Skip to content

合同管理模块功能方案设计(v2 - 二次迭代版)

初版日期:2026-03-26 修订日期:2026-05-07(基于已落地实现重新整理,明确二次迭代目标) 模块名称:yudao-module-contract 文档用途:合同管理子系统的整体方案、当前实现状态、二次迭代待办清单


修订说明(与初版差异)

本次修订基于一阶段(v1)已落地代码 + 多个迭代计划文档(合同模块开发计划/合同全生命周期业务设计/合同全生命周期状态机/合同台账模块重设计/合同台账详情页改造/合同审批流程节点设计),对原方案做如下调整:

调整项初版(v1)设计二次迭代(v2)设计
功能拆分「合同台账」单一入口管理全生命周期拆分为 「合同起草」(status 0~2)+ 「合同台账」(status≥4),共用 contract_info
签署环节状态字段预留「3 签署中」但无实现新增独立流程单据 contract_sign(typeCode=203),起草审批通过后自动生成签署记录,签署确认审批通过才推进到「已生效」
签署可选强约束必须签署配置 sign_enabled 控制:开启=经签署确认才生效;关闭=审批通过直接生效
状态流转仅 0→1→2 实现完整 0→1→2→(3)→4→5→6/7→8 状态机闭环(含终止/归档/确认完成 API)
合同文件版本单字段 file_urls JSON 数组三阶段独立存储:contract_file_urls(起草稿)+ signed_file_url(签署件)+ contract_change.file_urls(变更协议),台账详情聚合展示
甲乙方录入直接填 partyA/partyB 信息新增 our_role(我方甲/乙)+ counterparty_*(对方单位),后端按角色自动映射到 partyA/partyB 字段
跨业务关联设计 biz_type + biz_id 通用字段实际改为 counterparty_type(1-CRM 客户 / 2-ERP 供应商)+ counterparty_id,弱依赖 + 选择器组件直连 CRM/ERP
变更回写仅设计未实现(v2 待办)变更审批通过后回写主合同 + 协议文件追加到合同文件版本历史
台账列表 UI普通 CRUD 列表顶部 Tabs(全部/已生效/履约中/已完成/已终止/已归档)+ 行操作按状态条件显示
台账详情单页表单多 Tab 视图(基本信息/合同文件/明细/收付款/履约/变更/附件)+ 顶栏操作按钮
CRM 合同迁移计划渐进迁移(延后)CRM 合同保持现状,新业务全部走 contract 模块

一、项目背景与目标

1.1 背景

宇擎(RuoYi Office)项目面向中小企业提供一体化办公管理平台。合同作为企业经营的核心法律文件,贯穿销售、采购、项目、人事等多个业务环节。CRM 模块虽已有一套销售合同能力,但局限明显:

  • 强绑定 CRM:与客户/商机/CRM 数据权限深度耦合,无法复用于采购、租赁、劳动等场景
  • 缺乏全生命周期:无模板、变更、补充协议、履约跟踪、归档等能力
  • 流程框架未统一:CRM 用独立 Listener 模式,未复用项目统一的 FlowBillService 框架

1.2 目标

参照泛微/蓝凌/Appian CLM 等主流方案,结合中小企业实际,建设独立的 yudao-module-contract 模块:

  1. 合同全生命周期闭环:起草 → 审批 → 签署 → 生效 → 履约 → 完成/终止 → 归档
  2. 统一所有合同类型:销售/采购/服务/租赁/劳动/框架协议
  3. 复用 OA 流程框架FlowBillService + BillCodeUtils + 三通道回调
  4. 合同文件全程跟随:起草稿 → 签署件 → 变更协议三阶段独立管理 + 台账聚合
  5. 跨模块松耦合对接:通过 ContractInfoApi Feign 接口为 CRM/ERP/HRM 提供合同数据
  6. 覆盖 80% 中小企业场景:核心能力完备,复杂场景预留扩展接口

1.3 设计原则

原则说明
统一规范严格遵循后端分层、前端组件、流程集成等已有开发范式
面向扩展合同分类、履约类型等通过字典/枚举驱动
适度简化不内置电子签章/AI 审查/在线编辑器,保留接口预留
松耦合对接通过 contract-api Feign 接口与其他模块交互
业务视角分离起草(流程视角)与台账(资产视角)拆为两个菜单入口,复用同一张表

二、整体架构

2.1 模块依赖关系

                        ┌──────────────────────────────┐
                        │   yudao-module-contract       │
                        │  ┌────────────────────────┐   │
                        │  │  contract-api          │   │ ← 对外暴露:枚举/DTO/Feign 接口
                        │  └────────────────────────┘   │
                        │  ┌────────────────────────┐   │
                        │  │  contract-server       │   │ ← 业务实现
                        │  └────────────────────────┘   │
                        └──────────────┬───────────────┘
                                       │ 依赖
                ┌──────────────────────┼──────────────────────┐
                ▼                      ▼                      ▼
        ┌──────────┐          ┌──────────┐          ┌──────────┐
        │ bpm-api  │          │system-api│          │infra-api │
        │(流程审批)│          │(用户/部门)│         │(文件服务)│
        └──────────┘          └──────────┘          └──────────┘

                          contract-api 被调用方:
                ┌──────────┐  ┌──────────┐  ┌──────────┐  ┌──────────┐
                │   CRM    │  │   ERP    │  │   HRM    │  │    OA    │
                └──────────┘  └──────────┘  └──────────┘  └──────────┘

2.2 业务全景

2.3 后端目录结构

cn.iocoder.yudao.module.contract
├── controller/admin/
│   ├── category/        # 合同分类
│   ├── template/        # 合同模板
│   ├── info/            # 合同台账(主)
│   ├── sign/            # 合同签署 ★ v2 新增
│   ├── payment/         # 收付款计划
│   ├── change/          # 合同变更
│   ├── performance/     # 合同履约
│   ├── stats/           # 统计分析
│   └── config/          # 合同配置

├── service/
│   ├── category/
│   ├── template/
│   ├── info/             # 实现 FlowBillService(contract_approve)
│   ├── sign/             # ★ v2 新增,实现 FlowBillService(contract_sign)
│   ├── payment/
│   ├── change/           # 实现 FlowBillService(contract_change)
│   ├── performance/      # 履约联动主合同状态推进
│   ├── stats/
│   ├── config/
│   └── ContractFlowBillServiceFactory.java

├── dal/dataobject/
│   ├── category/  template/  info/  item/  sign/(★)  payment/  change/  performance/  config/
├── dal/mysql/   (Mapper 同上)

├── api/                 # 对外 Feign 实现(ContractInfoApi)
├── framework/           # security/rpc 配置
├── process/             # 流程回调(mq/local/feign 三通道)
└── job/                 # 定时任务(合同到期提醒)

2.4 前端目录结构(apps/web-antd/src/

api/contract/
├── category/   template/   info/   sign/(★)   payment/   change/   performance/   stats/   config/

views/contract/
├── category/                  # 合同分类(树表 CRUD)
├── template/                  # 合同模板
├── draft/                     # ★ v2 新增「合同起草」
│   └── list/                  # 起草列表(status≤2)
├── info/
│   ├── list/                  # 合同台账列表(status≥4,顶部 Tabs)★ v2 重构
│   ├── detail/                # 起草详情/编辑(流程表单)
│   ├── ledger/                # ★ v2 新增 台账详情(多 Tab 只读)
│   └── components/            # 共享组件(CounterpartySelectModal 等)
├── sign/                      # ★ v2 新增「合同签署」
│   ├── list/                  # 签署列表
│   └── info/                  # 签署详情(含签署件上传 + 起草稿预览)
├── change/                    # 合同变更
├── performance/               # 合同履约
├── stats/                     # 统计分析
└── config/                    # 合同配置(含签署开关 ★)

2.5 移动端目录(UniApp)

ruoyi-office-uniapp/src/
├── pages-contract/            # 合同分包(v2 待办)
└── api/contract/

三、数据模型

3.1 数据库表总览

#表名说明v1 状态v2 调整
1contract_category合同分类(树形)已有不变
2contract_template合同模板已有不变
3contract_info合同主表(台账)已有新增 7 字段(生命周期+签署件+起草稿)
4contract_item合同明细行已有不变
5contract_payment_plan收付款计划已有不变
6contract_change合同变更已有新增 file_urls(变更协议文件)
7contract_performance合同履约已有不变
8contract_config合同配置(每租户一条)已有新增 sign_enabled
9contract_sign合同签署记录 ★v2 新增新表

3.2 contract_info(合同主表)

核心字段(已落地实现,注意与 v1 设计的差异):

sql
CREATE TABLE `contract_info` (
  `id`                    BIGINT       NOT NULL AUTO_INCREMENT,
  -- 基本信息
  `contract_code`         VARCHAR(64)  NOT NULL                COMMENT '合同编号',
  `contract_name`         VARCHAR(255) NOT NULL                COMMENT '合同名称',
  `category_id`           BIGINT       DEFAULT NULL            COMMENT '合同分类ID',
  `contract_type`         TINYINT      NOT NULL                COMMENT '合同类型',
  `contract_nature`       TINYINT      NOT NULL DEFAULT 1      COMMENT '合同性质',

  -- ★ v2 调整:签约主体(取代直接填写 partyA/partyB)
  `our_company_id`        BIGINT       DEFAULT NULL            COMMENT '我方主体ID(system_dept)',
  `our_company_name`      VARCHAR(255) DEFAULT NULL            COMMENT '我方主体名称',
  `our_role`              TINYINT      DEFAULT 1               COMMENT '我方角色(1甲方 2乙方)',
  `counterparty_type`     TINYINT      DEFAULT NULL            COMMENT '对方类型(1-CRM客户 2-ERP供应商)',
  `counterparty_id`       BIGINT       DEFAULT NULL            COMMENT '对方单位ID',
  `counterparty_name`     VARCHAR(255) DEFAULT NULL            COMMENT '对方单位名称',
  `counterparty_contact`  VARCHAR(64)  DEFAULT NULL            COMMENT '对方联系人',
  `counterparty_phone`    VARCHAR(32)  DEFAULT NULL            COMMENT '对方联系电话',
  `counterparty_address`  VARCHAR(512) DEFAULT NULL            COMMENT '对方地址',
  -- 甲/乙方字段由 our_role 自动映射写入
  `party_a_company_id`    BIGINT       DEFAULT NULL,
  `party_a_company_name`  VARCHAR(255) DEFAULT NULL,
  `party_b_name`          VARCHAR(255) DEFAULT NULL,
  `party_b_contact`       VARCHAR(64)  DEFAULT NULL,
  `party_b_phone`         VARCHAR(32)  DEFAULT NULL,
  `party_b_address`       VARCHAR(512) DEFAULT NULL,

  -- 金额
  `total_amount`          DECIMAL(18,2) DEFAULT 0.00           COMMENT '合同总金额',
  `performance_amount`    DECIMAL(18,2) DEFAULT 0.00           COMMENT '累计已履约金额',
  `performance_status`    TINYINT      DEFAULT 0               COMMENT '履约进度(0未 1部分 2完成)',
  `currency`              VARCHAR(16)  DEFAULT 'CNY',

  -- 日期
  `sign_date`             DATE         DEFAULT NULL            COMMENT '签订日期',
  `start_date`            DATE         DEFAULT NULL            COMMENT '生效日期',
  `end_date`              DATE         DEFAULT NULL            COMMENT '截止日期',

  -- 状态 + 流程
  `status`                TINYINT      NOT NULL DEFAULT 0      COMMENT '合同状态(0~8)',
  `process_instance_id`   VARCHAR(64)  DEFAULT NULL,
  `process_status`        TINYINT      DEFAULT 0,

  -- 组织
  `owner_user_id`         BIGINT       DEFAULT NULL,
  `owner_user_name`       VARCHAR(64)  DEFAULT NULL,
  `dept_id`               BIGINT       DEFAULT NULL,
  `dept_name`             VARCHAR(128) DEFAULT NULL,
  `company_id`            BIGINT       DEFAULT NULL,
  `company_name`          VARCHAR(255) DEFAULT NULL,

  -- 关联
  `parent_contract_id`    BIGINT       DEFAULT NULL            COMMENT '主合同ID(补充协议)',
  `biz_type`              VARCHAR(32)  DEFAULT NULL            COMMENT '业务类型(保留扩展)',
  `biz_id`                BIGINT       DEFAULT NULL            COMMENT '业务ID(保留扩展)',

  -- ★ v2 新增:合同文件(独立于 file_urls 附件)
  `contract_file_urls`    JSON         DEFAULT NULL            COMMENT '起草稿文件(JSON数组)',
  `signed_file_url`       VARCHAR(512) DEFAULT NULL            COMMENT '正式签署件URL',

  -- ★ v2 新增:生命周期字段
  `effective_date`        DATE         DEFAULT NULL            COMMENT '实际生效日期',
  `terminate_reason`      VARCHAR(500) DEFAULT NULL            COMMENT '终止原因',
  `terminate_date`        DATE         DEFAULT NULL            COMMENT '终止日期',
  `archive_date`          DATE         DEFAULT NULL            COMMENT '归档日期',
  `archive_remark`        VARCHAR(500) DEFAULT NULL            COMMENT '归档说明',
  `complete_date`         DATE         DEFAULT NULL            COMMENT '完成日期',

  -- 附件 + 备注
  `file_urls`             JSON         DEFAULT NULL            COMMENT '通用附件(报价单等)',
  `remark`                TEXT         DEFAULT NULL,
  -- 标准字段...
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_contract_code` (`contract_code`, `tenant_id`),
  KEY `idx_status` (`status`),
  KEY `idx_end_date` (`end_date`),
  KEY `idx_counterparty` (`counterparty_type`, `counterparty_id`)
);

3.3 contract_sign(合同签署记录 ★ v2 新增)

sql
CREATE TABLE `contract_sign` (
  `id`                  BIGINT       NOT NULL AUTO_INCREMENT,
  -- 单据基础
  `bill_code`           VARCHAR(50)  NOT NULL                COMMENT '签署编号',
  `process_instance_id` VARCHAR(64)  DEFAULT NULL            COMMENT '流程实例ID',
  `process_status`      TINYINT      DEFAULT 0               COMMENT '审批状态',
  -- 关联合同
  `contract_id`         BIGINT       NOT NULL                COMMENT '合同ID',
  `contract_code`       VARCHAR(50)  DEFAULT NULL            COMMENT '合同编号(冗余)',
  `contract_name`       VARCHAR(200) DEFAULT NULL            COMMENT '合同名称(冗余)',
  -- 签署信息
  `sign_method`         TINYINT      DEFAULT 1               COMMENT '签署方式(1线下 2电子)',
  `sign_date`           DATE         DEFAULT NULL            COMMENT '签署日期',
  `sign_remark`         VARCHAR(500) DEFAULT NULL            COMMENT '签署说明',
  -- 组织维度(标准)
  `company_id`          BIGINT       DEFAULT NULL,
  `company_name`        VARCHAR(200) DEFAULT NULL,
  `dept_id`             BIGINT       DEFAULT NULL,
  `dept_name`           VARCHAR(200) DEFAULT NULL,
  `owner_user_id`       BIGINT       DEFAULT NULL            COMMENT '经办人ID',
  `owner_user_name`     VARCHAR(30)  DEFAULT NULL            COMMENT '经办人姓名',
  `remark`              VARCHAR(500) DEFAULT NULL,
  -- 标准字段...
  PRIMARY KEY (`id`),
  KEY `idx_contract_id` (`contract_id`)
);

签署件文件通过 AttachmentServicebill_type=203)存储,不直接落字段;最终签署件 URL 在审批通过时回写到 contract_info.signed_file_url

3.4 contract_config(合同配置)

sql
CREATE TABLE `contract_config` (
  `id`               BIGINT NOT NULL AUTO_INCREMENT,
  `notify_enabled`   BIT(1)      DEFAULT b'1'    COMMENT '是否开启到期提醒',
  `notify_days`      INT         DEFAULT 30      COMMENT '提前提醒天数',
  `code_prefix`      VARCHAR(16) DEFAULT 'HT'    COMMENT '编号前缀',
  `code_date_format` VARCHAR(16) DEFAULT 'yyyyMMdd',
  `code_seq_length`  INT         DEFAULT 4,
  `sign_enabled`     BIT(1)      DEFAULT b'1'    COMMENT '★ 是否启用签署环节',
  -- 标准字段...
);

3.5 contract_change(合同变更)

sql
-- 在 v1 基础上新增(v2 待落地 SQL):
ALTER TABLE `contract_change`
  ADD COLUMN `file_urls` JSON DEFAULT NULL COMMENT '变更协议文件';

其余表(contract_category/contract_template/contract_item/contract_payment_plan/contract_performance)保持 v1 结构,详见初版方案附录。


四、合同状态机(v2 完整版)

4.1 状态枚举(ContractStatusEnum

名称标识说明进入方式
0草稿DRAFT初始状态创建 / 驳回 / 撤回
1审批中APPROVING起草审批进行中提交审批
2已审批APPROVED起草审批通过待签署BPM 回调
3签署中SIGNING等待双方签字盖章 + 签署确认审批签署单提交审批
4已生效EFFECTIVE合同正式生效签署确认通过 / 直接生效(sign_enabled=false)
5履约中PERFORMING正在履约登记首笔履约(自动推进)
6已完成COMPLETED履约完毕手动确认完成
7已终止TERMINATED合同被终止手动终止(填原因)
8已归档ARCHIVED归档保存手动归档(最终态)

4.2 状态流转图

4.3 流转规则

规则说明
R1 签署可跳过contract_config.sign_enabled 控制:开启=审批通过自动生成签署记录,签署确认通过才生效;关闭=审批通过直接生效
R2 签署经办人系统在起草审批通过时自动生成签署记录,经办人 = 合同负责人 owner_user_id,单人线下完成后回到系统确认
R3 履约推进已生效合同登记首笔履约时自动推进 4→5;履约金额满额时仅更新 performance_status 为 2,不自动改 status,需用户手动确认完成
R4 终止填原因已审批/签署中/已生效/履约中可终止,必须填 terminate_reason,写入 terminate_date = today()
R5 归档为终态已生效/已完成/已终止可归档,写入 archive_datearchive_remark,归档后只读

4.4 状态对应可用操作

状态可用操作操作位置
0 草稿编辑、提交审批、删除起草详情页
1 审批中撤回起草详情页 / 我的待办
2 已审批终止、(自动进入签署或直接生效)起草详情页
3 签署中签署确认(在签署单详情中)、终止签署详情页 / 台账
4 已生效登记履约、发起变更、终止、归档台账列表 / 台账详情
5 履约中登记履约、发起变更、确认完成、终止台账列表 / 台账详情
6 已完成归档台账列表 / 台账详情
7 已终止归档台账列表 / 台账详情
8 已归档仅查看台账详情

五、流程集成

5.1 单据类型(ContractBillTypeEnum

typeCode名称processDefinitionKey状态
201合同审批(起草)contract_approvev1 已实现
202合同变更审批contract_changev1 已实现
203合同签署确认contract_sign★ v2 新增

⚠️ 当前代码 BUGContractBillTypeEnum.javaCONTRACT_SIGN 误写为 ("202", "合同变更审批", "contract_change"),需修复为 ("203", "合同签署确认", "contract_sign")此为 v2 阶段必修项。

5.2 系统枚举

SystemEnum 已新增:

java
CONTRACT("CT", "合同管理")

5.3 流程回调实现(已落地)

service/
├── ContractFlowBillServiceFactory.java                # 工厂
├── info/ContractInfoServiceImpl.java                  # 实现 FlowBillService(contract_approve)
├── change/ContractChangeServiceImpl.java              # 实现 FlowBillService(contract_change)
└── sign/ContractSignServiceImpl.java                  # ★ 实现 FlowBillService(contract_sign)

process/
├── mq/ContractMqNotificationConsumer.java             # MQ 三通道
├── local/ContractLocalNotificationListener.java       # 本地事件
└── feign/ContractFeignNotificationController.java     # Feign HTTP

5.4 三个流程单据生命周期钩子

钩子contract_approve(起草)contract_change(变更)contract_sign(签署)
updateProcessStatus撤回/驳回时合同回 0 草稿撤回/驳回时变更回草稿撤回/驳回时主合同回 2 已审批
onProcessApproved1) 设状态 2 已审批
2) 读 sign_enabled:开启则生成签署记录;关闭则直接 4 已生效 + effective_date
(v2 待办) 回写主合同字段 + 协议文件追加到合同文件版本1) 读签署件附件
2) 回写到 signed_file_url
3) 主合同设 4 已生效 + effective_date
onProcessRejected合同回 0 草稿变更回草稿主合同回 2 已审批
onProcessCancelled合同回 0 草稿变更回草稿主合同回 2 已审批
deleteBill删合同主表 + 明细删变更记录删签署记录 + 附件

5.5 BPM 流程模型设计

详见 合同审批流程节点设计.md

contract_approve(起草审批)

发起人 → 部门负责人 → 合同专员审核 → 条件分支
                                      ├─ 金额≤10万 → 分管领导审批 → 结束
                                      └─ 金额>10万  → 主要领导审批 → 结束

contract_change(变更审批)

发起人 → 部门负责人 → 合同专员审核 → 分管领导审批 → 结束

contract_sign(签署确认审批)★ v2 新增

发起人(经办人上传签署件) → 合同专员审核文件合规性 → 结束

候选人岗位:

  • subLeader(分管领导)、mainLeader(主要领导)—— 已有
  • CONTRACT_SPECIALIST(合同专员)—— v1 已新增

六、核心功能详细设计

6.1 合同分类管理

参照 v1 设计,已落地实现,无变化。

6.2 合同模板管理

参照 v1 设计,已落地实现,无变化。

6.3 合同起草(v2 新增菜单 / status≤2)

菜单contract-draft-list,组件 ContractDraftList,路径 views/contract/draft/list/

列表页(仅展示自己起草、status≤2 的合同):

  • 后端通过 ContractInfoPageReqVO.statusMax=2 范围筛选
  • 列:合同编号 / 名称 / 类型 / 金额 / 审批状态 / 操作
  • 操作:编辑(草稿态)/ 删除(草稿态)/ 查看
  • 顶部按钮:新建合同、导出

详情页views/contract/info/detail/index.vue):

  • BasicForm + formSchema:基本信息(编号/名称/类型/性质/分类/我方主体/我方角色/对方类型/对方单位/金额/币种/三个日期/负责人/备注)
  • 子表区域:
    • 合同明细行(ContractItemTable
    • 收款计划(PaymentPlanGrid
    • ★ v2 待办:合同文件(起草稿)独立卡片(绑定 contractFileUrls
    • 附件列表(绑定 fileUrls
  • 流程操作:保存草稿 / 提交审批 / 撤回 / 删除 / 关闭

6.4 合同签署(★ v2 新增)

菜单contract-sign-list,详情 contract-sign-detail(隐藏菜单)

列表页views/contract/sign/list/):

  • 列:签署编号 / 关联合同编号 / 合同名称 / 经办人 / 签署状态 / 操作
  • 操作:草稿态 = 编辑/删除/提交;其他 = 查看

详情页views/contract/sign/info/index.vue):

  • BasicForm:签署编号(只读)/ 关联合同(只读链接)/ 签署方式 / 签署日期 / 签署说明
  • #form-extension 插槽:
    • 签署件上传AttachmentList,必须,PDF/扫描件,限制 5 个、50MB)
    • 合同起草稿(只读预览)(从 contractInfo.contractFileUrls 加载)
  • beforeApproval:动态字段权限驱动,校验通过自动保存
  • 提交前置:必须已上传签署件

6.5 合同台账(v2 重构 / status≥4)

菜单contract-info-list(重定位为台账),详情 contract-ledger-detail(隐藏菜单)

6.5.1 列表页(views/contract/info/list/index.vue

┌─────────────────────────────────────────────────────┐
│ Tabs: [全部] [已生效] [履约中] [已完成] [已终止] [已归档] │
│ 搜索: 编号 / 名称 / 类型 / 分类 / 对方单位 / 创建时间    │
│ Grid:                                                │
│   编号(链接到台账详情) / 名称 / 类型 / 对方 / 金额    │
│   / 状态(Tag) / 履约进度(Progress) / 负责人          │
│   / 生效日期 / 截止日期 / 操作                        │
│ 行操作(按 status 显示):                             │
│   4 已生效: 登记履约 / 发起变更 / 终止 / 归档          │
│   5 履约中: 登记履约 / 发起变更 / 确认完成 / 终止       │
│   6 已完成: 归档                                      │
│   7 已终止: 归档                                      │
│   8 已归档: 仅查看                                    │
└─────────────────────────────────────────────────────┘

后端通过 ContractInfoPageReqVO.statusMin=4 + Tab 切换的精确 status 区分。

6.5.2 详情页(views/contract/info/ledger/index.vue

┌─────────────────────────────────────────────────────┐
│ 顶栏: [返回列表] 编号 名称 [状态Tag] | 操作按钮区     │
│   操作按钮按 status 动态显示:                          │
│     4: [登记履约] [发起变更] [归档] [终止]            │
│     5: [登记履约] [发起变更] [确认完成] [终止]        │
│     6/7: [归档]                                      │
├─────────────────────────────────────────────────────┤
│ Tabs:                                                │
│   1) 基本信息   - Descriptions 只读 + 生命周期信息    │
│   2) 合同文件   - 聚合起草稿+签署件+变更协议三阶段     │
│   3) 合同明细   - ContractItemTable 只读             │
│   4) 收款计划   - PaymentPlanGrid 只读               │
│   5) 履约记录   - VxeGrid                            │
│   6) 变更记录   - VxeGrid                            │
│   7) 附件信息   - AttachmentList 只读                 │
└─────────────────────────────────────────────────────┘

合同文件 Tab 聚合规则(前端 buildContractFiles()):

  • contract_file_urls JSON 数组 → 每项标记为 phase=draft, phaseLabel=起草稿
  • signed_file_url 字符串 → 标记为 phase=signed, phaseLabel=签署件
  • 每条 contract_change.file_urls → 标记为 phase=change, phaseLabel=变更协议(变更编号)

6.6 合同变更(v2 增强)

当前已有:基本 CRUD + 提交审批 + 列表/详情。

v2 待办

  1. 变更详情表单新增「变更协议文件」上传卡片(AttachmentListfile_urls 字段直接绑定)
  2. 提交前校验:变更协议文件必须上传
  3. onProcessApproved 回写主合同(当前为 TODO):
    • change_type=1 金额变更 → 更新 contract_info.total_amount
    • change_type=2 期限变更 → 更新 contract_info.end_date
    • 其他变更类型 → 写履历,不强制改字段
  4. 变更协议文件追加到 contract_info.contract_file_urls,便于在台账详情统一查看

6.7 合同履约(v2 增强已落地)

已实现

  • CRUD + 履约金额自动汇总(syncContractPerformanceStats
  • 履约状态推导(0 未/1 部分/2 完成)

v2 待办

  • 前置校验:createPerformance 中校验合同 status ∈ [4, 5]
  • 首笔履约自动推进 status 4 → 5(当前 syncContractPerformanceStats 仅更新 performance_status,未推进 status
  • 履约金额满额时返回前端提示("已达合同总金额,是否确认完成?")

6.8 收付款计划

参照 v1 设计,已落地实现。

6.9 合同配置(v2 增强)

已实现:编号规则(前缀+日期格式+流水位数)、到期提醒(开关+天数)、sign_enabled DO 字段。

v2 待办:前端 views/contract/config/index.vue 新增「签署环节开关」Switch 组件。

6.10 统计分析

参照 v1 设计,已落地实现 8 个概览指标 + 月度统计 + 分类统计。

v2 增强建议(可选):

  • 合同生命周期分布(按 status 统计)
  • 履约完成率 Top10 / Bottom10
  • 即将到期合同列表(近 30 天 end_date < today + notify_days)
  • 收付款逾期统计

七、字典数据

字典类型字典名称字典值状态
contract_type合同类型1-销售 / 2-采购 / 3-服务 / 4-租赁 / 5-劳动 / 6-框架 / 99-其他已有
contract_nature合同性质1-收入 / 2-支出 / 3-无金额已有
contract_status合同状态0~8已有(v2 完整使用)
contract_change_type变更类型1-金额 / 2-期限 / 3-条款 / 4-范围 / 99-其他已有
contract_performance_type履约类型1-交付 / 2-验收 / 3-开票 / 4-收款 / 5-付款 / 6-服务交付 / 99-其他已有
contract_payment_status收付款状态0-待 / 1-已 / 2-逾期已有
contract_sign_method签署方式1-线下 / 2-电子(预留)v2 新增
contract_our_role我方角色1-甲方 / 2-乙方v2 新增
contract_counterparty_type对方类型1-CRM 客户 / 2-ERP 供应商v2 新增

八、跨模块对接

8.1 contract-api 已暴露接口

java
public interface ContractInfoApi {
    ContractInfoDTO getContract(Long id);
    List<ContractInfoDTO> getContractList(List<Long> ids);
    List<ContractInfoDTO> getSimpleContractList();
}

8.2 v2 待补充接口

java
// 履约汇总(CRM 回款页等场景使用)
ContractPerformanceSummaryDTO getPerformanceSummary(Long contractId);

// 跨模块新增履约记录(CRM 回款 / ERP 入库自动写入)
Long addPerformanceRecord(ContractPerformanceCreateReqDTO dto);

// 通过对方单位反查合同
List<ContractInfoDTO> getContractsByCounterparty(Integer counterpartyType, Long counterpartyId);

8.3 与各业务模块对接

模块对接方式状态
CRM创建销售合同时通过 CounterpartySelectModal 选择客户(counterparty_type=1已实现
ERP创建采购合同时通过 CounterpartySelectModal 选择供应商(counterparty_type=2已实现
CRM 回款回款完成后通过 ContractInfoApi.addPerformanceRecord 自动写入履约v2 待办
ERP 入库入库时调用 addPerformanceRecord 写入交付记录v2 待办
OA 用印用印申请关联合同(用合同选择器)v2 待办
HRM 入职自动创建劳动合同(contract_type=5v2 待办

九、合同文件全生命周期管理

9.1 文件三阶段独立存储

阶段字段存储方式上传时机
起草稿contract_info.contract_file_urls(JSON)直接落表,多版本起草草稿阶段(v2 待落地前端独立卡片)
签署件contract_info.signed_file_url单字段 + 通过 AttachmentServicebill_type=203)管理上传签署详情页提交前必须上传,审批通过自动回写
变更协议contract_change.file_urls(JSON)直接落表变更提交前上传(v2 待落地校验)
附件contract_info.file_urls(JSON)通用附件(报价单/需求文档等)起草任意阶段
履约凭证contract_performance.file_url单字段登记履约时上传

9.2 台账详情聚合

台账详情「合同文件」Tab 自动聚合三个阶段的文件,列表展示 阶段 / 文件名 / 时间 / 操作,支持预览和下载。

9.3 预览策略(沿用项目统一方案)

文件类型PC 端移动端
PDFiframe 内嵌 / KKFileViewuni.openDocument
Word/Excel@vue-office/docx excel / KKFileViewuni.openDocument
图片Ant Design Vue Imageuni.previewImage
其他KKFileView 或下载uni.openDocument

十、二次迭代(v2)待办清单

阶段 A:BUG 修复 + 后端能力补齐(优先)

#任务涉及文件优先级
A1修复 ContractBillTypeEnum.CONTRACT_SIGN 误用 202/contract_change 的 BUGyudao-module-contract-api/.../ContractBillTypeEnum.java★★★
A2ContractChangeServiceImpl.onProcessApproved 回写主合同:金额变更→更新 total_amount,期限变更→更新 end_date,并把变更协议追加到 contract_file_urlsservice/change/ContractChangeServiceImpl.java★★★
A3履约前置校验 + 首笔履约自动推进 4→5service/performance/ContractPerformanceServiceImpl.java★★
A4ContractInfoApi 补充 3 个跨模块接口(履约汇总/添加履约/按对方反查)contract-api/.../ContractInfoApi.java + 实现★★
A5contract_change.file_urls SQL 字段(如尚未实际存在)ruoyi-office-db/{今天}_update/alter_contract_change_file_urls.sql★★

阶段 B:前端补齐与体验优化

#任务涉及文件优先级
B1起草详情页新增「合同文件(起草稿)」独立卡片,绑定 contractFileUrlsviews/contract/info/detail/index.vue + data.ts★★★
B2合同配置页新增「签署环节开关」SwitchsignEnabledviews/contract/config/index.vue★★★
B3变更详情页新增「变更协议文件」上传卡片 + 提交校验views/contract/change/modules/form.vue + API★★
B4API 类型补全ContractInfoApi.ContractInfo 增加 effectiveDate / terminateReason / terminateDate / archiveDate / archiveRemark / completeDate / contractFileUrls / signedFileUrlapi/contract/info/index.ts★★
B5履约金额满额前端提示框views/contract/performance/modules/form.vue

阶段 C:移动端

#任务涉及文件优先级
C1UniApp 合同台账列表(仅查看 status≥4)pages-contract/index.vue★★
C2UniApp 合同台账详情(多 Tab 风格简化)pages-contract/detail/index.vue★★
C3UniApp 合同审批接入(起草/变更/签署三个流程详情页)pages-bpm/ 配置 + 三个 detail 页★★
C4API 层 api/contract/index.ts移动端工程★★

阶段 D:BPM 流程模型部署

#任务涉及文件优先级
D1在 BPM 设计器中创建并部署 contract_approve 模型(按金额分支)BPM 后台★★★
D2在 BPM 设计器中创建并部署 contract_change 模型BPM 后台★★★
D3★ 在 BPM 设计器中创建并部署 contract_sign 模型BPM 后台★★★
D4给关键候选岗位绑定用户(合同专员/分管领导/主要领导)system_user_post★★

阶段 E:定时任务与运营

#任务涉及文件优先级
E1合同到期提醒定时任务(按 notify_days 触发,未实现)job/ContractExpireRemindJob.java★★
E2收付款逾期检查定时任务(更新 contract_payment_plan.status=2job/ContractPaymentOverdueJob.java

阶段 F:跨模块对接落地

#任务模块优先级
F1CRM 回款完成后调用 addPerformanceRecord 自动写入履约yudao-module-crm★★
F2ERP 入库/付款联动履约写入yudao-module-erp★★
F3OA 用印申请增加合同选择器yudao-module-oa
F4HRM 入职流程触发劳动合同创建yudao-module-hrm

阶段 G:统计分析增强(可选)

#任务优先级
G1合同生命周期分布饼图(按 status 统计)
G2履约完成率排行
G3即将到期合同列表

十一、关键设计决策

11.1 为什么拆分「起草」和「台账」?

视角起草(流程视角)台账(资产视角)
关注点我有哪些合同正在审批/拟稿公司当前生效的合同资产
数据范围status ≤ 2 + 自己创建的status ≥ 4 + 全部数据权限范围
页面形态列表 + 表单(可编辑)列表(顶部 Tabs)+ 多 Tab 详情(只读 + 操作按钮)
入口「合同起草」菜单「合同台账」菜单
数据存储共用 contract_info 表,通过 status 区分

11.2 为什么签署做成独立流程单据?

参照 OA「用车申请→还车确认」、「公文发文→收文」模式:

  • 业务实质:起草是"申请合同生效",签署是"确认签署完成",是两个独立审批
  • 审批人不同:起草由领导审批,签署由合同专员审核文件合规性
  • 可选性:通过 sign_enabled 配置开关,小企业可关闭签署直接生效
  • 复用框架:与 contract_approvecontract_change 完全对称地实现 FlowBillService

11.3 为什么用 our_role + counterparty_* 取代直填 partyA/partyB?

  • 业务直观:用户思维是"我方/对方",而不是"甲方/乙方"
  • 自动联动our_role 决定了甲乙方对应关系,前端不需要分别填两套
  • 跨模块复用counterparty_type + counterparty_id 可直接关联 CRM 客户 / ERP 供应商,避免手填错误
  • 甲乙方仍保留:用于合同打印、对外展示等场景,由后端 mapPartyByOurRole() 自动映射

11.4 为什么合同文件分三阶段独立存储?

  • 审计需要:每个阶段的文件是不可变的历史记录
  • 权限分离:起草稿可在草稿态修改,签署件审批通过后只读
  • 统一聚合:台账详情通过前端聚合展示版本历史,无需后端额外建表
  • 扩展性:未来加入电子签章时,只需在 signed_file_url 旁加 electronic_seal_url 等字段

11.5 中小企业简化策略

简化项当前做法扩展预留
电子签章不内置,附件上传盖章 PDF预留 sign_method=2 电子签署 枚举
AI 合规检查通过审批流程人工把关未来可对接 AI 模块
在线编辑器模板下载本地 Word/WPS 编辑未来可集成 OnlyOffice
多币种汇率仅记录币种预留 currency 字段
多级审批矩阵用 BPM 标准条件分支BPM 自身支持
数据权限标准租户 + 部门权限未来加细粒度

十二、文档关联

相关文档用途
合同审批流程节点设计.mdBPM 设计器配置参考
合同管理模块业务流程测试用例.md集成测试场景
ruoyi-office-prompt/cursor/plans/合同模块开发计划_f7cadc9e.plan.md一阶段(v1)开发计划
ruoyi-office-prompt/cursor/plans/合同全生命周期业务设计_78230c32.plan.mdv2 业务设计计划
ruoyi-office-prompt/cursor/plans/合同全生命周期状态机_74e6923e.plan.mdv2 状态机设计
ruoyi-office-prompt/cursor/plans/合同台账模块重设计_14a8a008.plan.mdv2 台账列表/详情重设计
ruoyi-office-prompt/cursor/plans/合同台账详情页改造_4db6bb73.plan.mdv2 台账详情多 Tab 改造

十三、版本历史

版本日期主要变更
v12026-03-26初版方案:8 张表、起草+审批+履约
v1.12026-03-30新增合同专员岗位 + 流程节点设计
v22026-05-07本次修订:起草/台账分离、签署独立流程、状态机闭环、合同文件三阶段、台账多 Tab UI、跨模块对接接口规划

附录 A:v2 已实现 vs 待办速览

✅ 已落地(v2 阶段)

  • 9 张表(含 contract_sign)+ 全部 v2 新增字段 SQL
  • ContractStatusEnum 枚举类
  • 合同台账生命周期 API(terminate/archive/confirmComplete)
  • 合同签署 Service/Controller + FlowBillService 实现
  • 起草审批通过自动生成签署记录 / 直接生效(按 sign_enabled 分流)
  • 签署审批通过回写 signed_file_url + 推进 4 已生效
  • 前端「合同起草」菜单 + 列表(status≤2
  • 前端「合同台账」列表重构(顶部 Tabs + 行操作按状态)
  • 前端「合同台账详情」多 Tab(基本信息/合同文件/明细/收付款/履约/变更/附件)
  • 前端「合同签署」菜单 + 列表 + 详情(含签署件上传 + 起草稿预览)
  • 后端 ContractInfoPageReqVO 增加 statusMin/statusMax/processStatus
  • 合同文件三阶段聚合展示(起草稿+签署件+变更协议)

🔧 待办(v2 收尾)

  • A1 修复 ContractBillTypeEnum.CONTRACT_SIGN BUG(最高优先级)
  • A2 ContractChangeServiceImpl.onProcessApproved 实现回写主合同
  • A3 履约前置校验 + 首笔自动推进
  • A4 ContractInfoApi 补充跨模块接口
  • B1 起草详情页「合同文件(起草稿)」独立卡片
  • B2 合同配置页「签署开关」前端
  • B3 变更详情页「变更协议文件」上传
  • B4 前端 API TypeScript 类型补全
  • C1~C4 移动端 UniApp 全套
  • D1~D4 BPM 流程模型在设计器中实际部署
  • E1~E2 定时任务(到期提醒/收付款逾期)
  • F1~F4 跨模块对接落地(CRM/ERP/OA/HRM)
  • G1~G3 统计分析增强(可选)
联系我们

获取报价、演示和二开方案

微信咨询二维码

微信咨询

17156169080

添加时备注「RuoYi Office」

在线体验商业版