Merge remote-tracking branch 'origin/master'

This commit is contained in:
ahhui
2023-07-31 16:43:42 +08:00
7 changed files with 101 additions and 80 deletions

View File

@@ -3,7 +3,7 @@ ENV = 'development'
# 本地环境接口地址 # 本地环境接口地址
#`VITE_API_URL = 'https://demo.dvadmin.com/api' #`VITE_API_URL = 'https://demo.dvadmin.com/api'
VITE_API_URL = 'http://192.168.1.160:8003' VITE_API_URL = 'http://192.168.1.94:10000'
# 是否启用按钮权限 # 是否启用按钮权限
VITE_PM_ENABLED = true VITE_PM_ENABLED = true

View File

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

View File

@@ -1,9 +1,15 @@
<template> <template>
<el-form ref="formRef" :rules="rules" :model="deptFormData" label-width="100px" label-position="right" class="dept-form-com"> <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-form-item label="父级部门" prop="parent">
<el-select v-model="deptFormData.parent" style="width: 100%"> <el-tree-select
<el-option v-for="item in deptAllList" :key="item.id" :label="item.name" :value="item.id" /> v-model="deptFormData.parent"
</el-select> :props="defaultTreeProps"
:data="deptDefaultList"
lazy
check-strictly
:load="handleTreeLoad"
style="width: 100%"
/>
</el-form-item> </el-form-item>
<el-form-item required label="部门名称" prop="name"> <el-form-item required label="部门名称" prop="name">
<el-input v-model="deptFormData.name" /> <el-input v-model="deptFormData.name" />
@@ -11,14 +17,14 @@
<el-form-item required label="部门标识" prop="key"> <el-form-item required label="部门标识" prop="key">
<el-input v-model="deptFormData.key" /> <el-input v-model="deptFormData.key" />
</el-form-item> </el-form-item>
<el-form-item label="负责人" prop="owner"> <el-form-item label="负责人">
<el-input v-model="deptFormData.owner" /> <el-input v-model="deptFormData.owner" />
</el-form-item> </el-form-item>
<el-form-item label="备注" prop="remark"> <el-form-item label="备注">
<el-input v-model="deptFormData.remark" maxlength="200" show-word-limit type="textarea" /> <el-input v-model="deptFormData.description" maxlength="200" show-word-limit type="textarea" />
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button @click="handleUpdateMenu" type="primary" :disabled="deptBtnLoading"> <el-button @click="handleUpdateMenu" type="primary" :loading="deptBtnLoading">
{{ deptFormData.id ? '保存' : '新增' }} {{ deptFormData.id ? '保存' : '新增' }}
</el-button> </el-button>
<el-button @click="handleClose">取消 </el-button> <el-button @click="handleClose">取消 </el-button>
@@ -29,14 +35,29 @@
<script lang="ts" setup> <script lang="ts" setup>
import { reactive, ref, onMounted } from 'vue'; import { reactive, ref, onMounted } from 'vue';
import { ElForm, FormRules } from 'element-plus'; import { ElForm, FormRules } from 'element-plus';
import { getAllDeptList, AddObj, UpdateObj } from '../api'; import { lazyLoadDept, AddObj, UpdateObj } from '../api';
import { successNotification } from '../../../../utils/message'; 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 { interface IProps {
initFormData: TreeItemType | null; 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 formRef = ref<InstanceType<typeof ElForm>>();
const rules = reactive<FormRules>({ const rules = reactive<FormRules>({
name: [{ required: true, message: '部门名称必填', trigger: 'blur' }], name: [{ required: true, message: '部门名称必填', trigger: 'blur' }],
@@ -45,27 +66,20 @@ const rules = reactive<FormRules>({
const props = withDefaults(defineProps<IProps>(), { const props = withDefaults(defineProps<IProps>(), {
initFormData: () => null, initFormData: () => null,
treeData: () => [],
}); });
const emit = defineEmits(['drawerClose']); const emit = defineEmits(['drawerClose']);
let deptAllList = ref<DeptListType[]>([]); let deptDefaultList = ref<TreeItemType[]>([]);
let deptFormData = reactive<DeptFormDataType>({ let deptFormData = reactive<DeptFormDataType>({
key: '', key: '',
parent: '', parent: '',
name: '', name: '',
owner: '', owner: '',
remark: '', description: '',
is_catalog: true,
}); });
let deptBtnLoading = ref(false); let deptBtnLoading = ref(false);
const getData = async () => {
const res = await getAllDeptList();
if (res?.code === 2000) {
deptAllList.value = res.data;
}
};
const setDeptFormData = () => { const setDeptFormData = () => {
if (props.initFormData?.id) { if (props.initFormData?.id) {
deptFormData.id = props.initFormData?.id; deptFormData.id = props.initFormData?.id;
@@ -73,6 +87,15 @@ const setDeptFormData = () => {
deptFormData.parent = props.initFormData.parent || ''; deptFormData.parent = props.initFormData.parent || '';
deptFormData.name = props.initFormData.name || ''; deptFormData.name = props.initFormData.name || '';
deptFormData.owner = props.initFormData.owner || ''; 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 () => { onMounted(async () => {
await getData(); props.treeData.map((item) => {
deptDefaultList.value.push(item);
});
setDeptFormData(); setDeptFormData();
}); });
</script> </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. * 处理crud警告Invalid prop: type check failed for prop "name". Expected String with value "2", got Number with value 2.
*/ */
res.data.forEach((item: any) => { res.data.forEach((item: any) => {
item.dept = String(item.dept);
if (item.role && Array.isArray(item.role) && item.role.length > 0) { if (item.role && Array.isArray(item.role) && item.role.length > 0) {
item.role = item.role.map((r: number) => String(r)); item.role = item.role.map((r: number) => String(r));
} }

View File

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

View File

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

View File

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