目录
一、已解决的问题
1、a标签无法下载/预览文件
2、企业微信自建应用调试工具不显示log信息
3、从B页面返回A页面,定时器不会自动清除,重新进入B页面,vuex也不会恢复初始数据
4、 iframe标签无法预览PDF
5、企微消息通知进入应用的某个详情页,无法返回上一页
二、未解决的问题
1、使用router.push进行页面跳转,点击左上角图标会退出应用
2、页面编辑状态校验,返回上一页无法拦截已编辑状态
一、已解决的问题
1、a标签无法下载/预览文件
(1)<a>标签、组件库的link标签。
问题:因文件做加密,所以无法成功请求。如果不考虑文件私密性的话,可以尝试使用(用uniapp+企业微信自建应用使用过,没出现问题)。
(2)从后台获取文件流进行转化。
问题:安卓能正常显示查看,但是ios不支持。
const data = res
const url = window.URL.createObjectURL(new Blob([data]))
const link = document.createElement('a')
link.style.display = 'none'
link.href = url
link.setAttribute('download', file.name)
document.body.appendChild(link)
link.click()
(3)企业微信自建应用开发SDK+api下载。
官网地址:
wx.config --使用说明 - 接口文档 - 企业微信开发者中心
wx.previewFile--文件接口 - 接口文档 - 企业微信开发者中心
实现过程如下:
1)ios大多识别不到jWeixin,需要转换一下。建议public/index.html中,全局修改jWeixin。(也可以哪里使用哪里修改)
<script>
let soianWX;
if (jWeixin.config) {
soianWX = jWeixin;
} else {
soianWX = wx;
}
</script>
2)同样在该文件,建议使用引入的方式,引入JS文件。
(两个版本都引入,免得部分api缺失,还要花精力去找为什么【***api is not a function】或【***api undifined】)
<script src="https://res.wx.qq.com/open/js/jweixin-1.2.0.js"></script>
<script src="https://res.wx.qq.com/wwopen/js/jsapi/jweixin-1.0.0.js "></script>
3)请求企业微信sdk
大部分的api都不支持直接使用的,比如当前使用的.previewFile、拉取用户隐私、打开会话等等等等,都需要请求企业微信sdk。
因sdk注册一次规定时间内都能使用,且有开销限制,所以建议封装请求,然后在页面内单独请求api。
// 引入加密插件
import sha1 from 'js-sha1'
/**
* 拼接签名字符串
* @param ticket 通过access_token获取的jsapi_ticket
* @param noncestr 自己生成的随机字符串
* @param timestamp 生成签名时的时间戳
*/
export function getSignature(ticket, noncestr, timestamp) {
const url = window.location.href
const TICKET = 'jsapi_ticket=' + ticket + '&noncestr=' + noncestr + '×tamp=' + timestamp + '&url=' + url
return sha1(TICKET)
}
// 获取js-sdk
export async function JWeixinConfig(state, url, Obj) {
// 生成签名
let ticket = ''
// 生成时间戳
const timestamp = Date.parse(new Date())
// 生成的随机字符串
const nonceStr = randomString(16)
// 获取企业微信配置项,肯定是后端生成更为安全
await getJWeixinTicket().then(res => {
ticket = res.data
})
// 必须步骤--获取sdk鉴权
soianWX.config({
// 必须这么写,否则wx.invoke调用形式的jsapi会有问题
beta: true,
// 调试, true可以查看线上api信息,方便看报错
debug: false,
// 企业微信应用id,必填
appId,
// 时间戳,必填
timestamp,
// 随机字符串,必填
nonceStr,
// 签名字符串,必填
signature: getSignature(ticket, nonceStr, timestamp),
// 需获取权限的api,必填
jsApiList: [
'previewFile',
'invoke'
]
})
// ready,必须步骤
soianWX.ready((res) => {
// 下载附件 --这里可以通过state传入的字符串做判断,使用哪些api,防止页面内使用api时无法成功获取,在此处再次调用。
soianWX.invoke('previewFile', {
url, // 需要预览文件的地址(必填,可以使用相对路径)
name: Obj.name, // 需要预览文件的文件名,必须有带文件格式的后缀,例如.doc(不填的话取url的最后部分,最后部分是个包含格式后缀的文件名)
size: Obj.size, // 需要预览文件的字节大小(必填,而且大小必须正确,否则会打开失败)
success: (response) => { console.log('下载成功走这里', response) },
fail: (err) => {
if (err.errMsg.indexOf('function not exist') > -1) {
Toast.html('版本过低请升级')
}
})
}
// error,必须步骤
soianWX.error((res) => {
soianWX.cppsysStatus = false
})
}
4)页面内使用。
以上信息全配置好了,页面内绑定click事件就可以直接使用了。如果走fail且非版本问题,再重新获取sdk。
soianWX.previewFile({
url, // 需要预览文件的地址(必填,可以使用相对路径)
name: file.name, // 需要预览文件的文件名,必须有带文件格式的后缀,例如.doc(不填的话取url的最后部分,最后部分是个包含格式后缀的文件名)
size, // 需要预览文件的字节大小(必填,而且大小必须正确,否则会打开失败)
success: (res) => { console.log('下载成功走这里', res) },
fail: (res) => {
if (res.errMsg.indexOf('function not exist') > -1) {
this.$toast('版本过低请升级')
return
}
JWeixinConfig('previewFile', url, { name: file.name, size })
}
})
5)说明:
问题1:如果文件是采用文件流的方式返回,size的获取方式如下:
getFileDownload(file.path).then((res) => {
// 从流的头部获取文件大小字段
const size = new Blob([res]).size
})
(当然后端能给处理就省事多了)。
问题2:为什么页面内请求.previewFile和封装使用的方式不太一样?
好问题,但我也说不明白,或许可以问问企业微信开发团队是怎么想的。
其实页面内那个写法,是官网示例写法,正常按照【config——ready——api——error】的顺序使用是没有问题的。
但是封装使用后,不论鉴权是否过期,页面里ios偶尔不支持jWeixin.previewFile下载;只要鉴权没过期,安卓就可以下载成功。此时在封装的地方,将'previewFile'和 'invoke'同时注册,并通过.invoke回调使用,ios和安卓就都支持。
其他api是否会出现这个问题不太清楚,没试过。
可以参考官方的这个说法。没实践过。
问题3:安卓打开txt文件会乱码,其它文件打开没有问题;ios显示正常。
应是QQ浏览器内核有点什么处理问题,因为安卓将文件下载后,使用其它浏览器、wps去查看和编辑,都是没有问题的。没有解决办法,网上说是文件格式的问题,还没来得及试试,感兴趣可以尝试。
实现思路:(1)先区分ios端还是android,ios使用wx.previewFile方法,android使用【(2)从后台获取文件流进行转化】的方式,在转化前判断文件为txt时强行更改文件格式url = window.URL.createObjectURL(new Blob([data], { type: 'text/plain,charset=UTF-8' })),再进行下载。
附分端处理代码
//是否为ios
let isIOS = /iPhone|iPad|iPod/i.test(navigator.userAgent)
// 区分移动端和pc端,如果是返回true,否则返回false
export function isMobile() {
let flag = navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i);
return flag;
},
问题4:wx.config需要的信息也可以通过请求接口返回。
2、企业微信自建应用调试工具不显示log信息
因企业微信自建应用请求企业微信SDK本地无法调试,需要修改很多配置信息,所以需要借助线上调试工具查看控制台信息,辅助开发。
先检查config文件或main.js文件有没有对打包后的文件去log处理,如果没有,可以使用以下工具进行控制台打印查看。
1)移动端使用(有时可能会不出log信息和报错,只有网络请求信息)
<script src="https://cdn.bootcss.com/vConsole/3.3.4/vconsole.min.js"></script>
<!-- ios测试环境调试 -->
<script>
new VConsole();
// 初始化
var vConsole = new VConsole();
</script>
2)如果1)不好用,可以使用这个(亲测好用)
<script src="//cdn.bootcss.com/eruda/1.5.2/eruda.min.js"></script>
<script>
eruda.init();
</script>
3)有些应用仅支持pc使用,不需要用app使用,那就可以直接使用官网提供的方法。
常见问题 - FAQ - 接口文档 - 企业微信开发者中心
3、从B页面返回A页面,定时器不会自动清除,重新进入B页面,vuex也不会恢复初始数据
原理我也不太清楚,不知道为什么pc不需要特意销毁和重置,但企业微信应用开发就不行。需要在destroyed(){}中销毁定时器,并恢复初始数据。
4、 iframe标签无法预览PDF
企业微信应用貌似是不支持的,用第三方包吧。
// npm下载
npm i pdfh5
// 页面引入
import Pdfh5 from 'pdfh5'
import 'pdfh5/css/pdfh5.css'
<div id="pdfType" />
// 接口请求对流转换拿到url
if (res.size !== 0) {
const blob = new Blob([res], { type: 'application/pdf' })
const url = URL.createObjectURL(blob)
this.baseUrl = url
}
// pdf预览
initPdf() {
this.pdfh5 = new Pdfh5('#pdfType', {
pdfurl: this.baseUrl, // pdf文件地址(我用的文件流转换的url,可以使用)
lazy: false, // 是否懒加载,默认false,文件流形式只显示2页,后边加载不出,建议关闭
renderType: 'canvas', // canvas、svg,默认canvas
maxZoom: 3, // 手势缩放最大倍数,默认3
scrollEnable: true, // 是否允许pdf滚动,默认true
zoomEnable: true, // 是否允许pdf手势缩放,默认true
limit: 0 // 限制pdf加载最大页数,默认0不限制
})
// 监听完成事件 this.totalNum在lazy为true时显示不正确,false时显示正确
// this.pdfh5.on('complete', function(status, msg, time) {
// console.log('状态:' + status + ',信息:' + msg + ',耗时:' + time + '毫秒, 总页数:' + this.totalNum)
// })
}
5、企微消息通知进入应用的某个详情页,无法返回上一页
具体表现为:手势返回、左上角系统图标返回、左上角ios系统图标关闭应用,均无法返回上一页/关闭
原因:检查代码后发现,通过企微消息通知进入应用后,进入的是空白页,空白页对不同的通知消息再跳转不同的处理页/详情页时,使用的是this.$router.push(),当我们返回上一页,其实返回的是空白页(而不是退出系统),空白页再次进行处理重新跳转回处理页/详情页,造成“退不出去”的错觉……
修改:this.$router.replace() 跳转,将当前空白页关闭。
二、未解决的问题
1、使用router.push进行页面跳转,点击左上角图标会退出应用
ios:手势返回、左上角返回上一页正常。
安卓:手势返回无问题,左上角返回会退出应用。
原理还不清楚。
2、页面编辑状态校验,返回上一页无法拦截已编辑状态
安卓:因点击返回直接退出应用,无法校验能否拦截。手势返回没有试过,参考微信小程序框架开发经验来看,企业微信自建应用应该是有自己的api可以做拦截的。
ios:官网文档明确说明,怎样都不行。只能有提示信息,拦是拦不住的。