fix: 🐛 菜单管理和字典管理
1.修复菜单管理问题; 2.修复字典管理问题;
This commit is contained in:
@@ -34,6 +34,19 @@ class DictionaryCreateUpdateSerializer(CustomModelSerializer):
|
|||||||
"""
|
"""
|
||||||
字典管理 创建/更新时的列化器
|
字典管理 创建/更新时的列化器
|
||||||
"""
|
"""
|
||||||
|
value = serializers.CharField(max_length=100)
|
||||||
|
|
||||||
|
def validate_value(self, value):
|
||||||
|
"""
|
||||||
|
在父级的字典编号验证重复性
|
||||||
|
"""
|
||||||
|
initial_data = self.initial_data
|
||||||
|
parent = initial_data.get('parent',None)
|
||||||
|
if parent is None:
|
||||||
|
unique = Dictionary.objects.filter(value=value).exists()
|
||||||
|
if unique:
|
||||||
|
raise serializers.ValidationError("字典编号不能重复")
|
||||||
|
return value
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Dictionary
|
model = Dictionary
|
||||||
@@ -51,20 +64,24 @@ class DictionaryViewSet(CustomModelViewSet):
|
|||||||
"""
|
"""
|
||||||
queryset = Dictionary.objects.all()
|
queryset = Dictionary.objects.all()
|
||||||
serializer_class = DictionarySerializer
|
serializer_class = DictionarySerializer
|
||||||
|
create_serializer_class = DictionaryCreateUpdateSerializer
|
||||||
extra_filter_class = []
|
extra_filter_class = []
|
||||||
search_fields = ['label']
|
search_fields = ['label']
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
|
if self.action =='list':
|
||||||
params = self.request.query_params
|
params = self.request.query_params
|
||||||
parent = params.get('parent', None)
|
parent = params.get('parent', None)
|
||||||
if params:
|
if params:
|
||||||
if parent:
|
if parent:
|
||||||
queryset = self.queryset.filter(status=1, parent=parent)
|
queryset = self.queryset.filter(parent=parent)
|
||||||
else:
|
else:
|
||||||
queryset = self.queryset.filter(status=1, parent__isnull=True)
|
queryset = self.queryset.filter(parent__isnull=True)
|
||||||
else:
|
else:
|
||||||
queryset = self.queryset.filter(status=1, parent__isnull=True)
|
queryset = self.queryset.filter(parent__isnull=True)
|
||||||
return queryset
|
return queryset
|
||||||
|
else:
|
||||||
|
return self.queryset
|
||||||
|
|
||||||
|
|
||||||
class InitDictionaryViewSet(APIView):
|
class InitDictionaryViewSet(APIView):
|
||||||
|
|||||||
@@ -63,10 +63,10 @@
|
|||||||
<el-col class="center">
|
<el-col class="center">
|
||||||
<el-divider>
|
<el-divider>
|
||||||
<el-button @click="saveMenu()" type="primary" round>保存</el-button>
|
<el-button @click="saveMenu()" type="primary" round>保存</el-button>
|
||||||
<el-button @click="newMenu()" type="success" round>新建</el-button>
|
<el-button @click="newMenu()" type="success" round :disabled="!form.id">新建</el-button>
|
||||||
<el-button @click="addChildMenu()" type="info" round>添加子级</el-button>
|
<el-button @click="addChildMenu()" type="info" round :disabled="!form.id">添加子级</el-button>
|
||||||
<el-button @click="addSameLevelMenu()" type="warning" round>添加同级</el-button>
|
<el-button @click="addSameLevelMenu()" type="warning" round :disabled="!form.id">添加同级</el-button>
|
||||||
<el-button @click="deleteMenu()" type="danger" round>删除部门</el-button>
|
<el-button @click="deleteMenu()" type="danger" round :disabled="!form.id">删除部门</el-button>
|
||||||
</el-divider>
|
</el-divider>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
@@ -79,7 +79,7 @@
|
|||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import * as api from './api';
|
import * as api from './api';
|
||||||
import { ElForm, ElTree, FormRules } from 'element-plus';
|
import {ElForm, ElMessageBox, ElTree, FormRules} from 'element-plus';
|
||||||
import { ref, onMounted, reactive, toRaw, watch } from 'vue';
|
import { ref, onMounted, reactive, toRaw, watch } from 'vue';
|
||||||
import XEUtils from 'xe-utils';
|
import XEUtils from 'xe-utils';
|
||||||
import { errorMessage, successMessage } from '../../../utils/message';
|
import { errorMessage, successMessage } from '../../../utils/message';
|
||||||
@@ -175,7 +175,6 @@ const formRef = ref<InstanceType<typeof ElForm>>();
|
|||||||
|
|
||||||
const rules = reactive<FormRules>({
|
const rules = reactive<FormRules>({
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
parent: [{ required: true, message: '父级部门名称必填', trigger: 'blur' }],
|
|
||||||
name: [{ required: true, message: '部门名称必填', trigger: 'blur' }],
|
name: [{ required: true, message: '部门名称必填', trigger: 'blur' }],
|
||||||
key: [{ required: true, message: '部门标识必填', trigger: 'blur' }],
|
key: [{ required: true, message: '部门标识必填', trigger: 'blur' }],
|
||||||
});
|
});
|
||||||
@@ -236,10 +235,21 @@ const addSameLevelMenu = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const deleteMenu = () => {
|
const deleteMenu = () => {
|
||||||
|
ElMessageBox.confirm(
|
||||||
|
'您确认删除该菜单项吗?',
|
||||||
|
'温馨提示',
|
||||||
|
{
|
||||||
|
confirmButtonText: '确认',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
type: 'warning',
|
||||||
|
}
|
||||||
|
).then(() => {
|
||||||
api.DelObj(form).then((res: APIResponseData) => {
|
api.DelObj(form).then((res: APIResponseData) => {
|
||||||
successMessage(res.msg as string);
|
successMessage(res.msg as string);
|
||||||
getData();
|
getData();
|
||||||
});
|
});
|
||||||
|
})
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleNodeClick = (data: any, node: any, prop: any) => {
|
const handleNodeClick = (data: any, node: any, prop: any) => {
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ export function GetList(query: UserPageQuery) {
|
|||||||
}
|
}
|
||||||
export function GetObj(id: InfoReq) {
|
export function GetObj(id: InfoReq) {
|
||||||
return request({
|
return request({
|
||||||
url: apiPrefix + id,
|
url: apiPrefix + id+'/',
|
||||||
method: 'get',
|
method: 'get',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -36,6 +36,6 @@ export function DelObj(id: DelReq) {
|
|||||||
return request({
|
return request({
|
||||||
url: apiPrefix + id + '/',
|
url: apiPrefix + id + '/',
|
||||||
method: 'delete',
|
method: 'delete',
|
||||||
data: { id },
|
data: { },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,15 @@ export const createCrudOptions = function ({ crudExpose, context }: CreateCrudOp
|
|||||||
return await api.DelObj(row.id);
|
return await api.DelObj(row.id);
|
||||||
};
|
};
|
||||||
const addRequest = async ({ form }: AddReq) => {
|
const addRequest = async ({ form }: AddReq) => {
|
||||||
|
const data = crudExpose.getSearchFormData()
|
||||||
|
const parent = data.parent
|
||||||
|
form.parent = parent
|
||||||
|
if(parent){
|
||||||
return await api.AddObj(form);
|
return await api.AddObj(form);
|
||||||
|
}else{
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -16,7 +16,12 @@ import { request } from '/@/utils/service';
|
|||||||
//此处为crudOptions配置
|
//此处为crudOptions配置
|
||||||
export const createCrudOptions = function ({ crudExpose, context }: CreateCrudOptionsProps): CreateCrudOptionsRet {
|
export const createCrudOptions = function ({ crudExpose, context }: CreateCrudOptionsProps): CreateCrudOptionsRet {
|
||||||
const pageRequest = async (query: UserPageQuery) => {
|
const pageRequest = async (query: UserPageQuery) => {
|
||||||
|
if(context!.selectOptions.value.id){
|
||||||
return await api.GetList({ menu: context!.selectOptions.value.id } as any);
|
return await api.GetList({ menu: context!.selectOptions.value.id } as any);
|
||||||
|
}else{
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
const editRequest = async ({ form, row }: EditReq) => {
|
const editRequest = async ({ form, row }: EditReq) => {
|
||||||
form.id = row.id;
|
form.id = row.id;
|
||||||
|
|||||||
@@ -11,16 +11,19 @@ let selectOptions: any = ref({ name: null });
|
|||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
selectMenu: object;
|
selectMenu: object;
|
||||||
}>();
|
}>();
|
||||||
|
const { crudRef, crudBinding, crudExpose, context } = useFs({ createCrudOptions, context: { selectOptions } });
|
||||||
|
const { doRefresh,setTableData } = crudExpose;
|
||||||
|
|
||||||
watch(props.selectMenu, (val: any) => {
|
watch(props.selectMenu, (val: any) => {
|
||||||
if (!val.is_catalog) {
|
if (!val.is_catalog && val.id) {
|
||||||
selectOptions.value = val;
|
selectOptions.value = val;
|
||||||
doRefresh();
|
doRefresh();
|
||||||
|
}else{
|
||||||
|
//清空表格数据
|
||||||
|
setTableData([])
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const { crudRef, crudBinding, crudExpose, context } = useFs({ createCrudOptions, context: { selectOptions } });
|
|
||||||
const { doRefresh } = crudExpose;
|
|
||||||
|
|
||||||
defineExpose({ selectOptions });
|
defineExpose({ selectOptions });
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -27,81 +27,57 @@
|
|||||||
</el-tree>
|
</el-tree>
|
||||||
</el-card>
|
</el-card>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="20" class="p-1">
|
<el-col :span="6" class="p-1">
|
||||||
<el-card :body-style="{ height: '100%' }">
|
<el-card :body-style="{ height: '100%' }">
|
||||||
<el-form ref="formRef" :rules="rules" :model="form" label-width="80px" label-position="right">
|
<el-form ref="formRef" :rules="rules" :model="form" label-width="80px" label-position="right">
|
||||||
<el-alert :title="content" type="success" effect="dark" :closable="false" center />
|
<el-alert :title="content" type="success" effect="dark" :closable="false" center />
|
||||||
<el-divider>
|
<el-divider>
|
||||||
<strong>菜单配置</strong>
|
<strong>菜单配置</strong>
|
||||||
</el-divider>
|
</el-divider>
|
||||||
<el-row>
|
|
||||||
<el-col :span="10">
|
|
||||||
<el-form-item label="菜单ID" prop="id"> <el-input v-model="form.id" disabled />
|
<el-form-item label="菜单ID" prop="id"> <el-input v-model="form.id" disabled />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
|
||||||
<el-col :span="10">
|
|
||||||
<el-form-item label="父级ID" prop="parent"> <el-input v-model="form.parent" /> </el-form-item>
|
<el-form-item label="父级ID" prop="parent"> <el-input v-model="form.parent" /> </el-form-item>
|
||||||
</el-col>
|
|
||||||
<el-col :span="10">
|
|
||||||
<el-form-item required label="菜单名称" prop="name"> <el-input v-model="form.name" />
|
<el-form-item required label="菜单名称" prop="name"> <el-input v-model="form.name" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
|
||||||
<el-col :span="10">
|
|
||||||
<el-form-item label="组件地址" prop="component">
|
<el-form-item label="组件地址" prop="component">
|
||||||
<el-autocomplete class="w-full" v-model="form.component"
|
<el-autocomplete class="w-full" v-model="form.component"
|
||||||
:fetch-suggestions="querySearch" :trigger-on-focus="false" clearable debounce="100"
|
:fetch-suggestions="querySearch" :trigger-on-focus="false" clearable debounce="100"
|
||||||
placeholder="输入组件地址" />
|
placeholder="输入组件地址" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
|
||||||
<el-col :span="10">
|
|
||||||
<el-form-item required label="Url" prop="web_path"> <el-input v-model="form.web_path" />
|
<el-form-item required label="Url" prop="web_path"> <el-input v-model="form.web_path" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
|
||||||
<el-col :span="10">
|
|
||||||
<el-form-item label="排序" prop="sort">
|
<el-form-item label="排序" prop="sort">
|
||||||
<el-input-number v-model="form.sort" controls-position="right" />
|
<el-input-number v-model="form.sort" controls-position="right" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
|
||||||
<el-col :span="10">
|
|
||||||
<el-form-item label="状态">
|
<el-form-item label="状态">
|
||||||
<el-radio-group v-model="form.status">
|
<el-radio-group v-model="form.status">
|
||||||
<el-radio :label="true">启用</el-radio>
|
<el-radio :label="true">启用</el-radio>
|
||||||
<el-radio :label="false">禁用</el-radio>
|
<el-radio :label="false">禁用</el-radio>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
|
||||||
<el-col :span="10">
|
|
||||||
<el-form-item label="侧边可见">
|
<el-form-item label="侧边可见">
|
||||||
<el-radio-group v-model="form.visible">
|
<el-radio-group v-model="form.visible">
|
||||||
<el-radio :label="true">启用</el-radio>
|
<el-radio :label="true">启用</el-radio>
|
||||||
<el-radio :label="false">禁用</el-radio>
|
<el-radio :label="false">禁用</el-radio>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
|
||||||
|
|
||||||
<el-col :span="20">
|
|
||||||
<el-form-item label="图标" prop="icon">
|
<el-form-item label="图标" prop="icon">
|
||||||
<IconSelector clearable v-model="form.icon" />
|
<IconSelector clearable v-model="form.icon" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-form>
|
||||||
<el-col class="center">
|
<el-divider></el-divider>
|
||||||
<el-divider>
|
<div>
|
||||||
<el-button @click="saveMenu()" type="primary" round>保存</el-button>
|
<el-button @click="saveMenu()" type="primary" round>保存</el-button>
|
||||||
<el-button @click="newMenu()" type="success" round>新建</el-button>
|
<el-button @click="newMenu()" type="success" round :disabled="!form.id">新建</el-button>
|
||||||
<el-button @click="addChildMenu()" type="info" round>添加子级</el-button>
|
<el-button @click="addChildMenu()" type="warning" round :disabled="!form.id">添加子级</el-button>
|
||||||
<el-button @click="addSameLevelMenu()" type="warning" round>添加同级</el-button>
|
<!-- <el-button @click="addSameLevelMenu()" type="warning" round>添加同级</el-button>-->
|
||||||
<el-button @click="deleteMenu()" type="danger" round>删除菜单</el-button>
|
<el-button @click="deleteMenu()" type="danger" round :disabled="!form.id">删除菜单</el-button>
|
||||||
</el-divider>
|
</div>
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
<el-row>
|
|
||||||
<el-col class="h-full">
|
|
||||||
<el-card :body-style="{ height: '100%' }" class="mt-10">
|
|
||||||
<menuButton :select-menu="form" />
|
|
||||||
</el-card>
|
</el-card>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
<el-col :span="14" class="p-1">
|
||||||
</el-form>
|
<el-card :body-style="{ height: '100%' }" >
|
||||||
|
<menuButton :select-menu="form" />
|
||||||
</el-card>
|
</el-card>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
@@ -111,7 +87,7 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import * as api from './api';
|
import * as api from './api';
|
||||||
import * as menuButoonApi from './components/menuButton/api';
|
import * as menuButoonApi from './components/menuButton/api';
|
||||||
import { ElForm, ElTree, FormRules } from 'element-plus';
|
import { ElForm, ElTree, FormRules,ElMessageBox } from 'element-plus';
|
||||||
import { ref, onMounted, watch, reactive, toRaw, defineAsyncComponent, nextTick, shallowRef } from 'vue';
|
import { ref, onMounted, watch, reactive, toRaw, defineAsyncComponent, nextTick, shallowRef } from 'vue';
|
||||||
import XEUtils from 'xe-utils';
|
import XEUtils from 'xe-utils';
|
||||||
import { errorMessage, successMessage } from '../../../utils/message';
|
import { errorMessage, successMessage } from '../../../utils/message';
|
||||||
@@ -340,10 +316,21 @@ const addSameLevelMenu = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const deleteMenu = () => {
|
const deleteMenu = () => {
|
||||||
|
ElMessageBox.confirm(
|
||||||
|
'您确认删除该菜单项吗?',
|
||||||
|
'温馨提示',
|
||||||
|
{
|
||||||
|
confirmButtonText: '确认',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
type: 'warning',
|
||||||
|
}
|
||||||
|
).then(() => {
|
||||||
api.DelObj(form).then((res: APIResponseData) => {
|
api.DelObj(form).then((res: APIResponseData) => {
|
||||||
successMessage(res.msg as string);
|
successMessage(res.msg as string);
|
||||||
getData();
|
getData();
|
||||||
});
|
});
|
||||||
|
})
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleNodeClick = (data: any, node: any, prop: any) => {
|
const handleNodeClick = (data: any, node: any, prop: any) => {
|
||||||
@@ -355,7 +342,7 @@ const handleNodeClick = (data: any, node: any, prop: any) => {
|
|||||||
isAddNewMenu.value = false;
|
isAddNewMenu.value = false;
|
||||||
|
|
||||||
// 点击tree node时,加载对应的权限菜单
|
// 点击tree node时,加载对应的权限菜单
|
||||||
getPermissions({ menu: form.id });
|
// getPermissions({ menu: form.id });
|
||||||
};
|
};
|
||||||
|
|
||||||
const addPermission = () => {
|
const addPermission = () => {
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ export const createCrudOptions = function ({ crudExpose, rolePermission }: { cru
|
|||||||
title: '序号',
|
title: '序号',
|
||||||
form: { show: false },
|
form: { show: false },
|
||||||
column: {
|
column: {
|
||||||
//type: 'index',
|
type: 'index',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
width: '70px',
|
width: '70px',
|
||||||
columnSetDisabled: true, //禁止在列设置中选择
|
columnSetDisabled: true, //禁止在列设置中选择
|
||||||
|
|||||||
Reference in New Issue
Block a user