某相册类小程序项目总结
1.项目简介
一款为家庭设计的亲密社交产品,分为云端存储、智能电视、小程序三个平台,小程序端主要功能包括:
- 建立相册,上传图片、视频,
- 单张图片(视频)的预览、分享、下载、评论
- 相册集预览、分享、下载、评论
- 相册内容管理,删除、下载、设置封面、重命名、设置成开机视屏及屏保图片等
- 照片共享,手机、电视多端家庭内容同步和管理
- 邀请、删除家庭成员,添加、删除绑定设备
- 个性化设置家庭昵称、自己昵称、相册名称
2. 主要工作和疑难点汇总
2.1 主要工作
- 封装api请求,改造wx.requeset方法,封装http请求
- 抽取公共样式文件,在每个page文件夹的.wxss文件中,通过import 引入,
如:@import "../../lib/base.wxss"; - 抽取公共组件,如单个相册组件、弹出卡片组件、个人头像组件、照片卡片组件,通过在各个页面配置usingComponents参数使用。
- 封装全局公共函数
- 业务逻辑
-
接入百度统计, 统计实时数据
在我的应用中添加小程序appkey,下载解压后的js文件到utils文件夹中去,同时将百度添加到request合法域名中去。
2.2 业务亮点
2.3 疑难点汇总
- 如何在小程序中使用less,可以实时转化为 .wxss文件?
- 小程序Page里的函数比app.js先执行的解决办法
- fixed 元素 auto 不生效原因
- 封装一个有输入框的modal层组件
- 微信小程序去除button默认边框样式
- 小程序如何获取点击元素信息
- 小程序如何在页面间传递数组对象?
-
小程序如何批量上传图片
chooseImage、chooseVideo的回调函数中,wx.uploadFile 上传,更新进度 this.data.updated_length + 1 当所有照片都上传成功,updated_length == total_length时, 显示完全上传完毕 视频的进度显示和图片的不一样 图片是每次上传成功一张,updated_length + 1 视频是调用 wx.uploadFile 对象的 onProgressUpdate 函数,看到视频上传进度,每500毫秒更新一次
- 小程序几个组件
-
如何让swiper 跳转到点击的index ?
current 参数 preview了, 还能点击图片么, 失败,不使用 https://www.cnblogs.com/BlueCc/p/10172742.html
- 动态设置小程序背景图片
-
如何实现分享、点赞功能
分享: onShareAppMessage, 点赞:根据本人是否点赞过,是否有点赞权限 onShareAppMessage: function(res) { var obj = { from: 'sharephoto', mac: app.globalData.mac, open_id: app.globalData.open_id, member_id: app.globalData.current_member.member_id, family_id: app.globalData.family_id, album_id: this.data.album_id } obj = JSON.stringify(obj); var name = app.globalData.current_member.nick_name; var shareObj = { title: `${name}跟你分享了一本有趣的相册集‘${this.data.album_title}’`, // 默认是小程序的名称(可以写slogan等) path:`pages/login/login?message=${obj}`, imageUrl: this.data.album_cover, //自定义图片路径,可以是本地文件路径、代码包文件路径或者网络图片路径,支持PNG及JPG,不传入 imageUrl 则使用默认截图。显示图片长宽比是 5:4 success: function(res){ }, fail: function(){ } }; return shareObj; }, //节流,300ms才能点一次 if (this.timer) { clearTimeout(this.timer) } this.timer = setTimeout(() => { console.log('点击点赞', this.data.like_id); server.like(family_id, this.data.album_id, mac, member_id, open_id, app.globalData.open_id, form_id, this.data.like_id).then((res)=>{ this.getPhotoBlock(); }) }, 300)
-
如何实现全选、单选功能
对某一天日期的照片,如果没张都选了,传递今天整个相册 每次单选照片都会重新判断是否全选
-
小程序时间过滤器 formatTime util的使用
wxs中new Date()等js方法不可用, 所以不能用过滤器,还是用方法
-
为什么多个 formId 会重复,
因为不支持同时获取多个 formId, 每次只能获取一个
-
如何实现预览照片,点击后跳转到单张照片?
wx.previewImage,这里注意 swiper中,currentIndex 左右滑动是否一致,change函数的处理。
-
如何支持同时预览图片和视频?
直接使用 wx.previewImage缺点:不能支持视频,不支持对单张照片做其他操作,智能预览,所以先跳转到 swiper页面 点击照片,预览单张照片。点击视频,跳转到vediofull页面。
-
视频播放是否全屏
videofullchange,监听全屏事件,小程序视频根据尺寸判断全屏 在 chooseVideo 的时候, 获取视频的高宽
-
解决,如果有其他照片上传失败怎么办?
每次调用 showProgress
-
如何判断小程序来源?分享?邀请?
this.data.message.from几个值判断,一共有9种情况 邀请、分享、在家庭中,不在家庭中,是不是管理员,是否来源扫一扫 单张相片 相册 受到邀请,不在家庭 受到邀请,在家庭中 扫一扫,不在家庭中 扫一扫,在家庭中,是管理员 扫一扫,在家庭中,不是管理员 不是成员,不是扫一扫 已经在家庭中 其他
-
showActionSheet 有长度限制吗?
有6个,超过怎么办?二层底部弹卡
- 如何见人照片与视频
- 内容过滤
- 接入百度移动统计
-
授权问题
问题出现在,分享给第三人单张照片的时候,未先授权小程序前,不能查看照片,改变login页面逻辑,去掉入门授权,在点击分享、下载时候再询问授权 首页、家庭页,操作后才授权,点击前会有蒙层
-
安全问题
需要操作的页面,onLoad都会 checkInFamily,如果不在任何家庭中,跳转到scan页面
-
哪些情况下展示红包?
创建相册、邀请成功成员
-
如何通过扫描二维码获得数据
wx.scanCode, 获取返回参数
- 如何判断自己有没有全选评论、点赞、编辑?
如果照片、视频来源于分享者,且分享人的id=评论id,用分享人的信息给后端传递参数。无论是获取评论、删除评论、发送评论,被分享人都是使用的分享者信息。
-
一级tab页面需要哪些验证?
1,首先检查有没有授权,wx.getUserInfo,授权后下一步操作 2,检查checkIn,在不在家庭中,有没有操作权限,没有退出 3,获取成员信息,检查有没有红包,有,领取后下一步操作
-
如何拿到信息扫描?
wx.scanCode({ success: (res)... 通过res值获取
-
获取验证码逻辑
me.data.timerFun = setInterval(function () { if (me.data.timer > 0) { me.setData({timer:me.data.timer-1}) }else { me.setData({timer:'重新发送'}) clearInterval(me.data.timerFun); } }, 1000);
4. 业务逻辑梳理
4.1 项目哪几个page组成?有几个组件?
| 16个page | 5个组件 |
| ---- | ---- |
| login | 获取token、管理跳转 |
| le_login | 同步账号 |
| about | 账号绑定、消息、关于、意见反馈 |
| photo-edit | 照片编辑页 |
| select-device | 选择屏保页面 |
| h5 | 红包页面 |
| comment | 评论列表页面 |
| swiperphotos | 视频、照片滑动页面 |
| vediofull | 全屏播放视频页面 |
| photomanage | 照片管理页面,全选、反选、下载 |
| photos | 相册所有照片页面 |
| one-photo | 单张照片分享页面 |
| homepage | 首页,我的相册页面 |
| familypage | 家庭首页 |
| del-member | 删除成员、设备页面 |
| my-modal | 弹卡组件|
| member-icon | 头像组件|
| photo-album | 相册组件|
| photo-detail | 相册详情组件|
| red-packet | 红包组件|
4.2 挑几个页面看看
-
family 页面?
1.1 邀请成员
主要通过 onShareAppMessage 函数,将邀请人的信息添加在 path的参数中,在login页面中获得
1.2 添加设备
调整到 homescan页面
1.3 退出家庭
//如果只剩本人自己, 解散家庭,否则按照退出家庭算
-
photomanage 页面?(点击,下载、设置壁纸,设置屏保后跳转的页面)
全选,反选逻辑 设置封面逻辑,如何做到 所有天,只有一个封面?每一天的照片、视频,是一个组件 select_photos 所有选中的照片 选照片、下载、删除逻辑: 传值过来的是 按日期分布的数组,按照日期对应,修改当天的照片数组。 遍历所有天的照片,计算选中张数,编号。 设置封面逻辑: 所有天照片,只有有一天选中了,其他所有置灰。
-
photos 页面? 点击相册进入的页面
功能:上传照片、视频,点赞、评论
-
vediofull 页面
首先需要创建视频播放上下文对象 wx.createVideoContext('myVideo'); 退出: 视频对象 pause,退出全屏, 对象置为null 监听是否需要横屏: 如果视频宽度大于高度,横屏
-
swiperphotos 页面
如何支持,同时预览照片和视频? 不使用原生自带的 wx.previewImage 视频,跳转到 vediofull 页面 定位到当前照片是,所有 swiper数组的第几章照片 初始状态,当前滑动照片数,预览照片上面的显示数字,current_index,和 swiper组件绑定的,current值差1,change函数滑动照片,改变current_index值
5. 几个组件简介
-
member-icon:
支持头像组件两种形态:文字在头像下方、文字在头像右方
-
my-modal:
支持弹出会话层有input文本框,支持编辑和新建功能 新建相册名称为空,编辑相册名称为相册名称,怎么做到的? 新建,文本框内容为update_value,编辑为从父类传过来的数据,textvalue 如何在操作完编辑后,新建,相册名称为空? 每次确认后,input框内容置空 实时计算文本框字数? bindinput函数
-
photo-album: 相册组件
每个相册组件,点击跳转到该相册详情页面
-
red-packet: 红包组件
//将红包信息参数发送给后端,传递给前端一个web-view 地址链接 //webview src指向网页的链接。(承载网页的容器,会自动铺满整个小程序页面) <web-view src="{{link}}"></web-view>
-
photo-detail: 相册详情组件,支持同一天照片全选、反选,设置屏保、删除、下载等功能
如何区分对照片的操作类型?设置封面?下载?删除?根据前一个页面传过来的操作类型判断 photo-detail只是一天的照片、视频操作,如何将所有日期选中照片传递给后端? 每次触发某一天的照片,是一个数组,向父元素触发事件, this.data.photo_block.forEach((item, index)=> { if(item.days == photo.days) { this.data.photo_block[index] = photo; } }) 如何统计总数? 每次重新计算选中照片。遍历。
6. 问题汇总解答
1. 如何在小程序中使用less,可以实时转化为 .wxss文件?
微信小程序只支持原生css写法,但是很浪费时间,使用 wxss-cli 可以实时将编写的 .less 文件自动编译为 .wxss 文件
1、npm或者yarn全局安装wxss-cli
npm install -g wxss-cli
2、运行wxss-cli命令(miniProject为小程序目录),less文件保存时自动编译
wxss ./miniProject
2. 小程序Page里的函数比app.js先执行的解决办法
问题描述:
当我们初始化一个小程序时,默认文件 app.js 中有onLaunch函数,
onLaunch: function () {
console.log("onLaunch");
wx.login({
success: res => {
console.log("login");
// 发送 res.code 到后台换取 openId, sessionKey, unionId
}
})
}
默认目录,"pages/index/index", 中index.js 有 onLoad函数
onLoad: function () {
console.log("index onLoad");
}
小程序网络请求默认为异步请求,在app.js的onLaunch运行后进行异步请求时,程序不会停止,index.js页已执行onload, onload里面的数据会因为没有获取到app.js里的东西而报错, 我们希望onLaunch执行完后再执行onLoad。
他们的执行顺序是,onLaunch > index onLoad > login
我们希望的执行顺序是:
onLaunch > login > index onLoad
解决办法
- 定义回调函数, onload里获取不到东西就一直获取,不执行下一步操作,直到获取到app.js的数据才继续执行。若login返回为空,则给app.js注册一个loginSuccessCallback回调,这个回调方法的执行时机,就是app.js中的异步请求完毕
- 把 app.js 中的 onLaunch 中方法拿到 index.js 文件中,按照自己的逻辑写
- 使用promise
方法1:
App({
onLaunch: function () {
wx.login({
success: res => {
this.globalData.checkLogin = true;
//由于这里是网络请求,可能会在 Page.onLoad 之后才返回
// 所以此处加入 callback 以防止这种情况
if (this.checkLoginReadyCallback){
this.checkLoginReadyCallback(res);
}
}
})
},
globalData: {
checkLogin: false
}
...
})
//index.js
//获取应用实例
const app = getApp()
Page({
data: {
test: false
},
onLoad: function () {
let that = this;
//判断onLaunch是否执行完毕
if (app.globalData.checkLogin){
that.setData({
test:true
})
}else{
app.checkLoginReadyCallback = res => {
//登陆成功后自己希望执行的,和上面一样
that.setData({
test:true
})
};
}
}
})
方法2:
把 app.js 中的 onLaunch 中登陆后才执行的方法拿到 index.js 文件中,这是最简单的方法
//index.js
onLoad: function () {
wx.login({
success: res => {
resolve(res);
}
})
}
方法3:
// app.js中定义一个新的方法
App({
onLaunch: function () {
...
},
getAuthKey: function (argument) {
var that = this;
return new Promise(function(resolve, reject){
wx.login({
success: res => {
resolve(res);
}
})
})
}
...
})
//index.js
onLoad: function () {
...
app.getAuthKey().then(function(res){
console.log('res')
})
}
3. fixed 元素 auto 必须要同时设置 top、left
position: fixed;
top: 132rpx;
left: 30rpx;
width: 690rpx;
margin: 0 auto;
4.封装一个有输入框的modal层组件
其实很简单,就是在modal中添加新的 input,
<view>
<modal class="modal" wx:if="{{!hiddenModal}}"
title="{{title}}" confirm-text="确定" cancel-text="取消" bindconfirm="modalconfirm" bindcancel="modalcancel">
<view class="input-line">
<input placeholder='请输入内容' maxlength="{{ maxlength }}" bindinput='input' type="text" type="text" value="{{ textvalue }}" />
<text>{{ currentlength}}/{{ maxlength }}</text>
</view>
</modal>
</view>
.modal{
width: 540rpx;
max-width: 540rpx;
border-radius: 28rpx;
.input-line {
display: flex;
border: 2rpx solid rgba(0, 0, 0, 0.05);
font-size: 28rpx;
padding: 16rpx;
height: 40rpx;
line-height: 40rpx;
}
input, text{
display: inline-block;
vertical-align: top;
}
input {
flex: 1;
}
text {
width: 90rpx;
color: #FFA004 ;
}
}
5.微信小程序去除button默认边框样式
button::after{
border: none;
}
6.小程序如何获取点击元素信息
使用驼峰模式,给点击元素绑定 data-*,通过 event.currentTarget.dataset 获取
<image src="{{ item.mini_pic }}" class="{{ item.show_opacity ? 'show_opacity' : ''}}" bindtap="tap" data-message="{{ item }}">
</image>
// 获取的点击节点元素是一个对象
tap: function(event) {
var message = event.currentTarget.dataset.message;
}
7. 小程序如何在页面间传递数组对象?
方法1:A页面跳转链接添加参数,B页面onLoad 接受
方法2:设置全局变量 globalData,用的少,一般适用于全局共享的一份信息,如用户open_id等
// A页面
// 数组、对象都需要stringify
var listData = JSON.stringify(that.data.listData)
var taskArray = JSON.stringify(that.data.taskArray)
wx.navigateTo({
url: '../workRecord/updateBatch?listData=' + listData + '&taskArray=' + taskArray
})
//B页面
onLoad: function (options) {
var that = this
var listData = JSON.parse(options.listData)
var taskArray = JSON.parse(options.taskArray)
}
//A页面:
app.globalData.open_id = 3;
//B页面:
var lala = app.globalData.open_id;
8. 小程序如何批量上传图片
chooseImage、的回调函数中,wx.uploadFile
上传,更新进度
6. 其他
-
封装http请求
class HTTP{
request({url,data={},method='POST', header={'content-type':'application/json'} }){ return new Promise((resolve, reject)=>{ this._request(url,resolve,reject,data, method, header) }) } _request(url,resolve, reject, data={}, method='POST', header){ wx.request({ url:url, method:method, data:data, header: header, success:(res)=>{ const code = res.statusCode.toString() if (code.startsWith('2') && res.data.errno == 10000){ resolve(res.data) } else{ if(res && res.data && res.data.errmsg) { this._show_error(res.data.errmsg) } else { this._show_error(tips[1]) } console.log('错111111111') reject(res) } }, fail:(err)=>{ reject(err) console.log('错22222222') this._show_error(tips[1]) } }) } _show_error(tip){ if(!tip){ tip = tips[1] } wx.showToast({ title: tip, icon:'none', duration:2000 }) } }
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。