|
|
@@ -23,6 +23,15 @@
|
|
|
</el-select>
|
|
|
</el-form-item>
|
|
|
|
|
|
+ <el-form-item label="商品分类">
|
|
|
+ <el-select v-model="form.categoryId" placeholder="请选择分类(用于前台商城筛选)" clearable filterable style="width: 300px;">
|
|
|
+ <el-option-group v-for="group in categoryGroups" :key="group.label" :label="group.label">
|
|
|
+ <el-option v-for="cat in group.options" :key="cat.id" :label="cat.label" :value="cat.id" />
|
|
|
+ </el-option-group>
|
|
|
+ </el-select>
|
|
|
+ <div style="font-size: 12px; color: #999; margin-top: 4px;">不选则不出现在商城分类筛选中;可在「商品分类管理」中维护分类</div>
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
<!-- 测评商品扩展信息 -->
|
|
|
<template v-if="form.productType === 'assessment'">
|
|
|
<el-form-item label="测评类型">
|
|
|
@@ -343,7 +352,7 @@
|
|
|
</template>
|
|
|
|
|
|
<script>
|
|
|
-import { getProduct, createProduct, updateProduct, listAllSupplySystems, getPredefinedPurchaseFields, getProductPurchaseFields, saveProductPurchaseFields, getMySupplySystem, saveProductGiftRule, listProductGiftRules, listMembershipLevels, getGrowthArchiveProduct, saveGrowthArchiveProduct, listDeliveryServicePersons, saveDeliveryServicePersons, listDeliveryOnlineSlots, saveDeliveryOnlineSlots, getProductList, getProductSkuList, saveBundleItems, getBundleItems, getApprovedGuides, saveProductGift, getProductGiftList } from '@/api/admin'
|
|
|
+import { getProduct, createProduct, updateProduct, listAllSupplySystems, getPredefinedPurchaseFields, getProductPurchaseFields, saveProductPurchaseFields, getMySupplySystem, saveProductGiftRule, listProductGiftRules, listMembershipLevels, getGrowthArchiveProduct, saveGrowthArchiveProduct, listDeliveryServicePersons, saveDeliveryServicePersons, listDeliveryOnlineSlots, saveDeliveryOnlineSlots, getProductList, getProductSkuList, saveBundleItems, getBundleItems, getApprovedGuides, saveProductGift, getProductGiftList, getCategoryTree } from '@/api/admin'
|
|
|
import { saveDimensionWeights, getDimensionWeights } from '@/api/dimension-weight'
|
|
|
import DimensionWeightPicker from '@/components/DimensionWeightPicker.vue'
|
|
|
import ProductSkuEditor from './components/ProductSkuEditor.vue'
|
|
|
@@ -385,7 +394,8 @@ export default {
|
|
|
totalSessions: 1,
|
|
|
validityDays: 365,
|
|
|
guideScope: 'all',
|
|
|
- sortOrder: 0
|
|
|
+ sortOrder: 0,
|
|
|
+ categoryId: null
|
|
|
},
|
|
|
bundleItems: [], // 套餐组成: [{childProductId, childSkuId, quantity, productOptions:[], skuOptions:[]}]
|
|
|
servicePersons: [], // 线上服务者(deliveryMethod=4): [{userId,name,title,intro,avatar,price,originalPrice}]
|
|
|
@@ -405,6 +415,7 @@ export default {
|
|
|
// 可选赠品配置:{ [levelCode]: [{giftType,giftProductId,cfValue,sortOrder}] }
|
|
|
giftConfigsByLevel: {},
|
|
|
onShelfProducts: [],
|
|
|
+ categoryList: [],
|
|
|
rules: {
|
|
|
name: [{ required: true, message: '请输入商品名称', trigger: 'blur' }],
|
|
|
productType: [{ required: true, message: '请选择商品类型', trigger: 'change' }],
|
|
|
@@ -533,6 +544,32 @@ export default {
|
|
|
isEdit() {
|
|
|
return !!this.$route.query.id
|
|
|
},
|
|
|
+ categoryGroups() {
|
|
|
+ const groups = []
|
|
|
+ const map = {}
|
|
|
+ const flat = []
|
|
|
+ const walk = (nodes, level) => {
|
|
|
+ for (const node of nodes) {
|
|
|
+ const prefix = level > 0 ? ' '.repeat(level) : ''
|
|
|
+ flat.push({ id: node.id, label: prefix + node.name, parentId: node.parentId, level })
|
|
|
+ map[node.id] = node
|
|
|
+ if (node.children && node.children.length) {
|
|
|
+ walk(node.children, level + 1)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ walk(this.categoryList, 0)
|
|
|
+ for (const item of flat) {
|
|
|
+ const parentName = map[item.parentId] ? map[item.parentId].name : '顶级分类'
|
|
|
+ let group = groups.find(g => g.label === parentName)
|
|
|
+ if (!group) {
|
|
|
+ group = { label: parentName, options: [] }
|
|
|
+ groups.push(group)
|
|
|
+ }
|
|
|
+ group.options.push(item)
|
|
|
+ }
|
|
|
+ return groups
|
|
|
+ },
|
|
|
isSupplierAdmin() {
|
|
|
const rolesStr = localStorage.getItem('roles')
|
|
|
const roles = rolesStr ? JSON.parse(rolesStr) : []
|
|
|
@@ -578,6 +615,7 @@ export default {
|
|
|
this.loadPredefinedFields()
|
|
|
this.ensureMembershipLevels()
|
|
|
this.loadOnShelfProducts()
|
|
|
+ this.loadCategories()
|
|
|
if (this.isEdit) {
|
|
|
this.loadProduct(this.$route.query.id)
|
|
|
}
|
|
|
@@ -645,7 +683,8 @@ export default {
|
|
|
totalSessions: p.totalSessions || 1,
|
|
|
validityDays: p.validityDays || 365,
|
|
|
guideScope: p.guideScope || 'all',
|
|
|
- sortOrder: p.sortOrder != null ? p.sortOrder : 0
|
|
|
+ sortOrder: p.sortOrder != null ? p.sortOrder : 0,
|
|
|
+ categoryId: p.categoryId || null
|
|
|
}
|
|
|
if (p.images) {
|
|
|
try {
|
|
|
@@ -781,6 +820,16 @@ async loadGiftRule(productId) {
|
|
|
console.warn('加载上架商品失败', e)
|
|
|
}
|
|
|
},
|
|
|
+ async loadCategories() {
|
|
|
+ try {
|
|
|
+ const res = await getCategoryTree(true)
|
|
|
+ if (res.code === 200 && Array.isArray(res.data)) {
|
|
|
+ this.categoryList = res.data
|
|
|
+ }
|
|
|
+ } catch (e) {
|
|
|
+ console.warn('加载商品分类失败', e)
|
|
|
+ }
|
|
|
+ },
|
|
|
async loadGiftConfigs(productId) {
|
|
|
try {
|
|
|
await this.ensureMembershipLevels()
|