# DimensionWeightPicker 重设计 实施计划 > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. **Goal:** 将 DimensionWeightPicker 从 checkbox+slider 改为 slider+数字输入框,动态 max 限制总和 ≤ 100% **Architecture:** 单 Vue 组件重写,Props/emit 接口不变,与父组件零耦合改动 **Tech Stack:** Vue 2 + Element UI + Options API **Design doc:** `docs/superpowers/specs/2026-07-02-dimension-weight-picker-redesign.md` --- ### Task 1: 重写 Template 部分 **Files:** - Modify: `cfc-web/src/components/DimensionWeightPicker.vue:1-30` - [ ] **Step 1: 替换 template 内容** 将原来的 `` + 每行 checkbox + slider 的结构,替换为纯 slider + 数字输入框: ```vue ``` - [ ] **Step 2: 确认结果** ```bash grep -n 'el-checkbox\|el-checkbox-group' cfc-web/src/components/DimensionWeightPicker.vue || echo "已无 checkbox" ``` --- ### Task 2: 重写 Script 逻辑 **Files:** - Modify: `cfc-web/src/components/DimensionWeightPicker.vue:32-121` - [ ] **Step 1: 设置数据属性 `currentValue`,去掉 `enabledDimensions`** 替换整个 `data()` — 每个维度加 `currentValue` 字段替代之前的 `weight`: ```js data() { return { dimensions: [ { code: 'body', name: '身·土', color: '#FF8C42', currentValue: 0 }, { code: 'mind', name: '智·金', color: '#6366F1', currentValue: 0 }, { code: 'action', name: '行·木', color: '#10B981', currentValue: 0 }, { code: 'wealth', name: '富·水', color: '#F59E0B', currentValue: 0 }, { code: 'heart', name: '心·火', color: '#FF6B9D', currentValue: 0 } ], presets: [ { label: '均衡', weights: { body: 20, mind: 20, action: 20, wealth: 20, heart: 20 } }, { label: '偏身', weights: { body: 40, mind: 15, action: 15, wealth: 15, heart: 15 } }, { label: '偏智', weights: { body: 15, mind: 40, action: 15, wealth: 15, heart: 15 } }, { label: '偏行', weights: { body: 15, mind: 15, action: 40, wealth: 15, heart: 15 } }, { label: '偏富', weights: { body: 15, mind: 15, action: 15, wealth: 40, heart: 15 } }, { label: '偏心', weights: { body: 15, mind: 15, action: 15, wealth: 15, heart: 40 } } ] } } ``` - [ ] **Step 2: 替换 computed** 删除旧的 `sum` 和 `enabledDimensions`,新增 `sum` 用 `currentValue`: ```js computed: { sum() { return this.dimensions.reduce((s, d) => s + (d.currentValue || 0), 0) } } ``` - [ ] **Step 3: 替换 watch** 简化 — 从外部 props `value` 初始化 `currentValue`,只保留 `handler`: ```js watch: { value: { immediate: true, handler(val) { if (Array.isArray(val) && val.length > 0) { val.forEach(w => { const dim = this.dimensions.find(d => d.code === w.dimension) if (dim) { dim.currentValue = w.weight || 0 } }) } } } } ``` - [ ] **Step 4: 替换 methods — 关键逻辑** ```js methods: { getMaxForDim(code) { const otherTotal = this.dimensions .filter(d => d.code !== code && (d.currentValue || 0) > 0) .reduce((s, d) => s + (d.currentValue || 0), 0) return Math.max(0, 100 - otherTotal) }, getRemaining() { return 100 - this.sum }, onWeightChange() { // 当其他维度有值时,当前维度的上限已被 getMaxForDim 控制 // 但数字输入可能未 clamp,强制修正 this.dimensions.forEach(d => { const max = this.getMaxForDim(d.code) if (d.currentValue > max) { d.currentValue = max } if (d.currentValue < 0) { d.currentValue = 0 } }) this.emitValue() }, emitValue() { const weights = this.dimensions.map(d => ({ dimension: d.code, weight: d.currentValue || 0, enabled: (d.currentValue || 0) > 0 })) this.$emit('input', weights) }, applyPreset(preset) { this.dimensions.forEach(d => { d.currentValue = preset.weights[d.code] || 0 }) this.onWeightChange() } } ``` - [ ] **Step 5: 确认 props 接口不变** ```js props: { value: { type: Array, default: () => [] }, showPresets: { type: Boolean, default: false } } ``` - [ ] **Step 6: 移除旧的 `isEnabled`, `onEnabledChange` 方法(上面已替换)** --- ### Task 3: 重写样式 **Files:** - Modify: `cfc-web/src/components/DimensionWeightPicker.vue:124-167` - [ ] **Step 1: 替换 style 块** ```vue ``` --- ### Task 4: 功能验证 - [ ] **Step 1: 检查 LSP 诊断** Run: 使用 OpenCode 的 `lsp_diagnostics` 检查 `cfc-web/src/components/DimensionWeightPicker.vue` Expected: 无错误 - [ ] **Step 2: 验证接口兼容性** ```bash grep -r 'DimensionWeightPicker' cfc-web/src/ --include='*.vue' -l ``` 确认 Activities.vue, ArticleEdit.vue, EnergyRuleManagement.vue 中的用法无需改动(props `value` 和 `showPresets` 不变) - [ ] **Step 3: commit** ```bash cd /sc-data/cfc git add cfc-web/src/components/DimensionWeightPicker.vue docs/superpowers/plans/2026-07-02-dimension-weight-picker-redesign.md docs/superpowers/specs/2026-07-02-dimension-weight-picker-redesign.md git commit -m "feat: 重写DimensionWeightPicker为slider+数字输入,动态max限制总和≤100%" ``` --- ### 自检清单 | 规格要求 | 对应 Task | |---------|-----------| | 5 个维度各 slider + 数字输入 | Task 1 (template) | | slider 动态 max 限制 | Task 2 (getMaxForDim) | | 数字输入与 slider 双向同步 | Task 1 + Task 2 | | 总和显示 | Task 2 (computed sum) | | 预设按钮 | Task 1 + Task 2 (applyPreset) | | Props/emit 接口兼容 | Task 2 Step 5 | | 样式统一 | Task 3 | 未发现占位符、类型不一致或循环引用问题。