Przeglądaj źródła

docs(S1): restore approval flow plan v2.0 + version bump (Web 2.4.47 / API 1.0.11)

aidopdev 2 miesięcy temu
rodzic
commit
164bd0f5e3

+ 1 - 1
Web/package.json

@@ -1,7 +1,7 @@
 {
 	"name": "admin.net",
 	"type": "module",
-	"version": "2.4.46",
+	"version": "2.4.47",
 	"packageManager": "pnpm@10.32.1",
 	"lastBuildTime": "2026.03.15",
 	"description": "Admin.NET 站在巨人肩膀上的 .NET 通用权限开发框架",

+ 1197 - 0
doc/plan/S1/S1-订单管理-审批流程实施方案.md

@@ -0,0 +1,1197 @@
+# S1 产销协同 — 订单管理 · 审批流程实施方案
+
+> **版本**:v2.0 · 2026-04-15(决策确认版)  
+> **范围**:合同评审、订单评审、订单交付、订单发货  
+> **目标**:基于 Admin.NET 现有审批流程插件(方案 B),补全流程运行时引擎,实现**仅通过配置(画流程图 + 设节点属性)即可创建和运行各类审批业务流程**
+
+---
+
+## 目录
+
+0. [决策记录](#0-决策记录)
+1. [现有审批流程插件评估](#1-现有审批流程插件评估)
+2. [差距分析与问题清单](#2-差距分析与问题清单)
+3. [整体架构方案](#3-整体架构方案)
+4. [数据模型设计](#4-数据模型设计)
+5. [后端核心改造](#5-后端核心改造)
+6. [前端核心改造](#6-前端核心改造)
+7. [通知机制设计](#7-通知机制设计)
+8. [业务联动:回调注册机制](#8-业务联动回调注册机制)
+9. [S1 订单管理业务接入示例](#9-s1-订单管理业务接入示例)
+10. [配置化使用指南](#10-配置化使用指南)
+11. [实施路线图](#11-实施路线图)
+
+---
+
+## 0. 决策记录
+
+> 以下为 2026-04-15 商议确认的方案决策,作为后续实施的依据。
+
+### 0.1 总体方案
+
+| 决策项 | 决策结果 |
+|--------|---------|
+| 技术路线 | **方案 B**:基于现有 `Admin.NET.Plugin.ApprovalFlow` 插件增量扩展 |
+| 配置化目标 | 业务流程(合同评审、订单评审等)**仅通过配置**即可创建,无需写审批引擎代码 |
+| 配置化边界 | L1(流程图+审批人)+ L2(条件分支)纯配置化;L3(业务联动)通过轻量回调注册机制 |
+
+### 0.2 功能范围
+
+| 决策项 | 决策结果 |
+|--------|---------|
+| 流程发起方式 | **A+C 兼备**:业务表单内嵌入 `<ApprovalPanel>` 快捷发起 + 审批中心统一发起入口 |
+| 审批人类型 | **指定用户、指定角色、指定部门、发起人本人**(4 种);发起人上级、表单字段值后续扩展 |
+| 多人审批模式 | **或签 + 会签**;依次审批后续扩展 |
+| 审批操作 | **全部实现**:同意、拒绝、转办、撤回、退回上一步、加签、催办(共 7 种) |
+| 通知机制 | **全部实现**,按优先级分批交付:页面待办 → SignalR 站内信 → 钉钉/企微 → 邮件/短信 |
+| 条件分支 | 排他网关 + 简单条件表达式(配置化) |
+| 与现有代码关系 | **先并行**:保留原有 SeOrder 硬编码 API,新增审批流驱动路径,验证可用后再切换 |
+| 业务联动 | 回调注册机制(`IFlowBizHandler` 接口),每种业务类型实现一个 Handler(约 10-20 行代码) |
+
+### 0.3 插件现状说明
+
+> Admin.NET 框架定位为"通用权限开发平台"(RBAC),**审批流程不在其官方 26 项内置功能清单中**。
+> `Admin.NET.Plugin.ApprovalFlow` 是一个**插件骨架示例**,提供了流程定义 CRUD + LogicFlow 画布,
+> 但**不包含运行时引擎**(状态机推进、审批人分配、待办/已办、同意/拒绝等操作)。
+> 这是框架设计如此,非版本过旧或获取不完整。本方案的核心工作是补齐运行时部分。
+
+---
+
+## 1. 现有审批流程插件评估
+
+### 1.1 已有能力(可复用)
+
+| 层面 | 现状 | 可用性 |
+|------|------|--------|
+| **流程定义 CRUD** | `ApprovalFlowService` 提供增删改查、分页、详情 | ✅ 可用 |
+| **流程设计器(前端)** | LogicFlow 2.x 画布 + BPMN 节点 + 拖拽面板 + 小地图 + 快照导出 | ✅ 基本可用 |
+| **流程 JSON 持久化** | `FlowJson`(nodes/edges)+ `FormJson`(数据库/表/操作类型)存于 `approval_flow` 表 | ✅ 可用 |
+| **表单关联** | `editFormDialog.vue` 可选择数据库、数据表、操作类型 | ⚠️ 仅存储元数据,不生成动态表单 |
+| **菜单种子** | `SysMenuSeedData.cs` 已注册 `/platform/approvalFlow` 菜单 | ✅ 可用 |
+| **中间件匹配** | `ApprovalFlowMiddleware` + `SysApprovalService.MatchApproval` | ⚠️ 仅做记录,不阻断 |
+
+### 1.2 插件代码结构
+
+```
+server/Plugins/Admin.NET.Plugin.ApprovalFlow/
+├── Entity/
+│   ├── ApprovalFlow.cs           # 流程定义(模板)
+│   ├── ApprovalFlowRecord.cs     # 流程实例记录(简陋)
+│   ├── ApprovalForm.cs           # 表单定义(未使用)
+│   └── ApprovalFormRecord.cs     # 表单变更记录
+├── Enum/
+│   └── FlowTypeEnum.cs           # 空枚举(占位)
+├── Middleware/
+│   └── ApprovalFlowMiddleware.cs # 请求中间件
+├── Service/
+│   ├── ApprovalFlow/
+│   │   ├── ApprovalFlowService.cs    # CRUD + FlowList + FormRoutes
+│   │   └── Dto/
+│   │       ├── ApprovalFlowItem.cs   # FlowJson 的 nodes/edges 结构
+│   │       ├── ApprovalFormItem.cs   # FormJson 结构 + Route 计算
+│   │       ├── ApprovalFlowInput.cs  # 分页/筛选/增删改查入参
+│   │       └── ApprovalFlowOutput.cs # 列表/详情出参
+│   └── SysApproval/
+│       └── SysApprovalService.cs     # 中间件调用的匹配逻辑
+├── SeedData/
+│   └── SysMenuSeedData.cs
+├── Configuration/
+│   └── ApprovalFlow.json
+├── Startup.cs
+└── GlobalUsings.cs
+```
+
+**前端**(`Web/src/views/approvalFlow/`):
+
+```
+index.vue                           # 列表主页
+component/
+├── editDialog.vue                  # 基本信息编辑
+├── editFormDialog.vue              # 表单(DB 元数据)编辑
+├── editFlowDialog.vue              # LogicFlow 流程设计器
+├── detailDialog.vue                # 详情查看
+└── LogicFlow/
+    ├── Panel/
+    │   ├── PanelControl.vue        # 工具栏(缩放/撤销/截图/小地图)
+    │   ├── PanelNode.vue           # 节点拖拽面板
+    │   └── PanelDataDialog.vue     # JSON 数据查看
+    └── Property/
+        ├── PropertyDialog.vue      # 属性面板容器
+        └── PropertyCommon.vue      # 节点基本信息(只读 id/type)
+```
+
+---
+
+## 2. 差距分析与问题清单
+
+### 2.1 关键缺失
+
+| # | 缺失项 | 严重度 | 说明 |
+|---|--------|--------|------|
+| G1 | **流程运行时引擎** | 🔴 致命 | 无节点推进、无状态机、无自动流转逻辑;中间件只插入记录不阻断请求 |
+| G2 | **审批人/角色指派** | 🔴 致命 | `FlowProperties` 是空类 `{}`;节点上无法配置审批人、角色、部门 |
+| G3 | **审批操作 API** | 🔴 致命 | 无"同意/拒绝/转办/加签/撤回/退回/催办"等运行时操作接口 |
+| G4 | **待办/已办查询** | 🔴 致命 | 无按用户查询待审批、已审批、我发起的流程等 API |
+| G5 | **条件分支执行** | 🟡 重要 | LogicFlow 画布可画网关,但后端无条件判断执行逻辑 |
+| G6 | **会签/或签** | 🟡 重要 | 无多人审批聚合模式 |
+| G7 | **通知机制** | 🟡 重要 | 无站内信/WebSocket/邮件/钉钉推送集成 |
+| G8 | **节点属性编辑** | 🟢 一般 | 前端 PropertyCommon 只读显示 id/type,扩展信息为空 |
+
+### 2.2 现有代码问题
+
+| # | 问题 | 风险 | 处理方式 |
+|---|------|------|---------|
+| B1 | `SysApprovalService.MatchApproval` 对**每个请求**都执行 DB 查询 | 高 | 改为启动时缓存 + 事件刷新 |
+| B2 | 路由匹配用 `Contains` 子串匹配,容易误匹配 | 中 | 改为精确路径比较 |
+| B3 | `FlowList` 用 `FirstAsync()` 查询,code 不存在时直接抛异常 | 中 | 改为 `FirstOrDefaultAsync` + 空校验 |
+| B4 | `ApprovalFormItem.Route` 在 `EntityName` 为 null/空时抛异常 | 中 | 加空值保护 |
+| B5 | `FlowProperties` 空类导致节点自定义属性无法存储 | 高 | 改为结构化定义 |
+| B6 | `FlowTypeEnum` 为空枚举 | 低 | 补充定义 |
+| B7 | 前端 undo/redo 按钮始终 disabled | 低 | 绑定 LogicFlow history 事件 |
+| B8 | 中间件构造函数用 `App.GetRequiredService` 而非 DI | 低 | 改为 `InvokeAsync` 参数注入 |
+
+---
+
+## 3. 整体架构方案
+
+### 3.1 方案选型(已确认:方案 B)
+
+| 方案 | 描述 | 结论 |
+|------|------|------|
+| A. 引入第三方引擎(Elsa 3.x) | NuGet 引入 Elsa | ❌ 不采用 |
+| **B. 基于现有插件增量扩展** | 补齐运行时引擎 | ✅ **已确认采用** |
+| C. 完全自建新插件 | 从头新建 | ❌ 不采用 |
+
+### 3.2 架构全景
+
+```
+┌─────────────────────────────────────────────────────────────────────┐
+│                          前端 (Vue 3)                                │
+│                                                                     │
+│  ┌──────────────┐  ┌───────────────┐  ┌──────────────────────────┐ │
+│  │ 流程设计器    │  │  业务表单      │  │   审批中心                │ │
+│  │ (LogicFlow)  │  │ + ApprovalPanel│  │ 待办/已办/我发起的/时间线 │ │
+│  └──────┬───────┘  └──────┬────────┘  └────────────┬─────────────┘ │
+└─────────┼─────────────────┼────────────────────────┼───────────────┘
+          │ 设计/发布        │ 发起/查看               │ 审批操作
+          ▼                 ▼                        ▼
+┌─────────────────────────────────────────────────────────────────────┐
+│                          后端 API 层                                 │
+│                                                                     │
+│  ┌──────────────┐  ┌──────────────┐  ┌──────────────────────────┐  │
+│  │ ApprovalFlow │  │ FlowInstance │  │ FlowTask                 │  │
+│  │   Service    │  │   Service    │  │  Service                 │  │
+│  │ (流程定义    │  │ (流程实例    │  │ (审批任务                │  │
+│  │  CRUD+发布)  │  │  发起/查询)  │  │ 同意/拒绝/转办/撤回      │  │
+│  └──────────────┘  └──────────────┘  │ 退回/加签/催办)          │  │
+│                                      └──────────────────────────┘  │
+│                           │                                        │
+│                  ┌────────▼────────┐                               │
+│                  │  FlowEngine     │  ← 核心推进引擎               │
+│                  │ ┌─────────────┐ │                               │
+│                  │ │ 状态机      │ │                               │
+│                  │ │ 条件分支    │ │                               │
+│                  │ │ 审批人解析  │ │                               │
+│                  │ │ 会签/或签   │ │                               │
+│                  │ └─────────────┘ │                               │
+│                  └────────┬────────┘                               │
+│                           │                                        │
+│         ┌─────────────────┼──────────────────┐                     │
+│         ▼                 ▼                  ▼                     │
+│  ┌────────────┐  ┌──────────────┐  ┌──────────────┐              │
+│  │ 通知服务    │  │ 回调注册     │  │ 审计日志     │              │
+│  │ SignalR     │  │ IFlowBiz-    │  │ FlowLog      │              │
+│  │ 钉钉/企微   │  │ Handler      │  │              │              │
+│  │ 邮件/短信   │  │ (业务联动)   │  │              │              │
+│  └────────────┘  └──────────────┘  └──────────────┘              │
+└─────────────────────────────────────────────────────────────────────┘
+          │
+          ▼
+┌─────────────────────────────────────────────────────────────────────┐
+│                          数据层 (MySQL)                               │
+│                                                                     │
+│  approval_flow           流程定义(模板)      ← 已有,需扩展        │
+│  approval_flow_instance  流程实例              ← 新增                │
+│  approval_flow_task      审批任务              ← 新增                │
+│  approval_flow_log       操作日志              ← 新增                │
+└─────────────────────────────────────────────────────────────────────┘
+```
+
+### 3.3 关键设计决策
+
+**1) 节点定义不单独建表,存在 FlowJson 中**
+
+经考量,`approval_flow_node` 独立表会导致 FlowJson 与 Node 表的双重维护和同步问题。改为:
+
+- **前端 LogicFlow** 保存时将节点属性(审批人、审批方式等)写入每个 node 的 `properties` 字段
+- **后端** 读取 `FlowJson` 并反序列化得到节点列表,无需额外 Node 表
+- `FlowProperties` 从空类改为结构化类型,包含审批人配置
+
+这样 LogicFlow 画布即唯一数据源,前端所见即所得。
+
+**2) 中间件改为可选审计模式**
+
+`ApprovalFlowMiddleware` 不再用于核心审批推进。审批操作全部通过显式 API 调用完成。中间件保留但优化:仅做审计日志,按需开关。
+
+---
+
+## 4. 数据模型设计
+
+### 4.1 流程定义表(扩展现有 `approval_flow`)
+
+保留现有字段(`Id`, `Code`, `Name`, `FormJson`, `FlowJson`, `Status`, `Remark`),**新增**:
+
+| 字段 | 类型 | 说明 |
+|------|------|------|
+| `BizType` | `string(64)` | 业务类型编码,如 `CONTRACT_REVIEW`、`ORDER_REVIEW`。配置化关键字段 |
+| `Version` | `int` | 版本号,每次发布 +1 |
+| `IsPublished` | `bool` | 是否已发布(只有已发布的流程可以被发起) |
+
+### 4.2 FlowJson 中的节点属性结构(`FlowProperties` 改造)
+
+不单独建 Node 表,而是将节点配置嵌入 `FlowJson` 的每个 node.properties 中:
+
+```json
+{
+  "nodes": [
+    {
+      "id": "node_1",
+      "type": "bpmn:userTask",
+      "x": 300, "y": 200,
+      "text": { "value": "意见评审" },
+      "properties": {
+        "nodeName": "意见评审",
+        "approverType": "Role",
+        "approverIds": "1001,1002",
+        "approverNames": "销售部,技术部",
+        "multiApproveMode": "Any",
+        "timeoutHours": 48,
+        "timeoutAction": "Notify"
+      }
+    },
+    {
+      "id": "gateway_1",
+      "type": "bpmn:exclusiveGateway",
+      "properties": {
+        "conditions": [
+          {
+            "targetNodeId": "node_gm",
+            "expression": "bizData.contractAmount > 1000000",
+            "label": "金额>100万"
+          },
+          {
+            "targetNodeId": "node_dept",
+            "expression": "bizData.contractAmount <= 1000000",
+            "label": "金额≤100万",
+            "isDefault": true
+          }
+        ]
+      }
+    }
+  ],
+  "edges": [ ... ]
+}
+```
+
+对应 C# 反序列化结构:
+
+```csharp
+public class FlowProperties
+{
+    // ── 用户任务节点属性 ──
+    public string? NodeName { get; set; }
+    public string? ApproverType { get; set; }       // SpecificUser / Role / Department / Initiator
+    public string? ApproverIds { get; set; }         // 逗号分隔
+    public string? ApproverNames { get; set; }       // 冗余,便于前端展示
+    public string? MultiApproveMode { get; set; }    // Any / All
+    public int? TimeoutHours { get; set; }
+    public string? TimeoutAction { get; set; }       // AutoApprove / AutoReject / Notify
+
+    // ── 网关节点属性 ──
+    public List<GatewayCondition>? Conditions { get; set; }
+}
+
+public class GatewayCondition
+{
+    public string TargetNodeId { get; set; }
+    public string Expression { get; set; }
+    public string? Label { get; set; }
+    public bool IsDefault { get; set; }
+}
+```
+
+### 4.3 流程实例表(新增 `approval_flow_instance`)
+
+| 字段 | 类型 | 说明 |
+|------|------|------|
+| `Id` | `long` | 主键 |
+| `FlowId` | `long` | 关联流程定义 Id |
+| `FlowVersion` | `int` | 发起时的流程版本 |
+| `BizType` | `string(64)` | 业务类型 |
+| `BizId` | `long` | 关联业务单据 Id(如订单 Id) |
+| `BizNo` | `string(128)` | 业务单号(冗余) |
+| `Title` | `string(256)` | 流程标题,如"合同评审-CRM20260415001" |
+| `InitiatorId` | `long` | 发起人 Id |
+| `InitiatorName` | `string(64)` | 发起人姓名(冗余) |
+| `Status` | `enum` | `Draft / Running / Approved / Rejected / Cancelled / Terminated` |
+| `CurrentNodeId` | `string(64)` | 当前所在节点 Id |
+| `FlowJsonSnapshot` | `BigString` | 发起时的完整 FlowJson 快照(含节点属性) |
+| `StartTime` | `DateTime` | 发起时间 |
+| `EndTime` | `DateTime?` | 结束时间 |
+| 继承 `EntityBaseOrg` | | 含 CreateUserId / TenantId / OrgId 等 |
+
+### 4.4 审批任务表(新增 `approval_flow_task`)
+
+| 字段 | 类型 | 说明 |
+|------|------|------|
+| `Id` | `long` | 主键 |
+| `InstanceId` | `long` | 关联流程实例 Id |
+| `NodeId` | `string(64)` | 对应 FlowJson 中的 node.id |
+| `NodeName` | `string(128)` | 节点名称(冗余) |
+| `AssigneeId` | `long` | 指派审批人 Id |
+| `AssigneeName` | `string(64)` | 审批人姓名(冗余) |
+| `Status` | `enum` | `Pending / Approved / Rejected / Transferred / Cancelled / Returned` |
+| `Comment` | `string(1024)` | 审批意见 |
+| `ActionTime` | `DateTime?` | 操作时间 |
+| `TransferToId` | `long?` | 转办目标人 Id |
+| `IsAddSign` | `bool` | 是否为加签产生的任务 |
+| `AddSignById` | `long?` | 加签发起人 Id |
+| 继承 `EntityBaseOrg` | | |
+
+### 4.5 操作日志表(新增 `approval_flow_log`)
+
+| 字段 | 类型 | 说明 |
+|------|------|------|
+| `Id` | `long` | 主键 |
+| `InstanceId` | `long` | 关联流程实例 Id |
+| `TaskId` | `long?` | 关联任务 Id(可空,Submit 无 Task) |
+| `NodeId` | `string(64)` | 节点 Id |
+| `Action` | `enum` | `Submit / Approve / Reject / Transfer / Withdraw / Return / AddSign / Urge / Cancel / AutoTimeout` |
+| `OperatorId` | `long` | 操作人 Id |
+| `OperatorName` | `string(64)` | 操作人姓名 |
+| `Comment` | `string(1024)` | 操作说明/审批意见 |
+| `CreateTime` | `DateTime` | 操作时间 |
+
+### 4.6 ER 关系图
+
+```
+┌───────────────────────────┐
+│     approval_flow         │ ← 流程定义(模板)
+│  (已有表,扩展 3 个字段)   │
+│                           │
+│  FlowJson 内嵌节点属性:   │
+│  · approverType           │
+│  · approverIds            │
+│  · multiApproveMode       │
+│  · conditions (网关)      │
+└─────────────┬─────────────┘
+              │ 1:N(通过 BizType 匹配)
+              ▼
+┌───────────────────────────┐
+│  approval_flow_instance   │ ← 流程实例(运行态)
+│  · BizType + BizId        │
+│  · Status (状态机)        │
+│  · FlowJsonSnapshot       │
+└─────────────┬─────────────┘
+              │ 1:N
+     ┌────────┴────────┐
+     ▼                 ▼
+┌───────────┐   ┌───────────┐
+│  _task    │   │  _log     │
+│ (审批任务) │   │ (操作日志) │
+│ · Pending │   │ · Approve │
+│ · Approved│   │ · Reject  │
+│ · ...     │   │ · Transfer│
+└───────────┘   │ · Return  │
+                │ · AddSign │
+                │ · Urge    │
+                │ · ...     │
+                └───────────┘
+```
+
+---
+
+## 5. 后端核心改造
+
+### 5.1 枚举定义
+
+```csharp
+public enum FlowInstanceStatusEnum
+{
+    [Description("草稿")]   Draft = 0,
+    [Description("审批中")] Running = 1,
+    [Description("已通过")] Approved = 2,
+    [Description("已拒绝")] Rejected = 3,
+    [Description("已撤销")] Cancelled = 4,
+    [Description("已终止")] Terminated = 5,
+}
+
+public enum FlowTaskStatusEnum
+{
+    [Description("待审批")] Pending = 0,
+    [Description("已同意")] Approved = 1,
+    [Description("已拒绝")] Rejected = 2,
+    [Description("已转办")] Transferred = 3,
+    [Description("已取消")] Cancelled = 4,
+    [Description("已退回")] Returned = 5,
+}
+
+public enum FlowLogActionEnum
+{
+    [Description("提交")]     Submit = 1,
+    [Description("同意")]     Approve = 2,
+    [Description("拒绝")]     Reject = 3,
+    [Description("转办")]     Transfer = 4,
+    [Description("撤回")]     Withdraw = 5,
+    [Description("退回")]     Return = 6,
+    [Description("加签")]     AddSign = 7,
+    [Description("催办")]     Urge = 8,
+    [Description("取消")]     Cancel = 9,
+    [Description("超时自动")] AutoTimeout = 10,
+}
+
+public enum ApproverTypeEnum
+{
+    [Description("指定用户")] SpecificUser = 1,
+    [Description("指定角色")] Role = 2,
+    [Description("指定部门")] Department = 3,
+    [Description("发起人")]   Initiator = 4,
+}
+
+public enum MultiApproveModeEnum
+{
+    [Description("或签(一人通过即可)")] Any = 1,
+    [Description("会签(所有人通过)")]   All = 2,
+}
+```
+
+### 5.2 核心服务:流程引擎 FlowEngineService
+
+这是整个方案的核心。以下为完整的方法签名和职责说明:
+
+```csharp
+/// <summary>
+/// 流程推进引擎 — 核心状态机
+/// 不暴露为 API,由其他 Service 内部调用
+/// </summary>
+public class FlowEngineService : ITransient
+{
+    // ═══════════════════════════════════════════
+    //  核心生命周期
+    // ═══════════════════════════════════════════
+
+    /// <summary>
+    /// 发起流程
+    /// 1. 按 BizType 查询最新已发布的流程定义
+    /// 2. 创建 Instance(Status=Running),快照 FlowJson
+    /// 3. 解析 StartEvent → 找到第一个 UserTask → 解析审批人 → 创建 Task(s)
+    /// 4. 写 Log(Action=Submit)
+    /// 5. 发送通知
+    /// 6. 触发回调 Handler.OnFlowStarted()
+    /// </summary>
+    public async Task<long> StartFlow(StartFlowInput input);
+
+    /// <summary>
+    /// 审批操作:同意
+    /// 1. 校验当前用户是否为 Task 的 Assignee
+    /// 2. 更新 Task.Status = Approved
+    /// 3. 写 Log
+    /// 4. 判断节点是否完成:
+    ///    - 或签:一人 Approved 即节点完成,取消同节点其他 Pending Task
+    ///    - 会签:所有 Task 均 Approved 才节点完成
+    /// 5. 节点完成 → AdvanceToNext()
+    /// </summary>
+    public async Task Approve(long taskId, string? comment);
+
+    /// <summary>
+    /// 审批操作:拒绝
+    /// 1. 更新 Task.Status = Rejected
+    /// 2. 取消同节点其他 Pending Task
+    /// 3. 更新 Instance.Status = Rejected
+    /// 4. 写 Log + 通知发起人 + 触发回调
+    /// </summary>
+    public async Task Reject(long taskId, string? comment);
+
+    // ═══════════════════════════════════════════
+    //  扩展操作
+    // ═══════════════════════════════════════════
+
+    /// <summary>
+    /// 转办:将 Task 转给另一个人
+    /// 1. 当前 Task 标记 Transferred
+    /// 2. 新建 Task 给目标人
+    /// 3. 写 Log + 通知目标人
+    /// </summary>
+    public async Task Transfer(long taskId, long targetUserId, string? comment);
+
+    /// <summary>
+    /// 撤回:发起人撤回流程
+    /// 条件:Instance.Status == Running 且当前节点的所有 Task 均为 Pending(无人操作过)
+    /// 效果:取消所有 Pending Task,Instance.Status = Cancelled
+    /// </summary>
+    public async Task Withdraw(long instanceId);
+
+    /// <summary>
+    /// 退回上一步
+    /// 1. 取消当前节点所有 Pending Task
+    /// 2. 从 FlowJson 的 edges 反向找到上一个 UserTask 节点
+    /// 3. 为上一个节点重新创建 Task(原审批人)
+    /// 4. 更新 Instance.CurrentNodeId
+    /// 5. 写 Log + 通知
+    /// </summary>
+    public async Task ReturnToPrev(long taskId, string? comment);
+
+    /// <summary>
+    /// 加签:在当前节点临时增加审批人
+    /// 1. 创建新的 Task(标记 IsAddSign=true)
+    /// 2. 如果当前节点是或签,加签 Task 不影响已通过的判定
+    /// 3. 如果当前节点是会签,加签 Task 也需通过才算节点完成
+    /// </summary>
+    public async Task AddSign(long taskId, long targetUserId, string? comment);
+
+    /// <summary>
+    /// 催办:给当前节点所有 Pending 审批人发送催办通知
+    /// 写 Log(Action=Urge) + 发送通知
+    /// </summary>
+    public async Task Urge(long instanceId);
+
+    // ═══════════════════════════════════════════
+    //  内部引擎方法
+    // ═══════════════════════════════════════════
+
+    /// <summary>
+    /// 推进到下一个节点
+    /// 1. 从 edges 找到当前节点的出边
+    /// 2. 目标是 UserTask → 解析审批人 → 创建 Task
+    /// 3. 目标是 ExclusiveGateway → 评估 conditions → 递归 AdvanceToNext
+    /// 4. 目标是 EndEvent → Instance.Status = Approved → 触发回调
+    /// </summary>
+    private async Task AdvanceToNext(ApprovalFlowInstance instance, string currentNodeId);
+
+    /// <summary>
+    /// 解析审批人
+    /// SpecificUser → 直接拆分 ApproverIds
+    /// Role → 查 SysUserRole 获取角色下所有用户
+    /// Department → 查 SysUserExtOrg + SysOrg 获取部门人员
+    /// Initiator → 返回发起人
+    /// </summary>
+    private async Task<List<(long userId, string userName)>> ResolveApprovers(
+        FlowProperties props, long initiatorId);
+
+    /// <summary>
+    /// 评估网关条件表达式
+    /// 支持简单的字段比较表达式,如 "bizData.amount > 100000"
+    /// </summary>
+    private string EvaluateGateway(List<GatewayCondition> conditions,
+        Dictionary<string, object>? bizData);
+}
+```
+
+### 5.3 流程实例服务 FlowInstanceService(API 层)
+
+```csharp
+/// <summary>
+/// 流程实例服务 — 暴露为 API
+/// </summary>
+[ApiDescriptionSettings(ApprovalFlowConst.GroupName, Order = 95)]
+public class FlowInstanceService : IDynamicApiController, ITransient
+{
+    /// <summary>发起流程</summary>
+    [HttpPost] public async Task<long> Start(StartFlowInput input);
+
+    /// <summary>查询实例详情(含当前节点、任务列表)</summary>
+    [HttpGet] public async Task<FlowInstanceDetailOutput> GetDetail([FromQuery] long id);
+
+    /// <summary>查询业务单据关联的流程实例</summary>
+    [HttpGet] public async Task<FlowInstanceDetailOutput?> GetByBiz(
+        [FromQuery] string bizType, [FromQuery] long bizId);
+
+    /// <summary>审批时间线</summary>
+    [HttpGet] public async Task<List<FlowTimelineItem>> GetTimeline([FromQuery] long instanceId);
+}
+```
+
+### 5.4 审批任务服务 FlowTaskService(API 层)
+
+```csharp
+/// <summary>
+/// 审批任务服务 — 暴露为 API
+/// </summary>
+[ApiDescriptionSettings(ApprovalFlowConst.GroupName, Order = 90)]
+public class FlowTaskService : IDynamicApiController, ITransient
+{
+    // ── 查询 ──
+    /// <summary>我的待办(分页)</summary>
+    [HttpPost] public async Task<SqlSugarPagedList<TaskPageOutput>> MyPendingPage(TaskPageInput input);
+
+    /// <summary>我的已办(分页)</summary>
+    [HttpPost] public async Task<SqlSugarPagedList<TaskPageOutput>> MyDonePage(TaskPageInput input);
+
+    /// <summary>我发起的(分页)</summary>
+    [HttpPost] public async Task<SqlSugarPagedList<InstancePageOutput>> MyInitiatedPage(InstancePageInput input);
+
+    /// <summary>待办数量(用于菜单角标)</summary>
+    [HttpGet] public async Task<int> MyPendingCount();
+
+    // ── 操作 ──
+    /// <summary>同意</summary>
+    [HttpPost] public async Task Approve(TaskActionInput input);
+
+    /// <summary>拒绝</summary>
+    [HttpPost] public async Task Reject(TaskActionInput input);
+
+    /// <summary>转办</summary>
+    [HttpPost] public async Task Transfer(TaskTransferInput input);
+
+    /// <summary>撤回</summary>
+    [HttpPost] public async Task Withdraw(TaskWithdrawInput input);
+
+    /// <summary>退回上一步</summary>
+    [HttpPost] public async Task ReturnToPrev(TaskActionInput input);
+
+    /// <summary>加签</summary>
+    [HttpPost] public async Task AddSign(TaskAddSignInput input);
+
+    /// <summary>催办</summary>
+    [HttpPost] public async Task Urge(TaskUrgeInput input);
+}
+```
+
+### 5.5 改造现有 ApprovalFlowService
+
+在现有 CRUD 基础上增加:
+
+```csharp
+/// <summary>发布流程(Version+1,IsPublished=true)</summary>
+[HttpPost] public async Task Publish(long id);
+
+/// <summary>获取业务类型列表(供前端下拉选择)</summary>
+[HttpGet] public async Task<List<string>> GetBizTypes();
+
+/// <summary>获取指定业务类型的最新已发布流程定义</summary>
+[HttpGet] public async Task<ApprovalFlow?> GetPublishedByBizType([FromQuery] string bizType);
+```
+
+### 5.6 改造 SysApprovalService(中间件)
+
+```
+改造方向:
+- 中间件保留但默认关闭(配置开关)
+- 仅用于审计日志记录
+- 不再用于核心审批推进
+- 修复 B1-B4 的代码质量问题
+```
+
+---
+
+## 6. 前端核心改造
+
+### 6.1 节点属性编辑器增强
+
+改造 `PropertyCommon.vue` + `PropertyDialog.vue`:
+
+```
+┌─────────────────────────────────────┐
+│  节点属性                            │
+│                                     │
+│  节点名称:[意见评审               ] │
+│                                     │
+│  ── 审批配置 ──                     │
+│  审批类型:[指定角色           ▼   ] │
+│  选择角色:[销售部 ✕] [技术部 ✕   ] │
+│  审批方式:[或签(一人通过)     ▼   ] │
+│                                     │
+│  ── 超时设置(可选)──              │
+│  超时时间:[48] 小时                 │
+│  超时动作:[自动通知           ▼   ] │
+│                                     │
+│         [保存到节点]                 │
+└─────────────────────────────────────┘
+```
+
+```
+┌─────────────────────────────────────┐
+│  网关条件                            │
+│                                     │
+│  分支 1:                             │
+│   目标节点:[总经理审批        ▼   ] │
+│   条件表达式:[amount > 1000000    ] │
+│   描述:[金额>100万               ] │
+│                                     │
+│  分支 2:                             │
+│   目标节点:[部门经理审批      ▼   ] │
+│   ☑ 默认分支                        │
+│   描述:[金额≤100万               ] │
+│                                     │
+│  [+ 添加分支]       [保存到节点]    │
+└─────────────────────────────────────┘
+```
+
+关键实现:
+1. 根据 `nodeData.type` 显示不同的属性表单(UserTask vs Gateway vs Start/End)
+2. 审批类型切换时,动态展示对应选择器(用户搜索 / 角色多选 / 部门树选)
+3. 保存时调用 `lf.setProperties(nodeId, properties)` 更新 LogicFlow 节点数据
+4. 流程保存时 `getGraphData()` 自动包含所有节点属性
+
+### 6.2 流程定义页面增强
+
+在现有 `index.vue` 的列表中增加:
+
+| 增强项 | 说明 |
+|--------|------|
+| 业务类型列 | 显示 `BizType`,可筛选 |
+| 版本列 | 显示 `Version` |
+| 发布状态列 | Tag: 已发布(绿) / 未发布(灰) |
+| 发布按钮 | 操作列增加"发布"按钮 |
+| 编辑对话框 | 增加"业务类型"下拉选择 |
+
+### 6.3 审批中心页面(新增)
+
+```
+Web/src/views/approvalFlow/center/
+├── index.vue              # 主页,el-tabs: 我的待办 / 我的已办 / 我发起的
+├── pendingList.vue        # 待办列表(表格 + 操作按钮)
+├── doneList.vue           # 已办列表(只读)
+├── initiatedList.vue      # 我发起的列表
+├── approvalDialog.vue     # 审批操作对话框(同意/拒绝/转办/退回/加签)
+└── timeline.vue           # 审批时间线组件(可复用)
+```
+
+**待办列表 UI 示意**:
+
+```
+┌─────────────────────────────────────────────────────────────────┐
+│ 我的待办 (3)    我的已办    我发起的                              │
+├─────────────────────────────────────────────────────────────────┤
+│ 流程标题         业务编号      发起人    发起时间     当前节点   操作 │
+│ 合同评审-C001   CRM20260415  张三      04-15 09:30  意见评审   [处理] │
+│ 订单评审-O023   SO20260414   李四      04-14 16:00  资源检查   [处理] │
+│ 合同评审-C003   CRM20260413  王五      04-13 11:00  二次评审   [处理] │
+└─────────────────────────────────────────────────────────────────┘
+```
+
+**审批操作对话框 UI**:
+
+```
+┌──────────────────────────────────┐
+│  审批操作 — 合同评审-C001         │
+│                                  │
+│  ┌──────────────────────────┐   │
+│  │ [审批时间线]               │   │
+│  │ ● 张三 提交  04-15 09:30  │   │
+│  │ ● 当前: 意见评审(待审批)   │   │
+│  │ ○ 意见反馈(未到达)         │   │
+│  │ ○ ...                     │   │
+│  └──────────────────────────┘   │
+│                                  │
+│  审批意见:[                    ] │
+│                                  │
+│  [同意] [拒绝] [转办] [退回]     │
+│                [加签] [催办]     │
+└──────────────────────────────────┘
+```
+
+### 6.4 通用 ApprovalPanel 组件
+
+```vue
+<!-- 嵌入任何业务表单页面底部 -->
+<ApprovalPanel
+  biz-type="CONTRACT_REVIEW"
+  :biz-id="orderId"
+  :biz-no="orderBillNo"
+  :title="`合同评审-${orderBillNo}`"
+  @started="onFlowStarted"
+  @completed="onFlowCompleted"
+/>
+```
+
+组件内部逻辑:
+
+```
+1. onMounted → 调用 GET /flowInstance/getByBiz?bizType=...&bizId=... 查询是否已有实例
+2. 无实例 → 显示 [提交审批] 按钮
+   点击 → POST /flowInstance/start → 刷新
+3. 有实例:
+   a. 显示审批时间线(GET /flowInstance/timeline)
+   b. 查询当前用户是否有 Pending Task
+      是 → 显示 [同意] [拒绝] [转办] [退回] [加签] 按钮
+      否 → 只读查看
+   c. 如果是发起人且可撤回 → 显示 [撤回] 按钮
+   d. 如果是发起人/审批人 → 显示 [催办] 按钮
+```
+
+### 6.5 菜单注册
+
+审批中心需要新增菜单种子:
+
+| 菜单 | 路径 | 位置 |
+|------|------|------|
+| 审批中心 | `/approvalFlow/center` | 一级菜单或挂在"工作台"下 |
+
+---
+
+## 7. 通知机制设计
+
+### 7.1 通知架构
+
+```
+FlowEngine 操作完成
+    │
+    ▼
+FlowNotifyService.Send(notifyInput)
+    │
+    ├─→ 1. 页面待办列表(默认,查询即可见)
+    │
+    ├─→ 2. SignalR 实时推送(利用 Admin.NET 已有的 SysOnlineUserHub)
+    │      → 前端右上角弹出待办提醒 + 更新角标数字
+    │
+    ├─→ 3. 钉钉/企微工作通知(利用已有 DingTalk/WorkWeixin 插件)
+    │      → 调用 DingTalkService / WorkWeixinService 推送消息
+    │
+    └─→ 4. 邮件/短信(利用已有 SysEmailService / SysSmsService)
+           → 发送审批提醒邮件/短信
+```
+
+### 7.2 通知触发时机
+
+| 事件 | 通知对象 | 通知内容 |
+|------|---------|---------| 
+| 流程发起 | 第一个节点的审批人 | "您有新的审批待办:{title}" |
+| 同意→推进到下一节点 | 下一节点审批人 | "您有新的审批待办:{title}" |
+| 同意→流程结束 | 发起人 | "您的{title}已审批通过" |
+| 拒绝 | 发起人 | "您的{title}已被拒绝" |
+| 转办 | 转办目标人 | "{operator}将审批任务转办给您:{title}" |
+| 退回上一步 | 上一步审批人 | "审批被退回,请重新处理:{title}" |
+| 加签 | 加签目标人 | "{operator}邀请您参与审批:{title}" |
+| 催办 | 当前节点所有 Pending 审批人 | "请尽快处理审批:{title}" |
+| 撤回 | 原审批人(被取消) | "发起人已撤回:{title}" |
+
+### 7.3 通知渠道优先级与配置
+
+```json
+// 可在系统配置中设置每种通知渠道的启用/禁用
+{
+  "FlowNotify": {
+    "SignalR": true,
+    "DingTalk": true,
+    "WorkWeixin": false,
+    "Email": true,
+    "Sms": false
+  }
+}
+```
+
+各渠道独立开关,按需组合。
+
+---
+
+## 8. 业务联动:回调注册机制
+
+### 8.1 接口定义
+
+```csharp
+/// <summary>
+/// 业务流程回调处理器接口
+/// 每种 BizType 实现一个 Handler,注册到 DI 容器
+/// </summary>
+public interface IFlowBizHandler
+{
+    /// <summary>业务类型编码(与流程定义的 BizType 匹配)</summary>
+    string BizType { get; }
+
+    /// <summary>流程发起后回调(可选:更新业务表状态为"审批中")</summary>
+    Task OnFlowStarted(long bizId, long instanceId) => Task.CompletedTask;
+
+    /// <summary>流程结束后回调(必须:更新业务表最终状态)</summary>
+    Task OnFlowCompleted(long bizId, FlowInstanceStatusEnum finalStatus);
+
+    /// <summary>单个节点审批完成回调(可选:按节点推进业务进度)</summary>
+    Task OnNodeCompleted(long bizId, string nodeId, string nodeName) => Task.CompletedTask;
+}
+```
+
+### 8.2 合同评审回调示例
+
+```csharp
+/// <summary>
+/// 合同评审业务回调 — 仅约 15 行业务代码
+/// </summary>
+public class ContractReviewBizHandler : IFlowBizHandler, ITransient
+{
+    public string BizType => "CONTRACT_REVIEW";
+
+    private readonly SqlSugarRepository<SeOrder> _orderRep;
+
+    public ContractReviewBizHandler(SqlSugarRepository<SeOrder> orderRep)
+        => _orderRep = orderRep;
+
+    public async Task OnFlowStarted(long bizId, long instanceId)
+    {
+        await _orderRep.AsUpdateable()
+            .SetColumns(u => new SeOrder { FlowState = "审批中", UpdateTime = DateTime.Now })
+            .Where(u => u.Id == bizId)
+            .ExecuteCommandAsync();
+    }
+
+    public async Task OnFlowCompleted(long bizId, FlowInstanceStatusEnum finalStatus)
+    {
+        var state = finalStatus == FlowInstanceStatusEnum.Approved ? "已通过" : "已拒绝";
+        await _orderRep.AsUpdateable()
+            .SetColumns(u => new SeOrder { FlowState = state, UpdateTime = DateTime.Now })
+            .Where(u => u.Id == bizId)
+            .ExecuteCommandAsync();
+    }
+}
+```
+
+### 8.3 引擎调用回调的方式
+
+```csharp
+// FlowEngineService 内部
+private async Task InvokeHandler(string bizType, Func<IFlowBizHandler, Task> action)
+{
+    var handlers = App.GetServices<IFlowBizHandler>();
+    var handler = handlers.FirstOrDefault(h => h.BizType == bizType);
+    if (handler != null)
+        await action(handler);
+}
+
+// 使用:
+await InvokeHandler(instance.BizType, h => h.OnFlowCompleted(instance.BizId, finalStatus));
+```
+
+### 8.4 接入新业务的步骤
+
+| 步骤 | 操作方 | 工作量 | 说明 |
+|------|--------|--------|------|
+| 1 | 管理员 | 配置 | 在审批流程管理页面新增流程定义,设 BizType,画流程图,发布 |
+| 2 | 开发者 | ~15 行 | 实现 `IFlowBizHandler`,注册到 DI |
+| 3 | 开发者 | ~3 行 | 在业务表单页面嵌入 `<ApprovalPanel>` |
+| 4 | — | 0 | 审批引擎代码无需修改 |
+
+---
+
+## 9. S1 订单管理业务接入示例
+
+### 9.1 五个功能的审批流程配置
+
+| 序号 | 子功能 | BizType | 流程节点设计 | 说明 |
+|------|--------|---------|-------------|------|
+| 1 | 合同评审 | `CONTRACT_REVIEW` | 意见评审(销售部,或签) → 意见反馈(技术部,会签) → 二次评审(售前组,或签) → 领导意见(分管领导) → 合同盖章(法务部,或签) | 5 环节 |
+| 2 | 产品设计 | `PRODUCT_DESIGN` | 设计提交(设计部) → 技术评审(技术部,会签) → BOM确认(工艺部) | 3 环节 |
+| 3 | 订单评审 | `ORDER_REVIEW` | DOP下载(计划员) → 模拟资源(产能组) → 检查交期(销售) → 交期确认(销售,会签) → 资源锁定(计划员) | 5 环节 |
+| 4 | 订单交付 | `ORDER_DELIVERY` | 交期确认 → 生产计划 → 物料计划 → 执行采购 → 生产执行 → 入库发运 | 6 环节,全流程规划 |
+| 5 | 订单发货 | `ORDER_SHIPPING` | 生成发货通知(销售) → 仓库确认(仓库) → 物流安排(物流) | 3 环节 |
+
+### 9.2 业务代码集成示例
+
+```csharp
+// SeOrderService.cs — 新增方法(与现有 review/confirm-delivery 并行)
+
+/// <summary>提交合同评审(走审批流)</summary>
+[HttpPost("seorder/{id}/submit-contract-review")]
+public async Task<object> SubmitContractReview(long id)
+{
+    var order = await _seOrderRep.GetFirstAsync(u => u.Id == id && u.IsDeleted == 0)
+                ?? throw Oops.Oh("订单不存在");
+
+    var instanceId = await _flowEngine.StartFlow(new StartFlowInput
+    {
+        BizType = "CONTRACT_REVIEW",
+        BizId = id,
+        BizNo = order.BillNo,
+        Title = $"合同评审-{order.BillNo}",
+    });
+
+    return new { instanceId, message = "已提交合同评审" };
+}
+
+/// <summary>提交订单评审(走审批流)</summary>
+[HttpPost("seorder/{id}/submit-order-review")]
+public async Task<object> SubmitOrderReview(long id)
+{
+    var order = await _seOrderRep.GetFirstAsync(u => u.Id == id && u.IsDeleted == 0)
+                ?? throw Oops.Oh("订单不存在");
+
+    var instanceId = await _flowEngine.StartFlow(new StartFlowInput
+    {
+        BizType = "ORDER_REVIEW",
+        BizId = id,
+        BizNo = order.BillNo,
+        Title = $"订单评审-{order.BillNo}",
+    });
+
+    return new { instanceId, message = "已提交订单评审" };
+}
+```
+
+### 9.3 前端集成示例
+
+```vue
+<!-- 订单详情页面底部 -->
+<template>
+  <div class="order-detail">
+    <!-- ...现有订单表单... -->
+
+    <!-- 审批区域 -->
+    <ApprovalPanel
+      biz-type="CONTRACT_REVIEW"
+      :biz-id="orderId"
+      :biz-no="orderBillNo"
+      :title="`合同评审-${orderBillNo}`"
+    />
+  </div>
+</template>
+```
+
+---
+
+## 10. 配置化使用指南
+
+### 10.1 管理员:创建新的审批流程(零代码)
+
+```
+步骤 1: 打开【平台管理】→【审批流程】
+步骤 2: 点击【新增】
+        - 名称:合同评审流程
+        - 业务类型:CONTRACT_REVIEW(下拉选择或手动输入)
+步骤 3: 点击行上的【流程】按钮 → 进入 LogicFlow 设计器
+        - 从左侧面板拖入节点:开始 → 用户任务 → 用户任务 → ... → 结束
+        - 用箭头连接各节点
+        - 点击每个用户任务节点 → 右侧抽屉设置:
+          · 节点名称:意见评审
+          · 审批类型:指定角色
+          · 选择角色:销售部
+          · 审批方式:或签
+        - (可选)拖入排他网关节点 → 配置条件分支
+步骤 4: 点击【保存】
+步骤 5: 回到列表,点击【发布】
+步骤 6: 完成!业务人员即可在订单页面发起此流程
+```
+
+### 10.2 开发者:接入新的业务类型
+
+```
+1. 【管理员】在审批流程页面创建并发布流程定义
+2. 【开发者】编写 Handler(约 15 行):
+   public class XxxBizHandler : IFlowBizHandler, ITransient
+   {
+       public string BizType => "YOUR_BIZ_TYPE";
+       public async Task OnFlowCompleted(long bizId, FlowInstanceStatusEnum status) { ... }
+   }
+3. 【开发者】在前端页面嵌入组件(约 3 行):
+   <ApprovalPanel biz-type="YOUR_BIZ_TYPE" :biz-id="id" />
+4. 无需修改审批引擎代码
+```
+
+### 10.3 条件分支配置示例
+
+在网关节点的属性面板中配置:
+
+| 分支 | 目标节点 | 条件表达式 | 说明 |
+|------|---------|-----------|------|
+| 分支 1 | 总经理审批 | `bizData.contractAmount > 1000000` | 金额 > 100万 |
+| 分支 2(默认) | 部门经理审批 | — | 其他情况 |
+
+条件表达式中的 `bizData` 由发起流程时传入的业务数据字典提供。
+
+---
+
+## 11. 实施路线图
+
+### Phase 1:基础引擎 + 数据层(约 2 周)
+
+| # | 任务 | 说明 | 估时 |
+|---|------|------|------|
+| 1.1 | 数据库建模 | 扩展 approval_flow(+3字段)、新增 3 张表 | 1d |
+| 1.2 | 实体 + 枚举 | C# Entity / Enum / DTO 定义 | 1d |
+| 1.3 | FlowProperties 改造 | 从空类改为结构化,含审批人/网关条件 | 0.5d |
+| 1.4 | FlowEngineService 核心 | StartFlow + Approve + Reject + AdvanceToNext + ResolveApprovers | 3d |
+| 1.5 | 扩展操作 | Transfer + Withdraw + ReturnToPrev + AddSign + Urge | 2d |
+| 1.6 | IFlowBizHandler 回调机制 | 接口 + DI 注册 + 引擎调用 | 0.5d |
+| 1.7 | 流程发布逻辑 | Publish API + 版本号管理 | 0.5d |
+| 1.8 | 审批中心 API | 待办/已办/我发起的/时间线/待办数 | 1.5d |
+
+### Phase 2:前端 UI(约 2 周)
+
+| # | 任务 | 说明 | 估时 |
+|---|------|------|------|
+| 2.1 | 节点属性编辑器 | PropertyCommon 增强:审批人选择/审批方式/超时/网关条件 | 3d |
+| 2.2 | 流程定义页面增强 | BizType / Version / 发布状态 / 发布操作 | 1d |
+| 2.3 | 审批中心页面 | 待办 + 已办 + 我发起的 + 审批操作对话框 + 时间线 | 3d |
+| 2.4 | 通用 ApprovalPanel | 嵌入式审批组件 | 1.5d |
+| 2.5 | 菜单 + 路由注册 | 审批中心菜单种子 | 0.5d |
+| 2.6 | 前端联调 | 端到端跑通完整流程 | 1d |
+
+### Phase 3:通知机制(约 1 周)
+
+| # | 任务 | 说明 | 估时 |
+|---|------|------|------|
+| 3.1 | FlowNotifyService | 统一通知调度服务 | 0.5d |
+| 3.2 | SignalR 站内信 | 利用 SysOnlineUserHub 推送 + 前端角标 | 1d |
+| 3.3 | 钉钉工作通知 | 利用 DingTalkService 推送 | 1d |
+| 3.4 | 企业微信通知 | 利用 WorkWeixinService 推送 | 1d |
+| 3.5 | 邮件/短信 | 利用已有邮件短信服务 | 1d |
+| 3.6 | 通知渠道配置 | 系统配置页面 + JSON 开关 | 0.5d |
+
+### Phase 4:业务接入 + 验证(约 1 周)
+
+| # | 任务 | 说明 | 估时 |
+|---|------|------|------|
+| 4.1 | 合同评审接入 | Handler + 前端 ApprovalPanel + 流程定义 | 1d |
+| 4.2 | 订单评审接入 | Handler + 前端 + 流程定义 | 1d |
+| 4.3 | 端到端验证 | 完整场景测试(发起→多节点审批→通过/拒绝→业务联动→通知) | 1.5d |
+| 4.4 | Bug 修复 + 优化 | 根据测试结果修复 | 1.5d |
+
+### 后续迭代
+
+| 功能 | 说明 |
+|------|------|
+| 依次审批模式 | MultiApproveMode.Sequential |
+| 发起人上级 | ApproverType.Superior(需组织架构上级关系) |
+| 表单字段审批人 | 根据业务表单字段值动态指定审批人 |
+| 并行网关 | 多条分支同时进行 |
+| 超时自动处理 | 定时任务扫描 + AutoApprove/AutoReject |
+| 流程版本对比 | 可视化对比两个版本的流程图差异 |
+| 流程监控看板 | 管理员查看所有流程实例状态统计 |
+| 订单交付/发货接入 | 更多 S1 业务场景 |
+
+---
+
+## 附录 A:现有 SeOrder 数据模型参考
+
+| 表 | 实体 | 说明 |
+|----|------|------|
+| `crm_seorder` | `SeOrder` | 销售订单主表,含 `FlowState` 字段 |
+| `crm_seorderentry` | `SeOrderEntry` | 订单明细,含 `Progress` (0=再评审,1=新建,2=评审,3=确认) |
+| `crm_seorder_change` | `SeOrderChange` | 订单变更申请 |
+
+现有 `SeOrderService` API(与审批流**并行保留**,验证后再切换):
+- `GET seorder/list` / `GET seorder/{id}` / `POST seorder/save`
+- `POST seorder/{id}/review` — 硬编码设进度=2
+- `POST seorder/{id}/confirm-delivery` — 硬编码设进度=3
+- `POST seorder/{id}/unlock` — 空实现
+- `POST seorder/{id}/change` — 变更申请
+
+---
+
+## 附录 B:与钉钉审批的关系
+
+项目中存在 `Admin.NET.Plugin.DingTalk` 插件,已有钉钉工作流 API 对接。本方案与钉钉审批的关系:
+
+- **内部审批**:使用本方案自建引擎,适合系统内全流程可控
+- **钉钉通知**:审批引擎发起/推进时,通过钉钉插件发送工作通知提醒(Phase 3 实现)
+- **钉钉审批**:如需在钉钉 App 内审批,可后续对接钉钉审批流 API(本期不做)
+
+---
+
+## 附录 C:技术选型对比参考
+
+| 维度 | 自建引擎(本方案) | Elsa 3.x | Camunda | 钉钉审批 |
+|------|-------------------|----------|---------|---------| 
+| 集成难度 | 低(天然集成) | 中(需适配) | 高(独立部署) | 低(已有插件) |
+| 功能完整度 | 按需渐进 | 高 | 很高 | 仅审批 |
+| 学习成本 | 低 | 中 | 高 | 低 |
+| 灵活性 | 高(完全可控) | 中 | 中 | 低 |
+| 运维复杂度 | 低 | 中 | 高 | 零(SaaS) |
+| 适合场景 | 中小规模审批 | 复杂工作流 | 企业级 BPM | 移动审批 |

+ 3 - 3
server/Admin.NET.Web.Entry/Admin.NET.Web.Entry.csproj

@@ -11,9 +11,9 @@
     <GenerateSatelliteAssembliesForCore>true</GenerateSatelliteAssembliesForCore>
     <Copyright>Admin.NET</Copyright>
     <Description>Admin.NET 通用权限开发平台</Description>
-    <AssemblyVersion>1.0.10</AssemblyVersion>
-    <FileVersion>1.0.10</FileVersion>
-    <Version>1.0.10</Version>
+    <AssemblyVersion>1.0.11</AssemblyVersion>
+    <FileVersion>1.0.11</FileVersion>
+    <Version>1.0.11</Version>
   </PropertyGroup>
 
   <ItemGroup>