# TBOSS OA 模块 — 全量 UI 设计 > 版本:v1.0 | 日期:2026-06-04 | 基于 PRD / Database / Strategy 文档 > > **架构前提**:用户/组织/客户数据来自 ERP(通过 .NET API)、审批引擎复用 ERP、消息复用 .NET 服务端、OA 权限独立 ACL。 > 页面中标注「经理」「财务」「管理员」的区块为对应角色专属增量功能,基础内容对所有角色可见。 --- ## 0. 页面跳转关系总图 ``` ┌─────────────────────────────────────────────────────────────────────────────┐ │ Appshell — 底部三 Tab │ │ / → IndexedStack + GoRouter │ └─────────────────────────────────────────────────────────────────────────────┘ │ │ │ ▼ ▼ ▼ ┌─────────┐ ┌─────────┐ ┌─────────────┐ │ /messages │ │ /home │ │ /profile │ │ 消息通知 │ │ 工作台 │ │ 个人中心 │ └────┬─────┘ └────┬─────┘ └──────┬──────┘ │ │ │ │ 点击消息卡片 │ 轮播图点击 │ 语言设置 / 关于 │ 按 BizType 路由 │ → 公告详情/外部链接 │ ▼ │ │ ┌─────────────────┐ │ 金刚区·发起 │ │ 审批待办 → 详情页 │ │ → /expense-apply/apply │ │ 审批结果 → 详情页 │ │ → /expense/apply │ │ 撤回通知 → 消息列表│ │ → /vehicle/apply │ │ 系统公告 → 公告详情│ │ → /overtime/apply │ │ 过期提醒 → 详情页 │ │ → /announcement/create│ └─────────────────┘ │ (管理员额外) │ │ │ │ 金刚区·记录 │ │ → /expense-apply/list │ │ → /expense/list │ │ → /overtime/list │ │ → /vehicle/list │ │ → /outing-log/list │ │ → /announcement/list │ │ │ │ 金刚区·报表 │ │ → /report/expense-apply │ │ → /report/expense │ │ → /report/overtime │ │ → /report/vehicle │ │ → /report/outing-log │ │ │ │ 看板卡片 │ │ → 对应列表/报表/消息 │ └────────────────────────┘ ┌──────────────────────────────────────────────────────────────────────────────┐ │ 表单 → 列表 → 详情 主链路 │ │ │ │ ┌────────────┐ 存草稿/提交 ┌────────────┐ 点击卡片 ┌──────────┐ │ │ │ 表单页 │ ───────────────→ │ 列表页 │ ────────────→ │ 详情页 │ │ │ │ (apply/ │ │ (list) │ │ (detail/ │ │ │ │ create) │ ←─────────────── │ │ ←──────────── │ :id) │ │ │ └────────────┘ 左滑编辑/删除 └────────────┘ 返回 └──────────┘ │ │ ↑ ↑ │ │ │ │ │ │ │ 经理: 左滑一键同意 │ │ │ │ │ │ 用车: 左滑确认还车 │ │ │ │ │ │ │ │ │ │ rejected 重新编辑 ───┘ draft → 编辑跳表单 │ │ │ pending → 撤回申请 │ │ └── draft 编辑回填 ──────────────────────→ approved → 还车/核销 │ │ │ │ 事前申请: /expense-apply/apply → /expense-apply/list → /expense-apply/detail │ │ 费用报销: /expense/apply → /expense/list → /expense/detail │ │ 加班申请: /overtime/apply → /overtime/list → /overtime/detail │ │ 用车申请: /vehicle/apply → /vehicle/list → /vehicle/detail │ │ 外勤日志: /outing-log/create → /outing-log/list → /outing-log/detail │ │ │ │ 特殊链路: │ │ · 报销表单可「导入事前申请」→ 半屏多选已通过的申请 → 自动带入项目/科目 │ │ · 用车 approved 后 → 详情页底部「还车登记」→ Status=returned │ │ · 报销 approved+unpaid → 财务进详情页 → 三字查验 → 打款归档 │ └──────────────────────────────────────────────────────────────────────────────┘ ┌──────────────────────────────────────────────────────────────────────────────┐ │ 公告 & 权限 独立链路 │ │ │ │ 管理员: │ │ /home 金刚区 → /announcement/create → 存草稿/预览/发布 │ │ /profile → /admin/permissions → 搜索员工 → 抽屉编辑权限 → 保存+审计日志 │ │ │ │ 全员: │ │ /announcement/list ──点击──→ /announcement/detail/:id │ │ ↑ │ │ │ │ ├ 停留≥2s → 自动标记已读 │ │ │ ├ 管理员: 已读/未读统计 + DING 催办 │ │ └──── 返回列表(红点消失) ───┘ │ └──────────────────────────────────────────────────────────────────────────────┘ ┌──────────────────────────────────────────────────────────────────────────────┐ │ 报表 独立链路 │ │ │ │ /home 金刚区·报表 ─┬─ /report/expense-apply-detail 事前申请明细报表 │ │ ├─ /report/expense-detail 费用报销明细报表 │ │ ├─ /report/overtime-detail 加班明细报表 │ │ ├─ /report/vehicle-detail 用车明细报表 │ │ └─ /report/outing-log-detail 外勤日志明细报表 │ │ │ │ 每页: 时间筛选 + 专属筛选 → 数值卡片 + fl_chart 趋势图 │ │ 经理: 柱状图点击 → 下方明细列表联动过滤 → 可穿透跳详情页 │ │ 财务/管理员: 底部明细列表 + Excel 导出 │ └──────────────────────────────────────────────────────────────────────────────┘ 角色路由速查: 员工 → 轮播图 + 金刚区 + 个人快捷看板(本月报销+本月单据) 经理 → 员工版 + 待审批红色角标 + 快捷看板升级为部门范围 + 下属审批切换 财务 → 员工版 + 财务看盘(全公司:已支付/待付款/异常退回) + 核销入口 管理员 → 员工版 + 金刚区额外「发布公告」+ 全公司财务看盘 + 权限管理入口 ``` --- ## 1. 框架、导航及权限模块(5 页) #### 页面 1:Appshell 底部导航 (`/`) | 区域 | 组件 | 说明 | |------|------|------| | 底部导航 | TDTabBar | 三个 Tab:消息、工作台、我的 | | 主内容区 | IndexedStack + GoRouter | 路由驱动的视图容器,保持各 Tab 页面状态 | | 消息角标 | TDBadge | 未读消息数,进入时拉取 + 30s 轮询或 Push 刷新。数据来源 .NET 消息模块 API | | 交互 | 行为 | |------|------| | 点击 Tab | 路由切换,图标变 `#00ABF3` | | 重复点击当前 Tab | 列表页 ScrollToTop,非列表无行为 | --- #### 页面 2:消息通知聚合页 (`/messages`) ##### 页面结构 | 区域 | 组件 | 说明 | |------|------|------| | 导航栏 | TDNavbar | 标题"消息通知",右侧"全部已读"按钮(仅未读>0 时显示) | | 列表 | TDListView | 下拉刷新 / 上拉加载 | | 数据来源 | — | .NET 消息模块 API(非本地 Message 表) | ##### 消息类型 | 类型 | 图标 | 示例标题 | 点击行为 | |------|------|---------|---------| | 审批待办 | 📋 | "张三提交了差旅报销,待审批" | 进入详情页,底部展审批操作栏 | | 审批结果 | ✅/❌ | "您的差旅报销已通过" / "已被拒绝" | 进入详情页查看结果 | | 撤回通知 | ↩ | "张三撤回了差旅报销" | 消息列表(单据已不可审批) | | 系统公告 | 📢 | "【通知公告】2026年端午放假安排" | 进入公告详情页 | | 过期提醒 | ⏰ | "您的差旅申请已过期,预算已释放" | 进入对应详情页 | ##### 消息卡片 | 元素 | 组件 | 说明 | |------|------|------| | 图标 | Icon | 按消息类型展示不同图标 | | 标题 | Text | 消息大标题 | | 摘要 | Text | 摘要文本,单行截断 | | 时间 | Text | 发送时间,格式 MM-DD HH:mm | | 未读标记 | TDBadge | 未读消息显示红点 | ##### 卡片交互 | 操作 | 组件 | 行为 | |------|------|------| | 左滑 | TDSwipeAction | `[标记已读]`(蓝)+ `[删除]`(红)。已读消息不可左滑 | | 标记已读 | — | 调 .NET 消息 API,成功→红点淡出+卡片透明度↓ | | 删除 | TDDialog | 确认弹窗→卡片收起+调 API 删除 | ##### 推送通道 | 消息类别 | 通道 | |---------|------| | 审批类 | App Push + 站内消息 | | 公告类 | 站内消息 | | DING 催办 | App Push(高优先级,无视免打扰) | --- #### 页面 3:工作台 (`/home`) ##### 角色判定 | 权限 | 工作台版本 | 优先级 | |------|---------|:--:| | 有 `oa.admin.*` | 管理员版 | 1 | | 无 admin,有 `oa.expense.mark_paid` | 财务版 | 2 | | 无上述,有 `oa.*.approve` 或 `oa.*.view_dept` | 经理版 | 3 | | 其他 | 员工版 | 4 | > 高优先级叠加低优先级的基础区块。权限数据来源:`OaUserPermission` 本地表。 ##### 所有角色共有 | 区域 | 组件 | 说明 | |------|------|------| | 轮播图 | TDesign `Swiper` | 3s 自动切换,循环播放。点击有 LinkUrl→跳转,无→全屏预览双指缩放。数据来源 `SysBanner`(OA 本地) | | 金刚区 | TDGrid(4 列) | 三区域:**发起** 事前申请/费用报销/用车申请/加班申请;**记录** 申请记录/报销记录/加班记录/用车记录 + 外勤日志/公司公告;**报表** 事前申请报表/费用报销报表/加班报表/用车报表 + 外勤日志报表 | ##### 员工版 | 区域 | 组件 | 说明 | |------|------|------| | 快捷看板-卡片1 | TDCard | 本月累计报销(本人已付款总额 ¥),点击→报销记录列表 | | 快捷看板-卡片2 | TDCard | 本月已提单据(本人提交总数 笔),点击→申请记录列表 | | 数据来源 | — | .NET 服务端预计算,缓存 5min,下拉强制刷新 | ##### 经理/老板版 | 区域 | 组件 | 说明 | |------|------|------| | 待审批卡片 | TDCard + TDBadge | 红色角标显示待办数,数据来源 .NET → ERP,点击→消息列表 | | 快捷看板升级 | TDCard ×3 | 数据范围升级为本部门:本月累计报销(部门) / 本月已提单据(部门) / 部门在途单据 | ##### 财务版 | 区域 | 组件 | 说明 | |------|------|------| | 财务看盘 | TDCard ×3 | 替代快捷看板,全公司数据:本月已支付总额 / 待付款总额 / 本周异常退回 | | 数据来源 | — | .NET 全公司聚合查询,缓存 5min | ##### 管理员版 | 区域 | 组件 | 说明 | |------|------|------| | 金刚区增量 | TDGrid | 发起区域额外显示"发布公告"入口 | | 快捷看板 | TDCard ×3 | 与财务版相同,全公司数据 | --- #### 页面 3.1:个人中心 (`/profile`) ##### 页面结构 | 区域 | 组件 | 说明 | |------|------|------| | 头像 | TDAvatar | 点击更换,数据来源 `GET /api/user/{erpUserId}` | | 用户信息 | Text | 姓名 / 部门 / 岗位,同上 | | 功能列表 | TDListView | 分组样式 | ##### 功能列表 | 功能 | 行为 | |------|------| | 语言设置 | 底部弹出 TDActionSheet:简体中文 / 繁體中文 / English。选择后立即生效,写入本地存储,下次启动保持 | | 关于 | 版本号 / 用户协议 / 隐私政策 | ##### 交互 | 操作 | 行为 | |------|------| | 点击头像 | 唤起相册/相机 → 裁剪(1:1,≤2MB) → `PUT /api/user/avatar` → 全局刷新。失败 Toast"头像上传失败" | | 登录态 | 宿主 App 统一管理。监听宿主登出→清本地缓存。API 401→MethodChannel 通知宿主重登录 | --- #### 页面 3.2:权限管理 (`/admin/permissions`)【管理员专属】 | 区域 | 组件 | 说明 | |------|------|------| | 搜索栏 | TDSearchBar | 按姓名/工号模糊搜索,300ms 防抖,来源 `GET /api/user/search` | | 员工列表 | TDListView | 每页 20 条,默认按部门+姓名排序。每张卡片展示:头像、姓名、工号、部门、当前权限标签(TDTag) | **抽屉内容**(TDDrawer,点击员工卡片右侧滑出): | 区域 | 组件 | 说明 | |------|------|------| | 快捷套餐 | TDButton ×4 | 员工(apply+view_own+create)/ 审批人(员工权限+approve+view_dept+comment)/ 财务(view_all+mark_paid+export)/ 管理员(全部)。点击后自动勾选对应权限点 | | 权限点列表 | TDCheckbox 分组 | 按模块分组(报销/事前/加班/用车/外勤/公告/报表/管理),逐项勾选。无角色用户默认等同"员工" | | 确认保存 | TDButton | `PUT /api/oa/user-permissions` → 写入 OaPermissionChangeLog(Before/After 快照 JSON)→ Toast"权限已更新"。失败→Toast 红 | | 变更记录 | 折叠区 | TDTimeline 展示最近 20 条 OaPermissionChangeLog:操作时间、操作人、变更摘要(如"添加了财务人员角色") | | 自保护 | — | 无法取消自己的 admin 角色→Toast;至少保留一名管理员→后端拒绝 | --- ## 2. 费用控制与报销模块(6 页) #### 页面 4:事前申请表单 (`/expense-apply/apply`) ##### 基本信息区 | 字段 | 组件 | 说明 | |------|------|------| | 申请人 | TDInput(只读) | 当前登录用户姓名,`GET /api/user/{erpUserId}` | | 所属部门 | TDInput(只读) | 同上 | | 申请日期 | TDInput(只读) | 当前日期 `DateTime.now()`,格式 YYYY-MM-DD | | 紧急程度 | TDRadioGroup | 普通 / 紧急 / 特急,默认普通 | | 费用类型 | TDCheckboxGroup(多选) | 至少勾选一项,如"差旅费"+"办公费",对应 DB `ExpenseTypes` 逗号分隔存储 | | 预估含税 | TDSwitch | 默认关,对应 DB `IsTaxIncluded` | | 费用事由 | TDTextarea | 必填,≤200 字,对应 DB `Purpose` | | 有效期至 | TDDatePicker | 可选,不填则永不过期,对应 DB `ValidUntil` | ##### 关联管控区 | 字段 | 组件 | 说明 | |------|------|------| | 关联项目 | TDCascader | .NET → ERP ProjectService,选定后加载科目 | | 预算科目 | TDPicker | .NET → ERP SubjectService,选定后加载余额 | | 可用余额 | 只读文本 | 项目+科目选定后异步展示"¥XXXX.xx"。超预算时金额变红+警告,不阻止提交 | | 关联合同号 | TDInput | 选填,对应 DB `ReferenceNo` | ##### 费用类型专用字段(按 ExpenseTypes 动态展示) | 勾选类型 | 显示字段 | |---------|---------| | 差旅费 | 预计开始日期 / 预计结束日期 / 是否过夜(TDSwitch)/ 交通工具(TDPicker:飞机/高铁/火车/自驾) | | 招待费 | 招待对象单位 / 招待层级(TDPicker:普通/重要/VIP)/ 外部人数 / 内部陪同人数 / 地点。校验:陪同人数 ≤ 外部人数 | | 会议费 | 预计开始日期 / 预计结束日期 / 会议地点 | | 其他类型 | 无专用字段,通用字段已覆盖 | > 以上字段数据库全部 NULL 允许,应用层按 ExpenseTypes 动态校验必填。 ##### 预估明细区 | 字段 | 组件 | 说明 | |------|------|------| | 费用类别 | TDPicker | SysCostCategory 叶子节点,下拉受 ExpenseTypes 联动过滤 | | 数量 | TDInput(数字) | >0 | | 单位 | TDPicker | 张 / 间 / 人 / 天 / 套 / 个,默认"张" | | 单价 | TDInput(数字) | >0 | | 单项金额 | 只读 | 自动计算 = 数量 × 单价 | | 明细说明 | TDInput | 选填 | | [+ 添加] | 按钮 | 平滑展开新明细卡片 | | ✕ 删除 | 图标按钮 | 气泡确认→折叠消失 | | — | — | — | | **预估总金额** | 只读(大字) | 所有明细行单项金额自动汇总为"¥XX,XXX.XX",对应 DB `EstimatedAmount`。若超预算→金额变红 + 警告"您的申请金额已超支,提交后将自动触发高管特批流程" | ##### 附件上传区 | 属性 | 说明 | |------|------| | 组件 | TDesign `TDUpload` | | 数量 | 最多 9 张,满 9 隐藏上传入口 | | 类型 | 图片 ≤10MB / PDF ≤20MB | | 来源 | 相册 / 相机 / 文件选择器 | | 展示 | 网格缩略图,右上角删除按钮 | | 预览 | 点击缩略图→黑底全屏(双指缩放 0.5x~3x),PDF→原生查看器 | | 存储 | `Attachment (BizType='expense_apply')` | ##### 底部操作栏 | 按钮 | 颜色 | 可见条件 | 行为 | |------|------|---------|------| | `[重置]` | 灰 | 编辑已有草稿时 | 确认弹窗→清空至初始状态 | | `[存为草稿]` | 浅蓝 | 始终 | 不校验,保存所有已填内容(含空字段) | | `[提交审批]` | `#00ABF3` | 始终 | 触发全局校验,失败不提交,超预算不阻止 | ##### 校验规则 | 校验项 | 规则 | |--------|------| | 费用类型 | 至少勾选一项 | | 费用事由 | 必填,≤200 字 | | 项目 / 科目 | 必选(ERP 有数据时) | | 预估明细 | 至少一行(数量>0,单价>0) | | 差旅类 | 开始/结束日期必填,结束≥开始 | | 招待类 | 单位/层级/外部人数必填,陪同≤外部人数 | | 会议类 | 开始/结束日期必填,地点必填 | > 不通过时 ScrollTo 报错字段(300ms)+ 红闪 2s + TDMessage 红色横幅。 ##### 页间流转 | 操作 | API | 成功 | 失败 | |------|-----|------|------| | 存草稿 | `PUT /api/oa/expense-apply/draft` | Toast 绿"已保存为草稿" → 跳列表(激活"草稿"Tab) | Toast 红"保存失败,请稍后重试" | | 提交审批 | `POST /api/oa/expense-apply/submit` | .NET 创建 ERP 审批实例 → 返回 ApprovalInstanceId → Toast"已提交,等待审批" → 跳列表 | 同上 | | 返回(有修改) | — | TDDialog"当前内容尚未保存,是否退出?"→ 继续编辑 / 放弃并退出 | — | --- #### 页面 5:费用报销表单 (`/expense/apply`) ##### 新建方式 | 方式 | 操作 | 说明 | |------|------|------| | 导入申请 | 点击顶部蓝色快捷链「导入已通过的事前申请」| 半屏抽屉多选 approved+有额度的申请,每条填导入金额。项目/科目/成本中心自动带入,额度实时校验。空→TDEmpty | | 直接新建 | 不导入,手动填写 | 手动选择项目→科目→查预算,链式操作与页面 4 相同 | ##### 基本信息区 | 字段 | 组件 | 说明 | |------|------|------| | 报销事由 | TDTextarea | 必填,对应 DB `Purpose` | | 成本中心 | TDPicker | .NET → ERP CostCenterService,可选。ERP 无数据时隐藏 | | 报销总金额 | 只读 | 明细累加上浮动画显示,对应 DB `TotalAmount` | | 项目 / 科目 | 只读或手动 | 导入时自动带入;直接新建时手动选择(TDCascader,同页面 4) | ##### 收款账户区 | 字段 | 组件 | 说明 | |------|------|------| | 开户行 | TDInput+下拉联想 | `GET /api/dict/banks`,可自由输入 | | 户名 | TDInput | 默认当前用户姓名,可修改 | | 账号 | TDInput | 校验 16-19 位数字 | ##### 报销明细区 | 字段 | 组件 | 说明 | |------|------|------| | 发生日期 | TDDatePicker | 年月日,对应 DB `ExpenseDate` | | 费用类别 | TDPicker | SysCostCategory 叶子节点,对应 DB `ExpenseType` | | 费用描述 | TDInput | 摘要说明,对应 DB `ExpenseDesc` | | 币种 | TDPicker | 默认 CNY。选外币时自动从 .NET→ERP ExchangeRateService 填汇率 | | 原币金额 | TDInput(数字) | 不含税金额,对应 DB `Amount` | | 税额 | TDInput(数字) | 进项税额,对应 DB `TaxAmount` | | 价税合计 | 只读 | 自动计算 = 金额+税额,对应 DB `TotalAmount` | | 本币金额 | 只读 | 自动计算 = 价税合计×汇率,对应 DB `BaseAmount` | | 发票类型 | TDPicker | 增值税专票(special) / 普票(general) / 无发票(none) | | 发票号码 | TDInput | 专票/普票时必填,无发票时可空 | | 发票代码 | TDInput | 同上 | | 税率 | TDPicker | 6% / 9% / 13%,对应 DB `TaxRate` | | [+ 添加] | 按钮 | 平滑展开新明细卡片 | | ✕ 删除 | 图标按钮 | 气泡确认→折叠消失 | > 无发票场景:单笔≤200 元小额零星可选 `none`,此时发票号和代码可空。明细金额自动汇总至主表 `TotalAmount`。 ##### 附件上传区 | 属性 | 说明 | |------|------| | 组件 | TDesign `TDUpload` | | 数量 | 最多 9 张 | | 大小 | ≤10MB | | 绑定 | 可绑定到具体明细行(`Attachment.DetailId`) | | 存储 | `Attachment (BizType='expense')` | | 交互 | 同页面 4 | ##### 底部操作栏 | 按钮 | 颜色 | 可见条件 | 行为 | |------|------|---------|------| | `[重置]` | 灰 | 编辑已有草稿时 | 确认弹窗→清空至初始状态 | | `[存为草稿]` | 浅蓝 | 始终 | 不校验,保存已填内容 | | `[提交审批]` | `#00ABF3` | 始终 | 触发全局校验,失败不提交,超预算不阻止 | ##### 校验规则 | 校验项 | 规则 | |--------|------| | 报销事由 | 必填 | | 项目 / 科目 | 直接新建时必选(ERP 有数据时) | | 导入金额 | 每条>0,∑≤对应申请剩余可报额度 | | 收款银行/户名/账号 | 必填,账号 16-19 位数字 | | 报销明细 | 至少一行(金额>0,费用类别必选) | | 发票信息 | 发票类型必选,专票/普票时发票号必填 | > 不通过时 ScrollTo 报错字段+红闪+TDMessage。 ##### 页间流转 | 操作 | API | 成功 | 失败 | |------|-----|------|------| | 存草稿 | `PUT /api/oa/expense/draft` | Toast 绿"已保存为草稿" → 跳列表(激活"草稿"Tab) | Toast 红 | | 提交审批 | `POST /api/oa/expense/submit` | .NET 创建 ERP 审批实例 + 冻结预算 + 写入 ExpenseApplicationMapping → Toast"已提交" → 跳列表 | Toast 红 | | 返回(有修改) | — | TDDialog"是否退出?"→ 继续编辑 / 放弃 | — | --- #### 页面 6:事前申请列表 (`/expense-apply/list`) ##### 页面结构 | 区域 | 组件 | 说明 | |------|------|------| | 导航栏 | TDNavbar | 标题"申请记录" | | 筛选栏 | DateRangeFilter + FilterDropdown ×2 | TabBar 下方:日期范围选择器 + 费用类型(差旅/招待/办公/会议)+ 紧急程度(普通/紧急/特急)。筛选条件变化时重新拉取数据 | | 状态筛选 | TDTabBar | Tab:全部 / 草稿 / 审批中 / 已通过 / 已拒绝 / 已撤回。默认选中"全部" | | 列表 | TDListView | 下拉刷新(page=1)/ 上拉加载(page++)。数据来源 OA 本地 ExpenseApplication 表,审批状态通过 .NET→ERP 实时查询 | | 空状态 | TDEmpty | 文案随 Tab 变化:"暂无草稿""暂无审批中的单据"等 | ##### 列表卡片 | 元素 | 组件 | 说明 | |------|------|------| | 编号 | Text | 单据编号 BXSQ-YYYYMMDD-XXX | | 摘要 | Text | 事由摘要,单行截断 | | 金额 | Text | 预估金额,粗体高亮 | | 日期 | Text | 提单日期 YYYY-MM-DD | | 类型标签 | TDTag | 费用类型标签(如"差旅"+"办公") | | 状态 | StatusTag | 灰-草稿 / 橙-审批中 / 绿-已通过 / 红-已拒绝 / 灰-已撤回 | ##### 卡片交互 | 状态/角色 | 操作 | 行为 | |----------|------|------| | 任意 | 点击 | → 详情页 `/expense-apply/detail/:id` | | 本人 draft | 左滑 | `[编辑]`(TDSwipeAction 蓝)+ `[删除]`(红)。编辑→跳表单回填;删除→TDDialog 确认→软删除 | | 本人 rejected | 左滑 | `[编辑]`(TDSwipeAction 蓝),跳表单回填 | | 他人/其他 | 左滑无反应 | — | ##### 经理增量 | 区域 | 组件 | 说明 | |------|------|------| | 范围切换 | TDChip ×2 | TDTabBar 上方:`我的发起` / `下属审批`,选中高亮 `#00ABF3` | | 下属卡片-申请人 | Text | 额外显示"申请人姓名 — 部门" | | 下属 pending | TDSwipeAction | 左滑 `[一键同意]`(绿),就地审批 | > 数据来源:`GET /api/oa/approval/subordinates` → OA 业务表 JOIN ERP 审批状态。 --- #### 页面 7:费用报销列表 (`/expense/list`) ##### 页面结构 | 区域 | 组件 | 说明 | |------|------|------| | 导航栏 | TDNavbar | 标题"报销记录" | | 筛选栏 | DateRangeFilter | TabBar 下方:日期范围选择器。筛选条件变化时重新拉取数据 | | 状态筛选 | TDTabBar | Tab:全部 / 草稿 / 审批中 / 已通过 / 待付款 / 已付款 / 已拒绝 / 已撤回 | | 列表 | TDListView | 同页面 6。数据来源 OA 本地 Expense 表 | | 空状态 | TDEmpty | 同页面 6 | ##### 列表卡片 | 元素 | 组件 | 说明 | |------|------|------| | 编号 | Text | 单据编号 BX-YYYYMMDD-XXX | | 摘要 | Text | 事由摘要 | | 金额 | Text | 报销金额,粗体高亮 | | 日期 | Text | 提单日期 | | 状态 | StatusTag | 同页面 6 | | 付款状态 | TDTag | 黄-待付款 / 蓝-已付款 | > 卡片交互同页面 6(左滑编辑/删除规则一致)。 ##### 财务增量 | 区域 | 组件 | 说明 | |------|------|------| | 数据范围 | — | 默认全公司(不限制 ApplicantId) | | 核销入口 | — | 点击卡片→详情页完成核销。列表页不提供快捷付款 | ##### 经理增量 与页面 6 相同:TDTabBar 上方 `TDChip` 范围切换 + `TDSwipeAction` 一键同意。 --- #### 页面 8:事前申请详情 (`/expense-apply/detail/:id`) | 区域 | 组件 | 说明 | |------|------|------| | 状态横幅 | StatusBanner | 审批中(⏳ 橙,显示当前审批人)/ 已通过(✅ 绿)/ 已拒绝(❌ 红)/ 已撤回(↩ 灰)。审批状态通过 ERP 实时查询 | | 基本信息 | TDDescription | key-value 双栏:申请人 / 部门 / 日期 / 紧急程度 / 费用类型(TDTag 多选标签)/ 含税标记 / 有效期至 / 关联合同号 | | 使用状态 | TDTag | 未使用(绿)/ 部分使用(黄)/ 已用完(灰),对应 DB `UsageStatus` | | 关联项目 | TDDescription | 项目名称 / 预算科目 / 预估总金额(¥) | | 明细列表 | TDTable | 每行:类别 / 数量×单价 / 单位 / 单项金额 / 说明。>5 行默认折叠,`[展开全部]` 按钮展开 | | 附件 | TDUpload | 支撑材料宫格,点击缩略图→全屏预览(双指缩放)。来源于 Attachment (BizType='expense_apply') | | 审批时间线 | TDTimeline | 纵向时间线,首节点"发起人已提交"(拼装 CreateTime+申请人),后续节点来自 .NET→ERP。若 withdrawn→末尾追加灰色撤回节点 | | 底部 | 见下方操作表 | 员工/经理/管理员角色操作 | ##### 页面 8 操作表 **员工** | 状态 | 按钮 | 行为 | |------|------|------| | draft | `[编辑]` `[提交审批]` | 编辑→跳表单回填;提交→校验→调 ERP | | pending | `[撤回申请]` | TDDialog→`POST /api/oa/approval/withdraw`→Status='withdrawn' | | rejected | `[重新编辑并发起]` | 跳表单编辑态,提交后更新原记录 | | approved | 无 | 等待报销引用 | | withdrawn | 无 | 仅查看 | **经理**(pending+当前审批人=该经理):`[同意]`(主色)/ `[拒绝]`(白底红字,≥5字理由)。风控看板:申请人同类单据数+预算进度条。 **管理员**(所有状态):`[强制终止]`(红底白字)+ `[查看审批链]`(含旧实例)。 > 通用交互:时间线节点点击→当前用户待审批可弹出审批操作。审批人头像/姓名点击→TDDialog。 --- #### 页面 9:费用报销详情 (`/expense/detail/:id`) | 区域 | 组件 | 说明 | |------|------|------| | 状态横幅 | StatusBanner | 审批状态(同页面 8)+ 付款状态 TDTag:待付款(黄)/ 已付款(蓝) | | 基本信息 | TDDescription | 申请人 / 部门 / 日期 / 事由 / 成本中心 / 项目 / 科目 / 报销总金额(¥) | | 收款信息 | TDDescription | 开户行 / 户名 / 账号(详情页完整展示,列表页脱敏展示后 4 位 `****0123`) | | 申请来源 | TDList | 若导入:列出关联申请编号 + 每张导入金额;若直接新建:不展示 | | 明细列表 | TDTable | 每行:日期 / 类别 / 描述 / 原币金额+币种 / 税额 / 价税合计 / 本币金额+汇率 / 发票类型/号/码/税率。>5 行折叠 | | 附件 | TDUpload | 发票影像宫格,可绑定明细行。来源于 Attachment (BizType='expense') | | 审批时间线 | TDTimeline | 同页面 8 | | 财务查验区 | TDCheckbox ×3 | 仅财务可见:验真 / 税号一致 / 类目合规。全勾→解锁打款按钮。对应 DB `IsInvoiceVerified/IsTaxIdMatched/IsCategoryCompliant` | | 底部 | 见本页下方操作表 | 员工/经理/管理员/财务角色 | ##### 页面 9 操作表 **员工** | 状态 | 按钮 | 行为 | |------|------|------| | draft | `[编辑]` `[提交审批]` | 编辑→跳表单回填;提交→校验→调 ERP | | pending | `[撤回申请]` | TDDialog→`POST /api/oa/approval/withdraw`→Status='withdrawn' | | rejected | `[重新编辑并发起]` | 跳表单编辑态,提交后更新原记录 | | approved | 无 | 等待财务打款 | | withdrawn | 无 | 仅查看 | **经理**(pending+当前审批人=该经理):`[同意]`(主色)/ `[拒绝]`(白底红字,≥5字理由)。风控看板:申请人同类单据数+预算进度条。 **管理员**(所有状态):`[强制终止]`(红底白字)+ `[查看审批链]`(含旧实例)。 > 通用交互:时间线节点点击→当前用户待审批可弹出审批操作。审批人头像/姓名点击→TDDialog。 **财务**(Status=approved + PaymentStatus=unpaid) | 操作 | 行为 | |------|------| | 三项合规复选框 | 验真 / 税号一致 / 类目合规。未全勾→`[确认打款]` 灰色锁定 | | `[确认打款并归档]` | 全勾后激活→滑出凭证表单(电汇流水号+记账凭证号必填)→PaymentStatus='paid' | | `[退回修改]` | 选择退回节点(员工重填/经理重审)→状态倒流 | | 归档后 | 按钮替换为 `[下一笔待付款]`;无则 Toast"全部待付款单据已处理完毕" | --- ## 3. 勤务考勤、用车调度与外勤外务模块(9 页) #### 页面 10:加班申请表单 (`/overtime/apply`) ##### 基本信息区 | 字段 | 组件 | 说明 | |------|------|------| | 加班类型 | TDPicker | 工作日 / 休息日 / 法定节假日,默认"工作日"。节假日标注费率(300%) | | 补偿方式 | TDRadio | 转调休 / 结算加班费 / 混合模式。默认"转调休" | | 混合比例 | TDSlider | 10%~90%,步长 10%,仅补偿方式=混合时显示。右侧实时文字:"30% 转调休 + 70% 结算加班费" | | 开始时间 | TDDatePicker | 年月日时分,必填 | | 结束时间 | TDDatePicker | 年月日时分,必填。校验:必须晚于开始时间 | | 净工时 | 只读大字卡片 | 自动计算 = (结束-开始) - 午餐(12:00-13:00) - 晚餐(18:00-18:30)。≤0→变红+提交按钮置灰 | | 加班原因 | TDTextarea | 必填 | ##### 底部操作栏 | 按钮 | 行为 | |------|------| | `[存为草稿]` | 不校验,保存已填内容 | | `[提交审批]` | 触发校验(必填项+净工时>0),通过后 `POST /api/oa/overtime/submit` → ERP 创建审批实例 | ##### 校验规则 | 校验项 | 规则 | |--------|------| | 开始/结束时间 | 必填,结束>开始 | | 净工时 | 必须>0 | | 加班原因 | 必填 | > 不通过时 ScrollTo+红闪+TDMessage。 --- #### 页面 11:加班申请列表 (`/overtime/list`) | 区域 | 组件 | 说明 | |------|------|------| | 导航栏 | TDNavbar | 标题"加班记录" | | 筛选栏 | DateRangeFilter + FilterDropdown | TabBar 下方:日期范围选择器 + 加班类型(工作日/休息日/节假日) | | 状态筛选 | TDTabBar | 全部 / 草稿 / 审批中 / 已通过 / 已拒绝 / 已撤回 | | 列表 | TDListView | 下拉刷新/上拉加载,数据来源 OA 本地 Overtime 表,审批状态通过 ERP 实时查询 | ##### 列表卡片 | 元素 | 组件 | 说明 | |------|------|------| | 编号 | Text | JB-YYYYMMDD-XXX | | 类型标签 | TDTag | 工作日/休息日/节假日 | | 净工时 | Text | 粗体高亮 X.Xh | | 补偿方式 | Text | 加班费 / 转调休 / "X%调休+Y%结算" | | 日期 | Text | 提单日期 | | 状态 | StatusTag | 同页面 6 | ##### 卡片交互 | 状态/角色 | 操作 | 行为 | |----------|------|------| | 任意 | 点击 | → 详情页 `/overtime/detail/:id` | | 本人 draft | 左滑 | `[编辑]` `[删除]`(同页面 6) | | 本人 rejected | 左滑 | `[编辑]` | | 他人/其他 | 左滑无反应 | — | > **经理增量**:TDChip 范围切换(`我的发起` / `下属审批`)+ TDSwipeAction `[一键同意]`。同页面 6。 --- #### 页面 12:加班申请详情 (`/overtime/detail/:id`) | 区域 | 组件 | 说明 | |------|------|------| | 状态横幅 | StatusBanner | 同页面 8 | | 基本信息 | TDDescription | 申请人/部门/加班类型/补偿方式/混合比例/开始时间/结束时间/净工时/原因 | | 审批时间线 | TDTimeline | 同页面 8 | | 底部操作栏 | 同页面 8 | 员工端各状态操作。**经理端**(pending 审批人=本人):同意/拒绝。**管理员端**:强制终止+查看审批链 | --- #### 页面 13:用车申请表单 (`/vehicle/apply`) ##### 基本信息区 | 字段 | 组件 | 说明 | |------|------|------| | 车牌号 | TDPicker | OA 本地 SysVehicle 车池(仅显示空闲+使用中车辆)。冲突车辆标红,无可用→TDEmpty | | 用车事由 | TDInput | 必填 | | 用车目的 | TDPicker | 客户接待 / 商务出行 / 公务 | | 始发地 | TDInput | 原生定位自动填入,可修改 | | 目的地 | TDInput + 地图图标 | 点击地图图标→MethodChannel 唤醒原生地图选点,回填地址+经纬度 | | 出车时间 | TDDatePicker | 年月日时分,必填 | | 还车时间 | TDDatePicker | 年月日时分,必填。校验:必须晚于出车时间 | | 同行人数 | TDInput(数字) | 默认 1,输入 0 自动调整为 1 | | 同行人 | TDChip + MethodChannel | 点击[+]→原生通讯录多选→胶囊标签展示,x 剔除 | ##### 排期冲突检测 | 触发条件 | 行为 | |---------|------| | 车牌+出车/还车时间选定后 | 异步调 .NET → OA 本地 Vehicle 表校验时段重叠 | | 冲突 | 红色警告"该时段车辆已被预订",提交按钮锁死。提示"请选择其他车辆或调整时间" | | 无冲突 | 可正常提交 | ##### 底部操作栏 与页面 4 相同:`[存为草稿]` + `[提交审批]`,提交调 `POST /api/oa/vehicle/submit`。 ##### 校验规则 | 校验项 | 规则 | |--------|------| | 车牌号 | 必选 | | 事由/目的 | 必填 | | 出车/还车时间 | 必填,还车>出车 | | 排期冲突 | 无冲突方可提交 | --- #### 页面 14:用车申请列表 (`/vehicle/list`) | 区域 | 组件 | 说明 | |------|------|------| | 导航栏 | TDNavbar | 标题"用车记录" | | 筛选栏 | DateRangeFilter + FilterDropdown | TabBar 下方:日期范围选择器 + 用车目的(客户接待/商务出行/公务) | | 状态筛选 | TDTabBar | 全部 / 草稿 / 审批中 / 已通过 / 已拒绝 / 已撤回 / 已还车 | | 列表 | TDListView | 数据来源 OA 本地 Vehicle 表 | ##### 列表卡片 | 元素 | 组件 | 说明 | |------|------|------| | 编号 | Text | YC-YYYYMMDD-XXX | | 车牌 | Text | 粗体高亮 | | 行程 | Text | 始发地 → 目的地 | | 时间 | Text | 出车时间 MM-DD HH:mm | | 用途标签 | TDTag | 接待/商务/公务 | | 状态 | StatusTag | 同页面 6,额外含 returned(已还车-蓝) | ##### 卡片交互 | 状态/角色 | 操作 | 行为 | |----------|------|------| | 任意 | 点击 | → 详情页 `/vehicle/detail/:id` | | 本人 draft/rejected | 左滑 | `[编辑]` `[删除]`(同页面 6) | | 本人 approved | 左滑 | `[确认还车]`,拉起半屏核销抽屉 | | 已还车 | 左滑无反应 | — | > 经理增量:TDChip 范围切换 + TDSwipeAction 一键同意(同页面 6)。 --- #### 页面 15:用车申请详情 (`/vehicle/detail/:id`) | 区域 | 组件 | 说明 | |------|------|------| | 状态横幅 | StatusBanner | 同页面 8,额外含 returned(已还车-蓝) | | 基本信息 | TDDescription | 申请人/部门/车牌/目的/事由/始发地→目的地/出车时间/还车时间/同行人数/同行人列表 | | 地图 | 静态地图 | 始发地+目的地标记,点击→MethodChannel 唤醒原生地图导航 | | 审批时间线 | TDTimeline | 同页面 8 | | 底部操作栏 | 同页面 8 | 员工端各状态操作 | ##### 还车登记(仅 approved 状态) | 字段 | 组件 | 说明 | |------|------|------| | 实还时间 | TDDatePicker | 年月日时分。若早于 EndTime→灰字提示"提前还车";若晚于→红字"已超出原计划还车时间" | | 出车前里程 | TDInput(数字) | 必填 | | 还车后里程 | TDInput(数字) | 必填,校验≥出车前里程。不通过→红色提示+提交按钮置灰 | | 实际费用金额 | TDInput(数字) | 路桥费/停车费等实际费用总额(元),对应 DB `ActualCost` | | 费用备注 | TDInput | 费用明细补充说明,对应 DB `CostRemark` | | 确认提交 | 按钮 | TDDialog"提交后里程和费用不可再修改"→确认→Status='returned'→页面刷新+底部灰字"已还车归档于 YYYY-MM-DD HH:mm" | > **经理端**(pending 审批人=本人):详情页底部同意/拒绝操作栏。**管理员端**:强制终止+查看审批链。 --- #### 页面 16:外勤日志创建 (`/outing-log/create`) ##### 页面结构 | 区域 | 组件 | 说明 | |------|------|------| | GPS 定位区 | MethodChannel → 只读文本 | 页面初始化强制请求高精度 GPS,逆地理编码地址只读不可修改。绿色盾牌安全图标。精度>100m→黄色警告。失败→TDEmpty"无法获取当前位置"+提交按钮置灰 | | 客户名称 | TDInput + 联想 | `GET /api/customer/search?q=` 联想匹配 ERP 客户池。无匹配→自由文本,提交时 .NET 自动创建 ERP 客户 | | 客户联系人 | TDPicker | 选填,选定客户后加载该客户的联系人列表(来源 ERP 客户主数据),对应 DB `ContactId` | | 工作总结 | TDTextarea | 必填 | | 后续计划 | TDInput | 选填 | ##### 现场拍照 | 属性 | 说明 | |------|------| | 方式 | 跳过相册,MethodChannel 直接唤起原生相机 | | 水印 | 服务器授时 + GPS 经纬度,自动渲染 | | 数量 | 最少 1 张,最多 9 张 | | 存储 | Attachment (BizType='outing_log'),FileType='sign_in_photo' | | 校验 | <1 张→提交按钮置灰+红提示"请至少拍摄一张现场照片"。相机权限被拒→TDDialog+前往设置 | ##### 底部操作栏 | 按钮 | 行为 | |------|------| | `[存为草稿]` | GPS/CustomerId 可为空,保存已填内容 | | `[提交]` | 校验 GPS 已定位 + 客户名已填 + 照片≥1。提交调 `PUT /api/oa/outing-log/submit` | --- #### 页面 17:外勤日志列表 (`/outing-log/list`) | 区域 | 组件 | 说明 | |------|------|------| | 导航栏 | TDNavbar | 标题"外勤记录" | | 筛选栏 | DateRangeFilter | TabBar 下方:日期范围选择器 | | 筛选 | TDTabBar | 全部 / 草稿 / 已完成 | | 列表 | TDListView | 按 CreateTime 倒序,数据来源 OA 本地 OutingLog 表 | ##### 列表卡片 | 元素 | 组件 | 说明 | |------|------|------| | 编号 | Text | VST-YYYYMMDD-XXX | | 客户名 | Text | 粗体高亮 | | 地址 | Text | 签到地址截断一行 | | 摘要 | Text | 工作总结截取 50 字 | | 日期 | Text | YYYY-MM-DD | | 状态 | StatusTag | 草稿(灰)/ 已完成(绿) | | 新点评标记 | TDBadge | 橙色,条件:`Comment.CreateTime > COALESCE(LastViewedTime,'1900-01-01')` 且评论者≠本人 | ##### 卡片交互 | 状态/角色 | 操作 | 行为 | |----------|------|------| | 任意 | 点击 | → 详情页 `/outing-log/detail/:id` | | 本人 draft | 左滑 | `[编辑]` `[删除]` | | completed | 左滑无反应 | — | > 经理增量:TDChip 范围切换(同页面 6),卡片追加业务员姓名。 --- #### 页面 18:外勤日志详情 (`/outing-log/detail/:id`) | 区域 | 组件 | 说明 | |------|------|------| | 微缩地图 | 静态地图 | 点击→MethodChannel 唤醒原生导航 | | 基本信息 | TDDescription | 业务员/部门/客户名/签到地址/签到时间 | | 工作总结 | Text | 完整正文 | | 后续计划 | Text | 后续推进计划 | | 照片墙 | TDUpload | 带防伪水印照片,点击全屏预览 | | 点评区 | TDList | 按时间升序气泡样式展示。员工端只读 | | 底部(经理) | TDRate + TDInput | 星级评分 1-5 星 + 文字点评 + 发送按钮 | ##### 页面交互 | 操作 | 行为 | |------|------| | 进入详情 | 无感 `PUT /api/oa/outing-log/:id/view`,更新 LastViewedTime,列表"新点评"红点消失 | | 经理点评 | 【经理专属】点选星级+输入文字→发送→气泡追加。写入 OutingLogComment,同步更新 OutingLog.UpdateTime | --- ## 4. 行政公告模块(3 页) #### 页面 19:公告列表 (`/announcement/list`) ##### 页面结构 | 区域 | 组件 | 说明 | |------|------|------| | 导航栏 | TDNavbar | 标题"公司公告" | | 类型筛选 | TDTabBar | 全部 / 通知公告 / 人事与制度 / 放假与活动。管理员额外显示"我的草稿"Tab | | 列表 | TDListView | 排序:置顶优先→未过期按发布时间倒序→已过期置灰。数据来源 OA 本地 Announcement 表 | | 空状态 | TDEmpty | "暂无行政公告" | ##### 列表卡片 | 元素 | 组件 | 说明 | |------|------|------| | 标题 | Text | 粗体 | | 类型标签 | TDTag | 通知/制度/活动 | | 部门 | Text | 发布部门(调 `GET /api/user/{publisherId}`) | | 时间 | Text | MM-DD HH:mm | | 未读标记 | TDBadge | 红点,AnnouncementReadLog.IsRead=0 时显示 | | 已过期 | Text | 卡片整体置灰 + 标题末尾标注"已过期" | > 不支持搜索。点击卡片→详情页。返回列表后红点消失。 --- #### 页面 20:公告详情 (`/announcement/detail/:id`) ##### 页面结构 | 区域 | 组件 | 说明 | |------|------|------| | 标题 | Text | 大标题,红头文件样式 | | 发布信息 | Text | 发布部门 / 发布时间 | | 正文 | WebView | HTML/Markdown 渲染 | | 附件 | TDList | 点击→原生下载管理器打开。空→整区隐藏。来源 Attachment (BizType='announcement') | | 已过期横幅 | TDBanner | 红色"该公告已于 YYYY-MM-DD HH:mm 过期" | ##### 页面交互 | 操作 | 行为 | |------|------| | 停留≥2s | 无感 `POST /api/oa/announcement/:id/read`,AnnouncementReadLog.IsRead=1 | | <2s 返回 | 不发送已读请求,红点保留 | | 返回列表 | 已读公告红点消失 | ##### 管理员增量 | 区域 | 组件 | 说明 | |------|------|------| | 已读/未读统计 | TDChip ×2 | `[已读 N 人]`(绿)/ `[未读 N 人]`(灰)。点击展开员工列表(头像+部门) | | DING 催办 | TDButton | 点击→震动反馈→封装未读 UserIds→MethodChannel 强推 Push。Toast"已向 N 名未读员工发送催办通知"。更新 `IsUrged=1` | --- #### 页面 21:公告发布 (`/announcement/create`)【管理员专属】 | 区域 | 组件 | 说明 | |------|------|------| | 导航栏 | TDNavbar | 标题"发布公告",右侧 `[预览]` 按钮 | | 标题 | TDInput | 必填 | | 分类 | TDPicker | notice(通知)/policy(制度)/activity(活动) | | 正文 | TDRichText | 加粗/斜体/下划线/列表/图片/链接/字号 H1-H3 | | 附件 | TDUpload | 最多 5 个,PDF/图片/Word/Excel,单文件≤20MB | | 置顶 | TDSwitch | 默认关闭,对应 DB `IsTop` | | 有效期 | TDDatePicker | 可选,不填永不过期,对应 DB `ExpiryDate` | | 接收范围 | TDDrawer | 点击→右侧滑出:①全员(默认)②按部门(部门树多选,TDCheckbox)③按指定用户(员工搜索多选)。底部实时统计覆盖人数。对应 DB `PrivateLevel` + `AnnouncementTarget` | | 按钮 | 行为 | |------|------| | `[存为草稿]` | Status='draft',仅创建者+管理员可见 | | `[预览]` | TDDialog 全屏模拟详情页效果 | | `[发布]` | TDDialog 确认→Status='published'→异步写入 AnnouncementReadLog→Toast | --- ## 5. 报表模块(5 页) > 入口:工作台金刚区报表区域(5 个独立入口)。每个报表独立页面,独立路由,独立加载数据。筛选条件在页面顶部,下方为数值卡片 + 趋势图(fl_chart)。角色数据范围:员工=本人、经理=本部门、财务/管理员=全公司。预置时间段缓存 5min,自定义时间段实时查询。 --- #### 页面 22:事前申请明细报表 (`/report/expense-apply-detail`) **页面结构** | 区域 | 组件 | 说明 | |------|------|------| | 时间筛选 | TDChip + TDDatePicker | 快捷按钮(本月/本季/本年)+ 自定义起止日期 | | 状态筛选 | TDPicker | 全部 / 已通过 / 已拒绝 / 已撤回 | | 数值卡片 | TDCard ×4 | 累计申请总额(年初至今)/ 当月笔数 / 已通过笔数 / 已通过金额。仅展示不可点击,空→¥0.00 | | 趋势图 | fl_chart 双折线 | 近 12 月申请金额 vs 已通过金额对比。长按→tooltip(日期+数值),水平滑动 | | 数据来源 | — | OA 本地 ExpenseApplication 表,.NET 按角色+时间聚合 | **角色差异** | 角色 | 图表类型 | 明细列表 | 导出 | |------|---------|:--:|:--:| | 员工 | 个人双折线 | ❌ | ❌ | | 经理 | 部门横向对比柱状图(每人两根柱:申请/已通过) | ✅ | ❌ | | 财务/管理员 | 全公司趋势图 | ✅ | ✅ Excel | --- #### 页面 23:费用报销明细报表 (`/report/expense-detail`) **页面结构** | 区域 | 组件 | 说明 | |------|------|------| | 时间筛选 | TDChip + TDDatePicker | 同页面 22 | | 状态筛选 | TDPicker ×2 | 审批状态(全部/已通过/已拒绝)+ 付款状态(全部/待付款/已付款) | | 数值卡片 | TDCard ×4 | 累计核销总额(年初至今)/ 当月笔数 / 待审批笔数 / 待付款笔数 | | 趋势图 | fl_chart 双折线 | 近 12 月报销金额 vs 审批通过金额对比 | | 数据来源 | — | OA 本地 Expense 表,审批状态通过 ERP 实时查询 | **角色差异** | 角色 | 图表类型 | 明细列表 | 导出 | |------|---------|:--:|:--:| | 员工 | 个人双折线 | ❌ | ❌ | | 经理 | 部门横向对比柱状图 | ✅ | ❌ | | 财务/管理员 | 全公司趋势图 | ✅ | ✅ Excel | --- #### 页面 24:加班明细报表 (`/report/overtime-detail`) **页面结构** | 区域 | 组件 | 说明 | |------|------|------| | 时间筛选 | TDChip + TDDatePicker | 同页面 22 | | 加班类型 | TDPicker | 全部 / 工作日 / 休息日 / 节假日 | | 数值卡片 | TDCard ×4 | 当月净工时(h)/ 当月次数 / 累计调休小时 / 加班费结算次数 | | 趋势图 | fl_chart 堆叠柱状图 | 近 12 月加班工时,按类型(工作日/休息日/节假日)分色堆叠 | | 数据来源 | — | OA 本地 Overtime 表 | **角色差异** | 角色 | 图表类型 | 明细列表 | 导出 | |------|---------|:--:|:--:| | 员工 | 个人堆叠柱状图 | ❌ | ❌ | | 经理 | 部门横向对比柱状图(每人汇总工时) | ✅ | ❌ | | 财务/管理员 | 全公司趋势图 | ✅ | ✅ Excel | --- #### 页面 25:用车明细报表 (`/report/vehicle-detail`) **页面结构** | 区域 | 组件 | 说明 | |------|------|------| | 时间筛选 | TDChip + TDDatePicker | 同页面 22 | | 车辆筛选 | TDPicker | 全部 / 按车牌筛选 | | 用途筛选 | TDPicker | 全部 / 接待 / 商务 / 公务 | | 数值卡片 | TDCard ×4 | 当月次数 / 累计里程(km)/ 路桥停车费 / 未还车数量 | | 趋势图 | fl_chart 双轴折线 | 近 12 月用车次数(左轴)vs 累计费用(右轴) | | 数据来源 | — | OA 本地 Vehicle 表 | **角色差异** | 角色 | 图表类型 | 明细列表 | 导出 | |------|---------|:--:|:--:| | 员工 | 个人双轴折线 | ❌ | ❌ | | 经理 | 部门横向对比柱状图(每人次数/费用) | ✅ | ❌ | | 财务/管理员 | 全公司双轴折线 | ✅ | ✅ Excel | --- #### 页面 26:外勤日志明细报表 (`/report/outing-log-detail`) **页面结构** | 区域 | 组件 | 说明 | |------|------|------| | 时间筛选 | TDChip + TDDatePicker | 同页面 22 | | 客户筛选 | TDSearchBar | 输入客户名模糊搜索 | | 数值卡片 | TDCard ×4 | 当月拜访次数 / 拜访客户数(去重)/ 平均评分(⭐)/ 未点评日志数 | | 趋势图 | fl_chart 双轴折线 | 近 12 月拜访次数(左轴)vs 平均评分(右轴) | | 数据来源 | — | OA 本地 OutingLog 表 LEFT JOIN OutingLogComment | **角色差异** | 角色 | 图表类型 | 明细列表 | 导出 | |------|---------|:--:|:--:| | 员工 | 个人双轴折线 | ❌ | ❌ | | 经理 | 部门横向对比柱状图(每人次数/评分) | ✅ | ❌ | | 财务/管理员 | 全公司双轴折线 | ✅ | ✅ Excel | > **经理版交互增强**:点击柱状图柱体→下方列表联动过滤该员工本月单据→可穿透跳转对应详情页。适用于页面 22~26 所有报表。 --- ## 6. 全局设计规范 #### 6.1 色彩体系 | Token | 值 | 用途 | |-------|------|------| | `--primary` | `#00ABF3` | 主按钮/激活态/高亮 Chip/链接 | | `--primary-light` | `#E6F7FD` | 主色浅底 | | `--primary-active` | `#0089C4` | 主色按压态 | | `--success` | `#00A870` | 已通过/同意/金额正面 | | `--warning` | `#E37318` | 审批中/超支警告/排期冲突 | | `--danger` | `#D54941` | 已拒绝/拒绝/删除/强制终止 | | `--text-primary` | `#1A1A1A` | 标题/关键金额 | | `--text-secondary` | `#666666` | 摘要/辅助说明/时间戳 | | `--text-placeholder` | `#BFBFBF` | 占位符/禁用文字 | | `--bg-page` | `#F5F5F5` | 页面背景 | | `--bg-card` | `#FFFFFF` | 卡片/表单底色 | | `--border` | `#E7E7E7` | 分割线/描边/输入框边框 | | `--status-gray` | `#999999` | 草稿/已撤回/已过期 | | `--bg-disabled` | `#EEEEEE` | 禁用按钮/输入框背景 | | `--text-disabled` | `#BFBFBF` | 禁用态文字(复用 `--text-placeholder`) | #### 6.2 字号层级 | Token | 字号 | 行高 | 用途 | |-------|------|------|------| | `--fs-title` | 18sp | 26px | 导航栏标题/详情大标题 | | `--fs-subtitle` | 16sp | 24px | 卡片标题/表单分组/金额大字/按钮 | | `--fs-body` | 14sp | 22px | 正文/列表摘要/输入框/Chip | | `--fs-caption` | 12sp | 18px | 辅助说明/时间戳/状态标签/红点数 | #### 6.3 间距系统 | Token | 值 | 用途 | |-------|------|------| | `--space-xs` | 4px | 图标与文字间距/Chip 内边距 | | `--space-sm` | 8px | 列表项内 padding/表单行间距 | | `--space-md` | 16px | 卡片内边距/页面左右边距 | | `--space-lg` | 24px | 表单分组间距/卡片间距 | | `--space-xl` | 32px | 页面顶部/底部留白 | #### 6.4 空状态 | 场景 | 文案 | |------|------| | 消息列表为空 | "暂无消息通知" | | 申请列表为空 | "暂无记录,点击下方按钮发起申请" | | 审批列表为空 | "暂无待审批单据" | | 报销明细为空 | "暂无报销明细,请先添加费用明细" | | 照片墙为空 | "暂无附件" | | 搜索无结果 | "未找到匹配的员工,试试其他关键词" | | 公告列表为空 | "暂无行政公告" | | 报表无数据 | "所选时间范围内暂无数据" | | 导入事前申请为空 | "暂无可用的事前申请,请确认已有审批通过的申请" | | 下属审批为空 | "暂无下属提交的审批单据" | | 附件上传已满 | "上传数量已达上限" | | 车辆池为空 | "暂无可用车辆,请联系管理员添加" | #### 6.5 加载态 | 场景 | 方式 | |------|------| | 页面首次加载 | TDSkeleton 骨架屏(最长 8s 超时转网络异常态) | | 下拉刷新 | RefreshIndicator | | 上拉加载更多 | 底部菊花 + "加载中..." | | 按钮提交中 | 按钮替换为 TDLoading 小菊花 + 禁用态 | | 附件上传中 | 缩略图叠加半透明蒙层 + 中心菊花 | | 一键导出中 | 圆形悬浮按钮旋转 + "导出中..." | #### 6.6 网络异常态 | 场景 | 处理 | |------|------| | 列表加载失败 | TDEmpty + 断网图标 + `[点击重试]` | | 提交失败 | TDToast(红)"提交失败,请稍后重试" | | 接口超时(>15s) | TDEmpty + 时钟图标 + `[点击重试]`"请求超时" | | 服务端 500 | TDToast"服务器繁忙,请稍后重试" | | 401 未授权 | 静默触发宿主登录流程 | #### 6.7 并发冲突 | 场景 | 处理 | |------|------| | 编辑草稿时单据已被他人提交 | `CONCURRENCY_CONFLICT`→TDDialog"已被修改或删除"→返回列表刷新 | | 审批时单据已被他人处理 | `APPROVAL_CONFLICT`→详情页自动刷新+Toast"状态已更新" | #### 6.8 全局交互 - **横竖屏**:仅支持竖屏 - **键盘**:聚焦时页面上移;金额类弹数字键盘;文本类弹默认键盘 - **返回手势**:iOS 边缘右滑;Android 系统返回键;表单有未保存修改时拦截确认 - **Deep Link**:`tboss://oa/{path}` → GoRouter 路由 - **字体缩放**:sp 单位,最小 11sp,导航栏标题不溢出 - **下拉刷新**:列表页顶部下拉触发 `RefreshIndicator`,重置 page=1 重新加载,刷新完成后短暂展示"已更新"提示 #### 6.9 圆角规范 | Token | 值 | 用途 | |-------|------|------| | `--radius-sm` | 4px | Chip / Tag / 小按钮 / 输入框 | | `--radius-md` | 8px | 卡片 / 大按钮 / 列表项 | | `--radius-lg` | 12px | 对话框 / 抽屉 / 底部弹出面板 | | `--radius-round` | 999px | 胶囊按钮 / 头像 / 状态圆点 | #### 6.10 阴影层级 | Token | 值 | 用途 | |-------|------|------| | `--shadow-none` | `none` | 平面/无阴影 | | `--shadow-card` | `0 2px 8px rgba(0,0,0,0.08)` | 卡片/列表项 | | `--shadow-fab` | `0 4px 16px rgba(0,0,0,0.12)` | 悬浮按钮/底部操作栏/导航栏 | | `--shadow-drawer` | `-4px 0 20px rgba(0,0,0,0.15)` | 右侧抽屉/半屏面板 | #### 6.11 动画时间规范 | Token | 值 | 用途 | |-------|------|------| | `--duration-fast` | 150ms | 按压反馈/hover 响应/Tag 关闭 | | `--duration-normal` | 300ms | 页面过渡/图表数据刷新/ScrollTo 滚动/红闪消失 | | `--duration-slow` | 500ms | 抽屉滑出/卡片展开收起/淡入淡出 | | `--easing-standard` | `cubic-bezier(0.4, 0, 0.2, 1)` | 标准缓动曲线,用于所有过渡动画 | > **应用示例**:图表刷新间隔统一用 `--duration-normal`(300ms);表单校验失败红闪 2s 后淡出用 `--duration-slow`;按钮按下态用 `--duration-fast`;骨架屏超时阈值 8s(见 §6.5)。 #### 6.12 导航栏标题清单 | 页面 | 路由 | 标题 | |------|------|------| | 1 | `/` | —(Appshell) | | 2 | `/messages` | "消息通知" | | 3 | `/home` | "工作台" | | 3.1 | `/profile` | "我的" | | 3.2 | `/admin/permissions` | "权限管理" | | 4 | `/expense-apply/apply` | "事前申请" | | 5 | `/expense/apply` | "费用报销" | | 6 | `/expense-apply/list` | "申请记录" | | 7 | `/expense/list` | "报销记录" | | 8 | `/expense-apply/detail/:id` | "申请详情" | | 9 | `/expense/detail/:id` | "报销详情" | | 10 | `/overtime/apply` | "加班申请" | | 11 | `/overtime/list` | "加班记录" | | 12 | `/overtime/detail/:id` | "加班详情" | | 13 | `/vehicle/apply` | "用车申请" | | 14 | `/vehicle/list` | "用车记录" | | 15 | `/vehicle/detail/:id` | "用车详情" | | 16 | `/outing-log/create` | "外勤日志" | | 17 | `/outing-log/list` | "外勤记录" | | 18 | `/outing-log/detail/:id` | "日志详情" | | 19 | `/announcement/list` | "公司公告" | | 20 | `/announcement/detail/:id` | "公告详情" | | 21 | `/announcement/create` | "发布公告" | | 22 | `/report/expense-apply-detail` | "事前申请明细报表" | | 23 | `/report/expense-detail` | "费用报销明细报表" | | 24 | `/report/overtime-detail` | "加班明细报表" | | 25 | `/report/vehicle-detail` | "用车明细报表" | | 26 | `/report/outing-log-detail` | "外勤日志明细报表" | --- > **文档版本**:v1.0 | 日期:2026-06-04