【uni-app】银行卡卡包页面

3,854 阅读5分钟

什么需求?

实习工作的时候负责用 uni-app 做一个带积分提现功能的 h5。产品的原型设计里面,这部分的业务逻辑是:客户申请提现,工作人员在后台看见提现申请后再对银行卡进行对账打款。于是就需要有一个类似微信银行卡包的页面,UI 图是这样的:

这个页面特别简单,但有这么一点需要注意:卡片的颜色和logo需要根据不同的银行来与之相匹配。

解决问题的几种思路

看到这个需求,我的第一反应是:交给后端,让他们给颜色和logo。

(全剧终)

哈哈哈,并没有。这件事情要是交给后端来做的,其实工作量蛮大的。一是因为他们根据银行卡号来获取银行名称的接口也是网上找的代码,要是匹配银行主色调的话,太多银行了工作量未免会太大了一点。其次是Logo,他们倒是能返回logo,但是从UI图来看这个样式还是对logo有些要求的,最理想的是 1:1 的比例的Png,而后端能那边返回的logo太难看了,最基础的比例都不能保证,与上同理,要他们相对应匹配的话工作量太大,作罢。

这时候可能还有人说,可以交给 UI 出图,对应匹配出图就是了。但我觉得要是这么做的话太偷懒了,而且图片会产生比较大的静态资源,无论是放在前端或者后端都是一个负担。

第二个思路是,在网上找银行Logo资源放在前端这边(纯logo体积较小),得到接口返回的数据,根据银行名字或编号来匹配Logo,主色调的话,我想到用Canvas获取。简单来说就是把 Logo 图片绘制到 Canvas 元素上,再用Canvans的 getImageData 方法获取 rgba ,求平均值得到主色调。

有了上面的想法后,我去找后端要了银行名称的列表,看到一共有一百多个银行之后,我意识到我的想法还是过于单纯了——想将Logo和银行匹配,就要把Logo的名称改成银行名称,一个个匹配并且重命名,绝对是一种找虐的行为。

这样一来,想匹配所有的银行是不太可能了。出于以上业务限制,我决定只匹配一些常用的银行,一些比较少见的银行就不覆盖了,干脆用一种相同的样式代替,既然这样的话,Canvans 也不用了,主流银行不会太多,直接用取色器取底色,写进去就好了。这样一来既能满足绝大部分需求又能减少性能损耗

实现方法及效果

分析完需求,确定好如何做之后就简单了。

这个页面,基本数据只有一个关于用户银行卡的对象数组。给的数据很有限,因为银行名称标识不同银行,这里我就用银行名称来遍历判断。

(放在项目静态文件夹中的Logo)

bankIcon:[
				{
					bankName:'中国建设银行',
					icon:'../../../static/bankcard/bankLogo/中国建设银行.png',
					color:'background:#0066B3'
				},
				{
					bankName:'中国工商银行',
					icon:'../../../static/bankcard/bankLogo/中国工商银行.png',
					color:'background:#C7000A'
				},
				{
					bankName:'中国邮政储蓄银行',
					icon:'../../../static/bankcard/bankLogo/中国邮政储蓄银行.png',
					color:'background:#02724A'
				},
        {
					// 没有匹配到的银行的样式,要放到最后
					icon:'../../../static/bankcard/bankLogo/else.png',
					color:'background:#2b926c'
				}
        ]

在页面的data中定义这么一个对象数组,银行号用来识别,只要匹配得上就将图标和颜色(用取色器吸LOGO)的样式赋值给用户银行卡的对象数组。

推荐一个好用简洁的取色神器

如果银行卡名称没有在这些对象数组里面,就给其匹配最后一个通用样式的数组 — — 所以要新增适配的银行不能放在最后一个。

this.cardList.forEach((item)=>{
					this.bankIcon.forEach((item2,index)=>{
						if(item.bankName == item2.bankName){
							Object.assign(item,item2)
							return	
						}
						if(item.color) return
						if(index == this.bankIcon.length-1){
							Object.assign(item,item2)
						}
					})
				})

这里用的是 Object.assign 方法,这个方法会将第二个对象中,第一个对象不存在的KEY复制到第一个对象里。

搞定好数据,就是写样式的活了,这里没啥好说的,只有一点稍微要注意:就是右侧的背景,有淡淡的白色logo

我是这么解决的,给这个淡色Logo套一个 view 并让这个 view 相对外层的卡片绝对定位,且长宽写死(高度需和卡片高度一致,宽度则为logo的宽度,宽度需要比高度略大才好看),给一个 overflow: hidden ,这样就可以将里面的图片写大一点,超过这个高度就会会截掉一部分,比较美观。

那怎么把图片反白? 这里需要懂一点心思了,我用的是 filter:drop-shadow 属性,给图片一个白色的,透明度高的投影。然后给其一个向左的偏移值,需要和Logo的宽度一致。

这时候,因为Logo的盒子有hidden属性,所以是看不见这个白色投影的,很简单,让图片本体向右再偏移相同单位长度就ok了。

filter: drop-shadow(300rpx 0rpx rgba(255,255,255,0.1)); 
right: 300rpx;

写好样式,大功告成~

后言

这是我写的第一篇技术博客,涉及的内容很简单、很浅显,解决方法也不是很高级,但这里面的内容,是我作为一个初学者的探索,我觉得应该把它们记录下来、分享出来。这个过程,也让我明白开发中很多工作都是有束缚的,但要学会戴着镣铐跳舞,在有限的资源中思考解决问题的办法。

感谢你能看到最后。