2026-06-16 14:07:58 +08:00
|
|
|
|
# 工作流审批中心开发设计文档
|
|
|
|
|
|
|
|
|
|
|
|
**版本**: 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` 展示,带颜色区分
|
|
|
|
|
|
- 操作列仅保留"审批"和"查看",移除独立的"驳回"按钮
|
2026-06-17 11:00:42 +08:00
|
|
|
|
- **右上角 Badge 计数从列表接口返回的 `total` 字段获取,不再单独调用 `getTodoCount` 接口**
|
2026-06-16 14:07:58 +08:00
|
|
|
|
|
|
|
|
|
|
**弹窗交互**:
|
|
|
|
|
|
```
|
|
|
|
|
|
审批处理弹窗
|
|
|
|
|
|
├── 流程名称(只读)
|
|
|
|
|
|
├── 申请人(只读)
|
|
|
|
|
|
├── 处理结果(单选:同意/驳回)*必填
|
|
|
|
|
|
├── 审批意见/驳回原因(文本域)
|
|
|
|
|
|
│ └── 驳回时必须填写
|
|
|
|
|
|
└── 按钮:取消、确定
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 3.2 我的已办 (done.vue)
|
|
|
|
|
|
|
|
|
|
|
|
**核心功能**:
|
|
|
|
|
|
- 列表展示已处理记录
|
|
|
|
|
|
- 筛选:流程类型、处理结果
|
|
|
|
|
|
- 操作:查看、流转
|
|
|
|
|
|
- 右上角 Badge 显示已处理数量
|
|
|
|
|
|
|
|
|
|
|
|
**关键设计决策**:
|
|
|
|
|
|
- "流转"按钮打开**流转时间线弹窗**,使用 `el-timeline` 组件
|
|
|
|
|
|
- 原型:简单的 message 提示
|
|
|
|
|
|
- 本实现:完整的时间线弹窗,展示每一步的审批详情
|
|
|
|
|
|
- 处理结果使用自定义 slot + `el-tag` 展示(已同意=绿色,已驳回=红色)
|
2026-06-17 11:00:42 +08:00
|
|
|
|
- **右上角 Badge 计数从列表接口返回的 `total` 字段获取**
|
2026-06-16 14:07:58 +08:00
|
|
|
|
|
|
|
|
|
|
**流转弹窗设计**:
|
|
|
|
|
|
```
|
|
|
|
|
|
流程流转详情弹窗
|
|
|
|
|
|
├── 流程名称(标题下方)
|
|
|
|
|
|
└── 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}> | 统计数据 |
|
2026-06-17 11:00:42 +08:00
|
|
|
|
| `getTodoCount` | - | Promise<number> | **待办数量(已弃用,前端不再使用)** |
|
2026-06-16 14:07:58 +08:00
|
|
|
|
| `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/)
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
**文档结束**
|