共享益——成果展示
頁面展示
前端部分開發程式碼:
<script setup>
import { User, Lock } from "@element-plus/icons-vue";
import { ElMessage } from "element-plus";
import { ref } from "vue";
import { userRegisterService, userLoginService } from "@/api/user.js";
//控制註冊與登入表單的顯示, 預設顯示註冊
const isRegister = ref(false);
//用於註冊的資料模型
const registerData = ref({
username: "",
password: "",
rePassword: "",
});
//定義函式,清空資料模型的資料
const clearRegisterData = () => {
registerData.value = {
username: "",
password: "",
rePassword: "",
};
};
//自定義確認密碼的校驗函式
const rePasswordValid = (rule, value, callback) => {
if (value == null || value === "") {
return callback(new Error("請再次確認密碼"));
}
if (registerData.value.password !== value) {
return callback(new Error("兩次輸入密碼不一致"));
}
};
//用於註冊的表單校驗模型
const registerDataRules = ref({
username: [
{ required: true, message: "請輸入使用者名稱", trigger: "blur" },
{ min: 5, max: 16, message: "使用者名稱的長度必須為5~16位", trigger: "blur" },
],
password: [
{ required: true, message: "請輸入密碼", trigger: "blur" },
{ min: 5, max: 16, message: "密碼長度必須為5~16位", trigger: "blur" },
],
rePassword: [{ validator: rePasswordValid, trigger: "blur" }],
});
// 呼叫後臺介面完成註冊
const register = async () => {
let result = await userRegisterService(registerData.value);
console.log("result :>> ", result);
if (result.code === 0) {
alert(result.msg ? result.msg : "註冊成功");
} else {
alert("註冊失敗");
}
};
import { useRouter } from 'vue-router';
import { useTokenStore } from '@/stores/token.js';
const router = useRouter();
const tokenStore = useTokenStore();
// 登入函式
const login = async () => {
let result = await userLoginService(registerData.value);
//儲存token
tokenStore.setToken(result.data)
ElMessage.success('登入成功!')
router.push('/')
};
</script>
<template>
<el-row class="login-page">
<el-col :span="12" class="bg"></el-col>
<el-col :span="6" :offset="3" class="form">
<!-- 登錄檔單 -->
<!-- 登錄檔單 -->
<el-form ref="form" size="large" autocomplete="off" v-if="isRegister" :model="registerData"
:rules="registerDataRules">
<el-form-item>
<h1>註冊</h1>
</el-form-item>
<el-form-item prop="username">
<el-input :prefix-icon="User" placeholder="請輸入使用者名稱" v-model="registerData.username"></el-input>
</el-form-item>
<el-form-item prop="password">
<el-input :prefix-icon="Lock" type="password" placeholder="請輸入密碼"
v-model="registerData.password"></el-input>
</el-form-item>
<el-form-item prop="rePassword">
<el-input :prefix-icon="Lock" type="password" placeholder="請輸入再次密碼"
v-model="registerData.rePassword"></el-input>
</el-form-item>
<!-- 註冊按鈕 -->
<el-form-item>
<el-button class="button" type="primary" auto-insert-space @click="register">
註冊
</el-button>
</el-form-item>
<el-form-item class="flex">
<el-link type="info" :underline="false" @click="
isRegister = false;
clearRegisterData();
">
← 返回
</el-link>
</el-form-item>
</el-form>
<!-- 登入表單 -->
<el-form ref="form" size="large" autocomplete="off" v-else :model="registerData" :rules="registerDataRules">
<el-form-item>
<h1>登入</h1>
</el-form-item>
<el-form-item prop="username">
<el-input :prefix-icon="User" placeholder="請輸入使用者名稱" v-model="registerData.username"></el-input>
</el-form-item>
<el-form-item prop="password">
<el-input name="password" :prefix-icon="Lock" type="password" placeholder="請輸入密碼"
v-model="registerData.password"></el-input>
</el-form-item>
<el-form-item class="flex">
<div class="flex">
<el-checkbox>記住我</el-checkbox>
<el-link type="primary" :underline="false">忘記密碼?</el-link>
</div>
</el-form-item>
<!-- 登入按鈕 -->
<el-form-item>
<el-button class="button" type="primary" auto-insert-space @click="login">登入</el-button>
</el-form-item>
<el-form-item class="flex">
<el-link type="info" :underline="false" @click="
isRegister = true;
clearRegisterData();
">
註冊 →
</el-link>
</el-form-item>
</el-form>
</el-col>
</el-row>
</template>
<style lang="scss" scoped>
/* 樣式 */
.login-page {
height: 100vh;
background-color: #fff;
.bg {
background: url("@/assets/logo2.png") no-repeat 60% center / 240px auto,
url("@/assets/login_bg.jpg") no-repeat center / cover;
border-radius: 0 20px 20px 0;
}
.form {
display: flex;
flex-direction: column;
justify-content: center;
user-select: none;
.title {
margin: 0 auto;
}
.button {
width: 100%;
}
.flex {
width: 100%;
display: flex;
justify-content: space-between;
}
}
}
</style>
後端部分開發程式碼
1.郵箱驗證
package com.example.service.Impl;
import com.example.mapper.UserMapper;
import com.example.pojo.Result;
import com.example.service.IMailService;
import jakarta.mail.MessagingException;
import jakarta.mail.internet.MimeMessage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;
import java.util.Random;
import java.util.concurrent.TimeUnit;
@Service
public class IMailServiceImpl implements IMailService {
@Autowired
private UserMapper userMapper;
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Autowired
private JavaMailSender mailSender;
@Value("${spring.mail.username}")
private String mailUserName;
@Override
public Result getCode(String username, String email) {
// 非空校驗
if (null == username || "".equals(username)) return Result.error("賬號不能為空!");
if (null == email || "".equals(email)) return Result.error("郵箱不能為空!");
// System.out.println(staffNumber);
// System.out.println(mailAddress);
// 賬號存在校驗
String email_user = userMapper.getEmailByUsername(username);
// System.out.println(email);
if (email_user == null) return Result.error("郵箱不存在!");
if (!email_user.equals(email)) return Result.error("郵箱不匹配!");
ValueOperations<String, String> operations = stringRedisTemplate.opsForValue();
String verifyCode = operations.get("verify");
// 使用當前時間作為種子值
long seed = System.currentTimeMillis();
Random random = new Random(seed);
// if (verifyCode == null) {
verifyCode = String.valueOf(random.nextInt(899999) + 100000);//生成簡訊驗證碼
// }
// 驗證碼存入redis並設定過期時間
operations.set("verify", verifyCode, 5, TimeUnit.MINUTES);
// 編寫郵箱內容
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("<html><head><title></title></head><body>");
stringBuilder.append("您好<br/>");
stringBuilder.append("您的驗證碼是:").append(verifyCode).append("<br/>");
stringBuilder.append("您可以複製此驗證碼並返回至共享益找回密碼頁面,以驗證您的郵箱。<br/>");
stringBuilder.append("此驗證碼只能使用一次,在");
// stringBuilder.append(overtime.toString());
stringBuilder.append("5分鐘內有效。驗證成功則自動失效。<br/>");
stringBuilder.append("如果您沒有進行上述操作,請忽略此郵件。");
MimeMessage mimeMessage = mailSender.createMimeMessage();
// 發件配置併傳送郵件
try {
MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(mimeMessage, true);
//這裡只是設定username 並沒有設定host和password,因為host和password在springboot啟動建立JavaMailSender例項的時候已經讀取了
mimeMessageHelper.setFrom(mailUserName);
// 使用者的郵箱地址
mimeMessageHelper.setTo(email);
// 郵件的標題
mimeMessage.setSubject("郵箱驗證-共享益");
// 上面所拼接的郵件內容
mimeMessageHelper.setText(stringBuilder.toString(), true);
mailSender.send(mimeMessage);
} catch (MessagingException e) {
e.printStackTrace();
}
return Result.success("獲取驗證碼成功,請檢視移步您的郵箱" + email + "檢視驗證碼!");
}
}
2。訊息處理
package com.example.mapper;
import com.example.pojo.Message;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import java.util.List;
@Mapper
public interface MessageMapper {
//傳送訊息,將傳送的訊息新增到資料庫
@Insert("INSERT INTO message (id, send_id, receive_id, message, time) VALUES (#{id}, #{sendId}, #{receiveId}, #{message}, now())")
void sendMessage(Message message);
//根據自己的id查詢所有給自己傳送過訊息的使用者id
@Select("SELECT DISTINCT send_id FROM message WHERE receive_id = #{id}")
List<Integer> findAllSendId(Integer id);
//根據自己的id查詢所有自己接受到訊息的使用者id
@Select("SELECT DISTINCT receive_id FROM message WHERE send_id = #{id}")
List<Integer> findAllReceiveId(Integer id);
//根據自己的id查詢所有與自己有過會話的使用者id 並根據時間排序
@Select("""
SELECT id
FROM(
SELECT DISTINCT id ,MAX(time) as time
FROM (
SELECT DISTINCT receive_id AS id, MAX(time) as time
FROM message
WHERE send_id = #{id}
GROUP BY receive_id
UNION
SELECT DISTINCT send_id AS id, MAX(time) as time
FROM message
WHERE receive_id = #{id}
GROUP BY send_id
) merged
GROUP BY id
ORDER BY time DESC
) merge
ORDER BY time DESC
""")
List<Integer> findAllUserId(Integer id);
//根據自己的id和另一個人的id查詢所有的訊息 並根據時間先後排序
@Select("SELECT * FROM message WHERE (send_id = #{myId} AND receive_id = #{otherId}) OR (send_id = #{otherId} AND receive_id = #{myId}) ORDER BY time ASC")
List<Message> findAllMessage(Integer myId, Integer otherId);
//刪除與某個人的全部訊息
@Delete("DELETE FROM message WHERE (send_id = #{myId} AND receive_id = #{otherId}) OR (send_id = #{otherId} AND receive_id = #{myId})")
void deleteAllMessage(Integer myId, Integer otherId);
}