# 会议核销SaaS系统技术开发文档

## 1. 文档说明

### 1.1 文档目的
- 将 `基金会、协会、北京欣欣会议核销系统_完整版.md` 的业务需求落地为可研发实施的技术方案。
- 作为产品、研发、测试、运维的统一执行基线。

### 1.2 适用范围
- 多租户会议核销SaaS平台。
- 覆盖系统设置、项目管理、会议管理、审核管理、专家（参会人）管理、模板管理、财务管理等模块。

### 1.3 术语统一
- 租户：单位主体。
- 模板：统一使用“模板”命名。
- 专家：参会人主数据实体。
- 审核聚合状态：待审核、审核中、审核通过、审核拒绝。

---

## 2. 总体技术架构

### 2.1 架构分层
- 前端层：Web管理端（PC优先）。
- 网关层：统一鉴权、限流、审计埋点入口。
- 业务服务层：用户权限、项目会议、审核、模板、财务、专家服务。
- 任务调度层：通知发送、超时催办、报表导出、文件处理。
- 数据层：关系型数据库 + 对象存储 + 缓存。

### 2.2 推荐技术栈
- 前端：`Vue3 + TypeScript + Element Plus`（最终确定）。
- 后端：`Java Spring Boot`（最终确定）。
- 数据库：`MySQL 5.7`（最终确定）。
- 缓存：`Redis`（会话、字典、短期查询缓存、分布式锁）。
- 对象存储：`阿里云 OSS`（会议资料、模板、附件，最终确定）。
- 消息队列：当前阶段不引入，异步任务采用 `Spring Scheduler + 数据库任务表` 实现。

### 2.3 部署拓扑
- 环境：`dev / test / staging / prod` 四套。
- 组件：`api`、`worker`、`scheduler`、`web`、`mysql`、`redis`、`object-storage`。
- 网络：内外网隔离，数据库与对象存储走私网。

### 2.4 前端组件规范（Element Plus）
- 页面类型统一
  - 列表页：查询区 + 表格区 + 分页区 + 批量操作区。
  - 详情页：基础信息卡片 + 状态流转卡片 + 操作记录时间线。
  - 表单页：分步表单或分组卡片表单，统一必填标识与校验提示。
- 组件选型统一
  - 表格：`el-table`，大列表必须启用服务端分页与排序。
  - 表单：`el-form + el-form-item`，统一校验触发时机（blur/change）。
  - 弹窗：`el-dialog`，二次确认场景统一危险操作提示文案。
  - 抽屉：`el-drawer`，用于轻量编辑与详情预览。
  - 上传：`el-upload`，统一文件类型、大小、命名校验。
- 交互规范
  - 所有异步操作提供加载态、防重复提交和结果反馈。
  - 高风险操作（删除、状态回滚、支付确认）必须二次确认。
  - 权限不足按钮置灰并提供提示，不直接隐藏关键功能入口。
- 视觉与主题
  - 统一使用 Element Plus 主题变量管理色板、间距、字体。
  - 状态色规范：成功（绿）、处理中（蓝）、拒绝/异常（红）、待处理（橙）。

### 2.5 部署配置与环境变量清单（必须）
- 应用基础
  - `APP_ENV`、`SERVER_PORT`、`LOG_LEVEL`、`TIME_ZONE=Asia/Shanghai`
- MySQL 5.7
  - `DB_URL`、`DB_USERNAME`、`DB_PASSWORD`
  - `DB_POOL_MAX_ACTIVE`、`DB_POOL_MIN_IDLE`、`DB_CONN_TIMEOUT_MS`
  - `DB_TX_ISOLATION`（建议按业务定义，默认 `READ COMMITTED`）
- Redis
  - `REDIS_HOST`、`REDIS_PORT`、`REDIS_PASSWORD`、`REDIS_DB`
  - `REDIS_LOCK_TIMEOUT_MS`
- OSS
  - `OSS_ENDPOINT`、`OSS_BUCKET`、`OSS_ACCESS_KEY_ID`、`OSS_ACCESS_KEY_SECRET`
  - `OSS_SIGN_EXPIRE_SECONDS`、`OSS_CORS_ORIGIN_WHITELIST`
- 鉴权与安全
  - `JWT_SECRET`、`JWT_EXPIRE_MINUTES`、`REFRESH_TOKEN_EXPIRE_DAYS`
  - `DATA_ENCRYPT_KEY`（敏感字段加密）/ `KMS_KEY_ID`（如启用KMS）
- 调度任务
  - `SCHEDULER_ENABLED`、`SCHEDULER_POLL_INTERVAL_MS`
  - `SCHEDULER_BATCH_SIZE`、`JOB_MAX_RETRY`、`JOB_TIMEOUT_SECONDS`
- 通知与邮件
  - 邮件 SMTP 参数统一在“通知网关配置 > 邮件网关”中维护
  - `MAIL_FROM`、`NOTIFY_CHANNELS`

---

## 3. 多租户与权限模型

### 3.1 租户隔离策略
- 所有业务表强制包含 `tenant_id`。
- 查询默认注入 `tenant_id` 过滤条件。
- 导出、下载、搜索、统计均执行租户隔离校验。

### 3.2 RBAC + 数据范围
- RBAC：平台超级管理员、单位管理员、负责人、项目执行人、审核人、财务、审计只读。
- 数据范围：租户范围、项目范围、会议范围、模块范围。
- 策略优先级：显式拒绝 > 显式允许 > 默认拒绝。

### 3.3 职责互斥
- 提交人与对应审核人不能同人。
- 初审人与终审人默认不能同人（例外需留痕）。
- 财务不可修改审核结论，审核人不可修改财务字段。

---

## 4. 业务模块技术拆分

### 4.1 系统设置
- 租户管理（平台级）：租户创建、启停、状态治理与审计留痕。
- 企业管理：企业档案维护。
- 用户管理：账号生命周期、代理授权、角色变更快照。
- 菜单与权限：菜单可见性与动作权限绑定。
- 审核流配置：1级/2级/3级审核链配置。
- 通知策略：渠道、触发事件、模板变量。
- 审计日志：高风险操作留痕与查询。

### 4.2 项目管理
- 项目主数据：负责人、执行人、预算、期数、状态。
- 预算控制：超支阈值、审批链、冻结/解冻。
- 变更控制：周期、预算、负责人、执行人变更留痕。
- SLA预警：到期预警、超支预警、资料缺失预警。

### 4.3 会议管理
- 会议主数据：时间、地点、形式、费用、占比。
- 资料模块：基础信息、核销材料、现场照片、劳务协议、发票明细、专家简介。
- 会议级提交：必填模块完成后触发审核流程。
- 字段锁定：提交后锁定费用类字段，终审后只读。

### 4.4 审核管理
- 节点动作：通过、拒绝、退回修改、转审。
- 状态映射：节点状态映射会议聚合状态。
- SLA：超时催办与升级通知。
- 审核留痕：意见、附件、前后状态、操作终端。

### 4.5 专家（参会人）管理
- 专家主数据：身份信息、联系方式、职称、机构。
- 银行卡治理：多卡、默认卡、一致性校验。
- 去重合并：身份证唯一 + 相似度辅助。
- 快照引用：会议提交时固化专家关键字段快照。

### 4.6 模板管理
- 模板全生命周期：草稿、已发布、已停用、已归档。
- 版本管理：新版本发布、回滚、差异追踪。
- 下载留痕：下载日志、水印、越权校验。
- 流程联动：会议推荐模板、审核节点通知模板、结算模板。

### 4.7 财务管理
- 入账口径：仅终审通过会议进入财务计算。
- 支付流转：待提交 -> 待财务确认 -> 已确认 -> 部分支付 -> 已结清。
- 对账结算：差异工单、锁账/解锁、台账导出。
- 风控规则：超预算、超阈值、重复支付拦截。

### 4.8 会议字段管理（已下线）
- 会议字段管理模块已从当前版本移除，不再提供字典配置页面与相关接口。
- 会议模块字段由业务模型与接口契约直接维护。

### 4.9 发票管理（已实现）
- 发票抬头主数据：企业名称、税号、开户行、账号、地址、电话。
- 关联范围：支持按项目绑定默认抬头，会议可覆盖。
- 合规校验：税号格式、账号长度、唯一性校验。
- 留痕与导出：支持变更历史与按权限导出。

---

## 5. 核心状态机定义

### 5.1 项目状态机
- `待开始 -> 进行中 -> 已完成`
- 可人工流转：`进行中 -> 已中止`、`已完成 -> 已归档`、`任意 -> 已冻结`

### 5.2 会议状态机
- `未开始 -> 进行中 -> 已完成`
- 扩展流转：`未开始 -> 已取消`、`任意 -> 已冻结`、`进行中/已完成 -> 已延期(标记)`

### 5.3 审核状态机
- 节点状态：待审核、初审拒绝、初审通过、复审拒绝、复审通过、终审拒绝、终审通过
- 聚合状态：待审核、审核中、审核通过、审核拒绝
- 关键规则：终审通过后若关键字段变更，回退到待审核

### 5.4 支付状态机
- `待提交 -> 待财务确认 -> 已确认 -> 部分支付 -> 已结清`
- 风险场景：`任意 -> 冻结支付`

---

## 6. 数据模型设计（核心表）

> 以下为核心表建议，实际可按单体/微服务拆分。

### 6.1 租户与用户
- `tenant`：租户信息。
- `user`：用户账号（含状态、有效期、tenant_id）。
- `role` / `permission` / `role_permission`：角色权限模型。
- `user_role`：用户角色绑定。
- `user_delegation`：代理授权记录（生效时间窗、状态、失效原因）。
- `data_scope_policy`：数据范围策略。

### 6.1.1 平台设置补充模型
- `enterprise`：企业主数据（名称、网址、Logo、状态）。
- `menu`：菜单定义（层级、路由、排序、状态、permission_code）。
- `role_menu`：角色与菜单绑定关系。

### 6.2 项目与会议
- `project`：项目主表（预算、期数、状态、负责人）。
- `project_member`：项目成员（主办/合作负责人、执行人）。
- `project_change_log`：项目变更日志。
- `meeting`：会议主表（时间、地点、费用、状态）。
- `meeting_material`：会议资料主表（模块、版本、状态）。
- `meeting_material_file`：资料附件文件表。
- `meeting_expert_snapshot`：会议引用专家快照。

### 6.3 审核
- `audit_flow`：审核流定义。
- `audit_flow_node`：审核节点定义。
- `audit_task`：审核任务实例（按会议+模块+节点）。
- `audit_action_log`：审核动作日志（通过/拒绝/退回/转审）。

### 6.4 专家
- `expert`：专家主表（脱敏展示字段 + 加密字段索引）。
- `expert_bank_card`：专家银行卡表（默认卡、状态）。
- `expert_merge_log`：专家合并记录。

### 6.5 模板
- `template`：模板主表（类型、状态、范围）。
- `template_version`：模板版本表（版本号、生效标记）。
- `template_download_log`：模板下载日志。

### 6.6 财务
- `finance_project_summary`：项目级财务汇总。
- `finance_meeting_bill`：会议费用账单。
- `finance_payment`：支付记录。
- `finance_reconciliation`：对账记录。
- `finance_risk_event`：财务风险事件。

### 6.7 通用
- `notification_policy` / `notification_policy_event`：通知策略与事件绑定（已实现）。
- `notification_task`：通知执行任务（已实现，支持任务化发送与重试）。
- `export_task`：导出任务中心（已实现，支持任务化导出与状态跟踪）。
- `operation_audit_log`：系统操作审计日志。

### 6.8 关键索引建议
- 所有核心业务表组合索引：`(tenant_id, status, updated_at)`。
- 审核任务索引：`(tenant_id, assignee_user_id, node_status)`。
- 财务支付索引：`(tenant_id, project_id, payment_status, payment_time)`。
- 下载日志索引：`(tenant_id, template_id, downloader_id, created_at)`。

### 6.9 字段级DDL规范（MySQL 5.7）
- 通用字段（所有业务主表）
  - `id bigint unsigned`：主键。
  - `tenant_id bigint unsigned`：租户隔离键，必填并建索引。
  - `status varchar(32)`：状态字段，必填并建索引。
  - `is_deleted tinyint(1)`：软删除标记，默认 `0`。
  - `created_by bigint unsigned`、`created_at datetime`。
  - `updated_by bigint unsigned`、`updated_at datetime`。
- 用户生命周期扩展字段（`sys_user`）
  - `valid_from datetime`：账号生效时间。
  - `valid_to datetime`：账号失效时间。
  - 登录/鉴权/关键写操作均需校验有效期窗口。
- 金额与比例字段
  - 金额统一 `bigint`（单位：分），禁止使用 `float/double`。
  - 比例统一 `decimal(8,6)`（如 `0.150000` 表示 15%）。
- 文本与枚举
  - 短文本优先 `varchar`，长文本使用 `text`。
  - 枚举字段使用 `varchar + 字典约束`，避免 MySQL `enum` 变更成本。
- 索引规范
  - 组合索引按“等值过滤字段在前、范围字段在后”。
  - 高频查询字段必须包含 `tenant_id`，避免跨租户扫描。
- 约束规范
  - 关键业务唯一键建议：`tenant_id + business_no` 唯一索引。
  - 外键约束按性能评估可选，必须在应用层做强校验。

### 6.10 字段级数据字典补充（按业务优先级）
- 目标
  - 将“完整版业务文档”的关键字段沉淀为研发可直接落库、联调、测试的统一口径。
  - 本节与 `6.1~6.9` 配套使用；未列出的字段可在模块详细设计中扩展。
- `project`（项目主表）建议补充字段
  - 组织关系：`host_enterprise_id`、`partner_enterprise_id`。
  - 人员关系：`host_owner_user_id`、`host_executor_user_id`、`partner_owner_user_id`、`partner_executor_user_id`。
  - 预算控制：`allow_meeting_over_budget`、`over_budget_threshold_ratio`、`over_budget_approval_chain_json`。
  - 过程指标：`meeting_total_count`、`meeting_completed_count`、`budget_execution_ratio`、`risk_flags_json`。
- `meeting`（会议主表）建议补充字段
  - 基础维度：`subject`、`sub_project_name`、`meeting_category`、`meeting_form`、`location`、`start_time`、`end_time`。
  - 预算维度：`budget_amount_cent`、`labor_ratio`、`catering_ratio`。
  - 流程维度：`current_audit_node`、`last_submit_at`、`last_reject_reason`。
  - 风险维度：`overdue_days`、`risk_flags_json`、`is_frozen`、`freeze_reason`。
- `meeting_material`（会议资料主表）建议补充字段
  - 模块标识：`material_module`（BASIC/MATERIAL/PHOTO/LABOR/INVOICE/EXPERT_PROFILE）。
  - 版本链：`material_version`、`is_latest_version`、`source_version_id`。
  - 状态字段：`fill_status`、`audit_node_status`、`audit_aggregate_status`。
  - 追溯字段：`submit_remark`、`reject_count`、`last_reject_reason`、`resubmit_at`。
- `meeting_material_invoice_item`（建议新增：发票明细项）
  - 明细口径：`expense_type`、`invoice_no`、`invoice_amount_cent`、`tax_amount_cent`、`detail_amount_cent`、`vendor_name`、`occur_date`、`remark`。
  - 索引建议：`(tenant_id, meeting_id, expense_type, occur_date)`。
- `meeting_material_invoice_file`（建议新增：发票明细附件）
  - 附件口径：`file_type`（INVOICE/DETAIL/PHOTO/TICKET/OTHER）、`file_name`、`oss_key`、`content_type`、`size`。
  - 关联字段：`invoice_item_id`、`meeting_id`、`material_version`。
- `meeting_invoice_summary`（建议新增：发票模块汇总）
  - 汇总口径：`category_amount_cent_json`、`meeting_total_amount_cent`、`is_over_budget`。
- `audit_task`（审核任务）建议补充字段
  - SLA字段：`sla_deadline_at`、`overtime_hours`、`is_overtime`。
  - 流转字段：`transfer_from_user_id`、`transfer_reason`、`return_reason`。
  - 统计字段：`reject_count`、`last_reject_reason`、`last_action_at`。
- `audit_action_log`（审核动作日志）建议补充字段
  - 动作细化：`action_type`（APPROVE/REJECT/RETURN/TRANSFER/REMIND）。
  - 上下文字段：`from_status`、`to_status`、`opinion`、`attachment_json`。
  - 终端字段：`operator_ip`、`operator_terminal`、`request_id`。
- `expert`（专家主表）建议补充字段
  - 基础字段：`gender`、`birthday`、`id_card_no`、`id_card_valid_until`、`phone`、`title`、`hospital`。
  - 状态治理：`status_reason`、`status_changed_by`、`status_changed_at`。
  - 合规模块：`sensitive_mask_level`、`export_restricted`。
- `expert_bank_card`（专家银行卡）建议补充字段
  - 卡片字段：`bank_name`、`bank_account_no`、`bank_province`、`bank_city`、`bank_branch_name`。
  - 治理字段：`is_default`、`card_status`、`inconsistent_name_approved`、`change_reason`。
- `template` / `template_version` 建议补充字段
  - 模板范围：`template_type`、`scope_type`、`scope_id`、`effective_from`、`effective_to`。
  - 版本治理：`version_no`、`is_effective`、`change_log`、`rollback_reason`。
  - 安全治理：`watermark_enabled`、`download_rate_limit_per_hour`。
- `finance_meeting_bill`（会议账单）建议补充字段
  - 分类费用：`venue_amount_cent`、`build_amount_cent`、`hotel_amount_cent`、`catering_amount_cent`、`local_traffic_amount_cent`、`long_distance_traffic_amount_cent`、`material_amount_cent`、`design_amount_cent`、`labor_payable_amount_cent`、`labor_actual_amount_cent`。
  - 财务录入：`finance_review_fee_cent`、`management_fee_cent`、`tax_fee_cent`、`custom_fee_json`。
  - 对账结算：`paid_amount_cent`、`unpaid_amount_cent`、`reconciliation_result`、`reconciliation_diff_amount_cent`、`reconciliation_diff_reason`、`settlement_no`。
- 与现有实现对齐建议
  - `6.10` 字段优先用于新增列与新表设计，不破坏现有 API 契约。
  - 存量接口先兼容返回，新增字段按“可选字段 -> 必填字段”两阶段升级。

---

## 7. 接口设计规范与清单 

### 7.1 API规范
- 协议：`HTTPS + RESTful + JSON`。
- 鉴权：`JWT + Refresh Token`。
- 幂等：创建支付、审核动作、导出任务使用幂等键。
- 错误码：统一业务错误码（权限不足、状态不允许、重复提交、超预算等）。

### 7.2 核心接口分组（示例）
- 鉴权与用户
  - `POST /api/auth/login`
  - `POST /api/users`
  - `PATCH /api/users/{id}/status`
- 平台设置（租户/企业/菜单）
  - `GET /api/tenants`
  - `POST /api/tenants`
  - `POST /api/tenants/{id}/enable`
  - `POST /api/tenants/{id}/disable`
  - `GET /api/enterprises`
  - `POST /api/enterprises`
  - `PUT /api/enterprises/{id}`
  - `GET /api/menus`
  - `POST /api/menus`
  - `POST /api/roles/{id}/menus`
- 用户生命周期增强
  - `POST /api/users/{id}/delegations`
  - `GET /api/users/{id}/delegations`
  - `POST /api/delegations/{id}/disable`
- 项目
  - `GET /api/projects`
  - `POST /api/projects`
  - `PATCH /api/projects/{id}`
  - `POST /api/projects/{id}/freeze`
- 会议
  - `GET /api/meetings`
  - `POST /api/meetings`
  - `POST /api/meetings/{id}/submit`
  - `POST /api/meetings/{id}/withdraw`
- 审核
  - `GET /api/audits/tasks`
  - `POST /api/audits/tasks/{id}/approve`
  - `POST /api/audits/tasks/{id}/reject`
  - `POST /api/audits/tasks/{id}/return`
  - `POST /api/audits/tasks/{id}/transfer`
- 专家
  - `GET /api/experts`
  - `POST /api/experts`
  - `POST /api/experts/{id}/merge`
- 模板
  - `GET /api/templates`
  - `POST /api/templates`
  - `POST /api/templates/{id}/publish`
  - `POST /api/templates/{id}/rollback`
  - `GET /api/templates/{id}/download`
- 财务
  - `GET /api/finance/projects`
  - `POST /api/finance/payments`
  - `POST /api/finance/reconciliation`
  - `POST /api/finance/lock`
  - `POST /api/finance/unlock`

### 7.2.2 接口实施状态对照（2026-03）
- 已实现（核心）
  - 租户、用户、角色、数据权限、审核流、项目、会议提交、会议资料六模块、审核动作（通过/拒绝/退回/转审/催办/SLA）。
  - 财务支付确认、对账、锁账/解锁；模板上传发布回滚归档水印下载与流程联动；专家主档案与合并/导入导出/银行卡；通知策略中心；可观测性告警中心。
  - `POST /api/meetings/{id}/withdraw`（会议撤回提交）；发票管理模块（发票抬头主数据 API 与页面）。
  - `POST /api/notifications/dispatch` + `POST /api/notifications/receipts` + `GET /api/notifications/tasks`（通知执行引擎）。
  - `GET/POST /api/export-tasks` + `POST /api/export-tasks/{id}/refresh-token` + `GET /api/export-tasks/{id}/download`（导出任务中心，下载鉴权与过期控制）。
  - `POST /api/observability/alert-rules/evaluate/auto`（自动评估）+ `GET /api/operations/dashboard`（运营看板汇总）。
  - 代理授权生命周期：`GET /api/users/{id}/delegations`、`POST /api/users/{id}/delegations`、`POST /api/delegations/{id}/disable`，含有效期自动状态流转与代理权限继承判定。
- 未实现（文档已定义）
  - 租户管理前端入口与平台菜单治理（菜单管理模块化能力）。
  - 企业管理模块化落地（企业主数据独立维护与项目引用联动）。
  - 账号有效期统一校验（登录/刷新令牌/关键写操作一致校验）。
  - 通知外部通道深度对接（真实短信/邮件供应商回执、失败原因标准化）。

### 7.2.1 接口权限映射规范（必须）
- 每个接口必须绑定以下元数据
  - `permissionCode`：动作权限码（如 `meeting.submit`）。
  - `dataScopeType`：租户/项目/会议/模块范围校验类型。
  - `auditActionCode`：审计动作码（如 `AUDIT_MEETING_SUBMIT`）。
- 权限校验顺序
  - 登录鉴权 -> 角色动作权限 -> 数据范围权限 -> 职责互斥规则 -> 状态机校验。
- 前端按钮权限规则
  - 按 `permissionCode` 控制可见/可点击；
  - 置灰时需展示无权限原因。

### 7.3 前后端统一开发规范（必须）
- 接口契约统一
  - 所有接口采用 `REST + JSON + UTF-8`，路径前缀统一为 `/api`。
  - 成功响应统一结构：`{ code, message, data, requestId, timestamp }`，其中 `code=0` 表示成功。
  - 失败响应统一结构：`{ code, message, errors, requestId, timestamp }`，`errors` 用于字段级错误。
- 数据格式统一
  - 时间统一使用 `ISO 8601`（后端返回 UTC，前端按时区展示）。
  - 金额统一使用“分”为最小单位（`long`），前端仅展示时转元并格式化。
  - 比例统一用百分比小数（如 `0.15`），前端展示为 `15%`。
  - 枚举统一返回 `code + label`，禁止前端硬编码状态文案。
- 分页与排序统一
  - 请求参数统一：`pageNo`、`pageSize`、`sortBy`、`sortOrder`。
  - 分页响应统一：`{ list, total, pageNo, pageSize }`。
  - 大列表必须后端分页，禁止前端全量拉取再分页。
- 权限与安全统一
  - 前端负责“可见性控制”，后端负责“最终权限校验”，两端都必须校验。
  - 所有写操作接口要求鉴权 + 操作审计埋点。
  - 高风险动作（删除、回滚、支付确认、锁账）要求二次确认与幂等键。
- 命名与字段统一
  - 接口字段统一使用 `camelCase`。
  - 数据库字段统一使用 `snake_case`。
  - 布尔字段统一前缀：`is`/`has`；状态字段统一使用 `status`。
  - 主键统一 `id`（雪花或UUID），业务单号使用独立字段（如 `orderNo`、`settlementNo`）。
- 前后端协作流程统一
  - 先定义并评审接口文档（建议 OpenAPI），后并行开发。
  - Mock 数据由后端提供 schema，前端不得长期依赖手写假字段。
  - 联调前冻结字段名、枚举值、错误码，变更必须走变更单。
- 日志与排障统一
  - 每个请求生成并透传 `requestId`，前后端日志可串联检索。
  - 关键链路（会议提交、审核动作、支付确认）必须输出结构化业务日志。
  - 前端错误上报包含：路由、用户、请求接口、requestId、堆栈摘要。
- 质量门禁统一
  - 后端：单元测试覆盖状态机、金额计算、权限校验。
  - 前端：核心页面需有组件测试与关键流程 E2E。
  - CI 门禁：代码扫描、测试通过、接口兼容性检查通过后方可合并。

### 7.4 统一错误码清单（必须）
- 落地位置（当前实现）
  - 统一错误码由后端 Java 常量类维护：`backend/src/main/java/com/writeoff/common/exception/ErrorCodes.java`。
  - 业务异常通过 `BusinessException` 抛出，并引用 `ErrorCodes` 常量，避免散落硬编码数字。
  - 数据库当前不维护错误码字典表（如需运营化配置可在后续版本新增）。
- 通用规则
  - 错误码为整数，`0` 表示成功。
  - 错误码分段：`1xxxx` 通用与认证，`2xxxx` 权限与租户，`3xxxx` 业务状态机，`4xxxx` 财务与支付，`5xxxx` 文件与模板，`9xxxx` 系统异常。
  - `message` 面向用户，`errors` 面向前端字段级提示，`requestId` 用于排障追踪。
- `10001` 参数校验失败：必填项缺失或格式错误。
- `10002` 请求幂等冲突：重复提交被拦截。
- `10003` 资源不存在：目标对象不存在或已删除。
- `10004` 方法不允许：不支持的请求方法或路径。
- `10005` 请求过于频繁：触发限流策略。
- `11001` 未登录或Token无效：需要重新登录。
- `11002` Token已过期：需要刷新或重新登录。
- `11003` 会话失效：账号被禁用或异地下线。
- `20001` 无操作权限：角色不具备动作权限。
- `20002` 无数据权限：越权访问租户/项目/会议数据。
- `20003` 租户状态异常：租户已停用或冻结。
- `20004` 职责互斥冲突：提交人与审核人冲突，或初审终审冲突。
- `30001` 状态不允许流转：当前状态不支持该动作。
- `30002` 审核节点不匹配：非当前节点审核人发起审核动作。
- `30003` 审核任务已处理：重复审核或并发处理冲突。
- `30004` 会议级提交条件不足：必填模块未完成。
- `30005` 终审后变更限制：关键字段变更需回退待审核。
- `30006` 项目变更校验失败：期数/周期/预算不满足约束。
- `40001` 超预算拦截：金额超过项目预算且未审批放行。
- `40002` 占比超阈值：餐费或劳务费超过阈值限制。
- `40003` 支付状态不允许：当前支付状态不能执行该动作。
- `40004` 缺少支付凭证：支付确认必填凭证未上传。
- `40005` 对账差异未处理：存在差异工单，不允许结清。
- `40006` 重复支付风险：同会议同金额同凭证号重复。
- `50001` 文件类型不支持：不在白名单范围内。
- `50002` 文件大小超限：超过模块上传限制。
- `50003` 文件安全校验失败：病毒扫描或格式校验失败。
- `50004` 模板状态不允许：草稿/停用/归档状态不支持该操作。
- `50005` 模板版本冲突：版本已变更，需要刷新重试。
- `50006` 文件下载越权：无项目或会议下载权限。
- `90001` 系统内部异常：未分类错误。
- `90002` 数据库异常：数据库连接或事务执行失败。
- `90003` 外部服务异常：OSS或邮件服务调用失败。
- `90004` 异步任务执行失败：任务重试后仍失败。
- 前端处理约定
  - `10001` 返回字段级错误时，表单逐项高亮并定位首个错误项。
  - `11001/11002/11003` 统一跳转登录页并提示登录状态失效。
  - `200xx/300xx/400xx/500xx` 弹业务提示，不显示系统堆栈。
  - `900xx` 展示统一兜底文案并提示 `requestId` 给运维排障。

### 7.5 HTTP状态码映射规范
- `200`：成功（`code=0`）。
- `400`：请求参数错误（通常对应 `10001`）。
- `401`：未认证/登录失效（`11001/11002/11003`）。
- `403`：权限不足或数据越权（`20001/20002`）。
- `404`：资源不存在（`10003`）。
- `409`：状态冲突或并发冲突（`30001/30003/50005`）。
- `422`：业务校验失败（`30004/30006/40001/40002`）。
- `429`：请求过于频繁（`10005`）。
- `500`：系统内部异常（`90001+`）。
- 约束：前端以业务 `code` 为主处理逻辑，HTTP状态码作为网络层辅助判断。

### 7.6 核心接口请求响应示例（节选）
- 会议级提交
  - 请求：`POST /api/meetings/{id}/submit`
  - Body:
```json
{
  "idempotencyKey": "submit-20260309-0001",
  "operatorId": 10001,
  "remark": "资料提交审核"
}
```
  - 响应：
```json
{
  "code": 0,
  "message": "success",
  "data": {
    "meetingId": 20001,
    "auditStatus": "PENDING",
    "currentNode": "INIT_REVIEW"
  },
  "requestId": "9f0f8c2f7e9e4d24",
  "timestamp": "2026-03-09T10:20:30Z"
}
```
- 审核通过
  - 请求：`POST /api/audits/tasks/{id}/approve`
  - Body:
```json
{
  "idempotencyKey": "audit-approve-20260309-0101",
  "opinion": "资料完整，审核通过"
}
```
  - 响应：
```json
{
  "code": 0,
  "message": "success",
  "data": {
    "taskId": 30001,
    "nodeStatus": "APPROVED",
    "meetingAuditStatus": "IN_REVIEW"
  },
  "requestId": "c4316bb50aa74c45",
  "timestamp": "2026-03-09T10:30:20Z"
}
```
- 支付确认
  - 请求：`POST /api/finance/payments`
  - Body:
```json
{
  "idempotencyKey": "pay-confirm-20260309-0008",
  "projectId": 5001,
  "meetingId": 20001,
  "amountCent": 1280000,
  "paymentVoucherOssKey": "1001/5001/20001/finance/202603/voucher-01.pdf"
}
```
  - 响应：
```json
{
  "code": 0,
  "message": "success",
  "data": {
    "paymentId": 90001,
    "paymentStatus": "CONFIRMED"
  },
  "requestId": "8f7cd9b0b8f84b5b",
  "timestamp": "2026-03-09T10:40:02Z"
}
```

### 7.7 业务能力到接口映射补全（缺口收敛）
- 系统设置-角色管理
  - `GET /api/roles`（角色列表）
  - `POST /api/roles`（创建角色）
  - `PUT /api/roles/{id}`（编辑角色）
  - `POST /api/roles/{id}/enable`、`POST /api/roles/{id}/disable`（启停）
  - `POST /api/roles/{id}/permissions`（动作权限绑定）
- 系统设置-数据权限管理
  - `GET /api/data-scope-policies`
  - `POST /api/data-scope-policies`
  - `PUT /api/data-scope-policies/{id}`
  - `POST /api/data-scope-policies/{id}/copy`
  - `POST /api/data-scope-policies/{id}/assign-roles`
  - `POST /api/data-scope-policies/{id}/enable`、`POST /api/data-scope-policies/{id}/disable`
- 系统设置-审计日志
  - `GET /api/audit-logs`（按账号/模块/动作/时间范围查询）
  - `GET /api/audit-logs/export-tasks`、`POST /api/audit-logs/export-tasks`（异步导出）
- 会议资料与总结包
  - `POST /api/meetings/{id}/materials/{module}/submit`（模块提交）
  - `POST /api/meetings/{id}/materials/{module}/resubmit`（驳回后重提）
  - `POST /api/meetings/{id}/materials/export`（导出会议资料包，任务化）
  - `POST /api/meetings/{id}/summary/generate`（生成会议总结）
  - `GET /api/meetings/{id}/summary/download`（下载会议总结）
- 审核运营动作
  - `POST /api/audits/tasks/{id}/remind`（单任务催办）
  - `POST /api/audits/tasks/batch-remind`（批量催办）
  - `POST /api/audits/tasks/export-opinions`（导出审核意见）
- 通知策略中心（配置侧）
  - `GET /api/notification-policies`
  - `POST /api/notification-policies`
  - `PUT /api/notification-policies/{id}`
  - `POST /api/notification-policies/{id}/events`
  - `POST /api/notification-policies/{id}/enable`、`POST /api/notification-policies/{id}/disable`
- 发票管理（抬头主数据）
  - `GET /api/invoice-heads`
  - `POST /api/invoice-heads`
  - `PUT /api/invoice-heads/{id}`
  - `POST /api/invoice-heads/{id}/enable`、`POST /api/invoice-heads/{id}/disable`

### 7.8 接口与权限矩阵总表（模块 -> 接口 -> 权限）
- 约束
  - 每个接口在 OpenAPI 中必须绑定：`permissionCode`、`dataScopeType`、`auditActionCode`。
  - 前端按钮权限与接口权限码同源维护，禁止“按钮权限码”和“接口权限码”双套定义。
- 实施状态（2026-03，后端已落地）
  - 已在后端注解层统一为：`@RequirePermission(value=..., dataScope=..., auditAction=...)`。
  - 已新增启动期门禁组件：`PermissionMetadataGuard`（配置项：`writeoff.permission-metadata.strict`）。
  - 审计日志动作码已切换为优先读取 `auditActionCode`（未配置时回退 `permissionCode`）。
- 基线矩阵（节选，可直接用于前后端同源配置）
  - 系统设置-角色管理
    - `GET /api/roles` -> `permissionCode=role.read`，`dataScopeType=TENANT`，`auditActionCode=ROLE_LIST`
    - `POST /api/roles/{id}/permissions` -> `permissionCode=role.permission.bind`，`dataScopeType=TENANT`，`auditActionCode=ROLE_BIND_PERMISSIONS`
  - 系统设置-数据权限
    - `POST /api/data-scope-policies/{id}/assign-roles` -> `permissionCode=data.permission.manage`，`dataScopeType=TENANT`，`auditActionCode=DATA_PERMISSION_ASSIGN_ROLES`
    - `POST /api/data-scope-policies/{id}/enable` -> `permissionCode=data.permission.manage`，`dataScopeType=TENANT`，`auditActionCode=DATA_PERMISSION_ENABLE`
  - 系统设置-通知策略
    - `POST /api/notification-policies/{id}/events` -> `permissionCode=notification.policy.manage`，`dataScopeType=TENANT`，`auditActionCode=NOTIFICATION_POLICY_BIND_EVENTS`
    - `POST /api/notification-policies/{id}/disable` -> `permissionCode=notification.policy.manage`，`dataScopeType=TENANT`，`auditActionCode=NOTIFICATION_POLICY_DISABLE`
  - 会议资料与总结
    - `POST /api/meetings/{id}/materials/export` -> `permissionCode=meeting.material.export`，`dataScopeType=MEETING`，`auditActionCode=MEETING_MATERIAL_EXPORT`
    - `GET /api/meetings/{id}/summary/download` -> `permissionCode=meeting.material.export`，`dataScopeType=MEETING`，`auditActionCode=MEETING_SUMMARY_DOWNLOAD`
  - 审核与流程
    - `POST /api/audits/tasks/{id}/approve` -> `permissionCode=audit.approve`，`dataScopeType=MEETING`，`auditActionCode=AUDIT_APPROVE`
    - `POST /api/audit-flows/{id}/default` -> `permissionCode=audit.flow.manage`，`dataScopeType=TENANT`，`auditActionCode=AUDIT_FLOW_SET_DEFAULT`
  - 财务与导出
    - `POST /api/finance/payments` -> `permissionCode=finance.payment.confirm`，`dataScopeType=PROJECT`，`auditActionCode=FINANCE_PAYMENT_CONFIRM`
    - `POST /api/finance/meeting-bills` -> `permissionCode=finance.reconciliation`，`dataScopeType=PROJECT`，`auditActionCode=FINANCE_MEETING_BILL_UPSERT`
    - `GET /api/audit-logs` -> `permissionCode=audit.log.read`，`dataScopeType=GLOBAL_READONLY`，`auditActionCode=AUDIT_LOG_LIST`
- 数据范围类型建议枚举
  - `TENANT`、`PROJECT`、`MEETING`、`MEETING_MODULE`、`GLOBAL_READONLY`。
- 测试与门禁
  - 后端单测必须覆盖：权限码缺失拒绝发布、数据范围校验拒绝越权、审计动作码入库完整。
  - 前端联调必须覆盖：无权限置灰提示、越权请求统一错误码回传、批量接口的部分失败处理。

---

## 8. 文件存储与媒体处理

### 8.1 文件上传
- 先传对象存储，后写业务记录。
- 支持分片上传与断点续传（大视频场景）。

### 8.2 文件校验
- 类型白名单、大小限制、病毒扫描、哈希去重。
- 文件命名规范校验，不合规可自动重命名。

### 8.3 文件访问控制
- 私有桶 + 预签名URL短时访问。
- 下载权限与项目/会议数据权限联动。

### 8.4 阿里云OSS目录与生命周期策略
- 路径规范
  - `/{tenantId}/{projectId}/{meetingId}/{module}/{yyyyMM}/{fileName}`
  - 模块建议：`basic`、`material`、`photo`、`labor`、`invoice`、`template`。
- 上传策略
  - 大文件分片上传，完成后回调写入业务表。
  - 文件名落库前进行规范化，保存原始名与存储名。
- 生命周期
  - 热数据：近12个月标准存储。
  - 冷归档：超期转低频或归档存储（按合规策略）。
  - 删除策略：业务删除先软删，物理删由定时任务延迟执行。
- 安全策略
  - Bucket 私有读，禁公网列举。
  - 预签名URL有效期建议 `5-15` 分钟。
  - 开启防盗链、跨域白名单和操作日志。

---

## 9. 安全与合规

### 9.1 数据安全
- 敏感字段（身份证号、银行卡号）加密存储。
- 前端脱敏展示，按角色控制明文可见性。
- 导出敏感数据需二次确认并留痕。

### 9.2 审计安全
- 高风险操作全量留痕：重置密码、角色变更、审核结论修改、支付确认、导出全量数据。
- 审计日志不可篡改（WORM策略或审计库隔离）。

### 9.3 访问安全
- 登录失败策略、验证码、人机校验、IP风控。
- 接口限流与防重放。

---

## 10. 异步任务与通知

### 10.0 实现方式（当前版本）
- 不引入消息队列。
- 使用 `Spring @Scheduled` 轮询任务表执行异步任务。
- 任务表建议：`async_job`（任务定义）与 `async_job_log`（执行日志）。

### 10.1 任务类型
- 超时催办任务。
- 审核状态变更通知任务。
- 模板过期停用任务。
- 导出报表任务。

### 10.2 通知渠道
- 站内信、邮件、微信（可扩展）。
- 通知模板变量统一由模板管理维护。
- 当前实现状态：已完成“通知策略配置中心 + 发送执行引擎”（通道适配、重试、回执入库）；真实供应商SDK对接待补齐。

### 10.3 失败重试
- 指数退避重试（最多3次）。
- 超过重试次数标记失败并告警，支持人工重试。

### 10.4 Scheduler分布式执行规范（无消息队列场景）
- 任务表字段建议
  - `job_id`、`job_type`、`payload`、`status`、`next_run_at`、`retry_count`、`max_retry`、`locked_by`、`locked_at`。
- 抢占与互斥
  - 使用 `Redis 分布式锁` 或 DB 乐观锁抢占任务，确保同一任务仅单实例执行。
  - 抢占条件：`status=READY and next_run_at<=now`。
- 超时回收
  - 执行超时任务由回收任务重置为 `READY` 或标记 `FAILED`。
  - `locked_at` 超过阈值（如 10 分钟）触发回收。
- 幂等保障
  - 任务执行前后校验幂等键，避免重复通知、重复导出、重复状态推进。
- 批处理控制
  - 单次拉取任务上限（如 100 条），避免长事务和任务饥饿。
- 默认参数（建议）
  - 轮询周期：`3000ms`
  - 单批拉取：`100` 条
  - 单任务超时：`120s`
  - 最大重试：`3` 次
  - 重试间隔：`30s`、`120s`、`300s`
  - 锁超时回收阈值：`600s`

---

## 11. 非功能性要求

### 11.1 性能指标（建议）
- 页面列表接口：P95 < 500ms。
- 审核动作接口：P95 < 300ms。
- 文件上传成功率：> 99.9%。

### 11.2 可用性
- 服务可用性目标：99.9%。
- 数据库主从 + 自动备份 + 灾备演练。
- MySQL 5.7 运行基线
  - 字符集：`utf8mb4`；排序规则：`utf8mb4_general_ci`（或按业务统一）。
  - 时区：数据库与应用统一 `Asia/Shanghai`。
  - `sql_mode` 固化到环境配置并在各环境保持一致。
  - 慢查询阈值、连接池、最大连接数需有统一基线值。

### 11.3 可观测性
- 指标：QPS、错误率、慢查询、任务堆积、任务失败率。
- 日志：结构化日志 + TraceId 全链路追踪。
- 告警：支付失败、审核超时、导出失败、存储异常。

### 11.4 SLO与告警阈值（建议）
- SLO目标
  - 核心API可用性：`>=99.9%`（月）。
  - 审核动作成功率：`>=99.95%`。
  - 支付确认成功率：`>=99.95%`。
- 告警阈值
  - API 5xx 错误率连续5分钟 > `1%` 触发P1告警。
  - 审核超时任务占比 > `3%` 触发P2告警。
  - 异步任务堆积 > `1000` 条或失败率 > `5%` 触发P1告警。
  - 导出任务平均耗时 > `60s` 连续10分钟触发P2告警。
- 恢复阈值
  - 连续10分钟恢复到阈值以下自动关闭告警。
- 当前实现状态
  - 已实现规则评估、触发、抑制窗口、事件恢复标记。
  - 已实现定时自动评估与连续恢复窗口判定（默认恢复窗口 10 分钟，可配置）。

---

## 12. 测试策略

### 12.1 测试层级
- 单元测试：状态机、金额计算、权限校验。
- 集成测试：审核流、支付流、通知流。
- E2E：项目->会议->审核->财务完整闭环。

### 12.2 重点用例
- 提交人与审核人互斥校验。
- 终审通过后关键字段变更回退。
- 超预算拦截与审批放行。
- 重复支付拦截。
- 模板版本回滚与下载权限校验。

---

## 13. 研发排期建议（可直接排期）

### 13.1 P0（核心上线）
- 多租户、RBAC、数据范围。
- 项目/会议/审核/财务四大主流程闭环。
- 审计日志与敏感字段合规。
- 文件上传下载与权限联动。

### 13.2 P1（高优先级增强）
- 模板版本治理、下载留痕。
- 专家去重合并、多卡治理、快照机制。
- SLA超时升级、批量催办、风险预警。
- 对账工单与锁账流程。

### 13.3 P2（效率优化）
- 报表中心与运营看板。
- 高级搜索与统计分析。
- 自动化策略（模板推荐、智能校验）。

### 13.4 发布与回滚策略（建议）
- 发布策略
  - 默认小步快跑，按模块灰度（先内部租户后全量）。
  - 生产发布窗口避开财务结算高峰时段。
- 数据库变更
  - DDL 采用向后兼容策略（先加字段再切流，再清理旧字段）。
  - 所有迁移脚本必须可回滚并在预发演练通过。
- 回滚策略
  - 应用回滚：保留最近2个稳定版本，异常5分钟内回退。
  - 数据回滚：通过备份+增量日志恢复，禁止直接手改线上数据。
- 灰度与自动回滚阈值
  - 灰度阶段 5xx 错误率连续5分钟 > `1%` 自动触发回滚。
  - 核心接口P95延迟连续10分钟劣化 > `30%` 触发人工确认回滚。
  - 关键业务失败率（审核通过/支付确认）连续10分钟 > `2%` 触发P1告警与回滚评估。
- 灾备目标
  - 建议 `RPO <= 15分钟`、`RTO <= 60分钟`。

---

## 14. 待确认项（立项前必须冻结）

- 部署方式（单体优先或微服务拆分）与服务拆分边界。
- 合规要求细则（数据留存期限、加密算法、审计保留周期）。
- 发票管理主数据口径（税号规则、唯一键、项目默认抬头覆盖规则）。
- 通知执行通道范围（是否纳入企业微信/短信）与失败回执标准。
- 导出任务中心口径（同步/异步分界、任务时限、下载安全策略）。
