Files
jurong_circle_front_app/pages/register/register.vue
2025-09-15 21:03:25 +08:00

490 lines
12 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>
<view class="register-container">
<view class="register-title">
<view class="title">
用户注册
</view>
<view class="sub-title">
创建你的账号欢迎来到炬融圈
</view>
</view>
<view class="register-main">
<u-form :model="userRegister.userRegisterForm" class="register-form" ref="userRegisterRef"
:border-bottom="false" :error-type="['message']" label-width="0">
<u-form-item :left-icon-style="inputIcon" left-icon="../../static/icon/Phone.png" prop="phone">
<u-input v-model="userRegister.userRegisterForm.phone" placeholder="请输入手机号" maxlength="11"
type="number" placeholder-style="color: #737373;" />
</u-form-item>
<u-form-item :left-icon-style="inputIcon" left-icon="../../static/icon/Mail.png" prop="smsCode">
<u-input v-model="userRegister.userRegisterForm.smsCode" placeholder="请输入短信验证码" maxlength="6"
type="number" placeholder-style="color: #737373;" />
<template v-slot:right>
<u-verification-code ref="msgCodeRef" @change="codeMsgChange"></u-verification-code>
<u-button :disabled="!canSendSMS" size="mini" type="primary"
@tap="getMsgCode">{{msgCodeBtn}}</u-button>
</template>
</u-form-item>
<u-form-item :left-icon-style="inputIcon" left-icon="../../static/icon/Map pin.png" prop="regionLabel">
<u-input type="select" v-model="userRegister.userRegisterForm.regionLabel" placeholder="请选择省市区"
placeholder-style="color: #737373;" @click="showRegitionPicker = true" />
</u-form-item>
<u-form-item :left-icon-style="inputIcon" left-icon="../../static/icon/Lock.png" prop="password">
<u-input type="password" v-model="userRegister.userRegisterForm.password" placeholder="请输入密码"
maxlength="20" placeholder-style="color: #737373;" />
</u-form-item>
<u-form-item :left-icon-style="inputIcon" left-icon="../../static/icon/Lock.png" prop="confirmPassword">
<u-input type="password" v-model="userRegister.userRegisterForm.confirmPassword" maxlength="20"
placeholder="请输入确认密码" placeholder-style="color: #737373;" />
</u-form-item>
<u-form-item :left-icon-style="inputIcon" left-icon="../../static/icon/Globe.png" prop="captcha">
<u-input v-model="userRegister.userRegisterForm.captcha" placeholder="请输入验证码" maxlength="4"
placeholder-style="color: #737373;" />
<template v-slot:right>
<image @click="loadCaptcha" class="captcha-img" :src="captcha" mode=""></image>
</template>
</u-form-item>
</u-form>
<view class="reflash" @click="loadCaptcha">
<image class="reflash-icon" src="/static/icon/Repeat.png" mode=""></image>
刷新验证码
</view>
<u-checkbox v-model="is_read" size="26" class="must-read" :label-disabled="true">
我已阅读并同意<span @click="showFile1=true">用户协议</span><span @click="showFile2=true">隐私政策</span>
</u-checkbox>
<u-button type="primary" class="register-btn" @click="handleRegister">立即注册</u-button>
<view class="login">
<view class="login-text">没有账号</view>
<view class="login-link" @click="handleLogin">立即登录</view>
</view>
</view>
<!-- 省市区 -->
<u-select v-model="showRegitionPicker" :list="regionOptions" mode="mutil-column-auto" label-name="label"
value-name="code" child-name="children" @confirm="handleRegion"></u-select>
<!-- 协议1 -->
<u-popup v-model="showFile1" mode="bottom" border-radius="14" :closeable="true">
<view class="file">
<h3>用户协议</h3>
<p>1. 用户应当遵守法律法规不得发布违法违规内容</p>
<p>2. 用户对自己发布的内容承担全部责任</p>
<p>3. 平台有权对违规内容进行删除或限制</p>
<p>4. 用户应当保护好自己的账号安全</p>
<p>5. 平台保留修改本协议的权利</p>
</view>
</u-popup>
<!-- 协议2 -->
<u-popup v-model="showFile2" mode="bottom" border-radius="14" :closeable="true">
<view class="file">
<h3>隐私政策</h3>
<p>1. 我们重视用户隐私保护</p>
<p>2. 我们只收集必要的用户信息</p>
<p>3. 用户信息仅用于提供服务</p>
<p>4. 我们不会向第三方泄露用户信息</p>
<p>5. 用户有权查看修改或删除个人信息</p>
</view>
</u-popup>
</view>
</template>
<script setup lang="ts">
import {
onMounted,
reactive,
ref,
computed
} from 'vue';
import {
onReady
} from '@dcloudio/uni-app';
import {
captchaAPI
} from '../../api/captcha.js';
import {
commonAPI
} from '../../api/common.js';
import {
authAPI
} from '../../api/auth.js';
// 输入框图标样式
const inputIcon = {
width: '32rpx',
verticalAlign: 'middle'
}
// 省市区
const showRegitionPicker = ref(false)
const regionOptions = ref()
// 加载省市区
const loadRegion = () => {
commonAPI.getRegion().then(res => {
if (res.success) {
regionOptions.value = res.data
}
})
}
// 选择省市区
const handleRegion = (e) => {
console.log(e);
userRegister.userRegisterForm.regionLabel = e[0].label + "/" + e[1].label + "/" + e[2].label
userRegister.userRegisterForm.region = e[2].value
}
// 验证码
const captcha = ref()
const captchaId = ref()
// 请求验证码
const loadCaptcha = () => {
captchaAPI.generate().then(res => {
captcha.value = res.data.image
captchaId.value = res.data.captchaId
})
}
// 校验规则
const validatePassword = (rule, value, callback) => {
if (!value) {
callback(new Error('请输入密码'));
} else if (value.length < 6) {
callback(new Error('密码至少6个字符'));
} else if (value.length > 20) {
callback(new Error('密码不能超过20个字符'));
} else if (!/(?=.*[a-zA-Z])(?=.*\d)/.test(value)) {
callback(new Error('密码必须包含字母和数字'));
} else {
// 如果确认密码已输入,重新验证确认密码
if (userRegister.userRegisterForm.confirmPassword) {
userRegisterRef.value?.validateField('confirmPassword');
}
callback();
}
};
const validateConfirmPassword = (rule, value, callback) => {
if (!value) {
callback(new Error('请确认密码'));
} else if (value !== userRegister.userRegisterForm.password) {
callback(new Error('两次输入的密码不一致'));
} else {
callback();
}
};
// 注册表单
const userRegisterRef = ref()
const userRegister = reactive({
userRegisterForm: {
username: '13758452159',
phone: '13758452159',
smsCode: 'asrfdv',
region: '',
regionLabel: '',
password: 's123456s',
confirmPassword: 's123456s',
captcha: 'vfjs',
},
rules: {
phone: [{
required: true,
message: '请输入手机号',
trigger: ['blur']
},
{
pattern: /^1[3-9]\d{9}$/,
message: '请输入正确的手机号格式',
trigger: ['blur']
}
],
smsCode: [{
required: true,
message: '请输入短信验证码',
trigger: ['blur']
},
{
pattern: /^\d{6}$/,
message: '短信验证码为6位数字',
trigger: ['blur']
},
],
regionLabel: [{
required: true,
message: '请选择省市区',
trigger: ['change']
}],
password: [{
validator: validatePassword,
trigger: ['blur']
}],
confirmPassword: [{
validator: validateConfirmPassword,
trigger: ['blur']
}],
captcha: [{
required: true,
message: '请输入验证码',
trigger: ['blur']
},
{
min: 4,
max: 4,
message: '验证码长度为4位',
trigger: 'blur'
}
],
}
})
// 注册处理
const handleRegister = async () => {
if (!is_read.value) {
uni.showToast({
title: '请先同意协议',
icon: 'none'
})
return
}
// 等待表单验证完成
const valid = await userRegisterRef.value.validate();
if (valid) {
console.log(valid);
}
// userRegisterRef.value.validate((valid : any) => {
// if (valid) {
// // 验证验证码
// captchaAPI.verify({
// captchaId: captchaId.value,
// captchaText: userRegister.userRegisterForm.captcha
// }).then(verifyResponse => {
// console.log(verifyResponse);
// if (!verifyResponse.data.success) {
// uni.showToast({
// title: verifyResponse.data.message || '验证码错误',
// icon: 'error'
// })
// // 重新加载验证码
// loadCaptcha()
// return
// }
// })
// const registerData = {
// username: userRegister.userRegisterForm.phone,
// phone: userRegister.userRegisterForm.phone,
// city: userRegister.userRegisterForm.region,
// password: userRegister.userRegisterForm.password,
// smsCode: userRegister.userRegisterForm.smsCode,
// captchaId: captchaId.value,
// captchaText: userRegister.userRegisterForm.captcha,
// province: userRegister.userRegisterForm.region,
// }
// authAPI.register(registerData).then(response => {
// // 直接注册成功的情况
// // setToken(response.data.token)
// // setUser(response.data.user)
// console.log(response);
// })
// }
// })
}
// 手机验证码
const msgCodeBtn = ref()
const msgCodeRef = ref()
// 手机验证码变化
const codeMsgChange = (text) => {
msgCodeBtn.value = text;
}
// 是否能够发送手机验证码
const canSendSMS = computed(() => {
const phoneRegex = /^1[3-9]\d{9}$/;
return phoneRegex.test(userRegister.userRegisterForm.phone);
});
// 获取手机验证码
const getMsgCode = () => {
// 校验手机号
if (msgCodeRef.value.canGetCode) {
console.log("发送验证码");
msgCodeRef.value.start();
} else {
uni.showToast({
title: '等待...'
})
}
}
// 是否阅读
const is_read = ref(false)
const showFile1 = ref(false)
const showFile2 = ref(false)
// 跳转登录页面
const handleLogin = () => {
uni.redirectTo({
url: '/pages/login/login'
})
}
onMounted(() => {
loadCaptcha()
loadRegion()
})
onReady(() => {
userRegisterRef.value.setRules(userRegister.rules)
})
</script>
<style scoped lang="scss">
.register-container {
width: 100%;
height: 100vh;
background: linear-gradient(180deg, #BAC9FF 0%, #FFFFFF 100%);
.register-title {
padding-top: 114rpx;
.title {
font-family: SF Pro;
font-weight: 650;
font-style: Expanded Semibold;
font-size: 48rpx;
leading-trim: NONE;
line-height: 80rpx;
letter-spacing: 0%;
text-align: center;
color: #000000;
}
.sub-title {
font-family: Work Sans;
font-weight: 400;
font-size: 26rpx;
leading-trim: NONE;
line-height: 100%;
letter-spacing: -2%;
text-align: center;
color: #5B5B5B;
}
}
.register-main {
.register-form {
padding: 20rpx 98rpx 10rpx;
}
.captcha-img {
width: 200rpx;
height: 80rpx;
}
.reflash {
width: 90%;
margin-bottom: 30rpx;
display: flex;
justify-content: flex-end;
align-items: center;
// 文字
font-family: Work Sans;
font-weight: 400;
font-size: 26rpx;
leading-trim: NONE;
line-height: 100%;
letter-spacing: -2%;
color: #3781EF;
.reflash-icon {
width: 32rpx;
height: 32rpx;
margin-right: 10rpx;
}
}
.must-read {
padding: 0 76rpx;
font-family: Work Sans;
font-weight: 400;
leading-trim: NONE;
line-height: 100%;
letter-spacing: -2%;
text-align: center;
color: #000000;
text-align: left;
span {
font-family: Work Sans;
font-weight: 400;
font-size: 26rpxpx;
leading-trim: NONE;
line-height: 100%;
letter-spacing: -2%;
text-align: center;
color: #3781EF;
}
}
.register-btn {
margin: 40rpx 54rpx 20rpx;
font-family: SF Pro;
font-weight: 650;
font-style: Expanded Semibold;
font-size: 40rpx;
leading-trim: NONE;
line-height: 46rpx;
letter-spacing: 0%;
text-align: center;
}
.login {
margin: 40rpx 0 80rpx;
padding-bottom: 80rpx;
display: flex;
justify-content: center;
align-items: center;
// 文字
font-family: Work Sans;
font-weight: 400;
font-size: 26rpx;
leading-trim: NONE;
line-height: 100%;
letter-spacing: -2%;
text-align: center;
.login-text {
color: #737373;
}
.login-link {
display: flex;
justify-content: center;
align-items: center;
color: #3781EF;
}
}
}
.file {
padding: 80rpx 40rpx;
}
}
</style>