最近公司想要做一个单对单咨询,有跨端的需求(小程序、h5),就用了uni app +腾讯IM
使用cli生成uni项目
利用环境变量区分h5跟小程序环境,分别加载了两套SDK
先说一下tim发送消息的流程
登录 => 初始化SDK => 拉取会话列表 => 根据会话列表ID拉取会话详情 => 选择图片 => 创建图片对象createImageMessage(在这步会把本地的图片传到腾讯的服务器) => 将创建的图片对象发送出去 复制代码
发送文字消息很顺利,一到发送图片,就步步坑
贴一下引入的代码 main.js
import Vue from 'vue' import App from './App' // 根据不同的开发环境引入不同的SDK // #ifdef H5 import TIM from 'tim-js-sdk'; import COS from "cos-js-sdk-v5"; // #endif // #ifdef MP-WEIXIN import TIM from 'tim-wx-sdk'; import COS from "cos-wx-sdk-v5"; // #endif // 初始化TIM let options = { SDKAppID: SDKAPPID } let tim = TIM.create(options) wx.$app = tim // #ifdef H5 wx.$app.registerPlugin({ 'cos-js-sdk': COS }) // #endif // #ifdef MP-WEIXIN wx.$app.registerPlugin({ 'cos-wx-sdk': COS }) // #endif App.mpType = 'app' const app = new Vue({ store, ...App }) app.$mount() 复制代码
根据uni-app的文档,chooseImage选择图片后,在h5端会返回tempFiles
值是file对象,但我打印了返回值之后并不是 file,而是一个包含了路径跟类型的object,在TIM的SDK中,检验了参数类型
同时Uni-app 没有input[type="file"] 所以也无法传入HTML节点
把图片上所有2.0.0-26920200409002
依赖全部替换成2.0.0-26920200424005
,重新运行npm i
再次运行项目,打印的时候就会发现tempFiles的值变成了file对象
正当我以为问题解决了,掉了的头发有回报的时候,第二个问题出现了
一开始怀疑是不是sdk引入错误了,只加载js-sdk,也会报这个错误,后来发现在这两个SDK中都有这句话判断
// tim-js-sdk { key: "createImageMessage", value: function(e) { e.currentUser = this.tim.context.identifier; var t = new Vh(e); if (ba) { var n = e.payload.file; // ls方法判断了传入的对象是否是file 是file就会报异常 if (ls(n)) return void cs.warn("微信小程序环境下调用 createImageMessage 接口时,payload.file 不支持传入 File 对象"); var r = n.tempFilePaths[0], o = { url: r, name: r.slice(r.lastIndexOf("/") + 1), size: n.tempFiles[0].size, type: r.slice(r.lastIndexOf(".") + 1).toLowerCase() }; e.payload.file = o } else if (Ra && ls(e.payload.file)) { var i = e.payload.file; e.payload.file = { files: [i] } } var a = new Ml({ imageFormat: "UNKNOWN", uuid: this._generateUUID(), file: e.payload.file }); return t.setElement(a), this.messageOptionMap.set(t.messageID, e), t } } 复制代码
这就很令人窒息。。第一个报错提示让我一定要传入file文件,第二个提示让我不能传入file文件。。那应该传什么
没办法了 从源码上动刀吧
为了尽量靠近小程序的传递方式,我修改了源码中对图片的检测,把传入file的检测去掉了,改成了传入完整的chooseimage的回调,与小程序的传参保持一致
第一步要做的就是修改入参的检测,就是要修改遇到的第一个问题
// tim-js // 格式化后5508行 payload: { type: "Object", required: !0, validator: function (e) { if (ms(e.file)) return console.warn("createImageMessage payload.file 不能为 undefined。请参考 https://imsdk-1252463788.file.myqcloud.com/IM_DOC/Web/SDK.html#createImageMessage"), !1; if (Ra) { // 去掉file类型的检测 // if (!(e.file instanceof HTMLInputElement || ls(e.file))) return console.warn("createImageMessage payload.file 的类型必须是 HTMLInputElement 或 File。请参考 https://imsdk-1252463788.file.myqcloud.com/IM_DOC/Web/SDK.html#createImageMessage"), // !1; if (e.file instanceof HTMLInputElement && 0 === e.file.files.length) return console.warn("createImageMessage 您没有选择文件,无法发送。请参考 https://imsdk-1252463788.file.myqcloud.com/IM_DOC/Web/SDK.html#createImageMessage"), !1 } return !0 } } 复制代码
去掉类型检测后,再修改一下创建图片对象的部分
// tim-js // 格式化后12200行 { key: "createImageMessage", value: function (e) { e.currentUser = this.tim.context.identifier; var t = new Vh(e); if (ba) { var n = e.payload.file; if (ls(n)) return void cs.warn("微信小程序环境下调用 createImageMessage 接口时,payload.file 不支持传入 File 对象"); var r = n.tempFilePaths[0], o = { url: r, name: r.slice(r.lastIndexOf("/") + 1), size: n.tempFiles[0].size, // 修改此处 chooseimage的file对象路径没有后缀名,所以用了他的type类型,截取获得后缀 type: n.tempFiles[0].type.split('/')[1] // type: r.slice(r.lastIndexOf(".") + 1).toLowerCase() }; e.payload.file = o } else if (Ra && ls(e.payload.file)) { var i = e.payload.file; e.payload.file = { files: [i] } } var a = new Ml({ imageFormat: "UNKNOWN", uuid: this._generateUUID(), file: e.payload.file }); return t.setElement(a), this.messageOptionMap.set(t.messageID, e), t } }, 复制代码
上面有几个地方固定了下标为0,因为uni-app的图片选择暂时只支持单张,所以写死下标可行,目前使用来说没发现什么问题
处理完成之后 外部调用的时候就可以传入整个chooseimage 的回调值,也不用分别处理小程序跟h5
你以为这两个问题处理完了就解决了吗,并没有!我又遇到了第三个问题,腾讯IM上传图片视频等需要依赖cos插件,我在main.js中引入并且注册了cos-js-sdk-v5,但是上传的时候提示异常未检测到COS上传插件
玩的这么刺激,头发都要掉完了。。。
这个问题最后还是解决了,我没有去看源码,直接使用了cos-wx-sdk 就能正常上传图片,到现在都不知道为啥
这个一波三折的问题处理完了,接下来还不知道有多少问题等着,整体这几个问题解决用了一天,但是挠了一天半的头,头发也掉了无数根。百度搜了无数次,也问了很多人,感谢uni群里大佬的帮助
文档还是要及时写,隔了一天很多细节都有点忘记了。
写的有点拖沓,请大家见谅