diff --git a/lib/ui/grid/grid.js b/lib/ui/grid/grid.js index 44ef7cc..d84d32f 100644 --- a/lib/ui/grid/grid.js +++ b/lib/ui/grid/grid.js @@ -16,7 +16,8 @@ import { GridColumn, GridInputColumn, GridTextColumn, GridDropdownColumn, GridCh * @version 1.0.2 */ -const ScriptPath = (self.document == null ? self.location.href : self.document.currentScript.src).replace(/\?.+$/, ''); +const ScriptPath = (self.document == null ? self.location.href : self.document.currentScript.src).replace(/ui\.min\.js\?.+$/, ''); +const Encoder = new TextEncoder('utf-8'); const ColumnChangedType = { Reorder: 'reorder', @@ -460,6 +461,15 @@ const GridColumnDirection = { * @interface */ +/** + * Grid 数据导出对象 + * @typedef GridExportData + * @property {Uint8Array} data - 导出数据 + * @property {string} [type] - 导出类型,`"compressed"` 意为压缩数据 + * @property {string} [error] - 压缩中的异常信息提示 + * @interface + */ + /** * 列排序定义接口 * @typedef GridColumnSortDefinition @@ -2094,11 +2104,19 @@ export class Grid { * }> * } * ``` - * @param {boolean} [compressed=true] - 是否采用 deflate 压缩 - * @returns {Promise} 返回 `Uint8Array` 数据对象 + * @param {string | boolean} [compressed=deflate] - 压缩编码,传入 false 则取消压缩 + * @param {string} [module] - 压缩模块,默认采用 wasm_flate.deflate 编码,自定义模块需要实现以下消息事件 + * * `onmessage` - 接收消息 + * * `{ type: 'init', path: string}` - 初始化消息,参数 `path` 为 `ui.min.js` 脚本所在路径 + * * `{ type: 'compress', data: Uint8Array }` - 压缩消息,参数 `data` 为原始数据 + * * `postMessage` - 返回消息 + * * `{ type: 'init', result?: 0, error?: string}` - 初始化事件中的消息反馈,没有 `error` 意为成功 + * * `{ error: string }` - 压缩事件中的消息反馈,`error` 值为错误信息 + * * `Uint8Array` - 反馈压缩后的数据 + * @returns {Promise} 返回 `Uint8Array` 数据对象 * @since 1.0.2 */ - export(compressed) { + export(compressed, module) { const data = { columns: this.columns.map(c => ({ key: c.key, @@ -2122,7 +2140,7 @@ export class Grid { } else { val = s[c.key]; if (val != null) { - if (Object.prototype.hasOwnProperty.call(val, 'DisplayValue')) { + if (Object.prototype.hasOwnProperty.call(val, 'DisplayValue') && val.Value === val.DisplayValue) { val = val.DisplayValue; } else if (Array.isArray(val)) { val = val.join(', '); @@ -2153,13 +2171,17 @@ export class Grid { sortArray: this.sortArray }; const json = JSON.stringify(data); - const uncompressed = json => new TextEncoder('utf-8').encode(json); if (compressed === false) { - return Promise.resolve(uncompressed(json)); + return Promise.resolve(Encoder.encode(json)); } return new Promise(resolve => { let working; - const url = URL.createObjectURL(new Blob([`let wasm,WASM_VECTOR_LEN=0,encoder=new TextEncoder("utf-8"),cachegetUint8Memory0=null;function getUint8Memory0(){return null!==cachegetUint8Memory0&&cachegetUint8Memory0.buffer===wasm.memory.buffer||(cachegetUint8Memory0=new Uint8Array(wasm.memory.buffer)),cachegetUint8Memory0}let cachegetInt32Memory0=null;function getInt32Memory0(){return null!==cachegetInt32Memory0&&cachegetInt32Memory0.buffer===wasm.memory.buffer||(cachegetInt32Memory0=new Int32Array(wasm.memory.buffer)),cachegetInt32Memory0}function passArray8ToWasm0(e,t){const n=t(1*e.length);return getUint8Memory0().set(e,n/1),WASM_VECTOR_LEN=e.length,n}function getArrayU8FromWasm0(e,t){return getUint8Memory0().subarray(e/1,e/1+t)}function deflate_encode_raw(e){var t=passArray8ToWasm0(e,wasm.__wbindgen_malloc),n=WASM_VECTOR_LEN;wasm.deflate_encode_raw(8,t,n);var r=getInt32Memory0()[2],a=getInt32Memory0()[3],s=getArrayU8FromWasm0(r,a).slice();return wasm.__wbindgen_free(r,1*a),s}self.addEventListener("message",e=>{const t=e.data.type;if("init"===t)if("function"==typeof WebAssembly.instantiateStreaming){const t={},n=fetch(e.data.module);WebAssembly.instantiateStreaming(n,t).then(({instance:e})=>{wasm=e.exports,self.postMessage({type:"init",result:0})}).catch(e=>n.then(t=>{"application/wasm"!==t.headers.get("Content-Type")?self.postMessage({type:"init",error:"\`WebAssembly.instantiateStreaming\` failed because your server does not serve wasm with \`application/wasm\` MIME type. Original error: "+e.message}):self.postMessage({type:"init",error:e.message})}))}else self.postMessage({type:"init",error:"no \`WebAssembly.instantiateStreaming\`"});else if("compress"===t)if(null==wasm)self.postMessage({error:"no \`wasm\` instance"});else{let t=deflate_encode_raw(encoder.encode(e.data.text));self.postMessage(t,[t.buffer])}});`])); + let url; + if (typeof module === 'string') { + url = `${ScriptPath}${module}`; + } else { + url = URL.createObjectURL(new Blob([`let wasm,WASM_VECTOR_LEN=0,cachegetUint8Memory0=null;function getUint8Memory0(){return null!==cachegetUint8Memory0&&cachegetUint8Memory0.buffer===wasm.memory.buffer||(cachegetUint8Memory0=new Uint8Array(wasm.memory.buffer)),cachegetUint8Memory0}let cachegetInt32Memory0=null;function getInt32Memory0(){return null!==cachegetInt32Memory0&&cachegetInt32Memory0.buffer===wasm.memory.buffer||(cachegetInt32Memory0=new Int32Array(wasm.memory.buffer)),cachegetInt32Memory0}function passArray8ToWasm0(e,t){const a=t(1*e.length);return getUint8Memory0().set(e,a/1),WASM_VECTOR_LEN=e.length,a}function getArrayU8FromWasm0(e,t){return getUint8Memory0().subarray(e/1,e/1+t)}function encode_raw(e,t){var a=passArray8ToWasm0(t,wasm.__wbindgen_malloc),r=WASM_VECTOR_LEN;wasm[e+"_encode_raw"](8,a,r);var s=getInt32Memory0()[2],n=getInt32Memory0()[3],m=getArrayU8FromWasm0(s,n).slice();return wasm.__wbindgen_free(s,1*n),m}self.addEventListener("message",e=>{const t=e.data.type;if("init"===t)if("function"==typeof WebAssembly.instantiateStreaming){const t={},a=fetch(e.data.path+"wasm_flate_bg.wasm");WebAssembly.instantiateStreaming(a,t).then(({instance:e})=>{wasm=e.exports,self.postMessage({type:"init",result:0})}).catch(e=>a.then(t=>{"application/wasm"!==t.headers.get("Content-Type")?self.postMessage({type:"init",error:"\`WebAssembly.instantiateStreaming\` failed because your server does not serve wasm with \`application/wasm\` MIME type. Original error: "+e.message}):self.postMessage({type:"init",error:e.message})}))}else self.postMessage({type:"init",error:"no \`WebAssembly.instantiateStreaming\`"});else if("compress"===t)if(null==wasm)self.postMessage({error:"no \`wasm\` instance"});else{let t=encode_raw("${compressed ?? 'deflate'}",e.data.data);self.postMessage(t,[t.buffer])}});`])); + } const worker = new Worker(url); /** * @private @@ -2176,17 +2198,18 @@ export class Grid { const timer = setTimeout(() => { if (working) { // terminate(reject, { message: 'timeout' }); - terminate(resolve, { data: uncompressed(json), error: 'timeout' }); + terminate(resolve, { data: Encoder.encode(json), error: 'timeout' }); } }, 30000); worker.addEventListener('message', e => { if (working) { if (e.data.error != null) { // terminate(reject, { message: e.data.error }); - terminate(resolve, { data: uncompressed(json), error: e.data.error }); + terminate(resolve, { data: Encoder.encode(json), error: e.data.error }); } else { if (e.data.type === 'init') { - worker.postMessage({ type: 'compress', text: json }); + const uncompressed = Encoder.encode(json); + worker.postMessage({ type: 'compress', data: uncompressed }, [uncompressed.buffer]); } else { clearTimeout(timer); terminate(resolve, { type: 'compressed', data: e.data }); @@ -2198,11 +2221,11 @@ export class Grid { if (working) { clearTimeout(timer); // terminate(reject, e); - terminate(resolve, { data: uncompressed(json), error: e.message }); + terminate(resolve, { data: Encoder.encode(json), error: e.message }); } }) working = true; - worker.postMessage({ type: 'init', module: ScriptPath.replace(/ui\.min\.js$/, 'wasm_flate_bg.wasm') }); + worker.postMessage({ type: 'init', path: ScriptPath.replace(/ui\.min\.js$/, 'wasm_flate_bg.wasm') }); }); } @@ -2590,7 +2613,7 @@ export class Grid { } cols.forEach((col, j) => { const cell = createElement('td', 'ui-grid-cell'); - virtualRow.cells[col.key ?? j] = {}; + virtualRow.cells[col.key ?? j] = { style: '' }; if (col.visible !== false) { let style = this._get(col.key, 'style') ?? {}; if (col.isfixed) { @@ -2823,7 +2846,7 @@ export class Grid { if (stateChanged) { if (typeof type.createEdit === 'function') { delete virtualCell.attrs; - delete virtualCell.style; + virtualCell.style = ''; delete virtualCell.value; delete virtualCell.enabled; } @@ -2943,7 +2966,7 @@ export class Grid { return; } let val = this.total[col.key]; - if (Object.prototype.hasOwnProperty.call(val, 'DisplayValue')) { + if (val != null && Object.prototype.hasOwnProperty.call(val, 'DisplayValue')) { val = val.DisplayValue; } val ??= '';