Files
new-cashier/jeepay-ui-agent/src/views/user/Register.vue
2024-05-23 14:39:33 +08:00

690 lines
18 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<div id="userLayout" :class="['user-layout-wrapper']">
<div class="top" style="display: none">
<!-- <div class="header">-->
<!-- <img :src="oemSiteInfo.sysLogoUrl" style="height: 30px;">-->
<!-- </div>-->
<!-- <a class="mch-url" href="#">
<span>服务商登录</span>
<i class="bi bi-arrow-right-short" />
</a> -->
</div>
<div
class="container"
:style="[
{ background: 'url(' + oemSiteInfo.agent.loginPageBGImgUrl + ')' },
{ backgroundSize: 'cover' },
{ backgroundPosition: 'center top' },
{ backgroundRepeat: 'no-repeat' },
]"
>
<div class="user-layout-lang" />
<div class="user-layout-content">
<!-- 错误提示信息 -->
<a-alert
v-if="showRegisterErrorInfo"
type="error"
showIcon
style="margin-bottom: 15px"
:message="showRegisterErrorInfo"
/>
<div class="main">
<div class="desc">服务商注册</div>
<a-form
ref="formRegister"
class="user-layout-login"
:model="formState"
:rules="vdata.rules"
@submit="handleSubmit"
>
<!-- <a-form-item name="agentName" class="input-item">-->
<!-- <login-text-up-->
<!-- v-model:value="formState.agentName"-->
<!-- placeholder="服务商名称"-->
<!-- />-->
<!-- </a-form-item>-->
<a-form-item name="phone" class="input-item">
<login-text-up
v-model:value="formState.phone"
placeholder="手机号"
/>
</a-form-item>
<div class="code-body">
<div
class="code code-layout-item"
style="display: flex; justify-content: center"
>
<a-form-item name="vercode" class="input-item">
<login-text-up
v-model:value="formState.vercode"
:isLogin="true"
placeholder="图形验证码"
/>
</a-form-item>
<div class="code-img" style="position: relative">
<img
v-show="vercodeImgSrc"
:src="vercodeImgSrc"
@click="refVercode()"
/>
<div
v-show="isOverdue"
class="vercode-mask"
@click="refVercode()"
>
已过期 请刷新
</div>
</div>
</div>
</div>
<div class="code">
<a-form-item name="code" class="input-item">
<login-text-up
v-model:value="formState.code"
placeholder="请输入验证码"
/>
</a-form-item>
<div>
<a-button
type="primary"
:disabled="vdata.isDisabled"
style="height: 40px; margin-left: 10px"
@click="sendSMS()"
>{{ vdata.codeBtnText }}</a-button
>
</div>
</div>
<a-form-item name="password" class="input-item">
<login-text-up
v-model:value="formState.password"
placeholder="登录密码"
isPassword="password"
/>
</a-form-item>
<a-form-item name="confirmPwd" class="input-item">
<login-text-up
v-model:value="formState.confirmPwd"
placeholder="确认登录密码"
isPassword="password"
/>
</a-form-item>
<a-form-item name="inviteCode" class="input-item">
<login-text-up
v-model:value="formState.inviteCode"
placeholder="请输入邀请码(选填)"
/>
</a-form-item>
<a-form-item name="checked">
<a-checkbox
class="checked_size"
v-model:checked="formState.checked"
@click.stop.prevent="check"
>我已阅读并同意<a
class="forge-password checked_size"
@click.stop.prevent="serviceAgreement"
>服务协议</a
><a class="forge-password checked_size" @click.stop.prevent="privacyPolicy"
>隐私政策</a
></a-checkbox
>
</a-form-item>
<a-form-item class="input-item">
<a class="forge-password checked_size_login" style="float: right" @click="toLogin"
>去登录 >></a
>
</a-form-item>
</a-form>
<a-button
size="large"
type="primary"
htmlType="submit"
class="login-button submit"
:loading="loginBtnLoadingFlag"
style="width: 100%"
@click="handleSubmit"
>
注册
</a-button>
</div>
<div class="footer" />
</div>
</div>
</div>
<a-modal
v-model:visible="vdata.visible"
:title="vdata.toastTitle"
:footer="null"
width="70%"
>
<div style="height: 70vh; overflow: auto" v-html="vdata.toastContent" />
</a-modal>
</template>
<script setup lang="ts">
import { sendSmsCode, register, $getPasswordRules } from "@/api/login";
import { $getTreaty } from "@/api/manage";
import router from "@/router";
import { useRoute } from "vue-router";
import { message } from "ant-design-vue";
import { ref, reactive, onMounted } from "vue";
import { useOem } from "@/store/modules/oem";
import { vercode } from "@/api/login";
// 获取网站信息
const oemSiteInfo = useOem().getSiteInfo();
let loginPosition = ref(""); // 决定登录框水平位置 左中右?
let loginPageCardPosition = oemSiteInfo.agent.loginPageCardPosition;
if (loginPageCardPosition === "right") {
loginPosition.value = "flex-end";
} else if (loginPageCardPosition === "center") {
loginPosition.value = "center";
} else if (loginPageCardPosition === "left") {
loginPosition.value = "flex-start";
}
let loginBtnLoadingFlag = false; // 登录按钮是否显示 加载状态
let showRegisterErrorInfo = ref(""); // 是否显示登录错误面板信息
let timer: number = -1;
let formRegister = ref();
let isOverdue = ref(false); // 设置过期样式
let vercodeImgSrc = ref(""); // 验证码图片
let vercodeToken = ref(""); // 验证码验证token
let formState: any = reactive({
agentName: "",
phone: "",
code: "",
password: "",
confirmPwd: "",
checked: false,
inviteCode: null,
});
const vdata = reactive({
visibleCode:false,
codeBtnText: "发送验证码",
visible: false, // 对话框
toastContent: "", // 对话框内容
toastTitle: "", // 对话框标题
isDisabled: false,
checked: false,
passwordRules: /^$/, //密码规则
passwordRulesText: "", //密码规则提示文字
rules: {
agentName: [
{ required: true, message: "请输入服务商名称", trigger: "blur" },
],
phone: [
{
required: true,
pattern: /^1\d{10}$/,
message: "请输入正确的手机号",
trigger: "blur",
},
],
code: [{ required: true, message: "请输入验证码", trigger: "blur" }],
password: [
{ required: false, trigger: "blur" },
{
validator: (rule, value) => {
if (!vdata.passwordRules.test(formState.password)) {
return Promise.reject(vdata.passwordRulesText);
} else if (formState.password !== formState.confirmPwd) {
return Promise.reject("两次输入密码不一致");
} else return Promise.resolve();
},
},
],
confirmPwd: [
{ required: true, trigger: "blur", message: "请输入确认登录密码" },
{
validator: (rule, value) => {
if (!vdata.passwordRules.test(formState.password)) {
return Promise.reject(vdata.passwordRulesText);
} else if (formState.password !== formState.confirmPwd) {
return Promise.reject("两次输入密码不一致");
} else return Promise.resolve();
},
},
],
checked: [
{
type: "boolean",
required: true,
message: "请勾选用户隐私协议",
trigger: "check",
},
{
validator: (rule, value) => {
if (formState.checked) {
return Promise.resolve();
} else {
return Promise.reject("请勾选用户隐私协议");
}
},
},
],
},
});
onMounted(() => {
formState.inviteCode = useRoute().query.c;
getPasswordRules();
refVercode();
});
function refVercode() {
// 刷新图片验证码
// 获取图形验证码
vercode().then((res) => {
vercodeImgSrc.value = res.imageBase64Data;
vercodeToken.value = res.vercodeToken;
isOverdue.value = false;
if (timer) clearInterval(timer); // 如果多次点击则清除已有的定时器
// 超过60秒提示过期刷新
timer = window.setInterval(() => {
res.expireTime--;
if (res.expireTime <= 0) {
isOverdue.value = true;
clearInterval(timer);
}
}, 1000);
});
}
function sendSMSCode() {
vdata.visibleCode = true;
refVercode();
}
function getPasswordRules() {
// 获取密码规则
$getPasswordRules().then((res) => {
vdata.passwordRules = new RegExp(res.regexpRules);
vdata.passwordRulesText = res.errTips;
});
}
// handler
function handleSubmit() {
formRegister.value
.validate()
.then((valid) => {
let params = {
agentName: formState.phone,
phone: formState.phone,
code: formState.code,
confirmPwd: formState.confirmPwd,
inviteCode: formState.inviteCode,
};
register(params)
.then((res) => {
message.success("注册成功");
router.push({ path: "/user/login" }); // 校验成功,返回登录页
})
.catch((err) => {
showRegisterErrorInfo = err.msg || JSON.stringify(err);
loginBtnLoadingFlag = false;
});
})
.catch((valid) => {});
}
function sendSMS() {
// 发送短信验证
if (!formState.phone) {
return message.error("请输入手机号!");
}
// 校验手机号
const reg = /^[1][0-9]{10}$/;
if (!reg.test(formState.phone)) {
return message.error("请输入正确的手机号!");
}
vdata.isDisabled = true;
sendSmsCode({
phone: formState.phone,
smsType: "register",
vercode: formState.vercode,
vercodeToken: vercodeToken.value,
})
.then((res) => {
return message.success("发送成功!");
})
.catch((err) => {
vdata.isDisabled = false;
showRegisterErrorInfo = err.msg || JSON.stringify(err);
loginBtnLoadingFlag = false;
// 出错后三秒停止计时
setTimeout(() => {
if (timer) clearInterval(timer);
vdata.isDisabled = false;
vdata.codeBtnText = "发送短信验证码";
}, 500);
});
let time = 60; // 重发验证码时间
vdata.codeBtnText = `${time}秒后重新发送`;
const timer = setInterval(() => {
time -= 1;
vdata.codeBtnText = `${time}秒后重新发送`;
if (time === 0) {
clearInterval(timer);
vdata.isDisabled = false;
vdata.codeBtnText = "发送短信验证码";
}
}, 1000);
}
// 跳转页面
function toLogin() {
router.push({ name: "login", path: "/user/login" });
}
// 服务协议
function serviceAgreement() {
vdata.visible = true;
vdata.toastTitle = "服务协议";
// message.success('服务协议')
getTreaty("服务协议");
}
// 隐私政策
function privacyPolicy() {
vdata.visible = true;
vdata.toastTitle = "隐私政策";
getTreaty("隐私政策");
}
// 隐私协议与服务政策
const getTreaty = (name) => {
$getTreaty().then((res) => {
name === "服务协议"
? (vdata.toastContent = res.agentServiceAgreement)
: (vdata.toastContent = res.agentPrivacyPolicy);
});
};
// 勾选用户协议
function check() {
formState.checked = !formState.checked;
}
</script>
<style lang="less" scoped>
#userLayout.user-layout-wrapper {
height: 100%;
.top {
height: 80px;
padding: 0 35px;
box-sizing: border-box;
display: flex;
justify-content: space-between;
align-items: center;
.header {
height: 44px;
line-height: 44px;
}
.mch-url {
display: flex;
align-items: center;
color: #000;
cursor: pointer;
span {
margin-right: 10px;
}
&:hover {
color: steelblue;
.bi {
transform: translateX(10px);
}
}
}
.bi {
font-size: 18px;
}
}
.container {
display: flex;
justify-content: center;
align-items: center; //修改这一项来决定登录对话框的水平位置flex-start == left center == center flex-end == right
flex-direction: column;
box-sizing: border-box;
padding: 0;
width: 100%;
//height: calc(100vh - 80px);
height: calc(100vh + 0px) !important;
background: #f0f2f5 url(/src/assets/svg/background.svg) no-repeat 50%;
background-size: cover;
//padding: 50px 0 84px;
position: relative;
transition: 0.3s ease;
.user-layout-lang {
width: 100%;
// height: 40px;
// line-height: 44px;
height: 0;
text-align: right;
}
.user-layout-content {
width: 100%;
height: 100%;
transition: 0.3s ease;
input {
height: 40px !important;
}
.main {
padding: 50px 30px;
box-sizing: border-box;
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
justify-content: flex-start;
background: #fff;
border-top: 1px solid #e7eaf3;
align-items: center;
transition: all 0.3s, border 0s ease;
.ant-form {
max-width: 300px;
}
.desc {
font-weight: bold;
font-size: 20px;
letter-spacing: 0.04em;
color: #2691ff;
margin-bottom: 20px;
text-align: center;
}
.input-item {
margin-bottom: 20px;
}
}
.footer {
// position: absolute;
width: 100%;
bottom: 0;
padding: 0 16px;
margin: 48px 0 24px;
text-align: center;
.links {
margin-bottom: 8px;
font-size: 14px;
a {
color: rgba(0, 0, 0, 0.45);
transition: all 0.3s;
&:not(:last-child) {
margin-right: 40px;
}
}
}
.copyright {
color: rgba(0, 0, 0, 0.45);
font-size: 14px;
}
}
}
a {
text-decoration: none;
}
}
//登录页响应式的调整
@media screen and (min-width: 769px) and (max-width: 1024px) {
.container {
padding: 0 100px;
min-height: 700px;
height: calc(100vh - 80px);
align-items: v-bind(loginPosition);
.user-layout-content {
width: 360px;
height: auto;
.main {
width: 360px;
box-shadow: 0 6px 12px rgb(140 152 164 / 8%);
border: 0.0625rem solid #e7eaf3;
height: auto;
justify-content: center;
border-radius: 10px;
}
}
}
}
@media screen and (min-width: 1025px) and (max-width: 1366px) {
.container {
padding: 0 150px;
min-height: 700px;
height: calc(100vh - 80px);
align-items: v-bind(loginPosition);
.user-layout-content {
width: 360px;
height: auto;
.main {
width: 360px;
box-shadow: 0 6px 12px rgb(140 152 164 / 8%);
border: 0.0625rem solid #e7eaf3;
height: auto;
justify-content: center;
border-radius: 10px;
}
}
}
}
@media screen and (min-width: 1367px) and (max-width: 1600px) {
.container {
padding: 0 250px;
min-height: 700px;
height: calc(100vh - 80px);
align-items: v-bind(loginPosition);
.user-layout-content {
width: 360px;
height: auto;
.main {
width: 360px;
box-shadow: 0 6px 12px rgb(140 152 164 / 8%);
border: 0.0625rem solid #e7eaf3;
height: auto;
justify-content: center;
border-radius: 10px;
}
}
}
}
@media screen and (min-width: 1601px) {
.container {
padding: 0 300px;
min-height: 700px;
height: calc(100vh - 80px);
align-items: v-bind(loginPosition);
.user-layout-content {
width: 360px;
height: auto;
.main {
width: 360px;
box-shadow: 0 6px 12px rgb(140 152 164 / 8%);
border: 0.0625rem solid #e7eaf3;
height: auto;
justify-content: center;
border-radius: 10px;
}
}
}
}
}
</style>
<style lang="less" scoped>
.user-layout-login {
label {
font-size: 14px;
}
.forge-password {
font-size: 14px;
color: @jee-theme;
}
button.login-button {
padding: 0 15px;
font-size: 16px;
height: 40px;
width: 100%;
}
.user-login-other {
text-align: left;
margin-top: 24px;
line-height: 22px;
.item-icon {
font-size: 24px;
color: rgba(0, 0, 0, 0.2);
margin-left: 16px;
vertical-align: middle;
cursor: pointer;
transition: color 0.3s;
&:hover {
color: #1890ff;
}
}
.register {
float: right;
}
}
.code {
display: flex;
justify-content: space-between;
.code-input {
width: 216px;
}
.code-img {
width: 120px;
height: 40px;
margin-left: 10px;
}
}
.submit {
margin-bottom: 0;
}
}
.checked_size {
font-size: 12px !important;
}
.checked_size_login {
margin-bottom: 15px;
}
</style>