真正的大学生都是在ddl前完成任务的,对于项目的思考在前几天就开始了,不过也是选择到现在来小组内交流项目题目,有什么二手交易平台啊,网络教育啥的。
激烈的讨论了半小时之后选择了一个校园互助平台,在我想法里面,也就是类似美团跑腿(其实这个我也没用过来着,按字面意思来理解的)之类的,不过对于任务的内容更加宽泛,可以是什么求组队、求教题什么的,万物皆可是任务?大概这种感觉吧。
话说因为我们有一个成员去上课了,所以无法参与到PPT的制作当中,最后就把答辩的光荣使命交付给他了。
以前都不知道还有开题答辩这种东西,真正开始的时候都不知道应该讲哪些方面,毕竟我们的项目还只是一个构思而已,最后还是借鉴网上的回答,选择了四个方面:
1.立项背景与意义
2.初步方案设计
3.创新性
4.预期成果
按理说创新性就是我们的重点了,毕竟即便是我们校区里面还没有类似的APP什么的,但是想法也算不上很新,果然也就只能说是一些算法创新了吧,不过也确实,因为我们是要自己写一些推荐、估价之类的算法的。
我负责写初步方案设计,基本就只是将系统拆分了一下,然后大概讲了一下各自的作用,最后说了一下要使用的技术,感觉项目都还没开始,好像也没啥东西讲。
越来越感觉自己再写日记了,话说我也不知道这个博客开了能写啥,说是要检查进度。
上完课吃完午饭,急冲冲的跑去答辩,好家伙,还是有点人的。按照答辩次序的话我们是最后几组,先是听了前面人的项目,不得了不得了,我直呼斯巴拉西,突然就感觉我们这项目有些弱鸡。
完了,日活300,这是个什么鬼要求,我们年级一共350个人,直接炸裂,说实在有点退堂鼓了。
因为各种过程,最后还是决定开始实现了。
其实刚开始是打算做一个web项目的,但是考虑到日活的要求(后来改成交易量了,其实好像也没简单多少,起码还是有点信心做下去了),所以应该是要做一个微信小程序,又要开始学习新技术了,起飞。
今天主要是初步讨论了一下小程序的功能需求,考虑到任务发布人和接取人之间应当需要有一个交流,但是微信小程序似乎也没有提供这样一个接口,所以我们需要自己实现,这就表示需要完成一个聊天功能。
但是我们之前并没有实现过类似服务器主动向客户端发送信息的功能,所以在这个方面有些迷茫,然后是又想出另外一个方法,就是用留言回复功能代替聊天,将留言回复分为私密和公共,考虑到被接取的任务是要移出可接取列表的,如果这个时候用户之间还需要交流,就只能是再为每个用户再创建一个当前正在进行的任务列表,然后在里面留言回复,这么一想反而更加麻烦了。
最后是突然想起以前看过的一个websocket协议,能够用来实现客户端和服务端之间的全双工通讯,略微尝试之后发现还算简单,所以最终就定下来要实现聊天功能了。
然后还是讨论了一些基本的功能需求,近两天完成《功能需求规格书》之后,就要正式开始项目设计了。
今天功能需求规格书就算基本完成了,还有一些细节上的问题可以在实现过程当中边修改。
今天我们主要是讨论了三个问题:
1.关于如何给用户推荐任务。刚开始我的想法是获取用户当前的地点,然后给他推荐他周围的任务,但是另外一位组员不认同,他觉得用户所处地点不是那么有用,就比如说要是用户当前在宿舍,但是他准备去食堂,想看看有没有带饭的任务,但是我们就会很难说是给用户推荐什么任务,相反,我们可以事先划出一些区域,当用户处于这些区域的时候,我们就给他推荐这些区域的任务,还有就是在不同地点区域,地点值在推荐算法中的比重也是不同的,想来确实如此,所以我们应该是会运用这个方案,在后期实现的时候在做一些细节上的修改和完善。
2.关于任务完成判断的问题。这就是一个很复杂的事情了,只要我们一往一些极端的方面思考,就会发现我们当前很难实现这个事情,所以我们只能说是基于我们学院同学基本友好的基础上去讨论,这样我们就可以处理一些中间可能会出现的问题,现在我们的想法就是必须任务发布人和接取人同时确认任务完成该任务才算完成,还有就是接取人对当前任务可以有放弃的权力,后续细节会逐步完善。
3.关于支付问题。刚开始我们想着是用一个商户号来做一个转手,就是说任务发布人首先是将钱发到我们的商户号,然后由我们再转发给接取人,这样我们就可以控制价格,前面的优惠券想法就可以实现了,但是后来想到钱要经过我们手中,我们实在是保证不了安全,所以最后决定是用户之间直接交流,然后关于优惠我们就想其它的办法。
因为各种原因,今天才完整的将需求确定下来,然后初步完成了一下系统设计,商量了前后端对接的问题,项目已经正式可以开始实现了。
因为后来考虑到推广问题,所以是选择了微信小程序的技术路线,然后分配任务的时候我是被分派到做前端界面,也就需要去学习一下微信小程序的相关知识,加上每周都要上课,只有周末有时间出来学习一下,所以一直是拖到今天才开始正式实现,不过比较庆幸的是我之前学习过Vue,微信小程序和这个还是很像的,否者估计是还得往后拖一周左右。这也算是学习完之后就直接开始实战了吧。
因为是刚学完微信小程序,加上对之前的CSS之类的知识有所遗忘,所以刚开始的速度会有些慢,熟悉之后应该可以加快一些速度的。
受人数和相关知识的局限,我们小组是没有专门的美工的,只能由前端代领美工一职,想来工作量应该也还算可以,开始的时候我们商量了一下,大概做个七八个界面就可以完成了,主要的就是tabbar上的首页、任务、订单还有个人四个页面,要实现聊天功能的话,聊天界面也算一个比较重要的点,然后就是任务详情页面以及发布任务要提交的表单页面,可以适当加一些其它页面来点缀整个系统,是各模块之间的转化更加流程顺滑,不过页面设计等细节上的问题就是交给我来考虑了。
首先要实现的就是首页,我们是有一个公告功能的,不论是APP还是微信小程序其实很多都是在首页放上一个轮播图的,里面主要会是一些推荐之类的东西,我们就用其来承载我们的公告。
这个是当前实现出来的首页界面布局,中间摆的一些图片后面应该会进行修改,现在主要是用来占位置的。因为项目内容原因,我们其实不太清楚首页除了最开始说要摆上的公告以外还能摆什么东西,后来讨论了很久之后,联系到消息的通知功能(微信小程序的原因,小程序直接通知用户的功能是受到限制的,除非是绑定了服务号,但是服务号又需要拥有企业,就非常麻烦),最后是再摆上了相关状态任务的计数,这样用户在刚进小程序就能大致了解自己相关任务的当前状态。
虽然小程序是封装了一个swiper组件,但是调整起样式是真的麻烦,特别是还想有一定的动画效果的时候,最后是靠js才实现了一般的效果,主要就是动态改变组件的class。
其它界面元素主要就是卡片式布局了,因为不太了解设计相关的知识,我就只能靠平时自己使用应用程序的感受来了,卡片式布局我还是比较喜欢的,就用在自己的项目里面了,实现起来不是很难,最主要的就是一个边框圆角border-radius,其次就是边框的阴影box-shadow了。
还有一个就是自定义tabbar的实现,原生的tabbar就只能是那种等分且有文字的形式,因为我想要那种中间是一个“+”的图片,点击就跳转到任务发布表单的tabbar,所以只能是自定义。刚开始我还以为会很麻烦,其实也还好。主要是有几个要注意的点。
第一就是要把app.json中原来tabbar中添加上"custom": true,然后就是要在根目录中创建
这些都是固定格式的东西,再然后就是像写界面一样写就好了。还要注意的就是这里面的url一定都要在app.json里面的tabbar中注册,否则会报错。
其中的原理就是使用wx.switchTo跳转。然后有一些js的代码。
switchNav(event) {
let index = event.target.dataset.current
if (this.data.currentTab === index) {
return false
} else if(index === 2){
return false
}else {
app.globalData.currentSelected = index
let url = event.currentTarget.dataset.url
wx.switchTab({url})
}
}
在其它页面的onshow生命周期中也要加上一些js。
onShow() {
if (typeof this.getTabBar === 'function' && this.getTabBar()) {
this.getTabBar().setData({
currentTab: 0 //这个是当前页面在tabbar中的index
})
}
}
还是对新知识的不熟悉以及对原来知识的遗忘,昨天磕磕绊绊才完成了一个界面,然后今天想着应该可以快一些了,加上反正每个都要实现的,我就先选择了先做聊天界面,没想到这个更加麻烦。
这是仿照微信聊天的一个界面,但是微信聊天的一些效果着实有些不太好完成,就先搁置了。
第一个难点就是聊天气泡,气泡的框还好解决,主要就是突出来的那个小角有些困难,刚开始是想着用背景图片的,但是随着聊天语句的增长,气泡框是会拓展的,这就会导致背景图片的形变,最后我也不知道背景会变成一个什么样子。既然作为一个整体不行,那就分成两块,于是我就将方形框和小角分开来,对小角使用绝对布局,固定在头像旁边,然后方形框随着聊天字数来改变,再设置一下z-index,使方形框盖住小角,就实现了上面的效果,但是这就牵扯出了适配的问题,微信小程序开发工具中主要是iphone的几款机型,调整了一下感觉还成,但是安卓机型太多了,有可能之后会出现各种适配问题,就要使用其它的解决方案了,甚至到时候可能要去掉气泡了,因为现在还没有想到上面好的解决方法。
.chat-bubble{
position: absolute;//绝对定位
top: 40rpx;
transform: rotate(45deg);//将方块旋转
height: 25rpx;
width: 25rpx;
border-radius: 5rpx;
z-index: 10;//设置层级
}
遇到的第二个坑就是输入框的问题。小程序的input输入框点击之后就会呼出手机的软键盘,但是会出现弹出的软键盘将聊天内容遮挡的问题,这个的解决办法就是使用scroll-view作为聊天内容展示的载体,然后使用scroll-view的scroll-into-view属性,需要注意的要点就是这个要给每一个聊天内容的view添加上id。还有一个问题就是我在input旁边放置了一个发送按钮,但是只要点击发送按钮,input就会失去焦点,导致软键盘收起,如果是给input添加自动聚焦,就会导致软键盘收起到一半又自动弹出,不论何种情况都不是很好的用户体验,但是目前没有比较好的解决办法,可能后期会去掉这个按钮,使用软键盘中的发送键。
还有一些诸如聊天气泡左右分布之类的问题,也思考了很长时间,这里就不多赘述了。
刚开始想着聊天界面没有很多东西,应该很快就能做完,没想到一下子就花了几天解决各种遇到的问题,而且最后还是有些问题没有想到好的办法,看来前端没有我想象中那么简单,我现在开始怀疑后面的界面会更加麻烦。
又到了一个新的周末了,这周前面几天还是在解决聊天界面的问题,虽然最后是完成了一个界面,但是估计真机测试的时候还有许多地方需要完善。有了前面两个界面的铺垫,相关知识也熟悉和回忆的差不多了,接下来就可以适当加快速度了。
刚开始我是想做成那种一行一个的列表的形式的,但是有小组成员说这样太单调了,因为到时候其他界面肯定也是列表形式,不如这个就做成类似美团的那种样子的,我想想也是,没想到中间还有好几个坑。
还是受限于我们项目的类型,因为暂时还不支持发布任务时添加图片,所以一个任务项外面就会显得有些空旷,有人建议把任务内容摆出来,我总感觉界面上字太多效果会很差,应该更多使用一些词段或者是图片,但是不把内容放在外面就对接取任务的人很不友好,因为他是有方向的去接取任务的,需要能够快速知道任务的主要内容,不能是一个个任务点击查看详情,这样会很浪费时间,甚至导致放弃接取任务。为此我们还争论了很久,我始终不认同将内容摆在外面,最后就是想着使用标签的功能,就是在每个任务项下面展示一些标签描述该任务的主要功能,但是这又带来一个新的问题,就是标签的内容怎么填,如果是由我们从用户填写的任务介绍中抓取就会很麻烦,所以我们想着由用户自己来创建标签,不过这也只是一种解决方案,具体效果还是得看最后实现出来是什么样了。
还有一个坑就是关于左右展示两列的问题了,刚开始我想着很简单,不就是设置左右浮动了,但是测试之后这样是不行的,浮动以后会出现一个卡位的问题,因为每一个任务项的高度是不定的,尝试了各种方法,什么清除浮动之类的,最后只能说使用偏门的方法了,就是将整个展示界面分成左右两列,在各自的区域展示就不会卡位,但是有可能会出现一遍特别长另一边特别短的情况,不过这都算小问题了。
今天继续任务模块的界面。这是任务表单和任务详情展示两个界面,因为还有些细节没有讨论好,所以这两个只能算是半成品,后面还要加上一些内容。
这两个界面有许多相关联的地方,就放到一起做了。做起来的时候还算顺利,没有遇到之前两个界面那么棘手的问题,然后现在还有一个想法没有实现,就是标签功能,也就是允许用户自己给发布的任务粘上一些标识任务关键的标签,方便接任务的人发现自己想要接取的任务,这个主要难在任务表单里面,要做出比较好看的效果不是很容易,目前还在构思中。
还有就是任务表单那一块,picker组件的显示在小程序开发工具和真机预览的时候有不一致,不知道真正上线会以谁为准,就是关于时间选择器显示的问题,我想要的样式是不显示当前时间之前的时间,但是在小程序开发工具中却显示了,网上找了好久的资料不知道怎么解决这个问题,甚至是想要自己写一个picker了,然后真机预览的时候发现就是我想要的样式,就很迷惑。
转眼项目就开始一个多月了,今天主要是总结一下这一个多月以来的工作。
3月11号的时候参加开题答辩,刚开学的时候我们感觉还有一点时间来考虑我们项目做什么,所以就没有很急着讨论,只是说各个成员思考一下做什么项目比较好,那时候也基本一天有那么一两个点子,但基本都是否定掉了,真正到快要答辩的时候,我们才猛然察觉我们项目还没定,头脑一热就想出了这个点子,然后匆匆忙忙写了开题申请书就交上去了,其实到这时候我们心里都是没有底的,感觉是很大概率过不了的,没想到最后居然是通过过了,但是也添加了一个附加条件,就是这个条件几度让我们想放弃,虽然最后还是坚持开始做了。
其实这学期时间还是比较紧的,不仅因为这学期本身课就不算少,还有就是今年12月份的研究生统考,考研不早点开始的话,到时候时间可能会不够,因此每周能够抽出来做项目的时间其实就是周末,还有就是每天晚上可能空出来的几个小时了。
刚开始一两周我们主要是一起详细的讨论了我们项目的需求分析文档,针对其中的支付、聊天等问题思考了许多解决方案,然后就是形成我们的系统设计文档,不过这个我们只是完成了整体框架,细节打算是之后再填补,因为我们实在是没有这种真正上线的项目,所以在这一方面还是有很多欠缺,许多内容考虑不完善。
随后就是各自完成各自的任务了,因为是第一次接触微信小程序,所以我还是花费了一个周末的时间去学习相关知识,在有一定Vue基础的情况下,微信小程序学起来还算是比较快的。然后就是正式开始我的前端设计实现了,感觉还是因为没有美工的原因,我前端实现的时候会有一定的困难,没有我刚开始想象的那么简单,因为每完成一个样式,我就要自己思考后面的界面要怎么做才好看,还要和大家讨论怎样可以,相当于美工和前端一个人做了,做要是还没有设计相关的知识储备,每一步都不好走。
正式开始实现工作以来两周左右,我主要完成了首页和任务页面,以及一些过度页面,其中遇到了不少困难,也有些到现在还没有想出较好的解决方法,不过整体下来还算顺利,没有出现一个界面卡很长时间做不出来的情况,最重要的是在这期间积累的一些经验,还有就是确认了界面设计的一个大致风格,再设计的时候就会轻松很多。
不知道钉钉是出现了什么问题,戴鸿君老师中期答辩12号的通知今天才通知我,连着中期答辩的具体要求。
首页、任务、订单和个人界面还剩两个、争取本周做完这两个。
订单界面和任务界面有一定的相似性,所以做起来还算快,但是订单项就卡了一下,主要还是在考虑展示些什么内容比较好,刚开始设计的是展示任务标题、接取时间(只有被接取的任务才会成为订单,然后订单主要有进行中和已完成两种状态)、任务类型、接取人头像等,然后再加上一个渐变的颜色来区分任务类型,但是后来发现这样会导致“我接取的”和“我发布的”中的订单项要写两套,毕竟不能在“我接取的”里面的订单项再摆上自己的头像吧,还有一个就是渐变色的背景导致订单界面和前面两个有一个整体风格上的冲突,所以就重构了一下订单项的构成,变成了现在这个样子。
在这里也遇到了一个坑,就是scroll-view的使用,因为左右是分开滚动的,但是我在右边使用scroll-view展示订单项的时候发现,scroll-view会默认设置成整个页面的宽度,一调整宽度就会导致整个订单项的形变,然后我就想着用view的overflow来进行滚动,但是这个又会导致是整个页面的滚动,而不是右边单个view的滚动,加上下午的时候脑子有些迷糊,硬是每太相同应该怎么办。到了晚上的时候突然就想明白了,就是在scroll-view外面套一层view,限制外层view的大小,果然这就成功了。
还有一个就是任务状态的选择效果也调整了一段时间,最后是靠修改内边距的值才达到了我想要的效果,但是不知道这样会不会出现适配问题。
主要实现的一个效果就是当两个状态至少有一个被选择时,确认后任务状态标签就处于被激活状态。这个在任务界面中也有使用。
说实在,我总感觉这次设计出来的这个界面和前面的有一点不搭,主要是前面用的都是卡片式或者是半卡片式的布局,这个界面就有点平铺直叙了,后期再想想新的设计方案吧。个人模块内容还是比较多的,虽然每个二级页面都不会很难,但是加到一起工作量就比较大了。
今天主要是完成了个人的主界面以及二级的个人详情以及信誉积分,做到这里又感受到没有美工的痛苦了,因为图片全部要自己去找,找到一个合适当前整体风格的图片说实在的有点麻烦,关键就是自己不会做图片咯。
主要是感觉信誉积分这里面很单调,想要在后面加一个背景图片,但是找了很久都没有找到感觉合适的,只能说是暂时搁置这事了。
今天还空了点时间,就继续完成个人信息模块了,下一个就是设置,我是想在里面放一个联系我们和一个意见反馈,中间做了一个简单的过度跳转界面就不展示了。
很简单的一个界面,我甚至还没加上提交按钮。
又是很简单的一个界面,要不干脆两个合到一起?其实这个联系我们界面,我个人感觉还是挺简洁好看的。还有就是长按保存图片的js。
saveQRImage:function(event){
let url = event.currentTarget.dataset.imgurl
console.log(url)
wx.getSetting({
success: (res) => {
if (!res.authSetting['scope.writePhotosAlbum']) {
wx.authorize({
scope: 'scope.writePhotosAlbum',
success:()=> {
wx.saveImageToPhotosAlbum({
filePath: url,
fail:(res)=>{
console.log(res);
}
})
},
fail: (res) =>{
console.log(res);
}
})
}else{
wx.saveImageToPhotosAlbum({
filePath: url,
fail:(res)=>{
console.log(res);
}
})
}
},
fail: (res) =>{
console.log(res);
}
})
}
我现在知道的微信小程序实现保存到手机相册的方法有两个,一个是wx.saveImageToPhotosAlbum,但是这个不支持网络url,只能支持项目本地的url,还有一个是wx.getImageInfo,这个能支持网络url,不过最后都是要调用wx.saveImageToPhotosAlbum保存到相册,在这之前是需要用户授权scope.writePhotosAlbum的。我是打算直接将二维码放到项目本地了,所以就只需使用第一个方法。
稍微看了一下现在写的页面,发现也是有一些了。
今天就是中期答辩了,原本以为会很麻烦,结果其实就是检查项目进度,现在前端界面是写完了,还剩一些细节需要修缮,然后就是添加JS代码了,估计很快就能实现前后端的对接了。等答辩完就休息一段时间,还有好多其它的事情要忙。
麻烦的事情来了,因为我做前端界面的时候默认后端是能够很快的把数据传送过的,但是经过一些小测试后发现很多地方想要展示到我设计的效果的话,就会涉及到好几个表的连接,甚至是会需要多次请求后端,这样的效率太低了,所以只能说是修改前端需要展示的东西了,这就说明很多细节要变,但是好在整体不需要太大的变化,所以又要忙活一阵子了。
原本以为很快就可以改完,结果没想到最后还是花了两周才改完,主要是刚开始觉得一些细节修起来很快,但是一调整一天都不一定能够改完一个,经常出现一些我无法理解的问题,然后连debug都不知道中哪里开始,但就是出现不了我想要的样式,可能这就是前端的痛苦所在吧,确实有些离谱。
接下来就是展示几个页面。
改得最难受的就是聊天界面了,当时这个界面就做了好几天,结果几乎就是全部推翻重做了。
既然页面写完了,一些与后端对接的js也就可以开始了。
写了一下注册登录的逻辑,其实就是用户一打开就判断该用户是否是新用户,这个判断依据就是用wx.login去获取到一个code码,后端拿到code后去访问 https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/login/auth.code2Session.html 接口,就能获取到用户的openid,这是用户在一个小程序中的唯一标识符,我们会将其保存在数据库中,刚开始我们还想着就直接前端访问接口直接传给后端openid了,但是因为调用这个接口是要用到appID和appSecret的,为保证安全,前端是不允许访问该接口的,所以最后只好是丢给后端去实现了,我就只管拿数据了。
wx.login({
success: (res) => {
wx.request({
url: 'https://api',
method: 'POST',
data: {code: res.code},
header: {'content-type': 'application/x-www-form-urlencoded'},
success: (res) => {
// console.log(res)
if(res.statusCode == 200){
//根据后端传来的数据,如果是新用户就跳转到注册界面,否则跳转到登录界面
wx.navigateTo({
url: '/pages/subordinatePage/register/register?isRegister=' + res.data,
})
}else{
wx.showToast({
title: '抱歉,请求失败!',
icon: 'none',
duration: 1500
})
}
},
fail: (res) => {console.log(res)}
})
}, fail: (res) => {console.log(res)}
})
注册的时候需要用户授权来获取个人信息,这里关键的一点就是个体小程序是不能获取用户的手机号的,所以我们就是在注册界面要求用户填手机号了,因为验证真假有点麻烦,我就只写了一个正则判断了,
if (!(/^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}$/.test(parseInt(phoneNum)))) {
wx.showToast({
title: '手机号码有误',
duration: 1500,
icon:'none'
})
return false
}
最后附上注册的代码,里面有一点就是用户注册成功以后会在缓存中存储个人信息,这样就避免需要重复登录,为了实现类似session的功能,还需要在缓冲中保存当前保存的时间戳,然后用户每次登录的时候取缓冲中的个人信息并且将保存的时间戳和当前时间戳进行比较,如果两者差值到一定数值,就判断为失效,用户就需要再登录一次。
wx.getUserProfile({
lang: "zh_CN",
desc: "展示个人信息",
success: (getres) => {
let comeback = true
let tempInfo = getres.userInfo
let currentInfo = this.data.userInfo
tempInfo.phoneNum = currentInfo.phoneNum
tempInfo.studentId = currentInfo.studentId
tempInfo.dormNum = currentInfo.dormNum
tempInfo.gender = parseInt(currentInfo.gender)
new Promise((resolve, reject)=>{
wx.downloadFile({
url: tempInfo.avatarUrl,
success: (downloadres) => {
wx.getFileSystemManager().readFile({
filePath: downloadres.tempFilePath,
encoding: 'base64',
success: res => {
resolve('data:image/png;base64,' + res.data)
}
})
}
})
}).then( imgdata => {
wx.login({
success: (loginres) => {
wx.request({
url: 'https://api',
method: 'POST',
data: {
code: loginres.code,
phoneNumber: tempInfo.phoneNum,
userName: tempInfo.nickName,
studentId: tempInfo.studentId,
dormNum: tempInfo.dormNum,
gender: tempInfo.gender,
avatar: imgdata
},
header: {'content-type': 'application/x-www-form-urlencoded'},
success: (requestres) => {
console.log(requestres)
if(requestres.data == ""){
wx.showToast({
title: '该手机号已被注册!',
icon: 'none',
duration: 1500
})
comeback = false
return
}
if(requestres.statusCode == 200){
app.globalData.userInfo = requestres.data
app.globalData.userInfo.avatar = app.globalData.urlStart + app.globalData.userInfo.avatar
if(!app.globalData.socketConnected){
app.useWebSocket(app.globalData.userInfo.phoneNum)
}
wx.showToast({
title: '注册成功!',
icon: 'none',
duration: 1000
})
}else{
wx.showToast({
title: '抱歉,请求失败!',
icon: 'none',
duration: 1500
})
comeback = false
}
if(comeback){
let secessionExpiration = Date.parse(new Date()) + 7*24*60*60*1000
wx.setStorageSync('userInfo', app.globalData.userInfo)
wx.setStorageSync('userInfo_expiration', secessionExpiration)
wx.redirectTo({
url: '/pages/subordinatePage/greenhandGuide/greenhandGuide',
})
}
},fail: (requestres) => {console.log(requestres)}
})
},fail: (loginresres) => {console.log(loginresres)}
})
})
},
fail: (res) => {
console.log(res)
wx.showModal({
title: '授权提示',
content: '小程序需要您的微信授权才能使用哦~',
showCancel: false,
confirmText: '确定'
})
}
})
Js写起来就有些忘记时间了,漏了很多天的博客,今天我们小程序终于算是发布了,最关键的是审核的是真的麻烦,因为我们的小程序涉及到了用户信息发布,所以必须得是企业主体,但是刚开始的时候我们不知道这一条,中间尝试了各种方法都过不了审核,最后不得不就是去申请企业认证,这一弄就是两周,所以到现在我们小程序才发布出来,就只剩下一周的时间可以宣传了,也不知道最后我们的指标到底能不能完成,只能是拼一下了。
接下来就补充一些之前写的比较有难度的js代码。
最难的一个就是聊天功能了,因为小程序不提供聊天功能,所以我们是使用websocket来实现聊天的,这个其实还算好,最难的一个就是聊天的消息提醒功能了。
这个就涉及到当前是否在与消息来源者的聊天页面中,如果不在就要将其保存起来用作消息提示的基础,如果在,就直接在页面中展示就行了。
wx.onSocketMessage((result) => {
let msg = JSON.parse(result.data)
console.log(msg)
if(msg.msg){
return
}
let currentPages = getCurrentPages()
let isInChatWithPhone = false
for(let page of currentPages){
if(page.route == "pages/subordinatePage/chat/chat"){
if(page.options.orderId == msg.orderId){
if(msg.resultType == 0){
wx.showToast({
title: msg.error,
icon: 'none',
duration: 1500,
success: () => {
setTimeout(() => {
wx.navigateBack({
delta: 0
})
}, 1500)
}
})
return
}else{
this.globalData.chatPage.updateMsgList(msg)
isInChatWithPhone = true
}
break
}
}
}
if(!isInChatWithPhone){
this.globalData.msgList.push(msg)
this.changeRedpoint(true)//这是更新tabbar状态的方法
if(this.globalData.orderPage){
this.globalData.orderPage.changeItem(msg.orderId, true)
}
}
})
当有新消息未读的时候tabbar就是如下效果。这里面有一个比较坑的点,就是这整个tabbar不是一个对象,也是四个对象,刚开始的时候我没有注意到这一点,结果就出现主要在首页的时候tabbar的订单那里会出现这个红点,所以必须得将四个tabbar对象都保存起来,才能做到全部同步更新。
changeRedpoint(flag){
this.globalData.hasNewMsg = flag
for(let tarbar of this.globalData.myTarbar){
tarbar.setData({
showRedpoint: flag
})
}
}
因为是基于websocket实现的聊天,所以当用户不在小程序中的时候是没有办法接收的消息提醒的,这个问题可以用微信的订阅消息来解决,这里暂时还没有加上,当用户重新上线之后,我们还是要能够做到消息提醒的,不过这时候就是靠从后端获取到数据了。
getNewChatOfList: function(callback = function(){}){
for(let i = 0; i < this.data.orderInfos.length; i++){
if(!(this.data.orderInfos[i].finishTime == "" || !this.data.orderInfos[i].finishTime)){
return
}
new Promise((resolve) => {
let anotherPhoneNum =
(this.data.userInfo.phoneNum == this.data.orderInfos[i].phoneNum ?
this.data.orderInfos[i].task.phoneNum : this.data.orderInfos[i].phoneNum)
wx.request({
url: 'https://api',
method: 'POST',
data: {
fromUserPhoneNum: anotherPhoneNum,
toUserPhoneNum: this.data.userInfo.phoneNum,
orderId: parseInt(this.data.orderInfos[i].orderId)
},
header: {'content-type': 'application/x-www-form-urlencoded'},
success: (res) => {
if(res.statusCode == 200){
resolve(res.data)
callback()
}else{
resolve(0)
}
},
fail: (res) => {
console.log(res)
this.setData({
isloading: false
})
resolve(0)
}
})
}).then((num) => {
if(num > 0){
this.data.orderInfos[i].hasNew = true
this.setData({
orderInfos: this.data.orderInfos
})
}
})
}
}
这个方法是对一个订单项来看是否有新消息,考虑到效率问题,就只看正在进行中订单。
还有一个比较麻烦的点就是scrollview上拉加载,下拉刷新微信是有方法提供的,想要实现上拉加载,我目前能想到的方法就是通过计算拖动的像素距离。
touchStart: function(event) {
this.setData({
touchDown: event.touches[0].clientY
})
wx.createSelectorQuery().select('.task-list-inner').boundingClientRect(rect => {
this.setData({
innerHeight: rect.height
})
}).exec()
wx.createSelectorQuery().select('.task-list').fields({
scrollOffset: true,
size: true
}, rect => {
this.setData({
startScroll: rect.scrollTop,
height: rect.height
})
}).exec()
},
touchEnd: function(event) {
let currentY = event.changedTouches[0].clientY;
let {startScroll, innerHeight, height, touchDown} = this.data;
// if (currentY > touchDown && currentY- touchDown > 20 && startScroll == 0) {
// console.log("触摸开头")
// }else
if(currentY < touchDown && touchDown - currentY >= 40 && (startScroll +
height >= (innerHeight + 8) || startScroll +
height >= (innerHeight - 8)) && innerHeight > height) {
console.log("触摸底部")
this.setData({
isloading: true
})
setTimeout(()=>{
this.setData({
isloading: false
})
}, 800)
}
}
基本原理就是先获取用户点击的屏幕坐标,然后获取到用户手指抬起时的坐标,还有就是要获取到scrollview滚动轴离顶部的距离,判断用户是否在底部,并且还在往上拖,要注意的一点就是像素计算的时候会有一些偏差,所以需要有一定的修正值。
js的补充就写到这里了,剩下的都是一些比较繁琐的代码,但是实现的逻辑并没有那么难。
转眼就已经宣传了一周了,这一周下来只能说效果还行,但是离我们的预期值还是有些距离的,感觉上还是因为审核耽误了太多时间了,导致宣传时间远远不够,所以以后要注意这一点,事先就要了解一些相关的消息,不要上来就开始实现项目了。
从3月4号一拍脑袋讨论出一个项目到现在恍恍惚惚也已经过去了3个月了,在这三个月当中,也不止一次想过放弃,但最后还是咬咬牙坚持着完成了整个项目,最后也取得了还算可以的成果。截止到现在,微信统计的数据当中显示我们已经有了140余的用户,每天也有一定的访问量。