docs: add implementation plan for transport plan arranged tab
Break the arranged-tab design into TDD utility steps and list-page filter sync. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
1 parent
a4e107b2e6
commit
87374f3976
1 file changed
+258
@@ -0,0 +1,258 @@
|
||||
# 运输计划列表「已安排」Tab Implementation Plan
|
||||
|
||||
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||||
|
||||
**Goal:** 在运输计划列表「待安排」之后增加「已安排」Tab,筛选跟进状态为 `arranged` 的计划。
|
||||
|
||||
**Architecture:** 沿用「待安排 / 草稿中」跟进状态 Tab 模式:扩展 `PL_PLAN_LIST_TABS` 与 `plPlanListTabToFilters`,列表页切换 Tab 时同步 `searchForm.followStatus`。后端已支持 `followStatus=arranged`,无需改接口。
|
||||
|
||||
**Tech Stack:** Vue 3 + TypeScript;`node:test` + `pnpm exec tsx --test`
|
||||
|
||||
**Spec:** `docs/superpowers/specs/2026-09-04-pl-plan-arranged-tab-design.md`
|
||||
|
||||
**注意:** 工作区可能有无关未提交改动。只改本计划列出的文件,提交时勿夹带无关 diff。
|
||||
|
||||
---
|
||||
|
||||
## 文件结构
|
||||
|
||||
| 操作 | 文件 | 职责 |
|
||||
|------|------|------|
|
||||
| Create | `web-admin/src/utils/pl-plan-list-tabs.test.ts` | Tab 顺序 / filter / 跟进状态 Tab 判定单测 |
|
||||
| Modify | `web-admin/src/utils/pl-display.ts` | `PlPlanListTab`、`PL_PLAN_LIST_TABS`、`isPlPlanFollowStatusListTab`、`plPlanListTabToFilters` |
|
||||
| Modify | `web-admin/src/views/pl/plan/index.vue` | `handlePlanTypeTabChange` 切到 `arranged` 时同步筛选 |
|
||||
|
||||
---
|
||||
|
||||
### Task 1: Tab 工具函数单测 + 实现
|
||||
|
||||
**Files:**
|
||||
- Create: `web-admin/src/utils/pl-plan-list-tabs.test.ts`
|
||||
- Modify: `web-admin/src/utils/pl-display.ts`
|
||||
|
||||
- [ ] **Step 1: 写失败单测**
|
||||
|
||||
创建 `web-admin/src/utils/pl-plan-list-tabs.test.ts`:
|
||||
|
||||
```typescript
|
||||
import assert from 'node:assert/strict'
|
||||
import { describe, it } from 'node:test'
|
||||
import {
|
||||
PL_PLAN_LIST_TABS,
|
||||
isPlPlanFollowStatusListTab,
|
||||
plPlanListTabToFilters
|
||||
} from './pl-display'
|
||||
|
||||
describe('PL_PLAN_LIST_TABS', () => {
|
||||
it('places arranged immediately after pending_arrange', () => {
|
||||
const names = PL_PLAN_LIST_TABS.map((t) => t.name)
|
||||
assert.deepEqual(names.slice(0, 3), ['pending_arrange', 'arranged', 'drafting'])
|
||||
assert.equal(
|
||||
PL_PLAN_LIST_TABS.find((t) => t.name === 'arranged')?.label,
|
||||
'已安排'
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('isPlPlanFollowStatusListTab', () => {
|
||||
it('recognizes pending_arrange, arranged, drafting', () => {
|
||||
assert.equal(isPlPlanFollowStatusListTab('pending_arrange'), true)
|
||||
assert.equal(isPlPlanFollowStatusListTab('arranged'), true)
|
||||
assert.equal(isPlPlanFollowStatusListTab('drafting'), true)
|
||||
assert.equal(isPlPlanFollowStatusListTab('all'), false)
|
||||
assert.equal(isPlPlanFollowStatusListTab('inbound'), false)
|
||||
})
|
||||
})
|
||||
|
||||
describe('plPlanListTabToFilters', () => {
|
||||
it('maps arranged to followStatus arranged with empty planType', () => {
|
||||
assert.deepEqual(plPlanListTabToFilters('arranged'), {
|
||||
planType: '',
|
||||
followStatus: 'arranged'
|
||||
})
|
||||
})
|
||||
|
||||
it('keeps pending_arrange and drafting behavior', () => {
|
||||
assert.deepEqual(plPlanListTabToFilters('pending_arrange'), {
|
||||
planType: '',
|
||||
followStatus: 'pending_arrange'
|
||||
})
|
||||
assert.deepEqual(plPlanListTabToFilters('drafting'), {
|
||||
planType: '',
|
||||
followStatus: 'drafting'
|
||||
})
|
||||
})
|
||||
|
||||
it('maps type tabs without followStatus', () => {
|
||||
assert.deepEqual(plPlanListTabToFilters('all'), { planType: '' })
|
||||
assert.deepEqual(plPlanListTabToFilters('inbound'), { planType: 'inbound' })
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
- [ ] **Step 2: 跑测确认失败**
|
||||
|
||||
```bash
|
||||
cd web-admin && pnpm exec tsx --test src/utils/pl-plan-list-tabs.test.ts
|
||||
```
|
||||
|
||||
Expected: FAIL(`arranged` 尚未进入 `PL_PLAN_LIST_TABS` / filter)
|
||||
|
||||
- [ ] **Step 3: 最小实现**
|
||||
|
||||
在 `web-admin/src/utils/pl-display.ts` 中:
|
||||
|
||||
1. 更新类型与注释:
|
||||
|
||||
```typescript
|
||||
/** 运输计划列表 Tab(单据类型前增加「待安排」「已安排」「草稿中」) */
|
||||
export type PlPlanListTab = PlPlanTypeTab | 'pending_arrange' | 'arranged' | 'drafting'
|
||||
```
|
||||
|
||||
2. 更新 Tab 列表(「待安排」后插入「已安排」):
|
||||
|
||||
```typescript
|
||||
export const PL_PLAN_LIST_TABS: { label: string; name: PlPlanListTab }[] = [
|
||||
{ label: '待安排', name: 'pending_arrange' },
|
||||
{ label: '已安排', name: 'arranged' },
|
||||
{ label: '草稿中', name: 'drafting' },
|
||||
...PL_PLAN_TYPE_TABS
|
||||
]
|
||||
```
|
||||
|
||||
3. 更新跟进状态 Tab 判定:
|
||||
|
||||
```typescript
|
||||
export function isPlPlanFollowStatusListTab(
|
||||
tab: PlPlanListTab | string
|
||||
): tab is 'pending_arrange' | 'arranged' | 'drafting' {
|
||||
return tab === 'pending_arrange' || tab === 'arranged' || tab === 'drafting'
|
||||
}
|
||||
```
|
||||
|
||||
4. 在 `plPlanListTabToFilters` 中增加 `arranged` 分支(放在 `pending_arrange` 之后、`drafting` 之前):
|
||||
|
||||
```typescript
|
||||
export function plPlanListTabToFilters(tab: PlPlanListTab): {
|
||||
planType: string
|
||||
followStatus?: string
|
||||
} {
|
||||
if (tab === 'pending_arrange') {
|
||||
return { planType: '', followStatus: 'pending_arrange' }
|
||||
}
|
||||
if (tab === 'arranged') {
|
||||
return { planType: '', followStatus: 'arranged' }
|
||||
}
|
||||
if (tab === 'drafting') {
|
||||
return { planType: '', followStatus: 'drafting' }
|
||||
}
|
||||
return { planType: plPlanTypeTabToFilter(tab) }
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] **Step 4: 跑测确认通过**
|
||||
|
||||
```bash
|
||||
cd web-admin && pnpm exec tsx --test src/utils/pl-plan-list-tabs.test.ts
|
||||
```
|
||||
|
||||
Expected: PASS(全部用例通过)
|
||||
|
||||
- [ ] **Step 5: Commit**
|
||||
|
||||
```bash
|
||||
git add web-admin/src/utils/pl-display.ts web-admin/src/utils/pl-plan-list-tabs.test.ts
|
||||
git commit -m "$(cat <<'EOF'
|
||||
feat(web-admin): add arranged tab to transport plan list filters
|
||||
|
||||
Insert「已安排」after「待安排」in PL_PLAN_LIST_TABS and map it to followStatus=arranged.
|
||||
EOF
|
||||
)"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Task 2: 列表页 Tab 切换同步筛选
|
||||
|
||||
**Files:**
|
||||
- Modify: `web-admin/src/views/pl/plan/index.vue`
|
||||
|
||||
- [ ] **Step 1: 更新 `handlePlanTypeTabChange`**
|
||||
|
||||
在 `handlePlanTypeTabChange` 中,于 `pending_arrange` 分支后增加 `arranged` 分支(`isPlPlanFollowStatusListTab` 已含 `arranged`,从跟进状态 Tab 切回类型 Tab 时会自动恢复默认筛选,无需额外改动):
|
||||
|
||||
```typescript
|
||||
function handlePlanTypeTabChange(tab: PlPlanListTab | string) {
|
||||
const nextTab = tab as PlPlanListTab
|
||||
const prevTab = activePlanTypeTab.value
|
||||
activePlanTypeTab.value = nextTab
|
||||
const filters = plPlanListTabToFilters(nextTab)
|
||||
searchForm.planType = filters.planType
|
||||
if (nextTab === 'pending_arrange') {
|
||||
searchForm.followStatus = ['pending_arrange']
|
||||
} else if (nextTab === 'arranged') {
|
||||
searchForm.followStatus = ['arranged']
|
||||
} else if (nextTab === 'drafting') {
|
||||
searchForm.followStatus = ['drafting']
|
||||
} else if (isPlPlanFollowStatusListTab(prevTab) && !isPlPlanFollowStatusListTab(nextTab)) {
|
||||
searchForm.followStatus = [...PL_PLAN_DEFAULT_FOLLOW_STATUSES]
|
||||
}
|
||||
pagination.page = 1
|
||||
fetchData()
|
||||
}
|
||||
```
|
||||
|
||||
说明:
|
||||
|
||||
- `fetchData` / 导出已通过 `plPlanListTabToFilters(activePlanTypeTab.value)` 取 `followStatus`,无需再改
|
||||
- `handleReset` 仍默认「待安排」,保持不变
|
||||
- 工具栏与行操作不改
|
||||
|
||||
- [ ] **Step 2: 手动验收清单(开发机)**
|
||||
|
||||
打开 `http://localhost:3006/#/pl/plan-module/plan`:
|
||||
|
||||
1. Tab 顺序为:待安排 → **已安排** → 草稿中 → 全部 → 入库单 → 出库单 → 直销单
|
||||
2. 点「已安排」:列表仅跟进状态为「已安排」;筛选区跟进状态仅勾选「已安排」
|
||||
3. 点「全部」:跟进状态恢复默认勾选(不含已取消)
|
||||
4. 点「重置」:回到「待安排」
|
||||
5. 工具栏/行操作与其他 Tab 一致(无额外隐藏)
|
||||
|
||||
- [ ] **Step 3: Commit**
|
||||
|
||||
```bash
|
||||
git add web-admin/src/views/pl/plan/index.vue
|
||||
git commit -m "$(cat <<'EOF'
|
||||
feat(web-admin): sync followStatus when switching to arranged plan tab
|
||||
|
||||
Mirror pending_arrange behavior so the arranged tab forces followStatus filter to arranged.
|
||||
EOF
|
||||
)"
|
||||
```
|
||||
|
||||
- [ ] **Step 4: 更新知识图谱(若本会话改过代码)**
|
||||
|
||||
```bash
|
||||
./scripts/update-graph.sh frontend
|
||||
```
|
||||
|
||||
或:
|
||||
|
||||
```bash
|
||||
cd web-admin && graphify update .
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Spec 覆盖自检
|
||||
|
||||
| Spec 要求 | Task |
|
||||
|-----------|------|
|
||||
| Tab 顺序:待安排 → 已安排 → 草稿中 → … | Task 1 |
|
||||
| 筛选 `followStatus=arranged` | Task 1 + Task 2 |
|
||||
| 切回类型 Tab 恢复默认跟进状态 | Task 1(`isPlPlanFollowStatusListTab`)+ Task 2 |
|
||||
| 列表/工具栏不改 | Task 2(刻意不改) |
|
||||
| 默认落地仍为待安排 | Task 2(`handleReset` 不动) |
|
||||
| 后端不改 | 无对应 Task |
|
||||
|
||||
无 TBD / 占位;类型名 `arranged` 前后一致。
|
||||
Reference in new issue
Block a user