仓库初始化+岗位相关页面
This commit is contained in:
@@ -0,0 +1,210 @@
|
||||
import { createStore } from 'vuex'
|
||||
import type { Router } from 'vue-router'
|
||||
import { fetchUserRoutes } from '@/api/menu'
|
||||
import type { MenuItemRaw } from '@/api/menu'
|
||||
import { buildDynamicRoutes } from '@/router/dynamicRoutes'
|
||||
import { fetchIndustryTree, fetchJobCategoryTree, fetchRegionTree } from '@/api/common'
|
||||
import type { IndustryItem, JobCategoryItem, RegionItem } from '@/api/common'
|
||||
|
||||
/** 职位列表页缓存数据(从详情页返回时恢复用) */
|
||||
export interface JobListCache {
|
||||
/** 缓存的职位列表 */
|
||||
list: any[]
|
||||
/** 当前已加载到的页码 */
|
||||
pageNum: number
|
||||
/** 总记录数 */
|
||||
total: number
|
||||
/** 列表滚动位置 */
|
||||
scrollTop: number
|
||||
}
|
||||
|
||||
export interface RootState {
|
||||
appName: string
|
||||
showLogin: boolean
|
||||
loginRedirect: string
|
||||
|
||||
/**
|
||||
* 登录状态 — 登录成功设为 true,退出成功设为 false
|
||||
* 因为后端 Cookie 是 HttpOnly 的,前端 JS 无法读取,所以用内存状态管理
|
||||
*/
|
||||
isAuthenticated: boolean
|
||||
|
||||
/**
|
||||
* 后端返回的原始菜单数据,SideNav 用它来渲染导航
|
||||
*/
|
||||
dynamicMenus: MenuItemRaw[]
|
||||
|
||||
/**
|
||||
* 标记动态路由是否已经加载过,避免重复请求
|
||||
* 每次登出时重置为 false
|
||||
*/
|
||||
routesLoaded: boolean
|
||||
|
||||
/**
|
||||
* 记录已注册的动态路由 name,登出时用来逐个 removeRoute
|
||||
*/
|
||||
dynamicRouteNames: string[]
|
||||
|
||||
/**
|
||||
* 行业树分类数据(一级二级嵌套)
|
||||
* 由 /public/industries/tree 接口返回,进首页和 Jobs 页时刷新
|
||||
* 其他页面/组件可直接从 store 读取
|
||||
*/
|
||||
industries: IndustryItem[]
|
||||
|
||||
/**
|
||||
* 岗位树分类数据(一级二级三级嵌套)
|
||||
* 由 /public/job-categories/tree 接口返回,进首页和 Jobs 页时刷新
|
||||
* 其他页面/组件可直接从 store 读取
|
||||
*/
|
||||
jobCategories: JobCategoryItem[]
|
||||
|
||||
/**
|
||||
* 地区树分类数据(省市区三级嵌套)
|
||||
* 由 /public/regions/tree 接口返回,进首页和 Jobs 页时刷新
|
||||
* 其他页面/组件可直接从 store 读取
|
||||
*/
|
||||
regions: RegionItem[]
|
||||
|
||||
/**
|
||||
* 职位列表页缓存 — 从详情页返回时恢复列表和滚动位置
|
||||
* 为 null 表示没有缓存,需要重新请求
|
||||
*/
|
||||
jobListCache: JobListCache | null
|
||||
}
|
||||
|
||||
export default createStore<RootState>({
|
||||
state: {
|
||||
appName: 'JobAssistant',
|
||||
showLogin: false,
|
||||
loginRedirect: '',
|
||||
isAuthenticated: sessionStorage.getItem('isAuthenticated') === 'true',
|
||||
dynamicMenus: [],
|
||||
routesLoaded: false,
|
||||
dynamicRouteNames: [],
|
||||
industries: [],
|
||||
jobCategories: [],
|
||||
regions: [],
|
||||
jobListCache: null,
|
||||
},
|
||||
getters: {
|
||||
getAppName: (state) => state.appName,
|
||||
},
|
||||
mutations: {
|
||||
SET_APP_NAME(state, name: string) {
|
||||
state.appName = name
|
||||
},
|
||||
SET_SHOW_LOGIN(state, show: boolean) {
|
||||
state.showLogin = show
|
||||
},
|
||||
SET_LOGIN_REDIRECT(state, path: string) {
|
||||
state.loginRedirect = path
|
||||
},
|
||||
SET_AUTHENTICATED(state, val: boolean) {
|
||||
state.isAuthenticated = val
|
||||
if (val) {
|
||||
sessionStorage.setItem('isAuthenticated', 'true')
|
||||
} else {
|
||||
sessionStorage.removeItem('isAuthenticated')
|
||||
}
|
||||
},
|
||||
SET_DYNAMIC_MENUS(state, menus: MenuItemRaw[]) {
|
||||
state.dynamicMenus = menus
|
||||
},
|
||||
SET_ROUTES_LOADED(state, loaded: boolean) {
|
||||
state.routesLoaded = loaded
|
||||
},
|
||||
SET_DYNAMIC_ROUTE_NAMES(state, names: string[]) {
|
||||
state.dynamicRouteNames = names
|
||||
},
|
||||
SET_INDUSTRIES(state, data: IndustryItem[]) {
|
||||
state.industries = data
|
||||
},
|
||||
SET_JOB_CATEGORIES(state, data: JobCategoryItem[]) {
|
||||
state.jobCategories = data
|
||||
},
|
||||
SET_REGIONS(state, data: RegionItem[]) {
|
||||
state.regions = data
|
||||
},
|
||||
SET_JOB_LIST_CACHE(state, cache: JobListCache | null) {
|
||||
state.jobListCache = cache
|
||||
},
|
||||
},
|
||||
actions: {
|
||||
updateAppName({ commit }, name: string) {
|
||||
commit('SET_APP_NAME', name)
|
||||
},
|
||||
openLogin({ commit }, redirect = '') {
|
||||
commit('SET_LOGIN_REDIRECT', redirect)
|
||||
commit('SET_SHOW_LOGIN', true)
|
||||
},
|
||||
closeLogin({ commit }) {
|
||||
commit('SET_SHOW_LOGIN', false)
|
||||
commit('SET_LOGIN_REDIRECT', '')
|
||||
},
|
||||
|
||||
/**
|
||||
* 核心 action:从后端(或 mock)拉取菜单,转成路由并注册
|
||||
*
|
||||
* @param router — vue-router 实例,由路由守卫调用时传入
|
||||
*
|
||||
* 流程:
|
||||
* 1. 调 fetchUserRoutes 拿到后端菜单数据
|
||||
* 2. 存到 state.dynamicMenus(给 SideNav 渲染用)
|
||||
* 3. 用 buildDynamicRoutes 转成 RouteRecordRaw
|
||||
* 4. 逐条 router.addRoute 注册
|
||||
* 5. 记录已注册的路由名,标记 routesLoaded = true
|
||||
*/
|
||||
async loadDynamicRoutes({ commit }, router: Router) {
|
||||
const menus = await fetchUserRoutes()
|
||||
commit('SET_DYNAMIC_MENUS', menus)
|
||||
|
||||
const routes = buildDynamicRoutes(menus)
|
||||
const names: string[] = []
|
||||
|
||||
for (const route of routes) {
|
||||
router.addRoute(route)
|
||||
if (route.name) names.push(route.name as string)
|
||||
}
|
||||
|
||||
commit('SET_DYNAMIC_ROUTE_NAMES', names)
|
||||
commit('SET_ROUTES_LOADED', true)
|
||||
},
|
||||
|
||||
/**
|
||||
* 登出:重置状态(不再操作 localStorage,登录状态由 Cookie 管理)
|
||||
* 注意:动态路由不清除,与登录状态无关
|
||||
*/
|
||||
logout({ commit }) {
|
||||
commit('SET_AUTHENTICATED', false)
|
||||
commit('SET_SHOW_LOGIN', false)
|
||||
commit('SET_LOGIN_REDIRECT', '')
|
||||
},
|
||||
|
||||
/**
|
||||
* 加载工具类公共数据(行业分类、岗位分类等)
|
||||
* 进首页和 Jobs 页时调用,刷新全局数据
|
||||
*/
|
||||
async loadCommonData({ commit }) {
|
||||
try {
|
||||
const [industryRes, jobCategoryRes, regionRes] = await Promise.all([
|
||||
fetchIndustryTree(),
|
||||
fetchJobCategoryTree(),
|
||||
fetchRegionTree(),
|
||||
])
|
||||
if (industryRes.code === '0' && industryRes.data) {
|
||||
commit('SET_INDUSTRIES', industryRes.data)
|
||||
}
|
||||
if (jobCategoryRes.code === '0' && jobCategoryRes.data) {
|
||||
commit('SET_JOB_CATEGORIES', jobCategoryRes.data)
|
||||
}
|
||||
if (regionRes.code === '0' && regionRes.data) {
|
||||
commit('SET_REGIONS', regionRes.data)
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('[store] 加载公共分类数据失败', err)
|
||||
}
|
||||
},
|
||||
},
|
||||
modules: {},
|
||||
})
|
||||
Reference in New Issue
Block a user