新增用户注册功能
This commit is contained in:
@@ -0,0 +1,180 @@
|
||||
<template>
|
||||
<div class="register-container">
|
||||
<div class="register-card">
|
||||
<div class="header">
|
||||
<h2>创建账号</h2>
|
||||
<p>提交后需管理员审核通过方可登录</p>
|
||||
</div>
|
||||
<el-form
|
||||
ref="formRef"
|
||||
:model="form"
|
||||
:rules="rules"
|
||||
label-position="top"
|
||||
@keyup.enter.native="onSubmit"
|
||||
>
|
||||
<el-form-item label="邮箱" prop="email">
|
||||
<el-input v-model="form.email" placeholder="name@example.com" autocomplete="email" />
|
||||
</el-form-item>
|
||||
<el-form-item label="密码" prop="password">
|
||||
<el-input
|
||||
v-model="form.password"
|
||||
type="password"
|
||||
placeholder="至少 8 位且包含字母与数字"
|
||||
show-password
|
||||
autocomplete="new-password"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="确认密码" prop="confirmPassword">
|
||||
<el-input
|
||||
v-model="form.confirmPassword"
|
||||
type="password"
|
||||
placeholder="再次输入密码"
|
||||
show-password
|
||||
autocomplete="new-password"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="姓名" prop="full_name">
|
||||
<el-input v-model="form.full_name" placeholder="请输入姓名" />
|
||||
</el-form-item>
|
||||
<el-form-item label="部门" prop="department">
|
||||
<el-input v-model="form.department" placeholder="请输入部门" />
|
||||
</el-form-item>
|
||||
<div class="actions">
|
||||
<el-button type="primary" :loading="submitting" @click="onSubmit">提交注册</el-button>
|
||||
<RouterLink to="/login">已有账号?返回登录</RouterLink>
|
||||
</div>
|
||||
</el-form>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { reactive, ref } from "vue";
|
||||
import { useRouter } from "vue-router";
|
||||
import type { FormInstance, FormRules } from "element-plus";
|
||||
import { ElMessage } from "element-plus";
|
||||
import { register as apiRegister } from "../api/auth";
|
||||
import type { RegisterRequest } from "../types/api";
|
||||
|
||||
const router = useRouter();
|
||||
const defaultRole: RegisterRequest["role"] = "CRA";
|
||||
|
||||
const formRef = ref<FormInstance>();
|
||||
const form = reactive({
|
||||
email: "",
|
||||
password: "",
|
||||
confirmPassword: "",
|
||||
full_name: "",
|
||||
department: "",
|
||||
});
|
||||
const submitting = ref(false);
|
||||
|
||||
const passwordRule = {
|
||||
validator: (_: any, value: string, callback: (err?: Error) => void) => {
|
||||
if (!value || value.length < 8) {
|
||||
callback(new Error("密码至少 8 位"));
|
||||
return;
|
||||
}
|
||||
if (!/[A-Za-z]/.test(value) || !/[0-9]/.test(value)) {
|
||||
callback(new Error("需包含字母和数字"));
|
||||
return;
|
||||
}
|
||||
callback();
|
||||
},
|
||||
trigger: "blur",
|
||||
};
|
||||
|
||||
const rules: FormRules<typeof form> = {
|
||||
email: [
|
||||
{ required: true, message: "请输入邮箱", trigger: "blur" },
|
||||
{ type: "email", message: "邮箱格式不正确", trigger: "blur" },
|
||||
],
|
||||
password: [
|
||||
{ required: true, message: "请输入密码", trigger: "blur" },
|
||||
passwordRule,
|
||||
],
|
||||
confirmPassword: [
|
||||
{ required: true, message: "请确认密码", trigger: "blur" },
|
||||
{
|
||||
validator: (_: any, value: string, callback: (err?: Error) => void) => {
|
||||
if (value !== form.password) {
|
||||
callback(new Error("两次输入的密码不一致"));
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
},
|
||||
trigger: "blur",
|
||||
},
|
||||
],
|
||||
full_name: [{ required: true, message: "请输入姓名", trigger: "blur" }],
|
||||
department: [{ required: true, message: "请输入部门", trigger: "blur" }],
|
||||
};
|
||||
|
||||
const onSubmit = async () => {
|
||||
if (!formRef.value) return;
|
||||
await formRef.value.validate(async (valid) => {
|
||||
if (!valid) return;
|
||||
submitting.value = true;
|
||||
try {
|
||||
await apiRegister({
|
||||
email: form.email,
|
||||
password: form.password,
|
||||
full_name: form.full_name,
|
||||
role: defaultRole,
|
||||
department: form.department,
|
||||
});
|
||||
ElMessage.success("注册成功,等待管理员审核");
|
||||
setTimeout(() => {
|
||||
router.push("/login");
|
||||
}, 3000);
|
||||
Object.assign(form, {
|
||||
email: "",
|
||||
password: "",
|
||||
confirmPassword: "",
|
||||
full_name: "",
|
||||
department: "",
|
||||
});
|
||||
} finally {
|
||||
submitting.value = false;
|
||||
}
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.register-container {
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: linear-gradient(135deg, #f7f9fb 0%, #eef2f7 100%);
|
||||
padding: 24px;
|
||||
}
|
||||
.register-card {
|
||||
width: 420px;
|
||||
background: #fff;
|
||||
padding: 24px 28px;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.05);
|
||||
border: 1px solid #f0f2f5;
|
||||
}
|
||||
.header h2 {
|
||||
margin: 0;
|
||||
font-size: 22px;
|
||||
color: #1f2d3d;
|
||||
}
|
||||
.header p {
|
||||
margin: 6px 0 16px;
|
||||
color: #6c7a89;
|
||||
}
|
||||
.actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-top: 12px;
|
||||
}
|
||||
.actions a {
|
||||
color: var(--ctms-primary);
|
||||
font-size: 14px;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user