ElementUI--数据表格增删改查与表单验证

简介: ElementUI--数据表格增删改查与表单验证

一、CRUD实现


1.1 后台CRUD编写

package com.zking.ssm.controller;
import com.zking.ssm.model.Book;
import com.zking.ssm.service.IBookService;
import com.zking.ssm.util.JsonResponseBody;
import com.zking.ssm.util.PageBean;
import com.zking.ssm.vo.BookFileVo;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.List;
import java.util.Map;
@Controller
@RequestMapping("/book")
public class BookController {
    @Autowired
    private IBookService bookService;
    @RequestMapping("/addBook")
    @ResponseBody
    public JsonResponseBody<?> addBook(Book book){
        try {
            bookService.insert(book);
            return new JsonResponseBody<>("新增书本成功",true,0,null);
        } catch (Exception e) {
            e.printStackTrace();
            return new JsonResponseBody<>("新增书本失败",false,0,null);
        }
    }
    @RequestMapping("/editBook")
    @ResponseBody
    public JsonResponseBody<?> editBook(Book book){
        try {
            bookService.updateByPrimaryKey(book);
            return new JsonResponseBody<>("编辑书本成功",true,0,null);
        } catch (Exception e) {
            e.printStackTrace();
            return new JsonResponseBody<>("编辑书本失败",false,0,null);
        }
    }
    @RequestMapping("/delBook")
    @ResponseBody
    public JsonResponseBody<?> delBook(Book book){
        try {
            bookService.deleteByPrimaryKey(book.getId());
            return new JsonResponseBody<>("删除书本成功",true,0,null);
        } catch (Exception e) {
            e.printStackTrace();
            return new JsonResponseBody<>("删除书本失败",false,0,null);
        }
    }
    @RequestMapping("/queryBookPager")
    @ResponseBody
    public JsonResponseBody<List<Book>> queryBookPager(Book book, HttpServletRequest req){
        try {
            PageBean pageBean=new PageBean();
            pageBean.setRequest(req);
            List<Book> books = bookService.queryBookPager(book, pageBean);
            return new JsonResponseBody<>("OK",true,pageBean.getTotal(),books);
        } catch (Exception e) {
            e.printStackTrace();
            return new JsonResponseBody<>("分页查询书本失败",false,0,null);
        }
    }
    @RequestMapping("/queryBookCharts")
    @ResponseBody
    public JsonResponseBody<?> queryBookCharts(){
        try{
            Map<String, Object> charts = bookService.queryBookCharts();
            return new JsonResponseBody<>("OK",true,0,charts);
        }catch (Exception e){
            e.printStackTrace();
            return new JsonResponseBody<>("查询统计分析数据失败",false,0,null);
        }
    }
    @RequestMapping("/upload")
    @ResponseBody
    public JsonResponseBody<?> upload(BookFileVo bookFileVo){
        try {
            MultipartFile bookFile = bookFileVo.getBookFile();
            System.out.println(bookFileVo);
            System.out.println(bookFile.getContentType());
            System.out.println(bookFile.getOriginalFilename());
            return new JsonResponseBody<>("上传成功",true,0,null);
        } catch (Exception e) {
            e.printStackTrace();
            return new JsonResponseBody<>("上传失败",false,0,null);
        }
    }
    @RequestMapping("/download")
    public void download(HttpServletRequest request, HttpServletResponse response){
        try {
            String relativePath = "uploads/1.jpg";
            String absolutePath = request.getRealPath(relativePath);
            InputStream is = new FileInputStream(new File(absolutePath));
            OutputStream out = response.getOutputStream();
            response.setContentType("application/octet-stream");
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("1.jpg", "UTF-8"));
            byte[] by = new byte[1024];
            int len = -1;
            while (-1 != (len = is.read(by))) {
                out.write(by);
            }
            is.close();
            out.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    @RequestMapping("/downloadUrl")
    public void downloadUrl(HttpServletRequest request, HttpServletResponse response){
        String relativePath = "uploads/1.jpg";
        String absolutePath = request.getRealPath(relativePath);
        InputStream is = null;
        OutputStream out = null;
        try {
            is = new FileInputStream(new File(absolutePath));
            // 设置Content-Disposition
            response.setHeader("Content-Disposition",
                    "attachment;filename=" + URLEncoder.encode("1.jpg", "UTF-8"));
            out = response.getOutputStream();
            IOUtils.copy(is, out);
            response.flushBuffer();
            System.out.println("完成");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            IOUtils.closeQuietly(is);
            IOUtils.closeQuietly(out);
        }
    }
}


1.2 配置访问路径

src/api/action.js :

  //获取书本信息
  'BOOKMSG_BOOKINFO_REQ': '/book/queryBookPager',
  //新增书本
  'BOOK_ADD': '/book/addBook',
  //修改书本
  'BOOK_EDIT': '/book/editBook',
  //删除书本
  'BOOK_DEL': '/book/delBook',


1.3 前端编写(及窗口)

<template>
  <div class="Book" style="padding: 30px;">
    <!-- 输入框搜索 -->
    <el-form :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="warning" @click="onSubmit()">查询</el-button>
        <el-button type="warning" icon="el-icon-plus" @click="addBook()">新增</el-button>
      </el-form-item>
    </el-form>
    <!-- 书籍的书籍表格 -->
    <el-table :data="tableData" style="width: 100%">
      <el-table-column prop="id" label="书籍ID"></el-table-column>
      <el-table-column prop="bookname" label="书籍名称"></el-table-column>
      <el-table-column prop="price" label="书籍价格"></el-table-column>
      <el-table-column prop="booktype" label="书籍类型"></el-table-column>
      <!-- “编辑”“删除”功能连接 -->
      <el-table-column label="操作">
        <!--
          在<template>上使用特殊的slot-scope 特性,可以接收传递给插槽的prop
          slot-scope:类似将每一行的row对象封装到槽中,之后直接从scope中获取
          row对象信息和行索引index信息即可
        -->
        <template slot-scope="scope">
          <el-button size="mini" @click="handleEdit(scope.row)">编辑</el-button>
          <el-button size="mini" type="danger" @click="handleDelete(scope.row)">删除</el-button>
        </template>
      </el-table-column>
    </el-table>
    <!-- 分页 -->
    <div class="block" style="padding: 20px;">
      <el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="page"
        background :page-sizes="[10, 20, 30, 40]" :page-size="rows" layout="total, sizes, prev, pager, next, jumper"
        :total="total">
      </el-pagination>
    </div>
    <!--
  弹出窗口:增加和修改书本信息共用一个弹出窗口,需要根据用户的选择动态的设置弹出窗口的标题
  :tile  通过绑定值的方式设置dialog的标题
  :visible.sync  控制弹出窗口的显示或隐藏,.sync同步修饰符
  @close="closeBookForm",设置窗口关闭时调用的处理函数,可用于清空表单
  :model="bookForm":用于定义表单对应的model,具体model的定义可见data部分。
  v-show="optiontype == 'update'" 通过操作类型控制是否显示书本编号字段,如果当前操作类型为
         新增,则不用显示,书本编号在数据表中是自增的。
  :label-width="formLabelWidth" 统一定义标签的宽度。
  :style="{width: formEleWidth}"  统一定义form元素的宽度。
  -->
    <el-dialog :title="dialogName" :visible.sync="dialogFormVisible" @close="closeBookForm" width="500px">
      <el-form :model="bookForm">
        <el-form-item v-show="optiontype == 'update'" label="编号" :label-width="formLabelWidth">
          <el-input v-model="bookForm.id" autocomplete="off" :style="{width: formEleWidth}"></el-input>
        </el-form-item>
        <el-form-item label="书名" :label-width="formLabelWidth">
          <el-input v-model="bookForm.bookname" autocomplete="off" :style="{width: formEleWidth}"></el-input>
        </el-form-item>
        <el-form-item label="价格" :label-width="formLabelWidth">
          <el-input v-model="bookForm.price" autocomplete="off" :style="{width: formEleWidth}"></el-input>
        </el-form-item>
        <el-form-item label="类型" :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()">确 定</el-button>
      </div>
    </el-dialog>
  </div>
</template>


注1:隐藏显示设置,通过Vue实例对象中的dialogFormVisible="true|false"来控制dialog显示隐藏

      :visible.sync="dialogFormVisible"

 

注2:通过close或closed事件,在关闭dialog弹出框时清空form表单数据和验证信息;

      @close="dialogClose"  


1.4 增删改查实现

<script>
  export default {
    name: 'BookList',
    data() {
      return {
        bookname: '',
        tableData: [],
        rows: 10,
        total: 0,
        page: 1,
        //控制对话框是否显示,默认是隐藏状态
        dialogFormVisible: false,
        //统一控制标签的宽度
        formLabelWidth: '40px',
        //统一控制表单元素的宽度
        formEleWidth: '400px',
        //对话框标题,默认为新增,如果是点击修改按钮打开对话框,则标题应为修改。
        dialogName: '新增书本',
        //操作类型,默认为添加,如果是点击修改打开对话框,则操作类类型应变为修改
        //该变量用于控制是否显示书本编号字段,当操作类型为新增时不需显示(书本编号数据表字段为自增)
        //当操作类型为修改时,需要显示。
        optiontype: 'add',
        //定义验证规则
        rules:{
          bookname: [{
              required: true,
              message: '请输入书籍名称',
              trigger: 'blur'
            },
            {
              min: 1,
              max: 10,
              message: '长度在 1 到 10 个字符',
              trigger: 'blur'
            }
          ],
          price: [{
            required: true,
            message: '请输入价格',
            trigger: 'blur'
          }],
          booktype: [{
            required: true,
            message: '请输入书籍类别',
            trigger: 'blur'
          }]
        },
        //定义表单对应的model
        bookForm: {
          id: '',
          bookname: '',
          price: null,
          booktype: ''
        }
      }
    },
    methods: {
      /* 新增书本 */
      saveBook() {
        this.$refs['bookForm'].validate((valid) => {
          if (valid) {
            //默认新增
            var url = this.axios.urls.BOOK_ADD;
            if (this.optiontype == 'update') {
              url = this.axios.urls.BOOK_EDIT;
            }
            console.log(url)
            this.axios.post(url, this.bookForm).then(d => {
              //关闭窗口
              this.closeBookForm();
              this.dialogFormVisible = false;
              this.query({});
            }).catch();
          } else {
            console.log('error submit!!');
            return false;
          }
        });
      },
      //选择分页
      handleSizeChange(r) {
        //当页大小发生变化
        let params = {
          bookname: this.bookname,
          rows: r,
          page: this.page
        }
        this.query(params);
      },
      //输入分页
      handleCurrentChange(p) {
        //当前页码大小发生变化
        let params = {
          bookname: this.bookname,
          rows: this.rows,
          // 分页
          page: p
        }
        this.query(params);
      },
      //查询方法
      query(params) {
        //获取后台请求书籍数据的地址
        let url = this.axios.urls.BOOKMSG_BOOKINFO_REQ;
        this.axios.get(url, {
          params: params
        }).then(d => {
          this.tableData = d.data.rows;
          this.total = d.data.total;
        }).catch(e => {});
      },
      onSubmit() {
        let params = {
          bookname: this.bookname
        }
        console.log(params)
        this.query(params);
        this.bookname = ''
      },
      //当关闭对话框时,该方法用于清空表单
      closeBookForm() {
        this.bookForm.id = null;
        this.bookForm.bookname = null;
        this.bookForm.booktype = null;
        this.bookForm.price = null;
      },
      //打开对话框,将对话框标题设置为新增,操作类型设置为'add'
      addBook() {
        this.dialogName = '新增书本信息';
        this.dialogFormVisible = true;
        this.optiontype = 'add';
      },
      //打开对话框,将对话框标题设置为修改,操作类型设置为'update',
      //并使用获取的待修改的记录的值设置对应的表单元素
      handleEdit(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';
      },
      //删除书本记录
      handleDelete(row) {
        this.$confirm('此操作将永久删除该文件, 是否继续?', '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        }).then(() => {
          //获取删除书本访问路径
          var url = this.axios.urls.BOOK_DEL;
          this.axios.post(url, {
            id: row.id
          }).then(r => {
            this.$message({
              type: 'success',
              message: '删除成功!'
            });
            this.query({});
          })
        }).catch(() => {
          this.$message({
            type: 'info',
            message: '已取消删除'
          });
        });
      }
    },
    created() {
      this.query({})
    }
  }
</script>


1.4.1 新增示例

b68e7a8db7964784af418be41c5c5b94.gif


1.4.2 修改示例

650ed6426f7d4bada9d87e897ecfb19d.gif


1.4.3 删除示例

1d65f352aa6b4eeea9fe9d6b4311d1ff.gif


二、表单验证


2.1 设置表单验证属性

  Form 组件提供了表单验证的功能,只需要通过 rules 属性传入约定的验证规则,并将 Form-Item 的 prop 属性设置为需校验的字段名即可。校验规则参见 async-validator

413b69896927406cb851d98fd5c0b8c8.png

2.2 自定义验证规则

 //定义验证规则
        rules:{
          bookname: [{
              required: true,
              message: '请输入书籍名称',
              trigger: 'blur'
            },
            {
              min: 1,
              max: 10,
              message: '长度在 1 到 10 个字符',
              trigger: 'blur'
            }
          ],
          price: [{
            required: true,
            message: '请输入价格',
            trigger: 'blur'
          }],
          booktype: [{
            required: true,
            message: '请输入书籍类别',
            trigger: 'blur'
          }]
        },


2.3 使用规则

      /* 新增书本 */
      saveBook() {
        this.$refs['bookForm'].validate((valid) => {
          if (valid) {
            //默认新增
            var url = this.axios.urls.BOOK_ADD;
            if (this.optiontype == 'update') {
              url = this.axios.urls.BOOK_EDIT;
            }
            console.log(url)
            this.axios.post(url, this.bookForm).then(d => {
              //关闭窗口
              this.closeBookForm();
              this.dialogFormVisible = false;
              this.query({});
            }).catch();
          } else {
            console.log('error submit!!');
            return false;
          }
        });
      },


2.4 效果演示

e776cf477fd04645824d753bc2a5ca04.gif

目录
相关文章
|
6天前
|
数据采集 数据库 Python
有哪些方法可以验证用户输入数据的格式是否符合数据库的要求?
有哪些方法可以验证用户输入数据的格式是否符合数据库的要求?
112 75
|
2月前
|
存储 监控 数据处理
flink 向doris 数据库写入数据时出现背压如何排查?
本文介绍了如何确定和解决Flink任务向Doris数据库写入数据时遇到的背压问题。首先通过Flink Web UI和性能指标监控识别背压,然后从Doris数据库性能、网络连接稳定性、Flink任务数据处理逻辑及资源配置等方面排查原因,并通过分析相关日志进一步定位问题。
223 61
|
21天前
|
SQL 关系型数据库 API
HarmonyOs开发:关系型数据库封装之增删改查
每个方法都预留了多种调用方式,比如使用callback异步回调或者使用Promise异步回调,亦或者同步执行,大家在使用的过程中,可以根据自身业务需要进行选择性调用,也分别暴露了成功和失败的方法,可以针对性的判断在执行的过程中是否执行成功。
83 13
|
19天前
|
SQL 存储 运维
从建模到运维:联犀如何完美融入时序数据库 TDengine 实现物联网数据流畅管理
本篇文章是“2024,我想和 TDengine 谈谈”征文活动的三等奖作品。文章从一个具体的业务场景出发,分析了企业在面对海量时序数据时的挑战,并提出了利用 TDengine 高效处理和存储数据的方法,帮助企业解决在数据采集、存储、分析等方面的痛点。通过这篇文章,作者不仅展示了自己对数据处理技术的理解,还进一步阐释了时序数据库在行业中的潜力与应用价值,为读者提供了很多实际的操作思路和技术选型的参考。
31 1
|
24天前
|
存储 Java easyexcel
招行面试:100万级别数据的Excel,如何秒级导入到数据库?
本文由40岁老架构师尼恩撰写,分享了应对招商银行Java后端面试绝命12题的经验。文章详细介绍了如何通过系统化准备,在面试中展示强大的技术实力。针对百万级数据的Excel导入难题,尼恩推荐使用阿里巴巴开源的EasyExcel框架,并结合高性能分片读取、Disruptor队列缓冲和高并发批量写入的架构方案,实现高效的数据处理。此外,文章还提供了完整的代码示例和配置说明,帮助读者快速掌握相关技能。建议读者参考《尼恩Java面试宝典PDF》进行系统化刷题,提升面试竞争力。关注公众号【技术自由圈】可获取更多技术资源和指导。
|
27天前
|
前端开发 JavaScript 数据库
获取数据库中字段的数据作为下拉框选项
获取数据库中字段的数据作为下拉框选项
54 5
|
2月前
|
关系型数据库 MySQL 数据库
GBase 数据库如何像MYSQL一样存放多行数据
GBase 数据库如何像MYSQL一样存放多行数据
|
28天前
|
存储 Oracle 关系型数据库
数据库传奇:MySQL创世之父的两千金My、Maria
《数据库传奇:MySQL创世之父的两千金My、Maria》介绍了MySQL的发展历程及其分支MariaDB。MySQL由Michael Widenius等人于1994年创建,现归Oracle所有,广泛应用于阿里巴巴、腾讯等企业。2009年,Widenius因担心Oracle收购影响MySQL的开源性,创建了MariaDB,提供额外功能和改进。维基百科、Google等已逐步替换为MariaDB,以确保更好的性能和社区支持。掌握MariaDB作为备用方案,对未来发展至关重要。
56 3
|
28天前
|
安全 关系型数据库 MySQL
MySQL崩溃保险箱:探秘Redo/Undo日志确保数据库安全无忧!
《MySQL崩溃保险箱:探秘Redo/Undo日志确保数据库安全无忧!》介绍了MySQL中的三种关键日志:二进制日志(Binary Log)、重做日志(Redo Log)和撤销日志(Undo Log)。这些日志确保了数据库的ACID特性,即原子性、一致性、隔离性和持久性。Redo Log记录数据页的物理修改,保证事务持久性;Undo Log记录事务的逆操作,支持回滚和多版本并发控制(MVCC)。文章还详细对比了InnoDB和MyISAM存储引擎在事务支持、锁定机制、并发性等方面的差异,强调了InnoDB在高并发和事务处理中的优势。通过这些机制,MySQL能够在事务执行、崩溃和恢复过程中保持
66 3
|
28天前
|
SQL 关系型数据库 MySQL
数据库灾难应对:MySQL误删除数据的救赎之道,技巧get起来!之binlog
《数据库灾难应对:MySQL误删除数据的救赎之道,技巧get起来!之binlog》介绍了如何利用MySQL的二进制日志(Binlog)恢复误删除的数据。主要内容包括: 1. **启用二进制日志**:在`my.cnf`中配置`log-bin`并重启MySQL服务。 2. **查看二进制日志文件**:使用`SHOW VARIABLES LIKE &#39;log_%&#39;;`和`SHOW MASTER STATUS;`命令获取当前日志文件及位置。 3. **创建数据备份**:确保在恢复前已有备份,以防意外。 4. **导出二进制日志为SQL语句**:使用`mysqlbinlog`
85 2

热门文章

最新文章