feat(useTitle): Add useTitle
feat(useNProgress): Add useNProgress
This commit is contained in:
parent
3fc7d4d39a
commit
c5ab3599c8
|
@ -14,6 +14,5 @@
|
|||
"i18n-ally.enabledParsers": ["ts"],
|
||||
"i18n-ally.sourceLanguage": "en",
|
||||
"i18n-ally.displayLanguage": "zh-CN",
|
||||
"i18n-ally.enabledFrameworks": ["vue", "react"],
|
||||
"god.tsconfig": "./tsconfig.json"
|
||||
"i18n-ally.enabledFrameworks": ["vue", "react"]
|
||||
}
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
import { config } from '@/config/axios'
|
||||
import { config } from '@/config/axios/config'
|
||||
import { MockMethod } from 'vite-plugin-mock'
|
||||
|
||||
const { result_code } = config
|
||||
|
||||
const timeout = 2000
|
||||
|
||||
const List: {
|
||||
username: string
|
||||
password: string
|
||||
|
@ -28,6 +30,7 @@ export default [
|
|||
{
|
||||
url: '/user/login',
|
||||
method: 'post',
|
||||
timeout,
|
||||
response: ({ body }) => {
|
||||
const data = body
|
||||
let hasUser = false
|
||||
|
|
25
package.json
25
package.json
|
@ -26,13 +26,14 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"@iconify/iconify": "^2.1.0",
|
||||
"@vueuse/core": "^7.5.1",
|
||||
"@vueuse/core": "^7.5.3",
|
||||
"@zxcvbn-ts/core": "^1.2.0",
|
||||
"animate.css": "^4.1.1",
|
||||
"axios": "^0.24.0",
|
||||
"element-plus": "1.3.0-beta.1",
|
||||
"element-plus": "1.3.0-beta.2",
|
||||
"lodash-es": "^4.17.21",
|
||||
"mockjs": "^1.1.0",
|
||||
"nprogress": "^0.2.0",
|
||||
"pinia": "^2.0.9",
|
||||
"qs": "^6.10.2",
|
||||
"vue": "3.2.26",
|
||||
|
@ -44,28 +45,30 @@
|
|||
"devDependencies": {
|
||||
"@commitlint/cli": "^16.0.1",
|
||||
"@commitlint/config-conventional": "^16.0.0",
|
||||
"@iconify/json": "^1.1.450",
|
||||
"@iconify/json": "^1.1.453",
|
||||
"@intlify/vite-plugin-vue-i18n": "^3.2.1",
|
||||
"@purge-icons/generated": "^0.7.0",
|
||||
"@types/lodash-es": "^4.17.5",
|
||||
"@types/node": "^17.0.5",
|
||||
"@typescript-eslint/eslint-plugin": "^5.8.1",
|
||||
"@typescript-eslint/parser": "^5.8.1",
|
||||
"@types/node": "^17.0.8",
|
||||
"@types/nprogress": "^0.2.0",
|
||||
"@types/qs": "^6.9.7",
|
||||
"@typescript-eslint/eslint-plugin": "^5.9.0",
|
||||
"@typescript-eslint/parser": "^5.9.0",
|
||||
"@vitejs/plugin-vue": "^2.0.1",
|
||||
"@vitejs/plugin-vue-jsx": "^1.3.3",
|
||||
"autoprefixer": "^10.4.1",
|
||||
"autoprefixer": "^10.4.2",
|
||||
"commitizen": "^4.2.4",
|
||||
"eslint": "^8.6.0",
|
||||
"eslint-config-prettier": "^8.3.0",
|
||||
"eslint-define-config": "^1.2.1",
|
||||
"eslint-define-config": "^1.2.2",
|
||||
"eslint-plugin-prettier": "^4.0.0",
|
||||
"eslint-plugin-vue": "^8.2.0",
|
||||
"husky": "^7.0.4",
|
||||
"less": "^4.1.2",
|
||||
"lint-staged": "^12.1.4",
|
||||
"lint-staged": "^12.1.7",
|
||||
"postcss": "^8.4.5",
|
||||
"postcss-html": "^1.3.0",
|
||||
"postcss-less": "^5.0.0",
|
||||
"postcss-less": "^6.0.0",
|
||||
"prettier": "^2.5.1",
|
||||
"pretty-quick": "^3.1.3",
|
||||
"rimraf": "^3.0.2",
|
||||
|
@ -82,7 +85,7 @@
|
|||
"vite-plugin-style-import": "^1.4.1",
|
||||
"vite-plugin-svg-icons": "^1.1.0",
|
||||
"vite-plugin-windicss": "^1.6.1",
|
||||
"vue-tsc": "^0.30.1",
|
||||
"vue-tsc": "^0.30.2",
|
||||
"windicss": "^3.4.2",
|
||||
"windicss-analysis": "^0.3.5"
|
||||
},
|
||||
|
|
1782
pnpm-lock.yaml
1782
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
|
@ -1,7 +1,8 @@
|
|||
import { useAxios } from '@/hooks/web/useAxios'
|
||||
import type { UserLoginType } from './types'
|
||||
|
||||
const { request } = useAxios()
|
||||
|
||||
export const loginApi = ({ data }: AxiosConfig) => {
|
||||
export const loginApi = (data: UserLoginType) => {
|
||||
return request({ url: '/user/login', method: 'post', data })
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
export type UserLoginType = {
|
||||
username: string
|
||||
password: string
|
||||
}
|
|
@ -16,7 +16,7 @@ provide('configGlobal', props)
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<ElConfigProvider :locale="locale.elLocale" :size="size">
|
||||
<ElConfigProvider :locale="locale.elLocale" :message="{ max: 1 }" :size="size">
|
||||
<slot></slot>
|
||||
</ElConfigProvider>
|
||||
</template>
|
||||
|
|
|
@ -21,7 +21,6 @@ export interface AppState {
|
|||
greyMode: boolean
|
||||
showBackTop: boolean
|
||||
showMenuTab: boolean
|
||||
requestTime: boolean
|
||||
isDark: boolean
|
||||
size: ElememtPlusSzie
|
||||
sizeMap: ElememtPlusSzie[]
|
||||
|
@ -44,7 +43,6 @@ export const appModules: AppState = {
|
|||
greyMode: false, // 是否开始灰色模式,用于特殊悼念日
|
||||
showBackTop: true, // 是否显示回到顶部
|
||||
showMenuTab: false, // 是否固定一级菜单
|
||||
requestTime: false, // 是否在接口调用时添加时间戳,避免IE缓存
|
||||
isDark: wsCache.get('isDark') || false, // 是否是暗黑模式
|
||||
size: wsCache.get('default') || 'default', // 组件尺寸
|
||||
sizeMap: ['default', 'large', 'small']
|
||||
|
|
|
@ -6,7 +6,7 @@ const config: {
|
|||
test: string
|
||||
}
|
||||
result_code: number | string
|
||||
default_headers: AxiosHeadersType
|
||||
default_headers: AxiosHeaders
|
||||
request_timeout: number
|
||||
} = {
|
||||
/**
|
|
@ -10,7 +10,7 @@ import { ElMessage } from 'element-plus'
|
|||
|
||||
import qs from 'qs'
|
||||
|
||||
import { config } from '@/config/axios'
|
||||
import { config } from '@/config/axios/config'
|
||||
|
||||
const { result_code, base_url } = config
|
||||
|
||||
|
@ -25,7 +25,6 @@ const service: AxiosInstance = axios.create({
|
|||
// request拦截器
|
||||
service.interceptors.request.use(
|
||||
(config: AxiosRequestConfig) => {
|
||||
console.log('我进来了吗')
|
||||
if (
|
||||
config.method === 'post' &&
|
||||
(config.headers as AxiosRequestHeaders)['Content-Type'] ===
|
||||
|
@ -59,7 +58,6 @@ service.interceptors.request.use(
|
|||
// response 拦截器
|
||||
service.interceptors.response.use(
|
||||
(response: AxiosResponse<Recordable>) => {
|
||||
console.log(response)
|
||||
if (response.data.code === result_code) {
|
||||
return response.data
|
||||
} else {
|
||||
|
@ -67,7 +65,6 @@ service.interceptors.response.use(
|
|||
}
|
||||
},
|
||||
(error: AxiosError) => {
|
||||
console.log(error)
|
||||
console.log('err' + error) // for debug
|
||||
ElMessage.error(error.message)
|
||||
return Promise.reject(error)
|
|
@ -1,12 +1,8 @@
|
|||
import { service } from '@/plugins/axios'
|
||||
import { service } from '@/config/axios'
|
||||
|
||||
import { AxiosPromise } from 'axios'
|
||||
|
||||
import { useAppStoreWithOut } from '@/store/modules/app'
|
||||
|
||||
import { config } from '@/config/axios'
|
||||
|
||||
const appStore = useAppStoreWithOut()
|
||||
import { config } from '@/config/axios/config'
|
||||
|
||||
const { default_headers } = config
|
||||
|
||||
|
@ -22,7 +18,7 @@ export function useAxios() {
|
|||
return service({
|
||||
url: url,
|
||||
method,
|
||||
params: appStore.getRequestTime ? { time: new Date().getTime(), ...(params || {}) } : params,
|
||||
params,
|
||||
data,
|
||||
responseType: responseType,
|
||||
headers: {
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
import { watch, ref, nextTick, unref } from 'vue'
|
||||
import type { NProgressOptions } from 'nprogress'
|
||||
import NProgress from 'nprogress'
|
||||
import 'nprogress/nprogress.css'
|
||||
import { useCssVar } from '@vueuse/core'
|
||||
|
||||
const primaryColor = useCssVar('--el-color-primary', document.documentElement)
|
||||
|
||||
export function useNProgress() {
|
||||
const isLoading = ref(false)
|
||||
NProgress.configure({ showSpinner: false } as NProgressOptions)
|
||||
|
||||
watch(
|
||||
() => isLoading.value,
|
||||
async (loading: boolean) => {
|
||||
loading ? NProgress.start() : NProgress.done()
|
||||
await nextTick()
|
||||
const bar = document.getElementById('nprogress')?.getElementsByClassName('bar')[0] as ElRef
|
||||
if (bar) {
|
||||
bar.style.background = unref(primaryColor.value)
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
function toggle() {
|
||||
isLoading.value = !isLoading.value
|
||||
}
|
||||
|
||||
return {
|
||||
toggle
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
import { watch, ref } from 'vue'
|
||||
import { isString } from '@/utils/is'
|
||||
import { useAppStoreWithOut } from '@/store/modules/app'
|
||||
import { useI18n } from '@/hooks/web/useI18n'
|
||||
|
||||
const appStore = useAppStoreWithOut()
|
||||
|
||||
export function useTitle(newTitle?: string) {
|
||||
const { t } = useI18n()
|
||||
const title = ref(
|
||||
newTitle ? `${appStore.getTitle} - ${t(newTitle as string)}` : appStore.getTitle
|
||||
)
|
||||
|
||||
watch(
|
||||
title,
|
||||
(n, o) => {
|
||||
if (isString(n) && n !== o && document) {
|
||||
document.title = n
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
)
|
||||
|
||||
return title
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
<script setup lang="ts"></script>
|
||||
|
||||
<template>
|
||||
<section>
|
||||
<router-view v-slot="{ Component, route }">
|
||||
<component :is="Component" :key="route.fullPath" />
|
||||
</router-view>
|
||||
</section>
|
||||
</template>
|
|
@ -22,6 +22,12 @@ export default {
|
|||
remember: 'Remember me',
|
||||
forgetPassword: 'Forget password'
|
||||
},
|
||||
router: {
|
||||
login: 'Login'
|
||||
},
|
||||
mock: {
|
||||
loginErr: 'Wrong account or password'
|
||||
},
|
||||
formDemo: {
|
||||
input: 'Input',
|
||||
inputNumber: 'InputNumber',
|
||||
|
|
|
@ -22,6 +22,12 @@ export default {
|
|||
remember: '记住我',
|
||||
forgetPassword: '忘记密码'
|
||||
},
|
||||
router: {
|
||||
login: '登录'
|
||||
},
|
||||
mock: {
|
||||
loginErr: '账号或密码错误'
|
||||
},
|
||||
formDemo: {
|
||||
input: '输入框',
|
||||
inputNumber: '数字输入框',
|
||||
|
|
|
@ -29,6 +29,8 @@ import { createApp } from 'vue'
|
|||
|
||||
import App from './App.vue'
|
||||
|
||||
import './permission'
|
||||
|
||||
async function setupAll() {
|
||||
const app = createApp(App)
|
||||
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
import router from './router'
|
||||
import { useAppStoreWithOut } from '@/store/modules/app'
|
||||
import { useCache } from '@/hooks/web/useCache'
|
||||
// import type { RouteRecordRaw } from 'vue-router'
|
||||
import { useTitle } from '@/hooks/web/useTitle'
|
||||
import { useNProgress } from '@/hooks/web/useNProgress'
|
||||
|
||||
const appStore = useAppStoreWithOut()
|
||||
|
||||
const { wsCache } = useCache()
|
||||
|
||||
const { toggle } = useNProgress()
|
||||
|
||||
const whiteList = ['/login'] // 不重定向白名单
|
||||
|
||||
router.beforeEach((to, from, next) => {
|
||||
console.log(from)
|
||||
toggle()
|
||||
if (wsCache.get(appStore.getUserInfo)) {
|
||||
if (to.path === '/login') {
|
||||
next({ path: '/' })
|
||||
} else {
|
||||
// if (permissionStore.getIsAddRouters) {
|
||||
// next()
|
||||
// return
|
||||
// }
|
||||
// permissionStore.generateRoutes().then(() => {
|
||||
// permissionStore.addRouters.forEach(async (route) => {
|
||||
// await router.addRoute(route as RouteRecordRaw) // 动态添加可访问路由表
|
||||
// })
|
||||
// const redirectPath = from.query.redirect || to.path
|
||||
// const redirect = decodeURIComponent(redirectPath as string)
|
||||
// const nextData = to.path === redirect ? { ...to, replace: true } : { path: redirect }
|
||||
// permissionStore.setIsAddRouters(true)
|
||||
// next(nextData)
|
||||
// })
|
||||
next()
|
||||
}
|
||||
} else {
|
||||
if (whiteList.indexOf(to.path) !== -1) {
|
||||
next()
|
||||
} else {
|
||||
next(`/login?redirect=${to.path}`) // 否则全部重定向到登录页
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
router.afterEach(async (to) => {
|
||||
useTitle(to?.meta?.title as string)
|
||||
toggle() // 结束Progress
|
||||
})
|
|
@ -2,16 +2,36 @@ import { createRouter, createWebHashHistory } from 'vue-router'
|
|||
import type { RouteRecordRaw } from 'vue-router'
|
||||
import type { App } from 'vue'
|
||||
// import { getParentLayout } from './helper'
|
||||
import { t } from '@/hooks/web/useI18n'
|
||||
import { useI18n } from '@/hooks/web/useI18n'
|
||||
const { t } = useI18n()
|
||||
|
||||
/* Layout */
|
||||
const Layout = () => import('@/layout/Layout.vue')
|
||||
|
||||
export const constantRouterMap: AppRouteRecordRaw[] = [
|
||||
{
|
||||
path: '/redirect',
|
||||
component: Layout,
|
||||
name: 'Redirect',
|
||||
children: [
|
||||
{
|
||||
path: '/redirect/:path*',
|
||||
name: 'Redirect',
|
||||
component: () => import('@/views/Redirect/Redirect.vue'),
|
||||
meta: {}
|
||||
}
|
||||
],
|
||||
meta: {
|
||||
hidden: true
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/login',
|
||||
component: () => import('@/views/Login/Login.vue'),
|
||||
name: 'Login',
|
||||
meta: {
|
||||
hidden: true,
|
||||
title: t('common.login'),
|
||||
title: t('router.login'),
|
||||
noTagsView: true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -58,9 +58,6 @@ export const useAppStore = defineStore({
|
|||
getShowMenuTab(): boolean {
|
||||
return this.showMenuTab
|
||||
},
|
||||
getRequestTime(): boolean {
|
||||
return this.requestTime
|
||||
},
|
||||
getIsDark(): boolean {
|
||||
return this.isDark
|
||||
},
|
||||
|
@ -117,9 +114,6 @@ export const useAppStore = defineStore({
|
|||
setShowMenuTab(showMenuTab: boolean) {
|
||||
this.showMenuTab = showMenuTab
|
||||
},
|
||||
setRequestTime(requestTime: boolean) {
|
||||
this.requestTime = requestTime
|
||||
},
|
||||
setIsDark(isDark: boolean) {
|
||||
this.isDark = isDark
|
||||
if (this.isDark) {
|
||||
|
|
|
@ -5,7 +5,8 @@ import { useI18n } from '@/hooks/web/useI18n'
|
|||
import { ElButton, ElCheckbox, ElLink } from 'element-plus'
|
||||
import { required } from '@/utils/formRules'
|
||||
import { useForm } from '@/hooks/web/useForm'
|
||||
import { loginApi } from '../api'
|
||||
import { loginApi } from '@/api/login'
|
||||
import type { UserLoginType } from '@/api/login/types'
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
|
@ -87,12 +88,11 @@ async function signIn() {
|
|||
if (validate) {
|
||||
loading.value = true
|
||||
const { getFormData } = methods
|
||||
const formData = await getFormData()
|
||||
const res = await loginApi({
|
||||
data: formData
|
||||
})
|
||||
const formData = (await getFormData()) as UserLoginType
|
||||
const res = await loginApi(formData)
|
||||
.catch(() => {})
|
||||
.finally(() => (loading.value = false))
|
||||
console.log(res)
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
@ -118,7 +118,9 @@ async function signIn() {
|
|||
</template>
|
||||
|
||||
<template #login>
|
||||
<ElButton type="primary" class="w-[100%]" @click="signIn">{{ t('login.login') }}</ElButton>
|
||||
<ElButton :loading="loading" type="primary" class="w-[100%]" @click="signIn">
|
||||
{{ t('login.login') }}
|
||||
</ElButton>
|
||||
</template>
|
||||
|
||||
<template #otherIcon>
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
<template>
|
||||
<div></div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { unref } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
|
||||
const { currentRoute, replace } = useRouter()
|
||||
|
||||
const { params, query } = unref(currentRoute)
|
||||
const { path, _redirect_type = 'path' } = params
|
||||
|
||||
Reflect.deleteProperty(params, '_redirect_type')
|
||||
Reflect.deleteProperty(params, 'path')
|
||||
|
||||
const _path = Array.isArray(path) ? path.join('/') : path
|
||||
|
||||
if (_redirect_type === 'name') {
|
||||
replace({
|
||||
name: _path,
|
||||
query,
|
||||
params
|
||||
})
|
||||
} else {
|
||||
replace({
|
||||
path: _path.startsWith('/') ? _path : '/' + _path,
|
||||
query
|
||||
})
|
||||
}
|
||||
</script>
|
|
@ -16,16 +16,20 @@ declare type ComponentRef<T> = InstanceType<T>
|
|||
|
||||
declare type LocaleType = 'zh-CN' | 'en'
|
||||
|
||||
declare type AxiosHeaders =
|
||||
| 'application/json'
|
||||
| 'application/x-www-form-urlencoded'
|
||||
| 'multipart/form-data'
|
||||
|
||||
declare type AxiosMethod = 'get' | 'post' | 'delete' | 'put'
|
||||
|
||||
declare type AxiosResponseType = 'arraybuffer' | 'blob' | 'document' | 'json' | 'text' | 'stream'
|
||||
|
||||
declare type AxiosConfig = {
|
||||
params?: Recordable
|
||||
data?: Recordable
|
||||
url?: string
|
||||
method?: 'get' | 'post' | 'delete' | 'put'
|
||||
method?: AxiosMethod
|
||||
headersType?: string
|
||||
responseType?: 'arraybuffer' | 'blob' | 'document' | 'json' | 'text' | 'stream'
|
||||
responseType?: AxiosResponseType
|
||||
}
|
||||
|
||||
declare type AxiosHeadersType =
|
||||
| 'application/json'
|
||||
| 'application/x-www-form-urlencoded'
|
||||
| 'multipart/form-data'
|
||||
|
|
|
@ -22,7 +22,6 @@ function pathResolve(dir: string) {
|
|||
export default ({ command, mode }: ConfigEnv): UserConfig => {
|
||||
let env = null
|
||||
const isBuild = command === 'build'
|
||||
console.log(isBuild)
|
||||
if (!isBuild) {
|
||||
env = loadEnv((process.argv[3] === '--mode' ? process.argv[4] : process.argv[3]), root)
|
||||
} else {
|
||||
|
|
Loading…
Reference in New Issue