2024/05/20(团队开发)
上次完成了注册页面的基本设计,下一步就是最后的存入数据库的部分和界面的美化。
由于用户信息的密码信息要进行保密,所以我打算设计两个数据库表来存储有关用户的数据。一个时有关于用户密码隐私的电话和密码表,另一个是用户可以自己设计的信息表,这也方便登录后的数据读取,也减少了泄露用户密码的可能。
create table user ( id int auto_increment primary key, headshot varchar(200) null, username varchar(20) null, phone char(11) not null, gender char(2) null, birthday date null, location varchar(50) null, message varchar(100) null, account varchar(16) not null, constraint user_pk unique (phone) ) charset = utf8;
create table userprivacy ( id int auto_increment primary key, phone char(11) not null, password varchar(32) not null, constraint userprivacy_pk unique (phone) ) charset = utf8;
完整的注册页面
<template> <view class="register-container"> <!-- 获取验证码 --> <!-- v-if="!idlogin&&verifycode" --> <view v-if="!passwordInput" class="getcodecontainer"> <view class="logo"> <!-- 这里放置你的应用 logo --> <image src="/static/logo.png" class="logo-img" mode="aspectFit" /> </view> <view class="form-group"> <text class="label">手机号:</text> <input type="tel" v-model="phoneNumber" placeholder="请输入手机号" /> </view> <view class="form-group"> <text class="label">验证码:</text> <input type="text" v-model="verificationCode" placeholder="请输入验证码" /> <button @click="getVerificationCode" :disabled="countdown > 0||phoneNumber.length !== 11||!isPhoneNumberValid" :class="{ 'code-btn-active': countdown <= 0 }">{{ countdown > 0 ? '重新获取('+ countdown + ' s)' : '获取验证码' }}</button> </view> <button class="regis-btn" @click="verificat" :disabled="phoneNumber.length !== 11 || verificationCode === ''|| !isPhoneNumberValid">注册</button> </view> <view v-else class="getcodecontainer"> <view class="logo"> <!-- 这里放置你的应用 logo --> <image src="/static/logo.png" class="logo-img" mode="aspectFit" /> </view> <view class="form-group"> <text class="label">设置密码:</text> <input type="password" v-model="password" placeholder="请输入密码" /> </view> <view class="form-group"> <text class="password-requirement">8-20个字符,必须包含字母和数字</text> </view> <view class="form-group"> <text class="label">确认密码:</text> <input type="password" v-model="confirmPassword" placeholder="请再次输入密码" @blur="checkPasswordMatch" /> </view> <button class="regis-btn" @click="register" :disabled="!isFormValid">注册</button> <text class="error-msg">{{passwordError}}</text> </view> <view class="login-link" @click="goToLoginPage">已有账号,去登录</view> </view> </view> </template> <script> export default { data() { return { password: '', confirmPassword: '', phoneNumber: '', verificationCode: '', countdown: 0, passwordInput: false, passwordError: '' }; }, computed: { isPhoneNumberValid() { return /^\d{11}$/.test(this.phoneNumber); // 使用正则表达式检验电话号码是否全是数字且长度为11位 }, isPasswordMatch() { return this.password === this.confirmPassword; }, isPasswordValid() { return this.password.length >= 8 && this.password.length <= 20 && /\d/.test(this.password) && /[a-zA-Z]/.test(this.password); }, isFormValid() { return this.isPasswordMatch && this.isPasswordValid; } }, methods: { goToLoginPage()//跳转登录 { uni.redirectTo({ url:"/pages/userinformation/login/login" }) }, checkPasswordMatch() { if (!this.isPasswordMatch) { this.passwordError = '两次输入的密码不一致'; } else { this.passwordError = ''; } }, verificat() {//验证码验证 uni.request({ url:this.$BASE_URL.BASE_URL+"/verifySmsCode", data:{ phone:this.phoneNumber, code:this.verificationCode }, success: (res) => { console.log(res.data.code); if(res.data.code) { uni.showToast({ title:"验证成功", }); this.passwordInput=true; } else{ uni.showToast({ title:"验证码过期或错误", icon:"none" }); } } }) }, register() { // 创建一个包含 phoneNumber 和 password 的实体对象 const requestBody = { phone: this.phoneNumber, password: this.password }; // 发送 POST 请求 uni.request({ url: this.$BASE_URL.BASE_URL+"/register", method: 'POST', data: requestBody, success: (res) => { // 请求成功处理 if(res.data.code) { uni.showToast({ title:"注册成功", }); this.goToLoginPage(); } else{ uni.showToast({ title:res.data.msg, icon:'none' }); } }, fail: (err) => { // 请求失败处理 console.error('Request failed:', err); } }); }, getVerificationCode() {//获取验证码 var self=this // 模拟发送验证码 // 模拟倒计时 this.countdown = 60; // 倒计时时间(秒) const timer = setInterval(() => { if (this.countdown > 0) { this.countdown--; } else { clearInterval(timer); this.countdown = 0; } }, 1000); uni.hideKeyboard() uni.request({ url:this.$BASE_URL.BASE_URL+"/getcode", data:{ phone:self.phoneNumber }, success:(res)=>{ if(res.data.code) { console.log(res.data) uni.showToast({ title:"验证码已发送", }); } else{ uni.showToast({ title:"验证码获取失败", icon: 'error', }) } }, fail: () => { uni.showToast({ title:"验证码获取失败", icon: 'error', }) } }) }, } }; </script> <style> .error-msg { margin-top: ; color: red; font-size: 12px; } .password-requirement { color: #999; font-size: 12px; } html, body { height: 100%; /* 设置页面高度为100% */ margin: 0; /* 去除页面的默认边距 */ } .register-container{ background: linear-gradient(to bottom, #FFFFE0 0%, #87CEEB 250%); /* 使用线性渐变背景 */ height: 700px; /* 让容器充满整个页面 */ padding: 20px; /* 设置内边距 */ border-radius: 10px; /* 设置圆角 */ display: flex; /* 使用 Flex 布局 */ flex-direction: column; /* 垂直布局 */ justify-content: top; /* 内容垂直居中 */ align-items: center; /* 内容水平居中 */ } .getcodecontainer { background: linear-gradient(to bottom, #FFFFE0 0%, #87CEEB 250%); /* 使用线性渐变背景 */ height: 80%; /* 让容器充满整个页面 */ padding: 20px; /* 设置内边距 */ border-radius: 10px; /* 设置圆角 */ display: flex; /* 使用 Flex 布局 */ flex-direction: column; /* 垂直布局 */ justify-content: top; /* 内容垂直居中 */ align-items: center; /* 内容水平居中 */ } .logo { margin-bottom: 30px; } .logo-img { width: 100px; height: 100px; border-radius: 50%; } .form-group { margin-bottom: 20px; display: flex; align-items: center; justify-content: center; } .label { font-weight: bold; margin-right: 10px; } input { flex: 1; padding: 10px; border-radius: 5px; font-size: 18px; background-color: rgba(255, 255, 255, 0.3); /* 设置背景为浅白色并透明 */ } .code-btn-active { display: flex; /* 使用 flex 布局 */ align-items: center; /* 垂直居中 */ justify-content: center; /* 水平居中 */ padding: 10px 15px; background-color: #00aaff; color: #ffffff; border: none; border-radius: 5px; cursor: pointer; font-size: 14px; transition: background-color 0.3s; height: 45px ; } button{ display: flex; /* 使用 flex 布局 */ align-items: center; /* 垂直居中 */ justify-content: center; /* 水平居中 */ padding: 10px 15px; background-color: #00aaff; color: #ffffff; border: none; border-radius: 5px; cursor: pointer; font-size: 14px; transition: background-color 0.3s; height: 45px ; } /* 禁用状态下的样式保持不变 */ .button:hover { background-color: #0056b3; } button:disabled { background-color: #ccc; cursor: not-allowed; height: 45px ; } .regis-btn { width: 100%; } /* .countdown { font-size: 12px; color: #888; margin-top: 10px; } */ .code-btn:hover, .regis-btn:hover { background-color: rgba(255, 255, 255, 0.8); /* 鼠标悬停时的背景色,这里使用半透明白色 */ } .login-link { margin-top: 20px; color: #007bff; cursor: pointer; } </style>
后端代码:
controller层:
package com.share.viedo_app.controller; import com.share.viedo_app.pojo.Result; import com.share.viedo_app.pojo.User; import com.share.viedo_app.pojo.UserPrivacy; import com.share.viedo_app.pojo.Video; import com.share.viedo_app.service.UserService; import com.share.viedo_app.util.AliMes; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.web.bind.annotation.*; import java.time.Duration; import java.util.Random; @Slf4j @RestController public class UserController { @Autowired private StringRedisTemplate stringRedisTemplate; @Autowired private UserService userService; @GetMapping("/getcode") public Result getCode(@RequestParam String phone)//发送验证码 { String code = String.valueOf(new Random().nextInt(899999) + 100000); AliMes aliMes=new AliMes(); boolean result=aliMes.sendMes(phone,code); System.out.println(code); if(result) { stringRedisTemplate.opsForValue().set(phone, code, Duration.ofMinutes(5)); System.out.println(result); return Result.success(); } else { return Result.error("短信发送失败"); } } @GetMapping("/verifySmsCode")//验证码验证 public Result verifySmsCode(@RequestParam String phone,@RequestParam String code) { String savedCode = stringRedisTemplate.opsForValue().get(phone); if (savedCode != null && savedCode.equals(code)) { // 验证成功,清除验证码 System.out.println("验证成功"); stringRedisTemplate.delete(phone); return Result.success(); } return Result.error("验证失败,验证码错误或已过期"); } }
service层:
package com.share.viedo_app.service.Impl; import com.share.viedo_app.mapper.UserMapper; import com.share.viedo_app.pojo.User; import com.share.viedo_app.pojo.UserPrivacy; import com.share.viedo_app.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service public class UserServiceImpl implements UserService { @Autowired private UserMapper userMapper; @Override public void register(UserPrivacy userPrivacy) { userMapper.register1(userPrivacy); userMapper.register(userPrivacy); } }
mapper层:
package com.share.viedo_app.mapper; import com.share.viedo_app.pojo.User; import com.share.viedo_app.pojo.UserPrivacy; import com.share.viedo_app.service.UserService; import org.apache.ibatis.annotations.Insert; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Select; import org.apache.ibatis.annotations.Update; @Mapper public interface UserMapper { @Insert("insert into userprivacy( phone, password) values (#{phone},MD5(#{password}))") void register(UserPrivacy userPrivacy); }