feat(server): 完成 P0+P1 后端能力(工作流、RBAC、付款归档)
P0 MVP: - 认证:login/refresh/logout/forgot/reset + tokenVersion - RBAC:角色到权限映射 + requirePermission - 发票池:upload/bind/signed-url + 判重(VALID_003/VALID_005) - 报销:create/view/submit + 单号生成 - 工作流:approve + department_manager 解析 P1 扩展: - 动作:reject/return/withdraw(含 comment) - transfer:任务转审 + 链路上限 3 - pay:approved -> paid + 发票归档 used_complete - 动态审批链:approval_rules 驱动 回归脚本: - smoke-test.sh / regression-dedup.sh / regression-workflow-actions.sh
这个提交包含在:
@@ -0,0 +1,66 @@
|
||||
# hyb-oa 技术栈与复用报告(定案)
|
||||
|
||||
**日期**:2026-02-05
|
||||
**适用范围**:OA 报销系统(Phase 1)
|
||||
|
||||
## 1. 定案结论(统一口径)
|
||||
| 层级 | 选型 |
|
||||
| :--- | :--- |
|
||||
| 前端(OA) | React + Vite + Tailwind |
|
||||
| 后端(OA API) | Fastify |
|
||||
| ORM | Prisma |
|
||||
| 数据库 | PostgreSQL |
|
||||
| 认证 | JWT(access + refresh rotation),refresh 以 httpOnly Cookie 传输 |
|
||||
| 权限 | RBAC(权限码) |
|
||||
| 审计 | `workflow_history`(流程)+ `audit_logs`(安全与关键变更) |
|
||||
| 部署 | Docker + Nginx(反向代理) |
|
||||
|
||||
## 2. 关键取舍(为什么这么选)
|
||||
|
||||
### 2.1 常驻 Node 服务场景:优先“稳定性/少踩坑”
|
||||
本项目目标是云服务器常驻 Node 服务 + 长期演进,因此选型优先级为:
|
||||
1) 工具链成熟度与可维护性
|
||||
2) 团队上手成本与踩坑风险
|
||||
3) 可观测性/审计/权限等生产配套
|
||||
4) 性能(在常驻服务场景下,冷启动优势不显著)
|
||||
|
||||
### 2.2 Prisma vs Drizzle(定案:Prisma)
|
||||
- Prisma:迁移范式统一、资料多、团队协作成本低;适合“新人不踩坑”
|
||||
- Drizzle:更轻、更 SQL 直观,但更依赖团队 SQL/事务/索引纪律;在本项目“稳定性优先”的定义下不作为默认
|
||||
|
||||
### 2.3 Fastify vs Hono(定案:Fastify)
|
||||
- Fastify 适合常驻服务:生态成熟、插件与生产实践丰富(鉴权、日志、schema 校验等)
|
||||
- Hono 更偏极简/Edge/Serverless 方向;并非本项目的默认最优解
|
||||
|
||||
### 2.4 为什么不使用 Supabase(本项目定案)
|
||||
本项目部署形态为“自建常驻 API + 自建权限/审计/工作流/文件存储”,Supabase 在此形态下会带来:
|
||||
- 额外的运维与概念复杂度(RLS、RPC、Storage、Auth 等)
|
||||
- 架构边界不清(哪些逻辑在 DB,哪些在服务层)
|
||||
因此 hyb-oa 选择“Fastify + Prisma + PostgreSQL”作为单一事实源。
|
||||
|
||||
## 3. 复用资产清单(来自 `shenzhou-business-suite`)
|
||||
> 原则:复用“成熟结构/约束/枚举/经验”,把改造集中在“Supabase 调用 → REST API 调用”。
|
||||
|
||||
| 资产 | 来源路径(参考) | 复用价值 | 备注/改造点 |
|
||||
| :--- | :--- | :---: | :--- |
|
||||
| 工作流引擎 4 表 + `approval_rules`/`approval_transfers`/`document_sequences` | `shenzhou-business-suite/supabase/schema/70_workflow/01_workflow_02_tables.sql` | ⭐⭐⭐⭐⭐ | 转 Prisma schema;工作流事务由 Fastify 服务层实现 |
|
||||
| 工作流配置/类型(assignee_rule 等) | `shenzhou-business-suite/src/types/workflow.ts` | ⭐⭐⭐⭐ | 作为工作流 JSON 配置与契约参考 |
|
||||
| 权限码体系 | `shenzhou-business-suite/src/types/permissions.ts` | ⭐⭐⭐⭐ | 复用命名与粒度;补 `expense.proxy_*` |
|
||||
| 报销表结构参考(forms/items/attachments) | `shenzhou-business-suite/supabase/schema/20_finance/06_reimbursement_01_tables.sql` | ⭐⭐⭐⭐ | 字段设计参考;hyb-oa 简化并补 `file_sha256` 等 |
|
||||
| 默认费用类型 seed(35 启用 + 3 legacy 禁用) | `shenzhou-business-suite/supabase/seed.sql` | ⭐⭐⭐⭐⭐ | hyb-oa 额外启用 `utilities/rent` 形成 37 启用 |
|
||||
| 存储安全基线(类型/大小/访问控制) | `shenzhou-business-suite/supabase/migrations/20260131175000_storage_security_baseline.sql` | ⭐⭐⭐⭐ | 思路迁移到“本地存储 + 签名 URL” |
|
||||
| UI 组件(shadcn/ui 风格) | `shenzhou-business-suite/src/components/ui/*` | ⭐⭐⭐⭐ | 实现阶段复制到 `hyb-oa/client/src/`(需统一路径与样式变量) |
|
||||
| 报销前端页面结构 | `shenzhou-business-suite/src/pages/finance/reimbursement/*` | ⭐⭐⭐ | 需移除 Supabase 调用,替换为 OA API |
|
||||
| 测试框架 | `shenzhou-business-suite/playwright.config.ts` + `vitest.config.ts` | ⭐⭐⭐ | 实现阶段迁移;补齐鉴权/工作流核心路径 |
|
||||
|
||||
## 4. 关键设计原则(写入规格书的那几条)
|
||||
- 状态 vs 节点分离:报销单 `status` 固定 7 状态;审批节点由 `workflow_tasks` 驱动
|
||||
- 配置驱动:`approval_rules`/`expense_types`/`document_sequences` 均可配置;P0 预置默认值即可生效
|
||||
- 审计分层:
|
||||
- `workflow_history`:流程动作与审批链路(权威)
|
||||
- `audit_logs`:登录/敏感字段/配置变更/判重例外等安全关键事件
|
||||
- 文件存储:P0 本地存储 + 签名 URL;P2 切换 MinIO/OSS(接口不变)
|
||||
|
||||
## 5. 与本仓库当前现状对齐(信息校验)
|
||||
- `server/package.json` 已包含:`fastify`、`@fastify/jwt`、`prisma/@prisma/client`、`zod`
|
||||
- `docker-compose.yml` 已提供 PostgreSQL 15(本地/开发用)
|
||||
在新工单中引用
屏蔽一个用户