Browse Source

Merge branch 'dev_YWQ' into dev

dev_YWQ
HolyKnightIX 1 year ago
parent
commit
b89da41ca5
18 changed files with 5880 additions and 5715 deletions
  1. +1
    -1
      .env.development
  2. +1
    -1
      .env.production
  3. +0
    -6
      .env.staging
  4. +2
    -2
      package.json
  5. +23
    -0
      src/apis/login.js
  6. BIN
      src/assets/video/loginVideo.mp4
  7. +8
    -1
      src/lang/package/en.ts
  8. +9
    -2
      src/lang/package/zh-cn.ts
  9. +9
    -8
      src/layout/components/Navbar.vue
  10. +47
    -47
      src/permission.ts
  11. +20
    -1
      src/router/index.ts
  12. +65
    -0
      src/utils/request.js
  13. +12
    -12
      src/utils/request.ts
  14. +130
    -72
      src/views/login/index.vue
  15. +2
    -2
      src/views/redirect/index.vue
  16. +15
    -0
      src/views/signSucceed/index.vue
  17. +3
    -5
      vite.config.ts
  18. +5533
    -5555
      yarn.lock

+ 1
- 1
.env.development View File

@@ -5,4 +5,4 @@ NODE_ENV='development'


VITE_APP_TITLE = 'Metavatar-PC' VITE_APP_TITLE = 'Metavatar-PC'
VITE_APP_PORT = 3000 VITE_APP_PORT = 3000
VITE_APP_BASE_API = '/dev-api'
VITE_APP_BASE_API = 'https://photo.metavatar.cc/C'

+ 1
- 1
.env.production View File

@@ -2,4 +2,4 @@


VITE_APP_TITLE = 'Metavatar-PC' VITE_APP_TITLE = 'Metavatar-PC'
VITE_APP_PORT = 3000 VITE_APP_PORT = 3000
VITE_APP_BASE_API = '/prod-api'
VITE_APP_BASE_API = 'https://photo.metavatar.cc/C'

+ 0
- 6
.env.staging View File

@@ -1,6 +0,0 @@
## 模拟环境
NODE_ENV='staging'

VITE_APP_TITLE = 'vue3-element-admin'
VITE_APP_PORT = 3000
VITE_APP_BASE_API = '/prod--api'

+ 2
- 2
package.json View File

@@ -27,7 +27,7 @@
"screenfull": "^6.0.0", "screenfull": "^6.0.0",
"vue": "^3.2.45", "vue": "^3.2.45",
"vue-i18n": "9", "vue-i18n": "9",
"vue-router": "^4.1.6"
"vue-router": "^4.0.13"
}, },
"devDependencies": { "devDependencies": {
"@commitlint/cli": "^17.5.1", "@commitlint/cli": "^17.5.1",
@@ -71,4 +71,4 @@
"repository": "https://gitee.com/youlaiorg/vue3-element-admin.git", "repository": "https://gitee.com/youlaiorg/vue3-element-admin.git",
"author": "有来开源组织", "author": "有来开源组织",
"license": "MIT" "license": "MIT"
}
}

+ 23
- 0
src/apis/login.js View File

@@ -0,0 +1,23 @@
import request from "@/utils/request.js";

const baseURL = import.meta.env.VITE_APP_BASE_API

/**
* @description 注册
* @params email,password
* @returns data
*/
export function register(data) {
return request({
url: `/api/user/doRegisterByEmail`,
method: 'post',
data
})
}

/**
* @description:获取图形验证码
* @return: 验证码地址
*/
export const getCodeImgUrl = baseURL + '/api/user/captcha.jpg'


BIN
src/assets/video/loginVideo.mp4 View File


+ 8
- 1
src/lang/package/en.ts View File

@@ -7,11 +7,15 @@ export default {


// 登录页面国际化 // 登录页面国际化
login: { login: {
title: "Metavatar-PC Sign in",
title: "Metavatar-PC",
username: "Username", username: "Username",
password: "Password", password: "Password",
login: "Sign in", login: "Sign in",
register: "Sign up",
loginBtn: "Sign in",
registerBtn: "Sign up",
verifyCode: "Verify Code", verifyCode: "Verify Code",
signIn: "Already got an account? Sign in here",
signUp: "Don't have an account? Sign up here", signUp: "Don't have an account? Sign up here",
forgetPwd: "I forgot my password", forgetPwd: "I forgot my password",
}, },
@@ -79,4 +83,7 @@ export default {
WeChatPay: "WeChatPay", WeChatPay: "WeChatPay",
Alipay: "Alipay", Alipay: "Alipay",
}, },
signSucceed: {
title: "Sign Succeed !",
},
}; };

+ 9
- 2
src/lang/package/zh-cn.ts View File

@@ -7,11 +7,15 @@ export default {


// 登录页面国际化 // 登录页面国际化
login: { login: {
title: "Metavatar-PC 登录",
title: "Metavatar-PC",
username: "用户名", username: "用户名",
password: "密码", password: "密码",
login: "登 录",
login: "登录",
register: "注册",
loginBtn: "登 录",
registerBtn: "注 册",
verifyCode: "验证码", verifyCode: "验证码",
signIn: "已有账号?现在登录!",
signUp: "没有账号?现在加入!", signUp: "没有账号?现在加入!",
forgetPwd: "忘记密码", forgetPwd: "忘记密码",
}, },
@@ -79,4 +83,7 @@ export default {
WeChatPay: "微信支付", WeChatPay: "微信支付",
Alipay: "支付宝支付", Alipay: "支付宝支付",
}, },
signSucceed: {
title: "注册成功!",
},
}; };

+ 9
- 8
src/layout/components/Navbar.vue View File

@@ -123,14 +123,15 @@ function logout() {
confirmButtonText: confirm, confirmButtonText: confirm,
cancelButtonText: cancel, cancelButtonText: cancel,
}).then(() => { }).then(() => {
userStore
.logout()
.then(() => {
tagsViewStore.delAllViews();
})
.then(() => {
router.push(`/login?redirect=${route.fullPath}`);
});
router.push(`/login`);
// userStore
// .logout()
// .then(() => {
// tagsViewStore.delAllViews();
// })
// .then(() => {
// router.push(`/login?redirect=${route.fullPath}`);
// });
}); });
} }




+ 47
- 47
src/permission.ts View File

@@ -11,51 +11,51 @@ const permissionStore = usePermissionStoreHook();
// 白名单路由 // 白名单路由
const whiteList = ["/login"]; const whiteList = ["/login"];


router.beforeEach(async (to, from, next) => {
NProgress.start();
const hasToken = localStorage.getItem("accessToken");
if (hasToken) {
if (to.path === "/login") {
// 如果已登录,跳转首页
next({ path: "/" });
NProgress.done();
} else {
const userStore = useUserStoreHook();
const hasRoles = userStore.roles && userStore.roles.length > 0;
if (hasRoles) {
// 未匹配到任何路由,跳转404
if (to.matched.length === 0) {
from.name ? next({ name: from.name }) : next("/404");
} else {
next();
}
} else {
try {
const { roles } = await userStore.getInfo();
const accessRoutes = await permissionStore.generateRoutes(roles);
accessRoutes.forEach((route) => {
router.addRoute(route);
});
next({ ...to, replace: true });
} catch (error) {
// 移除 token 并跳转登录页
await userStore.resetToken();
next(`/login?redirect=${to.path}`);
NProgress.done();
}
}
}
} else {
// 未登录可以访问白名单页面
if (whiteList.indexOf(to.path) !== -1) {
next();
} else {
next(`/login?redirect=${to.path}`);
NProgress.done();
}
}
});
// router.beforeEach(async (to, from, next) => {
// NProgress.start();
// const hasToken = localStorage.getItem("accessToken");
// if (hasToken) {
// if (to.path === "/login") {
// // 如果已登录,跳转首页
// next({ path: "/" });
// NProgress.done();
// } else {
// const userStore = useUserStoreHook();
// const hasRoles = userStore.roles && userStore.roles.length > 0;
// if (hasRoles) {
// // 未匹配到任何路由,跳转404
// if (to.matched.length === 0) {
// from.name ? next({ name: from.name }) : next("/404");
// } else {
// next();
// }
// } else {
// try {
// const { roles } = await userStore.getInfo();
// const accessRoutes = await permissionStore.generateRoutes(roles);
// accessRoutes.forEach((route) => {
// router.addRoute(route);
// });
// next({ ...to, replace: true });
// } catch (error) {
// // 移除 token 并跳转登录页
// await userStore.resetToken();
// next(`/login?redirect=${to.path}`);
// NProgress.done();
// }
// }
// }
// } else {
// // 未登录可以访问白名单页面
// if (whiteList.indexOf(to.path) !== -1) {
// next();
// } else {
// next(`/login?redirect=${to.path}`);
// NProgress.done();
// }
// }
// });


router.afterEach(() => {
NProgress.done();
});
// router.afterEach(() => {
// NProgress.done();
// });

+ 20
- 1
src/router/index.ts View File

@@ -78,7 +78,7 @@ export const constantRoutes: RouteRecordRaw[] = [
}, },
}, },
], ],
},// 修改密码
}, // 修改密码
{ {
path: "/", path: "/",
component: Layout, component: Layout,
@@ -116,6 +116,25 @@ export const constantRoutes: RouteRecordRaw[] = [
}, },
], ],
}, },
// 商店
{
path: "/",
component: Layout,
redirect: "/signSucceed",
children: [
{
path: "signSucceed",
component: () => import("@/views/signSucceed/index.vue"),
name: "signSucceed",
meta: {
title: "signSucceed",
icon: "homepage",
affix: true,
name: "signSucceed.title",
},
},
],
},
// { // {
// path: "/dashboard", // path: "/dashboard",
// component: Layout, // component: Layout,


+ 65
- 0
src/utils/request.js View File

@@ -0,0 +1,65 @@
import axios from 'axios'
import router from '@/router'
import { ElMessage } from 'element-plus'
ElMessage

/**
* @description:发送Axios请求
*/
const request = axios.create({
baseURL: '/api',
timeout: 5000
})

// 请求拦截器
request.interceptors.request.use(
function (config) {
// 给所有授权的请求提供token
const AccessToken = localStorage.getItem("AccessToken")
if (AccessToken) {
config.headers.token = AccessToken
}
return config
},
function (error) {
// 操作
return Promise.reject(error)
}
)

// 响应拦截器
request.interceptors.response.use(
function (response) {
let code = response.data.code
// 当token过期或损坏时
if (code == 1052) {
router.push("/login");
ElMessage.error("登录过期,请重新登录!");
return

// 弹出错误
} else if (code != 200) {
if (code == 1053) {
router.push("/login");
// Toast.fail("请您先登录!");
return

} else if (code == 500) {
ElMessage.error("系统异常,请稍后再试");

// 其他错误
} else {

return Promise.reject(response.data)
}
} else {
// 正常返回
return response.data
}

},
function (error) {
}
)

export default request

+ 12
- 12
src/utils/request.ts View File

@@ -1,11 +1,11 @@
import axios, { InternalAxiosRequestConfig, AxiosResponse } from 'axios';
import { useUserStoreHook } from '@/store/modules/user';
import axios, { InternalAxiosRequestConfig, AxiosResponse } from "axios";
import { useUserStoreHook } from "@/store/modules/user";


// 创建 axios 实例 // 创建 axios 实例
const service = axios.create({ const service = axios.create({
baseURL: import.meta.env.VITE_APP_BASE_API, baseURL: import.meta.env.VITE_APP_BASE_API,
timeout: 50000, timeout: 50000,
headers: { 'Content-Type': 'application/json;charset=utf-8' }
headers: { "Content-Type": "application/json;charset=utf-8" },
}); });


// 请求拦截器 // 请求拦截器
@@ -26,7 +26,7 @@ service.interceptors.request.use(
service.interceptors.response.use( service.interceptors.response.use(
(response: AxiosResponse) => { (response: AxiosResponse) => {
const { code, msg } = response.data; const { code, msg } = response.data;
if (code === '00000') {
if (code === "00000") {
return response.data; return response.data;
} }
// 响应数据为二进制流处理(Excel导出) // 响应数据为二进制流处理(Excel导出)
@@ -34,23 +34,23 @@ service.interceptors.response.use(
return response; return response;
} }


ElMessage.error(msg || '系统出错');
return Promise.reject(new Error(msg || 'Error'));
ElMessage.error(msg || "系统出错");
return Promise.reject(new Error(msg || "Error"));
}, },
(error: any) => { (error: any) => {
if (error.response.data) { if (error.response.data) {
const { code, msg } = error.response.data; const { code, msg } = error.response.data;
// token 过期,重新登录 // token 过期,重新登录
if (code === 'A0230') {
ElMessageBox.confirm('当前页面已失效,请重新登录', '提示', {
confirmButtonText: '确定',
type: 'warning'
if (code === "A0230") {
ElMessageBox.confirm("当前页面已失效,请重新登录", "提示", {
confirmButtonText: "确定",
type: "warning",
}).then(() => { }).then(() => {
localStorage.clear(); localStorage.clear();
window.location.href = '/';
window.location.href = "/";
}); });
} else { } else {
ElMessage.error(msg || '系统出错');
ElMessage.error(msg || "系统出错");
} }
} }
return Promise.reject(error.message); return Promise.reject(error.message);


+ 130
- 72
src/views/login/index.vue View File

@@ -2,7 +2,7 @@
<div class="login-container"> <div class="login-container">
<div class="videoBox"> <div class="videoBox">
<video <video
src="../../assets/video/loginVideo.mp4"
src="https://video.metavatar.cc/sv/4aaaaa5e-18832dbb5e6/4aaaaa5e-18832dbb5e6.mp4"
muted muted
autoplay autoplay
loop loop
@@ -15,7 +15,9 @@
class="login-form" class="login-form"
> >
<div class="flex text-white items-center py-4"> <div class="flex text-white items-center py-4">
<span class="text-2xl flex-1 text-center">{{ $t("login.title") }}</span>
<span class="text-2xl flex-1 text-center">{{
$t("login.title") + " " + $t("login.login")
}}</span>
<lang-select style="color: #fff" /> <lang-select style="color: #fff" />
</div> </div>


@@ -45,7 +47,7 @@
<el-input <el-input
class="flex-1" class="flex-1"
v-model="loginData.password" v-model="loginData.password"
placeholder="密码"
:placeholder="$t('login.password')"
:type="passwordVisible === false ? 'password' : 'input'" :type="passwordVisible === false ? 'password' : 'input'"
size="large" size="large"
name="password" name="password"
@@ -70,13 +72,13 @@
v-model="loginData.verifyCode" v-model="loginData.verifyCode"
auto-complete="off" auto-complete="off"
:placeholder="$t('login.verifyCode')" :placeholder="$t('login.verifyCode')"
class="w-[60%]"
class="flex-1"
@keyup.enter="handleLogin" @keyup.enter="handleLogin"
/> />


<div class="captcha">
<img :src="captchaBase64" @click="getCaptcha" />
</div>
<span class="captcha">
<img v-if="showCodeImg" :src="verifyCode" @click="getCode" />
</span>
</el-form-item> </el-form-item>


<el-button <el-button
@@ -85,11 +87,11 @@
type="primary" type="primary"
class="loginBtn" class="loginBtn"
@click.prevent="handleLogin" @click.prevent="handleLogin"
>{{ $t("login.login") }}
>{{ $t("login.loginBtn") }}
</el-button> </el-button>


<div :class="currentLan == 'zh-cn' ? 'bottomBtnCN' : 'bottomBtnEN'"> <div :class="currentLan == 'zh-cn' ? 'bottomBtnCN' : 'bottomBtnEN'">
<div style="margin-bottom: 5px">
<div style="margin-bottom: 5px" @click="loginFlag">
<span class="join">{{ $t("login.signUp") }}</span> <span class="join">{{ $t("login.signUp") }}</span>
</div> </div>
<div> <div>
@@ -105,7 +107,9 @@
class="login-form" class="login-form"
> >
<div class="flex text-white items-center py-4"> <div class="flex text-white items-center py-4">
<span class="text-2xl flex-1 text-center">{{ $t("login.title") }}</span>
<span class="text-2xl flex-1 text-center">{{
$t("login.title") + " " + $t("login.register")
}}</span>
<lang-select style="color: #fff" /> <lang-select style="color: #fff" />
</div> </div>


@@ -135,12 +139,12 @@
<el-input <el-input
class="flex-1" class="flex-1"
v-model="loginData.password" v-model="loginData.password"
placeholder="密码"
:placeholder="$t('login.password')"
:type="passwordVisible === false ? 'password' : 'input'" :type="passwordVisible === false ? 'password' : 'input'"
size="large" size="large"
name="password" name="password"
@keyup="checkCapslock" @keyup="checkCapslock"
@keyup.enter="handleLogin"
@keyup.enter="handleRegister"
/> />
<span class="mr-2" @click="passwordVisible = !passwordVisible"> <span class="mr-2" @click="passwordVisible = !passwordVisible">
<svg-icon <svg-icon
@@ -152,7 +156,7 @@
</el-tooltip> </el-tooltip>


<!-- 验证码 --> <!-- 验证码 -->
<el-form-item prop="verifyCode">
<el-form-item v-if="isLogin" prop="verifyCode">
<span class="p-2 text-white"> <span class="p-2 text-white">
<svg-icon icon-class="verify_code" /> <svg-icon icon-class="verify_code" />
</span> </span>
@@ -160,13 +164,13 @@
v-model="loginData.verifyCode" v-model="loginData.verifyCode"
auto-complete="off" auto-complete="off"
:placeholder="$t('login.verifyCode')" :placeholder="$t('login.verifyCode')"
class="w-[60%]"
@keyup.enter="handleLogin"
class="flex-1"
@keyup.enter="handleRegister"
/> />


<div class="captcha">
<img :src="captchaBase64" @click="getCaptcha" />
</div>
<span class="captcha">
<img v-if="showCodeImg" :src="verifyCode" @click="getCode" />
</span>
</el-form-item> </el-form-item>


<el-button <el-button
@@ -174,13 +178,13 @@
:loading="loading" :loading="loading"
type="primary" type="primary"
class="loginBtn" class="loginBtn"
@click.prevent="handleLogin"
>{{ $t("login.login") }}
@click.prevent="handleRegister"
>{{ $t("login.registerBtn") }}
</el-button> </el-button>


<div :class="currentLan == 'zh-cn' ? 'bottomBtnCN' : 'bottomBtnEN'"> <div :class="currentLan == 'zh-cn' ? 'bottomBtnCN' : 'bottomBtnEN'">
<div style="margin-bottom: 5px" @click="loginFlag"> <div style="margin-bottom: 5px" @click="loginFlag">
<span class="join">{{ $t("login.signUp") }}</span>
<span class="join">{{ $t("login.signIn") }}</span>
</div> </div>
<div> <div>
<span class="join">{{ $t("login.forgetPwd") }}</span> <span class="join">{{ $t("login.forgetPwd") }}</span>
@@ -191,16 +195,23 @@
</template> </template>


<script setup lang="ts"> <script setup lang="ts">
import router from "@/router";
import LangSelect from "@/components/LangSelect/index.vue"; import LangSelect from "@/components/LangSelect/index.vue";
import SvgIcon from "@/components/SvgIcon/index.vue"; import SvgIcon from "@/components/SvgIcon/index.vue";
import { register, getCodeImgUrl } from "@/apis/login";

import axios from "axios";


// 状态管理依赖 // 状态管理依赖
import { useUserStore } from "@/store/modules/user"; import { useUserStore } from "@/store/modules/user";


// API依赖 // API依赖
import { LocationQuery, LocationQueryValue, useRoute } from "vue-router";
import { getCaptchaApi } from "@/api/auth";
import {
LocationQuery,
LocationQueryValue,
useRoute,
useRouter,
} from "vue-router";

import { LoginData } from "@/api/auth/types"; import { LoginData } from "@/api/auth/types";


import { useI18n } from "vue-i18n"; import { useI18n } from "vue-i18n";
@@ -210,7 +221,7 @@ const currentLan = ref(locale);


const userStore = useUserStore(); const userStore = useUserStore();
const route = useRoute(); const route = useRoute();
const router = useRouter();
/** /**
* 按钮loading * 按钮loading
*/ */
@@ -229,21 +240,23 @@ const passwordVisible = ref(false);
/** /**
* 验证码图片Base64字符串 * 验证码图片Base64字符串
*/ */
const captchaBase64 = ref();
const verifyCode = ref();


/** /**
* 登录/注册 * 登录/注册
*/ */
const isLogin = ref(true); const isLogin = ref(true);


const showCodeImg = ref(true);
/** /**
* 登录表单引用 * 登录表单引用
*/ */
const loginFormRef = ref(ElForm); const loginFormRef = ref(ElForm);


const loginData = ref<LoginData>({
username: "admin",
password: "123456",
const loginData = ref({
username: "",
password: "",
verifyCode: "",
}); });


const loginRules = { const loginRules = {
@@ -256,7 +269,8 @@ const loginRules = {
* @description: 切换登录/注册状态 * @description: 切换登录/注册状态
*/ */
function loginFlag() { function loginFlag() {
isLogin.value = !isLogin;
isLogin.value = !isLogin.value;
passwordVisible.value = !isLogin.value;
console.log(isLogin.value, "isLogin.value"); console.log(isLogin.value, "isLogin.value");
} }


@@ -279,56 +293,100 @@ function checkCapslock(e: any) {
isCapslock.value = key && key.length === 1 && key >= "A" && key <= "Z"; isCapslock.value = key && key.length === 1 && key >= "A" && key <= "Z";
} }


/**
* 获取验证码
*/
function getCaptcha() {
getCaptchaApi().then(({ data }) => {
const { verifyCodeBase64, verifyCodeKey } = data;
loginData.value.verifyCodeKey = verifyCodeKey;
captchaBase64.value = verifyCodeBase64;
function handleLogin() {
router.push("/createVideo");
}

function handleRegister() {
const data = {
email: loginData.value.username,
password: loginData.value.password,
};
const emailReg =
/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;

if (!data.email) {
ElMessage.error("邮箱不能为空!");
return;
}

if (!data.password) {
ElMessage.error("密码不能为空!");
return;
}

if (!emailReg.test(data.email)) {
ElMessage.error("邮箱格式错误!");
return;
}
console.log(data);
doRegister(data);
}

function getCode() {
showCodeImg.value = false;
axios({
url: getCodeImgUrl,
method: "get",
}).then(() => {
verifyCode.value = getCodeImgUrl;
showCodeImg.value = true;
}); });
} }


/** /**
* 登录
* @description:注册
* @param {type} data
* @return: data
*/ */
function handleLogin() {
loginFormRef.value.validate((valid: boolean) => {
if (valid) {
loading.value = true;
userStore
.login(loginData.value)
.then(() => {
const query: LocationQuery = route.query;

const redirect = (query.redirect as LocationQueryValue) ?? "/";

const otherQueryParams = Object.keys(query).reduce(
(acc: any, cur: string) => {
if (cur !== "redirect") {
acc[cur] = query[cur];
}
return acc;
},
{}
);

router.push({ path: redirect, query: otherQueryParams });
})
.catch(() => {
// 验证失败,重新生成验证码
getCaptcha();
})
.finally(() => {
loading.value = false;
});
}
});
async function doRegister(data: object) {
try {
const res = await register(data);
console.log(res, "res");
} catch (error) {
console.log(error);
}
} }


// /**
// * 登录
// */
// function handleLogin() {
// loginFormRef.value.validate((valid: boolean) => {
// if (valid) {
// loading.value = true;
// userStore
// .login(loginData.value)
// .then(() => {
// const query: LocationQuery = route.query;

// const redirect = (query.redirect as LocationQueryValue) ?? "/";

// const otherQueryParams = Object.keys(query).reduce(
// (acc: any, cur: string) => {
// if (cur !== "redirect") {
// acc[cur] = query[cur];
// }
// return acc;
// },
// {}
// );

// router.push({ path: redirect, query: otherQueryParams });
// })
// .catch(() => {
// // 验证失败,重新生成验证码
// getCaptcha();
// })
// .finally(() => {
// loading.value = false;
// });
// }
// });
// }

onMounted(() => { onMounted(() => {
getCaptcha();
getCode();
}); });
</script> </script>




+ 2
- 2
src/views/redirect/index.vue View File

@@ -3,7 +3,7 @@
</template> </template>


<script setup lang="ts"> <script setup lang="ts">
import { useRoute, useRouter } from 'vue-router';
import { useRoute, useRouter } from "vue-router";


const route = useRoute(); const route = useRoute();
const router = useRouter(); const router = useRouter();
@@ -11,5 +11,5 @@ const router = useRouter();
const { params, query } = route; const { params, query } = route;
const { path } = params; const { path } = params;


router.replace({ path: '/' + path, query });
router.replace({ path: "/" + path, query });
</script> </script>

+ 15
- 0
src/views/signSucceed/index.vue View File

@@ -0,0 +1,15 @@
<template>
<div />
</template>

<script setup lang="ts">
import { useRoute, useRouter } from "vue-router";

const route = useRoute();
const router = useRouter();

const { params, query } = route;
const { path } = params;

console.log(query.ticket, "ticket");
</script>

+ 3
- 5
vite.config.ts View File

@@ -42,12 +42,10 @@ export default defineConfig(({ mode }: ConfigEnv): UserConfig => {
open: true, // 运行是否自动打开浏览器 open: true, // 运行是否自动打开浏览器
proxy: { proxy: {
// 反向代理解决跨域 // 反向代理解决跨域
[env.VITE_APP_BASE_API]: {
target: "http://vapi.youlai.tech", // 线上接口地址
// target: 'http://localhost:8989', // 本地接口地址
"/api": {
target: env.VITE_APP_BASE_API, // 线上接口地址
changeOrigin: true, changeOrigin: true,
rewrite: (path) =>
path.replace(new RegExp("^" + env.VITE_APP_BASE_API), ""), // 替换 /dev-api 为 target 接口地址
rewrite: (path) => path.replace(/^\/api/, ""),
}, },
}, },
}, },


+ 5533
- 5555
yarn.lock
File diff suppressed because it is too large
View File


Loading…
Cancel
Save