- 新增工作流框架开发指南文档 (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天标准开发周期的高效开发流程
33 KiB
33 KiB
Warm-Flow 工作流框架开发指南
📋 目录
1. 工作流框架概述
1.1 框架介绍
本项目集成了 warm-flow 工作流框架,这是由 dromara 社区开源的轻量级工作流引擎,具有以下特点:
- 🚀 轻量级: 核心代码简洁,易于理解和扩展
- 🔧 可配置: 支持通过配置文件动态开启/关闭工作流功能
- 🎯 易集成: 与 Spring Boot 无缝集成,支持 MyBatis-Plus
- 📊 可视化: 内置流程设计器和流程图展示
- 🔐 权限控制: 集成 Sa-Token 权限认证
- 📧 消息通知: 支持站内信、邮件、短信通知
1.2 配置开关
工作流功能通过 @ConditionalOnEnable 注解控制,配置如下:
# application.yml
warm-flow:
enabled: true # 设置为 true 时,启用工作流功能
2. 技术架构
2.1 技术栈
┌─────────────────────────────────────────────────────────┐
│ 前端层 (Vue 3) │
├─────────────────────────────────────────────────────────┤
│ - approvalButton (审批按钮组件) │
│ - submitVerify (提交审批组件) │
│ - approvalRecord (审批记录组件) │
│ - flowChart (流程图组件) │
└─────────────────────────────────────────────────────────┘
│
┌─────────────────────────────────────────────────────────┐
│ 后端层 (Spring Boot) │
├─────────────────────────────────────────────────────────┤
│ - FlwTaskController (任务管理控制器) │
│ - FlwInstanceController (流程实例控制器) │
│ - FlwDefinitionController(流程定义控制器) │
│ - TestLeaveController (请假业务控制器) │
└─────────────────────────────────────────────────────────┘
│
┌─────────────────────────────────────────────────────────┐
│ 服务层 (Service) │
├─────────────────────────────────────────────────────────┤
│ - IFlwTaskService (任务服务) │
│ - IFlwInstanceService (实例服务) │
│ - IFlwDefinitionService (定义服务) │
│ - IFlwCommonService (通用服务) │
│ - ITestLeaveService (请假业务服务) │
└─────────────────────────────────────────────────────────┘
│
┌─────────────────────────────────────────────────────────┐
│ Warm-Flow 核心引擎 │
├─────────────────────────────────────────────────────────┤
│ - FlowEngine (工作流引擎) │
│ - DefService (流程定义服务) │
│ - InsService (流程实例服务) │
│ - TaskService (任务服务) │
│ - NodeService (节点服务) │
│ - HisTaskService (历史任务服务) │
└─────────────────────────────────────────────────────────┘
2.2 数据库表结构
warm-flow 使用以下核心表:
-- 流程定义表
flow_definition -- 存储流程定义信息
flow_node -- 存储流程节点信息
flow_skip -- 存储节点间跳转关系
-- 流程实例表
flow_instance -- 存储流程实例信息
flow_task -- 存储当前待办任务
flow_his_task -- 存储历史任务记录
-- 扩展表
flow_category -- 流程分类表
flow_copy -- 抄送表
3. 核心组件
3.1 后端核心服务
3.1.1 流程定义服务 (IFlwDefinitionService)
public interface IFlwDefinitionService {
// 查询流程定义列表
TableDataInfo<FlowDefinitionVo> queryList(FlowDefinition flowDefinition, PageQuery pageQuery);
// 发布流程定义
boolean publish(Long id);
// 导入流程定义
boolean importJson(MultipartFile file, String category);
// 删除流程定义
boolean removeDef(List<Long> ids);
}
3.1.2 流程实例服务 (IFlwInstanceService)
public interface IFlwInstanceService {
// 查询运行中的流程实例
TableDataInfo<FlowInstanceVo> selectRunningInstanceList(FlowInstanceBo bo, PageQuery pageQuery);
// 查询已结束的流程实例
TableDataInfo<FlowInstanceVo> selectFinishInstanceList(FlowInstanceBo bo, PageQuery pageQuery);
// 撤销流程
boolean cancelProcessApply(FlowCancelBo bo);
// 作废流程
boolean invalid(FlowInvalidBo bo);
}
3.1.3 任务服务 (IFlwTaskService)
public interface IFlwTaskService {
// 启动工作流
StartProcessReturnDTO startWorkFlow(StartProcessBo startProcessBo);
// 办理任务
boolean completeTask(CompleteTaskBo completeTaskBo);
// 查询待办任务
TableDataInfo<FlowTaskVo> pageByTaskWait(FlowTaskBo flowTaskBo, PageQuery pageQuery);
// 查询已办任务
TableDataInfo<FlowHisTaskVo> pageByTaskFinish(FlowTaskBo flowTaskBo, PageQuery pageQuery);
}
3.2 前端核心组件
3.2.1 审批按钮组件 (approvalButton.vue)
<template>
<div style="display: flex; justify-content: space-between">
<div>
<el-button
v-if="submitButtonShow"
:loading="buttonLoading"
type="info"
@click="submitForm('draft')"
>
暂存
</el-button>
<el-button
v-if="submitButtonShow"
:loading="buttonLoading"
type="primary"
@click="submitForm('submit')"
>
提 交
</el-button>
<el-button
v-if="approvalButtonShow"
:loading="buttonLoading"
type="primary"
@click="approvalVerifyOpen"
>
审批
</el-button>
<el-button v-if="id && status !== 'draft'" type="primary" @click="handleApprovalRecord">
流程进度
</el-button>
</div>
<div>
<el-button style="float: right" @click="goBack()">返回</el-button>
</div>
</div>
</template>
功能特点:
- 根据页面类型和流程状态动态显示按钮
- 支持暂存、提交、审批、查看流程进度等操作
- 自动处理按钮的显示/隐藏逻辑
3.2.2 提交审批组件 (submitVerify.vue)
<!-- 核心功能 -->
<el-form-item label="消息提醒">
<el-checkbox-group v-model="form.messageType">
<el-checkbox value="1" disabled>站内信</el-checkbox>
<el-checkbox value="2">邮件</el-checkbox>
<el-checkbox value="3">短信</el-checkbox>
</el-checkbox-group>
</el-form-item>
<el-form-item label="下一步审批人" v-if="nestNodeList?.length > 0">
<div v-for="item in nestNodeList" :key="item.nodeCode">
<span>【{{ item.nodeName }}】:</span>
<el-input placeholder="请选择审批人" readonly v-model="nickName[item.nodeCode]">
<template v-slot:append>
<el-button @click="choosePeople(item)" icon="search">选择</el-button>
</template>
</el-input>
</div>
</el-form-item>
功能特点:
- 支持消息通知配置(站内信、邮件、短信)
- 支持附件上传
- 支持抄送人员选择
- 支持下一步审批人选择
- 支持审批意见填写
- 支持多种操作:提交、委托、转办、加签、减签、终止、退回
3.2.3 审批记录组件 (approvalRecord.vue)
<el-tabs v-model="tabActiveName">
<el-tab-pane label="流程图" name="image">
<flowChart :ins-id="insId" v-if="insId" />
</el-tab-pane>
<el-tab-pane label="审批信息" name="info">
<el-table :data="historyList" border>
<el-table-column prop="nodeName" label="任务名称" />
<el-table-column prop="approveName" label="办理人" />
<el-table-column prop="flowStatus" label="状态" />
<el-table-column prop="message" label="审批意见" />
<el-table-column prop="createTime" label="开始时间" />
<el-table-column prop="updateTime" label="结束时间" />
</el-table>
</el-tab-pane>
</el-tabs>
功能特点:
- 流程图可视化展示
- 详细的审批记录表格
- 支持附件下载
- 审批时长统计
4. 工作流开发流程
4.1 后端开发步骤
步骤 1: 创建业务实体
// 1. 创建业务Bo类
@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;
}
// 2. 创建业务Vo类
@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;
}
步骤 2: 创建 Service 接口和实现
// Service接口
public interface ITestLeaveService {
TestLeaveVo queryById(Long id);
TableDataInfo<TestLeaveVo> queryPageList(TestLeaveBo bo, PageQuery pageQuery);
List<TestLeaveVo> queryList(TestLeaveBo bo);
TestLeaveVo insertByBo(TestLeaveBo bo);
TestLeaveVo updateByBo(TestLeaveBo bo);
Boolean deleteWithValidByIds(List<Long> ids);
}
// Service实现类
@Service
@RequiredArgsConstructor
public class TestLeaveServiceImpl implements ITestLeaveService {
private final TestLeaveMapper baseMapper;
@Override
public TestLeaveVo insertByBo(TestLeaveBo bo) {
TestLeave add = BeanUtil.toBean(bo, TestLeave.class);
// 设置默认状态为草稿
add.setStatus("draft");
validEntityBeforeSave(add);
boolean flag = baseMapper.insert(add) > 0;
if (flag) {
bo.setId(add.getId());
return BeanUtil.toBean(add, TestLeaveVo.class);
}
return null;
}
// 其他CRUD方法实现...
}
步骤 3: 创建 Controller
@ConditionalOnEnable // 工作流条件开启注解
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/workflow/leave")
public class TestLeaveController extends BaseController {
private final ITestLeaveService testLeaveService;
@SaCheckPermission("workflow:leave:list")
@GetMapping("/list")
public TableDataInfo<TestLeaveVo> list(TestLeaveBo bo, PageQuery pageQuery) {
return testLeaveService.queryPageList(bo, pageQuery);
}
@SaCheckPermission("workflow:leave:add")
@PostMapping()
public R<TestLeaveVo> add(@Validated(AddGroup.class) @RequestBody TestLeaveBo bo) {
return R.ok(testLeaveService.insertByBo(bo));
}
@SaCheckPermission("workflow:leave:edit")
@PutMapping()
public R<TestLeaveVo> edit(@Validated(EditGroup.class) @RequestBody TestLeaveBo bo) {
return R.ok(testLeaveService.updateByBo(bo));
}
// 其他CRUD接口...
}
4.2 前端开发步骤
步骤 1: 创建 API 接口
// api/workflow/leave/types.ts
export interface LeaveForm extends BaseEntity {
id?: string | number;
leaveType?: string;
startDate?: string;
endDate?: string;
leaveDays?: number;
remark?: string;
status?: string;
}
export interface LeaveVO extends BaseEntity {
id?: string | number;
leaveType?: string;
startDate?: string;
endDate?: string;
leaveDays?: number;
remark?: string;
status?: string;
}
// api/workflow/leave/index.ts
export const listLeave = (query: LeaveQuery): AxiosPromise<LeaveVO[]> => {
return request({
url: '/workflow/leave/list',
method: 'get',
params: query,
});
};
export const addLeave = (data: LeaveForm): AxiosPromise<LeaveVO> => {
return request({
url: '/workflow/leave',
method: 'post',
data: data,
});
};
步骤 2: 创建列表页面
<!-- views/workflow/leave/index.vue -->
<template>
<div class="p-2">
<!-- 搜索表单 -->
<div v-show="showSearch" class="search">
<el-form ref="queryFormRef" :model="queryParams" :inline="true">
<el-form-item label="请假天数" prop="startLeaveDays">
<el-input v-model="queryParams.startLeaveDays" placeholder="请输入请假天数" />
</el-form-item>
<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">
<template #header>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
v-hasPermi="['workflow:leave:add']"
type="primary"
plain
icon="Plus"
@click="handleAdd"
>
新增
</el-button>
</el-col>
</el-row>
</template>
<el-table v-loading="loading" border :data="leaveList">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="请假类型" align="center">
<template #default="scope">
<el-tag>{{ getLeaveTypeLabel(scope.row.leaveType) }}</el-tag>
</template>
</el-table-column>
<el-table-column label="请假天数" align="center" prop="leaveDays" />
<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"
icon="Edit"
@click="handleUpdate(scope.row)"
>
修改
</el-button>
<el-button
type="primary"
size="small"
icon="View"
@click="handleView(scope.row)"
>
查看
</el-button>
<el-button
v-if="scope.row.status === 'waiting'"
size="small"
type="primary"
icon="Notification"
@click="handleCancel(scope.row.id)"
>
撤销
</el-button>
</template>
</el-table-column>
</el-table>
</el-card>
</div>
</template>
<script setup lang="ts">
import { listLeave, delLeave } from '@/api/workflow/leave';
import { cancelProcessApply } from '@/api/workflow/instance';
// 组件逻辑...
</script>
步骤 3: 创建编辑页面
<!-- views/workflow/leave/leaveEdit.vue -->
<template>
<div class="p-2">
<!-- 审批按钮 -->
<el-card shadow="never">
<approvalButton
@submitForm="submitForm"
@approvalVerifyOpen="approvalVerifyOpen"
@handleApprovalRecord="handleApprovalRecord"
:buttonLoading="buttonLoading"
:id="form.id"
:status="form.status"
:pageType="routeParams.type"
/>
</el-card>
<!-- 表单内容 -->
<el-card shadow="never">
<el-form ref="leaveFormRef" :model="form" :rules="rules" label-width="80px">
<el-form-item label="请假类型" prop="leaveType">
<el-select v-model="form.leaveType" placeholder="请选择请假类型">
<el-option
v-for="item in options"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item label="请假时间" required>
<el-date-picker
v-model="leaveTime"
type="daterange"
value-format="YYYY-MM-DD HH:mm:ss"
@change="changeLeaveTime()"
/>
</el-form-item>
<el-form-item label="请假天数" prop="leaveDays">
<el-input v-model="form.leaveDays" disabled type="number" />
</el-form-item>
<el-form-item label="请假原因" prop="remark">
<el-input v-model="form.remark" type="textarea" :rows="3" />
</el-form-item>
</el-form>
</el-card>
<!-- 工作流组件 -->
<submitVerify
ref="submitVerifyRef"
:task-variables="taskVariables"
@submit-callback="submitCallback"
/>
<approvalRecord ref="approvalRecordRef" />
<!-- 流程选择对话框 -->
<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 { addLeave, getLeave, updateLeave } from '@/api/workflow/leave';
import { startWorkFlow } from '@/api/workflow/task';
import SubmitVerify from '@/components/Process/submitVerify.vue';
import ApprovalRecord from '@/components/Process/approvalRecord.vue';
import ApprovalButton from '@/components/Process/approvalButton.vue';
// 流程定义选项
const flowCodeOptions = [
{ value: 'leave1', label: '请假申请-普通' },
{ value: 'leave2', label: '请假申请-排他网关' },
{ value: 'leave3', label: '请假申请-并行网关' },
{ value: 'leave4', label: '请假申请-会签' },
{ value: 'leave5', label: '请假申请-并行会签网关' },
{ value: 'leave6', label: '请假申请-排他并行会签' },
];
// 提交表单
const submitForm = async (status: string) => {
// 验证表单
await leaveFormRef.value?.validate();
// 保存业务数据
let res;
if (form.value.id) {
res = await updateLeave(form.value);
} else {
res = await addLeave(form.value);
}
// 如果是暂存,直接返回
if (status === 'draft') {
proxy?.$modal.msgSuccess('暂存成功');
return;
}
// 如果是提交,启动工作流
if (!flowCode.value) {
dialogVisible.visible = true;
return;
}
await handleStartWorkFlow(res.data);
};
// 启动工作流
const handleStartWorkFlow = async (data: LeaveForm) => {
const submitFormData = {
flowCode: flowCode.value,
businessId: data.id,
variables: {
leaveDays: data.leaveDays,
userList: ['1', '3', '4'], // 会签用户列表
},
};
const resp = await startWorkFlow(submitFormData);
submitVerifyRef.value.openDialog(resp.data.taskId);
};
</script>
5. 请假工作流示例
5.1 工作流模式
系统提供 6 种不同的工作流模式:
| 流程编码 | 流程名称 | 特点说明 |
|---|---|---|
| leave1 | 请假申请-普通 | 简单的线性审批流程 |
| leave2 | 请假申请-排他网关 | 根据条件选择不同分支 |
| leave3 | 请假申请-并行网关 | 多个分支并行执行 |
| leave4 | 请假申请-会签 | 多人会签,所有人都需审批 |
| leave5 | 请假申请-并行会签网关 | 并行网关+会签组合 |
| leave6 | 请假申请-排他并行会签 | 排他网关+并行会签组合 |
5.2 流程变量
// 工作流变量配置
const taskVariables = {
// leave2/6 使用的流程变量(排他网关条件判断)
leaveDays: data.leaveDays,
// leave4/5 使用的流程变量(会签用户列表)
userList: ['1', '3', '4'],
};
5.3 状态流转
draft(草稿) → waiting(待审批) → complete(已完成)
↓ ↓
cancel(已取消) back(已退回)
6. 前端组件使用
6.1 工作流页面模板
<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>
import SubmitVerify from '@/components/Process/submitVerify.vue';
import ApprovalRecord from '@/components/Process/approvalRecord.vue';
import ApprovalButton from '@/components/Process/approvalButton.vue';
// 必需的ref引用
const submitVerifyRef = ref();
const approvalRecordRef = ref();
// 必需的事件处理
const submitForm = (status) => {
/* 提交表单逻辑 */
};
const approvalVerifyOpen = () => {
/* 打开审批窗口 */
};
const handleApprovalRecord = () => {
/* 查看审批记录 */
};
const submitCallback = () => {
/* 提交回调 */
};
</script>
6.2 路由跳转工具
// 使用工作流通用路由跳转
import workflowCommon from '@/api/workflow/workflowCommon';
const handleOpen = (row: FlowTaskVO) => {
const routerJumpVo = {
businessId: row.businessId,
taskId: row.id,
type: 'approval', // add/update/view/approval
formCustom: row.formCustom,
formPath: row.formPath,
};
workflowCommon.routerJump(routerJumpVo, proxy);
};
7. 工作流状态管理
7.1 业务状态
| 状态值 | 状态名称 | 说明 | 可用操作 |
|---|---|---|---|
| draft | 草稿 | 新建但未提交 | 编辑、删除、提交 |
| waiting | 待审批 | 流程进行中 | 查看、撤销 |
| complete | 已完成 | 流程正常结束 | 查看 |
| cancel | 已取消 | 申请人撤销 | 编辑、删除、重新提交 |
| back | 已退回 | 审批人退回 | 编辑、删除、重新提交 |
| invalid | 已作废 | 管理员作废 | 查看 |
| terminate | 已终止 | 流程异常终止 | 查看 |
7.2 任务状态
| 状态值 | 状态名称 | 说明 |
|---|---|---|
| waiting | 待办 | 等待当前用户处理 |
| complete | 已办 | 当前用户已处理 |
| reject | 已拒绝 | 当前用户拒绝 |
| delegate | 已委托 | 当前用户委托他人 |
| transfer | 已转办 | 当前用户转办他人 |
7.3 状态检查工具
// 前端状态检查
const canEdit = computed(() => {
return ['draft', 'cancel', 'back'].includes(form.value.status);
});
const canCancel = computed(() => {
return form.value.status === 'waiting';
});
const showApprovalButton = computed(() => {
return routeParams.value.type === 'approval' && form.value.status === 'waiting';
});
8. 最佳实践
8.1 后端开发最佳实践
1. VO 类基础字段规范
// 所有工作流业务VO类必须包含统一基础字段
public class TestLeaveVo {
// 业务字段
private Long id;
private String leaveType;
// ...其他业务字段
// 基础字段(必须包含,避免MyBatis映射错误)
private Long createBy;
private Date createTime;
private Long updateBy;
private Date updateTime;
}
2. 权限注解规范
// 所有工作流接口必须添加权限检查
@SaCheckPermission("workflow:leave:list")
@GetMapping("/list")
public TableDataInfo<TestLeaveVo> list(TestLeaveBo bo, PageQuery pageQuery) {
return testLeaveService.queryPageList(bo, pageQuery);
}
3. 条件开启注解
// 所有工作流相关类必须添加条件开启注解
@ConditionalOnEnable
@Service
public class TestLeaveServiceImpl implements ITestLeaveService {
// 实现逻辑
}
4. 事务管理
// 涉及业务数据和工作流数据的操作需要事务保证
@Transactional(rollbackFor = Exception.class)
public TestLeaveVo insertByBo(TestLeaveBo bo) {
// 1. 保存业务数据
TestLeave entity = BeanUtil.toBean(bo, TestLeave.class);
entity.setStatus("draft");
baseMapper.insert(entity);
// 2. 如果需要同时操作工作流数据,确保在同一事务中
return BeanUtil.toBean(entity, TestLeaveVo.class);
}
8.2 前端开发最佳实践
1. 组件引入规范
<script setup>
// 工作流组件统一引入
import SubmitVerify from '@/components/Process/submitVerify.vue';
import ApprovalRecord from '@/components/Process/approvalRecord.vue';
import ApprovalButton from '@/components/Process/approvalButton.vue';
// API接口引入
import { addLeave, getLeave, updateLeave } from '@/api/workflow/leave';
import { startWorkFlow } from '@/api/workflow/task';
</script>
2. 表单验证规范
// 工作流表单必须包含的验证规则
const rules = {
// 业务字段验证
leaveType: [{ required: true, message: '请假类型不能为空', trigger: 'blur' }],
leaveDays: [{ required: true, message: '请假天数不能为空', trigger: 'blur' }],
// 如果有时间范围,需要自定义验证
leaveTime: [{ required: true, message: '请假时间不能为空', trigger: 'blur' }],
};
3. 错误处理规范
// 提交表单错误处理
const submitForm = async (status: string) => {
try {
// 表单验证
await leaveFormRef.value?.validate();
// 业务数据保存
buttonLoading.value = true;
const res = form.value.id ? await updateLeave(form.value) : await addLeave(form.value);
// 工作流处理
if (status === 'submit') {
await handleStartWorkFlow(res.data);
}
} catch (error) {
console.error('提交失败:', error);
proxy?.$modal.msgError('操作失败,请重试');
} finally {
buttonLoading.value = false;
}
};
8.3 性能优化
1. 组件懒加载
// 工作流组件按需加载
const SubmitVerify = defineAsyncComponent(() => import('@/components/Process/submitVerify.vue'));
const ApprovalRecord = defineAsyncComponent(() =>
import('@/components/Process/approvalRecord.vue'),
);
2. 接口优化
// 避免重复请求,使用缓存
const { data: taskInfo, loading } = useCachedRequest(() => getTask(taskId.value), {
cacheKey: `task_${taskId.value}`,
ttl: 5 * 60 * 1000, // 5分钟缓存
});
9. 常见问题
9.1 MyBatis 映射错误
问题: Could not set property 'createBy'
原因: VO 类缺少基础字段,但 SQL 查询包含这些字段
解决: 确保所有 VO 类包含统一的基础字段
// 正确的VO类定义
public class TestLeaveVo {
// 业务字段
private Long id;
private String leaveType;
// 必须包含的基础字段
private Long createBy;
private Date createTime;
private Long updateBy;
private Date updateTime;
}
9.2 工作流组件不显示
问题: 审批按钮或其他工作流组件不显示
原因:
- 没有添加
@ConditionalOnEnable注解 - 配置文件中
warm-flow.enabled=false - 组件引入路径错误
解决:
# 确保配置正确
warm-flow:
enabled: true
// 确保添加条件注解
@ConditionalOnEnable
@RestController
public class TestLeaveController {
// 控制器逻辑
}
9.3 权限问题
问题: 接口访问被拒绝
原因: 缺少权限注解或权限配置不正确
解决:
- 添加权限注解:
@SaCheckPermission("workflow:leave:list") - 在菜单管理中配置对应的权限标识
- 为用户角色分配相应权限
9.4 流程启动失败
问题: 启动工作流时报错
原因:
- 流程定义未发布
- 流程编码不存在
- 业务数据状态不正确
解决:
- 检查流程定义是否已发布
- 确认
flowCode参数正确 - 确保业务数据状态为
draft
9.5 日期格式问题
问题: 日期选择器数据格式不匹配
原因: 前端日期格式与后端不一致
解决:
<!-- 统一使用标准格式 -->
<el-date-picker
v-model="leaveTime"
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)]"
/>
10. 总结
warm-flow 工作流框架为本项目提供了完整的工作流解决方案,具有以下优势:
- 轻量级: 核心简洁,易于理解和维护
- 可扩展: 支持自定义业务逻辑和权限控制
- 可视化: 内置流程设计器和流程图展示
- 完整性: 提供完整的前后端组件和示例
通过请假工作流示例,开发者可以快速掌握工作流开发的完整流程,并应用到其他业务场景中。
文档维护: 本文档随项目发展持续更新
最后更新: 2025-01-09
版本: v1.0