deotalandAi/apps/FrontendDesigner/src/stores/index.js

335 lines
10 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { defineStore } from 'pinia'
import {adminApi,requestUtils} from '@deotaland/utils'
import {permissionRoutes} from '../router/index.js';
import { nextTick } from 'vue';
// 管理员认证状态管理store
export const useAuthStore = defineStore('auth', {
state: () => ({
token: localStorage.getItem('token') || '',
user: JSON.parse(localStorage.getItem('user') || 'null'),
permissionRouter: JSON.parse(localStorage.getItem('permissionRouter') || '[]'),
permissionButton: JSON.parse(localStorage.getItem('permissionButton') || '[]'),
router: null,
routesUpdated: 0,//路由更新次数
routerList: window.location.hostname.indexOf('local') === -1 ? [] : permissionRoutes,//侧边栏路由
}),
getters: {
// 判断是否已登录
isAuthenticated: (state) => !!state.token && !!state.user,
// 获取用户名
username: (state) => state.user?.username || '',
// 获取用户角色
userRole: (state) => state.user?.role || '',
// 判断是否有按钮权限
hasButtonPermission: (state) => (buttonName) => state.permissionButton.includes(buttonName),
},
actions: {
// 登录
login(loginData,callback) {
const { accessToken} = loginData
this.token = accessToken
this.user = loginData
// 持久化存储
localStorage.setItem('token', accessToken)
localStorage.setItem('user', JSON.stringify(this.user))
this.getPermissionCodesByUserId(callback);
},
// 登出
logout() {
this.token = ''
this.user = null
// 清除持久化存储
localStorage.removeItem('token')
localStorage.removeItem('user')
localStorage.removeItem('admin-remember-me')
},
//获取用户权限
async getPermissionCodesByUserId(callback){
let requestUrl = {
method: adminApi.default.getPermissionCodesByUserId.method,
url: adminApi.default.getPermissionCodesByUserId.url.replace('{userId}', this.user.userId),
}
const res = await requestUtils.common(requestUrl);
if(res.code === 0){
const data = res.data;
this.permissionRouter = data.filter(item => item.indexOf('router') !== -1);
this.permissionButton = data.filter(item => item.indexOf('admin') !== -1);
//本地存储权限列表
localStorage.setItem('permissionRouter', JSON.stringify(this.permissionRouter))
localStorage.setItem('permissionButton', JSON.stringify(this.permissionButton))
this.addPermissionRoutes(callback);
}
},
// 动态添加权限路由
addPermissionRoutes(callback) {
if (!this.router) {
console.error('Router 未初始化');
callback && callback();
return;
}
// const accessibleRoutes = permissionRoutes.filter(route => {
// const hasPermission = this.permissionRouter.includes('router:'+route.name);
// return hasPermission;
// });
let accessibleRoutes = [];
const findRouteInTree = (tree, name) => {
for (const route of tree) {
if (route.name === name) {
return route;
}
if (route.children) {
const found = findRouteInTree(route.children, name);
if (found) return found;
}
}
return null;
};
const findRouteInPermissionRoutes = (name) => {
return findRouteInTree(permissionRoutes, name);
};
const deepCopyRoute = (route, includeChildren = false) => {
const copy = { ...route };
delete copy.children;
if (includeChildren && route.children) {
copy.children = route.children.map(child => deepCopyRoute(child, includeChildren));
}
return copy;
};
const builderRouterTree = (routes) => {
if (!routes || routes.length === 0) return;
for (let i = 0; i < routes.length; i++) {
const currentName = routes[i];
const targetRoute = findRouteInPermissionRoutes(currentName);
if (!targetRoute) {
console.warn(`未找到路由: ${currentName}`);
return;
}
if (i === 0) {
const existingRoute = accessibleRoutes.find(r => r.name === currentName);
if (!existingRoute) {
const newRoute = deepCopyRoute(targetRoute, false);
accessibleRoutes.push(newRoute);
}
} else {
const parentName = routes[i - 1];
const parentRoute = findRouteInTree(accessibleRoutes, parentName);
if (!parentRoute) {
console.warn(`父路由不存在: ${parentName}, 当前路由: ${currentName}, accessibleRoutes:`, accessibleRoutes);
return;
}
if (!parentRoute.children) {
parentRoute.children = [];
}
const existingChild = parentRoute.children.find(child => child.name === currentName);
if (!existingChild) {
const newChildRoute = deepCopyRoute(targetRoute, false);
parentRoute.children.push(newChildRoute);
}
}
}
};
// 将权限字符串转成二维数组:去掉前缀后按“:”拆成层级数组
const permissionRouterTree = this.permissionRouter.map(code => {
// 去掉 router: 前缀
const remain = code.replace(/^router:/, '');
// 按冒号拆成层级
return remain.split(':');
});
console.log('permissionRouterTree:', permissionRouterTree);
permissionRouterTree.forEach(item => {
builderRouterTree(item);
});
if (accessibleRoutes.length === 0) {
console.warn('没有可访问的路由,请检查权限列表');
callback && callback();
return;
}
this.routerList = [];
accessibleRoutes.forEach(route => {
this.router.addRoute('Admin', route);
this.routerList.push(route);
});
this.routesUpdated++;
callback && callback();
},
// 检查认证状态
checkAuth() {
const storedToken = localStorage.getItem('token')
const storedUser = localStorage.getItem('user')
if (storedToken && storedUser) {
this.token = storedToken
this.user = JSON.parse(storedUser)
return true
}
return false
},
}
})
// 全局状态管理store
export const useAppStore = defineStore('app', {
state: () => ({
// 应用主题设置
theme: 'light',
// 国际化语言设置
locale: 'zh-CN',
// 加载状态
isLoading: false,
// 侧边栏展开状态(响应式适配用)
sidebarCollapsed: false,
// 移动端菜单显示状态
mobileMenuVisible: false
}),
getters: {
// 获取当前主题
currentTheme: (state) => state.theme,
// 获取当前语言
currentLocale: (state) => state.locale,
// 判断是否是深色主题
isDarkTheme: (state) => state.theme === 'dark',
// 判断是否是浅色主题
isLightTheme: (state) => state.theme === 'light',
// 获取加载状态(兼容性)
loading: (state) => state.isLoading
},
actions: {
// 切换主题
toggleTheme() {
this.theme = this.theme === 'light' ? 'dark' : 'light'
// 保存到localStorage
localStorage.setItem('theme', this.theme)
// 应用到document
document.documentElement.setAttribute('data-theme', this.theme)
},
// 设置主题
setTheme(theme) {
this.theme = theme
localStorage.setItem('theme', theme)
document.documentElement.setAttribute('data-theme', theme)
},
// 切换语言
toggleLocale() {
this.locale = this.locale === 'zh-CN' ? 'en-US' : 'zh-CN'
localStorage.setItem('locale', this.locale)
// 不再触发事件由Vue的响应式系统自动通知
},
// 设置语言
setLocale(locale) {
this.locale = locale
localStorage.setItem('locale', locale)
// 不再触发事件由Vue的响应式系统自动通知
},
// 设置加载状态
setLoading(loading) {
this.isLoading = loading
},
// 切换侧边栏状态
toggleSidebar() {
this.sidebarCollapsed = !this.sidebarCollapsed
},
// 设置侧边栏状态
setSidebarCollapsed(collapsed) {
this.sidebarCollapsed = collapsed
},
// 切换移动端菜单显示状态
toggleMobileMenu() {
this.mobileMenuVisible = !this.mobileMenuVisible
},
// 设置移动端菜单显示状态
setMobileMenuVisible(visible) {
this.mobileMenuVisible = visible
},
// 初始化应用状态
initApp() {
// 从localStorage读取保存的主题和语言设置
const savedTheme = localStorage.getItem('theme') || 'light'
const savedLocale = localStorage.getItem('locale') || 'zh-CN'
this.setTheme(savedTheme)
this.setLocale(savedLocale)
// 初始化移动端状态
const isMobile = window.innerWidth < 768
this.sidebarCollapsed = isMobile
this.mobileMenuVisible = false
}
}
})
// 用户状态管理store可根据需要扩展
export const useUserStore = defineStore('user', {
state: () => ({
userInfo: null,
isLoggedIn: false,
token: null
}),
getters: {
// 获取用户信息
user: (state) => state.userInfo,
// 判断是否已登录
loggedIn: (state) => state.isLoggedIn
},
actions: {
// 设置用户信息
setUser(userInfo) {
this.userInfo = userInfo
this.isLoggedIn = true
},
// 清除用户信息
clearUser() {
this.userInfo = null
this.isLoggedIn = false
this.token = null
localStorage.removeItem('token')
},
// 设置token
setToken(token) {
this.token = token
localStorage.setItem('token', token)
},
// 从localStorage初始化用户状态
initUser() {
const token = localStorage.getItem('token')
if (token) {
this.token = token
// 这里可以添加token验证逻辑
this.isLoggedIn = true
}
}
}
})
// 默认导出,用于兼容 useStore() 调用
export default useAppStore