feat(product-family): auto-derive logistics/craft tags from family members
This commit is contained in:
@@ -406,7 +406,7 @@ function collectSiblings(ogNode: any): any[] {
|
||||
}
|
||||
|
||||
function openConfigModal(og: any, dropTarget: any) {
|
||||
configOG.value = og
|
||||
configOG.value = { ...og, familyId: og.familyId ?? findOgNodeById(og.rawId)?.familyId ?? null }
|
||||
configDropTarget.value = dropTarget
|
||||
const ogNode = findOgNodeById(og.rawId)
|
||||
const siblings = ogNode ? collectSiblings(ogNode) : []
|
||||
@@ -729,7 +729,11 @@ async function openEdit(g: Good) {
|
||||
countryId: g.countryId,
|
||||
cascaderCategory: findCategoryPath(allCategories.value, g.categoryId),
|
||||
categoryId: g.categoryId,
|
||||
tagIds: (g.tags || []).map(t => t.id),
|
||||
// 有族时:自动组(物流/工艺/位置)标签为派生数据,不进入可编辑选择
|
||||
tagIds: (g.tags || []).filter((t: any) => {
|
||||
const og = (g as any).originGood?.family
|
||||
return !og || !t.tagGroupId || !autoTagGroupIds.value.has(t.tagGroupId)
|
||||
}).map((t: any) => t.id),
|
||||
positionId: g.positionId || '',
|
||||
}
|
||||
initEditFamily((g as any).originGood?.family ?? null)
|
||||
@@ -1289,6 +1293,29 @@ const groupedTagOptions = computed(() => {
|
||||
return groups
|
||||
})
|
||||
|
||||
// ─── 族派生标签:物流/工艺/位置组由族自动同步,表单中只读 ───
|
||||
const isAutoTagGroup = (name: string) => /物流|工艺|位置/.test(name)
|
||||
const autoTagGroupIds = computed(() =>
|
||||
new Set(allTagGroups.value.filter((g) => isAutoTagGroup(g.groupName)).map((g) => g.id)),
|
||||
)
|
||||
const configHasFamily = computed(() => Boolean((configOG.value as any)?.familyId))
|
||||
const configTagOptions = computed(() =>
|
||||
configHasFamily.value
|
||||
? groupedTagOptions.value.filter((g) => g.id === 'ungrouped' || !autoTagGroupIds.value.has(g.id as any))
|
||||
: groupedTagOptions.value,
|
||||
)
|
||||
const editTagOptions = computed(() =>
|
||||
editFamilyId.value
|
||||
? groupedTagOptions.value.filter((g) => g.id === 'ungrouped' || !autoTagGroupIds.value.has(g.id as any))
|
||||
: groupedTagOptions.value,
|
||||
)
|
||||
/** 当前商品的自动组标签(只读展示) */
|
||||
const editDerivedTags = computed(() =>
|
||||
editFamilyId.value
|
||||
? ((editGood.value as any)?.tags ?? []).filter((t: any) => autoTagGroupIds.value.has(t.tagGroupId))
|
||||
: [],
|
||||
)
|
||||
|
||||
function toggleTagInSelection(tagId: string): void {
|
||||
const idx = selectedTagIds.value.indexOf(tagId)
|
||||
if (idx >= 0) selectedTagIds.value.splice(idx, 1)
|
||||
@@ -1922,12 +1949,15 @@ onMounted(() => loadAll())
|
||||
<el-form-item label="标签">
|
||||
<div class="select-inline">
|
||||
<el-select v-model="configForm.tagIds" multiple filterable placeholder="选择标签" style="flex:1">
|
||||
<el-option-group v-for="g in groupedTagOptions" :key="g.id" :label="g.label">
|
||||
<el-option-group v-for="g in configTagOptions" :key="g.id" :label="g.label">
|
||||
<el-option v-for="t in g.tags" :key="t.id" :label="t.tagName" :value="t.id" />
|
||||
</el-option-group>
|
||||
</el-select>
|
||||
<el-button text :icon="Plus" @click="quickCreateTag(() => { const latest = allTags[allTags.length - 1]; if (latest) configForm.tagIds.push(latest.id) })" />
|
||||
</div>
|
||||
<div v-if="configHasFamily" class="derived-tags-note">
|
||||
物流 / 工艺 / 印刷位置标签由族成员自动生成,无需手动选择
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
@@ -2049,12 +2079,19 @@ onMounted(() => loadAll())
|
||||
<el-form-item label="标签">
|
||||
<div class="select-inline">
|
||||
<el-select v-model="editForm.tagIds" multiple filterable placeholder="选择标签" style="flex:1">
|
||||
<el-option-group v-for="g in groupedTagOptions" :key="g.id" :label="g.label">
|
||||
<el-option-group v-for="g in editTagOptions" :key="g.id" :label="g.label">
|
||||
<el-option v-for="t in g.tags" :key="t.id" :label="t.tagName" :value="t.id" />
|
||||
</el-option-group>
|
||||
</el-select>
|
||||
<el-button text :icon="Plus" @click="quickCreateTag(() => { const latest = allTags[allTags.length - 1]; if (latest) editForm.tagIds.push(latest.id) })" />
|
||||
</div>
|
||||
<div v-if="editFamilyId && editDerivedTags.length" class="derived-tags-row">
|
||||
<span class="derived-tags-label">族自动:</span>
|
||||
<el-tag v-for="t in editDerivedTags" :key="t.id" size="small" type="info" class="derived-tag">{{ t.tagName }}</el-tag>
|
||||
</div>
|
||||
<div v-else-if="editFamilyId" class="derived-tags-note">
|
||||
物流 / 工艺 / 印刷位置标签由族成员自动生成,无需手动选择
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="editIsCustom" label="基础价格">
|
||||
<el-input v-model="customContentForm.goodPrice" placeholder="例如 28.00" />
|
||||
@@ -2491,6 +2528,10 @@ onMounted(() => loadAll())
|
||||
}
|
||||
.edit-family-code { margin-left: auto; color: var(--el-color-primary); }
|
||||
.edit-family-loading { color: var(--el-text-color-placeholder); font-size: 12px; padding: 4px 0; }
|
||||
.derived-tags-note { font-size: 12px; color: var(--el-text-color-secondary); margin-top: 4px; }
|
||||
.derived-tags-row { display: flex; align-items: center; flex-wrap: wrap; gap: 4px; margin-top: 4px; }
|
||||
.derived-tags-label { font-size: 12px; color: var(--el-text-color-secondary); }
|
||||
.derived-tag { pointer-events: none; }
|
||||
.edit-merged-list { display: flex; flex-direction: column; gap: 6px; margin-bottom: 8px; }
|
||||
.edit-merged-item {
|
||||
display: flex; align-items: center; gap: 8px;
|
||||
|
||||
Reference in New Issue
Block a user