代码地址:https://github.com/hyblist/SpringBoot-Vue2.git
jdk1.8
mysql
node
navicat
idea
SpringBoot + Vue
1、前端环境搭建
1、Vue后台主体搭建
地址:https://element.eleme.cn/#/zh-CN/component/installation
弹窗:https://layuion.com/docs/
docsify动态生成您的文档网站:https://docsify.js.org/#/
安装:
npm i element-ui -S
搭建项目
1、vue-cli安装:
npm config set registry https://registry.npm.taobao.org
npm install -g @vue/cli
2、创建一个名为vue的工程
vue create vue
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Y75jaYg2-1656746400673)(springboot+vue.assets/image-20220626135443407.png)]
3、测试启动
cd vue
npm run serve
4、项目结构
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tCpKvhrY-1656746400675)(springboot+vue.assets/image-20220626135932147.png)]
5、安装element-ui
npm i element-ui -S
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
Vue.use(ElementUI,{small})
6、修样式
新建goloable.css,并在main.js导入import ‘./assets/goloable.css’
html,body,div{
margin: 0;
padding: 0;
}
html,body{
height: 100%;
}
Home.vue
<!--https://element.eleme.cn/#/zh-CN/component/container#container-bu-ju-rong-qi 搜布局容器,取其中代码,并做修改-->
<template>
<div style="height: 100%">
<!--菜单下面的横线border: 1px solid #eee",去掉-->
<el-container style="height: 100%">
<!--页面架构-->
<!--el-aside侧边栏-->
<!--el-container有el-header主体 设置颜色:border-bottom: 1px solid #ccc;居中line-height: 60px-->
<!--el-container-->
<el-aside width="200px" style="background-color: rgb(238, 241, 246);height: 100%" >
<el-menu :default-openeds="['1', '3']" style="height: 100%">
<el-submenu index="1">
<template slot="title"><i class="el-icon-message"></i>导航一</template>
<el-menu-item-group>
<template slot="title">分组一</template>
<el-menu-item index="1-1">选项1</el-menu-item>
<el-menu-item index="1-2">选项2</el-menu-item>
</el-menu-item-group>
<el-menu-item-group title="分组2">
<el-menu-item index="1-3">选项3</el-menu-item>
</el-menu-item-group>
<el-submenu index="1-4">
<template slot="title">选项4</template>
<el-menu-item index="1-4-1">选项4-1</el-menu-item>
</el-submenu>
</el-submenu>
<el-submenu index="2">
<template slot="title"><i class="el-icon-menu"></i>导航二</template>
<el-menu-item-group>
<template slot="title">分组一</template>
<el-menu-item index="2-1">选项1</el-menu-item>
<el-menu-item index="2-2">选项2</el-menu-item>
</el-menu-item-group>
<el-menu-item-group title="分组2">
<el-menu-item index="2-3">选项3</el-menu-item>
</el-menu-item-group>
<el-submenu index="2-4">
<template slot="title">选项4</template>
<el-menu-item index="2-4-1">选项4-1</el-menu-item>
</el-submenu>
</el-submenu>
<el-submenu index="3">
<template slot="title"><i class="el-icon-setting"></i>导航三</template>
<el-menu-item-group>
<template slot="title">分组一</template>
<el-menu-item index="3-1">选项1</el-menu-item>
<el-menu-item index="3-2">选项2</el-menu-item>
</el-menu-item-group>
<el-menu-item-group title="分组2">
<el-menu-item index="3-3">选项3</el-menu-item>
</el-menu-item-group>
<el-submenu index="3-4">
<template slot="title">选项4</template>
<el-menu-item index="3-4-1">选项4-1</el-menu-item>
</el-submenu>
</el-submenu>
</el-menu>
</el-aside>
<el-container>
<el-header style="text-align: right; font-size: 12px;border-bottom: 1px solid #ccc;line-height: 60px">
<el-dropdown>
<i class="el-icon-setting" style="margin-right: 15px"></i>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item>查看</el-dropdown-item>
<el-dropdown-item>新增</el-dropdown-item>
<el-dropdown-item>删除</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
<span>王小虎</span>
</el-header>
<el-main>
<el-table :data="tableData">
<el-table-column prop="date" label="日期" width="140">
</el-table-column>
<el-table-column prop="name" label="姓名" width="120">
</el-table-column>
<el-table-column prop="address" label="地址">
</el-table-column>
</el-table>
</el-main>
</el-container>
</el-container>
</div>
</template>
<script>
export default {
data() {
const item = {
date: '2016-05-02',
name: '王小虎',
address: '上海市普陀区金沙江路 1518 弄'
};
return {
tableData: Array(10).fill(item)
}
}
}
</script>
2、Vue后台整体完善(一)
1、设置整体页面100%
goloable.css
*{
margin: 0;
padding: 0;
box-sizing: border-box;
}
App.vue
<template>
<div id="app">
<router-view/>
</div>
</template>
<style>
</style>
2、调整Home.vue
Home.vue 去除div,并设置<el-container style=“height: 100vh”>;并进行以下设置
<!--https://element.eleme.cn/#/zh-CN/component/container#container-bu-ju-rong-qi 搜布局容器,取其中代码,并做修改-->
<template>
<!--菜单下面的横线border: 1px solid #eee",去掉-->
<el-container style="height: 100vh">
<!--页面架构-->
<!--el-aside侧边栏-->
<!--el-container有el-header主体 设置颜色:border-bottom: 1px solid #ccc;居中line-height: 60px-->
<!--el-container-->
<!--:width="sideWidth+'px'",绑定,并使其自动更换宽度-->
<el-aside :width="sideWidth+'px'" style="background-color: rgb(238, 241, 246); box-shadow: 2px 0 20px #888888;" >
<!--overflow: hidden 多层子菜单菜单超出,设置样式;background-color:颜色;text-color字体颜色-->
<!--active-text-color="#ffdo4b" 选中菜单的颜色;绑定 :collapse-transition="false"菜单的动漫:
collapse="isCollapse"菜单收缩根据这个变量来变化 -->
<el-menu :default-openeds="['1', '3']" style="min-height: 100%; overflow: hidden"
background-color="rgb(48,65,86)"
text-color="#fff"
active-text-color="#ffdo4b"
:collapse-transition="false"
:collapse="isCollapse"
>
<!--设置log,新增一个div;style="height: 60px;line-height: 60px;设置高度text-align: center"位置居中,左(默认),右-->
<!--style="width: 20px"设置图片大小;position: relative;位置相对 top: 5px 下移动;-->
<div style="height: 60px;line-height: 60px;text-align: center">
<img src="../assets/logo.png" alt="" style="width: 20px;position: relative;top: 5px;margin-right: 5px">
<!--是否展示绑定一个变量v-show="logoTextShow"-->
<b style="color: white" v-show="logoTextShow">后台管理系统</b>
</div>
<el-submenu index="1">
<template slot="title">
<!--样式有问题调整导航-->
<i class="el-icon-message"></i>
<span>导航一</span>
</template>
<el-menu-item-group>
<template slot="title">分组一</template>
<el-menu-item index="1-1">选项1</el-menu-item>
<el-menu-item index="1-2">选项2</el-menu-item>
</el-menu-item-group>
<el-menu-item-group title="分组2">
<el-menu-item index="1-3">选项3</el-menu-item>
</el-menu-item-group>
<el-submenu index="1-4">
<template slot="title">选项4</template>
<el-menu-item index="1-4-1">选项4-1</el-menu-item>
</el-submenu>
</el-submenu>
<el-submenu index="2">
<template slot="title">
<i class="el-icon-menu"></i>
<span>导航二</span>
</template>
<el-menu-item-group>
<template slot="title">分组一</template>
<el-menu-item index="2-1">选项1</el-menu-item>
<el-menu-item index="2-2">选项2</el-menu-item>
</el-menu-item-group>
<el-menu-item-group title="分组2">
<el-menu-item index="2-3">选项3</el-menu-item>
</el-menu-item-group>
<el-submenu index="2-4">
<template slot="title">选项4</template>
<el-menu-item index="2-4-1">选项4-1</el-menu-item>
</el-submenu>
</el-submenu>
<el-submenu index="3">
<template slot="title">
<i class="el-icon-setting"></i>
<span>导航三</span>
</template>
<el-menu-item-group>
<template slot="title">分组一</template>
<el-menu-item index="3-1">选项1</el-menu-item>
<el-menu-item index="3-2">选项2</el-menu-item>
</el-menu-item-group>
<el-menu-item-group title="分组2">
<el-menu-item index="3-3">选项3</el-menu-item>
</el-menu-item-group>
<el-submenu index="3-4">
<template slot="title">选项4</template>
<el-menu-item index="3-4-1">选项4-1</el-menu-item>
</el-submenu>
</el-submenu>
</el-menu>
</el-aside>
<el-container>
<!--菜单顶部调整-->
<el-header style=" font-size: 12px;border-bottom: 1px solid #ccc;line-height: 60px;display: flex">
<div style="flex: 1;font-size: 18px">
<!--绑定点击事件-->
<span v-bind:class="collapseBtnClass" style="cursor:pointer; " @click="collapse"></span>
</div>
<!--el-dropdown下展图标设置,可以通过f12知道其位置-->
<el-dropdown style="width: 70px; cursor:pointer">
<!--class="el-icon-caret-bottom"图标样式;style="margin-left: 5px"可以设置与文字距离-->
<span>王小虎</span><i class="el-icon-caret-bottom" style="margin-left: 5px"></i>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item>个人信息</el-dropdown-item>
<el-dropdown-item>退出</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</el-header>
<el-main>
<el-table :data="tableData">
<el-table-column prop="date" label="日期" width="140">
</el-table-column>
<el-table-column prop="name" label="姓名" width="120">
</el-table-column>
<el-table-column prop="address" label="地址">
</el-table-column>
</el-table>
</el-main>
</el-container>
</el-container>
</template>
<script>
export default {
data() {
const item = {
date: '2016-05-02',
name: '王小虎',
address: '上海市普陀区金沙江路 1518 弄'
};
return {
tableData: Array(10).fill(item),
collapseBtnClass:'el-icon-s-fold',
isCollapse:false,
sideWidth:200,
//logo处理
logoTextShow:true
}
},
methods:{
collapse(){ //点击按钮触发修改
this.isCollapse = !this.isCollapse
if (this.isCollapse){ //收缩
this.sideWidth = 64
//并更换图标
this.collapseBtnClass='el-icon-s-unfold'
this.logoTextShow = false
}else {//展开
this.sideWidth = 200
//并更换图标
this.collapseBtnClass='el-icon-s-fold'
this.logoTextShow = true
}
}
}
}
</script>
3、Vue后台整体完善(二)
1、添加分页
<!--完整版-->
<!--分页:style="padding: 20px(高度) 10px(margin-left[默认隐藏]:10px)[左距离] 设置位置-->
<div style="padding: 20px 10px">
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="currentPage4"
:page-sizes="[100, 200, 300, 400]"
:page-size="100"
layout="total, sizes, prev, pager, next, jumper"
:total="400">
</el-pagination>
</div>
2、定制样式
*{
margin: 0;
padding: 0;
box-sizing: border-box;
}
.ml-5{
margin-left: 10px;
}
.ml-5{
margin-right: 5px;
}
.pd-10{
padding: 10px 0;
}
3、调整Home.vue
<!--https://element.eleme.cn/#/zh-CN/component/container#container-bu-ju-rong-qi 搜布局容器,取其中代码,并做修改-->
<template>
<!--菜单下面的横线border: 1px solid #eee",去掉-->
<el-container style="height: 100vh">
<!--页面架构-->
<!--el-aside侧边栏-->
<!--el-container有el-header主体 设置颜色:border-bottom: 1px solid #ccc;居中line-height: 60px-->
<!--el-container-->
<!--:width="sideWidth+'px'",绑定,并使其自动更换宽度-->
<el-aside :width="sideWidth+'px'" style="background-color: rgb(238, 241, 246); box-shadow: 2px 0 20px #888888;" >
<!--overflow: hidden 多层子菜单菜单超出,设置样式;background-color:颜色;text-color字体颜色-->
<!--active-text-color="#ffdo4b" 选中菜单的颜色;绑定 :collapse-transition="false"菜单的动漫:
collapse="isCollapse"菜单收缩根据这个变量来变化 -->
<el-menu :default-openeds="['1', '3']" style="min-height: 100%; overflow: hidden"
background-color="rgb(48,65,86)"
text-color="#fff"
active-text-color="#ffdo4b"
:collapse-transition="false"
:collapse="isCollapse"
>
<!--设置log,新增一个div;style="height: 60px;line-height: 60px;设置高度text-align: center"位置居中,左(默认),右-->
<!--style="width: 20px"设置图片大小;position: relative;位置相对 top: 5px 下移动;-->
<div style="height: 60px;line-height: 60px;text-align: center">
<img src="../assets/logo.png" alt="" style="width: 20px;position: relative;top: 5px;margin-right: 5px">
<!--是否展示绑定一个变量v-show="logoTextShow"-->
<b style="color: white" v-show="logoTextShow">后台管理系统</b>
</div>
<el-submenu index="1">
<template slot="title">
<!--样式有问题调整导航-->
<i class="el-icon-message"></i>
<span>导航一</span>
</template>
<el-menu-item-group>
<template slot="title">分组一</template>
<el-menu-item index="1-1">选项1</el-menu-item>
<el-menu-item index="1-2">选项2</el-menu-item>
</el-menu-item-group>
<el-menu-item-group title="分组2">
<el-menu-item index="1-3">选项3</el-menu-item>
</el-menu-item-group>
<el-submenu index="1-4">
<template slot="title">选项4</template>
<el-menu-item index="1-4-1">选项4-1</el-menu-item>
</el-submenu>
</el-submenu>
<el-submenu index="2">
<template slot="title">
<i class="el-icon-menu"></i>
<span>导航二</span>
</template>
<el-menu-item-group>
<template slot="title">分组一</template>
<el-menu-item index="2-1">选项1</el-menu-item>
<el-menu-item index="2-2">选项2</el-menu-item>
</el-menu-item-group>
<el-menu-item-group title="分组2">
<el-menu-item index="2-3">选项3</el-menu-item>
</el-menu-item-group>
<el-submenu index="2-4">
<template slot="title">选项4</template>
<el-menu-item index="2-4-1">选项4-1</el-menu-item>
</el-submenu>
</el-submenu>
<el-submenu index="3">
<template slot="title">
<i class="el-icon-setting"></i>
<span>导航三</span>
</template>
<el-menu-item-group>
<template slot="title">分组一</template>
<el-menu-item index="3-1">选项1</el-menu-item>
<el-menu-item index="3-2">选项2</el-menu-item>
</el-menu-item-group>
<el-menu-item-group title="分组2">
<el-menu-item index="3-3">选项3</el-menu-item>
</el-menu-item-group>
</el-submenu>
</el-menu>
</el-aside>
<el-container>
<!--菜单顶部调整-->
<el-header style=" font-size: 12px;border-bottom: 1px solid #ccc;line-height: 60px;display: flex">
<div style="flex: 1;font-size: 18px">
<!--绑定点击事件-->
<span v-bind:class="collapseBtnClass" style="cursor:pointer; " @click="collapse"></span>
</div>
<!--el-dropdown下展图标设置,可以通过f12知道其位置-->
<el-dropdown style="width: 70px; cursor:pointer">
<!--class="el-icon-caret-bottom"图标样式;style="margin-left: 5px"可以设置与文字距离-->
<span>王小虎</span><i class="el-icon-caret-bottom" style="margin-left: 5px"></i>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item>个人信息</el-dropdown-item>
<el-dropdown-item>退出</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</el-header>
<el-main>
<!--添加面包屑-->
<div style = "margin-bottom: 30px">
<el-breadcrumb separator="/">
<el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
<el-breadcrumb-item>用户管理</el-breadcrumb-item>
</el-breadcrumb>
</div>
<!--搜索position: relative ; top:-10px连这用的-->
<div style="position: relative ; top:-10px">
<!--width英 [w?dθ]宽度;placeholder="请输入名称"提示语,suffix-icon="el-icon-search"嵌套图标-->
<el-input style="width: 200px" placeholder="请输入名称" suffix-icon="el-icon-search" class="mr-10"></el-input>
<el-input style="width: 200px" placeholder="邮箱" suffix-icon="el-icon-message" class="mr-10"></el-input>
<el-input style="width: 200px" placeholder="地址" suffix-icon="el-icon-position" class="mr-10"></el-input>
<el-button class="ml-5" type="primary">搜索</el-button>
</div>
<!--按钮 <i class="el-icon-circle-plus-outline" >嵌套按钮-->
<div style=" position: relative; top:-6px ">
<el-button type="primary">新增 <i class="el-icon-circle-plus-outline" ></i></el-button>
<el-button type="danger">批量删除 <i class="el-icon-circle-close"></i></el-button>
<el-button type="primary">导入 <i class="el-icon-top"></i></el-button>
<el-button type="primary">导出 <i class="el-icon-bottom"></i></el-button>
</div>
<!--表格设置边框border stripe有线-->
<!--:header-cell-class-name="headerBg"和下面的<script><script>有联系-->
<el-table :data="tableData" border stripe :header-cell-class-name="headerBg">
<el-table-column prop="date" label="日期" width="120">
</el-table-column>
<el-table-column prop="name" label="姓名" width="120" >
</el-table-column>
<el-table-column prop="address" label="地址">
</el-table-column>
<!--添加编辑操作-->
<el-table-column label="操作" width="150" >
<template slot-scope="scope" >
<el-button >编辑</el-button>
<el-button type="danger">删除</el-button>
</template>
</el-table-column>
</el-table>
<!--分页:style="padding: 20px(高度) 10px(margin-left[默认隐藏]:10px)[左距离] 设置位置-->
<div style="padding: 20px 10px">
<el-pagination
:page-sizes="[5, 10, 15, 20]"
:page-size="10"
layout="total, sizes, prev, pager, next, jumper"
:total="400">
</el-pagination>
</div>
</el-main>
</el-container>
</el-container>
</template>
<script>
export default {
data() {
const item = {
date: '2016-05-02',
name: '王小虎',
address: '上海市普陀区金沙江路 1518 弄'
};
return {
tableData: Array(10).fill(item),
collapseBtnClass:'el-icon-s-fold',
isCollapse:false,
sideWidth:200,
//logo处理
logoTextShow:true,
headerBg:'headerBg'
}
},
methods:{
collapse(){ //点击按钮触发修改
this.isCollapse = !this.isCollapse
if (this.isCollapse){ //收缩
this.sideWidth = 64
//并更换图标
this.collapseBtnClass='el-icon-s-unfold'
this.logoTextShow = false
}else {//展开
this.sideWidth = 200
//并更换图标
this.collapseBtnClass='el-icon-s-fold'
this.logoTextShow = true
}
}
}
}
</script>
<style>
.headerBg{
background: rgba(204, 204, 204, 0.59) !important;
}
</style>
2、后端环境搭建
1、 创建springboot项目,和配置数据库
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KQyXRYtX-1656746400677)(springboot+vue.assets/image-20220626212732545.png)]
2、把vue项目拉到springboot里面,并在springboot配置启动前端的配置[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CJRv56q0-1656746400678)(springboot+vue.assets/image-20220626214628189.png)]
测试前后端是否正常运行
3、搭建/连接数据库
1、创建sys_user表
1-1、一个表要有唯一的主键,勾选自动递增
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QzmMIKAF-1656746400678)(springboot+vue.assets/image-20220627093836101.png)]
1-2、创建时间字段默认值CURRENT_TIMESTAMP
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tv75T5gL-1656746400679)(springboot+vue.assets/image-20220627094426869.png)]
1-3、创建表的sql
CREATE TABLE `sys_user` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'id',
`username` varchar(50) DEFAULT NULL,
`password` varchar(50) DEFAULT NULL,
`nickname` varchar(50) DEFAULT NULL COMMENT '昵称',
`email` varchar(50) DEFAULT NULL,
`phone` varchar(50) DEFAULT NULL,
`address` varchar(50) DEFAULT NULL,
`create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
2、测试查询数据
entity 英 [?ent?ti] 实体:User.java
package com.yebin.springboot.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
public class User {
private Integer id;
private String username;
private String password;
private String nickname;
private String email;
private String phone;
private String address;
}
mapper(作用:与数据库交互):UserMapper.java
package com.yebin.springboot.mapper;
import com.yebin.springboot.entity.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import java.util.List;
@Mapper
public interface UserMapper {
@Select("select * from sys_user")
List<User> findAll();
}
controller: UserController.java
package com.yebin.springboot.controller;
import com.yebin.springboot.entity.User;
import com.yebin.springboot.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
public class UserController {
@Autowired
private UserMapper userMapper;
@GetMapping("/")
private List<User> index(){
return userMapper.findAll();
}
}
4、实现增删改查
安装mybatisx插件
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-depPnMzp-1656746400680)(springboot+vue.assets/image-20220627115620336.png)]
controller: UserController.java
package com.yebin.springboot.controller;
import com.yebin.springboot.entity.User;
import com.yebin.springboot.mapper.UserMapper;
import com.yebin.springboot.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserMapper userMapper;
@Autowired
private UserService userService;
@GetMapping
private List<User> index(){
return userMapper.findAll();
}
@PostMapping
private Integer save(@RequestBody User user){
return userService.save(user);
}
@DeleteMapping("/{id}")
private Integer delete(@PathVariable Integer id){
return userMapper.deleteById(id);
}
}
mapper(作用:与数据库交互):UserMapper.java
package com.yebin.springboot.mapper;
import com.yebin.springboot.entity.User;
import org.apache.ibatis.annotations.*;
import java.util.List;
@Mapper
public interface UserMapper {
@Select("select * from sys_user")
List<User> findAll();
@Insert("INSERT INTO sys_user(username,password,nickname,email,phone,address) VALUES(#{username},#{password},#{nickname},#{email},#{phone},#{address})")
int insert(User user);
int update(User user);
@Delete("delete from sys_user where id = #{id}")
Integer deleteById(@Param("id") Integer id);
}
User.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yebin.springboot.mapper.UserMapper">
<update id="update">
-- 判断username是否为空
-- 密码不在这里修改
-- 注意要加","符号,要不然会报错
update sys_user
<set>
<if test="username != null">
username = #{username},
</if>
<if test="nickname != null">
nickname = #{nickname},
</if>
<if test="email != null">
email = #{email},
</if>
<if test="phone != null">
phone = #{phone},
</if>
<if test="address != null">
address = #{address}
</if>
</set>
<where>
id = #{id}
</where>
</update>
</mapper>
mybatis xml格式
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yebinhuang.mapper.UserMapper">
</mapper>
配置mybatis application.yaml
server:
port: 9090
spring:
application:
name: springboot
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/my_project?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
username: root
password: 123456
mybatis:
mapper-locations: classpath:mapper/*.xml
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
5、实现分页查询(mybatis)
5- 1、不使用插件写分页/带参数分页
后端处理(不带参数):
SELECT * FROM sys_user LIMIT 0, 2;
SELECT * FROM sys_user LIMIT 2, 2;
SELECT * FROM sys_user LIMIT 4, 2;
UserController.java
package com.yebin.springboot.controller;
import com.yebin.springboot.entity.User;
import com.yebin.springboot.mapper.UserMapper;
import com.yebin.springboot.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserMapper userMapper;
@Autowired
private UserService userService;
@GetMapping
private List<User> index(){
return userMapper.findAll();
}
@PostMapping
private Integer save(@RequestBody User user){
return userService.save(user);
}
@DeleteMapping("/{id}")
private Integer delete(@PathVariable Integer id){
return userMapper.deleteById(id);
}
@GetMapping("/page")
private Map<String,Object> findPage(@RequestParam Integer pageNum, @RequestParam Integer pageSize){
pageNum = (pageNum - 1)* pageSize;
List<User> data = userMapper.selectPage(pageNum,pageSize);
Integer total = userMapper.selectTotal();
Map<String,Object> res = new HashMap<>();
res.put("data",data);
res.put("total",total);
return res;
}
}
UserMapper.java
package com.yebin.springboot.mapper;
import com.yebin.springboot.entity.User;
import org.apache.ibatis.annotations.*;
import java.util.List;
@Mapper
public interface UserMapper {
@Select("select * from sys_user")
List<User> findAll();
@Insert("INSERT INTO sys_user(username,password,nickname,email,phone,address) VALUES(#{username},#{password},#{nickname},#{email},#{phone},#{address})")
int insert(User user);
int update(User user);
@Delete("delete from sys_user where id = #{id}")
Integer deleteById(@Param("id") Integer id);
@Select("select * from sys_user limit #{pageNum},#{pageSize}")
List<User> selectPage(@Param("pageNum")Integer pageNum,@Param("pageSize")Integer pageSize);
@Select("select count(*) from sys_user")
Integer selectTotal();
}
User.java 忽略某个字段不展示给前端@JsonIgnore
package com.yebin.springboot.entity;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
public class User {
private Integer id;
private String username;
@JsonIgnore
private String password;
private String nickname;
private String email;
private String phone;
private String address;
}
前端处理:
1、会出现跨域问题:解决方案看“其他——>3、前端跨域问题”
2、elementUi找Pagination 分页——附加功能
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
然后添加到
<script>
export default {
data() {
return {
pageNum:1,
pageSize:10,
}
},
created(){
//分页
this.load()
},
methods:{
//分页
load(){
fetch("http://localhost:9090/user/page?pageNum="+this.pageNum + "&pageSize="+this.pageSize).then(res =>res.json()).then(res =>{
console.log(res)
//绑定接口的数据
this.tableData = res.data
this.total = res.total
})
},
//分页
handleCurrentChange(pageNum){
this.pageNum = pageNum
this.load()
},
//分页
handleSizeChange(pageSize){
this.pageSize = pageSize
this.load()
}
}
}
</script>
Home.vue 分页的修改
<!--https://element.eleme.cn/#/zh-CN/component/container#container-bu-ju-rong-qi 搜布局容器,取其中代码,并做修改-->
<template>
<!--菜单下面的横线border: 1px solid #eee",去掉-->
<el-container style="height: 100vh">
<!--页面架构-->
<!--el-aside侧边栏-->
<!--el-container有el-header主体 设置颜色:border-bottom: 1px solid #ccc;居中line-height: 60px-->
<!--el-container-->
<!--:width="sideWidth+'px'",绑定,并使其自动更换宽度-->
<el-aside :width="sideWidth+'px'" style="background-color: rgb(238, 241, 246); box-shadow: 2px 0 20px #888888;" >
<!--overflow: hidden 多层子菜单菜单超出,设置样式;background-color:颜色;text-color字体颜色-->
<!--active-text-color="#ffdo4b" 选中菜单的颜色;绑定 :collapse-transition="false"菜单的动漫:
collapse="isCollapse"菜单收缩根据这个变量来变化 -->
<el-menu :default-openeds="['1', '3']" style="min-height: 100%; overflow: hidden"
background-color="rgb(48,65,86)"
text-color="#fff"
active-text-color="#ffdo4b"
:collapse-transition="false"
:collapse="isCollapse"
>
<!--设置log,新增一个div;style="height: 60px;line-height: 60px;设置高度text-align: center"位置居中,左(默认),右-->
<!--style="width: 20px"设置图片大小;position: relative;位置相对 top: 5px 下移动;-->
<div style="height: 60px;line-height: 60px;text-align: center">
<img src="../assets/logo.png" alt="" style="width: 20px;position: relative;top: 5px;margin-right: 5px">
<!--是否展示绑定一个变量v-show="logoTextShow"-->
<b style="color: white" v-show="logoTextShow">后台管理系统</b>
</div>
<el-submenu index="1">
<template slot="title">
<!--样式有问题调整导航-->
<i class="el-icon-message"></i>
<span>导航一</span>
</template>
<el-menu-item-group>
<template slot="title">分组一</template>
<el-menu-item index="1-1">选项1</el-menu-item>
<el-menu-item index="1-2">选项2</el-menu-item>
</el-menu-item-group>
<el-menu-item-group title="分组2">
<el-menu-item index="1-3">选项3</el-menu-item>
</el-menu-item-group>
<el-submenu index="1-4">
<template slot="title">选项4</template>
<el-menu-item index="1-4-1">选项4-1</el-menu-item>
</el-submenu>
</el-submenu>
<el-submenu index="2">
<template slot="title">
<i class="el-icon-menu"></i>
<span>导航二</span>
</template>
<el-menu-item-group>
<template slot="title">分组一</template>
<el-menu-item index="2-1">选项1</el-menu-item>
<el-menu-item index="2-2">选项2</el-menu-item>
</el-menu-item-group>
<el-menu-item-group title="分组2">
<el-menu-item index="2-3">选项3</el-menu-item>
</el-menu-item-group>
<el-submenu index="2-4">
<template slot="title">选项4</template>
<el-menu-item index="2-4-1">选项4-1</el-menu-item>
</el-submenu>
</el-submenu>
<el-submenu index="3">
<template slot="title">
<i class="el-icon-setting"></i>
<span>导航三</span>
</template>
<el-menu-item-group>
<template slot="title">分组一</template>
<el-menu-item index="3-1">选项1</el-menu-item>
<el-menu-item index="3-2">选项2</el-menu-item>
</el-menu-item-group>
<el-menu-item-group title="分组2">
<el-menu-item index="3-3">选项3</el-menu-item>
</el-menu-item-group>
</el-submenu>
</el-menu>
</el-aside>
<el-container>
<!--菜单顶部调整-->
<el-header style=" font-size: 12px;border-bottom: 1px solid #ccc;line-height: 60px;display: flex">
<div style="flex: 1;font-size: 18px">
<!--绑定点击事件-->
<span v-bind:class="collapseBtnClass" style="cursor:pointer; " @click="collapse"></span>
</div>
<!--el-dropdown下展图标设置,可以通过f12知道其位置-->
<el-dropdown style="width: 70px; cursor:pointer">
<!--class="el-icon-caret-bottom"图标样式;style="margin-left: 5px"可以设置与文字距离-->
<span>王小虎</span><i class="el-icon-caret-bottom" style="margin-left: 5px"></i>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item>个人信息</el-dropdown-item>
<el-dropdown-item>退出</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</el-header>
<el-main>
<!--添加面包屑-->
<div style = "margin-bottom: 30px">
<el-breadcrumb separator="/">
<el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
<el-breadcrumb-item>用户管理</el-breadcrumb-item>
</el-breadcrumb>
</div>
<!--搜索position: relative ; top:-10px连这用的-->
<div style="position: relative ; top:-10px">
<!--width英 [w?dθ]宽度;placeholder="请输入名称"提示语,suffix-icon="el-icon-search"嵌套图标-->
<el-input style="width: 200px" placeholder="请输入名称" suffix-icon="el-icon-search" class="mr-10"></el-input>
<el-input style="width: 200px" placeholder="邮箱" suffix-icon="el-icon-message" class="mr-10"></el-input>
<el-input style="width: 200px" placeholder="地址" suffix-icon="el-icon-position" class="mr-10"></el-input>
<el-button class="ml-5" type="primary">搜索</el-button>
</div>
<!--按钮 <i class="el-icon-circle-plus-outline" >嵌套按钮-->
<div style=" position: relative; top:-6px ">
<el-button type="primary">新增 <i class="el-icon-circle-plus-outline" ></i></el-button>
<el-button type="danger">批量删除 <i class="el-icon-circle-close"></i></el-button>
<el-button type="primary">导入 <i class="el-icon-top"></i></el-button>
<el-button type="primary">导出 <i class="el-icon-bottom"></i></el-button>
</div>
<!--表格设置边框border stripe有线-->
<!--:header-cell-class-name="headerBg"和下面的<script><script>有联系-->
<!-- :data="tableData" 与下面的<script>中的created()做数据绑定-->
<el-table :data="tableData" border stripe :header-cell-class-name="headerBg">
<el-table-column prop="id" label="id" width="50"></el-table-column>
<el-table-column prop="username" label="用户名" ></el-table-column>
<el-table-column prop="nickname" label="昵称" ></el-table-column>
<el-table-column prop="phone" label="电话" ></el-table-column>
<el-table-column prop="email" label="邮箱" ></el-table-column>
<el-table-column prop="address" label="地址"></el-table-column>
<!--添加编辑操作-->
<el-table-column label="操作" width="150" >
<template slot-scope="scope" >
<el-button >编辑</el-button>
<el-button type="danger">删除</el-button>
</template>
</el-table-column>
</el-table>
<!--分页:style="padding: 20px(高度) 10px(margin-left[默认隐藏]:10px)[左距离] 设置位置-->
<div style="padding: 20px 10px">
<!--@size-change="handleSizeChange"、@current-change="handleCurrentChange"、:current-page="pageNum"
:page-size="pageSize"、实现动态翻页-->
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="pageNum"
:page-size="pageSize"
:page-sizes="[10, 20, 50, 100]"
layout="total, sizes, prev, pager, next, jumper"
:total="total">
</el-pagination>
</div>
</el-main>
</el-container>
</el-container>
</template>
<script>
export default {
data() {
return {
tableData: [],
total: 0,
pageNum:1,
pageSize:10,
collapseBtnClass:'el-icon-s-fold',
isCollapse:false,
sideWidth:200,
//logo处理
logoTextShow:true,
headerBg:'headerBg'
}
},
created(){
//分页
this.load()
},
methods:{
collapse(){ //点击按钮触发修改
this.isCollapse = !this.isCollapse
if (this.isCollapse){ //收缩
this.sideWidth = 64
//并更换图标
this.collapseBtnClass='el-icon-s-unfold'
this.logoTextShow = false
}else {//展开
this.sideWidth = 200
//并更换图标
this.collapseBtnClass='el-icon-s-fold'
this.logoTextShow = true
}
},
//分页
load(){
//请求分页查询数据
//注意:res.json()和res.join()
// fetch("http://localhost:9090/user/page?pageNum=1&pageSize=2").then(res =>res.json()).then(res =>{
// console.log(res)
// 改成动态
fetch("http://localhost:9090/user/page?pageNum="+this.pageNum + "&pageSize="+this.pageSize).then(res =>res.json()).then(res =>{
console.log(res)
//绑定接口的数据
this.tableData = res.data
this.total = res.total
})
},
//分页
handleCurrentChange(pageNum){
this.pageNum = pageNum
this.load()
},
//分页
handleSizeChange(pageSize){
this.pageSize = pageSize
this.load()
}
}
}
</script>
<style>
.headerBg{
background: rgba(204, 204, 204, 0.59) !important;
}
</style>
后端处理(带参数):
主要在于改sql
UserMapper.java
package com.yebin.springboot.mapper;
import com.yebin.springboot.entity.User;
import org.apache.ibatis.annotations.*;
import java.util.List;
@Mapper
public interface UserMapper {
@Select("select * from sys_user")
List<User> findAll();
@Insert("INSERT INTO sys_user(username,password,nickname,email,phone,address) VALUES(#{username},#{password},#{nickname},#{email},#{phone},#{address})")
int insert(User user);
int update(User user);
@Delete("delete from sys_user where id = #{id}")
Integer deleteById(@Param("id") Integer id);
@Select("select * from sys_user where " +
"username like concat('%' , #{username}, '%') " +
"limit #{pageNum},#{pageSize}")
List<User> selectPage(
@Param("username")String username,
@Param("pageNum")Integer pageNum,
@Param("pageSize")Integer pageSize);
@Select("select count(*) from sys_user where " +
"username like concat('%' , #{username}, '%')" +
"")
Integer selectTotal(
@Param("username")String username
);
}
UserController.java
package com.yebin.springboot.controller;
import com.yebin.springboot.entity.User;
import com.yebin.springboot.mapper.UserMapper;
import com.yebin.springboot.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserMapper userMapper;
@Autowired
private UserService userService;
@GetMapping
private List<User> index(){
return userMapper.findAll();
}
@PostMapping
private Integer save(@RequestBody User user){
return userService.save(user);
}
@DeleteMapping("/{id}")
private Integer delete(@PathVariable Integer id){
return userMapper.deleteById(id);
}
@GetMapping("/page")
private Map<String,Object> findPage(
@RequestParam String username,
@RequestParam Integer pageNum,
@RequestParam Integer pageSize){
pageNum = (pageNum - 1)* pageSize;
List<User> data = userMapper.selectPage(username,pageNum,pageSize);
Integer total = userMapper.selectTotal(username);
Map<String,Object> res = new HashMap<>();
res.put("data",data);
res.put("total",total);
return res;
}
}
前端处理(带参数):
对应Home.vue修改
<el-input style="width: 200px" placeholder="请输入名称" suffix-icon="el-icon-search" class="mr-10" v-model = "username" ></el-input>
<!--@click="load"点击绑定load方法-->
<el-button class="ml-5" type="primary" @click="load">搜索</el-button>
data() {
return {
//带参数
username:"",
tableData: [],
total: 0,
pageNum:1,
pageSize:10,
collapseBtnClass:'el-icon-s-fold',
isCollapse:false,
sideWidth:200,
//logo处理
logoTextShow:true,
headerBg:'headerBg'
}
}
fetch("http://localhost:9090/user/page?pageNum="+this.pageNum + "&pageSize="+this.pageSize+ "&username="+this.username).
then(res =>res.json())
3、SpringBoot集成Mybatis-Plus
1、Mybatis-Plus实现分页
快速实现增删改查,但是sql的编写会慢慢忘掉
Mybatis-Plus官网:https://www.baomidou.com/pages/24112f/ (建议多看官网)
1-1、引入依赖依赖和修改配置
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus</artifactId>
<version>3.5.1</version>
</dependency>
1-2、mybatis-plus配置(只能留一个)
mybatis和mybatis-plus只能存在一个,要不然会打架,所以导入依赖只能存在其中一个
server:
port: 9090
spring:
application:
name: springboot
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/my_project?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
username: root
password: 123456
mybatis-plus:
mapper-locations: classpath:mapper/*.xml
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
true map-underscore-to-camel-case: true
1-3、在官网→插件主体:copy分页插件代码
MybatisPlusConfig.java
package com.yebin.springboot.config;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@MapperScan("com.yebin.springboot.mapper")
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ND9tM9On-1656746400681)(springboot+vue.assets/image-20220628133312136.png)]
1-4、mybatis-plus分页查询
@GetMapping("/page")
public IPage<User> findPage(
@RequestParam Integer pageNum,
@RequestParam Integer pageSize,
@RequestParam(defaultValue = "") String username,
@RequestParam(defaultValue = "") String email,
@RequestParam(defaultValue = "") String address
){
IPage<User> page = new Page<>(pageNum,pageSize);
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
if (!"".equals(username)){
queryWrapper.like("username",username);
}
if (!"".equals(username)){
queryWrapper.like("email",email);
}
if (!"".equals(username)){
queryWrapper.like("address",address);
}
return userService.page(page,queryWrapper);
}
2、后端代码处理
-----------------------------改得面目全非------------------------
mapper改成MybatisPlus接手,所有UserMapper中得注解@Mapper可以删了,可以看MybatisPlusConfig.java
UserMapper.java 注意要继承extends BaseMapper
package com.yebin.springboot2.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.yebin.springboot2.entity.User;
public interface UserMapper extends BaseMapper<User> {
}
UserController.java
package com.yebin.springboot2.controller;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yebin.springboot2.entity.User;
import com.yebin.springboot2.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@GetMapping
private List<User> findAll() {
return userService.list();
}
@PostMapping
private boolean save(@RequestBody User user) {
return userService.saveUser(user);
}
@DeleteMapping("/{id}")
private boolean delete(@PathVariable Integer id) {
return userService.removeById(id);
}
@PostMapping ("/del/batch")
private boolean deleteBatch(@RequestBody List<Integer> ids) {
System.out.println(ids);
return userService.removeByIds(ids);
}
@GetMapping("/page")
public IPage<User> findPage(
@RequestParam Integer pageNum,
@RequestParam Integer pageSize,
@RequestParam(defaultValue = "") String username,
@RequestParam(defaultValue = "") String email,
@RequestParam(defaultValue = "") String address
){
IPage<User> page = new Page<>(pageNum,pageSize);
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
if (!"".equals(username)){
queryWrapper.like("username",username);
}
if (!"".equals(username)){
queryWrapper.like("email",email);
}
if (!"".equals(username)){
queryWrapper.like("address",address);
}
queryWrapper.orderByDesc("id");
return userService.page(page,queryWrapper);
}
}
User.java 实体类需要注明数据库表名称
package com.yebin.springboot2.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Data;
@Data
@TableName(value = "sys_user")
public class User {
@TableId(type = IdType.AUTO)
private Integer id;
private String username;
@JsonIgnore
private String password;
private String nickname;
private String email;
private String phone;
private String address;
}
UserSevice.java 继承extends ServiceImpl<UserMapper, User>,ServiceImpl继承了IService,IService有些方法名重叠,或者说已经写好,直接调用即可
package com.yebin.springboot2.service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yebin.springboot2.entity.User;
import com.yebin.springboot2.mapper.UserMapper;
import org.springframework.stereotype.Service;
@Service
public class UserService extends ServiceImpl<UserMapper, User> {
public boolean saveUser(User user) {
if (user.getId() == null) {
return save(user);
} else {
return updateById(user);
}
}
}
3、前端代码处理
去除fetch改用axios封装
fetch("http://localhost:9090/user/page?" +
"pageNum="+this.pageNum +
"&pageSize="+this.pageSize+
"&username="+this.username+
"&address="+this.address+
"&email="+this.email
).then(res =>res.json())
安装Axios
npm i axios -s
封装request.js
import axios from 'axios'
const request = axios.create({
baseURL: '/api',
timeout: 5000
})
request.interceptors.request.use(config => {
config.headers['Content-Type'] = 'application/json;charset=utf-8';
return config
}, error => {
return Promise.reject(error)
});
request.interceptors.response.use(
response => {
let res = response.data;
if (response.config.responseType === 'blob') {
return res
}
if (typeof res === 'string') {
res = res ? JSON.parse(res) : res
}
return res;
},
error => {
console.log('err' + error)
return Promise.reject(error)
}
)
export default request
修改fetch改成Axios,方式
request.get("http://localhost:9090/user/page",{
params:{
pageNum:this.pageNum,
pageSize:this.pageSize,
username:this.username,
address:this.address,
email:this.email
}
}).then(res=>{
this.tableData = res.records
this.total = res.total
})
}
1、新增重置按钮
<el-button type="warning" @click="reset">重置</el-button>
reset(){
this.username=""
this.address=""
this.email=""
this.load()
}
2、添加新增弹窗…(详情看–其他–)
Home.vue
<!--https://element.eleme.cn/#/zh-CN/component/container#container-bu-ju-rong-qi 搜布局容器,取其中代码,并做修改-->
<template>
<!--菜单下面的横线border: 1px solid #eee",去掉-->
<el-container style="height: 100vh">
<!--页面架构-->
<!--el-aside侧边栏-->
<!--el-container有el-header主体 设置颜色:border-bottom: 1px solid #ccc;居中line-height: 60px-->
<!--el-container-->
<!--:width="sideWidth+'px'",绑定,并使其自动更换宽度-->
<el-aside :width="sideWidth+'px'" style="background-color: rgb(238, 241, 246); box-shadow: 2px 0 20px #888888;">
<!--overflow: hidden 多层子菜单菜单超出,设置样式;background-color:颜色;text-color字体颜色-->
<!--active-text-color="#ffdo4b" 选中菜单的颜色;绑定 :collapse-transition="false"菜单的动漫:
collapse="isCollapse"菜单收缩根据这个变量来变化 -->
<el-menu :default-openeds="['1', '3']" style="min-height: 100%; overflow: hidden"
background-color="rgb(48,65,86)"
text-color="#fff"
active-text-color="#ffdo4b"
:collapse-transition="false"
:collapse="isCollapse"
>
<!--设置log,新增一个div;style="height: 60px;line-height: 60px;设置高度text-align: center"位置居中,左(默认),右-->
<!--style="width: 20px"设置图片大小;position: relative;位置相对 top: 5px 下移动;-->
<div style="height: 60px;line-height: 60px;text-align: center">
<img src="../assets/logo.png" alt="" style="width: 20px;position: relative;top: 5px;margin-right: 5px">
<!--是否展示绑定一个变量v-show="logoTextShow"-->
<b style="color: white" v-show="logoTextShow">后台管理系统</b>
</div>
<el-submenu index="1">
<template slot="title">
<!--样式有问题调整导航-->
<i class="el-icon-message"></i>
<span>导航一</span>
</template>
<el-menu-item-group>
<template slot="title">分组一</template>
<el-menu-item index="1-1">选项1</el-menu-item>
<el-menu-item index="1-2">选项2</el-menu-item>
</el-menu-item-group>
<el-menu-item-group title="分组2">
<el-menu-item index="1-3">选项3</el-menu-item>
</el-menu-item-group>
<el-submenu index="1-4">
<template slot="title">选项4</template>
<el-menu-item index="1-4-1">选项4-1</el-menu-item>
</el-submenu>
</el-submenu>
<el-submenu index="2">
<template slot="title">
<i class="el-icon-menu"></i>
<span>导航二</span>
</template>
<el-menu-item-group>
<template slot="title">分组一</template>
<el-menu-item index="2-1">选项1</el-menu-item>
<el-menu-item index="2-2">选项2</el-menu-item>
</el-menu-item-group>
<el-menu-item-group title="分组2">
<el-menu-item index="2-3">选项3</el-menu-item>
</el-menu-item-group>
<el-submenu index="2-4">
<template slot="title">选项4</template>
<el-menu-item index="2-4-1">选项4-1</el-menu-item>
</el-submenu>
</el-submenu>
<el-submenu index="3">
<template slot="title">
<i class="el-icon-setting"></i>
<span>导航三</span>
</template>
<el-menu-item-group>
<template slot="title">分组一</template>
<el-menu-item index="3-1">选项1</el-menu-item>
<el-menu-item index="3-2">选项2</el-menu-item>
</el-menu-item-group>
<el-menu-item-group title="分组2">
<el-menu-item index="3-3">选项3</el-menu-item>
</el-menu-item-group>
</el-submenu>
</el-menu>
</el-aside>
<el-container>
<!--菜单顶部调整-->
<el-header style=" font-size: 12px;border-bottom: 1px solid #ccc;line-height: 60px;display: flex">
<div style="flex: 1;font-size: 18px">
<!--绑定点击事件-->
<span v-bind:class="collapseBtnClass" style="cursor:pointer; " @click="collapse"></span>
</div>
<!--el-dropdown下展图标设置,可以通过f12知道其位置-->
<el-dropdown style="width: 70px; cursor:pointer">
<!--class="el-icon-caret-bottom"图标样式;style="margin-left: 5px"可以设置与文字距离-->
<span>黄业斌</span><i class="el-icon-caret-bottom" style="margin-left: 5px"></i>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item>个人信息</el-dropdown-item>
<el-dropdown-item>退出</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</el-header>
<el-main>
<!--添加面包屑-->
<div style="margin-bottom: 30px">
<el-breadcrumb separator="/">
<el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
<el-breadcrumb-item>用户管理</el-breadcrumb-item>
</el-breadcrumb>
</div>
<!--搜索position: relative ; top:-10px连这用的-->
<div style="position: relative ; top:-10px">
<!--width英 [w?dθ]宽度;placeholder="请输入名称"提示语,suffix-icon="el-icon-search"嵌套图标-->
<el-input style="width: 200px" placeholder="请输入名称" suffix-icon="el-icon-search" class="mr-10"
v-model="username"></el-input>
<el-input style="width: 200px" placeholder="邮箱" suffix-icon="el-icon-message" class="mr-10"
v-model="email"></el-input>
<el-input style="width: 200px" placeholder="地址" suffix-icon="el-icon-position" class="mr-10"
v-model="address"></el-input>
<!--@click="load"点击绑定load方法-->
<el-button class="ml-5" type="primary" @click="load">搜索</el-button>
<el-button type="warning" @click="reset">重置</el-button>
</div>
<!--按钮 <i class="el-icon-circle-plus-outline" >嵌套按钮-->
<div style=" position: relative; top:-6px ">
<el-button type="primary" @click="handleAdd">新增 <i class="el-icon-circle-plus-outline"></i></el-button>
<el-button type="danger" @click="delBatch">批量删除 <i class="el-icon-circle-close"></i></el-button>
<el-button type="primary">导入 <i class="el-icon-top"></i></el-button>
<el-button type="primary">导出 <i class="el-icon-bottom"></i></el-button>
</div>
<!--表格设置边框border stripe有线-->
<!--:header-cell-class-name="headerBg"和下面的<script><script>有联系-->
<!-- :data="tableData" 与下面的<script>中的created()做数据绑定-->
<el-table :data="tableData" border stripe :header-cell-class-name="headerBg"
@selection-change="handleSelectionChange">
<el-table-column type="selection" width="55"></el-table-column>
<el-table-column prop="id" label="id" width="50"></el-table-column>
<el-table-column prop="username" label="用户名"></el-table-column>
<el-table-column prop="nickname" label="昵称"></el-table-column>
<el-table-column prop="phone" label="电话"></el-table-column>
<el-table-column prop="email" label="邮箱"></el-table-column>
<el-table-column prop="address" label="地址"></el-table-column>
<!--添加编辑操作-->
<el-table-column label="操作" width="150">
<template slot-scope="scope">
<el-button @click="handleEdit(scope.row)">编辑</el-button>
<!--Popconfirm 气泡确认框-->
<el-popconfirm
class="ml-10"
title="你要删除吗?"
@confirm="delone(scope.row.id)"
>
<el-button type="danger" slot="reference" class="ml-5">删除</el-button><!--slot="reference"使按钮显示-->
</el-popconfirm>
</template>
</el-table-column>
</el-table>
<!--分页:style="padding: 20px(高度) 10px(margin-left[默认隐藏]:10px)[左距离] 设置位置-->
<div style="padding: 20px 10px">
<!--@size-change="handleSizeChange"、@current-change="handleCurrentChange"、:current-page="pageNum"
:page-size="pageSize"、实现动态翻页-->
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="pageNum"
:page-size="pageSize"
:page-sizes="[10, 20, 50, 100]"
layout="total, sizes, prev, pager, next, jumper"
:total="total">
</el-pagination>
</div>
<div>
<!--visible.sync=""控制弹窗是否显示-->
<el-dialog title="用户信息" :visible.sync="dialogFormVisible" width="30%">
<el-form label-width="80px">
<el-form-item label="用户名">
<el-input v-model="form.username" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="昵称">
<el-input v-model="form.nickname" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="电话">
<el-input v-model="form.phone" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="邮箱">
<el-input v-model="form.email" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="地址">
<el-input v-model="form.address" autocomplete="off"></el-input>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogFormVisible = false">取 消</el-button>
<el-button type="primary" @click="saveUser">确 定</el-button>
</div>
</el-dialog>
</div>
</el-main>
</el-container>
</el-container>
</template>
<script>
import request from "@/utils/request";
export default {
data() {
return {
username: "",
address: "",
email: "",
nickname: "",
tableData: [],
total: 0,
pageNum: 1,
pageSize: 10,
collapseBtnClass: 'el-icon-s-fold',
isCollapse: false,
sideWidth: 200,
//logo处理
logoTextShow: true,
headerBg: 'headerBg',
dialogFormVisible: false,
form: {},
multipleSelection: []
}
},
created() {
//分页
this.load()
},
methods: {
collapse() { //点击按钮触发修改
this.isCollapse = !this.isCollapse
if (this.isCollapse) { //收缩
this.sideWidth = 64
//并更换图标
this.collapseBtnClass = 'el-icon-s-unfold'
this.logoTextShow = false
} else {//展开
this.sideWidth = 200
//并更换图标
this.collapseBtnClass = 'el-icon-s-fold'
this.logoTextShow = true
}
},
reset() {
this.username = ""
this.address = ""
this.email = ""
this.load()
},
//分页
load() {
//请求分页查询数据
//注意:res.json()和res.join()
// fetch("http://localhost:9090/user/page?pageNum=1&pageSize=2").then(res =>res.json()).then(res =>{
// console.log(res)
// 改成动态
// fetch("http://localhost:9090/user/page?" +
// "pageNum="+this.pageNum +
// "&pageSize="+this.pageSize+
// "&username="+this.username+
// "&address="+this.address+
// "&email="+this.email
// ).then(res =>res.json()).then(res =>{
// console.log(res)
// //绑定接口的数据
// this.tableData = res.data
// this.total = res.total
// })
//-----------------------------------------------------------------------------
//修改成Axios,方式
request.get("/user/page", {
params: {
pageNum: this.pageNum,
pageSize: this.pageSize,
username: this.username,
address: this.address,
email: this.email
}
}).then(res => {
//绑定接口的数据
this.tableData = res.records
this.total = res.total
})
},
rules: {
username: [
{required: true, message: '请输入活动名称', trigger: 'blur'},
{min: 3, max: 5, message: '长度在 3 到 5 个字符', trigger: 'blur'}
]
},
//添加用户确认
handleAdd() {
this.dialogFormVisible = true
this.form = {}
},
//添加用户
saveUser() {
request.post("/user/", this.form).then(res => {
if (res) {
this.$message.success("新增成功")
this.load()
} else {
this.$message.error("新增失败")
}
});
this.dialogFormVisible = false
},
//编辑用户
handleEdit(row) {
console.log(row)
this.form = row
this.dialogFormVisible = true
},
//删除用户
delone(id) {
console.log(id)
request.delete("/user/" + id, this.form).then(res => {
if (res) {
this.$message.success("删除成功")
this.load()
} else {
this.$message.error("删除失败")
}
});
this.dialogFormVisible = false
},
//批量删除
handleSelectionChange(val) {
console.log(val)
this.multipleSelection = val
},
//批量删除按钮
delBatch() {
let ids = this.multipleSelection.map(v =>v.id) //[{},{},{}]=>[1,2,3]对象转换成数组
console.log(ids)
request.post("/user/del/batch", ids).then(res => { //这里的","很关键,不能写成"+",会很刺激
if (res) {
this.$message.success("批量删除成功")
this.load()
} else {
this.$message.error("批量删除失败")
}
console.log(res)
});
},
//分页
handleCurrentChange(pageNum) {
this.pageNum = pageNum
this.load()
},
//分页
handleSizeChange(pageSize) {
this.pageSize = pageSize
this.load()
}
}
}
</script>
<style>
.headerBg {
background: rgba(204, 204, 204, 0.59) !important;
}
</style>
4、MybatisPlus自动生成代码
1、安装依赖
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.5.1</version>
</dependency>
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity</artifactId>
<version>1.7</version>
</dependency>
2、创建utils包,创建CodeGenerator.java类
package com.yebin.springboot2.utils;
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import java.util.Collections;
public class CodeGenerator {
private static void generate(){
FastAutoGenerator.create(
"jdbc:mysql://localhost:3306/my_project?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8",
"root", "123456")
.globalConfig(builder -> {
builder.author("ye_bin")
.enableSwagger()
.outputDir("F:\\Project\\springboot2\\src\\main\\java\\");
})
.packageConfig(builder -> {
builder.parent("com.yebin.springboot2")
.moduleName(null)
.pathInfo(Collections.singletonMap(OutputFile.mapperXml, "F:\\Project\\springboot2\\src\\main\\resources\\mapper"));
})
.strategyConfig(builder -> {
builder.entityBuilder().enableLombok();
builder.mapperBuilder().enableMapperAnnotation().build();
builder.controllerBuilder().enableHyphenStyle()
.enableRestStyle();
builder.addInclude("sys_user")
.addTablePrefix("t_", "sys_");
})
.execute();
}
}
3、下图位置可以复制模板去修改,也可以修改其他的
controller.java.vm
//自定义controller模板
package ${package.Controller};
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.List;
import $!{package.Service}.$!{table.serviceName};
import ${package.Entity}.${entity};
#if(${superControllerClassPackage})
import ${superControllerClassPackage};
#end
/**
* <p>
* $!{table.comment} 前端控制器
* </p>
*
* @author ${author}
* @since ${date}
*/
#if(${restControllerStyle})
@RestController
#else
@Controller
#end
@RequestMapping("#if(${package.ModuleName})/${package.ModuleName}#end/#if(${controllerMappingHyphenStyle})${controllerMappingHyphen}#else${table.entityPath}#end")
#if(${kotlin})
class ${table.controllerName}#if(${superControllerClass}) : ${superControllerClass}()#end
#else
#if(${superControllerClass})
public class ${table.controllerName} extends ${superControllerClass} {
#else
public class ${table.controllerName} {
#end
@Resource
private ${table.serviceName} ${table.entityPath}Service;
@PostMapping
public Boolean save(@RequestBody ${entity} ${table.entityPath}){
return ${table.entityPath}Service.saveOrUpdate(${table.entityPath});
}
@DeleteMapping("/{id}")
public Boolean delete(@PathVariable Integer id){
return ${table.entityPath}Service.removeById(id);
}
@GetMapping
public List<${entity}> findAll(){
return ${table.entityPath}Service.list();
}
@GetMapping("/{id}")
public List<${entity}> findOne(@PathVariable Integer id){
return ${table.entityPath}Service.list();
}
@GetMapping("/page")
public IPage<${entity}> findPage(
@RequestParam Integer pageNum,
@RequestParam Integer pageSize
){
QueryWrapper${entity}> queryWrapper = new QueryWrapper<>();
queryWrapper.orderByDesc("id");
return ${table.entityPath}Service.page(new Page<>(pageNum,pageSize),queryWrapper);
}
}
}
#end
5、Vue使用路由
修改Home.vue文件改成Manage.vue
拆分Manage.vue
导入vuex
npm i vuex@3.6.2 -s
后面再补
6、springboot实现导入导出
Hutool官网:https://www.hutool.cn/docs/#/
导入依赖
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.7.2</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.17</version>
</dependency>
导出
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9RQCQmL3-1656746400682)(springboot+vue.assets/image-20220629224926854.png)]
User
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-poIyZxZ4-1656746400683)(springboot+vue.assets/image-20220629224809495.png)]
导入
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9OIlTtXB-1656746400684)(springboot+vue.assets/image-20220629224837014.png)]
7、springboot和Vue实现用户登录
登录页面
其他
div标签
1、div有什么作用
div在html中有着分割的作用,分割与其他样式的作用,去设置页面的布局和样式,主要的作用就是包含一个区块,区块夹在div中,和前后代码隔开,形成一个区块。
2、div用法
是一个块级元素。这意味着它的内容自动地开始一个新行。实际上,换行是固有的特定的格式表现。可以通过的 class style id 应用额外的样式。
java的泛型
1、泛型本质
Java 泛型(generics)是 JDK 5 中引入的一个新特性, 泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型。
泛型的本质是参数化类型,即给类型指定一个参数,然后在使用时再指定此参数具体的值,那样这个类型就可以在使用时决定了。这种参数类型可以用在类、接口和方法中,分别被称为泛型类、泛型接口、泛型方法。
ArrayList<Integer> intValues = new ArrayList<Integer>()
2、优点:
Java语言中引入泛型是一个较大的功能增强。不仅语言、类型系统和编译器有了较大的变化,以支持泛型,而且类库也进行了很大的改动,许多重要的类,比如集合框架,都已经成为泛型化的了。这带来了很多好处:
1、类型安全
在没有泛型之前,从集合中读取到的每一个对象都必须进行类型转换,如果不小心插入了错误的类型对象,在运行时的转换处理就会出错。
public static void noGeneric() {
ArrayList names = new ArrayList();
names.add("mikechen的互联网架构");
names.add(123);
}
public static void useGeneric() {
ArrayList<String> names = new ArrayList<>();
names.add("mikechen的互联网架构");
names.add(123);
}
2、消除强制类型转换
泛型的一个附带好处是,消除源代码中的许多强制类型转换,这使得代码更加可读,并且减少了出错机会。
List list = new ArrayList();
list.add("hello");
String s = (String) list.get(0);
List<String> list = new ArrayList<String>();
list.add("hello");
String s = list.get(0);
3、更高的运行效率
在非泛型编程中,将筒单类型作为Object传递时会引起Boxing(装箱)和Unboxing(拆箱)操作,这两个过程都是具有很大开销的。引入泛型后,就不必进行Boxing和Unboxing操作了,所以运行效率相对较高,特别在对集合操作非常频繁的系统中,这个特点带来的性能提升更加明显。
泛型变量固定了类型,使用的时候就已经知道是值类型还是引用类型,避免了不必要的装箱、拆箱操作
object a=1;
int b=(int)a;
public static T GetValue<T>(T a){
return a;
}
public static void Main(){
int b=GetValue<int>(1);
}
4、潜在的性能收益
3、如何使用泛型
泛型有三种使用方式,分别为:泛型类、泛型接口和泛型方法。
1、泛型类
public class 类名 <泛型类型1,...> {
}
注意事项:泛型类型必须是引用类型(非基本数据类型)
定义泛型类,在类名后添加一对尖括号,并在尖括号中填写类型参数,参数可以有多个,多个参数使用逗号分隔:
public class GenericClass<ab,a,c> {}
当然,这个后面的参数类型也是有规范的,不能像上面一样随意,通常类型参数我们都使用大写的单个字母表示:
T:任意类型 type
E:集合中元素的类型 element
K:key-value形式 key
V: key-value形式 value
示例代码:
public class GenericClass<T> {
private T value;
public GenericClass(T value) {
this.value = value;
}
public T getValue() {
return value;
}
public void setValue(T value) {
this.value = value;
}
}
2、泛型接口
public interface interfaceName<T>
注意:
方法声明中定义的形参只能在该方法里使用,而接口、类声明中定义的类型形参则可以在整个接口、类中使用。当调用fun()方法时,根据传入的实际对象,编译器就会判断出类型形参T所代表的实际类型。
public interface GenericInterface<T> {
void show(T value);}
}
public class StringShowImpl implements GenericInterface<String> {
@Override
public void show(String value) {
System.out.println(value);
}}
public class NumberShowImpl implements GenericInterface<Integer> {
@Override
public void show(Integer value) {
System.out.println(value);
}}
注意:
GenericInterface<String> genericInterface = new NumberShowImpl();
GenericInterface g1 = new NumberShowImpl();
GenericInterface g2 = new StringShowImpl();
3、泛型方法
泛型方法,是在调用方法的时候指明泛型的具体类型 。
public <T>T method Tt
示例
public <T> T genercMethod(T t){
System.out.println(t.getClass());
System.out.println(t);
return t;
}
public static void main(String[] args) {
GenericsClassDemo<String> genericString = new GenericsClassDemo("helloGeneric");
String str = genericString.genercMethod("hello");
Integer i = genericString.genercMethod(123);
}
数据库三大范式是什么?
第一范式:每个列都不可以在拆分。 第二范式:在第一范式的基础上,非主键列完全依赖于逐渐,而不能是依赖于主键的一部分。 第三范式:在第二范式的基础上,非主键列只依赖于主键,不依赖于其他非主键。 在设计数据库结构的时候,要尽量遵守三范式,如果不遵守,必须有足够的理由。比如性能。事实上我们经常会为了性能而妥协数据库的设计。
mybatis xml格式
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yebinhuang.mapper.UserMapper">
</mapper>
@JsonIgnore
忽略某个字段不给前端展示
前端与后端做数据绑定
后端提供一个接口:http://localhost:9090/user/page?pageNum=1&pageSize=2"
数据类型如下:
{
"total": 8,
"data": [
{
"id": 1,
"username": "admin",
"nickname": "管理员",
"email": "hyblist@163.com",
"phone": "17324070785",
"address": "广东茂名"
},
{
"id": 2,
"username": "xiaoming",
"nickname": "小明",
"email": "xiaoming@163.com",
"phone": "10086",
"address": "小明的家"
}
]
}
前端操作
<template>
</div>
<!--表格设置边框border stripe有线-->
<!--:header-cell-class-name="headerBg"和下面的<script><script>有联系-->
<!-- :data="tableData" 与下面的<script>中的created()做数据绑定-->
<el-table :data="tableData" border stripe :header-cell-class-name="headerBg">
<el-table-column prop="id" label="id" width="50"></el-table-column>
<el-table-column prop="username" label="用户名" ></el-table-column>
<el-table-column prop="nickname" label="昵称" ></el-table-column>
<el-table-column prop="phone" label="电话" ></el-table-column>
<el-table-column prop="email" label="邮箱" ></el-table-column>
<el-table-column prop="address" label="地址"></el-table-column>
<!--添加编辑操作-->
<el-table-column label="操作" width="150" >
<template slot-scope="scope" >
<el-button >编辑</el-button>
<el-button type="danger">删除</el-button>
</template>
</el-table-column>
</el-table>
<!--分页:style="padding: 20px(高度) 10px(margin-left[默认隐藏]:10px)[左距离] 设置位置-->
<div style="padding: 20px 10px">
</template>
<script>
export default {
created(){
//请求分页查询数据
//注意:res.json()和res.join()
fetch("http://localhost:9090/user/page?pageNum=1&pageSize=2").then(res =>res.json()).then(res =>{
console.log(res)
//绑定接口的数据
this.tableData = res.data
this.total = res.total
})
}
</script>
复制地址
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9HWlzC9S-1656746400685)(springboot+vue.assets/image-20220627221548676.png)]
前端一些功能实现
1、按钮弹窗(Dialog 对话框)
关键:visible.sync=""控制弹窗是否显示,官方采用dialogFormVisible控制
<div>
<!--visible.sync=""控制弹窗是否显示,官方采用dialogFormVisible控制-->
<el-dialog title="用户信息" :visible.sync="dialogFormVisible" width="30%">
<el-form label-width="80px">
<el-form-item label="用户名">
<el-input v-model="form.username" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="昵称">
<el-input v-model="form.nickname" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="电话">
<el-input v-model="form.phone" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="邮箱">
<el-input v-model="form.email" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="地址">
<el-input v-model="form.address" autocomplete="off"></el-input>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogFormVisible = false">取 消</el-button>
<el-button type="primary" @click="saveUser">确 定</el-button>
</div>
</el-dialog>
</div>
2、二次确认弹窗(Popconfirm 气泡确认框)
<template slot-scope="scope">
<el-button @click="handleEdit(scope.row)">编辑</el-button>
<!--Popconfirm 气泡确认框-->
<el-popconfirm
class="ml-10"
title="你要删除吗?"
@confirm="delone(scope.row.id)"
>
<el-button type="danger" slot="reference" class="ml-5">删除</el-button><!--slot="reference"使按钮显示-->
</el-popconfirm>
</template>
3、新增(绑定按钮弹窗)
新增按钮绑定handleAdd()方法
<div style=" position: relative; top:-6px ">
<el-button type="primary" @click="handleAdd">新增 <i class="el-icon-circle-plus-outline"></i></el-button>
<el-button type="danger" @click="delBatch">批量删除 <i class="el-icon-circle-close"></i></el-button>
<el-button type="primary">导入 <i class="el-icon-top"></i></el-button>
<el-button type="primary">导出 <i class="el-icon-bottom"></i></el-button>
</div>
handleAdd()方法
handleAdd() {
this.dialogFormVisible = true
this.form = {}
},
弹窗的确认按钮绑定@click="saveUser"完成接口请求
saveUser() {
request.post("/user/", this.form).then(res => {
if (res) {
this.$message.success("新增成功")
this.load()
} else {
this.$message.error("新增失败")
}
});
this.dialogFormVisible = false
},
4、列表编辑(调用)
列表取row中数据:row打印出来是一个对象
<el-table-column label="操作" width="150">
<template slot-scope="scope">
<el-button @click="handleEdit(scope.row)">编辑</el-button>
</template>
</el-table-column>
绑定了@click="handleEdit(scope.row)"方法
handleEdit(row) {
console.log(row)
this.form = row
this.dialogFormVisible = true
},
5、删除(调用二次弹窗的方法/或者不调用,如过不调用可以直接用@click=“delone(scope.row.id)”)
@confirm=“delone(scope.row.id)”
delone(id) {
request.delete("/user/" + id, this.form).then(res => {
if (res) {
this.$message.success("删除成功")
this.load()
} else {
this.$message.error("删除失败")
}
});
this.dialogFormVisible = false
},
6、批量删除
在data()里面添加字段
multipleSelection: []
使<el-table></el-table>绑定@selection-change="handleSelectionChange"这个方法
<el-table :data="tableData" border stripe :header-cell-class-name="headerBg"
@selection-change="handleSelectionChange">
<el-table-column type="selection" width="55"></el-table-column>
handleSelectionChange()
,
handleSelectionChange(val) {
console.log(val)
this.multipleSelection = val
}
批量删除按钮绑定@click="delBatch"方法
<div style=" position: relative; top:-6px ">
<el-button type="primary" @click="handleAdd">新增 <i class="el-icon-circle-plus-outline"></i></el-button>
<el-button type="danger" @click="delBatch">批量删除 <i class="el-icon-circle-close"></i></el-button>
<el-button type="primary">导入 <i class="el-icon-top"></i></el-button>
<el-button type="primary">导出 <i class="el-icon-bottom"></i></el-button>
</div>
@click="delBatch"方法
delBatch() {
let ids = this.multipleSelection.map(v =>v.id)
console.log(ids)
request.post("/user/del/batch", ids).then(res => {
if (res) {
this.$message.success("批量删除成功")
this.load()
} else {
this.$message.error("批量删除失败")
}
console.log(res)
});
全选(Table 表格)
<el-table-column type="selection" width="55"></el-table-column>
Exception
1、Invalid bound statement (not found): com.yebin.springboot.mapper.UserMapper.update
原因:没有配置mybatis的配置
mybatis:
mapper-locations: classpath:mapper/*xml
2、org.apache.ibatis.binding.BindingException: Parameter ‘pageNum’ not found. A
原因:@Param(“pageNum”)没有加@Param接收pageNum
@Select("select * from sys_user limit #{pageNum},#{pageSize}")
List<User> selectPage(@Param("pageNum")Integer pageNum,@Param("pageSize")Integer pageSize);
3、前端跨域问题
Access to fetch at ‘http://localhost:9090/user/page?pageNum=1&pageSize=2’ from origin ‘http://localhost:8080’ has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource. If an opaque response serves your needs, set the request’s mode to ‘no-cors’ to fetch the resource with CORS disabled.
后端做调整:springboot跨域设置
package com.yebin.springboot.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
@Configuration
public class CorsConfig {
private static final long MAX_AGE = 24 * 60 * 60;
@Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.addAllowedOrigin("http://localhost:8080");
corsConfiguration.addAllowedHeader("*");
corsConfiguration.addAllowedMethod("*");
corsConfiguration.setMaxAge(MAX_AGE);
source.registerCorsConfiguration("/**", corsConfiguration);
return new CorsFilter(source);
}
}
4、The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.
原因:mysql服务没有启动
5、mybatis和mybatis-plus只能存在一个
mybatis和mybatis-plus只能存在一个,要不然会打架,所以导入依赖只能存在其中一个
mybatis-plus:
mapper-locations: classpath:mapper/*.xml
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
true map-underscore-to-camel-case: true
6、 Component template should contain exactly one root element. If you are using v-if on multiple elements, use v-else-if to chain them instead.
原因缺少一个<div></div>
7、Uncaught TypeError: (0 , vue__WEBPACK_IMPORTED_MODULE_2__.reactive) is not a function
原因vuex版本太高
npm i vuex@3.6.2 -s
if (res) {
this.$message.success("批量删除成功")
this.load()
} else {
this.$message.error("批量删除失败")
}
console.log(res)
});
全选(Table 表格)
```vue
<el-table-column type="selection" width="55"></el-table-column>
Exception
1、Invalid bound statement (not found): com.yebin.springboot.mapper.UserMapper.update
原因:没有配置mybatis的配置
mybatis:
mapper-locations: classpath:mapper/*xml
2、org.apache.ibatis.binding.BindingException: Parameter ‘pageNum’ not found. A
原因:@Param(“pageNum”)没有加@Param接收pageNum
@Select("select * from sys_user limit #{pageNum},#{pageSize}")
List<User> selectPage(@Param("pageNum")Integer pageNum,@Param("pageSize")Integer pageSize);
3、前端跨域问题
Access to fetch at ‘http://localhost:9090/user/page?pageNum=1&pageSize=2’ from origin ‘http://localhost:8080’ has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource. If an opaque response serves your needs, set the request’s mode to ‘no-cors’ to fetch the resource with CORS disabled.
后端做调整:springboot跨域设置
package com.yebin.springboot.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
@Configuration
public class CorsConfig {
private static final long MAX_AGE = 24 * 60 * 60;
@Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.addAllowedOrigin("http://localhost:8080");
corsConfiguration.addAllowedHeader("*");
corsConfiguration.addAllowedMethod("*");
corsConfiguration.setMaxAge(MAX_AGE);
source.registerCorsConfiguration("/**", corsConfiguration);
return new CorsFilter(source);
}
}
4、The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.
原因:mysql服务没有启动
5、mybatis和mybatis-plus只能存在一个
mybatis和mybatis-plus只能存在一个,要不然会打架,所以导入依赖只能存在其中一个
mybatis-plus:
mapper-locations: classpath:mapper/*.xml
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
true map-underscore-to-camel-case: true
6、 Component template should contain exactly one root element. If you are using v-if on multiple elements, use v-else-if to chain them instead.
原因缺少一个<div></div>
7、Uncaught TypeError: (0 , vue__WEBPACK_IMPORTED_MODULE_2__.reactive) is not a function
原因vuex版本太高
npm i vuex@3.6.2 -s
|