2025-12-10 10:00:51 +08:00

767 lines
19 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 class="main-box">
<!-- 背景图片 -->
<div class="imgStyle" v-if="logoImg">
<img style="width: 100vw;height: 100vh;" src="../../assets/kyy/register-bg.png" alt="">
</div>
<div class="imgStyle" v-else>
<img style="width: 100vw;height: 100vh;background-position: center center" src="../../assets/kyy/register-bg.png"
alt="">
</div>
<!-- 头部图标 -->
<img @click="goHomePage" style="cursor: pointer" class="logo-top1" :src="logoImg" alt="" v-if="isLogo && isShow">
<img @click="goHomePage" style="cursor: pointer" class="logo-top" src="../../assets/kyy/LOGONew.png" alt=""
v-else-if="isShow">
<!-- 注册表单 -->
<div class="register-form">
<div class="regist-container">
<el-form ref="registForm" :model="registForm" :rules="rules" class="regist-form" autocomplete="on"
label-position="left" style="z-index: 1">
<!-- 表单标题区域 -->
<div class="title-container">
<span class="title">注册</span>
<span class="subtitle" @click="handleLogin">前往登录 ></span>
</div>
<!-- 手机号输入区域 -->
<div class="form-row">
<el-form-item prop="mobile" class="form-item-custom full-width">
<div class="form-item">
<span class="svg-container country-code">
+86
</span>
<el-input ref="mobile" v-model="registForm.mobile" placeholder="请输入手机号" type="text"
class="custom-input" />
</div>
</el-form-item>
</div>
<!-- 验证码输入区域 -->
<div class="form-row">
<el-form-item prop="vcode" class="form-item-custom full-width">
<div class="form-item">
<span class="svg-container">
验证码
</span>
<el-input ref="vcode" v-model="registForm.vcode" placeholder="请输入验证码" type="text"
class="custom-input" />
<span class="get-code-btn" @click="getSmsCode" :class="{ disabled: countdown > 0 }">
{{ countdown > 0 ? `${countdown}s后重新获取` : '获取验证码' }}
</span>
</div>
</el-form-item>
</div>
<!-- 信息补充区域标题 -->
<div class="info-supplement">
<span class="info-title">信息补充可跳过</span>
</div>
<!-- 账户名输入区域非必填 -->
<div class="form-row">
<el-form-item class="form-item-custom full-width">
<div class="form-item">
<span class="svg-container">
账户名
</span>
<el-input ref="username" v-model="registForm.username" placeholder="请输入账户名(默认手机号)" name="username" type="text"
class="custom-input" />
</div>
</el-form-item>
</div>
<!-- 密码输入区域非必填 -->
<div class="form-row">
<el-form-item class="form-item-custom full-width">
<div class="form-item">
<span class="svg-container">
密码
</span>
<el-input :key="passwordType" ref="password" v-model="registForm.password" :type="passwordType"
placeholder="请输入密码" name="password" class="custom-input" />
<span class="show-pwd" @click="showPwd">
<svg-icon :icon-class="passwordType === 'password' ? 'eye' : 'eye-open'" />
</span>
</div>
</el-form-item>
</div>
<!-- 用户协议勾选区域 -->
<div class="agreement">
<el-checkbox v-model="agreeProtocol">
我已阅读并同意用户协议隐私政策产品服务协议
</el-checkbox>
</div>
<!-- 注册按钮区域 -->
<div class="twoBtn">
<el-button class="register-btn" :loading="loading" type="primary"
@click.native.prevent="handleRegister('registForm')">
立即注册
</el-button>
</div>
</el-form>
</div>
</div>
</div>
</template>
<script>
import { getLogoAPI, register, sendCode } from "@/api/login";
import { cityArr } from '@/assets/province.js'
import { mapState } from "vuex";
import { getHomePath } from '@/views/setting/tools'
export default {
name: "indexNew",
data() {
return {
// 显示控制
isShow: false,
isLogo: false,
logoUrlOut: '',
logoImg: require("../../assets/kyy/LOGO.png"),
logoText: "开元云",
photosUrl: null,
// 用户协议勾选状态
agreeProtocol: false,
// 验证码倒计时秒数
countdown: 0,
// 倒计时定时器
countdownTimer: null,
// 短信验证码的codeid
codeid: '',
// 当前页面URL
url: window.location.href,
value: '',
// 注册表单数据
registForm: {
mobile: "", // 手机号(必填)
vcode: "", // 验证码(必填)
username: "", // 账户名(非必填,默认手机号)
password: "", // 密码(非必填)
org_type: "2", // 机构类型必填固定为2
wechat_openid: localStorage.getItem('wechat_openid') || "", // 微信openid默认为空
domain_name: "" // 域名
},
// 表单验证规则
rules: {
// 手机号验证规则
mobile: [
{
pattern: /^1(3\d|4[5-9]|5[0-35-9]|6[567]|7[0-8]|8\d|9[0-35-9])\d{8}$/,
message: "请输入有效的手机号",
},
{ required: true, trigger: "blur", message: "请输入手机号" },
],
// 验证码验证规则
vcode: [
{ required: true, message: "请输入验证码", trigger: "blur" }
]
},
// 密码显示类型password/text
passwordType: "password",
// 注册按钮加载状态
loading: false,
redirect: undefined,
otherQuery: {},
};
},
// 组件创建时调用
created() {
this.init();
},
// 组件挂载后调用
mounted() {
// 初始化域名
this.registForm.domain_name = window.location.hostname;
},
computed: {
// 从Vuex获取微信openid
...mapState({
wechat_openid: state => state.login.wechat_openid,
}),
},
methods: {
// 跳转到首页
goHomePage() {
if (this.logoUrlOut) {
window.location.href = this.logoUrlOut
} else {
window.location.href = 'https://www.opencomputing.cn/';
}
},
// 获取城市数据
cityArr() {
return cityArr;
},
// 初始化函数 - 获取Logo等信息
init() {
let params = {
url_link: this.GetQueryString(this.url)
};
getLogoAPI(params).then((res) => {
if (res.status == true && res.data && res.data.length) {
this.$store.commit('setLogoInfo', res.data[0]);
this.isShow = true
this.$store.commit('setLogoInfoNew', res.data[0].additional_msg);
// 特殊机构处理
if (res.data[0].orgname == '中关村数智人工智能产业联盟') {
this.logoUrlOut = 'https://www.ncmatch.cn'
}
this.photosUrl = res.data[0];
if (this.photosUrl.orgname != '业主机构') {
this.isLogo = true
this.logoImg = this.photosUrl.logo;
this.$store.commit('setLogo', this.photosUrl.logo)
this.logoText = this.photosUrl.orgname;
} else {
this.$store.commit('setLogo', "")
}
} else {
this.$message({
message: "获取ipc失败~",
type: "error",
});
}
});
},
// 从URL中获取查询参数
GetQueryString(name) {
if (name.indexOf("#") != -1) {
const params = name.split("#")[0];
return params;
}
},
// 显示/隐藏密码
showPwd() {
if (this.passwordType === "password") {
this.passwordType = "";
} else {
this.passwordType = "password";
}
this.$nextTick(() => {
this.$refs.password.focus();
});
},
// 获取短信验证码
async getSmsCode() {
// 如果正在倒计时,直接返回
if (this.countdown > 0) return;
// 验证手机号是否为空
if (!this.registForm.mobile) {
this.$message({
message: "请输入手机号",
type: "error",
});
return;
}
const mobileRegex = /^1(3\d|4[5-9]|5[0-35-9]|6[567]|7[0-8]|8\d|9[0-35-9])\d{8}$/;
if (!mobileRegex.test(this.registForm.mobile)) {
this.$message({
message: "请输入有效的手机号",
type: "error",
});
return;
}
let params = {
mobile: this.registForm.mobile,
action_type: "register",
};
try {
let res = await sendCode(params)
console.log('短信验证码完整响应:', res);
if (res.status == true) {
this.$message({
message: "验证码已发送",
type: "success",
});
let codeid = '';
// 尝试从不同的响应结构获取 codeid
if (res.data && res.data.codeid) {
// 结构: { data: { codeid: 'xxx' } }
codeid = res.data.codeid;
} else if (res.codeid) {
// 结构: { codeid: 'xxx' }
codeid = res.codeid;
} else if (res.data && typeof res.data === 'string') {
// 结构: { data: 'xxx' } 且 data 直接是 codeid
codeid = res.data;
} else if (res.data && res.data.data && res.data.data.codeid) {
// 结构: { data: { data: { codeid: 'xxx' } } }
codeid = res.data.data.codeid;
} else {
// 如果都没有找到,使用手机号和时间戳生成一个临时的 codeid
console.warn('无法从响应中获取 codeid使用临时值。响应结构:', res);
codeid = `temp_${this.registForm.mobile}_${Date.now()}`;
}
this.codeid = codeid;
console.log('最终获取的 codeid:', this.codeid);
// 开始倒计时
this.startCountdown();
} else {
this.$message({
message: res.msg,
type: "error",
});
}
} catch (error) {
console.error('发送验证码失败:', error);
}
},
// 开始验证码倒计时
startCountdown() {
this.countdown = 60;
this.countdownTimer = setInterval(() => {
this.countdown--;
if (this.countdown <= 0) {
clearInterval(this.countdownTimer);
}
}, 1000);
},
// 跳转到登录页面
handleLogin() {
this.$router.push({ name: "Login" });
},
// 注册处理函数
handleRegister(formName) {
// 第一步:检查用户是否同意协议
if (!this.agreeProtocol) {
this.$message({
message: "请先阅读并同意用户协议",
type: "error",
});
return;
}
// 第二步:进行表单验证
this.$refs[formName].validate((valid) => {
if (valid) {
// 表单验证通过,开始注册流程
this.loading = true;
// 第三步:构建注册数据
const registerData = {
mobile: this.registForm.mobile, // 手机号(必填)
vcode: this.registForm.vcode, // 验证码(必填)
codeid: this.codeid, // 短信接口返回的codeid必填
org_type: "2", // 机构类型必填固定为2
username: this.registForm.username || this.registForm.mobile, // 用户名(默认手机号)
password: this.registForm.password, // 密码
nick_name: this.registForm.mobile, // 显示名(默认手机号)
wechat_openid: this.registForm.wechat_openid, // 微信openid默认为空
domain_name: this.registForm.domain_name || window.location.hostname // 域名
};
console.log('注册参数:', registerData);
// 第四步调用注册API
register(registerData).then((res) => {
this.loading = false;
console.log('注册返回:', res);
if (res.status == true) {
// 注册成功
this.$message({
message: "注册成功",
type: "success",
});
// 跳转到登录页面
this.$router.push({ name: "Login" });
} else {
// 注册失败,显示错误信息
this.$message({
message: res.message || res.msg || "注册失败",
type: "error",
});
}
}).catch((error) => {
// 网络错误处理
console.error('注册失败:', error);
this.loading = false;
this.$message({
message: "注册失败,请重试",
type: "error",
});
});
} else {
// 表单验证失败
this.$message({
message: "请填写正确的手机号和验证码",
type: "error",
});
}
});
},
},
// 组件销毁前清理定时器
beforeDestroy() {
if (this.countdownTimer) {
clearInterval(this.countdownTimer);
}
}
}
</script>
<style scoped lang="scss">
// 定义样式变量
$cursor: black;
$primary-color: #409EFF;
$border-color: #E4E7ED;
$background-color: #F5F7FA;
$light-gray: #909399;
// 主容器样式
.main-box {
position: relative;
width: 100vw;
height: 100vh;
overflow: hidden;
img {
width: 100%;
height: 100%;
object-fit: cover;
}
}
// 头部图标样式
.logo-top {
width: 200px !important;
height: 70px !important;
position: absolute;
top: 2%;
left: 2%;
z-index: 1000;
}
.logo-top1 {
width: 260px !important;
height: 80px !important;
position: absolute;
top: 3%;
left: 3%;
z-index: 1000;
}
// 注册表单容器样式
.register-form {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 90%;
max-width: 480px;
min-height: 560px;
background: rgba(255, 255, 255, 0.95);
border-radius: 16px;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
backdrop-filter: blur(10px);
overflow: hidden;
z-index: 999;
}
// 注册内容区域样式
.regist-container {
width: 100%;
height: 100%;
padding: 40px 35px;
.regist-form {
width: 100%;
}
// 标题区域样式
.title-container {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 30px;
.title {
font-size: 24px;
font-weight: 600;
color: #303133;
}
.subtitle {
font-size: 14px;
color: $primary-color;
cursor: pointer;
&:hover {
text-decoration: underline;
}
}
}
// 表单行样式
.form-row {
margin-bottom: 20px;
}
// 表单项样式
.form-item-custom {
margin-bottom: 0;
&.full-width {
width: 100%;
}
}
// 表单项目样式
.form-item {
display: flex;
align-items: center;
width: 100%;
height: 48px;
background: white;
border: 1px solid $border-color;
border-radius: 8px;
transition: all 0.3s ease;
position: relative;
&:hover {
border-color: $primary-color;
}
&:focus-within {
border-color: $primary-color;
box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.1);
}
}
// 图标容器样式
.svg-container {
padding: 0 16px;
display: flex;
align-items: center;
justify-content: center;
height: 100%;
color: #606266;
font-size: 14px;
background: #f8f9fa;
border-right: 1px solid $border-color;
border-radius: 8px 0 0 8px;
min-width: 80px;
&.country-code {
min-width: 60px;
background: transparent;
border-right: none;
color: #303133;
font-weight: 500;
}
}
// 自定义输入框样式
.custom-input {
flex: 1;
border: none !important;
outline: none !important;
background: transparent;
height: 100%;
::v-deep .el-input__inner {
border: none !important;
background: transparent !important;
height: 46px;
padding: 0 16px;
font-size: 14px;
&:focus {
border: none !important;
box-shadow: none !important;
}
&::placeholder {
color: $light-gray;
}
}
}
// 获取验证码按钮样式
.get-code-btn {
position: absolute;
right: 12px;
top: 50%;
transform: translateY(-50%);
color: $primary-color;
font-size: 14px;
cursor: pointer;
background: none;
border: none;
padding: 4px 8px;
border-radius: 4px;
transition: background-color 0.3s ease;
white-space: nowrap;
&:hover {
background: rgba(64, 158, 255, 0.1);
}
&.disabled {
color: $light-gray;
cursor: not-allowed;
&:hover {
background: none;
}
}
}
// 显示密码按钮样式
.show-pwd {
position: absolute;
right: 12px;
top: 50%;
transform: translateY(-50%);
font-size: 16px;
color: #909399;
cursor: pointer;
z-index: 2;
}
// 信息补充区域样式
.info-supplement {
margin: 24px 0 16px 0;
padding-bottom: 8px;
border-bottom: 1px solid #f0f0f0;
.info-title {
font-size: 14px;
color: $light-gray;
font-weight: 500;
}
}
// 协议勾选区域样式
.agreement {
margin: 20px 0;
::v-deep .el-checkbox {
.el-checkbox__label {
font-size: 14px;
color: #606266;
}
}
}
// 按钮区域样式
.twoBtn {
display: flex;
flex-direction: column;
align-items: center;
margin-top: 30px;
}
// 注册按钮样式
.register-btn {
width: 100%;
height: 48px;
background: $primary-color;
border: none;
border-radius: 8px;
font-size: 16px;
font-weight: 500;
color: white;
transition: all 0.3s ease;
&:hover {
background: #66b1ff;
transform: translateY(-1px);
box-shadow: 0 4px 12px rgba(64, 158, 255, 0.3);
}
&:active {
transform: translateY(0);
}
}
}
// 响应式设计 - 移动端适配
@media (max-width: 768px) {
.register-form {
width: 95%;
min-width: unset;
height: auto;
max-height: 90vh;
overflow-y: auto;
}
.regist-container {
padding: 24px 20px;
}
// 移动端调整头部图标大小
.logo-top {
width: 150px !important;
height: 52px !important;
}
.logo-top1 {
width: 200px !important;
height: 62px !important;
}
}
// 动画效果
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.3s ease;
}
.fade-enter,
.fade-leave-to {
opacity: 0;
}
// 自定义滚动条样式
::-webkit-scrollbar {
width: 6px;
}
::-webkit-scrollbar-track {
background: #f1f1f1;
border-radius: 3px;
}
::-webkit-scrollbar-thumb {
background: #c1c1c1;
border-radius: 3px;
}
::-webkit-scrollbar-thumb:hover {
background: #a8a8a8;
}
</style>