This commit is contained in:
张成
2025-10-08 18:53:38 +08:00
parent 43eb9715fa
commit 845658f193
39 changed files with 4820 additions and 93 deletions

View File

@@ -40,7 +40,7 @@ export default {
}
},
methods: {
...mapActions(['handleLogOut']),
...mapActions('user', ['handleLogOut']),
logout() {
this.handleLogOut(this)
},

View File

@@ -72,11 +72,10 @@ export default {
},
computed: {
...mapGetters({
sysFormModel: 'sysFormModel',
menuList: 'menuList',
tagRouter: 'tagRouter',
userName: 'userName',
userAvator: 'avatorImgPath'
sysFormModel: 'app/sysFormModel',
menuList: 'user/menuList',
userName: 'user/userName',
userAvator: 'user/avatorImgPath'
}),
cacheList() {
return ['ParentView']

167
src/config/menuConfig.js Normal file
View File

@@ -0,0 +1,167 @@
/**
* 默认菜单配置
* 当 authorityMenus 接口失败时使用
*/
export const defaultMenus = [
{
id: 1,
name: '首页',
path: '/home',
component: 'home/index',
parent_id: 0,
type: '页面',
is_show_menu: 1,
icon: 'md-home',
sort: 1
},
{
id: 5,
name: '系统管理',
path: '/system',
component: '',
parent_id: 0,
type: '菜单',
is_show_menu: 1,
icon: 'md-settings',
sort: 2,
children: [
{
id: 11,
name: '用户管理',
path: '/system/user',
component: 'system/sys_user',
parent_id: 5,
type: '页面',
is_show_menu: 1,
icon: 'md-person',
sort: 1
},
{
id: 12,
name: '角色管理',
path: '/system/role',
component: 'system/sys_role',
parent_id: 5,
type: '页面',
is_show_menu: 1,
icon: 'md-people',
sort: 2
},
{
id: 13,
name: '系统日志',
path: '/system/log',
component: 'system/sys_log',
parent_id: 5,
type: '页面',
is_show_menu: 1,
icon: 'md-list',
sort: 3
},
{
id: 15,
name: '参数设置',
path: '/system/param',
component: 'system/sys_param_setup',
parent_id: 5,
type: '页面',
is_show_menu: 1,
icon: 'md-options',
sort: 4
}
]
},
{
id: 120,
name: '高级管理',
path: '/system_high',
component: '',
parent_id: 0,
type: '菜单',
is_show_menu: 1,
icon: 'md-construct',
sort: 3,
children: [
{
id: 122,
name: '菜单管理',
path: '/system_high/menu',
component: 'system_high/sys_menu',
parent_id: 120,
type: '页面',
is_show_menu: 1,
icon: 'md-menu',
sort: 1
},
{
id: 123,
name: '控制管理',
path: '/system_high/control',
component: 'system_high/sys_control',
parent_id: 120,
type: '页面',
is_show_menu: 1,
icon: 'md-cube',
sort: 2
},
{
id: 124,
name: '系统标题',
path: '/system_high/title',
component: 'system_high/sys_title',
parent_id: 120,
type: '页面',
is_show_menu: 1,
icon: 'md-text',
sort: 3
}
]
}
]
/**
* 根据菜单 ID 数组过滤菜单
* @param {Array} menuIds - 菜单 ID 数组
* @param {Array} allMenus - 所有菜单配置
* @returns {Array} 过滤后的菜单
*/
export function filterMenusByIds(menuIds, allMenus = defaultMenus) {
if (!menuIds || menuIds.length === 0) {
return allMenus
}
const idSet = new Set(menuIds)
function filterMenu(menu) {
if (!idSet.has(menu.id)) {
return null
}
const filteredMenu = { ...menu }
if (menu.children && menu.children.length > 0) {
const filteredChildren = menu.children
.map(child => filterMenu(child))
.filter(child => child !== null)
if (filteredChildren.length > 0) {
filteredMenu.children = filteredChildren
} else {
delete filteredMenu.children
}
}
return filteredMenu
}
return allMenus
.map(menu => filterMenu(menu))
.filter(menu => menu !== null)
}
export default {
defaultMenus,
filterMenusByIds
}

View File

@@ -25,8 +25,6 @@ import * as tools from './utils/tools'
// ==================== Store 模块 ====================
import storeModules, { userModule, appModule } from './store'
import { setUserServer } from './store/user'
import { setParamSetupServer } from './store/app'
// ==================== 路由配置 ====================
import routerConfig, { createBaseRoutes, setupRouterGuards } from './router'
@@ -62,10 +60,6 @@ import * as systemApi from './api/system'
// system_high API
import * as systemHighApi from './api/system_high'
// 自动设置 API
setUserServer(systemApi.userServer)
setParamSetupServer(systemHighApi.paramSetupServer)
// ==================== 框架类 ====================
class AdminFramework {
constructor() {
@@ -203,22 +197,6 @@ class AdminFramework {
this.store = store
}
/**
* 设置用户服务实例
* @param {Object} userServer - 用户服务实例
*/
setUserServer(userServer) {
setUserServer(userServer)
}
/**
* 设置参数设置服务实例
* @param {Object} paramSetupServer - 参数设置服务实例
*/
setParamSetupServer(paramSetupServer) {
setParamSetupServer(paramSetupServer)
}
/**
* 创建路由实例
* @param {Object} Router - VueRouter 类
@@ -230,14 +208,14 @@ class AdminFramework {
*/
createRouter(Router, components = {}, customRoutes = [], ViewUI, homeName = 'home') {
const { LoginPage, Page401, Page404, Page500 } = components
if (!LoginPage || !Page401 || !Page404 || !Page500) {
console.error('Missing required page components')
return null
}
const baseRoutes = createBaseRoutes(LoginPage, Page401, Page404, Page500)
const router = new Router({
routes: [...baseRoutes, ...customRoutes],
mode: 'hash'
@@ -282,7 +260,7 @@ class AdminFramework {
*/
getRoutes(components = {}) {
const { Main, ParentView, Page404, HomePage } = components
if (!Main || !ParentView || !Page404) {
console.error('Missing required layout components')
return null

View File

@@ -1,11 +1,5 @@
import { getBreadCrumbList, getHomeRoute } from '../utils/tools'
// 注意:这里的 paramSetupServer 需要在使用时注入
let paramSetupServerInstance = null
export const setParamSetupServer = (server) => {
paramSetupServerInstance = server
}
import paramSetupServer from '../api/system_high/paramSetupServer'
export default {
namespaced: true,
@@ -37,23 +31,20 @@ export default {
logoUrl: defaultLogo
}
if (!paramSetupServerInstance) {
commit('setSysTitle', formModel)
return
}
try {
let res1 = await paramSetupServerInstance.getOne('sys_title')
if (res1.data) {
let res1 = await paramSetupServer.getOne('sys_title')
if (res1 && res1.data) {
formModel.title = res1.data.value
document.title = res1.data.value
}
let res2 = await paramSetupServerInstance.getOne('sys_logo')
if (res2.data) {
let res2 = await paramSetupServer.getOne('sys_logo')
if (res2 && res2.data) {
formModel.logoUrl = res2.data.value
}
} catch (error) {
console.error('Failed to get sys title:', error)
console.warn('获取系统标题失败,使用默认标题:', error || '接口调用失败')
// 使用默认标题
document.title = formModel.title
}
commit('setSysTitle', formModel)

View File

@@ -1,12 +1,7 @@
import { setToken, getToken } from '../utils/tools'
import uiTool from '../utils/uiTool'
// 注意:这里的 userServer 需要在使用时注入
let userServerInstance = null
export const setUserServer = (server) => {
userServerInstance = server
}
import { defaultMenus, filterMenusByIds } from '../config/menuConfig'
import userServer from '../api/system/userServer'
export default {
namespaced: true,
@@ -48,43 +43,132 @@ export default {
menuList: state => state.menuList
},
actions: {
async setAuthorityMenus({ state, commit }, { Main, ParentView, Page404 }) {
if (!userServerInstance) {
console.error('userServer not initialized')
return
async setAuthorityMenus({ state, commit }, { Main, ParentView, Page404, authorityMenus, menuIds }) {
// 如果传入了 authorityMenus直接使用否则从接口获取
let menus = authorityMenus
if (!menus) {
try {
let res = await userServer.authorityMenus()
console.log('获取权限菜单返回:', res)
// res 的结构是 { code, message, data }
if (res && res.code === 0 && res.data) {
menus = res.data
}
} catch (error) {
console.error('获取权限菜单失败:', error)
console.warn('将使用默认菜单配置')
// 如果接口失败,使用默认菜单配置
// 如果有 menuIds根据 ID 过滤菜单;否则使用所有默认菜单
if (menuIds && menuIds.length > 0) {
menus = filterMenusByIds(menuIds, defaultMenus)
console.log('根据菜单 IDs 过滤后的菜单:', menus)
} else {
menus = defaultMenus
console.log('使用所有默认菜单')
}
}
}
let res = await userServerInstance.authorityMenus()
let authorityMenus = res.data
commit('setAuthorityMenus', JSON.stringify(authorityMenus))
// 如果 menus 是字符串,先解析
if (typeof menus === 'string') {
try {
menus = JSON.parse(menus)
} catch (e) {
console.error('解析权限菜单失败:', e)
menus = defaultMenus
}
}
// 如果 menus 仍然为空或不是数组,使用默认菜单
if (!menus || !Array.isArray(menus)) {
console.warn('菜单数据无效,使用默认菜单')
menus = defaultMenus
}
console.log('最终处理的权限菜单:', menus)
// 保存权限菜单
commit('setAuthorityMenus', JSON.stringify(menus))
// 生成路由菜单
let mainMenu = uiTool.getRoutes(Main, ParentView, Page404)
commit('setMenuList', mainMenu.children)
console.log('生成的主菜单:', mainMenu)
if (mainMenu && mainMenu.children) {
commit('setMenuList', mainMenu.children)
}
},
async handleLogin({ state, commit, dispatch }, { userFrom, Main, ParentView, Page404 }) {
if (!userServerInstance) {
throw new Error('userServer not initialized')
}
debugger
let promise = new Promise(async (resolve, reject) => {
try {
let res = await userServerInstance.login(userFrom)
try {
let res = await userServer.login(userFrom)
console.log('登录接口返回:', res)
let token = res.data.token
let name = res.data.user.name.trim()
commit('setUserName', name)
commit('setToken', token)
await dispatch('setAuthorityMenus', { Main, ParentView, Page404 })
resolve(res)
} catch (error) {
reject(error)
// 检查返回数据结构
// http.post 返回的是 response.data即 { code, message, data }
if (!res) {
throw new Error('登录接口无返回数据')
}
})
return promise
if (res.code !== 0) {
throw new Error(res.message || '登录失败')
}
if (!res.data) {
throw new Error('登录接口返回数据格式错误')
}
// 实际数据在 res.data 中
let token = res.data.token
let user = res.data.user
let authorityMenusIds = res.data.authorityMenus
if (!token) {
throw new Error('未获取到 token')
}
if (!user || !user.name) {
throw new Error('未获取到用户信息')
}
let name = user.name.trim()
commit('setUserName', name)
commit('setToken', token)
// 登录接口返回的 authorityMenus 是菜单 ID 数组字符串
console.log('登录返回的菜单 IDs:', authorityMenusIds)
// 解析菜单 IDs
let menuIds = []
if (authorityMenusIds) {
try {
if (typeof authorityMenusIds === 'string') {
menuIds = JSON.parse(authorityMenusIds)
} else if (Array.isArray(authorityMenusIds)) {
menuIds = authorityMenusIds
}
} catch (e) {
console.error('解析菜单 IDs 失败:', e)
}
}
// 调用 authorityMenus 接口获取完整菜单数据
// 如果接口失败,会使用默认菜单配置和 menuIds 进行过滤
await dispatch('setAuthorityMenus', {
Main,
ParentView,
Page404,
menuIds
})
return res
} catch (error) {
console.error('登录失败:', error)
throw error
}
},
async handleLogOut({ state, commit }, vue) {
commit('setToken', '')

View File

@@ -28,12 +28,8 @@ class Http {
timeout: this.config.timeout,
headers: {},
baseURL: this.baseUrl(),
responseType: 'json',
transformResponse: [
function(data) {
return data
}
]
responseType: 'json'
// 移除 transformResponse,使用 axios 默认的 JSON 解析
}
let newConfig = Object.assign({}, defaultConfig, config)

View File

@@ -27,6 +27,9 @@
<script>
import config from '@/config'
import LoginForm from '@component/login-form'
import Main from '@component/main'
import ParentView from '@component/parent-view'
import Page404 from '@/views/error-page/404.vue'
import { mapActions } from 'vuex'
export default {
@@ -39,11 +42,35 @@ export default {
LoginForm,
},
methods: {
...mapActions(['handleLogin']),
...mapActions('user', ['handleLogin']),
async handleSubmit({ userName, password }) {
let user = { name: userName, password: password }
await this.handleLogin(user)
window.location.reload()
try {
let userFrom = { name: userName, password: password }
await this.handleLogin({
userFrom,
Main,
ParentView,
Page404
})
this.$Message.success('登录成功!')
window.location.reload()
} catch (error) {
console.error('登录失败:', error)
// 处理不同类型的错误
let errorMsg = '登录失败,请检查用户名和密码'
if (error) {
if (typeof error === 'string') {
errorMsg = error
} else if (error.message) {
errorMsg = error.message
} else if (error.data && error.data.message) {
errorMsg = error.data.message
}
}
this.$Message.error(errorMsg)
}
},
},
}