上次完成了註冊頁面的基本設計,下一步就是最後的存入資料庫的部分和介面的美化。
由於使用者資訊的密碼資訊要進行保密,所以我打算設計兩個資料庫表來儲存有關使用者的資料。一個時有關於使用者密碼隱私的電話和密碼錶,另一個是使用者可以自己設計的資訊表,這也方便登入後的資料讀取,也減少了洩露使用者密碼的可能。
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); }