From 5665e762995eb259e16b78edab2d9ca8c4edd85e Mon Sep 17 00:00:00 2001 From: walon Date: Fri, 22 Oct 2021 14:33:12 +0800 Subject: [PATCH] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91=E4=BC=98?= =?UTF-8?q?=E5=8C=96LubanAssistant=E4=BF=9D=E5=AD=98=EF=BC=8C=E5=8F=AA?= =?UTF-8?q?=E4=BF=9D=E5=AD=98=E6=94=B9=E5=8F=98=E7=9A=84=E8=AE=B0=E5=BD=95?= =?UTF-8?q?=E3=80=82=E4=BC=98=E5=8C=96=E8=AE=B0=E5=BD=95=E6=98=BE=E7=A4=BA?= =?UTF-8?q?=E9=A1=BA=E5=BA=8F=EF=BC=8C=E5=A6=82=E6=9E=9Ckey=E4=B8=BAint?= =?UTF-8?q?=E5=92=8Clong=E7=B1=BB=E5=9E=8B=EF=BC=8C=E6=8C=89=E4=BB=8E?= =?UTF-8?q?=E5=B0=8F=E5=88=B0=E5=A4=A7=E6=8E=92=E5=BA=8F=EF=BC=8C=E8=80=8C?= =?UTF-8?q?=E4=B8=8D=E6=98=AF=E6=8C=89=E5=AD=97=E7=AC=A6=E4=B8=B2=E9=A1=BA?= =?UTF-8?q?=E5=BA=8F=E6=8E=92=E5=BA=8F=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Luban.Job.Cfg/Source/Datas/DArray.cs | 11 ++++ src/Luban.Job.Cfg/Source/Datas/DBean.cs | 11 ++++ src/Luban.Job.Cfg/Source/Datas/DBytes.cs | 10 +++ src/Luban.Job.Cfg/Source/Datas/DDateTime.cs | 10 +++ src/Luban.Job.Cfg/Source/Datas/DFshort.cs | 20 +++--- src/Luban.Job.Cfg/Source/Datas/DList.cs | 12 ++++ src/Luban.Job.Cfg/Source/Datas/DMap.cs | 12 ++++ src/Luban.Job.Cfg/Source/Datas/DSet.cs | 11 ++++ src/Luban.Job.Cfg/Source/Utils/DataUtil.cs | 17 +++++ src/LubanAssistant/AssistantTab.cs | 24 +++++-- src/LubanAssistant/ExcelUtil.cs | 70 ++++++++++++++++----- src/LubanAssistant/FillSheetVisitor.cs | 6 +- src/LubanAssistant/Source/Datas/DType.cs | 5 ++ src/LubanAssistant/ToExcelStringVisitor.cs | 2 +- 14 files changed, 186 insertions(+), 35 deletions(-) diff --git a/src/Luban.Job.Cfg/Source/Datas/DArray.cs b/src/Luban.Job.Cfg/Source/Datas/DArray.cs index 104c009..e5c18db 100644 --- a/src/Luban.Job.Cfg/Source/Datas/DArray.cs +++ b/src/Luban.Job.Cfg/Source/Datas/DArray.cs @@ -1,4 +1,5 @@ using Luban.Job.Cfg.DataVisitors; +using Luban.Job.Cfg.Utils; using Luban.Job.Common.Types; using System.Collections.Generic; @@ -17,6 +18,16 @@ namespace Luban.Job.Cfg.Datas this.Datas = datas; } + public override bool Equals(object obj) + { + return obj is DArray d && DataUtil.IsCollectionEqual(Datas, d.Datas); + } + + public override int GetHashCode() + { + throw new System.NotSupportedException(); + } + public override void Apply(IDataActionVisitor visitor, T x) { visitor.Accept(this, x); diff --git a/src/Luban.Job.Cfg/Source/Datas/DBean.cs b/src/Luban.Job.Cfg/Source/Datas/DBean.cs index 0e44525..a7cbcf7 100644 --- a/src/Luban.Job.Cfg/Source/Datas/DBean.cs +++ b/src/Luban.Job.Cfg/Source/Datas/DBean.cs @@ -1,5 +1,6 @@ using Luban.Job.Cfg.DataVisitors; using Luban.Job.Cfg.Defs; +using Luban.Job.Cfg.Utils; using System.Collections.Generic; namespace Luban.Job.Cfg.Datas @@ -21,6 +22,16 @@ namespace Luban.Job.Cfg.Datas this.Fields = fields; } + public override bool Equals(object obj) + { + return obj is DBean d && string.Equals(ImplType?.FullName, d.ImplType?.FullName) && DataUtil.IsCollectionEqual(Fields, d.Fields); + } + + public override int GetHashCode() + { + throw new System.NotSupportedException(); + } + public DType GetField(string fieldName) { if (ImplType.TryGetField(fieldName, out var _, out var findex)) diff --git a/src/Luban.Job.Cfg/Source/Datas/DBytes.cs b/src/Luban.Job.Cfg/Source/Datas/DBytes.cs index 0f8b148..953b59f 100644 --- a/src/Luban.Job.Cfg/Source/Datas/DBytes.cs +++ b/src/Luban.Job.Cfg/Source/Datas/DBytes.cs @@ -11,6 +11,16 @@ namespace Luban.Job.Cfg.Datas { } + public override bool Equals(object obj) + { + return obj is DBytes d && System.Collections.StructuralComparisons.StructuralEqualityComparer.Equals(Value, d.Value); + } + + public override int GetHashCode() + { + throw new System.NotSupportedException(); + } + public override void Apply(IDataActionVisitor visitor, T x) { visitor.Accept(this, x); diff --git a/src/Luban.Job.Cfg/Source/Datas/DDateTime.cs b/src/Luban.Job.Cfg/Source/Datas/DDateTime.cs index 6228c2f..0ec3089 100644 --- a/src/Luban.Job.Cfg/Source/Datas/DDateTime.cs +++ b/src/Luban.Job.Cfg/Source/Datas/DDateTime.cs @@ -20,6 +20,16 @@ namespace Luban.Job.Cfg.Datas this._localTime = (int)new DateTimeOffset(time).ToUnixTimeSeconds(); } + public override bool Equals(object obj) + { + return obj is DDateTime d && Time == d.Time; + } + + public override int GetHashCode() + { + return _localTime.GetHashCode(); + } + public int GetUnixTime(TimeZoneInfo asTimeZone) { if (asTimeZone == null || asTimeZone == TimeZoneInfo.Local) diff --git a/src/Luban.Job.Cfg/Source/Datas/DFshort.cs b/src/Luban.Job.Cfg/Source/Datas/DFshort.cs index 48e8895..bd50ee7 100644 --- a/src/Luban.Job.Cfg/Source/Datas/DFshort.cs +++ b/src/Luban.Job.Cfg/Source/Datas/DFshort.cs @@ -17,6 +17,16 @@ namespace Luban.Job.Cfg.Datas { } + public override bool Equals(object obj) + { + return obj is DFshort d && Value == d.Value; + } + + public override int GetHashCode() + { + return Value.GetHashCode(); + } + public override void Apply(IDataActionVisitor visitor, T x) { visitor.Accept(this, x); @@ -36,15 +46,5 @@ namespace Luban.Job.Cfg.Datas { return visitor.Accept(this, x); } - - public override bool Equals(object obj) - { - return obj is DFshort o && o.Value == this.Value; - } - - public override int GetHashCode() - { - return Value.GetHashCode(); - } } } diff --git a/src/Luban.Job.Cfg/Source/Datas/DList.cs b/src/Luban.Job.Cfg/Source/Datas/DList.cs index fe1c00f..f754a45 100644 --- a/src/Luban.Job.Cfg/Source/Datas/DList.cs +++ b/src/Luban.Job.Cfg/Source/Datas/DList.cs @@ -1,4 +1,5 @@ using Luban.Job.Cfg.DataVisitors; +using Luban.Job.Cfg.Utils; using Luban.Job.Common.Types; using System.Collections.Generic; @@ -17,6 +18,17 @@ namespace Luban.Job.Cfg.Datas this.Datas = datas; } + + public override bool Equals(object obj) + { + return obj is DList d && DataUtil.IsCollectionEqual(Datas, d.Datas); + } + + public override int GetHashCode() + { + throw new System.NotSupportedException(); + } + public override void Apply(IDataActionVisitor visitor, T x) { visitor.Accept(this, x); diff --git a/src/Luban.Job.Cfg/Source/Datas/DMap.cs b/src/Luban.Job.Cfg/Source/Datas/DMap.cs index 20a15e6..df364d6 100644 --- a/src/Luban.Job.Cfg/Source/Datas/DMap.cs +++ b/src/Luban.Job.Cfg/Source/Datas/DMap.cs @@ -1,7 +1,9 @@ using Luban.Job.Cfg.DataVisitors; +using Luban.Job.Cfg.Utils; using Luban.Job.Common.Types; using System; using System.Collections.Generic; +using System.Linq; namespace Luban.Job.Cfg.Datas { @@ -27,6 +29,16 @@ namespace Luban.Job.Cfg.Datas } } + public override bool Equals(object obj) + { + return obj is DMap d && Datas.Count == d.Datas.Count && Datas.All(e => d.Datas.TryGetValue(e.Key, out var v) && object.Equals(e.Value, v)); + } + + public override int GetHashCode() + { + throw new System.NotSupportedException(); + } + public override void Apply(IDataActionVisitor visitor, T x) { visitor.Accept(this, x); diff --git a/src/Luban.Job.Cfg/Source/Datas/DSet.cs b/src/Luban.Job.Cfg/Source/Datas/DSet.cs index c8df53c..d3951fb 100644 --- a/src/Luban.Job.Cfg/Source/Datas/DSet.cs +++ b/src/Luban.Job.Cfg/Source/Datas/DSet.cs @@ -1,4 +1,5 @@ using Luban.Job.Cfg.DataVisitors; +using Luban.Job.Cfg.Utils; using Luban.Job.Common.Types; using System; using System.Collections.Generic; @@ -27,6 +28,16 @@ namespace Luban.Job.Cfg.Datas } } + public override bool Equals(object obj) + { + return obj is DList d && DataUtil.IsCollectionEqual(Datas, d.Datas); + } + + public override int GetHashCode() + { + throw new System.NotSupportedException(); + } + public override void Apply(IDataActionVisitor visitor, T x) { visitor.Accept(this, x); diff --git a/src/Luban.Job.Cfg/Source/Utils/DataUtil.cs b/src/Luban.Job.Cfg/Source/Utils/DataUtil.cs index d669a90..247937d 100644 --- a/src/Luban.Job.Cfg/Source/Utils/DataUtil.cs +++ b/src/Luban.Job.Cfg/Source/Utils/DataUtil.cs @@ -157,6 +157,23 @@ namespace Luban.Job.Cfg.Utils default: return ""; } } + + public static bool IsCollectionEqual(List a, List b) + { + if (a.Count == b.Count) + { + for (int i = 0, n = a.Count; i < n; i++) + { + if (!object.Equals(a[i], b[i])) + { + return false; + } + } + return true; + } + return false; + } + //public static string Data2String(DType data) //{ // var s = new StringBuilder(); diff --git a/src/LubanAssistant/AssistantTab.cs b/src/LubanAssistant/AssistantTab.cs index 6a11464..e16bbd3 100644 --- a/src/LubanAssistant/AssistantTab.cs +++ b/src/LubanAssistant/AssistantTab.cs @@ -114,6 +114,7 @@ namespace LubanAssistant var tableDataInfo = LastLoadTableData = await DataLoaderUtil.LoadTableDataAsync(RootDefineFile, InputDataDir, rawSheet.TableName); var title = ExcelUtil.ParseTitles(sheet); ExcelUtil.FillRecords(sheet, rawSheet.TitleRowCount, title, tableDataInfo); + MessageBox.Show("加载成功"); } catch (Exception e) { @@ -158,7 +159,7 @@ namespace LubanAssistant } } - private void SaveRecords(Action saveTask) + private void SaveRecords(Func saveTask) { Worksheet sheet = Globals.LubanAssistant.Application.ActiveSheet; @@ -181,7 +182,7 @@ namespace LubanAssistant var tableDef = await DataLoaderUtil.LoadTableDefAsync(RootDefineFile, InputDataDir, tableName); var title = ExcelUtil.ParseTitles(sheet); - saveTask(sheet, rawSheet.TitleRowCount, LastLoadTableData, tableDef, title); + await saveTask(sheet, rawSheet.TitleRowCount, LastLoadTableData, tableDef, title); } catch (Exception e) { @@ -192,15 +193,16 @@ namespace LubanAssistant private void BtnSaveAllClick(object sender, RibbonControlEventArgs e) { - SaveRecords((Worksheet sheet, int titleRowNum, TableDataInfo tableDataInfo, DefTable defTable, Title title) => + SaveRecords(async (Worksheet sheet, int titleRowNum, TableDataInfo tableDataInfo, DefTable defTable, Title title) => { int usedRowNum = sheet.UsedRange.Rows.Count; int firstDataRowNum = titleRowNum + 2; if (firstDataRowNum <= usedRowNum) { var newRecords = ExcelUtil.LoadRecordsInRange(defTable, sheet, title, (sheet.Range[$"A{firstDataRowNum}:A{usedRowNum}"]).EntireRow); - ExcelUtil.SaveRecords(InputDataDir, defTable, newRecords); + await ExcelUtil.SaveRecordsAsync(InputDataDir, defTable, GetModifyRecords(LastLoadTableData, newRecords)); CleanRemovedRecordFiles(LastLoadTableData, newRecords); + MessageBox.Show("保存成功"); } else { @@ -209,6 +211,15 @@ namespace LubanAssistant }); } + private List GetModifyRecords(TableDataInfo lastTableDataInfo, List newRecords) + { + string index = lastTableDataInfo.Table.IndexField.Name; + var oldRecordDic = lastTableDataInfo.MainRecords.ToDictionary(r => r.Data.GetField(index)); + var newRecordDic = newRecords.ToDictionary(r => r.Data.GetField(index)); + + return newRecordDic.Where(e => !oldRecordDic.TryGetValue(e.Key, out var r) || !object.Equals(e.Value.Data, r.Data)).Select(e => e.Value).ToList(); + } + private void CleanRemovedRecordFiles(TableDataInfo lastTableDataInfo, List newRecords) { string index = lastTableDataInfo.Table.IndexField.Name; @@ -241,13 +252,14 @@ namespace LubanAssistant MessageBox.Show("没有选中的行"); return; } - SaveRecords((Worksheet sheet, int titleRowNum, TableDataInfo tableDataInfo, DefTable defTable, Title title) => + SaveRecords(async (Worksheet sheet, int titleRowNum, TableDataInfo tableDataInfo, DefTable defTable, Title title) => { int usedRowNum = sheet.UsedRange.Rows.Count; if (titleRowNum + 1 < usedRowNum) { var newRecords = ExcelUtil.LoadRecordsInRange(defTable, sheet, title, selectRange.EntireRow); - ExcelUtil.SaveRecords(InputDataDir, defTable, newRecords); + await ExcelUtil.SaveRecordsAsync(InputDataDir, defTable, GetModifyRecords(LastLoadTableData, newRecords)); + MessageBox.Show("保存成功"); } else { diff --git a/src/LubanAssistant/ExcelUtil.cs b/src/LubanAssistant/ExcelUtil.cs index 22ca2f7..01eba7a 100644 --- a/src/LubanAssistant/ExcelUtil.cs +++ b/src/LubanAssistant/ExcelUtil.cs @@ -1,9 +1,11 @@ -using Luban.Job.Cfg.DataExporters; +using Luban.Common.Utils; +using Luban.Job.Cfg.DataExporters; using Luban.Job.Cfg.Datas; using Luban.Job.Cfg.DataSources.Excel; using Luban.Job.Cfg.DataVisitors; using Luban.Job.Cfg.Defs; using Luban.Job.Cfg.Utils; +using Luban.Job.Common.Types; using Microsoft.Office.Interop.Excel; using System; using System.Collections.Generic; @@ -150,9 +152,28 @@ namespace LubanAssistant //int nextRowIndex = titleRowNum + 2; + // 对于 int和long类型记录,按值排序 + var records = tableDataInfo.MainRecords; + DefField keyField = tableDataInfo.Table.IndexField; + if (keyField != null && (keyField.CType is TInt || keyField.CType is TLong)) + { + string keyFieldName = keyField.Name; + records.Sort((a, b) => + { + DType keya = a.Data.GetField(keyFieldName); + DType keyb = b.Data.GetField(keyFieldName); + switch (keya) + { + case DInt ai: return ai.Value.CompareTo((keyb as DInt).Value); + case DLong al: return al.Value.CompareTo((keyb as DLong).Value); + default: throw new NotSupportedException(); + } + }); + } + int totalRowCount = 0; var dataRangeArray = new List(); - foreach (var rec in tableDataInfo.MainRecords) + foreach (var rec in records) { var fillVisitor = new FillSheetVisitor(dataRangeArray, title.ToIndex + 1, totalRowCount); totalRowCount += rec.Data.Apply(fillVisitor, title); @@ -168,7 +189,7 @@ namespace LubanAssistant } } - Range recordFillRange = sheet.Range[sheet.Cells[titleRowNum + 2, 1], sheet.Cells[titleRowNum + dataRangeArray.Count, title.ToIndex + 1]]; + Range recordFillRange = sheet.Range[sheet.Cells[titleRowNum + 2, 1], sheet.Cells[titleRowNum + 1 + dataRangeArray.Count, title.ToIndex + 1]]; recordFillRange.Value = resultDataRangeArray; } @@ -181,26 +202,45 @@ namespace LubanAssistant return excelSource.ReadMulti(table.ValueTType); } - public static void SaveRecords(string inputDataDir, DefTable table, List records) + public static async Task SaveRecordsAsync(string inputDataDir, DefTable table, List records) { var recordOutputDir = Path.Combine(inputDataDir, table.InputFiles[0]); string index = table.IndexField.Name; + + var saveRecordTasks = new List(); + foreach (var r in records) { - var ss = new MemoryStream(); - var jsonWriter = new Utf8JsonWriter(ss, new JsonWriterOptions() + saveRecordTasks.Add(Task.Run(async () => { - Indented = true, - SkipValidation = false, - Encoder = System.Text.Encodings.Web.JavaScriptEncoder.Create(System.Text.Unicode.UnicodeRanges.All), - }); - RawJsonExportor.Ins.Accept(r.Data, jsonWriter); + var ss = new MemoryStream(); + var jsonWriter = new Utf8JsonWriter(ss, new JsonWriterOptions() + { + Indented = true, + SkipValidation = false, + Encoder = System.Text.Encodings.Web.JavaScriptEncoder.Create(System.Text.Unicode.UnicodeRanges.All), + }); + RawJsonExportor.Ins.Accept(r.Data, jsonWriter); - jsonWriter.Flush(); - var key = r.Data.GetField(index); - var fileName = $"{key.Apply(ToStringVisitor.Ins)}.json"; - File.WriteAllBytes(Path.Combine(recordOutputDir, fileName), DataUtil.StreamToBytes(ss)); + jsonWriter.Flush(); + byte[] resultBytes = DataUtil.StreamToBytes(ss); + var key = r.Data.GetField(index); + var fileName = $"{key.Apply(ToStringVisitor.Ins)}.json"; + + // 只有文件内容改变才重新加载 + string fileFullPath = Path.Combine(recordOutputDir, fileName); + if (File.Exists(fileFullPath)) + { + var oldBytes = await FileUtil.ReadAllBytesAsync(fileFullPath); + if (System.Collections.StructuralComparisons.StructuralEqualityComparer.Equals(resultBytes, oldBytes)) + { + return; + } + } + await FileUtil.SaveFileAsync(recordOutputDir, fileName, resultBytes); + })); } + await Task.WhenAll(saveRecordTasks); } //public static void FillRecord(Worksheet sheet, ref int nextRowIndex, Title title, Record record) diff --git a/src/LubanAssistant/FillSheetVisitor.cs b/src/LubanAssistant/FillSheetVisitor.cs index 1cf8d3c..7b8282c 100644 --- a/src/LubanAssistant/FillSheetVisitor.cs +++ b/src/LubanAssistant/FillSheetVisitor.cs @@ -260,21 +260,21 @@ namespace LubanAssistant public int Accept(DVector2 type, Title x) { var v = type.Value; - SetTitleValue(x, $"{v.X},{v.Y}"); + SetTitleValue(x, $"{v.X}, {v.Y}"); return 1; } public int Accept(DVector3 type, Title x) { var v = type.Value; - SetTitleValue(x, $"{v.X},{v.Y},{v.Z}"); + SetTitleValue(x, $"{v.X}, {v.Y}, {v.Z}"); return 1; } public int Accept(DVector4 type, Title x) { var v = type.Value; - SetTitleValue(x, $"{v.X},{v.Y},{v.Z},{v.W}"); + SetTitleValue(x, $"{v.X}, {v.Y}, {v.Z}, {v.W}"); return 1; } diff --git a/src/LubanAssistant/Source/Datas/DType.cs b/src/LubanAssistant/Source/Datas/DType.cs index 7a8399b..9474adb 100644 --- a/src/LubanAssistant/Source/Datas/DType.cs +++ b/src/LubanAssistant/Source/Datas/DType.cs @@ -24,5 +24,10 @@ namespace Luban.Job.Cfg.Datas { Value = value; } + + public override int GetHashCode() + { + return Value.GetHashCode(); + } } } diff --git a/src/LubanAssistant/ToExcelStringVisitor.cs b/src/LubanAssistant/ToExcelStringVisitor.cs index b0df041..bb2bc94 100644 --- a/src/LubanAssistant/ToExcelStringVisitor.cs +++ b/src/LubanAssistant/ToExcelStringVisitor.cs @@ -127,7 +127,7 @@ namespace LubanAssistant { if (string.IsNullOrEmpty(sep) && type.Type.ElementType.Apply(IsNotSepTypeVisitor.Ins)) { - sep = ","; + sep = ";"; } return string.Join(sep, type.Datas.Select(d => d.Apply(this, sep))); }