✨ init Project
This commit is contained in:
8
src/pinia/index.js
Normal file
8
src/pinia/index.js
Normal file
@@ -0,0 +1,8 @@
|
||||
import { createPinia } from 'pinia'
|
||||
import { useAppStore } from '@/pinia/modules/app'
|
||||
import { useUserStore } from '@/pinia/modules/user'
|
||||
import { useDictionaryStore } from '@/pinia/modules/dictionary'
|
||||
|
||||
const store = createPinia()
|
||||
|
||||
export { store, useAppStore, useUserStore, useDictionaryStore }
|
133
src/pinia/modules/app.js
Normal file
133
src/pinia/modules/app.js
Normal file
@@ -0,0 +1,133 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import { ref, watchEffect, reactive } from 'vue'
|
||||
import { setBodyPrimaryColor } from '@/utils/format'
|
||||
import { useDark, usePreferredDark } from '@vueuse/core'
|
||||
|
||||
export const useAppStore = defineStore('app', () => {
|
||||
const device = ref('')
|
||||
const drawerSize = ref('')
|
||||
const operateMinWith = ref('240')
|
||||
const config = reactive({
|
||||
weakness: false,
|
||||
grey: false,
|
||||
primaryColor: '#3b82f6',
|
||||
showTabs: true,
|
||||
darkMode: 'auto',
|
||||
layout_side_width: 256,
|
||||
layout_side_collapsed_width: 80,
|
||||
layout_side_item_height: 48,
|
||||
show_watermark: true,
|
||||
side_mode: 'normal',
|
||||
// 页面过渡动画配置
|
||||
transition_type: 'slide'
|
||||
})
|
||||
|
||||
const isDark = useDark({
|
||||
selector: 'html',
|
||||
attribute: 'class',
|
||||
valueDark: 'dark',
|
||||
valueLight: 'light'
|
||||
})
|
||||
|
||||
const preferredDark = usePreferredDark()
|
||||
|
||||
const toggleTheme = (darkMode) => {
|
||||
isDark.value = darkMode
|
||||
}
|
||||
|
||||
const toggleWeakness = (e) => {
|
||||
config.weakness = e
|
||||
}
|
||||
|
||||
const toggleGrey = (e) => {
|
||||
config.grey = e
|
||||
}
|
||||
|
||||
const togglePrimaryColor = (e) => {
|
||||
config.primaryColor = e
|
||||
}
|
||||
|
||||
const toggleTabs = (e) => {
|
||||
config.showTabs = e
|
||||
}
|
||||
|
||||
const toggleDevice = (e) => {
|
||||
if (e === 'mobile') {
|
||||
drawerSize.value = '100%'
|
||||
operateMinWith.value = '80'
|
||||
} else {
|
||||
drawerSize.value = '800'
|
||||
operateMinWith.value = '240'
|
||||
}
|
||||
device.value = e
|
||||
}
|
||||
|
||||
const toggleDarkMode = (e) => {
|
||||
config.darkMode = e
|
||||
}
|
||||
|
||||
// 监听系统主题变化
|
||||
watchEffect(() => {
|
||||
if (config.darkMode === 'auto') {
|
||||
isDark.value = preferredDark.value
|
||||
return
|
||||
}
|
||||
isDark.value = config.darkMode === 'dark'
|
||||
})
|
||||
|
||||
const toggleConfigSideWidth = (e) => {
|
||||
config.layout_side_width = e
|
||||
}
|
||||
|
||||
const toggleConfigSideCollapsedWidth = (e) => {
|
||||
config.layout_side_collapsed_width = e
|
||||
}
|
||||
|
||||
const toggleConfigSideItemHeight = (e) => {
|
||||
config.layout_side_item_height = e
|
||||
}
|
||||
|
||||
const toggleConfigWatermark = (e) => {
|
||||
config.show_watermark = e
|
||||
}
|
||||
|
||||
const toggleSideMode = (e) => {
|
||||
config.side_mode = e
|
||||
}
|
||||
|
||||
const toggleTransition = (e) => {
|
||||
config.transition_type = e
|
||||
}
|
||||
|
||||
// 监听色弱模式和灰色模式
|
||||
watchEffect(() => {
|
||||
document.documentElement.classList.toggle('html-weakenss', config.weakness)
|
||||
document.documentElement.classList.toggle('html-grey', config.grey)
|
||||
})
|
||||
|
||||
// 监听主题色
|
||||
watchEffect(() => {
|
||||
setBodyPrimaryColor(config.primaryColor, isDark.value ? 'dark' : 'light')
|
||||
})
|
||||
|
||||
return {
|
||||
isDark,
|
||||
device,
|
||||
drawerSize,
|
||||
operateMinWith,
|
||||
config,
|
||||
toggleTheme,
|
||||
toggleDevice,
|
||||
toggleWeakness,
|
||||
toggleGrey,
|
||||
togglePrimaryColor,
|
||||
toggleTabs,
|
||||
toggleDarkMode,
|
||||
toggleConfigSideWidth,
|
||||
toggleConfigSideCollapsedWidth,
|
||||
toggleConfigSideItemHeight,
|
||||
toggleConfigWatermark,
|
||||
toggleSideMode,
|
||||
toggleTransition
|
||||
}
|
||||
})
|
41
src/pinia/modules/dictionary.js
Normal file
41
src/pinia/modules/dictionary.js
Normal file
@@ -0,0 +1,41 @@
|
||||
import { findSysDictionary } from '@/api/sysDictionary'
|
||||
|
||||
import { defineStore } from 'pinia'
|
||||
import { ref } from 'vue'
|
||||
|
||||
export const useDictionaryStore = defineStore('dictionary', () => {
|
||||
const dictionaryMap = ref({})
|
||||
|
||||
const setDictionaryMap = (dictionaryRes) => {
|
||||
dictionaryMap.value = { ...dictionaryMap.value, ...dictionaryRes }
|
||||
}
|
||||
|
||||
const getDictionary = async (type) => {
|
||||
if (dictionaryMap.value[type] && dictionaryMap.value[type].length) {
|
||||
return dictionaryMap.value[type]
|
||||
} else {
|
||||
const res = await findSysDictionary({ type })
|
||||
if (res.code === 0) {
|
||||
const dictionaryRes = {}
|
||||
const dict = []
|
||||
res.data.resysDictionary.sysDictionaryDetails &&
|
||||
res.data.resysDictionary.sysDictionaryDetails.forEach((item) => {
|
||||
dict.push({
|
||||
label: item.label,
|
||||
value: item.value,
|
||||
extend: item.extend
|
||||
})
|
||||
})
|
||||
dictionaryRes[res.data.resysDictionary.type] = dict
|
||||
setDictionaryMap(dictionaryRes)
|
||||
return dictionaryMap.value[type]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
dictionaryMap,
|
||||
setDictionaryMap,
|
||||
getDictionary
|
||||
}
|
||||
})
|
31
src/pinia/modules/params.js
Normal file
31
src/pinia/modules/params.js
Normal file
@@ -0,0 +1,31 @@
|
||||
import { getSysParam } from '@/api/sysParams'
|
||||
import { defineStore } from 'pinia'
|
||||
import { ref } from 'vue'
|
||||
|
||||
export const useParamsStore = defineStore('params', () => {
|
||||
const paramsMap = ref({})
|
||||
|
||||
const setParamsMap = (paramsRes) => {
|
||||
paramsMap.value = { ...paramsMap.value, ...paramsRes }
|
||||
}
|
||||
|
||||
const getParams = async(key) => {
|
||||
if (paramsMap.value[key] && paramsMap.value[key].length) {
|
||||
return paramsMap.value[key]
|
||||
} else {
|
||||
const res = await getSysParam({ key })
|
||||
if (res.code === 0) {
|
||||
const paramsRes = {}
|
||||
paramsRes[key] = res.data.value
|
||||
setParamsMap(paramsRes)
|
||||
return paramsMap.value[key]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
paramsMap,
|
||||
setParamsMap,
|
||||
getParams
|
||||
}
|
||||
})
|
144
src/pinia/modules/router.js
Normal file
144
src/pinia/modules/router.js
Normal file
@@ -0,0 +1,144 @@
|
||||
import { asyncRouterHandle } from '@/utils/asyncRouter'
|
||||
import { emitter } from '@/utils/bus.js'
|
||||
import { asyncMenu } from '@/api/menu'
|
||||
import { defineStore } from 'pinia'
|
||||
import { ref, watchEffect } from 'vue'
|
||||
import pathInfo from '@/pathInfo.json'
|
||||
|
||||
const notLayoutRouterArr = []
|
||||
const keepAliveRoutersArr = []
|
||||
const nameMap = {}
|
||||
|
||||
const formatRouter = (routes, routeMap, parent) => {
|
||||
routes &&
|
||||
routes.forEach((item) => {
|
||||
item.parent = parent
|
||||
item.meta.btns = item.btns
|
||||
item.meta.hidden = item.hidden
|
||||
if (item.meta.defaultMenu === true) {
|
||||
if (!parent) {
|
||||
item = { ...item, path: `/${item.path}` }
|
||||
notLayoutRouterArr.push(item)
|
||||
}
|
||||
}
|
||||
routeMap[item.name] = item
|
||||
if (item.children && item.children.length > 0) {
|
||||
formatRouter(item.children, routeMap, item)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const KeepAliveFilter = (routes) => {
|
||||
routes &&
|
||||
routes.forEach((item) => {
|
||||
// 子菜单中有 keep-alive 的,父菜单也必须 keep-alive,否则无效。这里将子菜单中有 keep-alive 的父菜单也加入。
|
||||
if (
|
||||
(item.children && item.children.some((ch) => ch.meta.keepAlive)) ||
|
||||
item.meta.keepAlive
|
||||
) {
|
||||
const path = item.meta.path
|
||||
keepAliveRoutersArr.push(pathInfo[path])
|
||||
nameMap[item.name] = pathInfo[path]
|
||||
}
|
||||
if (item.children && item.children.length > 0) {
|
||||
KeepAliveFilter(item.children)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export const useRouterStore = defineStore('router', () => {
|
||||
const keepAliveRouters = ref([])
|
||||
const asyncRouterFlag = ref(0)
|
||||
const setKeepAliveRouters = (history) => {
|
||||
const keepArrTemp = []
|
||||
history.forEach((item) => {
|
||||
if (nameMap[item.name]) {
|
||||
keepArrTemp.push(nameMap[item.name])
|
||||
}
|
||||
})
|
||||
keepAliveRouters.value = Array.from(new Set(keepArrTemp))
|
||||
}
|
||||
emitter.on('setKeepAlive', setKeepAliveRouters)
|
||||
|
||||
const asyncRouters = ref([])
|
||||
|
||||
const topMenu = ref([])
|
||||
|
||||
const leftMenu = ref([])
|
||||
|
||||
const menuMap = {}
|
||||
|
||||
const topActive = ref('')
|
||||
|
||||
const setLeftMenu = (name) => {
|
||||
sessionStorage.setItem('topActive', name)
|
||||
topActive.value = name
|
||||
leftMenu.value = []
|
||||
if (menuMap[name]?.children) {
|
||||
leftMenu.value = menuMap[name].children
|
||||
}
|
||||
return menuMap[name]?.children
|
||||
}
|
||||
|
||||
watchEffect(() => {
|
||||
let topActive = sessionStorage.getItem('topActive')
|
||||
asyncRouters.value[0]?.children.forEach((item) => {
|
||||
if (item.hidden) return
|
||||
menuMap[item.name] = item
|
||||
topMenu.value.push({ ...item, children: [] })
|
||||
})
|
||||
|
||||
setLeftMenu(topActive)
|
||||
})
|
||||
|
||||
const routeMap = {}
|
||||
// 从后台获取动态路由
|
||||
const SetAsyncRouter = async () => {
|
||||
asyncRouterFlag.value++
|
||||
const baseRouter = [
|
||||
{
|
||||
path: '/layout',
|
||||
name: 'layout',
|
||||
component: 'view/layout/index.vue',
|
||||
meta: {
|
||||
title: '底层layout'
|
||||
},
|
||||
children: []
|
||||
}
|
||||
]
|
||||
const asyncRouterRes = await asyncMenu()
|
||||
const asyncRouter = asyncRouterRes.data.menus
|
||||
asyncRouter &&
|
||||
asyncRouter.push({
|
||||
path: 'reload',
|
||||
name: 'Reload',
|
||||
hidden: true,
|
||||
meta: {
|
||||
title: '',
|
||||
closeTab: true
|
||||
},
|
||||
component: 'view/error/reload.vue'
|
||||
})
|
||||
formatRouter(asyncRouter, routeMap)
|
||||
baseRouter[0].children = asyncRouter
|
||||
if (notLayoutRouterArr.length !== 0) {
|
||||
baseRouter.push(...notLayoutRouterArr)
|
||||
}
|
||||
asyncRouterHandle(baseRouter)
|
||||
KeepAliveFilter(asyncRouter)
|
||||
asyncRouters.value = baseRouter
|
||||
return true
|
||||
}
|
||||
|
||||
return {
|
||||
topActive,
|
||||
setLeftMenu,
|
||||
topMenu,
|
||||
leftMenu,
|
||||
asyncRouters,
|
||||
keepAliveRouters,
|
||||
asyncRouterFlag,
|
||||
SetAsyncRouter,
|
||||
routeMap
|
||||
}
|
||||
})
|
144
src/pinia/modules/user.js
Normal file
144
src/pinia/modules/user.js
Normal file
@@ -0,0 +1,144 @@
|
||||
import { login, getUserInfo } from '@/api/user'
|
||||
import { jsonInBlacklist } from '@/api/jwt'
|
||||
import router from '@/router/index'
|
||||
import { ElLoading, ElMessage } from 'element-plus'
|
||||
import { defineStore } from 'pinia'
|
||||
import { ref, computed } from 'vue'
|
||||
import { useRouterStore } from './router'
|
||||
import { useCookies } from '@vueuse/integrations/useCookies'
|
||||
import { useStorage } from '@vueuse/core'
|
||||
|
||||
import { useAppStore } from '@/pinia'
|
||||
|
||||
export const useUserStore = defineStore('user', () => {
|
||||
const appStore = useAppStore()
|
||||
const loadingInstance = ref(null)
|
||||
|
||||
const userInfo = ref({
|
||||
uuid: '',
|
||||
nickName: '',
|
||||
headerImg: '',
|
||||
authority: {}
|
||||
})
|
||||
const token = useStorage('token', '')
|
||||
const xToken = useCookies('x-token')
|
||||
const currentToken = computed(() => token.value || xToken.value || '')
|
||||
|
||||
const setUserInfo = (val) => {
|
||||
userInfo.value = val
|
||||
if (val.originSetting) {
|
||||
Object.keys(appStore.config).forEach((key) => {
|
||||
if (val.originSetting[key] !== undefined) {
|
||||
appStore.config[key] = val.originSetting[key]
|
||||
}
|
||||
})
|
||||
}
|
||||
console.log(appStore.config)
|
||||
}
|
||||
|
||||
const setToken = (val) => {
|
||||
token.value = val
|
||||
xToken.value = val
|
||||
}
|
||||
|
||||
const NeedInit = async () => {
|
||||
await ClearStorage()
|
||||
await router.push({ name: 'Init', replace: true })
|
||||
}
|
||||
|
||||
const ResetUserInfo = (value = {}) => {
|
||||
userInfo.value = {
|
||||
...userInfo.value,
|
||||
...value
|
||||
}
|
||||
}
|
||||
/* 获取用户信息*/
|
||||
const GetUserInfo = async () => {
|
||||
const res = await getUserInfo()
|
||||
if (res.code === 0) {
|
||||
setUserInfo(res.data.userInfo)
|
||||
}
|
||||
return res
|
||||
}
|
||||
/* 登录*/
|
||||
const LoginIn = async (loginInfo) => {
|
||||
try {
|
||||
loadingInstance.value = ElLoading.service({
|
||||
fullscreen: true,
|
||||
text: '登录中,请稍候...'
|
||||
})
|
||||
|
||||
const res = await login(loginInfo)
|
||||
|
||||
if (res.code !== 0) {
|
||||
ElMessage.error(res.message || '登录失败')
|
||||
return false
|
||||
}
|
||||
// 登陆成功,设置用户信息和权限相关信息
|
||||
setUserInfo(res.data.user)
|
||||
setToken(res.data.token)
|
||||
|
||||
// 初始化路由信息
|
||||
const routerStore = useRouterStore()
|
||||
await routerStore.SetAsyncRouter()
|
||||
const asyncRouters = routerStore.asyncRouters
|
||||
|
||||
// 注册到路由表里
|
||||
asyncRouters.forEach((asyncRouter) => {
|
||||
router.addRoute(asyncRouter)
|
||||
})
|
||||
|
||||
if (!router.hasRoute(userInfo.value.authority.defaultRouter)) {
|
||||
ElMessage.error('请联系管理员进行授权')
|
||||
} else {
|
||||
await router.replace({ name: userInfo.value.authority.defaultRouter })
|
||||
}
|
||||
|
||||
const isWindows = /windows/i.test(navigator.userAgent)
|
||||
window.localStorage.setItem('osType', isWindows ? 'WIN' : 'MAC')
|
||||
|
||||
// 全部操作均结束,关闭loading并返回
|
||||
return true
|
||||
} catch (error) {
|
||||
console.error('LoginIn error:', error)
|
||||
return false
|
||||
} finally {
|
||||
loadingInstance.value?.close()
|
||||
}
|
||||
}
|
||||
/* 登出*/
|
||||
const LoginOut = async () => {
|
||||
const res = await jsonInBlacklist()
|
||||
|
||||
// 登出失败
|
||||
if (res.code !== 0) {
|
||||
return
|
||||
}
|
||||
|
||||
await ClearStorage()
|
||||
|
||||
// 把路由定向到登录页,无需等待直接reload
|
||||
router.push({ name: 'Login', replace: true })
|
||||
window.location.reload()
|
||||
}
|
||||
/* 清理数据 */
|
||||
const ClearStorage = async () => {
|
||||
token.value = ''
|
||||
xToken.value = ''
|
||||
sessionStorage.clear()
|
||||
localStorage.removeItem('originSetting')
|
||||
}
|
||||
|
||||
return {
|
||||
userInfo,
|
||||
token: currentToken,
|
||||
NeedInit,
|
||||
ResetUserInfo,
|
||||
GetUserInfo,
|
||||
LoginIn,
|
||||
LoginOut,
|
||||
setToken,
|
||||
loadingInstance,
|
||||
ClearStorage
|
||||
}
|
||||
})
|
Reference in New Issue
Block a user