This commit is contained in:
+3
-7
@@ -291,13 +291,9 @@
|
||||
<label class="checkbox-label"><input type="checkbox" id="config-exists" checked> 该配置项当前存在/生效</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>说明 <span class="required">*</span></label>
|
||||
<textarea id="config-description" rows="2" placeholder="配置项用途说明"></textarea>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>用途 <span class="hint">(规划模式)</span></label>
|
||||
<textarea id="config-purpose" rows="2" placeholder="详细用途描述"></textarea>
|
||||
<div class="form-group">
|
||||
<label>说明 <span class="required">*</span></label>
|
||||
<textarea id="config-description" rows="2" placeholder="配置项用途说明"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
|
||||
+9
-13
@@ -377,8 +377,7 @@ function openConfigModal(config, readonly) {
|
||||
: "配置值";
|
||||
document.getElementById("config-type").value = config ? config.type : "string";
|
||||
document.getElementById("config-value-range").value = config ? config.valueRange || "" : "";
|
||||
document.getElementById("config-description").value = config ? config.description : "";
|
||||
document.getElementById("config-purpose").value = config ? config.purpose || "" : "";
|
||||
document.getElementById("config-description").value = config ? config.description : "";
|
||||
document.getElementById("config-required").checked = config ? config.required === true : false;
|
||||
document.getElementById("config-exists").checked = config ? config.exists !== false : true;
|
||||
document.getElementById("config-range-preset").value = "";
|
||||
@@ -400,8 +399,8 @@ function updateRangePresetVisibility() {
|
||||
|
||||
/**
|
||||
* 根据模式和是否只读查看,设置配置模态框各字段的可编辑性
|
||||
* 规划模式:结构字段(类型/说明/用途/范围/键名/维度)可改,值不可改
|
||||
* 编辑模式:值可改,已有项的结构字段锁定
|
||||
* 规划模式:结构字段(类型/说明/范围/键名/维度)可改,值不可改
|
||||
* 编辑模式:值、说明可改,已有项的其他结构字段锁定
|
||||
* 只读查看:全部禁用
|
||||
* @param {boolean} readonly - 是否只读查看
|
||||
* @returns {void}
|
||||
@@ -409,8 +408,8 @@ function updateRangePresetVisibility() {
|
||||
function applyFieldPermissions(readonly) {
|
||||
const structFields = [
|
||||
"config-key", "config-type", "config-value-range", "config-required",
|
||||
"config-default-value",
|
||||
"config-description", "config-purpose",
|
||||
"config-default-value",
|
||||
"config-description",
|
||||
"config-idc", "config-environment", "config-group",
|
||||
];
|
||||
const valueField = "config-value";
|
||||
@@ -444,10 +443,8 @@ function applyFieldPermissions(readonly) {
|
||||
const isNew = !state.editingConfigId;
|
||||
document.getElementById("config-type").disabled = !isNew;
|
||||
document.getElementById("config-value-range").disabled = !isNew;
|
||||
document.getElementById("config-required").disabled = !isNew;
|
||||
document.getElementById("config-default-value").disabled = !isNew;
|
||||
document.getElementById("config-description").disabled = !isNew;
|
||||
document.getElementById("config-purpose").disabled = !isNew;
|
||||
document.getElementById("config-required").disabled = !isNew;
|
||||
document.getElementById("config-default-value").disabled = !isNew;
|
||||
document.getElementById("config-key").disabled = false;
|
||||
document.getElementById("config-idc").disabled = false;
|
||||
document.getElementById("config-environment").disabled = false;
|
||||
@@ -474,9 +471,8 @@ function collectConfigForm() {
|
||||
defaultValue: document.getElementById("config-default-value").value,
|
||||
required: document.getElementById("config-required").checked,
|
||||
exists: document.getElementById("config-exists").checked,
|
||||
description: document.getElementById("config-description").value.trim(),
|
||||
purpose: document.getElementById("config-purpose").value.trim(),
|
||||
};
|
||||
description: document.getElementById("config-description").value.trim(),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+1
-1
@@ -401,7 +401,7 @@ function createMcpServer() {
|
||||
"update_config",
|
||||
{
|
||||
description:
|
||||
"修改配置项(只读模式下禁止)。plan 模式可修改 type/description/purpose/valueRange/required/key/维度;edit 模式可修改 value/exists/key/维度。可仅传需修改的字段。",
|
||||
"修改配置项(只读模式下禁止)。plan 模式可修改 type/description/purpose/valueRange/required/key/维度;edit 模式可修改 value/exists/description/key/维度。可仅传需修改的字段。",
|
||||
inputSchema: {
|
||||
projectId: z.string().describe("项目 ID"),
|
||||
configId: z.string().describe("配置项 ID"),
|
||||
|
||||
@@ -238,8 +238,8 @@ function validateStructure(config, project) {
|
||||
|
||||
/**
|
||||
* 更新配置项
|
||||
* 规划模式:可修改 type、description、purpose、valueRange、required
|
||||
* 编辑模式:可修改 value、exists
|
||||
* 规划模式:可修改 type、description、purpose、valueRange、required
|
||||
* 编辑模式:可修改 value、exists、description
|
||||
* 只读模式:不可修改
|
||||
* @param {string} projectId - 项目 ID
|
||||
* @param {string} configId - 配置项 ID
|
||||
@@ -278,12 +278,13 @@ async function updateConfig(projectId, configId, data, mode) {
|
||||
if (data.environment !== undefined) config.environment = data.environment;
|
||||
if (data.group !== undefined) config.group = data.group;
|
||||
validateStructure(config, project);
|
||||
} else if (mode === "edit") {
|
||||
// 编辑模式:修改值与存在性
|
||||
if (data.value !== undefined) config.value = data.value;
|
||||
if (data.exists !== undefined) config.exists = data.exists !== false;
|
||||
validateEditValue(config);
|
||||
// 编辑模式下也可以修改 key 和维度(路径调整)
|
||||
} else if (mode === "edit") {
|
||||
// 编辑模式:修改值、存在性与说明
|
||||
if (data.value !== undefined) config.value = data.value;
|
||||
if (data.exists !== undefined) config.exists = data.exists !== false;
|
||||
validateEditValue(config);
|
||||
// 编辑模式下也可以修改 key 和维度(路径调整)
|
||||
if (data.description !== undefined) config.description = String(data.description ?? "").trim();
|
||||
if (data.key !== undefined) config.key = normalizeKey(data.key);
|
||||
if (data.idc !== undefined) config.idc = data.idc;
|
||||
if (data.environment !== undefined) config.environment = data.environment;
|
||||
|
||||
@@ -128,6 +128,38 @@ test("readonly 模式下拒绝项目/配置写操作,切换回 edit 后恢复"
|
||||
await callTool("set_mode", { mode: "edit" });
|
||||
});
|
||||
|
||||
test("edit 模式下可以修改配置说明", async () => {
|
||||
await callTool("set_mode", { mode: "edit" });
|
||||
|
||||
const { text: createText } = await callTool("create_project", { name: "MCP-Unittest-Desc" });
|
||||
const project = JSON.parse(createText.match(/\{[\s\S]*\}/)[0]);
|
||||
|
||||
const cfg = await callTool("create_config", {
|
||||
projectId: project.id,
|
||||
key: "db/host",
|
||||
description: "原始说明",
|
||||
value: "localhost",
|
||||
});
|
||||
const cfgObj = JSON.parse(cfg.text.match(/\{[\s\S]*\}/)[0]);
|
||||
|
||||
const updated = await callTool("update_config", {
|
||||
projectId: project.id,
|
||||
configId: cfgObj.id,
|
||||
description: "新的说明",
|
||||
});
|
||||
assert.ok(!updated.isError, "edit 模式下应允许修改说明");
|
||||
const updatedObj = JSON.parse(updated.text.match(/\{[\s\S]*\}/)[0]);
|
||||
assert.strictEqual(updatedObj.description, "新的说明");
|
||||
assert.strictEqual(updatedObj.value, "localhost", "仅改说明,值不应变化");
|
||||
|
||||
// 清理测试项目
|
||||
const delProject = await callTool("delete_project", { projectId: project.id });
|
||||
const confirmProject = await callTool("confirm_delete_project", {
|
||||
confirmation_token: delProject.structuredContent.confirmation_token,
|
||||
});
|
||||
assert.strictEqual(confirmProject.structuredContent.status, "deleted");
|
||||
});
|
||||
|
||||
test("配置删除同样为两步式确认", async () => {
|
||||
const { text: createText } = await callTool("create_project", { name: "MCP-Unittest-Cfg" });
|
||||
const project = JSON.parse(createText.match(/\{[\s\S]*\}/)[0]);
|
||||
|
||||
Reference in New Issue
Block a user