请求接口更新,添加500页面,修复初始状态下服务器连接失败造成直接退出登录的问题,修复ESLint问题。
This commit is contained in:
parent
bb55eaedad
commit
cd59783e90
|
@ -74,6 +74,7 @@ module.exports = defineConfig({
|
|||
'prefer-rest-params': 'error',
|
||||
'prefer-spread': 'error',
|
||||
'prefer-template': 'error',
|
||||
'eslint-comments/no-unlimited-disable': 'off',
|
||||
|
||||
'no-redeclare': 'off',
|
||||
'@typescript-eslint/no-redeclare': 'error',
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
/* eslint-disable */
|
||||
import { markRaw, nextTick, ref } from 'vue'
|
||||
import { mount } from '@vue/test-utils'
|
||||
import { describe, expect, it, test } from 'vitest'
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import NProgress from 'nprogress'
|
||||
import type { RouteRawConfig, RouterTypes, rawConfig } from '~/basic'
|
||||
import type { RouteRecordName } from 'vue-router'
|
||||
import { RouterView } from 'vue-router'
|
||||
/**
|
||||
* 根据请求,过滤异步路由
|
||||
* @param:menuList 异步路由数组
|
||||
|
@ -17,7 +16,6 @@ import router, { asyncRoutes, constantRoutes } from '@/router'
|
|||
import 'nprogress/nprogress.css'
|
||||
import { useBasicStore } from '@/store/basic'
|
||||
import { isArray } from 'xe-utils'
|
||||
import settings from '@/settings'
|
||||
|
||||
const buttonCodes: Array<Number> = [] //按钮权限
|
||||
interface menuRow {
|
||||
|
|
|
@ -7,11 +7,14 @@ import { getRouterList } from '@/api/router'
|
|||
|
||||
//路由进入前拦截
|
||||
//to:将要进入的页面 vue-router4.0 不推荐使用next()
|
||||
const whiteList = ['/login', '/404', '/401'] // no redirect whitelist
|
||||
const whiteList = ['/login', '/404', '/401', '/500'] // no redirect whitelist
|
||||
router.beforeEach(async (to) => {
|
||||
progressStart()
|
||||
document.title = langTitle(to.meta?.title) // i18 page title
|
||||
const basicStore = useBasicStore()
|
||||
if (to.path === '/500') {
|
||||
return true
|
||||
}
|
||||
//1.判断token
|
||||
if (basicStore.token) {
|
||||
if (to.path === '/login') {
|
||||
|
@ -36,7 +39,7 @@ router.beforeEach(async (to) => {
|
|||
console.error(`route permission error${e}`)
|
||||
basicStore.resetState()
|
||||
progressClose()
|
||||
return `/login?redirect=${to.path}`
|
||||
return `/500?redirect=${to.path}`
|
||||
}
|
||||
} else {
|
||||
return true
|
||||
|
|
|
@ -19,6 +19,11 @@ export const constantRoutes: RouterTypes = [
|
|||
component: () => import('@/views/error-page/401.vue'),
|
||||
hidden: true
|
||||
},
|
||||
{
|
||||
path: '/500',
|
||||
component: () => import('@/views/error-page/500.vue'),
|
||||
hidden: true
|
||||
},
|
||||
{
|
||||
path: '/',
|
||||
component: Layout,
|
||||
|
|
|
@ -13,7 +13,7 @@ export function mobilePhone(str) {
|
|||
/*
|
||||
* 传入一串num四个 一个空格
|
||||
* */
|
||||
export function toSplitNumFor(num, numToSpace) {
|
||||
export function toSplitNumFor(num) {
|
||||
return num.replace(/(.{4})/g, '$1 ')
|
||||
}
|
||||
// 匹配银行卡号
|
||||
|
|
|
@ -46,6 +46,7 @@ service.interceptors.response.use(
|
|||
}
|
||||
},
|
||||
(error) => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`err${error}`) // for debug
|
||||
ElMessage({
|
||||
message: error.ElMessage,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import type { AxiosRequestConfig } from 'axios'
|
||||
import axios from 'axios'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { useBasicStore } from '@/store/basic'
|
||||
|
||||
//使用axios.create()创建一个axios请求实例
|
||||
|
@ -31,6 +31,8 @@ service.interceptors.request.use(
|
|||
//请求后拦截
|
||||
service.interceptors.response.use(
|
||||
(res) => {
|
||||
const type = (res.headers['content-type'] as string) || ''
|
||||
if (!type.startsWith('application/json')) return res.data
|
||||
const { code } = res.data
|
||||
const successCode = '0,200,20000'
|
||||
const noAuthCode = '401,403'
|
||||
|
@ -38,30 +40,39 @@ service.interceptors.response.use(
|
|||
return res.data
|
||||
} else {
|
||||
if (noAuthCode.includes(code) && !location.href.includes('/login')) {
|
||||
ElMessageBox.confirm('请重新登录', {
|
||||
confirmButtonText: '重新登录',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
useBasicStore().resetStateAndToLogin()
|
||||
})
|
||||
useBasicStore().resetStateAndToLogin()
|
||||
}
|
||||
return Promise.reject(res.data)
|
||||
return Promise.reject(new Error(res.data?.msg ?? '未知异常'))
|
||||
}
|
||||
},
|
||||
//响应报错
|
||||
(err) => {
|
||||
ElMessage.error({
|
||||
message: err,
|
||||
duration: 2 * 1000
|
||||
})
|
||||
const { response } = err
|
||||
if (response?.status === 401) {
|
||||
useBasicStore().resetStateAndToLogin()
|
||||
} else {
|
||||
const { msg } = response?.data ?? { msg: '未知异常' }
|
||||
ElMessage.error({
|
||||
message: msg || err,
|
||||
duration: 2 * 1000
|
||||
})
|
||||
}
|
||||
return Promise.reject(err)
|
||||
}
|
||||
)
|
||||
|
||||
export const baseUrl: string = (() => {
|
||||
let port = import.meta.env.VITE_APP_BASE_URL
|
||||
if (/:\d{1,5}/.test(port)) port = port.match(/(?<port>:\d{1,5})/)?.groups?.port ?? ''
|
||||
else port = `:${location.port}`
|
||||
return `${location.protocol}//${location.hostname}${port}`
|
||||
})()
|
||||
|
||||
//导出service实例给页面调用 , config->页面的配置
|
||||
export default function request(config: AxiosRequestConfig) {
|
||||
return service({
|
||||
baseURL: import.meta.env.VITE_APP_BASE_URL,
|
||||
//baseURL: import.meta.env.VITE_APP_BASE_URL,
|
||||
baseURL: baseUrl,
|
||||
timeout: 8000,
|
||||
...config
|
||||
})
|
||||
|
|
|
@ -42,8 +42,7 @@ export function isName(value) {
|
|||
* @returns {boolean}
|
||||
*/
|
||||
export function isIP(ip) {
|
||||
const reg =
|
||||
/^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/
|
||||
const reg = /^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/
|
||||
return reg.test(ip)
|
||||
}
|
||||
|
||||
|
@ -53,8 +52,7 @@ export function isIP(ip) {
|
|||
* @returns {boolean}
|
||||
*/
|
||||
export function isUrl(url) {
|
||||
const reg =
|
||||
/^(https?|ftp):\/\/([a-zA-Z0-9.-]+(:[a-zA-Z0-9.&%$-]+)*@)*((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}|([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(:[0-9]+)*(\/($|[a-zA-Z0-9.,?'\\+&%$#=~_-]+))*$/
|
||||
const reg = /^(https?|ftp):\/\/([a-zA-Z0-9.-]+(:[a-zA-Z0-9.&%$-]+)*@)*((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}|([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(:[0-9]+)*(\/($|[a-zA-Z0-9.,?'\\+&%$#=~_-]+))*$/
|
||||
return reg.test(url)
|
||||
}
|
||||
|
||||
|
@ -124,8 +122,7 @@ export function isObject(arg) {
|
|||
* @returns {boolean}
|
||||
*/
|
||||
export function isPort(str) {
|
||||
const reg =
|
||||
/^([0-9]|[1-9]\d|[1-9]\d{2}|[1-9]\d{3}|[1-5]\d{4}|6[0-4]\d{3}|65[0-4]\d{2}|655[0-2]\d|6553[0-5])$/
|
||||
const reg = /^([0-9]|[1-9]\d|[1-9]\d{2}|[1-9]\d{3}|[1-5]\d{4}|6[0-4]\d{3}|65[0-4]\d{2}|655[0-2]\d|6553[0-5])$/
|
||||
return reg.test(str)
|
||||
}
|
||||
|
||||
|
@ -145,8 +142,7 @@ export function isPhone(str) {
|
|||
* @returns {boolean}
|
||||
*/
|
||||
export function isIdCard(str) {
|
||||
const reg =
|
||||
/^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/
|
||||
const reg = /^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/
|
||||
return reg.test(str)
|
||||
}
|
||||
|
||||
|
@ -176,13 +172,7 @@ export function isChina(str) {
|
|||
* @returns {boolean}
|
||||
*/
|
||||
export function isBlank(str) {
|
||||
return (
|
||||
str == null ||
|
||||
false ||
|
||||
str === '' ||
|
||||
str.trim() === '' ||
|
||||
str.toLocaleLowerCase().trim() === 'null'
|
||||
)
|
||||
return str == null || false || str === '' || str.trim() === '' || str.toLocaleLowerCase().trim() === 'null'
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -191,8 +181,7 @@ export function isBlank(str) {
|
|||
* @returns {boolean}
|
||||
*/
|
||||
export function isTel(str) {
|
||||
const reg =
|
||||
/^(400|800)([0-9\\-]{7,10})|(([0-9]{4}|[0-9]{3})(-| )?)?([0-9]{7,8})((-| |转)*([0-9]{1,4}))?$/
|
||||
const reg = /^(400|800)([0-9\\-]{7,10})|(([0-9]{4}|[0-9]{3})(-| )?)?([0-9]{7,8})((-| |转)*([0-9]{1,4}))?$/
|
||||
return reg.test(str)
|
||||
}
|
||||
|
||||
|
@ -210,14 +199,14 @@ export function isNum(str) {
|
|||
* @param cid 18为的身份证号码
|
||||
* @return Boolean 是否有效
|
||||
**/
|
||||
export function isIdentityNumber(cid) {
|
||||
export function isIdentityNumber(cid: string) {
|
||||
const arrExp = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2] //加权因子
|
||||
const arrValid = '1 0 X 9 8 7 6 5 4 3 2'.split(' ') //校检码
|
||||
if (/^\d{17}\d|x$/i.test(cid)) {
|
||||
let sum = 0
|
||||
for (let i = 0; i < cid.length - 1; i++) {
|
||||
// 对前17位数字与权值乘积求和
|
||||
sum += Number.parseInt(cid.substr(i, 1), 10) * arrExp[i]
|
||||
sum += Number.parseInt(cid.slice(i, i + 1), 10) * arrExp[i]
|
||||
}
|
||||
// 计算模(固定算法)
|
||||
const idx = sum % 11
|
||||
|
@ -253,7 +242,7 @@ export class ElValidate {
|
|||
validate.push({
|
||||
required: true,
|
||||
trigger: 'blur',
|
||||
message: isString(canEmpty) ? canEmpty : '请输入文本',
|
||||
message: isString(canEmpty) ? canEmpty : '请输入文本'
|
||||
})
|
||||
return validate
|
||||
}
|
||||
|
@ -268,11 +257,11 @@ export class ElValidate {
|
|||
{
|
||||
trigger: 'blur',
|
||||
message: '请输入有效的手机号',
|
||||
validator (rule, value, callback) {
|
||||
validator(rule, value, callback) {
|
||||
if (/^1[3456789]\d{9}$/g.test(value)) callback()
|
||||
else callback(new Error('无效的手机号'))
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
])
|
||||
}
|
||||
|
||||
|
@ -285,14 +274,14 @@ export class ElValidate {
|
|||
{
|
||||
trigger: 'blur',
|
||||
message: '请输入有效的身份证号',
|
||||
validator (rule, value, callback) {
|
||||
validator(rule, value, callback) {
|
||||
if (isIdentityNumber(value)) {
|
||||
callback()
|
||||
} else {
|
||||
callback(new Error('无效的身份证号'))
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
])
|
||||
}
|
||||
|
||||
|
@ -311,7 +300,7 @@ export class ElValidate {
|
|||
{
|
||||
trigger: 'change',
|
||||
message: lint,
|
||||
validator (rule, value, callback) {
|
||||
validator(rule, value, callback) {
|
||||
if (value.length < min) {
|
||||
callback(new Error(`输入文本太短,最少长度为${min}`))
|
||||
return
|
||||
|
@ -321,8 +310,8 @@ export class ElValidate {
|
|||
return
|
||||
}
|
||||
callback()
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
])
|
||||
}
|
||||
|
||||
|
|
237
src/views/error-page/500.vue
Normal file
237
src/views/error-page/500.vue
Normal file
|
@ -0,0 +1,237 @@
|
|||
<template>
|
||||
<div class="wscn-http404-container">
|
||||
<div class="wscn-http404">
|
||||
<div class="pic-404">
|
||||
<img class="pic-404__parent" src="@/assets/404_images/404.png" alt="404" />
|
||||
<img class="pic-404__child left" src="@/assets/404_images/404_cloud.png" alt="404" />
|
||||
<img class="pic-404__child mid" src="@/assets/404_images/404_cloud.png" alt="404" />
|
||||
<img class="pic-404__child right" src="@/assets/404_images/404_cloud.png" alt="404" />
|
||||
</div>
|
||||
<div class="bullshit">
|
||||
<div class="bullshit__oops">OOPS!</div>
|
||||
<div class="bullshit__info">
|
||||
All rights reserved
|
||||
<a style="color: #20a0ff" href="https://wallstreetcn.com" target="_blank">wallstreetcn</a>
|
||||
</div>
|
||||
<div class="bullshit__headline">服务器内部异常,请稍候重试</div>
|
||||
<div class="bullshit__info">
|
||||
或询问管理员服务器后台是否正常运行
|
||||
</div>
|
||||
<router-link :to="target" class="bullshit__return-home">重试</router-link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
const target = computed(() => useRoute().query.redirect || "/dashboard");
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.wscn-http404-container {
|
||||
transform: translate(-50%, -50%);
|
||||
position: absolute;
|
||||
top: 40%;
|
||||
left: 50%;
|
||||
}
|
||||
|
||||
.wscn-http404 {
|
||||
position: relative;
|
||||
width: 1200px;
|
||||
padding: 0 50px;
|
||||
overflow: hidden;
|
||||
|
||||
.pic-404 {
|
||||
position: relative;
|
||||
float: left;
|
||||
width: 600px;
|
||||
overflow: hidden;
|
||||
|
||||
&__parent {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
&__child {
|
||||
position: absolute;
|
||||
|
||||
&.left {
|
||||
width: 80px;
|
||||
top: 17px;
|
||||
left: 220px;
|
||||
opacity: 0;
|
||||
animation-name: cloudLeft;
|
||||
animation-duration: 2s;
|
||||
animation-timing-function: linear;
|
||||
animation-fill-mode: forwards;
|
||||
animation-delay: 1s;
|
||||
}
|
||||
|
||||
&.mid {
|
||||
width: 46px;
|
||||
top: 10px;
|
||||
left: 420px;
|
||||
opacity: 0;
|
||||
animation-name: cloudMid;
|
||||
animation-duration: 2s;
|
||||
animation-timing-function: linear;
|
||||
animation-fill-mode: forwards;
|
||||
animation-delay: 1.2s;
|
||||
}
|
||||
|
||||
&.right {
|
||||
width: 62px;
|
||||
top: 100px;
|
||||
left: 500px;
|
||||
opacity: 0;
|
||||
animation-name: cloudRight;
|
||||
animation-duration: 2s;
|
||||
animation-timing-function: linear;
|
||||
animation-fill-mode: forwards;
|
||||
animation-delay: 1s;
|
||||
}
|
||||
|
||||
@keyframes cloudLeft {
|
||||
0% {
|
||||
top: 17px;
|
||||
left: 220px;
|
||||
opacity: 0;
|
||||
}
|
||||
20% {
|
||||
top: 33px;
|
||||
left: 188px;
|
||||
opacity: 1;
|
||||
}
|
||||
80% {
|
||||
top: 81px;
|
||||
left: 92px;
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
top: 97px;
|
||||
left: 60px;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
@keyframes cloudMid {
|
||||
0% {
|
||||
top: 10px;
|
||||
left: 420px;
|
||||
opacity: 0;
|
||||
}
|
||||
20% {
|
||||
top: 40px;
|
||||
left: 360px;
|
||||
opacity: 1;
|
||||
}
|
||||
70% {
|
||||
top: 130px;
|
||||
left: 180px;
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
top: 160px;
|
||||
left: 120px;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
@keyframes cloudRight {
|
||||
0% {
|
||||
top: 100px;
|
||||
left: 500px;
|
||||
opacity: 0;
|
||||
}
|
||||
20% {
|
||||
top: 120px;
|
||||
left: 460px;
|
||||
opacity: 1;
|
||||
}
|
||||
80% {
|
||||
top: 180px;
|
||||
left: 340px;
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
top: 200px;
|
||||
left: 300px;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.bullshit {
|
||||
position: relative;
|
||||
float: left;
|
||||
width: 300px;
|
||||
padding: 30px 0;
|
||||
overflow: hidden;
|
||||
|
||||
&__oops {
|
||||
font-size: 32px;
|
||||
font-weight: bold;
|
||||
line-height: 40px;
|
||||
color: #1482f0;
|
||||
opacity: 0;
|
||||
margin-bottom: 20px;
|
||||
animation-name: slideUp;
|
||||
animation-duration: 0.5s;
|
||||
animation-fill-mode: forwards;
|
||||
}
|
||||
|
||||
&__headline {
|
||||
font-size: 20px;
|
||||
line-height: 24px;
|
||||
color: #222;
|
||||
font-weight: bold;
|
||||
opacity: 0;
|
||||
margin-bottom: 10px;
|
||||
animation-name: slideUp;
|
||||
animation-duration: 0.5s;
|
||||
animation-delay: 0.1s;
|
||||
animation-fill-mode: forwards;
|
||||
}
|
||||
|
||||
&__info {
|
||||
font-size: 13px;
|
||||
line-height: 21px;
|
||||
color: grey;
|
||||
opacity: 0;
|
||||
margin-bottom: 30px;
|
||||
animation-name: slideUp;
|
||||
animation-duration: 0.5s;
|
||||
animation-delay: 0.2s;
|
||||
animation-fill-mode: forwards;
|
||||
}
|
||||
|
||||
&__return-home {
|
||||
display: block;
|
||||
float: left;
|
||||
width: 110px;
|
||||
height: 36px;
|
||||
background: #1482f0;
|
||||
border-radius: 100px;
|
||||
text-align: center;
|
||||
color: #ffffff;
|
||||
opacity: 0;
|
||||
font-size: 14px;
|
||||
line-height: 36px;
|
||||
cursor: pointer;
|
||||
animation-name: slideUp;
|
||||
animation-duration: 0.5s;
|
||||
animation-delay: 0.3s;
|
||||
animation-fill-mode: forwards;
|
||||
}
|
||||
|
||||
@keyframes slideUp {
|
||||
0% {
|
||||
transform: translateY(60px);
|
||||
opacity: 0;
|
||||
}
|
||||
100% {
|
||||
transform: translateY(0);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
Loading…
Reference in New Issue
Block a user