---
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
{{ selectedDateFormatted }}
当日支出
¥{{ expense.toFixed(2) }}
当日收入
¥{{ income.toFixed(2) }}
```
```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
总支出
¥{{ formatMoney(stats.totalExpense) }}
```
### 阶段 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 开发团队