Springboot快速整合bootstrap-table使用,接口对接

这个表格加持还是不错了,自带了全局搜索,分页,数据导出,卡片视图,等,本次整合添加了数据添加弹窗和编辑数据回显弹窗,附完整页面代码,只需要拿过来替换自己实际的接口即可。

效果图

image-20240325192345466

接口案例

数据列表:

{
  "code": 200,
  "msg": "ok",
  "data": [
    {
      "categoryId": 52,
      "categoryName": "哈哈哈"
    },
    {
      "categoryId": 53,
      "categoryName": "哈哈哈地方"
    },
    {
      "categoryId": 7,
      "categoryName": "悬疑灵异"
    },
    {
      "categoryId": 4,
      "categoryName": "武侠仙侠"
    },
    {
      "categoryId": 3,
      "categoryName": "玄幻奇幻"
    }
  ]
}

增:/novel-category/add

删:/novel-category/delete/{id}

改:/novel-category/update

查:/novel-category/list

批量删:/novel-category/deleteBatch

对应后端实现

package com.xxx.readverse.controller;


import cn.dev33.satoken.util.SaResult;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xxx.readverse.entity.Category;
import com.xxx.readverse.service.CategoryService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import java.util.Arrays;
import java.util.List;

@Controller
@RequestMapping("/novel-category")
@Api(tags = "小说分类")
@CrossOrigin
public class CategoryController {

    @Autowired
    private CategoryService novelCategoryService;


    @GetMapping("/list")
    @ApiOperation("分类列表")
    @ResponseBody
    public SaResult getNovelCategories() {
        List<Category> categoryList = novelCategoryService.list(new QueryWrapper<Category>().last("limit 12"));
        return SaResult.data(categoryList);
    }

    @PostMapping("/add")
    @ApiOperation("新增分类")
    @ResponseBody
    public SaResult add(Category novelCategory) {
        try {
            novelCategoryService.save(novelCategory);
        } catch (DuplicateKeyException e) {
            return SaResult.error("操作未成功,可能是因为数据重复导致的");
        }
        return SaResult.data(novelCategory.getCategoryId());
    }

    @GetMapping("/deleteBatch")
    @ApiOperation("批量删除")
    @ResponseBody
    public SaResult deleteBatch(@RequestParam("ids") Integer[] ids) {
        novelCategoryService.removeByIds(Arrays.asList(ids));
        return SaResult.ok();
    }

    @GetMapping("/delete/{id}")
    @ApiOperation("删除分类")
    @ResponseBody
    public SaResult delete(@PathVariable Integer id) {
        novelCategoryService.removeById(id);
        return SaResult.ok();
    }

    @PostMapping("/update")
    @ApiOperation("修改分类")
    @ResponseBody
    public SaResult update(Category novelCategory) {
        novelCategoryService.updateById(novelCategory);
        return SaResult.ok();
    }

    @GetMapping("/{id}")
    @ApiOperation("获取某个分类信息")
    @ResponseBody
    public SaResult getById(@PathVariable Integer id) {
        Category category = novelCategoryService.getById(id);
        return  SaResult.data(category);
    }
    
}

页面完整代码

需要注意的问题

  1. 注意依赖引进

  2. 方法异步操作,特别是弹窗组件

  3. 数据项的ID,并不是每个都是id,根据实体数据来确认。

  4. 新增,编辑使用弹窗,控制弹窗的显示和关闭,$(‘xxx’).modal(‘show’), $(‘xxx’).modal(‘hide’)

  5. 基本通用,直接换接口名称就行。

<!doctype html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport"
    content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>表格演示</title>
  <link href="https://cdn.jsdelivr.net/npm/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet">
  <link href="https://cdn.jsdelivr.net/npm/bootstrap-table@1.22.3/dist/bootstrap-table.min.css" rel="stylesheet">

  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/bootstrap-table@1.22.3/dist/bootstrap-table.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/bootstrap-table@1.22.3/dist/locale/bootstrap-table-zh-CN.min.js"></script>
  <link href="https://cdn.jsdelivr.net/npm/bootstrap-icons/font/bootstrap-icons.css" rel="stylesheet">
  <script src="https://cdn.jsdelivr.net/npm/tableexport.jquery.plugin@1.28.0/tableExport.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>

  <style>
    .select,
    #locale {
      width: 100%;
    }

    .edit {
      margin-right: 10px;
    }
  </style>
</head>

<body>
  <!-- 新增弹窗 -->
  <!-- Modal Body -->
  <!-- if you want to close by clicking outside the modal, delete the last endpoint:data-bs-backdrop and data-bs-keyboard -->
  <div class="modal fade" id="addModal" tabindex="-1" data-bs-backdrop="static" data-bs-keyboard="false" role="dialog"
    aria-labelledby="modalTitleId" aria-hidden="true">
    <div class="modal-dialog modal-dialog-scrollable modal-dialog-centered modal-md" role="document">
      <form id="addForm">
        <div class="modal-content">
          <div class="modal-header">
            <h5 class="modal-title" id="modalTitleId">
              新增
            </h5>
            <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
          </div>
          <div class="modal-body">
            <div class="form-floating mb-3">
              <input type="text" class="form-control" name="categoryName" id="categoryName" placeholder="" />
              <label for="categoryName">Name</label>
            </div>

          </div>
          <div class="modal-footer">
            <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">
              关闭
            </button>
            <button type="reset" class="btn btn-outline-danger">清空</button>
            <button type="submit" class="btn btn-primary">保存</button>
          </div>
        </div>
      </form>
    </div>
  </div>

  <!-- 编辑弹窗 -->
  <!-- Modal Body -->
  <!-- if you want to close by clicking outside the modal, delete the last endpoint:data-bs-backdrop and data-bs-keyboard -->
  <div class="modal fade" id="editModal" tabindex="-1" data-bs-backdrop="static" data-bs-keyboard="false" role="dialog"
    aria-labelledby="modalTitleId" aria-hidden="true">
    <div class="modal-dialog modal-dialog-scrollable modal-dialog-centered modal-md" role="document">
      <form id="editForm">
        <div class="modal-content">
          <div class="modal-header">
            <h5 class="modal-title" id="modalTitleId">
              编辑
            </h5>
            <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
          </div>
          <div class="modal-body">
            <input type="hidden" name="categoryId">
            <div class="form-floating mb-3">
              <input type="text" class="form-control" name="categoryName" id="categoryName" placeholder="" />
              <label for="categoryName">Name</label>
            </div>
          </div>
          <div class="modal-footer">
            <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">
              关闭
            </button>
            <button type="reset" class="btn btn-outline-danger">清空</button>
            <button type="submit" class="btn btn-primary">保存</button>
          </div>
        </div>
      </form>
    </div>
  </div>



  <div class="container">
    <!-- 自定义工具栏 -->
    <div id="toolbar">
      <button id="add" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#addModal">
        <i class="bi bi-plus-square"></i> 新增
      </button>
      <button id="export" class="btn btn-success">
        <i class="bi bi-file-earmark-spreadsheet"></i> 导出
      </button>
      <button id="remove" class="btn btn-danger" disabled>
        <i class="bi bi-trash"></i> 批量删除
      </button>
    </div>
    <!-- 表格初始化 -->
    <table id="table" data-toolbar="#toolbar" data-search="true" data-show-refresh="true" data-show-toggle="true"
      data-show-fullscreen="true" data-show-columns="true" data-show-columns-toggle-all="true" data-detail-view="true"
      data-show-export="true" data-click-to-select="true" data-detail-formatter="detailFormatter"
      data-minimum-count-columns="2" data-show-pagination-switch="true" data-pagination="true" data-id-field="id"
      data-page-list="[5,10, 25, 50, 100, all]" data-show-footer="true" data-side-pagination="client"
      data-url="/novel-category/list" data-response-handler="responseHandler">
    </table>
  </div>


</body>
<script>
  // 获取组件
  var $table = $('#table')
  var $remove = $('#remove')
  var selections = []

  // 获取被选中行的ID
  function getIdSelections() {
    return $.map($table.bootstrapTable('getSelections'), function (row) {
      return row.categoryId
    })
  }

  // 处理远程响应的数据,可以指定要在表格显示的数据
  function responseHandler(res) {
    return res.data;
  }

  // 自定义显示样式
  function detailFormatter(index, row) {
    var html = []
    $.each(row, function (key, value) {
      html.push('<p><b>' + key + ':</b> ' + value + '</p>')
    })
    return html.join('')
  }

  function operateFormatter(value, row, index) {
    return [
      '<button type="button" class="btn btn-outline-primary edit btn-sm" title="编辑">',
      '<i class="bi bi-pencil"></i> 编辑',
      '</button> ',
      '<button type="button" class="btn btn-outline-danger remove btn-sm" title="删除">',
      '<i class="bi bi-trash"></i> 删除',
      '</button>'
    ].join('');
  }

  // 按钮点击事件
  window.operateEvents = {

    'click .edit': function (e, value, row, index) {
      // 弹窗编辑回显
      $.each(row, function (key, value) {
        $('#editForm input[name="' + key + '"]').val(value);
        // 如果表单字段是<input>标签之外的其他类型,也可以使用类似的方式进行赋值
      });
      $editModal.modal('show');
      // alert('You click edit action, row: ' + JSON.stringify(row))
    },

    // 移除
    'click .remove': async function (e, value, row, index) {
      if (await askDelete()) {
        // 从表格中移除选中的行
        remove(row.categoryId);
      }
    }
  }

  // 表格初始化
  function initTable() {

    $table.bootstrapTable('destroy').bootstrapTable({
      exportDataType: 'all',
      height: 550,
      locale: $('#locale').val(),
      columns: [
        [
          {
            field: 'state',
            checkbox: true,
            align: 'center',
            valign: 'middle'
          },
          {
            title: 'ID编号',
            field: 'categoryId',
            align: 'center',
            valign: 'middle',
            sortable: true,

          },
          {
            title: '分类名',
            field: 'categoryName',
            sortable: true,
            align: 'center'
          },
          {
            field: 'operate',
            title: '操作',
            align: 'center',
            clickToSelect: false,
            events: window.operateEvents,
            formatter: operateFormatter
          }
        ]
      ]
    })
    // 监听表格的选择事件,当表格中的行被选中或取消选中时触发
    $table.on('check.bs.table uncheck.bs.table ' +
      'check-all.bs.table uncheck-all.bs.table',
      function () {
        // 根据当前选中的行的数量来启用或禁用删除按钮
        $remove.prop('disabled', !$table.bootstrapTable('getSelections').length)

        // 保存你的数据,这里只保存当前页的数据
        selections = getIdSelections()
        console.log("当前选中:" + selections)
        // 如果你想要保存所有选中的数据,可以在这里使用 push 或 splice 方法
      })

    // 监听表格的所有事件,用于调试目的
    $table.on('all.bs.table', function (e, name, args) {
      // console.log(name, args)
    })

    // 点击删除按钮时执行的操作
    $remove.click(async function () {
      // 获取所有选中行的 ID
      var ids = getIdSelections()

      if (await askDelete()) {
        // 从表格中移除选中的行
        console.log("要删除的ids:" + ids)
        removeBatch(ids);
        // 禁用删除按钮
        $remove.prop('disabled', true)
      }
    })

  }

  // 绑定导出按钮点击事件
  $('#export').click(function () {
    $table.tableExport({
      type: 'excel', // 导出文件类型,可选 'csv', 'txt', 'sql', 'json', 'xml', 'excel', 'doc', 'png', 'pdf'
      escape: 'false' // 是否使用转义,默认为 true
    });
  });

  $(function () {
    initTable();
    $('#locale').change(initTable)
  })

  // 删除确认弹窗
  async function askDelete() {
    const result = await Swal.fire({
      title: "确定要删除它吗?",
      text: "删除后无法恢复!",
      icon: "warning",
      showCancelButton: true,
      confirmButtonColor: "#3085d6",
      cancelButtonColor: "#d33",
      confirmButtonText: "确定!"
    });

    return result.isConfirmed;
  }

  // 操作提示
  function mess() {
    Swal.fire({
      position: "top-end",
      icon: "success",
      title: "操作OK",
      showConfirmButton: false,
      timer: 1500
    });
  }

  var $addModal = $('#addModal');
  var $editModal = $('#editModal');

  // 新增
  $('#addForm').submit(function (event) {
    event.preventDefault();
    var data = $('#addForm').serialize();
    console.log(data);
    save(data)
    $addModal.modal('hide');
  })




  // 保存编辑
  $('#editForm').submit(function (event) {
    event.preventDefault();
    var data = $('#editForm').serialize();
    console.log(data);
    update(data);
    $editModal.modal('hide');
  })


  function save(data) {
    $.post("/novel-category/add", data, function (data) {
      if (data.code === 200) {
        mess();
        refresh();
      }
    })
  }

  function update(data) {
    $.post("/novel-category/update", data, function (data) {
      if (data.code === 200) {
        mess();
        refresh();
      }
    })
  }

  function remove(id) {
    $.get("/novel-category/delete/" + id, function (data) {
      if (data.code === 200) {
        refresh();
        mess();
      }
    })
  }

  function removeBatch(data) {
    $.get("/novel-category/deleteBatch?ids=" + data.join(','), function (data) {
      if (data.code === 200) {
        mess();
        refresh();
      }
    })
  }


  function refresh() {
    $table.bootstrapTable('refresh');
  }


</script>

</html>

注意数据的对接,特别是每行数据的id项,根据实际数据调整。

在这里插入图片描述

  • 28
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员-小李

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值