В свободное время она слушала, как невестка шепчет, что хочет сделать для нее небольшую программу, чтобы выражать свое повседневное настроение, и ей остается только что-то постить на ней. Теперь, когда невестка высказалась, давайте приложим небольшое усилие, потому что UI-схемы нет, все макеты все придуманы сами, контент чуть длиннее, а кому интересно, можно посмотреть на взглянуть мельком.
Далее будет объяснен процесс реализации этой небольшой демонстрации в виде изображений и кодов:
титульная страница
Визуализация главной страницы
Домашняя страница
- Музыка (ниже показаны только коды, связанные с музыкой)
<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('您已暂停音乐播放~')
} else {
that.audioCtx.play()
that.isPlay = !that.isPlay
tools.showToast('背景音乐已开启~')
}
}
}
.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. Получить экземпляр через wx.createInnerAudioContext().Музыка нормально воспроизводится на Android, но не на IOS.Если вас интересуют конкретные причины, то можно углубиться.
2. Поскольку предыдущая статья об апплете приглашения была выпущена, наиболее часто задаваемый вопрос заключается в том, что музыка не может быть воспроизведена, поэтому в этой демонстрации будет объяснен принцип реализации.
- календарь
Календарь здесь использует подключаемый модуль апплета Причина, по которой календарь размещен на главной странице, состоит в том, чтобы страница не была слишком монотонной. Вот как использовать плагин:
1. Войдите на общедоступную платформу WeChat> Настройки> Сторонние настройки> Добавить плагины> Найдите название связанных плагинов (лучше использовать appId для поиска)> Нажмите «Просмотреть подробности» в правой части плагина, введите плагин страница сведений для добавления плагинов, как правило, вы можете сразу добавить пропуск;
2. В сведениях о подключаемом модуле обычно есть документы об использовании или адреса git, и в документе будут представлены конкретные атрибутивные события подключаемого модуля;
3. Ниже объясняется, как использовать плагин в проекте:
(1) Найдите файл app.json в корневом каталоге src и добавьте следующее:
// "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=true
calendar-style="demo4-calendar"
board-style="demo4-board"
:days-color="demo4_days_style"
@dayClick="dayClick"
/>
- погода и адрес
(1), здесь я используюSDK программы AutoNavi WeChat Mini;
(2), сначала получите значение ключа, необходимое для использования соответствующего API, следующим образом:
(3) Загрузите соответствующий SDK (файл .js) и внедрите его в проект;
(4), получить погоду и адрес через соответствующий API:
getWeather () {
const that = this
let myAmapFun = new amapFile.AMapWX({key: '你申请的key'})
myAmapFun.getWeather({
success (res) {
// 成功回调
that.address = res.liveData.city
that.weather = res.liveData.weather + ' '
that.temperature = res.liveData.temperature + '℃'
that.winddirection = res.liveData.winddirection + '风' + res.liveData.windpower + '级'
},
fail (info) {
// 失败回调
console.log(info)
}
})
},
- Опубликовать дневник
Это предполагает публикацию текстового и графического содержимого.После того, как личный апплет будет отправлен на проверку, очень вероятно, что он не будет одобрен.Хотя в первый раз я представил свой личный апплет и прошел проверку, последующие проверки не прошли, хотя Я здесь Только я и моя жена можем размещать дневники Остальные вообще не видят плюсика выпуска в правом нижнем углу, но рецензенты проверят код Как только найдут похожий контент или слова связанные с публикацией в коде , это приведет к просмотру. Я не прошел, но к счастью, я прошел его один раз, и моя невестка может написать что-то нормально, что в принципе соответствует требованиям. К сожалению, функции, связанные с лайками, не были обновлены онлайн.
(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 = 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()
})
},
// 点赞或取消点赞
toLike (id, type, arr) {
const that = this
that.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.userInfo
wx.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 = 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('取消点赞成功')
} else {
tools.showToast('点赞成功~')
}
// getOpenId()方法里会执行一遍获取日记列表
that.getOpenId()
})
}
})
}
that.showDialog = false
}
(2) Домашняя страница получает список дневников.При сохранении дневника в коллекции базы данных я добавлю атрибут like к каждому объекту дневника, а like по умолчанию является пустым массивом;
(3) Когда пользователю нравится или отменяет лайк, атрибут tempObj в данных компонента будет временно хранить три параметра ①, _id соответствующего дневника; ② тип операции пользователя похож (например, «2») или отменить лайк (отмена лайка равна «1») 3. Массив лайков, соответствующий дневнику;
(4) Определите, был ли пользователь авторизован через wx.getSetting({}) API апплета. Если он авторизован для получения информации о пользователе, если он не авторизован, всплывающее окно подсказывает пользователю нажать кнопку подтверждения для авторизации вручную;
(5) После успешной авторизации и получения информации о пользователе мы начинаем вызывать облачные функции, связанные с лайком или отменой лайка, следующим образом:
const cloud = require('wx-server-sdk')
cloud.init()
const db = cloud.database()
exports.main = async (event, context) => {
try {
// wxContext内包含用户的openId
const wxContext = cloud.getWXContext()
// 定义空数组
let arr = []
if (event.like && event.like.length > 0) {
// 让定义的数组等于用户操作的当前日记下的like数组
arr = event.like
// 定义一个计数变量
let count = 0
// 循环遍历,当openId相同时替换like数组中的相同项,并存储对应的type
arr.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此用户并存储type
if (count === 0) {
arr.push({
openId: wxContext.OPENID,
type: event.type,
name: event.name
})
}
} else {
// 如果此条日记like数组本身就为空,直接push当前用户并存储type
arr.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) Соответствующие инструкции по работе с облачными функциями написаны в комментариях выше.Если есть какая-либо неясная информация, пожалуйста, оставьте сообщение. Функция лайка не обновлялась онлайн (причина - не прошла проверка), кому интересно, могут реализовать эту функцию по вышеизложенным идеям.
Выразите свое настроение
визуализация
объяснять
(1) Войдите на страницу настроения релиза через значок плюса релиза в правом нижнем углу главной страницы;
(2) Соответствующая информация, такая как адрес, переносится с домашней страницы по маршруту;
(3), далее основное внимание уделяется процессу загрузки изображений в облачное хранилище и записи в базу данных.Содержание выглядит следующим образом:
upload () {
const that = this
wx.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() * 1000000
const 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 = 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('写点什么吧~')
}
}
(4), путь к облаку здесь можно определить самостоятельно, а хранилище в облаке выглядит так:
(5) Мы временно сохраняем загруженный вручную путь к изображению через imgUrl в данных компонента и, наконец, сохраняем его в облачной базе данных вместе с помощью кнопки сохранения, которая сохраняется в базе данных следующим образом:
Страница сведений о журнале
Визуализация страницы сведений
объяснять
(1) Детали объясняются не слишком много.Здесь используются некоторые небольшие программные API, например, заголовок заголовка динамически изменяется, а фон верхнего заголовка случайным образом меняется каждый раз, когда динамический ввод вводится, и количество лайки тоже привозятся с главной страницы;
гостевая страница
визуализация
(1), до авторизации
(2), после авторизации
Адрес источника
Испытайте QR-код
Поскольку невестка не хочет, чтобы другие видели то, что она написала, поиск апплета по имени скрыт, если вы хотите добиться аналогичной функции, обратитесь к исходному коду. После того, как количество посетителей сможет просмотреть лимит, QR-код выдается здесь:
Вопросы, возникающие в демоверсии
Некоторые аватары пользователей становятся пустыми
(1), следующим образом:
(2) После просмотра базы данных поле аватара действительно пустое:
Суммировать
Хотя можно использовать облачную разработку, она не рекомендуется для частных лиц в крупных проектах.Из-за эффекта загрузки изображений и данных данные, полученные традиционным сервером, очевидно, намного быстрее.Так как есть такой бесплатный инструмент, я хочу чтобы почувствовать заинтересованность, ученики могут использовать его, поиграть в небольшую демонстрацию, новые трюки, я надеюсь, что эта статья поможет нуждающимся ученикам, они видели ее здесь, поставьте лайк, а затем уходите~