refactor(用户管理): ♻️ 用户管理优化

This commit is contained in:
猿小天
2023-04-09 22:26:26 +08:00
parent 58e611cb22
commit 42884685ff
4 changed files with 113 additions and 94 deletions

View File

@@ -123,6 +123,7 @@ class DeptViewSet(CustomModelViewSet):
data = serializer.data data = serializer.data
return SuccessResponse(data=data) return SuccessResponse(data=data)
@action(methods=["GET"], detail=False, permission_classes=[IsAuthenticated], extra_filter_class=[])
def dept_lazy_tree(self, request, *args, **kwargs): def dept_lazy_tree(self, request, *args, **kwargs):
parent = self.request.query_params.get('parent') parent = self.request.query_params.get('parent')
is_superuser = request.user.is_superuser is_superuser = request.user.is_superuser

View File

@@ -2,6 +2,15 @@ import { request } from '/@/utils/service';
import { PageQuery, AddReq, DelReq, EditReq, InfoReq } from '@fast-crud/fast-crud'; import { PageQuery, AddReq, DelReq, EditReq, InfoReq } from '@fast-crud/fast-crud';
export const apiPrefix = '/api/system/user/'; export const apiPrefix = '/api/system/user/';
export function GetDept(query: PageQuery) {
return request({
url: "/api/system/dept/dept_lazy_tree/",
method: 'get',
params: query,
});
}
export function GetList(query: PageQuery) { export function GetList(query: PageQuery) {
return request({ return request({
url: apiPrefix, url: apiPrefix,

View File

@@ -63,8 +63,10 @@ export const createCrudOptions = function ({ crudExpose }: { crudExpose: CrudExp
search: { search: {
show: true, show: true,
}, },
minWidth: 100,
type: 'input', type: 'input',
column:{
minWidth: 100 //最小列宽
},
form: { form: {
rules: [ rules: [
// 表单校验规则 // 表单校验规则
@@ -114,6 +116,9 @@ export const createCrudOptions = function ({ crudExpose }: { crudExpose: CrudExp
show: true, show: true,
}, },
type: 'input', type: 'input',
column:{
minWidth: 100 //最小列宽
},
form: { form: {
rules: [ rules: [
// 表单校验规则 // 表单校验规则
@@ -147,6 +152,9 @@ export const createCrudOptions = function ({ crudExpose }: { crudExpose: CrudExp
}); });
}, },
}), }),
column:{
minWidth: 150 //最小列宽
},
form: { form: {
rules: [ rules: [
// 表单校验规则 // 表单校验规则
@@ -190,6 +198,9 @@ export const createCrudOptions = function ({ crudExpose }: { crudExpose: CrudExp
}); });
}, },
}), }),
column:{
minWidth: 100 //最小列宽
},
form: { form: {
rules: [ rules: [
// 表单校验规则 // 表单校验规则
@@ -211,6 +222,9 @@ export const createCrudOptions = function ({ crudExpose }: { crudExpose: CrudExp
show: true, show: true,
}, },
type: 'input', type: 'input',
column:{
minWidth: 120 //最小列宽
},
form: { form: {
rules: [ rules: [
{ {
@@ -269,6 +283,9 @@ export const createCrudOptions = function ({ crudExpose }: { crudExpose: CrudExp
dict: dict({ dict: dict({
data: dictionary('user_type'), data: dictionary('user_type'),
}), }),
column:{
minWidth: 100 //最小列宽
},
form: { form: {
show: false, show: false,
value: 0, value: 0,

View File

@@ -1,124 +1,116 @@
<template> <template>
<fs-page> <fs-page>
<el-row class="mx-2"> <el-row class="mx-2">
<el-col :span="4" class="p-1"> <el-col xs="24" :sm="8" :md="6" :lg="4" :xl="4" class="p-1">
<el-card :body-style="{ height: '100%' }"> <el-card :body-style="{ height: '100%' }">
<p class="font-mono font-black text-center text-xl pb-5"> <p class="font-mono font-black text-center text-xl pb-5">
用户列表 部门列表
<el-tooltip effect="dark" :content="content" placement="right"> <el-tooltip effect="dark" :content="content" placement="right">
<el-icon> <QuestionFilled /> </el-icon> <el-icon>
</el-tooltip> <QuestionFilled/>
</p> </el-icon>
<el-input v-model="filterText" :placeholder="placeholder" /> </el-tooltip>
<el-tree </p>
ref="treeRef" <el-input v-model="filterText" :placeholder="placeholder"/>
class="font-mono font-bold leading-6 text-7xl" <el-tree
:data="data" ref="treeRef"
:props="treeProps" class="font-mono font-bold leading-6 text-7xl"
:filter-node-method="filterNode" :data="data"
:load="loadNode" :props="treeProps"
lazy :filter-node-method="filterNode"
icon="ArrowRightBold" icon="ArrowRightBold"
:indent="12" :indent="12"
> @node-click="onTreeNodeClick"
<template #default="{ node, data }"> >
<span class="text-center font-black text-xl">{{ node.label }}</span> <template #default="{ node, data }">
</template> <span class="text-center font-black text-xl">{{ node.label }}</span>
</el-tree> </template>
</el-card> </el-tree>
</el-col> </el-card>
<el-col :span="20" class="p-1"> </el-col>
<el-card :body-style="{ height: '100%' }"> <el-col xs="24" :sm="16" :md="18" :lg="20" :xl="20" class="p-1">
<fs-crud ref="crudRef" v-bind="crudBinding"> </fs-crud> <el-card :body-style="{ height: '100%' }">
</el-card>
</el-col> <fs-crud ref="crudRef" v-bind="crudBinding"></fs-crud>
</el-row>
</fs-page> </el-card>
</el-col>
</el-row>
</fs-page>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { useExpose, useCrud } from '@fast-crud/fast-crud'; import {useExpose, useCrud} from '@fast-crud/fast-crud';
import { createCrudOptions } from './crud'; import {createCrudOptions} from './crud';
import * as api from './api'; import * as api from './api';
import { ElTree } from 'element-plus'; import {ElTree} from 'element-plus';
import { ref, onMounted, watch, toRaw, defineAsyncComponent } from 'vue'; import {ref, onMounted, watch, toRaw, defineAsyncComponent} from 'vue';
import XEUtils from 'xe-utils'; import XEUtils from 'xe-utils';
import { errorMessage, successMessage } from '../../../utils/message'; import {errorMessage, successMessage} from '../../../utils/message';
import {GetDept} from "./api";
interface Tree { interface Tree {
id: number; id: number;
name: string; name: string;
status: boolean; status: boolean;
children?: Tree[]; children?: Tree[];
} }
interface APIResponseData { interface APIResponseData {
code?: number; code?: number;
data: []; data: [];
msg?: string; msg?: string;
} }
// 引入组件 // 引入组件
const placeholder = ref('请输入用户名称'); const placeholder = ref('请输入部门名称');
const filterText = ref(''); const filterText = ref('');
const treeRef = ref<InstanceType<typeof ElTree>>(); const treeRef = ref<InstanceType<typeof ElTree>>();
const treeProps = { const treeProps = {
children: 'children', children: 'children',
label: 'name', label: 'name',
icon: 'icon', icon: 'icon'
isLeaf: (data: Tree[], node: Node) => {
// @ts-ignore
if (node.data.hasChild) {
return false;
} else {
return true;
}
},
}; };
watch(filterText, (val) => { watch(filterText, (val) => {
treeRef.value!.filter(val); treeRef.value!.filter(val);
}); });
const filterNode = (value: string, data: Tree) => { const filterNode = (value: string, data: Tree) => {
if (!value) return true; if (!value) return true;
return toRaw(data).name.indexOf(value) !== -1; return toRaw(data).name.indexOf(value) !== -1;
}; };
// 懒加载
const loadNode = (node: Node, resolve: (data: Tree[]) => void) => {
// @ts-ignore
if (node.level !== 0) {
// @ts-ignore
api.GetList({ parent: node.data.id }).then((res: APIResponseData) => {
resolve(res.data);
console.log(res.data);
});
}
};
let data = ref([]); let data = ref([]);
const content = ` const content = `
1.用户数据支持懒加载; 1.部门信息;
`; `;
const getData = () => { const getData = () => {
api.GetList({}).then((ret: APIResponseData) => { api.GetDept({}).then((ret: APIResponseData) => {
const responseData = ret.data; const responseData = ret.data;
const result = XEUtils.toArrayTree(responseData, { const result = XEUtils.toArrayTree(responseData, {
parentKey: 'parent', parentKey: 'parent',
children: 'children', children: 'children',
strict: true, strict: true
}); });
data.value = result; console.log(result)
}); data.value = result;
});
}; };
//树形点击事件
const onTreeNodeClick = (node: any) => {
const {id} = node
crudExpose.doSearch({form: {dept: id}})
}
// 页面打开后获取列表数据 // 页面打开后获取列表数据
onMounted(() => { onMounted(() => {
getData(); getData();
}); });
// crud组件的ref // crud组件的ref
@@ -126,28 +118,28 @@ const crudRef = ref();
// crud 配置的ref // crud 配置的ref
const crudBinding = ref(); const crudBinding = ref();
// 暴露的方法 // 暴露的方法
const { crudExpose } = useExpose({ crudRef, crudBinding }); const {crudExpose} = useExpose({crudRef, crudBinding});
// 你的crud配置 // 你的crud配置
const { crudOptions } = createCrudOptions({ crudExpose }); const {crudOptions} = createCrudOptions({crudExpose});
// 初始化crud配置 // 初始化crud配置
const { resetCrudOptions } = useCrud({ crudExpose, crudOptions }); const {resetCrudOptions} = useCrud({crudExpose, crudOptions});
// 页面打开后获取列表数据 // 页面打开后获取列表数据
onMounted(() => { onMounted(() => {
crudExpose.doRefresh(); crudExpose.doRefresh();
}); });
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.el-row { .el-row {
height: 100%; height: 100%;
.el-col { .el-col {
height: 100%; height: 100%;
} }
} }
.el-card { .el-card {
height: 100%; height: 100%;
} }
</style> </style>