文章目录
- 前端代码实现
- 后端代码实现
- 跨域处理
前端代码实现
效果图
前端代码实现
<template>
<div class="login-container">
<el-card class="login-card">
<template #header>
<div class="card-header">
<span>登录</span>
</div>
</template>
<el-form label-width="80px" ref="formRef" :model="formData" :rules="rules">
<el-form-item label="用户名" prop="username">
<el-input v-model="formData.username" placeholder="请输入用户名" ></el-input>
</el-form-item>
<el-form-item label="密码" prop="password">
<el-input v-model="formData.password" type="password" placeholder="请输入密码"></el-input>
</el-form-item>
<el-form-item>
<el-button style="width: 100%;" @click="handleSubmit" type="primary">登录</el-button>
</el-form-item>
<el-form-item >
<el-button link type="info" @click="toggleToLogin" >没有账号?去注册</el-button>
</el-form-item>
</el-form>
</el-card>
</div>
</template>
<script setup>
import { ElMessage } from 'element-plus';
import axios from 'axios';
import { reactive, ref } from 'vue';
//初始化
const formRef = ref(null)
//跳转注册页面
const toggleToLogin = () => {
location.href = '/register'
}
//表单数据
const formData = ref({
username:'',
password:''
})
// 修正校验规则
const rules = reactive({
username:[
{required: true, message: '请输入用户名', trigger: 'blur'},
{min: 3, max: 20, message: '长度3到20个字符', trigger: 'blur'}
],
password:[
{required: true, message: '请输入密码', trigger: 'blur'},
{min: 3, max: 20, message: '长度在3到20个字符', trigger: 'blur'}
]
})
// 登录处理
const handleSubmit = async () => {
const form = formRef.value
if(!form) return;
try {
await form.validate();
const res = await axios.post('http://localhost:3030/user/login', formData.value);
if(res.data.code === 200) {
ElMessage.success( '登录成功');
location.href = '/manager/home';
} else {
ElMessage.error( '登录失败');
}
} catch (error) {
console.error('登录请求错误', error);
ElMessage.error(error.response?.data?.message || '登录失败,请稍后重试');
}
}
</script>
<style scoped>
.login-container {
min-height: 100vh;
display: flex;
background-color: aqua;
align-items: center;
justify-content: center;
}
.login-card {
width: 400px;
border-radius: 8px;
}
.card-header {
font-size: 24px;
font-weight: bold;
text-align: center;
}
</style>
后端代码实现
创建文件夹router,在router目录下创建path.js文件
//登录
router.post('/login', async (req,res)=>{
try {
const {username, password} = req.body
// 验证参数
if(!username?.trim() || !password?.trim()){ // 增加trim()检查
return res.status(400).json({
code: 400,
message: '用户名和密码不能为空'
})
}
const sql = 'select * from user where username = ? limit 1'
const [rows] = await pool.query(sql,[username])
if(rows.length === 0){
return res.status(401).json({
code: 401,
message: '用户名或密码错误'
})
}
const user = rows[0]
if(user.password !== password){
return res.status(401).json({
code: 401,
message: '用户名或密码错误'
})
}
// 删除敏感信息
delete user.password
success(res, {
code: 200,
user,
message: '登录成功'
})
} catch (error) {
handleError(res, error)
}
})
跨域处理
前端跨域,在vite.config.js中添加跨域请求
import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueDevTools from 'vite-plugin-vue-devtools'
// https://vite.dev/config/
export default defineConfig({
plugins: [
vue(),
vueDevTools(),
],
server:{
proxy:{
'/api':{target:'http://localhost:3030',changeOrigin:true,
rewrite:(path) => path.replace(/^\/api/,'')
}
}
},
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))
},
},
})
后端跨域,创建app.js,导入路由
const express = require('express')
const cors = require('cors')
const router = require('./router/path')
const app = express()
//解析数据
app.use(express.json())
app.use(express.urlencoded({extended:true}))
//跨域处理
app.use(cors(
{
origin:['http://localhost:5173'],
methods:['GET','POST','PUT','DELETE'],
credentials:true,
allowedHeaders:['Content-Type']
}
))
app.use('/user',router)
const PORT = process.env.PORT || 3030
app.listen(PORT,()=>{
console.log(`服务正在运行...端口为${PORT}`)
})
实现注册界面