【H5开发】03-手把手带你进步H5开发 - 共用一个接口的 单个提交vs批量提交功能

621 阅读3分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

这一节,已经整体做过两个页面,我们不会再把重点放在页面啦,是要关注js功能的实现。

首先我们看一下【批量提交】的功能效果图和接口设计

 可以看出,提交和批量提交共用一个接口,单独提交只需要“一份”数据,批量提交需要“数据数组”

解释一下功能:对于【单个提交】只需要填写“评分”点击提交,进行弹框确认即可,刷新页面,状态变为“已提交”,并且没有评分和提交按钮。对于【批量提交】需要进行评分,选中当前项,点击“批量提交”按钮,进行修改。


 1. 首先还是写数据列表,以及渲染页面效果。

  var datasTemp;
  // 批量提交辅助数组变量
  var tempList = [] ;
  var tempI = 0;
 //第一次进入页面,加载2021第二季度的数据。
  getList(year, jidu, bumen, gangwei, pageNum, pageSize);
 
  // 获取数据列表函数
  function getList(year, quarter,departmentId, jobPost, pageNum, pageSize) {
    console.log("getlist")
    $.ajax({
      type: "post",
      url: urlGlobal + "/api/assess/score/attendance/page",
      async: true,
      dataType: "json",//后台返回值类型
      contentType: "application/json;charset=utf-8", //如果提交的是json数据类型,则必须有此参数,表示提交的数据类型 
      async: false,//异步请求
      data: JSON.stringify({
        pageNum: pageNum,
        pageSize: pageSize,
        department: departmentId,
        jobPost: jobPost,
        year: year,
        quarter: quarter
      }),
      headers: { 'Authorization': 'Bearer ' + window.localStorage.getItem("token") },
      success: function (data) {
        if (data.code === 200) {
          var list = data.data.list
          console.log(list)
          //做分页的特殊处理
          total = data.data.totalCount; //总
          pades = data.data.totalPage; //总页数
          //isMore,当不是最后一页的时候,为ture,若是最后一页,则为false
          if (data.data.currPage < data.data.totalPage) {
            isMore = true;
          }
          if (data.data.currPage === data.data.totalPage) {
            isMore = false;
          }
          //如果总个数===0,做暂无数据的处理。
          if (data.data.totalCount == 0) {
            $("#allContent").empty();
            document.getElementById("piliang").style.display = "none"
            //$("#content_1").append("暂无内容");
          } else {
            var yCount = 0  //计算已提交的个数
            for (var i = 0; i < data.data.list.length; i++) {
              if(data.data.list[i].status == 1){
                yCount++
              }
              $("#allContent").append(strlistDom(data.data.list[i],i))
                // 添加数组信息
                tempI++;
              tempList.push({id: list[i].id, score:list[i].score, check: false, presetScore:list[i].presetScore})
            }
            //当前是最后一页的时候增加全部加载完毕的提示语
            if (data.data.currPage === data.data.totalPage) {
                $("#allContent").append("<div style='margin-top:0.2rem;margin-bottom:0.4rem;text-align:center;color: #999999;font-size:0.3rem;'>数据加载完毕</div>");
              }
            if(yCount === data.data.list.length){   // 全部已提交,不显示“批量提交”按钮
              document.getElementById("piliang").style.display = "none"
            }
          }
        }else {
          alertGlobal(data.message, 3000, true)
        }
      }
    });
  }

对于DOM元素渲染这里分了两种情况,其实是在对“已提交”“未提交”进行分别处理

  function strlistDom(data,i) {
    console.log(tempI)
    console.log("页面渲染开始")
    console.log(data)
    let status = data.status === 0 ? "待提交" : "已提交";
    console.log(status)
    var score = data.score ? data.score : 0;
    var str = "<div class='allDiv'>" +
      "<div class='divWrap'>" +
      "<div class='divLeft'>姓名</div>" +
      "<div class='divRight'>" + data.name + "</div></div><div class='hpVertical'></div>" +
      "<div class='divWrap'>" +
      "<div class='divLeft'>部门</div>" +
      "<div class='divRight'>" + data.department + "</div></div> <div class='hpVertical'></div>" +
      "<div class='divWrap'>" +
      "<div class='divLeft'>岗位</div>" +
      "<div class='divRight'>" + data.jobPostStr + "</div></div><div class='hpVertical'></div>" +
      "<div class='divWrap'>" +
      "<div class='divLeft'>考核类型</div>" +
      "<div class='divRight'>" + data.examineeTypeStr + "</div></div>" +
      "<div class='hpVertical'></div>" +
      "<div class='divWrap'>" +
      "<div class='divLeft'>分值</div>" +
      "<div class='divRight'>" + data.presetScore + "</div></div><div class='hpVertical'></div>" +
      "<div class='divWrap'>" +
      "<div class='divLeft'>状态</div>" +
      "<div class='divRightBlue'>" + status + "</div></div><div class='hpVertical'></div>"
      var extra1 = "<div class='divWrap'>" +
      "<div class='divLeft'>评分</div>" +
      "<div class='divRightBlue' >" + data.score + "</div></div><div class='hpVertical'></div>"
      var extra2 = "<div class='divWrap'>" +
      "<div class='divLeft'>评分</div>" +
      "<div class='divRightBlue' ><input class='input required' id='flag"+tempI+"' onchange='changeScore(\"" + data.id + "\",\"" + this + "\")' value='" + data.score + "'></div></div><div class='hpVertical'></div>" + //data-valid='isNonEmpty||onlyNum' data-error='请输入||请输入数字' 
      "<div class='divWrap' id='submit' style='justify-content: flex'><input class='sure' type='checkbox' id='checkbox' onchange='changeCheck(\"" + data.id + "\")''>" +
      "<div class='rate' onclick='pingfen(\"" + data.id + "\")'>提交</div></div></div>"
      if(status === '待提交'){
        // console.log('未提交')
        return str + extra2;
      }else{
        // console.log('已提交')
        return str + extra1;
      }
  }

  1. 接下来首先完成【单个提交】功能。在评分按钮写点击事件οnclick='pingfen(data.id)',其实主要功能就是简单的打开确认弹框。 但是考虑到每次提交需要向接口传入该条数据的id,以及评分,因此需要全局变量datasTemp保存id。
    datasTemp = id;
    $('#myModal').modal({show:true})
  }

对于弹框后的【确认】按钮,看似进行简单的拼接就可以实现接口的数据details,使用语句detail.push({ id: datasTemp, score: nowScore })  但后面我们就会发现稍有问题。我们后面再解决。

  function btnSure(i) {
    // 获取id和评分值
      var detail = [];
      var nowScore = parseInt($("#flag").val());
      detail.push({ id: datasTemp, score: nowScore })
      $.ajax({
        // 略。。。
        data: JSON.stringify({
          detail: detail
        }),
        // 略。。。
      });
    $('#myModal').modal('hide')
  }

需要注意的就是当完成提交后需要刷新页面,显示不同页面效果

  1. 然后实现【批量提交】功能。简单思路:对于复用的单一提交的接口,因此提交时把所有选中的行(每一整体的数据在pc端对应的就是一行数据,但在h5是一块数据,我们暂时也叫它一行)的id和score push到数组details里,使用相同接口即可完成。

难点(1)如何判断哪条(行)数据是选中的?答:根据checkbox来判断

难点(2)怎么区分那些有checkbox哪些没有呢?即哪些是直接不用做评分处理的

难点(3)checkbox是元素渲染上去的,如何拿到单独checkbox的true或false

难点(4)checkbox可以取消又选中 难道每次都要操作一次放进detail,不选中的时候再找出来删除吗?答:不用!用checkbox的onchange事件监听

综合了上述这么多问题,找到了解决方法。

详细思路: (1)每次页面加载时,拿到页面数据列表data,在每个元素被渲染(append)到页面之前,判断它是“已提交”还是“未提交”,对于未提交的数据重新放进一个数组中,包含id、score、check(是否选中)、preScore(用于分数比较)。这样在页面渲染完成之后就有了一个对象数组tempList,对应着每一个“未提交”的行。

for (var i = 0; i < data.data.list.length; i++) {
    if(data.data.list[i].status == 1){
          yCount++
    }
    $("#allContent").append(strlistDom(data.data.list[i],i))
    // 添加数组信息
    tempI++;
    tempList.push({id: list[i].id, score:list[i].score, check: false, presetScore:list[i].presetScore})
}

(2)对于每个元素的checkbox值的修改,我们复写onchange函数,在里面修改其状态即可

    for (var i = 0; i < tempList.length; i++) {
      if(tempList[i].id == id){
        tempList[i].check = (!tempList[i].check)
      }
    }
    console.log(tempList)
  }

完成这些后就可以知道哪些选中啦,并且也会对应修改tempList里面的check值,我们到时候遍历数组,找出check值为true的数组对象放入接口需要的detail数组就好啦。 但是detail数组中除了有id 还有 score,写下来就是怎么修改tempList中的score

(3)对于刚才单一提交中的parseInt($("#flag").val())好像用不了了,因为有很多flag了,这是需要在append 时区分一下。然后就正常写就好了,可以直接拿到分数了

  function allSubModal() {
    $('#allModal').modal({show:true})
    console.log("显示Modal")
  }
    console.log("批量提交") // datail(id score)
    var detail = [];
    for (var k = 0; k < tempList.length; k++) {
      if(tempList[k].check == true){
        // 如果是选中的,push到detail里面进行批量提交
        detail.push({ id: tempList[k].id, presetScore:tempList[k].presetScore, score: parseInt($("#flag"+ k).val())})
      }
    }
    var fz = 0  // 结果输入校验
    for(var m = 0; m < detail.length; m++){
      if(detail[m].score > detail[m].presetScore){
        fz = 1   // 有一个不符合就设置1
        alertGlobal("请检查!评分应小于分值", 3000, true)
        break;
      }
    }
    console.log(detail)
    if(fz = 0){    //全部符合输入条件
      // debugger
      $.ajax({
        type: "post",
        url: urlGlobal + "/api/assess/score/attendance/submit",
        async: true,
        dataType: "json",//后台返回值类型
        contentType: "application/json;charset=utf-8", //如果提交的是json数据类型,则必须有此参数,表示提交的数据类型 
        async: false,//异步请求
        data: JSON.stringify({
          detail: detail  // 包含id score
        }),
        headers: { 'Authorization': 'Bearer ' + window.localStorage.getItem("token") },
        success: function (data) {
          if (data.code === 200) {
            alertGlobal("提交成功", 3000, true)
          } else {
            alertGlobal(data.message, 3000, true)
          }
        }
      });
    }
    // 重置批量提交临时数组、变量
    tempList = [] ;
    tempI = 0;
    // 关闭modal
    $('#allModal').modal('hide')
  }

至此完成了批量提交。

但是还有几个小的注意点:每次提交之后需要清空临时数据以备下一次使用哦。