mirror of
				https://gitee.com/hhyykk/ipms-sjy-ui.git
				synced 2025-11-04 12:18:43 +08:00 
			
		
		
		
	初始化项目,自 v1.7.1 版本开始
This commit is contained in:
		
							
								
								
									
										10
									
								
								src/store/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								src/store/index.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
			
		||||
import type { App } from 'vue'
 | 
			
		||||
import { createPinia } from 'pinia'
 | 
			
		||||
 | 
			
		||||
const store = createPinia()
 | 
			
		||||
 | 
			
		||||
export const setupStore = (app: App<Element>) => {
 | 
			
		||||
  app.use(store)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export { store }
 | 
			
		||||
							
								
								
									
										274
									
								
								src/store/modules/app.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										274
									
								
								src/store/modules/app.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,274 @@
 | 
			
		||||
import { defineStore } from 'pinia'
 | 
			
		||||
import { store } from '../index'
 | 
			
		||||
import { setCssVar, humpToUnderline } from '@/utils'
 | 
			
		||||
import { ElMessage } from 'element-plus'
 | 
			
		||||
import { CACHE_KEY, useCache } from '@/hooks/web/useCache'
 | 
			
		||||
import { ElementPlusSize } from '@/types/elementPlus'
 | 
			
		||||
import { LayoutType } from '@/types/layout'
 | 
			
		||||
import { ThemeTypes } from '@/types/theme'
 | 
			
		||||
 | 
			
		||||
const { wsCache } = useCache()
 | 
			
		||||
 | 
			
		||||
interface AppState {
 | 
			
		||||
  breadcrumb: boolean
 | 
			
		||||
  breadcrumbIcon: boolean
 | 
			
		||||
  collapse: boolean
 | 
			
		||||
  uniqueOpened: boolean
 | 
			
		||||
  hamburger: boolean
 | 
			
		||||
  screenfull: boolean
 | 
			
		||||
  size: boolean
 | 
			
		||||
  locale: boolean
 | 
			
		||||
  message: boolean
 | 
			
		||||
  tagsView: boolean
 | 
			
		||||
  tagsViewIcon: boolean
 | 
			
		||||
  logo: boolean
 | 
			
		||||
  fixedHeader: boolean
 | 
			
		||||
  greyMode: boolean
 | 
			
		||||
  pageLoading: boolean
 | 
			
		||||
  layout: LayoutType
 | 
			
		||||
  title: string
 | 
			
		||||
  userInfo: string
 | 
			
		||||
  isDark: boolean
 | 
			
		||||
  currentSize: ElementPlusSize
 | 
			
		||||
  sizeMap: ElementPlusSize[]
 | 
			
		||||
  mobile: boolean
 | 
			
		||||
  footer: boolean
 | 
			
		||||
  theme: ThemeTypes
 | 
			
		||||
  fixedMenu: boolean
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const useAppStore = defineStore('app', {
 | 
			
		||||
  state: (): AppState => {
 | 
			
		||||
    return {
 | 
			
		||||
      userInfo: 'userInfo', // 登录信息存储字段-建议每个项目换一个字段,避免与其他项目冲突
 | 
			
		||||
      sizeMap: ['default', 'large', 'small'],
 | 
			
		||||
      mobile: false, // 是否是移动端
 | 
			
		||||
      title: import.meta.env.VITE_APP_TITLE, // 标题
 | 
			
		||||
      pageLoading: false, // 路由跳转loading
 | 
			
		||||
 | 
			
		||||
      breadcrumb: true, // 面包屑
 | 
			
		||||
      breadcrumbIcon: true, // 面包屑图标
 | 
			
		||||
      collapse: false, // 折叠菜单
 | 
			
		||||
      uniqueOpened: true, // 是否只保持一个子菜单的展开
 | 
			
		||||
      hamburger: true, // 折叠图标
 | 
			
		||||
      screenfull: true, // 全屏图标
 | 
			
		||||
      size: true, // 尺寸图标
 | 
			
		||||
      locale: true, // 多语言图标
 | 
			
		||||
      message: true, // 消息图标
 | 
			
		||||
      tagsView: true, // 标签页
 | 
			
		||||
      tagsViewIcon: true, // 是否显示标签图标
 | 
			
		||||
      logo: true, // logo
 | 
			
		||||
      fixedHeader: true, // 固定toolheader
 | 
			
		||||
      footer: true, // 显示页脚
 | 
			
		||||
      greyMode: false, // 是否开始灰色模式,用于特殊悼念日
 | 
			
		||||
      fixedMenu: wsCache.get('fixedMenu') || false, // 是否固定菜单
 | 
			
		||||
 | 
			
		||||
      layout: wsCache.get(CACHE_KEY.LAYOUT) || 'classic', // layout布局
 | 
			
		||||
      isDark: wsCache.get(CACHE_KEY.IS_DARK) || false, // 是否是暗黑模式
 | 
			
		||||
      currentSize: wsCache.get('default') || 'default', // 组件尺寸
 | 
			
		||||
      theme: wsCache.get(CACHE_KEY.THEME) || {
 | 
			
		||||
        // 主题色
 | 
			
		||||
        elColorPrimary: '#409eff',
 | 
			
		||||
        // 左侧菜单边框颜色
 | 
			
		||||
        leftMenuBorderColor: 'inherit',
 | 
			
		||||
        // 左侧菜单背景颜色
 | 
			
		||||
        leftMenuBgColor: '#001529',
 | 
			
		||||
        // 左侧菜单浅色背景颜色
 | 
			
		||||
        leftMenuBgLightColor: '#0f2438',
 | 
			
		||||
        // 左侧菜单选中背景颜色
 | 
			
		||||
        leftMenuBgActiveColor: 'var(--el-color-primary)',
 | 
			
		||||
        // 左侧菜单收起选中背景颜色
 | 
			
		||||
        leftMenuCollapseBgActiveColor: 'var(--el-color-primary)',
 | 
			
		||||
        // 左侧菜单字体颜色
 | 
			
		||||
        leftMenuTextColor: '#bfcbd9',
 | 
			
		||||
        // 左侧菜单选中字体颜色
 | 
			
		||||
        leftMenuTextActiveColor: '#fff',
 | 
			
		||||
        // logo字体颜色
 | 
			
		||||
        logoTitleTextColor: '#fff',
 | 
			
		||||
        // logo边框颜色
 | 
			
		||||
        logoBorderColor: 'inherit',
 | 
			
		||||
        // 头部背景颜色
 | 
			
		||||
        topHeaderBgColor: '#fff',
 | 
			
		||||
        // 头部字体颜色
 | 
			
		||||
        topHeaderTextColor: 'inherit',
 | 
			
		||||
        // 头部悬停颜色
 | 
			
		||||
        topHeaderHoverColor: '#f6f6f6',
 | 
			
		||||
        // 头部边框颜色
 | 
			
		||||
        topToolBorderColor: '#eee'
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  getters: {
 | 
			
		||||
    getBreadcrumb(): boolean {
 | 
			
		||||
      return this.breadcrumb
 | 
			
		||||
    },
 | 
			
		||||
    getBreadcrumbIcon(): boolean {
 | 
			
		||||
      return this.breadcrumbIcon
 | 
			
		||||
    },
 | 
			
		||||
    getCollapse(): boolean {
 | 
			
		||||
      return this.collapse
 | 
			
		||||
    },
 | 
			
		||||
    getUniqueOpened(): boolean {
 | 
			
		||||
      return this.uniqueOpened
 | 
			
		||||
    },
 | 
			
		||||
    getHamburger(): boolean {
 | 
			
		||||
      return this.hamburger
 | 
			
		||||
    },
 | 
			
		||||
    getScreenfull(): boolean {
 | 
			
		||||
      return this.screenfull
 | 
			
		||||
    },
 | 
			
		||||
    getSize(): boolean {
 | 
			
		||||
      return this.size
 | 
			
		||||
    },
 | 
			
		||||
    getLocale(): boolean {
 | 
			
		||||
      return this.locale
 | 
			
		||||
    },
 | 
			
		||||
    getMessage(): boolean {
 | 
			
		||||
      return this.message
 | 
			
		||||
    },
 | 
			
		||||
    getTagsView(): boolean {
 | 
			
		||||
      return this.tagsView
 | 
			
		||||
    },
 | 
			
		||||
    getTagsViewIcon(): boolean {
 | 
			
		||||
      return this.tagsViewIcon
 | 
			
		||||
    },
 | 
			
		||||
    getLogo(): boolean {
 | 
			
		||||
      return this.logo
 | 
			
		||||
    },
 | 
			
		||||
    getFixedHeader(): boolean {
 | 
			
		||||
      return this.fixedHeader
 | 
			
		||||
    },
 | 
			
		||||
    getGreyMode(): boolean {
 | 
			
		||||
      return this.greyMode
 | 
			
		||||
    },
 | 
			
		||||
    getFixedMenu(): boolean {
 | 
			
		||||
      return this.fixedMenu
 | 
			
		||||
    },
 | 
			
		||||
    getPageLoading(): boolean {
 | 
			
		||||
      return this.pageLoading
 | 
			
		||||
    },
 | 
			
		||||
    getLayout(): LayoutType {
 | 
			
		||||
      return this.layout
 | 
			
		||||
    },
 | 
			
		||||
    getTitle(): string {
 | 
			
		||||
      return this.title
 | 
			
		||||
    },
 | 
			
		||||
    getUserInfo(): string {
 | 
			
		||||
      return this.userInfo
 | 
			
		||||
    },
 | 
			
		||||
    getIsDark(): boolean {
 | 
			
		||||
      return this.isDark
 | 
			
		||||
    },
 | 
			
		||||
    getCurrentSize(): ElementPlusSize {
 | 
			
		||||
      return this.currentSize
 | 
			
		||||
    },
 | 
			
		||||
    getSizeMap(): ElementPlusSize[] {
 | 
			
		||||
      return this.sizeMap
 | 
			
		||||
    },
 | 
			
		||||
    getMobile(): boolean {
 | 
			
		||||
      return this.mobile
 | 
			
		||||
    },
 | 
			
		||||
    getTheme(): ThemeTypes {
 | 
			
		||||
      return this.theme
 | 
			
		||||
    },
 | 
			
		||||
    getFooter(): boolean {
 | 
			
		||||
      return this.footer
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  actions: {
 | 
			
		||||
    setBreadcrumb(breadcrumb: boolean) {
 | 
			
		||||
      this.breadcrumb = breadcrumb
 | 
			
		||||
    },
 | 
			
		||||
    setBreadcrumbIcon(breadcrumbIcon: boolean) {
 | 
			
		||||
      this.breadcrumbIcon = breadcrumbIcon
 | 
			
		||||
    },
 | 
			
		||||
    setCollapse(collapse: boolean) {
 | 
			
		||||
      this.collapse = collapse
 | 
			
		||||
    },
 | 
			
		||||
    setUniqueOpened(uniqueOpened: boolean) {
 | 
			
		||||
      this.uniqueOpened = uniqueOpened
 | 
			
		||||
    },
 | 
			
		||||
    setHamburger(hamburger: boolean) {
 | 
			
		||||
      this.hamburger = hamburger
 | 
			
		||||
    },
 | 
			
		||||
    setScreenfull(screenfull: boolean) {
 | 
			
		||||
      this.screenfull = screenfull
 | 
			
		||||
    },
 | 
			
		||||
    setSize(size: boolean) {
 | 
			
		||||
      this.size = size
 | 
			
		||||
    },
 | 
			
		||||
    setLocale(locale: boolean) {
 | 
			
		||||
      this.locale = locale
 | 
			
		||||
    },
 | 
			
		||||
    setMessage(message: boolean) {
 | 
			
		||||
      this.message = message
 | 
			
		||||
    },
 | 
			
		||||
    setTagsView(tagsView: boolean) {
 | 
			
		||||
      this.tagsView = tagsView
 | 
			
		||||
    },
 | 
			
		||||
    setTagsViewIcon(tagsViewIcon: boolean) {
 | 
			
		||||
      this.tagsViewIcon = tagsViewIcon
 | 
			
		||||
    },
 | 
			
		||||
    setLogo(logo: boolean) {
 | 
			
		||||
      this.logo = logo
 | 
			
		||||
    },
 | 
			
		||||
    setFixedHeader(fixedHeader: boolean) {
 | 
			
		||||
      this.fixedHeader = fixedHeader
 | 
			
		||||
    },
 | 
			
		||||
    setGreyMode(greyMode: boolean) {
 | 
			
		||||
      this.greyMode = greyMode
 | 
			
		||||
    },
 | 
			
		||||
    setFixedMenu(fixedMenu: boolean) {
 | 
			
		||||
      wsCache.set('fixedMenu', fixedMenu)
 | 
			
		||||
      this.fixedMenu = fixedMenu
 | 
			
		||||
    },
 | 
			
		||||
    setPageLoading(pageLoading: boolean) {
 | 
			
		||||
      this.pageLoading = pageLoading
 | 
			
		||||
    },
 | 
			
		||||
    setLayout(layout: LayoutType) {
 | 
			
		||||
      if (this.mobile && layout !== 'classic') {
 | 
			
		||||
        ElMessage.warning('移动端模式下不支持切换其他布局')
 | 
			
		||||
        return
 | 
			
		||||
      }
 | 
			
		||||
      this.layout = layout
 | 
			
		||||
      wsCache.set(CACHE_KEY.LAYOUT, this.layout)
 | 
			
		||||
    },
 | 
			
		||||
    setTitle(title: string) {
 | 
			
		||||
      this.title = title
 | 
			
		||||
    },
 | 
			
		||||
    setIsDark(isDark: boolean) {
 | 
			
		||||
      this.isDark = isDark
 | 
			
		||||
      if (this.isDark) {
 | 
			
		||||
        document.documentElement.classList.add('dark')
 | 
			
		||||
        document.documentElement.classList.remove('light')
 | 
			
		||||
      } else {
 | 
			
		||||
        document.documentElement.classList.add('light')
 | 
			
		||||
        document.documentElement.classList.remove('dark')
 | 
			
		||||
      }
 | 
			
		||||
      wsCache.set(CACHE_KEY.IS_DARK, this.isDark)
 | 
			
		||||
    },
 | 
			
		||||
    setCurrentSize(currentSize: ElementPlusSize) {
 | 
			
		||||
      this.currentSize = currentSize
 | 
			
		||||
      wsCache.set('currentSize', this.currentSize)
 | 
			
		||||
    },
 | 
			
		||||
    setMobile(mobile: boolean) {
 | 
			
		||||
      this.mobile = mobile
 | 
			
		||||
    },
 | 
			
		||||
    setTheme(theme: ThemeTypes) {
 | 
			
		||||
      this.theme = Object.assign(this.theme, theme)
 | 
			
		||||
      wsCache.set(CACHE_KEY.THEME, this.theme)
 | 
			
		||||
    },
 | 
			
		||||
    setCssVarTheme() {
 | 
			
		||||
      for (const key in this.theme) {
 | 
			
		||||
        setCssVar(`--${humpToUnderline(key)}`, this.theme[key])
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    setFooter(footer: boolean) {
 | 
			
		||||
      this.footer = footer
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
export const useAppStoreWithOut = () => {
 | 
			
		||||
  return useAppStore(store)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										103
									
								
								src/store/modules/dict.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								src/store/modules/dict.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,103 @@
 | 
			
		||||
import { defineStore } from 'pinia'
 | 
			
		||||
import { store } from '../index'
 | 
			
		||||
import { DictDataVO } from '@/api/system/dict/types'
 | 
			
		||||
import { CACHE_KEY, useCache } from '@/hooks/web/useCache'
 | 
			
		||||
const { wsCache } = useCache('sessionStorage')
 | 
			
		||||
import { listSimpleDictDataApi } from '@/api/system/dict/dict.data'
 | 
			
		||||
 | 
			
		||||
export interface DictValueType {
 | 
			
		||||
  value: any
 | 
			
		||||
  label: string
 | 
			
		||||
  clorType?: string
 | 
			
		||||
  cssClass?: string
 | 
			
		||||
}
 | 
			
		||||
export interface DictTypeType {
 | 
			
		||||
  dictType: string
 | 
			
		||||
  dictValue: DictValueType[]
 | 
			
		||||
}
 | 
			
		||||
export interface DictState {
 | 
			
		||||
  dictMap: Map<string, any>
 | 
			
		||||
  isSetDict: boolean
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const useDictStore = defineStore('dict', {
 | 
			
		||||
  state: (): DictState => ({
 | 
			
		||||
    dictMap: new Map<string, any>(),
 | 
			
		||||
    isSetDict: false
 | 
			
		||||
  }),
 | 
			
		||||
  getters: {
 | 
			
		||||
    getDictMap(): Recordable {
 | 
			
		||||
      const dictMap = wsCache.get(CACHE_KEY.DICT_CACHE)
 | 
			
		||||
      if (dictMap) {
 | 
			
		||||
        this.dictMap = dictMap
 | 
			
		||||
      }
 | 
			
		||||
      return this.dictMap
 | 
			
		||||
    },
 | 
			
		||||
    getIsSetDict(): boolean {
 | 
			
		||||
      return this.isSetDict
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  actions: {
 | 
			
		||||
    async setDictMap() {
 | 
			
		||||
      const dictMap = wsCache.get(CACHE_KEY.DICT_CACHE)
 | 
			
		||||
      if (dictMap) {
 | 
			
		||||
        this.dictMap = dictMap
 | 
			
		||||
        this.isSetDict = true
 | 
			
		||||
      } else {
 | 
			
		||||
        const res = await listSimpleDictDataApi()
 | 
			
		||||
        // 设置数据
 | 
			
		||||
        const dictDataMap = new Map<string, any>()
 | 
			
		||||
        res.forEach((dictData: DictDataVO) => {
 | 
			
		||||
          // 获得 dictType 层级
 | 
			
		||||
          const enumValueObj = dictDataMap[dictData.dictType]
 | 
			
		||||
          if (!enumValueObj) {
 | 
			
		||||
            dictDataMap[dictData.dictType] = []
 | 
			
		||||
          }
 | 
			
		||||
          // 处理 dictValue 层级
 | 
			
		||||
          dictDataMap[dictData.dictType].push({
 | 
			
		||||
            value: dictData.value,
 | 
			
		||||
            label: dictData.label,
 | 
			
		||||
            colorType: dictData.colorType,
 | 
			
		||||
            cssClass: dictData.cssClass
 | 
			
		||||
          })
 | 
			
		||||
        })
 | 
			
		||||
        this.dictMap = dictDataMap
 | 
			
		||||
        this.isSetDict = true
 | 
			
		||||
        wsCache.set(CACHE_KEY.DICT_CACHE, dictDataMap, { exp: 60 }) // 60 秒 过期
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    getDictByType(type: string) {
 | 
			
		||||
      if (!this.isSetDict) {
 | 
			
		||||
        this.setDictMap()
 | 
			
		||||
      }
 | 
			
		||||
      return this.dictMap[type]
 | 
			
		||||
    },
 | 
			
		||||
    async resetDict() {
 | 
			
		||||
      wsCache.delete(CACHE_KEY.DICT_CACHE)
 | 
			
		||||
      const res = await listSimpleDictDataApi()
 | 
			
		||||
      // 设置数据
 | 
			
		||||
      const dictDataMap = new Map<string, any>()
 | 
			
		||||
      res.forEach((dictData: DictDataVO) => {
 | 
			
		||||
        // 获得 dictType 层级
 | 
			
		||||
        const enumValueObj = dictDataMap[dictData.dictType]
 | 
			
		||||
        if (!enumValueObj) {
 | 
			
		||||
          dictDataMap[dictData.dictType] = []
 | 
			
		||||
        }
 | 
			
		||||
        // 处理 dictValue 层级
 | 
			
		||||
        dictDataMap[dictData.dictType].push({
 | 
			
		||||
          value: dictData.value,
 | 
			
		||||
          label: dictData.label,
 | 
			
		||||
          colorType: dictData.colorType,
 | 
			
		||||
          cssClass: dictData.cssClass
 | 
			
		||||
        })
 | 
			
		||||
      })
 | 
			
		||||
      this.dictMap = dictDataMap
 | 
			
		||||
      this.isSetDict = true
 | 
			
		||||
      wsCache.set(CACHE_KEY.DICT_CACHE, dictDataMap, { exp: 60 }) // 60 秒 过期
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
export const useDictStoreWithOut = () => {
 | 
			
		||||
  return useDictStore(store)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										59
									
								
								src/store/modules/locale.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								src/store/modules/locale.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,59 @@
 | 
			
		||||
import { defineStore } from 'pinia'
 | 
			
		||||
import { store } from '../index'
 | 
			
		||||
import zhCn from 'element-plus/es/locale/lang/zh-cn'
 | 
			
		||||
import en from 'element-plus/es/locale/lang/en'
 | 
			
		||||
import { CACHE_KEY, useCache } from '@/hooks/web/useCache'
 | 
			
		||||
import { LocaleDropdownType } from '@/types/localeDropdown'
 | 
			
		||||
 | 
			
		||||
const { wsCache } = useCache()
 | 
			
		||||
 | 
			
		||||
const elLocaleMap = {
 | 
			
		||||
  'zh-CN': zhCn,
 | 
			
		||||
  en: en
 | 
			
		||||
}
 | 
			
		||||
interface LocaleState {
 | 
			
		||||
  currentLocale: LocaleDropdownType
 | 
			
		||||
  localeMap: LocaleDropdownType[]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const useLocaleStore = defineStore('locales', {
 | 
			
		||||
  state: (): LocaleState => {
 | 
			
		||||
    return {
 | 
			
		||||
      currentLocale: {
 | 
			
		||||
        lang: wsCache.get(CACHE_KEY.LANG) || 'zh-CN',
 | 
			
		||||
        elLocale: elLocaleMap[wsCache.get(CACHE_KEY.LANG) || 'zh-CN']
 | 
			
		||||
      },
 | 
			
		||||
      // 多语言
 | 
			
		||||
      localeMap: [
 | 
			
		||||
        {
 | 
			
		||||
          lang: 'zh-CN',
 | 
			
		||||
          name: '简体中文'
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
          lang: 'en',
 | 
			
		||||
          name: 'English'
 | 
			
		||||
        }
 | 
			
		||||
      ]
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  getters: {
 | 
			
		||||
    getCurrentLocale(): LocaleDropdownType {
 | 
			
		||||
      return this.currentLocale
 | 
			
		||||
    },
 | 
			
		||||
    getLocaleMap(): LocaleDropdownType[] {
 | 
			
		||||
      return this.localeMap
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  actions: {
 | 
			
		||||
    setCurrentLocale(localeMap: LocaleDropdownType) {
 | 
			
		||||
      // this.locale = Object.assign(this.locale, localeMap)
 | 
			
		||||
      this.currentLocale.lang = localeMap?.lang
 | 
			
		||||
      this.currentLocale.elLocale = elLocaleMap[localeMap?.lang]
 | 
			
		||||
      wsCache.set(CACHE_KEY.LANG, localeMap?.lang)
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
export const useLocaleStoreWithOut = () => {
 | 
			
		||||
  return useLocaleStore(store)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										70
									
								
								src/store/modules/permission.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								src/store/modules/permission.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,70 @@
 | 
			
		||||
import { defineStore } from 'pinia'
 | 
			
		||||
import { store } from '../index'
 | 
			
		||||
import { cloneDeep } from 'lodash-es'
 | 
			
		||||
import remainingRouter from '@/router/modules/remaining'
 | 
			
		||||
import { generateRoute, flatMultiLevelRoutes } from '@/utils/routerHelper'
 | 
			
		||||
import { getAsyncRoutesApi } from '@/api/login'
 | 
			
		||||
import { CACHE_KEY, useCache } from '@/hooks/web/useCache'
 | 
			
		||||
 | 
			
		||||
const { wsCache } = useCache()
 | 
			
		||||
 | 
			
		||||
export interface PermissionState {
 | 
			
		||||
  routers: AppRouteRecordRaw[]
 | 
			
		||||
  addRouters: AppRouteRecordRaw[]
 | 
			
		||||
  menuTabRouters: AppRouteRecordRaw[]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const usePermissionStore = defineStore('permission', {
 | 
			
		||||
  state: (): PermissionState => ({
 | 
			
		||||
    routers: [],
 | 
			
		||||
    addRouters: [],
 | 
			
		||||
    menuTabRouters: []
 | 
			
		||||
  }),
 | 
			
		||||
  getters: {
 | 
			
		||||
    getRouters(): AppRouteRecordRaw[] {
 | 
			
		||||
      return this.routers
 | 
			
		||||
    },
 | 
			
		||||
    getAddRouters(): AppRouteRecordRaw[] {
 | 
			
		||||
      return flatMultiLevelRoutes(cloneDeep(this.addRouters))
 | 
			
		||||
    },
 | 
			
		||||
    getMenuTabRouters(): AppRouteRecordRaw[] {
 | 
			
		||||
      return this.menuTabRouters
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  actions: {
 | 
			
		||||
    async generateRoutes(): Promise<unknown> {
 | 
			
		||||
      return new Promise<void>(async (resolve) => {
 | 
			
		||||
        let res: AppCustomRouteRecordRaw[]
 | 
			
		||||
        if (wsCache.get(CACHE_KEY.ROLE_ROUTERS)) {
 | 
			
		||||
          res = wsCache.get(CACHE_KEY.ROLE_ROUTERS) as AppCustomRouteRecordRaw[]
 | 
			
		||||
        } else {
 | 
			
		||||
          res = await getAsyncRoutesApi()
 | 
			
		||||
          wsCache.set(CACHE_KEY.ROLE_ROUTERS, res)
 | 
			
		||||
        }
 | 
			
		||||
        const routerMap: AppRouteRecordRaw[] = generateRoute(res as AppCustomRouteRecordRaw[])
 | 
			
		||||
        // 动态路由,404一定要放到最后面
 | 
			
		||||
        this.addRouters = routerMap.concat([
 | 
			
		||||
          {
 | 
			
		||||
            path: '/:path(.*)*',
 | 
			
		||||
            redirect: '/404',
 | 
			
		||||
            name: '404Page',
 | 
			
		||||
            meta: {
 | 
			
		||||
              hidden: true,
 | 
			
		||||
              breadcrumb: false
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        ])
 | 
			
		||||
        // 渲染菜单的所有路由
 | 
			
		||||
        this.routers = cloneDeep(remainingRouter).concat(routerMap)
 | 
			
		||||
        resolve()
 | 
			
		||||
      })
 | 
			
		||||
    },
 | 
			
		||||
    setMenuTabRouters(routers: AppRouteRecordRaw[]): void {
 | 
			
		||||
      this.menuTabRouters = routers
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
export const usePermissionStoreWithOut = () => {
 | 
			
		||||
  return usePermissionStore(store)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										140
									
								
								src/store/modules/tagsView.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										140
									
								
								src/store/modules/tagsView.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,140 @@
 | 
			
		||||
import router from '@/router'
 | 
			
		||||
import type { RouteLocationNormalizedLoaded } from 'vue-router'
 | 
			
		||||
import { getRawRoute } from '@/utils/routerHelper'
 | 
			
		||||
import { defineStore } from 'pinia'
 | 
			
		||||
import { store } from '../index'
 | 
			
		||||
import { findIndex } from '@/utils'
 | 
			
		||||
 | 
			
		||||
export interface TagsViewState {
 | 
			
		||||
  visitedViews: RouteLocationNormalizedLoaded[]
 | 
			
		||||
  cachedViews: Set<string>
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const useTagsViewStore = defineStore('tagsView', {
 | 
			
		||||
  state: (): TagsViewState => ({
 | 
			
		||||
    visitedViews: [],
 | 
			
		||||
    cachedViews: new Set()
 | 
			
		||||
  }),
 | 
			
		||||
  getters: {
 | 
			
		||||
    getVisitedViews(): RouteLocationNormalizedLoaded[] {
 | 
			
		||||
      return this.visitedViews
 | 
			
		||||
    },
 | 
			
		||||
    getCachedViews(): string[] {
 | 
			
		||||
      return Array.from(this.cachedViews)
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  actions: {
 | 
			
		||||
    // 新增缓存和tag
 | 
			
		||||
    addView(view: RouteLocationNormalizedLoaded): void {
 | 
			
		||||
      this.addVisitedView(view)
 | 
			
		||||
      this.addCachedView()
 | 
			
		||||
    },
 | 
			
		||||
    // 新增tag
 | 
			
		||||
    addVisitedView(view: RouteLocationNormalizedLoaded) {
 | 
			
		||||
      if (this.visitedViews.some((v) => v.path === view.path)) return
 | 
			
		||||
      if (view.meta?.noTagsView) return
 | 
			
		||||
      this.visitedViews.push(
 | 
			
		||||
        Object.assign({}, view, {
 | 
			
		||||
          title: view.meta?.title || 'no-name'
 | 
			
		||||
        })
 | 
			
		||||
      )
 | 
			
		||||
    },
 | 
			
		||||
    // 新增缓存
 | 
			
		||||
    addCachedView() {
 | 
			
		||||
      const cacheMap: Set<string> = new Set()
 | 
			
		||||
      for (const v of this.visitedViews) {
 | 
			
		||||
        const item = getRawRoute(v)
 | 
			
		||||
        const needCache = !item.meta?.noCache
 | 
			
		||||
        if (!needCache) {
 | 
			
		||||
          continue
 | 
			
		||||
        }
 | 
			
		||||
        const name = item.name as string
 | 
			
		||||
        cacheMap.add(name)
 | 
			
		||||
      }
 | 
			
		||||
      if (Array.from(this.cachedViews).sort().toString() === Array.from(cacheMap).sort().toString())
 | 
			
		||||
        return
 | 
			
		||||
      this.cachedViews = cacheMap
 | 
			
		||||
    },
 | 
			
		||||
    // 删除某个
 | 
			
		||||
    delView(view: RouteLocationNormalizedLoaded) {
 | 
			
		||||
      this.delVisitedView(view)
 | 
			
		||||
      this.addCachedView()
 | 
			
		||||
    },
 | 
			
		||||
    // 删除tag
 | 
			
		||||
    delVisitedView(view: RouteLocationNormalizedLoaded) {
 | 
			
		||||
      for (const [i, v] of this.visitedViews.entries()) {
 | 
			
		||||
        if (v.path === view.path) {
 | 
			
		||||
          this.visitedViews.splice(i, 1)
 | 
			
		||||
          break
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    // 删除缓存
 | 
			
		||||
    delCachedView() {
 | 
			
		||||
      const route = router.currentRoute.value
 | 
			
		||||
      const index = findIndex<string>(this.getCachedViews, (v) => v === route.name)
 | 
			
		||||
      if (index > -1) {
 | 
			
		||||
        this.cachedViews.delete(this.getCachedViews[index])
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    // 删除所有缓存和tag
 | 
			
		||||
    delAllViews() {
 | 
			
		||||
      this.delAllVisitedViews()
 | 
			
		||||
      this.addCachedView()
 | 
			
		||||
    },
 | 
			
		||||
    // 删除所有tag
 | 
			
		||||
    delAllVisitedViews() {
 | 
			
		||||
      // const affixTags = this.visitedViews.filter((tag) => tag.meta.affix)
 | 
			
		||||
      this.visitedViews = []
 | 
			
		||||
    },
 | 
			
		||||
    // 删除其他
 | 
			
		||||
    delOthersViews(view: RouteLocationNormalizedLoaded) {
 | 
			
		||||
      this.delOthersVisitedViews(view)
 | 
			
		||||
      this.addCachedView()
 | 
			
		||||
    },
 | 
			
		||||
    // 删除其他tag
 | 
			
		||||
    delOthersVisitedViews(view: RouteLocationNormalizedLoaded) {
 | 
			
		||||
      this.visitedViews = this.visitedViews.filter((v) => {
 | 
			
		||||
        return v?.meta?.affix || v.path === view.path
 | 
			
		||||
      })
 | 
			
		||||
    },
 | 
			
		||||
    // 删除左侧
 | 
			
		||||
    delLeftViews(view: RouteLocationNormalizedLoaded) {
 | 
			
		||||
      const index = findIndex<RouteLocationNormalizedLoaded>(
 | 
			
		||||
        this.visitedViews,
 | 
			
		||||
        (v) => v.path === view.path
 | 
			
		||||
      )
 | 
			
		||||
      if (index > -1) {
 | 
			
		||||
        this.visitedViews = this.visitedViews.filter((v, i) => {
 | 
			
		||||
          return v?.meta?.affix || v.path === view.path || i > index
 | 
			
		||||
        })
 | 
			
		||||
        this.addCachedView()
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    // 删除右侧
 | 
			
		||||
    delRightViews(view: RouteLocationNormalizedLoaded) {
 | 
			
		||||
      const index = findIndex<RouteLocationNormalizedLoaded>(
 | 
			
		||||
        this.visitedViews,
 | 
			
		||||
        (v) => v.path === view.path
 | 
			
		||||
      )
 | 
			
		||||
      if (index > -1) {
 | 
			
		||||
        this.visitedViews = this.visitedViews.filter((v, i) => {
 | 
			
		||||
          return v?.meta?.affix || v.path === view.path || i < index
 | 
			
		||||
        })
 | 
			
		||||
        this.addCachedView()
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    updateVisitedView(view: RouteLocationNormalizedLoaded) {
 | 
			
		||||
      for (let v of this.visitedViews) {
 | 
			
		||||
        if (v.path === view.path) {
 | 
			
		||||
          v = Object.assign(v, view)
 | 
			
		||||
          break
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
export const useTagsViewStoreWithOut = () => {
 | 
			
		||||
  return useTagsViewStore(store)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										83
									
								
								src/store/modules/user.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								src/store/modules/user.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,83 @@
 | 
			
		||||
import { store } from '../index'
 | 
			
		||||
import { defineStore } from 'pinia'
 | 
			
		||||
import { getAccessToken, removeToken } from '@/utils/auth'
 | 
			
		||||
import { CACHE_KEY, useCache } from '@/hooks/web/useCache'
 | 
			
		||||
import { getInfoApi, loginOutApi } from '@/api/login'
 | 
			
		||||
 | 
			
		||||
const { wsCache } = useCache()
 | 
			
		||||
 | 
			
		||||
interface UserVO {
 | 
			
		||||
  id: number
 | 
			
		||||
  avatar: string
 | 
			
		||||
  nickname: string
 | 
			
		||||
}
 | 
			
		||||
interface UserInfoVO {
 | 
			
		||||
  permissions: string[]
 | 
			
		||||
  roles: string[]
 | 
			
		||||
  isSetUser: boolean
 | 
			
		||||
  user: UserVO
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const useUserStore = defineStore('admin-user', {
 | 
			
		||||
  state: (): UserInfoVO => ({
 | 
			
		||||
    permissions: [],
 | 
			
		||||
    roles: [],
 | 
			
		||||
    isSetUser: false,
 | 
			
		||||
    user: {
 | 
			
		||||
      id: 0,
 | 
			
		||||
      avatar: '',
 | 
			
		||||
      nickname: ''
 | 
			
		||||
    }
 | 
			
		||||
  }),
 | 
			
		||||
  getters: {
 | 
			
		||||
    getPermissions(): string[] {
 | 
			
		||||
      return this.permissions
 | 
			
		||||
    },
 | 
			
		||||
    getRoles(): string[] {
 | 
			
		||||
      return this.roles
 | 
			
		||||
    },
 | 
			
		||||
    getIsSetUser(): boolean {
 | 
			
		||||
      return this.isSetUser
 | 
			
		||||
    },
 | 
			
		||||
    getUser(): UserVO {
 | 
			
		||||
      return this.user
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  actions: {
 | 
			
		||||
    async setUserInfoAction() {
 | 
			
		||||
      if (!getAccessToken()) {
 | 
			
		||||
        this.resetState()
 | 
			
		||||
        return null
 | 
			
		||||
      }
 | 
			
		||||
      let userInfo = wsCache.get(CACHE_KEY.USER)
 | 
			
		||||
      if (!userInfo) {
 | 
			
		||||
        userInfo = await getInfoApi()
 | 
			
		||||
      }
 | 
			
		||||
      this.permissions = userInfo.permissions
 | 
			
		||||
      this.roles = userInfo.roles
 | 
			
		||||
      this.user = userInfo.user
 | 
			
		||||
      this.isSetUser = true
 | 
			
		||||
      wsCache.set(CACHE_KEY.USER, userInfo)
 | 
			
		||||
    },
 | 
			
		||||
    async loginOut() {
 | 
			
		||||
      await loginOutApi()
 | 
			
		||||
      removeToken()
 | 
			
		||||
      wsCache.clear()
 | 
			
		||||
      this.resetState()
 | 
			
		||||
    },
 | 
			
		||||
    resetState() {
 | 
			
		||||
      this.permissions = []
 | 
			
		||||
      this.roles = []
 | 
			
		||||
      this.isSetUser = false
 | 
			
		||||
      this.user = {
 | 
			
		||||
        id: 0,
 | 
			
		||||
        avatar: '',
 | 
			
		||||
        nickname: ''
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
export const useUserStoreWithOut = () => {
 | 
			
		||||
  return useUserStore(store)
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user