|
|
@@ -0,0 +1,190 @@
|
|
|
+import { defineStore } from 'pinia';
|
|
|
+import { ref, computed } from 'vue';
|
|
|
+import request from '@/utils/request';
|
|
|
+
|
|
|
+export interface MenuApiConfig {
|
|
|
+ // 接口URL
|
|
|
+ apiUrl?: string;
|
|
|
+ // 请求方法
|
|
|
+ method?: 'GET' | 'POST';
|
|
|
+ // 请求参数
|
|
|
+ params?: Record<string, any>;
|
|
|
+ // 数据提取路径,从接口响应中提取数量的路径
|
|
|
+ dataPath?: string;
|
|
|
+ // 是否为父级菜单(数字由子菜单汇总而来,不调用接口)
|
|
|
+ isParent?: boolean;
|
|
|
+ // 子菜单路径列表(仅当isParent为true时有效)
|
|
|
+ children?: string[];
|
|
|
+}
|
|
|
+
|
|
|
+export const useSideNumStore = defineStore('sideNum', () => {
|
|
|
+ // 存储每个菜单路径对应的气泡数量
|
|
|
+ const menuCounts = ref<Record<string, number>>({});
|
|
|
+ // 存储每个菜单路径对应的接口配置
|
|
|
+ const menuApiConfigs = ref<Record<string, MenuApiConfig>>({});
|
|
|
+
|
|
|
+ // 获取指定菜单路径的气泡数量
|
|
|
+ const getMenuCount = (menuPath: string): number => {
|
|
|
+ const config = menuApiConfigs.value[menuPath];
|
|
|
+ // 如果是父级菜单,计算子菜单数量总和
|
|
|
+ if (config && config.isParent && config.children) {
|
|
|
+ return config.children.reduce((total, childPath) => {
|
|
|
+ return total + (menuCounts.value[childPath] || 0);
|
|
|
+ }, 0);
|
|
|
+ }
|
|
|
+ // 普通菜单直接返回存储的数量
|
|
|
+ return menuCounts.value[menuPath] || 0;
|
|
|
+ };
|
|
|
+
|
|
|
+ // 获取所有有数量的菜单项
|
|
|
+ const getActiveMenus = computed(() => {
|
|
|
+ const activeMenus: Record<string, number> = {};
|
|
|
+ Object.keys(menuApiConfigs.value).forEach((key) => {
|
|
|
+ const count = getMenuCount(key); // 使用getMenuCount方法,支持父级菜单计算
|
|
|
+ if (count > 0) {
|
|
|
+ activeMenus[key] = count;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ return activeMenus;
|
|
|
+ });
|
|
|
+
|
|
|
+ // 获取总的未处理数量
|
|
|
+ const getTotalCount = computed(() => {
|
|
|
+ // 只计算非父级菜单的数量,避免重复计算
|
|
|
+ return Object.keys(menuApiConfigs.value).reduce((total, menuPath) => {
|
|
|
+ const config = menuApiConfigs.value[menuPath];
|
|
|
+ if (!config.isParent) {
|
|
|
+ return total + (menuCounts.value[menuPath] || 0);
|
|
|
+ }
|
|
|
+ return total;
|
|
|
+ }, 0);
|
|
|
+ });
|
|
|
+ // 设置菜单接口配置
|
|
|
+ const setMenuApiConfig = (menuPath: string, config: MenuApiConfig) => {
|
|
|
+ menuApiConfigs.value[menuPath] = {
|
|
|
+ method: 'GET',
|
|
|
+ dataPath: 'data.count', // 默认数据路径
|
|
|
+ isParent: false, // 默认不是父级菜单
|
|
|
+ ...config
|
|
|
+ };
|
|
|
+ };
|
|
|
+
|
|
|
+ // 设置父级菜单配置(数字由子菜单汇总)
|
|
|
+ const setParentMenuConfig = (menuPath: string, children: string[]) => {
|
|
|
+ menuApiConfigs.value[menuPath] = {
|
|
|
+ apiUrl: '', // 父级菜单不需要接口URL
|
|
|
+ isParent: true,
|
|
|
+ children: children
|
|
|
+ };
|
|
|
+ };
|
|
|
+
|
|
|
+ // 批量设置多个菜单的接口配置
|
|
|
+ const setMultipleApiConfigs = (configs: Record<string, MenuApiConfig>) => {
|
|
|
+ Object.keys(configs).forEach((menuPath) => {
|
|
|
+ setMenuApiConfig(menuPath, configs[menuPath]);
|
|
|
+ });
|
|
|
+ };
|
|
|
+
|
|
|
+ // 更新指定菜单的气泡数量
|
|
|
+ const updateMenuCount = (menuPath: string, count: number) => {
|
|
|
+ menuCounts.value[menuPath] = Math.max(0, count); // 确保数量不为负数
|
|
|
+ };
|
|
|
+
|
|
|
+ // 清空指定菜单的气泡数量
|
|
|
+ const clearMenuCount = (menuPath: string) => {
|
|
|
+ menuCounts.value[menuPath] = 0;
|
|
|
+ };
|
|
|
+
|
|
|
+ // 清空所有菜单的气泡数量
|
|
|
+ const clearAllCounts = () => {
|
|
|
+ menuCounts.value = {};
|
|
|
+ };
|
|
|
+
|
|
|
+ // 从接口响应中提取数量
|
|
|
+ const extractCountFromResponse = (response: any): number => {
|
|
|
+ try {
|
|
|
+ if (response.code === 200) {
|
|
|
+ return response.data;
|
|
|
+ }
|
|
|
+ } catch {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ // 获取指定菜单的数量(调用接口)
|
|
|
+ const fetchMenuCount = async (menuPath: string): Promise<number> => {
|
|
|
+ const config = menuApiConfigs.value[menuPath];
|
|
|
+ if (!config) {
|
|
|
+ console.warn(`菜单路径 ${menuPath} 没有配置接口信息`);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ console.log(menuPath, '========');
|
|
|
+ // 如果是父级菜单,不调用接口,直接返回子菜单数量总和
|
|
|
+ if (config.isParent) {
|
|
|
+ return getMenuCount(menuPath);
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ const response = await makeApiRequest(config);
|
|
|
+ const count = extractCountFromResponse(response);
|
|
|
+ updateMenuCount(menuPath, count);
|
|
|
+ return count;
|
|
|
+ } catch (error) {
|
|
|
+ console.error(`获取菜单 ${menuPath} 数量失败:`, error);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ // 发起API请求
|
|
|
+ const makeApiRequest = async (config: MenuApiConfig): Promise<any> => {
|
|
|
+ const { apiUrl, method = 'GET', params } = config;
|
|
|
+
|
|
|
+ if (method === 'GET') {
|
|
|
+ return await request.get(apiUrl, { params });
|
|
|
+ } else {
|
|
|
+ return await request.post(apiUrl, params);
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ // 刷新指定菜单的数量(立即调用接口)
|
|
|
+ const refreshMenuCount = async (menuPath: string): Promise<number> => {
|
|
|
+ return fetchMenuCount(menuPath);
|
|
|
+ };
|
|
|
+
|
|
|
+ // 刷新所有菜单的数量
|
|
|
+ const refreshAllCounts = async (): Promise<void> => {
|
|
|
+ // 只刷新非父级菜单的数量
|
|
|
+ const nonParentMenus = Object.keys(menuApiConfigs.value).filter((menuPath) => !menuApiConfigs.value[menuPath].isParent);
|
|
|
+ const promises = nonParentMenus.map((menuPath) => fetchMenuCount(menuPath));
|
|
|
+ await Promise.allSettled(promises);
|
|
|
+ };
|
|
|
+
|
|
|
+ // 重置Store状态
|
|
|
+ const resetStore = () => {
|
|
|
+ menuCounts.value = {};
|
|
|
+ menuApiConfigs.value = {};
|
|
|
+ };
|
|
|
+
|
|
|
+ return {
|
|
|
+ // 状态
|
|
|
+ menuCounts,
|
|
|
+ menuApiConfigs,
|
|
|
+ // 计算属性
|
|
|
+ getActiveMenus,
|
|
|
+ getTotalCount,
|
|
|
+ // 方法
|
|
|
+ getMenuCount,
|
|
|
+ setMenuApiConfig,
|
|
|
+ setParentMenuConfig,
|
|
|
+ setMultipleApiConfigs,
|
|
|
+ updateMenuCount,
|
|
|
+ clearMenuCount,
|
|
|
+ clearAllCounts,
|
|
|
+ extractCountFromResponse,
|
|
|
+ fetchMenuCount,
|
|
|
+ makeApiRequest,
|
|
|
+ refreshMenuCount,
|
|
|
+ refreshAllCounts,
|
|
|
+ resetStore
|
|
|
+ };
|
|
|
+});
|