Files
art-design/docs/superpowers/plans/2026-08-06-stocking-visibility-toggle.md
T
2026-08-06 11:37:34 +08:00

9.2 KiB
Raw Blame History

备货单 / 终版列表「全部 / 我的」视图切换 实现计划

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-281 useAuth 之后)
    • 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,浏览器打开备货单列表页。

核对项:

  1. 用非 73 账号登录:工具栏不出现「全部/我的」控件,列表行为同改动前。
  2. 打开 DevTools Network,看 /crm/stock/order/list 请求 Payload:无论是否 73,都应带上 view_scope=self(默认值)。
  3. (需 73 登录态)用 73 账号登录:出现「全部/我的」,默认选中「我的」;点「全部」后 Network 请求带 view_scope=all,点回「我的」带 view_scope=self,且每次切换分页回到第 1 页。
  4. 「全部」是否真返回全量数据,取决于后端是否已支持——后端未就绪时,切到「全部」数据可能不变,属预期。
  • 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 229 useAuth 之后)
    • 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。