|
|
@@ -21,18 +21,15 @@
|
|
|
</el-form-item>
|
|
|
|
|
|
<el-form-item label="菜单名称" required>
|
|
|
- <el-tree-select
|
|
|
- v-if="isCreating"
|
|
|
- rowKey="key"
|
|
|
- :data="routeViewList"
|
|
|
+ <el-autocomplete
|
|
|
+ value-key="label"
|
|
|
+ v-model="formParams.menuName"
|
|
|
clearable
|
|
|
- check-strictly
|
|
|
- v-model="routeViewValue"
|
|
|
+ @select="handleSelectMenu"
|
|
|
+ :fetch-suggestions="querySearchMenu"
|
|
|
/>
|
|
|
- <el-input v-else v-model="formParams.menuName" disabled />
|
|
|
</el-form-item>
|
|
|
|
|
|
-
|
|
|
<el-row :gutter="24">
|
|
|
<el-col :span="12">
|
|
|
<el-form-item prop="routeUrl">
|
|
|
@@ -80,8 +77,8 @@
|
|
|
<QuestionCircleOutlined />
|
|
|
</el-icon>
|
|
|
<template #content>
|
|
|
- 访问的组件路径,如:`/system/menu/menu`,默认在`views`目录下,默认 `LAYOUT`
|
|
|
- 如果是多级菜单 `ParentLayout`
|
|
|
+ 访问的组件路径,如:`/system/menu/menu`,默认在`views`目录下,默认 `LAYOUT` 如果是多级菜单
|
|
|
+ `ParentLayout`
|
|
|
</template>
|
|
|
</el-tooltip>
|
|
|
<span>组件路径</span>
|
|
|
@@ -119,9 +116,7 @@
|
|
|
<el-icon :size="18" class="mr-1 text-gray-400 cursor-pointer">
|
|
|
<QuestionCircleOutlined />
|
|
|
</el-icon>
|
|
|
- <template #content>
|
|
|
- 默认跳转路由地址,如:`/system/menu/menu` 多级路由情况下适用
|
|
|
- </template>
|
|
|
+ <template #content> 默认跳转路由地址,如:`/system/menu/menu` 多级路由情况下适用 </template>
|
|
|
</el-tooltip>
|
|
|
<span>默认路由</span>
|
|
|
</div>
|
|
|
@@ -131,8 +126,6 @@
|
|
|
</el-col>
|
|
|
</el-row>
|
|
|
|
|
|
-
|
|
|
-
|
|
|
<el-row :gutter="24">
|
|
|
<el-col :span="12">
|
|
|
<el-form-item label="菜单编码">
|
|
|
@@ -146,8 +139,6 @@
|
|
|
</el-col>
|
|
|
</el-row>
|
|
|
|
|
|
-
|
|
|
-
|
|
|
<el-divider border-style="dashed" class="mb-10">功能设置</el-divider>
|
|
|
|
|
|
<el-row :gutter="24">
|
|
|
@@ -216,9 +207,7 @@
|
|
|
<el-icon :size="18" class="mr-1 text-gray-400 cursor-pointer">
|
|
|
<QuestionCircleOutlined />
|
|
|
</el-icon>
|
|
|
- <template #content
|
|
|
- >选择是则会被`keep-alive`缓存,需要匹配组件的`name`和地址保持一致</template
|
|
|
- >
|
|
|
+ <template #content>选择是则会被`keep-alive`缓存,需要匹配组件的`name`和地址保持一致</template>
|
|
|
</el-tooltip>
|
|
|
<span>是否缓存</span>
|
|
|
</div>
|
|
|
@@ -226,7 +215,7 @@
|
|
|
<el-radio-group v-model="formParams.isCache" name="isCacheGroup">
|
|
|
<el-radio-button label="不缓存" :value="0" />
|
|
|
<el-radio-button label="缓存" :value="1" />
|
|
|
- </el-radio-group>
|
|
|
+ </el-radio-group>
|
|
|
</el-form-item>
|
|
|
</el-col>
|
|
|
</el-row>
|
|
|
@@ -260,8 +249,7 @@
|
|
|
<QuestionCircleOutlined />
|
|
|
</el-icon>
|
|
|
<template #content
|
|
|
- >取消自动计算根路由模式
|
|
|
- 开启之后,当菜单子菜单只有1个的时候,会直接显示子菜单</template
|
|
|
+ >取消自动计算根路由模式 开启之后,当菜单子菜单只有1个的时候,会直接显示子菜单</template
|
|
|
>
|
|
|
</el-tooltip>
|
|
|
<span>简化路由</span>
|
|
|
@@ -287,7 +275,7 @@
|
|
|
|
|
|
<script lang="ts" setup>
|
|
|
import { ref, computed, watch, shallowRef } from 'vue';
|
|
|
- import { ElMessage, FormInstance, FormRules } from 'element-plus';
|
|
|
+ import { ElMessage, FormInstance, FormRules, ElAutocomplete } from 'element-plus';
|
|
|
import { addMenu, editMenu } from '@/api/system/menu';
|
|
|
import { QuestionCircleOutlined } from '@vicons/antd';
|
|
|
import { replaceParams } from '@/utils/helper/treeHelper';
|
|
|
@@ -338,7 +326,6 @@
|
|
|
},
|
|
|
};
|
|
|
|
|
|
-
|
|
|
const subLoading = ref(false);
|
|
|
|
|
|
const defaultFormParams: MenuDetailItem = {
|
|
|
@@ -360,7 +347,7 @@
|
|
|
isCache: 0,
|
|
|
isFrame: 0,
|
|
|
frameSrc: '',
|
|
|
- openType: 1,
|
|
|
+ openType: 1,
|
|
|
query: '',
|
|
|
activeMenu: '',
|
|
|
};
|
|
|
@@ -371,7 +358,7 @@
|
|
|
return [
|
|
|
{
|
|
|
label: '顶级目录',
|
|
|
- value: -1, // 约定顶级目录值是 -1.
|
|
|
+ value: -1, // 约定顶级目录值是 -1.
|
|
|
children: replaceParams(cloneDeep(props.parentMenuTree || []), 'label', 'id'),
|
|
|
},
|
|
|
];
|
|
|
@@ -381,25 +368,33 @@
|
|
|
const routeViewValue = ref('');
|
|
|
const routeViewList = shallowRef<_RouteViewItem[]>([]);
|
|
|
|
|
|
-
|
|
|
// 根据 "上级菜单",生成可选的"当前菜单"
|
|
|
watch(
|
|
|
() => formParams.value.parentId,
|
|
|
(newVal) => {
|
|
|
// 编辑模式下,只是展示,不需要计算数据。
|
|
|
if (isEditing.value) return;
|
|
|
+ // 切换上级菜单的时候,子菜单的所有信息要清空
|
|
|
+ formParams.value.routeName = '';
|
|
|
+ formParams.value.routeUrl = '';
|
|
|
+ formParams.value.component = '';
|
|
|
+ formParams.value.icon = '';
|
|
|
+ formParams.value.menuName = '';
|
|
|
+ formParams.value.menuCode = '';
|
|
|
+ formParams.value.redirect = '';
|
|
|
+ formParams.value.activeMenu = '';
|
|
|
|
|
|
// 若清除选项
|
|
|
if (newVal == null) {
|
|
|
routeViewList.value = [];
|
|
|
return;
|
|
|
- }
|
|
|
+ }
|
|
|
|
|
|
// 若选择顶级目录, 返回路由表的 leve1 列表
|
|
|
if (newVal === -1) {
|
|
|
routeViewList.value = getChildRoutesView(null);
|
|
|
return;
|
|
|
- }
|
|
|
+ }
|
|
|
|
|
|
// 否则展示 parent 下的 子路由
|
|
|
const { routeName } = getTreeItem(props.parentMenuTree!, newVal, 'id') as Menu;
|
|
|
@@ -408,25 +403,9 @@
|
|
|
} else {
|
|
|
ElMessage.error('无法获取可用路由列表');
|
|
|
}
|
|
|
- }
|
|
|
+ },
|
|
|
);
|
|
|
|
|
|
- // 根据 routeViewValue,即 routeName,将菜单其余信息补充
|
|
|
- watch(routeViewValue, (val) => {
|
|
|
- if (!val) {
|
|
|
- handleReset();
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- const currentRoute = getRouteByName(val);
|
|
|
- formParams.value.routeName = currentRoute.name;
|
|
|
- formParams.value.routeUrl = currentRoute.path;
|
|
|
- formParams.value.component = currentRoute.component;
|
|
|
- formParams.value.icon = currentRoute.meta.icon as string;
|
|
|
- formParams.value.menuName = currentRoute.meta.title as string;
|
|
|
- formParams.value.activeMenu = currentRoute.meta.activeMenu as string || '';
|
|
|
- });
|
|
|
-
|
|
|
function setData(data: MenuDetailItem) {
|
|
|
formParams.value = data;
|
|
|
formRef.value?.resetFields();
|
|
|
@@ -472,6 +451,30 @@
|
|
|
routeViewValue.value = '';
|
|
|
}
|
|
|
|
|
|
+ // 选中菜单的下拉框
|
|
|
+ const handleSelectMenu = (e) => {
|
|
|
+ const currentRoute = getRouteByName(e.value);
|
|
|
+ formParams.value.routeName = currentRoute.name;
|
|
|
+ formParams.value.routeUrl = currentRoute.path;
|
|
|
+ formParams.value.component = currentRoute.component;
|
|
|
+ formParams.value.icon = currentRoute.meta.icon as string;
|
|
|
+ formParams.value.activeMenu = (currentRoute.meta.activeMenu as string) || '';
|
|
|
+ };
|
|
|
+
|
|
|
+ const createFilter = (queryString: string) => {
|
|
|
+ return (routerItem: _RouteViewItem) => {
|
|
|
+ const str = queryString.toLowerCase();
|
|
|
+ return routerItem.label.toLowerCase().includes(str) || routerItem.value.toLowerCase().includes(str);
|
|
|
+ };
|
|
|
+ };
|
|
|
+
|
|
|
+ // 根据输入的值,过滤出符合条件的路由
|
|
|
+ const querySearchMenu = (queryString: string, cb) => {
|
|
|
+ if (!queryString.trim()) return routeViewList.value;
|
|
|
+ const filterList = routeViewList.value.filter(createFilter(queryString));
|
|
|
+ cb(filterList);
|
|
|
+ };
|
|
|
+
|
|
|
defineExpose({
|
|
|
formSubmit,
|
|
|
handleReset,
|