一个简单H5投票页面的踩坑记录

一个简单H5投票页面的踩坑记录

前端时间公司要做一个投票相关的传统H5页面,要求对于每组投票要有限制,但又不能完全限制。听到这里我就懵逼了,这怎么做呢。最后制定的规则是:每人每天只能投10票。感觉好像这样的功能都在后端,前端只需要处理用户的操作逻辑就ok了。最后证明自己很傻很天真!

魔怔开启

后端同学说需求方不需要用户登录,你直接Cookie存一下就可以了。开始我以为是让我把Cookie附带传给他呢,就因为这最后接口写好后发现他的意思是我在前端存储这些信息!!!既然这样,没办法就自己吭哧吭哧搞呗。

重新梳理需求&制定方案

既然要存储数据,那就从头至尾重新梳理下需求:
1.不需要用户登录,要求每个人限投10票(其实只有用设备来识别)
2.投完票后再次进入页面要显示“已投票”
3.奖项列表页和公司详情页投票有关联性
基于以上的需求,以及后端同学给的数据结构。拟定的前端存储的数据结构
后端给的数据结构是这样的

奖项投票数据

{
    "reward_name": "奖项7",
    "reward_id": 1222,
    "votes_count": 10, #  可投票的候选数
    "candidates": [
        [
            "产品68",  # 公司名称
            "16856",   # candidate_id
            "23" # 投票数
        ],
        [
            "公司67",
            "16854",
            "1"
        ],
        [
            "产品66",
            "16852",
            "4252"
        ]
     ]
}

公司详情投票

{
    "candidate_id": 16894,
    "rewards": [
        [
            "2017最受机构青睐私募基金公司·股票型",   #奖项名称
            "77",                               #奖项ID
            "0",                                #奖项可参与投票的公司数量,为0时,不可投票
            "32"                                # 被投票数
        ]
    ],
    "products": [
        {
            "name": "兴业信托•朱雀18期",
            "candidate_id": 16900,
            "rewards": [
                [
                    "2017最具人气私募基金·股票型(三年期)",
                    "80",
                    "10",                       # 结构及其含义 同上
                    "32"                        # 被投票数
                ]
            ]
        }
    ],
    "candidate_name": "上海朱雀资产管理公司"
}

说实话,这样的数据结构在我看来相当不友好。要不是后端同学当面说明真是完全不知所以,沟通了一下发现需求方给的数据更加扯淡,最后能抽象成这样已经很不错了。没办法,既然接口好了,那就将就一下吧。
想了想如果用Cookie的话,对于简单的数据结构还可以。但是显然这这里不太适合,因为最后的这数据结构不可能太简单。我设计的前端数据存储结构是这样:

{
	"rewards_id": 23, //奖项id
  "count": 10, //可投票数
  "candidates":[45, 34, 44, 32] //已投公司
}

这样的话准备用localStorage来进行存储,但是明天怎么清空本地存储记录呢。那同样存个时间戳,每次登陆的时候去检测是否超过一天,如果超过就全部清空本地存储。看来这样可行。
每次投完票,就去遍历localstore。查看rewards_id是否存在,存在则去检索其中的candidates是否有id,没有就加进去,票数-1,发送请求。否则就return false
代码如下

	//投票操作
  $('.presents-box').on('click', '.js-vote', function() {
  	var that = $(this);
    var rewards_id = that.parents().parents().parents().attr('reward_id');
  	var candidates_id = that.attr('candidates_id');
    var flag = true;

    localArr = JSON.parse(localStorage.getItem('presents'));
    if(localArr != null) {
      for(var i in localArr) {
        if(localArr[i].rewards_id == rewards_id) {
          if(localArr[i].count > 0) {
            localArr[i].candidates.push(candidates_id);
            localArr[i].count -= 1;
            localStorage.setItem('presents', JSON.stringify(localArr));
          } else {
            alert('您已不能再投票!');
            return false;
          }
          flag = false;
        }
      }
      if(flag) {console.log((parseInt($('.detail-votes').attr('count')) - 1))
        var obj = {
          rewards_id: parseInt(rewards_id),
          count: (parseInt($('.detail-votes').attr('count')) - 1),
          candidates:[candidates_id]
        };
        localArr.push(obj);
        localStorage.setItem('presents', JSON.stringify(localArr));
      }
    }

  	//投票请求
  	$.ajax({
  		type: 'post',
  		url: 'http://www.nbd.com.cn/activity/jdj2/votes?reward_id='+rewards_id+'&candidate_id='+candidates_id,
  		success: function(res) {
  			that.parents().parents().addClass('voted');
        that.removeClass('js-vote');
        that.text('已投票');
  		}
  	});
  });

重刷新要显示已投结果,就用上面存储的本地数据去操作dom。这样需求就基本实现了,收工。
投票后的结果如图,
投票后结果

刷新后结果不变,跳转到公司详情页的投票页,已投也会显示。如图,
投票后结果

开始踩坑

第一脚坑

这样测试了几个数据,没什么问题。但当真是数据上去之后就出现了问题,投票好像老是不对。开始快速查原因,从逻辑开始,好像逻辑没有问题,只有一步一步打印结果。最后发现这个坑是我自己造成的
代码

代码

就是字段的名字给写错了,真是自己的坑自己填。

第二脚坑

在安卓上没有任何问题,当在ios上记录存储数据好像就有些问题了,刷新后不能记录。一开始我以为是平台差异性,在操作dom上会有些许差异。然后真机测试发现没有问题。那是怎么回事呢?设备上不好调试,但这种现象又只出现在真机设备上。之后copy一份在真机上调试打印数据,一点一点排查最终发现问题所在。
代码

oldTime是存储的本地时间,当第一次时localStorage是null,并且在iOS上是string。而在Android上是null,所以在Android上没问题,在iOS上每次都是true。所以都会清除掉存储的本地数据。然后就做了如下修改,

var arr = JSON.parse(localStorage.getItem('presents')),
    nowTime = nowTime = new Date().getDate(),
    oldTime = JSON.parse(localStorage.getItem('time')),
    newArr = [];

//iOS上
oldTime = !!(navigator.userAgent).match(/\(i[^;]+;( U;)? CPU.+Mac OS X/) && (oldTime == 'null') ? null : oldTime;

//固定时间间隔清除localStorage
if(Math.abs(nowTime - oldTime) >= 1 || oldTime == null ) {
  localStorage.clear();
  arr = JSON.parse(localStorage.getItem('presents'));
}

其实说坑也算不上很大,但是遇到的时候也是蛮坑人的。还有就是写代码变量名一定要明晰,造成不必要的麻烦。

posted @ 2017-09-20 16:25  marvine  阅读(4666)  评论(0编辑  收藏  举报