Step F1:前端工程骨架 & 登录鉴权

This commit is contained in:
Cheng Zhou
2025-12-16 20:21:30 +08:00
parent 5eab324c50
commit 78d13d077c
25 changed files with 523 additions and 1 deletions
+27
View File
@@ -0,0 +1,27 @@
<template>
<div class="home">
<el-card>
<h2>欢迎使用 CTMS</h2>
<p>当前角色{{ auth.user?.role || "未知" }}</p>
</el-card>
</div>
</template>
<script setup lang="ts">
import { onMounted } from "vue";
import { useAuthStore } from "../store/auth";
const auth = useAuthStore();
onMounted(() => {
if (!auth.user) {
auth.fetchMe();
}
});
</script>
<style scoped>
.home {
padding: 16px;
}
</style>
+73
View File
@@ -0,0 +1,73 @@
<template>
<div class="login-page">
<el-card class="login-card">
<h2 class="title">CTMS 登录</h2>
<el-form :model="form" ref="formRef" :rules="rules" label-width="80px" @keyup.enter.native="onSubmit">
<el-form-item label="用户名" prop="username">
<el-input v-model="form.username" autocomplete="username" />
</el-form-item>
<el-form-item label="密码" prop="password">
<el-input v-model="form.password" type="password" autocomplete="current-password" show-password />
</el-form-item>
<el-form-item>
<el-button type="primary" :loading="loading" @click="onSubmit">登录</el-button>
</el-form-item>
</el-form>
</el-card>
</div>
</template>
<script setup lang="ts">
import { reactive, ref } from "vue";
import { useRouter } from "vue-router";
import type { FormInstance, FormRules } from "element-plus";
import { useAuthStore } from "../store/auth";
const auth = useAuthStore();
const router = useRouter();
const formRef = ref<FormInstance>();
const form = reactive({
username: "",
password: "",
});
const rules: FormRules<typeof form> = {
username: [{ required: true, message: "请输入用户名", trigger: "blur" }],
password: [{ required: true, message: "请输入密码", trigger: "blur" }],
};
const loading = ref(false);
const onSubmit = async () => {
if (!formRef.value) return;
await formRef.value.validate(async (valid) => {
if (!valid) return;
loading.value = true;
try {
await auth.login(form.username, form.password);
await auth.fetchMe();
router.push("/");
} finally {
loading.value = false;
}
});
};
</script>
<style scoped>
.login-page {
display: flex;
align-items: center;
justify-content: center;
min-height: 100vh;
background: #f5f7fa;
}
.login-card {
width: 360px;
}
.title {
text-align: center;
margin-bottom: 16px;
}
</style>