✨ feat(mes): 新增物料产品选择器 V2 组件
parent
9f9ac51edf
commit
1f9380ba90
|
|
@ -1,78 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="head-container">
|
|
||||||
<el-input v-model="filterName" class="mb-20px" clearable placeholder="请输入分类名称">
|
|
||||||
<template #prefix>
|
|
||||||
<Icon icon="ep:search" />
|
|
||||||
</template>
|
|
||||||
</el-input>
|
|
||||||
</div>
|
|
||||||
<div class="head-container">
|
|
||||||
<el-tree
|
|
||||||
ref="treeRef"
|
|
||||||
:data="itemTypeList"
|
|
||||||
:expand-on-click-node="false"
|
|
||||||
:filter-node-method="filterNode"
|
|
||||||
:props="defaultProps"
|
|
||||||
default-expand-all
|
|
||||||
highlight-current
|
|
||||||
node-key="id"
|
|
||||||
@node-click="handleNodeClick"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts" setup>
|
|
||||||
import { ElTree } from 'element-plus'
|
|
||||||
import { MdItemTypeApi } from '@/api/mes/md/item/type'
|
|
||||||
import { defaultProps, handleTree } from '@/utils/tree'
|
|
||||||
|
|
||||||
defineOptions({ name: 'MesItemTypeTree' })
|
|
||||||
|
|
||||||
const filterName = ref('')
|
|
||||||
const itemTypeList = ref<Tree[]>([])
|
|
||||||
const treeRef = ref<InstanceType<typeof ElTree>>()
|
|
||||||
|
|
||||||
/** 获得分类树 */
|
|
||||||
const getTree = async () => {
|
|
||||||
const res = await MdItemTypeApi.getItemTypeSimpleList()
|
|
||||||
itemTypeList.value = []
|
|
||||||
itemTypeList.value.push(...handleTree(res))
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 基于名字过滤 */
|
|
||||||
const filterNode = (name: string, data: Tree) => {
|
|
||||||
if (!name) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return data.name.includes(name)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 处理分类被点击 */
|
|
||||||
let currentNode: any = {}
|
|
||||||
const handleNodeClick = async (row: { [key: string]: any }, treeNode: any) => {
|
|
||||||
if (currentNode && currentNode.name === row.name) {
|
|
||||||
treeNode.checked = !treeNode.checked
|
|
||||||
} else {
|
|
||||||
treeNode.checked = true
|
|
||||||
}
|
|
||||||
if (treeNode.checked) {
|
|
||||||
currentNode = row
|
|
||||||
emits('node-click', row)
|
|
||||||
} else {
|
|
||||||
treeRef.value!.setCurrentKey(undefined)
|
|
||||||
emits('node-click', undefined)
|
|
||||||
currentNode = null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const emits = defineEmits(['node-click'])
|
|
||||||
|
|
||||||
/** 监听过滤名称 */
|
|
||||||
watch(filterName, (val) => {
|
|
||||||
treeRef.value!.filter(val)
|
|
||||||
})
|
|
||||||
|
|
||||||
/** 初始化 */
|
|
||||||
onMounted(async () => {
|
|
||||||
await getTree()
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
|
|
@ -0,0 +1,97 @@
|
||||||
|
<!--
|
||||||
|
MES 物料分类树面板
|
||||||
|
|
||||||
|
功能:加载物料分类树 + 关键字过滤 + 点击节点通知父组件
|
||||||
|
用法:<MdItemTypeTree @node-click="handleTypeClick" />
|
||||||
|
说明:
|
||||||
|
- 组件 mount 后自动加载数据,也可通过 ref 调用 loadTree() 手动刷新
|
||||||
|
- 支持 toggle:点击已选中节点会取消选中(emit undefined)
|
||||||
|
Events:
|
||||||
|
nodeClick(data: MdItemTypeVO | undefined) — 点击树节点时触发;取消选中时为 undefined
|
||||||
|
Expose:
|
||||||
|
loadTree() — 手动刷新分类树
|
||||||
|
clearCurrent() — 清除当前选中节点高亮
|
||||||
|
-->
|
||||||
|
<template>
|
||||||
|
<el-input
|
||||||
|
v-model="filterText"
|
||||||
|
placeholder="搜索分类"
|
||||||
|
clearable
|
||||||
|
class="mb-12px"
|
||||||
|
:prefix-icon="iconSearch"
|
||||||
|
/>
|
||||||
|
<el-tree
|
||||||
|
ref="treeRef"
|
||||||
|
:data="treeData"
|
||||||
|
:props="treeProps"
|
||||||
|
:expand-on-click-node="false"
|
||||||
|
:filter-node-method="filterNode"
|
||||||
|
default-expand-all
|
||||||
|
highlight-current
|
||||||
|
node-key="id"
|
||||||
|
@node-click="handleNodeClick"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { MdItemTypeApi, MdItemTypeVO } from '@/api/mes/md/item/type'
|
||||||
|
import { handleTree } from '@/utils/tree'
|
||||||
|
import { Search as iconSearch } from '@element-plus/icons-vue'
|
||||||
|
|
||||||
|
defineOptions({ name: 'MdItemTypeTree' })
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
nodeClick: [data: MdItemTypeVO | undefined]
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const treeRef = ref() // 树组件 Ref
|
||||||
|
const filterText = ref('') // 搜索关键字
|
||||||
|
const treeData = ref<MdItemTypeVO[]>([]) // 树形数据
|
||||||
|
const treeProps = { children: 'children', label: 'name' } // 树属性映射
|
||||||
|
let currentNodeId: number | undefined // 当前选中节点 ID(用于 toggle 判断)
|
||||||
|
|
||||||
|
/** 过滤树节点(按名称匹配) */
|
||||||
|
const filterNode = (value: string, data: MdItemTypeVO) => {
|
||||||
|
if (!value) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return data.name?.includes(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 监听搜索关键字变化,触发树过滤 */
|
||||||
|
watch(filterText, (val) => {
|
||||||
|
treeRef.value?.filter(val)
|
||||||
|
})
|
||||||
|
|
||||||
|
/** 点击树节点:支持 toggle(再次点击同一节点取消选中) */
|
||||||
|
const handleNodeClick = (data: MdItemTypeVO) => {
|
||||||
|
if (currentNodeId === data.id) {
|
||||||
|
// 再次点击同一节点:取消选中
|
||||||
|
treeRef.value?.setCurrentKey(undefined)
|
||||||
|
currentNodeId = undefined
|
||||||
|
emit('nodeClick', undefined)
|
||||||
|
} else {
|
||||||
|
// 选中新节点
|
||||||
|
currentNodeId = data.id
|
||||||
|
emit('nodeClick', data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 加载分类树数据 */
|
||||||
|
const loadTree = async () => {
|
||||||
|
const list = await MdItemTypeApi.getItemTypeSimpleList()
|
||||||
|
treeData.value = handleTree(list)
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
loadTree()
|
||||||
|
})
|
||||||
|
|
||||||
|
/** 清除当前选中节点高亮 */
|
||||||
|
const clearCurrent = () => {
|
||||||
|
treeRef.value?.setCurrentKey(undefined)
|
||||||
|
currentNodeId = undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({ loadTree, clearCurrent })
|
||||||
|
</script>
|
||||||
Loading…
Reference in New Issue