chengc hai 3 días
pai
achega
bc888e2b19

+ 4 - 0
.gitignore

@@ -48,3 +48,7 @@ app.*.symbols
 app.*.map.json
 
 .codegraph/
+
+.vscode/
+docs/superpowers/prototype/
+

+ 0 - 583
docs/superpowers/specs/2026-05-29-tboss-oa-database.md

@@ -1,583 +0,0 @@
-# TBOSS OA — 数据库表字段详细设计
-
-**日期:** 2026-05-29
-**后端:** .NET Framework 4.8 · SQL Server(推荐)
-
----
-
-## 约定
-
-- 主键统一使用 `VARCHAR(36)` 存储 GUID
-- 金额字段使用 `DECIMAL(18,2)`
-- 所有表含 `CreateTime DATETIME NOT NULL DEFAULT GETDATE()` 和 `UpdateTime DATETIME`
-- 状态字段用 `VARCHAR(20)` 存英文标识,前端映射中文
-- `IsDeleted BIT NOT NULL DEFAULT 0` 软删除
-
----
-
-## 1. 基础数据表
-
-### 1.1 SysUser(用户表)
-
-| 字段 | 类型 | 必填 | 说明 |
-|------|------|------|------|
-| Id | VARCHAR(36) | PK | GUID |
-| UserName | NVARCHAR(50) | ✅ | 登录名 |
-| RealName | NVARCHAR(50) | ✅ | 真实姓名 |
-| PasswordHash | VARCHAR(128) | ✅ | 密码哈希 |
-| Role | VARCHAR(20) | ✅ | employee / approver / finance / admin |
-| DeptId | VARCHAR(36) | FK | 所属部门 |
-| Position | NVARCHAR(50) | | 岗位名称 |
-| Phone | VARCHAR(20) | | 手机号 |
-| Email | VARCHAR(100) | | 邮箱 |
-| AvatarUrl | VARCHAR(500) | | 头像URL |
-| IsActive | BIT | ✅ | 启用/停用,默认1 |
-| CreateTime | DATETIME | ✅ | |
-| UpdateTime | DATETIME | | |
-
-### 1.2 SysDepartment(部门表)
-
-| 字段 | 类型 | 必填 | 说明 |
-|------|------|------|------|
-| Id | VARCHAR(36) | PK | GUID |
-| DeptName | NVARCHAR(100) | ✅ | 部门名称 |
-| ParentId | VARCHAR(36) | | 上级部门ID |
-| ManagerId | VARCHAR(36) | FK→SysUser | 部门负责人 |
-| SortOrder | INT | | 排序,默认0 |
-| IsActive | BIT | ✅ | 默认1 |
-| CreateTime | DATETIME | ✅ | |
-| UpdateTime | DATETIME | | |
-
-### 1.3 SysProject(项目表)
-
-| 字段 | 类型 | 必填 | 说明 |
-|------|------|------|------|
-| Id | VARCHAR(36) | PK | GUID |
-| ProjectName | NVARCHAR(200) | ✅ | 项目名称 |
-| ProjectCode | VARCHAR(50) | | 项目编号 |
-| DeptId | VARCHAR(36) | FK→SysDepartment | 归属部门 |
-| BudgetAmount | DECIMAL(18,2) | | 项目预算总额 |
-| StartDate | DATE | | 项目开始日期 |
-| EndDate | DATE | | 项目结束日期 |
-| IsActive | BIT | ✅ | 默认1 |
-| CreateTime | DATETIME | ✅ | |
-| UpdateTime | DATETIME | | |
-
-### 1.4 SysBudgetSubject(预算科目表)
-
-| 字段 | 类型 | 必填 | 说明 |
-|------|------|------|------|
-| Id | VARCHAR(36) | PK | GUID |
-| SubjectName | NVARCHAR(100) | ✅ | 科目名称 |
-| SubjectCode | VARCHAR(50) | | 科目编码 |
-| ParentId | VARCHAR(36) | | 上级科目ID |
-| SortOrder | INT | | 排序 |
-| IsActive | BIT | ✅ | 默认1 |
-| CreateTime | DATETIME | ✅ | |
-| UpdateTime | DATETIME | | |
-
-### 1.5 SysCostCenter(成本中心表)
-
-| 字段 | 类型 | 必填 | 说明 |
-|------|------|------|------|
-| Id | VARCHAR(36) | PK | GUID |
-| CenterName | NVARCHAR(100) | ✅ | 成本中心名称 |
-| CenterCode | VARCHAR(50) | | 编码 |
-| DeptId | VARCHAR(36) | FK→SysDepartment | 归属部门 |
-| IsActive | BIT | ✅ | 默认1 |
-| CreateTime | DATETIME | ✅ | |
-| UpdateTime | DATETIME | | |
-
-### 1.6 SysVehicle(车辆信息表)
-
-| 字段 | 类型 | 必填 | 说明 |
-|------|------|------|------|
-| Id | VARCHAR(36) | PK | GUID |
-| LicensePlate | VARCHAR(20) | ✅ | 车牌号 |
-| VehicleType | VARCHAR(20) | ✅ | 轿车/SUV/商务车/面包车 |
-| Brand | NVARCHAR(50) | | 品牌型号 |
-| Seats | INT | | 座位数 |
-| DriverName | NVARCHAR(50) | | 默认司机 |
-| Status | VARCHAR(20) | ✅ | idle/in_use/maintenance,默认idle |
-| IsActive | BIT | ✅ | 默认1 |
-| CreateTime | DATETIME | ✅ | |
-| UpdateTime | DATETIME | | |
-
-### 1.7 SysCustomer(客户表)
-
-| 字段 | 类型 | 必填 | 说明 |
-|------|------|------|------|
-| Id | VARCHAR(36) | PK | GUID |
-| CustomerName | NVARCHAR(200) | ✅ | 客户名称 |
-| ShortName | NVARCHAR(100) | | 简称 |
-| Address | NVARCHAR(500) | | 地址 |
-| Longitude | DECIMAL(10,6) | | 经度 |
-| Latitude | DECIMAL(10,6) | | 纬度 |
-| SalespersonId | VARCHAR(36) | FK→SysUser | 负责业务员 |
-| IsActive | BIT | ✅ | 默认1 |
-| CreateTime | DATETIME | ✅ | |
-| UpdateTime | DATETIME | | |
-
-### 1.8 SysCustomerContact(客户联系人表)
-
-| 字段 | 类型 | 必填 | 说明 |
-|------|------|------|------|
-| Id | VARCHAR(36) | PK | GUID |
-| CustomerId | VARCHAR(36) | FK→SysCustomer | ✅ |
-| ContactName | NVARCHAR(50) | ✅ | 姓名 |
-| Position | NVARCHAR(50) | | 职务 |
-| Phone | VARCHAR(20) | | 电话 |
-| Email | VARCHAR(100) | | 邮箱 |
-| SortOrder | INT | | 排序 |
-| CreateTime | DATETIME | ✅ | |
-| UpdateTime | DATETIME | | |
-
----
-
-## 2. 业务主表
-
-### 2.1 Expense(报销单表)
-
-| 字段 | 类型 | 必填 | 说明 |
-|------|------|------|------|
-| Id | VARCHAR(36) | PK | GUID |
-| ReportNo | VARCHAR(30) | ✅ | 报销单号,如 BX-20260529-001 |
-| ApplicantId | VARCHAR(36) | FK→SysUser | ✅ 申请人 |
-| ApplicantName | NVARCHAR(50) | ✅ | 冗余,申请人姓名 |
-| DeptId | VARCHAR(36) | FK→SysDepartment | ✅ 申请部门 |
-| DeptName | NVARCHAR(100) | ✅ | 冗余,部门名称 |
-| ExpenseType | VARCHAR(20) | ✅ | 差旅费/办公用品/招待费/交通费/通讯费/其他 |
-| TotalAmount | DECIMAL(18,2) | ✅ | 报销总金额 |
-| InvoiceCount | INT | | 发票张数,默认0 |
-| CostCenterId | VARCHAR(36) | FK→SysCostCenter | 成本中心 |
-| ProjectId | VARCHAR(36) | FK→SysProject | 关联项目 |
-| ProjectName | NVARCHAR(200) | | 冗余,项目名称 |
-| BudgetSubjectId | VARCHAR(36) | FK→SysBudgetSubject | 预算科目 |
-| LoanWriteoffAmount | DECIMAL(18,2) | | 冲销借款金额,默认0 |
-| PaymentMethod | VARCHAR(20) | | 银行转账/现金/支票 |
-| PaymentStatus | VARCHAR(20) | | unpaid/paid/paying,默认unpaid |
-| AccountId | VARCHAR(36) | | 收款账户ID |
-| AccountName | NVARCHAR(50) | | 收款账户名 |
-| VoucherNo | VARCHAR(50) | | 财务凭证号 |
-| Remark | NVARCHAR(500) | | 备注说明 |
-| Status | VARCHAR(20) | ✅ | draft/pending/approved/rejected/withdrawn |
-| CurrentApproverId | VARCHAR(36) | FK→SysUser | 当前审批人 |
-| CreateTime | DATETIME | ✅ | |
-| UpdateTime | DATETIME | | |
-| IsDeleted | BIT | ✅ | 默认0 |
-
-### 2.2 ExpenseDetail(报销明细表)
-
-| 字段 | 类型 | 必填 | 说明 |
-|------|------|------|------|
-| Id | VARCHAR(36) | PK | GUID |
-| ExpenseId | VARCHAR(36) | FK→Expense | ✅ 关联报销单 |
-| ExpenseDate | DATE | ✅ | 费用发生日期 |
-| ExpenseType | VARCHAR(20) | ✅ | 费用类别 |
-| ExpenseDesc | NVARCHAR(200) | ✅ | 费用描述 |
-| Amount | DECIMAL(18,2) | ✅ | 金额(不含税) |
-| TaxAmount | DECIMAL(18,2) | | 税额,默认0 |
-| TotalAmount | DECIMAL(18,2) | ✅ | 价税合计 |
-| InvoiceNo | VARCHAR(50) | | 发票号码 |
-| InvoiceCode | VARCHAR(50) | | 发票代码 |
-| InvoiceType | VARCHAR(20) | | 增值税专用发票/普通发票/无发票 |
-| IsDeductible | BIT | | 是否抵扣,默认0 |
-| TaxRate | DECIMAL(5,4) | | 税率,如 0.09 |
-| Remark | NVARCHAR(200) | | 备注 |
-| SortOrder | INT | | 排序,默认1 |
-| CreateTime | DATETIME | ✅ | |
-| UpdateTime | DATETIME | | |
-
-### 2.3 ExpenseAttachment(报销附件表)
-
-| 字段 | 类型 | 必填 | 说明 |
-|------|------|------|------|
-| Id | VARCHAR(36) | PK | GUID |
-| ExpenseId | VARCHAR(36) | FK→Expense | ✅ 关联报销单 |
-| DetailId | VARCHAR(36) | | 关联明细,为空表示整单附件 |
-| FileName | NVARCHAR(200) | ✅ | 原始文件名 |
-| FileUrl | VARCHAR(500) | ✅ | 存储URL |
-| FileSize | BIGINT | | 文件大小(字节) |
-| FileType | VARCHAR(20) | | image/pdf/doc |
-| SortOrder | INT | | 排序 |
-| CreateTime | DATETIME | ✅ | |
-
-### 2.4 ExpenseApplication(报销申请单表)
-
-| 字段 | 类型 | 必填 | 说明 |
-|------|------|------|------|
-| Id | VARCHAR(36) | PK | GUID |
-| ApplicationNo | VARCHAR(30) | ✅ | 申请单号,如 BXSQ-20260529-001 |
-| ApplicantId | VARCHAR(36) | FK→SysUser | ✅ 申请人 |
-| ApplicantName | NVARCHAR(50) | ✅ | |
-| DeptId | VARCHAR(36) | FK→SysDepartment | ✅ |
-| DeptName | NVARCHAR(100) | ✅ | |
-| ExpenseType | VARCHAR(20) | ✅ | 差旅费/办公用品/招待费/交通费/通讯费/其他 |
-| EstimatedAmount | DECIMAL(18,2) | ✅ | 预估总金额 |
-| EstimatedStartDate | DATE | | 预计费用开始日期 |
-| EstimatedEndDate | DATE | | 预计费用结束日期 |
-| Urgency | VARCHAR(10) | | normal/urgent/critical,默认normal |
-| Purpose | NVARCHAR(500) | ✅ | 申请事由 |
-| ProjectId | VARCHAR(36) | FK→SysProject | 关联项目 |
-| ProjectName | NVARCHAR(200) | | 冗余 |
-| BudgetSubjectId | VARCHAR(36) | FK→SysBudgetSubject | 预算科目 |
-| Remark | NVARCHAR(500) | | 备注 |
-| Status | VARCHAR(20) | ✅ | draft/pending/approved/rejected/withdrawn |
-| CurrentApproverId | VARCHAR(36) | FK→SysUser | 当前审批人 |
-| CreateTime | DATETIME | ✅ | |
-| UpdateTime | DATETIME | | |
-| IsDeleted | BIT | ✅ | 默认0 |
-
-### 2.5 ExpenseAppDetail(报销申请明细表)
-
-| 字段 | 类型 | 必填 | 说明 |
-|------|------|------|------|
-| Id | VARCHAR(36) | PK | GUID |
-| ApplicationId | VARCHAR(36) | FK→ExpenseApplication | ✅ |
-| ItemName | NVARCHAR(200) | ✅ | 费用项目名称 |
-| EstimatedAmount | DECIMAL(18,2) | ✅ | 预估金额 |
-| Remark | NVARCHAR(200) | | 备注 |
-| SortOrder | INT | | 排序,默认1 |
-| CreateTime | DATETIME | ✅ | |
-| UpdateTime | DATETIME | | |
-
-### 2.6 Overtime(加班申请单表)
-
-| 字段 | 类型 | 必填 | 说明 |
-|------|------|------|------|
-| Id | VARCHAR(36) | PK | GUID |
-| ApplicationNo | VARCHAR(30) | ✅ | 申请单号,如 JB-20260529-001 |
-| ApplicantId | VARCHAR(36) | FK→SysUser | ✅ 申请人 |
-| ApplicantName | NVARCHAR(50) | ✅ | |
-| DeptId | VARCHAR(36) | FK→SysDepartment | ✅ |
-| DeptName | NVARCHAR(100) | ✅ | |
-| Position | NVARCHAR(50) | | 岗位 |
-| OtDate | DATE | ✅ | 加班日期 |
-| StartTime | DATETIME | ✅ | 开始时间 |
-| EndTime | DATETIME | ✅ | 结束时间 |
-| OtHours | DECIMAL(4,1) | ✅ | 申请加班时长 |
-| ActualOtHours | DECIMAL(4,1) | | 实际加班时长(审批后填写) |
-| ClockInTime | DATETIME | | 关联打卡-上班 |
-| ClockOutTime | DATETIME | | 关联打卡-下班 |
-| MealDeductHours | DECIMAL(3,1) | | 用餐扣除时长,默认0.5 |
-| OtType | VARCHAR(10) | ✅ | workday/weekend/holiday |
-| CompensationType | VARCHAR(10) | ✅ | overtime_pay/comp_leave |
-| Reason | NVARCHAR(500) | ✅ | 加班原因 |
-| Remark | NVARCHAR(500) | | 备注 |
-| Status | VARCHAR(20) | ✅ | draft/pending/approved/rejected/withdrawn |
-| CurrentApproverId | VARCHAR(36) | FK→SysUser | 当前审批人 |
-| CreateTime | DATETIME | ✅ | |
-| UpdateTime | DATETIME | | |
-| IsDeleted | BIT | ✅ | 默认0 |
-
-### 2.7 Vehicle(用车申请单表)
-
-| 字段 | 类型 | 必填 | 说明 |
-|------|------|------|------|
-| Id | VARCHAR(36) | PK | GUID |
-| ApplicationNo | VARCHAR(30) | ✅ | 申请单号,如 YC-20260529-001 |
-| ApplicantId | VARCHAR(36) | FK→SysUser | ✅ 申请人 |
-| ApplicantName | NVARCHAR(50) | ✅ | |
-| DeptId | VARCHAR(36) | FK→SysDepartment | ✅ |
-| DeptName | NVARCHAR(100) | ✅ | |
-| VehicleType | VARCHAR(20) | ✅ | 轿车/SUV/商务车/面包车 |
-| VehicleId | VARCHAR(36) | FK→SysVehicle | 指定车辆(审批后分配) |
-| LicensePlate | VARCHAR(20) | | 车牌号(冗余) |
-| Purpose | VARCHAR(20) | ✅ | 客户接待/商务出行/内部公务/其他 |
-| StartTime | DATETIME | ✅ | 预计开始时间 |
-| EndTime | DATETIME | ✅ | 预计结束时间 |
-| ReturnTime | DATETIME | | 实际还车时间 |
-| Origin | NVARCHAR(200) | ✅ | 出发地点 |
-| Destination | NVARCHAR(200) | ✅ | 目的地 |
-| PassengerCount | INT | | 乘车人数,默认1 |
-| Driver | VARCHAR(20) | ✅ | 自驾/配驾 |
-| DriverName | NVARCHAR(50) | | 驾驶员姓名 |
-| EstimatedMileage | DECIMAL(10,2) | | 预估里程(公里) |
-| ActualMileage | DECIMAL(10,2) | | 实际里程 |
-| StartOdometer | DECIMAL(10,2) | | 起始里程表读数 |
-| EndOdometer | DECIMAL(10,2) | | 结束里程表读数 |
-| EstimatedCost | DECIMAL(18,2) | | 预估费用 |
-| ActualCost | DECIMAL(18,2) | | 实际费用 |
-| Reason | NVARCHAR(500) | ✅ | 用车事由 |
-| Status | VARCHAR(20) | ✅ | draft/pending/approved/rejected/withdrawn |
-| CurrentApproverId | VARCHAR(36) | FK→SysUser | 当前审批人 |
-| CreateTime | DATETIME | ✅ | |
-| UpdateTime | DATETIME | | |
-| IsDeleted | BIT | ✅ | 默认0 |
-
-### 2.8 VehiclePassenger(用车同行人员表)
-
-| 字段 | 类型 | 必填 | 说明 |
-|------|------|------|------|
-| Id | VARCHAR(36) | PK | GUID |
-| ApplicationId | VARCHAR(36) | FK→Vehicle | ✅ |
-| UserId | VARCHAR(36) | FK→SysUser | 关联系统用户 |
-| PassengerName | NVARCHAR(50) | ✅ | 姓名(冗余/外部人员) |
-| CreateTime | DATETIME | ✅ | |
-
-### 2.9 OutingLog(业务员外出日志表)
-
-| 字段 | 类型 | 必填 | 说明 |
-|------|------|------|------|
-| Id | VARCHAR(36) | PK | GUID |
-| VisitNo | VARCHAR(30) | ✅ | 拜访编号,如 VST-20260529-001 |
-| SalespersonId | VARCHAR(36) | FK→SysUser | ✅ 业务员 |
-| SalespersonName | NVARCHAR(50) | ✅ | |
-| DeptId | VARCHAR(36) | FK→SysDepartment | ✅ |
-| DeptName | NVARCHAR(100) | ✅ | |
-| CustomerId | VARCHAR(36) | FK→SysCustomer | 客户 |
-| CustomerName | NVARCHAR(200) | ✅ | |
-| ContactId | VARCHAR(36) | FK→SysCustomerContact | 联系人 |
-| ContactName | NVARCHAR(50) | | |
-| ContactPhone | VARCHAR(20) | | |
-| ContactPosition | NVARCHAR(50) | | |
-| VisitDate | DATE | ✅ | 拜访日期 |
-| VisitStartTime | DATETIME | ✅ | 签到时间 |
-| VisitEndTime | DATETIME | ✅ | 签退时间 |
-| VisitType | VARCHAR(20) | ✅ | 商务沟通/产品演示/售后服务/合同签约/催款/其他 |
-| VisitPurpose | NVARCHAR(500) | ✅ | 拜访目的 |
-| VisitLocation | NVARCHAR(200) | ✅ | 拜访地点 |
-| VisitAddressDetail | NVARCHAR(200) | | 详细地址 |
-| Longitude | DECIMAL(10,6) | | 签到时经度 |
-| Latitude | DECIMAL(10,6) | | 签到时纬度 |
-| CheckInStatus | VARCHAR(20) | | normal/deviation,默认normal |
-| DistanceDeviation | INT | | 定位偏差距离(米),默认0 |
-| Participants | NVARCHAR(200) | | 参与人员(我方) |
-| VisitSummary | NVARCHAR(2000) | ✅ | 拜访总结 |
-| VisitResult | VARCHAR(20) | | 待跟进/已成交/需再次拜访/无意愿 |
-| CustomerFeedback | NVARCHAR(1000) | | 客户反馈 |
-| CompetitorInfo | NVARCHAR(1000) | | 竞品信息 |
-| NextVisitTime | DATETIME | | 下次拜访时间 |
-| NextVisitContent | NVARCHAR(500) | | 下次拜访内容 |
-| Materials | NVARCHAR(500) | | 携带资料 |
-| Status | VARCHAR(20) | ✅ | completed/draft |
-| CreateTime | DATETIME | ✅ | |
-| UpdateTime | DATETIME | | |
-| IsDeleted | BIT | ✅ | 默认0 |
-
-### 2.10 OutingLogAttachment(外出日志附件表)
-
-| 字段 | 类型 | 必填 | 说明 |
-|------|------|------|------|
-| Id | VARCHAR(36) | PK | GUID |
-| LogId | VARCHAR(36) | FK→OutingLog | ✅ |
-| FileName | NVARCHAR(200) | ✅ | |
-| FileUrl | VARCHAR(500) | ✅ | |
-| FileType | VARCHAR(20) | | sign_in_photo/sign_out_photo/visit_photo/other |
-| SortOrder | INT | | 排序 |
-| CreateTime | DATETIME | ✅ | |
-
-### 2.11 Announcement(公告表)
-
-| 字段 | 类型 | 必填 | 说明 |
-|------|------|------|------|
-| Id | VARCHAR(36) | PK | GUID |
-| Title | NVARCHAR(200) | ✅ | 公告标题 |
-| Content | NVARCHAR(MAX) | ✅ | 公告正文 |
-| ContentType | VARCHAR(10) | | text/html,默认text |
-| Type | VARCHAR(20) | ✅ | 通知公告/制度文件/活动通知/其他 |
-| PublisherId | VARCHAR(36) | FK→SysUser | ✅ 发布人 |
-| PublisherName | NVARCHAR(50) | ✅ | |
-| PublishTime | DATETIME | ✅ | 发布时间 |
-| IsTop | BIT | | 是否置顶,默认0 |
-| PrivateLevel | INT | | 可见级别:0=全员 1=指定部门 2=指定用户 |
-| RequireConfirm | BIT | | 需确认已读,默认0 |
-| ExpiryDate | DATETIME | ✅ | 过期时间 |
-| CreateTime | DATETIME | ✅ | |
-| UpdateTime | DATETIME | | |
-| IsDeleted | BIT | ✅ | 默认0 |
-
-### 2.12 AnnouncementTarget(公告可见范围表)
-
-| 字段 | 类型 | 必填 | 说明 |
-|------|------|------|------|
-| Id | VARCHAR(36) | PK | GUID |
-| AnnouncementId | VARCHAR(36) | FK→Announcement | ✅ |
-| TargetType | VARCHAR(10) | ✅ | dept/user |
-| TargetId | VARCHAR(36) | ✅ | 部门ID或用户ID |
-| CreateTime | DATETIME | ✅ | |
-
-### 2.13 AnnouncementAttachment(公告附件表)
-
-| 字段 | 类型 | 必填 | 说明 |
-|------|------|------|------|
-| Id | VARCHAR(36) | PK | GUID |
-| AnnouncementId | VARCHAR(36) | FK→Announcement | ✅ |
-| FileName | NVARCHAR(200) | ✅ | |
-| FileUrl | VARCHAR(500) | ✅ | |
-| FileSize | BIGINT | | |
-| CreateTime | DATETIME | ✅ | |
-
-### 2.14 AnnouncementReadLog(公告已读记录表)
-
-| 字段 | 类型 | 必填 | 说明 |
-|------|------|------|------|
-| Id | VARCHAR(36) | PK | GUID |
-| AnnouncementId | VARCHAR(36) | FK→Announcement | ✅ |
-| UserId | VARCHAR(36) | FK→SysUser | ✅ |
-| ReadTime | DATETIME | ✅ | 阅读时间 |
-| IsConfirmed | BIT | | 是否确认(需确认时),默认0 |
-| ConfirmTime | DATETIME | | 确认时间 |
-
----
-
-## 3. 审批与工作流表
-
-### 3.1 ApprovalRecord(审批记录表)
-
-| 字段 | 类型 | 必填 | 说明 |
-|------|------|------|------|
-| Id | VARCHAR(36) | PK | GUID |
-| BizId | VARCHAR(36) | ✅ | 业务单据ID |
-| BizType | VARCHAR(30) | ✅ | expense/expense_application/overtime/vehicle |
-| ApproverId | VARCHAR(36) | FK→SysUser | ✅ 审批人 |
-| ApproverName | NVARCHAR(50) | ✅ | |
-| ApprovalLevel | INT | ✅ | 审批层级(1,2,3...) |
-| Action | VARCHAR(20) | ✅ | pending/approve/reject/withdraw |
-| Opinion | NVARCHAR(500) | | 审批意见 |
-| ApprovalTime | DATETIME | ✅ | 审批时间 |
-| CreateTime | DATETIME | ✅ | |
-
-### 3.2 ApprovalChain(审批链配置表)
-
-| 字段 | 类型 | 必填 | 说明 |
-|------|------|------|------|
-| Id | VARCHAR(36) | PK | GUID |
-| BizType | VARCHAR(30) | ✅ | 业务类型 |
-| DeptId | VARCHAR(36) | | 适用部门(空=全局) |
-| LevelNo | INT | ✅ | 审批层级 |
-| ApproverId | VARCHAR(36) | FK→SysUser | 指定审批人 |
-| ApproverRole | VARCHAR(20) | | 按角色:dept_manager/finance/admin |
-| IsActive | BIT | ✅ | 默认1 |
-| CreateTime | DATETIME | ✅ | |
-| UpdateTime | DATETIME | | |
-
----
-
-## 4. 消息通知表
-
-### 4.1 Message(消息通知表)
-
-| 字段 | 类型 | 必填 | 说明 |
-|------|------|------|------|
-| Id | VARCHAR(36) | PK | GUID |
-| UserId | VARCHAR(36) | FK→SysUser | ✅ 接收人 |
-| Title | NVARCHAR(200) | ✅ | 消息标题 |
-| Content | NVARCHAR(500) | | 消息摘要 |
-| MsgType | VARCHAR(20) | ✅ | approval_notice/approval_result/announcement/system |
-| BizType | VARCHAR(30) | | 关联业务类型 |
-| BizId | VARCHAR(36) | | 关联业务ID |
-| IsRead | BIT | ✅ | 已读,默认0 |
-| ReadTime | DATETIME | | 阅读时间 |
-| CreateTime | DATETIME | ✅ | |
-
----
-
-## 5. 枚举值汇总
-
-### 5.1 业务状态
-| 值 | 中文 | 适用表 |
-|------|------|--------|
-| draft | 草稿 | 所有申请表 |
-| pending | 待审批 | 所有申请表 |
-| approved | 已通过 | 所有申请表 |
-| rejected | 已拒绝 | 所有申请表 |
-| withdrawn | 已撤回 | 所有申请表 |
-| completed | 已完成 | OutingLog |
-
-### 5.2 报销类型
-`差旅费 / 办公用品 / 招待费 / 交通费 / 通讯费 / 其他`
-
-### 5.3 加班类型
-`workday(工作日加班)/ weekend(休息日加班)/ holiday(节假日加班)`
-
-### 5.4 补偿方式
-`overtime_pay(加班费)/ comp_leave(调休)`
-
-### 5.5 用车目的
-`客户接待 / 商务出行 / 内部公务 / 其他`
-
-### 5.6 发票类型
-`增值税专用发票 / 增值税普通发票 / 无发票`
-
-### 5.7 付款状态
-`unpaid(未付款)/ paying(付款中)/ paid(已付款)`
-
-### 5.8 紧急程度
-`normal(普通)/ urgent(紧急)/ critical(特急)`
-
-### 5.9 拜访类型
-`商务沟通 / 产品演示 / 售后服务 / 合同签约 / 催款 / 其他`
-
-### 5.10 拜访结果
-`待跟进 / 已成交 / 需再次拜访 / 无意愿`
-
-### 5.11 公告类型
-`通知公告 / 制度文件 / 活动通知 / 其他`
-
-### 5.12 消息类型
-`approval_notice(审批通知)/ approval_result(审批结果)/ announcement(公告提醒)/ system(系统消息)`
-
-### 5.13 用户角色
-`employee / approver / finance / admin`
-
-### 5.14 车辆类型
-`轿车 / SUV / 商务车 / 面包车`
-
-### 5.15 车辆状态
-`idle(空闲)/ in_use(使用中)/ maintenance(维修中)`
-
----
-
-## 6. 表关系图(关键外键)
-
-```
-SysUser ──┬── Expense (ApplicantId, CurrentApproverId)
-          ├── ExpenseApplication
-          ├── Overtime
-          ├── Vehicle
-          ├── OutingLog (SalespersonId)
-          ├── Announcement (PublisherId)
-          ├── ApprovalRecord (ApproverId)
-          ├── Message (UserId)
-          └── SysDepartment (ManagerId)
-
-SysDepartment ──┬── SysUser (DeptId)
-                ├── Expense (DeptId)
-                ├── ExpenseApplication (DeptId)
-                ├── Overtime (DeptId)
-                ├── Vehicle (DeptId)
-                ├── OutingLog (DeptId)
-                └── ApprovalChain (DeptId)
-
-SysProject ──┬── Expense (ProjectId)
-             └── ExpenseApplication (ProjectId)
-
-SysCustomer ──┬── OutingLog (CustomerId)
-              └── SysCustomerContact (CustomerId)
-
-SysVehicle ──── Vehicle (VehicleId)
-
-ApprovalRecord ──┬── Expense (BizId, BizType='expense')
-                 ├── ExpenseApplication (BizId, BizType='expense_application')
-                 ├── Overtime (BizId, BizType='overtime')
-                 └── Vehicle (BizId, BizType='vehicle')
-```
-
----
-
-## 7. 索引建议
-
-| 表 | 索引字段 | 类型 | 说明 |
-|------|------|------|------|
-| Expense | Status, ApplicantId, DeptId, CreateTime DESC | 复合 | 列表查询主路径 |
-| Expense | ReportNo | 唯一 | 单号唯一约束 |
-| ExpenseDetail | ExpenseId | 普通 | 关联查询 |
-| ExpenseApplication | Status, ApplicantId, DeptId | 复合 | |
-| Overtime | Status, ApplicantId, OtDate DESC | 复合 | |
-| Vehicle | Status, ApplicantId, DeptId | 复合 | |
-| OutingLog | SalespersonId, VisitDate DESC | 复合 | |
-| Announcement | IsTop DESC, PublishTime DESC | 复合 | 列表排序 |
-| AnnouncementReadLog | AnnouncementId, UserId | 唯一 | 防重复记录 |
-| ApprovalRecord | BizId, BizType | 复合 | 关联查询 |
-| Message | UserId, IsRead, CreateTime DESC | 复合 | 消息列表 |

+ 0 - 476
docs/superpowers/specs/2026-05-29-tboss-oa-design.md

@@ -1,476 +0,0 @@
-# TBOSS OA Module — 设计规格说明书
-
-**日期:** 2026-05-29
-**版本:** 1.0
-
----
-
-## 1. 项目概述
-
-在 `tboss_oa_module`(Flutter Add-to-App 模块)中实现完整的 OA 前端功能,嵌入现有 Android(Java/Kotlin)和 iOS(Objective-C)宿主应用。
-
-### 约束条件
-- Flutter 3.38.10 · Dart SDK ^3.10.9
-- 主色 `#00ABF3` · UI 框架 TDesign Flutter 0.2.7
-- 必须支持横竖屏自动适配
-- iOS 宿主为 OC,禁止引入 Swift-only 依赖导致编译失败
-- 后端接口将使用 .NET Framework 4.8 开发(本次仅前端)
-
----
-
-## 2. 导航架构
-
-采用 **3 Tab 底部导航**(消息 / 工作台 / 我的),使用 GoRouter + TDesign TabBar。
-
-| Tab | 内容 | 图标 |
-|-----|------|------|
-| 消息 | 审批通知 + 系统公告提醒 | bell |
-| 工作台 | 功能入口 + 待办统计 + 报表入口 | app |
-| 我的 | 我发起的 + 我审批的 + 草稿箱 + 设置 | user |
-
----
-
-## 3. 页面清单(24 页)
-
-### 3.1 框架页(3 页)
-| 页面 | 路由 | 说明 |
-|------|------|------|
-| AppShell | `/` | 3 Tab 外壳,包含底部导航 |
-| 消息列表 | `/messages` | 审批通知 + 公告提醒聚合 |
-| 我的 | `/profile` | 个人中心 |
-
-### 3.2 报销单(3 页)
-| 页面 | 路由 | 说明 |
-|------|------|------|
-| 报销单列表 | `/expense/list` | 状态筛选 + 卡片列表 + 左滑编辑 |
-| 报销申请 | `/expense/apply?id=` | 分组表单 + 明细添加 + 存草稿/提交 |
-| 报销单详情 | `/expense/detail/:id` | 信息展示 + 审批时间线 + 角色操作栏 |
-
-### 3.3 报销申请单(3 页)
-| 页面 | 路由 |
-|------|------|
-| 报销申请列表 | `/expense-apply/list` |
-| 报销申请表单 | `/expense-apply/apply?id=` |
-| 报销申请详情 | `/expense-apply/detail/:id` |
-
-### 3.4 加班申请单(3 页)
-| 页面 | 路由 |
-|------|------|
-| 加班列表 | `/overtime/list` |
-| 加班申请 | `/overtime/apply?id=` |
-| 加班详情 | `/overtime/detail/:id` |
-
-### 3.5 用车申请单(3 页)
-| 页面 | 路由 |
-|------|------|
-| 用车列表 | `/vehicle/list` |
-| 用车申请 | `/vehicle/apply?id=` |
-| 用车详情 | `/vehicle/detail/:id` |
-
-### 3.6 业务员外出日志(3 页)
-| 页面 | 路由 |
-|------|------|
-| 外出日志列表 | `/outing-log/list` |
-| 外出日志创建 | `/outing-log/create` |
-| 外出日志详情 | `/outing-log/detail/:id` |
-
-### 3.7 公告(2 页)
-| 页面 | 路由 |
-|------|------|
-| 公告列表 | `/announcement/list` |
-| 公告详情 | `/announcement/detail/:id` |
-
-### 3.8 报表(4 页)
-| 页面 | 路由 |
-|------|------|
-| 报销明细报表 | `/report/expense-detail` |
-| 报销申请明细报表 | `/report/expense-apply-detail` |
-| 加班明细报表 | `/report/overtime-detail` |
-| 用车明细报表 | `/report/vehicle-detail` |
-
----
-
-## 4. 页面设计模式
-
-### 4.1 列表页模式(6 个列表页共用)
-
-```
-┌─────────────────────────────┐
-│  AppBar: 标题          [+]  │
-├─────────────────────────────┤
-│  [全部] [待审批] [已通过] [已拒绝]  ← 横向滚动状态筛选
-├─────────────────────────────┤
-│  ┌─────────────────────┐    │
-│  │ BX-20240501-001  待审批 │    │  ← 卡片,点击进详情
-│  │ 差旅费 · ¥2,380.00    │    │  ← 左滑露出编辑按钮
-│  │ 张三 · 2024-05-01     │    │
-│  └─────────────────────┘    │
-│  ┌─────────────────────┐    │
-│  │ BX-20240428-002  已通过 │    │
-│  │ ...                    │    │
-│  └─────────────────────┘    │
-└─────────────────────────────┘
-```
-
-- 组件:TDChip(状态筛选)+ AppCard + flutter_slidable(左滑操作)
-- 交互:下拉刷新 + 上拉加载更多
-- 空态:EmptyState 组件
-
-### 4.2 表单页模式(5 个申请页共用)
-
-```
-┌─────────────────────────────┐
-│  AppBar: 标题         草稿  │
-├─────────────────────────────┤
-│  ┌─ 基本信息 ─────────────┐ │
-│  │ 报销类型    差旅费  ›   │ │  ← FormFieldRow,点击弹出选择
-│  │ 报销金额    ¥2,380.00  │ │
-│  │ 备注       选填      ›  │ │
-│  └────────────────────────┘ │
-│  ┌─ 报销明细      +添加 ──┐ │
-│  │  机票        ¥1,308 ✕  │ │  ← 明细行,可删除
-│  │  酒店住宿     ¥848  ✕  │ │
-│  └────────────────────────┘ │
-├─────────────────────────────┤
-│  [存草稿]     [提交审批]     │  ← 底部固定操作栏
-└─────────────────────────────┘
-```
-
-- 组件:FormSection + FormFieldRow + TDDatePicker + TDPicker(底部弹出选择)
-- 明细行支持动态添加/删除/金额自动汇总
-
-### 4.3 详情页模式(6 个详情页共用)
-
-```
-┌─────────────────────────────┐
-│  AppBar: 标题              │
-├─────────────────────────────┤
-│      ┌───────┐             │
-│      │  ⏳   │  待审批      │  ← 状态头部(颜色随状态变)
-│      │ 当前审批人:王经理  │
-│      └───────┘             │
-│  ┌─ 基本信息 ─────────────┐ │
-│  │ 报销单号  BX-...       │ │  ← 键值对展示
-│  │ 申请人    张三·销售部  │ │
-│  │ 总金额    ¥2,380.00    │ │
-│  └────────────────────────┘ │
-│  ┌─ 审批进度 ─────────────┐ │
-│  │  ● 提交申请  张三 5/1  │ │  ← 时间线
-│  │  ● 经理审批  王经理    │ │
-│  │  ○ 财务审批  待处理    │ │
-│  └────────────────────────┘ │
-├─────────────────────────────┤
-│  [通过]           [拒绝]    │  ← 按角色显示不同按钮
-└─────────────────────────────┘
-```
-
-- 组件:StatusTag + TDTimeline/自定义时间线 + 动态底部操作栏
-- 底部按钮根据角色 + 单据状态动态渲染
-
-### 4.4 报表页模式(4 个报表页共用)
-
-```
-┌─────────────────────────────┐
-│  [日期范围 ▼] [类型 ▼] [部门 ▼] [查询] │  ← 筛选栏
-├─────────────────────────────┤
-│  ┌──────┐  ┌──────┐        │
-│  │总金额 │  │总笔数 │        │  ← 汇总卡片
-│  │¥12.8万│  │  86  │        │
-│  └──────┘  └──────┘        │
-│  ┌─ 费用趋势 ─────────────┐ │
-│  │    📊 柱状图/折线图     │ │  ← fl_chart
-│  └────────────────────────┘ │
-│  ┌─ 明细列表 ─────────────┐ │
-│  │ 差旅费  ¥35,200  28笔  │ │
-│  │ 办公用品 ¥12,800  15笔  │ │
-│  └────────────────────────┘ │
-└─────────────────────────────┘
-```
-
-- 组件:TDDropdownMenu/TDPicker(筛选器)+ fl_chart(图表)+ 汇总卡片 + 分类列表
-- 图表类型:柱状图(趋势)+ 饼图(分类占比,可选)
-
----
-
-## 5. 数据模型
-
-### 5.1 模型总览
-
-| 模型 | 字段数 | 状态 | 需补充 |
-|------|--------|------|--------|
-| ExpenseModel(报销单) | 22 | 缺3字段 | invoiceImages, paymentStatus, voucherNo |
-| ExpenseDetailModel(报销明细) | 15 | ✅ 完善 | — |
-| ExpenseApplicationModel(报销申请单) | 11 | 缺4字段 | estimatedStartDate, estimatedEndDate, urgency, projectId/Name, budgetSubjectId |
-| ExpenseAppDetailModel(报销申请明细) | 5 | ✅ 基本够用 | — |
-| OvertimeModel(加班申请单) | 16 | 缺3字段 | actualOtHours, clockInTime, clockOutTime, mealDeductHours |
-| VehicleModel(用车申请单) | 19 | 缺4字段 | actualMileage, actualCost, startOdometer, endOdometer, returnTime, passengers[] |
-| OutingLogModel(外出日志) | 30+ | ✅ 完善 | — |
-| AnnouncementModel(公告) | 18 | ✅ 完善 | — |
-
-共享模型:
-- **ApprovalRecord**:审批记录(id, bizId, bizType, approverId/Name, approvalLevel, action, opinion, approvalTime)
-- **ApprovalStatus**:枚举(draft/pending/approved/rejected/withdrawn)
-- **PaginatedData\<T\>**:分页数据
-
-### 5.2 待补充字段详情
-
-**ExpenseModel 补充:**
-```dart
-List<String> invoiceImages;   // 发票/附件图片URL列表
-String paymentStatus;         // 未付款/已付款/付款中
-String voucherNo;             // 财务凭证号
-```
-
-**ExpenseApplicationModel 补充:**
-```dart
-DateTime? estimatedStartDate;  // 预计费用开始日期
-DateTime? estimatedEndDate;    // 预计费用结束日期
-String urgency;                // 普通/紧急/特急
-String projectId;              // 关联项目ID
-String projectName;            // 关联项目名称
-String budgetSubjectId;        // 预算科目ID
-```
-
-**OvertimeModel 补充:**
-```dart
-double actualOtHours;          // 实际加班时长
-DateTime? clockInTime;         // 上班打卡时间
-DateTime? clockOutTime;        // 下班打卡时间
-double mealDeductHours;        // 用餐扣除时长
-```
-
-**VehicleModel 补充:**
-```dart
-double actualMileage;          // 实际里程
-double actualCost;             // 实际费用
-double startOdometer;          // 起始里程表读数
-double endOdometer;            // 结束里程表读数
-DateTime? returnTime;          // 实际还车时间
-List<String> passengers;       // 同行人员姓名列表
-```
-
----
-
-## 6. 用户角色与权限
-
-### 6.1 角色定义
-
-| 角色 | 权限范围 | 标识 |
-|------|---------|------|
-| 普通员工 | 发起申请、查看自己的数据、查看公告 | employee |
-| 审批人(经理) | 审批下属申请 + 员工所有权限 | approver |
-| 财务人员 | 全公司报销数据、确认付款、报表 | finance |
-| 系统管理员 | 发布公告、全部数据、系统设置 | admin |
-
-### 6.2 页面级权限对照
-
-| 页面 | 员工 | 审批人 | 财务/管理员 |
-|------|------|--------|------------|
-| 工作台 | 我的申请统计 | +待我审批区块 | +全公司概览 |
-| 列表页 | 自己的数据 | 下属+自己的 | 全部数据 |
-| 详情页-按钮 | [编辑][撤回][删除] | [通过][拒绝] | [确认付款][关闭] |
-| 报表 | 自己的统计 | 本部门 | 全公司 |
-| 我的Tab | 我发起的+草稿 | +我审批的 | +我审批的 |
-
-### 6.3 权限实现策略
-
-| 层级 | 实现方 | 机制 |
-|------|--------|------|
-| 数据范围 | 后端 | API 根据 token 角色返回不同数据,前端不感知 |
-| UI 可见性 | 前端 | 根据 `currentUser.role` 和单据状态条件渲染 |
-| 报表筛选选项 | 混合 | 部门列表由后端返回可选范围,数据由后端按权限过滤 |
-
----
-
-## 7. 报表筛选设计
-
-### 7.1 公共维度
-日期范围(起止日期)、部门、状态、申请人
-
-### 7.2 各报表独有维度
-
-| 报表 | 独有筛选维度 |
-|------|------------|
-| 报销明细表 | 报销类型、项目、预算科目、发票类型 |
-| 报销申请明细表 | 申请类型、紧急程度、项目 |
-| 加班明细表 | 加班类型、补偿方式 |
-| 用车明细表 | 车辆类型、驾驶员、自驾/配驾 |
-
-### 7.3 报表操作
-重置筛选、应用筛选、数据导出(后端实现)
-
----
-
-## 8. 技术架构
-
-### 8.1 依赖清单
-
-```yaml
-# pubspec.yaml 核心依赖
-tdesign_flutter: ^0.2.7     # TDesign UI 组件库(新增)
-flutter_riverpod: ^2.6.1     # 状态管理
-go_router: ^14.8.1           # 路由
-dio: ^5.7.0                  # 网络请求
-json_annotation: ^4.9.0      # JSON 序列化
-intl: ^0.19.0                # 国际化/日期格式化
-flutter_slidable: ^3.1.1     # 列表左滑操作
-fl_chart: ^0.69.2             # 图表(报表用)
-shimmer: ^3.0.0              # 骨架屏加载
-```
-
-### 8.2 目录结构
-
-```
-lib/
-├── main.dart
-├── app.dart                          # App入口 + Provider初始化
-├── core/
-│   ├── auth/auth_service.dart        # 认证(MethodChannel通信)
-│   ├── network/
-│   │   ├── api_client.dart           # Dio封装
-│   │   ├── api_exception.dart
-│   │   ├── api_response.dart
-│   │   ├── mock_data.dart            # Mock数据
-│   │   └── mock_interceptor.dart
-│   ├── router/app_router.dart        # GoRouter配置(含Shell路由)
-│   ├── theme/
-│   │   ├── app_colors.dart           # 颜色常量
-│   │   └── app_theme.dart            # TDesign + Material3主题
-│   └── utils/
-│       ├── date_utils.dart
-│       ├── responsive.dart           # 横竖屏/宽屏适配
-│       └── validators.dart
-├── features/
-│   ├── home/                         # 工作台
-│   ├── messages/                     # 消息Tab(新增)
-│   ├── profile/                      # 我的Tab(新增)
-│   ├── expense/                      # 报销单
-│   ├── expense_application/          # 报销申请单
-│   ├── overtime/                     # 加班申请单
-│   ├── vehicle/                      # 用车申请单
-│   ├── outing_log/                   # 外出日志
-│   ├── announcement/                 # 公告
-│   └── report/                       # 报表
-└── shared/
-    ├── models/
-    │   ├── approval_status.dart
-    │   └── pagination_model.dart
-    └── widgets/
-        ├── app_card.dart
-        ├── empty_state.dart
-        ├── form_field_row.dart
-        ├── form_section.dart
-        ├── loading_widget.dart
-        └── status_tag.dart
-```
-
-### 8.3 iOS 兼容性注意事项
-
-- TDesign Flutter 0.2.7 基于纯 Dart + Flutter,不依赖 Swift
-- 不使用任何 Swift-only 插件(如某些相机/定位插件可能有 Swift 依赖)
-- MethodChannel 通信使用 OC 端调用
-- `iosBundleIdentifier: com.amtxts.tbossOaModule` 已配置
-- 执行 `cd ios && pod install` 后编译验证
-
----
-
-## 9. 后端 API 接口规划(.NET Framework 4.8)
-
-### 9.1 通用规范
-
-- Base URL: `https://<host>/api`
-- 认证: Bearer Token(Header: `Authorization: Bearer <token>`)
-- 响应格式: `{ "code": 0, "message": "ok", "data": ... }`
-- 分页: `{ "list": [], "page": 1, "size": 20, "total": 100 }`
-- code=0 表示成功,其他值为业务错误码
-
-### 9.2 接口列表
-
-**认证**
-| 方法 | 路径 | 说明 |
-|------|------|------|
-| POST | /auth/login | 登录获取token |
-| GET | /auth/current-user | 获取当前用户信息(含角色) |
-
-**工作台**
-| 方法 | 路径 | 说明 |
-|------|------|------|
-| GET | /home/summary | 首页统计数据 |
-
-**报销单**
-| 方法 | 路径 | 说明 |
-|------|------|------|
-| GET | /expense/list?status=&page=&size= | 报销单列表 |
-| GET | /expense/detail/:id | 报销单详情 |
-| POST | /expense/apply | 提交报销单 |
-| PUT | /expense/draft | 保存草稿 |
-| PUT | /expense/approve | 审批操作 |
-
-**报销申请单**
-| 方法 | 路径 | 说明 |
-|------|------|------|
-| GET | /expense-apply/list | 列表 |
-| GET | /expense-apply/detail/:id | 详情 |
-| POST | /expense-apply/submit | 提交 |
-| PUT | /expense-apply/draft | 草稿 |
-| PUT | /expense-apply/approve | 审批 |
-
-**加班申请单**
-| 方法 | 路径 | 说明 |
-|------|------|------|
-| GET | /overtime/list | 列表 |
-| GET | /overtime/detail/:id | 详情 |
-| POST | /overtime/apply | 提交 |
-| PUT | /overtime/draft | 草稿 |
-| PUT | /overtime/approve | 审批 |
-
-**用车申请单**
-| 方法 | 路径 | 说明 |
-|------|------|------|
-| GET | /vehicle/list | 列表 |
-| GET | /vehicle/detail/:id | 详情 |
-| POST | /vehicle/apply | 提交 |
-| PUT | /vehicle/draft | 草稿 |
-| PUT | /vehicle/approve | 审批 |
-
-**外出日志**
-| 方法 | 路径 | 说明 |
-|------|------|------|
-| GET | /outing-log/list | 列表 |
-| GET | /outing-log/detail/:id | 详情 |
-| POST | /outing-log/create | 创建 |
-
-**公告**
-| 方法 | 路径 | 说明 |
-|------|------|------|
-| GET | /announcement/list | 列表 |
-| GET | /announcement/detail/:id | 详情 |
-| POST | /announcement/publish | 发布(管理员) |
-
-**报表**
-| 方法 | 路径 | 说明 |
-|------|------|------|
-| GET | /report/expense-detail?startDate=&endDate=&... | 报销明细报表 |
-| GET | /report/expense-apply-detail?... | 报销申请明细报表 |
-| GET | /report/overtime-detail?... | 加班明细报表 |
-| GET | /report/vehicle-detail?... | 用车明细报表 |
-
-**消息**
-| 方法 | 路径 | 说明 |
-|------|------|------|
-| GET | /messages/list | 消息通知列表 |
-| PUT | /messages/:id/read | 标记已读 |
-
----
-
-## 10. 设计决策记录
-
-| 决策 | 选择 | 理由 |
-|------|------|------|
-| 导航模式 | 3 Tab(消息/工作台/我的) | 参考钉钉,职责清晰 |
-| 列表样式 | 卡片式 + 状态筛选 | 钉钉/企业微信标准,现有代码兼容 |
-| 表单样式 | 分组表单 + 底部操作栏 | OA 行业惯例,FormSection 已有 |
-| 详情页 | 双角色同页 | 减少页面数,审批流程内嵌 |
-| 报表 | 筛选+汇总卡+图表+列表 | fl_chart 已引入 |
-| 权限 | 后端控数据 + 前端控 UI | 安全 + 灵活 |
-| TDesign 集成 | 替换主题 + 逐步替换组件 | 保持现有架构,渐进增强 |

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 945 - 0
docs/superpowers/specs/2026-05-30-tboss-oa-database.md


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 1052 - 0
docs/superpowers/specs/2026-05-30-tboss-oa-design.md


+ 509 - 0
docs/superpowers/specs/2026-05-30-tboss-oa-interactions.md

@@ -0,0 +1,509 @@
+# TBOSS OA 模块 — 全页面元素操作事件与跳转关系说明
+
+> 基于 `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 (仅管理员)
+```
+
+---
+
+## 页面 1:Appshell 底部导航外壳页 (`/`)
+
+| 元素 | 事件 | 行为 | 数据来源/接口 |
+|------|------|------|-------------|
+| 消息 Tab | 点击 | 路由 → `/messages`,图标变 `#00ABF3` | — |
+| 消息 Tab 角标 `TDBadge` | 数据绑定 | 未读消息数;进入时拉取,之后 30s 轮询或 Push 刷新 | `GET /api/messages/unread-count` |
+| 工作台 Tab | 点击 | 路由 → `/home`,图标变 `#00ABF3` | — |
+| 我的 Tab | 点击 | 路由 → `/profile`,图标变 `#00ABF3` | — |
+| 当前激活 Tab | 重复点击 | 若对应页面含列表 → ScrollToTop;否则无行为 | — |
+
+---
+
+## 页面 2:消息通知聚合页 (`/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` + 铃铛占位图:"暂无消息通知" | — |
+
+---
+
+## 页面 3:工作台 (`/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`) | — |
+
+### 财务版增量
+
+| 元素 | 事件 | 行为 | 数据来源/接口 |
+|------|------|------|-------------|
+| 财务看盘卡片 | — | 只读展示:已支付流水/待付款总额/异常退回数 | 全公司聚合查询 |
+
+---
+
+## 页面 3.1:我的个人中心页 (`/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 的个人报表视图 |
+
+---
+
+## 页面 4:事前申请表单页 (`/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`:"是否退出?"→ 继续编辑/放弃并退出 | — |
+
+---
+
+## 页面 5:费用报销表单页 (`/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 逻辑 | — |
+
+---
+
+## 页面 6:事前申请列表页 (`/expense-apply/list`)
+
+## 页面 7:费用报销列表页 (`/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` 状态;绿色按钮,无需进入详情页即审批通过 |
+
+### 财务版增量(仅页面 7)
+
+| 元素 | 事件 | 行为 |
+|------|------|------|
+| `[待付款]` Chip | 点击 | 筛选 `Status='approved' AND PaymentStatus='unpaid'` |
+| 卡片左滑-`[线下已付款]` | 点击 | 标记 `PaymentStatus='paid'` |
+
+---
+
+## 页面 8:事前申请详情页 (`/expense-apply/detail/:id`)
+
+## 页面 9:费用报销详情页 (`/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` |
+
+### 经理版底部操作栏(仅 pending 状态且当前审批人=该经理时展示)
+
+| 元素 | 事件 | 行为 | 接口 |
+|------|------|------|------|
+| [拒绝] | 点击 | `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 的失效记录) |
+
+### 财务版增量(仅页面 9)
+
+| 元素 | 事件 | 行为 | 数据来源 |
+|------|------|------|-------------|
+| 合规复选框 ×3 | 勾选 | 全部勾选→解锁 [确认打款] 按钮 | `Expense.IsInvoiceVerified/IsTaxIdMatched/IsCategoryCompliant` |
+| [退回修改] | 点击 | 选择退回节点(员工/经理)→状态倒流 | — |
+| [确认已线下打款并归档] | 点击 | 解锁后可用;滑出凭证表单(电汇流水号+记账凭证号必填)→提交→`Paid` | `Expense.BankTransferNo` + `VoucherNo` |
+| [下一笔待付款] | 点击 | 归档后替换显示;跳转下一条 `approved+unpaid`;无→"已无待付款单据" | — |
+
+---
+
+## 页面 10:加班申请表单页 (`/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 逻辑 | — |
+
+---
+
+## 页面 11:加班申请列表页 (`/overtime/list`)
+
+| 元素 | 事件 | 行为 |
+|------|------|------|
+| `TDChip`(全部/草稿/审批中/已通过/已拒绝/已撤回) | 点击 | 同列表页标准逻辑 |
+| 补偿方式展示 | — | `overtime_pay`→结算加班费 / `comp_leave`→转调休 / `mixed`→"X%调休+Y%结算" |
+| 其余交互 | — | 同页面 6/7 标准列表逻辑 |
+
+## 页面 12:加班申请详情页 (`/overtime/detail/:id`)
+
+同页面 8/9 详情节构,员工端仅 `[撤回]`。
+
+---
+
+## 页面 13:用车申请表单页 (`/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 逻辑 | — |
+
+---
+
+## 页面 14:用车申请列表页 (`/vehicle/list`)
+
+| 元素 | 事件 | 行为 |
+|------|------|------|
+| `TDChip`(全部/草稿/审批中/已通过/已拒绝/已撤回/已还车) | 点击 | 同列表页标准逻辑 |
+| 卡片左滑-`[编辑]`/`[删除]` | 点击 | 仅 draft/rejected |
+| 卡片左滑-`[确认还车]` | 点击 | 仅 approved;拉起半屏核销抽屉(复用页面 15) |
+| 卡片左滑(已还车) | — | 无操作 |
+
+---
+
+## 页面 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` |
+
+---
+
+## 页面 16:业务员外出日志创建页 (`/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 逻辑 | — |
+
+---
+
+## 页面 17:外出日志列表页 (`/outing-log/list`)
+
+| 元素 | 事件 | 行为 |
+|------|------|------|
+| `TDChip`(全部/本月) | 点击 | 切换刷新 |
+| 卡片"新点评" `TDBadge` | — | 橙色标记,数据来源:`OutingLogComment.CreateTime > COALESCE(LastViewedTime, '1900-01-01')` 且评论者非员工本人 |
+| 卡片左滑-`[编辑]`/`[删除]` | 点击 | 仅 draft;`[删除]`需确认弹窗 |
+| 卡片左滑(completed) | — | 无操作 |
+| 其余交互 | — | 同标准列表逻辑 |
+
+## 页面 18:外出日志详情页 (`/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` | — |
+
+---
+
+## 页面 19:公司公告列表页 (`/announcement/list`)
+
+| 元素 | 事件 | 行为 | 数据来源 |
+|------|------|------|-------------|
+| 导航栏标题 | — | "公司公告" | — |
+| `TDChip` 类型筛选 | 点击 | 全部/通知公告/人事与制度/放假与活动/我的草稿(仅管理员) | `Announcement.Type` + `Status` |
+| 公告卡片 | 点击 | 路由 → `/announcement/detail/:id` | — |
+| 列表排序 | — | 置顶→未过期(PublishTime DESC)→已过期(PublishTime DESC) | `IsTop`, `PublishTime`, `ExpiryDate` |
+| 已过期卡片 | — | 整体置灰+标题末尾"已过期" | `ExpiryDate < NOW` |
+| 未读红点 | — | 红点淡出(返回列表后) | `AnnouncementReadLog.IsRead=0` |
+| 列表区域 | 下拉/上拉 | 刷新/加载更多 | — |
+| 搜索 | — | 不支持 | — |
+
+---
+
+## 页面 20:公司公告详情页 (`/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` |
+
+---
+
+## 页面 21~25:个人五大明细报表页 (`/report/..`)
+
+| 元素 | 事件 | 行为 |
+|------|------|------|
+| `TDDropdownMenu`(本月/本季/本年) | 选择 | 数值卡片+图表 300ms 渐变刷新;不支持自定义日期 |
+| 数值卡片 | — | 只读;空→0/¥0.00 |
+| `fl_chart` 数据点 | 长按 | tooltip(日期+数值) |
+| `fl_chart` 图表 | 水平滑动 | 查看历史数据 |
+| 员工版数据导出 | — | 不支持 |
+| 图表为空 | — | `TDEmpty`:"所选时间范围内暂无数据" |
+
+### 经理版增量
+
+| 元素 | 事件 | 行为 |
+|------|------|------|
+| 柱状图柱体 | 点击 | 下方列表联动过滤→该员工本月单据流水 |
+| 流水条目 | 点击 | 穿透跳转对应单据详情页 |
+
+### 财务版增量(仅页面 22)
+
+| 元素 | 事件 | 行为 |
+|------|------|------|
+| 部门树/项目组筛选器 | 级联选择 | 多维组合筛选 |
+| [数据流水一键导出] | 点击 | Loading→后端生成 Excel→MethodChannel 唤起原生分享面板 |
+
+---
+
+## 页面 26:系统公告发布表单页 (`/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 逻辑 | — |
+
+---
+
+## 页面 27:全局用户权限配置页 (`/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 路由 |

+ 724 - 0
docs/superpowers/specs/2026-05-30-tboss-oa-prototype-spec.md

@@ -0,0 +1,724 @@
+# TBOSS OA 模块 — 原型规格补充说明书
+
+> 配合 `2026-05-30-tboss-oa-design.md`、`2026-05-30-tboss-oa-database.md`、`2026-05-30-tboss-oa-interactions.md` 使用,补齐高保真原型生成所需的布局标注、组件状态、Mock 数据、资源清单、权限矩阵和校验规则。
+
+---
+
+## 一、页面布局标注
+
+### 1.1 Appshell (`/`)
+
+```
+┌──────────────────────────────────────────┐
+│  [IndexedStack 主内容区]                  │
+│                                          │
+│                                          │
+├──────────────────────────────────────────┤
+│  TDTabBar (h=56px, bg=#FFFFFF)           │
+│  [🔔消息]   [📱工作台]   [👤我的]        │
+│   flex=1     flex=1      flex=1          │
+│   TDBadge 在图标右上角, offset(-4,-4)    │
+└──────────────────────────────────────────┘
+```
+
+### 1.2 消息通知 (`/messages`)
+
+```
+┌──────────────────────────────────────────┐
+│ TDNavbar: "消息通知"      [全部已读]      │
+├──────────────────────────────────────────┤
+│ TDListView (padding-h=16px, gap=8px)     │
+│ ┌──────────────────────────────────────┐ │
+│ │ [图标 24×24] 标题(14sp, bold)        │ │
+│ │              发送人(12sp)  时间(12sp) │ │
+│ │              摘要(12sp, --text-sec)   │ │
+│ │                              [红点 8×8]│ │
+│ └──────────────────────────────────────┘ │
+│ (卡片 h=auto, bg=#FFF, r=8px,           │
+│  padding=12px, 可左滑)                   │
+└──────────────────────────────────────────┘
+```
+
+### 1.3 工作台 (`/home`)
+
+```
+┌──────────────────────────────────────────┐
+│ TDNavbar: "TBOSS 工作台"                 │
+├──────────────────────────────────────────┤
+│ TDRotation (h=160px, 圆角8px)            │
+│   [图片1] [图片2] [图片3]  ··· ●○○      │
+├──────────────────────────────────────────┤
+│ TDGrid (4列, gap=12px, padding-h=16px)   │
+│ ┌────┐ ┌────┐ ┌────┐ ┌────┐            │
+│ │图标│ │图标│ │图标│ │图标│            │
+│ │事前│ │费用│ │用车│ │加班│   ← 发起行   │
+│ │申请│ │报销│ │申请│ │申请│            │
+│ └────┘ └────┘ └────┘ └────┘            │
+│ ┌────┐ ┌────┐ ┌────┐ ┌────┐            │
+│ │图标│ │图标│ │图标│ │图标│            │
+│ │申请│ │报销│ │外勤│ │公司│   ← 记录行   │
+│ │记录│ │记录│ │日志│ │公告│            │
+│ └────┘ └────┘ └────┘ └────┘            │
+│ (每格 icon=32×32, text=12sp)            │
+├──────────────────────────────────────────┤
+│ 【我的快捷看板】卡片 (h=120px)           │
+│ ┌─45%─┐ ┌─25%─┐ ┌─30%─┐               │
+│ │¥12,350│ │  8  │ │  2  │               │
+│ │本月报销│ │已提单│ │待处理│               │
+│ └──────┘ └─────┘ └─────┘               │
+└──────────────────────────────────────────┘
+```
+
+### 1.4 个人中心 (`/profile`)
+
+```
+┌──────────────────────────────────────────┐
+│ TDNavbar: "我的"                         │
+├──────────────────────────────────────────┤
+│ ┌──────────────────────────────────────┐ │
+│ │ [头像 64×64, r=32]                    │ │
+│ │ 张三          销售部 · 客户经理       │ │
+│ │ (padding=16px, bg=#FFF)              │ │
+│ └──────────────────────────────────────┘ │
+├──────────────────────────────────────────┤
+│ TDListView (分组样式, gap=0, 分割线1px)  │
+│  我的审批历史                    ›       │
+│ ───────────────────────────────         │
+│  我的报表                        ›       │
+│ ───────────────────────────────         │
+│  关于 TBOSS OA                   ›       │
+│ (每行 h=48px, padding-h=16px)           │
+└──────────────────────────────────────────┘
+```
+
+### 1.5 表单页布局(页面 4/5/10/13 通用)
+
+```
+┌──────────────────────────────────────────┐
+│ TDNavbar: "{表单名称}"                    │
+├──────────────────────────────────────────┤
+│ FormSection: 基本信息 (padding=16px)      │
+│ ┌──────────────────────────────────────┐ │
+│ │ 申请人姓名    [只读]    所属部门  [只读]│ │
+│ │ (两列并排, 各 flex=1, gap=12px)      │ │
+│ │ 申请日期      [只读]                  │ │
+│ │ 紧急程度  ○普通 ○紧急 ○特急           │ │
+│ │ 费用类型  [ 下拉选择  ▼ ]             │ │
+│ │ 费用事由  [                    ]      │ │
+│ │           (多行, h=80px)              │ │
+│ └──────────────────────────────────────┘ │
+│                                          │
+│ FormSection: 关联管控                     │
+│ ┌──────────────────────────────────────┐ │
+│ │ 关联项目      [ 级联选择  ▼ ]         │ │
+│ │ 预算科目      [ 级联选择  ▼ ]         │ │
+│ │ 💰 当前可用预算余额:¥50,000.00       │ │
+│ └──────────────────────────────────────┘ │
+│                                          │
+│ 支撑材料上传区                            │
+│ ┌──┐ ┌──┐ ┌──┐ ┌──┐ ┌──┐ ┌──┐        │
+│ │+ │ │  │ │  │ │  │ │  │ │  │  TDImageGrid│
+│ └──┘ └──┘ └──┘ └──┘ └──┘ └──┘  3列, gap=8│
+│ (每格 100×100, r=4px)                    │
+│                                          │
+├──────────────────────────────────────────┤
+│ [重置]   [存为草稿]      [ 提交审批 ]     │
+│ (灰色)   (浅蓝#E6F7FD)   (主色#00ABF3)   │
+│ 底部栏 h=56px, bg=#FFF, shadow-up        │
+└──────────────────────────────────────────┘
+```
+
+### 1.6 详情页布局(页面 8/9 通用)
+
+```
+┌──────────────────────────────────────────┐
+│ TDNavbar: "{单据}详情"                    │
+├──────────────────────────────────────────┤
+│ 状态大色块横幅 (h=120px)                  │
+│ ┌──────────────────────────────────────┐ │
+│ │         ✅ (icon 48×48)              │ │
+│ │        已通过                        │ │
+│ │    当前审批人:王经理                  │ │
+│ │ (bg=success时#E6F9F2, text=#00A870)   │ │
+│ └──────────────────────────────────────┘ │
+│ 提交时间:2026-05-30 14:30               │
+├──────────────────────────────────────────┤
+│ 基础信息 (key-value 双栏, 左灰右黑)       │
+│  申请人      │ 张三                      │
+│  所属部门    │ 销售部                     │
+│  费用类型    │ 差旅费                     │
+│  预估金额    │ ¥12,350.00                 │
+│  (左列 w=100px, 12sp, --text-secondary)  │
+├──────────────────────────────────────────┤
+│ 费用明细表 (明细>5行折叠)                 │
+│ ┌──────┬──────┬──────┬──────┐          │
+│ │费用类型│预估金额│ 说明 │      │          │
+│ ├──────┼──────┼──────┼──────┤          │
+│ │ ...  │ ...  │ ...  │      │          │
+│ └──────┴──────┴──────┴──────┘          │
+│            [ 展开全部 ▼ ]                │
+├──────────────────────────────────────────┤
+│ 附件宫格 TDImageGrid (3列)               │
+├──────────────────────────────────────────┤
+│ TDTimeline 审批流                         │
+│ ● 发起人已提交  2026-05-30 14:30         │
+│ │  (左竖线 2px, --border)               │
+│ ● 王经理已通过  2026-05-30 15:00         │
+│ │                                        │
+│ ○ 李会计审批中  (待处理)                  │
+├──────────────────────────────────────────┤
+│ [编辑]          [ 提交审批 ]              │
+│ 底部栏 h=56px, bg=#FFF                   │
+└──────────────────────────────────────────┘
+```
+
+### 1.7 列表页布局(页面 6/7/11/14 通用)
+
+```
+┌──────────────────────────────────────────┐
+│ TDNavbar: "{列表名称}"                    │
+├──────────────────────────────────────────┤
+│ TDChip 滚动条 (h=44px)                    │
+│ [全部] [草稿] [审批中] [已通过] [已拒绝]  │
+│ (gap=8px, padding-h=16px, 可水平滚动)     │
+├──────────────────────────────────────────┤
+│ TDListView (padding-h=16px, gap=12px)    │
+│ ┌──────────────────────────────────────┐ │
+│ │ BXSQ-20260530-001                    │ │
+│ │ 差旅费报销 — 深圳出差                 │ │
+│ │ ¥12,350.00          2026-05-30       │ │
+│ │                           [已通过]    │ │
+│ │ (h=auto, bg=#FFF, r=8px, p=12px)    │ │
+│ └──────────────────────────────────────┘ │
+│ ┌──────────────────────────────────────┐ │
+│ │ ...                                  │ │
+│ └──────────────────────────────────────┘ │
+└──────────────────────────────────────────┘
+```
+
+---
+
+## 二、组件状态矩阵
+
+### 2.1 按钮状态
+
+| 状态 | 样式 |
+|------|------|
+| 默认 | `bg=--primary(#00ABF3)`, `text=#FFF`, `fs=16sp`, `h=44px`, `r=22px` |
+| 按下 | `bg=--primary-active(#0089C4)`, 缩放 0.97 |
+| 禁用 | `bg=#E0E0E0`, `text=#BFBFBF`, 不可点击 |
+| Loading | 文本替换为 20×20 白色菊花 `TDLoading`, 按钮宽度不变 |
+
+**二级按钮(存为草稿/重置)**:
+| 状态 | 样式 |
+|------|------|
+| 默认 | `bg=--primary-light(#E6F7FD)`, `text=--primary(#00ABF3)`, 边框 1px `--primary` |
+| 按下 | `bg=#CCEFFC` |
+
+**危险按钮(删除/拒绝/强制终止)**:
+| 状态 | 样式 |
+|------|------|
+| 默认 | `bg=#FFF`, `text=--danger(#D54941)`, 边框 1px `--danger` |
+| 按下 | `bg=#FFF0EF` |
+
+### 2.2 输入框状态
+
+| 状态 | 样式 |
+|------|------|
+| 默认 | `bg=#FFF`, `border=1px --border(#E7E7E7)`, `r=4px`, `h=44px`, `padding-h=12px` |
+| 聚焦 | `border=1.5px --primary(#00ABF3)`, 外阴影 `0 0 0 2px rgba(0,171,243,0.1)` |
+| 报错 | `border=1.5px --danger(#D54941)`, 下方红色提示文字 12sp |
+| 只读 | `bg=--bg-page(#F5F5F5)`, `text=--text-secondary(#666666)`, 无边框 |
+
+### 2.3 TDChip 状态
+
+| 状态 | 样式 |
+|------|------|
+| 默认 | `bg=#F5F5F5`, `text=--text-secondary(#666666)`, `h=32px`, `r=16px`, `padding-h=12px` |
+| 选中 | `bg=--primary(#00ABF3)`, `text=#FFF` |
+
+### 2.4 卡片左滑
+
+| 状态 | 样式 |
+|------|------|
+| 默认 | 正常位置, `offsetX=0` |
+| 左滑露出操作 | 卡片主体左移 120px, 右侧露出按钮区 `w=120px`, 弹簧动画 200ms |
+| 删除动画 | 卡片 `opacity 0→1 200ms` + `height→0 300ms`, 下方卡片上移 |
+
+### 2.5 TDBadge 状态
+
+| 变体 | 样式 |
+|------|------|
+| 纯红点 | `w=8px, h=8px, r=4px, bg=--danger`, 无文字 |
+| 数字角标 | `h=18px, min-w=18px, r=9px, bg=--danger, text=#FFF, fs=10sp`, 数字>99 显示"99+" |
+| 消失动画 | `scale 1→0 + opacity 1→0, 200ms` |
+
+### 2.6 StatusTag 状态
+
+| 状态 | 样式 |
+|------|------|
+| 草稿 (draft) | `bg=#F5F5F5, text=--status-gray(#999999)` |
+| 审批中 (pending) | `bg=#FFF3E8, text=--warning(#E37318)` |
+| 已通过 (approved) | `bg=#E6F9F2, text=--success(#00A870)` |
+| 已拒绝 (rejected) | `bg=#FFF0EF, text=--danger(#D54941)` |
+| 已撤回 (withdrawn) | `bg=#F5F5F5, text=--status-gray(#999999)` |
+| 已还车 (returned) | `bg=#EDF2FC, text=#5A8CDB` |
+| 已完成 (completed) | `bg=#E6F9F2, text=--success(#00A870)` |
+
+---
+
+## 三、数据 Mock 结构
+
+### 3.1 消息列表项
+
+```json
+{
+  "id": "msg-001",
+  "msgType": "approval_notice",
+  "bizType": "expense",
+  "bizId": "exp-001",
+  "title": "王经理提交了一笔费用报销",
+  "sender": {
+    "id": "user-002",
+    "realName": "王经理",
+    "avatarUrl": "/avatars/user-002.jpg"
+  },
+  "content": "差旅费报销 — 深圳出差",
+  "isRead": false,
+  "createTime": "2026-05-30T14:30:00Z"
+}
+```
+
+### 3.2 列表卡片(事前申请)
+
+```json
+{
+  "applicationNo": "BXSQ-20260530-001",
+  "purpose": "深圳客户拜访差旅费",
+  "estimatedAmount": 12350.00,
+  "expenseType": "travel",
+  "status": "approved",
+  "createTime": "2026-05-30T10:00:00Z"
+}
+```
+
+### 3.3 详情页(事前申请)
+
+```json
+{
+  "id": "ea-001",
+  "applicationNo": "BXSQ-20260530-001",
+  "status": "approved",
+  "createTime": "2026-05-30T10:00:00Z",
+  "applicant": { "realName": "张三", "deptName": "销售部" },
+  "urgency": "normal",
+  "expenseType": "travel",
+  "projectName": "2026华南市场拓展",
+  "budgetSubjectName": "差旅费",
+  "estimatedAmount": 12350.00,
+  "purpose": "深圳客户拜访差旅费",
+  "currentApprover": { "realName": "王经理", "deptName": "销售部", "position": "销售总监" },
+  "details": [
+    { "expenseCategory": "交通费", "estimatedAmount": 8000.00, "remark": "往返机票" },
+    { "expenseCategory": "住宿费", "estimatedAmount": 3500.00, "remark": "三晚酒店" },
+    { "expenseCategory": "餐饮费", "estimatedAmount": 850.00, "remark": "客户招待" }
+  ],
+  "attachments": [
+    { "fileName": "出差申请单.pdf", "fileUrl": "/files/ea-001-1.pdf", "fileType": "pdf", "fileSize": 204800 },
+    { "fileName": "报价单.jpg", "fileUrl": "/files/ea-001-2.jpg", "fileType": "image", "fileSize": 512000 }
+  ],
+  "approvalTimeline": [
+    { "approvalLevel": 0, "action": "提交", "approver": { "realName": "张三" }, "createTime": "2026-05-30T10:00:00Z", "opinion": "" },
+    { "approvalLevel": 1, "action": "approve", "approver": { "realName": "王经理" }, "createTime": "2026-05-30T14:00:00Z", "approvalTime": "2026-05-30T15:00:00Z", "opinion": "同意" }
+  ],
+  "availableBudget": 50000.00
+}
+```
+
+### 3.4 待审批卡片(经理版)
+
+```json
+{
+  "pendingCount": 8,
+  "recentItems": [
+    { "applicantName": "张三", "bizTypeName": "费用报销", "amount": 12350.00, "createTime": "2026-05-30T10:00:00Z" },
+    { "applicantName": "李四", "bizTypeName": "事前申请", "amount": 5000.00, "createTime": "2026-05-30T09:30:00Z" },
+    { "applicantName": "赵五", "bizTypeName": "加班申请", "amount": null, "otHours": 4.5, "createTime": "2026-05-30T09:00:00Z" }
+  ]
+}
+```
+
+### 3.5 财务看盘卡片
+
+```json
+{
+  "monthPaidAmount": 285600.00,
+  "pendingPaymentAmount": 152300.00,
+  "weekAbnormalInvoices": 3
+}
+```
+
+### 3.6 快捷看板
+
+```json
+{
+  "monthExpenseTotal": 12350.00,
+  "monthApplicationCount": 8,
+  "pendingProcessCount": 2
+}
+```
+
+### 3.7 公告触达率
+
+```json
+{
+  "announcementId": "ann-001",
+  "totalTargets": 50,
+  "readCount": 45,
+  "unreadCount": 5,
+  "unreadUsers": [
+    { "id": "user-010", "realName": "钱六", "deptName": "财务部", "avatarUrl": "/avatars/user-010.jpg" },
+    { "id": "user-011", "realName": "孙七", "deptName": "行政部", "avatarUrl": "/avatars/user-011.jpg" }
+  ]
+}
+```
+
+### 3.8 权限管理列表项
+
+```json
+{
+  "id": "user-003",
+  "userName": "0048",
+  "realName": "张三",
+  "deptName": "销售部",
+  "avatarUrl": "/avatars/user-003.jpg",
+  "isActive": true,
+  "roles": ["employee"],
+  "roleChangeLog": [
+    {
+      "operatorName": "管理员",
+      "changeType": "assign_role",
+      "beforeSnapshot": ["employee"],
+      "afterSnapshot": ["employee", "finance"],
+      "createTime": "2026-05-28T11:00:00Z"
+    }
+  ]
+}
+```
+
+---
+
+## 四、资源清单
+
+### 4.1 默认头像占位
+
+| 场景 | 样式 |
+|------|------|
+| 无头像用户 | 圆形,`bg=--primary(#00ABF3)`,居中白色姓名首字母(如"张"),`fs=18sp` |
+| 已离职/软删除用户 | 圆形,`bg=--status-gray(#999999)`,首字母,整体透明度 0.5 |
+
+### 4.2 空状态占位图
+
+| 场景 | 图标 | 尺寸 | 文案 |
+|------|------|------|------|
+| 消息为空 | 铃铛(`TDIcons.notification`) | 80×80, `color=--text-placeholder` | "暂无消息通知" |
+| 列表为空 | 文档(`TDIcons.task`) | 80×80 | "暂无记录" |
+| 待审批为空 | 对勾(`TDIcons.check-circle`) | 80×80 | "暂无待审批单据" |
+| 明细为空 | 票据(`TDIcons.receipt`) | 60×60 | "暂无报销明细" |
+| 附件为空 | 图片(`TDIcons.image`) | 60×60 | "暂无附件" |
+| 搜索为空 | 搜索(`TDIcons.search`) | 80×80 | "未找到匹配的员工" |
+| 公告为空 | 喇叭(`TDIcons.notification`) | 80×80 | "暂无行政公告" |
+| 报表为空 | 图表(`TDIcons.chart`) | 100×100 | "所选时间范围内暂无数据" |
+
+### 4.3 状态横幅图标
+
+| 状态 | 图标 | 尺寸 | 底色 |
+|------|------|------|------|
+| 审批中 | `TDIcons.time-filled` | 48×48, `color=--warning` | `bg=#FFF3E8` |
+| 已通过 | `TDIcons.check-circle-filled` | 48×48, `color=--success` | `bg=#E6F9F2` |
+| 已拒绝 | `TDIcons.close-circle-filled` | 48×48, `color=--danger` | `bg=#FFF0EF` |
+| 已撤回 | `TDIcons.rollback` | 48×48, `color=--status-gray` | `bg=#F5F5F5` |
+
+### 4.4 财务归档盖章
+
+| 元素 | 样式 |
+|------|------|
+| "已归档"盖章 | 红色椭圆边框(`border=3px --danger, r=50%`),旋转 -15°,文字`--danger 16sp bold`,透明度 0.7 |
+| 位置 | 详情页发票区右上角,绝对定位 offset(16,-16) |
+
+### 4.5 防伪水印
+
+| 属性 | 值 |
+|------|------|
+| 位置 | 照片右下角 |
+| 内容 | `{YYYY-MM-DD HH:mm:ss}` + `{纬度},{经度}` |
+| 样式 | 半透明白色(`rgba(255,255,255,0.6)`),`fs=10sp`,等宽字体,两行 |
+
+### 4.6 财务凭证表单
+
+```
+┌──────────────────────────────────────┐
+│        财务凭证编号归档               │
+│                                      │
+│ 公司转账电汇流水号 *                  │
+│ ┌──────────────────────────────────┐ │
+│ │ BOF2026053000001234              │ │
+│ └──────────────────────────────────┘ │
+│                                      │
+│ 财务记账凭证号 *                      │
+│ ┌──────────────────────────────────┐ │
+│ │ JZ-2026-05-0032                  │ │
+│ └──────────────────────────────────┘ │
+│                                      │
+│         [ 确认归档 ]                  │
+└──────────────────────────────────────┘
+```
+
+---
+
+## 五、角色权限矩阵
+
+### 5.1 页面可见性
+
+| 页面 | 员工 | 经理 | 财务 | 管理员 |
+|------|:--:|:--:|:--:|:--:|
+| `/` (Appshell) | ✅ | ✅ | ✅ | ✅ |
+| `/messages` | ✅ | ✅ | ✅ | ✅ |
+| `/home` | 员工版 | +待审批卡片 | +财务看盘 | +公告入口 |
+| `/profile` | ✅ | ✅ | ✅ | ✅ |
+| `/expense-apply/apply` | ✅ | ✅ | — | — |
+| `/expense/apply` | ✅ | ✅ | — | — |
+| `/expense-apply/list` | 我的 | +下属标签 | 全公司(只读) | — |
+| `/expense/list` | 我的 | +下属标签 | +待付款Chip | — |
+| `/expense-apply/detail/:id` | 员工版 | 经理版 | — | 管理员版 |
+| `/expense/detail/:id` | 员工版 | 经理版 | 财务版 | 管理员版 |
+| `/overtime/apply` | ✅ | ✅ | — | — |
+| `/overtime/list` | 我的 | +下属标签 | 全公司(只读) | — |
+| `/overtime/detail/:id` | 员工版 | 经理版 | — | 管理员版 |
+| `/vehicle/apply` | ✅ | ✅ | — | — |
+| `/vehicle/list` | 我的 | +下属标签 | 全公司(只读) | — |
+| `/vehicle/detail/:id` | 员工版 | 经理版 | — | 管理员版 |
+| `/outing-log/create` | ✅ | ✅ | — | — |
+| `/outing-log/list` | 我的 | +下属标签 | — | — |
+| `/outing-log/detail/:id` | 员工版 | +点评区 | — | — |
+| `/announcement/list` | ✅ | ✅ | ✅ | +我的草稿Chip |
+| `/announcement/detail/:id` | ✅ | ✅ | ✅ | +触达审计 |
+| `/report/*` | 个人 | 部门 | 全公司+导出 | — |
+| `/announcement/create` | — | — | — | ✅ |
+| `/admin/permissions` | — | — | — | ✅ |
+
+### 5.2 角色判定优先级
+
+```
+Admin > Finance > Approver > Employee
+```
+
+高优先级角色叠加低优先级角色的功能块。例如:用户同时拥有 Approver + Employee → 展示经理版工作台 + 员工版列表切换。
+
+---
+
+## 六、表单校验规则汇总
+
+### 6.1 事前申请表单
+
+| 字段 | 规则 | 触发时机 | 违反行为 |
+|------|------|---------|---------|
+| 费用事由 | 必填,≤200字 | 提交时 | ScrollTo + 红框 + `TDMessage`"请填写费用事由" |
+| 关联项目 | 草稿可空,提交必填 | 提交时 | 同上"请选择关联项目" |
+| 预算科目 | 草稿可空,提交必填 | 提交时 | 同上"请选择预算科目" |
+| 预估金额合计 | 可超预算,仅警告 | 实时 | 金额变红 + 警告文本"已超支,将触发高管特批" |
+| 单张图片 | ≤10MB | 上传时 | `TDToast`"文件大小超过限制" |
+| 单份 PDF | ≤20MB | 上传时 | 同上 |
+
+### 6.2 费用报销表单
+
+| 字段 | 规则 | 触发时机 | 违反行为 |
+|------|------|---------|---------|
+| 银行账号 | 16-19位数字 | 实时(前端) + 提交(后端) | 红色提示"请输入正确的银行账号" |
+| 发票金额 | 纯数字 | 输入时 | 键盘限制,不接受非数字 |
+| 关联项目 | 草稿可空,提交必填 | 提交时 | ScrollTo 报错 |
+| 预算科目 | 草稿可空,提交必填 | 提交时 | 同上 |
+| 单张发票图片 | ≤10MB | 上传时 | Toast 提示 |
+
+### 6.3 加班申请表单
+
+| 字段 | 规则 | 触发时机 | 违反行为 |
+|------|------|---------|---------|
+| 净工时 | >0 | 实时 | 显示"0小时"+变红+提交按钮置灰 |
+| 开始时间 < 结束时间 | 不晚于 | 实时 | 边框变红+提示+提交按钮置灰 |
+| 混合比例 | 10%-90% | 滑块限制 | 滑块无法拖出范围 |
+
+### 6.4 用车申请表单
+
+| 字段 | 规则 | 触发时机 | 违反行为 |
+|------|------|---------|---------|
+| 还车时间 > 出车时间 | 不晚于 | 实时 | 红色提示+提交按钮置灰 |
+| 车牌+时间排期冲突 | 无重叠预订 | 异步校验 | 红色文本"排期冲突"+提交按钮锁死 |
+| 同行人数输入0 | 自动调整 | 失焦 | 0→1 |
+
+### 6.5 还车核销
+
+| 字段 | 规则 | 触发时机 | 违反行为 |
+|------|------|---------|---------|
+| 还车里程 ≥ 出车里程 | 不小于 | 实时 | 红色提示"还车里程不能小于出车里程"+提交按钮置灰 |
+
+### 6.6 外勤日志
+
+| 字段 | 规则 | 触发时机 | 违反行为 |
+|------|------|---------|---------|
+| GPS 定位 | 提交时必填 | 提交时 | 提交按钮置灰+"请先获取当前位置" |
+| 现场拍照 | ≥1张 | 提交时 | 提交按钮置灰+"请至少拍摄一张现场照片" |
+
+### 6.7 审批操作
+
+| 字段 | 规则 | 触发时机 | 违反行为 |
+|------|------|---------|---------|
+| 拒绝理由 | ≥5字(汉字) | 弹窗内输入 | 确定按钮置灰+提示"请输入至少5个字" |
+
+### 6.8 财务核销
+
+| 字段 | 规则 | 触发时机 | 违反行为 |
+|------|------|---------|---------|
+| 合规复选框 ×3 | 全部勾选 | 页面加载 | 打款按钮置灰(视觉锁定) |
+| 电汇流水号 | 必填 | 提交时 | 红色边框+提示"请输入公司转账电汇流水号" |
+| 记账凭证号 | 必填 | 提交时 | 红色边框+提示"请输入财务记账凭证号" |
+
+---
+
+## 七、页面完整 Mock 数据示例
+
+### 7.1 工作台首页完整响应
+
+```json
+{
+  "banners": [
+    { "imageUrl": "/banners/1.jpg", "title": "2026年Q2全员大会", "linkUrl": "/announcement/detail/ann-005" },
+    { "imageUrl": "/banners/2.jpg", "title": "端午节放假通知", "linkUrl": null },
+    { "imageUrl": "/banners/3.jpg", "title": "安全生产月活动", "linkUrl": "/announcement/detail/ann-006" }
+  ],
+  "quickStats": {
+    "monthExpenseTotal": 12350.00,
+    "monthApplicationCount": 8,
+    "pendingProcessCount": 2
+  },
+  "managerPending": {
+    "pendingCount": 8,
+    "recentItems": [
+      { "applicantName": "张三", "bizTypeName": "费用报销", "amount": 12350.00, "createTime": "2026-05-30T10:00:00Z" }
+    ]
+  },
+  "financeDashboard": {
+    "monthPaidAmount": 285600.00,
+    "pendingPaymentAmount": 152300.00,
+    "weekAbnormalInvoices": 3
+  }
+}
+```
+
+### 7.2 消息列表完整响应
+
+```json
+{
+  "total": 25,
+  "page": 1,
+  "unreadCount": 5,
+  "items": [
+    {
+      "id": "msg-001",
+      "msgType": "approval_notice",
+      "bizType": "expense",
+      "bizId": "exp-001",
+      "title": "张三提交了一笔费用报销",
+      "sender": { "realName": "张三", "avatarUrl": "/avatars/u-001.jpg" },
+      "content": "差旅费报销 — 深圳出差 ¥12,350.00",
+      "isRead": false,
+      "createTime": "2026-05-30T14:30:00Z"
+    },
+    {
+      "id": "msg-002",
+      "msgType": "approval_result",
+      "bizType": "expense_apply",
+      "bizId": "ea-003",
+      "title": "王经理拒绝了您的事前申请",
+      "sender": { "realName": "王经理", "avatarUrl": "/avatars/u-002.jpg" },
+      "content": "预算不足,请调整后重新提交",
+      "isRead": true,
+      "createTime": "2026-05-29T16:00:00Z"
+    },
+    {
+      "id": "msg-003",
+      "msgType": "announcement",
+      "bizType": "announcement",
+      "bizId": "ann-005",
+      "title": "2026年Q2全员大会通知",
+      "sender": { "realName": "系统管理员", "avatarUrl": "/avatars/u-admin.jpg" },
+      "content": "定于6月5日下午3点在3楼会议室召开全员大会",
+      "isRead": false,
+      "createTime": "2026-05-30T08:00:00Z"
+    }
+  ]
+}
+```
+
+---
+
+## 八、导航关系图(带权限分支)
+
+```
+/ (Appshell)
+│
+├── /messages ─────────────────────────────────────────────────
+│   │ (审批待办) → /{bizType}/detail/:id  (底部带审批操作栏)
+│   │ (审批结果) → /{bizType}/detail/:id
+│   │ (公告通知) → /announcement/detail/:id
+│   │ (纯通知)   → TDDialog 弹窗
+│   │
+│   └── 全部已读: POST /api/messages/read-all
+│       标记已读: PUT /api/messages/:id/read
+│       删除消息: PUT /api/messages/:id/delete
+│
+├── /home ───────────────────────────────────────────────────
+│   │ [员工] 轮播图 + 金刚区(8格) + 快捷看板(3卡片)
+│   │ [经理] +待审批卡片区 (→ /messages?filter=approval_notice)
+│   │ [财务] +全公司财务看盘
+│   │
+│   ├── 金刚区-发起 → /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 ──────────────────────────────────────────────────
+│   ├── 我的审批历史 (子页面)
+│   │   └── 点击单据号 → /{bizType}/detail/:id
+│   ├── 我的报表 (子页面, 5 Tab)
+│   │   └── → /report/{bizType}-detail
+│   ├── 关于 (子页面)
+│   └── 头像上传: PUT /api/user/avatar
+│
+├── /expense-apply/apply ──(存草稿/提交)──→ /expense-apply/list
+├── /expense/apply ────────(存草稿/提交)──→ /expense/list
+├── /vehicle/apply ────────(存草稿/提交)──→ /vehicle/list
+├── /overtime/apply ───────(存草稿/提交)──→ /overtime/list
+├── /outing-log/create ────(存草稿/提交)──→ /outing-log/list
+│
+├── /announcement/create [仅管理员] ────→ /announcement/list
+├── /admin/permissions [仅管理员]
+│
+└── 报表 /report/{bizType}-detail [员工/经理/财务]
+```
+
+**表单→列表→详情 核心流转**:
+```
+apply ──存为草稿──→ list (激活"草稿"Chip) ──左滑编辑──→ apply?id=xxx
+  │                                          │
+  └──提交审批──→ list (激活"全部"Chip)       └──点击卡片──→ detail/:id
+                                                             │
+                    rejected ←── 经理拒绝                      │
+                    approved  ←── 经理同意                     │
+                    withdrawn ←── 员工撤回                     │
+                                                             │
+                    └── rejected → 重新编辑 → apply?id=xxx (更新原记录)
+```