目录
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中
头部代码
<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 实现左侧栏折叠效果
步骤:
-
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. 准备工作
-
创建测试数据库
测试数据下载
注:下载好后扩展名改为 sql 文件上传原因改为了txt
-
准备好后台服务接口,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; }
-
后台单元测试
定义请求方法
@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; }
-
修改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 查询并在表格中显示数据
-
将查询书本信息的接口配置到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过滤器注释掉即可 测试
使用前 需要把依赖瞎咋 命令 npm install 下载依赖 cmd到项目路径
crud实现详情 课件分享