@@ -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' |
@@ -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' |
@@ -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", | "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" | ||||
} | |||||
} |
@@ -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: { | 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 !", | |||||
}, | |||||
}; | }; |
@@ -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: "注册成功!", | |||||
}, | |||||
}; | }; |
@@ -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}`); | |||||
// }); | |||||
}); | }); | ||||
} | } | ||||
@@ -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(); | |||||
// }); |
@@ -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, | ||||
@@ -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 实例 | // 创建 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); | ||||
@@ -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> | ||||
@@ -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> |
@@ -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, // 运行是否自动打开浏览器 | 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/, ""), | |||||
}, | }, | ||||
}, | }, | ||||
}, | }, | ||||