Files
ruoyi-vue-pro/.claude/skills/usage/new-module.md

38 KiB
Raw Blame History

references
references
design templates reference_modules usage_hint
path reason
skills/design/db-designer.yaml 数据库表设计规范 - 建表 SQL、字段命名、索引设计
path reason
skills/design/entity-designer.yaml 实体类(DO)设计规范 - 继承体系、注解规范、命名转换
path reason
skills/design/api-designer.yaml API 接口设计规范 - Controller 注解、请求响应格式、权限标识
path reason
skills/design/crud-designer.yaml CRUD 代码生成规范 - 各层代码模板、命名规范
path reason
skills/templates/skill-template.yaml Skill 文档模板 - 创建新模块 Skill 文档的模板
path reason
skills/modules/system/skill-system.yaml 系统模块参考 - 基础模块结构、多租户、树形结构
path reason
skills/modules/pay/skill-pay.yaml 支付模块参考 - 设计模式应用(工厂+策略+模板方法)
path reason
skills/modules/mall/skill-mall.yaml 商城模块参考 - 复杂业务模块结构
新增模块时可参考已有模块的 Skill 文档结构

Skill 使用指南 - 新增模块场景

本文档提供从零开始创建新模块的完整提示词模板,基于 yudao-vue-pro 项目的模块化架构规范。


目录

  1. 场景说明
  2. 提示词模板
  3. 实际示例
  4. 模块结构清单
  5. 必要文件模板

1. 场景说明

何时需要新增模块

在以下场景中,应当考虑创建新的业务模块:

场景特征 说明 示例
独立业务领域 业务功能独立,不依附于现有模块 CMS内容管理、工单系统
完整生命周期 具有独立的业务对象生命周期管理 订单管理、项目管理
多表关联 涉及5个以上数据表有复杂关联关系 商品管理SPU/SKU/分类/品牌等)
跨模块调用 需要被其他模块调用,或调用其他模块 支付模块、消息通知模块
可插拔部署 业务功能可选,不同租户/场景可能不需要 IoT设备管理、ERP进销存

不应创建新模块的情况

  • 简单的增删改查功能,可在现有模块中扩展
  • 仅增加几张配置表,不具备独立业务含义
  • 功能与现有模块高度耦合,无法独立运行

2. 提示词模板

2.1 需求分析阶段

提示词模板:

# 需求分析任务

我需要在 yudao-vue-pro 项目中新增一个 [模块名称] 模块,请帮我进行需求分析。

## 业务背景
[描述业务背景和目标,如:需要为系统增加内容管理能力,支持文章发布、栏目管理等功能]

## 核心功能需求
1. [功能点1][详细描述]
2. [功能点2][详细描述]
3. [功能点3][详细描述]

## 分析要求

请参考 skills/modules/system/skill-system.yaml 和 skills/modules/mall/skill-mall.yaml 的格式,帮我完成以下分析:

### 1. 业务定位分析
- 模块解决什么业务问题?
- 在整个系统中的定位是什么?
- 与现有模块的关系是什么?

### 2. 领域模型分析
参考 DDD 方法论,识别:
- 聚合根Aggregate Root哪些实体是核心聚合根
- 实体Entity有哪些业务实体
- 值对象Value Object有哪些值对象
- 领域服务Domain Service需要哪些领域服务
- 聚合边界:聚合内部的一致性边界是什么?

### 3. 设计原则确定
基于 SOLID 原则和项目规范,确定:
- 应采用哪些设计模式?(策略模式、工厂模式、模板方法模式等)
- 是否需要多租户支持?(继承 TenantBaseDO 还是 BaseDO
- 是否需要数据权限控制?
- 是否需要工作流集成?

请输出结构化的分析结果。

2.2 架构设计阶段

提示词模板:

# 架构设计任务

基于前面的需求分析结果,请为 [模块名称] 模块设计架构。

## 参考文档
- skills/modules/system/skill-system.yaml基础模块结构参考
- skills/modules/pay/skill-pay.yaml设计模式应用参考
- skills/modules/mall/skill-mall.yaml复杂业务模块参考

## 设计要求

### 1. 分层架构设计
按照项目规范设计以下层次:

| 层次 | 目录 | 职责 | 组件列表 |
|------|------|------|----------|
| api | api/ | 模块间API接口 | [列出API接口] |
| controller | controller/admin/ | HTTP接口 | [列出Controller] |
| service | service/ | 业务逻辑 | [列出Service] |
| dal | dal/ | 数据访问 | [列出Mapper] |
| framework | framework/ | 框架扩展 | [如有] |

### 2. 设计模式选择
根据业务特点,选择合适的设计模式:

**场景1需要支持多种类型切换如支付渠道、存储类型**
- 采用策略模式 + 工厂模式
- 参考skills/patterns/strategy-pattern.yaml、skills/patterns/factory-pattern.yaml

**场景2需要统一处理流程如审批流程、发送流程**
- 采用模板方法模式
- 参考skills/patterns/template-method-pattern.yaml

### 3. 模块间通信设计
- **对外API**:哪些功能需要暴露给其他模块?在 api/ 包中定义
- **依赖API**需要调用哪些其他模块的API
- **消息队列**:是否需要异步消息通知?

### 4. 子模块划分(如果模块较大)
如果模块包含多个独立子域,可考虑拆分子模块:
- yudao-module-{module}/
  - yudao-module-{domain1}/
  - yudao-module-{domain2}/

请输出详细的架构设计文档。

2.3 数据库设计阶段

提示词模板:

# 数据库设计任务

请为 [模块名称] 模块设计数据库表结构。

## 参考规范
- 所有表继承 BaseDO 或 TenantBaseDO 基类
- BaseDO 包含id, creator, create_time, updater, update_time, deleted
- TenantBaseDO 额外包含tenant_id
- 主键使用 BIGINT 类型,雪花算法生成

## 设计要求

### 1. 实体继承体系设计
为每个表确定继承关系:
- 需要多租户隔离:继承 TenantBaseDO
- 不需要多租户隔离:继承 BaseDO
- 忽略租户隔离:使用 @TenantIgnore 注解

### 2. 数据表设计

> **数据库方言PostgreSQL。** 除非用户明确指定,否则不得生成 MySQL 专有语法(如 `AUTO_INCREMENT`、`DATETIME`、`BIT(1)`、反引号、`ENGINE=InnoDB`、`INSERT IGNORE`、`ON DUPLICATE KEY UPDATE`)。

按照以下格式设计每张表:

```sql
-- 表名:{table_name}
-- 说明:{table_comment}
-- 继承:{BaseDO/TenantBaseDO}
CREATE TABLE {table_name} (
    id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
    creator VARCHAR(64) DEFAULT '',
    create_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updater VARCHAR(64) DEFAULT '',
    update_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    deleted BOOLEAN NOT NULL DEFAULT false,
    tenant_id BIGINT NOT NULL DEFAULT 0,
    {field1} VARCHAR(100) NOT NULL,
    {field2} INTEGER NOT NULL DEFAULT 0
);
COMMENT ON TABLE {table_name} IS '{table_comment}';
CREATE INDEX idx_{table_name}_{field} ON {table_name} (tenant_id, {field});

3. 表关系设计

描述表之间的关联关系:

  • 一对一关系1:1
  • 一对多关系1:N
  • 多对多关系N:N

4. 索引设计

为高频查询字段设计索引,考虑:

  • 唯一索引:唯一性约束字段
  • 普通索引:高频查询字段
  • 联合索引:组合查询条件

5. 状态枚举设计

为状态字段设计枚举值:

public enum {Entity}StatusEnum {
    STATUS_1(0, "状态1"),
    STATUS_2(1, "状态2");
    // ...
}

请输出完整的数据库设计文档包括建表SQL。


---

### 2.4 代码生成阶段

**提示词模板:**

```markdown
# 代码生成任务

请根据前面的设计和数据表结构,为 [模块名称] 模块生成代码框架。

## 项目结构参考
参考 yudao-module-system 模块的结构:

yudao-module-{module}/ ├── pom.xml # 单一 POM 文件 └── src/main/java/cn/iocoder/yudao/module/{module}/ ├── api/ # API 接口定义 + 实现(内部包) │ ├── {entity}/ │ │ ├── {Entity}Api.java # API 接口 │ │ ├── {Entity}ApiImpl.java # API 实现(@Service │ │ └── dto/ │ │ ├── {Entity}CreateReqDTO.java │ │ └── {Entity}RespDTO.java │ └── ... ├── controller/ # Controller 层 │ └── admin/ │ └── {entity}/ │ ├── {Entity}Controller.java │ └── vo/ │ ├── {Entity}SaveReqVO.java │ ├── {Entity}PageReqVO.java │ └── {Entity}RespVO.java ├── service/ # Service 层 │ └── {entity}/ │ ├── {Entity}Service.java │ └── {Entity}ServiceImpl.java ├── dal/ # 数据访问层 │ ├── dataobject/ │ │ └── {entity}/ │ │ └── {Entity}DO.java │ └── mysql/ │ └── {entity}/ │ └── {Entity}Mapper.java ├── enums/ # 枚举定义 │ ├── {Entity}StatusEnum.java │ └── ErrorCodeConstants.java ├── convert/ # 对象转换(可选) │ └── {Entity}Convert.java └── framework/ # 框架扩展(如有)


## 生成要求

### 1. DO 实体类
按照规范生成,参考 skills/modules/system/skill-system.yaml 的 data_model 部分:

```java
@TableName("{table_name}")
@KeySequence("{table_name}_seq")
@Data
@EqualsAndHashCode(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class {Entity}DO extends {BaseDO/TenantBaseDO} {

    /**
     * {字段说明}
     */
    private {Type} {fieldName};

    // ... 其他字段
}

2. Mapper 接口

继承 BaseMapperX提供通用 CRUD 和自定义查询:

@Mapper
public interface {Entity}Mapper extends BaseMapperX<{Entity}DO> {

    default PageResult<{Entity}DO> selectPage({Entity}PageReqVO reqVO) {
        return selectPage(reqVO, new LambdaQueryWrapperX<{Entity}DO>()
                .likeIfPresent({Entity}DO::getName, reqVO.getName())
                .eqIfPresent({Entity}DO::getStatus, reqVO.getStatus())
                .betweenIfPresent({Entity}DO::getCreateTime, reqVO.getCreateTime())
                .orderByDesc({Entity}DO::getId));
    }
}

3. Service 接口和实现

接口:

public interface {Entity}Service {

    Long create{Entity}(@Valid {Entity}SaveReqVO createReqVO);

    void update{Entity}(@Valid {Entity}SaveReqVO updateReqVO);

    void delete{Entity}(Long id);

    {Entity}DO get{Entity}(Long id);

    PageResult<{Entity}DO> get{Entity}Page({Entity}PageReqVO pageReqVO);
}

实现:

@Service
@Validated
public class {Entity}ServiceImpl implements {Entity}Service {

    @Resource
    private {Entity}Mapper {entity}Mapper;

    @Override
    public Long create{Entity}({Entity}SaveReqVO createReqVO) {
        // 1. 参数校验
        // 2. 数据转换
        {Entity}DO {entity} = BeanUtils.toBean(createReqVO, {Entity}DO.class);
        // 3. 数据保存
        {entity}Mapper.insert({entity});
        return {entity}.getId();
    }

    // ... 其他方法实现
}

4. Controller 类

@Tag(name = "管理后台 - {实体中文名}")
@RestController
@RequestMapping("/{module}/{entity}")
@Validated
public class {Entity}Controller {

    @Resource
    private {Entity}Service {entity}Service;

    @PostMapping("/create")
    @Operation(summary = "创建{实体中文名}")
    @PreAuthorize("@ss.hasPermission('{module}:{entity}:create')")
    public CommonResult<Long> create{Entity}(@Valid @RequestBody {Entity}SaveReqVO createReqVO) {
        return success({entity}Service.create{Entity}(createReqVO));
    }

    @PutMapping("/update")
    @Operation(summary = "更新{实体中文名}")
    @PreAuthorize("@ss.hasPermission('{module}:{entity}:update')")
    public CommonResult<Boolean> update{Entity}(@Valid @RequestBody {Entity}SaveReqVO updateReqVO) {
        {entity}Service.update{Entity}(updateReqVO);
        return success(true);
    }

    @DeleteMapping("/delete")
    @Operation(summary = "删除{实体中文名}")
    @Parameter(name = "id", description = "编号", required = true)
    @PreAuthorize("@ss.hasPermission('{module}:{entity}:delete')")
    public CommonResult<Boolean> delete{Entity}(@RequestParam("id") Long id) {
        {entity}Service.delete{Entity}(id);
        return success(true);
    }

    @GetMapping("/get")
    @Operation(summary = "获得{实体中文名}")
    @Parameter(name = "id", description = "编号", required = true)
    @PreAuthorize("@ss.hasPermission('{module}:{entity}:query')")
    public CommonResult<{Entity}RespVO> get{Entity}(@RequestParam("id") Long id) {
        {Entity}DO {entity} = {entity}Service.get{Entity}(id);
        return success(BeanUtils.toBean({entity}, {Entity}RespVO.class));
    }

    @GetMapping("/page")
    @Operation(summary = "获得{实体中文名}分页")
    @PreAuthorize("@ss.hasPermission('{module}:{entity}:query')")
    public CommonResult<PageResult<{Entity}RespVO>> get{Entity}Page(@Valid {Entity}PageReqVO pageReqVO) {
        PageResult<{Entity}DO> pageResult = {entity}Service.get{Entity}Page(pageReqVO);
        return success(BeanUtils.toBean(pageResult, {Entity}RespVO.class));
    }
}

5. VO 类

保存请求 VO

@Data
public class {Entity}SaveReqVO {

    @Schema(description = "编号", example = "1")
    private Long id;

    @Schema(description = "名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "示例")
    @NotBlank(message = "名称不能为空")
    private String name;

    @Schema(description = "状态", example = "0")
    private Integer status;

    // ... 其他字段
}

分页请求 VO

@Data
@EqualsAndHashCode(callSuper = true)
public class {Entity}PageReqVO extends PageParam {

    @Schema(description = "名称", example = "示例")
    private String name;

    @Schema(description = "状态", example = "0")
    private Integer status;

    @Schema(description = "创建时间")
    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
    private LocalDateTime[] createTime;
}

响应 VO

@Data
public class {Entity}RespVO {

    @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
    private Long id;

    @Schema(description = "名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "示例")
    private String name;

    @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
    private Integer status;

    @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
    private LocalDateTime createTime;

    // ... 其他字段
}

6. API 接口(跨模块调用)

接口定义:

public interface {Entity}Api {

    /**
     * 获取{实体中文名}
     *
     * @param id 编号
     * @return {实体中文名}
     */
    {Entity}RespDTO get{Entity}(Long id);

    /**
     * 创建{实体中文名}
     *
     * @param reqDTO 创建请求
     * @return 编号
     */
    Long create{Entity}(@Valid {Entity}CreateReqDTO reqDTO);
}

接口实现:

@Service
@Validated
public class {Entity}ApiImpl implements {Entity}Api {

    @Resource
    private {Entity}Service {entity}Service;

    @Override
    public {Entity}RespDTO get{Entity}(Long id) {
        {Entity}DO {entity} = {entity}Service.get{Entity}(id);
        return BeanUtils.toBean({entity}, {Entity}RespDTO.class);
    }

    @Override
    public Long create{Entity}({Entity}CreateReqDTO reqDTO) {
        {Entity}SaveReqVO saveReqVO = BeanUtils.toBean(reqDTO, {Entity}SaveReqVO.class);
        return {entity}Service.create{Entity}(saveReqVO);
    }
}

7. 错误码定义

public interface ErrorCodeConstants {
    // ========== {模块中文名} 1-0XX-XXX-XXX ==========
    ErrorCode {ENTITY}_NOT_EXISTS = new ErrorCode(1_0XX_000_000, "{实体中文名}不存在");
    ErrorCode {ENTITY}_NAME_DUPLICATE = new ErrorCode(1_0XX_000_001, "已存在该名字的{实体中文名}");
    // ... 其他错误码
}

请按照以上规范生成完整的代码框架。


---

### 2.5 测试阶段

**提示词模板:**

```markdown
# 测试任务

请为 [模块名称] 模块编写测试代码。

## 测试类型

### 1. 单元测试
为 Service 层编写单元测试:

```java
@SpringBootTest
class {Entity}ServiceImplTest {

    @Resource
    private {Entity}Service {entity}Service;

    @Test
    void testCreate{Entity}() {
        // 准备数据
        {Entity}SaveReqVO reqVO = new {Entity}SaveReqVO();
        reqVO.setName("测试名称");
        // ... 设置其他字段

        // 执行测试
        Long id = {entity}Service.create{Entity}(reqVO);

        // 验证结果
        assertNotNull(id);
        {Entity}DO entity = {entity}Service.get{Entity}(id);
        assertEquals("测试名称", entity.getName());
    }

    @Test
    void testUpdate{Entity}() {
        // 更新测试
    }

    @Test
    void testDelete{Entity}() {
        // 删除测试
    }

    @Test
    void testGet{Entity}Page() {
        // 分页查询测试
    }
}

2. 集成测试

为 Controller 层编写集成测试:

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@AutoConfigureMockMvc
class {Entity}ControllerTest {

    @Resource
    private MockMvc mockMvc;

    @Test
    void testCreate{Entity}() throws Exception {
        // 准备请求体
        String requestBody = """
            {
                "name": "测试名称",
                "status": 0
            }
            """;

        // 执行请求
        mockMvc.perform(post("/{module}/{entity}/create")
                .contentType(MediaType.APPLICATION_JSON)
                .content(requestBody))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.code").value(0))
                .andExpect(jsonPath("$.data").isNumber());
    }
}

3. 功能测试清单

请生成以下测试场景:

测试项 测试场景 预期结果
创建 正常创建 返回ID数据入库
创建 缺少必填项 返回参数校验错误
更新 正常更新 数据更新成功
更新 不存在的ID 返回数据不存在错误
删除 正常删除 数据标记删除
删除 不存在的ID 返回数据不存在错误
查询 单条查询 返回正确数据
查询 分页查询 返回分页数据
查询 条件筛选 返回筛选结果

请输出完整的测试代码和测试清单。


---

## 3. 实际示例

### 3.1 示例1内容管理CMS模块

**完整提示词:**

```markdown
# 新增模块任务内容管理CMS模块

我需要在 yudao-vue-pro 项目中新增一个 CMS内容管理系统模块请帮我完成从需求分析到代码生成的全过程。

## 业务背景
系统需要一个内容管理模块,支持:
1. 文章发布和管理(富文本、图片)
2. 栏目/分类管理(树形结构)
3. 标签管理
4. 评论管理
5. 内容审核流程

## 参考文档
请参考以下 Skill 文档:
- skills/modules/system/skill-system.yaml基础模块结构、多租户、树形结构
- skills/modules/mall/skill-mall.yamlSPU/SKU 模型参考文章类似SPU
- skills/modules/bpm/skill-bpm.yaml审核流程集成

## 任务要求

### 阶段1需求分析
1. 确定 CMS 模块的业务定位
2. 识别聚合根、实体、值对象
3. 确定设计原则(多租户支持、数据权限等)

### 阶段2架构设计
1. 设计分层架构
2. 设计模块间通信(是否需要 API
3. 确定是否需要工作流集成

### 阶段3数据库设计
1. 设计文章表cms_article
2. 设计栏目表cms_category
3. 设计标签表cms_tag
4. 设计文章标签关联表cms_article_tag
5. 设计评论表cms_comment
6. 设计表关系和索引

### 阶段4代码生成
按照项目规范生成:
1. DO 实体类
2. Mapper 接口
3. Service 接口和实现
4. Controller 类
5. VO 类
6. API 接口(如需跨模块调用)
7. 错误码定义

### 阶段5测试
生成单元测试和集成测试代码

请按顺序输出各阶段的设计文档和代码。

预期输出结构:

yudao-module-cms/
├── pom.xml
└── src/main/java/cn/iocoder/yudao/module/cms/
    ├── api/                              # API 接口(跨模块调用)
    │   └── article/
    │       ├── ArticleApi.java
    │       ├── ArticleApiImpl.java
    │       └── dto/
    │           └── ArticleRespDTO.java
    ├── controller/
    │   └── admin/
    │       ├── article/
    │       │   ├── ArticleController.java
    │       │   └── vo/
    │       ├── category/
    │       │   ├── CategoryController.java
    │       │   └── vo/
    │       ├── tag/
    │       └── comment/
    ├── service/
    │   ├── article/
    │   ├── category/
    │   ├── tag/
    │   └── comment/
    ├── dal/
    │   ├── dataobject/
    │   │   ├── article/ArticleDO.java
    │   │   ├── category/CategoryDO.java
    │   │   ├── tag/TagDO.java
    │   │   └── comment/CommentDO.java
    │   └── mysql/
    └── enums/
        ├── ArticleStatusEnum.java
        └── ErrorCodeConstants.java

3.2 示例2消息通知模块

完整提示词:

# 新增模块任务:消息通知模块

我需要新增一个消息通知模块,统一管理系统内的各类消息通知。

## 业务背景
当前系统需要统一的消息通知能力,支持:
1. 站内信(系统通知、用户消息)
2. 短信通知(验证码、业务通知)
3. 邮件通知
4. WebSocket 实时推送
5. 消息模板管理
6. 发送记录和状态追踪

## 参考文档
请参考以下 Skill 文档:
- skills/modules/system/skill-system.yaml短信/邮件/站内信现有实现
- skills/modules/pay/skill-pay.yaml策略模式 + 工厂模式(渠道切换)
- skills/modules/infra/skill-infra.yaml文件存储渠道参考

## 特殊要求
1. 消息发送采用策略模式,支持多渠道切换
2. 使用工厂模式创建消息客户端
3. 支持异步发送和重试机制
4. 支持消息模板变量替换

## 任务要求

### 阶段1架构设计
重点设计:
1. MessageClient 接口(策略模式)
2. MessageClientFactory 工厂类
3. AbstractMessageClient 抽象类(模板方法模式)
4. 各渠道实现类SmsMessageClient、EmailMessageClient、WebSocketMessageClient

### 阶段2数据库设计
1. 消息模板表notify_template
2. 消息发送记录表notify_send_log
3. 消息配置表notify_channel_config

### 阶段3代码生成
重点生成:
1. 策略模式相关代码
2. 工厂模式相关代码
3. 模板方法模式相关代码

设计模式应用示例:

// 策略模式:消息客户端接口
public interface MessageClient {

    /**
     * 发送消息
     */
    MessageSendResultDTO send(MessageSendReqDTO reqDTO);

    /**
     * 获取渠道类型
     */
    MessageChannelEnum getChannel();
}

// 模板方法模式:抽象基类
public abstract class AbstractMessageClient implements MessageClient {

    @Override
    public final MessageSendResultDTO send(MessageSendReqDTO reqDTO) {
        // 1. 参数校验
        validateParams(reqDTO);
        // 2. 模板变量替换
        String content = processTemplate(reqDTO);
        // 3. 执行发送(子类实现)
        return doSend(reqDTO, content);
    }

    protected abstract MessageSendResultDTO doSend(MessageSendReqDTO reqDTO, String content);
}

// 工厂模式:客户端工厂
@Component
public class MessageClientFactory {

    private final Map<MessageChannelEnum, MessageClient> clients = new ConcurrentHashMap<>();

    public MessageClient getClient(MessageChannelEnum channel) {
        return clients.get(channel);
    }
}

3.3 示例3工单系统模块

完整提示词:

# 新增模块任务:工单系统模块

我需要新增一个工单系统模块,用于企业内部的工单流转和管理。

## 业务背景
企业需要一个工单系统,支持:
1. 工单类型管理(故障报修、服务请求、问题反馈等)
2. 工单创建和分配
3. 工单状态流转(新建-处理中-已解决-已关闭)
4. 工单流转记录
5. 工单评价
6. SLA 服务时效管理
7. 工作流集成(审批流程)

## 参考文档
请参考以下 Skill 文档:
- skills/modules/bpm/skill-bpm.yaml工作流集成
- skills/modules/mall/skill-mall.yaml订单状态机参考
- skills/modules/system/skill-system.yaml用户/部门关联

## 特殊要求
1. 工单状态采用状态机模式
2. 与 BPM 模块集成,支持审批流程
3. 支持 SLA 超时提醒
4. 支持数据权限(仅查看本部门工单)

## 任务要求

### 阶段1领域模型设计
1. 识别聚合根Ticket工单
2. 识别实体TicketType、TicketLog、TicketComment
3. 识别值对象TicketStatus、TicketPriority
4. 设计状态流转规则

### 阶段2工作流集成设计
1. 工单创建时可选发起审批流程
2. 监听流程状态变更事件
3. 更新工单状态

### 阶段3数据库设计
1. 工单表ticket
2. 工单类型表ticket_type
3. 工单流转记录表ticket_log
4. 工单评价表ticket_evaluation

状态机设计示例:

public enum TicketStatusEnum {

    NEW(0, "新建"),
    ASSIGNED(10, "已分配"),
    PROCESSING(20, "处理中"),
    RESOLVED(30, "已解决"),
    CLOSED(40, "已关闭"),
    REJECTED(50, "已拒绝");

    // 状态流转规则
    private static final Map<TicketStatusEnum, Set<TicketStatusEnum>> TRANSITIONS = Map.of(
        NEW, Set.of(ASSIGNED, REJECTED),
        ASSIGNED, Set.of(PROCESSING, NEW),
        PROCESSING, Set.of(RESOLVED, ASSIGNED),
        RESOLVED, Set.of(CLOSED, PROCESSING),
        CLOSED, Set.of(),
        REJECTED, Set.of(NEW)
    );

    public boolean canTransitionTo(TicketStatusEnum target) {
        return TRANSITIONS.getOrDefault(this, Set.of()).contains(target);
    }
}

4. 模块结构清单

4.1 单模块结构

yudao-module-{module}/
├── pom.xml                              # 单一 POM 文件
└── src/
    ├── main/java/cn/iocoder/yudao/module/{module}/
    │   ├── api/                          # API 接口(跨模块调用)
    │   │   └── {entity}/
    │   │       ├── {Entity}Api.java
    │   │       ├── {Entity}ApiImpl.java
    │   │       └── dto/
    │   │           ├── {Entity}CreateReqDTO.java
    │   │           └── {Entity}RespDTO.java
    │   ├── controller/                   # Controller 层
    │   │   └── admin/
    │   │       └── {entity}/
    │   │           ├── {Entity}Controller.java
    │   │           └── vo/
    │   │               ├── {Entity}SaveReqVO.java
    │   │               ├── {Entity}PageReqVO.java
    │   │               └── {Entity}RespVO.java
    │   ├── service/                      # Service 层
    │   │   └── {entity}/
    │   │       ├── {Entity}Service.java
    │   │       └── {Entity}ServiceImpl.java
    │   ├── dal/                          # 数据访问层
    │   │   ├── dataobject/
    │   │   │   └── {entity}/
    │   │   │       └── {Entity}DO.java
    │   │   └── mysql/
    │   │       └── {entity}/
    │   │           └── {Entity}Mapper.java
    │   ├── enums/                        # 枚举定义
    │   │   ├── {Entity}StatusEnum.java
    │   │   └── ErrorCodeConstants.java
    │   ├── convert/                      # 对象转换(可选)
    │   │   └── {Entity}Convert.java
    │   └── framework/                    # 框架扩展(如有)
    │
    └── test/java/cn/iocoder/yudao/module/{module}/
        └── service/
            └── {entity}/
                └── {Entity}ServiceImplTest.java

4.2 多子模块结构(大型模块)

yudao-module-{module}/
├── pom.xml                              # 父 POM
├── yudao-module-{domain1}/              # 子域1
│   ├── controller/
│   ├── service/
│   └── dal/
├── yudao-module-{domain2}/              # 子域2
│   ├── controller/
│   ├── service/
│   └── dal/
└── yudao-module-{module}-api/           # 共享 API如有需要

5. 必要文件模板

5.1 POM 文件模板

单模块 POM推荐

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <groupId>cn.iocoder.boot</groupId>
        <artifactId>yudao</artifactId>
        <version>${revision}</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>yudao-module-{module}</artifactId>
    <packaging>jar</packaging>
    <name>${project.artifactId}</name>
    <description>{模块中文名}模块</description>

    <dependencies>
        <!-- System API如需调用 system 模块) -->
        <dependency>
            <groupId>cn.iocoder.boot</groupId>
            <artifactId>yudao-module-system</artifactId>
            <version>${revision}</version>
        </dependency>

        <!-- Web -->
        <dependency>
            <groupId>cn.iocoder.boot</groupId>
            <artifactId>yudao-spring-boot-starter-web</artifactId>
        </dependency>

        <!-- Security -->
        <dependency>
            <groupId>cn.iocoder.boot</groupId>
            <artifactId>yudao-spring-boot-starter-security</artifactId>
        </dependency>

        <!-- MyBatis -->
        <dependency>
            <groupId>cn.iocoder.boot</groupId>
            <artifactId>yudao-spring-boot-starter-mybatis</artifactId>
        </dependency>

        <!-- Tenant -->
        <dependency>
            <groupId>cn.iocoder.boot</groupId>
            <artifactId>yudao-spring-boot-starter-biz-tenant</artifactId>
        </dependency>

        <!-- Test -->
        <dependency>
            <groupId>cn.iocoder.boot</groupId>
            <artifactId>yudao-spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>

5.2 数据库 SQL 模板

-- {表说明}PostgreSQL
CREATE TABLE {table_name} (
    id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
    creator VARCHAR(64) DEFAULT '',
    create_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updater VARCHAR(64) DEFAULT '',
    update_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    deleted BOOLEAN NOT NULL DEFAULT false,
    tenant_id BIGINT NOT NULL DEFAULT 0,
    name VARCHAR(100) NOT NULL,
    status SMALLINT NOT NULL DEFAULT 0,
    remark VARCHAR(500) DEFAULT NULL
);
COMMENT ON TABLE {table_name} IS '{表说明}';
CREATE INDEX idx_{table_name}_name ON {table_name} (tenant_id, name);
CREATE INDEX idx_{table_name}_status ON {table_name} (tenant_id, status);

5.3 菜单权限 SQL 模板

-- 菜单 SQL
INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted)
VALUES ('{菜单名称}', '', 2, 0, {父菜单ID}, '{路径}', 'ep:document', '{组件路径}', '{组件名}', 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0');

-- 按钮权限 SQL假设新菜单ID为 @parentId
SELECT @parentId := LAST_INSERT_ID();

INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted)
VALUES ('{功能}查询', '{module}:{entity}:query', 3, 1, @parentId, '', '', '', '', 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0');

INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted)
VALUES ('{功能}新增', '{module}:{entity}:create', 3, 2, @parentId, '', '', '', '', 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0');

INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted)
VALUES ('{功能}修改', '{module}:{entity}:update', 3, 3, @parentId, '', '', '', '', 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0');

INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted)
VALUES ('{功能}删除', '{module}:{entity}:delete', 3, 4, @parentId, '', '', '', '', 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0');

INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted)
VALUES ('{功能}导出', '{module}:{entity}:export', 3, 5, @parentId, '', '', '', '', 0, b'1', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0');

5.4 错误码定义模板

package cn.iocoder.yudao.module.{module}.enums;

import cn.iocoder.yudao.framework.common.exception.ErrorCode;

/**
 * {模块中文名}错误码枚举类
 *
 * {模块} 系统,使用 1-0XX-000-000 段
 */
public interface ErrorCodeConstants {

    // ========== {实体1} 1-0XX-000-000 ==========
    ErrorCode {ENTITY1}_NOT_EXISTS = new ErrorCode(1_0XX_000_000, "{实体中文名}不存在");
    ErrorCode {ENTITY1}_NAME_DUPLICATE = new ErrorCode(1_0XX_000_001, "已存在该名字的{实体中文名}");
    ErrorCode {ENTITY1}_STATUS_ERROR = new ErrorCode(1_0XX_000_002, "{实体中文名}状态不正确");

    // ========== {实体2} 1-0XX-001-000 ==========
    ErrorCode {ENTITY2}_NOT_EXISTS = new ErrorCode(1_0XX_001_000, "{实体中文名}不存在");
    // ... 其他错误码
}

附录:快速检查清单

新增模块检查清单

检查项 说明 状态
需求分析
业务定位明确 清晰定义模块职责和边界 [ ]
领域模型识别 聚合根、实体、值对象已识别 [ ]
设计原则确定 多租户、数据权限、设计模式 [ ]
架构设计
分层架构设计 api/controller/service/dal [ ]
模块间通信设计 对外API和依赖API [ ]
设计模式选择 策略/工厂/模板方法等 [ ]
数据库设计
表结构设计 字段类型、长度、默认值 [ ]
表关系设计 外键、关联关系 [ ]
索引设计 高频查询字段索引 [ ]
状态枚举设计 状态值、流转规则 [ ]
代码实现
DO 实体类 继承正确的基类 [ ]
Mapper 接口 继承 BaseMapperX [ ]
Service 接口和实现 @Service, @Validated 注解 [ ]
Controller 类 @RestController, 权限注解 [ ]
VO 类 参数校验注解 [ ]
API 接口 跨模块调用支持(如需要) [ ]
错误码定义 统一错误码格式 [ ]
配置文件
POM 文件 依赖配置正确 [ ]
菜单权限 SQL 功能权限配置 [ ]
测试
单元测试 Service 层测试 [ ]
集成测试 Controller 层测试 [ ]
功能测试 业务场景测试 [ ]

附录yudao 原生模块架构参考

模块 架构模式 说明
yudao-module-system 单模块模式 用户、角色、权限、部门
yudao-module-infra 单模块模式 文件、配置、定时任务、日志
yudao-module-pay 单模块模式 支付、退款、钱包
yudao-module-member 单模块模式 会员、积分、等级
yudao-module-bpm 单模块模式 工作流
yudao-module-ai 单模块模式 AI 大模型
yudao-module-mp 单模块模式 微信公众号
yudao-module-report 单模块模式 报表
yudao-module-mall 多子模块模式 商城product/promotion/trade/statistics

结论yudao 项目主流采用单模块模式,多子模块模式仅在复杂业务模块(如 mall中使用。


文档版本: 2.0.0 最后更新: 2026-06-18 维护者: AI Assistant