SpringBoot与Vue前后端交互问题
在vue中找到vue.config.js文件中,加入下列代码:
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
devServer: {
port:8888,//修改前端应用的端口号(可以改为你想改的任意数字,不要与后端冲突就行)
proxy: {
// 配置代理,解决跨域问题
'/api': {
target: 'http://localhost:8080', // 后端接口的基础 URL
changeOrigin: true, // 是否改变请求头中的 Origin 字段
pathRewrite: {
'^/api': '' // 将请求路径中的 '/api' 替换为空字符串,去除 '/api' 前缀
}
}
}
}
});
在后端创建CrosConfig文件,导入以下代码
package com.team.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class CrosConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("http://localhost:8888/")//端口号需要修改为与前端vue.config.js中相对应的端口号
.allowedMethods("GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS")
.allowCredentials(true)
.maxAge(3600)
.allowedHeaders("*");
}
}
目录结构为
在前端和后端分别按照以上操作,即可完成前后端交互。
下面是一个示例:
首先创建vue项目
选择手动配置项目
选择Babel、Router、Linter和使用配置文件
配置选择
点击创建项目,创建完成。
将router文件夹下的index.js改为下列代码
import Vue from 'vue'
import VueRouter from 'vue-router'
import ShopView from '../views/ShopMenu.vue'
Vue.use(VueRouter)
const routes = [
{
path: '/',
redirect: "/shop"
},
{
path:'/shop',
name:'shop',
component:ShopView
}
]
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes
})
export default router
安装element-ui和axios
npm install element-ui@2.15.3
npm install axios
在main.js中添加下列代码
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css';
Vue.use(ElementUI);
在views下创建ShopMenu.vue文件
<template>
<div>
<el-form :inline="true" :model="searchForm" class="demo-form-inline">
<el-form-item label="名称">
<el-input v-model="searchForm.name" placeholder="名称"></el-input>
</el-form-item>
<el-form-item label="地址">
<el-input v-model="searchForm.address" placeholder="地址"></el-input>
</el-form-item>
<el-form-item label="面积">
<el-input v-model="searchForm.size" placeholder="面积"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onSubmit">查询</el-button>
</el-form-item>
</el-form>
<el-row>
<el-button type="danger" plain @click="deleteByIds" style="float: left;">批量删除</el-button>
<el-button type="primary" plain @click="dialogVisible = true" style="float: left;">新增</el-button>
</el-row>
<el-dialog title="新增门店" :visible.sync="dialogVisible" width="30%">
<el-form ref="form" :model="shopadd" label-width="100px">
<el-form-item label="门店名称">
<el-input v-model="shopadd.name"></el-input>
</el-form-item>
<el-form-item label="地址">
<el-input v-model="shopadd.address"></el-input>
</el-form-item>
<el-form-item label="面积">
<el-input v-model="shopadd.size" placeholder="(平方米)"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="addshop">确定</el-button>
<el-button @click="dialogVisible = false">返回</el-button>
</el-form-item>
</el-form>
</el-dialog>
<el-table :data="tableData" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55">
</el-table-column>
<el-table-column prop="name" label="门店名称" width="180"></el-table-column>
<el-table-column prop="address" label="地点" width="180"></el-table-column>
<el-table-column prop="size" label="面积(平方米)" width="180">
</el-table-column>
<el-table-column align="center" label="操作">
<template slot-scope="scope">
<el-button type="primary" size="small" @click="editStore(scope.row.id)">编辑</el-button>
<el-button type="danger" size="small" @click="deleteStore(scope.row.id)">删除</el-button>
</template>
</el-table-column>
</el-table>
<br>
<el-dialog title="修改门店信息" :visible.sync="dialogVisible1" width="30%">
<el-form ref="form" :model="shopupdate" label-width="100px">
<el-form-item label="门店名称">
<el-input v-model="shopupdate.name"></el-input>
</el-form-item>
<el-form-item label="地址">
<el-input v-model="shopupdate.address"></el-input>
</el-form-item>
<el-form-item label="面积">
<el-input v-model="shopupdate.size" placeholder="(平方米)"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="updateshop">确定</el-button>
<el-button @click="dialogVisible1 = false">返回</el-button>
</el-form-item>
</el-form>
</el-dialog>
<!-- 分页条 -->
<el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange"
:current-page="currentPage" :page-sizes="[5, 10, 15, 20]" :page-size="pageSize"
layout="total, sizes, prev, pager, next, jumper" :total="totalCount">
</el-pagination>
</div>
</template>
<script>
import axios from 'axios';
export default {
name: 'VueShop',
data() {
return {
totalCount: 1000,
// 当前页码
currentPage: 1,
pageSize: 5,
tableData: [
{
name: '1',
address: '北京市',
size: '600',
id: ''
},
],
dialogVisible: false,
dialogVisible1: false,
searchForm: {
name: "",
address: "",
size: ""
},
shopadd: {
name: "",
address: "",
size: ""
},
shop: {
name: "",
address: "",
size: ""
},
shopupdate: {
name: "",
address: "",
size: ""
}
}
},
mounted() {
this.onSubmit();
},
methods: {
onSubmit() {
const params = {
name: this.searchForm.name || null,
address: this.searchForm.address || null,
size: this.searchForm.size || null,
pageSize: this.pageSize, // 每页显示条数
page: this.currentPage // 当前页码
};
axios.get('http://localhost:8080/store/select', { params })
.then(response => {
// 处理查询结果
console.log(response.data);
this.tableData = response.data.rows;
this.totalCount = response.data.total;
})
.catch(error => {
// 处理错误
console.error(error);
});
},
logout() {
this.$router.push({ path: "/login" });
},
deleteStore(id) {
console.log(id);
this.$confirm('此操作将删除该数据, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
axios.delete(`http://localhost:8080/store/${id}`)
.then(response => {
// 删除成功后的处理逻辑
console.log(response);
this.$message.success('门店删除成功');
this.onSubmit();
// 在此处执行其他逻辑,例如重新加载员工列表等
})
.catch(error => {
// 删除失败后的处理逻辑
this.$message.error('门店删除失败');
console.error(error);
});
}).catch(() => {
// 取消删除时的处理逻辑
this.$message.info('已取消删除');
});
},
editStore(row) {
console.log(row);
// 根据id从后端查询门店信息
axios.get(`http://localhost:8080/store/select/${row}`)
.then(response => {
console.log(response.data);
// 将查询到的员工信息回显到编辑表单中
this.shopupdate = response.data;
this.dialogVisible1 = true; // 打开编辑对话框
})
.catch(error => {
console.error(error);
});
},
addshop() {
const params = {
name: this.shopadd.name,
address: this.shopadd.address,
size: this.shopadd.size,
};
// 发送添加门店请求
axios.post('http://localhost:8080/store/add', params)
.then(response => {
// 处理添加门店成功的逻辑
console.log('添加门店成功', response);
// 关闭对话框
this.$message({
message: '恭喜你,添加成功',
type: 'success'
});
this.dialogVisible = false;
// 清空表单数据
this.shopadd = {};
// 刷新员工列表等操作
// ...
this.onSubmit();
})
.catch(error => {
// 处理添加门店失败的逻辑
console.error('添加门店失败', error);
// 显示错误提示等操作
this.onSubmit();
// ...
});
},
deleteByIds() {
const ids = this.multipleSelection.map(item => item.id);
console.log(ids);
this.$confirm('此操作将删除该数据, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
axios.delete(`http://localhost:8080/store/${ids.join(',')}`)
.then(response => {
// 处理删除成功的逻辑
console.log('删除成功', response.data);
this.$message({
message: '恭喜你,删除成功',
type: 'success'
});
this.onSubmit();
})
.catch(error => {
// 处理删除失败的逻辑
console.error('删除失败', error);
});
}).catch(() => {
this.$message.info('已取消删除');
})
},
updateshop() {
const requestBody = {
// 根据后端接口的定义,传递需要更新的门店信息
name: this.shopupdate.name,
address: this.shopupdate.address,
size: this.shopupdate.size,
};
axios.put(`http://localhost:8080/store/update/` + this.shopupdate.id, requestBody)
.then(response => {
console.log(response); // 打印响应信息
this.dialogVisible1 = false; // 关闭编辑对话框
// 刷新表格数据等操作
this.onSubmit();
this.$message.success('门店信息更新成功!');
})
.catch(error => {
console.error(error); // 打印错误信息
this.$message.error('门店信息更新失败,请重试!');
});
},
handleSizeChange(size) {
// 处理每页显示条数变更事件
this.pageSize = size;
// 这里可以重新调用查询接口获取当前页数据
// ...
this.onSubmit();
},
handleCurrentChange(currentPage) {
// 处理页码变更事件
this.currentPage = currentPage;
// 这里可以重新调用查询接口获取当前页数据
// ...
this.onSubmit();
},
handleSelectionChange(val) {
this.multipleSelection = val;
}
}
};
</script>
<style lang="scss" scoped>
</style>
后端用springboot创建
不会用springboot创建项目的可以看 2020版IDEA创建springboot项目
创建完项目后数据库的配置 在application.properties文件中添加如下代码
#数据库连接
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/scheduling
spring.datasource.username=root
spring.datasource.password=123456
#开启mybatis的日志输出
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
#开启数据库表字段 到 实体类属性的驼峰映射
mybatis.configuration.map-underscore-to-camel-case=true
在pom.xml文件中导入lombok和pageHelper
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.4.2</version>
</dependency>
后端目录结构
StoreController
package com.ysk.controller;
import com.ysk.pojo.PageBean;
import com.ysk.pojo.Result;
import com.ysk.pojo.Store;
import com.ysk.service.StoreService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@Slf4j
@RestController
@RequestMapping("/store")
public class StoreController {
@Autowired
private StoreService storeService;
@GetMapping("/select")
public PageBean page(@RequestParam(defaultValue = "1") Integer page,
@RequestParam(defaultValue = "5") Integer pageSize,
String name, String address, Double size){
log.info("分页查询,参数:{},{},{},{},{}", page, pageSize,name,address,size);
PageBean pageBean = storeService.page(page, pageSize,name,address,size);
return pageBean;
}
@PostMapping("/add")
public Result save(@RequestBody Store store){
log.info("新增门店,stuff:{}",store);
storeService.save(store);
return Result.success();
}
//批量删除
@DeleteMapping("/{ids}")
public Result delete(@PathVariable List<Integer> ids){
storeService.delete(ids);
return Result.success();
}
@GetMapping("/select/{id}")
public Store getStoreById(@PathVariable Integer id) {
// 在这里可以根据 userId 和 userName 进行身份验证或其他操作
// 假设 userService 提供了获取用户信息的方法
return storeService.getByStoreId(id);
}
@PutMapping("/update/{id}")
public Result update(@PathVariable("id") Integer id,@RequestBody Store store){
Store existingEmp = storeService.getByStoreId(id);
if (existingEmp != null) {
existingEmp.setName(store.getName());
existingEmp.setAddress(store.getAddress());
existingEmp.setSize(store.getSize());
storeService.update(existingEmp);
return Result.success();
} else {
return Result.error("门店信息不存在");
}
}
@GetMapping("/data")
public Store getDataByStore(@RequestParam("id") Integer id){
return storeService.getByStoreId(id);
}
}
StoreMapper
package com.ysk.mapper;
import com.ysk.pojo.Store;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import java.util.List;
@Mapper
public interface StoreMapper {
public List<Store> list(String name,String address,Double size);
@Insert("insert into store(name,address,size) value (#{name},#{address},#{size})")
public void insert(Store store);
public void delete(List<Integer> ids);
@Select("select * from store where id =#{id}")
public Store getStuffById(Integer id);
public void update(Store store);
}
PageBean
package com.ysk.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class PageBean {
private Long total;
private List rows;
}
Result
package com.ysk.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Result {
private Integer code;//响应码,1 代表成功; 0 代表失败
private String msg; //响应信息 描述字符串
private Object data; //返回的数据
//增删改 成功响应
public static Result success(){
return new Result(1,"success",null);
}
//查询 成功响应
public static Result success(Object data){
return new Result(1,"success",data);
}
//失败响应
public static Result error(String msg){
return new Result(0,msg,null);
}
}
Store
package com.ysk.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Store {
//店的id
private Integer id;
//用于展示的数据
private String name;//店的名字
private String address;//店的地址
//用于计算的数据
private Double size;//店的面积
private Double preDivisorValue;//开店前准备除数的权值
private Integer freePopulationNum;//店空闲时需要的人数
private Double aftDivisorValue;//关店后准备除数的权值
private Integer aftAddValue;//关店后准备加数的权值
private Integer prePrepareHourNum;//开店之前需要做几小时准备工作
private Integer aftPrepareHourNum;//关门之后需要做几小时准备工作
private Double passFlowDivisorValue;//人流量对应店员数的除数权值
}
StoreService
package com.ysk.service;
import com.ysk.pojo.PageBean;
import com.ysk.pojo.Store;
import com.ysk.pojo.PageBean;
import java.util.List;
public interface StoreService {
//分页查询
PageBean page(Integer page, Integer pageSize, String name, String address, Double size);
//新增门店
public void save(Store store);
//删除门店
public void delete(List<Integer> ids);
public Store getByStoreId(Integer id);
public void update(Store store);
}
StoreServiceImpl
package com.ysk.service.Impl;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.ysk.mapper.StoreMapper;
import com.ysk.pojo.PageBean;
import com.ysk.pojo.Store;
import com.ysk.service.StoreService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Slf4j
@Service
public class StoreServiceImpl implements StoreService {
@Autowired
private StoreMapper storeMapper;
@Override
public PageBean page(Integer page, Integer pageSize, String name, String address, Double size) {
PageHelper.startPage(page,pageSize);
List<Store> storeList = storeMapper.list(name,address,size);
Page<Store> s = (Page<Store>) storeList;
PageBean pageBean = new PageBean(s.getTotal(),s.getResult());
return pageBean;
}
@Override
public void save(Store store) {
storeMapper.insert(store);
}
@Override
public void delete(List<Integer> ids) {
storeMapper.delete(ids);
}
@Override
public Store getByStoreId(Integer id) {
return storeMapper.getStuffById(id);
}
@Override
public void update(Store store) {
storeMapper.update(store);
}
}
运行结果展示
新增
批量删除
修改
后端代码的地址
https://gitee.com/forget1204/2023-4-24
https://github.com/Yskkkkk/2023-4-24backend
前端代码的地址