mirror of
https://github.com/xinnan-tech/xiaozhi-esp32-server.git
synced 2026-07-28 01:53:53 +08:00
fix: 测试页面MCP工具参数编辑样式调整
This commit is contained in:
@@ -1028,35 +1028,174 @@ body {
|
|||||||
margin-bottom: 12px;
|
margin-bottom: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.property-item {
|
.properties-container #addMcpPropertyBtn {
|
||||||
|
display: block;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.properties-container #addMcpPropertyBtn:hover {
|
||||||
|
background: #4752c4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mcp-checkbox-label {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 8px;
|
|
||||||
margin-bottom: 8px;
|
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
margin-top: 8px;
|
||||||
|
color: #b9bbbe;
|
||||||
|
font-size: 13px;
|
||||||
|
cursor: pointer;
|
||||||
|
justify-content: flex-start;
|
||||||
}
|
}
|
||||||
|
|
||||||
.property-item input {
|
.mcp-checkbox-label input[type="checkbox"] {
|
||||||
flex: 1;
|
width: 16px;
|
||||||
padding: 6px 8px;
|
height: 16px;
|
||||||
border: 1px solid #40444b;
|
cursor: pointer;
|
||||||
border-radius: 4px;
|
}
|
||||||
background: #40444b;
|
|
||||||
|
.mcp-property-name {
|
||||||
color: white;
|
color: white;
|
||||||
font-size: 12px;
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
.remove-property {
|
.mcp-property-header {
|
||||||
background: #ed4245;
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mcp-properties-list {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 12px;
|
||||||
|
min-height: 60px;
|
||||||
|
padding: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-group-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-group-header label {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-group-header .properties-btn-primary {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mcp-empty-state {
|
||||||
|
text-align: center;
|
||||||
|
padding: 20px;
|
||||||
|
color: #999;
|
||||||
|
font-size: 14px;
|
||||||
|
width: 100%;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.properties-btn-primary {
|
||||||
|
background: #2196f3;
|
||||||
color: white;
|
color: white;
|
||||||
border: none;
|
border: none;
|
||||||
padding: 4px 8px;
|
padding: 6px 12px;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
|
font-weight: 500;
|
||||||
|
transition: background-color 0.2s;
|
||||||
|
display: block;
|
||||||
|
margin: 0 auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.remove-property:hover {
|
.properties-btn-primary:hover {
|
||||||
background: #c03537;
|
background: #2196f3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mcp-property-card {
|
||||||
|
background: #36393f;
|
||||||
|
border: 1px solid #40444b;
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 12px;
|
||||||
|
width: 100%;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mcp-property-card:hover {
|
||||||
|
background: #40444b;
|
||||||
|
border-color: #5865f2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mcp-property-card:active {
|
||||||
|
transform: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mcp-property-row-label {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
margin-bottom: 6px;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mcp-property-label {
|
||||||
|
color: #b9bbbe;
|
||||||
|
font-size: 13px;
|
||||||
|
width: 60px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mcp-property-value {
|
||||||
|
color: white;
|
||||||
|
font-size: 13px;
|
||||||
|
flex: 1;
|
||||||
|
word-break: break-all;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mcp-property-required-badge {
|
||||||
|
color: #f44336;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mcp-property-row-action {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
margin-top: 6px;
|
||||||
|
padding-top: 6px;
|
||||||
|
border-top: 1px solid #40444b;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mcp-property-delete-btn {
|
||||||
|
background: #f44336;
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
padding: 4px 12px;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 11px;
|
||||||
|
transition: background-color 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mcp-property-delete-btn:hover {
|
||||||
|
background: #d32f2f;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mcp-property-card-optional {
|
||||||
|
background: #4f545c;
|
||||||
|
color: #b9bbbe;
|
||||||
|
font-size: 11px;
|
||||||
|
padding: 2px 8px;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.property-modal {
|
||||||
|
max-width: 450px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ==================== 音频可视化器样式 ==================== */
|
/* ==================== 音频可视化器样式 ==================== */
|
||||||
|
|||||||
@@ -105,94 +105,167 @@ function renderMcpTools() {
|
|||||||
*/
|
*/
|
||||||
function renderMcpProperties() {
|
function renderMcpProperties() {
|
||||||
const container = document.getElementById('mcpPropertiesContainer');
|
const container = document.getElementById('mcpPropertiesContainer');
|
||||||
|
const emptyState = document.getElementById('mcpEmptyState');
|
||||||
if (!container) {
|
if (!container) {
|
||||||
return; // Container not found, skip rendering
|
return; // Container not found, skip rendering
|
||||||
}
|
}
|
||||||
if (mcpProperties.length === 0) {
|
if (mcpProperties.length === 0) {
|
||||||
container.innerHTML = '<div style="text-align: center; padding: 20px; color: #999; font-size: 14px;">暂无参数,点击下方按钮添加参数</div>';
|
if (emptyState) {
|
||||||
|
emptyState.style.display = 'block';
|
||||||
|
}
|
||||||
|
container.innerHTML = '';
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (emptyState) {
|
||||||
|
emptyState.style.display = 'none';
|
||||||
|
}
|
||||||
container.innerHTML = mcpProperties.map((prop, index) => `
|
container.innerHTML = mcpProperties.map((prop, index) => `
|
||||||
<div class="mcp-property-item">
|
<div class="mcp-property-card" onclick="window.mcpModule.editMcpProperty(${index})">
|
||||||
<div class="mcp-property-header">
|
<div class="mcp-property-row-label">
|
||||||
<span class="mcp-property-name">${prop.name}</span>
|
<span class="mcp-property-label">参数名称</span>
|
||||||
<button type="button" onclick="window.mcpModule.deleteMcpProperty(${index})"
|
<span class="mcp-property-value">${prop.name}${prop.required ? ' <span class="mcp-property-required-badge">[必填]</span>' : ''}</span>
|
||||||
style="padding: 3px 8px; border: none; border-radius: 3px; background-color: #f44336; color: white; cursor: pointer; font-size: 11px;">
|
|
||||||
删除
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="mcp-property-row">
|
<div class="mcp-property-row-label">
|
||||||
<div>
|
<span class="mcp-property-label">数据类型</span>
|
||||||
<label class="mcp-small-label">参数名称 *</label>
|
<span class="mcp-property-value">${getTypeLabel(prop.type)}</span>
|
||||||
<input type="text" class="mcp-small-input" value="${prop.name}"
|
|
||||||
onchange="window.mcpModule.updateMcpProperty(${index}, 'name', this.value)" required>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label class="mcp-small-label">数据类型 *</label>
|
|
||||||
<select class="mcp-small-input" onchange="window.mcpModule.updateMcpProperty(${index}, 'type', this.value)">
|
|
||||||
<option value="string" ${prop.type === 'string' ? 'selected' : ''}>字符串</option>
|
|
||||||
<option value="integer" ${prop.type === 'integer' ? 'selected' : ''}>整数</option>
|
|
||||||
<option value="number" ${prop.type === 'number' ? 'selected' : ''}>数字</option>
|
|
||||||
<option value="boolean" ${prop.type === 'boolean' ? 'selected' : ''}>布尔值</option>
|
|
||||||
<option value="array" ${prop.type === 'array' ? 'selected' : ''}>数组</option>
|
|
||||||
<option value="object" ${prop.type === 'object' ? 'selected' : ''}>对象</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
${(prop.type === 'integer' || prop.type === 'number') ? `
|
<div class="mcp-property-row-label">
|
||||||
<div class="mcp-property-row">
|
<span class="mcp-property-label">描述</span>
|
||||||
<div>
|
<span class="mcp-property-value">${prop.description || '-'}</span>
|
||||||
<label class="mcp-small-label">最小值</label>
|
|
||||||
<input type="number" class="mcp-small-input" value="${prop.minimum !== undefined ? prop.minimum : ''}"
|
|
||||||
placeholder="可选" onchange="window.mcpModule.updateMcpProperty(${index}, 'minimum', this.value ? parseFloat(this.value) : undefined)">
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label class="mcp-small-label">最大值</label>
|
|
||||||
<input type="number" class="mcp-small-input" value="${prop.maximum !== undefined ? prop.maximum : ''}"
|
|
||||||
placeholder="可选" onchange="window.mcpModule.updateMcpProperty(${index}, 'maximum', this.value ? parseFloat(this.value) : undefined)">
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
` : ''}
|
<div class="mcp-property-row-action">
|
||||||
<div class="mcp-property-row-full">
|
<button class="mcp-property-delete-btn" onclick="event.stopPropagation(); window.mcpModule.deleteMcpProperty(${index})">删除</button>
|
||||||
<label class="mcp-small-label">参数描述</label>
|
|
||||||
<input type="text" class="mcp-small-input" value="${prop.description || ''}"
|
|
||||||
placeholder="可选" onchange="window.mcpModule.updateMcpProperty(${index}, 'description', this.value)">
|
|
||||||
</div>
|
</div>
|
||||||
<label class="mcp-checkbox-label">
|
|
||||||
<input type="checkbox" ${prop.required ? 'checked' : ''}
|
|
||||||
onchange="window.mcpModule.updateMcpProperty(${index}, 'required', this.checked)">
|
|
||||||
必填参数
|
|
||||||
</label>
|
|
||||||
</div>
|
</div>
|
||||||
`).join('');
|
`).join('');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 添加参数
|
* 获取数据类型标签
|
||||||
*/
|
*/
|
||||||
function addMcpProperty() {
|
function getTypeLabel(type) {
|
||||||
mcpProperties.push({ name: `param_${mcpProperties.length + 1}`, type: 'string', required: false, description: '' });
|
const typeMap = {
|
||||||
renderMcpProperties();
|
'string': '字符串',
|
||||||
|
'integer': '整数',
|
||||||
|
'number': '数字',
|
||||||
|
'boolean': '布尔值',
|
||||||
|
'array': '数组',
|
||||||
|
'object': '对象'
|
||||||
|
};
|
||||||
|
return typeMap[type] || type;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 更新参数
|
* 添加参数 - 打开参数编辑模态框
|
||||||
*/
|
*/
|
||||||
function updateMcpProperty(index, field, value) {
|
function addMcpProperty() {
|
||||||
if (field === 'name') {
|
openPropertyModal();
|
||||||
const isDuplicate = mcpProperties.some((p, i) => i !== index && p.name === value);
|
}
|
||||||
if (isDuplicate) {
|
|
||||||
alert('参数名称已存在,请使用不同的名称');
|
/**
|
||||||
renderMcpProperties();
|
* 编辑参数 - 打开参数编辑模态框
|
||||||
return;
|
*/
|
||||||
|
function editMcpProperty(index) {
|
||||||
|
openPropertyModal(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 打开参数编辑模态框
|
||||||
|
*/
|
||||||
|
function openPropertyModal(index = null) {
|
||||||
|
const form = document.getElementById('mcpPropertyForm');
|
||||||
|
const title = document.getElementById('mcpPropertyModalTitle');
|
||||||
|
document.getElementById('mcpPropertyIndex').value = index !== null ? index : -1;
|
||||||
|
|
||||||
|
if (index !== null) {
|
||||||
|
const prop = mcpProperties[index];
|
||||||
|
title.textContent = '编辑参数';
|
||||||
|
document.getElementById('mcpPropertyName').value = prop.name;
|
||||||
|
document.getElementById('mcpPropertyType').value = prop.type || 'string';
|
||||||
|
document.getElementById('mcpPropertyMinimum').value = prop.minimum !== undefined ? prop.minimum : '';
|
||||||
|
document.getElementById('mcpPropertyMaximum').value = prop.maximum !== undefined ? prop.maximum : '';
|
||||||
|
document.getElementById('mcpPropertyDescription').value = prop.description || '';
|
||||||
|
document.getElementById('mcpPropertyRequired').checked = prop.required || false;
|
||||||
|
} else {
|
||||||
|
title.textContent = '添加参数';
|
||||||
|
form.reset();
|
||||||
|
document.getElementById('mcpPropertyName').value = `param_${mcpProperties.length + 1}`;
|
||||||
|
document.getElementById('mcpPropertyType').value = 'string';
|
||||||
|
document.getElementById('mcpPropertyMinimum').value = '';
|
||||||
|
document.getElementById('mcpPropertyMaximum').value = '';
|
||||||
|
document.getElementById('mcpPropertyDescription').value = '';
|
||||||
|
document.getElementById('mcpPropertyRequired').checked = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
updatePropertyRangeVisibility();
|
||||||
|
document.getElementById('mcpPropertyModal').style.display = 'flex';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 关闭参数编辑模态框
|
||||||
|
*/
|
||||||
|
function closePropertyModal() {
|
||||||
|
document.getElementById('mcpPropertyModal').style.display = 'none';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新数值范围输入框的可见性
|
||||||
|
*/
|
||||||
|
function updatePropertyRangeVisibility() {
|
||||||
|
const type = document.getElementById('mcpPropertyType').value;
|
||||||
|
const rangeGroup = document.getElementById('mcpPropertyRangeGroup');
|
||||||
|
if (type === 'integer' || type === 'number') {
|
||||||
|
rangeGroup.style.display = 'block';
|
||||||
|
} else {
|
||||||
|
rangeGroup.style.display = 'none';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理参数表单提交
|
||||||
|
*/
|
||||||
|
function handlePropertySubmit(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
const index = parseInt(document.getElementById('mcpPropertyIndex').value);
|
||||||
|
const name = document.getElementById('mcpPropertyName').value.trim();
|
||||||
|
const type = document.getElementById('mcpPropertyType').value;
|
||||||
|
const minimum = document.getElementById('mcpPropertyMinimum').value;
|
||||||
|
const maximum = document.getElementById('mcpPropertyMaximum').value;
|
||||||
|
const description = document.getElementById('mcpPropertyDescription').value.trim();
|
||||||
|
const required = document.getElementById('mcpPropertyRequired').checked;
|
||||||
|
|
||||||
|
// 检查名称重复
|
||||||
|
const isDuplicate = mcpProperties.some((p, i) => i !== index && p.name === name);
|
||||||
|
if (isDuplicate) {
|
||||||
|
alert('参数名称已存在,请使用不同的名称');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const propData = {
|
||||||
|
name,
|
||||||
|
type,
|
||||||
|
description,
|
||||||
|
required
|
||||||
|
};
|
||||||
|
|
||||||
|
// 数值类型添加范围限制
|
||||||
|
if (type === 'integer' || type === 'number') {
|
||||||
|
if (minimum !== '') {
|
||||||
|
propData.minimum = parseFloat(minimum);
|
||||||
|
}
|
||||||
|
if (maximum !== '') {
|
||||||
|
propData.maximum = parseFloat(maximum);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mcpProperties[index][field] = value;
|
|
||||||
if (field === 'type' && value !== 'integer' && value !== 'number') {
|
if (index >= 0) {
|
||||||
delete mcpProperties[index].minimum;
|
mcpProperties[index] = propData;
|
||||||
delete mcpProperties[index].maximum;
|
} else {
|
||||||
renderMcpProperties();
|
mcpProperties.push(propData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
renderMcpProperties();
|
||||||
|
closePropertyModal();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -215,6 +288,14 @@ function setupMcpEventListeners() {
|
|||||||
const cancelBtn = document.getElementById('cancelMcpBtn');
|
const cancelBtn = document.getElementById('cancelMcpBtn');
|
||||||
const form = document.getElementById('mcpToolForm');
|
const form = document.getElementById('mcpToolForm');
|
||||||
const addPropertyBtn = document.getElementById('addMcpPropertyBtn');
|
const addPropertyBtn = document.getElementById('addMcpPropertyBtn');
|
||||||
|
|
||||||
|
// 参数编辑模态框相关元素
|
||||||
|
const propertyModal = document.getElementById('mcpPropertyModal');
|
||||||
|
const closePropertyBtn = document.getElementById('closeMcpPropertyModalBtn');
|
||||||
|
const cancelPropertyBtn = document.getElementById('cancelMcpPropertyBtn');
|
||||||
|
const propertyForm = document.getElementById('mcpPropertyForm');
|
||||||
|
const propertyTypeSelect = document.getElementById('mcpPropertyType');
|
||||||
|
|
||||||
// Return early if required elements don't exist (e.g., in test environment)
|
// Return early if required elements don't exist (e.g., in test environment)
|
||||||
if (!toggleBtn || !panel || !addBtn || !modal || !closeBtn || !cancelBtn || !form || !addPropertyBtn) {
|
if (!toggleBtn || !panel || !addBtn || !modal || !closeBtn || !cancelBtn || !form || !addPropertyBtn) {
|
||||||
return;
|
return;
|
||||||
@@ -234,6 +315,17 @@ function setupMcpEventListeners() {
|
|||||||
if (e.target === modal) closeMcpModal();
|
if (e.target === modal) closeMcpModal();
|
||||||
});
|
});
|
||||||
form.addEventListener('submit', handleMcpSubmit);
|
form.addEventListener('submit', handleMcpSubmit);
|
||||||
|
|
||||||
|
// 参数编辑模态框事件
|
||||||
|
if (propertyModal && closePropertyBtn && cancelPropertyBtn && propertyForm && propertyTypeSelect) {
|
||||||
|
closePropertyBtn.addEventListener('click', closePropertyModal);
|
||||||
|
cancelPropertyBtn.addEventListener('click', closePropertyModal);
|
||||||
|
propertyModal.addEventListener('click', (e) => {
|
||||||
|
if (e.target === propertyModal) closePropertyModal();
|
||||||
|
});
|
||||||
|
propertyForm.addEventListener('submit', handlePropertySubmit);
|
||||||
|
propertyTypeSelect.addEventListener('change', updatePropertyRangeVisibility);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -275,7 +367,7 @@ function openMcpModal(index = null) {
|
|||||||
mcpProperties = [];
|
mcpProperties = [];
|
||||||
}
|
}
|
||||||
renderMcpProperties();
|
renderMcpProperties();
|
||||||
document.getElementById('mcpToolModal').style.display = 'block';
|
document.getElementById('mcpToolModal').style.display = 'flex';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -447,4 +539,4 @@ export async function executeMcpTool(toolName, toolArgs) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 暴露全局方法供 HTML 内联事件调用
|
// 暴露全局方法供 HTML 内联事件调用
|
||||||
window.mcpModule = { updateMcpProperty, deleteMcpProperty, editMcpTool, deleteMcpTool };
|
window.mcpModule = { addMcpProperty, editMcpProperty, deleteMcpProperty, editMcpTool, deleteMcpTool };
|
||||||
|
|||||||
@@ -244,20 +244,23 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<label for="mcpToolDescription">工具描述 *</label>
|
<label for="mcpToolDescription">工具描述 *</label>
|
||||||
<textarea id="mcpToolDescription" placeholder="详细描述工具的功能和使用场景..." required></textarea>
|
<textarea id="mcpToolDescription" placeholder="详细描述工具的功能和使用场景..." required>
|
||||||
|
</textarea>
|
||||||
</div>
|
</div>
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<label>输入参数</label>
|
<div class="input-group-header">
|
||||||
<div class="properties-container">
|
<label>输入参数</label>
|
||||||
<div id="mcpPropertiesContainer">
|
<button type="button" class="properties-btn-primary" id="addMcpPropertyBtn">
|
||||||
<div style="text-align: center; padding: 20px; color: #999; font-size: 14px;">
|
|
||||||
暂无参数,点击下方按钮添加参数
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<button type="button" class="btn-secondary" id="addMcpPropertyBtn">
|
|
||||||
➕ 添加参数
|
➕ 添加参数
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="properties-container">
|
||||||
|
<div class="mcp-empty-state" id="mcpEmptyState">
|
||||||
|
暂无参数,点击上方按钮添加参数
|
||||||
|
</div>
|
||||||
|
<div class="mcp-properties-list" id="mcpPropertiesContainer">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<label for="mcpMockResponse">
|
<label for="mcpMockResponse">
|
||||||
@@ -275,6 +278,62 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- 参数编辑模态框 -->
|
||||||
|
<div id="mcpPropertyModal" class="modal">
|
||||||
|
<div class="modal-content property-modal">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h2 id="mcpPropertyModalTitle">编辑参数</h2>
|
||||||
|
<button class="close-btn" id="closeMcpPropertyModalBtn">×</button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<form id="mcpPropertyForm">
|
||||||
|
<input type="hidden" id="mcpPropertyIndex" value="-1">
|
||||||
|
<div class="input-group">
|
||||||
|
<label for="mcpPropertyName">参数名称 *</label>
|
||||||
|
<input type="text" id="mcpPropertyName" placeholder="例如: param_1" required>
|
||||||
|
</div>
|
||||||
|
<div class="input-group">
|
||||||
|
<label for="mcpPropertyType">数据类型 *</label>
|
||||||
|
<select id="mcpPropertyType" class="model-select" required>
|
||||||
|
<option value="string">字符串</option>
|
||||||
|
<option value="integer">整数</option>
|
||||||
|
<option value="number">数字</option>
|
||||||
|
<option value="boolean">布尔值</option>
|
||||||
|
<option value="array">数组</option>
|
||||||
|
<option value="object">对象</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="input-group" id="mcpPropertyRangeGroup" style="display: none;">
|
||||||
|
<div class="config-row">
|
||||||
|
<div class="config-item">
|
||||||
|
<label for="mcpPropertyMinimum">最小值</label>
|
||||||
|
<input type="number" id="mcpPropertyMinimum" placeholder="可选">
|
||||||
|
</div>
|
||||||
|
<div class="config-item">
|
||||||
|
<label for="mcpPropertyMaximum">最大值</label>
|
||||||
|
<input type="number" id="mcpPropertyMaximum" placeholder="可选">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="input-group">
|
||||||
|
<label for="mcpPropertyDescription">参数描述</label>
|
||||||
|
<input type="text" id="mcpPropertyDescription" placeholder="可选">
|
||||||
|
</div>
|
||||||
|
<div class="input-group">
|
||||||
|
<label class="mcp-checkbox-label">
|
||||||
|
<input type="checkbox" id="mcpPropertyRequired">
|
||||||
|
必填参数
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="modal-actions">
|
||||||
|
<button type="button" class="btn-secondary" id="cancelMcpPropertyBtn">取消</button>
|
||||||
|
<button type="submit" class="btn-primary">保存</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- 背景加载 -->
|
<!-- 背景加载 -->
|
||||||
<script src="js/ui/background-load.js?v=0127"></script>
|
<script src="js/ui/background-load.js?v=0127"></script>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user