feat(command): 优化指令冲突显示与提示

- 【功能】新增指令冲突警告提示,当检测到冲突时显示详细信息及解决方案。
- 【优化】调整指令列表排序逻辑,将冲突指令优先显示并分组。
- 【样式】为冲突指令行添加专属高亮样式,提升视觉识别度。
- 【国际化】更新英文和中文多语言文件,增加指令冲突警告相关的翻译文本。
This commit is contained in:
Ocetars
2025-12-03 15:04:30 +08:00
parent 8144b61ae0
commit 7aa44ba3d8
3 changed files with 77 additions and 1 deletions
@@ -5,6 +5,11 @@
"disabled": "Disabled",
"conflicts": "Conflicts"
},
"conflictAlert": {
"title": "Command Conflicts Detected",
"description": "There are {count} conflicting commands. Conflicting commands will trigger multiple plugins simultaneously, which may cause unexpected behavior.",
"hint": "Click the \"Rename\" button to rename conflicting commands and resolve conflicts."
},
"table": {
"headers": {
"command": "Command",
@@ -5,6 +5,11 @@
"disabled": "已禁用",
"conflicts": "有冲突"
},
"conflictAlert": {
"title": "检测到指令冲突",
"description": "当前有 {count} 对指令存在冲突,冲突的指令会同时触发多个插件响应,可能导致意外行为。",
"hint": "请点击「重命名」按钮修改冲突指令的名称以解决冲突。"
},
"table": {
"headers": {
"command": "指令",
+67 -1
View File
@@ -111,7 +111,28 @@ const filteredCommands = computed(() => {
}
}
return result;
// Sort: conflict commands first, grouped by effective_command
const conflictCmds: CommandItem[] = [];
const normalCmds: CommandItem[] = [];
const conflictGroupMap: Map<string, CommandItem[]> = new Map();
for (const cmd of result) {
if (cmd.has_conflict) {
const key = cmd.effective_command || '';
if (!conflictGroupMap.has(key)) {
conflictGroupMap.set(key, []);
}
conflictGroupMap.get(key)!.push(cmd);
} else {
normalCmds.push(cmd);
}
}
for (const [_, group] of conflictGroupMap) {
conflictCmds.push(...group);
}
return [...conflictCmds, ...normalCmds];
});
// Toast helper
@@ -226,6 +247,14 @@ const getStatusInfo = (cmd: CommandItem) => {
return { text: tm('status.disabled'), color: 'error', variant: 'outlined' as const };
};
// Get row props for conflict highlighting
const getRowProps = ({ item }: { item: CommandItem }) => {
if (item.has_conflict) {
return { class: 'conflict-row' };
}
return {};
};
onMounted(async () => {
await fetchCommands();
});
@@ -323,6 +352,30 @@ onMounted(async () => {
</v-col>
</v-row>
<!-- Conflict Warning Alert -->
<v-alert
v-if="summary.conflicts > 0"
type="warning"
variant="flat"
class="mb-4"
prominent
border="start"
>
<template v-slot:prepend>
<v-icon size="28">mdi-alert-circle</v-icon>
</template>
<v-alert-title class="text-subtitle-1 font-weight-bold">
{{ tm('conflictAlert.title') }}
</v-alert-title>
<div class="text-body-2 mt-1">
{{ tm('conflictAlert.description', { count: summary.conflicts }) }}
</div>
<div class="text-body-2 mt-2">
<v-icon size="16" class="mr-1">mdi-lightbulb-outline</v-icon>
{{ tm('conflictAlert.hint') }}
</div>
</v-alert>
<!-- Commands Table -->
<v-card class="rounded-lg overflow-hidden elevation-1">
<v-data-table
@@ -331,6 +384,7 @@ onMounted(async () => {
:loading="loading"
item-key="handler_full_name"
hover
:row-props="getRowProps"
>
<template v-slot:loader>
<v-row class="py-8 d-flex align-center justify-center">
@@ -526,3 +580,15 @@ code {
font-size: 0.9em;
}
</style>
<style>
/* Conflict row highlighting */
.v-data-table .conflict-row {
background: linear-gradient(90deg, rgba(var(--v-theme-warning), 0.15) 0%, rgba(var(--v-theme-warning), 0.05) 100%) !important;
border-left: 3px solid rgb(var(--v-theme-warning)) !important;
}
.v-data-table .conflict-row:hover {
background: linear-gradient(90deg, rgba(var(--v-theme-warning), 0.25) 0%, rgba(var(--v-theme-warning), 0.1) 100%) !important;
}
</style>