feat: 属性管理
This commit is contained in:
parent
c0c64aee57
commit
4fb256f328
@ -69,6 +69,24 @@ export default [
|
|||||||
modifyTime: '2025-06-20 09:53:53',
|
modifyTime: '2025-06-20 09:53:53',
|
||||||
tag: null,
|
tag: null,
|
||||||
childList: []
|
childList: []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 127,
|
||||||
|
resourceName: 'app类目管理',
|
||||||
|
resourceType: 1,
|
||||||
|
resourceCode: null,
|
||||||
|
path: '/goods/appCategory/index',
|
||||||
|
pid: 37,
|
||||||
|
resourceDesc: null,
|
||||||
|
tenantId: 2,
|
||||||
|
icon: '',
|
||||||
|
isCache: 1,
|
||||||
|
visible: 0,
|
||||||
|
sort: '3',
|
||||||
|
createTime: '2025-06-20 09:52:12',
|
||||||
|
modifyTime: '2025-06-20 09:53:53',
|
||||||
|
tag: null,
|
||||||
|
childList: []
|
||||||
}
|
}
|
||||||
/* {
|
/* {
|
||||||
id: 127,
|
id: 127,
|
||||||
|
|||||||
169
src/views/goods/appCategory/index.vue
Normal file
169
src/views/goods/appCategory/index.vue
Normal file
@ -0,0 +1,169 @@
|
|||||||
|
<template>
|
||||||
|
<div id="category-tree" class="p-2 bg-white">
|
||||||
|
<p>类目展示:</p>
|
||||||
|
<el-tree
|
||||||
|
ref="treeRef"
|
||||||
|
style="max-width: 600px"
|
||||||
|
:props="defaultProps"
|
||||||
|
node-key="id"
|
||||||
|
draggable
|
||||||
|
:render-after-expand="false"
|
||||||
|
check-strictly
|
||||||
|
:load="handleLoadNode"
|
||||||
|
lazy
|
||||||
|
highlight-current
|
||||||
|
:expand-on-click-node="false"
|
||||||
|
@node-click="handleNodeClick"
|
||||||
|
@node-drag-start="handleDragStart"
|
||||||
|
@node-drop="handleDropFinish"
|
||||||
|
>
|
||||||
|
<template #default="{ node, data }">
|
||||||
|
<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="handleInputCancel(node, data)"
|
||||||
|
/>
|
||||||
|
<div>
|
||||||
|
<el-button type="primary" link @click="onEdit(data)" size="small">编辑 </el-button>
|
||||||
|
<el-button type="primary" link @click="append(data)" size="small"> 添加 </el-button>
|
||||||
|
<el-button type="danger" size="small" link @click="remove(node, data)">
|
||||||
|
删除
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-tree>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ElButton, ElMessage } from 'element-plus'
|
||||||
|
import type { RenderContentContext } from 'element-plus'
|
||||||
|
import { handleDragStart, handleDropFinish } from './use-drag'
|
||||||
|
|
||||||
|
interface Tree {
|
||||||
|
id: number
|
||||||
|
name: string
|
||||||
|
children?: Tree[]
|
||||||
|
}
|
||||||
|
type Node = RenderContentContext['node']
|
||||||
|
type Data = RenderContentContext['data']
|
||||||
|
|
||||||
|
const curId = ref(NaN)
|
||||||
|
const curParentId = ref(NaN)
|
||||||
|
const inputRef = ref()
|
||||||
|
const treeRef = ref()
|
||||||
|
|
||||||
|
// 编辑类目名称
|
||||||
|
const onEdit = (data: Data) => {
|
||||||
|
data.label2 = data.name
|
||||||
|
curId.value = data.id
|
||||||
|
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 handleInputCancel = (node: Node, data: Data) => {
|
||||||
|
if (data.id === Infinity) {
|
||||||
|
remove(node, data)
|
||||||
|
}
|
||||||
|
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(() => {
|
||||||
|
inputRef.value.focus()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除类目
|
||||||
|
const remove = (node: Node, data: Data) => {
|
||||||
|
const parent = node.parent
|
||||||
|
const children: Tree[] = parent?.data.children || parent?.data
|
||||||
|
const index = children.findIndex((d) => d.id === data.id)
|
||||||
|
children.splice(index, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
const defaultProps = {
|
||||||
|
label: 'name',
|
||||||
|
children: 'children',
|
||||||
|
disabled: 'disabled',
|
||||||
|
isLeaf: (data: any) => {
|
||||||
|
return !data.hasChild
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取类目列表
|
||||||
|
const handleLoadNode = (node, resolve) => {
|
||||||
|
api.commodity.getAppCategoryList.post!<any>({ parentId: node.data.id || 0 }).then((res) => {
|
||||||
|
resolve(
|
||||||
|
res.data.map((item: any) => ({
|
||||||
|
...item,
|
||||||
|
children: item.hasChild ? [] : undefined
|
||||||
|
}))
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 点击类目
|
||||||
|
const handleNodeClick = (node: Node, data: Data) => {
|
||||||
|
console.log('click', node, data)
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
#category-tree {
|
||||||
|
.category-tree-node {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
font-size: 14px;
|
||||||
|
padding-right: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
56
src/views/goods/appCategory/mock.ts
Normal file
56
src/views/goods/appCategory/mock.ts
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
interface Tree {
|
||||||
|
id: number
|
||||||
|
label: string
|
||||||
|
children?: Tree[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export const dataSource = ref<Tree[]>([
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
label: 'Level one 1',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
id: 4,
|
||||||
|
label: 'Level two 1-1',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
id: 9,
|
||||||
|
label: 'Level three 1-1-1'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 10,
|
||||||
|
label: 'Level three 1-1-2'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
label: 'Level one 2',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
id: 5,
|
||||||
|
label: 'Level two 2-1'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 6,
|
||||||
|
label: 'Level two 2-2'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
label: 'Level one 3',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
id: 7,
|
||||||
|
label: 'Level two 3-1'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 8,
|
||||||
|
label: 'Level two 3-2'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
])
|
||||||
24
src/views/goods/appCategory/use-drag.ts
Normal file
24
src/views/goods/appCategory/use-drag.ts
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import type { NodeDropType, RenderContentContext } from 'element-plus'
|
||||||
|
|
||||||
|
type Node = RenderContentContext['node']
|
||||||
|
|
||||||
|
// 开始拖拽
|
||||||
|
export const handleDragStart = (node: Node) => {
|
||||||
|
console.log('drag start', node)
|
||||||
|
}
|
||||||
|
// 拖拽成功完成时触发的事件
|
||||||
|
|
||||||
|
export const handleDropFinish = (draggingNode: Node, dropNode: Node, dropType: NodeDropType) => {
|
||||||
|
// 获取拖拽之后最新的ids
|
||||||
|
const getSortIds = () => {
|
||||||
|
const parentNode = dropType === 'inner' ? dropNode : dropNode.parent // 获取父节点
|
||||||
|
if (!parentNode || !parentNode.childNodes) return []
|
||||||
|
return parentNode.childNodes.map((node) => node.data.id)
|
||||||
|
}
|
||||||
|
// 获取拖拽到的位置索引
|
||||||
|
const sortIds = getSortIds()
|
||||||
|
if (!sortIds.length) return
|
||||||
|
api.commodity.sortCategory.post!({ categoryIds: sortIds }).then(() => {
|
||||||
|
console.log('tree drop:', draggingNode, dropNode.label, dropType)
|
||||||
|
})
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user