307 lines
8.4 KiB
Vue
307 lines
8.4 KiB
Vue
|
|
<template>
|
||
|
|
<view class="register-container p-30">
|
||
|
|
<!-- 顶部 Logo -->
|
||
|
|
<image
|
||
|
|
class="logo"
|
||
|
|
src="@/static/system/login/logo.png"
|
||
|
|
mode="aspectFit"
|
||
|
|
></image>
|
||
|
|
|
||
|
|
<!-- 表单区域 -->
|
||
|
|
<view class="form-card">
|
||
|
|
<!-- 头像和标题 -->
|
||
|
|
<view
|
||
|
|
class="wi-180 he-240 mx-auto r-md mb-20"
|
||
|
|
style="border: 1px solid #cccccc"
|
||
|
|
>
|
||
|
|
<CustomUpload @select="afterRead" :sourceType="['camera']">
|
||
|
|
<view class="wh-full flex-col-center">
|
||
|
|
<svg
|
||
|
|
t="1729656215869"
|
||
|
|
class="icon"
|
||
|
|
viewBox="0 0 1024 1024"
|
||
|
|
version="1.1"
|
||
|
|
xmlns="http://www.w3.org/2000/svg"
|
||
|
|
p-id="5302"
|
||
|
|
width="32"
|
||
|
|
height="32"
|
||
|
|
>
|
||
|
|
<path
|
||
|
|
d="M851.552 890.88 172.448 890.88c-74.592 0-135.296-60.672-135.296-135.296L37.152 370.752c0-74.624 60.672-135.328 135.296-135.328l132.16 0L302.912 195.904c0-34.624 28.192-62.816 62.816-62.816l302.016 0c29.408 0 53.312 23.904 53.312 53.312l0 49.024 130.464 0c74.592 0 135.296 60.672 135.296 135.328l0 384.832C986.816 830.208 926.144 890.88 851.552 890.88zM172.448 283.456c-48.128 0-87.296 39.168-87.296 87.328l0 384.832c0 48.128 39.168 87.296 87.296 87.296l679.104 0c48.128 0 87.296-39.168 87.296-87.296L938.848 370.752c0-48.16-39.168-87.328-87.296-87.328L716.8 283.424c-24.096 0-43.712-19.616-43.712-43.712L673.088 186.4c0-2.944-2.368-5.312-5.312-5.312l-302.016 0c-8.16 0-14.816 6.656-14.816 14.816L350.944 237.12c0 25.536-20.768 46.304-46.304 46.304L172.448 283.424zM512 755.84c-107.04 0-194.08-87.072-194.08-194.08S404.992 367.68 512 367.68s194.08 87.072 194.08 194.08S619.04 755.84 512 755.84zM512 415.68c-80.576 0-146.08 65.536-146.08 146.08S431.456 707.84 512 707.84s146.08-65.536 146.08-146.08S592.576 415.68 512 415.68zM816.8 438.016c-25.568 0-46.336-20.768-46.336-46.336s20.768-46.336 46.336-46.336 46.336 20.768 46.336 46.336S842.368 438.016 816.8 438.016zM816.8 390.016l-1.664 1.664c0 0.896 0.736 1.664 1.664 1.664L816.8 390.016z"
|
||
|
|
fill="#cdcdcd"
|
||
|
|
p-id="5303"
|
||
|
|
></path>
|
||
|
|
</svg>
|
||
|
|
</view>
|
||
|
|
</CustomUpload>
|
||
|
|
<!-- <text class="verify-title">身份验证</text> -->
|
||
|
|
</view>
|
||
|
|
|
||
|
|
<!-- 输入框 -->
|
||
|
|
<view class="input-group">
|
||
|
|
<view class="input-item">
|
||
|
|
<text class="label"><text class="required">*</text>姓名:</text>
|
||
|
|
<input
|
||
|
|
class="input-field"
|
||
|
|
type="text"
|
||
|
|
v-model="formData.name"
|
||
|
|
placeholder="请输入姓名"
|
||
|
|
/>
|
||
|
|
</view>
|
||
|
|
<view class="input-item">
|
||
|
|
<text class="label"><text class="required">*</text>手机号码:</text>
|
||
|
|
<input
|
||
|
|
class="input-field"
|
||
|
|
type="number"
|
||
|
|
v-model="formData.phone"
|
||
|
|
placeholder="请输入手机号码"
|
||
|
|
maxlength="11"
|
||
|
|
/>
|
||
|
|
</view>
|
||
|
|
<view class="input-item verification-code-item">
|
||
|
|
<text class="label"><text class="required">*</text>验证码:</text>
|
||
|
|
<input
|
||
|
|
class="input-field verification-code-input"
|
||
|
|
type="number"
|
||
|
|
v-model="formData.code"
|
||
|
|
placeholder="请输入验证码"
|
||
|
|
maxlength="6"
|
||
|
|
/>
|
||
|
|
<button
|
||
|
|
class="get-code-btn"
|
||
|
|
:disabled="isCountingDown"
|
||
|
|
@click="handleGetCode"
|
||
|
|
>
|
||
|
|
{{ countdownText }}
|
||
|
|
</button>
|
||
|
|
</view>
|
||
|
|
</view>
|
||
|
|
|
||
|
|
<!-- 验证按钮 -->
|
||
|
|
<button class="verify-btn" @click="handleVerify">验证</button>
|
||
|
|
</view>
|
||
|
|
</view>
|
||
|
|
</template>
|
||
|
|
|
||
|
|
<script lang="ts" setup>
|
||
|
|
import { ref, reactive, computed } from "vue";
|
||
|
|
import CustomUpload from "/src/components/BasicUpload/CustomUpload.vue";
|
||
|
|
import { onUnmounted } from "vue";
|
||
|
|
import { hideLoading, showLoading } from "@/utils/uniapp";
|
||
|
|
import { attachmentUpload } from "@/api/system/upload";
|
||
|
|
|
||
|
|
const formData = reactive({
|
||
|
|
name: "",
|
||
|
|
phone: "",
|
||
|
|
code: "",
|
||
|
|
avatar_url: "",
|
||
|
|
});
|
||
|
|
|
||
|
|
const countdown = ref(60);
|
||
|
|
const isCountingDown = ref(false);
|
||
|
|
let timer: NodeJS.Timeout | null = null;
|
||
|
|
const countdownText = computed(() => {
|
||
|
|
return isCountingDown.value ? `${countdown.value}s后重试` : "获取验证码";
|
||
|
|
});
|
||
|
|
|
||
|
|
const handleGetCode = () => {
|
||
|
|
if (isCountingDown.value) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
if (!formData.phone) {
|
||
|
|
uni.showToast({ title: "请输入手机号码", icon: "none" });
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
console.log("获取验证码,手机号:", formData.phone);
|
||
|
|
|
||
|
|
isCountingDown.value = true;
|
||
|
|
countdown.value = 60; // 重置倒计时
|
||
|
|
timer = setInterval(() => {
|
||
|
|
if (countdown.value > 1) {
|
||
|
|
countdown.value--;
|
||
|
|
} else {
|
||
|
|
if (timer) clearInterval(timer);
|
||
|
|
timer = null;
|
||
|
|
isCountingDown.value = false;
|
||
|
|
}
|
||
|
|
}, 1000);
|
||
|
|
};
|
||
|
|
|
||
|
|
const handleVerify = () => {
|
||
|
|
if (
|
||
|
|
!formData.name ||
|
||
|
|
!formData.phone ||
|
||
|
|
!formData.code ||
|
||
|
|
!formData.avatar_url
|
||
|
|
) {
|
||
|
|
uni.showToast({ title: "请填写完整的验证信息", icon: "none" });
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
console.log("提交验证信息:", formData);
|
||
|
|
uni.showToast({ title: "验证成功 (模拟)", icon: "success" });
|
||
|
|
};
|
||
|
|
|
||
|
|
async function afterRead(event: any) {
|
||
|
|
showLoading({ title: "上传中" });
|
||
|
|
const { result } = await attachmentUpload(event.tempFilePaths[0]);
|
||
|
|
hideLoading();
|
||
|
|
formData.avatar_url = result[0].filePath;
|
||
|
|
}
|
||
|
|
|
||
|
|
onUnmounted(() => {
|
||
|
|
if (timer) {
|
||
|
|
clearInterval(timer);
|
||
|
|
}
|
||
|
|
});
|
||
|
|
</script>
|
||
|
|
|
||
|
|
<style scoped lang="scss">
|
||
|
|
.register-container {
|
||
|
|
display: flex;
|
||
|
|
flex-direction: column;
|
||
|
|
align-items: center;
|
||
|
|
// height: 100vh; // 使用 min-height 避免内容过长时截断
|
||
|
|
min-height: 100vh;
|
||
|
|
background: url("@/static/base/bg.jpg") no-repeat;
|
||
|
|
background-size: 100% 100%;
|
||
|
|
padding: 20px;
|
||
|
|
box-sizing: border-box;
|
||
|
|
}
|
||
|
|
|
||
|
|
.logo {
|
||
|
|
width: 250px; // 根据实际 logo 尺寸调整
|
||
|
|
height: 60px; // 根据实际 logo 尺寸调整
|
||
|
|
margin-top: 40px; // 与顶部的距离
|
||
|
|
margin-bottom: 30px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.form-card {
|
||
|
|
background-color: #ffffff;
|
||
|
|
border-radius: 15px;
|
||
|
|
padding: 30px 25px;
|
||
|
|
box-sizing: border-box;
|
||
|
|
width: 100%;
|
||
|
|
max-width: 400px; // 限制最大宽度
|
||
|
|
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
|
||
|
|
display: flex;
|
||
|
|
flex-direction: column;
|
||
|
|
align-items: center;
|
||
|
|
}
|
||
|
|
|
||
|
|
.avatar-section {
|
||
|
|
display: flex;
|
||
|
|
flex-direction: column;
|
||
|
|
align-items: center;
|
||
|
|
margin-bottom: 25px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.avatar {
|
||
|
|
width: 70px;
|
||
|
|
height: 70px;
|
||
|
|
border-radius: 50%;
|
||
|
|
margin-bottom: 10px;
|
||
|
|
background-color: #f0f0f0; // 头像占位背景色
|
||
|
|
}
|
||
|
|
|
||
|
|
.verify-title {
|
||
|
|
font-size: 16px;
|
||
|
|
color: #333;
|
||
|
|
font-weight: bold;
|
||
|
|
}
|
||
|
|
|
||
|
|
.input-group {
|
||
|
|
width: 100%;
|
||
|
|
margin-bottom: 20px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.input-item {
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
margin-bottom: 20px;
|
||
|
|
border-bottom: 1px solid #eee; // 输入框底部线条
|
||
|
|
padding-bottom: 10px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.label {
|
||
|
|
width: 80px; // 固定标签宽度
|
||
|
|
font-size: 14px;
|
||
|
|
color: #666;
|
||
|
|
flex-shrink: 0; // 防止标签被压缩
|
||
|
|
display: flex; // 使星号和文字对齐
|
||
|
|
align-items: center;
|
||
|
|
}
|
||
|
|
|
||
|
|
.required {
|
||
|
|
color: red;
|
||
|
|
margin-right: 4px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.input-field {
|
||
|
|
flex-grow: 1;
|
||
|
|
font-size: 14px;
|
||
|
|
border: none; // 移除默认边框
|
||
|
|
outline: none; // 移除选中时的轮廓
|
||
|
|
padding: 5px 0; // 微调输入框内边距
|
||
|
|
color: #333;
|
||
|
|
}
|
||
|
|
|
||
|
|
.verification-code-item {
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
justify-content: space-between; // 让输入框和按钮分开
|
||
|
|
}
|
||
|
|
|
||
|
|
.verification-code-input {
|
||
|
|
flex-grow: 1; // 输入框占据剩余空间
|
||
|
|
margin-right: 10px; // 与按钮的间距
|
||
|
|
}
|
||
|
|
|
||
|
|
.get-code-btn {
|
||
|
|
background-color: #ffffff;
|
||
|
|
color: #007aff; // 按钮文字颜色
|
||
|
|
border: 1px solid #007aff; // 按钮边框
|
||
|
|
font-size: 12px;
|
||
|
|
padding: 8px 10px;
|
||
|
|
border-radius: 20px;
|
||
|
|
white-space: nowrap; // 防止文字换行
|
||
|
|
line-height: 1; // 确保文字垂直居中
|
||
|
|
height: auto; // 自适应高度
|
||
|
|
margin: 0; // 移除默认外边距
|
||
|
|
flex-shrink: 0; // 防止按钮被压缩
|
||
|
|
}
|
||
|
|
|
||
|
|
.get-code-btn[disabled] {
|
||
|
|
background-color: #f8f8f8;
|
||
|
|
color: #cccccc;
|
||
|
|
border-color: #cccccc;
|
||
|
|
}
|
||
|
|
// 移除按钮默认的边框伪元素
|
||
|
|
.get-code-btn::after {
|
||
|
|
border: none;
|
||
|
|
}
|
||
|
|
|
||
|
|
.verify-btn {
|
||
|
|
width: 100%;
|
||
|
|
height: 45px;
|
||
|
|
line-height: 45px;
|
||
|
|
background: linear-gradient(to right, #ff8c4a, #ff5e62); // 按钮渐变色
|
||
|
|
color: #ffffff;
|
||
|
|
font-size: 16px;
|
||
|
|
border-radius: 25px;
|
||
|
|
margin-top: 10px;
|
||
|
|
border: none; // 移除默认边框
|
||
|
|
box-shadow: 0 2px 5px rgba(255, 100, 100, 0.3); // 添加阴影
|
||
|
|
}
|
||
|
|
// 移除按钮默认的边框伪元素
|
||
|
|
.verify-btn::after {
|
||
|
|
border: none;
|
||
|
|
}
|
||
|
|
|
||
|
|
// 可以在这里添加 placeholder 的样式
|
||
|
|
input::placeholder {
|
||
|
|
color: #cccccc;
|
||
|
|
font-size: 14px;
|
||
|
|
}
|
||
|
|
</style>
|