当前位置: 首页 > news >正文

非常简单实用的前后端分离项目-仓库管理系统(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>
  1.  白屏是因为外层需要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.isCollapseif(!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-menubackground-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{@overridepublic 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 {@Overridepublic 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 或 POSTif (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.datathis.total=res.total}else{alert('获取数据失败!请刷新页面')}})},handleSizeChange(val) {console.log(`每页 ${val} 条`);this.pageNum=1//这个错误是先翻到第二页在调页面条数,显示无数据this.pageSize=valthis.loadPost()},handleCurrentChange(val) {console.log(`当前页: ${val}`);this.pageNum=valthis.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-optionv-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-optionv-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-optionv-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-dialogtitle="提示":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-optionv-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-dialogtitle="提示":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 = truethis.$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 = falsethis.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.datathis.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 = valthis.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-optionv-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-dialogtitle="提示":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 = truethis.$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 = truethis.$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 = falsethis.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.datathis.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 = valthis.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-popconfirmtitle="确定删除吗?"@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 = truethis.$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();}

相关文章:

非常简单实用的前后端分离项目-仓库管理系统(Springboot+Vue)part 2

七、创建前端项目 你下载了nodejs吗&#xff1f;从cn官网下载&#xff1a;http://nodejs.cn/download/&#xff0c;或者从一个国外org网站下载&#xff0c;选择自己想要的版本https://nodejs.org/download/release/&#xff0c;双击下载好的安装文件&#xff0c;选择安装路径安…...

开源 AI 智能名片 2 + 1 链动模式 S2B2C 商城小程序源码助力品牌共建:价值、策略与实践

摘要&#xff1a;在当今数字化商业环境下&#xff0c;品牌构建已演变为企业与消费者深度共建的过程。本文聚焦于“开源 AI 智能名片 2 1 链动模式 S2B2C 商城小程序源码”&#xff0c;探讨其如何融入品牌建设&#xff0c;通过剖析品牌价值构成&#xff0c;阐述该技术工具在助力…...

微信小程序中的WXSS与CSS的关系及使用技巧

微信小程序中的WXSS与CSS的关系及使用技巧 引言 在微信小程序的开发中,样式的设计与实现是构建用户友好界面的关键。微信小程序使用WXSS(WeiXin Style Sheets)作为其样式表语言,WXSS在语法上与CSS非常相似,但也有一些独特的特性。本文将深入探讨WXSS与CSS的关系,介绍WX…...

STM32的CAN波特率计算

公式&#xff1a; CAN波特率 APB总线频率 / &#xff08;BRP分频器 1&#xff09;/ (SWJ BS1 BS2) SWJ一般为1。 例如STM32F407的&#xff0c;CAN1和CAN2都在在APB1下&#xff0c;频率是42000000 如果想配置成1M波特率&#xff0c;则计算公式为&#xff1a;...

【LeetCode面试150】——57插入区间

博客昵称&#xff1a;沈小农学编程 作者简介&#xff1a;一名在读硕士&#xff0c;定期更新相关算法面试题&#xff0c;欢迎关注小弟&#xff01; PS&#xff1a;哈喽&#xff01;各位CSDN的uu们&#xff0c;我是你的小弟沈小农&#xff0c;希望我的文章能帮助到你。欢迎大家在…...

活着就好20241128

早晨问候&#xff1a; 亲爱的朋友们&#xff0c;大家早上好&#xff01;今天是2024年11月28日&#xff0c;第48周的第四天&#xff0c;也是十一月的第二十八天&#xff0c;农历甲辰[龙]年十月廿四。在这个即将步入月末、阳光依旧明媚的清晨&#xff0c;愿第一缕阳光轻轻洒落在…...

【kafka03】消息队列与微服务之Kafka 读写数据

Kafka 读写数据 参考文档 Apache Kafka 常见命令 kafka-topics.sh #消息的管理命令 kafka-console-producer.sh #生产者的模拟命令 kafka-console-consumer.sh #消费者的模拟命令 创建 Topic 创建topic名为 chen&#xff0c;partitions(分区)为3&#xff0…...

【Agorversev1.1数据转换】Agorverse高清地图转OpenStreetMap及SUMO路网

文章目录 Agorverse高清地图转OpenStreetMap及SUMO路网1. Agorverse osm转换说明2. 转换源码3. 处理效果4. SUMO-Carla联合仿真 Agorverse高清地图转OpenStreetMap及SUMO路网 1. Agorverse osm转换说明 根据作者的描述&#xff0c;其高清地图的osm文件与标准osm的区别在于以下…...

Vue 3 实现高性能拖拽指令的最佳实践

前言 在现代前端开发中&#xff0c;拖拽功能是增强用户体验的重要手段之一。本文将详细介绍如何在 Vue 3 中封装一个拖拽指令&#xff08;v-draggable&#xff09;&#xff0c;并通过实战例子演示其实现过程。通过这篇教程&#xff0c;您将不仅掌握基础的拖拽功能&#xff0c;…...

AIGC--------AIGC在医疗健康领域的潜力

AIGC在医疗健康领域的潜力 引言 AIGC&#xff08;Artificial Intelligence Generated Content&#xff0c;人工智能生成内容&#xff09;是一种通过深度学习和自然语言处理&#xff08;NLP&#xff09;等技术生成内容的方式。近年来&#xff0c;AIGC在医疗健康领域展现出了极…...

Apache Calcite - calcite jdbc驱动使用场景

前言 在使用Calcite查询数据时通常会用到这些代码获取schema Connection connection DriverManager.getConnection("jdbc:calcite:", info); CalciteConnection calciteConnection connection.unwrap(CalciteConnection.class); SchemaPlus rootSchema calciteC…...

IEC61850实现方案和测试-4-MMS协议

IEC61850实现方案和测试-4作为介绍实现方案和测试的第四篇文章&#xff0c;后续会继续更新&#xff0c;欢迎关注。前三篇如下 第一篇是&#xff1a;IEC61850实现方案和测试-1-CSDN博客 第二篇是&#xff1a;IEC61850实现方案和测试-2-UCA-CSDN博客 第三篇是&#xff1a;IEC6…...

【ubuntu24.04】GTX4700 配置安装cuda

筛选显卡驱动显卡驱动 NVIDIA-Linux-x86_64-550.135.run 而后重启:最新的是12.6 用于ubuntu24.04 ,但是我的4700的显卡驱动要求12.4 cuda...

时间的礼物:如何珍视每一刻

《时间的礼物&#xff1a;如何珍视每一刻》 夫时间者&#xff0c;宇宙之精髓&#xff0c;生命之经纬&#xff0c;悄无声息而流转不息&#xff0c;如织锦之细线&#xff0c;串联古今&#xff0c;贯穿万物。 人生短暂&#xff0c;犹如白驹过隙&#xff0c;倏忽而逝&#xff0c;…...

componentReceivePropsreact class生命周期

componentReceiveProps并不是有props的变化触发&#xff0c;而是由父组件的更新触发的 父组件导致组件重新渲染&#xff0c;即使props没有更改&#xff0c;也会调用componentReceiveProps这个方法&#xff1b;如果只想处理更改&#xff0c;确保当前值与变更值比较--官方 …...

快速理解微服务中Sentinel怎么实现限流

Sentinel是通过动态管理限流规则&#xff0c;根据定义的规则对请求进行限流控制。 一.实现步骤 1.定义资源&#xff1a;在Sentinel中&#xff0c;资源可以是URL、方法等&#xff0c;用于标识需要进行限流的请求&#xff1b;(在Sentinel中&#xff0c;需要我们去告诉Sentinel哪些…...

25.100ASK_T113-PRO 测试摄像头(型号)

1.摄像头 USB2.0 摄像头,支持 UVC协议, 就是V4L2 USB2.0 大概可这样理解吧.这个是2K分辨率. 2.8mm焦距. 开发板还是 100ASK_T113-PRO V1.2版 2.查看摄像头驱动挂载情况 这样接好. 看看设备有没有挂载上 # ls /dev/video* /dev/video0 /dev/video1 这两个就是USB摄像头.说…...

20241127 给typecho文章编辑附件 添加视频 图片预览

Typecho在写文章时&#xff0c;如果一次性上传太多张图片可能分不清哪张&#xff0c;因为附件没有略缩图&#xff0c;无法实时阅览图片&#xff0c;给文章插入图片时很不方便。 编辑admin/file-upload.php 大约十八行的位置 一个while 循环里面,这是在进行html元素更新操作,在合…...

StarRocks-join优化

1、背景 有两个大表&#xff0c;都是6kw级别上下的&#xff0c;通过SR然后包装了一个接口对外提供查询&#xff0c;当前的问题是&#xff0c;这样大的join查询会导致BE直接宕机。并且这个sql很有代表性&#xff0c;我截图如下&#xff1a; 这个表是个单分区&#xff0c;所以直接…...

如何通过ChatGPT提高自己的编程水平

在编程学习的过程中&#xff0c;开发者往往会遇到各种各样的技术难题和学习瓶颈。传统的学习方法依赖书籍、教程、视频等&#xff0c;但随着技术的不断发展&#xff0c;AI助手的崛起为编程学习带来了全新的机遇。ChatGPT&#xff0c;作为一种强大的自然语言处理工具&#xff0c…...

实时数据开发 | checkpoints监控和调优

监控Checkpoints 监控 checkpoint 行为最简单的方法是通过 UI 的 checkpoint 部分。 监控这两个指标: 算子收到第一个 checkpoint barrier 的时间。当触发 checkpoint 的耗费时间一直很高时&#xff0c;这意味着 checkpoint barrier 需要很长时间才能从 source 到达 operator…...

面试手撕题积累

1、实现滑动窗口限流&#xff0c;允许每分钟最多有100个请求 阿里一面题。 核心&#xff1a; 时间窗口管理&#xff1a;滑动窗口会根据时间流逝不断更新&#xff0c;需要记录请求的时间戳&#xff0c;并根据当前时间计算窗口内的请求数量。 限流判断&#xff1a;每次请求到来…...

开发中使用UML的流程_05 PIM-1:分析系统流程

目录 1、概述 2、PIM生成的过程 3、用例叙述格式 4、用例关系 5、执行流程&#xff1a; 6、惯用的编号方式 1、概述 在进入到PIM阶段之后&#xff0c;系统分析员将所有系统用例依相关性分成若干组&#xff0c;以组别方式生成该组系统用例涉及的PIM-1---PIM-4产生结果&am…...

【Go】-go中的锁机制

目录 一、锁的基础知识 1. 互斥量/互斥锁 2. CAS&#xff08;compare and swap&#xff09; 3. 自旋锁 4. 读写锁 5. 乐观锁 & 悲观锁 6. 死锁 二、go中锁机制 1. Mutex-互斥锁 2. RWMutex-读写锁 2.1 RWMutex流程概览 2.2 写锁饥饿问题 2.3. golang的读写锁源…...

Scala学习记录,全文单词统计

package test32 import java.io.PrintWriter import scala.io.Source //知识点 // 字符串.split("分隔符"&#xff1a;把字符串用指定的分隔符&#xff0c;拆分成多个部分&#xff0c;保存在数组中) object test {def main(args: Array[String]): Unit {//从文件1.t…...

重构项目架构

前言 我们上篇文章对整个项目进行一个整体的规划&#xff0c;其中对于APP类规划了类&#xff0c;本篇文章我们就来实现这个规划&#xff1b; class App {//加载页面constructor() {}//获取位置_getPosition() {}//接受位置_loadMap() {}//在地图上点击展现表单_showForm() {}/…...

一个开源轻量级的服务器资源监控平台,支持告警推送

大家好&#xff0c;今天给大家分享一款开源的轻量级服务器资源监控工具Beszel&#xff0c;提供历史数据记录、Docker容器统计信息监控以及多种警报功能&#xff0c;用于监控服务器资源。 项目介绍 Beszel由hub&#xff08;中心服务器端应用&#xff0c;基于PocketBase构建&…...

介绍一下atof(arr);(c基础)

hi , I am 36 适合对象c语言初学者 atof(arr)&#xff1b;是返回浮点数(double型)&#xff0c;浮点数数是arr数组中字符中数字 格式 #include<stdio.h> atof(arr); 返回值arr数组中的数 未改变arr数组 #include<stdio.h> //atof(arr) 返 <stdlib> int…...

基于微信小程序的平价药房管理系统+LW参考示例

1.项目介绍 系统角色&#xff1a;管理员、医生、普通用户功能模块&#xff1a;用户管理、医生管理、药品分类管理、药品信息管理、在线问诊管理、生活常识管理、日常提醒管理、过期处理、订单管理等技术选型&#xff1a;SpringBoot&#xff0c;Vue&#xff0c;uniapp等测试环境…...

什么是 C++ 中的函数对象?它有什么特点?如何定义和使用函数对象?数对象与普通函数有什么区别?

在 C 中&#xff0c;函数对象&#xff08;Function Object&#xff09;也被称为仿函数&#xff08;Functor&#xff09;&#xff0c;是一种可以像函数一样被调用的对象&#xff0c;是一个类的对象&#xff0c;该类重载了函数调用运算符operator()。 函数对象的特点: 与普通函数…...

JAVA篇05 —— 内部类(Local、Anonymous、Member、Static)

欢迎来到我的主页&#xff1a;【一只认真写代码的程序猿】 本篇文章收录于专栏【小小爪哇】 如果这篇文章对你有帮助&#xff0c;希望点赞收藏加关注啦~ 目录 1 内部类Inner Class 1.1 局部内部类 1.2 匿名内部类&#xff08;※※&#xff09; 1.3 匿名类最佳实践&#xf…...

vmware安装ubuntu22.04 复制黏贴 上网

1、ubuntu下载 [Download - 清华镜像站]&#xff1a; 点击 清华大学开源软件镜像站 - Ubuntu 22.04.4 下载 页面中的 ubuntu-22.04.4-desktop-amd64.iso清华大学开源软件镜像站 - Ubuntu 22.04.4 下载 2、安装向导 3、网络设置 sudo netplan try sudo netplan apply4、复制…...

Spring Bean初始化流程

首先&#xff1a; 加载Bean定义(Configuration) 然后对于每个Bean&#xff1a; 1、实例化Bean&#xff08;应该是从Bean方法中获取&#xff0c;Bean方法里面包含new这个类型的代码&#xff09;2、依赖注入&#xff08;所依赖的Bean要经历相同的流程&#xff09;、调用Setter…...

C 语言函数递归探秘:从基础概念到复杂问题求解的进阶之路

我的个人主页 我的专栏&#xff1a;C语言&#xff0c;希望能帮助到大家&#xff01;&#xff01;&#xff01;点赞❤ 收藏❤ 目录 什么是函数递归递归的基本组成递归的工作原理递归的优缺点递归的经典案例 5.1 阶乘计算5.2 斐波那契数列5.3 汉诺塔问题5.4 二分查找 递归的高级…...

【Zookeeper】三,Zookeeper的安装与基本操作

文章目录 安装Zookeeper下载解压解压后的目录结构运行Zookeeper 基本操作 安装Zookeeper 下载 官网下载Zookeeper&#xff0c;会得到一个tar包&#xff0c;如&#xff1a;apache-zookeeper-3.8.4-bin.tar.gz 解压 tar -xvf apache-zookeeper-3.8.4-bin.tar.gz -C /usr/loca…...

STL算法之数值算法<stl_numeric.h>

这一节介绍的算法&#xff0c;统称为数值(numeric)算法。STL规定&#xff0c;欲使用它们&#xff0c;客户端必须包含头文件<numeric>.SGI将它们实现与<stl_numeric.h>文件中。 目录 运用实例 accumulate adjacent_difference inner_product partial_sum pow…...

Git 入门超简单指南

1. 什么是 Git&#xff1f; Git 是一个分布式版本控制系统&#xff0c;由 Linus Torvalds 于 2005 年创建。它的主要目的是帮助开发者有效地管理和跟踪项目的历史版本。通过使用 Git&#xff0c;你可以轻松地记录每一次代码的修改&#xff0c;回滚到以前的版本&#xff0c;以及…...

UE5 和 UE4 中常用的控制台命令总结

调用控制台 按下键盘上的 ~ 键可以调用控制台命令。 技巧 使用键盘的 ↑ 键可以查看之前输入过的指令。控制台指令并不需要打全名&#xff0c;输入空格后跟随指令的部分字符可以进行模糊搜索。按下 Ctrl Shift , 打开 GPUProfile 面板。 命令如下&#xff1a; 调试类 s…...

[护网杯 2018]easy_tornado

这里有一个hint点进去看看&#xff0c;他说md5(cookie_secretmd5(filename))&#xff0c;所以我们需要获得cookie_secret的value 根据题目tornado,它可能是tornado的SSTI 这里吧filehash改为NULL. 是tornado的SSTI 输入{{handler.settings}} (settings 属性是一个字典&am…...

论 ONLYOFFICE:开源办公套件的深度探索

公主请阅 引言第一部分&#xff1a;ONLYOFFICE 的历史背景1.1 开源软件的崛起1.2 ONLYOFFICE 的发展历程 第二部分&#xff1a;ONLYOFFICE 的核心功能2.1 文档处理2.2 电子表格2.3 演示文稿 第三部分&#xff1a;技术架构与兼容性3.1 技术架构3.2 兼容性 第四部分&#xff1a;部…...

华为OD机试真题---幼儿园篮球游戏

华为OD机试真题中的“幼儿园篮球游戏”是一道有趣的逻辑模拟题。以下是该题目的详细描述及解题思路&#xff1a; 题目描述 幼儿园里有一个放倒的圆桶&#xff0c;它是一个线性结构。允许在桶的右边将篮球放入&#xff0c;可以在桶的左边和右边将篮球取出。每个篮球有单独的编…...

C#基础控制台程序

11.有一个54的矩阵&#xff0c;要求编程序求出其中值最大的那个元素的值&#xff0c;以及其所在的行号和列号。 12.从键盘输入一行字符&#xff0c;统计其中有多少个单词&#xff0c;单词之间用空格分隔开。 13.输入一个数&#xff0c;判断它是奇数还是偶数&#xff0c;如果…...

CASS插入多行文字

问题描述 有时在DWG文件中需要标注多行文字&#xff0c;文字注记只是单行的。 解决办法 工具栏中选择文字——>写文字。快捷键是 MTEXT 可以自行换行&#xff0c;并设置相关格式。 当需要把多行文字转换成单行文字的时候&#xff0c;使用下列功能。可以将多行文字变成…...

【青牛科技】D1671 75Ω 带4级低通滤波的单通道视频放大电 路芯片介绍

概 述 &#xff1a; D1671是 一 块 带 4级 低 通 滤 波 的 单 通 道 视 频 放 大 电 路 &#xff0c; 可 在3V或5V的 低 电 压 下 工 作 。 该 电 路 用 在 有 TV影 象 输 出 功 能 的 产 品 上 面&#xff0c;比如 机 顶 盒 &#xff0c;监 控 摄 象 头 &#xff0c;DVD&#…...

基于stm32的智能教室管理系统/智能家居系统

基于stm32的智能教室管理系统/智能家居系统 持续更新&#xff0c;欢迎关注!!! ** 基于stm32的智能教室管理系统/智能家居系统 ** 目前&#xff0c;物联网已广泛应用在我们的生活中。智慧校园是将校园中的生活、学习、工作等相关的资源联系在一起&#xff0c;实现管理的智能化…...

3.10 内核 BUG_ON() at xfs_vm_writepage() -> page_buffers()

目录 前言 问题分析 page buffers创建 page buffers丢失 Write-Protect Dirty Page w/o Buffers 问题解决 前言 这个问题发生在3.10.0-514.el7上&#xff0c;并且在RHEL的知识库中快速找到了对应的案例以及解决方案&#xff0c;但是&#xff0c;理解问题如何发生和解决…...

理解Java集合的基本用法—Collection:List、Set 和 Queue,Map

本博文部分参考 博客 &#xff0c;强烈推荐这篇博客&#xff0c;写得超级全面&#xff01;&#xff01;&#xff01; 图片来源 Java 集合框架 主要包括两种类型的容器&#xff0c;一种是集合&#xff08;Collection&#xff09;&#xff0c;存储一个元素集合&#xff08;单列…...

SQL for XML

关系数据模型与SQL SQL for XML 模式名功能RAW返回的行作为元素&#xff0c;列值作为元素的属性AUTO返回表名对应节点名称的元素&#xff0c;每列的属性作为元素的属性输出输出&#xff0c;可形成简单嵌套结构EXPLICIT通过SELECT语法定义输出XML结构PATH列名或列别名作为XPAT…...

RabbitMQ 篇-深入了解延迟消息、MQ 可靠性(生产者可靠性、MQ 可靠性、消费者可靠性)

??博客主页&#xff1a;【_-CSDN博客】** 感谢大家点赞??收藏评论** 文章目录 ???1.0 RabbitMQ 的可靠性 ? ? ? ? 2.0 发送者的可靠性 ? ? ? ? 2.1 生产者重试机制 ? ? ? ? 2.2 生产者确认机制 ? ? ? ? 2.2.1 开启生产者确认机制 ? ? ? ? 2.2…...

Java设计模式 —— 【创建型模式】原型模式(浅拷贝、深拷贝)详解

文章目录 前言原型模式一、浅拷贝1、案例2、引用数据类型 二、深拷贝1、重写clone()方法2、序列化 总结 前言 先看一下传统的对象克隆方式&#xff1a; 原型类&#xff1a; public class Student {private String name;public Student(String name) {this.name name;}publi…...