|
@@ -13,97 +13,125 @@
|
|
:expand-on-click-node="false"
|
|
:expand-on-click-node="false"
|
|
:filter-node-method="filterNode"
|
|
:filter-node-method="filterNode"
|
|
:props="defaultProps"
|
|
:props="defaultProps"
|
|
- :default-expanded-keys="firstLevelKeys"
|
|
|
|
- highlight-current
|
|
|
|
- node-key="id"
|
|
|
|
- @node-click="handleNodeClick"
|
|
|
|
- @node-contextmenu="handleRightClick"
|
|
|
|
- style="height: 52em"
|
|
|
|
|
|
+ :default-expanded-keys="expandedKeys"
|
|
|
|
+ highlight-current
|
|
|
|
+ node-key="id"
|
|
|
|
+ @node-click="handleNodeClick"
|
|
|
|
+ @node-contextmenu="handleRightClick"
|
|
|
|
+ style="height: 52em"
|
|
>
|
|
>
|
|
- <template #default="{ node }">
|
|
|
|
- <div
|
|
|
|
- style="display: flex; justify-content: space-between; align-items: center; width: 100%"
|
|
|
|
- >
|
|
|
|
- <div>
|
|
|
|
- <Icon
|
|
|
|
- style="vertical-align: middle;fill: currentColor;color: orange"
|
|
|
|
- v-if="node.data.type === 'dept'"
|
|
|
|
- icon="fa:folder-open"
|
|
|
|
- />
|
|
|
|
- <Icon
|
|
|
|
- style="vertical-align: middle;fill: currentColor;color:orange"
|
|
|
|
- v-if="node.data.type === 'device'"
|
|
|
|
- icon="fa:folder-open"
|
|
|
|
- />
|
|
|
|
- <Icon icon="fa:folder-open" v-if="node.data.type === 'file'" style="vertical-align: middle;color: orange;fill: currentColor;"/>
|
|
|
|
- <!-- 文件夹图标 -->
|
|
|
|
- <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>-->
|
|
|
|
|
|
+ <template #default="{ node }">
|
|
|
|
+ <div
|
|
|
|
+ style="display: flex; justify-content: space-between; align-items: center; width: 100%"
|
|
|
|
+ >
|
|
|
|
+ <div>
|
|
|
|
+ <Icon
|
|
|
|
+ style="vertical-align: middle;fill: currentColor;color: orange"
|
|
|
|
+ v-if="node.data.type === 'dept'"
|
|
|
|
+ icon="fa:folder-open"
|
|
|
|
+ />
|
|
|
|
+ <Icon
|
|
|
|
+ style="vertical-align: middle;fill: currentColor;color:orange"
|
|
|
|
+ v-if="node.data.type === 'device'"
|
|
|
|
+ icon="fa:folder-open"
|
|
|
|
+ />
|
|
|
|
+ <Icon icon="fa:folder-open" v-if="node.data.type === 'file'" style="vertical-align: middle;color: orange;fill: currentColor;"/>
|
|
|
|
+ <span style="vertical-align: middle; margin-left: 3px">{{ node.data.name }}</span>
|
|
</div>
|
|
</div>
|
|
- </template>
|
|
|
|
|
|
+ </div>
|
|
|
|
+ </template>
|
|
</el-tree>
|
|
</el-tree>
|
|
</div>
|
|
</div>
|
|
<div v-show="deviceVisible" ref="contextMenuRef" class="custom-menu" :style="{ left: menuX + 'px', top: menuY + 'px' }">
|
|
<div v-show="deviceVisible" ref="contextMenuRef" class="custom-menu" :style="{ left: menuX + 'px', top: menuY + 'px' }">
|
|
<ul>
|
|
<ul>
|
|
<li style="border-bottom: 1px solid #ccc;" @click="handleDeviceClick('add')">设备详情</li>
|
|
<li style="border-bottom: 1px solid #ccc;" @click="handleDeviceClick('add')">设备详情</li>
|
|
|
|
+ <li style="border-bottom: 0px solid #ccc;" @click="handleMenuClick('add')">新建目录</li>
|
|
</ul>
|
|
</ul>
|
|
</div>
|
|
</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>
|
|
|
|
|
|
+ <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>
|
|
</template>
|
|
|
|
|
|
<script lang="ts" setup>
|
|
<script lang="ts" setup>
|
|
import { ElTree } from 'element-plus'
|
|
import { ElTree } from 'element-plus'
|
|
import { defaultProps, handleTree } from '@/utils/tree'
|
|
import { defaultProps, handleTree } from '@/utils/tree'
|
|
import { CommonStatusEnum } from '@/utils/constants'
|
|
import { CommonStatusEnum } from '@/utils/constants'
|
|
-// import {IotInfoClassifyApi} from "@/api/pms/info";
|
|
|
|
import { IotTreeApi } from '@/api/system/tree'
|
|
import { IotTreeApi } from '@/api/system/tree'
|
|
-import { Folder } from '@element-plus/icons-vue'
|
|
|
|
-import {flatten} from "min-dash";
|
|
|
|
|
|
+import { nextTick, onMounted, onUnmounted, ref, watch } from 'vue'
|
|
|
|
+import { useI18n } from 'vue-i18n'
|
|
|
|
+import { useRouter } from 'vue-router'
|
|
|
|
+import {IotInfoClassifyApi} from "@/api/pms/info";
|
|
|
|
+
|
|
|
|
+// 类型定义
|
|
|
|
+interface Tree {
|
|
|
|
+ id: number | string
|
|
|
|
+ name: string
|
|
|
|
+ type: string
|
|
|
|
+ children?: Tree[]
|
|
|
|
+ [key: string]: any
|
|
|
|
+}
|
|
|
|
|
|
const { t } = useI18n() // 国际化
|
|
const { t } = useI18n() // 国际化
|
|
const message = useMessage() // 消息弹窗
|
|
const message = useMessage() // 消息弹窗
|
|
const dialogVisible = ref(false) // 弹窗的是否展示
|
|
const dialogVisible = ref(false) // 弹窗的是否展示
|
|
const dialogTitle = ref('') // 弹窗的标题
|
|
const dialogTitle = ref('') // 弹窗的标题
|
|
const formRef = ref() // 搜索的表单
|
|
const formRef = ref() // 搜索的表单
|
|
-const firstLevelKeys = ref([])
|
|
|
|
|
|
+const firstLevelKeys = ref<(number | string)[]>([])
|
|
|
|
+const expandedKeys = ref<(number | string)[]>([]) // 用于展开节点的路径
|
|
|
|
+
|
|
|
|
+// 表单相关
|
|
|
|
+const formLoading = ref(false)
|
|
|
|
+const formType = ref<'create' | 'update'>('create')
|
|
|
|
+const formData = ref({
|
|
|
|
+ id: undefined,
|
|
|
|
+ title: '',
|
|
|
|
+ parentId: undefined,
|
|
|
|
+ name: undefined,
|
|
|
|
+ sort: undefined,
|
|
|
|
+ leaderUserId: undefined,
|
|
|
|
+ phone: undefined,
|
|
|
|
+ email: undefined,
|
|
|
|
+ status: CommonStatusEnum.ENABLE
|
|
|
|
+})
|
|
|
|
+const formRules = ref({
|
|
|
|
+ name: [{ required: true, message: '请输入名称', trigger: 'blur' }],
|
|
|
|
+ sort: [{ required: true, message: '请输入排序', trigger: 'blur' }]
|
|
|
|
+})
|
|
|
|
+
|
|
const openForm = (type: string, id?: number) => {
|
|
const openForm = (type: string, id?: number) => {
|
|
formRef.value.open(type, id)
|
|
formRef.value.open(type, id)
|
|
}
|
|
}
|
|
@@ -123,10 +151,15 @@ const resetForm = () => {
|
|
}
|
|
}
|
|
formRef.value?.resetFields()
|
|
formRef.value?.resetFields()
|
|
}
|
|
}
|
|
|
|
+
|
|
defineOptions({ name: 'IotTree' })
|
|
defineOptions({ name: 'IotTree' })
|
|
|
|
+
|
|
|
|
+// 接收外部参数
|
|
const props = defineProps({
|
|
const props = defineProps({
|
|
- deviceId: { type: Number, required: true }
|
|
|
|
|
|
+ deviceId: { type: Number, required: true },
|
|
|
|
+ currentId: { type: [Number, String], default: null } // 新增:接收需要定位的节点ID
|
|
})
|
|
})
|
|
|
|
+
|
|
const deptName = ref('')
|
|
const deptName = ref('')
|
|
const nodeInfo = ref({})
|
|
const nodeInfo = ref({})
|
|
const treeList = ref<Tree[]>([]) // 树形结构
|
|
const treeList = ref<Tree[]>([]) // 树形结构
|
|
@@ -137,9 +170,10 @@ const menuX = ref(0)
|
|
const menuY = ref(0)
|
|
const menuY = ref(0)
|
|
const contextMenuRef = ref(null) // 弹窗DOM引用
|
|
const contextMenuRef = ref(null) // 弹窗DOM引用
|
|
let selectedNode = null
|
|
let selectedNode = null
|
|
-
|
|
|
|
|
|
+const parentId = ref()
|
|
|
|
|
|
const { push } = useRouter() // 路由跳转
|
|
const { push } = useRouter() // 路由跳转
|
|
|
|
+
|
|
// 动态高度计算
|
|
// 动态高度计算
|
|
const treeContainer = ref(null)
|
|
const treeContainer = ref(null)
|
|
const setHeight = () => {
|
|
const setHeight = () => {
|
|
@@ -149,6 +183,48 @@ const setHeight = () => {
|
|
treeContainer.value.style.height = `${windowHeight * 0.78}px` // 60px 底部预留
|
|
treeContainer.value.style.height = `${windowHeight * 0.78}px` // 60px 底部预留
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+// 新增:查找节点路径的递归方法
|
|
|
|
+const findNodePath = (nodes: Tree[], targetId: number | string, path: (number | string)[] = []): (number | string)[] | null => {
|
|
|
|
+ for (const node of nodes) {
|
|
|
|
+ path.push(node.id)
|
|
|
|
+ if (node.id === targetId) {
|
|
|
|
+ return [...path]
|
|
|
|
+ }
|
|
|
|
+ if (node.children && node.children.length) {
|
|
|
|
+ const result = findNodePath(node.children, targetId, path)
|
|
|
|
+ if (result) {
|
|
|
|
+ return result
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ path.pop()
|
|
|
|
+ }
|
|
|
|
+ return null
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// 新增:定位节点并高亮
|
|
|
|
+const locateNode = (targetId: number | string) => {
|
|
|
|
+ if (!targetId || !treeList.value.length) return
|
|
|
|
+
|
|
|
|
+ const pathIds = findNodePath(treeList.value, targetId)
|
|
|
|
+ if (pathIds) {
|
|
|
|
+ // 展开所有父节点
|
|
|
|
+ expandedKeys.value = pathIds.slice(0, -1)
|
|
|
|
+
|
|
|
|
+ // 等待DOM更新后设置当前节点
|
|
|
|
+ nextTick(() => {
|
|
|
|
+ if (treeRef.value) {
|
|
|
|
+ treeRef.value.setCurrentKey(targetId)
|
|
|
|
+
|
|
|
|
+ // 滚动到节点位置
|
|
|
|
+ const node = treeRef.value.getNode(targetId)
|
|
|
|
+ if (node && node.$el) {
|
|
|
|
+ node.$el.scrollIntoView({ behavior: 'smooth', block: 'nearest' })
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ })
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
onMounted(async () => {
|
|
onMounted(async () => {
|
|
await getTreeInfo()
|
|
await getTreeInfo()
|
|
setHeight()
|
|
setHeight()
|
|
@@ -161,11 +237,12 @@ onUnmounted(() => {
|
|
|
|
|
|
const handleRightClick = (event, node, data) => {
|
|
const handleRightClick = (event, node, data) => {
|
|
nodeInfo.value = node
|
|
nodeInfo.value = node
|
|
- console.log(JSON.stringify(nodeInfo.value))
|
|
|
|
event.preventDefault()
|
|
event.preventDefault()
|
|
menuX.value = event.clientX
|
|
menuX.value = event.clientX
|
|
menuY.value = event.clientY
|
|
menuY.value = event.clientY
|
|
selectedNode = data
|
|
selectedNode = data
|
|
|
|
+ debugger
|
|
|
|
+ parentId.value = data.data.id
|
|
if (nodeInfo.value.type === 'device') {
|
|
if (nodeInfo.value.type === 'device') {
|
|
deviceVisible.value = true
|
|
deviceVisible.value = true
|
|
} else if (nodeInfo.value.type === 'file') {
|
|
} else if (nodeInfo.value.type === 'file') {
|
|
@@ -177,44 +254,52 @@ const handleDeviceClick = async () => {
|
|
const id = nodeInfo.value.originId
|
|
const id = nodeInfo.value.originId
|
|
push({ name: 'DeviceDetailInfo', params: { id } })
|
|
push({ name: 'DeviceDetailInfo', params: { id } })
|
|
deviceVisible.value = false
|
|
deviceVisible.value = false
|
|
|
|
+ menuVisible.value = false
|
|
}
|
|
}
|
|
|
|
|
|
-
|
|
|
|
const handleMenuClick = async (action) => {
|
|
const handleMenuClick = async (action) => {
|
|
switch (action) {
|
|
switch (action) {
|
|
case 'add':
|
|
case 'add':
|
|
dialogVisible.value = true
|
|
dialogVisible.value = true
|
|
- dialogTitle.value = '新增资料分类'
|
|
|
|
|
|
+ dialogTitle.value = '新增目录'
|
|
formType.value = 'create'
|
|
formType.value = 'create'
|
|
resetForm()
|
|
resetForm()
|
|
break
|
|
break
|
|
case 'edit':
|
|
case 'edit':
|
|
resetForm()
|
|
resetForm()
|
|
dialogVisible.value = true
|
|
dialogVisible.value = true
|
|
- dialogTitle.value = '编辑资料分类'
|
|
|
|
|
|
+ dialogTitle.value = '编辑目录'
|
|
formType.value = 'update'
|
|
formType.value = 'update'
|
|
- formData.value = nodeInfo.value
|
|
|
|
- console.log(JSON.stringify(formData.value))
|
|
|
|
|
|
+ formData.value = { ...nodeInfo.value }
|
|
break
|
|
break
|
|
case 'delete':
|
|
case 'delete':
|
|
// 删除的二次确认
|
|
// 删除的二次确认
|
|
await message.delConfirm()
|
|
await message.delConfirm()
|
|
- // 发起删除
|
|
|
|
- await IotInfoClassifyApi.deleteIotInfoClassify(nodeInfo.value.id)
|
|
|
|
|
|
+ // 假设存在删除接口
|
|
|
|
+ await IotTreeApi.deleteIotTree(nodeInfo.value.id)
|
|
message.success(t('common.delSuccess'))
|
|
message.success(t('common.delSuccess'))
|
|
// 刷新列表
|
|
// 刷新列表
|
|
- await getTree()
|
|
|
|
|
|
+ await getTreeInfo()
|
|
break
|
|
break
|
|
}
|
|
}
|
|
|
|
+ deviceVisible.value = false
|
|
menuVisible.value = false
|
|
menuVisible.value = false
|
|
}
|
|
}
|
|
|
|
+
|
|
/** 获得部门树 */
|
|
/** 获得部门树 */
|
|
const getTreeInfo = async () => {
|
|
const getTreeInfo = async () => {
|
|
const res = await IotTreeApi.getSimpleTreeList()
|
|
const res = await IotTreeApi.getSimpleTreeList()
|
|
treeList.value = []
|
|
treeList.value = []
|
|
treeList.value.push(...handleTree(res))
|
|
treeList.value.push(...handleTree(res))
|
|
- firstLevelKeys.value = treeList.value.map(node => node.id);
|
|
|
|
- emits('success', treeList.value[0].id)
|
|
|
|
|
|
+
|
|
|
|
+ // 处理展开逻辑:有currentId则展开对应路径,否则展开一级节点
|
|
|
|
+ if (props.currentId) {
|
|
|
|
+ locateNode(props.currentId)
|
|
|
|
+ } else {
|
|
|
|
+ firstLevelKeys.value = treeList.value.map(node => node.id)
|
|
|
|
+ expandedKeys.value = [...firstLevelKeys.value]
|
|
|
|
+ }
|
|
|
|
+ emits('success', treeList.value[0]?.id)
|
|
}
|
|
}
|
|
|
|
|
|
/** 基于名字过滤 */
|
|
/** 基于名字过滤 */
|
|
@@ -223,42 +308,61 @@ const filterNode = (name: string, data: Tree) => {
|
|
return data.name.includes(name)
|
|
return data.name.includes(name)
|
|
}
|
|
}
|
|
|
|
|
|
-/** 处理部门被点击 */
|
|
|
|
|
|
+/** 处理节点被点击 */
|
|
const handleNodeClick = async (row: { [key: string]: any }) => {
|
|
const handleNodeClick = async (row: { [key: string]: any }) => {
|
|
deviceVisible.value = false
|
|
deviceVisible.value = false
|
|
menuVisible.value = false
|
|
menuVisible.value = false
|
|
emits('node-click', row)
|
|
emits('node-click', row)
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+/** 提交表单 */
|
|
|
|
+const submitForm = async () => {
|
|
|
|
+ // 表单验证逻辑
|
|
|
|
+ formLoading.value = true
|
|
|
|
+ try {
|
|
|
|
+ // 假设存在提交接口
|
|
|
|
+ formData.value.deviceId = props.deviceId
|
|
|
|
+ debugger
|
|
|
|
+ formData.value.parentId = parentId.value
|
|
|
|
+ if (formData.value.parentId===undefined||formData.value.parentId===null) {
|
|
|
|
+ formData.value.parentId = props.currentId
|
|
|
|
+ }
|
|
|
|
+ formData.value.type = 'file'
|
|
|
|
+ if (formType.value === 'create') {
|
|
|
|
+ debugger
|
|
|
|
+ await IotTreeApi.createIotTree(formData.value)
|
|
|
|
+ } else {
|
|
|
|
+ await IotTreeApi.updateIotTree(formData.value)
|
|
|
|
+ }
|
|
|
|
+ message.success(t(formType.value === 'create' ? 'common.addSuccess' : 'common.updateSuccess'))
|
|
|
|
+ dialogVisible.value = false
|
|
|
|
+ await getTreeInfo()
|
|
|
|
+ } catch (error) {
|
|
|
|
+ console.error(error)
|
|
|
|
+ } finally {
|
|
|
|
+ formLoading.value = false
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
const emits = defineEmits(['node-click', 'success'])
|
|
const emits = defineEmits(['node-click', 'success'])
|
|
|
|
|
|
-/** 监听deptName */
|
|
|
|
|
|
+/** 监听搜索框变化 */
|
|
watch(deptName, (val) => {
|
|
watch(deptName, (val) => {
|
|
treeRef.value!.filter(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 getTreeInfo()
|
|
|
|
-// })
|
|
|
|
|
|
+
|
|
|
|
+/** 监听currentId变化,重新定位 */
|
|
|
|
+watch(
|
|
|
|
+ () => props.currentId,
|
|
|
|
+ (newVal) => {
|
|
|
|
+ if (newVal && treeList.value.length) {
|
|
|
|
+ locateNode(newVal)
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ { immediate: true }
|
|
|
|
+)
|
|
</script>
|
|
</script>
|
|
|
|
+
|
|
<style lang="scss" scoped>
|
|
<style lang="scss" scoped>
|
|
.custom-menu {
|
|
.custom-menu {
|
|
position: fixed;
|
|
position: fixed;
|
|
@@ -287,7 +391,7 @@ watch(deptName, (val) => {
|
|
border: 1px solid #e4e7ed;
|
|
border: 1px solid #e4e7ed;
|
|
border-radius: 4px;
|
|
border-radius: 4px;
|
|
}
|
|
}
|
|
-/* 自定义滚动条(可选) */
|
|
|
|
|
|
+/* 自定义滚动条 */
|
|
.tree-container::-webkit-scrollbar {
|
|
.tree-container::-webkit-scrollbar {
|
|
width: 6px;
|
|
width: 6px;
|
|
}
|
|
}
|
|
@@ -295,4 +399,11 @@ watch(deptName, (val) => {
|
|
background: #c0c4cc;
|
|
background: #c0c4cc;
|
|
border-radius: 3px;
|
|
border-radius: 3px;
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+/* 自定义高亮样式 */
|
|
|
|
+::v-deep .el-tree--highlight-current .el-tree-node.is-current > .el-tree-node__content {
|
|
|
|
+ background-color: #eaf5ff !important;
|
|
|
|
+ color: #1890ff !important;
|
|
|
|
+ font-weight: bold;
|
|
|
|
+}
|
|
</style>
|
|
</style>
|