diff --git a/client/src/api/errorMessages.ts b/client/src/api/errorMessages.ts index 77917f53..e9682fae 100644 --- a/client/src/api/errorMessages.ts +++ b/client/src/api/errorMessages.ts @@ -8,6 +8,31 @@ function readStringList(value: unknown): string[] { .filter((item) => item.length > 0); } +const FEATURE_FLAG_DISABLED_MESSAGES: Record = { + portal_home_v1_disabled: "Portal 首页当前未启用,请联系管理员检查环境开关与功能开关配置。", + announcements_v1_disabled: "公告模块当前未启用,请联系管理员检查环境开关与功能开关配置。", + presence_board_v1_disabled: "团队状态模块当前未启用,请联系管理员检查环境开关与功能开关配置。", + weekly_report_v1_disabled: "周报模块当前未启用,请联系管理员检查环境开关与功能开关配置。", + employee_lifecycle_v1_disabled: "人员生命周期模块当前未启用,请联系管理员检查环境开关与功能开关配置。", + todo_board_v1_disabled: "待办模块当前未启用,请联系管理员检查环境开关与功能开关配置。", + project_domain_v1_disabled: "项目模块当前未启用,请联系管理员检查环境开关与功能开关配置。", + project_linking_v1_disabled: "项目关联功能当前未启用,请联系管理员检查环境开关与功能开关配置。", + project_communication_log_v1_disabled: "项目沟通回填当前未启用,请联系管理员检查环境开关与功能开关配置。", + project_closure_checklist_v1_disabled: "项目收口清单当前未启用,请联系管理员检查环境开关与功能开关配置。", + confidential_doc_refs_v1_disabled: "涉密资料引用当前未启用,请联系管理员检查环境开关与功能开关配置。", +}; + +function resolveFeatureFlagDisabledMessage(value: unknown): string | null { + if (typeof value !== "string" || !value.endsWith("_disabled")) { + return null; + } + + return ( + FEATURE_FLAG_DISABLED_MESSAGES[value] ?? + "当前功能未启用,请联系管理员检查环境开关与功能开关配置。" + ); +} + export function mapApiErrorMessage( code: string, details?: Record, @@ -90,6 +115,11 @@ export function mapApiErrorMessage( return `新密码不符合要求:${passwordErrors.join(";")}。`; } + const featureFlagMessage = resolveFeatureFlagDisabledMessage(details?.featureFlag); + if (featureFlagMessage) { + return featureFlagMessage; + } + if (details?.["x-device-fingerprint"] === "missing") { return "当前设备校验信息缺失,请刷新页面后重试。"; } diff --git a/deploy/trialrun/checklist.md b/deploy/trialrun/checklist.md index 4ed92b5e..a255c0c3 100644 --- a/deploy/trialrun/checklist.md +++ b/deploy/trialrun/checklist.md @@ -8,6 +8,8 @@ - [ ] 已在服务器创建 OA 目录(默认 `/opt/hyb-oa-trialrun`) - [ ] 已准备 `deploy/trialrun/.env`,并将 `APP_ORIGIN` 改为 OA 公网域名 - [ ] 已将 `COOKIE_SECURE` 设为 `true` +- [ ] 已确认 `deploy/trialrun/.env` 作为部署事实源,新增环境变量优先补到该文件 +- [ ] 已尽量使用无引号 env 值;历史带引号值当前兼容,但建议逐步清理 - [ ] 已将 OA Nginx 配置放到 `/etc/nginx/sites-available/hyb-oa` - [ ] 已上传 OA 域名证书到 `/etc/nginx/ssl//` - [ ] 已执行 `nginx -t && systemctl reload nginx` @@ -20,6 +22,7 @@ ## A. 发布前(Pre-flight) - [ ] 确认当前版本已打 tag:`git tag -a trialrun-YYYYMMDD-NN -m "trialrun release"` - [ ] 本地门禁:`./scripts/check-minimal.sh` +- [ ] 部署契约校验:`node deploy/trialrun/validate-env-contract.js` - [ ] 全量回归(建议):`cd server && RUN_AUDIT_REGRESSION=1 RUN_OCR_REGRESSION=1 ./scripts/regression-all.sh` - [ ] 备份(DB + 文件存储): - [ ] `set -a && source deploy/trialrun/.env && set +a` @@ -33,6 +36,8 @@ - [ ] `docker compose -f deploy/trialrun/docker-compose.yml --env-file deploy/trialrun/.env run --rm init` - [ ] 探活: - [ ] `curl -fsS http://127.0.0.1:3000/ready` +- [ ] Runtime smoke: + - [ ] `docker compose -f deploy/trialrun/docker-compose.yml --env-file deploy/trialrun/.env exec -T server node src/scripts/smoke-trialrun-runtime.js` - [ ] 登录验证(管理员账号): - [ ] 访问 `http://127.0.0.1:3000` - [ ] 登录成功,菜单权限正确 diff --git a/deploy/trialrun/runbook.md b/deploy/trialrun/runbook.md index da55994d..93484aea 100644 --- a/deploy/trialrun/runbook.md +++ b/deploy/trialrun/runbook.md @@ -29,6 +29,12 @@ cp deploy/trialrun/.env.example deploy/trialrun/.env - `JWT_SECRET` - `APP_ORIGIN`(建议与对外域名一致,例如 `https://oa.example.com`) +环境变量约束: +- `deploy/trialrun/.env` 现在是 trialrun 部署事实源,`server / worker / init` 统一通过 `env_file` 注入。 +- 推荐使用无引号值,例如 `COOKIE_SECURE=true`、`PORT=3000`。 +- 历史上已经写成带引号的 `.env` 当前仍兼容,但建议后续逐步改成无引号。 +- 正式部署前可先执行 `node deploy/trialrun/validate-env-contract.js` 做静态契约检查。 + 作业系统建议: - 试运行默认 `JOB_DRIVER=pgboss`(基于 Postgres 的队列调度,单机/多进程语义更稳) - 如需快速回滚作业调度:将 `JOB_DRIVER` 改回 `cron` @@ -41,6 +47,7 @@ cp deploy/trialrun/.env.example deploy/trialrun/.env ### 1.2 启动数据库与服务 ```bash cd /path/to/hyb-oa +node deploy/trialrun/validate-env-contract.js docker compose -f deploy/trialrun/docker-compose.yml --env-file deploy/trialrun/.env up -d db docker compose -f deploy/trialrun/docker-compose.yml --env-file deploy/trialrun/.env up -d --build server ``` @@ -77,8 +84,13 @@ docker compose -f deploy/trialrun/docker-compose.yml --env-file deploy/trialrun/ curl -fsS http://127.0.0.1:3000/health curl -fsS http://127.0.0.1:3000/ready curl -fsS http://127.0.0.1:3000/metrics | head +docker compose -f deploy/trialrun/docker-compose.yml --env-file deploy/trialrun/.env exec -T server node src/scripts/smoke-trialrun-runtime.js ``` +说明: +- `deploy/trialrun/deploy.sh` 现已自动执行 `validate-env-contract.js`、`/ready` 探活与 `smoke-trialrun-runtime.js`。 +- 若再出现“数据库开了但功能被环境硬关”的情况,部署会直接失败,不再等到手工点页面才发现。 + 浏览器访问: - `http://127.0.0.1:3000`(单域托管前端)