你的心事我全知晓——心情日记小程序丨实战

闲暇之余,听媳妇嘀咕说要给她做一个能表达她每日心情的小程序,只能她在上面发东西。既然媳妇发话了,就花点心思做一个吧,因为没有UI图,所有布局全靠自己瞎编,下面结合图片和代码跟大家讲解下实现过程,内容略长,感兴趣的可以一览。

下面将以图片、代码的形式和大家讲解这个小demo的实现过程:

首页

首页效果图

0

首页讲解

  • 音乐(下面仅展示音乐相关代码)
<div class="bg_music" @tap="audioPlay"><image src="../../static/images/music_icon.png" class="musicImg" :class="isPlay?'music_icon':''"/><image src="../../static/images/music_play.png" class="music_play" :class="isPlay?'pauseImg':'playImg'"/>
</div>
<audio id="myAudio" :src="audioUrl" autoplay loop></audio>
data () {return {isPlay: true,audioCtx: ''}
},
onLoad () {const that = thisthat.audioCtx = wx.createAudioContext('myAudio')that.getMusicUrl()
},
methods: {getMusicUrl () {const that = thisconst db = wx.cloud.database()const music = db.collection('music')music.get().then(res => {that.audioUrl = res.data[0].musicUrlthat.audioCtx.loop = truethat.audioCtx.play()})},audioPlay () {const that = thisif (that.isPlay) {that.audioCtx.pause()that.isPlay = !that.isPlaytools.showToast('您已暂停音乐播放~')} else {that.audioCtx.play()that.isPlay = !that.isPlaytools.showToast('背景音乐已开启~')}}
}
.bg_musicposition fixedright 0top 20rpxwidth 100rpxz-index 99display flexjustify-content flex-startalign-items flex-start.musicImgwidth 60rpxheight 60rpx.music_iconanimation musicRotate 3s linear infinite.music_playwidth 28rpxheight 60rpxmargin-left -10rpxtransform-origin top-webkit-transform rotate(20deg).playImganimation musicStop 1s linear forwards.pauseImganimation musicStart 1s linear forwards
#myAudiodisplay none

1、通过wx.createInnerAudioContext()获取实例 ,安卓机上音乐能正常播放,IOS上不行,具体原因感兴趣的可以去深究一下;

2、由于前面邀请函小程序相关文章发出后,问的最多的问题依然是音乐无法播放这块,所以这个demo中就再给大家讲解了下实现的原理。


  • 日历

这里日历使用了小程序插件,之所以在首页放一个日历是为了页面不显的太单调。下面讲解下插件是如何使用的:

1、登录微信公众平台>设置>第三方设置>添加插件>搜索相关插件的名字(使用appId搜索更好)>点击某个插件右侧的查看详情,进入插件详情页添加插件,一般都能立马添加通过;

0

2、插件详情里面一般都有使用文档,或git地址,插件的具体属性事件都会在文档里有介绍;

3、下面讲解下如何在项目中使用插件:

1、找到src根目录下的app.json文件,添加如下内容:

// "cloud": true,
"plugins": {"calendar": {"version": "1.1.3","provider": "wx92c68dae5a8bb046"}
}

2、在需要引用该插件的页面的.json文件中加入如下内容:

{// "navigationBarTitleText": "媳妇的心情日记",// "enablePullDownRefresh": true,"usingComponents": {"calendar": "plugin://calendar/calendar"}
}

3、在页面中直接使用如下(具体属性方法的意思根据对应插件有所不同):

<calendar:class="showCalendar?'':'hide_right'"class="right"weeks-type="en"cell-size="20":header="showHeader"show-more-days=truecalendar-style="demo4-calendar"board-style="demo4-board":days-color="demo4_days_style"@dayClick="dayClick"
/>

  • 天气和地址

1、这里我借助的是高德微信小程序SDK;

2、首先获取使用相关api需要的key值,如下:

0

3、下载对应SDK(.js文件)并引入到项目中;

4、通过相关api获取天气和地址:

getWeather () {const that = thislet myAmapFun = new amapFile.AMapWX({key: '你申请的key'})myAmapFun.getWeather({success (res) {// 成功回调that.address = res.liveData.citythat.weather = res.liveData.weather + ' 'that.temperature = res.liveData.temperature + '℃'that.winddirection = res.liveData.winddirection + '风' + res.liveData.windpower + '级'},fail (info) {// 失败回调console.log(info)}})
},

  • 发表日记

这里涉及到发表文字图片内容,在个人小程序提交审核后很大可能是不会被通过的,虽然第一次提交我的个人小程序通过审核了,后面几次审核均未通过,虽然我这里只限制了我和媳妇两个人能发日记,其他人压根看不到右下角的发布加号,但是审核人员会查代码,代码中一旦被他们发现有类似发表相关的内容或字样就会导致审核不通过,好在已经通过了一次,媳妇能正常写点东西,也算基本符合要求,遗憾的是后面实现点赞相关的功能都没有更新到线上。

0

1、通过唯一的openId来判断是否显示首页右下角的发布加号;

2、后面会具体讲解页面里上传图片到云开发及存储到数据库相关功能


  • 点赞功能

1、这里点赞功能借助的小程序云开发的云函数来实现的,结合代码:

<ul class="list"><li class="item" v-for="(item, index) in diaryList" :key="item._id" @tap="toDetail(item)"><image class="like" src="../../static/images/like_active.png" v-if="likeList[index] === '2'" @tap.stop="toLike(item._id, '1', item.like)"/><image class="like" src="../../static/images/like.png" v-if="likeList[index] === '1'" @tap.stop="toLike(item._id, '2', item.like)"/><image class="img" :src="item.url" mode="aspectFill"/><p class="desc">{{item.desc}}</p><div class="name-weather"><span class="name">{{item.name}}</span><span class="weather">{{item.weather}}</span></div><p class="time-address"><span class="time">{{item.time}}</span><!-- <span class="address">{{item.address}}</span> --></p></li>
</ul>
<div class="dialog" v-if="showDialog"><div class="box"><h3>提示</h3><p>是否授权使用点赞功能?</p><div class="bottom"><button class="cancel" @tap="hideDialog">取消</button><button class="confirm" lang="zh_CN" open-type="getUserInfo" @getuserinfo="login">确认</button></div></div>
</div>
// 获取日记列表
getDiaryList () {const that = thiswx.cloud.callFunction({name: 'diaryList',data: {}}).then(res => {that.getSrcFlag = falsethat.diaryList = res.result.data.reverse()that.likeList = []that.diaryList.forEach((item, index) => {item.like.forEach(itemSecond => {if (itemSecond.openId === that.openId) {that.likeList.push(itemSecond.type)}})if (that.likeList.length < index + 1) {that.likeList.push('1')}})wx.hideNavigationBarLoading()wx.stopPullDownRefresh()})
},
// 点赞或取消点赞
toLike (id, type, arr) {const that = thisthat.tempObj = {id: id,type: type,like: arr}wx.getSetting({success (res) {if (res.authSetting['scope.userInfo']) {// 已经授权,可以直接调用 getUserInfo 获取头像昵称wx.getUserInfo({success: function (res) {that.userInfo = res.userInfowx.cloud.callFunction({name: 'like',data: {id: id,type: type,like: arr,name: that.userInfo.nickName}}).then(res => {if (type === '1') {tools.showToast('取消点赞成功')} else {tools.showToast('点赞成功~')}// getOpenId()方法里会执行一遍获取日记列表that.getOpenId()})}})} else {that.showDialog = true}}})
},
// 授权获取用户信息
login (e) {const that = thisconsole.log(that.tempObj, e)if (e.target.errMsg === 'getUserInfo:ok') {wx.getUserInfo({success: function (res) {that.userInfo = res.userInfowx.cloud.callFunction({name: 'like',data: {id: that.tempObj.id,type: that.tempObj.type,like: that.tempObj.like,name: that.userInfo.nickName}}).then(res => {if (that.tempObj.type === '1') {tools.showToast('取消点赞成功')} else {tools.showToast('点赞成功~')}// getOpenId()方法里会执行一遍获取日记列表that.getOpenId()})}})}that.showDialog = false
}

2、首页获取日记列表,在存储日记到数据库集合的时候我会在每条日记对象中添加一个like属性,like默认是一个空数组;

3、当用户点赞或取消点赞时,组件data中tempObj属性会临时存储三个参数:
①、对应日记的_id;
②、用户操作的类型是点赞(点赞是‘2’)或是取消点赞(取消点赞是‘1’);
③、对应日记的like数组;

4、通过小程序api的wx.getSetting({})来判断用户是否已经授权。如果授权了获取用户信息,未授权则弹框引导用户点击确认按钮去手动授权;

5、授权成功后,拿到用户信息,我们开始调用点赞或取消点赞相关的云函数,如下:

const cloud = require('wx-server-sdk')
cloud.init()
const db = cloud.database()
exports.main = async (event, context) => {try {// wxContext内包含用户的openIdconst wxContext = cloud.getWXContext()// 定义空数组let arr = []if (event.like && event.like.length > 0) {// 让定义的数组等于用户操作的当前日记下的like数组arr = event.like// 定义一个计数变量let count = 0// 循环遍历,当openId相同时替换like数组中的相同项,并存储对应的typearr.forEach((item, index) => {if (item.openId === wxContext.OPENID) {count++arr.splice(index, 1, {openId: wxContext.OPENID,type: event.type,name: event.name})}})// 当计数变量为0时,说明在这条日记中,like数组中未存储过此用户,直接push此用户并存储typeif (count === 0) {arr.push({openId: wxContext.OPENID,type: event.type,name: event.name})}} else {// 如果此条日记like数组本身就为空,直接push当前用户并存储typearr.push({openId: wxContext.OPENID,type: event.type,name: event.name})}// 通过云开发操作数据库的相关api,即update通过_id来更新集合中某条数据return await db.collection('diary').doc(event.id).update({data: {like: arr}})} catch (e) {console.error(e)}
}

6、相关云函数操作说明都写在上面的注释里,有不清楚的欢迎留言,由于点赞功能未更新到线上(原因是因为审核不通过),想体验的同学可以留下评论,提供体验权限。


发表心情

效果图

0

讲解

1、通过首页右下角的发布加号,进入发布心情页;

2、地址等相关信息是从首页通过路由带过来的;

3、下面重点讲解下关于上传图片到云存储并写入数据库的操作过程,内容如下:

upload () {const that = thiswx.chooseImage({count: 1,sizeType: ['compressed'], // 可以指定是原图还是压缩图,默认二者都有sourceType: ['album', 'camera'], // 可以指定来源是相册还是相机,默认二者都有success: function (res) {wx.showLoading({title: '上传中'})// 返回选定照片的本地文件路径列表,tempFilePath可以作为img标签的src属性显示图片let filePath = res.tempFilePaths[0]const name = Math.random() * 1000000const cloudPath = 'picture/' + name + filePath.match(/\.[^.]+?$/)[0]wx.cloud.uploadFile({cloudPath, // 云存储图片名字filePath // 临时路径}).then(res => {console.log(res)wx.hideLoading()that.imgUrl = res.fileID}).catch(e => {console.log('[上传图片] 失败:', e)})}})
},
save () {const that = thisif (that.desc) {that.getSrcFlag = falseconst db = wx.cloud.database()const diary = db.collection('diary')if (that.imgUrl === '../../static/images/default.png') {that.imgUrl = '../../static/images/default.jpg'}diary.add({data: {desc: that.desc,time: tools.getNowFormatDate(),url: that.imgUrl,name: that.name,weather: that.weather,address: that.address,like: []}}).then(res => {wx.reLaunch({url: '/pages/index/main'})}).catch(e => {console.log(e)})} else {tools.showToast('写点什么吧~')}
}

4、这里的cloudPath可以自己定义,存储到云中是这样的:

0

5、我们通过组件data中的imgUrl临时存储手动上传的图片路径,最终通过保存按钮一起存储到云数据库,存如到数据库是这样的:

0


日记详情页

详情页效果图

0

讲解

1、详情就不过多讲解,这里利用了一些小程序api,比方说动态改变头部标题,每次进入动态随机改变顶部标题背景,点赞数也是从首页带过来的;


访客页

效果图

1、授权前

0

2、授权后

0


总结

云开发虽然能用,但对于大型项目个人还是不推荐,从图片和数据加载这块的效果来看,传统服务端拿到的数据明显要快很多,既然有这么一个免费的工具,我想感兴趣的同学可以利用起来,玩点小demo,新花样。

源码链接

https://github.com/TencentCloudBase/Good-practice-tutorial-recommended


如果你有关于使用云开发CloudBase相关的技术故事/技术实战经验想要跟大家分享,欢迎留言联系我们哦~比心!

1649686-20190814103251115-895113566.png

转载于:https://www.cnblogs.com/CloudBase/p/11350380.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/423632.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java面试题28 牛客 下面有关java classloader说法错误的是?

java面试题28 牛客 下面有关java classloader说法错误的是? A Java默认提供的三个ClassLoader是BootStrap ClassLoader&#xff0c;Extension ClassLoader&#xff0c;App ClassLoader B ClassLoader使用的是双亲委托模型来搜索类的 C JVM在判定两个class是否相同时&#x…

css居中无效的解决办法

前几天自己用css做居中的效果 margin: 0 auto,平时我都事这样来写的&#xff0c;不过这次就是不能实现居中的效果&#xff0c;检查代码&#xff0c;原来是自己没有添加DTD语句&#xff0c;即&#xff1a;&#xff1c;!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitiona…

spark on yarn 部署问题

spark on yarn 部署报:java.io.IOException: Resource file:/usr/local/spark-1.6.3-bin-hadoop2.6/lib/spark-assembly-1.6.3-hadoop2.6.0.jar changed on src filesystem (expected 1530607524000, was 1478125561000 解决&#xff1a;spark-env.sh 之前配置 export HADOOP_C…

java面试题29 牛客 以下关于集合类ArrayList、LinkedList、HashMap描述

java面试题29 牛客 以下关于集合类ArrayList、LinkedList、HashMap描述错误的是&#xff08;&#xff09; A HashMap实现Map接口&#xff0c;它允许任何类型的键和值对象&#xff0c;并允许将null用作键或值 B ArrayList和LinkedList均实现了List接口 C 添加和删除元素时&am…

使用python爬取东方财富网机构调研数据

最近有一个需求,需要爬取东方财富网的机构调研数据.数据所在的网页地址为: 机构调研 网页如下所示: 可见数据共有8464页,此处不能直接使用scrapy爬虫进行爬取,因为点击下一页时,浏览器只是发起了javascript网络访问,然后将服务器返回的数据插入网页,无法通过网址直接获取对应页…

spark on yarn webUI logs不能查看

执行spark on yarn 执行&#xff1a;./bin/spark-submit --class org.apache.spark.examples.SparkPi --master yarn-cluster --executor-memory 1G --num-executors 3 ./lib/spark-examples-1.6.3-hadoop2.6.0.jar 10 命令执行成功后在yarn 资源管理界面查看不了logs 参考博…

post提交,WPF,Silverlight(加深记忆写一遍)

asp.net当<form id"form1" runat"server">默认post提交是提交到本页&#xff0c;每次提交会验证viewstate所以想提交到其它页会出错&#xff0c;如果真想提交到其它页&#xff0c;那么把其它页的viewstate标识改成和这个页一样 当去掉runat"ser…

java面试题30:牛客 下列哪项不属于jdk1.6垃圾收集器?

java面试题30&#xff1a;牛客 下列哪项不属于jdk1.6垃圾收集器&#xff1f; A:Serial收集器 B&#xff1a;parNew收集器 C:CMS收集器 D:G1收集器 1.Serial收集器 单线程收集器&#xff0c;收集时会暂停所有工作线程&#xff08;我们将这件事情称之为Stop The World&…

2019最新Python爬虫高频率面试题总结(一)

今天给大家出一个关于Python爬虫面试题的总结&#xff0c;相对于来说出现频率比较高的一些&#xff01;1. 为什么 requests 请求需要带上 header&#xff1f;原因是&#xff1a;模拟浏览器&#xff0c;欺骗服务器&#xff0c;获取和浏览器一致的内容header 的形式&#xff1a;字…

Silverlight专题(15) - 你自己的视频播放器之自定义MoveToPointSlider

前言&#xff1a; 这几天在网络上看到不少人在问如何创建一个Video Player&#xff08;Silverlight版本&#xff09; 而我在微软和这方面打了不少交道 所以计划用两篇文章解答下大家的问题 本篇文章先介绍下如何创建一个自定义的滚动条 下篇文章创建完整的一个Video Player 问题…

java面试题31:结构型模式中最体现扩展性的模式是()

java面试题31&#xff1a;结构型模式中最体现扩展性的模式是&#xff08;&#xff09; A:装饰模式 B&#xff1a;合成模式 C:桥接模式 D:适配器 蒙蔽树上蒙蔽果&#xff0c;蒙蔽树下你和我 结构型模式是描述如何将类对象结合在一起&#xff0c;形成一个更大的结构&#x…

hive 多用户访问模注意问题

首先是安装mysql 安装mysql数据库及客户端 yum install mysql-server yum install mysql servicemysqld start步骤一&#xff1a; yum -y install mysql-server步骤二&#xff1a;service mysqld start步骤三&#xff1a;mysql -u root -p  Enter password: &#xff08;默认…

10行代码实现小程序支付功能!丨实战

前面给大家讲过一个借助小程序云开发实现微信支付的&#xff0c;但是那个操作稍微有点繁琐&#xff0c;并且还会经常出现问题&#xff0c;今天就给大家讲一个简单的&#xff0c;并且借助官方支付api实现小程序支付功能。 传送门&#xff1a;借助小程序云开发实现小程序支付功能…

ASP.NET站点导航(五)

理解并扩展 ASP.NET 2.0 中的站点导航系统 http://msdn.microsoft.com/zh-cn/library/aa479338.aspx 发布日期 : 2006-3-15 | 更新日期 : 2006-3-15David Gristwood Developer & Platform Group, Microsoft 适用于&#xff1a; Microsoft ASP.NET 2.0 (Beta 2) 摘要&#…

java面试题32:Java网络程序设计中,下列正确的描述是()

java面试题32&#xff1a;Java网络程序设计中,下列正确的描述是&#xff08;&#xff09; A&#xff1a;Java网络编程API建立在Socket基础之上 B:Java网络接口只支持tcP以及其上层协议 C&#xff1a;Java网络接口只支持UDP以及其上层协议 D:Java网络接口支持IP以上的所有高…

【收藏】C# WinForm开发系列 - DataGridView 使用方法集锦 - 宁波.Net技术讨论区

1.DataGridView实现课程表 testcontrol.rar 2.DataGridView二维表头及单元格合并 DataGridView单元格合并和二维表头.rar myMultiColHeaderDgv.rar 3.DataGridView单元格显示GIF图片 gifanimationindatagrid.rar 4.自定义显示DataGridView列(行头显示行号与图标,同一单元格显示…

Java中Map, List, Set和Queue的区别和使用场景

转&#xff1a;https://blog.csdn.net/kingcat666/article/details/75579632 1. Java集合类基本概念 在编程中&#xff0c;常常需要集中存放多个数据。从传统意义上讲&#xff0c;数组是我们的一个很好的选择&#xff0c;前提是我们事先已经明确知道我们将要保存的对象的数量…

java面试题33 Math.round(11.5) 等于多少 (). Math.round(-11.5) 等于多少 ( ).

java面试题33 Math.round(11.5) 等于多少 (). Math.round(-11.5) 等于多少 ( ). A 11 ,-11 B 11 ,-12 C 12 ,-11 D 12 ,-12 蒙蔽树上蒙蔽果&#xff0c;蒙蔽树下你和我。 做Java的面试题时遇到了以下这题&#xff0c;百度了一下Math.round()的修约规则&#xff0c;有的说…

VC返回文件所在的路径

//返回文件所在的路径void GetPath(CString& Des,char* src){CString TmpStr src;int Location TmpStr.ReverseFind("");Des TmpStr.Left(Location);}转载于:https://www.cnblogs.com/enterBeijingThreetimes/archive/2008/11/26/1341615.html

Protel 介绍 protel99se正式汉化版下载 Protel DXP2004简体中文版

1. Protel介绍 protel99se正式汉化版下载 Protel DXP2004简体中文版http://www.elecfans.com/soft/22/23/2008/200807315722.html2.protel99se正式汉化版免费下载http://www.elecfans.com/zhuanti/protel99se.htmProtel se&#xff1a;Protel 99SE具有丰富的设计功能&#xff0…