zcui/saber3/docs/开发设计-工作流审批中心.md
2026-06-17 11:00:42 +08:00

407 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 工作流审批中心开发设计文档
**版本**: v1.0
**日期**: 2026-06-11
**作者**: AI 助手
---
## 1. 项目概述
### 1.1 项目背景
为 BladeX/Saber3 企业级微服务平台增加工作流审批中心模块,提供统一的流程任务管理入口。模块包含四个子页面:我的待办、我的已办、我的申请、我的流程(统一视图)。
### 1.2 技术栈
- **前端框架**: Vue 3 + Element Plus + Avue CRUD
- **构建工具**: Vite
- **语言**: JavaScript无 TypeScript
- **包管理**: pnpm
- **样式**: SCSS + Element Plus 主题变量
### 1.3 参考原型
原型项目位于 `prototype/` 目录(已从 `src/frontend` 移出),包含三个参考页面:
- `MyTodo.vue` — 我的待办
- `MyDone.vue` — 我的已办
- `MyApplication.vue` — 我的申请
---
## 2. 模块结构
### 2.1 文件目录
```
src/
├── api/
│ └── workflow/
│ └── index.js # API 接口层mock 数据)
├── views/
│ └── workflow/
│ ├── todo.vue # 我的待办
│ ├── done.vue # 我的已办
│ ├── my.vue # 我的申请
│ └── process.vue # 我的流程(统一视图)
├── components/ # 复用全局组件
└── router/ # 动态路由由后端菜单 JSON 生成
docs/
├── 需求分析-工作流审批中心.md # 需求文档
├── 开发设计-工作流审批中心.md # 本文档
└── sql/
└── workflow-menu-init.sql # 菜单初始化 SQL
```
### 2.2 菜单结构
```
业务流程 (parent_id=0, id=10001)
├── 我的待办 (parent_id=10001, id=10002) → /workflow/todo
├── 我的已办 (parent_id=10001, id=10003) → /workflow/done
├── 我的申请 (parent_id=10001, id=10004) → /workflow/my
└── 我的流程 (parent_id=10001, id=10005) → /workflow/process
```
---
## 3. 页面设计
### 3.1 我的待办 (todo.vue)
**风格**: Options API + `<avue-crud>`
**核心功能**:
- 列表展示待审批任务
- 筛选:流程类型、紧急程度
- 操作:审批(统一弹窗)、查看
- 右上角 Badge 显示待处理数量
**关键设计决策**:
- 审批/驳回合并为**统一弹窗**,使用单选按钮选择"同意/驳回"
- 原型:两个独立弹窗
- 本实现:合并为一个弹窗,减少用户操作步骤
- 紧急程度列使用自定义 slot + `el-tag` 展示,带颜色区分
- 操作列仅保留"审批"和"查看",移除独立的"驳回"按钮
- **右上角 Badge 计数从列表接口返回的 `total` 字段获取,不再单独调用 `getTodoCount` 接口**
**弹窗交互**:
```
审批处理弹窗
├── 流程名称(只读)
├── 申请人(只读)
├── 处理结果(单选:同意/驳回)*必填
├── 审批意见/驳回原因(文本域)
│ └── 驳回时必须填写
└── 按钮:取消、确定
```
### 3.2 我的已办 (done.vue)
**核心功能**:
- 列表展示已处理记录
- 筛选:流程类型、处理结果
- 操作:查看、流转
- 右上角 Badge 显示已处理数量
**关键设计决策**:
- "流转"按钮打开**流转时间线弹窗**,使用 `el-timeline` 组件
- 原型:简单的 message 提示
- 本实现:完整的时间线弹窗,展示每一步的审批详情
- 处理结果使用自定义 slot + `el-tag` 展示(已同意=绿色,已驳回=红色)
- **右上角 Badge 计数从列表接口返回的 `total` 字段获取**
**流转弹窗设计**:
```
流程流转详情弹窗
├── 流程名称(标题下方)
└── el-timeline
├── el-timeline-item (type=primary)
│ └── el-card
│ ├── 步骤名称 + 结果标签
│ ├── 处理人 + 时间
│ └── 备注(如有)
├── el-timeline-item (type=success)
│ └── ...
└── ...
```
### 3.3 我的申请 (my.vue)
**核心功能**:
- 列表展示个人发起的申请
- **无搜索条件区域**searchShow: false
- 操作:查看、编辑(仅待提交)、删除(仅待提交)
- 发起新流程按钮 + 流程选择弹窗
**关键设计决策**:
- 搜索条件隐藏,保持页面简洁
- 新增"待提交"状态(灰色标签)
- 编辑/删除按钮**条件渲染**:仅当 `status === '待提交'` 时显示
- 删除操作使用 `this.$confirm` 二次确认
**状态标签映射**:
| 状态 | Element Tag type | effect |
|------|-----------------|--------|
| 待提交 | info | plain |
| 审批中 | warning | light |
| 已完成 | success | light |
| 已驳回 | danger | light |
### 3.4 我的流程 (process.vue)
**核心功能**:
- 流程发起中心,展示所有可发起的流程类型
- CSS Grid 卡片网格布局
- 每个卡片包含:彩色图标、流程名称、分类、状态标签
- 点击卡片发起对应流程
**关键设计决策**:
- 使用 CSS Grid (`grid-template-columns: repeat(auto-fill, minmax(220px, 1fr))`) 实现自适应卡片布局
- 卡片顶部使用 CSS 伪元素 `::before` 实现彩色渐变横线
- 图标使用 Element Plus Icons背景色与横线颜色一致
- 悬停效果:卡片上浮 + 阴影 + 图标放大旋转
- 数据使用静态 mock 数组,后续可替换为 API 接口
**页面布局**:
```
┌────────────────────────────────────────┐
│ 我的流程 共 5 个流程 │
├────────────────────────────────────────┤
│ ┌────┐ ┌────┐ ┌────┐ ┌────┐ │
│ │图标│ │图标│ │图标│ │图标│ │
│ │名称│ │名称│ │名称│ │名称│ │
│ │分类│ │分类│ │分类│ │分类│ │
│ │启用│ │启用│ │启用│ │启用│ │
│ └────┘ └────┘ └────┘ └────┘ │
│ ┌────┐ │
│ │图标│ │
│ │名称│ │
│ │分类│ │
│ │启用│ │
│ └────┘ │
└────────────────────────────────────────┘
```
---
## 4. API 设计
### 4.1 接口清单
| 函数名 | 参数 | 返回值 | 说明 |
|--------|------|--------|------|
| `getTodoList` | current, size, params | Promise<{records, total}> | 待办列表 |
| `getDoneList` | current, size, params | Promise<{records, total}> | 已办列表 |
| `getMyList` | current, size, params | Promise<{records, total}> | 申请列表 |
| `getProcessList` | current, size, params | Promise<{records, total}> | 统一流程列表 |
| `getProcessStats` | - | Promise<{todoCount, doneCount, myCount, pendingCount, draftCount, rejectedCount}> | 统计数据 |
| `getTodoCount` | - | Promise<number> | **待办数量(已弃用,前端不再使用)** |
| `approve` | data | Promise | 审批通过 |
| `reject` | data | Promise | 审批驳回 |
| `getDetail` | id | Promise<record> | 流程详情 |
### 4.2 Mock 数据说明
当前使用 `Promise.resolve(mockData)` 方式模拟 API 响应,便于后续替换为真实接口。
**数据量**:
- 待办6 条
- 已办7 条(含流转步骤 trackSteps
- 申请6 条(含 2 条待提交)
**trackSteps 结构**:
```javascript
{
stepName: '部门经理审批',
handler: '李主管',
time: '2026-05-10 16:45:00',
result: '已同意',
resultType: 'success',
type: 'success',
remark: '符合部门需求,同意采购'
}
```
---
## 5. 状态管理
### 5.1 组件内部状态
各页面使用 Vue Options API 的 `data()` 管理状态,无需 Vuex/Pinia。
### 5.2 数据流
```
API (mock)
组件 onLoad()
data.records ← 列表数据
page.total ← 总条数
stats ← 统计数据
<avue-crud> 渲染
用户操作 → API 调用 → 刷新列表
```
---
## 6. 样式设计
### 6.1 通用样式
所有页面共享以下通用样式(已提取到各组件的 `<style scoped>`
```scss
.workflow-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
padding: 0 10px;
}
.workflow-title {
margin: 0;
font-size: 18px;
font-weight: 500;
}
```
### 6.2 统计卡片样式 (process.vue)
```scss
.stat-card {
display: flex;
align-items: center;
cursor: pointer;
transition: transform 0.2s;
&:hover { transform: translateY(-2px); }
}
.stat-icon {
width: 48px; height: 48px;
border-radius: 8px;
display: flex;
align-items: center; justify-content: center;
margin-right: 12px;
}
// 各卡片颜色...
```
### 6.3 流转弹窗样式 (done.vue)
```scss
.transfer-process-name {
font-size: 16px; font-weight: 500;
margin-bottom: 20px;
padding-bottom: 12px;
border-bottom: 1px solid #e4e7ed;
}
.step-header { display: flex; justify-content: space-between; }
.step-remark {
padding: 8px; background: #f5f7fa;
border-radius: 4px; margin-top: 6px;
}
```
---
## 7. 与原型差异说明
### 7.1 技术栈差异
| 维度 | 原型 | 本实现 |
|------|------|--------|
| API 风格 | Composition API (`<script setup>`) | Options API |
| 表格组件 | 原生 `el-table` | Avue `<avue-crud>` |
| 样式方案 | 原生 Element Plus | Avue 主题 + 自定义 SCSS |
| 图标 | Element Plus Icons | Element Plus Icons |
### 7.2 功能差异
| 功能 | 原型 | 本实现 | 说明 |
|------|------|--------|------|
| 审批弹窗 | 两个独立弹窗(审批/驳回) | 统一弹窗 + 单选 | 简化操作 |
| 流转查看 | message 提示 | el-timeline 弹窗 | 更直观 |
| 紧急程度 | 有列但数据字段不同 | 自定义 slot + tag | 保持 Saber3 风格 |
| 我的申请搜索 | 无 | 无 | 一致 |
| 编辑/删除 | 有(条件显示) | 有(条件显示) | 一致 |
| 我的流程 | 流程卡片网格(发起中心) | 流程卡片网格(发起中心) | 一致 |
### 7.3 设计决策理由
1. **统一审批弹窗**:减少弹窗数量,用户在一个弹窗内完成同意/驳回选择,操作路径更短
2. **流转时间线**:将原型的 message 提示升级为可视化时间线,审批历史一目了然
3. **Avue CRUD**:复用 Saber3 现有组件体系,保持项目风格一致性
4. **我的流程页面**:流程发起中心,使用卡片网格展示所有可发起的流程,点击即可发起
5. **待提交状态**:支持草稿功能,用户可以先创建流程暂不提交
---
## 8. 构建与部署
### 8.1 本地开发
```bash
pnpm run dev # 启动开发服务器,端口 2888
```
### 8.2 生产构建
```bash
pnpm run build # 开发构建esbuild
pnpm run build:prod # 生产构建terser去除 console
```
### 8.3 菜单初始化
执行 `docs/sql/workflow-menu-init.sql` 在数据库中创建菜单和权限。
---
## 9. 待办事项TODO
### 9.1 前端待办
- [ ] 接入真实 API 接口(替换 mock 数据)
- [ ] 流程详情页面(查看按钮跳转)
- [ ] 流程发起表单页面(选择流程类型后进入)
- [ ] 编辑功能(待提交状态的表单编辑)
- [ ] 审批意见附件上传
- [ ] 流程图可视化展示
### 9.2 后端待办
- [ ] 设计并创建流程实例表blade_flow_instance
- [ ] 设计并创建审批记录表blade_flow_approval
- [ ] 集成 Flowable/Activiti 工作流引擎
- [ ] 实现流程定义管理接口
- [ ] 实现审批/驳回/转办等业务接口
- [ ] 实现消息通知(待办提醒)
---
## 10. 附录
### 10.1 Git 提交记录
```
:sparkles: feat(workflow): 新增工作流审批中心模块
- 我的待办、我的已办、我的申请、我的流程四个页面
- 统一审批弹窗、流转时间线、统计卡片等交互
- mock 数据 + API 接口层
```
### 10.2 参考文档
- [Element Plus 官方文档](https://element-plus.org/)
- [Avue 官方文档](https://avuejs.com/)
- [Vue 3 官方文档](https://vuejs.org/)
- [BladeX 官方文档](https://bladex.cn/)
---
**文档结束**