| @@ -5,4 +5,4 @@ NODE_ENV='development' | |||
| VITE_APP_TITLE = 'Metavatar-PC' | |||
| VITE_APP_PORT = 3000 | |||
| VITE_APP_BASE_API = '/dev-api' | |||
| VITE_APP_BASE_API = 'https://photo.metavatar.cc/C' | |||
| @@ -2,4 +2,4 @@ | |||
| VITE_APP_TITLE = 'Metavatar-PC' | |||
| VITE_APP_PORT = 3000 | |||
| VITE_APP_BASE_API = '/prod-api' | |||
| VITE_APP_BASE_API = 'https://photo.metavatar.cc/C' | |||
| @@ -1,6 +0,0 @@ | |||
| ## 模拟环境 | |||
| NODE_ENV='staging' | |||
| VITE_APP_TITLE = 'vue3-element-admin' | |||
| VITE_APP_PORT = 3000 | |||
| VITE_APP_BASE_API = '/prod--api' | |||
| @@ -27,7 +27,7 @@ | |||
| "screenfull": "^6.0.0", | |||
| "vue": "^3.2.45", | |||
| "vue-i18n": "9", | |||
| "vue-router": "^4.1.6" | |||
| "vue-router": "^4.0.13" | |||
| }, | |||
| "devDependencies": { | |||
| "@commitlint/cli": "^17.5.1", | |||
| @@ -71,4 +71,4 @@ | |||
| "repository": "https://gitee.com/youlaiorg/vue3-element-admin.git", | |||
| "author": "有来开源组织", | |||
| "license": "MIT" | |||
| } | |||
| } | |||
| @@ -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' | |||
| @@ -7,11 +7,15 @@ export default { | |||
| // 登录页面国际化 | |||
| login: { | |||
| title: "Metavatar-PC Sign in", | |||
| title: "Metavatar-PC", | |||
| username: "Username", | |||
| password: "Password", | |||
| login: "Sign in", | |||
| register: "Sign up", | |||
| loginBtn: "Sign in", | |||
| registerBtn: "Sign up", | |||
| verifyCode: "Verify Code", | |||
| signIn: "Already got an account? Sign in here", | |||
| signUp: "Don't have an account? Sign up here", | |||
| forgetPwd: "I forgot my password", | |||
| }, | |||
| @@ -79,4 +83,7 @@ export default { | |||
| WeChatPay: "WeChatPay", | |||
| Alipay: "Alipay", | |||
| }, | |||
| signSucceed: { | |||
| title: "Sign Succeed !", | |||
| }, | |||
| }; | |||
| @@ -7,11 +7,15 @@ export default { | |||
| // 登录页面国际化 | |||
| login: { | |||
| title: "Metavatar-PC 登录", | |||
| title: "Metavatar-PC", | |||
| username: "用户名", | |||
| password: "密码", | |||
| login: "登 录", | |||
| login: "登录", | |||
| register: "注册", | |||
| loginBtn: "登 录", | |||
| registerBtn: "注 册", | |||
| verifyCode: "验证码", | |||
| signIn: "已有账号?现在登录!", | |||
| signUp: "没有账号?现在加入!", | |||
| forgetPwd: "忘记密码", | |||
| }, | |||
| @@ -79,4 +83,7 @@ export default { | |||
| WeChatPay: "微信支付", | |||
| Alipay: "支付宝支付", | |||
| }, | |||
| signSucceed: { | |||
| title: "注册成功!", | |||
| }, | |||
| }; | |||
| @@ -123,14 +123,15 @@ function logout() { | |||
| confirmButtonText: confirm, | |||
| cancelButtonText: cancel, | |||
| }).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}`); | |||
| // }); | |||
| }); | |||
| } | |||
| @@ -11,51 +11,51 @@ const permissionStore = usePermissionStoreHook(); | |||
| // 白名单路由 | |||
| 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(); | |||
| // }); | |||
| @@ -78,7 +78,7 @@ export const constantRoutes: RouteRecordRaw[] = [ | |||
| }, | |||
| }, | |||
| ], | |||
| },// 修改密码 | |||
| }, // 修改密码 | |||
| { | |||
| path: "/", | |||
| 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", | |||
| // component: Layout, | |||
| @@ -5,7 +5,6 @@ declare global { | |||
| const ElForm: typeof import('element-plus/es')['ElForm'] | |||
| const ElMessage: typeof import('element-plus/es')['ElMessage'] | |||
| const ElMessageBox: typeof import('element-plus/es')['ElMessageBox'] | |||
| const ElTree: typeof import('element-plus/es')['ElTree'] | |||
| const asyncComputed: typeof import('@vueuse/core')['asyncComputed'] | |||
| const autoResetRef: typeof import('@vueuse/core')['autoResetRef'] | |||
| const computed: typeof import('vue')['computed'] | |||
| @@ -275,7 +274,6 @@ declare module 'vue' { | |||
| readonly ElForm: UnwrapRef<typeof import('element-plus/es')['ElForm']> | |||
| readonly ElMessage: UnwrapRef<typeof import('element-plus/es')['ElMessage']> | |||
| readonly ElMessageBox: UnwrapRef<typeof import('element-plus/es')['ElMessageBox']> | |||
| readonly ElTree: UnwrapRef<typeof import('element-plus/es')['ElTree']> | |||
| readonly asyncComputed: UnwrapRef<typeof import('@vueuse/core')['asyncComputed']> | |||
| readonly autoResetRef: UnwrapRef<typeof import('@vueuse/core')['autoResetRef']> | |||
| readonly computed: UnwrapRef<typeof import('vue')['computed']> | |||
| @@ -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 | |||
| @@ -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 实例 | |||
| const service = axios.create({ | |||
| baseURL: import.meta.env.VITE_APP_BASE_API, | |||
| 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( | |||
| (response: AxiosResponse) => { | |||
| const { code, msg } = response.data; | |||
| if (code === '00000') { | |||
| if (code === "00000") { | |||
| return response.data; | |||
| } | |||
| // 响应数据为二进制流处理(Excel导出) | |||
| @@ -34,23 +34,23 @@ service.interceptors.response.use( | |||
| return response; | |||
| } | |||
| ElMessage.error(msg || '系统出错'); | |||
| return Promise.reject(new Error(msg || 'Error')); | |||
| ElMessage.error(msg || "系统出错"); | |||
| return Promise.reject(new Error(msg || "Error")); | |||
| }, | |||
| (error: any) => { | |||
| if (error.response.data) { | |||
| const { code, msg } = error.response.data; | |||
| // token 过期,重新登录 | |||
| if (code === 'A0230') { | |||
| ElMessageBox.confirm('当前页面已失效,请重新登录', '提示', { | |||
| confirmButtonText: '确定', | |||
| type: 'warning' | |||
| if (code === "A0230") { | |||
| ElMessageBox.confirm("当前页面已失效,请重新登录", "提示", { | |||
| confirmButtonText: "确定", | |||
| type: "warning", | |||
| }).then(() => { | |||
| localStorage.clear(); | |||
| window.location.href = '/'; | |||
| window.location.href = "/"; | |||
| }); | |||
| } else { | |||
| ElMessage.error(msg || '系统出错'); | |||
| ElMessage.error(msg || "系统出错"); | |||
| } | |||
| } | |||
| return Promise.reject(error.message); | |||
| @@ -2,7 +2,7 @@ | |||
| <div class="login-container"> | |||
| <div class="videoBox"> | |||
| <video | |||
| src="../../assets/video/loginVideo.mp4" | |||
| src="https://video.metavatar.cc/sv/4aaaaa5e-18832dbb5e6/4aaaaa5e-18832dbb5e6.mp4" | |||
| muted | |||
| autoplay | |||
| loop | |||
| @@ -15,7 +15,9 @@ | |||
| class="login-form" | |||
| > | |||
| <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" /> | |||
| </div> | |||
| @@ -45,7 +47,7 @@ | |||
| <el-input | |||
| class="flex-1" | |||
| v-model="loginData.password" | |||
| placeholder="密码" | |||
| :placeholder="$t('login.password')" | |||
| :type="passwordVisible === false ? 'password' : 'input'" | |||
| size="large" | |||
| name="password" | |||
| @@ -70,13 +72,13 @@ | |||
| v-model="loginData.verifyCode" | |||
| auto-complete="off" | |||
| :placeholder="$t('login.verifyCode')" | |||
| class="w-[60%]" | |||
| class="flex-1" | |||
| @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-button | |||
| @@ -85,11 +87,11 @@ | |||
| type="primary" | |||
| class="loginBtn" | |||
| @click.prevent="handleLogin" | |||
| >{{ $t("login.login") }} | |||
| >{{ $t("login.loginBtn") }} | |||
| </el-button> | |||
| <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> | |||
| </div> | |||
| <div> | |||
| @@ -105,7 +107,9 @@ | |||
| class="login-form" | |||
| > | |||
| <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" /> | |||
| </div> | |||
| @@ -135,12 +139,12 @@ | |||
| <el-input | |||
| class="flex-1" | |||
| v-model="loginData.password" | |||
| placeholder="密码" | |||
| :placeholder="$t('login.password')" | |||
| :type="passwordVisible === false ? 'password' : 'input'" | |||
| size="large" | |||
| name="password" | |||
| @keyup="checkCapslock" | |||
| @keyup.enter="handleLogin" | |||
| @keyup.enter="handleRegister" | |||
| /> | |||
| <span class="mr-2" @click="passwordVisible = !passwordVisible"> | |||
| <svg-icon | |||
| @@ -152,7 +156,7 @@ | |||
| </el-tooltip> | |||
| <!-- 验证码 --> | |||
| <el-form-item prop="verifyCode"> | |||
| <el-form-item v-if="isLogin" prop="verifyCode"> | |||
| <span class="p-2 text-white"> | |||
| <svg-icon icon-class="verify_code" /> | |||
| </span> | |||
| @@ -160,13 +164,13 @@ | |||
| v-model="loginData.verifyCode" | |||
| auto-complete="off" | |||
| :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-button | |||
| @@ -174,13 +178,13 @@ | |||
| :loading="loading" | |||
| type="primary" | |||
| class="loginBtn" | |||
| @click.prevent="handleLogin" | |||
| >{{ $t("login.login") }} | |||
| @click.prevent="handleRegister" | |||
| >{{ $t("login.registerBtn") }} | |||
| </el-button> | |||
| <div :class="currentLan == 'zh-cn' ? 'bottomBtnCN' : 'bottomBtnEN'"> | |||
| <div style="margin-bottom: 5px" @click="loginFlag"> | |||
| <span class="join">{{ $t("login.signUp") }}</span> | |||
| <span class="join">{{ $t("login.signIn") }}</span> | |||
| </div> | |||
| <div> | |||
| <span class="join">{{ $t("login.forgetPwd") }}</span> | |||
| @@ -191,16 +195,23 @@ | |||
| </template> | |||
| <script setup lang="ts"> | |||
| import router from "@/router"; | |||
| import LangSelect from "@/components/LangSelect/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"; | |||
| // 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 { useI18n } from "vue-i18n"; | |||
| @@ -210,7 +221,7 @@ const currentLan = ref(locale); | |||
| const userStore = useUserStore(); | |||
| const route = useRoute(); | |||
| const router = useRouter(); | |||
| /** | |||
| * 按钮loading | |||
| */ | |||
| @@ -229,21 +240,23 @@ const passwordVisible = ref(false); | |||
| /** | |||
| * 验证码图片Base64字符串 | |||
| */ | |||
| const captchaBase64 = ref(); | |||
| const verifyCode = ref(); | |||
| /** | |||
| * 登录/注册 | |||
| */ | |||
| const isLogin = ref(true); | |||
| const showCodeImg = ref(true); | |||
| /** | |||
| * 登录表单引用 | |||
| */ | |||
| const loginFormRef = ref(ElForm); | |||
| const loginData = ref<LoginData>({ | |||
| username: "admin", | |||
| password: "123456", | |||
| const loginData = ref({ | |||
| username: "", | |||
| password: "", | |||
| verifyCode: "", | |||
| }); | |||
| const loginRules = { | |||
| @@ -256,7 +269,8 @@ const loginRules = { | |||
| * @description: 切换登录/注册状态 | |||
| */ | |||
| function loginFlag() { | |||
| isLogin.value = !isLogin; | |||
| isLogin.value = !isLogin.value; | |||
| passwordVisible.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"; | |||
| } | |||
| /** | |||
| * 获取验证码 | |||
| */ | |||
| 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(() => { | |||
| getCaptcha(); | |||
| getCode(); | |||
| }); | |||
| </script> | |||
| @@ -3,7 +3,7 @@ | |||
| </template> | |||
| <script setup lang="ts"> | |||
| import { useRoute, useRouter } from 'vue-router'; | |||
| import { useRoute, useRouter } from "vue-router"; | |||
| const route = useRoute(); | |||
| const router = useRouter(); | |||
| @@ -11,5 +11,5 @@ const router = useRouter(); | |||
| const { params, query } = route; | |||
| const { path } = params; | |||
| router.replace({ path: '/' + path, query }); | |||
| router.replace({ path: "/" + path, query }); | |||
| </script> | |||
| @@ -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> | |||
| @@ -42,12 +42,10 @@ export default defineConfig(({ mode }: ConfigEnv): UserConfig => { | |||
| open: true, // 运行是否自动打开浏览器 | |||
| proxy: { | |||
| // 反向代理解决跨域 | |||
| [env.VITE_APP_BASE_API]: { | |||
| target: "http://vapi.youlai.tech", // 线上接口地址 | |||
| // target: 'http://localhost:8989', // 本地接口地址 | |||
| "/api": { | |||
| target: env.VITE_APP_BASE_API, // 线上接口地址 | |||
| changeOrigin: true, | |||
| rewrite: (path) => | |||
| path.replace(new RegExp("^" + env.VITE_APP_BASE_API), ""), // 替换 /dev-api 为 target 接口地址 | |||
| rewrite: (path) => path.replace(/^\/api/, ""), | |||
| }, | |||
| }, | |||
| }, | |||