这一篇是最长最复杂的,慢慢道来。
首先要或许用户的openid,即用户在本小程序的唯一表示,几乎在所有项目中都需要使用openid,在我的项目里,主要是通过openid判断用户是否已经点赞,获取的openid保存在全局变量中,方便各个页面调用,可以用云函数实现,非常简单。
在app.js里输入以下代码:
App({
onLaunch() {
wx.cloud.init({
env: 'shuanghei-8g9chbov02ee25e7'
})
wx.cloud.callFunction({
name: 'getopenid'
}).then(res => {
global = {
openid: res.openid //获取到的openid
}
getApp().globalData = global
})
}
})
详情页会列出评论,根据web端的样式,平时时间是以多久以前来展示的,如下图:
所以要自定义一个js方法,对long数据进行转换,在formatdata.js添加以下代码:
exports.longDateDiff = (long64) => {
let result
const minute = 1000 * 60
const hour = minute * 60
const day = hour * 24
const month = day * 30
const year = month * 12
const now = new Date().getTime()
const diffValue = now - long64
if (diffValue < 0) {
return
}
const yearC= diffValue / year
const monthC = diffValue / month
const weekC = diffValue / (7 * day)
const dayC = diffValue / day
const hourC = diffValue / hour
const minC = diffValue / minute
if (yearC >= 1) {
result = "" + parseInt(yearC) + "年前"
}
else if (monthC >= 1) {
result = "" + parseInt(monthC) + "月前"
} else if (weekC >= 1) {
result = "" + parseInt(weekC) + "周前"
} else if (dayC >= 1) {
result = "" + parseInt(dayC) + "天前"
} else if (hourC >= 1) {
result = "" + parseInt(hourC) + "小时前"
} else if (minC >= 1) {
result = "" + parseInt(minC) + "分钟前"
} else
result = "刚刚"
return result
之后开始写detail.js的代码了,先导入相关模块
import http from '../../utils/http'
import hljs from '../../utils/highlight'
import {
langtodata,
longDateDiff
} from '../../utils/formatDate'
定义属性:
/**
* 页面的初始数据
*/
data: {
articleModel: {},
//是否展示评论对话框
isShowDialog: false,
userInfo: {},
//未点过赞的样式
zanclass: 'icon-dianzan2',
zancolor: '#282828',
replys: 0,
replyList: []
},
定义一个方法将转移后的html代码反编码成正常的html代码
escape2Html(str) {
var arrEntities = {
'lt': '<',
'gt': '>',
'nbsp': ' ',
'amp': '&',
'quot': '"'
}
return str.replace(/&(lt|gt|nbsp|amp|quot);/ig, function (all, t) {
return arrEntities[t]
})
},
由于web端的评论是用邮箱来验证的,而小程序端是直接用微信用户名来入库的,所以定义一个方法隐藏邮件完整地址:
formatEmail(email) {
if (email.split('@').length > 1) {
let name = email.split('@')[0]
let domain = email.split('@')[1]
let com = domain.split('.')[domain.split('.').length - 1]
domain = domain.split('.')[0]
domain = `${domain[0]}**${domain[domain.length - 1]}.${com}`
if (name.length >= 4) {
name = `${name[0]}${name[1]}**${name[name.length - 2]}${name[name.length - 1]}`
}
return `${name}@${domain}`
} else {
return email
}
},
定义getarticle方法,从服务端获取文章的model,之前的文章也介绍过,需要将得到的content富媒体进行正则替换,才能正常显示代码高亮以及设置rich-text内的样式。
getarticle(articleid) {
http({
url: `/article/full/${articleid}`
}).then((res) => {
const rPre = /<pre>[\s\S]*?<\/pre>/g
const rCode = /<code.*?>([\s\S]*?)<\/code>/g
//r.test(res.data.content)
res.data.content = res.data.content.replace(rPre, (word) => {
rCode.test(word)
let html = this.escape2Html(RegExp.$1)
return `<pre><code class=\"hljs\">${hljs.highlightAuto(html).value}</code></pre>`
})
res.data.content = res.data.content.replace(/<img/g, '<img class=\"wximg\"')
res.data.content = res.data.content.replace(/<p>/g, '<p class=\"wxp\">')
res.data.createDatetime = langtodata(res.data.createDatetime)
this.setData({
articleModel: res.data
})
this.getdetail(articleid)
}).catch((err) => {
console.log('获取文章详情错误', err)
})
},
由于web端是生成静态页的,所以评论数、点赞等,都是通过ajax调用专门接口获得的,所以再定一个getdetail方法来获取这些数据。
这里的url参数最后加一个@xcx.com是因为,web端判断用户唯一标识是通过邮箱来验证的,所以数据库验证中,必须是email正常格式,为了符合要求,手动在字符串最后加上"@xcx.com"。
如果点过赞,则执行haszan方法,如果评论大于0,则获取评论列表。
getdetail(id) {
http({
url: `/article/detail/${id}?email=${getApp().globalData.openid}@xcx.com`
}).then((res) => {
this.setData({
replys: res.data.reply
})
if (res.data.reply > 0) {
this.getreplylist()
}
if (res.data.haszan) {
this.haszan()
}
}).catch((err) => {
wx.showToast({
title: '获取文章详情错误!',
icon: 'error',
duration: 1000
})
})
定义getreply方法,获取文章的评论。
getreplylist() {
http({
url: `/reply/article/${this.data.articleModel._id}/20/`
}).then((res) => {
let list = res.data.map(item => {
item.createDatetime = longDateDiff(item.createDatetime)
item.from=this.formatEmail(item.from)
return item
})
this.setData({
replyList: this.data.replyList.concat(list)
})
}).catch((e) => {
wx.showToast({
title: '获取评论错误!',
icon: 'error',
duration: 1000
})
})
},
定义haszan方法,改变点赞按钮的样式。
haszan() {
this.setData({
zanclass: 'icon-dianzan',
zancolor: 'red'
})
}
好了,到这里,详情页数据调用基本完成,接下去就是互动环节了,也就是底部固定的评论、点赞和分享。