|
@@ -0,0 +1,273 @@
|
|
|
+<template>
|
|
|
+ <div class="head-container">
|
|
|
+ <el-input v-model="deptName" class="mb-20px" clearable placeholder="请输入名称">
|
|
|
+ <template #prefix>
|
|
|
+ <Icon icon="ep:search" />
|
|
|
+ </template>
|
|
|
+ </el-input>
|
|
|
+ </div>
|
|
|
+ <div class="head-container">
|
|
|
+ <el-tree
|
|
|
+ ref="treeRef"
|
|
|
+ :data="treeList"
|
|
|
+ :expand-on-click-node="false"
|
|
|
+ :filter-node-method="filterNode"
|
|
|
+ :props="defaultProps"
|
|
|
+ default-expand-all
|
|
|
+ highlight-current
|
|
|
+ node-key="id"
|
|
|
+ @node-click="handleNodeClick"
|
|
|
+ @node-contextmenu="handleRightClick"
|
|
|
+ style="height: 35em"
|
|
|
+ >
|
|
|
+ <template #default="{ node}">
|
|
|
+ <div style="display: flex; justify-content: space-between;align-items: center;width: 100%">
|
|
|
+ <div>
|
|
|
+ <el-icon style="vertical-align: middle"><Folder /></el-icon> <!-- 文件夹图标 -->
|
|
|
+ <span style="vertical-align: middle;margin-left: 3px">{{ node.data.name }}</span>
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ <icon style="vertical-align: middle" @click="handleRightClick" icon="ep:edit" />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </el-tree>
|
|
|
+ </div>
|
|
|
+<!-- <div v-show="menuVisible" ref="contextMenuRef" class="custom-menu" :style="{ left: menuX + 'px', top: menuY + 'px' }">-->
|
|
|
+<!-- <ul>-->
|
|
|
+<!-- <li style="border-bottom: 1px solid #ccc;" @click="handleMenuClick('add')">新增子节点</li>-->
|
|
|
+<!-- <li style="border-bottom: 1px solid #ccc;" @click="handleMenuClick('edit')">编辑节点</li>-->
|
|
|
+<!-- <li @click="handleMenuClick('delete')">删除节点</li>-->
|
|
|
+<!-- </ul>-->
|
|
|
+<!-- </div>-->
|
|
|
+
|
|
|
+<!-- <Dialog v-model="dialogVisible" :title="dialogTitle" style="width: 40em">-->
|
|
|
+<!-- <el-form-->
|
|
|
+<!-- ref="formRef"-->
|
|
|
+<!-- v-loading="formLoading"-->
|
|
|
+<!-- :model="formData"-->
|
|
|
+<!-- :rules="formRules"-->
|
|
|
+<!-- label-width="80px"-->
|
|
|
+<!-- >-->
|
|
|
+<!-- <el-form-item label="资料分类名称" prop="name" label-width="110px">-->
|
|
|
+<!-- <el-input v-model="formData.name" placeholder="请输入资料分类名称" />-->
|
|
|
+<!-- </el-form-item>-->
|
|
|
+<!-- <el-form-item label="显示排序" prop="sort" label-width="110px">-->
|
|
|
+<!-- <el-input-number v-model="formData.sort" :min="0" controls-position="right" />-->
|
|
|
+<!-- </el-form-item>-->
|
|
|
+<!-- <el-form-item label="备注" prop="remark" label-width="110px">-->
|
|
|
+<!-- <el-input-->
|
|
|
+<!-- v-model="formData.remark"-->
|
|
|
+<!-- maxlength="11"-->
|
|
|
+<!-- placeholder="请输入备注"-->
|
|
|
+<!-- type="textarea"-->
|
|
|
+<!-- />-->
|
|
|
+<!-- </el-form-item>-->
|
|
|
+<!-- </el-form>-->
|
|
|
+<!-- <template #footer>-->
|
|
|
+<!-- <el-button type="primary" @click="submitForm">确 定</el-button>-->
|
|
|
+<!-- <el-button @click="dialogVisible = false">取 消</el-button>-->
|
|
|
+<!-- </template>-->
|
|
|
+<!-- </Dialog>-->
|
|
|
+</template>
|
|
|
+
|
|
|
+<script lang="ts" setup>
|
|
|
+import { ElTree, FormRules } from 'element-plus'
|
|
|
+import * as FileClassifyApi from '@/api/pms/info'
|
|
|
+import * as InfoClassifyApi from '@/api/pms/info'
|
|
|
+import { defaultProps, handleTree } from '@/utils/tree'
|
|
|
+import { CommonStatusEnum } from '@/utils/constants'
|
|
|
+// import {IotInfoClassifyApi} from "@/api/pms/info";
|
|
|
+import {IotTreeApi} from "@/api/system/tree";
|
|
|
+import { Document, Folder, Search } from '@element-plus/icons-vue'
|
|
|
+const { t } = useI18n() // 国际化
|
|
|
+const message = useMessage() // 消息弹窗
|
|
|
+const dialogVisible = ref(false) // 弹窗的是否展示
|
|
|
+const dialogTitle = ref('') // 弹窗的标题
|
|
|
+const formRef = ref() // 搜索的表单
|
|
|
+const openForm = (type: string, id?: number) => {
|
|
|
+ formRef.value.open(type, id)
|
|
|
+}
|
|
|
+
|
|
|
+// const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
|
|
|
+// const formType = ref('') // 表单的类型:create - 新增;update - 修改
|
|
|
+// const formData = ref({
|
|
|
+// id: undefined,
|
|
|
+// parentId: undefined,
|
|
|
+// deviceId: undefined,
|
|
|
+// name: undefined,
|
|
|
+// sort: undefined,
|
|
|
+// status: CommonStatusEnum.ENABLE,
|
|
|
+// remark: undefined
|
|
|
+// })
|
|
|
+// const formRules = reactive<FormRules>({
|
|
|
+// name: [{ required: true, message: '资料分类名称不能为空', trigger: 'blur' }],
|
|
|
+// sort: [{ required: true, message: '显示排序不能为空', trigger: 'blur' }],
|
|
|
+// status: [{ required: true, message: '状态不能为空', trigger: 'blur' }]
|
|
|
+// })
|
|
|
+// const submitForm = async () => {
|
|
|
+// // 校验表单
|
|
|
+// if (!formRef) return
|
|
|
+// const valid = await formRef.value.validate()
|
|
|
+// if (!valid) return
|
|
|
+// // 提交请求
|
|
|
+// formLoading.value = true
|
|
|
+// try {
|
|
|
+// const data = formData.value as unknown as InfoClassifyApi.IotInfoClassifyVO
|
|
|
+// debugger
|
|
|
+// if (formType.value === 'create') {
|
|
|
+// data.parentId = nodeInfo.value.id
|
|
|
+// data.deviceId = props.deviceId
|
|
|
+// await InfoClassifyApi.IotInfoClassifyApi.createIotInfoClassify(data)
|
|
|
+// message.success(t('common.createSuccess'))
|
|
|
+// } else {
|
|
|
+// await InfoClassifyApi.IotInfoClassifyApi.updateIotInfoClassify(data)
|
|
|
+// message.success(t('common.updateSuccess'))
|
|
|
+// }
|
|
|
+// dialogVisible.value = false
|
|
|
+//
|
|
|
+// } finally {
|
|
|
+// await getTree()
|
|
|
+// formLoading.value = false
|
|
|
+// }
|
|
|
+// }
|
|
|
+
|
|
|
+/** 重置表单 */
|
|
|
+const resetForm = () => {
|
|
|
+ formData.value = {
|
|
|
+ id: undefined,
|
|
|
+ title: '',
|
|
|
+ parentId: undefined,
|
|
|
+ name: undefined,
|
|
|
+ sort: undefined,
|
|
|
+ leaderUserId: undefined,
|
|
|
+ phone: undefined,
|
|
|
+ email: undefined,
|
|
|
+ status: CommonStatusEnum.ENABLE
|
|
|
+ }
|
|
|
+ formRef.value?.resetFields()
|
|
|
+}
|
|
|
+defineOptions({ name: 'IotTree' })
|
|
|
+const props = defineProps({
|
|
|
+ deviceId: { type: Number, required: true }
|
|
|
+})
|
|
|
+const deptName = ref('')
|
|
|
+const nodeInfo = ref({})
|
|
|
+const treeList = ref<Tree[]>([]) // 树形结构
|
|
|
+const treeRef = ref<InstanceType<typeof ElTree>>()
|
|
|
+const menuVisible = ref(false)
|
|
|
+const menuX = ref(0)
|
|
|
+const menuY = ref(0)
|
|
|
+const contextMenuRef = ref(null) // 弹窗DOM引用
|
|
|
+let selectedNode = null
|
|
|
+const handleRightClick = (event, node, data) => {
|
|
|
+ nodeInfo.value = node;
|
|
|
+ console.log(JSON.stringify(nodeInfo.value))
|
|
|
+ event.preventDefault()
|
|
|
+ menuX.value = event.clientX
|
|
|
+ menuY.value = event.clientY
|
|
|
+ selectedNode = data
|
|
|
+ menuVisible.value = true
|
|
|
+}
|
|
|
+
|
|
|
+// const handleMenuClick = async (action) => {
|
|
|
+// switch (action) {
|
|
|
+// case 'add':
|
|
|
+// dialogVisible.value = true
|
|
|
+// dialogTitle.value = '新增资料分类'
|
|
|
+// formType.value = 'create'
|
|
|
+// resetForm()
|
|
|
+// break
|
|
|
+// case 'edit':
|
|
|
+// resetForm()
|
|
|
+// dialogVisible.value = true
|
|
|
+// dialogTitle.value = '编辑资料分类'
|
|
|
+// formType.value = 'update'
|
|
|
+// formData.value = nodeInfo.value
|
|
|
+// console.log(JSON.stringify(formData.value))
|
|
|
+// break
|
|
|
+// case 'delete':
|
|
|
+// // 删除的二次确认
|
|
|
+// await message.delConfirm()
|
|
|
+// // 发起删除
|
|
|
+// await IotInfoClassifyApi.deleteIotInfoClassify(nodeInfo.value.id)
|
|
|
+// message.success(t('common.delSuccess'))
|
|
|
+// // 刷新列表
|
|
|
+// await getTree()
|
|
|
+// break
|
|
|
+// }
|
|
|
+// menuVisible.value = false
|
|
|
+// }
|
|
|
+/** 获得部门树 */
|
|
|
+const getTree = async () => {
|
|
|
+ debugger
|
|
|
+ const res = await IotTreeApi.getSimpleTreeList()
|
|
|
+ treeList.value = []
|
|
|
+ treeList.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 }) => {
|
|
|
+ console.log(row)
|
|
|
+ emits('node-click', row)
|
|
|
+}
|
|
|
+const emits = defineEmits(['node-click'])
|
|
|
+
|
|
|
+/** 监听deptName */
|
|
|
+watch(deptName, (val) => {
|
|
|
+ treeRef.value!.filter(val)
|
|
|
+})
|
|
|
+// const handleClickOutside = (event) => {
|
|
|
+// if (
|
|
|
+// menuVisible.value &&
|
|
|
+// contextMenuRef.value &&
|
|
|
+// !contextMenuRef.value.contains(event.target)
|
|
|
+// ) {
|
|
|
+// menuVisible.value = false
|
|
|
+// }
|
|
|
+// }
|
|
|
+// watch(menuVisible, (visible) => {
|
|
|
+// if (visible) {
|
|
|
+// document.addEventListener('click', handleClickOutside)
|
|
|
+// } else {
|
|
|
+// document.removeEventListener('click', handleClickOutside)
|
|
|
+// }
|
|
|
+// })
|
|
|
+// onBeforeUnmount(() => {
|
|
|
+// document.removeEventListener('click', handleClickOutside)
|
|
|
+// })
|
|
|
+/** 初始化 */
|
|
|
+onMounted(async () => {
|
|
|
+ await getTree()
|
|
|
+})
|
|
|
+</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;
|
|
|
+ font-size: 14px;
|
|
|
+ margin: 5px
|
|
|
+}
|
|
|
+.custom-menu li:hover {
|
|
|
+ background: #77a0ec;
|
|
|
+}
|
|
|
+
|
|
|
+</style>
|