mirror of
https://github.com/zclzone/vue-naive-admin.git
synced 2025-12-28 12:10:20 +08:00
Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
100b91a118 | ||
|
|
26b71f0ec6 | ||
|
|
92e7ada37b | ||
|
|
2d879d0592 | ||
|
|
8806a6cb43 | ||
|
|
85a04fd06d | ||
|
|
4a5b8dd005 | ||
|
|
2f7da255e5 | ||
|
|
6664ae8f7b |
@@ -11,7 +11,27 @@
|
|||||||
"primaryColor": "#316C72FF",
|
"primaryColor": "#316C72FF",
|
||||||
"primaryColorHover": "#316C72E3",
|
"primaryColorHover": "#316C72E3",
|
||||||
"primaryColorPressed": "#2B4C59FF",
|
"primaryColorPressed": "#2B4C59FF",
|
||||||
"primaryColorSuppl": "#316C7263"
|
"primaryColorSuppl": "#316C72E3",
|
||||||
|
|
||||||
|
"infoColor": "#2080F0FF",
|
||||||
|
"infoColorHover": "#4098FCFF",
|
||||||
|
"infoColorPressed": "#1060C9FF",
|
||||||
|
"infoColorSuppl": "#4098FCFF",
|
||||||
|
|
||||||
|
"successColor": "#18A058FF",
|
||||||
|
"successColorHover": "#36AD6AFF",
|
||||||
|
"successColorPressed": "#0C7A43FF",
|
||||||
|
"successColorSuppl": "#36AD6AFF",
|
||||||
|
|
||||||
|
"warningColor": "#F0A020FF",
|
||||||
|
"warningColorHover": "#FCB040FF",
|
||||||
|
"warningColorPressed": "#C97C10FF",
|
||||||
|
"warningColorSuppl": "#FCB040FF",
|
||||||
|
|
||||||
|
"errorColor": "#D03050FF",
|
||||||
|
"errorColorHover": "#DE576DFF",
|
||||||
|
"errorColorPressed": "#AB1F3FFF",
|
||||||
|
"errorColorSuppl": "#DE576DFF"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import request from '@/utils/http'
|
import { request } from '@/utils'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
getUser: () => request.get('/user'),
|
getUser: () => request.get('/user'),
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import { defineComponent, h } from 'vue'
|
|||||||
import { useLoadingBar, useDialog, useMessage, useNotification } from 'naive-ui'
|
import { useLoadingBar, useDialog, useMessage, useNotification } from 'naive-ui'
|
||||||
import { useCssVar } from '@vueuse/core'
|
import { useCssVar } from '@vueuse/core'
|
||||||
import { kebabCase } from 'lodash-es'
|
import { kebabCase } from 'lodash-es'
|
||||||
import { setupMessage, setupDialog } from '@/utils/common/naiveTools'
|
import { setupMessage, setupDialog } from '@/utils'
|
||||||
import { naiveThemeOverrides } from '~/settings'
|
import { naiveThemeOverrides } from '~/settings'
|
||||||
|
|
||||||
function setupCssVar() {
|
function setupCssVar() {
|
||||||
|
|||||||
@@ -38,16 +38,16 @@ const wrapper = ref(null)
|
|||||||
const isOverflow = ref(false)
|
const isOverflow = ref(false)
|
||||||
|
|
||||||
const refreshIsOverflow = debounce(() => {
|
const refreshIsOverflow = debounce(() => {
|
||||||
const wrapperWidth = wrapper.value.offsetWidth
|
const wrapperWidth = wrapper.value?.offsetWidth
|
||||||
const contentWidth = content.value.offsetWidth
|
const contentWidth = content.value?.offsetWidth
|
||||||
isOverflow.value = contentWidth > wrapperWidth
|
isOverflow.value = contentWidth > wrapperWidth
|
||||||
resetTranslateX(wrapperWidth, contentWidth)
|
resetTranslateX(wrapperWidth, contentWidth)
|
||||||
}, 200)
|
}, 200)
|
||||||
|
|
||||||
function handleMouseWheel(e) {
|
function handleMouseWheel(e) {
|
||||||
const { wheelDelta } = e
|
const { wheelDelta } = e
|
||||||
const wrapperWidth = wrapper.value.offsetWidth
|
const wrapperWidth = wrapper.value?.offsetWidth
|
||||||
const contentWidth = content.value.offsetWidth
|
const contentWidth = content.value?.offsetWidth
|
||||||
/**
|
/**
|
||||||
* @wheelDelta 平行滚动的值 >0: 右移 <0: 左移
|
* @wheelDelta 平行滚动的值 >0: 右移 <0: 左移
|
||||||
* @translateX 内容translateX的值
|
* @translateX 内容translateX的值
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { renderIcon, renderCustomIcon } from '@/utils/icon'
|
import { renderIcon, renderCustomIcon } from '@/utils'
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
icon: {
|
icon: {
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { isNullOrWhitespace } from '@/utils/is'
|
import { isNullOrWhitespace } from '@/utils'
|
||||||
|
|
||||||
defineProps({
|
defineProps({
|
||||||
label: {
|
label: {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { isNullOrWhitespace } from '@/utils/is'
|
import { isNullOrWhitespace } from '@/utils'
|
||||||
|
|
||||||
const ACTIONS = {
|
const ACTIONS = {
|
||||||
view: '查看',
|
view: '查看',
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
<template>
|
<template>
|
||||||
<router-view v-slot="{ Component, route }">
|
<router-view v-slot="{ Component, route }">
|
||||||
<KeepAlive :include="keepAliveRouteNames">
|
<KeepAlive :include="keepAliveRouteNames">
|
||||||
<component :is="Component" v-if="appStore.reloadFlag" :key="route.meta?.key || route.fullPath" />
|
<component :is="Component" v-if="appStore.reloadFlag" :key="appStore.aliveKeys[route.name] || route.fullPath" />
|
||||||
</KeepAlive>
|
</KeepAlive>
|
||||||
</router-view>
|
</router-view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { useAppStore } from '@/store/modules/app'
|
import { useAppStore } from '@/store'
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
const appStore = useAppStore()
|
const appStore = useAppStore()
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { renderCustomIcon, renderIcon } from '@/utils/icon'
|
import { renderCustomIcon, renderIcon } from '@/utils'
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { useAppStore } from '@/store/modules/app'
|
import { useAppStore } from '@/store'
|
||||||
|
|
||||||
const appStore = useAppStore()
|
const appStore = useAppStore()
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -8,8 +8,8 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { useUserStore } from '@/store/modules/user'
|
import { useUserStore } from '@/store'
|
||||||
import { renderIcon } from '@/utils/icon'
|
import { renderIcon } from '@/utils'
|
||||||
|
|
||||||
const userStore = useUserStore()
|
const userStore = useUserStore()
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { useAppStore } from '@/store/modules/app'
|
import { useAppStore } from '@/store'
|
||||||
const title = import.meta.env.VITE_TITLE
|
const title = import.meta.env.VITE_TITLE
|
||||||
|
|
||||||
const appStore = useAppStore()
|
const appStore = useAppStore()
|
||||||
|
|||||||
@@ -12,11 +12,8 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { usePermissionStore } from '@/store/modules/permission'
|
import { usePermissionStore, useAppStore } from '@/store'
|
||||||
|
import { renderCustomIcon, renderIcon, isExternal } from '@/utils'
|
||||||
import { isExternal } from '@/utils/is'
|
|
||||||
import { useAppStore } from '@/store/modules/app'
|
|
||||||
import { renderCustomIcon, renderIcon } from '@/utils/icon'
|
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const curRoute = useRoute()
|
const curRoute = useRoute()
|
||||||
|
|||||||
@@ -11,9 +11,9 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { useTagsStore } from '@/store/modules/tags'
|
import { useTagsStore, useAppStore } from '@/store'
|
||||||
import { renderIcon } from '@/utils/icon'
|
import { renderIcon } from '@/utils'
|
||||||
import { useAppStore } from '@/store/modules/app'
|
import { useLocalStorage } from '@vueuse/core'
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
show: {
|
show: {
|
||||||
@@ -79,7 +79,7 @@ const actionMap = new Map([
|
|||||||
() => {
|
() => {
|
||||||
if (route.meta?.keepAlive) {
|
if (route.meta?.keepAlive) {
|
||||||
// 重置keepAlive
|
// 重置keepAlive
|
||||||
route.meta.key = +new Date()
|
appStore.setAliveKeys(route.name, +new Date())
|
||||||
}
|
}
|
||||||
appStore.reloadPage()
|
appStore.reloadPage()
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import ContextMenu from './ContextMenu.vue'
|
import ContextMenu from './ContextMenu.vue'
|
||||||
import { useTagsStore } from '@/store/modules/tags'
|
import { useTagsStore } from '@/store'
|
||||||
import ScrollX from '@/components/common/ScrollX.vue'
|
import ScrollX from '@/components/common/ScrollX.vue'
|
||||||
|
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ import AppHeader from './components/header/index.vue'
|
|||||||
import SideBar from './components/sidebar/index.vue'
|
import SideBar from './components/sidebar/index.vue'
|
||||||
import AppMain from './components/AppMain.vue'
|
import AppMain from './components/AppMain.vue'
|
||||||
import AppTags from './components/tags/index.vue'
|
import AppTags from './components/tags/index.vue'
|
||||||
import { useAppStore } from '@/store/modules/app'
|
import { useAppStore } from '@/store'
|
||||||
import { header, tags } from '~/settings'
|
import { header, tags } from '~/settings'
|
||||||
|
|
||||||
const appStore = useAppStore()
|
const appStore = useAppStore()
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
|
/** 重置样式 */
|
||||||
import '@/styles/reset.css'
|
import '@/styles/reset.css'
|
||||||
import '@/styles/index.scss'
|
|
||||||
import 'uno.css'
|
import 'uno.css'
|
||||||
|
import '@/styles/global.scss'
|
||||||
import 'virtual:svg-icons-register'
|
import 'virtual:svg-icons-register'
|
||||||
|
|
||||||
import { createApp } from 'vue'
|
import { createApp } from 'vue'
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import { getToken, refreshAccessToken } from '@/utils/token'
|
import { getToken, refreshAccessToken, isNullOrWhitespace } from '@/utils'
|
||||||
import { isNullOrWhitespace } from '@/utils/is'
|
|
||||||
|
|
||||||
const WHITE_LIST = ['/login', '/404']
|
const WHITE_LIST = ['/login', '/404']
|
||||||
export function createPermissionGuard(router) {
|
export function createPermissionGuard(router) {
|
||||||
|
|||||||
@@ -1,24 +1,30 @@
|
|||||||
import { createRouter, createWebHistory, createWebHashHistory } from 'vue-router'
|
import { createRouter, createWebHistory, createWebHashHistory } from 'vue-router'
|
||||||
import { setupRouterGuard } from './guard'
|
import { setupRouterGuard } from './guard'
|
||||||
import { basicRoutes as routes, EMPTY_ROUTE, NOT_FOUND_ROUTE } from './routes'
|
import { basicRoutes, EMPTY_ROUTE, NOT_FOUND_ROUTE } from './routes'
|
||||||
import { getToken } from '@/utils/token'
|
import { getToken, isNullOrWhitespace } from '@/utils'
|
||||||
import { isNullOrWhitespace } from '@/utils/is'
|
import { useUserStore, usePermissionStore } from '@/store'
|
||||||
import { useUserStore } from '@/store/modules/user'
|
|
||||||
import { usePermissionStore } from '@/store/modules/permission'
|
|
||||||
|
|
||||||
const isHash = import.meta.env.VITE_USE_HASH === 'true'
|
const isHash = import.meta.env.VITE_USE_HASH === 'true'
|
||||||
export const router = createRouter({
|
export const router = createRouter({
|
||||||
history: isHash ? createWebHashHistory('/') : createWebHistory('/'),
|
history: isHash ? createWebHashHistory('/') : createWebHistory('/'),
|
||||||
routes,
|
routes: basicRoutes,
|
||||||
scrollBehavior: () => ({ left: 0, top: 0 }),
|
scrollBehavior: () => ({ left: 0, top: 0 }),
|
||||||
})
|
})
|
||||||
|
|
||||||
export async function resetRouter() {
|
export async function setupRouter(app) {
|
||||||
router.getRoutes().forEach((route) => {
|
|
||||||
const { name } = route
|
|
||||||
router.hasRoute(name) && router.removeRoute(name)
|
|
||||||
})
|
|
||||||
await addDynamicRoutes()
|
await addDynamicRoutes()
|
||||||
|
setupRouterGuard(router)
|
||||||
|
app.use(router)
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function resetRouter() {
|
||||||
|
const basicRouteNames = getRouteNames(basicRoutes)
|
||||||
|
router.getRoutes().forEach((route) => {
|
||||||
|
const name = route.name
|
||||||
|
if (!basicRouteNames.includes(name)) {
|
||||||
|
router.removeRoute(name)
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function addDynamicRoutes() {
|
export async function addDynamicRoutes() {
|
||||||
@@ -46,8 +52,14 @@ export async function addDynamicRoutes() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function setupRouter(app) {
|
export function getRouteNames(routes) {
|
||||||
await addDynamicRoutes()
|
return routes.map((route) => getRouteName(route)).flat(1)
|
||||||
setupRouterGuard(router)
|
}
|
||||||
app.use(router)
|
|
||||||
|
function getRouteName(route) {
|
||||||
|
const names = [route.name]
|
||||||
|
if (route.children && route.children.length) {
|
||||||
|
names.push(...route.children.map((item) => getRouteName(item)).flat(1))
|
||||||
|
}
|
||||||
|
return names
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,3 +3,5 @@ import { createPinia } from 'pinia'
|
|||||||
export function setupStore(app) {
|
export function setupStore(app) {
|
||||||
app.use(createPinia())
|
app.use(createPinia())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export * from './modules'
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ export const useAppStore = defineStore('app', {
|
|||||||
return {
|
return {
|
||||||
reloadFlag: true,
|
reloadFlag: true,
|
||||||
collapsed: false,
|
collapsed: false,
|
||||||
|
/** keepAlive路由的key,重新赋值可重置keepAlive */
|
||||||
|
aliveKeys: {},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
@@ -25,5 +27,8 @@ export const useAppStore = defineStore('app', {
|
|||||||
setCollapsed(collapsed) {
|
setCollapsed(collapsed) {
|
||||||
this.collapsed = collapsed
|
this.collapsed = collapsed
|
||||||
},
|
},
|
||||||
|
setAliveKeys(key, val) {
|
||||||
|
this.aliveKeys[key] = val
|
||||||
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
4
src/store/modules/index.js
Normal file
4
src/store/modules/index.js
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
export * from './app'
|
||||||
|
export * from './permission'
|
||||||
|
export * from './tags'
|
||||||
|
export * from './user'
|
||||||
@@ -53,5 +53,8 @@ export const usePermissionStore = defineStore('permission', {
|
|||||||
this.accessRoutes = accessRoutes
|
this.accessRoutes = accessRoutes
|
||||||
return accessRoutes
|
return accessRoutes
|
||||||
},
|
},
|
||||||
|
resetPermission() {
|
||||||
|
this.$reset()
|
||||||
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import { sStorage } from '@/utils/cache'
|
import { sStorage } from '@/utils'
|
||||||
|
|
||||||
export const activeTag = sStorage.get('activeTag')
|
export const activeTag = sStorage.get('activeTag')
|
||||||
export const tags = sStorage.get('tags')
|
export const tags = sStorage.get('tags')
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { defineStore } from 'pinia'
|
import { defineStore } from 'pinia'
|
||||||
import { activeTag, tags, WITHOUT_TAG_PATHS } from './helpers'
|
import { activeTag, tags, WITHOUT_TAG_PATHS } from './helpers'
|
||||||
import { router } from '@/router'
|
import { router } from '@/router'
|
||||||
import { sStorage } from '@/utils/cache'
|
import { sStorage } from '@/utils'
|
||||||
|
|
||||||
export const useTagsStore = defineStore('tag', {
|
export const useTagsStore = defineStore('tag', {
|
||||||
state() {
|
state() {
|
||||||
@@ -57,5 +57,9 @@ export const useTagsStore = defineStore('tag', {
|
|||||||
router.push(filterTags[filterTags.length - 1].path)
|
router.push(filterTags[filterTags.length - 1].path)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
resetTags() {
|
||||||
|
this.setTags([])
|
||||||
|
this.setActiveTag('')
|
||||||
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { defineStore } from 'pinia'
|
import { defineStore } from 'pinia'
|
||||||
import { removeToken } from '@/utils/token'
|
import { resetRouter } from '@/router'
|
||||||
import { toLogin } from '@/utils/auth'
|
import { useTagsStore, usePermissionStore } from '@/store'
|
||||||
|
import { removeToken, toLogin } from '@/utils'
|
||||||
import api from '@/api'
|
import api from '@/api'
|
||||||
|
|
||||||
export const useUserStore = defineStore('user', {
|
export const useUserStore = defineStore('user', {
|
||||||
@@ -35,8 +36,13 @@ export const useUserStore = defineStore('user', {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
async logout() {
|
async logout() {
|
||||||
|
const { resetTags } = useTagsStore()
|
||||||
|
const { resetPermission } = usePermissionStore()
|
||||||
removeToken()
|
removeToken()
|
||||||
this.userInfo = {}
|
resetTags()
|
||||||
|
resetPermission()
|
||||||
|
resetRouter()
|
||||||
|
this.$reset()
|
||||||
toLogin()
|
toLogin()
|
||||||
},
|
},
|
||||||
setUserInfo(userInfo = {}) {
|
setUserInfo(userInfo = {}) {
|
||||||
@@ -1,14 +1,16 @@
|
|||||||
html {
|
|
||||||
font-size: 4px; // * 1rem = 4px 方便unocss计算:在unocss中 1字体单位 = 0.25rem,相当于 1等份 = 1px
|
|
||||||
}
|
|
||||||
|
|
||||||
html,
|
html,
|
||||||
body {
|
body {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
background-color: #f2f2f2;
|
}
|
||||||
font-family: 'Encode Sans Condensed', sans-serif;
|
|
||||||
|
html {
|
||||||
|
font-size: 4px; // * 1rem = 4px 方便unocss计算:在unocss中 1字体单位 = 0.25rem,相当于 1等份 = 1px
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-size: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#app {
|
#app {
|
||||||
@@ -16,7 +18,7 @@ body {
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* router view transition fade-slide */
|
/* transition fade-slide */
|
||||||
.fade-slide-leave-active,
|
.fade-slide-leave-active,
|
||||||
.fade-slide-enter-active {
|
.fade-slide-enter-active {
|
||||||
transition: all 0.3s;
|
transition: all 0.3s;
|
||||||
@@ -32,7 +34,6 @@ body {
|
|||||||
transform: translateX(30px);
|
transform: translateX(30px);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 自定义滚动条样式 */
|
|
||||||
/* 自定义滚动条样式 */
|
/* 自定义滚动条样式 */
|
||||||
.cus-scroll {
|
.cus-scroll {
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
@@ -12,7 +12,7 @@ html {
|
|||||||
|
|
||||||
a {
|
a {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
color: #333;
|
color: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
a:hover,
|
a:hover,
|
||||||
@@ -33,8 +33,3 @@ textarea {
|
|||||||
border: none;
|
border: none;
|
||||||
resize: none;
|
resize: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
|
||||||
font-size: 14px;
|
|
||||||
font-weight: 400;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,14 +0,0 @@
|
|||||||
import { router } from '@/router'
|
|
||||||
|
|
||||||
export function toLogin() {
|
|
||||||
router.replace({
|
|
||||||
path: '/login',
|
|
||||||
query: { ...router.currentRoute.value.query, redirect: router.currentRoute.value.path },
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export function toFourZeroFour() {
|
|
||||||
router.replace({
|
|
||||||
path: '/404',
|
|
||||||
})
|
|
||||||
}
|
|
||||||
16
src/utils/auth/auth.js
Normal file
16
src/utils/auth/auth.js
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import { router } from '@/router'
|
||||||
|
|
||||||
|
export function toLogin() {
|
||||||
|
const currentRoute = unref(router.currentRoute)
|
||||||
|
const needRedirect = !currentRoute.meta.requireAuth && !['/404', '/login'].includes(router.currentRoute.value.path)
|
||||||
|
router.replace({
|
||||||
|
path: '/login',
|
||||||
|
query: needRedirect ? { ...currentRoute.query, redirect: currentRoute.path } : {},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function toFourZeroFour() {
|
||||||
|
router.replace({
|
||||||
|
path: '/404',
|
||||||
|
})
|
||||||
|
}
|
||||||
2
src/utils/auth/index.js
Normal file
2
src/utils/auth/index.js
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
export * from './auth'
|
||||||
|
export * from './token'
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import { lStorage } from './cache'
|
import { lStorage } from '@/utils'
|
||||||
import api from '@/api'
|
import api from '@/api'
|
||||||
|
|
||||||
const TOKEN_CODE = 'access_token'
|
const TOKEN_CODE = 'access_token'
|
||||||
76
src/utils/common/common.js
Normal file
76
src/utils/common/common.js
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
import dayjs from 'dayjs'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @desc 格式化时间
|
||||||
|
* @param {(Object|string|number)} time
|
||||||
|
* @param {string} format
|
||||||
|
* @returns {string | null}
|
||||||
|
*/
|
||||||
|
export function formatDateTime(time = undefined, format = 'YYYY-MM-DD HH:mm:ss') {
|
||||||
|
return dayjs(time).format(format)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function formatDate(date = undefined, format = 'YYYY-MM-DD') {
|
||||||
|
return formatDateTime(date, format)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @desc 函数节流
|
||||||
|
* @param {Function} fn
|
||||||
|
* @param {Number} wait
|
||||||
|
* @returns {Function}
|
||||||
|
*/
|
||||||
|
export function throttle(fn, wait) {
|
||||||
|
var context, args
|
||||||
|
var previous = 0
|
||||||
|
|
||||||
|
return function () {
|
||||||
|
var now = +new Date()
|
||||||
|
context = this
|
||||||
|
args = arguments
|
||||||
|
if (now - previous > wait) {
|
||||||
|
fn.apply(context, args)
|
||||||
|
previous = now
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @desc 函数防抖
|
||||||
|
* @param {Function} func
|
||||||
|
* @param {number} wait
|
||||||
|
* @param {boolean} immediate
|
||||||
|
* @return {*}
|
||||||
|
*/
|
||||||
|
export function debounce(method, wait, immediate) {
|
||||||
|
let timeout
|
||||||
|
return function (...args) {
|
||||||
|
let context = this
|
||||||
|
if (timeout) {
|
||||||
|
clearTimeout(timeout)
|
||||||
|
}
|
||||||
|
// 立即执行需要两个条件,一是immediate为true,二是timeout未被赋值或被置为null
|
||||||
|
if (immediate) {
|
||||||
|
/**
|
||||||
|
* 如果定时器不存在,则立即执行,并设置一个定时器,wait毫秒后将定时器置为null
|
||||||
|
* 这样确保立即执行后wait毫秒内不会被再次触发
|
||||||
|
*/
|
||||||
|
let callNow = !timeout
|
||||||
|
timeout = setTimeout(() => {
|
||||||
|
timeout = null
|
||||||
|
}, wait)
|
||||||
|
if (callNow) {
|
||||||
|
method.apply(context, args)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 如果immediate为false,则函数wait毫秒后执行
|
||||||
|
timeout = setTimeout(() => {
|
||||||
|
/**
|
||||||
|
* args是一个类数组对象,所以使用fn.apply
|
||||||
|
* 也可写作method.call(context, ...args)
|
||||||
|
*/
|
||||||
|
method.apply(context, args)
|
||||||
|
}, wait)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
4
src/utils/common/index.js
Normal file
4
src/utils/common/index.js
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
export * from './common'
|
||||||
|
export * from './is'
|
||||||
|
export * from './icon'
|
||||||
|
export * from './naiveTools'
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import { isNullOrUndef } from '@/utils/is'
|
import { isNullOrUndef } from '@/utils'
|
||||||
|
|
||||||
export function setupMessage(NMessage) {
|
export function setupMessage(NMessage) {
|
||||||
let loadingMessage = null
|
let loadingMessage = null
|
||||||
|
|||||||
@@ -1,7 +1,4 @@
|
|||||||
import { useUserStore } from '@/store/modules/user'
|
import { useUserStore } from '@/store'
|
||||||
import { isNullOrUndef } from '@/utils/is'
|
|
||||||
import { removeToken } from '@/utils/token'
|
|
||||||
import { toLogin } from '@/utils/auth'
|
|
||||||
|
|
||||||
export function addBaseParams(params) {
|
export function addBaseParams(params) {
|
||||||
if (!params.userId) {
|
if (!params.userId) {
|
||||||
@@ -9,35 +6,27 @@ export function addBaseParams(params) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function resolveResError(error = {}) {
|
export function resolveResError(code, message) {
|
||||||
let { code, message } = error
|
switch (code) {
|
||||||
if (isNullOrUndef(code)) {
|
case 400:
|
||||||
// 未知错误
|
message = message ?? '请求参数错误'
|
||||||
code = -1
|
break
|
||||||
message = message ?? '接口未知异常!'
|
case 401:
|
||||||
} else {
|
message = message ?? '登录已过期'
|
||||||
switch (code) {
|
useUserStore().logout()
|
||||||
case 400:
|
break
|
||||||
message = message ?? '请求参数错误'
|
case 403:
|
||||||
break
|
message = message ?? '没有权限'
|
||||||
case 401:
|
break
|
||||||
message = message ?? '登录已过期'
|
case 404:
|
||||||
removeToken()
|
message = message ?? '资源或接口不存在'
|
||||||
toLogin()
|
break
|
||||||
break
|
case 500:
|
||||||
case 403:
|
message = message ?? '服务器异常'
|
||||||
message = message ?? '没有权限'
|
break
|
||||||
break
|
default:
|
||||||
case 404:
|
message = message ?? `【${code}】: 未知异常!`
|
||||||
message = message ?? '资源或接口不存在'
|
break
|
||||||
break
|
|
||||||
case 500:
|
|
||||||
message = message ?? '服务器异常'
|
|
||||||
break
|
|
||||||
default:
|
|
||||||
message = message ?? '操作异常!'
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return { code, message }
|
return message
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import { repReject, repResolve, reqReject, reqResolve } from './interceptors'
|
import { resReject, resResolve, reqReject, reqResolve } from './interceptors'
|
||||||
|
|
||||||
export function createAxios(options = {}) {
|
export function createAxios(options = {}) {
|
||||||
const defaultOptions = {
|
const defaultOptions = {
|
||||||
@@ -10,10 +10,10 @@ export function createAxios(options = {}) {
|
|||||||
...options,
|
...options,
|
||||||
})
|
})
|
||||||
service.interceptors.request.use(reqResolve, reqReject)
|
service.interceptors.request.use(reqResolve, reqReject)
|
||||||
service.interceptors.response.use(repResolve, repReject)
|
service.interceptors.response.use(resResolve, resReject)
|
||||||
return service
|
return service
|
||||||
}
|
}
|
||||||
|
|
||||||
export default createAxios({
|
export const request = createAxios({
|
||||||
baseURL: import.meta.env.VITE_BASE_API,
|
baseURL: import.meta.env.VITE_BASE_API,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import { getToken } from '@/utils/token'
|
import { getToken } from '@/utils'
|
||||||
import { toLogin } from '@/utils/auth'
|
|
||||||
import { resolveResError } from './helpers'
|
import { resolveResError } from './helpers'
|
||||||
|
|
||||||
export function reqResolve(config) {
|
export function reqResolve(config) {
|
||||||
@@ -10,9 +9,7 @@ export function reqResolve(config) {
|
|||||||
|
|
||||||
const token = getToken()
|
const token = getToken()
|
||||||
if (!token) {
|
if (!token) {
|
||||||
// * 未登录或者token过期的情况下,跳转登录页重新登录
|
return Promise.reject({ code: 401, message: '登录已过期,请重新登录!' })
|
||||||
toLogin()
|
|
||||||
return Promise.reject({ code: '-1', message: '未登录' })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -28,19 +25,34 @@ export function reqReject(error) {
|
|||||||
return Promise.reject(error)
|
return Promise.reject(error)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function repResolve(response) {
|
export function resResolve(response) {
|
||||||
const { noNeedTip } = response.config
|
// TODO: 处理不同的 response.headers
|
||||||
if (response.data?.code !== 0) {
|
const { data, status, config, statusText } = response
|
||||||
const { code, message } = resolveResError(response?.data)
|
if (data?.code !== 0) {
|
||||||
!noNeedTip && $message.error(message)
|
const code = data?.code ?? status
|
||||||
return Promise.reject({ code, message, error: response?.data })
|
|
||||||
|
/** 根据code处理对应的操作,并返回处理后的message */
|
||||||
|
const message = resolveResError(code, data?.message ?? statusText)
|
||||||
|
|
||||||
|
/** 需要错误提醒 */
|
||||||
|
!config.noNeedTip && $message.error(message)
|
||||||
|
return Promise.reject({ code, message, error: data || response })
|
||||||
}
|
}
|
||||||
return Promise.resolve(response?.data)
|
return Promise.resolve(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function repReject(error) {
|
export function resReject(error) {
|
||||||
const { noNeedTip } = error.response?.config || error.config
|
if (!error || !error.response) {
|
||||||
const { code, message } = resolveResError(error.response?.data)
|
const code = error?.code
|
||||||
!noNeedTip && $message.error(message)
|
/** 根据code处理对应的操作,并返回处理后的message */
|
||||||
return Promise.reject({ code, message, error })
|
const message = resolveResError(code, error.message)
|
||||||
|
$message?.error(message)
|
||||||
|
return Promise.reject({ code, message, error })
|
||||||
|
}
|
||||||
|
const { data, status, config } = error.response
|
||||||
|
const code = data?.code ?? status
|
||||||
|
const message = resolveResError(code, data?.message ?? error.message)
|
||||||
|
/** 需要错误提醒 */
|
||||||
|
!config?.noNeedTip && $message.error(message)
|
||||||
|
return Promise.reject({ code, message, error: error.response?.data || error.response })
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,76 +1,4 @@
|
|||||||
import dayjs from 'dayjs'
|
export * from './common'
|
||||||
|
export * from './storage'
|
||||||
/**
|
export * from './http'
|
||||||
* @desc 格式化时间
|
export * from './auth'
|
||||||
* @param {(Object|string|number)} time
|
|
||||||
* @param {string} format
|
|
||||||
* @returns {string | null}
|
|
||||||
*/
|
|
||||||
export function formatDateTime(time = undefined, format = 'YYYY-MM-DD HH:mm:ss') {
|
|
||||||
return dayjs(time).format(format)
|
|
||||||
}
|
|
||||||
|
|
||||||
export function formatDate(date = undefined, format = 'YYYY-MM-DD') {
|
|
||||||
return formatDateTime(date, format)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @desc 函数节流
|
|
||||||
* @param {Function} fn
|
|
||||||
* @param {Number} wait
|
|
||||||
* @returns {Function}
|
|
||||||
*/
|
|
||||||
export function throttle(fn, wait) {
|
|
||||||
var context, args
|
|
||||||
var previous = 0
|
|
||||||
|
|
||||||
return function () {
|
|
||||||
var now = +new Date()
|
|
||||||
context = this
|
|
||||||
args = arguments
|
|
||||||
if (now - previous > wait) {
|
|
||||||
fn.apply(context, args)
|
|
||||||
previous = now
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @desc 函数防抖
|
|
||||||
* @param {Function} func
|
|
||||||
* @param {number} wait
|
|
||||||
* @param {boolean} immediate
|
|
||||||
* @return {*}
|
|
||||||
*/
|
|
||||||
export function debounce(method, wait, immediate) {
|
|
||||||
let timeout
|
|
||||||
return function (...args) {
|
|
||||||
let context = this
|
|
||||||
if (timeout) {
|
|
||||||
clearTimeout(timeout)
|
|
||||||
}
|
|
||||||
// 立即执行需要两个条件,一是immediate为true,二是timeout未被赋值或被置为null
|
|
||||||
if (immediate) {
|
|
||||||
/**
|
|
||||||
* 如果定时器不存在,则立即执行,并设置一个定时器,wait毫秒后将定时器置为null
|
|
||||||
* 这样确保立即执行后wait毫秒内不会被再次触发
|
|
||||||
*/
|
|
||||||
let callNow = !timeout
|
|
||||||
timeout = setTimeout(() => {
|
|
||||||
timeout = null
|
|
||||||
}, wait)
|
|
||||||
if (callNow) {
|
|
||||||
method.apply(context, args)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// 如果immediate为false,则函数wait毫秒后执行
|
|
||||||
timeout = setTimeout(() => {
|
|
||||||
/**
|
|
||||||
* args是一个类数组对象,所以使用fn.apply
|
|
||||||
* 也可写作method.call(context, ...args)
|
|
||||||
*/
|
|
||||||
method.apply(context, args)
|
|
||||||
}, wait)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { isNullOrUndef } from '@/utils/is'
|
import { isNullOrUndef } from '@/utils'
|
||||||
|
|
||||||
class Storage {
|
class Storage {
|
||||||
constructor(option) {
|
constructor(option) {
|
||||||
@@ -10,8 +10,8 @@
|
|||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div f-c-c mt-20 w-350 rounded-10 b-1 bc-ccc>
|
<div f-c-c flex-col mt-20 w-350>
|
||||||
<div flex w-360 flex-wrap justify-around p-10>
|
<div flex flex-wrap justify-around p-10 rounded-10 b-1 bc-ccc>
|
||||||
<div w-50 h-50 b-1 rounded-5 f-c-c p-10 m-20>
|
<div w-50 h-50 b-1 rounded-5 f-c-c p-10 m-20>
|
||||||
<span w-6 h-6 rounded-3 bg-black></span>
|
<span w-6 h-6 rounded-3 bg-black></span>
|
||||||
</div>
|
</div>
|
||||||
@@ -34,12 +34,12 @@
|
|||||||
<span w-6 h-6 rounded-3 bg-black></span>
|
<span w-6 h-6 rounded-3 bg-black></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div w-50 h-50 b-1 rounded-5 f-c-c flex-col p-10 m-20>
|
<div w-50 h-50 b-1 rounded-5 flex-col justify-between items-center p-10 m-20>
|
||||||
<div flex w-full justify-between>
|
<div flex w-full justify-between>
|
||||||
<span w-6 h-6 rounded-3 bg-black></span>
|
<span w-6 h-6 rounded-3 bg-black></span>
|
||||||
<span w-6 h-6 rounded-3 bg-black></span>
|
<span w-6 h-6 rounded-3 bg-black></span>
|
||||||
</div>
|
</div>
|
||||||
<span w-6 h-6 rounded-3 bg-black></span>
|
<div w-6 h-6 rounded-3 bg-black></div>
|
||||||
<div flex w-full justify-between>
|
<div flex w-full justify-between>
|
||||||
<span w-6 h-6 rounded-3 bg-black></span>
|
<span w-6 h-6 rounded-3 bg-black></span>
|
||||||
<span w-6 h-6 rounded-3 bg-black></span>
|
<span w-6 h-6 rounded-3 bg-black></span>
|
||||||
@@ -60,7 +60,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<h2 font-normal text-14 mt-10 color-gray>Flex 骰子</h2>
|
||||||
</div>
|
</div>
|
||||||
<h2 font-normal text-14 text-center w-350 mt-10 color-gray>Flex 骰子</h2>
|
|
||||||
</CommonPage>
|
</CommonPage>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import request from '@/utils/http'
|
import { request } from '@/utils'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
getPosts: (params = {}) => request.get('posts', { params }),
|
getPosts: (params = {}) => request.get('posts', { params }),
|
||||||
|
|||||||
@@ -82,11 +82,9 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { NButton, NSwitch } from 'naive-ui'
|
import { NButton, NSwitch } from 'naive-ui'
|
||||||
import { formatDateTime } from '@/utils'
|
import { formatDateTime, renderIcon, isNullOrUndef } from '@/utils'
|
||||||
import { renderIcon } from '@/utils/icon'
|
|
||||||
import { useCRUD } from '@/composables'
|
import { useCRUD } from '@/composables'
|
||||||
import api from './api'
|
import api from './api'
|
||||||
import { isNullOrUndef } from '@/utils/is'
|
|
||||||
|
|
||||||
defineOptions({ name: 'CrudTable' })
|
defineOptions({ name: 'CrudTable' })
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import request from '@/utils/http'
|
import { request } from '@/utils'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
login: (data) => request.post('/auth/login', data, { noNeedToken: true }),
|
login: (data) => request.post('/auth/login', data, { noNeedToken: true }),
|
||||||
|
|||||||
@@ -46,8 +46,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { lStorage } from '@/utils/cache'
|
import { lStorage, setToken } from '@/utils'
|
||||||
import { setToken } from '@/utils/token'
|
|
||||||
import { useStorage } from '@vueuse/core'
|
import { useStorage } from '@vueuse/core'
|
||||||
import bgImg from '@/assets/images/login_bg.webp'
|
import bgImg from '@/assets/images/login_bg.webp'
|
||||||
import api from './api'
|
import api from './api'
|
||||||
|
|||||||
@@ -52,7 +52,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { useUserStore } from '@/store/modules/user'
|
import { useUserStore } from '@/store'
|
||||||
|
|
||||||
const userStore = useUserStore()
|
const userStore = useUserStore()
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
Reference in New Issue
Block a user