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

news2024/11/28 16:05:11

  七、创建前端项目

  你下载了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.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();
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2249172.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

应急响应靶机——Windows近源攻击

载入虚拟机&#xff0c;开启虚拟机&#xff0c;点击“解题.exe”&#xff1a; &#xff08;账户密码&#xff1a;Administrator/zgsf2024&#xff09; 1、攻击者的外网IP地址 2、攻击者的内网跳板IP地址 3、攻击者使用的限速软件的md5大写 4、攻击者的后门md5大写 5、攻击…

用两个栈实现队列 剑指offer

题目描述 用两个栈实现一个队列。队列声明如下图&#xff0c;请实现它的两个函数appendTail和deleteHead,分别完成在队尾插入节点和队头删除节点的功能。 代码实现 测试用例 相关题目

超详细ensp配置VRRP和MSTP协议

一、简介 1、什么是VRRP&#xff1a; &#xff08;1&#xff09;VRRP&#xff08;Virtual Router Redundancy Protocol&#xff09;的概念&#xff1a; VRRP&#xff08;Virtual Router Redundancy Protocol&#xff09;指的是一种实现路由器冗余备份的协议&#xff0c;常用于…

嵌入式Linux开发4——文件类型2

目录 使用stat查明文件类型 stat 命令 stat() 系统调用 struct stat 结构体 常见字段和它们的含义 fstat 函数 示例&#xff1a; lstat 函数 区别总结 使用场景 stat、fstat 和 lstat 比较 链接 硬链接 硬链接的特性 创建硬链接 硬链接的优缺点 符号链接&#…

模电期末笔记 (包过版)

文章目录 一、直流电路公式题型一&#xff1a;电压源与电流源求电压&#xff0c;电流&#xff0c;功率题型二&#xff1a;基尔霍夫定律求电压&#xff0c;电流题型三: 理想电源的等效变换题型四&#xff1a;求复杂电路的电压&#xff0c;电流&#xff0c;电功率**题型五&#x…

C# 常量

文章目录 前言一、整数常量&#xff08;一&#xff09;合法与非法实例对比&#xff08;二&#xff09;不同进制及类型示例 二、浮点常量三、字符常量四、字符串常量五、定义常量 前言 在 C# 编程的世界里&#xff0c;常量是一类特殊的数据元素&#xff0c;它们如同程序中的 “定…

C++11新增的特性

一.列表初始化/{}初始化 回顾&#xff1a;C98中⼀般数组和结构体可以⽤{}进⾏初始化。 1.C11中&#xff0c;一切对象皆可用{}初始化&#xff0c;内置类型⽀持&#xff0c;⾃定义类型也⽀持&#xff08;⾃定义类型本质是类型转换&#xff0c;中间会产⽣临时对象&#xff0c;最…

SAP学习

1、概述 2、SD 2.1 销售中的企业结构 2.2流程概览

Linux之网络基础

网络发展 网络的发展可以从人与人之间的工作模式开始谈起, 人与人的工作模式反应了机器与机器的工作模式: 1. 独立模式: 在网络发展的早期计算机间处于独立模式, 计算机之间相互独立 最开始计算机之间是独立运行的, 数据之间的交互需要人用软盘等存储介质拷贝过去, 一般涉及…

数字图像处理(9):VGA接口及其时序

&#xff08;1&#xff09;特点&#xff1a;成本低、结构简单、应用灵活 VGA接口需要五个信号&#xff1a;R、G、B、Hsync、Vsync &#xff08;2&#xff09;VGA的工作原理&#xff1a; 设定一个高速时钟信号&#xff08;像素时钟&#xff09;来控制每个像素的传输速率&#…

111. UE5 GAS RPG 实现角色技能和场景状态保存到存档

实现角色的技能存档保存和加载 首先&#xff0c;我们在LoadScreenSaveGame.h文件里&#xff0c;增加一个结构体&#xff0c;用于存储技能相关的所有信息 //存储技能的相关信息结构体 USTRUCT(BlueprintType) struct FSavedAbility {GENERATED_BODY()//需要存储的技能UPROPERT…

【jmeter】服务器使用jmeter压力测试(从安装到简单压测示例)

一、服务器上安装jmeter 1、官方下载地址&#xff0c;https://jmeter.apache.org/download_jmeter.cgi 2、服务器上用wget下载 # 更新系统 sudo yum update -y# 安装 wget 以便下载 JMeter sudo yum install wget -y# 下载 JMeter 压缩包&#xff08;使用 JMeter 官方网站的最…

图像算法在生物医药领域的应用

摘要&#xff1a; 随着科技的飞速发展&#xff0c;图像算法在生物医药领域的应用日益广泛且深入。本文详细阐述了图像算法在生物医药多个方面的应用&#xff0c;包括医学影像诊断、病理图像分析、药物研发、细胞图像研究以及生物医学工程等。通过对这些应用的探讨&#xff0c;展…

注意力(Attention)机制详解(附代码)

Attention机制是深度学习中的一种技术&#xff0c;特别是在自然语言处理&#xff08;NLP&#xff09;和计算机视觉领域中得到了广泛的应用。它的核心思想是模仿人类的注意力机制&#xff0c;即人类在处理信息时会集中注意力在某些关键部分上&#xff0c;而忽略其他不那么重要的…

Jmeter测试nginx部署的静态网页最大在线人数

一、下载Jmeter apache-jmeter-5.4.3.tar资源-CSDN文库 解压之后&#xff0c;双击ApacheJMeter.jar,即可打开 二、测试最大在线人数 1、plugins-manager下载安装 起初刚解压的jmeter里面没有插件管理这个选项 去官网下载&#xff1a;Install :: JMeter-Plugins.org 将下载j…

【深度学习|目标跟踪】StrongSort 详解(以及StrongSort++)

StrongSort详解 1、论文及源码2、DeepSort回顾3、StrongSort的EMA4、StrongSort的NSA Kalman5、StrongSort的MC6、StrongSort的BOT特征提取器7、StrongSort的AFLink8、未完待续 1、论文及源码 论文地址&#xff1a;https://arxiv.org/pdf/2202.13514 源码地址&#xff1a;https…

Scala关于成绩的常规操作

score.txt中的数据&#xff1a; 姓名&#xff0c;语文&#xff0c;数学&#xff0c;英语 张伟&#xff0c;87&#xff0c;92&#xff0c;88 李娜&#xff0c;90&#xff0c;85&#xff0c;95 王强&#xff0c;78&#xff0c;90&#xff0c;82 赵敏&#xff0c;92&#xff0c;8…

OpenAI Whisper 语音识别 模型部署及接口封装

环境配置: 一、安装依赖&#xff1a; pip install -U openai-whisper 或者&#xff0c;以下命令会从这个存储库拉取并安装最新的提交&#xff0c;以及其Python依赖项&#xff1a; pip install githttps://github.com/openai/whisper.git 二、安装ffmpeg&#xff1a; cd …

草图大师2020安装教程附安装包下载

软件介绍 草图大师&#xff08;Sketchup&#xff09;是由谷歌公司推出的一款环保型3D建模软件。草图大师可以快速和方便地创建、观察和修改三维创意&#xff0c;具有沿路径放样、导入的2D物体可随视角转动、布尔运算等功能。传统铅笔草图的优雅自如&#xff0c;现代数字科技的…

野火直播 5.7.5x | 频道丰富,有国外频道,部分支持回看

野火直播是一款专为电视盒子设计的电视直播软件&#xff0c;提供海量的电视直播资源和丰富的内容选择。涵盖全球多地的电视台直播源&#xff0c;包括央视、卫视、地方台、海外台等上千个电视频道。软件界面简洁&#xff0c;操作便捷&#xff0c;支持高清流畅播放&#xff0c;并…