diff --git a/.trellis/tasks/05-29-frontend-simplification-audit-fixes/check.jsonl b/.trellis/tasks/05-29-frontend-simplification-audit-fixes/check.jsonl new file mode 100644 index 00000000..e4a2b5cd --- /dev/null +++ b/.trellis/tasks/05-29-frontend-simplification-audit-fixes/check.jsonl @@ -0,0 +1,4 @@ +{"file": ".trellis/spec/hyb-oa/frontend-react-vite-design.md", "reason": "核对前端页面修复是否符合降噪、低频能力后置和验证规则。"} +{"file": ".trellis/spec/hyb-oa/project-governance.md", "reason": "核对任务范围、单人开发验证门禁和提交治理。"} +{"file": ".trellis/spec/hyb-oa/reimbursement-invoice-ocr.md", "reason": "核对报销支付相关修复没有扩大业务边界。"} +{"file": ".trellis/tasks/05-29-frontend-simplification-audit-fixes/research/audit-context.md", "reason": "核对本任务审计发现和验收上下文。"} diff --git a/.trellis/tasks/05-29-frontend-simplification-audit-fixes/implement.jsonl b/.trellis/tasks/05-29-frontend-simplification-audit-fixes/implement.jsonl new file mode 100644 index 00000000..279aa792 --- /dev/null +++ b/.trellis/tasks/05-29-frontend-simplification-audit-fixes/implement.jsonl @@ -0,0 +1,4 @@ +{"file": ".trellis/spec/hyb-oa/frontend-react-vite-design.md", "reason": "前端 A 类页面任务优先、低频能力后置、自然中文和验证规则。"} +{"file": ".trellis/spec/hyb-oa/project-governance.md", "reason": "单人开发小批量、可验证、可回滚的项目治理规则。"} +{"file": ".trellis/spec/hyb-oa/reimbursement-invoice-ocr.md", "reason": "报销、付款和附件相关改动的边界规则。"} +{"file": ".trellis/tasks/05-29-frontend-simplification-audit-fixes/research/audit-context.md", "reason": "本任务审计发现和上一轮验证上下文。"} diff --git a/.trellis/tasks/05-29-frontend-simplification-audit-fixes/implement.md b/.trellis/tasks/05-29-frontend-simplification-audit-fixes/implement.md new file mode 100644 index 00000000..0b088bcd --- /dev/null +++ b/.trellis/tasks/05-29-frontend-simplification-audit-fixes/implement.md @@ -0,0 +1,18 @@ +# 实施说明 + +## Plan + +1. 将工作台系统管理摘要中的“审计日志”链接从 `/audit` 修正为现有路由 `/audit-logs`。 +2. 将报销支付表单默认付款日期从固定历史日期改为组件初始化当天日期。 +3. 将报销详情状态摘要值从“状态:xx”改为只显示状态值,避免和 label 重复。 +4. 在 `login-portal-ux.spec.ts` 补充聚焦断言,验证工作台系统摘要中的审计日志入口指向 `/audit-logs`。 +5. 核对差旅入口仍位于高级/低频位置,不把差旅恢复到默认主路径。 + +## Risk + +- 改动只涉及前端链接、默认表单值、展示文案和测试断言,不触碰后端 API、权限模型、审批状态机、数据库或真实业务数据。 +- Playwright 聚焦测试需要运行在包含本地新代码的前端服务上;如 `127.0.0.1:3000` 已有旧服务,应使用新端口并通过 `E2E_BASE_URL` 指定。 + +## Rollback + +- 回滚本任务 commit 即可恢复原页面行为。 diff --git a/.trellis/tasks/05-29-frontend-simplification-audit-fixes/prd.md b/.trellis/tasks/05-29-frontend-simplification-audit-fixes/prd.md new file mode 100644 index 00000000..fc55fdc8 --- /dev/null +++ b/.trellis/tasks/05-29-frontend-simplification-audit-fixes/prd.md @@ -0,0 +1,109 @@ +# 前端降噪审计修复 + +## Goal + +修复前端降噪审计中已确认的低风险问题,避免工作台坏链路、财务付款日期误填和详情页重复文案继续影响试运行体验;同时明确差旅入口仍只作为历史/低频能力处理,不恢复为当前主线。 + +## What I Already Know + +- 用户已认可前端降噪后的方向,并要求后续作为统一设计规则。 +- 用户确认产品面向国内、小于 10 人的科技初创公司,系统由单人长期开发维护。 +- 已完成两轮前端降噪:PC 工作台、报销列表、审批中心、报销详情。 +- 已完成部署复检,公网 live readiness、权限矩阵、PC 只读视觉、移动入口和企微渲染均已通过。 +- 只读审计发现: + - 工作台系统管理摘要里的“审计日志”指向 `/audit`,实际路由为 `/audit-logs`。 + - 报销财务支付表单默认付款日期硬编码为 `2026-02-08`。 + - 报销详情状态摘要出现“状态 / 状态:xxx”重复文案。 + - 差旅入口仍出现在高级/低频位置,需要保持不恢复主线的边界。 + +## Scope + +- 修复 PC 工作台系统管理摘要中的审计日志链接。 +- 修复 PC 报销详情财务支付面板的付款日期默认值。 +- 修复 PC 报销详情顶部状态摘要的重复文案。 +- 补充一个聚焦 Playwright 断言覆盖工作台审计日志入口。 +- 只读核对差旅入口边界,不恢复差旅主线能力。 + +## Assumptions + +- 本任务只修复审计发现,不继续扩大页面重构范围。 +- 不修改后端 API、数据库、权限模型、审批状态机、真实数据或企业微信配置。 +- 差旅不在本任务恢复为主线能力;仅确认现有入口是否应保留为高级/历史/权限场景。 +- 这次改动是小批量、可验证、可回滚的前端修复。 + +## Requirements + +- 工作台“审计日志”入口必须跳转到现有 `/audit-logs` 路由。 +- 付款日期不得继续硬编码历史日期;默认值应降低误填风险。 +- 报销详情顶部状态摘要不得重复展示“状态”两个标签。 +- 差旅入口不得重新进入高频主路径;如保留,必须位于高级、历史、权限或已有业务关联路径,不新增可见主入口。 +- 继续保持自然中文文案,不引入 `Portal`、`Dashboard`、`Workflow` 作为用户可见产品词。 + +## Acceptance Criteria + +- [x] 管理员从工作台系统管理摘要点击“审计日志”进入 `/audit-logs`。 +- [x] 报销支付表单默认付款日期不再是固定历史日期。 +- [x] 报销详情状态摘要只展示一次状态语义。 +- [x] 差旅不进入工作台、审批中心或报销列表的默认主路径。 +- [x] 前端 typecheck 和 build 通过。 +- [x] UI 设计规则检查和 Trellis governance 通过。 +- [x] 如改动面向用户可测试,部署与公网检查通过后再告知用户测试。 + +## Test Plan + +- `cd client && npm run typecheck` +- `cd client && npm run build` +- `cd client && E2E_BASE_URL=http://127.0.0.1: npx playwright test tests/e2e/login-portal-ux.spec.ts --grep "系统摘要审计日志" --workers=1 --reporter=list` +- `node scripts/qa/check-ui-design-rules.mjs` +- `node scripts/qa/check-trellis-governance.mjs` +- `git diff --check` + +## Definition Of Done + +- PRD 和实施方案得到用户批准。 +- 按 Trellis workflow 激活任务并读取前端规约。 +- 完成前端修复并保持改动范围小。 +- 运行必要验证命令: + - `cd client && npm run typecheck` + - `cd client && npm run build` + - `node scripts/qa/check-ui-design-rules.mjs` + - `node scripts/qa/check-trellis-governance.mjs` + - `git diff --check` +- 必要时补充聚焦 Playwright 或路由断言。 +- 提交中文 commit,commit message 引用本 Trellis task。 + +## Verification Results + +- PASS:`cd client && npm run typecheck` +- PASS:`cd client && npm run build` +- PASS:`cd client && E2E_BASE_URL=http://127.0.0.1:3017 npx playwright test tests/e2e/login-portal-ux.spec.ts --grep "系统摘要审计日志" --workers=1 --reporter=list` +- PASS:`node scripts/qa/check-ui-design-rules.mjs` +- PASS:`python3 ./.trellis/scripts/task.py validate 05-29-frontend-simplification-audit-fixes` +- PASS:`node scripts/qa/check-trellis-governance.mjs` +- PASS:`git diff --check` +- Note:首次聚焦 Playwright 未指定 `E2E_BASE_URL`,命中已有 `127.0.0.1:3000` 旧服务并失败;改用本轮新代码启动的 `127.0.0.1:3017` 后通过。 + +## Out Of Scope + +- 不做第三轮全站页面重构。 +- 不恢复差旅主线能力。 +- 不修改移动端/企业微信页面,除非共享代码受影响。 +- 不修改后端 API、数据库、权限、审批状态机或部署配置。 +- 不写真实业务数据,不执行真实付款,不写企业微信。 + +## Technical Notes + +- 相关审计文件: + - `client/src/pages/PortalHomePage.tsx` + - `client/src/router/index.tsx` + - `client/src/components/navigation/NavLinks.tsx` + - `client/src/pages/reimbursement-detail/ReimbursementActions.tsx` + - `client/src/pages/ReimbursementDetailPage.tsx` + - `client/src/pages/WorkflowTasksPage.tsx` + - `client/src/pages/ReimbursementsPage.tsx` +- 相关事实源: + - `docs/产品设计规则.md` + - `.trellis/spec/hyb-oa/frontend-react-vite-design.md` + - `.trellis/spec/hyb-oa/project-governance.md` +- 验证证据参考: + - `.trellis/tasks/archive/2026-05/05-29-frontend-simplification-wave2-deploy-verify/research/postdeploy-summary.md` diff --git a/.trellis/tasks/05-29-frontend-simplification-audit-fixes/research/audit-context.md b/.trellis/tasks/05-29-frontend-simplification-audit-fixes/research/audit-context.md new file mode 100644 index 00000000..555b8ade --- /dev/null +++ b/.trellis/tasks/05-29-frontend-simplification-audit-fixes/research/audit-context.md @@ -0,0 +1,15 @@ +# 审计上下文 + +## 来源 + +- 前端降噪只读审计确认的问题: + - PC 工作台系统管理摘要“审计日志”链接指向 `/audit`。 + - 报销支付表单默认付款日期为固定历史日期 `2026-02-08`。 + - 报销详情状态摘要出现“状态 / 状态:xxx”重复文案。 + - 差旅仍应保持低频/历史/权限路径,不恢复为当前主线。 +- 产品事实源要求 hyb-oa 面向国内、小于 10 人的科技初创公司,采用小团队中文工作台。 +- 前端规约要求 A 类页面任务优先、低频能力后置、自然中文,前端改动需执行 typecheck/build 和必要 Playwright/视觉验证。 + +## 验证参考 + +- 上一轮部署验证结论已记录在归档任务 `05-29-frontend-simplification-wave2-deploy-verify`,公网 live readiness、权限矩阵、PC 只读视觉、移动入口和企微渲染均已通过。 diff --git a/.trellis/tasks/05-29-frontend-simplification-audit-fixes/task.json b/.trellis/tasks/05-29-frontend-simplification-audit-fixes/task.json new file mode 100644 index 00000000..0d616341 --- /dev/null +++ b/.trellis/tasks/05-29-frontend-simplification-audit-fixes/task.json @@ -0,0 +1,31 @@ +{ + "id": "frontend-simplification-audit-fixes", + "name": "frontend-simplification-audit-fixes", + "title": "前端降噪审计修复", + "description": "修复前端降噪审计发现的工作台审计日志坏链路、报销支付日期默认值和报销详情重复状态文案。", + "status": "in_progress", + "dev_type": null, + "scope": "frontend", + "package": null, + "priority": "P2", + "creator": "shunli", + "assignee": "shunli", + "createdAt": "2026-05-29", + "completedAt": null, + "branch": null, + "base_branch": "main", + "worktree_path": null, + "commit": null, + "pr_url": null, + "subtasks": [], + "children": [], + "parent": null, + "relatedFiles": [ + "client/src/pages/PortalHomePage.tsx", + "client/src/pages/reimbursement-detail/ReimbursementActions.tsx", + "client/src/pages/ReimbursementDetailPage.tsx", + "client/tests/e2e/login-portal-ux.spec.ts" + ], + "notes": "", + "meta": {} +} diff --git a/client/src/pages/PortalHomePage.tsx b/client/src/pages/PortalHomePage.tsx index de406a72..caf0cd11 100644 --- a/client/src/pages/PortalHomePage.tsx +++ b/client/src/pages/PortalHomePage.tsx @@ -1077,7 +1077,7 @@ export function PortalHomePage() { roleCapabilities.canManageSystem ? { key: "system-audit", - href: "/audit", + href: "/audit-logs", label: "审计日志", value: "查看", note: "查询关键操作留痕。", diff --git a/client/src/pages/ReimbursementDetailPage.tsx b/client/src/pages/ReimbursementDetailPage.tsx index aa49a1ba..45220922 100644 --- a/client/src/pages/ReimbursementDetailPage.tsx +++ b/client/src/pages/ReimbursementDetailPage.tsx @@ -1176,7 +1176,7 @@ export function ReimbursementDetailPage() {
状态
-
状态:{reimbursementStatusLabel(detail.status)}
+
{reimbursementStatusLabel(detail.status)}
处理人
diff --git a/client/src/pages/reimbursement-detail/ReimbursementActions.tsx b/client/src/pages/reimbursement-detail/ReimbursementActions.tsx index 23cce09b..9e9a0ac3 100644 --- a/client/src/pages/reimbursement-detail/ReimbursementActions.tsx +++ b/client/src/pages/reimbursement-detail/ReimbursementActions.tsx @@ -6,6 +6,10 @@ import { Textarea } from "../../components/ui/textarea"; type PaymentChannel = "bank" | "alipay" | "wechat" | "cash" | "other"; +function todayDateString() { + return new Date().toISOString().slice(0, 10); +} + export type PayPayload = { paymentVoucherNo: string; paymentDate: string; @@ -46,7 +50,7 @@ export function ReimbursementActions({ }: ReimbursementActionsProps) { const [withdrawComment, setWithdrawComment] = useState("申请撤回并补充说明后重提"); const [paymentVoucherNo, setPaymentVoucherNo] = useState(""); - const [paymentDate, setPaymentDate] = useState("2026-02-08"); + const [paymentDate, setPaymentDate] = useState(todayDateString); const [paymentChannel, setPaymentChannel] = useState("bank"); const [paymentNote, setPaymentNote] = useState(""); const canShowSubmit = showSubmitAction && ["draft", "rejected"].includes(status); diff --git a/client/tests/e2e/login-portal-ux.spec.ts b/client/tests/e2e/login-portal-ux.spec.ts index 104e430d..9faa9774 100644 --- a/client/tests/e2e/login-portal-ux.spec.ts +++ b/client/tests/e2e/login-portal-ux.spec.ts @@ -660,6 +660,21 @@ test("Portal 域管理角色也进入经理视图", async ({ page }) => { await expect(page.locator('[aria-label="portal-card-team_presence"]')).toBeVisible(); }); +test("Portal 系统摘要审计日志入口指向实际路由", async ({ page }) => { + await mockPasswordLogin(page); + await mockNavigation(page, "manager"); + await mockPortalHome(page, "manager"); + await mockAttendanceToday(page); + await mockNotificationList(page); + await mockMe(page, ["admin"], "Admin"); + + await login(page, ADMIN); + + await page.locator("summary").filter({ hasText: "角色重点" }).click(); + await expect(page.getByRole("heading", { name: "系统管理" })).toBeVisible(); + await expect(page.getByRole("link", { name: /审计日志.*查看/ })).toHaveAttribute("href", "/audit-logs"); +}); + test("企微 WebView 下默认进入移动工作台", async ({ page }) => { await page.addInitScript(() => { Object.defineProperty(window.navigator, "userAgent", {