feat(management-navigation-single-company-ux): 收敛管理导航与单公司配置体验

这个提交包含在:
2026-08-03 12:43:00 +08:00
父节点 f4ddc18f12
当前提交 4b0184c64b
共修改 36 个文件,包含 1249 行新增和 178 行删除
@@ -2107,3 +2107,82 @@ const actions = collectVisibleActions();
expect(actions.map(({ key, label }) => ({ key, label }))).toEqual(EXPECTED_ACTIONS);
for (const action of actions) expect(action.height).toBeGreaterThanOrEqual(44);
```
## Scenario: Management Route Metadata And Permission Disclosure
### 1. Scope / Trigger
- Trigger: adding or changing a PC management landing item, management subpage,
nested management detail, breadcrumb, sidebar ownership or recent-visit title.
### 2. Signatures
- Registry: `client/src/features/navigation/managementRoutes.ts`.
- Resolver inputs: `pathname: string` plus the current `permissions: string[]`.
- Router permissions: `getManagementRoutePermissions(key)`.
- Recent visits: `writeRecentVisit(path, title, permissions)` and
`readRecentVisits(permissions)`.
### 3. Contracts
- The management landing cards, root-navigation permission union, sidebar
active state, Topbar title/breadcrumb and recent-visit filtering derive from
the same registry entry.
- React Router keeps explicit component declarations and consumes the same
registry permissions. Server authorization remains the hard access boundary;
navigation metadata only enforces least disclosure.
- Match the most specific route deliberately. A nested employee profile must
resolve after its exact siblings and must not inherit a broader prefix by
accident.
- A user without the registered permission receives no restricted title,
breadcrumb or recent-visit link. Revoked permissions also clean stale local
recent-visit records.
- The sidebar keeps one `管理` root entry. Do not spread low-frequency child
pages back into the primary navigation.
### 4. Validation & Error Matrix
- Registered route + allowed permission -> natural Chinese title, parent chain
and management sidebar active state.
- Registered route + denied permission -> no restricted metadata; Router and
server guards still reject access.
- Unknown registry key passed to the Router helper -> throw during development
instead of silently using an empty permission list.
- Newly declared application route missing from the route manifest -> local
candidate route gate fails.
### 5. Good/Base/Bad Cases
- Good: `/people/:employeeId` uses the registry for both
`管理 / 人员 / 员工档案` and its `system.users` Router guard.
- Base: `/system/settings` displays only `管理`, with no self-referencing
breadcrumb.
- Bad: add a path to `SystemSettingsPage`, `NavLinks`, `PAGE_TITLES` and Router
as four hand-maintained facts.
### 6. Tests Required
- Registry contract covers unique keys, expected path inventory, parents,
permissions, landing metadata and root permission derivation.
- Permission-negative coverage asserts no title/breadcrumb disclosure and
filters a previously stored recent visit after permission revocation.
- Focused Playwright covers direct management deep links, sidebar active state,
nested breadcrumbs and the management-root return link.
- Run `cd client && npm run typecheck && npm run build` and
`bash scripts/qa/run-local-candidate.sh list`.
### 7. Wrong vs Correct
#### Wrong
```tsx
const MANAGEMENT_ACTIVE_PATHS = ["/people", "/system/users"];
<RequirePermission anyOf={["system.users"]}>...</RequirePermission>
```
#### Correct
```tsx
isManagementPath(pathname, permissions);
<RequirePermission anyOf={getManagementRoutePermissions("people")}>...</RequirePermission>
```
@@ -0,0 +1 @@
{"_example": "Fill with {\"file\": \"<path>\", \"reason\": \"<why>\"}. Put spec/research files only — no code paths. Run `python3 .trellis/scripts/get_context.py --mode packages` to list available specs. Delete this line once real entries are added."}
@@ -0,0 +1,96 @@
# 管理导航闭环与单公司体验收敛设计
## 1. 设计边界
本任务修复管理信息架构的单一事实源和单公司配置体验,不把管理区改造成产品化后台。侧栏继续只有一个「管理」入口;管理首页继续承担低频配置入口聚合。统一层只提供路由元数据、父子关系和导航表达,不接管 React Router 组件装配或服务端权限校验。
## 2. 管理路由注册表
在 `client/src/features/navigation/` 建立共享管理路由注册表。每项建议包含:
- `key`:稳定标识。
- `path`:可导航地址;详情项可只提供 matcher 和父级。
- `match`:exact/prefix 或显式匹配规则,避免 `/people` 与 `/people/:id` 标题混淆。
- `title`:Topbar、面包屑和最近访问使用的自然中文。
- `parentKey`:父级管理项;顶层配置页父级固定为 management root。
- `group`、`icon`、`description`、`anyOf`:管理首页卡片的分组、展示和权限合同。
- `showOnLanding`:详情层级不在聚合页重复显示。
共享解析函数:
- `resolveManagementRoute(pathname, permissions)`:只返回当前有权识别的最具体匹配项。
- `resolveManagementBreadcrumbs(pathname, permissions)`:在当前权限范围内沿 `parentKey` 生成可点击路径。
- `isManagementPath(pathname, permissions)`:供侧栏选中判断,避免无权路径激活管理导航。
- `getVisibleManagementItems(permissions)`:供管理首页渲染。
管理根入口的 `anyOf` 从所有可见管理子项权限求并集派生,避免 `NavLinks.tsx` 再维护一份权限列表。页面可见性仍以现有 Router 权限守卫和服务端权限校验为硬边界;注册表权限负责导航信息最小披露,不能替代访问控制。
`features/navigation/schema.ts` 先调用管理解析器,再回退到现有业务页面元数据;`NavLinks.tsx` 删除 `MANAGEMENT_ACTIVE_PATHS`;`SystemSettingsPage.tsx` 删除本地 `ITEMS`。
## 3. Topbar 面包屑
Topbar 已是所有 PC 页面稳定存在的壳层,比逐页增加返回按钮更可靠。管理路径命中时,把当前“标题 + 管理分组胶囊”表达为紧凑面包屑:
```text
管理 / 企业银行账户
管理 / 人员 / 员工档案
```
- 非当前节点使用 `Link`;当前节点使用文本并带 `aria-current="page"`。
- 管理首页仍显示普通标题「管理」。
- 非管理业务页面保持现有 Topbar,不在本任务推广全系统面包屑。
- 页面内部 `PageHeader` / `WorkspaceHeader` 不重复增加返回按钮,避免一页两套层级。
- Topbar 从 `useAuth()` 取得当前权限后解析管理元数据;无权命中时不渲染受限标题或父链,避免权限守卫跳转前的短暂信息泄露。
## 4. 路由覆盖门禁
管理首页注册表是可见入口事实源,React Router 仍显式声明页面。测试用显式允许的管理路由清单核对:
1. 每个 landing item 都能被 resolver 精确识别。
2. 每个已注册详情路径返回正确父链。
3. 所有管理页面标题均为自然中文。
4. `SystemSettingsPage` 和 `NavLinks` 不再出现第二份管理路径数组。
5. `/system/payment-accounts` 明确回归侧栏 active。
6. 同一路径在权限具备/缺失时分别验证可见元数据与不披露行为。
不在运行时解析 Router JSX,也不引入通用动态路由框架。
## 5. 最近访问权限收口
当前 `AppShellLayout` 会把路径和 `resolvePageMeta()` 标题写入 localStorage,但仓库中尚无读取最近访问的 UI。共享注册表接入后:
- 写入管理路径前按当前权限解析;无权路径不写入受限标题。
- 提供按当前权限过滤的读取函数,未来消费者只能读取过滤后的结果,不能直接展示 localStorage 原值。
- 权限被撤销后,过滤结果立即隐藏受限标题和链接;可同步清理失效记录,避免旧数据长期残留。
- 不把最近访问改成服务端存储,也不在本任务新增入口或页面。
## 6. 单公司 UI
后端模型保持不变。前端把 `LegalEntity` 解释为当前公司资料:
- 0 条 active:显示「完善公司信息」初始化区。
- 1 条 active:显示公司摘要和现有维护能力,隐藏多公司选择语义。
- 多条 active:显示异常提示,不猜测默认公司,不自动清理。
企业银行账户页面复用同一查询:
- 0 条:只显示空状态和去公司信息的链接。
- 1 条:内部自动使用其 ID,页面只读展示名称。
- 多条:禁用保存并提示异常。
暂不改变服务端 `legalEntityId` 请求字段,以保持 API、审计、付款快照和历史数据兼容。
## 7. 文档口径
`docs/产品口径.md` 当前编号到 R-5,因此新增 R-6,而不是留下缺号直接写 R-7。内容固化:单公司、内部 OA、非 SaaS、无公司切换;保留内部关系模型不等于对用户暴露多公司能力。
## 8. 兼容与回滚
- 无数据库迁移,无生产数据写入。
- 回滚只需恢复前端注册表消费者和旧文案;API/数据不受影响。
- 异常多公司场景保持 fail-closed,不会因前端自动选择错误公司影响付款账户。
- 生产公司信息、付款账户和员工银行机构已通过既有路径完成配置;本任务只修复后续管理体验,不回读、不迁移也不改写这些真实资料。
## 9. 视觉与技能边界
项目要求页面视觉与交互以 `frontend-design` skill 裁决,但当前会话未提供该 skill。实施前若仍不可用,沿用现有 Topbar、Link、空状态、表单和管理卡片组件,不新增视觉体系;任何明显视觉重排需再次说明该限制。
@@ -0,0 +1 @@
{"_example": "Fill with {\"file\": \"<path>\", \"reason\": \"<why>\"}. Put spec/research files only — no code paths. Run `python3 .trellis/scripts/get_context.py --mode packages` to list available specs. Delete this line once real entries are added."}
@@ -0,0 +1,64 @@
# 管理导航闭环与单公司体验收敛实施计划
## 1. 实施前门禁
- [x] 用户审查并明确批准 PRD、设计和本实施计划后,才运行 `task.py start`。
- [x] 运行 `trellis-before-dev`,读取 frontend、hyb-oa、项目治理和产品体验相关规约。
- [x] 实施前再次检查 `frontend-design` skill 是否可用;不可用时只复用现有视觉组件,不自行发明新样式。
- [x] 保护当前生产公司/银行资料;不连接生产、不写真实数据、不执行部署。
## 2. 共享管理路由
- [x] 建立管理路由注册表和最具体路径解析、父链、权限过滤函数。
- [x] 迁移 `SystemSettingsPage` 的入口列表到共享注册表。
- [x] 迁移 `NavLinks` 的管理选中判断并删除 `MANAGEMENT_ACTIVE_PATHS`。
- [x] 让 `resolvePageMeta` 从共享注册表解析管理标题,补齐当前遗漏页面和人员档案详情。
- [x] 让管理根入口权限从注册表派生,并让 resolver、面包屑和侧栏 active 接收当前权限;无权路径不披露受限元数据。
- [x] 收口最近访问写入/读取:写入前校验当前权限,读取时按当前权限过滤并覆盖权限撤销场景。
- [x] 增加注册表完整性、重复 key/path、父级循环、自然中文标题和权限字段测试。
## 3. Topbar 管理面包屑
- [x] 在 Topbar 命中管理子页时渲染 `管理 / 当前页`,管理首页不自指。
- [x] 覆盖 `管理 / 人员 / 员工档案` 等二级父链、可点击链接和 `aria-current`。
- [x] 验证直接深链、刷新、浏览器前进后退和窄屏换行,不依赖 location state。
- [x] 保持非管理页面 Topbar 行为与最近访问记录兼容。
## 4. 单公司体验
- [x] 把主数据中的「法体」用户文案改为「公司信息」,保留 API/类型/数据库命名。
- [x] 0/1/多条 active 公司信息分别渲染初始化、单公司维护和异常提示。
- [x] 企业银行账户页在 0 条时提供公司信息入口,1 条时自动关联并只读显示,多条时阻断保存。
- [x] 保持付款账户权限、完整账号输入、替换/停用、审计和通知调用不变。
## 5. 测试与检查
- [x] 增加共享 resolver、管理 landing、侧栏 active、Topbar breadcrumb 的聚焦测试。
- [x] 增加无权深链不显示受限面包屑,以及权限撤销后最近访问不返回旧标题/链接的测试。
- [x] 增加企业银行账户 0/1/多公司状态测试,断言无真实账号或 payload 进入证据。
- [x] 运行 `cd client && npm run typecheck && npm run build`。
- [x] 运行受影响前端测试及必要 Playwright 合成路径;不使用生产账号或真实银行资料。
- [x] 运行 `git diff --check`、敏感内容、Trellis governance、process/docs 门禁。
## 6. 文档、审查与提交
- [x] 在 `docs/产品口径.md` 以 R-6 固化单公司内部 OA 边界。
- [x] 若路由注册表形成稳定通用合同,用 `trellis-update-spec` 更新现有 frontend spec;不新建无必要文档。
- [x] 只读复核路由覆盖、权限可见性、面包屑父链和 0/1/多公司 fail-closed 行为。
- [x] 中文提交并引用 `management-navigation-single-company-ux`;不自动部署。
- [ ] 另行批准生产部署后运行公网检查,只有通过后才通知用户线上验收。
## 7. 回滚点
- 共享路由迁移必须先有 resolver 测试,再删除旧数组;任一入口丢失时恢复消费者,不修改服务端。
- 单公司 UI 只改变展示与默认选择;若异常场景处理不符合预期,回滚前端即可,`LegalEntity` 和付款账户数据不变。
## 8. 本地实施与验证记录
- 共享注册表已驱动管理首页、管理根权限、Router 权限、侧栏 active、Topbar 标题/面包屑和最近访问过滤。
- 只读复核发现并修正 `/people/:employeeId` 缺少显式前端权限守卫的问题;服务端权限边界未改。
- 企业银行账户页已覆盖零个、一个和异常多个启用公司状态;异常状态 fail-closed。
- 聚焦 Playwright:8/8 通过;此前完整 PC 财务/管理回归:9/9 通过。
- `npm run typecheck`、`npm run build`、路由清单门禁、Trellis validate/governance、process contract、docs audit、敏感内容和 `git diff --check` 均通过;docs audit 保留既有 22 个未登记文档警告,无错误。
- 路由清单顺带补齐既有 `/mobile/payment-batches` 分类缺口,仅登记现有路由和现有测试,不改变产品行为。
- 未部署、未连接生产、未写入真实公司或银行资料。
@@ -0,0 +1,118 @@
# 管理导航闭环与单公司体验收敛
## Goal
让管理人员从「管理」进入任一配置页后始终知道当前位置并能一键返回管理首页,同时把管理入口、侧栏归属和页面标题收敛到同一份路由事实源;在此基础上按“单公司、内部 OA、非产品化”边界简化公司信息和企业银行账户配置,不让用户面对无业务价值的多公司选择。
## Background
- 侧栏管理分组只有一个顶层入口:`client/src/features/navigation/schema.ts` 的 `ADMIN_NAV_ORDER` 仅包含 `/system/settings`。这符合“管理聚合入口”的产品方向,本任务不把每个配置页重新铺回侧栏。
- 子页归属目前是重复且不完整的手工事实:`SystemSettingsPage.tsx` 维护管理首页入口;`NavLinks.tsx` 维护独立的 `MANAGEMENT_ACTIVE_PATHS`;`features/navigation/schema.ts` 的 `PAGE_TITLES` 又维护 Topbar 标题。三者已经漂移。
- `/system/payment-accounts` 未加入 `MANAGEMENT_ACTIVE_PATHS`,因此当前页面不保持侧栏「管理」高亮。`PAGE_TITLES` 还缺少用户、部门、费用标准、报销模板、主数据、企业银行账户和通知渠道等多个管理页,缺失时可能回退为原始路径。
- 管理子页没有统一父级面包屑。用户从聚合页进入配置页后,只能自行重新寻找侧栏「管理」,深链或刷新后更缺少上下文。
- 本任务规划期间,生产曾因没有 `LegalEntity` 数据而使企业银行账户页面出现无选项的法人主体下拉框;管理员现已通过既有路径完成公司信息、付款账户和员工银行机构配置。该业务阻塞已经解除,但零公司状态仍需修复,避免以后初始化或测试环境再次走入死路。
- 本系统只服务当前公司内部、小于 10 人团队,不作为产品发布,不支持多公司、多租户或公司切换。`LegalEntity` 仍作为付款账户、成本中心等数据的内部关联锚点保留,不因前端简化而重做数据库模型。
- `docs/产品口径.md` 的权限口径目前编号到 R-5;单公司长期边界应作为下一条 R-6 固化,避免制造缺号的 R-7。
## Priority
1. 高:管理导航闭环与共享路由事实源,覆盖每次管理页面访问。
2. 中:企业银行账户空状态与唯一公司自动关联,避免配置死路。
3. 低:公司信息单例化表达和「法体」自然中文改名;不阻塞当前一次性生产录入。
## Scope
- 前端管理路由元数据、管理聚合页入口、PC 侧栏选中状态、Topbar 标题/面包屑和最近访问标题。
- 主数据中的公司信息单例表达,以及企业银行账户页面在零个、一个或异常多个启用公司时的交互。
- 与上述行为直接相关的前端类型、单元/组件测试和现有产品口径文档。
- 不修改后端数据模型、权限、银行资料加密/审计、制单逻辑或生产数据;不包含付款详情结构统一。
## Requirements
### R1 管理路由单一事实源
- 新建一份前端管理路由注册表,至少包含稳定 key、路径匹配规则、标题、父级、管理首页分组、图标、说明和权限要求。
- 「管理」聚合页入口、侧栏「管理」选中判断、Topbar 页面标题/分组和管理面包屑必须从该注册表派生,不再分别维护 `ITEMS`、`MANAGEMENT_ACTIVE_PATHS` 和不完整的管理 `PAGE_TITLES`。
- 注册表中的权限条件是路由元数据合同的一部分;管理根入口的权限集合从可见子项派生,不再在 `NavLinks.tsx` 单独维护另一份 `anyOf`。
- React Router 的页面组件与权限边界继续在 `router/index.tsx` 显式声明;本任务不为追求配置化而把懒加载组件塞进产品元数据。
- 注册表必须覆盖当前管理首页全部入口及必要详情层级,包括人员档案;新增管理页如果未登记,测试必须失败,而不是回退为原始路径后静默上线。
### R2 管理导航闭环
- PC 管理首页仍只占一个侧栏入口,不把低频配置页铺回主导航。
- 任一管理子页的 Topbar 显示可点击父级路径,例如 `管理 / 企业银行账户`;点击「管理」固定回到 `/system/settings`,不依赖浏览器历史。
- 人员档案等二级页面显示 `管理 / 人员 / 员工档案`;中间「人员」可返回人员列表。
- 直接访问深链、刷新页面或从全局搜索进入时,面包屑和侧栏高亮仍正确。
- 管理标题和父链解析必须接收当前用户权限;无权访问某个管理页时不得通过 Topbar 面包屑、父链或管理入口泄露该页面名称。
- 管理首页本身只显示当前页标题,不显示自指的「返回管理」。
### R3 页面标题与侧栏状态
- `/system/payment-accounts` 及所有已登记管理子页均保持侧栏「管理」选中。
- Topbar 不得把管理子页显示为原始 URL;管理页标题和分组必须与聚合页卡片一致。
- 最近访问记录只写入当前有权访问的管理路由,并继续使用自然中文标题,不因注册表重构写入原始路径。
- 读取最近访问时必须按当前权限重新过滤;用户权限被收回后,旧记录不得继续显示受限管理页面标题或链接。当前实现只有 localStorage 写入、尚无读取 UI,本任务修正写入/读取合同但不新建最近访问页面。
### R4 单公司长期边界
- 在 `docs/产品口径.md` 增加下一条可用编号 R-6:系统只服务当前公司内部,不做多公司、多租户、公司切换或面向外部客户的产品化配置。
- 不新增 tenant/company switcher、跨公司权限、公司维度工作区或多公司初始化流程。
- 保留 `LegalEntity` 表和现有关联作为内部账务/主数据锚点;本任务不重命名数据库表、不迁移外键、不删除历史能力。
- 前端用户文案把「法体」统一改为「公司信息」或「公司」,不向普通管理员暴露会计/产品化术语。
### R5 公司信息单例表达
- 公司信息为空时,主数据页显示一次性初始化表单和明确说明。
- 正常存在一条启用公司信息时,以单公司查看/维护方式展示,不提供公司切换器或鼓励继续创建第二家公司。
- 若历史或测试环境异常存在多条启用记录,不静默选择,不自动合并或删除;显示管理员可理解的异常提示,并保留现有数据供单独治理。
- 当前生产通过既有「主数据 → 法体」录入不被本任务阻塞;本任务不执行任何生产公司资料写入。
### R6 企业银行账户配置不走死路
- 没有公司信息时,不显示无解释的空法人主体下拉框;显示「请先完善公司信息」和可点击入口。
- 恰有一条启用公司信息时自动关联并只读显示公司名称,不要求用户重复选择。
- 异常存在多条启用公司信息时禁止猜测默认值,明确提示先处理公司信息。
- 公司银行账户、员工银行资料、权限、加密、审计和通知合同保持不变;本任务不读取、回填或迁移真实完整账号。
### R7 范围与设备
- 本任务服务 PC 管理配置体验;按照现有产品规则,不新建复杂移动端管理台。
- 窄屏通过现有 Topbar 菜单和可换行面包屑保持可用,但不新增移动专属公司/银行配置页面。
- 付款详情结构统一、处理进度时间线、粘性操作区和银行制单业务逻辑不纳入本任务。
## Acceptance Criteria
- [x] 管理首页全部可见入口、侧栏归属、Topbar 标题和面包屑来自同一管理路由注册表;不存在第二份手工管理路径列表。
- [x] 自动化逐项证明当前管理入口均有标题、权限、父级和路径匹配;新增未登记管理页会导致测试失败。
- [x] 无权限用户看不到对应管理入口;深链访问期间 Topbar 不渲染受限页面名称或面包屑。
- [x] 所有管理页面均显示 `管理 / 当前页面`,且「管理」可返回聚合页;员工档案显示 `管理 / 人员 / 员工档案`。
- [x] 直接深链、刷新和前进后退后父链仍正确;管理首页不显示自指面包屑。
- [x] 所有管理子页保持侧栏「管理」高亮,`/system/payment-accounts` 回归测试覆盖此前遗漏。
- [x] Topbar 与最近访问记录不再为管理子页回退显示原始路径。
- [x] 最近访问按当前权限过滤:撤销权限后,既有 localStorage 记录不再向用户显示受限页面标题或链接;聚焦测试覆盖权限变更场景。
- [x] 主数据 UI 使用「公司信息」而不是「法体」,正常单公司状态不出现公司切换器或新增第二公司的主导入口。
- [x] 零公司信息时,企业银行账户页提供明确说明和「完善公司信息」入口;一条时自动关联;多条异常时不静默选择。
- [x] `LegalEntity` 数据模型、现有外键、付款账户加密/审计/通知和生产数据保持不变,无数据库迁移、无真实资料写入。
- [x] `docs/产品口径.md` 以连续编号 R-6 固化单公司内部 OA 边界。
- [x] 前端相关单元/组件测试、TypeScript 检查和生产构建通过;Trellis、敏感内容和 diff 门禁通过。
- [x] 只有部署与公网检查通过后才通知用户线上验收;生产公司资料录入另由管理员执行。
## Test Plan
- 注册表契约测试:逐项校验稳定 key、唯一匹配、父级、标题、权限和管理首页可见项;覆盖未登记管理入口的失败用例。
- 导航组件测试:覆盖管理首页、企业银行账户、人员列表与员工档案深链,验证侧栏高亮、Topbar 标题、面包屑链接和最近访问中文标题;同一路径分别验证有权和无权状态。
- 权限变更测试:先以有权状态写入最近访问,再撤销权限读取,断言受限页面标题和链接均不返回;无权深链不渲染受限面包屑。
- 公司状态组件测试:分别覆盖零个、一个和多个启用公司;验证引导入口、自动关联、只读公司名称和异常 fail-closed 行为。
- 回归检查:确认管理页权限边界及 React Router 显式路由未改变,付款账户敏感字段不会进入测试快照或日志。
- 前端门禁:运行相关 Vitest、`npm run typecheck` 与 `npm run build`。
- 治理门禁:运行 Trellis task validate、Trellis governance、敏感内容检查(如当前流程要求)与 `git diff --check`。
- 面向线上用户的验收仅在另行批准部署且公网检查通过后进行;生产配置和真实数据写入不属于自动化测试。
## Out of Scope
- 多租户、多公司切换、跨公司数据隔离、集团组织、合并报表或 SaaS 产品化。
- 重命名或删除 `LegalEntity` 数据模型、外键迁移、历史数据合并和生产数据修复。
- 把所有管理子页重新放进侧栏,或建设复杂的二级侧栏导航。
- 移动端管理配置台、付款详情结构统一、审批/处理进度重构和银行制单业务变更。
- 代替管理员录入公司全称、税号、银行账户或员工收款资料。
- 取消或重建既有付款批次、生成制单、网银导入、上传回单或登记付款完成;这些属于独立的生产操作与制单验收。
@@ -0,0 +1,26 @@
{
"id": "management-navigation-single-company-ux",
"name": "management-navigation-single-company-ux",
"title": "管理导航闭环与单公司体验收敛",
"description": "统一管理首页、侧栏高亮与顶部面包屑的路由事实源,并按单公司内部 OA 口径简化公司信息和企业银行账户配置。",
"status": "in_progress",
"dev_type": null,
"scope": "client 管理导航共享事实源、公司信息单例体验、企业银行账户空状态/自动关联及产品边界文档",
"package": null,
"priority": "P2",
"creator": "shunli",
"assignee": "shunli",
"createdAt": "2026-08-03",
"completedAt": null,
"branch": null,
"base_branch": "main",
"worktree_path": null,
"commit": null,
"pr_url": null,
"subtasks": [],
"children": [],
"parent": null,
"relatedFiles": [],
"notes": "",
"meta": {}
}