From cd34395ba16703ac8f053cedfbe98e83a078479b Mon Sep 17 00:00:00 2001 From: Tevin <tingquanren@163.com> Date: Thu, 17 Nov 2022 11:56:56 +0800 Subject: [PATCH] 优化二维码组件显示 --- common/Bridge.js | 253 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 250 insertions(+), 3 deletions(-) diff --git a/common/Bridge.js b/common/Bridge.js index efc8eb3..f46cf14 100644 --- a/common/Bridge.js +++ b/common/Bridge.js @@ -24,12 +24,15 @@ import { Fetcher } from '@components/bases/Fetcher'; import { Tools } from '@components/common/Tools'; +import { $fileTrans } from '@components/common/FileTransform'; export class Bridge { constructor() { this._data = { count: 100, + fileSaved: {}, // 已保存图片名称列表 { 'blob:***' : 'bridge:***' } + fileLoaded: {}, // 已读取图片名称列表 { 'bridge:***' : 'blob:***' } }; this._receives = {}; this._earlyInvok = []; @@ -98,9 +101,16 @@ this[name] = (res) => { if (callback && Tools.isFunction(callback)) { if (res) { - let data = typeof res === 'string' ? JSON.parse(res) : res; - // 转换接收参数键名为驼峰 - data = this.transKeyName('camel', data); + 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(); @@ -211,6 +221,243 @@ return Fetcher.prototype.transKeyName(type, json); } + /* ----- 文件系统 ----- */ + + /** + * 保存文件到 java 端,并返回文件名 + * @param objUrl + * @param callback + * @param onError + */ + fileSave(objUrl = '', callback, onError) { + // 非 ObjectURL 跳过 + if (objUrl.indexOf('blob:') < 0) { + callback(objUrl); + return; + } + if (this._data.fileSaved[objUrl]) { + callback(this._data.fileSaved[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); + onError({ + method: 'img_write', + request: { + fileName: writeData.fileName, + currentIdx: writeData.currentIdx, + totalIdx: writeData.total, + data: (writeData.data || '').substr(0, 10) + + '...(共' + (writeData.data || '').length + '个base64字符)', + }, + response: res, + }); + return; + } + // 按分段递归保存 + if (index < baseData.total - 1) { + setTimeout(() => { + saveFileChunk(baseData, index + 1); + }, 10); + } + // 已完成 + else { + callback && callback('bridge:' + baseData.fileName); + } + }); + }; + $fileTrans.transObjUrlToBaseData(objUrl, baseData => { + this._data.fileSaved[objUrl] = 'bridge:' + baseData.fileName; + saveFileChunk(baseData, 0); + }); + } + + /** + * 从 java 读取文件 base64 + * @param bridgeName + * @param callback + * @param onError + */ + fileLoad(bridgeName = '', callback, onError) { + // 非存储地址,跳过 + if (bridgeName.indexOf('bridge:') < 0) { + callback(bridgeName); + return; + } + if (this._data.fileLoaded[bridgeName]) { + callback(this._data.fileLoaded[bridgeName]); + return; + } + const fileName = bridgeName.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); + onError({ + method: 'img_read', + request: { + ...loadData, + totalCount, + }, + response: { + result: res.result, + msg: res.msg, + 'total_size': res.totalSize, + data: (res.data || '').substr(0, 10) + + '...(共' + (res.data || '').length + '个base64字符)', + }, + }); + 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, + }; + try { + $fileTrans.transBaseDataToObjUrl(baseData, objUrl => { + this._data.fileLoaded[bridgeName] = objUrl; + callback && callback(objUrl); + }); + } catch (e) { + onError({ + method: 'img_read@merge_after_base64_loaded', + request: { + ...loadData, + totalCount, + }, + response: { + result: res.result, + msg: res.msg, + 'total_size': res.totalSize, + data: (res.data || '').substr(0, 10) + + '...(共' + (res.data || '').length + '个base64字符)', + }, + base64Arr: baseData.baseArr.map(baseItem => (baseItem || []).substr(0, 10) + + '...(共' + (res.data || '').length + '个base64字符)'), + message: 'Base64合并解析异常!', + }); + } + } + }); + }; + loadFileChunk(0); + } + + /** + * 从 java 端移除文件 + * @param bridgeName + */ + fileRemove(bridgeName = '') { + if (bridgeName.indexOf('bridge:') < 0) { + return; + } + const fileName = bridgeName.split(':')[1]; + this.invoking('img_del', { fileName }); + // 移除 + Object.keys(this._data.fileSaved).forEach(objUrl => { + if (bridgeName === this._data.fileSaved[objUrl]) { + delete this._data.fileSaved[objUrl]; + } + }); + } + + /** + * 文件存储批量操作服务 + * @param type + * @param names + * @param callback + */ + fileStore(type, names = [], callback) { + if (!names || names.length === 0) { + callback && callback([]); + return; + } + if (typeof names === 'string') { + names = names.split(','); + } + // 保存 + if (type === 'save') { + const list = []; + const save = index => { + this.fileSave(names[index], bridgeName => { + list.push(bridgeName); + // 递归下一个 + if (index < names.length - 1) { + setTimeout(() => { + save(index + 1); + }, 10); + } + // 完成 + else { + callback && callback(list); + } + }, err => { + callback && callback(null, err); + }); + }; + 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); + } + }, err => { + callback && callback(null, err); + }); + }; + load(0); + } + // 移除 + else if (type === 'remove') { + names.forEach((name, index) => { + setTimeout(() => { + this.fileRemove(name); + }, 10 * index); + }); + } + } + } // 全局服务实例 -- Gitblit v1.9.1