Co-Authored-By: Claude <noreply@anthropic.com>
9.2 KiB
备货单 / 终版列表「全部 / 我的」视图切换 实现计划
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: 在 stocking_list.vue 与 final_list.vue 给 userId === 73 的特权用户增加「全部 / 我的」视图切换,切换时给列表接口传 view_scope=all|self。
Architecture: 纯前端 UI + 传参改动。新增本地状态 viewScope,工具栏渲染条件 canViewAll = userStore.getUserInfo.userId === 73;getList 把 viewScope.value 作为 view_scope 随请求发出;切换时重置页码并重新请求。是否返回全量数据由后端按 token 鉴权决定(后端改造见 spec 第 3.4 节,不在本计划内)。
Tech Stack: Vue 3 <script setup> + TypeScript、element-plus 2.8、Pinia(useUserStore)、unplugin-auto-import(ref/reactive/computed/onMounted/watch 自动导入,无需手写 import)。
Global Constraints
- 无前端单元测试框架:本项目
package.json无test脚本。验收方式 =lint通过 + 本地dev手动核对,不写自动化测试。 - 后端是前置依赖:前端「全部」真正生效需后端
GET /crm/stock/order/list支持view_scope参数(见 spec 3.4)。前端可先行独立完成 UI 与传参;完整功能联调待后端就绪。 - 安全边界在后端:前端
userId === 73仅控制按钮显隐,非授权依据。 - 代码风格:遵循现有写法——
<script setup lang="ts">、element-plus 组件、snake_case 请求参数。 - commit 规范:每任务一次 commit,信息以
feat:开头。
文件结构
| 文件 | 责任 | 改动类型 |
|---|---|---|
src/views/crmpc/stocking/stocking_list.vue |
备货单列表,加视图切换 + view_scope 传参 |
Modify |
src/views/crmpc/stocking/final_list.vue |
终版列表,同构改动 | Modify |
两文件改动完全同构,仅 is_final(0 vs 1)不同。不新建文件。
Task 1: stocking_list.vue 增加视图切换
Files:
- Modify:
src/views/crmpc/stocking/stocking_list.vue- 模板工具栏(约
line 9-22的toolbar-right) getList参数(约line 339-344)- script 状态(约
line 280-281useAuth之后) - script import(约
line 264-274)
- 模板工具栏(约
Interfaces:
-
Consumes:
useUserStore(来自@/store/modules/user),其getUserInfo: computed => Partial<{ userId: number }>;CrmService.getStockList(params)(已存在)。 -
Produces: 列表请求新增参数字段
view_scope: 'all' | 'self'。 -
Step 1: 添加 import
在 <script setup lang="ts"> 顶部 import 区(import { useAuth } from '@/composables/useAuth' 同处)增加一行:
import { useUserStore } from '@/store/modules/user'
- Step 2: 添加状态与切换处理
在 const { hasAuth } = useAuth()(约 line 281)之后插入:
const userStore = useUserStore()
// 仅 userId=73 的特权用户可切换「全部/我的」
const canViewAll = computed(() => userStore.getUserInfo.userId === 73)
const viewScope = ref<'all' | 'self'>('self')
const onScopeChange = () => {
pagination.currentPage = 1
getList()
}
说明:computed / ref 由 unplugin-auto-import 提供,无需 import。getUserInfo.userId 类型为 number | undefined,undefined === 73 为 false,判空安全。
- Step 3: 修改
getList请求参数
定位 getList 内(约 line 339-344):
const params = {
current: currentPage,
size: pageSize,
is_final: 0, // 只获取备货单,非终版
keyword: keyword.value
}
改为(增加 view_scope):
const params = {
current: currentPage,
size: pageSize,
is_final: 0, // 只获取备货单,非终版
keyword: keyword.value,
view_scope: viewScope.value
}
- Step 4: 工具栏添加切换控件
定位模板 toolbar-right(约 line 9-21),在 <el-input> 之前插入 el-radio-group:
原:
<div class="toolbar-right">
<el-input
v-model="keyword"
改为:
<div class="toolbar-right">
<el-radio-group
v-if="canViewAll"
v-model="viewScope"
@change="onScopeChange"
style="margin-right: 12px"
>
<el-radio-button value="self">我的</el-radio-button>
<el-radio-button value="all">全部</el-radio-button>
</el-radio-group>
<el-input
v-model="keyword"
说明:用 value(element-plus 2.6+ 推荐)而非 label 作值,避免 2.8 的 label 弃用告警。文字走默认插槽。
- Step 5: Lint 校验
Run: npm run fix -- src/views/crmpc/stocking/stocking_list.vue
Expected: 无 error。若有,按提示修复(常见:prettier 格式)。
- Step 6: 手动核对(前端独立部分)
Run: npm run dev,浏览器打开备货单列表页。
核对项:
- 用非 73 账号登录:工具栏不出现「全部/我的」控件,列表行为同改动前。
- 打开 DevTools Network,看
/crm/stock/order/list请求 Payload:无论是否 73,都应带上view_scope=self(默认值)。 - (需 73 登录态)用 73 账号登录:出现「全部/我的」,默认选中「我的」;点「全部」后 Network 请求带
view_scope=all,点回「我的」带view_scope=self,且每次切换分页回到第 1 页。 - 「全部」是否真返回全量数据,取决于后端是否已支持——后端未就绪时,切到「全部」数据可能不变,属预期。
- Step 7: Commit
git add src/views/crmpc/stocking/stocking_list.vue
git commit -m "feat(stocking): 备货单列表为特权用户增加「全部/我的」视图切换
Co-Authored-By: Claude <noreply@anthropic.com>"
Task 2: final_list.vue 增加视图切换(同构)
Files:
- Modify:
src/views/crmpc/stocking/final_list.vue- 模板工具栏(约
line 7-19的toolbar-right) getList参数(约line 278-283)- script 状态(约
line 229useAuth之后) - script import(约
line 206-216)
- 模板工具栏(约
Interfaces:
-
Consumes: 同 Task 1(
useUserStore、CrmService.getStockList)。 -
Produces: 同 Task 1(
view_scope参数)。 -
Step 1: 添加 import
在 <script setup lang="ts"> 顶部 import 区增加:
import { useUserStore } from '@/store/modules/user'
- Step 2: 添加状态与切换处理
在 const { hasAuth } = useAuth()(约 line 229)之后插入:
const userStore = useUserStore()
// 仅 userId=73 的特权用户可切换「全部/我的」
const canViewAll = computed(() => userStore.getUserInfo.userId === 73)
const viewScope = ref<'all' | 'self'>('self')
const onScopeChange = () => {
pagination.currentPage = 1
getList()
}
- Step 3: 修改
getList请求参数
定位 getList 内(约 line 278-283):
const params = {
current: currentPage,
size: pageSize,
is_final: 1, // 只获取备货单,非终版
keyword: keyword.value
}
改为:
const params = {
current: currentPage,
size: pageSize,
is_final: 1, // 终版
keyword: keyword.value,
view_scope: viewScope.value
}
(注:原代码注释「非终版」是笔误,此处顺手修正为「终版」。)
- Step 4: 工具栏添加切换控件
定位模板 toolbar-right(约 line 7-19),在 <el-input> 之前插入:
原:
<div class="toolbar-right">
<el-input
v-model="keyword"
改为:
<div class="toolbar-right">
<el-radio-group
v-if="canViewAll"
v-model="viewScope"
@change="onScopeChange"
style="margin-right: 12px"
>
<el-radio-button value="self">我的</el-radio-button>
<el-radio-button value="all">全部</el-radio-button>
</el-radio-group>
<el-input
v-model="keyword"
- Step 5: Lint 校验
Run: npm run fix -- src/views/crmpc/stocking/final_list.vue
Expected: 无 error。
- Step 6: 手动核对(前端独立部分)
Run: npm run dev,浏览器打开终版列表页。核对项同 Task 1 Step 6(注意此处是 is_final=1 的终版页)。
- Step 7: Commit
git add src/views/crmpc/stocking/final_list.vue
git commit -m "feat(stocking): 终版列表为特权用户增加「全部/我的」视图切换
Co-Authored-By: Claude <noreply@anthropic.com>"
后端联调清单(交付后端,不在本计划执行范围)
接口 GET /crm/stock/order/list 增加可选参数 view_scope:
| 请求 | 后端行为 |
|---|---|
不传 / view_scope=self |
按现状:依 token 用户过滤 |
view_scope=all 且 token 用户 id ∈ {73} |
返回全量 |
view_scope=all 且 token 用户 id ∉ {73} |
降级为 self(返回该用户自己的) |
要点:只信 token,忽略前端任何用户标识,防 IDOR。