6.创建vue3项目-实现管理员登录前端页面
分类: springboot uni-app vue 专栏: 带小白springboot3+vue3+uniapp 标签: springboot3 vue uniapp
2026-01-17 15:57:07 99浏览
效果图

创建 vue3 项目
第六章 MyBatis-Plus+Vue+Element前后端分离实战-[springboot][springboot3.0新教材]博客-jf3q杰凡IT问答
这是我之前写的文章,可以参考下。
注意要安装 vue 脚手架.如果你没装的话
npm install -g @vue/cli跨域问题解决+axios 配置
vue.config.js 修改这个文件即可
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
transpileDependencies: true,
lintOnSave:false
})
//以上是自动生成的,下面是为解决跨域加的
module.exports = {
publicPath:'/',
devServer: {
host:'localhost',
port:7777, //前端项目端口号 选填
proxy:{
[process.env.VUE_APP_BASE_API]: {
target: `http://localhost:8888`, //后端项目地址
changeOrigin: true,
ws: true, // 是否支持 websocket, 默认是 true
pathRewrite: {['^' + process.env.VUE_APP_BASE_API]: ''}
}
}
}
}要新建文件
.env.development 和.env.production
内容如下
# 开发环境配置
ENV = 'development'
VUE_APP_BASE_API = '/dev-api'
# 生产环境配置
ENV = 'production'
VUE_APP_BASE_API = '/prod-api'
axios 的配置 js
import axios from "axios";
import {ElMessage, ElMessageBox} from "element-plus";
// Full config: https://github.com/axios/axios#request-config
// axios.defaults.baseURL = process.env.baseURL || process.env.apiUrl || '';
// axios.defaults.headers.common['Authorization'] = AUTH_TOKEN;
// axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
let config = {
// baseURL: process.env.baseURL || process.env.apiUrl || ""
// timeout: 60 * 1000, // Timeout
// withCredentials: true, // Check cross-site Access-Control
baseURL: process.env.VUE_APP_BASE_API
// dev-api/login
};
const _axios = axios.create(config);
_axios.interceptors.request.use(
function(config) {
// Do something before request is sent
//向请求头放 token 这个操作每个发送axios都要操作的
var token = sessionStorage.getItem("token");
if(token){
config.headers['token']=token
}
return config;
},
function(error) {
// Do something with request error
return Promise.reject(error);
}
);
// Add a response interceptor
_axios.interceptors.response.use(
function(response) {
// Do something with response data
if(response.data.code == 3000){
ElMessageBox.confirm(response.data.mess,"系统提示",{
confirmButtonText:'重新登录',
cancelButtonText:'取消',
type:'warning'
}
).then(()=>{
location.href="/";
})
// 阻止进一步链式调用 没提示任何信息 不走then
return new Promise(() => {});
}else if(response.data.code==5000){
ElMessage.error(response.data.mess)
// 阻止进一步链式调用 没提示任何信息 不走then
return new Promise(() => {});
}else{
//要走 then
return response.data;
}
},
function(error) {
// Do something with response error
return Promise.reject(error);
}
);
// Vue 3 插件安装方式
const requestPlugin = {
install(app) {
app.config.globalProperties.$axios = _axios;
app.provide('axios', _axios);
window.axios = _axios;
}
};
export default requestPlugin;
export {_axios as request}
注意要在 main.js 中引入
import { createApp } from 'vue'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import App from './App.vue'
import router from './router'
import store from './store'
import requestPlugin from './axios/index'
const app = createApp(App)
// 使用插件
app.use(store)
app.use(router)
app.use(ElementPlus)
app.use(requestPlugin)
// 挂载应用
app.mount('#app')
要跟你的 axios 的配置文件目录一致哦,我的是在前端项目根目录下的 axios 文件夹下的 index.js
axios 请求后端接口
请求登录接口的核心代码
// 提交表单
const submitForm = async () => {
if (!loginFormRef.value) return
await loginFormRef.value.validate(async (valid) => {
if (valid) {
try {
// 调用登录API
const res = await login( loginForm)
console.log(res)
ElMessage.success('登录成功')
// 登录成功后跳转到首页
router.push('/about')
} catch (error) {
console.error('登录错误:', error)
ElMessage.error('登录失败,请重试')
}
}
})
}注意 await login( loginForm)是发请求到后端
import {login} from '@/api/index'这样引入 login 函数
import {request} from '@/axios/index'
export function login(query) {
return request({
url: '/login',
method: 'post',
params: query
})
}这个文件专门存放前端请求后端的所有接口

下面是之前写的分页查询的一个 vue3+elementplus 的 demo(备用参考)
<script setup>
import {onMounted, ref} from "vue";
import axios from 'axios'
import {ElMessage, ElMessageBox} from "element-plus";
const fileList=ref([])
const suceessFile = (response,uploadFile,uploadFiles) => {
console.log(response)
console.log(uploadFile)
console.log(uploadFiles)
fileList.value=[]
if(response.code==5000){
ElMessage.error(response.mess)
}else{
ElMessage.success(response.mess)
getPage()
}
}
const submitForm = () => {
ruleFormRef.value.validate( (v)=>{
if(v){
//校验通过
axios({
url: '/api/stu/saveOrUpdate',
method: 'post',
data:ruleForm.value
}).then(res => {
console.log(res);
if(res.data.code== 2000){
ElMessage.success(res.data.mess)
dialogVisible.value=false
getPage()
}else{
ElMessage.error(res.data.mess)
}
})
}else{
//么按规矩填写表单
ElMessage.error("请按提示填写表单")
}
})
}
const resetForm = () => {
ruleFormRef.value.resetFields()
}
const onAdd = () => {
dialogVisible.value=true
}
const formInline= ref({
studentname: '',
classno: ''
})
const changePageNum = (val) => {
pageNum.value=val
getPage()
}
const dialogVisible=ref(false)
const total= ref(0)
const pageNum= ref(1)
const pages= ref(0)
const pageSize= ref(3)
const tableData=ref([])
const onSubmit = () => {
pageNum.value=1
getPage()
}
const toUpdate = (row) => {
console.log(row)
ruleForm.value.gender=row.gender
ruleForm.value.age=row.age
ruleForm.value.address=row.address
ruleForm.value.id=row.id
ruleForm.value.studentname=row.studentname
dialogVisible.value=true
}
const ruleForm= ref({
id: '',
studentname: '',
age: '',
gender: '',
address: ''
})
const rules= ref(
{
studentname: [
{ required: true, message: '请输入学生名字', trigger: 'blur' },
],
age: [
{ required: true, message: '请输入学生年龄', trigger: 'blur' },
],
gender: [
{ required: true, message: '请选择性别', trigger: 'blur' },
],
address: [
{ required: true, message: '请输入地址', trigger: 'blur' },
],
}
)
const ruleFormRef= ref(null)
const toDel = (id) => {
ElMessageBox.confirm(
'您确定要删除该记录吗?',
'Warning',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}
)
.then(() => {
axios({
url: '/api/stu/del/'+id,
method:'delete',
}).then(res => {
if (res.data.code == 2000) {
ElMessage({
type: 'success',
message: res.data.mess,
})
getPage()
}else{
ElMessage({
type: 'error',
message: res.data.mess,
})
}
})
})
.catch(() => {
ElMessage({
type: 'info',
message: '取消删除',
})
})
}
const getPage = () => {
axios({
url: '/api/stu/page?pageNum='+pageNum.value,
method: 'get',
params: formInline.value
}).then(res => {
console.log(res);
tableData.value=res.data.data.records
total.value=res.data.data.total
pages.value=res.data.data.pages
pageNum.value=res.data.data.current
pageSize.value=res.data.data.size
})
}
const classList=ref([])
onMounted( ()=>{
axios({
url: '/api/class',
}).then(res => {
console.log(res);
classList.value=res.data.data
})
getPage()
})
const closeDialog = () => {
resetForm()
dialogVisible.value=false
}
</script>
<template>
<div>
<el-dialog
@close="closeDialog"
v-model="dialogVisible"
title="新增/修改"
width="500"
>
<el-form
ref="ruleFormRef"
style="max-width: 600px"
:model="ruleForm"
:rules="rules"
label-width="auto"
class="demo-ruleForm"
status-icon
>
<el-form-item label="学生姓名" prop="studentname">
<el-input v-model="ruleForm.studentname" />
</el-form-item>
<el-form-item label="性别" prop="gender">
<el-radio-group v-model="ruleForm.gender">
<el-radio value="男">男</el-radio>
<el-radio value="女">女</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="学生年龄" prop="age">
<el-input type="number" v-model="ruleForm.age" />
</el-form-item>
<el-form-item label="地址" prop="address">
<el-input v-model="ruleForm.address" type="textarea" />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submitForm(ruleFormRef)">
确定
</el-button>
<el-button @click="resetForm(ruleFormRef)">重置</el-button>
</el-form-item>
</el-form>
</el-dialog>
<el-form :inline="true" :model="formInline" class="demo-form-inline">
<el-form-item label="学生名字">
<el-input v-model="formInline.studentname" placeholder="xxxx" clearable />
</el-form-item>
<el-form-item label="班级" >
<el-select v-model="formInline.classno" style="width: 200px" placeholder="请选择">
<el-option value="" label="请选择班级" ></el-option>
<el-option v-for="c in classList" :key="c.classno" :value="c.classno" :label="c.classname" ></el-option>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="warning" @click="onSubmit">查询</el-button>
<el-button type="primary" @click="onAdd">新增</el-button>
</el-form-item>
</el-form>
<el-table :data="tableData" style="width: 100%">
<el-table-column prop="id" label="编号" />
<el-table-column label="电子照片" >
<template #default="scope">
<img :src="'/api/student/'+scope.row.photo" style="height: 50px;height: 50px">
</template>
</el-table-column>
<el-table-column prop="studentname" label="名字" />
<el-table-column prop="gender" label="性别" />
<el-table-column prop="age" label="年龄" />
<el-table-column prop="classname" label="班级" />
<el-table-column prop="address" label="地址" />
<el-table-column label="操作" >
<template #default="scope">
<el-button size="small" type="success" @click="toUpdate(scope.row)">编辑</el-button>
<el-button size="small" type="danger" @click="toDel(scope.row.id)">删除</el-button>
<el-upload
:file-list="fileList"
:show-file-list="false"
class="upload-demo"
:on-success="suceessFile"
:action="'/api/stu/upload?id='+scope.row.id"
multiple
:limit="1"
>
<el-button type="primary" size="small">上传电子照</el-button>
</el-upload>
</template>
</el-table-column>
</el-table>
<el-pagination
background
layout="prev, pager, next"
:page-size="pageSize"
:page-count="pages"
@current-change="changePageNum"
:total="total" />
</div>
</template>
<style scoped lang="scss">
</style>
好博客就要一起分享哦!分享海报
此处可发布评论
评论(0)展开评论
展开评论
您可能感兴趣的博客

新业务
springboot学习
ssm框架课
vue学习
【带小白】java基础速成