优化部门,支持懒加载

pull/57/head
hongzai 2022-05-16 17:13:11 +08:00
parent dfcd429a5d
commit fe8a589145
5 changed files with 38959 additions and 241 deletions

View File

@ -4,7 +4,7 @@ from rest_framework import routers
from dvadmin.system.views.api_white_list import ApiWhiteListViewSet from dvadmin.system.views.api_white_list import ApiWhiteListViewSet
from dvadmin.system.views.area import AreaViewSet from dvadmin.system.views.area import AreaViewSet
from dvadmin.system.views.button import ButtonViewSet from dvadmin.system.views.button import ButtonViewSet
from dvadmin.system.views.dept import DeptViewSet from dvadmin.system.views.dept import DeptViewSet, DeptQueryViewSet
from dvadmin.system.views.dictionary import DictionaryViewSet from dvadmin.system.views.dictionary import DictionaryViewSet
from dvadmin.system.views.file_list import FileViewSet from dvadmin.system.views.file_list import FileViewSet
from dvadmin.system.views.login_log import LoginLogViewSet from dvadmin.system.views.login_log import LoginLogViewSet
@ -21,6 +21,7 @@ system_url.register(r'button', ButtonViewSet)
system_url.register(r'menu_button', MenuButtonViewSet) system_url.register(r'menu_button', MenuButtonViewSet)
system_url.register(r'role', RoleViewSet) system_url.register(r'role', RoleViewSet)
system_url.register(r'dept', DeptViewSet) system_url.register(r'dept', DeptViewSet)
system_url.register(r'dept_query', DeptQueryViewSet)
system_url.register(r'user', UserViewSet) system_url.register(r'user', UserViewSet)
system_url.register(r'operation_log', OperationLogViewSet) system_url.register(r'operation_log', OperationLogViewSet)
system_url.register(r'dictionary', DictionaryViewSet) system_url.register(r'dictionary', DictionaryViewSet)

View File

@ -1,10 +1,9 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
""" """
@author: 猿小天 @author: H0nGzA1
@contact: QQ:1638245306 @contact: QQ:2505811377
@Created on: 2021/6/3 003 0:30 @Remark: 部门管理
@Remark: 角色管理
""" """
from rest_framework import serializers from rest_framework import serializers
@ -18,10 +17,24 @@ class DeptSerializer(CustomModelSerializer):
""" """
部门-序列化器 部门-序列化器
""" """
parent_name = serializers.CharField(read_only=True,source='parent.name') parent_name = serializers.CharField(read_only=True, source='parent.name')
class Meta: class Meta:
model = Dept model = Dept
fields = "__all__" fields = '__all__'
read_only_fields = ["id"]
class DeptQuerySerializer(CustomModelSerializer):
"""
部门-序列化器
"""
parent_name = serializers.CharField(read_only=True, source='parent.name')
code = serializers.CharField(source='id')
class Meta:
model = Dept
fields = ['id', 'name', 'parent', 'parent_name', 'code']
read_only_fields = ["id"] read_only_fields = ["id"]
@ -54,6 +67,8 @@ class DeptViewSet(CustomModelViewSet):
serializer_class = DeptSerializer serializer_class = DeptSerializer
create_serializer_class = DeptCreateUpdateSerializer create_serializer_class = DeptCreateUpdateSerializer
update_serializer_class = DeptCreateUpdateSerializer update_serializer_class = DeptCreateUpdateSerializer
filter_fields = ['name']
search_fields = []
# extra_filter_backends = [] # extra_filter_backends = []
# def list(self, request, *args, **kwargs): # def list(self, request, *args, **kwargs):
@ -64,3 +79,9 @@ class DeptViewSet(CustomModelViewSet):
# return self.get_paginated_response(serializer.data) # return self.get_paginated_response(serializer.data)
# serializer = self.get_serializer(queryset, many=True, request=request) # serializer = self.get_serializer(queryset, many=True, request=request)
# return SuccessResponse(data=serializer.data, msg="获取成功") # return SuccessResponse(data=serializer.data, msg="获取成功")
class DeptQueryViewSet(CustomModelViewSet):
queryset = Dept.objects.all()
serializer_class = DeptQuerySerializer
filter_fields = ['name']

38540
web/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,3 +1,12 @@
/*
* @Author: H0nGzA1
* @Date: 2022-05-16 15:47:21
* @LastEditors: hongzai 2505811377@qq.com
* @LastEditTime: 2022-05-16 16:50:33
* @FilePath: /web/src/views/system/dept/api.js
* @Description:
* email:2505811377@qq.com
*/
/* /*
* @创建文件时间: 2021-06-01 22:41:21 * @创建文件时间: 2021-06-01 22:41:21
* @Auther: 猿小天 * @Auther: 猿小天
@ -6,53 +15,151 @@
* 联系Qq:1638245306 * 联系Qq:1638245306
* @文件介绍: 部门管理接口 * @文件介绍: 部门管理接口
*/ */
import { request } from '@/api/service' import { request } from "@/api/service";
import XEUtils from 'xe-utils' import XEUtils from "xe-utils";
export const urlPrefix = '/api/system/dept/' export const urlPrefix = "/api/system/dept/";
/** /**
* 列表查询 * 列表查询
*/ */
export function GetList (query) { export function GetList(query) {
query.limit = 999 // query.limit = 999;
return request({ return request({
url: urlPrefix, url: urlPrefix,
method: 'get', method: "get",
params: query params: query,
}).then(res => { }).then((res) => {
// 将列表数据转换为树形数据 // 将列表数据转换为树形数据
res.data.data = XEUtils.toArrayTree(res.data.data, { parentKey: 'parent', strict: false }) res.data.data = XEUtils.toArrayTree(res.data.data, {
return res parentKey: "parent",
}) strict: false,
});
return res;
});
} }
/** /**
* 新增 * 新增
*/ */
export function createObj (obj) { export function createObj(obj) {
return request({ return request({
url: urlPrefix, url: urlPrefix,
method: 'post', method: "post",
data: obj data: obj,
}) });
} }
/** /**
* 修改 * 修改
*/ */
export function UpdateObj (obj) { export function UpdateObj(obj) {
return request({ return request({
url: urlPrefix + obj.id + '/', url: urlPrefix + obj.id + "/",
method: 'put', method: "put",
data: obj data: obj,
}) });
} }
/** /**
* 删除 * 删除
*/ */
export function DelObj (id) { export function DelObj(id) {
return request({ return request({
url: urlPrefix + id + '/', url: urlPrefix + id + "/",
method: 'delete', method: "delete",
data: { id } data: { id },
}) });
} }
export function GetTreeChildrenByParentId(parentId) {
return TreeNodesLazyLoader.getChildren(parentId);
}
export function GetNodesByValues(values) {
return TreeNodesLazyLoader.getNodesByValues(values);
}
const getPcasData = request({
url: "/api/system/dept_query/",
method: "get",
}).then((res) => {
// 将列表数据转换为树形数据
res.data.data = XEUtils.toArrayTree(res.data.data, {
parentKey: "parent",
strict: false,
});
return res.data.data;
});
export default getPcasData;
export const TreeNodesLazyLoader = {
getNodesByValues(values) {
// console.log("getNodesByValues", values);
if (!(values instanceof Array)) {
values = [values];
}
return getPcasData.then((data) => {
const nodes = [];
for (const value of values) {
const found = this.getNode(data, value);
if (found) {
nodes.push(found);
}
}
return nodes;
});
},
getNode(list, value) {
for (const item of list) {
if (item.code === value) {
return item;
}
if (item.children && item.children.length > 0) {
const found = this.getNode(item.children, value);
if (found) {
return found;
}
}
}
},
getChildren(parent) {
return getPcasData.then((data) => {
const list = this.getChildrenByParent(parent, data);
if (list == null) {
return [];
}
return this.cloneAndDeleteChildren(list);
});
},
getChildrenByParent(parentId, tree) {
if (!parentId) {
// 取第一级
return tree;
} else {
for (const node of tree) {
if (node.code === parentId) {
return node.children;
}
if (node.children && node.children.length > 0) {
// 递归查找
const list = this.getChildrenByParent(parentId, node.children);
if (list) {
return list;
}
}
}
}
},
cloneAndDeleteChildren(list) {
const newList = [];
for (const node of list) {
const newNode = {};
Object.assign(newNode, node);
if (newNode.children == null || newNode.children.length === 0) {
newNode.isLeaf = true;
newNode.leaf = true;
}
delete newNode.children;
newList.push(newNode);
}
// console.log("found children:", newList);
return newList;
},
};

View File

@ -1,240 +1,289 @@
import { request } from '@/api/service' import { request } from "@/api/service";
import { urlPrefix as deptPrefix } from './api' import { urlPrefix as deptPrefix } from "./api";
import XEUtils from 'xe-utils' import XEUtils from "xe-utils";
import * as Api from "./api";
export const crudOptions = (vm) => { export const crudOptions = (vm) => {
return { return {
pagination: false, // pagination: false,
pageOptions: { pageOptions: {
compact: true compact: true,
}, },
options: { options: {
// tableType: 'vxe-table', tableType: "vxe-table",
// rowKey: true, // 必须设置true or false rowKey: true, // 必须设置true or false
rowId: 'id', rowId: "id",
height: '100%', // 表格高度100%, 使用toolbar必须设置 height: "100%", // 表格高度100%, 使用toolbar必须设置
highlightCurrentRow: false, highlightCurrentRow: false,
defaultExpandAll: true defaultExpandAll: true,
// treeConfig: { // 树形数据配置 treeConfig: {
// expandAll: true, lazy: true,
// children: 'children', },
// }
}, },
rowHandle: { rowHandle: {
width: 140, width: 140,
view: { view: {
thin: true, thin: true,
text: '', text: "",
disabled () { disabled() {
return !vm.hasPermissions('Retrieve') return !vm.hasPermissions("Retrieve");
} },
}, },
edit: { edit: {
thin: true, thin: true,
text: '', text: "",
disabled () { disabled() {
return !vm.hasPermissions('Update') return !vm.hasPermissions("Update");
} },
}, },
remove: { remove: {
thin: true, thin: true,
text: '', text: "",
disabled () { disabled() {
return !vm.hasPermissions('Delete') return !vm.hasPermissions("Delete");
} },
} },
}, },
indexRow: { // 或者直接传true,不显示title不居中 indexRow: {
title: '序号', // 或者直接传true,不显示title不居中
align: 'center', title: "序号",
width: 100 align: "center",
width: 100,
}, },
viewOptions: { viewOptions: {
componentType: 'form' componentType: "form",
}, },
formOptions: { formOptions: {
defaultSpan: 12 // 默认的表单 span defaultSpan: 12, // 默认的表单 span
}, },
columns: [{ columns: [
title: '关键词', {
key: 'search', title: "关键词",
show: false, key: "search",
disabled: true, show: false,
search: {
disabled: false
},
form: {
disabled: true, disabled: true,
component: { search: {
props: { disabled: false,
clearable: true },
}, form: {
placeholder: '请输入关键词' disabled: true,
} component: {
}, props: {
view: { // 查看对话框组件的单独配置
disabled: true
}
},
{
title: 'ID',
key: 'id',
show: false,
disabled: true,
width: 90,
form: {
disabled: true
}
},
{
title: '上级部门',
key: 'parent',
show: false,
search: {
disabled: true
},
type: 'cascader',
dict: {
cache: false,
url: deptPrefix,
isTree: true,
value: 'id', // 数据字典中value字段的属性名
label: 'name', // 数据字典中label字段的属性名
children: 'children', // 数据字典中children字段的属性名
getData: (url, dict) => { // 配置此参数会覆盖全局的getRemoteDictFunc
return request({ url: url, params: { limit: 999, status: 1 } }).then(ret => {
const data = XEUtils.toArrayTree(ret.data.data, { parentKey: 'parent', strict: true })
return [{ id: null, name: '根节点', children: data }]
})
}
},
form: {
component: {
span: 12,
props: {
elProps: {
clearable: true, clearable: true,
showAllLevels: false, // 仅显示最后一级 },
props: { placeholder: "请输入关键词",
checkStrictly: true, // 可以不需要选到最后一级
emitPath: false,
clearable: true
}
}
}
}
}
},
{
title: '部门名称',
key: 'name',
sortable: true,
treeNode: true, // 设置为树形列
search: {
disabled: false,
component: {
props: {
clearable: true
}
}
},
width: 180,
type: 'input',
form: {
rules: [ // 表单校验规则
{ required: true, message: '部门名称必填项' }
],
component: {
span: 12,
props: {
clearable: true
}, },
placeholder: '请输入部门名称'
}, },
itemProps: { view: {
class: { yxtInput: true } // 查看对话框组件的单独配置
} disabled: true,
}
},
{
title: '负责人',
key: 'owner',
sortable: true,
form: {
component: {
span: 12,
props: {
clearable: true
},
placeholder: '请输入负责人'
}
}
},
{
title: '联系电话',
key: 'phone',
sortable: true,
form: {
component: {
span: 12,
props: {
clearable: true
},
placeholder: '请输入联系电话'
}
}
},
{
title: '邮箱',
key: 'email',
sortable: true,
form: {
component: {
span: 12,
props: {
clearable: true
},
placeholder: '请输入邮箱'
}, },
rules: [
{ type: 'email', message: '请输入正确的邮箱地址', trigger: ['blur', 'change'] }
]
}
}, {
title: '排序',
key: 'sort',
sortable: true,
width: 80,
type: 'number',
form: {
value: 1,
component: {
span: 12,
placeholder: '请选择序号'
}
}
},
{
title: '状态',
key: 'status',
sortable: true,
search: {
disabled: false
}, },
width: 90, {
type: 'radio', title: "ID",
dict: { key: "id",
data: vm.dictionary('button_status_bool') show: false,
disabled: true,
width: 90,
form: {
disabled: true,
},
}, },
form: { {
value: true, show: false,
component: { title: "上级部门",
span: 12, key: "parent",
placeholder: '请选择状态' type: "tree-selector",
} dict: {
} isTree: true,
} label: "name",
].concat(vm.commonEndColumns()) value: "code",
} getNodes(values) {
} // 配置行展示远程获取nodes
return Api.GetNodesByValues(values);
},
},
form: {
helper: "默认留空为根节点",
component: {
span: 12,
props: {
multiple: false,
elProps: {
lazy: true,
load(node, resolve) {
// 懒加载
// console.log("懒加载");
if (node.level === 0) {
Api.GetTreeChildrenByParentId().then((data) => {
resolve(data);
});
return;
}
Api.GetTreeChildrenByParentId(node.data.code).then((data) => {
resolve(data);
});
},
},
},
},
},
},
// {
// title: '上级部门',
// key: 'parent',
// show: false,
// search: {
// disabled: true
// },
// type: 'cascader',
// dict: {
// cache: false,
// url: deptPrefix,
// isTree: true,
// value: 'id', // 数据字典中value字段的属性名
// label: 'name', // 数据字典中label字段的属性名
// children: 'children', // 数据字典中children字段的属性名
// getData: (url, dict) => { // 配置此参数会覆盖全局的getRemoteDictFunc
// return request({ url: url, params: { limit: 999, status: 1 } }).then(ret => {
// const data = XEUtils.toArrayTree(ret.data.data, { parentKey: 'parent', strict: true })
// return [{ id: null, name: '根节点', children: data }]
// })
// }
// },
// form: {
// component: {
// span: 12,
// props: {
// elProps: {
// clearable: true,
// showAllLevels: false, // 仅显示最后一级
// props: {
// checkStrictly: true, // 可以不需要选到最后一级
// emitPath: false,
// clearable: true
// }
// }
// }
// }
// }
// },
{
title: "部门名称",
key: "name",
sortable: true,
treeNode: true, // 设置为树形列
search: {
disabled: false,
component: {
props: {
clearable: true,
},
},
},
width: 180,
type: "input",
form: {
rules: [
// 表单校验规则
{ required: true, message: "部门名称必填项" },
],
component: {
span: 12,
props: {
clearable: true,
},
placeholder: "请输入部门名称",
},
itemProps: {
class: { yxtInput: true },
},
},
},
{
title: "负责人",
key: "owner",
sortable: true,
form: {
component: {
span: 12,
props: {
clearable: true,
},
placeholder: "请输入负责人",
},
},
},
{
title: "联系电话",
key: "phone",
sortable: true,
form: {
component: {
span: 12,
props: {
clearable: true,
},
placeholder: "请输入联系电话",
},
},
},
{
title: "邮箱",
key: "email",
sortable: true,
form: {
component: {
span: 12,
props: {
clearable: true,
},
placeholder: "请输入邮箱",
},
rules: [
{
type: "email",
message: "请输入正确的邮箱地址",
trigger: ["blur", "change"],
},
],
},
},
{
title: "排序",
key: "sort",
sortable: true,
width: 80,
type: "number",
form: {
value: 1,
component: {
span: 12,
placeholder: "请选择序号",
},
},
},
{
title: "状态",
key: "status",
sortable: true,
search: {
disabled: false,
},
width: 90,
type: "radio",
dict: {
data: vm.dictionary("button_status_bool"),
},
form: {
value: true,
component: {
span: 12,
placeholder: "请选择状态",
},
},
},
].concat(vm.commonEndColumns()),
};
};