feat: 商品详情
This commit is contained in:
parent
263fbb3633
commit
3f18c2ea0e
@ -2,21 +2,41 @@
|
|||||||
<div class="max-w-1/2">
|
<div class="max-w-1/2">
|
||||||
<dl v-for="item in list" :key="item.typeId" class="flex mb-1 items-center">
|
<dl v-for="item in list" :key="item.typeId" class="flex mb-1 items-center">
|
||||||
<dt>
|
<dt>
|
||||||
|
<el-upload
|
||||||
|
ref="uploadRef"
|
||||||
|
:auto-upload="false"
|
||||||
|
:limit="1"
|
||||||
|
:on-change="handleFileChange"
|
||||||
|
:on-exceed="handleExceed"
|
||||||
|
accept="image/*"
|
||||||
|
list-type="picture-card"
|
||||||
|
class="w-10 h-10"
|
||||||
|
>
|
||||||
|
<el-icon><Plus /></el-icon>
|
||||||
|
<template #file="{ file }">
|
||||||
|
<div class="relative w-10 h-10">
|
||||||
|
<img class="w-10 h-10" :src="file.url" alt="" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-upload>
|
||||||
<el-button type="primary" plain size="small" class="mr-2">{{ item.name }}</el-button>
|
<el-button type="primary" plain size="small" class="mr-2">{{ item.name }}</el-button>
|
||||||
</dt>
|
</dt>
|
||||||
<dd class="flex">
|
<dd class="flex">
|
||||||
<img :src="item.img" alt="" />
|
|
||||||
<p>
|
<p>
|
||||||
<span class="text-xs text-[#666]">数量:</span
|
<span class="text-xs text-[#666]">库存:</span
|
||||||
><el-input v-model="item.num" size="small" class="w-20 mr-2"></el-input>
|
><el-input v-model="item.stock" size="small" class="w-20 mr-2"></el-input>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<span class="text-xs text-[#666]">成本价:</span
|
||||||
|
><el-input v-model="item.originPrice" size="small" class="w-20 mr-2"></el-input>
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<span class="text-xs text-[#666]">原价:</span
|
<span class="text-xs text-[#666]">原价:</span
|
||||||
><el-input v-model="item.sale" size="small" class="w-20 mr-2"></el-input>
|
><el-input v-model="item.salePrice" size="small" class="w-20 mr-2"></el-input>
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<span class="text-xs text-[#666]">售价:</span
|
<span class="text-xs text-[#666]">售价:</span
|
||||||
><el-input v-model="item.amount" size="small" class="w-20 mr-2"></el-input>
|
><el-input v-model="item.promotionPrice" size="small" class="w-20 mr-2"></el-input>
|
||||||
</p>
|
</p>
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
@ -24,5 +44,65 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
const props = defineProps<{ list: any[] }>()
|
import { ref } from 'vue'
|
||||||
|
import { ElMessage } from 'element-plus'
|
||||||
|
import { Plus } from '@element-plus/icons-vue'
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
list: any[]
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
const props = defineProps<Props>()
|
||||||
|
|
||||||
|
const uploadRef = ref()
|
||||||
|
|
||||||
|
// 处理文件选择
|
||||||
|
const handleFileChange = (file: any, fileList: any[]) => {
|
||||||
|
// 限制只能选择一张图片
|
||||||
|
if (fileList.length > 1) {
|
||||||
|
fileList.splice(0, 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 超出限制时的处理
|
||||||
|
const handleExceed = () => {
|
||||||
|
ElMessage.warning('只能选择一张图片')
|
||||||
|
}
|
||||||
|
|
||||||
|
// 上传图片
|
||||||
|
const uploadImage = async (item: any) => {
|
||||||
|
if (!uploadRef.value) return
|
||||||
|
|
||||||
|
const uploadInstance = uploadRef.value
|
||||||
|
const fileList = uploadInstance.fileList
|
||||||
|
|
||||||
|
if (fileList.length === 0) {
|
||||||
|
ElMessage.warning('请选择要上传的图片')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 创建FormData
|
||||||
|
const form = new FormData()
|
||||||
|
form.append('files', fileList[0].raw)
|
||||||
|
|
||||||
|
// 调用上传API
|
||||||
|
const res = await (globalThis as any).api.resource.uploadFile.post!(form)
|
||||||
|
|
||||||
|
if (res.data && res.data.length > 0) {
|
||||||
|
// 更新图片URL
|
||||||
|
item.imageUrl = res.data[0].url
|
||||||
|
ElMessage.success('图片上传成功')
|
||||||
|
|
||||||
|
// 清空上传列表
|
||||||
|
uploadInstance.clearFiles()
|
||||||
|
} else {
|
||||||
|
ElMessage.error('图片上传失败')
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('上传失败:', error)
|
||||||
|
ElMessage.error('图片上传失败')
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -55,31 +55,41 @@
|
|||||||
</form-wrap>
|
</form-wrap>
|
||||||
</el-card>
|
</el-card>
|
||||||
<el-card class="mt-2 sku-info">
|
<el-card class="mt-2 sku-info">
|
||||||
<h4 class="font-bold mb-2">SKU信息:</h4>
|
<h4 class="font-bold mb-2">属性配置:</h4>
|
||||||
<el-form-item label="后台类目">
|
<el-form inline>
|
||||||
<el-tree-select
|
<el-form-item label="后台类目">
|
||||||
show-checkbox
|
<el-tree-select
|
||||||
v-model="$dialog.data.categoryId"
|
show-checkbox
|
||||||
:props="defaultAdminCategoryTreeProps"
|
v-model="$dialog.data.categoryId"
|
||||||
:render-after-expand="false"
|
:props="defaultAdminCategoryTreeProps"
|
||||||
@check="
|
:render-after-expand="false"
|
||||||
(checkedNode: any, checkedStatus: any) =>
|
@check="
|
||||||
handleCheckChange(checkedNode, checkedStatus, 'admin')
|
(checkedNode: any, checkedStatus: any) =>
|
||||||
"
|
handleCheckChange(checkedNode, checkedStatus, 'admin')
|
||||||
:load="handleLoadNode"
|
"
|
||||||
lazy
|
:load="handleLoadNode"
|
||||||
style="width: 240px"
|
lazy
|
||||||
>
|
style="width: 240px"
|
||||||
</el-tree-select>
|
>
|
||||||
</el-form-item>
|
</el-tree-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="测试商品">
|
||||||
|
<el-switch v-model="isTest" active-value="1" inactive-value="0" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
<div ref="dragRef">
|
<div ref="dragRef">
|
||||||
<dl v-for="(item, index) in categoryData" :key="item.typeId" class="flex items-center">
|
<dl v-for="(item, index) in categoryData" :key="item.id" class="flex items-center">
|
||||||
<dt class="text-sm text-[#666] mb-2">{{ item.typeName }}:</dt>
|
<dt class="text-sm text-[#666] mb-2">{{ item.categoryPropertyName }}:</dt>
|
||||||
<dd class="flex mb-2">
|
<dd class="flex mb-2">
|
||||||
<div v-for="child in item.options" :key="item.typeId + '-' + child.id">
|
<div v-for="child in item.vvPropertyValueList" :key="item.id + '-' + child.id">
|
||||||
<el-tag closable effect="plain" :type="colors[index % 4]" class="mr-1">{{
|
<el-tag
|
||||||
child.name
|
closable
|
||||||
}}</el-tag>
|
effect="plain"
|
||||||
|
:type="colors[index % 4]"
|
||||||
|
class="mr-1"
|
||||||
|
@close="onDeletePropertyValue(index, child.id)"
|
||||||
|
>{{ child.categoryPropertyValue }}</el-tag
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
<el-input
|
<el-input
|
||||||
v-if="inputVisibles[index]"
|
v-if="inputVisibles[index]"
|
||||||
@ -87,14 +97,14 @@
|
|||||||
v-model="inputValue"
|
v-model="inputValue"
|
||||||
class="w-20"
|
class="w-20"
|
||||||
size="small"
|
size="small"
|
||||||
@keyup.enter="handleInputConfirm(index)"
|
@keyup.enter="handleInputConfirm(index, skuList)"
|
||||||
@blur="handleInputConfirm(index)"
|
@blur="handleInputConfirm(index)"
|
||||||
/>
|
/>
|
||||||
<el-button
|
<el-button
|
||||||
v-else
|
v-else
|
||||||
class="button-new-tag ml-1"
|
class="button-new-tag ml-1"
|
||||||
size="small"
|
size="small"
|
||||||
@click="onAddCategoryDataOption(index)"
|
@click="onAddPropertyValue(index)"
|
||||||
>
|
>
|
||||||
+ 新增
|
+ 新增
|
||||||
</el-button>
|
</el-button>
|
||||||
@ -102,13 +112,13 @@
|
|||||||
</dl>
|
</dl>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h4 class="my-1">价格配置:</h4>
|
<h4 class="my-1">sku配置:</h4>
|
||||||
<div
|
<div
|
||||||
class="flex w-full flex-wrap justify-between p-2 rounded-[5px]"
|
class="flex w-full flex-wrap justify-between p-2 rounded-[5px]"
|
||||||
style="border: 1px dashed #bbb"
|
style="border: 1px dashed #bbb"
|
||||||
>
|
>
|
||||||
<category-config :list="list.slice(0, Math.floor(list.length / 2))" />
|
<category-config :list="skuList.slice(0, Math.floor(skuList.length / 2))" />
|
||||||
<category-config :list="list.slice(Math.floor(list.length / 2))" />
|
<category-config :list="skuList.slice(Math.floor(skuList.length / 2))" />
|
||||||
</div>
|
</div>
|
||||||
</el-card>
|
</el-card>
|
||||||
<el-card>
|
<el-card>
|
||||||
@ -126,10 +136,10 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { initConfig } from './config'
|
import { initConfig } from './config'
|
||||||
import { categoryDataMock, categoryOptionsMock } from './mock'
|
import { categoryDataMock } from './mock'
|
||||||
import {
|
import {
|
||||||
generateTargetData,
|
generateSkuList,
|
||||||
useCategoryAddOption,
|
usePropertyValue,
|
||||||
colors,
|
colors,
|
||||||
useDrag,
|
useDrag,
|
||||||
handleLoadNode,
|
handleLoadNode,
|
||||||
@ -161,18 +171,27 @@ const {
|
|||||||
onClickChooseResourceBtn
|
onClickChooseResourceBtn
|
||||||
} = useImportFile()
|
} = useImportFile()
|
||||||
|
|
||||||
const categoryOptions123 = ref(categoryOptionsMock)
|
const isTest = ref(0)
|
||||||
|
|
||||||
const categoryData = ref(categoryDataMock)
|
const categoryData = ref(categoryDataMock)
|
||||||
const { inputValue, InputRefs, inputVisibles, onAddCategoryDataOption, handleInputConfirm } =
|
const {
|
||||||
useCategoryAddOption(categoryData)
|
inputValue,
|
||||||
|
InputRefs,
|
||||||
|
inputVisibles,
|
||||||
|
onAddPropertyValue,
|
||||||
|
onClosePropertyValue,
|
||||||
|
handleInputConfirm
|
||||||
|
} = usePropertyValue(categoryData.value)
|
||||||
|
|
||||||
const { dragRef, createDrag } = useDrag(categoryData)
|
const { dragRef, createDrag } = useDrag(categoryData)
|
||||||
createDrag()
|
createDrag()
|
||||||
const list = computed(() => generateTargetData(categoryData.value))
|
const skuList = generateSkuList(categoryData.value)
|
||||||
console.warn('----- my data is list.value: ', list.value)
|
|
||||||
|
|
||||||
const htmlContent = ref('自定义')
|
const htmlContent = ref('自定义')
|
||||||
|
|
||||||
|
const onDeletePropertyValue = (index: number, id: number) =>
|
||||||
|
onClosePropertyValue(index, id, skuList)
|
||||||
|
|
||||||
const onSubmit = () => {
|
const onSubmit = () => {
|
||||||
console.warn('----- my data is htmlContent: ', htmlContent.value)
|
console.warn('----- my data is htmlContent: ', htmlContent.value)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -37,7 +37,7 @@ export const categoryOptionsMock = [
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
/*
|
||||||
// 类目配置项
|
// 类目配置项
|
||||||
export const categoryDataMock = [
|
export const categoryDataMock = [
|
||||||
{
|
{
|
||||||
@ -66,6 +66,145 @@ export const categoryDataMock = [
|
|||||||
{ id: 33, name: '黄' }
|
{ id: 33, name: '黄' }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
] */
|
||||||
|
|
||||||
|
// 类目配置项
|
||||||
|
export const categoryDataMock = [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
isDelete: 0,
|
||||||
|
createTime: 1756023528000,
|
||||||
|
modifyTime: 1756023528000,
|
||||||
|
categoryId: 16,
|
||||||
|
categoryName: '项链',
|
||||||
|
categoryPropertyName: '珍珠直径',
|
||||||
|
defaultSort: -1,
|
||||||
|
vvPropertyValueList: [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
isDelete: 0,
|
||||||
|
createTime: 1756015260000,
|
||||||
|
modifyTime: 1756015260000,
|
||||||
|
categoryPropertyId: 1,
|
||||||
|
categoryPropertyValue: '6-7mm',
|
||||||
|
defaultSort: -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
isDelete: 0,
|
||||||
|
createTime: 1756015260000,
|
||||||
|
modifyTime: 1756015260000,
|
||||||
|
categoryPropertyId: 1,
|
||||||
|
categoryPropertyValue: '8-9mm',
|
||||||
|
defaultSort: 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 4,
|
||||||
|
isDelete: 0,
|
||||||
|
createTime: 1756015260000,
|
||||||
|
modifyTime: 1756015260000,
|
||||||
|
categoryPropertyId: 1,
|
||||||
|
categoryPropertyValue: '9-10mm',
|
||||||
|
defaultSort: 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
isDelete: 0,
|
||||||
|
createTime: 1756015260000,
|
||||||
|
modifyTime: 1756015260000,
|
||||||
|
categoryPropertyId: 1,
|
||||||
|
categoryPropertyValue: '7-8mm',
|
||||||
|
defaultSort: 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 5,
|
||||||
|
isDelete: 0,
|
||||||
|
createTime: 1756015260000,
|
||||||
|
modifyTime: 1756015260000,
|
||||||
|
categoryPropertyId: 1,
|
||||||
|
categoryPropertyValue: '10-11mm',
|
||||||
|
defaultSort: 5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 6,
|
||||||
|
isDelete: 0,
|
||||||
|
createTime: 1756015260000,
|
||||||
|
modifyTime: 1756015260000,
|
||||||
|
categoryPropertyId: 1,
|
||||||
|
categoryPropertyValue: '11-12mm',
|
||||||
|
defaultSort: 6
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
isDelete: 0,
|
||||||
|
createTime: 1756023528000,
|
||||||
|
modifyTime: 1756023528000,
|
||||||
|
categoryId: 16,
|
||||||
|
categoryName: '项链',
|
||||||
|
categoryPropertyName: '颜色分类',
|
||||||
|
defaultSort: 2,
|
||||||
|
vvPropertyValueList: [
|
||||||
|
{
|
||||||
|
id: 12,
|
||||||
|
isDelete: 0,
|
||||||
|
createTime: 1756015420000,
|
||||||
|
modifyTime: 1756015420000,
|
||||||
|
categoryPropertyId: 3,
|
||||||
|
categoryPropertyValue: '极光正圆【配鉴定证书】',
|
||||||
|
defaultSort: 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
isDelete: 0,
|
||||||
|
createTime: 1756023528000,
|
||||||
|
modifyTime: 1756023528000,
|
||||||
|
categoryId: 16,
|
||||||
|
categoryName: '项链',
|
||||||
|
categoryPropertyName: '项链长度',
|
||||||
|
defaultSort: 3,
|
||||||
|
vvPropertyValueList: [
|
||||||
|
{
|
||||||
|
id: 8,
|
||||||
|
isDelete: 0,
|
||||||
|
createTime: 1756015381000,
|
||||||
|
modifyTime: 1756015381000,
|
||||||
|
categoryPropertyId: 2,
|
||||||
|
categoryPropertyValue: '43cm',
|
||||||
|
defaultSort: 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 9,
|
||||||
|
isDelete: 0,
|
||||||
|
createTime: 1756015381000,
|
||||||
|
modifyTime: 1756015381000,
|
||||||
|
categoryPropertyId: 2,
|
||||||
|
categoryPropertyValue: '45cm',
|
||||||
|
defaultSort: 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 10,
|
||||||
|
isDelete: 0,
|
||||||
|
createTime: 1756015381000,
|
||||||
|
modifyTime: 1756015381000,
|
||||||
|
categoryPropertyId: 2,
|
||||||
|
categoryPropertyValue: '47cm',
|
||||||
|
defaultSort: 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 11,
|
||||||
|
isDelete: 0,
|
||||||
|
createTime: 1756015381000,
|
||||||
|
modifyTime: 1756015381000,
|
||||||
|
categoryPropertyId: 2,
|
||||||
|
categoryPropertyValue: '50cm',
|
||||||
|
defaultSort: 4
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|||||||
@ -2,43 +2,49 @@ import { useDraggable } from 'vue-draggable-plus'
|
|||||||
// 定义源数据的结构类型
|
// 定义源数据的结构类型
|
||||||
interface Option {
|
interface Option {
|
||||||
id: number
|
id: number
|
||||||
name: string
|
categoryPropertyValue: string
|
||||||
|
isAdd?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Category {
|
interface Category {
|
||||||
typeName: string
|
typeName: string
|
||||||
typeId: number
|
typeId: number
|
||||||
options: Option[]
|
vvPropertyValueList: Option[]
|
||||||
}
|
}
|
||||||
|
|
||||||
type CategoryDataMock = Category[]
|
type CategoryDataMock = Category[]
|
||||||
|
|
||||||
// 定义目标数据的结构类型
|
// 定义目标数据的结构类型
|
||||||
interface TargetData {
|
interface TSkuList {
|
||||||
serialNo: string
|
serialNo: string
|
||||||
name: string
|
name: string
|
||||||
sale: string
|
salePrice: string
|
||||||
img: string
|
imageUrl: string
|
||||||
num: number
|
stock: number
|
||||||
amount: string
|
originPrice: number
|
||||||
|
promotionPrice: string
|
||||||
|
vvSkuPropertyValueList: any[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export const generateTargetData = (categoryData: CategoryDataMock): TargetData[] => {
|
// 创建sku列表
|
||||||
const result: TargetData[] = []
|
export const generateSkuList = (categoryData: CategoryDataMock): Ref<TSkuList[]> => {
|
||||||
const optionGroups: Option[][] = categoryData.map((category) => category.options)
|
const result: TSkuList[] = []
|
||||||
|
const optionGroups: Option[][] = categoryData.map((category) => category.vvPropertyValueList)
|
||||||
|
|
||||||
// 使用递归生成所有可能的组合
|
// 使用递归生成所有可能的组合
|
||||||
const combine = (index: number, current: Option[]) => {
|
const combine = (index: number, current: Option[]) => {
|
||||||
if (index === optionGroups.length) {
|
if (index === optionGroups.length) {
|
||||||
const serialNo = current.map((opt) => opt.id.toString()).join('-')
|
const serialNo = current.map((opt) => opt.id.toString()).join('-')
|
||||||
const name = current.map((opt) => opt.name).join('-')
|
const name = current.map((opt) => opt.categoryPropertyValue).join('-')
|
||||||
result.push({
|
result.push({
|
||||||
serialNo,
|
serialNo,
|
||||||
name,
|
name,
|
||||||
sale: '',
|
salePrice: '',
|
||||||
num: 0,
|
stock: 0,
|
||||||
img: '',
|
originPrice: 0,
|
||||||
amount: ''
|
imageUrl: '',
|
||||||
|
promotionPrice: '',
|
||||||
|
vvSkuPropertyValueList: current
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -48,33 +54,99 @@ export const generateTargetData = (categoryData: CategoryDataMock): TargetData[]
|
|||||||
}
|
}
|
||||||
|
|
||||||
combine(0, [])
|
combine(0, [])
|
||||||
return result
|
return ref(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 添加类目
|
// 增加属性、删除属性
|
||||||
export const useCategoryAddOption = (categoryData: any) => {
|
export const usePropertyValue = (categoryData: CategoryDataMock) => {
|
||||||
const inputVisibles = ref(Array.from({ length: categoryData.value.length }, (_) => false))
|
const inputVisibles = ref(Array.from({ length: categoryData.length }, (_) => false))
|
||||||
|
|
||||||
const InputRefs = ref()
|
const InputRefs = ref()
|
||||||
const inputValue = ref('')
|
const inputValue = ref('')
|
||||||
const onAddCategoryDataOption = (index: number) => {
|
const onAddPropertyValue = (index: number) => {
|
||||||
inputVisibles.value[index] = true
|
inputVisibles.value[index] = true
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
InputRefs.value[index].input!.focus()
|
InputRefs.value[index].input!.focus()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
const handleInputConfirm = (index: number) => {
|
const onClosePropertyValue = (index: number, id: number, skuList: Ref<TSkuList[]>) => {
|
||||||
|
const i = categoryData[index].vvPropertyValueList.findIndex((item: any) => item.id === id)
|
||||||
|
categoryData[index].vvPropertyValueList.splice(i, 1)
|
||||||
|
const deleteIndexs: number[] = []
|
||||||
|
skuList.value.forEach((item: TSkuList, skuIndex: number) => {
|
||||||
|
if (item.vvSkuPropertyValueList.find((it) => it.id === id)) {
|
||||||
|
deleteIndexs.push(skuIndex)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
skuList.value = skuList.value.filter(
|
||||||
|
(_: TSkuList, index: number) => !deleteIndexs.includes(index)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
// 新增回车确认
|
||||||
|
const handleInputConfirm = (lineIndex: number, skuList: TSkuList[] = []) => {
|
||||||
if (inputValue.value) {
|
if (inputValue.value) {
|
||||||
categoryData.value[index].options.push({
|
const id = Math.random()
|
||||||
id: inputValue.value,
|
categoryData[lineIndex].vvPropertyValueList.push({
|
||||||
name: inputValue.value,
|
id,
|
||||||
|
categoryPropertyValue: inputValue.value,
|
||||||
isAdd: true
|
isAdd: true
|
||||||
})
|
})
|
||||||
|
skuList.push(
|
||||||
|
...generateAddSkuList(
|
||||||
|
lineIndex,
|
||||||
|
{ id, categoryPropertyValue: inputValue.value },
|
||||||
|
categoryData
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
inputVisibles.value[index] = false
|
inputVisibles.value[lineIndex] = false
|
||||||
inputValue.value = ''
|
inputValue.value = ''
|
||||||
}
|
}
|
||||||
return { inputVisibles, InputRefs, inputValue, onAddCategoryDataOption, handleInputConfirm }
|
|
||||||
|
// 新增属性的时候创建数据
|
||||||
|
const generateAddSkuList = (
|
||||||
|
lineIndex: number,
|
||||||
|
addData: Option,
|
||||||
|
categoryData: CategoryDataMock
|
||||||
|
): TSkuList[] => {
|
||||||
|
const result: TSkuList[] = []
|
||||||
|
const optionGroups: Option[][] = categoryData
|
||||||
|
.filter((_, index) => index !== lineIndex)
|
||||||
|
.map((category) => category.vvPropertyValueList)
|
||||||
|
|
||||||
|
// 使用递归生成所有可能的组合
|
||||||
|
const combine = (index: number, current: Option[]) => {
|
||||||
|
if (index === categoryData.length) {
|
||||||
|
const serialNo = current.map((opt) => opt.id.toString()).join('-')
|
||||||
|
const name = current.map((opt) => opt.categoryPropertyValue).join('-')
|
||||||
|
result.push({
|
||||||
|
serialNo,
|
||||||
|
name,
|
||||||
|
salePrice: '',
|
||||||
|
stock: 0,
|
||||||
|
originPrice: 0,
|
||||||
|
imageUrl: '',
|
||||||
|
promotionPrice: '',
|
||||||
|
vvSkuPropertyValueList: current
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for (const option of optionGroups[index]) {
|
||||||
|
combine(index + 1, [...current, option])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
combine(1, [addData])
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
inputVisibles,
|
||||||
|
InputRefs,
|
||||||
|
inputValue,
|
||||||
|
onAddPropertyValue,
|
||||||
|
onClosePropertyValue,
|
||||||
|
handleInputConfirm
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const colors = ['primary', 'success', 'warning', 'danger', 'info']
|
export const colors = ['primary', 'success', 'warning', 'danger', 'info']
|
||||||
@ -120,7 +192,7 @@ export const handleLoadNode = (node: any, resolve: any) => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 树结构懒加载后台类目
|
// 树结构懒加载app类目
|
||||||
export const handleLoadNode2 = (node: any, resolve: any) => {
|
export const handleLoadNode2 = (node: any, resolve: any) => {
|
||||||
api.commodity.getAppCategoryList.post!<any>({ parentId: node.data.value || 0 }).then((res) => {
|
api.commodity.getAppCategoryList.post!<any>({ parentId: node.data.value || 0 }).then((res) => {
|
||||||
resolve(
|
resolve(
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user