一、简介

时序图:

二、参数列表

参数名描述类型默认值条件
currentPage当前页数Integer非必须
pageSize一页数据数量Integer非必须

三、接口规范

[请求] /activity/find-list?currentPage=1&pageSize=10 GET
[响应]
{
"code": 200,
"data": {
"total": 10,
"records": [
{
"activityId": 23,
"activityName": "抽奖测试",
"description": "年会抽奖活动",
"valid": true
},
{
"activityId": 22,
"activityName": "抽奖测试",
"description": "年会抽奖活动",
"valid": true
},
{
"activityId": 21,
"activityName": "节⽇抽奖",
"description": "⽐特年会抽奖活动",
"valid": true
}
]
},
"msg": ""
}

四、Controller 层

com/yj/lottery_system/controller 包下 ActivityController类中:

  • 调用前面奖品列表展示的PageParam 分页查询的参数,作为参数
  • 调用service层,
  • convertTOFindActivityListResult:将service返回值转换为Controller层
  • 返回
@RequestMapping(" /activity/find-list")
public CommonResult<FindActivityListResult> findActivityList(PageParam param) {
  //日志打印
  log.info("findActivityList PageParam: {}", JacksonUtil.writeValueAsString(param));
  //调用service服务
  return CommonResult.success(convertTOFindActivityListResult( activityService.findActivityList(param)));
  }

4.1 FindActivityListResult:Controller层返回值

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

  • 根据接口规范中的响应数据返回:activityId,activityName,description,valid四个属性
package com.yj.lottery_system.controller.result;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
@Data
public class FindActivityListResult implements Serializable {
//活动总数
private Integer total;
//当前页活动列表
private List<FindActivityListResult.ActivityInfo> records;
  @Data
  public static class  ActivityInfo implements Serializable {
  //活动id
  private Long activityId;
  //活动名
  private String activityName;
  //活动描述
  private String description;
  //活动是否结束
  private Boolean valid;
  }
  }

4.2 convertTOFindActivityListResult:将service返回值转换为Controller层

com/yj/lottery_system/controller 包下 ActivityController类中:

  • 非空判断
  • 将service层返回值一一赋值给Controller层返回数据
private FindActivityListResult convertTOFindActivityListResult(PageListDTO<ActivityDTO> activityList) {
  if(null == activityList) {
  throw new ControllerException(ControllerErrorCodeConstants.FIND_ACTIVITY_LIST_ERROR);
  }
  FindActivityListResult findActivityListResult = new FindActivityListResult();
  findActivityListResult.setTotal(activityList.getTotal());
  findActivityListResult.setRecords(activityList.getRecords().stream()
  .map( activityDTO -> {
  FindActivityListResult.ActivityInfo activityInfo = new FindActivityListResult.ActivityInfo();
  activityInfo.setActivityId(activityDTO.getActivityId());
  activityInfo.setActivityName(activityDTO.getActivityName());
  activityInfo.setDescription(activityDTO.getDescription());
  activityInfo.setValid(activityDTO.valid());
  return activityInfo;
  }).collect(Collectors.toList())
  );
  return findActivityListResult;
  }

4.3 新增错误码

com/yj/lottery_system/common/errorcode 包下:ControllerErrorCodeConstants类中:

ErrorCode FIND_ACTIVITY_LIST_ERROR = new ErrorCode(301,"查询活动列表失败");

五、service层

5.1 创建接口

com/yj/lottery_system/service 包下:IActivityService接口类中:

/**
* 分页获取活动列表
* @param param
* @return
*/
PageListDTO<ActivityDTO> findActivityList(PageParam param);

5.2 实现接口

com/yj/lottery_system/service/impl 包下 ActivityServiceImpl类中:

  • 调用dao获取活动总数
  • 调用dao获取当前页活动列表
  • 将dao层返回数据,一一赋值给service返回数据
  • 返回
/**
* 分页获取活动基本信息列表
* @param param
* @return
*/
@Override
public PageListDTO<ActivityDTO> findActivityList(PageParam param) {
  //获取总量
  int total = activityMapper.count();
  //获取当前页活动列表
  int offset = (param.getCurrentPage() - 1) * param.getPageSize();
  List<ActivityDO> activityDOList = activityMapper.selectActivityList(offset,param.getPageSize());
    List<ActivityDTO> activityDTOList = activityDOList.stream()
      .map(activityDO -> {
      ActivityDTO activityDTO = new ActivityDTO();
      activityDTO.setActivityId(activityDO.getId());
      activityDTO.setActivityName(activityDO.getActivityName());
      activityDTO.setDescription(activityDO.getDescription());
      activityDTO.setStatus(ActivityStatusEnum.forName(activityDO.getStatus()));
      return activityDTO;
      }).collect(Collectors.toList());
      return new PageListDTO<>(total,activityDTOList);
        }

5.3 service层返回数据

com.yj.lottery_system.service.dto包下:

  • 根据返回值,设置四个属性
  • 并且与controller层对应,提供判断活动状态的 valid 方法。
package com.yj.lottery_system.service.dto;
import com.yj.lottery_system.service.enums.ActivityStatusEnum;
import lombok.Data;
import java.io.Serializable;
@Data
public class ActivityDTO implements Serializable {
//活动id
private Long activityId;
//活动名
private String activityName;
//活动描述
private String description;
//活动状态
private ActivityStatusEnum status;
//活动是否结束
public Boolean valid() {
return status.equals(ActivityStatusEnum.RUNNING);
}
}

六、dao层

com/yj/lottery_system/dao/mapper 包下 ActivityMapper:

/**
* 查询活动总数
* @return
*/
@Select("select count(1) from activity")
int count();
/**
* 查询当前页面的奖品列表
* @param offset
* @param pageSize
* @return
*/
@Select("select * from activity order by id desc limit ${offset}, #{pageSize}")
List<ActivityDO> selectActivityList(@Param("offset") Integer offset,
  @Param("pageSize") Integer pageSize);

七、测试

八、前端

static/activities-list.html:

<!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">
            <style>
              body {
              font-family: Arial, sans-serif;
              background-color: #f2f2f2;
              }
              .activity-list {
              padding:0 30px;
              }
              #activities{
              height: calc(100vh - 134px);
              overflow-y: auto;
              padding-right: 10px;
              }
              .activity-item {
              display: flex;
              align-items: center;
              justify-content: space-between;
              background-color: #f7f7f7;
              padding: 24px;
              border-radius: 4px;
              overflow: hidden;
              margin-bottom: 10px;
              border-radius: 8px;
              padding-bottom: 12px;
              }
              .activity-info{
              width: calc(100% - 120px);
              }
              .activity-info h4{
              width: 100%;
              font-weight: 600;
              font-size: 15px;
              color: #000000;
              margin-bottom: 4px;
              }
              .activity-info p{
              font-weight: 400;
              font-size: 14px;
              color: #666666;
              margin: 0;
              line-height: 28px;
              }
              .active a{
              font-weight: 400;
              font-size: 15px;
              color: red;
              margin-bottom: 0;
              display: block;
              width: 250px;
              }
              .inactive a{
              font-weight: 400;
              font-size: 15px;
              color: gray;
              margin-bottom: 0;
              display: block;
              width: 250px;
              }
              .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;
              }
              .activity-list h2 {
              font-weight: 600;
              font-size: 18px;
              color: #000000;
              height: 70px;
              display: flex;
              align-items: center;
              margin-bottom: 0;
              }
            </style>
          </head>
            <body style="background-color: white">
              <div class="activity-list">
            <h2>活动列表</h2>
                <div id="activities">
                <!-- 活动列表将动态插入这里 -->
                </div>
                  <div class="pagination">
                <button class="btn-outline-primary" onclick="fetchActivities(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="fetchActivities(totalPages)">尾页</button>
              </div>
            </div>
          <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
          <script src="./js/toastr.min.js"></script>
            <script>
              var currentPage = 1;
              var pageSize = 10;
              var totalPages;
              var userToken = localStorage.getItem("user_token");
              // 发送AJAX请求的函数
              function fetchActivities(page) {
              // 如果页码小于1,则重置为1
              if (page < 1) {
              page = 1;
              }
              // 更新当前页码
              currentPage = page;
              // 构建要发送的数据对象
              var dataToSend = {
              currentPage: currentPage,
              pageSize: pageSize
              };
              // 发送AJAX请求
              $.ajax({
              url: '/activity/find-list',
              type: 'GET',
              data: dataToSend, // 将分页参数作为请求数据发送
              dataType: 'json',
              headers: {
              // jwt
              "user_token": userToken
              },
              success: function(result) {
              if (result.code != 200) {
              alert("查询活动列表失败!" + result.msg);
              } else {
              var activities = result.data.records; // 假设返回的数据中活动列表字段为 'records'
              var activitiesHtml = '';
              var listContainer = document.getElementById('activities');
              // 在添加新内容前,先清空listContainer
              listContainer.innerHTML = '';
              activities.forEach(function(activity) {
              var url = 'draw.html?activityName='+ encodeURIComponent(activity.activityName)
              +'&activityId=' + encodeURIComponent(activity.activityId)
              +'&valid=' + encodeURIComponent(activity.valid);
            var linkTextActive = `<a href="${url}" target="_blank">活动进行中,去抽奖</a>`;
            var linkTextInactive = `<a href="${url}" target="_blank">活动已完成,查看中奖名单</a>`;
              var validClass = activity.valid ? 'active' : 'inactive';
              var link = activity.valid ? linkTextActive : linkTextInactive;
              activitiesHtml += `
              <div class="activity-item">
                <div class="activity-info">
                <h4>${activity.activityName}</h4>
                <p>${activity.description}</p>
              </div>
              <div class="${validClass}">
              <p>${link}</p>
            </div>
          </div>
          `;
          });
          $('#activities').html(activitiesHtml);
          // 更新分页控件的总页数
          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) {
          fetchActivities(currentPage - 1);
          } else {
          alert("已经是第一页");
          }
          }
          function nextPage() {
          if (currentPage < totalPages) {
          fetchActivities(currentPage + 1);
          } else {
          alert("已经是最后一页");
          }
          }
          $(document).ready(function() {
          fetchActivities(1);
          });
          // 绑定输入框回车事件
          $('#pageInput').on('keypress', function(e) {
          if (e.key === 'Enter') {
          var page = parseInt(this.value);
          if(page > totalPages){
          page = totalPages
          $('#pageInput').val(totalPages);
          }
          if (!isNaN(page) && page >= 1 && page <= totalPages) {
          fetchActivities(page);
          }
          }
          });
        </script>
      </body>
    </html>