# 阶段3:登录页面开发(纯 UI)
## 1。创建目录结构
### (1)执行命令
```bash
mkdir resources\js\admin\views
mkdir resources\js\admin\layouts
```
### (2)说明
创建后台页面组件目录和布局组件目录。
## 2。创建 Login.vue
### (1)文件路径
`resources\js\admin\views\Login.vue`
### (2)完整代码
```vue
<template>
<div class="login-container">
<el-card class="login-card">
<template #header>
<div class="login-header">
<h2>好站站后台管理</h2>
<p>登录开始建站</p>
</div>
</template>
<el-form :model="form" :rules="rules" ref="formRef">
<el-form-item prop="email">
<el-input
v-model="form.email"
placeholder="邮箱"
:prefix-icon="User"
size="large"
/>
</el-form-item>
<el-form-item prop="password">
<el-input
v-model="form.password"
type="password"
placeholder="密码"
:prefix-icon="Lock"
size="large"
show-password
/>
</el-form-item>
<el-form-item>
<el-button
type="primary"
size="large"
:loading="loading"
@click="handleLogin"
style="width: 100%"
>
登录
</el-button>
</el-form-item>
</el-form>
</el-card>
</div>
</template>
<script setup>
import { ref, reactive } from 'vue';
import { ElMessage } from 'element-plus';
import { User, Lock } from '@element-plus/icons-vue';
const formRef = ref();
const loading = ref(false);
const form = reactive({
email: '',
password: '',
});
const rules = {
email: [
{ required: true, message: '请输入邮箱', trigger: 'blur' },
{ type: 'email', message: '邮箱格式不正确', trigger: 'blur' },
],
password: [
{ required: true, message: '请输入密码', trigger: 'blur' },
{ min: 6, message: '密码至少6位', trigger: 'blur' },
],
};
const handleLogin = () => {
if (!formRef.value) return;
formRef.value.validate(async (valid) => {
if (!valid) return;
loading.value = true;
// 阶段3:只做前端验证,不调用API
setTimeout(() => {
loading.value = false;
ElMessage.warning('后端API开发中,暂不支持登录');
}, 500);
});
};
</script>
<style scoped>
.login-container {
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}
.login-card {
width: 400px;
}
.login-header {
text-align: center;
}
</style>
```
### (3)代码说明
| 代码 | 作用 |
|------|------|
| `el-card` | Element Plus 卡片容器,让登录表单有层次感 |
| `el-form` + `rules` | 表单验证配置,前端校验减少无效请求 |
| `v-model` | 双向绑定表单数据 |
| `:prefix-icon` | 输入框前置图标 |
| `show-password` | 密码显示/隐藏切换功能 |
| `:loading="loading"` | 按钮加载状态,防止重复提交 |
| `setTimeout` | 模拟登录请求(阶段3暂不调用真实API) |
| `linear-gradient` | CSS 渐变背景,提升视觉体验 |
## 3。创建 App.vue
### (1)文件路径
`resources\js\admin\App.vue`
### (2)完整代码
```vue
<template>
<router-view />
</template>
```
### (3)代码说明
| 代码 | 作用 |
|------|------|
| `<router-view />` | Vue Router 的路由出口,根据当前 URL 显示对应页面组件 |
## 4。创建 MainLayout.vue(占位)
### (1)文件路径
`resources\js\admin\layouts\MainLayout.vue`
### (2)完整代码
```vue
<template>
<div>后台布局开发中...</div>
</template>
```
### (3)说明
阶段3暂不实现完整布局,创建占位组件确保路由不报错。
## 5。创建 Dashboard.vue(占位)
### (1)文件路径
`resources\js\admin\views\Dashboard.vue`
### (2)完整代码
```vue
<template>
<div>仪表盘开发中...</div>
</template>
```
### (3)说明
阶段3暂不实现仪表盘,创建占位组件确保路由不报错。
## 6。更新路由配置
### (1)文件路径
`resources\js\admin\router\index.js`
### (2)完整代码
```javascript
import { createRouter, createWebHistory } from 'vue-router';
const routes = [
{
path: '/admin/login',
name: 'login',
component: () => import('../views/Login.vue'),
},
{
path: '/admin',
component: () => import('../layouts/MainLayout.vue'),
children: [
{
path: '',
name: 'dashboard',
component: () => import('../views/Dashboard.vue'),
},
],
},
];
const router = createRouter({
history: createWebHistory(),
routes,
});
export default router;
```
### (3)代码说明
| 代码 | 作用 |
|------|------|
| `createRouter()` | 创建路由实例 |
| `createWebHistory()` | 使用 HTML5 历史模式,URL 不带 `#` |
| `component: () => import(...)` | 动态导入组件,实现代码分割 |
| `children` | 嵌套路由,共用 MainLayout 布局 |
## 7。更新 main.js
### (1)文件路径
`resources\js\admin\main.js`
### (2)完整代码
```javascript
import { createApp } from 'vue';
import ElementPlus from 'element-plus';
import 'element-plus/dist/index.css';
import * as ElementPlusIconsVue from '@element-plus/icons-vue';
import App from './App.vue';
import router from './router';
const app = createApp(App);
// 注册所有 Element Plus 图标组件
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
app.component(key, component);
}
app.use(ElementPlus);
app.use(router);
app.mount('#app');
```
### (3)代码说明
| 代码 | 作用 |
|------|------|
| `createApp(App)` | 创建 Vue 应用实例 |
| `app.component(key, component)` | 注册图标组件,可在模板中直接使用 `<el-icon><User /></el-icon>` |
| `app.use(ElementPlus)` | 安装 Element Plus 插件 |
| `app.use(router)` | 安装路由插件 |
| `app.mount('#app')` | 将应用挂载到 DOM 元素 |
## 8。编译验证
### (1)执行命令
```bash
npm run build
```
### (2)预期输出
```
vite v6.4.2 building for production...
✓ xxx modules transformed.
public/build/manifest.json
public/build/assets/Login-xxx.css
public/build/assets/Login-xxx.js
✓ built in x.xxs
```
## 9。访问测试
### (1)登录页面
浏览器打开:`http://engine-api.test/admin/login`
预期显示:紫色渐变背景的登录表单,包含邮箱、密码输入框和登录按钮。
### (2)表单验证测试
| 操作 | 预期结果 |
|------|---------|
| 点击登录(邮箱为空) | 提示「请输入邮箱」 |
| 输入非邮箱格式 | 提示「邮箱格式不正确」 |
| 密码少于6位 | 提示「密码至少6位」 |
| 正确填写后点击登录 | 提示「后端API开发中,暂不支持登录」 |
## 10。遇到的问题及解决
### 问题:页面空白,Vue 未渲染
**现象**:访问 `/admin/login` 显示空白页面。
**原因分析**:`main.js` 中未注册路由和 Element Plus 插件。
**解决方案**:在 `main.js` 中添加 `app.use(router)` 和 `app.use(ElementPlus)`。
## 11。验证结果
| 验证项 | 预期结果 | 实际结果 |
|--------|---------|---------|
| 编译 | 无报错 | ✅ 通过 |
| 登录页面访问 | 显示登录表单 | ✅ 通过 |
| 邮箱格式验证 | 提示格式错误 | ✅ 通过 |
| 密码长度验证 | 提示至少6位 | ✅ 通过 |
| 登录按钮点击 | 提示暂不支持登录 | ✅ 通过 |