文章目录
- 前端代码实现
- 后端代码实现
- 跨域处理
前端代码实现
效果图
前端代码实现
<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.valueif(!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.passwordsuccess(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}`)
})
实现注册界面