In her spare time, she listened to her daughter-in-law murmuring that she wanted to make a small program to express her daily mood, only she could send things on it. Now that the daughter-in-law has spoken, take some pains to do it, because there is no UI diagram, all the layout is made up by oneself. Now, we will explain the implementation process with pictures and code. The content is slightly longer, and we can have a list of interesting ones.
Following will be in the form of pictures, code and you will explain the implementation of this small demo process:
home page
Home page rendering
Home page explanation
- Music (only music related code is shown below)
<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 = this that.audioCtx = wx.createAudioContext('myAudio') that.getMusicUrl() }, methods: { getMusicUrl () { const that = this const db = wx.cloud.database() const music = db.collection('music') music.get().then(res => { that.audioUrl = res.data[0].musicUrl that.audioCtx.loop = true that.audioCtx.play() }) }, audioPlay () { const that = this if (that.isPlay) { that.audioCtx.pause() that.isPlay = !that.isPlay tools.showToast('You have suspended music playing~') } else { that.audioCtx.play() that.isPlay = !that.isPlay tools.showToast('Background music is on~') } } }
.bg_music position fixed right 0 top 20rpx width 100rpx z-index 99 display flex justify-content flex-start align-items flex-start .musicImg width 60rpx height 60rpx .music_icon animation musicRotate 3s linear infinite .music_play width 28rpx height 60rpx margin-left -10rpx transform-origin top -webkit-transform rotate(20deg) .playImg animation musicStop 1s linear forwards .pauseImg animation musicStart 1s linear forwards #myAudio display none
1. Obtain an example through wx. createInner AudioContext (), the music on Android can play normally, but not on IOS. The specific reasons for interest can be further explored.
2. Since the previous invitation letter widget related articles issued, the most question is still that music can not play this piece, so this demo will explain to you the principle of implementation below.
- calendar
Here the calendar uses a widget plug-in, the reason for putting a calendar on the home page is that the page does not appear too monotonous. Here's how the plug-in is used:
1. Log on to Wechat Public Platform > Settings > Third Party Settings > Add Plug-ins > Search for the name of the relevant plug-ins (better with appId search)> Click on the right side of a plug-in to view the details and enter the plug-in details page to add plug-ins, which can be added immediately.
2. The details of plug-ins are usually documented, or git addresses. The specific attribute events of plug-ins are introduced in the documents.
3. How to use plug-ins in projects is explained below.
1. Find the app.json file in the src root directory and add the following:
// "cloud": true, "plugins": { "calendar": { "version": "1.1.3", "provider": "wx92c68dae5a8bb046" } }
2. Add the following to the.json file of the page that needs to refer to the plug-in:
{ // "Navigation BarTitleText": "Daughter-in-law's mood diary". // "enablePullDownRefresh": true, "usingComponents": { "calendar": "plugin://calendar/calendar" } }
3. Use it directly on the page as follows (the meaning of the specific attribute method varies according to the corresponding plug-in):
<calendar :class="showCalendar?'':'hide_right'" class="right" weeks-type="en" cell-size="20" :header="showHeader" show-more-days=true calendar-style="demo4-calendar" board-style="demo4-board" :days-color="demo4_days_style" @dayClick="dayClick" />
- Weather and address
1. Here I use the help of Gaode Weixin applet SDK;
2. First, get the key value needed to use the relevant api, as follows:
3. Download the corresponding SDK (.js file) and introduce it into the project.
4. Obtain weather and address through relevant api:
getWeather () { const that = this let myAmapFun = new amapFile.AMapWX({key: 'You applied for it. key'}) myAmapFun.getWeather({ success (res) { // Successful callback that.address = res.liveData.city that.weather = res.liveData.weather + ' ' that.temperature = res.liveData.temperature + '℃' that.winddirection = res.liveData.winddirection + 'wind' + res.liveData.windpower + 'level' }, fail (info) { // Failure callback console.log(info) } }) },
- Publish diary
This involves publishing text and pictures. It is very likely that they will not be passed after the submission of personal procedures for examination. Although the personal procedures submitted to me for the first time have passed the examination, the subsequent audits have not passed, although I only restrict my and my daughter-in-law to issue diaries here, others can not see the bottom right at all. Corner issuance plus sign, but auditors will check the code, code once they find that similar publication of relevant content or words will lead to audit failure, but has passed once, daughter-in-law can write something normally, also basically meet the requirements, unfortunately, later to achieve some praise related functions are not more. New to online.
1. Determine whether the release plus sign in the lower right corner of the home page is displayed by the unique openId.
2. Later, we will explain the functions of uploading pictures to the cloud and storing them in the database.
- Praise function
1. Here, we recommend that the cloud function developed by the small program cloud can be used to implement the function, combined with the code:
<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>Tips</h3> <p>Are you authorized to use the Praise function?</p> <div class="bottom"> <button class="cancel" @tap="hideDialog">cancel</button> <button class="confirm" lang="zh_CN" open-type="getUserInfo" @getuserinfo="login">confirm</button> </div> </div> </div>
// Get a list of diaries getDiaryList () { const that = this wx.cloud.callFunction({ name: 'diaryList', data: {} }).then(res => { that.getSrcFlag = false that.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() }) }, // To offer or cancel a compliment. toLike (id, type, arr) { const that = this that.tempObj = { id: id, type: type, like: arr } wx.getSetting({ success (res) { if (res.authSetting['scope.userInfo']) { // Authorized to call getUserInfo directly to get the avatar nickname wx.getUserInfo({ success: function (res) { that.userInfo = res.userInfo wx.cloud.callFunction({ name: 'like', data: { id: id, type: type, like: arr, name: that.userInfo.nickName } }).then(res => { if (type === '1') { tools.showToast('Cancel some praise for success') } else { tools.showToast('Comment on Success~') } // The getOpenId() method executes once to get the list of diaries that.getOpenId() }) } }) } else { that.showDialog = true } } }) }, // Authorize access to user information login (e) { const that = this console.log(that.tempObj, e) if (e.target.errMsg === 'getUserInfo:ok') { wx.getUserInfo({ success: function (res) { that.userInfo = res.userInfo wx.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('Cancel some praise for success') } else { tools.showToast('Comment on Success~') } // The getOpenId() method executes once to get the list of diaries that.getOpenId() }) } }) } that.showDialog = false }
2. The home page gets the list of diaries. When I store the diaries into the database collection, I add a like attribute to each diary object. Like is an empty array by default.
3. When the user clicks or cancels the clicks, the tempObj attribute in component data temporarily stores three parameters:
(1) the _id of the corresponding diary;
(2) The type of user's operation is "point praise" (point praise is "2") or "cancel point praise" (cancel point praise is "1");
(3) The like array corresponding to the diary;
4. Use the wx.getSetting({}) of the applet api to determine whether the user has been authorized. If authorized to obtain user information, unauthorized, the bullet box guides the user to click the confirmation button to authorize manually.
5. After the authorization is successful, we get the user information. We begin to call the cloud functions related to the point approval or cancel the point approval. The following are the following:
const cloud = require('wx-server-sdk') cloud.init() const db = cloud.database() exports.main = async (event, context) => { try { // The wxContext contains the user's openId const wxContext = cloud.getWXContext() // Define empty arrays let arr = [] if (event.like && event.like.length > 0) { // Make the defined array equal to the like array in the current diary of the user's operation arr = event.like // Define a counting variable let count = 0 // Loop traversal, replacing the same item in the like array when openId is the same, and storing the corresponding type arr.forEach((item, index) => { if (item.openId === wxContext.OPENID) { count++ arr.splice(index, 1, { openId: wxContext.OPENID, type: event.type, name: event.name }) } }) // When the count variable is 0, it means that in this diary, the user has not been stored in the like array, push the user directly and store the type. if (count === 0) { arr.push({ openId: wxContext.OPENID, type: event.type, name: event.name }) } } else { // If the log like array itself is empty, push the current user directly and store the type arr.push({ openId: wxContext.OPENID, type: event.type, name: event.name }) } // update updates a data item in a collection by using _id return await db.collection('diary').doc(event.id).update({ data: { like: arr } }) } catch (e) { console.error(e) } }
6. Relevant cloud function operation instructions are all written in the comments above. There are unclear welcome messages. Since the function of clicking on praise has not been updated online (because the audit has not passed), students who want to experience can leave comments and provide experience privileges.
Publish your mood
Design sketch
explain
1. Enter the release mood page by issuing a plus sign in the lower right corner of the home page.
2. Relevant information such as address is brought from the home page through routing.
3. The following focuses on the operation process of uploading pictures to cloud storage and writing to the database. The contents are as follows:
upload () { const that = this wx.chooseImage({ count: 1, sizeType: ['compressed'], // You can specify whether it's original or compressed, both by default. sourceType: ['album', 'camera'], // You can specify whether the source is an album or a camera by default. success: function (res) { wx.showLoading({ title: 'Upload in' }) // Returns a list of local file paths for selected photos, tempFilePath can display images as src attributes of img Tags let filePath = res.tempFilePaths[0] const name = Math.random() * 1000000 const cloudPath = 'picture/' + name + filePath.match(/\.[^.]+?$/)[0] wx.cloud.uploadFile({ cloudPath, // Cloud Storage Picture Name filePath // Temporary Path }).then(res => { console.log(res) wx.hideLoading() that.imgUrl = res.fileID }).catch(e => { console.log('[Upload pictures] Failure:', e) }) } }) }, save () { const that = this if (that.desc) { that.getSrcFlag = false const 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('Write something about it.~') } }
4. The cloud Path here can be defined by itself, and stored in the cloud is as follows:
5. We temporarily store the uploaded image path manually through imgUrl in component data, and finally store it in cloud database by saving buttons, as in database:
Diary Details Page
Details page rendering
explain
1. Details will not be explained too much. Here we use some small program api, such as dynamic change of header title, dynamic random change of the top header background each time we enter, the point of praise is also brought from the home page.
Visitor Page
Design sketch
1. Before authorization
2. After authorization
summary
Although cloud development can be used, it is not recommended for large-scale project individuals. According to the effect of loading pictures and data, the traditional server obtains much faster data. Now that there is such a free tool, I think interested students can use it to play with a little demo and new tricks.
Source Link
https://github.com/TencentClo...
If you want to share your technical stories / experiences in developing CloudBase using the cloud, please leave a message to contact us.