feat: 商品管理+首页商品合并
This commit is contained in:
parent
701c093695
commit
954a9d49f0
@ -16,7 +16,7 @@ export default [
|
||||
modifyTime: '2024-07-15 15:45:58',
|
||||
tag: null,
|
||||
childList: [
|
||||
{
|
||||
/* {
|
||||
id: 38,
|
||||
resourceName: '首页商品',
|
||||
resourceType: 1,
|
||||
@ -33,7 +33,7 @@ export default [
|
||||
modifyTime: '2024-06-19 17:56:01',
|
||||
tag: null,
|
||||
childList: []
|
||||
},
|
||||
}, */
|
||||
{
|
||||
id: 39,
|
||||
resourceName: '商品管理',
|
||||
|
||||
@ -152,8 +152,13 @@ const onClickChooseResourceBtn = (data: Data) => {
|
||||
curFileData.value = data
|
||||
showFileExplorer.value = true
|
||||
}
|
||||
const handleChooseResourceFileCallback = (files: FileItem[], curFileData: Data) => {
|
||||
curFileData.imageUrl = files[0].resourceUrl
|
||||
const handleChooseResourceFileCallback = async (files: FileItem[], curFileData: Data) => {
|
||||
const imgUrl = files[0].resourceUrl
|
||||
await api.commodity.updateAppCategory.post!({
|
||||
id: curFileData.id,
|
||||
imageUrl: imgUrl
|
||||
})
|
||||
curFileData.imageUrl = imgUrl
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@ -19,9 +19,9 @@ export const initConfig = () => {
|
||||
isNew: { label: '新品', slot: 'isNew' },
|
||||
isFlash: { label: '限时秒杀', slot: 'isFlash' },
|
||||
btn: {
|
||||
types: ['primary', 'info', 'warning', 'success', 'danger'],
|
||||
names: ['编辑', '复制', '加入首页', '上下架', '删除'],
|
||||
width: 230
|
||||
types: ['primary', 'info', 'danger'],
|
||||
names: ['编辑', '复制', '删除'],
|
||||
width: 150
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
<Editor
|
||||
style="height: 500px; overflow-y: hidden"
|
||||
v-model="model"
|
||||
:defaultConfig="{ placeholder: '请输入内容...' }"
|
||||
:defaultConfig="editorConfig"
|
||||
mode="default"
|
||||
@onCreated="
|
||||
(editor: any) => {
|
||||
@ -23,15 +23,44 @@
|
||||
<script setup lang="ts">
|
||||
import '@wangeditor/editor/dist/css/style.css'
|
||||
import { Editor, Toolbar } from '@wangeditor/editor-for-vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
|
||||
const model = defineModel()
|
||||
|
||||
// 模拟 ajax 异步获取内容
|
||||
/* onMounted(() => {
|
||||
setTimeout(() => {
|
||||
// model.value = '<p>模拟 Ajax 异步设置内容</p>'
|
||||
}, 1500)
|
||||
}) */
|
||||
// 编辑器配置
|
||||
const editorConfig = {
|
||||
placeholder: '请输入内容...',
|
||||
MENU_CONF: {
|
||||
uploadImage: {
|
||||
// 自定义上传
|
||||
async customUpload(file: File, insertFn: (url: string, alt: string, href: string) => void) {
|
||||
try {
|
||||
// 创建 FormData
|
||||
const form = new FormData()
|
||||
form.append('files', file)
|
||||
|
||||
// 调用上传接口
|
||||
const res = await api.resource.uploadFile.post!<any>(form)
|
||||
|
||||
// 获取图片 URL
|
||||
const imageUrl = res.data[0]?.url
|
||||
if (imageUrl) {
|
||||
// 插入图片到编辑器
|
||||
insertFn(imageUrl, file.name, imageUrl)
|
||||
} else {
|
||||
ElMessage.error('图片上传失败')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('图片上传失败:', error)
|
||||
ElMessage.error('图片上传失败')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 工具栏配置
|
||||
const toolbarConfig = {}
|
||||
|
||||
// 编辑器实例,必须用 shallowRef
|
||||
const editorRef = shallowRef()
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div>
|
||||
<search-module :search="search" :table="table">
|
||||
<search-module :search="search" :table="table" @search="onSearch">
|
||||
<template #btn>
|
||||
<el-button @click="onAddOrEdit('add', null)" type="success">新增</el-button>
|
||||
</template>
|
||||
@ -24,34 +24,60 @@
|
||||
</el-tree-select>
|
||||
</template>
|
||||
</search-module>
|
||||
<table-module :table="table">
|
||||
<template #headerBtn>
|
||||
<el-radio-group v-model="commodityType" @change="onChangeCommodityType">
|
||||
<el-radio-button
|
||||
v-for="item in commodityTypeOptions"
|
||||
:key="item.value"
|
||||
:value="item.value"
|
||||
>{{ item.label }}</el-radio-button
|
||||
>
|
||||
</el-radio-group>
|
||||
</template>
|
||||
<div class="bg-white mt-2.5 pt-2.5 pl-2.5">
|
||||
<el-radio-group v-model="commodityType" @change="onChangeCommodityType">
|
||||
<el-radio-button
|
||||
v-for="item in commodityTypeOptions"
|
||||
:key="item.value"
|
||||
:value="item.value"
|
||||
>{{ item.label }}</el-radio-button
|
||||
>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
<table-module :table="table" v-show="commodityType !== 'frontPage'" class="!mt-0">
|
||||
<template #status="{ row }">
|
||||
<el-icon v-if="row.status === 'online'" color="green"><Check /></el-icon>
|
||||
<el-icon v-else color="red"><Close /></el-icon>
|
||||
<el-switch
|
||||
v-model="row.status"
|
||||
:active-value="'online'"
|
||||
:inactive-value="'down'"
|
||||
size="small"
|
||||
@change="onChangeStatus(row)"
|
||||
/>
|
||||
</template>
|
||||
<template #isNew="{ row }">
|
||||
<el-icon v-if="row.isNew" color="green"><Check /></el-icon>
|
||||
<el-icon v-else color="red"><Close /></el-icon>
|
||||
<el-switch
|
||||
v-model="row.isNew"
|
||||
:active-value="1"
|
||||
:inactive-value="0"
|
||||
size="small"
|
||||
@change="onChangeCommodityOtherStatus(row, 'isNew')"
|
||||
/>
|
||||
</template>
|
||||
<template #isFlash="{ row }">
|
||||
<el-icon v-if="row.isFlash" color="green"><Check /></el-icon>
|
||||
<el-icon v-else color="red"><Close /></el-icon>
|
||||
<el-switch
|
||||
v-model="row.isFlash"
|
||||
:active-value="1"
|
||||
:inactive-value="0"
|
||||
size="small"
|
||||
@change="onChangeCommodityOtherStatus(row, 'isFlash')"
|
||||
/>
|
||||
</template>
|
||||
<template #frontPage="{ row }">
|
||||
<el-icon v-if="row.frontPage" color="green"><Check /></el-icon>
|
||||
<el-icon v-else color="red"><Close /></el-icon>
|
||||
<el-switch
|
||||
v-model="row.frontPage"
|
||||
:active-value="1"
|
||||
:inactive-value="0"
|
||||
size="small"
|
||||
@change="onChangeCommodityOtherStatus(row, 'frontPage')"
|
||||
/>
|
||||
</template>
|
||||
</table-module>
|
||||
<home-goods
|
||||
v-show="commodityType === 'frontPage'"
|
||||
:rondomNumber="rondomNumber"
|
||||
:searchData="search.$data"
|
||||
class="!mt-0"
|
||||
></home-goods>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -59,8 +85,7 @@
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { initConfig } from './config'
|
||||
import { useCommodityType, handleLoadNode } from './use-method'
|
||||
import { Check } from '@element-plus/icons-vue'
|
||||
import { Close } from '@element-plus/icons-vue'
|
||||
import HomeGoods from '../home-goods/index.vue'
|
||||
|
||||
const router = useRouter()
|
||||
/** 新增&编辑 */
|
||||
@ -76,18 +101,7 @@ const onAddOrEdit = (type: string, 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) => {
|
||||
handleMessageBox({
|
||||
msg: `是否加入首页?`,
|
||||
success: api.commodity.changeCommodityInfo.post!,
|
||||
data: { id: row.id, frontPage: 1 }
|
||||
}).then(() => {
|
||||
table.value.$onGetData(table.value)
|
||||
})
|
||||
table.value.$onGetData(table.value, 1, search)
|
||||
}
|
||||
|
||||
// 删除
|
||||
@ -97,32 +111,54 @@ const onDelete = (row: any) => {
|
||||
success: api.commodity.changeCommodityInfo.post!,
|
||||
data: { id: row.id, isDelete: 1 }
|
||||
}).then(() => {
|
||||
table.value.$onGetData(table.value)
|
||||
table.value.$onGetData(table.value, 1, search)
|
||||
})
|
||||
}
|
||||
|
||||
// 改变上下架
|
||||
const onChangeStatus = (row: any) => {
|
||||
const type = row.status === 'online' ? '下架' : '上架'
|
||||
const type = row.status === 'online' ? '上架' : '下架'
|
||||
handleMessageBox({
|
||||
msg: `是否确认${type}吗?`,
|
||||
success: api.commodity.changeCommodityInfo.post!,
|
||||
data: {
|
||||
id: row.id,
|
||||
status: row.status === 'online' ? 'down' : 'online'
|
||||
status: row.status
|
||||
},
|
||||
fail: () => {
|
||||
row.status = row.status === 'online' ? 'down' : 'online'
|
||||
}
|
||||
}).then(() => {
|
||||
table.value.$onGetData(table.value)
|
||||
})
|
||||
.then(() => {
|
||||
table.value.$onGetData(table.value, 1, search)
|
||||
})
|
||||
.catch(() => {
|
||||
row.status = row.status === 'online' ? 'down' : 'online'
|
||||
})
|
||||
}
|
||||
|
||||
/** 改变其他状态 */
|
||||
const onChangeCommodityOtherStatus = (row: any, status: string) => {
|
||||
const type = { isNew: '新品', isFlash: '限时秒杀', frontPage: '加入首页' }[status]
|
||||
handleMessageBox({
|
||||
msg: `是否将此商品${row[status] === 1 ? '设置' : '取消'}${type}吗?`,
|
||||
success: api.commodity.changeCommodityInfo.post!,
|
||||
data: {
|
||||
id: row.id,
|
||||
[status]: row[status]
|
||||
},
|
||||
fail: () => {
|
||||
row[status] = row[status] === 1 ? 0 : 1
|
||||
}
|
||||
}).catch(() => {
|
||||
row[status] = row[status] === 1 ? 0 : 1
|
||||
})
|
||||
}
|
||||
/** 初始化页面 */
|
||||
const ConfigData = initConfig()
|
||||
const { search, table } = handleInit(ConfigData, api.commodity.getCommodityList.post, [
|
||||
onAddOrEdit.bind(null, 'edit'),
|
||||
onCopy,
|
||||
onAddHome,
|
||||
onChangeStatus,
|
||||
onDelete
|
||||
])
|
||||
const { commodityType, onChangeCommodityType, commodityTypeOptions } = useCommodityType(
|
||||
@ -131,6 +167,15 @@ const { commodityType, onChangeCommodityType, commodityTypeOptions } = useCommod
|
||||
)
|
||||
onChangeCommodityType(commodityType.value)
|
||||
|
||||
const rondomNumber = ref(NaN)
|
||||
const onSearch = (val: any) => {
|
||||
if (search.value.$data.status === 'frontPage') {
|
||||
rondomNumber.value = Math.random()
|
||||
} else {
|
||||
table.value.$onGetData(table.value, 1, val)
|
||||
}
|
||||
}
|
||||
|
||||
/** 页面缓存 */
|
||||
defineOptions({ name: 'Commodity' })
|
||||
</script>
|
||||
|
||||
@ -1,32 +1,35 @@
|
||||
type TCommodityType = 'all' | 'online' | 'down' | 'draft' | 'delete'
|
||||
type TCommodityType = 'all' | 'online' | 'down' | 'draft' | 'delete' | 'frontPage'
|
||||
|
||||
export const useCommodityType = (search: any, table: any) => {
|
||||
let beforeValue = 'online'
|
||||
const commodityType = ref<TCommodityType>('online')
|
||||
const commodityTypeOptions = [
|
||||
{ label: '在线商品', value: 'online' },
|
||||
{ label: '首页商品', value: 'frontPage' },
|
||||
{ label: '所有商品', value: 'all' },
|
||||
{ label: '下架商品', value: 'down' },
|
||||
{ label: '草稿', value: 'draft' },
|
||||
{ label: '已删商品', value: 'delete' }
|
||||
]
|
||||
const cacheTableData = { all: [], online: [], down: [], draft: [], delete: [] } // 缓存表单数据
|
||||
const cacheTablePage = { all: {}, online: {}, down: {}, draft: {}, delete: {} } // 缓存表单页面数据
|
||||
const onChangeCommodityType = (type: 'all' | 'online' | 'down' | 'draft' | 'delete') => {
|
||||
const cacheTableData = { all: [], online: [], down: [], draft: [], delete: [], frontPage: [] } // 缓存表单数据
|
||||
const cacheTablePage = { all: {}, online: {}, down: {}, draft: {}, delete: {}, frontPage: {} } // 缓存表单页面数据
|
||||
const onChangeCommodityType = (
|
||||
type: 'all' | 'online' | 'down' | 'draft' | 'delete' | 'frontPage'
|
||||
) => {
|
||||
cacheTableData[beforeValue as typeof type] = toRaw(table.value.$data)
|
||||
cacheTablePage[beforeValue as typeof type] = toRaw(table.value.$pages)
|
||||
beforeValue = type
|
||||
search.value.$default = { status: type }
|
||||
search.value.$data = { status: type }
|
||||
handleSetTableConfig(table, type)
|
||||
search.value.$default.status = type
|
||||
search.value.$data.status = type
|
||||
// handleSetTableConfig(table, type)
|
||||
if (cacheTableData[type].length) {
|
||||
table.value.$data = cacheTableData[type]
|
||||
table.value.$pages = cacheTablePage[type]
|
||||
} else {
|
||||
if (type === 'all') {
|
||||
search.value.$data = { status: '' }
|
||||
search.value.$data.status = ''
|
||||
table.value.$onGetData(table.value, 1, search)
|
||||
} else {
|
||||
} else if (type !== 'frontPage') {
|
||||
table.value.$onGetData(table.value, 1, search)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,10 +1,6 @@
|
||||
const configData = ref()
|
||||
export const initConfig = () => {
|
||||
configData.value = pageConfig({
|
||||
search: {
|
||||
comTitle: { label: '标题', clearable: true },
|
||||
adminCategoryId: { label: '类目', slot: 'adminCategoryId' }
|
||||
},
|
||||
table: {
|
||||
id: { label: '产品ID' },
|
||||
title: { label: '标题' },
|
||||
@ -15,12 +11,13 @@ export const initConfig = () => {
|
||||
label: '在线',
|
||||
slot: 'status'
|
||||
},
|
||||
frontPage: { label: '加入首页', slot: 'frontPage' },
|
||||
isNew: { label: '新品', slot: 'isNew' },
|
||||
isFlash: { label: '限时秒杀', slot: 'isFlash' },
|
||||
btn: {
|
||||
types: ['primary', 'warning', 'success', 'danger'],
|
||||
names: ['编辑', '移除首页', '上架', '下架'],
|
||||
width: 200
|
||||
types: ['primary', 'warning', 'danger'],
|
||||
names: ['编辑', '复制', '删除'],
|
||||
width: 150
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@ -1,39 +1,42 @@
|
||||
<template>
|
||||
<div>
|
||||
<search-module :search="search" :table="table">
|
||||
<template #adminCategoryId>
|
||||
<el-tree-select
|
||||
show-checkbox
|
||||
v-model="search.$data.adminCategoryId"
|
||||
:props="{
|
||||
label: 'label',
|
||||
children: 'children',
|
||||
disabled: 'disabled',
|
||||
isLeaf: (data: any) => {
|
||||
return !data.hasChild
|
||||
}
|
||||
}"
|
||||
:render-after-expand="false"
|
||||
:load="handleLoadNode"
|
||||
lazy
|
||||
style="width: 240px"
|
||||
>
|
||||
</el-tree-select>
|
||||
</template>
|
||||
</search-module>
|
||||
<div id="table-drag-wrap">
|
||||
<table-module :table="table">
|
||||
<template #status="{ row }">
|
||||
<el-icon v-if="row.status === 'online'" color="green"><Check /></el-icon>
|
||||
<el-icon v-else color="red"><Close /></el-icon>
|
||||
<el-switch
|
||||
v-model="row.status"
|
||||
:active-value="'online'"
|
||||
:inactive-value="'down'"
|
||||
size="small"
|
||||
@change="onChangeStatus(row)"
|
||||
/>
|
||||
</template>
|
||||
<template #frontPage="{ row }">
|
||||
<el-switch
|
||||
v-model="row.frontPage"
|
||||
:active-value="1"
|
||||
:inactive-value="0"
|
||||
@change="onChangeCommodityOtherStatus(row, 'frontPage')"
|
||||
size="small"
|
||||
/>
|
||||
</template>
|
||||
<template #isNew="{ row }">
|
||||
<el-icon v-if="row.isNew" color="green"><Check /></el-icon>
|
||||
<el-icon v-else color="red"><Close /></el-icon>
|
||||
<el-switch
|
||||
v-model="row.isNew"
|
||||
:active-value="1"
|
||||
:inactive-value="0"
|
||||
@change="onChangeCommodityOtherStatus(row, 'isNew')"
|
||||
size="small"
|
||||
></el-switch>
|
||||
</template>
|
||||
<template #isFlash="{ row }">
|
||||
<el-icon v-if="row.isFlash" color="green"><Check /></el-icon>
|
||||
<el-icon v-else color="red"><Close /></el-icon>
|
||||
<el-switch
|
||||
v-model="row.isFlash"
|
||||
:active-value="1"
|
||||
:inactive-value="0"
|
||||
@change="onChangeCommodityOtherStatus(row, 'isFlash')"
|
||||
size="small"
|
||||
></el-switch>
|
||||
</template>
|
||||
</table-module>
|
||||
</div>
|
||||
@ -43,46 +46,65 @@
|
||||
<script lang="ts" setup>
|
||||
import { useDraggable } from 'vue-draggable-plus'
|
||||
import { initConfig } from './config'
|
||||
import { Check } from '@element-plus/icons-vue'
|
||||
import { Close } from '@element-plus/icons-vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
|
||||
// 移除首页
|
||||
const onRemoveHome = (row: any) => {
|
||||
handleMessageBox({
|
||||
msg: `是否加入首页?`,
|
||||
success: api.commodity.changeCommodityInfo.post!,
|
||||
data: { id: row.id, frontPage: 0 }
|
||||
}).then(() => {
|
||||
table.value.$onGetData(table.value)
|
||||
})
|
||||
const props = defineProps<{ searchData: any; rondomNumber: number }>()
|
||||
|
||||
/** 复制 */
|
||||
const onCopy = async (row: any) => {
|
||||
await api.commodity.copyCommodity.post!({ productId: row.id })
|
||||
ElMessage.success('复制成功')
|
||||
table.value.$onGetData(table.value, 1, { ...props.searchData, frontPage: 1, status: undefined })
|
||||
}
|
||||
|
||||
// 下架
|
||||
const onDown = (row: any) => {
|
||||
// 改变上下架
|
||||
const onChangeStatus = (row: any) => {
|
||||
const type = row.status === 'online' ? '上架' : '下架'
|
||||
handleMessageBox({
|
||||
msg: `是否确认下架该商品?`,
|
||||
msg: `是否确认${type}吗?`,
|
||||
success: api.commodity.changeCommodityInfo.post!,
|
||||
data: {
|
||||
id: row.id,
|
||||
status: 'down'
|
||||
status: row.status
|
||||
},
|
||||
fail: () => {
|
||||
row.status = row.status === 'online' ? 'down' : 'online'
|
||||
}
|
||||
})
|
||||
.then(() => {
|
||||
table.value.$onGetData(table.value, 1, {
|
||||
...props.searchData,
|
||||
frontPage: 1,
|
||||
status: undefined
|
||||
})
|
||||
})
|
||||
.catch(() => {
|
||||
row.status = row.status === 'online' ? 'down' : 'online'
|
||||
})
|
||||
}
|
||||
|
||||
// 删除
|
||||
const onDelete = (row: any) => {
|
||||
handleMessageBox({
|
||||
msg: `是否确认删除吗?`,
|
||||
success: api.commodity.changeCommodityInfo.post!,
|
||||
data: { id: row.id, isDelete: 1 }
|
||||
}).then(() => {
|
||||
table.value.$onGetData(table.value)
|
||||
table.value.$onGetData(table.value, 1, { ...props.searchData, frontPage: 1, status: undefined })
|
||||
})
|
||||
}
|
||||
|
||||
// 上架
|
||||
const onUp = (row: any) => {
|
||||
const onChangeCommodityOtherStatus = (row: any, status: string) => {
|
||||
const type = { isNew: '新品', isFlash: '限时秒杀' }[status]
|
||||
handleMessageBox({
|
||||
msg: `是否确认上架该商品?`,
|
||||
msg: `是否将此商品${row[status] === 1 ? '设置' : '取消'}${type}吗?`,
|
||||
success: api.commodity.changeCommodityInfo.post!,
|
||||
data: {
|
||||
id: row.id,
|
||||
status: 'online'
|
||||
data: { id: row.id, [status]: row[status] },
|
||||
fail: () => {
|
||||
row[status] = row[status] === 1 ? 0 : 1
|
||||
}
|
||||
}).then(() => {
|
||||
table.value.$onGetData(table.value)
|
||||
}).catch(() => {
|
||||
row[status] = row[status] === 1 ? 0 : 1
|
||||
})
|
||||
}
|
||||
|
||||
@ -93,15 +115,13 @@ const onEdit = (row: any) => {
|
||||
|
||||
/** 初始化页面 */
|
||||
const ConfigData = initConfig()
|
||||
const { search, table } = handleInit(ConfigData, api.commodity.getCommodityList.post, [
|
||||
const { table } = handleInit(ConfigData, api.commodity.getCommodityList.post, [
|
||||
onEdit,
|
||||
onRemoveHome,
|
||||
onUp,
|
||||
onDown
|
||||
onCopy,
|
||||
onDelete
|
||||
])
|
||||
search.value.$default = { frontPage: 1 }
|
||||
table.value.$pages.pageSize = 1000
|
||||
table.value.$onGetData(table.value, 1, search)
|
||||
table.value.$onGetData(table.value, 1, { frontPage: 1 })
|
||||
|
||||
// 拖拽实例
|
||||
let draggableInstance: any = null
|
||||
@ -151,6 +171,28 @@ watch(
|
||||
{ deep: true }
|
||||
)
|
||||
|
||||
watch(
|
||||
() => props.searchData,
|
||||
(val) => {
|
||||
if (val.status === 'frontPage' && !table.value.$data.length) {
|
||||
table.value.$onGetData(table.value, 1, { ...val, frontPage: 1, status: undefined })
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
watch(
|
||||
() => props.rondomNumber,
|
||||
(val) => {
|
||||
if (val) {
|
||||
table.value.$onGetData(table.value, 1, {
|
||||
...props.searchData,
|
||||
frontPage: 1,
|
||||
status: undefined
|
||||
})
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
// 树结构懒加载后台类目
|
||||
const handleLoadNode = (node: any, resolve: any) => {
|
||||
api.commodity.getCategoryList.post!<any>({ parentId: node.data.value || 0 }).then((res) => {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user