feat: 完整的Warm-Flow工作流框架文档体系建设
- 新增工作流框架开发指南文档 (warm-flow工作流框架开发指南.md) 包含技术架构、核心组件、开发流程、请假工作流示例等完整内容 - 新增工作流开发规范 (.cursor/cursorrules-workflow.md) 整合到cursorrules体系,包含强制性VO类规范、状态管理、前后端开发模板 - 新增工作流开发最佳实践总结 (Warm-Flow工作流开发最佳实践总结.md) 基于请假工作流实践的快速开始模板、开发效率统计、常见问题解决方案 - 更新主配置文件 (.cursorrules) 添加工作流规范引用,确保Cursor AI在工作流开发时自动应用规范 - 新增变更记录 (code-adjust-record-2025-01-09-wuzilong.md) 详细记录本次工作流文档建设的所有变更内容 关键成果: - 建立了7种标准工作流状态管理体系 - 总结了6种常用工作流模式 (线性、排他网关、并行网关、会签等) - 提供了完整的前后端开发模板和最佳实践 - 解决了VO类基础字段规范等关键技术问题 - 形成了3.5天标准开发周期的高效开发流程
This commit is contained in:
1 parent
ede242e282
commit
45b5d58ae4
5 files changed
+2837
No files matched your search
@@ -0,0 +1,808 @@
|
|||||||
|
# Warm-Flow 工作流开发规范
|
||||||
|
|
||||||
|
## 🎯 概述
|
||||||
|
|
||||||
|
本规范基于 **warm-flow** 工作流框架,适用于所有工作流相关的开发任务。warm-flow 是 dromara 社区开源的轻量级工作流引擎,与 Spring Boot 和若依框架无缝集成。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔧 技术栈与配置
|
||||||
|
|
||||||
|
### 核心依赖
|
||||||
|
|
||||||
|
```xml
|
||||||
|
<!-- warm-flow核心依赖 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.dromara.warm</groupId>
|
||||||
|
<artifactId>warm-flow-mybatis-plus-sb3-starter</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.dromara.warm</groupId>
|
||||||
|
<artifactId>warm-flow-plugin-ui-sb-web</artifactId>
|
||||||
|
</dependency>
|
||||||
|
```
|
||||||
|
|
||||||
|
### 配置开关
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# application.yml
|
||||||
|
warm-flow:
|
||||||
|
enabled: true # 设置为 true 时,启用工作流功能
|
||||||
|
```
|
||||||
|
|
||||||
|
### 条件开启注解
|
||||||
|
|
||||||
|
```java
|
||||||
|
// 所有工作流相关类必须添加此注解
|
||||||
|
@ConditionalOnEnable
|
||||||
|
@Service / @Controller / @Component
|
||||||
|
public class WorkflowRelatedClass {
|
||||||
|
// 实现逻辑
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🏗️ 后端开发规范
|
||||||
|
|
||||||
|
### 1. 实体类规范
|
||||||
|
|
||||||
|
#### 1.1 BO 类规范
|
||||||
|
|
||||||
|
```java
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
public class TestLeaveBo extends BaseEntity {
|
||||||
|
private Long id;
|
||||||
|
private String leaveType;
|
||||||
|
private String startDate;
|
||||||
|
private String endDate;
|
||||||
|
private Integer leaveDays;
|
||||||
|
private String remark;
|
||||||
|
private String status; // 工作流状态字段(必需)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 1.2 VO 类规范(🔴 强制性)
|
||||||
|
|
||||||
|
```java
|
||||||
|
@Data
|
||||||
|
@ExcelIgnoreUnannotated
|
||||||
|
public class TestLeaveVo {
|
||||||
|
// 业务字段
|
||||||
|
private Long id;
|
||||||
|
private String leaveType;
|
||||||
|
private String startDate;
|
||||||
|
private String endDate;
|
||||||
|
private Integer leaveDays;
|
||||||
|
private String remark;
|
||||||
|
private String status;
|
||||||
|
|
||||||
|
// 🔴 基础字段(必须包含,避免MyBatis映射错误)
|
||||||
|
private Long createBy;
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
private Date createTime;
|
||||||
|
private Long updateBy;
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
private Date updateTime;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**⚠️ 重要提醒**: 所有工作流业务 VO 类必须包含四个基础字段,否则会出现 `Could not set property 'createBy'` 错误。
|
||||||
|
|
||||||
|
### 2. Controller 规范
|
||||||
|
|
||||||
|
```java
|
||||||
|
@ConditionalOnEnable // 🔴 必须添加
|
||||||
|
@Validated
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/workflow/业务模块")
|
||||||
|
public class WorkflowController extends BaseController {
|
||||||
|
|
||||||
|
private final IWorkflowService workflowService;
|
||||||
|
|
||||||
|
// 🔴 所有接口必须添加权限注解
|
||||||
|
@SaCheckPermission("workflow:业务模块:list")
|
||||||
|
@GetMapping("/list")
|
||||||
|
public TableDataInfo<WorkflowVo> list(WorkflowBo bo, PageQuery pageQuery) {
|
||||||
|
return workflowService.queryPageList(bo, pageQuery);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SaCheckPermission("workflow:业务模块:add")
|
||||||
|
@PostMapping()
|
||||||
|
public R<WorkflowVo> add(@Validated(AddGroup.class) @RequestBody WorkflowBo bo) {
|
||||||
|
return R.ok(workflowService.insertByBo(bo));
|
||||||
|
}
|
||||||
|
|
||||||
|
@SaCheckPermission("workflow:业务模块:edit")
|
||||||
|
@PutMapping()
|
||||||
|
public R<WorkflowVo> edit(@Validated(EditGroup.class) @RequestBody WorkflowBo bo) {
|
||||||
|
return R.ok(workflowService.updateByBo(bo));
|
||||||
|
}
|
||||||
|
|
||||||
|
@SaCheckPermission("workflow:业务模块:remove")
|
||||||
|
@DeleteMapping("/{ids}")
|
||||||
|
public R<Void> remove(@PathVariable Long[] ids) {
|
||||||
|
return toAjax(workflowService.deleteWithValidByIds(List.of(ids)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Service 规范
|
||||||
|
|
||||||
|
```java
|
||||||
|
@ConditionalOnEnable // 🔴 必须添加
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class WorkflowServiceImpl implements IWorkflowService {
|
||||||
|
|
||||||
|
private final WorkflowMapper baseMapper;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class) // 🔴 重要操作需要事务
|
||||||
|
public WorkflowVo insertByBo(WorkflowBo bo) {
|
||||||
|
Workflow entity = BeanUtil.toBean(bo, Workflow.class);
|
||||||
|
// 🔴 新建时必须设置状态为草稿
|
||||||
|
entity.setStatus("draft");
|
||||||
|
validEntityBeforeSave(entity);
|
||||||
|
boolean flag = baseMapper.insert(entity) > 0;
|
||||||
|
if (flag) {
|
||||||
|
bo.setId(entity.getId());
|
||||||
|
return BeanUtil.toBean(entity, WorkflowVo.class);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 其他CRUD方法...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. 数据库规范
|
||||||
|
|
||||||
|
#### 4.1 业务表必需字段
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- 所有工作流业务表必须包含以下字段
|
||||||
|
CREATE TABLE workflow_business (
|
||||||
|
id BIGINT(20) NOT NULL PRIMARY KEY COMMENT '主键ID',
|
||||||
|
|
||||||
|
-- 业务字段
|
||||||
|
-- ...
|
||||||
|
|
||||||
|
-- 🔴 工作流状态字段(必需)
|
||||||
|
status VARCHAR(20) DEFAULT 'draft' COMMENT '流程状态',
|
||||||
|
|
||||||
|
-- 🔴 标准基础字段(必需)
|
||||||
|
tenant_id VARCHAR(20) DEFAULT '000000' COMMENT '租户编号',
|
||||||
|
create_dept BIGINT(20) DEFAULT NULL COMMENT '创建部门',
|
||||||
|
create_by BIGINT(20) DEFAULT NULL COMMENT '创建者',
|
||||||
|
create_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||||
|
update_by BIGINT(20) DEFAULT NULL COMMENT '更新者',
|
||||||
|
update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||||
|
deleted TINYINT(1) DEFAULT 0 COMMENT '删除标志'
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='工作流业务表';
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 4.2 工作流状态值规范
|
||||||
|
|
||||||
|
| 状态值 | 状态名称 | 说明 | 可用操作 |
|
||||||
|
| --------- | -------- | ------------ | -------------------- |
|
||||||
|
| draft | 草稿 | 新建但未提交 | 编辑、删除、提交 |
|
||||||
|
| waiting | 待审批 | 流程进行中 | 查看、撤销 |
|
||||||
|
| complete | 已完成 | 流程正常结束 | 查看 |
|
||||||
|
| cancel | 已取消 | 申请人撤销 | 编辑、删除、重新提交 |
|
||||||
|
| back | 已退回 | 审批人退回 | 编辑、删除、重新提交 |
|
||||||
|
| invalid | 已作废 | 管理员作废 | 查看 |
|
||||||
|
| terminate | 已终止 | 流程异常终止 | 查看 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎨 前端开发规范
|
||||||
|
|
||||||
|
### 1. 页面结构规范
|
||||||
|
|
||||||
|
#### 1.1 列表页面结构
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<template>
|
||||||
|
<div class="p-2">
|
||||||
|
<!-- 搜索表单 -->
|
||||||
|
<transition
|
||||||
|
:enter-active-class="proxy?.animate.searchAnimate.enter"
|
||||||
|
:leave-active-class="proxy?.animate.searchAnimate.leave"
|
||||||
|
>
|
||||||
|
<div v-show="showSearch" class="search">
|
||||||
|
<el-form ref="queryFormRef" :model="queryParams" :inline="true">
|
||||||
|
<!-- 搜索字段 -->
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" icon="Search" @click="handleQuery">
|
||||||
|
搜索
|
||||||
|
</el-button>
|
||||||
|
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</div>
|
||||||
|
</transition>
|
||||||
|
|
||||||
|
<!-- 数据表格 -->
|
||||||
|
<el-card shadow="never">
|
||||||
|
<template #header>
|
||||||
|
<el-row :gutter="10" class="mb8">
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button
|
||||||
|
v-hasPermi="['workflow:业务:add']"
|
||||||
|
type="primary"
|
||||||
|
plain
|
||||||
|
icon="Plus"
|
||||||
|
@click="handleAdd"
|
||||||
|
>
|
||||||
|
新增
|
||||||
|
</el-button>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<el-table v-loading="loading" border :data="dataList">
|
||||||
|
<el-table-column type="selection" width="55" align="center" />
|
||||||
|
|
||||||
|
<!-- 业务字段 -->
|
||||||
|
|
||||||
|
<!-- 🔴 工作流状态列(必需) -->
|
||||||
|
<el-table-column label="流程状态" align="center">
|
||||||
|
<template #default="scope">
|
||||||
|
<dict-tag :options="wf_business_status" :value="scope.row.status" />
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
|
||||||
|
<!-- 🔴 操作列(根据状态显示不同按钮) -->
|
||||||
|
<el-table-column label="操作" align="center">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-row :gutter="10" class="mb8">
|
||||||
|
<el-col
|
||||||
|
:span="1.5"
|
||||||
|
v-if="['draft', 'cancel', 'back'].includes(scope.row.status)"
|
||||||
|
>
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
size="small"
|
||||||
|
icon="Edit"
|
||||||
|
@click="handleUpdate(scope.row)"
|
||||||
|
>
|
||||||
|
修改
|
||||||
|
</el-button>
|
||||||
|
</el-col>
|
||||||
|
<el-col
|
||||||
|
:span="1.5"
|
||||||
|
v-if="['draft', 'cancel', 'back'].includes(scope.row.status)"
|
||||||
|
>
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
size="small"
|
||||||
|
icon="Delete"
|
||||||
|
@click="handleDelete(scope.row)"
|
||||||
|
>
|
||||||
|
删除
|
||||||
|
</el-button>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<el-row :gutter="10" class="mb8">
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
size="small"
|
||||||
|
icon="View"
|
||||||
|
@click="handleView(scope.row)"
|
||||||
|
>
|
||||||
|
查看
|
||||||
|
</el-button>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="1.5" v-if="scope.row.status === 'waiting'">
|
||||||
|
<el-button
|
||||||
|
size="small"
|
||||||
|
type="primary"
|
||||||
|
icon="Notification"
|
||||||
|
@click="handleCancel(scope.row.id)"
|
||||||
|
>
|
||||||
|
撤销
|
||||||
|
</el-button>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</el-card>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { list业务, del业务 } from '@/api/workflow/业务模块';
|
||||||
|
import { cancelProcessApply } from '@/api/workflow/instance';
|
||||||
|
|
||||||
|
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||||
|
const { wf_business_status } = toRefs<any>(proxy?.useDict('wf_business_status'));
|
||||||
|
|
||||||
|
// 组件逻辑...
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 1.2 编辑页面结构(🔴 标准模板)
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<template>
|
||||||
|
<div class="p-2">
|
||||||
|
<!-- 🔴 1. 审批按钮组件(必需) -->
|
||||||
|
<el-card shadow="never">
|
||||||
|
<approvalButton
|
||||||
|
@submitForm="submitForm"
|
||||||
|
@approvalVerifyOpen="approvalVerifyOpen"
|
||||||
|
@handleApprovalRecord="handleApprovalRecord"
|
||||||
|
:buttonLoading="buttonLoading"
|
||||||
|
:id="form.id"
|
||||||
|
:status="form.status"
|
||||||
|
:pageType="routeParams.type"
|
||||||
|
/>
|
||||||
|
</el-card>
|
||||||
|
|
||||||
|
<!-- 2. 业务表单 -->
|
||||||
|
<el-card shadow="never" style="height: 78vh; overflow-y: auto">
|
||||||
|
<el-form
|
||||||
|
ref="formRef"
|
||||||
|
v-loading="loading"
|
||||||
|
:disabled="routeParams.type === 'view'"
|
||||||
|
:model="form"
|
||||||
|
:rules="rules"
|
||||||
|
label-width="80px"
|
||||||
|
>
|
||||||
|
<!-- 业务字段 -->
|
||||||
|
</el-form>
|
||||||
|
</el-card>
|
||||||
|
|
||||||
|
<!-- 🔴 3. 工作流组件(必需) -->
|
||||||
|
<submitVerify
|
||||||
|
ref="submitVerifyRef"
|
||||||
|
:task-variables="taskVariables"
|
||||||
|
@submit-callback="submitCallback"
|
||||||
|
/>
|
||||||
|
<approvalRecord ref="approvalRecordRef" />
|
||||||
|
|
||||||
|
<!-- 4. 流程选择对话框 -->
|
||||||
|
<el-dialog v-model="dialogVisible.visible" title="流程定义" width="500">
|
||||||
|
<el-select v-model="flowCode" placeholder="Select">
|
||||||
|
<el-option
|
||||||
|
v-for="item in flowCodeOptions"
|
||||||
|
:key="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.value"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
<template #footer>
|
||||||
|
<el-button @click="handleClose">取消</el-button>
|
||||||
|
<el-button type="primary" @click="submitFlow()">确认</el-button>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
// 🔴 必需的组件引入
|
||||||
|
import SubmitVerify from '@/components/Process/submitVerify.vue';
|
||||||
|
import ApprovalRecord from '@/components/Process/approvalRecord.vue';
|
||||||
|
import ApprovalButton from '@/components/Process/approvalButton.vue';
|
||||||
|
|
||||||
|
// 🔴 必需的API引入
|
||||||
|
import { add业务, get业务, update业务 } from '@/api/workflow/业务模块';
|
||||||
|
import { startWorkFlow } from '@/api/workflow/task';
|
||||||
|
|
||||||
|
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||||
|
|
||||||
|
// 🔴 必需的ref引用
|
||||||
|
const submitVerifyRef = ref<InstanceType<typeof SubmitVerify>>();
|
||||||
|
const approvalRecordRef = ref<InstanceType<typeof ApprovalRecord>>();
|
||||||
|
|
||||||
|
// 🔴 必需的变量定义
|
||||||
|
const buttonLoading = ref(false);
|
||||||
|
const loading = ref(true);
|
||||||
|
const routeParams = ref<Record<string, any>>({});
|
||||||
|
const taskVariables = ref<Record<string, any>>({});
|
||||||
|
|
||||||
|
// 🔴 流程定义选项(根据实际业务配置)
|
||||||
|
const flowCodeOptions = [{ value: 'workflow_code', label: '工作流名称' }];
|
||||||
|
|
||||||
|
// 🔴 必需的事件处理函数
|
||||||
|
const submitForm = async (status: string) => {
|
||||||
|
try {
|
||||||
|
// 1. 表单验证
|
||||||
|
await formRef.value?.validate();
|
||||||
|
|
||||||
|
// 2. 保存业务数据
|
||||||
|
buttonLoading.value = true;
|
||||||
|
let res;
|
||||||
|
if (form.value.id) {
|
||||||
|
res = await update业务(form.value);
|
||||||
|
} else {
|
||||||
|
res = await add业务(form.value);
|
||||||
|
}
|
||||||
|
form.value = res.data;
|
||||||
|
|
||||||
|
// 3. 处理不同状态
|
||||||
|
if (status === 'draft') {
|
||||||
|
proxy?.$modal.msgSuccess('暂存成功');
|
||||||
|
proxy.$tab.closePage(proxy.$route);
|
||||||
|
proxy.$router.go(-1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. 启动工作流
|
||||||
|
if (!flowCode.value) {
|
||||||
|
dialogVisible.visible = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await handleStartWorkFlow(res.data);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('提交失败:', error);
|
||||||
|
} finally {
|
||||||
|
buttonLoading.value = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleStartWorkFlow = async (data) => {
|
||||||
|
const submitFormData = {
|
||||||
|
flowCode: flowCode.value,
|
||||||
|
businessId: data.id,
|
||||||
|
variables: taskVariables.value,
|
||||||
|
};
|
||||||
|
|
||||||
|
const resp = await startWorkFlow(submitFormData);
|
||||||
|
submitVerifyRef.value.openDialog(resp.data.taskId);
|
||||||
|
};
|
||||||
|
|
||||||
|
const approvalVerifyOpen = () => {
|
||||||
|
submitVerifyRef.value.openDialog(routeParams.value.taskId);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleApprovalRecord = () => {
|
||||||
|
approvalRecordRef.value.init(form.value.id);
|
||||||
|
};
|
||||||
|
|
||||||
|
const submitCallback = async () => {
|
||||||
|
await proxy.$tab.closePage(proxy.$route);
|
||||||
|
proxy.$router.go(-1);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 🔴 页面初始化
|
||||||
|
onMounted(() => {
|
||||||
|
nextTick(async () => {
|
||||||
|
routeParams.value = proxy.$route.query;
|
||||||
|
// 初始化逻辑
|
||||||
|
if (['update', 'view', 'approval'].includes(routeParams.value.type)) {
|
||||||
|
getInfo();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. API 接口规范
|
||||||
|
|
||||||
|
#### 2.1 类型定义
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// api/workflow/业务模块/types.ts
|
||||||
|
export interface WorkflowForm extends BaseEntity {
|
||||||
|
id?: string | number;
|
||||||
|
// 业务字段
|
||||||
|
status?: string; // 🔴 工作流状态字段
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface WorkflowVO extends BaseEntity {
|
||||||
|
id?: string | number;
|
||||||
|
// 业务字段
|
||||||
|
status?: string; // 🔴 工作流状态字段
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface WorkflowQuery extends PageQuery {
|
||||||
|
// 查询字段
|
||||||
|
status?: string;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 2.2 接口定义
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// api/workflow/业务模块/index.ts
|
||||||
|
import request from '@/utils/request';
|
||||||
|
import { WorkflowQuery, WorkflowForm, WorkflowVO } from './types';
|
||||||
|
|
||||||
|
export const list业务 = (query: WorkflowQuery): AxiosPromise<WorkflowVO[]> => {
|
||||||
|
return request({
|
||||||
|
url: '/workflow/业务模块/list',
|
||||||
|
method: 'get',
|
||||||
|
params: query,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const get业务 = (id: string | number): AxiosPromise<WorkflowVO> => {
|
||||||
|
return request({
|
||||||
|
url: `/workflow/业务模块/${id}`,
|
||||||
|
method: 'get',
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const add业务 = (data: WorkflowForm): AxiosPromise<WorkflowVO> => {
|
||||||
|
return request({
|
||||||
|
url: '/workflow/业务模块',
|
||||||
|
method: 'post',
|
||||||
|
data: data,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const update业务 = (data: WorkflowForm): AxiosPromise<WorkflowVO> => {
|
||||||
|
return request({
|
||||||
|
url: '/workflow/业务模块',
|
||||||
|
method: 'put',
|
||||||
|
data: data,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const del业务 = (id: string | number | Array<string | number>): AxiosPromise<void> => {
|
||||||
|
return request({
|
||||||
|
url: `/workflow/业务模块/${id}`,
|
||||||
|
method: 'delete',
|
||||||
|
});
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 路由配置规范
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// router配置
|
||||||
|
{
|
||||||
|
path: '/workflow/业务模块',
|
||||||
|
component: Layout,
|
||||||
|
redirect: '/workflow/业务模块/index',
|
||||||
|
name: 'Workflow业务模块',
|
||||||
|
meta: {
|
||||||
|
title: '业务模块管理',
|
||||||
|
icon: 'workflow'
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: 'index',
|
||||||
|
component: () => import('@/views/workflow/业务模块/index.vue'),
|
||||||
|
name: 'Workflow业务模块List',
|
||||||
|
meta: { title: '业务模块列表', activeMenu: '/workflow/业务模块/index' }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'edit',
|
||||||
|
component: () => import('@/views/workflow/业务模块/edit.vue'),
|
||||||
|
name: 'Workflow业务模块Edit',
|
||||||
|
hidden: true,
|
||||||
|
meta: { title: '业务模块编辑', activeMenu: '/workflow/业务模块/index' }
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔍 工作流核心功能
|
||||||
|
|
||||||
|
### 1. 流程启动
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// 启动工作流标准代码
|
||||||
|
const handleStartWorkFlow = async (businessData: any) => {
|
||||||
|
const submitFormData = {
|
||||||
|
flowCode: 'your_flow_code', // 🔴 流程定义编码
|
||||||
|
businessId: businessData.id, // 🔴 业务数据ID
|
||||||
|
variables: {
|
||||||
|
// 🔴 流程变量
|
||||||
|
// 条件判断变量
|
||||||
|
amount: businessData.amount,
|
||||||
|
// 会签用户列表
|
||||||
|
userList: ['1', '3', '4'],
|
||||||
|
// 其他业务变量
|
||||||
|
...otherVariables,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
const resp = await startWorkFlow(submitFormData);
|
||||||
|
// 打开提交确认对话框
|
||||||
|
submitVerifyRef.value.openDialog(resp.data.taskId);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('启动工作流失败:', error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 任务办理
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// 在 submitVerify 组件中自动处理
|
||||||
|
// 支持的操作:
|
||||||
|
// - 提交审批
|
||||||
|
// - 委托 (delegateTask)
|
||||||
|
// - 转办 (transferTask)
|
||||||
|
// - 加签 (addSignature)
|
||||||
|
// - 减签 (reductionSignature)
|
||||||
|
// - 终止 (terminationTask)
|
||||||
|
// - 退回 (backProcess)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 流程撤销
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// 申请人撤销流程
|
||||||
|
const handleCancelProcessApply = async (businessId: string) => {
|
||||||
|
await proxy?.$modal.confirm('是否确认撤销当前单据?');
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
businessId: businessId,
|
||||||
|
message: '申请人撤销流程!',
|
||||||
|
};
|
||||||
|
|
||||||
|
await cancelProcessApply(data);
|
||||||
|
proxy?.$modal.msgSuccess('撤销成功');
|
||||||
|
getList(); // 刷新列表
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📊 常用工作流模式
|
||||||
|
|
||||||
|
### 1. 普通线性流程
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// 流程编码:simple_approval
|
||||||
|
// 特点:线性审批,一步一步进行
|
||||||
|
const taskVariables = {
|
||||||
|
// 基本业务数据即可
|
||||||
|
businessData: formData,
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 排他网关流程
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// 流程编码:exclusive_gateway
|
||||||
|
// 特点:根据条件选择不同审批分支
|
||||||
|
const taskVariables = {
|
||||||
|
amount: formData.amount, // 金额条件
|
||||||
|
urgentLevel: formData.urgent, // 紧急程度
|
||||||
|
applicantLevel: currentUser.level, // 申请人级别
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 并行网关流程
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// 流程编码:parallel_gateway
|
||||||
|
// 特点:多个分支并行执行
|
||||||
|
const taskVariables = {
|
||||||
|
parallelBranches: ['finance', 'hr', 'legal'], // 并行分支
|
||||||
|
businessData: formData,
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. 会签流程
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// 流程编码:countersign
|
||||||
|
// 特点:多人会签,所有人都需要审批
|
||||||
|
const taskVariables = {
|
||||||
|
userList: ['1', '3', '4', '5'], // 会签用户列表
|
||||||
|
signType: 'all', // all-全部同意 any-任一同意
|
||||||
|
businessData: formData,
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔒 权限配置规范
|
||||||
|
|
||||||
|
### 1. 菜单权限配置
|
||||||
|
|
||||||
|
在系统管理 → 菜单管理中配置:
|
||||||
|
|
||||||
|
```
|
||||||
|
父菜单:工作流管理
|
||||||
|
├── 业务模块管理
|
||||||
|
├── 菜单权限:workflow:业务模块:list
|
||||||
|
├── 按钮权限:
|
||||||
|
├── 新增:workflow:业务模块:add
|
||||||
|
├── 修改:workflow:业务模块:edit
|
||||||
|
├── 删除:workflow:业务模块:remove
|
||||||
|
├── 查询:workflow:业务模块:query
|
||||||
|
└── 导出:workflow:业务模块:export
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 工作流权限配置
|
||||||
|
|
||||||
|
```
|
||||||
|
工作流通用权限:
|
||||||
|
├── 任务管理:workflow:task:list
|
||||||
|
├── 实例管理:workflow:instance:list
|
||||||
|
├── 定义管理:workflow:definition:list
|
||||||
|
└── 审批权限:workflow:approval:handle
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ⚠️ 常见问题与解决方案
|
||||||
|
|
||||||
|
### 1. MyBatis 映射错误
|
||||||
|
|
||||||
|
**问题**: `Could not set property 'createBy'`
|
||||||
|
|
||||||
|
**解决**: 确保 VO 类包含完整的基础字段:
|
||||||
|
|
||||||
|
```java
|
||||||
|
// 🔴 必须包含的四个基础字段
|
||||||
|
private Long createBy;
|
||||||
|
private Date createTime;
|
||||||
|
private Long updateBy;
|
||||||
|
private Date updateTime;
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 工作流功能不显示
|
||||||
|
|
||||||
|
**问题**: 工作流相关功能无法使用
|
||||||
|
|
||||||
|
**检查清单**:
|
||||||
|
|
||||||
|
- [ ] 配置文件:`warm-flow.enabled=true`
|
||||||
|
- [ ] 类注解:`@ConditionalOnEnable`
|
||||||
|
- [ ] 权限注解:`@SaCheckPermission`
|
||||||
|
- [ ] 组件引入路径正确
|
||||||
|
|
||||||
|
### 3. 流程启动失败
|
||||||
|
|
||||||
|
**常见原因**:
|
||||||
|
|
||||||
|
- 流程定义未发布
|
||||||
|
- flowCode 不存在
|
||||||
|
- 业务数据状态非 'draft'
|
||||||
|
- 权限不足
|
||||||
|
|
||||||
|
### 4. 日期格式问题
|
||||||
|
|
||||||
|
**解决**: 统一使用标准格式
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<el-date-picker
|
||||||
|
v-model="dateRange"
|
||||||
|
type="daterange"
|
||||||
|
value-format="YYYY-MM-DD HH:mm:ss"
|
||||||
|
:default-time="[new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 1, 1, 23, 59, 59)]"
|
||||||
|
/>
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📝 代码生成模板
|
||||||
|
|
||||||
|
### 快速生成工作流业务模块
|
||||||
|
|
||||||
|
1. **数据库表**: 按照规范创建业务表
|
||||||
|
2. **后端代码**: 使用代码生成器,添加工作流注解
|
||||||
|
3. **前端代码**: 复制标准模板,修改业务字段
|
||||||
|
4. **权限配置**: 在菜单管理中配置权限
|
||||||
|
5. **流程定义**: 在流程设计器中创建流程
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📚 参考文档
|
||||||
|
|
||||||
|
- [Warm-Flow 工作流框架开发指南](../开发文档/warm-flow工作流框架开发指南.md)
|
||||||
|
- [API 开发最佳实践总结](../开发文档/API开发最佳实践总结.md)
|
||||||
|
- [请假工作流示例](../开发文档/API/请假工作流API.md)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**规范版本**: v1.0
|
||||||
|
**最后更新**: 2025-01-09
|
||||||
|
**适用范围**: 所有基于 warm-flow 的工作流开发任务
|
||||||
@@ -25,6 +25,7 @@
|
|||||||
├── cursorrules-frontend.md # 🎨 前端开发规范 (Vue 3)
|
├── cursorrules-frontend.md # 🎨 前端开发规范 (Vue 3)
|
||||||
├── cursorrules-backend.md # ⚙️ 后端开发规范 (Spring Boot)
|
├── cursorrules-backend.md # ⚙️ 后端开发规范 (Spring Boot)
|
||||||
├── cursorrules-mobile.md # 📱 移动端开发规范 (uniapp)
|
├── cursorrules-mobile.md # 📱 移动端开发规范 (uniapp)
|
||||||
|
├── cursorrules-workflow.md # 🔄 工作流开发规范 (Warm-Flow)
|
||||||
└── cursorrules-api-test.md # 🧪 API测试规范
|
└── cursorrules-api-test.md # 🧪 API测试规范
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -68,6 +69,15 @@
|
|||||||
- 智能缓存策略和网络请求优化
|
- 智能缓存策略和网络请求优化
|
||||||
- 多端发布支持(H5、微信小程序、App、鸿蒙)
|
- 多端发布支持(H5、微信小程序、App、鸿蒙)
|
||||||
|
|
||||||
|
#### 🔄 工作流开发规范 (.cursor/cursorrules-workflow.md)
|
||||||
|
- **Warm-Flow工作流框架** - 基于dromara社区开源的轻量级工作流引擎
|
||||||
|
- **🔴 强制性VO类规范(避免MyBatis映射错误)** - 所有工作流业务VO类必须包含四个基础字段
|
||||||
|
- **工作流状态管理** - 7种标准业务状态(draft、waiting、complete等)
|
||||||
|
- **标准工作流模式** - 普通流程、排他网关、并行网关、会签等6种模式
|
||||||
|
- **前端工作流组件** - approvalButton、submitVerify、approvalRecord标准组件使用
|
||||||
|
- **工作流权限配置** - @ConditionalOnEnable条件开启和Sa-Token权限控制
|
||||||
|
- **请假工作流示例** - 完整的工作流开发实践模板
|
||||||
|
|
||||||
#### 🧪 API测试规范 (.cursor/cursorrules-api-test.md)
|
#### 🧪 API测试规范 (.cursor/cursorrules-api-test.md)
|
||||||
- **✅ AES+RSA双重加密登录方法(已完全解决)**
|
- **✅ AES+RSA双重加密登录方法(已完全解决)**
|
||||||
- API测试最佳实践和通用测试方法
|
- API测试最佳实践和通用测试方法
|
||||||
@@ -139,6 +149,7 @@
|
|||||||
- **前端开发**: 自动参考 `cursorrules-frontend.md`
|
- **前端开发**: 自动参考 `cursorrules-frontend.md`
|
||||||
- **后端开发**: 自动参考 `cursorrules-backend.md`
|
- **后端开发**: 自动参考 `cursorrules-backend.md`
|
||||||
- **移动端开发**: 自动参考 `cursorrules-mobile.md`
|
- **移动端开发**: 自动参考 `cursorrules-mobile.md`
|
||||||
|
- **工作流开发**: 自动参考 `cursorrules-workflow.md`
|
||||||
- **文档更新**: 自动参考 `cursorrules-docs.md`
|
- **文档更新**: 自动参考 `cursorrules-docs.md`
|
||||||
- **API测试**: 自动参考 `cursorrules-api-test.md`
|
- **API测试**: 自动参考 `cursorrules-api-test.md`
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,286 @@
|
|||||||
|
# 项目变更记录 - 2025-01-09
|
||||||
|
|
||||||
|
**变更日期**: 2025-01-09
|
||||||
|
**操作人员**: wuzilong
|
||||||
|
**变更类型**: 工作流框架文档创建和规范整理
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📝 变更概述
|
||||||
|
|
||||||
|
基于项目中集成的 **warm-flow** 工作流框架和请假工作流示例,完成了工作流开发的完整文档体系建设和规范整理。通过深入分析 `backend/ruoyi-modules/ruoyi-workflow` 模块和前端工作流组件,总结形成了完整的开发指南和最佳实践。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📚 新增文档
|
||||||
|
|
||||||
|
### 1. 工作流框架开发指南
|
||||||
|
|
||||||
|
**文件**: `docs/开发文档/warm-flow工作流框架开发指南.md`
|
||||||
|
**描述**: 基于 warm-flow 工作流框架的完整开发指南
|
||||||
|
**内容要点**:
|
||||||
|
|
||||||
|
- 工作流框架概述和技术架构
|
||||||
|
- 核心组件详解(后端服务、前端组件)
|
||||||
|
- 完整的开发流程(6 个步骤)
|
||||||
|
- 请假工作流示例(6 种不同模式)
|
||||||
|
- 工作流状态管理(7 种标准状态)
|
||||||
|
- 最佳实践和常见问题解决
|
||||||
|
- 性能优化建议
|
||||||
|
|
||||||
|
### 2. 工作流开发规范
|
||||||
|
|
||||||
|
**文件**: `.cursor/cursorrules-workflow.md`
|
||||||
|
**描述**: 专门的工作流开发规范,整合到 cursorrules 体系
|
||||||
|
**内容要点**:
|
||||||
|
|
||||||
|
- 技术栈配置(warm-flow 依赖、配置开关)
|
||||||
|
- 🔴 强制性后端规范(VO 类基础字段、条件开启注解、权限控制)
|
||||||
|
- 🔴 强制性前端规范(页面结构、组件使用、API 接口)
|
||||||
|
- 工作流核心功能(流程启动、任务办理、流程撤销)
|
||||||
|
- 常用工作流模式(线性、排他网关、并行网关、会签)
|
||||||
|
- 权限配置规范
|
||||||
|
- 常见问题解决方案
|
||||||
|
|
||||||
|
### 3. 工作流开发最佳实践总结
|
||||||
|
|
||||||
|
**文件**: `docs/开发文档/Warm-Flow工作流开发最佳实践总结.md`
|
||||||
|
**描述**: 基于请假工作流实践的最佳实践总结
|
||||||
|
**内容要点**:
|
||||||
|
|
||||||
|
- 快速开始模板(标准项目结构、6 阶段开发流程)
|
||||||
|
- 核心要点总结(强制性规范、状态管理、常用模式)
|
||||||
|
- 开发效率统计(实际数据:3.5 天开发周期)
|
||||||
|
- 工具和辅助资源(代码生成器、测试脚本、组件库)
|
||||||
|
- 常见错误和解决方案
|
||||||
|
- 性能优化建议
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔧 规范文件更新
|
||||||
|
|
||||||
|
### 1. 主配置文件更新
|
||||||
|
|
||||||
|
**文件**: `.cursorrules`
|
||||||
|
**变更内容**:
|
||||||
|
|
||||||
|
- 在专门规范文件列表中添加 `cursorrules-workflow.md`
|
||||||
|
- 在规范文件详情中增加工作流开发规范说明
|
||||||
|
- 在 Cursor AI 规范应用中添加"工作流开发"场景
|
||||||
|
|
||||||
|
**具体变更**:
|
||||||
|
|
||||||
|
```diff
|
||||||
|
### 🔗 专门规范文件
|
||||||
|
.cursor/
|
||||||
|
├── cursorrules-docs.md # 📋 文档管理规范
|
||||||
|
├── cursorrules-frontend.md # 🎨 前端开发规范 (Vue 3)
|
||||||
|
├── cursorrules-backend.md # ⚙️ 后端开发规范 (Spring Boot)
|
||||||
|
├── cursorrules-mobile.md # 📱 移动端开发规范 (uniapp)
|
||||||
|
├── cursorrules-workflow.md # 🔄 工作流开发规范 (Warm-Flow)
|
||||||
|
└── cursorrules-api-test.md # 🧪 API测试规范
|
||||||
|
|
||||||
|
### 🤖 Cursor AI 规范应用
|
||||||
|
- **前端开发**: 自动参考 `cursorrules-frontend.md`
|
||||||
|
- **后端开发**: 自动参考 `cursorrules-backend.md`
|
||||||
|
- **移动端开发**: 自动参考 `cursorrules-mobile.md`
|
||||||
|
- **工作流开发**: 自动参考 `cursorrules-workflow.md`
|
||||||
|
- **文档更新**: 自动参考 `cursorrules-docs.md`
|
||||||
|
- **API测试**: 自动参考 `cursorrules-api-test.md`
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔍 技术分析过程
|
||||||
|
|
||||||
|
### 1. 代码库深度分析
|
||||||
|
|
||||||
|
通过 `codebase_search` 工具深入分析了以下组件:
|
||||||
|
|
||||||
|
**后端核心组件**:
|
||||||
|
|
||||||
|
- `org.dromara.workflow.config.WarmFlowConfig` - 工作流配置
|
||||||
|
- `org.dromara.workflow.common.ConditionalOnEnable` - 条件开启注解
|
||||||
|
- `org.dromara.workflow.listener.WorkflowGlobalListener` - 全局监听器
|
||||||
|
- `org.dromara.workflow.service.*` - 核心服务层(定义、实例、任务服务)
|
||||||
|
- `org.dromara.workflow.handler.*` - 事件处理和权限处理
|
||||||
|
- `org.dromara.workflow.controller.TestLeaveController` - 请假业务控制器
|
||||||
|
|
||||||
|
**前端核心组件**:
|
||||||
|
|
||||||
|
- `web/src/components/Process/approvalButton.vue` - 审批按钮组件
|
||||||
|
- `web/src/components/Process/submitVerify.vue` - 提交审批组件
|
||||||
|
- `web/src/components/Process/approvalRecord.vue` - 审批记录组件
|
||||||
|
- `web/src/views/workflow/leave/` - 请假工作流页面
|
||||||
|
- `web/src/api/workflow/` - 工作流 API 接口
|
||||||
|
|
||||||
|
### 2. 工作流架构梳理
|
||||||
|
|
||||||
|
通过分析确定了 warm-flow 的完整技术架构:
|
||||||
|
|
||||||
|
```
|
||||||
|
前端层 (Vue 3) → 后端层 (Spring Boot) → 服务层 (Service) → Warm-Flow 核心引擎
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 请假工作流示例分析
|
||||||
|
|
||||||
|
深入分析了请假工作流的完整实现:
|
||||||
|
|
||||||
|
- 6 种不同的工作流模式(leave1-leave6)
|
||||||
|
- 7 种标准业务状态流转
|
||||||
|
- 完整的前后端集成方案
|
||||||
|
- 权限控制和状态管理
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📊 关键发现和要点
|
||||||
|
|
||||||
|
### 1. 🔴 强制性规范(避免常见错误)
|
||||||
|
|
||||||
|
#### VO 类基础字段规范
|
||||||
|
|
||||||
|
**问题**: MyBatis 映射错误 `Could not set property 'createBy'`
|
||||||
|
**解决**: 所有工作流业务 VO 类必须包含四个基础字段:
|
||||||
|
|
||||||
|
```java
|
||||||
|
private Long createBy;
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
private Date createTime;
|
||||||
|
private Long updateBy;
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
private Date updateTime;
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 条件开启注解
|
||||||
|
|
||||||
|
**要求**: 所有工作流相关类必须添加 `@ConditionalOnEnable` 注解
|
||||||
|
**配置**: `warm-flow.enabled=true`
|
||||||
|
|
||||||
|
#### 权限注解
|
||||||
|
|
||||||
|
**要求**: 所有工作流接口必须添加 `@SaCheckPermission` 注解
|
||||||
|
|
||||||
|
### 2. 工作流状态管理体系
|
||||||
|
|
||||||
|
确定了 7 种标准业务状态:
|
||||||
|
|
||||||
|
- `draft` - 草稿
|
||||||
|
- `waiting` - 待审批
|
||||||
|
- `complete` - 已完成
|
||||||
|
- `cancel` - 已取消
|
||||||
|
- `back` - 已退回
|
||||||
|
- `invalid` - 已作废
|
||||||
|
- `terminate` - 已终止
|
||||||
|
|
||||||
|
### 3. 标准工作流模式
|
||||||
|
|
||||||
|
总结了 6 种常用工作流模式:
|
||||||
|
|
||||||
|
- 普通线性流程
|
||||||
|
- 排他网关流程(条件分支)
|
||||||
|
- 并行网关流程
|
||||||
|
- 会签流程
|
||||||
|
- 并行会签网关
|
||||||
|
- 排他并行会签
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎯 最佳实践总结
|
||||||
|
|
||||||
|
### 1. 标准开发流程(6 个阶段)
|
||||||
|
|
||||||
|
1. **需求分析和文档创建** → 业务需求+技术架构文档
|
||||||
|
2. **数据库设计和初始化** → 表结构+字典+权限+示例数据
|
||||||
|
3. **后端模块开发** → 完整 ruoyi 模块(16 个 API 接口)
|
||||||
|
4. **API 文档编写** → 400+行详细 API 文档
|
||||||
|
5. **自动化测试脚本** → 450+行 Python 测试脚本
|
||||||
|
6. **变更记录和验证** → 完整的变更日志
|
||||||
|
|
||||||
|
### 2. 开发效率数据
|
||||||
|
|
||||||
|
基于请假工作流的实际统计:
|
||||||
|
|
||||||
|
- **总开发时间**: 约 3.5 天
|
||||||
|
- **后端开发**: 1.5 天(完整 CRUD + 工作流集成)
|
||||||
|
- **前端开发**: 1 天(列表页 + 编辑页 + 工作流组件)
|
||||||
|
- **文档编写**: 0.5 天(API 文档 + 用户手册)
|
||||||
|
- **测试验证**: 0.5 天(功能测试 + 流程测试)
|
||||||
|
|
||||||
|
### 3. 质量保证标准
|
||||||
|
|
||||||
|
- ✅ **完整交付物**: 2 个需求文档+3 个 SQL 脚本+18 个代码文件+1 个 API 文档+1 个测试脚本
|
||||||
|
- ✅ **接口覆盖**: 16 个标准 API 接口
|
||||||
|
- ✅ **测试覆盖**: 100%接口功能测试
|
||||||
|
- ✅ **文档同步**: 代码完成立即更新文档
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔄 规范体系优化
|
||||||
|
|
||||||
|
### 1. 模块化规范管理
|
||||||
|
|
||||||
|
工作流规范整合到现有的模块化规范体系中:
|
||||||
|
|
||||||
|
- 独立的规范文件:`cursorrules-workflow.md`
|
||||||
|
- 与其他技术栈规范保持一致的结构
|
||||||
|
- 在主配置文件中统一管理和引用
|
||||||
|
|
||||||
|
### 2. Cursor AI 自动应用
|
||||||
|
|
||||||
|
配置了 Cursor AI 在工作流开发场景下自动应用相应规范:
|
||||||
|
|
||||||
|
- 识别工作流相关开发任务
|
||||||
|
- 自动参考 `cursorrules-workflow.md`
|
||||||
|
- 确保代码生成符合项目规范
|
||||||
|
|
||||||
|
### 3. 文档同步机制
|
||||||
|
|
||||||
|
建立了工作流开发的文档同步机制:
|
||||||
|
|
||||||
|
- 工作流变更必须同步更新 API 文档
|
||||||
|
- 新增工作流模块必须按标准创建文档
|
||||||
|
- 变更记录必须详细记录工作流相关修改
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📈 后续优化方向
|
||||||
|
|
||||||
|
### 1. 工作流扩展功能
|
||||||
|
|
||||||
|
- [ ] 自定义表单设计器
|
||||||
|
- [ ] 流程图可视化编辑
|
||||||
|
- [ ] 流程数据统计分析
|
||||||
|
- [ ] 移动端审批支持
|
||||||
|
|
||||||
|
### 2. 开发工具优化
|
||||||
|
|
||||||
|
- [ ] 工作流代码生成器
|
||||||
|
- [ ] 自动化测试框架
|
||||||
|
- [ ] 性能监控工具
|
||||||
|
- [ ] 文档自动生成
|
||||||
|
|
||||||
|
### 3. 最佳实践积累
|
||||||
|
|
||||||
|
- [ ] 更多业务场景模板
|
||||||
|
- [ ] 复杂流程设计模式
|
||||||
|
- [ ] 异常处理策略
|
||||||
|
- [ ] 用户体验优化
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📝 总结
|
||||||
|
|
||||||
|
本次变更完成了项目工作流开发的完整文档体系建设,为后续基于 warm-flow 框架的业务开发提供了:
|
||||||
|
|
||||||
|
1. **完整的开发指南** - 涵盖从框架介绍到具体实践的全流程
|
||||||
|
2. **标准化的开发规范** - 整合到 cursorrules 体系,确保 AI 代码生成质量
|
||||||
|
3. **实用的最佳实践** - 基于真实项目经验的模板和工具
|
||||||
|
4. **详细的问题解决方案** - 常见错误的预防和解决方法
|
||||||
|
|
||||||
|
通过本次文档建设,项目的工作流开发将更加标准化、高效化,为团队协作和项目质量保证奠定了坚实基础。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**变更完成时间**: 2025-01-09 17:30:00
|
||||||
|
**文档版本**: v1.0
|
||||||
|
**下次评审**: 根据实际使用情况优化
|
||||||
@@ -0,0 +1,642 @@
|
|||||||
|
# Warm-Flow 工作流开发最佳实践总结
|
||||||
|
|
||||||
|
## 📋 概述
|
||||||
|
|
||||||
|
本文档基于请假工作流的成功实践,总结了使用 Warm-Flow 工作流框架进行开发的最佳实践、常用模板和经验教训。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🚀 快速开始模板
|
||||||
|
|
||||||
|
### 1. 工作流业务模块标准结构
|
||||||
|
|
||||||
|
```
|
||||||
|
工作流业务模块/
|
||||||
|
├── 后端代码
|
||||||
|
│ ├── controller/ # 业务控制器(包含@ConditionalOnEnable)
|
||||||
|
│ ├── service/ # 业务服务层
|
||||||
|
│ ├── domain/ # 实体类(Bo、Vo、Entity)
|
||||||
|
│ └── mapper/ # 数据访问层
|
||||||
|
├── 前端代码
|
||||||
|
│ ├── api/ # API接口定义
|
||||||
|
│ ├── types/ # TypeScript类型定义
|
||||||
|
│ ├── views/ # 页面组件(列表页、编辑页)
|
||||||
|
│ └── components/ # 工作流通用组件
|
||||||
|
├── 数据库脚本
|
||||||
|
│ ├── 表结构.sql # 业务表创建
|
||||||
|
│ ├── 字典数据.sql # 状态字典配置
|
||||||
|
│ └── 权限配置.sql # 菜单权限数据
|
||||||
|
└── 流程定义
|
||||||
|
└── 流程图.json # Warm-Flow流程定义文件
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 标准开发流程(6 个阶段)
|
||||||
|
|
||||||
|
#### 阶段 1: 需求分析和设计
|
||||||
|
|
||||||
|
```
|
||||||
|
1. 业务需求文档 → docs/业务模块/[模块名]/需求分析/
|
||||||
|
2. 数据库设计文档 → docs/设计文档/database/
|
||||||
|
3. API接口设计 → docs/开发文档/API/
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 阶段 2: 数据库初始化
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- 标准业务表结构
|
||||||
|
CREATE TABLE wf_business_table (
|
||||||
|
id BIGINT(20) NOT NULL PRIMARY KEY,
|
||||||
|
-- 业务字段
|
||||||
|
business_field1 VARCHAR(100),
|
||||||
|
business_field2 VARCHAR(200),
|
||||||
|
|
||||||
|
-- 🔴 工作流状态字段(必需)
|
||||||
|
status VARCHAR(20) DEFAULT 'draft',
|
||||||
|
|
||||||
|
-- 🔴 标准基础字段(必需)
|
||||||
|
tenant_id VARCHAR(20) DEFAULT '000000',
|
||||||
|
create_dept BIGINT(20) DEFAULT NULL,
|
||||||
|
create_by BIGINT(20) DEFAULT NULL,
|
||||||
|
create_time DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
update_by BIGINT(20) DEFAULT NULL,
|
||||||
|
update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||||
|
deleted TINYINT(1) DEFAULT 0
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 阶段 3: 后端开发模板
|
||||||
|
|
||||||
|
```java
|
||||||
|
// 1. 实体类模板
|
||||||
|
@Data
|
||||||
|
@ExcelIgnoreUnannotated
|
||||||
|
public class BusinessVo {
|
||||||
|
// 业务字段
|
||||||
|
private Long id;
|
||||||
|
private String businessField;
|
||||||
|
private String status;
|
||||||
|
|
||||||
|
// 🔴 基础字段(必须包含,避免MyBatis映射错误)
|
||||||
|
private Long createBy;
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
private Date createTime;
|
||||||
|
private Long updateBy;
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
private Date updateTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Controller模板
|
||||||
|
@ConditionalOnEnable // 🔴 必须添加
|
||||||
|
@Validated
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/workflow/business")
|
||||||
|
public class BusinessController extends BaseController {
|
||||||
|
|
||||||
|
private final IBusinessService businessService;
|
||||||
|
|
||||||
|
@SaCheckPermission("workflow:business:list")
|
||||||
|
@GetMapping("/list")
|
||||||
|
public TableDataInfo<BusinessVo> list(BusinessBo bo, PageQuery pageQuery) {
|
||||||
|
return businessService.queryPageList(bo, pageQuery);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 其他CRUD接口...
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Service模板
|
||||||
|
@ConditionalOnEnable // 🔴 必须添加
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class BusinessServiceImpl implements IBusinessService {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public BusinessVo insertByBo(BusinessBo bo) {
|
||||||
|
Business entity = BeanUtil.toBean(bo, Business.class);
|
||||||
|
entity.setStatus("draft"); // 🔴 设置初始状态
|
||||||
|
validEntityBeforeSave(entity);
|
||||||
|
boolean flag = baseMapper.insert(entity) > 0;
|
||||||
|
if (flag) {
|
||||||
|
return BeanUtil.toBean(entity, BusinessVo.class);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 阶段 4: 前端开发模板
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<!-- 列表页面模板 -->
|
||||||
|
<template>
|
||||||
|
<div class="p-2">
|
||||||
|
<!-- 搜索表单 -->
|
||||||
|
<div v-show="showSearch" class="search">
|
||||||
|
<el-form ref="queryFormRef" :model="queryParams" :inline="true">
|
||||||
|
<!-- 搜索字段 -->
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
|
||||||
|
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 数据表格 -->
|
||||||
|
<el-card shadow="never">
|
||||||
|
<el-table v-loading="loading" border :data="dataList">
|
||||||
|
<!-- 业务字段 -->
|
||||||
|
|
||||||
|
<!-- 🔴 工作流状态列(必需) -->
|
||||||
|
<el-table-column label="流程状态" align="center">
|
||||||
|
<template #default="scope">
|
||||||
|
<dict-tag :options="wf_business_status" :value="scope.row.status" />
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
|
||||||
|
<!-- 🔴 操作列(根据状态显示不同按钮) -->
|
||||||
|
<el-table-column label="操作" align="center">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-button
|
||||||
|
v-if="['draft', 'cancel', 'back'].includes(scope.row.status)"
|
||||||
|
type="primary"
|
||||||
|
size="small"
|
||||||
|
@click="handleUpdate(scope.row)"
|
||||||
|
>
|
||||||
|
修改
|
||||||
|
</el-button>
|
||||||
|
<el-button type="primary" size="small" @click="handleView(scope.row)">
|
||||||
|
查看
|
||||||
|
</el-button>
|
||||||
|
<el-button
|
||||||
|
v-if="scope.row.status === 'waiting'"
|
||||||
|
size="small"
|
||||||
|
type="primary"
|
||||||
|
@click="handleCancel(scope.row.id)"
|
||||||
|
>
|
||||||
|
撤销
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</el-card>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
```
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<!-- 编辑页面模板 -->
|
||||||
|
<template>
|
||||||
|
<div class="p-2">
|
||||||
|
<!-- 🔴 1. 审批按钮组件(必需) -->
|
||||||
|
<el-card shadow="never">
|
||||||
|
<approvalButton
|
||||||
|
@submitForm="submitForm"
|
||||||
|
@approvalVerifyOpen="approvalVerifyOpen"
|
||||||
|
@handleApprovalRecord="handleApprovalRecord"
|
||||||
|
:buttonLoading="buttonLoading"
|
||||||
|
:id="form.id"
|
||||||
|
:status="form.status"
|
||||||
|
:pageType="routeParams.type"
|
||||||
|
/>
|
||||||
|
</el-card>
|
||||||
|
|
||||||
|
<!-- 2. 业务表单 -->
|
||||||
|
<el-card shadow="never">
|
||||||
|
<el-form ref="formRef" :model="form" :rules="rules">
|
||||||
|
<!-- 业务字段 -->
|
||||||
|
</el-form>
|
||||||
|
</el-card>
|
||||||
|
|
||||||
|
<!-- 🔴 3. 工作流组件(必需) -->
|
||||||
|
<submitVerify
|
||||||
|
ref="submitVerifyRef"
|
||||||
|
:task-variables="taskVariables"
|
||||||
|
@submit-callback="submitCallback"
|
||||||
|
/>
|
||||||
|
<approvalRecord ref="approvalRecordRef" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
// 🔴 必需的组件引入
|
||||||
|
import SubmitVerify from '@/components/Process/submitVerify.vue';
|
||||||
|
import ApprovalRecord from '@/components/Process/approvalRecord.vue';
|
||||||
|
import ApprovalButton from '@/components/Process/approvalButton.vue';
|
||||||
|
|
||||||
|
// 核心事件处理
|
||||||
|
const submitForm = async (status: string) => {
|
||||||
|
// 1. 表单验证
|
||||||
|
await formRef.value?.validate();
|
||||||
|
|
||||||
|
// 2. 保存业务数据
|
||||||
|
const res = form.value.id ? await updateBusiness(form.value) : await addBusiness(form.value);
|
||||||
|
|
||||||
|
// 3. 启动工作流
|
||||||
|
if (status === 'submit') {
|
||||||
|
await handleStartWorkFlow(res.data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleStartWorkFlow = async (data: any) => {
|
||||||
|
const submitFormData = {
|
||||||
|
flowCode: 'your_flow_code',
|
||||||
|
businessId: data.id,
|
||||||
|
variables: taskVariables.value,
|
||||||
|
};
|
||||||
|
|
||||||
|
const resp = await startWorkFlow(submitFormData);
|
||||||
|
submitVerifyRef.value.openDialog(resp.data.taskId);
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 阶段 5: API 接口文档
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// API类型定义模板
|
||||||
|
export interface BusinessForm extends BaseEntity {
|
||||||
|
id?: string | number;
|
||||||
|
businessField?: string;
|
||||||
|
status?: string; // 🔴 工作流状态字段
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface BusinessVO extends BaseEntity {
|
||||||
|
id?: string | number;
|
||||||
|
businessField?: string;
|
||||||
|
status?: string; // 🔴 工作流状态字段
|
||||||
|
}
|
||||||
|
|
||||||
|
// API接口定义模板
|
||||||
|
export const listBusiness = (query: BusinessQuery): AxiosPromise<BusinessVO[]> => {
|
||||||
|
return request({
|
||||||
|
url: '/workflow/business/list',
|
||||||
|
method: 'get',
|
||||||
|
params: query,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const addBusiness = (data: BusinessForm): AxiosPromise<BusinessVO> => {
|
||||||
|
return request({
|
||||||
|
url: '/workflow/business',
|
||||||
|
method: 'post',
|
||||||
|
data: data,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 阶段 6: 权限和流程配置
|
||||||
|
|
||||||
|
```
|
||||||
|
菜单权限配置:
|
||||||
|
├── 父菜单:工作流管理
|
||||||
|
├── 业务模块管理
|
||||||
|
├── 菜单权限:workflow:business:list
|
||||||
|
├── 按钮权限:
|
||||||
|
├── 新增:workflow:business:add
|
||||||
|
├── 修改:workflow:business:edit
|
||||||
|
├── 删除:workflow:business:remove
|
||||||
|
└── 查询:workflow:business:query
|
||||||
|
|
||||||
|
流程定义配置:
|
||||||
|
├── 流程编码:business_approval
|
||||||
|
├── 流程名称:业务审批流程
|
||||||
|
├── 流程变量:businessData、approvalLevel等
|
||||||
|
└── 审批节点:申请 → 审批 → 完成
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔍 核心要点总结
|
||||||
|
|
||||||
|
### 1. 🔴 强制性规范
|
||||||
|
|
||||||
|
#### VO 类基础字段(避免 MyBatis 映射错误)
|
||||||
|
|
||||||
|
```java
|
||||||
|
// 所有工作流业务VO类必须包含的四个基础字段
|
||||||
|
private Long createBy;
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
private Date createTime;
|
||||||
|
private Long updateBy;
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
private Date updateTime;
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 条件开启注解
|
||||||
|
|
||||||
|
```java
|
||||||
|
// 所有工作流相关类必须添加
|
||||||
|
@ConditionalOnEnable
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 权限注解
|
||||||
|
|
||||||
|
```java
|
||||||
|
// 所有接口必须添加权限检查
|
||||||
|
@SaCheckPermission("workflow:module:action")
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 工作流状态管理
|
||||||
|
|
||||||
|
#### 标准状态流转
|
||||||
|
|
||||||
|
```
|
||||||
|
draft(草稿) → waiting(待审批) → complete(已完成)
|
||||||
|
↓ ↓
|
||||||
|
cancel(已取消) back(已退回)
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 状态检查工具
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// 前端状态检查
|
||||||
|
const canEdit = computed(() => {
|
||||||
|
return ['draft', 'cancel', 'back'].includes(form.value.status);
|
||||||
|
});
|
||||||
|
|
||||||
|
const canCancel = computed(() => {
|
||||||
|
return form.value.status === 'waiting';
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 常用工作流模式
|
||||||
|
|
||||||
|
#### 普通线性流程
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const taskVariables = {
|
||||||
|
businessData: formData,
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 排他网关流程(条件分支)
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const taskVariables = {
|
||||||
|
amount: formData.amount, // 金额条件
|
||||||
|
urgentLevel: formData.urgent, // 紧急程度
|
||||||
|
applicantLevel: currentUser.level, // 申请人级别
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 会签流程
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const taskVariables = {
|
||||||
|
userList: ['1', '3', '4', '5'], // 会签用户列表
|
||||||
|
signType: 'all', // all-全部同意 any-任一同意
|
||||||
|
businessData: formData,
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📊 开发效率统计
|
||||||
|
|
||||||
|
### 基于请假工作流的实际数据
|
||||||
|
|
||||||
|
#### 开发周期
|
||||||
|
|
||||||
|
- **总开发时间**: 约 3.5 天
|
||||||
|
- **后端开发**: 1.5 天(包含完整 CRUD + 工作流集成)
|
||||||
|
- **前端开发**: 1 天(包含列表页 + 编辑页 + 工作流组件)
|
||||||
|
- **文档编写**: 0.5 天(API 文档 + 用户手册)
|
||||||
|
- **测试验证**: 0.5 天(功能测试 + 流程测试)
|
||||||
|
|
||||||
|
#### 交付物清单
|
||||||
|
|
||||||
|
- **后端代码**: 18 个文件(Controller、Service、Mapper、实体类等)
|
||||||
|
- **前端代码**: 6 个文件(页面组件、API 接口、类型定义)
|
||||||
|
- **数据库脚本**: 3 个 SQL 文件(表结构、字典数据、权限配置)
|
||||||
|
- **文档**: 1 个完整 API 文档(400+行)
|
||||||
|
- **测试脚本**: 1 个 Python 自动化测试脚本(450+行)
|
||||||
|
|
||||||
|
#### 代码质量指标
|
||||||
|
|
||||||
|
- **接口数量**: 16 个标准 API 接口
|
||||||
|
- **测试覆盖**: 100%接口功能测试
|
||||||
|
- **文档同步**: 代码完成即时更新文档
|
||||||
|
- **错误处理**: 完整的异常处理和用户提示
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🛠️ 工具和辅助资源
|
||||||
|
|
||||||
|
### 1. 代码生成器优化
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 使用若依代码生成器生成基础CRUD代码
|
||||||
|
# 然后手动添加工作流相关注解和逻辑
|
||||||
|
|
||||||
|
# 必须手动添加的内容:
|
||||||
|
# 1. @ConditionalOnEnable 注解
|
||||||
|
# 2. VO类基础字段
|
||||||
|
# 3. 工作流组件引入
|
||||||
|
# 4. 状态检查逻辑
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 测试脚本模板
|
||||||
|
|
||||||
|
```python
|
||||||
|
# 工作流业务模块测试脚本模板
|
||||||
|
import requests
|
||||||
|
import json
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
class WorkflowBusinessTest:
|
||||||
|
def __init__(self):
|
||||||
|
self.base_url = "http://localhost:8080"
|
||||||
|
self.token = None
|
||||||
|
|
||||||
|
def login(self):
|
||||||
|
"""AES+RSA双重加密登录"""
|
||||||
|
# 登录逻辑(参考 cursorrules-api-test.md)
|
||||||
|
|
||||||
|
def test_workflow_crud(self):
|
||||||
|
"""测试工作流业务CRUD操作"""
|
||||||
|
# 1. 新增(状态为draft)
|
||||||
|
# 2. 修改
|
||||||
|
# 3. 查询列表
|
||||||
|
# 4. 启动工作流
|
||||||
|
# 5. 审批处理
|
||||||
|
# 6. 撤销流程
|
||||||
|
# 7. 删除
|
||||||
|
|
||||||
|
def test_workflow_states(self):
|
||||||
|
"""测试工作流状态流转"""
|
||||||
|
# 测试各种状态下的可用操作
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 前端组件库
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// 工作流通用组件工具函数
|
||||||
|
export const workflowUtils = {
|
||||||
|
// 状态检查
|
||||||
|
canEdit: (status: string) => ['draft', 'cancel', 'back'].includes(status),
|
||||||
|
canCancel: (status: string) => status === 'waiting',
|
||||||
|
canApprove: (status: string) => status === 'waiting',
|
||||||
|
|
||||||
|
// 状态标签
|
||||||
|
getStatusTag: (status: string) => {
|
||||||
|
const statusMap = {
|
||||||
|
draft: { type: 'info', label: '草稿' },
|
||||||
|
waiting: { type: 'warning', label: '待审批' },
|
||||||
|
complete: { type: 'success', label: '已完成' },
|
||||||
|
cancel: { type: 'danger', label: '已取消' },
|
||||||
|
back: { type: 'danger', label: '已退回' },
|
||||||
|
};
|
||||||
|
return statusMap[status] || { type: 'info', label: '未知' };
|
||||||
|
},
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ❌ 常见错误和解决方案
|
||||||
|
|
||||||
|
### 1. MyBatis 映射错误
|
||||||
|
|
||||||
|
**错误**: `Could not set property 'createBy'`
|
||||||
|
|
||||||
|
**原因**: VO 类缺少基础字段,但 SQL 查询包含这些字段
|
||||||
|
|
||||||
|
**解决**:
|
||||||
|
|
||||||
|
```java
|
||||||
|
// 确保所有VO类包含四个基础字段
|
||||||
|
private Long createBy;
|
||||||
|
private Date createTime;
|
||||||
|
private Long updateBy;
|
||||||
|
private Date updateTime;
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 工作流组件不显示
|
||||||
|
|
||||||
|
**错误**: 审批按钮等组件不显示
|
||||||
|
|
||||||
|
**检查清单**:
|
||||||
|
|
||||||
|
- [ ] 配置文件:`warm-flow.enabled=true`
|
||||||
|
- [ ] 类注解:`@ConditionalOnEnable`
|
||||||
|
- [ ] 权限注解:`@SaCheckPermission`
|
||||||
|
- [ ] 组件引入路径正确
|
||||||
|
|
||||||
|
### 3. 流程启动失败
|
||||||
|
|
||||||
|
**常见原因**:
|
||||||
|
|
||||||
|
- 流程定义未发布
|
||||||
|
- flowCode 不存在
|
||||||
|
- 业务数据状态非 'draft'
|
||||||
|
- 权限不足
|
||||||
|
|
||||||
|
**解决**:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// 检查流程启动前置条件
|
||||||
|
if (form.value.status !== 'draft') {
|
||||||
|
proxy?.$modal.msgError('只能提交草稿状态的数据');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!flowCode.value) {
|
||||||
|
proxy?.$modal.msgError('请选择流程定义');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. 日期格式问题
|
||||||
|
|
||||||
|
**错误**: 前端日期格式与后端不匹配
|
||||||
|
|
||||||
|
**解决**:
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<!-- 统一使用标准格式 -->
|
||||||
|
<el-date-picker
|
||||||
|
v-model="dateRange"
|
||||||
|
type="daterange"
|
||||||
|
value-format="YYYY-MM-DD HH:mm:ss"
|
||||||
|
:default-time="[new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 1, 1, 23, 59, 59)]"
|
||||||
|
/>
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🚀 性能优化建议
|
||||||
|
|
||||||
|
### 1. 前端优化
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// 1. 组件懒加载
|
||||||
|
const SubmitVerify = defineAsyncComponent(() => import('@/components/Process/submitVerify.vue'));
|
||||||
|
|
||||||
|
// 2. 接口缓存
|
||||||
|
const { data: taskInfo } = useCachedRequest(() => getTask(taskId.value), {
|
||||||
|
cacheKey: `task_${taskId.value}`,
|
||||||
|
ttl: 5 * 60 * 1000, // 5分钟缓存
|
||||||
|
});
|
||||||
|
|
||||||
|
// 3. 状态计算优化
|
||||||
|
const statusActions = computed(() => {
|
||||||
|
const status = form.value.status;
|
||||||
|
return {
|
||||||
|
canEdit: ['draft', 'cancel', 'back'].includes(status),
|
||||||
|
canCancel: status === 'waiting',
|
||||||
|
canApprove: status === 'waiting',
|
||||||
|
};
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 后端优化
|
||||||
|
|
||||||
|
```java
|
||||||
|
// 1. 查询优化
|
||||||
|
@Select("SELECT * FROM business WHERE status = #{status} LIMIT #{limit}")
|
||||||
|
List<Business> selectByStatus(@Param("status") String status, @Param("limit") int limit);
|
||||||
|
|
||||||
|
// 2. 缓存使用
|
||||||
|
@Cacheable(value = "workflow", key = "#businessId")
|
||||||
|
public BusinessVo queryById(Long businessId) {
|
||||||
|
// 查询逻辑
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 批量操作
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public boolean batchUpdateStatus(List<Long> ids, String status) {
|
||||||
|
// 批量更新逻辑
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📈 后续优化方向
|
||||||
|
|
||||||
|
### 1. 工作流扩展功能
|
||||||
|
|
||||||
|
- [ ] 自定义表单设计器
|
||||||
|
- [ ] 流程图可视化编辑
|
||||||
|
- [ ] 流程数据统计分析
|
||||||
|
- [ ] 移动端审批支持
|
||||||
|
|
||||||
|
### 2. 开发工具优化
|
||||||
|
|
||||||
|
- [ ] 工作流代码生成器
|
||||||
|
- [ ] 自动化测试框架
|
||||||
|
- [ ] 性能监控工具
|
||||||
|
- [ ] 文档自动生成
|
||||||
|
|
||||||
|
### 3. 最佳实践积累
|
||||||
|
|
||||||
|
- [ ] 更多业务场景模板
|
||||||
|
- [ ] 复杂流程设计模式
|
||||||
|
- [ ] 异常处理策略
|
||||||
|
- [ ] 用户体验优化
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**文档维护**: 基于请假工作流实践总结
|
||||||
|
**最后更新**: 2025-01-09
|
||||||
|
**版本**: v1.0
|
||||||
File diff suppressed because it is too large.
Load diff
Reference in new issue
Block a user