Kaynağa Gözat

chore: archive OpenSpec changes weapp-capsule-safearea and weapp-fixes-and-schedule-creation

xuyunhui 1 hafta önce
ebeveyn
işleme
874277fbe2
25 değiştirilmiş dosya ile 702 ekleme ve 4 silme
  1. 11 0
      docs/superpowers/plans/2026-06-24-weapp-capsule-safearea.md
  2. 4 0
      docs/superpowers/plans/2026-06-24-weapp-fixes-and-schedule-creation.md
  3. 2 0
      docs/superpowers/specs/2026-06-24-weapp-capsule-safearea-design.md
  4. 128 0
      docs/superpowers/specs/2026-06-24-weapp-fixes-and-schedule-creation-design.md
  5. 4 4
      openspec/changes/archive/2026-06-24-weapp-capsule-safearea/.comet.yaml
  6. 0 0
      openspec/changes/archive/2026-06-24-weapp-capsule-safearea/.comet/handoff/brainstorm-summary.md
  7. 0 0
      openspec/changes/archive/2026-06-24-weapp-capsule-safearea/.comet/handoff/design-context.json
  8. 0 0
      openspec/changes/archive/2026-06-24-weapp-capsule-safearea/.comet/handoff/design-context.md
  9. 0 0
      openspec/changes/archive/2026-06-24-weapp-capsule-safearea/.comet/subagent-progress.md
  10. 0 0
      openspec/changes/archive/2026-06-24-weapp-capsule-safearea/.openspec.yaml
  11. 0 0
      openspec/changes/archive/2026-06-24-weapp-capsule-safearea/design.md
  12. 0 0
      openspec/changes/archive/2026-06-24-weapp-capsule-safearea/proposal.md
  13. 0 0
      openspec/changes/archive/2026-06-24-weapp-capsule-safearea/specs/weapp-capsule-safearea/spec.md
  14. 0 0
      openspec/changes/archive/2026-06-24-weapp-capsule-safearea/tasks.md
  15. 24 0
      openspec/changes/archive/2026-06-25-weapp-fixes-and-schedule-creation/.comet.yaml
  16. 30 0
      openspec/changes/archive/2026-06-25-weapp-fixes-and-schedule-creation/.comet/handoff/brainstorm-summary.md
  17. 14 0
      openspec/changes/archive/2026-06-25-weapp-fixes-and-schedule-creation/.comet/handoff/design-context.json
  18. 237 0
      openspec/changes/archive/2026-06-25-weapp-fixes-and-schedule-creation/.comet/handoff/design-context.md
  19. 2 0
      openspec/changes/archive/2026-06-25-weapp-fixes-and-schedule-creation/.openspec.yaml
  20. 74 0
      openspec/changes/archive/2026-06-25-weapp-fixes-and-schedule-creation/design.md
  21. 25 0
      openspec/changes/archive/2026-06-25-weapp-fixes-and-schedule-creation/proposal.md
  22. 48 0
      openspec/changes/archive/2026-06-25-weapp-fixes-and-schedule-creation/specs/schedule-creation/spec.md
  23. 0 0
      openspec/changes/archive/2026-06-25-weapp-fixes-and-schedule-creation/tasks.md
  24. 44 0
      openspec/specs/schedule-creation/spec.md
  25. 55 0
      openspec/specs/weapp-capsule-safearea/spec.md

+ 11 - 0
docs/superpowers/plans/2026-06-24-weapp-capsule-safearea.md

@@ -2,6 +2,7 @@
 change: weapp-capsule-safearea
 design-doc: docs/superpowers/specs/2026-06-24-weapp-capsule-safearea-design.md
 base-ref: fe7ae882ea6905abf5f97f370efe8ffee9a7134f
+archived-with: 2026-06-24-weapp-capsule-safearea
 ---
 
 # 微信小程序胶囊安全区适配实施计划
@@ -39,6 +40,7 @@ base-ref: fe7ae882ea6905abf5f97f370efe8ffee9a7134f
 | `src/components/task/TaskListView.vue` | 修改 | 顶部自定义标题栏改为 `<TopBar>`,右侧放发布/新增按钮;筛选标签保留在 TopBar 下方 |
 | `src/components/dispatch/ScheduleView.vue` | 修改 | 右侧 slot 同时放入「今天」和「新增排班」两个按钮;月份切换行右侧清空 |
 
+archived-with: 2026-06-24-weapp-capsule-safearea
 ---
 
 ### Task 1: 创建 CapsuleSafeArea.vue 组件
@@ -108,6 +110,7 @@ git add src/components/common/CapsuleSafeArea.vue
 git commit -m "feat: add CapsuleSafeArea component for weapp capsule button safe area"
 ```
 
+archived-with: 2026-06-24-weapp-capsule-safearea
 ---
 
 ### Task 2: 改造 TopBar.vue 集成 CapsuleSafeArea
@@ -204,6 +207,7 @@ git add src/components/common/TopBar.vue
 git commit -m "feat: wrap TopBar right slot with CapsuleSafeArea, add min-w-0 for title truncation"
 ```
 
+archived-with: 2026-06-24-weapp-capsule-safearea
 ---
 
 ### Task 3: 改造调度端首页 DispatchHome.vue
@@ -282,6 +286,7 @@ git add src/components/home/DispatchHome.vue
 git commit -m "feat: DispatchHome use TopBar with CapsuleSafeArea for notification bell"
 ```
 
+archived-with: 2026-06-24-weapp-capsule-safearea
 ---
 
 ### Task 4: 改造销售端首页 SalesHome.vue
@@ -360,6 +365,7 @@ git add src/components/home/SalesHome.vue
 git commit -m "feat: SalesHome use TopBar with CapsuleSafeArea for notification bell"
 ```
 
+archived-with: 2026-06-24-weapp-capsule-safearea
 ---
 
 ### Task 5: 改造施工端首页 ConstructionHome.vue
@@ -436,6 +442,7 @@ git add src/components/home/ConstructionHome.vue
 git commit -m "feat: ConstructionHome use TopBar with CapsuleSafeArea for notification bell"
 ```
 
+archived-with: 2026-06-24-weapp-capsule-safearea
 ---
 
 ### Task 6: 改造任务列表页 TaskListView.vue
@@ -501,6 +508,7 @@ git add src/components/task/TaskListView.vue
 git commit -m "feat: TaskListView use TopBar with CapsuleSafeArea for publish button"
 ```
 
+archived-with: 2026-06-24-weapp-capsule-safearea
 ---
 
 ### Task 7: 改造排班页 ScheduleView.vue
@@ -610,6 +618,7 @@ git add src/components/dispatch/ScheduleView.vue
 git commit -m "feat: ScheduleView move today and add-schedule buttons to TopBar right slot with CapsuleSafeArea"
 ```
 
+archived-with: 2026-06-24-weapp-capsule-safearea
 ---
 
 ### Task 8: 类型检查与构建验证
@@ -652,6 +661,7 @@ Expected: 构建成功,无错误。确认非微信环境下布局与之前一
 git commit -m "chore: validation passed for CapsuleSafeArea integration" --allow-empty
 ```
 
+archived-with: 2026-06-24-weapp-capsule-safearea
 ---
 
 ## Self-Review Checklist
@@ -687,6 +697,7 @@ git commit -m "chore: validation passed for CapsuleSafeArea integration" --allow
 - `TopBar` 的 `title` prop 类型保持 `string`,`showBack` 保持 `boolean` 可选(默认 `true`)。
 - 所有首页的 `TopBar` 使用 `title=""`(空字符串,符合 `string` 类型)。
 
+archived-with: 2026-06-24-weapp-capsule-safearea
 ---
 
 **Plan complete and saved to `docs/superpowers/plans/2026-06-24-weapp-capsule-safearea.md`.**

+ 4 - 0
docs/superpowers/plans/2026-06-24-weapp-fixes-and-schedule-creation.md

@@ -1,3 +1,7 @@
+---
+archived-with: 2026-06-25-weapp-fixes-and-schedule-creation
+status: final
+---
 # 清道夫 App 5 项修复与排班新增实施计划
 
 > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [x]`) syntax for tracking.

+ 2 - 0
docs/superpowers/specs/2026-06-24-weapp-capsule-safearea-design.md

@@ -2,6 +2,8 @@
 comet_change: weapp-capsule-safearea
 role: technical-design
 canonical_spec: openspec
+archived-with: 2026-06-24-weapp-capsule-safearea
+status: final
 ---
 
 # 微信小程序胶囊安全区适配设计

+ 128 - 0
docs/superpowers/specs/2026-06-24-weapp-fixes-and-schedule-creation-design.md

@@ -0,0 +1,128 @@
+---
+comet_change: weapp-fixes-and-schedule-creation
+role: technical-design
+canonical_spec: openspec
+archived-with: 2026-06-25-weapp-fixes-and-schedule-creation
+status: final
+---
+
+# 清道夫 App 5 项修复与排班新增设计文档
+
+## 变更概述
+
+本次变更修复清道夫 App 的 5 个 UI/交互问题,并补全后端缺失的车辆下拉接口:
+
+1. tab 页面 TopBar 出现多余返回按钮。
+2. 任务页发布/新增按钮仍被微信胶囊遮挡。
+3. 排班页无法新增排班。
+4. 自定义 tabBar 切换后高亮不同步。
+5. 退出登录无动画、卡顿。
+
+## 上下文
+
+- 前端:uni-app Vue 3 + TypeScript,自定义导航栏 `navigationStyle: custom`。
+- 通用组件:`TopBar.vue`、`CapsuleSafeArea.vue`。
+- 自定义 tabBar:`src/custom-tab-bar/index.js`。
+- 后端:Java Spring Boot + MyBatis-Plus。
+- 用户要求:所有 API 以后端接口为准;缺失则后端补全。
+
+## 目标与非目标
+
+**目标:**
+- tab 页面 TopBar 不显示返回按钮。
+- 任务页新增/发布按钮完全避开微信胶囊。
+- 排班页可按 V21-SOP 原型新增排班并保存到后端。
+- tabBar 高亮与当前页面实时同步。
+- 退出登录动画流畅、无卡顿。
+- 后端补全 `/vehicle/simple-list`。
+
+**非目标:**
+- 不重构导航/tabBar 整体架构。
+- 不改变任务/排班核心业务状态机。
+- 不新增排班以外的调度功能。
+
+## 技术方案
+
+### 1. TopBar 返回按钮
+
+- 修改 `src/components/common/TopBar.vue`,将 `showBack` 默认值从 `true` 改为 `false`。
+- tab 页面无需传入;非 tab 页面若需返回,显式传入 `:showBack="true"`。
+- 全局搜索 `<TopBar` 使用处,为需要返回的非 tab 页面补充属性。
+
+### 2. 任务页发布按钮胶囊遮挡
+
+- 确认 `TaskListView.vue` 的发布/新增按钮已放入 `TopBar` 的 `right` slot。
+- 确认 `TopBar.vue` 的 right slot 外层已包裹 `<CapsuleSafeArea>`。
+- 若 `CapsuleSafeArea` 计算的安全宽度仍不足,检查 `safeWidth` 公式与微信胶囊边界,必要时调整按钮内边距或字体大小,确保按钮完整可见且可点击。
+
+### 3. 排班页新增排班
+
+在 `ScheduleView.vue` 内实现新增排班弹窗:
+
+**表单字段(对齐后端 `DispatchSchedule`):**
+| 原型字段 | 提交字段 | 说明 |
+|---|---|---|
+| 班组 | `teamId` / `teamName` | 下拉 `/team/simple-list` |
+| 工作日期 | `workDate` | `uni-datetime-picker` 或日期选择器,格式 `yyyy-MM-dd` |
+| 班次类型 | `shiftType` | 月计划 → `month_plan`;应急 → `emergency` |
+| 车辆 | `vehicleIds` | 多选,调用 `/vehicle/simple-list` |
+| 人员 | `staffIds` | 多选,调用 `/staff/simple-list` |
+| 备注 | `remark` | 文本输入 |
+| 状态 | `status` | 默认 `idle` 或 `0`,与后端约定 |
+
+**API 调整:**
+- 更新 `src/api/schedule.ts` 的 `createSchedule` 参数,改为接收 `DispatchSchedule` 对象。
+- 更新 `src/api/vehicle.ts`,新增/复用 `getVehicleSimpleList()` 调用 `/vehicle/simple-list`。
+
+**后端补全:**
+- `VehicleController.java` 新增 `GET /vehicle/simple-list`,返回 `List<Map<String, Object>>`,结构 `{ value: vehicleId, label: plateNo }`。
+- `VehicleService.java` 新增 `simpleList()` 查询未删除车辆列表。
+
+### 4. 自定义 tabBar 高亮同步
+
+- 在每个 tab 页面的 `onShow` 生命周期中调用 `this.getTabBar()?.setData({ selected: <index> })`。
+- `custom-tab-bar/index.js` 保持 `selected` 数据字段响应式,无需额外逻辑。
+- tab 索引映射:home=0,task=1,schedule=2,my=3(以当前代码为准)。
+
+### 5. 退出登录卡顿
+
+- 调整 `ProfileView.vue` 中 `logout` 方法顺序:
+  1. 先调用 `uni.reLaunch({ url: '/pages/login/login' })` 触发页面切换动画。
+  2. 再调用 `authStore.doLogout()` 清理 token、用户信息。
+  3. toast 提示在跳转后可选显示或省略,避免阻塞主线程。
+
+## 数据流
+
+```
+[ScheduleView] 打开弹窗
+    ├── GET /team/simple-list  → 班组下拉
+    ├── GET /vehicle/simple-list → 车辆多选
+    ├── GET /staff/simple-list  → 人员多选
+    └── POST /schedule         → 保存排班
+            └── GET /schedule/date/{workDate} → 刷新列表
+```
+
+## 测试策略
+
+- `npm run type-check` 无 TS 错误。
+- `npm run build:mp-weixin` 构建通过。
+- 微信开发者工具真机预览:
+  - tab 页面无返回按钮。
+  - 任务页发布按钮可点击、不与胶囊重叠。
+  - 排班新增完整流程:选择班组/日期/类型/车辆/人员 → 保存 → 列表刷新。
+  - 切换 tab 时 tabBar 高亮即时更新。
+  - 退出登录动画流畅。
+- 后端:`mvn compile` 通过,`/vehicle/simple-list` 返回正确格式。
+
+## 风险与缓解
+
+| 风险 | 缓解 |
+|---|---|
+| `TopBar` 默认关闭返回后,非 tab 页面遗漏补充 | 全局搜索使用处并逐一确认 |
+| 车辆下拉后端接口未部署 | 本次同时修改前端与后端,按用户要求后端补全 |
+| tabBar `getTabBar()` 在页面未挂载时为 null | 使用可选链 `?.setData` |
+| 退出登录清理逻辑在跳转后执行失败 | 确保 `authStore.doLogout()` 不依赖当前页面上下文 |
+
+## Spec Patch
+
+无。delta spec `schedule-creation` 已覆盖新增排班需求;其余修复为既有能力实现层修正,未改变 spec 级需求。

+ 4 - 4
openspec/changes/weapp-capsule-safearea/.comet.yaml → openspec/changes/archive/2026-06-24-weapp-capsule-safearea/.comet.yaml

@@ -1,5 +1,5 @@
 workflow: full
-phase: verify
+phase: archive
 context_compression: off
 build_mode: subagent-driven-development
 build_pause: null
@@ -14,10 +14,10 @@ design_doc: docs/superpowers/specs/2026-06-24-weapp-capsule-safearea-design.md
 plan: docs/superpowers/plans/2026-06-24-weapp-capsule-safearea.md
 verify_result: pass
 verification_report: docs/superpowers/reports/2026-06-24-weapp-capsule-safearea-verify.md
-branch_status: pending
+branch_status: handled
 created_at: 2026-06-24
-verified_at: null
-archived: false
+verified_at: 2026-06-24
+archived: true
 handoff_context: openspec/changes/weapp-capsule-safearea/.comet/handoff/design-context.json
 handoff_hash: aa611532c57837edccdaa3c5221ab2e70b42ac50630cca269c20b0a2dbbd2af3
 build_command: npm run build:mp-weixin

+ 0 - 0
openspec/changes/weapp-capsule-safearea/.comet/handoff/brainstorm-summary.md → openspec/changes/archive/2026-06-24-weapp-capsule-safearea/.comet/handoff/brainstorm-summary.md


+ 0 - 0
openspec/changes/weapp-capsule-safearea/.comet/handoff/design-context.json → openspec/changes/archive/2026-06-24-weapp-capsule-safearea/.comet/handoff/design-context.json


+ 0 - 0
openspec/changes/weapp-capsule-safearea/.comet/handoff/design-context.md → openspec/changes/archive/2026-06-24-weapp-capsule-safearea/.comet/handoff/design-context.md


+ 0 - 0
openspec/changes/weapp-capsule-safearea/.comet/subagent-progress.md → openspec/changes/archive/2026-06-24-weapp-capsule-safearea/.comet/subagent-progress.md


+ 0 - 0
openspec/changes/weapp-capsule-safearea/.openspec.yaml → openspec/changes/archive/2026-06-24-weapp-capsule-safearea/.openspec.yaml


+ 0 - 0
openspec/changes/weapp-capsule-safearea/design.md → openspec/changes/archive/2026-06-24-weapp-capsule-safearea/design.md


+ 0 - 0
openspec/changes/weapp-capsule-safearea/proposal.md → openspec/changes/archive/2026-06-24-weapp-capsule-safearea/proposal.md


+ 0 - 0
openspec/changes/weapp-capsule-safearea/specs/weapp-capsule-safearea/spec.md → openspec/changes/archive/2026-06-24-weapp-capsule-safearea/specs/weapp-capsule-safearea/spec.md


+ 0 - 0
openspec/changes/weapp-capsule-safearea/tasks.md → openspec/changes/archive/2026-06-24-weapp-capsule-safearea/tasks.md


+ 24 - 0
openspec/changes/archive/2026-06-25-weapp-fixes-and-schedule-creation/.comet.yaml

@@ -0,0 +1,24 @@
+workflow: full
+phase: archive
+context_compression: off
+build_mode: executing-plans
+build_pause: null
+subagent_dispatch: null
+tdd_mode: direct
+review_mode: standard
+isolation: branch
+verify_mode: full
+auto_transition: true
+base_ref: ea69785ac75bf2d11d7848e474f3539cdd6a2fee
+design_doc: docs/superpowers/specs/2026-06-24-weapp-fixes-and-schedule-creation-design.md
+plan: docs/superpowers/plans/2026-06-24-weapp-fixes-and-schedule-creation.md
+verify_result: pass
+verification_report: docs/superpowers/reports/2026-06-24-weapp-fixes-and-schedule-creation-verify.md
+branch_status: handled
+created_at: 2026-06-25
+verified_at: 2026-06-25
+archived: true
+handoff_context: openspec/changes/weapp-fixes-and-schedule-creation/.comet/handoff/design-context.json
+handoff_hash: fbd4d371098581149798d176bc0180b6b9eee40b29afc5b01cb7fcbb66ad0352
+build_command: npm run build:mp-weixin
+verify_command: npm run type-check

+ 30 - 0
openspec/changes/archive/2026-06-25-weapp-fixes-and-schedule-creation/.comet/handoff/brainstorm-summary.md

@@ -0,0 +1,30 @@
+# Brainstorm Summary
+
+- Change: weapp-fixes-and-schedule-creation
+- Date: 2026-06-24
+
+## 确认的技术方案
+
+基于 OpenSpec proposal/design/specs 与用户在先前对话中的确认,采用以下方案一次性修复 5 个问题:
+
+1. **TopBar 返回按钮**:`TopBar` 默认 `showBack=false`,非 tab 页面显式开启。
+2. **任务页胶囊遮挡**:确认并调整 `TaskListView` 在 `TopBar` right slot 的按钮布局,确保 `CapsuleSafeArea` 生效。
+3. **排班新增**:在 `ScheduleView` 内实现弹窗表单,字段对齐后端 `DispatchSchedule`,调用 `POST /schedule`;后端补全 `/vehicle/simple-list`。
+4. **tabBar 高亮同步**:tab 页面 `onShow` 显式 `getTabBar().setData({ selected })`。
+5. **退出登录卡顿**:先 `uni.reLaunch` 跳转登录页,再执行清理。
+
+## 关键取舍与风险
+
+- 选择弹窗而非新页面实现排班新增,保持当前页面上下文,符合原型。
+- 后端补全 `/vehicle/simple-list` 而非前端用 `/vehicle/list?pageSize=100`,严格遵循“以后端接口为准,缺失则补全”。
+- 风险:`TopBar` 默认关闭返回可能影响非 tab 页面;缓解:全局搜索并补充 `:showBack="true"`。
+
+## 测试策略
+
+- 前端 type-check 与构建通过。
+- 微信开发者工具/真机预览验证 5 个问题。
+- 后端编译与 `/vehicle/simple-list` 接口验证。
+
+## Spec Patch
+
+无。

+ 14 - 0
openspec/changes/archive/2026-06-25-weapp-fixes-and-schedule-creation/.comet/handoff/design-context.json

@@ -0,0 +1,14 @@
+{
+  "change": "weapp-fixes-and-schedule-creation",
+  "phase": "design",
+  "mode": "compact",
+  "canonical_spec": "openspec",
+  "generated_by": "comet-handoff.sh",
+  "context_hash": "fbd4d371098581149798d176bc0180b6b9eee40b29afc5b01cb7fcbb66ad0352",
+  "files": [
+    { "path": "openspec/changes/weapp-fixes-and-schedule-creation/proposal.md", "sha256": "7d44bf59909b1d8861860c6107dd35fc17c1a9247584cbb05abe113535a9f823" },
+    { "path": "openspec/changes/weapp-fixes-and-schedule-creation/design.md", "sha256": "f1fc2bd669651006f9a686a48639964aabcc26e146a74b428e09a6a0989d838f" },
+    { "path": "openspec/changes/weapp-fixes-and-schedule-creation/tasks.md", "sha256": "fdc5606154bc3a4b6b24b60de0eb92db8ce016d0b8d3a42a1096c209e2bbd46c" },
+    { "path": "openspec/changes/weapp-fixes-and-schedule-creation/specs/schedule-creation/spec.md", "sha256": "2006b8ae40885ef27c038a56c31103f83180d292b62feb8cfb3f48f1c510201e" }
+  ]
+}

+ 237 - 0
openspec/changes/archive/2026-06-25-weapp-fixes-and-schedule-creation/.comet/handoff/design-context.md

@@ -0,0 +1,237 @@
+# Comet Design Handoff
+
+- Change: weapp-fixes-and-schedule-creation
+- Phase: design
+- Mode: compact
+- Context hash: fbd4d371098581149798d176bc0180b6b9eee40b29afc5b01cb7fcbb66ad0352
+
+Generated-by: comet-handoff.sh
+
+OpenSpec remains the canonical capability spec. This handoff is a deterministic, source-traceable context pack, not an agent-authored summary.
+
+## openspec/changes/weapp-fixes-and-schedule-creation/proposal.md
+
+- Source: openspec/changes/weapp-fixes-and-schedule-creation/proposal.md
+- Lines: 1-25
+- SHA256: 7d44bf59909b1d8861860c6107dd35fc17c1a9247584cbb05abe113535a9f823
+
+```md
+## Why
+
+清道夫 App 在 V21-SOP 原型验证过程中暴露出 5 个影响体验的 UI/交互问题:tab 页面 TopBar 出现多余的返回按钮、任务页发布按钮仍被微信胶囊遮挡、排班页无法新增排班、自定义 tabBar 高亮切换滞后、退出登录无动画且卡顿。本次变更一次性修复这 5 个问题,并严格以后端现有接口为准,缺失接口则在后端补全。
+
+## What Changes
+
+- **移除 tab 页 TopBar 返回按钮**:`TopBar` 默认 `showBack` 改为 `false`;仅非 tab 页面显式开启返回按钮。
+- **修复任务页发布/新增按钮被胶囊遮挡**:重新调整 `TaskListView` 在 `TopBar` 右侧插槽的按钮布局,确保胶囊安全区计算生效。
+- **实现排班页新增排班**:按 V21-SOP 原型交互,在 `ScheduleView` 中新增排班表单弹窗/页面,调用 `/schedule` POST 接口;前端车辆下拉调用后端接口,缺失 `/vehicle/simple-list` 时后端补全该接口。
+- **修复自定义 tabBar 高亮不同步**:在 tab 页面 `onShow` 中显式调用 `setData({ selected })` 刷新自定义 tabBar 高亮状态。
+- **修复退出登录卡顿无动画**:调整 `ProfileView` 登出顺序,先 `uni.reLaunch` 跳转登录页,再处理清理与提示,避免阻塞主线程。
+
+## Capabilities
+
+### New Capabilities
+- `schedule-creation`: 排班页新增排班功能,包含表单、后端接口调用、原型交互映射。
+
+### Modified Capabilities
+<!-- 本次其余 4 项均为既有能力的实现缺陷修复,不涉及规格级需求变更;排班新增为全新能力。 -->
+
+## Impact
+
+- 前端:`src/components/common/TopBar.vue`、`src/components/task/TaskListView.vue`、`src/components/dispatch/ScheduleView.vue`、`src/custom-tab-bar/index.js`、`src/components/my/ProfileView.vue`、`src/api/schedule.ts`、`src/api/vehicle.ts`。
+- 后端:`VehicleController.java`、`VehicleService.java`(新增 `/vehicle/simple-list`)。
+- 构建:需保持 `npm run build:mp-weixin` 与 `npm run type-check` 通过。
+```
+
+## openspec/changes/weapp-fixes-and-schedule-creation/design.md
+
+- Source: openspec/changes/weapp-fixes-and-schedule-creation/design.md
+- Lines: 1-74
+- SHA256: f1fc2bd669651006f9a686a48639964aabcc26e146a74b428e09a6a0989d838f
+
+```md
+## Context
+
+清道夫 App 采用 uni-app Vue 3 + TypeScript 开发,页面使用 `navigationStyle: custom` 自定义导航栏。`TopBar` 组件为通用导航头,`CapsuleSafeArea` 负责计算微信胶囊安全区。自定义 tabBar 使用微信小程序 `custom-tab-bar` 组件。后端为 Java Spring Boot + MyBatis-Plus。
+
+当前问题:
+- `TopBar` 默认 `showBack: true`,导致 tab 页面(首页、任务、排班、我的)出现多余返回按钮。
+- 任务页发布/新增按钮虽放入 `TopBar` 右侧插槽,但仍被胶囊遮挡,需要进一步调整。
+- 排班页 `addSchedule()` 仅提示“排班功能开发中”,未实现 V21-SOP 原型的新增排班流程。
+- 自定义 tabBar 在页面切换后高亮状态未同步更新。
+- 退出登录时先执行 `authStore.doLogout()` 和 `uni.showToast`,再 `uni.reLaunch`,导致页面切换无动画、卡顿。
+
+## Goals / Non-Goals
+
+**Goals:**
+- tab 页面 TopBar 不显示返回按钮,非 tab 页面保留返回能力。
+- 任务页新增/发布按钮完全避开微信胶囊,可正常点击。
+- 排班页可按原型新增排班并保存到后端。
+- tabBar 高亮与当前页面实时同步。
+- 退出登录动画流畅、无卡顿。
+- 后端缺失 `/vehicle/simple-list` 时补全该接口,保证前端下拉数据可用。
+
+**Non-Goals:**
+- 不重构整个导航或 tabBar 架构。
+- 不改变任务/排班核心业务状态机。
+- 不新增排班以外的调度功能。
+
+## Decisions
+
+1. **TopBar 默认不显示返回按钮**
+   - 将 `showBack` 默认值改为 `false`;需要返回的页面显式传入 `:showBack="true"`。
+   - 理由:tab 页面是入口页,绝大多数场景不需要返回;显式开启更安全,避免遗漏。
+
+2. **任务页按钮胶囊安全区二次确认**
+   - 检查 `TaskListView` 是否正确将按钮放入 `TopBar` 的 right slot,并确认 `CapsuleSafeArea` 已包裹 right slot。
+   - 如仍被遮挡,调整按钮容器为 `CapsuleSafeArea` 内部元素,确保 `margin-left` 生效。
+
+3. **排班新增采用弹窗表单**
+   - 在 `ScheduleView` 内实现 `uni-popup` 或同项目弹窗组件,表单字段:班组(下拉 `/team/simple-list`)、工作日期(日期选择器)、班次类型(月计划/应急,映射 `month_plan/emergency`)、车辆(多选,调用 `/vehicle/simple-list`)、人员(多选,调用 `/staff/simple-list`)、备注(文本)。
+   - 提交调用 `POST /schedule`,成功后刷新当前日期班表列表。
+   - 理由:与原型一致,保持在当前页面完成新增,避免全页跳转。
+
+4. **后端车辆下拉接口补全 `/vehicle/simple-list`**
+   - 在 `VehicleController` 新增该接口,返回 `{ value: vehicleId, label: plateNo }`。
+   - 理由:前端现有 `getAvailableVehicles()` 调用不存在的 `/vehicle/available`;用户要求以后端接口为准,缺失则补全。
+
+5. **tabBar 高亮同步**
+   - 在每个 tab 页面的 `onShow` 中调用 `uni.setTabBarItem` 不够,因为项目使用自定义 tabBar;需通过 `getTabBar().setData({ selected: index })` 显式同步。
+
+6. **退出登录顺序调整**
+   - 先调用 `uni.reLaunch({ url: '/pages/login/login' })`,再执行 `authStore.doLogout()` 清理 token/state;toast 可在跳转后可选显示或省略。
+   - 理由:`reLaunch` 是同步触发页面切换的 API,放在前面可立即释放当前页面;清理逻辑在后台完成不影响动画。
+
+## Risks / Trade-offs
+
+- [Risk] `TopBar` 默认 `showBack=false` 可能导致已有非 tab 页面依赖默认返回而失效。
+  → Mitigation:全局搜索 `TopBar` 使用处,为非 tab 页面补充 `:showBack="true"`。
+- [Risk] 排班表单字段与后端 `DispatchSchedule` 不完全对齐。
+  → Mitigation:严格参考后端 entity 字段命名,提交前做一次字段映射。
+- [Risk] 自定义 tabBar `getTabBar()` 在页面未完全挂载时可能为 `null`。
+  → Mitigation:使用 `this.getTabBar()?.setData` 并加空值保护。
+- [Risk] 后端新增接口需要重新部署才能生效。
+  → Mitigation:前端同时保留降级方案(如使用 `/vehicle/list?pageSize=100`),但本次按用户要求优先补全后端接口。
+
+## Migration Plan
+
+1. 后端:新增 `/vehicle/simple-list`,重启服务。
+2. 前端:修改 `TopBar`、`TaskListView`、`ScheduleView`、`custom-tab-bar/index.js`、`ProfileView` 及相关 API 文件。
+3. 构建:`npm run type-check` 与 `npm run build:mp-weixin` 验证。
+4. 真机验证:微信开发者工具 + 真机预览,检查胶囊遮挡、tabBar 高亮、退出动画。
+
+## Open Questions
+
+- 任务页发布按钮在当前角色化首页改造后,是否仍命名为“发布”或已改为“新增”?以当前代码为准。
+- V21-SOP 原型文件路径需读取确认排班弹窗具体字段顺序与校验规则。
+```
+
+## openspec/changes/weapp-fixes-and-schedule-creation/tasks.md
+
+- Source: openspec/changes/weapp-fixes-and-schedule-creation/tasks.md
+- Lines: 1-43
+- SHA256: fdc5606154bc3a4b6b24b60de0eb92db8ce016d0b8d3a42a1096c209e2bbd46c
+
+```md
+## 1. 后端接口补全
+
+- [ ] 1.1 在 `VehicleController` 新增 `GET /vehicle/simple-list`,返回 `{ value, label }` 列表
+- [ ] 1.2 在 `VehicleService` 添加 `simpleList()` 查询方法
+- [ ] 1.3 后端编译验证(`mvn compile` 或 IDE 构建)
+
+## 2. TopBar 返回按钮修复
+
+- [ ] 2.1 将 `TopBar` 默认 `showBack` 改为 `false`
+- [ ] 2.2 全局检查 `TopBar` 使用处,为非 tab 页面补充 `:showBack="true"`(如需要)
+- [ ] 2.3 确认 tab 页面(home/task/schedule/my)不再显示返回按钮
+
+## 3. 任务页发布/新增按钮胶囊遮挡修复
+
+- [ ] 3.1 检查 `TaskListView` 中发布/新增按钮是否正确置于 `TopBar` right slot
+- [ ] 3.2 确认 `CapsuleSafeArea` 包裹 right slot 且安全间距生效
+- [ ] 3.3 如仍被遮挡,调整按钮容器使其落在安全区内
+
+## 4. 排班页新增排班功能实现
+
+- [ ] 4.1 更新 `src/api/schedule.ts` 中 `createSchedule` 参数以匹配后端 `DispatchSchedule`
+- [ ] 4.2 更新 `src/api/vehicle.ts`,使用 `/vehicle/simple-list` 获取车辆下拉
+- [ ] 4.3 在 `ScheduleView` 中实现新增排班弹窗/表单(班组、日期、班次类型、车辆、人员、备注)
+- [ ] 4.4 实现班次类型映射:月计划/应急 ↔ `month_plan`/`emergency`
+- [ ] 4.5 实现表单校验与提交,调用 `POST /schedule`
+- [ ] 4.6 提交成功后刷新当前日期班表列表
+
+## 5. 自定义 tabBar 高亮同步修复
+
+- [ ] 5.1 在 tab 页面 `onShow` 中显式调用 `getTabBar().setData({ selected })`
+- [ ] 5.2 确保 `custom-tab-bar/index.js` 中 `selected` 响应式更新
+- [ ] 5.3 验证切换 tab 后高亮即时同步
+
+## 6. 退出登录卡顿修复
+
+- [ ] 6.1 调整 `ProfileView` 登出顺序:先 `uni.reLaunch` 到登录页,再执行清理逻辑
+- [ ] 6.2 移除或延后阻塞式 `uni.showToast`,确保页面切换动画流畅
+
+## 7. 构建与验证
+
+- [ ] 7.1 运行 `npm run type-check` 无错误
+- [ ] 7.2 运行 `npm run build:mp-weixin` 无错误
+- [ ] 7.3 微信开发者工具/真机预览验证 5 个问题均已修复
+```
+
+## openspec/changes/weapp-fixes-and-schedule-creation/specs/schedule-creation/spec.md
+
+- Source: openspec/changes/weapp-fixes-and-schedule-creation/specs/schedule-creation/spec.md
+- Lines: 1-48
+- SHA256: 2006b8ae40885ef27c038a56c31103f83180d292b62feb8cfb3f48f1c510201e
+
+```md
+## ADDED Requirements
+
+### Requirement: Schedule page can create a new schedule
+The system SHALL provide a schedule creation entry on the schedule page that opens a form, collects required fields, and saves a new `DispatchSchedule` via the backend `POST /schedule` endpoint.
+
+#### Scenario: Open create schedule form
+- **WHEN** the user taps the "新增排班" button on `pages/schedule/schedule`
+- **THEN** a form popup opens with fields for team, work date, shift type, vehicles, staff, and remark
+
+#### Scenario: Select team
+- **WHEN** the user opens the team dropdown
+- **THEN** the system calls `GET /team/simple-list` and displays `{ value, label }` options
+
+#### Scenario: Select vehicles
+- **WHEN** the user opens the vehicle selector
+- **THEN** the system calls `GET /vehicle/simple-list` and displays vehicles by plate number
+
+#### Scenario: Select staff
+- **WHEN** the user opens the staff selector
+- **THEN** the system calls `GET /staff/simple-list` and displays staff by name
+
+#### Scenario: Save new schedule
+- **WHEN** the user fills the form and taps save
+- **THEN** the system calls `POST /schedule` with `teamId`, `teamName`, `workDate`, `shiftType` (`month_plan`/`emergency`), `vehicleIds`, `staffIds`, `status`, and `remark`
+- **AND** the popup closes and the schedule list for the selected date refreshes
+
+#### Scenario: Cancel create schedule
+- **WHEN** the user taps cancel or the mask area
+- **THEN** the popup closes without saving
+
+### Requirement: Schedule creation follows V21-SOP prototype interaction
+The system SHALL align the schedule creation flow, field labels, and value mapping with the V21-SOP prototype.
+
+#### Scenario: Shift type mapping
+- **WHEN** the user selects "月计划" or "应急"
+- **THEN** the system stores the value as `month_plan` or `emergency` respectively before submitting to the backend
+
+#### Scenario: Form validation
+- **WHEN** the user attempts to save with missing required fields
+- **THEN** the system shows a validation message and does not call the backend
+
+## MODIFIED Requirements
+
+*No existing spec-level requirements are changed; other fixes in this change are implementation-level corrections to existing behavior.*
+
+## REMOVED Requirements
+
+*None.*
+```
+

+ 2 - 0
openspec/changes/archive/2026-06-25-weapp-fixes-and-schedule-creation/.openspec.yaml

@@ -0,0 +1,2 @@
+schema: spec-driven
+created: 2026-06-25

+ 74 - 0
openspec/changes/archive/2026-06-25-weapp-fixes-and-schedule-creation/design.md

@@ -0,0 +1,74 @@
+## Context
+
+清道夫 App 采用 uni-app Vue 3 + TypeScript 开发,页面使用 `navigationStyle: custom` 自定义导航栏。`TopBar` 组件为通用导航头,`CapsuleSafeArea` 负责计算微信胶囊安全区。自定义 tabBar 使用微信小程序 `custom-tab-bar` 组件。后端为 Java Spring Boot + MyBatis-Plus。
+
+当前问题:
+- `TopBar` 默认 `showBack: true`,导致 tab 页面(首页、任务、排班、我的)出现多余返回按钮。
+- 任务页发布/新增按钮虽放入 `TopBar` 右侧插槽,但仍被胶囊遮挡,需要进一步调整。
+- 排班页 `addSchedule()` 仅提示“排班功能开发中”,未实现 V21-SOP 原型的新增排班流程。
+- 自定义 tabBar 在页面切换后高亮状态未同步更新。
+- 退出登录时先执行 `authStore.doLogout()` 和 `uni.showToast`,再 `uni.reLaunch`,导致页面切换无动画、卡顿。
+
+## Goals / Non-Goals
+
+**Goals:**
+- tab 页面 TopBar 不显示返回按钮,非 tab 页面保留返回能力。
+- 任务页新增/发布按钮完全避开微信胶囊,可正常点击。
+- 排班页可按原型新增排班并保存到后端。
+- tabBar 高亮与当前页面实时同步。
+- 退出登录动画流畅、无卡顿。
+- 后端缺失 `/vehicle/simple-list` 时补全该接口,保证前端下拉数据可用。
+
+**Non-Goals:**
+- 不重构整个导航或 tabBar 架构。
+- 不改变任务/排班核心业务状态机。
+- 不新增排班以外的调度功能。
+
+## Decisions
+
+1. **TopBar 默认不显示返回按钮**
+   - 将 `showBack` 默认值改为 `false`;需要返回的页面显式传入 `:showBack="true"`。
+   - 理由:tab 页面是入口页,绝大多数场景不需要返回;显式开启更安全,避免遗漏。
+
+2. **任务页按钮胶囊安全区二次确认**
+   - 检查 `TaskListView` 是否正确将按钮放入 `TopBar` 的 right slot,并确认 `CapsuleSafeArea` 已包裹 right slot。
+   - 如仍被遮挡,调整按钮容器为 `CapsuleSafeArea` 内部元素,确保 `margin-left` 生效。
+
+3. **排班新增采用弹窗表单**
+   - 在 `ScheduleView` 内实现 `uni-popup` 或同项目弹窗组件,表单字段:班组(下拉 `/team/simple-list`)、工作日期(日期选择器)、班次类型(月计划/应急,映射 `month_plan/emergency`)、车辆(多选,调用 `/vehicle/simple-list`)、人员(多选,调用 `/staff/simple-list`)、备注(文本)。
+   - 提交调用 `POST /schedule`,成功后刷新当前日期班表列表。
+   - 理由:与原型一致,保持在当前页面完成新增,避免全页跳转。
+
+4. **后端车辆下拉接口补全 `/vehicle/simple-list`**
+   - 在 `VehicleController` 新增该接口,返回 `{ value: vehicleId, label: plateNo }`。
+   - 理由:前端现有 `getAvailableVehicles()` 调用不存在的 `/vehicle/available`;用户要求以后端接口为准,缺失则补全。
+
+5. **tabBar 高亮同步**
+   - 在每个 tab 页面的 `onShow` 中调用 `uni.setTabBarItem` 不够,因为项目使用自定义 tabBar;需通过 `getTabBar().setData({ selected: index })` 显式同步。
+
+6. **退出登录顺序调整**
+   - 先调用 `uni.reLaunch({ url: '/pages/login/login' })`,再执行 `authStore.doLogout()` 清理 token/state;toast 可在跳转后可选显示或省略。
+   - 理由:`reLaunch` 是同步触发页面切换的 API,放在前面可立即释放当前页面;清理逻辑在后台完成不影响动画。
+
+## Risks / Trade-offs
+
+- [Risk] `TopBar` 默认 `showBack=false` 可能导致已有非 tab 页面依赖默认返回而失效。
+  → Mitigation:全局搜索 `TopBar` 使用处,为非 tab 页面补充 `:showBack="true"`。
+- [Risk] 排班表单字段与后端 `DispatchSchedule` 不完全对齐。
+  → Mitigation:严格参考后端 entity 字段命名,提交前做一次字段映射。
+- [Risk] 自定义 tabBar `getTabBar()` 在页面未完全挂载时可能为 `null`。
+  → Mitigation:使用 `this.getTabBar()?.setData` 并加空值保护。
+- [Risk] 后端新增接口需要重新部署才能生效。
+  → Mitigation:前端同时保留降级方案(如使用 `/vehicle/list?pageSize=100`),但本次按用户要求优先补全后端接口。
+
+## Migration Plan
+
+1. 后端:新增 `/vehicle/simple-list`,重启服务。
+2. 前端:修改 `TopBar`、`TaskListView`、`ScheduleView`、`custom-tab-bar/index.js`、`ProfileView` 及相关 API 文件。
+3. 构建:`npm run type-check` 与 `npm run build:mp-weixin` 验证。
+4. 真机验证:微信开发者工具 + 真机预览,检查胶囊遮挡、tabBar 高亮、退出动画。
+
+## Open Questions
+
+- 任务页发布按钮在当前角色化首页改造后,是否仍命名为“发布”或已改为“新增”?以当前代码为准。
+- V21-SOP 原型文件路径需读取确认排班弹窗具体字段顺序与校验规则。

+ 25 - 0
openspec/changes/archive/2026-06-25-weapp-fixes-and-schedule-creation/proposal.md

@@ -0,0 +1,25 @@
+## Why
+
+清道夫 App 在 V21-SOP 原型验证过程中暴露出 5 个影响体验的 UI/交互问题:tab 页面 TopBar 出现多余的返回按钮、任务页发布按钮仍被微信胶囊遮挡、排班页无法新增排班、自定义 tabBar 高亮切换滞后、退出登录无动画且卡顿。本次变更一次性修复这 5 个问题,并严格以后端现有接口为准,缺失接口则在后端补全。
+
+## What Changes
+
+- **移除 tab 页 TopBar 返回按钮**:`TopBar` 默认 `showBack` 改为 `false`;仅非 tab 页面显式开启返回按钮。
+- **修复任务页发布/新增按钮被胶囊遮挡**:重新调整 `TaskListView` 在 `TopBar` 右侧插槽的按钮布局,确保胶囊安全区计算生效。
+- **实现排班页新增排班**:按 V21-SOP 原型交互,在 `ScheduleView` 中新增排班表单弹窗/页面,调用 `/schedule` POST 接口;前端车辆下拉调用后端接口,缺失 `/vehicle/simple-list` 时后端补全该接口。
+- **修复自定义 tabBar 高亮不同步**:在 tab 页面 `onShow` 中显式调用 `setData({ selected })` 刷新自定义 tabBar 高亮状态。
+- **修复退出登录卡顿无动画**:调整 `ProfileView` 登出顺序,先 `uni.reLaunch` 跳转登录页,再处理清理与提示,避免阻塞主线程。
+
+## Capabilities
+
+### New Capabilities
+- `schedule-creation`: 排班页新增排班功能,包含表单、后端接口调用、原型交互映射。
+
+### Modified Capabilities
+<!-- 本次其余 4 项均为既有能力的实现缺陷修复,不涉及规格级需求变更;排班新增为全新能力。 -->
+
+## Impact
+
+- 前端:`src/components/common/TopBar.vue`、`src/components/task/TaskListView.vue`、`src/components/dispatch/ScheduleView.vue`、`src/custom-tab-bar/index.js`、`src/components/my/ProfileView.vue`、`src/api/schedule.ts`、`src/api/vehicle.ts`。
+- 后端:`VehicleController.java`、`VehicleService.java`(新增 `/vehicle/simple-list`)。
+- 构建:需保持 `npm run build:mp-weixin` 与 `npm run type-check` 通过。

+ 48 - 0
openspec/changes/archive/2026-06-25-weapp-fixes-and-schedule-creation/specs/schedule-creation/spec.md

@@ -0,0 +1,48 @@
+## ADDED Requirements
+
+### Requirement: Schedule page can create a new schedule
+The system SHALL provide a schedule creation entry on the schedule page that opens a form, collects required fields, and saves a new `DispatchSchedule` via the backend `POST /schedule` endpoint.
+
+#### Scenario: Open create schedule form
+- **WHEN** the user taps the "新增排班" button on `pages/schedule/schedule`
+- **THEN** a form popup opens with fields for team, work date, shift type, vehicles, staff, and remark
+
+#### Scenario: Select team
+- **WHEN** the user opens the team dropdown
+- **THEN** the system calls `GET /team/simple-list` and displays `{ value, label }` options
+
+#### Scenario: Select vehicles
+- **WHEN** the user opens the vehicle selector
+- **THEN** the system calls `GET /vehicle/simple-list` and displays vehicles by plate number
+
+#### Scenario: Select staff
+- **WHEN** the user opens the staff selector
+- **THEN** the system calls `GET /staff/simple-list` and displays staff by name
+
+#### Scenario: Save new schedule
+- **WHEN** the user fills the form and taps save
+- **THEN** the system calls `POST /schedule` with `teamId`, `teamName`, `workDate`, `shiftType` (`month_plan`/`emergency`), `vehicleIds`, `staffIds`, `status`, and `remark`
+- **AND** the popup closes and the schedule list for the selected date refreshes
+
+#### Scenario: Cancel create schedule
+- **WHEN** the user taps cancel or the mask area
+- **THEN** the popup closes without saving
+
+### Requirement: Schedule creation follows V21-SOP prototype interaction
+The system SHALL align the schedule creation flow, field labels, and value mapping with the V21-SOP prototype.
+
+#### Scenario: Shift type mapping
+- **WHEN** the user selects "月计划" or "应急"
+- **THEN** the system stores the value as `month_plan` or `emergency` respectively before submitting to the backend
+
+#### Scenario: Form validation
+- **WHEN** the user attempts to save with missing required fields
+- **THEN** the system shows a validation message and does not call the backend
+
+## MODIFIED Requirements
+
+*No existing spec-level requirements are changed; other fixes in this change are implementation-level corrections to existing behavior.*
+
+## REMOVED Requirements
+
+*None.*

+ 0 - 0
openspec/changes/weapp-fixes-and-schedule-creation/tasks.md → openspec/changes/archive/2026-06-25-weapp-fixes-and-schedule-creation/tasks.md


+ 44 - 0
openspec/specs/schedule-creation/spec.md

@@ -0,0 +1,44 @@
+# schedule-creation Specification
+
+## Purpose
+TBD - created by archiving change weapp-fixes-and-schedule-creation. Update Purpose after archive.
+## Requirements
+### Requirement: Schedule page can create a new schedule
+The system SHALL provide a schedule creation entry on the schedule page that opens a form, collects required fields, and saves a new `DispatchSchedule` via the backend `POST /schedule` endpoint.
+
+#### Scenario: Open create schedule form
+- **WHEN** the user taps the "新增排班" button on `pages/schedule/schedule`
+- **THEN** a form popup opens with fields for team, work date, shift type, vehicles, staff, and remark
+
+#### Scenario: Select team
+- **WHEN** the user opens the team dropdown
+- **THEN** the system calls `GET /team/simple-list` and displays `{ value, label }` options
+
+#### Scenario: Select vehicles
+- **WHEN** the user opens the vehicle selector
+- **THEN** the system calls `GET /vehicle/simple-list` and displays vehicles by plate number
+
+#### Scenario: Select staff
+- **WHEN** the user opens the staff selector
+- **THEN** the system calls `GET /staff/simple-list` and displays staff by name
+
+#### Scenario: Save new schedule
+- **WHEN** the user fills the form and taps save
+- **THEN** the system calls `POST /schedule` with `teamId`, `teamName`, `workDate`, `shiftType` (`month_plan`/`emergency`), `vehicleIds`, `staffIds`, `status`, and `remark`
+- **AND** the popup closes and the schedule list for the selected date refreshes
+
+#### Scenario: Cancel create schedule
+- **WHEN** the user taps cancel or the mask area
+- **THEN** the popup closes without saving
+
+### Requirement: Schedule creation follows V21-SOP prototype interaction
+The system SHALL align the schedule creation flow, field labels, and value mapping with the V21-SOP prototype.
+
+#### Scenario: Shift type mapping
+- **WHEN** the user selects "月计划" or "应急"
+- **THEN** the system stores the value as `month_plan` or `emergency` respectively before submitting to the backend
+
+#### Scenario: Form validation
+- **WHEN** the user attempts to save with missing required fields
+- **THEN** the system shows a validation message and does not call the backend
+

+ 55 - 0
openspec/specs/weapp-capsule-safearea/spec.md

@@ -0,0 +1,55 @@
+# weapp-capsule-safearea Specification
+
+## Purpose
+TBD - created by archiving change weapp-capsule-safearea. Update Purpose after archive.
+## Requirements
+### Requirement: CapsuleSafeArea component calculates safe margin
+The system SHALL provide a `CapsuleSafeArea` component that computes the minimum right-side margin needed to avoid the WeChat mini-program capsule button, and wraps its default slot with that left margin.
+
+#### Scenario: WeChat environment
+- **WHEN** the app runs in WeChat mini-program
+- **THEN** the component uses `uni.getMenuButtonBoundingClientRect()` and `uni.getSystemInfoSync()` to compute `safeWidth = screenWidth - menuButton.left + 8px`, and applies `margin-left: safeWidth` to the wrapped content
+
+#### Scenario: Non-WeChat environment
+- **WHEN** the app runs on H5 or App
+- **THEN** the component returns a safe width of `0` so the layout remains unchanged
+
+#### Scenario: API failure fallback
+- **WHEN** `uni.getMenuButtonBoundingClientRect()` fails or returns invalid data
+- **THEN** the component falls back to a conservative estimate based on `screenWidth` (approximately 28% of screen width) so the layout remains safe on common devices
+
+### Requirement: TopBar right slot is protected by capsule safe area
+The system SHALL wrap the `TopBar` right slot inside `CapsuleSafeArea` so any right-side action buttons are shifted left of the capsule automatically. Pages using `TopBar` shall not need to manually add capsule-safe spacing.
+
+#### Scenario: Right slot contains a button
+- **WHEN** a page places a button in the `TopBar` right slot
+- **THEN** the button is rendered with a left margin equal to the capsule safe width and remains fully clickable
+
+### Requirement: Home page notification bell avoids capsule
+The system SHALL ensure the notification bell on `pages/home/home` (all roles) does not overlap the WeChat capsule by rendering the home header with `TopBar` and placing the bell inside the `TopBar` right slot.
+
+#### Scenario: Dispatch home renders notification icon
+- **WHEN** `DispatchHome.vue` renders the top-right notification bell
+- **THEN** the header uses `TopBar`, the left slot keeps the existing avatar/greeting, and the bell is placed inside the `TopBar` right slot and is not covered by the capsule
+
+### Requirement: Task page add button avoids capsule
+The system SHALL ensure the "新增/发布" button on `pages/task/task` does not overlap the WeChat capsule by rendering the task list header with `TopBar` and placing the button inside the `TopBar` right slot.
+
+#### Scenario: TaskListView renders add button
+- **WHEN** `TaskListView.vue` renders the top-right add button
+- **THEN** the header uses `TopBar` with the page title, and the button is placed inside the `TopBar` right slot and is not covered by the capsule
+
+### Requirement: Schedule page actions avoid capsule
+The system SHALL ensure the "今天" and "新增排班" buttons on `pages/schedule/schedule` do not overlap the WeChat capsule by placing both buttons inside the `TopBar` right slot.
+
+#### Scenario: ScheduleView renders top actions
+- **WHEN** `ScheduleView.vue` renders the top-right action buttons
+- **THEN** both "今天" and "新增排班" buttons are placed inside the `TopBar` right slot and are not covered by the capsule, and the month-switching row below `TopBar` only keeps the month navigation on the left
+
+### Requirement: Build passes and layout remains valid on non-WeChat platforms
+The system SHALL keep `npm run build:mp-weixin` and `npm run type-check` passing, and non-WeChat layouts must not regress.
+
+#### Scenario: Build verification
+- **WHEN** the project is built for WeChat or type-checked
+- **THEN** no TypeScript or template errors are introduced
+