feat: app类目完成+商品编辑后台类目自测
This commit is contained in:
parent
5c8b7bcccf
commit
163030aef1
@ -31,7 +31,9 @@ const login = {
|
|||||||
*/
|
*/
|
||||||
getCommodityList: ['/product/list'], // 获取商品列表
|
getCommodityList: ['/product/list'], // 获取商品列表
|
||||||
getCommodityDetail: ['/product/detail'], // 获取商品详情
|
getCommodityDetail: ['/product/detail'], // 获取商品详情
|
||||||
addOrUpdateCommodity: ['/product/insertOrUpadate'] // 修改商品详情
|
addOrUpdateCommodity: ['/product/insertOrUpadate'], // 修改商品详情
|
||||||
|
changeCommodityInfo: ['/product/onlyUpdateProduct'], // 修改商品信息(列表页)
|
||||||
|
copyCommodity: ['/product/copy'] // 复制商品
|
||||||
}
|
}
|
||||||
|
|
||||||
export default login
|
export default login
|
||||||
|
|||||||
@ -73,7 +73,7 @@
|
|||||||
import { ElMessage } from 'element-plus'
|
import { ElMessage } from 'element-plus'
|
||||||
import { Folder } from '@element-plus/icons-vue'
|
import { Folder } from '@element-plus/icons-vue'
|
||||||
|
|
||||||
interface FileItem {
|
export interface FileItem {
|
||||||
id: number
|
id: number
|
||||||
fileName: string
|
fileName: string
|
||||||
type: 'file' | 'image' | 'video'
|
type: 'file' | 'image' | 'video'
|
||||||
|
|||||||
@ -1,7 +1,12 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="resource-upload">
|
<div class="resource-upload">
|
||||||
<div class="resource-upload__wrapper">
|
<div class="resource-upload__wrapper">
|
||||||
<el-button type="primary" :size="size" class="relative !text-white">
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
:link="isLink"
|
||||||
|
:size="size"
|
||||||
|
:class="['relative', { '!text-white': !isLink }]"
|
||||||
|
>
|
||||||
{{ buttonText }}
|
{{ buttonText }}
|
||||||
<input
|
<input
|
||||||
ref="inputRef"
|
ref="inputRef"
|
||||||
@ -20,6 +25,7 @@
|
|||||||
interface Props {
|
interface Props {
|
||||||
/** 是否允许多选文件 */
|
/** 是否允许多选文件 */
|
||||||
multiple?: boolean
|
multiple?: boolean
|
||||||
|
isLink?: boolean
|
||||||
size?: 'small' | 'default'
|
size?: 'small' | 'default'
|
||||||
/** 接受的文件类型 */
|
/** 接受的文件类型 */
|
||||||
accept?: 'image/*,video/*' | 'image/*' | 'video/*'
|
accept?: 'image/*,video/*' | 'image/*' | 'video/*'
|
||||||
@ -27,15 +33,22 @@ interface Props {
|
|||||||
buttonText?: string
|
buttonText?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface FileItem {
|
||||||
|
fileName: string
|
||||||
|
resourceUrl: string
|
||||||
|
type: 'image' | 'video'
|
||||||
|
}
|
||||||
|
|
||||||
withDefaults(defineProps<Props>(), {
|
withDefaults(defineProps<Props>(), {
|
||||||
multiple: false,
|
multiple: false,
|
||||||
accept: 'image/*,video/*',
|
accept: 'image/*,video/*',
|
||||||
buttonText: '选择文件',
|
buttonText: '选择文件',
|
||||||
|
isLink: false,
|
||||||
size: 'default'
|
size: 'default'
|
||||||
})
|
})
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(e: 'change', files: File[]): void
|
(e: 'change', files: FileItem[]): void
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const inputRef = ref<HTMLInputElement | null>(null)
|
const inputRef = ref<HTMLInputElement | null>(null)
|
||||||
|
|||||||
@ -11,7 +11,7 @@ const useAppStore = defineStore({
|
|||||||
state: (): AppState => ({
|
state: (): AppState => ({
|
||||||
device: 'desktop',
|
device: 'desktop',
|
||||||
sidebar: {
|
sidebar: {
|
||||||
opened: sidebarStatus ? sidebarStatus : true,
|
opened: sidebarStatus,
|
||||||
withoutAnimation: false
|
withoutAnimation: false
|
||||||
},
|
},
|
||||||
size: localStorage.getItem('size') || 'default'
|
size: localStorage.getItem('size') || 'default'
|
||||||
|
|||||||
@ -1,9 +1,26 @@
|
|||||||
<template>
|
<template>
|
||||||
<div id="category-tree" class="p-2 bg-white">
|
<div id="category-tree" class="p-2 bg-white">
|
||||||
<p>类目展示:</p>
|
<p>
|
||||||
|
app类目展示:
|
||||||
|
<el-input
|
||||||
|
v-if="addRootCategory.showInput"
|
||||||
|
class="w-20 !h-[22px]"
|
||||||
|
v-model="addRootCategory.inputValue"
|
||||||
|
ref="addRootCategoryInputRef"
|
||||||
|
@keyup.enter="onAddRootCategory"
|
||||||
|
@blur="addRootCategory.showInput = false"
|
||||||
|
></el-input>
|
||||||
|
<el-button
|
||||||
|
v-else
|
||||||
|
class="w-20 !h-[22px]"
|
||||||
|
type="primary"
|
||||||
|
size="small"
|
||||||
|
@click="onClickAddRootCategory"
|
||||||
|
>添加根类目</el-button
|
||||||
|
>
|
||||||
|
</p>
|
||||||
<el-tree
|
<el-tree
|
||||||
ref="treeRef"
|
ref="treeRef"
|
||||||
style="max-width: 600px"
|
|
||||||
:props="defaultProps"
|
:props="defaultProps"
|
||||||
node-key="id"
|
node-key="id"
|
||||||
draggable
|
draggable
|
||||||
@ -13,115 +30,98 @@
|
|||||||
lazy
|
lazy
|
||||||
highlight-current
|
highlight-current
|
||||||
:expand-on-click-node="false"
|
:expand-on-click-node="false"
|
||||||
@node-click="handleNodeClick"
|
|
||||||
@node-drag-start="handleDragStart"
|
@node-drag-start="handleDragStart"
|
||||||
@node-drop="handleDropFinish"
|
@node-drop="handleDropFinish"
|
||||||
>
|
>
|
||||||
<template #default="{ node, data }">
|
<template #default="{ node, data }">
|
||||||
<div class="category-tree-node">
|
<div class="category-tree-node">
|
||||||
<span v-if="curId !== data.id">{{ data.name }}</span>
|
|
||||||
<el-input
|
|
||||||
ref="inputRef"
|
|
||||||
v-else
|
|
||||||
v-model="data.label2"
|
|
||||||
size="small"
|
|
||||||
class="w-40"
|
|
||||||
@keyup.enter="handleInputConfirm(data)"
|
|
||||||
@blur="treeRef.remove(node)"
|
|
||||||
/>
|
|
||||||
<div>
|
<div>
|
||||||
<el-button type="primary" link @click="onEdit(data)" size="small">编辑 </el-button>
|
<img :src="data.imageUrl" alt="" class="w-5 h-5" />
|
||||||
<el-button type="primary" link @click="append(data)" size="small"> 添加 </el-button>
|
<span v-if="curEditId !== data.id">{{ data.name }}</span>
|
||||||
|
<el-input
|
||||||
|
ref="editInputRef"
|
||||||
|
v-else
|
||||||
|
v-model="data.label2"
|
||||||
|
size="small"
|
||||||
|
class="w-40"
|
||||||
|
@keyup.enter="handleEditInputConfirm(node, data)"
|
||||||
|
@blur="curEditId = NaN"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<el-button type="primary" link @click="onEdit(node, data)" size="small"
|
||||||
|
>编辑
|
||||||
|
</el-button>
|
||||||
|
<el-input
|
||||||
|
ref="addInputRef"
|
||||||
|
class="w-20"
|
||||||
|
size="small"
|
||||||
|
v-if="data.id === curAddAppCategoryId"
|
||||||
|
v-model="addInputValue"
|
||||||
|
@keyup.enter="onAddInputConfirm(node, data)"
|
||||||
|
@blur="curAddAppCategoryId = NaN"
|
||||||
|
></el-input>
|
||||||
|
<el-button
|
||||||
|
v-else
|
||||||
|
type="warning"
|
||||||
|
link
|
||||||
|
@click="onAppendChildBtn(node, data)"
|
||||||
|
size="small"
|
||||||
|
>
|
||||||
|
添加子类目
|
||||||
|
</el-button>
|
||||||
|
<file-upload-btn
|
||||||
|
class="inline-block"
|
||||||
|
isLink
|
||||||
|
size="small"
|
||||||
|
accept="image/*"
|
||||||
|
@click="curFileData = data"
|
||||||
|
@change="(val) => handleChooseResourceFileCallback(val, curFileData)"
|
||||||
|
/>
|
||||||
|
<el-button
|
||||||
|
type="success"
|
||||||
|
link
|
||||||
|
size="small"
|
||||||
|
class="ml-2"
|
||||||
|
@click="onClickChooseResourceBtn(data)"
|
||||||
|
>资源库导入</el-button
|
||||||
|
>
|
||||||
<el-button type="danger" size="small" link @click="onDelete(node)"> 删除 </el-button>
|
<el-button type="danger" size="small" link @click="onDelete(node)"> 删除 </el-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-tree>
|
</el-tree>
|
||||||
|
<FileExplorerDialog
|
||||||
|
v-model="showFileExplorer"
|
||||||
|
v-model:initPathArray="currentPathArray"
|
||||||
|
@select="(files: FileItem[]) => handleChooseResourceFileCallback(files, curFileData)"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
import FileExplorerDialog, { FileItem } from '@/components/FileExplorerDialog/index.vue'
|
||||||
|
import fileUploadBtn from '@/components/FileUploadBtn/index.vue'
|
||||||
import { ElButton, ElMessage } from 'element-plus'
|
import { ElButton, ElMessage } from 'element-plus'
|
||||||
import type { RenderContentContext } from 'element-plus'
|
|
||||||
import { handleDragStart, handleDropFinish } from './use-drag'
|
import { handleDragStart, handleDropFinish } from './use-drag'
|
||||||
|
import {
|
||||||
interface Tree {
|
treeRef,
|
||||||
id: number
|
onEdit,
|
||||||
name: string
|
onAddInputConfirm,
|
||||||
children?: Tree[]
|
handleEditInputConfirm,
|
||||||
}
|
curEditId,
|
||||||
type Node = RenderContentContext['node']
|
curAddAppCategoryId,
|
||||||
type Data = RenderContentContext['data']
|
editInputRef,
|
||||||
|
addInputRef,
|
||||||
const curId = ref(NaN)
|
addInputValue,
|
||||||
const curParentId = ref(NaN)
|
onAppendChildBtn,
|
||||||
const inputRef = ref()
|
onDelete,
|
||||||
const treeRef = ref()
|
addRootCategory,
|
||||||
|
addRootCategoryInputRef,
|
||||||
// 编辑类目名称
|
onClickAddRootCategory,
|
||||||
const onEdit = (data: Data) => {
|
onAddRootCategory,
|
||||||
data.label2 = data.name
|
Data
|
||||||
curId.value = data.id
|
} from './init-method'
|
||||||
nextTick(() => {
|
|
||||||
inputRef.value.focus()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 回车确认
|
|
||||||
const handleInputConfirm = async (data: any) => {
|
|
||||||
if (curId.value === Infinity) {
|
|
||||||
await api.commodity.updateAppCategory.post!({
|
|
||||||
...data,
|
|
||||||
name: data.label2,
|
|
||||||
parentId: curParentId.value
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
await api.commodity.updateAppCategory.post!({ ...data, name: data.label2 })
|
|
||||||
}
|
|
||||||
ElMessage.success('更新成功')
|
|
||||||
data.name = data.label2
|
|
||||||
data.label2 = ''
|
|
||||||
curId.value = NaN
|
|
||||||
}
|
|
||||||
|
|
||||||
// 增加类目
|
|
||||||
const append = async (data: Data) => {
|
|
||||||
const node = treeRef.value.getNode(data.id)
|
|
||||||
curId.value = Infinity
|
|
||||||
curParentId.value = data.id
|
|
||||||
const newChild = { id: curId.value, name: '', label2: 'test', hasChild: false }
|
|
||||||
if (!node.expanded) {
|
|
||||||
await api.commodity.getAppCategoryList.post!<any>({ parentId: data.id || 0 }).then((res) => {
|
|
||||||
res.data.forEach((item: any) => {
|
|
||||||
treeRef.value.append(
|
|
||||||
{
|
|
||||||
...item,
|
|
||||||
children: item.hasChild ? [] : undefined
|
|
||||||
},
|
|
||||||
data
|
|
||||||
)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
treeRef.value.append(newChild, data)
|
|
||||||
node.expanded = true
|
|
||||||
nextTick(() => {
|
|
||||||
const timer = setTimeout(() => {
|
|
||||||
clearTimeout(timer)
|
|
||||||
inputRef.value.focus()
|
|
||||||
}, 500)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 删除类目
|
|
||||||
const onDelete = async (node: Node) => {
|
|
||||||
await api.commodity.updateAppCategory.post!({
|
|
||||||
id: node.data.id,
|
|
||||||
isDelete: 1
|
|
||||||
})
|
|
||||||
treeRef.value.remove(node)
|
|
||||||
ElMessage.success('删除成功')
|
|
||||||
}
|
|
||||||
|
|
||||||
const defaultProps = {
|
const defaultProps = {
|
||||||
label: 'name',
|
label: 'name',
|
||||||
@ -144,9 +144,16 @@ const handleLoadNode = (node, resolve) => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 点击类目
|
// 选择资源库文件按钮
|
||||||
const handleNodeClick = (node: Node, data: Data) => {
|
const curFileData = ref({})
|
||||||
console.log('click', node, data)
|
const currentPathArray = ref<{ name: string; id: number }[]>([{ name: '根目录', id: 0 }])
|
||||||
|
const showFileExplorer = ref(false)
|
||||||
|
const onClickChooseResourceBtn = (data: Data) => {
|
||||||
|
curFileData.value = data
|
||||||
|
showFileExplorer.value = true
|
||||||
|
}
|
||||||
|
const handleChooseResourceFileCallback = (files: FileItem[], curFileData: Data) => {
|
||||||
|
curFileData.imageUrl = files[0].resourceUrl
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
97
src/views/goods/appCategory/init-method.ts
Normal file
97
src/views/goods/appCategory/init-method.ts
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
import { ElMessage, type RenderContentContext } from 'element-plus'
|
||||||
|
|
||||||
|
export type Node = RenderContentContext['node']
|
||||||
|
export type Data = RenderContentContext['data']
|
||||||
|
|
||||||
|
export const curEditId = ref(NaN)
|
||||||
|
export const editInputRef = ref()
|
||||||
|
export const treeRef = ref()
|
||||||
|
|
||||||
|
// 编辑类目名称
|
||||||
|
export const onEdit = (node: Node, data: Data) => {
|
||||||
|
data.label2 = data.name
|
||||||
|
curEditId.value = data.id
|
||||||
|
nextTick(() => {
|
||||||
|
editInputRef.value.focus()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 编辑类目回车确认
|
||||||
|
export const handleEditInputConfirm = async (node: Node, data: Data) => {
|
||||||
|
if (data.label2) {
|
||||||
|
await api.commodity.updateAppCategory.post!({ ...data, name: data.label2 })
|
||||||
|
ElMessage.success('更新成功')
|
||||||
|
data.name = data.label2
|
||||||
|
data.label2 = ''
|
||||||
|
curEditId.value = NaN
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const curAddAppCategoryId = ref(NaN)
|
||||||
|
export const addInputRef = ref()
|
||||||
|
export const addInputValue = ref('')
|
||||||
|
|
||||||
|
// 增加子类目按钮
|
||||||
|
export const onAppendChildBtn = async (node: Node, data: Data) => {
|
||||||
|
curAddAppCategoryId.value = data.id
|
||||||
|
nextTick(() => {
|
||||||
|
addInputRef.value.focus()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 增加子类目回车确认
|
||||||
|
export const onAddInputConfirm = async (node: Node, data: Data) => {
|
||||||
|
if (addInputValue.value) {
|
||||||
|
await api.commodity.updateAppCategory.post!({
|
||||||
|
parentId: data.id,
|
||||||
|
name: addInputValue.value
|
||||||
|
})
|
||||||
|
ElMessage.success('添加成功')
|
||||||
|
addInputValue.value = ''
|
||||||
|
curAddAppCategoryId.value = NaN
|
||||||
|
node.loaded = false
|
||||||
|
node.expand()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除类目
|
||||||
|
export const onDelete = async (node: Node) => {
|
||||||
|
handleMessageBox({
|
||||||
|
msg: `是否删除类目?`,
|
||||||
|
success: api.commodity.updateAppCategory.post!,
|
||||||
|
data: { id: node.data.id, isDelete: 1 }
|
||||||
|
}).then(() => {
|
||||||
|
treeRef.value.remove(node)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根类目相关
|
||||||
|
*/
|
||||||
|
export const addRootCategory = reactive({ showInput: false, inputValue: '' })
|
||||||
|
export const addRootCategoryInputRef = ref()
|
||||||
|
|
||||||
|
// 点击添加根类目按钮
|
||||||
|
export const onClickAddRootCategory = () => {
|
||||||
|
addRootCategory.showInput = true
|
||||||
|
nextTick(() => {
|
||||||
|
addRootCategoryInputRef.value.input!.focus()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// 添加根类目回车确定
|
||||||
|
export const onAddRootCategory = async () => {
|
||||||
|
const newRoot = { parentId: 0, name: addRootCategory.inputValue }
|
||||||
|
const res = await api.commodity.updateAppCategory.post!<{ id: number }>(newRoot)
|
||||||
|
treeRef.value.insertAfter(
|
||||||
|
{
|
||||||
|
...newRoot,
|
||||||
|
children: [],
|
||||||
|
id: res.data.id,
|
||||||
|
hasChild: 0
|
||||||
|
},
|
||||||
|
treeRef.value.store.root.childNodes.slice(-1)[0]
|
||||||
|
)
|
||||||
|
addRootCategory.showInput = false
|
||||||
|
addRootCategory.inputValue = ''
|
||||||
|
ElMessage.success('添加成功')
|
||||||
|
}
|
||||||
@ -18,7 +18,7 @@ export const handleDropFinish = (draggingNode: Node, dropNode: Node, dropType: N
|
|||||||
// 获取拖拽到的位置索引
|
// 获取拖拽到的位置索引
|
||||||
const sortIds = getSortIds()
|
const sortIds = getSortIds()
|
||||||
if (!sortIds.length) return
|
if (!sortIds.length) return
|
||||||
api.commodity.sortCategory.post!({ categoryIds: sortIds }).then(() => {
|
api.commodity.sortAppCategory.post!({ categoryIds: sortIds }).then(() => {
|
||||||
console.log('tree drop:', draggingNode, dropNode.label, dropType)
|
console.log('tree drop:', draggingNode, dropNode.label, dropType)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@ -50,10 +50,12 @@ export const handleAddChildCategoryConfirm = async (node: Node, data: any) => {
|
|||||||
|
|
||||||
// 编辑类目回车确认
|
// 编辑类目回车确认
|
||||||
export const handleEditChildCategoryConfirm = async (node: Node, data: any) => {
|
export const handleEditChildCategoryConfirm = async (node: Node, data: any) => {
|
||||||
await api.commodity.updateCategory.post!({ ...data, name: data.label2 })
|
if (data.label2) {
|
||||||
ElMessage.success('更新成功')
|
await api.commodity.updateCategory.post!({ ...data, name: data.label2 })
|
||||||
data.name = data.label2
|
ElMessage.success('更新成功')
|
||||||
editChildCategoryId.value = NaN
|
data.name = data.label2
|
||||||
|
editChildCategoryId.value = NaN
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 删除类目
|
// 删除类目
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="max-w-1/2 sku-config">
|
<div class="max-w-1/2 sku-config">
|
||||||
<dl v-for="item in list" :key="item.typeId" class="flex mb-1 items-center">
|
<dl v-for="(item, index) in list" :key="item.typeId" class="flex mb-1 items-center">
|
||||||
|
<span class="text-sm text-[#666] mr-1">{{ (startIndex || 0) + index + 1 }}</span>
|
||||||
<dt class="flex items-center">
|
<dt class="flex items-center">
|
||||||
<el-upload
|
<el-upload
|
||||||
ref="uploadRef"
|
ref="uploadRef"
|
||||||
@ -46,6 +47,7 @@ import { Plus } from '@element-plus/icons-vue'
|
|||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
list: any[]
|
list: any[]
|
||||||
|
startIndex?: number
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
|||||||
@ -85,13 +85,19 @@ export const handleGetNewAdminCategoryData = (data: any) => {
|
|||||||
|
|
||||||
// 编辑的时候对sku进行重组
|
// 编辑的时候对sku进行重组
|
||||||
export const handleGetNewSkuList = (data: any) => {
|
export const handleGetNewSkuList = (data: any) => {
|
||||||
return data.map((item: any) => ({
|
return data.map((item: any) => {
|
||||||
...item,
|
let categoryPropertyNames = ''
|
||||||
name: item.vvSkuPropertyValueList.reduce((str: string, cur: any, index: number) => {
|
let name = ''
|
||||||
cur.categoryPropertyName = cur.productPropertyName
|
item.vvSkuPropertyValueList.forEach((child: any, index: number) => {
|
||||||
cur.categoryPropertyValue = cur.productPropertyValue
|
child.categoryPropertyName = child.productPropertyName
|
||||||
str += index === 0 ? cur.productPropertyValue : '-' + cur.productPropertyValue
|
child.categoryPropertyValue = child.productPropertyValue
|
||||||
return str
|
categoryPropertyNames += (index === 0 ? '' : '-') + child.categoryPropertyName
|
||||||
}, '')
|
name += (index === 0 ? '' : '-') + child.categoryPropertyValue
|
||||||
}))
|
})
|
||||||
|
return {
|
||||||
|
...item,
|
||||||
|
name,
|
||||||
|
categoryPropertyNames
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@ -182,7 +182,12 @@
|
|||||||
type="danger"
|
type="danger"
|
||||||
class="button-new-tag ml-1 !text-white"
|
class="button-new-tag ml-1 !text-white"
|
||||||
size="small"
|
size="small"
|
||||||
@click="onDeletePropertyTypeBtn(index, adminCategoryData, skuList)"
|
@click="
|
||||||
|
() => {
|
||||||
|
onDeletePropertyTypeBtn(index, adminCategoryData, skuList)
|
||||||
|
skuList = generateSkuList(adminCategoryData)
|
||||||
|
}
|
||||||
|
"
|
||||||
>
|
>
|
||||||
删除属性
|
删除属性
|
||||||
</el-button>
|
</el-button>
|
||||||
@ -196,7 +201,10 @@
|
|||||||
style="border: 1px dashed #bbb"
|
style="border: 1px dashed #bbb"
|
||||||
>
|
>
|
||||||
<category-config :list="skuList.slice(0, Math.floor(skuList.length / 2))" />
|
<category-config :list="skuList.slice(0, Math.floor(skuList.length / 2))" />
|
||||||
<category-config :list="skuList.slice(Math.floor(skuList.length / 2))" />
|
<category-config
|
||||||
|
:startIndex="Math.floor(skuList.length / 2)"
|
||||||
|
:list="skuList.slice(Math.floor(skuList.length / 2))"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</el-card>
|
</el-card>
|
||||||
<el-card>
|
<el-card>
|
||||||
|
|||||||
@ -15,7 +15,6 @@ export const handleEditPropertyTypeConfirm = async (item: any) => {
|
|||||||
|
|
||||||
export const onDeletePropertyTypeBtn = (index: number, adminCategoryData: any, skuList: any) => {
|
export const onDeletePropertyTypeBtn = (index: number, adminCategoryData: any, skuList: any) => {
|
||||||
adminCategoryData.splice(index, 1)
|
adminCategoryData.splice(index, 1)
|
||||||
skuList.length = 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const curPropertyValueId = ref('')
|
export const curPropertyValueId = ref('')
|
||||||
@ -31,7 +30,44 @@ export const onClickPropertyValue = (item: any, child: any) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const onEditPropertyValue = (child: any, skuList: any) => {
|
export const onEditPropertyValue = (child: any, skuList: any) => {
|
||||||
|
const oldCategoryPropertyValue = child.categoryPropertyValue
|
||||||
child.categoryPropertyValue = inputEditPropertyValue.value
|
child.categoryPropertyValue = inputEditPropertyValue.value
|
||||||
|
handleEditSkuListPropertyValue(
|
||||||
|
child.categoryPropertyName,
|
||||||
|
oldCategoryPropertyValue,
|
||||||
|
skuList,
|
||||||
|
inputEditPropertyValue.value
|
||||||
|
)
|
||||||
curPropertyValueId.value = ''
|
curPropertyValueId.value = ''
|
||||||
inputEditPropertyValue.value = ''
|
inputEditPropertyValue.value = ''
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 修改skuList中的属性值名称
|
||||||
|
const handleEditSkuListPropertyValue = (
|
||||||
|
categoryPropertyName: string,
|
||||||
|
oldCategoryPropertyValue: string,
|
||||||
|
skuList: any,
|
||||||
|
inputEditPropertyValue: string
|
||||||
|
) => {
|
||||||
|
const newPropertyValue = inputEditPropertyValue
|
||||||
|
skuList.forEach((item: any) => {
|
||||||
|
const index = (item.categoryPropertyNames || '')
|
||||||
|
.split('-')
|
||||||
|
.findIndex((item: string) => item === categoryPropertyName)
|
||||||
|
if (index !== -1) {
|
||||||
|
const names = (item.name || '').split('-')
|
||||||
|
if (names[index] === oldCategoryPropertyValue) {
|
||||||
|
names[index] = newPropertyValue
|
||||||
|
item.name = names.join('-')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
item.vvSkuPropertyValueList.forEach((item: any) => {
|
||||||
|
if (
|
||||||
|
item.categoryPropertyName === categoryPropertyName &&
|
||||||
|
item.categoryPropertyValue === oldCategoryPropertyValue
|
||||||
|
) {
|
||||||
|
item.categoryPropertyValue = newPropertyValue
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
@ -19,6 +19,7 @@ type CategoryDataMock = Category[]
|
|||||||
export interface TSkuList {
|
export interface TSkuList {
|
||||||
serialNo: string
|
serialNo: string
|
||||||
name: string
|
name: string
|
||||||
|
categoryPropertyNames: string
|
||||||
salePrice: string
|
salePrice: string
|
||||||
imageUrl: string
|
imageUrl: string
|
||||||
stock: number
|
stock: number
|
||||||
@ -40,9 +41,11 @@ export const generateSkuList = (adminCategoryData: CategoryDataMock): TSkuList[]
|
|||||||
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.categoryPropertyValue).join('-')
|
const name = current.map((opt) => opt.categoryPropertyValue).join('-')
|
||||||
|
const categoryPropertyNames = current.map((opt) => opt.categoryPropertyName).join('-')
|
||||||
result.push({
|
result.push({
|
||||||
serialNo,
|
serialNo,
|
||||||
name,
|
name,
|
||||||
|
categoryPropertyNames,
|
||||||
salePrice: '',
|
salePrice: '',
|
||||||
stock: 0,
|
stock: 0,
|
||||||
originPrice: 0,
|
originPrice: 0,
|
||||||
@ -116,8 +119,9 @@ export const usePropertyValue = () => {
|
|||||||
item.name += '-' + inputValue.value
|
item.name += '-' + inputValue.value
|
||||||
item.vvSkuPropertyValueList.push({ ...newData })
|
item.vvSkuPropertyValueList.push({ ...newData })
|
||||||
})
|
})
|
||||||
|
} else {
|
||||||
|
skuList.push(...generateAddSkuList(lineIndex, { ...newData }, adminCategoryData))
|
||||||
}
|
}
|
||||||
skuList.push(...generateAddSkuList(lineIndex, { ...newData }, adminCategoryData))
|
|
||||||
}
|
}
|
||||||
inputVisibles.value[lineIndex] = false
|
inputVisibles.value[lineIndex] = false
|
||||||
inputValue.value = ''
|
inputValue.value = ''
|
||||||
@ -130,18 +134,23 @@ export const usePropertyValue = () => {
|
|||||||
adminCategoryData: CategoryDataMock
|
adminCategoryData: CategoryDataMock
|
||||||
): TSkuList[] => {
|
): TSkuList[] => {
|
||||||
const result: TSkuList[] = []
|
const result: TSkuList[] = []
|
||||||
const optionGroups: Option[][] = adminCategoryData
|
const optionGroups: Option[][] = adminCategoryData.map((category, i) => {
|
||||||
.filter((_, index) => index !== lineIndex)
|
if (i === lineIndex) {
|
||||||
.map((category) => category.vvPropertyValueList)
|
return category.vvPropertyValueList.filter((item) => item.id === addData.id)
|
||||||
|
}
|
||||||
|
return 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.categoryPropertyValue).join('-')
|
const name = current.map((opt) => opt.categoryPropertyValue).join('-')
|
||||||
|
const categoryPropertyNames = current.map((opt) => opt.categoryPropertyName).join('-')
|
||||||
result.push({
|
result.push({
|
||||||
serialNo,
|
serialNo,
|
||||||
name,
|
name,
|
||||||
|
categoryPropertyNames,
|
||||||
salePrice: '',
|
salePrice: '',
|
||||||
stock: 0,
|
stock: 0,
|
||||||
originPrice: 0,
|
originPrice: 0,
|
||||||
@ -156,7 +165,7 @@ export const usePropertyValue = () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
combine(0, [addData])
|
combine(0, [])
|
||||||
//bug
|
//bug
|
||||||
console.warn('----- my data is result111: ', result)
|
console.warn('----- my data is result111: ', result)
|
||||||
return result
|
return result
|
||||||
|
|||||||
@ -21,6 +21,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
import { ElMessage } from 'element-plus'
|
||||||
import { initConfig } from './config'
|
import { initConfig } from './config'
|
||||||
import { useCommodityType } from './use-method'
|
import { useCommodityType } from './use-method'
|
||||||
|
|
||||||
@ -35,13 +36,17 @@ const onAddOrEdit = (type: string, row: any) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** 复制 */
|
/** 复制 */
|
||||||
const onCopy = (row: any) => {}
|
const onCopy = async (row: any) => {
|
||||||
|
await api.commodity.copyCommodity.post!({ productId: row.id })
|
||||||
|
ElMessage.success('复制成功')
|
||||||
|
table.value.$onGetData(table.value)
|
||||||
|
}
|
||||||
|
|
||||||
// 加入首页
|
// 加入首页
|
||||||
const onAddHome = (row: any) => {
|
const onAddHome = (row: any) => {
|
||||||
handleMessageBox({
|
handleMessageBox({
|
||||||
msg: `是否加入首页?`,
|
msg: `是否加入首页?`,
|
||||||
success: api.commodity.addOrUpdateCommodity.post!,
|
success: api.commodity.changeCommodityInfo.post!,
|
||||||
data: { id: row.id, frontPage: 1 }
|
data: { id: row.id, frontPage: 1 }
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
table.value.$onGetData(table.value)
|
table.value.$onGetData(table.value)
|
||||||
@ -52,8 +57,8 @@ const onAddHome = (row: any) => {
|
|||||||
const onDelete = (row: any) => {
|
const onDelete = (row: any) => {
|
||||||
handleMessageBox({
|
handleMessageBox({
|
||||||
msg: `是否确认删除吗?`,
|
msg: `是否确认删除吗?`,
|
||||||
success: api.commodity.addOrUpdateCommodity.post!,
|
success: api.commodity.changeCommodityInfo.post!,
|
||||||
data: { id: row.id, status: 'delete' }
|
data: { id: row.id, isDelete: 1 }
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
table.value.$onGetData(table.value)
|
table.value.$onGetData(table.value)
|
||||||
})
|
})
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user