浏览代码

feat: 新增useStorage

kailong321200875 1 年之前
父节点
当前提交
dfea91c7e1

+ 1 - 1
package.json

@@ -7,7 +7,7 @@
   "scripts": {
     "i": "pnpm install",
     "dev": "vite --mode base",
-    "ts:check": "vue-tsc --noEmit",
+    "ts:check": "vue-tsc --noEmit --skipLibCheck",
     "build:pro": "vite build --mode pro",
     "build:gitee": "vite build --mode gitee",
     "build:dev": "vite build --mode dev",

+ 4 - 4
src/App.vue

@@ -4,7 +4,7 @@ import { useAppStore } from '@/store/modules/app'
 import { ConfigGlobal } from '@/components/ConfigGlobal'
 import { isDark } from '@/utils/is'
 import { useDesign } from '@/hooks/web/useDesign'
-import { useCache } from '@/hooks/web/useCache'
+import { useStorage } from '@/hooks/web/useStorage'
 
 const { getPrefixCls } = useDesign()
 
@@ -16,12 +16,12 @@ const currentSize = computed(() => appStore.getCurrentSize)
 
 const greyMode = computed(() => appStore.getGreyMode)
 
-const { wsCache } = useCache()
+const { getStorage } = useStorage()
 
 // 根据浏览器当前主题设置系统主题色
 const setDefaultTheme = () => {
-  if (wsCache.get('isDark') !== null) {
-    appStore.setIsDark(wsCache.get('isDark'))
+  if (getStorage('isDark') !== null) {
+    appStore.setIsDark(getStorage('isDark'))
     return
   }
   const isDarkTheme = isDark()

+ 6 - 5
src/components/Setting/src/Setting.vue

@@ -10,10 +10,12 @@ import { trim, setCssVar } from '@/utils'
 import ColorRadioPicker from './components/ColorRadioPicker.vue'
 import InterfaceDisplay from './components/InterfaceDisplay.vue'
 import LayoutRadioPicker from './components/LayoutRadioPicker.vue'
-import { useCache } from '@/hooks/web/useCache'
+import { useStorage } from '@/hooks/web/useStorage'
 import { useClipboard } from '@vueuse/core'
 import { useDesign } from '@/hooks/web/useDesign'
 
+const { removeStorage } = useStorage()
+
 const { getPrefixCls } = useDesign()
 
 const prefixCls = getPrefixCls('setting')
@@ -186,10 +188,9 @@ const copyConfig = async () => {
 
 // 清空缓存
 const clear = () => {
-  const { wsCache } = useCache()
-  wsCache.delete('layout')
-  wsCache.delete('theme')
-  wsCache.delete('isDark')
+  removeStorage('layout')
+  removeStorage('theme')
+  removeStorage('isDark')
   window.location.reload()
 }
 </script>

+ 3 - 3
src/components/UserInfo/src/UserInfo.vue

@@ -1,7 +1,7 @@
 <script setup lang="ts">
 import { ElDropdown, ElDropdownMenu, ElDropdownItem, ElMessageBox } from 'element-plus'
 import { useI18n } from '@/hooks/web/useI18n'
-import { useCache } from '@/hooks/web/useCache'
+import { useStorage } from '@/hooks/web/useStorage'
 import { resetRouter } from '@/router'
 import { useRouter } from 'vue-router'
 import { loginOutApi } from '@/api/login'
@@ -24,7 +24,7 @@ const prefixCls = getPrefixCls('user-info')
 
 const { t } = useI18n()
 
-const { wsCache } = useCache()
+const { clear } = useStorage()
 
 const { replace } = useRouter()
 
@@ -37,7 +37,7 @@ const loginOut = () => {
     .then(async () => {
       const res = await loginOutApi().catch(() => {})
       if (res) {
-        wsCache.clear()
+        clear()
         tagsViewStore.delAllViews()
         resetRouter() // 重置静态路由表
         replace('/login')

+ 3 - 3
src/components/UserInfo/src/components/LockPage.vue

@@ -3,7 +3,7 @@ import { ref } from 'vue'
 import { ElInput, ElButton } from 'element-plus'
 import { resetRouter } from '@/router'
 import { useRouter } from 'vue-router'
-import { useCache } from '@/hooks/web/useCache'
+import { useStorage } from '@/hooks/web/useStorage'
 import { useLockStore } from '@/store/modules/lock'
 import { useI18n } from '@/hooks/web/useI18n'
 import { useNow } from '@/hooks/web/useNow'
@@ -14,7 +14,7 @@ import { useTagsViewStore } from '@/store/modules/tagsView'
 
 const tagsViewStore = useTagsViewStore()
 
-const { wsCache } = useCache()
+const { clear } = useStorage()
 
 const { replace } = useRouter()
 
@@ -51,7 +51,7 @@ async function unLock() {
 async function goLogin() {
   const res = await loginOutApi().catch(() => {})
   if (res) {
-    wsCache.clear()
+    clear()
     tagsViewStore.delAllViews()
     resetRouter() // 重置静态路由表
     lockStore.resetLockInfo()

+ 3 - 3
src/directives/permission/hasPermi.ts

@@ -1,18 +1,18 @@
 import type { App, Directive, DirectiveBinding } from 'vue'
 import { useI18n } from '@/hooks/web/useI18n'
-import { useCache } from '@/hooks/web/useCache'
+import { useStorage } from '@/hooks/web/useStorage'
 import { intersection } from 'lodash-es'
 import { isArray } from '@/utils/is'
 import { useAppStoreWithOut } from '@/store/modules/app'
 
 const { t } = useI18n()
-const { wsCache } = useCache()
+const { getStorage } = useStorage()
 const appStore = useAppStoreWithOut()
 
 // 全部权限
 const all_permission = ['*.*.*']
 const hasPermission = (value: string | string[]): boolean => {
-  const permissions = wsCache.get(appStore.getUserInfo).permissions as string[]
+  const permissions = getStorage(appStore.getUserInfo).permissions as string[]
   if (!value) {
     throw new Error(t('permission.hasPermission'))
   }

+ 0 - 0
src/hooks/web/useEmitt.ts → src/hooks/event/useEmitt.ts


+ 0 - 17
src/hooks/web/useCache.ts

@@ -1,17 +0,0 @@
-/**
- * 配置浏览器本地存储的方式,可直接存储对象数组。
- */
-
-import WebStorageCache from 'web-storage-cache'
-
-type CacheType = 'sessionStorage' | 'localStorage'
-
-export const useCache = (type: CacheType = 'sessionStorage') => {
-  const wsCache: WebStorageCache = new WebStorageCache({
-    storage: type
-  })
-
-  return {
-    wsCache
-  }
-}

+ 31 - 0
src/hooks/web/useStorage.ts

@@ -0,0 +1,31 @@
+import { isArray, isObject } from '@/utils/is'
+
+export const useStorage = (type: 'sessionStorage' | 'localStorage' = 'sessionStorage') => {
+  const setStorage = (key: string, value: any) => {
+    window[type].setItem(key, isArray(value) || isObject(value) ? JSON.stringify(value) : value)
+  }
+
+  const getStorage = (key: string) => {
+    const value = window[type].getItem(key)
+    try {
+      return JSON.parse(value || '')
+    } catch (error) {
+      return value
+    }
+  }
+
+  const removeStorage = (key: string) => {
+    window[type].removeItem(key)
+  }
+
+  const clear = () => {
+    window[type].clear()
+  }
+
+  return {
+    setStorage,
+    getStorage,
+    removeStorage,
+    clear
+  }
+}

+ 5 - 5
src/permission.ts

@@ -1,6 +1,6 @@
 import router from './router'
 import { useAppStoreWithOut } from '@/store/modules/app'
-import { useCache } from '@/hooks/web/useCache'
+import { useStorage } from '@/hooks/web/useStorage'
 import type { RouteRecordRaw } from 'vue-router'
 import { useTitle } from '@/hooks/web/useTitle'
 import { useNProgress } from '@/hooks/web/useNProgress'
@@ -15,7 +15,7 @@ const appStore = useAppStoreWithOut()
 
 const dictStore = useDictStoreWithOut()
 
-const { wsCache } = useCache()
+const { getStorage } = useStorage()
 
 const { start, done } = useNProgress()
 
@@ -26,7 +26,7 @@ const whiteList = ['/login'] // 不重定向白名单
 router.beforeEach(async (to, from, next) => {
   start()
   loadStart()
-  if (wsCache.get(appStore.getUserInfo)) {
+  if (getStorage(appStore.getUserInfo)) {
     if (to.path === '/login') {
       next({ path: '/' })
     } else {
@@ -44,8 +44,8 @@ router.beforeEach(async (to, from, next) => {
       }
 
       // 开发者可根据实际情况进行修改
-      const roleRouters = wsCache.get('roleRouters') || []
-      const userInfo = wsCache.get(appStore.getUserInfo)
+      const roleRouters = getStorage('roleRouters') || []
+      const userInfo = getStorage(appStore.getUserInfo)
 
       // 是否使用动态路由
       if (appStore.getDynamicRouter) {

+ 14 - 14
src/store/modules/app.ts

@@ -2,9 +2,9 @@ import { defineStore } from 'pinia'
 import { store } from '../index'
 import { setCssVar, humpToUnderline } from '@/utils'
 import { ElMessage, ComponentSize } from 'element-plus'
-import { useCache } from '@/hooks/web/useCache'
+import { useStorage } from '@/hooks/web/useStorage'
 
-const { wsCache } = useCache()
+const { getStorage, setStorage } = useStorage()
 
 interface AppState {
   breadcrumb: boolean
@@ -57,13 +57,13 @@ export const useAppStore = defineStore('app', {
       fixedHeader: true, // 固定toolheader
       footer: true, // 显示页脚
       greyMode: false, // 是否开始灰色模式,用于特殊悼念日
-      dynamicRouter: wsCache.get('dynamicRouter') || false, // 是否动态路由
-      fixedMenu: wsCache.get('fixedMenu') || false, // 是否固定菜单
+      dynamicRouter: getStorage('dynamicRouter') || false, // 是否动态路由
+      fixedMenu: getStorage('fixedMenu') || false, // 是否固定菜单
 
-      layout: wsCache.get('layout') || 'classic', // layout布局
-      isDark: wsCache.get('isDark') || false, // 是否是暗黑模式
-      currentSize: wsCache.get('default') || 'default', // 组件尺寸
-      theme: wsCache.get('theme') || {
+      layout: getStorage('layout') || 'classic', // layout布局
+      isDark: getStorage('isDark') || false, // 是否是暗黑模式
+      currentSize: getStorage('default') || 'default', // 组件尺寸
+      theme: getStorage('theme') || {
         // 主题色
         elColorPrimary: '#409eff',
         // 左侧菜单边框颜色
@@ -213,11 +213,11 @@ export const useAppStore = defineStore('app', {
       this.greyMode = greyMode
     },
     setDynamicRouter(dynamicRouter: boolean) {
-      wsCache.set('dynamicRouter', dynamicRouter)
+      setStorage('dynamicRouter', dynamicRouter)
       this.dynamicRouter = dynamicRouter
     },
     setFixedMenu(fixedMenu: boolean) {
-      wsCache.set('fixedMenu', fixedMenu)
+      setStorage('fixedMenu', fixedMenu)
       this.fixedMenu = fixedMenu
     },
     setPageLoading(pageLoading: boolean) {
@@ -229,7 +229,7 @@ export const useAppStore = defineStore('app', {
         return
       }
       this.layout = layout
-      wsCache.set('layout', this.layout)
+      setStorage('layout', this.layout)
     },
     setTitle(title: string) {
       this.title = title
@@ -243,18 +243,18 @@ export const useAppStore = defineStore('app', {
         document.documentElement.classList.add('light')
         document.documentElement.classList.remove('dark')
       }
-      wsCache.set('isDark', this.isDark)
+      setStorage('isDark', this.isDark)
     },
     setCurrentSize(currentSize: ComponentSize) {
       this.currentSize = currentSize
-      wsCache.set('currentSize', this.currentSize)
+      setStorage('currentSize', this.currentSize)
     },
     setMobile(mobile: boolean) {
       this.mobile = mobile
     },
     setTheme(theme: ThemeTypes) {
       this.theme = Object.assign(this.theme, theme)
-      wsCache.set('theme', this.theme)
+      setStorage('theme', this.theme)
     },
     setCssVarTheme() {
       for (const key in this.theme) {

+ 5 - 5
src/store/modules/locale.ts

@@ -2,10 +2,10 @@ 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 { useCache } from '@/hooks/web/useCache'
+import { useStorage } from '@/hooks/web/useStorage'
 import { LocaleDropdownType } from '@/components/LocaleDropdown'
 
-const { wsCache } = useCache()
+const { getStorage, setStorage } = useStorage()
 
 const elLocaleMap = {
   'zh-CN': zhCn,
@@ -20,8 +20,8 @@ export const useLocaleStore = defineStore('locales', {
   state: (): LocaleState => {
     return {
       currentLocale: {
-        lang: wsCache.get('lang') || 'zh-CN',
-        elLocale: elLocaleMap[wsCache.get('lang') || 'zh-CN']
+        lang: getStorage('lang') || 'zh-CN',
+        elLocale: elLocaleMap[getStorage('lang') || 'zh-CN']
       },
       // 多语言
       localeMap: [
@@ -49,7 +49,7 @@ export const useLocaleStore = defineStore('locales', {
       // this.locale = Object.assign(this.locale, localeMap)
       this.currentLocale.lang = localeMap?.lang
       this.currentLocale.elLocale = elLocaleMap[localeMap?.lang]
-      wsCache.set('lang', localeMap?.lang)
+      setStorage('lang', localeMap?.lang)
     }
   }
 })

+ 2 - 1
src/views/Example/Page/ExampleAdd.vue

@@ -6,7 +6,7 @@ import { ElButton } from 'element-plus'
 import { useI18n } from '@/hooks/web/useI18n'
 import { useRouter } from 'vue-router'
 import { saveTableApi } from '@/api/table'
-import { useEmitt } from '@/hooks/web/useEmitt'
+import { useEmitt } from '@/hooks/event/useEmitt'
 
 const { emitter } = useEmitt()
 
@@ -50,3 +50,4 @@ const save = async () => {
     </template>
   </ContentDetailWrap>
 </template>
+@/hooks/event/useEmitt

+ 2 - 1
src/views/Example/Page/ExampleEdit.vue

@@ -7,7 +7,7 @@ import { useI18n } from '@/hooks/web/useI18n'
 import { useRouter, useRoute } from 'vue-router'
 import { saveTableApi, getTableDetApi } from '@/api/table'
 import { TableData } from '@/api/table/types'
-import { useEmitt } from '@/hooks/web/useEmitt'
+import { useEmitt } from '@/hooks/event/useEmitt'
 
 const { emitter } = useEmitt()
 
@@ -64,3 +64,4 @@ const save = async () => {
     </template>
   </ContentDetailWrap>
 </template>
+@/hooks/event/useEmitt

+ 2 - 1
src/views/Example/Page/ExamplePage.vue

@@ -9,7 +9,7 @@ import { useTable } from '@/hooks/web/useTable'
 import { TableData } from '@/api/table/types'
 import { h, reactive, ref, unref } from 'vue'
 import { useRouter } from 'vue-router'
-import { useEmitt } from '@/hooks/web/useEmitt'
+import { useEmitt } from '@/hooks/event/useEmitt'
 import { CrudSchema, useCrudSchemas } from '@/hooks/web/useCrudSchemas'
 
 defineOptions({
@@ -265,3 +265,4 @@ const action = (row: TableData, type: string) => {
     />
   </ContentWrap>
 </template>
+@/hooks/event/useEmitt

+ 4 - 5
src/views/Login/components/LoginForm.vue

@@ -5,7 +5,7 @@ import { useI18n } from '@/hooks/web/useI18n'
 import { ElButton, ElCheckbox, ElLink } from 'element-plus'
 import { useForm } from '@/hooks/web/useForm'
 import { loginApi, getTestRoleApi, getAdminRoleApi } from '@/api/login'
-import { useCache } from '@/hooks/web/useCache'
+import { useStorage } from '@/hooks/web/useStorage'
 import { useAppStore } from '@/store/modules/app'
 import { usePermissionStore } from '@/store/modules/permission'
 import { useRouter } from 'vue-router'
@@ -24,7 +24,7 @@ const permissionStore = usePermissionStore()
 
 const { currentRoute, addRoute, push } = useRouter()
 
-const { wsCache } = useCache()
+const { setStorage } = useStorage()
 
 const { t } = useI18n()
 
@@ -222,7 +222,7 @@ const signIn = async () => {
         const res = await loginApi(formData)
 
         if (res) {
-          wsCache.set(appStore.getUserInfo, res.data)
+          setStorage(appStore.getUserInfo, res.data)
           // 是否使用动态路由
           if (appStore.getDynamicRouter) {
             getRole()
@@ -253,9 +253,8 @@ const getRole = async () => {
   const res =
     formData.username === 'admin' ? await getAdminRoleApi(params) : await getTestRoleApi(params)
   if (res) {
-    const { wsCache } = useCache()
     const routers = res.data || []
-    wsCache.set('roleRouters', routers)
+    setStorage('roleRouters', routers)
 
     formData.username === 'admin'
       ? await permissionStore.generateRoutes('admin', routers).catch(() => {})

+ 1 - 0
stylelint.config.js

@@ -16,6 +16,7 @@ module.exports = {
         ignoreAtRules: ['function', 'if', 'each', 'include', 'mixin']
       }
     ],
+    'media-query-no-invalid': null,
     'no-empty-source': null,
     'named-grid-areas-no-invalid': null,
     'unicode-bom': 'never',