feat: 添加标签颜色变体和验证功能,增强工具配置管理

This commit is contained in:
catlog22
2026-01-08 19:11:27 +08:00
parent d0523684e5
commit 3124125b4c
3 changed files with 75 additions and 5 deletions

View File

@@ -284,6 +284,37 @@
border-radius: 0.25rem;
}
/* Tag color variants */
.tag-item.tag-分析, .tool-tag.tag-分析 {
background: hsl(210 100% 50% / 0.15);
color: hsl(210 100% 45%);
}
.tag-item.tag-编码, .tool-tag.tag-编码 {
background: hsl(142 76% 36% / 0.15);
color: hsl(142 76% 36%);
}
.tag-item.tag-Debug, .tool-tag.tag-Debug {
background: hsl(0 84% 60% / 0.15);
color: hsl(0 84% 50%);
}
.tag-item.tag-重构, .tool-tag.tag-重构 {
background: hsl(280 70% 50% / 0.15);
color: hsl(280 70% 45%);
}
.tag-item.tag-测试, .tool-tag.tag-测试 {
background: hsl(45 93% 47% / 0.15);
color: hsl(45 93% 35%);
}
.tag-item.tag-文档, .tool-tag.tag-文档 {
background: hsl(180 70% 40% / 0.15);
color: hsl(180 70% 35%);
}
.tag-remove {
display: flex;
align-items: center;
@@ -334,6 +365,15 @@
border-color: hsl(var(--primary) / 0.3);
}
.predefined-tag-btn.selected,
.predefined-tag-btn:disabled {
background: hsl(var(--primary) / 0.1);
color: hsl(var(--muted-foreground));
border-color: hsl(var(--primary) / 0.2);
opacity: 0.6;
cursor: not-allowed;
}
.predefined-tag-btn i {
opacity: 0.7;
}

View File

@@ -335,7 +335,7 @@ function buildToolConfigModalContent(tool, config, models, status) {
'<h4>Tags <span class="text-muted">(optional labels)</span></h4>' +
'<div class="tags-unified-input" id="tagsUnifiedInput">' +
(config.tags || []).map(function(tag) {
return '<span class="tag-item">' + escapeHtml(tag) + '<button type="button" class="tag-remove" data-tag="' + escapeHtml(tag) + '">&times;</button></span>';
return '<span class="tag-item tag-' + escapeHtml(tag) + '">' + escapeHtml(tag) + '<button type="button" class="tag-remove" data-tag="' + escapeHtml(tag) + '">&times;</button></span>';
}).join('') +
'<input type="text" id="tagInput" class="tag-inline-input" placeholder="输入标签按 Enter 添加" />' +
'</div>' +
@@ -375,7 +375,7 @@ function initToolConfigModalEvents(tool, currentConfig, models) {
// Insert tags before the input
currentTags.forEach(function(tag) {
var tagEl = document.createElement('span');
tagEl.className = 'tag-item';
tagEl.className = 'tag-item tag-' + escapeHtml(tag);
tagEl.innerHTML = escapeHtml(tag) + '<button type="button" class="tag-remove" data-tag="' + escapeHtml(tag) + '">&times;</button>';
container.insertBefore(tagEl, input);
});
@@ -389,6 +389,18 @@ function initToolConfigModalEvents(tool, currentConfig, models) {
renderTags();
};
});
// Update predefined tag buttons state
document.querySelectorAll('.predefined-tag-btn').forEach(function(btn) {
var tag = btn.getAttribute('data-tag');
if (currentTags.indexOf(tag) !== -1) {
btn.classList.add('selected');
btn.disabled = true;
} else {
btn.classList.remove('selected');
btn.disabled = false;
}
});
}
// Click on unified input container focuses the input
@@ -665,10 +677,10 @@ function renderToolsSection() {
var toolConfig = cliToolConfig && cliToolConfig.tools ? cliToolConfig.tools[tool] : null;
var tags = toolConfig && toolConfig.tags ? toolConfig.tags : [];
// Build tags HTML
// Build tags HTML with color classes
var tagsHtml = tags.length > 0
? '<div class="tool-tags">' + tags.map(function(tag) {
return '<span class="tool-tag">' + escapeHtml(tag) + '</span>';
return '<span class="tool-tag tag-' + escapeHtml(tag) + '">' + escapeHtml(tag) + '</span>';
}).join('') + '</div>'
: '';

View File

@@ -185,6 +185,24 @@ export function getToolConfig(baseDir: string, tool: string): CliToolConfig {
return config.tools[tool] || DEFAULT_CONFIG.tools[tool];
}
/**
* Validate and sanitize tags array
* @param tags - Raw tags array from user input
* @returns Sanitized tags array
*/
function validateTags(tags: string[] | undefined): string[] | undefined {
if (!tags || !Array.isArray(tags)) return undefined;
const MAX_TAGS = 10;
const MAX_TAG_LENGTH = 30;
return tags
.filter(tag => typeof tag === 'string')
.map(tag => tag.trim())
.filter(tag => tag.length > 0 && tag.length <= MAX_TAG_LENGTH)
.slice(0, MAX_TAGS);
}
/**
* Update configuration for a specific tool
* Returns the updated tool config
@@ -206,7 +224,7 @@ export function updateToolConfig(
enabled: updates.enabled !== undefined ? updates.enabled : currentToolConfig.enabled,
primaryModel: updates.primaryModel || currentToolConfig.primaryModel,
secondaryModel: updates.secondaryModel || currentToolConfig.secondaryModel,
tags: updates.tags !== undefined ? updates.tags : currentToolConfig.tags
tags: updates.tags !== undefined ? validateTags(updates.tags) : currentToolConfig.tags
};
// Save updated config