!57 优化前端部门选择,支持懒加载

优化前端部门选择,支持懒加载
treebeard
dvadmin 2022-05-16 14:36:18 +00:00 committed by Gitee
commit 2ac4343e8c
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
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.area import AreaViewSet
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.file_list import FileViewSet
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'role', RoleViewSet)
system_url.register(r'dept', DeptViewSet)
system_url.register(r'dept_query', DeptQueryViewSet)
system_url.register(r'user', UserViewSet)
system_url.register(r'operation_log', OperationLogViewSet)
system_url.register(r'dictionary', DictionaryViewSet)

View File

@ -1,10 +1,9 @@
# -*- coding: utf-8 -*-
"""
@author: 猿小天
@contact: QQ:1638245306
@Created on: 2021/6/3 003 0:30
@Remark: 角色管理
@author: H0nGzA1
@contact: QQ:2505811377
@Remark: 部门管理
"""
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:
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"]
@ -54,6 +67,8 @@ class DeptViewSet(CustomModelViewSet):
serializer_class = DeptSerializer
create_serializer_class = DeptCreateUpdateSerializer
update_serializer_class = DeptCreateUpdateSerializer
filter_fields = ['name']
search_fields = []
# extra_filter_backends = []
# def list(self, request, *args, **kwargs):
@ -64,3 +79,9 @@ class DeptViewSet(CustomModelViewSet):
# return self.get_paginated_response(serializer.data)
# serializer = self.get_serializer(queryset, many=True, request=request)
# 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
* @Auther: 猿小天
@ -6,53 +15,151 @@
* 联系Qq:1638245306
* @文件介绍: 部门管理接口
*/
import { request } from '@/api/service'
import XEUtils from 'xe-utils'
export const urlPrefix = '/api/system/dept/'
import { request } from "@/api/service";
import XEUtils from "xe-utils";
export const urlPrefix = "/api/system/dept/";
/**
* 列表查询
*/
export function GetList (query) {
query.limit = 999
export function GetList(query) {
// query.limit = 999;
return request({
url: urlPrefix,
method: 'get',
params: query
}).then(res => {
method: "get",
params: query,
}).then((res) => {
// 将列表数据转换为树形数据
res.data.data = XEUtils.toArrayTree(res.data.data, { parentKey: 'parent', strict: false })
return res
})
res.data.data = XEUtils.toArrayTree(res.data.data, {
parentKey: "parent",
strict: false,
});
return res;
});
}
/**
* 新增
*/
export function createObj (obj) {
export function createObj(obj) {
return request({
url: urlPrefix,
method: 'post',
data: obj
})
method: "post",
data: obj,
});
}
/**
* 修改
*/
export function UpdateObj (obj) {
export function UpdateObj(obj) {
return request({
url: urlPrefix + obj.id + '/',
method: 'put',
data: obj
})
url: urlPrefix + obj.id + "/",
method: "put",
data: obj,
});
}
/**
* 删除
*/
export function DelObj (id) {
export function DelObj(id) {
return request({
url: urlPrefix + id + '/',
method: 'delete',
data: { id }
})
url: urlPrefix + id + "/",
method: "delete",
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 { urlPrefix as deptPrefix } from './api'
import XEUtils from 'xe-utils'
import { request } from "@/api/service";
import { urlPrefix as deptPrefix } from "./api";
import XEUtils from "xe-utils";
import * as Api from "./api";
export const crudOptions = (vm) => {
return {
pagination: false,
// pagination: false,
pageOptions: {
compact: true
compact: true,
},
options: {
// tableType: 'vxe-table',
// rowKey: true, // 必须设置true or false
rowId: 'id',
height: '100%', // 表格高度100%, 使用toolbar必须设置
tableType: "vxe-table",
rowKey: true, // 必须设置true or false
rowId: "id",
height: "100%", // 表格高度100%, 使用toolbar必须设置
highlightCurrentRow: false,
defaultExpandAll: true
// treeConfig: { // 树形数据配置
// expandAll: true,
// children: 'children',
// }
defaultExpandAll: true,
treeConfig: {
lazy: true,
},
},
rowHandle: {
width: 140,
view: {
thin: true,
text: '',
disabled () {
return !vm.hasPermissions('Retrieve')
}
text: "",
disabled() {
return !vm.hasPermissions("Retrieve");
},
},
edit: {
thin: true,
text: '',
disabled () {
return !vm.hasPermissions('Update')
}
text: "",
disabled() {
return !vm.hasPermissions("Update");
},
},
remove: {
thin: true,
text: '',
disabled () {
return !vm.hasPermissions('Delete')
}
}
text: "",
disabled() {
return !vm.hasPermissions("Delete");
},
},
},
indexRow: { // 或者直接传true,不显示title不居中
title: '序号',
align: 'center',
width: 100
indexRow: {
// 或者直接传true,不显示title不居中
title: "序号",
align: "center",
width: 100,
},
viewOptions: {
componentType: 'form'
componentType: "form",
},
formOptions: {
defaultSpan: 12 // 默认的表单 span
defaultSpan: 12, // 默认的表单 span
},
columns: [{
title: '关键词',
key: 'search',
show: false,
disabled: true,
search: {
disabled: false
},
form: {
columns: [
{
title: "关键词",
key: "search",
show: false,
disabled: true,
component: {
props: {
clearable: true
},
placeholder: '请输入关键词'
}
},
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: {
search: {
disabled: false,
},
form: {
disabled: true,
component: {
props: {
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: "请输入关键词",
},
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: '请输入邮箱'
view: {
// 查看对话框组件的单独配置
disabled: true,
},
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')
{
title: "ID",
key: "id",
show: false,
disabled: true,
width: 90,
form: {
disabled: true,
},
},
form: {
value: true,
component: {
span: 12,
placeholder: '请选择状态'
}
}
}
].concat(vm.commonEndColumns())
}
}
{
show: false,
title: "上级部门",
key: "parent",
type: "tree-selector",
dict: {
isTree: true,
label: "name",
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()),
};
};