feat: 属性管理
This commit is contained in:
parent
c0c64aee57
commit
4fb256f328
@ -69,6 +69,24 @@ export default [
|
||||
modifyTime: '2025-06-20 09:53:53',
|
||||
tag: null,
|
||||
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,
|
||||
|
||||
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