2025-09-15
This commit is contained in:
490
pages/register/register.vue
Normal file
490
pages/register/register.vue
Normal file
@@ -0,0 +1,490 @@
|
||||
<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>
|
||||
Reference in New Issue
Block a user