235 lines
6.6 KiB
Vue
235 lines
6.6 KiB
Vue
<template>
|
|
<a-card class="full_height" :bordered="false">
|
|
<template #title>
|
|
<div class="card-title_between">
|
|
<p>
|
|
<icon-drag-arrow />
|
|
<span class="title" style="margin-left: 15px">{{
|
|
$t('organization')
|
|
}}</span>
|
|
</p>
|
|
<a-button type="primary" @click="handleAdd">
|
|
<template #icon>
|
|
<icon-plus />
|
|
</template>
|
|
{{ $t('add-department') }}
|
|
</a-button>
|
|
</div>
|
|
</template>
|
|
<a-row :gutter="12">
|
|
<a-col class="border" :span="12">
|
|
<a-tree
|
|
v-model:expanded-keys="expandedKeys"
|
|
:field-names="{ key: 'id', title: 'name' }"
|
|
:data="departmentListData"
|
|
@select="onSelect"
|
|
>
|
|
<template #icon>
|
|
<IconStar />
|
|
</template>
|
|
<template #extra="nodeData">
|
|
<a-row
|
|
v-if="nodeData.isShowEditIcon"
|
|
style="position: absolute; right: 0"
|
|
:gutter="24"
|
|
>
|
|
<a-col :span="4" @click="handleEdit"><icon-edit /></a-col>
|
|
<a-col :span="4">
|
|
<a-popconfirm
|
|
:ok-text="t('cancel')"
|
|
:cancel-text="t('delete')"
|
|
:ok-button-props="{ type: 'outline' }"
|
|
:cancel-button-props="{ type: 'primary', status: 'danger' }"
|
|
:content="
|
|
t('please.confirm.delete.some', { name: t('department') })
|
|
"
|
|
type="error"
|
|
@cancel="handleDelete(nodeData)"
|
|
>
|
|
<icon-delete />
|
|
</a-popconfirm>
|
|
</a-col>
|
|
<a-col :span="4" @click="handleMoveUp(nodeData)"
|
|
><icon-up
|
|
/></a-col>
|
|
<a-col :span="4" @click="handleMoveDown(nodeData)"
|
|
><icon-down
|
|
/></a-col>
|
|
</a-row>
|
|
</template>
|
|
</a-tree>
|
|
</a-col>
|
|
<a-col :span="12">
|
|
<a-descriptions
|
|
v-if="departmentDetailInfo"
|
|
:column="1"
|
|
layout="horizontal"
|
|
bordered
|
|
>
|
|
<a-descriptions-item :label="t('department-name')">
|
|
{{ departmentDetailInfo.name }}</a-descriptions-item
|
|
>
|
|
<a-descriptions-item :label="t('belongto-department')">
|
|
{{ departmentDetailInfo.parentName || '-' }}</a-descriptions-item
|
|
>
|
|
<a-descriptions-item :label="t('department-head')">
|
|
{{ departmentDetailInfo.username || '-' }}</a-descriptions-item
|
|
>
|
|
<a-descriptions-item :label="t('department-desc')">
|
|
{{ departmentDetailInfo.remark }}</a-descriptions-item
|
|
>
|
|
</a-descriptions>
|
|
</a-col>
|
|
</a-row>
|
|
<departmentFormModal
|
|
v-model:visible="showModal"
|
|
:department-list-data="departmentListData"
|
|
:record="departmentDetailInfo"
|
|
:user-list-data="allUserList"
|
|
:is-edit="isEdit"
|
|
@submitted="getDepartmentListData"
|
|
/>
|
|
</a-card>
|
|
</template>
|
|
|
|
<script lang="ts" setup>
|
|
import { reactive, ref, watch, onMounted } from 'vue';
|
|
import { useI18n } from 'vue-i18n';
|
|
import useDepartmentList from '@/views/setting/composables/useDepartmentList';
|
|
import {
|
|
DepartmentItem,
|
|
getAllUserList,
|
|
UserList,
|
|
departmentSetUp,
|
|
departmentSetDown,
|
|
delDepartment,
|
|
} from '@/api/setting';
|
|
import { debounce } from '@/utils';
|
|
import { Message } from '@arco-design/web-vue';
|
|
import departmentFormModal from './components/department-form-modal.vue';
|
|
|
|
const {
|
|
departmentListData,
|
|
allDepartmentKeys,
|
|
getDepartmentListData,
|
|
getDepartmentDetailData,
|
|
} = useDepartmentList();
|
|
const emit = defineEmits(['onSelectTree']);
|
|
const expandedKeys = ref<(string | number)[]>([]);
|
|
const { t } = useI18n();
|
|
watch(
|
|
allDepartmentKeys,
|
|
(val) => {
|
|
expandedKeys.value = val;
|
|
},
|
|
{ immediate: true }
|
|
);
|
|
|
|
const showModal = ref<boolean>(false);
|
|
const isEdit = ref<boolean>(false);
|
|
const departmentDetailInfo = ref<DepartmentItem | null>(null);
|
|
|
|
const resetEditIcon = (nodes: any[]) => {
|
|
nodes.forEach((node) => {
|
|
node.isShowEditIcon = false;
|
|
if (node.children && node.children.length > 0) {
|
|
resetEditIcon(node.children);
|
|
}
|
|
});
|
|
};
|
|
const currentNode = ref<any>(null);
|
|
const onSelect = debounce(async (_: (string | number)[], event: any) => {
|
|
const { node } = event;
|
|
if (node.id === currentNode.value?.id) return;
|
|
currentNode.value = node;
|
|
// 递归重置所有节点的 isShowEditIcon
|
|
resetEditIcon(departmentListData.value);
|
|
// 只设置当前节点
|
|
if (currentNode.value.level !== 1) {
|
|
node.isShowEditIcon = true;
|
|
}
|
|
departmentDetailInfo.value = await getDepartmentDetailData(
|
|
currentNode.value.id
|
|
);
|
|
}, 300);
|
|
|
|
// 所有用户数据
|
|
const allUserList = ref<UserList>([]);
|
|
const userKeyword = ref<string>('');
|
|
|
|
const getAllUserListData = async () => {
|
|
try {
|
|
const { code, data } = await getAllUserList({
|
|
keyword: userKeyword.value,
|
|
});
|
|
if (code === 200 && data?.length) {
|
|
allUserList.value = data;
|
|
}
|
|
} catch (error) {
|
|
console.error('获取所以用户数据失败:', error);
|
|
}
|
|
};
|
|
|
|
const handleAdd = () => {
|
|
showModal.value = true;
|
|
isEdit.value = false;
|
|
};
|
|
const handleEdit = () => {
|
|
showModal.value = true;
|
|
isEdit.value = true;
|
|
};
|
|
const handleDelete = async (item) => {
|
|
const { id } = item;
|
|
try {
|
|
const { code, message } = await delDepartment(id);
|
|
if (code === 200) {
|
|
Message.success(message);
|
|
getDepartmentListData();
|
|
}
|
|
} catch (error) {
|
|
console.log('删除失败:', error);
|
|
}
|
|
};
|
|
|
|
const handleMoveUp = async (item) => {
|
|
const { id } = item;
|
|
try {
|
|
const { code, message } = await departmentSetUp(id);
|
|
if (code === 200) {
|
|
Message.success(message);
|
|
getDepartmentListData();
|
|
} else {
|
|
Message.info(message);
|
|
}
|
|
} catch (error) {
|
|
console.log('向上移动失败:', error);
|
|
}
|
|
};
|
|
const handleMoveDown = async (item) => {
|
|
const { id } = item;
|
|
try {
|
|
const { code, message } = await departmentSetDown(id);
|
|
if (code === 200) {
|
|
Message.success(message);
|
|
getDepartmentListData();
|
|
} else {
|
|
Message.info(message);
|
|
}
|
|
} catch (error) {
|
|
console.log('向下移动失败:', error);
|
|
}
|
|
};
|
|
|
|
onMounted(() => {
|
|
getAllUserListData();
|
|
});
|
|
</script>
|
|
|
|
<style lang="less" scoped>
|
|
.border {
|
|
border: 1px solid #f4f4f4;
|
|
height: 100%;
|
|
padding: 15px 0;
|
|
}
|
|
</style>
|