You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

287 lines
10 KiB
Vue

9 months ago
<template>
<div class="left-tree-container">
<j-input placeholder="名称" v-model:value="searchValue" @pressEnter="search" @change="searchChange">
<template #suffix>
<AIcon type="SearchOutlined" @click="search" />
</template>
</j-input>
<div v-if="admin" class="add-btn">
<j-button type="primary" @click="addGroup">
新增站点
</j-button>
</div>
<div class="tree">
<j-spin :spinning='loading'>
<j-tree :tree-data="listData" v-if="listData.length" draggable @dragstart="dragstart"
:fieldNames="{ title: 'name', key: 'id', children: 'children' }" blockNode
:selectedKeys="selectedKeys" :default-expanded-keys="defaultExpandedKeys"
:showLine="{ showLeafIcon: false }" :showIcon="true">
<template #title="{ name, data, level, type, positionX }">
<div v-if="selectId === data.id">
<j-input v-model:value="addName" @blur="() => saveGroup(data)" ref="inputRef"
:maxlength="64"></j-input>
</div>
<span v-else class='department-tree-item-content'>
<span class='title' :style="{
width: type === 'root' ? '60px' : (level === 2 ? '80px' : '60px'),
}">
<j-ellipsis>
<AIcon v-if="level === 2 && positionX" type="HeartFilled" />
&nbsp;{{ name }}
</j-ellipsis>
</span>
<span class="func-btns" :style="{
width: type === 'root' ? '145px' : (level === 2 ? '80px' : '100px'),
}" @click="(e) => e.stopPropagation()">
<PermissionButton hasPermission="system/Role:groupUpdate" type="link"
:tooltip="{ title: '编辑' }" @click="editGroup(data)">
<AIcon type="EditOutlined" />
</PermissionButton>
<PermissionButton v-if="level == 1" hasPermission="system/Role:groupUpdate" type="link"
:tooltip="{ title: '新增子站' }">
<AIcon type="PlusOutlined" />
</PermissionButton>
<PermissionButton v-if="level == 1" hasPermission="system/Role:groupUpdate" type="link"
:tooltip="{ title: '新增子监测点' }">
<AIcon type="PlusCircleOutlined" />
</PermissionButton>
<PermissionButton hasPermission="system/Role:groupUpdate" type="link"
:tooltip="{ title: '删除' }" :popConfirm="{
title: `确定要删除吗`,
onConfirm: () => { },
}">
<AIcon type="DeleteOutlined" />
</PermissionButton>
<PermissionButton v-if="level == 2" hasPermission="system/Role:groupUpdate" type="link"
:tooltip="{ title: '移除' }">
<AIcon type="CloseOutlined" />
</PermissionButton>
<PermissionButton v-if="type === 'root'" hasPermission="system/Role:groupUpdate"
type="link" :tooltip="{ title: '导入excel' }">
<AIcon type="UploadOutlined" />
</PermissionButton>
<PermissionButton v-if="type === 'root'" hasPermission="system/Role:groupUpdate"
type="link" :tooltip="{ title: '导出excel' }">
<AIcon type="DownloadOutlined" />
</PermissionButton>
</span>
</span>
</template>
</j-tree>
<j-empty v-else description="暂无数据" />
</j-spin>
</div>
</div>
</template>
<script lang="ts" setup>
import { onlyMessage } from '@/utils/comm';
import { useUserInfo } from '@/store/userInfo';
import { storeToRefs } from 'pinia';
import { filterTreeItem } from '@/utils/comm'
const loading = ref<boolean>(false); // 数据加载状态
const emit = defineEmits(['selectData']);
const props = defineProps({
listData: {
type: Array,
default: []
}
})
const userInfoStore = useUserInfo();
const { userInfos } = storeToRefs(userInfoStore);
const admin = computed(() => {
return userInfos.value?.username === 'admin';
});
const selectedKeys = ref<string[]>(['global_role']);
const searchValue = ref();
const inputRef = ref();
const addName = ref();
const selectId = ref();
const mapMonitorList = ref();
const defaultExpandedKeys = ref<(number | string)[]>([]);
const dragstart = ({ event, node }: { event: DragEvent, node: any }) => {
// console.log("🚀 node:", node)
//event.preventDefault()
event.dataTransfer?.setData('monitorData', JSON.stringify(node.dataRef)); // 使用 text/plain 类型存储节点信息
}
//获取全部id
const getTreeId = <T>(treeNode: T[]) => {
let result: any[] = [];
const traverse = (node: any) => {
result?.push(node.id)
if (node.children && Array.isArray(node.children)) {
node.children.forEach((child: any) => traverse(child))
}
}
treeNode?.forEach((child: any) => traverse(child))
return result
}
defaultExpandedKeys.value = getTreeId(props.listData)
const queryGroup = async (select?: Boolean, searchName?: string) => {
// const params = searchName
// ? {
// sorts: [{ name: 'createTime', order: 'desc' }],
// terms: [
// {
// terms: [
// {
// value: '%' + searchName + '%',
// termType: 'like',
// column: 'name',
// },
// ],
// },
// ],
// }
// : { sorts: [{ name: 'createTime', order: 'desc' }] };
// const req: any = await queryRoleGroup(params);
// if (req.status === 200) {
// listData.value[0].children = req.result;
// if (req.result[req.result.length - 1].id === 'default_group') {
// req.result.unshift(req.result[req.result.length - 1]);
// req.result.pop();
// }
// // if(req.result.length && select){
// // selectGroup(req.result[0].id)
// // }
// }
};
const addGroup = () => {
// addName.value = '';
// const newId = randomString();
// listData.value[0].children?.splice(1, 0, {
// name: '',
// id: newId,
// });
// selectId.value = newId;
// nextTick(() => {
// inputRef.value.focus();
// });
};
const saveGroup = async (data: any) => {
if (addName.value === '') {
if (data.name === '') {
// listData.value[0].children.splice(1, 1);
}
}
else {
const saveData = {
name: addName.value,
id: data.id,
};
const res = { status: 200 }//await saveRoleGroup(saveData);
if (res.status === 200) {
onlyMessage('操作成功!');
// queryGroup();
} else {
onlyMessage('操作失败!');
}
}
setTimeout(() => {
selectId.value = '';
}, 300);
};
const search = () => {
queryGroup(true, searchValue.value);
};
const searchChange = () => {
if (searchValue.value === '') {
queryGroup();
}
};
const editGroup = (data: any) => {
if (!selectId.value) {
selectId.value = data.id;
addName.value = data.name;
// listData.value[0].children?.forEach((item: any) => {
// if (item.id === data.id) {
// item.edit = true;
// }
// });
nextTick(() => {
inputRef.value.focus();
});
}
};
onMounted(() => {
mapMonitorList.value = filterTreeItem(props.listData, 'children', (i) => i.level == 2 && i.positionX)
});
</script>
<style lang="less" scoped>
.left-tree-container {
display: flex;
height: 100%;
flex-direction: column;
.add-btn {
margin: 24px 0;
:deep(.ant-btn-primary) {
width: 100%;
}
}
:deep(.ant-tree-treenode-disabled){
.ant-tree-node-content-wrapper{
color: rgba(0, 0, 0, 0.55)
}
}
:deep(.ant-tree-treenode) {
width: 100%;
.ant-tree-node-content-wrapper {
flex: 1 1 auto;
.ant-tree-title {
&:hover {
.func-btns {
display: block;
}
}
}
}
}
.tree {
overflow-y: auto;
overflow-x: auto;
flex: 1 1 auto;
.department-tree-item-content {
display: inline-flex;
align-items: stretch;
.title {
flex: 1;
margin-right: 80px;
}
.func-btns {
display: none;
font-size: 14px;
width: 100px;
margin-left: -80px;
:deep(.ant-btn-link) {
padding: 0 4px;
height: 24px;
}
}
}
.loading {
display: flex;
width: 100%;
justify-content: center;
margin-top: 20px;
}
}
}
</style>