// 上传前压缩:小程序默认上传超时 60 秒,手机原图/聊天记录图片较大时容易超时中断。 // 超过 800KB 的图片先用 compressImage 压到约 75% 质量,失败则回退原图。 var COMPRESS_THRESHOLD = 800 * 1024 export function compressPickedImages(paths, files, callback) { var result = [] var index = 0 function finish() { callback(result) } function next() { if (index >= paths.length) { finish() return } var i = index++ var path = paths[i] var file = files && files[i] var size = file && typeof file.size === 'number' ? file.size : 0 if (!path || (size > 0 && size <= COMPRESS_THRESHOLD) || typeof uni === 'undefined' || typeof uni.compressImage !== 'function') { result[i] = path next() return } uni.compressImage({ src: path, quality: 75, success: function (res) { result[i] = (res && res.tempFilePath) || path next() }, fail: function () { result[i] = path next() } }) } if (!paths || !paths.length) { callback([]) return } next() } /** * 统一图片选择器(微信小程序支持「从聊天记录选择图片」) * * 背景: * uni.chooseImage 只能从 album(手机相册)或 camera(拍照)选图, * 无法直接选择聊天记录里的图片;微信小程序要从聊天记录选图, * 必须调用 uni.chooseMessageFile({ type: 'image' })。 * 为保证小程序端所有图片上传入口都能从聊天记录选图,统一使用本方法。 * * 用法与 uni.chooseImage 基本一致(回调风格): * pickImage({ * count: 1, * sizeType: ['compressed'], * sourceType: ['album', 'camera'], // 可选,默认 ['album', 'camera'] * success: function (res) { * // res.tempFilePaths: 图片本地临时路径数组 * // res.tempFiles: [{ path, size, name, type }] * }, * fail: function (err) {} * }) * * 说明: * 微信小程序下会先弹出 ActionSheet:拍照 / 从相册选择 / 从聊天记录选择, * 前两项走 uni.chooseImage,最后一项走 uni.chooseMessageFile。 * 非微信平台(H5/App 等)不支持聊天记录选图,保持原 uni.chooseImage 行为。 */ export function pickImage(options) { var opts = options || {} var count = opts.count || 9 var sizeType = opts.sizeType || ['original', 'compressed'] var sourceType = opts.sourceType || ['album', 'camera'] var success = opts.success var fail = opts.fail var complete = opts.complete function finish(res) { if (success) success(res) if (complete) complete(res) } function onSuccess(res) { var paths = (res && res.tempFilePaths) || [] if (!paths.length) { finish(res) return } compressPickedImages(paths, (res && res.tempFiles) || [], function (compressedPaths) { var out = {} for (var key in res) { if (Object.prototype.hasOwnProperty.call(res, key)) out[key] = res[key] } out.tempFilePaths = compressedPaths if (res && res.tempFiles) { var files = [] for (var i = 0; i < res.tempFiles.length; i++) { var file = res.tempFiles[i] || {} var copy = {} for (var k in file) { if (Object.prototype.hasOwnProperty.call(file, k)) copy[k] = file[k] } copy.path = compressedPaths[i] || copy.path files.push(copy) } out.tempFiles = files } finish(out) }) } function onFail(err) { if (fail) fail(err) if (complete) complete(err) } // sourceType 只支持单个来源时(如 ['camera'])直接调起对应入口 function callChooseImage(types) { uni.chooseImage({ count: count, sizeType: sizeType, sourceType: types, success: onSuccess, fail: onFail }) } // #ifdef MP-WEIXIN // 微信小程序:先选来源,再从聊天记录 / 相册 / 相机取图 var actionList = [] if (sourceType.indexOf('camera') > -1) actionList.push({ label: '拍照', type: 'camera' }) if (sourceType.indexOf('album') > -1) actionList.push({ label: '从相册选择', type: 'album' }) actionList.push({ label: '从聊天记录选择', type: 'chat' }) var itemList = [] for (var i = 0; i < actionList.length; i++) itemList.push(actionList[i].label) uni.showActionSheet({ itemList: itemList, success: function (sheetRes) { var action = actionList[sheetRes.tapIndex] if (!action) return if (action.type !== 'chat') { callChooseImage([action.type]) return } if (typeof uni.chooseMessageFile !== 'function') { // 低版本基础库不支持聊天记录选图,降级为相册选图 callChooseImage(['album']) return } uni.chooseMessageFile({ count: count, type: 'image', success: function (res) { var files = [] var tempFiles = res.tempFiles || [] for (var j = 0; j < tempFiles.length; j++) { files.push({ path: tempFiles[j].path, size: tempFiles[j].size, name: tempFiles[j].name, type: tempFiles[j].type }) } var paths = [] for (var k = 0; k < files.length; k++) paths.push(files[k].path) onSuccess({ tempFilePaths: paths, tempFiles: files }) }, fail: onFail }) }, fail: onFail }) // #endif // #ifndef MP-WEIXIN // 非微信平台不支持聊天记录选图,保持原行为 callChooseImage(sourceType) // #endif }