- 技术栈:React 18 + TypeScript + Vite + Tailwind - API 层:ApiError + 401 自动刷新 + single-flight 重试 - 鉴权:内存 Access Token + Cookie Refresh + 启动 bootstrap - RBAC:权限映射 + RequireAuth/RequirePermission 路由守卫 - 布局:OA 工作台壳层 + 侧边栏 + 5 个占位页面 - 样式:复用 hyb-web 视觉 token(单向同步) - 文档:新增 client README,补充 server 联调说明
161 行
4.9 KiB
Markdown
161 行
4.9 KiB
Markdown
# hyb-oa Server Runbook (P0/P1)
|
||
|
||
## 1. 环境准备
|
||
- Node.js: `>=20`
|
||
- Docker + Docker Compose
|
||
- 本地工具:`curl`、`jq`
|
||
- 配置文件:从 `server/.env.example` 复制为 `server/.env` 并按需修改
|
||
|
||
```bash
|
||
cd /home/shunli/Projects/hyb-oa/server
|
||
cp .env.example .env
|
||
```
|
||
|
||
## 2. Gate 基线命令(必须顺序执行)
|
||
|
||
### 2.1 启动数据库
|
||
```bash
|
||
cd /home/shunli/Projects/hyb-oa
|
||
docker compose up -d db
|
||
```
|
||
|
||
### 2.2 应用迁移
|
||
```bash
|
||
cd /home/shunli/Projects/hyb-oa/server
|
||
npm run prisma:migrate:deploy
|
||
```
|
||
|
||
### 2.3 执行 seed(幂等)
|
||
```bash
|
||
cd /home/shunli/Projects/hyb-oa/server
|
||
npm run seed:dev
|
||
```
|
||
|
||
### 2.4 启动服务
|
||
```bash
|
||
cd /home/shunli/Projects/hyb-oa/server
|
||
npm run dev
|
||
```
|
||
|
||
### 2.5 冒烟验证
|
||
```bash
|
||
cd /home/shunli/Projects/hyb-oa/server
|
||
./scripts/smoke-test.sh
|
||
```
|
||
|
||
## 3. 1 分钟快速验证
|
||
```bash
|
||
cd /home/shunli/Projects/hyb-oa/server
|
||
./scripts/smoke-test.sh
|
||
```
|
||
|
||
---
|
||
|
||
## 4. 回归入口
|
||
|
||
### 4.1 脚本回归(推荐)
|
||
```bash
|
||
cd /home/shunli/Projects/hyb-oa/server
|
||
BASE_URL=http://127.0.0.1:3000 ./scripts/smoke-test.sh
|
||
```
|
||
|
||
### 4.2 判重专项回归(dedup)
|
||
```bash
|
||
cd /home/shunli/Projects/hyb-oa/server
|
||
DATABASE_URL='postgresql://hyboa_user:[email protected]:5432/hyb_oa?schema=public' \
|
||
BASE_URL=http://127.0.0.1:3000 ./scripts/regression-dedup.sh
|
||
```
|
||
|
||
### 4.3 工作流动作回归
|
||
```bash
|
||
cd /home/shunli/Projects/hyb-oa/server
|
||
./scripts/regression-workflow-actions.sh
|
||
```
|
||
|
||
覆盖场景:
|
||
- `reject`:实例=`rejected`,报销=`rejected`
|
||
- `return`:实例=`terminated`,报销=`draft`
|
||
- `withdraw`:审批未处理前可撤回
|
||
- `return` 后二次 `submit`:创建新实例
|
||
- `PERM_002`:非 assignee 无法操作
|
||
- `no_actionable_approver`:全链无可执行审批人阻断
|
||
- `negative_not_allowed`:负金额防御
|
||
- `manager skip`:直属上级缺失时跳过并记录
|
||
- `transfer`:转审成功(任务改派 + 任务/转审记录/history 三处证据)
|
||
- `transfer` 参数校验:reason<10 返回 `VALID_002`
|
||
- `transfer` 同人转审:返回 `VALID_001`(`same_assignee_not_allowed`)
|
||
- `transfer` 链路上限:同 task 第 4 次转审阻断(`chain_limit_exceeded`)
|
||
- `transfer` 目标校验:目标审批人须 active 且具备 `expense.approve`
|
||
- `pay`:财务付款成功(`approved -> paid`,发票 `bound -> archived(used_complete)`)
|
||
- `pay` 权限:非财务返回 `PERM_001`
|
||
- `pay` 状态校验:非 `approved/paid` 返回 `VALID_001`
|
||
- `pay` 幂等:重复付款返回 200(`archivedInvoiceCount` 可为 0)
|
||
|
||
### 4.4 一键全量回归
|
||
```bash
|
||
cd /home/shunli/Projects/hyb-oa/server
|
||
./scripts/regression-all.sh
|
||
```
|
||
|
||
串联 `smoke-test.sh + regression-dedup.sh + regression-workflow-actions.sh`,适用于 CI 或发版前检查。
|
||
|
||
### 4.5 Postman 回归
|
||
- Collection: `server/postman/hyb-oa.postman_collection.json`
|
||
- Environment: `server/postman/hyb-oa.postman_environment.json`
|
||
- 核心链路:
|
||
1. Login Employee
|
||
2. Create Reimbursement
|
||
3. Upload Invoice
|
||
4. Bind Invoice
|
||
5. Submit Reimbursement
|
||
6. Login CEO
|
||
7. Approve Workflow Task
|
||
8. Get Signed URL
|
||
|
||
### 4.6 前端壳联调(P1-5)
|
||
```bash
|
||
cd /home/shunli/Projects/hyb-oa/client
|
||
npm install
|
||
npm run dev
|
||
```
|
||
|
||
说明:
|
||
- 前端开发地址默认 `http://127.0.0.1:5173`。
|
||
- 通过 Vite 代理将 `/api` 转发到 `http://127.0.0.1:3000`。
|
||
- Access Token 仅保存在内存,Refresh Token 通过 HttpOnly Cookie 续签。
|
||
|
||
---
|
||
|
||
## 5. 关键环境变量
|
||
- `DATABASE_URL`: PostgreSQL 连接串
|
||
- `JWT_SECRET`: JWT & signed-url token 签名密钥
|
||
- `APP_TIMEZONE`: 默认 `Asia/Shanghai`
|
||
- `STORAGE_DIR`: 默认 `generated/storage`(相对 `server/`)
|
||
- `SIGNED_URL_TTL_SECONDS`: 默认 `600`
|
||
- `MAX_UPLOAD_SIZE_BYTES`: 默认 `10485760`(10MB)
|
||
|
||
> 生产提示:大表加索引需评估 `CREATE INDEX CONCURRENTLY`,避免锁表影响。
|
||
|
||
---
|
||
|
||
## 6. 常见失败排查
|
||
|
||
| 现象 | 可能原因 | 解决方案 |
|
||
|---|---|---|
|
||
| `prisma migrate deploy` 失败 | `DATABASE_URL` 未配置/不可达 | 检查 `server/.env` 与数据库容器状态 |
|
||
| `npm run seed:dev` 重复执行报错 | seed 脚本被改坏,未保持幂等 | 检查 `seed-config.js`/`seed-dev.js` 的 `upsert` / `skipDuplicates` |
|
||
| signed-url 接口返回 403 | `JWT_SECRET` 不一致、token 过期、访问人无权限 | 统一服务密钥、确认 URL 在 TTL 内、检查账号角色 |
|
||
| 上传返回 `file_too_large` | 文件超 `MAX_UPLOAD_SIZE_BYTES` | 调整环境变量或使用更小文件 |
|
||
| 上传失败且报目录/权限错误 | `STORAGE_DIR` 不存在或不可写 | 创建目录并修正权限;Docker 需确认 volume 挂载 |
|
||
|
||
---
|
||
|
||
## 7. 手工故障注入(非阻塞)
|
||
|
||
### 7.1 `STORAGE_DIR` 不可写路径
|
||
- 临时将 `STORAGE_DIR` 指向只读目录,执行上传接口,确认错误可观测(日志+返回码)。
|
||
|
||
### 7.2 磁盘空间不足(ENOSPC)
|
||
- 在受控环境中制造磁盘满条件后重试上传。
|
||
- 预期:错误路径可观测(日志中能定位到 I/O 错误),不要求纳入日常 CI 冒烟。
|