@@ -0,0 +1,97 @@ | |||
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 登录 | |||
* @params email,password,code | |||
* @returns data | |||
*/ | |||
export function login(data) { | |||
return request({ | |||
url: `/api/user/loginByEmail`, | |||
method: 'post', | |||
data | |||
}) | |||
} | |||
/** | |||
/** | |||
* @description:重新发送邮件 | |||
* @param {string} data | |||
* @return: data | |||
*/ | |||
export function sendRegisterEmail(email) { | |||
return request({ | |||
url: `/api/user/sendRegisterEmail`, | |||
method: 'post', | |||
data: { | |||
} | |||
}) | |||
} | |||
/** | |||
/** | |||
* @description:忘记密码发送邮件 | |||
* @param {string} data | |||
* @return: data | |||
*/ | |||
export function sendUpdPwdEmailApi(email) { | |||
return request({ | |||
url: `/api/user/sendUpdPwdEmail`, | |||
method: 'post', | |||
data: { | |||
} | |||
}) | |||
} | |||
/** | |||
/** | |||
* @description:邮件重置密码, | |||
* @param pwd, ticket | |||
* @return: data | |||
*/ | |||
export function resetPwdEmailApi(data) { | |||
return request({ | |||
url: `/api/user/doUpdPass`, | |||
method: 'post', | |||
data | |||
}) | |||
} | |||
/** | |||
/** | |||
* @description:邮件重置密码, | |||
* @param oldpwd, newpwd | |||
* @return: data | |||
*/ | |||
export function resetPwdFormApi(data) { | |||
return request({ | |||
url: `/api/user/oldUpdPass`, | |||
method: 'post', | |||
data | |||
}) | |||
} | |||
/** | |||
* @description:获取图形验证码 | |||
* @return: 验证码地址 | |||
*/ | |||
export const getCodeImgUrl = baseURL + '/api/user/captcha.jpg' | |||
@@ -9,7 +9,8 @@ const baseURL = import.meta.env.VITE_APP_BASE_API | |||
*/ | |||
export function register(data) { | |||
return request({ | |||
url: `/api/user/doRegisterByEmail`, | |||
// url: `/api/user/doRegisterByEmail`, | |||
url: `/api/user/doRegisterByPhone`, | |||
method: 'post', | |||
data | |||
}) | |||
@@ -22,7 +23,8 @@ export function register(data) { | |||
*/ | |||
export function login(data) { | |||
return request({ | |||
url: `/api/user/loginByEmail`, | |||
// url: `/api/user/loginByEmail`, | |||
url: `/api/user/login`, | |||
method: 'post', | |||
data | |||
}) | |||
@@ -50,16 +52,41 @@ export function sendRegisterEmail(email) { | |||
* @param {string} data | |||
* @return: data | |||
*/ | |||
export function sendUpdPwdEmailApi(email) { | |||
// export function sendUpdPwdEmailApi(email) { | |||
// return request({ | |||
// url: `/api/user/sendUpdPwdEmail`, | |||
// method: 'post', | |||
// data: { | |||
// } | |||
// }) | |||
// } | |||
/**`/api/user/sendLoginPhoneCode?phone=${phone}` | |||
* @description 忘记密码第一步,根据图片验证码和手机号获取短信 | |||
* @param {object} loginParams (phone,code) | |||
* @returns data | |||
*/ | |||
export function sendUpdPwdEmailApi(data) { | |||
return request({ | |||
url: `/api/user/sendPhoneCode?phone=${data.phone}&code=${data.code}`, | |||
method: 'get', | |||
}) | |||
} | |||
/**`/api/user/sendLoginPhoneCode?phone=${phone}` | |||
* @description 忘记密码第二步,短信验证码和新密码 | |||
* @param {object} loginParams (phone,code,pwd) | |||
* @returns data | |||
*/ | |||
export function doUpdPassApi(loginParams) { | |||
return request({ | |||
url: `/api/user/sendUpdPwdEmail`, | |||
url: `/api/user/updPass`, | |||
method: 'post', | |||
data: { | |||
} | |||
data: loginParams | |||
}) | |||
} | |||
/** | |||
/** | |||
* @description:邮件重置密码, | |||
@@ -1,7 +1,7 @@ | |||
<template> | |||
<el-dropdown class="outSide" trigger="click" @command="handleLanguageChange"> | |||
<div> | |||
<svg-icon icon-class="language" /> | |||
<svg-icon icon-class="language" style="color: #fff" /> | |||
</div> | |||
<template #dropdown> | |||
<el-dropdown-menu> | |||
@@ -15,7 +15,7 @@ export default { | |||
login: { | |||
title: "Metavatar-PC", | |||
username: "Username", | |||
email: "E-mail", | |||
email: "Phone", | |||
password: "Password", | |||
confirmPassword: "Confirm password", | |||
login: "Sign in", | |||
@@ -27,14 +27,15 @@ export default { | |||
signUp: "Don't have an account? Sign up here", | |||
forgetPwd: "I forgot my password", | |||
forgetPwdTitle:'Forgot password', | |||
SendEmail:'Send an email', | |||
SendEmail:'Send SMS Code', | |||
resetPassword:'Reset password', | |||
setNewPwd:'Set new password', | |||
newPwd:'New password', | |||
oldPwd:'Old password', | |||
confirmNewPwd:'Confirm new password', | |||
confirm:'Confirm', | |||
gohome:'Back to home page' | |||
gohome:'Back to home page', | |||
SMSCode:'SMS Code' | |||
}, | |||
// 导航栏国际化 | |||
@@ -15,7 +15,7 @@ export default { | |||
login: { | |||
title: "Metavatar-PC", | |||
username: "用户名", | |||
email: "电子邮件", | |||
email: "手机号", | |||
password: "密码", | |||
confirmPassword: "确认密码", | |||
login: "登录", | |||
@@ -27,14 +27,15 @@ export default { | |||
signUp: "没有账号?现在加入!", | |||
forgetPwd: "忘记密码", | |||
forgetPwdTitle:'忘记密码', | |||
SendEmail:'发送邮件', | |||
SendEmail:'发送短信验证码', | |||
resetPassword:'重置密码', | |||
setNewPwd:'设置新密码', | |||
newPwd:'新密码', | |||
oldPwd:'旧密码', | |||
confirmNewPwd:'确认新密码', | |||
confirm:'确定', | |||
gohome:'回到首页' | |||
gohome:'回到首页', | |||
SMSCode:'短信验证码', | |||
}, | |||
// 导航栏国际化 | |||
@@ -1,25 +1,52 @@ | |||
<template> | |||
<div :class="classObj" class="app-wrapper"> | |||
<!-- 手机设备侧边栏打开遮罩层 --> | |||
<div | |||
v-if="classObj.mobile && classObj.openSidebar" | |||
class="drawer-bg" | |||
@click="handleOutsideClick" | |||
></div> | |||
<Sidebar class="sidebar-container" /> | |||
<div :class="{ hasTagsView: showTagsView }" class="main-container"> | |||
<div | |||
:class="{ 'fixed-header': fixedHeader }" | |||
style="box-shadow: rgba(0, 0, 0, 0.05) 0px 4px 4px; height: 80px" | |||
> | |||
<navbar /> | |||
<tags-view v-if="showTagsView" /> | |||
<div class="app-wrapper"> | |||
<!-- 侧边栏 --> | |||
<div class="Sidebar"> | |||
<div class="imgBox"> | |||
<img | |||
class="boxCentreImg" | |||
src="../assets//img/left-top-logo.png" | |||
alt="" | |||
/> | |||
</div> | |||
<!-- 侧边路由列表 --> | |||
<div class="myRouter"> | |||
<div class="myRouter-item" @click="router.push('/createVideo')"> | |||
<div class="icon"> | |||
<el-icon><i-ep-edit /></el-icon> | |||
</div> | |||
{{ $t("createVideo.title") }} | |||
</div> | |||
<div class="myRouter-item" @click="router.push('/moveImg')"> | |||
<div class="icon"> | |||
<el-icon><i-ep-edit /></el-icon> | |||
</div> | |||
{{ $t("createVideo.title") }} | |||
</div> | |||
</div> | |||
</div> | |||
<!-- 右边显示部分 --> | |||
<div class="rightBox"> | |||
<!-- nav栏 --> | |||
<div class="nav"> | |||
<!-- 语言 --> | |||
<lang-select class="navItem" /> | |||
<!-- 登录 --> | |||
<div class="navItem" v-if="!AccessToken" @click="router.push('login')"> | |||
{{ $t("navbar.goLogin") }} | |||
</div> | |||
<!-- 注销 --> | |||
<div | |||
class="navItem" | |||
v-if="AccessToken" | |||
@click="logout" | |||
style="margin-left: 10px" | |||
> | |||
{{ $t("navbar.logout") }} | |||
</div> | |||
</div> | |||
<!-- 主页面 --> | |||
<app-main /> | |||
<app-main style="background-color: #000" /> | |||
</div> | |||
</div> | |||
</template> | |||
@@ -28,16 +55,41 @@ | |||
import { computed, watchEffect } from "vue"; | |||
import { useWindowSize } from "@vueuse/core"; | |||
import { AppMain, Navbar } from "./components/index"; | |||
import SignSucceed from "../views/signSucceed/index.vue"; | |||
import Sidebar from "./components/Sidebar/index.vue"; | |||
import LangSelect from "@/components/LangSelect/index.vue"; | |||
import { useAppStore } from "@/store/modules/app"; | |||
import { useSettingsStore } from "@/store/modules/settings"; | |||
// import { useSettingsStore } from "@/store/modules/settings"; | |||
import { useRoute, useRouter } from "vue-router"; | |||
import { useI18n } from "vue-i18n"; | |||
import { userInfoModules } from "@/store/modules/userInfo"; | |||
const userInfoPinia = userInfoModules(); | |||
const route = useRoute(); | |||
const router = useRouter(); | |||
const { params } = route; | |||
const { width } = useWindowSize(); | |||
const AccessToken = localStorage.getItem("AccessToken"); | |||
// 当前语言状态与国际化组件 | |||
const { locale } = useI18n(); | |||
const lanChange = ref(locale); | |||
function logout() { | |||
const msg = | |||
(lanChange.value as string) == "zh-cn" | |||
? "确定退出登录吗?" | |||
: "Are you sure to log out?"; | |||
const notice = (lanChange.value as string) == "zh-cn" ? "提示" : "Notice"; | |||
const confirm = (lanChange.value as string) == "zh-cn" ? "确定" : "Confirm"; | |||
const cancel = (lanChange.value as string) == "zh-cn" ? "取消" : "Cancel"; | |||
ElMessageBox.confirm(msg, notice, { | |||
confirmButtonText: confirm, | |||
cancelButtonText: cancel, | |||
}).then(() => { | |||
userInfoPinia.loginOut(); | |||
router.push(`/login`); | |||
localStorage.removeItem("AccessToken"); | |||
}); | |||
} | |||
/** | |||
* 响应式布局容器固定宽度 | |||
* | |||
@@ -48,18 +100,7 @@ const { width } = useWindowSize(); | |||
const WIDTH = 992; | |||
const appStore = useAppStore(); | |||
const settingsStore = useSettingsStore(); | |||
const fixedHeader = computed(() => settingsStore.fixedHeader); | |||
const showTagsView = computed(() => settingsStore.tagsView); | |||
const showSettings = computed(() => settingsStore.showSettings); | |||
const classObj = computed(() => ({ | |||
hideSidebar: !appStore.sidebar.opened, | |||
openSidebar: appStore.sidebar.opened, | |||
withoutAnimation: appStore.sidebar.withoutAnimation, | |||
mobile: appStore.device === "mobile", | |||
})); | |||
// const settingsStore = useSettingsStore(); | |||
watchEffect(() => { | |||
if (width.value < WIDTH) { | |||
@@ -84,48 +125,109 @@ function handleOutsideClick() { | |||
onMounted(() => {}); | |||
</script> | |||
<!-- 新样式 --> | |||
<style lang="scss" scoped> | |||
.app-wrapper { | |||
&::after { | |||
display: table; | |||
clear: both; | |||
content: ""; | |||
width: 1920px; | |||
display: flex; | |||
} | |||
.Sidebar { | |||
width: 230px; | |||
background-color: #000; | |||
height: 100vh; | |||
color: #fff; | |||
.imgBox { | |||
width: 100%; | |||
height: 80px; | |||
position: relative; | |||
img { | |||
max-width: 80%; | |||
max-height: 80%; | |||
} | |||
} | |||
.myRouter { | |||
position: relative; | |||
height: calc(100% - 80px); | |||
padding: 200px 20px 0; | |||
color: #fff; | |||
// color: #868593; | |||
&-item { | |||
display: flex; | |||
width: 100%; | |||
height: 50px; | |||
padding-left: 10px; | |||
font-size: 20px; | |||
font-weight: 500; | |||
line-height: 50px; | |||
text-align: center; | |||
cursor: pointer; | |||
// border-bottom: 2px solid #fff; | |||
transition: all 0.3s; | |||
border-radius: 5px; | |||
margin-bottom: 20px; | |||
margin-right: 20px; | |||
.icon { | |||
width: 40px; | |||
height: 40px; | |||
color: #fff; | |||
border-radius: 50%; | |||
.el-icon { | |||
width: 25px; | |||
height: 25px; | |||
font-size: 25px; | |||
// color: #797a9f; | |||
color: #fff; | |||
text-align: center; | |||
vertical-align: sub; | |||
} | |||
} | |||
&:hover { | |||
// background: rgba(255, 255, 255, 0.2); | |||
color: #000; | |||
background: #fff; | |||
.el-icon { | |||
// color: #d4d0ff; | |||
color: #000; | |||
} | |||
} | |||
} | |||
position: relative; | |||
width: 100%; | |||
height: 100%; | |||
e &.mobile.openSidebar { | |||
position: fixed; | |||
top: 0; | |||
.pricing { | |||
position: absolute; | |||
bottom: 60px; | |||
width: calc(100% - 40px); | |||
text-align: center; | |||
} | |||
.API { | |||
position: absolute; | |||
bottom: 0px; | |||
width: calc(100% - 40px); | |||
text-align: center; | |||
} | |||
} | |||
} | |||
.fixed-header { | |||
position: fixed; | |||
top: 0; | |||
right: 0; | |||
z-index: 9; | |||
width: calc(100% - #{$sideBarWidth}); | |||
transition: width 0.28s; | |||
} | |||
.hideSidebar .fixed-header { | |||
width: calc(100% - 54px); | |||
} | |||
.mobile .fixed-header { | |||
width: 100%; | |||
} | |||
.drawer-bg { | |||
position: absolute; | |||
top: 0; | |||
z-index: 999; | |||
width: 100%; | |||
height: 100%; | |||
// background: #1b213a; | |||
background: #000; | |||
opacity: 0.3; | |||
.rightBox { | |||
width: 1690px; | |||
// background-color: #000; | |||
.nav { | |||
display: flex; | |||
justify-content: flex-end; | |||
align-items: center; | |||
margin-right: 20px; | |||
width: 100%; | |||
height: 80px; | |||
background-color: #000; | |||
padding: 30px; | |||
// padding: 30px 30px 0 1500px; | |||
color: #fff; | |||
.navItem { | |||
font-size: 16px; | |||
margin-right: 30px; | |||
} | |||
} | |||
} | |||
</style> |
@@ -1,5 +1,6 @@ | |||
body { | |||
font-family: Arial, Microsoft YaHei, 黑体, 宋体, sans-serif; | |||
font-size: 14px; | |||
} | |||
.inmiddle { | |||
@@ -2,6 +2,7 @@ | |||
export {} | |||
declare global { | |||
const EffectScope: typeof import('vue')['EffectScope'] | |||
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 asyncComputed: typeof import('@vueuse/core')['asyncComputed'] | |||
@@ -270,6 +271,7 @@ import { UnwrapRef } from 'vue' | |||
declare module 'vue' { | |||
interface ComponentCustomProperties { | |||
readonly EffectScope: UnwrapRef<typeof import('vue')['EffectScope']> | |||
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 asyncComputed: UnwrapRef<typeof import('@vueuse/core')['asyncComputed']> | |||
@@ -24,6 +24,7 @@ declare module '@vue/runtime-core' { | |||
ElSelect: typeof import('element-plus/es')['ElSelect'] | |||
ElTabPane: typeof import('element-plus/es')['ElTabPane'] | |||
ElTabs: typeof import('element-plus/es')['ElTabs'] | |||
ElTooltip: typeof import('element-plus/es')['ElTooltip'] | |||
GithubCorner: typeof import('./../components/GithubCorner/index.vue')['default'] | |||
Hamburger: typeof import('./../components/Hamburger/index.vue')['default'] | |||
IconSelect: typeof import('./../components/IconSelect/index.vue')['default'] | |||
@@ -6,8 +6,23 @@ | |||
<div class="left"> | |||
<!-- 选择模版弹出框 --> | |||
<div class="chooseModelBox" :class="showChooseModel ? '' : 'noModel'"> | |||
<!-- 箭头 --> | |||
<!-- 伸缩按钮 --> | |||
<div | |||
v-if="showChooseModel && videoType" | |||
class="shrinkBtn" | |||
@click="showChooseModel = false" | |||
> | |||
> | |||
</div> | |||
<div | |||
v-if="!showChooseModel" | |||
class="shrinkBtn" | |||
@click="showChooseModel = true" | |||
> | |||
< | |||
</div> | |||
<!-- 箭头 --> | |||
<!-- <div | |||
v-if="showChooseModel && videoType" | |||
class="openChooseModel" | |||
@click="showChooseModel = false" | |||
@@ -20,8 +35,9 @@ | |||
@click="showChooseModel = true" | |||
> | |||
<img src="../../assets/img/arrowRight.png" alt="" /> | |||
</div> | |||
</div> --> | |||
<!-- tab栏 --> | |||
<p>性别</p> | |||
<div class="tab" v-show="showChooseModel"> | |||
<div | |||
class="tabItem" | |||
@@ -45,6 +61,30 @@ | |||
女性 | |||
</div> | |||
</div> | |||
<p>视频比例</p> | |||
<div class="tab" v-show="showChooseModel"> | |||
<div | |||
class="tabItem" | |||
:class="modelTabItemActive2 == 0 ? 'tabItemActive' : ''" | |||
@click="changeTabVideoType(0)" | |||
> | |||
全部 | |||
</div> | |||
<div | |||
class="tabItem" | |||
:class="modelTabItemActive2 == 2 ? 'tabItemActive' : ''" | |||
@click="changeTabVideoType(2)" | |||
> | |||
横屏 | |||
</div> | |||
<div | |||
class="tabItem" | |||
:class="modelTabItemActive2 == 1 ? 'tabItemActive' : ''" | |||
@click="changeTabVideoType(1)" | |||
> | |||
竖屏 | |||
</div> | |||
</div> | |||
<!-- 模版列表 --> | |||
<div | |||
class="modeListBox" | |||
@@ -296,19 +336,32 @@ const lanChange = ref(locale); | |||
const AccessToken = localStorage.getItem("AccessToken"); // 判断有没有登录 | |||
//#region 选择模版弹出框 | |||
const videoType = ref(null); //判断横屏2还是竖屏1 | |||
const videoType = ref(null); //判断横屏2还是竖屏1,初始为没有,控制按钮显隐 | |||
const showChooseModel = ref(true); // 控制弹窗显示隐藏 | |||
const modeList = ref([]); //模版列表 | |||
const modelImg = ref(null); //模版回显图 | |||
const modelTabItemActive = ref(0); //模版tab栏 | |||
const modelTabItemActive = ref(0); //模版tab栏 性别 | |||
const modelTabItemActive2 = ref(0); //模版tab栏 比例 | |||
const modelPageNum = ref(1); | |||
const modelPageSize = ref(20); | |||
const overLoadModel = ref(true); //禁用模版加载更多 | |||
const modelId = ref(null); // 选中模版的id | |||
// 获取模版列表 | |||
async function getModeList(sex, pageNum, pageSize) { | |||
const res = await modeListApi(sex, pageNum, pageSize); | |||
modeList.value = res.data.list; | |||
let sexx = null; | |||
if (sex == 0) { | |||
sexx = ""; | |||
} else { | |||
sexx = sex; | |||
} | |||
const res = await modeListApi(sexx, pageNum, pageSize); | |||
if (tabVideoType.value == 0) { | |||
modeList.value = res.data.list; | |||
} else { | |||
modeList.value = res.data.list.filter( | |||
(item) => item.videoType == tabVideoType.value | |||
); | |||
} | |||
overLoadModel.value = false; | |||
} | |||
// 点击模版 | |||
@@ -318,18 +371,45 @@ function clickModelItem(item) { | |||
videoType.value = item.videoType; | |||
modelId.value = item.id; | |||
} | |||
// tab栏切换 | |||
// tab栏切换 性别 | |||
// tab栏切换 横竖比例 videoType==1为竖,==2为横 | |||
const tabSex = ref(0); | |||
const tabVideoType = ref(0); | |||
function changeTabSex(index) { | |||
modeList.value = []; | |||
modelPageNum.value = 1; | |||
modelTabItemActive.value = index; | |||
overLoadModel.value = false; | |||
if (index == 0) { | |||
getModeList("", modelPageNum.value, modelPageSize.value); | |||
} else { | |||
getModeList(index, modelPageNum.value, modelPageSize.value); | |||
} | |||
tabSex.value = index; | |||
getModeList(index, modelPageNum.value, modelPageSize.value); | |||
} | |||
function changeTabVideoType(index) { | |||
modeList.value = []; | |||
modelPageNum.value = 1; | |||
modelTabItemActive2.value = index; | |||
overLoadModel.value = false; | |||
tabVideoType.value = index; | |||
getModeList(tabSex.value, modelPageNum.value, modelPageSize.value); | |||
} | |||
// watch(tabSex, (newVal, oldVal) => { | |||
// if (newVal == 0) { | |||
// getModeList("", modelPageNum.value, modelPageSize.value); | |||
// } else { | |||
// } | |||
// }); | |||
// function changeTabSex(index) { | |||
// modeList.value = []; | |||
// modelPageNum.value = 1; | |||
// modelTabItemActive.value = index; | |||
// overLoadModel.value = false; | |||
// if (index == 0) { | |||
// getModeList("", modelPageNum.value, modelPageSize.value); | |||
// } else { | |||
// getModeList(index, modelPageNum.value, modelPageSize.value); | |||
// } | |||
// } | |||
// 触底刷新 | |||
async function loadMoreModel(params) { | |||
modelPageNum.value += 1; | |||
if (modelTabItemActive.value == 0) { | |||
@@ -604,7 +684,10 @@ onMounted(async () => { | |||
<style lang="scss" scoped> | |||
.page { | |||
height: calc(100vh - 80px); | |||
// height: calc(100vh - 80px); | |||
background-color: #fff; | |||
border-radius: 30px 0 0 0; | |||
overflow: hidden; | |||
} | |||
.mask { | |||
position: absolute; | |||
@@ -623,16 +706,17 @@ onMounted(async () => { | |||
position: absolute; | |||
top: 0px; | |||
left: 0px; | |||
width: 90%; | |||
width: 30%; | |||
height: 100%; | |||
padding: 30px; | |||
transition: all 0.3s; | |||
background-color: #f1f2f6; | |||
// background-color: #f1f2f6; | |||
background-color: #454545; | |||
z-index: 9; | |||
.openChooseModel, | |||
.closeChooseModel { | |||
position: absolute; | |||
top: 10px; | |||
top: 50%; | |||
width: 50px; | |||
height: 20px; | |||
z-index: 999; | |||
@@ -642,54 +726,97 @@ onMounted(async () => { | |||
height: 100%; | |||
} | |||
} | |||
.openChooseModel { | |||
right: 0px; | |||
} | |||
.closeChooseModel { | |||
right: -50px; | |||
// 伸缩按钮 | |||
.shrinkBtn { | |||
position: absolute; | |||
top: 350px; | |||
right: -40px; | |||
width: 40px; | |||
height: 100px; | |||
line-height: 80px; | |||
padding: 10px; | |||
font-size: 30px; | |||
background-color: #454545; | |||
color: #fff; | |||
&::before { | |||
position: absolute; | |||
top: -40px; | |||
left: -0px; | |||
content: ""; | |||
width: 0; | |||
height: 0px; | |||
border-top: 20px solid transparent; | |||
border-right: 20px solid transparent; | |||
border-bottom: 20px solid #454545; | |||
border-left: 20px solid #454545; | |||
} | |||
&::after { | |||
position: absolute; | |||
bottom: -40px; | |||
left: -0px; | |||
content: ""; | |||
width: 0; | |||
height: 0px; | |||
border-top: 20px solid #454545; | |||
border-right: 20px solid transparent; | |||
border-bottom: 20px solid transparent; | |||
border-left: 20px solid #454545; | |||
} | |||
} | |||
// tab栏 | |||
p { | |||
color: #fff; | |||
font-size: 16px; | |||
padding: 0 20px; | |||
} | |||
.tab { | |||
margin: auto; | |||
margin-top: 10px; | |||
display: flex; | |||
width: 100%; | |||
height: 50px; | |||
background-color: #fff; | |||
height: 40px; | |||
// background-color: #fff; | |||
margin-bottom: 10px; | |||
border-radius: 25px; | |||
color: #b9b9b9; | |||
.tabItem { | |||
flex: 1; | |||
font-size: 16px; | |||
text-align: center; | |||
line-height: 50px; | |||
border-radius: 25px; | |||
line-height: 40px; | |||
border-radius: 15px; | |||
transition: all 0.3s; | |||
cursor: pointer; | |||
margin: 0 10px; | |||
background-color: #000; | |||
} | |||
.tabItemActive { | |||
background-color: #000; | |||
color: #fff; | |||
background-color: #fff; | |||
color: #000; | |||
} | |||
} | |||
// 模版列表 | |||
.modeListBox { | |||
display: flex; | |||
flex-wrap: wrap; | |||
justify-content: flex-start; | |||
width: 100%; | |||
height: calc(100% - 60px); | |||
height: calc(100% - 180px); | |||
padding: 20px; | |||
border-radius: 20px; | |||
background-color: #fff; | |||
// background-color: #fff; | |||
overflow: hidden; | |||
overflow-y: scroll; | |||
.modeListBoxItme { | |||
position: relative; | |||
padding: 20px; | |||
width: 300px; | |||
height: 300px; | |||
background: rgba(0, 0, 0, 0.1); | |||
width: 45%; | |||
height: 110px; | |||
margin: 0 10px 10px 0; | |||
border-radius: 15px; | |||
// background: rgba(0, 0, 0, 0.1); | |||
background-color: #fff; | |||
z-index: 2; | |||
cursor: pointer; | |||
img { | |||
@@ -701,26 +828,13 @@ onMounted(async () => { | |||
} | |||
.modeListBoxItmeActive { | |||
border: 3px solid #7264f5; | |||
// &::before { | |||
// content: ""; | |||
// position: absolute; | |||
// top: -5px; | |||
// left: -5px; | |||
// width: 310px; | |||
// height: 310px; | |||
// background: linear-gradient( | |||
// 225deg, | |||
// rgba(81, 217, 202, 1), | |||
// rgba(114, 100, 245, 1) | |||
// ); | |||
// border-radius: 16px; | |||
// } | |||
} | |||
} | |||
} | |||
.noModel { | |||
width: 0; | |||
padding: 0; | |||
// opacity: 0; | |||
} | |||
// 展示区 | |||
.showModelImgBox { | |||
@@ -9,7 +9,7 @@ | |||
loop | |||
></video> | |||
</div> | |||
<!-- 正常登录 --> | |||
<!-- 正常登录 isLogin == 1--> | |||
<el-form | |||
v-if="isLogin == 1" | |||
ref="loginFormRef" | |||
@@ -17,15 +17,22 @@ | |||
:rules="loginRules" | |||
class="login-form" | |||
> | |||
<div class="flex text-white items-center py-4"> | |||
<span class="text-2xl flex-1 text-center">{{ | |||
<div class="flex text-white items-center"> | |||
<span class="flex-1 text-center">{{ | |||
$t("login.title") + " " + $t("login.login") | |||
}}</span> | |||
<lang-select style="color: #fff" /> | |||
<el-tooltip | |||
class="box-item" | |||
effect="dark" | |||
:content="$t('navbar.LanguageChange')" | |||
placement="top-start" | |||
> | |||
<lang-select class="navItem" style="color: #ffffff" /> | |||
</el-tooltip> | |||
</div> | |||
<el-form-item prop="email"> | |||
<div class="p-2 text-white"> | |||
<div class="text-white"> | |||
<svg-icon icon-class="user" /> | |||
</div> | |||
<el-input | |||
@@ -39,7 +46,7 @@ | |||
</el-form-item> | |||
<el-form-item prop="password"> | |||
<span class="p-2 text-white"> | |||
<span class="text-white"> | |||
<svg-icon icon-class="password" /> | |||
</span> | |||
<el-input | |||
@@ -61,7 +68,7 @@ | |||
<!-- 验证码 --> | |||
<el-form-item prop="verifyCode"> | |||
<span class="p-2 text-white"> | |||
<span class="text-white"> | |||
<svg-icon icon-class="verify_code" /> | |||
</span> | |||
<el-input | |||
@@ -114,7 +121,7 @@ | |||
</div> | |||
</div> | |||
</el-form> | |||
<!-- 注册账户 --> | |||
<!-- 注册账户 isLogin == 2--> | |||
<el-form | |||
v-if="isLogin == 2" | |||
ref="loginFormRef" | |||
@@ -122,15 +129,22 @@ | |||
:rules="loginRules" | |||
class="login-form" | |||
> | |||
<div class="flex text-white items-center py-4"> | |||
<span class="text-2xl flex-1 text-center">{{ | |||
<div class="flex text-white items-center"> | |||
<span class="flex-1 text-center">{{ | |||
$t("login.title") + " " + $t("login.register") | |||
}}</span> | |||
<lang-select style="color: #fff" /> | |||
<el-tooltip | |||
class="box-item" | |||
effect="dark" | |||
:content="$t('navbar.LanguageChange')" | |||
placement="top-start" | |||
> | |||
<lang-select class="navItem" style="color: #ffffff" /> | |||
</el-tooltip> | |||
</div> | |||
<el-form-item prop="email"> | |||
<div class="p-2 text-white"> | |||
<div class="text-white"> | |||
<svg-icon icon-class="user" /> | |||
</div> | |||
<el-input | |||
@@ -144,7 +158,7 @@ | |||
</el-form-item> | |||
<el-form-item prop="password"> | |||
<span class="p-2 text-white"> | |||
<span class="text-white"> | |||
<svg-icon icon-class="password" /> | |||
</span> | |||
<el-input | |||
@@ -164,7 +178,7 @@ | |||
</el-form-item> | |||
<el-form-item prop="confirmPassword"> | |||
<span class="p-2 text-white"> | |||
<span class="text-white"> | |||
<svg-icon icon-class="password" /> | |||
</span> | |||
<el-input | |||
@@ -221,7 +235,75 @@ | |||
</div> | |||
</div> | |||
</el-form> | |||
<!-- 忘记密码 --> | |||
<!-- 注册账户之后输入短信验证码 isLogin == 6--> | |||
<el-form | |||
v-if="isLogin == 6" | |||
ref="loginFormRef" | |||
:model="loginData6" | |||
:rules="loginRules" | |||
class="login-form" | |||
> | |||
<div class="flex text-white items-center"> | |||
<span class="flex-1 text-center">{{ | |||
$t("login.title") + " " + $t("login.register") | |||
}}</span> | |||
<el-tooltip | |||
class="box-item" | |||
effect="dark" | |||
:content="$t('navbar.LanguageChange')" | |||
placement="top-start" | |||
> | |||
<lang-select class="navItem" style="color: #ffffff" /> | |||
</el-tooltip> | |||
</div> | |||
<el-form-item prop="SMSCode"> | |||
<div class="text-white"> | |||
<svg-icon icon-class="user" /> | |||
</div> | |||
<el-input | |||
class="flex-1" | |||
ref="email" | |||
size="large" | |||
v-model="loginData6.SMSCode" | |||
:placeholder="$t('login.SMSCode')" | |||
name="email" | |||
/> | |||
</el-form-item> | |||
<el-button | |||
size="default" | |||
:loading="loading" | |||
type="primary" | |||
class="loginBtn" | |||
@click.prevent="handleRegister" | |||
> | |||
<el-icon | |||
v-if="isRegistering" | |||
style="margin-right: 10px" | |||
class="is-loading" | |||
> | |||
<svg | |||
viewBox="0 0 1024 1024" | |||
xmlns="http://www.w3.org/2000/svg" | |||
data-v-ea893728="" | |||
> | |||
<path | |||
fill="currentColor" | |||
d="M512 64a32 32 0 0 1 32 32v192a32 32 0 0 1-64 0V96a32 32 0 0 1 32-32zm0 640a32 32 0 0 1 32 32v192a32 32 0 1 1-64 0V736a32 32 0 0 1 32-32zm448-192a32 32 0 0 1-32 32H736a32 32 0 1 1 0-64h192a32 32 0 0 1 32 32zm-640 0a32 32 0 0 1-32 32H96a32 32 0 0 1 0-64h192a32 32 0 0 1 32 32zM195.2 195.2a32 32 0 0 1 45.248 0L376.32 331.008a32 32 0 0 1-45.248 45.248L195.2 240.448a32 32 0 0 1 0-45.248zm452.544 452.544a32 32 0 0 1 45.248 0L828.8 783.552a32 32 0 0 1-45.248 45.248L647.744 692.992a32 32 0 0 1 0-45.248zM828.8 195.264a32 32 0 0 1 0 45.184L692.992 376.32a32 32 0 0 1-45.248-45.248l135.808-135.808a32 32 0 0 1 45.248 0zm-452.544 452.48a32 32 0 0 1 0 45.248L240.448 828.8a32 32 0 0 1-45.248-45.248l135.808-135.808a32 32 0 0 1 45.248 0z" | |||
></path> | |||
</svg> | |||
</el-icon> | |||
{{ $t("login.registerBtn") }} | |||
</el-button> | |||
<div :class="currentLan == 'zh-cn' ? 'bottomBtnCN' : 'bottomBtnEN'"> | |||
<div style="margin-bottom: 5px" @click="loginFlag(1)"> | |||
<span class="join">{{ $t("login.signIn") }}</span> | |||
</div> | |||
</div> | |||
</el-form> | |||
<!-- 忘记密码 isLogin == 3--> | |||
<el-form | |||
v-if="isLogin == 3" | |||
ref="loginFormRef" | |||
@@ -229,15 +311,22 @@ | |||
:rules="loginRules" | |||
class="login-form" | |||
> | |||
<div class="flex text-white items-center py-4"> | |||
<span class="text-2xl flex-1 text-center">{{ | |||
<div class="flex text-white items-center"> | |||
<span class="flex-1 text-center">{{ | |||
$t("login.title") + " " + $t("login.forgetPwdTitle") | |||
}}</span> | |||
<lang-select style="color: #fff" /> | |||
<el-tooltip | |||
class="box-item" | |||
effect="dark" | |||
:content="$t('navbar.LanguageChange')" | |||
placement="top-start" | |||
> | |||
<lang-select class="navItem" style="color: #ffffff" /> | |||
</el-tooltip> | |||
</div> | |||
<el-form-item prop="email"> | |||
<div class="p-2 text-white"> | |||
<div class="text-white"> | |||
<svg-icon icon-class="user" /> | |||
</div> | |||
<el-input | |||
@@ -249,6 +338,23 @@ | |||
name="email" | |||
/> | |||
</el-form-item> | |||
<!-- 验证码 --> | |||
<el-form-item prop="code"> | |||
<span class="text-white"> | |||
<svg-icon icon-class="verify_code" /> | |||
</span> | |||
<el-input | |||
v-model="loginData3.code" | |||
auto-complete="off" | |||
:placeholder="$t('login.verifyCode')" | |||
class="flex-1" | |||
@keyup.enter="handleLogin" | |||
/> | |||
<span class="captcha"> | |||
<img v-if="showCodeImg" :src="verifyCodeUrl" @click="getCode" /> | |||
</span> | |||
</el-form-item> | |||
<el-button | |||
size="default" | |||
@@ -282,7 +388,7 @@ | |||
</div> | |||
</div> | |||
</el-form> | |||
<!-- 重置密码 --> | |||
<!-- 重置密码 isLogin == 4--> | |||
<el-form | |||
v-if="isLogin == 4" | |||
ref="loginFormRef" | |||
@@ -290,22 +396,29 @@ | |||
:rules="loginRules" | |||
class="login-form" | |||
> | |||
<div class="flex text-white items-center py-4"> | |||
<span class="text-2xl flex-1 text-center">{{ | |||
<div class="flex text-white items-center"> | |||
<span class="flex-1 text-center">{{ | |||
$t("login.title") + " " + $t("login.resetPassword") | |||
}}</span> | |||
<lang-select style="color: #fff" /> | |||
<el-tooltip | |||
class="box-item" | |||
effect="dark" | |||
:content="$t('navbar.LanguageChange')" | |||
placement="top-start" | |||
> | |||
<lang-select class="navItem" style="color: #ffffff" /> | |||
</el-tooltip> | |||
</div> | |||
<el-form-item prop="oldPassword"> | |||
<span class="p-2 text-white"> | |||
<el-form-item prop="verifyCode"> | |||
<span class="text-white"> | |||
<svg-icon icon-class="password" /> | |||
</span> | |||
<el-input | |||
class="flex-1" | |||
v-model="loginData4.oldPassword" | |||
:placeholder="$t('login.oldPwd')" | |||
:type="passwordVisible === false ? 'password' : 'input'" | |||
v-model="loginData4.verifyCode" | |||
:placeholder="$t('login.SMSCode')" | |||
:type="'input'" | |||
size="large" | |||
name="password" | |||
/> | |||
@@ -318,7 +431,7 @@ | |||
</el-form-item> | |||
<el-form-item prop="password"> | |||
<span class="p-2 text-white"> | |||
<span class="text-white"> | |||
<svg-icon icon-class="password" /> | |||
</span> | |||
<el-input | |||
@@ -338,7 +451,7 @@ | |||
</el-form-item> | |||
<el-form-item prop="confirmPassword4"> | |||
<span class="p-2 text-white"> | |||
<span class="text-white"> | |||
<svg-icon icon-class="password" /> | |||
</span> | |||
<el-input | |||
@@ -387,16 +500,16 @@ | |||
<div style="margin-bottom: 5px" @click="loginFlag(1)"> | |||
<span class="join">{{ $t("login.signIn") }}</span> | |||
</div> | |||
<div> | |||
<!-- <div> | |||
<span | |||
class="join" | |||
@click="router.push({ path: 'createVideo', params: {} })" | |||
>{{ $t("login.gohome") }}</span | |||
> | |||
</div> | |||
</div> --> | |||
</div> | |||
</el-form> | |||
<!-- 忘记密码邮件返回 --> | |||
<!-- 忘记密码邮件返回 isLogin == 5--> | |||
<el-form | |||
v-if="isLogin == 5" | |||
ref="loginFormRef" | |||
@@ -404,15 +517,22 @@ | |||
:rules="loginRules" | |||
class="login-form" | |||
> | |||
<div class="flex text-white items-center py-4"> | |||
<span class="text-2xl flex-1 text-center">{{ | |||
<div class="flex text-white items-center"> | |||
<span class="flex-1 text-center">{{ | |||
$t("login.title") + " " + $t("login.setNewPwd") | |||
}}</span> | |||
<lang-select style="color: #fff" /> | |||
<el-tooltip | |||
class="box-item" | |||
effect="dark" | |||
:content="$t('navbar.LanguageChange')" | |||
placement="top-start" | |||
> | |||
<lang-select class="navItem" style="color: #ffffff" /> | |||
</el-tooltip> | |||
</div> | |||
<el-form-item prop="newPwd"> | |||
<div class="p-2 text-white"> | |||
<div class="text-white"> | |||
<svg-icon icon-class="password" /> | |||
</div> | |||
<el-input | |||
@@ -432,7 +552,7 @@ | |||
</span> | |||
</el-form-item> | |||
<el-form-item prop="confirmNewPwd"> | |||
<div class="p-2 text-white"> | |||
<div class="text-white"> | |||
<svg-icon icon-class="password" /> | |||
</div> | |||
<el-input | |||
@@ -496,6 +616,7 @@ import { | |||
sendRegisterEmail, | |||
getCodeImgUrl, | |||
sendUpdPwdEmailApi, | |||
doUpdPassApi, | |||
resetPwdEmailApi, | |||
resetPwdFormApi, | |||
} from "@/apis/login"; | |||
@@ -560,9 +681,10 @@ const loginData2 = ref({ | |||
}); | |||
const loginData3 = ref({ | |||
email: "", | |||
code: "", | |||
}); | |||
const loginData4 = ref({ | |||
oldPassword: "", | |||
verifyCode: "", | |||
password: "", | |||
confirmPassword4: "", | |||
}); | |||
@@ -570,6 +692,9 @@ const loginData5 = ref({ | |||
newPwd: "", | |||
confirmNewPwd: "", | |||
}); | |||
const loginData6 = ref({ | |||
SMSCode: "", | |||
}); | |||
const loginRules = ref({ | |||
email: [ | |||
@@ -636,7 +761,7 @@ function loginFlag(type: number) { | |||
*/ | |||
function saveInfo(data: any) { | |||
const userInfo = JSON.stringify({ | |||
email: data.email, | |||
email: data.phone, | |||
password: data.password, | |||
}); | |||
// 将用户信息加密 | |||
@@ -665,18 +790,21 @@ function getInfo() { | |||
function emailValidator(rule: any, value: any, callback: any) { | |||
const msg = | |||
currentLan.value == "zh-cn" | |||
? "邮箱不能为空!" | |||
? "手机号不能为空!" | |||
: "The E-amil can not be empty"; | |||
const msg2 = | |||
currentLan.value == "zh-cn" ? "邮箱格式不正确!" : "Incorrect email format"; | |||
currentLan.value == "zh-cn" | |||
? "手机号格式不正确!" | |||
: "Incorrect email format"; | |||
const phoneReg = /^[1][3-9]\d{9}$/; | |||
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 (!value) { | |||
callback(new Error(msg)); | |||
} else if (!emailReg.test(value)) { | |||
} else if (!phoneReg.test(value)) { | |||
callback(new Error(msg2)); | |||
} else { | |||
callback(); | |||
@@ -773,7 +901,7 @@ function handleLogin() { | |||
loginFormRef.value.validate((val: any) => { | |||
if (val) { | |||
const data = { | |||
email: loginData.value.email, | |||
phone: loginData.value.email, | |||
password: loginData.value.password, | |||
code: loginData.value.verifyCode, | |||
}; | |||
@@ -795,7 +923,7 @@ function handleRegister() { | |||
loginFormRef.value.validate((val: any) => { | |||
if (val) { | |||
const data = { | |||
email: loginData2.value.email, | |||
phone: loginData2.value.email, | |||
password: loginData2.value.password, | |||
}; | |||
isRegistering.value = true; | |||
@@ -815,17 +943,19 @@ function handleRegister() { | |||
function sendEmailforgetPwd() { | |||
const msg = | |||
currentLan.value == "zh-cn" | |||
? "确认信息已发送至您的邮箱,请注意查收" | |||
: "An email has been send to you, Please pay attention to confirm"; | |||
? "短信验证码已发送至您的手机,请注意查收" | |||
: "The SMS verification code has been sent to your mobile phone, please check it"; | |||
loginFormRef.value.validate(async (val: any) => { | |||
if (val) { | |||
const data = { | |||
email: loginData3.value.email, | |||
phone: loginData3.value.email, | |||
code: loginData3.value.code, | |||
}; | |||
await sendUpdPwdEmailApi(data.email) | |||
await sendUpdPwdEmailApi(data) | |||
.then((res) => { | |||
console.log(res, "res"); | |||
ElMessage.success(msg); | |||
isLogin.value = 4; | |||
}) | |||
.catch((err) => { | |||
console.log(err, "err"); | |||
@@ -878,14 +1008,20 @@ function resetPwdForm() { | |||
loginFormRef.value.validate(async (val: any) => { | |||
if (val) { | |||
try { | |||
const res = await resetPwdFormApi({ | |||
oldpwd: loginData4.value.oldPassword, | |||
newpwd: loginData4.value.password, | |||
const res = await doUpdPassApi({ | |||
phone: loginData3.value.email, | |||
code: loginData4.value.verifyCode, | |||
pwd: loginData4.value.password, | |||
}); | |||
localStorage.removeItem("AccessToken"); | |||
loginData.value.password = ""; | |||
isLogin.value = 1; | |||
router.push({ path: "login", query: {} }); | |||
ElMessage.success( | |||
currentLan.value == "zh-cn" | |||
? "重置密码成功!" | |||
: "Reset password successfully" | |||
); | |||
// router.push({ path: "login", query: {} }); | |||
} catch (error: any) { | |||
ElMessage.error(error.message); | |||
console.log(error); | |||
@@ -920,16 +1056,16 @@ function getCode() { | |||
*/ | |||
async function doRegister(data: object) { | |||
const msg = | |||
currentLan.value == "zh-cn" | |||
? "确认信息已发送至您的邮箱,请注意查收" | |||
: "An email has been send to you, Please pay attention to confirm"; | |||
currentLan.value == "zh-cn" ? "注册成功!" : "Registered successfully"; | |||
await register(data) | |||
.then((res) => { | |||
console.log(res, "res"); | |||
isRegistering.value = false; | |||
ElMessage.success(msg); | |||
isLogin.value = 1; | |||
// 注册成功将账号密码保存到本地 | |||
saveInfo(data); | |||
router.go(0); | |||
}) | |||
.catch((err) => { | |||
// 注册失败刷新验证码 | |||
@@ -996,8 +1132,16 @@ onMounted(() => { | |||
getCode(); | |||
getInfo(); | |||
// 重置密码 | |||
if (router.currentRoute.value.params.type) { | |||
isLogin.value = Number(router.currentRoute.value.params.type); | |||
// if (router.currentRoute.value.params.type) { | |||
// // isLogin.value = Number(router.currentRoute.value.params.type); | |||
// isLogin.value = 4; | |||
// } | |||
// if (router.currentRoute.value.params.type) { | |||
// // isLogin.value = Number(router.currentRoute.value.params.type); | |||
// isLogin.value = 4; | |||
// } | |||
if (route.query.type) { | |||
isLogin.value = 4; | |||
} | |||
//有resetPwd则说明是重置密码邮件来的 | |||
if (route.query.resetPwd) { | |||
@@ -1011,6 +1155,8 @@ onMounted(() => { | |||
.login-container { | |||
position: relative; | |||
width: 100%; | |||
// width: 1920px; | |||
// height: 1080px; | |||
min-height: 100%; | |||
overflow: hidden; | |||
// background-color: #2d3a4b; | |||
@@ -1055,6 +1201,15 @@ onMounted(() => { | |||
&:hover { | |||
backdrop-filter: blur(7px); | |||
} | |||
.items-center { | |||
padding: 20px; | |||
font-size: 30px; | |||
} | |||
.el-form-item { | |||
.text-white { | |||
padding: 8px; | |||
} | |||
} | |||
} | |||
} | |||
@@ -18,6 +18,11 @@ | |||
alt="" | |||
/> | |||
</div> | |||
<div class="container"> | |||
<div class="box red"></div> | |||
<div class="box white"></div> | |||
<div class="box green"></div> | |||
</div> | |||
</div> | |||
</template> | |||
@@ -93,3 +98,40 @@ onMounted(() => { | |||
} | |||
} | |||
</style> | |||
<style lang="scss" scoped> | |||
.container { | |||
display: flex; | |||
align-items: center; | |||
justify-content: space-between; | |||
width: 80px; | |||
height: 20px; | |||
perspective: 500px; | |||
transition: transform 0.5s; | |||
} | |||
.box { | |||
width: 20px; | |||
height: 20px; | |||
transition: transform 0.5s; | |||
transform-style: preserve-3d; | |||
} | |||
.red { | |||
background-color: red; | |||
} | |||
.white { | |||
background-color: white; | |||
transform: translateZ(20px); | |||
} | |||
.green { | |||
background-color: green; | |||
transform: translateZ(-20px); | |||
} | |||
.container:hover .box { | |||
transform: rotateY(180deg); | |||
} | |||
</style> |