最近被一个逻辑很恶心的项目折腾的死去活来,有必要在这里吐槽一下。因为我感觉到整个人都不好了,我都开始怀疑人生,怀疑智商了。
项目虐我千百遍,我带项目如初恋
这句话绝对是骗人的,上一张媳妇的玉手照,在这炎炎夏日清热解暑。
遇到问题还得解决,即使恶心,吐完了还是要继续的吃的。又不是SHI,没那么可怕的。
开始正题,先来看看需求。
说现在有一个页面,ios和安卓客户端还有微信内显示的内容不一样,页面内有一个下拉选择框,下拉选改变,页面中的内容也不一样,当然这样说太抽象了,上一张图看看。
嗯,问题就是上面这样了,上图中没有说明每种平台的充值面额和面额单位是不一样,这里就不说样式什么的也不一样了。
当然,这都是表象,所有复杂的问题,都是要慢慢解决,一个一个解决。首先是设备环境判断,这个很简单,网上有很多设备判断的代码段,我这里有一段。
//识别设备
var system = function(name) {
var u = navigator.userAgent.toLocaleLowerCase(),
system = {};
['mobile', 'iphone', 'android', 'micromessenger'].forEach(function(name) {
system[name] = new RegExp(name, 'g').test(u);
});
system.weixin = system.micromessenger;
return name === undefined ? system : system[name];
};
然后根据设备拉取不同的页面数据,因为上图中的下拉框和面额选这都是后台的数据,页面中的静态html其实很少。
if(system().weixin) { //微信内打开
$scope.weixin = true;
if(system().iphone) {
$scope.getPage("weixin");
$scope.ios = true;
} else {
document.body.innerHTML = "";
location.href = "http://www.youximao.tv/wap/index.html";
}
} else { //应用内打开
$scope.weixin = false;
if(system().iphone) { //iphone内打开
$scope.getPage("iphone");
$scope.ios = true;
} else {
$scope.getPage("android"); //android内打开
$scope.ios = false;
}
}
这样基本就解决了不同设备环境的数据匹配问题了,当然现在还有数据问题,我们先来看下后端过来的数据是什么样的。
{
"code": "000",
"data": {
"defChoose": 401,
"categoryList": [
{
"categoryName": "九游",
"categoryId": 401,
"categoryExt": {
"ctime": 1467788595,
"extName": "U点",
"goodsCategoryId": 401,
"isDelete": 1,
"prompt": "",
"proportion": 10,
"utime": 1467788595
},
"denominations": [
{
"ctime": 1467624031,
"denominationCategoryId": 401,
"denominationId": 6,
"goodsCategoryId": 12,
"goodsTypeId": 3,
"isDelete": 1,
"isEnable": 1,
"name": "50U点",
"num": 50.00,
"price": 48.00,
"utime": 1467683017
}, {
"ctime": 1467624440,
"denominationCategoryId": 401,
"denominationId": 7,
"goodsCategoryId": 11,
"goodsTypeId": 3,
"isDelete": 1,
"isEnable": 1,
"name": "30U点",
"num": 30.00,
"price": 30.00,
"utime": 1467684863
}
]
}
]
"catPoint": 4410
},
"message": "success"
}
上面的数据list基本都只取了一个值,这样的数据拿过来,其实是有点复杂的,我们需要从中间提取出有用数据,现在我应该比较庆幸选择angular来搭建这个页面了。
<div class="form-group margin-top-4">
<label class="form-lable" for="plat">充值平台</label>
<div class="select-warp" name="plat">
<select class="select" ng-model="plat" ng-options="plat as plat.categoryName for plat in page.categoryList" ng-change="changePlat()"></select>
</div>
</div>
<p class="message"><span ng-show="plat.categoryName == '百度'">代金券有效期7天</span</p>
这样看起来是不是很方便,当然还有一个百度平台的另类。
<!--baidu 选择百度的时候显示-->
<div class="baidu" ng-show="plat.categoryName == '百度'">
<div class="form-group">
<label class="form-lable">账号类型</label>
<div class="radio-type">
<input type="radio" name="type" value="1" ng-model="formData.type" />
<span>百度账号</span>
</div>
<div class="radio-type">
<input type="radio" name="type" value="2" ng-model="formData.type" />
<span>多酷账号</span>
</div>
</div>
<div class="form-group margin-top-4">
<label class="form-lable" for="game">游戏名称</label>
<div class="input-warp">
<input class="input" type="text" name="game" placeholder="请输入游戏名称" ng-model="formData.game" ng-blur="validateGame()" />
</div>
</div>
<p class="message"><span ng-show="showMsg.game">请输入游戏名称</span></p>
</div>
<!--/baidu-->
面额选择部分
<!--choose-warp-->
<div class="choose-warp">
<div class="choose">
<div class="radio-warp" ng-repeat="item in plat.denominations">
<input type="radio" name="denominationId" value="{{item.denominationId}}" ng-model="formData.denominationId" />
<button>{{item.num + plat.categoryExt.extName}}</button>
</div>
</div>
</div>
<!--/choose-warp-->
其实整个页面都是围绕着plat的选择,而变化的,所以js部分的逻辑只要围绕着plat的变化写就可以了。
$scope.changePlat = function() {
$scope.formData.account = ""; //重置表单
$scope.formData.game = ""; //重置表单
$scope.showMsg.paybtn = true;
//默认选择面额
$scope.formData.denominationId = $scope.plat.denominations[0].denominationId;
switch($scope.plat.categoryName) {
case "九游":
$scope.placeholder = "手机号或UC号";
$scope.validateAccount = validateNum;
break;
case "百度":
$scope.placeholder = "手机/邮箱/用户名";
$scope.validateAccount = validateLength;
break;
case "360":
$scope.placeholder = "邮箱";
$scope.validateAccount = validateEmail;
break;
case "腾讯":
$scope.placeholder = "QQ号码";
$scope.validateAccount = validateNum;
break;
default:
$scope.placeholder = "邮箱";
$scope.validateAccount = validateEmail;
break;
}
}
当然这里只是一部分功能的实现,关于支付按钮,弹出框的显示,按钮可否点击,不同设备显示不同的按钮等。
以上都是装X部分,给你们一点小彩蛋。
右侧开关按钮的纯css写法,input可以直接取值,配合angular很完美。
<div class="checkbox">
<input type="checkbox" name="remberAccount" ng-model="remberAccount" ng-change="isRember()" />
<span></span>
</div>
非常简单的页面结构,重要的部分是CSS
.checkbox {
width: .8rem;
height: .6rem;
position: relative;
}
.checkbox input {
position: absolute;
width: 100%;
height: 100%;
opacity: 0;
z-index: 10;
}
.checkbox span {
box-sizing: content-box;
position: absolute;
display: block;
width: .8rem;
height: .4rem;
top: .1rem;
border: 1px solid #EEE;
background: #FFF;
border-radius: .4rem;
-webkit-transition: all 0.3s ease-in-out;
transition: all 0.3s ease-in-out;
}
.checkbox input+span:after {
position: absolute;
box-sizing: border-box;
content: "";
right: .4rem;
width: .4rem;
height: .4rem;
border: 1px solid transparent;
box-shadow: 0 0 .05rem rgba(0, 0, 0, .5);
background: #FFF;
border-radius: .4rem;
-webkit-transition: all 0.3s ease-in-out;
transition: all 0.3s ease-in-out;
}
.checkbox input:checked+span {
background: #FFD800;
}
.checkbox input:checked+span:after {
right: 0;
}
感觉文章有点标题党,干货太少了,可能是懒了,也可能是很多方案是思路上的,代码不能不能表述,不过有问题还是希望可以找我一起探讨,如果喜欢就点个赞吧。