Kaynağa Gözat

feat:完善注册功能,包括前后端通信,表单校验等

白白 1 yıl önce
ebeveyn
işleme
28c595c62b

+ 14 - 0
src/apis/user.ts

@@ -1,5 +1,6 @@
 import axiosInstance from "@/apis/axios.config";
 import { type ILoginUserFrom } from "@/types/user";
+import type {UserRegisterDTO} from "@/types/dto";
 
 const USER_PREFIX = "/api/user"
 
@@ -16,7 +17,20 @@ const userApis = {
                 id
             }
         })
+    },
+
+    sendVerifyCode: (officialEmail:string) => {
+        return axiosInstance.get(`${USER_PREFIX}/verifyCode`, {
+            params: {
+                officialEmail
+            }
+        })
+    },
+
+    register: (userRegisterDTO: UserRegisterDTO) => {
+        return axiosInstance.post(`${USER_PREFIX}/register`, userRegisterDTO)
     }
+
 }
 
 export default userApis

+ 9 - 1
src/types/dto.ts

@@ -1,4 +1,4 @@
-import {AssignmentStatus} from './enums';
+import {AssignmentStatus, Role} from './enums';
 
 export interface AssignmentDTO {
     assignmentName: string; // 作业名称不能缺失
@@ -45,4 +45,12 @@ export interface CourseUpdateDTO {
     enrollCode: string; // 选课码不能缺失
 }
 
+export interface UserRegisterDTO {
+    name: string; // 真实姓名不能缺失
+    password: string; // 密码(加密存储)不能缺失
+    officialEmail: string; // 南大官邮,xxx@smail.nju.edu.cn 不能缺失
+    verifyCode: string; // 验证码不能缺失
+    officialNumber: string; // 南大学号、工号不能缺失
+    role: Role; // 用户角色:学生、教师、管理员不能缺失
+}
 

+ 6 - 0
src/types/enums.ts

@@ -19,4 +19,10 @@ export enum AssignmentCompletionStatus {
     // PUBLISHED(4, "PUBLISHED"), // 老师已批改并发布
     // NOT_CORRECTED(5, "NOT_CORRECTED"), //未批改(状态仅老师可见)
     // CORRECTED(6, "CORRECTED") //已批改、但还未发布(状态仅老师可见)
+}
+
+export enum Role {
+    ADMIN = "ADMIN",
+    STUDENT ="STUDENT",
+    TEACHER = "TEACHER"
 }

+ 176 - 75
src/views/LoginPage/component/Register.vue

@@ -1,83 +1,184 @@
 <!-- 注册页面 -->
     <!-- 姓名 密码 重复密码 南大官邮 验证码 南大学号 角色(选择卡) -->
      <!-- TODO:验证码 美化 后端提交  -->
-    <template>
-        <form @submit.prevent="register">
-          <div>
-                <label for="role">账号属性:</label>
-                <select id="role" v-model="formData.role">
-                    <option value="student">学生</option>
-                    <option value="teacher">教师</option>
-                </select>
-          </div>
-          <div>
-            <label for="name">姓名:</label>
-            <input type="text" id="name" v-model="formData.name" required />
-          </div>
-          <div>
-            <label for="password">密码:</label>
-            <input type="password" id="password" v-model="formData.password" required />
-          </div>
-          <div>
-            <label for="confirmPassword">重复密码:</label>
-            <input type="password" id="confirmPassword" v-model="formData.confirmPassword" required />
-            <span v-if="!isPasswordMatch" style="color: red;">两次密码不匹配</span>
-          </div>
-          <div>
-            <label for="email">南大官邮(必填):</label>
-            <input type="email" id="email" v-model="formData.email" required placeholder="xxx@smail.nju.edu.cn" pattern="[^@]+@smail.nju.edu.cn" title="邮箱格式应为xxx@smail.nju.edu.cn" />
-            <small>格式:xxx@smail.nju.edu.cn</small>
-          </div>
-          <!-- TODO: 验证码功能暂时未实现 UserController.java-->
-          <div>
-            <label for="captcha">验证码:</label>
-            <input type="text" id="captcha" v-model="formData.captcha" required />
-          </div>
-          <div>
-            <label for="studentId">南大学号/工号:</label>
-            <input type="text" id="studentId" v-model="formData.studentId" required />
-          </div>
-
-          <button type="submit" :disabled="!isPasswordMatch">注册</button>
-        </form>
-    </template>
-
-<script>
-import { ref, computed, reactive, defineProps } from 'vue';
+<template>
+  <div style="background-color: #8e8e8e; padding: 20px; width: 600px; border-radius: 5px; margin: 20px auto">
+    <!--角色-->
+    <el-form
+        :rules="userRules"
+        :model="userRegisterDTO"
+        ref="formRef"
+        :size="formSize"
+    >
+      <el-form-item label="角色" prop="role">
+        <el-select v-model="userRegisterDTO.role" placeholder="请选择角色">
+          <el-option
+              v-for="item in roleOptions"
+              :key="item.value"
+              :label="item.label"
+              :value="item.value"
+              :disabled="item.disabled"
+          />
+        </el-select>
+      </el-form-item>
 
+      <!--姓名-->
+      <el-form-item label="姓名" prop="name">
+        <el-input v-model="userRegisterDTO.name" placeholder="请输入真实姓名"></el-input>
+      </el-form-item>
 
-export default {
-  name: 'RegistrationForm',
-  setup() {
-    const formData = ref({
-      name: '',
-      password: '',
-      officialEmail: '',
-      verifyCode: '',
-      officialNumber: '',
-      role: ''
-    });
-
-    // 计算属性来检查密码是否匹配
-    const isPasswordMatch = computed(() => {
-      return formData.value.password === formData.value.confirmPassword;
-    });
-
-    const register = () => {
-      if (!isPasswordMatch.value) {
-        alert("两次输入的密码不匹配,请重新输入!");
-        return; // 阻止表单提交
+      <!--学号-->
+      <el-form-item label="学号" prop="officialNumber">
+        <el-input v-model="userRegisterDTO.officialNumber" placeholder="请输入学号"></el-input>
+      </el-form-item>
+
+      <!--邮箱-->
+      <el-form-item label="邮箱" prop="officialEmail">
+        <el-input v-model="userRegisterDTO.officialEmail" placeholder="请输入邮箱"></el-input>
+      </el-form-item>
+
+      <!--密码-->
+      <el-form-item label="密码" prop="password">
+        <el-input v-model="userRegisterDTO.password" placeholder="请输入密码" show-password></el-input>
+      </el-form-item>
+
+      <!--输入验证码-->
+      <!--TODO:发送验证码按钮和输入框在一起,参考登录界面-->
+      <el-form-item label="输入验证码" prop="verifyCode">
+        <el-input v-model="userRegisterDTO.verifyCode" placeholder="输入验证码"></el-input>
+      </el-form-item>
+
+      <el-button @click="sendVerifyCode">发送验证码</el-button>
+      <el-button @click="register(formRef)">注册</el-button>
+    </el-form>
+  </div>
+
+
+</template>
+
+<script lang="ts" setup>
+  import type {UserRegisterDTO} from "@/types/dto";
+  import {reactive, ref} from "vue";
+  import useApis from "@/apis";
+  import {Role} from "@/types/enums";
+  import {type ComponentSize, ElMessage, type FormInstance, type FormRules} from "element-plus";
+  import {useRoute} from "vue-router";
+  import router from "@/router";
+
+  const apis = useApis()
+  let userRegisterDTO = reactive<UserRegisterDTO>({} as UserRegisterDTO)
+
+  const roleOptions = [
+    {
+      label: "学生",
+      value: Role.STUDENT,
+      disabled: false
+    },
+    {
+      label: "教师",
+      value: Role.TEACHER,
+      disabled: true
+    },
+    {
+      label: "管理员",
+      value: Role.ADMIN,
+      disabled: true
+    }
+  ]
+
+  const formSize = ref<ComponentSize>('default')
+  const formRef = ref<FormInstance>()
+  const userRules = reactive<FormRules<UserRegisterDTO>>({
+    role:[
+      {
+        required: true,
+        message: "角色不能为空",
+        trigger: 'change'
+      }
+    ],
+    name: [
+      {
+        required: true,
+        message: "姓名不能为空",
+        trigger: 'blur'
       }
-      //TODO: 在这里添加发送请求到后端的逻辑
-      console.log('注册信息:', formData.value);
-      // 你可以使用 axios 发送请求到你的后端API
-    };
-
-    return {
-      formData,
-      isPasswordMatch,
-      register
-    };
+    ],
+    officialNumber: [
+      {
+        required: true,
+        message: "学号不能为空",
+        trigger: 'blur'
+      }
+    ],
+    officialEmail: [
+      {
+        required: true,
+        message: "邮箱不能为空",
+        trigger: 'blur'
+      }
+    ],
+    password: [
+      {
+        required: true,
+        message: "密码不能为空",
+        trigger: 'blur'
+      }
+    ],
+    verifyCode: [
+      {
+        required: true,
+        message: "验证码不能为空",
+        trigger: 'blur'
+      }
+    ]
+  })
+
+  const register = async (formEl: FormInstance | undefined) => {
+    if (!formEl) return
+    await formEl.validate((valid, fields) => {
+      if (valid) {
+        console.log("合法输入")
+        apis.register(userRegisterDTO)
+            .then((res: any) => {
+              router.push(`/login`)
+            })
+            .catch((err: any) => {
+              console.error(err);
+            })
+            .finally(() => {
+            });
+      } else {
+        ElMessage({
+          message: '请将信息填写完整',
+          type: 'warning',
+        })
+      }
+    })
+
+  }
+
+  const sendVerifyCode = () => {
+    apis.sendVerifyCode(userRegisterDTO.officialEmail)
+        .then((res: any) => {
+          ElMessage({
+            message: '验证码发送成功',
+            type: 'success',
+          })
+        })
+        .catch((err: any) => {
+          ElMessage({
+            message: '验证码发送失败',
+            type: 'error',
+          })
+          console.log(err)
+        })
+        .finally(() => {
+        });
   }
-};
+</script>
+
+<script lang="ts">
+export default {
+  name: "Register"
+}
 </script>