所有的光芒,都需要时间才能被看到
前情提要:
【H5开发】从一个简单页面带你体验H5开发 ~ 从静态页面到调接口手把手教学整个页面实现过程 https://blog.csdn.net/Sabrina_cc/article/details/119865234
【H5开发】02手把手带你开发H5列表页面 ~ 包含查询、重置、提交功能https://blog.csdn.net/Sabrina_cc/article/details/119888243
这一节,已经整体做过两个页面,我们不会再把重点放在页面啦,是要关注js功能的实现。
首先我们看一下【批量提交】的功能效果图和接口设计
可以看出,提交和批量提交共用一个接口,单独提交只需要“一份”数据,批量提交需要“数据数组”
解释一下功能:对于【单个提交】只需要填写“评分”点击提交,进行弹框确认即可,刷新页面,状态变为“已提交”,并且没有评分和提交按钮。对于【批量提交】需要进行评分,选中当前项,点击“批量提交”按钮,进行修改。
1. 首先还是写数据列表,以及渲染页面效果。
// 存储临时data数据
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元素渲染这里分了两种情况,其实是在对“已提交”“未提交”进行分别处理
// 渲染页面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;
}
}
2. 接下来首先完成【单个提交】功能。在评分按钮写点击事件οnclick='pingfen(data.id)',其实主要功能就是简单的打开确认弹框。 但是考虑到每次提交需要向接口传入该条数据的id,以及评分,因此需要全局变量datasTemp保存id。
function pingfen(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')
}
需要注意的就是当完成提交后需要刷新页面,显示不同页面效果
3. 然后实现【批量提交】功能。简单思路:对于复用的单一提交的接口,因此提交时把所有选中的行(每一整体的数据在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,对应着每一个“未提交”的行。
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})
}
(2)对于每个元素的checkbox值的修改,我们复写onchange函数,在里面修改其状态即可
<input class='sure' type='checkbox' id='checkbox' onchange='changeCheck(\"" + data.id + "\")''>
function changeCheck(id) {
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 时区分一下。然后就正常写就好了,可以直接拿到分数了
<input class='input required' id='flag"+tempI+"' value='" + data.score + "'>
// 批量提交
function allSubModal() {
$('#allModal').modal({show:true})
console.log("显示Modal")
}
function allSubmit() {
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')
}
至此完成了批量提交。
但是还有几个小的注意点:每次提交之后需要清空临时数据以备下一次使用哦。