--- name: pancli-implement description: 根据 pancli 设计图(.pen 文件)进行前后端完整实施的专业技能,确保高度还原设计,数据表支持,交互确认 license: MIT compatibility: Requires .pen design files, Entity layer, WebApi controllers, Vue 3 frontend metadata: author: EmailBill Development Team version: "1.0.0" generatedBy: opencode lastUpdated: "2026-02-03" source: "基于 .pans/v2.pen 设计实施流程" --- # pancli-implement - 设计图实施技能 > 根据 pancli 设计图(.pen 文件)进行前后端完整实施,确保高度还原设计稿,包括数据表确认、API 开发、前端组件实现和交互验证。 ## 何时使用此技能 **总是使用此技能当:** - 需要根据 .pen 设计文件实施前后端功能 - 将设计图转换为可运行的代码 - 需要确认数据表结构是否支持设计需求 - 实施过程中需要询问用户确认交互细节 - 高度还原设计稿的视觉效果和交互体验 **触发条件:** - 用户提到 "实施设计图"、"根据设计实现"、"按照 pancli" - 任务涉及从 .pen 文件到代码的转换 - 需要同时开发前端和后端 ## 核心实施原则 ### 0. **模块化架构:复杂页面拆分** **重要:** 对于复杂页面(如日历、统计概览、仪表板),必须采用**模块化架构**: **目录结构规范:** ``` views/ calendarV2/ # 页面目录 Index.vue # 主页面(编排器) modules/ # 模块目录 Calendar.vue # 日历模块 Stats.vue # 统计模块 TransactionList.vue # 交易列表模块 ``` **模块化原则:** 1. **高内聚模块** - 每个模块是独立的功能单元 - 模块内部管理自己的数据和状态 - 模块自己调用 API 获取数据 - 模块自己处理内部事件 2. **Index.vue 作为编排器** - **只负责布局和事件编排** - **不调用 API,不管理业务数据** - 接收用户交互(如日期选择) - 通过 props 传递必要参数给模块 - 通过事件监听模块的输出 - 协调模块间的通信 3. **模块间通信** - 父 → 子:通过 props 传递(只传必要参数,如 `selectedDate`) - 子 → 父:通过 emit 发送事件(如 `@transaction-click`) - 兄弟模块:通过父组件中转事件 4. **不使用 TypeScript** - 项目使用纯 JavaScript + Vue 3 Composition API - **不要**在 ` ``` ```vue ``` ```vue ``` **模块化的好处:** - ✅ **关注点分离**:Index 只管布局和编排,模块专注业务逻辑 - ✅ **独立维护**:修改某个模块不影响其他模块 - ✅ **可复用性**:模块可以在其他页面复用 - ✅ **可测试性**:每个模块可以独立测试 - ✅ **代码清晰**:职责明确,代码结构清晰 **反模式(不要这样做):** ```vue ``` **什么时候需要模块化?** - 页面有 3 个以上独立功能区域 - 每个区域有自己的数据查询需求 - 页面代码超过 300 行 - 功能区域可能被其他页面复用 **什么时候不需要模块化?** - 简单页面(如登录页、详情页) - 只有一个主要功能 - 代码少于 200 行 - 无明显的功能分区 ### 1. **数据优先,提前确认** 在开始编码前,**必须先确认数据表结构**: **检查清单:** - [ ] 读取 .pen 设计文件,理解所有数据需求 - [ ] 检查现有 Entity 层,确认是否支持设计需求 - [ ] 如果需要新增字段/表/枚举值,**先询问用户确认** - [ ] 列出所有数据变更,等待用户批准后再继续 **示例确认流程:** ```markdown ## 数据表结构确认 根据设计图分析,需要以下数据支持: ### 现有实体: ✅ TransactionRecord - 支持交易记录 ✅ BudgetRecord - 支持预算管理 ✅ TransactionCategory - 支持分类 ### 需要变更: 1. **TransactionCategory 表新增字段** - 字段名: IconName (string) - 用途: 存储 lucide 图标名称(如 "utensils"、"shopping-cart") - 原因: 设计图使用图标名称渲染,现有 Icon 字段存储 SVG 不适合 2. **BudgetRecord 新增计算字段** - 字段名: ProgressPercentage (decimal, 计算属性) - 用途: 当前支出占预算的百分比 - 原因: 设计图显示进度条需要 ### 是否批准以上变更?如不批准,请提供替代方案。 ``` **不得做:** - ❌ 未经确认直接修改 Entity 层 - ❌ 假设字段存在而不检查 - ❌ 跳过数据表确认直接实施前端 ### 2. **交互细节,逐一确认** 设计图无法表达所有交互逻辑,**必须向用户确认**: **需要确认的交互:** 1. **按钮点击行为** - 跳转到哪个页面? - 弹出什么对话框? - 触发什么 API? 2. **周期切换逻辑**(如周/月/年) - 周:本周一到周日?还是最近7天? - 月:自然月?还是最近30天? - 年:当年1-12月?还是最近12个月? 3. **数据计算逻辑** - 环比百分比如何计算? - 趋势图数据范围? - 空状态显示什么? 4. **跳转目标** - "查看全部"跳转到哪里? - "管理预算"跳转到哪个页面? - 通知按钮打开什么? **示例确认:** ```markdown ## 交互行为确认 ### 1. 顶部通知按钮 设计图:bell 图标按钮 **问题:** 点击后跳转到哪里? - A. 消息中心(MessageView.vue) - B. 通知列表(新页面) - C. 弹出通知面板 ### 2. 周期切换(周/月/年) 设计图:三个 segment 切换按钮 **问题:** 周期定义? - 周:本周一到周日 or 最近7天 - 月:当前自然月 or 最近30天 - 年:当年1-12月 or 最近12个月 ### 3. 核心指标徽章(如 "-15%") 设计图:显示百分比变化 **问题:** 对比哪个周期? - A. 与上一周期对比(上周/上月/去年) - B. 与同期对比(去年同周/去年同月) - C. 与预算目标对比 请明确以上交互逻辑。 ``` ### 3. **高度还原设计稿** **视觉还原标准:** - 严格按照设计图的间距、字号、颜色、圆角 - 使用设计图中的实际字体(如 DM Sans, Bricolage Grotesque, JetBrains Mono) - 匹配卡片阴影、边框样式 - 复现设计图的布局层级 **对照检查:** ```typescript // 设计图: // - padding: 24px // - gap: 16px // - cornerRadius: 12px // - fontSize: 14px // - fontWeight: 600 // 实现:
``` **字体映射:** | 设计图字体 | CSS 实现 | |-----------|---------| | Bricolage Grotesque | `font-family: 'Bricolage Grotesque', system-ui, sans-serif` | | DM Sans | `font-family: 'DM Sans', -apple-system, sans-serif` | | JetBrains Mono | `font-family: 'JetBrains Mono', 'SF Mono', monospace` | | Newsreader | `font-family: 'Newsreader', Georgia, serif` | ### 4. **前后端同步开发** **开发顺序:** ``` 1. 确认数据表 → 2. 开发后端 API → 3. 实施前端组件 → 4. 集成测试 → 5. 视觉验证 ``` **后端开发标准:** - 在 `Entity/` 中新增/修改实体 - 在 `Repository/` 中添加数据访问方法 - 在 `Service/` 中实现业务逻辑 - 在 `WebApi/Controllers/` 中创建 API 端点 - 编写 xUnit 测试验证逻辑 **前端开发标准:** - 在 `Web/src/views/` 中创建/修改页面组件 - 在 `Web/src/components/` 中提取可复用组件 - 在 `Web/src/api/` 中定义 API 客户端 - 使用 Vue 3 Composition API + ` ``` **B. 业务模块 (Business Module)** `src/views/Statistics/modules/MetricsCard.vue` - **职责**:独立负责特定功能区域的 UI 和数据获取。 - **原则**:自包含 (Self-contained) - 自己 import api,自己 fetch data。 ```vue ``` ### 阶段 5: 集成测试与验证 **5.1 运行测试** ```bash # 后端测试 dotnet test WebApi.Test/WebApi.Test.csproj # 前端构建 cd Web pnpm lint pnpm build ``` **5.2 视觉验证** ```typescript // 使用 pencil 截图对比 pencil_get_screenshot(nodeId: "jF3SD") // 设计图截图 // 在浏览器中截图实际效果 // 对比以下方面: // - 间距是否一致(padding, gap) // - 字号是否匹配(fontSize) // - 颜色是否准确(fill, textColor) // - 圆角是否正确(cornerRadius) // - 布局是否对齐(layout, justifyContent, alignItems) ``` **5.3 交互验证** - [ ] 周期切换按钮工作正常 - [ ] 核心指标数据正确显示 - [ ] 徽章百分比计算准确 - [ ] 点击卡片跳转正确 - [ ] 空状态显示合理 - [ ] 加载状态流畅 - [ ] 错误处理友好 ## 避免的反模式 ### ❌ 不要这样做: **1. 未经确认修改数据表** ```csharp // ❌ 直接新增字段 public class TransactionCategory : BaseEntity { public string IconName { get; set; } // ❌ 未经用户确认 } ``` **2. 猜测交互逻辑** ```vue // ❌ 假设跳转目标 ``` **3. 不按设计图样式** ```scss // 设计图: padding: 24px .card { padding: 20px; // ❌ 不匹配设计 } ``` **4. 跳过测试** ```bash # ❌ 不运行测试直接提交 git add . git commit -m "完成实施" ``` **5. 忽略暗色模式** ```scss .card { background: #FFFFFF; // ❌ 只实现亮色模式 } ``` ### ✅ 应该这样做: **1. 数据变更先确认** ```markdown ## 数据表变更请求 需要在 TransactionCategory 新增以下字段: - IconName (string): 存储图标名称 - 用途: 前端渲染 lucide 图标 是否批准? ``` **2. 交互逻辑先确认** ```markdown ## 交互确认 通知按钮点击后: - A. 跳转到 MessageView - B. 弹出通知列表 - C. 其他 请明确选择。 ``` **3. 严格按照设计图** ```scss // 设计图: padding: 24px, gap: 16px, borderRadius: 12px .card { padding: 24px; // ✅ 匹配设计 gap: 16px; // ✅ 匹配设计 border-radius: 12px; // ✅ 匹配设计 } ``` **4. 完整测试** ```bash # ✅ 运行所有测试 dotnet test cd Web && pnpm lint && pnpm build ``` **5. 支持暗色模式** ```scss .card { background: #FFFFFF; @media (prefers-color-scheme: dark) { background: #18181B; // ✅ 暗色适配 } } ``` ## 委派与任务管理 **使用此技能时:** ```typescript delegate_task( category: "visual-engineering", load_skills: ["pancli-implement", "frontend-ui-ux"], description: "根据 v2.pen 设计图实施统计概览页面", prompt: ` ## 任务 根据 .pans/v2.pen 中的统计概览设计图(节点 ID: jF3SD)实施完整的前后端功能 ## 预期结果 - [ ] Entity 层变更(如需要,经用户确认) - [ ] 后端 API 开发并通过测试 - [ ] 前端页面高度还原设计图 - [ ] 交互逻辑符合用户确认 - [ ] 亮色/暗色主题都正常 - [ ] 所有测试通过(dotnet test, pnpm build) ## 必需工具 - pencil_batch_get: 读取设计文件 - pencil_get_screenshot: 设计图截图 - read: 读取现有代码 - glob: 查找文件 - edit/write: 修改/新增代码 - bash: 运行测试 ## 必须做 1. **数据确认阶段** - 读取设计文件分析数据需求 - 检查现有 Entity 是否支持 - 如需变更,生成确认清单并等待用户批准 2. **交互确认阶段** - 列出所有不确定的交互逻辑 - 生成确认清单并等待用户明确 3. **后端开发** - 按用户批准修改 Entity - 实现 Repository 数据访问 - 创建 Controller API - 编写 xUnit 测试并通过 4. **前端开发** - **复杂页面强制模块化**: 采用 Index.vue + modules/ 结构 - Index.vue 仅编排,modules 负责数据获取 - 定义 API 客户端(src/api/) - 严格按照设计图样式(间距、字号、颜色、圆角) - 使用设计图中的实际字体 - 支持亮色/暗色主题 5. **验证阶段** - 运行后端测试:dotnet test - 运行前端构建:pnpm lint && pnpm build - 视觉对比设计图截图 - 验证交互逻辑 ## 不得做 - ❌ 未经确认直接修改 Entity - ❌ 猜测交互逻辑而不询问 - ❌ 禁止复杂页面写成单文件组件 (Monolithic) - ❌ 不按设计图样式随意实现 - ❌ 跳过测试 - ❌ 忽略暗色模式 - ❌ 使用占位数据而不调用真实 API ## 上下文 - 设计文件: .pans/v2.pen - 设计节点 ID: jF3SD (Statistics - Overview - Light) - 现有页面: Web/src/views/StatisticsView.vue - 现有 API: Web/src/api/statistics.js - Entity 层: Entity/*.cs - Controller 层: WebApi/Controllers/*.cs ## 实施流程 1. 数据确认 → 等待批准 2. 交互确认 → 等待明确 3. 后端开发 → 测试通过 4. 前端开发 → 视觉验证 5. 集成测试 → 全部通过 `, run_in_background: false ) ``` ## 快速参考 ### 数据表确认模板 ```markdown ## 数据表结构确认 ### 现有实体分析 ✅ [实体名] - 支持 [功能] ❌ [实体名] - 缺少 [字段] ### 需要变更 1. **[表名] 新增字段** - 字段名: [字段名] ([类型]) - 用途: [用途说明] - 原因: [为什么需要] 2. **[表名] 修改字段** - 字段名: [字段名] - 变更: [原类型] → [新类型] - 原因: [为什么修改] ### 是否批准? ``` ### 交互确认模板 ```markdown ## 交互逻辑确认 ### 1. [交互元素名称] **设计位置:** [描述] **问题:** [需要确认的问题] **选项:** - A. [选项1] - B. [选项2] - C. 其他:[请说明] ### 2. [数据计算逻辑] **设计显示:** [设计图显示的内容] **问题:** [计算逻辑或数据来源] **选项:** - A. [选项1] - B. [选项2] 请逐一明确。 ``` ### 样式映射表 | 设计图属性 | CSS 属性 | 示例 | |-----------|---------|------| | padding | padding | `padding: 24px` | | gap | gap | `gap: 16px` | | cornerRadius | border-radius | `border-radius: 12px` | | fill | background | `background: #FFFFFF` | | textColor | color | `color: #1A1A1A` | | fontSize | font-size | `font-size: 14px` | | fontWeight | font-weight | `font-weight: 600` | | fontFamily | font-family | `font-family: 'DM Sans', sans-serif` | | width: "fill_container" | width: 100% | `width: 100%` | | height: "hug_contents" | height: auto | `height: auto` | | layout: "vertical" | flex-direction: column | `flex-direction: column` | | layout: "horizontal" | flex-direction: row | `flex-direction: row` | | justifyContent: "space_between" | justify-content: space-between | `justify-content: space-between` | | alignItems: "center" | align-items: center | `align-items: center` | --- **版本:** 1.0.0 **最后更新:** 2026-02-03 **维护者:** EmailBill 开发团队