From bab852804ba2aa1dc23385e62f6873ccdbd73ccf Mon Sep 17 00:00:00 2001 From: Tevin <tingquanren@163.com> Date: Sun, 17 Jul 2022 10:23:55 +0800 Subject: [PATCH] 优化文件存储服务,提供列队批量操作 --- common/Bridge.js | 219 +++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 files changed, 206 insertions(+), 13 deletions(-) diff --git a/common/Bridge.js b/common/Bridge.js index 1c1c5e8..cf2b376 100644 --- a/common/Bridge.js +++ b/common/Bridge.js @@ -22,6 +22,10 @@ * window.linking('{method:\'methodName\', param:{key2:\'value2\'}, marker:\'mk222at1541994536008\'}'); */ +import { Fetcher } from '@components/bases/Fetcher'; +import { Tools } from '@components/common/Tools'; +import { $fileTrans } from '@components/common/FileTransform'; + export class Bridge { constructor() { @@ -84,16 +88,27 @@ */ _sendLinking(method, param, callback) { // 数据检查 - if (Object.prototype.toString.call(param) !== '[object Object]') { + if (!Tools.isObject(param)) { console.error('$bridge.invoking 需要接受 JSON 对象!'); return; } + // 转换发送参数键名为下划线 + param = this.transKeyName('underline', param); // 如果有回调,转存回调 const name = 'cb' + this._data.count++ + 'at' + Date.now(); this[name] = (res) => { - if (callback && Object.prototype.toString.call(callback) === '[object Function]') { + if (callback && Tools.isFunction(callback)) { if (res) { - const data = typeof res === 'string' ? JSON.parse(res) : res; + let data; + try { + // 转对象 + data = typeof res === 'string' ? JSON.parse(res) : res; + // 转换接收参数键名为驼峰 + data = this.transKeyName('camel', data); + } catch (e) { + Tools.toast('跨端通讯异常:解析数据失败!'); + return; + } callback(data); } else { callback(); @@ -115,11 +130,10 @@ * @param {object|function} [param] * @param {function} [callback] */ - invoking(method, param, callback) { + invoking(method, param = {}, callback) { // param 为函数时 - const trans = param; - if (trans && Object.prototype.toString.call(trans) === '[object Function]') { - callback = trans; + if (param && Tools.isFunction(param)) { + callback = param; param = {}; } if (this._checkLinking()) { @@ -139,20 +153,25 @@ window.telling = (res) => { const data = typeof res === 'string' ? JSON.parse(res) : res; const { method, param, marker } = data; + // 转换接收参数键名为驼峰 + const param2 = this.transKeyName('camel', param); if (this._receives[method]) { + // 有通知回调 if (marker) { - this._receives[method](param, (param2) => { + this._receives[method](param2, (param2) => { this._sendTelling(method, param2 || {}, marker); }); - } else { - this._receives[method](param); + } + // 无通知回调 + else { + this._receives[method](param2); } } }; } /** - * 发送响应 + * 回发App通知的响应 * @param {string} method * @param {object} param * @param {string} marker @@ -160,10 +179,12 @@ */ _sendTelling(method, param, marker) { // 数据检查 - if (Object.prototype.toString.call(param) !== '[object Object]') { + if (!Tools.isObject(param)) { console.error('$bridge.register 注册的函数需要接受 JSON 对象!'); return; } + // 转换发送参数键名为下划线 + param = this.transKeyName('underline', param); // 发送 window.aisim.linking(JSON.stringify({ method, @@ -173,7 +194,7 @@ } /** - * 注册接收指令,可供 app 查询 + * 注册接收指令,可接收 app 通知 * @param method * @param callback */ @@ -189,6 +210,178 @@ return platform === 'android' || platform === 'iOS'; } + /** + * 键名转换 + * @param type + * @param json + */ + transKeyName(type, json) { + return Fetcher.prototype.transKeyName(type, json); + } + + /* ----- 文件系统 ----- */ + + /** + * 保存文件到 java 端,并返回文件名 + * @param objUrl + * @param callback + */ + fileSave(objUrl = '', callback) { + // 非 ObjectURL 跳过 + if (objUrl.indexOf('blob:') < 0) { + callback(objUrl); + return; + } + // 分段存储 + const saveFileChunk = (baseData, index) => { + const writeData = { + fileName: baseData.fileName, + currentIdx: index, + totalIdx: baseData.total, + data: baseData.baseArr[index], + }; + this.invoking('img_write', writeData, res => { + if (res.result === false) { + Tools.toast(res.msg); + return; + } + // 按分段递归保存 + if (index < baseData.total - 1) { + setTimeout(() => { + saveFileChunk(baseData, index + 1); + }, 10); + } + // 已完成 + else { + callback && callback('bridge:' + baseData.fileName); + } + }); + }; + $fileTrans.transObjUrlToBaseData(objUrl, baseData => { + saveFileChunk(baseData, 0); + }); + } + + /** + * 从 java 读取文件 base64 + * @param fileName + * @param callback + */ + fileLoad(fileName = '', callback) { + // 非存储地址,跳过 + if (fileName.indexOf('bridge:') < 0) { + callback(fileName); + return; + } + fileName = fileName.split(':')[1]; + const chunkSize = $fileTrans.getChunkSize(); + const baseArr = []; + let totalSize = 0; + let totalCount = 0; + const loadFileChunk = (index) => { + const loadData = { + fileName, + offset: chunkSize * index, + length: chunkSize, + }; + this.invoking('img_read', loadData, res => { + if (res.result === false) { + Tools.toast(res.msg); + return; + } + if (totalSize === 0) { + totalSize = res.totalSize; + totalCount = Math.ceil(res.totalSize / chunkSize); + } + baseArr.push(res.data); + // 按分段递归读取 + if (totalCount > 1 && totalCount - 1 > index) { + loadFileChunk(index + 1); + } + // 读取完成 + else { + const baseData = { + baseArr, + fileName, + }; + $fileTrans.transBaseDataToObjUrl(baseData, objUrl => { + callback && callback(objUrl); + }); + } + }); + }; + loadFileChunk(0); + } + + /** + * 从 java 端移除文件 + * @param fileName + */ + fileRemove(fileName = '') { + if (fileName.indexOf('bridge:') < 0) { + return; + } + fileName = fileName.split(':')[1]; + this.invoking('img_del', { fileName }); + } + + /** + * 文件存储批量操作服务 + * @param type + * @param names + * @param callback + */ + fileStorehouse(type, names = [], callback) { + // 保存 + if (type === 'save') { + const list = []; + const save = index => { + this.fileSave(names[index], fileName => { + list.push(fileName); + // 递归下一个 + if (index < names.length - 1) { + setTimeout(() => { + save(index + 1); + }, 10); + } + // 完成 + else { + callback && callback(list); + } + }); + }; + save(0); + } + // 读取 + else if (type === 'load') { + const list = []; + const load = index => { + this.fileLoad(names[index], objUrl => { + list.push(objUrl); + // 递归下一个 + if (index < names.length - 1) { + setTimeout(() => { + load(index + 1); + }, 10); + } + // 完成 + else { + callback && callback(list); + } + }); + }; + load(0); + } + // 移除 + else if (type === 'remove') { + names.forEach((name, index) => { + setTimeout(() => { + this.fileRemove(name); + }, 10 * index); + }); + } + } + } // 全局服务实例 -- Gitblit v1.9.1