Files
continew-admin-ui/src/views/system/user/dept/index.vue

226 lines
5.5 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="left-tree">
<div class="left-tree__search">
<a-input v-model="inputValue" :placeholder="props.placeholder" allow-clear>
<template #prefix><icon-search /></template>
</a-input>
</div>
<div class="left-tree__container">
<div class="left-tree__tree">
<a-tree
ref="treeRef"
:data="(treeData as unknown as TreeNodeData[])"
:field-names="{ key: 'id' }"
show-line
block-node
default-expand-all
:selected-keys="selectedKeys"
@select="select"
>
<template #title="node">
<a-trigger
v-model:popup-visible="node.popupVisible"
trigger="contextMenu"
align-point
animation-name="slide-dynamic-origin"
auto-fit-transform-origin
position="bl"
scroll-to-close
>
<a-tooltip v-if="node.description" :content="node.description" background-color="rgb(var(--primary-6))" position="right">
<div @contextmenu="onContextmenu(node)">{{ node.name }}</div>
</a-tooltip>
<div v-else @contextmenu="onContextmenu(node)">{{ node.name }}</div>
<template #content>
<RightMenu
v-if="has.hasPermOr(['system:dept:update', 'system:dept:delete'])"
:data="node"
@on-menu-item-click="onMenuItemClick"
/>
</template>
</a-trigger>
</template>
</a-tree>
</div>
</div>
</div>
<DeptAddModal ref="DeptAddModalRef" @save-success="getTreeData" />
</template>
<script setup lang="tsx">
import type { Message, Modal, TreeInstance, TreeNodeData } from '@arco-design/web-vue'
import { mapTree } from 'xe-utils'
import DeptAddModal from '../../dept/DeptAddModal.vue'
import RightMenu from './RightMenu.vue'
import { type DeptQuery, type DeptResp, deleteDept, listDept } from '@/apis'
import has from '@/utils/has'
interface Props {
placeholder?: string
}
const props = withDefaults(defineProps<Props>(), {
placeholder: '请输入关键词'
})
const emit = defineEmits<{
(e: 'node-click', keys: Array<any>): void
}>()
// 选中节点
const selectedKeys = ref()
const select = (keys: Array<any>) => {
selectedKeys.value = keys
emit('node-click', keys)
}
const queryForm = reactive<DeptQuery>({
sort: ['parentId,asc', 'sort,asc', 'createTime,desc']
})
interface TreeItem extends DeptResp {
popupVisible: boolean
}
const treeRef = ref<TreeInstance>()
const treeData = ref<TreeItem[]>([])
const loading = ref(false)
// 查询树列表
const getTreeData = async (query: DeptQuery = { ...queryForm }) => {
try {
loading.value = true
const { data } = await listDept(query)
treeData.value = mapTree(data, (i) => ({
...i,
popupVisible: false,
switcherIcon: (node: any) => {
if (!node.isLeaf) {
if (node.expanded) {
return <icon-down />
} else {
return <icon-down />
}
}
return <icon-idcard />
}
}))
await nextTick(() => {
treeRef.value?.expandAll(true)
select([data[0].id])
})
} finally {
loading.value = false
}
}
// 树查询
const inputValue = ref('')
watch(inputValue, (val) => {
queryForm.description = val
getTreeData()
})
// 保存当前右键的节点
const contextmenuNode = ref<TreeItem | null>(null)
const onContextmenu = (node: TreeItem) => {
contextmenuNode.value = node
}
// 关闭右键菜单弹框
const closeRightMenuPopup = () => {
if (contextmenuNode.value?.popupVisible) {
contextmenuNode.value.popupVisible = false
}
}
const DeptAddModalRef = ref<InstanceType<typeof DeptAddModal>>()
// 右键菜单项点击
const onMenuItemClick = (mode: string, node: DeptResp) => {
closeRightMenuPopup()
if (mode === 'add') {
DeptAddModalRef.value?.onAdd(node.id)
} else if (mode === 'update') {
DeptAddModalRef.value?.onUpdate(node.id)
} else if (mode === 'delete') {
Modal.warning({
title: '提示',
content: `是否确定删除 [${node.name}]`,
hideCancel: false,
okButtonProps: { status: 'danger' },
onBeforeOk: async () => {
try {
const res = await deleteDept(node.id)
if (res.success) {
Message.success('删除成功')
getTreeData()
}
return res.success
} catch (error) {
return false
}
}
})
}
}
onMounted(() => {
getTreeData()
})
</script>
<style lang="scss" scoped>
:deep(.arco-tree-node-title-text) {
width: 100%;
white-space: nowrap;
}
:deep(.arco-tree-node) {
line-height: normal;
.arco-tree-node-title {
border-radius: var(--border-radius-medium);
&:hover {
background-color: var(--color-secondary-hover);
}
}
}
:deep(.arco-tree-node-selected) {
.arco-tree-node-title {
background-color: rgba(var(--primary-6), 0.1);
&:hover {
background-color: rgba(var(--primary-6), 0.1);
}
}
}
.left-tree {
flex: 1;
overflow: hidden;
position: relative;
display: flex;
flex-direction: column;
box-sizing: border-box;
height: 100%;
&__search {
margin-bottom: 10px;
}
&__container {
flex: 1;
overflow: hidden;
background-color: var(--color-bg-1);
position: relative;
height: 100%;
margin-bottom:10px;
}
&__tree {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
overflow: auto
}
}
</style>