问题:微信多图上传 ios手机上偶尔出现报错chooseImage:the permission value is offline verifying(上传流程wx.chooseImage、给后台serverId用wx.uploadImage、本地展示用wx.getLocalImgData)
问题分析: 开启debug测试得出,先报错chooseImage:the permission value is offline verifying,在弹出config:ok
得出结论:导致错误的原因是"先执行了wx.chooseImage方法再执行wx.config(有请求异步导致)"。正常的情况是先弹出config,再调用wx.chooseImage方法
解决方法:
1、 setTimeout(() => { }, 400) // 延迟一下
2、放在wx.ready里面 确保wx.config执行完成触发
实现代码
Publish.vue
html
<!--图片展示-->
<div class="form-img-container" v-if="arr.length > 0">
<!-- 微信上传图片 -->
<wechat-uploader-img v-if="data" @addImg="addImg" @success="success(index)" @error="error(index)" :is-publish="true" @showImgDetail="showImgDetail(index, data)"
v-for="(data,index) in arr" :key="index" :index="index" :info="data" :mold="'bulletin'"/>
</div>
<!--上传按钮-->
<template>
<div class="uploaderImg" @click="handleChooseImage()">
<div class="add-img-icon"></div>
<div class="add-img-text">图片{{ arr.length }}/3张</div>
</div>
</template>
js
// 微信上传
import WechatUploaderImg from '@/components/WechatUploaderImg'
export default {
data () {
return {
form: {
images: [] // 上传到服务器的相册
},
isLoading: false,
// 暂存读取后数据
arr: [],
// 是否显示提示框
showDialog: false,
// 是否是ios手机
isIos: this.$utils.isIOS()
}
},
components: {
WechatUploaderImg
},
methods: {
// 图片上传(微信的js-dk)
handleChooseImage () {
if (this.isLoading) {
return
}
this.isLoading = true
let arr = []
for (let i = 0; i < this.arr.length; i++) {
if (this.arr[i]) {
arr.push(this.arr[i])
}
}
// 实际可用长度
let arrLen = arr.length
if (arrLen >= 3) {
this.isLoading = false
this.$utils.showMessage('亲,最多只能上传3张图片哦~')
} else {
if (this.isIos) {
setTimeout(() => { // 解决问题的重要代码(定时器延时)
this.fetChooseImage(arrLen)
}, 400)
} else {
this.fetChooseImage(arrLen)
}
}
},
fetChooseImage (arrLen) {
// eslint-disable-next-line
wx.ready(() => { // 解决问题的重要代码(方wx.ready里面)
this.$store.dispatch('Wechat/chooseImage', 3).then(res => {
this.isLoading = false
let localIds = res.localIds
if (localIds.length > 0 && 3 - arrLen >= localIds.length) {
this.localIdArr = localIds
} else if (localIds.length > 0 && 3 - arrLen < localIds.length) {
this.localIdArr = localIds.slice(0, 3 - arrLen)
}
this.handleUploadImage()
}).catch(err => {
this.isLoading = false
if (err.errMsg !== 'chooseImage:cancel') {
this.$utils.showErrorMsg('chooseImage:' + JSON.stringify(err))
}
})
})
},
handleUploadImage () {
if (!this.localIdArr.length) {
return
}
let localId = this.localIdArr.shift()
this.$store.dispatch('Wechat/uploadImage', localId).then(res => {
let serverId = res.serverId // 返回图片的服务器端ID
this.handleGetLocalImgData(localId, serverId)
this.handleUploadImage()
}).catch(err => {
this.$utils.showErrorMsg(err)
})
},
handleGetLocalImgData (localId, serverId) {
this.$store.dispatch('Wechat/getLocalImgData', localId).then(res => {
let localData = res.localData
let obj = {
// 读取成功的数据
readData: localData,
serverId: serverId,
// 上传成功的状态 true代表成功,false代表还在上传,null代表错误
isSuccess: false,
// 是否显示蒙层
isShow: true
}
this.arr.push(obj)
}).catch(err => {
this.$utils.showErrorMsg(err)
})
},
// 数据库添加图片
addImg (src, index) {
if (index !== undefined && this.form.images.length > index) {
this.form.images.splice(index, 1, {url: src})
}
if (index !== undefined && this.form.images.length <= index) {
this.form.images[index] = {url: src}
}
},
// 删除图片
deleteImg () {
this.arr.splice(this.imgDetailIndex, 1)
this.form.images.splice(this.imgDetailIndex, 1)
this.isShowImgDetail = false
},
// 上传成功的状态
success (index) {
this.arr[index].isShow = false
this.arr[index].isSuccess = true
},
// 上传失败的提示
error (index) {
this.arr[index].isSuccess = null
}
},
watch: {
arr (newVal) {
let length = newVal.length
if (length === 0) {
this.$refs.formInside.style.minHeight = '7.1rem'
this.$refs.formMid.style.minHeight = '5.4rem'
} else if (length > 0) {
let trueLength = 0
newVal.forEach(item => {
if (item) {
trueLength++
}
})
if (trueLength > 0) {
this.$refs.formInside.style.minHeight = 'unset'
this.$refs.formMid.style.minHeight = '2.172rem'
} else {
this.$refs.formInside.style.minHeight = '7.1rem'
this.$refs.formMid.style.minHeight = '5.4rem'
}
}
}
}
}
components/WechatUploaderImg
html
<template v-if="mold == 'bulletin'">
<div @click.prevent.stop="showImgDetail" v-if="info.readData" class="form-img">
<!-- 公告预览 有http开头的图片 先判断http的图片再判断机型 -->
<img v-if="info.readData.indexOf('http') === 0" :src="info.readData" alt="">
<img v-else-if="isIos" :src="info.readData" alt="">
<img v-else :src="'data:image/gif;base64,' + info.readData" alt="">
<transition name="fade">
<div v-if="info.isShow" :id="index" class="img_circle"></div>
</transition>
</div>
</template>
js
export default {
created () {
// 当url是http时不用上传
if (this.info.readData && this.info.readData.indexOf('http') !== 0) {
this.fetchImages()
}
},
props: {
info: {
type: Object
},
index: {
type: Number
},
mold: {
type: String
}
},
data () {
return {
loading: {
rate: 0
},
// 是否是ios手机
isIos: this.$utils.isIOS()
}
},
methods: {
// 图片上传到七牛
fetchImages () {
this.$http.post(`v1/common/upload/img`, {
img_content: this.info.serverId,
type: 1
}).then(res => {
let src = res.data.meta.img_url
this.$emit('addImg', src, this.index)
this.success()
}).catch(err => {
this.$utils.showErrorMsg(err)
this.error()
})
},
// 上传失败
error () {
this.$emit('error', this.index)
this.$utils.showErrorMsg('图片上传有误,请重新上传')
},
// 上传成功
success () {
this.$emit('success', this.index)
},
// 删除
splice () {
this.$emit('splice', this.index)
},
// 点击预览
showImgDetail () {
this.$emit('showImgDetail', this.index)
}
},
watch: {
info (val) {
// 微信上传
if (this.mold === 'avatar' && this.info.readData && this.info.readData.indexOf('http') !== 0) {
this.fetchImages()
}
}
}
}
Wechat.js
import Http from '@/libs/Http'
import Utils from '@/libs/Utils'
const state = {
url: ''
}
const mutations = {
/**
* 设置校验url
* @param {Object} state 状态
*/
setUrl (state) {
let currentUrl = document.URL
if (Utils.isIOS()) {
let landingUrl = sessionStorage.getItem('ios_landing_url')
if (landingUrl) {
state.url = landingUrl
} else {
state.url = currentUrl
}
} else {
state.url = currentUrl
}
}
}
const actions = {
/**
* 初始化微信配置
* @param {*} param0
* @param {*} payload payload.perms微信权限
*/
initConfig ({commit, state}, payload) {
return new Promise((resolve, reject) => {
let data = {
url: state.url,
perms: payload.perms
}
Http.post('/v1/wechat/js', data).then(response => {
let wechatJs = response.data.meta.wechat_js
// wechatJs.debug = true
/* eslint-disable no-undef */
wx.config(wechatJs)
resolve()
wx.error(err => {
console.log('wx.err', err)
})
}).catch(err => {
Utils.showError(err)
reject(err)
})
})
},
/**
* 分享操作
* @param {Object} param0
* @param {Object} payload {title:'',link:null,desc:null,type:null,img:''}
*/
share ({dispatch, state}, payload) {
return new Promise((resolve, reject) => {
dispatch('initConfig', {perms: ['onMenuShareTimeline', 'onMenuShareAppMessage']}).then(() => {
// dispatch('initConfig', {perms: ['updateAppMessageShareData', 'updateTimelineShareData']}).then(() => {
let parsedLink = payload.link === undefined || !payload.link ? window.location.href : payload.link
/* eslint-disable no-undef */
wx.ready(() => { // 因为是页面加载时就需要调用相关接口所以要加wx.ready方法
let share = {
title: payload.title,
link: parsedLink,
desc: payload.desc,
type: payload.type === null ? 'link' : payload.type,
imgUrl: payload.img === undefined || !payload.img ? null : payload.img,
success: resolve,
cancel: reject
}
wx.onMenuShareTimeline(share)
wx.onMenuShareAppMessage(share)
// wx.updateAppMessageShareData(share)
// wx.updateTimelineShareData(share)
})
})
})
},
/**
* 关闭分享操作
*/
unShare ({dispatch, state}, payload) {
return new Promise((resolve, reject) => {
if (payload === 'both') {
dispatch('initConfig', {perms: ['chooseImage', 'getLocalImgData', 'uploadImage', 'hideAllNonBaseMenuItem']}).then(() => {
/* eslint-disable no-undef */
wx.ready(() => { // 因为是页面加载时就需要调用相关接口所以要加wx.ready方法
wx.hideAllNonBaseMenuItem()
})
})
} else {
dispatch('initConfig', {perms: ['hideAllNonBaseMenuItem']}).then(() => {
/* eslint-disable no-undef */
wx.ready(() => { // 因为是页面加载时就需要调用相关接口所以要加wx.ready方法
wx.hideAllNonBaseMenuItem()
})
})
}
})
},
/**
* 从相册中选图片或者拍照
*/
chooseImage ({dispatch, state}, payload) {
return new Promise((resolve, reject) => {
// 因为是用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中
wx.chooseImage({
count: payload, // 默认9张照片
sizeType: ['original', 'compressed'], // 可以指定是原图还是压缩图,默认二者都有
sourceType: ['album', 'camera'], // 可以指定来源是相册还是相机,默认二者都有
success: resolve,
fail: reject,
complete: reject
})
})
},
/**
* 获取本地图片
*/
getLocalImgData ({dispatch, state}, payload) {
return new Promise((resolve, reject) => {
// 因为是用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中
wx.getLocalImgData({
localId: payload, // 图片的localID
success: resolve,
fail: reject
})
})
},
/**
* 上传图片接口
*/
uploadImage ({ dispatch, state }, payload) {
return new Promise((resolve, reject) => {
wx.uploadImage({
localId: payload, // 需要上传的图片的本地ID,由chooseImage接口获得
isShowProgressTips: 0, // 默认为1,显示进度提示
success: resolve,
fail: reject
})
})
}
}
export default {
namespaced: true,
state,
mutations,
actions
}