基于
2026-05-30-tboss-oa-design.md和2026-05-30-tboss-oa-database.md,覆盖 27 个页面的所有可交互元素及其操作逻辑。
/ (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 ───────────────────────────────────────────────────────────────
├─ 审批历史 → (子页面) → (点击单据) → /expense-apply/detail/:id
│ → /expense/detail/:id
│ → /overtime/detail/:id
│ → /vehicle/detail/:id
├─ 我的报表 → (子页面) → /report/.. (5 Tab)
└─ 关于 → (子页面)
表单页 (apply) ────(存为草稿/提交)──→ 列表页 (list) ──(点击卡片)──→ 详情页 (detail/:id)
↑ │ │
└───────(左滑编辑/draft编辑)─────────┘ (rejected→重新编辑)──┘
/admin/permissions (仅管理员)
/announcement/create (仅管理员)
/)| 元素 | 事件 | 行为 | 数据来源/接口 |
|---|---|---|---|
| 消息 Tab | 点击 | 路由 → /messages,图标变 #00ABF3 |
— |
消息 Tab 角标 TDBadge |
数据绑定 | 未读消息数;进入时拉取,之后 30s 轮询或 Push 刷新 | GET /api/messages/unread-count |
| 工作台 Tab | 点击 | 路由 → /home,图标变 #00ABF3 |
— |
| 我的 Tab | 点击 | 路由 → /profile,图标变 #00ABF3 |
— |
| 当前激活 Tab | 重复点击 | 若对应页面含列表 → ScrollToTop;否则无行为 | — |
/messages)| 元素 | 事件 | 行为 | 数据来源/接口 |
|---|---|---|---|
| 导航栏标题 | — | "消息通知" | — |
| 导航栏"全部已读" | 点击 | 仅未读消息>0 时显示;调用接口,所有红点淡出,按钮消失 | POST /api/messages/read-all |
| 消息卡片(公告类) | 点击 | 路由 → /announcement/detail/:id |
BizType='announcement' |
| 消息卡片(审批待办) | 点击 | 按 BizType 路由 → 对应详情页,底部直接展示审批操作栏 |
BizType 决定路由 |
| 消息卡片(审批结果) | 点击 | 按 BizType 路由 → 对应详情页 |
BizType 决定路由 |
| 消息卡片(无 BizType) | 点击 | TDDialog 展示完整正文(标题+发送人+时间+内容),仅关闭按钮 |
— |
| 已读消息卡片 | — | 透明度 0.6,无红点,不可左滑 | IsRead=1 |
| 未读消息卡片-左滑 | 手势 | 滑出 [标记已读](蓝色) + [删除](红色) |
— |
[标记已读] |
点击 | 异步标记;成功→红点淡出+透明度↓0.6;失败→Toast 红色"操作失败,请重试" | PUT /api/messages/:id/read |
[删除] |
点击 | TDDialog:"确认删除?删除后不可恢复。"→ 确定→卡片收起动画+软删除(IsDeleted=1) |
PUT /api/messages/:id/delete |
| 列表区域 | 下拉 | RefreshIndicator,重置 page=1 |
GET /api/messages?page=1 |
| 列表区域 | 上拉触底 | page++,底部菊花+"加载中...",静默追加 |
GET /api/messages?page=N |
| 空列表 | — | TDEmpty + 铃铛占位图:"暂无消息通知" |
— |
/home)| 元素 | 事件 | 行为 | 数据来源/接口 |
|---|---|---|---|
| 导航栏标题 | — | "TBOSS 工作台" | — |
TDRotation 轮播图 |
自动 | 每 3s 切换,循环 | SysBanner (IsActive=1, IsDeleted=0, ORDER BY SortOrder) |
| 轮播图 | 点击 | 有 LinkUrl→跳转;无→全屏预览(双指缩放) |
SysBanner.LinkUrl |
| 金刚区-事前申请 | 点击 | 路由 → /expense-apply/apply |
— |
| 金刚区-费用报销 | 点击 | 路由 → /expense/apply |
— |
| 金刚区-用车申请 | 点击 | 路由 → /vehicle/apply |
— |
| 金刚区-加班申请 | 点击 | 路由 → /overtime/apply |
— |
| 金刚区-申请记录 | 点击 | 路由 → /expense-apply/list(默认"全部"Chip) |
— |
| 金刚区-报销记录 | 点击 | 路由 → /expense/list(默认"全部"Chip) |
— |
| 金刚区-外勤日志 | 点击 | 路由 → /outing-log/list |
— |
| 金刚区-公司公告 | 点击 | 路由 → /announcement/list |
— |
| 快捷看板-已提单据总数 | 点击 | 路由 → /expense-apply/list(默认"全部") |
后端预计算(缓存5min) |
| 快捷看板-本月累计报销 | 点击 | 路由 → /report/expense-detail |
后端预计算(缓存5min) |
| 快捷看板-待处理总数 | 点击 | 路由 → /messages(筛选 approval_notice) |
后端预计算(缓存5min) |
| 页面整体 | 下拉 | 强制穿透缓存刷新轮播图+看板数据 | — |
| 元素 | 事件 | 行为 | 数据来源/接口 |
|---|---|---|---|
待审批卡片区 TDBadge |
— | 红色数字展示待办件数 | COUNT(ApprovalRecord WHERE ApproverId=当前用户 AND Action='pending' AND IsValid=1) |
| 待审批卡片区 | 点击 | 路由 → /messages(筛选 approval_notice) |
— |
| 元素 | 事件 | 行为 | 数据来源/接口 |
|---|---|---|---|
| 财务看盘卡片 | — | 只读展示:已支付流水/待付款总额/异常退回数 | 全公司聚合查询 |
/profile)| 元素 | 事件 | 行为 | 数据来源/接口 |
|---|---|---|---|
头像 TDAvatar |
点击 | 唤起相册/相机 → 裁剪(1:1,≤2MB,JPG/PNG) → 上传 → 全局刷新 | PUT /api/user/avatar → SysUser.AvatarUrl |
| 个人信息卡片 | — | 展示真实姓名、部门、岗位 | SysUser.RealName, DeptName, Position |
| 我的审批历史 | 点击 | 路由 → 审批历史子页面 | — |
| 我的报表 | 点击 | 路由 → 报表聚合子页面(5 Tab) | — |
| 关于 TBOSS OA | 点击 | 路由 → 关于子页面 | — |
| 关于-用户协议 | 点击 | url_launcher → 宿主 WebView |
远程 HTML |
| 关于-隐私政策 | 点击 | url_launcher → 宿主 WebView |
远程 HTML |
| 元素 | 事件 | 行为 | 数据来源/接口 |
|---|---|---|---|
| 导航栏标题 | — | "我的审批历史" | — |
| 单据卡片-编号 | 点击 | 按单据类型跳转详情页 | ApprovalRecord.BizId + BizType |
| 列表区域 | 下拉 | 刷新 page=1 |
ApplicantId 反查 4 张业务主表 JOIN ApprovalRecord |
| 列表区域 | 上拉触底 | page++ |
同上 |
| 空列表 | — | TDEmpty:"暂无审批记录" |
— |
| 元素 | 事件 | 行为 |
|---|---|---|
TDTabBar(5 Tab) |
切换 | 下方渲染对应页面 21~25 的个人报表视图 |
/expense-apply/apply)| 元素 | 事件 | 行为 | 数据来源/接口 |
|---|---|---|---|
| 申请人姓名 | — | 只读 | SysUser.RealName |
| 所属部门 | — | 只读 | SysUser.DeptId → SysDepartment.DeptName |
| 申请日期 | — | 只读,DateTime.now(),YYYY-MM-DD |
— |
紧急程度 TDRadioGroup |
选择 | 普通/紧急/特急,默认"普通" | ExpenseApplication.Urgency |
费用类型 TDPicker |
选择 | 差旅费/招待费/日常采购/活动经费;联动过滤预算科目候选 | ExpenseApplication.ExpenseType |
费用事由 TDTextarea |
输入 | 限制 200 字 | ExpenseApplication.Purpose |
关联项目 TDPicker |
级联选择 | 一级:SysProject.Name → 二级:SysBudgetSubject.Name(通过 SysProjectBudget 过滤) |
ExpenseApplication.ProjectId |
预算科目 TDPicker |
选择 | 选完项目+科目后异步加载可用余额 | ExpenseApplication.BudgetSubjectId |
| 预算余额展示 | — | 只读"¥XXXX.xx" | SysProjectBudget.AvailableAmount(ProjectId+SubjectId) |
预估金额 TDInput |
输入 | 纯数字键盘;汇总所有明细行,超预算→金额变红+警告文本 | ExpenseAppDetail.EstimatedAmount |
| [+ 添加费用明细] | 点击 | 展开新明细卡片,页面滚动聚焦 | — |
| 明细卡片 ✕ | 点击 | 气泡"确认删除"→ 折叠消失 | — |
| 附件上传 [+] | 点击 | 唤起相册/相机/文件;≤10MB(图)/≤20MB(PDF);超限 Toast | ExpenseApplicationAttachment |
| 附件缩略图 | 点击 | 黑底全屏预览,双指缩放(0.5x~3x),左右滑动,右上角关闭 | — |
| 附件缩略图 ⊖ | 点击 | 气泡"删除该附件?"→ 缩小消失+删除服务器文件 | — |
| PDF 附件 | 点击 | 原生 PDF 查看器打开 | — |
| [重置] | 点击 | 仅编辑草稿时可见;确认弹窗→清空至初始状态 | — |
| [存为草稿] | 点击 | Loading → PUT /expense-apply/draft → Toast 绿色 → 跳转列表(激活"草稿"Chip);失败→Toast 红色 |
ExpenseApplication (Status='draft') |
| [提交审批] | 点击 | 校验→ScrollTo 报错字段(300ms)+边框红闪+TDMessage;通过→Loading→POST /expense-apply/submit→Toast→跳转列表 |
ExpenseApplication (Status='pending') |
| 返回按钮(有未保存修改) | 点击 | TDDialog:"是否退出?"→ 继续编辑/放弃并退出 |
— |
/expense/apply)| 元素 | 事件 | 行为 | 数据来源/接口 |
|---|---|---|---|
| [一键导入] 快捷链 | 点击 | 半屏抽屉:approved 且未被引用的申请列表;空→TDEmpty;选一条覆盖回填 |
Expense.SourceApplicationId 排除已引用 |
| 报销事由 | 输入 | 可由导入回填或手工填写 | Expense.Purpose |
| 关联项目 | 选择 | 草稿可空 | Expense.ProjectId |
| 预算科目 | 选择 | 草稿可空 | Expense.BudgetSubjectId |
关联成本中心 TDPicker |
选择 | 可空,选项来自 SysCostCenter |
Expense.CostCenterId |
| 报销总金额 | — | 只读,明细累加上浮动画 | Expense.TotalAmount |
开户行 TDInput |
输入+联想 | /api/banks 下拉联想,可自由输入 |
Expense.BankName |
| 开户人户名 | 输入 | 默认当前用户姓名,可修改 | Expense.AccountName |
银行账号 TDInput |
输入 | 前端校验 16-19 位;提交时后端再校验;首次提交后回写默认账户 | Expense.BankAccount → SysUser.DefaultBankAccount |
| 发生日期 | 点击 | TDDatePicker(年月日,无时分) |
ExpenseDetail.ExpenseDate |
费用类别 TDPicker |
选择 | 选项来自 SysCostCategory(叶子节点) |
ExpenseDetail.ExpenseType |
发票金额 TDInput |
输入 | 纯数字键盘 | ExpenseDetail.TotalAmount |
| [+ 添加费用明细] | 点击 | 平滑展开新明细卡片 | — |
| 明细行 ✕ | 点击 | 气泡确认→折叠消失 | — |
| 发票上传 [+] | 点击 | 相册/相机,≤10MB;满 9 隐藏 | ExpenseAttachment |
| 发票缩略图 | 点击 | 黑底全屏预览 | — |
| [存为草稿] | 点击 | 复用页面 4 逻辑 | — |
| [提交审批] | 点击 | 复用页面 4 逻辑 | — |
| 返回按钮(有未保存修改) | 点击 | 复用页面 4 逻辑 | — |
/expense-apply/list)/expense/list)| 元素 | 事件 | 行为 | 数据来源/接口 |
|---|---|---|---|
| 导航栏标题 | — | "申请记录" / "报销记录" | — |
TDChip(全部/草稿/审批中/已通过/已拒绝/已撤回) |
点击 | 高亮 #00ABF3,列表淡入淡出刷新;无数据→TDEmpty(文案随 Chip 变化) |
ExpenseApplication.Status / Expense.Status |
| 列表区域 | 下拉 | 刷新,page=1 |
— |
| 列表区域 | 上拉触底 | page++,追加卡片 |
— |
| 卡片空白区 | 点击 | 路由 → 详情页 | /expense-apply/detail/:id 或 /expense/detail/:id |
卡片左滑-[编辑] |
点击 | 仅 draft/rejected;路由 → 表单编辑态 | /expense-apply/apply?id=xxx 或 /expense/apply?id=xxx |
卡片左滑-[删除] |
点击 | 仅 draft/rejected;TDDialog"确认删除?不可恢复。"→ 卡片收起+软删除 |
— |
| 卡片左滑(其他状态) | — | 无反应 | — |
StatusTag |
— | 仅展示(灰-草稿/橙-审批中/绿-已通过/红-已拒绝/灰-已撤回) | — |
| 元素 | 事件 | 行为 |
|---|---|---|
访问范围标签 [我的发起] |
点击 | 与员工版逻辑相同 |
访问范围标签 [下属审批] |
点击 | 列表清空+骨架屏→加载部门下属单据 |
下属卡片左滑-[一键同意] |
点击 | 仅 pending 状态;绿色按钮,无需进入详情页即审批通过 |
| 元素 | 事件 | 行为 |
|---|---|---|
[待付款] Chip |
点击 | 筛选 Status='approved' AND PaymentStatus='unpaid' |
卡片左滑-[线下已付款] |
点击 | 标记 PaymentStatus='paid' |
/expense-apply/detail/:id)/expense/detail/:id)| 元素 | 事件 | 行为 | 数据来源 |
|---|---|---|---|
| 状态横幅 | — | 图标+状态中文+当前审批人姓名 | Status + CurrentApproverId → SysUser.RealName |
| 提交时间 | — | 只读"YYYY-MM-DD HH:mm" | CreateTime |
| 费用明细表"展开全部" | 点击 | >5行时显示;平滑展开 | ExpenseAppDetail / ExpenseDetail |
| 附件缩略图 | 点击 | 黑底全屏预览,双指缩放,左右滑动 | ExpenseApplicationAttachment / ExpenseAttachment |
| 时间线节点 | 点击 | 当前用户待审批→弹出审批操作;否则→展开详情(审批人/时间/意见) | ApprovalRecord (IsValid=1 ORDER BY ApprovalLevel) |
| 审批人姓名/头像 | 点击 | TDDialog 展示基本信息卡片(姓名+部门+岗位) |
ApproverId → SysUser |
| [编辑](draft) | 点击 | 路由 → 表单编辑态 | — |
| [提交审批](draft) | 点击 | 校验→提交;失败→TDDialog"去编辑"引导 |
— |
| [撤回申请](pending) | 点击 | TDDialog"确认撤回?"→ 确定→Status='withdrawn'→页面刷新 |
— |
| [重新编辑并发起](rejected) | 点击 | 路由 → 表单编辑态;提交后更新原记录+旧审批链 IsValid=0 | ApprovalRecord.IsValid |
| 元素 | 事件 | 行为 | 接口 |
|---|---|---|---|
| [拒绝] | 点击 | TDDialog 输入理由(≥5字解锁确定按钮)→ POST |
/api/{bizType}/approve (action=reject) |
| [转交] | 点击 | MethodChannel 唤起通讯录单选 → POST |
/api/{bizType}/approve (action=transfer) |
| [同意] | 点击 | Loading → POST → 节点变绿 → 流转 |
/api/{bizType}/approve (action=approve) |
| 元素 | 事件 | 行为 |
|---|---|---|
| [强制终止] | 点击 | TDDialog 确认 → Status='withdrawn' + 写入终止原因 |
| [查看审批链] | 点击 | 展开完整 ApprovalRecord 历史(含 IsValid=0 的失效记录) |
| 元素 | 事件 | 行为 | 数据来源 |
|---|---|---|---|
| 合规复选框 ×3 | 勾选 | 全部勾选→解锁 [确认打款] 按钮 | Expense.IsInvoiceVerified/IsTaxIdMatched/IsCategoryCompliant |
| [退回修改] | 点击 | 选择退回节点(员工/经理)→状态倒流 | — |
| [确认已线下打款并归档] | 点击 | 解锁后可用;滑出凭证表单(电汇流水号+记账凭证号必填)→提交→Paid |
Expense.BankTransferNo + VoucherNo |
| [下一笔待付款] | 点击 | 归档后替换显示;跳转下一条 approved+unpaid;无→"已无待付款单据" |
— |
/overtime/apply)| 元素 | 事件 | 行为 | 数据来源 |
|---|---|---|---|
加班类型 TDPicker |
选择 | 工作日/休息日/节假日,默认"工作日";节假日标注费率 | Overtime.OtType |
补偿方式 TDRadio |
选择 | 转调休/结算加班费/混合,默认"转调休" | Overtime.CompensationType |
混合模式 TDSlider |
拖动 | 10%~90%,步长 10%;右侧实时比例文案 | Overtime.CompLeaveRatio |
| 开始时间 | 点击 | TDDatePicker 年月日时分 |
Overtime.StartTime |
| 结束时间 | 点击 | TDDatePicker;确认后自动计算净工时(扣除 12:00-13:00/18:00-18:30) |
Overtime.EndTime → NetOtHours |
| 净工时卡片 | — | 只读大字;≤0→变红+提交按钮置灰 | Overtime.NetOtHours |
| 开始>结束校验 | — | 边框变红+提示+提交按钮置灰 | — |
加班原因 TDTextarea |
输入 | 大文本 | Overtime.Reason |
| [存为草稿]/[提交审批] | 点击 | 复用页面 4 逻辑 | — |
| 返回按钮(有未保存修改) | 点击 | 复用页面 4 逻辑 | — |
/overtime/list)| 元素 | 事件 | 行为 |
|---|---|---|
TDChip(全部/草稿/审批中/已通过/已拒绝/已撤回) |
点击 | 同列表页标准逻辑 |
| 补偿方式展示 | — | overtime_pay→结算加班费 / comp_leave→转调休 / mixed→"X%调休+Y%结算" |
| 其余交互 | — | 同页面 6/7 标准列表逻辑 |
/overtime/detail/:id)同页面 8/9 详情节构,员工端仅 [撤回]。
/vehicle/apply)| 元素 | 事件 | 行为 | 数据来源 |
|---|---|---|---|
车牌号 TDPicker |
选择 | 全公司车池(空闲+使用中);冲突车辆标红"冲突";无可用→TDEmpty |
SysVehicle (IsDeleted=0) |
| 车牌号+出车/还车时间 | 失焦 | 异步排期冲突检测;冲突→红色文本+建议文字+锁死提交按钮 | Vehicle (Status IN pending,approved) |
| 用车事由 | 输入 | 文本 | Vehicle.Reason |
| 预计始发地 | 定位/输入 | 原生定位匹配 | Vehicle.Origin |
| 预计目的地+地图图标 | 输入/点图标 | MethodChannel 唤醒地图选点→回填地址+经纬度 | Vehicle.Destination + DestLongitude/Latitude |
| 预计出车时间 | 点击 | TDDatePicker 年月日时分 |
Vehicle.StartTime |
| 预计还车时间 | 点击 | TDDatePicker 年月日时分 |
Vehicle.EndTime |
| 还车>出车校验 | — | 否则红色提示+提交按钮置灰 | — |
| 同行总人数 | 输入 | 纯数字,0→1 | Vehicle.PassengerCount |
| 随行同行人 [+] | 点击 | MethodChannel 唤醒通讯录多选→胶囊标签展示;取消→无变化 | VehiclePassenger |
| 胶囊标签 x | 点击 | 剔除该人员 | — |
| [存为草稿]/[提交审批] | 点击 | 复用页面 4 逻辑 | — |
/vehicle/list)| 元素 | 事件 | 行为 |
|---|---|---|
TDChip(全部/草稿/审批中/已通过/已拒绝/已撤回/已还车) |
点击 | 同列表页标准逻辑 |
卡片左滑-[编辑]/[删除] |
点击 | 仅 draft/rejected |
卡片左滑-[确认还车] |
点击 | 仅 approved;拉起半屏核销抽屉(复用页面 15) |
| 卡片左滑(已还车) | — | 无操作 |
/vehicle/detail/:id)| 元素 | 事件 | 行为 | 数据来源 |
|---|---|---|---|
| 微缩静态地图 | 点击 | MethodChannel 唤醒原生地图导航 | OriginLongitude/Latitude, DestLongitude/Latitude |
| [确认还车并登记](approved) | 点击 | 滑出核销抽屉 | — |
| 核销-实还时间 | 点击 | TDDatePicker 年月日时分 |
Vehicle.ActualReturnTime |
| 核销-出车前里程 | 输入 | 纯数字键盘 | Vehicle.StartOdometer |
| 核销-还车后里程 | 输入 | 纯数字,前端校验≥出车前里程 | Vehicle.EndOdometer |
| 核销-费用备注 | 输入 | 路桥费/停车费 | Vehicle.ActualCost + CostRemark |
| 确认提交还车 | 点击 | TDDialog 确认→Status='returned'→页面刷新(底部显示归档时间+核销信息) |
— |
| 已还车底部栏 | — | 灰色只读"已还车归档于 YYYY-MM-DD HH:mm" | UpdateTime |
/outing-log/create)| 元素 | 事件 | 行为 | 数据来源 |
|---|---|---|---|
| GPS 定位区 | 页面初始化 | 强制请求高精度 GPS → ReadOnly 展示地址;精度>100m→黄色警告 | MethodChannel → OutingLog.CheckInLongitude/Latitude/Address |
| GPS 定位区(失败) | — | TDEmpty"无法获取当前位置";提交按钮置灰 |
— |
客户名称 TDInput |
输入 | 自动联想 SysCustomer.CustomerName;无匹配→自由文本(后端自动创建) |
OutingLog.CustomerName (草稿: CustomerId=NULL) |
今日工作总结 TDTextarea |
输入 | 大文本 | OutingLog.VisitSummary |
| 后续推进计划 | 输入 | 大文本 | OutingLog.NextPlan |
| 现场拍照区域 | 点击 | 跳过相册,直接唤醒相机;水印=服务器授时+GPS;满 4 隐藏 | OutingLogAttachment |
| 相机权限被拒 | — | TDDialog + "前往设置"按钮 |
— |
| [存为草稿] | 点击 | 复用页面 4 逻辑;GPS、CustomerId 可为空 | — |
| [提交] | 点击 | 校验 GPS+照片≥1;无→置灰+红色提示 | — |
| 返回按钮(有未保存修改) | 点击 | 复用页面 4 逻辑 | — |
/outing-log/list)| 元素 | 事件 | 行为 |
|---|---|---|
TDChip(全部/本月) |
点击 | 切换刷新 |
卡片"新点评" TDBadge |
— | 橙色标记,数据来源:OutingLogComment.CreateTime > COALESCE(LastViewedTime, '1900-01-01') 且评论者非员工本人 |
卡片左滑-[编辑]/[删除] |
点击 | 仅 draft;[删除]需确认弹窗 |
| 卡片左滑(completed) | — | 无操作 |
| 其余交互 | — | 同标准列表逻辑 |
/outing-log/detail/:id)| 元素 | 事件 | 行为 | 数据来源 |
|---|---|---|---|
| 微缩地图 | 点击 | 唤醒原生地图导航 | CheckInLongitude/Latitude |
| 照片墙缩略图 | 点击 | 全屏预览 | OutingLogAttachment |
| 主管点评区(员工端) | — | 只读浏览,不可回复 | OutingLogComment (ORDER BY CreateTime ASC) |
| 页面进入 | — | 无感 PUT /api/outing-log/:id/view,更新 LastViewedTime,列表"新点评"红点消失 |
OutingLog.LastViewedTime = NOW() |
| 元素 | 事件 | 行为 | 数据来源 |
|---|---|---|---|
TDRate 星级 |
点选 | 1-5 星 | OutingLogComment.RatingStars |
| 点评文本框 | 输入 | 批示文字 | OutingLogComment.CommentText |
| 发送按钮 | 点击 | 气泡追加+动画,写入 OutingLogComment,同步更新 OutingLog.UpdateTime |
— |
/announcement/list)| 元素 | 事件 | 行为 | 数据来源 |
|---|---|---|---|
| 导航栏标题 | — | "公司公告" | — |
TDChip 类型筛选 |
点击 | 全部/通知公告/人事与制度/放假与活动/我的草稿(仅管理员) | Announcement.Type + Status |
| 公告卡片 | 点击 | 路由 → /announcement/detail/:id |
— |
| 列表排序 | — | 置顶→未过期(PublishTime DESC)→已过期(PublishTime DESC) | IsTop, PublishTime, ExpiryDate |
| 已过期卡片 | — | 整体置灰+标题末尾"已过期" | ExpiryDate < NOW |
| 未读红点 | — | 红点淡出(返回列表后) | AnnouncementReadLog.IsRead=0 |
| 列表区域 | 下拉/上拉 | 刷新/加载更多 | — |
| 搜索 | — | 不支持 | — |
/announcement/detail/:id)| 元素 | 事件 | 行为 | 数据来源/接口 |
|---|---|---|---|
| 公告正文 | — | HTML/Markdown 渲染 | Announcement.Content |
| 已过期横幅 | — | 红色"该公告已于 YYYY-MM-DD HH:mm 过期" | Announcement.ExpiryDate |
| 附件图标 | 点击 | 原生浏览器/下载管理器打开;失败→Toast | AnnouncementAttachment |
| 附件列表为空 | — | 整个"附件下载"区块隐藏 | — |
| 页面停留 ≥2s | — | 无感发送已读请求;<2s 返回不发 | POST /api/announcements/:id/read → IsRead=1 |
| 元素 | 事件 | 行为 | 数据来源/接口 |
|---|---|---|---|
| [已读 N 人] Chip | 点击 | 展开已读员工列表(头像+部门) | AnnouncementReadLog (IsRead=1) |
| [未读 N 人] Chip | 点击 | 展开未读员工列表(头像+部门) | AnnouncementReadLog (IsRead=0) |
| [一键 DING] | 点击 | 震动反馈→封装 UserIds→MethodChannel 强推 Push/短信 | AnnouncementReadLog.IsUrged=1, LastUrgeTime |
/report/..)| 元素 | 事件 | 行为 |
|---|---|---|
TDDropdownMenu(本月/本季/本年) |
选择 | 数值卡片+图表 300ms 渐变刷新;不支持自定义日期 |
| 数值卡片 | — | 只读;空→0/¥0.00 |
fl_chart 数据点 |
长按 | tooltip(日期+数值) |
fl_chart 图表 |
水平滑动 | 查看历史数据 |
| 员工版数据导出 | — | 不支持 |
| 图表为空 | — | TDEmpty:"所选时间范围内暂无数据" |
| 元素 | 事件 | 行为 |
|---|---|---|
| 柱状图柱体 | 点击 | 下方列表联动过滤→该员工本月单据流水 |
| 流水条目 | 点击 | 穿透跳转对应单据详情页 |
| 元素 | 事件 | 行为 |
|---|---|---|
| 部门树/项目组筛选器 | 级联选择 | 多维组合筛选 |
| [数据流水一键导出] | 点击 | Loading→后端生成 Excel→MethodChannel 唤起原生分享面板 |
/announcement/create)| 元素 | 事件 | 行为 | 数据来源 |
|---|---|---|---|
公告标题 TDInput |
输入 | 文本 | Announcement.Title |
| 公告分类下拉 | 选择 | notice/policy/activity | Announcement.Type |
| 富文本编辑域 | 操作 | 加粗/斜体/下划线/有序列表/无序列表/插入图片/插入链接/字号(H1-H3+正文) | Announcement.Content |
| 附件上传 [+] | 点击 | ≤5 个,PDF/图片/Word/Excel,≤20MB | AnnouncementAttachment |
置顶 TDSwitch |
切换 | 默认关闭 | Announcement.IsTop |
有效期 TDDatePicker |
选择 | 非必填,不填永不过期 | Announcement.ExpiryDate |
| 接收范围选择器 | 点击 | 右侧滑出部门树多选(Checkbox);底部统计"已选 N 部门,覆盖 M 员工";默认全员 | AnnouncementTarget |
| [预览](导航栏右侧) | 点击 | TDDialog 全屏模拟详情页 |
— |
| [存为草稿] | 点击 | 保存→跳转公告列表(草稿仅创建者+管理员可见) | Announcement.Status='draft' |
| [发布] | 点击 | 确认弹窗"确认向 M 名员工发布?"→写入+异步 Job 初始化 AnnouncementReadLog→Toast |
Announcement.Status='published' |
| 返回按钮(有未保存修改) | 点击 | 复用页面 4 逻辑 | — |
/admin/permissions)| 元素 | 事件 | 行为 | 数据来源/接口 |
|---|---|---|---|
TDSearchBar |
输入 | 300ms 防抖模糊搜索→骨架屏→结果刷新;无结果→TDEmpty |
SysUser.UserName + RealName |
| 员工列表 | 下拉/上拉 | 刷新/每页 20 条加载更多 | 默认按部门+姓名排序 |
| 员工卡片 | 点击 | 右侧滑出 TDDrawer 权限编辑抽屉 |
— |
角色复选框 ×4 TDCheckboxGroup |
勾选 | 普通员工/审批人(经理)/财务人员/系统管理员 | SysUserRole |
启用/禁用 TDSwitch |
切换 | 映射 IsActive;经理有待审批时警告确认;取消→回弹 |
SysUser.IsActive |
| [确认保存权限修改] | 点击 | Loading→PUT /api/admin/assign-role→Toast+写入审计日志;失败→Toast 红色 |
SysRoleChangeLog |
| 【变更记录】折叠区 | 展开 | TDTimeline 展示最近 20 条变更记录 |
SysRoleChangeLog (CREATE TIME DESC LIMIT 20) |
| 抽屉关闭(有未保存修改) | — | 确认弹窗"是否放弃?" | — |
| 自保护 | — | 管理员无法取消自己的 admin 角色→Toast | — |
| 最后管理员保护 | — | 移除最后 admin 时后端拒绝 | — |
| 场景 | 行为 |
|---|---|
| 所有列表页下拉 | 刷新 page=1 |
| 所有列表页上拉触底 | page++ 追加 |
| 所有表单页返回(有未保存修改) | TDDialog 确认 |
| 所有表单提交/存草稿 | Loading 态 + 成功/失败 Toast |
| 所有附件缩略图点击 | 黑底全屏预览,双指缩放,左右滑动 |
| 所有 PDF 附件点击 | 原生 PDF 查看器 |
| 并发编辑冲突 | 错误码 CONCURRENCY_CONFLICT→TDDialog→返回列表刷新 |
| 并发审批冲突 | 错误码 APPROVAL_CONFLICT→详情页自动刷新+Toast |
| 401 未授权 | 静默触发宿主登录流程 |
| 横竖屏 | 仅支持竖屏 |
| Deep Link | tboss://oa/{path} → GoRouter 路由 |