2026-08-10-web-admin-confirm-pricing-batch-coefficient.md 8.8 KB

Web-Admin 确认定价弹窗批量设置调价系数 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: 在「选中供应商报价并设置最终售价」弹窗内,支持勾选商品并一键将调价系数统一设为同一数值(含两位小数),同步重算最终售价。

Architecture: 仅改 inquiry-quotation/index.vue:表格增加 selection(仅在售可选,全选=当前 confirmPricingDisplayItems);标题区增加批量条(已选数 + el-input-number + 批量应用);应用时写入系数并复用 handleConfirmPricingCoefficientChange。无后端变更。

Tech Stack: Vue3 + TypeScript + Element Plus(web-admin)

Global Constraints

  • Spec: docs/superpowers/specs/2026-08-10-web-admin-confirm-pricing-batch-coefficient-design.md
  • 调整方式:统一设为同一数值(非增减)
  • 小数:precision=2(如 5.11)
  • 全选范围:仅当前可见行(Tab + 分类 + 搜索)
  • 仅 inSale 行可选、可被批量写入
  • 「不在售」Tab:批量条禁用
  • 批量应用按钮:btn-ghost(中性描边),不与页脚主按钮抢主色
  • 打开弹窗重置:勾选清空、批量输入 null
  • 不改 submitConfirmPricing / API
  • web-admin 无组件单测脚手架:以手动验收清单为准(见 Task 4)
  • 不主动 commit(除非用户要求)

File map

文件 职责
web-admin/src/views/system/inquiry-quotation/index.vue 确认定价弹窗模板、状态、处理函数、局部样式
docs/web-admin-ui-spec-fresh-mint.md (可选)变更留痕一句

Task 1: 状态、selectable、批量应用与打开重置

Files:

  • Modify: web-admin/src/views/system/inquiry-quotation/index.vue(script:confirmPricingDialogVisible 状态区;handleConfirmPricingCoefficientChange 附近;打开确认定价弹窗函数内)

Interfaces:

  • Consumes: 现有 handleConfirmPricingCoefficientChange(row)、confirmPricingSaleTab、打开弹窗成功路径中的 confirmPricingDialogVisible = true
  • Produces:

    • confirmPricingTableRef
    • confirmPricingSelectedRows: Ref<any[]>
    • confirmPricingBatchCoefficient: Ref<number | null>
    • confirmPricingBatchDisabled: ComputedRef<boolean>
    • confirmPricingRowSelectable(row): boolean
    • onConfirmPricingSelectionChange(rows): void
    • applyConfirmPricingBatchCoefficient(): void
  • [x] Step 1: 在 confirmPricingDialogVisible 等状态旁新增:

const confirmPricingTableRef = ref<any>(null)
const confirmPricingSelectedRows = ref<any[]>([])
const confirmPricingBatchCoefficient = ref<number | null>(null)

const confirmPricingBatchDisabled = computed(
  () => confirmPricingSaleTab.value !== 'inSale'
)

const confirmPricingRowSelectable = (row: any) => Boolean(row?.inSale)

const onConfirmPricingSelectionChange = (rows: any[]) => {
  confirmPricingSelectedRows.value = Array.isArray(rows) ? rows : []
}

const applyConfirmPricingBatchCoefficient = () => {
  if (confirmPricingBatchDisabled.value) {
    ElMessage.warning('请切换到「在售」后再批量设置调价系数')
    return
  }
  const selected = (confirmPricingSelectedRows.value || []).filter((x) => x?.inSale)
  if (!selected.length) {
    ElMessage.warning('请先勾选商品')
    return
  }
  const coeff = Number(confirmPricingBatchCoefficient.value)
  if (!Number.isFinite(coeff)) {
    ElMessage.warning('请输入有效的调价系数')
    return
  }
  const safeCoeff = Number(coeff.toFixed(2))
  for (const row of selected) {
    row.pricingCoefficient = safeCoeff
    handleConfirmPricingCoefficientChange(row)
  }
  ElMessage.success(`已对 ${selected.length} 个商品设置调价系数`)
}

注意:applyConfirmPricingBatchCoefficient 必须定义在 handleConfirmPricingCoefficientChange 之后,或确保函数声明顺序不触发 TDZ(若用 const 箭头函数,放在被调用方之后)。

  • Step 2: 在打开确认定价弹窗、赋值 confirmPricingItems 并 confirmPricingDialogVisible.value = true 的成功路径中,增加重置:
confirmPricingSelectedRows.value = []
confirmPricingBatchCoefficient.value = null
confirmPricingDialogVisible.value = true
nextTick(() => {
  confirmPricingCategoryTreeRef.value?.setCurrentKey(undefined)
  confirmPricingTableRef.value?.clearSelection?.()
})

(合并到现有 nextTick 即可,避免重复 nextTick。)


Task 2: 标题区批量条 + 表格 selection 列

Files:

  • Modify: 同文件模板,确认定价弹窗内 picker-right-title 与 el-table.confirm-pricing-table(约 1516–1621 行)

  • [x] Step 1: 将标题区改为:

<div class="picker-right-title">
  <div class="picker-right-title-left">
    <span>商品售价调整</span>
    <span class="muted">共 {{ confirmPricingDisplayItems.length }} 个</span>
    <span class="muted confirm-pricing-selected-count"
      >已选 {{ confirmPricingSelectedRows.length }} 项</span
    >
    <span class="confirm-pricing-batch-label">调价系数</span>
    <el-input-number
      v-model="confirmPricingBatchCoefficient"
      :precision="2"
      :step="0.1"
      controls-position="right"
      class="confirm-pricing-batch-input"
      :disabled="confirmPricingBatchDisabled"
      placeholder="如 5.11"
    />
    <el-button
      class="btn-ghost"
      :disabled="confirmPricingBatchDisabled"
      @click="applyConfirmPricingBatchCoefficient"
    >
      批量应用
    </el-button>
  </div>
  <div class="picker-right-title-actions">
    <el-radio-group v-model="confirmPricingSaleTab" size="small">
      <el-radio-button label="inSale">在售</el-radio-button>
      <el-radio-button label="notInSale">不在售</el-radio-button>
    </el-radio-group>
  </div>
</div>
  • Step 2: 表格增加 ref、selection-change、selection 列(在序号列前):
<el-table
  ref="confirmPricingTableRef"
  class="confirm-pricing-table"
  :data="confirmPricingDisplayItems"
  stripe
  height="420"
  row-key="productId"
  :row-class-name="confirmPricingRowClassName"
  :cell-style="confirmPricingCellStyle"
  @selection-change="onConfirmPricingSelectionChange"
  @row-dblclick="openConfirmPricingProductView"
>
  <!-- empty 保持不变 -->
  <el-table-column
    type="selection"
    width="48"
    align="center"
    :selectable="confirmPricingRowSelectable"
  />
  <el-table-column type="index" label="序号" width="68" align="center" header-align="center" :index="(index) => index + 1" />
  <!-- 后续列保持现有顺序:图片、商品名称、供应商报价、调价系数、最终售价、分类 -->
</el-table>

Task 3: 局部样式(标题区不挤爆)

Files:

  • Modify: 同文件 <style scoped> 中 .confirm-pricing-* 段(约 4299 行起)

  • [x] Step 1: 追加:

.confirm-pricing-dialog .picker-right-title-left {
  flex-wrap: wrap;
  gap: 8px 12px;
  align-items: center;
}
.confirm-pricing-selected-count {
  margin-left: 4px;
}
.confirm-pricing-batch-label {
  font-size: 13px;
  color: var(--mint-text-muted, #64748b);
}
.confirm-pricing-batch-input {
  width: 120px;
}

若现有 .picker-right-title-left 已是 flex,只需在 confirm-pricing 作用域下加强 flex-wrap,避免窄宽时与 Tab 重叠。


Task 4: 手动验收

在 http://localhost:3008/#/inquiry/manage 打开「选中供应商报价并设置最终售价」:

  • Step 1: 在售 Tab → 表头全选 → 输入 5.11 → 批量应用 → 可见行系数均为 5.11,最终售价 = 报价 × 1.0511(四舍五入到分)。
  • Step 2: 取消全选后只勾 1–2 行 → 改系数 3 → 仅勾选行变化。
  • Step 3: 选分类或搜索缩小列表 → 全选 → 只改当前可见行;切回「全部」确认未可见行未变。
  • Step 4: 切「不在售」→ 无法勾选、批量控件禁用。
  • Step 5: 批量后再改单行系数/最终售价仍联动。
  • Step 6: 关闭再打开弹窗 → 已选为 0、批量输入为空。

(可选)在 docs/web-admin-ui-spec-fresh-mint.md 变更记录追加一句:询价确认定价弹窗支持勾选批量设置调价系数。


Spec coverage self-check

Spec 要求 Task
统一设值 + precision=2 Task 1–2
勾选全部/部分;全选=当前可见 Task 2(selection + displayItems)
仅在售可选;不在售禁用批量 Task 1–2
重算最终售价 Task 1 复用 handleConfirmPricingCoefficientChange
打开重置 Task 1 Step 2
不改后端提交 未改 submitConfirmPricing
批量按钮中性样式 Task 2 btn-ghost
验收场景 Task 4