- 新增工作流框架开发指南文档 (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天标准开发周期的高效开发流程
17 KiB
17 KiB
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: 数据库初始化
-- 标准业务表结构
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: 后端开发模板
// 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: 前端开发模板
<!-- 列表页面模板 -->
<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>
<!-- 编辑页面模板 -->
<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 接口文档
// 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 映射错误)
// 所有工作流业务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;
条件开启注解
// 所有工作流相关类必须添加
@ConditionalOnEnable
权限注解
// 所有接口必须添加权限检查
@SaCheckPermission("workflow:module:action")
2. 工作流状态管理
标准状态流转
draft(草稿) → waiting(待审批) → complete(已完成)
↓ ↓
cancel(已取消) back(已退回)
状态检查工具
// 前端状态检查
const canEdit = computed(() => {
return ['draft', 'cancel', 'back'].includes(form.value.status);
});
const canCancel = computed(() => {
return form.value.status === 'waiting';
});
3. 常用工作流模式
普通线性流程
const taskVariables = {
businessData: formData,
};
排他网关流程(条件分支)
const taskVariables = {
amount: formData.amount, // 金额条件
urgentLevel: formData.urgent, // 紧急程度
applicantLevel: currentUser.level, // 申请人级别
};
会签流程
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. 代码生成器优化
# 使用若依代码生成器生成基础CRUD代码
# 然后手动添加工作流相关注解和逻辑
# 必须手动添加的内容:
# 1. @ConditionalOnEnable 注解
# 2. VO类基础字段
# 3. 工作流组件引入
# 4. 状态检查逻辑
2. 测试脚本模板
# 工作流业务模块测试脚本模板
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. 前端组件库
// 工作流通用组件工具函数
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 查询包含这些字段
解决:
// 确保所有VO类包含四个基础字段
private Long createBy;
private Date createTime;
private Long updateBy;
private Date updateTime;
2. 工作流组件不显示
错误: 审批按钮等组件不显示
检查清单:
- 配置文件:
warm-flow.enabled=true - 类注解:
@ConditionalOnEnable - 权限注解:
@SaCheckPermission - 组件引入路径正确
3. 流程启动失败
常见原因:
- 流程定义未发布
- flowCode 不存在
- 业务数据状态非 'draft'
- 权限不足
解决:
// 检查流程启动前置条件
if (form.value.status !== 'draft') {
proxy?.$modal.msgError('只能提交草稿状态的数据');
return;
}
if (!flowCode.value) {
proxy?.$modal.msgError('请选择流程定义');
return;
}
4. 日期格式问题
错误: 前端日期格式与后端不匹配
解决:
<!-- 统一使用标准格式 -->
<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. 前端优化
// 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. 后端优化
// 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