diff --git a/client/README.md b/client/README.md index 6dccfb81..23092e26 100644 --- a/client/README.md +++ b/client/README.md @@ -34,6 +34,20 @@ npm run dev - 前端在 401 时自动调用 `/api/auth/refresh` 并重试一次请求。 - 登录与刷新请求都会附带 `x-device-fingerprint`。 +## 4.1 开发环境默认账号(seed:dev) +仅用于本地联调(`cd server && npm run seed:dev`): + +| 角色 | 账号 | 密码 | +|---|---|---| +| employee | `employee@hyinda.com` | `EmployeePassword1234` | +| manager | `manager@hyinda.com` | `ManagerPassword1234` | +| finance | `finance@hyinda.com` | `FinancePassword1234` | +| finance_mgr | `finance_mgr@hyinda.com` | `FinanceMgrPassword1234` | +| admin | `admin@hyinda.com` | `AdminPassword1234` | +| ceo | `ceo@hyinda.com` | `CeoPassword1234` | + +忘记密码:试运行/生产建议采用“管理员重置密码”策略。 + ## 5. 菜单与权限(当前壳层) - 仪表盘:登录即可访问。 - 我的报销:`expense.view_own` 或 `expense.view_all`。 diff --git a/client/src/api/errorMessages.ts b/client/src/api/errorMessages.ts index 4abdfd10..c678279d 100644 --- a/client/src/api/errorMessages.ts +++ b/client/src/api/errorMessages.ts @@ -7,6 +7,10 @@ export function mapApiErrorMessage( return "账号或密码错误,请检查后重试。"; } + if (code === "AUTH_003") { + return "账号已离职/禁用,请联系管理员。"; + } + if (code === "AUTH_004") { return "登录状态失效,请重新登录。"; } @@ -23,6 +27,10 @@ export function mapApiErrorMessage( return "目标数据不存在或已被删除。"; } + if (code === "SYS_001") { + return "服务暂不可用,请稍后重试或联系管理员。"; + } + if (code === "VALID_002") { return "输入内容长度不足,请补充后再提交。"; } @@ -59,4 +67,3 @@ export function mapApiErrorMessage( return fallbackMessage || "请求失败,请稍后重试。"; } - diff --git a/client/src/pages/LoginPage.tsx b/client/src/pages/LoginPage.tsx index 75b45ccd..4e072b2c 100644 --- a/client/src/pages/LoginPage.tsx +++ b/client/src/pages/LoginPage.tsx @@ -1,7 +1,12 @@ import { useState } from "react"; import { useNavigate, useSearchParams } from "react-router-dom"; +import { mapApiErrorMessage } from "../api/errorMessages"; import { isApiError } from "../api/types"; import { useAuth } from "../auth/AuthContext"; +import { Button } from "../components/ui/button"; +import { Card } from "../components/ui/card"; +import { Input } from "../components/ui/input"; +import { Label } from "../components/ui/label"; function resolveRedirect(searchParams: URLSearchParams) { const redirect = searchParams.get("redirect"); @@ -38,7 +43,9 @@ export function LoginPage() { navigate(redirectTo, { replace: true }); } catch (err) { if (isApiError(err)) { - setError(`${err.code}: ${err.message}`); + setError(`${err.code}: ${mapApiErrorMessage(err.code, err.details, err.message)}`); + } else if (err instanceof TypeError) { + setError("无法连接后端服务,请确认 server 已启动(http://127.0.0.1:3000)。"); } else { setError("登录失败,请稍后重试"); } @@ -48,49 +55,53 @@ export function LoginPage() { } return ( -
+

hyb-oa

登录工作台

使用邮箱/手机号与密码登录。

+

忘记密码:请联系管理员重置。

- +
- + {error ? ( -

+

{error}

) : null} - + - + ); } diff --git a/issues/2026-02-08_21-50-09-p4-trialrun-ready.csv b/issues/2026-02-08_21-50-09-p4-trialrun-ready.csv index 537bfa34..bb688abb 100644 --- a/issues/2026-02-08_21-50-09-p4-trialrun-ready.csv +++ b/issues/2026-02-08_21-50-09-p4-trialrun-ready.csv @@ -6,7 +6,7 @@ E4,待办页精修(列表详情动作),用UI primitives收敛待办列表与 E5,报销页精修(列表详情联动),收敛报销列表详情展示并优化支付凭证与票据区块一致性并补data-testid,employee可create submit withdraw且finance可pay并填写凭证字段,cd client && npm run typecheck && npm run build,manual,DONE,DONE,DONE,client/src/pages/ReimbursementsPage.tsx | client/src/pages/ReimbursementDetailPage.tsx | client/src/api/reimbursements.ts,"[""E3""]",为E2E补稳定选择器data-testid E6,票据中心精修(OCR与预览),收敛上传列表详情并强化OCR状态展示绑定与签名预览交互并补data-testid,OCR_PROVIDER=mock联调可轮询pending_ocr且ocr_failed展示原因且预览可用,cd client && npm run typecheck && npm run build,manual,DONE,DONE,DONE,client/src/pages/InvoicePoolPage.tsx | client/src/api/invoicePool.ts | client/src/api/http.ts,"[""E3""]",为E2E补稳定选择器data-testid E7,委派管理前端页(运营可用),新增委派管理页与API封装支持创建列表撤销并加菜单入口与守卫,可创建委派撤销后delegate不可代办且无权限用户403提示正确,"manual: manager创建委派让delegate代办一次后撤销再验证PERM_002",manual,DONE,TODO,TODO,client/src/pages/DelegationsPage.tsx | client/src/api/delegations.ts | client/src/router/index.tsx | client/src/components/navigation/Sidebar.tsx,"[""E3""]",权限码沿用expense.proxy_manage -E8,默认账号与失败体验收敛,补dev seed默认账号文档并让前端对网络失败给出可操作提示(含“忘记密码请联系管理员重置”),登录页后端不可达提示服务未启动且README列出默认账号且SYS_001提示可读,"manual: 停后端访问登录页看到提示并按README默认账号登录成功",manual,TODO,TODO,TODO,client/src/pages/LoginPage.tsx | client/src/api/errorMessages.ts | server/README.md | client/README.md,"[""E1""]",仅写dev seed账号不写生产密码与密钥 +E8,默认账号与失败体验收敛,补dev seed默认账号文档并让前端对网络失败给出可操作提示(含“忘记密码请联系管理员重置”),登录页后端不可达提示服务未启动且README列出默认账号且SYS_001提示可读,"manual: 停后端访问登录页看到提示并按README默认账号登录成功",manual,DONE,TODO,TODO,client/src/pages/LoginPage.tsx | client/src/api/errorMessages.ts | server/README.md | client/README.md,"[""E1""]",仅写dev seed账号不写生产密码与密钥 E9,DB索引补强(试运行性能),为列表分页与筛选补组合索引以降低试运行慢查询风险,迁移可重复执行且回归全绿,cd server && npm run prisma:migrate:deploy && ./scripts/regression-all.sh,manual,TODO,TODO,TODO,server/prisma/schema.prisma | server/prisma/migrations/*,"[""E1""]",新增组合索引仅增不破回滚成本低 E10,后端安全基线(上线级),增加安全头与关键接口限流并完善上传校验与日志脱敏约定,限流触发行为正确安全头存在上传非法类型被拒绝且不泄露token,"manual: curl压测login并验证429与headers并做一次上传非法类型校验",manual,TODO,TODO,TODO,server/src/app.js | server/src/config.js | server/src/routes/auth.js | server/src/routes/invoicePool.js | server/README.md | server/package.json,"[""E1""]",优先使用@fastify/helmet与@fastify/rate-limit并写回滚说明 E11,可观测性基线(ready与作业统计),新增/ready进行DB探活并为OCR与委派回收作业输出结构化统计,ready可反映db状态且作业日志输出claimed updated audited等计数便于排障,"manual: 启动服务curl /ready并触发一次job观察日志字段",manual,TODO,TODO,TODO,server/src/app.js | server/src/jobs/delegationRevokeJob.js | server/src/jobs/ocrJob.js | server/README.md,"[""E10""]",不引入外部监控先提供最小可观测字段 diff --git a/server/README.md b/server/README.md index 989d73cf..e40b5e27 100644 --- a/server/README.md +++ b/server/README.md @@ -31,6 +31,18 @@ cd /home/shunli/Projects/hyb-oa/server npm run seed:dev ``` +开发环境默认账号(仅用于本地 seed:dev): +- employee:`employee@hyinda.com` / `EmployeePassword1234` +- manager:`manager@hyinda.com` / `ManagerPassword1234` +- finance:`finance@hyinda.com` / `FinancePassword1234` +- finance_mgr:`finance_mgr@hyinda.com` / `FinanceMgrPassword1234` +- admin:`admin@hyinda.com` / `AdminPassword1234` +- ceo:`ceo@hyinda.com` / `CeoPassword1234` + +说明: +- 以上账号可通过 `SEED_*` 环境变量覆盖(见 `server/src/scripts/seed-dev.js`)。 +- 生产/试运行环境默认采用“管理员重置密码”,不建议启用默认弱口令。 + ### 2.4 启动服务 ```bash cd /home/shunli/Projects/hyb-oa/server