mockjs模拟数据 - 首页导航-左侧菜单-绑定菜单-显示数据分页crud

目录

1.mockjs模拟数据 - 首页导航-左侧菜单

1. mockjs

1.1 mockjs介绍

1.2 mockjs使用步骤

1.2.1 安装mockjs依赖

1.2.2 在项目中引入mockjs

1.2.3 创建目录和文件

1.2.4 为每个组件准备模拟数据

1.2.5 测试

1.2.6 前端调试

1.2.7 mockjs生成随机响应数据

1.2.8 根据不同响应,给出不同提示

2. 路由跳转方式

3. 系统首页

3.1 Main.vue

3.2 配置路由

3.4 编辑登录组件

3.6 实现左侧栏折叠效果

2.动态树 - 数据绑定实现crud

1. 准备工作

2. 动态树

2.1 在配置请求路径

2.2 使用动态数据构建导航菜单

2.2.1 通过接口获取数据

2.2.3 通过后台获取的数据构建菜单导航

2.3 点击菜单实现路由跳转

2.3.1 创建书本管理组件

2.3.2 配置路由

2.3.3 修改LeftAside组件

2.3.4 修改Main组件

3. 系统首页配置

4. 表格数据显示实现crud

4.1 页面布局

4.2 查询并在表格中显示数据


1.mockjs模拟数据 - 首页导航-左侧菜单

1. mockjs

1.1 mockjs介绍

Mock.js是一个模拟数据的生成器,用来帮助前端调试开发、进行前后端的原型分离以及用来提高自动化测试效率。众所周知Mock.js因为两个重要的特性风靡前端:

  • 数据类型丰富 支持生成随机的文本、数字、布尔值、日期、邮箱、链接、图片、颜色等。

  • 拦截Ajax请求 不需要修改既有代码,就可以拦截Ajax请求,返回模拟的响应数据。

官网

注:easy-mock,一个在线模拟后台的数据平台

1.2 mockjs使用步骤

1.2.1 安装mockjs依赖

# -D表示只在开发环境中使用
npm install mockjs -D

1.2.2 在项目中引入mockjs

为了只在开发环境使用mock,而打包到生产环境时自动不使用mock,我们可以在env中做一个配置。 在config目录里面有两个配置文件,分别是dev.env.js(开发环境),prod.env.js(生产环境)。 开发环境配置如下:config目录中的dev.env.js

module.exports = merge(prodEnv, {
  NODE_ENV: '"development"',
  //增加配置
  MOCK:'true'
})

生产环境配置如下:config目录中的prod.env.js

module.exports = {
  NODE_ENV: '"production"',
  //新增mockjs配置
  MOCK:'false'
}

修改main.js:

import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
​
//开发环境下才会引入mockjs,新增
//import是ES6标准中的模块化解决方案,require是node中遵循CommonJS规范的模块化解决方案
//后者支持动态引入,也就是require(${path}/xx.js)
process.env.MOCK && require('@/mock')
......

注意:import是ES6标准中的模块化解决方案,require是node中遵循CommonJS规范的模块化解决方案,后者支持动态引入,也就是require(${path}/xx.js)

1.2.3 创建目录和文件

1) 在src目录下创建mock目录,定义mock主文件index.js,并在该文件中定义拦截路由配置,/src/mock/index.js。 index.js内容如下:

//引入mockjs,npm已安装
import Mock from 'mockjs'
​
//引入封装的请求地址
import action from '@/api/action'
​
//全局设置:设置所有ajax请求的超时时间,模拟网络传输耗时
Mock.setup({
  //延时400s请求到数据
  // timeout: 400
  //延时200-400s请求到数据
  timeout: 200 - 400
})

1.2.4 为每个组件准备模拟数据

为每个组件(*.vue)准备模拟数据。然后导入到mock/index.js中

在mock/index.js中导入,设置请求url,模拟发送数据

。。。。。。
//将模拟数据导入到这里。
import loginData from '@/mock/json/login-mock.js'
​
//获取请求的url
let url = action.getFullPath("SYSTEM_USER_DOLOGIN");
​
//通过mockjs模拟发送请求
//url  请求url
//post 请求方式
//loginData  模拟数据
//mockjs会拦截发送的请求,并使用模拟数据充当真实返回的响应数据
//Mock.mock(url, "post", loginData);
​
//如果请求既可以是get又可以是post的请求方式可以使用如下方式:
Mock.mock(url, /post|get/i, loginData);

设置模拟数据,编辑login-mock.js

//为增加可读性loginData与mack/index.js中导入的名称对应
const loginData = {
  "success": true,
  "msg": "密码正确"
}
​
//将当前模块导出,导出后index.js才可以导入
export default loginData

1.2.5 测试

启动nodejs服务,关闭后台服务,测试登录。现在已经可以通过mockjs进行模拟数据测试了。

在mock/index.js中设置的mock请求,既可以是post可以是get方式的,如果要测试get请求方式,可以将Login.vue中的发送请求部分修改为get方式。

//修改url的获取方式,url已经配置在了action.js中
//post请求方式
/* let url = this.axios.urls.SYSTEM_USER_DOLOGIN;
this.axios.post(url, params).then(resp => {
  console.log(resp);
}).catch(resp => {}); */
​
//get请求方式,注意:与post请求不同的是参数的设置方式
let url = this.axios.urls.SYSTEM_USER_DOLOGIN;
this.axios.post(url, {params: params}).then(resp => {
  console.log(resp);
}).catch(resp => {});

注意:使用mockjs进行前端测试时,前提示要和后台开发人员定义好接口,否则测试没有意义。

1.2.6 前端调试

修改mock/index.js文件中的配置: 打断点然后运行打开浏览器的调式工具 f12

//如果请求既可以是get又可以是post的请求方式可以使用如下方式:
//Mock.mock(url, /post|get/i, loginData);

//前端调试模式
Mock.mock(url, /post|get/i, (options) => {
  // 最佳实践,
  debugger;
  return Mock.mock(loginData);
});

修改后点击提交,在打开开发者工具的前提下,会进入调试模式。

1.2.7 mockjs生成随机响应数据

编辑login-mock.js文件:

//静态响应
/* const loginData = {
  "success": true,
  "msg": "密码正确"
} */

//随机响应
const loginData = {
  //1表示50%概率
  "success|1": true,
  //2-3指重复2到3次
  "msg|2-3": "msg"
}

1.2.8 根据不同响应,给出不同提示

编辑Login.vue文件

//get请求方式
let url = this.axios.urls.SYSTEM_USER_DOLOGIN;
this.axios.post(url, {
  params: params
}).then(resp => {

  //提示成功和失败,主要演示获取响应数据的方法
  if (resp.data.success) {
    //可以到element-ui官网查看用法
    this.$message({
      message: '登录成功',
      type: 'success'
    });
  }else{
    this.$message({
      message: '登录失败',
      type: 'error'
    });
    
  }

  console.log(resp);
}).catch(resp => {});

2. 路由跳转方式

通过路由跳转,常用方式

  • 字符串: this.$router.push('/home/first')

  • 对象: this.$router.push({ path: '/home/first' })

  • 命名的路由: this.$router.push({ name: 'home', params: { userId: wise }}) params为传递的参数

this.$router.push、replace、go的区别

this.router.push(): 跳转到不同的url,这个方法会向history栈添加一个记录,点击后退会返回到上一个页面 this.router.replace() : 同样是跳转到指定的url,但是这个方法不会向history里面添加新的记录,点击返回,会跳转到上上一个页面。上一个记录是不存在的。 this.$router.go(n):相对于当前页面向前或向后跳转多少个页面,类似 window.history.go(n)。n可为正数可为负数。负数返回上一个页面

3. 系统首页

3.1 Main.vue

<template>
  <el-container class="main-container">
    <!-- 侧边栏有折叠效果,通过class控制折叠还是显示的效果 -->
    <el-aside  v-bind:class="asideClass">
      <LeftAside ></LeftAside>
    </el-aside>
    <el-container>
      <el-header class="main-header">
        <!--  @left-state="leftSate"  -->
        <TopNav></TopNav>
      </el-header>
      <el-main class="main-center">
        <router-view />
      </el-main>
    </el-container>
  </el-container>
</template>

<script>
// 导入组件
import TopNav from "@/components/TopNav.vue";
import LeftAside from "@/components/LeftAside.vue";


// 导出模块
export default {
  //组件名称
  name: "Main",

  data: function () {
    return {
      //asideClass: "main-aside",
      openState: null,
    };
  },

  //将import的组件定义的Main中以便于使用
  components: {
    TopNav,
    LeftAside,
  },
  methods: {
    
  }
};
</script>
<style scoped>
.main-container {
  height: 100%;
  width: 100%;
  box-sizing: border-box;
}

.main-aside-collapsed {
  /* 在CSS中,通过对某一样式声明! important ,可以更改默认的CSS样式优先级规则,使该条样式属性声明具有最高优先级 */
  width: 64px !important;
  height: 100%;
  background-color: #334157;
  margin: 0px;
}

.main-aside {
  width: 220px !important;
  height: 100%;
  background-color: #334157;
  margin: 0px;
}

.main-header,
.main-center {
  padding: 0px;
  border-left: 2px solid #333;
}
</style>

3.2 配置路由

router/index.js, 配置路由前先导入Main组件



....
{
  //增加Main组件路由
  path: '/Main',
  name: 'Main',
  component: Main
}

3.4 编辑登录组件

当登录成功后,显示系统首页

系统运行后的界面:

需要资料图片 放入src/assets中

icon.zip - 蓝奏云

头部代码

<template>
	<el-menu class="el-menu-demo" mode="horizontal" background-color="#334157" text-color="#fff" active-text-color="#fff">
		<el-button class="buttonimg">
      <!--
      该图标就是控制显示或隐藏侧边栏的图标
      当侧边栏处于打开状态时,显示关闭图标,表示可以执行关闭
      当侧边栏处于折叠状态时,显示打开图标,表示可以执行打开
      -->
			<img class="showimg" :src="!opened?imgshow:imgsq"  @click="doToggle()">
		</el-button>
		<el-submenu index="2" class="submenu">
			<template slot="title">超级管理员</template>
			<el-menu-item index="2-1">设置</el-menu-item>
			<el-menu-item index="2-2">个人中心</el-menu-item>
			<el-menu-item index="2-3" @click = "Signout">退出</el-menu-item>
		</el-submenu>
	</el-menu>
</template>

<script>
	export default {
    //定义组件名称
    name:'TopNav',

    data: function() {
      return {
		opened:true,
       imgshow:require('../assets/img/show.png'),
       imgsq:require('../assets/img/sq.png')
      }
    },


	}
</script>

<style scoped>
	.el-menu-vertical-demo:not(.el-menu--collapse) {
		border: none;
	}

	.submenu {
		float: right;
	}

	.buttonimg {
		height: 60px;
		background-color: transparent;
		border: none;
	}

	.showimg {
		width: 26px;
		height: 26px;
		position: absolute;
		top: 17px;
		left: 17px;
	}

	.showimg:active {
		border: none;
	}
</style>

右侧菜单栏代码

<template>
  <div>
<!-- <el-radio-group v-model="isCollapse" style="margin-bottom: 20px;">
  <el-radio-button :label="false">展开</el-radio-button>
  <el-radio-button :label="true">收起</el-radio-button>
</el-radio-group> -->
<el-menu router :default-active="$router.path" class="el-menu-vertical-demo"    text-color="#fff" active-text-color="#ffd04b" @open="handleOpen"   background-color="#334157"  @close="handleClose" :collapse="isCollapse">
  	<div class="logobox">
			<img class="logoimg" src="../assets/img/logo.png" alt="">
		</div>



   <el-submenu index="1">
    <template slot="title">
      <i class="el-icon-location"></i>
      <span slot="title">导航一</span>
    </template>
    <el-menu-item-group>
      <span slot="title">分组一</span>
      <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">
      <span slot="title">选项4</span>
      <el-menu-item index="1-4-1">选项1</el-menu-item>
    </el-submenu>
  </el-submenu>
  <el-menu-item index="2">
    <i class="el-icon-menu"></i>
    <span slot="title">导航二</span>
  </el-menu-item>
  <el-menu-item index="3" disabled>
    <i class="el-icon-document"></i>
    <span slot="title">导航三</span>
  </el-menu-item>
  <el-menu-item index="4">
    <i class="el-icon-setting"></i>
    <span slot="title">导航四</span>
  </el-menu-item> 
</el-menu>

  </div>
</template>

<script>
export default {
  name:'LeftAside',
  props:['opened'],
   data() {
      return {
        isCollapse: false,
      
      };
    },

    

}
</script>

<style>
  .el-menu-vertical-demo:not(.el-menu--collapse) {
    width: 220px;
    min-height: 400px;
  }
  .el-menu-vertical-demo:not(.el-menu--collapse) {
		border: none;
		text-align: left;
	}

	.el-menu-item-group__title {
		padding: 0px;
	}

	.el-menu-bg {
		background-color: #1f2d3d !important;
	}

	.el-menu {
		border: none;
	}

	.logobox {
		height: 40px;
		line-height: 40px;
		color: #9d9d9d;
		font-size: 20px;
		text-align: center;
		padding: 20px 0px;
	}

	.logoimg {
		height: 40px;
	}
</style>

3.6 实现左侧栏折叠效果

步骤:

  1. TopNav.vue定义监听函数,监听折叠按键的click事件,并将折叠或打开的状态值通过自定义事件传递给Main.vue组件。

 doToggle: function() {
        this.opened = !this.opened;
        his.$emit("left-open-collapsed", this.opened);
		
      }

2.Main.vue组件接收到TopNav.vue组件传递的状态值,根据状态值设置打开或折叠的样式,并将状态值通过props传递给LeftAside.vue组件

定义方法

toggleLeftStat(openState){
      if(openState){
        this.asideClass="main-aside";
      }else{
        this.asideClass="main-aside-collapsed";
      }
       this.openState = openState;
    }

3,LeftAside.vue组件通过接收到的状态值设置自身的打开或折叠效果。

<script>
export default {
  name:'LeftAside',
  props:['opened'],
   data() {
      return {
        isCollapse: false,
      };
    },
    methods: {
      handleOpen(key, keyPath) {
        console.log(key, keyPath);
      },
      handleClose(key, keyPath) {
        console.log(key, keyPath);
      }
    },
     watch:{
      opened (val){
         return this.isCollapse =!val;
       }
     },
 
 
   

}
</script>

做完后可以测试 是否能够收缩

2.动态树 - 数据绑定实现crud

1. 准备工作

  1. 创建测试数据库

    测试数据下载

    webserver.txt - 蓝奏云

    注:下载好后扩展名改为 sql 文件上传原因改为了txt

  2. 准备好后台服务接口,Moudel查询,和Book查询(支持分页)

    book查询需要

    使用ssm中切面制作分页 与分页插件 融合

    看博客

    (1条消息) mybatis与spring集成和分页插件应用嘴强程序员的博客-CSDN博客spring整合mybatis分页插件

    直接查看如何制作分页即可

    菜单查询!!

    注意后台获取数据需要用到递归 查库中为主菜单的pid 为 -1的

    service 层代码 sql 语句 select * from t_moudel where pid = ?

        @Override
        public List<Module> listModule(Integer pid) {
            List<Module> modules = module.listModule(pid);
            for (Module m:modules
                 ) {
         if("".equals(m.getUrl()) || null ==m.getUrl()){
             m.setModules(listModule(m.getId()));
         }
    
            }
    
            return modules;
        }

  3. 后台单元测试

    定义请求方法

    @RequestMapping("/listBook")
    public RetrunData bookList(Book bo, HttpServletRequest req) {
        //自定义的 分页实体
        PageBean pageBean = new PageBean();
        //条用分页条件改变
        pageBean.setRequest(req);
        //此处返回 map 也可以 自定义类
        RetrunData retrunData = null;
        try {
        //注意切面注解定义在业务层 
            List<Book> books = book.bookList(bo, pageBean);
            retrunData = new RetrunData(1, "数据加载成功", books);
            retrunData.setTotal(pageBean.getTotal());
        } catch (Exception e) {
            retrunData = new RetrunData(-1, "数据加载失败", null);
        }
    
    
        return retrunData;
    }

  4. 修改vue配置,使用真实环境

2. 动态树

2.1 在配置请求路径

在src/api/action.js中配置获取动态树数据的请求路径

export default {
	//服务器
	'SERVER': 'http://localhost:8080/',

	//登陆请求
	'SYSTEM_USER_DOLOGIN': '/login', //登陆

	//获取动态树数据请求
	'SYSTEM_MODULE_REQ': '/listBook',

	//获取完整的请求地址
	'getFullPath': k => { //获得请求的完整地址,用于mockjs测试时使用
		return this.SERVER + this[k];
	}

}

2.2 使用动态数据构建导航菜单

2.2.1 通过接口获取数据

LeftAside.vue:

data() {
      return {
        isCollapse: false,
        modules:[]
      };
    },
    methods: {
      handleOpen(key, keyPath) {
        console.log(key, keyPath);
      },
      handleClose(key, keyPath) {
        console.log(key, keyPath);
      }
    },
     watch:{
       opened (val){
         return this.isCollapse =!val;
       }
     },
 
    created:function(){
      let url =this.axios.urls.LISTMODULE_MODULE_DOLOGTN;
     this.axios.get(
      url,{}
     ).then(resp=>{
      console.log(resp)

     this.modules=resp.data.data;

     }).catch(error=>(
     console.log(error)
     )
     );
      


    }

测试是否打印数据 看浏览器的开发工具

2.2.3 通过后台获取的数据构建菜单导航

2.2.3.1 先构建一级导航菜单

LeftAside.vue:

页面效果:

2.2.3.2 构建二级导航菜单

LeftAside.vue:

页面效果:

页面代码

<template>
  <div>
<!-- <el-radio-group v-model="isCollapse" style="margin-bottom: 20px;">
  <el-radio-button :label="false">展开</el-radio-button>
  <el-radio-button :label="true">收起</el-radio-button>
</el-radio-group> -->
<el-menu router :default-active="$router.path" class="el-menu-vertical-demo"    text-color="#fff" active-text-color="#ffd04b" @open="handleOpen"   background-color="#334157"  @close="handleClose" :collapse="isCollapse">
  	<div class="logobox">
			<img class="logoimg" src="../assets/img/logo.png" alt="">
		</div>
<el-submenu v-for="m in modules" :key="m.id" :index="'index_'+m.id">

 <template slot="title">
      <i :class="m.icon"></i>
      <span slot="title">{{m.text}}</span>
    </template>

   <el-menu-item-group>
      <span slot="title">分组一</span>
      <el-menu-item v-for="m1 in m.modules" :key="m1.id" :index="m1.url ">{{m1.text}}</el-menu-item>
     
    </el-menu-item-group>

</el-submenu>

</el-menu>

  </div>
</template>

<script>
export default {
  name:'LeftAside',
  props:['opened'],
   data() {
      return {
        isCollapse: false,
        modules:[]
      };
    },
    methods: {
      handleOpen(key, keyPath) {
        console.log(key, keyPath);
      },
      handleClose(key, keyPath) {
        console.log(key, keyPath);
      }
    },
     watch:{
       opened (val){
        return this.isCollapse =!val;
       }
     },
 
    created:function(){
      let url =this.axios.urls.LISTMODULE_MODULE_DOLOGTN;
     this.axios.get(
      url,{}
     ).then(resp=>{
     //  console.log(resp)

     this.modules=resp.data.data;

     }).catch(error=>(
     console.log(error)
     )
     );
      


    }

}
</script>

<style>
  .el-menu-vertical-demo:not(.el-menu--collapse) {
    width: 220px;
    min-height: 400px;
  }
  .el-menu-vertical-demo:not(.el-menu--collapse) {
		border: none;
		text-align: left;
	}

	.el-menu-item-group__title {
		padding: 0px;
	}

	.el-menu-bg {
		background-color: #1f2d3d !important;
	}

	.el-menu {
		border: none;
	}

	.logobox {
		height: 40px;
		line-height: 40px;
		color: #9d9d9d;
		font-size: 20px;
		text-align: center;
		padding: 20px 0px;
	}

	.logoimg {
		height: 40px;
	}
</style>

2.3 点击菜单实现路由跳转

2.3.1 创建书本管理组件

数据库保存数据

t_module_vue表中已经配置了功能url,为方便,将书本管理组件定义为BookList。如果使用其他名字则需要修改功能url配置,保持一致。

2.3.2 配置路由

2.3.3 修改LeftAside组件

2.3.4 修改Main组件

3. 系统首页配置

进入默认显示界面

或者添加首页界面 然后配置

添加默认菜单

 <el-menu-item index="/Home" >
 <template slot="title">
    <i class="el-icon-s-home"></i>
    <span slot="title">首页</span>
    </template>
  </el-menu-item>

4. 表格数据显示实现crud

4.1 页面布局

页面上使用的面包屑,查询条件,表格,分页等空间,可以查看element-ui官网。该步骤主要关注页面布局,并没有绑定数据,编写完成后,观察页面效果。 BookList.vue:

<template>
  <div>
    <!--面包屑-->
    <el-breadcrumb style="margin-top: 15px; margin-left: 5px" separator="/">
      <el-breadcrumb-item>首页</el-breadcrumb-item>
      <el-breadcrumb-item>书本管理</el-breadcrumb-item>
    </el-breadcrumb>

    <!--查询条件   inline 改变是否行内 显示-->
    <el-form style="margin-top: 15px" :inline="true" class="demo-form-inline">
      <el-form-item label="书名">
        <el-input v-model="bookName" placeholder="书名"></el-input>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" @click="qry">查询</el-button>
        <el-button type="primary" @click="addBook">新增</el-button>
      </el-form-item>
    </el-form>

    <el-table :data="tableData" border style="width: 95%; margin: auto">
      <el-table-column fixed prop="bookname" label="书名" width="180">
      </el-table-column>
      <el-table-column prop="id" label="编号" width="210"> </el-table-column>
      <el-table-column prop="price" label="价格" width="210"> </el-table-column>
      <el-table-column prop="booktype" label="类型" width="210">
        <!-- <img src="" alt=""> -->
      </el-table-column>
      <el-table-column fixed="right" label="操作" width="100">
        <template slot-scope="scope">
          <el-button @click="handleClick(scope.row)" type="text" size="small"
            >编辑</el-button
          >
          <!-- <el-button @click="delbook(scope.row)" type="text" size="small"
            >删除</el-button -->
            <el-popconfirm
  confirm-button-text='确定'
  cancel-button-text='取消'
  @confirm="delbook(scope.row)"
  icon-color="red"
  title="你确定要删除吗?"
>
  <el-button  type="text" size="small" slot="reference" >删除</el-button>
</el-popconfirm>
          
        </template>
      </el-table-column>
    </el-table>

    <!-- 分页栏 -->
    <el-pagination
      background
      @size-change="handleSizeChange"
      @current-change="handleCurrentChange"
      :current-page="page"
      :page-sizes="[10, 20, 30, 40]"
      :page-size="rows"
      layout="total, sizes, prev, pager, next, jumper"
      :total="total"
    >
    </el-pagination>

  </div>
</template>

4.2 查询并在表格中显示数据

  1. 将查询书本信息的接口配置到api/action.js中

//获取书本信息
 'BOOKMSG_BOOKINFO_REQ':'/listBook',

BookList.vue组件 图一: template部分:

图二: script部分

  data() {
    // 自定义 正则
    var validatePrice = (rule, value, callback) => {
      if (!value) {
        callback(new Error("请输入价格"));
      } else if (isNaN(value)) {
        callback(new Error("只能输入数字"));
      } else {
        callback();
      }
    };
    return {
      bookName: "",
      tableData: [],
      page: 1,
      rows: 10,
      total: 1,
      dialogName: "新增书本",
      dialogFormVisible: false,
      //统一控制标签的宽度
      formLabelWidth: "70px",

      //统一控制表单元素的宽度
      formEleWidth: "350px",

      bookForm: {
        id: 0,
        bookname: "",
        price: "",
        booktype: "",
      },
      optiontype: "addbook",
      //表单验证
      rules: {
        bookname: [
          { required: true, message: "请输入书本名", trigger: "blur" },
        ],
        price: [
          //validatePrice 引入自定义表单验证

          { required: true, validator: validatePrice, trigger: "blur" },
        ],
      },
    };
  }
  
  方法
qry() {
      let url = this.axios.urls.BookList_Book_DOLOGTN;
      //  console.log(122312)
      //分页需要 参数名发送后接受  查看后台的pageBen方法中定义
      let props = {
        bookname: this.bookName,
        page: this.page,
        rows: this.rows,
      };

      this.axios
        .post(url, props)
        .then((resp) => {
          //   console.log(resp)
          this.tableData = resp.data.data;
          this.total = resp.data.total;
        })
        .catch((error) => {
          console.log(error);
        });
    }

script部分,图二:

,
    handleSizeChange(rows) {
      this.rows = rows;
      this.page = 1;
      //  console.log(this.rows)
      this.qry();
    },
    handleCurrentChange(page) {
      this.page = page;
      this.qry();
    }

增加与删除修改 把请求地址分别修改一下即可

<template>
  <div>
    <!--面包屑-->
    <el-breadcrumb style="margin-top: 15px; margin-left: 5px" separator="/">
      <el-breadcrumb-item>首页</el-breadcrumb-item>
      <el-breadcrumb-item>书本管理</el-breadcrumb-item>
    </el-breadcrumb>

    <!--查询条件   inline 改变是否行内 显示-->
    <el-form style="margin-top: 15px" :inline="true" class="demo-form-inline">
      <el-form-item label="书名">
        <el-input v-model="bookName" placeholder="书名"></el-input>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" @click="qry">查询</el-button>
        <el-button type="primary" @click="addBook">新增</el-button>
      </el-form-item>
    </el-form>

    <el-table :data="tableData" border style="width: 95%; margin: auto">
      <el-table-column fixed prop="bookname" label="书名" width="180">
      </el-table-column>
      <el-table-column prop="id" label="编号" width="210"> </el-table-column>
      <el-table-column prop="price" label="价格" width="210"> </el-table-column>
      <el-table-column prop="booktype" label="类型" width="210">
        <!-- <img src="" alt=""> -->
      </el-table-column>
      <el-table-column fixed="right" label="操作" width="100">
        <template slot-scope="scope">
          <el-button @click="handleClick(scope.row)" type="text" size="small"
            >编辑</el-button
          >
          <!-- <el-button @click="delbook(scope.row)" type="text" size="small"
            >删除</el-button -->
            <el-popconfirm
  confirm-button-text='确定'
  cancel-button-text='取消'
  @confirm="delbook(scope.row)"
  icon-color="red"
  title="你确定要删除吗?"
>
  <el-button  type="text" size="small" slot="reference" >删除</el-button>
</el-popconfirm>
          
        </template>
      </el-table-column>
    </el-table>

    <!-- 分页栏 -->
    <el-pagination
      background
      @size-change="handleSizeChange"
      @current-change="handleCurrentChange"
      :current-page="page"
      :page-sizes="[10, 20, 30, 40]"
      :page-size="rows"
      layout="total, sizes, prev, pager, next, jumper"
      :total="total"
    >
    </el-pagination>

    <!-- 编辑 窗口 -->

    <el-dialog
      :title="dialogName"
      :visible.sync="dialogFormVisible"
      @close="closeBookForm('bookForm')"
      width="500px"
    >
      <el-form :model="bookForm" :rules="rules" ref="bookForm">
        <el-form-item
          
          v-show="optiontype == 'update'"
          label="编号"
          :label-width="formLabelWidth"
        >
          <el-input
            v-model="bookForm.id"
            disabled
            autocomplete="off"
            :style="{ width: formEleWidth }"
          ></el-input>
        </el-form-item>
        <el-form-item
          label="书名"
          prop="bookname"
          :label-width="formLabelWidth"
        >
          <el-input
            v-model="bookForm.bookname"
            autocomplete="off"
            :style="{ width: formEleWidth }"
          ></el-input>
        </el-form-item>
        <el-form-item label="价格" prop="price" :label-width="formLabelWidth">
          <el-input
            v-model="bookForm.price"
            autocomplete="off"
            :style="{ width: formEleWidth }"
          ></el-input>
        </el-form-item>
        <el-form-item
          label="类型"
          prop="booktype"
          :label-width="formLabelWidth"
        >
          <el-select
            v-model="bookForm.booktype"
            placeholder="选择类型"
            :style="{ width: formEleWidth }"
          >
            <el-option label="名著" value="mz"></el-option>
            <el-option label="小说" value="xs"></el-option>
          </el-select>
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="dialogFormVisible = false">取 消</el-button>
        <el-button type="primary" @click="saveBook('bookForm')"
          >确 定</el-button
        >
      </div>
    </el-dialog>
  </div>
</template>






<script>
export default {
  name: "BookList",
  methods: {
    handleClick(row) {
      // console.log(row);
      this.dialogName = "修改书籍";
      this.dialogFormVisible = true;
      this.bookForm.id = row.id;
      this.bookForm.bookname = row.bookname;
      this.bookForm.booktype = row.booktype;
      this.bookForm.price = row.price;
      this.optiontype = "update";
    },
    qry() {
      let url = this.axios.urls.BookList_Book_DOLOGTN;
      //  console.log(122312)
      let props = {
        bookname: this.bookName,
        page: this.page,
        rows: this.rows,
      };

      this.axios
        .post(url, props)
        .then((resp) => {
          //   console.log(resp)
          this.tableData = resp.data.data;
          this.total = resp.data.total;
        })
        .catch((error) => {
          console.log(error);
        });
    },
    handleSizeChange(rows) {
      this.rows = rows;
      this.page = 1;
      //  console.log(this.rows)
      this.qry();
    },
    handleCurrentChange(page) {
      this.page = page;
      this.qry();
    },
    addBook() {
      this.dialogName = "新增书籍";
     
      this.closeBookForm();

      this.dialogFormVisible = true;
      this.optiontype = "addbook";
    },
    closeBookForm(bookForm) {
      console.log(bookForm);
      this.bookForm.id = null;
      this.bookForm.bookname = null;
      this.bookForm.booktype = null;
      this.bookForm.price = null;
      
      //  console.log(this.bookForm)
      this.dialogFormVisible = false;
      if(bookForm == undefined){return ""}
      //对整个表单进行重置,将所有字段值重置为初始值并移除校验结果 resetFields
      this.$refs[bookForm].resetFields();
    },
    saveBook(bookForm) {
      //提交
      // console.log(bookForm)
      //验证表单,valid true 表示通过验证,false没通过
      this.$refs[bookForm].validate((valid) => {
        //     console.log(valid)
        if (valid) {
          let url = this.axios.urls.BOOKMSG_BOOKINFO_ADD;

          //如果当前操作类型为update则需要调用更新接口
          if (this.optiontype == "update") {
            url = this.axios.urls.BOOKMSG_BOOKINFO_UPDATE;
          }
          this.axios
            .post(url, this.bookForm)
            .then((resp) => {
              //操作成功,关闭弹出框,执行查询以便于显示最新数据
              //操作失败,提示失败,关闭弹出框
              if (resp.data.code == 1) {
                this.$message({
                  message: resp.data.msg,
                  type: "success",
                });

                //this.dialogFormVisible = false;
                //调用查询
                this.qry();
                //清理表单
                this.closeBookForm();
              } else {
                this.$message({
                  message: resp.data.msg,
                  type: "error",
                });
                //关闭窗体
                this.dialogFormVisible = false;
              }
            })
            .catch((error) => {
              //   console.log(error)
            });
        }
      });
    },
    delbook(row) {
      //  console.log(row)
      let url = this.axios.urls.BOOKMSG_BOOKINFO_DELETE;
      this.axios
        .post(url, {
          id: row.id,
        })
        .then((resp) => {
          if (resp.data.code == 1) {
            this.$message({
              message: resp.data.msg,
              type: "success",
            });

            //this.dialogFormVisible = false;
            //调用查询
            this.qry();
          } else {
            this.$message({
              message: resp.data.msg,
              type: "error",
            });
          }
        })
        .catch((error) => {
          console.log(error);
        });
        
    },
  },

  data() {
    // 自定义 正则
    var validatePrice = (rule, value, callback) => {
      if (!value) {
        callback(new Error("请输入价格"));
      } else if (isNaN(value)) {
        callback(new Error("只能输入数字"));
      } else {
        callback();
      }
    };
    return {
      bookName: "",
      tableData: [],
      page: 1,
      rows: 10,
      total: 1,
      dialogName: "新增书本",
      dialogFormVisible: false,
      //统一控制标签的宽度
      formLabelWidth: "70px",

      //统一控制表单元素的宽度
      formEleWidth: "350px",

      bookForm: {
        id: 0,
        bookname: "",
        price: "",
        booktype: "",
      },
      optiontype: "addbook",
      //表单验证
      rules: {
        bookname: [
          { required: true, message: "请输入书本名", trigger: "blur" },
        ],
        price: [
          //validatePrice 引入自定义表单验证

          { required: true, validator: validatePrice, trigger: "blur" },
        ],
      },
    };
  },
  created() {
    this.qry();
  },
};
</script>

<style>
</style>

源代码 带 jwt令牌 在http中把 jwt过滤器注释掉即可 测试

文件.zip - 蓝奏云

使用前 需要把依赖瞎咋 命令 npm install 下载依赖 cmd到项目路径

crud实现详情 课件分享

课件.zip - 蓝奏云

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值