From 7b98d41e0095218e18113e0a13a198c86b51cb14 Mon Sep 17 00:00:00 2001 From: XieTao Date: Sat, 12 Mar 2016 16:33:39 +0800 Subject: [PATCH 01/10] =?UTF-8?q?=E7=BB=99=20ItemHandoverForm=20=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=20MARC=20=E8=BF=87=E6=BB=A4=E5=99=A8=E5=8A=9F?= =?UTF-8?q?=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DigitalPlatform.LibraryClient/BiblioLoader.cs | 2 +- .../OneInstanceDialog.cs | 1 - .../MongoDb/BuildMongoOperDatabase.cs | 21 +- .../OperLogRecover.cs | 33 ++- DigitalPlatform.Text/DigitalPlatform.Text.cs | 2 - dp2Circulation/AccountBook/AccountBookForm.cs | 121 +++++---- dp2Circulation/Dictionary/RelationDialog.cs | 88 ++++-- .../IO/ImportExportForm.Designer.cs | 86 ++++++ dp2Circulation/IO/ImportExportForm.cs | 19 ++ dp2Circulation/IO/ImportExportForm.resx | 120 ++++++++ .../ItemHandOver/ItemHandoverForm.cs | 257 +++++++++++------- .../ItemHandOver/ScanBarcodeForm.cs | 18 +- dp2Circulation/MainForm/InitialExtension.cs | 5 +- .../Monitor/StartLogRecoverDlg.Designer.cs | 58 ++-- dp2Circulation/Monitor/StartLogRecoverDlg.cs | 16 ++ dp2Circulation/Order/PrintAcceptForm.cs | 201 +++++++------- dp2Circulation/Order/PrintOrderForm.cs | 146 +++++----- dp2Circulation/dp2Circulation.csproj | 11 +- dp2Installer/MainForm.cs | 5 +- dp2Installer/dp2Installer.csproj | 2 +- dp2Installer/opac_app/Browse.aspx.cs | 10 +- dp2LibraryXE/opac_app/Browse.aspx.cs | 10 +- dp2OPAC/Browse.aspx.cs | 10 +- 23 files changed, 851 insertions(+), 391 deletions(-) create mode 100644 dp2Circulation/IO/ImportExportForm.Designer.cs create mode 100644 dp2Circulation/IO/ImportExportForm.cs create mode 100644 dp2Circulation/IO/ImportExportForm.resx diff --git a/DigitalPlatform.LibraryClient/BiblioLoader.cs b/DigitalPlatform.LibraryClient/BiblioLoader.cs index ed444750a..921255bf2 100644 --- a/DigitalPlatform.LibraryClient/BiblioLoader.cs +++ b/DigitalPlatform.LibraryClient/BiblioLoader.cs @@ -109,7 +109,7 @@ public IEnumerator GetEnumerator() if (this.Prompt != null) { MessagePromptEventArgs e = new MessagePromptEventArgs(); - e.MessageText = "获得书目记录时发生错误: " + strError; + e.MessageText = "获得书目记录 '"+strCommand+"' ("+StringUtil.MakePathList(format_list)+") 时发生错误: " + strError; e.Actions = "yes,no,cancel"; this.Prompt(this, e); if (e.ResultAction == "cancel") diff --git a/DigitalPlatform.LibraryServer.Install/OneInstanceDialog.cs b/DigitalPlatform.LibraryServer.Install/OneInstanceDialog.cs index 449b4be1e..b31010397 100644 --- a/DigitalPlatform.LibraryServer.Install/OneInstanceDialog.cs +++ b/DigitalPlatform.LibraryServer.Install/OneInstanceDialog.cs @@ -878,7 +878,6 @@ public static bool MatchLocalString(string strSerialNumber, string strInstanceNa return false; } - private void button_setSerialNumber_Click(object sender, EventArgs e) { string strError = ""; diff --git a/DigitalPlatform.LibraryServer/MongoDb/BuildMongoOperDatabase.cs b/DigitalPlatform.LibraryServer/MongoDb/BuildMongoOperDatabase.cs index 477773c9c..509d477e0 100644 --- a/DigitalPlatform.LibraryServer/MongoDb/BuildMongoOperDatabase.cs +++ b/DigitalPlatform.LibraryServer/MongoDb/BuildMongoOperDatabase.cs @@ -94,15 +94,18 @@ static int ParseLogRecorverStart(string strStart, // 解析通用启动参数 // 格式 /* - * - * clearFirst缺省为false + * + * clearFirst 缺省为 false + * continueWhenError 缺省值为 false * */ public static int ParseLogRecoverParam(string strParam, out bool bClearFirst, + out bool bContinueWhenError, out string strError) { strError = ""; bClearFirst = false; + bContinueWhenError = false; if (String.IsNullOrEmpty(strParam) == true) return 0; @@ -121,6 +124,10 @@ public static int ParseLogRecoverParam(string strParam, bClearFirst = DomUtil.GetBooleanParam(dom.DocumentElement, "clearFirst", false); + // 2016/3/8 + bContinueWhenError = DomUtil.GetBooleanParam(dom.DocumentElement, + "continueWhenError", + false); return 0; } @@ -157,8 +164,11 @@ public override void Worker() // bool bClearFirst = false; + bool bContinueWhenError = false; + nRet = ParseLogRecoverParam(startinfo.Param, out bClearFirst, + out bContinueWhenError, out strError); if (nRet == -1) { @@ -241,6 +251,7 @@ public override void Worker() nRet = DoOneLogFile(strFileName, lStartIndex, lMax, + bContinueWhenError, out strError); if (nRet == -1) goto ERROR1; @@ -306,6 +317,7 @@ long GetOperLogCount(string strDate, int DoOneLogFile(string strFileName, long lStartIndex, long lMax, + bool bContinueWhenError, out string strError) { strError = ""; @@ -381,8 +393,9 @@ int DoOneLogFile(string strFileName, out strError); if (nRet == -1) { - this.AppendResultText("发生错误:" + strError + "\r\n"); - return -1; + this.AppendResultText("*** 做日志记录 " + strFileName + " " + (lIndex).ToString() + " 时发生错误:" + strError + "\r\n"); + if (bContinueWhenError == false) + return -1; } } diff --git a/DigitalPlatform.LibraryServer/OperLogRecover.cs b/DigitalPlatform.LibraryServer/OperLogRecover.cs index 26c8b8e77..d388e9f6b 100644 --- a/DigitalPlatform.LibraryServer/OperLogRecover.cs +++ b/DigitalPlatform.LibraryServer/OperLogRecover.cs @@ -97,20 +97,21 @@ static int ParseLogRecorverStart(string strStart, // 解析通用启动参数 // 格式 /* - * - * recoverLevel缺省为Snapshot - * clearFirst缺省为false - * - * + * + * recoverLevel 缺省为 Snapshot + * clearFirst 缺省为 false + * continueWhenError 缺省值为 false * */ public static int ParseLogRecoverParam(string strParam, out string strRecoverLevel, out bool bClearFirst, + out bool bContinueWhenError, out string strError) { strError = ""; bClearFirst = false; strRecoverLevel = ""; + bContinueWhenError = false; if (String.IsNullOrEmpty(strParam) == true) return 0; @@ -144,6 +145,11 @@ public static int ParseLogRecoverParam(string strParam, else bClearFirst = false; + // 2016/3/8 + bContinueWhenError = DomUtil.GetBooleanParam(dom.DocumentElement, + "continueWhenError", + false); + return 0; } @@ -177,9 +183,12 @@ public override void Worker() // string strRecoverLevel = ""; bool bClearFirst = false; + bool bContinueWhenError = false; + nRet = ParseLogRecoverParam(startinfo.Param, out strRecoverLevel, out bClearFirst, + out bContinueWhenError, out strError); if (nRet == -1) { @@ -279,6 +288,7 @@ public override void Worker() { nRet = DoOneLogFile(strFileName, lStartIndex, + bContinueWhenError, out strError); if (nRet == -1) goto ERROR1; @@ -318,12 +328,13 @@ int IComparer.Compare(Object x, Object y) // parameters: // strFileName 纯文件名 // lStartIndex 开始的记录(从0开始计数) - // return: + // return:DoOperLogRecord( // -1 error // 0 file not found // 1 succeed int DoOneLogFile(string strFileName, long lStartIndex, + bool bContinueWhenError, out string strError) { strError = ""; @@ -407,11 +418,13 @@ int DoOneLogFile(string strFileName, out strError); if (nRet == -1) { - this.AppendResultText("发生错误:" + strError + "\r\n"); + this.AppendResultText("*** 做日志记录 " + strFileName + " " + (lIndex).ToString() + " 时发生错误:" + strError + "\r\n"); + // 2007/6/25 - // 如果为纯逻辑恢复,遇到错误就停下来。这便于进行测试。 - // 若不想停下来,可以选择“逻辑+快照”型 - if (this.RecoverLevel == RecoverLevel.Logic) + // 如果为纯逻辑恢复(并且 bContinueWhenError 为 false),遇到错误就停下来。这便于进行测试。 + // 若不想停下来,可以选择“逻辑+快照”型,或者设置 bContinueWhenError 为 true + if (this.RecoverLevel == RecoverLevel.Logic + && bContinueWhenError == false) return -1; } } diff --git a/DigitalPlatform.Text/DigitalPlatform.Text.cs b/DigitalPlatform.Text/DigitalPlatform.Text.cs index 5e0eaf1e2..02358478c 100644 --- a/DigitalPlatform.Text/DigitalPlatform.Text.cs +++ b/DigitalPlatform.Text/DigitalPlatform.Text.cs @@ -99,8 +99,6 @@ public static string Encrypt(string strSource, string strKey) return Convert.ToBase64String(baOutput); } - - public static string Decrypt(string strSource, string strKey) { byte[] baInput = Convert.FromBase64String(strSource); diff --git a/dp2Circulation/AccountBook/AccountBookForm.cs b/dp2Circulation/AccountBook/AccountBookForm.cs index 2422b1c29..db07c3417 100644 --- a/dp2Circulation/AccountBook/AccountBookForm.cs +++ b/dp2Circulation/AccountBook/AccountBookForm.cs @@ -4182,6 +4182,8 @@ int BuildWordXmlTableLine(PrintOption option, string strMARC = ""; string strOutMarcSyntax = ""; + this.ColumnTable.Clear(); // 清除上一记录处理时残余的内容 + if (this.MarcFilter != null || option.HasEvalue() == true) { @@ -4190,27 +4192,30 @@ int BuildWordXmlTableLine(PrintOption option, // 获得MARC格式书目记录 string strBiblioRecPath = ListViewUtil.GetItemText(item, COLUMN_BIBLIORECPATH); - nRet = GetMarc(strBiblioRecPath, - out strMARC, - out strOutMarcSyntax, - out strError); - if (nRet == -1) - goto ERROR1; - if (this.MarcFilter != null) + if (string.IsNullOrEmpty(strBiblioRecPath) == false) { - this.ColumnTable.Clear(); // 清除上一记录处理时残余的内容 - this.MarcFilter.Host.UiItem = item; // 当前正在处理的 ListViewItem - - // 触发filter中的Record相关动作 - nRet = this.MarcFilter.DoRecord( - null, - strMARC, - strOutMarcSyntax, - nIndex, + nRet = GetMarc(strBiblioRecPath, + out strMARC, + out strOutMarcSyntax, out strError); if (nRet == -1) goto ERROR1; + + if (this.MarcFilter != null) + { + this.MarcFilter.Host.UiItem = item; // 当前正在处理的 ListViewItem + + // 触发filter中的Record相关动作 + nRet = this.MarcFilter.DoRecord( + null, + strMARC, + strOutMarcSyntax, + nIndex, + out strError); + if (nRet == -1) + goto ERROR1; + } } } @@ -4963,6 +4968,8 @@ int BuildTextTableLine(PrintOption option, string strMARC = ""; string strOutMarcSyntax = ""; + this.ColumnTable.Clear(); // 清除上一记录处理时残余的内容 + if (this.MarcFilter != null || option.HasEvalue() == true) { @@ -4971,27 +4978,30 @@ int BuildTextTableLine(PrintOption option, // 获得MARC格式书目记录 string strBiblioRecPath = ListViewUtil.GetItemText(item, COLUMN_BIBLIORECPATH); - nRet = GetMarc(strBiblioRecPath, - out strMARC, - out strOutMarcSyntax, - out strError); - if (nRet == -1) - goto ERROR1; - if (this.MarcFilter != null) + if (string.IsNullOrEmpty(strBiblioRecPath) == false) { - this.ColumnTable.Clear(); // 清除上一记录处理时残余的内容 - this.MarcFilter.Host.UiItem = item; // 当前正在处理的 ListViewItem - - // 触发filter中的Record相关动作 - nRet = this.MarcFilter.DoRecord( - null, - strMARC, - strOutMarcSyntax, - nIndex, + nRet = GetMarc(strBiblioRecPath, + out strMARC, + out strOutMarcSyntax, out strError); if (nRet == -1) goto ERROR1; + + if (this.MarcFilter != null) + { + this.MarcFilter.Host.UiItem = item; // 当前正在处理的 ListViewItem + + // 触发filter中的Record相关动作 + nRet = this.MarcFilter.DoRecord( + null, + strMARC, + strOutMarcSyntax, + nIndex, + out strError); + if (nRet == -1) + goto ERROR1; + } } } @@ -5722,6 +5732,8 @@ int BuildHtmlTableLine(PrintOption option, string strMARC = ""; string strOutMarcSyntax = ""; + this.ColumnTable.Clear(); // 清除上一记录处理时残余的内容 + if (this.MarcFilter != null || option.HasEvalue() == true) { @@ -5732,34 +5744,36 @@ int BuildHtmlTableLine(PrintOption option, // 获得MARC格式书目记录 string strBiblioRecPath = ListViewUtil.GetItemText(item, COLUMN_BIBLIORECPATH); - // TODO: 可以 cache,提高速度 - nRet = GetMarc(strBiblioRecPath, - out strMARC, - out strOutMarcSyntax, - out strError); - if (nRet == -1) - { - strLineContent = strError; - goto END1; - } - - if (this.MarcFilter != null) + if (string.IsNullOrEmpty(strBiblioRecPath) == false) { - this.ColumnTable.Clear(); // 清除上一记录处理时残余的内容 - this.MarcFilter.Host.UiItem = item; // 当前正在处理的 ListViewItem - - // 触发filter中的Record相关动作 - nRet = this.MarcFilter.DoRecord( - null, - strMARC, - strOutMarcSyntax, - nIndex, + // TODO: 可以 cache,提高速度 + nRet = GetMarc(strBiblioRecPath, + out strMARC, + out strOutMarcSyntax, out strError); if (nRet == -1) { strLineContent = strError; goto END1; } + + if (this.MarcFilter != null) + { + this.MarcFilter.Host.UiItem = item; // 当前正在处理的 ListViewItem + + // 触发filter中的Record相关动作 + nRet = this.MarcFilter.DoRecord( + null, + strMARC, + strOutMarcSyntax, + nIndex, + out strError); + if (nRet == -1) + { + strLineContent = strError; + goto END1; + } + } } } @@ -6007,7 +6021,6 @@ string GetColumnContent(ListViewItem item, } } } - catch { return null; // 表示没有这个subitem下标 diff --git a/dp2Circulation/Dictionary/RelationDialog.cs b/dp2Circulation/Dictionary/RelationDialog.cs index 069b4818b..daa883a64 100644 --- a/dp2Circulation/Dictionary/RelationDialog.cs +++ b/dp2Circulation/Dictionary/RelationDialog.cs @@ -258,13 +258,16 @@ public static string BuildDebugInfo(RelationDialog dlg) text.Append(" 源分类号(缩位后的)=[" + control.SourceText + "] \r\n"); text.Append(" 目标分类号(自动选定)=[" + control.TargetText + "] \r\n"); - text.Append(" 命中事项("+info.Rows.Count+"):\r\n"); - int j = 0; - foreach(DpRow row in info.Rows) + if (info.Rows != null) { - text.Append( - " " + (j+1).ToString() + ") " + BuildRowLine(row) + "\r\n"); - j++; + text.Append(" 命中事项(" + info.Rows.Count + "):\r\n"); + int j = 0; + foreach (DpRow row in info.Rows) + { + text.Append( + " " + (j + 1).ToString() + ") " + BuildRowLine(row) + "\r\n"); + j++; + } } i++; @@ -285,6 +288,22 @@ static string BuildRowLine(DpRow row) return text.ToString(); } + static string BuildRowLines(List rows) + { + StringBuilder text = new StringBuilder(); + + text.Append(" 命中事项(" + rows.Count + "):\r\n"); + int j = 0; + foreach (DpRow row in rows) + { + text.Append( + " " + (j + 1).ToString() + ") " + BuildRowLine(row) + "\r\n"); + j++; + } + + return text.ToString(); + } + #endregion int _processing = 0; @@ -1182,27 +1201,47 @@ bool SelectRowByKey(string strText) return false; } + static void VerifyLevelString(string strLevel) + { + int index = Int32.Parse(strLevel); + if (index <= 0) + throw new Exception("strLevel 字符串 '" + strLevel + "' 不合法。应为大于等于 1 的数字"); + } + static List BuildHitCountList(List rows, string strSourceKey) { - List list = new List(); - Hashtable table = new Hashtable(); // strKey --> int - foreach(DpRow row in rows) + try { - string strLevel = row[COLUMN_LEVEL].Text; - int value = 0; - if (table.ContainsKey(strLevel) == true) - value = (int)table[strLevel]; - table[strLevel] = value + 1; - } + List list = new List(); + Hashtable table = new Hashtable(); // strKey --> int + foreach (DpRow row in rows) + { + string strLevel = row[COLUMN_LEVEL].Text; + + // throw new Exception("test"); + VerifyLevelString(strLevel); + + int value = 0; + if (table.ContainsKey(strLevel) == true) + value = (int)table[strLevel]; + table[strLevel] = value + 1; + } + + foreach (string key in table.Keys) + { + int index = Int32.Parse(key); + int value = (int)table[key]; + SetValue(list, index - 1, value); + } - foreach(string key in table.Keys) + return list; + } + catch(Exception ex) { - int index = Int32.Parse(key); - int value = (int)table[key]; - SetValue(list, index-1, value); + throw new Exception("BuildHitCountList() 出现异常: " + + "strSourceKey=["+strSourceKey+"]" + + BuildRowLines(rows), ex); } - - return list; } static void SetValue(List list, int index, int value) @@ -1365,6 +1404,13 @@ int SearchAll(string strStyle, return -2; return nCount; } +#if NO + catch (Exception ex) + { + string strContent = BuildDebugInfo(this); + throw new Exception(strContent, ex); + } +#endif finally { _stop.EndLoop(); diff --git a/dp2Circulation/IO/ImportExportForm.Designer.cs b/dp2Circulation/IO/ImportExportForm.Designer.cs new file mode 100644 index 000000000..40325f54b --- /dev/null +++ b/dp2Circulation/IO/ImportExportForm.Designer.cs @@ -0,0 +1,86 @@ +namespace dp2Circulation +{ + partial class ImportExportForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.tabControl1 = new System.Windows.Forms.TabControl(); + this.tabPage1 = new System.Windows.Forms.TabPage(); + this.tabPage2 = new System.Windows.Forms.TabPage(); + this.tabControl1.SuspendLayout(); + this.SuspendLayout(); + // + // tabControl1 + // + this.tabControl1.Controls.Add(this.tabPage1); + this.tabControl1.Controls.Add(this.tabPage2); + this.tabControl1.Location = new System.Drawing.Point(13, 13); + this.tabControl1.Name = "tabControl1"; + this.tabControl1.SelectedIndex = 0; + this.tabControl1.Size = new System.Drawing.Size(443, 309); + this.tabControl1.TabIndex = 0; + // + // tabPage1 + // + this.tabPage1.Location = new System.Drawing.Point(4, 22); + this.tabPage1.Name = "tabPage1"; + this.tabPage1.Padding = new System.Windows.Forms.Padding(3); + this.tabPage1.Size = new System.Drawing.Size(435, 283); + this.tabPage1.TabIndex = 0; + this.tabPage1.Text = "tabPage1"; + this.tabPage1.UseVisualStyleBackColor = true; + // + // tabPage2 + // + this.tabPage2.Location = new System.Drawing.Point(4, 22); + this.tabPage2.Name = "tabPage2"; + this.tabPage2.Padding = new System.Windows.Forms.Padding(3); + this.tabPage2.Size = new System.Drawing.Size(192, 74); + this.tabPage2.TabIndex = 1; + this.tabPage2.Text = "tabPage2"; + this.tabPage2.UseVisualStyleBackColor = true; + // + // ImportExportForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(468, 334); + this.Controls.Add(this.tabControl1); + this.Name = "ImportExportForm"; + this.Text = "ImportExportForm"; + this.tabControl1.ResumeLayout(false); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.TabControl tabControl1; + private System.Windows.Forms.TabPage tabPage1; + private System.Windows.Forms.TabPage tabPage2; + } +} \ No newline at end of file diff --git a/dp2Circulation/IO/ImportExportForm.cs b/dp2Circulation/IO/ImportExportForm.cs new file mode 100644 index 000000000..2cce6abec --- /dev/null +++ b/dp2Circulation/IO/ImportExportForm.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Windows.Forms; + +namespace dp2Circulation +{ + public partial class ImportExportForm : Form + { + public ImportExportForm() + { + InitializeComponent(); + } + } +} diff --git a/dp2Circulation/IO/ImportExportForm.resx b/dp2Circulation/IO/ImportExportForm.resx new file mode 100644 index 000000000..1af7de150 --- /dev/null +++ b/dp2Circulation/IO/ImportExportForm.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/dp2Circulation/ItemHandOver/ItemHandoverForm.cs b/dp2Circulation/ItemHandOver/ItemHandoverForm.cs index 99edb223b..a5c88ac1c 100644 --- a/dp2Circulation/ItemHandOver/ItemHandoverForm.cs +++ b/dp2Circulation/ItemHandOver/ItemHandoverForm.cs @@ -243,7 +243,7 @@ private void ItemHandoverForm_Load(object sender, EventArgs e) "location_string", ""); - this.checkBox_verify_autoUppercaseBarcode.Checked = + this.checkBox_verify_autoUppercaseBarcode.Checked = this.MainForm.AppInfo.GetBoolean( "itemhandoverform", "auto_uppercase_barcode", @@ -252,7 +252,7 @@ private void ItemHandoverForm_Load(object sender, EventArgs e) API.PostMessage(this.Handle, WM_LOADSIZE, 0, 0); } - private void ItemHandoverForm_FormClosing(object sender, + private void ItemHandoverForm_FormClosing(object sender, FormClosingEventArgs e) { #if NO @@ -334,7 +334,8 @@ private void ItemHandoverForm_FormClosed(object sender, FormClosedEventArgs e) SaveSize(); } - /*public*/ void LoadSize() + /*public*/ + void LoadSize() { #if NO // 设置窗口尺寸状态 @@ -375,7 +376,8 @@ private void ItemHandoverForm_FormClosed(object sender, FormClosedEventArgs e) "splitContainer_inandoutof_ratio"); } - /*public*/ void SaveSize() + /*public*/ + void SaveSize() { if (this.MainForm != null && this.MainForm.AppInfo != null) { @@ -443,16 +445,14 @@ public override void EnableControls(bool bEnable) this.button_verify_load.Enabled = bEnable; this.checkBox_verify_autoUppercaseBarcode.Enabled = bEnable; - // print page this.button_print_option.Enabled = bEnable; this.button_print_printCheckedList.Enabled = bEnable; this.button_print_printNormalList.Enabled = bEnable; - } - /// + /// /// 清除列表中现存的内容,准备装入新内容 /// public override void ClearBefore() @@ -468,7 +468,6 @@ public override void ClearBefore() SortColumns.ClearColumnSortDisplay(this.listView_outof.Columns); } - // 根据条码号文件装载 private void button_load_loadFromBarcodeFile_Click(object sender, EventArgs e) { @@ -841,7 +840,6 @@ internal override int DoLoadRecords(List lines, this.listView_in.BeginUpdate(); try { - for (int i = 0; i < infos.Count; i++) { if (stop != null) @@ -862,7 +860,6 @@ internal override int DoLoadRecords(List lines, } // stop.SetMessage("正在装入路径 " + strLine + " 对应的记录..."); - string strOutputItemRecPath = ""; ListViewItem item = null; @@ -950,7 +947,6 @@ void CreateColumnHeader(ListView list) // 2009/10/27 ColumnHeader columnHeader_targetRecpath = new ColumnHeader(); - list.Columns.Clear(); list.Columns.AddRange(new ColumnHeader[] { @@ -973,7 +969,6 @@ void CreateColumnHeader(ListView list) columnHeader_accessno, columnHeader_targetRecpath}); - // // columnHeader_barcode // @@ -1521,7 +1516,7 @@ static void SetItemColor(ListViewItem item, } internal override void SetListViewItemText(XmlDocument dom, - byte [] baTimestamp, + byte[] baTimestamp, bool bSetBarcodeColumn, string strRecPath, string strBiblioRecPath, @@ -1653,8 +1648,6 @@ internal override ListViewItem AddToListView(ListView list, return item; } - - void SetNextButtonEnable() { string strError = ""; @@ -1718,7 +1711,7 @@ void SetNextButtonEnable() if (nNeedMoveCount > 0) { this.button_move_moveAll.Enabled = true; - this.button_move_moveAll.Text = "转移到目标库 ["+nNeedMoveCount.ToString()+"] (&M)..."; + this.button_move_moveAll.Text = "转移到目标库 [" + nNeedMoveCount.ToString() + "] (&M)..."; } else { @@ -1748,7 +1741,7 @@ void SetNextButtonEnable() if (nProcessiingCount > 0) { this.button_move_changeStateAll.Enabled = true; - this.button_move_changeStateAll.Text = "清除“加工中”状态 ["+nProcessiingCount.ToString()+"] (&C)..."; + this.button_move_changeStateAll.Text = "清除“加工中”状态 [" + nProcessiingCount.ToString() + "] (&C)..."; } else { @@ -1760,7 +1753,7 @@ void SetNextButtonEnable() if (this.listView_in.Items.Count > 0) { this.button_move_notifyReader.Enabled = true; - this.button_move_notifyReader.Text = "通知荐购读者 [" + this.listView_in.Items.Count .ToString()+ "] (&N)..."; + this.button_move_notifyReader.Text = "通知荐购读者 [" + this.listView_in.Items.Count.ToString() + "] (&N)..."; } else { @@ -1842,13 +1835,13 @@ int ReportLoadState(out string strError) if (item.ImageIndex == TYPE_ERROR) nRedCount++; - else + else nWhiteCount++; } if (nRedCount != 0) { - strError = "列表中有 " +nRedCount+ " 个错误事项(红色行)。请修改数据后重新装载。"; + strError = "列表中有 " + nRedCount + " 个错误事项(红色行)。请修改数据后重新装载。"; return 2; } @@ -1892,7 +1885,7 @@ bool ReportVerifyState(out string strError) && this.listView_outof.Items.Count == 0) return true; - strError = "验证尚未完成。\r\n\r\n列表中有:\r\n已验证事项(绿色) "+nGreenCount.ToString()+" 个\r\n错误事项(红色) " +nRedCount.ToString()+ "个\r\n未验证事项(白色) " +nWhiteCount.ToString()+ "个\r\n集合外事项(位于下方列表内) " +this.listView_outof.Items.Count+ "个\r\n\r\n(只有全部事项都为已验证状态(绿色),才表明验证已经完成)"; + strError = "验证尚未完成。\r\n\r\n列表中有:\r\n已验证事项(绿色) " + nGreenCount.ToString() + " 个\r\n错误事项(红色) " + nRedCount.ToString() + "个\r\n未验证事项(白色) " + nWhiteCount.ToString() + "个\r\n集合外事项(位于下方列表内) " + this.listView_outof.Items.Count + "个\r\n\r\n(只有全部事项都为已验证状态(绿色),才表明验证已经完成)"; return false; } @@ -1962,8 +1955,8 @@ private void button_verify_load_Click(object sender, EventArgs e) stop.OnStop += new StopEventHandler(this.DoStop); stop.Initial("正在装载册 " - +this.textBox_verify_itemBarcode.Text - +" ..."); + + this.textBox_verify_itemBarcode.Text + + " ..."); stop.BeginLoop(); try @@ -2009,7 +2002,7 @@ private void button_verify_load_Click(object sender, EventArgs e) if (this.listView_outof.Items.Count != 0) this.listView_outof.EnsureVisible(this.listView_outof.Items.Count - 1); - strError = "条码为 " + strError = "条码为 " + this.textBox_verify_itemBarcode.Text + " 的册记录不在集合内。已加入到集合外列表。"; goto ERROR1; @@ -2025,7 +2018,7 @@ private void button_verify_load_Click(object sender, EventArgs e) { strError = "条码 " + this.textBox_verify_itemBarcode.Text - +" 所对应的事项虽然已经包含在集合内,但数据有误,无法通过验证。\r\n\r\n请对该条码相关数据进行修改,然后刷新事项,并重新扫入条码进行验证。"; + + " 所对应的事项虽然已经包含在集合内,但数据有误,无法通过验证。\r\n\r\n请对该条码相关数据进行修改,然后刷新事项,并重新扫入条码进行验证。"; // 选定该事项 item.Selected = true; // 将事项滚入视野 @@ -2135,7 +2128,7 @@ private void button_print_printCheckedList_Click(object sender, EventArgs e) if (bOK == false) { - string strWarning = strError + "\r\n\r\n" + string strWarning = strError + "\r\n\r\n" + "是否仍要打印已验证的部分(绿色行)?"; DialogResult result = MessageBox.Show(this, strWarning, @@ -2165,7 +2158,6 @@ private void button_print_printCheckedList_Click(object sender, EventArgs e) } PrintList("已验证清单", items); - return; ERROR1: MessageBox.Show(this, strError); @@ -2300,11 +2292,8 @@ int BuildHtml( MessageBox.Show(this, "由于当前打印用到了 “种价格”列,为保证打印结果的准确,程序自动按 ‘种记录路径’ 列对全部列表事项进行一次自动排序。\r\n\r\n为避免这里的自动排序,可在打印前用鼠标左键点栏标题进行符合自己意愿的排序,只要最后一次点的是‘种记录路径’栏标题即可。"); ForceSortColumnsIn(COLUMN_BIBLIORECPATH); } - - } - // 计算出页总数 int nTablePageCount = items.Count / option.LinesPerPage; if ((items.Count % option.LinesPerPage) != 0) @@ -2346,7 +2335,6 @@ int BuildHtml( macro_table["%recpathfilename%"] = Path.GetFileName(this.RecPathFilePath); } - filenames = new List(); // 每页一个文件,这个数组存放了所有文件名 string strFileNamePrefix = this.MainForm.DataDir + "\\~itemhandover"; @@ -2473,7 +2461,6 @@ int BuildHtml( StreamUtil.WriteText(strFileName, "
接受者:
"); - BuildPageBottom(option, macro_table, strFileName, @@ -2482,6 +2469,14 @@ int BuildHtml( } + string strMarcFilterFilePath = option.GetTemplatePageFilePath("MARC过滤器"); + if (String.IsNullOrEmpty(strMarcFilterFilePath) == false) + { + int nRet = PrepareMarcFilter(strMarcFilterFilePath, out strError); + if (nRet == -1) + return -1; + } + // 表格页循环 for (int i = 0; i < nTablePageCount; i++) { @@ -2509,14 +2504,6 @@ int BuildHtml( true); } - /* - for (int i = 0; i < this.listView_in.Items.Count; i++) - { - - } - * */ - - return 0; } @@ -2570,7 +2557,7 @@ int BuildPageTop(PrintOption option, StreamUtil.WriteText(strFileName, "" + strLink + ""); - + // 页眉 string strPageHeaderText = option.PageHeader; @@ -2603,7 +2590,6 @@ int BuildPageTop(PrintOption option, if (bOutputTable == true) { - // 表格开始 StreamUtil.WriteText(strFileName, ""); // border='1' @@ -2637,12 +2623,12 @@ int BuildPageTop(PrintOption option, } // 汇总种价格。假定nIndex处在切换行(同一种内最后一行) - static decimal ComputeBiblioPrice(List items, + decimal ComputeBiblioPrice(List items, int nIndex) { decimal total = 0; string strBiblioRecPath = GetColumnContent(items[nIndex], "biblioRecpath"); - for (int i = nIndex; i>=0; i--) + for (int i = nIndex; i >= 0; i--) { ListViewItem item = items[i]; @@ -2691,54 +2677,124 @@ int BuildTableLine(PrintOption option, { // 栏目内容 string strLineContent = ""; + int nRet = 0; bool bBiblioSumLine = false; // 是否为种的最后一行(汇总行) + int nIndex = nPage * option.LinesPerPage + nLine; + + if (nIndex >= items.Count) + goto END1; + + ListViewItem item = items[nIndex]; + + string strMARC = ""; + string strOutMarcSyntax = ""; + + this.ColumnTable.Clear(); // 清除上一记录处理时残余的内容 + + if (this.MarcFilter != null + || option.HasEvalue() == true) + { + string strError = ""; + + // TODO: 有错误要明显报出来,否则容易在打印出来后才发现,就晚了 + + // 获得MARC格式书目记录 + string strBiblioRecPath = ListViewUtil.GetItemText(item, COLUMN_BIBLIORECPATH); + + if (string.IsNullOrEmpty(strBiblioRecPath) == false) + { + // TODO: 可以 cache,提高速度 + nRet = GetMarc(strBiblioRecPath, + out strMARC, + out strOutMarcSyntax, + out strError); + if (nRet == -1) + { + strLineContent = strError; + goto END1; + } + + if (this.MarcFilter != null) + { + this.MarcFilter.Host.UiItem = item; // 当前正在处理的 ListViewItem + + // 触发filter中的Record相关动作 + nRet = this.MarcFilter.DoRecord( + null, + strMARC, + strOutMarcSyntax, + nIndex, + out strError); + if (nRet == -1) + { + strLineContent = strError; + goto END1; + } + } + } + } + for (int i = 0; i < option.Columns.Count; i++) { Column column = option.Columns[i]; +#if NO int nIndex = nPage * option.LinesPerPage + nLine; if (nIndex >= items.Count) break; ListViewItem item = items[nIndex]; +#endif - string strContent = GetColumnContent(item, - column.Name); - - if (strContent == "!!!#") - strContent = ((nPage * option.LinesPerPage) + nLine + 1).ToString(); + string strContent = ""; - if (strContent == "!!!biblioPrice") + if (string.IsNullOrEmpty(column.Evalue) == false) { - // 看看自己是不是处在切换边沿 - string strCurLineBiblioRecPath = GetColumnContent(item, "biblioRecpath"); + Jurassic.ScriptEngine engine = new Jurassic.ScriptEngine(); + engine.EnableExposedClrTypes = true; + engine.SetGlobalValue("syntax", strOutMarcSyntax); + engine.SetGlobalValue("biblio", new MarcRecord(strMARC)); + strContent = engine.Evaluate(column.Evalue).ToString(); + } + else + { + strContent = GetColumnContent(item, + column.Name); - string strNextLineBiblioRecPath = ""; + if (strContent == "!!!#") + strContent = ((nPage * option.LinesPerPage) + nLine + 1).ToString(); - if (nIndex < items.Count - 1) + if (strContent == "!!!biblioPrice") { - ListViewItem next_item = items[nIndex + 1]; - strNextLineBiblioRecPath = GetColumnContent(next_item, "biblioRecpath"); - } + // 看看自己是不是处在切换边沿 + string strCurLineBiblioRecPath = GetColumnContent(item, "biblioRecpath"); - if (strCurLineBiblioRecPath != strNextLineBiblioRecPath) - { - // 处在切换边沿 + string strNextLineBiblioRecPath = ""; - // 汇总前面的册价格 - strContent = ComputeBiblioPrice(items, nIndex).ToString(); - bBiblioSumLine = true; - } - else - { - // 其他普通行 - strContent = " "; - } + if (nIndex < items.Count - 1) + { + ListViewItem next_item = items[nIndex + 1]; + strNextLineBiblioRecPath = GetColumnContent(next_item, "biblioRecpath"); + } + + if (strCurLineBiblioRecPath != strNextLineBiblioRecPath) + { + // 处在切换边沿 + // 汇总前面的册价格 + strContent = ComputeBiblioPrice(items, nIndex).ToString(); + bBiblioSumLine = true; + } + else + { + // 其他普通行 + strContent = " "; + } + } } // 截断字符串 @@ -2760,6 +2816,8 @@ int BuildTableLine(PrintOption option, ""; } + END1: + if (bBiblioSumLine == false) { StreamUtil.WriteText(strFileName, @@ -2780,9 +2838,8 @@ int BuildTableLine(PrintOption option, return 0; } - // 获得栏目内容 - static string GetColumnContent(ListViewItem item, + string GetColumnContent(ListViewItem item, string strColumnName) { // 去掉"-- ?????"部分 @@ -2795,6 +2852,20 @@ static string GetColumnContent(ListViewItem item, string strText = StringUtil.GetLeft(strColumnName); + // 2009/10/8 + // 要求ColumnTable值 + if (strText.Length > 0 && strText[0] == '@') + { + strText = strText.Substring(1); + + /* + if (this.ColumnTable.Contains(strText) == false) + return "error:列 '" + strText + "' 在ColumnTable中没有找到"; + * */ + + return (string)this.ColumnTable[strText]; + } + try { @@ -2852,10 +2923,14 @@ static string GetColumnContent(ListViewItem item, case "种价格": return "!!!biblioPrice"; // 特殊值,表示种价格 default: - return "undefined column"; + { + if (this.ColumnTable.Contains(strText) == false) + return "未知栏目 '" + strText + "'"; + + return (string)this.ColumnTable[strText]; + } } } - catch { return null; // 表示没有这个subitem下标 @@ -3527,7 +3602,7 @@ static void SetGroupBackcolor( { string strPrevText = ""; bool bDark = false; - for(int i=0;i GetSelectedItems(ListView list) @@ -4135,7 +4210,7 @@ void menu_refreshSelected_Click(object sender, EventArgs e) RefreshLines(COLUMN_RECPATH, items, true, - new string[] { "summary", "@isbnissn", "targetrecpath"}); + new string[] { "summary", "@isbnissn", "targetrecpath" }); if (this.tabControl_main.SelectedTab == this.tabPage_verify) { SetVerifyPageNextButtonEnabled(); @@ -4182,7 +4257,7 @@ void menu_deleteSelected_Click(object sender, EventArgs e) } DialogResult result = MessageBox.Show(this, -"确实要移除选定的 "+items.Count.ToString()+" 个事项?", +"确实要移除选定的 " + items.Count.ToString() + " 个事项?", this.FormCaption, MessageBoxButtons.YesNo, MessageBoxIcon.Question, @@ -4477,7 +4552,7 @@ private void listView_outof_MouseUp(object sender, MouseEventArgs e) contextMenu.MenuItems.Add(menuItem); - contextMenu.Show(this.listView_outof, new Point(e.X, e.Y)); + contextMenu.Show(this.listView_outof, new Point(e.X, e.Y)); } private void ItemHandoverForm_Activated(object sender, EventArgs e) @@ -4583,7 +4658,7 @@ int DoMove( nMovedCount++; item.Selected = true; - stop.SetProgressValue(i+1); + stop.SetProgressValue(i + 1); } } finally @@ -4746,7 +4821,7 @@ int CopyOneBiblioRecord(string strSourceBiblioRecPath, out strError); if (nRet == -1) { - strError = "将记录 '"+strTargetBiblioRecPath+"' 的XML转换到MARC记录时出错: " + strError; + strError = "将记录 '" + strTargetBiblioRecPath + "' 的XML转换到MARC记录时出错: " + strError; return -1; } @@ -4781,7 +4856,7 @@ int CopyOneBiblioRecord(string strSourceBiblioRecPath, string strTargetBiblioDbName = Global.GetDbName(strTargetBiblioRecPath); if (String.IsNullOrEmpty(strTargetBiblioDbName) == true) { - strError = "从路径 '"+strTargetBiblioRecPath+"' 中获得数据库名时出错"; + strError = "从路径 '" + strTargetBiblioRecPath + "' 中获得数据库名时出错"; return -1; } @@ -4791,7 +4866,7 @@ int CopyOneBiblioRecord(string strSourceBiblioRecPath, if (strSourceSyntax.ToLower() != strTargetSyntax.ToLower()) { - strError = "源书目记录 '"+strSourceBiblioRecPath+"' 所在库的格式 '"+strSourceSyntax+"' 和 目标数据记录 '"+strTargetBiblioRecPath+"' 所在库的格式 '"+strTargetSyntax+"' 不同"; + strError = "源书目记录 '" + strSourceBiblioRecPath + "' 所在库的格式 '" + strSourceSyntax + "' 和 目标数据记录 '" + strTargetBiblioRecPath + "' 所在库的格式 '" + strTargetSyntax + "' 不同"; return -1; } @@ -4805,7 +4880,7 @@ int CopyOneBiblioRecord(string strSourceBiblioRecPath, out strError); if (nRet == -1) { - strError = "将记录 '"+strTargetBiblioRecPath+"' 的XML转换到MARC记录时出错: " + strError; + strError = "将记录 '" + strTargetBiblioRecPath + "' 的XML转换到MARC记录时出错: " + strError; return -1; } @@ -5264,14 +5339,14 @@ int MergeTwoXml( if (source_node.NamespaceURI != strNamespaceURI) continue; - XmlNode new_node = source.CreateElement(strPrefix, + XmlNode new_node = source.CreateElement(strPrefix, source_node.LocalName, strNamespaceURI); source.DocumentElement.AppendChild(new_node); DomUtil.SetElementOuterXml(new_node, source_node.OuterXml); } - + return 0; } @@ -5488,7 +5563,7 @@ int MoveOneRecord(ListViewItem item, out strError); if (lRet == -1) return -1; - + if (errorinfos != null && errorinfos.Length > 0) { int nErrorCount = 0; @@ -5606,7 +5681,7 @@ private void button_move_changeStateAll_Click(object sender, EventArgs e) int nClearCount = ClearProcessingState(items); ListViewUtil.ClearSelection(this.listView_in); // 清除全部选择标志 - + // TODO: 记忆下所有的书目记录路径,然后去重。对这些书目记录通知推荐者 @@ -5927,7 +6002,7 @@ int SaveOneBatchOrders(List entity_list, strErrorText += "事项 '" + ListViewUtil.GetItemText(item, COLUMN_RECPATH) + "' 在保存过程中发生错误: " + errorinfo.ErrorInfo; } - ListViewUtil.ChangeItemText(item, + ListViewUtil.ChangeItemText(item, COLUMN_ERRORINFO, errorinfo.ErrorInfo); SetItemColor(item, TYPE_ERROR); @@ -5971,7 +6046,7 @@ static int GetChangedCount(List items) if (data == null) // 2015/9/15 continue; if (data.Changed == true) - nCount ++; + nCount++; } return nCount; @@ -6016,7 +6091,7 @@ private void button_move_notifyReader_Click(object sender, EventArgs e) if (nRet == -1) goto ERROR1; - MessageBox.Show(this, "成功通知书目记录 "+nNotifiedCount+" 个"); + MessageBox.Show(this, "成功通知书目记录 " + nNotifiedCount + " 个"); return; ERROR1: this.SetNextButtonEnable(); @@ -6367,7 +6442,7 @@ void _scanBarcodeForm_BarcodeScaned(object sender, ScanedEventArgs e) { Console.Beep(); ListViewUtil.SelectLine(dup, true); - MessageBox.Show(this, "您扫入的册条码号 ‘"+e.Barcode+"’ 在列表中已经存在了,请注意不要重复扫入"); + MessageBox.Show(this, "您扫入的册条码号 ‘" + e.Barcode + "’ 在列表中已经存在了,请注意不要重复扫入"); this._scanBarcodeForm.Activate(); return; } diff --git a/dp2Circulation/ItemHandOver/ScanBarcodeForm.cs b/dp2Circulation/ItemHandOver/ScanBarcodeForm.cs index d91ac3c7d..d10995f9a 100644 --- a/dp2Circulation/ItemHandOver/ScanBarcodeForm.cs +++ b/dp2Circulation/ItemHandOver/ScanBarcodeForm.cs @@ -56,9 +56,25 @@ private void ScanBarcodeForm_Activated(object sender, EventArgs e) this.Opacity = 1.0; } + /* +System.ComponentModel.Win32Exception (0x80004005): 参数错误。 + 在 System.Windows.Forms.Form.UpdateLayered() + 在 System.Windows.Forms.Form.set_Opacity(Double value) + 在 dp2Circulation.ScanBarcodeForm.ScanBarcodeForm_Deactivate(Object sender, EventArgs e) 位置 c:\dp2-master\dp2\dp2Circulation\ItemHandOver\ScanBarcodeForm.cs:行号 61 + 在 System.Windows.Forms.Form.OnDeactivate(EventArgs e) + 在 System.Windows.Forms.Form.set_Active(Boolean value) + 在 System.Windows.Forms.Form.WmActivate(Message& m) + 在 System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam) + * */ private void ScanBarcodeForm_Deactivate(object sender, EventArgs e) { - this.Opacity = 0.8; + try + { + this.Opacity = 0.8; + } + catch + { + } } } diff --git a/dp2Circulation/MainForm/InitialExtension.cs b/dp2Circulation/MainForm/InitialExtension.cs index a4f427f39..ab120449d 100644 --- a/dp2Circulation/MainForm/InitialExtension.cs +++ b/dp2Circulation/MainForm/InitialExtension.cs @@ -1524,8 +1524,11 @@ void ClearBackground() if (ApplicationDeployment.IsNetworkDeployed == false) strBodyClass = " class='green' "; + string strHead = ""; + Global.WriteHtml(m_backgroundForm.WebBrowser, - "" + strLink + ""); + // "" + strHead + strLink + ""); } catch (Exception ex) { diff --git a/dp2Circulation/Monitor/StartLogRecoverDlg.Designer.cs b/dp2Circulation/Monitor/StartLogRecoverDlg.Designer.cs index 6a84c6d0c..078d41da6 100644 --- a/dp2Circulation/Monitor/StartLogRecoverDlg.Designer.cs +++ b/dp2Circulation/Monitor/StartLogRecoverDlg.Designer.cs @@ -35,11 +35,12 @@ private void InitializeComponent() this.textBox_startIndex = new System.Windows.Forms.TextBox(); this.label2 = new System.Windows.Forms.Label(); this.textBox_startFileName = new System.Windows.Forms.TextBox(); - this.label3 = new System.Windows.Forms.Label(); + this.label_recoverLevel = new System.Windows.Forms.Label(); this.comboBox_recoverLevel = new System.Windows.Forms.ComboBox(); this.checkBox_clearBefore = new System.Windows.Forms.CheckBox(); this.button_OK = new System.Windows.Forms.Button(); this.button_Cancel = new System.Windows.Forms.Button(); + this.checkBox_continueWhenError = new System.Windows.Forms.CheckBox(); this.groupBox1.SuspendLayout(); this.SuspendLayout(); // @@ -63,9 +64,9 @@ private void InitializeComponent() this.groupBox1.Controls.Add(this.textBox_startFileName); this.groupBox1.Controls.Add(this.label1); this.groupBox1.Location = new System.Drawing.Point(9, 10); - this.groupBox1.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2); + this.groupBox1.Margin = new System.Windows.Forms.Padding(2); this.groupBox1.Name = "groupBox1"; - this.groupBox1.Padding = new System.Windows.Forms.Padding(2, 2, 2, 2); + this.groupBox1.Padding = new System.Windows.Forms.Padding(2); this.groupBox1.Size = new System.Drawing.Size(308, 103); this.groupBox1.TabIndex = 0; this.groupBox1.TabStop = false; @@ -86,7 +87,7 @@ private void InitializeComponent() this.textBox_startIndex.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.textBox_startIndex.Location = new System.Drawing.Point(102, 66); - this.textBox_startIndex.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2); + this.textBox_startIndex.Margin = new System.Windows.Forms.Padding(2); this.textBox_startIndex.Name = "textBox_startIndex"; this.textBox_startIndex.Size = new System.Drawing.Size(114, 21); this.textBox_startIndex.TabIndex = 4; @@ -106,20 +107,20 @@ private void InitializeComponent() this.textBox_startFileName.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.textBox_startFileName.Location = new System.Drawing.Point(102, 22); - this.textBox_startFileName.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2); + this.textBox_startFileName.Margin = new System.Windows.Forms.Padding(2); this.textBox_startFileName.Name = "textBox_startFileName"; this.textBox_startFileName.Size = new System.Drawing.Size(146, 21); this.textBox_startFileName.TabIndex = 1; // - // label3 + // label_recoverLevel // - this.label3.AutoSize = true; - this.label3.Location = new System.Drawing.Point(7, 146); - this.label3.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0); - this.label3.Name = "label3"; - this.label3.Size = new System.Drawing.Size(77, 12); - this.label3.TabIndex = 1; - this.label3.Text = "ָ(&L):"; + this.label_recoverLevel.AutoSize = true; + this.label_recoverLevel.Location = new System.Drawing.Point(7, 146); + this.label_recoverLevel.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0); + this.label_recoverLevel.Name = "label_recoverLevel"; + this.label_recoverLevel.Size = new System.Drawing.Size(77, 12); + this.label_recoverLevel.TabIndex = 1; + this.label_recoverLevel.Text = "ָ(&L):"; // // comboBox_recoverLevel // @@ -132,7 +133,7 @@ private void InitializeComponent() "Snapshot()", "Robust(ݴ)"}); this.comboBox_recoverLevel.Location = new System.Drawing.Point(111, 144); - this.comboBox_recoverLevel.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2); + this.comboBox_recoverLevel.Margin = new System.Windows.Forms.Padding(2); this.comboBox_recoverLevel.Name = "comboBox_recoverLevel"; this.comboBox_recoverLevel.Size = new System.Drawing.Size(207, 20); this.comboBox_recoverLevel.TabIndex = 2; @@ -142,7 +143,7 @@ private void InitializeComponent() // this.checkBox_clearBefore.AutoSize = true; this.checkBox_clearBefore.Location = new System.Drawing.Point(9, 178); - this.checkBox_clearBefore.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2); + this.checkBox_clearBefore.Margin = new System.Windows.Forms.Padding(2); this.checkBox_clearBefore.Name = "checkBox_clearBefore"; this.checkBox_clearBefore.Size = new System.Drawing.Size(192, 16); this.checkBox_clearBefore.TabIndex = 3; @@ -153,10 +154,10 @@ private void InitializeComponent() // this.button_OK.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); this.button_OK.Location = new System.Drawing.Point(200, 247); - this.button_OK.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2); + this.button_OK.Margin = new System.Windows.Forms.Padding(2); this.button_OK.Name = "button_OK"; this.button_OK.Size = new System.Drawing.Size(56, 22); - this.button_OK.TabIndex = 4; + this.button_OK.TabIndex = 5; this.button_OK.Text = "ȷ"; this.button_OK.UseVisualStyleBackColor = true; this.button_OK.Click += new System.EventHandler(this.button_OK_Click); @@ -166,14 +167,25 @@ private void InitializeComponent() this.button_Cancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); this.button_Cancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; this.button_Cancel.Location = new System.Drawing.Point(261, 247); - this.button_Cancel.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2); + this.button_Cancel.Margin = new System.Windows.Forms.Padding(2); this.button_Cancel.Name = "button_Cancel"; this.button_Cancel.Size = new System.Drawing.Size(56, 22); - this.button_Cancel.TabIndex = 5; + this.button_Cancel.TabIndex = 6; this.button_Cancel.Text = "ȡ"; this.button_Cancel.UseVisualStyleBackColor = true; this.button_Cancel.Click += new System.EventHandler(this.button_Cancel_Click); // + // checkBox_continueWhenError + // + this.checkBox_continueWhenError.AutoSize = true; + this.checkBox_continueWhenError.Location = new System.Drawing.Point(9, 198); + this.checkBox_continueWhenError.Margin = new System.Windows.Forms.Padding(2); + this.checkBox_continueWhenError.Name = "checkBox_continueWhenError"; + this.checkBox_continueWhenError.Size = new System.Drawing.Size(138, 16); + this.checkBox_continueWhenError.TabIndex = 4; + this.checkBox_continueWhenError.Text = "(&T)"; + this.checkBox_continueWhenError.UseVisualStyleBackColor = true; + // // StartLogRecoverDlg // this.AcceptButton = this.button_OK; @@ -181,14 +193,15 @@ private void InitializeComponent() this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.CancelButton = this.button_Cancel; this.ClientSize = new System.Drawing.Size(326, 279); + this.Controls.Add(this.checkBox_continueWhenError); this.Controls.Add(this.button_Cancel); this.Controls.Add(this.button_OK); this.Controls.Add(this.checkBox_clearBefore); this.Controls.Add(this.comboBox_recoverLevel); - this.Controls.Add(this.label3); + this.Controls.Add(this.label_recoverLevel); this.Controls.Add(this.groupBox1); this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); - this.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2); + this.Margin = new System.Windows.Forms.Padding(2); this.Name = "StartLogRecoverDlg"; this.ShowInTaskbar = false; this.Text = " ־ָ "; @@ -208,11 +221,12 @@ private void InitializeComponent() private System.Windows.Forms.TextBox textBox_startFileName; private System.Windows.Forms.TextBox textBox_startIndex; private System.Windows.Forms.Label label2; - private System.Windows.Forms.Label label3; + private System.Windows.Forms.Label label_recoverLevel; private System.Windows.Forms.ComboBox comboBox_recoverLevel; private System.Windows.Forms.CheckBox checkBox_clearBefore; private System.Windows.Forms.Button button_OK; private System.Windows.Forms.Button button_Cancel; private System.Windows.Forms.Label label4; + private System.Windows.Forms.CheckBox checkBox_continueWhenError; } } \ No newline at end of file diff --git a/dp2Circulation/Monitor/StartLogRecoverDlg.cs b/dp2Circulation/Monitor/StartLogRecoverDlg.cs index 2dd4149db..62e245408 100644 --- a/dp2Circulation/Monitor/StartLogRecoverDlg.cs +++ b/dp2Circulation/Monitor/StartLogRecoverDlg.cs @@ -32,6 +32,7 @@ public string TaskName if (value == "创建 MongoDB 日志库") { this.comboBox_recoverLevel.Visible = false; + this.label_recoverLevel.Visible = false; } } } @@ -69,16 +70,19 @@ private void StartLogRecoverDlg_Load(object sender, EventArgs e) // 通用启动参数 string strRecoverLevel = ""; bool bClearFirst = false; + bool bContinueWhenError = false; nRet = ParseLogRecoverParam(this.StartInfo.Param, out strRecoverLevel, out bClearFirst, + out bContinueWhenError, out strError); if (nRet == -1) goto ERROR1; this.comboBox_recoverLevel.Text = strRecoverLevel; this.checkBox_clearBefore.Checked = bClearFirst; + this.checkBox_clearBefore.Checked = bContinueWhenError; return; ERROR1: MessageBox.Show(this, strError); @@ -138,6 +142,10 @@ private void button_OK_Click(object sender, EventArgs e) "clearFirst", (this.checkBox_clearBefore.Checked == true ? "yes" : "no")); + DomUtil.SetAttr(dom.DocumentElement, + "continueWhenError", + (this.checkBox_continueWhenError.Checked == true ? "yes" : "no")); + this.StartInfo.Param = dom.OuterXml; this.DialogResult = DialogResult.OK; this.Close(); @@ -198,15 +206,18 @@ static int ParseLogRecoverStart(string strStart, /// 待解析的参数字符串 /// 日志恢复级别 /// 在恢复前是否清除现有的数据库记录 + /// 出错后是否继续批处理 /// 错误信息。当本方法发生错误时 /// -1: 出错。错误信息在 strError 参数中返回;0: 成功 public static int ParseLogRecoverParam(string strParam, out string strRecoverLevel, out bool bClearFirst, + out bool bContinueWhenError, out string strError) { strError = ""; bClearFirst = false; + bContinueWhenError = false; strRecoverLevel = ""; if (String.IsNullOrEmpty(strParam) == true) @@ -241,6 +252,11 @@ public static int ParseLogRecoverParam(string strParam, else bClearFirst = false; + // 2016/3/8 + bContinueWhenError = DomUtil.GetBooleanParam(dom.DocumentElement, + "continueWhenError", + false); + return 0; } } diff --git a/dp2Circulation/Order/PrintAcceptForm.cs b/dp2Circulation/Order/PrintAcceptForm.cs index fbdee3004..352762868 100644 --- a/dp2Circulation/Order/PrintAcceptForm.cs +++ b/dp2Circulation/Order/PrintAcceptForm.cs @@ -370,7 +370,8 @@ private void PrintAcceptForm_FormClosed(object sender, FormClosedEventArgs e) SaveSize(); } - /*public*/ void LoadSize() + /*public*/ + void LoadSize() { #if NO // 设置窗口尺寸状态 @@ -401,7 +402,8 @@ private void PrintAcceptForm_FormClosed(object sender, FormClosedEventArgs e) } } - /*public*/ void SaveSize() + /*public*/ + void SaveSize() { #if NO MainForm.AppInfo.SaveMdiChildFormStates(this, @@ -744,7 +746,7 @@ public int LoadFromItemRecPathFile( sr = new StreamReader(strFilename); - for (int i = 0; ;) + for (int i = 0; ; ) { if (stop != null) { @@ -896,7 +898,7 @@ int LoadOneItem( long lRet = Channel.GetItemInfo( stop, - + (strRecPath[0] != '@' ? "@path:" + strRecPath : strRecPath), // "", "xml", @@ -1545,7 +1547,7 @@ int GetLinkedOrderRecordRecPath(string strRefID, if (lRet > 1) { - strError = "参考ID '" + strRefID + "' 命中多条("+lRet.ToString()+")订购记录"; + strError = "参考ID '" + strRefID + "' 命中多条(" + lRet.ToString() + ")订购记录"; return -1; } @@ -1688,7 +1690,8 @@ public static List GetLocationRefIDs(string strText) // -1 出错 // 0 一般册,不是套内的册。strResult中为空 // 1 套内册。strResult中返回了值 - /*public*/ static int GetCopyDetail(string strDistribute, + /*public*/ + static int GetCopyDetail(string strDistribute, string strRefID, out string strResult, out string strError) @@ -1730,7 +1733,7 @@ public static List GetLocationRefIDs(string strText) if (String.IsNullOrEmpty(strPart) == true) continue; - string[] ids = strPart.Split(new char[] { ','}); + string[] ids = strPart.Split(new char[] { ',' }); for (int j = 0; j < ids.Length; j++) { string strID = ids[j].Trim(); @@ -1754,7 +1757,7 @@ public static List GetLocationRefIDs(string strText) else { bTao = true; - iTao ++; + iTao++; } if (bTao == false) @@ -1779,7 +1782,7 @@ public static List GetLocationRefIDs(string strText) } } - strError = "refid '"+strRefID+"' 在字符串 '"+strDistribute+"' 中没有找到"; + strError = "refid '" + strRefID + "' 在字符串 '" + strDistribute + "' 中没有找到"; return -1; // not found } @@ -1883,12 +1886,13 @@ static void SetItemColor(ListViewItem item, } - /*public*/ static ListViewItem AddToListView(ListView list, - XmlDocument dom, - string strRecPath, - string strBiblioSummary, - string strISBnISSN, - string strBiblioRecPath) + /*public*/ + static ListViewItem AddToListView(ListView list, + XmlDocument dom, + string strRecPath, + string strBiblioSummary, + string strISBnISSN, + string strBiblioRecPath) { ListViewItem item = new ListViewItem(strRecPath, TYPE_NORMAL); @@ -1907,7 +1911,8 @@ static void SetItemColor(ListViewItem item, // 根据订购记录DOM设置ListViewItem除第一列以外的文字 // parameters: // bSetBarcodeColumn 是否要设置第一列记录路径的内容 - /*public*/ static void SetListViewItemText(XmlDocument dom, + /*public*/ + static void SetListViewItemText(XmlDocument dom, bool bSetRecPathColumn, string strRecPath, string strBiblioSummary, @@ -2428,14 +2433,16 @@ private void tabControl_main_SelectedIndexChanged(object sender, EventArgs e) } - /*public*/ class NamedListViewItems : List + /*public*/ + class NamedListViewItems : List { public string Seller = ""; List Items = new List(); } // 根据渠道(书商)名分入多个不同的List - /*public*/ class NamedListViewItemsCollection : List + /*public*/ + class NamedListViewItemsCollection : List { public void AddItem(string strSeller, ListViewItem item) @@ -3043,6 +3050,8 @@ int BuildMergedTableLine(PrintOption option, ListViewItem item = items[nIndex]; + this.ColumnTable.Clear(); // 清除上一记录处理时残余的内容 + if (this.MarcFilter != null) { string strError = ""; @@ -3054,29 +3063,30 @@ int BuildMergedTableLine(PrintOption option, // 获得MARC格式书目记录 string strBiblioRecPath = ListViewUtil.GetItemText(item, MERGED_COLUMN_BIBLIORECPATH); - nRet = GetMarc(strBiblioRecPath, - out strMARC, - out strOutMarcSyntax, - out strError); - if (nRet == -1) + if (string.IsNullOrEmpty(strBiblioRecPath) == false) { - strLineContent = strError; - goto END1; - } - - this.ColumnTable.Clear(); // 清除上一记录处理时残余的内容 + nRet = GetMarc(strBiblioRecPath, + out strMARC, + out strOutMarcSyntax, + out strError); + if (nRet == -1) + { + strLineContent = strError; + goto END1; + } - // 触发filter中的Record相关动作 - nRet = this.MarcFilter.DoRecord( - null, - strMARC, - strOutMarcSyntax, - nIndex, - out strError); - if (nRet == -1) - { - strLineContent = strError; - goto END1; + // 触发filter中的Record相关动作 + nRet = this.MarcFilter.DoRecord( + null, + strMARC, + strOutMarcSyntax, + nIndex, + out strError); + if (nRet == -1) + { + strLineContent = strError; + goto END1; + } } } @@ -3084,14 +3094,14 @@ int BuildMergedTableLine(PrintOption option, { Column column = option.Columns[i]; - /* - int nIndex = nPage * option.LinesPerPage + nLine; + /* + int nIndex = nPage * option.LinesPerPage + nLine; - if (nIndex >= items.Count) - break; + if (nIndex >= items.Count) + break; - ListViewItem item = items[nIndex]; - * */ + ListViewItem item = items[nIndex]; + * */ string strContent = GetMergedColumnContent(item, column.Name); @@ -3233,7 +3243,7 @@ string GetMergedColumnContent(ListViewItem item, case "总价格": return ListViewUtil.GetItemText(item, MERGED_COLUMN_TOTALPRICE); - // 2013/5/31 + // 2013/5/31 case "itemPrice": case "实体单价": return ListViewUtil.GetItemText(item, MERGED_COLUMN_ITEMPRICE); @@ -3493,7 +3503,7 @@ static int GetMergedTotalCopies(NamedListViewItems items) } } - total += nCopy*nSubCopy; + total += nCopy * nSubCopy; } return total; @@ -4193,7 +4203,7 @@ public void LoadFromOrderBatchNo(string strDefaultBatchNo) if (nItemRecCount == 0) { - MessageBox.Show(this, "未装入任何已验收的册记录 (处理订购记录 "+nOrderRecCount.ToString()+" 条)"); + MessageBox.Show(this, "未装入任何已验收的册记录 (处理订购记录 " + nOrderRecCount.ToString() + " 条)"); } } finally @@ -4258,7 +4268,7 @@ int LoadOrderItem(string strRecPath, data.Timestamp = item_timestamp; data.Xml = strOrderXml; - item.SubItems.Add("获取订购记录 "+strRecPath+" 时出错: " + strError); + item.SubItems.Add("获取订购记录 " + strRecPath + " 时出错: " + strError); SetItemColor(item, TYPE_ERROR); list.Items.Add(item); @@ -4604,7 +4614,7 @@ private void listView_origin_MouseUp(object sender, MouseEventArgs e) { strItemRecPath = ListViewUtil.GetItemText(this.listView_origin.SelectedItems[0], ORIGIN_COLUMN_RECPATH); } - menuItem = new MenuItem("打开种册窗,观察册记录 '"+strItemRecPath+"' (&I)"); + menuItem = new MenuItem("打开种册窗,观察册记录 '" + strItemRecPath + "' (&I)"); menuItem.Tag = this.listView_origin; menuItem.Click += new System.EventHandler(this.menu_loadItemRecord_Click); if (this.listView_origin.SelectedItems.Count == 0) @@ -4614,7 +4624,7 @@ private void listView_origin_MouseUp(object sender, MouseEventArgs e) string strOrderRecPath = ""; if (this.listView_origin.SelectedItems.Count > 0) { - strOrderRecPath = ListViewUtil.GetItemText(this.listView_origin.SelectedItems[0],ORIGIN_COLUMN_ORDERRECPATH); + strOrderRecPath = ListViewUtil.GetItemText(this.listView_origin.SelectedItems[0], ORIGIN_COLUMN_ORDERRECPATH); } menuItem = new MenuItem("打开种册窗,观察订购记录 '" + strOrderRecPath + "' (&O)"); menuItem.Tag = this.listView_origin; @@ -4964,7 +4974,8 @@ void RefreshLines(List items) } - /*public*/ int RefreshOneItem(ListViewItem item, + /*public*/ + int RefreshOneItem(ListViewItem item, out string strError) { strError = ""; @@ -5081,7 +5092,8 @@ int OriginIndex(ListViewItem item) return this.listView_origin.Items.IndexOf(item); } - /*public*/ class Tao + /*public*/ + class Tao { public string OrderRecPath = ""; // 订购记录路径 public string No = ""; // 套序号 从1开始计数 @@ -5100,7 +5112,7 @@ static int AddOneItem(ref List taos, strError = ""; Tao tao = null; - for(int i=0;i taos, } catch { - strError = "strCount '"+strCount+"' 格式不正确。应当为整数"; + strError = "strCount '" + strCount + "' 格式不正确。应当为整数"; return -1; } @@ -5136,7 +5148,7 @@ static int AddOneItem(ref List taos, else { if (nCount != tao.Count) - tao.ErrorInfo = "出现不一致的册数 '"+strCount+"'"; + tao.ErrorInfo = "出现不一致的册数 '" + strCount + "'"; } tao.IDs.Add(strID); @@ -5220,7 +5232,7 @@ int CheckSubCopy(out string strError) } catch { - strError = "序号 '"+strID1+"' 格式错误"; + strError = "序号 '" + strID1 + "' 格式错误"; return -1; } try @@ -5243,7 +5255,7 @@ int CheckSubCopy(out string strError) if (tao.Count != tao.IDs.Count) { - strError = "订购记录 '"+tao.OrderRecPath+"' 内第 "+tao.No+" 套应有 "+tao.Count.ToString()+" 册,但当前只有 "+tao.IDs.Count.ToString()+" 册,出现了不完整情况"; + strError = "订购记录 '" + tao.OrderRecPath + "' 内第 " + tao.No + " 套应有 " + tao.Count.ToString() + " 册,但当前只有 " + tao.IDs.Count.ToString() + " 册,出现了不完整情况"; return -1; } @@ -5348,13 +5360,13 @@ int FillMergedList(out string strError) // 2013/5/31 // 单价,实体价 string strItemPrice = ListViewUtil.GetItemText(source, - ORIGIN_COLUMN_ITEMPRICE); + ORIGIN_COLUMN_ITEMPRICE); // 2013/5/31 // 单价,订购价 string strOrderPrice = ListViewUtil.GetItemText(source, - ORIGIN_COLUMN_ORDERPRICE); + ORIGIN_COLUMN_ORDERPRICE); // 单价,到书价 @@ -6459,6 +6471,8 @@ int BuildOriginTableLine(PrintOption option, ListViewItem item = items[nIndex]; + this.ColumnTable.Clear(); // 清除上一记录处理时残余的内容 + if (this.MarcFilter != null) { string strError = ""; @@ -6470,29 +6484,30 @@ int BuildOriginTableLine(PrintOption option, // 获得MARC格式书目记录 string strBiblioRecPath = ListViewUtil.GetItemText(item, ORIGIN_COLUMN_BIBLIORECPATH); - nRet = GetMarc(strBiblioRecPath, - out strMARC, - out strOutMarcSyntax, - out strError); - if (nRet == -1) + if (string.IsNullOrEmpty(strBiblioRecPath) == false) { - strLineContent = strError; - goto END1; - } - - this.ColumnTable.Clear(); // 清除上一记录处理时残余的内容 + nRet = GetMarc(strBiblioRecPath, + out strMARC, + out strOutMarcSyntax, + out strError); + if (nRet == -1) + { + strLineContent = strError; + goto END1; + } - // 触发filter中的Record相关动作 - nRet = this.MarcFilter.DoRecord( - null, - strMARC, - strOutMarcSyntax, - nIndex, - out strError); - if (nRet == -1) - { - strLineContent = strError; - goto END1; + // 触发filter中的Record相关动作 + nRet = this.MarcFilter.DoRecord( + null, + strMARC, + strOutMarcSyntax, + nIndex, + out strError); + if (nRet == -1) + { + strLineContent = strError; + goto END1; + } } } @@ -6536,7 +6551,7 @@ int BuildOriginTableLine(PrintOption option, ""; } - END1: + END1: StreamUtil.WriteText(strFileName, ""); @@ -6625,7 +6640,7 @@ string GetOriginColumnContent(ListViewItem item, case "经费来源": return ListViewUtil.GetItemText(item, ORIGIN_COLUMN_SOURCE); - // 验收价 + // 验收价 case "price": case "acceptprice": case "acceptPrice": @@ -6634,13 +6649,13 @@ string GetOriginColumnContent(ListViewItem item, case "到书价": return ListViewUtil.GetItemText(item, ORIGIN_COLUMN_ACCEPTPRICE); - // 实体记录中的价格 + // 实体记录中的价格 case "itemprice": case "itemPrice": case "实体单价": return ListViewUtil.GetItemText(item, ORIGIN_COLUMN_ITEMPRICE); - // 订购价 + // 订购价 case "orderprice": case "orderPrice": case "订购单价": @@ -6882,7 +6897,7 @@ static int GetOriginTotalSeries(List items) // 不是各套的第一册,就跳过 if (strIndex == "1") - total ++; + total++; } return total; @@ -7718,10 +7733,10 @@ int BuildExchangeRateHtml( if (string.IsNullOrEmpty(strOrderRecPath) == true) continue; - string strOrderPrice = ListViewUtil.GetItemText(item,ORIGIN_COLUMN_ORDERPRICE); - string strAcceptPrice = ListViewUtil.GetItemText(item,ORIGIN_COLUMN_ACCEPTPRICE); + string strOrderPrice = ListViewUtil.GetItemText(item, ORIGIN_COLUMN_ORDERPRICE); + string strAcceptPrice = ListViewUtil.GetItemText(item, ORIGIN_COLUMN_ACCEPTPRICE); - string strOrderSubCopy = ListViewUtil.GetItemText(item,ORIGIN_COLUMN_ORDERSUBCOPY); + string strOrderSubCopy = ListViewUtil.GetItemText(item, ORIGIN_COLUMN_ORDERSUBCOPY); string strAcceptSubCopy = ListViewUtil.GetItemText(item, ORIGIN_COLUMN_ACCEPTSUBCOPY); // ACCEPTSUBCOPY需要加工一下。原始形态为 1:1/3 需要取出'/'右边的数字 @@ -7812,7 +7827,7 @@ int BuildExchangeRateHtml( } // 排序事项? - string [] keys = new string[this.m_exchangeTable.Keys.Count]; + string[] keys = new string[this.m_exchangeTable.Keys.Count]; this.m_exchangeTable.Keys.CopyTo(keys, 0); Array.Sort(keys); @@ -8166,7 +8181,8 @@ public AcceptOriginPrintOption(string strDataDir, } // 原始数据listviewitem的Tag所携带的数据结构 - /*public*/ class OriginAcceptItemData + /*public*/ + class OriginAcceptItemData { /// /// 内容是否发生过修改 @@ -8220,7 +8236,8 @@ public ExchangeRatePrintOption(string strDataDir, } - /*public*/ class ExchangeInfo + /*public*/ + class ExchangeInfo { // 源货币 public string OriginCurrency = ""; diff --git a/dp2Circulation/Order/PrintOrderForm.cs b/dp2Circulation/Order/PrintOrderForm.cs index 57bb2b40e..0bd8b03f2 100644 --- a/dp2Circulation/Order/PrintOrderForm.cs +++ b/dp2Circulation/Order/PrintOrderForm.cs @@ -2924,6 +2924,8 @@ int BuildStatisHtml( ListViewItem item = items[i]; + this.ColumnTable.Clear(); // 清除上一记录处理时残余的内容 + // 获得种记录中的主要分类依据。分类号或者出版社名 string strKey = ""; // 主要分类依据 string strSecondaryKey = ""; // 次要分类依据 @@ -2934,38 +2936,40 @@ int BuildStatisHtml( // 获得MARC格式书目记录 string strBiblioRecPath = ListViewUtil.GetItemText(item, MERGED_COLUMN_BIBLIORECPATH); - // 获得MARC格式书目记录 - // return: - // -1 出错 - // 0 空记录 - // 1 成功 - nRet = GetMarc(strBiblioRecPath, - out strMARC, - out strOutMarcSyntax, - out strError); - if (nRet == -1) - return -1; - this.ColumnTable.Clear(); // 清除上一记录处理时残余的内容 - - if (nRet != 0) + if (string.IsNullOrEmpty(strBiblioRecPath) == false) { - // 触发filter中的Record相关动作 - nRet = this.MarcFilter.DoRecord( - null, - strMARC, - strOutMarcSyntax, - i, + // 获得MARC格式书目记录 + // return: + // -1 出错 + // 0 空记录 + // 1 成功 + nRet = GetMarc(strBiblioRecPath, + out strMARC, + out strOutMarcSyntax, out strError); if (nRet == -1) return -1; - if (strStatisType == "class") - strKey = (string)this.ColumnTable["biblioclass"]; - else if (strStatisType == "publisher") + if (nRet != 0) { - strKey = (string)this.ColumnTable["bibliopublisher"]; - strSecondaryKey = (string)this.ColumnTable["biblioclass"]; + // 触发filter中的Record相关动作 + nRet = this.MarcFilter.DoRecord( + null, + strMARC, + strOutMarcSyntax, + i, + out strError); + if (nRet == -1) + return -1; + + if (strStatisType == "class") + strKey = (string)this.ColumnTable["biblioclass"]; + else if (strStatisType == "publisher") + { + strKey = (string)this.ColumnTable["bibliopublisher"]; + strSecondaryKey = (string)this.ColumnTable["biblioclass"]; + } } } @@ -4569,6 +4573,8 @@ int BuildMergedTableLine(PrintOption option, ListViewItem item = items[nIndex]; + this.ColumnTable.Clear(); // 清除上一记录处理时残余的内容 + if (this.MarcFilter != null) { string strError = ""; @@ -4580,33 +4586,33 @@ int BuildMergedTableLine(PrintOption option, // 获得MARC格式书目记录 string strBiblioRecPath = ListViewUtil.GetItemText(item, MERGED_COLUMN_BIBLIORECPATH); - nRet = GetMarc(strBiblioRecPath, - out strMARC, - out strOutMarcSyntax, - out strError); - if (nRet == -1) + if (string.IsNullOrEmpty(strBiblioRecPath) == false) { - strHtmlLineContent = strError; - goto END1; - } - - this.ColumnTable.Clear(); // 清除上一记录处理时残余的内容 + nRet = GetMarc(strBiblioRecPath, + out strMARC, + out strOutMarcSyntax, + out strError); + if (nRet == -1) + { + strHtmlLineContent = strError; + goto END1; + } - // 触发filter中的Record相关动作 - nRet = this.MarcFilter.DoRecord( - null, - strMARC, - strOutMarcSyntax, - nIndex, - out strError); - if (nRet == -1) - { - strHtmlLineContent = strError; - goto END1; + // 触发filter中的Record相关动作 + nRet = this.MarcFilter.DoRecord( + null, + strMARC, + strOutMarcSyntax, + nIndex, + out strError); + if (nRet == -1) + { + strHtmlLineContent = strError; + goto END1; + } } } - for (int i = 0; i < option.Columns.Count; i++) { Column column = option.Columns[i]; @@ -7507,6 +7513,8 @@ int BuildOriginTableLine(PrintOption option, ListViewItem item = items[nIndex]; + this.ColumnTable.Clear(); // 清除上一记录处理时残余的内容 + if (this.MarcFilter != null) { string strError = ""; @@ -7518,33 +7526,33 @@ int BuildOriginTableLine(PrintOption option, // 获得MARC格式书目记录 string strBiblioRecPath = ListViewUtil.GetItemText(item, ORIGIN_COLUMN_BIBLIORECPATH); - nRet = GetMarc(strBiblioRecPath, - out strMARC, - out strOutMarcSyntax, - out strError); - if (nRet == -1) + if (string.IsNullOrEmpty(strBiblioRecPath) == false) { - strLineContent = strError; - goto END1; - } - - this.ColumnTable.Clear(); // 清除上一记录处理时残余的内容 + nRet = GetMarc(strBiblioRecPath, + out strMARC, + out strOutMarcSyntax, + out strError); + if (nRet == -1) + { + strLineContent = strError; + goto END1; + } - // 触发filter中的Record相关动作 - nRet = this.MarcFilter.DoRecord( - null, - strMARC, - strOutMarcSyntax, - nIndex, - out strError); - if (nRet == -1) - { - strLineContent = strError; - goto END1; + // 触发filter中的Record相关动作 + nRet = this.MarcFilter.DoRecord( + null, + strMARC, + strOutMarcSyntax, + nIndex, + out strError); + if (nRet == -1) + { + strLineContent = strError; + goto END1; + } } } - for (int i = 0; i < option.Columns.Count; i++) { Column column = option.Columns[i]; diff --git a/dp2Circulation/dp2Circulation.csproj b/dp2Circulation/dp2Circulation.csproj index 5972b89e4..5aa891057 100644 --- a/dp2Circulation/dp2Circulation.csproj +++ b/dp2Circulation/dp2Circulation.csproj @@ -51,7 +51,7 @@ dp2 V2 true publish.htm - 26 + 29 2.10.0.%2a false true @@ -377,6 +377,12 @@ ChatLoginDialog.cs + + Form + + + ImportExportForm.cs + Form @@ -1563,6 +1569,9 @@ ChatLoginDialog.cs + + ImportExportForm.cs + ScanBarcodeForm.cs diff --git a/dp2Installer/MainForm.cs b/dp2Installer/MainForm.cs index d6e476c67..7ec5942b8 100644 --- a/dp2Installer/MainForm.cs +++ b/dp2Installer/MainForm.cs @@ -1469,9 +1469,10 @@ int VerifySerialNumbers(bool bDisplaySectionTitle, AppendString("放弃设置实例 '" + strInstanceName + "' 的序列号\r\n"); continue; } - if (DigitalPlatform.LibraryServer.OneInstanceDialog.MatchLocalString(strSerialCode, strInstanceName) == false) + if (DigitalPlatform.LibraryServer.OneInstanceDialog.MatchLocalString(strSerialCode, strInstanceName) == false + && strSerialCode != "community") { - MessageBox.Show(this, "实例 '" + strInstanceName + "' 的序列号序列号 '" + strSerialCode + "' 经验证无效。请重新输入"); + MessageBox.Show(this, "实例 '" + strInstanceName + "' 的序列号 '" + strSerialCode + "' 经验证无效。请重新输入"); goto REDO_INPUT; } diff --git a/dp2Installer/dp2Installer.csproj b/dp2Installer/dp2Installer.csproj index cf191be9d..f771b77a6 100644 --- a/dp2Installer/dp2Installer.csproj +++ b/dp2Installer/dp2Installer.csproj @@ -34,7 +34,7 @@ dp2 V2 true publish.htm - 101 + 102 1.1.0.%2a false true diff --git a/dp2Installer/opac_app/Browse.aspx.cs b/dp2Installer/opac_app/Browse.aspx.cs index fbb24c77a..07144ac59 100644 --- a/dp2Installer/opac_app/Browse.aspx.cs +++ b/dp2Installer/opac_app/Browse.aspx.cs @@ -76,7 +76,6 @@ void TitleBarControl1_LibraryCodeChanged(object sender, LibraryCodeChangedEventA this.BrowseSearchResultControl1.ResetAllItemsControlPager(); } - protected void Page_Load(object sender, EventArgs e) { // 是否登录? @@ -107,7 +106,6 @@ protected void Page_Load(object sender, EventArgs e) else this.SideBarControl1.CfgFile = app.DataDir + "\\browse\\" + strCfgFileName; - string strDataFileName = this.Request["datafile"]; if (String.IsNullOrEmpty(strDataFileName) == true) @@ -136,7 +134,7 @@ protected void Page_Load(object sender, EventArgs e) return; } - this.Response.Flush(); + // this.Response.Flush(); this.Response.End(); return; } @@ -831,7 +829,6 @@ int BuildRssOutput( PathUtil.CreateDirIfNeed(strCacheDir); string strResultsetFilename = strCacheDir + "/" + strPrefix; - // 如果RSS文件已经存在,就不要从 dp2library 获取了 if (File.Exists(strResultsetFilename + ".rss") == true) { @@ -843,7 +840,6 @@ int BuildRssOutput( out strError); if (nRet == -1) return -1; - return 0; } @@ -890,11 +886,13 @@ int DumpRssFile(string strRssFile, try { + // http://stackoverflow.com/questions/904952/whats-causing-session-state-has-created-a-session-id-but-cannot-save-it-becau + string sessionId = Session.SessionID; + app.ResultsetLocks.LockForRead(strRssFile, 500); try { - using (Stream stream = File.Open(strRssFile, FileMode.Open, FileAccess.ReadWrite, diff --git a/dp2LibraryXE/opac_app/Browse.aspx.cs b/dp2LibraryXE/opac_app/Browse.aspx.cs index fbb24c77a..07144ac59 100644 --- a/dp2LibraryXE/opac_app/Browse.aspx.cs +++ b/dp2LibraryXE/opac_app/Browse.aspx.cs @@ -76,7 +76,6 @@ void TitleBarControl1_LibraryCodeChanged(object sender, LibraryCodeChangedEventA this.BrowseSearchResultControl1.ResetAllItemsControlPager(); } - protected void Page_Load(object sender, EventArgs e) { // 是否登录? @@ -107,7 +106,6 @@ protected void Page_Load(object sender, EventArgs e) else this.SideBarControl1.CfgFile = app.DataDir + "\\browse\\" + strCfgFileName; - string strDataFileName = this.Request["datafile"]; if (String.IsNullOrEmpty(strDataFileName) == true) @@ -136,7 +134,7 @@ protected void Page_Load(object sender, EventArgs e) return; } - this.Response.Flush(); + // this.Response.Flush(); this.Response.End(); return; } @@ -831,7 +829,6 @@ int BuildRssOutput( PathUtil.CreateDirIfNeed(strCacheDir); string strResultsetFilename = strCacheDir + "/" + strPrefix; - // 如果RSS文件已经存在,就不要从 dp2library 获取了 if (File.Exists(strResultsetFilename + ".rss") == true) { @@ -843,7 +840,6 @@ int BuildRssOutput( out strError); if (nRet == -1) return -1; - return 0; } @@ -890,11 +886,13 @@ int DumpRssFile(string strRssFile, try { + // http://stackoverflow.com/questions/904952/whats-causing-session-state-has-created-a-session-id-but-cannot-save-it-becau + string sessionId = Session.SessionID; + app.ResultsetLocks.LockForRead(strRssFile, 500); try { - using (Stream stream = File.Open(strRssFile, FileMode.Open, FileAccess.ReadWrite, diff --git a/dp2OPAC/Browse.aspx.cs b/dp2OPAC/Browse.aspx.cs index fbb24c77a..07144ac59 100644 --- a/dp2OPAC/Browse.aspx.cs +++ b/dp2OPAC/Browse.aspx.cs @@ -76,7 +76,6 @@ void TitleBarControl1_LibraryCodeChanged(object sender, LibraryCodeChangedEventA this.BrowseSearchResultControl1.ResetAllItemsControlPager(); } - protected void Page_Load(object sender, EventArgs e) { // 是否登录? @@ -107,7 +106,6 @@ protected void Page_Load(object sender, EventArgs e) else this.SideBarControl1.CfgFile = app.DataDir + "\\browse\\" + strCfgFileName; - string strDataFileName = this.Request["datafile"]; if (String.IsNullOrEmpty(strDataFileName) == true) @@ -136,7 +134,7 @@ protected void Page_Load(object sender, EventArgs e) return; } - this.Response.Flush(); + // this.Response.Flush(); this.Response.End(); return; } @@ -831,7 +829,6 @@ int BuildRssOutput( PathUtil.CreateDirIfNeed(strCacheDir); string strResultsetFilename = strCacheDir + "/" + strPrefix; - // 如果RSS文件已经存在,就不要从 dp2library 获取了 if (File.Exists(strResultsetFilename + ".rss") == true) { @@ -843,7 +840,6 @@ int BuildRssOutput( out strError); if (nRet == -1) return -1; - return 0; } @@ -890,11 +886,13 @@ int DumpRssFile(string strRssFile, try { + // http://stackoverflow.com/questions/904952/whats-causing-session-state-has-created-a-session-id-but-cannot-save-it-becau + string sessionId = Session.SessionID; + app.ResultsetLocks.LockForRead(strRssFile, 500); try { - using (Stream stream = File.Open(strRssFile, FileMode.Open, FileAccess.ReadWrite, From d22872d44138764b0358ff721da896358dc38281 Mon Sep 17 00:00:00 2001 From: XieTao Date: Thu, 24 Mar 2016 17:05:52 +0800 Subject: [PATCH 02/10] =?UTF-8?q?=E5=A2=9E=E6=B7=BB=E5=AF=BC=E5=87=BA?= =?UTF-8?q?=E4=B9=A6=E7=9B=AE=E8=BD=AC=E5=82=A8=E6=96=87=E4=BB=B6=E5=8A=9F?= =?UTF-8?q?=E8=83=BD(=E6=9C=AA=E5=85=A8=E9=83=A8=E5=AE=8C=E6=88=90)?= =?UTF-8?q?=EF=BC=9B=E4=BF=AE=E6=AD=A3=20dp2circulation=20=E4=B9=A6?= =?UTF-8?q?=E7=9B=AE=E6=9F=A5=E8=AF=A2=E7=AA=97=E7=9A=84=E8=BD=AC=E7=A7=BB?= =?UTF-8?q?=E4=B9=A6=E7=9B=AE=E8=AE=B0=E5=BD=95=E5=8A=9F=E8=83=BD=E7=9A=84?= =?UTF-8?q?=E4=B8=80=E4=B8=AA=20bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MongoDb/BuildMongoOperDatabase.cs | 1 - .../LibraryService.cs | 3 + DigitalPlatform.Xml/DomUtil.cs | 35 ++ .../IO/ImportExportForm.Designer.cs | 101 +++- dp2Circulation/IO/ImportExportForm.cs | 512 +++++++++++++++++- .../ItemHandOver/ItemHandoverForm.cs | 1 + dp2Circulation/MainForm/MainForm.Designer.cs | 10 + dp2Circulation/MainForm/MainForm.cs | 154 ++++-- .../SearchForms/BiblioSearchForm.cs | 383 +++++++++++++ dp2Circulation/SearchForms/ItemSearchForm.cs | 377 ++++++++++++- .../SearchForms/ItemSearchFormBase.cs | 12 +- dp2Circulation/dp2Circulation.csproj | 2 +- dp2Installer/opac_app/Test.aspx.cs | 17 + 13 files changed, 1532 insertions(+), 76 deletions(-) create mode 100644 dp2Installer/opac_app/Test.aspx.cs diff --git a/DigitalPlatform.LibraryServer/MongoDb/BuildMongoOperDatabase.cs b/DigitalPlatform.LibraryServer/MongoDb/BuildMongoOperDatabase.cs index 509d477e0..90899ad01 100644 --- a/DigitalPlatform.LibraryServer/MongoDb/BuildMongoOperDatabase.cs +++ b/DigitalPlatform.LibraryServer/MongoDb/BuildMongoOperDatabase.cs @@ -131,7 +131,6 @@ public static int ParseLogRecoverParam(string strParam, return 0; } - // 一次操作循环 public override void Worker() { diff --git a/DigitalPlatform.LibraryService/LibraryService.cs b/DigitalPlatform.LibraryService/LibraryService.cs index e26ee5513..c513495a8 100644 --- a/DigitalPlatform.LibraryService/LibraryService.cs +++ b/DigitalPlatform.LibraryService/LibraryService.cs @@ -2379,6 +2379,9 @@ public LibraryServerResult Search( try { + // test + Thread.Sleep(new TimeSpan(0, 0, 30)); + // 权限判断 // 权限字符串 diff --git a/DigitalPlatform.Xml/DomUtil.cs b/DigitalPlatform.Xml/DomUtil.cs index 7b5dcf8a8..63b3797fc 100644 --- a/DigitalPlatform.Xml/DomUtil.cs +++ b/DigitalPlatform.Xml/DomUtil.cs @@ -12,6 +12,41 @@ namespace DigitalPlatform.Xml // DomUtil类包含XML DOM的一些扩展功能函数 public class DomUtil { + // 删除 start 元素下的所有空元素 + // parameters: + // bCheckStart 是否检查 start。如果本参数为 true, 当 start 为空元素时,要删除 start 元素 + public static void RemoveEmptyElements(XmlElement start, + bool bCheckStart = false) + { + List delete = new List(); + foreach (XmlNode node in start.ChildNodes) + { + if (node.NodeType != XmlNodeType.Element) + continue; + XmlElement element = node as XmlElement; + if (element.HasAttributes == false + && string.IsNullOrEmpty(element.InnerText.Trim()) == true) + { + delete.Add(element); + } + else + RemoveEmptyElements(element, true); + } + + foreach (XmlElement element in delete) + { + element.ParentNode.RemoveChild(element); + } + + if (bCheckStart == true && start.ParentNode != null) + { + XmlElement element = start; + if (element.HasAttributes == false + && string.IsNullOrEmpty(element.InnerText.Trim()) == true) + element.ParentNode.RemoveChild(element); + } + } + public static XmlNode RenameNode(XmlNode node, string namespaceURI, string qualifiedName) diff --git a/dp2Circulation/IO/ImportExportForm.Designer.cs b/dp2Circulation/IO/ImportExportForm.Designer.cs index 40325f54b..0c322ad71 100644 --- a/dp2Circulation/IO/ImportExportForm.Designer.cs +++ b/dp2Circulation/IO/ImportExportForm.Designer.cs @@ -29,14 +29,20 @@ protected override void Dispose(bool disposing) private void InitializeComponent() { this.tabControl1 = new System.Windows.Forms.TabControl(); - this.tabPage1 = new System.Windows.Forms.TabPage(); + this.tabPage_range = new System.Windows.Forms.TabPage(); + this.listView_in = new DigitalPlatform.GUI.ListViewNF(); + this.button_load_scanBarcode = new System.Windows.Forms.Button(); + this.button_load_loadFromRecPathFile = new System.Windows.Forms.Button(); + this.button_load_loadFromBatchNo = new System.Windows.Forms.Button(); + this.button_load_loadFromBarcodeFile = new System.Windows.Forms.Button(); this.tabPage2 = new System.Windows.Forms.TabPage(); this.tabControl1.SuspendLayout(); + this.tabPage_range.SuspendLayout(); this.SuspendLayout(); // // tabControl1 // - this.tabControl1.Controls.Add(this.tabPage1); + this.tabControl1.Controls.Add(this.tabPage_range); this.tabControl1.Controls.Add(this.tabPage2); this.tabControl1.Location = new System.Drawing.Point(13, 13); this.tabControl1.Name = "tabControl1"; @@ -44,22 +50,84 @@ private void InitializeComponent() this.tabControl1.Size = new System.Drawing.Size(443, 309); this.tabControl1.TabIndex = 0; // - // tabPage1 + // tabPage_range // - this.tabPage1.Location = new System.Drawing.Point(4, 22); - this.tabPage1.Name = "tabPage1"; - this.tabPage1.Padding = new System.Windows.Forms.Padding(3); - this.tabPage1.Size = new System.Drawing.Size(435, 283); - this.tabPage1.TabIndex = 0; - this.tabPage1.Text = "tabPage1"; - this.tabPage1.UseVisualStyleBackColor = true; + this.tabPage_range.Controls.Add(this.listView_in); + this.tabPage_range.Controls.Add(this.button_load_scanBarcode); + this.tabPage_range.Controls.Add(this.button_load_loadFromRecPathFile); + this.tabPage_range.Controls.Add(this.button_load_loadFromBatchNo); + this.tabPage_range.Controls.Add(this.button_load_loadFromBarcodeFile); + this.tabPage_range.Location = new System.Drawing.Point(4, 22); + this.tabPage_range.Name = "tabPage_range"; + this.tabPage_range.Padding = new System.Windows.Forms.Padding(3); + this.tabPage_range.Size = new System.Drawing.Size(435, 283); + this.tabPage_range.TabIndex = 0; + this.tabPage_range.Text = "范围"; + this.tabPage_range.UseVisualStyleBackColor = true; + // + // listView_in + // + this.listView_in.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.listView_in.FullRowSelect = true; + this.listView_in.HideSelection = false; + this.listView_in.Location = new System.Drawing.Point(5, 92); + this.listView_in.Margin = new System.Windows.Forms.Padding(2); + this.listView_in.Name = "listView_in"; + this.listView_in.Size = new System.Drawing.Size(425, 186); + this.listView_in.TabIndex = 10; + this.listView_in.UseCompatibleStateImageBehavior = false; + this.listView_in.View = System.Windows.Forms.View.Details; + // + // button_load_scanBarcode + // + this.button_load_scanBarcode.Location = new System.Drawing.Point(179, 44); + this.button_load_scanBarcode.Margin = new System.Windows.Forms.Padding(2); + this.button_load_scanBarcode.Name = "button_load_scanBarcode"; + this.button_load_scanBarcode.Size = new System.Drawing.Size(170, 22); + this.button_load_scanBarcode.TabIndex = 9; + this.button_load_scanBarcode.Text = "扫入册条码(&S)..."; + this.button_load_scanBarcode.UseVisualStyleBackColor = true; + this.button_load_scanBarcode.Click += new System.EventHandler(this.button_load_scanBarcode_Click); + // + // button_load_loadFromRecPathFile + // + this.button_load_loadFromRecPathFile.Location = new System.Drawing.Point(5, 45); + this.button_load_loadFromRecPathFile.Margin = new System.Windows.Forms.Padding(2); + this.button_load_loadFromRecPathFile.Name = "button_load_loadFromRecPathFile"; + this.button_load_loadFromRecPathFile.Size = new System.Drawing.Size(170, 22); + this.button_load_loadFromRecPathFile.TabIndex = 7; + this.button_load_loadFromRecPathFile.Text = "从册记录路径文件(&R)..."; + this.button_load_loadFromRecPathFile.UseVisualStyleBackColor = true; + // + // button_load_loadFromBatchNo + // + this.button_load_loadFromBatchNo.Location = new System.Drawing.Point(179, 18); + this.button_load_loadFromBatchNo.Margin = new System.Windows.Forms.Padding(2); + this.button_load_loadFromBatchNo.Name = "button_load_loadFromBatchNo"; + this.button_load_loadFromBatchNo.Size = new System.Drawing.Size(170, 22); + this.button_load_loadFromBatchNo.TabIndex = 8; + this.button_load_loadFromBatchNo.Text = "根据批次号检索(&B)..."; + this.button_load_loadFromBatchNo.UseVisualStyleBackColor = true; + // + // button_load_loadFromBarcodeFile + // + this.button_load_loadFromBarcodeFile.Location = new System.Drawing.Point(5, 19); + this.button_load_loadFromBarcodeFile.Margin = new System.Windows.Forms.Padding(2); + this.button_load_loadFromBarcodeFile.Name = "button_load_loadFromBarcodeFile"; + this.button_load_loadFromBarcodeFile.Size = new System.Drawing.Size(170, 22); + this.button_load_loadFromBarcodeFile.TabIndex = 6; + this.button_load_loadFromBarcodeFile.Text = "从条码号文件(&F)..."; + this.button_load_loadFromBarcodeFile.UseVisualStyleBackColor = true; + this.button_load_loadFromBarcodeFile.Click += new System.EventHandler(this.button_load_loadFromBarcodeFile_Click); // // tabPage2 // this.tabPage2.Location = new System.Drawing.Point(4, 22); this.tabPage2.Name = "tabPage2"; this.tabPage2.Padding = new System.Windows.Forms.Padding(3); - this.tabPage2.Size = new System.Drawing.Size(192, 74); + this.tabPage2.Size = new System.Drawing.Size(435, 283); this.tabPage2.TabIndex = 1; this.tabPage2.Text = "tabPage2"; this.tabPage2.UseVisualStyleBackColor = true; @@ -72,7 +140,11 @@ private void InitializeComponent() this.Controls.Add(this.tabControl1); this.Name = "ImportExportForm"; this.Text = "ImportExportForm"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.ImportExportForm_FormClosing); + this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.ImportExportForm_FormClosed); + this.Load += new System.EventHandler(this.ImportExportForm_Load); this.tabControl1.ResumeLayout(false); + this.tabPage_range.ResumeLayout(false); this.ResumeLayout(false); } @@ -80,7 +152,12 @@ private void InitializeComponent() #endregion private System.Windows.Forms.TabControl tabControl1; - private System.Windows.Forms.TabPage tabPage1; + private System.Windows.Forms.TabPage tabPage_range; private System.Windows.Forms.TabPage tabPage2; + private System.Windows.Forms.Button button_load_scanBarcode; + private System.Windows.Forms.Button button_load_loadFromRecPathFile; + private System.Windows.Forms.Button button_load_loadFromBatchNo; + private System.Windows.Forms.Button button_load_loadFromBarcodeFile; + private DigitalPlatform.GUI.ListViewNF listView_in; } } \ No newline at end of file diff --git a/dp2Circulation/IO/ImportExportForm.cs b/dp2Circulation/IO/ImportExportForm.cs index 2cce6abec..42160895a 100644 --- a/dp2Circulation/IO/ImportExportForm.cs +++ b/dp2Circulation/IO/ImportExportForm.cs @@ -2,18 +2,528 @@ using System.Collections.Generic; using System.ComponentModel; using System.Data; +using System.Diagnostics; using System.Drawing; +using System.IO; using System.Linq; using System.Text; using System.Windows.Forms; namespace dp2Circulation { - public partial class ImportExportForm : Form + public partial class ImportExportForm : BatchPrintFormBase { public ImportExportForm() { InitializeComponent(); } + + private void ImportExportForm_Load(object sender, EventArgs e) + { + CreateColumnHeader(this.listView_in); + } + + private void ImportExportForm_FormClosing(object sender, FormClosingEventArgs e) + { + + } + + private void ImportExportForm_FormClosed(object sender, FormClosedEventArgs e) + { + + } + + // 设置listview栏目标题 + void CreateColumnHeader(ListView list) + { + ColumnHeader columnHeader_barcode = new ColumnHeader(); + ColumnHeader columnHeader_isbnIssn = new ColumnHeader(); + ColumnHeader columnHeader_state = new ColumnHeader(); + ColumnHeader columnHeader_location = new ColumnHeader(); + ColumnHeader columnHeader_price = new ColumnHeader(); + ColumnHeader columnHeader_bookType = new ColumnHeader(); + ColumnHeader columnHeader_comment = new ColumnHeader(); + ColumnHeader columnHeader_borrower = new ColumnHeader(); + ColumnHeader columnHeader_borrowDate = new ColumnHeader(); + ColumnHeader columnHeader_borrowPeriod = new ColumnHeader(); + ColumnHeader columnHeader_recpath = new ColumnHeader(); + ColumnHeader columnHeader_errorInfo = new ColumnHeader(); + ColumnHeader columnHeader_registerNo = new ColumnHeader(); + ColumnHeader columnHeader_mergeComment = new ColumnHeader(); + ColumnHeader columnHeader_batchNo = new ColumnHeader(); + ColumnHeader columnHeader_biblioRecpath = new ColumnHeader(); + ColumnHeader columnHeader_accessno = new ColumnHeader(); + + // 2009/10/27 + ColumnHeader columnHeader_targetRecpath = new ColumnHeader(); + + list.Columns.Clear(); + + list.Columns.AddRange(new ColumnHeader[] { + columnHeader_barcode, + columnHeader_errorInfo, + columnHeader_isbnIssn, + columnHeader_state, + columnHeader_location, + columnHeader_price, + columnHeader_bookType, + columnHeader_registerNo, + columnHeader_comment, + columnHeader_mergeComment, + columnHeader_batchNo, + columnHeader_borrower, + columnHeader_borrowDate, + columnHeader_borrowPeriod, + columnHeader_recpath, + columnHeader_biblioRecpath, + columnHeader_accessno, + columnHeader_targetRecpath}); + + // + // columnHeader_barcode + // + columnHeader_barcode.Text = "册条码号"; + columnHeader_barcode.Width = 150; + // + // columnHeader_errorInfo + // + columnHeader_errorInfo.Text = "摘要/错误信息"; + columnHeader_errorInfo.Width = 200; + // + // columnHeader_isbnIssn + // + columnHeader_isbnIssn.Text = "ISBN/ISSN"; + columnHeader_isbnIssn.Width = 160; + // + // columnHeader_state + // + columnHeader_state.Text = "状态"; + columnHeader_state.Width = 100; + // + // columnHeader_location + // + columnHeader_location.Text = "馆藏地点"; + columnHeader_location.Width = 150; + // + // columnHeader_price + // + columnHeader_price.Text = "册价格"; + columnHeader_price.Width = 150; + // + // columnHeader_bookType + // + columnHeader_bookType.Text = "册类型"; + columnHeader_bookType.Width = 150; + // + // columnHeader_registerNo + // + columnHeader_registerNo.Text = "登录号"; + columnHeader_registerNo.Width = 150; + // + // columnHeader_comment + // + columnHeader_comment.Text = "附注"; + columnHeader_comment.Width = 150; + // + // columnHeader_mergeComment + // + columnHeader_mergeComment.Text = "合并注释"; + columnHeader_mergeComment.Width = 150; + // + // columnHeader_batchNo + // + columnHeader_batchNo.Text = "批次号"; + // + // columnHeader_borrower + // + columnHeader_borrower.Text = "借阅者"; + columnHeader_borrower.Width = 150; + // + // columnHeader_borrowDate + // + columnHeader_borrowDate.Text = "借阅日期"; + columnHeader_borrowDate.Width = 150; + // + // columnHeader_borrowPeriod + // + columnHeader_borrowPeriod.Text = "借阅期限"; + columnHeader_borrowPeriod.Width = 150; + // + // columnHeader_recpath + // + columnHeader_recpath.Text = "册记录路径"; + columnHeader_recpath.Width = 200; + // + // columnHeader_biblioRecpath + // + columnHeader_biblioRecpath.Text = "种记录路径"; + columnHeader_biblioRecpath.Width = 200; + // + // columnHeader_accessno + // + columnHeader_accessno.Text = "索取号"; + columnHeader_accessno.Width = 200; + // + // columnHeader_targetRecpath + // + columnHeader_targetRecpath.Text = "目标书目记录路径"; + columnHeader_targetRecpath.Width = 200; + } + + /// + /// 最近使用过的条码文件全路径 + /// + public string BarcodeFilePath = ""; + /// + /// 最近使用过的记录路径文件全路径 + /// + public string RecPathFilePath = ""; + + private void button_load_loadFromBarcodeFile_Click(object sender, EventArgs e) + { + int nRet = 0; + string strError = ""; + + bool bClearBefore = true; + if (Control.ModifierKeys == Keys.Control) + bClearBefore = false; + + if (bClearBefore == true) + ClearBefore(); + OpenFileDialog dlg = new OpenFileDialog(); + + dlg.Title = "请指定要打开的条码号文件名"; + dlg.FileName = this.BarcodeFilePath; + dlg.Filter = "条码号文件 (*.txt)|*.txt|All files (*.*)|*.*"; + dlg.RestoreDirectory = true; + + if (dlg.ShowDialog() != DialogResult.OK) + return; + + // this.SourceStyle = "barcodefile"; + + int nDupCount = 0; + string strRecPathFilename = Path.GetTempFileName(); + try + { + nRet = ConvertBarcodeFile(dlg.FileName, + strRecPathFilename, + out nDupCount, + out strError); + if (nRet == -1) + goto ERROR1; + + nRet = LoadFromRecPathFile(strRecPathFilename, + "图书", // this.comboBox_load_type.Text, + true, + new string[] { "summary", "@isbnissn", "targetrecpath" }, + false, + out strError); + if (nRet == -1) + goto ERROR1; + } + finally + { + if (string.IsNullOrEmpty(strRecPathFilename) == false) + { + File.Delete(strRecPathFilename); + strRecPathFilename = ""; + } + } + + if (nDupCount != 0) + { + MessageBox.Show(this, "装入过程中有 " + nDupCount.ToString() + "个重复条码事项被忽略。"); + } + +#if NO + // 记忆文件名 + this.BarcodeFilePath = dlg.FileName; + this.Text = "典藏移交 " + Path.GetFileName(this.BarcodeFilePath); + + // 汇报数据装载情况。 + // return: + // 0 尚未装载任何数据 + // 1 装载已经完成 + // 2 虽然装载了数据,但是其中有错误事项 + int nState = ReportLoadState(out strError); + if (nState != 1) + goto ERROR1; +#endif + return; + ERROR1: + MessageBox.Show(this, strError); + } + + /// + /// 允许或者禁止界面控件。在长操作前,一般需要禁止界面控件;操作完成后再允许 + /// + /// 是否允许界面控件。true 为允许, false 为禁止 + public override void EnableControls(bool bEnable) + { + // load page + // this.comboBox_load_type.Enabled = this.ScanMode == true ? false : bEnable; + this.button_load_loadFromBatchNo.Enabled = this.ScanMode == true ? false : bEnable; + this.button_load_loadFromBarcodeFile.Enabled = this.ScanMode == true ? false : bEnable; + this.button_load_loadFromRecPathFile.Enabled = this.ScanMode == true ? false : bEnable; + this.button_load_scanBarcode.Enabled = this.ScanMode == true ? false : bEnable; + + } + + bool _scanMode = false; + + /// + /// 是否处在扫描条码的状态? + /// + public bool ScanMode + { + get + { + return this._scanMode; + } + set + { + if (this._scanMode == value) + return; + + this._scanMode = value; + + // this.comboBox_load_type.Enabled = !this._scanMode; + this.button_load_loadFromBarcodeFile.Enabled = !this._scanMode; + this.button_load_loadFromBatchNo.Enabled = !this._scanMode; + this.button_load_loadFromRecPathFile.Enabled = !this._scanMode; + this.button_load_scanBarcode.Enabled = !this._scanMode; + + if (this._scanMode == false) + { + if (this._scanBarcodeForm != null) + this._scanBarcodeForm.Close(); + } + else + { + button_load_scanBarcode_Click(this, new EventArgs()); + } + } + } + + ScanBarcodeForm _scanBarcodeForm = null; + + private void button_load_scanBarcode_Click(object sender, EventArgs e) + { + + } + + // 检查路径所从属书目库是否为图书/期刊库? + // return: + // -1 error + // 0 不符合要求。提示信息在strError中 + // 1 符合要求 + internal override int CheckItemRecPath(string strPubType, + string strItemRecPath, + out string strError) + { + strError = ""; + + string strItemDbName = Global.GetDbName(strItemRecPath); + string strBiblioDbName = this.MainForm.GetBiblioDbNameFromItemDbName(strItemDbName); + if (String.IsNullOrEmpty(strBiblioDbName) == true) + { + strError = "实体库 '" + strItemDbName + "' 未找到对应的书目库名"; + return -1; + } + + return 1; +#if NO + string strIssueDbName = this.MainForm.GetIssueDbName(strBiblioDbName); + + if (strPubType == "图书") + { + if (String.IsNullOrEmpty(strIssueDbName) == false) + { + strError = "路径 '" + strItemRecPath + "' 所从属的书目库 '" + strBiblioDbName + "' 为期刊型,和当前出版物类型 '" + strPubType + "' 不一致"; + return 0; + } + return 1; + } + + if (strPubType == "连续出版物") + { + if (String.IsNullOrEmpty(strIssueDbName) == true) + { + strError = "路径 '" + strItemRecPath + "' 所从属的书目库 '" + strBiblioDbName + "' 为图书型,和当前出版物类型 '" + strPubType + "' 不一致"; + return 0; + } + return 1; + } + + strError = "CheckItemRecPath() 未知的出版物类型 '" + strPubType + "'"; + return -1; +#endif + } + + // 处理一小批记录的装入 + internal override int DoLoadRecords(List lines, + List items, + bool bFillSummaryColumn, + string[] summary_col_names, + out string strError) + { + strError = ""; + +#if DEBUG + if (items != null) + { + Debug.Assert(lines.Count == items.Count, ""); + } +#endif + + List records = new List(); + + // 集中获取全部册记录信息 + for (; ; ) + { + if (stop != null && stop.State != 0) + { + strError = "用户中断1"; + return -1; + } + + DigitalPlatform.LibraryClient.localhost.Record[] searchresults = null; + + string[] paths = new string[lines.Count]; + lines.CopyTo(paths); + REDO_GETRECORDS: + long lRet = this.Channel.GetBrowseRecords( + this.stop, + paths, + "id,xml,timestamp", // 注意,包含了 timestamp + out searchresults, + out strError); + if (lRet == -1) + { + if (this.InvokeRequired == false) + { + DialogResult temp_result = MessageBox.Show(this, + strError + "\r\n\r\n是否重试?", + this.FormCaption, + MessageBoxButtons.RetryCancel, + MessageBoxIcon.Question, + MessageBoxDefaultButton.Button1); + if (temp_result == DialogResult.Retry) + goto REDO_GETRECORDS; + } + return -1; + } + + records.AddRange(searchresults); + + // 去掉已经做过的一部分 + lines.RemoveRange(0, searchresults.Length); + + if (lines.Count == 0) + break; + } + + // 准备 DOM 和书目摘要等 + List infos = null; + int nRet = GetSummaries( + bFillSummaryColumn, + summary_col_names, + records, + out infos, + out strError); + if (nRet == -1) + return -1; + + Debug.Assert(records.Count == infos.Count, ""); + + List orderinfos = new List(); + + if (this.InvokeRequired == false) + this.listView_in.BeginUpdate(); + try + { + for (int i = 0; i < infos.Count; i++) + { + if (stop != null) + { + if (stop.State != 0) + { + strError = "用户中断1"; + return -1; + } + } + + RecordInfo info = infos[i]; + + if (info.Record.RecordBody == null) + { + strError = "请升级 dp2Kernel 到最新版本"; + return -1; + } + // stop.SetMessage("正在装入路径 " + strLine + " 对应的记录..."); + + string strOutputItemRecPath = ""; + ListViewItem item = null; + + if (items != null) + item = items[i]; + + // 根据册条码号,装入册记录 + // return: + // -2 册条码号已经在list中存在了 + // -1 出错 + // 1 成功 + nRet = LoadOneItem( + "图书", // this.LoadType, // this.comboBox_load_type.Text, + bFillSummaryColumn, + summary_col_names, + "@path:" + info.Record.Path, + info, + this.listView_in, + null, + out strOutputItemRecPath, + ref item, + out strError); + + +#if NO + // 准备装入订购信息 + if (nRet != -1 && this.checkBox_load_fillOrderInfo.Checked == true) + { + Debug.Assert(item != null, ""); + string strRefID = ListViewUtil.GetItemText(item, COLUMN_REFID); + if (String.IsNullOrEmpty(strRefID) == false) + { + OrderInfo order_info = new OrderInfo(); + order_info.ItemRefID = strRefID; + order_info.ListViewItem = item; + orderinfos.Add(order_info); + } + } +#endif + + } + } + finally + { + if (this.InvokeRequired == false) + this.listView_in.EndUpdate(); + } + +#if NO + // 从服务器获得订购记录的路径 + if (orderinfos.Count > 0) + { + nRet = LoadOrderInfo( + orderinfos, + out strError); + if (nRet == -1) + return -1; + } +#endif + + return 0; + } } } diff --git a/dp2Circulation/ItemHandOver/ItemHandoverForm.cs b/dp2Circulation/ItemHandOver/ItemHandoverForm.cs index a5c88ac1c..9c416e98b 100644 --- a/dp2Circulation/ItemHandOver/ItemHandoverForm.cs +++ b/dp2Circulation/ItemHandOver/ItemHandoverForm.cs @@ -202,6 +202,7 @@ private void ItemHandoverForm_Load(object sender, EventArgs e) { MainForm.SetControlFont(this, this.MainForm.DefaultFont); } + CreateColumnHeader(this.listView_in); CreateColumnHeader(this.listView_outof); diff --git a/dp2Circulation/MainForm/MainForm.Designer.cs b/dp2Circulation/MainForm/MainForm.Designer.cs index 8515e0461..663483fe7 100644 --- a/dp2Circulation/MainForm/MainForm.Designer.cs +++ b/dp2Circulation/MainForm/MainForm.Designer.cs @@ -216,6 +216,7 @@ private void InitializeComponent() this.toolStripButton_close = new System.Windows.Forms.ToolStripButton(); this.splitter_fixed = new System.Windows.Forms.Splitter(); this.timer_operHistory = new System.Windows.Forms.Timer(this.components); + this.MenuItem_importExport = new System.Windows.Forms.ToolStripMenuItem(); this.menuStrip_main.SuspendLayout(); this.statusStrip_main.SuspendLayout(); this.toolStrip_main.SuspendLayout(); @@ -959,6 +960,7 @@ private void InitializeComponent() this.MenuItem_printAccountBook, this.MenuItem_printBindingList, this.MenuItem_inventory, + this.MenuItem_importExport, this.toolStripSeparator17, this.MenuItem_openTestSearch}); this.MenuItem_batch.Name = "MenuItem_batch"; @@ -1744,6 +1746,13 @@ private void InitializeComponent() this.splitter_fixed.TabIndex = 6; this.splitter_fixed.TabStop = false; // + // MenuItem_importExport + // + this.MenuItem_importExport.Name = "MenuItem_importExport"; + this.MenuItem_importExport.Size = new System.Drawing.Size(152, 22); + this.MenuItem_importExport.Text = "뵼(&I)"; + this.MenuItem_importExport.Click += new System.EventHandler(this.MenuItem_importExport_Click); + // // MainForm // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); @@ -1972,6 +1981,7 @@ private void InitializeComponent() private System.Windows.Forms.ToolStripButton toolStripButton_messageHub_userManage; private System.Windows.Forms.TableLayoutPanel tableLayoutPanel_messageHub; private System.Windows.Forms.ToolStripButton toolStripButton_messageHub_relogin; + private System.Windows.Forms.ToolStripMenuItem MenuItem_importExport; } } diff --git a/dp2Circulation/MainForm/MainForm.cs b/dp2Circulation/MainForm/MainForm.cs index 1795b463e..9eadbfaf0 100644 --- a/dp2Circulation/MainForm/MainForm.cs +++ b/dp2Circulation/MainForm/MainForm.cs @@ -2365,6 +2365,72 @@ Form GetTopChildWindow(Type type) return null; } + // 得到顶层MDI窗口 + // 注: this.ActiveMdiChild 不一定在最顶层 + Form GetTopChildWindow() + { + if (this.MdiChildren.Length == 0) + return null; + List handles = new List(); + foreach (Form mdi in this.MdiChildren) + { + handles.Add(mdi.Handle); + } + + IntPtr hwnd = this.ActiveMdiChild.Handle; + IntPtr top = hwnd; + while (hwnd != IntPtr.Zero) + { + if (handles.IndexOf(hwnd) != -1) + top = hwnd; + + hwnd = API.GetWindow(hwnd, API.GW_HWNDPREV); + } + + foreach (Form mdi in this.MdiChildren) + { + if (mdi.Handle == top) + return mdi; + } + + return null; + } +#if NO + // 得到顶层MDI窗口 + // 注: this.ActiveMdiChild 不一定在最顶层 + Form GetTopChildWindow() + { + if (ActiveMdiChild == null) + return null; + + // 得到顶层的MDI Child + IntPtr hwnd = this.ActiveMdiChild.Handle; + if (hwnd == IntPtr.Zero) + return null; + + for (; ; ) + { + if (hwnd == IntPtr.Zero) + break; + + Form child = null; + for (int j = 0; j < this.MdiChildren.Length; j++) + { + if (hwnd == this.MdiChildren[j].Handle) + { + child = this.MdiChildren[j]; + return child; + } + } + + hwnd = API.GetWindow(hwnd, API.GW_HWNDPREV); + } + + return this.ActiveMdiChild; + } + +#endif + // 是否为MDI子窗口中最顶层的2个之一? // 2008/9/8 internal bool IsTopTwoChildWindow(Form form) @@ -4016,6 +4082,41 @@ private void toolStripTextBox_barcode_KeyDown(object sender, KeyEventArgs e) } + // return: + // true 已经装载 + // false 没有装载 + bool TryLoadItemBarcodeToItemSearchForm() + { + Form top = this.GetTopChildWindow(); + if (top != null && top is ItemSearchForm) + { + ItemSearchForm form = top as ItemSearchForm; + form.Activate(); + List barcodes = new List(); + barcodes.Add(this.toolStripTextBox_barcode.Text); + + form.ClearMessage(); + string strError = ""; + // 往列表中追加若干册条码号 + // return: + // -1 出错 + // 0 成功 + // 1 成功,但有警告,警告在 strError 中返回 + int nRet = form.AppendBarcodes(barcodes, out strError); + if (nRet == -1 || nRet == 1) + { + // MessageBox.Show(this, strError); + form.ShowMessage(strError, "red", true); + } + + this.toolStripTextBox_barcode.SelectAll(); + this.toolStripTextBox_barcode.Focus(); + return true; + } + + return false; + } + // 装入册条码号相关记录 // 尽量占用当前已经打开的种册窗 void LoadItemBarcode() @@ -4026,20 +4127,8 @@ void LoadItemBarcode() return; } - /* - ItemInfoForm form = this.TopItemInfoForm; - - if (form == null) - { - // 新开一个实体窗 - form = new ItemInfoForm(); - form.MdiParent = this; - form.MainForm = this; - form.Show(); - } - - form.LoadRecord(this.toolStripTextBox_barcode.Text); - * */ + if (TryLoadItemBarcodeToItemSearchForm() == true) + return; EntityForm form = this.GetTopChildWindow(); @@ -4134,35 +4223,11 @@ void LoadItemOrReaderBarcode() } if (nRet == 1) - { - /* - ReaderInfoForm form = this.TopReaderInfoForm; - - if (form == null) - { - // 新开一个读者窗 - form = new ReaderInfoForm(); - form.MdiParent = this; - form.MainForm = this; - form.Show(); - } - else - Global.Activate(form); - - - form.LoadRecord(this.toolStripTextBox_barcode.Text, - false); - * */ LoadReaderBarcode(); - } if (nRet == 2) - { LoadItemBarcode(); - } - return; - ERROR1: MessageBox.Show(this, strError); } @@ -7119,12 +7184,6 @@ public void BeginInvokeScript( private void MenuItem_inventory_Click(object sender, EventArgs e) { -#if NO - NewInventoryForm form = new NewInventoryForm(); - form.MdiParent = this; - form.Show(); -#endif - // OpenWindow(); if (StringUtil.CompareVersion(this.ServerVersion, "2.50") < 0) { MessageBox.Show(this, "dp2library 版本 2.50 和以上才能使用 盘点窗"); @@ -7133,6 +7192,11 @@ private void MenuItem_inventory_Click(object sender, EventArgs e) OpenWindow(); } + private void MenuItem_importExport_Click(object sender, EventArgs e) + { + OpenWindow(); + } + private void tabControl_panelFixed_SizeChanged(object sender, EventArgs e) { if (this.qrRecognitionControl1 != null) @@ -8298,6 +8362,8 @@ private void toolStripButton_messageHub_relogin_Click(object sender, EventArgs e this.MessageHub.Connect(); this.MessageHub.Login(); } + + } /// diff --git a/dp2Circulation/SearchForms/BiblioSearchForm.cs b/dp2Circulation/SearchForms/BiblioSearchForm.cs index d71ee3e92..ee91a4e19 100644 --- a/dp2Circulation/SearchForms/BiblioSearchForm.cs +++ b/dp2Circulation/SearchForms/BiblioSearchForm.cs @@ -2106,6 +2106,12 @@ private void listView_records_MouseUp(object sender, MouseEventArgs e) if (this.listView_records.SelectedItems.Count == 0) subMenuItem.Enabled = false; menuItem.MenuItems.Add(subMenuItem); + + subMenuItem = new MenuItem("导出书目转储文件 [" + this.listView_records.SelectedItems.Count.ToString() + " ] (&B)..."); + subMenuItem.Click += new System.EventHandler(this.menu_saveToBiblioDumpFile_Click); + if (this.listView_records.SelectedItems.Count == 0) + subMenuItem.Enabled = false; + menuItem.MenuItems.Add(subMenuItem); } // 装入其它查询窗 @@ -4284,6 +4290,10 @@ int CopyToAnotherDatabase( stop.SetMessage("正在" + strActionName + "书目记录 '" + strRecPath + "' 到 '" + dlg.RecPath + "' ..."); + // 2016/3/23 + channel.Timeout = new TimeSpan(0, 40, 0); // 复制的时候可能需要复制对象,所需时间一般很长 + + REDO: // result.Value: // -1 出错 // 0 成功,没有警告信息。 @@ -4303,11 +4313,24 @@ int CopyToAnotherDatabase( out baOutputTimestamp, out strError); if (lRet == -1) + { + DialogResult result = MessageBox.Show(this, +"复制或移动书目记录 '" + strRecPath + " --> " + dlg.RecPath + "' 时出现错误: " + strError + "。\r\n\r\n是否重试? (Yes 重试;No 跳过此条、继续后面处理;Cancel 放弃未完成的操作)", +"BiblioSearchForm", +MessageBoxButtons.YesNoCancel, +MessageBoxIcon.Question, +MessageBoxDefaultButton.Button1); + if (result == System.Windows.Forms.DialogResult.Yes) + goto REDO; + if (result == System.Windows.Forms.DialogResult.No) + goto CONTINUE; goto ERROR1; + } if (bCopy == false) moved_items.Add(item); + CONTINUE: stop.SetProgressValue(++i); } @@ -5771,6 +5794,7 @@ void menu_deleteSelectedRecords_Click(object sender, EventArgs e) byte[] baNewTimestamp = null; + channel.Timeout = new TimeSpan(0, 5, 0); lRet = channel.SetBiblioInfo( stop, "delete", @@ -5950,6 +5974,362 @@ public string LastCatalogingRule } } + // 导出到书目转储文件 + void menu_saveToBiblioDumpFile_Click(object sender, EventArgs e) + { + string strError = ""; + int nRet = 0; + + if (this.listView_records.SelectedItems.Count == 0) + { + strError = "尚未选定要导出的事项"; + goto ERROR1; + } + + // 询问文件名 + SaveFileDialog dlg = new SaveFileDialog(); + + dlg.Title = "请指定要创建的书目转储件名"; + dlg.CreatePrompt = false; + dlg.OverwritePrompt = true; + dlg.FileName = ""; + // dlg.InitialDirectory = Environment.CurrentDirectory; + dlg.Filter = "书目转储文件 (*.bdf)|*.bdf|All files (*.*)|*.*"; + + dlg.RestoreDirectory = true; + + if (dlg.ShowDialog() != DialogResult.OK) + return; + + this.EnableControls(false); + + LibraryChannel channel = this.GetChannel(); + + stop.OnStop += new StopEventHandler(this.DoStop); + stop.Initial("正在导出到 XML 文件 ..."); + stop.BeginLoop(); + + XmlTextWriter writer = null; + + try + { + writer = new XmlTextWriter(dlg.FileName, Encoding.UTF8); + } + catch (Exception ex) + { + strError = "创建文件 " + dlg.FileName + " 失败,原因: " + ex.Message; + goto ERROR1; + } + + try + { + stop.SetProgressRange(0, this.listView_records.SelectedItems.Count); + + writer.Formatting = Formatting.Indented; + writer.Indentation = 4; + + writer.WriteStartDocument(); + writer.WriteStartElement("dprms", "collection", DpNs.dprms); + + writer.WriteAttributeString("xmlns", "dprms", null, DpNs.dprms); +#if NO + writer.WriteAttributeString("xmlns", "unimarc", null, DigitalPlatform.Xml.Ns.unimarcxml); + writer.WriteAttributeString("xmlns", "marc21", null, DigitalPlatform.Xml.Ns.usmarcxml); +#endif + + List items = new List(); + foreach (ListViewItem item in this.listView_records.SelectedItems) + { + if (string.IsNullOrEmpty(item.Text) == true) + continue; + + items.Add(item); + } + + ListViewBiblioLoader loader = new ListViewBiblioLoader(channel, // this.Channel, + stop, + items, + this.m_biblioTable); + loader.Prompt -= new MessagePromptEventHandler(loader_Prompt); + loader.Prompt += new MessagePromptEventHandler(loader_Prompt); + + int i = 0; + foreach (LoaderItem item in loader) + { + Application.DoEvents(); // 出让界面控制权 + + if (stop != null && stop.State != 0) + { + strError = "用户中断"; + goto ERROR1; + } + + BiblioInfo info = item.BiblioInfo; + + string strXml = ""; + { + if (string.IsNullOrEmpty(info.NewXml) == false) + strXml = info.NewXml; + else + strXml = info.OldXml; + } + + if (string.IsNullOrEmpty(strXml) == true) + goto CONTINUE; + + XmlDocument dom = new XmlDocument(); + try + { + dom.LoadXml(strXml); + } + catch (Exception ex) + { + strError = "XML 装入 DOM 时出错: " + ex.Message; + goto ERROR1; + } + + if (dom.DocumentElement == null) + goto CONTINUE; + + // 写入 dprms:record 元素 + writer.WriteStartElement("dprms", "record", DpNs.dprms); + + { + // 写入 dprms:biblio 元素 + writer.WriteStartElement("dprms", "biblio", DpNs.dprms); + + writer.WriteAttributeString("path", this.MainForm.LibraryServerUrl + "?" + item.BiblioInfo.RecPath); + writer.WriteAttributeString("timestamp", ByteArray.GetHexTimeStampString(item.BiblioInfo.Timestamp)); + + dom.DocumentElement.WriteTo(writer); + writer.WriteEndElement(); + } + + string strBiblioDbName = StringUtil.GetDbName(item.BiblioInfo.RecPath); + BiblioDbProperty prop = this.MainForm.GetBiblioDbProperty(strBiblioDbName); + if (prop == null) + { + strError = "数据库名 '"+strBiblioDbName+"' 没有找到属性定义"; + goto ERROR1; + } + + if (string.IsNullOrEmpty(prop.OrderDbName) == false) + { + // dprms:orderCollection + nRet = OutputEntities( + stop, + channel, + item.BiblioInfo.RecPath, + "order", + writer, + out strError); + if (nRet == -1) + goto ERROR1; + } + if (string.IsNullOrEmpty(prop.IssueDbName) == false) + { + // dprms:issueCollection + nRet = OutputEntities( + stop, + channel, + item.BiblioInfo.RecPath, + "issue", + writer, + out strError); + if (nRet == -1) + goto ERROR1; + } + if (string.IsNullOrEmpty(prop.ItemDbName) == false) + { + // dprms:itemCollection + nRet = OutputEntities( + stop, + channel, + item.BiblioInfo.RecPath, + "item", + writer, + out strError); + if (nRet == -1) + goto ERROR1; + } + if (string.IsNullOrEmpty(prop.CommentDbName) == false) + { + // dprms:commentCollection + nRet = OutputEntities( + stop, + channel, + item.BiblioInfo.RecPath, + "comment", + writer, + out strError); + if (nRet == -1) + goto ERROR1; + } + // 收尾 dprms:record 元素 + writer.WriteEndElement(); + + CONTINUE: + stop.SetProgressValue(++i); + } + + writer.WriteEndElement(); // + writer.WriteEndDocument(); + } + catch (Exception ex) + { + strError = "写入文件 " + dlg.FileName + " 失败,原因: " + ex.Message; + goto ERROR1; + } + finally + { + writer.Close(); + + stop.EndLoop(); + stop.OnStop -= new StopEventHandler(this.DoStop); + stop.Initial(""); + stop.HideProgress(); + + this.ReturnChannel(channel); + + this.EnableControls(true); + } + + MainForm.StatusBarMessage = this.listView_records.SelectedItems.Count.ToString() + + "条记录成功保存到文件 " + dlg.FileName; + return; + ERROR1: + MessageBox.Show(this, strError); + } + + public static int OutputEntities( + Stop stop, + LibraryChannel channel, + string strBiblioRecPath, + string strDbType, + XmlTextWriter writer, + out string strError) + { + strError = ""; + + bool bBegin = false; + + long lPerCount = 100; // 每批获得多少个 + long lStart = 0; + long lResultCount = 0; + long lCount = -1; + for (; ; ) + { + if (stop != null && stop.State != 0) + { + strError = "用户中断"; + return -1; + } + + EntityInfo[] entities = null; + + long lRet = 0; + + channel.Timeout = new TimeSpan(0, 5, 0); + if (strDbType == "item") + { + lRet = channel.GetEntities( + stop, + strBiblioRecPath, + lStart, + lCount, + "", // "onlygetpath", + "zh", + out entities, + out strError); + } + if (strDbType == "order") + { + lRet = channel.GetOrders( + stop, + strBiblioRecPath, + lStart, + lCount, + "", // "onlygetpath", + "zh", + out entities, + out strError); + } + if (strDbType == "issue") + { + lRet = channel.GetIssues( + stop, + strBiblioRecPath, + lStart, + lCount, + "", // "onlygetpath", + "zh", + out entities, + out strError); + } + if (strDbType == "comment") + { + lRet = channel.GetComments( + stop, + strBiblioRecPath, + lStart, + lCount, + "", // "onlygetpath", + "zh", + out entities, + out strError); + } + if (lRet == -1) + return -1; + + lResultCount = lRet; + + if (lRet == 0) + return 0; + + Debug.Assert(entities != null, ""); + + foreach (EntityInfo info in entities) + { + if (info.ErrorCode != ErrorCodeValue.NoError) + { + strError = "路径为 '" + info.OldRecPath + "' 的册记录装载中发生错误: " + info.ErrorInfo; // NewRecPath + return -1; + } + + if (bBegin == false) + { + writer.WriteStartElement("dprms", strDbType + "Collection", DpNs.dprms); + bBegin = true; + } + + XmlDocument item_dom = new XmlDocument(); + item_dom.LoadXml(info.OldRecord); + + writer.WriteStartElement("dprms", strDbType, DpNs.dprms); + writer.WriteAttributeString("path", info.OldRecPath); + writer.WriteAttributeString("timestamp", ByteArray.GetHexTimeStampString(info.OldTimestamp)); + DomUtil.RemoveEmptyElements(item_dom.DocumentElement); + item_dom.DocumentElement.WriteContentTo(writer); + writer.WriteEndElement(); + } + + lStart += entities.Length; + if (lStart >= lResultCount) + break; + + if (lCount == -1) + lCount = lPerCount; + + if (lStart + lCount > lResultCount) + lCount = lResultCount - lStart; + } + + if (bBegin == true) + writer.WriteEndElement(); + + return 1; + } + void menu_saveToXmlFile_Click(object sender, EventArgs e) { string strError = ""; @@ -5961,11 +6341,13 @@ void menu_saveToXmlFile_Click(object sender, EventArgs e) goto ERROR1; } +#if NO Encoding preferredEncoding = this.CurrentEncoding; { // 观察要保存的第一条记录的marc syntax } +#endif // 询问文件名 SaveFileDialog dlg = new SaveFileDialog(); @@ -7190,6 +7572,7 @@ private void ToolStripMenuItem_continueLoad_Click(object sender, EventArgs e) strStyle = "id,cols"; } + channel.Timeout = new TimeSpan(0, 5, 0); long lRet = channel.GetSearchResult( stop, null, // strResultSetName diff --git a/dp2Circulation/SearchForms/ItemSearchForm.cs b/dp2Circulation/SearchForms/ItemSearchForm.cs index 193d095c4..c522c07a3 100644 --- a/dp2Circulation/SearchForms/ItemSearchForm.cs +++ b/dp2Circulation/SearchForms/ItemSearchForm.cs @@ -67,6 +67,11 @@ public partial class ItemSearchForm : ItemSearchFormBase /// public string ExportItemRecPathFilename = ""; + /// + /// 最近一次导出到书目转储文件时使用过的文件名 + /// + public string ExportBiblioDumpFilename = ""; + /// /// 浏览框。显示检索命中记录的浏览格式 /// @@ -1623,6 +1628,9 @@ private void ItemSearchForm_Activated(object sender, EventArgs e) this.MainForm.MenuItem_recoverUrgentLog.Enabled = false; // this.MainForm.MenuItem_font.Enabled = false; // this.MainForm.MenuItem_restoreDefaultFont.Enabled = false; + + this.MainForm.toolStripDropDownButton_barcodeLoadStyle.Enabled = true; + this.MainForm.toolStripTextBox_barcode.Enabled = true; } // 装入种册窗/实体窗,用册条码号/记录路径 @@ -2333,6 +2341,15 @@ private void listView_records_MouseUp(object sender, MouseEventArgs e) subMenuItem.Enabled = false; menuItemExport.MenuItems.Add(subMenuItem); + if (this.DbType == "item") + { + subMenuItem = new MenuItem("到书目转储文件 [" + (nPathItemCount == -1 ? "?" : nPathItemCount.ToString()) + "] (&B)..."); + subMenuItem.Click += new System.EventHandler(this.menu_exportBiblioDumpFile_Click); + if (nPathItemCount == 0) + subMenuItem.Enabled = false; + menuItemExport.MenuItems.Add(subMenuItem); + } + // --- subMenuItem = new MenuItem("-"); menuItemExport.MenuItems.Add(subMenuItem); @@ -4951,6 +4968,129 @@ void menu_pasteFromClipboard_insertAfter_Click(object sender, EventArgs e) listView_records_SelectedIndexChanged(null, null); } + // 往列表中追加若干册条码号 + // return: + // -1 出错 + // 0 成功 + // 1 成功,但有警告,警告在 strError 中返回 + public int AppendBarcodes(List barcodes, + out string strError) + { + strError = ""; + int nRet = 0; + + SetStatusMessage(""); // 清除以前残留的显示 + + stop.OnStop += new StopEventHandler(this.DoStop); + stop.Initial("正在导入条码号 ..."); + stop.BeginLoop(); + + try + { + // 准备查重 + Hashtable table = new Hashtable(); + foreach (ListViewItem item in this.listView_records.Items) + { + string strBarcode = ""; + // 根据 ListViewItem 对象,获得册条码号列的内容 + nRet = GetItemBarcodeOrRefID( + item, + true, + out strBarcode, + out strError); + if (nRet == -1) + return -1; + table[strBarcode] = 1; + } + + List dups = new List(); + List errors = new List(); + + // 导入的事项是没有序的,因此需要清除已有的排序标志 + ListViewUtil.ClearSortColumns(this.listView_records); + + stop.SetProgressRange(0, barcodes.Count); + + List items = new List(); + + int i = 0; + foreach (string strBarcode in barcodes) + { + Application.DoEvents(); // 出让界面控制权 + + if (stop != null && stop.State != 0) + { + strError = "用户中断"; + return -1; + } + + stop.SetProgressValue(i); + + if (strBarcode == null) + break; + + if (table.ContainsKey(strBarcode) == true) + { + dups.Add(strBarcode); + continue; + } + + ListViewItem item = new ListViewItem(); + item.Text = ""; + + // return: + // false 出现错误 + // true 成功 + if (FillLineByBarcode(strBarcode, item) == true) + { + this.listView_records.Items.Add(item); + items.Add(item); + } + else + errors.Add(item.SubItems[2].Text); + + i++; + } + + // 刷新浏览行 + nRet = RefreshListViewLines(items, + "", + false, + true, + out strError); + if (nRet == -1) + return -1; + + // 刷新书目摘要 + nRet = FillBiblioSummaryColumn(items, + false, + out strError); + if (nRet == -1) + return -1; + + if (errors.Count > 0) + { + strError = StringUtil.MakePathList(errors, "\r\n"); + return -1; + } + + if (dups.Count > 0) + { + strError = "下列册条码号已经在列表中存在了: " + StringUtil.MakePathList(dups); + return 1; + } + return 0; + } + finally + { + stop.EndLoop(); + stop.OnStop -= new StopEventHandler(this.DoStop); + stop.Initial(""); + stop.HideProgress(); + } + } + + // TODO: 优化速度 void menu_importFromBarcodeFile_Click(object sender, EventArgs e) { @@ -4991,7 +5131,6 @@ void menu_importFromBarcodeFile_Click(object sender, EventArgs e) // 导入的事项是没有序的,因此需要清除已有的排序标志 ListViewUtil.ClearSortColumns(this.listView_records); - if (this.listView_records.Items.Count > 0) { DialogResult result = MessageBox.Show(this, @@ -5016,26 +5155,19 @@ void menu_importFromBarcodeFile_Click(object sender, EventArgs e) { Application.DoEvents(); // 出让界面控制权 - if (stop != null) + if (stop != null && stop.State != 0) { - if (stop.State != 0) - { - MessageBox.Show(this, "用户中断"); - return; - } + MessageBox.Show(this, "用户中断"); + return; } string strBarcode = sr.ReadLine(); stop.SetProgressValue(sr.BaseStream.Position); - if (strBarcode == null) break; - // - - ListViewItem item = new ListViewItem(); item.Text = ""; // ListViewUtil.ChangeItemText(item, 1, strBarcode); @@ -5144,8 +5276,6 @@ public int RefreshBrowseLine(ListViewItem item, return 0; } - - // 导出选择的行中有路径的部分行 的条码栏内容 为条码号文件 void menu_exportBarcodeFile_Click(object sender, EventArgs e) { @@ -5410,6 +5540,227 @@ static int LoadRuleNameTable(string strFilename, return 1; } + int GetSelectedBiblioRecPath( + ref List biblioRecPathList,// 按照出现先后的顺序存储书目记录路径 + ref Hashtable groupTable, // 书目记录路径 --> List (册记录路径列表) + out string strError) + { + strError = ""; + int nRet = 0; + + stop.SetProgressRange(0, this.listView_records.SelectedItems.Count); + + int i = 0; + foreach (ListViewItem item in this.listView_records.SelectedItems) + { + stop.SetProgressValue(i++); + + Application.DoEvents(); // 出让界面控制权 + + if (stop != null + && stop.State != 0) + { + strError = "用户中断"; + return -1; + } + + if (string.IsNullOrEmpty(item.Text) == true) + continue; + + int nCol = -1; + string strBiblioRecPath = ""; + // 获得事项所从属的书目记录的路径 + // return: + // -1 出错 + // 0 相关数据库没有配置 parent id 浏览列 + // 1 找到 + nRet = GetBiblioRecPath(item, + true, + out nCol, + out strBiblioRecPath, + out strError); + if (nRet == -1) + return -1; + if (nRet == 0) + return -1; + + List item_recpaths = (List)groupTable[strBiblioRecPath]; + if (item_recpaths == null) + { + biblioRecPathList.Add(strBiblioRecPath); + item_recpaths = new List(); + groupTable[strBiblioRecPath] = item_recpaths; + } + + item_recpaths.Add(item.Text); + } + + return 0; + } + + // 保存选择的行中的有路径的部分行 到书目转储文件 + // 需要先将册记录按照书目记录路径聚集 + void menu_exportBiblioDumpFile_Click(object sender, EventArgs e) + { + string strError = ""; + int nRet = 0; + + List biblioRecPathList = new List(); // 按照出现先后的顺序存储书目记录路径 + + Hashtable groupTable = new Hashtable(); // 书目记录路径 --> List (册记录路径列表) + + + // 询问文件名 + SaveFileDialog dlg = new SaveFileDialog(); + + dlg.Title = "请指定要创建的书目转储文件名"; + dlg.CreatePrompt = false; + dlg.OverwritePrompt = true; + dlg.FileName = this.ExportBiblioDumpFilename; + // dlg.InitialDirectory = Environment.CurrentDirectory; + dlg.Filter = "书目转储文件 (*.bdf)|*.bdf|All files (*.*)|*.*"; + + dlg.RestoreDirectory = true; + + if (dlg.ShowDialog() != DialogResult.OK) + return; + + this.ExportBiblioDumpFilename = dlg.FileName; + + stop.OnStop += new StopEventHandler(this.DoStop); + stop.Initial("正在导出书目转储记录 ..."); + stop.BeginLoop(); + + try + { + using (XmlTextWriter w = new XmlTextWriter( + this.ExportBiblioDumpFilename, Encoding.UTF8)) + { + w.Formatting = Formatting.Indented; + w.Indentation = 4; + + w.WriteStartDocument(); + w.WriteStartElement("dprms", "collection", DpNs.dprms); + w.WriteAttributeString("xmlns", "dprms", null, DpNs.dprms); + + nRet = GetSelectedBiblioRecPath( + ref biblioRecPathList,// 按照出现先后的顺序存储书目记录路径 + ref groupTable, // 书目记录路径 --> List (册记录路径列表) + out strError); + if (nRet == -1) + goto ERROR1; + + foreach (string strBiblioRecPath in biblioRecPathList) + { + Application.DoEvents(); + + if (stop != null && stop.State != 0) + { + strError = "用户中断"; + goto ERROR1; + } + + string[] results = null; + byte[] baTimestamp = null; + + stop.SetMessage("正在获取书目记录 " + strBiblioRecPath); + + long lRet = Channel.GetBiblioInfos( + stop, + strBiblioRecPath, + "", + new string[] { "xml" }, // formats + out results, + out baTimestamp, + out strError); + if (lRet == 0) + goto ERROR1; + if (lRet == -1) + goto ERROR1; + + if (results == null || results.Length == 0) + { + strError = "results error"; + goto ERROR1; + } + + string strXml = results[0]; + XmlDocument domBiblio = new XmlDocument(); + domBiblio.LoadXml(strXml); + + // 写入 dprms:record 元素 + w.WriteStartElement("dprms", "record", DpNs.dprms); + + // 写入 dprms:biblio 元素 + w.WriteStartElement("dprms", "biblio", DpNs.dprms); + +#if NO + // 给根元素设置几个参数 + DomUtil.SetAttr(domBiblio.DocumentElement, "path", DpNs.dprms, this.MainForm.LibraryServerUrl + "?" + item.BiblioInfo.RecPath); // strRecPath + DomUtil.SetAttr(domBiblio.DocumentElement, "timestamp", DpNs.dprms, ByteArray.GetHexTimeStampString(item.BiblioInfo.Timestamp)); // baTimestamp +#endif + + w.WriteAttributeString("path", this.MainForm.LibraryServerUrl + "?" + strBiblioRecPath); + w.WriteAttributeString("timestamp", ByteArray.GetHexTimeStampString(baTimestamp)); + + domBiblio.DocumentElement.WriteTo(w); + w.WriteEndElement(); + + w.WriteStartElement("dprms", "itemCollection", DpNs.dprms); + List item_recpaths = (List)groupTable[strBiblioRecPath]; + foreach (string item_recpath in item_recpaths) + { + + string strItemXml = ""; + byte[] baItemTimestamp = null; + // 获得一条记录 + //return: + // -1 出错 + // 0 没有找到 + // 1 找到 + nRet = GetRecord( + item_recpath, + out strItemXml, + out baItemTimestamp, + out strError); + if (nRet == -1) + goto ERROR1; + + XmlDocument item_dom = new XmlDocument(); + item_dom.LoadXml(strItemXml); + + w.WriteStartElement("dprms", "item", DpNs.dprms); + w.WriteAttributeString("path", item_recpath); + w.WriteAttributeString("timestamp", ByteArray.GetHexTimeStampString(baItemTimestamp)); + DomUtil.RemoveEmptyElements(item_dom.DocumentElement); + item_dom.DocumentElement.WriteContentTo(w); + w.WriteEndElement(); + } + w.WriteEndElement(); + + // 收尾 dprms:record 元素 + w.WriteEndElement(); + } + + w.WriteEndElement(); + w.WriteEndDocument(); + } + } + finally + { + stop.EndLoop(); + stop.OnStop -= new StopEventHandler(this.DoStop); + stop.Initial(""); + stop.HideProgress(); + } + + this.MainForm.StatusBarMessage = "书目记录 " + groupTable.Count.ToString() + "个 已成功导出到文件 " + this.ExportBiblioDumpFilename; + return; + ERROR1: + MessageBox.Show(this, strError); + } + + // 将从属的书目记录保存到MARC文件 void menu_saveBiblioRecordToMarcFile_Click(object sender, EventArgs e) { diff --git a/dp2Circulation/SearchForms/ItemSearchFormBase.cs b/dp2Circulation/SearchForms/ItemSearchFormBase.cs index f31fdc74e..646759561 100644 --- a/dp2Circulation/SearchForms/ItemSearchFormBase.cs +++ b/dp2Circulation/SearchForms/ItemSearchFormBase.cs @@ -1028,7 +1028,10 @@ public virtual int GetBiblioRecPath(ListViewItem item, return 1; } - internal void FillLineByBarcode( + // return: + // false 出现错误 + // true 成功 + internal bool FillLineByBarcode( string strBarcode, ListViewItem item) { @@ -1049,12 +1052,12 @@ internal void FillLineByBarcode( if (nRet == -1) { ListViewUtil.ChangeItemText(item, 2, strError); - return; + return false; } else if (nRet == 0) { ListViewUtil.ChangeItemText(item, 2, "条码号 '" + strBarcode + "' 没有找到记录"); - return; + return false; } else if (nRet == 1) { @@ -1063,7 +1066,7 @@ internal void FillLineByBarcode( else if (nRet > 1) // 命中发生重复 { ListViewUtil.ChangeItemText(item, 2, "条码号 '" + strBarcode + "' 命中 " + nRet.ToString() + " 条记录,这是一个严重错误"); - return; + return false; } string strItemDbName = Global.GetDbName(strItemRecPath); @@ -1074,6 +1077,7 @@ internal void FillLineByBarcode( ListViewUtil.ChangeItemText(item, index, strBarcode); // TODO: 将书目记录路径放入item.Tag中备用 + return true; } // 根据册条码号,检索出其册记录路径和从属的书目记录路径,以及馆藏地点信息。 diff --git a/dp2Circulation/dp2Circulation.csproj b/dp2Circulation/dp2Circulation.csproj index 5aa891057..4a6c42120 100644 --- a/dp2Circulation/dp2Circulation.csproj +++ b/dp2Circulation/dp2Circulation.csproj @@ -51,7 +51,7 @@ dp2 V2 true publish.htm - 29 + 30 2.10.0.%2a false true diff --git a/dp2Installer/opac_app/Test.aspx.cs b/dp2Installer/opac_app/Test.aspx.cs new file mode 100644 index 000000000..25fda95ae --- /dev/null +++ b/dp2Installer/opac_app/Test.aspx.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; +using System.Web.UI; +using System.Web.UI.WebControls; + +namespace WebApplication1 +{ + public partial class Test : System.Web.UI.Page + { + protected void Page_Load(object sender, EventArgs e) + { + + } + } +} \ No newline at end of file From 88a3a4f48cb2dd4c896743dde36eaebe40578490 Mon Sep 17 00:00:00 2001 From: XieTao Date: Mon, 28 Mar 2016 17:19:19 +0800 Subject: [PATCH 03/10] =?UTF-8?q?=E5=AE=8C=E5=96=84=E8=AF=BB=E8=80=85=20ri?= =?UTF-8?q?ghts=20=E8=AE=BE=E7=BD=AE=E5=8A=9F=E8=83=BD;=20=E5=AE=8C?= =?UTF-8?q?=E5=96=84=20dp2mserver=20=E8=B4=A6=E6=88=B7=E7=AE=A1=E7=90=86?= =?UTF-8?q?=E7=95=8C=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DigitalPlatform.CommonControl/PropertyDlg.cs | 197 ++++++++-- .../PropertyDlg.resx | 20 +- DigitalPlatform.LibraryServer/AppScript.cs | 50 ++- .../LibraryService.cs | 2 +- .../UserDialog.Designer.cs | 22 ++ .../UserDialog.cs | 71 ++++ .../UserManageDialog.cs | 66 +++- dp2Circulation/MainForm/InitialExtension.cs | 46 ++- dp2Circulation/Reader/ReaderInfoForm.cs | 13 +- dp2Circulation/default/objectrights.xml | 26 +- dp2Circulation/default/patronrights.xml | 49 +++ dp2Circulation/dp2Circulation.csproj | 6 +- dp2Circulation/userrightsdef.xml | 368 +++++++++--------- dp2Installer/dp2Installer.csproj | 2 +- dp2Installer/opac_app/Report.aspx.cs | 5 + dp2LibraryXE/LibraryHost.cs | 1 - dp2LibraryXE/dp2LibraryXE.csproj | 2 +- dp2LibraryXE/opac_app/Report.aspx.cs | 5 + dp2OPAC/Report.aspx.cs | 5 + 19 files changed, 694 insertions(+), 262 deletions(-) create mode 100644 dp2Circulation/default/patronrights.xml diff --git a/DigitalPlatform.CommonControl/PropertyDlg.cs b/DigitalPlatform.CommonControl/PropertyDlg.cs index cad6e8b54..d5a2f23fb 100644 --- a/DigitalPlatform.CommonControl/PropertyDlg.cs +++ b/DigitalPlatform.CommonControl/PropertyDlg.cs @@ -7,6 +7,7 @@ using System.Collections.Generic; using DigitalPlatform.Xml; +using DigitalPlatform.Text; namespace DigitalPlatform.CommonControl { @@ -20,7 +21,8 @@ public class PropertyDlg : System.Windows.Forms.Form public string PropertyString = ""; - List _propertyNameList = null; // 配置中出现过的属性名 + // List _propertyNameList = null; // 配置中出现过的属性名 + Hashtable _propertyNameTable = new Hashtable(); // 配置中出现过的属性名。属性名 --> ListViewItem List _langNameList = null; // 配置中出现过的语言类型 @@ -37,6 +39,8 @@ public class PropertyDlg : System.Windows.Forms.Form private SplitContainer splitContainer_main; private Panel panel_up; private Panel panel_down; + private ToolStrip toolStrip1; + private ToolStripDropDownButton toolStripDropDownButton_quickSet; private System.ComponentModel.IContainer components; public PropertyDlg() @@ -86,12 +90,15 @@ private void InitializeComponent() this.splitContainer_main = new System.Windows.Forms.SplitContainer(); this.panel_up = new System.Windows.Forms.Panel(); this.panel_down = new System.Windows.Forms.Panel(); + this.toolStrip1 = new System.Windows.Forms.ToolStrip(); + this.toolStripDropDownButton_quickSet = new System.Windows.Forms.ToolStripDropDownButton(); ((System.ComponentModel.ISupportInitialize)(this.splitContainer_main)).BeginInit(); this.splitContainer_main.Panel1.SuspendLayout(); this.splitContainer_main.Panel2.SuspendLayout(); this.splitContainer_main.SuspendLayout(); this.panel_up.SuspendLayout(); this.panel_down.SuspendLayout(); + this.toolStrip1.SuspendLayout(); this.SuspendLayout(); // // label_property @@ -214,6 +221,7 @@ private void InitializeComponent() // // panel_up // + this.panel_up.Controls.Add(this.toolStrip1); this.panel_up.Controls.Add(this.listView_property); this.panel_up.Controls.Add(this.button_uncheckAll); this.panel_up.Controls.Add(this.button_checkAll); @@ -233,6 +241,27 @@ private void InitializeComponent() this.panel_down.Size = new System.Drawing.Size(586, 99); this.panel_down.TabIndex = 0; // + // toolStrip1 + // + this.toolStrip1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.toolStrip1.Dock = System.Windows.Forms.DockStyle.None; + this.toolStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.toolStripDropDownButton_quickSet}); + this.toolStrip1.Location = new System.Drawing.Point(474, 209); + this.toolStrip1.Name = "toolStrip1"; + this.toolStrip1.Size = new System.Drawing.Size(112, 25); + this.toolStrip1.TabIndex = 7; + this.toolStrip1.Text = "toolStrip1"; + // + // toolStripDropDownButton_quickSet + // + this.toolStripDropDownButton_quickSet.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text; + this.toolStripDropDownButton_quickSet.Image = ((System.Drawing.Image)(resources.GetObject("toolStripDropDownButton_quickSet.Image"))); + this.toolStripDropDownButton_quickSet.ImageTransparentColor = System.Drawing.Color.Magenta; + this.toolStripDropDownButton_quickSet.Name = "toolStripDropDownButton_quickSet"; + this.toolStripDropDownButton_quickSet.Size = new System.Drawing.Size(69, 22); + this.toolStripDropDownButton_quickSet.Text = "快速设定"; + // // PropertyDlg // this.AutoScaleBaseSize = new System.Drawing.Size(6, 14); @@ -253,6 +282,8 @@ private void InitializeComponent() this.panel_up.PerformLayout(); this.panel_down.ResumeLayout(false); this.panel_down.PerformLayout(); + this.toolStrip1.ResumeLayout(false); + this.toolStrip1.PerformLayout(); this.ResumeLayout(false); this.PerformLayout(); @@ -262,11 +293,19 @@ private void InitializeComponent() private void PropertyDlg_Load(object sender, System.EventArgs e) { SetListViewTitle(listView_property); + + toolTip_comment.SetToolTip(this.listView_property, "tool tip text"); + + this.BeginInvoke(new Action(Initial)); + } + + void Initial() + { LoadXml(); textBox_property.Text = PropertyString; - toolTip_comment.SetToolTip(this.listView_property, "tool tip text"); + ChangeColor(); } public void SetListViewTitle(ListView listView) @@ -282,7 +321,6 @@ int LoadOneXml(string strFileName, strError = ""; XmlDocument dom = new XmlDocument(); - try { dom.Load(strFileName); @@ -295,11 +333,11 @@ int LoadOneXml(string strFileName, XmlNodeList propertyList = dom.SelectNodes("root/property"); - int i, j; - for (i = 0; i < propertyList.Count; i++) + // int j; + foreach (XmlNode node in propertyList) { // 找到事项名字 - string strName = DomUtil.GetAttr(propertyList[i], "name"); + string strName = DomUtil.GetAttr(node, "name"); if (strName == "") continue; @@ -308,12 +346,12 @@ int LoadOneXml(string strFileName, XmlNode nodeComment = null; if (Lang == "") - nodeComment = propertyList[i].SelectSingleNode("comment"); + nodeComment = node.SelectSingleNode("comment"); else { - nodeComment = propertyList[i].SelectSingleNode("comment[@lang='" + Lang + "']"); + nodeComment = node.SelectSingleNode("comment[@lang='" + Lang + "']"); if (nodeComment == null) // 按照指定的语言找,但是没有找到 - nodeComment = propertyList[i].SelectSingleNode("comment"); + nodeComment = node.SelectSingleNode("comment"); } string strComment = ""; @@ -330,22 +368,22 @@ int LoadOneXml(string strFileName, item.SubItems.Add(strComment); listView_property.Items.Add(item); - } // 创建语言数组 - XmlNodeList commentList = dom.SelectNodes("//property/comment"); + XmlNodeList commentList = dom.SelectNodes("root/property/comment"); _langNameList = new List(); // = new ArrayList(); - for (i = 0; i < propertyList.Count; i++) + foreach (XmlNode node in commentList) { // 找到事项名字 - string strLang = DomUtil.GetAttr(commentList[i], "lang"); + string strLang = DomUtil.GetAttr(node, "lang"); if (strLang == "") continue; +#if NO bool bFound = false; for (j = 0; j < _langNameList.Count; j++) { @@ -358,6 +396,9 @@ int LoadOneXml(string strFileName, if (bFound == false) _langNameList.Add(strLang); +#endif + if (_langNameList.IndexOf(strLang) == -1) + _langNameList.Add(strLang); } @@ -367,9 +408,11 @@ int LoadOneXml(string strFileName, void LoadXml() { _langNameList = new List(); - _propertyNameList = new List(); // = new string[listView_property.Items.Count]; + // _propertyNameList = new List(); // = new string[listView_property.Items.Count]; + _propertyNameTable = new Hashtable(); listView_property.Items.Clear(); + this.toolStripDropDownButton_quickSet.DropDownItems.Clear(); string strError = ""; @@ -378,6 +421,7 @@ void LoadXml() string[] filenames = this.CfgFileName.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); + this.listView_property.BeginUpdate(); foreach (string filename in filenames) { // 装载一个 XML 文件 @@ -385,7 +429,12 @@ void LoadXml() out strError); if (nRet == -1) goto ERROR1; + nRet = FillQuickSetMenu(filename, + out strError); + if (nRet == -1) + goto ERROR1; } + this.listView_property.EndUpdate(); #if NO XmlDocument dom = new XmlDocument(); @@ -446,7 +495,10 @@ void LoadXml() foreach (ListViewItem item in listView_property.Items) { // _propertyNameList[j] = listView_property.Items[j].Text; - _propertyNameList.Add(item.Text); + + // _propertyNameList.Add(item.Text); + + _propertyNameTable[item.Text.ToLower()] = item; } #if NO @@ -479,11 +531,16 @@ void LoadXml() } #endif + if (this.toolStripDropDownButton_quickSet.DropDownItems.Count == 0) + this.toolStripDropDownButton_quickSet.Visible = false; + else + this.toolStripDropDownButton_quickSet.Visible = true; return; ERROR1: MessageBox.Show(strError); } +#if NO // 是否为已经定义的属性名 bool IsDefinedPropertyName(string strName) { @@ -498,6 +555,15 @@ bool IsDefinedPropertyName(string strName) return false; } +#endif + // 是否为已经定义的属性名 + bool IsDefinedPropertyName(string strName) + { + if (this._propertyNameTable == null) + return false; + + return _propertyNameTable.ContainsKey(strName.ToLower()); + } // 获得一个列表中属于当前没有定义的属性名 ArrayList GetNoDefinedPropertyNames(string strList) @@ -523,15 +589,15 @@ ArrayList GetNoDefinedPropertyNames(string strList) } // 获得一个列表中属于当前定义的属性名 - ArrayList GetDefinedPropertyNames(string strList) + List GetDefinedPropertyNames(string strList) { - ArrayList aResult = new ArrayList(); + List aResult = new List(); string[] aName = strList.Split(new Char[] { ',' }); - for (int i = 0; i < aName.Length; i++) + foreach (string s in aName) { - string strName = aName[i]; - strName = strName.Trim(); + // string strName = aName[i]; + string strName = s.Trim(); if (strName == "") continue; @@ -544,8 +610,13 @@ ArrayList GetDefinedPropertyNames(string strList) return aResult; } + int _skipItemChecked = 0; // 2016/3/26 + private void listView_property_ItemCheck(object sender, System.Windows.Forms.ItemCheckEventArgs e) { + if (_skipItemChecked > 0) + return; + // 得到checked事项 ArrayList checkedItems = GetCheckedItems(listView_property, e); @@ -586,10 +657,8 @@ private void listView_property_ItemCheck(object sender, System.Windows.Forms.Ite } ChangeColor(); - } - void ChangeColor() { for (int i = 0; i < this.listView_property.Items.Count; i++) @@ -604,7 +673,6 @@ void ChangeColor() this.listView_property.Items[i].ForeColor = SystemColors.MenuText; this.listView_property.Items[i].BackColor = SystemColors.Menu; } - } } @@ -612,12 +680,12 @@ private void textBox_property_TextChanged(object sender, System.EventArgs e) { //bool bChanged = false; // 提取已定义的部分 - ArrayList aDefined = GetDefinedPropertyNames(textBox_property.Text); + List aDefined = GetDefinedPropertyNames(textBox_property.Text); // check - for (int i = 0; i < aDefined.Count; i++) + foreach (string strName in aDefined) { - string strName = (string)aDefined[i]; + // string strName = (string)aDefined[i]; //bool bRet = CheckItem(strName, true); @@ -626,9 +694,9 @@ private void textBox_property_TextChanged(object sender, System.EventArgs e) } // uncheck - for (int j = 0; j < listView_property.Items.Count; j++) + foreach (ListViewItem item in listView_property.Items) { - string strItemName = listView_property.Items[j].Text; + string strItemName = item.Text; bool bFound = false; for (int k = 0; k < aDefined.Count; k++) @@ -643,9 +711,9 @@ private void textBox_property_TextChanged(object sender, System.EventArgs e) // 属于需要off的事项 if (bFound == false) { - if (listView_property.Items[j].Checked == false) + if (item.Checked == false) continue; - listView_property.Items[j].Checked = false; + item.Checked = false; //bChanged = true; } @@ -653,25 +721,44 @@ private void textBox_property_TextChanged(object sender, System.EventArgs e) } +#if NO bool CheckItem(string strName, bool bChecked) { - for (int i = 0; i < listView_property.Items.Count; i++) + foreach (ListViewItem item in listView_property.Items) { - if (String.Compare(strName, listView_property.Items[i].Text, true) == 0) + if (String.Compare(strName, item.Text, true) == 0) { - if (listView_property.Items[i].Checked == bChecked) + if (item.Checked == bChecked) return false; // 没有改变状态 else { - listView_property.Items[i].Checked = bChecked; + item.Checked = bChecked; return true; // 改变了状态 } - } } return false; // 没有找到事项 } +#endif + + // 2016/3/26 优化速度 + bool CheckItem(string strName, bool bChecked) + { + ListViewItem item = (ListViewItem)_propertyNameTable[strName.ToLower()]; + if (item == null) + return false; // 没有找到事项 + + if (item.Checked == bChecked) + return false; // 没有改变状态 + else + { + _skipItemChecked++; + item.Checked = bChecked; + _skipItemChecked--; + return true; // 改变了状态 + } + } // 得到所有checked Item // 是当前的所有checked item加上考虑e参数中可能增加和减除的item,合并而成 @@ -708,7 +795,6 @@ private void button_Cancel_Click(object sender, System.EventArgs e) this.Close(); } - private void listView_property_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e) { ListViewItem selection = listView_property.GetItemAt(e.X, e.Y); @@ -728,7 +814,6 @@ private void listView_property_MouseMove(object sender, System.Windows.Forms.Mou } tipsItem = selection; - } private void listView_property_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e) @@ -745,7 +830,6 @@ private void listView_property_MouseUp(object sender, System.Windows.Forms.Mouse // 子菜单 for (int i = 0; i < _langNameList.Count; i++) { - MenuItem menuItemSub = new MenuItem(_langNameList[i]); menuItemSub.Click += new System.EventHandler(this.menu_selectLanguage_Click); @@ -765,7 +849,6 @@ private void listView_property_MouseUp(object sender, System.Windows.Forms.Mouse // 选择了语言 private void menu_selectLanguage_Click(object sender, System.EventArgs e) { - if (sender is MenuItem) { string strSave = textBox_property.Text; @@ -812,5 +895,41 @@ private void listView_property_ColumnClick(object sender, ColumnClickEventArgs e this.listView_property.ListViewItemSorter = null; } + int FillQuickSetMenu(string strFileName, out string strError) + { + strError = ""; + + XmlDocument dom = new XmlDocument(); + try + { + dom.Load(strFileName); + } + catch (Exception ex) + { + strError = "装载文件 '" + strFileName + "' 时出错: " + ex.Message; + return -1; + } + + XmlNodeList groups = dom.DocumentElement.SelectNodes("groups/group"); + foreach (XmlElement group in groups) + { + string strCaption = DomUtil.GetCaption(this.Lang, group); + ToolStripItem item = new ToolStripMenuItem(strCaption); + item.Tag = group.GetAttribute("value"); + item.Click += item_Click; + this.toolStripDropDownButton_quickSet.DropDownItems.Add(item); + } + return 0; + } + + void item_Click(object sender, EventArgs e) + { + ToolStripMenuItem item = sender as ToolStripMenuItem; + string strValue = item.Tag as string; + if (Control.ModifierKeys == Keys.Control) + textBox_property.Text = StringUtil.MergeList(textBox_property.Text, strValue, false); + else + textBox_property.Text = strValue; + } } } diff --git a/DigitalPlatform.CommonControl/PropertyDlg.resx b/DigitalPlatform.CommonControl/PropertyDlg.resx index eec3ece5b..bf2855834 100644 --- a/DigitalPlatform.CommonControl/PropertyDlg.resx +++ b/DigitalPlatform.CommonControl/PropertyDlg.resx @@ -120,10 +120,28 @@ 17, 17 + + 172, 17 + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIDSURBVDhPpZLrS5NhGMb3j4SWh0oRQVExD4gonkDpg4hG + YKxG6WBogkMZKgPNCEVJFBGdGETEvgwyO9DJE5syZw3PIlPEE9pgBCLZ5XvdMB8Ew8gXbl54nuf63dd9 + 0OGSnwCahxbPRNPAPMw9Xpg6ZmF46kZZ0xSKzJPIrhpDWsVnpBhGkKx3nAX8Pv7z1zg8OoY/cITdn4fw + bf/C0kYAN3Ma/w3gWfZL5kzTKBxjWyK2DftwI9tyMYCZKXbNHaD91bLYJrDXsYbrWfUKwJrPE9M2M1Oc + VzOOpHI7Jr376Hi9ogHqFIANO0/MmmmbmSmm9a8ze+I4MrNWAdjtoJgWcx+PSzg166yZZ8xM8XvXDix9 + c4jIqFYAjoriBV9AhEPv1mH/sonogha0afbZMMZz+yreTGyhpusHwtNNCsA5U1zS4BLxzJIfg299qO32 + Ir7UJtZfftyATqeT+8o2D8JSjQrAJblrncYL7ZJ2+bfaFnC/1S1NjL3diRat7qrO7wLRP3HjWsojBeCo + mDEo5mNjuweFGvjWg2EBhCbpkW78htSHHwRyNdmgAFzPEee2iFkzayy2OLXzT4gr6UdUnlXrullsxxQ+ + kx0g8BTA3aZlButjSTyjODq/WcQcW/B/Je4OQhLvKQDnzN1mp0nnkvAhR8VuMzNrpm1mpjgkoVwB/v8D + TgDQASA1MVpwzwAAAABJRU5ErkJggg== + + 44 - AAABAAgAICAQAAAAAADoAgAAhgAAABAQEAAAAAAAKAEAAG4DAAAwMAAAAQAIAKgOAACWBAAAICAAAAEA diff --git a/DigitalPlatform.LibraryServer/AppScript.cs b/DigitalPlatform.LibraryServer/AppScript.cs index 99807c888..d180b9b8b 100644 --- a/DigitalPlatform.LibraryServer/AppScript.cs +++ b/DigitalPlatform.LibraryServer/AppScript.cs @@ -1297,7 +1297,9 @@ public int DoVerifyReaderFunction( // 执行函数 try { - return host.VerifyReader(strAction, + return host.VerifyReader( + sessioninfo, + strAction, itemdom, out strError); } @@ -1335,7 +1337,9 @@ public LibraryHost() // -1 调用出错 // 0 校验正确 // 1 校验发现错误 - public virtual int VerifyReader(string strAction, + public virtual int VerifyReader( + SessionInfo sessioninfo, + string strAction, XmlDocument readerdom, out string strError) { @@ -1363,9 +1367,51 @@ public virtual int VerifyReader(string strAction, #endif } + string strRights = DomUtil.GetElementText(readerdom.DocumentElement, "rights"); + + // 检查读者权限。要求不能大于当前用户的权限 + List warning_rights = null; + if (IsLessOrEqualThan(strRights, sessioninfo.Rights, out warning_rights) == false) + { + strError = "读者记录中的权限超出了当前用户的权限,这是不允许的。超出的部分权限值 '" + StringUtil.MakePathList(warning_rights) + "'"; + return 1; + } + return 0; } + // strLeft 包含的权限是否小于等于 strRight + static bool IsLessOrEqualThan(string strLeft, + string strRight, + out List warning_rights) + { + warning_rights = new List(); + + if (string.IsNullOrEmpty(strLeft) && string.IsNullOrEmpty(strRight)) + return true; + if (string.IsNullOrEmpty(strLeft)) + return true; // strLeft == 空 && strRight != 空 + if (string.IsNullOrEmpty(strRight)) + { + warning_rights = StringUtil.SplitList(strRight); + return false; // strLeft != 空 && strRight == 空 + } + + string[] left = strLeft.Split(new char[] {','}, StringSplitOptions.RemoveEmptyEntries); + string[] right = strRight.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); + + foreach(string s in left) + { + if (Array.IndexOf(right, s) == -1) + warning_rights.Add(s); + } + + if (warning_rights.Count > 0) + return false; + + return true; + } + // return: // -1 调用出错 // 0 校验正确 diff --git a/DigitalPlatform.LibraryService/LibraryService.cs b/DigitalPlatform.LibraryService/LibraryService.cs index c513495a8..e4aa46dd1 100644 --- a/DigitalPlatform.LibraryService/LibraryService.cs +++ b/DigitalPlatform.LibraryService/LibraryService.cs @@ -2380,7 +2380,7 @@ public LibraryServerResult Search( try { // test - Thread.Sleep(new TimeSpan(0, 0, 30)); + // Thread.Sleep(new TimeSpan(0, 0, 30)); // 权限判断 diff --git a/DigitalPlatform.MessageClient.GUI/UserDialog.Designer.cs b/DigitalPlatform.MessageClient.GUI/UserDialog.Designer.cs index b36369f0f..7f4a82909 100644 --- a/DigitalPlatform.MessageClient.GUI/UserDialog.Designer.cs +++ b/DigitalPlatform.MessageClient.GUI/UserDialog.Designer.cs @@ -46,6 +46,7 @@ private void InitializeComponent() this.button_OK = new System.Windows.Forms.Button(); this.textBox_duty = new System.Windows.Forms.TextBox(); this.label8 = new System.Windows.Forms.Label(); + this.checkBox_changePassword = new System.Windows.Forms.CheckBox(); this.SuspendLayout(); // // label1 @@ -63,11 +64,13 @@ private void InitializeComponent() this.textBox_userName.Name = "textBox_userName"; this.textBox_userName.Size = new System.Drawing.Size(204, 21); this.textBox_userName.TabIndex = 1; + this.textBox_userName.TextChanged += new System.EventHandler(this.textBox_comment_TextChanged); // // textBox_password // this.textBox_password.Location = new System.Drawing.Point(119, 39); this.textBox_password.Name = "textBox_password"; + this.textBox_password.PasswordChar = '*'; this.textBox_password.Size = new System.Drawing.Size(204, 21); this.textBox_password.TabIndex = 3; // @@ -84,6 +87,7 @@ private void InitializeComponent() // this.textBox_confirmPassword.Location = new System.Drawing.Point(119, 66); this.textBox_confirmPassword.Name = "textBox_confirmPassword"; + this.textBox_confirmPassword.PasswordChar = '*'; this.textBox_confirmPassword.Size = new System.Drawing.Size(204, 21); this.textBox_confirmPassword.TabIndex = 5; // @@ -104,6 +108,7 @@ private void InitializeComponent() this.textBox_department.Name = "textBox_department"; this.textBox_department.Size = new System.Drawing.Size(289, 21); this.textBox_department.TabIndex = 7; + this.textBox_department.TextChanged += new System.EventHandler(this.textBox_comment_TextChanged); // // label4 // @@ -122,6 +127,7 @@ private void InitializeComponent() this.textBox_rights.Name = "textBox_rights"; this.textBox_rights.Size = new System.Drawing.Size(289, 21); this.textBox_rights.TabIndex = 9; + this.textBox_rights.TextChanged += new System.EventHandler(this.textBox_comment_TextChanged); // // label5 // @@ -138,6 +144,7 @@ private void InitializeComponent() this.textBox_tel.Name = "textBox_tel"; this.textBox_tel.Size = new System.Drawing.Size(204, 21); this.textBox_tel.TabIndex = 13; + this.textBox_tel.TextChanged += new System.EventHandler(this.textBox_comment_TextChanged); // // label6 // @@ -158,6 +165,7 @@ private void InitializeComponent() this.textBox_comment.ScrollBars = System.Windows.Forms.ScrollBars.Vertical; this.textBox_comment.Size = new System.Drawing.Size(289, 89); this.textBox_comment.TabIndex = 15; + this.textBox_comment.TextChanged += new System.EventHandler(this.textBox_comment_TextChanged); // // label7 // @@ -198,6 +206,7 @@ private void InitializeComponent() this.textBox_duty.Name = "textBox_duty"; this.textBox_duty.Size = new System.Drawing.Size(289, 21); this.textBox_duty.TabIndex = 11; + this.textBox_duty.TextChanged += new System.EventHandler(this.textBox_comment_TextChanged); // // label8 // @@ -208,11 +217,23 @@ private void InitializeComponent() this.label8.TabIndex = 10; this.label8.Text = "义务(&D):"; // + // checkBox_changePassword + // + this.checkBox_changePassword.AutoSize = true; + this.checkBox_changePassword.Location = new System.Drawing.Point(329, 41); + this.checkBox_changePassword.Name = "checkBox_changePassword"; + this.checkBox_changePassword.Size = new System.Drawing.Size(72, 16); + this.checkBox_changePassword.TabIndex = 18; + this.checkBox_changePassword.Text = "修改密码"; + this.checkBox_changePassword.UseVisualStyleBackColor = true; + this.checkBox_changePassword.CheckedChanged += new System.EventHandler(this.checkBox_changePassword_CheckedChanged); + // // UserDialog // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ClientSize = new System.Drawing.Size(420, 360); + this.Controls.Add(this.checkBox_changePassword); this.Controls.Add(this.textBox_duty); this.Controls.Add(this.label8); this.Controls.Add(this.button_OK); @@ -261,5 +282,6 @@ private void InitializeComponent() private System.Windows.Forms.Button button_OK; private System.Windows.Forms.TextBox textBox_duty; private System.Windows.Forms.Label label8; + private System.Windows.Forms.CheckBox checkBox_changePassword; } } \ No newline at end of file diff --git a/DigitalPlatform.MessageClient.GUI/UserDialog.cs b/DigitalPlatform.MessageClient.GUI/UserDialog.cs index 4637f7b5e..fbb1d951e 100644 --- a/DigitalPlatform.MessageClient.GUI/UserDialog.cs +++ b/DigitalPlatform.MessageClient.GUI/UserDialog.cs @@ -11,6 +11,13 @@ namespace DigitalPlatform.MessageClient { public partial class UserDialog : Form { + // 是否为修改模式。false 表示为创建模式;true 表示为修改模式 + public bool ChangeMode + { + get; + set; + } + public UserDialog() { InitializeComponent(); @@ -52,15 +59,41 @@ void BuildUserItem() private void UserDialog_Load(object sender, EventArgs e) { + if (this.ChangeMode) + this.checkBox_changePassword.Visible = true; + else + { + this.checkBox_changePassword.Checked = true; + this.checkBox_changePassword.Visible = false; + } + + checkBox_changePassword_CheckedChanged(this, new EventArgs()); + this.LoadFromUserItem(); + + this.Changed = false; } private void button_OK_Click(object sender, EventArgs e) { + string strError = ""; + + if (this.checkBox_changePassword.Checked == true) + { + if (this.textBox_password.Text != this.textBox_confirmPassword.Text) + { + strError = "密码 和 确认密码 不一致。请重新输入"; + goto ERROR1; + } + } + this.BuildUserItem(); this.DialogResult = System.Windows.Forms.DialogResult.OK; this.Close(); + return; + ERROR1: + MessageBox.Show(this, strError); } private void button_Cancel_Click(object sender, EventArgs e) @@ -68,5 +101,43 @@ private void button_Cancel_Click(object sender, EventArgs e) this.DialogResult = System.Windows.Forms.DialogResult.Cancel; this.Close(); } + + private void checkBox_changePassword_CheckedChanged(object sender, EventArgs e) + { + if (this.checkBox_changePassword.Checked == true) + { + this.textBox_password.Enabled = true; + this.textBox_confirmPassword.Enabled = true; + } + else + { + this.textBox_password.Enabled = false; + this.textBox_confirmPassword.Enabled = false; + } + } + + public bool ChangePassword + { + get + { + return this.checkBox_changePassword.Checked; + } + set + { + this.checkBox_changePassword.Checked = value; + } + } + + // 对话框打开期间,字段内容是否发生过修改。注:不包含密码和确认密码字段 + public bool Changed + { + get; + set; + } + + private void textBox_comment_TextChanged(object sender, EventArgs e) + { + this.Changed = true; + } } } diff --git a/DigitalPlatform.MessageClient.GUI/UserManageDialog.cs b/DigitalPlatform.MessageClient.GUI/UserManageDialog.cs index f528dd87c..113c50748 100644 --- a/DigitalPlatform.MessageClient.GUI/UserManageDialog.cs +++ b/DigitalPlatform.MessageClient.GUI/UserManageDialog.cs @@ -113,7 +113,12 @@ void NewUser() this.EnableControls(false); try { - this.Connection.SetUsers("create", users); + MessageResult result = this.Connection.SetUsers("create", users); + if (result.Value == -1) + { + strError = result.ErrorInfo; + goto ERROR1; + } } catch (AggregateException ex) { @@ -195,12 +200,19 @@ void ModifyUser() ListViewItem item = this.listView1.SelectedItems[0]; UserDialog dlg = new UserDialog(); dlg.Font = this.Font; + dlg.ChangeMode = true; dlg.UserItem = (UserItem)item.Tag; dlg.ShowDialog(this); if (dlg.DialogResult == System.Windows.Forms.DialogResult.Cancel) return; + if (dlg.Changed == false && dlg.ChangePassword == false) + { + MessageBox.Show(this, "没有发生修改"); + return; + } + List users = new List(); UserItem user = dlg.UserItem; users.Add(user); @@ -208,7 +220,32 @@ void ModifyUser() this.EnableControls(false); try { - this.Connection.SetUsers("change", users); + if (dlg.Changed == true) + { + MessageResult result = this.Connection.SetUsers("change", users); + if (result.Value == -1) + { + strError = result.ErrorInfo; + // 如果这里返回出错仅仅是因为权限不够,还需要尝试继续执行后面的修改密码的操作 + if (result.String != "Denied") + goto ERROR1; + } + } + + if (dlg.ChangePassword) + { + MessageResult result = this.Connection.SetUsers("changePassword", users); + if (result.Value == -1) + { + if (string.IsNullOrEmpty(strError) == false) + strError += "; "; + strError += result.ErrorInfo; + goto ERROR1; + } + } + + if (string.IsNullOrEmpty(strError) == false) + goto ERROR1; } catch (AggregateException ex) { @@ -248,14 +285,16 @@ void DeleteUser() goto ERROR1; } - DialogResult result = MessageBox.Show(this, -"确实要删除选定的 " + this.listView1.SelectedItems.Count.ToString() + " 个用户?", -"UserManageDialog", -MessageBoxButtons.YesNo, -MessageBoxIcon.Question, -MessageBoxDefaultButton.Button2); - if (result != DialogResult.Yes) - return; + { + DialogResult result = MessageBox.Show(this, + "确实要删除选定的 " + this.listView1.SelectedItems.Count.ToString() + " 个用户?", + "UserManageDialog", + MessageBoxButtons.YesNo, + MessageBoxIcon.Question, + MessageBoxDefaultButton.Button2); + if (result != DialogResult.Yes) + return; + } List users = new List(); foreach (ListViewItem item in this.listView1.SelectedItems) @@ -267,7 +306,12 @@ void DeleteUser() this.EnableControls(false); try { - this.Connection.SetUsers("delete", users); + MessageResult result = this.Connection.SetUsers("delete", users); + if (result.Value == -1) + { + strError = result.ErrorInfo; + goto ERROR1; + } } catch (AggregateException ex) { diff --git a/dp2Circulation/MainForm/InitialExtension.cs b/dp2Circulation/MainForm/InitialExtension.cs index ab120449d..91a34ab28 100644 --- a/dp2Circulation/MainForm/InitialExtension.cs +++ b/dp2Circulation/MainForm/InitialExtension.cs @@ -1834,6 +1834,44 @@ bool Detect360() return false; } + // 判断两个文件的版本号是否一致 + static bool VersionChanged(string filename1, string filename2) + { + if (File.Exists(filename1) == false) + return false; + if (File.Exists(filename2) == false) + return false; + string strVersion1 = GetVersion(filename1); + string strVersion2 = GetVersion(filename2); + if (strVersion1 == strVersion2) + return false; + return true; + } + + // 获得一个文件的版本号 + static string GetVersion(string filename) + { + string strExt = Path.GetExtension(filename).ToLower(); + if (strExt == ".xml") + { + XmlDocument dom = new XmlDocument(); + try + { + dom.Load(filename); + } + catch + { + return null; + } + + if (dom.DocumentElement == null) + return null; + return dom.DocumentElement.GetAttribute("version"); + } + + return null; + } + // 从数据目录 default 子目录复制配置文件到用户目录 // 如果用户目录中已经有同名文件存在,则不复制了 // 这种做法,是为了让用户可以修改实际使用的配置文件,并且在升级安装的时候,用户目录内的文件不会被安装修改原始的配置文件过程所覆盖 @@ -1868,6 +1906,7 @@ bool CopyDefaultCfgFiles(out string strError) filenames.Add("patron_change_actions.xml"); filenames.Add("856_change_actions.xml"); #endif + filenames.Add("patronrights.xml"); FileInfo[] fis = di.GetFiles("*.*"); foreach (FileInfo fi in fis) @@ -1875,10 +1914,11 @@ bool CopyDefaultCfgFiles(out string strError) if (filenames.IndexOf(fi.Name.ToLower()) != -1) filenames.Remove(fi.Name.ToLower()); + string strSourceFileName = fi.FullName; string strTargetFileName = Path.Combine(this.UserDir, fi.Name); - if (File.Exists(strTargetFileName) == false) // 偶尔会出现判断错误 + if (File.Exists(strTargetFileName) == false // 偶尔会出现判断错误 + || VersionChanged(strSourceFileName, strTargetFileName) == true) { - string strSourceFileName = fi.FullName; #if DEBUG if (File.Exists(strSourceFileName) == false) { @@ -1888,7 +1928,7 @@ bool CopyDefaultCfgFiles(out string strError) #endif try { - File.Copy(strSourceFileName, strTargetFileName, false); + File.Copy(strSourceFileName, strTargetFileName, true); } catch (IOException) { diff --git a/dp2Circulation/Reader/ReaderInfoForm.cs b/dp2Circulation/Reader/ReaderInfoForm.cs index 293cdb969..2cc8285b8 100644 --- a/dp2Circulation/Reader/ReaderInfoForm.cs +++ b/dp2Circulation/Reader/ReaderInfoForm.cs @@ -5450,13 +5450,18 @@ private void readerEditControl1_EditRights(object sender, EventArgs e) DigitalPlatform.CommonControl.PropertyDlg dlg = new DigitalPlatform.CommonControl.PropertyDlg(); MainForm.SetControlFont(dlg, this.Font, false); - string strRightsCfgFileName = Path.Combine(this.MainForm.UserDir, "objectrights.xml"); + string strPatronRightsCfgFileName = Path.Combine(this.MainForm.UserDir, "patronrights.xml"); + string strRightsCfgFileName = Path.Combine(this.MainForm.UserDir, "objectrights.xml"); dlg.StartPosition = FormStartPosition.CenterScreen; dlg.Text = "当前读者的权限"; dlg.PropertyString = this.readerEditControl1.Rights; - dlg.CfgFileName = Path.Combine(this.MainForm.DataDir, "userrightsdef.xml"); + if (File.Exists(strPatronRightsCfgFileName) == true + && Control.ModifierKeys != Keys.Control) + dlg.CfgFileName = strPatronRightsCfgFileName; // 优先用读者权限定义配置文件 + else + dlg.CfgFileName = Path.Combine(this.MainForm.DataDir, "userrightsdef.xml"); if (File.Exists(strRightsCfgFileName) == true) dlg.CfgFileName += "," + strRightsCfgFileName; dlg.ShowDialog(this); @@ -5836,7 +5841,7 @@ void FillBorrowHistoryPage(List items, string strLink = ""; string strScriptHead = "" + "" - + ""; + + ""; string strStyle = @""; text.Append("" @@ -5875,7 +5880,7 @@ void FillBorrowHistoryPage(List items, foreach (ChargingItemWrapper wrapper in items) { ChargingItem item = wrapper.Item; - text.Append(""); + text.Append(""); text.Append(""); text.Append(""); diff --git a/dp2Circulation/default/objectrights.xml b/dp2Circulation/default/objectrights.xml index 56d557e7e..b160b3649 100644 --- a/dp2Circulation/default/objectrights.xml +++ b/dp2Circulation/default/objectrights.xml @@ -1,27 +1,27 @@  - + - 第一级 - Level 1 + 第一级 + Level 1 - 第二级 - Level 2 + 第二级 + Level 2 - 第三级 - Level 3 + 第三级 + Level 3 - 第四级 - Level 4 + 第四级 + Level 4 - 读者 - Patron + 读者 + Patron - 工作人员 - Librarian + 工作人员 + Librarian \ No newline at end of file diff --git a/dp2Circulation/default/patronrights.xml b/dp2Circulation/default/patronrights.xml new file mode 100644 index 000000000..d0982feaf --- /dev/null +++ b/dp2Circulation/default/patronrights.xml @@ -0,0 +1,49 @@ + + + + 借书 + borrow + + + 还书 + return + + + 续借 + renew + + + 读过 + read + + + 检索书目库 + search biblio + + + 获得书目信息 + get biblio info + + + 检索册 + search item + + + 获得册信息 + get item info + + + 修改册 + set item info + + + + + + + + + + + + \ No newline at end of file diff --git a/dp2Circulation/dp2Circulation.csproj b/dp2Circulation/dp2Circulation.csproj index 4a6c42120..8ce209842 100644 --- a/dp2Circulation/dp2Circulation.csproj +++ b/dp2Circulation/dp2Circulation.csproj @@ -51,7 +51,7 @@ dp2 V2truepublish.htm - 30 + 312.10.0.%2afalsetrue @@ -1366,6 +1366,10 @@ PreserveNewest + + Designer + PreserveNewest + diff --git a/dp2Circulation/userrightsdef.xml b/dp2Circulation/userrightsdef.xml index ff08d4cfd..f4a570dcc 100644 --- a/dp2Circulation/userrightsdef.xml +++ b/dp2Circulation/userrightsdef.xml @@ -1,392 +1,392 @@  - 借书 - borrow + 借书 + borrow - 还书 - return + 还书 + return - 续借 - renew + 续借 + renew - 丢失 - lost + 丢失 + lost - 读过 - read + 读过 + read - 预约 - reservation books + 预约 + reservation books - 采购 - order + 采购 + order - 设置系统时钟 - set system clock + 设置系统时钟 + set system clock - 修改读者密码 - change reader password + 修改读者密码 + change reader password - 校验读者密码 - verify reader password + 校验读者密码 + verify reader password - 获得书目摘要 - get biblio summary + 获得书目摘要 + get biblio summary - 检索借阅历史 - search charging history + 检索借阅历史 + search charging history - 检索读者 - search reader + 检索读者 + search reader - 获取读者信息 - get reader info + 获取读者信息 + get reader info - 修改读者信息 - set reader info + 修改读者信息 + set reader info - 移动读者信息 - move reader info + 移动读者信息 + move reader info - 仅修改读者信息中的状态和注释 - only change reader state and comment + 仅修改读者信息中的状态和注释 + only change reader state and comment - 强制修改读者信息中的证条码号 - force change reader barcode + 强制修改读者信息中的证条码号 + force change reader barcode - 列出书目库检索途径 -- 即将废止 - list biblio db froms + 列出书目库检索途径 -- 即将废止 + list biblio db froms - 列出数据库检索途径 - list database froms + 列出数据库检索途径 + list database froms - 检索书目库 - search biblio + 检索书目库 + search biblio - 获得书目信息 - get biblio info + 获得书目信息 + get biblio info - 检索册 - search item + 检索册 + search item - 获得册信息 - get item info + 获得册信息 + get item info - 修改册 - set item info + 修改册 + set item info - 获得操作日志 - get oper log + 获得操作日志 + get oper log - 交费 - amerce + 交费 + amerce - 变更费用之价格和注释 - modify amerce price and comment + 变更费用之价格和注释 + modify amerce price and comment - 单独变更费用之注释部分(非追加式) - only modify amerce comment + 单独变更费用之注释部分(非追加式) + only modify amerce comment - 撤回交费 - amerce undo + 撤回交费 + amerce undo - 盘点 - inventory + 盘点 + inventory - 删除盘点记录 - delete inventory record + 删除盘点记录 + delete inventory record - 检索 - search + 检索 + search - 获得记录 - get record + 获得记录 + get record - 获得日历 - get calendar + 获得日历 + get calendar - 修改日历 - change calendar + 修改日历 + change calendar - 创建日历 - new calendar + 创建日历 + new calendar - 删除日历 - delete calendar + 删除日历 + delete calendar - 批处理任务 - batch task + 批处理任务 + batch task - 清除所有数据库 - clear all dbs + 清除所有数据库 + clear all dbs - 转移读者信息 - devolve reader info + 转移读者信息 + devolve reader info - 获得用户信息 - get user + 获得用户信息 + get user - 修改用户信息 - set user + 修改用户信息 + set user - 创建新用户 - create new user + 创建新用户 + create new user - 删除用户 - delete user + 删除用户 + delete user - (强制)修改(其他)用户密码 - change user password + (强制)修改(其他)用户密码 + change user password - 允许模拟读者登录 - Simulate Reader Login + 允许模拟读者登录 + Simulate Reader Login - 允许模拟工作人员登录 - Simulate Worker Login + 允许模拟工作人员登录 + Simulate Worker Login - 获得系统参数 - get system parameters + 获得系统参数 + get system parameters - 设置系统参数 - set system parameters + 设置系统参数 + set system parameters - 应急恢复 - urgent recover + 应急恢复 + urgent recover - 修复借阅信息 - repair borrowinfo + 修复借阅信息 + repair borrowinfo - 入馆登记 - pass gate + 入馆登记 + pass gate - 获取资源 - get resource + 获取资源 + get resource - 修改资源 - write resource + 修改资源 + write resource - 修改书目数据 - set biblio info + 修改书目数据 + set biblio info - 创建租金交费请求 - create hire record + 创建租金交费请求 + create hire record - 创建押金交费请求 - create foregift record + 创建押金交费请求 + create foregift record - 创建押金退费请求 - create foregift returnback record + 创建押金退费请求 + create foregift returnback record - (费用)结算 - settlement + (费用)结算 + settlement - 撤销(费用)结算 - undo settlement + 撤销(费用)结算 + undo settlement - 删除(费用)的结算记录 - delete settlement record + 删除(费用)的结算记录 + delete settlement record - 检索期信息 - search issue + 检索期信息 + search issue - 获得期信息 - get issue info + 获得期信息 + get issue info - 修改期信息 - set issue info + 修改期信息 + set issue info - 检索订购信息 - search order + 检索订购信息 + search order - 获得订购信息 - get order info + 获得订购信息 + get order info - 修改订购信息 - set order info + 修改订购信息 + set order info - 获得评注信息 - get comment info + 获得评注信息 + get comment info - 修改评注信息 - set comment info + 修改评注信息 + set comment info - 检索评注信息 - search comment + 检索评注信息 + search comment - 阻止修改自己的密码 - deny change my password + 阻止修改自己的密码 + deny change my password - 写入对象资源 - write object resources + 写入对象资源 + write object resources - 直接写入数据库记录 - direct write database records + 直接写入数据库记录 + direct write database records - 写入模板 - write template + 写入模板 + write template - 管理数据库 - manage database + 管理数据库 + manage database - 完整还原数据记录 - restore data record + 完整还原数据记录 + restore data record - 管理缓存 - Manage Cache + 管理缓存 + Manage Cache - 管理评注 - Manage Comment + 管理评注 + Manage Comment - 设置种次号尾号 - Set Tail Number + 设置种次号尾号 + Set Tail Number - 设置实用库记录信息 - Set Util Info + 设置实用库记录信息 + Set Util Info - 获得读者识别码 - Get Patron Identifier + 获得读者识别码 + Get Patron Identifier - 获得通道信息 - Get Channel Information + 获得通道信息 + Get Channel Information - 管理服务器通道 - Manage Server Channel + 管理服务器通道 + Manage Server Channel - 观看报表 - View Report + 观看报表 + View Report - 上传文件 - Upload Files + 上传文件 + Upload Files - 下载文件 - Download Files + 下载文件 + Download Files - 检查前端版本 - Check Client Version + 检查前端版本 + Check Client Version - 前端允许界面直接修改订购记录 - Client UI Allow Modify Order Record + 前端允许界面直接修改订购记录 + Client UI Allow Modify Order Record - 前端保存记录时是否强制校验数据。校验时如果发现数据有错,会拒绝保存 - Client Force Verify Data + 前端保存记录时是否强制校验数据。校验时如果发现数据有错,会拒绝保存 + Client Force Verify Data - 前端删除书目记录时是否强制删除下属的实体、期、订购、评注记录。如果不具备此权限,则需要下属记录全部删除以后才能删除书目记录 - Client Delete Biblio Subrecords + 前端删除书目记录时是否强制删除下属的实体、期、订购、评注记录。如果不具备此权限,则需要下属记录全部删除以后才能删除书目记录 + Client Delete Biblio Subrecords - 前端允许进行模拟借还操作 - Client Simulate Borrow + 前端允许进行模拟借还操作 + Client Simulate Borrow \ No newline at end of file diff --git a/dp2Installer/dp2Installer.csproj b/dp2Installer/dp2Installer.csproj index f771b77a6..f273e8ca1 100644 --- a/dp2Installer/dp2Installer.csproj +++ b/dp2Installer/dp2Installer.csproj @@ -34,7 +34,7 @@ dp2 V2 true publish.htm - 102 + 104 1.1.0.%2a false true diff --git a/dp2Installer/opac_app/Report.aspx.cs b/dp2Installer/opac_app/Report.aspx.cs index edf33086f..5f905df1d 100644 --- a/dp2Installer/opac_app/Report.aspx.cs +++ b/dp2Installer/opac_app/Report.aspx.cs @@ -94,6 +94,11 @@ protected void Page_Load(object sender, EventArgs e) { this.Response.StatusCode = 403; this.Response.StatusDescription = strError + "。请重新登录"; + // 2016/3/26 + this.Response.Write("

"+HttpUtility.HtmlEncode(strError)+"

" + + "

返回主页

" + + "

重新登录

" + + ""); this.Response.End(); return; } diff --git a/dp2LibraryXE/LibraryHost.cs b/dp2LibraryXE/LibraryHost.cs index 581eecd23..fa8f05c79 100644 --- a/dp2LibraryXE/LibraryHost.cs +++ b/dp2LibraryXE/LibraryHost.cs @@ -220,7 +220,6 @@ int Start(string strDataDir, } } - if (host.Description.Behaviors.Find() == null) { ServiceThrottlingBehavior behavior = new ServiceThrottlingBehavior(); diff --git a/dp2LibraryXE/dp2LibraryXE.csproj b/dp2LibraryXE/dp2LibraryXE.csproj index 6c94dc602..60a3a5065 100644 --- a/dp2LibraryXE/dp2LibraryXE.csproj +++ b/dp2LibraryXE/dp2LibraryXE.csproj @@ -36,7 +36,7 @@ dp2 V2 true publish.htm - 70 + 71 1.1.0.%2a false true diff --git a/dp2LibraryXE/opac_app/Report.aspx.cs b/dp2LibraryXE/opac_app/Report.aspx.cs index edf33086f..5f905df1d 100644 --- a/dp2LibraryXE/opac_app/Report.aspx.cs +++ b/dp2LibraryXE/opac_app/Report.aspx.cs @@ -94,6 +94,11 @@ protected void Page_Load(object sender, EventArgs e) { this.Response.StatusCode = 403; this.Response.StatusDescription = strError + "。请重新登录"; + // 2016/3/26 + this.Response.Write("

"+HttpUtility.HtmlEncode(strError)+"

" + + "

返回主页

" + + "

重新登录

" + + ""); this.Response.End(); return; } diff --git a/dp2OPAC/Report.aspx.cs b/dp2OPAC/Report.aspx.cs index edf33086f..5f905df1d 100644 --- a/dp2OPAC/Report.aspx.cs +++ b/dp2OPAC/Report.aspx.cs @@ -94,6 +94,11 @@ protected void Page_Load(object sender, EventArgs e) { this.Response.StatusCode = 403; this.Response.StatusDescription = strError + "。请重新登录"; + // 2016/3/26 + this.Response.Write("

"+HttpUtility.HtmlEncode(strError)+"

" + + "

返回主页

" + + "

重新登录

" + + ""); this.Response.End(); return; } From 19697cda658411fabbca41ed36658b3c89351b7a Mon Sep 17 00:00:00 2001 From: XieTao Date: Tue, 29 Mar 2016 12:04:48 +0800 Subject: [PATCH 04/10] =?UTF-8?q?=E8=AE=A9=20GreenUtility=20=E8=83=BD?= =?UTF-8?q?=E8=BF=BD=E5=8A=A0=20DocumentFormat.OpenXml.dll=20=E5=88=B0=20a?= =?UTF-8?q?pp.zip=20=E4=B8=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- GreenUtility/Program.cs | 95 ++++++++++++++++++++++++++-- dp2Circulation/dp2Circulation.csproj | 2 +- 2 files changed, 90 insertions(+), 7 deletions(-) diff --git a/GreenUtility/Program.cs b/GreenUtility/Program.cs index 746feaaa4..2473399ec 100644 --- a/GreenUtility/Program.cs +++ b/GreenUtility/Program.cs @@ -12,6 +12,7 @@ using System.Xml; using Ionic.Zip; +using System.Collections; /* * 制作和解压绿色更新安装包的实用工具程序 @@ -700,6 +701,9 @@ static int CreateZipFile(string strProjectFileName, XmlNamespaceManager nsmgr = new XmlNamespaceManager(new NameTable()); nsmgr.AddNamespace("ns", "http://schemas.microsoft.com/developer/msbuild/2003"); + _referenceTable.Clear(); + BuildReferenceTable(dom, nsmgr, ref _referenceTable); + XmlNodeList contents = dom.DocumentElement.SelectNodes("//ns:Content", nsmgr); foreach (XmlElement content in contents) { @@ -735,22 +739,101 @@ static int CreateZipFile(string strProjectFileName, return -1; // .exe .exe.config .exe.manifest - string strBinSourceDir = Path.Combine(strSourceDir, "bin/debug"); + string strBinSourceDir = Path.Combine(strSourceDir, "bin\\debug"); strZipFileName = Path.Combine(strTargetDir, "app.zip"); filenames = GetExeFileNames(strBinSourceDir); + + // Debug.Assert(false, ""); + // 添加一些可能遗漏的文件 2016/3/29 + /* + + False + + + + + Include + True + Assembly + + * */ + XmlNodeList publishFiles = dom.DocumentElement.SelectNodes("//ns:PublishFile", nsmgr); + foreach(XmlElement publishFile in publishFiles) + { + string strFileType = GetNodeInnerText(publishFile.SelectSingleNode("ns:FileType", nsmgr)); + string strPublishState = GetNodeInnerText(publishFile.SelectSingleNode("ns:PublishState", nsmgr)); + if (strFileType != "Assembly" || strPublishState != "Include") + continue; + string strFileName = publishFile.GetAttribute("Include") + ".dll"; + string strHintPath = (string)_referenceTable[strFileName]; + if (string.IsNullOrEmpty(strHintPath)) + continue; + string strFilePath = Path.Combine(strSourceDir, strHintPath); + + // 复制文件到 bin 目录 + string strTargetPath = Path.Combine(strBinSourceDir, strFileName); + File.Copy(strFilePath, strTargetPath, true); + + Console.WriteLine("追加文件: " + strTargetPath); + strFilePath = new FileInfo(strTargetPath).FullName; + if (filenames.IndexOf(strTargetPath) == -1) + filenames.Add(strTargetPath); + } + nRet = Compress( - strBinSourceDir, - filenames, - Encoding.UTF8, - strZipFileName, - out strError); +strBinSourceDir, +filenames, +Encoding.UTF8, +strZipFileName, +out strError); if (nRet == -1) return -1; return 0; } + static Hashtable _referenceTable = new Hashtable(); // Reference 对照表。纯文件名 --> 相对路径 + + static void BuildReferenceTable(XmlDocument dom, + XmlNamespaceManager nsmgr, + ref Hashtable referenceTable) + { + /* + + False + packages\DocumentFormat.OpenXml.2.5\lib\DocumentFormat.OpenXml.dll + + * */ + XmlNodeList references = dom.DocumentElement.SelectNodes("//ns:Reference", nsmgr); + foreach (XmlElement reference in references) + { + string strHintPath = GetNodeInnerText(reference.SelectSingleNode("ns:HintPath", nsmgr)); + if (string.IsNullOrEmpty(strHintPath)) + continue; + string strFileName = GetLeft(reference.GetAttribute("Include")) + ".dll"; + referenceTable[strFileName] = strHintPath; + } + } + + // 获得逗号左边的字符串 + static string GetLeft(string strText) + { + if (string.IsNullOrEmpty(strText) == true) + return ""; + int nRet = strText.IndexOf(","); + if (nRet == -1) + return strText; + return strText.Substring(0, nRet).Trim(); + } + + static string GetNodeInnerText(XmlNode node) + { + if (node == null) + return ""; + return node.InnerText.Trim(); + } + static int Compress( string strBaseDir, List filenames, diff --git a/dp2Circulation/dp2Circulation.csproj b/dp2Circulation/dp2Circulation.csproj index 8ce209842..77786d1de 100644 --- a/dp2Circulation/dp2Circulation.csproj +++ b/dp2Circulation/dp2Circulation.csproj @@ -51,7 +51,7 @@ dp2 V2 true publish.htm - 31 + 32 2.10.0.%2a false true From 2da129ba43c3d1444374057939cd30db7a4ed810 Mon Sep 17 00:00:00 2001 From: XieTao Date: Thu, 31 Mar 2016 22:38:55 +0800 Subject: [PATCH 05/10] =?UTF-8?q?=E5=A2=9E=E5=BC=BA=E6=AF=8F=E4=B8=AA?= =?UTF-8?q?=E5=88=86=E9=A6=86=E7=8B=AC=E7=AB=8B=E9=AA=8C=E8=AF=81=E6=9D=A1?= =?UTF-8?q?=E7=A0=81=E5=8F=B7=E7=9A=84=E7=9B=B8=E5=85=B3=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DigitalPlatform.LibraryServer/AppEntity.cs | 2 +- DigitalPlatform.LibraryServer/AppScript.cs | 1 + .../LibraryService.cs | 2 +- DigitalPlatform.Text/StringUtil.cs | 53 ++++++ .../Charging/QuickChargingForm.Designer.cs | 87 +++++----- dp2Circulation/Charging/QuickChargingForm.cs | 67 +++++++- .../Charging/QuickChargingForm.resx | 21 ++- dp2Circulation/FontSetting/MyForm.cs | 20 +++ dp2Circulation/Properties/AssemblyInfo.cs | 7 +- dp2Circulation/SearchForms/ItemSearchForm.cs | 157 +++++++++++++++++- dp2Circulation/dp2Circulation.csproj | 2 +- dp2Installer/dp2Installer.csproj | 2 +- 12 files changed, 371 insertions(+), 50 deletions(-) diff --git a/DigitalPlatform.LibraryServer/AppEntity.cs b/DigitalPlatform.LibraryServer/AppEntity.cs index cc346ee2a..b8d2b7e07 100644 --- a/DigitalPlatform.LibraryServer/AppEntity.cs +++ b/DigitalPlatform.LibraryServer/AppEntity.cs @@ -2201,7 +2201,7 @@ public LibraryServerResult SetEntities( } } - if (strError != "") + if (string.IsNullOrEmpty(strError) == false) { EntityInfo error = new EntityInfo(info); error.ErrorInfo = strError; diff --git a/DigitalPlatform.LibraryServer/AppScript.cs b/DigitalPlatform.LibraryServer/AppScript.cs index d180b9b8b..c3b0bf06a 100644 --- a/DigitalPlatform.LibraryServer/AppScript.cs +++ b/DigitalPlatform.LibraryServer/AppScript.cs @@ -410,6 +410,7 @@ public int DoVerifyBarcodeScriptFunction( } // 迟绑定技术。从assembly中实时寻找特定名字的函数 + // TODO: 如果两个版本的函数都定义了,会发生什么? MethodInfo mi = hostEntryClassType.GetMethod("VerifyBarcode"); if (mi == null) { diff --git a/DigitalPlatform.LibraryService/LibraryService.cs b/DigitalPlatform.LibraryService/LibraryService.cs index e4aa46dd1..6c3c58686 100644 --- a/DigitalPlatform.LibraryService/LibraryService.cs +++ b/DigitalPlatform.LibraryService/LibraryService.cs @@ -858,7 +858,7 @@ static string CheckClientVersion(string strText) strName = strName.ToLower(); if (strName == "dp2circulation") { - if (version.CompareTo(new Version("2.8")) < 0) + if (version.CompareTo(new Version("2.13")) < 0) return "前端 dp2circulation (内务)版本太旧,登录失败。请立即升级到最新版本"; } diff --git a/DigitalPlatform.Text/StringUtil.cs b/DigitalPlatform.Text/StringUtil.cs index cf4211fed..10b958b98 100644 --- a/DigitalPlatform.Text/StringUtil.cs +++ b/DigitalPlatform.Text/StringUtil.cs @@ -16,6 +16,59 @@ public class StringUtil { public static string SpecialChars = "!·#¥%……—*()——+-=[]《》<>,。?/\|{}“”‘’•"; + public static bool IsValidCMIS(string strText) + { + if (string.IsNullOrEmpty(strText)) + return false; + if (strText.Length == 16) + { + if (IsPureNumber(strText)) + return true; + return false; + } + + if (strText.Length == 19) + { + char ch = strText[0]; + if (ch == 'G' || ch == 'J' || ch == 'L') + { + string strMiddle = strText.Substring(1, 16); // 中间 16 位 + if (IsPureNumber(strMiddle) == false) + return false; + // 最后两位可能是数字或者大写字母 + if (char.IsLetterOrDigit(strText[18]) == false + || char.IsLower(strText[18]) == true + || char.IsLetterOrDigit(strText[17]) == false + || char.IsLower(strText[17]) == true) + return false; + return true; + } + else + return false; + } + + return false; + } + + // 检测一个号码字符串是否在指定的范围内 + public static bool Between(string strNumber, + string strStart, + string strEnd) + { + if (strStart.Length != strEnd.Length) + throw new ArgumentException("strStart 和 strEnd 应当字符数相同"); + if (strNumber == null) + throw new ArgumentException("strNumber 参数值不能为 null"); + + if (strNumber.Length != strStart.Length) + return false; + if (string.Compare(strNumber, strStart) < 0) + return false; + if (string.Compare(strNumber, strEnd) > 0) + return false; + return true; + } + public static int CompareVersion(string strVersion1, string strVersion2) { if (string.IsNullOrEmpty(strVersion1) == true) diff --git a/dp2Circulation/Charging/QuickChargingForm.Designer.cs b/dp2Circulation/Charging/QuickChargingForm.Designer.cs index a34f4f945..59fea3127 100644 --- a/dp2Circulation/Charging/QuickChargingForm.Designer.cs +++ b/dp2Circulation/Charging/QuickChargingForm.Designer.cs @@ -56,6 +56,7 @@ private void InitializeComponent() this.toolStripSeparator4 = new System.Windows.Forms.ToolStripSeparator(); this.toolStripMenuItem_loadPatronInfo = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripMenuItem_inventoryBook = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem_read = new System.Windows.Forms.ToolStripMenuItem(); this.dpColumn_color = new DigitalPlatform.CommonControl.DpColumn(); this.dpColumn_state = new DigitalPlatform.CommonControl.DpColumn(); this.dpColumn_content = new DigitalPlatform.CommonControl.DpColumn(); @@ -79,7 +80,7 @@ private void InitializeComponent() this.toolStripButton_selectItem = new System.Windows.Forms.ToolStripButton(); this.toolStripDropDownButton1 = new System.Windows.Forms.ToolStripDropDownButton(); this.ToolStripMenuItem_inventoryFromFile = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripMenuItem_read = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripDropDownButton_selectLibraryCode = new System.Windows.Forms.ToolStripDropDownButton(); this.contextMenuStrip_selectFunc.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.splitContainer_main)).BeginInit(); this.splitContainer_main.Panel1.SuspendLayout(); @@ -117,99 +118,106 @@ private void InitializeComponent() this.toolStripMenuItem_inventoryBook, this.toolStripMenuItem_read}); this.contextMenuStrip_selectFunc.Name = "contextMenuStrip_selectFunc"; - this.contextMenuStrip_selectFunc.Size = new System.Drawing.Size(153, 292); + this.contextMenuStrip_selectFunc.Size = new System.Drawing.Size(149, 270); this.contextMenuStrip_selectFunc.Opening += new System.ComponentModel.CancelEventHandler(this.contextMenuStrip_selectFunc_Opening); // // toolStripMenuItem_borrow // this.toolStripMenuItem_borrow.Name = "toolStripMenuItem_borrow"; - this.toolStripMenuItem_borrow.Size = new System.Drawing.Size(152, 22); + this.toolStripMenuItem_borrow.Size = new System.Drawing.Size(148, 22); this.toolStripMenuItem_borrow.Text = "借"; this.toolStripMenuItem_borrow.Click += new System.EventHandler(this.toolStripMenuItem_borrow_Click); // // toolStripMenuItem_continueBorrow // this.toolStripMenuItem_continueBorrow.Name = "toolStripMenuItem_continueBorrow"; - this.toolStripMenuItem_continueBorrow.Size = new System.Drawing.Size(152, 22); + this.toolStripMenuItem_continueBorrow.Size = new System.Drawing.Size(148, 22); this.toolStripMenuItem_continueBorrow.Text = "同一读者借"; this.toolStripMenuItem_continueBorrow.Click += new System.EventHandler(this.toolStripMenuItem_continueBorrow_Click); // // toolStripSeparator1 // this.toolStripSeparator1.Name = "toolStripSeparator1"; - this.toolStripSeparator1.Size = new System.Drawing.Size(149, 6); + this.toolStripSeparator1.Size = new System.Drawing.Size(145, 6); // // toolStripMenuItem_return // this.toolStripMenuItem_return.Name = "toolStripMenuItem_return"; - this.toolStripMenuItem_return.Size = new System.Drawing.Size(152, 22); + this.toolStripMenuItem_return.Size = new System.Drawing.Size(148, 22); this.toolStripMenuItem_return.Text = "还"; this.toolStripMenuItem_return.Click += new System.EventHandler(this.toolStripMenuItem_return_Click); // // toolStripMenuItem_verifyReturn // this.toolStripMenuItem_verifyReturn.Name = "toolStripMenuItem_verifyReturn"; - this.toolStripMenuItem_verifyReturn.Size = new System.Drawing.Size(152, 22); + this.toolStripMenuItem_verifyReturn.Size = new System.Drawing.Size(148, 22); this.toolStripMenuItem_verifyReturn.Text = "验证还"; this.toolStripMenuItem_verifyReturn.Click += new System.EventHandler(this.toolStripMenuItem_verifyReturn_Click); // // toolStripSeparator2 // this.toolStripSeparator2.Name = "toolStripSeparator2"; - this.toolStripSeparator2.Size = new System.Drawing.Size(149, 6); + this.toolStripSeparator2.Size = new System.Drawing.Size(145, 6); // // toolStripMenuItem_renew // this.toolStripMenuItem_renew.Name = "toolStripMenuItem_renew"; - this.toolStripMenuItem_renew.Size = new System.Drawing.Size(152, 22); + this.toolStripMenuItem_renew.Size = new System.Drawing.Size(148, 22); this.toolStripMenuItem_renew.Text = "续借"; this.toolStripMenuItem_renew.Click += new System.EventHandler(this.toolStripMenuItem_renew_Click); // // toolStripMenuItem_verifyRenew // this.toolStripMenuItem_verifyRenew.Name = "toolStripMenuItem_verifyRenew"; - this.toolStripMenuItem_verifyRenew.Size = new System.Drawing.Size(152, 22); + this.toolStripMenuItem_verifyRenew.Size = new System.Drawing.Size(148, 22); this.toolStripMenuItem_verifyRenew.Text = "验证续借"; this.toolStripMenuItem_verifyRenew.Click += new System.EventHandler(this.toolStripMenuItem_verifyRenew_Click); // // toolStripSeparator3 // this.toolStripSeparator3.Name = "toolStripSeparator3"; - this.toolStripSeparator3.Size = new System.Drawing.Size(149, 6); + this.toolStripSeparator3.Size = new System.Drawing.Size(145, 6); // // toolStripMenuItem_lost // this.toolStripMenuItem_lost.Name = "toolStripMenuItem_lost"; - this.toolStripMenuItem_lost.Size = new System.Drawing.Size(152, 22); + this.toolStripMenuItem_lost.Size = new System.Drawing.Size(148, 22); this.toolStripMenuItem_lost.Text = "丢失"; this.toolStripMenuItem_lost.Click += new System.EventHandler(this.toolStripMenuItem_lost_Click); // // toolStripMenuItem_verifyLost // this.toolStripMenuItem_verifyLost.Name = "toolStripMenuItem_verifyLost"; - this.toolStripMenuItem_verifyLost.Size = new System.Drawing.Size(152, 22); + this.toolStripMenuItem_verifyLost.Size = new System.Drawing.Size(148, 22); this.toolStripMenuItem_verifyLost.Text = "验证丢失"; this.toolStripMenuItem_verifyLost.Click += new System.EventHandler(this.toolStripMenuItem_verifyLost_Click); // // toolStripSeparator4 // this.toolStripSeparator4.Name = "toolStripSeparator4"; - this.toolStripSeparator4.Size = new System.Drawing.Size(149, 6); + this.toolStripSeparator4.Size = new System.Drawing.Size(145, 6); // // toolStripMenuItem_loadPatronInfo // this.toolStripMenuItem_loadPatronInfo.Name = "toolStripMenuItem_loadPatronInfo"; - this.toolStripMenuItem_loadPatronInfo.Size = new System.Drawing.Size(152, 22); + this.toolStripMenuItem_loadPatronInfo.Size = new System.Drawing.Size(148, 22); this.toolStripMenuItem_loadPatronInfo.Text = "装载读者信息"; this.toolStripMenuItem_loadPatronInfo.Click += new System.EventHandler(this.toolStripMenuItem_loadPatronInfo_Click); // - // ToolStripMenuItem_inventoryBook + // toolStripMenuItem_inventoryBook // - this.toolStripMenuItem_inventoryBook.Name = "ToolStripMenuItem_inventoryBook"; - this.toolStripMenuItem_inventoryBook.Size = new System.Drawing.Size(152, 22); + this.toolStripMenuItem_inventoryBook.Name = "toolStripMenuItem_inventoryBook"; + this.toolStripMenuItem_inventoryBook.Size = new System.Drawing.Size(148, 22); this.toolStripMenuItem_inventoryBook.Text = "盘点图书"; this.toolStripMenuItem_inventoryBook.Click += new System.EventHandler(this.ToolStripMenuItem_inventoryBook_Click); // + // toolStripMenuItem_read + // + this.toolStripMenuItem_read.Name = "toolStripMenuItem_read"; + this.toolStripMenuItem_read.Size = new System.Drawing.Size(148, 22); + this.toolStripMenuItem_read.Text = "读过"; + this.toolStripMenuItem_read.Click += new System.EventHandler(this.ToolStripMenuItem_read_Click); + // // dpColumn_color // this.dpColumn_color.Alignment = System.Drawing.StringAlignment.Near; @@ -272,8 +280,8 @@ private void InitializeComponent() // splitContainer_main.Panel2 // this.splitContainer_main.Panel2.Controls.Add(this.tableLayoutPanel_right); - this.splitContainer_main.Size = new System.Drawing.Size(530, 296); - this.splitContainer_main.SplitterDistance = 289; + this.splitContainer_main.Size = new System.Drawing.Size(587, 307); + this.splitContainer_main.SplitterDistance = 320; this.splitContainer_main.SplitterWidth = 8; this.splitContainer_main.TabIndex = 0; // @@ -283,7 +291,7 @@ private void InitializeComponent() this.webBrowser_reader.Location = new System.Drawing.Point(0, 0); this.webBrowser_reader.MinimumSize = new System.Drawing.Size(20, 20); this.webBrowser_reader.Name = "webBrowser_reader"; - this.webBrowser_reader.Size = new System.Drawing.Size(289, 296); + this.webBrowser_reader.Size = new System.Drawing.Size(320, 307); this.webBrowser_reader.TabIndex = 0; this.webBrowser_reader.DocumentCompleted += new System.Windows.Forms.WebBrowserDocumentCompletedEventHandler(this.webBrowser_reader_DocumentCompleted); // @@ -302,7 +310,7 @@ private void InitializeComponent() this.tableLayoutPanel_right.RowStyles.Add(new System.Windows.Forms.RowStyle()); this.tableLayoutPanel_right.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); this.tableLayoutPanel_right.RowStyles.Add(new System.Windows.Forms.RowStyle()); - this.tableLayoutPanel_right.Size = new System.Drawing.Size(233, 296); + this.tableLayoutPanel_right.Size = new System.Drawing.Size(259, 307); this.tableLayoutPanel_right.TabIndex = 0; // // panel_input @@ -315,9 +323,9 @@ private void InitializeComponent() this.panel_input.Controls.Add(this.label_input_message); this.panel_input.Controls.Add(this.pictureBox_action); this.panel_input.Dock = System.Windows.Forms.DockStyle.Fill; - this.panel_input.Location = new System.Drawing.Point(3, 191); + this.panel_input.Location = new System.Drawing.Point(3, 202); this.panel_input.Name = "panel_input"; - this.panel_input.Size = new System.Drawing.Size(227, 82); + this.panel_input.Size = new System.Drawing.Size(253, 82); this.panel_input.TabIndex = 1; // // colorSummaryControl1 @@ -327,7 +335,7 @@ private void InitializeComponent() this.colorSummaryControl1.ColorList = ""; this.colorSummaryControl1.Location = new System.Drawing.Point(0, 69); this.colorSummaryControl1.Name = "colorSummaryControl1"; - this.colorSummaryControl1.Size = new System.Drawing.Size(227, 10); + this.colorSummaryControl1.Size = new System.Drawing.Size(253, 10); this.colorSummaryControl1.TabIndex = 5; this.colorSummaryControl1.Click += new System.EventHandler(this.colorSummaryControl1_Click); // @@ -340,7 +348,7 @@ private void InitializeComponent() this.textBox_input.ImeMode = System.Windows.Forms.ImeMode.Disable; this.textBox_input.Location = new System.Drawing.Point(3, 25); this.textBox_input.Name = "textBox_input"; - this.textBox_input.Size = new System.Drawing.Size(147, 42); + this.textBox_input.Size = new System.Drawing.Size(173, 42); this.textBox_input.TabIndex = 1; this.textBox_input.Enter += new System.EventHandler(this.textBox_input_Enter); this.textBox_input.Leave += new System.EventHandler(this.textBox_input_Leave); @@ -370,7 +378,7 @@ private void InitializeComponent() // this.pictureBox_action.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); this.pictureBox_action.ContextMenuStrip = this.contextMenuStrip_selectFunc; - this.pictureBox_action.Location = new System.Drawing.Point(159, 0); + this.pictureBox_action.Location = new System.Drawing.Point(185, 0); this.pictureBox_action.Name = "pictureBox_action"; this.pictureBox_action.Size = new System.Drawing.Size(68, 67); this.pictureBox_action.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom; @@ -406,7 +414,7 @@ private void InitializeComponent() this.dpTable_tasks.MaxTextHeight = 200; this.dpTable_tasks.Name = "dpTable_tasks"; this.dpTable_tasks.Padding = new System.Windows.Forms.Padding(8); - this.dpTable_tasks.Size = new System.Drawing.Size(227, 182); + this.dpTable_tasks.Size = new System.Drawing.Size(253, 193); this.dpTable_tasks.TabIndex = 1; this.dpTable_tasks.Text = "dpTable1"; this.dpTable_tasks.ScrollBarTouched += new DigitalPlatform.CommonControl.ScrollBarTouchedEventHandler(this.dpTable_tasks_ScrollBarTouched); @@ -423,11 +431,12 @@ private void InitializeComponent() this.toolStripButton_enableHanzi, this.toolStripButton_upperInput, this.toolStripButton_selectItem, - this.toolStripDropDownButton1}); - this.toolStrip_main.Location = new System.Drawing.Point(0, 276); + this.toolStripDropDownButton1, + this.toolStripDropDownButton_selectLibraryCode}); + this.toolStrip_main.Location = new System.Drawing.Point(0, 287); this.toolStrip_main.Name = "toolStrip_main"; this.toolStrip_main.RenderMode = System.Windows.Forms.ToolStripRenderMode.System; - this.toolStrip_main.Size = new System.Drawing.Size(233, 20); + this.toolStrip_main.Size = new System.Drawing.Size(259, 20); this.toolStrip_main.TabIndex = 2; this.toolStrip_main.Text = "toolStrip1"; // @@ -500,18 +509,21 @@ private void InitializeComponent() this.ToolStripMenuItem_inventoryFromFile.Text = "从文件导入盘点 ..."; this.ToolStripMenuItem_inventoryFromFile.Click += new System.EventHandler(this.ToolStripMenuItem_inventoryFromFile_Click); // - // ToolStripMenuItem_read + // toolStripDropDownButton_selectLibraryCode // - this.toolStripMenuItem_read.Name = "ToolStripMenuItem_read"; - this.toolStripMenuItem_read.Size = new System.Drawing.Size(152, 22); - this.toolStripMenuItem_read.Text = "读过"; - this.toolStripMenuItem_read.Click += new System.EventHandler(this.ToolStripMenuItem_read_Click); + this.toolStripDropDownButton_selectLibraryCode.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text; + this.toolStripDropDownButton_selectLibraryCode.Image = ((System.Drawing.Image)(resources.GetObject("toolStripDropDownButton_selectLibraryCode.Image"))); + this.toolStripDropDownButton_selectLibraryCode.ImageTransparentColor = System.Drawing.Color.Magenta; + this.toolStripDropDownButton_selectLibraryCode.Name = "toolStripDropDownButton_selectLibraryCode"; + this.toolStripDropDownButton_selectLibraryCode.Size = new System.Drawing.Size(69, 17); + this.toolStripDropDownButton_selectLibraryCode.Text = "选择分馆"; + this.toolStripDropDownButton_selectLibraryCode.ToolTipText = "选择当前操作所针对的分馆"; // // QuickChargingForm // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(530, 296); + this.ClientSize = new System.Drawing.Size(587, 307); this.Controls.Add(this.splitContainer_main); this.Name = "QuickChargingForm"; this.ShowIcon = false; @@ -581,5 +593,6 @@ private void InitializeComponent() private System.Windows.Forms.ToolStripDropDownButton toolStripDropDownButton1; private System.Windows.Forms.ToolStripMenuItem ToolStripMenuItem_inventoryFromFile; private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem_read; + private System.Windows.Forms.ToolStripDropDownButton toolStripDropDownButton_selectLibraryCode; } } \ No newline at end of file diff --git a/dp2Circulation/Charging/QuickChargingForm.cs b/dp2Circulation/Charging/QuickChargingForm.cs index eeb910da9..24591eeae 100644 --- a/dp2Circulation/Charging/QuickChargingForm.cs +++ b/dp2Circulation/Charging/QuickChargingForm.cs @@ -160,6 +160,69 @@ private void QuickChargingForm_Load(object sender, EventArgs e) { SetReaderHtmlString("(空)"); } + + this.BeginInvoke(new Action(FillLibraryCodeListMenu)); + } + + string _focusLibraryCode = ""; + + // 当前操作所针对的分馆 代码 + // 注: 全局用户可以操作任何分管,和总馆,通过此成员,可以明确它当前正在操作哪个分馆,这样可以明确 VerifyBarcode() 的 strLibraryCodeList 参数值 + public string FocusLibraryCode + { + get + { + return _focusLibraryCode; + } + set + { + this._focusLibraryCode = value; + this.Text = "快捷出纳 - " + (string.IsNullOrEmpty(value) == true ? "[总馆]" : value); + } + } + + void FillLibraryCodeListMenu() + { + string strError = ""; + List all_library_codes = null; + int nRet = this.GetAllLibraryCodes(out all_library_codes, out strError); + + List library_codes = null; + if (Global.IsGlobalUser(this.Channel.LibraryCodeList) == true) + { + library_codes = all_library_codes; + library_codes.Insert(0, ""); + } + else + library_codes = StringUtil.SplitList(this.Channel.LibraryCodeList); + + this.toolStripDropDownButton_selectLibraryCode.DropDownItems.Clear(); + foreach (string library_code in library_codes) + { + string strName = library_code; + if (string.IsNullOrEmpty(strName) == true) + strName = "[总馆]"; + ToolStripItem item = new ToolStripMenuItem(strName); + item.Tag = library_code; + item.Click += item_Click; + this.toolStripDropDownButton_selectLibraryCode.DropDownItems.Add(item); + } + + // 默认选定第一项 + if (this.toolStripDropDownButton_selectLibraryCode.DropDownItems.Count > 0) + item_Click(this.toolStripDropDownButton_selectLibraryCode.DropDownItems[0], new EventArgs()); + } + + void item_Click(object sender, EventArgs e) + { + ToolStripMenuItem item = (ToolStripMenuItem)sender; + foreach (ToolStripMenuItem current in this.toolStripDropDownButton_selectLibraryCode.DropDownItems) + { + if (current != item && current.Checked == true) + current.Checked = false; + } + item.Checked = true; + FocusLibraryCode = item.Tag as string; } void m_webExternalHost_readerInfo_OutputDebugInfo(object sender, OutputDebugInfoEventArgs e) @@ -1485,7 +1548,7 @@ void _doAction(FuncState func, // 1 是合法的读者证条码号 // 2 是合法的册条码号 int nRet = VerifyBarcode( - this.Channel.LibraryCodeList, + this.FocusLibraryCode, // this.Channel.LibraryCodeList, strText, out strError); if (nRet == -2) @@ -1508,7 +1571,7 @@ void _doAction(FuncState func, { // TODO: 语音提示 // TODO: 红色对话框 - MessageBox.Show(this, "'" + strText + "' 不是合法的条码号"); + MessageBox.Show(this, "'" + strText + "' 不是合法的条码号: " + strError); this.textBox_input.SelectAll(); this.textBox_input.Focus(); return; diff --git a/dp2Circulation/Charging/QuickChargingForm.resx b/dp2Circulation/Charging/QuickChargingForm.resx index e69a4d68b..b481963bb 100644 --- a/dp2Circulation/Charging/QuickChargingForm.resx +++ b/dp2Circulation/Charging/QuickChargingForm.resx @@ -125,7 +125,7 @@ AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0 ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAAC4 - CQAAAk1TRnQBSQFMAgEBAgEAAVQBAAFUAQABEAEAARABAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo + CQAAAk1TRnQBSQFMAgEBAgEAAWQBAAFkAQABEAEAARABAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo AwABQAMAARADAAEBAQABCAYAAQQYAAGAAgABgAMAAoABAAGAAwABgAEAAYABAAKAAgADwAEAAcAB3AHA AQAB8AHKAaYBAAEzBQABMwEAATMBAAEzAQACMwIAAxYBAAMcAQADIgEAAykBAANVAQADTQEAA0IBAAM5 AQABgAF8Af8BAAJQAf8BAAGTAQAB1gEAAf8B7AHMAQABxgHWAe8BAAHWAucBAAGQAakBrQIAAf8BMwMA @@ -189,7 +189,7 @@ AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0 ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAAB2 - IQAAAk1TRnQBSQFMAgEBBQEAAVQBAAFUAQABQAEAAUABAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo + IQAAAk1TRnQBSQFMAgEBBQEAAWQBAAFkAQABQAEAAUABAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo BAABAQIAAYADAAEBAQABCAYAAYAYAAGAAgABgAMAAoABAAGAAwABgAEAAYABAAKAAgADwAEAAcAB3AHA AQAB8AHKAaYBAAEzBQABMwEAATMBAAEzAQACMwIAAxYBAAMcAQADIgEAAykBAANVAQADTQEAA0IBAAM5 AQABgAF8Af8BAAJQAf8BAAGTAQAB1gEAAf8B7AHMAQABxgHWAe8BAAHWAucBAAGQAakBrQIAAf8BMwMA @@ -342,7 +342,7 @@ AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0 ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAAAs - DwAAAk1TRnQBSQFMAgEBBQEAAVQBAAFUAQABGAEAARgBAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo + DwAAAk1TRnQBSQFMAgEBBQEAAWQBAAFkAQABGAEAARgBAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo AwABYAMAATADAAEBAQABCAYAARIYAAGAAgABgAMAAoABAAGAAwABgAEAAYABAAKAAgADwAEAAcAB3AHA AQAB8AHKAaYBAAEzBQABMwEAATMBAAEzAQACMwIAAxYBAAMcAQADIgEAAykBAANVAQADTQEAA0IBAAM5 AQABgAF8Af8BAAJQAf8BAAGTAQAB1gEAAf8B7AHMAQABxgHWAe8BAAHWAucBAAGQAakBrQIAAf8BMwMA @@ -471,6 +471,21 @@ mDEo5mNjuweFGvjWg2EBhCbpkW78htSHHwRyNdmgAFzPEee2iFkzayy2OLXzT4gr6UdUnlXrullsxxQ+ kx0g8BTA3aZlButjSTyjODq/WcQcW/B/Je4OQhLvKQDnzN1mp0nnkvAhR8VuMzNrpm1mpjgkoVwB/v8D TgDQASA1MVpwzwAAAABJRU5ErkJggg== + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIDSURBVDhPpZLrS5NhGMb3j4SWh0oRQVExD4gonkDpg4hG + 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/FontSetting/MyForm.cs b/dp2Circulation/FontSetting/MyForm.cs index 9621a18d2..b131466db 100644 --- a/dp2Circulation/FontSetting/MyForm.cs +++ b/dp2Circulation/FontSetting/MyForm.cs @@ -425,6 +425,26 @@ public virtual void Channel_AfterLogin(object sender, AfterLoginEventArgs e) this.MainForm.Channel_AfterLogin(sender, e); // 2015/11/4 原来是 this } + // 获得全部可用的图书馆代码。注意,并不包含 "" (全局) + public int GetAllLibraryCodes(out List library_codes, + out string strError) + { + strError = ""; + library_codes = new List(); + + string strValue = ""; + long lRet = this.Channel.GetSystemParameter(stop, + "system", + "libraryCodes", + out strValue, + out strError); + if (lRet == -1) + return -1; + library_codes = StringUtil.SplitList(strValue); + + return 0; + } + #endregion /// diff --git a/dp2Circulation/Properties/AssemblyInfo.cs b/dp2Circulation/Properties/AssemblyInfo.cs index daac754de..64e6ecaff 100644 --- a/dp2Circulation/Properties/AssemblyInfo.cs +++ b/dp2Circulation/Properties/AssemblyInfo.cs @@ -29,8 +29,8 @@ // Build Number // Revision // -[assembly: AssemblyVersion("2.12.*")] // "2.4.*" -[assembly: AssemblyFileVersion("2.12.0.0")] +[assembly: AssemblyVersion("2.13.*")] // "2.4.*" +[assembly: AssemblyFileVersion("2.13.0.0")] // V2.6 2015/11/7 MainForm BiblioSearchForm ChannelForm 采用 ChannelPool。注意观察有无通讯通道方面的故障 // V2.7 2015/11/30 EntityForm 大幅度改造,采用 ChannelPool。Stop 类的 BeginLoop() 不再允许嵌套,注意观察是否会抛出异常。固定面板区属性页的显示很多已经改造为 PropertyTaskList 实现 @@ -40,4 +40,5 @@ // V2.10 2015/12/14 DigitalPlatform.CirculationClient.dll 中剥离部分纯粹通讯功能到 DigitalPlatform.LibraryClient.dll。有可能部分统计方案编译报错,需要修改后发布 // 2.10.5829.27554 2015/12/17 修改了 DigitalPlatform.Drawing 和 DigitalPlatform 的 AssemblyInfo.cs 文件 // V2.11 2016/1/4 读者查询窗和读者窗在导出读者详情 Excel 文件时,可以选择输出借阅历史了。“关于”窗口里面标识了开源的情况。 -// V2.12 2016/1/22 clientcfgs 子目录从数据目录移动到用户目录中了。*projects.xml 也移动了。 \ No newline at end of file +// V2.12 2016/1/22 clientcfgs 子目录从数据目录移动到用户目录中了。*projects.xml 也移动了。 +// V2.13 2016/3/31 启用按照每个分馆进行条码号校验的功能 \ No newline at end of file diff --git a/dp2Circulation/SearchForms/ItemSearchForm.cs b/dp2Circulation/SearchForms/ItemSearchForm.cs index c522c07a3..506c1821a 100644 --- a/dp2Circulation/SearchForms/ItemSearchForm.cs +++ b/dp2Circulation/SearchForms/ItemSearchForm.cs @@ -2178,6 +2178,14 @@ private void listView_records_MouseUp(object sender, MouseEventArgs e) subMenuItem.Enabled = false; menuItem.MenuItems.Add(subMenuItem); + + subMenuItem = new MenuItem("校验册记录 [" + this.listView_records.SelectedItems.Count.ToString() + "] (&V)"); + subMenuItem.Click += new System.EventHandler(this.menu_verifyItemRecord_Click); + if (this.listView_records.SelectedItems.Count == 0 || bLooping == true) + subMenuItem.Enabled = false; + menuItem.MenuItems.Add(subMenuItem); + + // --- subMenuItem = new MenuItem("-"); menuItem.MenuItems.Add(subMenuItem); @@ -2458,6 +2466,20 @@ private void listView_records_MouseUp(object sender, MouseEventArgs e) contextMenu.Show(this.listView_records, new Point(e.X, e.Y)); } + void menu_verifyItemRecord_Click(object sender, EventArgs e) + { + string strError = ""; + int nRet = 0; + + nRet = VerifyItemRecord(out strError); + if (nRet == -1) + goto ERROR1; + MessageBox.Show(this, "共处理 " + nRet.ToString() + " 个册记录"); + return; + ERROR1: + MessageBox.Show(this, strError); + } + void menu_borrow_Click(object sender, EventArgs e) { string strError = ""; @@ -2501,6 +2523,139 @@ void menu_inventory_Click(object sender, EventArgs e) MessageBox.Show(this, strError); } + int VerifyItemRecord(out string strError) + { + strError = ""; + int nRet = 0; + + Debug.Assert(this.DbType == "item", ""); + + if (this.listView_records.SelectedItems.Count == 0) + { + strError = "尚未选定要进行批处理的事项"; + return -1; + } + + if (stop != null && stop.State == 0) // 0 表示正在处理 + { + strError = "目前有长操作正在进行,无法进行校验册记录的操作"; + return -1; + } + + // 切换到“操作历史”属性页 + this.MainForm.ActivateFixPage("history"); + + int nCount = 0; + + stop.Style = StopStyle.EnableHalfStop; + stop.OnStop += new StopEventHandler(this.DoStop); + stop.Initial("正在进行校验册记录的操作 ..."); + stop.BeginLoop(); + + this.EnableControls(false); + try + { + stop.SetProgressRange(0, this.listView_records.SelectedItems.Count); + + List items = new List(); + foreach (ListViewItem item in this.listView_records.SelectedItems) + { + if (string.IsNullOrEmpty(item.Text) == true) + continue; + + items.Add(item); + } + + ListViewPatronLoader loader = new ListViewPatronLoader(this.Channel, + stop, + items, + this.m_biblioTable); + loader.DbTypeCaption = this.DbTypeCaption; + + int i = 0; + foreach (LoaderItem item in loader) + { + Application.DoEvents(); // 出让界面控制权 + + if (stop != null + && stop.State != 0) + { + strError = "用户中断"; + return -1; + } + + BiblioInfo info = item.BiblioInfo; + + XmlDocument itemdom = new XmlDocument(); + try + { + itemdom.LoadXml(info.OldXml); + } + catch (Exception ex) + { + strError = "记录 '" + info.RecPath + "' 的 XML 装入 DOM 时出错: " + ex.Message; + return -1; + } + + string strBarcode = DomUtil.GetElementText(itemdom.DocumentElement, "barcode"); + + if (string.IsNullOrEmpty(strBarcode) == false) + { + + string strLocation = DomUtil.GetElementText(itemdom.DocumentElement, "location"); + strLocation = StringUtil.GetPureLocationString(strLocation); + + string strLibraryCode = ""; + string strRoom = ""; + // 解析 + Global.ParseCalendarName(strLocation, + out strLibraryCode, + out strRoom); + + + // -2 服务器没有配置校验方法,无法校验 + // -1 出错 + // 0 不是合法的条码号 + // 1 是合法的读者证条码号 + // 2 是合法的册条码号 + nRet = this.MainForm.VerifyBarcode( + this.stop, + this.Channel, + strLibraryCode, + strBarcode, + null, + out strError); + if (nRet == -2) + return -1; + if (nRet != 2) + { + if (nRet == 1 && string.IsNullOrEmpty(strError) == true) + strError = strLibraryCode + ": 这看起来是一个证条码号"; + + this.MainForm.OperHistory.AppendHtml("
" + HttpUtility.HtmlEncode(info.RecPath) + "
"); + this.MainForm.OperHistory.AppendHtml("
" + "册条码号 '" + strBarcode + "' 不合法: " + strError + "
"); + } + + nCount++; + } + + stop.SetProgressValue(++i); + } + + return nCount; + } + finally + { + stop.EndLoop(); + stop.OnStop -= new StopEventHandler(this.DoStop); + stop.Initial(""); + stop.HideProgress(); + stop.Style = StopStyle.None; + + this.EnableControls(true); + } + } + // 进行流通操作 int DoCirculation(string strAction, @@ -5702,7 +5857,7 @@ void menu_exportBiblioDumpFile_Click(object sender, EventArgs e) w.WriteAttributeString("path", this.MainForm.LibraryServerUrl + "?" + strBiblioRecPath); w.WriteAttributeString("timestamp", ByteArray.GetHexTimeStampString(baTimestamp)); - + domBiblio.DocumentElement.WriteTo(w); w.WriteEndElement(); diff --git a/dp2Circulation/dp2Circulation.csproj b/dp2Circulation/dp2Circulation.csproj index 77786d1de..9d1bcf084 100644 --- a/dp2Circulation/dp2Circulation.csproj +++ b/dp2Circulation/dp2Circulation.csproj @@ -51,7 +51,7 @@ dp2 V2 true publish.htm - 32 + 34 2.10.0.%2a false true diff --git a/dp2Installer/dp2Installer.csproj b/dp2Installer/dp2Installer.csproj index f273e8ca1..1c91e9831 100644 --- a/dp2Installer/dp2Installer.csproj +++ b/dp2Installer/dp2Installer.csproj @@ -34,7 +34,7 @@ dp2 V2 true publish.htm - 104 + 106 1.1.0.%2a false true From 95ed7c3d7f565374a970ed36135e9ac3f3487fd3 Mon Sep 17 00:00:00 2001 From: XieTao Date: Fri, 8 Apr 2016 03:40:18 +0800 Subject: [PATCH 06/10] =?UTF-8?q?=E4=BF=AE=E6=AD=A3=E4=B8=80=E4=BA=9B=20Bu?= =?UTF-8?q?g?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DigitalPlatform.IO/ItemFileBase.cs | 2868 +++++++++-------- DigitalPlatform.LibraryServer/AppBiblio.cs | 2 +- DigitalPlatform.LibraryServer/AppDup.cs | 290 +- DigitalPlatform.LibraryServer/AppEntity.cs | 66 +- DigitalPlatform.LibraryServer/AppReader.cs | 51 +- DigitalPlatform.LibraryServer/AppScript.cs | 101 +- DigitalPlatform.LibraryServer/DupResultSet.cs | 11 +- .../LibraryApplication.cs | 2 - DigitalPlatform.LibraryServer/SessionInfo.cs | 5 +- .../LibraryService.cs | 12 +- .../DigitalPlatform.ResultSet.cs | 1 - DigitalPlatform.Text/StringUtil.cs | 5 +- DigitalPlatform.rms.db/DatabaseCollection.cs | 34 +- dp2Circulation/EntityForm/EntityForm.cs | 5 +- dp2Circulation/Reader/ReaderSearchForm.cs | 152 + dp2Circulation/SearchForms/ItemSearchForm.cs | 9 + dp2Circulation/Statis/ReportForm.cs | 39 +- dp2Circulation/Statis/ReportWriter.cs | 128 +- dp2Circulation/Statis/SQLiteUtil.cs | 11 +- dp2Circulation/dp2Circulation.csproj | 6 +- dp2Installer/dp2Installer.csproj | 2 +- dp2Library/Host.cs | 46 +- dp2LibraryXE/dp2LibraryXE.csproj | 6 +- 23 files changed, 2147 insertions(+), 1705 deletions(-) diff --git a/DigitalPlatform.IO/ItemFileBase.cs b/DigitalPlatform.IO/ItemFileBase.cs index 9b4466efe..a98ebb6aa 100644 --- a/DigitalPlatform.IO/ItemFileBase.cs +++ b/DigitalPlatform.IO/ItemFileBase.cs @@ -7,40 +7,40 @@ namespace DigitalPlatform.IO { - // 数据事项 - public class Item : IComparable - { -// public int DataLength = 0; + // 数据事项 + public class Item : IComparable + { + // public int DataLength = 0; - public virtual int Length - { - get - { - return 0; - } - set - { - } - } + public virtual int Length + { + get + { + return 0; + } + set + { + } + } - public virtual void ReadData(Stream stream) - { - // 读入Length个bytes的内容 + public virtual void ReadData(Stream stream) + { + // 读入Length个bytes的内容 - } + } - public virtual void ReadCompareData(Stream stream) - { - // 读入Length个bytes的内容 + public virtual void ReadCompareData(Stream stream) + { + // 读入Length个bytes的内容 - } + } - public virtual void WriteData(Stream stream) - { - // 写入Length个bytes的内容 + public virtual void WriteData(Stream stream) + { + // 写入Length个bytes的内容 - } + } public virtual void BuildBuffer() { @@ -48,113 +48,112 @@ public virtual void BuildBuffer() } - // 实现IComparable接口的CompareTo()方法, - // 根据ID比较两个对象的大小,以便排序, - // 按右对齐方式比较 - // obj: An object to compare with this instance - // 返回值 A 32-bit signed integer that indicates the relative order of the comparands. The return value has these meanings: - // Less than zero: This instance is less than obj. - // Zero: This instance is equal to obj. - // Greater than zero: This instance is greater than obj. - // 异常: ArgumentException,obj is not the same type as this instance. - public virtual int CompareTo(object obj) - { - Item item = (Item)obj; + // 实现IComparable接口的CompareTo()方法, + // 根据ID比较两个对象的大小,以便排序, + // 按右对齐方式比较 + // obj: An object to compare with this instance + // 返回值 A 32-bit signed integer that indicates the relative order of the comparands. The return value has these meanings: + // Less than zero: This instance is less than obj. + // Zero: This instance is equal to obj. + // Greater than zero: This instance is greater than obj. + // 异常: ArgumentException,obj is not the same type as this instance. + public virtual int CompareTo(object obj) + { + Item item = (Item)obj; - return (this.Length - item.Length); // 比较谁内容更长 - } + return (this.Length - item.Length); // 比较谁内容更长 + } - } + } - // 枚举器 - public class ItemFileBaseEnumerator : IEnumerator - { - ItemFileBase m_file = null; - long m_index = -1; + // 枚举器 + public class ItemFileBaseEnumerator : IEnumerator + { + ItemFileBase m_file = null; + long m_index = -1; - public ItemFileBaseEnumerator(ItemFileBase file) - { - m_file = file; - } + public ItemFileBaseEnumerator(ItemFileBase file) + { + m_file = file; + } - public void Reset() - { - m_index = -1; - } + public void Reset() + { + m_index = -1; + } - public bool MoveNext() - { - m_index ++; - if (m_index >= m_file.Count) - return false; + public bool MoveNext() + { + m_index++; + if (m_index >= m_file.Count) + return false; - return true; - } + return true; + } - public object Current - { - get - { - return (object)m_file[m_index]; - } - } - } + public object Current + { + get + { + return (object)m_file[m_index]; + } + } + } - // 拍紧风格 + // 拍紧风格 [Flags] - public enum CompressStyle - { - Index = 0x01, // 拍紧索引文件 - Data = 0x02, // 拍紧数据文件 - } - - public delegate Item Delegate_newItem(); - - /// - /// 文件中的事项集合。实现事项可排序、自由存取的大文件功能。对内存需求小。 - /// - public class ItemFileBase : IEnumerable, IDisposable - { + public enum CompressStyle + { + Index = 0x01, // 拍紧索引文件 + Data = 0x02, // 拍紧数据文件 + } + + public delegate Item Delegate_newItem(); + + /// + /// 文件中的事项集合。实现事项可排序、自由存取的大文件功能。对内存需求小。 + /// + public class ItemFileBase : IEnumerable, IDisposable + { public bool ReadOnly = false; - public ReaderWriterLock m_lock = new ReaderWriterLock(); - public static int m_nLockTimeout = 5000; // 5000=5秒 + public ReaderWriterLock m_lock = new ReaderWriterLock(); + public static int m_nLockTimeout = 5000; // 5000=5秒 + bool disposed = false; + // 大文件,大流 + public string m_strBigFileName = ""; + public Stream m_streamBig = null; - bool disposed = false; - // 大文件,大流 - public string m_strBigFileName = ""; - public Stream m_streamBig = null; + // 小文件,小流 + public string m_strSmallFileName = ""; + public Stream m_streamSmall = null; - // 小文件,小流 - public string m_strSmallFileName = ""; - public Stream m_streamSmall = null; + public long m_count = 0; - public long m_count = 0; + bool bDirty = false; //初始值false,表示干净 - bool bDirty = false; //初始值false,表示干净 - - public Delegate_newItem procNewItem = null; - /* - * 使用说明 - 如果procNewItem已经挂接了delegate,则集合类会在适当时候使用它来创建新Item或其派生类的对象 - 这个方法的好处,是不用派生集合类ItemFileBase - 如果procNewItem为空,就使用this.NewItem()函数。基类中有缺省实现,就是返回Item类型对象 - 这个方法的缺点,是要派生集合类ItemFileBase - 两个方法最好不要混用,因为容易导致理解混乱。如果混用,procNewItem优先。 - * - */ + public Delegate_newItem procNewItem = null; + /* + * 使用说明 + 如果procNewItem已经挂接了delegate,则集合类会在适当时候使用它来创建新Item或其派生类的对象 + 这个方法的好处,是不用派生集合类ItemFileBase + 如果procNewItem为空,就使用this.NewItem()函数。基类中有缺省实现,就是返回Item类型对象 + 这个方法的缺点,是要派生集合类ItemFileBase + 两个方法最好不要混用,因为容易导致理解混乱。如果混用,procNewItem优先。 + * + */ - public ItemFileBase() - { - // - // TODO: Add constructor logic here - // - } + public ItemFileBase() + { + // + // TODO: Add constructor logic here + // + } #if NO // TODO: 容易造成 mem leak。建议用 Dispose() 改写 @@ -172,135 +171,140 @@ public ItemFileBase() } #endif - // Implement IDisposable. - // Do not make this method virtual. - // A derived class should not be able to override this method. - public void Dispose() - { - Dispose(true); - // This object will be cleaned up by the Dispose method. - // Therefore, you should call GC.SupressFinalize to - // take this object off the finalization queue - // and prevent finalization code for this object - // from executing a second time. - GC.SuppressFinalize(this); - } + // Implement IDisposable. + // Do not make this method virtual. + // A derived class should not be able to override this method. + public void Dispose() + { + Dispose(true); + // This object will be cleaned up by the Dispose method. + // Therefore, you should call GC.SupressFinalize to + // take this object off the finalization queue + // and prevent finalization code for this object + // from executing a second time. + GC.SuppressFinalize(this); + } - // Dispose(bool disposing) executes in two distinct scenarios. - // If disposing equals true, the method has been called directly - // or indirectly by a user's code. Managed and unmanaged resources - // can be disposed. - // If disposing equals false, the method has been called by the - // runtime from inside the finalizer and you should not reference - // other objects. Only unmanaged resources can be disposed. - private void Dispose(bool disposing) - { - // Check to see if Dispose has already been called. - if(!this.disposed) - { - // If disposing equals true, dispose all managed - // and unmanaged resources. - if(disposing) - { - // Dispose managed resources. + // Dispose(bool disposing) executes in two distinct scenarios. + // If disposing equals true, the method has been called directly + // or indirectly by a user's code. Managed and unmanaged resources + // can be disposed. + // If disposing equals false, the method has been called by the + // runtime from inside the finalizer and you should not reference + // other objects. Only unmanaged resources can be disposed. + private void Dispose(bool disposing) + { + // Check to see if Dispose has already been called. + if (!this.disposed) + { + // If disposing equals true, dispose all managed + // and unmanaged resources. + if (disposing) + { + // Dispose managed resources. // 这里有一点问题:可能析构函数调不了Close() - // this.Close(); - } + // this.Close(); + } this.Close(); // 2007/6/8 移动到这里的 - - /* - // Call the appropriate methods to clean up - // unmanaged resources here. - // If disposing is false, - // only the following code is executed. - CloseHandle(handle); - handle = IntPtr.Zero; - */ - } - disposed = true; - } + /* + // Call the appropriate methods to clean up + // unmanaged resources here. + // If disposing is false, + // only the following code is executed. + CloseHandle(handle); + handle = IntPtr.Zero; + */ + } + disposed = true; + } - // 创建新item对象 - // 如果派生了item类并且希望放在本集合中管理,可派生集合类并重载本函数。 - // 也可使用procNewItem接口,这样就不必派生集合类 - // 参见procNewItem定义处说明 - public virtual Item NewItem() - { - return new Item(); - } + // 创建新item对象 + // 如果派生了item类并且希望放在本集合中管理,可派生集合类并重载本函数。 + // 也可使用procNewItem接口,这样就不必派生集合类 + // 参见procNewItem定义处说明 + public virtual Item NewItem() + { + return new Item(); + } - // 整数索引器 - public Item this[Int64 nIndex] - { - get - { - return GetItem(nIndex, false); - } - } + // 整数索引器 + public Item this[Int64 nIndex] + { + get + { + return GetItem(nIndex, false); + } + } - // 记录数 - public Int64 Count - { - get - { - // 加读锁 - this.m_lock.AcquireReaderLock(m_nLockTimeout); - try - { - return m_count; - } - finally - { - this.m_lock.ReleaseReaderLock(); - } - - } - } + // 记录数 + public Int64 Count + { + get + { + // 加读锁 + this.m_lock.AcquireReaderLock(m_nLockTimeout); + try + { + return m_count; + } + finally + { + this.m_lock.ReleaseReaderLock(); + } - // 清空内容,但仍然在可用状态 - public void Clear() - { - // 加写锁 - this.m_lock.AcquireWriterLock(m_nLockTimeout); - try - { - if (m_streamBig != null) - m_streamBig.SetLength(0); - - if (m_streamSmall != null) - m_streamSmall.SetLength(0); - - m_count=0; - bDirty = false; - } - finally - { - this.m_lock.ReleaseWriterLock(); - } + } + } - } + // 清空内容,但仍然在可用状态 + public void Clear() + { + // 加写锁 + this.m_lock.AcquireWriterLock(m_nLockTimeout); + try + { + if (m_streamBig != null) + m_streamBig.SetLength(0); + + if (m_streamSmall != null) + m_streamSmall.SetLength(0); + + m_count = 0; + bDirty = false; + } + finally + { + this.m_lock.ReleaseWriterLock(); + } + + } + + public delegate string Delegate_getTempFileName(); // 打开 // bInitialIndex 初始化index文件,并打开。 - public void Open(bool bInitialIndex) + public void Open(bool bInitialIndex, + Delegate_getTempFileName procGetTempFileName = null) { // 加写锁 this.m_lock.AcquireWriterLock(m_nLockTimeout); try { - if (m_streamBig == null) { - if (m_strBigFileName == "") + // 2016/4/5 + // 优先使用临时的函数 创建临时文件 + if (procGetTempFileName != null) + m_strBigFileName = procGetTempFileName(); + + if (string.IsNullOrEmpty(m_strBigFileName) == true) m_strBigFileName = this.GetTempFileName(); // 创建临时文件可以用delegate处理 m_streamBig = File.Open(m_strBigFileName, FileMode.OpenOrCreate); - /* m_streamBig = File.Open(m_strBigFileName, FileMode.OpenOrCreate, @@ -320,7 +324,7 @@ public void Open(bool bInitialIndex) if (strSaveSmallFileName != "") m_strSmallFileName = strSaveSmallFileName; - OpenIndexFile(); + OpenIndexFile(procGetTempFileName); } } @@ -330,471 +334,470 @@ public void Open(bool bInitialIndex) } } - // 完整复制一个集合对象 - public void Copy(ItemFileBase file) - { - // 加写锁 - this.m_lock.AcquireWriterLock(m_nLockTimeout); - try - { - this.Clear(); - - foreach(Item item in file) - { - this.Add(item); - } - } - finally - { - this.m_lock.ReleaseWriterLock(); - } - } + // 完整复制一个集合对象 + public void Copy(ItemFileBase file) + { + // 加写锁 + this.m_lock.AcquireWriterLock(m_nLockTimeout); + try + { + this.Clear(); + + foreach (Item item in file) + { + this.Add(item); + } + } + finally + { + this.m_lock.ReleaseWriterLock(); + } + } - // 压缩掉那些已标记删除事项占据的磁盘空间 - // 对于index文件,如果其中没有包含标记删除的事项,可以使用乘法搜索,速度快。 - // 一般要求排序前,Compress一下,否则排序速度很慢。 - public void CompressDeletedItem(CompressStyle style) - { - if ((style & CompressStyle.Data) == CompressStyle.Data) - { - // 删除标志在index文件中 - - throw(new Exception("暂时不支持此功能")); - /* - // 清除老index - RemoveIndexFile(); - OpenIndexFile(); - */ - } - - if ((style & CompressStyle.Index) == CompressStyle.Index) - { - if (m_streamSmall == null) - return; - CompressIndex(m_streamSmall); - bDirty = false; - } + // 压缩掉那些已标记删除事项占据的磁盘空间 + // 对于index文件,如果其中没有包含标记删除的事项,可以使用乘法搜索,速度快。 + // 一般要求排序前,Compress一下,否则排序速度很慢。 + public void CompressDeletedItem(CompressStyle style) + { + if ((style & CompressStyle.Data) == CompressStyle.Data) + { + // 删除标志在index文件中 + + throw (new Exception("暂时不支持此功能")); + /* + // 清除老index + RemoveIndexFile(); + OpenIndexFile(); + */ + } - } + if ((style & CompressStyle.Index) == CompressStyle.Index) + { + if (m_streamSmall == null) + return; + CompressIndex(m_streamSmall); + bDirty = false; + } - // 在尾部追加一个事项 - public virtual void Add(Item item) - { - // 加写锁 - this.m_lock.AcquireWriterLock(m_nLockTimeout); - try - { + } + + // 在尾部追加一个事项 + public virtual void Add(Item item) + { + // 加写锁 + this.m_lock.AcquireWriterLock(m_nLockTimeout); + try + { - // 将数据文件指针置于尾部 - m_streamBig.Seek(0, - SeekOrigin.End); + // 将数据文件指针置于尾部 + m_streamBig.Seek(0, + SeekOrigin.End); - // 若存在索引文件 - if (m_streamSmall != null) - { - // 写入一个新index条目 + // 若存在索引文件 + if (m_streamSmall != null) + { + // 写入一个新index条目 - m_streamSmall.Seek (0,SeekOrigin.End); - long nPosition = m_streamBig.Position ; + m_streamSmall.Seek(0, SeekOrigin.End); + long nPosition = m_streamBig.Position; - byte[] bufferPosition = new byte[8]; - bufferPosition = System.BitConverter.GetBytes((long)nPosition); // 原来缺乏(long), 是一个bug. 2006/10/1 修改 + byte[] bufferPosition = new byte[8]; + bufferPosition = System.BitConverter.GetBytes((long)nPosition); // 原来缺乏(long), 是一个bug. 2006/10/1 修改 Debug.Assert(bufferPosition.Length == 8, ""); m_streamSmall.Write(bufferPosition, 0, 8); - } + } // 2007/7/3 item.BuildBuffer(); - byte[] bufferLength = System.BitConverter.GetBytes((Int32)item.Length); + byte[] bufferLength = System.BitConverter.GetBytes((Int32)item.Length); Debug.Assert(bufferLength.Length == 4, ""); - m_streamBig.Write(bufferLength,0,4); + m_streamBig.Write(bufferLength, 0, 4); - item.WriteData(m_streamBig); + item.WriteData(m_streamBig); - m_count++; - } - finally - { - this.m_lock.ReleaseWriterLock(); - } - } + m_count++; + } + finally + { + this.m_lock.ReleaseWriterLock(); + } + } - // 标记删除一条记录 - public void RemoveAt(int nIndex) - { - // 加写锁 - this.m_lock.AcquireWriterLock(m_nLockTimeout); - try - { - - if (nIndex < 0 || nIndex >= m_count) - { - throw(new Exception("下标 " + Convert.ToString(nIndex) + " 越界(Count=" + Convert.ToString(m_count) + ")")); - } - int nRet = RemoveAtAuto(nIndex); - if (nRet == -1) - { - throw(new Exception ("RemoveAtAuto fail")); - } - - m_count --; - // bDirty = true; // 表示已经有标记删除的事项了 - - } - finally - { - this.m_lock.ReleaseWriterLock(); - } - } + // 标记删除一条记录 + public void RemoveAt(int nIndex) + { + // 加写锁 + this.m_lock.AcquireWriterLock(m_nLockTimeout); + try + { - //标记删除多条记录 - public void RemoveAt(int nIndex, - int nCount) - { - // 加写锁 - this.m_lock.AcquireWriterLock(m_nLockTimeout); - try - { - - if (nIndex < 0 || nIndex + nCount > m_count) - { - throw(new Exception("下标 " + Convert.ToString(nIndex) + " 越界(Count=" + Convert.ToString(m_count) + ")")); - } - - int nRet = 0; - if (m_streamSmall != null) // 有索引文件时 - { - // nRet = RemoveAtIndex(nIndex); - nRet = CompressRemoveAtIndex(nIndex, nCount); - } - else - { - throw(new Exception ("暂时还没有编写")); - - } - - - if (nRet == -1) - { - throw(new Exception ("RemoveAtAuto fail")); - } - - m_count -= nCount; - // bDirty = true; // 表示已经有标记删除的事项了 - - } - finally - { - this.m_lock.ReleaseWriterLock(); - } - } + if (nIndex < 0 || nIndex >= m_count) + { + throw (new Exception("下标 " + Convert.ToString(nIndex) + " 越界(Count=" + Convert.ToString(m_count) + ")")); + } + int nRet = RemoveAtAuto(nIndex); + if (nRet == -1) + { + throw (new Exception("RemoveAtAuto fail")); + } - // 插入一个事项 - public virtual void Insert(int nIndex, - Item item) - { - // 加写锁 - this.m_lock.AcquireWriterLock(m_nLockTimeout); - try - { + m_count--; + // bDirty = true; // 表示已经有标记删除的事项了 + + } + finally + { + this.m_lock.ReleaseWriterLock(); + } + } + + //标记删除多条记录 + public void RemoveAt(int nIndex, + int nCount) + { + // 加写锁 + this.m_lock.AcquireWriterLock(m_nLockTimeout); + try + { + + if (nIndex < 0 || nIndex + nCount > m_count) + { + throw (new Exception("下标 " + Convert.ToString(nIndex) + " 越界(Count=" + Convert.ToString(m_count) + ")")); + } + + int nRet = 0; + if (m_streamSmall != null) // 有索引文件时 + { + // nRet = RemoveAtIndex(nIndex); + nRet = CompressRemoveAtIndex(nIndex, nCount); + } + else + { + throw (new Exception("暂时还没有编写")); + + } + + + if (nRet == -1) + { + throw (new Exception("RemoveAtAuto fail")); + } + + m_count -= nCount; + // bDirty = true; // 表示已经有标记删除的事项了 + + } + finally + { + this.m_lock.ReleaseWriterLock(); + } + } + + // 插入一个事项 + public virtual void Insert(int nIndex, + Item item) + { + // 加写锁 + this.m_lock.AcquireWriterLock(m_nLockTimeout); + try + { if (m_streamSmall == null && m_streamBig == null) throw (new Exception("内部文件尚未打开或者已经被关闭")); - // 若不存在索引文件 - if (m_streamSmall == null) - throw(new Exception("暂不支持无索引文件方式下的插入操作")); + // 若不存在索引文件 + if (m_streamSmall == null) + throw (new Exception("暂不支持无索引文件方式下的插入操作")); - // 将数据文件指针置于尾部 - m_streamBig.Seek(0, - SeekOrigin.End); + // 将数据文件指针置于尾部 + m_streamBig.Seek(0, + SeekOrigin.End); - // 若存在索引文件 - if (m_streamSmall != null) - { - // 插入一个新index条目 - long lStart = (long)nIndex * 8; - StreamUtil.Move(m_streamSmall, - lStart, - m_streamSmall.Length - lStart, - lStart + 8); + // 若存在索引文件 + if (m_streamSmall != null) + { + // 插入一个新index条目 + long lStart = (long)nIndex * 8; + StreamUtil.Move(m_streamSmall, + lStart, + m_streamSmall.Length - lStart, + lStart + 8); - m_streamSmall.Seek (lStart,SeekOrigin.Begin); - long nPosition = m_streamBig.Position; + m_streamSmall.Seek(lStart, SeekOrigin.Begin); + long nPosition = m_streamBig.Position; - byte[] bufferPosition = new byte[8]; + byte[] bufferPosition = new byte[8]; bufferPosition = System.BitConverter.GetBytes((long)nPosition); // 原来缺乏(long), 是一个bug. 2006/10/1 修改 Debug.Assert(bufferPosition.Length == 8, ""); - m_streamSmall.Write (bufferPosition,0,8); - } + m_streamSmall.Write(bufferPosition, 0, 8); + } - byte[] bufferLength = System.BitConverter.GetBytes((Int32)item.Length); + byte[] bufferLength = System.BitConverter.GetBytes((Int32)item.Length); Debug.Assert(bufferLength.Length == 4, ""); - m_streamBig.Write(bufferLength,0,4); - - item.WriteData(m_streamBig); + m_streamBig.Write(bufferLength, 0, 4); - m_count++; - - } - finally - { - this.m_lock.ReleaseWriterLock(); - } - } + item.WriteData(m_streamBig); + m_count++; - // 关闭。删除所有文件。 - public void Close() - { - // 加写锁 - this.m_lock.AcquireWriterLock(m_nLockTimeout); - try - { + } + finally + { + this.m_lock.ReleaseWriterLock(); + } + } - RemoveDataFile(); - RemoveIndexFile(); + // 关闭。删除所有文件。 + public void Close() + { + // 加写锁 + this.m_lock.AcquireWriterLock(m_nLockTimeout); + try + { + RemoveDataFile(); - } - finally - { - this.m_lock.ReleaseWriterLock(); - } - } + RemoveIndexFile(); + } + finally + { + this.m_lock.ReleaseWriterLock(); + } + } - // 将外部文件绑定到本对象 - public void Attach(string strFileName, - string strIndexFileName) - { - // 加写锁 - this.m_lock.AcquireWriterLock(m_nLockTimeout); - try - { + // 将外部文件绑定到本对象 + public void Attach(string strFileName, + string strIndexFileName) + { + // 加写锁 + this.m_lock.AcquireWriterLock(m_nLockTimeout); + try + { - RemoveIndexFile(); - RemoveDataFile(); // 清除当前正在使用的内部数据文件 + RemoveIndexFile(); + RemoveDataFile(); // 清除当前正在使用的内部数据文件 - m_strBigFileName = strFileName; - m_streamBig = File.Open (m_strBigFileName, - FileMode.Open, + m_strBigFileName = strFileName; + m_streamBig = File.Open(m_strBigFileName, + FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite); // 2007/12/26 - bool bCountSeted = false; - if (strIndexFileName != null) - { - if (File.Exists(strIndexFileName) == true) - { - this.m_strSmallFileName = strIndexFileName; - this.OpenIndexFile(); - } - else - { - this.CreateIndexFile(strIndexFileName); - } - - m_count = GetCountFromIndexFile(); - bCountSeted = true; - } - - if (bCountSeted == false) - m_count = GetCountFromDataFile(); - - } - finally - { - this.m_lock.ReleaseWriterLock(); - } - } + bool bCountSeted = false; + if (strIndexFileName != null) + { + if (File.Exists(strIndexFileName) == true) + { + this.m_strSmallFileName = strIndexFileName; + this.OpenIndexFile(); + } + else + { + this.CreateIndexFile(strIndexFileName); + } + + m_count = GetCountFromIndexFile(); + bCountSeted = true; + } + if (bCountSeted == false) + m_count = GetCountFromDataFile(); - // 将数据文件整序后输出 - void Resequence(string strOutputFileName) - { - this.m_streamSmall.Seek(0, SeekOrigin.Begin); + } + finally + { + this.m_lock.ReleaseWriterLock(); + } + } - for(;;) - { - } + // 将数据文件整序后输出 + void Resequence(string strOutputFileName) + { + this.m_streamSmall.Seek(0, SeekOrigin.Begin); - // return; - } + for (; ; ) + { + } - // 将数据文件和对象脱钩 - // parameters: - // bResequence 是否重新整序? - // return: - // 数据文件名 - public void Detach(out string strDataFileName, - out string strIndexFileName) - { - // 加写锁 - this.m_lock.AcquireWriterLock(m_nLockTimeout); - try - { + // return; + } - strDataFileName = m_strBigFileName; - CloseDataFile(); - m_strBigFileName = ""; // 避免析构函数去删除 + // 将数据文件和对象脱钩 + // parameters: + // bResequence 是否重新整序? + // return: + // 数据文件名 + public void Detach(out string strDataFileName, + out string strIndexFileName) + { + // 加写锁 + this.m_lock.AcquireWriterLock(m_nLockTimeout); + try + { - strIndexFileName = this.m_strSmallFileName; - CloseIndexFile(); + strDataFileName = m_strBigFileName; + CloseDataFile(); - this.m_strSmallFileName = ""; // 避免析构函数去删除 + m_strBigFileName = ""; // 避免析构函数去删除 - return; - } - finally - { - this.m_lock.ReleaseWriterLock(); - } - } + strIndexFileName = this.m_strSmallFileName; + CloseIndexFile(); - // 排序 - public void Sort() - { - // 加写锁 - this.m_lock.AcquireWriterLock(m_nLockTimeout); - try - { - if (this.m_strSmallFileName != "") - CreateIndexFile(this.m_strSmallFileName); - else - CreateIndexFile(null); - QuickSort(); - } - finally - { - this.m_lock.ReleaseWriterLock(); - } - } + this.m_strSmallFileName = ""; // 避免析构函数去删除 - // 确保创建了索引 - public void EnsureCreateIndex() - { - if (this.m_streamSmall == null) - { - this.CreateIndexFile(null); + return; } - else + finally + { + this.m_lock.ReleaseWriterLock(); + } + } + + // 排序 + public void Sort(Delegate_getTempFileName procGetTempFileName = null) + { + // 加写锁 + this.m_lock.AcquireWriterLock(m_nLockTimeout); + try + { + if (string.IsNullOrEmpty(this.m_strSmallFileName) == false) + CreateIndexFile(this.m_strSmallFileName, procGetTempFileName); + else + CreateIndexFile(null, procGetTempFileName); + QuickSort(); + } + finally + { + this.m_lock.ReleaseWriterLock(); + } + } + + // 确保创建了索引 + public void EnsureCreateIndex(Delegate_getTempFileName procGetTempFileName = null) + { + if (this.m_streamSmall == null) + { + this.CreateIndexFile(null, procGetTempFileName); + } + else { // Debug时可以校验一下index文件尺寸和Count的关系是否正确 } } - // 创建Index - // parameters: - // strIndexFileName 如果==null,表示自动分配临时文件 - public void CreateIndexFile(string strIndexFileName) - { - int nLength; + // 创建Index + // parameters: + // strIndexFileName 如果==null,表示自动分配临时文件 + public void CreateIndexFile(string strIndexFileName, + Delegate_getTempFileName procGetTempFileName = null) + { + int nLength; - RemoveIndexFile(); + RemoveIndexFile(); - if (strIndexFileName != null) - this.m_strSmallFileName = strIndexFileName; + if (strIndexFileName != null) + this.m_strSmallFileName = strIndexFileName; - OpenIndexFile(); + OpenIndexFile(procGetTempFileName); - m_streamBig.Seek(0, SeekOrigin.Begin); - m_streamSmall.Seek(0, SeekOrigin.End); + m_streamBig.Seek(0, SeekOrigin.Begin); + m_streamSmall.Seek(0, SeekOrigin.End); - int i=0; - long lPosition = 0; - for(i=0;;i++) - { - //长度字节数组 - byte[] bufferLength = new byte[4]; - int n = m_streamBig.Read(bufferLength,0,4); - if (n<4) //表示文件到尾 - break; + int i = 0; + long lPosition = 0; + for (i = 0; ; i++) + { + //长度字节数组 + byte[] bufferLength = new byte[4]; + int n = m_streamBig.Read(bufferLength, 0, 4); + if (n < 4) //表示文件到尾 + break; - nLength = System.BitConverter.ToInt32(bufferLength,0); - if (nLength<0) //删除项 - { - nLength = (int)GetRealValue(nLength); - goto CONTINUE; - } + nLength = System.BitConverter.ToInt32(bufferLength, 0); + if (nLength < 0) //删除项 + { + nLength = (int)GetRealValue(nLength); + goto CONTINUE; + } - byte[] bufferOffset = new byte[8]; - bufferOffset = System.BitConverter.GetBytes((long)lPosition); + byte[] bufferOffset = new byte[8]; + bufferOffset = System.BitConverter.GetBytes((long)lPosition); Debug.Assert(bufferOffset.Length == 8, ""); - m_streamSmall.Write (bufferOffset,0,8); + m_streamSmall.Write(bufferOffset, 0, 8); - CONTINUE: + CONTINUE: - m_streamBig.Seek (nLength,SeekOrigin.Current); - lPosition += (4+nLength); - } - } + m_streamBig.Seek(nLength, SeekOrigin.Current); + lPosition += (4 + nLength); + } + } - // 快速排序 - // 修改:建议增加delegate用来探测是否需要中断循环 - // 一般用户不要调用这个函数,调用Sort()即可 - // 如何显示排序进度? 头疼的事情。可否用堆栈深度表示进度? - // 需要辨别完全排序的部分中,item的数量,将这些部分从总item - // 数量中去除,就是进度指示的依据。 - // return: - // 0 succeed - // 1 interrupted - public int QuickSort() - { + // 快速排序 + // 修改:建议增加delegate用来探测是否需要中断循环 + // 一般用户不要调用这个函数,调用Sort()即可 + // 如何显示排序进度? 头疼的事情。可否用堆栈深度表示进度? + // 需要辨别完全排序的部分中,item的数量,将这些部分从总item + // 数量中去除,就是进度指示的依据。 + // return: + // 0 succeed + // 1 interrupted + public int QuickSort() + { if (this.m_streamSmall == null) { throw new Exception("调用QuickSort前,需要先创建索引"); } - ArrayList stack = new ArrayList (); // 堆栈 - int nStackTop = 0; - long nMaxRow = m_streamSmall.Length /8; //m_count; - long k = 0; - long j = 0; - long i = 0; - - if (nMaxRow == 0) - return 0; - - /* - if (nMaxRow >= 10) // 调试 - nMaxRow = 10; - */ - - Push(stack, 0, nMaxRow - 1, ref nStackTop); - while(nStackTop>0) - { - Pop(stack, ref k, ref j, ref nStackTop); - while(k= 10) // 调试 + nMaxRow = 10; + */ + + Push(stack, 0, nMaxRow - 1, ref nStackTop); + while (nStackTop > 0) + { + Pop(stack, ref k, ref j, ref nStackTop); + while (k < j) + { + Split(k, j, ref i); + Push(stack, i + 1, j, ref nStackTop); + j = i - 1; + } + } + + return 0; + } + + #region 基础函数 + + // 删除Index文件 + private void RemoveIndexFile() + { + // 如果流对象存在,关闭,置空 + if (m_streamSmall != null) + { + m_streamSmall.Close(); + m_streamSmall = null; + } if (this.ReadOnly == false) { @@ -806,18 +809,18 @@ private void RemoveIndexFile() } } - bDirty = false; - } + bDirty = false; + } - // 删除data文件 - private void RemoveDataFile() - { - // 如果流对象存在,关闭,置空 - if (m_streamBig != null) - { - m_streamBig.Close(); - m_streamBig = null; - } + // 删除data文件 + private void RemoveDataFile() + { + // 如果流对象存在,关闭,置空 + if (m_streamBig != null) + { + m_streamBig.Close(); + m_streamBig = null; + } if (this.ReadOnly == false) { @@ -828,551 +831,558 @@ private void RemoveDataFile() m_strBigFileName = ""; } } - } + } - public void CloseDataFile() - { - // 如果流对象存在,关闭,置空 - if (m_streamBig != null) - { - m_streamBig.Close(); - m_streamBig = null; - } - } + public void CloseDataFile() + { + // 如果流对象存在,关闭,置空 + if (m_streamBig != null) + { + m_streamBig.Close(); + m_streamBig = null; + } + } - // 是否具有打开的索引文件 - public bool HasIndexed - { - get - { - if (m_streamSmall == null) - return false; - return true; - } - } + // 是否具有打开的索引文件 + public bool HasIndexed + { + get + { + if (m_streamSmall == null) + return false; + return true; + } + } public virtual string GetTempFileName() { return Path.GetTempFileName(); } - // 打开Index文件 - private void OpenIndexFile() - { - if (m_streamSmall == null) - { - if (m_strSmallFileName == "") - m_strSmallFileName = this.GetTempFileName(); - // 创建index文件的时候,可以给出角色暗示,以便取有特色的物理文件名 - - m_streamSmall = File.Open(m_strSmallFileName, - FileMode.OpenOrCreate, + // 打开Index文件 + private void OpenIndexFile(Delegate_getTempFileName procGetTempFileName = null) + { + if (m_streamSmall == null) + { + + if (string.IsNullOrEmpty(m_strSmallFileName) == true) + { + // 2016/4/5 + // 优先使用临时的函数 创建临时文件 + if (procGetTempFileName != null) + m_strSmallFileName = procGetTempFileName(); + + if (string.IsNullOrEmpty(m_strSmallFileName) == true) + m_strSmallFileName = this.GetTempFileName(); + } + // 创建index文件的时候,可以给出角色暗示,以便取有特色的物理文件名 + + m_streamSmall = File.Open(m_strSmallFileName, + FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite); // 2007/12/26 + } - } + bDirty = false; + // m_streamSmall的非空就表明它处于Open状态 + } - bDirty = false; - // m_streamSmall的非空就表明它处于Open状态 - } + public void CloseIndexFile() + { + // 如果流对象存在,关闭,置空 + if (m_streamSmall != null) + { + m_streamSmall.Close(); + m_streamSmall = null; + } + } - public void CloseIndexFile() - { - // 如果流对象存在,关闭,置空 - if (m_streamSmall != null) - { - m_streamSmall.Close(); - m_streamSmall = null; - } - } + private Int64 GetCountFromDataFile() + { + Debug.Assert(m_streamBig != null, "data流必须先打开"); + m_streamBig.Seek(0, SeekOrigin.Begin); - private Int64 GetCountFromDataFile() - { - Debug.Assert(m_streamBig != null, "data流必须先打开"); - - m_streamBig.Seek(0, SeekOrigin.Begin); - - Int64 i=0; - Int32 nLength; - - while(true) - { - //长度字节数组 - byte[] bufferLength = new byte[4]; - int n = m_streamBig.Read(bufferLength,0,4); - if (n < 4) //表示文件到尾 - break; - - nLength = System.BitConverter.ToInt32(bufferLength,0); - if (nLength<0) //删除项 - { - nLength = (int)GetRealValue(nLength); - goto CONTINUE; - } - i++; - - CONTINUE: - m_streamBig.Seek(nLength, SeekOrigin.Current); - } - return i; - } + Int64 i = 0; + Int32 nLength; - // 从索引文件得到元素个数 - // 要求bDirty == false - private Int64 GetCountFromIndexFile() - { - Debug.Assert(m_streamSmall != null, "index流必须先打开"); - - return m_streamSmall.Length / 8; - - /* 适当时候增加遍历计算个数功能, 排除那些负数偏移值 - m_streamBig.Seek(0, SeekOrigin.Begin); - - Int64 i=0; - Int32 nLength; - - while(true) - { - //长度字节数组 - byte[] bufferLength = new byte[4]; - int n = m_streamBig.Read(bufferLength,0,4); - if (n < 4) //表示文件到尾 - break; - - nLength = System.BitConverter.ToInt32(bufferLength,0); - if (nLength<0) //删除项 - { - nLength = (int)GetRealValue(nLength); - goto CONTINUE; - } - i++; - - CONTINUE: - m_streamBig.Seek(nLength, SeekOrigin.Current); - } - return i; - */ - } + while (true) + { + //长度字节数组 + byte[] bufferLength = new byte[4]; + int n = m_streamBig.Read(bufferLength, 0, 4); + if (n < 4) //表示文件到尾 + break; - // 得到真正的位置或长度 - Int64 GetRealValue(Int64 lPositionOrLength) - { - if (lPositionOrLength<0) - { - lPositionOrLength = -lPositionOrLength; - lPositionOrLength--; - } - return lPositionOrLength; - } + nLength = System.BitConverter.ToInt32(bufferLength, 0); + if (nLength < 0) //删除项 + { + nLength = (int)GetRealValue(nLength); + goto CONTINUE; + } + i++; - // 得到删除标记使用的位置或长度 - // 负数表示被删除的事项 - Int64 GetDeletedValue(Int64 lPositionOrLength) - { - if (lPositionOrLength >= 0) - { - lPositionOrLength ++; - lPositionOrLength = -lPositionOrLength; - } + CONTINUE: + m_streamBig.Seek(nLength, SeekOrigin.Current); + } + return i; + } - return lPositionOrLength; - } + // 从索引文件得到元素个数 + // 要求bDirty == false + private Int64 GetCountFromIndexFile() + { + Debug.Assert(m_streamSmall != null, "index流必须先打开"); + return m_streamSmall.Length / 8; - // bContainDeleted 是否包含被删除的事项? - public Item GetItem(Int64 nIndex, - bool bContainDeleted) - { - Item item = null; - long lBigOffset; - - //自动返回大文件的编移量,小文件存在时,从小文件得到,不存在时,从大文件得到 - //bContainDeleted等于false,忽略已删除的记录,为true,不忽略 - //返回值 - //>=0:正常 - //-1:当bContainDeleted为false时:表示出错的情况,true时表示正常的负值 - lBigOffset = GetDataOffsetAuto(nIndex, bContainDeleted); - - //当bContainDeleted为false时即不包含已删除记录时,返回值-1,表示没找到 - if (bContainDeleted == false) - { - if (lBigOffset == -1) - return null; - } - item = GetItemByOffset(lBigOffset); - - return item; - } + /* 适当时候增加遍历计算个数功能, 排除那些负数偏移值 + m_streamBig.Seek(0, SeekOrigin.Begin); - // bContainDeleted 是否包含被删除的事项? - public Item GetCompareItem(Int64 nIndex, - bool bContainDeleted) - { - Item item = null; - long lBigOffset; - - //自动返回大文件的编移量,小文件存在时,从小文件得到,不存在时,从大文件得到 - //bContainDeleted等于false,忽略已删除的记录,为true,不忽略 - //返回值 - //>=0:正常 - //-1:当bContainDeleted为false时:表示出错的情况,true时表示正常的负值 - lBigOffset = GetDataOffsetAuto(nIndex, bContainDeleted); - - //当bContainDeleted为false时即不包含已删除记录时,返回值-1,表示没找到 - if (bContainDeleted == false) - { - if (lBigOffset == -1) - return null; - } - item = GetCompareItemByOffset(lBigOffset); - - return item; - } + Int64 i=0; + Int32 nLength; + while(true) + { + //长度字节数组 + byte[] bufferLength = new byte[4]; + int n = m_streamBig.Read(bufferLength,0,4); + if (n < 4) //表示文件到尾 + break; - // 自动返回事项在数据文件的编移量。所谓自动,意思是, 小文件存在时,从小文件查得到(快),不存在时,从大文件顺序得到(慢) - // parameters: - // bContainDeleted等于false,忽略已删除的记录,为true,不忽略 - // 返回值 - // >=0 正常 - // -1 当bContainDeleted为false时:表示出错的情况,true时表示正常的负值 - long GetDataOffsetAuto(long nIndex,bool bContainDeleted) - { - if (m_streamSmall != null) - { - return GetDataOffsetFromIndexFile(nIndex, bContainDeleted); - } - else - { - return GetDataOffsetFromDataFile(nIndex, bContainDeleted); - } - } + nLength = System.BitConverter.ToInt32(bufferLength,0); + if (nLength<0) //删除项 + { + nLength = (int)GetRealValue(nLength); + goto CONTINUE; + } + i++; - // 在数据文件中直接搜索事项的起点偏移量。 - // 当然,这样速度很慢 - // return: - // -1 当bContainDeleted为false时-1表示出错的情况,bContainDeleted为true时表示正常的负值 - long GetDataOffsetFromDataFile(long nIndex,bool bContainDeleted) - { - m_streamBig.Seek(0, SeekOrigin.Begin); - long lBigOffset = 0; - - int nLength; - int i = 0; - while(true) - { - //读4个字节,得到长度 - byte[] bufferLength = new byte[4]; - int n = m_streamBig.Read(bufferLength,0,4); - if (n<4) //表示文件到尾 - break; - nLength = System.BitConverter.ToInt32(bufferLength,0); - - if (bContainDeleted == false) - { - if (nLength<0) - { - //转换为实际的长度,再seek - long lTemp = GetRealValue(nLength); - m_streamBig.Seek (lTemp,SeekOrigin.Current); - - lBigOffset += (4+lTemp); - continue; - } - } - - if (i == nIndex) - { - return lBigOffset; - } - else - { - m_streamBig.Seek (nLength,SeekOrigin.Current); - } - - lBigOffset += (4+nLength); - - i++; - } - - return -1; - } + CONTINUE: + m_streamBig.Seek(nLength, SeekOrigin.Current); + } + return i; + */ + } - // 从索引文件中计算返回事项在数据文件中的偏移量 - // return: - // -1 当bContainDeleted为false时-1表示出错的情况,bContainDeleted为true时表示正常的负值 - long GetDataOffsetFromIndexFile( - long nIndex, - bool bContainDeleted) - { - if (m_streamSmall == null) - { - Debug.Assert(true, "索引文件流为null, GetDataOffsetFromIndexFile()函数无法执行"); - throw(new Exception ("索引文件流为null, GetDataOffsetFromIndexFile()函数无法执行")); - } - - // 干净,也就是索引中确保无删除项存在的情况下,可以用乘法运算得到位置,速度快 - if (bDirty == false) - { - if (nIndex*8>=m_streamSmall.Length || nIndex<0) - { - throw(new Exception("索引 " + Convert.ToString(nIndex) + "经计算超过索引文件当前最大范围")); - } - return GetIndexItemValue(nIndex); - } - else - { - long lBigOffset = 0; - - m_streamSmall.Seek(0, SeekOrigin.Begin); - int i = 0; - while(true) - { - //读8个字节,得到位置 - byte[] bufferBigOffset = new byte[8]; - int n = m_streamSmall.Read(bufferBigOffset,0,8); - if (n < 8) //表示文件到尾 - break; - lBigOffset = System.BitConverter.ToInt32(bufferBigOffset, 0); - - if (bContainDeleted == false) - { - //为负数时跳过 - if (lBigOffset<0) - { - continue; - } - } - //表示按序号找到 - if (i == nIndex) - { - return lBigOffset; - } - i++; - } - } - return -1; - } + // 得到真正的位置或长度 + Int64 GetRealValue(Int64 lPositionOrLength) + { + if (lPositionOrLength < 0) + { + lPositionOrLength = -lPositionOrLength; + lPositionOrLength--; + } + return lPositionOrLength; + } - // 用*8的方法算索引事项在索引文件的位置,取得其值 - // ,包含已删除的记录,并取出它所代表的数据事项在数据文件的编移量 - long GetIndexItemValue(long nIndex) - { - if( m_streamSmall == null) - { - throw(new Exception("m_streamSmall对象为空, GetIndexItemValue()无法进行")); - } - - if (nIndex*8 >= m_streamSmall.Length || nIndex<0) - { - throw(new Exception("索引 " + Convert.ToString(nIndex) + "经计算超过索引文件当前最大范围")); - } - - m_streamSmall.Seek(nIndex*8, - SeekOrigin.Begin); - - byte[] bufferOffset = new byte[8]; - int n = m_streamSmall.Read(bufferOffset, 0, 8); - if (n <= 0) - { - throw(new Exception("GetIndexItemValue()异常:实际流的长度"+Convert.ToString (m_streamSmall.Length )+"\r\n" - +"希望Seek到的位置"+Convert.ToString (nIndex*8)+"\r\n" - +"实际读的长度"+Convert.ToString (n))); - } - long lOffset = System.BitConverter.ToInt64(bufferOffset,0); - - return lOffset; - } + // 得到删除标记使用的位置或长度 + // 负数表示被删除的事项 + Int64 GetDeletedValue(Int64 lPositionOrLength) + { + if (lPositionOrLength >= 0) + { + lPositionOrLength++; + lPositionOrLength = -lPositionOrLength; + } - // lOffset不论正负数都可以找到记录,调用时,注意,如果不需要得到被删除的记录,自已做判断 - Item GetItemByOffset(long lOffset) - { - Item item = null; - - if (lOffset <0) - { - lOffset = GetRealValue(lOffset); - } - - if (lOffset >= m_streamBig.Length ) - { - throw(new Exception ("内部错误,位置大于总长度")); - //return null; - } - - m_streamBig.Seek(lOffset, SeekOrigin.Begin); - - //长度字节数组 - byte[] bufferLength = new byte[4]; - int n = m_streamBig.Read(bufferLength,0,4); - if (n<4) //表示文件到尾 - { - throw(new Exception ("内部错误:Read error")); - //return null; - } - - // 如果procNewItem已经挂接了delegate,则使用它来创建新Item或其派生类的对象 - // 这个方法的好处,是不用派生集合类ItemFileBase - if (this.procNewItem != null) - item = procNewItem(); - else // procNewItem为空,就使用this.NewItem()函数。基类中有缺省实现,就是返回Item类型对象 - item = this.NewItem(); // 这个方法的缺点,是要派生集合类ItemFileBase - - item.Length = System.BitConverter.ToInt32(bufferLength, 0); - item.ReadData(m_streamBig); - - return item; - } + return lPositionOrLength; + } - // lOffset不论正负数都可以找到记录,调用时,注意,如果不需要得到被删除的记录,自已做判断 - public Item GetCompareItemByOffset(long lOffset) - { - Item item = null; - - if (lOffset <0) - { - lOffset = GetRealValue(lOffset); - } - - if (lOffset >= m_streamBig.Length ) - { - throw(new Exception ("内部错误,位置大于总长度")); - //return null; - } - - m_streamBig.Seek(lOffset, SeekOrigin.Begin); - - //长度字节数组 - byte[] bufferLength = new byte[4]; - int n = m_streamBig.Read(bufferLength,0,4); - if (n<4) //表示文件到尾 - { - throw(new Exception ("内部错误:Read error")); - //return null; - } - - // 如果procNewItem已经挂接了delegate,则使用它来创建新Item或其派生类的对象 - // 这个方法的好处,是不用派生集合类ItemFileBase - if (this.procNewItem != null) - item = procNewItem(); - else // procNewItem为空,就使用this.NewItem()函数。基类中有缺省实现,就是返回Item类型对象 - item = this.NewItem(); // 这个方法的缺点,是要派生集合类ItemFileBase - - item.Length = System.BitConverter.ToInt32(bufferLength, 0); - item.ReadCompareData(m_streamBig); - - return item; - } + // bContainDeleted 是否包含被删除的事项? + public Item GetItem(Int64 nIndex, + bool bContainDeleted) + { + Item item = null; + long lBigOffset; + + //自动返回大文件的编移量,小文件存在时,从小文件得到,不存在时,从大文件得到 + //bContainDeleted等于false,忽略已删除的记录,为true,不忽略 + //返回值 + //>=0:正常 + //-1:当bContainDeleted为false时:表示出错的情况,true时表示正常的负值 + lBigOffset = GetDataOffsetAuto(nIndex, bContainDeleted); + + //当bContainDeleted为false时即不包含已删除记录时,返回值-1,表示没找到 + if (bContainDeleted == false) + { + if (lBigOffset == -1) + return null; + } + item = GetItemByOffset(lBigOffset); + + return item; + } + + // bContainDeleted 是否包含被删除的事项? + public Item GetCompareItem(Int64 nIndex, + bool bContainDeleted) + { + Item item = null; + long lBigOffset; + + //自动返回大文件的编移量,小文件存在时,从小文件得到,不存在时,从大文件得到 + //bContainDeleted等于false,忽略已删除的记录,为true,不忽略 + //返回值 + //>=0:正常 + //-1:当bContainDeleted为false时:表示出错的情况,true时表示正常的负值 + lBigOffset = GetDataOffsetAuto(nIndex, bContainDeleted); + + //当bContainDeleted为false时即不包含已删除记录时,返回值-1,表示没找到 + if (bContainDeleted == false) + { + if (lBigOffset == -1) + return null; + } + item = GetCompareItemByOffset(lBigOffset); + + return item; + } + + + // 自动返回事项在数据文件的编移量。所谓自动,意思是, 小文件存在时,从小文件查得到(快),不存在时,从大文件顺序得到(慢) + // parameters: + // bContainDeleted等于false,忽略已删除的记录,为true,不忽略 + // 返回值 + // >=0 正常 + // -1 当bContainDeleted为false时:表示出错的情况,true时表示正常的负值 + long GetDataOffsetAuto(long nIndex, bool bContainDeleted) + { + if (m_streamSmall != null) + { + return GetDataOffsetFromIndexFile(nIndex, bContainDeleted); + } + else + { + return GetDataOffsetFromDataFile(nIndex, bContainDeleted); + } + } + + // 在数据文件中直接搜索事项的起点偏移量。 + // 当然,这样速度很慢 + // return: + // -1 当bContainDeleted为false时-1表示出错的情况,bContainDeleted为true时表示正常的负值 + long GetDataOffsetFromDataFile(long nIndex, bool bContainDeleted) + { + m_streamBig.Seek(0, SeekOrigin.Begin); + long lBigOffset = 0; + + int nLength; + int i = 0; + while (true) + { + //读4个字节,得到长度 + byte[] bufferLength = new byte[4]; + int n = m_streamBig.Read(bufferLength, 0, 4); + if (n < 4) //表示文件到尾 + break; + nLength = System.BitConverter.ToInt32(bufferLength, 0); + + if (bContainDeleted == false) + { + if (nLength < 0) + { + //转换为实际的长度,再seek + long lTemp = GetRealValue(nLength); + m_streamBig.Seek(lTemp, SeekOrigin.Current); + + lBigOffset += (4 + lTemp); + continue; + } + } + + if (i == nIndex) + { + return lBigOffset; + } + else + { + m_streamBig.Seek(nLength, SeekOrigin.Current); + } + + lBigOffset += (4 + nLength); + + i++; + } + + return -1; + } + + // 从索引文件中计算返回事项在数据文件中的偏移量 + // return: + // -1 当bContainDeleted为false时-1表示出错的情况,bContainDeleted为true时表示正常的负值 + long GetDataOffsetFromIndexFile( + long nIndex, + bool bContainDeleted) + { + if (m_streamSmall == null) + { + Debug.Assert(true, "索引文件流为null, GetDataOffsetFromIndexFile()函数无法执行"); + throw (new Exception("索引文件流为null, GetDataOffsetFromIndexFile()函数无法执行")); + } + + // 干净,也就是索引中确保无删除项存在的情况下,可以用乘法运算得到位置,速度快 + if (bDirty == false) + { + if (nIndex * 8 >= m_streamSmall.Length || nIndex < 0) + { + throw (new Exception("索引 " + Convert.ToString(nIndex) + "经计算超过索引文件当前最大范围")); + } + return GetIndexItemValue(nIndex); + } + else + { + long lBigOffset = 0; + + m_streamSmall.Seek(0, SeekOrigin.Begin); + int i = 0; + while (true) + { + //读8个字节,得到位置 + byte[] bufferBigOffset = new byte[8]; + int n = m_streamSmall.Read(bufferBigOffset, 0, 8); + if (n < 8) //表示文件到尾 + break; + lBigOffset = System.BitConverter.ToInt32(bufferBigOffset, 0); + + if (bContainDeleted == false) + { + //为负数时跳过 + if (lBigOffset < 0) + { + continue; + } + } + //表示按序号找到 + if (i == nIndex) + { + return lBigOffset; + } + i++; + } + } + return -1; + } + + // 用*8的方法算索引事项在索引文件的位置,取得其值 + // ,包含已删除的记录,并取出它所代表的数据事项在数据文件的编移量 + long GetIndexItemValue(long nIndex) + { + if (m_streamSmall == null) + { + throw (new Exception("m_streamSmall对象为空, GetIndexItemValue()无法进行")); + } + + if (nIndex * 8 >= m_streamSmall.Length || nIndex < 0) + { + throw (new Exception("索引 " + Convert.ToString(nIndex) + "经计算超过索引文件当前最大范围")); + } + + m_streamSmall.Seek(nIndex * 8, + SeekOrigin.Begin); + + byte[] bufferOffset = new byte[8]; + int n = m_streamSmall.Read(bufferOffset, 0, 8); + if (n <= 0) + { + throw (new Exception("GetIndexItemValue()异常:实际流的长度" + Convert.ToString(m_streamSmall.Length) + "\r\n" + + "希望Seek到的位置" + Convert.ToString(nIndex * 8) + "\r\n" + + "实际读的长度" + Convert.ToString(n))); + } + long lOffset = System.BitConverter.ToInt64(bufferOffset, 0); + + return lOffset; + } + + // lOffset不论正负数都可以找到记录,调用时,注意,如果不需要得到被删除的记录,自已做判断 + Item GetItemByOffset(long lOffset) + { + Item item = null; + + if (lOffset < 0) + { + lOffset = GetRealValue(lOffset); + } + + if (lOffset >= m_streamBig.Length) + { + throw (new Exception("内部错误,位置大于总长度")); + //return null; + } + + m_streamBig.Seek(lOffset, SeekOrigin.Begin); + + //长度字节数组 + byte[] bufferLength = new byte[4]; + int n = m_streamBig.Read(bufferLength, 0, 4); + if (n < 4) //表示文件到尾 + { + throw (new Exception("内部错误:Read error")); + //return null; + } + + // 如果procNewItem已经挂接了delegate,则使用它来创建新Item或其派生类的对象 + // 这个方法的好处,是不用派生集合类ItemFileBase + if (this.procNewItem != null) + item = procNewItem(); + else // procNewItem为空,就使用this.NewItem()函数。基类中有缺省实现,就是返回Item类型对象 + item = this.NewItem(); // 这个方法的缺点,是要派生集合类ItemFileBase + + item.Length = System.BitConverter.ToInt32(bufferLength, 0); + item.ReadData(m_streamBig); + + return item; + } + + + // lOffset不论正负数都可以找到记录,调用时,注意,如果不需要得到被删除的记录,自已做判断 + public Item GetCompareItemByOffset(long lOffset) + { + Item item = null; + + if (lOffset < 0) + { + lOffset = GetRealValue(lOffset); + } + + if (lOffset >= m_streamBig.Length) + { + throw (new Exception("内部错误,位置大于总长度")); + //return null; + } + + m_streamBig.Seek(lOffset, SeekOrigin.Begin); + + //长度字节数组 + byte[] bufferLength = new byte[4]; + int n = m_streamBig.Read(bufferLength, 0, 4); + if (n < 4) //表示文件到尾 + { + throw (new Exception("内部错误:Read error")); + //return null; + } + + // 如果procNewItem已经挂接了delegate,则使用它来创建新Item或其派生类的对象 + // 这个方法的好处,是不用派生集合类ItemFileBase + if (this.procNewItem != null) + item = procNewItem(); + else // procNewItem为空,就使用this.NewItem()函数。基类中有缺省实现,就是返回Item类型对象 + item = this.NewItem(); // 这个方法的缺点,是要派生集合类ItemFileBase + + item.Length = System.BitConverter.ToInt32(bufferLength, 0); + item.ReadCompareData(m_streamBig); + + return item; + } + - /* - // 真正压缩标记删除了的那些事项 - private static int CompressIndex(Stream oStream) - { - if (oStream == null) - { - return -1; - } - - long lDeletedStart = 0; //删除块的起始位置 - long lDeletedEnd = 0; //删除块的结束位置 - long lDeletedLength = 0; - bool bDeleted = false; //是否已出现删除块 - - long lUseablePartLength = 0; //后面正常块的长度 - bool bUserablePart = false; //是否已出现正常块 - - bool bEnd = false; - long lValue = 0; - - oStream.Seek (0,SeekOrigin.Begin ); - while(true) - { - int nRet; - byte[] bufferValue = new byte[8]; - nRet = oStream.Read(bufferValue,0,8); - if (nRet != 8 && nRet != 0) - { - throw(new Exception ("内部错误:读到的长度不等于8")); - //break; - } - if (nRet == 0)//表示结束 - { - if(bUserablePart == false) - break; - - lValue = -1; - bEnd = true; - //break; - } - - if (bEnd != true) - { - lValue = BitConverter.ToInt64(bufferValue,0); - } - if (lValue<0) - { - if (bDeleted == true && bUserablePart == true) - { - lDeletedEnd = lDeletedStart + lDeletedLength; - //调MovePart(lDeletedStart,lDeletedEnd,lUseablePartLength) - - StreamUtil.Move(oStream, - lDeletedEnd, - lUseablePartLength, - lDeletedStart); - - //重新定位deleted的起始位置 - lDeletedStart = lUseablePartLength-lDeletedLength+lDeletedEnd; - lDeletedEnd = lDeletedStart+lDeletedLength; - - oStream.Seek (lDeletedEnd+lUseablePartLength,SeekOrigin.Begin); - - } - - bDeleted = true; - bUserablePart = false; - lDeletedLength += 8; //结束位置加8 - } - else if (lValue>=0) - { - //当出现过删除块时,又进入新的有用块时,前方的有用块不计,重新计算长度 - //| userable | ........ | userable | - //| ........ | userable | - if (bDeleted == true && bUserablePart == false) - { - lUseablePartLength = 0; - } - - bUserablePart = true; - lUseablePartLength += 8; + // 真正压缩标记删除了的那些事项 + private static int CompressIndex(Stream oStream) + { + if (oStream == null) + { + return -1; + } + + long lDeletedStart = 0; //删除块的起始位置 + long lDeletedEnd = 0; //删除块的结束位置 + long lDeletedLength = 0; + bool bDeleted = false; //是否已出现删除块 + + long lUseablePartLength = 0; //后面正常块的长度 + bool bUserablePart = false; //是否已出现正常块 + + bool bEnd = false; + long lValue = 0; + + oStream.Seek (0,SeekOrigin.Begin ); + while(true) + { + int nRet; + byte[] bufferValue = new byte[8]; + nRet = oStream.Read(bufferValue,0,8); + if (nRet != 8 && nRet != 0) + { + throw(new Exception ("内部错误:读到的长度不等于8")); + //break; + } + if (nRet == 0)//表示结束 + { + if(bUserablePart == false) + break; + + lValue = -1; + bEnd = true; + //break; + } + + if (bEnd != true) + { + lValue = BitConverter.ToInt64(bufferValue,0); + } + if (lValue<0) + { + if (bDeleted == true && bUserablePart == true) + { + lDeletedEnd = lDeletedStart + lDeletedLength; + //调MovePart(lDeletedStart,lDeletedEnd,lUseablePartLength) + + StreamUtil.Move(oStream, + lDeletedEnd, + lUseablePartLength, + lDeletedStart); + + //重新定位deleted的起始位置 + lDeletedStart = lUseablePartLength-lDeletedLength+lDeletedEnd; + lDeletedEnd = lDeletedStart+lDeletedLength; + + oStream.Seek (lDeletedEnd+lUseablePartLength,SeekOrigin.Begin); + + } + + bDeleted = true; + bUserablePart = false; + lDeletedLength += 8; //结束位置加8 + } + else if (lValue>=0) + { + //当出现过删除块时,又进入新的有用块时,前方的有用块不计,重新计算长度 + //| userable | ........ | userable | + //| ........ | userable | + if (bDeleted == true && bUserablePart == false) + { + lUseablePartLength = 0; + } + + bUserablePart = true; + lUseablePartLength += 8; - if (bDeleted == false) - { - lDeletedStart += 8; //当不存在删除块时,删除超始位置加8 - } - } - - if (bEnd == true) - { - break; - } - } - - //只剩尾部的被删除记录 - if (bDeleted == true && bUserablePart == false) - { - //lDeletedEnd = lDeletedStart + lDeletedLength; - oStream.SetLength(lDeletedStart); - } - - // bDirty = false; - return 0; - } + if (bDeleted == false) + { + lDeletedStart += 8; //当不存在删除块时,删除超始位置加8 + } + } + + if (bEnd == true) + { + break; + } + } + + //只剩尾部的被删除记录 + if (bDeleted == true && bUserablePart == false) + { + //lDeletedEnd = lDeletedStart + lDeletedLength; + oStream.SetLength(lDeletedStart); + } + + // bDirty = false; + return 0; + } */ @@ -1438,368 +1448,368 @@ private static int CompressIndex(Stream oStream) } - #endregion + #endregion - - #region 排序有关的基础函数 - void Push(ArrayList stack, - long lStart, - long lEnd, - ref int nStackTop) - { - if (nStackTop < 0) - { - throw(new Exception ("nStackTop不能小于0")); - } - if (lStart < 0) - { - throw(new Exception ("nStart不能小于0")); - } + #region 排序有关的基础函数 - if (nStackTop*2 != stack.Count ) - { - throw(new Exception ("nStackTop*2不等于stack.m_count")); - } + void Push(ArrayList stack, + long lStart, + long lEnd, + ref int nStackTop) + { + if (nStackTop < 0) + { + throw (new Exception("nStackTop不能小于0")); + } + if (lStart < 0) + { + throw (new Exception("nStart不能小于0")); + } + if (nStackTop * 2 != stack.Count) + { + throw (new Exception("nStackTop*2不等于stack.m_count")); + } - stack.Add (lStart); - stack.Add (lEnd); - nStackTop ++; - } + stack.Add(lStart); + stack.Add(lEnd); + nStackTop++; + } - void Pop(ArrayList stack, - ref long lStart, - ref long lEnd, - ref int nStackTop) - { - if (nStackTop <= 0) - { - throw(new Exception ("pop以前,nStackTop不能小于等于0")); - } - if (nStackTop*2 != stack.Count ) - { - throw(new Exception ("nStackTop*2不等于stack.m_count")); - } + void Pop(ArrayList stack, + ref long lStart, + ref long lEnd, + ref int nStackTop) + { + if (nStackTop <= 0) + { + throw (new Exception("pop以前,nStackTop不能小于等于0")); + } - lStart = (long)stack[(nStackTop-1) * 2]; - lEnd = (long)stack[(nStackTop-1) * 2+1]; + if (nStackTop * 2 != stack.Count) + { + throw (new Exception("nStackTop*2不等于stack.m_count")); + } - stack.RemoveRange((nStackTop-1) * 2,2); + lStart = (long)stack[(nStackTop - 1) * 2]; + lEnd = (long)stack[(nStackTop - 1) * 2 + 1]; - nStackTop --; - } + stack.RemoveRange((nStackTop - 1) * 2, 2); + nStackTop--; + } - void Split(long nStart, - long nEnd, - ref long nSplitPos) - { - // 取得中项 - long pStart = 0; - long pEnd = 0; - long pMiddle = 0; - long pSplit = 0; - long nMiddle; - long m,n,i,j,k; - long T = 0; - int nRet; - long nSplit; - - - nMiddle = (nStart + nEnd) / 2; - - pStart = GetIndexItemValue(nStart); - pEnd = GetIndexItemValue(nEnd); - - // 看起点和终点是否紧密相连 - if (nStart + 1 == nEnd) - { - nRet = Compare(pStart, pEnd); - if (nRet > 0) - { // 交换 - T = pStart; - SetRowPtr(nStart, pEnd); - SetRowPtr(nEnd, T); - } - nSplitPos = nStart; - return; - } - - - pMiddle = GetIndexItemValue(nMiddle); //GetRowPtr(nMiddle); - - nRet = Compare(pStart, pEnd); - if (nRet <= 0) - { - nRet = Compare(pStart, pMiddle); - if (nRet <= 0) - { - pSplit = pMiddle; - nSplit = nMiddle; - } - else - { - pSplit = pStart; - nSplit = nStart; - } - } - else - { - nRet = Compare(pEnd, pMiddle); - if (nRet <= 0) - { - pSplit = pMiddle; - nSplit = nMiddle; - } - else - { - pSplit = pEnd; - nSplit = nEnd; - } - - } - - // - k = nSplit; - m = nStart; - n = nEnd; - - T = GetIndexItemValue(k); - // (m)-->(k) - SetRowPtr(k, GetIndexItemValue(m)); - i = m; - j = n; - while(i!=j) - { - while(true) - { - nRet = Compare(GetIndexItemValue(j), T); - if (nRet >= 0 && i(i) - SetRowPtr(i, GetIndexItemValue(j) /*GetRowPtr(j)*/); - i = i + 1; - while(true) - { - nRet = Compare(/*GetRowPtr(i)*/ GetIndexItemValue(i), T); - if (nRet <=0 && i 0) + { // 交换 + T = pStart; + SetRowPtr(nStart, pEnd); + SetRowPtr(nEnd, T); + } + nSplitPos = nStart; + return; + } + + + pMiddle = GetIndexItemValue(nMiddle); //GetRowPtr(nMiddle); + + nRet = Compare(pStart, pEnd); + if (nRet <= 0) + { + nRet = Compare(pStart, pMiddle); + if (nRet <= 0) + { + pSplit = pMiddle; + nSplit = nMiddle; + } + else + { + pSplit = pStart; + nSplit = nStart; + } + } + else + { + nRet = Compare(pEnd, pMiddle); + if (nRet <= 0) + { + pSplit = pMiddle; + nSplit = nMiddle; + } + else + { + pSplit = pEnd; + nSplit = nEnd; + } + + } + + // + k = nSplit; + m = nStart; + n = nEnd; + + T = GetIndexItemValue(k); + // (m)-->(k) + SetRowPtr(k, GetIndexItemValue(m)); + i = m; + j = n; + while (i != j) + { + while (true) + { + nRet = Compare(GetIndexItemValue(j), T); + if (nRet >= 0 && i < j) + j = j - 1; + else + break; + } + if (i < j) + { + // (j)-->(i) + SetRowPtr(i, GetIndexItemValue(j) /*GetRowPtr(j)*/); + i = i + 1; + while (true) + { + nRet = Compare(/*GetRowPtr(i)*/ GetIndexItemValue(i), T); + if (nRet <= 0 && i < j) + i = i + 1; + else + break; + } + if (i < j) + { + // (i)--(j) + SetRowPtr(j, GetIndexItemValue(i) /*GetRowPtr(i)*/); + j = j - 1; + } + } + } + SetRowPtr(i, T); + nSplitPos = i; + } + + + public void SetRowPtr(long nIndex, long lPtr) + { + byte[] bufferOffset; + + //得到值 + bufferOffset = new byte[8]; + bufferOffset = BitConverter.GetBytes((long)lPtr); + - //覆盖值 - m_streamSmall.Seek (nIndex*8,SeekOrigin.Begin); + //覆盖值 + m_streamSmall.Seek(nIndex * 8, SeekOrigin.Begin); Debug.Assert(bufferOffset.Length == 8, ""); - m_streamSmall.Write (bufferOffset,0,8); + m_streamSmall.Write(bufferOffset, 0, 8); - } + } - // 本函数是内部使用。若要改变排序行为,可重载Item的CompareTo()函数 - public virtual int Compare(long lPtr1,long lPtr2) - { - if (lPtr1<0 && lPtr2<0) - return 0; - else if (lPtr1>=0 && lPtr2<0) - return 1; - else if (lPtr1<0 && lPtr2>=0) - return -1; + // 本函数是内部使用。若要改变排序行为,可重载Item的CompareTo()函数 + public virtual int Compare(long lPtr1, long lPtr2) + { + if (lPtr1 < 0 && lPtr2 < 0) + return 0; + else if (lPtr1 >= 0 && lPtr2 < 0) + return 1; + else if (lPtr1 < 0 && lPtr2 >= 0) + return -1; - Item item1 = GetCompareItemByOffset(lPtr1); - Item item2 = GetCompareItemByOffset(lPtr2); + Item item1 = GetCompareItemByOffset(lPtr1); + Item item2 = GetCompareItemByOffset(lPtr2); - return item1.CompareTo(item2); - } + return item1.CompareTo(item2); + } - #endregion + #endregion - #region 和删除有关的基础函数 + #region 和删除有关的基础函数 - // 自动选择从何处删除 - int RemoveAtAuto(int nIndex) - { - int nRet = -1; - if (m_streamSmall != null) // 有索引文件时 - { - // nRet = RemoveAtIndex(nIndex); - nRet = CompressRemoveAtIndex(nIndex, 1); - } - else // 索引文件不存在时, 从数据文件中删除 - { - nRet = RemoveAtData(nIndex); - } - return nRet; - } + // 自动选择从何处删除 + int RemoveAtAuto(int nIndex) + { + int nRet = -1; + if (m_streamSmall != null) // 有索引文件时 + { + // nRet = RemoveAtIndex(nIndex); + nRet = CompressRemoveAtIndex(nIndex, 1); + } + else // 索引文件不存在时, 从数据文件中删除 + { + nRet = RemoveAtData(nIndex); + } + return nRet; + } - // 在索引流中定位事项 - public long LocateIndexItem(int nIndex) - { - long lPositionS = 0; - if (bDirty == false) - { - lPositionS = nIndex*8; - if (lPositionS>=m_streamSmall.Length || nIndex<0) - { - throw(new Exception("下标越界...")); - } - - m_streamSmall.Seek(lPositionS, SeekOrigin.Begin); - return lPositionS; - } - else - { - m_streamSmall.Seek (0,SeekOrigin.Begin); - long lBigOffset; - int i = 0; - while(true) - { - //读8个字节,得到位置 - byte[] bufferBigOffset = new byte[8]; - int n = m_streamSmall.Read(bufferBigOffset,0,8); - if (n<8) //表示文件到尾 - break; - lBigOffset = System.BitConverter.ToInt64(bufferBigOffset,0); - - //为负数时跳过 - if (lBigOffset<0) - { - goto CONTINUE; - } - - //表示按序号找到 - if (i == nIndex) - { - m_streamSmall.Seek (lPositionS,SeekOrigin.Begin ); - return lPositionS; - } - i++; - - CONTINUE: - lPositionS += 8; - } - } - return -1; - } + // 在索引流中定位事项 + public long LocateIndexItem(int nIndex) + { + long lPositionS = 0; + if (bDirty == false) + { + lPositionS = nIndex * 8; + if (lPositionS >= m_streamSmall.Length || nIndex < 0) + { + throw (new Exception("下标越界...")); + } - // 从索引文件中标记删除一个事项 - public int MaskRemoveAtIndex(int nIndex) - { - int nRet; + m_streamSmall.Seek(lPositionS, SeekOrigin.Begin); + return lPositionS; + } + else + { + m_streamSmall.Seek(0, SeekOrigin.Begin); + long lBigOffset; + int i = 0; + while (true) + { + //读8个字节,得到位置 + byte[] bufferBigOffset = new byte[8]; + int n = m_streamSmall.Read(bufferBigOffset, 0, 8); + if (n < 8) //表示文件到尾 + break; + lBigOffset = System.BitConverter.ToInt64(bufferBigOffset, 0); + + //为负数时跳过 + if (lBigOffset < 0) + { + goto CONTINUE; + } + + //表示按序号找到 + if (i == nIndex) + { + m_streamSmall.Seek(lPositionS, SeekOrigin.Begin); + return lPositionS; + } + i++; + + CONTINUE: + lPositionS += 8; + } + } + return -1; + } + + // 从索引文件中标记删除一个事项 + public int MaskRemoveAtIndex(int nIndex) + { + int nRet; - // lBigOffset表示大文件的编移量,-1表示错误 - long lBigOffset = GetDataOffsetFromIndexFile(nIndex,false); - if (lBigOffset == -1) - return -1; + // lBigOffset表示大文件的编移量,-1表示错误 + long lBigOffset = GetDataOffsetFromIndexFile(nIndex, false); + if (lBigOffset == -1) + return -1; - lBigOffset = GetDeletedValue(lBigOffset); + lBigOffset = GetDeletedValue(lBigOffset); - byte[] bufferBigOffset = new byte[8]; - bufferBigOffset = BitConverter.GetBytes((long)lBigOffset); + byte[] bufferBigOffset = new byte[8]; + bufferBigOffset = BitConverter.GetBytes((long)lBigOffset); - nRet = (int)LocateIndexItem(nIndex); - if (nRet == -1) - return -1; + nRet = (int)LocateIndexItem(nIndex); + if (nRet == -1) + return -1; Debug.Assert(bufferBigOffset.Length == 8, ""); - m_streamSmall.Write(bufferBigOffset,0,8); + m_streamSmall.Write(bufferBigOffset, 0, 8); - return 0; - } + return 0; + } - // 从索引文件中挤压式删除一个事项 - public int CompressRemoveAtIndex(int nIndex, - int nCount) - { - if (m_streamSmall == null) - throw new Exception("索引文件尚未初始化"); + // 从索引文件中挤压式删除一个事项 + public int CompressRemoveAtIndex(int nIndex, + int nCount) + { + if (m_streamSmall == null) + throw new Exception("索引文件尚未初始化"); - long lStart = (long)nIndex * 8; - StreamUtil.Move(m_streamSmall, - lStart + 8*nCount, - m_streamSmall.Length - lStart - 8*nCount, - lStart); + long lStart = (long)nIndex * 8; + StreamUtil.Move(m_streamSmall, + lStart + 8 * nCount, + m_streamSmall.Length - lStart - 8 * nCount, + lStart); - m_streamSmall.SetLength(m_streamSmall.Length - 8*nCount); + m_streamSmall.SetLength(m_streamSmall.Length - 8 * nCount); - return 0; - } + return 0; + } - //从大文件中删除 - public int RemoveAtData(int nIndex) - { - //得到大文件偏移量 - long lBigOffset = GetDataOffsetFromDataFile(nIndex, false); - if (lBigOffset == -1) - return -1; - - if (lBigOffset >= m_streamBig.Length ) - { - throw(new Exception ("内部错误,位置大于总长度")); - //return null; - } - - m_streamBig.Seek(lBigOffset,SeekOrigin.Begin); - //长度字节数组 - byte[] bufferLength = new byte[4]; - int n = m_streamBig.Read(bufferLength,0,4); - if (n<4) //表示文件到尾 - { - throw(new Exception ("内部错误:Read error")); - //return null; - } - - int nLength = System.BitConverter.ToInt32(bufferLength,0); - nLength = (int)GetDeletedValue(nLength); - - bufferLength = BitConverter.GetBytes((Int32)nLength); - m_streamBig.Seek (-4,SeekOrigin.Current); + //从大文件中删除 + public int RemoveAtData(int nIndex) + { + //得到大文件偏移量 + long lBigOffset = GetDataOffsetFromDataFile(nIndex, false); + if (lBigOffset == -1) + return -1; + + if (lBigOffset >= m_streamBig.Length) + { + throw (new Exception("内部错误,位置大于总长度")); + //return null; + } + + m_streamBig.Seek(lBigOffset, SeekOrigin.Begin); + //长度字节数组 + byte[] bufferLength = new byte[4]; + int n = m_streamBig.Read(bufferLength, 0, 4); + if (n < 4) //表示文件到尾 + { + throw (new Exception("内部错误:Read error")); + //return null; + } + + int nLength = System.BitConverter.ToInt32(bufferLength, 0); + nLength = (int)GetDeletedValue(nLength); + + bufferLength = BitConverter.GetBytes((Int32)nLength); + m_streamBig.Seek(-4, SeekOrigin.Current); Debug.Assert(bufferLength.Length == 4); - m_streamBig.Write (bufferLength,0,4); + m_streamBig.Write(bufferLength, 0, 4); - return 0; - } + return 0; + } - #endregion + #endregion - IEnumerator IEnumerable.GetEnumerator() - { - return new ItemFileBaseEnumerator(this); - } + IEnumerator IEnumerable.GetEnumerator() + { + return new ItemFileBaseEnumerator(this); + } - } + } } diff --git a/DigitalPlatform.LibraryServer/AppBiblio.cs b/DigitalPlatform.LibraryServer/AppBiblio.cs index afb4e8a30..9b695a067 100644 --- a/DigitalPlatform.LibraryServer/AppBiblio.cs +++ b/DigitalPlatform.LibraryServer/AppBiblio.cs @@ -3782,7 +3782,7 @@ public LibraryServerResult SetBiblioInfo( && StringUtil.IsInList("order", sessioninfo.RightsOrigin) == false) { result.Value = -1; - result.ErrorInfo = "设置书目信息被拒绝。不具备order或setbiblioinfo权限。"; + result.ErrorInfo = "设置书目信息被拒绝。不具备 order 或 setbiblioinfo 权限。"; result.ErrorCode = ErrorCode.AccessDenied; return result; } diff --git a/DigitalPlatform.LibraryServer/AppDup.cs b/DigitalPlatform.LibraryServer/AppDup.cs index 73e24ac69..c63acd411 100644 --- a/DigitalPlatform.LibraryServer/AppDup.cs +++ b/DigitalPlatform.LibraryServer/AppDup.cs @@ -9,6 +9,7 @@ using DigitalPlatform.Text; using DigitalPlatform.Xml; using DigitalPlatform.rms.Client; +using System.IO; // using DigitalPlatform.rms.Client.rmsws_localhost; // Record @@ -56,7 +57,7 @@ public LibraryServerResult GetDupSearchResult( goto ERROR1; } - dupset.EnsureCreateIndex(); + dupset.EnsureCreateIndex(getTempFileName); int nCount = (int)lCount; int nStart = (int)lStart; @@ -82,7 +83,6 @@ public LibraryServerResult GetDupSearchResult( bool bCols = (StringUtil.IsInList("cols", strBrowseInfoStyle) == true); - List pathlist = new List(); List results = new List(); @@ -151,7 +151,6 @@ public LibraryServerResult GetDupSearchResult( result.ErrorCode = ErrorCode.SystemError; result.ErrorInfo = strError; return result; - } // 列出查重方案信息 @@ -296,9 +295,9 @@ public LibraryServerResult SearchDup( List aKeyLine = null; // 模拟创建检索点,以获得检索点列表 - // return: - // -1 error - // 0 succeed + // return: + // -1 error + // 0 succeed nRet = GetKeys( // sessioninfo.Channels, channel, @@ -310,104 +309,151 @@ public LibraryServerResult SearchDup( goto ERROR1; DupResultSet onedatabase_set = null; // 一个库的结果集 - - - XmlNodeList accesspoints = nodeDatabase.SelectNodes("accessPoint"); - // 循环 - for (int j = 0; j < accesspoints.Count; j++) + try { - XmlNode accesspoint = accesspoints[j]; - - string strFrom = DomUtil.GetAttr(accesspoint, "name"); - - // 获得from所对应的key - List keys = GetKeyByFrom(aKeyLine, - strFrom); - if (keys.Count == 0) - continue; - - string strWeight = DomUtil.GetAttr(accesspoint, "weight"); - string strSearchStyle = DomUtil.GetAttr(accesspoint, "searchStyle"); - - int nWeight = 0; - try + XmlNodeList accesspoints = nodeDatabase.SelectNodes("accessPoint"); + // 循环 + for (int j = 0; j < accesspoints.Count; j++) { - nWeight = Convert.ToInt32(strWeight); - } - catch - { - // 警告定义问题? - } + XmlNode accesspoint = accesspoints[j]; - for (int k = 0; k < keys.Count; k++) - { - string strKey = (string)keys[k]; - if (strKey == "") + string strFrom = DomUtil.GetAttr(accesspoint, "name"); + + // 获得from所对应的key + List keys = GetKeyByFrom(aKeyLine, + strFrom); + if (keys.Count == 0) continue; - DupResultSet dupset = null; - - // 针对一个from进行检索 - // return: - // -1 error - // 0 not found - // 1 found - nRet = SearchOneFrom( - // sessioninfo.Channels, - channel, - strDatabaseName, - strFrom, - strKey, - strSearchStyle, - nWeight, - nThreshold, - 5000, // ??? - (bIncludeOriginRecord == false) ? strOriginBiblioRecPath : null, - out dupset, - out strError); + string strWeight = DomUtil.GetAttr(accesspoint, "weight"); + string strSearchStyle = DomUtil.GetAttr(accesspoint, "searchStyle"); - if (nRet == -1) + int nWeight = 0; + try { - // ??? 警告检索错误? - continue; + nWeight = Convert.ToInt32(strWeight); } - - if (onedatabase_set == null) + catch { - onedatabase_set = dupset; - continue; + // 警告定义问题? } - if (nRet == 0) - continue; + for (int k = 0; k < keys.Count; k++) + { + string strKey = (string)keys[k]; + if (strKey == "") + continue; + + DupResultSet dupset = null; + try + { + // 针对一个from进行检索 + // return: + // -1 error + // 0 not found + // 1 found + nRet = SearchOneFrom( + // sessioninfo.Channels, + channel, + strDatabaseName, + strFrom, + strKey, + strSearchStyle, + nWeight, + nThreshold, + 5000, // ??? + (bIncludeOriginRecord == false) ? strOriginBiblioRecPath : null, + out dupset, + out strError); + + if (nRet == -1) + { + // ??? 警告检索错误? + continue; + } + + if (onedatabase_set == null) + { + onedatabase_set = dupset; + dupset = null; // 避免出 try 范围时被释放。因为内容已经转移给 onedatabase_set 了 + continue; + } + + if (nRet == 0) + continue; + + Debug.Assert(dupset != null, ""); + + onedatabase_set.EnsureCreateIndex(getTempFileName); + dupset.EnsureCreateIndex(getTempFileName); + + // 将dupset和前一个set归并 + // 归并可以参考ResultSet中的Merge算法 + DupResultSet tempset = new DupResultSet(); + tempset.Open(false, getTempFileName); + // 功能: 合并两个数组 + // parameters: + // strStyle 运算风格 OR , AND , SUB + // sourceLeft 源左边结果集 + // sourceRight 源右边结果集 + // targetLeft 目标左边结果集 + // targetMiddle 目标中间结果集 + // targetRight 目标右边结果集 + // bOutputDebugInfo 是否输出处理信息 + // strDebugInfo 处理信息 + // return + // -1 出错 + // 0 成功 + nRet = DupResultSet.Merge("OR", + onedatabase_set, + dupset, + null, // targetLeft, + tempset, + null, // targetRight, + false, + out strDebugInfo, + out strError); + if (nRet == -1) + goto ERROR1; + + { + if (onedatabase_set != null) + onedatabase_set.Dispose(); + onedatabase_set = tempset; + } + + } + finally + { + if (dupset != null) + dupset.Dispose(); + } + } // end of k loop + + } // end of j loop + + + if (alldatabase_set == null) + { + alldatabase_set = onedatabase_set; + onedatabase_set = null; // 避免出 try 范围时被释放。因为内容已经转移给 alldatabase_set 了 + continue; + } + + // 合并 + if (onedatabase_set != null) + { + DupResultSet tempset0 = new DupResultSet(); + tempset0.Open(false, getTempFileName); + + alldatabase_set.EnsureCreateIndex(getTempFileName); + onedatabase_set.EnsureCreateIndex(getTempFileName); - Debug.Assert(dupset != null, ""); - - onedatabase_set.EnsureCreateIndex(); - dupset.EnsureCreateIndex(); - - // 将dupset和前一个set归并 - // 归并可以参考ResultSet中的Merge算法 - DupResultSet tempset = new DupResultSet(); - tempset.Open(false); - // 功能: 合并两个数组 - // parameters: - // strStyle 运算风格 OR , AND , SUB - // sourceLeft 源左边结果集 - // sourceRight 源右边结果集 - // targetLeft 目标左边结果集 - // targetMiddle 目标中间结果集 - // targetRight 目标右边结果集 - // bOutputDebugInfo 是否输出处理信息 - // strDebugInfo 处理信息 - // return - // -1 出错 - // 0 成功 nRet = DupResultSet.Merge("OR", + alldatabase_set, onedatabase_set, - dupset, null, // targetLeft, - tempset, + tempset0, null, // targetRight, false, out strDebugInfo, @@ -415,43 +461,18 @@ public LibraryServerResult SearchDup( if (nRet == -1) goto ERROR1; - onedatabase_set = tempset; - - } // end of k loop - - } // end of j loop - + { + if (alldatabase_set != null) + alldatabase_set.Dispose(); - if (alldatabase_set == null) - { - alldatabase_set = onedatabase_set; - continue; + alldatabase_set = tempset0; + } + } } - - // 合并 - if (onedatabase_set != null) + finally { - DupResultSet tempset0 = new DupResultSet(); - tempset0.Open(false); - - - alldatabase_set.EnsureCreateIndex(); - onedatabase_set.EnsureCreateIndex(); - - - nRet = DupResultSet.Merge("OR", - alldatabase_set, - onedatabase_set, - null, // targetLeft, - tempset0, - null, // targetRight, - false, - out strDebugInfo, - out strError); - if (nRet == -1) - goto ERROR1; - - alldatabase_set = tempset0; + if (onedatabase_set != null) + onedatabase_set.Dispose(); } } @@ -459,11 +480,14 @@ public LibraryServerResult SearchDup( if (alldatabase_set != null) { alldatabase_set.SortStyle = DupResultSetSortStyle.OverThreshold; - alldatabase_set.Sort(); + alldatabase_set.Sort(getTempFileName); } - - sessioninfo1.DupResultSet = alldatabase_set; + { + if (sessioninfo1.DupResultSet != null) + sessioninfo1.DupResultSet.Dispose(); + sessioninfo1.DupResultSet = alldatabase_set; + } if (alldatabase_set != null) result.Value = alldatabase_set.Count; @@ -477,6 +501,12 @@ public LibraryServerResult SearchDup( return result; } + string getTempFileName() + { + Debug.Assert(string.IsNullOrEmpty(this.TempDir) == false, ""); + return Path.Combine(this.TempDir, "~dup_" + Guid.NewGuid().ToString()); + } + // 针对一个from进行检索 // parameters: // strExcludeBiblioRecPath 要排除掉的记录路径 @@ -540,14 +570,13 @@ int SearchOneFrom( List aPath = null; dupset = new DupResultSet(); - dupset.Open(false); + dupset.Open(false, getTempFileName); // 获得结果集,对逐个记录进行处理 for (; ; ) { // TODO: 中间要可以中断 - lRet = channel.DoGetSearchResult( "dup", // strResultSetName lStart, @@ -592,7 +621,6 @@ int SearchOneFrom( return -1; } - // 从模拟keys中根据from获得对应的key static List GetKeyByFrom(List aKeyLine, string strFromName) @@ -668,10 +696,10 @@ int GetDupProjectNode(string strProjectName, return -1; } - node = root.SelectSingleNode("project[@name='"+strProjectName+"']"); + node = root.SelectSingleNode("project[@name='" + strProjectName + "']"); if (node == null) { - strError = "查重方案 '" +strProjectName+ "' 的定义不存在"; + strError = "查重方案 '" + strProjectName + "' 的定义不存在"; return 0; } diff --git a/DigitalPlatform.LibraryServer/AppEntity.cs b/DigitalPlatform.LibraryServer/AppEntity.cs index b8d2b7e07..59a404db4 100644 --- a/DigitalPlatform.LibraryServer/AppEntity.cs +++ b/DigitalPlatform.LibraryServer/AppEntity.cs @@ -3015,6 +3015,7 @@ int CheckItemLibraryCode(XmlDocument dom, return CheckItemLibraryCode(dom, strLibraryCodeList, out strLibraryCode, out strError); } + // TODO: location 海淀分馆/阅览室 应该属于 libraryCodeList 海淀分馆/* // 检查一个册记录的馆藏地点是否符合馆代码列表要求 // parameters: // strLibraryCodeList 当前用户管辖的馆代码列表 @@ -3055,21 +3056,22 @@ public int CheckItemLibraryCode(XmlDocument dom, #endif strLocation = StringUtil.GetPureLocationString(strLocation); + string strPureName = ""; + + // 将馆藏地点字符串分解为 馆代码+地点名 两个部分 + ParseCalendarName(strLocation, + out strLibraryCode, + out strPureName); + // 先试探一下,馆藏地点字符串是否和 strLibraryCodeList 完全一致。 // 这种检测主要是为了处理 strLibraryCodeList 传来 "西城分馆/集贤斋" 这样的个人书斋全路径的情况 if (strLocation == strLibraryCodeList) { + // TODO: 2016/4/3 适当时候需要让 strLibrayCode = strLocation,以表示尽量精确的(读者所在馆代码)身份 // 在管辖范围内 return 0; } - string strPureName = ""; - - // 将馆藏地点字符串分解为 馆代码+地点名 两个部分 - ParseCalendarName(strLocation, - out strLibraryCode, - out strPureName); - // 即便是全局用户,也要到得到馆代码后函数才能返回 if (SessionInfo.IsGlobalUser(strLibraryCodeList) == true) return 0; @@ -3845,6 +3847,7 @@ int DoEntityOperChange( } } + // *** 检查旧记录的馆藏地点 // 检查一个册记录的馆藏地点是否符合馆代码列表要求 // return: // -1 检查过程出错 @@ -4093,7 +4096,6 @@ int DoEntityOperChange( // exist_timestamp此时已经反映了库中被修改后的记录的时间戳 } - // 合并新旧记录 string strNewXml = ""; if (bForce == false) @@ -4127,18 +4129,31 @@ int DoEntityOperChange( } string strTargetLibraryCode = ""; - // 检查一个册记录的馆藏地点是否符合馆代码列表要求 - // return: - // -1 检查过程出错 - // 0 符合要求 - // 1 不符合要求 - nRet = CheckItemLibraryCode(strNewXml, - sessioninfo, - // sessioninfo.LibraryCodeList, - out strTargetLibraryCode, - out strError); - if (nRet == -1) - goto ERROR1; + { + // 检查一个册记录的馆藏地点是否符合馆代码列表要求 + // return: + // -1 检查过程出错 + // 0 符合要求 + // 1 不符合要求 + nRet = CheckItemLibraryCode(strNewXml, + sessioninfo, + // sessioninfo.LibraryCodeList, + out strTargetLibraryCode, + out strError); + if (nRet == -1) + goto ERROR1; + + // 检查新记录是否属于管辖范围 + if (sessioninfo.GlobalUser == false + || sessioninfo.UserType == "reader") + { + if (nRet != 0) + { + strError = "册记录新内容中的馆藏地点不符合要求: " + strError; + goto ERROR1; + } + } + } // 2014/7/3 if (this.VerifyBookType == true) @@ -4166,17 +4181,6 @@ int DoEntityOperChange( goto ERROR1; } - // 检查新记录是否属于管辖范围 - if (sessioninfo.GlobalUser == false - || sessioninfo.UserType == "reader") - { - if (nRet != 0) - { - strError = "册记录新内容中的馆藏地点不符合要求: " + strError; - goto ERROR1; - } - } - // 保存新记录 byte[] output_timestamp = null; lRet = channel.DoSaveTextRes(info.NewRecPath, diff --git a/DigitalPlatform.LibraryServer/AppReader.cs b/DigitalPlatform.LibraryServer/AppReader.cs index c43989c77..c691c29cd 100644 --- a/DigitalPlatform.LibraryServer/AppReader.cs +++ b/DigitalPlatform.LibraryServer/AppReader.cs @@ -863,25 +863,6 @@ public LibraryServerResult SetReaderInfo( } } - if (strAction == "new" - || strAction == "change" - || strAction == "changereaderbarcode" - || strAction == "move") - { - nRet = this.DoVerifyReaderFunction( - sessioninfo, - strAction, - domNewRec, - out strError); - if (nRet != 0) - { - result.Value = -1; - result.ErrorInfo = strError; - result.ErrorCode = ErrorCode.SystemError; - return result; - } - } - // 对读者证条码号查重,如果必要,并获得strRecPath if ( // bBarcodeChanged == true && (strAction == "new" @@ -892,7 +873,7 @@ public LibraryServerResult SetReaderInfo( && String.IsNullOrEmpty(strNewBarcode) == false ) { - +#if NO // 验证条码号 if (this.VerifyBarcode == true) { @@ -932,6 +913,7 @@ public LibraryServerResult SetReaderInfo( return result; } } +#endif List aPath = null; @@ -1008,6 +990,35 @@ public LibraryServerResult SetReaderInfo( } } + if (strAction == "new" +|| strAction == "change" +|| strAction == "changereaderbarcode" +|| strAction == "move") + { + // 注:要在 strRecPath 决定后再进行此调用 + // return: + // -3 条码号错误 + // -2 not found script + // -1 出错 + // 0 成功 + nRet = this.DoVerifyReaderFunction( + sessioninfo, + strAction, + strRecPath, + domNewRec, + out strError); + if (nRet != 0) + { + result.Value = -1; + result.ErrorInfo = strError + "。保存操作失败"; + if (nRet == -1) + result.ErrorCode = ErrorCode.InvalidReaderBarcode; + else + result.ErrorCode = ErrorCode.SystemError; + return result; + } + } + // 对显示名检查和查重 if (bDisplayNameChanged == true && (strAction == "new" diff --git a/DigitalPlatform.LibraryServer/AppScript.cs b/DigitalPlatform.LibraryServer/AppScript.cs index c3b0bf06a..8259cb636 100644 --- a/DigitalPlatform.LibraryServer/AppScript.cs +++ b/DigitalPlatform.LibraryServer/AppScript.cs @@ -21,6 +21,7 @@ using DigitalPlatform.Script; using DigitalPlatform.Interfaces; using System.Web; +using DigitalPlatform.rms.Client; namespace DigitalPlatform.LibraryServer { @@ -1250,12 +1251,14 @@ public int DoVerifyItemFunction( // 执行脚本函数 VerifyReader // parameters: // return: + // -3 条码号错误 // -2 not found script // -1 出错 // 0 成功 public int DoVerifyReaderFunction( SessionInfo sessioninfo, string strAction, + string strRecPath, XmlDocument itemdom, out string strError) { @@ -1301,6 +1304,7 @@ public int DoVerifyReaderFunction( return host.VerifyReader( sessioninfo, strAction, + strRecPath, itemdom, out strError); } @@ -1335,17 +1339,56 @@ public LibraryHost() } // return: + // -3 条码号错误 // -1 调用出错 // 0 校验正确 // 1 校验发现错误 public virtual int VerifyReader( SessionInfo sessioninfo, string strAction, + string strRecPath, XmlDocument readerdom, out string strError) { strError = ""; - // int nRet = 0; + int nRet = 0; + + string strNewBarcode = DomUtil.GetElementText(readerdom.DocumentElement, "barcode"); + + if (strAction == "new" +|| strAction == "change" +|| strAction == "changereaderbarcode" +|| strAction == "move") + { + if (string.IsNullOrEmpty(strNewBarcode) == false) + { + string strDbName = ResPath.GetDbName(strRecPath); + if (string.IsNullOrEmpty(strDbName) == true) + { + strError = "从读者库记录路径 '"+strRecPath+"' 获得数据库名时出错。验证读者记录失败"; + return -1; + } + + string strLibraryCode = ""; + if (this.App.IsReaderDbName(strDbName, out strLibraryCode) == false) + { + strError = "数据库名 '" + strDbName + "' 不是读者库。验证读者记录失败"; + return -1; + } + + // return: + // -1 调用出错 + // 0 校验正确 + // 1 校验发现错误 + nRet = VerifyPatronBarcode(strLibraryCode, strNewBarcode, out strError); + if (nRet != 0) + { + if (nRet == 1) + return -3; + return nRet; + } + } + } string strPersonalLibrary = DomUtil.GetElementText(readerdom.DocumentElement, "personalLibrary"); @@ -1381,6 +1424,62 @@ public virtual int VerifyReader( return 0; } + // 2016/4/3 + // 按照缺省行为,验证读者记录中的证条码号 + // return: + // -1 调用出错 + // 0 校验正确 + // 1 校验发现错误 + public int VerifyPatronBarcode( + string strLibraryCode, + string strNewBarcode, + out string strError) + { + strError = ""; + // 验证条码号 + if (this.App.VerifyBarcode == true) + { + // return: + // 0 invalid barcode + // 1 is valid reader barcode + // 2 is valid item barcode + int nResultValue = 0; + + // return: + // -2 not found script + // -1 出错 + // 0 成功 + int nRet = this.App.DoVerifyBarcodeScriptFunction( + this, + strLibraryCode, + strNewBarcode, + out nResultValue, + out strError); + if (nRet == -2 || nRet == -1 || nResultValue != 1) + { + if (nRet == -2) + { + strError = "library.xml 中没有配置条码号验证函数,无法进行条码号验证"; + return -1; + } + else if (nRet == -1) + { + strError = "验证册条码号的过程中出错" + + (string.IsNullOrEmpty(strError) == true ? "" : ": " + strError); + return -1; + } + else if (nResultValue != 1) + { + strError = "条码号 '" + strNewBarcode + "' 经验证发现不是一个合法的证条码号" + + (string.IsNullOrEmpty(strError) == true ? "" : "(" + strError + ")"); + } + + return 1; + } + } + return 0; + } + // strLeft 包含的权限是否小于等于 strRight static bool IsLessOrEqualThan(string strLeft, string strRight, diff --git a/DigitalPlatform.LibraryServer/DupResultSet.cs b/DigitalPlatform.LibraryServer/DupResultSet.cs index c310a14d7..07a9d65f9 100644 --- a/DigitalPlatform.LibraryServer/DupResultSet.cs +++ b/DigitalPlatform.LibraryServer/DupResultSet.cs @@ -63,7 +63,7 @@ public override void BuildBuffer() byte[] baPathLength = BitConverter.GetBytes((Int32)nPathBytes); Debug.Assert(baPathLength.Length == 4, ""); - this.Length = 4/*weight*/ + 4/*threshold*/ + 4/*length of path content */ + nPathBytes; + this.Length = 4/*weight*/ + 4/*threshold*/ + 4/*length of path content */ + nPathBytes; m_buffer = new byte[this.Length]; @@ -216,7 +216,7 @@ public int CompareWeightTo(object obj) int delta = this.Weight - item.Weight; if (delta != 0) - return -1*delta; // 大在前 + return -1 * delta; // 大在前 // 如权值相同,再按照路径排序 // 小在前 @@ -233,7 +233,7 @@ public int CompareOverThresholdTo(object obj) int delta = over1 - over2; if (delta != 0) - return -1*delta; // 大在前 + return -1 * delta; // 大在前 // 如差额相同,再按照路径排序 // 小在前 @@ -250,13 +250,11 @@ public class DupResultSet : ItemFileBase // 排序风格 public DupResultSetSortStyle SortStyle = DupResultSetSortStyle.Path; - public DupResultSet() { } - public override Item NewItem() { return new DupLineItem(); @@ -291,10 +289,8 @@ public override int Compare(long lPtr1, long lPtr2) Debug.Assert(false, "invalid sort style"); return 0; } - } - // 功能: 合并两个数组 // parameters: // strStyle 运算风格 OR , AND , SUB @@ -439,7 +435,6 @@ public static int Merge(string strStyle, } } - if (String.Compare(strStyle, "OR", true) == 0 && targetMiddle != null) { diff --git a/DigitalPlatform.LibraryServer/LibraryApplication.cs b/DigitalPlatform.LibraryServer/LibraryApplication.cs index 6eabf7b69..9d5160cfd 100644 --- a/DigitalPlatform.LibraryServer/LibraryApplication.cs +++ b/DigitalPlatform.LibraryServer/LibraryApplication.cs @@ -3564,8 +3564,6 @@ public bool IsReaderDbName(string strReaderDbName, { IsInCirculation = this.ReaderDbs[i].InCirculation; strLibraryCode = this.ReaderDbs[i].LibraryCode; - - return true; } } diff --git a/DigitalPlatform.LibraryServer/SessionInfo.cs b/DigitalPlatform.LibraryServer/SessionInfo.cs index e6b14017b..80abdfeb1 100644 --- a/DigitalPlatform.LibraryServer/SessionInfo.cs +++ b/DigitalPlatform.LibraryServer/SessionInfo.cs @@ -252,7 +252,6 @@ public string GetTempDir() return this.m_strTempDir; } - public void CloseSession() { if (this._closed == true) @@ -276,6 +275,10 @@ public void CloseSession() if (this.Channels != null) this.Channels.Dispose(); + // 2016/4/5 + if (this.DupResultSet != null) + this.DupResultSet.Dispose(); + this.ClientIP = ""; } diff --git a/DigitalPlatform.LibraryService/LibraryService.cs b/DigitalPlatform.LibraryService/LibraryService.cs index 6c3c58686..1758ae5d8 100644 --- a/DigitalPlatform.LibraryService/LibraryService.cs +++ b/DigitalPlatform.LibraryService/LibraryService.cs @@ -3359,7 +3359,7 @@ public LibraryServerResult CopyBiblioInfo( && StringUtil.IsInList("order", sessioninfo.RightsOrigin) == false) { result.Value = -1; - result.ErrorInfo = "复制书目信息被拒绝。不具备order或setbiblioinfo权限。"; + result.ErrorInfo = "复制书目信息被拒绝。不具备 order 或 setbiblioinfo 权限。"; result.ErrorCode = ErrorCode.AccessDenied; return result; } @@ -9589,6 +9589,16 @@ public LibraryServerResult GetSystemParameter( if (strCategory == "system") { + // 2016/4/6 + // 获得系统的临时文件目录 + if (strName == "systemTempDir") + { + string strTempFileName = Path.GetTempFileName(); + File.Delete(strTempFileName); + strValue = Path.GetDirectoryName(strTempFileName); + goto END1; + } + if (strName == "libraryCodes") { List librarycodes = new List(); diff --git a/DigitalPlatform.ResultSet/DigitalPlatform.ResultSet.cs b/DigitalPlatform.ResultSet/DigitalPlatform.ResultSet.cs index 0951339d7..e5b5f0224 100644 --- a/DigitalPlatform.ResultSet/DigitalPlatform.ResultSet.cs +++ b/DigitalPlatform.ResultSet/DigitalPlatform.ResultSet.cs @@ -10,7 +10,6 @@ using DigitalPlatform.IO; using DigitalPlatform.Text; - namespace DigitalPlatform.ResultSet { //设计意图: diff --git a/DigitalPlatform.Text/StringUtil.cs b/DigitalPlatform.Text/StringUtil.cs index 10b958b98..accae84b8 100644 --- a/DigitalPlatform.Text/StringUtil.cs +++ b/DigitalPlatform.Text/StringUtil.cs @@ -30,7 +30,10 @@ public static bool IsValidCMIS(string strText) if (strText.Length == 19) { char ch = strText[0]; - if (ch == 'G' || ch == 'J' || ch == 'L') + if ( + // ch == 'G' || ch == 'J' || ch == 'L' + char.IsLetter(ch) && char.IsUpper(ch) + ) { string strMiddle = strText.Substring(1, 16); // 中间 16 位 if (IsPureNumber(strMiddle) == false) diff --git a/DigitalPlatform.rms.db/DatabaseCollection.cs b/DigitalPlatform.rms.db/DatabaseCollection.cs index 212b0badc..e58a963bc 100644 --- a/DigitalPlatform.rms.db/DatabaseCollection.cs +++ b/DigitalPlatform.rms.db/DatabaseCollection.cs @@ -6218,6 +6218,30 @@ public void Cancel() } + /* +dp2LibraryXE 发生未知的异常: + +发生未捕获的异常: +Type: System.ObjectDisposedException +Message: 已关闭 Safe handle +Stack: + 在 System.Runtime.InteropServices.SafeHandle.DangerousAddRef(Boolean& success) + 在 System.StubHelpers.StubHelpers.SafeHandleAddRef(SafeHandle pHandle, Boolean& success) + 在 Microsoft.Win32.Win32Native.SetEvent(SafeWaitHandle handle) + 在 System.Threading.EventWaitHandle.Set() + 在 DigitalPlatform.rms.DatabaseCommandTask.ThreadMain() 位置 c:\dp2-master\dp2\DigitalPlatform.rms.db\DatabaseCollection.cs:行号 6279 + 在 System.Threading.ThreadHelper.ThreadStart_Context(Object state) + 在 System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) + 在 System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) + 在 System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) + 在 System.Threading.ThreadHelper.ThreadStart() + + +dp2LibraryXE 版本: dp2LibraryXE, Version=1.1.5939.41661, Culture=neutral, PublicKeyToken=null +操作系统:Microsoft Windows NT 6.2.9200.0 +本机 MAC 地址: F0DEF174382F,CC52AFE3CF21,8CA982C371DB,8CA982C371DA +--- + * */ // 主函数 public void ThreadMain() { @@ -6276,7 +6300,15 @@ public void ThreadMain() } finally // 一定要返回信号 { - m_event.Set(); + + try + { + m_event.Set(); + } + catch + { + + } // 本线程负责释放资源 CloseReader(); diff --git a/dp2Circulation/EntityForm/EntityForm.cs b/dp2Circulation/EntityForm/EntityForm.cs index 2e8d12457..cb6b52e7b 100644 --- a/dp2Circulation/EntityForm/EntityForm.cs +++ b/dp2Circulation/EntityForm/EntityForm.cs @@ -4421,7 +4421,10 @@ public int DoSaveAll(string strStyle = "displaysuccess,verifydata,searchdup") } finally { - this.ShowMessage("记录保存成功", "green", true); + if (nErrorCount == 0) + this.ShowMessage("记录保存成功", "green", true); + else + this.ShowMessage("记录保存失败", "red", true); Progress.EndLoop(); Progress.OnStop -= new StopEventHandler(this.DoStop); diff --git a/dp2Circulation/Reader/ReaderSearchForm.cs b/dp2Circulation/Reader/ReaderSearchForm.cs index cb031a83e..8c8835bc2 100644 --- a/dp2Circulation/Reader/ReaderSearchForm.cs +++ b/dp2Circulation/Reader/ReaderSearchForm.cs @@ -1312,6 +1312,20 @@ private void listView_records_MouseUp(object sender, MouseEventArgs e) menuItem = new MenuItem("-"); contextMenu.MenuItems.Add(menuItem); + bool bLooping = (stop != null && stop.State == 0); // 0 表示正在处理 + + { + menuItem = new MenuItem("功能(&F)"); + contextMenu.MenuItems.Add(menuItem); + + MenuItem subMenuItem = null; + + subMenuItem = new MenuItem("校验读者记录 [" + this.listView_records.SelectedItems.Count.ToString() + "] (&V)"); + subMenuItem.Click += new System.EventHandler(this.menu_verifyPatronRecord_Click); + if (this.listView_records.SelectedItems.Count == 0 || bLooping == true) + subMenuItem.Enabled = false; + menuItem.MenuItems.Add(subMenuItem); + } // 批处理 // 正在检索的时候,不允许进行批处理操作。因为stop.BeginLoop()嵌套后的Min Max Value之间的保存恢复问题还没有解决 @@ -1482,6 +1496,144 @@ private void listView_records_MouseUp(object sender, MouseEventArgs e) contextMenu.Show(this.listView_records, new Point(e.X, e.Y)); } + void menu_verifyPatronRecord_Click(object sender, EventArgs e) + { + string strError = ""; + int nRet = 0; + + if (this.listView_records.SelectedItems.Count == 0) + { + strError = "尚未选择要校验的读者记录事项"; + goto ERROR1; + } + + // 读者信息缓存 + // 如果已经初始化,则保持 + if (this.m_biblioTable == null) + this.m_biblioTable = new Hashtable(); + + int nCount = 0; + + this.MainForm.OperHistory.AppendHtml("
" + HttpUtility.HtmlEncode(DateTime.Now.ToLongTimeString()) + " 开始进行读者记录校验
"); + + stop.Style = StopStyle.EnableHalfStop; + stop.OnStop += new StopEventHandler(this.DoStop); + stop.Initial("正在校验读者记录 ..."); + stop.BeginLoop(); + + this.EnableControls(false); + + this.listView_records.Enabled = false; + try + { + if (stop != null) + stop.SetProgressRange(0, this.listView_records.SelectedItems.Count); + + List items = new List(); + foreach (ListViewItem item in this.listView_records.SelectedItems) + { + if (string.IsNullOrEmpty(item.Text) == true) + continue; + + items.Add(item); + } + + ListViewPatronLoader loader = new ListViewPatronLoader(this.Channel, + stop, + items, + this.m_biblioTable); + loader.DbTypeCaption = this.DbTypeCaption; + + int i = 0; + foreach (LoaderItem item in loader) + { + Application.DoEvents(); // 出让界面控制权 + + if (stop != null + && stop.State != 0) + { + strError = "用户中断"; + goto ERROR1; + } + + stop.SetProgressValue(i); + + BiblioInfo info = item.BiblioInfo; + + // this.MainForm.OperHistory.AppendHtml("
" + HttpUtility.HtmlEncode(info.RecPath) + "
"); + + XmlDocument dom = new XmlDocument(); + dom.LoadXml(info.OldXml); + + string strBarcode = DomUtil.GetElementText(dom.DocumentElement, "barcode"); + + if (string.IsNullOrEmpty(strBarcode) == false) + { + string strReaderDbName = Global.GetDbName(info.RecPath); + string strLibraryCode = this.MainForm.GetReaderDbLibraryCode(strReaderDbName); + + // -2 服务器没有配置校验方法,无法校验 + // -1 出错 + // 0 不是合法的条码号 + // 1 是合法的读者证条码号 + // 2 是合法的册条码号 + nRet = this.MainForm.VerifyBarcode( + this.stop, + this.Channel, + strLibraryCode, + strBarcode, + null, + out strError); + if (nRet == -2) + goto ERROR1; + if (nRet != 1) + { + if (nRet == 2 && string.IsNullOrEmpty(strError) == true) + strError = strLibraryCode + ": 这看起来是一个册条码号"; + + this.MainForm.OperHistory.AppendHtml("
" + HttpUtility.HtmlEncode(info.RecPath) + "
"); + this.MainForm.OperHistory.AppendHtml("
" + "证条码号 '" + strBarcode + "' 不合法: " + strError + "
"); + + { + item.ListViewItem.BackColor = Color.FromArgb(155, 0, 0); + item.ListViewItem.ForeColor = Color.FromArgb(255,255,255); + } + } + + nCount++; + } + + + + i++; + } + + } + catch (Exception ex) + { + strError = "校验读者记录的过程中出现异常: " + ExceptionUtil.GetDebugText(ex); + goto ERROR1; + } + finally + { + this.listView_records.Enabled = true; + + stop.EndLoop(); + stop.OnStop -= new StopEventHandler(this.DoStop); + stop.Initial(""); + stop.HideProgress(); + stop.Style = StopStyle.None; + + this.EnableControls(true); + + this.MainForm.OperHistory.AppendHtml("
" + HttpUtility.HtmlEncode(DateTime.Now.ToLongTimeString()) + " 结束执行读者记录校验
"); + } + + return; + ERROR1: + MessageBox.Show(this, strError); + } + // 借阅历史 --> 实体查询窗 void menu_exportChargingHistoryToItemSearchForm_Click(object sender, EventArgs e) { diff --git a/dp2Circulation/SearchForms/ItemSearchForm.cs b/dp2Circulation/SearchForms/ItemSearchForm.cs index 506c1821a..8e51223bb 100644 --- a/dp2Circulation/SearchForms/ItemSearchForm.cs +++ b/dp2Circulation/SearchForms/ItemSearchForm.cs @@ -2547,6 +2547,8 @@ int VerifyItemRecord(out string strError) int nCount = 0; + this.MainForm.OperHistory.AppendHtml("
" + HttpUtility.HtmlEncode(DateTime.Now.ToLongTimeString()) + " 开始进行册记录校验
"); + stop.Style = StopStyle.EnableHalfStop; stop.OnStop += new StopEventHandler(this.DoStop); stop.Initial("正在进行校验册记录的操作 ..."); @@ -2634,6 +2636,11 @@ int VerifyItemRecord(out string strError) this.MainForm.OperHistory.AppendHtml("
" + HttpUtility.HtmlEncode(info.RecPath) + "
"); this.MainForm.OperHistory.AppendHtml("
" + "册条码号 '" + strBarcode + "' 不合法: " + strError + "
"); + + { + item.ListViewItem.BackColor = Color.FromArgb(155, 0, 0); + item.ListViewItem.ForeColor = Color.FromArgb(255, 255, 255); + } } nCount++; @@ -2653,6 +2660,8 @@ int VerifyItemRecord(out string strError) stop.Style = StopStyle.None; this.EnableControls(true); + + this.MainForm.OperHistory.AppendHtml("
" + HttpUtility.HtmlEncode(DateTime.Now.ToLongTimeString()) + " 结束执行读者记录校验
"); } } diff --git a/dp2Circulation/Statis/ReportForm.cs b/dp2Circulation/Statis/ReportForm.cs index a80b73e97..ee5a95e69 100644 --- a/dp2Circulation/Statis/ReportForm.cs +++ b/dp2Circulation/Statis/ReportForm.cs @@ -2758,9 +2758,14 @@ int Create_131_report(string strLibraryCode, string strName = line.GetString(0); string strDepartment = line.GetString(1); +#if NO string strDepartmentName = strDepartment.Replace(" ", "_"); if (string.IsNullOrEmpty(strDepartmentName) == true) strDepartmentName = "其他部门"; +#endif + + // 2016/4/7 + string strDepartmentName = GetValidDepartmentString(strDepartment); string strPureFileName = GetValidPathString(strDepartmentName) + "\\" + GetValidPathString(strReaderBarcode + "_" + strName) + ".rml"; string strOutputFileName = ""; @@ -2819,7 +2824,7 @@ int Create_131_report(string strLibraryCode, writer, strOutputFileName, macro_table, - "创建 "+strReportType+" 表时", + "创建 " + strReportType + " 表时", out strError); if (nRet == -1) return -1; @@ -2922,6 +2927,31 @@ static int IndexOf(char[] chars, char c) return -1; } + public static string GetValidDepartmentString(string strText, string strReplaceChar = "_") + { + if (strText != null) + strText = strText.Trim(); + if (string.IsNullOrEmpty(strText) == true) + return "其他部门"; + + // 文件名非法字符 + string department_invalid_chars = " /"; + + StringBuilder result = new StringBuilder(); + foreach (char c in strText) + { + if (c == ' ') + continue; + if (department_invalid_chars.IndexOf(c) != -1) + result.Append(strReplaceChar); + else + result.Append(c); + } + + return result.ToString(); + } + + // 101 111 121 122 // 121 表 按照读者 *姓名* 分类的借书册数表 // 122 表 按照读者 *姓名* 没有借书的读者 @@ -3016,7 +3046,7 @@ int Create_201_report(string strLibraryCode, writer, strOutputFileName, macro_table, - "创建 "+strReportType+" 表时", + "创建 " + strReportType + " 表时", out strError); } @@ -3064,7 +3094,7 @@ int Create_202_report(string strLibraryCode, writer, strOutputFileName, macro_table, - "创建 "+strReportType+" 表时", + "创建 " + strReportType + " 表时", out strError); } @@ -7246,7 +7276,7 @@ int DoReplication( } catch (Exception ex) { - strError = "ReportForm DoReplication() exception: " + ExceptionUtil.GetAutoText(ex); + strError = "ReportForm DoReplication() exception: " + ExceptionUtil.GetDebugText(ex); return -1; } finally @@ -10929,7 +10959,6 @@ int CreateOneTimeReports( string strOutputDir = Path.Combine(strReportsDir, GetValidPathString(GetSubDirName(time.Time))); - // 看看目录是否已经存在 if (time.Detect) { diff --git a/dp2Circulation/Statis/ReportWriter.cs b/dp2Circulation/Statis/ReportWriter.cs index e2046a59e..799606f5c 100644 --- a/dp2Circulation/Statis/ReportWriter.cs +++ b/dp2Circulation/Statis/ReportWriter.cs @@ -9,16 +9,17 @@ // using System.Data.SQLite; using System.Collections; using System.Diagnostics; -using DigitalPlatform.IO; using System.Globalization; using System.Data.Common; +using System.Data; +using System.Collections.Specialized; +using System.Data.SQLite; +using DigitalPlatform.IO; using DigitalPlatform.dp2.Statis; using DigitalPlatform.Text; -using System.Data; -using System.Collections.Specialized; using DigitalPlatform.Xml; -using System.Data.SQLite; +using DigitalPlatform; namespace dp2Circulation { @@ -281,7 +282,7 @@ public static Report BuildReport(SQLiteDataReader table, #endif public int OutputRmlReport( - DbDataReader data_reader, + DbDataReader data_reader, Hashtable macro_table, string strOutputFileName, out string strError) @@ -604,7 +605,7 @@ void OutputRmlTable( // if (column.DataType != DataType.Currency) { object v = null; - + if (column.ColumnNumber < data_reader.FieldCount) v = data_reader.GetValue(column.ColumnNumber); #if NO @@ -637,7 +638,7 @@ void OutputRmlTable( } catch (Exception ex) // 俘获可能因字符串转换为整数抛出的异常 { - throw new Exception("在累加 行 " + i.ToString() + " 列 " + column.ColumnNumber.ToString() + " 值的时候,抛出异常: " + ex.Message); + throw new Exception("在累加 行 " + i.ToString() + " 列 " + column.ColumnNumber.ToString() + " 值的时候,抛出异常: " + ExceptionUtil.GetAutoText(ex)); } } } @@ -762,7 +763,16 @@ object AddValue(ColumnDataType datatype, if (o1 is Int32) return (Int32)o1 + (Int32)o2; if (o1 is double) + { +#if NO + if (o2 is long) + { + return (double)o1 + Convert.ToDouble(o2); + } return (double)o1 + (double)o2; +#endif + return (double)o1 + Convert.ToDouble(o2); + } if (o1 is decimal) return (decimal)o1 + (decimal)o2; if (o1 is string) @@ -914,7 +924,8 @@ public override void Close() // 摘要: // Not implemented. Returns 0 - public override int Depth { + public override int Depth + { get { return 0; @@ -923,7 +934,8 @@ public override int Depth { // // 摘要: // Returns the number of columns in the current resultset - public override int FieldCount { + public override int FieldCount + { get { if (this.FieldValues == null) @@ -936,7 +948,8 @@ public override int FieldCount { // 摘要: // Retrieve the count of records affected by an update/insert command. Only // valid once the data reader is closed! - public override int RecordsAffected { + public override int RecordsAffected + { get { if (this._fetched == true) @@ -954,7 +967,8 @@ public override int RecordsAffected { // // 返回结果: // The value contained in the column - public override object this[int i] { + public override object this[int i] + { get { return this.FieldValues[i]; @@ -970,7 +984,8 @@ public override object this[int i] { // // 返回结果: // The value contained in the column - public override object this[string name] { + public override object this[string name] + { get { throw new Exception("尚未实现"); @@ -1014,7 +1029,8 @@ public override bool HasRows // // 摘要: // Returns True if the data reader is closed - public override bool IsClosed { + public override bool IsClosed + { get { return false; @@ -1049,9 +1065,9 @@ public override bool Read() public override bool GetBoolean(int i) { object o = this.FieldValues[i]; - if ( o is bool) + if (o is bool) return (bool)o; - throw new Exception("列 "+i.ToString()+" 不是 bool 类型"); + throw new Exception("列 " + i.ToString() + " 不是 bool 类型"); } // @@ -1067,9 +1083,9 @@ public override bool GetBoolean(int i) public override byte GetByte(int i) { object o = this.FieldValues[i]; - if ( o is byte) + if (o is byte) return (byte)o; - throw new Exception("列 "+i.ToString()+" 不是 byte 类型"); + throw new Exception("列 " + i.ToString() + " 不是 byte 类型"); } // @@ -1152,14 +1168,14 @@ public override char GetChar(int i) public override long GetChars(int i, long fieldoffset, char[] buffer, int bufferoffset, int length) { object o = this.FieldValues[i]; - if ( o is string) + if (o is string) { string strText = (string)o; if (buffer != null) strText.CopyTo((int)fieldoffset, buffer, bufferoffset, length); return strText.Length; } - throw new Exception("列 "+i.ToString()+" 不是 byte 类型"); + throw new Exception("列 " + i.ToString() + " 不是 byte 类型"); } // @@ -1205,22 +1221,22 @@ public override DateTime GetDateTime(int i) public override decimal GetDecimal(int i) { object o = this.FieldValues[i]; - if ( o is double) + if (o is double) return (decimal)(double)o; - if ( o is decimal) + if (o is decimal) return (decimal)o; - if ( o is int) + if (o is int) return (decimal)o; - if ( o is long) + if (o is long) return (decimal)o; - if ( o is string) - { - decimal v = 0; - decimal.TryParse((string)o, out v); - return v; - } - - throw new Exception("列 "+i.ToString()+" 不是 decimal 类型"); + if (o is string) + { + decimal v = 0; + decimal.TryParse((string)o, out v); + return v; + } + + throw new Exception("列 " + i.ToString() + " 不是 decimal 类型"); } // @@ -1236,22 +1252,22 @@ public override decimal GetDecimal(int i) public override double GetDouble(int i) { object o = this.FieldValues[i]; - if ( o is double) + if (o is double) return (double)o; - if ( o is decimal) + if (o is decimal) return (double)o; - if ( o is int) + if (o is int) return (double)o; - if ( o is long) + if (o is long) return (double)o; - if ( o is string) - { - double v = 0; - double.TryParse((string)o, out v); - return v; - } - - throw new Exception("列 "+i.ToString()+" 不是 decimal 类型"); + if (o is string) + { + double v = 0; + double.TryParse((string)o, out v); + return v; + } + + throw new Exception("列 " + i.ToString() + " 不是 decimal 类型"); } // @@ -1290,23 +1306,23 @@ public override Type GetFieldType(int i) // float public override float GetFloat(int i) { - object o = this.FieldValues[i]; - if ( o is float) + object o = this.FieldValues[i]; + if (o is float) return (float)o; - if ( o is decimal) + if (o is decimal) return (float)o; - if ( o is int) + if (o is int) return (float)o; - if ( o is long) + if (o is long) return (float)o; - if ( o is string) - { - float v = 0; - float.TryParse((string)o, out v); - return v; - } - - throw new Exception("列 "+i.ToString()+" 不是 float 类型"); + if (o is string) + { + float v = 0; + float.TryParse((string)o, out v); + return v; + } + + throw new Exception("列 " + i.ToString() + " 不是 float 类型"); } diff --git a/dp2Circulation/Statis/SQLiteUtil.cs b/dp2Circulation/Statis/SQLiteUtil.cs index 1e32edf4a..e4461d7ac 100644 --- a/dp2Circulation/Statis/SQLiteUtil.cs +++ b/dp2Circulation/Statis/SQLiteUtil.cs @@ -1423,7 +1423,16 @@ internal static int ParsePriceString(string strPrice, return -1; strUnit = item.Prefix + item.Postfix; - value = (long)(item.Value * 100); + try + { + value = (long)(item.Value * 100); + } + catch(Exception ex) + { + // 2016/3/31 + strError = "元值 '"+item.Value.ToString()+"' 折算为分值的时候出现异常:" + ex.Message; + return -1; + } return 0; } diff --git a/dp2Circulation/dp2Circulation.csproj b/dp2Circulation/dp2Circulation.csproj index 9d1bcf084..32b0ad44a 100644 --- a/dp2Circulation/dp2Circulation.csproj +++ b/dp2Circulation/dp2Circulation.csproj @@ -51,7 +51,7 @@ dp2 V2 true publish.htm - 34 + 38 2.10.0.%2a false true @@ -2830,9 +2830,9 @@ - + False - Microsoft .NET Framework 4 %28x86 和 x64%29与 .NET Framework 4 的更新%28KB2468871%29 + Microsoft .NET Framework 4 %28x86 和 x64%29 true diff --git a/dp2Installer/dp2Installer.csproj b/dp2Installer/dp2Installer.csproj index 1c91e9831..64fc60210 100644 --- a/dp2Installer/dp2Installer.csproj +++ b/dp2Installer/dp2Installer.csproj @@ -34,7 +34,7 @@ dp2 V2 true publish.htm - 106 + 112 1.1.0.%2a false true diff --git a/dp2Library/Host.cs b/dp2Library/Host.cs index a99dc5fab..b4043d784 100644 --- a/dp2Library/Host.cs +++ b/dp2Library/Host.cs @@ -25,6 +25,7 @@ using DigitalPlatform.LibraryServer; using DigitalPlatform.IO; using DigitalPlatform.Text; +using System.IO; namespace dp2Library { @@ -33,7 +34,7 @@ public partial class LibraryServiceHost : ServiceBase // ServiceHost m_host = null; List m_hosts = new List(); - Thread m_thread = null; + Thread m_thread = null; public EventLog Log = null; @@ -54,6 +55,11 @@ public static void Main(string[] args) { new LibraryServiceHost().ConsoleRun(); } + else if (args.Length == 1 && args[0].Equals("cleartemp")) + { + // 清除临时文件目录中的临时文件 + ClearTempFiles(); + } else { ServiceBase.Run(new LibraryServiceHost()); @@ -130,7 +136,7 @@ public static string[] GetHostUrl(string strProductName) } } -#endif +#endif // 获得instance信息 // parameters: @@ -277,14 +283,14 @@ static bool CheckFunction(string strSerialCode, string strFunction) } // 将本地字符串匹配序列号 - static bool MatchLocalString(string strSerialNumber, + static bool MatchLocalString(string strSerialNumber, string strInstanceName, out string strDebugInfo) { strDebugInfo = ""; StringBuilder debuginfo = new StringBuilder(); - debuginfo.Append("序列号 '" + strSerialNumber + "' 实例名 '"+strInstanceName+"'\r\n"); + debuginfo.Append("序列号 '" + strSerialNumber + "' 实例名 '" + strInstanceName + "'\r\n"); List macs = SerialCodeForm.GetMacAddress(); debuginfo.Append("本机 MAC 地址: " + StringUtil.MakePathList(macs) + "\r\n"); @@ -298,7 +304,7 @@ static bool MatchLocalString(string strSerialNumber, strInstanceName); string strSha1 = Cryptography.GetSHA1(StringUtil.SortParams(strLocalString) + "_reply"); - debuginfo.Append("MAC 地址 '" + mac + "' 环境字符串 '"+strLocalString+"' SHA '"+strSha1+"'\r\n"); + debuginfo.Append("MAC 地址 '" + mac + "' 环境字符串 '" + strLocalString + "' SHA '" + strSha1 + "'\r\n"); if (strSha1 == SerialCodeForm.GetCheckCode(strSerialNumber)) { debuginfo.Append("匹配\r\n"); @@ -374,7 +380,7 @@ void ThreadMain() if (MatchLocalString(strSerialNumber, strInstanceName, out strDebugInfo) == false) //if (strSha1 != SerialCodeForm.GetCheckCode(strSerialNumber)) { - this.Log.WriteEntry("dp2Library 实例 '"+strInstanceName+"' 序列号不合法,无法启动。\r\n调试信息如下:\r\n" + strDebugInfo, + this.Log.WriteEntry("dp2Library 实例 '" + strInstanceName + "' 序列号不合法,无法启动。\r\n调试信息如下:\r\n" + strDebugInfo, EventLogEntryType.Error); continue; } @@ -643,7 +649,7 @@ System.ServiceModel.Channels.Binding CreateWsHttpBinding0() quotas.MaxStringContentLength = 1024 * 1024; binding.ReaderQuotas = quotas; SetTimeout(binding); - binding.ReliableSession.InactivityTimeout = new TimeSpan(0, 20, 0); + binding.ReliableSession.InactivityTimeout = new TimeSpan(0, 20, 0); // binding.ReliableSession.Enabled = true; binding.ReliableSession.InactivityTimeout = new TimeSpan(0, 20, 0); @@ -989,6 +995,32 @@ protected override void OnStop() this.m_thread = null; } } + + // 清除以前残留的临时文件 + static void ClearTempFiles() + { + string strTempFileName = Path.GetTempFileName(); + File.Delete(strTempFileName); + string strTempDir = Path.GetDirectoryName(strTempFileName); + + int nCount = 0; + DirectoryInfo di = new DirectoryInfo(strTempDir); + FileInfo [] fis = di.GetFiles("*.tmp"); + foreach(FileInfo fi in fis) + { + try + { + Console.WriteLine(fi.FullName); + File.Delete(fi.FullName); + nCount++; + } + catch(Exception ex) + { + Console.WriteLine("删除出现异常: " + ex.Message); + } + } + Console.WriteLine("共删除 "+nCount.ToString()+" 个临时文件"); + } } public class MyValidator : UserNamePasswordValidator diff --git a/dp2LibraryXE/dp2LibraryXE.csproj b/dp2LibraryXE/dp2LibraryXE.csproj index 60a3a5065..468fd028d 100644 --- a/dp2LibraryXE/dp2LibraryXE.csproj +++ b/dp2LibraryXE/dp2LibraryXE.csproj @@ -36,7 +36,7 @@ dp2 V2 true publish.htm - 71 + 75 1.1.0.%2a false true @@ -270,9 +270,9 @@ - + False - Microsoft .NET Framework 4 %28x86 和 x64%29与 .NET Framework 4 的更新%28KB2468871%29 + Microsoft .NET Framework 4 %28x86 和 x64%29 true From 4eba1dd8b2fe16927c0d6ae93fce06c438d3b056 Mon Sep 17 00:00:00 2001 From: XieTao Date: Fri, 8 Apr 2016 13:10:36 +0800 Subject: [PATCH 07/10] =?UTF-8?q?=E5=88=9D=E6=AD=A5=E5=AE=9E=E7=8E=B0=20dp?= =?UTF-8?q?2Catalog=20=E4=B8=AD=E5=9B=BA=E5=AE=9A=E8=AE=B0=E5=BD=95?= =?UTF-8?q?=E7=AA=97=E7=9B=B8=E5=85=B3=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AppLogRecover.cs | 99 ++++++---- dp2Catalog/MainForm/MainForm.Designer.cs | 68 ++++++- dp2Catalog/MainForm/MainForm.cs | 166 ++++++++++++++-- dp2Catalog/MainForm/MainForm.resx | 45 +++++ dp2Catalog/MarcDetailForm.cs | 180 +++++++++++++----- dp2Catalog/MdiForm/MyForm.cs | 16 +- dp2Catalog/Z39.50/ZQueryControl.cs | 37 +++- dp2Catalog/Z39.50/ZSearchForm.cs | 43 ++++- dp2Catalog/dp2/dp2SearchForm.cs | 92 ++++++++- dp2Circulation/dp2Circulation.csproj | 2 +- 10 files changed, 616 insertions(+), 132 deletions(-) diff --git a/DigitalPlatform.LibraryServer/AppLogRecover.cs b/DigitalPlatform.LibraryServer/AppLogRecover.cs index e4bfea586..18efdde05 100644 --- a/DigitalPlatform.LibraryServer/AppLogRecover.cs +++ b/DigitalPlatform.LibraryServer/AppLogRecover.cs @@ -67,14 +67,14 @@ public int RecoverBorrow( return -1; } - DO_SNAPSHOT: + DO_SNAPSHOT: // 快照恢复 if (level == RecoverLevel.Snapshot) { XmlNode node = null; string strReaderXml = DomUtil.GetElementText(domLog.DocumentElement, - "readerRecord", + "readerRecord", out node); if (node == null) { @@ -659,7 +659,7 @@ public int RecoverBorrow( return 0; - ERROR1: + ERROR1: if (level == RecoverLevel.LogicAndSnapshot) { level = RecoverLevel.Snapshot; @@ -875,7 +875,7 @@ int RemoveReaderSideLink( XmlNode nodeBorrow = readerdom.DocumentElement.SelectSingleNode("borrows/borrow[@barcode='" + strItemBarcode + "']"); if (nodeBorrow == null) { - strError = "在读者记录 '"+strReaderBarcode+"' 中没有找到关于册条码号 '"+strItemBarcode+"' 的链"; + strError = "在读者记录 '" + strReaderBarcode + "' 中没有找到关于册条码号 '" + strItemBarcode + "' 的链"; return 0; } @@ -1160,7 +1160,7 @@ int BorrowChangeReaderAndItemRecord( string strBorrower0 = DomUtil.GetElementInnerText(itemdom.DocumentElement, "borrower"); - if (string.IsNullOrEmpty(strBorrower0) == false + if (string.IsNullOrEmpty(strBorrower0) == false && strBorrower0 != strReaderBarcode) { string strRemovedInfo = ""; @@ -1183,7 +1183,7 @@ int BorrowChangeReaderAndItemRecord( } else { - this.WriteErrorLog("册条码号为 '"+strItemBarcodeParam+"' 的册记录,在进行借书操作(拟被读者 '"+strReaderBarcode+"' 借阅)以前,发现它被另一读者 '"+strBorrower0+"' 持有,软件已经自动修正(删除)了此读者记录的半侧借阅信息链。被移走的片断 XML 信息为 '"+strRemovedInfo+"'"); + this.WriteErrorLog("册条码号为 '" + strItemBarcodeParam + "' 的册记录,在进行借书操作(拟被读者 '" + strReaderBarcode + "' 借阅)以前,发现它被另一读者 '" + strBorrower0 + "' 持有,软件已经自动修正(删除)了此读者记录的半侧借阅信息链。被移走的片断 XML 信息为 '" + strRemovedInfo + "'"); } } @@ -1476,7 +1476,7 @@ public int RecoverReturn( } else { - strRecoverComment += "经过筛选,仍然有 " + aFoundPath.Count.ToString() + " 条册记录含有借阅者 '"+strReaderBarcode+"' 信息,那么就只好选择其中第一个册记录 " + strOutputItemRecPath + " 进行还书操作。"; + strRecoverComment += "经过筛选,仍然有 " + aFoundPath.Count.ToString() + " 条册记录含有借阅者 '" + strReaderBarcode + "' 信息,那么就只好选择其中第一个册记录 " + strOutputItemRecPath + " 进行还书操作。"; } } else @@ -1750,7 +1750,7 @@ public int RecoverReturn( // 需要把根据“所借册条码号”清除读者记录中借阅信息的动作提前进行? 这样遇到特殊情况范围时,至少读者记录中的信息是被清除了的,这是容错的需要 string strError_1 = ""; nRet = ReturnAllReader( - // Channels, + // Channels, channel, strItemBarcode, "", @@ -1921,7 +1921,7 @@ public int RecoverReturn( if (bDupItemBarcode == false) { nRet = ReturnAllReader( - // Channels, + // Channels, channel, strItemBarcode, strOutputReaderRecPath, @@ -2105,8 +2105,8 @@ static int ClearBorrowItem( } bool bChanged = false; - XmlNodeList nodes = dom.DocumentElement.SelectNodes("//borrows/borrow[@barcode='"+strBorrowItemBarcode+"']"); - for(int j=0;j元素 - XmlNode nodeOverdue = readerdom.DocumentElement.SelectSingleNode("overdues/overdue[@id='"+strID+"']"); + XmlNode nodeOverdue = readerdom.DocumentElement.SelectSingleNode("overdues/overdue[@id='" + strID + "']"); if (nodeOverdue != null) { if (nodeOverdue.ParentNode != null) @@ -5790,7 +5819,7 @@ public int RecoverAmerce( out strError); if (lRet == -1) goto ERROR1; - + } return 0; @@ -5847,7 +5876,7 @@ static string GetAmerceRecordStringByID(XmlDocument domLog, continue; } - strResult += "id: " +strID + " -- " + records[index] + "\r\n"; + strResult += "id: " + strID + " -- " + records[index] + "\r\n"; } return strResult; @@ -5880,7 +5909,7 @@ static int GetAttachmentRecord( long lLength = 0; // 找到记录开头 - for (int i=0; i<=nAttachmentIndex; i++) + for (int i = 0; i <= nAttachmentIndex; i++) { byte[] length = new byte[8]; int nRet = attachment.Read(length, 0, 8); @@ -6063,7 +6092,7 @@ public int RecoverDevolveReaderInfo( } catch { - strError = "元素的attachmentIndex属性值'"+strAttachmentIndex+"'格式不正确,应当为>=0的纯数字"; + strError = "元素的attachmentIndex属性值'" + strAttachmentIndex + "'格式不正确,应当为>=0的纯数字"; return -1; } @@ -6075,7 +6104,7 @@ public int RecoverDevolveReaderInfo( out strError); if (nRet == -1) { - strError = "获得 index 为 "+nAttachmentIndex.ToString()+" 的日志附件记录时出错:" + strError; + strError = "获得 index 为 " + nAttachmentIndex.ToString() + " 的日志附件记录时出错:" + strError; return -1; } strItemXml = Encoding.UTF8.GetString(baItem); @@ -6342,7 +6371,7 @@ public int RecoverSetBiblioInfo( "action"); // 快照恢复 - if (level == RecoverLevel.Snapshot + if (level == RecoverLevel.Snapshot || bReuse == true) { byte[] timestamp = null; @@ -7691,7 +7720,7 @@ public int RecoverWriteRes( } catch { - strError = "lTotalLength值 '"+strTotalLength+"' 格式不正确"; + strError = "lTotalLength值 '" + strTotalLength + "' 格式不正确"; return -1; } string strMetadata = DomUtil.GetElementText( @@ -7874,7 +7903,7 @@ public int RecoverRepairBorrowInfo( goto ERROR1; } } - + // 读入册记录 string strConfirmItemRecPath = DomUtil.GetElementText(domLog.DocumentElement, "confirmItemRecPath"); @@ -8085,7 +8114,7 @@ public int RecoverRepairBorrowInfo( } else { - strError = "不可识别的strAction值 '"+strAction+"'"; + strError = "不可识别的strAction值 '" + strAction + "'"; goto ERROR1; } diff --git a/dp2Catalog/MainForm/MainForm.Designer.cs b/dp2Catalog/MainForm/MainForm.Designer.cs index e723907df..5ee3a7d7e 100644 --- a/dp2Catalog/MainForm/MainForm.Designer.cs +++ b/dp2Catalog/MainForm/MainForm.Designer.cs @@ -80,6 +80,7 @@ private void InitializeComponent() this.MenuItem_help = new System.Windows.Forms.ToolStripMenuItem(); this.MenuItem_cfg = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripSeparator6 = new System.Windows.Forms.ToolStripSeparator(); + this.MenuItem_openUserFolder = new System.Windows.Forms.ToolStripMenuItem(); this.MenuItem_openDataFolder = new System.Windows.Forms.ToolStripMenuItem(); this.MenuItem_openProgramFolder = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripSeparator19 = new System.Windows.Forms.ToolStripSeparator(); @@ -102,6 +103,10 @@ private void InitializeComponent() this.toolButton_refresh = new System.Windows.Forms.ToolStripButton(); this.toolButton_loadTemplate = new System.Windows.Forms.ToolStripButton(); this.toolStripSeparator10 = new System.Windows.Forms.ToolStripSeparator(); + this.toolStripButton_searchZ = new System.Windows.Forms.ToolStripButton(); + this.toolStripButton_searchA = new System.Windows.Forms.ToolStripButton(); + this.toolStripButton_copyToFixed = new System.Windows.Forms.ToolStripButton(); + this.toolStripSeparator20 = new System.Windows.Forms.ToolStripSeparator(); this.toolButton_dup = new System.Windows.Forms.ToolStripButton(); this.toolButton_verify = new System.Windows.Forms.ToolStripButton(); this.toolStripSeparator11 = new System.Windows.Forms.ToolStripSeparator(); @@ -121,7 +126,6 @@ private void InitializeComponent() this.toolStrip_panelFixed = new System.Windows.Forms.ToolStrip(); this.toolStripButton_close = new System.Windows.Forms.ToolStripButton(); this.splitter_fixed = new System.Windows.Forms.Splitter(); - this.MenuItem_openUserFolder = new System.Windows.Forms.ToolStripMenuItem(); this.menuStrip_main.SuspendLayout(); this.toolStrip_main.SuspendLayout(); this.statusStrip_main.SuspendLayout(); @@ -524,6 +528,13 @@ private void InitializeComponent() this.toolStripSeparator6.Name = "toolStripSeparator6"; this.toolStripSeparator6.Size = new System.Drawing.Size(174, 6); // + // MenuItem_openUserFolder + // + this.MenuItem_openUserFolder.Name = "MenuItem_openUserFolder"; + this.MenuItem_openUserFolder.Size = new System.Drawing.Size(177, 22); + this.MenuItem_openUserFolder.Text = "ûļ(&U)"; + this.MenuItem_openUserFolder.Click += new System.EventHandler(this.MenuItem_openUserFolder_Click); + // // MenuItem_openDataFolder // this.MenuItem_openDataFolder.Name = "MenuItem_openDataFolder"; @@ -576,6 +587,10 @@ private void InitializeComponent() this.toolButton_refresh, this.toolButton_loadTemplate, this.toolStripSeparator10, + this.toolStripButton_searchZ, + this.toolStripButton_searchA, + this.toolStripButton_copyToFixed, + this.toolStripSeparator20, this.toolButton_dup, this.toolButton_verify, this.toolStripSeparator11, @@ -735,6 +750,44 @@ private void InitializeComponent() this.toolStripSeparator10.Name = "toolStripSeparator10"; this.toolStripSeparator10.Size = new System.Drawing.Size(6, 29); // + // toolStripButton_searchZ + // + this.toolStripButton_searchZ.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text; + this.toolStripButton_searchZ.Image = ((System.Drawing.Image)(resources.GetObject("toolStripButton_searchZ.Image"))); + this.toolStripButton_searchZ.ImageTransparentColor = System.Drawing.Color.Magenta; + this.toolStripButton_searchZ.Name = "toolStripButton_searchZ"; + this.toolStripButton_searchZ.Size = new System.Drawing.Size(23, 26); + this.toolStripButton_searchZ.Text = "Z"; + this.toolStripButton_searchZ.ToolTipText = " Z39.50 ǰ¼"; + this.toolStripButton_searchZ.Click += new System.EventHandler(this.toolStripButton_searchZ_Click); + // + // toolStripButton_searchA + // + this.toolStripButton_searchA.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text; + this.toolStripButton_searchA.Image = ((System.Drawing.Image)(resources.GetObject("toolStripButton_searchA.Image"))); + this.toolStripButton_searchA.ImageTransparentColor = System.Drawing.Color.Magenta; + this.toolStripButton_searchA.Name = "toolStripButton_searchA"; + this.toolStripButton_searchA.Size = new System.Drawing.Size(23, 26); + this.toolStripButton_searchA.Text = "A"; + this.toolStripButton_searchA.ToolTipText = "ѷǰ¼"; + this.toolStripButton_searchA.Click += new System.EventHandler(this.toolStripButton_searchA_Click); + // + // toolStripButton_copyToFixed + // + this.toolStripButton_copyToFixed.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text; + this.toolStripButton_copyToFixed.Image = ((System.Drawing.Image)(resources.GetObject("toolStripButton_copyToFixed.Image"))); + this.toolStripButton_copyToFixed.ImageTransparentColor = System.Drawing.Color.Magenta; + this.toolStripButton_copyToFixed.Name = "toolStripButton_copyToFixed"; + this.toolStripButton_copyToFixed.Size = new System.Drawing.Size(45, 26); + this.toolStripButton_copyToFixed.Text = "<"; + this.toolStripButton_copyToFixed.ToolTipText = "ӵǰڸƵ̶"; + this.toolStripButton_copyToFixed.Click += new System.EventHandler(this.toolStripButton_copyToFixed_Click); + // + // toolStripSeparator20 + // + this.toolStripSeparator20.Name = "toolStripSeparator20"; + this.toolStripSeparator20.Size = new System.Drawing.Size(6, 29); + // // toolButton_dup // this.toolButton_dup.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; @@ -793,7 +846,7 @@ private void InitializeComponent() this.toolStripButton_testSearch.Image = ((System.Drawing.Image)(resources.GetObject("toolStripButton_testSearch.Image"))); this.toolStripButton_testSearch.ImageTransparentColor = System.Drawing.Color.Magenta; this.toolStripButton_testSearch.Name = "toolStripButton_testSearch"; - this.toolStripButton_testSearch.Size = new System.Drawing.Size(79, 26); + this.toolStripButton_testSearch.Size = new System.Drawing.Size(79, 21); this.toolStripButton_testSearch.Text = "Test Search"; this.toolStripButton_testSearch.Visible = false; this.toolStripButton_testSearch.Click += new System.EventHandler(this.toolStripButton_testSearch_Click); @@ -937,13 +990,6 @@ private void InitializeComponent() this.splitter_fixed.TabIndex = 7; this.splitter_fixed.TabStop = false; // - // MenuItem_openUserFolder - // - this.MenuItem_openUserFolder.Name = "MenuItem_openUserFolder"; - this.MenuItem_openUserFolder.Size = new System.Drawing.Size(177, 22); - this.MenuItem_openUserFolder.Text = "ûļ(&U)"; - this.MenuItem_openUserFolder.Click += new System.EventHandler(this.MenuItem_openUserFolder_Click); - // // MainForm // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); @@ -1079,6 +1125,10 @@ private void InitializeComponent() private System.Windows.Forms.ToolStripMenuItem MenuItem_resetSerialCode; private System.Windows.Forms.ToolStripMenuItem MenuItem_openAdvertiseForm; private System.Windows.Forms.ToolStripMenuItem MenuItem_openUserFolder; + private System.Windows.Forms.ToolStripButton toolStripButton_searchZ; + private System.Windows.Forms.ToolStripButton toolStripButton_searchA; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator20; + public System.Windows.Forms.ToolStripButton toolStripButton_copyToFixed; } } diff --git a/dp2Catalog/MainForm/MainForm.cs b/dp2Catalog/MainForm/MainForm.cs index 28a79adcd..b6d7e2956 100644 --- a/dp2Catalog/MainForm/MainForm.cs +++ b/dp2Catalog/MainForm/MainForm.cs @@ -263,7 +263,7 @@ private void MainForm_Load(object sender, EventArgs e) // 设置文件名,以便本次运行结束时覆盖旧文件 Servers.FileName = Path.Combine(this.DataDir, "servers.bin"); } - catch(Exception ex) + catch (Exception ex) { MessageBox.Show(this, "servers.bin 装载出现异常: " + ex.Message); } @@ -373,7 +373,7 @@ void RestoreLastOpenedMdiWindow(string strOpenedMdiWindow) } } - string[] types = strOpenedMdiWindow.Split(new char[] {','}); + string[] types = strOpenedMdiWindow.Split(new char[] { ',' }); for (int i = 0; i < types.Length; i++) { string strType = types[i]; @@ -726,7 +726,7 @@ int LoadFroms(string strFileName, } catch (Exception ex) { - strError = "装载文件 " +strFileName+ " 到XMLDOM时出错: " + ex.Message; + strError = "装载文件 " + strFileName + " 到XMLDOM时出错: " + ex.Message; return -1; } @@ -1062,7 +1062,7 @@ private void toolButton_saveTo_Click(object sender, EventArgs e) finally { save.RestoreAll(); - } + } } private void toolButton_save_Click(object sender, EventArgs e) @@ -1257,6 +1257,55 @@ public MarcDetailForm TopMarcDetailForm } } + public void SetMdiToNormal() + { + if (this.ActiveMdiChild != null) + { + if (this.ActiveMdiChild.WindowState != FormWindowState.Normal) + this.ActiveMdiChild.WindowState = FormWindowState.Normal; + } + } + + MdiClient GetMdiClient() + { + Type t = typeof(Form); + PropertyInfo pi = t.GetProperty("MdiClient", BindingFlags.Instance | BindingFlags.NonPublic); + return (MdiClient)pi.GetValue(this, null); + } + + // 设置窗口到左侧固定位置 + public void SetFixedPosition(Form form, string strStyle) + { + MdiClient client = GetMdiClient(); + if (strStyle == "left") + { + form.Location = new Point(0, 0); + form.Size = new Size((client.ClientSize.Width / 2) - 1, client.ClientSize.Height - 1); + } + else + { + form.Location = new Point(client.ClientSize.Width / 2, 0); + form.Size = new Size((client.ClientSize.Width / 2) - 1, client.ClientSize.Height - 1); + } + } + + public MarcDetailForm FixedMarcDetailForm + { + get + { + foreach (Form form in this.MdiChildren) + { + if (form is MarcDetailForm) + { + MarcDetailForm detail = form as MarcDetailForm; + if (detail.Fixed) + return detail; + } + } + return null; + } + } + // 当前顶层的DcForm public DcForm TopDcForm @@ -1267,7 +1316,7 @@ public DcForm TopDcForm } } - // 得到特定类型的顶层MDI窗口 + // 得到特定类型的顶层MDI窗口。注,会忽略 fixed 类型的窗口 Form GetTopChildWindow(Type type) { if (ActiveMdiChild == null) @@ -1285,11 +1334,11 @@ Form GetTopChildWindow(Type type) break; Form child = null; - for (int j = 0; j < this.MdiChildren.Length; j++) + foreach (Form form in this.MdiChildren) { - if (hwnd == this.MdiChildren[j].Handle) + if (hwnd == form.Handle) { - child = this.MdiChildren[j]; + child = form; goto FOUND; } } @@ -1298,7 +1347,14 @@ Form GetTopChildWindow(Type type) FOUND: if (child.GetType().Equals(type) == true) + { + if (child is MyForm) + { + if (((MyForm)child).Fixed) + goto CONTINUE; + } return child; + } CONTINUE: hwnd = API.GetWindow(hwnd, API.GW_HWNDNEXT); @@ -1401,7 +1457,7 @@ private void MenuItem_saveOriginRecordToIso2709_Click(object sender, EventArgs e dp2SearchForm search = (dp2SearchForm)this.ActiveMdiChild; search.SaveOriginRecordToIso2709(); } - + } private void MenuItem_openZhongcihaoForm_Click(object sender, EventArgs e) @@ -1802,7 +1858,7 @@ public int DownloadDataFile(string strFileName, strError = ""; string strUrl = "http://dp2003.com/dp2Catalog/" + strFileName; - string strLocalFileName = Path.Combine(this.DataDir , strFileName); + string strLocalFileName = Path.Combine(this.DataDir, strFileName); string strTempFileName = Path.Combine(this.DataDir, "~temp_download_webfile"); int nRet = WebFileDownloadDialog.DownloadWebFile( @@ -2059,7 +2115,7 @@ private void toolButton_verify_Click(object sender, EventArgs e) // dcform.VerifyData(); } } - + // 连接MARC文件 private void MenuItem_linkMarcFile_Click(object sender, EventArgs e) @@ -2150,6 +2206,32 @@ public AmazonSearchForm GetAmazonSearchForm() return searchform; } + public ZSearchForm GetZSearchForm() + { + ZSearchForm searchform = null; + + searchform = this.TopZSearchForm; + + if (searchform == null) + { + // 新开一个dp2检索窗 + // FormWindowState old_state = this.WindowState; + + searchform = new ZSearchForm(); + searchform.MainForm = this; + searchform.MdiParent = this; + // searchform.WindowState = FormWindowState.Minimized; + searchform.Show(); + + // this.WindowState = old_state; + this.Activate(); + + // 需要等待初始化操作彻底完成 + // searchform.WaitLoadFinish(); + } + + return searchform; + } public dp2SearchForm GetDp2SearchForm() { @@ -3061,10 +3143,10 @@ public int SmartHanziTextToPinyin( out string strPinyin, out string strError) { - return SmartHanziTextToPinyin(owner, - strText, - style, - ( bAutoSel ? "auto" : "" ), + return SmartHanziTextToPinyin(owner, + strText, + style, + (bAutoSel ? "auto" : ""), out strPinyin, out strError); } @@ -3465,7 +3547,7 @@ public int AddPinyin( string strCfgXml, PinyinStyle style = PinyinStyle.None, string strPrefix = "", - string strDuoyinStyle="" + string strDuoyinStyle = "" /*bool bAutoSel = false*/) { string strError = ""; @@ -3981,10 +4063,10 @@ internal int VerifySerialCode( //string strSha1 = Cryptography.GetSHA1(StringUtil.SortParams(strLocalString) + "_reply"); - if (CheckFunction(GetEnvironmentString(""), strRequirFuncList) == false || + if (CheckFunction(GetEnvironmentString(""), strRequirFuncList) == false || // strSha1 != GetCheckCode(strSerialCode) - MatchLocalString(strSerialCode) == false - || String.IsNullOrEmpty(strSerialCode) == true) + MatchLocalString(strSerialCode) == false + || String.IsNullOrEmpty(strSerialCode) == true) { if (bReinput == false) { @@ -4119,7 +4201,7 @@ int ResetSerialCode( string strMAC = (string)ext_table["mac"]; if (string.IsNullOrEmpty(strMAC) == true) strOriginCode = "!error"; - else + else strOriginCode = Cryptography.Encrypt(strOriginCode, this.CopyrightKey); SerialCodeForm dlg = new SerialCodeForm(); @@ -4298,6 +4380,50 @@ public void WriteErrorLog(string strText) "log_", ".txt"); } + + // 用 Z39.50 检索当前记录 + private void toolStripButton_searchZ_Click(object sender, EventArgs e) + { + // 从当前记录窗得到检索词 + Form active = this.ActiveMdiChild; + if (active == null) + return; + + string strUse = ""; + string strQueryWord = ""; + if (active is MarcDetailForm) + { + MarcDetailForm detailform = active as MarcDetailForm; + bool bRet = detailform.GetQueryContent(out strUse, + out strQueryWord); + if (bRet == false) + { + MessageBox.Show(this, "无法从当前记录窗 MARC 记录中获得检索词"); + return; + } + } + + ZSearchForm searchform = GetZSearchForm(); + searchform.SetQueryContent(strUse, strQueryWord); + searchform.Activate(); + searchform.DoSearch(); + } + + // 用亚马逊检索当前记录 + private void toolStripButton_searchA_Click(object sender, EventArgs e) + { + AmazonSearchForm searchform = GetAmazonSearchForm(); + } + + // 从当前窗口复制到固定窗口 + private void toolStripButton_copyToFixed_Click(object sender, EventArgs e) + { + if (this.ActiveMdiChild is MarcDetailForm) + { + MarcDetailForm detailform = (MarcDetailForm)this.ActiveMdiChild; + detailform.CopyMarcToFixed(); + } + } } public class EnableState diff --git a/dp2Catalog/MainForm/MainForm.resx b/dp2Catalog/MainForm/MainForm.resx index 83651b031..94748ed68 100644 --- a/dp2Catalog/MainForm/MainForm.resx +++ b/dp2Catalog/MainForm/MainForm.resx @@ -258,6 +258,51 @@ YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAABcSURBVEhL7cwxDsAwCENRBs7O6bhTKleoYkhSszHwJG/w ZRyZ2WIW5zw8/cGNqtbibBhKcSaMYF683jFhcPd35bDIfdArnOVYNuFP3/BJnzAe2NFhHFYXr2NH5AHx GGbpB9C82QAAAABJRU5ErkJggg== + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIDSURBVDhPpZLrS5NhGMb3j4SWh0oRQVExD4gonkDpg4hG + 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 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIDSURBVDhPpZLrS5NhGMb3j4SWh0oRQVExD4gonkDpg4hG + 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 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIDSURBVDhPpZLrS5NhGMb3j4SWh0oRQVExD4gonkDpg4hG + 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/dp2Catalog/MarcDetailForm.cs b/dp2Catalog/MarcDetailForm.cs index a58a6fbdb..4daccc2a6 100644 --- a/dp2Catalog/MarcDetailForm.cs +++ b/dp2Catalog/MarcDetailForm.cs @@ -469,11 +469,13 @@ public string UiState public void LoadSize() { - // 设置窗口尺寸状态 - MainForm.AppInfo.LoadMdiChildFormStates(this, - "mdi_form_state", - MainForm.DefaultMdiWindowWidth, - MainForm.DefaultMdiWindowHeight); + if (this.SupressSizeSetting == false) + { + // 设置窗口尺寸状态 + MainForm.AppInfo.LoadMdiChildFormStates(this, + "mdi_form_state", + MainForm.DefaultMdiWindowWidth, + MainForm.DefaultMdiWindowHeight); #if NO // 获得splitContainer_originDataMain的状态 @@ -484,6 +486,8 @@ public void LoadSize() if (nValue != -1) this.splitContainer_originDataMain.SplitterDistance = nValue; #endif + } + this.UiState = MainForm.AppInfo.GetString( "marcdetailform", "ui_state", @@ -495,8 +499,10 @@ public void SaveSize() { if (this.MainForm != null && this.MainForm.AppInfo != null) { - MainForm.AppInfo.SaveMdiChildFormStates(this, - "mdi_form_state"); + if (this.SupressSizeSetting == false) + { + MainForm.AppInfo.SaveMdiChildFormStates(this, + "mdi_form_state"); #if NO // 保存splitContainer_originDataMain的状态 @@ -505,6 +511,8 @@ public void SaveSize() "splitContainer_originDataMain", this.splitContainer_originDataMain.SplitterDistance); #endif + } + MainForm.AppInfo.SetString( "marcdetailform", "ui_state", @@ -976,7 +984,7 @@ public int LoadDp2Record(dp2SearchForm dp2_searchform, goto ERROR1; } - _processing ++; + _processing++; try { @@ -1581,7 +1589,7 @@ int Set2709OriginText(byte[] baOrigin, } - this.textBox_originData.Text = (baOrigin == null? "" : encoding.GetString(baOrigin)); + this.textBox_originData.Text = (baOrigin == null ? "" : encoding.GetString(baOrigin)); return 0; } @@ -1852,6 +1860,13 @@ private void MarcDetailForm_Activated(object sender, EventArgs e) this.MainForm.CurrentVerifyResultControl = null; } + MarcDetailForm exist_fixed = this.MainForm.FixedMarcDetailForm; + + if (this.Fixed == false && exist_fixed != null) + MainForm.toolStripButton_copyToFixed.Enabled = true; + else + MainForm.toolStripButton_copyToFixed.Enabled = false; + SyncRecord(); } @@ -1966,7 +1981,6 @@ public void SaveRecordToWorksheet() if (dlg.ShowDialog() != DialogResult.OK) return; - bool bExist = File.Exists(dlg.FileName); bool bAppend = false; @@ -2092,7 +2106,7 @@ public void SaveOriginRecordToIso2709() dlg.CrLf = MainForm.LastCrLfIso2709; dlg.RemoveField998 = MainForm.LastRemoveField998; dlg.EncodingListItems = Global.GetEncodingList(true); - dlg.EncodingName = + dlg.EncodingName = (String.IsNullOrEmpty(MainForm.LastEncodingName) == true ? GetEncodingForm.GetEncodingName(preferredEncoding) : MainForm.LastEncodingName); dlg.EncodingComment = "注: 原始编码方式为 " + GetEncodingForm.GetEncodingName(preferredEncoding); dlg.MarcSyntax = "<自动>"; // strPreferedMarcSyntax; @@ -2288,7 +2302,7 @@ public void SaveOriginRecordToIso2709() } if (bAppend == true) - MainForm.MessageText = + MainForm.MessageText = "1条记录成功追加到文件 " + MainForm.LastIso2709FileName + " 尾部"; else MainForm.MessageText = @@ -2477,7 +2491,7 @@ private void MarcEditor_GetConfigFile(object sender, DigitalPlatform.Marc.GetCon return; } - string strPath = this.MainForm.DataDir + "\\" + strMarcSyntaxOID.Replace(".", "_") + "\\" + strCfgFileName; + string strPath = this.MainForm.DataDir + "\\" + strMarcSyntaxOID.Replace(".", "_") + "\\" + strCfgFileName; try { @@ -2608,7 +2622,7 @@ private void MarcEditor_GetConfigDom(object sender, GetConfigDomEventArgs e) } catch (Exception ex) { - e.ErrorInfo = "装载配置文件 '"+strCfgFilePath+"' 到 XMLDOM 的过程中出现错误: " + ex.Message; + e.ErrorInfo = "装载配置文件 '" + strCfgFilePath + "' 到 XMLDOM 的过程中出现错误: " + ex.Message; return; } e.XmlDocument = dom; @@ -2814,7 +2828,7 @@ public int LinkMarcFile() } void LoadLinkedMarcRecord(string strMarc, - byte [] baRecord) + byte[] baRecord) { int nRet = 0; string strError = ""; @@ -2840,7 +2854,7 @@ void LoadLinkedMarcRecord(string strMarc, this.CurrentRecord = null; - + DigitalPlatform.Z3950.Record record = new DigitalPlatform.Z3950.Record(); if (strMarcSyntax == "unimarc" || strMarcSyntax == "") record.m_strSyntaxOID = "1.2.840.10003.5.1"; @@ -2908,7 +2922,7 @@ void LoadLinkedMarcRecord(string strMarc, this.MarcEditor.Focus(); return; - ERROR1: + ERROR1: MessageBox.Show(this, strError); } @@ -2920,7 +2934,7 @@ public int SearchDup(string strSender) string strError = ""; int nRet = 0; - Debug.Assert(strSender == "toolbar" || strSender == "ctrl_d",""); + Debug.Assert(strSender == "toolbar" || strSender == "ctrl_d", ""); string strStartPath = this.SavePath; @@ -3012,13 +3026,13 @@ public int SearchDup(string strSender) } else if (strProtocol.ToLower() == "dp2library") { - dp2SearchForm dp2_searchform = this.GetDp2SearchForm(); + dp2SearchForm dp2_searchform = this.GetDp2SearchForm(); - if (dp2_searchform == null) - { - strError = "没有连接的或者打开的dp2检索窗,无法进行查重"; - goto ERROR1; - } + if (dp2_searchform == null) + { + strError = "没有连接的或者打开的dp2检索窗,无法进行查重"; + goto ERROR1; + } if (String.IsNullOrEmpty(strStartPath) == true) { /* @@ -3068,15 +3082,15 @@ public int SearchDup(string strSender) } - //// - /* - dp2SearchForm dp2_searchform = this.GetDp2SearchForm(); + //// + /* + dp2SearchForm dp2_searchform = this.GetDp2SearchForm(); - if (dp2_searchform == null) - { - strError = "没有连接的或者打开的dp2检索窗,无法进行查重"; - goto ERROR1; - }*/ + if (dp2_searchform == null) + { + strError = "没有连接的或者打开的dp2检索窗,无法进行查重"; + goto ERROR1; + }*/ // 将strPath解析为server url和local path两个部分 string strServerName = ""; @@ -5422,7 +5436,7 @@ public int InitialAutogenAssembly(out string strError) } else { - strError = "暂不支持来自 '"+strProtocol+"' 协议的数据自动创建功能"; + strError = "暂不支持来自 '" + strProtocol + "' 协议的数据自动创建功能"; goto ERROR1; } @@ -5954,10 +5968,10 @@ void m_genDataViewer_TriggerAction(object sender, TriggerActionArgs e) e.sender, e.e); } - catch(Exception ex) + catch (Exception ex) { // 2015/8/24 - strError = "MARC记录窗的记录 '"+this.SavePath+"' 在执行创建数据脚本的时候出现异常: " + ExceptionUtil.GetDebugText(ex) + strError = "MARC记录窗的记录 '" + this.SavePath + "' 在执行创建数据脚本的时候出现异常: " + ExceptionUtil.GetDebugText(ex) + "\r\n\r\n建议检查此书目记录相关的 dp2catalog_marc_autogen.cs 配置文件,试着刷新相关书目库定义,或者与数字平台的工程师取得联系"; goto ERROR1; } @@ -6526,7 +6540,7 @@ public int LoadDtlpTemplate(string strPath) // 将形态为 “本地服务器/中文图书”这样的路径转换为“中文图书@本地服务器” static string CanonicalizePath(string strPath) { - string[] parts = strPath.Split(new char[] {'/'}); + string[] parts = strPath.Split(new char[] { '/' }); if (parts.Length < 2) return ""; @@ -6624,7 +6638,7 @@ public int LoadDp2libraryTemplate(string strPath) if (this.IsValid() == false) return -1; - dbname_dlg.ShowDialog(this); //// + dbname_dlg.ShowDialog(this); //// if (dbname_dlg.DialogResult != DialogResult.OK) @@ -6733,7 +6747,7 @@ public int LoadDp2libraryTemplate(string strPath) temp_dlg.ApCfgTitle = "marcdetailform_selecttemplatedlg"; if (this.IsValid() == false) return -1; - temp_dlg.ShowDialog(this); //// + temp_dlg.ShowDialog(this); //// if (temp_dlg.DialogResult != DialogResult.OK) @@ -7104,7 +7118,7 @@ public int SaveToDp2libraryTemplate(string strPath) if (nRet == -1) goto ERROR1; - MessageBox.Show(this, "修改模板 '"+strCfgFilePath+"' 成功"); + MessageBox.Show(this, "修改模板 '" + strCfgFilePath + "' 成功"); return 0; ERROR1: MessageBox.Show(this, strError); @@ -7296,7 +7310,7 @@ public int VerifyData(object sender, { strError = "服务器上没有定义路径为 '" + strCfgPath + "' 的配置文件(或.fltx配置文件),数据校验无法进行"; goto ERROR1; - } + } if (nRet == -1) goto ERROR1; @@ -7630,7 +7644,7 @@ void DoViewVerifyResult(bool bOpenWindow) m_verifyViewer.FormClosed -= new FormClosedEventHandler(m_viewer_FormClosed); m_verifyViewer.FormClosed += new FormClosedEventHandler(m_viewer_FormClosed); - + m_verifyViewer.Locate -= new LocateEventHandler(m_viewer_Locate); m_verifyViewer.Locate += new LocateEventHandler(m_viewer_Locate); @@ -7907,7 +7921,7 @@ void m_macroutil_ParseOneMacro(object sender, ParseOneMacroEventArgs e) return; } - ERROR1: + ERROR1: e.Canceled = true; // 不能解释处理 return; } @@ -8104,10 +8118,10 @@ void DisplayHtml(string strMARC, string strSytaxOID) { string strError = ""; string strHtmlString = ""; - // return: - // -1 出错 - // 0 .fltx 文件没有找到 - // 1 成功 + // return: + // -1 出错 + // 0 .fltx 文件没有找到 + // 1 成功 int nRet = this.MainForm.BuildMarcHtmlText( strSytaxOID, strMARC, @@ -8340,7 +8354,7 @@ int BuildMarc21Html(string strMARC, if (nRet == -1) return -1; - text.Append("" + GetHeadString (false)+ "
" + strContent + "" + strContent + "
" + (nStart + 1).ToString() + "" + HttpUtility.HtmlEncode(GetOperTypeName(item.Action)) + "
借还Borrow and Return册登记Item Registration
"); + text.Append("" + GetHeadString(false) + "
"); foreach (NameValueLine line in results) { text.Append(""); @@ -8730,7 +8744,79 @@ static int ScriptMarc21(string strMARC, #endregion + public bool GetQueryContent(out string strUse, + out string strWord) + { + strUse = ""; + strWord = ""; + + string strError = ""; + string strMarcSyntax = ""; + string strMarcSyntaxOID = this.GetCurrentMarcSyntaxOID(out strError); + if (String.IsNullOrEmpty(strMarcSyntaxOID) == true) + { + /* + strError = "当前MARC syntax OID为空,无法判断MARC具体格式"; + goto ERROR1; + * */ + return false; + } + + if (strMarcSyntaxOID == "1.2.840.10003.5.1") + strMarcSyntax = "unimarc"; + if (strMarcSyntaxOID == "1.2.840.10003.5.10") + strMarcSyntax = "usmarc"; + + string strMARC = this.MarcEditor.Marc; + MarcRecord record = new MarcRecord(strMARC); + + if (strMarcSyntax == "unimarc") + { + strWord = record.select("field[@name='010']/subfield[@name='a']").FirstContent; + if (string.IsNullOrEmpty(strWord) == true) + { + strWord = record.select("field[@name='200']/subfield[@name='a']").FirstContent; + strUse = "title"; + } + else + strUse = "ISBN"; + if (string.IsNullOrEmpty(strWord) == true) + return false; + + return true; + } + if (strMarcSyntax == "usmarc") + { + strWord = record.select("field[@name='020']/subfield[@name='a']").FirstContent; + if (string.IsNullOrEmpty(strWord) == true) + { + strWord = record.select("field[@name='245']/subfield[@name='a']").FirstContent; + strUse = "title"; + } + else + strUse = "ISBN"; + if (string.IsNullOrEmpty(strWord) == true) + return false; + + return true; + } + return false; + } + public void CopyMarcToFixed() + { + MarcDetailForm exist_fixed = this.MainForm.FixedMarcDetailForm; + if (exist_fixed == null) + { + MessageBox.Show(this, "固定记录窗不存在,无法进行复制操作"); + return; + } + + string strMARC = this.MarcEditor.Marc; + // TODO: 需要检查 MARC 格式是否一致 + exist_fixed.MarcEditor.Marc = strMARC; + exist_fixed.ShowMessage("MARC 编辑器中已成功复制了新内容", "green", true); + } } public class VerifyHost diff --git a/dp2Catalog/MdiForm/MyForm.cs b/dp2Catalog/MdiForm/MyForm.cs index ef20fd18e..29e132ccd 100644 --- a/dp2Catalog/MdiForm/MyForm.cs +++ b/dp2Catalog/MdiForm/MyForm.cs @@ -1,12 +1,13 @@ -using DigitalPlatform; -using DigitalPlatform.CommonControl; -using System; +using System; using System.Collections.Generic; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; +using DigitalPlatform; +using DigitalPlatform.CommonControl; + namespace dp2Catalog { /// @@ -52,6 +53,15 @@ public virtual bool Floating set; } + /// + /// 窗口是否为固定窗口。所谓固定窗口就是固定在某一侧的窗口 + /// + public virtual bool Fixed + { + get; + set; + } + /// /// 界面语言 /// diff --git a/dp2Catalog/Z39.50/ZQueryControl.cs b/dp2Catalog/Z39.50/ZQueryControl.cs index 862f3126f..cbcbccb20 100644 --- a/dp2Catalog/Z39.50/ZQueryControl.cs +++ b/dp2Catalog/Z39.50/ZQueryControl.cs @@ -103,7 +103,7 @@ static string GetLogicString(string strText) return strText.Trim(); } - // XMLʽ仯Ϊʽʽ + // XML ʽ仯Ϊʽʽ public static int GetQueryString( FromCollection Froms, string strQueryXml, @@ -212,6 +212,7 @@ public static int GetQueryString( return 1; } + // XML ʽ // paramers: // bOptimize ǷŻ public string GetContent(bool bOptimize) @@ -260,6 +261,37 @@ public void Clear() } } + public void SetContent(string strUse, string strWord) + { + this.Clear(); + { + Line line = this.Lines[0]; + + // line.comboBox_logicOperator.Text = ""; + line.textBox_word.Text = strWord; + SelectComboBoxValue(line.comboBox_from, strUse); + } + } + + static void SelectComboBoxValue(ComboBox combobox, string strValue) + { + strValue = strValue.ToLower(); + foreach(string s in combobox.Items) + { + string strLeft; + string strRight; + StringUtil.ParseTwoPart(s, "-", out strLeft, out strRight); + strLeft = strLeft.Trim(); + strRight = strRight.Trim(); + if (strLeft.ToLower() == strValue) + { + combobox.Text = s; + return; + } + } + } + + // XML ʽõؼ // ܻ׳쳣 public void SetContent(string strContentXml) { @@ -281,7 +313,6 @@ public void SetContent(string strContentXml) XmlNode node = nodes[i]; - line.comboBox_logicOperator.Text = DomUtil.GetAttr(node, "logic"); line.textBox_word.Text = DomUtil.GetAttr(node, "word"); line.comboBox_from.Text = DomUtil.GetAttr(node, "from"); @@ -310,10 +341,8 @@ public override bool Focused return false; } } - } - public class Line { public ComboBox comboBox_logicOperator = null; diff --git a/dp2Catalog/Z39.50/ZSearchForm.cs b/dp2Catalog/Z39.50/ZSearchForm.cs index dd6278523..2a6793a04 100644 --- a/dp2Catalog/Z39.50/ZSearchForm.cs +++ b/dp2Catalog/Z39.50/ZSearchForm.cs @@ -844,6 +844,12 @@ public int DoSearchOneServer() return -1; } + // 2016/4/8 + public void SetQueryContent(string strUse, string strWord) + { + this.queryControl1.SetContent(strUse, strWord); + } + // 准备检索一个服务器 // 并不启动检索 // thread: @@ -877,7 +883,6 @@ public int PrepareSearchOneServer( + (connection.TargetInfo.IsbnForce13 == true ? "force13," : "") + (connection.TargetInfo.IsbnWild == true ? "wild," : ""); - nRet = ZQueryControl.GetQueryString( this.MainForm.Froms, strQueryXml, @@ -3469,12 +3474,12 @@ record = (DigitalPlatform.Z3950.Record) return; } + MarcDetailForm exist_fixed = this.MainForm.FixedMarcDetailForm; MarcDetailForm form = new MarcDetailForm(); form.MdiParent = this.MainForm; form.MainForm = this.MainForm; - // 继承自动识别的OID if (connection.TargetInfo != null && connection.TargetInfo.DetectMarcSyntax == true) @@ -3482,7 +3487,22 @@ record = (DigitalPlatform.Z3950.Record) //form.AutoDetectedMarcSyntaxOID = record.AutoDetectedSyntaxOID; form.UseAutoDetectedMarcSyntaxOID = true; } + + // 在已经有左侧窗口的情况下,普通窗口需要显示在右侧 + if (exist_fixed != null) + { + if (exist_fixed != null) + exist_fixed.Activate(); + + form.SupressSizeSetting = true; + this.MainForm.SetMdiToNormal(); + } form.Show(); + // 在已经有左侧窗口的情况下,普通窗口需要显示在右侧 + if (exist_fixed != null) + { + this.MainForm.SetFixedPosition(form, "right"); + } form.LoadRecord(this, index); } @@ -3651,9 +3671,9 @@ record = (DigitalPlatform.Z3950.Record) } { + MarcDetailForm exist_fixed = this.MainForm.FixedMarcDetailForm; MarcDetailForm form = new MarcDetailForm(); - form.MdiParent = this.MainForm; form.MainForm = this.MainForm; @@ -3665,7 +3685,22 @@ record = (DigitalPlatform.Z3950.Record) form.UseAutoDetectedMarcSyntaxOID = true; } + + // 在已经有左侧窗口的情况下,普通窗口需要显示在右侧 + if (exist_fixed != null) + { + if (exist_fixed != null) + exist_fixed.Activate(); + + form.SupressSizeSetting = true; + this.MainForm.SetMdiToNormal(); + } form.Show(); + // 在已经有左侧窗口的情况下,普通窗口需要显示在右侧 + if (exist_fixed != null) + { + this.MainForm.SetFixedPosition(form, "right"); + } form.LoadRecord(this, index); } @@ -3758,6 +3793,8 @@ private void ZSearchForm_Activated(object sender, EventArgs e) this.MainForm.toolButton_dup.Enabled = false; this.MainForm.toolButton_verify.Enabled = false; this.MainForm.toolButton_refresh.Enabled = false; + + MainForm.toolStripButton_copyToFixed.Enabled = false; } diff --git a/dp2Catalog/dp2/dp2SearchForm.cs b/dp2Catalog/dp2/dp2SearchForm.cs index 1934c99cd..90904fd5c 100644 --- a/dp2Catalog/dp2/dp2SearchForm.cs +++ b/dp2Catalog/dp2/dp2SearchForm.cs @@ -3346,7 +3346,7 @@ private void listView_browse_DoubleClick(object sender, EventArgs e) } LoadDetail(nIndex, - LoadToExistDetailWindow == true ? false : true); + LoadToExistDetailWindow == true ? "exist" : "new"); } finally { @@ -3520,9 +3520,12 @@ bool HasTopDetailForm(int index) } // parameters: + // strStyle 打开的风格 new/exist/fixed // bOpendNew 是否打开新的详细窗 void LoadDetail(int index, - bool bOpenNew = true) + string strStyle = "new" + // bool bOpenNew = true + ) { // 取出记录路径,析出书目库名,然后看这个书目库的syntax // 可能装入MARC和DC两种不同的窗口 @@ -3551,9 +3554,15 @@ void LoadDetail(int index, { MarcDetailForm form = null; + MarcDetailForm exist_fixed = this.MainForm.FixedMarcDetailForm; - if (bOpenNew == false) + if (strStyle == "exist") form = this.MainForm.TopMarcDetailForm; + else if (strStyle == "fixed") + form = exist_fixed; + + if (exist_fixed != null) + exist_fixed.Activate(); if (form == null) { @@ -3562,11 +3571,49 @@ void LoadDetail(int index, form.MdiParent = this.MainForm; form.MainForm = this.MainForm; + if (strStyle == "fixed") + { + form.Fixed = true; + form.SupressSizeSetting = true; + this.MainForm.SetMdiToNormal(); + } + else + { + // 在已经有左侧窗口的情况下,普通窗口需要显示在右侧 + if (exist_fixed != null) + { + form.SupressSizeSetting = true; + this.MainForm.SetMdiToNormal(); + } + } form.Show(); + if (strStyle == "fixed") + this.MainForm.SetFixedPosition(form, "left"); + else + { + // 在已经有左侧窗口的情况下,普通窗口需要显示在右侧 + if (exist_fixed != null) + { + this.MainForm.SetFixedPosition(form, "right"); + } + } } else + { form.Activate(); - + if (strStyle == "fixed") + { + this.MainForm.SetMdiToNormal(); + } + else + { + // 在已经有左侧窗口的情况下,普通窗口需要显示在右侧 + if (exist_fixed != null) + { + this.MainForm.SetMdiToNormal(); + } + } + } // MARC Syntax OID // 需要建立数据库配置参数,从中得到MARC格式 @@ -3576,10 +3623,9 @@ void LoadDetail(int index, } else if (strSyntax.ToLower() == "dc") { - DcForm form = null; - if (bOpenNew == false) + if (strStyle == "exist") form = this.MainForm.TopDcForm; if (form == null) @@ -3608,6 +3654,7 @@ void LoadDetail(int index, } + /* // 获得书目记录的XML格式 // parameters: @@ -4889,6 +4936,8 @@ private void dp2SearchForm_Activated(object sender, EventArgs e) MainForm.toolButton_refresh.Enabled = true; MainForm.toolButton_loadFullRecord.Enabled = false; + + MainForm.toolStripButton_copyToFixed.Enabled = false; } private void listView_browse_SelectedIndexChanged(object sender, EventArgs e) @@ -5487,6 +5536,16 @@ private void listView_browse_MouseUp(object sender, MouseEventArgs e) ToolStripSeparator sep = new ToolStripSeparator(); contextMenu.Items.Add(sep); + menuItem = new ToolStripMenuItem("装入左侧固定记录窗(&L)"); + menuItem.Click += new System.EventHandler(this.menu_loadToFixedDetailForm_Click); + if (nSelectedCount == 0) + menuItem.Enabled = false; + contextMenu.Items.Add(menuItem); + + // --- + sep = new ToolStripSeparator(); + contextMenu.Items.Add(sep); + menuItem = new ToolStripMenuItem("剪切(&T)"); menuItem.Click += new System.EventHandler(this.menu_cutToClipboard_Click); if (nSelectedCount == 0) @@ -8102,6 +8161,21 @@ void ConvertPastedLines() MessageBox.Show(this, strError); } + // 装入左侧固定的记录窗 + void menu_loadToFixedDetailForm_Click(object sender, EventArgs e) + { + int nIndex = -1; + if (this.listView_browse.SelectedIndices.Count > 0) + nIndex = this.listView_browse.SelectedIndices[0]; + else + { + if (this.listView_browse.FocusedItem == null) + return; + nIndex = this.listView_browse.Items.IndexOf(this.listView_browse.FocusedItem); + } + LoadDetail(nIndex, "fixed"); + } + void menu_loadToOpenedDetailForm_Click(object sender, EventArgs e) { int nIndex = -1; @@ -8113,8 +8187,7 @@ void menu_loadToOpenedDetailForm_Click(object sender, EventArgs e) return; nIndex = this.listView_browse.Items.IndexOf(this.listView_browse.FocusedItem); } - LoadDetail(nIndex, - false); + LoadDetail(nIndex, "exist"); } @@ -8129,8 +8202,7 @@ void menu_loadToNewDetailForm_Click(object sender, EventArgs e) return; nIndex = this.listView_browse.Items.IndexOf(this.listView_browse.FocusedItem); } - LoadDetail(nIndex, - true); + LoadDetail(nIndex, "new"); } void menuItem_selectAll_Click(object sender, diff --git a/dp2Circulation/dp2Circulation.csproj b/dp2Circulation/dp2Circulation.csproj index 32b0ad44a..4801b58b5 100644 --- a/dp2Circulation/dp2Circulation.csproj +++ b/dp2Circulation/dp2Circulation.csproj @@ -51,7 +51,7 @@ dp2 V2 true publish.htm - 38 + 40 2.10.0.%2a false true From e863c8fc24675cebf03d7a03d008a738a77dd4f2 Mon Sep 17 00:00:00 2001 From: XieTao Date: Fri, 8 Apr 2016 14:26:04 +0800 Subject: [PATCH 08/10] =?UTF-8?q?=E5=AE=8C=E5=96=84=20dp2Catalog=20?= =?UTF-8?q?=E5=9B=BA=E5=AE=9A=E8=AE=B0=E5=BD=95=E7=AA=97=E7=9B=B8=E5=85=B3?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dp2Catalog/Amazon/AmazonSearchForm.cs | 23 ++++++++++++++++++ dp2Catalog/Amazon/AmazonSimpleQueryControl.cs | 5 ++++ dp2Catalog/MainForm/MainForm.cs | 24 +++++++++++++++++++ dp2Catalog/dp2Catalog.csproj | 2 +- 4 files changed, 53 insertions(+), 1 deletion(-) diff --git a/dp2Catalog/Amazon/AmazonSearchForm.cs b/dp2Catalog/Amazon/AmazonSearchForm.cs index 9b8bd982f..55ba6b7d7 100644 --- a/dp2Catalog/Amazon/AmazonSearchForm.cs +++ b/dp2Catalog/Amazon/AmazonSearchForm.cs @@ -685,6 +685,13 @@ public void SaveSize() } + // 2016/4/8 + public void SetQueryContent(string strUse, string strWord) + { + this.tabControl_query.SelectedTab = this.tabPage_simple; + this.amazonSimpleQueryControl_simple.SetContent(strUse, strWord); + } + // 准备用于首次检索的 URL int GetSimpleSearchRequestUrl(out string strUrl, out string strError) @@ -2058,6 +2065,8 @@ void LoadDetail(int index, } { + MarcDetailForm exist_fixed = this.MainForm.FixedMarcDetailForm; + MarcDetailForm form = new MarcDetailForm(); form.MdiParent = this.m_mainForm; @@ -2071,7 +2080,21 @@ void LoadDetail(int index, form.AutoDetectedMarcSyntaxOID = record.AutoDetectedSyntaxOID; } #endif + // 在已经有左侧窗口的情况下,普通窗口需要显示在右侧 + if (exist_fixed != null) + { + if (exist_fixed != null) + exist_fixed.Activate(); + + form.SupressSizeSetting = true; + this.MainForm.SetMdiToNormal(); + } form.Show(); + // 在已经有左侧窗口的情况下,普通窗口需要显示在右侧 + if (exist_fixed != null) + { + this.MainForm.SetFixedPosition(form, "right"); + } form.LoadRecord(this, index); } diff --git a/dp2Catalog/Amazon/AmazonSimpleQueryControl.cs b/dp2Catalog/Amazon/AmazonSimpleQueryControl.cs index d39a16a8d..1c4bb49fc 100644 --- a/dp2Catalog/Amazon/AmazonSimpleQueryControl.cs +++ b/dp2Catalog/Amazon/AmazonSimpleQueryControl.cs @@ -198,6 +198,11 @@ void FillMatchStyles() this.tabComboBox_match.Text = matchs[0]; } + public void SetContent(string strUse, string strWord) + { + SetContentString(strWord + "^" + strUse); + } + // 构造检索式 public int BuildQueryString(out string strText, out string strError) diff --git a/dp2Catalog/MainForm/MainForm.cs b/dp2Catalog/MainForm/MainForm.cs index b6d7e2956..b381fd5cb 100644 --- a/dp2Catalog/MainForm/MainForm.cs +++ b/dp2Catalog/MainForm/MainForm.cs @@ -4412,7 +4412,31 @@ private void toolStripButton_searchZ_Click(object sender, EventArgs e) // 用亚马逊检索当前记录 private void toolStripButton_searchA_Click(object sender, EventArgs e) { + // 从当前记录窗得到检索词 + Form active = this.ActiveMdiChild; + if (active == null) + return; + + string strUse = ""; + string strQueryWord = ""; + if (active is MarcDetailForm) + { + MarcDetailForm detailform = active as MarcDetailForm; + bool bRet = detailform.GetQueryContent(out strUse, + out strQueryWord); + if (bRet == false) + { + MessageBox.Show(this, "无法从当前记录窗 MARC 记录中获得检索词"); + return; + } + } + AmazonSearchForm searchform = GetAmazonSearchForm(); + if (searchform.WindowState == FormWindowState.Minimized) + searchform.WindowState = FormWindowState.Normal; + searchform.SetQueryContent(strUse, strQueryWord); + searchform.Activate(); + searchform.DoSearch(); } // 从当前窗口复制到固定窗口 diff --git a/dp2Catalog/dp2Catalog.csproj b/dp2Catalog/dp2Catalog.csproj index 5c20890c5..b1a474a09 100644 --- a/dp2Catalog/dp2Catalog.csproj +++ b/dp2Catalog/dp2Catalog.csproj @@ -50,7 +50,7 @@ dp2 V2 true publish.htm - 6 + 7 2.5.0.%2a false true From a665bc635c2bcbf3609847b7518259a3659f015f Mon Sep 17 00:00:00 2001 From: XieTao Date: Mon, 11 Apr 2016 21:06:51 +0800 Subject: [PATCH 09/10] =?UTF-8?q?=E5=A4=A7=E9=87=8F=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../LibraryChannel.cs | 63 +++ .../localhost/LibraryService.wsdl | 86 ++++ .../Service References/localhost/Reference.cs | 208 ++++++++++ .../localhost/metadata.wsdl | 10 + .../localhost/metadata1.xsd | 292 +++++++------- .../localhost/metadata5.xsd | 238 ++++++----- DigitalPlatform.LibraryServer/AppReader.cs | 268 ++++++++++++- DigitalPlatform.LibraryServer/AppScript.cs | 48 ++- .../DigitalPlatform.LibraryServer.csproj | 1 + .../LibraryApplication.cs | 71 +++- .../ReadersMonitor.cs | 186 ++++++++- .../ILibraryService.cs | 10 + .../ILibraryServiceREST.cs | 10 + .../LibraryService.cs | 55 +++ .../DongshifangMessageHost.cs | 377 ++++++++++++++++++ .../DongshifangMessageInterface.csproj | 67 ++++ .../Properties/AssemblyInfo.cs | 36 ++ dp2-net40.sln | 17 + .../SearchForms/BiblioSearchForm.cs | 236 ++++++++++- .../OpenBiblioDumpFileDialog.Designer.cs | 232 +++++++++++ .../SearchForms/OpenBiblioDumpFileDialog.cs | 235 +++++++++++ .../SearchForms/OpenBiblioDumpFileDialog.resx | 120 ++++++ dp2Circulation/dp2Circulation.csproj | 9 + dp2Installer/dp2Installer.csproj | 2 +- .../library_data/templates/reader/keys | 2 +- .../templates/reader/keys_recover | 2 +- dp2LibraryXE/dp2LibraryXE.csproj | 2 +- .../library_data/templates/reader/keys | 2 +- .../templates/reader/keys_recover | 2 +- 29 files changed, 2578 insertions(+), 309 deletions(-) create mode 100644 DongshifangMessageInterface/DongshifangMessageHost.cs create mode 100644 DongshifangMessageInterface/DongshifangMessageInterface.csproj create mode 100644 DongshifangMessageInterface/Properties/AssemblyInfo.cs create mode 100644 dp2Circulation/SearchForms/OpenBiblioDumpFileDialog.Designer.cs create mode 100644 dp2Circulation/SearchForms/OpenBiblioDumpFileDialog.cs create mode 100644 dp2Circulation/SearchForms/OpenBiblioDumpFileDialog.resx diff --git a/DigitalPlatform.LibraryClient/LibraryChannel.cs b/DigitalPlatform.LibraryClient/LibraryChannel.cs index bd47540b9..25ecf5f98 100644 --- a/DigitalPlatform.LibraryClient/LibraryChannel.cs +++ b/DigitalPlatform.LibraryClient/LibraryChannel.cs @@ -4217,6 +4217,69 @@ public long ResetPassword( } } + public long BindPatron( + DigitalPlatform.Stop stop, + string strAction, + string strQueryWord, + string strPassword, + string strBindingID, + string strStyle, + string strResultTypeList, + out string[] results, + out string strError) + { + strError = ""; + results = null; + + REDO: + try + { + IAsyncResult soapresult = this.ws.BeginBindPatron( + strAction, + strQueryWord, + strPassword, + strBindingID, + strStyle, + strResultTypeList, + null, + null); + for (; ; ) + { + DoIdle(); // 出让控制权,避免CPU资源耗费过度 + + if (soapresult.IsCompleted) + break; + } + if (this.m_ws == null) + { + strError = "用户中断"; + this.ErrorCode = localhost.ErrorCode.RequestCanceled; + return -1; + } + + LibraryServerResult result = this.ws.EndBindPatron( + out results, + soapresult); + if (result.Value == -1 && result.ErrorCode == ErrorCode.NotLogin) + { + if (DoNotLogin(ref strError) == 1) + goto REDO; + return -1; + } + strError = result.ErrorInfo; + this.ErrorCode = result.ErrorCode; + this.ClearRedoCount(); + return result.Value; + } + catch (Exception ex) + { + int nRet = ConvertWebError(ex, out strError); + if (nRet == 0) + return -1; + goto REDO; + } + } + // 清除所有数据库内的数据 /// /// 清除所有数据库的记录 diff --git a/DigitalPlatform.LibraryClient/Service References/localhost/LibraryService.wsdl b/DigitalPlatform.LibraryClient/Service References/localhost/LibraryService.wsdl index c4092de49..0d0ff9cc2 100644 --- a/DigitalPlatform.LibraryClient/Service References/localhost/LibraryService.wsdl +++ b/DigitalPlatform.LibraryClient/Service References/localhost/LibraryService.wsdl @@ -607,6 +607,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -3906,6 +3944,12 @@ + + + + + + @@ -4466,6 +4510,10 @@ + + + + @@ -4926,6 +4974,15 @@ + + + + + + + + + @@ -5809,6 +5866,15 @@ + + + + + + + + + @@ -6718,6 +6784,17 @@ + + + + + + + + + + + @@ -7769,6 +7846,15 @@ + + + + + + + + + diff --git a/DigitalPlatform.LibraryClient/Service References/localhost/Reference.cs b/DigitalPlatform.LibraryClient/Service References/localhost/Reference.cs index f26ae84b1..c95686075 100644 --- a/DigitalPlatform.LibraryClient/Service References/localhost/Reference.cs +++ b/DigitalPlatform.LibraryClient/Service References/localhost/Reference.cs @@ -3277,6 +3277,14 @@ public interface dp2libraryREST { DigitalPlatform.LibraryClient.localhost.LibraryServerResult EndSearchCharging(out DigitalPlatform.LibraryClient.localhost.ChargingItemWrapper[] results, System.IAsyncResult result); + [System.ServiceModel.OperationContractAttribute(Action="http://dp2003.com/dp2library/rest/dp2libraryREST/BindPatron", ReplyAction="http://dp2003.com/dp2library/rest/dp2libraryREST/BindPatronResponse")] + DigitalPlatform.LibraryClient.localhost.LibraryServerResult BindPatron(out string[] results, string strAction, string strQueryWord, string strPassword, string strBindingID, string strStyle, string strResultTypeList); + + [System.ServiceModel.OperationContractAttribute(AsyncPattern=true, Action="http://dp2003.com/dp2library/rest/dp2libraryREST/BindPatron", ReplyAction="http://dp2003.com/dp2library/rest/dp2libraryREST/BindPatronResponse")] + System.IAsyncResult BeginBindPatron(string strAction, string strQueryWord, string strPassword, string strBindingID, string strStyle, string strResultTypeList, System.AsyncCallback callback, object asyncState); + + DigitalPlatform.LibraryClient.localhost.LibraryServerResult EndBindPatron(out string[] results, System.IAsyncResult result); + [System.ServiceModel.OperationContractAttribute(Action="http://dp2003.com/dp2library/rest/dp2libraryREST/GetVersion", ReplyAction="http://dp2003.com/dp2library/rest/dp2libraryREST/GetVersionResponse")] DigitalPlatform.LibraryClient.localhost.LibraryServerResult GetVersion(out string uid); @@ -4364,6 +4372,32 @@ public DigitalPlatform.LibraryClient.localhost.LibraryServerResult Result { } } + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")] + public partial class BindPatronCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { + + private object[] results1; + + public BindPatronCompletedEventArgs(object[] results, System.Exception exception, bool cancelled, object userState) : + base(exception, cancelled, userState) { + this.results1 = results; + } + + public string[] results { + get { + base.RaiseExceptionIfNecessary(); + return ((string[])(this.results1[0])); + } + } + + public DigitalPlatform.LibraryClient.localhost.LibraryServerResult Result { + get { + base.RaiseExceptionIfNecessary(); + return ((DigitalPlatform.LibraryClient.localhost.LibraryServerResult)(this.results1[1])); + } + } + } + [System.Diagnostics.DebuggerStepThroughAttribute()] [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")] public partial class GetVersionCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { @@ -6819,6 +6853,12 @@ public partial class dp2libraryRESTClient : System.ServiceModel.ClientBase SearchChargingCompleted; + public event System.EventHandler BindPatronCompleted; + public event System.EventHandler GetVersionCompleted; public event System.EventHandler LoginCompleted; @@ -8306,6 +8348,68 @@ public void SearchChargingAsync(string patronBarcode, string timeRange, string a count}, this.onEndSearchChargingDelegate, this.onSearchChargingCompletedDelegate, userState); } + public DigitalPlatform.LibraryClient.localhost.LibraryServerResult BindPatron(out string[] results, string strAction, string strQueryWord, string strPassword, string strBindingID, string strStyle, string strResultTypeList) { + return base.Channel.BindPatron(out results, strAction, strQueryWord, strPassword, strBindingID, strStyle, strResultTypeList); + } + + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] + public System.IAsyncResult BeginBindPatron(string strAction, string strQueryWord, string strPassword, string strBindingID, string strStyle, string strResultTypeList, System.AsyncCallback callback, object asyncState) { + return base.Channel.BeginBindPatron(strAction, strQueryWord, strPassword, strBindingID, strStyle, strResultTypeList, callback, asyncState); + } + + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] + public DigitalPlatform.LibraryClient.localhost.LibraryServerResult EndBindPatron(out string[] results, System.IAsyncResult result) { + return base.Channel.EndBindPatron(out results, result); + } + + private System.IAsyncResult OnBeginBindPatron(object[] inValues, System.AsyncCallback callback, object asyncState) { + string strAction = ((string)(inValues[0])); + string strQueryWord = ((string)(inValues[1])); + string strPassword = ((string)(inValues[2])); + string strBindingID = ((string)(inValues[3])); + string strStyle = ((string)(inValues[4])); + string strResultTypeList = ((string)(inValues[5])); + return this.BeginBindPatron(strAction, strQueryWord, strPassword, strBindingID, strStyle, strResultTypeList, callback, asyncState); + } + + private object[] OnEndBindPatron(System.IAsyncResult result) { + string[] results = this.GetDefaultValueForInitialization(); + DigitalPlatform.LibraryClient.localhost.LibraryServerResult retVal = this.EndBindPatron(out results, result); + return new object[] { + results, + retVal}; + } + + private void OnBindPatronCompleted(object state) { + if ((this.BindPatronCompleted != null)) { + InvokeAsyncCompletedEventArgs e = ((InvokeAsyncCompletedEventArgs)(state)); + this.BindPatronCompleted(this, new BindPatronCompletedEventArgs(e.Results, e.Error, e.Cancelled, e.UserState)); + } + } + + public void BindPatronAsync(string strAction, string strQueryWord, string strPassword, string strBindingID, string strStyle, string strResultTypeList) { + this.BindPatronAsync(strAction, strQueryWord, strPassword, strBindingID, strStyle, strResultTypeList, null); + } + + public void BindPatronAsync(string strAction, string strQueryWord, string strPassword, string strBindingID, string strStyle, string strResultTypeList, object userState) { + if ((this.onBeginBindPatronDelegate == null)) { + this.onBeginBindPatronDelegate = new BeginOperationDelegate(this.OnBeginBindPatron); + } + if ((this.onEndBindPatronDelegate == null)) { + this.onEndBindPatronDelegate = new EndOperationDelegate(this.OnEndBindPatron); + } + if ((this.onBindPatronCompletedDelegate == null)) { + this.onBindPatronCompletedDelegate = new System.Threading.SendOrPostCallback(this.OnBindPatronCompleted); + } + base.InvokeAsync(this.onBeginBindPatronDelegate, new object[] { + strAction, + strQueryWord, + strPassword, + strBindingID, + strStyle, + strResultTypeList}, this.onEndBindPatronDelegate, this.onBindPatronCompletedDelegate, userState); + } + public DigitalPlatform.LibraryClient.localhost.LibraryServerResult GetVersion(out string uid) { return base.Channel.GetVersion(out uid); } @@ -13362,6 +13466,14 @@ public interface dp2library { DigitalPlatform.LibraryClient.localhost.LibraryServerResult EndSearchCharging(out DigitalPlatform.LibraryClient.localhost.ChargingItemWrapper[] results, System.IAsyncResult result); + [System.ServiceModel.OperationContractAttribute(Action="http://dp2003.com/dp2library/dp2library/BindPatron", ReplyAction="http://dp2003.com/dp2library/dp2library/BindPatronResponse")] + DigitalPlatform.LibraryClient.localhost.LibraryServerResult BindPatron(out string[] results, string strAction, string strQueryWord, string strPassword, string strBindingID, string strStyle, string strResultTypeList); + + [System.ServiceModel.OperationContractAttribute(AsyncPattern=true, Action="http://dp2003.com/dp2library/dp2library/BindPatron", ReplyAction="http://dp2003.com/dp2library/dp2library/BindPatronResponse")] + System.IAsyncResult BeginBindPatron(string strAction, string strQueryWord, string strPassword, string strBindingID, string strStyle, string strResultTypeList, System.AsyncCallback callback, object asyncState); + + DigitalPlatform.LibraryClient.localhost.LibraryServerResult EndBindPatron(out string[] results, System.IAsyncResult result); + [System.ServiceModel.OperationContractAttribute(Action="http://dp2003.com/dp2library/dp2library/GetVersion", ReplyAction="http://dp2003.com/dp2library/dp2library/GetVersionResponse")] DigitalPlatform.LibraryClient.localhost.LibraryServerResult GetVersion(out string uid); @@ -14443,6 +14555,32 @@ public DigitalPlatform.LibraryClient.localhost.LibraryServerResult Result { } } + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")] + public partial class BindPatronCompletedEventArgs1 : System.ComponentModel.AsyncCompletedEventArgs { + + private object[] results1; + + public BindPatronCompletedEventArgs1(object[] results, System.Exception exception, bool cancelled, object userState) : + base(exception, cancelled, userState) { + this.results1 = results; + } + + public string[] results { + get { + base.RaiseExceptionIfNecessary(); + return ((string[])(this.results1[0])); + } + } + + public DigitalPlatform.LibraryClient.localhost.LibraryServerResult Result { + get { + base.RaiseExceptionIfNecessary(); + return ((DigitalPlatform.LibraryClient.localhost.LibraryServerResult)(this.results1[1])); + } + } + } + [System.Diagnostics.DebuggerStepThroughAttribute()] [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")] public partial class GetVersionCompletedEventArgs1 : System.ComponentModel.AsyncCompletedEventArgs { @@ -16898,6 +17036,12 @@ public partial class dp2libraryClient : System.ServiceModel.ClientBase SearchChargingCompleted; + public event System.EventHandler BindPatronCompleted; + public event System.EventHandler GetVersionCompleted; public event System.EventHandler LoginCompleted; @@ -18385,6 +18531,68 @@ public void SearchChargingAsync(string patronBarcode, string timeRange, string a count}, this.onEndSearchChargingDelegate, this.onSearchChargingCompletedDelegate, userState); } + public DigitalPlatform.LibraryClient.localhost.LibraryServerResult BindPatron(out string[] results, string strAction, string strQueryWord, string strPassword, string strBindingID, string strStyle, string strResultTypeList) { + return base.Channel.BindPatron(out results, strAction, strQueryWord, strPassword, strBindingID, strStyle, strResultTypeList); + } + + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] + public System.IAsyncResult BeginBindPatron(string strAction, string strQueryWord, string strPassword, string strBindingID, string strStyle, string strResultTypeList, System.AsyncCallback callback, object asyncState) { + return base.Channel.BeginBindPatron(strAction, strQueryWord, strPassword, strBindingID, strStyle, strResultTypeList, callback, asyncState); + } + + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] + public DigitalPlatform.LibraryClient.localhost.LibraryServerResult EndBindPatron(out string[] results, System.IAsyncResult result) { + return base.Channel.EndBindPatron(out results, result); + } + + private System.IAsyncResult OnBeginBindPatron(object[] inValues, System.AsyncCallback callback, object asyncState) { + string strAction = ((string)(inValues[0])); + string strQueryWord = ((string)(inValues[1])); + string strPassword = ((string)(inValues[2])); + string strBindingID = ((string)(inValues[3])); + string strStyle = ((string)(inValues[4])); + string strResultTypeList = ((string)(inValues[5])); + return this.BeginBindPatron(strAction, strQueryWord, strPassword, strBindingID, strStyle, strResultTypeList, callback, asyncState); + } + + private object[] OnEndBindPatron(System.IAsyncResult result) { + string[] results = this.GetDefaultValueForInitialization(); + DigitalPlatform.LibraryClient.localhost.LibraryServerResult retVal = this.EndBindPatron(out results, result); + return new object[] { + results, + retVal}; + } + + private void OnBindPatronCompleted(object state) { + if ((this.BindPatronCompleted != null)) { + InvokeAsyncCompletedEventArgs e = ((InvokeAsyncCompletedEventArgs)(state)); + this.BindPatronCompleted(this, new BindPatronCompletedEventArgs1(e.Results, e.Error, e.Cancelled, e.UserState)); + } + } + + public void BindPatronAsync(string strAction, string strQueryWord, string strPassword, string strBindingID, string strStyle, string strResultTypeList) { + this.BindPatronAsync(strAction, strQueryWord, strPassword, strBindingID, strStyle, strResultTypeList, null); + } + + public void BindPatronAsync(string strAction, string strQueryWord, string strPassword, string strBindingID, string strStyle, string strResultTypeList, object userState) { + if ((this.onBeginBindPatronDelegate == null)) { + this.onBeginBindPatronDelegate = new BeginOperationDelegate(this.OnBeginBindPatron); + } + if ((this.onEndBindPatronDelegate == null)) { + this.onEndBindPatronDelegate = new EndOperationDelegate(this.OnEndBindPatron); + } + if ((this.onBindPatronCompletedDelegate == null)) { + this.onBindPatronCompletedDelegate = new System.Threading.SendOrPostCallback(this.OnBindPatronCompleted); + } + base.InvokeAsync(this.onBeginBindPatronDelegate, new object[] { + strAction, + strQueryWord, + strPassword, + strBindingID, + strStyle, + strResultTypeList}, this.onEndBindPatronDelegate, this.onBindPatronCompletedDelegate, userState); + } + public DigitalPlatform.LibraryClient.localhost.LibraryServerResult GetVersion(out string uid) { return base.Channel.GetVersion(out uid); } diff --git a/DigitalPlatform.LibraryClient/Service References/localhost/metadata.wsdl b/DigitalPlatform.LibraryClient/Service References/localhost/metadata.wsdl index bd5f3eb85..6516c13bb 100644 --- a/DigitalPlatform.LibraryClient/Service References/localhost/metadata.wsdl +++ b/DigitalPlatform.LibraryClient/Service References/localhost/metadata.wsdl @@ -88,6 +88,12 @@ + + + + + + @@ -648,6 +654,10 @@ + + + + diff --git a/DigitalPlatform.LibraryClient/Service References/localhost/metadata1.xsd b/DigitalPlatform.LibraryClient/Service References/localhost/metadata1.xsd index ce80ccf0a..c85fe74fd 100644 --- a/DigitalPlatform.LibraryClient/Service References/localhost/metadata1.xsd +++ b/DigitalPlatform.LibraryClient/Service References/localhost/metadata1.xsd @@ -242,6 +242,26 @@ + + + + + + + + + + + + + + + + + + + + @@ -250,7 +270,7 @@ - + @@ -267,7 +287,7 @@ - + @@ -282,7 +302,7 @@ - + @@ -296,7 +316,7 @@ - + @@ -317,7 +337,7 @@ - + @@ -333,7 +353,7 @@ - + @@ -348,8 +368,8 @@ - - + + @@ -369,12 +389,12 @@ - + - + @@ -389,7 +409,7 @@ - + @@ -406,7 +426,7 @@ - + @@ -427,7 +447,7 @@ - + @@ -444,7 +464,7 @@ - + @@ -465,7 +485,7 @@ - + @@ -481,7 +501,7 @@ - + @@ -499,8 +519,8 @@ - - + + @@ -514,7 +534,7 @@ - + @@ -523,7 +543,7 @@ - + @@ -531,8 +551,8 @@ - - + + @@ -547,8 +567,8 @@ - - + + @@ -570,7 +590,7 @@ - + @@ -590,7 +610,7 @@ - + @@ -613,7 +633,7 @@ - + @@ -632,7 +652,7 @@ - + @@ -642,15 +662,15 @@ - + - - + + @@ -673,7 +693,7 @@ - + @@ -691,7 +711,7 @@ - + @@ -711,8 +731,8 @@ - - + + @@ -728,7 +748,7 @@ - + @@ -742,7 +762,7 @@ - + @@ -753,12 +773,12 @@ - - - - - - + + + + + + @@ -781,13 +801,13 @@ - - - - - + + + + + - + @@ -803,7 +823,7 @@ - + @@ -812,15 +832,15 @@ - + - - + + @@ -839,8 +859,8 @@ - - + + @@ -848,15 +868,15 @@ - + - - + + @@ -873,7 +893,7 @@ - + @@ -894,8 +914,8 @@ - - + + @@ -917,7 +937,7 @@ - + @@ -935,8 +955,8 @@ - - + + @@ -944,15 +964,15 @@ - + - - + + @@ -970,8 +990,8 @@ - - + + @@ -979,15 +999,15 @@ - + - - + + @@ -1004,7 +1024,7 @@ - + @@ -1025,8 +1045,8 @@ - - + + @@ -1048,7 +1068,7 @@ - + @@ -1062,7 +1082,7 @@ - + @@ -1074,7 +1094,7 @@ - + @@ -1090,7 +1110,7 @@ - + @@ -1105,8 +1125,8 @@ - - + + @@ -1125,8 +1145,8 @@ - - + + @@ -1146,7 +1166,7 @@ - + @@ -1167,8 +1187,8 @@ - - + + @@ -1176,14 +1196,14 @@ - + - + @@ -1192,15 +1212,15 @@ - + - - + + @@ -1212,7 +1232,7 @@ - + @@ -1228,7 +1248,7 @@ - + @@ -1246,8 +1266,8 @@ - - + + @@ -1255,14 +1275,14 @@ - + - + @@ -1279,8 +1299,8 @@ - - + + @@ -1289,15 +1309,15 @@ - + - - + + @@ -1313,7 +1333,7 @@ - + @@ -1328,7 +1348,7 @@ - + @@ -1343,7 +1363,7 @@ - + @@ -1360,7 +1380,7 @@ - + @@ -1374,7 +1394,7 @@ - + @@ -1393,11 +1413,11 @@ - + - + @@ -1413,8 +1433,8 @@ - - + + @@ -1429,7 +1449,7 @@ - + @@ -1446,7 +1466,7 @@ - + @@ -1456,14 +1476,14 @@ - + - + @@ -1479,7 +1499,7 @@ - + @@ -1499,8 +1519,8 @@ - - + + @@ -1515,7 +1535,7 @@ - + @@ -1533,7 +1553,7 @@ - + @@ -1550,7 +1570,7 @@ - + @@ -1570,8 +1590,8 @@ - - + + @@ -1586,7 +1606,7 @@ - + @@ -1604,7 +1624,7 @@ - + @@ -1622,7 +1642,7 @@ - + @@ -1639,8 +1659,8 @@ - - + + @@ -1654,8 +1674,8 @@ - - + + @@ -1673,7 +1693,7 @@ - + @@ -1695,7 +1715,7 @@ - + @@ -1712,7 +1732,7 @@ - + @@ -1736,7 +1756,7 @@ - + @@ -1756,8 +1776,8 @@ - - + + diff --git a/DigitalPlatform.LibraryClient/Service References/localhost/metadata5.xsd b/DigitalPlatform.LibraryClient/Service References/localhost/metadata5.xsd index 4834d5b06..9201fb1a9 100644 --- a/DigitalPlatform.LibraryClient/Service References/localhost/metadata5.xsd +++ b/DigitalPlatform.LibraryClient/Service References/localhost/metadata5.xsd @@ -362,6 +362,26 @@ + + + + + + + + + + + + + + + + + + + + @@ -370,7 +390,7 @@ - + @@ -387,7 +407,7 @@ - + @@ -402,7 +422,7 @@ - + @@ -416,7 +436,7 @@ - + @@ -437,7 +457,7 @@ - + @@ -453,7 +473,7 @@ - + @@ -468,8 +488,8 @@ - - + + @@ -489,12 +509,12 @@ - + - + @@ -509,7 +529,7 @@ - + @@ -526,7 +546,7 @@ - + @@ -547,7 +567,7 @@ - + @@ -564,7 +584,7 @@ - + @@ -585,7 +605,7 @@ - + @@ -601,7 +621,7 @@ - + @@ -619,8 +639,8 @@ - - + + @@ -634,7 +654,7 @@ - + @@ -643,7 +663,7 @@ - + @@ -651,8 +671,8 @@ - - + + @@ -667,7 +687,7 @@ - + @@ -703,7 +723,7 @@ - + @@ -723,7 +743,7 @@ - + @@ -746,7 +766,7 @@ - + @@ -765,7 +785,7 @@ - + @@ -775,15 +795,15 @@ - + - - + + @@ -806,7 +826,7 @@ - + @@ -824,7 +844,7 @@ - + @@ -844,8 +864,8 @@ - - + + @@ -861,7 +881,7 @@ - + @@ -875,7 +895,7 @@ - + @@ -886,12 +906,12 @@ - - - - + + + + - + @@ -923,11 +943,11 @@ - - - - - + + + + + @@ -959,7 +979,7 @@ - + @@ -989,7 +1009,7 @@ - + @@ -1009,7 +1029,7 @@ - + @@ -1025,7 +1045,7 @@ - + @@ -1043,7 +1063,7 @@ - + @@ -1064,8 +1084,8 @@ - - + + @@ -1087,7 +1107,7 @@ - + @@ -1105,7 +1125,7 @@ - + @@ -1121,7 +1141,7 @@ - + @@ -1140,7 +1160,7 @@ - + @@ -1156,7 +1176,7 @@ - + @@ -1174,7 +1194,7 @@ - + @@ -1195,8 +1215,8 @@ - - + + @@ -1218,7 +1238,7 @@ - + @@ -1232,7 +1252,7 @@ - + @@ -1244,7 +1264,7 @@ - + @@ -1260,7 +1280,7 @@ - + @@ -1275,8 +1295,8 @@ - - + + @@ -1295,7 +1315,7 @@ - + @@ -1331,7 +1351,7 @@ - + @@ -1352,7 +1372,7 @@ - + @@ -1383,7 +1403,7 @@ - + @@ -1422,7 +1442,7 @@ - + @@ -1435,7 +1455,7 @@ - + @@ -1451,7 +1471,7 @@ - + @@ -1469,7 +1489,7 @@ - + @@ -1504,7 +1524,7 @@ - + @@ -1521,7 +1541,7 @@ - + @@ -1558,7 +1578,7 @@ - + @@ -1575,7 +1595,7 @@ - + @@ -1590,7 +1610,7 @@ - + @@ -1605,7 +1625,7 @@ - + @@ -1622,7 +1642,7 @@ - + @@ -1636,7 +1656,7 @@ - + @@ -1655,11 +1675,11 @@ - + - + @@ -1675,8 +1695,8 @@ - - + + @@ -1691,7 +1711,7 @@ - + @@ -1708,7 +1728,7 @@ - + @@ -1718,14 +1738,14 @@ - + - + @@ -1741,7 +1761,7 @@ - + @@ -1761,7 +1781,7 @@ - + @@ -1794,7 +1814,7 @@ - + @@ -1812,7 +1832,7 @@ - + @@ -1829,7 +1849,7 @@ - + @@ -1849,7 +1869,7 @@ - + @@ -1862,7 +1882,7 @@ - + @@ -1879,7 +1899,7 @@ - + @@ -1897,7 +1917,7 @@ - + @@ -1915,7 +1935,7 @@ - + @@ -1932,7 +1952,7 @@ - + @@ -1945,7 +1965,7 @@ - + @@ -1962,7 +1982,7 @@ - + @@ -1994,7 +2014,7 @@ - + @@ -2016,7 +2036,7 @@ - + @@ -2033,7 +2053,7 @@ - + @@ -2057,7 +2077,7 @@ - + @@ -2077,7 +2097,7 @@ - + diff --git a/DigitalPlatform.LibraryServer/AppReader.cs b/DigitalPlatform.LibraryServer/AppReader.cs index c691c29cd..ba48618e5 100644 --- a/DigitalPlatform.LibraryServer/AppReader.cs +++ b/DigitalPlatform.LibraryServer/AppReader.cs @@ -4027,7 +4027,7 @@ int BuildReaderResults( string strOutputPath, // recpaths 时需要 byte[] baTimestamp, // timestamp 时需要 OperType operType, // html 时需要 - string [] saBorrowedItemBarcode, + string[] saBorrowedItemBarcode, string strCurrentItemBarcode, ref string[] results, out string strError) @@ -4812,5 +4812,271 @@ public int AddFriends( return 0; } + + // 为读者记录绑定新的号码,或者解除绑定 + // parameters: + // strAction 动作。有 bind/unbind + // strQueryWord 用于定位读者记录的检索词。 + // 0) 如果以"RI:"开头,表示利用 参考ID 进行检索 + // 1) 如果以"NB:"开头,表示利用姓名生日进行检索。姓名和生日之间间隔以'|'。姓名必须完整,生日为8字符形式 + // 2) 如果以"EM:"开头,表示利用email地址进行检索。注意 email 本身应该是 email:xxxx 这样的形态。也就是说,整个加起来是 EM:email:xxxxx + // 3) 如果以"TP:"开头,表示利用电话号码进行检索 + // 4) 如果以"ID:"开头,表示利用身份证号进行检索 + // 5) 如果以"CN:"开头,表示利用证件号码进行检索 + // 6) 否则用证条码号进行检索 + // strPassword 读者记录的密码 + // strBindingID 要绑定的号码。格式如 email:xxxx 或 weixinid:xxxxx + // strStyle 风格。multiple/single。默认 single + // multiple 表示允许多次绑定同一类型号码;sigle 表示同一类型号码只能绑定一次,如果多次绑定以前的同类型号码会被清除 + // strResultTypeList 结果类型数组 xml/html/text/calendar/advancexml/recpaths/summary + // 其中calendar表示获得读者所关联的日历名;advancexml表示经过运算了的提供了丰富附加信息的xml,例如具有超期和停借期附加信息 + // advancexml_borrow_bibliosummary/advancexml_overdue_bibliosummary/advancexml_history_bibliosummary + // results 返回操作成功后的读者记录 + // return: + // -1 出错 + // 0 因为条件不具备功能没有成功执行 + // 1 功能成功执行 + public int BindPatron( + SessionInfo sessioninfo, + string strAction, + string strQueryWord, + string strPassword, + string strBindingID, + string strStyle, + string strResultTypeList, + out string[] results, + out string strError) + { + strError = ""; + results = null; + + RmsChannel channel = sessioninfo.Channels.GetChannel(this.WsUrl); + if (channel == null) + { + strError = "get channel error"; + return -1; + } + + int nRedoCount = 0; + REDO: + bool bTempPassword = false; + string strXml = ""; + string strOutputPath = ""; + byte[] timestamp = null; + string strToken = ""; + + // 获得读者记录, 并检查密码是否符合。为登录用途 + // 该函数的特殊性在于,它可以用多种检索入口,而不仅仅是条码号 + // parameters: + // strQueryWord 登录名 + // 0) 如果以"RI:"开头,表示利用 参考ID 进行检索 + // 1) 如果以"NB:"开头,表示利用姓名生日进行检索。姓名和生日之间间隔以'|'。姓名必须完整,生日为8字符形式 + // 2) 如果以"EM:"开头,表示利用email地址进行检索。注意 email 本身应该是 email:xxxx 这样的形态。也就是说,整个加起来是 EM:email:xxxxx + // 3) 如果以"TP:"开头,表示利用电话号码进行检索 + // 4) 如果以"ID:"开头,表示利用身份证号进行检索 + // 5) 如果以"CN:"开头,表示利用证件号码进行检索 + // 6) 否则用证条码号进行检索 + // strPassword 密码。如果为null,表示不进行密码判断。注意,不是"" + // return: + // -2 当前没有配置任何读者库,或者可以操作的读者库 + // -1 error + // 0 not found + // 1 命中1条 + // >1 命中多于1条 + int nRet = this.GetReaderRecXmlForLogin( + channel, + "", // strLibraryCodeList, + strQueryWord, + strPassword, + -1, // nIndex, + sessioninfo.ClientIP, + null, // strGetToken, + out bTempPassword, + out strXml, + out strOutputPath, + out timestamp, + out strToken, + out strError); + if (nRet == -1 || nRet == -2) + { + strError = "以 '" + strQueryWord + "' 检索读者帐户记录出错: " + strError; + return -1; + } + + if (nRet == 0) + { + strError = "帐户不存在或密码不正确"; + return -1; + } + + if (nRet > 1) + { + strError = "以 '" + strQueryWord + "' 检索读者记录时, 因所匹配的帐户多于一个,无法确认读者记录。可改用证条码号进行绑定操作。"; + return -1; + } + + XmlDocument readerdom = null; + nRet = LibraryApplication.LoadToDom(strXml, + out readerdom, + out strError); + if (nRet == -1) + { + strError = "装载读者记录进入XML DOM时发生错误: " + strError; + return -1; + } + + bool bChanged = false; + + bool bMultiple = strStyle == "multiple"; + + // 修改读者记录的 email 字段 + string strEmail = DomUtil.GetElementText(readerdom.DocumentElement, "email"); + string strNewEmail = ""; + if (strAction == "bind") + { + strNewEmail = AddBindingString(strEmail, + strBindingID, + bMultiple); + } + else if (strAction == "unbind") + { + strNewEmail = RemoveBindingString(strEmail, strBindingID); + } + else + { + strError = "未知的 strAction 参数值 '" + strAction + "'"; + return -1; + } + + // 如果记录中没有 refID 字段,则主动填充 + string strRefID = DomUtil.GetElementText(readerdom.DocumentElement, "refID"); + if (string.IsNullOrEmpty(strRefID) == true) + { + DomUtil.SetElementText(readerdom.DocumentElement, "refID", Guid.NewGuid().ToString()); + m_bChanged = true; + } + + if (strNewEmail != strEmail) + { + DomUtil.SetElementText(readerdom.DocumentElement, "email", strEmail); + m_bChanged = true; + } + + if (bChanged == true) + { + string strRecPath = strOutputPath; + byte[] output_timestamp = null; + // 保存读者记录 + long lRet = channel.DoSaveTextRes(strRecPath, + readerdom.OuterXml, + false, + "content", // "content,ignorechecktimestamp", + timestamp, // timestamp, + out output_timestamp, + out strOutputPath, + out strError); + if (lRet == -1) + { + if (channel.ErrorCode == ChannelErrorCode.TimestampMismatch + && nRedoCount < 10) + { + nRedoCount++; + goto REDO; + } + return -1; + } + + timestamp = output_timestamp; + + // 让缓存失效 + string strReaderBarcode = DomUtil.GetElementText(readerdom.DocumentElement, "barcode"); + this.ClearLoginCache(strReaderBarcode); // 及时失效登录缓存 + } + + List recpaths = new List(); + recpaths.Add(strOutputPath); + + // 构造读者记录的返回格式 + nRet = BuildReaderResults( + sessioninfo, + readerdom, + strXml, + strResultTypeList, + "", // strLibraryCode, + recpaths, + strOutputPath, + timestamp, + OperType.None, + null, + "", + ref results, + out strError); + if (nRet == -1) + return -1; + + if (bChanged) + return 1; + return 0; + } + + // 加入一个绑定号码 + static string AddBindingString(string strText, + string strBinding, + bool bMultiple) + { + if (string.IsNullOrEmpty(strText) == true) + return strBinding; + + if (bMultiple == false) + { + string strName = ""; + string strValue = ""; + StringUtil.ParseTwoPart(strBinding, ":", out strName, out strValue); + + List results = new List(); + string[] parts = strText.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); + foreach (string s in parts) + { + string strLine = s.Trim(); + if (string.IsNullOrEmpty(strLine)) + continue; + string strLeft = ""; + string strRight = ""; + StringUtil.ParseTwoPart(strLine, ":", out strLeft, out strRight); + if (strName == strLeft) + continue; // 忽视所有同类型的号码 + results.Add(strLine); + } + + results.Add(strBinding); + return StringUtil.MakePathList(results); + } + else + return strText + "," + strBinding; + } + + // 去掉一个绑定号码 + static string RemoveBindingString(string strText, + string strBinding) + { + if (string.IsNullOrEmpty(strText) == true) + return ""; + + List results = new List(); + + string[] parts = strText.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); + foreach (string s in parts) + { + string strLine = s.Trim(); + if (string.IsNullOrEmpty(strLine)) + continue; + if (strLine == strBinding) + continue; // 忽视发现的号码 + results.Add(strLine); + } + + return StringUtil.MakePathList(results); + } + } } diff --git a/DigitalPlatform.LibraryServer/AppScript.cs b/DigitalPlatform.LibraryServer/AppScript.cs index 8259cb636..876395685 100644 --- a/DigitalPlatform.LibraryServer/AppScript.cs +++ b/DigitalPlatform.LibraryServer/AppScript.cs @@ -52,8 +52,7 @@ public int InitialExternalMessageInterfaces(out string strError) this.m_externalMessageInterfaces = null; - XmlNode root = this.LibraryCfgDom.DocumentElement.SelectSingleNode( - "externalMessageInterface"); + XmlNode root = this.LibraryCfgDom.DocumentElement.SelectSingleNode("externalMessageInterface"); if (root == null) { strError = "在library.xml中没有找到元素"; @@ -1365,7 +1364,7 @@ public virtual int VerifyReader( string strDbName = ResPath.GetDbName(strRecPath); if (string.IsNullOrEmpty(strDbName) == true) { - strError = "从读者库记录路径 '"+strRecPath+"' 获得数据库名时出错。验证读者记录失败"; + strError = "从读者库记录路径 '" + strRecPath + "' 获得数据库名时出错。验证读者记录失败"; return -1; } @@ -1375,7 +1374,7 @@ public virtual int VerifyReader( strError = "数据库名 '" + strDbName + "' 不是读者库。验证读者记录失败"; return -1; } - + // return: // -1 调用出错 // 0 校验正确 @@ -1481,7 +1480,7 @@ public int VerifyPatronBarcode( } // strLeft 包含的权限是否小于等于 strRight - static bool IsLessOrEqualThan(string strLeft, + static bool IsLessOrEqualThan(string strLeft, string strRight, out List warning_rights) { @@ -1497,10 +1496,10 @@ static bool IsLessOrEqualThan(string strLeft, return false; // strLeft != 空 && strRight == 空 } - string[] left = strLeft.Split(new char[] {','}, StringSplitOptions.RemoveEmptyEntries); + string[] left = strLeft.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); string[] right = strRight.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); - foreach(string s in left) + foreach (string s in left) { if (Array.IndexOf(right, s) == -1) warning_rights.Add(s); @@ -1937,6 +1936,17 @@ public virtual int NotifyReader( out strError); } + if (strBodyType == "mq") + { + return NotifyReaderSMS( + readerdom, + calendar, + strBodyType, + out strBody, + out strMime, + out strError); + } + strBody = ""; strError = ""; // wantNotifyBarcodes = new List(); @@ -2017,8 +2027,7 @@ public virtual int NotifyReader( { bOverdue = true; strOverDue = string.Format(this.App.GetString("已超期s"), // 已超期 {0} - this.App.GetDisplayTimePeriodStringEx(lOver.ToString() + " " + strPeriodUnit)) - ; + this.App.GetDisplayTimePeriodStringEx(lOver.ToString() + " " + strPeriodUnit)); } } } @@ -2190,14 +2199,14 @@ public static bool SetChars(ref string strText, // 短消息通知读者超期的版本。供NotifyReader()的重载版本必要时引用 public int NotifyReaderSMS( - XmlDocument readerdom, - Calendar calendar, - // List notifiedBarcodes, - string strBodyType, - out string strBody, - out string strMime, - // out List wantNotifyBarcodes, - out string strError) + XmlDocument readerdom, + Calendar calendar, + // List notifiedBarcodes, + string strBodyType, + out string strBody, + out string strMime, + // out List wantNotifyBarcodes, + out string strError) { strBody = ""; strError = ""; @@ -2236,7 +2245,6 @@ public int NotifyReaderSMS( bool bOverdue = false; // 是否超期 DateTime timeReturning = DateTime.MinValue; { - DateTime timeNextWorkingDay; long lOver = 0; string strPeriodUnit = ""; @@ -2264,8 +2272,7 @@ public int NotifyReaderSMS( { bOverdue = true; strOverDue = string.Format(this.App.GetString("已超期s"), // 已超期 {0} - this.App.GetDisplayTimePeriodStringEx(lOver.ToString() + " " + strPeriodUnit)) - ; + this.App.GetDisplayTimePeriodStringEx(lOver.ToString() + " " + strPeriodUnit)); } } } @@ -2278,7 +2285,6 @@ public int NotifyReaderSMS( if (bOverdue == true) { - // 看看是不是已经通知过 if (string.IsNullOrEmpty(strChars) == false && strChars[0] == 'y') continue; diff --git a/DigitalPlatform.LibraryServer/DigitalPlatform.LibraryServer.csproj b/DigitalPlatform.LibraryServer/DigitalPlatform.LibraryServer.csproj index 79b5edfd8..029f6a634 100644 --- a/DigitalPlatform.LibraryServer/DigitalPlatform.LibraryServer.csproj +++ b/DigitalPlatform.LibraryServer/DigitalPlatform.LibraryServer.csproj @@ -78,6 +78,7 @@ + diff --git a/DigitalPlatform.LibraryServer/LibraryApplication.cs b/DigitalPlatform.LibraryServer/LibraryApplication.cs index 9d5160cfd..f45e7869c 100644 --- a/DigitalPlatform.LibraryServer/LibraryApplication.cs +++ b/DigitalPlatform.LibraryServer/LibraryApplication.cs @@ -31,6 +31,7 @@ using DigitalPlatform.Message; using DigitalPlatform.rms.Client.rmsws_localhost; +using System.Messaging; namespace DigitalPlatform.LibraryServer { @@ -110,7 +111,8 @@ public partial class LibraryApplication : IDisposable // 2.67 (2016/1/6) GetItemInfo() API 的 @barcode-list:" "get-path-list" 功能允许间杂 @refID:前缀的号码。 // 2.68 (2016/1/9) Return() API 增加了 read action。会将动作记入操作日志。ChargingOperDatabase 库也会自动更新 // 2.69 (2016/1/29) 各个 API 都对读者身份加强了检查,防止出现权限漏洞。 - public static string Version = "2.69"; + // 2.70 (2016/4/10) 增加 MSMQ 消息队列功能,读者记录的修改、dp2mail 消息都自动发送到这个消息队列。dp2library 失效日期从 5.1 变为 7.1。ReadersMonitor 后台任务会自动给没有 refID 元素的读者记录增加此元素 + public static string Version = "2.70"; #if NO int m_nRefCount = 0; public int AddRef() @@ -145,6 +147,11 @@ public int ReleaseRef() /// public bool CheckClientVersion = false; + /// + /// dp2library 用于输出消息的队列路径。 + /// + public string OutgoingQueue = ""; + // 存储各种参数信息 // 为C#脚本所准备 public Hashtable ParamTable = new Hashtable(); @@ -982,23 +989,27 @@ public int LoadCfg( { this.AccessLogMaxCountPerDay = 10000; } + // 消息 // 元素 - // 属性dbname/reserveTimeSpan + // 属性dbname/reserveTimeSpan/defaultQueue node = dom.DocumentElement.SelectSingleNode("message") as XmlElement; if (node != null) { - app.MessageDbName = DomUtil.GetAttr(node, "dbname"); - app.MessageReserveTimeSpan = DomUtil.GetAttr(node, "reserveTimeSpan"); + this.MessageDbName = DomUtil.GetAttr(node, "dbname"); + this.MessageReserveTimeSpan = DomUtil.GetAttr(node, "reserveTimeSpan"); + // 2016/4/10 + this.OutgoingQueue = DomUtil.GetAttr(node, "defaultQueue"); // 2010/12/31 add - if (String.IsNullOrEmpty(app.MessageReserveTimeSpan) == true) - app.MessageReserveTimeSpan = "365day"; + if (String.IsNullOrEmpty(this.MessageReserveTimeSpan) == true) + this.MessageReserveTimeSpan = "365day"; } else { - app.MessageDbName = ""; - app.MessageReserveTimeSpan = "365day"; + this.MessageDbName = ""; + this.MessageReserveTimeSpan = "365day"; + this.OutgoingQueue = ""; } // OPAC服务器 @@ -1204,6 +1215,29 @@ public int LoadCfg( // goto ERROR1; } + // 创建 MSMQ 消息队列 +#if LOG_INFO + app.WriteErrorLog("INFO: Message Queue"); +#endif + if (string.IsNullOrEmpty(this.OutgoingQueue) == false) + { + try + { + if (!MessageQueue.Exists(this.OutgoingQueue)) + MessageQueue.Create(this.OutgoingQueue); + } + catch (Exception ex) + { + app.HangupList.Add("MessageQueueCreateFail"); + app.WriteErrorLog("*** 创建 MSMQ 队列 '" + this.OutgoingQueue + "' 失败: " + ex.Message + + " 系统被挂起。"); + } + } + else + { + + } + // 初始化 mongodb 相关对象 nRet = InitialMongoDatabases(out strError); @@ -1609,7 +1643,7 @@ public int LoadCfg( #endif } - if (DateTime.Now > new DateTime(2016, 5, 1)) + if (DateTime.Now > new DateTime(2016, 7, 1)) { // 通知系统挂起 // this.HangupReason = HangupReason.Expire; @@ -2990,6 +3024,8 @@ public void Save(string strFileName, writer.WriteStartElement("message"); writer.WriteAttributeString("dbname", this.MessageDbName); writer.WriteAttributeString("reserveTimeSpan", this.MessageReserveTimeSpan); // 2007/11/5 + if (string.IsNullOrEmpty(this.OutgoingQueue) == false) + writer.WriteAttributeString("defaultQueue", this.OutgoingQueue); writer.WriteEndElement(); /* @@ -4700,7 +4736,7 @@ public int GetAccount(string strUserID, // 2015/9/9 if (this.LibraryCfgDom == null || LibraryCfgDom.DocumentElement == null) { - strError = "LibraryCfgDom 尚未初始化"; + strError = "LibraryCfgDom 尚未初始化。请检查 dp2library 错误日志"; return -1; } @@ -8294,8 +8330,9 @@ void SplitLoginName(string strLoginName, // 该函数的特殊性在于,它可以用多种检索入口,而不仅仅是条码号 // parameters: // strQueryWord 登录名 + // 0) 如果以"RI:"开头,表示利用 参考ID 进行检索 // 1) 如果以"NB:"开头,表示利用姓名生日进行检索。姓名和生日之间间隔以'|'。姓名必须完整,生日为8字符形式 - // 2) 如果以"EM:"开头,表示利用email地址进行检索 + // 2) 如果以"EM:"开头,表示利用email地址进行检索。注意 email 本身应该是 email:xxxx 这样的形态。也就是说,整个加起来是 EM:email:xxxxx // 3) 如果以"TP:"开头,表示利用电话号码进行检索 // 4) 如果以"ID:"开头,表示利用身份证号进行检索 // 5) 如果以"CN:"开头,表示利用证件号码进行检索 @@ -8368,7 +8405,7 @@ int GetReaderRecXmlForLogin( bBarcode = false; strFrom = "Email"; strMatch = "exact"; - strQueryWord = strName; + strQueryWord = strName; // 2016/4/11 注 strName 内容应为 email:xxxxx } else if (strPrefix == "TP:") { @@ -8391,6 +8428,14 @@ int GetReaderRecXmlForLogin( strMatch = "exact"; strQueryWord = strName; } + else if (strPrefix == "RI:") + { + // 2016/4/11 + bBarcode = false; + strFrom = "参考ID"; + strMatch = "exact"; + strQueryWord = strName; + } else { strError = "未知的登录名前缀 '" + strPrefix + "'"; @@ -8683,8 +8728,6 @@ int GetReaderRecXmlForLogin( * */ } - - // 将XML装入DOM public static int LoadToDom(string strXml, out XmlDocument dom, diff --git a/DigitalPlatform.LibraryServer/ReadersMonitor.cs b/DigitalPlatform.LibraryServer/ReadersMonitor.cs index 8883e66f7..53d796de5 100644 --- a/DigitalPlatform.LibraryServer/ReadersMonitor.cs +++ b/DigitalPlatform.LibraryServer/ReadersMonitor.cs @@ -3,12 +3,13 @@ using System.Text; using System.Xml; using System.Diagnostics; +using System.Collections; +using System.Messaging; using DigitalPlatform.Xml; using DigitalPlatform.rms.Client; using DigitalPlatform.IO; using DigitalPlatform.Text; -using System.Collections; namespace DigitalPlatform.LibraryServer { @@ -32,6 +33,8 @@ public override string DefaultName } } + MessageQueue _queue = null; + // 一次操作循环 // TODO: 是否需要对读者记录加锁? public override void Worker() @@ -136,10 +139,47 @@ public override void Worker() recpath_table.Clear(); + if (string.IsNullOrEmpty(this.App.OutgoingQueue) == false) + { + try + { + _queue = new MessageQueue(this.App.OutgoingQueue); + } + catch (Exception ex) + { + strError = "创建路径为 '" + this.App.OutgoingQueue + "' 的 MessageQueue 对象失败: " + ex.Message; + goto ERROR1; + } + } + else + this._queue = null; + List bodytypes = new List(); + + string strBodyTypesDef = GetBodyTypesDef(); + + if (string.IsNullOrEmpty(strBodyTypesDef) == true) + strBodyTypesDef = "dpmail,email"; // 空表示只使用两种保守的类型 + else if (strBodyTypesDef == "[all]") + { + // 全部类型。包括 mq 和外部接口 + bodytypes.Add("dpmail"); + bodytypes.Add("email"); + if (string.IsNullOrEmpty(this.App.OutgoingQueue) == false) + bodytypes.Add("mq"); // MSMQ 消息队列 + if (this.App.m_externalMessageInterfaces != null) + { + foreach (MessageInterface message_interface in this.App.m_externalMessageInterfaces) + { + bodytypes.Add(message_interface.Type); + } + } + } + else + bodytypes = StringUtil.SplitList(strBodyTypesDef); + RmsChannel channel = this.RmsChannels.GetChannel(this.App.WsUrl); int nTotalRecCount = 0; - for (int i = 0; i < this.App.ReaderDbs.Count; i++) { #if NO @@ -261,6 +301,7 @@ public override void Worker() // 处理 nRet = DoOneRecord( + bodytypes, strOutputPath, strLibraryCode, strXmlBody, @@ -309,8 +350,21 @@ public override void Worker() return; } + // 获得通知类型的定义 + // monitors/readersMonitor 元素的 types 属性。缺省为空 + string GetBodyTypesDef() + { + if (this.App.LibraryCfgDom == null || this.App.LibraryCfgDom.DocumentElement == null) + return ""; + XmlElement def_node = this.App.LibraryCfgDom.DocumentElement.SelectSingleNode("monitors/readersMonitor") as XmlElement; + if (def_node == null) + return ""; + return def_node.GetAttribute("types"); + } + // 处理一条记录 int DoOneRecord( + List bodytypes, string strPath, string strLibraryCode, string strReaderXml, @@ -325,7 +379,6 @@ int DoOneRecord( int nRedoCount = 0; REDO: - byte[] output_timestamp = null; XmlDocument readerdom = new XmlDocument(); @@ -335,12 +388,14 @@ int DoOneRecord( } catch (Exception ex) { - strError = "装载XML到DOM出错: " + ex.Message; + strError = "装载 XML 到 DOM 出错: " + ex.Message; return -1; } string strReaderBarcode = DomUtil.GetElementText(readerdom.DocumentElement, "barcode"); + string strRefID = DomUtil.GetElementText(readerdom.DocumentElement, + "refID"); string strReaderType = DomUtil.GetElementText(readerdom.DocumentElement, "readerType"); @@ -356,22 +411,15 @@ int DoOneRecord( out strError); if (nRet == -1 || nRet == 0) { + // 注: 借书和还书是否需要工作日历参数? 如果也需要,则在相关读者借书或者还书时候就会遇到报错,管理员会及时处理 + // TODO: 将来在这里增加通知系统管理员的动作 strError = "获得读者类型 '" + strReaderType + "' 的相关日历过程失败: " + strError; return -1; } bool bChanged = false; - List bodytypes = new List(); - bodytypes.Add("dpmail"); - bodytypes.Add("email"); - if (this.App.m_externalMessageInterfaces != null) - { - foreach (MessageInterface message_interface in this.App.m_externalMessageInterfaces) - { - bodytypes.Add(message_interface.Type); - } - } + // 每种 bodytype 做一次 for (int i = 0; i < bodytypes.Count; i++) @@ -469,6 +517,40 @@ int DoOneRecord( { // 发送邮件 + // 2016/4/10 + if (strBodyType == "mq") + { + // 向 MSMQ 消息队列发送消息 + nRet = SendToQueue(this._queue, + string.IsNullOrEmpty(strRefID) ? strReaderBarcode : "@refID:" + strRefID, + strBody, + out strError); + if (nRet == -1) + { + strError = "发送 MQ 出错: " + strError; + if (this.App.Statis != null) + this.App.Statis.IncreaseEntryValue(strLibraryCode, + "超期通知", + "MQ超期通知消息发送错误数", + 1); + this.AppendResultText(strError + "\r\n"); + bSendMessageError = true; + + this.App.WriteErrorLog(strError); + readerdom = new XmlDocument(); + readerdom.LoadXml(strOldReaderXml); + } + else + { + if (this.App.Statis != null) + this.App.Statis.IncreaseEntryValue( + strLibraryCode, + "超期通知", + "MQ超期通知人数", + 1); + } + } + if (strBodyType == "dpmail") { // 发送消息 @@ -606,7 +688,6 @@ int DoOneRecord( 1); } } - } if (bSendMessageError == false) @@ -691,6 +772,22 @@ int DoOneRecord( if (nRet == 1) bChanged = true; + // 2016/4/10 + // 如果读者记录中没有 refID 元素,自动创建它 + // return: + // -1 出错 + // 0 读者记录没有改变 + // 1 读者记录发生改变 + nRet = AddRefID(readerdom, + out strError); + if (nRet == -1) + { + strError = "在为读者记录添加 refID 元素时发生错误: " + strError; + this.AppendResultText(strError + "\r\n"); + } + if (nRet == 1) + bChanged = true; + // 修改读者记录后存回 if (bChanged == true) { @@ -743,6 +840,59 @@ int DoOneRecord( return 0; } + // 向 MSMQ 消息队列发送消息 + // parameters: + // strRecipient 应优先用读者记录的 refID 字段(格式为 @refID:xxxxxx),如果没有则用 barcode 字段 + static int SendToQueue(MessageQueue myQueue, + string strRecipient, + string strBody, + out string strError) + { + strError = ""; + + XmlDocument dom = new XmlDocument(); + dom.LoadXml(""); + DomUtil.SetElementText(dom.DocumentElement, "type", "patronNotify"); + DomUtil.SetElementText(dom.DocumentElement, "recipient", strRecipient); + DomUtil.SetElementText(dom.DocumentElement, "body", strBody); + DomUtil.SetElementText(dom.DocumentElement, "mime", "text"); + + try + { + System.Messaging.Message myMessage = new System.Messaging.Message(); + myMessage.Body = dom.DocumentElement.OuterXml; + myMessage.Formatter = new XmlMessageFormatter(new Type[] { typeof(string) }); + myQueue.Send(myMessage); + return 0; + } + catch (Exception ex) + { + strError = "发送消息到 MQ 失败: " + ex.Message; + return -1; + } + } + + // 2016/4/10 + // 如果读者记录中没有 refID 元素,自动创建它 + // return: + // -1 出错 + // 0 读者记录没有改变 + // 1 读者记录发生改变 + int AddRefID(XmlDocument readerdom, + out string strError) + { + strError = ""; + + string strRefID = DomUtil.GetElementText(readerdom.DocumentElement, "refID"); + if (string.IsNullOrEmpty(strRefID) == true) + { + DomUtil.SetElementText(readerdom.DocumentElement, "refID", Guid.NewGuid().ToString()); + return 1; + } + + return 0; + } + // 2015/10/9 // 删除超过极限数量的 BorrowHistory/borrow 元素 // return: @@ -1043,6 +1193,10 @@ public static int SetNotifiedChars(LibraryApplication app, { index = 1; } + else if (strBodyType == "mq") + { + index = 2; + } else { MessageInterface external_interface = app.GetMessageInterface(strBodyType); @@ -1058,7 +1212,7 @@ public static int SetNotifiedChars(LibraryApplication app, strError = "external_interface (type '" + external_interface.Type + "') 没有在 m_externalMessageInterfaces 数组中找到"; return -1; } - index += 2; + index += 3; // 原来是 2 } for (int i = 0; i < strChars.Length; i++) diff --git a/DigitalPlatform.LibraryService/ILibraryService.cs b/DigitalPlatform.LibraryService/ILibraryService.cs index 46a195dd0..37b774135 100644 --- a/DigitalPlatform.LibraryService/ILibraryService.cs +++ b/DigitalPlatform.LibraryService/ILibraryService.cs @@ -798,5 +798,15 @@ LibraryServerResult SearchCharging( long start, long count, out ChargingItemWrapper[] results); + + [OperationContract(IsInitiating = true, IsTerminating = false)] + LibraryServerResult BindPatron( + string strAction, + string strQueryWord, + string strPassword, + string strBindingID, + string strStyle, + string strResultTypeList, + out string[] results); } } diff --git a/DigitalPlatform.LibraryService/ILibraryServiceREST.cs b/DigitalPlatform.LibraryService/ILibraryServiceREST.cs index 6039f45a8..242193ac4 100644 --- a/DigitalPlatform.LibraryService/ILibraryServiceREST.cs +++ b/DigitalPlatform.LibraryService/ILibraryServiceREST.cs @@ -818,5 +818,15 @@ LibraryServerResult SearchCharging( long start, long count, out ChargingItemWrapper[] results); + + [OperationContract] + LibraryServerResult BindPatron( + string strAction, + string strQueryWord, + string strPassword, + string strBindingID, + string strStyle, + string strResultTypeList, + out string[] results); } } diff --git a/DigitalPlatform.LibraryService/LibraryService.cs b/DigitalPlatform.LibraryService/LibraryService.cs index 1758ae5d8..0a8f57881 100644 --- a/DigitalPlatform.LibraryService/LibraryService.cs +++ b/DigitalPlatform.LibraryService/LibraryService.cs @@ -7686,6 +7686,61 @@ public LibraryServerResult ResetPassword(string strParameters, return result; } + // 为读者记录绑定新的号码 + // parameters: + // strAction 动作。有 bind/unbind + // strQueryWord 用于定位读者记录的检索词。 + // 0) 如果以"RI:"开头,表示利用 参考ID 进行检索 + // 1) 如果以"NB:"开头,表示利用姓名生日进行检索。姓名和生日之间间隔以'|'。姓名必须完整,生日为8字符形式 + // 2) 如果以"EM:"开头,表示利用email地址进行检索。注意 email 本身应该是 email:xxxx 这样的形态。也就是说,整个加起来是 EM:email:xxxxx + // 3) 如果以"TP:"开头,表示利用电话号码进行检索 + // 4) 如果以"ID:"开头,表示利用身份证号进行检索 + // 5) 如果以"CN:"开头,表示利用证件号码进行检索 + // 6) 否则用证条码号进行检索 + // strPassword 读者记录的密码 + // strBindingID 要绑定的号码。格式如 email:xxxx 或 weixinid:xxxxx + // strStyle 风格。multiple/single。默认 single + // multiple 表示允许多次绑定同一类型号码;sigle 表示同一类型号码只能绑定一次,如果多次绑定以前的同类型号码会被清除 + // strResultTypeList 结果类型数组 xml/html/text/calendar/advancexml/recpaths/summary + // 其中calendar表示获得读者所关联的日历名;advancexml表示经过运算了的提供了丰富附加信息的xml,例如具有超期和停借期附加信息 + // advancexml_borrow_bibliosummary/advancexml_overdue_bibliosummary/advancexml_history_bibliosummary + // results 返回操作成功后的读者记录 + public LibraryServerResult BindPatron( + string strAction, + string strQueryWord, + string strPassword, + string strBindingID, + string strStyle, + string strResultTypeList, + out string[] results) + { + results = null; + + LibraryServerResult result = this.PrepareEnvironment("BindingPatron", false); + if (result.Value == -1) + return result; + + string strError = ""; + // 不需要登录 + // return: + // -1 出错 + // 0 因为条件不具备功能没有成功执行 + // 1 功能成功执行 + int nRet = app.BindPatron( + sessioninfo, + strAction, + strQueryWord, + strPassword, + strBindingID, + strStyle, + strResultTypeList, + out results, + out strError); + result.Value = nRet; + result.ErrorInfo = strError; + return result; + } + // 获得值列表 // parameters: // values 返回值列表。 diff --git a/DongshifangMessageInterface/DongshifangMessageHost.cs b/DongshifangMessageInterface/DongshifangMessageHost.cs new file mode 100644 index 000000000..5141b58a8 --- /dev/null +++ b/DongshifangMessageInterface/DongshifangMessageHost.cs @@ -0,0 +1,377 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Xml; +using System.Net; +using System.Web; +using System.IO; +using System.Security.Cryptography; +using System.Configuration; + +using DigitalPlatform.Interfaces; +using DigitalPlatform.Xml; + +namespace DongshifangMessageInterface +{ + public class DongshifangMessageHost : ExternalMessageHost + { + // return: + // -1 发送失败 + // 0 没有必要发送 + // 1 发送成功 + public override int SendMessage( + string strReaderBarcode, + string strReaderXml, + string strMessageText, + string strLibraryCode, + out string strError) + { + strError = ""; + + if (string.IsNullOrEmpty(strReaderXml) == true) + return 0; + + XmlDocument dom = new XmlDocument(); + try + { + dom.LoadXml(strReaderXml); + } + catch (Exception ex) + { + strError = "读者记录 XML 装入 DOM 出错: " + ex.Message; + return -1; + } + + // 获得电话号码 + string strTel = DomUtil.GetElementText(dom.DocumentElement, "tel"); + if (string.IsNullOrEmpty(strTel) == true) + return 0; + + // 提取出手机号 + string[] tels = strTel.Split(new char[] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries); + List mobiles = new List(); + foreach (string tel in tels) + { + string strText = tel.Trim(); + if (strText.Length == 11) + mobiles.Add(strTel); + } + + if (mobiles.Count == 0) + return 0; + + foreach (string tel in mobiles) + { + int nRet = SendMessage(tel, + strMessageText, + strLibraryCode, + out strError); + if (nRet <= 0) + { + strError = "发送出错,错误码 [" + nRet.ToString() + "]"; + return -1; + } + + break; + } + + return 1; + } + + // 发送一条消息。可以大于 70 字,分为多条发送 + public static int SendMessage(string strTel, + string strMessage, + string strLibraryCode, + out string strError) + { + if (string.IsNullOrEmpty(strTel) == true + || string.IsNullOrEmpty(strMessage) == true) + { + strError = "strMessage 和 strTel 参数不能为空"; + return -1; + } + + ConfigParam param = null; + + try + { + param = ConfigParam.LoadConfig(strLibraryCode); + } + catch (Exception ex) + { + strError = ex.Message; + return -1; + } + + + if (strMessage.Length <= param.nMaxChars) + { + return SendOneMessage( + param, + strTel, + strMessage, + strLibraryCode, + out strError); + } + + int nCount = 0; + for (; ; ) + { + int nLength = strMessage.Length; + if (nLength > param.nMaxChars) + nLength = param.nMaxChars; + string strPart = strMessage.Substring(0, nLength); + int nRet = SendOneMessage( + param, + strTel, + strPart, + strLibraryCode, + out strError); + if (nRet <= 0) + return nRet; + nCount += nRet; + + if (strMessage.Length <= nLength) + break; + strMessage = strMessage.Substring(nLength); + } + + return nCount; + } + + /* + * app.config 需要这样配置 + + + + + * + * */ + /* 旧用法,已经废止 + * app.config 需要这样配置 + + + + + + + + * + * */ + /* +返回值参对表 + +编号 值 说明 +1 大于0 发送成功,此次发送成功条数 +2 -1 参数无效 +3 -2 通道不存在或者当前业务不支持此通道 +4 -3 定时格式错误 +5 -4 接收号码无效 +6 -5 提交号码个数超过上限,最多100条 +7 -6 短信内容长度不符合要求,普通短信70字 +8 -7 当前账户余额不足 +9 -8 网关发送短信时出现异常 +10 -9 用户或者密码没输入 +11 -10 企业ID或者会员账号不存在 +12 -11 密码错误 +13 -12 账户锁定 +14 -13 网关状态关闭 +15 -14 验证用户时执行异常 +16 -15 网关初始化失败 +17 -16 当前IP已被系统屏蔽,密码失败次数太多 +18 -17 发送异常 +19 -18 账号未审核 +20 -19 当前时间不允许发送短信 +21 -20 传输密钥未设置,请登陆平台设置 +22 -21 提取密钥异常 +23 -22 签名验证失败 +24 -23 发现屏蔽关键字 +25 -100到-199 运营商返回失败代码 + * */ + static int SendOneMessage( + ConfigParam param, + string strTel, + string strMessage, + string strLibraryCode, + out string strError) + { + strError = ""; + + if (string.IsNullOrEmpty(strTel) == true + || string.IsNullOrEmpty(strMessage) == true) + { + strError = "strMessage 和 strTel 参数不能为空"; + return -1; + } + +#if NO + string strDepCode = System.Configuration.ConfigurationManager.AppSettings["eid"].ToString(); + string strUserID = System.Configuration.ConfigurationManager.AppSettings["uid"].ToString(); + string strPassword = System.Configuration.ConfigurationManager.AppSettings["pwd"].ToString(); +#endif + +#if NO + ConfigParam param = null; + + try + { + param = ConfigParam.LoadConfig(strLibraryCode); + } + catch (Exception ex) + { + strError = ex.Message; + return -1; + } +#endif + + // http://api.xhsms.com/gb2312/web_api/?x_eid=企业ID&x_uid=账号&x_pwd_md5=登陆密码MD5值&x_ac=10&x_gate_id=300&x_target_no=手机号码&x_memo=短信内容 + string strUrl = "http://api.xhsms.com/gb2312/web_api/?x_eid=" + + param.strDepCode + + "&x_uid=" + param.strUserID + + "&x_pwd_md5=" + GetMd5(param.strPassword) + + "&x_ac=10&x_gate_id=300&x_target_no=" + strTel + + "&x_memo=" + HttpUtility.UrlEncode(strMessage, Encoding.GetEncoding(936)); + try + { + HttpWebRequest hr = (HttpWebRequest)WebRequest.Create(strUrl); + hr.UserAgent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)"; + hr.Method = "GET"; + hr.Timeout = 1 * 60 * 1000; // 30 * 60 * 1000; + WebResponse hs = hr.GetResponse(); + Stream sr = hs.GetResponseStream(); + StreamReader ser = new StreamReader(sr, Encoding.Default); + string strResult = ser.ReadToEnd(); + int v = 0; + if (int.TryParse(strResult, out v) == false) + { + strError = "HTTP 请求返回字符串 '" + strResult + "'"; + return -1; + } + return v; + } + catch (Exception ex) + { + strError = "HTTP 调用失败: " + ex.Message; + return -1; + } + } + + static string GetMd5(string strText) + { + MD5 hasher = MD5.Create(); + byte[] buffer = Encoding.ASCII.GetBytes(strText); + byte[] target = hasher.ComputeHash(buffer); + StringBuilder sb = new StringBuilder(); + foreach (byte b in target) + { + sb.Append(b.ToString("x2").ToLower()); + } + + return sb.ToString(); + } + } + + class ConfigParam + { + public string strDepCode = ""; + public string strUserID = ""; + public string strPassword = ""; + public int nMaxChars = 70; // 每条短消息的字符数。短信服务商可能给文字加上前缀字符串,这样实际能用的可能少于 70 个字符,需要用参数配置一下 + + public static ConfigParam LoadConfig(string strLibraryCode) + { + string strDir = AppDomain.CurrentDomain.BaseDirectory; + string strCfgFile = Path.Combine(strDir, "DongshifangMessageInterface.dll.config"); + + XmlDocument dom = new XmlDocument(); + try + { + dom.Load(strCfgFile); + } + catch + { + throw new Exception("配置文件 '" + strCfgFile + "' 装载错误"); + } + + if (dom.DocumentElement == null) + throw new Exception("配置文件 '" + strCfgFile + "' 缺乏根元素"); + + XmlElement node = dom.DocumentElement.SelectSingleNode("library[@code='" + strLibraryCode + "']") as XmlElement; + if (node == null) + { + // 如果找不到特定馆代码的事项,就找 '*' 的事项,这是负责所有未明确配置的馆代码的 + node = dom.DocumentElement.SelectSingleNode("library[@code='*']") as XmlElement; + if (node == null) + throw new Exception("配置文件 '" + strCfgFile + "' 中没有配置馆代码为 '" + strLibraryCode + "' 或者为 '*' 的参数 (library 元素)"); + } + + ConfigParam cfg = new ConfigParam(); + + cfg.strDepCode = DomUtil.GetAttr(node, "eid"); + if (string.IsNullOrEmpty(cfg.strDepCode) == true) + throw new Exception("配置文件中尚未为馆代码 '" + strLibraryCode + "'配置 eid 参数"); + + cfg.strUserID = DomUtil.GetAttr(node, "uid"); + if (string.IsNullOrEmpty(cfg.strUserID) == true) + throw new Exception("配置文件中尚未为馆代码 '" + strLibraryCode + "'配置 uid 参数"); + + cfg.strPassword = DomUtil.GetAttr(node, "pwd"); + if (string.IsNullOrEmpty(cfg.strPassword) == true) + throw new Exception("配置文件中尚未为馆代码 '" + strLibraryCode + "'配置 pwd 参数"); + + int nMaxChars = 70; + string strMaxChars = node.GetAttribute("max_chars"); + if (string.IsNullOrEmpty(strMaxChars) == false) + { + if (Int32.TryParse(strMaxChars, out nMaxChars) == false) + throw new Exception("配置文件中馆代码 '" + strLibraryCode + "' 所在元素的 max_chars 属性值 '" + strMaxChars + "' 格式错误。应该为纯数字"); + } + cfg.nMaxChars = nMaxChars; + + return cfg; + } + + +#if NO + public static ConfigParam LoadConfig() + { + + string strDir = AppDomain.CurrentDomain.BaseDirectory; + string strExePath = Path.Combine(strDir, "DongshifangMessageInterface.dll"); + Configuration config = null; + + try + { + config = ConfigurationManager.OpenExeConfiguration(strExePath); + } + catch + { + throw new Exception("配置文件 '"+strExePath+".config' 装载错误"); + } + + ConfigParam cfg = new ConfigParam(); + + if (config.AppSettings.Settings["eid"] == null) + throw new Exception("配置文件中尚未配置 eid 参数"); + cfg.strDepCode = config.AppSettings.Settings["eid"].Value; + + if (config.AppSettings.Settings["uid"] == null) + throw new Exception("配置文件中尚未配置 uid 参数"); + cfg.strUserID = config.AppSettings.Settings["uid"].Value; + + if (config.AppSettings.Settings["pwd"] == null) + throw new Exception("配置文件中尚未配置 pwd 参数"); + cfg.strPassword = config.AppSettings.Settings["pwd"].Value; + + return cfg; + } +#endif + + } +} diff --git a/DongshifangMessageInterface/DongshifangMessageInterface.csproj b/DongshifangMessageInterface/DongshifangMessageInterface.csproj new file mode 100644 index 000000000..970f32745 --- /dev/null +++ b/DongshifangMessageInterface/DongshifangMessageInterface.csproj @@ -0,0 +1,67 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {E0C00B33-6BBF-4F9F-8B69-42325C888A46} + Library + Properties + DongshifangMessageInterface + DongshifangMessageInterface + v4.0 + 512 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + + + + {3C4F8133-8652-40B6-B37B-200B25C2B043} + DigitalPlatform.Interfaces + + + {E6489E89-1349-4EE7-A00B-AC96B9912587} + DigitalPlatform.Xml + + + + + \ No newline at end of file diff --git a/DongshifangMessageInterface/Properties/AssemblyInfo.cs b/DongshifangMessageInterface/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..8c240347f --- /dev/null +++ b/DongshifangMessageInterface/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的常规信息通过以下 +// 特性集控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("DongshifangMessageInterface")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("DongshifangMessageInterface")] +[assembly: AssemblyCopyright("Copyright © 2013")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 使此程序集中的类型 +// 对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型, +// 则将该类型上的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("6640b544-3594-42df-861e-aeee859fa8c7")] + +// 程序集的版本信息由下面四个值组成: +// +// 主版本 +// 次版本 +// 内部版本号 +// 修订号 +// +// 可以指定所有这些值,也可以使用“内部版本号”和“修订号”的默认值, +// 方法是按如下所示使用“*”: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/dp2-net40.sln b/dp2-net40.sln index 2bd429d1e..b9a31748c 100644 --- a/dp2-net40.sln +++ b/dp2-net40.sln @@ -162,6 +162,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GcatServer", "GcatServer\Gc EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DigitalPlatform.KernelClient", "DigitalPlatform.KernelClient\DigitalPlatform.KernelClient.csproj", "{CA11A59D-373D-4CA2-8C9F-CFCAE41190EF}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DongshifangMessageInterface", "DongshifangMessageInterface\DongshifangMessageInterface.csproj", "{E0C00B33-6BBF-4F9F-8B69-42325C888A46}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -1252,6 +1254,21 @@ Global {CA11A59D-373D-4CA2-8C9F-CFCAE41190EF}.Test|Mixed Platforms.ActiveCfg = Release|Any CPU {CA11A59D-373D-4CA2-8C9F-CFCAE41190EF}.Test|Mixed Platforms.Build.0 = Release|Any CPU {CA11A59D-373D-4CA2-8C9F-CFCAE41190EF}.Test|x86.ActiveCfg = Release|Any CPU + {E0C00B33-6BBF-4F9F-8B69-42325C888A46}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E0C00B33-6BBF-4F9F-8B69-42325C888A46}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E0C00B33-6BBF-4F9F-8B69-42325C888A46}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {E0C00B33-6BBF-4F9F-8B69-42325C888A46}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {E0C00B33-6BBF-4F9F-8B69-42325C888A46}.Debug|x86.ActiveCfg = Debug|Any CPU + {E0C00B33-6BBF-4F9F-8B69-42325C888A46}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E0C00B33-6BBF-4F9F-8B69-42325C888A46}.Release|Any CPU.Build.0 = Release|Any CPU + {E0C00B33-6BBF-4F9F-8B69-42325C888A46}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {E0C00B33-6BBF-4F9F-8B69-42325C888A46}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {E0C00B33-6BBF-4F9F-8B69-42325C888A46}.Release|x86.ActiveCfg = Release|Any CPU + {E0C00B33-6BBF-4F9F-8B69-42325C888A46}.Test|Any CPU.ActiveCfg = Release|Any CPU + {E0C00B33-6BBF-4F9F-8B69-42325C888A46}.Test|Any CPU.Build.0 = Release|Any CPU + {E0C00B33-6BBF-4F9F-8B69-42325C888A46}.Test|Mixed Platforms.ActiveCfg = Release|Any CPU + {E0C00B33-6BBF-4F9F-8B69-42325C888A46}.Test|Mixed Platforms.Build.0 = Release|Any CPU + {E0C00B33-6BBF-4F9F-8B69-42325C888A46}.Test|x86.ActiveCfg = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/dp2Circulation/SearchForms/BiblioSearchForm.cs b/dp2Circulation/SearchForms/BiblioSearchForm.cs index ee91a4e19..3ff4da3c4 100644 --- a/dp2Circulation/SearchForms/BiblioSearchForm.cs +++ b/dp2Circulation/SearchForms/BiblioSearchForm.cs @@ -5986,6 +5986,7 @@ void menu_saveToBiblioDumpFile_Click(object sender, EventArgs e) goto ERROR1; } +#if NO // 询问文件名 SaveFileDialog dlg = new SaveFileDialog(); @@ -6000,6 +6001,16 @@ void menu_saveToBiblioDumpFile_Click(object sender, EventArgs e) if (dlg.ShowDialog() != DialogResult.OK) return; +#endif + OpenBiblioDumpFileDialog dlg = new OpenBiblioDumpFileDialog(); + MainForm.SetControlFont(dlg, this.Font); + + this.MainForm.AppInfo.LinkFormState(dlg, "bibliosearchform_OpenBiblioDumpFileDialog"); + dlg.ShowDialog(this); + this.MainForm.AppInfo.UnlinkFormState(dlg); + + if (dlg.DialogResult != System.Windows.Forms.DialogResult.OK) + return; this.EnableControls(false); @@ -6077,20 +6088,42 @@ void menu_saveToBiblioDumpFile_Click(object sender, EventArgs e) if (string.IsNullOrEmpty(strXml) == true) goto CONTINUE; - XmlDocument dom = new XmlDocument(); + XmlDocument biblio_dom = new XmlDocument(); try { - dom.LoadXml(strXml); + biblio_dom.LoadXml(strXml); } catch (Exception ex) { - strError = "XML 装入 DOM 时出错: " + ex.Message; + strError = "书目记录 '" + info.RecPath + "' 的 XML 装入 DOM 时出错: " + ex.Message; goto ERROR1; } - if (dom.DocumentElement == null) + if (biblio_dom.DocumentElement == null) goto CONTINUE; + if (dlg.IncludeObjectFile) + { + // 将书目记录中的对象资源写入外部文件 + nRet = WriteObjectFiles(stop, + channel, + info.RecPath, + ref biblio_dom, + dlg.ObjectDirectoryName, + out strError); + if (nRet == -1) + { + DialogResult temp_result = MessageBox.Show(this, +strError + "\r\n\r\n是否继续处理?", +"BiblioSearchForm", +MessageBoxButtons.OKCancel, +MessageBoxIcon.Question, +MessageBoxDefaultButton.Button1); + if (temp_result == DialogResult.Cancel) + goto ERROR1; + } + } + // 写入 dprms:record 元素 writer.WriteStartElement("dprms", "record", DpNs.dprms); @@ -6101,15 +6134,16 @@ void menu_saveToBiblioDumpFile_Click(object sender, EventArgs e) writer.WriteAttributeString("path", this.MainForm.LibraryServerUrl + "?" + item.BiblioInfo.RecPath); writer.WriteAttributeString("timestamp", ByteArray.GetHexTimeStampString(item.BiblioInfo.Timestamp)); - dom.DocumentElement.WriteTo(writer); + biblio_dom.DocumentElement.WriteTo(writer); writer.WriteEndElement(); } + string strBiblioDbName = StringUtil.GetDbName(item.BiblioInfo.RecPath); BiblioDbProperty prop = this.MainForm.GetBiblioDbProperty(strBiblioDbName); if (prop == null) { - strError = "数据库名 '"+strBiblioDbName+"' 没有找到属性定义"; + strError = "数据库名 '" + strBiblioDbName + "' 没有找到属性定义"; goto ERROR1; } @@ -6201,6 +6235,196 @@ void menu_saveToBiblioDumpFile_Click(object sender, EventArgs e) MessageBox.Show(this, strError); } + // 将书目记录中的对象资源写入外部文件 + public static int WriteObjectFiles(Stop stop, + LibraryChannel channel, + string strBiblioRecPath, + ref XmlDocument biblio_dom, + string strOutputDir, + out string strError) + { + strError = ""; + + List recpaths = new List(); + List errors = new List(); + + XmlNamespaceManager nsmgr = new XmlNamespaceManager(new NameTable()); + nsmgr.AddNamespace("dprms", DpNs.dprms); + + XmlNodeList nodes = biblio_dom.DocumentElement.SelectNodes("//dprms:file", nsmgr); + + foreach (XmlElement node in nodes) + { + string strID = DomUtil.GetAttr(node, "id"); + string strUsage = DomUtil.GetAttr(node, "usage"); + string strRights = DomUtil.GetAttr(node, "rights"); + + string strResPath = strBiblioRecPath + "/object/" + strID; + strResPath = strResPath.Replace(":", "/"); + recpaths.Add(strResPath); + } + + try + { + BrowseLoader loader = new BrowseLoader(); + loader.Channel = channel; + loader.Stop = stop; + loader.RecPaths = recpaths; + loader.Format = "id,metadata,timestamp"; + + int i = 0; + foreach (DigitalPlatform.LibraryClient.localhost.Record record in loader) + { + Application.DoEvents(); + + if (stop != null && stop.State != 0) + { + strError = "用户中断"; + return -1; + } + + Debug.Assert(record.Path == recpaths[i], ""); + XmlElement file = nodes[i] as XmlElement; + + if (record.RecordBody.Result != null + && record.RecordBody.Result.ErrorCode != ErrorCodeValue.NoError) + { + if (record.RecordBody.Result.ErrorCode == ErrorCodeValue.NotFound) + goto CONTINUE; + strError = record.RecordBody.Result.ErrorString; + file.SetAttribute("_error", strError); + errors.Add(strError); + goto CONTINUE; + } + + string strMetadataXml = record.RecordBody.Metadata; + byte[] baMetadataTimestamp = record.RecordBody.Timestamp; + + file.SetAttribute("_timestamp", ByteArray.GetHexTimeStampString(baMetadataTimestamp)); + + // TODO: 另一种方法是用 URL 数据库名 ObjectID 等共同构造一个文件名 + string strGUID = Guid.NewGuid().ToString(); + string strMetadataFileName = Path.Combine(strOutputDir, strGUID + ".met"); + string strObjectFileName = Path.Combine(strOutputDir, strGUID + ".bin"); + + // metadata 写入外部文件 + if (string.IsNullOrEmpty(strMetadataXml) == false) + { + PathUtil.CreateDirIfNeed(Path.GetDirectoryName(strMetadataFileName)); + using (StreamWriter sw = new StreamWriter(strMetadataFileName)) + { + sw.Write(strMetadataXml); + } + } + + file.SetAttribute("_metadataFile", Path.GetFileName(strMetadataFileName)); + + // 对象内容写入外部文件 + int nRet = DownloadObject(stop, + channel, + record.Path, + strObjectFileName, + out strError); + if (nRet == -1) + { + // TODO: 是否要重试几次? + file.SetAttribute("error", strError); + errors.Add(strError); + goto CONTINUE; + } + + file.SetAttribute("_objectFile", Path.GetFileName(strObjectFileName)); + +#if NO + // 取metadata值 + Hashtable values = StringUtil.ParseMedaDataXml(strMetadataXml, + out strError); + if (values == null) + { + file.SetAttribute("error", strError); + errors.Add(strError); + continue; + } + + // metadata 中的一些属性,写入 file 元素属性? _ 打头 + // localpath + ListViewUtil.ChangeItemText(item, COLUMN_LOCALPATH, (string)values["localpath"]); + + // size + ListViewUtil.ChangeItemText(item, COLUMN_SIZE, (string)values["size"]); + + // mime + ListViewUtil.ChangeItemText(item, COLUMN_MIME, (string)values["mimetype"]); + + // tiemstamp + string strTimestamp = ByteArray.GetHexTimeStampString(baMetadataTimestamp); + ListViewUtil.ChangeItemText(item, COLUMN_TIMESTAMP, strTimestamp); +#endif + + CONTINUE: + i++; + } + + if (errors.Count > 0) + { + strError = StringUtil.MakePathList(errors, "; "); + return -1; + } + + return 0; + } + catch (Exception ex) + { + // TODO: 出现异常后,是否改为用原来的方法一个一个对象地获取 metadata? + strError = ex.Message; + return -1; + } + } + + static int DownloadObject(Stop stop, + LibraryChannel channel, + string strResPath, + string strOutputFileName, + out string strError) + { + strError = ""; + + PathUtil.CreateDirIfNeed(Path.GetDirectoryName(strOutputFileName)); + + TimeSpan old_timeout = channel.Timeout; + channel.Timeout = new TimeSpan(0, 5, 0); + + if (stop != null) + stop.Initial("正在下载对象 " + strResPath); + try + { + byte[] baOutputTimeStamp = null; + string strMetaData = ""; + string strOutputPath = ""; + + long lRet = channel.GetRes( + stop, + strResPath, + strOutputFileName, + out strMetaData, + out baOutputTimeStamp, + out strOutputPath, + out strError); + if (lRet == -1) + { + strError = "下载对象 '" + strResPath + "' 到文件失败,原因: " + strError; + return -1; + } + return 0; + } + finally + { + channel.Timeout = old_timeout; + if (stop != null) + stop.Initial(""); + } + } + public static int OutputEntities( Stop stop, LibraryChannel channel, diff --git a/dp2Circulation/SearchForms/OpenBiblioDumpFileDialog.Designer.cs b/dp2Circulation/SearchForms/OpenBiblioDumpFileDialog.Designer.cs new file mode 100644 index 000000000..b488d1267 --- /dev/null +++ b/dp2Circulation/SearchForms/OpenBiblioDumpFileDialog.Designer.cs @@ -0,0 +1,232 @@ +namespace dp2Circulation +{ + partial class OpenBiblioDumpFileDialog + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.label1 = new System.Windows.Forms.Label(); + this.textBox_biblioDumpFileName = new System.Windows.Forms.TextBox(); + this.button_getBiblioDumpFileName = new System.Windows.Forms.Button(); + this.button_getObjectDirectoryName = new System.Windows.Forms.Button(); + this.textBox_objectDirectoryName = new System.Windows.Forms.TextBox(); + this.label2 = new System.Windows.Forms.Label(); + this.checkBox_includeObjectFile = new System.Windows.Forms.CheckBox(); + this.checkBox_includeEntities = new System.Windows.Forms.CheckBox(); + this.checkBox_includeIssues = new System.Windows.Forms.CheckBox(); + this.checkBox_includeOrders = new System.Windows.Forms.CheckBox(); + this.checkBox_includeComments = new System.Windows.Forms.CheckBox(); + this.button_Cancel = new System.Windows.Forms.Button(); + this.button_OK = new System.Windows.Forms.Button(); + this.SuspendLayout(); + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(10, 16); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(113, 12); + this.label1.TabIndex = 0; + this.label1.Text = "书目转储文件名(&F):"; + // + // textBox_biblioDumpFileName + // + this.textBox_biblioDumpFileName.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.textBox_biblioDumpFileName.Location = new System.Drawing.Point(12, 31); + this.textBox_biblioDumpFileName.Name = "textBox_biblioDumpFileName"; + this.textBox_biblioDumpFileName.Size = new System.Drawing.Size(380, 21); + this.textBox_biblioDumpFileName.TabIndex = 1; + // + // button_getBiblioDumpFileName + // + this.button_getBiblioDumpFileName.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.button_getBiblioDumpFileName.Location = new System.Drawing.Point(398, 31); + this.button_getBiblioDumpFileName.Name = "button_getBiblioDumpFileName"; + this.button_getBiblioDumpFileName.Size = new System.Drawing.Size(48, 23); + this.button_getBiblioDumpFileName.TabIndex = 2; + this.button_getBiblioDumpFileName.Text = "..."; + this.button_getBiblioDumpFileName.UseVisualStyleBackColor = true; + this.button_getBiblioDumpFileName.Click += new System.EventHandler(this.button_getBiblioDumpFileName_Click); + // + // button_getObjectDirectoryName + // + this.button_getObjectDirectoryName.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.button_getObjectDirectoryName.Location = new System.Drawing.Point(398, 191); + this.button_getObjectDirectoryName.Name = "button_getObjectDirectoryName"; + this.button_getObjectDirectoryName.Size = new System.Drawing.Size(48, 23); + this.button_getObjectDirectoryName.TabIndex = 10; + this.button_getObjectDirectoryName.Text = "..."; + this.button_getObjectDirectoryName.UseVisualStyleBackColor = true; + this.button_getObjectDirectoryName.Click += new System.EventHandler(this.button_getObjectDirectoryName_Click); + // + // textBox_objectDirectoryName + // + this.textBox_objectDirectoryName.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.textBox_objectDirectoryName.Location = new System.Drawing.Point(36, 193); + this.textBox_objectDirectoryName.Name = "textBox_objectDirectoryName"; + this.textBox_objectDirectoryName.Size = new System.Drawing.Size(356, 21); + this.textBox_objectDirectoryName.TabIndex = 9; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(34, 178); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(101, 12); + this.label2.TabIndex = 8; + this.label2.Text = "对象文件目录(&O):"; + // + // checkBox_includeObjectFile + // + this.checkBox_includeObjectFile.AutoSize = true; + this.checkBox_includeObjectFile.Checked = true; + this.checkBox_includeObjectFile.CheckState = System.Windows.Forms.CheckState.Checked; + this.checkBox_includeObjectFile.Location = new System.Drawing.Point(12, 159); + this.checkBox_includeObjectFile.Name = "checkBox_includeObjectFile"; + this.checkBox_includeObjectFile.Size = new System.Drawing.Size(114, 16); + this.checkBox_includeObjectFile.TabIndex = 7; + this.checkBox_includeObjectFile.Text = "包含对象文件(&O)"; + this.checkBox_includeObjectFile.UseVisualStyleBackColor = true; + this.checkBox_includeObjectFile.CheckedChanged += new System.EventHandler(this.checkBox_includeObjectFile_CheckedChanged); + // + // checkBox_includeEntities + // + this.checkBox_includeEntities.AutoSize = true; + this.checkBox_includeEntities.Checked = true; + this.checkBox_includeEntities.CheckState = System.Windows.Forms.CheckState.Checked; + this.checkBox_includeEntities.Location = new System.Drawing.Point(12, 65); + this.checkBox_includeEntities.Name = "checkBox_includeEntities"; + this.checkBox_includeEntities.Size = new System.Drawing.Size(102, 16); + this.checkBox_includeEntities.TabIndex = 3; + this.checkBox_includeEntities.Text = "包含册记录(&E)"; + this.checkBox_includeEntities.UseVisualStyleBackColor = true; + // + // checkBox_includeIssues + // + this.checkBox_includeIssues.AutoSize = true; + this.checkBox_includeIssues.Checked = true; + this.checkBox_includeIssues.CheckState = System.Windows.Forms.CheckState.Checked; + this.checkBox_includeIssues.Location = new System.Drawing.Point(12, 87); + this.checkBox_includeIssues.Name = "checkBox_includeIssues"; + this.checkBox_includeIssues.Size = new System.Drawing.Size(102, 16); + this.checkBox_includeIssues.TabIndex = 4; + this.checkBox_includeIssues.Text = "包含期记录(&I)"; + this.checkBox_includeIssues.UseVisualStyleBackColor = true; + // + // checkBox_includeOrders + // + this.checkBox_includeOrders.AutoSize = true; + this.checkBox_includeOrders.Checked = true; + this.checkBox_includeOrders.CheckState = System.Windows.Forms.CheckState.Checked; + this.checkBox_includeOrders.Location = new System.Drawing.Point(12, 107); + this.checkBox_includeOrders.Name = "checkBox_includeOrders"; + this.checkBox_includeOrders.Size = new System.Drawing.Size(114, 16); + this.checkBox_includeOrders.TabIndex = 5; + this.checkBox_includeOrders.Text = "包含订购记录(&O)"; + this.checkBox_includeOrders.UseVisualStyleBackColor = true; + // + // checkBox_includeComments + // + this.checkBox_includeComments.AutoSize = true; + this.checkBox_includeComments.Checked = true; + this.checkBox_includeComments.CheckState = System.Windows.Forms.CheckState.Checked; + this.checkBox_includeComments.Location = new System.Drawing.Point(12, 129); + this.checkBox_includeComments.Name = "checkBox_includeComments"; + this.checkBox_includeComments.Size = new System.Drawing.Size(114, 16); + this.checkBox_includeComments.TabIndex = 6; + this.checkBox_includeComments.Text = "包含评注记录(&C)"; + this.checkBox_includeComments.UseVisualStyleBackColor = true; + // + // button_Cancel + // + this.button_Cancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.button_Cancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.button_Cancel.Location = new System.Drawing.Point(371, 247); + this.button_Cancel.Name = "button_Cancel"; + this.button_Cancel.Size = new System.Drawing.Size(75, 23); + this.button_Cancel.TabIndex = 12; + this.button_Cancel.Text = "取消"; + this.button_Cancel.UseVisualStyleBackColor = true; + this.button_Cancel.Click += new System.EventHandler(this.button_Cancel_Click); + // + // button_OK + // + this.button_OK.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.button_OK.Location = new System.Drawing.Point(290, 247); + this.button_OK.Name = "button_OK"; + this.button_OK.Size = new System.Drawing.Size(75, 23); + this.button_OK.TabIndex = 11; + this.button_OK.Text = "确定"; + this.button_OK.UseVisualStyleBackColor = true; + this.button_OK.Click += new System.EventHandler(this.button_OK_Click); + // + // OpenBiblioDumpFileDialog + // + this.AcceptButton = this.button_OK; + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this.button_Cancel; + this.ClientSize = new System.Drawing.Size(458, 282); + this.Controls.Add(this.button_OK); + this.Controls.Add(this.button_Cancel); + this.Controls.Add(this.checkBox_includeComments); + this.Controls.Add(this.checkBox_includeOrders); + this.Controls.Add(this.checkBox_includeIssues); + this.Controls.Add(this.checkBox_includeEntities); + this.Controls.Add(this.checkBox_includeObjectFile); + this.Controls.Add(this.button_getObjectDirectoryName); + this.Controls.Add(this.textBox_objectDirectoryName); + this.Controls.Add(this.label2); + this.Controls.Add(this.button_getBiblioDumpFileName); + this.Controls.Add(this.textBox_biblioDumpFileName); + this.Controls.Add(this.label1); + this.Name = "OpenBiblioDumpFileDialog"; + this.Text = "打开书目转储文件"; + this.Load += new System.EventHandler(this.OpenBiblioDumpFileDialog_Load); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Label label1; + private System.Windows.Forms.TextBox textBox_biblioDumpFileName; + private System.Windows.Forms.Button button_getBiblioDumpFileName; + private System.Windows.Forms.Button button_getObjectDirectoryName; + private System.Windows.Forms.TextBox textBox_objectDirectoryName; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.CheckBox checkBox_includeObjectFile; + private System.Windows.Forms.CheckBox checkBox_includeEntities; + private System.Windows.Forms.CheckBox checkBox_includeIssues; + private System.Windows.Forms.CheckBox checkBox_includeOrders; + private System.Windows.Forms.CheckBox checkBox_includeComments; + private System.Windows.Forms.Button button_Cancel; + private System.Windows.Forms.Button button_OK; + } +} \ No newline at end of file diff --git a/dp2Circulation/SearchForms/OpenBiblioDumpFileDialog.cs b/dp2Circulation/SearchForms/OpenBiblioDumpFileDialog.cs new file mode 100644 index 000000000..0857f1cb9 --- /dev/null +++ b/dp2Circulation/SearchForms/OpenBiblioDumpFileDialog.cs @@ -0,0 +1,235 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Windows.Forms; + +namespace dp2Circulation +{ + public partial class OpenBiblioDumpFileDialog : Form + { + bool _createMode = false; + + /// + /// 是否为创建模式?false 表示打开模式 + /// + public bool CreateMode + { + get + { + return _createMode; + } + set + { + _createMode = value; + if (value == true) + { + this.Text = "创建书目转储文件"; + } + else + { + this.Text = "打开书目转储文件"; + } + } + } + + public OpenBiblioDumpFileDialog() + { + InitializeComponent(); + } + + private void OpenBiblioDumpFileDialog_Load(object sender, EventArgs e) + { + + } + + private void button_OK_Click(object sender, EventArgs e) + { + string strError = ""; + + if (string.IsNullOrEmpty(this.textBox_biblioDumpFileName.Text) == true) + { + strError = "尚未指定书目转储文件名"; + goto ERROR1; + } + + if (string.IsNullOrEmpty(this.textBox_objectDirectoryName.Text) == true + && this.checkBox_includeObjectFile.Checked == true) + { + strError = "尚未指定对象文件目录"; + goto ERROR1; + } + + // TODO: CreateMode 为 true 情况下,警告对象文件目录里面已经有了文件 + + this.DialogResult = System.Windows.Forms.DialogResult.OK; + this.Close(); + return; + ERROR1: + MessageBox.Show(this, strError); + } + + private void button_Cancel_Click(object sender, EventArgs e) + { + this.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.Close(); + } + + private void button_getBiblioDumpFileName_Click(object sender, EventArgs e) + { + if (this.CreateMode) + { + // 询问文件名 + SaveFileDialog dlg = new SaveFileDialog(); + + dlg.Title = "请指定要创建的书目转储文件名"; + dlg.CreatePrompt = false; + dlg.OverwritePrompt = true; + dlg.FileName = this.textBox_biblioDumpFileName.Text; + // dlg.InitialDirectory = Environment.CurrentDirectory; + dlg.Filter = "书目转储文件 (*.bdf)|*.bdf|All files (*.*)|*.*"; + + dlg.RestoreDirectory = true; + + if (dlg.ShowDialog() != DialogResult.OK) + return; + + this.textBox_biblioDumpFileName.Text = dlg.FileName; + } + else + { + OpenFileDialog dlg = new OpenFileDialog(); + + dlg.Title = "请指定要打开的书目转储文件名"; + dlg.FileName = this.textBox_biblioDumpFileName.Text; + dlg.Filter = "书目转储文件 (*.bdf)|*.bdf|All files (*.*)|*.*"; + dlg.RestoreDirectory = true; + + if (dlg.ShowDialog() != DialogResult.OK) + return; + + this.textBox_biblioDumpFileName.Text = dlg.FileName; + } + + if (string.IsNullOrEmpty(this.textBox_objectDirectoryName.Text)) + this.textBox_objectDirectoryName.Text = this.textBox_biblioDumpFileName.Text + ".object"; + } + + private void button_getObjectDirectoryName_Click(object sender, EventArgs e) + { + FolderBrowserDialog dir_dlg = new FolderBrowserDialog(); + + dir_dlg.Description = "请指定对象文件所在目录:"; + dir_dlg.RootFolder = Environment.SpecialFolder.MyComputer; + dir_dlg.ShowNewFolderButton = this.CreateMode; + dir_dlg.SelectedPath = this.textBox_objectDirectoryName.Text; + + if (dir_dlg.ShowDialog() != DialogResult.OK) + return; + + this.textBox_objectDirectoryName.Text = dir_dlg.SelectedPath; + } + + private void checkBox_includeObjectFile_CheckedChanged(object sender, EventArgs e) + { + if (this.checkBox_includeObjectFile.Checked) + { + this.textBox_objectDirectoryName.Enabled = true; + this.button_getObjectDirectoryName.Enabled = true; + } + else + { + this.textBox_objectDirectoryName.Enabled = false; + this.textBox_objectDirectoryName.Text = ""; + this.button_getObjectDirectoryName.Enabled = false; + } + } + + public string FileName + { + get + { + return this.textBox_biblioDumpFileName.Text; + } + set + { + this.textBox_biblioDumpFileName.Text = value; + } + } + + public string ObjectDirectoryName + { + get + { + return this.textBox_objectDirectoryName.Text; + } + set + { + this.textBox_biblioDumpFileName.Text = value; + } + } + + public bool IncludeEntities + { + get + { + return this.checkBox_includeEntities.Checked; + } + set + { + this.checkBox_includeEntities.Checked = value; + } + } + + public bool IncludeIssues + { + get + { + return this.checkBox_includeIssues.Checked; + } + set + { + this.checkBox_includeIssues.Checked = value; + } + } + + public bool IncludeOrders + { + get + { + return this.checkBox_includeOrders.Checked; + } + set + { + this.checkBox_includeOrders.Checked = value; + } + } + + public bool IncludeComments + { + get + { + return this.checkBox_includeComments.Checked; + } + set + { + this.checkBox_includeComments.Checked = value; + } + } + + public bool IncludeObjectFile + { + get + { + return this.checkBox_includeObjectFile.Checked; + } + set + { + this.checkBox_includeObjectFile.Checked = value; + } + } + } +} diff --git a/dp2Circulation/SearchForms/OpenBiblioDumpFileDialog.resx b/dp2Circulation/SearchForms/OpenBiblioDumpFileDialog.resx new file mode 100644 index 000000000..1af7de150 --- /dev/null +++ b/dp2Circulation/SearchForms/OpenBiblioDumpFileDialog.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/dp2Circulation/dp2Circulation.csproj b/dp2Circulation/dp2Circulation.csproj index 4801b58b5..a55d06d9b 100644 --- a/dp2Circulation/dp2Circulation.csproj +++ b/dp2Circulation/dp2Circulation.csproj @@ -2148,6 +2148,9 @@ OneActionDialog.cs + + OpenBiblioDumpFileDialog.cs + Designer SettlementForm.cs @@ -2328,6 +2331,12 @@ OneActionDialog.cs + + Form + + + OpenBiblioDumpFileDialog.cs + Form diff --git a/dp2Installer/dp2Installer.csproj b/dp2Installer/dp2Installer.csproj index 64fc60210..3aa7365d4 100644 --- a/dp2Installer/dp2Installer.csproj +++ b/dp2Installer/dp2Installer.csproj @@ -34,7 +34,7 @@ dp2 V2 true publish.htm - 112 + 114 1.1.0.%2a false true diff --git a/dp2Installer/library_data/templates/reader/keys b/dp2Installer/library_data/templates/reader/keys index 6d336209f..4023af2c4 100644 --- a/dp2Installer/library_data/templates/reader/keys +++ b/dp2Installer/library_data/templates/reader/keys @@ -152,7 +152,7 @@ public class MyKeysHost : KeysHost
- + diff --git a/dp2Installer/library_data/templates/reader/keys_recover b/dp2Installer/library_data/templates/reader/keys_recover index 39f3ae5f4..8d783b953 100644 --- a/dp2Installer/library_data/templates/reader/keys_recover +++ b/dp2Installer/library_data/templates/reader/keys_recover @@ -152,7 +152,7 @@ public class MyKeysHost : KeysHost
- + diff --git a/dp2LibraryXE/dp2LibraryXE.csproj b/dp2LibraryXE/dp2LibraryXE.csproj index 468fd028d..3629d9b8a 100644 --- a/dp2LibraryXE/dp2LibraryXE.csproj +++ b/dp2LibraryXE/dp2LibraryXE.csproj @@ -36,7 +36,7 @@ dp2 V2 true publish.htm - 75 + 78 1.1.0.%2a false true diff --git a/dp2LibraryXE/library_data/templates/reader/keys b/dp2LibraryXE/library_data/templates/reader/keys index 6d336209f..4023af2c4 100644 --- a/dp2LibraryXE/library_data/templates/reader/keys +++ b/dp2LibraryXE/library_data/templates/reader/keys @@ -152,7 +152,7 @@ public class MyKeysHost : KeysHost
- + diff --git a/dp2LibraryXE/library_data/templates/reader/keys_recover b/dp2LibraryXE/library_data/templates/reader/keys_recover index 39f3ae5f4..8d783b953 100644 --- a/dp2LibraryXE/library_data/templates/reader/keys_recover +++ b/dp2LibraryXE/library_data/templates/reader/keys_recover @@ -152,7 +152,7 @@ public class MyKeysHost : KeysHost
- + From 7152c72057592c78d73e5929027e3ea4c8c4cbf1 Mon Sep 17 00:00:00 2001 From: XieTao Date: Mon, 11 Apr 2016 22:28:11 +0800 Subject: [PATCH 10/10] =?UTF-8?q?=E7=A6=81=E6=AD=A2=E4=B8=BA=E8=AF=BB?= =?UTF-8?q?=E8=80=85=E8=AE=B0=E5=BD=95=E7=9A=84=E5=AD=98=E5=8F=96=E5=AE=9A?= =?UTF-8?q?=E4=B9=89=E4=BD=BF=E7=94=A8=E4=B8=80=E4=B8=AA=E6=98=9F=E5=8F=B7?= =?UTF-8?q?=E7=9A=84=E9=82=A3=E7=A7=8D=E5=BD=A2=E6=80=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DigitalPlatform.LibraryServer/AppScript.cs | 9 +++++++++ DigitalPlatform.LibraryServer/LibraryApplication.cs | 8 ++++++++ dp2Installer/dp2Installer.csproj | 2 +- 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/DigitalPlatform.LibraryServer/AppScript.cs b/DigitalPlatform.LibraryServer/AppScript.cs index 876395685..62a08386a 100644 --- a/DigitalPlatform.LibraryServer/AppScript.cs +++ b/DigitalPlatform.LibraryServer/AppScript.cs @@ -1420,6 +1420,15 @@ public virtual int VerifyReader( return 1; } + // 2016/4/11 + // 检查 access 元素里面的星号 + string strAccess = DomUtil.GetElementText(readerdom.DocumentElement, "access"); + if (strAccess != null && strAccess.Trim() == "*") + { + strError = "读者记录中 access 元素值不允许使用 * 形态"; + return -1; + } + return 0; } diff --git a/DigitalPlatform.LibraryServer/LibraryApplication.cs b/DigitalPlatform.LibraryServer/LibraryApplication.cs index f45e7869c..8e429ca97 100644 --- a/DigitalPlatform.LibraryServer/LibraryApplication.cs +++ b/DigitalPlatform.LibraryServer/LibraryApplication.cs @@ -9461,6 +9461,14 @@ public int LoginForReader(SessionInfo sessioninfo, return -1; } + // 检查 access 元素里面的星号 + string strAccess = DomUtil.GetElementText(readerdom.DocumentElement, "access"); + if (strAccess != null && strAccess.Trim() == "*") + { + strError = "读者记录中 access 元素值不允许使用 * 形态"; + return -1; + } + // 获得一个参考帐户 Account accountref = null; // 从library.xml文件定义 获得一个帐户的信息 diff --git a/dp2Installer/dp2Installer.csproj b/dp2Installer/dp2Installer.csproj index 3aa7365d4..13267eb49 100644 --- a/dp2Installer/dp2Installer.csproj +++ b/dp2Installer/dp2Installer.csproj @@ -34,7 +34,7 @@ dp2 V2 true publish.htm - 114 + 115 1.1.0.%2a false true