feat: 商品管理自测
This commit is contained in:
parent
7099bea338
commit
701c093695
@ -30,6 +30,7 @@ const login = {
|
|||||||
* 商品管理
|
* 商品管理
|
||||||
*/
|
*/
|
||||||
getCommodityList: ['/product/list'], // 获取商品列表
|
getCommodityList: ['/product/list'], // 获取商品列表
|
||||||
|
sortCommodity: ['/product/order'], // 商品排序
|
||||||
getCommodityDetail: ['/product/detail'], // 获取商品详情
|
getCommodityDetail: ['/product/detail'], // 获取商品详情
|
||||||
addOrUpdateCommodity: ['/product/insertOrUpadate'], // 修改商品详情
|
addOrUpdateCommodity: ['/product/insertOrUpadate'], // 修改商品详情
|
||||||
changeCommodityInfo: ['/product/onlyUpdateProduct'], // 修改商品信息(列表页)
|
changeCommodityInfo: ['/product/onlyUpdateProduct'], // 修改商品信息(列表页)
|
||||||
|
|||||||
@ -3,7 +3,7 @@ export const initConfig = () => {
|
|||||||
configData.value = pageConfig({
|
configData.value = pageConfig({
|
||||||
search: {
|
search: {
|
||||||
title: { label: '标题', clearable: true },
|
title: { label: '标题', clearable: true },
|
||||||
comCategoryId: { label: '类目', option: [], clearable: true }
|
adminCategoryId: { label: '类目', slot: 'adminCategoryId' }
|
||||||
},
|
},
|
||||||
table: {
|
table: {
|
||||||
id: { label: '产品ID' },
|
id: { label: '产品ID' },
|
||||||
@ -11,6 +11,13 @@ export const initConfig = () => {
|
|||||||
showSaleCount: { label: '销量' },
|
showSaleCount: { label: '销量' },
|
||||||
showPromotionPrice: { label: '价格' },
|
showPromotionPrice: { label: '价格' },
|
||||||
showSalePrice: { label: '促销价' },
|
showSalePrice: { label: '促销价' },
|
||||||
|
status: {
|
||||||
|
label: '在线',
|
||||||
|
slot: 'status'
|
||||||
|
},
|
||||||
|
frontPage: { label: '加入首页', slot: 'frontPage' },
|
||||||
|
isNew: { label: '新品', slot: 'isNew' },
|
||||||
|
isFlash: { label: '限时秒杀', slot: 'isFlash' },
|
||||||
btn: {
|
btn: {
|
||||||
types: ['primary', 'info', 'warning', 'success', 'danger'],
|
types: ['primary', 'info', 'warning', 'success', 'danger'],
|
||||||
names: ['编辑', '复制', '加入首页', '上下架', '删除'],
|
names: ['编辑', '复制', '加入首页', '上下架', '删除'],
|
||||||
|
|||||||
@ -4,6 +4,25 @@
|
|||||||
<template #btn>
|
<template #btn>
|
||||||
<el-button @click="onAddOrEdit('add', null)" type="success">新增</el-button>
|
<el-button @click="onAddOrEdit('add', null)" type="success">新增</el-button>
|
||||||
</template>
|
</template>
|
||||||
|
<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>
|
</search-module>
|
||||||
<table-module :table="table">
|
<table-module :table="table">
|
||||||
<template #headerBtn>
|
<template #headerBtn>
|
||||||
@ -16,6 +35,22 @@
|
|||||||
>
|
>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</template>
|
</template>
|
||||||
|
<template #status="{ row }">
|
||||||
|
<el-icon v-if="row.status === 'online'" color="green"><Check /></el-icon>
|
||||||
|
<el-icon v-else color="red"><Close /></el-icon>
|
||||||
|
</template>
|
||||||
|
<template #isNew="{ row }">
|
||||||
|
<el-icon v-if="row.isNew" color="green"><Check /></el-icon>
|
||||||
|
<el-icon v-else color="red"><Close /></el-icon>
|
||||||
|
</template>
|
||||||
|
<template #isFlash="{ row }">
|
||||||
|
<el-icon v-if="row.isFlash" color="green"><Check /></el-icon>
|
||||||
|
<el-icon v-else color="red"><Close /></el-icon>
|
||||||
|
</template>
|
||||||
|
<template #frontPage="{ row }">
|
||||||
|
<el-icon v-if="row.frontPage" color="green"><Check /></el-icon>
|
||||||
|
<el-icon v-else color="red"><Close /></el-icon>
|
||||||
|
</template>
|
||||||
</table-module>
|
</table-module>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -23,7 +58,9 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ElMessage } from 'element-plus'
|
import { ElMessage } from 'element-plus'
|
||||||
import { initConfig } from './config'
|
import { initConfig } from './config'
|
||||||
import { useCommodityType } from './use-method'
|
import { useCommodityType, handleLoadNode } from './use-method'
|
||||||
|
import { Check } from '@element-plus/icons-vue'
|
||||||
|
import { Close } from '@element-plus/icons-vue'
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
/** 新增&编辑 */
|
/** 新增&编辑 */
|
||||||
|
|||||||
@ -4,8 +4,8 @@ export const useCommodityType = (search: any, table: any) => {
|
|||||||
let beforeValue = 'online'
|
let beforeValue = 'online'
|
||||||
const commodityType = ref<TCommodityType>('online')
|
const commodityType = ref<TCommodityType>('online')
|
||||||
const commodityTypeOptions = [
|
const commodityTypeOptions = [
|
||||||
{ label: '所有商品', value: 'all' },
|
|
||||||
{ label: '在线商品', value: 'online' },
|
{ label: '在线商品', value: 'online' },
|
||||||
|
{ label: '所有商品', value: 'all' },
|
||||||
{ label: '下架商品', value: 'down' },
|
{ label: '下架商品', value: 'down' },
|
||||||
{ label: '草稿', value: 'draft' },
|
{ label: '草稿', value: 'draft' },
|
||||||
{ label: '已删商品', value: 'delete' }
|
{ label: '已删商品', value: 'delete' }
|
||||||
@ -44,3 +44,24 @@ export const useCommodityType = (search: any, table: any) => {
|
|||||||
}
|
}
|
||||||
return { commodityType, onChangeCommodityType, commodityTypeOptions }
|
return { commodityType, onChangeCommodityType, commodityTypeOptions }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 树结构懒加载后台类目
|
||||||
|
export const handleLoadNode = (node: any, resolve: any) => {
|
||||||
|
api.commodity.getCategoryList.post!<any>({ parentId: node.data.value || 0 }).then((res) => {
|
||||||
|
resolve(
|
||||||
|
res.data.map((item: any) => ({
|
||||||
|
label: item.name,
|
||||||
|
value: item.id,
|
||||||
|
hasChild: item.hasChild,
|
||||||
|
disabled: !!item.hasChild,
|
||||||
|
categoryPropertyList: (item.vvCategoryPropertyDTOList || []).map((child: any) => ({
|
||||||
|
...child,
|
||||||
|
vvPropertyValueList: child.vvPropertyValueList.map((it: any) => ({
|
||||||
|
...it,
|
||||||
|
categoryPropertyName: child.categoryPropertyName
|
||||||
|
}))
|
||||||
|
}))
|
||||||
|
}))
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
@ -3,17 +3,24 @@ export const initConfig = () => {
|
|||||||
configData.value = pageConfig({
|
configData.value = pageConfig({
|
||||||
search: {
|
search: {
|
||||||
comTitle: { label: '标题', clearable: true },
|
comTitle: { label: '标题', clearable: true },
|
||||||
comCategoryId: { label: '类目', option: [], clearable: true }
|
adminCategoryId: { label: '类目', slot: 'adminCategoryId' }
|
||||||
},
|
},
|
||||||
table: {
|
table: {
|
||||||
id: { label: '产品ID' },
|
id: { label: '产品ID' },
|
||||||
comTitle: { label: '标题' },
|
title: { label: '标题' },
|
||||||
sales: { label: '销量' },
|
showSaleCount: { label: '销量' },
|
||||||
price: { label: '价格' },
|
showPromotionPrice: { label: '价格' },
|
||||||
|
showSalePrice: { label: '促销价' },
|
||||||
|
status: {
|
||||||
|
label: '在线',
|
||||||
|
slot: 'status'
|
||||||
|
},
|
||||||
|
isNew: { label: '新品', slot: 'isNew' },
|
||||||
|
isFlash: { label: '限时秒杀', slot: 'isFlash' },
|
||||||
btn: {
|
btn: {
|
||||||
types: ['primary'],
|
types: ['primary', 'warning', 'success', 'danger'],
|
||||||
names: ['移除首页'],
|
names: ['编辑', '移除首页', '上架', '下架'],
|
||||||
width: 90
|
width: 200
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@ -1,12 +1,41 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<search-module :search="search" :table="table">
|
<search-module :search="search" :table="table">
|
||||||
<template #btn>
|
<template #adminCategoryId>
|
||||||
<el-button @click="onAddOrEdit('add', null)" type="success">新增</el-button>
|
<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>
|
</template>
|
||||||
</search-module>
|
</search-module>
|
||||||
<div id="table-drag-wrap">
|
<div id="table-drag-wrap">
|
||||||
<table-module :table="table"> </table-module>
|
<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>
|
||||||
|
</template>
|
||||||
|
<template #isNew="{ row }">
|
||||||
|
<el-icon v-if="row.isNew" color="green"><Check /></el-icon>
|
||||||
|
<el-icon v-else color="red"><Close /></el-icon>
|
||||||
|
</template>
|
||||||
|
<template #isFlash="{ row }">
|
||||||
|
<el-icon v-if="row.isFlash" color="green"><Check /></el-icon>
|
||||||
|
<el-icon v-else color="red"><Close /></el-icon>
|
||||||
|
</template>
|
||||||
|
</table-module>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -14,32 +43,134 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { useDraggable } from 'vue-draggable-plus'
|
import { useDraggable } from 'vue-draggable-plus'
|
||||||
import { initConfig } from './config'
|
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) => {}
|
const onRemoveHome = (row: any) => {
|
||||||
|
|
||||||
// 删除
|
|
||||||
const onDelete = (row: any) => {
|
|
||||||
handleMessageBox({
|
handleMessageBox({
|
||||||
msg: `是否确认删除吗?`,
|
msg: `是否加入首页?`,
|
||||||
success: api.commodity.delCommodity.post!,
|
success: api.commodity.changeCommodityInfo.post!,
|
||||||
data: { id: row.id }
|
data: { id: row.id, frontPage: 0 }
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
table.value.$onGetData(table.value)
|
table.value.$onGetData(table.value)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 下架
|
||||||
|
const onDown = (row: any) => {
|
||||||
|
handleMessageBox({
|
||||||
|
msg: `是否确认下架该商品?`,
|
||||||
|
success: api.commodity.changeCommodityInfo.post!,
|
||||||
|
data: {
|
||||||
|
id: row.id,
|
||||||
|
status: 'down'
|
||||||
|
}
|
||||||
|
}).then(() => {
|
||||||
|
table.value.$onGetData(table.value)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 上架
|
||||||
|
const onUp = (row: any) => {
|
||||||
|
handleMessageBox({
|
||||||
|
msg: `是否确认上架该商品?`,
|
||||||
|
success: api.commodity.changeCommodityInfo.post!,
|
||||||
|
data: {
|
||||||
|
id: row.id,
|
||||||
|
status: 'online'
|
||||||
|
}
|
||||||
|
}).then(() => {
|
||||||
|
table.value.$onGetData(table.value)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const router = useRouter()
|
||||||
|
const onEdit = (row: any) => {
|
||||||
|
router.push({ path: '/goods/detail', query: { type: 'edit', id: row.id } })
|
||||||
|
}
|
||||||
|
|
||||||
/** 初始化页面 */
|
/** 初始化页面 */
|
||||||
const ConfigData = initConfig()
|
const ConfigData = initConfig()
|
||||||
const { search, table } = handleInit(ConfigData, api.commodity.getCommodityList.post, [
|
const { search, table } = handleInit(ConfigData, api.commodity.getCommodityList.post, [
|
||||||
onRemoveHome
|
onEdit,
|
||||||
|
onRemoveHome,
|
||||||
|
onUp,
|
||||||
|
onDown
|
||||||
])
|
])
|
||||||
search.value.$default = { frontPage: 1 }
|
search.value.$default = { frontPage: 1 }
|
||||||
table.value.$pages.pageSize = 1000
|
table.value.$pages.pageSize = 1000
|
||||||
table.value.$onGetData(table.value, 1, search)
|
table.value.$onGetData(table.value, 1, search)
|
||||||
setTimeout(() => {
|
|
||||||
useDraggable('#table-drag-wrap .el-table__body tbody', table.value.$data)
|
// 拖拽实例
|
||||||
}, 2000)
|
let draggableInstance: any = null
|
||||||
|
|
||||||
|
// 初始化拖拽功能
|
||||||
|
const initDraggable = () => {
|
||||||
|
setTimeout(() => {
|
||||||
|
const tbody = document.querySelector('#table-drag-wrap .el-table__body tbody')
|
||||||
|
if (tbody && table.value.$data.length > 0) {
|
||||||
|
// 如果已有实例,先销毁
|
||||||
|
if (draggableInstance) {
|
||||||
|
draggableInstance.destroy?.()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建新的拖拽实例
|
||||||
|
draggableInstance = useDraggable(tbody, table.value.$data, {
|
||||||
|
onEnd: (evt) => {
|
||||||
|
handleDragEnd(evt)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}, 100)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 拖拽完成处理
|
||||||
|
const handleDragEnd = async (evt: any) => {
|
||||||
|
const { oldIndex, newIndex } = evt
|
||||||
|
// 检查是否真的发生了位置变化
|
||||||
|
if (oldIndex === newIndex) {
|
||||||
|
console.log('位置没有变化,无需更新')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
await api.commodity.sortCommodity.post!({ ids: table.value.$data.map((item) => item.id) })
|
||||||
|
ElMessage.success('排序更新成功')
|
||||||
|
} catch (error) {
|
||||||
|
ElMessage.error('排序更新失败')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 监听表格数据变化,自动重新初始化拖拽
|
||||||
|
watch(
|
||||||
|
() => table.value.$data,
|
||||||
|
(val) => {
|
||||||
|
initDraggable()
|
||||||
|
},
|
||||||
|
{ deep: true }
|
||||||
|
)
|
||||||
|
|
||||||
|
// 树结构懒加载后台类目
|
||||||
|
const handleLoadNode = (node: any, resolve: any) => {
|
||||||
|
api.commodity.getCategoryList.post!<any>({ parentId: node.data.value || 0 }).then((res) => {
|
||||||
|
resolve(
|
||||||
|
res.data.map((item: any) => ({
|
||||||
|
label: item.name,
|
||||||
|
value: item.id,
|
||||||
|
hasChild: item.hasChild,
|
||||||
|
disabled: !!item.hasChild,
|
||||||
|
categoryPropertyList: (item.vvCategoryPropertyDTOList || []).map((child: any) => ({
|
||||||
|
...child,
|
||||||
|
vvPropertyValueList: child.vvPropertyValueList.map((it: any) => ({
|
||||||
|
...it,
|
||||||
|
categoryPropertyName: child.categoryPropertyName
|
||||||
|
}))
|
||||||
|
}))
|
||||||
|
}))
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/** 页面缓存 */
|
/** 页面缓存 */
|
||||||
defineOptions({ name: 'HomeGoods' })
|
defineOptions({ name: 'HomeGoods' })
|
||||||
|
|||||||
@ -113,6 +113,7 @@ const onAddFiles = async () => {
|
|||||||
$dialog.value.config.files.show = true
|
$dialog.value.config.files.show = true
|
||||||
dialogType.value = 'add'
|
dialogType.value = 'add'
|
||||||
dialog.data = {}
|
dialog.data = {}
|
||||||
|
fileList.value = []
|
||||||
}
|
}
|
||||||
|
|
||||||
// 加载子文件夹
|
// 加载子文件夹
|
||||||
@ -126,6 +127,7 @@ const handleLoadNode = (node, resolve) => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
const addFileType = ref('')
|
const addFileType = ref('')
|
||||||
|
const inputRef = ref()
|
||||||
// 添加文件夹
|
// 添加文件夹
|
||||||
const onAddFolder = () => {
|
const onAddFolder = () => {
|
||||||
curRenameId.value = Infinity
|
curRenameId.value = Infinity
|
||||||
@ -133,12 +135,15 @@ const onAddFolder = () => {
|
|||||||
addFileType.value = 'folder'
|
addFileType.value = 'folder'
|
||||||
table.value.$data.push({
|
table.value.$data.push({
|
||||||
id: Infinity,
|
id: Infinity,
|
||||||
parentId: search.value.$data.parentId,
|
parentId: search.value.$data.parentId || 0,
|
||||||
defaultSort: 0,
|
defaultSort: 0,
|
||||||
type: 'file',
|
type: 'file',
|
||||||
fileName: '',
|
fileName: '',
|
||||||
modifyTime: new Date()
|
modifyTime: new Date()
|
||||||
})
|
})
|
||||||
|
nextTick(() => {
|
||||||
|
inputRef.value.focus()
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 删除
|
// 删除
|
||||||
@ -154,8 +159,10 @@ const onDelete = (row: any) => {
|
|||||||
|
|
||||||
// 跳转
|
// 跳转
|
||||||
const onJump = (row: any) => {
|
const onJump = (row: any) => {
|
||||||
search.value.$data.parentId = row.locations[row.locations.length - 1].id
|
if (row.locations.length > 0) {
|
||||||
table.value.$onGetData(table.value, 1, search)
|
search.value.$data.parentId = row.locations[row.locations.length - 1].id
|
||||||
|
table.value.$onGetData(table.value, 1, search)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 移动
|
// 移动
|
||||||
@ -188,6 +195,9 @@ const onRename = (row: any) => {
|
|||||||
renameInputVal.value = row.fileName
|
renameInputVal.value = row.fileName
|
||||||
curRenameId.value = row.id
|
curRenameId.value = row.id
|
||||||
addFileType.value = ''
|
addFileType.value = ''
|
||||||
|
nextTick(() => {
|
||||||
|
inputRef.value.focus()
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 回车确认
|
// 回车确认
|
||||||
@ -197,13 +207,17 @@ const handleInputConfirm = async (row: any) => {
|
|||||||
}
|
}
|
||||||
await api.resource.addOrEditResource.post!([{ ...row, fileName: renameInputVal.value }])
|
await api.resource.addOrEditResource.post!([{ ...row, fileName: renameInputVal.value }])
|
||||||
ElMessage.success('操作成功')
|
ElMessage.success('操作成功')
|
||||||
|
table.value.$onGetData(table.value)
|
||||||
row.fileName = renameInputVal.value
|
row.fileName = renameInputVal.value
|
||||||
curRenameId.value = NaN
|
curRenameId.value = NaN
|
||||||
}
|
}
|
||||||
|
|
||||||
// 失焦
|
// 失焦
|
||||||
const handleInputCancel = (row: any) => {
|
const handleInputCancel = (row: any) => {
|
||||||
curRenameId.value = row.fileName
|
if (row.id === Infinity) {
|
||||||
|
table.value.$data.splice(table.value.$data.indexOf(row), 1)
|
||||||
|
}
|
||||||
|
curRenameId.value = NaN
|
||||||
addFileType.value = ''
|
addFileType.value = ''
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -272,7 +286,7 @@ $dialog.value.submit = async () => {
|
|||||||
fileName: item.srcFileName,
|
fileName: item.srcFileName,
|
||||||
resourceUrl: item.url,
|
resourceUrl: item.url,
|
||||||
defaultSort: 0,
|
defaultSort: 0,
|
||||||
parentId: $dialog.value.data.parentId,
|
parentId: $dialog.value.data.parentId || 0,
|
||||||
type: 'image'
|
type: 'image'
|
||||||
}))
|
}))
|
||||||
await api.resource.addOrEditResource.post!(params)
|
await api.resource.addOrEditResource.post!(params)
|
||||||
@ -281,7 +295,7 @@ $dialog.value.submit = async () => {
|
|||||||
} else {
|
} else {
|
||||||
const params = selectFiles.value.map((item: any) => ({
|
const params = selectFiles.value.map((item: any) => ({
|
||||||
...item,
|
...item,
|
||||||
parentId: $dialog.value.data.parentId
|
parentId: $dialog.value.data.parentId || 0
|
||||||
}))
|
}))
|
||||||
await api.resource.addOrEditResource.post!(params)
|
await api.resource.addOrEditResource.post!(params)
|
||||||
ElMessage.success('操作成功')
|
ElMessage.success('操作成功')
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user