# Workflow Engine 技术产品文档 > 版本:v1.0 · 最后更新:2026-05-09 ## 目录 1. [概述](#1-概述) 2. [架构](#2-架构) 3. [数据模型](#3-数据模型) 4. [步骤类型详解](#4-步骤类型详解) 5. [API 参考](#5-api-参考) 6. [使用示例](#6-使用示例) 7. [当前限制](#7-当前限制) 8. [升级路线图](#8-升级路线图) --- ## 1. 概述 ### 1.1 定位 raisfast 内置工作流引擎,为 CMS 内容发布流程提供自动化编排能力。设计目标: - **轻量**:不依赖外部服务(无 Redis/MQ),数据全部存储在 SQLite 中 - **同步驱动**:步骤推进由 API 调用触发,而非后台轮询(除 Delay 类型) - **声明式定义**:工作流以 JSON 定义步骤和转移关系,存储在 `workflow_definitions` 表 - **可观测**:每步执行生成 `workflow_step_logs` 记录,含输入/输出/耗时 ### 1.2 设计原则 | 原则 | 说明 | |------|------| | 极简核心 | 5 种步骤类型覆盖 90% 常见场景 | | 单实例单步骤 | 任意时刻一个实例只处于一个当前步骤(Parallel 除外) | | Context 传递 | 工作流上下文在步骤间自动传递和合并 | | 幂等安全 | 定义创建时校验所有引用完整性 | ### 1.3 不做的事 - 不做分布式协调(无 leader election、分布式锁) - 不做 DAG 拓扑(无复杂依赖图) - 不做可视化编辑器后端(前端自行实现) - 不做跨系统编排(无 HTTP callback、无 gRPC 调用) --- ## 2. 架构 ``` ┌─────────────────────────────────────────────────┐ │ HTTP API │ │ /admin/workflows CRUD │ │ /admin/workflows/{id}/start │ │ /admin/workflows/instances/{id}/execute │ │ /admin/workflows/instances/{id}/cancel │ │ /admin/workflows/instances/{id}/logs │ └────────────────────┬────────────────────────────┘ │ ┌────────────────────▼────────────────────────────┐ │ WorkflowService │ │ ┌─────────────┐ ┌──────────────────────────┐ │ │ │ validate │ │ execute_step │ │ │ │ _steps │ │ ├─ Task/Await/Delay │ │ │ │ │ │ ├─ Branch (条件路由) │ │ │ │ resolve │ │ └─ Parallel (并行→汇合) │ │ │ │ _next_step │ │ │ │ │ └─────────────┘ └──────────────────────────┘ │ └────────────────────┬────────────────────────────┘ │ ┌────────────────────▼────────────────────────────┐ │ Model 层 (sqlx) │ │ workflow_definitions │ │ workflow_instances │ │ workflow_step_logs │ └─────────────────────────────────────────────────┘ ``` ### 三层分离 | 层 | 文件 | 职责 | |----|------|------| | Handler | `src/handlers/workflow.rs` | HTTP 请求解析、参数校验、响应封装 | | Service | `src/services/workflow.rs` | 状态机逻辑、步骤解析、条件评估、并行调度 | | Model | `src/models/workflow.rs` | SQL 查询、数据结构映射 | --- ## 3. 数据模型 ### 3.1 workflow_definitions — 工作流定义 | 字段 | 类型 | 说明 | |------|------|------| | `id` | INTEGER PK | 自增主键 | | `document_id` | TEXT UNIQUE | UUID v7,对外暴露的 ID | | `name` | TEXT | 工作流名称 | | `description` | TEXT? | 描述 | | `steps` | TEXT | JSON 数组,步骤定义(见 4.1) | | `initial_step` | TEXT | 入口步骤 ID | | `version` | INTEGER | 版本号(当前未使用,预留) | | `enabled` | BOOLEAN | 是否启用,禁用时无法启动新实例 | | `created_at` | TEXT | ISO 8601 | | `updated_at` | TEXT | ISO 8601 | ### 3.2 workflow_instances — 工作流实例 | 字段 | 类型 | 说明 | |------|------|------| | `id` | INTEGER PK | 自增主键 | | `document_id` | TEXT UNIQUE | UUID v7 | | `definition_id` | INTEGER FK | 关联定义 | | `status` | TEXT | `running` / `completed` / `failed` / `cancelled` | | `current_step` | TEXT? | 当前步骤 ID(`completed`/`failed`/`cancelled` 时为 NULL) | | `context` | TEXT | JSON,工作流上下文(跨步骤传递) | | `triggered_by` | INTEGER? | 触发者 user.id | | `started_at` | TEXT | 启动时间 | | `completed_at` | TEXT? | 完成时间 | | `updated_at` | TEXT | 最后更新 | **实例状态机:** ``` start_workflow │ ▼ ┌──────────┐ ┌───────│ running │───────┐ │ └──────────┘ │ │ │ │ │ execute_step cancel fail_step │ │ │ │ │ ▼ ▼ ▼ │ ┌──────────┐ │ ┌─────────┐ │ │ running │ │ │ failed │ │ │(下一步) │ │ └─────────┘ │ └──────────┘ │ │ │ ▼ │ │ ┌───────────┐ │ │ │ cancelled │ │ │ └───────────┘ │ ▼ │ ┌───────────┐ │ │ completed │◄──────────────────┘ └───────────┘ (最后一步 next 为空) ``` ### 3.3 workflow_step_logs — 步骤执行日志 | 字段 | 类型 | 说明 | |------|------|------| | `id` | INTEGER PK | 自增主键 | | `document_id` | TEXT UNIQUE | UUID v7 | | `instance_id` | INTEGER FK | 关联实例 | | `step_id` | TEXT | 步骤定义 ID | | `step_name` | TEXT | 步骤名称(冗余,方便查询) | | `status` | TEXT | `running` / `completed` / `failed` | | `input` | TEXT? | JSON,步骤开始时的 context 快照 | | `output` | TEXT? | JSON,步骤完成时的输出 | | `error` | TEXT? | 错误信息(仅 failed) | | `started_at` | TEXT | 开始时间 | | `completed_at` | TEXT? | 完成时间 | --- ## 4. 步骤类型详解 ### 4.1 StepDef 结构 每个步骤定义包含以下字段: ```json { "id": "review", "name": "审核", "type": "await", "config": {}, "next": "publish", "timeout_ms": 0 } ``` | 字段 | 类型 | 必填 | 说明 | |------|------|------|------| | `id` | string | 是 | 步骤唯一标识,工作流内不可重复 | | `name` | string | 是 | 显示名称 | | `type` | string | 是 | 步骤类型:`task` / `await` / `branch` / `parallel` / `delay` | | `config` | object | 否 | 步骤配置(各类型含义不同) | | `next` | any | 否 | 下一步转移规则(各类型格式不同) | | `timeout_ms` | number | 否 | 超时毫秒数(当前预留,未实现自动超时) | ### 4.2 Task — 自动任务 **语义**:系统自动执行的步骤。调用方通过 `execute_step` 提交结果后推进到 `next`。 **`next` 格式**:`string`,目标步骤 ID 或空字符串(表示结束)。 ```json { "id": "notify", "name": "发送通知", "type": "task", "config": { "channel": "email" }, "next": "archive" } ``` **执行流程**: 1. `execute_step` 被调用,`step_output` 合并到 context 2. 当前步骤 log 标记为 `completed` 3. `resolve_next_step` 返回 `next` 指定的步骤 ID 4. 实例推进到下一步 **`next` 特殊值**: | 值 | 行为 | |------|------| | `"s2"` | 推进到步骤 `s2` | | `""` / `null` | 工作流完成(status = `completed`) | ### 4.3 Await — 等待外部事件 **语义**:等待人工操作(如审批)或外部系统回调。与 Task 共享相同的状态转移逻辑,区别在于语义——Await 表示"需要外部触发"。 **`next` 格式**:与 Task 相同。 ```json { "id": "approve", "name": "等待审批", "type": "await", "config": { "roles": ["admin", "editor"] }, "next": "publish" } ``` **执行流程**:与 Task 完全一致。区分 `task` 和 `await` 的目的是让前端知道当前步骤是否需要用户交互。 ### 4.4 Branch — 条件分支 **语义**:根据工作流 context 中的字段值选择下一步。 **`next` 格式**:`Array<{ condition?: Object, step: string }>` - `condition`:键值对,所有字段必须完全匹配 - 无 `condition` 的分支是 fallback(当所有条件都不匹配时) - 按数组顺序评估,第一个匹配的分支生效 ```json { "id": "decide", "name": "审核结果", "type": "branch", "config": {}, "next": [ { "condition": { "approved": true }, "step": "publish" }, { "condition": { "approved": false, "reason": "reject" }, "step": "notify_reject" }, { "step": "draft" } ] } ``` **条件匹配规则**: | 期望值类型 | 比较方式 | |-----------|---------| | String | `context[key].as_str() == expected` | | Number | `context[key].as_f64() == expected.as_f64()` | | Bool | `context[key].as_bool() == expected` | | null / Object / Array | 不匹配,返回 `false` | 所有 condition 中的字段必须同时匹配(AND 逻辑)。缺少某个字段的 context 也不匹配。 ### 4.5 Parallel — 并行执行 **语义**:同时启动多个分支,所有分支完成后汇合到 `join_next` 或结束。 **`next` 格式**:`string[]`(分支步骤 ID 数组) **`config` 字段**: | 字段 | 类型 | 说明 | |------|------|------| | `join_next` | `string?` | 所有分支完成后的下一步。省略则所有分支完成后直接结束工作流 | ```json { "id": "parallel_notify", "name": "并行通知", "type": "parallel", "config": { "join_next": "generate_report" }, "next": ["email_notify", "slack_notify"] } ``` **执行流程**: ``` execute_step (Parallel) │ ┌─────────────┼─────────────┐ │ 创建所有分支的 running log │ │ context 写入 _parallel │ │ current_step = 分支[0] │ └─────────────┼─────────────┘ │ ┌──────────▼──────────┐ │ execute_step │ │ (分支 A - task) │ └──────────┬──────────┘ │ 完成 A,pending 移除 A │ remaining > 0 │ current_step = 分支 B ┌──────────▼──────────┐ │ execute_step │ │ (分支 B - task) │ └──────────┬──────────┘ │ 完成 B,pending 清空 │ remaining == 0 │ 清除 _parallel │ ┌────────▼────────┐ │ join_next 存在? │ └───┬─────────┬───┘ │ Yes │ No ▼ ▼ 推进到 工作流 join_next completed ``` **并行状态追踪**:通过 context 中的 `_parallel` 字段实现(内部字段,API 不暴露): ```json { "_parallel": { "parent": "parallel_notify", "pending": ["slack_notify"], "join_next": "generate_report" } } ``` **注意**:当前实现为**顺序执行**分支(串行通过 `execute_step` 逐一完成),而非真正的并发执行。这是基于以下考虑: 1. CMS 场景下"并行"通常是逻辑上的编排需求("这三件事都需要做"),而非性能需求 2. SQLite 不支持高并发写入 3. 真正的并发需要后台 worker 支持 ### 4.6 Delay — 延迟等待 **语义**:等待指定时间后自动推进。 **`next` 格式**:与 Task 相同。 ```json { "id": "wait_24h", "name": "等待24小时", "type": "delay", "config": { "duration_ms": 86400000 }, "next": "check_status" } ``` **当前状态**:`config` 中预留了 `duration_ms`,但引擎尚未实现自动超时推进。目前 Delay 步骤的行为与 Task 相同——需要外部 `execute_step` 调用来推进。 --- ## 5. API 参考 所有 API 位于 `/api/v1/admin/workflows` 前缀下。 ### 5.1 创建工作流定义 ``` POST /api/v1/admin/workflows ``` **请求体**: ```json { "id": "content-review", "name": "内容审核流程", "description": "文章发布前的多级审核", "steps": [ { "id": "draft", "name": "起草", "type": "task", "config": {}, "next": "review" }, { "id": "review", "name": "审核", "type": "await", "config": {}, "next": "" } ] } ``` **响应**: ```json { "code": 0, "message": "created", "data": { "id": 1, "document_id": "content-review", "name": "内容审核流程", ... } } ``` **错误码**: | 状态码 | 场景 | |--------|------| | 400 | steps 为空、步骤引用不存在的 ID、parallel/branch 的 next 格式错误 | ### 5.2 列出所有定义 ``` GET /api/v1/admin/workflows ``` ### 5.3 获取单个定义 ``` GET /api/v1/admin/workflows/{id} ``` ### 5.4 删除定义 ``` DELETE /api/v1/admin/workflows/{id} ``` 注意:删除定义不会级联删除已有实例。 ### 5.5 启动工作流实例 ``` POST /api/v1/admin/workflows/{id}/start ``` **请求体**: ```json { "context": { "title": "新文章", "author": "张三" }, "triggered_by": "user-doc-id-xxx" } ``` **响应**:返回 `WorkflowInstance`,`status = "running"`,`current_step = initial_step`。 **错误码**: | 状态码 | 场景 | |--------|------| | 400 | 工作流定义已禁用(`enabled = false`) | | 404 | 工作流定义不存在 | ### 5.6 执行当前步骤 ``` POST /api/v1/admin/workflows/instances/{instanceId}/execute ``` **请求体**: ```json { "output": { "approved": true, "comment": "通过" } } ``` **行为**: 1. `output` 中的键值合并到工作流 context 2. 当前步骤 log 标记为 `completed` 3. 根据步骤类型和 context 决定下一步 **错误码**: | 状态码 | 场景 | |--------|------| | 400 | 实例不是 `running` 状态 | | 404 | 实例不存在 | ### 5.7 取消工作流实例 ``` POST /api/v1/admin/workflows/instances/{instanceId}/cancel ``` **错误码**: | 状态码 | 场景 | |--------|------| | 400 | 实例不是 `running` 状态 | | 404 | 实例不存在 | ### 5.8 获取步骤日志 ``` GET /api/v1/admin/workflows/instances/{instanceId}/logs ``` **响应**: ```json { "code": 0, "message": "ok", "data": [ { "step_id": "draft", "step_name": "起草", "status": "completed", "input": "{\"title\":\"新文章\"}", "output": "{\"title\":\"新文章\",\"content\":\"...\"}", "started_at": "2026-05-09T10:00:00Z", "completed_at": "2026-05-09T10:05:00Z" } ] } ``` ### 5.9 列出工作流实例 ``` GET /api/v1/admin/workflows/instances?definition_id=xxx&status=running&page=1&page_size=20 ``` 所有查询参数均可选。 --- ## 6. 使用示例 ### 6.1 简单审批流 ``` 起草 → 审核 → 发布 ``` ```json { "id": "simple-review", "name": "简单审批", "steps": [ { "id": "draft", "name": "起草", "type": "task", "config": {}, "next": "review" }, { "id": "review", "name": "审核", "type": "await", "config": {}, "next": "publish" }, { "id": "publish", "name": "发布", "type": "task", "config": {}, "next": "" } ] } ``` ### 6.2 条件分支流 ``` 起草 → 审核 → [通过?发布 : 驳回通知] ``` ```json { "id": "branch-review", "name": "分支审批", "steps": [ { "id": "draft", "name": "起草", "type": "task", "config": {}, "next": "review" }, { "id": "review", "name": "审核决策", "type": "branch", "config": {}, "next": [ { "condition": { "approved": true }, "step": "publish" }, { "step": "reject" } ] }, { "id": "publish", "name": "发布", "type": "task", "config": {}, "next": "" }, { "id": "reject", "name": "驳回通知", "type": "task", "config": {}, "next": "" } ] } ``` 调用 `execute_step` 时传入 output: ```json { "output": { "approved": true } } ``` ### 6.3 并行通知 + 汇合 ``` ┌→ 邮件通知 ─┐ 提交审核 → │ │ → 生成报告 └→ Slack通知 ┘ ``` ```json { "id": "parallel-notify", "name": "并行通知", "steps": [ { "id": "submit", "name": "提交", "type": "task", "config": {}, "next": "notify" }, { "id": "notify", "name": "并行通知", "type": "parallel", "config": { "join_next": "report" }, "next": ["email", "slack"] }, { "id": "email", "name": "邮件通知", "type": "task", "config": {}, "next": "" }, { "id": "slack", "name": "Slack通知", "type": "task", "config": {}, "next": "" }, { "id": "report", "name": "生成报告", "type": "task", "config": {}, "next": "" } ] } ``` ### 6.4 完整内容发布流 ```json { "id": "content-publish", "name": "内容发布流程", "description": "含审核、并行通知、条件发布的完整流程", "steps": [ { "id": "draft", "name": "起草", "type": "task", "config": {}, "next": "review" }, { "id": "review", "name": "编辑审核", "type": "await", "config": {}, "next": "decide" }, { "id": "decide", "name": "审核结果", "type": "branch", "config": {}, "next": [ { "condition": { "approved": true, "priority": "high" }, "step": "urgent_publish" }, { "condition": { "approved": true }, "step": "normal_publish" }, { "step": "back_to_draft" } ] }, { "id": "urgent_publish", "name": "紧急发布", "type": "task", "config": {}, "next": "notify" }, { "id": "normal_publish", "name": "普通发布", "type": "task", "config": {}, "next": "" }, { "id": "notify", "name": "通知相关人员", "type": "parallel", "config": { "join_next": "log" }, "next": ["notify_author", "notify_editors"] }, { "id": "notify_author", "name": "通知作者", "type": "task", "config": {}, "next": "" }, { "id": "notify_editors", "name": "通知编辑组", "type": "task", "config": {}, "next": "" }, { "id": "log", "name": "记录日志", "type": "task", "config": {}, "next": "" }, { "id": "back_to_draft", "name": "退回修改", "type": "task", "config": {}, "next": "draft" } ] } ``` --- ## 7. 当前限制 ### 7.1 已知限制 | 限制 | 说明 | |------|------| | Parallel 顺序执行 | 并行分支通过串行 `execute_step` 完成,非真正并发 | | Delay 未实现自动超时 | 需外部调用 `execute_step` 推进,未接入后台定时器 | | 条件表达式仅支持等值比较 | 不支持 `>`/`<`/`contains`/正则等复杂条件 | | 定义不可修改 | 创建后 steps 不可变更(需删除重建) | | 无版本管理 | `version` 字段预留但未使用 | | 无重试机制 | 步骤失败后无法自动重试 | | 无超时告警 | `timeout_ms` 字段预留但未实现 | | Context 无类型约束 | 所有值都是 `serde_json::Value`,无 schema 校验 | | 取消不清理并行状态 | 并行执行中取消实例,不会标记各分支 log 为 cancelled | ### 7.2 性能边界 - 单实例最大步骤数:无硬限制(实际受 SQLite TEXT 列大小限制) - 并行分支数:无硬限制(每个分支创建独立 step_log 行) - Context 大小:受 SQLite TEXT 列限制(默认 1GB) - 无分页的 `list_workflows`:定义数量大时需加分页 --- ## 8. 升级路线图 按优先级分为 **P0(必需)**、**P1(重要)**、**P2(增强)** 三个等级。 ### P0:核心补全 #### 8.1 Delay 自动超时 **目标**:Delay 步骤到时间后自动推进,无需外部调用。 **方案**: - `WorkflowService::start_workflow` 检查初始步骤是否为 Delay,若是则注册定时器 - 使用 `tokio::time::sleep` + `tokio::spawn` 在后台到期后调用 `execute_step` - Worker 调度器(`src/worker/scheduler.rs`)已有定时任务框架,可复用 **预估工作量**:1-2 天 #### 8.2 步骤超时检测 **目标**:`timeout_ms > 0` 的步骤在指定时间未完成时自动标记失败。 **方案**: - 启动步骤时记录 `started_at` - Worker 定时扫描 `workflow_step_logs WHERE status = 'running' AND (now - started_at) > timeout` - 自动调用 `fail_step` **预估工作量**:1 天 #### 8.3 定义更新 **目标**:支持修改已有工作流定义的 steps,不影响运行中的实例。 **方案**: - 新增 `PUT /admin/workflows/{id}` 端点 - 运行中的实例继续使用启动时的 steps 快照(存储在 instance 上或首次加载时缓存) - 新启动的实例使用最新定义 **预估工作量**:1 天 ### P1:实用功能 #### 8.4 条件表达式增强 **目标**:支持比较运算符和嵌套字段。 **方案**: ```json { "condition": { "score": { "$gt": 80 }, "tags": { "$contains": "rust" }, "meta.region": { "$in": ["us", "eu"] } } } ``` 参考 MongoDB 查询语法,实现 `$gt`/`$lt`/`$gte`/`$lte`/`$in`/`$contains`/`$regex` 运算符。 **预估工作量**:2-3 天 #### 8.5 步骤重试 **目标**:失败步骤可配置自动重试。 **方案**: - StepDef 新增 `config.retry`: ```json { "retry": { "max_attempts": 3, "interval_ms": 5000, "backoff": "exponential" } } ``` - `fail_step` 检查重试配置,若未达上限则重新创建 running log - 指数退避:`interval_ms * 2^(attempt-1)` **预估工作量**:2 天 #### 8.6 Parallel 真正并发 **目标**:并行分支真正同时执行,而非串行。 **方案**: - 使用 `tokio::spawn` 并发执行各分支 - 分支结果通过 `JoinHandle` 收集 - 所有分支完成后才推进到 `join_next` **前提**:需要先实现真正的后台 Task 执行能力(见 8.8)。 **预估工作量**:3-5 天 #### 8.7 工作流事件 **目标**:工作流状态变更时发出事件,供 Webhook/通知系统消费。 **方案**: - 复用现有 `EventBus`,新增事件类型: - `WorkflowStarted { instance_id, definition_id }` - `StepCompleted { instance_id, step_id, output }` - `StepFailed { instance_id, step_id, error }` - `WorkflowCompleted { instance_id }` - `WorkflowCancelled { instance_id }` - Handler 层在调用 service 后 emit 事件 **预估工作量**:1-2 天 ### P2:高级特性 #### 8.8 Task 自动执行 **目标**:Task 步骤可绑定 plugin hook 或内置 action,自动执行而非等待外部 `execute_step`。 **方案**: - StepDef config 新增 `action`: ```json { "action": "plugin:email/send", "params": { "to": "{{context.author_email}}" } } ``` - 引擎在推进到 Task 步骤时自动调用对应 handler - 支持 `mustache` 模板语法从 context 中取值 **预估工作量**:5-7 天 #### 8.9 子工作流 **目标**:步骤可嵌套调用另一个工作流。 **方案**: - 新增步骤类型 `SubWorkflow`: ```json { "id": "sub", "type": "sub_workflow", "config": { "workflow_id": "approval-flow" }, "next": "..." } ``` - 父实例等待子实例完成后获取其 output 作为自身 step output **预估工作量**:3-5 天 #### 8.10 可视化定义 **目标**:前端拖拽式工作流编辑器 + 后端验证。 **方案**: - 前端使用 React Flow / dagre.js 绘制流程图 - 导出为现有 JSON 格式 - 后端新增 `POST /admin/workflows/validate` 校验端点 **预估工作量**:前端为主,后端 1 天 #### 8.11 版本管理 **目标**:工作流定义支持版本化和灰度发布。 **方案**: - `workflow_definitions` 新增 `version` 自增逻辑 - 实例记录 `definition_version` - 支持回滚到指定版本 **预估工作量**:2-3 天 #### 8.12 审计与监控 **目标**:集成 `audit_log`,提供工作流运行统计面板。 **方案**: - 复用 `src/audit.rs`,记录关键操作 - 新增统计 API: - `GET /admin/workflows/stats` — 定义数、运行中/完成/失败实例数 - `GET /admin/workflows/instances/{id}/timeline` — 甘特图数据 - 平均步骤耗时计算 **预估工作量**:2-3 天 --- ## 升级优先级总览 | 优先级 | 编号 | 名称 | 工作量 | 价值 | |--------|------|------|--------|------| | **P0** | 8.1 | Delay 自动超时 | 1-2 天 | 完善 Delay 语义 | | **P0** | 8.2 | 步骤超时检测 | 1 天 | 防止步骤永久卡住 | | **P0** | 8.3 | 定义更新 | 1 天 | 基础管理能力 | | **P1** | 8.4 | 条件表达式增强 | 2-3 天 | 解锁复杂业务场景 | | **P1** | 8.5 | 步骤重试 | 2 天 | 提高可靠性 | | **P1** | 8.6 | Parallel 真正并发 | 3-5 天 | 性能提升 | | **P1** | 8.7 | 工作流事件 | 1-2 天 | 可观测性 | | **P2** | 8.8 | Task 自动执行 | 5-7 天 | 真正的自动化 | | **P2** | 8.9 | 子工作流 | 3-5 天 | 流程复用 | | **P2** | 8.10 | 可视化定义 | 后端 1 天 | 用户体验 | | **P2** | 8.11 | 版本管理 | 2-3 天 | 安全变更 | | **P2** | 8.12 | 审计与监控 | 2-3 天 | 运维能力 | **建议实施顺序**:8.3 → 8.1 → 8.2 → 8.7 → 8.4 → 8.5 → 8.12 → 8.8 → 8.6 → 8.11 → 8.9 → 8.10