修改菜单
This commit is contained in:
@@ -96,11 +96,6 @@ public class OrionWebAutoConfiguration implements WebMvcConfigurer {
|
|||||||
// 默认 objectMapper
|
// 默认 objectMapper
|
||||||
ObjectMapper objectMapper = converter.getObjectMapper();
|
ObjectMapper objectMapper = converter.getObjectMapper();
|
||||||
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
|
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
|
||||||
// 序列化配置
|
|
||||||
SimpleModule module = new SimpleModule();
|
|
||||||
module.addSerializer(Long.class, ToStringSerializer.instance);
|
|
||||||
module.addSerializer(Long.TYPE, ToStringSerializer.instance);
|
|
||||||
objectMapper.registerModule(module);
|
|
||||||
return converter;
|
return converter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -37,6 +37,9 @@ public class SystemMenuUpdateRequest implements Serializable {
|
|||||||
@Schema(description = "排序")
|
@Schema(description = "排序")
|
||||||
private Integer sort;
|
private Integer sort;
|
||||||
|
|
||||||
|
@Schema(description = "菜单类型 1父菜单 2子菜单 3功能")
|
||||||
|
private Integer type;
|
||||||
|
|
||||||
@Schema(description = "是否可见 0不可见 1可见")
|
@Schema(description = "是否可见 0不可见 1可见")
|
||||||
private Integer visible;
|
private Integer visible;
|
||||||
|
|
||||||
|
|||||||
@@ -49,7 +49,6 @@ public class SystemMenuValidMenuRequest implements Serializable {
|
|||||||
@Schema(description = "菜单缓存 0不缓存 1缓存")
|
@Schema(description = "菜单缓存 0不缓存 1缓存")
|
||||||
private Integer cache;
|
private Integer cache;
|
||||||
|
|
||||||
@NotBlank
|
|
||||||
@Size(max = 64)
|
@Size(max = 64)
|
||||||
@Schema(description = "菜单图标")
|
@Schema(description = "菜单图标")
|
||||||
private String icon;
|
private String icon;
|
||||||
|
|||||||
@@ -64,5 +64,4 @@ public class SystemMenuVO implements Serializable {
|
|||||||
@Schema(description = "子节点")
|
@Schema(description = "子节点")
|
||||||
private List<SystemMenuVO> children;
|
private List<SystemMenuVO> children;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ public class SystemMenuServiceImpl implements SystemMenuService {
|
|||||||
// 转换
|
// 转换
|
||||||
SystemMenuDO updateRecord = SystemMenuConvert.MAPPER.to(request);
|
SystemMenuDO updateRecord = SystemMenuConvert.MAPPER.to(request);
|
||||||
// 验证参数
|
// 验证参数
|
||||||
this.validateRequest(updateRecord, record.getType());
|
this.validateRequest(updateRecord, request.getType());
|
||||||
// 更新
|
// 更新
|
||||||
int effect = systemMenuDAO.updateById(updateRecord);
|
int effect = systemMenuDAO.updateById(updateRecord);
|
||||||
log.info("SystemMenuService-updateSystemMenu effect: {}, updateRecord: {}", effect, JSON.toJSONString(updateRecord));
|
log.info("SystemMenuService-updateSystemMenu effect: {}, updateRecord: {}", effect, JSON.toJSONString(updateRecord));
|
||||||
|
|||||||
@@ -24,6 +24,10 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.hide {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
.ml4 {
|
.ml4 {
|
||||||
margin-left: 4px;
|
margin-left: 4px;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,7 +32,11 @@ const useMenuStore = defineStore('menu', {
|
|||||||
return node;
|
return node;
|
||||||
}).filter(Boolean);
|
}).filter(Boolean);
|
||||||
};
|
};
|
||||||
return render([{ name: '根目录', id: 0 }, ...state.menus]);
|
return [{
|
||||||
|
key: 0,
|
||||||
|
title: '根目录',
|
||||||
|
children: render([...state.menus])
|
||||||
|
}];
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -60,12 +64,12 @@ const useMenuStore = defineStore('menu', {
|
|||||||
// 子级
|
// 子级
|
||||||
for (let e of arr) {
|
for (let e of arr) {
|
||||||
if (e.children && e.children.length) {
|
if (e.children && e.children.length) {
|
||||||
// @ts-ignore
|
if (this.findParentMenu(e.children, id)) {
|
||||||
if (this.findParent(e.children, id) !== null) {
|
|
||||||
return e.children;
|
return e.children;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return null;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -15,16 +15,16 @@
|
|||||||
<a-form :model="formModel"
|
<a-form :model="formModel"
|
||||||
ref="formRef"
|
ref="formRef"
|
||||||
label-align="right"
|
label-align="right"
|
||||||
:style="{ width: '440px' }"
|
:style="{ width: '460px' }"
|
||||||
:label-col-props="{ span: 5 }"
|
:label-col-props="{ span: 6 }"
|
||||||
:wrapper-col-props="{ span: 19 }"
|
:wrapper-col-props="{ span: 18 }"
|
||||||
:rules="formRules">
|
:rules="formRules">
|
||||||
<!-- 上级菜单 -->
|
<!-- 上级菜单 -->
|
||||||
<a-form-item field="parentId" label="上级菜单">
|
<a-form-item field="parentId" label="上级菜单">
|
||||||
<menu-tree-selector v-model="formModel.parentId"
|
<menu-tree-selector v-model:model-value="formModel.parentId"
|
||||||
:disabled="!!(isAddHandle && formModel.id)" />
|
:disabled="formModel.type === MenuTypeEnum.PARENT_MENU.value" />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<!-- 名称 -->
|
<!-- 菜单名称 -->
|
||||||
<a-form-item field="name" label="菜单名称">
|
<a-form-item field="name" label="菜单名称">
|
||||||
<a-input v-model="formModel.name" placeholder="请输入菜单名称" />
|
<a-input v-model="formModel.name" placeholder="请输入菜单名称" />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
@@ -35,7 +35,9 @@
|
|||||||
:options="toOptions(MenuTypeEnum)" />
|
:options="toOptions(MenuTypeEnum)" />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<!-- 菜单图标 -->
|
<!-- 菜单图标 -->
|
||||||
<a-form-item field="icon" label="菜单图标">
|
<a-form-item v-if="formModel.type !== MenuTypeEnum.FUNCTION.value"
|
||||||
|
field="icon"
|
||||||
|
label="菜单图标">
|
||||||
<icon-picker v-model:icon="formModel.icon">
|
<icon-picker v-model:icon="formModel.icon">
|
||||||
<template #iconSelect>
|
<template #iconSelect>
|
||||||
<a-input v-model="formModel.icon" placeholder="请选择菜单图标" />
|
<a-input v-model="formModel.icon" placeholder="请选择菜单图标" />
|
||||||
@@ -43,19 +45,26 @@
|
|||||||
</icon-picker>
|
</icon-picker>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<!-- 菜单权限 -->
|
<!-- 菜单权限 -->
|
||||||
<a-form-item field="permission" label="菜单权限">
|
<a-form-item v-if="formModel.type === MenuTypeEnum.FUNCTION.value"
|
||||||
|
field="permission"
|
||||||
|
label="菜单权限">
|
||||||
<a-input v-model="formModel.permission"
|
<a-input v-model="formModel.permission"
|
||||||
placeholder="菜单权限 infra:system-menu:query"
|
placeholder="菜单权限 infra:system-menu:query"
|
||||||
allow-clear />
|
allow-clear />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<!-- 外链地址 -->
|
<!-- 外链地址 -->
|
||||||
<a-form-item field="path" label="外链地址">
|
<a-form-item v-if="formModel.type !== MenuTypeEnum.FUNCTION.value"
|
||||||
|
field="path"
|
||||||
|
label="外链地址"
|
||||||
|
tooltip="输入组件名称后则不会生效">
|
||||||
<a-input v-model="formModel.path"
|
<a-input v-model="formModel.path"
|
||||||
placeholder="外链地址与组件名称二选一"
|
placeholder="外链地址与组件名称二选一"
|
||||||
allow-clear />
|
allow-clear />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<!-- 组件名称 -->
|
<!-- 组件名称 -->
|
||||||
<a-form-item field="component" label="组件名称">
|
<a-form-item v-if="formModel.type !== MenuTypeEnum.FUNCTION.value"
|
||||||
|
field="component"
|
||||||
|
label="组件名称">
|
||||||
<a-input v-model="formModel.component"
|
<a-input v-model="formModel.component"
|
||||||
placeholder="路由组件名称"
|
placeholder="路由组件名称"
|
||||||
allow-clear />
|
allow-clear />
|
||||||
@@ -67,14 +76,20 @@
|
|||||||
:style="{ width: '120px' }"
|
:style="{ width: '120px' }"
|
||||||
allow-clear />
|
allow-clear />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<!-- 可见状态 -->
|
<!-- 是否可见 -->
|
||||||
<a-form-item field="type" label="可见状态">
|
<a-form-item v-if="formModel.type !== MenuTypeEnum.FUNCTION.value"
|
||||||
|
field="type"
|
||||||
|
label="是否可见"
|
||||||
|
tooltip="选择隐藏后不会在菜单以及 tab 中显示 但是可以访问">
|
||||||
<a-radio-group type="button"
|
<a-radio-group type="button"
|
||||||
v-model="formModel.visible"
|
v-model="formModel.visible"
|
||||||
:options="toOptions(MenuVisibleEnum)" />
|
:options="toOptions(MenuVisibleEnum)" />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<!-- 缓存状态 -->
|
<!-- 是否缓存 -->
|
||||||
<a-form-item field="type" label="缓存状态">
|
<a-form-item v-if="formModel.type !== MenuTypeEnum.FUNCTION.value"
|
||||||
|
field="type"
|
||||||
|
label="是否缓存"
|
||||||
|
tooltip="选择缓存后则会使用 keep-alive 缓存组件">
|
||||||
<a-radio-group type="button"
|
<a-radio-group type="button"
|
||||||
v-model="formModel.cache"
|
v-model="formModel.cache"
|
||||||
:options="toOptions(MenuCacheEnum)" />
|
:options="toOptions(MenuCacheEnum)" />
|
||||||
@@ -91,7 +106,7 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { reactive, ref } from 'vue';
|
import { reactive, ref, watch, watchEffect } from 'vue';
|
||||||
import useLoading from '@/hooks/loading';
|
import useLoading from '@/hooks/loading';
|
||||||
import useVisible from '@/hooks/visible';
|
import useVisible from '@/hooks/visible';
|
||||||
import formRules from '../type/form.rules';
|
import formRules from '../type/form.rules';
|
||||||
@@ -100,6 +115,7 @@
|
|||||||
import IconPicker from '@sanqi377/arco-vue-icon-picker';
|
import IconPicker from '@sanqi377/arco-vue-icon-picker';
|
||||||
import MenuTreeSelector from '@/views/system/menu/components/menu-tree-selector.vue';
|
import MenuTreeSelector from '@/views/system/menu/components/menu-tree-selector.vue';
|
||||||
import { createMenu, updateMenu } from '@/api/system/menu';
|
import { createMenu, updateMenu } from '@/api/system/menu';
|
||||||
|
import { keysIn } from 'lodash';
|
||||||
|
|
||||||
const { visible, setVisible } = useVisible();
|
const { visible, setVisible } = useVisible();
|
||||||
const { loading, setLoading } = useLoading();
|
const { loading, setLoading } = useLoading();
|
||||||
@@ -107,28 +123,39 @@
|
|||||||
const title = ref<string>();
|
const title = ref<string>();
|
||||||
const isAddHandle = ref<boolean>(true);
|
const isAddHandle = ref<boolean>(true);
|
||||||
|
|
||||||
|
const defaultForm = () => {
|
||||||
|
return {
|
||||||
|
id: undefined,
|
||||||
|
parentId: 0,
|
||||||
|
name: undefined,
|
||||||
|
type: MenuTypeEnum.PARENT_MENU.value,
|
||||||
|
permission: undefined,
|
||||||
|
sort: 10,
|
||||||
|
visible: MenuVisibleEnum.SHOW.value,
|
||||||
|
cache: MenuCacheEnum.SHOW.value,
|
||||||
|
icon: undefined,
|
||||||
|
path: undefined,
|
||||||
|
component: undefined,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
const formRef = ref<any>();
|
const formRef = ref<any>();
|
||||||
const formModel = reactive<Record<string, any>>({
|
const formModel = reactive<Record<string, any>>(defaultForm());
|
||||||
id: undefined,
|
|
||||||
parentId: undefined,
|
|
||||||
name: undefined,
|
|
||||||
type: undefined,
|
|
||||||
permission: undefined,
|
|
||||||
sort: undefined,
|
|
||||||
visible: undefined,
|
|
||||||
cache: undefined,
|
|
||||||
icon: undefined,
|
|
||||||
path: undefined,
|
|
||||||
component: undefined,
|
|
||||||
});
|
|
||||||
|
|
||||||
const emits = defineEmits(['added', 'updated']);
|
const emits = defineEmits(['added', 'updated']);
|
||||||
|
|
||||||
|
// 选择根目录 parentId就是 0
|
||||||
|
watch(() => formModel.type, () => {
|
||||||
|
if (formModel.type === MenuTypeEnum.PARENT_MENU.value) {
|
||||||
|
formModel.parentId = 0;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// 打开新增
|
// 打开新增
|
||||||
const openAdd = (record: any) => {
|
const openAdd = (record: any) => {
|
||||||
title.value = '添加菜单';
|
title.value = '添加菜单';
|
||||||
isAddHandle.value = true;
|
isAddHandle.value = true;
|
||||||
renderForm(record);
|
renderForm({ ...defaultForm(), ...record });
|
||||||
setVisible(true);
|
setVisible(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -136,12 +163,10 @@
|
|||||||
const openUpdate = (record: any) => {
|
const openUpdate = (record: any) => {
|
||||||
title.value = '修改菜单';
|
title.value = '修改菜单';
|
||||||
isAddHandle.value = false;
|
isAddHandle.value = false;
|
||||||
renderForm(record);
|
renderForm({ ...defaultForm(), ...record });
|
||||||
setVisible(true);
|
setVisible(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
defineExpose({ openAdd, openUpdate });
|
|
||||||
|
|
||||||
// 渲染表单
|
// 渲染表单
|
||||||
const renderForm = (record: any) => {
|
const renderForm = (record: any) => {
|
||||||
Object.keys(formModel).forEach(k => {
|
Object.keys(formModel).forEach(k => {
|
||||||
@@ -149,6 +174,8 @@
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
defineExpose({ openAdd, openUpdate });
|
||||||
|
|
||||||
// 确定
|
// 确定
|
||||||
const handlerOk = async () => {
|
const handlerOk = async () => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
@@ -161,14 +188,14 @@
|
|||||||
if (isAddHandle.value) {
|
if (isAddHandle.value) {
|
||||||
// 新增
|
// 新增
|
||||||
await createMenu(formModel as any);
|
await createMenu(formModel as any);
|
||||||
emits('added', { ...formModel });
|
emits('added');
|
||||||
} else {
|
} else {
|
||||||
// 修改
|
// 修改
|
||||||
await updateMenu(formModel as any);
|
await updateMenu(formModel as any);
|
||||||
emits('updated', { ...formModel });
|
emits('updated');
|
||||||
}
|
}
|
||||||
// 清空
|
// 清空
|
||||||
// handlerClear();
|
handlerClear();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return false;
|
return false;
|
||||||
} finally {
|
} finally {
|
||||||
@@ -185,7 +212,6 @@
|
|||||||
const handlerClear = () => {
|
const handlerClear = () => {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
setVisible(false);
|
setVisible(false);
|
||||||
renderForm({});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -97,7 +97,8 @@
|
|||||||
{{ getEnumValue(record.status, MenuStatusEnum) }}
|
{{ getEnumValue(record.status, MenuStatusEnum) }}
|
||||||
</a-tag>
|
</a-tag>
|
||||||
<!-- 显示状态 -->
|
<!-- 显示状态 -->
|
||||||
<a-tag :color="getEnumValue(record.visible, MenuVisibleEnum,'color')">
|
<a-tag v-if="(record.visible || record.visible === 0) && record.type !== MenuTypeEnum.FUNCTION.value"
|
||||||
|
:color="getEnumValue(record.visible, MenuVisibleEnum,'color')">
|
||||||
{{ getEnumValue(record.visible, MenuVisibleEnum) }}
|
{{ getEnumValue(record.visible, MenuVisibleEnum) }}
|
||||||
</a-tag>
|
</a-tag>
|
||||||
</a-space>
|
</a-space>
|
||||||
@@ -110,7 +111,7 @@
|
|||||||
size="mini"
|
size="mini"
|
||||||
v-if="record.type !== MenuTypeEnum.FUNCTION.value"
|
v-if="record.type !== MenuTypeEnum.FUNCTION.value"
|
||||||
v-permission="['infra:system-menu:create']"
|
v-permission="['infra:system-menu:create']"
|
||||||
@click="emits('openAdd', { id: record.id, parentId: record.id })">
|
@click="emits('openAdd', { parentId: record.id })">
|
||||||
新增
|
新增
|
||||||
</a-button>
|
</a-button>
|
||||||
<!-- 修改 -->
|
<!-- 修改 -->
|
||||||
@@ -192,13 +193,13 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
// 添加后回调
|
// 添加后回调
|
||||||
const addedCallback = (record: any) => {
|
const addedCallback = () => {
|
||||||
console.log('addCallback', record);
|
loadMenuData();
|
||||||
};
|
};
|
||||||
|
|
||||||
// 更新后回调
|
// 更新后回调
|
||||||
const updatedCallback = (record: any) => {
|
const updatedCallback = () => {
|
||||||
console.log('updateCallback', record);
|
loadMenuData();
|
||||||
};
|
};
|
||||||
|
|
||||||
defineExpose({
|
defineExpose({
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
<template>
|
<template>
|
||||||
<a-tree-select :default-value="modelValue"
|
<a-tree-select v-model:model-value="value"
|
||||||
:data="treeData"
|
:data="treeData"
|
||||||
:disabled="disabled"
|
:disabled="disabled"
|
||||||
:allow-search="true"
|
:allow-search="true"
|
||||||
:filter-tree-node="filterTreeNode"
|
:filter-tree-node="filterTreeNode"
|
||||||
placeholder="请选择上级菜单"
|
placeholder="请选择上级菜单" />
|
||||||
@change="onChange" />
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
@@ -16,12 +15,23 @@
|
|||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { useMenuStore } from '@/store';
|
import { useMenuStore } from '@/store';
|
||||||
|
import { computed } from 'vue';
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
modelValue: Number,
|
||||||
|
disabled: Boolean
|
||||||
|
});
|
||||||
|
|
||||||
defineProps(['modelValue', 'disabled']);
|
|
||||||
const emits = defineEmits(['update:modelValue']);
|
const emits = defineEmits(['update:modelValue']);
|
||||||
const onChange = (e: any) => {
|
|
||||||
emits('update:modelValue', e);
|
const value = computed({
|
||||||
};
|
get() {
|
||||||
|
return props.modelValue;
|
||||||
|
},
|
||||||
|
set(e) {
|
||||||
|
emits('update:modelValue', e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// 树数据
|
// 树数据
|
||||||
const menuStore = useMenuStore();
|
const menuStore = useMenuStore();
|
||||||
|
|||||||
@@ -6,8 +6,8 @@
|
|||||||
@openUpdate="(e) => modal.openUpdate(e)" />
|
@openUpdate="(e) => modal.openUpdate(e)" />
|
||||||
<!-- 添加修改框 -->
|
<!-- 添加修改框 -->
|
||||||
<menu-form-modal ref="modal"
|
<menu-form-modal ref="modal"
|
||||||
@added="(e) => table.addedCallback(e)"
|
@added="() => table.addedCallback()"
|
||||||
@updated="(e) => table.updatedCallback(e)" />
|
@updated="() => table.updatedCallback()" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,44 @@
|
|||||||
import { FieldRule } from '@arco-design/web-vue';
|
import { FieldRule } from '@arco-design/web-vue';
|
||||||
|
|
||||||
|
export const parentId = [{
|
||||||
|
required: true,
|
||||||
|
message: '请选择父菜单'
|
||||||
|
}] as FieldRule[];
|
||||||
|
|
||||||
export const name = [{
|
export const name = [{
|
||||||
required: true,
|
required: true,
|
||||||
|
message: '请输入菜单名称'
|
||||||
|
}, {
|
||||||
|
maxLength: 32,
|
||||||
|
message: `菜单名称长度不能大于32位`
|
||||||
|
}] as FieldRule[];
|
||||||
|
|
||||||
|
export const type = [{
|
||||||
|
required: true,
|
||||||
|
message: '请选择菜单类型'
|
||||||
|
}] as FieldRule[];
|
||||||
|
|
||||||
|
export const sort = [{
|
||||||
|
required: true,
|
||||||
|
message: '请输入菜单排序'
|
||||||
|
}] as FieldRule[];
|
||||||
|
|
||||||
|
export const visible = [{
|
||||||
|
required: true,
|
||||||
|
message: '请选择是否可见'
|
||||||
|
}] as FieldRule[];
|
||||||
|
|
||||||
|
export const cache = [{
|
||||||
|
required: true,
|
||||||
|
message: '请选择是否缓存'
|
||||||
}] as FieldRule[];
|
}] as FieldRule[];
|
||||||
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name
|
parentId,
|
||||||
|
name,
|
||||||
|
type,
|
||||||
|
sort,
|
||||||
|
visible,
|
||||||
|
cache,
|
||||||
} as Record<string, FieldRule | FieldRule[]>;
|
} as Record<string, FieldRule | FieldRule[]>;
|
||||||
|
|||||||
Reference in New Issue
Block a user