tboss-oa-interactions.md 30 KB

TBOSS OA 模块 — 交互设计

版本:v1.0 | 日期:2026-06-03 | 基于 tboss-oa-product-strategy.md

覆盖 27 个页面的所有可交互元素及其操作逻辑。数据源标注遵循 v2.0 架构(审批走 ERP、用户/组织/客户走 ERP、消息走 .NET 服务端、权限走 OA ACL)。


1. 全局数据源

数据 来源 说明
用户信息(姓名/部门/岗位/头像) .NET GET /api/user/{id} 非本地表
组织架构树 .NET GET /api/dept/tree 非本地表
客户数据 .NET GET /api/customer/search?q= 非本地表
审批流程(状态/时间线/待办) .NET GET/POST /api/oa/approval/* 服务端转发 ERP
消息通知 .NET 消息模块 API 服务端已有模块
OA 权限 本地 OaUserPermission JOIN OaPermission OA 自管
业务单据 本地 OA 业务表 OA 自管
车辆池 本地 SysVehicle OA 自管
费用类别 本地 SysCostCategory OA 自管
轮播图 本地 SysBanner OA 自管
银行列表 .NET GET /api/dict/banks 服务端字典

2. 页面跳转关系总图

/ (Appshell)
├─ /messages ──────────────────────────────────────────────────────
│   └─ (点击) → /announcement/detail/:id
│            → /expense-apply/detail/:id  /expense/detail/:id
│            → /overtime/detail/:id       /vehicle/detail/:id
│
├─ /home ──────────────────────────────────────────────────────────
│   ├─ (轮播图) → 公告/活动链接 或 全屏预览
│   ├─ (金刚区-发起) → /expense-apply/apply  /expense/apply
│   │                → /vehicle/apply         /overtime/apply
│   ├─ (金刚区-记录) → /expense-apply/list    /expense/list
│   │                → /outing-log/list       /announcement/list
│   ├─ (看板) → /expense-apply/list  /report/expense-detail  /messages
│
└─ /profile
    ├─ 审批历史 → (子页面) → 各详情页
    ├─ 我的报表 → (子页面) → /report/.. (5 Tab)
    └─ 关于 → (子页面)

表单页 ──(存草稿/提交)──→ 列表页 ──(点击卡片)──→ 详情页
    ↑                         │                    │
    └──(左滑编辑/draft编辑)───┘  (rejected→重新编辑)┘

/admin/permissions  (管理员)
/announcement/create (管理员)

3. 页面详细交互

页面 4.0:借款/备用金表单 (/loan/apply)

元素 事件 行为 数据来源
借款类型 TDPicker 选择 备用金/差旅借款 Loan.LoanType
借款金额 TDInput 输入 纯数字 Loan.Amount
借款事由 TDTextarea 输入 Loan.Purpose
[存为草稿]/[提交审批] 点击 复用标准逻辑,提交调 POST /api/oa/loan/submit

页面 4.0a:借款列表 (/loan/list)

元素 事件 行为 数据来源
TDChip(全部/草稿/审批中/已通过/已拒绝/已撤回) 点击 标准筛选 ApprovalStatus 缓存
卡片额外展示 还款状态标签(未还/部分已还/已还清/已核销) Loan.RepaymentStatus
已通过+未还清卡片左滑 手势 [登记还款] → 选还款方式+金额 → POST /api/oa/loan/repay

页面 4.0b:借款详情 (/loan/detail/:id)

已通过且未还清的借款底部展示还款记录列表(LoanRepayment 按时间倒序)。


页面 1:Appshell 底部导航 (/)

元素 事件 行为 数据来源
消息 Tab 点击 路由 → /messages,图标变 #00ABF3
消息 Tab 角标 数据绑定 未读消息数;进入时拉取,30s 轮询或 Push 刷新 .NET 消息模块 API
工作台 Tab 点击 路由 → /home
我的 Tab 点击 路由 → /profile
当前激活 Tab 重复点击 若含列表 → ScrollToTop

页面 2:消息通知聚合页 (/messages)

元素 事件 行为 数据来源
导航栏标题 "消息通知"
"全部已读" 点击 仅未读>0 时显示;调用 API,红点淡出,按钮消失 .NET 消息模块 API
消息卡片(公告类) 点击 /announcement/detail/:id MsgType='announcement'
消息卡片(审批待办) 点击 按 BizType 路由 → 对应详情页,底部展审批操作栏 BizType 决定路由
消息卡片(审批结果) 点击 按 BizType 路由 → 对应详情页 BizType 决定路由
已读消息卡片 透明度 0.6,无红点,不可左滑 IsRead=1
未读卡片-左滑 手势 滑出 [标记已读](蓝) + [删除](红)
[标记已读] 点击 成功→红点淡出+透明度↓;失败→Toast"操作失败,请重试" .NET 消息模块 API
[删除] 点击 TDDialog 确认 → 卡片收起 .NET 消息模块 API
列表 下拉/上拉 刷新 page=1 / page++ 追加 .NET 消息模块 API
空列表 TDEmpty + 铃铛:"暂无消息通知"

页面 3:工作台 (/home)

角色判定(决定工作台变体):查 OaUserPermission

  • oa.admin.* → 管理员版
  • 无 admin 但有 oa.expense.mark_paid → 财务版
  • 无上述但有 oa.*.approveoa.*.view_dept → 经理版
  • 其余 → 员工版

员工版

元素 事件 行为 数据来源
轮播图 自动/点击 3s 切换;有 LinkUrl→跳转,无→全屏预览(双指缩放) SysBanner (IsActive=1, IsDeleted=0)
金刚区-事前申请 点击 /expense-apply/apply
金刚区-费用报销 点击 /expense/apply
金刚区-用车申请 点击 /vehicle/apply
金刚区-加班申请 点击 /overtime/apply
金刚区-申请记录 点击 /expense-apply/list(默认"全部")
金刚区-报销记录 点击 /expense/list
金刚区-外勤日志 点击 /outing-log/list
金刚区-公司公告 点击 /announcement/list
看板-已提单据 点击 /expense-apply/list .NET 预计算(缓存 5min)
看板-本月报销 点击 /report/expense-detail .NET 预计算
看板-待处理 点击 /messages(筛选 approval_notice) .NET 预计算
页面整体 下拉 强制穿透缓存刷新

经理版增量

元素 事件 行为 数据来源
待审批卡片 TDBadge 红色数字展示待办件数 GET /api/oa/approval/pending-count
待审批卡片 点击 /messages(筛选 approval_notice)

财务版增量

元素 事件 行为 数据来源
财务看盘卡片 已支付流水/待付款总额/异常退回数 .NET 全公司聚合查询

页面 3.1:个人中心 (/profile)

元素 事件 行为 数据来源
头像 TDAvatar 点击 唤起相册/相机→裁剪(1:1,≤2MB)→上传→全局刷新 PUT /api/user/avatar → .NET → ERP
个人信息卡片 姓名/部门/岗位 GET /api/user/{erpUserId}
我的审批历史 点击 → 子页面
我的报表 点击 → 子页面(5 Tab)
关于 点击 → 版本号/用户协议/隐私政策

子页面:我的审批历史

元素 事件 行为 数据来源
单据卡片-编号 点击 按 BizType 跳转详情页 GET /api/oa/approval/my-history
列表 下拉/上拉 刷新/加载更多 同上
空列表 TDEmpty:"暂无审批记录"

页面 4:事前申请表单 (/expense-apply/apply)

元素 事件 行为 数据来源
申请人姓名 只读 GET /api/user/{erpUserId} → RealName
所属部门 只读 GET /api/user/{erpUserId} → DeptName
申请日期 只读,DateTime.now(),YYYY-MM-DD
紧急程度 TDRadioGroup 选择 普通/紧急/特急,默认"普通" ExpenseApplication.Urgency
费用类型 TDCheckboxGroup 多选 至少一项,联动过滤科目候选 ExpenseApplication.ExpenseTypes
费用事由 TDTextarea 输入 ≤200 字 ExpenseApplication.Purpose
关联项目 TDPicker 级联 一级→ProjectService;二级→SubjectService ExpenseApplication.ProjectId
预算科目 TDPicker 选择 选定后调 BudgetService 加载可用余额 ExpenseApplication.BudgetSubjectId
预算余额 只读 ¥XXXX.xx,ERP 无预算→隐藏区块 .NET → ERP BudgetService
预估金额 TDInput 输入 纯数字键盘;汇总超预算→变红+警告 ExpenseAppDetail.EstimatedAmount
[+ 添加费用明细] 点击 展开新卡片,页面滚动聚焦
明细卡片 ✕ 点击 气泡确认→折叠消失
附件上传 [+] 点击 相册/相机/文件;≤10MB(图)/≤20MB(PDF) Attachment(BizType='expense_apply')
附件缩略图 点击 黑底全屏预览,双指缩放(0.5x~3x),左右滑动
附件 ⊖ 点击 气泡确认→删除服务器文件
PDF 附件 点击 原生 PDF 查看器
[重置] 点击 仅编辑草稿时可见;确认弹窗→清空
[存为草稿] 点击 Loading → PUT → Toast 绿→跳列表(激活"草稿"Chip) ExpenseApplication (Status='draft')
[提交审批] 点击 校验→ScrollTo+红闪+TDMessage → Loading → POST → .NET → ERP 创建实例 → 存 ApprovalInstanceId → Toast → 跳列表 .NET POST /api/oa/expense-apply/submit
返回(有未保存修改) 点击 TDDialog:"是否退出?"

页面 5:费用报销表单 (/expense/apply)

元素 事件 行为 数据来源
[导入事前申请] 点击 半屏多选抽屉:approved 且尚有额度的申请,每条填导入金额;可追加多条;空→TDEmpty .NET API → ExpenseApplication (Status='approved', UsageStatus IN unused/partially_used)
对公/对私 TDSwitch 切换 personal→收款人账户;corporate→供应商名称+对公账户 Expense.PaymentType
报销事由 输入 可导入回填或手工 Expense.Purpose
成本中心 TDPicker 选择 可空 .NET → ERP CostCenterService
报销总金额 只读,明细累加上浮动画 Expense.TotalAmount
开户行/户名/账号 输入 对私展示;前端校验账号 16-19 位 Expense.BankName/AccountName/BankAccount
供应商名称/账户 输入 对公展示 Expense.SupplierName
币种 TDPicker 选择 默认 CNY,选外币→自动从 ERP 填汇率 ExpenseDetail.CurrencyCode/ExchangeRate
费用类别 TDPicker 选择 叶子节点 SysCostCategory
原币金额/本币金额 输入/只读 原币×汇率=本币(服务端算) ExpenseDetail.Amount/BaseAmount
分摊设置 输入 比例+目标部门/项目;不分摊留空 ExpenseDetail.AllocationPercent/AllocationDeptId/AllocationProjectId
借款冲销 提交时 .NET 查未还借款→弹窗确认冲销明细 GET /api/oa/loan/outstanding
[+ 添加费用明细] 点击 平滑展开新卡片
明细行 ✕ 点击 气泡确认→折叠
发票上传 [+] 点击 相册/相机,≤10MB,满 9 隐藏;可绑定明细行 Attachment(BizType='expense')
发票缩略图 点击 黑底全屏预览
[存为草稿]/[提交审批] 点击 复用页面 4 逻辑
返回(有修改) 点击 复用页面 4 逻辑

页面 6/7:事前申请/费用报销列表页

元素 事件 行为 数据来源
导航栏 "申请记录" / "报销记录"
TDChip(全部/草稿/审批中/已通过/已拒绝/已撤回) 点击 高亮 #00ABF3,列表淡入淡出刷新;无数据→TDEmpty(文案随 Chip) ApprovalStatus 缓存
列表 下拉/上拉 刷新/追加 本地 OA 表 + 后台静默刷新 ApprovalStatus
卡片空白区 点击 → 详情页
卡片左滑-[编辑] 点击 仅 draft/rejected → 表单编辑态
卡片左滑-[删除] 点击 仅 draft/rejected → TDDialog 确认 → 软删除
StatusTag 仅展示(灰/橙/绿/红/灰)

经理版增量

元素 事件 行为 数据来源
范围标签 [我的发起] 点击 员工版逻辑
范围标签 [下属审批] 点击 骨架屏→加载部门下属单据 GET /api/oa/approval/subordinates
下属卡片左滑-[一键同意] 点击 仅 pending;绿色按钮,就地审批 POST /api/oa/approval/action

财务版增量(仅页面 7):

元素 事件 行为 数据来源
[待付款] Chip 点击 筛选 Status='approved' AND PaymentStatus='unpaid' 本地 Expense 表
卡片左滑-[线下已付款] 点击 标记 PaymentStatus='paid' 本地 Expense 表

页面 8/9:事前申请/费用报销详情页

员工版

元素 事件 行为 数据来源
状态横幅 图标 + 状态中文 + 当前审批人姓名 ApprovalStatus + 审批人姓名从 .NET API 获取
提交时间 YYYY-MM-DD HH:mm CreateTime
费用明细"展开全部" 点击 >5 行时显示;平滑展开 本地子表
附件缩略图 点击 黑底全屏预览 本地附件表
审批时间线 纵向时间线渲染 GET /api/oa/approval/timeline?bizType=&bizId= → .NET → ERP
时间线节点 点击 当前用户待审批→弹出审批操作;否则→展开详情
审批人姓名/头像 点击 TDDialog 展示基本信息卡片 GET /api/user/{approverId}
[编辑](draft) 点击 → 表单编辑态
[提交审批](draft) 点击 校验→提交;失败→TDDialog 引导 POST /api/oa/approval/action?action=submit
[撤回申请](pending) 点击 TDDialog 确认 → Status='withdrawn' → 旧 instanceId 追加到 PreviousInstanceIds POST /api/oa/approval/withdraw
[重新编辑并发起](rejected) 点击 → 表单编辑态;提交后更新原记录+旧审批链失效

经理版底部操作栏(pending 状态 + 当前审批人=该经理)

元素 事件 行为 数据来源
[拒绝] 点击 TDDialog 输入理由(≥5 字解锁)→ POST POST /api/oa/approval/action {action: reject}
[转交] 点击 MethodChannel 唤起通讯录单选 → POST POST /api/oa/approval/action {action: transfer}
[同意] 点击 Loading → POST → 节点变绿 → 流转 POST /api/oa/approval/action {action: approve}
风控参考看板 申请人本月同类单据数 + 预算消耗进度条 本地查询 + .NET 转发 ERP

管理员版底部操作栏

元素 事件 行为
[强制终止] 点击 TDDialog 确认 → Status='withdrawn' + 写入终止原因
[查看审批链] 点击 展开完整审批历史(含历史 instanceId 的流程)

财务版增量(仅页面 9)

元素 事件 行为 数据来源
合规复选框 ×3 勾选 全部勾选→解锁 [确认打款] 按钮 Expense.IsInvoiceVerified/IsTaxIdMatched/IsCategoryCompliant
[退回修改] 点击 选退回节点(员工/经理)→状态倒流 .NET API
[确认已线下打款并归档] 点击 解锁后;滑出凭证表单(电汇流水号+记账凭证号必填)→提交→Paid Expense.BankTransferNo + VoucherNo
[下一笔待付款] 点击 归档后替换显示;跳转下一条 approved+unpaid;无→"已无待付款"

页面 10:加班申请表单 (/overtime/apply)

元素 事件 行为 数据来源
加班类型 TDPicker 选择 工作日/休息日/节假日,默认"工作日";节假日标注费率 Overtime.OtType
补偿方式 TDRadio 选择 转调休/结算加班费/混合,默认"转调休" Overtime.CompensationType
混合模式 TDSlider 拖动 10%~90%,步长 10%;右侧实时比例文案 Overtime.CompLeaveRatio
开始/结束时间 点击 TDDatePicker 年月日时分;确认后自动算净工时(扣除 12:00-13:00/18:00-18:30) Overtime.StartTime/EndTimeNetOtHours
净工时卡片 只读大字;≤0→变红+提交按钮置灰 Overtime.NetOtHours
开始>结束校验 边框变红+提示+提交按钮置灰
加班原因 TDTextarea 输入 Overtime.Reason
[存为草稿]/[提交审批] 点击 复用页面 4 逻辑;提交时 .NET 创建 ERP 审批实例
返回(有修改) 点击 复用页面 4 逻辑

页面 11:加班列表 / 页面 12:加班详情

交互模式同页面 6/7 和 8/9。加班类型标签(工作日/休息日/节假日)、补偿方式展示(加班费/转调休/"X%调休+Y%结算")。员工端仅 [撤回]


页面 13:用车申请表单 (/vehicle/apply)

元素 事件 行为 数据来源
车牌号 TDPicker 选择 全公司车池;冲突车辆标红"冲突";无可用→TDEmpty SysVehicle (IsDeleted=0)
车牌+出车/还车时间 失焦 异步排期冲突检测;冲突→红色文本+锁死提交按钮 Vehicle (Status IN pending,approved)
用车事由 输入 Vehicle.Reason
始发地 定位/输入 原生定位匹配 Vehicle.Origin + 经纬度
目的地+地图图标 输入/点击 MethodChannel 唤醒地图选点→回填地址+经纬度 Vehicle.Destination + 经纬度
出车/还车时间 点击 TDDatePicker 年月日时分 Vehicle.StartTime/EndTime
还车>出车校验 否则红色提示+按钮置灰
同行总人数 输入 纯数字,0→1 Vehicle.PassengerCount
随行同行人 [+] 点击 MethodChannel 唤醒通讯录多选→胶囊标签;取消→无变化 VehiclePassenger
胶囊标签 x 点击 剔除人员
[存为草稿]/[提交审批] 点击 复用页面 4 逻辑

页面 14:用车列表 / 页面 15:用车详情

元素 事件 行为 数据来源
TDChip(全部/草稿/审批中/已通过/已拒绝/已撤回/已还车) 点击 标准逻辑 ApprovalStatus 缓存
卡片左滑-[编辑]/[删除] 点击 仅 draft/rejected
卡片左滑-[确认还车] 点击 仅 approved;拉起半屏核销抽屉
微缩地图 点击 唤醒原生地图导航 本地经纬度
[确认还车并登记] 点击 滑出核销抽屉:实还时间/出车前里程/还车后里程/费用备注 Vehicle 还车字段
还车里程校验 还车后 ≥ 出车前,否则按钮置灰+红提示
确认提交还车 点击 TDDialog 确认→Status='returned'→页面刷新

页面 16:外勤日志创建 (/outing-log/create)

元素 事件 行为 数据来源
GPS 定位区 页面初始化 强制高精度 GPS → ReadOnly 展示地址;精度>100m→黄色警告 MethodChannel → OutingLog.CheckIn*
GPS 定位失败 TDEmpty"无法获取当前位置";提交按钮置灰
客户名称 TDInput 输入 自动联想;无匹配→自由文本(提交时 .NET 自动创建 ERP 客户) GET /api/customer/search?q=
工作总结 TDTextarea 输入 OutingLog.VisitSummary
后续计划 输入 OutingLog.NextPlan
现场拍照 点击 跳过相册,直接相机;水印=服务器授时+GPS;最少1张最多4张 Attachment(BizType='outing_log')
相机权限被拒 TDDialog + "前往设置"
[存为草稿]/[提交] 点击 校验 GPS+照片≥1
返回(有修改) 点击 复用页面 4 逻辑

页面 17:外勤日志列表 / 页面 18:外勤日志详情

元素 事件 行为 数据来源
TDChip(全部/本月) 点击 切换刷新
卡片"新点评" TDBadge 橙色标记 OutingLogComment.CreateTime > COALESCE(LastViewedTime, '1900-01-01') 且评论者≠本人
卡片左滑-[编辑]/[删除] 点击 仅 draft
微缩地图 点击 唤醒原生地图导航 本地经纬度
照片墙 点击 全屏预览 Attachment(BizType='outing_log')
页面进入 无感 PUT 更新 LastViewedTime,列表"新点评"消失 PUT /api/oa/outing-log/:id/view
主管点评区(员工端) 只读浏览,不可回复 OutingLogComment

经理版增量

元素 事件 行为 数据来源
TDRate 星级 点选 1-5 星 OutingLogComment.RatingStars
点评文本框 输入 批示文字 OutingLogComment.CommentText
发送按钮 点击 气泡追加+动画 POST /api/oa/outing-log/:id/comment

页面 19:公告列表 (/announcement/list)

元素 事件 行为 数据来源
TDChip 类型筛选 点击 全部/通知公告/人事与制度/放假与活动/我的草稿(仅管理员) Announcement.Type + Status
排序规则 置顶→未过期(PublishTime DESC)→已过期(PublishTime DESC) IsTop, PublishTime, ExpiryDate
已过期卡片 整体置灰+标题末尾"已过期" ExpiryDate < NOW
未读红点 返回列表后红点消失 AnnouncementReadLog.IsRead=0
公告卡片 点击 /announcement/detail/:id
搜索 不支持

页面 20:公告详情 (/announcement/detail/:id)

元素 事件 行为 数据来源
正文 HTML/Markdown 渲染 Announcement.Content
已过期横幅 红色"该公告已于 YYYY-MM-DD HH:mm 过期" Announcement.ExpiryDate
附件图标 点击 原生浏览器/下载管理器;失败→Toast Attachment(BizType='announcement')
停留 ≥2s 无感标记已读;<2s 返回不发送 POST /api/oa/announcement/:id/read

管理员版增量

元素 事件 行为 数据来源
[已读 N 人] Chip 点击 展开已读员工列表(头像+部门) AnnouncementReadLog (IsRead=1) + .NET 用户 API
[未读 N 人] Chip 点击 展开未读员工列表 AnnouncementReadLog (IsRead=0)
[一键 DING] 点击 震动反馈→MethodChannel 强推 Push/短信 AnnouncementReadLog.IsUrged=1

页面 21~25:五大明细报表 (/report/..)

元素 事件 行为
TDDropdownMenu(本月/本季/本年) 选择 数值卡片+图表 300ms 渐变刷新
数值卡片 只读;空→0/¥0.00
fl_chart 数据点 长按 tooltip(日期+数值)
fl_chart 图表 水平滑动 查看历史数据
图表为空 TDEmpty:"所选时间范围内暂无数据"

经理版增量:柱状图柱体点击 → 下方列表联动过滤该员工本月单据 → 可穿透跳详情页。

财务版增量(仅页面 22):部门树/项目组级联筛选 + [数据流水一键导出] → 后端生成 Excel → MethodChannel 原生分享。


页面 26:公告发布 (/announcement/create)

元素 事件 行为 数据来源
公告标题 TDInput 输入 Announcement.Title
分类下拉 选择 notice/policy/activity Announcement.Type
富文本编辑域 操作 加粗/斜体/下划线/列表/图片/链接/字号 Announcement.Content
附件上传 [+] 点击 ≤5 个,PDF/图片/Word/Excel,≤20MB Attachment(BizType='announcement')
置顶 TDSwitch 切换 默认关闭 Announcement.IsTop
有效期 TDDatePicker 选择 非必填,不填永不过期 Announcement.ExpiryDate
接收范围选择器 点击 右侧滑出部门树多选(Checkbox);默认全员;底部统计人数 AnnouncementTarget
[预览] 点击 TDDialog 全屏模拟详情页
[存为草稿] 点击 保存(仅创建者+管理员可见) Announcement.Status='draft'
[发布] 点击 确认弹窗 → 写入 + 异步初始化 AnnouncementReadLog → Toast Announcement.Status='published'
返回(有修改) 点击 复用页面 4 逻辑

页面 27:权限管理 (/admin/permissions)

元素 事件 行为 数据来源
TDSearchBar 输入 300ms 防抖模糊搜索→骨架屏→刷新;无结果→TDEmpty GET /api/user/search?q=
员工列表 下拉/上拉 刷新/每页 20 条 默认按部门+姓名排序
员工卡片 点击 右侧滑出 TDDrawer 权限编辑抽屉
快捷套餐按钮 ×4 点击 一键赋予标准权限集(员工/审批人/财务/管理员) OaUserPermission
权限点复选框 勾选 逐项加减 OaUserPermission
启用/禁用 TDSwitch 切换 经理有待审批时警告确认 OA 权限状态
[确认保存] 点击 Loading → PUT → Toast + 写审计日志 OaUserPermission + OaPermissionChangeLog
【变更记录】折叠区 展开 TDTimeline 展示最近 20 条 OaPermissionChangeLog
抽屉关闭(有未保存修改) 确认弹窗"是否放弃?"
自保护 无法取消自己的 admin 权限 → Toast
最后管理员保护 后端拒绝移除最后一个 admin

4. API 端点汇总

OA 业务 API(.NET 服务端新增)

# 权限
GET    /api/oa/permissions
GET    /api/oa/user-permissions?userId=
PUT    /api/oa/user-permissions
GET    /api/oa/permission-changelog?userId=&page=

# 业务单据
POST   /api/oa/expense-apply/submit
POST   /api/oa/expense/submit
POST   /api/oa/overtime/submit
POST   /api/oa/vehicle/submit
PUT    /api/oa/{bizType}/draft
GET    /api/oa/{bizType}/list?status=&page=
GET    /api/oa/{bizType}/detail/:id
DELETE /api/oa/{bizType}/:id

# 外勤日志
PUT    /api/oa/outing-log/submit
PUT    /api/oa/outing-log/:id/view
POST   /api/oa/outing-log/:id/comment

# 审批代理
GET    /api/oa/approval/pending?userId=&bizType=&page=
GET    /api/oa/approval/pending-count?userId=
GET    /api/oa/approval/timeline?bizType=&bizId=
POST   /api/oa/approval/action
POST   /api/oa/approval/withdraw
GET    /api/oa/approval/my-history?userId=&page=
GET    /api/oa/approval/subordinates?approverId=&bizType=&page=

# 公告
POST   /api/oa/announcement/publish
POST   /api/oa/announcement/:id/read
POST   /api/oa/announcement/:id/ding
GET    /api/oa/announcement/read-stats/:id

# 报表
GET    /api/oa/report/{type}?range=&userId=
POST   /api/oa/report/expense/export

# 车辆/轮播图
GET    /api/oa/vehicles
POST   /api/oa/vehicles
PUT    /api/oa/vehicles/:id
GET    /api/oa/banners

复用已有 API

GET    /api/user/{id}
GET    /api/user/search?q=&page=
GET    /api/dept/tree
PUT    /api/user/avatar
GET    /api/customer/search?q=
GET    /api/messages?page=
GET    /api/messages/unread-count
PUT    /api/messages/:id/read
POST   /api/messages/read-all
DELETE /api/messages/:id
GET    /api/dict/banks
GET    /api/dict/cost-categories

5. 全局交互规范

5.1 空状态

场景 文案
消息列表为空 "暂无消息通知"
申请列表为空 "暂无记录,点击下方按钮发起申请"
审批列表为空 "暂无待审批单据"
搜索无结果 "未找到匹配的员工,试试其他关键词"
公告列表为空 "暂无行政公告"

5.2 加载态

场景 方式
页面首次加载 TDSkeleton 骨架屏(最长 8s 超时转网络异常态)
下拉刷新 RefreshIndicator
上拉加载更多 底部菊花 + "加载中..."
按钮提交中 按钮替换为 TDLoading 小菊花 + 禁用态
附件上传中 缩略图叠加半透明蒙层 + 中心菊花

5.3 网络异常态

场景 方式
列表加载失败 TDEmpty + 断网图标 + [点击重试]
提交失败 TDToast(红)"提交失败,请稍后重试"
接口超时(>15s) TDEmpty + [点击重试]
401 未授权 静默触发宿主登录流程

5.4 全局交互

  • 横竖屏:仅支持竖屏
  • 键盘:聚焦时页面上移;金额类弹数字键盘;文本类弹默认键盘
  • 返回手势:iOS 边缘右滑;Android 系统返回键;表单页有未保存修改时拦截确认
  • Deep Linktboss://oa/{path} → GoRouter 路由
  • 并发冲突:编辑/审批冲突 → TDDialog 提示 → 刷新
  • 字体缩放:sp 单位,最小 11sp,导航栏标题不溢出

5.5 设计 Token

Token 用途
--primary #00ABF3 主按钮/激活态/高亮/链接
--success #00A870 已通过/同意/金额正面
--warning #E37318 审批中/超支警告/冲突提示
--danger #D54941 已拒绝/拒绝/删除
--text-primary #1A1A1A 标题/关键金额
--text-secondary #666666 摘要/辅助说明
--bg-page #F5F5F5 页面背景
--bg-card #FFFFFF 卡片/表单底色
--border #E7E7E7 分割线/描边

文档版本:v1.0 | 日期:2026-06-03