diff --git a/src/dust/packages/dust-core/dict-obj.ts b/src/dust/packages/dust-core/dict-obj.ts index 790b3ff..59427b3 100644 --- a/src/dust/packages/dust-core/dict-obj.ts +++ b/src/dust/packages/dust-core/dict-obj.ts @@ -36,7 +36,7 @@ class DictObj { private _keyColumns: DictColumn[] = []; private _nextNo = 0; private _nextId = 0; - private _cacheData: IDictionary = {}; + private _cacheData: IDictionary = {}; private _id = '0'; /** * 对象ID @@ -439,6 +439,10 @@ class DictObj { * @param row */ async triggerError(err?: string, row?: DictRow) { + if (err) { + console.warn(err); + } + this.onError.post({ error: err, row, @@ -483,7 +487,7 @@ class DictObj { } }); - if (!ignoreDetail && this.isMaster) { + if (!ignoreDetail) { this._childRelations.forEach(r => { const err = r.detail.getErrors(); if (err) { @@ -988,7 +992,7 @@ class DictObj { return dr; } - this.updateParentAsync(); + await this.updateParentAsync(); await this.triggerCollectionChangedAsync(CollectionChangedAction.REMOVE, dr); if (this._currentRow === dr) { await this.moveToPrevAsync(); @@ -1054,9 +1058,9 @@ class DictObj { if (this._rows.length > 0) { if (firstIndex < this._rows.length) { - this.moveToAsync(firstIndex); + await this.moveToAsync(firstIndex); } else if (firstIndex > 0) { - this.moveToAsync(firstIndex - 1); + await this.moveToAsync(firstIndex - 1); } } } @@ -1140,13 +1144,20 @@ class DictObj { } for (const key in this._cacheData) { - for (const row of this._cacheData[key]) { + const cacheData = this._cacheData[key]; + for (const row of cacheData.rows) { if (row.getRowState() !== RowState.UNCHANGED) { if (!iterate || iterate(row) !== false) { changes.push(row); } } } + + for (const delRow of cacheData.deletedRows) { + if (!iterate || iterate(delRow) !== false) { + changes.push(delRow); + } + } } return changes; @@ -1271,7 +1282,7 @@ class DictObj { this._rows = []; if (this._currentRow && this._currentRow.getRowState() === RowState.ADDED) { - this.setCurrentRowAsync(null); + await this.setCurrentRowAsync(null); } // 还原数据 @@ -1377,10 +1388,10 @@ class DictObj { for (const r of this.rows) { if (!schemaData.updateRows[r.getId()]) { continue; } const newData = schemaData.updateRows[r.getId()]; - r.loadData(newData); - await this.triggerCollectionChangedAsync(CollectionChangedAction.REPLACE, r); - await r.refreshLayoutAsync(); + r.updateData(newData); } + + await this.triggerCollectionChangedAsync(CollectionChangedAction.REPLACE); } // 加载明细数据 @@ -1393,7 +1404,7 @@ class DictObj { for (const d of jsonDetails) { if (!d.id || !map[d.id]) { continue; } await map[d.id].deserializeAsync(d); - await map[d.id].updateParentAsync(); + await map[d.id].updateParentAsync(undefined, true); } } @@ -1410,7 +1421,6 @@ class DictObj { if (schemaData.rows !== undefined) { const rows = schemaData.rows || []; await this.loadDataAsync(rows, schemaData.totalRows, hasGrid); - await this.onAfterLoadData.post({}); } } @@ -1440,6 +1450,11 @@ class DictObj { } this._totalRows = totalRows || this._rows.length; + await this.afterLoadDataAsync(); + } + + private async afterLoadDataAsync() { + await this.onAfterLoadData.post({}); await this.triggerCollectionChangedAsync(CollectionChangedAction.RESET); await this.moveToFirstAsync(); } @@ -1559,7 +1574,7 @@ class DictObj { isMaster: this.isMaster, rows: [], state: this.state, - readonly: readonly, + readonly, pageSize: this.isMultiPage ? this.pageSize : 0, pageIndex: this.pagenum < 1 ? 0 : this.pagenum - 1, totalRows: this.pagenum <= 1 ? -1 : this._totalRows, @@ -1678,14 +1693,14 @@ class DictObj { } } - private hasSavaData(objs: DictObjSchema[]): boolean { + private hasSaveData(objs: DictObjSchema[]): boolean { for (const ds of objs) { if (ds.rows.length > 0 && ds.rows.some(r => r.$rowState !== RowState.UNCHANGED)) { return true; } const details = ds.relations.map(r => r.detail); - if (this.hasSavaData(details)) { + if (this.hasSaveData(details)) { return true; } } @@ -1741,7 +1756,7 @@ class DictObj { } } - const hasData = this.hasSavaData(postData.objs); + const hasData = this.hasSaveData(postData.objs); if (!hasData) { await this.onAfterSave.post({}); return true; @@ -1757,11 +1772,7 @@ class DictObj { await this.afterObjSave(); if (this.isMaster && this.currentRow) { - const tempRow = this.currentRow; await this.searchByRowAsync(this.currentRow); - if (tempRow === this.currentRow) { - await this.loadDetailsAsync(); - } } if (others && others.length > 0) { @@ -1976,7 +1987,7 @@ class DictObj { const data = result || {}; const schemaData = data[0]; if (row !== undefined) { - this.loadRowDataOfRemote(row, schemaData); + await this.loadRowDataOfRemote(row, schemaData); return; } @@ -1986,18 +1997,14 @@ class DictObj { public putCache(key: string) { if (!key) { return; } - const cache: DictRow[] = []; - - this.rows.forEach(r => { - cache.push(r); - }); - - this._deletedRows.forEach(r => { - cache.push(r); - }); + const cache:CacheData = { + deletedRows: [...this._deletedRows], + rows: [...this._rows], + originRows: [...this._originRows] + }; - this.rows.splice(0); - this._deletedRows.splice(0); + this._rows = []; + this._deletedRows = []; this._cacheData[key] = cache; } @@ -2006,33 +2013,56 @@ class DictObj { return this._cacheData[key]; } + private loadCache(cache:CacheData) { + this._rows = cache.rows; + this._deletedRows = cache.deletedRows; + this._originRows = cache.originRows; + } + public flushCache(key: string) { if (!key) { return; } delete this._cacheData[key]; } - private searchCacheData(row: DictRow, relations: DictRelation[]): boolean { + private async searchCacheData(relations: DictRelation[], row?: DictRow) { + if (!this._parentRelation) { + return false; + } + for (const rel of relations) { + // 缓存当前数据 const key = rel.getNestedKey(); + if (key === String(row?.$id)) { + return true; + } + + // 保存当前数据 rel.detail.putCache(key); - const newKey = rel.setNestedKey(row); - const cacheData = rel.detail.getCache(newKey); - if (!cacheData) { - return false; - } + // 根据传入行,加载新数据 + if (row) { + const newKey = rel.setNestedKey(row); + let cacheData = rel.detail.getCache(newKey); + if (!cacheData && row.getRowState() === RowState.ADDED) { + cacheData = { + deletedRows: [], + originRows: [], + rows: [] + }; + } - cacheData.forEach(r => { - if (r.getRowState() === RowState.DELETED) { - rel.detail._deletedRows.push(r); - } else { - rel.detail.rows.push(r); + if (!cacheData) { + return false; } - }); - rel.detail.flushCache(newKey); + rel.detail.loadCache(cacheData); + rel.detail.flushCache(newKey); + } else { + // 清空数据 + rel.setNestedKey(); + } - rel.detail.renderAsync(RenderAction.DATA); + await rel.detail.afterLoadDataAsync(); } return true; @@ -2059,7 +2089,7 @@ class DictObj { * @param {DictRow} row * @return */ - async searchByRowAsync(row: DictRow) { + async searchByRowAsync(row: DictRow, loadDetail = true) { if (!row) { throw new Error('row is null'); } @@ -2073,6 +2103,9 @@ class DictObj { return; } await this.searchAsync({ row }); + if (loadDetail && this.isMaster && row === this.currentRow) { + await this.loadDetailsAsync(); + } } private async loadRowDataOfRemote(row: DictRow, schemaData: any) { @@ -2100,55 +2133,59 @@ class DictObj { * @return {void} */ async loadDetailsAsync(row?: DictRow, excludes?: DictObj[], includes?: DictObj[]) { - if (this._childRelations.length <= 0) { + let relations = this._childRelations.filter(rel => excludes === undefined || excludes.indexOf(rel.detail) < 0); + if (includes && includes.length > 0) { + relations = relations.filter(r => includes.indexOf(r.detail) >= 0); + } + + if (relations.length <= 0) { return; } if (!row) { - row = this._currentRow || undefined; + row = this._currentRow ?? undefined; } + // 空行处理逻辑 if (!row) { + await this.clearDetailsAsync(excludes); + await this.searchCacheData(relations); return; } + // 从从表,检查缓存数据 + const handled = await this.searchCacheData(relations, row); + if (handled) { return; } - let relations = this._childRelations.filter(rel => excludes === undefined || excludes.indexOf(rel.detail) < 0); - if (includes && includes.length > 0) { - relations = relations.filter(r => includes.indexOf(r.detail) >= 0); - } - + // 主表,清空缓存数据以及明细 if (!this._parentRelation) { relations.forEach(rel => { rel.detail.clearCache(); }); + await this.clearDetailsAsync(excludes); + } - if (row.getRowState() === RowState.ADDED) { - await this.clearDetailsAsync(excludes); - return; - } - } else { - // 新增逻辑,支持cacheData - const handled = this.searchCacheData(row, relations); - if (handled) { return; } + if (row.getRowState() === RowState.ADDED) { + return; } try { - relations.forEach(r => { - r.detail.setLoading(true); - }); + for (const r of relations) { + await r.detail.setLoading(true); + } const result = await this.searchRemoteAsync({ relations, row, - readonly: true + readonly: true, + showError: true }); if (!result) return; const data = result || {}; await this.deserializeAsync(data[0]); } finally { - relations.forEach(r => { - r.detail.setLoading(false); - }); + for (const r of relations) { + await r.detail.setLoading(false); + } } } @@ -2352,7 +2389,7 @@ class DictObj { * 更新父数据 * @param col 明细列 */ - async updateParentAsync(col?: DictColumn) { + async updateParentAsync(col?: DictColumn, ignoreAggregate?: boolean) { if (this._updating) { return; } @@ -2370,13 +2407,18 @@ class DictObj { } if (col) { - await parentRlt.aggregateDetailAsync(col); + if (!ignoreAggregate) { + await parentRlt.aggregateDetailAsync(col); + } + parentRlt.updateEditLimit(); return; } for (const c of this.columns) { - await parentRlt.aggregateDetailAsync(c); + if (!ignoreAggregate) { + await parentRlt.aggregateDetailAsync(c); + } } parentRlt.updateEditLimit(); @@ -2407,8 +2449,8 @@ class DictObj { await this.loadDetailsAsync(); } - // 新增行强制清空明细 - if (this._currentRow && this._currentRow.getRowState() === RowState.ADDED) { + // 空行,新增行强制清空明细 + if (!this._currentRow || this._currentRow.getRowState() === RowState.ADDED) { await this.loadDetailsAsync(); } } @@ -3061,10 +3103,14 @@ class DictColumn { }); } - getRefName(key: string) { - if (!this.refFieldName || !this._refData || !this._refData[key]) return null; + getRefName(): string | undefined { + if (this.refType === RefType.ENUM) { + return this.refItem?.name; + } + + if (!this.refFieldName || !this.refItem) return undefined; - return this._refData[key][this.refFieldName]; + return this.refItem[this.refFieldName]; } /** @@ -3296,9 +3342,7 @@ class DictRelation { */ async serializeAsync(option: SerializeOption = {}) { const newOption: SerializeOption = { ...option }; - if (option.isSyncData) { - newOption.relations = this._detail.detailRelations.filter(r => r.check()); - } + newOption.relations = this._detail.detailRelations.filter(r => r.check()); return { detail: await this._detail.serializeAsync(newOption), @@ -3356,12 +3400,7 @@ class DictRelation { return ''; } - const arr: string[] = []; - this._masterColunms.forEach(name => { - arr.push(row[name] || ''); - }); - - this._nestedKey = arr.join('|'); + this._nestedKey = String(row.$id); return this._nestedKey; } @@ -3385,24 +3424,10 @@ class DictRelation { } /** - * 字表合计 - * @param {DictColumn} detailCol - */ - aggregateDetail(detailCol: DictColumn) { - try { - const masterColName = this._totalMap[detailCol.columnName]; - if (!masterColName) { - return; - } - const curRow = this._master.currentRow; - if (curRow) { - curRow.setValue(masterColName, this.getTotalValue(detailCol)); - } - } catch (ex) { - console.log(ex); - } - } - + * 字表合计 + * @param detailCol + * @returns + */ async aggregateDetailAsync(detailCol: DictColumn) { try { const masterColName = this._totalMap[detailCol.columnName]; @@ -3541,10 +3566,10 @@ class DictRow { return this._error; } - setError(err: string | undefined) { + async setError(err: string | undefined) { this._error = err; if (this._obj) { - this._obj.triggerError(this._error, this); + await this._obj.triggerError(this._error, this); } } @@ -3749,6 +3774,19 @@ class DictRow { } } + /** + * 根据传入data更新行数据 + * @param data + * @returns + */ + updateData(data: any) { + if (!data) { return; } + this._obj.columns.forEach(c => { + if (data[c.columnName] === undefined) { return; } + this._data[c.columnName] = data[c.columnName]; + }); + } + /** * 加载数据,数据来自于data,通常是服务获取来的数据 * @param {DictRow|Object} data 数据 @@ -3997,7 +4035,7 @@ class DictRow { this._data[col.columnName] = val; - const refVal = col.getRefName(val) ?? refValue; + const refVal = col.getRefName() ?? refValue; this._data[col.columnName + '$'] = refVal || null; // 清空错误 @@ -4393,7 +4431,7 @@ class DictRow { } // 检查空行 if (this.isEmpty()) { - this.deleteAsync(); + await this.deleteAsync(); return true; } @@ -4880,6 +4918,7 @@ interface SearchOption { relations?: DictRelation[] readonly?: boolean carryUI?: boolean + showError?: boolean } interface PostData { @@ -4887,3 +4926,9 @@ interface PostData { objs: DictObjSchema[] state?: any } + +interface CacheData { + originRows: DictRow[] + deletedRows: DictRow[] + rows: DictRow[] +} diff --git a/src/dust/packages/dust-vue/DictPage/dict-biz.ts b/src/dust/packages/dust-vue/DictPage/dict-biz.ts index 018b42b..b8ab14f 100644 --- a/src/dust/packages/dust-vue/DictPage/dict-biz.ts +++ b/src/dust/packages/dust-vue/DictPage/dict-biz.ts @@ -120,12 +120,12 @@ export default class DictBiz extends Biz { case 'query': case 'refresh': { let obj = store.master; - if (args && args.obj) { + if (args?.obj) { obj = args.obj as DictObj; } await obj.searchAsync({ reset: true }); if (obj.getError() !== '') { - this.showMessage(store, obj.getError(), 'error', '查询失败'); + await this.showMessage(store, obj.getError(), 'error', '查询失败'); } break; } @@ -135,9 +135,9 @@ export default class DictBiz extends Biz { if (confirmResult === 'confirm') { const result = await store.master.deleteAsync(store.master.currentRow); if (!result) { - this.showMessage(store, store.master.getAllErrorHtml('未知错误'), 'error', '删除失败'); + await this.showMessage(store, store.master.getAllErrorHtml('未知错误'), 'error', '删除失败'); } else { - this.showMessage(store, '数据已删除', 'success', '删除成功'); + await this.showMessage(store, '数据已删除', 'success', '删除成功'); } } break; @@ -145,7 +145,11 @@ export default class DictBiz extends Biz { case 'save': { const success = await store.master.saveAsync(); if (!success) { - this.showMessage(store, store.master.getAllErrorHtml('未知错误'), 'error', '保存失败'); + const lastError = store.master.getErrors(); + if (lastError === 'cancel') { + return; + } + await this.showMessage(store, store.master.getAllErrorHtml('未知错误'), 'error', '保存失败'); } else { await store.master.endEditAsync(); }