From 2376678aa8f90f294405d443244611edac444267 Mon Sep 17 00:00:00 2001 From: ChenX Date: Tue, 8 Dec 2020 09:47:55 +0800 Subject: [PATCH] =?UTF-8?q?!1344=20=E4=BC=98=E5=8C=96:=E5=A6=82=E6=9E=9C?= =?UTF-8?q?=E7=94=A8=E6=88=B7=E5=BC=80=E5=90=AF=E4=BA=86=E8=87=AA=E5=8A=A8?= =?UTF-8?q?PU,=E9=82=A3=E4=B9=88=E5=9C=A8=E4=BF=9D=E5=AD=98=E5=BA=8F?= =?UTF-8?q?=E5=88=97=E5=8C=96=E6=97=B6=E4=B8=8D=E5=BA=8F=E5=88=97=E5=8C=96?= =?UTF-8?q?=E5=8E=86=E5=8F=B2=E8=AE=B0=E5=BD=95(=E4=BB=A5=E6=AD=A4?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=80=A7=E8=83=BD=E5=92=8C=E5=87=8F=E5=B0=91?= =?UTF-8?q?=E5=86=85=E5=AD=98=E4=BD=BF=E7=94=A8)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- __test__/Geometry/EdgeGeometry.test.ts | 2 +- src/Add-on/Save.ts | 25 +++- src/Editor/AutoSave.ts | 124 ++++++++++++++---- src/Editor/CommandMachine.ts | 2 + .../Modal/OptionModal/SystemConfig.tsx | 2 +- 5 files changed, 120 insertions(+), 35 deletions(-) diff --git a/__test__/Geometry/EdgeGeometry.test.ts b/__test__/Geometry/EdgeGeometry.test.ts index 51bec397b..3a69470ba 100644 --- a/__test__/Geometry/EdgeGeometry.test.ts +++ b/__test__/Geometry/EdgeGeometry.test.ts @@ -76,7 +76,7 @@ test('构建盖子失败2', () => { //因为修改RegionParse精度降低到2个小数点就没问题了 let d = - { "file": [1, "Board", 8, 2, 100, false, 1, 6, 0, [1, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, 0, 97.11678151856177, -50.86622139217798, 0, 1], 0, 0, true, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 97.11678151856177, -50.86622139217798, 0, 1], 0, 3, 633, 361.5, 18, true, "Polyline", 8, 2, 0, false, 0, 7, 0, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], 0, 0, true, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], 0, 2, 4, [0, 0], 0, [361.5, 0], 0, [361.5, 633], 0, [0, 633], 0, true, 2, 3, 100, 10, 5, true, "Polyline", 8, 2, 0, false, 0, 7, 0, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], 0, 0, true, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], 0, 2, 4, [0, 0], 0, [10, 0], 0, [10, 100], 0, [0, 100], 0, true, 0, 3, 0, 0, 0, 0, 0, [1, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, 0, 448.61678151856177, -63.86622139217798, 266.5, 1], 3, 100, 20, 2.001107831095416, true, "Polyline", 8, 2, 0, false, 0, 7, 0, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], 0, 0, true, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], 0, 2, 4, [0, 0], 0, [20, 0], 0, [20, 100], 0, [0, 100], 0, true, 0, 3, 0, 0, 0, 0, 0, [1, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, 0, 438.61678151856177, -50.86622139217798, 266.49751214702076, 1], 3, 0, 0, 0, 0, 0, 9, 2, "左开门板", "主卧", "衣柜", "", "", "", 0, 0, "不排", 2, 0, "1.5", "1.5", "1.5", "1.5", "", "", "", 4, "不排", "不排", "不排", "不排", true, true, 0, 0, 0, 0, 0, 0, 0, 1, true], "basePt": { "x": 97.11678151856177, "y": -68.86622139217798, "z": 0; }, "ucs": [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]; }; + { "file": [1, "Board", 8, 2, 100, false, 1, 6, 0, [1, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, 0, 97.11678151856177, -50.86622139217798, 0, 1], 0, 0, true, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 97.11678151856177, -50.86622139217798, 0, 1], 0, 3, 633, 361.5, 18, true, "Polyline", 8, 2, 0, false, 0, 7, 0, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], 0, 0, true, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], 0, 2, 4, [0, 0], 0, [361.5, 0], 0, [361.5, 633], 0, [0, 633], 0, true, 2, 3, 100, 10, 5, true, "Polyline", 8, 2, 0, false, 0, 7, 0, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], 0, 0, true, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], 0, 2, 4, [0, 0], 0, [10, 0], 0, [10, 100], 0, [0, 100], 0, true, 0, 3, 0, 0, 0, 0, 0, [1, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, 0, 448.61678151856177, -63.86622139217798, 266.5, 1], 3, 100, 20, 2.001107831095416, true, "Polyline", 8, 2, 0, false, 0, 7, 0, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], 0, 0, true, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], 0, 2, 4, [0, 0], 0, [20, 0], 0, [20, 100], 0, [0, 100], 0, true, 0, 3, 0, 0, 0, 0, 0, [1, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, 0, 438.61678151856177, -50.86622139217798, 266.49751214702076, 1], 3, 0, 0, 0, 0, 0, 9, 2, "左开门板", "主卧", "衣柜", "", "", "", 0, 0, "不排", 2, 0, "1.5", "1.5", "1.5", "1.5", "", "", "", 4, "不排", "不排", "不排", "不排", true, true, 0, 0, 0, 0, 0, 0, 0, 1, true], "basePt": { "x": 97.11678151856177, "y": -68.86622139217798, "z": 0 }, "ucs": [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1] }; let brs = LoadBoardsFromFileData(d); for (let br of brs) diff --git a/src/Add-on/Save.ts b/src/Add-on/Save.ts index 92abadee4..95194ea82 100644 --- a/src/Add-on/Save.ts +++ b/src/Add-on/Save.ts @@ -60,14 +60,25 @@ export class Save implements Command } let db = app.Database; - let f = db.FileWrite(); - let vf = new CADFiler(); - app.Viewer.CameraCtrl.WriteFile(vf); + let f: CADFiler; let isError = false; if (userConfig.autoClearHistory) { + //备份,清理 + let hrBak = app.Database.hm.historyRecord; + let hrIndex = app.Database.hm.curIndex; + app.Database.hm.historyRecord = []; + app.Database.hm.curIndex = -1; + + //拷贝db + f = db.FileWrite(); db = new Database().FileRead(f); + + //还原 + app.Database.hm.historyRecord = hrBak; + app.Database.hm.curIndex = hrIndex; + try { Purge(db); @@ -89,7 +100,11 @@ export class Save implements Command intent: Intent.SUCCESS, }); } + else + f = db.FileWrite(); + let vf = new CADFiler(); + app.Viewer.CameraCtrl.WriteFile(vf); f.Write(vf.Data); f.Write(app.Editor.UCSMatrix.toArray()); @@ -214,7 +229,7 @@ function UploadFileHistory(file: any) let userName = localStorage.getItem(StoreageKeys.UserName); //记录历史记录 - let hisStart = app.Database.hm.curIndex - 3;//前十个 + let hisStart = app.Database.hm.curIndex - 3 + 1;//前n条历史记录 let hisIndex = app.Database.hm.curIndex; //修正当前开始位置 if (hisStart < 0) @@ -222,7 +237,7 @@ function UploadFileHistory(file: any) else hisIndex -= hisStart; - let hisEnd = Math.min(app.Database.hm.historyRecord.length, hisIndex + 3);//后10 + let hisEnd = Math.min(app.Database.hm.historyRecord.length, app.Database.hm.curIndex + 3 + 1);//后n条历史记录 let hisf = new CADFiler(); //参考HistoryManager的序列化 diff --git a/src/Editor/AutoSave.ts b/src/Editor/AutoSave.ts index 8ae470a19..4c8281e7b 100644 --- a/src/Editor/AutoSave.ts +++ b/src/Editor/AutoSave.ts @@ -1,18 +1,30 @@ +import { Purge } from "../Add-on/Purge"; import { app } from "../ApplicationServices/Application"; -import { Database } from "../DatabaseServices/Database"; -import { arrayRemoveIf } from "../Common/ArrayExt"; -import { IndexedDbStore, StoreName } from "../IndexedDb/IndexedDbStore"; import { Log } from "../Common/Log"; import { StoreageKeys } from "../Common/StoreageKeys"; -import { TopPanelStore } from "../UI/Store/TopPanelStore"; -import { userConfig } from "./UserConfig"; +import { CADFiler } from "../DatabaseServices/CADFiler"; +import { Database } from "../DatabaseServices/Database"; import { FileServer } from "../DatabaseServices/FileServer"; +import { IndexedDbStore, StoreName } from "../IndexedDb/IndexedDbStore"; +import { TopPanelStore } from "../UI/Store/TopPanelStore"; +import { CommandState } from "./CommandState"; import { TempEditor } from "./TempEditor"; +import { userConfig } from "./UserConfig"; +/** + * TENET(时间钳攻击) + * 这个类保证了在某个时间周期内的操作被保存,通过2个机制来确定生效. + * 1.周期调用.若有未保存的,则保存它,并且重置计时器.(常规操作) + * 2.命令结束后调用.若超过时间周期,则保存它,并且重置计时器.(容错操作,避免在周期后产生的记录需要到下个周期才能保存) + * + * 保证了: + * 在命令结束后才运行(避免在命令状态下保存导致的错误) + */ export class AutoSaveServer { //缓存过了 isCached = false; + private lastTime = 0; private timeId: NodeJS.Timeout; constructor() { @@ -22,31 +34,13 @@ export class AutoSaveServer this.isCached = false; }); } + Start() { this.Stop(); - const topStore = TopPanelStore.GetInstance() as TopPanelStore; - this.timeId = setInterval(async () => - { - if (app.Saved || !topStore.editoring || this.isCached || TempEditor.EditorIng) return; - - let f = app.Database.FileWrite(); - if (false) - { - let newDB = new Database().FileRead(f); - newDB.hm.Clear(); - arrayRemoveIf(newDB.ModelSpace.Entitys, e => e.IsErase); - arrayRemoveIf(newDB.TemplateTable.Objects, e => e.IsErase); - arrayRemoveIf(newDB.GroupTable.Objects, g => - { - return g.Entitys.length === 0 || g.Entitys.every(e => !e || e.IsErase); - }); - f = newDB.FileWrite(); - } - //异步不等待 - this.SavaData(f.Data); - }, userConfig.autoSaveConfig.time * 60 * 1000); + this.timeId = setInterval(() => this.Do(), userConfig.autoSaveConfig.time * 60 * 1000); } + Stop() { if (this.timeId) @@ -55,6 +49,46 @@ export class AutoSaveServer this.timeId = null; } } + + Do() + { + let now = Date.now(); + if (userConfig.autoSaveConfig.enable + && now - this.lastTime > userConfig.autoSaveConfig.time * 60 * 1000) + { + this.SaveFile(); + this.lastTime = now; + } + } + + private SaveFile() + { + const topStore = TopPanelStore.GetInstance() as TopPanelStore; + if (app.Saved || this.isCached) + { + // console.log("文件已经被保存,不需要自动保存!"); + return; + } + + if (!topStore.editoring || TempEditor.EditorIng || CommandState.CommandIng) + { + console.log("文件正在编辑中稍后重试!"); + // setTimeout(() => this.SaveFile(), 1000);// + return; + }; + + let f = AppDbWriteToFile(); + + if (false) + { + let newDB = new Database().FileRead(f); + Purge(newDB); + f = newDB.FileWrite(); + } + //异步不等待 + this.SavaData(f.Data); + } + async SavaData(data: any[]) { const indexDbStore = await IndexedDbStore.CADStore(); @@ -63,13 +97,47 @@ export class AutoSaveServer if (uid) { indexDbStore.Put(StoreName.FileCache, uid, { time: new Date().toLocaleString(), data, fid: server.m_CurFileId }); - Log("文件缓存成功!"); + Log("文件自动备份成功!"); } this.isCached = true; } - async Clear() + + public async Clear() { const store = await IndexedDbStore.CADStore(); store.Delete(StoreName.FileCache, localStorage.getItem(StoreageKeys.Uid)); } } + +/** + * 当前图纸写入到文件中,并且只保存一些命令历史记录 + * @returns + */ +function AppDbWriteToFile(): CADFiler +{ + const SaveRecordCount = 3; //前N条和后N条历史记录 + let hisStart = app.Database.hm.curIndex - SaveRecordCount + 1; //前n条历史记录 + let hisIndex = app.Database.hm.curIndex; + //修正当前开始位置 + if (hisStart < 0) + hisStart = 0; + + else + hisIndex -= hisStart; + + //结束为止 + let hisEnd = Math.min(app.Database.hm.historyRecord.length, app.Database.hm.curIndex + SaveRecordCount + 1); //后n条历史记录 + + //备份,清理 + let hrBak = app.Database.hm.historyRecord; + let hrIndex = app.Database.hm.curIndex; + + app.Database.hm.curIndex = hisIndex; + app.Database.hm.historyRecord = hrBak.slice(hisStart, hisEnd); + + let f = app.Database.FileWrite(); + + app.Database.hm.historyRecord = hrBak; + app.Database.hm.curIndex = hrIndex; + return f; +} diff --git a/src/Editor/CommandMachine.ts b/src/Editor/CommandMachine.ts index 732f166b0..74d91b68b 100644 --- a/src/Editor/CommandMachine.ts +++ b/src/Editor/CommandMachine.ts @@ -157,6 +157,8 @@ class CommandMachine app.Database.hm.Undo(); } + app.AutoSaveServer.Do();//触发自动保存,在这里触发自动保存,保证历史记录已经被写入(是完整的) + app.Viewer.GripScene.visible = true; app.Viewer.GripScene.UpdateAll(); app.Editor.UpdateScreen(); diff --git a/src/UI/Components/Modal/OptionModal/SystemConfig.tsx b/src/UI/Components/Modal/OptionModal/SystemConfig.tsx index a19bc9b1f..a61a1141f 100644 --- a/src/UI/Components/Modal/OptionModal/SystemConfig.tsx +++ b/src/UI/Components/Modal/OptionModal/SystemConfig.tsx @@ -94,7 +94,7 @@ export class SystemConfigPanel extends React.Component uiOption={this.saveUiData} type={CheckObjectType.GT0Num} /> - mins + 分钟