增加悬浮窗功能
This commit is contained in:
@@ -3,7 +3,7 @@ import { Account_BaseUrl } from "@/api/config";
|
|||||||
const baseURL = Account_BaseUrl + "/admin/quick";
|
const baseURL = Account_BaseUrl + "/admin/quick";
|
||||||
const API = {
|
const API = {
|
||||||
getList(data: any) {
|
getList(data: any) {
|
||||||
return request<any>({
|
return request<any, QuickMenu[]>({
|
||||||
url: `${baseURL}`,
|
url: `${baseURL}`,
|
||||||
method: "get",
|
method: "get",
|
||||||
params: data
|
params: data
|
||||||
@@ -35,3 +35,34 @@ export default API;
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 悬浮窗配置 实体类。
|
||||||
|
*
|
||||||
|
* QuickMenu
|
||||||
|
*/
|
||||||
|
export interface QuickMenu {
|
||||||
|
createTime?: string;
|
||||||
|
id?: number;
|
||||||
|
/**
|
||||||
|
* 菜单Id
|
||||||
|
*/
|
||||||
|
menuId: number;
|
||||||
|
/**
|
||||||
|
* 店铺Id
|
||||||
|
*/
|
||||||
|
shopId?: number;
|
||||||
|
/**
|
||||||
|
* 排序
|
||||||
|
*/
|
||||||
|
sort?: number;
|
||||||
|
/**
|
||||||
|
* 状态 1-启用 0-禁用
|
||||||
|
*/
|
||||||
|
status?: number;
|
||||||
|
updateTime?: string;
|
||||||
|
/**
|
||||||
|
* 菜单图标
|
||||||
|
*/
|
||||||
|
url?: string;
|
||||||
|
[property: string]: any;
|
||||||
|
}
|
||||||
|
|||||||
@@ -8,6 +8,8 @@
|
|||||||
:data="menus"
|
:data="menus"
|
||||||
:render-after-expand="false"
|
:render-after-expand="false"
|
||||||
style="width: 240px"
|
style="width: 240px"
|
||||||
|
node-key="menuId"
|
||||||
|
:disabled-key="disabled"
|
||||||
></el-tree-select>
|
></el-tree-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
@@ -40,7 +42,9 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, onMounted } from "vue";
|
// 补充缺失的导入
|
||||||
|
import { ref, onMounted, watch } from "vue";
|
||||||
|
import { ElNotification, ElMessage } from "element-plus"; // 导入提示组件
|
||||||
import { filterNumberInput } from "@/utils";
|
import { filterNumberInput } from "@/utils";
|
||||||
import { roleTemplateAdd } from "@/api/account/roleTemplate";
|
import { roleTemplateAdd } from "@/api/account/roleTemplate";
|
||||||
import MenuAPI from "@/api/account/menu";
|
import MenuAPI from "@/api/account/menu";
|
||||||
@@ -50,80 +54,147 @@ const props = defineProps({
|
|||||||
isGetMenu: {
|
isGetMenu: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
required: false,
|
required: false,
|
||||||
|
default: false, // 补充默认值
|
||||||
},
|
},
|
||||||
parMenus: {
|
parMenus: {
|
||||||
type: Array,
|
type: Array,
|
||||||
required: false,
|
required: false,
|
||||||
|
default: () => [], // 补充默认值
|
||||||
},
|
},
|
||||||
item: {
|
item: {
|
||||||
type: Object,
|
type: Object,
|
||||||
required: false,
|
required: false,
|
||||||
|
default: () => null,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
watch(
|
|
||||||
() => props.item,
|
|
||||||
(newval) => {
|
|
||||||
if (newval) {
|
|
||||||
form.value = newval;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{ deep: true }
|
|
||||||
);
|
|
||||||
const menus = ref([]);
|
const menus = ref([]);
|
||||||
onMounted(async () => {
|
|
||||||
if (!props.isGetMenu) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const res = await MenuAPI.getRoutes();
|
|
||||||
console.log("getRoutes", res);
|
|
||||||
menus.value = returnMenu(res);
|
|
||||||
console.log(menus.value);
|
|
||||||
});
|
|
||||||
|
|
||||||
watch(
|
|
||||||
() => props.parMenus.length,
|
|
||||||
(newval) => {
|
|
||||||
menus.value = returnMenu(props.parMenus);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 格式化菜单数据:核心逻辑 - 禁用有子菜单的父节点,仅允许选叶子节点
|
||||||
|
* @param arr 原始菜单数组
|
||||||
|
* @returns 格式化后带禁用标记的菜单数组
|
||||||
|
*/
|
||||||
function returnMenu(arr) {
|
function returnMenu(arr) {
|
||||||
let result = [];
|
let result = [];
|
||||||
for (let menu of arr) {
|
for (let menu of arr) {
|
||||||
menu.label = menu.title;
|
// 过滤掉"默认接口目录"
|
||||||
menu.value = menu.menuId;
|
if (menu.title === "默认接口目录") continue;
|
||||||
result.push({
|
|
||||||
|
// 筛选有效子菜单:非隐藏 + 类型为0
|
||||||
|
const children = menu.children ? menu.children.filter((v) => !v.hidden && v.type === 0) : [];
|
||||||
|
// 递归处理子菜单
|
||||||
|
const formattedChildren = returnMenu(children);
|
||||||
|
|
||||||
|
// 核心:判断是否为叶子节点(无有效子菜单)
|
||||||
|
const isLeaf = formattedChildren.length === 0;
|
||||||
|
|
||||||
|
// 组装节点:有子菜单则禁用(disabled: true),无则允许选择
|
||||||
|
const menuNode = {
|
||||||
...menu,
|
...menu,
|
||||||
label: menu.title,
|
label: menu.title,
|
||||||
value: menu.menuId,
|
value: menu.menuId,
|
||||||
children: menu.children ? returnMenu(menu.children) : [],
|
menuId: menu.menuId, // 保持node-key一致
|
||||||
});
|
disabled: !isLeaf, // 有子菜单 → 禁用,无 → 启用
|
||||||
|
children: formattedChildren,
|
||||||
|
};
|
||||||
|
|
||||||
|
// 特殊处理:如果子菜单只有1个,直接扁平化(保持原有逻辑)
|
||||||
|
if (formattedChildren.length === 1) {
|
||||||
|
result.push({
|
||||||
|
...formattedChildren[0],
|
||||||
|
disabled: formattedChildren[0].children.length > 0, // 子节点仍判断是否有后代
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
result.push(menuNode);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
if (!props.isGetMenu) return;
|
||||||
|
try {
|
||||||
|
const res = await MenuAPI.getRoutes();
|
||||||
|
menus.value = returnMenu(res);
|
||||||
|
} catch (error) {
|
||||||
|
ElMessage.error("菜单数据加载失败");
|
||||||
|
console.error("getRoutes error:", error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 监听父组件传入的菜单变化
|
||||||
|
watch(
|
||||||
|
() => props.parMenus,
|
||||||
|
(newVal) => {
|
||||||
|
if (newVal.length) {
|
||||||
|
menus.value = returnMenu(newVal);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ deep: true } // 监听数组内部变化
|
||||||
|
);
|
||||||
|
|
||||||
|
// 对话框显隐绑定
|
||||||
const visible = defineModel({
|
const visible = defineModel({
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
required: false,
|
required: false,
|
||||||
|
default: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
const formRef = ref(null);
|
const formRef = ref(null);
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
|
// 表单初始化
|
||||||
const form = ref({
|
const form = ref({
|
||||||
menuId: "",
|
menuId: "",
|
||||||
sort: 0,
|
sort: 0,
|
||||||
url: "",
|
url: "",
|
||||||
status: 1,
|
status: 1,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自定义校验规则:确保选中的是叶子节点(兜底验证)
|
||||||
|
* @param rule 校验规则
|
||||||
|
* @param value 选中的menuId
|
||||||
|
* @param callback 回调函数
|
||||||
|
*/
|
||||||
|
function validateLeafMenu(rule, value, callback) {
|
||||||
|
if (!value) {
|
||||||
|
return callback(new Error("请选择菜单"));
|
||||||
|
}
|
||||||
|
// 递归查找节点,判断是否为叶子节点
|
||||||
|
const findNode = (nodes, menuId) => {
|
||||||
|
for (let node of nodes) {
|
||||||
|
if (node.menuId === menuId) return node;
|
||||||
|
if (node.children) {
|
||||||
|
const res = findNode(node.children, menuId);
|
||||||
|
if (res) return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
const selectedNode = findNode(menus.value, value);
|
||||||
|
|
||||||
|
if (!selectedNode) {
|
||||||
|
callback(new Error("选择的菜单不存在"));
|
||||||
|
} else if (selectedNode.disabled) {
|
||||||
|
callback(new Error("有子菜单的父节点不可选,请选择子菜单"));
|
||||||
|
} else {
|
||||||
|
callback(); // 校验通过
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 表单校验规则:修复拼写错误 + 新增自定义叶子节点校验
|
||||||
const rules = ref({
|
const rules = ref({
|
||||||
menuId: [
|
menuId: [
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
message: "请选择菜单",
|
validator: validateLeafMenu, // 替换原有规则为自定义校验
|
||||||
triiger: "blur",
|
trigger: "change", // 选择变化时校验(原triiger拼写错误)
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 重置表单
|
||||||
function resetForm() {
|
function resetForm() {
|
||||||
form.value = {
|
form.value = {
|
||||||
menuId: "",
|
menuId: "",
|
||||||
@@ -131,48 +202,65 @@ function resetForm() {
|
|||||||
url: "",
|
url: "",
|
||||||
status: 1,
|
status: 1,
|
||||||
};
|
};
|
||||||
formRef.value.resetFields();
|
if (formRef.value) {
|
||||||
|
formRef.value.resetFields(); // 避免null调用
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 提交
|
// 提交事件
|
||||||
const emits = defineEmits(["success"]);
|
const emits = defineEmits(["success"]);
|
||||||
function submitHandle() {
|
async function submitHandle() {
|
||||||
formRef.value.validate(async (vaild) => {
|
try {
|
||||||
try {
|
// 修复vaild拼写错误
|
||||||
if (vaild) {
|
const valid = await formRef.value.validate();
|
||||||
loading.value = true;
|
if (!valid) return;
|
||||||
if (form.value.sort === "") {
|
|
||||||
form.value.sort = 0;
|
|
||||||
}
|
|
||||||
await quickApi.add(form.value);
|
|
||||||
|
|
||||||
ElNotification({
|
loading.value = true;
|
||||||
title: "注意",
|
// 排序值兜底
|
||||||
message: "添加成功",
|
form.value.sort = form.value.sort === "" ? 0 : form.value.sort;
|
||||||
type: "success",
|
|
||||||
});
|
|
||||||
|
|
||||||
emits("success");
|
// 区分新增/编辑
|
||||||
|
if (form.value.id) {
|
||||||
visible.value = false;
|
await quickApi.edit(form.value);
|
||||||
}
|
ElNotification({ title: "成功", message: "编辑成功", type: "success" });
|
||||||
} catch (error) {
|
} else {
|
||||||
console.log(error);
|
await quickApi.add(form.value);
|
||||||
|
ElNotification({ title: "成功", message: "添加成功", type: "success" });
|
||||||
}
|
}
|
||||||
setTimeout(() => {
|
|
||||||
loading.value = false;
|
emits("success");
|
||||||
}, 500);
|
visible.value = false;
|
||||||
});
|
} catch (error) {
|
||||||
|
ElMessage.error(form.value.id ? "编辑失败" : "添加失败");
|
||||||
|
console.error("submit error:", error);
|
||||||
|
} finally {
|
||||||
|
loading.value = false; // 无论成败都关闭loading
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 监听props.item初始化表单
|
||||||
|
watch(
|
||||||
|
() => props.item,
|
||||||
|
(newval) => {
|
||||||
|
if (newval) {
|
||||||
|
form.value = { ...newval }; // 深拷贝,避免修改原对象
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ deep: true, immediate: true } // 初始化触发
|
||||||
|
);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
.dialog_footer {
|
.dialog_footer {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 14px;
|
gap: 14px;
|
||||||
|
|
||||||
.btn {
|
.btn {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// 可选:美化禁用节点的样式
|
||||||
|
.el-select-dropdown__item.is-disabled {
|
||||||
|
color: var(--el-text-color-regular);
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -55,7 +55,10 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, reactive, onMounted } from "vue";
|
import { useQuickStore, usePermissionStore } from "@/store";
|
||||||
|
const quickStore = useQuickStore();
|
||||||
|
|
||||||
|
import { ref, reactive, onMounted, toRaw } from "vue";
|
||||||
import MenuAPI from "@/api/account/menu";
|
import MenuAPI from "@/api/account/menu";
|
||||||
|
|
||||||
import quickApi from "@/api/account/quick";
|
import quickApi from "@/api/account/quick";
|
||||||
@@ -64,9 +67,9 @@ import dialogAdd from "./dialog-add.vue";
|
|||||||
|
|
||||||
const showAdd = ref(false);
|
const showAdd = ref(false);
|
||||||
|
|
||||||
const nowEditMenu = ref({});
|
const nowEditMenu = ref(null);
|
||||||
function editMenu(item) {
|
function editMenu(item) {
|
||||||
nowEditMenu.value = item;
|
nowEditMenu.value = { ...item };
|
||||||
showAdd.value = true;
|
showAdd.value = true;
|
||||||
}
|
}
|
||||||
const tableData = reactive({
|
const tableData = reactive({
|
||||||
@@ -78,6 +81,7 @@ const tableData = reactive({
|
|||||||
});
|
});
|
||||||
|
|
||||||
function Refresh() {
|
function Refresh() {
|
||||||
|
quickStore.getQuickMenus();
|
||||||
getList();
|
getList();
|
||||||
}
|
}
|
||||||
function getList() {
|
function getList() {
|
||||||
@@ -86,7 +90,7 @@ function getList() {
|
|||||||
.getList({
|
.getList({
|
||||||
page: tableData.page,
|
page: tableData.page,
|
||||||
size: tableData.size,
|
size: tableData.size,
|
||||||
isEdit: true,
|
isEdit: 1,
|
||||||
})
|
})
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
tableData.list = res;
|
tableData.list = res;
|
||||||
@@ -101,25 +105,45 @@ const menus = ref([]);
|
|||||||
async function getMenus() {
|
async function getMenus() {
|
||||||
const res = await MenuAPI.getRoutes();
|
const res = await MenuAPI.getRoutes();
|
||||||
menus.value = res;
|
menus.value = res;
|
||||||
|
console.log("menus", res);
|
||||||
}
|
}
|
||||||
const menusIdMap = computed(() => {
|
const menusIdMap = computed(() => {
|
||||||
const map = getMenuMao();
|
const map = getMenuMap();
|
||||||
|
console.log("map", map);
|
||||||
|
|
||||||
return map;
|
return map;
|
||||||
});
|
});
|
||||||
function returnMenuName(item) {
|
function returnMenuName(item) {
|
||||||
const menu = menusIdMap.value.get(`${item.menuId}`);
|
const menu = menusIdMap.value.get(`${item.menuId}`);
|
||||||
return menu.title;
|
console.log("menuId", item.menuId);
|
||||||
|
console.log("menu", menu);
|
||||||
|
|
||||||
|
return menu ? menu.title : "";
|
||||||
}
|
}
|
||||||
function getMenuMao() {
|
function getMenuMap() {
|
||||||
|
// 初始化Map
|
||||||
const map = new Map();
|
const map = new Map();
|
||||||
for (const menu of menus.value) {
|
|
||||||
map.set(menu.menuId, menu);
|
// 定义递归函数处理菜单节点
|
||||||
if (menu.children && menu.children.length > 0) {
|
function processMenuNode(menuNode) {
|
||||||
for (const child of menu.children) {
|
// 将当前节点存入Map
|
||||||
map.set(child.menuId, child);
|
map.set(menuNode.menuId, menuNode);
|
||||||
}
|
|
||||||
|
// 如果有子节点且子节点数组不为空,则递归处理每个子节点
|
||||||
|
if (menuNode.children && Array.isArray(menuNode.children) && menuNode.children.length > 0) {
|
||||||
|
menuNode.children.forEach((childNode) => {
|
||||||
|
processMenuNode(childNode);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 遍历根级菜单,逐个处理
|
||||||
|
if (menus.value && Array.isArray(menus.value)) {
|
||||||
|
menus.value.forEach((rootMenu) => {
|
||||||
|
processMenuNode(rootMenu);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
function isEnableChange(value, item) {
|
function isEnableChange(value, item) {
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
<div class="fast-menu">
|
<div class="fast-menu">
|
||||||
<el-dropdown
|
<el-dropdown
|
||||||
trigger="click"
|
trigger="click"
|
||||||
|
@command="menuClick"
|
||||||
placement="top-end"
|
placement="top-end"
|
||||||
@visible-change="handleVisibleChange"
|
@visible-change="handleVisibleChange"
|
||||||
append-to-body="true"
|
append-to-body="true"
|
||||||
@@ -13,8 +14,18 @@
|
|||||||
</el-icon> -->
|
</el-icon> -->
|
||||||
<template #dropdown>
|
<template #dropdown>
|
||||||
<el-dropdown-menu>
|
<el-dropdown-menu>
|
||||||
<el-dropdown-item v-for="(item, index) in list" :key="index">
|
<el-dropdown-item
|
||||||
Action {{ index + 1 }}
|
v-for="(item, index) in quickStore.quickMenus"
|
||||||
|
:key="index"
|
||||||
|
:command="item.menuId"
|
||||||
|
>
|
||||||
|
{{ returnMenuName(item.menuId) }}
|
||||||
|
</el-dropdown-item>
|
||||||
|
<el-dropdown-item :command="-1">
|
||||||
|
<el-icon>
|
||||||
|
<Edit color="#4080FF" />
|
||||||
|
</el-icon>
|
||||||
|
<span style="color: #4080ff">编辑</span>
|
||||||
</el-dropdown-item>
|
</el-dropdown-item>
|
||||||
</el-dropdown-menu>
|
</el-dropdown-menu>
|
||||||
</template>
|
</template>
|
||||||
@@ -22,8 +33,30 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref } from "vue";
|
import { ref, computed } from "vue";
|
||||||
const list = ref(new Array(10).fill(1));
|
import { useQuickStore, usePermissionStore, useUserStore } from "@/store";
|
||||||
|
import router from "@/router";
|
||||||
|
|
||||||
|
const userStore = useUserStore();
|
||||||
|
const quickStore = useQuickStore();
|
||||||
|
const permissionStore = usePermissionStore();
|
||||||
|
console.log("permissionStore", permissionStore.menus);
|
||||||
|
|
||||||
|
function menuClick(menuId: number) {
|
||||||
|
console.log("menuId", menuId);
|
||||||
|
if (menuId == -1) {
|
||||||
|
if (userStore.userInfo.id == 1) {
|
||||||
|
return router.push("/system/commonlyUsedMenu");
|
||||||
|
} else {
|
||||||
|
return router.push("/commonlyUsedMenu");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
permissionStore.menuJump(menuId);
|
||||||
|
}
|
||||||
|
|
||||||
|
function returnMenuName(menuId: number) {
|
||||||
|
return permissionStore.returnMenuName(menuId);
|
||||||
|
}
|
||||||
|
|
||||||
const imgsrc = computed(() => {
|
const imgsrc = computed(() => {
|
||||||
return showMenu.value
|
return showMenu.value
|
||||||
|
|||||||
@@ -14,5 +14,6 @@ export * from "./modules/settings";
|
|||||||
export * from "./modules/tags-view";
|
export * from "./modules/tags-view";
|
||||||
export * from "./modules/user";
|
export * from "./modules/user";
|
||||||
export * from "./modules/dict";
|
export * from "./modules/dict";
|
||||||
|
export * from "./modules/quick";
|
||||||
|
|
||||||
export { store };
|
export { store };
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ export const usePermissionStore = defineStore("permission", () => {
|
|||||||
// 路由是否加载完成
|
// 路由是否加载完成
|
||||||
const isRoutesLoaded = ref(false);
|
const isRoutesLoaded = ref(false);
|
||||||
|
|
||||||
|
const menus = ref<RouteVO[]>([])
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -31,6 +32,7 @@ export const usePermissionStore = defineStore("permission", () => {
|
|||||||
}
|
}
|
||||||
MenuAPI.getRoutes()
|
MenuAPI.getRoutes()
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
|
menus.value = data
|
||||||
if (!isTest) {
|
if (!isTest) {
|
||||||
const dynamicRoutes = parseDynamicRoutes(data.filter(v => v.type == 0));
|
const dynamicRoutes = parseDynamicRoutes(data.filter(v => v.type == 0));
|
||||||
dynamicRoutes.forEach((route) => {
|
dynamicRoutes.forEach((route) => {
|
||||||
@@ -93,8 +95,60 @@ export const usePermissionStore = defineStore("permission", () => {
|
|||||||
});
|
});
|
||||||
isRoutesLoaded.value = false;
|
isRoutesLoaded.value = false;
|
||||||
};
|
};
|
||||||
|
function getMenuMap() {
|
||||||
|
// 初始化Map
|
||||||
|
const map = new Map();
|
||||||
|
|
||||||
|
// 定义递归函数处理菜单节点
|
||||||
|
function processMenuNode(menuNode) {
|
||||||
|
// 将当前节点存入Map
|
||||||
|
map.set(menuNode.menuId, menuNode);
|
||||||
|
|
||||||
|
// 如果有子节点且子节点数组不为空,则递归处理每个子节点
|
||||||
|
if (menuNode.children && Array.isArray(menuNode.children) && menuNode.children.length > 0) {
|
||||||
|
menuNode.children.forEach((childNode) => {
|
||||||
|
processMenuNode(childNode);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 遍历根级菜单,逐个处理
|
||||||
|
if (menus.value && Array.isArray(menus.value)) {
|
||||||
|
menus.value.forEach((rootMenu) => {
|
||||||
|
processMenuNode(rootMenu);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
function returnMenuName(menuId: number | string) {
|
||||||
|
const menu = menusIdMap.value.get(`${menuId}`);
|
||||||
|
return menu ? menu.title : '';
|
||||||
|
}
|
||||||
|
const menusIdMap = computed(() => {
|
||||||
|
const map = getMenuMap();
|
||||||
|
return map;
|
||||||
|
});
|
||||||
|
|
||||||
|
function menuJump(menuId: number | string) {
|
||||||
|
const menu = menusIdMap.value.get(`${menuId}`);
|
||||||
|
console.log('menu', menu);
|
||||||
|
if (menu) {
|
||||||
|
if (menu.name) {
|
||||||
|
router.push({ name: menu.name as string })
|
||||||
|
|
||||||
|
} else {
|
||||||
|
router.push({ path: menu.path as string })
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
menuJump,
|
||||||
|
returnMenuName,
|
||||||
|
menus,
|
||||||
routes,
|
routes,
|
||||||
mixedLayoutLeftRoutes,
|
mixedLayoutLeftRoutes,
|
||||||
isRoutesLoaded,
|
isRoutesLoaded,
|
||||||
|
|||||||
37
src/store/modules/quick.ts
Normal file
37
src/store/modules/quick.ts
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
|
||||||
|
import { store } from "@/store";
|
||||||
|
import quickApi, { type QuickMenu } from "@/api/account/quick";
|
||||||
|
import { usePermissionStoreHook } from "@/store/modules/permission";
|
||||||
|
|
||||||
|
|
||||||
|
export const useQuickStore = defineStore("quick", () => {
|
||||||
|
const quickMenus = ref<QuickMenu[]>([]);
|
||||||
|
|
||||||
|
async function getQuickMenus() {
|
||||||
|
const res = await quickApi.getList({ isEdit: 0 });
|
||||||
|
const obj: any = {}
|
||||||
|
let arr = []
|
||||||
|
for (let menu of res) {
|
||||||
|
if (obj.hasOwnProperty(menu.menuId) || menu.status != 1 || !usePermissionStoreHook().returnMenuName(menu.menuId)) {
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
obj[menu.menuId] = true;
|
||||||
|
arr.push(menu)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
quickMenus.value = arr;
|
||||||
|
}
|
||||||
|
getQuickMenus()
|
||||||
|
return {
|
||||||
|
quickMenus, getQuickMenus
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用于在组件外部(如在Pinia Store 中)使用 Pinia 提供的 store 实例。
|
||||||
|
* 官方文档解释了如何在组件外部使用 Pinia Store:
|
||||||
|
* https://pinia.vuejs.org/core-concepts/outside-component-usage.html#using-a-store-outside-of-a-component
|
||||||
|
*/
|
||||||
|
export function useQuickStoreHook() {
|
||||||
|
return useQuickStore(store);
|
||||||
|
}
|
||||||
5
src/views/shop/commonlyUsedMenu/index.vue
Normal file
5
src/views/shop/commonlyUsedMenu/index.vue
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<FastMenuConfig></FastMenuConfig>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
Reference in New Issue
Block a user