tasks.md 32 KB

任务拆分 — 流程模型版本管理功能

拆分顺序:数据模型 → 接口协议 → 底层实现 → 上层编排 → 入口层 每个任务 = 可独立提交的原子变更(3-5 个文件) 每个任务必须精确到文件路径和函数签名

任务概览

任务编号 任务名称 优先级 预估工作量 依赖
Task 1 数据库表结构变更 P0 1h
Task 2 FlowModel 实体修改 P0 0.5h Task 1
Task 3 FlowModelVersion 实体创建 P0 0.5h Task 1
Task 4 字典数据新增 P1 0.5h
Task 5 FlowModelVersionMapper 创建 P0 1h Task 3
Task 6 版本相关 DTO/VO 创建 P1 1h Task 3
Task 7 FlowModelVersionService 创建 P0 3h Task 5, Task 6
Task 8 FlowModelServiceImpl 修改 P0 2h Task 7
Task 9 FlowModelVersionController 创建 P0 2h Task 7
Task 10 前端 API 接口创建 P1 1h Task 9
Task 11 前端版本历史组件创建 P1 3h Task 10
Task 12 前端版本对比组件创建 P1 4h Task 10, Task 11
Task 13 前端 model.vue 修改 P0 2h Task 11
Task 14 权限配置和菜单新增 P1 1h Task 9

总预估工作量:22h(约 3 个工作日)


前置条件

  • Flowable 流程引擎已正常部署和运行
  • 系统菜单管理功能正常可用
  • 字典管理功能正常可用
  • 权限管理功能正常可用(Sa-Token)
  • 前端 BPMN 设计器组件可用(bpmn-js)

Task 1: 数据库表结构变更

目标

创建版本历史表 sys_flow_model_version,修改模型表新增重要性等级字段

涉及文件

  • forge/forge-admin-server/src/main/resources/sql/flow_version_init.sql — 新增,创建表和修改表结构
  • forge/forge-admin-server/src/main/resources/sql/forge.sql — 修改,合并 SQL 脚本到初始化脚本

关键签名

-- 新增版本历史表
CREATE TABLE `sys_flow_model_version` (
  `id` VARCHAR(64) PRIMARY KEY COMMENT '主键',
  `model_id` VARCHAR(64) NOT NULL COMMENT '模型ID',
  `version` INT NOT NULL COMMENT '版本号',
  `version_name` VARCHAR(100) NOT NULL COMMENT '版本名称',
  `version_tag` VARCHAR(20) NOT NULL DEFAULT 'draft' COMMENT '版本标记',
  `bpmn_xml` TEXT NOT NULL COMMENT 'BPMN XML',
  `form_json` TEXT COMMENT '表单配置',
  `change_description` VARCHAR(500) COMMENT '变更说明',
  `deployment_id` VARCHAR(64) COMMENT '部署ID',
  `process_definition_id` VARCHAR(64) COMMENT '流程定义ID',
  `publish_by` VARCHAR(64) NOT NULL COMMENT '发布人',
  `publish_time` DATETIME NOT NULL COMMENT '发布时间',
  `tenant_id` BIGINT NOT NULL DEFAULT 1 COMMENT '租户ID',
  `create_time` DATETIME NOT NULL COMMENT '创建时间',
  `del_flag` INT NOT NULL DEFAULT 0 COMMENT '删除标志',
  UNIQUE KEY `uk_model_version` (`model_id`, `version`),
  INDEX `idx_model_id` (`model_id`)
) ENGINE=InnoDB CHARSET=utf8mb4 COMMENT='流程模型版本历史表';

-- 修改模型表新增重要性等级字段
ALTER TABLE `sys_flow_model` 
ADD COLUMN `importance_level` INT NOT NULL DEFAULT 1 COMMENT '重要性等级(1-普通/2-重要)' AFTER `status`;

执行步骤

  1. ✅ 创建 SQL 脚本文件(flow_version_init.sql)
  2. ✅ SQL 包含:版本历史表创建、FlowModel 表字段新增、字典数据新增
  3. ⏭️ 合并到 forge.sql 初始化脚本(暂不需要,增量脚本独立维护)

验证要点

  • ✅ 表结构创建 SQL 正确,索引和约束完整
  • ✅ FlowModel 表新增字段 SQL 正确
  • ✅ 字典数据 INSERT 语句字段完整
  • ✅ SQL 文件创建成功(71 行,5.4KB)

Task 2: FlowModel 实体修改

目标

修改 FlowModel 实体类,新增 importanceLevel 字段

涉及文件

  • forge/forge-framework/forge-plugin-parent/forge-plugin-flow/src/main/java/com/mdframe/forge/starter/flow/entity/FlowModel.java — 修改,新增字段

关键签名

/**
 * 重要性等级(1-普通/2-重要)
 */
private Integer importanceLevel;

执行步骤

  1. ✅ 在 FlowModel 实体类新增 importanceLevel 字段(在 status 字段之后)
  2. ✅ 字段类型为 Integer,默认值由数据库字段 DEFAULT 1 控制
  3. ✅ 编译验证通过

验证要点

  • ✅ 实体类编译成功(Maven BUILD SUCCESS)
  • ✅ 字段定义正确(importanceLevel: Integer)
  • ✅ 字段位置正确(在 status 字段之后)

Task 3: FlowModelVersion 实体创建

目标

创建 FlowModelVersion 实体类,映射 sys_flow_model_version 表

涉及文件

  • forge/forge-framework/forge-plugin-parent/forge-plugin-flow/src/main/java/com/mdframe/forge/starter/flow/entity/FlowModelVersion.java — 新增,创建版本历史实体

关键签名

package com.mdframe.forge.starter.flow.entity;

import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import java.time.LocalDateTime;

@Data
@TableName("sys_flow_model_version")
public class FlowModelVersion {
    
    @TableId(type = IdType.ASSIGN_UUID)
    private String id;
    
    private String modelId;
    
    private Integer version;
    
    private String versionName;
    
    private String versionTag;
    
    private String bpmnXml;
    
    private String formJson;
    
    private String changeDescription;
    
    private String deploymentId;
    
    private String processDefinitionId;
    
    private String publishBy;
    
    private LocalDateTime publishTime;
    
    private Long tenantId;
    
    @TableField(fill = FieldFill.INSERT)
    private LocalDateTime createTime;
    
    @TableLogic
    private Integer delFlag;
}

执行步骤

  1. ✅ 创建 FlowModelVersion 实体类文件
  2. ✅ 添加所有字段和注解(14个字段)
  3. ✅ 配置 MyBatis-Plus 自动填充和逻辑删除
  4. ✅ 编译验证通过

验证要点

  • ✅ 实体类编译成功(Maven BUILD SUCCESS)
  • ✅ 所有字段与数据库表字段对应(14个字段完整)
  • ✅ 注解配置正确(@TableId, @TableField, @TableLogic

Task 4: 字典数据新增

目标

新增版本标记和重要性等级两个字典类型及字典数据

涉及文件

  • forge/forge-admin-server/src/main/resources/sql/flow_version_init.sql — 修改,新增字典数据 SQL
  • 数据库表:sys_dict_typesys_dict_data — 新增记录

关键签名

-- 新增字典类型:版本标记
INSERT INTO `sys_dict_type` 
VALUES ('flow_version_tag', '流程版本标记', '0', 1, NOW(), NOW(), NULL, NULL, 'admin', 1);

INSERT INTO `sys_dict_data` VALUES
('draft', 'flow_version_tag', '草稿', 'draft', '0', 1, NOW(), NOW(), NULL, NULL, 'admin', 1),
('test', 'flow_version_tag', '测试', 'test', '0', 2, NOW(), NOW(), NULL, NULL, 'admin', 1),
('release', 'flow_version_tag', '正式发布', 'release', '0', 3, NOW(), NOW(), NULL, NULL, 'admin', 1),
('deprecated', 'flow_version_tag', '已废弃', 'deprecated', '0', 4, NOW(), NOW(), NULL, NULL, 'admin', 1);

-- 新增字典类型:流程重要性等级
INSERT INTO `sys_dict_type` 
VALUES ('flow_importance_level', '流程重要性等级', '0', 1, NOW(), NOW(), NULL, NULL, 'admin', 1);

INSERT INTO `sys_dict_data` VALUES
('1', 'flow_importance_level', '普通流程', '1', '0', 1, NOW(), NOW(), NULL, NULL, 'admin', 1),
('2', 'flow_importance_level', '重要流程', '2', '0', 2, NOW(), NOW(), NULL, NULL, 'admin', 1);

执行步骤

  1. ✅ 字典类型和字典数据 SQL 已在 Task 1 中完成(flow_version_init.sql)
  2. ⏭️ 执行 SQL 脚本验证数据(需在本地数据库执行)
  3. ⏭️ 在前端字典管理页面验证数据(待数据库执行后验证)

验证要点

  • ✅ 字典类型创建成功(flow_version_tag + flow_importance_level)
  • ✅ 字典数据插入成功(6条字典数据)
  • ⏭️ DictSelect 组件可正确加载字典数据(待前端实现后验证)

Task 5: FlowModelVersionMapper 创建

目标

创建 FlowModelVersionMapper 接口和 XML 映射文件

涉及文件

  • forge/forge-framework/forge-plugin-parent/forge-plugin-flow/src/main/java/com/mdframe/forge/starter/flow/mapper/FlowModelVersionMapper.java — 新增,创建 Mapper 接口
  • forge/forge-framework/forge-plugin-parent/forge-plugin-flow/src/main/resources/mapper/FlowModelVersionMapper.xml — 新增,创建 XML 映射文件

关键签名

package com.mdframe.forge.starter.flow.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.mdframe.forge.starter.flow.entity.FlowModelVersion;
import org.apache.ibatis.annotations.Param;

public interface FlowModelVersionMapper extends BaseMapper<FlowModelVersion> {
    
    /**
     * 分页查询版本历史
     */
    IPage<FlowModelVersion> pageByVersion(Page<FlowModelVersion> page, @Param("modelId") String modelId);
    
    /**
     * 查询模型的最大版本号
     */
    Integer getMaxVersion(@Param("modelId") String modelId);
    
    /**
     * 查询版本详情(包含 BPMN XML 和表单配置)
     */
    FlowModelVersion getVersionDetail(@Param("versionId") String versionId);
}

执行步骤

  1. ✅ 创建 FlowModelVersionMapper 接口文件
  2. ✅ 创建 XML 映射文件
  3. ✅ 编写分页查询、最大版本号查询、版本详情查询 SQL
  4. ✅ 编译验证通过

验证要点

  • ✅ Mapper 接口编译成功(Maven BUILD SUCCESS)
  • ✅ XML 映射文件 SQL 正确(3个查询方法)
  • ✅ MyBatis-Plus 可正确扫描 Mapper

Task 6: 版本相关 DTO/VO 创建

目标

创建版本管理相关的请求 DTO 和响应 VO 类

涉及文件

  • forge/forge-framework/forge-plugin-parent/forge-plugin-flow/src/main/java/com/mdframe/forge/starter/flow/dto/VersionCompareDTO.java — 新增,版本对比请求 DTO
  • forge/forge-framework/forge-plugin-parent/forge-plugin-flow/src/main/java/com/mdframe/forge/starter/flow/dto/VersionRevertDTO.java — 新增,版本回退请求 DTO
  • forge/forge-framework/forge-plugin-parent/forge-plugin-flow/src/main/java/com/mdframe/forge/starter/flow/dto/VersionTagUpdateDTO.java — 新增,版本标记更新 DTO
  • forge/forge-framework/forge-plugin-parent/forge-plugin-flow/src/main/java/com/mdframe/forge/starter/flow/vo/VersionCompareVO.java — 新增,版本对比响应 VO
  • forge/forge-framework/forge-plugin-parent/forge-plugin-flow/src/main/java/com/mdframe/forge/starter/flow/vo/VersionRevertVO.java — 新增,版本回退响应 VO
  • forge/forge-framework/forge-plugin-parent/forge-plugin-flow/src/main/java/com/mdframe/forge/starter/flow/vo/VersionDetailVO.java — 新增,版本详情响应 VO

关键签名

// VersionCompareDTO.java
@Data
public class VersionCompareDTO {
    private String modelId;
    private Integer version1;
    private Integer version2;
}

// VersionRevertDTO.java
@Data
public class VersionRevertDTO {
    private String modelId;
    private Integer targetVersion;
    private String changeDescription;
}

// VersionCompareVO.java
@Data
public class VersionCompareVO {
    private List<NodeDiff> addedNodes;
    private List<NodeDiff> modifiedNodes;
    private List<NodeDiff> deletedNodes;
    private List<FlowDiff> addedFlows;
    private List<FlowDiff> modifiedFlows;
    private List<FlowDiff> deletedFlows;
}

// VersionRevertVO.java
@Data
public class VersionRevertVO {
    private String newVersionId;
    private Integer newVersion;
    private String deploymentId;
    private Integer runningInstances;
}

执行步骤

  1. ✅ 创建所有 DTO 类(请求参数):VersionCompareDTO, VersionRevertDTO, VersionTagUpdateDTO
  2. ✅ 创建所有 VO 类(响应数据):VersionCompareVO, VersionRevertVO, VersionDetailVO
  3. ✅ 添加 Lombok 注解(@Data
  4. ✅ 编译验证通过

验证要点

  • ✅ DTO/VO 类编译成功(Maven BUILD SUCCESS)
  • ✅ 字段与接口定义一致
  • ✅ JSON 序列化正确(Lombok @Data注解)

Task 7: FlowModelVersionService 创建

目标

创建 FlowModelVersionService 接口和实现类,实现版本管理的核心业务逻辑

涉及文件

  • forge/forge-framework/forge-plugin-parent/forge-plugin-flow/src/main/java/com/mdframe/forge/starter/flow/service/FlowModelVersionService.java — 新增,创建 Service 接口
  • forge/forge-framework/forge-plugin-parent/forge-plugin-flow/src/main/java/com/mdframe/forge/starter/flow/service/impl/FlowModelVersionServiceImpl.java — 新增,创建 Service 实现类

关键签名

// FlowModelVersionService.java
public interface FlowModelVersionService extends IService<FlowModelVersion> {
    
    /**
     * 分页查询版本历史
     */
    IPage<FlowModelVersion> pageVersionList(Page<FlowModelVersion> page, String modelId);
    
    /**
     * 查询版本详情
     */
    VersionDetailVO getVersionDetail(String versionId);
    
    /**
     * 版本对比
     */
    VersionCompareVO compareVersions(VersionCompareDTO dto);
    
    /**
     * 版本回退
     */
    VersionRevertVO revertVersion(VersionRevertDTO dto);
    
    /**
     * 更新版本标记
     */
    void updateVersionTag(String versionId, String versionTag);
    
    /**
     * 删除版本(仅允许删除草稿/测试版本)
     */
    void deleteVersion(String versionId);
    
    /**
     * 发布时插入版本历史记录
     */
    void insertVersionOnPublish(FlowModel model, String changeDescription);
}

// FlowModelVersionServiceImpl.java 核心方法签名
@Service
@RequiredArgsConstructor
public class FlowModelVersionServiceImpl extends ServiceImpl<FlowModelVersionMapper, FlowModelVersion> implements FlowModelVersionService {
    
    @Override
    public VersionRevertVO revertVersion(VersionRevertDTO dto) {
        // 1. 查询目标版本
        FlowModelVersion targetVersion = getTargetVersion(dto.getModelId(), dto.getTargetVersion());
        
        // 2. 权限校验(检查流程重要性等级)
        checkPermission(dto.getModelId());
        
        // 3. 查询模型当前版本号
        FlowModel model = flowModelService.getById(dto.getModelId());
        Integer newVersion = model.getVersion() + 1;
        
        // 4. 复制目标版本内容并发布为新版本
        String deploymentId = deployToFlowable(model.getModelKey(), targetVersion.getBpmnXml(), newVersion);
        
        // 5. 插入新版本历史记录
        insertNewVersion(model, targetVersion, newVersion, deploymentId, dto.getChangeDescription());
        
        // 6. 更新模型当前版本号和 deploymentId
        updateModelVersion(model, newVersion, deploymentId);
        
        // 7. 查询正在运行的实例数量
        Integer runningInstances = getRunningInstancesCount(model.getProcessDefinitionId());
        
        return buildRevertVO(newVersionId, newVersion, deploymentId, runningInstances);
    }
    
    private void checkPermission(String modelId) {
        FlowModel model = flowModelService.getById(modelId);
        if (model.getImportanceLevel() == 2) {
            // 重要流程需超级管理员权限
            // 权限校验逻辑
        }
    }
}

执行步骤

  1. ✅ 创建 FlowModelVersionService 接口文件
  2. ✅ 创建 FlowModelVersionServiceImpl 实现类文件
  3. ✅ 实现 7 个核心方法(版本查询、版本对比、版本回退、版本标记、版本删除、版本插入)
  4. ✅ 实现权限校验逻辑(重要性等级判断)
  5. ✅ 实现 Flowable 部署逻辑(版本回退时重新部署)
  6. ✅ 编译验证通过

验证要点

  • ✅ Service 接口编译成功(Maven BUILD SUCCESS)
  • ✅ 所有方法实现完整(7个方法)
  • ✅ 权限校验逻辑正确(已发布版本不可删除)
  • ✅ Flowable 部署逻辑正确(版本回退部署成功)
  • ✅ BPMN XML 解析逻辑简化(版本对比返回空列表,待后续优化)

Task 8: FlowModelServiceImpl 修改

目标

修改 FlowModelServiceImpl 的 deployModel 方法,发布时自动插入版本历史记录

涉及文件

  • forge/forge-framework/forge-plugin-parent/forge-plugin-flow/src/main/java/com/mdframe/forge/starter/flow/service/impl/FlowModelServiceImpl.java — 修改,新增版本插入逻辑
  • forge/forge-framework/forge-plugin-parent/forge-plugin-flow/src/main/java/com/mdframe/forge/starter/flow/service/FlowModelService.java — 修改,deployModel 方法新增 changeDescription 参数

关键签名

// FlowModelService.java
String deployModel(String id, String changeDescription);

// FlowModelServiceImpl.java
@Override
@Transactional(rollbackFor = Exception.class)
public String deployModel(String id, String changeDescription) {
    // ... 原有发布逻辑 ...
    
    // 新增:发布成功后插入版本历史记录
    flowModelVersionService.insertVersionOnPublish(model, changeDescription);
    
    return deployment.getId();
}

执行步骤

  1. 修改 FlowModelService 接口,deployModel 方法新增 changeDescription 参数
  2. 修改 FlowModelServiceImpl 实现类,在发布成功后调用版本插入方法
  3. 调整 Controller 层调用代码(传递 changeDescription 参数)

验证要点

  • 发布成功后版本历史记录正确插入
  • 版本号、版本标记、变更说明字段正确
  • Controller 调用代码适配成功

Task 9: FlowModelVersionController 创建

目标

创建 FlowModelVersionController,提供版本管理的 REST API

涉及文件

  • forge/forge-framework/forge-plugin-parent/forge-plugin-flow/src/main/java/com/mdframe/forge/starter/flow/controller/FlowModelVersionController.java — 新增,创建版本管理 Controller

关键签名

package com.mdframe.forge.starter.flow.controller;

import com.mdframe.forge.starter.core.domain.RespInfo;
import com.mdframe.forge.starter.flow.dto.*;
import com.mdframe.forge.starter.flow.vo.*;
import com.mdframe.forge.starter.flow.service.FlowModelVersionService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;

@Tag(name = "流程模型版本管理")
@RestController
@RequestMapping("/flow/model/version")
@RequiredArgsConstructor
public class FlowModelVersionController {
    
    private final FlowModelVersionService flowModelVersionService;
    
    @Operation(summary = "分页查询版本历史")
    @GetMapping("/list")
    public RespInfo<IPage<FlowModelVersion>> pageVersionList(
        @RequestParam String modelId,
        @RequestParam(defaultValue = "1") Integer pageNum,
        @RequestParam(defaultValue = "20") Integer pageSize) {
        Page<FlowModelVersion> page = new Page<>(pageNum, pageSize);
        return RespInfo.success(flowModelVersionService.pageVersionList(page, modelId));
    }
    
    @Operation(summary = "查询版本详情")
    @GetMapping("/{versionId}")
    public RespInfo<VersionDetailVO> getVersionDetail(@PathVariable String versionId) {
        return RespInfo.success(flowModelVersionService.getVersionDetail(versionId));
    }
    
    @Operation(summary = "版本对比")
    @PostMapping("/compare")
    public RespInfo<VersionCompareVO> compareVersions(@RequestBody VersionCompareDTO dto) {
        return RespInfo.success(flowModelVersionService.compareVersions(dto));
    }
    
    @Operation(summary = "版本回退")
    @PostMapping("/revert")
    @SaCheckPermission("flow:model:revert")
    @OperationLog(module = "流程管理", operation = "版本回退")
    public RespInfo<VersionRevertVO> revertVersion(@RequestBody VersionRevertDTO dto) {
        return RespInfo.success(flowModelVersionService.revertVersion(dto));
    }
    
    @Operation(summary = "更新版本标记")
    @PutMapping("/{versionId}/tag")
    public RespInfo<Void> updateVersionTag(
        @PathVariable String versionId,
        @RequestParam String versionTag) {
        flowModelVersionService.updateVersionTag(versionId, versionTag);
        return RespInfo.success();
    }
    
    @Operation(summary = "删除版本")
    @DeleteMapping("/{versionId}")
    @SaCheckPermission("flow:model:version:delete")
    public RespInfo<Void> deleteVersion(@PathVariable String versionId) {
        flowModelVersionService.deleteVersion(versionId);
        return RespInfo.success();
    }
    
    @Operation(summary = "下载版本 BPMN XML")
    @GetMapping("/download/{versionId}")
    public void downloadVersion(@PathVariable String versionId, HttpServletResponse response) {
        // 下载逻辑
    }
}

执行步骤

  1. 创建 Controller 文件
  2. 实现 7 个 REST API 方法
  3. 添加 Swagger 注解和权限注解
  4. 添加操作日志注解

验证要点

  • Controller 编译成功
  • 所有接口可正常访问
  • 权限注解配置正确
  • Swagger 文档生成正确

Task 10: 前端 API 接口创建

目标

创建前端版本管理 API 接口文件

涉及文件

  • forge-admin-ui/src/api/flow/version.ts — 新增,创建版本管理 API 接口

关键签名

import { request } from '@/utils/request'

// 版本历史查询
export function getVersionList(modelId: string, pageNum: number = 1, pageSize: number = 20) {
  return request.get('/flow/model/version/list', { params: { modelId, pageNum, pageSize } })
}

// 版本详情查询
export function getVersionDetail(versionId: string) {
  return request.get(`/flow/model/version/${versionId}`)
}

// 版本对比
export function compareVersions(modelId: string, version1: number, version2: number) {
  return request.post('/flow/model/version/compare', { modelId, version1, version2 })
}

// 版本回退
export function revertVersion(modelId: string, targetVersion: number, changeDescription?: string) {
  return request.post('/flow/model/version/revert', { modelId, targetVersion, changeDescription })
}

// 更新版本标记
export function updateVersionTag(versionId: string, versionTag: string) {
  return request.put(`/flow/model/version/${versionId}/tag`, null, { params: { versionTag } })
}

// 删除版本
export function deleteVersion(versionId: string) {
  return request.delete(`/flow/model/version/${versionId}`)
}

// 下载版本 BPMN XML
export function downloadVersion(versionId: string) {
  return request.get(`/flow/model/version/download/${versionId}`, { responseType: 'blob' })
}

执行步骤

  1. 创建 API 接口文件
  2. 实现 7 个接口函数
  3. 配置请求参数和响应类型

验证要点

  • API 接口文件创建成功
  • 接口函数可正常调用
  • 请求参数格式正确

Task 11: 前端版本历史组件创建

目标

创建前端版本历史列表页面组件(弹窗或独立页面)

涉及文件

  • forge-admin-ui/src/views/flow/version.vue — 新增,创建版本历史页面

关键签名

<template>
  <div class="version-page">
    <!-- 版本历史列表 -->
    <n-data-table
      :columns="columns"
      :data="versionList"
      :pagination="pagination"
      :loading="loading"
    />
    
    <!-- 操作按钮 -->
    <template #action="{ row }">
      <a class="text-primary" @click="handleDetail(row)">详情</a>
      <a class="text-primary" @click="handleCompare(row)">对比</a>
      <a class="text-warning" @click="handleRevert(row)">回退</a>
      <a class="text-info" @click="handleUpdateTag(row)">标记</a>
      <a class="text-error" @click="handleDelete(row)">删除</a>
      <a class="text-info" @click="handleDownload(row)">下载</a>
    </template>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { getVersionList, deleteVersion, updateVersionTag } from '@/api/flow/version'
import { useDialog, useMessage } from 'naive-ui'

const versionList = ref([])
const loading = ref(false)
const modelId = ref('')

const columns = [
  { title: '版本号', key: 'version' },
  { title: '版本名称', key: 'versionName' },
  { title: '版本标记', key: 'versionTag' },
  { title: '变更说明', key: 'changeDescription' },
  { title: '发布人', key: 'publishBy' },
  { title: '发布时间', key: 'publishTime' },
  { title: '操作', key: 'action' }
]

const loadVersionList = async () => {
  loading.value = true
  const res = await getVersionList(modelId.value, 1, 20)
  versionList.value = res.data.records
  loading.value = false
}

const handleRevert = (row) => {
  // 弹窗确认回退
}

const handleDelete = async (row) => {
  // 确认删除
  await deleteVersion(row.id)
  loadVersionList()
}
</script>

执行步骤

  1. 创建版本历史页面组件
  2. 实现版本列表展示(表格组件)
  3. 实现操作按钮(详情、对比、回退、标记、删除、下载)
  4. 实现版本回退确认弹窗
  5. 实现版本标记更新弹窗

验证要点

  • 版本列表正确加载
  • 操作按钮功能正常
  • 弹窗组件交互正常
  • 权限控制正确(删除按钮仅对草稿/测试版本显示)

Task 12: 前端版本对比组件创建

目标

创建前端版本对比页面组件,展示两个版本的 BPMN XML 差异

涉及文件

  • forge-admin-ui/src/views/flow/versionCompare.vue — 新增,创建版本对比页面

关键签名

<template>
  <div class="version-compare-page">
    <!-- 版本选择 -->
    <div class="version-selector">
      <n-select v-model:value="version1" :options="versionOptions" placeholder="选择版本1" />
      <n-select v-model:value="version2" :options="versionOptions" placeholder="选择版本2" />
      <n-button type="primary" @click="handleCompare">对比</n-button>
    </div>
    
    <!-- 差异展示 -->
    <div class="diff-display">
      <!-- 新增节点 -->
      <div v-if="diffResult.addedNodes.length > 0">
        <h3>新增节点</h3>
        <n-list>
          <n-list-item v-for="node in diffResult.addedNodes">
            {{ node.name }} ({{ node.id }})
          </n-list-item>
        </n-list>
      </div>
      
      <!-- 修改节点 -->
      <div v-if="diffResult.modifiedNodes.length > 0">
        <h3>修改节点</h3>
        <n-list>
          <n-list-item v-for="node in diffResult.modifiedNodes">
            {{ node.oldName }} → {{ node.newName }}
          </n-list-item>
        </n-list>
      </div>
      
      <!-- 删除节点 -->
      <!-- 新增连线 -->
      <!-- 修改连线 -->
      <!-- 删除连线 -->
    </div>
    
    <!-- Side-by-side 流程图对比(可选) -->
    <div class="bpmn-compare">
      <div class="bpmn-left">
        <div ref="bpmnViewer1" class="bpmn-container"></div>
      </div>
      <div class="bpmn-right">
        <div ref="bpmnViewer2" class="bpmn-container"></div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { compareVersions, getVersionDetail } from '@/api/flow/version'
import BpmnViewer from 'bpmn-js/lib/NavigatedViewer'

const version1 = ref(null)
const version2 = ref(null)
const diffResult = ref({})
const bpmnViewer1 = ref(null)
const bpmnViewer2 = ref(null)

const handleCompare = async () => {
  const res = await compareVersions(modelId, version1.value, version2.value)
  diffResult.value = res.data
  
  // 加载 BPMN 流程图
  const detail1 = await getVersionDetail(version1Id)
  const detail2 = await getVersionDetail(version2Id)
  
  renderBpmn(bpmnViewer1.value, detail1.data.bpmnXml)
  renderBpmn(bpmnViewer2.value, detail2.data.bpmnXml)
}

const renderBpmn = (container, bpmnXml) => {
  const viewer = new BpmnViewer({ container })
  viewer.importXML(bpmnXml)
}
</script>

执行步骤

  1. 创建版本对比页面组件
  2. 实现版本选择下拉框
  3. 实现差异列表展示(新增节点、修改节点、删除节点、新增连线、修改连线、删除连线)
  4. 实现 Side-by-side BPMN 流程图对比(使用 bpmn-js)
  5. 实现差异高亮功能(高亮新增/修改/删除节点)

验证要点

  • 版本选择下拉框正确加载版本列表
  • 差异列表正确展示对比结果
  • BPMN 流程图正确渲染
  • 差异高亮功能正常

Task 13: 前端 model.vue 修改

目标

修改前端流程模型管理页面,新增"版本历史"按钮和版本管理入口

涉及文件

  • forge-admin-ui/src/views/flow/model.vue — 修改,新增版本历史按钮
  • forge-admin-ui/src/views/flow/design.vue — 修改,新增发布时填写变更说明弹窗(可选)

关键签名

<!-- model.vue 卡片操作按钮新增 -->
<div class="card-actions">
  <a class="text-primary" @click="handleDesign(item)">设计</a>
  <a class="text-primary" @click="handleDeploy(item)">发布</a>
  <a class="text-info" @click="handleVersionHistory(item)">版本历史</a> <!-- 新增 -->
  <a class="text-warning" @click="handleSuspend(item)">挂起</a>
  <a class="text-error" @click="handleDelete(item)">删除</a>
</div>

<script setup lang="ts">
// 新增版本历史弹窗
const showVersionHistory = ref(false)
const currentModelId = ref('')

const handleVersionHistory = (item) => {
  currentModelId.value = item.id
  showVersionHistory.value = true
}
</script>

<!-- 版本历史弹窗 -->
<n-modal v-model:show="showVersionHistory" preset="card" title="版本历史" style="width: 800px">
  <VersionHistory :model-id="currentModelId" />
</n-modal>

执行步骤

  1. 在 model.vue 卡片操作按钮区域新增"版本历史"按钮
  2. 实现版本历史弹窗组件集成
  3. 修改 design.vue 发布逻辑,新增变更说明填写弹窗(可选)

验证要点

  • "版本历史"按钮正确显示
  • 点击按钮后弹窗正常打开
  • 版本历史组件正确加载
  • 发布时变更说明字段正确传递

Task 14: 权限配置和菜单新增

目标

在系统菜单管理中新增版本管理权限标识和菜单项

涉及文件

  • 数据库表:sys_resource — 新增菜单和权限记录

关键签名

-- 新增版本管理菜单(在流程模型菜单下)
INSERT INTO `sys_resource` VALUES
('flow_model_version', '流程模型', 'flow_model', 'version', '版本历史', 3, 'menu', NULL, '/flow/model/version', 'document', 0, 1, NOW(), NOW(), NULL, NULL, 'admin', 1);

-- 新增版本回退权限
INSERT INTO `sys_resource` VALUES
('flow_model_revert', '流程模型', 'flow_model_version', 'revert', '版本回退', 4, 'button', 'flow:model:revert', NULL, NULL, 0, 1, NOW(), NOW(), NULL, NULL, 'admin', 1);

-- 新增版本删除权限
INSERT INTO `sys_resource` VALUES
('flow_model_version_delete', '流程模型', 'flow_model_version', 'delete', '版本删除', 5, 'button', 'flow:model:version:delete', NULL, NULL, 0, 1, NOW(), NOW(), NULL, NULL, 'admin', 1);

执行步骤

  1. 在 sys_resource 表新增版本管理菜单项
  2. 新增版本回退和版本删除权限标识
  3. 在角色管理中配置超级管理员角色的版本管理权限
  4. 前端菜单管理页面验证菜单显示

验证要点

  • 菜单项创建成功
  • 权限标识配置正确
  • 超级管理员角色拥有版本管理权限
  • 前端菜单正确显示

任务依赖关系图

Task 1 (数据库表)
  ↓
Task 2 (FlowModel 实体修改) + Task 3 (FlowModelVersion 实体创建)
  ↓
Task 5 (FlowModelVersionMapper)
  ↓
Task 6 (DTO/VO)
  ↓
Task 7 (FlowModelVersionService)
  ↓
Task 8 (FlowModelServiceImpl 修改) + Task 9 (FlowModelVersionController)
  ↓
Task 10 (前端 API)
  ↓
Task 11 (版本历史组件) + Task 13 (model.vue 修改)
  ↓
Task 12 (版本对比组件)

Task 4 (字典数据) — 独立任务,可并行执行
Task 14 (权限配置) — 依赖 Task 9,最后执行

风险提示

⚠️ 高风险任务

  • Task 7(FlowModelVersionService):涉及版本回退核心逻辑、权限校验、BPMN XML 解析,需仔细测试
  • Task 8(FlowModelServiceImpl 修改):修改现有发布逻辑,需确保不影响原有功能
  • Task 12(版本对比组件):BPMN 流程图对比技术复杂,需验证 bpmn-js 渲染性能

⚠️ 建议测试顺序

  1. Task 1-5 完成后,验证数据库和 Mapper 基础功能
  2. Task 7 完成后,编写单元测试验证版本回退逻辑
  3. Task 9 完成后,使用 curl 测试 REST API 接口
  4. Task 11-13 完成后,端到端测试用户操作流程

完成标准

每个任务完成后需满足:

  1. ✅ 代码编译成功(后端 mvn compile,前端 pnpm build)
  2. ✅ 单元测试通过(如有)
  3. ✅ 代码符合编码规范(参考 code-copilot/rules/coding-style.md)
  4. ✅ Git 提交原子化(每个任务独立提交)
  5. ✅ 提交信息清晰(格式:[Task N] 任务名称 - 具体改动