HTML+CSS+JS对话式实战(5)-活动管理页之查看报名名单的实现

点此查看 所有教程、项目、源码导航

文章目录

  • [1. 本篇任务说明](#1. 本篇任务说明)
  • [2. 接口约定](#2. 接口约定)
  • [3. HTML 修改](#3. HTML 修改)
  • [4. 编写 JS 逻辑](#4. 编写 JS 逻辑)
  • [5. 测试流程](#5. 测试流程)
  • [6. 效果查看](#6. 效果查看)

1. 本篇任务说明

毛哥:副队,活动的增删改查我们都写完啦,现在是不是该做报名名单了?

副队:没错。一个活动发布出去之后,学生可以报名,管理员需要点开活动,查看这条活动下面所有报名人的信息。这一节我们就实现查看报名名单功能。

毛哥:那这个接口怎么设计?也是 POST 对吧?

副队:对,咱们项目约定全部使用 POST。调用这个接口的时候,把活动 id 传给后端,后端根据活动 id,去报名表里查出所有关联的报名记录,最后用统一格式返回:{code, msg, data}。

毛哥:又是这个返回格式!我现在越来越熟悉了,成功的时候 code 为 200,data 里面放报名数组;失败的时候 code 不是 200,msg 告诉我们失败原因。

副队:理解到位。报名名单我们单独用一个弹窗展示,不和之前新增、编辑活动的弹窗混在一起,逻辑会更清爽。

2. 接口约定

副队:先把接口信息整理成表格,方便后面写代码对照。

项目 内容
请求方式 POST
请求地址 /activity/getSignList
请求参数 activityId:活动编号
返回格式 {code, msg, data}
data 报名对象数组,每个报名对象包含:报名 id、活动 id、活动名称、学生姓名、学号、联系方式、报名时间

示例返回 JSON:

js 复制代码
{
  "code": 200,
  "msg": "查询报名名单成功",
  "data": [
    {
      "id": 1,
      "activityId": 10,
      "activityName": "春日户外拓展活动",
      "studentName": "张三",
      "studentNo": "2025001001",
      "phone": "13800138000",
      "signTime": "2026-11-06 16:20:10"
    },
    {
      "id": 2,
      "activityId": 10,
      "activityName": "春日户外拓展活动",
      "studentName": "李四",
      "studentNo": "2025001002",
      "phone": "13900139000",
      "signTime": "2026-11-06 17:05:33"
    }
  ]
}

毛哥:如果这个活动还没有人报名呢?

副队:后端会正常返回 code=200,data 就是一个空数组,前端拿到之后渲染一个提示:暂无报名人员,这样就不用单独处理异常。

副队:当然,现在咱们还没开发学生报名的页面,我临时在数据库里面给你放一些数据方便你测试就行。

3. HTML 修改

副队:我们先改 activity-manage.html,两件事情:第一,在表格每一行新增一个【查看报名】按钮;第二,新增一个弹窗,用来展示报名名单。

找到getActivityList函数里面,生成操作按钮区域,确认已经有查看报名的按钮:

在页面弹窗区域,新增报名名单弹窗:

html 复制代码
<!-- 查看报名名单弹窗 -->
  <div class="mask" id="listMask">
    <div class="dialog">
      <h3>报名名单</h3>
      <table class="common-table">
        <thead>
          <tr>
            <th>报名编号</th>
            <th>活动编号</th>
            <th>活动名称</th>
            <th>姓名</th>
            <th>学号</th>
            <th>手机号</th>
            <th>报名时间</th>
          </tr>
        </thead>
        <tbody id="signTableBody">
          <!-- JS 动态渲染报名数据 -->
        </tbody>
      </table>
      <div id="signEmptyTip" style="text-align:center; padding:20px; display:none;">暂无报名人员</div>
      <div class="dialog-footer">
        <button class="close" onclick="closeSignMask()">关闭</button>
      </div>
    </div>
  </div>

毛哥:这个弹窗和编辑弹窗结构很像,公共样式是不是可以直接复用?

副队:没错,弹窗、表格、按钮的样式都写在公共 CSS,这里只需要新增少量独立样式,如果后面需要微调这个弹窗独有的效果,再写到 activity-manage.css。

4. 编写 JS 逻辑

副队:通用 postRequest 我们之前已经封装好了,直接拿来调用接口。我们需要这几个函数:打开报名弹窗、关闭弹窗、加载报名列表、渲染表格。

在 activity-manage.js 追加下面代码:

js 复制代码
/**
 * 打开报名名单弹窗
 * @param {number} activityId 活动id
 */
function viewNameList(activityId) {
    // 保存当前查看的活动 id
    window.currentSignActivityId = activityId;
    // 清空旧数据
    document.getElementById("signTableBody").innerHTML = "";
    document.getElementById("signEmptyTip").style.display = "none";
    // 请求报名列表
    postRequest("/activity/getSignList", {
        activityId: activityId
    }, function (res) {
        if (res.code === 200) {
            renderSignList(res.data);
        } else {
            alert(res.msg);
        }
    });
    // 显示弹窗
    document.getElementById("listMask").classList.add('show');
}

/**
 * 关闭报名名单弹窗
 */
function closeSignMask() {
    document.getElementById("listMask").classList.remove('show');
}

/**
 * 渲染报名名单表格
 * @param {Array} list 报名数组
 */
function renderSignList(list) {
  const tbody = document.getElementById("signTableBody");
  const emptyTip = document.getElementById("signEmptyTip");
  if (list.length === 0) {
    emptyTip.style.display = "block";
    return;
  }
  emptyTip.style.display = "none";
  let html = "";
  list.forEach(function (item) {
    html += `
      <tr>
        <td>${item.id}</td>
        <td>${item.activityId}</td>
        <td>${item.activityName}</td>
        <td>${item.studentName}</td>
        <td>${item.studentNo}</td>
        <td>${item.phone}</td>
        <td>${item.signTime}</td>
      </tr>
    `;
  });
  tbody.innerHTML = html;
}

毛哥:副队,我看懂了!点击按钮先拿到活动 id,调用通用 postRequest,后端返回数据,如果成功就交给渲染函数;数组为空就展示提示文字。

副队:是的,而且我们把弹窗显示隐藏,和数据加载分开,逻辑清晰。如果以后想要增加导出报名名单,也是在这个基础上继续扩展。

毛哥,我还有一个疑问,为啥viewNameList函数传递的参数是activityId,而在之前的活动编辑时,我们传递的是id。

副队:观察的很细心嘛,这问题首先要说明一点,具体传什么是前后端约定好的,此处实际上如果后端实现采用id的话,也可以传id;那为啥使用activityId更好呢,因为现在是报名这个数据领域,这个领域的id应该是报名的序号,活动id的话是指向活动这个概念的。哎呀,总之这个问题还是偏后端一点啦,你现在记住就是按约定好的去传参数就OK了。

5. 测试流程

副队:写完代码之后,我们按这个顺序测试一遍。

  1. 打开活动管理页面,加载活动列表;
  2. 挑选一条已经有报名的活动,点击【查看报名】;
  3. 弹窗弹出,表格展示所有报名学生;
  4. 挑选一条没有报名的活动,点击按钮,出现"暂无报名人员";
  5. 如果后端报错,弹出提示信息。
    毛哥:太棒啦!管理员现在就可以看到谁报名了活动。

6. 效果查看

此时点击报名名单,显示当前活动的报名人员:

弹窗宽度有点小了,调整css如下:

css 复制代码
  .dialog {
    width: 420px;                           /* 弹窗内容盒子固定宽度,调整为720px */
    background: #fff;                       /* 弹窗白色背景 */
    padding: 20px;                          /* 弹窗内部边距 */
    border-radius: 6px;                     /* 弹窗圆角 */
  }

在此打开,效果如下:

至此,活动管理页面功能全部完成。

相关推荐
曦樂~27 分钟前
【Web Development】02 CSS
前端·css
东鹏特饮1 小时前
经典打砖块(Breakout)游戏
前端·css·css3
新*3 小时前
从一段 WebSocket 代码聊开:bytes 不是 zlib、binaryType 决定一切,15MB 大消息的零拷贝优化
javascript·python·websocket·性能优化·blob·zlib·arraybuffer
OpsEye4 小时前
别再挨个充会员了:多模型编码,最麻烦的从来不是选模型
javascript·ai编程
学以智用5 小时前
jsencrypt.js 完整详解
javascript
Hilaku8 小时前
你们公司有 35 岁以上的前端吗?
前端·javascript·程序员
鸿蒙开发8 小时前
小程序存档写到一半怎么办?双槽保存与损坏恢复实战
前端·javascript·react.js
知忆_IS9 小时前
TerriaMap 开发实战04:MVT数据自定义符号化 - terriajs源码修改
javascript·webgis·terriamap·terriajs
reasonsummer9 小时前
【教学类-150-03】20261108蝴蝶连连看html(一页2个版面、3个版面)
python·html