feat: 商品详情编辑
This commit is contained in:
parent
e1f682b95c
commit
c198ca35ea
@ -1,5 +1,12 @@
|
|||||||
|
interface PreviewItem {
|
||||||
|
fileName: string
|
||||||
|
name: string
|
||||||
|
resourceUrl: string
|
||||||
|
type: 'image' | 'video'
|
||||||
|
}
|
||||||
|
|
||||||
// 选择资源库图片
|
// 选择资源库图片
|
||||||
export const useImportFile = () => {
|
export const useImportFile = (fileList: Ref<PreviewItem[]>) => {
|
||||||
const showFileExplorer = ref(false)
|
const showFileExplorer = ref(false)
|
||||||
const fileType = {
|
const fileType = {
|
||||||
mainImageUrl: '主图',
|
mainImageUrl: '主图',
|
||||||
@ -10,8 +17,8 @@ export const useImportFile = () => {
|
|||||||
const currentPathArray = ref<{ name: string; id: number }[]>([{ name: '根目录', id: 0 }])
|
const currentPathArray = ref<{ name: string; id: number }[]>([{ name: '根目录', id: 0 }])
|
||||||
|
|
||||||
// 处理文件选择
|
// 处理文件选择
|
||||||
const handleChooseResourceFileCallback = (files: any[] = []) => {
|
const handleChooseResourceFileCallback = (files: PreviewItem[] = []) => {
|
||||||
handleChooseFiles(curFileType.value, files)
|
handleChooseFiles(curFileType.value, files, fileList.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
const onClickChooseResourceBtn = (type: 'mainImageUrl' | 'videoUrl' | 'subImage') => {
|
const onClickChooseResourceBtn = (type: 'mainImageUrl' | 'videoUrl' | 'subImage') => {
|
||||||
@ -26,10 +33,10 @@ export const useImportFile = () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const fileList = ref<any[]>([])
|
|
||||||
export const handleChooseFiles = (
|
export const handleChooseFiles = (
|
||||||
fileType: 'mainImageUrl' | 'videoUrl' | 'subImage',
|
fileType: 'mainImageUrl' | 'videoUrl' | 'subImage',
|
||||||
files: any = []
|
files: any = [],
|
||||||
|
fileList: PreviewItem[]
|
||||||
) => {
|
) => {
|
||||||
const fileNameMap = {
|
const fileNameMap = {
|
||||||
mainImageUrl: '主图',
|
mainImageUrl: '主图',
|
||||||
@ -37,12 +44,10 @@ export const handleChooseFiles = (
|
|||||||
subImage: '副图'
|
subImage: '副图'
|
||||||
}
|
}
|
||||||
if (['mainImageUrl', 'videoUrl'].includes(fileType)) {
|
if (['mainImageUrl', 'videoUrl'].includes(fileType)) {
|
||||||
const index = fileList.value.findIndex((item: any) => item.fileType === fileType)
|
const index = fileList.findIndex((item: any) => item.fileType === fileType)
|
||||||
if (index !== -1) {
|
if (index !== -1) {
|
||||||
fileList.value.splice(index, 1)
|
fileList.splice(index, 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fileList.value.push(
|
fileList.push(...files.map((item: any) => ({ ...item, fileType, name: fileNameMap[fileType] })))
|
||||||
...files.map((item: any) => ({ ...item, fileType, name: fileNameMap[fileType] }))
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,7 +5,7 @@ export const initConfig = () => {
|
|||||||
dialog: [
|
dialog: [
|
||||||
{
|
{
|
||||||
title: { label: '商品标题', class: '!w-full' },
|
title: { label: '商品标题', class: '!w-full' },
|
||||||
appCategoryId: { label: 'app类目', slot: 'appCategoryId' },
|
appCategoryIds: { label: 'app类目', slot: 'appCategoryId' },
|
||||||
mainImageUrl: { label: '主图', slot: 'mainFile' },
|
mainImageUrl: { label: '主图', slot: 'mainFile' },
|
||||||
videoUrl: { label: '视频', slot: 'videoFile' },
|
videoUrl: { label: '视频', slot: 'videoFile' },
|
||||||
subImageUrl: { label: '副图', slot: 'subFile' },
|
subImageUrl: { label: '副图', slot: 'subFile' },
|
||||||
|
|||||||
@ -9,9 +9,10 @@
|
|||||||
v-model="$dialog.data.appCategoryId"
|
v-model="$dialog.data.appCategoryId"
|
||||||
:props="defaultAdminCategoryTreeProps"
|
:props="defaultAdminCategoryTreeProps"
|
||||||
:render-after-expand="false"
|
:render-after-expand="false"
|
||||||
|
:default-expanded-keys="defaultCheckedNodes.app"
|
||||||
@check="
|
@check="
|
||||||
(checkedNode: any, checkedStatus: any) =>
|
(checkedNode: any, checkedStatus: any) =>
|
||||||
handleCheckChange(checkedNode, checkedStatus, 'app')
|
handleCheckChange(checkedNode, checkedStatus, 'app', $dialog.data)
|
||||||
"
|
"
|
||||||
:load="handleLoadNode2"
|
:load="handleLoadNode2"
|
||||||
lazy
|
lazy
|
||||||
@ -22,7 +23,7 @@
|
|||||||
<file-upload-btn
|
<file-upload-btn
|
||||||
accept="image/*"
|
accept="image/*"
|
||||||
size="normal"
|
size="normal"
|
||||||
@change="(val) => handleChooseFiles('mainImageUrl', val)"
|
@change="(val) => handleChooseFiles('mainImageUrl', val, fileList)"
|
||||||
/>
|
/>
|
||||||
<el-button class="ml-2" @click="onClickChooseResourceBtn('mainImageUrl')"
|
<el-button class="ml-2" @click="onClickChooseResourceBtn('mainImageUrl')"
|
||||||
>资源库导入</el-button
|
>资源库导入</el-button
|
||||||
@ -32,7 +33,7 @@
|
|||||||
<file-upload-btn
|
<file-upload-btn
|
||||||
size="normal"
|
size="normal"
|
||||||
accept="video/*"
|
accept="video/*"
|
||||||
@change="(val) => handleChooseFiles('videoUrl', val)"
|
@change="(val) => handleChooseFiles('videoUrl', val, fileList)"
|
||||||
/>
|
/>
|
||||||
<el-button class="ml-2" @click="onClickChooseResourceBtn('videoUrl')"
|
<el-button class="ml-2" @click="onClickChooseResourceBtn('videoUrl')"
|
||||||
>资源库导入</el-button
|
>资源库导入</el-button
|
||||||
@ -43,7 +44,7 @@
|
|||||||
size="normal"
|
size="normal"
|
||||||
multiple
|
multiple
|
||||||
accept="image/*"
|
accept="image/*"
|
||||||
@change="(val) => handleChooseFiles('subImage', val)"
|
@change="(val) => handleChooseFiles('subImage', val, fileList)"
|
||||||
/>
|
/>
|
||||||
<el-button class="ml-2" @click="onClickChooseResourceBtn('subImage')"
|
<el-button class="ml-2" @click="onClickChooseResourceBtn('subImage')"
|
||||||
>资源库导入</el-button
|
>资源库导入</el-button
|
||||||
@ -60,9 +61,10 @@
|
|||||||
<el-form-item label="后台类目">
|
<el-form-item label="后台类目">
|
||||||
<el-tree-select
|
<el-tree-select
|
||||||
show-checkbox
|
show-checkbox
|
||||||
v-model="$dialog.data.categoryId"
|
v-model="$dialog.data.adminCategoryId"
|
||||||
:props="defaultAdminCategoryTreeProps"
|
:props="defaultAdminCategoryTreeProps"
|
||||||
:render-after-expand="false"
|
:render-after-expand="false"
|
||||||
|
:default-expanded-keys="defaultCheckedNodes.admin"
|
||||||
@check="
|
@check="
|
||||||
(checkedNode: any, checkedStatus: any) =>
|
(checkedNode: any, checkedStatus: any) =>
|
||||||
handleCheckChange(checkedNode, checkedStatus, 'admin')
|
handleCheckChange(checkedNode, checkedStatus, 'admin')
|
||||||
@ -78,7 +80,7 @@
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
<div ref="dragRef">
|
<div ref="dragRef">
|
||||||
<dl v-for="(item, index) in categoryData" :key="item.id" class="flex items-center">
|
<dl v-for="(item, index) in adminCategoryData" :key="item.id" class="flex items-center">
|
||||||
<dt class="text-sm text-[#666] mb-2">{{ item.categoryPropertyName }}:</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.vvPropertyValueList" :key="item.id + '-' + child.id">
|
<div v-for="child in item.vvPropertyValueList" :key="item.id + '-' + child.id">
|
||||||
@ -146,44 +148,58 @@ import {
|
|||||||
handleLoadNode2,
|
handleLoadNode2,
|
||||||
handleCheckChange,
|
handleCheckChange,
|
||||||
defaultAdminCategoryTreeProps,
|
defaultAdminCategoryTreeProps,
|
||||||
checkedNodes
|
defaultCheckedNodes,
|
||||||
|
handleGetDialogData,
|
||||||
|
fileList,
|
||||||
|
TSkuList
|
||||||
} from './use-method'
|
} from './use-method'
|
||||||
import categoryConfig from './category-config.vue'
|
import categoryConfig from './category-config.vue'
|
||||||
import wanEditor from './editor.vue'
|
import wanEditor from './editor.vue'
|
||||||
import fileUploadBtn from '@/components/FileUploadBtn/index.vue'
|
import fileUploadBtn from '@/components/FileUploadBtn/index.vue'
|
||||||
import resourceReview from '@/components/ResourceReview/index.vue'
|
import resourceReview from '@/components/ResourceReview/index.vue'
|
||||||
import { useImportFile, fileList, handleChooseFiles } from './choose-file-method'
|
import { useImportFile, handleChooseFiles } from './choose-file-method'
|
||||||
import FileExplorerDialog from '@/components/FileExplorerDialog/index.vue'
|
import FileExplorerDialog from '@/components/FileExplorerDialog/index.vue'
|
||||||
|
import { Atrans$DialogRes } from '@/utils/page/config'
|
||||||
|
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
|
const $dialog = ref<Atrans$DialogRes>({} as Atrans$DialogRes)
|
||||||
const init = async () => {
|
const init = async () => {
|
||||||
checkedNodes.value = { admin: [], app: [] }
|
defaultCheckedNodes.value = { admin: [], app: [] }
|
||||||
await api.commodity.getCommodityDetail.post!({ productId: route.query.id })
|
const data = initConfig().value!
|
||||||
|
$dialog.value = data.$dialog
|
||||||
|
$dialog.value.config = data.dialog1
|
||||||
|
$dialog.value.data = { appCategoryId: '', adminCategoryId: '', isTest: 0, title: '' }
|
||||||
|
adminCategoryData.value = []
|
||||||
|
if (route.query.id) {
|
||||||
|
const res = await api.commodity.getCommodityDetail.post!<any>({ productId: route.query.id })
|
||||||
|
handleGetDialogData(res.data, $dialog, fileList)
|
||||||
|
adminCategoryData.value = categoryDataMock
|
||||||
|
initPropertyData(adminCategoryData.value)
|
||||||
|
skuList.value = generateSkuList(adminCategoryData.value)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const { $dialog, dialog1 } = toRefs(initConfig().value!)
|
|
||||||
$dialog.value.config = dialog1.value
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
showFileExplorer,
|
showFileExplorer,
|
||||||
currentPathArray,
|
currentPathArray,
|
||||||
handleChooseResourceFileCallback,
|
handleChooseResourceFileCallback,
|
||||||
onClickChooseResourceBtn
|
onClickChooseResourceBtn
|
||||||
} = useImportFile()
|
} = useImportFile(fileList)
|
||||||
|
|
||||||
const categoryData = ref(categoryDataMock)
|
const adminCategoryData = ref([])
|
||||||
const {
|
const {
|
||||||
inputValue,
|
inputValue,
|
||||||
InputRefs,
|
InputRefs,
|
||||||
inputVisibles,
|
inputVisibles,
|
||||||
|
initPropertyData,
|
||||||
onAddPropertyValue,
|
onAddPropertyValue,
|
||||||
onClosePropertyValue,
|
onClosePropertyValue,
|
||||||
handleInputConfirm
|
handleInputConfirm
|
||||||
} = usePropertyValue(categoryData.value)
|
} = usePropertyValue()
|
||||||
|
|
||||||
const { dragRef, createDrag } = useDrag(categoryData)
|
const { dragRef, createDrag } = useDrag(adminCategoryData)
|
||||||
createDrag()
|
createDrag()
|
||||||
const skuList = generateSkuList(categoryData.value)
|
const skuList = ref<TSkuList[]>([])
|
||||||
|
|
||||||
const htmlContent = ref('自定义')
|
const htmlContent = ref('自定义')
|
||||||
|
|
||||||
|
|||||||
@ -207,6 +207,152 @@ export const categoryDataMock = [
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
/* export const categoryDataMock = [
|
||||||
|
{
|
||||||
|
id: 7,
|
||||||
|
isDelete: 0,
|
||||||
|
createTime: 1755940247000,
|
||||||
|
modifyTime: 1755940247000,
|
||||||
|
productId: 5,
|
||||||
|
productPropertyName: '珍珠直径',
|
||||||
|
defalutSort: 1,
|
||||||
|
vvProductPropertyValueList: [
|
||||||
|
{
|
||||||
|
id: 21,
|
||||||
|
isDelete: 0,
|
||||||
|
createTime: 1755940416000,
|
||||||
|
modifyTime: 1755940416000,
|
||||||
|
productId: 5,
|
||||||
|
productPropertyName: '珍珠直径',
|
||||||
|
productPropertyValue: '7-8mm',
|
||||||
|
productPropertyId: 7,
|
||||||
|
defalutSort: 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 20,
|
||||||
|
isDelete: 0,
|
||||||
|
createTime: 1755940416000,
|
||||||
|
modifyTime: 1755940416000,
|
||||||
|
productId: 5,
|
||||||
|
productPropertyName: '珍珠直径',
|
||||||
|
productPropertyValue: '8-9mm',
|
||||||
|
productPropertyId: 7,
|
||||||
|
defalutSort: 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 19,
|
||||||
|
isDelete: 0,
|
||||||
|
createTime: 1755940416000,
|
||||||
|
modifyTime: 1755940416000,
|
||||||
|
productId: 5,
|
||||||
|
productPropertyName: '珍珠直径',
|
||||||
|
productPropertyValue: '9-10mm',
|
||||||
|
productPropertyId: 7,
|
||||||
|
defalutSort: 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 18,
|
||||||
|
isDelete: 0,
|
||||||
|
createTime: 1755940416000,
|
||||||
|
modifyTime: 1755940416000,
|
||||||
|
productId: 5,
|
||||||
|
productPropertyName: '珍珠直径',
|
||||||
|
productPropertyValue: '10-11mm',
|
||||||
|
productPropertyId: 7,
|
||||||
|
defalutSort: 4
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 6,
|
||||||
|
isDelete: 0,
|
||||||
|
createTime: 1755940247000,
|
||||||
|
modifyTime: 1755940247000,
|
||||||
|
productId: 5,
|
||||||
|
productPropertyName: '项链长度',
|
||||||
|
defalutSort: 2,
|
||||||
|
vvProductPropertyValueList: [
|
||||||
|
{
|
||||||
|
id: 17,
|
||||||
|
isDelete: 0,
|
||||||
|
createTime: 1755940428000,
|
||||||
|
modifyTime: 1755940428000,
|
||||||
|
productId: 5,
|
||||||
|
productPropertyName: '项链长度',
|
||||||
|
productPropertyValue: '43cm',
|
||||||
|
productPropertyId: 6,
|
||||||
|
defalutSort: 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 16,
|
||||||
|
isDelete: 0,
|
||||||
|
createTime: 1755940519000,
|
||||||
|
modifyTime: 1755940519000,
|
||||||
|
productId: 5,
|
||||||
|
productPropertyName: '项链长度',
|
||||||
|
productPropertyValue: '45cm',
|
||||||
|
productPropertyId: 6,
|
||||||
|
defalutSort: 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 15,
|
||||||
|
isDelete: 0,
|
||||||
|
createTime: 1755940519000,
|
||||||
|
modifyTime: 1755940519000,
|
||||||
|
productId: 5,
|
||||||
|
productPropertyName: '项链长度',
|
||||||
|
productPropertyValue: '47cm',
|
||||||
|
productPropertyId: 6,
|
||||||
|
defalutSort: 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 14,
|
||||||
|
isDelete: 0,
|
||||||
|
createTime: 1755940519000,
|
||||||
|
modifyTime: 1755940519000,
|
||||||
|
productId: 5,
|
||||||
|
productPropertyName: '项链长度',
|
||||||
|
productPropertyValue: '50cm',
|
||||||
|
productPropertyId: 6,
|
||||||
|
defalutSort: 4
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 5,
|
||||||
|
isDelete: 0,
|
||||||
|
createTime: 1755940247000,
|
||||||
|
modifyTime: 1755940247000,
|
||||||
|
productId: 5,
|
||||||
|
productPropertyName: '颜色分类',
|
||||||
|
defalutSort: 3,
|
||||||
|
vvProductPropertyValueList: [
|
||||||
|
{
|
||||||
|
id: 13,
|
||||||
|
isDelete: 0,
|
||||||
|
createTime: 1755940570000,
|
||||||
|
modifyTime: 1755940570000,
|
||||||
|
productId: 5,
|
||||||
|
productPropertyName: '颜色分类',
|
||||||
|
productPropertyValue: '【极光白透粉】大几乎无瑕大配证书',
|
||||||
|
productPropertyId: 5,
|
||||||
|
defalutSort: 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 12,
|
||||||
|
isDelete: 0,
|
||||||
|
createTime: 1755940570000,
|
||||||
|
modifyTime: 1755940570000,
|
||||||
|
productId: 5,
|
||||||
|
productPropertyName: '颜色分类',
|
||||||
|
productPropertyValue: '【极光冷白】大几乎无瑕大配证书',
|
||||||
|
productPropertyId: 5,
|
||||||
|
defalutSort: 2
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
] */
|
||||||
|
|
||||||
//
|
//
|
||||||
export const a = [
|
export const a = [
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
import { Atrans$DialogRes } from '@/utils/page/config'
|
||||||
import { useDraggable } from 'vue-draggable-plus'
|
import { useDraggable } from 'vue-draggable-plus'
|
||||||
// 定义源数据的结构类型
|
// 定义源数据的结构类型
|
||||||
interface Option {
|
interface Option {
|
||||||
@ -15,7 +16,7 @@ interface Category {
|
|||||||
type CategoryDataMock = Category[]
|
type CategoryDataMock = Category[]
|
||||||
|
|
||||||
// 定义目标数据的结构类型
|
// 定义目标数据的结构类型
|
||||||
interface TSkuList {
|
export interface TSkuList {
|
||||||
serialNo: string
|
serialNo: string
|
||||||
name: string
|
name: string
|
||||||
salePrice: string
|
salePrice: string
|
||||||
@ -27,9 +28,9 @@ interface TSkuList {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 创建sku列表
|
// 创建sku列表
|
||||||
export const generateSkuList = (categoryData: CategoryDataMock): Ref<TSkuList[]> => {
|
export const generateSkuList = (adminCategoryData: CategoryDataMock): TSkuList[] => {
|
||||||
const result: TSkuList[] = []
|
const result: TSkuList[] = []
|
||||||
const optionGroups: Option[][] = categoryData.map((category) => category.vvPropertyValueList)
|
const optionGroups: Option[][] = adminCategoryData.map((category) => category.vvPropertyValueList)
|
||||||
|
|
||||||
// 使用递归生成所有可能的组合
|
// 使用递归生成所有可能的组合
|
||||||
const combine = (index: number, current: Option[]) => {
|
const combine = (index: number, current: Option[]) => {
|
||||||
@ -54,24 +55,29 @@ export const generateSkuList = (categoryData: CategoryDataMock): Ref<TSkuList[]>
|
|||||||
}
|
}
|
||||||
|
|
||||||
combine(0, [])
|
combine(0, [])
|
||||||
return ref(result)
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
// 增加属性、删除属性
|
// 增加属性、删除属性
|
||||||
export const usePropertyValue = (categoryData: CategoryDataMock) => {
|
export const usePropertyValue = () => {
|
||||||
const inputVisibles = ref(Array.from({ length: categoryData.length }, (_) => false))
|
let adminCategoryData: CategoryDataMock = []
|
||||||
|
const inputVisibles = ref<boolean[]>([])
|
||||||
|
const initPropertyData = (initData: CategoryDataMock) => {
|
||||||
|
inputVisibles.value = Array.from({ length: initData.length }, (_) => false)
|
||||||
|
adminCategoryData = initData
|
||||||
|
}
|
||||||
|
|
||||||
const InputRefs = ref()
|
const InputRefs = ref()
|
||||||
const inputValue = ref('')
|
const inputValue = ref('')
|
||||||
const onAddPropertyValue = (index: number) => {
|
const onAddPropertyValue = (index: number) => {
|
||||||
inputVisibles.value[index] = true
|
inputVisibles.value[index] = true
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
InputRefs.value[index].input!.focus()
|
InputRefs.value[0].input!.focus()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
const onClosePropertyValue = (index: number, id: number, skuList: Ref<TSkuList[]>) => {
|
const onClosePropertyValue = (index: number, id: number, skuList: Ref<TSkuList[]>) => {
|
||||||
const i = categoryData[index].vvPropertyValueList.findIndex((item: any) => item.id === id)
|
const i = adminCategoryData[index].vvPropertyValueList.findIndex((item: any) => item.id === id)
|
||||||
categoryData[index].vvPropertyValueList.splice(i, 1)
|
adminCategoryData[index].vvPropertyValueList.splice(i, 1)
|
||||||
const deleteIndexs: number[] = []
|
const deleteIndexs: number[] = []
|
||||||
skuList.value.forEach((item: TSkuList, skuIndex: number) => {
|
skuList.value.forEach((item: TSkuList, skuIndex: number) => {
|
||||||
if (item.vvSkuPropertyValueList.find((it) => it.id === id)) {
|
if (item.vvSkuPropertyValueList.find((it) => it.id === id)) {
|
||||||
@ -86,7 +92,7 @@ export const usePropertyValue = (categoryData: CategoryDataMock) => {
|
|||||||
const handleInputConfirm = (lineIndex: number, skuList: TSkuList[] = []) => {
|
const handleInputConfirm = (lineIndex: number, skuList: TSkuList[] = []) => {
|
||||||
if (inputValue.value) {
|
if (inputValue.value) {
|
||||||
const id = Math.random()
|
const id = Math.random()
|
||||||
categoryData[lineIndex].vvPropertyValueList.push({
|
adminCategoryData[lineIndex].vvPropertyValueList.push({
|
||||||
id,
|
id,
|
||||||
categoryPropertyValue: inputValue.value,
|
categoryPropertyValue: inputValue.value,
|
||||||
isAdd: true
|
isAdd: true
|
||||||
@ -95,7 +101,7 @@ export const usePropertyValue = (categoryData: CategoryDataMock) => {
|
|||||||
...generateAddSkuList(
|
...generateAddSkuList(
|
||||||
lineIndex,
|
lineIndex,
|
||||||
{ id, categoryPropertyValue: inputValue.value },
|
{ id, categoryPropertyValue: inputValue.value },
|
||||||
categoryData
|
adminCategoryData
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -107,16 +113,16 @@ export const usePropertyValue = (categoryData: CategoryDataMock) => {
|
|||||||
const generateAddSkuList = (
|
const generateAddSkuList = (
|
||||||
lineIndex: number,
|
lineIndex: number,
|
||||||
addData: Option,
|
addData: Option,
|
||||||
categoryData: CategoryDataMock
|
adminCategoryData: CategoryDataMock
|
||||||
): TSkuList[] => {
|
): TSkuList[] => {
|
||||||
const result: TSkuList[] = []
|
const result: TSkuList[] = []
|
||||||
const optionGroups: Option[][] = categoryData
|
const optionGroups: Option[][] = adminCategoryData
|
||||||
.filter((_, index) => index !== lineIndex)
|
.filter((_, index) => index !== lineIndex)
|
||||||
.map((category) => category.vvPropertyValueList)
|
.map((category) => category.vvPropertyValueList)
|
||||||
|
|
||||||
// 使用递归生成所有可能的组合
|
// 使用递归生成所有可能的组合
|
||||||
const combine = (index: number, current: Option[]) => {
|
const combine = (index: number, current: Option[]) => {
|
||||||
if (index === categoryData.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.categoryPropertyValue).join('-')
|
const name = current.map((opt) => opt.categoryPropertyValue).join('-')
|
||||||
result.push({
|
result.push({
|
||||||
@ -136,13 +142,16 @@ export const usePropertyValue = (categoryData: CategoryDataMock) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
combine(1, [addData])
|
combine(0, [addData])
|
||||||
|
//bug
|
||||||
|
console.warn('----- my data is result111: ', result)
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
inputVisibles,
|
inputVisibles,
|
||||||
InputRefs,
|
InputRefs,
|
||||||
inputValue,
|
inputValue,
|
||||||
|
initPropertyData,
|
||||||
onAddPropertyValue,
|
onAddPropertyValue,
|
||||||
onClosePropertyValue,
|
onClosePropertyValue,
|
||||||
handleInputConfirm
|
handleInputConfirm
|
||||||
@ -207,9 +216,63 @@ export const handleLoadNode2 = (node: any, resolve: any) => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export const checkedNodes = ref<{ admin: number[]; app: number[] }>({ admin: [], app: [] })
|
// 图片预览列表
|
||||||
export const handleCheckChange = (_: any, checkedStatus: any, type: 'admin' | 'app') => {
|
export const fileList = ref<PreviewItem[]>([])
|
||||||
|
// 选中后台类目和app类目,获取父子id
|
||||||
|
export const defaultCheckedNodes = ref<{ admin: number[]; app: number[] }>({ admin: [], app: [] })
|
||||||
|
export const handleCheckChange = (_: any, checkedStatus: any, type: 'admin' | 'app', data: any) => {
|
||||||
// checkedStatus: { checkedKeys, checkedNodes, halfCheckedKeys, halfCheckedNodes }
|
// checkedStatus: { checkedKeys, checkedNodes, halfCheckedKeys, halfCheckedNodes }
|
||||||
checkedNodes.value[type] = [...checkedStatus.halfCheckedKeys, ...checkedStatus.checkedKeys]
|
data[type + 'CategoryIds'] = [...checkedStatus.halfCheckedKeys, ...checkedStatus.checkedKeys]
|
||||||
console.warn('----- my data is checkedNodes: ', checkedNodes)
|
}
|
||||||
|
|
||||||
|
interface PreviewItem {
|
||||||
|
fileName: string
|
||||||
|
name: string
|
||||||
|
resourceUrl: string
|
||||||
|
type: 'image' | 'video'
|
||||||
|
}
|
||||||
|
|
||||||
|
// 编辑的时候从接口响应数据提取$dialog数据
|
||||||
|
export const handleGetDialogData = (
|
||||||
|
data: any,
|
||||||
|
$dialog: Ref<Atrans$DialogRes>,
|
||||||
|
fileList: Ref<PreviewItem[]>
|
||||||
|
) => {
|
||||||
|
const result = { ...$dialog.value.data }
|
||||||
|
result.appCategoryId = data.appCategoryId2
|
||||||
|
result.adminCategoryId = data.adminCategoryId
|
||||||
|
defaultCheckedNodes.value.admin = extractAdminCategoryIds(data)
|
||||||
|
defaultCheckedNodes.value.app = [data.appCategoryId1, data.appCategoryId2]
|
||||||
|
result.isTest = data.isTest
|
||||||
|
result.title = data.title
|
||||||
|
const files = [
|
||||||
|
{ fileName: '主图', name: '主图', resourceUrl: data.mainImageUrl, type: 'image' },
|
||||||
|
{ fileName: '视频', name: '视频', resourceUrl: data.videoUrl, type: 'video' }
|
||||||
|
]
|
||||||
|
files.push(
|
||||||
|
...data.vvProductDetailList
|
||||||
|
.filter((item: any) => item.type === 1)
|
||||||
|
.map((item: any) => ({
|
||||||
|
fileName: '副图',
|
||||||
|
name: '副图',
|
||||||
|
resourceUrl: item.resourceUrl,
|
||||||
|
type: 'image'
|
||||||
|
}))
|
||||||
|
)
|
||||||
|
fileList.value = files as PreviewItem[]
|
||||||
|
$dialog.value.data = result
|
||||||
|
}
|
||||||
|
|
||||||
|
// 将adminCategoryId1, adminCategoryId2, ... 提取出来并排序
|
||||||
|
function extractAdminCategoryIds(obj: Record<string, any>): number[] {
|
||||||
|
return Object.entries(obj)
|
||||||
|
.filter(([key]) => key.startsWith('adminCategoryId'))
|
||||||
|
.sort(([keyA], [keyB]) => {
|
||||||
|
// 按数字部分排序 (adminCategoryId1 < adminCategoryId2)
|
||||||
|
const numA = parseInt(keyA.replace('adminCategoryId', ''))
|
||||||
|
const numB = parseInt(keyB.replace('adminCategoryId', ''))
|
||||||
|
return numA - numB
|
||||||
|
})
|
||||||
|
.map(([, value]) => value)
|
||||||
|
.filter((val) => ![undefined, null].includes(val)) as number[]
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user