diff --git a/DigitalPlatform.CommonControl/FloatingMessageForm.Designer.cs b/DigitalPlatform.CommonControl/FloatingMessageForm.Designer.cs index 5d45e432c..6ef251e1a 100644 --- a/DigitalPlatform.CommonControl/FloatingMessageForm.Designer.cs +++ b/DigitalPlatform.CommonControl/FloatingMessageForm.Designer.cs @@ -35,7 +35,6 @@ private void InitializeComponent() // timer1 // this.timer1.Interval = 1000; - this.timer1.Tick += new System.EventHandler(this.timer1_Tick); // // FloatingMessageForm // diff --git a/DigitalPlatform.CommonControl/FloatingMessageForm.cs b/DigitalPlatform.CommonControl/FloatingMessageForm.cs index afcfd3245..3a6381b99 100644 --- a/DigitalPlatform.CommonControl/FloatingMessageForm.cs +++ b/DigitalPlatform.CommonControl/FloatingMessageForm.cs @@ -8,6 +8,8 @@ using System.Windows.Forms; using System.Drawing.Drawing2D; using System.Diagnostics; +using System.Threading.Tasks; +using System.Threading; namespace DigitalPlatform.CommonControl { @@ -16,7 +18,9 @@ namespace DigitalPlatform.CommonControl /// public partial class FloatingMessageForm : Form { +#if REMOVED DateTime _clearTime = new DateTime(0); +#endif // 是否允许感知 Click 清除文字 public bool Closeable = false; @@ -80,7 +84,7 @@ protected override CreateParams CreateParams const int WS_EX_NOACTIVATE = 0x08000000; // const int WS_EX_TOOLWINDOW = 0x00000080; - cp.ExStyle |= (int)(WS_EX_NOACTIVATE + cp.ExStyle |= (int)(WS_EX_NOACTIVATE // | WS_EX_TOOLWINDOW ); @@ -120,7 +124,7 @@ public bool Clickable windowLong |= 0x20; API.SetWindowLong(this.Handle, API.GWL_EXSTYLE, windowLong); } - catch(ObjectDisposedException) + catch (ObjectDisposedException) { } @@ -512,21 +516,51 @@ protected override void WndProc(ref Message m) } } + int _inDelay = 0; + CancellationTokenSource _cancelDelay = new CancellationTokenSource(); + // 设定延时 Clear 时间长度 public void DelayClear(TimeSpan delta) { + _cancelDelay?.Cancel(); + _cancelDelay = new CancellationTokenSource(); + var token = _cancelDelay.Token; + _ = Task.Run(async () => + { + _inDelay++; + try + { + await Task.Delay(delta, token); + token.ThrowIfCancellationRequested(); + this.TryInvoke(() => + { + base.Text = ""; + this.Invalidate(); + }); + } + finally + { + _inDelay--; + } + }); +#if REMOVED this._clearTime = DateTime.Now + delta; timer1.Start(); +#endif } public bool InDelay() { + return _inDelay > 0; +#if REMOVED if (this._clearTime == new DateTime(0)) return false; return true; +#endif } +#if REMOVED private void timer1_Tick(object sender, EventArgs e) { if (this._clearTime != new DateTime(0) @@ -538,13 +572,17 @@ private void timer1_Tick(object sender, EventArgs e) StopDelayClear(); } } +#endif public void StopDelayClear() { + _cancelDelay?.Cancel(); + _cancelDelay = null; +#if REMOVED timer1.Stop(); this._clearTime = new DateTime(0); +#endif } - } /// diff --git a/DigitalPlatform.IO/BarcodeCapture.cs b/DigitalPlatform.IO/BarcodeCapture.cs index ec6b63d85..b49a0be88 100644 --- a/DigitalPlatform.IO/BarcodeCapture.cs +++ b/DigitalPlatform.IO/BarcodeCapture.cs @@ -147,6 +147,7 @@ private struct EventMsg static bool _shift = false; static bool _alt = false; + static bool _ctrl = false; private int KeyboardHookProc(int nCode, Int32 wParam, IntPtr lParam) { @@ -172,6 +173,13 @@ private int KeyboardHookProc(int nCode, Int32 wParam, IntPtr lParam) goto END1; } + if (key == Keys.LControlKey || key == Keys.RControlKey) + { + _ctrl = false; + Debug.WriteLine("Ctrl keyup"); + goto END1; + } + // 检查是否属于禁用的键 is_stop_key = IsStopKey(key); } @@ -197,6 +205,13 @@ private int KeyboardHookProc(int nCode, Int32 wParam, IntPtr lParam) goto END1; } + if (key == Keys.LControlKey || key == Keys.RControlKey) + { + _ctrl = true; + Debug.WriteLine("Ctrl keydown"); + goto END1; + } + // 检查是否属于禁用的键 is_stop_key = IsStopKey(key); @@ -320,7 +335,8 @@ public bool IsStopKey(Keys key) if (_alt) key |= Keys.Alt; - + if (_ctrl) + key |= Keys.Control; return _stopKeys.Where(o => o == key).Any(); } diff --git a/DigitalPlatform.LibraryServer/AppCirculation.cs b/DigitalPlatform.LibraryServer/AppCirculation.cs index e63c10a8a..55b6d833c 100644 --- a/DigitalPlatform.LibraryServer/AppCirculation.cs +++ b/DigitalPlatform.LibraryServer/AppCirculation.cs @@ -16958,6 +16958,10 @@ void AppendWarning(ref string warning, string text) return -1; } } + else + { + // 其余情况,是否要把当前位置修改为 ?xxx:xxx 形态? + } // 2020/3/27 // 最近一次借还本册操作的时间。用于同步借还请求判断先后关系 diff --git a/DigitalPlatform.RFID.Manager/RfidManager.cs b/DigitalPlatform.RFID.Manager/RfidManager.cs index d371200e3..00b5930ca 100644 --- a/DigitalPlatform.RFID.Manager/RfidManager.cs +++ b/DigitalPlatform.RFID.Manager/RfidManager.cs @@ -1801,6 +1801,44 @@ public static void ClearChannels() { Base.ClearChannels(); } + + // 2024/1/18 + public static ListReadersResult ListReaders() + { + try + { + BaseChannel channel = Base.GetChannel(); + try + { + var result = channel.Object.ListReaders(); + if (result.Value == -1) + Base.TriggerSetError(result, + new SetErrorEventArgs { Error = result.ErrorInfo }); + else + Base.TriggerSetError(result, + new SetErrorEventArgs { Error = null }); // 清除以前的报错 + + return result; + } + finally + { + Base.ReturnChannel(channel); + } + } + catch (Exception ex) + { + // Base.Clear(); + _ = Base.ClearAsync(); + + Base.TriggerSetError(ex, + new SetErrorEventArgs + { + Error = $"RFID 中心出现异常: {ExceptionUtil.GetAutoText(ex)}" + }); + return new ListReadersResult { Value = -1, ErrorInfo = ex.Message }; + } + } + } public delegate void ListTagsEventHandler(object sender, diff --git a/DigitalPlatform/4.0/Stop/NewStopManager.cs b/DigitalPlatform/4.0/Stop/NewStopManager.cs index 7dc1e14d2..93a23710c 100644 --- a/DigitalPlatform/4.0/Stop/NewStopManager.cs +++ b/DigitalPlatform/4.0/Stop/NewStopManager.cs @@ -1659,6 +1659,18 @@ public void UpdateProgressValue(Stop stop) { if (stop == _surfaceStop) { + // 2024/1/17 + if (stop.ProgressMin == -1 + || stop.ProgressMax == -1) + { + InternalSetProgressBar( + stop, + -1, + -1, + -1); + return; + } + if (stop.ProgressMin == -1) throw new Exception("ProgressMin 尚未初始化"); if (stop.ProgressMax == -1) diff --git a/RfidDrivers.First/RfidDriver1.cs b/RfidDrivers.First/RfidDriver1.cs index 0a010d331..47dfaf983 100644 --- a/RfidDrivers.First/RfidDriver1.cs +++ b/RfidDrivers.First/RfidDriver1.cs @@ -19,7 +19,6 @@ using DigitalPlatform; using DigitalPlatform.RFID; using DigitalPlatform.Text; -using System.Security.Cryptography; // 锁定全部读卡器靠一个全局锁来实现。锁定一个读卡器靠 RecordLock 来实现。锁定一个读卡器之前,先尝试用 read 方式获得全局锁 diff --git a/dp2Circulation/Properties/AssemblyInfo.cs b/dp2Circulation/Properties/AssemblyInfo.cs index 5fc7a3ba5..8459aa0d7 100644 --- a/dp2Circulation/Properties/AssemblyInfo.cs +++ b/dp2Circulation/Properties/AssemblyInfo.cs @@ -29,8 +29,8 @@ // Build Number // Revision // -[assembly: AssemblyVersion("3.96.*")] -[assembly: AssemblyFileVersion("3.96.0.0")] +[assembly: AssemblyVersion("3.94.*")] +[assembly: AssemblyFileVersion("3.94.0.0")] // V2.6 2015/11/7 MainForm BiblioSearchForm ChannelForm 采用 ChannelPool。注意观察有无通讯通道方面的故障 // V2.7 2015/11/30 EntityForm 大幅度改造,采用 ChannelPool。Stop 类的 BeginLoop() 不再允许嵌套,注意观察是否会抛出异常。固定面板区属性页的显示很多已经改造为 PropertyTaskList 实现 @@ -232,8 +232,9 @@ // 2023/12/22 当参数为超高频高校联盟格式,不写入 UserBank 时,种册窗册登记对话框写入标签以后,对话框内再次点按钮写入,会报错说 PII 不存在,这个 bug 已经修正 // 2023/12/26 超高频国标格式,既可以把机构代码写入 UII(EPC Bank) 中,也可以特殊指定写入 User Bank(此时 EPC Bank 中的 UII 中不再包含机构代码)。允许这种特殊写入法主要是考虑到它利于在小尺寸 EPC 标签上使用国标格式 // 3.93 2024/1/2 快捷出纳窗的人脸识别增加允许命中多个记录的功能 -// 2024/1/4 书目查询窗导出到订购、期、实体、评注查询窗的功能重构为利用多线程。LibraryChannel 通道超时改为 40 秒 +// 3.94 2024/1/4 书目查询窗导出到订购、期、实体、评注查询窗的功能重构为利用多线程。LibraryChannel 通道超时改为 40 秒 // 书目查询窗导出下属的订购、期、实体、评注记录到记录路径文件,重构为利用多线程 // 读者查询窗导出借阅历史到实体查询窗的功能,重构为利用多线程 // 2024/1/8 读者查询窗导出借阅历史到实体查询窗的功能,增加了一个询问对话框,询问是每个读者记录的借阅历史导出到一个单独的实体查询窗,还是所有读者记录的都导出到唯一的一个实体查询窗 -// 2024/1/16 书目查询窗共享检索时的利用 looping 方式改进。Z39.50 检索时 .ShowMessage() 后来没有清除显示的 bug 被修正 \ No newline at end of file +// 2024/1/16 书目查询窗共享检索时的利用 looping 方式改进。Z39.50 检索时 .ShowMessage() 后来没有清除显示的 bug 被修正 +// 2024/1/17 重构 AmerceForm 中的两个装载信息的线程为 Task,消除了 NewStop 类抛异常的 bug \ No newline at end of file diff --git a/dp2Circulation/Reader/AmerceForm.Designer.cs b/dp2Circulation/Reader/AmerceForm.Designer.cs index b39cdbc02..9d7fb55b7 100644 --- a/dp2Circulation/Reader/AmerceForm.Designer.cs +++ b/dp2Circulation/Reader/AmerceForm.Designer.cs @@ -108,30 +108,31 @@ private void InitializeComponent() // label1 // this.label1.AutoSize = true; - this.label1.Location = new System.Drawing.Point(2, 5); - this.label1.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0); + this.label1.Location = new System.Drawing.Point(4, 9); + this.label1.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.label1.Name = "label1"; - this.label1.Size = new System.Drawing.Size(101, 12); + this.label1.Size = new System.Drawing.Size(180, 21); this.label1.TabIndex = 0; this.label1.Text = "֤(&R):"; // // textBox_readerBarcode // this.textBox_readerBarcode.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.textBox_readerBarcode.Location = new System.Drawing.Point(113, 1); - this.textBox_readerBarcode.Margin = new System.Windows.Forms.Padding(2); + this.textBox_readerBarcode.Font = new System.Drawing.Font("", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134))); + this.textBox_readerBarcode.Location = new System.Drawing.Point(207, 2); + this.textBox_readerBarcode.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); this.textBox_readerBarcode.Name = "textBox_readerBarcode"; - this.textBox_readerBarcode.Size = new System.Drawing.Size(141, 21); + this.textBox_readerBarcode.Size = new System.Drawing.Size(257, 39); this.textBox_readerBarcode.TabIndex = 1; this.textBox_readerBarcode.Enter += new System.EventHandler(this.textBox_readerBarcode_Enter); this.textBox_readerBarcode.Leave += new System.EventHandler(this.textBox_readerBarcode_Leave); // // splitContainer_main // - this.splitContainer_main.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) - | System.Windows.Forms.AnchorStyles.Left) + this.splitContainer_main.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); - this.splitContainer_main.Location = new System.Drawing.Point(0, 30); + this.splitContainer_main.Location = new System.Drawing.Point(0, 52); this.splitContainer_main.Margin = new System.Windows.Forms.Padding(0); this.splitContainer_main.Name = "splitContainer_main"; this.splitContainer_main.Orientation = System.Windows.Forms.Orientation.Horizontal; @@ -143,19 +144,19 @@ private void InitializeComponent() // splitContainer_main.Panel2 // this.splitContainer_main.Panel2.Controls.Add(this.splitContainer_lists); - this.splitContainer_main.Size = new System.Drawing.Size(617, 399); - this.splitContainer_main.SplitterDistance = 98; - this.splitContainer_main.SplitterWidth = 8; + this.splitContainer_main.Size = new System.Drawing.Size(1131, 699); + this.splitContainer_main.SplitterDistance = 171; + this.splitContainer_main.SplitterWidth = 14; this.splitContainer_main.TabIndex = 2; // // webBrowser_readerInfo // this.webBrowser_readerInfo.Dock = System.Windows.Forms.DockStyle.Fill; this.webBrowser_readerInfo.Location = new System.Drawing.Point(0, 0); - this.webBrowser_readerInfo.Margin = new System.Windows.Forms.Padding(2); - this.webBrowser_readerInfo.MinimumSize = new System.Drawing.Size(15, 16); + this.webBrowser_readerInfo.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); + this.webBrowser_readerInfo.MinimumSize = new System.Drawing.Size(28, 28); this.webBrowser_readerInfo.Name = "webBrowser_readerInfo"; - this.webBrowser_readerInfo.Size = new System.Drawing.Size(617, 98); + this.webBrowser_readerInfo.Size = new System.Drawing.Size(1131, 171); this.webBrowser_readerInfo.TabIndex = 0; this.webBrowser_readerInfo.DocumentCompleted += new System.Windows.Forms.WebBrowserDocumentCompletedEventHandler(this.webBrowser_readerInfo_DocumentCompleted); // @@ -163,6 +164,7 @@ private void InitializeComponent() // this.splitContainer_lists.Dock = System.Windows.Forms.DockStyle.Fill; this.splitContainer_lists.Location = new System.Drawing.Point(0, 0); + this.splitContainer_lists.Margin = new System.Windows.Forms.Padding(6, 5, 6, 5); this.splitContainer_lists.Name = "splitContainer_lists"; this.splitContainer_lists.Orientation = System.Windows.Forms.Orientation.Horizontal; // @@ -173,9 +175,9 @@ private void InitializeComponent() // splitContainer_lists.Panel2 // this.splitContainer_lists.Panel2.Controls.Add(this.tableLayoutPanel_amercingOverdue); - this.splitContainer_lists.Size = new System.Drawing.Size(617, 293); - this.splitContainer_lists.SplitterDistance = 145; - this.splitContainer_lists.SplitterWidth = 8; + this.splitContainer_lists.Size = new System.Drawing.Size(1131, 514); + this.splitContainer_lists.SplitterDistance = 254; + this.splitContainer_lists.SplitterWidth = 14; this.splitContainer_lists.TabIndex = 1; // // tableLayoutPanel_amerced @@ -194,19 +196,19 @@ private void InitializeComponent() this.tableLayoutPanel_amerced.RowStyles.Add(new System.Windows.Forms.RowStyle()); this.tableLayoutPanel_amerced.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); this.tableLayoutPanel_amerced.RowStyles.Add(new System.Windows.Forms.RowStyle()); - this.tableLayoutPanel_amerced.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); - this.tableLayoutPanel_amerced.Size = new System.Drawing.Size(617, 145); + this.tableLayoutPanel_amerced.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 35F)); + this.tableLayoutPanel_amerced.Size = new System.Drawing.Size(1131, 254); this.tableLayoutPanel_amerced.TabIndex = 0; // // label2 // this.label2.AutoSize = true; this.label2.Font = new System.Drawing.Font("", 9F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134))); - this.label2.Location = new System.Drawing.Point(0, 2); - this.label2.Margin = new System.Windows.Forms.Padding(0, 2, 2, 0); + this.label2.Location = new System.Drawing.Point(0, 4); + this.label2.Margin = new System.Windows.Forms.Padding(0, 4, 4, 0); this.label2.Name = "label2"; - this.label2.Padding = new System.Windows.Forms.Padding(0, 3, 0, 2); - this.label2.Size = new System.Drawing.Size(64, 17); + this.label2.Padding = new System.Windows.Forms.Padding(0, 5, 0, 4); + this.label2.Size = new System.Drawing.Size(110, 30); this.label2.TabIndex = 0; this.label2.Text = "ѽ:"; // @@ -236,10 +238,10 @@ private void InitializeComponent() this.listView_amerced.FullRowSelect = true; this.listView_amerced.HideSelection = false; this.listView_amerced.LargeImageList = this.imageList_itemType; - this.listView_amerced.Location = new System.Drawing.Point(0, 19); + this.listView_amerced.Location = new System.Drawing.Point(0, 34); this.listView_amerced.Margin = new System.Windows.Forms.Padding(0); this.listView_amerced.Name = "listView_amerced"; - this.listView_amerced.Size = new System.Drawing.Size(617, 100); + this.listView_amerced.Size = new System.Drawing.Size(1131, 176); this.listView_amerced.SmallImageList = this.imageList_itemType; this.listView_amerced.TabIndex = 1; this.listView_amerced.UseCompatibleStateImageBehavior = false; @@ -343,13 +345,15 @@ private void InitializeComponent() // this.toolStrip_amerced.Dock = System.Windows.Forms.DockStyle.Fill; this.toolStrip_amerced.GripStyle = System.Windows.Forms.ToolStripGripStyle.Hidden; + this.toolStrip_amerced.ImageScalingSize = new System.Drawing.Size(28, 28); this.toolStrip_amerced.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { this.toolStripButton_amerced_selectAll, this.toolStripButton_undoAmerce, this.toolStripLabel_amercedMessage}); - this.toolStrip_amerced.Location = new System.Drawing.Point(0, 119); + this.toolStrip_amerced.Location = new System.Drawing.Point(0, 210); this.toolStrip_amerced.Name = "toolStrip_amerced"; - this.toolStrip_amerced.Size = new System.Drawing.Size(617, 26); + this.toolStrip_amerced.Padding = new System.Windows.Forms.Padding(0, 0, 4, 0); + this.toolStrip_amerced.Size = new System.Drawing.Size(1131, 44); this.toolStrip_amerced.TabIndex = 3; this.toolStrip_amerced.Text = "toolStrip1"; // @@ -359,7 +363,7 @@ private void InitializeComponent() this.toolStripButton_amerced_selectAll.Image = ((System.Drawing.Image)(resources.GetObject("toolStripButton_amerced_selectAll.Image"))); this.toolStripButton_amerced_selectAll.ImageTransparentColor = System.Drawing.Color.Magenta; this.toolStripButton_amerced_selectAll.Name = "toolStripButton_amerced_selectAll"; - this.toolStripButton_amerced_selectAll.Size = new System.Drawing.Size(36, 23); + this.toolStripButton_amerced_selectAll.Size = new System.Drawing.Size(58, 38); this.toolStripButton_amerced_selectAll.Text = "ȫѡ"; this.toolStripButton_amerced_selectAll.Click += new System.EventHandler(this.toolStripButton_amerced_selectAll_Click); // @@ -372,7 +376,7 @@ private void InitializeComponent() this.toolStripButton_undoAmerce.Image = ((System.Drawing.Image)(resources.GetObject("toolStripButton_undoAmerce.Image"))); this.toolStripButton_undoAmerce.ImageTransparentColor = System.Drawing.Color.Magenta; this.toolStripButton_undoAmerce.Name = "toolStripButton_undoAmerce"; - this.toolStripButton_undoAmerce.Size = new System.Drawing.Size(73, 23); + this.toolStripButton_undoAmerce.Size = new System.Drawing.Size(123, 38); this.toolStripButton_undoAmerce.Text = "ؽ"; this.toolStripButton_undoAmerce.Click += new System.EventHandler(this.toolStripButton_undoAmerce_Click); // @@ -381,7 +385,7 @@ private void InitializeComponent() this.toolStripLabel_amercedMessage.Alignment = System.Windows.Forms.ToolStripItemAlignment.Right; this.toolStripLabel_amercedMessage.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text; this.toolStripLabel_amercedMessage.Name = "toolStripLabel_amercedMessage"; - this.toolStripLabel_amercedMessage.Size = new System.Drawing.Size(211, 23); + this.toolStripLabel_amercedMessage.Size = new System.Drawing.Size(367, 38); this.toolStripLabel_amercedMessage.Text = "ѡ󣬰Ŧſ -->"; // // tableLayoutPanel_amercingOverdue @@ -402,21 +406,23 @@ private void InitializeComponent() this.tableLayoutPanel_amercingOverdue.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); this.tableLayoutPanel_amercingOverdue.RowStyles.Add(new System.Windows.Forms.RowStyle()); this.tableLayoutPanel_amercingOverdue.RowStyles.Add(new System.Windows.Forms.RowStyle()); - this.tableLayoutPanel_amercingOverdue.Size = new System.Drawing.Size(617, 140); + this.tableLayoutPanel_amercingOverdue.Size = new System.Drawing.Size(1131, 246); this.tableLayoutPanel_amercingOverdue.TabIndex = 0; // // toolStrip_amercing // this.toolStrip_amercing.Dock = System.Windows.Forms.DockStyle.Fill; this.toolStrip_amercing.GripStyle = System.Windows.Forms.ToolStripGripStyle.Hidden; + this.toolStrip_amercing.ImageScalingSize = new System.Drawing.Size(28, 28); this.toolStrip_amercing.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { this.toolStripButton_amercing_selectAll, this.toolStripButton_submit, this.toolStripButton_modifyPriceAndComment, this.toolStripLabel_amercingMessage}); - this.toolStrip_amercing.Location = new System.Drawing.Point(0, 107); + this.toolStrip_amercing.Location = new System.Drawing.Point(0, 192); this.toolStrip_amercing.Name = "toolStrip_amercing"; - this.toolStrip_amercing.Size = new System.Drawing.Size(617, 33); + this.toolStrip_amercing.Padding = new System.Windows.Forms.Padding(0, 0, 4, 0); + this.toolStrip_amercing.Size = new System.Drawing.Size(1131, 54); this.toolStrip_amercing.TabIndex = 5; this.toolStrip_amercing.Text = "toolStrip1"; // @@ -426,7 +432,7 @@ private void InitializeComponent() this.toolStripButton_amercing_selectAll.Image = ((System.Drawing.Image)(resources.GetObject("toolStripButton_amercing_selectAll.Image"))); this.toolStripButton_amercing_selectAll.ImageTransparentColor = System.Drawing.Color.Magenta; this.toolStripButton_amercing_selectAll.Name = "toolStripButton_amercing_selectAll"; - this.toolStripButton_amercing_selectAll.Size = new System.Drawing.Size(36, 30); + this.toolStripButton_amercing_selectAll.Size = new System.Drawing.Size(58, 48); this.toolStripButton_amercing_selectAll.Text = "ȫѡ"; this.toolStripButton_amercing_selectAll.Click += new System.EventHandler(this.toolStripButton_amercing_selectAll_Click); // @@ -439,7 +445,7 @@ private void InitializeComponent() this.toolStripButton_submit.Image = ((System.Drawing.Image)(resources.GetObject("toolStripButton_submit.Image"))); this.toolStripButton_submit.ImageTransparentColor = System.Drawing.Color.Magenta; this.toolStripButton_submit.Name = "toolStripButton_submit"; - this.toolStripButton_submit.Size = new System.Drawing.Size(54, 30); + this.toolStripButton_submit.Size = new System.Drawing.Size(89, 48); this.toolStripButton_submit.Text = ""; this.toolStripButton_submit.Click += new System.EventHandler(this.toolStripButton_submit_Click); // @@ -451,7 +457,7 @@ private void InitializeComponent() this.toolStripButton_modifyPriceAndComment.Image = ((System.Drawing.Image)(resources.GetObject("toolStripButton_modifyPriceAndComment.Image"))); this.toolStripButton_modifyPriceAndComment.ImageTransparentColor = System.Drawing.Color.Magenta; this.toolStripButton_modifyPriceAndComment.Name = "toolStripButton_modifyPriceAndComment"; - this.toolStripButton_modifyPriceAndComment.Size = new System.Drawing.Size(101, 30); + this.toolStripButton_modifyPriceAndComment.Size = new System.Drawing.Size(172, 48); this.toolStripButton_modifyPriceAndComment.Text = "ֻ޸Ľ/ע"; this.toolStripButton_modifyPriceAndComment.Click += new System.EventHandler(this.toolStripButton_modifyPriceAndComment_Click); // @@ -460,7 +466,7 @@ private void InitializeComponent() this.toolStripLabel_amercingMessage.Alignment = System.Windows.Forms.ToolStripItemAlignment.Right; this.toolStripLabel_amercingMessage.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text; this.toolStripLabel_amercingMessage.Name = "toolStripLabel_amercingMessage"; - this.toolStripLabel_amercingMessage.Size = new System.Drawing.Size(211, 30); + this.toolStripLabel_amercingMessage.Size = new System.Drawing.Size(367, 48); this.toolStripLabel_amercingMessage.Text = "ѡ󣬰Ŧſ -->"; // // listView_overdues @@ -483,10 +489,10 @@ private void InitializeComponent() this.listView_overdues.Dock = System.Windows.Forms.DockStyle.Fill; this.listView_overdues.FullRowSelect = true; this.listView_overdues.HideSelection = false; - this.listView_overdues.Location = new System.Drawing.Point(0, 19); + this.listView_overdues.Location = new System.Drawing.Point(0, 34); this.listView_overdues.Margin = new System.Windows.Forms.Padding(0); this.listView_overdues.Name = "listView_overdues"; - this.listView_overdues.Size = new System.Drawing.Size(617, 88); + this.listView_overdues.Size = new System.Drawing.Size(1131, 158); this.listView_overdues.TabIndex = 1; this.listView_overdues.UseCompatibleStateImageBehavior = false; this.listView_overdues.View = System.Windows.Forms.View.Details; @@ -555,11 +561,11 @@ private void InitializeComponent() // this.label3.AutoSize = true; this.label3.Font = new System.Drawing.Font("", 9F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134))); - this.label3.Location = new System.Drawing.Point(0, 2); - this.label3.Margin = new System.Windows.Forms.Padding(0, 2, 2, 0); + this.label3.Location = new System.Drawing.Point(0, 4); + this.label3.Margin = new System.Windows.Forms.Padding(0, 4, 4, 0); this.label3.Name = "label3"; - this.label3.Padding = new System.Windows.Forms.Padding(0, 3, 0, 2); - this.label3.Size = new System.Drawing.Size(64, 17); + this.label3.Padding = new System.Windows.Forms.Padding(0, 5, 0, 4); + this.label3.Size = new System.Drawing.Size(110, 30); this.label3.TabIndex = 0; this.label3.Text = "δ:"; // @@ -568,19 +574,19 @@ private void InitializeComponent() this.panel_amercing_command.AutoSize = true; this.panel_amercing_command.BackColor = System.Drawing.SystemColors.Control; this.panel_amercing_command.Dock = System.Windows.Forms.DockStyle.Fill; - this.panel_amercing_command.Location = new System.Drawing.Point(0, 107); + this.panel_amercing_command.Location = new System.Drawing.Point(0, 192); this.panel_amercing_command.Margin = new System.Windows.Forms.Padding(0); this.panel_amercing_command.Name = "panel_amercing_command"; - this.panel_amercing_command.Size = new System.Drawing.Size(617, 1); + this.panel_amercing_command.Size = new System.Drawing.Size(1131, 1); this.panel_amercing_command.TabIndex = 1; // // button_load // this.button_load.FlatStyle = System.Windows.Forms.FlatStyle.Flat; - this.button_load.Location = new System.Drawing.Point(258, 0); - this.button_load.Margin = new System.Windows.Forms.Padding(2); + this.button_load.Location = new System.Drawing.Point(473, 0); + this.button_load.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); this.button_load.Name = "button_load"; - this.button_load.Size = new System.Drawing.Size(74, 22); + this.button_load.Size = new System.Drawing.Size(136, 38); this.button_load.TabIndex = 2; this.button_load.Text = "װ(&L)"; this.button_load.UseVisualStyleBackColor = true; @@ -595,10 +601,10 @@ private void InitializeComponent() // button_beginFillSummary // this.button_beginFillSummary.FlatStyle = System.Windows.Forms.FlatStyle.Flat; - this.button_beginFillSummary.Location = new System.Drawing.Point(456, 0); - this.button_beginFillSummary.Margin = new System.Windows.Forms.Padding(2); + this.button_beginFillSummary.Location = new System.Drawing.Point(836, 0); + this.button_beginFillSummary.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); this.button_beginFillSummary.Name = "button_beginFillSummary"; - this.button_beginFillSummary.Size = new System.Drawing.Size(123, 22); + this.button_beginFillSummary.Size = new System.Drawing.Size(226, 38); this.button_beginFillSummary.TabIndex = 4; this.button_beginFillSummary.Text = "ĿժҪ(&F)"; this.button_beginFillSummary.UseVisualStyleBackColor = true; @@ -608,9 +614,10 @@ private void InitializeComponent() // checkBox_fillSummary // this.checkBox_fillSummary.AutoSize = true; - this.checkBox_fillSummary.Location = new System.Drawing.Point(337, 4); + this.checkBox_fillSummary.Location = new System.Drawing.Point(618, 7); + this.checkBox_fillSummary.Margin = new System.Windows.Forms.Padding(6, 5, 6, 5); this.checkBox_fillSummary.Name = "checkBox_fillSummary"; - this.checkBox_fillSummary.Size = new System.Drawing.Size(114, 16); + this.checkBox_fillSummary.Size = new System.Drawing.Size(195, 25); this.checkBox_fillSummary.TabIndex = 3; this.checkBox_fillSummary.Text = "װĿժҪ(&S)"; this.checkBox_fillSummary.UseVisualStyleBackColor = true; @@ -623,9 +630,10 @@ private void InitializeComponent() this.panel_load.Controls.Add(this.label1); this.panel_load.Controls.Add(this.checkBox_fillSummary); this.panel_load.Controls.Add(this.button_load); - this.panel_load.Location = new System.Drawing.Point(3, 3); + this.panel_load.Location = new System.Drawing.Point(6, 5); + this.panel_load.Margin = new System.Windows.Forms.Padding(6, 5, 6, 5); this.panel_load.Name = "panel_load"; - this.panel_load.Size = new System.Drawing.Size(605, 24); + this.panel_load.Size = new System.Drawing.Size(1109, 42); this.panel_load.TabIndex = 5; // // tableLayoutPanel_main @@ -636,21 +644,22 @@ private void InitializeComponent() this.tableLayoutPanel_main.Controls.Add(this.splitContainer_main, 0, 1); this.tableLayoutPanel_main.Dock = System.Windows.Forms.DockStyle.Fill; this.tableLayoutPanel_main.Location = new System.Drawing.Point(0, 0); + this.tableLayoutPanel_main.Margin = new System.Windows.Forms.Padding(6, 5, 6, 5); this.tableLayoutPanel_main.Name = "tableLayoutPanel_main"; this.tableLayoutPanel_main.RowCount = 2; this.tableLayoutPanel_main.RowStyles.Add(new System.Windows.Forms.RowStyle()); this.tableLayoutPanel_main.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); - this.tableLayoutPanel_main.Size = new System.Drawing.Size(617, 429); + this.tableLayoutPanel_main.Size = new System.Drawing.Size(1131, 751); this.tableLayoutPanel_main.TabIndex = 6; // // AmerceForm // - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); + this.AutoScaleDimensions = new System.Drawing.SizeF(11F, 21F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(617, 429); + this.ClientSize = new System.Drawing.Size(1131, 751); this.Controls.Add(this.tableLayoutPanel_main); this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); - this.Margin = new System.Windows.Forms.Padding(2); + this.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); this.Name = "AmerceForm"; this.ShowInTaskbar = false; this.Text = ""; diff --git a/dp2Circulation/Reader/AmerceForm.cs b/dp2Circulation/Reader/AmerceForm.cs index 219b08c5c..d67146777 100644 --- a/dp2Circulation/Reader/AmerceForm.cs +++ b/dp2Circulation/Reader/AmerceForm.cs @@ -16,8 +16,7 @@ using DigitalPlatform.CommonControl; using DigitalPlatform.LibraryClient; using DigitalPlatform.LibraryClient.localhost; -using DigitalPlatform.Core; -using Jint.Parser.Ast; + namespace dp2Circulation { @@ -34,13 +33,13 @@ public partial class AmerceForm : MyForm internal Thread threadFillSummary = null; * */ - volatile bool m_bStopFillAmercing = true; - internal Thread threadFillAmercing = null; - FillAmercingParam FillAmercingParam = null; + //volatile bool m_bStopFillAmercing = true; + //internal Thread threadFillAmercing = null; + //FillAmercingParam FillAmercingParam = null; - volatile bool m_bStopFillAmerced = true; - internal Thread threadFillAmerced = null; - FillAmercedParam FillAmercedParam = null; + //volatile bool m_bStopFillAmerced = true; + //internal Thread threadFillAmerced = null; + //FillAmercedParam FillAmercedParam = null; // 图标下标 const int ITEMTYPE_AMERCED = 0; @@ -807,35 +806,10 @@ int _loadReader(string strReaderBarcode, if (String.IsNullOrEmpty(strXml) == false) { -#if NO - nRet = FillAmercingList(strXml, - out strError); - if (nRet == -1) - { - // strError = "FillAmercingList()发生错误: " + strError; - // goto ERROR1; - SetError(this.listView_overdues, strError); - } -#endif BeginFillAmercing(strXml); } -#if NO - nRet = LoadAmercedRecords(this.textBox_readerBarcode.Text, - out strError); - if (nRet == -1) - { - //strError = "LoadAmercedRecords()发生错误: " + strError; - //goto ERROR1; - SetError(this.listView_amerced, strError); - } -#endif BeginFillAmerced(this.ReaderBarcode, null); - -#if NO - if (this.checkBox_fillSummary.Checked == true) - this.BeginFillSummary(); -#endif return 1; } finally @@ -867,6 +841,9 @@ private void button_load_Click(object sender, EventArgs e) void StopFillAmerced(bool bForce) { + _cancelFillAmerced?.Cancel(); + _cancelFillAmerced = null; +#if REMOVED // 如果以前在做,立即停止 m_bStopFillAmerced = true; @@ -880,13 +857,39 @@ void StopFillAmerced(bool bForce) this.threadFillAmerced = null; } } +#endif } + Task _taskFillAmerced = null; + CancellationTokenSource _cancelFillAmerced = new CancellationTokenSource(); + + // 开始填充已交费信息 // 如果有ids,则表示追加它们。否则为重新装载strReaderBaroode指明的读者的已交费记录 void BeginFillAmerced(string strReaderBarcode, List ids) { + _cancelFillAmerced?.Cancel(); + _cancelFillAmerced = new CancellationTokenSource(); + + var param = new FillAmercedParam(); + param.ReaderBarcode = strReaderBarcode; + param.IDs = ids; + param.FillSummary = this.TryGet(() => + { + return this.checkBox_fillSummary.Checked; + }); + + _taskFillAmerced = Task.Factory.StartNew(() => + { + ThreadFillAmercedMain(param, + _cancelFillAmerced.Token); + }, +this.CancelToken, +TaskCreationOptions.LongRunning, +TaskScheduler.Default); + +#if REMOVED // 如果以前在做,立即停止 StopFillAmerced(true); @@ -898,19 +901,15 @@ void BeginFillAmerced(string strReaderBarcode, this.threadFillAmerced = new Thread(new ThreadStart(this.ThreadFillAmercedMain)); this.threadFillAmerced.Start(); +#endif } - void ThreadFillAmercedMain() + void ThreadFillAmercedMain(FillAmercedParam param, + CancellationToken token) { string strError = ""; - m_bStopFillAmerced = false; + // m_bStopFillAmerced = false; - /* - LibraryChannel channel = new LibraryChannel(); - channel.Url = Program.MainForm.LibraryServerUrl; - channel.BeforeLogin += new BeforeLoginEventHandle(Channel_BeforeLogin); - channel.AfterLogin += new AfterLoginEventHandle(Channel_AfterLogin); - */ var looping = Looping(out LibraryChannel channel, "正在获取已交费信息 ..."); try @@ -930,7 +929,7 @@ void ThreadFillAmercedMain() if (lRet == -1) goto ERROR1; - if (m_bStopFillAmerced == true) + if (token.IsCancellationRequested == true) return; // 2010/12/16 change @@ -941,7 +940,7 @@ void ThreadFillAmercedMain() goto ERROR1; } - if (string.IsNullOrEmpty(this.FillAmercedParam.ReaderBarcode) == false) + if (string.IsNullOrEmpty(param.ReaderBarcode) == false) { ClearList(this.listView_amerced); @@ -950,14 +949,14 @@ void ThreadFillAmercedMain() // 2007/4/5 改造 加上了 GetXmlStringSimple() strQueryXml = "" - + StringUtil.GetXmlStringSimple(this.FillAmercedParam.ReaderBarcode) + + StringUtil.GetXmlStringSimple(param.ReaderBarcode) + "" + strMatchStyle + "=string-1" + strLang + ""; strResultSetName = "amercing"; } // end of strReaderBarcode != "" else { - if (this.FillAmercedParam.IDs == null || this.FillAmercedParam.IDs.Count == 0) + if (param.IDs == null || param.IDs.Count == 0) { strError = "IDs 参数不能为空"; goto ERROR1; @@ -967,9 +966,9 @@ void ThreadFillAmercedMain() string strMatchStyle = "exact"; strQueryXml = ""; - for (int i = 0; i < this.FillAmercedParam.IDs.Count; i++) + for (int i = 0; i < param.IDs.Count; i++) { - string strID = this.FillAmercedParam.IDs[i]; + string strID = param.IDs[i]; if (i > 0) strQueryXml += ""; @@ -998,7 +997,7 @@ void ThreadFillAmercedMain() if (lRet == -1) goto ERROR1; - if (m_bStopFillAmerced == true) + if (token.IsCancellationRequested == true) return; long lHitCount = lRet; @@ -1014,7 +1013,7 @@ void ThreadFillAmercedMain() int i = 0; foreach (Record record in loader) { - if (m_bStopFillAmerced == true + if (token.IsCancellationRequested == true || looping.Stopped) { strError = "中断,列表不完整..."; @@ -1025,23 +1024,6 @@ void ThreadFillAmercedMain() looping.Progress.SetMessage($"正在装载已交费事项 {strPath} ..."); - /* - lRet = channel.GetRecord(looping.stop, - strPath, - out byte[] timestamp, - out string strXml, - out strError); - if (lRet == -1) - { - if (channel.ErrorCode == ErrorCode.AccessDenied) - { - // 2018/11/6 - SetError(listView_amerced, "获取记录 '" + strPath + "' 时权限不够: " + strError); - continue; - } - goto ERROR1; - } - */ if (record.RecordBody != null && record.RecordBody.Result != null && record.RecordBody.Result.ErrorCode != ErrorCodeValue.NoError) { @@ -1068,86 +1050,9 @@ void ThreadFillAmercedMain() looping.Progress.SetProgressValue(i); } } -#if REMOVED - long lStart = 0; - long lPerCount = Math.Min(50, lHitCount); - Record[] searchresults = null; - - // 获得结果集,装入listview - for (; ; ) - { - if (m_bStopFillAmerced == true) - { - strError = "中断,列表不完整..."; - goto ERROR1; - } - // stop.SetMessage("正在装入浏览信息 " + (lStart + 1).ToString() + " - " + (lStart + lPerCount).ToString() + " (命中 " + lHitCount.ToString() + " 条记录) ..."); - - lRet = channel.GetSearchResult( - looping.stop, - strResultSetName, // strResultSetName - lStart, - lPerCount, - "id", // "id,cols" - strLang, - out searchresults, - out strError); - if (lRet == -1) - goto ERROR1; - - if (lRet == 0) - { - strError = "未命中"; - return; - } - - // 处理浏览结果 - for (int i = 0; i < searchresults.Length; i++) - { - if (m_bStopFillAmerced == true) - { - strError = "中断,列表不完整..."; - goto ERROR1; - } - - string strPath = searchresults[i].Path; - - byte[] timestamp = null; - string strXml = ""; - - lRet = channel.GetRecord(looping.stop, - strPath, - out timestamp, - out strXml, - out strError); - if (lRet == -1) - { - if (channel.ErrorCode == ErrorCode.AccessDenied) - { - // 2018/11/6 - SetError(listView_amerced, "获取记录 '" + strPath + "' 时权限不够: " + strError); - continue; - } - goto ERROR1; - } - - int nRet = Safe_fillAmercedLine( - looping.stop, - strXml, - strPath, - out strError); - if (nRet == -1) - goto ERROR1; - } - - lStart += searchresults.Length; - if (lStart >= lHitCount || lPerCount <= 0) - break; - } -#endif // 第二阶段,填充摘要 - if (this.FillAmercedParam.FillSummary == true) + if (param.FillSummary == true) { looping.Progress.SetMessage("正在装载已交费事项的书目摘要 ..."); @@ -1162,7 +1067,7 @@ void ThreadFillAmercedMain() { if (looping.Stopped) return; - if (this.m_bStopFillAmerced == true) + if (token.IsCancellationRequested == true) return; // looping.stop.SetProgressValue(i); @@ -1188,25 +1093,6 @@ void ThreadFillAmercedMain() path_list.Add($"@itemBarcode:{strItemBarcode}"); item_list.Add(item); - /* - looping.stop.SetMessage($"正在装载已交费事项 {strItemBarcode} 的书目摘要 ..."); - - lRet = channel.GetBiblioSummary( - looping.stop, - strItemBarcode, - "", // strItemRecPath, - null, - out string strBiblioRecPath, - out strSummary, - out strError); - if (lRet == -1) - { - strSummary = strError; // 2009/3/13 changed - // return -1; - } - - ChangeItemText(item, COLUMN_AMERCING_BIBLIOSUMMARY, strSummary); - */ } { @@ -1241,41 +1127,11 @@ void ThreadFillAmercedMain() finally { looping.Dispose(); - /* - channel.BeforeLogin -= new BeforeLoginEventHandle(Channel_BeforeLogin); - channel.AfterLogin -= new AfterLoginEventHandle(Channel_AfterLogin); - channel.Close(); - */ - m_bStopFillAmerced = true; } ERROR1: SetError(this.listView_amerced, strError); - // Safe_errorBox(strError); - } - -#if REMOVED - // FillAmercedLine - delegate int Delegate_FillAmercedLine(Stop stop, - string strXml, - string strRecPath, - out string strError); - - - int Safe_fillAmercedLine(Stop stop, - string strXml, - string strRecPath, - out string strError) - { - //string strItemBarcodeParam = ""; - //string strSummaryParam = ""; - Delegate_FillAmercedLine d = new Delegate_FillAmercedLine(FillAmercedLine); - object[] args = new object[] { stop, strXml, strRecPath, "" }; - int nRet = (int)this.Invoke(d, args); - strError = (string)args[3]; - return nRet; } -#endif #endregion @@ -1283,6 +1139,9 @@ int Safe_fillAmercedLine(Stop stop, void StopFillAmercing(bool bForce) { + _cancelFillAmercing?.Cancel(); + _cancelFillAmercing = null; +#if REMOVED // 如果以前在做,立即停止 m_bStopFillAmercing = true; @@ -1295,25 +1154,47 @@ void StopFillAmercing(bool bForce) this.threadFillAmercing = null; } } +#endif } + Task _taskFillAmercing = null; + CancellationTokenSource _cancelFillAmercing = new CancellationTokenSource(); + void BeginFillAmercing(string strXml) { + _cancelFillAmercing?.Cancel(); + _cancelFillAmercing = new CancellationTokenSource(); + + var param = new FillAmercingParam(); + param.Xml = strXml; + param.FillSummary = this.TryGet(() => + { + return this.checkBox_fillSummary.Checked; + }); + + _taskFillAmercing = Task.Factory.StartNew(() => + { + ThreadFillAmercingMain(param, + _cancelFillAmercing.Token); + }, +this.CancelToken, +TaskCreationOptions.LongRunning, +TaskScheduler.Default); + +#if REMOVED // 如果以前在做,立即停止 StopFillAmercing(true); - FillAmercingParam = new FillAmercingParam(); + this.FillAmercingParam = new FillAmercingParam(); this.FillAmercingParam.Xml = strXml; this.FillAmercingParam.FillSummary = this.checkBox_fillSummary.Checked; this.threadFillAmercing = new Thread(new ThreadStart(this.ThreadFillAmercingMain)); this.threadFillAmercing.Start(); +#endif } - // ClearList - // delegate void Delegate_ClearList(ListView list); - void ClearList(ListView list) { this.Invoke((Action)(() => @@ -1322,38 +1203,6 @@ void ClearList(ListView list) })); } -#if NO - void Safe_clearList(ListView list) - { - Delegate_ClearList d = new Delegate_ClearList(ClearList); - this.Invoke(d, new object[] { list }); - } -#endif - - // ErrorBox - // delegate void Delegate_ErrorBox(string strText); - -#if REMOVED - void ErrorBox(string strText) - { - this.Invoke((Action)(() => - { - MessageBox.Show(this, strText); - })); - } -#endif - -#if NO - void Safe_errorBox(string strText) - { - Delegate_ErrorBox d = new Delegate_ErrorBox(ErrorBox); - this.Invoke(d, new object[] { strText }); - } -#endif - - // AddListItem - // delegate void Delegate_AddListItem(ListView list, ListViewItem item); - void AddListItem(ListView list, ListViewItem item) { this.Invoke((Action)(() => @@ -1362,14 +1211,6 @@ void AddListItem(ListView list, ListViewItem item) })); } -#if NO - void Safe_addListItem(ListView list, ListViewItem item) - { - Delegate_AddListItem d = new Delegate_AddListItem(AddListItem); - this.Invoke(d, new object[] { list, item }); - } -#endif - void GetBarcodeAndSummary(ListView list, ListViewItem item, out string strItemBarcode, @@ -1387,81 +1228,6 @@ void GetBarcodeAndSummary(ListView list, } } -#if REMOVED - // GetBarcodeAndSummary - delegate void Delegate_GetBarcodeAndSummary(ListView list, - ListViewItem item, - out string strItemBarcode, - out string strSummary); - - void Safe_getBarcodeAndSummary(ListView list, - ListViewItem item, - out string strItemBarcode, - out string strSummary) - { - //string strItemBarcodeParam = ""; - //string strSummaryParam = ""; - Delegate_GetBarcodeAndSummary d = new Delegate_GetBarcodeAndSummary(GetBarcodeAndSummary); - object[] args = new object[] { list, item, "", "" }; - this.Invoke(d, args); - strItemBarcode = (string)args[2]; - strSummary = (string)args[3]; - } -#endif - - // ChangeItemText - // delegate void Delegate_ChangeItemText(ListViewItem item, int nCol, string strText); - -#if REMOVED - void ChangeItemText(ListViewItem item, int nCol, string strText) - { - this.Invoke((Action)(() => - { - ListViewUtil.ChangeItemText(item, nCol, strText); - })); - } -#endif - -#if NO - void Safe_changeItemText(ListViewItem item, int nCol, string strText) - { - Delegate_ChangeItemText d = new Delegate_ChangeItemText(ChangeItemText); - this.Invoke(d, new object[] { item, nCol, strText }); - } -#endif - - // GetItemList - // delegate List Delegate_GetItemList(ListView list); - -#if REMOVED - List GetItemList(ListView list) - { - return (List)this.Invoke((Func>)(() => - { - List results = new List(); - foreach (ListViewItem item in list.Items) - { - results.Add(item); - } - return results; - })); - } -#endif - -#if NO - List Safe_getItemList(ListView list) - { - Delegate_GetItemList d = new Delegate_GetItemList(GetItemList); - return (List)this.Invoke(d, new object[] { list }); - } -#endif - -#if NO - // SetError - delegate void Delegate_SetError(ListView list, - string strError); -#endif - // 设置错误字符串显示 static void SetError(ListView list, string strError) @@ -1477,27 +1243,14 @@ static void SetError(ListView list, })); } -#if NO - void Safe_setError(ListView list, - string strError) - { - Delegate_SetError d = new Delegate_SetError(SetError); - this.Invoke(d, new object[] { list, strError }); - } -#endif - /*public*/ - void ThreadFillAmercingMain() + void ThreadFillAmercingMain( + FillAmercingParam param, + CancellationToken token) { string strError = ""; - m_bStopFillAmercing = false; - - /* - LibraryChannel channel = new LibraryChannel(); - channel.Url = Program.MainForm.LibraryServerUrl; + //m_bStopFillAmercing = false; - channel.BeforeLogin += new BeforeLoginEventHandle(Channel_BeforeLogin); - */ var looping = Looping(out LibraryChannel channel, "正在获取待交费信息 ..."); try @@ -1507,7 +1260,7 @@ void ThreadFillAmercingMain() XmlDocument dom = new XmlDocument(); try { - dom.LoadXml(this.FillAmercingParam.Xml); + dom.LoadXml(param.Xml); } catch (Exception ex) { @@ -1522,7 +1275,7 @@ void ThreadFillAmercingMain() for (int i = 0; i < nodes.Count; i++) { - if (this.m_bStopFillAmercing == true) + if (token.IsCancellationRequested == true) { strError = "中断,列表不完整..."; goto ERROR1; @@ -1618,13 +1371,13 @@ void ThreadFillAmercingMain() */ // 第二阶段,填充摘要 - if (this.FillAmercingParam.FillSummary == true) + if (param.FillSummary == true) { List items = ListViewUtil.GetItems(listView_overdues); for (int i = 0; i < items.Count; i++) { - if (this.m_bStopFillAmercing == true) + if (token.IsCancellationRequested == true) return; ListViewItem item = items[i]; @@ -1657,7 +1410,6 @@ void ThreadFillAmercingMain() strSummary = strError; // 2009/3/13 changed // return -1; } - } finally { @@ -1685,16 +1437,10 @@ void ThreadFillAmercingMain() finally { looping.Dispose(); - /* - channel.BeforeLogin -= new BeforeLoginEventHandle(Channel_BeforeLogin); - channel.Close(); - */ - m_bStopFillAmercing = true; } ERROR1: SetError(this.listView_overdues, strError); this.ShowMessage(strError, "red", true); // 2019/9/19 - // Safe_errorBox(strError); } #endregion @@ -2172,7 +1918,6 @@ int GetChangedInfo( strInfo += ",并且注释要追加内容 '" + strAppendComment + "'"; } * */ - } // 第二个条件 diff --git a/dp2Circulation/Reader/AmerceForm.resx b/dp2Circulation/Reader/AmerceForm.resx index 4b1b36c08..1e4fecbea 100644 --- a/dp2Circulation/Reader/AmerceForm.resx +++ b/dp2Circulation/Reader/AmerceForm.resx @@ -125,7 +125,7 @@ AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0 ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAABK - CQAAAk1TRnQBSQFMAgEBBAEAAQwBAAEEAQABEAEAARABAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo + CQAAAk1TRnQBSQFMAgEBBAEAAQwBAAEMAQABEAEAARABAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo AwABQAMAASADAAEBAQABCAYAAQgYAAGAAgABgAMAAoABAAGAAwABgAEAAYABAAKAAgADwAEAAcAB3AHA AQAB8AHKAaYBAAEzBQABMwEAATMBAAEzAQACMwIAAxYBAAMcAQADIgEAAykBAANVAQADTQEAA0IBAAM5 AQABgAF8Af8BAAJQAf8BAAGTAQAB1gEAAf8B7AHMAQABxgHWAe8BAAHWAucBAAGQAakBrQIAAf8BMwMA @@ -174,31 +174,31 @@ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 - YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAgxJREFUOE+lkvtL - U2EYx+0PEbtpFwnBKPGKiJImGP0gYhIYs1E5GF5gIxkpA00JRSmMEF0ohMh+GaRWYlqabMVcNdS2QpaI - VqiDIYhk397vA6fXhCjyhYdzeM/5fp7vczkAdeL2cwho7v/wWzT1zcN+Pwhr51uY2/y41PQaF+wzKKiZ - QvaN58g0jyLd5KEUcQbg+84P/Cm2tncQjW3j68YWIqubCC3FcOJc478BAuGoZM6zvoRnakXEruEIjhc4 - /g5gZop9c+voGAyLbQIfeBZxLL9BA1jzXvuGbWamuKh+GmmVbswE19A59FEBbmoAG7YbsLtm2mZmiml9 - cvabNDwpz6YB7LYBoMXCumkJr7LOmnnHzBQ/9X2Bo2cOibm1GsBREbAQiYmw/8lnuCeWkVzcgnZlnw1j - 3HV/wuNXK6i/9x5Hc6wawDlTXHbLJ+LZUBQPRyKwdQdxutwl1h+NLXHh5Ht1ewBHsiwawCW57HyDAfWR - dvl0uhZQ1eqX8aVc7EKLqrum651ATLf9OJx5XQM4KmY0xPzZ0hFAiQJnXB0WwME0E3IsL5B17ZlADqWb - NYDrOepdlcysmTWWOrxqbceRWtaLk0VO1XW72D5Vckd2gMBfq8zdpmUG62NJvKM4+XyziDk24xmfWoGE - s1c0gHPmbrPTpHNJKOCo2G1mZs20zcwUJ5yp1AB5+8/zEwgF5GMVDxh4AAAAAElFTkSuQmCC + YQUAAAAJcEhZcwAAGdYAABnWARjRyu0AAAIDSURBVDhPpZLrS5NhGMb3j4SWh0oRQVExD4gonkDpg4hG + YKxG6WBogkMZKgPNCEVJFBGdGETEvgwyO9DJE5syZw3PIlPEE9pgBCLZ5XvdMB8Ew8gXbl54nuf63dd9 + 0OGSnwCahxbPRNPAPMw9Xpg6ZmF46kZZ0xSKzJPIrhpDWsVnpBhGkKx3nAX8Pv7z1zg8OoY/cITdn4fw + bf/C0kYAN3Ma/w3gWfZL5kzTKBxjWyK2DftwI9tyMYCZKXbNHaD91bLYJrDXsYbrWfUKwJrPE9M2M1Oc + VzOOpHI7Jr376Hi9ogHqFIANO0/MmmmbmSmm9a8ze+I4MrNWAdjtoJgWcx+PSzg166yZZ8xM8XvXDix9 + c4jIqFYAjoriBV9AhEPv1mH/sonogha0afbZMMZz+yreTGyhpusHwtNNCsA5U1zS4BLxzJIfg299qO32 + Ir7UJtZfftyATqeT+8o2D8JSjQrAJblrncYL7ZJ2+bfaFnC/1S1NjL3diRat7qrO7wLRP3HjWsojBeCo + mDEo5mNjuweFGvjWg2EBhCbpkW78htSHHwRyNdmgAFzPEee2iFkzayy2OLXzT4gr6UdUnlXrullsxxQ+ + kx0g8BTA3aZlButjSTyjODq/WcQcW/B/Je4OQhLvKQDnzN1mp0nnkvAhR8VuMzNrpm1mpjgkoVwB/v8D + TgDQASA1MVpwzwAAAABJRU5ErkJggg== iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 - YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAgxJREFUOE+lkvtL - U2EYx+0PEbtpFwnBKPGKiJImGP0gYhIYs1E5GF5gIxkpA00JRSmMEF0ohMh+GaRWYlqabMVcNdS2QpaI - VqiDIYhk397vA6fXhCjyhYdzeM/5fp7vczkAdeL2cwho7v/wWzT1zcN+Pwhr51uY2/y41PQaF+wzKKiZ - QvaN58g0jyLd5KEUcQbg+84P/Cm2tncQjW3j68YWIqubCC3FcOJc478BAuGoZM6zvoRnakXEruEIjhc4 - /g5gZop9c+voGAyLbQIfeBZxLL9BA1jzXvuGbWamuKh+GmmVbswE19A59FEBbmoAG7YbsLtm2mZmiml9 - cvabNDwpz6YB7LYBoMXCumkJr7LOmnnHzBQ/9X2Bo2cOibm1GsBREbAQiYmw/8lnuCeWkVzcgnZlnw1j - 3HV/wuNXK6i/9x5Hc6wawDlTXHbLJ+LZUBQPRyKwdQdxutwl1h+NLXHh5Ht1ewBHsiwawCW57HyDAfWR - dvl0uhZQ1eqX8aVc7EKLqrum651ATLf9OJx5XQM4KmY0xPzZ0hFAiQJnXB0WwME0E3IsL5B17ZlADqWb - NYDrOepdlcysmTWWOrxqbceRWtaLk0VO1XW72D5Vckd2gMBfq8zdpmUG62NJvKM4+XyziDk24xmfWoGE - s1c0gHPmbrPTpHNJKOCo2G1mZs20zcwUJ5yp1AB5+8/zEwgF5GMVDxh4AAAAAElFTkSuQmCC + YQUAAAAJcEhZcwAAGdYAABnWARjRyu0AAAIDSURBVDhPpZLrS5NhGMb3j4SWh0oRQVExD4gonkDpg4hG + YKxG6WBogkMZKgPNCEVJFBGdGETEvgwyO9DJE5syZw3PIlPEE9pgBCLZ5XvdMB8Ew8gXbl54nuf63dd9 + 0OGSnwCahxbPRNPAPMw9Xpg6ZmF46kZZ0xSKzJPIrhpDWsVnpBhGkKx3nAX8Pv7z1zg8OoY/cITdn4fw + bf/C0kYAN3Ma/w3gWfZL5kzTKBxjWyK2DftwI9tyMYCZKXbNHaD91bLYJrDXsYbrWfUKwJrPE9M2M1Oc + VzOOpHI7Jr376Hi9ogHqFIANO0/MmmmbmSmm9a8ze+I4MrNWAdjtoJgWcx+PSzg166yZZ8xM8XvXDix9 + c4jIqFYAjoriBV9AhEPv1mH/sonogha0afbZMMZz+yreTGyhpusHwtNNCsA5U1zS4BLxzJIfg299qO32 + Ir7UJtZfftyATqeT+8o2D8JSjQrAJblrncYL7ZJ2+bfaFnC/1S1NjL3diRat7qrO7wLRP3HjWsojBeCo + mDEo5mNjuweFGvjWg2EBhCbpkW78htSHHwRyNdmgAFzPEee2iFkzayy2OLXzT4gr6UdUnlXrullsxxQ+ + kx0g8BTA3aZlButjSTyjODq/WcQcW/B/Je4OQhLvKQDnzN1mp0nnkvAhR8VuMzNrpm1mpjgkoVwB/v8D + TgDQASA1MVpwzwAAAABJRU5ErkJggg== @@ -207,46 +207,46 @@ iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 - YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAgxJREFUOE+lkvtL - U2EYx+0PEbtpFwnBKPGKiJImGP0gYhIYs1E5GF5gIxkpA00JRSmMEF0ohMh+GaRWYlqabMVcNdS2QpaI - VqiDIYhk397vA6fXhCjyhYdzeM/5fp7vczkAdeL2cwho7v/wWzT1zcN+Pwhr51uY2/y41PQaF+wzKKiZ - QvaN58g0jyLd5KEUcQbg+84P/Cm2tncQjW3j68YWIqubCC3FcOJc478BAuGoZM6zvoRnakXEruEIjhc4 - /g5gZop9c+voGAyLbQIfeBZxLL9BA1jzXvuGbWamuKh+GmmVbswE19A59FEBbmoAG7YbsLtm2mZmiml9 - cvabNDwpz6YB7LYBoMXCumkJr7LOmnnHzBQ/9X2Bo2cOibm1GsBREbAQiYmw/8lnuCeWkVzcgnZlnw1j - 3HV/wuNXK6i/9x5Hc6wawDlTXHbLJ+LZUBQPRyKwdQdxutwl1h+NLXHh5Ht1ewBHsiwawCW57HyDAfWR - dvl0uhZQ1eqX8aVc7EKLqrum651ATLf9OJx5XQM4KmY0xPzZ0hFAiQJnXB0WwME0E3IsL5B17ZlADqWb - NYDrOepdlcysmTWWOrxqbceRWtaLk0VO1XW72D5Vckd2gMBfq8zdpmUG62NJvKM4+XyziDk24xmfWoGE - s1c0gHPmbrPTpHNJKOCo2G1mZs20zcwUJ5yp1AB5+8/zEwgF5GMVDxh4AAAAAElFTkSuQmCC + YQUAAAAJcEhZcwAAGdYAABnWARjRyu0AAAIDSURBVDhPpZLrS5NhGMb3j4SWh0oRQVExD4gonkDpg4hG + YKxG6WBogkMZKgPNCEVJFBGdGETEvgwyO9DJE5syZw3PIlPEE9pgBCLZ5XvdMB8Ew8gXbl54nuf63dd9 + 0OGSnwCahxbPRNPAPMw9Xpg6ZmF46kZZ0xSKzJPIrhpDWsVnpBhGkKx3nAX8Pv7z1zg8OoY/cITdn4fw + bf/C0kYAN3Ma/w3gWfZL5kzTKBxjWyK2DftwI9tyMYCZKXbNHaD91bLYJrDXsYbrWfUKwJrPE9M2M1Oc + VzOOpHI7Jr376Hi9ogHqFIANO0/MmmmbmSmm9a8ze+I4MrNWAdjtoJgWcx+PSzg166yZZ8xM8XvXDix9 + c4jIqFYAjoriBV9AhEPv1mH/sonogha0afbZMMZz+yreTGyhpusHwtNNCsA5U1zS4BLxzJIfg299qO32 + Ir7UJtZfftyATqeT+8o2D8JSjQrAJblrncYL7ZJ2+bfaFnC/1S1NjL3diRat7qrO7wLRP3HjWsojBeCo + mDEo5mNjuweFGvjWg2EBhCbpkW78htSHHwRyNdmgAFzPEee2iFkzayy2OLXzT4gr6UdUnlXrullsxxQ+ + kx0g8BTA3aZlButjSTyjODq/WcQcW/B/Je4OQhLvKQDnzN1mp0nnkvAhR8VuMzNrpm1mpjgkoVwB/v8D + TgDQASA1MVpwzwAAAABJRU5ErkJggg== iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 - YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAgxJREFUOE+lkvtL - U2EYx+0PEbtpFwnBKPGKiJImGP0gYhIYs1E5GF5gIxkpA00JRSmMEF0ohMh+GaRWYlqabMVcNdS2QpaI - VqiDIYhk397vA6fXhCjyhYdzeM/5fp7vczkAdeL2cwho7v/wWzT1zcN+Pwhr51uY2/y41PQaF+wzKKiZ - QvaN58g0jyLd5KEUcQbg+84P/Cm2tncQjW3j68YWIqubCC3FcOJc478BAuGoZM6zvoRnakXEruEIjhc4 - /g5gZop9c+voGAyLbQIfeBZxLL9BA1jzXvuGbWamuKh+GmmVbswE19A59FEBbmoAG7YbsLtm2mZmiml9 - cvabNDwpz6YB7LYBoMXCumkJr7LOmnnHzBQ/9X2Bo2cOibm1GsBREbAQiYmw/8lnuCeWkVzcgnZlnw1j - 3HV/wuNXK6i/9x5Hc6wawDlTXHbLJ+LZUBQPRyKwdQdxutwl1h+NLXHh5Ht1ewBHsiwawCW57HyDAfWR - dvl0uhZQ1eqX8aVc7EKLqrum651ATLf9OJx5XQM4KmY0xPzZ0hFAiQJnXB0WwME0E3IsL5B17ZlADqWb - NYDrOepdlcysmTWWOrxqbceRWtaLk0VO1XW72D5Vckd2gMBfq8zdpmUG62NJvKM4+XyziDk24xmfWoGE - s1c0gHPmbrPTpHNJKOCo2G1mZs20zcwUJ5yp1AB5+8/zEwgF5GMVDxh4AAAAAElFTkSuQmCC + YQUAAAAJcEhZcwAAGdYAABnWARjRyu0AAAIDSURBVDhPpZLrS5NhGMb3j4SWh0oRQVExD4gonkDpg4hG + YKxG6WBogkMZKgPNCEVJFBGdGETEvgwyO9DJE5syZw3PIlPEE9pgBCLZ5XvdMB8Ew8gXbl54nuf63dd9 + 0OGSnwCahxbPRNPAPMw9Xpg6ZmF46kZZ0xSKzJPIrhpDWsVnpBhGkKx3nAX8Pv7z1zg8OoY/cITdn4fw + bf/C0kYAN3Ma/w3gWfZL5kzTKBxjWyK2DftwI9tyMYCZKXbNHaD91bLYJrDXsYbrWfUKwJrPE9M2M1Oc + VzOOpHI7Jr376Hi9ogHqFIANO0/MmmmbmSmm9a8ze+I4MrNWAdjtoJgWcx+PSzg166yZZ8xM8XvXDix9 + c4jIqFYAjoriBV9AhEPv1mH/sonogha0afbZMMZz+yreTGyhpusHwtNNCsA5U1zS4BLxzJIfg299qO32 + Ir7UJtZfftyATqeT+8o2D8JSjQrAJblrncYL7ZJ2+bfaFnC/1S1NjL3diRat7qrO7wLRP3HjWsojBeCo + mDEo5mNjuweFGvjWg2EBhCbpkW78htSHHwRyNdmgAFzPEee2iFkzayy2OLXzT4gr6UdUnlXrullsxxQ+ + kx0g8BTA3aZlButjSTyjODq/WcQcW/B/Je4OQhLvKQDnzN1mp0nnkvAhR8VuMzNrpm1mpjgkoVwB/v8D + TgDQASA1MVpwzwAAAABJRU5ErkJggg== iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 - YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAgxJREFUOE+lkvtL - U2EYx+0PEbtpFwnBKPGKiJImGP0gYhIYs1E5GF5gIxkpA00JRSmMEF0ohMh+GaRWYlqabMVcNdS2QpaI - VqiDIYhk397vA6fXhCjyhYdzeM/5fp7vczkAdeL2cwho7v/wWzT1zcN+Pwhr51uY2/y41PQaF+wzKKiZ - QvaN58g0jyLd5KEUcQbg+84P/Cm2tncQjW3j68YWIqubCC3FcOJc478BAuGoZM6zvoRnakXEruEIjhc4 - /g5gZop9c+voGAyLbQIfeBZxLL9BA1jzXvuGbWamuKh+GmmVbswE19A59FEBbmoAG7YbsLtm2mZmiml9 - cvabNDwpz6YB7LYBoMXCumkJr7LOmnnHzBQ/9X2Bo2cOibm1GsBREbAQiYmw/8lnuCeWkVzcgnZlnw1j - 3HV/wuNXK6i/9x5Hc6wawDlTXHbLJ+LZUBQPRyKwdQdxutwl1h+NLXHh5Ht1ewBHsiwawCW57HyDAfWR - dvl0uhZQ1eqX8aVc7EKLqrum651ATLf9OJx5XQM4KmY0xPzZ0hFAiQJnXB0WwME0E3IsL5B17ZlADqWb - NYDrOepdlcysmTWWOrxqbceRWtaLk0VO1XW72D5Vckd2gMBfq8zdpmUG62NJvKM4+XyziDk24xmfWoGE - s1c0gHPmbrPTpHNJKOCo2G1mZs20zcwUJ5yp1AB5+8/zEwgF5GMVDxh4AAAAAElFTkSuQmCC + YQUAAAAJcEhZcwAAGdYAABnWARjRyu0AAAIDSURBVDhPpZLrS5NhGMb3j4SWh0oRQVExD4gonkDpg4hG + YKxG6WBogkMZKgPNCEVJFBGdGETEvgwyO9DJE5syZw3PIlPEE9pgBCLZ5XvdMB8Ew8gXbl54nuf63dd9 + 0OGSnwCahxbPRNPAPMw9Xpg6ZmF46kZZ0xSKzJPIrhpDWsVnpBhGkKx3nAX8Pv7z1zg8OoY/cITdn4fw + bf/C0kYAN3Ma/w3gWfZL5kzTKBxjWyK2DftwI9tyMYCZKXbNHaD91bLYJrDXsYbrWfUKwJrPE9M2M1Oc + VzOOpHI7Jr376Hi9ogHqFIANO0/MmmmbmSmm9a8ze+I4MrNWAdjtoJgWcx+PSzg166yZZ8xM8XvXDix9 + c4jIqFYAjoriBV9AhEPv1mH/sonogha0afbZMMZz+yreTGyhpusHwtNNCsA5U1zS4BLxzJIfg299qO32 + Ir7UJtZfftyATqeT+8o2D8JSjQrAJblrncYL7ZJ2+bfaFnC/1S1NjL3diRat7qrO7wLRP3HjWsojBeCo + mDEo5mNjuweFGvjWg2EBhCbpkW78htSHHwRyNdmgAFzPEee2iFkzayy2OLXzT4gr6UdUnlXrullsxxQ+ + kx0g8BTA3aZlButjSTyjODq/WcQcW/B/Je4OQhLvKQDnzN1mp0nnkvAhR8VuMzNrpm1mpjgkoVwB/v8D + TgDQASA1MVpwzwAAAABJRU5ErkJggg== diff --git a/dp2Circulation/dp2Circulation.csproj b/dp2Circulation/dp2Circulation.csproj index 5f1062cd4..cb5d1f188 100644 --- a/dp2Circulation/dp2Circulation.csproj +++ b/dp2Circulation/dp2Circulation.csproj @@ -36,7 +36,7 @@ true - c:\publish\dp2circulation\v3_dev\ + c:\publish\dp2circulation\v3\ true Web true @@ -46,14 +46,14 @@ false false true - http://dp2003.com/dp2Circulation/v3_dev/ + http://dp2003.com/dp2Circulation/v3/ zh-CN dp2内务 V3 DigitalPlatform dp2 V3 true publish.htm - 520 + 523 3.78.0.%2a false true diff --git a/dp2SSL/App.xaml.cs b/dp2SSL/App.xaml.cs index 4ffc33934..65f8be1b8 100644 --- a/dp2SSL/App.xaml.cs +++ b/dp2SSL/App.xaml.cs @@ -220,7 +220,7 @@ protected async override void OnStartup(StartupEventArgs e) && e1 != null && e1.Level == "error") { - PageShelf.TrySetMessage(null, "*** ERROR *** " + e1.Message); + ShelfData.TrySetMessage(null, "*** ERROR *** " + e1.Message); } } catch (Exception ex) @@ -347,7 +347,8 @@ await Task.Run(() => _barcodeCapture.StopKeys = new List { System.Windows.Forms.Keys.Alt | System.Windows.Forms.Keys.Tab, System.Windows.Forms.Keys.LWin, - System.Windows.Forms.Keys.RWin + System.Windows.Forms.Keys.RWin, + System.Windows.Forms.Keys.Alt | System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Delete, }; _barcodeCapture.InputLine += _barcodeCapture_inputLine; //_barcodeCapture.InputChar += _barcodeCapture_InputChar; @@ -380,7 +381,7 @@ await TinyServer.InitialMessageQueueAsync( await TinyServer.DeleteAllResultsetAsync(); TinyServer.StartSendTask(_cancelRefresh.Token); - PageShelf.TrySetMessage(null, "我这台智能书柜启动了!"); + ShelfData.TrySetMessage(null, "我这台智能书柜启动了!"); ShelfData.StartMonitorTask(); } @@ -655,7 +656,7 @@ await TinyServer.InitialMessageQueueAsync( TinyServer.StartSendTask(_cancelSendingMessage.Token); // _cancelApp.Token if (string.IsNullOrEmpty(message) == false) - PageShelf.TrySetMessage(null, message); // "我这台智能书柜启动了!" + ShelfData.TrySetMessage(null, message); // "我这台智能书柜启动了!" } else { @@ -1141,7 +1142,7 @@ protected override void OnSessionEnding(SessionEndingCancelEventArgs e) WpfClientInfo.Finish(GrantAccess); WpfClientInfo.WriteDebugLog("End WpfClientInfo.Finish()"); - PageShelf.TrySetMessage(null, $"我这台智能书柜停止了哟!({e.ReasonSessionEnding})"); + ShelfData.TrySetMessage(null, $"我这台智能书柜停止了哟!({e.ReasonSessionEnding})"); try { @@ -1221,7 +1222,7 @@ protected async override void OnExit(ExitEventArgs e) catch { // 如果直接发送不成功,则送入 MessageQueue 中 - PageShelf.TrySetMessage(null, $"我这台智能书柜退出了哟!"); + ShelfData.TrySetMessage(null, $"我这台智能书柜退出了哟!"); } try @@ -1566,6 +1567,7 @@ public static bool AutoTrigger } } +#if REMOVED // 身份读卡器是否竖向放置 public static bool PatronReaderVertical { @@ -1575,6 +1577,16 @@ public static bool PatronReaderVertical "patron_info_lasting", false); } } +#endif + // 竖向放置的身份读卡器名 + public static string VerticalReaderName + { + get + { + return WpfClientInfo.Config?.Get("ssl_operation", + "vertial_reader_name", null); + } + } // 自动返回菜单页面 public static bool AutoBackMenuPage @@ -2770,7 +2782,7 @@ public static void SendDialogText(Window window, string title) else text = App.FindTextChildren(window); })); - PageShelf.TrySetMessage(null, $"==== {title} 对话框显示并等待输入 ====\r\n{text}"); + ShelfData.TrySetMessage(null, $"==== {title} 对话框显示并等待输入 ====\r\n{text}"); } public static NormalResult PressButton(string button_name) diff --git a/dp2SSL/Config/ConfigParams.cs b/dp2SSL/Config/ConfigParams.cs index 2e5cf737a..ff5f618eb 100644 --- a/dp2SSL/Config/ConfigParams.cs +++ b/dp2SSL/Config/ConfigParams.cs @@ -79,7 +79,8 @@ public void LoadData() FullScreen = _config.GetInt("global", "fullScreen", 1) == 1 ? true : false; AutoTrigger = _config.GetBoolean("ssl_operation", "auto_trigger", false); - PatronInfoLasting = _config.GetBoolean("ssl_operation", "patron_info_lasting", false); + // PatronInfoLasting = _config.GetBoolean("ssl_operation", "patron_info_lasting", false); + VerticalReaderName = _config.Get("ssl_operation", "vertial_reader_name", null); AutoBackMenuPage = _config.GetBoolean("ssl_operation", "auto_back_menu_page", false); ProcessMonitor = _config.GetBoolean("global", "process_monitor", true); ReplicateEntities = _config.GetBoolean("shelf", "replicateEntities", false); @@ -141,7 +142,8 @@ public string SaveData() _config.Set("global", "faceInputMultipleHits", FaceInputMultipleHits); _config.SetInt("global", "fullScreen", FullScreen == true ? 1 : 0); _config.SetBoolean("ssl_operation", "auto_trigger", AutoTrigger); - _config.SetBoolean("ssl_operation", "patron_info_lasting", PatronInfoLasting); + // _config.SetBoolean("ssl_operation", "patron_info_lasting", PatronInfoLasting); + _config.Set("ssl_operation", "vertial_reader_name", VerticalReaderName); _config.SetBoolean("ssl_operation", "auto_back_menu_page", AutoBackMenuPage); _config.SetBoolean("global", "process_monitor", ProcessMonitor); _config.SetBoolean("shelf", "replicateEntities", ReplicateEntities); @@ -541,6 +543,7 @@ public bool AutoTrigger } private bool _autoTrigger; +#if REMOVED // 默认值 false [Display( Order = 7, @@ -561,6 +564,28 @@ public bool PatronInfoLasting } } private bool _patronInfoLasting; +#endif + // 默认值 null + [Display( +Order = 7, +Name = "竖放的身份读写器", // 拿走不敏感。读者信息显示持久 +Description = "竖放的RFID读者卡读写器名称" +)] + [ItemsSource(typeof(ReaderNameItemsSource))] + [Category("自助借还操作风格")] + public string VerticalReaderName + { + get => _verticalReaderName; + set + { + if (_verticalReaderName != value) + { + _verticalReaderName = value; + OnPropertyChanged("VerticalReaderName"); + } + } + } + private string _verticalReaderName; // 默认值 false [Display( diff --git a/dp2SSL/Config/FunctionItemsSource.cs b/dp2SSL/Config/FunctionItemsSource.cs index 25768fcb9..c2c206387 100644 --- a/dp2SSL/Config/FunctionItemsSource.cs +++ b/dp2SSL/Config/FunctionItemsSource.cs @@ -1,4 +1,5 @@ -using System; +using DigitalPlatform.RFID; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -102,4 +103,23 @@ public ItemCollection GetValues() return items; } } + + // 当前全部读写器名字列表 + public class ReaderNameItemsSource : IItemsSource + { + public ItemCollection GetValues() + { + ItemCollection items = new ItemCollection(); + var result = RfidManager.ListReaders(); + if (result.Value == -1) + return items; + items.Add(""); + foreach (var reader in result.Readers) + { + items.Add(reader); + } + + return items; + } + } } diff --git a/dp2SSL/Controls/Patron.cs b/dp2SSL/Controls/Patron.cs index bec00ac94..8677c951d 100644 --- a/dp2SSL/Controls/Patron.cs +++ b/dp2SSL/Controls/Patron.cs @@ -987,6 +987,10 @@ public FillResult Fill(OneTag tag) // 2020/6/2 this.Protocol = tag.Protocol; + // 2024/1/18 + this.ReaderName = tag.ReaderName; + this.Antenna = tag.AntennaID.ToString(); + if (tag.TagInfo == null && tag.Protocol == InventoryInfo.ISO15693) { // throw new Exception("Fill() taginfo == null"); @@ -1054,10 +1058,17 @@ public FillResult Fill(OneTag tag) return new FillResult { Value = 1 }; // 优化 string protocol_save = this.Protocol; + string readername_save = this.ReaderName; + string antenna_save = this.Antenna; this.Clear(); this.Protocol = protocol_save; + + // 2024/1/19 + this.ReaderName = readername_save; + this.Antenna = antenna_save; + this.UID = tag.UID; this.PII = pii; this.OI = oi; @@ -1096,6 +1107,9 @@ public void Clear() // 2020/9/8 this.Protocol = null; + // 2024/1/18 + this.ReaderName = null; + this.Antenna = null; this.SetNotEmpty(); diff --git a/dp2SSL/Controls/PatronControl.xaml.cs b/dp2SSL/Controls/PatronControl.xaml.cs index 505f52d1b..06fd5c72e 100644 --- a/dp2SSL/Controls/PatronControl.xaml.cs +++ b/dp2SSL/Controls/PatronControl.xaml.cs @@ -47,9 +47,9 @@ public void SetStartMessage(string style) bool rfid = StringUtil.IsInList("rfid", style); bool face = StringUtil.IsInList("face", style); if (fingerprint && rfid) - this.startMessage.Text = "请放读者卡,或扫指纹 ..."; + this.startMessage.Text = $"请放读者卡,或扫{PageBorrow.GetFingerprintCaption()} ..."; else if (fingerprint) - this.startMessage.Text = "请扫指纹 ..."; + this.startMessage.Text = $"请扫{PageBorrow.GetFingerprintCaption()} ..."; else if (rfid) this.startMessage.Text = "请放读者卡 ..."; diff --git a/dp2SSL/Dialog/WriteTagWindow.xaml.cs b/dp2SSL/Dialog/WriteTagWindow.xaml.cs index 308a170a3..49927d7fb 100644 --- a/dp2SSL/Dialog/WriteTagWindow.xaml.cs +++ b/dp2SSL/Dialog/WriteTagWindow.xaml.cs @@ -118,12 +118,12 @@ private void WriteTagWindow_Unloaded(object sender, RoutedEventArgs e) App.PatronTagChanged -= App_PatronTagChanged; App.LineFeed -= App_LineFeed; - PageShelf.TrySetMessage(null, $"写入 RFID 标签对话框关闭"); + ShelfData.TrySetMessage(null, $"写入 RFID 标签对话框关闭"); } private async void WriteTagWindow_Loaded(object sender, RoutedEventArgs e) { - PageShelf.TrySetMessage(null, $"写入 RFID 标签对话框打开"); + ShelfData.TrySetMessage(null, $"写入 RFID 标签对话框打开"); _tagChanged = false; App.LineFeed += App_LineFeed; @@ -176,7 +176,7 @@ private async void App_LineFeed(object sender, LineFeedEventArgs e) // 册条码号应该都是大写的 barcode = barcode.ToUpper(); - PageShelf.TrySetMessage(null, $"扫入册条码号: {barcode}"); + ShelfData.TrySetMessage(null, $"扫入册条码号: {barcode}"); // 根据 PII 准备好 TaskInfo var result = await this.PrepareTaskAsync(barcode); @@ -551,7 +551,7 @@ async Task TryWriteTagAsync(IList entities, if (write_result.Value == -1) return write_result; - PageShelf.TrySetMessage(null, $"写入 RFID 成功。\r\n{task_info.GetOiPii()}\r\n{task_info?.Title}"); + ShelfData.TrySetMessage(null, $"写入 RFID 成功。\r\n{task_info.GetOiPii()}\r\n{task_info?.Title}"); #if REMOVED // 写入 var chip = BuildChip(task_info); @@ -868,7 +868,7 @@ private void writeButton_Click(object sender, RoutedEventArgs e) return; } - PageShelf.TrySetMessage(null, $"写入 RFID 成功。\r\n{TaskInfo?.GetOiPii()}\r\n{TaskInfo?.Title}"); + ShelfData.TrySetMessage(null, $"写入 RFID 成功。\r\n{TaskInfo?.GetOiPii()}\r\n{TaskInfo?.Title}"); } // 根据 PII 准备好 TaskInfo diff --git a/dp2SSL/Models/DoorStateTask.cs b/dp2SSL/Models/DoorStateTask.cs index fcef9e6af..bf34d8195 100644 --- a/dp2SSL/Models/DoorStateTask.cs +++ b/dp2SSL/Models/DoorStateTask.cs @@ -192,7 +192,7 @@ public async static Task BuildDoorActionsAsync(DoorItem door, if (result.Value == -1) { SetGlobalError("save_actions", $"SaveDoorActions() 出错: {result.ErrorInfo}"); - PageShelf.TrySetMessage(null, $"SaveDoorActions() 出错: {result.ErrorInfo}。这是一个严重错误,请管理员及时介入处理"); + ShelfData.TrySetMessage(null, $"SaveDoorActions() 出错: {result.ErrorInfo}。这是一个严重错误,请管理员及时介入处理"); } else { diff --git a/dp2SSL/Models/GlobalMonitor.cs b/dp2SSL/Models/GlobalMonitor.cs index 19bf4f11a..3fd6b055b 100644 --- a/dp2SSL/Models/GlobalMonitor.cs +++ b/dp2SSL/Models/GlobalMonitor.cs @@ -136,13 +136,13 @@ public static void StartMonitorTask() if (update_result.Value == 1) { App.TriggerUpdated("重启 dp2ssl(greensetup) 可使用新版本"); - PageShelf.TrySetMessage(null, "dp2SSL 升级文件已经下载成功,下次重启 dp2ssl(greensetup) 时可自动启用新版本"); + ShelfData.TrySetMessage(null, "dp2SSL 升级文件已经下载成功,下次重启 dp2ssl(greensetup) 时可自动启用新版本"); } else if (update_result.Value == 2) { _needReboot = true; App.TriggerUpdated("重启计算机可使用新版本"); - PageShelf.TrySetMessage(null, "dp2SSL 升级文件已经下载成功,下次重启计算机时可自动升级到新版本"); + ShelfData.TrySetMessage(null, "dp2SSL 升级文件已经下载成功,下次重启计算机时可自动升级到新版本"); } else { @@ -150,7 +150,7 @@ public static void StartMonitorTask() if (ReturnUpateResult) { ReturnUpateResult = false; - PageShelf.TrySetMessage(null, "没有发现新版本"); + ShelfData.TrySetMessage(null, "没有发现新版本"); } } } @@ -319,11 +319,11 @@ public static void ActivateUpdate() { if (_updateSucceedCount > 0) { - PageShelf.TrySetMessage(null, "稍早已经更新过了,现在重启 dp2ssl 可以使用此新版本"); + ShelfData.TrySetMessage(null, "稍早已经更新过了,现在重启 dp2ssl 可以使用此新版本"); return; } - PageShelf.TrySetMessage(null, "开始更新"); + ShelfData.TrySetMessage(null, "开始更新"); _lastUpdateTime = DateTime.MinValue; ActivateMonitor(); } diff --git a/dp2SSL/Models/ShelfData.cs b/dp2SSL/Models/ShelfData.cs index 3658f61d8..44dd4d79d 100644 --- a/dp2SSL/Models/ShelfData.cs +++ b/dp2SSL/Models/ShelfData.cs @@ -29,6 +29,8 @@ using DigitalPlatform.LibraryServer; using DigitalPlatform.Xml; using static DigitalPlatform.RFID.LogicChip; +using Microsoft.EntityFrameworkCore.Internal; +using DocumentFormat.OpenXml.Office2013.Drawing.ChartStyle; namespace dp2SSL { @@ -297,7 +299,7 @@ public static void RfidManager_ListLocks(object sender, ListLocksEventArgs e) text = $"门 '{result.Door.Name}' 被 {result.Door.Operator?.GetDisplayStringMasked()} 打开"; else text = $"门 '{result.Door.Name}' 被 {result.Door.Operator?.GetDisplayStringMasked()} 关上"; - PageShelf.TrySetMessage(null, text); + ShelfData.TrySetMessage(null, text); } // 2021/9/26 @@ -3867,6 +3869,13 @@ string ToString(List door_list) }); */ + if (silently == false) + { + string error = CheckUiiDup(all); + if (error != null) + warnings.Add(error); + } + return new InitialShelfResult { Warnings = warnings, @@ -3886,6 +3895,54 @@ bool Cross(List doors1, List doors2) } } + public static string CheckUiiDup(IReadOnlyCollection all) + { + // 对 all 里面的 UII 进行查重 + var uiis = all + .Select(o => new { UII = o.GetOiPii(), Entity = o }) + .ToList(); + + var dups = uiis.GroupBy(o => o.UII) + .Select(o => new + { + Key = o.Key, + Entities = o.Select(i => i.Entity).ToList(), + Count = o.Count() + }) + .Where(o => o.Count > 1) + .ToList(); + + if (dups.Count > 0) + { + List infos = new List(); + foreach (var dup in dups) + { + infos.Add($"{dup.Key}:{GetDoorNames(dup.Entities)}"); + } + return $"下列标签的 UII 发生了重复: {StringUtil.MakePathList(infos, "; ")}"; + } + + return null; + + string GetDoorNames(IEnumerable entities) + { + List results = new List(); + foreach (var entity in entities) + { + results.Add(GetDoorName(entity)); + } + return StringUtil.MakePathList(results, ","); + } + + string GetDoorName(Entity entity) + { + var doors = DoorItem.FindDoors(ShelfData.Doors, entity.ReaderName, entity.Antenna); + if (doors.Count != 1) + return $"(未知门名)ReaderName={entity.ReaderName}|Antenna={entity.Antenna}"; + return doors[0].Name; + } + } + // Exception: // 可能会抛出异常 ArgumentException TagDataException static void SetTagType(TagAndData data, @@ -3922,7 +3979,7 @@ static void SetTagType(TagAndData data, // 注1: taginfo.EAS 在调用后可能被修改 // 注2: 本函数不再抛出异常。会在 ErrorInfo 中报错 var chip_info = RfidTagList.GetChipInfo(data.OneTag.TagInfo); - + if (string.IsNullOrEmpty(chip_info.ErrorInfo) == false) { data.Type = ""; // 表示类型不确定 @@ -4102,6 +4159,7 @@ static Entity NewEntity(TagAndData tag, bool throw_exception = true) Debug.Assert(string.IsNullOrEmpty(pii) == false); Debug.Assert(chip != null); #endif + // 注意: 这里 pii 可能为空 result.PII = pii; } catch (Exception ex) @@ -4175,6 +4233,10 @@ static Entity NewEntity(TagAndData tag, bool throw_exception = true) result.OI = oi; result.AOI = aoi; + // 2024/1/18 + if (string.IsNullOrEmpty(result.PII)) + result.PII = chip?.FindElement(ElementOID.PII)?.Text; + // 2020/8/27 // 严格要求必须有 OI(AOI) 字段 if (string.IsNullOrEmpty(oi) && string.IsNullOrEmpty(aoi)) @@ -7371,6 +7433,174 @@ public static string IsOiChanging(string old_location, string new_location) return $"馆藏地从 '{old_location}' 变为 '{new_location}' 将导致机构代码从 '{old_oi}' 变为 '{new_oi}'"; } + // 2024/1/17 + // 正常运行情况下,触发一次全面盘点动作 + public static async Task DoInventoryAsync() + { + List all_actions = new List(); + + foreach (var door in ShelfData.Doors) + { + var entities = new List(); + foreach (var entity in door.AllEntities) + { + var dup = entity.Clone(); + dup.Container = null; + entities.Add(dup); + } + + if (entities.Count > 0) + { + var result = BuildInventoryActions( + entities, + "dont_change_eas,dont_return", + out List actions); + if (result.Value == -1) + return result; // TODO: 是否继续做完再报错 + all_actions.AddRange(actions); + } + } + if (all_actions.Count > 0) + await ShelfData.SaveActionsToDatabaseAsync(all_actions); + return new NormalResult { Value = all_actions.Count }; + } + + // parameters: + // style 如果包含 dont_change_eas,表示不修改 EAS + // 如果包含 dont_return, 表示不建立 return 动作 + public static NormalResult BuildInventoryActions( + IReadOnlyCollection entities, + string style, // 2024/1/17 + out List actions) + { + var dont_change_eas = StringUtil.IsInList("dont_change_eas", style); + var dont_return = StringUtil.IsInList("dont_return", style); + + DateTime now = ShelfData.Now; // DateTime.Now; + + actions = new List(); + foreach (var entity in entities) + { + if (dont_return == false) + { + actions.Add(new ActionInfo + { + Entity = entity.Clone(), + Action = "return", + Operator = GetOperator(entity, false), + OperTime = now, + }); + } + actions.Add(new ActionInfo + { + Entity = entity.Clone(), + Action = "transfer", // 这里是试探性的 transfer,如果册记录不发生变化则不写入操作日志 + CurrentShelfNo = ShelfData.GetShelfNo(entity), + Operator = GetOperator(entity, false), + OperTime = now, + }); + + // 2020/4/2 + // 还书操作前先尝试修改 EAS + + // 对于前面已经出错的标签不修改 EAS + if (dont_change_eas == false + && entity.Error == null && StringUtil.IsInList("patronCard,oiError", entity.ErrorCode) == false) + { + var eas_result = ShelfData.SetEAS(entity.UID, entity.Antenna, false); + if (eas_result.Value == -1) + { + string text = $"修改 EAS 动作失败: {eas_result.ErrorInfo}"; + entity.AppendError(text, "red", "setEasError"); + + return new NormalResult + { + Value = -1, + ErrorInfo = $"修改册 '{entity.GetPiiOrUid()}' 的 EAS 失败: {eas_result.ErrorInfo}", + ErrorCode = "setEasError" + }; + } + } + } + + return new NormalResult(); + } + + // 获得特定门的 Operator + // parameters: + // logNullOperator 是否在错误日志里面记载未找到门的 Operator 的情况?(读者借书时候需要 log,其他时候不需要) + static Operator GetOperator(Entity entity, bool logNullOperator) + { + var doors = DoorItem.FindDoors(ShelfData.Doors, entity.ReaderName, entity.Antenna); + if (doors.Count == 0) + return null; + if (doors.Count > 1) + { + WpfClientInfo.WriteErrorLog($"读卡器名 '{entity.ReaderName}' 天线编号 {entity.Antenna} 匹配上 {doors.Count} 个门"); + throw new Exception($"读卡器名 '{entity.ReaderName}' 天线编号 {entity.Antenna} 匹配上 {doors.Count} 个门。请检查 shelf.xml 并修正配置此错误,确保只匹配一个门"); + } + + var person = doors[0].Operator; + if (person == null) + { + if (logNullOperator) + WpfClientInfo.WriteErrorLog($"标签 '{entity.UID}' 经查找属于门 '{doors[0].Name}',但此时门 '{doors[0].Name}' 并没有关联的 Operator 信息"); + return new Operator(); + } + return person; + } + + // 将所有暂存信息构造为 Action,但并不立即提交 + public static async Task BuildAllActionsAsync() + { + var result = await ShelfData.BuildActionsAsync((entity) => + { + return GetOperator(entity, true); + }); + + if (result.Value == -1) + { + App.SetError("save_actions", $"SaveAllActions() 出错: {result.ErrorInfo}"); + TrySetMessage(null, $"SaveAllActions() 出错: {result.ErrorInfo}。这是一个严重错误,请管理员及时介入处理"); + } + else + { + App.SetError("save_actions", null); + } + } + + + public static void TrySetMessage(string[] groups, string text) + { + // TODO: 当 groups 为 null 时,是代表当前书柜 dp2mserver 所加入的所有群名列表 + /* + if (groups == null) + { + groups = TinyServer.GroupNames; + if (groups == null || groups.Length == 0) + { + App.CurrentApp?.SetError("setMessage", $"发送消息出现异常: GroupName 不正确。消息内容:{StringUtil.CutString(text, 100)}"); + WpfClientInfo.WriteErrorLog($"发送消息出现异常: GroupName 不正确"); + return; + } + } + */ + + _ = Task.Run(async () => + { + try + { + await TinyServer.SendMessageAsync(groups, text); + } + catch (Exception ex) + { + App.SetError("setMessage", $"发送消息出现异常: {ex.Message}。消息内容:{StringUtil.CutString(text, 100)}"); + WpfClientInfo.WriteErrorLog($"发送消息出现异常: {ExceptionUtil.GetDebugText(ex)}。消息内容:{text}"); + } + }); + } + + /* static Operator OperatorFromRequest(RequestItem request) { diff --git a/dp2SSL/Models/ShelfData_monitor.cs b/dp2SSL/Models/ShelfData_monitor.cs index 8280b84b6..626c2b919 100644 --- a/dp2SSL/Models/ShelfData_monitor.cs +++ b/dp2SSL/Models/ShelfData_monitor.cs @@ -198,7 +198,7 @@ public static void StartMonitorTask() // 如果 Config 中没有记载断点位置,说明以前从来没有首次同步过。需要进行一次首次同步 if (string.IsNullOrEmpty(startDate)) { - // SaveStartDate(""); + SaveStartDate(null); // (2024/1/18) 当本次下载没有完整完成的情况下,下次 dp2ssl (启动后)还会继续尝试重新下载全部读者记录 // 专用 token source using (var download_source = CancellationTokenSource.CreateLinkedTokenSource(token)) @@ -214,7 +214,7 @@ public static void StartMonitorTask() (text) => { WpfClientInfo.WriteInfoLog(text); - PageShelf.TrySetMessage(null, text); + ShelfData.TrySetMessage(null, text); }, download_source.Token); if (repl_result.Value == -1) @@ -222,12 +222,16 @@ public static void StartMonitorTask() // TODO: 判断通讯出错的错误码。如果是通讯出错,则稍后需要重试下载 _replicatePatronError++; + WpfClientInfo.WriteErrorLog($"下载全部读者记录到本地缓存出错(注意 settings.xml 中分界日期已经清空,这样后面时机恰当时会自动重新尝试下载): {repl_result.ErrorInfo}"); + App.CurrentApp.SpeakSequence($"下载全部读者记录到本地缓存出错: {repl_result.ErrorInfo}"); } else { SaveStartDate(repl_result.StartDate); + WpfClientInfo.WriteErrorLog($"下载全部读者记录到本地缓存成功。分界日期 '{repl_result.StartDate}' 已经记入 settings.xml"); + App.CurrentApp.SpeakSequence("下载全部读者记录到本地缓存完成"); } @@ -329,7 +333,7 @@ public static void StartMonitorTask() (text) => { WpfClientInfo.WriteInfoLog(text); - PageShelf.TrySetMessage(null, text); + ShelfData.TrySetMessage(null, text); App.CurrentApp.SpeakSequence(text); }, download_source.Token); diff --git a/dp2SSL/Models/ShelfData_sync.cs b/dp2SSL/Models/ShelfData_sync.cs index 31ca5d80c..7032a9a29 100644 --- a/dp2SSL/Models/ShelfData_sync.cs +++ b/dp2SSL/Models/ShelfData_sync.cs @@ -1274,7 +1274,7 @@ static void MessageNotifyOverflow(List actions) }); if (overflow_titles.Count > 0) { - PageShelf.TrySetMessage(null, $"下列图书发生超额借阅:\r\n{StringUtil.MakePathList(overflow_titles, "\r\n")}"); + ShelfData.TrySetMessage(null, $"下列图书发生超额借阅:\r\n{StringUtil.MakePathList(overflow_titles, "\r\n")}"); } } diff --git a/dp2SSL/Page/PageBorrow.xaml.cs b/dp2SSL/Page/PageBorrow.xaml.cs index 96819ca1f..fcfe90b83 100644 --- a/dp2SSL/Page/PageBorrow.xaml.cs +++ b/dp2SSL/Page/PageBorrow.xaml.cs @@ -526,12 +526,19 @@ private async void App_LineFeed(object sender, LineFeedEventArgs e) string barcode = e.Text.ToUpper(); // 触发人脸识别 - if (string.IsNullOrEmpty(barcode) - && string.IsNullOrEmpty(App.FaceUrl) == false) + if (string.IsNullOrEmpty(barcode)) { - PatronClear(); - PatronControl_InputFace(this, new EventArgs()); - return; + if (StringUtil.IsInList("face", GetPageStyleList()) == true) + { + PatronClear(); + PatronControl_InputFace(this, new EventArgs()); + return; + } + else + { + App.CurrentApp.Speak("不允许人脸识别"); + return; + } } // if (App.EnablePatronBarcode == false) @@ -703,6 +710,13 @@ async Task ChangeEntitiesAsync(//BaseChannel channel, } })); + // 2024/1/19 + // 修正: 当 ISO15693 的标签被发现实际上是读者标签时,意味着并没有发生实质性变化,changed 应该修正为 false + if (e.AddPatrons.Count == 1 + && e.RemoveBooks.Count == 1 + && e.AddPatrons[0].OneTag?.UID == e.RemoveBooks[0].OneTag?.UID) + changed = false; + if (update_entities.Count > 0) { _ = FillBookFieldsAsync(//channel, @@ -1687,17 +1701,25 @@ void SetPatronInfo(GetMessageResult result) if (result.Value == -1) { - SetPatronError("fingerprint", $"指纹中心出错: {result.ErrorInfo}, 错误码: {result.ErrorCode}"); + SetPatronError("fingerprint", $"{GetFingerprintCaption()}中心出错: {result.ErrorInfo}, 错误码: {result.ErrorCode}"); if (IsVerticalCard()/*_patron.IsFingerprintSource || App.PatronReaderVertical == true*/) PatronClear(); // 只有当面板上的读者信息来源是指纹仪时(或者身份读卡器竖放),才清除面板上的读者信息 return; } + else if (result.Quality == -1) + { + // 掌纹(或者指纹)图像质量较差 + // TODO: 有没有必要提示,如何提示? 比如积累到一定次数以后,提醒“请调整手掌距离” + return; + } else { // 清除以前残留的报错信息 SetPatronError("fingerprint", ""); } + // TODO: (掌纹识别)和上一个识别的读者证条码号一样,则语音提示,不做重新装载读者信息 + if (result.Message == null) return; @@ -3446,7 +3468,7 @@ bool IsPatronOK(string action, return true; string fang = "放好"; - if (IsVerticalCard()/*App.PatronReaderVertical*/) + if (IsVerticalCardDefined()/*App.PatronReaderVertical*/) fang = "扫"; string debug_info = $"(uid:[{_patron.UID}],barcode:[{_patron.Barcode}])"; @@ -3454,7 +3476,7 @@ bool IsPatronOK(string action, { // 提示信息要考虑到应用了指纹的情况 if (string.IsNullOrEmpty(App.FingerprintUrl) == false) - message = $"请先{fang}读者卡,或扫入一次指纹,然后再进行借书操作{(show_debug_info ? debug_info : "")}"; + message = $"请先{fang}读者卡,或扫入一次{GetFingerprintCaption()},然后再进行借书操作{(show_debug_info ? debug_info : "")}"; else message = $"请先{fang}读者卡,然后再进行借书操作{(show_debug_info ? debug_info : "")}"; } @@ -3467,7 +3489,7 @@ bool IsPatronOK(string action, // 提示信息要考虑到应用了指纹的情况 if (string.IsNullOrEmpty(App.FingerprintUrl) == false) - message = $"请先{fang}读者卡,或扫入一次指纹,然后再进行{action_name}操作{(show_debug_info ? debug_info : "")}"; + message = $"请先{fang}读者卡,或扫入一次{GetFingerprintCaption()},然后再进行{action_name}操作{(show_debug_info ? debug_info : "")}"; else message = $"请先{fang}读者卡,然后再进行{action_name}操作{(show_debug_info ? debug_info : "")}"; } @@ -3493,7 +3515,7 @@ bool IsPatronOK(string action, List styles = new List(); styles.Add($"请{fang}可用的读者 RFID 卡鉴别身份"); if (string.IsNullOrEmpty(App.FingerprintUrl) == false) - styles.Add("或扫入一次指纹"); + styles.Add($"或扫入一次{GetFingerprintCaption()}"); if (string.IsNullOrEmpty(App.FaceUrl) == false) styles.Add("或人脸识别"); if (string.IsNullOrEmpty(App.PatronBarcodeStyle) == false && App.PatronBarcodeStyle != "禁用") @@ -3509,6 +3531,14 @@ bool IsPatronOK(string action, return false; } + public static string GetFingerprintCaption() + { + if (App.FingerprintUrl != null + && App.FingerprintUrl.ToLower().Contains("palm")) + return "掌纹"; + return "指纹"; + } + #if NO NormalResult Return() { @@ -4588,7 +4618,7 @@ public static int UploadFile( } #endif -#endregion + #endregion #if OLDVERSION @@ -4793,7 +4823,7 @@ private void ClearPatron_Click(object sender, RoutedEventArgs e) { CancelDelayClearTask(); - PatronClear(); + PatronClear(true); // 2024/1/19 改为 true } #region 提醒拿走读者卡 @@ -5204,8 +5234,10 @@ async Task Get14443ACardUIDAsync(ProgressWindow progress, remove_text = $"拿走多余的读者卡(ISO14443A),然后"; // "读卡器只应放一张副卡。请拿走多余的副卡"; string text = $"放上要{action_caption}的副卡"; + /* if (App.PatronReaderVertical) text = $"扫要{action_caption}的副卡"; + */ App.Invoke(new Action(() => { progress.MessageText = "请" + remove_text + text; @@ -5589,7 +5621,17 @@ public static NormalResult ModifyBinding(XmlDocument dom, // (这种方式下需要固定读者信息一段时间) public bool IsVerticalCard() { - return (App.PatronReaderVertical || _patron.IsFingerprintSource); + if (_patron.IsFingerprintSource + || StringUtil.IsInList(_patron.ReaderName, App.VerticalReaderName)) + return true; + return false; + // return (App.PatronReaderVertical || _patron.IsFingerprintSource); + } + + // 是否已经定义了某个竖放的读写器 + public bool IsVerticalCardDefined() + { + return string.IsNullOrEmpty(App.VerticalReaderName) == false; } void SetFixVisible() diff --git a/dp2SSL/Page/PageSetting.xaml b/dp2SSL/Page/PageSetting.xaml index a9818785d..936eae91d 100644 --- a/dp2SSL/Page/PageSetting.xaml +++ b/dp2SSL/Page/PageSetting.xaml @@ -69,6 +69,8 @@ + + diff --git a/dp2SSL/Page/PageSetting.xaml.cs b/dp2SSL/Page/PageSetting.xaml.cs index 0840a9731..a1e461d11 100644 --- a/dp2SSL/Page/PageSetting.xaml.cs +++ b/dp2SSL/Page/PageSetting.xaml.cs @@ -1520,5 +1520,43 @@ private void activatePatronReplication_Click(object sender, RoutedEventArgs e) { ShelfData.ActivateReplication(); } + + // 2024/1/17 + // 迫使下一次启动 dp2ssl 时进行一轮盘点。 + // 方法是通过修改 最后一次启动阶段写入动作库的时间 为久远的时间,这样下次启动 dp2ssl 的时候程序会发现当前时间和这个时间差距超过 30 天,就会把盘点动作写入本地动作库 + private void forceRestartInventory_Click(object sender, RoutedEventArgs e) + { + if (App.Function != "智能书柜") + { + App.ErrorBox("盘点书柜内全部图书", + $"当前 dp2ssl 不是智能书柜功能状态,无法执行此功能", + "red"); + return; + } + + ShelfData.SetWriteTime(DateTime.MinValue); + } + + private async void tiggerInventory_Click(object sender, RoutedEventArgs e) + { + if (App.Function != "智能书柜") + { + App.ErrorBox("盘点书柜内全部图书", + $"当前 dp2ssl 不是智能书柜功能状态,无法执行此功能", + "red"); + return; + } + + var result = await ShelfData.DoInventoryAsync(); + if (result.Value == -1) + App.ErrorBox("盘点书柜内全部图书", + $"处理出错: {result.ErrorInfo}", + "red"); + else + App.ErrorBox("盘点书柜内全部图书", + $"处理完成。创建盘点记录 {result.Value} 个", + "green"); + + } } } diff --git a/dp2SSL/Page/PageShelf.xaml.cs b/dp2SSL/Page/PageShelf.xaml.cs index 1a3054c2d..e22a4cd74 100644 --- a/dp2SSL/Page/PageShelf.xaml.cs +++ b/dp2SSL/Page/PageShelf.xaml.cs @@ -647,12 +647,19 @@ private async void App_LineFeed(object sender, LineFeedEventArgs e) // 扫入一个条码 string barcode = e.Text; // .ToUpper(); - if (string.IsNullOrEmpty(barcode) - && string.IsNullOrEmpty(App.FaceUrl) == false) + if (string.IsNullOrEmpty(barcode)) { - PatronClear(); - PatronControl_InputFace(this, new EventArgs()); - return; + if (string.IsNullOrEmpty(App.FaceUrl) == false) + { + PatronClear(); + PatronControl_InputFace(this, new EventArgs()); + return; + } + else + { + App.CurrentApp.Speak("不允许人脸识别"); + return; + } } if ((string.IsNullOrEmpty(App.PatronBarcodeStyle) || App.PatronBarcodeStyle == "禁用") @@ -746,7 +753,7 @@ private async void ShelfData_DoorStateChanged(object sender, DoorStateChangedEve text = $"门 '{e.Door.Name}' 被 {e.Door.Operator?.GetDisplayString()} 打开"; else text = $"门 '{e.Door.Name}' 被 {e.Door.Operator?.GetDisplayString()} 关上"; - TrySetMessage(null, text); + ShelfData.TrySetMessage(null, text); } if (e.NewState == "close") @@ -834,36 +841,6 @@ await Task.Run(() => } #endif - public static void TrySetMessage(string[] groups, string text) - { - // TODO: 当 groups 为 null 时,是代表当前书柜 dp2mserver 所加入的所有群名列表 - /* - if (groups == null) - { - groups = TinyServer.GroupNames; - if (groups == null || groups.Length == 0) - { - App.CurrentApp?.SetError("setMessage", $"发送消息出现异常: GroupName 不正确。消息内容:{StringUtil.CutString(text, 100)}"); - WpfClientInfo.WriteErrorLog($"发送消息出现异常: GroupName 不正确"); - return; - } - } - */ - - _ = Task.Run(async () => - { - try - { - await TinyServer.SendMessageAsync(groups, text); - } - catch (Exception ex) - { - App.SetError("setMessage", $"发送消息出现异常: {ex.Message}。消息内容:{StringUtil.CutString(text, 100)}"); - WpfClientInfo.WriteErrorLog($"发送消息出现异常: {ExceptionUtil.GetDebugText(ex)}。消息内容:{text}"); - } - }); - } - static string GetPartialName(string buttonName) { if (buttonName == "count") @@ -968,7 +945,7 @@ static string GetStyleMessage() List styles = new List(); styles.Add($"刷读者 RFID 卡鉴别身份"); if (string.IsNullOrEmpty(App.FingerprintUrl) == false) - styles.Add("或扫入一次指纹"); + styles.Add($"或扫入一次{PageBorrow.GetFingerprintCaption()}"); if (string.IsNullOrEmpty(App.FaceUrl) == false) styles.Add("或人脸识别"); if (string.IsNullOrEmpty(App.PatronBarcodeStyle) == false && App.PatronBarcodeStyle != "禁用") @@ -1597,7 +1574,7 @@ private async void PageShelf_Unloaded(object sender, RoutedEventArgs e) // 提交尚未提交的取出和放入 // PatronClear(true); - await BuildAllActionsAsync(); + await ShelfData.BuildAllActionsAsync(); await SubmitAsync(true); RfidManager.SetError -= RfidManager_SetError; @@ -1668,7 +1645,7 @@ bool SetPatronInfo(GetMessageResult result, string protocol) if (result.Value == -1) { - SetPatronError("fingerprint", $"指纹或人脸中心出错: {result.ErrorInfo}, 错误码: {result.ErrorCode}"); + SetPatronError("fingerprint", $"{PageBorrow.GetFingerprintCaption()}或人脸中心出错: {result.ErrorInfo}, 错误码: {result.ErrorCode}"); if (_patron.IsFingerprintSource) PatronClear(); // 只有当面板上的读者信息来源是指纹仪时,才清除面板上的读者信息 return false; @@ -2208,7 +2185,7 @@ async Task InitialShelfEntitiesAsync(string networkMode, App.CurrentApp.SetError("setMessage", null); */ - TrySetMessage(null, "我正在执行初始化 ..."); + ShelfData.TrySetMessage(null, "我正在执行初始化 ..."); } App.Invoke(new Action(() => @@ -2247,7 +2224,7 @@ async Task InitialShelfEntitiesAsync(string networkMode, if (passwordErrorCount > 5) { string error = "密码错误次数太多,开门功能被禁用"; - TrySetMessage(null, error); + ShelfData.TrySetMessage(null, error); ErrorBox("", error); // 延时 10 分钟清除 passwordErrorCount if (delayClear == null) @@ -2262,12 +2239,12 @@ async Task InitialShelfEntitiesAsync(string networkMode, return; } - TrySetMessage(null, "“开门”按钮被按下(正在初始化对话框),等待现场操作者输入管理密码"); + ShelfData.TrySetMessage(null, "“开门”按钮被按下(正在初始化对话框),等待现场操作者输入管理密码"); var password = GetPassword(); if (password == null) { - TrySetMessage(null, "放弃输入密码开门"); + ShelfData.TrySetMessage(null, "放弃输入密码开门"); // ErrorBox("放弃输入密码开门"); } else @@ -2276,7 +2253,7 @@ async Task InitialShelfEntitiesAsync(string networkMode, if (App.MatchLockingPassword(password) == false) { passwordErrorCount++; - TrySetMessage(null, "密码错误,无法开门"); + ShelfData.TrySetMessage(null, "密码错误,无法开门"); ErrorBox("", "密码错误,无法开门"); } else @@ -2284,7 +2261,7 @@ async Task InitialShelfEntitiesAsync(string networkMode, var open_result = RfidManager.OpenShelfLock(progress.Door.LockPath); if (open_result.Value == -1) { - TrySetMessage(null, open_result.ErrorInfo); + ShelfData.TrySetMessage(null, open_result.ErrorInfo); ErrorBox("", open_result.ErrorInfo); } } @@ -2294,20 +2271,20 @@ async Task InitialShelfEntitiesAsync(string networkMode, { silently = false; eventRetry.Set(); - TrySetMessage(null, "“重试”按钮被按下(正在初始化对话框)"); + ShelfData.TrySetMessage(null, "“重试”按钮被按下(正在初始化对话框)"); }; progress.silentlyRetryButton.Click += (s, e) => { silently = true; eventRetry.Set(); - TrySetMessage(null, "“静默重试”按钮被按下(正在初始化对话框)"); + ShelfData.TrySetMessage(null, "“静默重试”按钮被按下(正在初始化对话框)"); }; progress.cancelButton.Click += (s, e) => { eventCancel.Set(); progress.Close(); - TrySetMessage(null, "“中断”按钮被按下(正在初始化对话框)"); + ShelfData.TrySetMessage(null, "“中断”按钮被按下(正在初始化对话框)"); }; App.SetSize(progress, "tall"); progress.EnableRetryOpenButtons(false); @@ -2557,7 +2534,9 @@ await Task.Run(() => })); // 构造 actions,用于同步到 dp2library 服务器 - var build_result = BuildInventoryActions(part, + var build_result = ShelfData.BuildInventoryActions( + part, + "", out List part_actions); if (build_result.Value == -1 && silently == false) { @@ -2858,6 +2837,13 @@ await Task.Run(() => // 启动门状态处理任务。此任务长期在后台运行 DoorStateTask.StartTask(); + // 进行一次针对全部图书 UII 的查重 + { + var warning = ShelfData.CheckUiiDup(ShelfData.l_All); + if (warning != null) + App.ErrorBox("发现错误: 图书 UII 出现重复", warning + "\r\n\r\n请尽快将这些图书从书柜中取出进行甄别、重新加工处理"); + } + // 2021/10/11 var numbers = $"{ShelfData.BookTagList.Tags.Count}:{ShelfData.PatronTagList.Tags.Count}"; WpfClientInfo.WriteInfoLog($"标签总数 {numbers}"); @@ -2897,7 +2883,7 @@ await Task.Run(() => ShelfData.FirstInitialized = true; // 第一次初始化已经完成 { - TrySetMessage(null, "我已经成功完成初始化。读者可以开始用我借书啦"); + ShelfData.TrySetMessage(null, "我已经成功完成初始化。读者可以开始用我借书啦"); } } else @@ -2912,7 +2898,7 @@ await Task.Run(() => // "智能书柜初始化失败。请检查读卡器和门锁参数配置,重新进行初始化 ..." ); { - TrySetMessage(null, "*** 抱歉,我初始化失败了。请管理员帮我解决一下吧!"); + ShelfData.TrySetMessage(null, "*** 抱歉,我初始化失败了。请管理员帮我解决一下吧!"); } /* ProgressWindow error = null; Application.Current.Dispatcher.Invoke(new Action(() => @@ -3884,7 +3870,7 @@ public async Task SubmitAsync(bool silently = false) || ShelfData.l_Removes.Count > 0 || ShelfData.l_Changes.Count > 0) { - await BuildAllActionsAsync(); + await ShelfData.BuildAllActionsAsync(); await DoRequestAsync(ShelfData.PullActions(), silently ? "silence" : ""); // await SubmitCheckInOut("silence"); } @@ -4140,79 +4126,6 @@ Operator GetOperator() } */ - // 获得特定门的 Operator - // parameters: - // logNullOperator 是否在错误日志里面记载未找到门的 Operator 的情况?(读者借书时候需要 log,其他时候不需要) - static Operator GetOperator(Entity entity, bool logNullOperator) - { - var doors = DoorItem.FindDoors(ShelfData.Doors, entity.ReaderName, entity.Antenna); - if (doors.Count == 0) - return null; - if (doors.Count > 1) - { - WpfClientInfo.WriteErrorLog($"读卡器名 '{entity.ReaderName}' 天线编号 {entity.Antenna} 匹配上 {doors.Count} 个门"); - throw new Exception($"读卡器名 '{entity.ReaderName}' 天线编号 {entity.Antenna} 匹配上 {doors.Count} 个门。请检查 shelf.xml 并修正配置此错误,确保只匹配一个门"); - } - - var person = doors[0].Operator; - if (person == null) - { - if (logNullOperator) - WpfClientInfo.WriteErrorLog($"标签 '{entity.UID}' 经查找属于门 '{doors[0].Name}',但此时门 '{doors[0].Name}' 并没有关联的 Operator 信息"); - return new Operator(); - } - return person; - } - - static NormalResult BuildInventoryActions( - IReadOnlyCollection entities, - out List actions) - { - DateTime now = ShelfData.Now; // DateTime.Now; - - actions = new List(); - foreach (var entity in entities) - { - actions.Add(new ActionInfo - { - Entity = entity.Clone(), - Action = "return", - Operator = GetOperator(entity, false), - OperTime = now, - }); - actions.Add(new ActionInfo - { - Entity = entity.Clone(), - Action = "transfer", // 这里是试探性的 transfer,如果册记录不发生变化则不写入操作日志 - CurrentShelfNo = ShelfData.GetShelfNo(entity), - Operator = GetOperator(entity, false), - OperTime = now, - }); - - // 2020/4/2 - // 还书操作前先尝试修改 EAS - - // 对于前面已经出错的标签不修改 EAS - if (entity.Error == null && StringUtil.IsInList("patronCard,oiError", entity.ErrorCode) == false) - { - var eas_result = ShelfData.SetEAS(entity.UID, entity.Antenna, false); - if (eas_result.Value == -1) - { - string text = $"修改 EAS 动作失败: {eas_result.ErrorInfo}"; - entity.AppendError(text, "red", "setEasError"); - - return new NormalResult - { - Value = -1, - ErrorInfo = $"修改册 '{entity.GetPiiOrUid()}' 的 EAS 失败: {eas_result.ErrorInfo}", - ErrorCode = "setEasError" - }; - } - } - } - - return new NormalResult(); - } #if REMOVED // 注:本函数被废止 @@ -4275,24 +4188,6 @@ async Task InventoryBooksAsync( } #endif - // 将所有暂存信息构造为 Action,但并不立即提交 - async Task BuildAllActionsAsync() - { - var result = await ShelfData.BuildActionsAsync((entity) => - { - return GetOperator(entity, true); - }); - - if (result.Value == -1) - { - SetGlobalError("save_actions", $"SaveAllActions() 出错: {result.ErrorInfo}"); - TrySetMessage(null, $"SaveAllActions() 出错: {result.ErrorInfo}。这是一个严重错误,请管理员及时介入处理"); - } - else - { - SetGlobalError("save_actions", null); - } - } SubmitWindow _progressWindow = null; @@ -4466,7 +4361,7 @@ public async Task DoRequestAsync(List actions, text.AppendLine(); i++; } - TrySetMessage(null, text.ToString()); + ShelfData.TrySetMessage(null, text.ToString()); #endif } @@ -4752,7 +4647,7 @@ static async Task SendMessagesAsync(List infos, text.AppendLine(); i++; } - TrySetMessage(null, text.ToString()); + ShelfData.TrySetMessage(null, text.ToString()); } static string MakeList(List list) @@ -5060,11 +4955,11 @@ void Welcome() else if (_patron.Protocol == "barcode") style = "条码卡"; else if (_patron.Protocol == "fingerprint") - style = "指纹"; + style = PageBorrow.GetFingerprintCaption(); else if (_patron.Protocol == "face") style = "人脸"; - TrySetMessage(null, $"{name} 刷{style}"); + ShelfData.TrySetMessage(null, $"{name} 刷{style}"); } } diff --git a/dp2SSL/Properties/AssemblyInfo.cs b/dp2SSL/Properties/AssemblyInfo.cs index 9fffacd59..d333b2eeb 100644 --- a/dp2SSL/Properties/AssemblyInfo.cs +++ b/dp2SSL/Properties/AssemblyInfo.cs @@ -51,8 +51,8 @@ // 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 // 方法是按如下所示使用“*”: : // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.9.11")] // 1.5.* -[assembly: AssemblyFileVersion("1.9.11.0")] // 1.5.0.0 +[assembly: AssemblyVersion("1.9.10")] // 1.5.* +[assembly: AssemblyFileVersion("1.9.10.0")] // 1.5.0.0 // 1.0 2019/2/21 第一个版本 // 1.1 2019/2/26 可以显示版本号了 @@ -184,3 +184,8 @@ // (2024/1/12) 解决读者信息同步 setreaderinfo new 动作时没有利用 libraryCode 元素 从而产生 .xxx 形态的 UII 的一个 bug // 界面风格做了部分优化。左侧按钮向右挪动了一点,为了避免小尺寸书柜屏幕触摸困难。人脸识别按钮增加了中文。主菜单采用 Thin 字体 Weight // (2024/1/16) 解决图书封面图片残缺的文件造成崩溃的 bug。被锁定的图像临时文件会被记入 memory_deleting.txt 文件,等下次 dp2ssl 启动时会根据里面的记载删除临时图像文件(最后删除这个记忆文件) +// (2024/1/17) 管理界面增加了立即触发盘点的命令,和一个迫使重新启动以后进行盘点的命令。都是针对书柜的功能 +// (2024/1/18) 掌纹识别功能解决了 "capture:xxx" 被当作读者证条码号装载读者的 bug +// 1.9.10 (2024/1/18) 书柜初始化阶段,增加了对每个门中的图书,和全部图书进行 UII 查重、报错的步骤 +// 书柜全部下载读者记录到本地缓存的中途如果遇到中断,settings.xml 文件中 patronReplication/startDate 参数会被清空,这样,后面重新启动 dp2ssl 的时候或者其它适当时机,会自动重新开始下载全部读者记录到本地缓存,直到全部成功为止 +// 自助借还原先的配置参数“身份读卡器竖放”被删除,代替它的是一个新的参数“竖放的身份读写器”,内容为身份读写器的名字。自助借还界面会根据这个读写器名字,判断 ISO14443A 或 ISO15693 或者 ISO18000P6C 的读者卡是否需要按照竖放进行特定处理和提醒。原来参数的缺点是,无法弄清楚两个或以上的读写器都可以读 ISO15693 读者卡、到底哪个是竖放的 diff --git a/dp2SSL/Tasks/ShutdownTask.cs b/dp2SSL/Tasks/ShutdownTask.cs index f7c10378e..10a985cad 100644 --- a/dp2SSL/Tasks/ShutdownTask.cs +++ b/dp2SSL/Tasks/ShutdownTask.cs @@ -294,7 +294,7 @@ async static Task ShutdownAsync(CancellationToken token) progress.Show(); })); - PageShelf.TrySetMessage(null, "即将自动关机,正在倒计时 ..."); + ShelfData.TrySetMessage(null, "即将自动关机,正在倒计时 ..."); try { @@ -345,7 +345,7 @@ async static Task ShutdownAsync(CancellationToken token) WpfClientInfo.WriteErrorLog($"自动关机过程出现异常: {ExceptionUtil.GetDebugText(ex)}"); } }); - PageShelf.TrySetMessage(null, "Windows 将在一秒后关机"); + ShelfData.TrySetMessage(null, "Windows 将在一秒后关机"); } } finally @@ -356,7 +356,7 @@ async static Task ShutdownAsync(CancellationToken token) progress.Close(); })); - // PageShelf.TrySetMessage(null, "已经关机"); + // ShelfData.TrySetMessage(null, "已经关机"); _shutdownTask = null; } diff --git a/dp2SSL/Tasks/SterilampTask.cs b/dp2SSL/Tasks/SterilampTask.cs index 0878dc5fe..9e86e685f 100644 --- a/dp2SSL/Tasks/SterilampTask.cs +++ b/dp2SSL/Tasks/SterilampTask.cs @@ -258,7 +258,7 @@ async static Task SterilampAsync(CancellationToken token) progress.Show(); })); - PageShelf.TrySetMessage(null, "即将开始紫外线消毒,正在倒计时 ..."); + ShelfData.TrySetMessage(null, "即将开始紫外线消毒,正在倒计时 ..."); try { @@ -290,7 +290,7 @@ async static Task SterilampAsync(CancellationToken token) progress.MessageText = "正在进行紫外线消毒,请不要靠近书柜\r\n\r\n警告:紫外线对眼睛和皮肤有害"; })); - PageShelf.TrySetMessage(null, "正在进行紫外线消毒,请不要靠近书柜"); + ShelfData.TrySetMessage(null, "正在进行紫外线消毒,请不要靠近书柜"); // TODO: 屏幕上可以显示剩余时间 // TODO: 背景色动画,闪动 @@ -322,7 +322,7 @@ async static Task SterilampAsync(CancellationToken token) progress.Close(); })); - PageShelf.TrySetMessage(null, "紫外线消毒结束"); + ShelfData.TrySetMessage(null, "紫外线消毒结束"); _sterilampTask = null; } diff --git a/dp2SSL/design.txt b/dp2SSL/design.txt index 24d707a66..994621f80 100644 --- a/dp2SSL/design.txt +++ b/dp2SSL/design.txt @@ -187,3 +187,45 @@ https://social.msdn.microsoft.com/Forums/sqlserver/en-US/6a836c72-a06f-487c-8645 *** + + +~~~ +给书柜设计一个功能,先将所有“智能书柜”当前位置的册,这种当前位置清空。 +然后对在书柜内的全部标签盘点一次,设置册记录的当前位置。 +不过需要注意,对在借状态的册的当前位置不要清空。 + +~~~ +需要思考一下,Return() API 还书的时候,是否要给册记录的当前架位至少增添一个问号,表示位置不确定。 +等后面馆员进行盘点以后,这些册的当前位置才能确定下来。 +如果还书的工作人员账户另有规定,明确指定了 currentLocation,则依这个 currentLocation 修改册记录当前位置,这个效果不变。 + +~~~ +需要给书柜做一个随时可以远程调用触发的,盘点当前所有在书柜中的册的功能 + +~~~ +https://www.cnblogs.com/yuejin/p/3506762.html + #region 是否屏蔽CTRL+ALT+DEL + /// + /// 是否屏蔽CTRL+ALT+DEL + /// + /// 1=屏蔽 0=取消屏蔽 + public static void ShieldMissionTask(int i) + { + try + { + RegistryKey key = Registry.CurrentUser; + RegistryKey key1 = key.CreateSubKey(@"Software\Microsoft\Windows\CurrentVersion\Policies\System"); + key1.SetValue("DisableTaskMgr", i, Microsoft.Win32.RegistryValueKind.DWord); + } + catch (Exception ex) + { + throw ex; + } + } + #endregion + +~~~ +https://stackoverflow.com/questions/21351697/wpf-stop-ctrlaltdel-and-windows-button-using-c-sharp + +https://stackoverflow.com/questions/5178916/is-there-any-method-to-disable-logoff-lock-and-taskmanager-in-ctrlaltdel-in-c?rq=1 + diff --git a/dp2SSL/dp2SSL.csproj b/dp2SSL/dp2SSL.csproj index b04f1ca26..8bfda0f7a 100644 --- a/dp2SSL/dp2SSL.csproj +++ b/dp2SSL/dp2SSL.csproj @@ -36,7 +36,7 @@ dp2 V3 true publish.htm - 61 + 67 1.8.63.%2a false true