hl-api-changelog/changelogs/2026-04/2026-04-17_frontend-bug_step4-pricing-tier-tabs.md

6.6 KiB

前端 Bug 通知 — Step4 定价管理 顶部档位 Tab 只显示已有价格的档位

  • 日期: 2026-04-17
  • 类型: 前端 Bug 修复指南(不涉及后端代码改动,后端无需重启
  • 涉及端: 管理后台 hl-ui产品编辑页 Step4 定价管理)
  • 后端服务: hl-product-service-v2后端已核实数据完全正确,无需改动

一、问题描述

在产品编辑页 Step4「定价管理」顶部档位切换区域

  • 预期:显示产品 Step1 配置的全部档位 tab(例如 5 档:经济 / 舒适 / 轻奢 / 高端 / 豪华),每个档位都有独立 tab 可点击切换,用户可以给任何档位添加价格
  • 实际只显示已有价格数据的档位 tab。若用户只给其中 1 档(如"舒适")设置过价格,顶部就只显示 1 个灰色 tag「舒适」,其他 4 档没有 tab → 用户无法切换到那 4 档去添加价格,定价页陷入"单档死循环"

复现路径

  • 环境:测试服 192.168.100.160
  • 产品 ID2045018534152478721
  • 页面:产品编辑 → Step4 定价管理
  • 前置Step1 配置了 5 档(经济/舒适/轻奢/高端/豪华),且只对其中某 1 档设置过价格

截图现象

  • 顶部只有 1 个 tag「舒适」对应 tierSeq=2 的价格记录)
  • 价格列表显示 ¥7,777 / ¥3,333 / ¥500 / ¥500
  • 其他 4 个档位的 tab 完全缺失

二、根因分析(后端已核实无误)

1. 后端接口返回数据 100% 正确

调用 GET /admin/product/item/2045018534152478721,响应:

{
  "code": 200,
  "data": {
    "tiers": [
      { "tierSeq": 1, "tierName": "经济", "tierDescription": "快捷酒店/双床标间" },
      { "tierSeq": 2, "tierName": "舒适", "tierDescription": "四星酒店/河景房" },
      { "tierSeq": 3, "tierName": "轻奢", "tierDescription": "五星酒店/高级套房" },
      { "tierSeq": 4, "tierName": "高端", "tierDescription": "精品度假酒店/江景套房" },
      { "tierSeq": 5, "tierName": "豪华", "tierDescription": "奢华度假庄园/别墅" }
    ]
  }
}

调用 GET /admin/product/item/2045018534152478721/price-calendar?month=2026-04,返回 30 条记录,全部 tierSeq=2(对应"舒适"档用户历史设置的价格)。

所以:

  • 顶部显示「舒适」✓ 与 DB 真实数据完全对应DB 里只有 tierSeq=2 的记录)
  • 其他档位没 tab 是因为 DB 里没有对应 tierSeq 的价格记录

2. Bug 所在代码

文件src/views/product/edit/components/steps/PricingStep.vue

问题代码(大约 218-227 行,顶部档位切换 NButtonGroup 渲染处):

<NButtonGroup v-if="isDual" size="small">
  <NButton
    v-for="seq in detectedTierSeqs"   <!--  只遍历已有价格的档位 -->
    :key="seq"
    :type="currentTierSeq === seq ? 'primary' : 'default'"
    @click="currentTierSeq = seq"
  >
    {{ getTierLabel(seq) }}
  </NButton>
</NButtonGroup>

相关变量定义(大约 39-43 行):

const tiers = computed(() => store.productData.tiers || [])           // Step1 配置的全部档位5 档)
const isDual = computed(() => tiers.value.length > 1 || detectedTierSeqs.value.length > 1)
const currentTierSeq = ref(1)
const detectedTierSeqs = ref([])  // 从价格日历数据中反向检测到的档位

detectedTierSeqsloadCalendar 里从已有价格数据反向 collect大约 106 行):

const seqs = [...new Set(rawCalendarData.map(d => d.tierSeq).filter(Boolean))].sort()
detectedTierSeqs.value = seqs

→ 当 DB 里只有 tierSeq=2 的记录,detectedTierSeqs = [2] → 顶部只渲染 1 个 tab 「舒适」。


三、修复方案(前端改动)

核心改动

顶部档位 tab 应遍历 tiersStep1 配置的全部档位),而不是 detectedTierSeqs(从数据反推的档位)

具体修改

文件src/views/product/edit/components/steps/PricingStep.vue

改法v-for 的集合从 detectedTierSeqs 改为 tiers

<NButtonGroup v-if="isDual" size="small">
  <NButton
    v-for="tier in tiers"
    :key="tier.tierSeq"
    :type="currentTierSeq === tier.tierSeq ? 'primary' : 'default'"
    @click="currentTierSeq = tier.tierSeq"
  >
    {{ tier.tierName || `档位${tier.tierSeq}` }}
  </NButton>
</NButtonGroup>

同步注意

  1. isDual 判断条件保留:保持 tiers.value.length > 1 || detectedTierSeqs.value.length > 1(某些老数据可能没 tiers 但有价格,兜底用 detectedTierSeqs 判 isDual
  2. currentTierSeq 初始化:建议在 loadCalendar 之后做一次校正,如果 currentTierSeq 不在 tiers 列表里,fallback 到 tiers[0].tierSeq,避免默认的 ref(1) 在"档位 1 没配置"的产品上访问不到对应价格
  3. filterAndAggregate 过滤条件:当前判断 detectedTierSeqs.length > 1 才 filter,改后建议改成 tiers.length > 1(因为切换 tab 是按 Step1 档位切,不按检测出来的档位切)
  4. 无需修改 PriceIntervalEditor.vue:该组件里 tierOptions 已经是 store.productData.tiers 动态生成(弹窗内 5 个档位按钮显示正常)

回归测试点

  • 多档产品tiers=5且只给 1 档配过价格 → 顶部应显示 5 个 tab,可自由切换
  • 多档产品且 5 档都配过价格 → 顶部 5 个 tab,每个切换后显示对应档位的价格区间
  • 单档产品tiers=1→ 顶部不显示 NButtonGroupisDual=false
  • 切换档位 tab 后:
    • 价格区间列表过滤显示该档位的数据
    • 新增/编辑价格区间时默认 tierSeq = 当前选中的 tab不是硬编码的 1
    • 删除价格时 deletePriceCalendar(..., { tierSeq: currentTierSeq.value }) 能正确删除

四、后端是否有配合改动

后端数据结构、接口行为、字段定义完全不变。本 bug 是纯前端渲染逻辑问题。


五、相关接口清单(不变,仅作参考)

方法 路径 说明
GET /admin/product/item/{id} 产品详情(返回完整 tiers 列表)
GET /admin/product/item/{id}/price-calendar?month=YYYY-MM 查询某月价格日历(返回含 tierSeq 的价格记录列表)
POST /admin/product/item/{id}/price-calendar/batch 批量设置价格(请求体含 tierSeq
DELETE /admin/product/item/{id}/price-calendar 按 tierSeq + 日期范围删除价格

六、优先级

P1 — 此 bug 会让多档产品的定价流程完全走不通(除了第一次创建时设置的档位外,其余档位永远加不了价格)。建议尽快修复。