277 lines
6.7 KiB
Vue
277 lines
6.7 KiB
Vue
<script setup lang="ts">
|
|
import { onMounted, ref } from "vue";
|
|
import { getCodeImg, sendEmailCode, sendPhoneCode } from "@/api/login";
|
|
import useUserStore from "@/store/modules/user";
|
|
|
|
// 定义 props
|
|
const props = defineProps<{
|
|
register: boolean;
|
|
captchaEnabled: boolean;
|
|
method: 'password' | 'phone' | 'email';
|
|
}>();
|
|
|
|
// 响应式数据
|
|
const registerForm = ref({
|
|
username: "",
|
|
password: "",
|
|
confirmPassword: "",
|
|
email: '',
|
|
phonenumber: '',
|
|
code: "",
|
|
uuid: "",
|
|
});
|
|
|
|
const codeUrl = ref("");
|
|
|
|
// 分开控制发送验证码和注册的 loading 状态
|
|
const sendCodeLoading = ref(false);
|
|
const registerLoading = ref(false);
|
|
|
|
const registerRef = ref<any>(null);
|
|
|
|
// 表单校验规则
|
|
const registerRules = {
|
|
username: [
|
|
{ required: true, message: "请输入您的账号", trigger: "blur" },
|
|
{ min: 2, max: 20, message: "用户账号长度必须介于 2 和 20 之间", trigger: "blur" }
|
|
],
|
|
password: [
|
|
{ required: true, message: "请输入您的密码", trigger: "blur" },
|
|
{ min: 5, max: 20, message: "用户密码长度必须介于 5 和 20 之间", trigger: "blur" },
|
|
{ pattern: /^[^<>"'|\\]+$/, message: "不能包含非法字符:< > \" ' \\\ |", trigger: "blur" }
|
|
],
|
|
confirmPassword: [
|
|
{ required: true, message: "请再次输入您的密码", trigger: "blur" },
|
|
{
|
|
validator: (rule: any, value: any, callback: any) => {
|
|
if (registerForm.value.password !== value) {
|
|
callback(new Error("两次输入的密码不一致"));
|
|
} else {
|
|
callback();
|
|
}
|
|
},
|
|
trigger: "blur"
|
|
}
|
|
],
|
|
code: [{ required: true, message: "请输入验证码", trigger: "change" }]
|
|
};
|
|
|
|
// 用户仓库
|
|
const userStore = useUserStore();
|
|
|
|
// 获取图形验证码
|
|
function getCode() {
|
|
if (!props.captchaEnabled) return;
|
|
getCodeImg().then((res: any) => {
|
|
codeUrl.value = "data:image/gif;base64," + res.img;
|
|
registerForm.value.uuid = res.uuid;
|
|
});
|
|
}
|
|
|
|
// 发送验证码
|
|
function sendCode() {
|
|
if (props.method === 'email') {
|
|
sendEmailCode(registerForm.value, 'register');
|
|
} else if (props.method === 'phone') {
|
|
sendPhoneCode(registerForm.value, 'register');
|
|
}
|
|
}
|
|
|
|
// 注册提交
|
|
function handleRegister() {
|
|
registerRef.value.validate((valid: boolean) => {
|
|
if (valid) {
|
|
loading.value = true;
|
|
userStore.register(registerForm.value, props.method).then(() => {
|
|
uni.showModal({
|
|
title: "系统提示",
|
|
content: `<font color='red'>恭喜你,您的账号 ${registerForm.value.username} 注册成功!</font>`,
|
|
showCancel: false,
|
|
success: () => {
|
|
uni.redirectTo({
|
|
url: "/pages/login/login" // 跳转到登录页
|
|
});
|
|
}
|
|
});
|
|
}).catch(() => {
|
|
getCode();
|
|
}).finally(() => {
|
|
loading.value = false;
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
// 页面加载时获取验证码
|
|
onMounted(() => {
|
|
getCode();
|
|
});
|
|
</script>
|
|
|
|
<template>
|
|
<view class="register-container">
|
|
<uni-forms
|
|
ref="registerRef"
|
|
:model="registerForm"
|
|
:rules="registerRules"
|
|
class="register-form"
|
|
>
|
|
<!-- 邮箱输入 -->
|
|
<uni-forms-item prop="email" v-if="method === 'email'">
|
|
<uni-easyinput
|
|
v-model="registerForm.email"
|
|
type="text"
|
|
placeholder="邮箱"
|
|
prefixIcon="email"
|
|
/>
|
|
</uni-forms-item>
|
|
|
|
<!-- 手机号输入 -->
|
|
<uni-forms-item prop="phonenumber" v-else-if="method === 'phone'">
|
|
<uni-easyinput
|
|
v-model="registerForm.phonenumber"
|
|
type="text"
|
|
placeholder="手机号"
|
|
prefixIcon="phone"
|
|
/>
|
|
</uni-forms-item>
|
|
|
|
<!-- 用户名输入 -->
|
|
<uni-forms-item prop="username" v-else>
|
|
<uni-easyinput
|
|
v-model="registerForm.username"
|
|
type="text"
|
|
placeholder="账号"
|
|
prefixIcon="user"
|
|
/>
|
|
</uni-forms-item>
|
|
|
|
<!-- 密码输入 -->
|
|
<uni-forms-item prop="password">
|
|
<uni-easyinput
|
|
v-model="registerForm.password"
|
|
type="password"
|
|
placeholder="密码"
|
|
prefixIcon="lock"
|
|
@keyup.enter="handleRegister"
|
|
/>
|
|
</uni-forms-item>
|
|
|
|
<!-- 确认密码输入 -->
|
|
<uni-forms-item prop="confirmPassword">
|
|
<uni-easyinput
|
|
v-model="registerForm.confirmPassword"
|
|
type="password"
|
|
placeholder="确认密码"
|
|
prefixIcon="lock"
|
|
@keyup.enter="handleRegister"
|
|
/>
|
|
</uni-forms-item>
|
|
|
|
<!-- 验证码输入 -->
|
|
<uni-forms-item prop="code">
|
|
<view class="code-input">
|
|
<uni-easyinput
|
|
v-model="registerForm.code"
|
|
type="text"
|
|
placeholder="验证码"
|
|
prefixIcon="code"
|
|
@keyup.enter="handleRegister"
|
|
/>
|
|
|
|
<!-- 图形验证码或发送按钮 -->
|
|
<view class="code-action">
|
|
<uni-image
|
|
v-if="captchaEnabled && method === 'password'"
|
|
:src="codeUrl"
|
|
class="code-img"
|
|
@click="getCode"
|
|
mode="aspectFill"
|
|
/>
|
|
<uni-button
|
|
v-else
|
|
type="primary"
|
|
size="mini"
|
|
@click="sendCode"
|
|
:loading="loading"
|
|
>
|
|
发送验证码
|
|
</uni-button>
|
|
</view>
|
|
</view>
|
|
</uni-forms-item>
|
|
|
|
<!-- 注册按钮 -->
|
|
<uni-forms-item>
|
|
<button
|
|
type="primary"
|
|
size="default"
|
|
class="register-btn"
|
|
:loading="loading"
|
|
@click="handleRegister"
|
|
>
|
|
注册
|
|
</button>
|
|
</uni-forms-item>
|
|
|
|
<!-- 已有账号跳转 -->
|
|
<view class="login-link">
|
|
<text class="question-text">已有账号?</text>
|
|
<navigator url="/pages/login" class="link-type">立即登录</navigator>
|
|
</view>
|
|
</uni-forms>
|
|
</view>
|
|
</template>
|
|
|
|
<style scoped lang="scss">
|
|
.register-container {
|
|
padding: 40rpx;
|
|
}
|
|
|
|
.register-form {
|
|
background-color: #fff;
|
|
padding: 60rpx;
|
|
border-radius: 16rpx;
|
|
box-shadow: 0 10rpx 30rpx rgba(0, 0, 0, 0.05);
|
|
}
|
|
|
|
.code-input {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 20rpx;
|
|
}
|
|
|
|
.code-action {
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.code-img {
|
|
width: 180rpx;
|
|
height: 70rpx;
|
|
border-radius: 8rpx;
|
|
}
|
|
|
|
.register-btn {
|
|
width: 100%;
|
|
height: 80rpx;
|
|
line-height: 80rpx;
|
|
font-size: 30rpx;
|
|
border-radius: 40rpx;
|
|
margin-top: 20rpx;
|
|
}
|
|
|
|
.login-link {
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
margin-top: 40rpx;
|
|
font-size: 26rpx;
|
|
color: #666;
|
|
}
|
|
|
|
.link-type {
|
|
color: #007aff;
|
|
margin-left: 10rpx;
|
|
text-decoration: underline;
|
|
}
|
|
</style> |