一、描述

支持翻頁

時序圖:

二、參數要求

參數名

描述

類型

默認值

條件

currentPage

在第幾頁

Integer


非必須

pageSize

一頁幾條數據

Integer


非必須

三、接口規範

[請求] /prize/find-list?currentPage=1&pageSize=10 GET
[響應] 
{
 "code": 200,
 "data": {
 "total": 3,
 "records": [
	 {
		 "prizeId": 17,
		 "prizeName": "吹⻛機",
		 "description": "吹⻛機",
		 "price": 100,
		 "imageUrl": "d11fa79c-9cfb-46b9-8fb6-3226ba1ff6d6.jpg"
	 },
	 {
		 "prizeId": 13,
		 "prizeName": "華為⼿機",
		 "description": "華為⼿機",
		 "price": 5000,
		 "imageUrl": "5a85034b-91b7-48fe-953d-67aef2bdcc2d.jpg"
	 },
	 {
		 "prizeId": 12,
	 	 "prizeName": "咖啡機",
	 	 "description": "家⽤咖啡機",
 			"price": 3000,
 			"imageUrl": "https://ts1.cn.mm.bing.net/th/id/RC.59493f741a4d956f354d241ec1034624?			rik=JpdNO%2bfC3NMONw&riu=http%3a%2f%2fcdn02.ehaier.com%2fproduct%2f5600fa6c1a0a2ebc278b47e8_1200_1200.jpg&ehk=8MptQ5r5ILWiL4v%2f5mn3s0%2f1H05r1yp%2fL6feezFw89Q%3d&risl=&pid=ImgRaw&r=0"
	}
 ]
 },
 "msg": ""
}

四、controller 層

com/yj/lottery_system/controller 包下 PrizeController方法實現

  • FindPrizeListResult 該方法controller層的返回值
  • PageParam 涉及翻頁的參數
  • 打印調用日誌
  • 調用service
  • 將service返回值與controller返回值進行轉換
@RequestMapping("/prize/find-list")
    public CommonResult<FindPrizeListResult> findPrizeList(PageParam param) {
        //日誌打印
        log.info("findPrizeList PageParam: {}", JacksonUtil.writeValueAsString(param));
        //調用service服務
        PageListDTO<PrizeDTO> prizeList = prizeService.findPrizeList(param);
        return CommonResult.success(convertTOFindPrizeListResult(prizeList));
    }

4.1 FindPrizeListResult:controller層的返回值

com.yj.lottery_system.controller.result 包下

  • 根據接口規範的響應內容,包含 total(當前獎品總數)和 records(當前獎品列表)
  • records中又包含: prizeId ,prizeName,description,imageUrl 四個內容
  • 將上面四個內容實現成內部類。

package com.yj.lottery_system.controller.result;

import lombok.Data;

import java.io.Serializable;
import java.math.BigDecimal;
import java.util.List;

@Data
public class FindPrizeListResult implements Serializable {
    //獎品總數
    private Integer total;
    //當前頁獎品
    private List<PrizeInfo> records;
    @Data
    public static class  PrizeInfo implements Serializable {
       //獎品id
        private Long prizeId;

        //獎品名
        private String prizeName;

        //獎品描述
        private String description;

        //圖片索引
        private String imageUrl;

        //獎品價值
        private BigDecimal price;

    }
}

4.2 PageParam controller 參數類

com.yj.lottery_system.controller.param 包下:

  • 根據接口規範請求,包含currentPage ,pageSize 兩個內容,給上默認值。
package com.yj.lottery_system.controller.param;

import lombok.Data;

import java.io.Serializable;

@Data
public class PageParam implements Serializable {
    //當前頁,默認1
    private Integer currentPage = 1;
    //當前頁數量,默認10
    private Integer pageSize = 10;
    //計算偏移量
    public Integer offset() {
        return  (currentPage-1) * pageSize;
    }
}

4.3 convertTOFindPrizeListResult :service返回值 轉換 controller 返回值

com/yj/lottery_system/controller 包下 PrizeController 類中:

  • 非空校驗
  • 將service的返回值,一一賦值給controller
private FindPrizeListResult convertTOFindPrizeListResult(PageListDTO<PrizeDTO> prizeList) {
        if(null == prizeList) {
            throw new ControllerException(ControllerErrorCodeConstants.FIND_PRIZE_LIST_ERROR);
        }
        FindPrizeListResult findPrizeListResult = new FindPrizeListResult();
        findPrizeListResult.setTotal(prizeList.getTotal());
        findPrizeListResult.setRecords(
                prizeList.getRecords().stream()
                        .map(prizeDTO -> {
                            FindPrizeListResult.PrizeInfo prizeInfo = new FindPrizeListResult.PrizeInfo();
                            prizeInfo.setPrizeName(prizeDTO.getName());
                            prizeInfo.setDescription(prizeDTO.getDescription());
                            prizeInfo.setPrizeId(prizeDTO.getPrizeId());
                            prizeInfo.setImageUrl(prizeDTO.getImageUrl());
                            prizeInfo.setPrice(prizeDTO.getPrice());
                            return prizeInfo;
                        }).collect(Collectors.toList())
        );
        return findPrizeListResult;
    }

4.4 controller 新增錯誤碼

com.yj.lottery_system.common.errorcode 包下 ControllerErrorCodeConstants

ErrorCode FIND_PRIZE_LIST_ERROR = new ErrorCode(200,"查詢獎品列表失敗");

五、 service層

5.1 創建接口

com.yj.lottery_system.service 包下 IPrizeService 類中

/**
     * 翻頁查詢列表
     * @param param
     * @return
     */
    PageListDTO<PrizeDTO> findPrizeList(PageParam param);

5.2 實現接口

com/yj/lottery_system/service/impl 包下 PrizeServiceImpl 類中:

  • 調用dao層的兩個SQL方法,在將dao的返回類型與service返回類型進行一一賦值即可。
@Override
    public PageListDTO<PrizeDTO> findPrizeList(PageParam param) {
        //總量
        int total = prizeMapper.count();
        //查詢當前頁列表
        List<PrizeDTO> prizeDTOList = new ArrayList<>();
        List<PrizeDO> prizeDOList = prizeMapper.selectPrizeList(param.offset(),param.getPageSize());
        for(PrizeDO prizeDO : prizeDOList) {
            PrizeDTO prizeDTO = new PrizeDTO();
            prizeDTO.setPrizeId(prizeDO.getId());
            prizeDTO.setDescription(prizeDO.getDescription());
            prizeDTO.setImageUrl(prizeDO.getImageUrl());
            prizeDTO.setName(prizeDO.getName());
            prizeDTO.setPrice(prizeDO.getPrice());
            prizeDTOList.add(prizeDTO);
        }
        return new PageListDTO<>(total,prizeDTOList);
    }

六、dao 層

com/yj/lottery_system/dao/mapper 包下 PrizeMapper類中:

  • 新增兩個查詢方法即可。
@Select("select count(1) from prize")
    int count();
    @Select("select * from prize order by id desc limit ${offset}, #{pageSize}")
    List<PrizeDO> selectPrizeList(@Param("offset") Integer offset,@Param("pageSize") Integer pageSize);

七、測試

八、 前端

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>獎品列表</title>
    <link rel="stylesheet" href="https://cdn.bootcdn.net/ajax/libs/bootstrap/4.5.2/css/bootstrap.min.css">
    <link rel="stylesheet" href="./css/base.css"></link>
    <style>
    body {
      font-family: Arial, sans-serif;
      padding: 0 30px;
    }
    table {
      /* height: calc(100vh - 143px); */
      height: 300px;
    }
    .table td, .table th{
      border: none;
    }
    .table thead th{
      background-color: #f7f7f7;
      border-bottom: none;
      font-weight: 600;
      font-size: 16px;
      color: #999999;
      height: 80px;
      line-height: 80px;
      padding: 0;
      position: sticky;
      top: 0px;
    }
    .table tbody+tbody{
      border-top: none;
    }
    .prize-table {
      width: 100%; /* 表格寬度為容器寬度的100% */
      height: 100vh;
      overflow-y: auto;
    }
    .prize-table h2{
      background: #fff;
      width: 100%;
      font-weight: 600;
      font-size: 18px;
      color: #000000;
      height: 70px;
      display: flex;
      align-items: center;
      margin-bottom: 0;
    }
    .table-box{
      height: calc(100vh - 140px);
      overflow-y: auto;
    }
    .prize-table th, .prize-table td {
        text-align: center;
        vertical-align: middle;
        padding: 10px;
        height: 50px; /* 統一設置表頭和單元格的高度 */
    }
    /* 第一列和第三列的樣式 */
    .prize-table th:first-child, .prize-table td:first-child,
    .prize-table th:nth-child(3), .prize-table td:nth-child(3),
    .prize-table th:nth-child(5), .prize-table td:nth-child(5) {
        width: 15%; /* 設置第一列和第三列的寬度為15% */
    }
    /* 第四列的樣式 */
    .prize-table th:nth-child(4), .prize-table td:nth-child(4) {
        width: 30%; /* 設置第四列的寬度為30% */
    }
    /* 其他列的樣式(例如第二列和第五列) */
    .prize-table th:nth-child(2), .prize-table td:nth-child(2) {
        width: 25%; /* 保持第二列和第五列的寬度為20% */
    }
    .prize-table th {
      /* 如果有特定的樣式只適用於表頭,可以在這裏添加 */
    }
    .prize-table td {
      height: 100px; /* 特定於單元格的高度設置 */
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
      max-width: 300px;
    }
    .prize-table img{
      width: 76px;
      height: 76px;
      border-radius: 8px;
      object-fit: scale-down;
      border:1px solid #e4e4e4;
    }
    .pagination {
      display: flex;
      justify-content: flex-end;
      margin-top: 18px;
      padding-right: 16px;
    }
    .pagination button {
      margin: 0 5px; /* 按鈕之間的間距保持不變 */
      border-radius: 5px; /* 設置圓角為20像素,可以根據需要調整 */
      border: 1px solid #007bff;
      background-color: #fff;
      padding: 0px 8px; /* 可以添加一些內邊距,使按鈕看起來更飽滿 */
      cursor: pointer; /* 將鼠標光標改為指針形狀,提升用户體驗 */
      font-size: 13px;
    }
    .pagination span{
      margin: 0 10px;
      font-size: 14px;
    }
    .pagination input{
      width: 80px;
      text-align: center;
    }
  </style>
</head>
<body>
<div class=" prize-table">
    <h2>獎品列表</h2>
    <div class="table-box">
      <table class="table">
        <thead>
        <tr>
            <th>獎品id</th>
            <th>獎品圖</th>
            <th>獎品名</th>
            <th>獎品描述</th>
            <th>獎品價值</th>
        </tr>
        </thead>
        <tbody>
        <tbody id="prizeList">
            <!-- 獎品列表將動態插入這裏 -->
        </tbody>
        </tbody>
      </table>
    </div>
    <div class="pagination">
        <button class="btn-outline-primary" onclick="fetchPrizes(1)">首頁</button>
        <button class="btn-outline-primary" onclick="previousPage()">上一頁</button>
        <span>第 <input type="number" id="pageInput" min="1" value="1" /> 頁</span>
        <button class="btn-outline-primary" onclick="nextPage()">下一頁</button>
        <button class="btn-outline-primary" onclick="fetchPrizes(totalPages)">尾頁</button>
    </div>
</div>


<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script>
    var userToken = localStorage.getItem("user_token");

    var currentPage = 1;
    var pageSize = 10;
    var totalPages;

    // 發送AJAX請求的函數
    function fetchPrizes(page) {
      console.log(page);
      // 如果頁碼小於1,則重置為1
      if (page < 1) {
        page = 1;
      }

      // 更新當前頁碼
      currentPage = page;

      // 構建要發送的數據對象
      var dataToSend = {
        currentPage: currentPage,
        pageSize: pageSize
      };

      // 發送AJAX請求
      $.ajax({
          url: '/prize/find-list',
          type: 'GET',
          data: dataToSend, // 將分頁參數作為請求數據發送
          headers: {
              // jwt
              "user_token": userToken
          },
          dataType: 'json', // 期望從服務器接收的數據類型是JSON
          success: function(result) {
            if (result.code != 200) {
                alert("查詢獎品列表失敗!" + result.msg);
            } else {
                var prizes = result.data.records;
                var prizesHtml = '';
                // 清空現有的表格內容
                var prizeList = $('#prizeList');
                prizeList.empty();
                prizes.forEach(function(prize) {
                    var imageUrl = prize.imageUrl ? prize.imageUrl : '/pic/defaultPrizeImg.png';
                    prizeList.append('<tr> ' +
                            '<td>' + prize.prizeId + '</td>' +
                            '<td><img src="' + imageUrl + '" alt="' + prize.prizeName + '" class="prize-image"></td>' +
                            '<td>' + prize.prizeName + '</td>' +
                            '<td>' + prize.description + '</td>' +
                            '<td>' + prize.price + '元</td>' +
                            '</tr>');
                });
                // 更新分頁控件的總頁數
                totalPages = Math.ceil(result.data.total / pageSize);
                // 更新輸入框的值
                $('#pageInput').val(currentPage);
              } // else end
          },
          error:function(err){
              console.log(err);
              if(err!=null && err.status==401){
                  alert("用户未登錄, 即將跳轉到登錄頁!");
                  // 跳轉登錄頁
                  window.location.href = "/blogin.html";
                  window.parent.location.href = "/blogin.html";//讓父頁面一起跳轉
              }
          }
      });
    }

    function previousPage() {
      if (currentPage > 1) {
        fetchPrizes(currentPage - 1);
      } else {
        alert("已經是第一頁");
      }
    }

    function nextPage() {
      if (currentPage < totalPages) {
        fetchPrizes(currentPage + 1);
      } else {
        alert("已經是最後一頁");
      }
    }

    $(document).ready(function() {
      fetchPrizes(1);
    });

    // 綁定輸入框回車事件
    $('#pageInput').on('keypress', function(e) {
      if (e.key === 'Enter') {
        var page = parseInt(this.value, 10);
        if (!isNaN(page) && page >= 1 && page <= totalPages) {
          fetchPrizes(page);
        }
      }
    });

</script>
</body>
</html>