feat(部门管理): 新增编辑实现

This commit is contained in:
sheng
2023-07-31 14:49:12 +08:00
committed by 李强
parent 05f4e2970d
commit 7110d10432
6 changed files with 100 additions and 79 deletions

View File

@@ -34,8 +34,8 @@ const route = useRoute();
const stores = useTagsViewRoutes();
const storesThemeConfig = useThemeConfig();
const { themeConfig } = storeToRefs(storesThemeConfig);
import websocket from "/@/utils/websocket";
import { ElNotification } from "element-plus";
import websocket from '/@/utils/websocket';
import { ElNotification } from 'element-plus';
// 获取版本号
const getVersion = computed(() => {
let isVersion = false;
@@ -61,11 +61,10 @@ onBeforeMount(() => {
setIntroduction.jsCdn();
//websockt 模块
try {
websocket.init(wsReceive)
//websocket.init(wsReceive)
} catch (e) {
console.log("websocket错误")
console.log('websocket错误');
}
});
// 页面加载时
onMounted(() => {
@@ -87,7 +86,7 @@ onMounted(() => {
});
// 页面销毁时,关闭监听布局配置/i18n监听
onUnmounted(() => {
mittBus.off('openSetingsDrawer', () => { });
mittBus.off('openSetingsDrawer', () => {});
});
// 监听路由的变化,设置网站标题
watch(
@@ -101,11 +100,11 @@ watch(
);
// websocket相关代码
import { messageCenterStore } from "/@/stores/messageCenter";
import { messageCenterStore } from '/@/stores/messageCenter';
const wsReceive = (message: any) => {
const data = JSON.parse(message.data)
const { unread } = data
const messageCenter = messageCenterStore()
const data = JSON.parse(message.data);
const { unread } = data;
const messageCenter = messageCenterStore();
messageCenter.setUnread(unread);
if (data.contentType === 'SYSTEM') {
ElNotification({
@@ -113,14 +112,12 @@ const wsReceive = (message: any) => {
message: data.content,
type: 'success',
position: 'bottom-right',
duration: 5000
})
duration: 5000,
});
}
}
};
onBeforeUnmount(() => {
// 关闭连接
websocket.close()
})
websocket.close();
});
</script>

View File

@@ -1,9 +1,15 @@
<template>
<el-form ref="formRef" :rules="rules" :model="deptFormData" label-width="100px" label-position="right" class="dept-form-com">
<el-form-item label="父级部门" prop="parent">
<el-select v-model="deptFormData.parent" style="width: 100%">
<el-option v-for="item in deptAllList" :key="item.id" :label="item.name" :value="item.id" />
</el-select>
<el-tree-select
v-model="deptFormData.parent"
:props="defaultTreeProps"
:data="deptDefaultList"
lazy
check-strictly
:load="handleTreeLoad"
style="width: 100%"
/>
</el-form-item>
<el-form-item required label="部门名称" prop="name">
<el-input v-model="deptFormData.name" />
@@ -11,14 +17,14 @@
<el-form-item required label="部门标识" prop="key">
<el-input v-model="deptFormData.key" />
</el-form-item>
<el-form-item label="负责人" prop="owner">
<el-form-item label="负责人">
<el-input v-model="deptFormData.owner" />
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="deptFormData.remark" maxlength="200" show-word-limit type="textarea" />
<el-form-item label="备注">
<el-input v-model="deptFormData.description" maxlength="200" show-word-limit type="textarea" />
</el-form-item>
<el-form-item>
<el-button @click="handleUpdateMenu" type="primary" :disabled="deptBtnLoading">
<el-button @click="handleUpdateMenu" type="primary" :loading="deptBtnLoading">
{{ deptFormData.id ? '保存' : '新增' }}
</el-button>
<el-button @click="handleClose">取消 </el-button>
@@ -29,14 +35,29 @@
<script lang="ts" setup>
import { reactive, ref, onMounted } from 'vue';
import { ElForm, FormRules } from 'element-plus';
import { getAllDeptList, AddObj, UpdateObj } from '../api';
import { lazyLoadDept, AddObj, UpdateObj } from '../api';
import { successNotification } from '../../../../utils/message';
import { DeptFormDataType, TreeItemType, DeptListType } from '../types';
import { DeptFormDataType, TreeItemType, APIResponseData } from '../types';
import type Node from 'element-plus/es/components/tree/src/model/node';
interface IProps {
initFormData: TreeItemType | null;
treeData: TreeItemType[];
}
const defaultTreeProps: any = {
children: 'children',
label: 'name',
value: 'id',
isLeaf: (data: TreeItemType[], node: Node) => {
if (node?.data.hasChild) {
return false;
} else {
return true;
}
},
};
const formRef = ref<InstanceType<typeof ElForm>>();
const rules = reactive<FormRules>({
name: [{ required: true, message: '部门名称必填', trigger: 'blur' }],
@@ -45,27 +66,20 @@ const rules = reactive<FormRules>({
const props = withDefaults(defineProps<IProps>(), {
initFormData: () => null,
treeData: () => [],
});
const emit = defineEmits(['drawerClose']);
let deptAllList = ref<DeptListType[]>([]);
let deptDefaultList = ref<TreeItemType[]>([]);
let deptFormData = reactive<DeptFormDataType>({
key: '',
parent: '',
name: '',
owner: '',
remark: '',
is_catalog: true,
description: '',
});
let deptBtnLoading = ref(false);
const getData = async () => {
const res = await getAllDeptList();
if (res?.code === 2000) {
deptAllList.value = res.data;
}
};
const setDeptFormData = () => {
if (props.initFormData?.id) {
deptFormData.id = props.initFormData?.id;
@@ -73,6 +87,15 @@ const setDeptFormData = () => {
deptFormData.parent = props.initFormData.parent || '';
deptFormData.name = props.initFormData.name || '';
deptFormData.owner = props.initFormData.owner || '';
deptFormData.description = props.initFormData.description || '';
}
};
const handleTreeLoad = (node: Node, resolve: Function) => {
if (node.level !== 0) {
lazyLoadDept({ parent: node.data.id }).then((res: APIResponseData) => {
resolve(res.data);
});
}
};
@@ -103,7 +126,9 @@ const handleClose = (type: string = '') => {
};
onMounted(async () => {
await getData();
props.treeData.map((item) => {
deptDefaultList.value.push(item);
});
setDeptFormData();
});
</script>

View File

@@ -12,6 +12,7 @@ export const createCrudOptions = function ({ crudExpose }: CreateCrudOptionsProp
* 处理crud警告Invalid prop: type check failed for prop "name". Expected String with value "2", got Number with value 2.
*/
res.data.forEach((item: any) => {
item.dept = String(item.dept);
if (item.role && Array.isArray(item.role) && item.role.length > 0) {
item.role = item.role.map((r: number) => String(r));
}

View File

@@ -1,6 +1,6 @@
<template>
<el-input v-model="filterVal" :prefix-icon="Search" placeholder="请输入部门名称" />
<div class="tree-com">
<div class="dept-tree-com">
<div class="tc-head">
<el-icon size="16" color="#606266" class="tc-head-icon">
<HomeFilled />
@@ -15,22 +15,21 @@
<el-tree
ref="treeRef"
:data="treeData"
:props="treeProps"
:props="defaultTreeProps"
:filter-node-method="handleFilterTreeNode"
:load="handleLoadNode"
lazy
:indent="38"
@node-click="handleNodeClick"
highlight-current
default-expand-all
>
<template #default="{ node, data }">
<element-tree-line :node="node" :showLabelLine="false" :indent="32">
<span v-if="data.status" class="text-center font-black font-normal">
<SvgIcon name="iconfont icon-shouye" />&nbsp;{{ node.label }}
<span v-show="showTotalNum">10</span>
<SvgIcon name="iconfont icon-shouye" color="var(--el-color-primary)" />&nbsp;{{ node.label }}
<span v-show="showTotalNum">{{ data.dept_user_count }}</span>
</span>
<span v-else class="text-center font-black font-normal text-red-700"> <SvgIcon name="iconfont icon-shouye" />&nbsp;{{ node.label }} </span>
<span v-else color="var(--el-color-primary)"> <SvgIcon name="iconfont icon-shouye" />&nbsp;{{ node.label }} </span>
</element-tree-line>
</template>
</el-tree>
@@ -85,9 +84,16 @@ interface IProps {
const ElementTreeLine = getElementLabelLine(h);
const treeProps = {
const defaultTreeProps: any = {
children: 'children',
label: 'name',
isLeaf: (data: TreeItemType[], node: Node) => {
if (node.data.hasChild) {
return false;
} else {
return true;
}
},
};
withDefaults(defineProps<IProps>(), {
@@ -233,7 +239,7 @@ const handleSort = async (type: string) => {
</style>
<style lang="scss">
.tree-com {
.dept-tree-com {
height: calc(100% - 60px);
padding: 20px;
box-sizing: border-box;
@@ -257,7 +263,7 @@ const handleSort = async (type: string) => {
padding: 0;
box-sizing: border-box;
margin-right: 5px;
margin-left: 18px;
margin-left: 20px;
}
.el-tree .el-tree-node__expand-icon.expanded {

View File

@@ -3,8 +3,7 @@
<el-row class="dept-el-row">
<el-col :span="6">
<div class="dept-box dept-left">
<TreeCom :treeData="deptTreeData" @treeClick="handleTreeClick" @updateDept="handleUpdateMenu"
@deleteDept="handleDeleteMenu" />
<TreeCom :treeData="deptTreeData" @treeClick="handleTreeClick" @updateDept="handleUpdateMenu" @deleteDept="handleDeleteMenu" />
</div>
</el-col>
@@ -15,9 +14,8 @@
</el-col>
</el-row>
<el-drawer v-model="drawerVisible" title="部门配置" direction="rtl" size="500px" :close-on-click-modal="false"
:before-close="handleDrawerClose">
<DeptFormCom v-if="drawerVisible" :initFormData="drawerFormData" @drawerClose="handleDrawerClose" />
<el-drawer v-model="drawerVisible" title="部门配置" direction="rtl" size="500px" :close-on-click-modal="false" :before-close="handleDrawerClose">
<DeptFormCom v-if="drawerVisible" :initFormData="drawerFormData" :treeData="deptTreeData" @drawerClose="handleDrawerClose" />
</el-drawer>
</fs-page>
</template>
@@ -34,9 +32,9 @@ import { successNotification } from '../../../utils/message';
import { APIResponseData, TreeItemType } from './types';
let deptTreeData = ref([]);
let drawerVisible = ref(false)
let drawerFormData = ref<Partial<TreeItemType>>({})
let deptUserRef = ref<InstanceType<typeof DeptUserCom> | null>(null)
let drawerVisible = ref(false);
let drawerFormData = ref<Partial<TreeItemType>>({});
let deptUserRef = ref<InstanceType<typeof DeptUserCom> | null>(null);
const getData = async () => {
let res: APIResponseData = await GetList({});
@@ -56,30 +54,26 @@ const getData = async () => {
* 部门的点击事件
*/
const handleTreeClick = (id: string) => {
deptUserRef.value?.handleDoRefreshUser(id)
}
deptUserRef.value?.handleDoRefreshUser(id);
};
/**
* 部门的删除事件
*/
const handleDeleteMenu = (id: string, callback: Function) => {
ElMessageBox.confirm(
'确认删除该部门吗?',
'温馨提示',
{
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning',
}
).then(async () => {
const res: APIResponseData = await DelObj(id)
callback()
ElMessageBox.confirm('您确认删除该部门吗?', '温馨提示', {
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning',
}).then(async () => {
const res: APIResponseData = await DelObj(id);
callback();
if (res?.code === 2000) {
successNotification(res.msg as string);
getData();
deptUserRef.value?.handleDoRefreshUser('')
deptUserRef.value?.handleDoRefreshUser('');
}
})
});
};
/**
@@ -87,18 +81,17 @@ const handleDeleteMenu = (id: string, callback: Function) => {
*/
const handleUpdateMenu = (type: string, record?: TreeItemType) => {
if (type === 'update' && record) {
drawerFormData.value = record
drawerFormData.value = record;
}
drawerVisible.value = true
drawerVisible.value = true;
};
const handleDrawerClose = (type?: string) => {
if (type === 'submit') {
getData()
getData();
}
drawerVisible.value = false
drawerFormData.value = {}
}
drawerVisible.value = false;
drawerFormData.value = {};
};
onMounted(() => {
getData();

View File

@@ -45,8 +45,7 @@ export interface DeptFormDataType {
parent: string | number;
name: string;
owner: string;
remark: string;
is_catalog?: boolean;
description: string;
}
export interface DeptListType {