wip: perf pinia

This commit is contained in:
kailong321200875 2022-09-30 16:52:39 +08:00
parent da39f3bc90
commit e757c54fb6
10 changed files with 180 additions and 197 deletions

View File

@ -27,13 +27,13 @@
}, },
"dependencies": { "dependencies": {
"@iconify/iconify": "^3.0.0", "@iconify/iconify": "^3.0.0",
"@vueuse/core": "^9.2.0", "@vueuse/core": "^9.3.0",
"@wangeditor/editor": "^5.1.18", "@wangeditor/editor": "^5.1.20",
"@wangeditor/editor-for-vue": "^5.1.10", "@wangeditor/editor-for-vue": "^5.1.10",
"@zxcvbn-ts/core": "^2.0.5", "@zxcvbn-ts/core": "^2.0.5",
"animate.css": "^4.1.1", "animate.css": "^4.1.1",
"axios": "^0.27.2", "axios": "^0.27.2",
"echarts": "^5.3.3", "echarts": "^5.4.0",
"echarts-wordcloud": "^2.0.0", "echarts-wordcloud": "^2.0.0",
"element-plus": "2.2.17", "element-plus": "2.2.17",
"intro.js": "^6.0.0", "intro.js": "^6.0.0",
@ -42,11 +42,11 @@
"mockjs": "^1.1.0", "mockjs": "^1.1.0",
"nprogress": "^0.2.0", "nprogress": "^0.2.0",
"pinia": "^2.0.22", "pinia": "^2.0.22",
"pinia-plugin-persist": "^1.0.0", "pinia-plugin-persistedstate": "^2.2.0",
"qrcode": "^1.5.1", "qrcode": "^1.5.1",
"qs": "^6.11.0", "qs": "^6.11.0",
"url": "^0.11.0", "url": "^0.11.0",
"vue": "3.2.39", "vue": "3.2.40",
"vue-i18n": "9.2.2", "vue-i18n": "9.2.2",
"vue-router": "^4.1.5", "vue-router": "^4.1.5",
"vue-types": "^4.2.1", "vue-types": "^4.2.1",
@ -55,21 +55,21 @@
"devDependencies": { "devDependencies": {
"@commitlint/cli": "^17.1.2", "@commitlint/cli": "^17.1.2",
"@commitlint/config-conventional": "^17.1.0", "@commitlint/config-conventional": "^17.1.0",
"@iconify/json": "^2.1.110", "@iconify/json": "^2.1.115",
"@intlify/vite-plugin-vue-i18n": "^6.0.1", "@intlify/vite-plugin-vue-i18n": "^6.0.3",
"@purge-icons/generated": "^0.9.0", "@purge-icons/generated": "^0.9.0",
"@types/intro.js": "^5.1.0", "@types/intro.js": "^5.1.0",
"@types/lodash-es": "^4.17.6", "@types/lodash-es": "^4.17.6",
"@types/node": "^18.7.18", "@types/node": "^18.7.23",
"@types/nprogress": "^0.2.0", "@types/nprogress": "^0.2.0",
"@types/qrcode": "^1.5.0", "@types/qrcode": "^1.5.0",
"@types/qs": "^6.9.7", "@types/qs": "^6.9.7",
"@typescript-eslint/eslint-plugin": "^5.38.0", "@typescript-eslint/eslint-plugin": "^5.38.1",
"@typescript-eslint/parser": "^5.38.0", "@typescript-eslint/parser": "^5.38.1",
"@vitejs/plugin-vue": "^3.1.0", "@vitejs/plugin-vue": "^3.1.0",
"@vitejs/plugin-vue-jsx": "^2.0.1", "@vitejs/plugin-vue-jsx": "^2.0.1",
"autoprefixer": "^10.4.12", "autoprefixer": "^10.4.12",
"eslint": "^8.23.1", "eslint": "^8.24.0",
"eslint-config-prettier": "^8.5.0", "eslint-config-prettier": "^8.5.0",
"eslint-define-config": "^1.7.0", "eslint-define-config": "^1.7.0",
"eslint-plugin-prettier": "^4.2.1", "eslint-plugin-prettier": "^4.2.1",
@ -83,16 +83,16 @@
"postcss-less": "^6.0.0", "postcss-less": "^6.0.0",
"prettier": "^2.7.1", "prettier": "^2.7.1",
"rimraf": "^3.0.2", "rimraf": "^3.0.2",
"rollup": "^2.79.0", "rollup": "^2.79.1",
"stylelint": "^14.12.0", "stylelint": "^14.13.0",
"stylelint-config-html": "^1.1.0", "stylelint-config-html": "^1.1.0",
"stylelint-config-prettier": "^9.0.3", "stylelint-config-prettier": "^9.0.3",
"stylelint-config-recommended": "^9.0.0", "stylelint-config-recommended": "^9.0.0",
"stylelint-config-standard": "^28.0.0", "stylelint-config-standard": "^28.0.0",
"stylelint-order": "^5.0.0", "stylelint-order": "^5.0.0",
"typescript": "4.8.3", "typescript": "4.8.4",
"unplugin-vue-macros": "^0.11.2", "unplugin-vue-macros": "^0.11.2",
"vite": "3.1.3", "vite": "3.1.4",
"vite-plugin-eslint": "^1.8.1", "vite-plugin-eslint": "^1.8.1",
"vite-plugin-html": "^3.2.0", "vite-plugin-html": "^3.2.0",
"vite-plugin-mock": "^2.9.6", "vite-plugin-mock": "^2.9.6",

View File

@ -1,106 +0,0 @@
import { useCache } from '@/hooks/web/useCache'
const { wsCache } = useCache()
export type LayoutType = 'classic' | 'topLeft' | 'top' | 'cutMenu'
export type ThemeTypes = {
elColorPrimary?: string
leftMenuBorderColor?: string
leftMenuBgColor?: string
leftMenuBgLightColor?: string
leftMenuBgActiveColor?: string
leftMenuCollapseBgActiveColor?: string
leftMenuTextColor?: string
leftMenuTextActiveColor?: string
logoTitleTextColor?: string
logoBorderColor?: string
topHeaderBgColor?: string
topHeaderTextColor?: string
topHeaderHoverColor?: string
topToolBorderColor?: string
}
export interface AppState {
breadcrumb: boolean
breadcrumbIcon: boolean
collapse: boolean
uniqueOpened: boolean
hamburger: boolean
screenfull: boolean
size: boolean
locale: boolean
tagsView: boolean
tagsViewIcon: boolean
logo: boolean
fixedHeader: boolean
greyMode: boolean
dynamicRouter: boolean
pageLoading: boolean
layout: LayoutType
title: string
userInfo: string
isDark: boolean
currentSize: ElememtPlusSize
sizeMap: ElememtPlusSize[]
mobile: boolean
footer: boolean
theme: ThemeTypes
}
export const appModules: AppState = {
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: false, // 是否只保持一个子菜单的展开
hamburger: true, // 折叠图标
screenfull: true, // 全屏图标
size: true, // 尺寸图标
locale: true, // 多语言图标
tagsView: true, // 标签页
tagsViewIcon: true, // 是否显示标签图标
logo: true, // logo
fixedHeader: true, // 固定toolheader
footer: true, // 显示页脚
greyMode: false, // 是否开始灰色模式,用于特殊悼念日
dynamicRouter: wsCache.get('dynamicRouter') || false, // 是否动态路由
layout: wsCache.get('layout') || 'classic', // layout布局
isDark: wsCache.get('isDark') || false, // 是否是暗黑模式
currentSize: wsCache.get('default') || 'default', // 组件尺寸
theme: wsCache.get('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'
}
}

View File

@ -1,32 +0,0 @@
import { useCache } from '@/hooks/web/useCache'
import zhCn from 'element-plus/es/locale/lang/zh-cn'
import en from 'element-plus/es/locale/lang/en'
const { wsCache } = useCache()
export const elLocaleMap = {
'zh-CN': zhCn,
en: en
}
export interface LocaleState {
currentLocale: LocaleDropdownType
localeMap: LocaleDropdownType[]
}
export const localeModules: LocaleState = {
currentLocale: {
lang: wsCache.get('lang') || 'zh-CN',
elLocale: elLocaleMap[wsCache.get('lang') || 'zh-CN']
},
// 多语言
localeMap: [
{
lang: 'zh-CN',
name: '简体中文'
},
{
lang: 'en',
name: 'English'
}
]
}

View File

@ -4,11 +4,13 @@ import '@/plugins/windi.css'
// 导入全局的svg图标 // 导入全局的svg图标
import '@/plugins/svgIcon' import '@/plugins/svgIcon'
import './store'
// 初始化多语言 // 初始化多语言
import { setupI18n } from '@/plugins/vueI18n' import { setupI18n } from '@/plugins/vueI18n'
// 引入状态管理 // 引入状态管理
import { setupStore } from '@/store' // import { setupStore } from '@/store'
// 全局组件 // 全局组件
import { setupGlobCom } from '@/components' import { setupGlobCom } from '@/components'
@ -33,13 +35,14 @@ import { createApp } from 'vue'
import App from './App.vue' import App from './App.vue'
import './permission' import './permission'
// 创建实例 // 创建实例
const setupAll = async () => { const setupAll = async () => {
const app = createApp(App) const app = createApp(App)
await setupI18n(app) await setupI18n(app)
setupStore(app) // setupStore(app)
setupGlobCom(app) setupGlobCom(app)

View File

@ -1,13 +1,22 @@
import type { App } from 'vue' // TODO: 感觉这样是有问题的,但目前还没想到更好的办法
import { createPinia } from 'pinia' import { createPinia } from 'pinia'
import piniaPluginPersist from 'pinia-plugin-persist'
import { createApp } from 'vue'
import App from '../App.vue'
import { createPersistedState } from 'pinia-plugin-persistedstate'
const app = createApp(App)
const store = createPinia() const store = createPinia()
store.use(piniaPluginPersist) store.use(
createPersistedState({
storage: sessionStorage
})
)
export const setupStore = (app: App<Element>) => { app.use(store)
app.use(store)
}
export { store } export { store }

View File

@ -1,19 +1,114 @@
import { defineStore } from 'pinia' import { defineStore } from 'pinia'
import { store } from '../index' import { store } from '../index'
import { useCache } from '@/hooks/web/useCache'
import { appModules } from '@/config/app'
import type { AppState, LayoutType, ThemeTypes } from '@/config/app'
import { setCssVar, humpToUnderline } from '@/utils' import { setCssVar, humpToUnderline } from '@/utils'
import { ElMessage } from 'element-plus' import { ElMessage } from 'element-plus'
const { wsCache } = useCache() type LayoutType = 'classic' | 'topLeft' | 'top' | 'cutMenu'
export const useAppStore = defineStore({ type ThemeTypes = {
id: 'app', elColorPrimary?: string
state: (): AppState => appModules, leftMenuBorderColor?: string
persist: { leftMenuBgColor?: string
enabled: true leftMenuBgLightColor?: string
leftMenuBgActiveColor?: string
leftMenuCollapseBgActiveColor?: string
leftMenuTextColor?: string
leftMenuTextActiveColor?: string
logoTitleTextColor?: string
logoBorderColor?: string
topHeaderBgColor?: string
topHeaderTextColor?: string
topHeaderHoverColor?: string
topToolBorderColor?: string
}
interface AppState {
breadcrumb: boolean
breadcrumbIcon: boolean
collapse: boolean
uniqueOpened: boolean
hamburger: boolean
screenfull: boolean
size: boolean
locale: boolean
tagsView: boolean
tagsViewIcon: boolean
logo: boolean
fixedHeader: boolean
greyMode: boolean
dynamicRouter: boolean
pageLoading: boolean
layout: LayoutType
title: string
userInfo: string
isDark: boolean
currentSize: ElememtPlusSize
sizeMap: ElememtPlusSize[]
mobile: boolean
footer: boolean
theme: ThemeTypes
}
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: false, // 是否只保持一个子菜单的展开
hamburger: true, // 折叠图标
screenfull: true, // 全屏图标
size: true, // 尺寸图标
locale: true, // 多语言图标
tagsView: true, // 标签页
tagsViewIcon: true, // 是否显示标签图标
logo: true, // logo
fixedHeader: true, // 固定toolheader
footer: true, // 显示页脚
greyMode: false, // 是否开始灰色模式,用于特殊悼念日
dynamicRouter: false, // 是否动态路由
layout: 'classic', // layout布局
isDark: false, // 是否是暗黑模式
currentSize: 'default', // 组件尺寸
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'
}
}
}, },
persist: true,
getters: { getters: {
getBreadcrumb(): boolean { getBreadcrumb(): boolean {
return this.breadcrumb return this.breadcrumb
@ -129,7 +224,7 @@ export const useAppStore = defineStore({
this.greyMode = greyMode this.greyMode = greyMode
}, },
setDynamicRouter(dynamicRouter: boolean) { setDynamicRouter(dynamicRouter: boolean) {
wsCache.set('dynamicRouter', dynamicRouter) // wsCache.set('dynamicRouter', dynamicRouter)
this.dynamicRouter = dynamicRouter this.dynamicRouter = dynamicRouter
}, },
setPageLoading(pageLoading: boolean) { setPageLoading(pageLoading: boolean) {
@ -141,7 +236,7 @@ export const useAppStore = defineStore({
return return
} }
this.layout = layout this.layout = layout
wsCache.set('layout', this.layout) // wsCache.set('layout', this.layout)
}, },
setTitle(title: string) { setTitle(title: string) {
this.title = title this.title = title
@ -155,18 +250,18 @@ export const useAppStore = defineStore({
document.documentElement.classList.add('light') document.documentElement.classList.add('light')
document.documentElement.classList.remove('dark') document.documentElement.classList.remove('dark')
} }
wsCache.set('isDark', this.isDark) // wsCache.set('isDark', this.isDark)
}, },
setCurrentSize(currentSize: ElememtPlusSize) { setCurrentSize(currentSize: ElememtPlusSize) {
this.currentSize = currentSize this.currentSize = currentSize
wsCache.set('currentSize', this.currentSize) // wsCache.set('currentSize', this.currentSize)
}, },
setMobile(mobile: boolean) { setMobile(mobile: boolean) {
this.mobile = mobile this.mobile = mobile
}, },
setTheme(theme: ThemeTypes) { setTheme(theme: ThemeTypes) {
this.theme = Object.assign(this.theme, theme) this.theme = Object.assign(this.theme, theme)
wsCache.set('theme', this.theme) // wsCache.set('theme', this.theme)
}, },
setCssVarTheme() { setCssVarTheme() {
for (const key in this.theme) { for (const key in this.theme) {

View File

@ -6,15 +6,12 @@ export interface DictState {
dictObj: Recordable dictObj: Recordable
} }
export const useDictStore = defineStore({ export const useDictStore = defineStore('dict', {
id: 'dict',
state: (): DictState => ({ state: (): DictState => ({
isSetDict: false, isSetDict: false,
dictObj: {} dictObj: {}
}), }),
persist: { persist: true,
enabled: true
},
getters: { getters: {
getDictObj(): Recordable { getDictObj(): Recordable {
return this.dictObj return this.dictObj

View File

@ -1,17 +1,38 @@
import { defineStore } from 'pinia' import { defineStore } from 'pinia'
import { store } from '../index' import { store } from '../index'
import { useCache } from '@/hooks/web/useCache' import zhCn from 'element-plus/es/locale/lang/zh-cn'
import { localeModules, elLocaleMap } from '@/config/locale' import en from 'element-plus/es/locale/lang/en'
import type { LocaleState } from '@/config/locale'
const { wsCache } = useCache() const elLocaleMap = {
'zh-CN': zhCn,
en: en
}
interface LocaleState {
currentLocale: LocaleDropdownType
localeMap: LocaleDropdownType[]
}
export const useLocaleStore = defineStore({ export const useLocaleStore = defineStore('locales', {
id: 'locales', state: (): LocaleState => {
state: (): LocaleState => localeModules, return {
persist: { currentLocale: {
enabled: true lang: 'zh-CN',
elLocale: elLocaleMap['zh-CN']
},
// 多语言
localeMap: [
{
lang: 'zh-CN',
name: '简体中文'
},
{
lang: 'en',
name: 'English'
}
]
}
}, },
persist: true,
getters: { getters: {
getCurrentLocale(): LocaleDropdownType { getCurrentLocale(): LocaleDropdownType {
return this.currentLocale return this.currentLocale
@ -25,7 +46,7 @@ export const useLocaleStore = defineStore({
// this.locale = Object.assign(this.locale, localeMap) // this.locale = Object.assign(this.locale, localeMap)
this.currentLocale.lang = localeMap?.lang this.currentLocale.lang = localeMap?.lang
this.currentLocale.elLocale = elLocaleMap[localeMap?.lang] this.currentLocale.elLocale = elLocaleMap[localeMap?.lang]
wsCache.set('lang', localeMap?.lang) // wsCache.set('lang', localeMap?.lang)
} }
} }
}) })

View File

@ -11,17 +11,14 @@ export interface PermissionState {
menuTabRouters: AppRouteRecordRaw[] menuTabRouters: AppRouteRecordRaw[]
} }
export const usePermissionStore = defineStore({ export const usePermissionStore = defineStore('permission', {
id: 'permission',
state: (): PermissionState => ({ state: (): PermissionState => ({
routers: [], routers: [],
addRouters: [], addRouters: [],
isAddRouters: false, isAddRouters: false,
menuTabRouters: [] menuTabRouters: []
}), }),
persist: { persist: true,
enabled: true
},
getters: { getters: {
getRouters(): AppRouteRecordRaw[] { getRouters(): AppRouteRecordRaw[] {
return this.routers return this.routers

View File

@ -10,8 +10,7 @@ export interface TagsViewState {
cachedViews: Set<string> cachedViews: Set<string>
} }
export const useTagsViewStore = defineStore({ export const useTagsViewStore = defineStore('tagsView', {
id: 'tagsView',
state: (): TagsViewState => ({ state: (): TagsViewState => ({
visitedViews: [], visitedViews: [],
cachedViews: new Set() cachedViews: new Set()