123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146 |
- <template>
- <div class="head-container">
- <el-input v-model="deviceCategoryName" class="mb-20px" clearable placeholder="请输入设备分类名称">
- <template #prefix>
- <Icon icon="ep:search" />
- </template>
- </el-input>
- </div>
- <div ref="treeContainer" class="tree-container">
- <el-tree
- ref="treeRef"
- :data="deviceCategoryList"
- :expand-on-click-node="false"
- :filter-node-method="filterNode"
- :props="defaultProps"
- :default-expand-all="false"
- highlight-current
- node-key="id"
- @node-click="handleNodeClick"
- @node-contextmenu="handleRightClick"
- style="height: 52em"
- />
- </div>
- <div
- v-show="menuVisible"
- class="custom-menu"
- :style="{ left: menuX + 'px', top: menuY + 'px' }"
- >
- <ul>
- <li @click="handleMenuClick('add')">新增子节点</li>
- <li @click="handleMenuClick('edit')">重命名</li>
- <li @click="handleMenuClick('delete')">删除</li>
- </ul>
- </div>
- </template>
- <script lang="ts" setup>
- import { ElTree } from 'element-plus'
- import * as DeviceCategoryApi from '@/api/pms/productclassify'
- import { defaultProps, handleTree } from '@/utils/tree'
- import { useTreeStore } from '@/store/modules/treeStore'
- defineOptions({ name: 'DeviceCategoryTree' })
- const treeStore = useTreeStore();
- const deviceCategoryName = ref('')
- const deviceCategoryList = ref<Tree[]>([]) // 树形结构
- const treeRef = ref<InstanceType<typeof ElTree>>()
- const menuVisible = ref(false);
- const menuX = ref(0);
- const menuY = ref(0);
- let selectedNode = null;
- const firstLevelKeys = ref([])
- const handleRightClick = (event, { node, data }) => {
- event.preventDefault();
- menuX.value = event.clientX;
- menuY.value = event.clientY;
- selectedNode = data; // 存储当前操作的节点数据 :ml-citation{ref="7" data="citationList"}
- menuVisible.value = true;
- };
- const treeContainer = ref(null)
- const setHeight = () => {
- if (!treeContainer.value) return
- const windowHeight = window.innerHeight
- const containerTop = treeContainer.value.offsetTop
- treeContainer.value.style.height = `${windowHeight * 0.78}px` // 60px 底部预留
- }
- const handleMenuClick = (action) => {
- switch(action) {
- case 'add':
- // 调用新增节点逻辑 :ml-citation{ref="4" data="citationList"}
- break;
- case 'edit':
- // 调用编辑节点逻辑 :ml-citation{ref="7" data="citationList"}
- break;
- case 'delete':
- // 调用删除节点逻辑 :ml-citation{ref="4" data="citationList"}
- break;
- }
- menuVisible.value = false;
- };
- /** 获得 设备分类 树 */
- const getTree = async () => {
- const res = await DeviceCategoryApi.IotProductClassifyApi.getSimpleProductClassifyList()
- deviceCategoryList.value = []
- deviceCategoryList.value.push(...handleTree(res))
- }
- /** 基于名字过滤 */
- const filterNode = (name: string, data: Tree) => {
- if (!name) return true
- return data.name.includes(name)
- }
- /** 处理 设备分类 被点击 */
- const handleNodeClick = async (row: { [key: string]: any }) => {
- emits('node-click', row)
- treeStore.setSelectedId(row.id);
- }
- const emits = defineEmits(['node-click'])
- /** 监听 deviceCategoryName */
- watch(deviceCategoryName, (val) => {
- treeRef.value!.filter(val)
- })
- /** 初始化 */
- onMounted(async () => {
- await getTree()
- setHeight()
- window.addEventListener('resize', setHeight)
- })
- onUnmounted(() => {
- window.removeEventListener('resize', setHeight)
- })
- </script>
- <style lang="scss" scoped>
- .custom-menu {
- position: fixed;
- background: white;
- border: 1px solid #ccc;
- box-shadow: 2px 2px 5px rgba(0,0,0,0.1);
- z-index: 1000;
- }
- .custom-menu ul {
- list-style: none;
- padding: 0;
- margin: 0;
- }
- .custom-menu li {
- padding: 8px 20px;
- cursor: pointer;
- }
- .custom-menu li:hover {
- background: #f5f5f5;
- }
- .tree-container {
- overflow-y: auto;
- min-width: 100%;
- border: 1px solid #e4e7ed;
- border-radius: 4px;
- }
- </style>
|