docs/archives/128-context-ui-and-variable-system-refactor/implementation-codemirror.md
文档版本: v1.0 创建日期: 2025-10-23 完成日期: 2025-10-23 实施目标: 将 VariableAwareInput 从原生 textarea 迁移到 CodeMirror 6,实现变量高亮、自动完成和缺失变量快捷添加 优先级: 🔴 P0 高优先级 状态: ✅ 已完成并通过构建测试
{{ 触发变量补全VariableAwareInput.vue (主组件)
├── useVariableDetection.ts (变量检测逻辑)
├── codemirror-extensions.ts (CodeMirror 扩展)
├── selection-safety helpers (组件内选择校验)
├── ContextUserWorkspace.vue (事件集成)
└── InputPanel.vue (事件传递)
useVariableDetection.ts - 变量检测引擎功能职责:
{{variable}} 占位符核心接口:
export interface DetectedVariable {
name: string
source: 'global' | 'temporary' | 'predefined' | 'missing'
value: string
from: number
to: number
}
codemirror-extensions.ts - CodeMirror 扩展集合功能职责:
variableHighlighter() - 变量高亮渲染variableAutocompletion() - 自动完成功能missingVariableTooltip() - 缺失变量悬浮提示createThemeExtension() - 主题适配VariableAwareInput.vue - 主组件重构功能职责:
新增职责:
validateSelection():阻止跨越 {{ }} 边界的非法选择countOccurrencesOutsideVariables():统计出现次数时自动忽略占位符内部的命中replaceAllOccurrencesOutsideVariables():批量替换时仅处理纯文本命中,保护已存在的变量占位符这些辅助函数确保 CodeMirror 版本延续原生 textarea 实现的“变量保护”策略。
.cm-variable-global { background: #e6f7ff; } /* 全局变量 - 蓝色 */
.cm-variable-temporary { background: #f6ffed; } /* 临时变量 - 绿色 */
.cm-variable-predefined { background: #f9f0ff; } /* 预定义变量 - 紫色 */
.cm-variable-missing {
background: #fff1f0; /* 缺失变量 - 红色 */
text-decoration: underline wavy red;
}
{{ 自动触发补全弹窗{
label: variableName, // 变量名
type: 'variable',
detail: sourceLabel, // 来源标签
info: valuePreview, // 值预览 (截断至50字符)
apply: `{{${variableName}}}`, // 应用文本
boost: priorityScore // 优先级分数
}
add-missing-variable 事件 (VariableAwareInput → InputPanel → ContextUserWorkspace)现象:
[vite]: Rollup failed to resolve import "codemirror" from "VariableAwareInput.vue"
解决方案:
# 在 packages/ui 目录下安装
cd packages/ui
pnpm add codemirror @codemirror/state @codemirror/view @codemirror/language @codemirror/autocomplete @codemirror/tooltip
现象:
"DecorationSet" is not exported by "@codemirror/view/dist/index.js"
"CompletionResult" is not exported by "@codemirror/autocomplete/dist/index.js"
解决方案:
// 错误的导入方式
import { DecorationSet } from '@codemirror/view'
import { CompletionResult } from '@codemirror/autocomplete'
// 正确的导入方式
import type { DecorationSet } from '@codemirror/view'
import type { CompletionResult } from '@codemirror/autocomplete'
现象:
[Vue warn]: Extraneous non-emits event listeners (addMissingVariable) were passed to component
解决方案: 在 InputPanel.vue 中正确声明事件
const emit = defineEmits<{
"add-missing-variable": [varName: string];
}>();
// 添加事件处理函数
const handleAddMissingVariable = (varName: string) => {
emit("add-missing-variable", varName);
};
// ContextUserWorkspace.vue
const handleAddMissingVariable = (name: string) => {
temporaryVariables.value[name] = "";
emit("variable-change", name, "");
};
解决方案: 使用 RangeSetBuilder 高效管理装饰器
buildDecorations(view: EditorView): DecorationSet {
const builder = new RangeSetBuilder<Decoration>()
const variables = getVariables()
for (const variable of variables) {
const decoration = Decoration.mark({
class: `cm-variable-${variable.source}`,
attributes: {
'data-variable-name': variable.name,
'data-variable-source': variable.source
}
})
builder.add(variable.from, variable.to, decoration)
}
return builder.finish()
}
现象: 早期实现直接对全文正则替换,可能把 {{customer_name}} 中选中的 customer 替换为新变量名,导致占位符损坏。
解决方案: 在组件内新增一组助手函数,保证所有统计和替换都忽略 {{ }} 内部的文本。
const validateSelection = (...) => { /* 检查是否跨越变量边界 */ }
const countOccurrencesOutsideVariables = (...) => { /* 忽略占位符内部 */ }
const replaceAllOccurrencesOutsideVariables = (...) => { /* 仅替换安全命中 */ }
if (data.replaceAll) {
newValue = replaceAllOccurrencesOutsideVariables(
text,
currentSelection.value.text,
placeholder
)
}
packages/ui/src/components/variable-extraction/useVariableDetection.ts — 变量解析与分类核心。packages/ui/src/components/variable-extraction/codemirror-extensions.ts — CodeMirror 高亮、补全、提示扩展集合。packages/ui/src/components/variable-extraction/VariableAwareInput.vue — 替换为 CodeMirror 实现,并新增 Selection Safety Helpers。packages/ui/src/components/InputPanel.vue — 转发 add-missing-variable 事件。packages/ui/src/components/context-mode/ContextUserWorkspace.vue — 同步临时变量并处理新增/删除/清空事件。packages/ui/src/components/TestAreaPanel.vue — 发出 temporary-variable-remove/temporary-variables-clear 事件反馈。packages/ui/src/i18n/locales/*.ts — 新增 variableDetection 相关文案。package.json、packages/ui/package.json — 增补 CodeMirror 6 所需依赖。{
"codemirror": "^6.0.2",
"@codemirror/state": "^6.5.2",
"@codemirror/view": "^6.38.6",
"@codemirror/language": "^6.11.3",
"@codemirror/autocomplete": "^6.19.0",
"@codemirror/tooltip": "^0.19.16",
"@codemirror/commands": "^6.9.0"
}
✅ 构建验证
✅ 代码质量
✅ 架构设计
🔄 变量高亮功能
🔄 自动完成功能
{{ 触发补全弹窗{{variableName}}🔄 缺失变量快捷添加
pnpm dev:fresh{{)当前实现遵循以下最佳实践:
文档生成时间: 2025-10-23 17:52 最后更新: 2025-10-23 17:52 文档状态: ✅ 已完成