业务与办公场景 UI 架构
Poco 双场景布局的路由策略、代码边界、渐进迁移方式和验收要求。
Poco 支持两套用途不同的界面:
- 业务场景:保留现有功能密度较高的 UI 和布局。
- 办公场景:面向日常办公人员,强调任务发起、最近会话、常用能力和最佳实践。
场景不是主题。场景决定信息架构和页面布局,主题预设与 Light/Dark 继续独立决定颜色、字体、圆角和阴影。
默认场景与切换权限
Backend 返回的账号级 ui_scene 始终决定用户登录后的界面场景,同一账号跨浏览器、跨设备保持一致。未知或缺失值统一回退为业务场景。
- 管理员可在用户管理中设置每个用户的默认进入场景;新建用户默认使用业务场景。
- “新用户配置”中的默认场景仅用于后续通过 SSO 自动注册的用户,不覆盖已有用户。
- 权限菜单
feature.settings.sceneSwitch只控制用户是否可见切换入口以及是否可写入自己的场景偏好,不改变其已配置的默认场景。 - 场景页面按
ui_scene渲染,具体业务操作继续使用各自的功能权限判断。例如缺少“新任务”权限时仍显示办公场景,但任务发起入口不可用。
场景切换不再依赖 Frontend 环境变量。部署时需先执行 Backend Alembic 迁移;迁移会创建权限菜单并向现有功能角色授予该权限,避免正在使用场景切换的用户升级后失去入口。如需全局关闭,可在权限菜单中禁用“场景切换”资源。部署步骤参考部署指南。
核心决策
保留一套 URL 路由
同一个业务页面只保留一个稳定地址,例如:
/{lng}/home
/{lng}/agents/free
/{lng}/chat/{session_id}不创建 /business/home 或 /office/home。账号字段 ui_scene 决定当前地址渲染哪个场景视图。
这样可以避免:
- 重复维护权限、导航、深链和页面参数。
- 场景切换时发生额外重定向。
- 新设备登录后先显示业务页面,再跳转到办公页面。
- 两套路由逐渐产生不同的请求和行为逻辑。
只有业务语义、权限或数据契约本身不同的新功能,才应新增独立 URL。
共享行为,隔离视图
请求、状态、权限、计算和跳转属于行为层;布局、文案组织和组件组合属于视图层。
代码边界:
app路由文件保持轻量,只挂载场景分发组件。- 容器组件读取场景、调用 hooks,并把 ViewModel 与事件回调交给视图。
hooks、actions、services和model不感知场景。- 场景 View 不直接调用接口,不复制会话创建、权限和统计逻辑。
components/ui保持 shadcn/ui 的项目级默认实现,不为办公场景修改基础圆角或全局样式。
目录约定
页面级代码按业务功能归档,再按场景拆分视图:
frontend/features/home/
├── components/
│ ├── home-scene-page-client.tsx
│ ├── home-overview-page-client.tsx
│ └── home-page-client.tsx
├── hooks/
│ └── use-office-home-content.ts
├── model/
│ ├── office-home-content.ts
│ └── office-home-icons.ts
├── services/
│ └── office-home-content-service.ts
└── views/
└── office/
└── office-home-view.tsx首页侧栏也在现有共享侧栏入口按场景分发:
frontend/components/shared/sidebar/
├── app-sidebar.tsx
├── global-navigation-sidebar.tsx
└── office-navigation-sidebar.tsxhome-overview-page-client.tsx 继续承载业务场景首页,home-page-client.tsx 复用现有任务发起行为,办公 View 只负责布局和展示。办公首页与定时任务共用 office-navigation-sidebar.tsx,页面内容仍按各自功能目录隔离。
定时任务的办公场景视图统一放在功能目录内:
frontend/features/scheduled-tasks/components/
├── scheduled-tasks-scene-page-client.tsx
├── scheduled-task-detail-scene-page-client.tsx
└── office/
├── office-scheduled-tasks-page.tsx
├── office-scheduled-task-form-page.tsx
└── office-scheduled-task-detail-page.tsx不要建立一份包含所有办公功能的巨型 office-ui 页面目录。页面视图与其所属功能放在一起,未来的场景外壳只处理全局导航和内容区域。
渲染与无闪屏
AppShell 必须先取得当前账号及 ui_scene,再挂载 UiSceneProvider 和场景外壳。加载账号期间不渲染任一场景的真实页面。
办公场景页面自己的数据尚未返回时,应立即显示办公场景的 Skeleton 或空状态,不能先显示业务场景内容作为占位。
场景切换流程:
- 用户选择目标场景。
- 前端更新账号设置。
UiSceneProvider更新场景状态和当前用户缓存。- 场景外壳与当前页面 View 在相同 URL 下切换。
- 保存失败时回滚到原场景并提示用户。
首页落地范围
办公首页按照设计稿拆成四个区域:
- 办公导航与最近会话。
- 欢迎区和任务输入器。
- 常用任务类型快捷入口。
- 最佳实践卡片。
优先复用:
- 任务历史与状态:
AppShellContext。 - 会话创建与跳转:现有任务发起逻辑。
- 输入、附件和能力选择:现有
TaskComposer。 - 定时任务、AI 听记、Skills 等入口:现有路由和权限。
- 基础组件:现有 shadcn/ui 和项目共享组件。
没有服务端数据源的最佳实践内容、分类和使用量先通过独立 Mock 数据模块提供。Mock 只能服务展示,不得伪装成接口响应,也不能散落在 JSX 中。接入接口时只替换数据适配层。
当前 Mock 边界与后续数据契约记录在办公场景接口待办。
渐进迁移
第一阶段只实现办公首页。尚未提供办公视图的页面继续使用业务场景页面,不复制现有路由。
每迁移一个页面:
- 盘点该页面现有请求、权限、计算和副作用。
- 抽出可复用的行为层。
- 保持业务场景输出不变。
- 新增办公场景 View。
- 补齐场景分发和多主题、多视口验收。
不要为了未来页面提前创建空容器、通用注册表或无实际使用者的抽象;出现第二个稳定复用点后再提取公共能力。
视觉与组件约束
- 只使用语义化颜色、边框、阴影和文字层级。
- 不读取主题 ID,不在业务组件中拼接主题专用 className。
- 独立 Surface 使用明确的
bg-card、bg-popover或已有theme-*语义类。 - 办公首页保持克制、清晰和低学习成本,强调主任务输入,不让装饰抢占操作层级。
- Hover、Selected、Focus、Disabled 必须可区分且不改变布局。
- 桌面、中间宽度和窄屏都必须可用;窄屏导航使用现有移动 Sidebar/Sheet 机制。
详细配色规则参考主题系统与前端配色开发手册,验收参考主题视觉验收与踩坑手册。
完成标准
- 业务场景原有接口、权限、计算和交互没有变化。
- 办公场景在同一 URL 下直接渲染,没有场景重定向和错误 UI 闪屏。
- 办公首页核心任务发起流程真实可用。
- 无接口模块使用集中 Mock,并留下明确接口待办。
- 用户可见文本全部使用 i18n。
components/ui没有办公场景特例。- Classic、其他主题、Light/Dark 及常用视口完成验证。
- Lint、主题契约测试和差异检查通过。