非常简单实用的前后端分离项目-仓库管理系统(Springboot+Vue)part 2
七、创建前端项目
你下载了nodejs吗?从cn官网下载:http://nodejs.cn/download/,或者从一个国外org网站下载,选择自己想要的版本https://nodejs.org/download/release/,双击下载好的安装文件,选择安装路径安装好即可。安装完成后,输入命令查看版本,mac首次安装都无需配置环境变量。
根据以上命令查看配置信息,先在设置路径目录下新建两个文件夹(eg:node_global和node_cache),设置新的文件夹
PS D: \nodejs> npm config set prefix "D: \nodejs\node_global"
PS D: \nodejs> npm config set cache "D: \nodejs\node_cache"
PS D: \nodejs> npm get registry
https: //registry.npmjs.org/
PS D: \nodejs> npm config set registry https://mirrors.cloud.tencent.com/npm/
管理员模式下载vue脚手架,理论上你应该下载过了
npm install -g @vue/cli
在cmd中创建vue项目 vue create vuedemo1 ,powershell中参见下方网页
“vue : 无法加载文件 D:\nodejs\node_global\vue.ps1,因为在此系统上禁止运行脚本”的解决方法-CSDN博客
用上下方向键移动,然后回车,我选择Vue2,等待创建完成
执行启动项目命令(注意要先进入项目目录)
cd vuedemo1
npm run serve
现在cd在desktop,vue create wms-web,选择vue2,Take A While......
cd进入,npm run serve成功启动vue脚手架,localhost:8080
八、前端项目导到idea中运行
把wms-web复制到springboot_vue_wms中,在idea打开项目,你要是足够nb用webstrom去吧
为了节约时间,不用cmd一条慢慢输入命令,可以选择小绿三角的''编译配置''
停止服务直接CTRL + C 即可
记得把前端的git删除
tmd,后面vue服务器频频报错,找了我一个半小时,问题解决了,我的idea不知道为什么对node_modules文件进行了排除(变成黄色的),右键该文件后将目录标记为不排除就能解决element提示的问题,记得更新对应的本地的vue服务器
九、导入Element-ui
Element - 网站快速成型工具 饿了么 nb
注意了,这个安装方式和引用方式只适用于vue2,vue3用这个会报错,就算强行安装上,最后运行的时候页面只会是空白的。
npm i element-ui -S
报错可能是版本不匹配, 试试npm install element-plus --save
npm install --legacy-peer-deps element-ui --save也行
打开对应的文件管理器,发现安装成功
好了,现在是VUE时间!
记得把main.js必要的修改
import Vue from 'vue'
import App from './App.vue'
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
Vue.config.productionTip = false
Vue.use(ElementUI)
new Vue({
render: h => h(App),
}).$mount('#app')
App.vue如下
<template>
<div id="app">
<el-button type="primary">BUTTON</el-button>
</div>
</template>
<script>
export default {
name: 'App',
components: {
}
}
</script>
<style>
</style>
十、搭建页面布局
难道不用router吗
新建IndexPage.vue文件,(后面你会命名为index,这里index报错是因为规范是组件名应该是多个单词组成的,而不是单个单词。可以考虑IndexPage或者其他的多词命名. 实在说太多不好弄的 , 导入之后报错的在vue.config中配置lintOnSave: false(胡说八道) //@8 版本中新增了要求组件名称以驼峰格式命名
<template>
<el-container style="height: 500px; border: 1px solid #eee">
<el-aside width="200px" style="background-color: rgb(238, 241, 246)">
<el-menu :default-openeds="['1', '3']">
<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">
<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>
</template>
<style scoped>
.el-header {
background-color: #B3C0D1;
color: #333;
line-height: 60px;
}
.el-aside {
color: #333;
}
</style>
<script>
export default {
name:"IndexPage",
data() {
const item = {
date: '2016-05-02',
name: '王小虎',
address: '上海市普陀区金沙江路 1518 弄'
};
return {
tableData: Array(20).fill(item)
}
}
};
</script>
App.vue相应的添加
<template>
<div id="app">
<IndexPage></IndexPage>
</div>
</template>
<script>
import IndexPage from "@/components/IndexPage.vue";
export default {
name: 'App',
components: {
IndexPage
}
}
</script>
<style>
/*
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
*/
</style>
-
白屏是因为外层需要template
根据你的需求微修一下,我对部分部件进行了height:100%的代码修改
在assets下新建一个global.css文件,在main.js中导入 import './assets/global.css'
*{
margin:0;
padding: 0;
}
在IndexPage中style添加
.el-main{ padding:5px; }
十一、页面布局的拆分
原页面太长了,在components中新建几个界面AppAside.vue,AppHeader.vue,IndexPage.vue,AppMain.vue
AppAside是将menu部分剪切到template中;将dropdown中,给到AppHeader;table复制到Appmain( 其实是想改成MainComponent的 下面是IndexPage.vue
<template>
<el-container style="height: 100%; border: 1px solid #eee">
<el-aside width="200px" style="background-color: rgb(238, 241, 246);height: 100%">
<AppAside></AppAside>
</el-aside>
<el-container style="height: 100%">
<el-header style="text-align: right; font-size: 12px ;">
<AppHeader></AppHeader>
<span>王小虎</span>
</el-header>
<el-main style="height: 100%">
<AppMain></AppMain>
</el-main>
</el-container>
</el-container>
</template>
<style scoped>
.el-header {
background-color: #B3C0D1;
color: #333;
line-height: 60px;
}
.el-main{
padding:5px;
}
.el-aside {
color: #333;
}
</style>
<script>
import AppAside from "@/components/AppAside.vue";
import AppHeader from "@/components/AppHeader.vue";
import AppMain from "@/components/AppMain.vue";
export default {
name:"IndexPage",
components: {AppMain, AppHeader, AppAside},
};
</script>
如果有包版本的冲突,npm install --legacy-peer-deps
十二、编写Header头页面
1.dropdown下拉
@click和@click.native有什么区别,如何阻止第三方组件内部的冒泡一.@click和@click.nati - 掘金
这是一篇文章在vue3的部分同学们,可能对native的选择有帮助
AppHeader.vue
<template>
<div style="display:flex;line-height:60px;">
<div>
<i class="el-icon-s-fold" style="font-size:20px;vertical-align: middle;"></i>
</div>
<div style="flex:1;text-align:center;font-size:27px;">
<span>欢迎来到仓库管理系统</span>
</div>
<span>王小虎</span>
<el-dropdown trigger="click">
<i class="el-icon-arrow-down" style="margin-left:5px;"></i>
<el-dropdown-menu slot="dropdown"><!--直接给图标加line-height:60px就居中了;加上height和line-height,让他们相等就可以让文本垂直居中;加垂直vertical-align: middle;应该就好了-->
<el-dropdown-item @click.native="toUser">个人中心</el-dropdown-item>
<el-dropdown-item @click.native="logout">退出登录</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>
</template>
<style scoped>
</style>
<script>
export default{
name:"AppHeader",
methods:{
toUser() {
console.log('to_user')
},
logout(){
console.log('logout')
},
}
}
</script>
IndexPage.vue部分
<el-container style="height: 100%; border: 1px solid #eee">
<el-aside width="200px" style="background-color: rgb(238, 241, 246);height: 100%">
<AppAside></AppAside>
</el-aside>
2.菜单伸缩图标
原先的太多了,不符合项目的要求,
这里是因为设置了1px的border
3.欢迎字样
4.去除背景,加入下边框
十三、菜单导航页面编写
一级菜单,AppHeader.vue
<template>
<div style="display:flex;line-height:60px;">
<div>
<i class="el-icon-s-fold" style="font-size:20px;vertical-align: middle;"></i>
</div>
<div style="flex:1;text-align:center;font-size:27px;">
<span>欢迎来到仓库管理系统</span>
</div>
<span>王小虎</span>
<el-dropdown trigger="click">
<i class="el-icon-arrow-down" style="margin-left:5px;"></i>
<el-dropdown-menu slot="dropdown"><!--直接给图标加line-height:60px就居中了;加上height和line-height,让他们相等就可以让文本垂直居中;加垂直vertical-align: middle;应该就好了-->
<el-dropdown-item @click.native="toUser">个人中心</el-dropdown-item>
<el-dropdown-item @click.native="logout">退出登录</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>
</template>
<style scoped>
</style>
<script>
export default{
name:"AppHeader",
methods:{
toUser() {
console.log('to_user')
},
logout(){
console.log('logout')
},
}
}
</script>
十四、菜单导航页面伸缩
伸缩的思路:图标和文字,收起和展开是有变量的,根据element的官方文档,对aside修改
两相对比,发现动画不太流畅影响观感 。
并且header的选项,把信号跨组件给到aside,可以回去看看vue的多种跨组件方法吗?Vue跨组件通信8种方式汇总
可以直接使用全局事件总线快很多,这里提供一个不太好的方法(很卡):header点击图标---提交--->父组件--改变-->aside子组件(collapse)
IndexPage.vue
<template>
<el-container style="height: 100%; border: 1px solid #eee">
<el-aside :width="aside_width" style="background-color: rgb(238, 241, 246);height: 100% ;margin-left:-1px">
<AppAside :isCollapse="isCollapse"></AppAside>
</el-aside>
<el-container style="height: 100%">
<el-header style="text-align: right; font-size: 12px ;height:100%;border-bottom: rgba(168,168,168,0.3) 1px solid">
<AppHeader @doCollapse="doCollapse" :icon="icon"></AppHeader>
</el-header>
<el-main style="height: 100%">
<AppMain></AppMain>
</el-main>
</el-container>
</el-container>
</template>
<style scoped>
.el-header {
/*background-color:#B3C0D1;*/
color: #333;
line-height: 60px;
}
.el-main{
padding:5px;
}
.el-aside {
color: #333;
}
</style>
<script>
import AppAside from "@/components/AppAside.vue";
import AppHeader from "@/components/AppHeader.vue";
import AppMain from "@/components/AppMain.vue";
import appAside from "@/components/AppAside.vue";
export default {
name:"IndexPage",
computed: {
appAside() {
return appAside
}
},
components: {AppMain, AppHeader, AppAside},
data(){
return {
isCollapse:false,
aside_width:'200px',
icon:'el-icon-s-fold'
}
},
methods:{
doCollapse(){
console.log(11111)
this.isCollapse =!this.isCollapse
if(!this.isCollapse){//默认展开,你想写三目也行 this.isCollapse ===true?this.changeWidth="64px":this.changeWidth="200px"
this.aside_width='200px'
this.icon='el-icon-s-fold'
}else{
this.aside_width='62px'
this.icon='el-icon-s-unfold'
}
}
}
};
</script>
AppHeader.vue
<template>
<div style="display:flex;line-height:60px;">
<div style="cursor:pointer;">
<i :class="icon" style="font-size:20px;vertical-align: middle;" @click="collapse"></i>
</div>
<div style="flex:1;text-align:center;font-size:27px;">
<span>欢迎来到仓库管理系统</span>
</div>
<span>王小虎</span>
<el-dropdown trigger="click">
<i class="el-icon-arrow-down" style="margin-left:5px;"></i>
<el-dropdown-menu slot="dropdown"><!--直接给图标加line-height:60px就居中了;加上height和line-height,让他们相等就可以让文本垂直居中;加垂直vertical-align: middle;应该就好了-->
<el-dropdown-item @click.native="toUser">个人中心</el-dropdown-item>
<el-dropdown-item @click.native="logout">退出登录</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>
</template>
<style scoped>
</style>
<script>
export default{
name:"AppHeader",
props:{
icon:String
},
methods:{
toUser() {
console.log('to_user')
},
logout(){
console.log('logout')
},
collapse(){
this.$emit('doCollapse')
}
}
}
</script>
AppAside.vue
<template>
<el-menu
background-color="#545c64"
text-color="#fff"
active-text-color="#ffd04b"
style="height:100vh;"
default-active="/Home"
:collapse="isCollapse"
:collapse-transition="false">
<el-menu-item index="/One">
<i class="el-icon-s-home"></i>
<span slot="title">首页</span>
</el-menu-item>
<el-menu-item index="/Two">
<i class="el-icon-s-flag"></i>
<span slot="title">导航一</span>
</el-menu-item>
<el-menu-item index="/Home">
<i class="el-icon-s-opportunity"></i>
<span slot="title">导航二</span>
</el-menu-item>
</el-menu>
</template>
<style scoped>
</style>
<script>
export default{
name:"AppAside",
data(){
return{
// isCollapse:false
}
},
props:{
isCollapse:Boolean
}
}
</script>
十五、axios的安装和处理跨域
1.安装axios
npm install axios --save
在main.js全局引入axios
import axios from "axios";
Vue.prototype.$axios =axios;
跨域:解决SpringBoot跨域问题8种方法,含网关、-CSDN博客SpringBoot解决跨域的5种方式_springboot跨域-CSDN博客
package com.wms.common;
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 CorsConfig implements WebMvcConfigurer{
@override
public void addCorsMappings(CorsRegistry registry){
registry.addMapping("/**")
//是否发送Cookie
.allowCredentials(true)
//放行哪些原始域
.aliowedOriginPatterns("*")
.allowedMethods(new String[]{"GET","POST","PUT","DELETE"})
.allowedHeaders("*")
.exposedHeaders("*");
}
}
get使用 这个get前端写法已经过时了
this.$axios.get('http://localhost:8090/1ist').then(res=>{
console.log(res)
})
post使用
this.$axios.post('http://localhost:8091/user/1istP',()).then(res=>{
console.log(res)
})
将地址设置为全局,记得开mysql!!!!!!!!!!!!啊啊啊啊啊啊
实际上,跨域可以一个@CrossOrigin解决(@CrossOrigin使用场景要求(jdk1.8+,Spring4.2+)
但是请在wms/src/main/java/com.wms/common新建CorConfig.java
package com.wms.common;
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 CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
//是否发送Cookie
.allowCredentials(true)
//放行哪些原始域
.allowedOriginPatterns("*")
.allowedMethods(new String[]{"GET", "POST", "PUT", "DELETE"})
.allowedHeaders("*")
.exposedHeaders("*");
}
}
AppMain中
methods:{ loadGet(){ this.$axios.get('http://localhost:8090/user/list').then(res=>res.data).then(res=>{ console.log(res) }) } },
这个sql显示要在yml文件里加配置,可以搜mybatis控制台打印sql配置
请在pom中添加
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version> <!-- 请使用最新的版本号 -->
</dependency>
你可以将 StringUtil.isNotBlack(user.getName()) 替换为 StringUtils.isNotBlank(user.getName())。这样就可以正确地判断 user.getName() 是否既非 null 又不是空白字符串了。
在main.js中添加,从而全局地址
Vue.prototype.$httpUrl='http://localhost:8090'
this.$axios.get(this.$httpUrl+'/user/list').then(res=>res.data).then(res=>{可以把$httpUrl去掉,去用去拦截:这里就不这么搞了。
request.js可供选择使用,我就不用了Vue项目搭建常用的配置文件,request.js和vue.config.js_vue项目搭建常用的配置文件,request.js和vue.config.js-CSDN博客
// 1.引入axios
// 2.axios.create方法创建实例
// 3.使用实例对象创建请求拦截器
// 4.使用实例创建响应拦截器
// 5.export抛出实例对象
// 6.main.js中引入request文件对象
import axios from 'axios'
import store from '@/store/index'
const Server =axios.create({
baseURL:'',
timeout:3000
})
//使用Server创建请求拦截器
Server.interceptors.request.use(function(config){
store.commit('setLoading',true) //设置loading效果
return config;
},function(error){
return Promise.reject(error)
})
//使用Server创建响应拦截器
Server.interceptors.response.use(function(response){
console.log(response);
//判断接口返回的数据成功,直接返回数据中data数据
if(response.status == 200){
setTimeout(() => {
store.commit('setLoading',false) //设置loading效果
}, 1000);
return response.data;
}
return response;
},function(error){
return Promise.reject(error);
});
export default Server
UserController.java部分
//查询(模糊、匹配)
@PostMapping("/listP")
public List<User> listP(@RequestBody User user) {
LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper();
if(StringUtils.isNotBlank(user.getName())){
lambdaQueryWrapper.like(User::getName, user.getName());
}
//lambdaQueryWrapper.like(User::getName, user.getName());
//lambdaQueryWrapper.eq(User::getName, user.getName());
//eq就是完全匹配
return userService.list(lambdaQueryWrapper);
}
Appmain.vue部分
<script>
export default{
name:"AppMain",/*其实是想改成MainComponent的*/
data() {
return {
tableData: Array(10).fill(item)
}
},
methods:{
loadGet(){
this.$axios.get(this.$httpUrl+'/user/list').then(res=>res.data).then(res=>{
console.log(res)
})
},
loadPost(){
this.$axios.post(this.$httpUrl+'/user/listP',{}).then(res=>res.data).then(res=>{
console.log(res)
})
}
},
beforeMount() {
this.loadGet()
}
}
</script>
十六、列表展示
1.列表数据
2.用tag转换列
3.header-cell-style设置表头样式
4.加上边框
5.按钮(编辑、删除)
6.后端返回结果封装(Result)
AppMain.vue的需修改
<template>
<el-table :data="tableData">
<el-table-column prop="id" label="ID" width="60">
</el-table-column>
<el-table-column prop="no" label="账号" width="120">
</el-table-column>
<el-table-column prop="name" label="姓名" width="80">
</el-table-column>
<el-table-column prop="age" label="年龄" width="80">
</el-table-column>
<el-table-column prop="sex" label="性别" width="80">
</el-table-column>
<el-table-column prop="roleId" label="角色" width="80">
</el-table-column>
<el-table-column prop="phone" label="电话" width="120">
</el-table-column>
<el-table-column prop="operate" label="操作">
</el-table-column>
</el-table>
</template>
<style scoped>
</style>
<script>
export default{
name:"AppMain",/*其实是想改成MainComponent的*/
data() {
return {
tableData:[]
}
},
methods:{
loadGet(){
this.$axios.get(this.$httpUrl+'/user/list').then(res=>res.data).then(res=>{
console.log(res)
})
},
loadPost(){
this.$axios.post(this.$httpUrl+'/user/listP',{}).then(res=>res.data).then(res=>{
console.log(res)
this.tableData=res
})
}
},
beforeMount() {
this.loadPost()
}
}
</script>
这里我还报错了,改了loadPost才正确,这是tyqw的建议
从你的代码来看,问题可能出在以下几个方面:
1. **API 调用方式**:你在 `loadGet` 方法中使用了 GET 请求来获取用户列表,但在 `loadPost` 方法中使用了 POST 请求。如果你的后端 API 需要通过 POST 请求来获取用户列表,那么你应该只保留一个方法,并确保它正确地调用了后端接口。
2. **响应处理**:你需要将后端返回的数据赋值给 `tableData` 数组,以便在 Vue 组件中显示这些数据。目前,你只是打印了返回的数据,但没有将其赋值给 `tableData`。
3. **组件生命周期钩子**:你可以在 `mounted` 生命周期钩子中调用加载数据的方法,而不是在 `beforeMount` 中。这样可以确保 DOM 已经渲染完毕后再进行数据请求和更新。
4. **错误处理**:建议添加错误处理逻辑,以防止网络或服务器出现问题时导致应用崩溃。
以下是修改后的代码示例
<template>
<el-table :data="tableData">
<!-- ... -->
</el-table>
</template>
<script>
export default {
name: "AppMain",
data() {
return {
tableData: []
};
},
mounted() {
this.loadData();
},
methods: {
loadData() {
// 确保使用正确的 HTTP 方法(GET 或 POST)
const method = 'POST'; // 根据实际需求选择 GET 或 POST
if (method === 'GET') {
this.$axios.get(this.$httpUrl + '/user/list')
.then(response => {
this.tableData = response.data;
})
.catch(error => {
console.error('Error fetching data:', error);
});
} else if (method === 'POST') {
this.$axios.post(this.$httpUrl + '/user/listP', {})
.then(response => {
this.tableData = response.data;
})
.catch(error => {
console.error('Error fetching data:', error);
});
}
}
}
};
</script>
请注意以下几点:
- 将 `beforeMount` 改为 `mounted`。
- 在 `loadData` 方法中根据实际情况选择 GET 或 POST 请求。
- 将后端返回的数据直接赋值给 `tableData`。
- 添加错误处理逻辑。
这样应该可以帮助你解决“暂无数据”的问题。如果问题仍然存在,请检查后端 API 的 URL 是否正确以及返回的数据格式是否符合预期。
2.用tag转换列
<template>
<el-table :data="tableData">
<el-table-column prop="id" label="ID" width="60">
</el-table-column>
<el-table-column prop="no" label="账号" width="120">
</el-table-column>
<el-table-column prop="name" label="姓名" width="80">
</el-table-column>
<el-table-column prop="age" label="年龄" width="80">
</el-table-column>
<el-table-column prop="sex" label="性别" width="80">
<template slot-scope="scope">
<el-tag
:type="scope.row.sex === 1 ?'primary':'success'"
disable-transitions>{{scope.row.sex=== 1 ?'男':'女'}}</el-tag>
</template>
</el-table-column>
<el-table-column prop="roleId" label="角色" width="120">
<template slot-scope="scope">
<el-tag
:type="scope.row.roleId === 0 ?'danger':(scope.row.roleId === 1 ?'primary':'success')"
disable-transitions>{{scope.row.roleId === 0 ?'超级管理员':(scope.row.roleId === 1 ?'管理员':'用户')}}</el-tag>
</template>
</el-table-column>
<el-table-column prop="phone" label="电话" width="120">
</el-table-column>
<el-table-column prop="operate" label="操作">
</el-table-column>
</el-table>
</template>
可能会报错,idea又抽风了,进一步修改
<el-table-column prop="operate" label="操作">
<el-button size="small" type="success">编辑</el-button>
<el-button size="small" type="danger">删除</el-button>
</el-table-column>
修改对应的Usercontroller.java,因为你是一个列表,查出来的数据就放进去就好
//查询(模糊、匹配)
@PostMapping("/listP")
public Result listP(@RequestBody User user) {
LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper();
if(StringUtils.isNotBlank(user.getName())){
lambdaQueryWrapper.like(User::getName, user.getName());
}
//lambdaQueryWrapper.like(User::getName, user.getName());
//lambdaQueryWrapper.eq(User::getName, user.getName());
//eq就是完全匹配
return Result.success(userService.list(lambdaQueryWrapper));
}
重启后端服务WmsApplication,这时前端刷新后什么都没有是正常的,因为数据经过了一层封装,在AppMain中修改loadPost如下,对200进行判定,
loadPost(){
this.$axios.post(this.$httpUrl+'/user/listP',{}).then(res=>res.data).then(res=>{
console.log(res)
if(res.code===200){
this.tableData=res.data
}
else{
alert('获取数据失败!请刷新页面')
}
})
}
十七、分页查询
1.页面加上分页代码
2.修改查询方法和参数
3.处理翻页、设置条数逻辑(注意一个问题)
部分AppMain.vue
.......................
<el-table-column prop="operate" label="操作">
<el-button size="small" type="success">编辑</el-button>
<el-button size="small" type="danger">删除</el-button>
</el-table-column>
</el-table>
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="currentPage4"
:page-sizes="[2, 5, 10, 20, 50]"
:page-size="pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="total">
</el-pagination>
</div>
</template>
<style scoped>
</style>
<script>
export default{
name:"AppMain",/*其实是想改成MainComponent的*/
data() {
return {
tableData:[],
pageSize:10,
pageNum:1,
total:0
}
},
methods:{
loadGet(){
this.$axios.get(this.$httpUrl+'/user/list').then(res=>res.data).then(res=>{
console.log(res)
})
},
loadPost(){
this.$axios.post(this.$httpUrl+'/user/listPageC1',{
pageSize:this.pageSize,
pageNum:this.pageNum
}).then(res=>res.data).then(res=>{
console.log(res)
if(res.code===200){
this.tableData=res.data
this.total=res.total
}
else{
alert('获取数据失败!请刷新页面')
}
})
},
handleSizeChange(val) {
console.log(`每页 ${val} 条`);
this.pageNum=1//这个错误是先翻到第二页在调页面条数,显示无数据
this.pageSize=val
this.loadPost()
},
handleCurrentChange(val) {
console.log(`当前页: ${val}`);
this.pageNum=val
this.loadPost()
}
},
beforeMount() {
this.loadPost()
}
}
</script>
QueryPageParam.java
private HashMap parma = new HashMap();
UserController.vue
@PostMapping("/listPageC1")
//public List<User>listPage(@RequestBody HashMap map){
public Result listPageC1(@RequestBody QueryPageParam query) {
HashMap param = query.getParam();
String name = (String) param.get("name");
System.out.println("name===" + (String) param.get("name"));
Page<User> page = new Page();
page.setCurrent(query.getPageNum());
page.setSize(query.getPageSize());
LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper();
if(StringUtils.isNotBlank(name)&&!"null".equals(name)) {
lambdaQueryWrapper.like(User::getName, name);
}
//IPage result=userService.pageC(page);
IPage result=userService.pageCC(page,lambdaQueryWrapper);
System.out.println("total=="+result.getTotal());
return Result.success(result.getRecords(),result.getTotal());//提醒,listPageC1的return记得改
}
十八、查询处理
1.查询的布局(包含查询、重置按钮)
2.输入框,在appmain.vue中如此
<template>
<div>
<div style="margin-left:5px">
<el-input v-model="name" placeholder="请输入名字:" suffix-icon="el-icon-search" style="width:200px;"></el-input>
<el-button type ="primary" style="margin-left:5px" @click="loadPost">查询</el-button>
<el-button type="success">重置</el-button>
</div>
<el-table :data="tableData"
:header-cell-style="{background:'#e0ecf4',color:'#555'}"
border
>
main.js中如此
//Vue.use(ElementUI) Vue.use(ElementUI,{size:'small'})
查询要把数据传到后端去啊,loadpost需要传一个name过去啊,param是代表需要传的参数啊 。就是那个querypageparam一起封装的啊hashmap param想传什么传什么,
3下拉框
4.回车事件(查询)@keyup.enter.native
5.重置处理:新增
<el-input v-model="name" placeholder="请输入名字:" suffix-icon="el-icon-search" style="width:200px;"
@keyup.enter.native="loadPost"></el-input><!--Vue3输入框回车事件用@change="loadPostPage",重置只需加 clearable属性-->
<el-select v-model="sex" filterableplacehoLder="请选择性别">
<el-option
v-for="item in sexs"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
..................
..................
..................
export default{
name:"AppMain",/*其实是想改成MainComponent的*/
data() {
return {
tableData:[],
pageSize:10,
pageNum:1,
total:0,
name:'',
sex:'',
sexs:[
{
value:'1',
label:'男'
},{
value:'0',
label:'女'
}
],
}
},
可以优化,获取当前触发事件的dom的参数,再去执行axios请求,不然每次都要给后端发送一大堆数据 ,usercontroller部分如下
@PostMapping("/listPageC1")
//public List<User>listPage(@RequestBody HashMap map){
public Result listPageC1(@RequestBody QueryPageParam query) {
HashMap param = query.getParam();
String name = (String) param.get("name");
//System.out.println("name===" + (String) param.get("name"));
String sex = (String) param.get("sex");
Page<User> page = new Page();
page.setCurrent(query.getPageNum());
page.setSize(query.getPageSize());
LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper();
if(StringUtils.isNotBlank(name)&&!"null".equals(name)) {
lambdaQueryWrapper.like(User::getName, name);
}
if(StringUtils.isNotBlank(sex)) {
lambdaQueryWrapper.eq(User::getSex, sex);
}
//IPage result=userService.pageC(page);
IPage result=userService.pageCC(page,lambdaQueryWrapper);
System.out.println("total=="+result.getTotal());
return Result.success(result.getRecords(),result.getTotal());//提醒,listPageC1的return记得改
}
Appmain.vue
<div style="margin-left:5px">
<el-input v-model="name" placeholder="请输入名字:" suffix-icon="el-icon-search" style="width:200px;"
@keyup.enter.native="loadPost"></el-input><!--Vue3输入框回车事件用@change="loadPostPage",重置只需加 clearable属性-->
<el-select v-model="sex" filterableplacehoLder="请选择性别" style="margin-left:5px">
<el-option
v-for="item in sexs"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
<el-button type ="primary" style="margin-left:5px" @click="loadPost">查询</el-button>
<el-button type="success" @click="resetParam">重置</el-button><!--重置好像在input里面添加个clearable可以实现名字的清空;直接重置接post如何?-->
</div>
........................
..........................
..........................
.....................methods中添加这个
resetParam(){
this.name=''
this.sex=''
},
你的代码已经相当不错了,但确实有一些地方可以优化。特别是关于减少不必要的数据传输,可以通过优化前端逻辑来实现。下面是几个建议:
1. **动态构建请求参数**:
可以通过一个方法来动态构建要发送给后端的数据对象,这样可以确保只有用户实际更改过的字段才会包含在请求中。
2. **使用计算属性**:
对于那些依赖于其他数据变化而变化的数据,可以考虑使用计算属性(computed properties),这可以帮助减少不必要的数据处理。
3. **事件委托**:
虽然在这个例子中并不适用,但在某些情况下,使用事件委托可以减少DOM监听器的数量,提高性能。
4. **优化按钮操作**:
你可以将`loadPost`方法的调用封装在一个新的方法中,以便更好地控制何时以及如何发送请求。
以下是根据上述建议对你的代码进行的一些优化:
<template>
<div>
<div style="margin-left:5px">
<el-input v-model="searchParams.name" placeholder="请输入名字:" suffix-icon="el-icon-search" style="width:200px;" @keyup.enter.native="fetchData"></el-input>
<el-select v-model="searchParams.sex" filterable placeholder="请选择性别" style="margin-left:5px">
<el-option
v-for="item in sexs"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
<el-button type="primary" style="margin-left:5px" @click="fetchData">查询</el-button>
<el-button type="success" @click="resetParams">重置</el-button>
</div>
<el-table :data="tableData" :header-cell-style="{background:'#e0ecf4',color:'#555'}" border>
<!-- 表格列定义保持不变 -->
</el-table>
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="currentPage"
:page-sizes="[2, 5, 10, 20, 50]"
:page-size="pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="total">
</el-pagination>
</div>
</template>
<script>
export default {
name: "MainComponent",
data() {
return {
tableData: [],
pageSize: 10,
pageNum: 1,
total: 0,
searchParams: {
name: '',
sex: ''
},
sexs: [
{ value: '1', label: '男' },
{ value: '0', label: '女' }
]
};
},
methods: {
fetchData() {
const params = {
pageSize: this.pageSize,
pageNum: this.pageNum,
...this.searchParams // 展开搜索参数对象
};
// 过滤掉值为空的参数,避免向后端发送多余的数据
const filteredParams = Object.fromEntries(Object.entries(params).filter(([_, v]) => v !== '' && v !== null));
this.$axios.post(this.$httpUrl + '/user/listPageC1', filteredParams)
.then(res => res.data)
.then(res => {
if (res.code === 200) {
this.tableData = res.data;
this.total = res.total;
} else {
alert('获取数据失败!请刷新页面');
}
});
},
resetParams() {
this.searchParams.name = '';
this.searchParams.sex = '';
},
handleSizeChange(val) {
this.pageSize = val;
this.pageNum = 1; // 切换每页数量时重置页码为第一页
this.fetchData();
},
handleCurrentChange(val) {
this.pageNum = val;
this.fetchData();
}
},
beforeMount() {
this.fetchData();
}
};
</script>
主要改动点:
- - 将查询条件集中管理到 `searchParams` 对象中,便于管理和传递。
- - 在 `fetchData` 方法中,通过解构赋值和过滤,只发送非空的查询参数给后端。
- - 使用 `fetchData` 方法统一处理数据加载,简化了代码逻辑。
- - 修改组件名为 `MainComponent`,符合你的需求。
这些改动应该能帮助你减少不必要的数据传输,并使代码更加简洁高效。
十九、新增
1.新增按钮
2.弹出窗口,添加对centerDialogVisible的判定,以及弹窗
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="currentPage4"
:page-sizes="[2, 5, 10, 20, 50]"
:page-size="pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="total">
</el-pagination>
<el-dialog
title="提示"
:visible.sync="centerDialogVisible"
width="30%"
center>
<span>需要注意的是内容是默认不居中的</span>
<span slot="footer" class="dialog-footer">
<el-button @click="centerDialogVisible=false">取消</el-button>
<el-button type="primary" @click="centerDialogVisible=false">确定</el-button>
</span>
</el-dialog>
</div>
</template>
.................
..................
..................
sexs: [
{
value: '1',
label: '男'
}, {
value: '0',
label: '女'
}
],
centerDialogVisible: false
}
},
methods: {
add() {
this.centerDialogVisible = true
},
3.编写表单vue项目表单中使用resetFields()报错或未生效-CSDN博客
4.提交数据(提示信息、列表刷新)
5.数据的检查
哎呦wc,一定一定一定要注意啊,from和form由于键盘手快打错了,找了我2hours的bug,cnm
AppMain.vue
<template>
<div>
<div style="margin-left:5px">
<el-input v-model="name" placeholder="请输入名字:" suffix-icon="el-icon-search" style="width:200px;"
@keyup.enter.native="loadPost"></el-input><!--Vue3输入框回车事件用@change="loadPostPage",重置只需加 clearable属性-->
<el-select v-model="sex" filterable placehoLder="请选择性别" style="margin-left:5px">
<el-option
v-for="item in sexs"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
<el-button type="primary" style="margin-left:5px" @click="loadPost">查询</el-button>
<el-button type="success" @click="resetParam">重置</el-button>
<!--重置好像在input里面添加个clearable可以实现名字的清空;直接重置接post如何?-->
<el-button type="primary" style="margin-left:5px" @click="add">新增</el-button>
</div>
<el-table :data="tableData"
:header-cell-style="{background:'#e0ecf4',color:'#555'}"
border
>
<el-table-column prop="id" label="ID" width="60">
</el-table-column>
<el-table-column prop="no" label="账号" width="120">
</el-table-column>
<el-table-column prop="name" label="姓名" width="80">
</el-table-column>
<el-table-column prop="age" label="年龄" width="80">
</el-table-column>
<el-table-column prop="sex" label="性别" width="80">
<template slot-scope="scope">
<el-tag
:type="scope.row.sex === 1 ?'primary':'success'"
disable-transitions>{{ scope.row.sex === 1 ? '男' : '女' }}
</el-tag>
</template>
</el-table-column>
<el-table-column prop="roleId" label="角色" width="120">
<template slot-scope="scope">
<el-tag
:type="scope.row.roleId === 0 ?'danger':(scope.row.roleId === 1 ?'primary':'success')"
disable-transitions>
{{ scope.row.roleId === 0 ? '超级管理员' : (scope.row.roleId === 1 ? '管理员' : '用户') }}
</el-tag>
</template>
</el-table-column>
<el-table-column prop="phone" label="电话" width="120">
</el-table-column>
<el-table-column prop="operate" label="操作">
<el-button size="small" type="success">编辑</el-button>
<el-button size="small" type="danger">删除</el-button>
</el-table-column>
</el-table>
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="currentPage4"
:page-sizes="[2, 5, 10, 20, 50]"
:page-size="pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="total">
</el-pagination>
<el-dialog
title="提示"
:visible.sync="centerDialogVisible"
width="30%"
center>
<el-form ref="form" :rules="rules" :model="form" label-width="80px">
<el-form-item label="账号" prop="no">
<el-col :span="20">
<el-input v-model="form.no"></el-input>
</el-col>
</el-form-item>
<el-form-item label="密码" prop="password">
<el-col :span="20">
<el-input v-model="form.password"></el-input>
</el-col>
</el-form-item>
<el-form-item label="名字" prop="name">
<el-col :span="20">
<el-input v-model="form.name"></el-input>
</el-col>
</el-form-item>
<el-form-item label="年龄" prop="age">
<el-col :span="20">
<el-input v-model="form.age"></el-input>
</el-col>
</el-form-item>
<el-form-item label="性别">
<el-radio-group v-model="form.sex">
<el-radio label="1">男</el-radio>
<el-radio label="0">女</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="电话" prop="phone">
<el-col :span="20">
<el-input v-model="form.phone"></el-input>
</el-col>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="centerDialogVisible=false">取消</el-button>
<el-button type="primary" @click="save">确定</el-button>
</span>
</el-dialog>
</div>
</template>
<style scoped>
</style>
<script>
export default {
name: "AppMain",/*其实是想改成MainComponent的*/
data() {
let checkAge = (rule, value, callback) => {
if (value > 150) {
callback(new Error('年龄太大!lbd再来我让你飞起来!'));
} else {
callback();
}
};
let checkDuplicate = (rule, value, callback) => {
if (this.form.id) {
return callback();
}
this.$axios.get(this.$httpUrl+"/user/findByNo?no=" + this.form.no).then(res=>res.data).then(res => {
if (res.code!== 200) {//es6解构也可以
callback();
} else {
callback(new Error('账号已经存在'));
}
});
};
return {
tableData: [],
pageSize: 10,
pageNum: 1,
currentPage4: 1, // 新增这一行来初始化 currentPage4 的值
total: 0,
name: '',
sex: '',
sexs: [
{
value: '1',
label: '男'
}, {
value: '0',
label: '女'
}
],
centerDialogVisible: false,
form: {
name: '',
no: '',
age: '',
password: '',
phone: '',
sex: '0',
roleId: '2'
},
rules: {
no: [
{required: true, message: '请输入账号', trigger: 'blur'},
{min: 3, max: 8, message: '长度在3-8个字符', trigger: 'blur'},
{validator: checkDuplicate, trigger: 'blur'}
],
name: [
{required: true, message: '请输入名字', trigger: 'blur'},
],
password: [
{required: true, message: '请输入密码', trigger: 'blur'},
{min: 4, max: 10, message: '长度在4-10个字符之间', trigger: 'blur'}
],
age: [
{required: true, message: '请输入年龄', trigger: 'blur'},
{min: 1, max: 3, message: '长度在1到3个位', trigger: 'blur'},
{pattern: /^([1-9][0-9]*){1,3}$/, message: '年龄必须为正整数字', trigger: "blur"},
{validator: checkAge, trigger: 'blur'}
],
phone: [
{required: true, message: "手机号不能为空", trigger: "blur"},
{pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/, message: "请输入正确的手机号码", trigger: "blur"}
]
}
}
},
methods: {
resetForm() {
this.$refs.form.resetFields();
},
add() {
this.centerDialogVisible = true
this.$nextTick(()=>{
this.resetForm()
})
},
save() {
this.$refs.form.validate((valid) => {
if (valid) {
this.$axios.post(this.$httpUrl + '/user/save', this.form).then(res => res.data).then(res => {
console.log(res)
if (res.code === 200) {
this.$message({
message: '操作成功!',
type: 'success'
});
this.centerDialogVisible = false
this.loadPost();
this.resetForm()
} else {
this.$message({
message: '操作失败!请返回重新操作...',
type: 'error'
});
}
});
} else {
console.log('error submit!!');
return false;
}
});
},
loadGet() {
this.$axios.get(this.$httpUrl + '/user/list').then(res => res.data).then(res => {
console.log(res)
})
},
loadPost() {
this.$axios.post(this.$httpUrl + '/user/listPageC1', {
pageSize: this.pageSize,
pageNum: this.pageNum,
param: {
name: this.name,
sex: this.sex,
}
}).then(res => res.data).then(res => {
console.log(res)
if (res.code === 200) {
this.tableData = res.data
this.total = res.total
} else {
alert('获取数据失败!请刷新页面')
}
})
},
resetParam() {
this.name = ''
this.sex = ''
},
handleSizeChange(val) {
console.log(`每页 ${val} 条`);
this.pageNum = 1//这个错误是先翻到第二页在调页面条数,显示无数据
this.pageSize = val;
this.loadPost();
},
handleCurrentChange(val) {
console.log(`当前页: ${val}`);
this.pageNum = val
this.loadPost();
}
},
beforeMount() {
this.loadPost()
}
}
</script>
UserController.java部分
@GetMapping("/findByNo")
public Result findByNo(@RequestParam String no) {
List list=userService.lambdaQuery().eq(User::getNo, no).list();
return list.size()>0?Result.success(list):Result.fail();
}
编辑
<template>
<div>
<div style="margin-left:5px">
<el-input v-model="name" placeholder="请输入名字:" suffix-icon="el-icon-search" style="width:200px;"
@keyup.enter.native="loadPost"></el-input><!--Vue3输入框回车事件用@change="loadPostPage",重置只需加 clearable属性-->
<el-select v-model="sex" filterable placehoLder="请选择性别" style="margin-left:5px">
<el-option
v-for="item in sexs"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
<el-button type="primary" style="margin-left:5px" @click="loadPost">查询</el-button>
<el-button type="success" @click="resetParam">重置</el-button>
<!--重置好像在input里面添加个clearable可以实现名字的清空;直接重置接post如何?-->
<el-button type="primary" style="margin-left:5px" @click="add">新增</el-button>
</div>
<el-table :data="tableData"
:header-cell-style="{background:'#e0ecf4',color:'#555'}"
border
>
<el-table-column prop="id" label="ID" width="60">
</el-table-column>
<el-table-column prop="no" label="账号" width="120">
</el-table-column>
<el-table-column prop="name" label="姓名" width="80">
</el-table-column>
<el-table-column prop="age" label="年龄" width="80">
</el-table-column>
<el-table-column prop="sex" label="性别" width="80">
<template slot-scope="scope">
<el-tag
:type="scope.row.sex === 1 ?'primary':'success'"
disable-transitions>{{ scope.row.sex === 1 ? '男' : '女' }}
</el-tag>
</template>
</el-table-column>
<el-table-column prop="roleId" label="角色" width="120">
<template slot-scope="scope">
<el-tag
:type="scope.row.roleId === 0 ?'danger':(scope.row.roleId === 1 ?'primary':'success')"
disable-transitions>
{{ scope.row.roleId === 0 ? '超级管理员' : (scope.row.roleId === 1 ? '管理员' : '用户') }}
</el-tag>
</template>
</el-table-column>
<el-table-column prop="phone" label="电话" width="120">
</el-table-column>
<el-table-column prop="operate" label="操作">
<template slot-scope="scope">
<el-button size="small" type="success" @click="mod(scope.row)">编辑</el-button>
<el-button size="small" type="danger" @click="del">删除</el-button>
</template>
</el-table-column>
</el-table>
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="currentPage4"
:page-sizes="[2, 5, 10, 20, 50]"
:page-size="pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="total">
</el-pagination>
<el-dialog
title="提示"
:visible.sync="centerDialogVisible"
width="30%"
center>
<el-form ref="form" :rules="rules" :model="form" label-width="80px">
<el-form-item label="账号" prop="no">
<el-col :span="20">
<el-input v-model="form.no"></el-input>
</el-col>
</el-form-item>
<el-form-item label="密码" prop="password">
<el-col :span="20">
<el-input v-model="form.password"></el-input>
</el-col>
</el-form-item>
<el-form-item label="名字" prop="name">
<el-col :span="20">
<el-input v-model="form.name"></el-input>
</el-col>
</el-form-item>
<el-form-item label="年龄" prop="age">
<el-col :span="20">
<el-input v-model="form.age"></el-input>
</el-col>
</el-form-item>
<el-form-item label="性别">
<el-radio-group v-model="form.sex">
<el-radio label="1">男</el-radio>
<el-radio label="0">女</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="电话" prop="phone">
<el-col :span="20">
<el-input v-model="form.phone"></el-input>
</el-col>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="centerDialogVisible=false">取消</el-button>
<el-button type="primary" @click="save">确定</el-button>
</span>
</el-dialog>
</div>
</template>
<style scoped>
</style>
<script>
export default {
name: "AppMain",/*其实是想改成MainComponent的*/
data() {
let checkAge = (rule, value, callback) => {
if (value > 150) {
callback(new Error('年龄太大!lbd再来我让你飞起来!'));
} else {
callback();
}
};
let checkDuplicate = (rule, value, callback) => {
if (this.form.id) {
return callback();
}
this.$axios.get(this.$httpUrl+"/user/findByNo?no=" + this.form.no).then(res=>res.data).then(res => {
if (res.code!== 200) {//es6解构也可以
callback();
} else {
callback(new Error('账号已经存在'));
}
});
};
return {
tableData: [],
pageSize: 10,
pageNum: 1,
currentPage4: 1, // 新增这一行来初始化 currentPage4 的值
total: 0,
name: '',
sex: '',
sexs: [
{
value: '1',
label: '男'
}, {
value: '0',
label: '女'
}
],
centerDialogVisible: false,
form: {
id:'',
name: '',
no: '',
age: '',
password: '',
phone: '',
sex: '0',
roleId: '2'
},
rules: {
no: [
{required: true, message: '请输入账号', trigger: 'blur'},
{min: 3, max: 8, message: '长度在3-8个字符', trigger: 'blur'},
{validator: checkDuplicate, trigger: 'blur'}
],
name: [
{required: true, message: '请输入名字', trigger: 'blur'},
],
password: [
{required: true, message: '请输入密码', trigger: 'blur'},
{min: 4, max: 10, message: '长度在4-10个字符之间', trigger: 'blur'}
],
age: [
{required: true, message: '请输入年龄', trigger: 'blur'},
{min: 1, max: 3, message: '长度在1到3个位', trigger: 'blur'},
{pattern: /^([1-9][0-9]*){1,3}$/, message: '年龄必须为正整数字', trigger: "blur"},
{validator: checkAge, trigger: 'blur'}
],
phone: [
{required: true, message: "手机号不能为空", trigger: "blur"},
{pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/, message: "请输入正确的手机号码", trigger: "blur"}
]
}
}
},
methods: {
resetForm() {
this.$refs.form.resetFields();
},
del(){
},
mod(row){
//this.form=row就可以了
this.centerDialogVisible = true
this.$nextTick(()=>{
this.form.id=row.id;
this.form.no=row.no;
this.form.name=row.name;
this.form.sex=row.sex+'';
this.form.age=row.age+'';//转化成字符串类型
this.form.phone=row.phone;
this.form.password='';
this.form.roleId=row.roleId;
})//修改User的时候要确保账号不能修改,否则有可能会数据库存在账号相同的情况!!!!给账号的input里加个v-bind:disabled="isDisabled“,如果是修改就把isDisabled设置为true,添加就false
},
add() {
this.centerDialogVisible = true
this.$nextTick(()=>{
this.resetForm()
})
},
doSave(){
this.$axios.post(this.$httpUrl + '/user/save', this.form).then(res => res.data).then(res => {
console.log(res)
if (res.code === 200) {
this.$message({
message: '操作成功!',
type: 'success'
});
this.centerDialogVisible = false
this.loadPost();
this.resetForm()
} else {
this.$message({
message: '操作失败!请返回重新操作...',
type: 'error'
});
}
});
},
doMod(){
this.$axios.post(this.$httpUrl + '/user/update', this.form).then(res => res.data).then(res => {
console.log(res);
if (res.code == 200) {
this.$message({
message: '操作成功!',
type: 'success'
});
this.centerDialogVisible = false;
this.loadPost();
this.resetForm();
} else {
this.$message({
message: '操作失败!',
type: 'error'
});
}
});
},
save() {
this.$refs.form.validate((valid) => {
if (valid) {
if(this.form.id){
this.doMod();
}
else{
this.doSave()
}
} else {
console.log('error submit!!');
return false;
}
});
},
loadGet() {
this.$axios.get(this.$httpUrl + '/user/list').then(res => res.data).then(res => {
console.log(res)
})
},
loadPost() {
this.$axios.post(this.$httpUrl + '/user/listPageC1', {
pageSize: this.pageSize,
pageNum: this.pageNum,
param: {
name: this.name,
sex: this.sex,
}
}).then(res => res.data).then(res => {
console.log(res)
if (res.code === 200) {
this.tableData = res.data
this.total = res.total
} else {
alert('获取数据失败!请刷新页面')
}
})
},
resetParam() {
this.name = ''
this.sex = ''
},
handleSizeChange(val) {
console.log(`每页 ${val} 条`);
this.pageNum = 1//这个错误是先翻到第二页在调页面条数,显示无数据
this.pageSize = val;
this.loadPost();
},
handleCurrentChange(val) {
console.log(`当前页: ${val}`);
this.pageNum = val
this.loadPost();
}
},
beforeMount() {
this.loadPost()
}
}
</script>
UserController.java部分内容
//新增
@PostMapping("/save")
public Result save(@RequestBody User user) {
return userService.save(user)?Result.success():Result.fail();
}
//更新
@PostMapping("/update")
public Result update(@RequestBody User user) {
return userService.updateById(user)?Result.success():Result.fail();
}//修改User的时候要确保账号不能修改,否则有可能会数据库存在账号相同的情况!!!!给账号的input里加个v-bind:disabled="isDisabled“,如果是修改就把isDisabled设置为true,添加就false
//修改
@PostMapping("/mod")
public boolean mod(@RequestBody User user) {
return userService.updateById(user);
}
//新增或修改
@PostMapping("/saveOrMod")
public boolean saveOrMod(@RequestBody User user) {
return userService.saveOrUpdate(user);
}
删除
<el-table-column prop="operate" label="操作">
<template slot-scope="scope">
<el-button size="small" type="success" @click="mod(scope.row)">编辑</el-button>
<el-popconfirm
title="确定删除吗?"
@confirm="del(scope.row.id)"
style="margin-left:8px;"
>
<el-button slot="reference" size="small" type="danger">删除</el-button>
</el-popconfirm>
</template>
</el-table-column>
</el-table>
..............................
..............................
..............................
methods: {
resetForm() {
this.$refs.form.resetFields();
},
del(id){
this.$axios.get(this.$httpUrl + '/user/del?id='+id).then(res => res.data).then(res => {
console.log(res)
if (res.code === 200) {
this.$message({
message: '操作成功!',
type: 'success'
});
this.loadPost();
} else {
this.$message({
message: '操作失败!请返回重新操作...',
type: 'error'
});
}
});
},
mod(row){
//this.form=row就可以了
this.centerDialogVisible = true
this.$nextTick(()=>{
this.form.id=row.id;
this.form.no=row.no;
this.form.name=row.name;
this.form.sex=row.sex+'';
this.form.age=row.age+'';//转化成字符串类型
this.form.phone=row.phone;
this.form.password='';
this.form.roleId=row.roleId;
})//修改User的时候要确保账号不能修改,否则有可能会数据库存在账号相同的情况!!!!给账号的input里加个v-bind:disabled="isDisabled“,如果是修改就把isDisabled设置为true,添加就false
},
//删除
@GetMapping("/del")
public Result del(@RequestParam String id) {
return userService.removeById(id)?Result.success():Result.fail();
}