更新oa代码

This commit is contained in:
2025-11-06 15:56:29 +08:00
parent 9c67793fc3
commit 6a9b5d413a
60 changed files with 6194 additions and 2757 deletions
+23 -36
View File
@@ -33,16 +33,15 @@
<script setup>
import { ref, computed, onMounted, onUnmounted } from 'vue';
import { useRouter, useRoute } from 'vue-router';
import { useAllDataStore } from '@/stores';
import { getAllMenus, getTenantMenus } from '@/api/menu';
import { useAllDataStore, useMenuStore } from '@/stores';
import MenuTreeItem from './MenuTreeItem.vue';
const emit = defineEmits(['menu-click']);
const router = useRouter();
const route = useRoute();
const list = ref([]);
const loading = ref(true);
const menuStore = useMenuStore();
const loading = computed(() => menuStore.loading);
const store = useAllDataStore();
const isCollapse = computed(() => store.state.isCollapse);
@@ -192,43 +191,31 @@ const transformMenuData = (menus) => {
return rootMenus;
};
// 获取菜单数据
// 获取菜单数据(从 store
const fetchMenus = async () => {
loading.value = true;
try {
// 获取用户信息,判断登录类型
const userInfo = JSON.parse(localStorage.getItem('userInfo') || '{}');
const loginType = userInfo.type; // "user" 或 "employee"
const roleId = userInfo.role; // 角色ID
let res;
if (loginType === "employee" && roleId) {
// 员工登录,使用getTenantMenus接口
res = await getTenantMenus(roleId);
} else {
// 用户登录,使用getAllMenus接口
res = await getAllMenus();
}
if (res && res.success && res.data) {
const menuData = res.data;
// 转换并排序菜单数据
const transformedMenus = transformMenuData(menuData);
list.value = transformedMenus;
} else {
console.error('获取菜单失败:', res?.message || '未知错误');
list.value = [];
loading.value = false;
return;
}
await menuStore.fetchMenus();
// 菜单数据会自动通过 computed 更新
} catch (error) {
console.error('获取菜单异常:', error);
list.value = [];
} finally {
loading.value = false;
}
};
// 监听 store 中的菜单数据变化,自动转换格式
const list = computed(() => {
const menuData = menuStore.menus;
if (!menuData || menuData.length === 0) {
return [];
}
// 转换并排序菜单数据
return transformMenuData(menuData);
});
// 监听菜单缓存刷新事件的处理函数(需要在外部定义以便在 onUnmounted 中使用)
const handleMenuRefresh = () => {
fetchMenus();
};
// 组件挂载时初始化主题监听和获取菜单
onMounted(() => {
// 初始化主题监听
@@ -250,7 +237,7 @@ onMounted(() => {
}, 100);
// 监听菜单缓存刷新事件
window.addEventListener('menu-cache-refreshed', fetchMenus);
window.addEventListener('menu-cache-refreshed', handleMenuRefresh);
});
// 组件卸载时清理事件监听
@@ -258,7 +245,7 @@ onUnmounted(() => {
if (themeObserver) {
themeObserver.disconnect();
}
window.removeEventListener('menu-cache-refreshed', fetchMenus);
window.removeEventListener('menu-cache-refreshed', handleMenuRefresh);
});
// 计算属性:统一排序所有菜单项(不再区分有无子菜单)
+22 -91
View File
@@ -59,10 +59,9 @@
<script setup lang="ts">
import { ref, computed, onMounted, onUnmounted } from "vue";
import { useRouter, useRoute } from "vue-router";
import { useAllDataStore } from "@/stores";
import { useAllDataStore, useMenuStore } from "@/stores";
import { useAuthStore } from "@/stores/auth";
import { User, SwitchButton, Sunny, Moon, Refresh } from '@element-plus/icons-vue';
import { getAllMenus, getTenantMenus } from '@/api/menu';
import { ElMessage } from 'element-plus';
const router = useRouter();
@@ -80,104 +79,36 @@ interface Breadcrumb {
path: string;
}
const menuList = ref<Menu[]>([]);
const menuStore = useMenuStore();
const cacheLoading = ref(false);
const MENU_CACHE_KEY = 'menu_cache';
// 从缓存加载菜单
function loadMenuFromCache(): Menu[] | null {
try {
const cached = localStorage.getItem(MENU_CACHE_KEY);
if (cached) {
const menuData = JSON.parse(cached);
// 检查缓存是否过期(可选:设置过期时间,这里暂时不设置)
return menuData;
}
} catch (error) {
console.error('Failed to load menu from cache', error);
}
return null;
}
// 使用 store 中的菜单数据
const menuList = computed(() => menuStore.menus);
// 保存菜单到缓存
function saveMenuToCache(menus: Menu[]) {
try {
localStorage.setItem(MENU_CACHE_KEY, JSON.stringify(menus));
} catch (error) {
console.error('Failed to save menu to cache', error);
}
}
// 从API加载菜单
async function loadMenuFromAPI(updateCache = true) {
try {
// 获取用户信息,判断登录类型
const userInfo = JSON.parse(localStorage.getItem('userInfo') || '{}');
const loginType = userInfo.type; // "user" 或 "employee"
const roleId = userInfo.role; // 角色ID
let res;
if (loginType === "employee" && roleId) {
// 员工登录,使用getTenantMenus接口
res = await getTenantMenus(roleId);
} else {
// 用户登录,使用getAllMenus接口
res = await getAllMenus();
}
const menus = res.data || [];
if (updateCache && menus.length > 0) {
saveMenuToCache(menus);
}
return menus;
} catch (error) {
console.error('Failed to load menu from API', error);
return [];
}
}
// 加载菜单(优先从缓存)
// 加载菜单(从 store
async function loadMenu() {
// 先尝试从缓存加载
const cachedMenus = loadMenuFromCache();
if (cachedMenus && cachedMenus.length > 0) {
menuList.value = cachedMenus;
// 异步更新缓存(后台更新,不阻塞UI)
loadMenuFromAPI(true).then(menus => {
if (menus.length > 0) {
menuList.value = menus;
}
});
} else {
// 缓存不存在,从API加载
menuList.value = await loadMenuFromAPI(true);
}
await menuStore.fetchMenus();
}
// 更新缓存(手动刷新)
async function refreshCache() {
cacheLoading.value = true;
try {
const menus = await loadMenuFromAPI(true);
if (menus.length > 0) {
menuList.value = menus;
// 重新加载动态路由
const { loadAndAddDynamicRoutes, resetDynamicRoutes } = await import('@/router/index');
// 重置路由加载状态,强制重新加载
resetDynamicRoutes();
await loadAndAddDynamicRoutes();
// 等待路由完全加载(给Vue Router一些时间更新路由表)
await new Promise(resolve => setTimeout(resolve, 200));
// 触发菜单刷新事件,通知CommonAside组件刷新菜单
window.dispatchEvent(new CustomEvent('menu-cache-refreshed'));
ElMessage.success('菜单缓存和路由更新成功');
} else {
ElMessage.warning('未获取到菜单数据');
}
await menuStore.refreshMenus();
// 重新加载动态路由
const { loadAndAddDynamicRoutes, resetDynamicRoutes } = await import('@/router/index');
// 重置路由加载状态,强制重新加载
resetDynamicRoutes();
await loadAndAddDynamicRoutes();
// 等待路由完全加载(给Vue Router一些时间更新路由表)
await new Promise(resolve => setTimeout(resolve, 200));
// 触发菜单刷新事件,通知CommonAside组件刷新菜单
window.dispatchEvent(new CustomEvent('menu-cache-refreshed'));
ElMessage.success('菜单缓存和路由更新成功');
} catch (error) {
console.error('Failed to refresh cache', error);
ElMessage.error('更新缓存失败,请检查网络连接');
@@ -260,7 +191,7 @@ const handleCommand = async (command) => {
localStorage.removeItem('active_tab');
sessionStorage.removeItem('tabs_list');
// 清除菜单缓存
localStorage.removeItem(MENU_CACHE_KEY);
menuStore.resetMenus();
// 重置 tabs store 状态
const { useTabsStore } = await import('@/stores');