From 3e515b8e046996daf5213a92ea91a9d0c060a3c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A7=A6=E6=B3=BD=E6=97=BA?= <2413898818@qq.com> Date: Mon, 16 Dec 2024 19:36:37 +0800 Subject: [PATCH] Default Changelist --- frontend/src/store/getters.js | 29 ++++++++- frontend/src/store/index.js | 23 +++++-- frontend/src/store/modules/app.js | 79 +++++++++++++++++++++- frontend/src/store/modules/permission.js | 49 +++++++++++--- frontend/src/store/modules/user.js | 83 +++++++++++++++++------- frontend/src/store/mutation-types.js | 50 +++++++++++++- 6 files changed, 270 insertions(+), 43 deletions(-) diff --git a/frontend/src/store/getters.js b/frontend/src/store/getters.js index 8805d33..0690ea5 100644 --- a/frontend/src/store/getters.js +++ b/frontend/src/store/getters.js @@ -1,15 +1,42 @@ +// 定义一个名为 getters 的对象,在 Vuex 中,getters 用于从 store 的状态(state)中派生数据, +// 类似于计算属性,它可以根据已有的 state 数据进行加工处理后返回新的数据供组件获取使用。 const getters = { + // 定义名为 'device' 的 getter 函数,它接收 state 参数(代表整个应用的状态对象), + // 然后返回 state.app.device 的值,也就是从全局状态中的 'app' 模块下获取 'device' 属性的值, + // 这个值可能用于表示当前应用运行所在的设备类型等相关信息,方便组件获取使用。 device: state => state.app.device, + // 定义名为 'theme' 的 getter 函数,作用是从全局状态中的 'app' 模块下获取 'theme' 属性的值, + // 该值可能对应着应用当前所使用的主题相关设置,组件可以通过这个 getter 来获取主题信息。 theme: state => state.app.theme, + // 定义名为 'color' 的 getter 函数,它会返回 state.app.color 的值,从 'app' 模块下获取与应用颜色相关的设置值, + // 例如可能是用于设置界面主体颜色之类的,组件可以据此来展示相应颜色风格的界面。 color: state => state.app.color, + // 定义名为 'token' 的 getter 函数,通过接收 state 参数,返回 state.user.token 的值, + // 这里是从全局状态中的 'user' 模块下获取用户登录的令牌(token)信息,组件可以利用这个 getter 来判断用户是否登录等情况。 token: state => state.user.token, + // 定义名为 'avatar' 的 getter 函数,用于获取 state.user.avatar 的值,即从 'user' 模块下拿到用户头像相关信息, + // 方便组件在需要展示用户头像的地方使用该值进行头像显示。 avatar: state => state.user.avatar, + // 定义名为 'nickname' 的 getter 函数,它返回 state.user.name 的值,也就是从 'user' 模块下获取用户的姓名(可能作为昵称使用), + // 供组件用于显示用户称呼等相关用途。 nickname: state => state.user.name, + // 定义名为 'welcome' 的 getter 函数,从 state.user.welcome 中获取值,这个值可能是针对用户的欢迎语之类的相关内容, + // 组件可以获取该值来展示相应的欢迎信息给用户。 welcome: state => state.user.welcome, + // 定义名为 'roles' 的 getter 函数,其作用是返回 state.user.roles 的值,从 'user' 模块下拿到用户所拥有的角色列表信息, + // 组件在需要根据用户角色进行权限判断或者展示不同角色对应的功能等场景时可以使用该值。 roles: state => state.user.roles, + // 定义名为 'userInfo' 的 getter 函数,会返回 state.user.info 的值,从 'user' 模块下获取完整的用户信息对象, + // 包含了各种详细的用户相关数据,组件若需要全面了解用户情况时可通过这个 getter 获取。 userInfo: state => state.user.info, + // 定义名为 'addRouters' 的 getter 函数,它从 state.permission.addRouters 中获取值, + // 这里是从全局状态中的 'permission' 模块下获取动态添加的路由信息,组件可以利用这个值来进行路由相关的操作或者展示等。 addRouters: state => state.permission.addRouters, + // 定义名为 'multiTab' 的 getter 函数,返回 state.app.multiTab 的值,从 'app' 模块下获取与多标签功能相关的设置信息, + // 组件可以根据该值来判断是否启用多标签等相关功能操作。 multiTab: state => state.app.multiTab } -export default getters +// 将定义好的 getters 对象导出,使得在其他模块(比如 Vue 组件等)中可以导入并使用这些 getters, +// 方便获取 Vuex 存储中经过加工处理后的各种派生数据。 +export default getters \ No newline at end of file diff --git a/frontend/src/store/index.js b/frontend/src/store/index.js index 4e8529a..e5bed4b 100644 --- a/frontend/src/store/index.js +++ b/frontend/src/store/index.js @@ -1,27 +1,40 @@ +// 从 'vue' 库中导入 Vue 构造函数,它是整个 Vue.js 框架的核心,后续很多功能的实现都依赖于它。 import Vue from 'vue' +// 从 'vuex' 库中导入 Vuex,Vuex 是 Vue.js 应用的状态管理模式和库,用于集中管理应用的各种状态数据、处理状态变更以及相关的异步操作等。 import Vuex from 'vuex' - +// 从 './modules/app' 文件中导入名为 'app' 的模块,这个模块应该是定义了与应用本身相关的一些状态、变更(mutations)、动作(actions)等内容,用于管理应用层面的状态逻辑。 import app from './modules/app' +// 从 './modules/user' 文件中导入名为 'user' 的模块,该模块大概率是围绕用户相关的状态数据(如用户信息、登录状态等)以及对应的状态操作逻辑来进行定义的,方便在整个应用中统一管理用户相关状态。 import user from './modules/user' +// 从 './modules/permission' 文件中导入名为 'permission' 的模块,通常会包含权限相关的状态定义、权限验证与变更等操作的逻辑,用于处理应用中的权限管理相关事宜。 import permission from './modules/permission' +// 从 './getters' 文件中导入名为 'getters' 的对象,在 Vuex 中,getters 用于定义从状态(state)中派生出来的数据获取方法,就像计算属性一样,方便组件获取经过处理后的状态数据。 import getters from './getters' - -Vue.use(Vuex) - +// 创建一个新的 Vuex.Store 实例,这是整个应用的状态管理中心,它接收一个配置对象来定义相关的状态管理细节。 export default new Vuex.Store({ + // modules 属性用于将各个子模块整合到这个根状态管理实例中,这里将之前导入的 'app'、'user'、'permission' 模块添加进来, + // 每个子模块都可以有自己独立的 state、mutations、actions 和 getters,方便对不同功能模块的状态进行分类管理,避免所有状态逻辑都堆积在根模块中。 modules: { app, user, permission }, + // state 属性用于定义整个应用的根状态数据,这里暂时为空,不过也可以根据实际需求在这里定义一些全局通用的基础状态值, + // 但更常见的是将具体的状态分散到各个子模块中,如上述导入的 'app'、'user'、'permission' 模块里去定义各自相关的状态。 state: { }, + // mutations 属性用于定义直接修改状态的同步方法集合,在 Vuex 中,只有通过 mutations 才能修改状态,以此保证状态变更的可追踪性, + // 这里暂时为空,实际应用中会根据具体业务逻辑来定义各种不同的 mutations 方法用于更新相应的状态数据。 mutations: { }, + // actions 属性用于定义可以包含异步操作并且通过提交 mutations 来间接修改状态的方法集合,常用于处理诸如 API 调用等异步业务逻辑, + // 这里也暂时为空,后续会根据具体需求添加相应的 actions 方法来触发对应的 mutations 完成状态变更。 actions: { }, + // 将之前导入的 getters 对象添加到这里,使得在整个应用中组件可以通过 Vuex 实例访问到这些定义好的派生数据获取方法, + // 从而方便地获取经过处理后的各种状态数据。 getters -}) +}) \ No newline at end of file diff --git a/frontend/src/store/modules/app.js b/frontend/src/store/modules/app.js index fff96bf..ab48961 100644 --- a/frontend/src/store/modules/app.js +++ b/frontend/src/store/modules/app.js @@ -1,4 +1,7 @@ +// 从 'vue' 库中导入 Vue 构造函数,它是 Vue.js 框架的核心,后续很多功能会依赖它来实现 import Vue from 'vue' +// 从 '../../store/mutation-types' 文件中解构导入多个常量,这些常量通常用于标识 Vuex 中 mutations 的类型 +// 例如用于区分不同状态变更操作的名称,方便在代码中统一管理和调用相关的状态修改逻辑 import { SIDEBAR_TYPE, DEFAULT_THEME, @@ -14,109 +17,181 @@ import { const app = { state: { + // 表示侧边栏是否显示,初始值为 true,意味着默认侧边栏是显示状态 sidebar: true, + // 用于标识当前应用运行所在的设备类型,初始值为 'desktop',表示默认认为是桌面设备 device: 'desktop', + // 应用的主题相关状态,初始为空字符串,后续可通过相应操作来设置具体的主题值 theme: '', + // 应用的布局模式相关状态,初始为空字符串,可根据业务需求设置不同的布局模式 layout: '', + // 应用内容宽度相关状态,初始为空字符串,用来确定内容区域的宽度设置情况 contentWidth: '', + // 表示头部是否固定,初始值为 false,即默认头部不是固定状态 fixedHeader: false, + // 表示侧边栏是否固定,初始值为 false,意味着默认侧边栏不是固定的 fixSiderbar: false, + // 表示头部是否自动隐藏,初始值为 false,即默认头部不会自动隐藏 autoHideHeader: false, + // 应用的颜色相关设置,初始值为 null,后续会根据操作来设置具体颜色值 color: null, + // 可能与颜色弱化(比如淡色模式等)相关的状态标识,初始值为 false weak: false, + // 用于标识是否启用多标签功能,初始值为 true,默认启用多标签 multiTab: true }, mutations: { + // 用于设置侧边栏的显示类型,接收当前状态对象 state 和要设置的类型值 type SET_SIDEBAR_TYPE: (state, type) => { + // 将 state 中的 sidebar 属性更新为传入的 type 值,改变侧边栏的显示状态 state.sidebar = type + // 使用 Vue.ls.set 方法(可能是自定义的本地存储操作)将 SIDEBAR_TYPE 对应的存储值设为 type + // 这样可以将侧边栏类型的设置持久化或者在其他地方能获取到该设置值 Vue.ls.set(SIDEBAR_TYPE, type) }, + // 用于关闭侧边栏的方法,该方法操作 state 来改变侧边栏状态 CLOSE_SIDEBAR: (state) => { + // 先通过 Vue.ls.set 将 SIDEBAR_TYPE 对应的存储值设为 true,具体含义由业务逻辑决定 Vue.ls.set(SIDEBAR_TYPE, true) + // 然后将 state 中的 sidebar 属性设置为 false,实现关闭侧边栏的效果 state.sidebar = false }, + // 用于切换设备类型的方法,接收要切换到的设备值 device,更新 state 中的 device 属性来反映设备类型变化 TOGGLE_DEVICE: (state, device) => { state.device = device }, + // 用于切换应用主题的方法,接收要设置的主题值 theme TOGGLE_THEME: (state, theme) => { - // setStore('_DEFAULT_THEME', theme) + // 原本可能有个 setStore 方法用于存储主题相关设置(当前被注释掉了) + // 现在使用 Vue.ls.set 方法将 DEFAULT_THEME 对应的存储值设为 theme,实现主题设置的持久化等操作 Vue.ls.set(DEFAULT_THEME, theme) + // 同时更新 state 中的 theme 属性,使应用内部的主题状态改变为传入的 theme 值 state.theme = theme }, + // 用于切换应用布局模式的方法,接收要设置的布局模式值 layout TOGGLE_LAYOUT_MODE: (state, layout) => { + // 通过 Vue.ls.set 将 DEFAULT_LAYOUT_MODE 对应的存储值设为 layout,可能用于后续获取布局模式设置等 Vue.ls.set(DEFAULT_LAYOUT_MODE, layout) + // 更新 state 中的 layout 属性,使应用的布局模式改变为传入的 layout 值 state.layout = layout }, + // 用于切换头部是否固定的方法,接收表示固定与否的布尔值 fixed TOGGLE_FIXED_HEADER: (state, fixed) => { + // 使用 Vue.ls.set 将 DEFAULT_FIXED_HEADER 对应的存储值设为 fixed,持久化头部固定状态设置 Vue.ls.set(DEFAULT_FIXED_HEADER, fixed) + // 更新 state 中的 fixedHeader 属性,改变头部固定的实际状态 state.fixedHeader = fixed }, + // 用于切换侧边栏是否固定的方法,接收表示固定与否的布尔值 fixed TOGGLE_FIXED_SIDERBAR: (state, fixed) => { + // 通过 Vue.ls.set 将 DEFAULT_FIXED_SIDEMENU 对应的存储值设为 fixed,用于存储侧边栏固定状态设置 Vue.ls.set(DEFAULT_FIXED_SIDEMENU, fixed) + // 更新 state 中的 fixSiderbar 属性,改变侧边栏固定的实际状态 state.fixSiderbar = fixed }, + // 用于切换头部是否自动隐藏的方法,接收表示隐藏与否的布尔值 show TOGGLE_FIXED_HEADER_HIDDEN: (state, show) => { + // 使用 Vue.ls.set 将 DEFAULT_FIXED_HEADER_HIDDEN 对应的存储值设为 show,持久化头部隐藏状态设置 Vue.ls.set(DEFAULT_FIXED_HEADER_HIDDEN, show) + // 更新 state 中的 autoHideHeader 属性,改变头部自动隐藏的实际状态 state.autoHideHeader = show }, + // 用于切换应用内容宽度类型的方法,接收要设置的内容宽度类型值 type TOGGLE_CONTENT_WIDTH: (state, type) => { + // 通过 Vue.ls.set 将 DEFAULT_CONTENT_WIDTH_TYPE 对应的存储值设为 type,方便后续获取该设置 Vue.ls.set(DEFAULT_CONTENT_WIDTH_TYPE, type) + // 更新 state 中的 contentWidth 属性,改变应用内容宽度的实际类型 state.contentWidth = type }, + // 用于切换应用颜色的方法,接收要设置的颜色值 color TOGGLE_COLOR: (state, color) => { + // 使用 Vue.ls.set 将 DEFAULT_COLOR 对应的存储值设为 color,持久化颜色设置 Vue.ls.set(DEFAULT_COLOR, color) + // 更新 state 中的 color 属性,改变应用的实际颜色设置 state.color = color }, + // 用于切换颜色弱化相关状态的方法,接收表示弱化与否的布尔值 flag TOGGLE_WEAK: (state, flag) => { + // 通过 Vue.ls.set 将 DEFAULT_COLOR_WEAK 对应的存储值设为 flag,持久化颜色弱化状态设置 Vue.ls.set(DEFAULT_COLOR_WEAK, flag) + // 更新 state 中的 weak 属性,改变颜色弱化的实际状态 state.weak = flag }, + // 用于切换多标签相关状态的方法,接收表示启用与否的布尔值 bool TOGGLE_MULTI_TAB: (state, bool) => { + // 使用 Vue.ls.set 将 DEFAULT_MULTI_TAB 对应的存储值设为 bool,持久化多标签设置 Vue.ls.set(DEFAULT_MULTI_TAB, bool) + // 更新 state 中的 multiTab 属性,改变多标签功能的实际启用状态 state.multiTab = bool } }, actions: { + // 名为 setSidebar 的 action 方法,用于触发 SET_SIDEBAR_TYPE 这个 mutation 来设置侧边栏类型 + // 接收一个 type 参数,会将其传递给对应的 mutation 方法 setSidebar ({ commit }, type) { commit('SET_SIDEBAR_TYPE', type) }, + // 名为 CloseSidebar 的 action 方法,用于触发 CLOSE_SIDEBAR 这个 mutation 来关闭侧边栏 CloseSidebar ({ commit }) { commit('CLOSE_SIDEBAR') }, + // 名为 ToggleDevice 的 action 方法,用于触发 TOGGLE_DEVICE 这个 mutation 来切换设备类型 + // 接收要切换到的设备值 device,并传递给对应的 mutation 方法 ToggleDevice ({ commit }, device) { commit('TOGGLE_DEVICE', device) }, + // 名为 ToggleTheme 的 action 方法,用于触发 TOGGLE_THEME 这个 mutation 来切换应用主题 + // 接收要设置的主题值 theme,并传递给对应的 mutation 方法 ToggleTheme ({ commit }, theme) { commit('TOGGLE_THEME', theme) }, + // 名为 ToggleLayoutMode 的 action 方法,用于触发 TOGGLE_LAYOUT_MODE 这个 mutation 来切换应用布局模式 + // 接收要设置的布局模式值 mode,并传递给对应的 mutation 方法 ToggleLayoutMode ({ commit }, mode) { commit('TOGGLE_LAYOUT_MODE', mode) }, + // 名为 ToggleFixedHeader 的 action 方法,用于切换头部是否固定的状态 + // 接收表示固定与否的布尔值 fixedHeader,先做一些额外逻辑判断(如果不是固定头部,则设置头部隐藏为 false) + // 再触发 TOGGLE_FIXED_HEADER 这个 mutation 来更新头部固定相关状态 ToggleFixedHeader ({ commit }, fixedHeader) { if (!fixedHeader) { commit('TOGGLE_FIXED_HEADER_HIDDEN', false) } commit('TOGGLE_FIXED_HEADER', fixedHeader) }, + // 名为 ToggleFixSiderbar 的 action 方法,用于触发 TOGGLE_FIXED_SIDERBAR 这个 mutation 来切换侧边栏是否固定的状态 + // 接收表示固定与否的布尔值 fixSiderbar,并传递给对应的 mutation 方法 ToggleFixSiderbar ({ commit }, fixSiderbar) { commit('TOGGLE_FIXED_SIDERBAR', fixSiderbar) }, + // 名为 ToggleFixedHeaderHidden 的 action 方法,用于触发 TOGGLE_FIXED_HEADER_HIDDEN 这个 mutation 来切换头部是否自动隐藏的状态 + // 接收表示隐藏与否的布尔值 show,并传递给对应的 mutation 方法 ToggleFixedHeaderHidden ({ commit }, show) { commit('TOGGLE_FIXED_HEADER_HIDDEN', show) }, + // 名为 ToggleContentWidth 的 action 方法,用于触发 TOGGLE_CONTENT_WIDTH 这个 mutation 来切换应用内容宽度类型 + // 接收要设置的内容宽度类型值 type,并传递给对应的 mutation 方法 ToggleContentWidth ({ commit }, type) { commit('TOGGLE_CONTENT_WIDTH', type) }, + // 名为 ToggleColor 的 action 方法,用于触发 TOGGLE_COLOR 这个 mutation 来切换应用颜色相关状态 + // 接收要设置的颜色值 color,并传递给对应的 mutation 方法 ToggleColor ({ commit }, color) { commit('TOGGLE_COLOR', color) }, + // 名为 ToggleWeak 的 action 方法,用于触发 TOGGLE_WEAK 这个 mutation 来切换颜色弱化相关状态 + // 接收表示弱化与否的布尔值 weakFlag,并传递给对应的 mutation 方法 ToggleWeak ({ commit }, weakFlag) { commit('TOGGLE_WEAK', weakFlag) }, + // 名为 ToggleMultiTab 的 action 方法,用于触发 TOGGLE_MULTI_TAB 这个 mutation 来切换多标签相关状态 + // 接收表示启用与否的布尔值 bool,并传递给对应的 mutation 方法 ToggleMultiTab ({ commit }, bool) { commit('TOGGLE_MULTI_TAB', bool) } } } -export default app +// 将定义好的 app 对象导出,使得在其他 JavaScript 文件中可以通过导入该模块来使用 app 中定义的 state、mutations 和 actions 等内容 +// 进而构建 Vuex 相关的应用状态管理逻辑等 +export default app \ No newline at end of file diff --git a/frontend/src/store/modules/permission.js b/frontend/src/store/modules/permission.js index 7037063..eeb0f7d 100644 --- a/frontend/src/store/modules/permission.js +++ b/frontend/src/store/modules/permission.js @@ -1,76 +1,107 @@ +// 从 '../../config/router.config' 文件中解构导入两个路由相关的配置, +// asyncRouterMap 可能是包含需要根据权限等条件动态加载的路由信息, +// constantRouterMap 可能是一些固定的、无需动态判断权限就始终存在的路由信息 import { asyncRouterMap, constantRouterMap } from '../../config/router.config' - /** * 过滤账户是否拥有某一个权限,并将菜单从加载列表移除 + * 该函数用于判断给定的用户权限列表是否包含当前路由所要求的权限,以此决定该路由是否应被加载显示。 * - * @param permission - * @param route - * @returns {boolean} + * @param permission 用户所拥有的权限列表,通常是一个数组,每个元素代表一种权限。 + * @param route 当前要检查权限的路由对象,包含了路由相关的各种元信息等。 + * @returns {boolean} 返回一个布尔值,表示用户是否拥有该路由对应的权限,拥有则返回 true,否则返回 false。 */ function hasPermission (permission, route) { + // 检查路由对象是否有元信息(meta),并且元信息中是否定义了权限(permission)要求 if (route.meta && route.meta.permission) { let flag = false + // 遍历用户的权限列表 for (let i = 0, len = permission.length; i < len; i++) { + // 检查当前路由要求的权限列表中是否包含用户所拥有的当前权限 flag = route.meta.permission.includes(permission[i]) + // 如果包含,说明用户有访问该路由的权限,直接返回 true if (flag) { return true } } + // 遍历完用户权限列表后,如果都不包含当前路由要求的权限,则返回 false,表示无权限访问该路由 return false } + // 如果路由没有定义权限要求,默认返回 true,即允许访问该路由 return true } - /** * 单账户多角色时,使用该方法可过滤角色不存在的菜单 + * 该函数用于判断给定角色是否在当前路由所要求的角色列表中,以此决定该路由是否对该角色可见。 + * (注意这里虽然有 eslint-disable-next-line 注释,可能是为了暂时忽略某些 ESLint 规则检查,但代码规范方面可能需要后续优化) * - * @param roles - * @param route - * @returns {*} + * @param roles 角色相关的对象,可能包含角色的唯一标识等信息,这里使用了 roles.id 来进行判断,推测是角色的标识属性。 + * @param route 当前要检查角色匹配的路由对象,包含了路由相关的各种元信息等。 + * @returns {*} 返回一个布尔值,表示当前角色是否符合该路由对角色的要求,符合则返回 true,否则返回 false(若路由未定义角色要求则默认返回 true)。 */ // eslint-disable-next-line function hasRole(roles, route) { + // 检查路由对象是否有元信息(meta),并且元信息中是否定义了角色(roles)要求 if (route.meta && route.meta.roles) { + // 检查当前路由要求的角色列表中是否包含传入的角色标识(roles.id),返回相应的布尔值结果 return route.meta.roles.includes(roles.id) } else { + // 如果路由没有定义角色要求,默认返回 true,即允许该角色访问该路由 return true } } function filterAsyncRouter (routerMap, roles) { + // 使用数组的 filter 方法遍历传入的路由列表(routerMap),对每个路由进行权限过滤操作 const accessedRouters = routerMap.filter(route => { + // 调用 hasPermission 函数检查当前路由是否有权限被访问,传入用户角色的权限列表和当前路由对象 if (hasPermission(roles.permissionList, route)) { + // 如果当前路由有子路由(children)并且子路由长度大于 0,说明需要对子路由也进行权限过滤 if (route.children && route.children.length) { + // 递归调用 filterAsyncRouter 函数,传入子路由列表和用户角色,对子路由进行权限过滤并更新子路由列表 route.children = filterAsyncRouter(route.children, roles) } + // 如果当前路由有权限访问,返回 true,表示该路由应被包含在最终的可访问路由列表中 return true } + // 如果当前路由没有权限访问,返回 false,表示该路由应从可访问路由列表中移除 return false }) + // 返回经过权限过滤后的可访问路由列表 return accessedRouters } const permission = { state: { + // 初始状态下,routers 属性被设置为 constantRouterMap,即那些固定的、无需动态判断权限就始终存在的路由信息 routers: constantRouterMap, + // 初始时 addRouters 为空数组,后续会用于添加根据权限动态筛选出来的路由信息 addRouters: [] }, mutations: { SET_ROUTERS: (state, routers) => { + // 将传入的根据权限筛选后的路由列表(routers)赋值给 state.addRouters,更新动态添加的路由信息 state.addRouters = routers + // 将固定路由列表(constantRouterMap)和动态筛选后的路由列表合并后赋值给 state.routers,更新总的路由信息 state.routers = constantRouterMap.concat(routers) } }, actions: { GenerateRoutes ({ commit }, data) { + // 返回一个 Promise 对象,用于处理异步操作,比如等待路由筛选等操作完成 return new Promise(resolve => { + // 从传入的数据对象中解构出 roles 属性,它包含了用户角色相关信息,用于后续路由筛选依据 const { roles } = data + // 调用 filterAsyncRouter 函数,传入 asyncRouterMap(动态路由列表)和 roles(用户角色信息),进行路由权限筛选 const accessedRouters = filterAsyncRouter(asyncRouterMap, roles) + // 调用 SET_ROUTERS 这个 mutation,将筛选后的路由列表传递进去,用于更新路由相关状态 commit('SET_ROUTERS', accessedRouters) + // 调用 resolve 函数,将 Promise 的状态置为已完成,表示路由生成操作结束 resolve() }) } } } -export default permission +// 将定义好的 permission 对象导出,方便在其他模块中引入使用,以实现基于权限的路由管理相关逻辑, +// 例如在 Vuex 中结合使用来控制前端应用中不同用户角色能访问的路由情况等。 +export default permission \ No newline at end of file diff --git a/frontend/src/store/modules/user.js b/frontend/src/store/modules/user.js index 783e95f..7ce1718 100644 --- a/frontend/src/store/modules/user.js +++ b/frontend/src/store/modules/user.js @@ -1,117 +1,150 @@ +// 从 'vue' 库中导入 Vue 构造函数,后续可能会基于 Vue 相关的功能或插件来进行操作,比如使用 Vue.ls 进行本地存储相关操作 import Vue from 'vue' +// 从 '../../api/login' 文件中解构导入登录、获取用户信息、登出相关的 API 函数,这些函数应该是与后端进行交互来实现对应功能的接口调用 import { login, getInfo, logout } from '../../api/login' +// 从 '../../store/mutation-types' 文件中导入 ACCESS_TOKEN 常量,这个常量可能是用于在 Vuex 的存储操作中标识与用户登录令牌(token)相关的键名等用途 import { ACCESS_TOKEN } from '../../store/mutation-types' +// 从 '../../utils/util' 文件中导入 welcome 函数,该函数可能用于生成欢迎语之类的相关功能 import { welcome } from '../../utils/util' - const user = { state: { + // 用于存储用户登录的令牌(token),初始为空字符串,登录成功后会更新为实际获取到的 token 值 token: '', + // 存储用户的姓名,初始为空字符串,通过获取用户信息后进行设置 name: '', + // 可能用于存储欢迎语相关内容,初始为空字符串,同样在获取用户信息等操作后更新 welcome: '', + // 存储用户头像的相关信息(比如头像的 URL 等),初始为空,后续获取用户信息时设置 avatar: '', + // 用于存储用户所拥有的角色列表,初始为空数组,会根据获取到的用户角色信息进行填充 roles: [], + // 用于存储更详细的用户信息对象,初始为空对象,在获取用户信息接口调用后进行赋值更新 info: {} }, - mutations: { + // 用于设置用户登录令牌(token)的 mutation 方法,接收当前状态对象 state 和要设置的 token 值 SET_TOKEN: (state, token) => { + // 将 state 中的 token 属性更新为传入的 token 值,实现对用户令牌的状态更新 state.token = token }, + // 用于设置用户姓名和欢迎语的 mutation 方法,接收包含姓名(name)和欢迎语(welcome)的对象 SET_NAME: (state, { name, welcome }) => { + // 更新 state 中的 name 属性为传入的姓名值 state.name = name + // 更新 state 中的 welcome 属性为传入的欢迎语值 state.welcome = welcome }, + // 用于设置用户头像相关信息的 mutation 方法,接收要设置的头像信息(avatar),更新 state 中的 avatar 属性 SET_AVATAR: (state, avatar) => { state.avatar = avatar }, + // 用于设置用户角色列表的 mutation 方法,接收要设置的角色列表(roles),更新 state 中的 roles 属性 SET_ROLES: (state, roles) => { state.roles = roles }, + // 用于设置详细用户信息对象的 mutation 方法,接收要设置的用户信息对象(info),更新 state 中的 info 属性 SET_INFO: (state, info) => { state.info = info } }, - actions: { - // 登录 + // 名为 Login 的 action 方法,用于处理用户登录逻辑,接收 commit 函数(用于提交 mutation)和用户登录信息(userInfo) Login ({ commit }, userInfo) { return new Promise((resolve, reject) => { + // 调用从外部导入的 login 函数(应该是与后端交互的登录接口调用),传入用户登录信息 userInfo login(userInfo).then(response => { + // 检查登录接口返回的响应中 code 是否为 0,表示登录是否成功(根据业务定义的响应规范) if (response.code === 0) { const token = response.data - // 把接口返回的token字段的值设置到localStorage的token键值对中,token的有效期是1天,Vue.ls中的ls是localStorage的意思 + // 使用 Vue.ls.set 方法(推测是基于 Vue 的本地存储封装,ls 表示 localStorage)将获取到的 token 值存储到本地存储中 + // 并设置有效期为 1 天(通过传入时间毫秒数 24 * 60 * 60 * 1000 来实现),键名为 ACCESS_TOKEN(之前导入的常量) Vue.ls.set(ACCESS_TOKEN, token, 24 * 60 * 60 * 1000) - // 设置token事件,修改全局变量state中的token值,讲mutations中的SET_TOKEN事件 + // 调用 commit 函数提交 SET_TOKEN 这个 mutation,将获取到的 token 值更新到 state 中的 token 属性,实现状态更新 commit('SET_TOKEN', token) + // 将 Promise 状态置为成功,意味着登录流程顺利完成 resolve() } else { - // 自定义错误 + // 如果登录失败(code 不为 0),创建一个自定义的错误对象,提示用户名或密码错误,并将 Promise 状态置为失败,向外抛出错误 reject(new Error('用户名或密码错误')) } }).catch(error => { + // 如果在登录接口调用过程中出现其他错误(比如网络问题等),在控制台打印错误信息,并将 Promise 状态置为失败,向外抛出错误 console.log(error) reject(error) }) }) }, - - // 获取用户信息 + // 名为 GetInfo 的 action 方法,用于获取用户信息,接收 commit 函数用于提交 mutation GetInfo ({ commit }) { return new Promise((resolve, reject) => { + // 调用从外部导入的 getInfo 函数(与后端交互的获取用户信息接口调用) getInfo().then(response => { - console.log('/user/info的响应如下:') + console.log('/user/info 的响应如下:') console.log(response) - const result = response.data // 取出响应体 + const result = response.data // 取出响应体中的数据部分(通常包含用户详细信息等内容) - if (result.role && result.role.permissions.length > 0) { // 如果权限 + // 检查返回的用户信息中 role 是否存在且 permissions 数组长度大于 0,即判断是否有有效的权限相关信息 + if (result.role && result.role.permissions.length > 0) { const role = result.role - role.permissions = result.role.permissions // permissions是给页面行为设置权限 + role.permissions = result.role.permissions // 将权限相关信息重新赋值给 role.permissions(可能是确保数据结构正确之类的操作) + // 对每个权限对象(per)进行遍历操作,主要是处理 actionEntitySet 相关内容(可能是解析出具体的操作行为等) role.permissions.map(per => { - if (per.actionEntitySet != null && per.actionEntitySet.length > 0) { + if (per.actionEntitySet!= null && per.actionEntitySet.length > 0) { const action = per.actionEntitySet.map(action => { return action.action }) per.actionList = action } }) - role.permissionList = role.permissions.map(permission => { // permissionList是从permissions中遍历解析得来的 + // 从 permissions 数组中遍历解析出每个权限对象的 permissionId,组成新的 permissionList 数组,用于后续权限相关判断等操作 + role.permissionList = role.permissions.map(permission => { return permission.permissionId }) - // 这些设置都在Vuex的getters里面了 - commit('SET_ROLES', result.role) // 在store中设置用户的权限 - commit('SET_INFO', result) // 在store中设置用户信息 + // 提交 SET_ROLES 这个 mutation,将处理后的角色相关信息(result.role)更新到 state 中的 roles 属性,在 store 中设置用户的权限 + commit('SET_ROLES', result.role) + // 提交 SET_INFO 这个 mutation,将完整的用户信息(result)更新到 state 中的 info 属性,在 store 中设置用户信息 + commit('SET_INFO', result) } else { - reject(new Error('getInfo: roles must be a non-null array !')) + // 如果没有有效的权限相关信息,创建一个自定义的错误对象,提示角色信息必须是非空数组,并将 Promise 状态置为失败,向外抛出错误 + reject(new Error('getInfo: roles must be a non-null array!')) } - // 这些设置都在Vuex的getters里面了 - commit('SET_NAME', { name: result.name, welcome: welcome() }) // 设置用户名称 - commit('SET_AVATAR', result.avatar) // 设置用户头像 + // 提交 SET_NAME 这个 mutation,设置用户名称(从 result 中获取 name)和欢迎语(调用 welcome 函数生成) + commit('SET_NAME', { name: result.name, welcome: welcome() }) + // 提交 SET_AVATAR 这个 mutation,设置用户头像(从 result 中获取 avatar) + commit('SET_AVATAR', result.avatar) + // 将 Promise 状态置为成功,意味着获取用户信息流程顺利完成,并返回完整的响应对象 resolve(response) }).catch(error => { + // 如果在获取用户信息接口调用过程中出现错误,将 Promise 状态置为失败,向外抛出错误 reject(error) }) }) }, - - // 登出 + // 名为 Logout 的 action 方法,用于处理用户登出逻辑,接收 commit 函数用于提交 mutation 和当前的 state 对象(包含用户相关状态) Logout ({ commit, state }) { return new Promise((resolve) => { + // 提交 SET_TOKEN 这个 mutation,将用户令牌(token)清空,即将 state 中的 token 属性设置为空字符串 commit('SET_TOKEN', '') + // 提交 SET_ROLES 这个 mutation,将用户角色列表清空,即将 state 中的 roles 属性设置为空数组 commit('SET_ROLES', []) + // 使用 Vue.ls.remove 方法(基于 Vue 的本地存储封装)移除本地存储中以 ACCESS_TOKEN 为键名存储的用户令牌信息 Vue.ls.remove(ACCESS_TOKEN) + // 调用从外部导入的 logout 函数(与后端交互的登出接口调用),传入当前用户的令牌(state.token) logout(state.token).then(() => { + // 无论登出接口调用是否成功(此处简单处理,实际可能需要更严谨的错误处理),都将 Promise 状态置为成功,意味着登出流程完成 resolve() }).catch(() => { + // 如果登出接口调用出现错误,同样将 Promise 状态置为成功,保证登出流程能继续推进(可能需要根据实际情况优化错误处理逻辑) resolve() }) }) } - } } +// 将定义好的 user 对象导出,方便在其他模块(比如 Vuex 相关模块)中引入使用,以实现用户登录、获取信息、登出等相关的状态管理和业务逻辑操作。 export default user diff --git a/frontend/src/store/mutation-types.js b/frontend/src/store/mutation-types.js index 2cf2dbb..6e30cc0 100644 --- a/frontend/src/store/mutation-types.js +++ b/frontend/src/store/mutation-types.js @@ -1,16 +1,64 @@ +// 以下是一系列使用 `export` 关键字导出的常量声明,在 JavaScript 模块系统中, +// 导出的常量可以被其他模块导入使用,这样便于在整个项目中统一管理和复用这些特定的标识字符串。 + +// 定义一个名为 ACCESS_TOKEN 的常量,其值为 'Access-Token',通常用于表示用户访问令牌相关的键名或标识, +// 例如在本地存储(localStorage)或者与后端交互传递用户登录认证信息时,作为区分访问令牌的特定字符串使用。 export const ACCESS_TOKEN = 'Access-Token' + +// 定义常量 SIDEBAR_TYPE,值为 'SIDEBAR_TYPE',可能用于标识侧边栏类型相关的设置或状态, +// 在应用中,当需要区分不同样式、显示模式的侧边栏时,可以通过这个常量作为统一的类型标识, +// 比如在 Vuex 的状态管理中作为键名来存储和获取侧边栏类型相关的设置信息。 export const SIDEBAR_TYPE = 'SIDEBAR_TYPE' + +// 定义常量 DEFAULT_THEME,值为 'DEFAULT_THEME',该常量大概率是用于表示应用默认主题相关的标识, +// 当进行主题切换、设置默认主题或者存储主题相关配置时,以此常量作为统一的名称来指代默认主题, +// 便于在代码中准确地找到与之对应的主题相关的设置逻辑或数据存储位置。 export const DEFAULT_THEME = 'DEFAULT_THEME' + +// 定义常量 DEFAULT_LAYOUT_MODE,值为 'DEFAULT_LAYOUT_MODE',一般用于标识应用默认布局模式的相关设置, +// 例如区分是流式布局、固定宽度布局等不同布局模式,在应用启动或者重置布局时,可依据这个常量来确定默认采用的布局方式, +// 并且在状态管理、配置存储等环节作为特定的键名来使用。 export const DEFAULT_LAYOUT_MODE = 'DEFAULT_LAYOUT_MODE' + +// 定义常量 DEFAULT_COLOR,值为 'DEFAULT_COLOR',通常代表应用默认颜色相关的标识, +// 像是设置界面主体颜色、按钮颜色等默认颜色配置时,使用这个常量来作为对应的标识,方便在整个项目中统一处理颜色相关的设置和获取操作。 export const DEFAULT_COLOR = 'DEFAULT_COLOR' + +// 定义常量 DEFAULT_COLOR_WEAK,值为 'DEFAULT_COLOR_WEAK',很可能与颜色弱化相关的设置有关, +// 比如实现淡色模式或者降低颜色对比度等功能时,以此常量作为区分和操作颜色弱化相关状态的标识, +// 在状态管理以及样式切换等代码逻辑中起到关键的标识作用。 export const DEFAULT_COLOR_WEAK = 'DEFAULT_COLOR_WEAK' + +// 定义常量 DEFAULT_FIXED_HEADER,值为 'DEFAULT_FIXED_HEADER',用于标识头部是否固定的默认设置相关情况, +// 在布局调整、页面交互涉及头部显示状态变化时,通过这个常量来指代头部固定相关的默认设置或者当前状态, +// 方便进行相应的逻辑判断和状态更新操作,例如在 Vuex 中作为键名来存储和修改头部固定状态信息。 export const DEFAULT_FIXED_HEADER = 'DEFAULT_FIXED_HEADER' + +// 定义常量 DEFAULT_FIXED_SIDEMENU,值为 'DEFAULT_FIXED_SIDEMENU',类似地,它用于标识侧边栏是否固定的默认设置相关事项, +// 当处理侧边栏的固定、浮动等显示状态变化以及相关配置存储时,以这个常量作为统一的标识来进行操作和判断, +// 确保整个项目中对侧边栏固定状态的处理具有一致性。 export const DEFAULT_FIXED_SIDEMENU = 'DEFAULT_FIXED_SIDEMENU' + +// 定义常量 DEFAULT_FIXED_HEADER_HIDDEN,值为 'DEFAULT_FIXED_HEADER_HIDDEN',主要用于表示头部是否自动隐藏的默认设置情况, +// 在页面交互过程中,涉及头部隐藏、显示逻辑以及相关状态管理时,通过这个常量来区分和操作头部隐藏相关的默认设置及状态信息, +// 比如根据不同页面滚动位置或者用户操作来决定头部是否隐藏时,以此作为判断依据和状态标识。 export const DEFAULT_FIXED_HEADER_HIDDEN = 'DEFAULT_FIXED_HEADER_HIDDEN' + +// 定义常量 DEFAULT_CONTENT_WIDTH_TYPE,值为 'DEFAULT_CONTENT_WIDTH_TYPE',通常是用于标识应用内容宽度类型的默认设置相关标识, +// 例如区分内容区域是采用流体宽度(随页面大小自适应变化)还是固定宽度等不同宽度类型设置,在页面布局以及响应式设计中, +// 依据这个常量来确定默认的内容宽度类型,并在状态管理、配置存储等环节使用它作为相应的键名来操作相关信息。 export const DEFAULT_CONTENT_WIDTH_TYPE = 'DEFAULT_CONTENT_WIDTH_TYPE' + +// 定义常量 DEFAULT_MULTI_TAB,值为 'DEFAULT_MULTI_TAB',大概率是用于表示多标签功能相关的默认设置标识, +// 比如在应用中判断是否默认启用多标签页面展示、切换多标签相关状态以及存储多标签配置信息时,通过这个常量来进行统一的指代和操作, +// 保证多标签功能相关的代码逻辑能够清晰且一致地进行处理。 export const DEFAULT_MULTI_TAB = 'DEFAULT_MULTI_TAB' +// 定义一个名为 CONTENT_WIDTH_TYPE 的常量对象,用于明确内容宽度类型的具体取值情况, +// 这里定义了两个属性:'Fluid' 和 'Fixed',分别代表流体宽度(自适应)和固定宽度这两种不同的内容宽度类型, +// 在应用中,当需要根据具体类型来设置或者判断内容宽度时,可以通过这个对象来获取对应的类型字符串, +// 使得代码中对内容宽度类型的使用更加清晰和规范,避免直接使用字符串字面量可能带来的错误和不易理解的问题。 export const CONTENT_WIDTH_TYPE = { Fluid: 'Fluid', Fixed: 'Fixed' -} +} \ No newline at end of file