spring cloud+vue在线视频网站 5.分页功能+增加章节

it2025-05-27  18

1 分页功能开发

首先集成分页功能需要先在 Maven 中添加 pagehelper 依赖,然后在 ChapterService 中添加 pagehelper 的设置,接着试一下分页功能是否生效。后面添加分页功能的具体细节,第一修改成后端接收分页要求,第二修改前端分页布局,第三修改前端请求。

1 添加依赖

首先在 course 的 pom.xml 文件中添加依赖和版本

<dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper-spring-boot-starter</artifactId> <version>1.2.10</version> </dependency>

然后在 service 模块中的 pom.xml 添加

<dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper-spring-boot-starter</artifactId> </dependency>

2 添加设置

在 ChapterService 的 list 类第一句添加PageHelper.startPage(1,1);即可,访问 http://127.0.0.1:9002/business/admin/chapter/list 即可看到只返回了一条记录。

1 添加后端 pageDto
package com.course.server.dto; import java.util.List; public class PageDto<T> { //当前页码 protected int page; //每页条数 protected int size; //总条数 protected long total; protected List<T> list; public long getTotal() { return total; } @Override public String toString() { return "PageDto{" + "page=" + page + ", size=" + size + ", total=" + total + ", list=" + list + '}'; } public List<T> getList() { return list; } public void setList(List<T> list) { this.list = list; } public void setTotal(long total) { this.total = total; } public int getPage() { return page; } public void setPage(int page) { this.page = page; } public int getSize() { return size; } public void setSize(int size) { this.size = size; } }
2 调整后端 Controller Service 层

这里调用后端查询的方法是,前端先传入分页的参数 page 和 size;接着后端先查询出结果,然后将结果传给 PageInfo 实例,实例对结果进行分页处理后再赋给 PageDto 返回前端。 修改 ChapterController 层代码如下:

package com.course.business.controller.admin; import com.course.server.dto.PageDto; import com.course.server.service.ChapterService; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; @RestController @RequestMapping("/admin/chapter") public class ChapterController { @Resource private ChapterService chapterService; @RequestMapping("/list") public PageDto list(@RequestBody PageDto pageDto){ chapterService.list(pageDto); return pageDto; } }

这里如果在 list 的传入函数中不加 @RequestBody 是接收不到传入的数据的。

ChapterService 代码如下:

package com.course.server.service; import com.course.server.domain.Chapter; import com.course.server.domain.ChapterExample; import com.course.server.dto.ChapterDto; import com.course.server.dto.PageDto; import com.course.server.mapper.ChapterMapper; import com.github.pagehelper.PageInfo; import org.springframework.beans.BeanUtils; import org.springframework.stereotype.Service; import javax.annotation.Resource; import java.util.ArrayList; import java.util.List; import com.github.pagehelper.PageHelper; @Service public class ChapterService { @Resource private ChapterMapper chapterMapper; public void list(PageDto pageDto){ PageHelper.startPage(pageDto.getPage(),pageDto.getSize()); ChapterExample chapterExample = new ChapterExample(); List<Chapter> chapterList = chapterMapper.selectByExample(chapterExample); PageInfo<Chapter> pageInfo = new PageInfo<>(chapterList); pageDto.setTotal(pageInfo.getTotal()); List<ChapterDto> chapterDtosList = new ArrayList<>(); for (int i = 0; i < chapterList.size(); i++) { Chapter chapter = chapterList.get(i); ChapterDto chapterDto = new ChapterDto(); BeanUtils.copyProperties(chapter,chapterDto); chapterDtosList.add(chapterDto); } pageDto.setList(chapterDtosList); } }
3 调整前端 chapter.vue

之前的 chapter 点击查询会直接返回所有结果,并不需要传给后端参数,所以直接用 get 请求。现在前端需要传递给后端 page 和 size 分页参数,所以需要用 post 请求,修改 method 中的 list 方法如下:

methods: { list(page) { let _this = this; console.log(page, _this.$refs.pagination.size), _this.$ajax.post('http://127.0.0.1:9000/business/admin/chapter/list',{ page: 1, size: 1 }).then((response)=>{ console.log(response); _this.chapters = response.data.list; }) } }

这时刷新会显示一条记录。

3 调整前端布局

这里添加了刷新按钮,和页面选择按钮。然后将 page 属性和选择的页面按钮绑定在一起,默认为1;将 size 属性和选择每页显示的数据条数绑定在一起,默认为10。 在 component 包中添加 pagination.vue 文件,代码如下:

<template> <div class="pagination" role="group" aria-label="分页"> <button type="button" class="btn btn-default btn-white btn-round" v-bind:disabled="page === 1" v-on:click="selectPage(1)"> 1 </button> <button type="button" class="btn btn-default btn-white btn-round" v-bind:disabled="page === 1" v-on:click="selectPage(page - 1)"> 上一页 </button> <button v-for="p in pages" v-bind:id="'page-' + p" type="button" class="btn btn-default btn-white btn-round" v-bind:class="{'btn-primary active':page == p}" v-on:click="selectPage(p)"> {{p}} </button> <button type="button" class="btn btn-default btn-white btn-round" v-bind:disabled="page === pageTotal" v-on:click="selectPage(page + 1)"> 下一页 </button> <button type="button" class="btn btn-default btn-white btn-round" v-bind:disabled="page === pageTotal" v-on:click="selectPage(pageTotal)"> {{pageTotal||1}} </button> &nbsp; <span class="m--padding-10"> 每页 <select v-model="size"> <option value="1">1</option> <option value="5">5</option> <option value="10">10</option> <option value="20">20</option> <option value="50">50</option> <option value="100">100</option> </select> 条,共【{{total}}】条 </span> </div> </template> <script> export default { name: 'pagination', props: { list: { type: Function, default: null }, itemCount: Number // 显示的页码数,比如总共有100页,只显示10页,其它用省略号表示 }, data: function () { return { total: 0, // 总行数 size: 10, // 每页条数 page: 0, // 当前页码 pageTotal: 0, // 总页数 pages: [], // 显示的页码数组 } }, methods: { /** * 渲染分页组件 * @param page * @param total */ render(page, total) { let _this = this; _this.page = page; _this.total = total; _this.pageTotal = Math.ceil(total / _this.size); _this.pages = _this.getPageItems(_this.pageTotal, page, _this.itemCount || 5); }, /** * 查询某一页 * @param page */ selectPage(page) { let _this = this; if (page < 1) { page = 1; } if (page > _this.pageTotal) { page = _this.pageTotal; } if (this.page !== page) { _this.page = page; if (_this.list) { _this.list(page); } } }, /** * 当前要显示在页面上的页码 * @param total * @param current * @param length * @returns {Array} */ getPageItems(total, current, length) { let items = []; if (length >= total) { for (let i = 1; i <= total; i++) { items.push(i); } } else { let base = 0; // 前移 if (current - 0 > Math.floor((length - 1) / 2)) { // 后移 base = Math.min(total, current - 0 + Math.ceil((length - 1) / 2)) - length; } for (let i = 1; i <= length; i++) { items.push(base + i); } } return items; } } } </script> <style scoped> .pagination { vertical-align: middle !important; font-size: 16px; margin-top: 0; margin-bottom: 10px; } .pagination button { margin-right: 5px; } .btn-primary.active { background-color: #2f7bba !important; border-color: #27689d !important; color: white !important; font-weight: 600; } /*.pagination select {*/ /*vertical-align: middle !important;*/ /*font-size: 16px;*/ /*margin-top: 0;*/ /*}*/ </style>

同时修改 chapter.vue 中 login 函数,添加 pagination 组件并显示,修改后代码如下:

<template> <div> <p> <button v-on:click="list(1)" class="btn btn-white btn-default btn-round"> <i class="ace-icon fa fa-refresh red2"></i> refresh </button> </p> <pagination ref="pagination" v-bind:list="list"></pagination> <table id="simple-table" class="table table-bordered table-hover"...> </div> </template> <script> import Pagination from "../../components/pagination"; export default { components:{ Pagination }, name: "chapter", data: function(){ return{ chapters:[] } }, mounted: function(){ let _this = this; _this.list(1); }, methods: { list(page) { let _this = this; console.log(page, _this.$refs.pagination.size), _this.$ajax.post('http://127.0.0.1:9000/business/admin/chapter/list',{ page: page, size: _this.$refs.pagination.size }).then((response)=>{ console.log(response); _this.chapters = response.data.list; _this.$refs.pagination.render(page, response.data.total) }) } } } </script>

这时可以选择页数刷新,成功显示出数据。

2 增加章节

下面我们增加一个增加章节的功能。首先需要在前端增加添加的页面,这里选择 bootstrap 中的表单和填出层,进行一些修改;然后在 chapter.vue 中增加 save 函数请求后端保存章节;最后在后端增加保存功能。

1 添加增加组件

有些组件可以直接去全局 CSS 样式复制了修改,这里用了模态框和表单的例子来修改。

表单修改后代码如下:

<div id="form-modal" class="modal fade" tabindex="-1" role="dialog"> <div class="modal-dialog" role="document"> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button> <h4 class="modal-title">表单</h4> </div> <div class="modal-body"> <form class="form-horizontal"> <div class="form-group"> <label class="col-sm-2 control-label">名称</label> <div class="col-sm-10"> <input v-model="chapter.name" class="form-control" placeholder="名称"> </div> </div> <div class="form-group"> <label class="col-sm-2 control-label">课程ID</label> <div class="col-sm-10"> <input v-model="chapter.courseId" class="form-control" placeholder="课程ID"> </div> </div> </form> </div> <div class="modal-footer"> <button type="button" class="btn btn-default" data-dismiss="modal">Close</button> <button type="button" v-on:click="save()" class="btn btn-primary">Save changes</button> </div> </div><!-- /.modal-content --> </div><!-- /.modal-dialog --> </div><!-- /.modal -->

同时在刷新按钮旁边新增一个 add 按钮。代码如下:

<button v-on:click="add()" class="btn btn-white btn-default btn-round"> <i class="ace-icon fa fa-edit red2"></i> add </button> &nbsp;

2 前端

点击 add 按钮时,模态框显示;点击 save 按钮后将表单数据传给后端,如果成功保存,则将页面关闭并显示第一页。

add() { $("#form-modal").modal("show"); }, save(page) { let _this = this; console.log(page); _this.$ajax.post('http://127.0.0.1:9000/business/admin/chapter/save',_this.chapter).then((response)=>{ console.log("保存大章结果",response); let res = response.data; if(res.success){ $("#form-modal").modal("hide"); _this.list(1); } }) }

3 后端添加

在 Controller 层和 Service 层添加 save 功能的对应代码。 Controller 层代码如下:

@RequestMapping("/save") public ChapterDto save(@RequestBody ChapterDto chapterDto){ chapterDto.setId(UuidUtil.getShortUuid()); chapterService.save(chapterDto); return chapterDto; }

Service 层代码如下:

public void save(ChapterDto chapterDto){ Chapter chapter = new Chapter(); BeanUtils.copyProperties(chapterDto,chapter); chapterMapper.insert(chapter); }

其中后端增加了工具类 CopyUtil 和 UuidUtil 类。CopyUtil 功能是复制实例内容到新的实例中,一般用在 domain 类和 dto 类转换。UuidUtil 功能是生成 8位 id,这里在 save 方法中用到了。

CopyUtil

package com.course.server.util; import org.springframework.beans.BeanUtils; import org.springframework.util.CollectionUtils; import java.util.ArrayList; import java.util.List; public class CopyUtil { public static <T> List<T> copyList(List source, Class<T> clazz) { List<T> target = new ArrayList<>(); if (!CollectionUtils.isEmpty(source)){ if (!CollectionUtils.isEmpty(source)){ for (Object c: source) { T obj = copy(c, clazz); target.add(obj); } } } return target; } public static <T> T copy(Object source, Class<T> clazz) { if (source == null) { return null; } T obj = null; try { obj = clazz.newInstance(); } catch (Exception e) { e.printStackTrace(); } BeanUtils.copyProperties(source, obj); return obj; } }

UuidUtil

package com.course.server.util; import java.util.UUID; public class UuidUtil { public static String[] chars = new String[] { "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" }; /** * 获取短UUID * @return */ public static String getShortUuid() { StringBuffer shortBuffer = new StringBuffer(); String uuid = UuidUtil.getUuid(); for (int i = 0; i < 8; i++) { String str = uuid.substring(i * 4, i * 4 + 4); int x = Integer.parseInt(str, 16); shortBuffer.append(chars[x % 0x3E]); // 对62取余 } return shortBuffer.toString(); } /** * 获得32位UUID */ public static String getUuid(){ String uuid = UUID.randomUUID().toString(); //去掉“-”符号 return uuid.replaceAll("-", ""); } public static void main(String[] args) { System.out.println(getUuid()); } }

同时,为了前后端数据交互数据的统一,新增了一个 responsedto 类。

package com.course.server.dto; public class ResponseDto<T> { /** * 业务上的成功或失败 */ private boolean success = true; /** * 返回码 */ private String code; /** * 返回信息 */ private String message; /** * 返回泛型数据,自定义类型 */ private T content; public String getCode() { return code; } public void setCode(String code) { this.code = code; } public boolean getSuccess() { return success; } public void setSuccess(boolean success) { this.success = success; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } public T getContent() { return content; } public void setContent(T content) { this.content = content; } @Override public String toString() { final StringBuffer sb = new StringBuffer("ResponseDto{"); sb.append("success=").append(success); sb.append(", code='").append(code).append('\''); sb.append(", message='").append(message).append('\''); sb.append(", content=").append(content); sb.append('}'); return sb.toString(); } }

这里将 Controller 层的返回统一改为 ResponseDto 类型,代码如下:

package com.course.business.controller.admin; import com.course.server.dto.ChapterDto; import com.course.server.dto.PageDto; import com.course.server.dto.ResponseDto; import com.course.server.service.ChapterService; import com.course.server.util.UuidUtil; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; @RestController @RequestMapping("/admin/chapter") public class ChapterController { @Resource private ChapterService chapterService; @RequestMapping("/list") public ResponseDto list(@RequestBody PageDto pageDto){ chapterService.list(pageDto); ResponseDto responseDto = new ResponseDto(); responseDto.setContent(pageDto); return responseDto; } @RequestMapping("/save") public ResponseDto save(@RequestBody ChapterDto chapterDto){ chapterDto.setId(UuidUtil.getShortUuid()); chapterService.save(chapterDto); ResponseDto responseDto = new ResponseDto(); responseDto.setContent(chapterDto); return responseDto; } }

总结

以上就完成了分页功能和增加章节功能的增加,并且将工具类封装在一起,还统一了后端返回给前端的数据类型。

最新回复(0)