“Get all the common functions of blog applets in one go” with applets · Cloud development

This article introduces how to realize the function button of the detail page of mini blog mini program, including comment, like, favorite and poster function specifically, here records the whole implementation process and some pits in the actual code.

Comments, likes, favorites function

Implementation approach

Implementation, the function of some articles, the main or comment, it is the bridge of communication between authors and readers, the comment function of derivative is nothing more than refinement of the interaction between the writer and the reader, or increase the spread of the article, when begin development so need to think about what you expect to achieve function, and the corresponding functions are realized.

My general rule of thumb is to go through the required features and general flow in my head, and then sketch a “very basic prototype, equivalent to the character of the product” in my notes.

Then I directly started to build the page and simple interaction “use fake data, finish the page first”. In fact, when constructing the page, I could supplement some defects in the process of the initial idea, so that I could make up for them in the design of the back-end and database structure, and the whole thing was basically perfect.

Looking back at the requirements of my small program, the first must be operation, at the bottom of the article needs to have an operation bar, used to send comments and other operations, after referring to some of the same type of small program, gradually realize their own set of style, style screenshots are as follows:

Once the feature is in place, the comment data needs to have a place to display “usually at the bottom of the post”, and then you have a list of comments at the bottom of the post, like this:

Since there is a “like” and “favorites” function button, does the user need to see the list of articles I “like” and “favorites”, so there is a corresponding list in “my”, the style is as follows:

So far, the most basic functions are almost the same, and then it depends on whether the back end can support these pages. “The main thing is to save and display data.”

For comments, there is definitely a need for a collection to hold user comments, and for user likes and favorites.

So based on the page we can design mini_comments and mini_posts_related collections. The former is used to save comment data, while the latter users save associations between user actions and articles.

The rest of the job is to realize, is nothing more than page interaction and data add, delete, change and check.

Detail point analysis

About the number of comments

There is currently a totalComments attribute in the collection of articles, which is incremented by 1 each time a comment is added to the article.

When I first wrote this, I checked it first and then updated it in two paragraphs. The original code is as follows:


let count=post.totalComments+1;

let result =await db.collection('mini_posts').doc(event.commentContent.postId).update({

​    data: {

​      totalComments: count

​    }

  });

Copy the code

When I look at the documentation, I find that db.command. Inc can be used to add 1 to the original field without having to look it up again, and still maintain atomicity. The code is as follows:


const _ = db.command

let result = db.collection('mini_posts').doc(event.commentContent.postId).update({

​    data: {

​      totalComments: _.inc(1)

​    }

  });

Copy the code

About adding sub-comments

Need to implement a reply under a comment.

In the interaction, when you click the commenter’s nickname or avatar, the corresponding click event will be triggered, in which the corresponding comment ID and necessary data will be recorded, and the focus will be set in the comment box:

/** * Click on the comment to reply */ focusComment:function (e) {

​    let that = this;

​    let name = e.currentTarget.dataset.name;

​    let commentId = e.currentTarget.dataset.id;

​    let openId = e.currentTarget.dataset.openid;



​    that.setData({

​      commentId: commentId,

​      placeholder: "Reply" + name + ":",

​      focus: true,

​      toName: name,

​      toOpenId: openId

​    });

  },

Copy the code

Db.com mand. Push can be used to operate “update instruction, add one or more values to the end of an array of values for a field” when adding sub-comments in cloud development, and add:

/** * Add child comment * @param {} event */ asyncfunction addPostChildComment(event) {



  let task = db.collection('mini_posts').doc(event.postId).update({

​    data: {

​      totalComments: _.inc(1)

​    }

  });

  await db.collection('mini_comments').doc(event.id).update({

​    data: {

​      childComment: _.push(event.comments)

​    }

  })

  await task;

}

Copy the code

About judging whether it has been collected

When the article is loaded for the first time, we need to determine whether the user has related operations on the article. If there are corresponding favorites and likes, the corresponding function ICONS need to be updated during initialization. The core code is as follows:

/** * Get favorites and likes */ getPostRelated: asyncfunction (blogId) {

​    let where = {

​      postId: blogId,

​      openId: app.globalData.openid

​    }

​    let postRelated = await api.getPostRelated(where, 1);

​    let that = this;

​    for (var item of postRelated.data) {

​      if (config.postRelatedType.COLLECTION === item.type) {

​        that.setData({

​          collection: { status: true, text: "Collected", icon: "favorfill"}})continue;

​      }

​      if (config.postRelatedType.ZAN === item.type) {

​        that.setData({

​          zan: { status: true, text: "Has been praised", icon: "appreciatefill"}})continue; }}},Copy the code

As for other interaction details and code details, you can read the source code to experience, if you have any questions or better implementation, you can also communicate with me.

Posters feature

Give some background

In fact, before the first small program has been implemented once, specific can refer to the use of cloud development optimization blog small program (three) – poster generation function, mainly using native Cavans for assembly, originally wanted to code copy to change on the line, but always feel that the original code is not particularly good.

I wanted to see if there was a wheel I could use, and sure enough, I found wXA-plugin-Canvas, a component that can generate beautiful posters with a very simple configuration.

Applets use NPM

Before summarizing the poster generation function, it is necessary to document the use of small program NPM to avoid unnecessary pitfalls.

Considering the size limitations of applets themselves, the NPM approach is optimal.

The reason is that according to the official documentation, only the build file generation directory in the applets NPM package is counted as the occupied space of the applets package, and only the code in this directory is uploaded when the applets code is uploaded. This greatly reduces the size of the uploaded code.

Here is a brief introduction to how to use the small program side of NPM “actually according to the official documentation to follow the steps can be”.

/miniprogram/node_modules /miniprogram /miniprogram/node_modules /miniprogram/node_modules /miniprogram/node_modules /miniprogram/node_modules

Install using commands:


npm install wxa-plugin-canvas --production  

Copy the code

After the installation is successful, you can build in the small program development tool. Before building, you need to check the USE of the NPM module

Then click on the Developer Tools menu bar: Tools > Build NPM:

After the build is complete, the miniprogram_npm directory will be generated. At this point, the project side is basically tuned through.

wxa-plugin-canvas

Once built, the wXA-plugin-Canvas custom component can be used normally, which is relatively simple to use.

Start by introducing this component on the page you want:


{

  "usingComponents": {"poster": "wxa-plugin-canvas/poster"}}Copy the code

Then you can use it in WSML:


<poster id="poster" hide-loading="{{false}}" preload="{{false}}" config="{{posterConfig}}" bind:success="onPosterSuccess" bind:fail="onPosterFail"></poster>

Copy the code

Since we need to obtain some data for the poster asynchronously before generating the poster, we adopt the way of generating the poster asynchronously.

Import the poster/poster.js file for this component and call it in code:


import Poster from '.. /.. /utils/poster'; Page({/** * asynchronously generate posters */onCreatePoster() {

​    	// setThis.setdata ({posterConfig: {posterConfig... } }, () => { Poster.create(); }); }})Copy the code

Core code parsing

The data needed for the poster

Let’s take a look at the overall structure of the shared poster:

First, we need to confirm what data is needed for the composition of the poster, and obtain the corresponding data before invoking the component.

The poster I designed mainly contains three pieces of content: user information (head picture and nickname), article information (first picture, title, introduction) and the most important small program code of the article.

User information and article information is actually relatively simple, in the details page of the applet have both data, but there are two problems need to pay attention to.

The first one is the domain name problem. All the pictures used in the canvas need to be configured with the domain name, the domain name of the profile picture and the domain name of the public account


https://mmbiz.qpic.cn

https://wx.qlogo.cn

Copy the code

The image URL returned by the material list of the public account is actually HTTP, but the small program stipulated that the binding domain name must be HTTPS. At that time, I had no choice, but later I tried to use HTTPS to access the URL of the first image. Fortunately, I used the address of the first image instead:


imageUrl = imageUrl.replace('http://'.'https://')

Copy the code

Finally, the article’s small program code, the need to use small program getUnlimited API, specific can refer to the official document, has provided the cloud call way “no need to obtain access_token”, call is relatively simple.

Had originally planned to at the time of sync “adminService” directly generate corresponding article small program code, the code is written after the local debugging can, but will be uploaded to the cloud after tests found has been an error, just know originally does not support around the tyres, the trigger at the same time also does not support cloud call, so the plan fell through, I play the TODO in the code.

In this case, it will be generated when the poster is generated, and then directly uploaded to the cloud storage, and the corresponding FileID will be saved to the article collection. In this way, it can be used all the time only once generated, the specific code is as follows:

@param {} event */ asyncfunction addPostQrCode(event)

{

  let scene = 'timestamp=' + event.timestamp;

  let result = await cloud.openapi.wxacode.getUnlimited({

​    scene: scene,

​    page: 'pages/detail/detail'

  })



  if (result.errCode === 0) {

​    let upload = await cloud.uploadFile({

​      cloudPath: event.postId + '.png',

​      fileContent: result.buffer,

​    })



​    await db.collection("mini_posts").doc(event.postId).update({

​      data: {

​        qrCode: upload.fileID

​      }

​    });



​    let fileList = [upload.fileID]

​    let resultUrl = await cloud.getTempFileURL({

​      fileList,

​    })

​    return resultUrl.fileList

  }



  return[]}Copy the code

However, there is an awkward place here. The maximum length of scene parameter in the API that generates the mini_posts code is 32, and the length of the article ID is already 32, so we cannot splice the path to the page according to the article ID. Therefore, we temporarily use the timestamp field in the mini_posts set “theoretically unique”.

So the timestamp field also needs to be compatible in the detail page.

Poster and picture display

Poster picture display is relatively simple, use a popover, will generate a good poster picture to display:

@param {} e */ onPosterSuccess(e) {const {detail} = e; this.setData({ posterImageUrl: detail, isShowPosterModal:true

​    })

​    console.info(detail)

  },

Copy the code

Save the poster image

Save images using wx. SaveImageToPhotosAlbum calling user photo albums, which need to be compatible with the user refused to photo album a series of operations, authorized by the specific code is as follows:

/** * save the poster image */ savePosterImage:function () {

​    let that = this

​    wx.saveImageToPhotosAlbum({

​      filePath: that.data.posterImageUrl,

​      success(result) {

​        console.log(result)

​        wx.showModal({

​          title: 'tip',

​          content: 'Qr code poster has been stored in the mobile phone album, please share it in moments as soon as possible',

​          showCancel: false,

​          success: function (res) {

​            that.setData({

​              isShowPosterModal: false,

​              isShow: false

​            })

​          }

​        })

​      },

​      fail: function (err) {

​        console.log(err);

​        if (err.errMsg === "saveImageToPhotosAlbum:fail auth deny") {

​          console.log("Re-authorize");

​          wx.showModal({

​            title: 'User not authorized',

​            content: 'If you want to save the poster image to the album, you need to obtain authorization. Is Save to Album selected in authorization Management? ',

​            showCancel: true,

​            success: function (res) {

​              if (res.confirm) {

​                console.log('User hits OK')

​                wx.openSetting({

​                  success: function success(res) {

​                    console.log('Open Settings', res.authSetting);

​                    wx.openSetting({

​                      success(settingdata) {

​                        console.log(settingdata)

​                        if (settingdata.authSetting['scope.writePhotosAlbum']) {

​                          console.log('Succeeded in obtaining permission to save to album');

​                        } else {

​                          console.log('Failed to get save to album permission'); }}})}}); }}})}}}); },Copy the code

Experience summary

  • There are good open source components to take advantage of, avoid reinventing the wheel, and learn from others’ implementations if you have the opportunity.

  • Take a look at the documentation, in fact, small program documentation is really quite detailed.

  • Here I want to share the process of implementing a feature and how to successfully implement it step by step when I have an idea.

  • The small program itself is not difficult, the corresponding documentation is also very detailed, but the assembly process and the realization of logic need to think and experience. Take a look at the documentation, in fact, small program documentation is really quite detailed.

  • If your ideas and processes are clear, but you’re still not doing what you want them to do, I suggest you take a break, familiarize yourself with HTML, CSS, and javascript, and look at the documentation a few times. Maybe the problem you’re having isn’t a problem anymore.

Source link

Github.com/TencentClou…