merge: feat/family-detail-tabs-dev into develop (local only, not pushed)
This commit is contained in:
@@ -52,6 +52,17 @@ watch(() => props.visible, (v) => {
|
|||||||
if (v) checkedIds.value = [...props.defaultCheckedIds]
|
if (v) checkedIds.value = [...props.defaultCheckedIds]
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 合并同名候选搜索(本地过滤同分类链接)
|
||||||
|
const mergeKeyword = ref('')
|
||||||
|
watch(() => props.visible, (v) => {
|
||||||
|
if (v) mergeKeyword.value = ''
|
||||||
|
})
|
||||||
|
const filteredSiblings = computed(() => {
|
||||||
|
const kw = mergeKeyword.value.trim()
|
||||||
|
if (!kw) return props.siblings
|
||||||
|
return props.siblings.filter((s) => (s.goodName ?? '').includes(kw))
|
||||||
|
})
|
||||||
|
|
||||||
function onCascaderChange(val: any) {
|
function onCascaderChange(val: any) {
|
||||||
form.value.categoryId = val.length ? val[val.length - 1] : ''
|
form.value.categoryId = val.length ? val[val.length - 1] : ''
|
||||||
}
|
}
|
||||||
@@ -126,11 +137,19 @@ async function handleSubmit() {
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item v-if="siblings.length" label="合并同名">
|
<el-form-item v-if="siblings.length" label="合并同名">
|
||||||
<div class="config-merge-box">
|
<div class="config-merge-box">
|
||||||
|
<el-input
|
||||||
|
v-model="mergeKeyword"
|
||||||
|
size="small"
|
||||||
|
clearable
|
||||||
|
placeholder="搜索同分类链接…"
|
||||||
|
style="margin-bottom:8px"
|
||||||
|
/>
|
||||||
<el-checkbox-group v-model="checkedIds">
|
<el-checkbox-group v-model="checkedIds">
|
||||||
<el-checkbox v-for="s in siblings" :key="s.rawId" :value="String(s.rawId)">
|
<el-checkbox v-for="s in filteredSiblings" :key="s.rawId" :value="String(s.rawId)">
|
||||||
{{ s.goodName }}<template v-if="s.goodPrice"> · ¥{{ s.goodPrice }}</template>
|
{{ s.goodName }}<template v-if="s.goodPrice"> · ¥{{ s.goodPrice }}</template>
|
||||||
</el-checkbox>
|
</el-checkbox>
|
||||||
</el-checkbox-group>
|
</el-checkbox-group>
|
||||||
|
<div v-if="!filteredSiblings.length" class="config-merge-empty">没有匹配的链接</div>
|
||||||
</div>
|
</div>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="图片">
|
<el-form-item label="图片">
|
||||||
@@ -149,5 +168,6 @@ async function handleSubmit() {
|
|||||||
.config-og-name { font-weight: 600; font-size: 14px; }
|
.config-og-name { font-weight: 600; font-size: 14px; }
|
||||||
.config-og-meta { color: #909399; font-size: 12px; margin-top: 2px; }
|
.config-og-meta { color: #909399; font-size: 12px; margin-top: 2px; }
|
||||||
.config-merge-box { width: 100%; }
|
.config-merge-box { width: 100%; }
|
||||||
|
.config-merge-empty { font-size: 12px; color: #909399; padding: 4px 0; }
|
||||||
.config-merge-box .el-checkbox-group { display: flex; flex-direction: column; align-items: flex-start; max-height: 200px; overflow-y: auto; }
|
.config-merge-box .el-checkbox-group { display: flex; flex-direction: column; align-items: flex-start; max-height: 200px; overflow-y: auto; }
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -155,6 +155,15 @@ const memberPriceSaving = ref<string>('')
|
|||||||
/** 族原始详情(含 priceMatrix) */
|
/** 族原始详情(含 priceMatrix) */
|
||||||
const familyDetailRaw = ref<any>(null)
|
const familyDetailRaw = ref<any>(null)
|
||||||
|
|
||||||
|
// ─── 族级并集视图:尺码表/包装规格(族物化并集)+ SKU(价格矩阵 = 各链接动态合并) ───
|
||||||
|
const familySizeRows = computed(() => familyDetailRaw.value?.sizeChart?.rows ?? [])
|
||||||
|
const familySizeColumns = computed(() => familyDetailRaw.value?.sizeChart?.columns ?? [])
|
||||||
|
const familyPackageRows = computed(() => familyDetailRaw.value?.packageSpecs?.rows ?? [])
|
||||||
|
const familySkuRows = computed(() => {
|
||||||
|
const rows = (familyDetailRaw.value?.priceMatrix?.rows ?? []) as any[]
|
||||||
|
return rows.map((r) => ({ ...r, sourceCount: Array.isArray(r.sources) ? r.sources.length : 0 }))
|
||||||
|
})
|
||||||
|
|
||||||
function toggleMemberExpand(key: string) {
|
function toggleMemberExpand(key: string) {
|
||||||
const next = new Set(expandedMemberKeys.value)
|
const next = new Set(expandedMemberKeys.value)
|
||||||
if (next.has(key)) next.delete(key)
|
if (next.has(key)) next.delete(key)
|
||||||
@@ -683,6 +692,58 @@ async function handleDeleteGood() {
|
|||||||
<el-option v-for="c in editFamilyCandidates" :key="c.id" :label="c.goodName" :value="String(c.id)"
|
<el-option v-for="c in editFamilyCandidates" :key="c.id" :label="c.goodName" :value="String(c.id)"
|
||||||
@click="addFamilyMember(c)" />
|
@click="addFamilyMember(c)" />
|
||||||
</el-select>
|
</el-select>
|
||||||
|
<el-tabs v-if="editFamilyId && editFamilyLoaded" class="family-detail-tabs">
|
||||||
|
<el-tab-pane :label="`尺码表 (${familySizeRows.length})`">
|
||||||
|
<el-table :data="familySizeRows" border size="small" max-height="260">
|
||||||
|
<el-table-column prop="sizeName" label="尺码" width="100" fixed />
|
||||||
|
<el-table-column
|
||||||
|
v-for="column in familySizeColumns"
|
||||||
|
:key="column.key"
|
||||||
|
:prop="column.key"
|
||||||
|
:label="`${column.name} (cm)`"
|
||||||
|
min-width="110"
|
||||||
|
/>
|
||||||
|
</el-table>
|
||||||
|
</el-tab-pane>
|
||||||
|
<el-tab-pane :label="`包装规格 (${familyPackageRows.length})`">
|
||||||
|
<el-table :data="familyPackageRows" border size="small" max-height="260">
|
||||||
|
<el-table-column prop="sizeName" label="尺码" width="90" fixed />
|
||||||
|
<el-table-column label="包装尺寸 (cm)" min-width="150">
|
||||||
|
<template #default="{ row }">
|
||||||
|
{{ row.dimensionsCm ? `${row.dimensionsCm.length}×${row.dimensionsCm.width}×${row.dimensionsCm.height}` : '-' }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="volumeCm3" label="体积 (cm³)" width="110" />
|
||||||
|
<el-table-column prop="grossWeightG" label="含包装重量 (g)" width="140" />
|
||||||
|
</el-table>
|
||||||
|
</el-tab-pane>
|
||||||
|
<el-tab-pane :label="`SKU (${familySkuRows.length})`">
|
||||||
|
<el-table :data="familySkuRows" border size="small" max-height="260">
|
||||||
|
<el-table-column label="物流" width="110">
|
||||||
|
<template #default="{ row }">{{ row.logistics || '-' }}</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="工艺" width="100">
|
||||||
|
<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>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="sizeName" label="尺码" width="90" />
|
||||||
|
<el-table-column prop="colorName" label="颜色" min-width="110" />
|
||||||
|
<el-table-column label="价格" width="100">
|
||||||
|
<template #default="{ row }">{{ row.price }}</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="链接数" width="80">
|
||||||
|
<template #default="{ row }">{{ row.sourceCount || 1 }}</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="状态" width="90">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<el-tag :type="row.manual ? 'warning' : 'success'" size="small">{{ row.manual ? '人工价' : '推导价' }}</el-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</el-tab-pane>
|
||||||
|
</el-tabs>
|
||||||
</div>
|
</div>
|
||||||
<el-form v-loading="editDetailLoading" label-width="80px" style="margin-top: 16px">
|
<el-form v-loading="editDetailLoading" label-width="80px" style="margin-top: 16px">
|
||||||
<el-form-item label="名称"><el-input v-model="editForm.goodName" /></el-form-item>
|
<el-form-item label="名称"><el-input v-model="editForm.goodName" /></el-form-item>
|
||||||
@@ -818,6 +879,8 @@ async function handleDeleteGood() {
|
|||||||
}
|
}
|
||||||
.member-detail-tabs :deep(.el-tabs__header) { margin-bottom: 8px; }
|
.member-detail-tabs :deep(.el-tabs__header) { margin-bottom: 8px; }
|
||||||
.edit-family-loading { color: var(--el-text-color-placeholder); font-size: 12px; padding: 4px 0; }
|
.edit-family-loading { color: var(--el-text-color-placeholder); font-size: 12px; padding: 4px 0; }
|
||||||
|
.family-detail-tabs { margin-top: 10px; }
|
||||||
|
.family-detail-tabs :deep(.el-tabs__header) { margin-bottom: 8px; }
|
||||||
.detail-tabs { margin-top: 12px; padding-top: 4px; border-top: 1px solid #ebeef5; }
|
.detail-tabs { margin-top: 12px; padding-top: 4px; border-top: 1px solid #ebeef5; }
|
||||||
.select-inline { display: flex; align-items: center; gap: 6px; width: 100%; }
|
.select-inline { display: flex; align-items: center; gap: 6px; width: 100%; }
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user