Appearance
BizSkuPicker 商品规格选择
规格组笛卡尔积 SKU 矩阵:specs 定义规格组(如颜色 × 尺码),组件自动展开全部组合行(规格列 + 售价 / 库存 / 启用 / 小计),specs 变化时保留已有行数据、增删差集;批量填充(全部 / 仅启用)、价格边界校验、库存与货值合计、JSON 外抛。电商 / 进销存商品发布的规格与库存录入。
基础用法
暂无数据
共 0 个 SKU / 启用 0 个库存合计 0 / 货值 ¥0.00
颜色 × 尺码笛卡尔积展开,行内编辑价格 / 库存,v-model 双向。
<script setup lang="ts">
/** 场景:商品发布——颜色×尺码笛卡尔积,行内编辑 */
import { ref } from 'vue'
import { BizSkuPicker } from 'vue3-ep-biz-lib'
import type { BizSkuRow, BizSkuSpec } from 'vue3-ep-biz-lib'
const specs: BizSkuSpec[] = [
{ name: '颜色', values: ['黑色', '白色'] },
{ name: '尺码', values: ['S', 'M', 'L'] },
]
const rows = ref<BizSkuRow[]>([])
</script>
<template>
<BizSkuPicker v-model="rows" :specs="specs" />
</template>
显示代码
批量填充
暂无数据
共 0 个 SKU / 启用 0 个库存合计 0 / 货值 ¥0.00
批量条一键填充价格 / 库存(全部或仅启用行),batch 事件外抛。
<script setup lang="ts">
/** 场景:批量填充——一键设价 / 设库存(全部或仅启用) */
import { ref } from 'vue'
import { ElMessage } from 'element-plus'
import { BizSkuPicker } from 'vue3-ep-biz-lib'
import type { BizSkuPickerBatchPayload, BizSkuRow, BizSkuSpec } from 'vue3-ep-biz-lib'
const specs: BizSkuSpec[] = [
{ name: '容量', values: ['64G', '128G', '256G'] },
{ name: '配色', values: ['远峰蓝', '钛银'] },
]
const rows = ref<BizSkuRow[]>([])
const onBatch = (payload: BizSkuPickerBatchPayload): void => {
ElMessage.success(`批量填充${payload.field === 'price' ? '价格' : '库存'} = ${payload.value}(${payload.scope === 'all' ? '全部' : '仅启用'})`)
}
</script>
<template>
<BizSkuPicker v-model="rows" :specs="specs" :batchable="true" @batch="onBatch" />
</template>
显示代码
规格变更
已编辑的价格 / 库存在新旧行间保留
暂无数据
共 0 个 SKU / 启用 0 个库存合计 0 / 货值 ¥0.00
动态增删规格值:已有行数据保留,差集自动增删。
<script setup lang="ts">
/** 场景:规格变更——增删规格值保留已有数据 */
import { ref } from 'vue'
import { ElButton } from 'element-plus'
import { BizSkuPicker } from 'vue3-ep-biz-lib'
import type { BizSkuRow, BizSkuSpec } from 'vue3-ep-biz-lib'
const specs = ref<BizSkuSpec[]>([
{ name: '口味', values: ['原味', '海苔'] },
{ name: '规格', values: ['120g', '300g'] },
])
const rows = ref<BizSkuRow[]>([])
let expanded = false
const toggleSpec = (): void => {
expanded = !expanded
specs.value = expanded
? [{ name: '口味', values: ['原味', '海苔', '藤椒'] }, { name: '规格', values: ['120g', '300g'] }]
: [{ name: '口味', values: ['原味', '海苔'] }, { name: '规格', values: ['120g', '300g'] }]
}
</script>
<template>
<div>
<div style="margin-bottom: 10px">
<ElButton size="small" @click="toggleSpec">{{ expanded ? '移除规格值「藤椒」' : '新增规格值「藤椒」' }}</ElButton>
<span style="margin-left: 8px; font-size: 12px; color: var(--el-text-color-secondary)">已编辑的价格 / 库存在新旧行间保留</span>
</div>
<BizSkuPicker v-model="rows" :specs="specs" :batchable="false" />
</div>
</template>
显示代码
部分停用
暂无数据
共 0 个 SKU / 启用 0 个库存合计 0 / 货值 ¥0.00
行级启用开关(缺货 / 下架组合置灰),合计仅统计启用行。
<script setup lang="ts">
/** 场景:部分停用——缺货组合置灰,合计仅统计启用行 */
import { ref } from 'vue'
import { BizSkuPicker } from 'vue3-ep-biz-lib'
import type { BizSkuRow, BizSkuSpec } from 'vue3-ep-biz-lib'
const specs: BizSkuSpec[] = [
{ name: '座位', values: ['一等座', '二等座', '商务座'] },
{ name: '车次', values: ['G101', 'G205'] },
]
const rows = ref<BizSkuRow[]>([])
</script>
<template>
<BizSkuPicker v-model="rows" :specs="specs" :batchable="false" />
</template>
显示代码
校验与提交
暂无数据
共 0 个 SKU / 启用 0 个库存合计 0 / 货值 ¥0.00
价格边界 1 ~ 9999 元,越界红框提示
expose
validate(启用行价格在界内且库存 > 0)+ 提交数据查看。<script setup lang="ts">
/** 场景:校验与提交——validate + 数据查看 */
import { ref } from 'vue'
import { ElButton, ElMessage } from 'element-plus'
import { BizSkuPicker } from 'vue3-ep-biz-lib'
import type { BizSkuPickerInstance, BizSkuRow, BizSkuSpec } from 'vue3-ep-biz-lib'
const specs: BizSkuSpec[] = [
{ name: '套餐', values: ['月度', '季度', '年度'] },
]
const rows = ref<BizSkuRow[]>([])
const pickerRef = ref<BizSkuPickerInstance>()
const submit = (): void => {
if (pickerRef.value?.validate() !== true) {
ElMessage.warning('校验未通过:启用行需价格在界内且库存 > 0')
return
}
ElMessage.success(`校验通过,提交 ${rows.value.length} 个 SKU(库存合计 ${pickerRef.value?.getTotalStock()})`)
}
</script>
<template>
<div>
<BizSkuPicker ref="pickerRef" v-model="rows" :specs="specs" :price-range="[1, 9999]" :batchable="false" />
<div style="margin-top: 10px; display: flex; gap: 8px; align-items: center">
<ElButton type="primary" size="small" @click="submit">校验并提交</ElButton>
<span style="font-size: 12px; color: var(--el-text-color-placeholder)">价格边界 1 ~ 9999 元,越界红框提示</span>
</div>
</div>
</template>
显示代码
多规格组
暂无数据
共 0 个 SKU / 启用 0 个库存合计 0 / 货值 ¥0.00
三规格组(颜色 × 尺码 × 版本)组合展开与滚动。
<script setup lang="ts">
/** 场景:三规格组——颜色×尺码×版本组合展开与滚动 */
import { ref } from 'vue'
import { BizSkuPicker } from 'vue3-ep-biz-lib'
import type { BizSkuRow, BizSkuSpec } from 'vue3-ep-biz-lib'
const specs: BizSkuSpec[] = [
{ name: '颜色', values: ['曜石黑', '珍珠白', '星河蓝'] },
{ name: '尺码', values: ['标准', '大杯'] },
{ name: '版本', values: ['基础版', '豪华版'] },
]
const rows = ref<BizSkuRow[]>([])
</script>
<template>
<BizSkuPicker v-model="rows" :specs="specs" />
</template>
显示代码
Props
| 属性名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| specs | BizSkuSpec[] | [] | 规格组(name + values) |
| v-model | BizSkuRow[] | [] | SKU 行(key / values / price / stock / enabled) |
| batchable | boolean | true | 显示批量设置条 |
| price-range | [number, number] | — | 价格边界(越界红框) |
| stock-max | number | — | 库存上限 |
| disabled | boolean | false | 禁用 |
Events
| 事件名 | 参数 | 说明 |
|---|---|---|
| batch | (payload) | 批量填充(field / value / scope / rows) |
| change | (rows) | 行数据变化 |
Expose
| 名称 | 类型 | 说明 |
|---|---|---|
| getEnabledCount | () => number | 启用行数 |
| getTotalStock | () => number | 库存合计(启用行) |
| validate | () => boolean | 启用行价格在界内且库存 > 0 |