feat(public): family-first contract — goodId=familyId, strict 5-dim price matrix
公开契约族化(前端只需知道款号/族): - GET /public/goods 一族一条(goodId=族ID,price=族起价,分页作用于分组后); 无族商品(自定义)不进任何公开端点(列表/首页/分类树/标签统计) - GET /public/goods/:goodId 仅认族 ID;公共字段取代表 Good,变体=全体成员并集, 尺码表/包装规格=族物化并集;旧 SDS 链接 ID 寻址 404 - priceMatrix 严格五维:尺码×颜色×印花数量×工艺×物流;维度来源改为链接级 标签(人工接管按人工标签),弃用原始 craftLabel;CUSTOM 成员尊重显式标签 - 名称派生补裸「单面/双面」写法(直喷双面→双面印花+直喷,18 条存量链接修复) - family_price_overrides 加 print_count 列(五键唯一),PUT/DELETE/校验五键化 - admin 编辑弹窗矩阵消费适配(SKU 列直读 printCount,成员格子三维匹配, 改价 payload 带 printCount) - 存量 339 族已全量重算;api 162/162、admin 22/22、双端构建绿
This commit is contained in:
@@ -133,6 +133,7 @@ interface MemberPriceCell {
|
||||
colorId: string
|
||||
sizeName: string | null
|
||||
colorName: string | null
|
||||
printCount: string
|
||||
craft: string
|
||||
logistics: string
|
||||
price: string
|
||||
@@ -216,9 +217,24 @@ function memberVariants(id: string) {
|
||||
return memberDetail(id)?.variants ?? []
|
||||
}
|
||||
|
||||
// 矩阵三个归因维度的合法取值(与 api 端 auto-tag-rules 一致)
|
||||
const PRINT_COUNT_VALUES = ['单面印花', '双面印花']
|
||||
const CRAFT_VALUES = ['烫画', '直喷', '不打印']
|
||||
const LOGISTICS_VALUES = ['包邮', '不包邮']
|
||||
|
||||
/** 成员的矩阵归因维度:优先取有效标签(人工接管后仍准确),回退按名称解析 */
|
||||
function memberDims(id: string) {
|
||||
const row = editFamilyMembers.value.find((m) => m.id === id)
|
||||
return linkDims(row?.goodName ?? null)
|
||||
const fallback = linkDims(row?.goodName ?? null)
|
||||
const tagNames = ((row as any)?.originGoodTags ?? [])
|
||||
.map((r: any) => r.tag?.tagName)
|
||||
.filter(Boolean) as string[]
|
||||
const crafts = CRAFT_VALUES.filter((v) => tagNames.includes(v))
|
||||
return {
|
||||
logistics: LOGISTICS_VALUES.find((v) => tagNames.includes(v)) ?? fallback.logistics,
|
||||
crafts: crafts.length ? crafts : fallback.crafts,
|
||||
printCount: PRINT_COUNT_VALUES.find((v) => tagNames.includes(v)) ?? fallback.printCount,
|
||||
}
|
||||
}
|
||||
|
||||
async function handleSyncMemberDetail(row: { id: string; sdsGoodId: string }) {
|
||||
@@ -234,21 +250,25 @@ async function handleSyncMemberDetail(row: { id: string; sdsGoodId: string }) {
|
||||
} finally { detailSyncing.value = '' }
|
||||
}
|
||||
|
||||
/** 该链接在族价格矩阵中的格子(craft/logistics 即该链接的标签维度) */
|
||||
/** 该链接在族价格矩阵中的格子(印花数量/工艺/物流 三维即该链接的归因标签) */
|
||||
function loadMemberPrices(ogId: string) {
|
||||
const row = editFamilyMembers.value.find((m) => m.id === ogId)
|
||||
if (!row?.craftLabel || !row.logisticsLabel) {
|
||||
const dims = memberDims(ogId)
|
||||
if (!dims.printCount || !dims.crafts.length || !dims.logistics) {
|
||||
memberPrices.value[ogId] = []
|
||||
return
|
||||
}
|
||||
const matrixRows = (familyDetailRaw.value?.priceMatrix?.rows ?? []) as any[]
|
||||
memberPrices.value[ogId] = matrixRows
|
||||
.filter((r: any) => r.craft === row.craftLabel && r.logistics === row.logisticsLabel)
|
||||
.filter((r: any) =>
|
||||
r.printCount === dims.printCount &&
|
||||
dims.crafts.includes(r.craft) &&
|
||||
r.logistics === dims.logistics)
|
||||
.map((r: any) => ({
|
||||
sizeId: String(r.sizeId),
|
||||
colorId: String(r.colorId),
|
||||
sizeName: r.sizeName ?? null,
|
||||
colorName: r.colorName ?? null,
|
||||
printCount: r.printCount,
|
||||
craft: r.craft,
|
||||
logistics: r.logistics,
|
||||
price: String(r.price ?? ''),
|
||||
@@ -263,7 +283,7 @@ async function saveMemberPrices(row: { id: string }) {
|
||||
memberPriceSaving.value = row.id
|
||||
try {
|
||||
await productFamiliesApi.putOverrides(editFamilyId.value, cells.map((c) => ({
|
||||
sizeId: c.sizeId, colorId: c.colorId, craft: c.craft, logistics: c.logistics, price: c.editPrice,
|
||||
sizeId: c.sizeId, colorId: c.colorId, printCount: c.printCount, craft: c.craft, logistics: c.logistics, price: c.editPrice,
|
||||
})))
|
||||
ElMessage.success('价格已保存')
|
||||
await loadEditFamily()
|
||||
@@ -803,7 +823,7 @@ async function handleDeleteGood() {
|
||||
<template #default="{ row }">{{ row.craft || '-' }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="印花数量" width="100">
|
||||
<template #default="{ row }">{{ row.craft?.includes('双面印花') ? '双面印花' : row.craft?.includes('单面印花') ? '单面印花' : '-' }}</template>
|
||||
<template #default="{ row }">{{ row.printCount || '-' }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="sizeName" label="尺码" width="90" />
|
||||
<el-table-column prop="colorName" label="颜色" min-width="110" />
|
||||
|
||||
Reference in New Issue
Block a user