From eea7d10ed5671821767a016d21e824864da49bc1 Mon Sep 17 00:00:00 2001 From: XieTao Date: Tue, 12 Apr 2016 15:50:35 +0800 Subject: [PATCH 01/14] =?UTF-8?q?=E6=95=B4=E7=90=86=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DigitalPlatform.LibraryServer/AppScript.cs | 2 +- .../LibraryApplication.cs | 74 +++++++++++-- DigitalPlatform.OPAC.Web/LoginControl.cs | 2 +- DigitalPlatform.dp2.Statis/ClosedXmlUtil.cs | 9 ++ .../DongshifangMessageHost.cs | 2 +- dp2Circulation/Reader/ReaderSearchForm.cs | 100 ++++++++++++++---- .../SearchForms/BiblioSearchForm.cs | 54 ++++++++++ dp2Circulation/dp2Circulation.csproj | 2 +- 8 files changed, 208 insertions(+), 37 deletions(-) diff --git a/DigitalPlatform.LibraryServer/AppScript.cs b/DigitalPlatform.LibraryServer/AppScript.cs index 62a08386a..209ff34be 100644 --- a/DigitalPlatform.LibraryServer/AppScript.cs +++ b/DigitalPlatform.LibraryServer/AppScript.cs @@ -1425,7 +1425,7 @@ public virtual int VerifyReader( string strAccess = DomUtil.GetElementText(readerdom.DocumentElement, "access"); if (strAccess != null && strAccess.Trim() == "*") { - strError = "读者记录中 access 元素值不允许使用 * 形态"; + strError = "读者记录中的存取定义(access 元素值)不允许使用 * 形态"; return -1; } diff --git a/DigitalPlatform.LibraryServer/LibraryApplication.cs b/DigitalPlatform.LibraryServer/LibraryApplication.cs index 8e429ca97..ea2f23c97 100644 --- a/DigitalPlatform.LibraryServer/LibraryApplication.cs +++ b/DigitalPlatform.LibraryServer/LibraryApplication.cs @@ -8294,7 +8294,6 @@ public int SearchInventoryRecDup( return -1; } - // 将登录名切割为前缀和名字值两个部分 void SplitLoginName(string strLoginName, out string strPrefix, @@ -8771,6 +8770,7 @@ public int ConvertReaderXmlToHtml( } */ + // 重设密码 // parameters: // strMessageTempate 消息文字模板。其中可以使用 %name% %barcode% %temppassword% %expiretime% %period% 等宏 // return: @@ -8904,12 +8904,64 @@ public int ResetPassword( // 观察 password 元素的 lastResetTime 属性,需在规定的时间长度以外才能再次进行重设 - // 核对 barcode - string strBarcode = DomUtil.GetElementText(readerdom.DocumentElement, "barcode"); - if (strBarcode.Trim() != strLoginName.Trim()) + string strBarcode = DomUtil.GetElementText(readerdom.DocumentElement, "barcode"); { - strError = "证条码号不匹配"; - return -1; + string strPrefix = ""; + string strValue = ""; + // 将登录名切割为前缀和名字值两个部分 + SplitLoginName(strLoginName, + out strPrefix, + out strValue); + + if (string.IsNullOrEmpty(strPrefix) == true) + { + // 核对 barcode + if (strBarcode.Trim() != strLoginName.Trim()) + { + strError = "证条码号不匹配"; + return -1; + } + } + if (strPrefix == "EM:") // 注意,整个 strLoginName 应该是 EM:email:xxxxx 这样的形态 + { + // 核对 Email + string strEmail = DomUtil.GetElementText(readerdom.DocumentElement, "email"); + if (StringUtil.SplitList(strEmail).IndexOf(strValue) == -1) + { + strError = "地址 '"+strValue+"' 不匹配"; + return -1; + } + } + if (strPrefix == "TP:") + { + // 核对 电话号码 + string strTel1 = DomUtil.GetElementText(readerdom.DocumentElement, "tel"); + if (StringUtil.SplitList(strTel1).IndexOf(strValue) == -1) + { + strError = "电话号码不匹配"; + return -1; + } + } + if (strPrefix == "ID:") + { + // 核对 身份证号 + string strID = DomUtil.GetElementText(readerdom.DocumentElement, "idCardNumber"); + if (strID != strValue) + { + strError = "身份证号不匹配"; + return -1; + } + } + if (strPrefix == "CN:") + { + // 核对 身份证号 + string strCN = DomUtil.GetElementText(readerdom.DocumentElement, "cardNumber"); + if (strCN != strValue) + { + strError = "证号不匹配"; + return -1; + } + } } // 核对 name @@ -8974,13 +9026,13 @@ public int ResetPassword( string strExpireTime = DateTimeUtil.Rfc1123DateTimeStringEx(expire); if (string.IsNullOrEmpty(strMessageTemplate) == true) - strMessageTemplate = "尊敬的 %name% 您好!\n您的读者帐户(证条码号为 %barcode%)已设临时密码 %temppassword%,若您在 %period% 内用它登录会自动变为正式密码"; + strMessageTemplate = "%name% 您好!\n您的读者帐户(证条码号为 %barcode%)已设临时密码 %temppassword%,在 %period% 内登录会成为正式密码"; string strBody = strMessageTemplate.Replace("%barcode%", strBarcode) .Replace("%name%", strName) .Replace("%temppassword%", strReaderTempPassword) .Replace("%expiretime%", expire.ToLongTimeString()) - .Replace("%period%", "一个小时"); + .Replace("%period%", "一小时"); // string strBody = "读者(证条码号) " + strBarcode + " 的帐户密码已经被重设为 " + strReaderNewPassword + ""; // 向手机号码发送短信 @@ -9309,7 +9361,7 @@ public static int VerifyToken( // 还可以为 token: 形态 // nIndex 如果有多个匹配的读者记录,此参数表示要选择其中哪一个。 // 如果为-1,表示首次调用此函数,还不知如何选择。如此时命中多个,函数会返回>1的值 - // strGetToken 是否要获得 token ,和有效期。 空 / day / month / year + // strGetToken 是否要获得 token ,和有效期。 空 / day / month / year // strOutputUserName 返回读者证条码号 // return: // -1 error @@ -9457,7 +9509,7 @@ public int LoginForReader(SessionInfo sessioninfo, out strError); if (nRet == -1) { - strError = "装载读者记录进入XML DOM时发生错误: " + strError; + strError = "装载读者记录进入 XML DOM 时发生错误: " + strError; return -1; } @@ -9465,7 +9517,7 @@ public int LoginForReader(SessionInfo sessioninfo, string strAccess = DomUtil.GetElementText(readerdom.DocumentElement, "access"); if (strAccess != null && strAccess.Trim() == "*") { - strError = "读者记录中 access 元素值不允许使用 * 形态"; + strError = "读者记录中的存取定义(access 元素值)不允许使用 * 形态"; return -1; } diff --git a/DigitalPlatform.OPAC.Web/LoginControl.cs b/DigitalPlatform.OPAC.Web/LoginControl.cs index 26f7e3772..92f3fb151 100644 --- a/DigitalPlatform.OPAC.Web/LoginControl.cs +++ b/DigitalPlatform.OPAC.Web/LoginControl.cs @@ -427,7 +427,7 @@ public bool ResetPassword get { OpacApplication app = (OpacApplication)this.Page.Application["app"]; - bool bValue = true; + bool bValue = false; // 2016/4/12 修改 XmlNode node = app.WebUiDom.DocumentElement.SelectSingleNode("loginControl"); if (node != null) { diff --git a/DigitalPlatform.dp2.Statis/ClosedXmlUtil.cs b/DigitalPlatform.dp2.Statis/ClosedXmlUtil.cs index f809c7533..d3cad4db7 100644 --- a/DigitalPlatform.dp2.Statis/ClosedXmlUtil.cs +++ b/DigitalPlatform.dp2.Statis/ClosedXmlUtil.cs @@ -187,6 +187,15 @@ public static int ExportToExcel( doc.SaveAs(dlg.FileName); doc.Dispose(); + + try + { + System.Diagnostics.Process.Start(dlg.FileName); + } + catch + { + + } return 1; } } diff --git a/DongshifangMessageInterface/DongshifangMessageHost.cs b/DongshifangMessageInterface/DongshifangMessageHost.cs index 5141b58a8..371cd99b2 100644 --- a/DongshifangMessageInterface/DongshifangMessageHost.cs +++ b/DongshifangMessageInterface/DongshifangMessageHost.cs @@ -69,7 +69,7 @@ public override int SendMessage( out strError); if (nRet <= 0) { - strError = "发送出错,错误码 [" + nRet.ToString() + "]"; + strError = "发送出错,错误码 [" + nRet.ToString() + "],错误信息:" + strError; return -1; } diff --git a/dp2Circulation/Reader/ReaderSearchForm.cs b/dp2Circulation/Reader/ReaderSearchForm.cs index 8c8835bc2..3ac15df47 100644 --- a/dp2Circulation/Reader/ReaderSearchForm.cs +++ b/dp2Circulation/Reader/ReaderSearchForm.cs @@ -32,6 +32,7 @@ using DigitalPlatform.CirculationClient; using DigitalPlatform.LibraryClient; using DigitalPlatform.LibraryClient.localhost; +using DigitalPlatform.dp2.Statis; namespace dp2Circulation { @@ -1409,33 +1410,40 @@ private void listView_records_MouseUp(object sender, MouseEventArgs e) menuItem.Enabled = false; contextMenu.MenuItems.Add(menuItem); #endif + bool bSearching = !this.textBox_queryWord.Enabled; - // --- - menuItem = new MenuItem("-"); - contextMenu.MenuItems.Add(menuItem); + // 导出 + { + menuItem = new MenuItem("导出(&X)"); + contextMenu.MenuItems.Add(menuItem); - bool bSearching = !this.textBox_queryWord.Enabled; + MenuItem subMenuItem = new MenuItem("导出到条码号文件 [" + this.listView_records.SelectedItems.Count.ToString() + " ] (&B)"); + subMenuItem.Click += new System.EventHandler(this.menu_exportBarcodeFile_Click); + if (this.listView_records.SelectedItems.Count == 0 + || bSearching == true) + subMenuItem.Enabled = false; + menuItem.MenuItems.Add(subMenuItem); - menuItem = new MenuItem("导出到条码号文件 [" + this.listView_records.SelectedItems.Count.ToString() + " ] (&B)"); - menuItem.Click += new System.EventHandler(this.menu_exportBarcodeFile_Click); - if (this.listView_records.SelectedItems.Count == 0 - || bSearching == true) - menuItem.Enabled = false; - contextMenu.MenuItems.Add(menuItem); + subMenuItem = new MenuItem("导出到记录路径文件 [" + this.listView_records.SelectedItems.Count.ToString() + "] (&P)"); + subMenuItem.Click += new System.EventHandler(this.menu_exportRecPathFile_Click); + if (this.listView_records.SelectedItems.Count == 0 + || bSearching == true) + subMenuItem.Enabled = false; + menuItem.MenuItems.Add(subMenuItem); - menuItem = new MenuItem("导出到记录路径文件 [" + this.listView_records.SelectedItems.Count.ToString() + "] (&P)"); - menuItem.Click += new System.EventHandler(this.menu_exportRecPathFile_Click); - if (this.listView_records.SelectedItems.Count == 0 - || bSearching == true) - menuItem.Enabled = false; - contextMenu.MenuItems.Add(menuItem); + subMenuItem = new MenuItem("到 Excel 文件 [" + this.listView_records.SelectedItems.Count.ToString() + "] (&E)..."); + subMenuItem.Click += new System.EventHandler(this.menu_exportExcelFile_Click); + if (this.listView_records.SelectedItems.Count == 0 + || bSearching == true) + subMenuItem.Enabled = false; + menuItem.MenuItems.Add(subMenuItem); - menuItem = new MenuItem("导出读者详情到 Excel 文件 [" + this.listView_records.SelectedItems.Count.ToString() + "] (&D)"); - menuItem.Click += new System.EventHandler(this.menu_exportReaderInfoToExcelFile_Click); - if (this.listView_records.SelectedItems.Count == 0 - || bSearching == true) - menuItem.Enabled = false; - contextMenu.MenuItems.Add(menuItem); + subMenuItem = new MenuItem("导出读者详情到 Excel 文件 [" + this.listView_records.SelectedItems.Count.ToString() + "] (&D)"); + subMenuItem.Click += new System.EventHandler(this.menu_exportReaderInfoToExcelFile_Click); + if (this.listView_records.SelectedItems.Count == 0 + || bSearching == true) + subMenuItem.Enabled = false; + menuItem.MenuItems.Add(subMenuItem); #if NO menuItem = new MenuItem("导出借阅历史到 Excel 文件 [" + this.listView_records.SelectedItems.Count.ToString() + "] (&D)"); @@ -1445,6 +1453,7 @@ private void listView_records_MouseUp(object sender, MouseEventArgs e) menuItem.Enabled = false; contextMenu.MenuItems.Add(menuItem); #endif + } // --- menuItem = new MenuItem("-"); @@ -1496,6 +1505,53 @@ private void listView_records_MouseUp(object sender, MouseEventArgs e) contextMenu.Show(this.listView_records, new Point(e.X, e.Y)); } + // 导出选择的行到 Excel 文件 + void menu_exportExcelFile_Click(object sender, EventArgs e) + { + string strError = ""; + + if (this.listView_records.SelectedItems.Count == 0) + { + strError = "尚未选定要导出的事项"; + goto ERROR1; + } + + List items = new List(); + foreach (ListViewItem item in this.listView_records.SelectedItems) + { + items.Add(item); + } + stop.Style = StopStyle.EnableHalfStop; + stop.OnStop += new StopEventHandler(this.DoStop); + stop.Initial("正在导出选定的事项到 Excel 文件 ..."); + stop.BeginLoop(); + + this.EnableControls(false); + try + { + int nRet = ClosedXmlUtil.ExportToExcel( + stop, + items, + out strError); + if (nRet == -1) + goto ERROR1; + } + finally + { + stop.EndLoop(); + stop.OnStop -= new StopEventHandler(this.DoStop); + stop.Initial(""); + stop.HideProgress(); + stop.Style = StopStyle.None; + + this.EnableControls(true); + } + + return; + ERROR1: + MessageBox.Show(this, strError); + } + void menu_verifyPatronRecord_Click(object sender, EventArgs e) { string strError = ""; diff --git a/dp2Circulation/SearchForms/BiblioSearchForm.cs b/dp2Circulation/SearchForms/BiblioSearchForm.cs index 3ff4da3c4..f02fbf397 100644 --- a/dp2Circulation/SearchForms/BiblioSearchForm.cs +++ b/dp2Circulation/SearchForms/BiblioSearchForm.cs @@ -27,6 +27,7 @@ // using DigitalPlatform.LibraryClient.localhost; using DigitalPlatform.LibraryClient; using DigitalPlatform.LibraryClient.localhost; +using DigitalPlatform.dp2.Statis; namespace dp2Circulation { @@ -2097,6 +2098,12 @@ private void listView_records_MouseUp(object sender, MouseEventArgs e) subMenuItem.Enabled = false; menuItem.MenuItems.Add(subMenuItem); + subMenuItem = new MenuItem("到 Excel 文件 [" + nSelectedItemCount.ToString() + "] (&E)..."); + subMenuItem.Click += new System.EventHandler(this.menu_exportExcelFile_Click); + if (nSelectedItemCount == 0) + subMenuItem.Enabled = false; + menuItem.MenuItems.Add(subMenuItem); + // --- subMenuItem = new MenuItem("-"); menuItem.MenuItems.Add(subMenuItem); @@ -2219,6 +2226,53 @@ private void listView_records_MouseUp(object sender, MouseEventArgs e) contextMenu.Show(this.listView_records, new Point(e.X, e.Y)); } + // 导出选择的行到 Excel 文件 + void menu_exportExcelFile_Click(object sender, EventArgs e) + { + string strError = ""; + + if (this.listView_records.SelectedItems.Count == 0) + { + strError = "尚未选定要导出的事项"; + goto ERROR1; + } + + List items = new List(); + foreach (ListViewItem item in this.listView_records.SelectedItems) + { + items.Add(item); + } + stop.Style = StopStyle.EnableHalfStop; + stop.OnStop += new StopEventHandler(this.DoStop); + stop.Initial("正在导出选定的事项到 Excel 文件 ..."); + stop.BeginLoop(); + + this.EnableControls(false); + try + { + int nRet = ClosedXmlUtil.ExportToExcel( + stop, + items, + out strError); + if (nRet == -1) + goto ERROR1; + } + finally + { + stop.EndLoop(); + stop.OnStop -= new StopEventHandler(this.DoStop); + stop.Initial(""); + stop.HideProgress(); + stop.Style = StopStyle.None; + + this.EnableControls(true); + } + + return; + ERROR1: + MessageBox.Show(this, strError); + } + void menu_printClaim_Click(object sender, EventArgs e) { string strError = ""; diff --git a/dp2Circulation/dp2Circulation.csproj b/dp2Circulation/dp2Circulation.csproj index a55d06d9b..99fbbc293 100644 --- a/dp2Circulation/dp2Circulation.csproj +++ b/dp2Circulation/dp2Circulation.csproj @@ -51,7 +51,7 @@ dp2 V2 true publish.htm - 40 + 41 2.10.0.%2a false true From 058339da32ce3da9dde2418abd64c890b0ec9002 Mon Sep 17 00:00:00 2001 From: XieTao Date: Tue, 12 Apr 2016 21:13:01 +0800 Subject: [PATCH 02/14] =?UTF-8?q?=E5=8A=A0=E5=9B=BA=E6=8A=A5=E8=A1=A8?= =?UTF-8?q?=E7=AA=97=E5=8F=A3=E9=A6=96=E6=AC=A1=E5=88=9B=E5=BB=BA=E6=9C=AC?= =?UTF-8?q?=E5=9C=B0=E5=AD=98=E5=82=A8=E7=9A=84=E9=83=A8=E5=88=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dp2Circulation/Statis/ReportForm.cs | 21 +++++++++++++++++++-- dp2Circulation/dp2Circulation.csproj | 2 +- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/dp2Circulation/Statis/ReportForm.cs b/dp2Circulation/Statis/ReportForm.cs index ee5a95e69..0decf0832 100644 --- a/dp2Circulation/Statis/ReportForm.cs +++ b/dp2Circulation/Statis/ReportForm.cs @@ -499,9 +499,17 @@ int BuildItemRecords( } // 处理浏览结果 - for (int i = 0; i < searchresults.Length; i++) + int i = 0; + foreach(DigitalPlatform.LibraryClient.localhost.Record searchresult in searchresults) { - DigitalPlatform.LibraryClient.localhost.Record searchresult = searchresults[i]; + // DigitalPlatform.LibraryClient.localhost.Record searchresult = searchresults[i]; + + // 2016/4/12 + // 检查事项状态。主动抛出异常,避免后面出现 index 异常 + if (searchresult.Cols == null) + throw new Exception("浏览事项 Cols 为空: (lStart="+lStart+" index="+i+") " + DumpResultItem(searchresult)); + if (searchresult.Cols.Length < 11) + throw new Exception("浏览事项异常: (lStart=" + lStart + " index=" + i + ") " + DumpResultItem(searchresult)); ItemLine line = new ItemLine(); line.ItemRecPath = searchresult.Path; @@ -577,6 +585,8 @@ int BuildItemRecords( line.BiblioRecPath = strBiblioRecPath; lines.Add(line); + + i++; } if (true) @@ -637,6 +647,13 @@ int BuildItemRecords( } } + static string DumpResultItem(DigitalPlatform.LibraryClient.localhost.Record searchresult) + { + if (searchresult.Cols == null) + return "path=" + searchresult.Path + ";cols=[null]"; + return "path=" + searchresult.Path + ";cols("+searchresult.Cols.Length.ToString()+")=" + string.Join("|", searchresult.Cols); + } + // safe set progress value, between max and min void SetProgress(long lProgress) { diff --git a/dp2Circulation/dp2Circulation.csproj b/dp2Circulation/dp2Circulation.csproj index 99fbbc293..512059042 100644 --- a/dp2Circulation/dp2Circulation.csproj +++ b/dp2Circulation/dp2Circulation.csproj @@ -51,7 +51,7 @@ dp2 V2 true publish.htm - 41 + 42 2.10.0.%2a false true From fcddba56d4f84d272ba447a7a73bfa157f277b08 Mon Sep 17 00:00:00 2001 From: XieTao Date: Wed, 13 Apr 2016 21:17:25 +0800 Subject: [PATCH 03/14] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E8=87=AA=E5=8A=A8?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=85=A8=E9=83=A8=E8=AF=BB=E8=80=85=E5=92=8C?= =?UTF-8?q?=E5=86=8C=E7=9A=84=E5=80=9F=E9=98=85=E4=BF=A1=E6=81=AF=E9=93=BE?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AppCirculation.cs | 237 ++++++- .../LibraryService.cs | 2 +- dp2Catalog/Z39.50/ZBatchSearchForm.cs | 5 + dp2Circulation/CheckBorrowInfoForm.cs | 655 ++++++++++++------ dp2Circulation/dp2Circulation.csproj | 2 +- dp2Installer/dp2Installer.csproj | 2 +- dp2LibraryXE/dp2LibraryXE.csproj | 2 +- 7 files changed, 684 insertions(+), 221 deletions(-) diff --git a/DigitalPlatform.LibraryServer/AppCirculation.cs b/DigitalPlatform.LibraryServer/AppCirculation.cs index 5a96d895c..5ae6d4cee 100644 --- a/DigitalPlatform.LibraryServer/AppCirculation.cs +++ b/DigitalPlatform.LibraryServer/AppCirculation.cs @@ -1219,6 +1219,7 @@ out BorrowInfo borrow_info // 2007/12/6 // 校验读者证条码号参数是否和XML记录中完全一致 +#if NO string strTempReaderBarcode = DomUtil.GetElementText(readerdom.DocumentElement, "barcode"); @@ -1229,10 +1230,26 @@ out BorrowInfo borrow_info // 2007/12/6 strError = "借阅操作被拒绝。因读者证条码号参数 '" + strReaderBarcode + "' 和读者记录中元素内的读者证条码号值 '" + strTempReaderBarcode + "' 不一致。"; goto ERROR1; } +#endif + { + // return: + // false 不匹配 + // true 匹配 + bool bRet = CheckBarcode(readerdom, + strReaderBarcode, + "读者", + out strError); + if (bRet == false) + { + strError = "借阅操作被拒绝。因" + strError + "。"; + goto ERROR1; + } + } // 2007/1/2 // 校验册条码号参数是否和XML记录中完全一致 +#if NO string strRefID = ""; string strHead = "@refID:"; // string strFrom = "册条码"; @@ -1261,6 +1278,22 @@ out BorrowInfo borrow_info // 2007/12/6 goto ERROR1; } } +#endif + { + // return: + // false 不匹配 + // true 匹配 + bool bRet = CheckBarcode(itemdom, + strItemBarcode, + "册", + out strError); + if (bRet == false) + { + // text-level: 内部错误 + strError = "借阅操作被拒绝。因" + strError + "。"; + goto ERROR1; + } + } string strReaderType = DomUtil.GetElementText(readerdom.DocumentElement, "readerType"); @@ -2372,7 +2405,7 @@ LibraryServerResult GetReaderRecord( // 看看读者记录所从属的数据库,是否在参与流通的读者库之列 // 2008/6/4 - if (bVerifyReaderRecPath == true + if (bVerifyReaderRecPath == true && String.IsNullOrEmpty(strOutputReaderRecPath) == false) { if (this.TestMode == true || sessioninfo.TestMode == true) @@ -4941,7 +4974,7 @@ public LibraryServerResult Return( } } - DomUtil.SetElementText(domOperLog.DocumentElement, + DomUtil.SetElementText(domOperLog.DocumentElement, "biblioRecPath", strBiblioRecPath); goto WRITE_OPERLOG; } @@ -15837,8 +15870,6 @@ public LibraryServerResult CheckReaderBorrowInfo( nErrorCount++; } } - - } finally { @@ -16228,6 +16259,7 @@ public LibraryServerResult RepairReaderSideError( } // 校验读者证条码号参数是否和XML记录中完全一致 +#if NO string strTempBarcode = DomUtil.GetElementText(readerdom.DocumentElement, "barcode"); if (strReaderBarcode != strTempBarcode) @@ -16235,6 +16267,21 @@ public LibraryServerResult RepairReaderSideError( strError = "修复操作被拒绝。因读者证条码号参数 '" + strReaderBarcode + "' 和读者记录中元素内的读者证条码号值 '" + strTempBarcode + "' 不一致。"; goto ERROR1; } +#endif + { + // return: + // false 不匹配 + // true 匹配 + bool bRet = CheckBarcode(readerdom, + strReaderBarcode, + "读者", + out strError); + if (bRet == false) + { + strError = "修复操作被拒绝。因" + strError + "。"; + goto ERROR1; + } + } XmlNode nodeBorrow = readerdom.DocumentElement.SelectSingleNode("borrows/borrow[@barcode='" + strItemBarcode + "']"); if (nodeBorrow == null) @@ -16336,11 +16383,9 @@ public LibraryServerResult RepairReaderSideError( aDupPath = new string[aPath.Count]; aPath.CopyTo(aDupPath); return result; - } else { - Debug.Assert(nRet == 1, ""); Debug.Assert(aPath.Count == 1, ""); @@ -16361,6 +16406,8 @@ public LibraryServerResult RepairReaderSideError( goto ERROR1; } +#if NO + // TODO: 要实现 strItemBarcode 为 @refID:xxxxx 的情况。因为现在允许册记录没有册条码号了 // 校验册条码号参数是否和XML记录中完全一致 string strTempItemBarcode = DomUtil.GetElementText(itemdom.DocumentElement, "barcode"); @@ -16369,6 +16416,21 @@ public LibraryServerResult RepairReaderSideError( strError = "修复操作被拒绝。因册条码号参数 '" + strItemBarcode + "' 和册记录中元素内的册条码号值 '" + strTempItemBarcode + "' 不一致。"; goto ERROR1; } +#endif + { + // return: + // false 不匹配 + // true 匹配 + bool bRet = CheckBarcode(itemdom, + strItemBarcode, + "册", + out strError); + if (bRet == false) + { + strError = "修复操作被拒绝。因" + strError + "。"; + goto ERROR1; + } + } // 看看册记录中是否有指回读者记录的链 string strBorrower = DomUtil.GetElementText(itemdom.DocumentElement, @@ -16376,7 +16438,7 @@ public LibraryServerResult RepairReaderSideError( if (strBorrower == strReaderBarcode) { strError = "修复操作被拒绝。您所请求要修复的链,本是一条完整正确的链。可直接进行普通还书操作。"; - goto ERROR1; + goto CORRECT; } DELETE_CHAIN: @@ -16481,6 +16543,11 @@ public LibraryServerResult RepairReaderSideError( result.ErrorInfo = strError; result.ErrorCode = ErrorCode.SystemError; return result; + CORRECT: + result.Value = -1; + result.ErrorInfo = strError; + result.ErrorCode = ErrorCode.NoError; // 表示链条本来就没有错误 + return result; } // 修复册记录一侧的借阅信息链条错误 @@ -16534,6 +16601,11 @@ public LibraryServerResult RepairItemSideError( string strReaderXml = ""; string strOutputReaderRecPath = ""; byte[] reader_timestamp = null; + // return: + // -1 error + // 0 not found + // 1 命中1条 + // >1 命中多于1条 nRet = this.GetReaderRecXml( // sessioninfo.Channels, channel, @@ -16548,15 +16620,30 @@ public LibraryServerResult RepairItemSideError( goto ERROR1; } - string strLibraryCode = ""; - // 观察一个读者记录路径,看看是不是在当前用户管辖的读者库范围内? - if (this.IsCurrentChangeableReaderPath(strOutputReaderRecPath, - sessioninfo.LibraryCodeList, - out strLibraryCode) == false) + if (nRet == 0) { - strError = "读者记录路径 '" + strOutputReaderRecPath + "' 的读者库不在当前用户管辖范围内"; + // 对应的读者记录不存在。就无法检查读者所在的馆代码了 + } + else if (nRet > 1) + { + strError = "证条码号为 '" + strReaderBarcode + "' 的读者记录存在 " + nRet + " 条。请先修复此问题,再重试修复册记录的链问题"; goto ERROR1; } + else + { + Debug.Assert(string.IsNullOrEmpty(strOutputReaderRecPath) == false, ""); + + string strLibraryCode = ""; + + // 观察一个读者记录路径,看看是不是在当前用户管辖的读者库范围内? + if (this.IsCurrentChangeableReaderPath(strOutputReaderRecPath, + sessioninfo.LibraryCodeList, + out strLibraryCode) == false) + { + strError = "读者记录路径 '" + strOutputReaderRecPath + "' 的读者库不在当前用户管辖范围内"; + goto ERROR1; + } + } XmlDocument readerdom = null; if (nRet == 0) @@ -16577,8 +16664,8 @@ public LibraryServerResult RepairItemSideError( goto ERROR1; } - // 校验读者证条码号参数是否和XML记录中完全一致 +#if NO string strTempBarcode = DomUtil.GetElementText(readerdom.DocumentElement, "barcode"); if (strReaderBarcode != strTempBarcode) @@ -16586,6 +16673,19 @@ public LibraryServerResult RepairItemSideError( strError = "修复操作被拒绝。因读者证条码号参数 '" + strReaderBarcode + "' 和读者记录中元素内的读者证条码号值 '" + strTempBarcode + "' 不一致。"; goto ERROR1; } +#endif + // return: + // false 不匹配 + // true 匹配 + bool bRet = CheckBarcode(readerdom, + strReaderBarcode, + "读者", + out strError); + if (bRet == false) + { + strError = "修复操作被拒绝。因" + strError + "。"; + goto ERROR1; + } } byte[] item_timestamp = null; @@ -16699,6 +16799,29 @@ public LibraryServerResult RepairItemSideError( goto ERROR1; } + string strLibraryCode = ""; + // 检查一个册记录的馆藏地点是否符合馆代码列表要求 + // return: + // -1 检查过程出错 + // 0 符合要求 + // 1 不符合要求 + nRet = CheckItemLibraryCode(itemdom, + sessioninfo, + out strLibraryCode, + out strError); + if (nRet == -1) + { + strError = "检查分馆代码时出错: " + strError; + goto ERROR1; + } + if (nRet == 1) + { + strError = "册记录 '" + strOutputItemRecPath + "' 不在当前用户管辖范围内"; + goto ERROR1; + } + +#if NO + // TODO: 要考虑 @refID:xxxx 形态。可以编写一个检查函数 // 校验册条码号参数是否和XML记录中完全一致 string strTempItemBarcode = DomUtil.GetElementText(itemdom.DocumentElement, "barcode"); @@ -16707,6 +16830,19 @@ public LibraryServerResult RepairItemSideError( strError = "修复操作被拒绝。因册条码号参数 '" + strItemBarcode + "' 和册记录中元素内的册条码号值 '" + strTempItemBarcode + "' 不一致。"; goto ERROR1; } +#endif + // return: + // false 不匹配 + // true 匹配 + bool bRet = CheckBarcode(itemdom, + strItemBarcode, + "册", + out strError); + if (bRet == false) + { + strError = "修复操作被拒绝。因" + strError + "。"; + goto ERROR1; + } // 看看册记录中是否有指向读者记录的链 string strBorrower = DomUtil.GetElementText(itemdom.DocumentElement, @@ -16714,7 +16850,7 @@ public LibraryServerResult RepairItemSideError( if (String.IsNullOrEmpty(strBorrower) == true) { strError = "修复操作被拒绝。您所请求要修复的册记录中,本来就没有借阅信息,因此谈不上修复。"; - goto ERROR1; + goto CORRECT; } if (strBorrower != strReaderBarcode) @@ -16737,12 +16873,21 @@ public LibraryServerResult RepairItemSideError( // DELETE_CHAIN: // 移除册记录侧的链 - DomUtil.SetElementText(itemdom.DocumentElement, - "borrower", ""); - DomUtil.SetElementText(itemdom.DocumentElement, - "borrowDate", ""); - DomUtil.SetElementText(itemdom.DocumentElement, - "borrowPeriod", ""); + DomUtil.DeleteElement(itemdom.DocumentElement, + "borrower"); + DomUtil.DeleteElement(itemdom.DocumentElement, + "borrowDate"); + DomUtil.DeleteElement(itemdom.DocumentElement, + "borrowPeriod"); + DomUtil.DeleteElement(itemdom.DocumentElement, + "borrowerReaderType"); + DomUtil.DeleteElement(itemdom.DocumentElement, + "borrowerRecPath"); + DomUtil.DeleteElement(itemdom.DocumentElement, + "returningDate"); + DomUtil.DeleteElement(itemdom.DocumentElement, + "operator"); + DomUtil.RemoveEmptyElements(itemdom.DocumentElement); byte[] output_timestamp = null; string strOutputPath = ""; @@ -16775,7 +16920,7 @@ public LibraryServerResult RepairItemSideError( domOperLog.LoadXml(""); DomUtil.SetElementText(domOperLog.DocumentElement, "libraryCode", - strLibraryCode); // 读者所在的馆代码 + strLibraryCode); // 册所在的馆代码 DomUtil.SetElementText(domOperLog.DocumentElement, "operation", "repairBorrowInfo"); DomUtil.SetElementText(domOperLog.DocumentElement, "action", "repairitemside"); DomUtil.SetElementText(domOperLog.DocumentElement, "readerBarcode", strReaderBarcode); @@ -16810,7 +16955,6 @@ public LibraryServerResult RepairItemSideError( // 解册记录锁 this.EntityLocks.UnlockForWrite(strItemBarcode); } - } finally { @@ -16826,6 +16970,53 @@ public LibraryServerResult RepairItemSideError( result.ErrorInfo = strError; result.ErrorCode = ErrorCode.SystemError; return result; + CORRECT: + result.Value = -1; + result.ErrorInfo = strError; + result.ErrorCode = ErrorCode.NoError; // 表示链条本来就没有错误 + return result; + } + + // 检查条码号参数和记录中的字段是否匹配 + // parameters: + // strRecordTypeCaption 记录类型。 册/读者 + // return: + // false 不匹配 + // true 匹配 + static bool CheckBarcode(XmlDocument itemdom, + string strItemBarcode, + string strRecordTypeCaption, + out string strError) + { + strError = ""; + + string strRefID = ""; + string strHead = "@refID:"; + if (StringUtil.HasHead(strItemBarcode, strHead, true) == true) + { + // strFrom = "参考ID"; + strRefID = strItemBarcode.Substring(strHead.Length); + + string strTempRefID = DomUtil.GetElementText(itemdom.DocumentElement, +"refID"); + if (strRefID != strTempRefID) + { + strError = "参考ID参数 '" + strRefID + "' 和" + strRecordTypeCaption + "记录中元素(参考ID)值 '" + strTempRefID + "' 不一致"; + return false; + } + } + else + { + string strTempItemBarcode = DomUtil.GetElementText(itemdom.DocumentElement, +"barcode"); + if (strItemBarcode != strTempItemBarcode) + { + strError = strRecordTypeCaption + "条码号参数 '" + strItemBarcode + "' 和" + strRecordTypeCaption + "记录中元素内的条码号值 '" + strTempItemBarcode + "' 不一致"; + return false; + } + } + + return true; } // 入馆登记 diff --git a/DigitalPlatform.LibraryService/LibraryService.cs b/DigitalPlatform.LibraryService/LibraryService.cs index 0a8f57881..c9a01893e 100644 --- a/DigitalPlatform.LibraryService/LibraryService.cs +++ b/DigitalPlatform.LibraryService/LibraryService.cs @@ -11273,7 +11273,7 @@ public LibraryServerResult RepairBorrowInfo( if (StringUtil.IsInList("repairborrowinfo", sessioninfo.RightsOrigin) == false) { result.Value = -1; - result.ErrorInfo = "修复借还信息的操作被拒绝。不具备repairborrowinfo权限。"; + result.ErrorInfo = "修复借还信息的操作被拒绝。不具备 repairborrowinfo 权限。"; result.ErrorCode = ErrorCode.AccessDenied; return result; } diff --git a/dp2Catalog/Z39.50/ZBatchSearchForm.cs b/dp2Catalog/Z39.50/ZBatchSearchForm.cs index e80301e39..a6e58772b 100644 --- a/dp2Catalog/Z39.50/ZBatchSearchForm.cs +++ b/dp2Catalog/Z39.50/ZBatchSearchForm.cs @@ -538,6 +538,11 @@ int DoSearch(out string strError) this.dpTable_records.Rows.Clear(); // TODO: 清除前,如果发现未保存,要警告 TreeNode node = this.zTargetControl1.SelectedNode; + if (node == null) + { + strError = "当前尚未选择检索目标节点,无法启动检索"; + return -1; + } node.Expand(); diff --git a/dp2Circulation/CheckBorrowInfoForm.cs b/dp2Circulation/CheckBorrowInfoForm.cs index 4935966d0..673ac36d5 100644 --- a/dp2Circulation/CheckBorrowInfoForm.cs +++ b/dp2Circulation/CheckBorrowInfoForm.cs @@ -121,19 +121,22 @@ private void CheckBorrowInfoForm_FormClosed(object sender, FormClosedEventArgs e private void button_beginCheckFromReader_Click(object sender, EventArgs e) { string strError = ""; + + bool bAutoRepair = Control.ModifierKeys == Keys.Control; + List barcodes = null; int nRet = SearchAllReaderBarcode(out barcodes, out strError); if (nRet == -1) goto ERROR1; - nRet = CheckAllReaderRecord(barcodes, + nRet = CheckReaderRecords(barcodes, + bAutoRepair, out strError); if (nRet == -1) goto ERROR1; MessageBox.Show(this, "OK"); - return; ERROR1: MessageBox.Show(this, strError); @@ -177,7 +180,7 @@ int SearchAllReaderBarcode(out List barcodes, stop.SetProgressRange(0, lCount); Global.WriteHtml(this.webBrowser_resultInfo, - "共有 "+lHitCount.ToString()+" 条读者记录。\r\n"); + "共有 " + lHitCount.ToString() + " 条读者记录。\r\n"); Record[] searchresults = null; @@ -207,7 +210,7 @@ int SearchAllReaderBarcode(out List barcodes, if (lRet == 0) { - strError = "未命中"; + strError = "未命中"; goto ERROR1; } @@ -228,7 +231,7 @@ int SearchAllReaderBarcode(out List barcodes, lStart += searchresults.Length; lCount -= searchresults.Length; - stop.SetMessage("共有条码 " + lHitCount .ToString()+ " 个。已获得条码 " + lStart.ToString() + " 个"); + stop.SetMessage("共有条码 " + lHitCount.ToString() + " 个。已获得条码 " + lStart.ToString() + " 个"); stop.SetProgressValue(lStart); if (lStart >= lHitCount || lCount <= 0) @@ -281,14 +284,20 @@ int SearchAllReaderBarcode(out List barcodes, return -1; } - int CheckAllReaderRecord(List barcodes, + // parameters: + // bAutoRepair 是否同时自动修复 + int CheckReaderRecords(List barcodes, + bool bAutoRepair, out string strError) { strError = ""; long lRet = 0; stop.OnStop += new StopEventHandler(this.DoStop); - stop.Initial("正在进行检查 ..."); + if (bAutoRepair) + stop.Initial("正在进行检查和自动修复 ..."); + else + stop.Initial("正在进行检查 ..."); stop.BeginLoop(); EnableControls(false); @@ -297,10 +306,18 @@ int CheckAllReaderRecord(List barcodes, try { Global.WriteHtml(this.webBrowser_resultInfo, - "正在进行检查...\r\n"); + "\r\n" + DateTime.Now.ToString() + "\r\n"); + + if (bAutoRepair) + Global.WriteHtml(this.webBrowser_resultInfo, + "正在进行检查和自动修复...\r\n"); + else + Global.WriteHtml(this.webBrowser_resultInfo, + "正在进行检查...\r\n"); stop.SetProgressRange(0, barcodes.Count); int nCount = 0; + int nRepairedCount = 0; for (int i = 0; i < barcodes.Count; i++) { Application.DoEvents(); // 出让界面控制权 @@ -314,7 +331,7 @@ int CheckAllReaderRecord(List barcodes, string strReaderBarcode = barcodes[i]; string strOutputReaderBarcode = ""; - stop.SetMessage("正在检查第 "+(i+1).ToString()+" 个读者记录,条码为 " + strReaderBarcode ); + stop.SetMessage("正在检查第 " + (i + 1).ToString() + " 个读者记录,条码为 " + strReaderBarcode); stop.SetProgressValue(i); int nStart = 0; @@ -322,9 +339,9 @@ int CheckAllReaderRecord(List barcodes, int nProcessedBorrowItems = 0; int nTotalBorrowItems = 0; + bool bFoundError = false; for (; ; ) { - lRet = Channel.RepairBorrowInfo( stop, "checkfromreader", @@ -345,7 +362,6 @@ int CheckAllReaderRecord(List barcodes, strOffsComment = "(偏移量" + nStart.ToString() + "开始的" + nProcessedBorrowItems + "个借阅册)"; } - if (lRet == -1) { Global.WriteHtml(this.webBrowser_resultInfo, @@ -355,6 +371,7 @@ int CheckAllReaderRecord(List barcodes, { Global.WriteHtml(this.webBrowser_resultInfo, "检查读者记录 " + strReaderBarcode + " 时" + strOffsComment + "发现问题: " + strError + "\r\n"); + bFoundError = true; } if (nTotalBorrowItems > 0 && nProcessedBorrowItems == 0) @@ -369,14 +386,20 @@ int CheckAllReaderRecord(List barcodes, break; } + string strReaderXml = ""; + string strReaderRecPath = ""; // 读者证条码号查重 - if (this.checkBox_checkReaderBarcodeDup.Checked == true) + if (this.checkBox_checkReaderBarcodeDup.Checked == true + || bFoundError) { + byte[] baTimestamp = null; string[] results = null; lRet = Channel.GetReaderInfo(stop, strReaderBarcode, "xml", out results, + out strReaderRecPath, + out baTimestamp, out strError); if (lRet == -1) { @@ -388,15 +411,39 @@ int CheckAllReaderRecord(List barcodes, Global.WriteHtml(this.webBrowser_resultInfo, "读者证条码号 " + strReaderBarcode + " 有重复记录 " + lRet.ToString() + "条\r\n"); } + if (lRet == 1) + { + strReaderXml = results[0]; + } } + if (bFoundError && string.IsNullOrEmpty(strReaderXml) == false) + { + int nRet = RepairAllErrorFromReaderSide(strReaderRecPath, + strReaderXml, + out strError); + if (nRet == -1) + { + Global.WriteHtml(this.webBrowser_resultInfo, + "*** 修复读者记录 " + strReaderBarcode + " 内链条问题时出错: " + strError + "\r\n"); + } + else + { + Global.WriteHtml(this.webBrowser_resultInfo, + "- 成功修复读者记录 " + strReaderBarcode + " 内链条问题\r\n"); + nRepairedCount++; + } + } nCount++; } - Global.WriteHtml(this.webBrowser_resultInfo, - "检查结束。共检查读者记录 " + nCount.ToString() + " 条。\r\n"); - + if (bAutoRepair) + Global.WriteHtml(this.webBrowser_resultInfo, + "修复结束。共检查读者记录 " + nCount.ToString() + " 条,修复有问题的读者记录 " + nRepairedCount.ToString() + " 条。\r\n"); + else + Global.WriteHtml(this.webBrowser_resultInfo, + "检查结束。共检查读者记录 " + nCount.ToString() + " 条。\r\n"); } finally @@ -410,7 +457,6 @@ int CheckAllReaderRecord(List barcodes, } return 0; - ERROR1: return -1; } @@ -456,19 +502,22 @@ public override void EnableControls(bool bEnable) private void button_beginCheckFromItem_Click(object sender, EventArgs e) { string strError = ""; + + bool bAutoRepair = Control.ModifierKeys == Keys.Control; + List barcodes = null; int nRet = SearchAllItemBarcode(out barcodes, out strError); if (nRet == -1) goto ERROR1; - nRet = CheckAllItemRecord(barcodes, + nRet = CheckItemRecords(barcodes, + bAutoRepair, out strError); if (nRet == -1) goto ERROR1; MessageBox.Show(this, "OK"); - return; ERROR1: MessageBox.Show(this, strError); @@ -583,7 +632,7 @@ int SearchAllItemBarcode(out List barcodes, { string strBarcode = barcodes[i]; - for (int j = i+1; j < barcodes.Count; j++) + for (int j = i + 1; j < barcodes.Count; j++) { if (strBarcode == barcodes[j]) { @@ -736,14 +785,19 @@ int SearchAllItemBarcode(string strBarcodeFilename, return -1; } - - int CheckAllItemRecord(List barcodes, + // parameters: + // bAutoRepair 是否同时自动修复 + int CheckItemRecords(List barcodes, + bool bAutoRepair, out string strError) { strError = ""; stop.OnStop += new StopEventHandler(this.DoStop); - stop.Initial("正在进行检查 ..."); + if (bAutoRepair) + stop.Initial("正在进行检查和自动修复 ..."); + else + stop.Initial("正在进行检查 ..."); stop.BeginLoop(); EnableControls(false); @@ -752,11 +806,19 @@ int CheckAllItemRecord(List barcodes, try { Global.WriteHtml(this.webBrowser_resultInfo, - "正在进行检查...\r\n"); +"\r\n" + DateTime.Now.ToString() + "\r\n"); + + if (bAutoRepair) + Global.WriteHtml(this.webBrowser_resultInfo, + "正在进行检查和自动修复...\r\n"); + else + Global.WriteHtml(this.webBrowser_resultInfo, + "正在进行检查...\r\n"); stop.SetProgressRange(0, barcodes.Count); int nCount = 0; + int nRepairedCount = 0; for (int i = 0; i < barcodes.Count; i++) { Application.DoEvents(); // 出让界面控制权 @@ -798,10 +860,9 @@ int CheckAllItemRecord(List barcodes, Global.WriteHtml(this.webBrowser_resultInfo, "检查册记录 " + strItemBarcode + " 时发现册条码号命中重复记录 " + aDupPath.Length.ToString() + "个 -- " + StringUtil.MakePathList(aDupPath) + "。\r\n"); - for (int j = 0; j < aDupPath.Length; j++) { - string strText = " 检查其中第 "+(j+1).ToString()+" 个,路径为 " + aDupPath[j] + ": "; + string strText = " 检查其中第 " + (j + 1).ToString() + " 个,路径为 " + aDupPath[j] + ": "; string[] aDupPathTemp = null; // string strOutputReaderBarcode = ""; @@ -828,6 +889,23 @@ int CheckAllItemRecord(List barcodes, Global.WriteHtml(this.webBrowser_resultInfo, strText); + + { + int nRet = RepairErrorFromItemSide(strItemBarcode, + aDupPath[j], + out strError); + if (nRet == -1) + { + Global.WriteHtml(this.webBrowser_resultInfo, + "*** 修复册记录 " + strItemBarcode + " 内链条问题时出错: " + strError + "\r\n"); + } + else + { + Global.WriteHtml(this.webBrowser_resultInfo, + "- 成功修复册记录 " + strItemBarcode + " 内链条问题\r\n"); + nRepairedCount++; + } + } } } // end of for @@ -848,6 +926,22 @@ int CheckAllItemRecord(List barcodes, { Global.WriteHtml(this.webBrowser_resultInfo, "检查册记录 " + strItemBarcode + " 时发现问题: " + strError + "\r\n"); + { + int nRet = RepairErrorFromItemSide(strItemBarcode, + "", + out strError); + if (nRet == -1) + { + Global.WriteHtml(this.webBrowser_resultInfo, + "*** 修复册记录 " + strItemBarcode + " 内链条问题时出错: " + strError + "\r\n"); + } + else + { + Global.WriteHtml(this.webBrowser_resultInfo, + "- 成功修复册记录 " + strItemBarcode + " 内链条问题\r\n"); + nRepairedCount++; + } + } } continue; } // end of return -1 @@ -859,40 +953,16 @@ int CheckAllItemRecord(List barcodes, } if (lRet == 1) { + Debug.Assert(false, "应该走不到这里"); Global.WriteHtml(this.webBrowser_resultInfo, "检查册记录 " + strItemBarcode + " 时发现问题: " + strError + "\r\n"); } - - /* - if (this.checkBox_checkItemBarcodeDup.Checked == true) - { - string[] paths = null; - lRet = Channel.SearchItemDup(stop, - strItemBarcode, - 100, - out paths, - out strError); - if (lRet == -1) - { - Global.WriteHtml(this.webBrowser_resultInfo, - "对册条码号 " + strItemBarcode + " 查重时出错: " + strError + "\r\n"); - } - if (lRet > 1) - { - Global.WriteHtml(this.webBrowser_resultInfo, - "册条码号 " + strItemBarcode + " 有重复记录 " + paths.Length.ToString() + "条\r\n"); - } - } - * */ - nCount++; } Global.WriteHtml(this.webBrowser_resultInfo, "检查结束。共检查册记录 " + nCount.ToString() + " 条。\r\n"); - - } finally { @@ -913,7 +983,9 @@ int CheckAllItemRecord(List barcodes, private void button_repairReaderSide_Click(object sender, EventArgs e) { string strError = ""; - int nRet = RepairError( + int nRet = 0; + + nRet = RepairError( "repairreaderside", this.textBox_readerBarcode.Text, this.textBox_itemBarcode.Text, @@ -928,6 +1000,198 @@ private void button_repairReaderSide_Click(object sender, EventArgs e) } + // 从册侧出发,修复一个册记录和相关读者记录的链条错误 + // return: + // -1 错误。 + // 0 没有必要修复 + // 1 已经修复 + int RepairErrorFromItemSide(string strItemBarcode, + string strConfirmItemRecPath, + out string strError) + { + strError = ""; + + // 获得册记录 + string strBiblioRecPath = ""; + string strItemRecPath = ""; + byte[] item_timestamp = null; + + string strItemXml = ""; + string strBiblioText = ""; + + // Result.Value -1出错 0没有找到 1找到 >1命中多于1条 + long lRet = Channel.GetItemInfo( + stop, + strItemBarcode, + "xml", // strResultType + out strItemXml, + out strItemRecPath, + out item_timestamp, + "", // strBiblioType + out strBiblioText, + out strBiblioRecPath, + out strError); + if (lRet == -1) + { + // 改用 strConfirmItemRecPath 试一下 + if (string.IsNullOrEmpty(strConfirmItemRecPath) == false) + { + lRet = Channel.GetItemInfo( +stop, +"@path:" + strConfirmItemRecPath, +"xml", // strResultType +out strItemXml, +out strItemRecPath, +out item_timestamp, +"", // strBiblioType +out strBiblioText, +out strBiblioRecPath, +out strError); + if (lRet == -1) + { + strError = "获取路径为 '" + strConfirmItemRecPath + "' 的册记录时出错:" + strError; + return -1; + } + } + strError = "获取册条码号为 '" + strItemBarcode + "' 的册记录时出错:" + strError; + return -1; + } + + XmlDocument itemdom = new XmlDocument(); + try + { + itemdom.LoadXml(strItemXml); + } + catch (Exception ex) + { + strError = "册记录装入 XMLDOM 时出错: " + ex.Message; + return -1; + } + + strItemBarcode = DomUtil.GetElementText(itemdom.DocumentElement, "barcode"); + if (string.IsNullOrEmpty(strItemBarcode)) + { + strItemBarcode = DomUtil.GetElementText(itemdom.DocumentElement, "refID"); + if (string.IsNullOrEmpty(strItemBarcode)) + { + strError = "册记录中既没有证条码号,也没有 参考 ID 字段内容,无法进行修复"; + return -1; + } + strItemBarcode = "@refID:" + strItemBarcode; + } + + string strBorrower = DomUtil.GetElementText(itemdom.DocumentElement, "borrower"); + if (string.IsNullOrEmpty(strBorrower) == true) + { + strError = "没有必要修复"; + return 0; + } + + string[] aDupPath = null; + + string strOutputReaderBarcode = ""; + int nProcessedBorrowItems = 0; + int nTotalBorrowItems = 0; + lRet = Channel.RepairBorrowInfo( + stop, + "repairitemside", + strBorrower, + strItemBarcode, + strConfirmItemRecPath, + 0, + -1, + out nProcessedBorrowItems, // 2008/10/27 + out nTotalBorrowItems, // 2008/10/27 + out strOutputReaderBarcode, + out aDupPath, + out strError); + if (lRet == -1) + { + if (Channel.ErrorCode == ErrorCode.NoError) + return 0; + return -1; + } + else + return 1; + } + + // 从读者侧出发,修复一个读者记录中,所有册记录的链条错误 + // return: + // -1 错误。可能有部分册已经修复成功 + // 其他 共修复多少个册事项 + int RepairAllErrorFromReaderSide(string strReaderRecPath, + string strReaderXml, + out string strError) + { + strError = ""; + + XmlDocument readerdom = new XmlDocument(); + try + { + readerdom.LoadXml(strReaderXml); + } + catch (Exception ex) + { + strError = "读者记录装入 XMLDOM 时出错: " + ex.Message; + return -1; + } + + string strReaderBarcode = DomUtil.GetElementText(readerdom.DocumentElement, "barcode"); + if (string.IsNullOrEmpty(strReaderBarcode)) + { + strReaderBarcode = DomUtil.GetElementText(readerdom.DocumentElement, "refID"); + if (string.IsNullOrEmpty(strReaderBarcode)) + { + strError = "读者记录 '" + strReaderRecPath + "' 中既没有证条码号,也没有 参考 ID 字段内容,无法进行修复"; + return -1; + } + strReaderBarcode = "@refID:" + strReaderBarcode; + } + + int nRepairedCount = 0; + List errors = new List(); + + XmlNodeList nodes = readerdom.DocumentElement.SelectNodes("borrows/borrow"); + foreach (XmlElement borrow in nodes) + { + string strItemBarcode = borrow.GetAttribute("barcode"); + string strConfirmItemRecPath = borrow.GetAttribute("recPath"); + + string[] aDupPath = null; + + string strOutputReaderBarcode = ""; + int nProcessedBorrowItems = 0; + int nTotalBorrowItems = 0; + long lRet = Channel.RepairBorrowInfo( + stop, + "repairreaderside", + strReaderBarcode, + strItemBarcode, + strConfirmItemRecPath, + 0, + -1, + out nProcessedBorrowItems, // 2008/10/27 + out nTotalBorrowItems, // 2008/10/27 + out strOutputReaderBarcode, + out aDupPath, + out strError); + if (lRet == -1) + { + if (Channel.ErrorCode != ErrorCode.NoError) + errors.Add(strError); + } + else + nRepairedCount++; + } + + if (errors.Count > 0) + { + strError = StringUtil.MakePathList(errors, "; "); + return -1; + } + return nRepairedCount; + } + int RepairError( string strAction, string strReaderBarcode, @@ -948,70 +1212,70 @@ int RepairError( try { - string strConfirmItemRecPath = ""; - REDO: - string[] aDupPath = null; + string strConfirmItemRecPath = ""; + REDO: + string[] aDupPath = null; - string strOutputReaderBarcode = ""; + string strOutputReaderBarcode = ""; - long lRet = Channel.RepairBorrowInfo( - stop, - strAction, // "repairreaderside", - strReaderBarcode, - strItemBarcode, - strConfirmItemRecPath, - 0, - -1, - out nProcessedBorrowItems, // 2008/10/27 - out nTotalBorrowItems, // 2008/10/27 - out strOutputReaderBarcode, - out aDupPath, - out strError); - if (lRet == -1) + long lRet = Channel.RepairBorrowInfo( + stop, + strAction, // "repairreaderside", + strReaderBarcode, + strItemBarcode, + strConfirmItemRecPath, + 0, + -1, + out nProcessedBorrowItems, // 2008/10/27 + out nTotalBorrowItems, // 2008/10/27 + out strOutputReaderBarcode, + out aDupPath, + out strError); + if (lRet == -1) + { + if (Channel.ErrorCode == ErrorCode.ItemBarcodeDup) { - if (Channel.ErrorCode == ErrorCode.ItemBarcodeDup) + // this.MainForm.PrepareSearch(); + LibraryChannel channel = this.MainForm.GetChannel(); + try { - // this.MainForm.PrepareSearch(); - LibraryChannel channel = this.MainForm.GetChannel(); - try + ItemBarcodeDupDlg dupdlg = new ItemBarcodeDupDlg(); + MainForm.SetControlFont(dupdlg, this.Font, false); + string strErrorNew = ""; + int nRet = dupdlg.Initial( + this.MainForm, + aDupPath, + "因册条码号发生重复,修复操作被拒绝。\r\n\r\n可根据下面列出的详细信息,选择适当的册记录,重试操作。\r\n\r\n原始出错信息:\r\n" + strError, + channel, // this.MainForm.Channel, + this.MainForm.Stop, + out strErrorNew); + if (nRet == -1) { - ItemBarcodeDupDlg dupdlg = new ItemBarcodeDupDlg(); - MainForm.SetControlFont(dupdlg, this.Font, false); - string strErrorNew = ""; - int nRet = dupdlg.Initial( - this.MainForm, - aDupPath, - "因册条码号发生重复,修复操作被拒绝。\r\n\r\n可根据下面列出的详细信息,选择适当的册记录,重试操作。\r\n\r\n原始出错信息:\r\n" + strError, - channel, // this.MainForm.Channel, - this.MainForm.Stop, - out strErrorNew); - if (nRet == -1) - { - // 初始化对话框失败 - MessageBox.Show(this, strErrorNew); - goto ERROR1; - } + // 初始化对话框失败 + MessageBox.Show(this, strErrorNew); + goto ERROR1; + } - this.MainForm.AppInfo.LinkFormState(dupdlg, "CheckBorrowInfoForm_dupdlg_state"); - dupdlg.ShowDialog(this); - this.MainForm.AppInfo.UnlinkFormState(dupdlg); + this.MainForm.AppInfo.LinkFormState(dupdlg, "CheckBorrowInfoForm_dupdlg_state"); + dupdlg.ShowDialog(this); + this.MainForm.AppInfo.UnlinkFormState(dupdlg); - if (dupdlg.DialogResult == DialogResult.Cancel) - goto ERROR1; + if (dupdlg.DialogResult == DialogResult.Cancel) + goto ERROR1; - strConfirmItemRecPath = dupdlg.SelectedRecPath; + strConfirmItemRecPath = dupdlg.SelectedRecPath; - goto REDO; - } - finally - { - this.MainForm.ReturnChannel(channel); - // this.MainForm.EndSearch(); - } + goto REDO; + } + finally + { + this.MainForm.ReturnChannel(channel); + // this.MainForm.EndSearch(); } + } - goto ERROR1; - } // end of return -1 + goto ERROR1; + } // end of return -1 } finally @@ -1234,7 +1498,7 @@ int BatchAddItemPrice(string strBarcodeFilename, if (lRet == 0) { - strError = "书目数据 '"+strBiblioRecPath+"' 中没有价格信息"; + strError = "书目数据 '" + strBiblioRecPath + "' 中没有价格信息"; Global.WriteHtml(this.webBrowser_resultInfo, "检查册记录 " + strItemBarcode + " 时警告(5): " + strError + "\r\n"); continue; @@ -1435,7 +1699,7 @@ static string CanonicalizePrice(string strPrice, } - if (strPrefix.IndexOf("CNY") != -1 + if (strPrefix.IndexOf("CNY") != -1 || strPrefix.IndexOf("cny") != -1 || strPrefix.IndexOf("CNY") != -1 || strPrefix.IndexOf("cny") != -1 @@ -1451,13 +1715,13 @@ static string CanonicalizePrice(string strPrice, goto DONE; } - DONE: - // 人民币 - if (bCNY == true) - return "CNY" + strValue; + DONE: + // 人民币 + if (bCNY == true) + return "CNY" + strValue; // 其他货币 - return strPrefix + strValue + strPostfix; + return strPrefix + strValue + strPostfix; } @@ -1480,75 +1744,64 @@ private void button_single_checkFromItem_Click(object sender, EventArgs e) string strText = ""; try { - string strItemBarcode = this.textBox_single_itemBarcode.Text; - string strOutputReaderBarcode = ""; + string strItemBarcode = this.textBox_single_itemBarcode.Text; + string strOutputReaderBarcode = ""; - int nProcessedBorrowItems = 0; - int nTotalBorrowItems = 0; + int nProcessedBorrowItems = 0; + int nTotalBorrowItems = 0; - long lRet = Channel.RepairBorrowInfo( - stop, - "checkfromitem", - "", - strItemBarcode, - "", - 0, - -1, - out nProcessedBorrowItems, // 2008/10/27 - out nTotalBorrowItems, // 2008/10/27 - out strOutputReaderBarcode, - out aDupPath, - out strError); - if (lRet == -1 || lRet == 1) + long lRet = Channel.RepairBorrowInfo( + stop, + "checkfromitem", + "", + strItemBarcode, + "", + 0, + -1, + out nProcessedBorrowItems, // 2008/10/27 + out nTotalBorrowItems, // 2008/10/27 + out strOutputReaderBarcode, + out aDupPath, + out strError); + if (lRet == -1 || lRet == 1) + { + if (Channel.ErrorCode == ErrorCode.ItemBarcodeDup) { - if (Channel.ErrorCode == ErrorCode.ItemBarcodeDup) - { - List linkedPath = new List(); + List linkedPath = new List(); - strText += "检查册记录 " + strItemBarcode + " 时发现册条码号命中重复记录 " + aDupPath.Length.ToString() + "个。检查其中\r\n"; + strText += "检查册记录 " + strItemBarcode + " 时发现册条码号命中重复记录 " + aDupPath.Length.ToString() + "个。检查其中\r\n"; - for (int j = 0; j < aDupPath.Length; j++) + for (int j = 0; j < aDupPath.Length; j++) + { + strText += " 第 " + (j + 1).ToString() + " 个,路径为 " + aDupPath[j] + " \r\n"; + + string[] aDupPathTemp = null; + long lRet_2 = Channel.RepairBorrowInfo( + stop, + "checkfromitem", + "", + strItemBarcode, + aDupPath[j], + 0, + -1, + out nProcessedBorrowItems, // 2008/10/27 + out nTotalBorrowItems, // 2008/10/27 + out strOutputReaderBarcode, + out aDupPathTemp, + out strError); + if (lRet_2 == -1) { - strText += " 第 " + (j + 1).ToString() + " 个,路径为 " + aDupPath[j] + " \r\n"; - - string[] aDupPathTemp = null; - long lRet_2 = Channel.RepairBorrowInfo( - stop, - "checkfromitem", - "", - strItemBarcode, - aDupPath[j], - 0, - -1, - out nProcessedBorrowItems, // 2008/10/27 - out nTotalBorrowItems, // 2008/10/27 - out strOutputReaderBarcode, - out aDupPathTemp, - out strError); - if (lRet_2 == -1) - { - goto ERROR1; - } - if (lRet_2 == 1) - { - strText += " 发现问题: " + strError + "\r\n"; - } - - } // end of for + goto ERROR1; + } + if (lRet_2 == 1) + { + strText += " 发现问题: " + strError + "\r\n"; + } - goto END1; - } + } // end of for - if (lRet == -1) - { - strText += "检查册记录 " + strItemBarcode + " 时出错: " + strError + "\r\n"; - } - if (lRet == 1) - { - strText += "检查册记录 " + strItemBarcode + " 时发现问题: " + strError + "\r\n"; - } goto END1; - } // end of return -1 or 1 + } if (lRet == -1) { @@ -1558,31 +1811,42 @@ private void button_single_checkFromItem_Click(object sender, EventArgs e) { strText += "检查册记录 " + strItemBarcode + " 时发现问题: " + strError + "\r\n"; } + goto END1; + } // end of return -1 or 1 + + if (lRet == -1) + { + strText += "检查册记录 " + strItemBarcode + " 时出错: " + strError + "\r\n"; + } + if (lRet == 1) + { + strText += "检查册记录 " + strItemBarcode + " 时发现问题: " + strError + "\r\n"; + } - if (string.IsNullOrEmpty(strItemBarcode) == false) + if (string.IsNullOrEmpty(strItemBarcode) == false) + { + string[] paths = null; + /* + lRet = Channel.SearchItemDup(stop, + strItemBarcode, + 100, + out paths, + out strError); + * */ + lRet = SearchEntityBarcode(stop, + strItemBarcode, + out paths, + out strError); + if (lRet == -1) { - string[] paths = null; - /* - lRet = Channel.SearchItemDup(stop, - strItemBarcode, - 100, - out paths, - out strError); - * */ - lRet = SearchEntityBarcode(stop, - strItemBarcode, - out paths, - out strError); - if (lRet == -1) - { - strText += "对册条码号 " + strItemBarcode + " 查重时出错: " + strError + "\r\n"; - } - if (lRet > 1) - { - strText += "册条码号 " + strItemBarcode + " 有重复记录 " + paths.Length.ToString() + "条\r\n"; - } + strText += "对册条码号 " + strItemBarcode + " 查重时出错: " + strError + "\r\n"; + } + if (lRet > 1) + { + strText += "册条码号 " + strItemBarcode + " 有重复记录 " + paths.Length.ToString() + "条\r\n"; } + } } @@ -1595,7 +1859,7 @@ private void button_single_checkFromItem_Click(object sender, EventArgs e) stop.Initial(""); } - END1: + END1: if (strText == "") MessageBox.Show(this, "没有发现问题。"); else @@ -1669,6 +1933,8 @@ private void button_single_checkFromReader_Click(object sender, EventArgs e) string strError = ""; int nRet = 0; + bool bAutoRepair = Control.ModifierKeys == Keys.Control; + if (this.textBox_single_readerBarcode.Text == "") { strError = "尚未指定要检查的读者证条码号"; @@ -1678,7 +1944,8 @@ private void button_single_checkFromReader_Click(object sender, EventArgs e) List barcodes = new List(); barcodes.Add(this.textBox_single_readerBarcode.Text); - nRet = CheckAllReaderRecord(barcodes, + nRet = CheckReaderRecords(barcodes, + bAutoRepair, out strError); if (nRet == -1) goto ERROR1; diff --git a/dp2Circulation/dp2Circulation.csproj b/dp2Circulation/dp2Circulation.csproj index 512059042..30eda50bd 100644 --- a/dp2Circulation/dp2Circulation.csproj +++ b/dp2Circulation/dp2Circulation.csproj @@ -51,7 +51,7 @@ dp2 V2 true publish.htm - 42 + 43 2.10.0.%2a false true diff --git a/dp2Installer/dp2Installer.csproj b/dp2Installer/dp2Installer.csproj index 13267eb49..1c45c2d00 100644 --- a/dp2Installer/dp2Installer.csproj +++ b/dp2Installer/dp2Installer.csproj @@ -34,7 +34,7 @@ dp2 V2 true publish.htm - 115 + 116 1.1.0.%2a false true diff --git a/dp2LibraryXE/dp2LibraryXE.csproj b/dp2LibraryXE/dp2LibraryXE.csproj index 3629d9b8a..612047319 100644 --- a/dp2LibraryXE/dp2LibraryXE.csproj +++ b/dp2LibraryXE/dp2LibraryXE.csproj @@ -36,7 +36,7 @@ dp2 V2 true publish.htm - 78 + 79 1.1.0.%2a false true From 88919d93e6535761e61674e97e05db0abd2a402c Mon Sep 17 00:00:00 2001 From: XieTao Date: Wed, 13 Apr 2016 23:06:52 +0800 Subject: [PATCH 04/14] =?UTF-8?q?=E4=B8=BA=E5=BF=AB=E6=8D=B7=E5=87=BA?= =?UTF-8?q?=E7=BA=B3=E7=AA=97=E5=A2=9E=E5=8A=A0=E4=BA=86=E6=9C=97=E8=AF=BB?= =?UTF-8?q?=E6=93=8D=E4=BD=9C=E5=87=BA=E9=94=99=E6=88=96=E8=80=85=E6=8F=90?= =?UTF-8?q?=E7=A4=BA=E7=8A=B6=E6=80=81=E7=9A=84=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dp2Circulation/CfgDlg.Designer.cs | 91 +++++++++++++------- dp2Circulation/CfgDlg.cs | 11 +++ dp2Circulation/Charging/ChargingTask.cs | 22 +++++ dp2Circulation/Charging/QuickChargingForm.cs | 17 ++++ dp2Circulation/dp2Circulation.csproj | 2 +- 5 files changed, 111 insertions(+), 32 deletions(-) diff --git a/dp2Circulation/CfgDlg.Designer.cs b/dp2Circulation/CfgDlg.Designer.cs index 4ed5529e3..ed18809d4 100644 --- a/dp2Circulation/CfgDlg.Designer.cs +++ b/dp2Circulation/CfgDlg.Designer.cs @@ -84,13 +84,15 @@ private void InitializeComponent() this.numericUpDown_charging_infoDlgOpacity = new System.Windows.Forms.NumericUpDown(); this.checkBox_charging_force = new System.Windows.Forms.CheckBox(); this.tabPage_quickCharging = new System.Windows.Forms.TabPage(); + this.comboBox_quickCharging_displayFormat = new System.Windows.Forms.ComboBox(); + this.comboBox_quickCharging_stateSpeak = new System.Windows.Forms.ComboBox(); + this.label34 = new System.Windows.Forms.Label(); this.comboBox_quickCharging_displayStyle = new System.Windows.Forms.ComboBox(); this.label30 = new System.Windows.Forms.Label(); this.checkBox_quickCharging_logOperTime = new System.Windows.Forms.CheckBox(); this.checkBox_quickCharging_isbnBorrow = new System.Windows.Forms.CheckBox(); this.groupBox_quickCharging_selectItemDialog = new System.Windows.Forms.GroupBox(); this.checkBox_quickCharging_autoOperItemDialogSingleItem = new System.Windows.Forms.CheckBox(); - this.comboBox_quickCharging_displayFormat = new System.Windows.Forms.ComboBox(); this.label27 = new System.Windows.Forms.Label(); this.checkBox_quickCharging_speakBookTitle = new System.Windows.Forms.CheckBox(); this.checkBox_quickCharging_speakNameWhenLoadReaderRecord = new System.Windows.Forms.CheckBox(); @@ -881,12 +883,14 @@ private void InitializeComponent() // tabPage_quickCharging // this.tabPage_quickCharging.AutoScroll = true; + this.tabPage_quickCharging.Controls.Add(this.comboBox_quickCharging_displayFormat); + this.tabPage_quickCharging.Controls.Add(this.comboBox_quickCharging_stateSpeak); + this.tabPage_quickCharging.Controls.Add(this.label34); this.tabPage_quickCharging.Controls.Add(this.comboBox_quickCharging_displayStyle); this.tabPage_quickCharging.Controls.Add(this.label30); this.tabPage_quickCharging.Controls.Add(this.checkBox_quickCharging_logOperTime); this.tabPage_quickCharging.Controls.Add(this.checkBox_quickCharging_isbnBorrow); this.tabPage_quickCharging.Controls.Add(this.groupBox_quickCharging_selectItemDialog); - this.tabPage_quickCharging.Controls.Add(this.comboBox_quickCharging_displayFormat); this.tabPage_quickCharging.Controls.Add(this.label27); this.tabPage_quickCharging.Controls.Add(this.checkBox_quickCharging_speakBookTitle); this.tabPage_quickCharging.Controls.Add(this.checkBox_quickCharging_speakNameWhenLoadReaderRecord); @@ -899,6 +903,41 @@ private void InitializeComponent() this.tabPage_quickCharging.Text = "ݳ"; this.tabPage_quickCharging.UseVisualStyleBackColor = true; // + // comboBox_quickCharging_displayFormat + // + this.comboBox_quickCharging_displayFormat.FormattingEnabled = true; + this.comboBox_quickCharging_displayFormat.Items.AddRange(new object[] { + "HTML", + "Ƭ"}); + this.comboBox_quickCharging_displayFormat.Location = new System.Drawing.Point(91, 14); + this.comboBox_quickCharging_displayFormat.Margin = new System.Windows.Forms.Padding(2); + this.comboBox_quickCharging_displayFormat.Name = "comboBox_quickCharging_displayFormat"; + this.comboBox_quickCharging_displayFormat.Size = new System.Drawing.Size(148, 20); + this.comboBox_quickCharging_displayFormat.TabIndex = 1; + // + // comboBox_quickCharging_stateSpeak + // + this.comboBox_quickCharging_stateSpeak.FormattingEnabled = true; + this.comboBox_quickCharging_stateSpeak.Items.AddRange(new object[] { + "[ʶ]", + "״̬", + "״̬+"}); + this.comboBox_quickCharging_stateSpeak.Location = new System.Drawing.Point(91, 155); + this.comboBox_quickCharging_stateSpeak.Margin = new System.Windows.Forms.Padding(2); + this.comboBox_quickCharging_stateSpeak.Name = "comboBox_quickCharging_stateSpeak"; + this.comboBox_quickCharging_stateSpeak.Size = new System.Drawing.Size(148, 20); + this.comboBox_quickCharging_stateSpeak.TabIndex = 9; + // + // label34 + // + this.label34.AutoSize = true; + this.label34.Location = new System.Drawing.Point(10, 158); + this.label34.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0); + this.label34.Name = "label34"; + this.label34.Size = new System.Drawing.Size(77, 12); + this.label34.TabIndex = 8; + this.label34.Text = "ʶ״̬(&S):"; + // // comboBox_quickCharging_displayStyle // this.comboBox_quickCharging_displayStyle.FormattingEnabled = true; @@ -909,7 +948,7 @@ private void InitializeComponent() this.comboBox_quickCharging_displayStyle.Margin = new System.Windows.Forms.Padding(2); this.comboBox_quickCharging_displayStyle.Name = "comboBox_quickCharging_displayStyle"; this.comboBox_quickCharging_displayStyle.Size = new System.Drawing.Size(148, 20); - this.comboBox_quickCharging_displayStyle.TabIndex = 23; + this.comboBox_quickCharging_displayStyle.TabIndex = 3; // // label30 // @@ -918,28 +957,28 @@ private void InitializeComponent() this.label30.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0); this.label30.Name = "label30"; this.label30.Size = new System.Drawing.Size(77, 12); - this.label30.TabIndex = 22; + this.label30.TabIndex = 2; this.label30.Text = "ʾ(&S):"; // // checkBox_quickCharging_logOperTime // this.checkBox_quickCharging_logOperTime.AutoSize = true; - this.checkBox_quickCharging_logOperTime.Location = new System.Drawing.Point(12, 305); + this.checkBox_quickCharging_logOperTime.Location = new System.Drawing.Point(12, 336); this.checkBox_quickCharging_logOperTime.Margin = new System.Windows.Forms.Padding(2); this.checkBox_quickCharging_logOperTime.Name = "checkBox_quickCharging_logOperTime"; this.checkBox_quickCharging_logOperTime.Size = new System.Drawing.Size(162, 16); - this.checkBox_quickCharging_logOperTime.TabIndex = 21; + this.checkBox_quickCharging_logOperTime.TabIndex = 12; this.checkBox_quickCharging_logOperTime.Text = "־мزʱ(&L)"; this.checkBox_quickCharging_logOperTime.UseVisualStyleBackColor = true; // // checkBox_quickCharging_isbnBorrow // this.checkBox_quickCharging_isbnBorrow.AutoSize = true; - this.checkBox_quickCharging_isbnBorrow.Location = new System.Drawing.Point(12, 166); + this.checkBox_quickCharging_isbnBorrow.Location = new System.Drawing.Point(12, 197); this.checkBox_quickCharging_isbnBorrow.Margin = new System.Windows.Forms.Padding(2); this.checkBox_quickCharging_isbnBorrow.Name = "checkBox_quickCharging_isbnBorrow"; this.checkBox_quickCharging_isbnBorrow.Size = new System.Drawing.Size(174, 16); - this.checkBox_quickCharging_isbnBorrow.TabIndex = 20; + this.checkBox_quickCharging_isbnBorrow.TabIndex = 10; this.checkBox_quickCharging_isbnBorrow.Text = " ISBN 黹鹦(&I)"; this.checkBox_quickCharging_isbnBorrow.UseVisualStyleBackColor = true; this.checkBox_quickCharging_isbnBorrow.CheckedChanged += new System.EventHandler(this.checkBox_quickCharging_isbnBorrow_CheckedChanged); @@ -947,10 +986,10 @@ private void InitializeComponent() // groupBox_quickCharging_selectItemDialog // this.groupBox_quickCharging_selectItemDialog.Controls.Add(this.checkBox_quickCharging_autoOperItemDialogSingleItem); - this.groupBox_quickCharging_selectItemDialog.Location = new System.Drawing.Point(12, 187); + this.groupBox_quickCharging_selectItemDialog.Location = new System.Drawing.Point(12, 218); this.groupBox_quickCharging_selectItemDialog.Name = "groupBox_quickCharging_selectItemDialog"; this.groupBox_quickCharging_selectItemDialog.Size = new System.Drawing.Size(252, 100); - this.groupBox_quickCharging_selectItemDialog.TabIndex = 20; + this.groupBox_quickCharging_selectItemDialog.TabIndex = 11; this.groupBox_quickCharging_selectItemDialog.TabStop = false; this.groupBox_quickCharging_selectItemDialog.Text = " ѡ¼Ի "; // @@ -961,22 +1000,10 @@ private void InitializeComponent() this.checkBox_quickCharging_autoOperItemDialogSingleItem.Margin = new System.Windows.Forms.Padding(2); this.checkBox_quickCharging_autoOperItemDialogSingleItem.Name = "checkBox_quickCharging_autoOperItemDialogSingleItem"; this.checkBox_quickCharging_autoOperItemDialogSingleItem.Size = new System.Drawing.Size(186, 16); - this.checkBox_quickCharging_autoOperItemDialogSingleItem.TabIndex = 19; + this.checkBox_quickCharging_autoOperItemDialogSingleItem.TabIndex = 0; this.checkBox_quickCharging_autoOperItemDialogSingleItem.Text = "ԶΨһõIJ¼(&A)"; this.checkBox_quickCharging_autoOperItemDialogSingleItem.UseVisualStyleBackColor = true; // - // comboBox_quickCharging_displayFormat - // - this.comboBox_quickCharging_displayFormat.FormattingEnabled = true; - this.comboBox_quickCharging_displayFormat.Items.AddRange(new object[] { - "HTML", - "Ƭ"}); - this.comboBox_quickCharging_displayFormat.Location = new System.Drawing.Point(91, 14); - this.comboBox_quickCharging_displayFormat.Margin = new System.Windows.Forms.Padding(2); - this.comboBox_quickCharging_displayFormat.Name = "comboBox_quickCharging_displayFormat"; - this.comboBox_quickCharging_displayFormat.Size = new System.Drawing.Size(148, 20); - this.comboBox_quickCharging_displayFormat.TabIndex = 18; - // // label27 // this.label27.AutoSize = true; @@ -984,7 +1011,7 @@ private void InitializeComponent() this.label27.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0); this.label27.Name = "label27"; this.label27.Size = new System.Drawing.Size(77, 12); - this.label27.TabIndex = 17; + this.label27.TabIndex = 0; this.label27.Text = "ʾʽ(&D):"; // // checkBox_quickCharging_speakBookTitle @@ -993,7 +1020,7 @@ private void InitializeComponent() this.checkBox_quickCharging_speakBookTitle.Location = new System.Drawing.Point(12, 134); this.checkBox_quickCharging_speakBookTitle.Name = "checkBox_quickCharging_speakBookTitle"; this.checkBox_quickCharging_speakBookTitle.Size = new System.Drawing.Size(96, 16); - this.checkBox_quickCharging_speakBookTitle.TabIndex = 16; + this.checkBox_quickCharging_speakBookTitle.TabIndex = 7; this.checkBox_quickCharging_speakBookTitle.Text = "ʶ (&P)"; this.checkBox_quickCharging_speakBookTitle.UseVisualStyleBackColor = true; // @@ -1003,7 +1030,7 @@ private void InitializeComponent() this.checkBox_quickCharging_speakNameWhenLoadReaderRecord.Location = new System.Drawing.Point(12, 112); this.checkBox_quickCharging_speakNameWhenLoadReaderRecord.Name = "checkBox_quickCharging_speakNameWhenLoadReaderRecord"; this.checkBox_quickCharging_speakNameWhenLoadReaderRecord.Size = new System.Drawing.Size(252, 16); - this.checkBox_quickCharging_speakNameWhenLoadReaderRecord.TabIndex = 15; + this.checkBox_quickCharging_speakNameWhenLoadReaderRecord.TabIndex = 6; this.checkBox_quickCharging_speakNameWhenLoadReaderRecord.Text = "ʶװض߼¼ʱ (&S)"; this.checkBox_quickCharging_speakNameWhenLoadReaderRecord.UseVisualStyleBackColor = true; // @@ -1014,7 +1041,7 @@ private void InitializeComponent() this.checkBox_quickCharging_noBorrowHistory.Margin = new System.Windows.Forms.Padding(2); this.checkBox_quickCharging_noBorrowHistory.Name = "checkBox_quickCharging_noBorrowHistory"; this.checkBox_quickCharging_noBorrowHistory.Size = new System.Drawing.Size(186, 16); - this.checkBox_quickCharging_noBorrowHistory.TabIndex = 13; + this.checkBox_quickCharging_noBorrowHistory.TabIndex = 5; this.checkBox_quickCharging_noBorrowHistory.Text = "Ϣвʾʷ(&H)"; this.checkBox_quickCharging_noBorrowHistory.UseVisualStyleBackColor = true; // @@ -2228,7 +2255,7 @@ private void InitializeComponent() this.groupBox7.Controls.Add(this.textBox_fingerprint_readerUrl); this.groupBox7.Location = new System.Drawing.Point(3, 14); this.groupBox7.Name = "groupBox7"; - this.groupBox7.Size = new System.Drawing.Size(467, 84); + this.groupBox7.Size = new System.Drawing.Size(416, 84); this.groupBox7.TabIndex = 0; this.groupBox7.TabStop = false; this.groupBox7.Text = " ָĶӿ URL "; @@ -2236,7 +2263,7 @@ private void InitializeComponent() // button_fingerprint_setDefaultValue // this.button_fingerprint_setDefaultValue.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); - this.button_fingerprint_setDefaultValue.Location = new System.Drawing.Point(356, 47); + this.button_fingerprint_setDefaultValue.Location = new System.Drawing.Point(305, 47); this.button_fingerprint_setDefaultValue.Name = "button_fingerprint_setDefaultValue"; this.button_fingerprint_setDefaultValue.Size = new System.Drawing.Size(105, 23); this.button_fingerprint_setDefaultValue.TabIndex = 1; @@ -2250,7 +2277,7 @@ private void InitializeComponent() | System.Windows.Forms.AnchorStyles.Right))); this.textBox_fingerprint_readerUrl.Location = new System.Drawing.Point(6, 20); this.textBox_fingerprint_readerUrl.Name = "textBox_fingerprint_readerUrl"; - this.textBox_fingerprint_readerUrl.Size = new System.Drawing.Size(455, 21); + this.textBox_fingerprint_readerUrl.Size = new System.Drawing.Size(404, 21); this.textBox_fingerprint_readerUrl.TabIndex = 0; // // button_fingerprint_clearLocalCacheFiles @@ -2659,7 +2686,6 @@ private void InitializeComponent() private System.Windows.Forms.CheckBox checkBox_quickCharging_speakNameWhenLoadReaderRecord; private System.Windows.Forms.CheckBox checkBox_quickCharging_speakBookTitle; private System.Windows.Forms.Label label26; - private System.Windows.Forms.ComboBox comboBox_quickCharging_displayFormat; private System.Windows.Forms.Label label27; private System.Windows.Forms.TabPage tabPage_labelPrint; private System.Windows.Forms.ComboBox comboBox_labelPrint_accessNoSource; @@ -2689,5 +2715,8 @@ private void InitializeComponent() public System.Windows.Forms.TextBox textBox_message_userName; private System.Windows.Forms.Label label32; private System.Windows.Forms.Label label33; + private System.Windows.Forms.ComboBox comboBox_quickCharging_stateSpeak; + private System.Windows.Forms.Label label34; + private System.Windows.Forms.ComboBox comboBox_quickCharging_displayFormat; } } \ No newline at end of file diff --git a/dp2Circulation/CfgDlg.cs b/dp2Circulation/CfgDlg.cs index 959e7be7d..535382d83 100644 --- a/dp2Circulation/CfgDlg.cs +++ b/dp2Circulation/CfgDlg.cs @@ -277,6 +277,11 @@ private void CfgDlg_Load(object sender, EventArgs e) "speak_book_title", false); + // 朗读状态 + this.comboBox_quickCharging_stateSpeak.Text = ap.GetString("quickcharging_form", + "state_speak", + "[不朗读]"); + // 启用 ISBN 借书还书功能 this.checkBox_quickCharging_isbnBorrow.Checked = ap.GetBoolean( "quickcharging_form", @@ -875,6 +880,12 @@ private void button_OK_Click(object sender, EventArgs e) "speak_book_title", this.checkBox_quickCharging_speakBookTitle.Checked); + // 朗读状态 + ap.SetString("quickcharging_form", + "state_speak", + this.comboBox_quickCharging_stateSpeak.Text); + + // 启用 ISBN 借书还书功能 ap.SetBoolean( "quickcharging_form", diff --git a/dp2Circulation/Charging/ChargingTask.cs b/dp2Circulation/Charging/ChargingTask.cs index bef94f60b..96685f165 100644 --- a/dp2Circulation/Charging/ChargingTask.cs +++ b/dp2Circulation/Charging/ChargingTask.cs @@ -52,6 +52,28 @@ public void RefreshPatronCardDisplay(DpRow row) cell.Relayout(); } + // parameters: + // strSpeakStyle 状态/状态+内容 + public string GetSpeakContent(DpRow row, string strSpeakStyle) + { + if (this.State == "finish" || this.State == "error") + { + string strText = ""; + if (this.Color == "red") + strText = "错误: "; + else if (this.Color == "yellow") + strText = "提示: "; + else + return ""; + if (strSpeakStyle == "状态") + return strText; + // 状态+内容 + return strText + this.ErrorInfo; + } + + return ""; + } + public void RefreshDisplay(DpRow row) { // 初始化列 diff --git a/dp2Circulation/Charging/QuickChargingForm.cs b/dp2Circulation/Charging/QuickChargingForm.cs index 24591eeae..9a28614bb 100644 --- a/dp2Circulation/Charging/QuickChargingForm.cs +++ b/dp2Circulation/Charging/QuickChargingForm.cs @@ -1238,6 +1238,13 @@ void _displayTask(string strAction, ChargingTask task) // 刷新显示 task.RefreshDisplay(line); + if (this.StateSpeak != "[不朗读]") + { + string strContent = task.GetSpeakContent(line, this.StateSpeak); + if (string.IsNullOrEmpty(strContent) == false) + this.MainForm.Speak(strContent); + } + if (task.Action == "load_reader_info" && string.IsNullOrEmpty(task.ReaderXml) == false) task.RefreshPatronCardDisplay(line); @@ -1856,6 +1863,16 @@ public string DisplayStyle } } + // 朗读状态 + public string StateSpeak + { + get + { + return this.MainForm.AppInfo.GetString("quickcharging_form", + "state_speak", + "[不朗读]"); + } + } /// /// 显示读者信息的格式。为 text html 之一 /// diff --git a/dp2Circulation/dp2Circulation.csproj b/dp2Circulation/dp2Circulation.csproj index 30eda50bd..1e75f6bad 100644 --- a/dp2Circulation/dp2Circulation.csproj +++ b/dp2Circulation/dp2Circulation.csproj @@ -51,7 +51,7 @@ dp2 V2 true publish.htm - 43 + 44 2.10.0.%2a false true From 99e5679a468cdde59bb807751b78c9549dd65a47 Mon Sep 17 00:00:00 2001 From: XieTao Date: Thu, 14 Apr 2016 19:33:31 +0800 Subject: [PATCH 05/14] =?UTF-8?q?=E5=AE=8C=E5=96=84=20BindPatron()=20API?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AppCirculation.cs | 7 --- DigitalPlatform.LibraryServer/AppReader.cs | 56 +++++++++++++++++-- .../LibraryService.cs | 53 +++++++++++------- dp2-net40.sln | 2 + dp2Circulation/AboutDlg.cs | 2 +- dp2Circulation/CheckBorrowInfoForm.cs | 7 ++- dp2Circulation/dp2Circulation.csproj | 2 +- 7 files changed, 93 insertions(+), 36 deletions(-) diff --git a/DigitalPlatform.LibraryServer/AppCirculation.cs b/DigitalPlatform.LibraryServer/AppCirculation.cs index 5ae6d4cee..75917dbb6 100644 --- a/DigitalPlatform.LibraryServer/AppCirculation.cs +++ b/DigitalPlatform.LibraryServer/AppCirculation.cs @@ -3111,7 +3111,6 @@ int CheckBorrowRights( } } - // 2008/4/14 string strBookState = DomUtil.GetElementText(itemdom.DocumentElement, "state"); if (String.IsNullOrEmpty(strBookState) == false) @@ -3136,7 +3135,6 @@ int CheckBorrowRights( return 0; } - // 从想要借阅的册信息中,找到图书类型 string strBookType = DomUtil.GetElementText(itemdom.DocumentElement, "bookType"); @@ -3222,7 +3220,6 @@ int CheckBorrowRights( return -1; } - // 然后看看总册数是否已经超过限制 int nMax = 0; try @@ -11744,12 +11741,10 @@ public int ProcessPauseBorrowing( for (; ; ) { - XmlNodeList nodes = readerdom.DocumentElement.SelectNodes("overdues/overdue"); if (nodes.Count == 0) break; - // 找到第一个已启动事项 XmlNode node = null; string strPauseStart = ""; @@ -14486,8 +14481,6 @@ int CheckOverdue( strOverdueItemBarcodeList += strBarcode; nOverCount++; } - - } // 发现未归还的册中出现了超期情况 diff --git a/DigitalPlatform.LibraryServer/AppReader.cs b/DigitalPlatform.LibraryServer/AppReader.cs index ba48618e5..c3e8504b5 100644 --- a/DigitalPlatform.LibraryServer/AppReader.cs +++ b/DigitalPlatform.LibraryServer/AppReader.cs @@ -4850,6 +4850,24 @@ public int BindPatron( strError = ""; results = null; + // 检查 strBindID 参数 + { + if (strBindingID.IndexOf(",") != -1) + { + strError = "strBindID 参数值 '" + strBindingID + "' 不合法。不允许包含逗号"; + return -1; + } + string strLeft = ""; + string strRight = ""; + StringUtil.ParseTwoPart(strBindingID, ":", out strLeft, out strRight); + if (string.IsNullOrEmpty(strLeft) + || string.IsNullOrEmpty(strRight)) + { + strError = "strBindID 参数值 '"+strBindingID+"' 不合法。应为 xxxx:xxxx 形态"; + return -1; + } + } + RmsChannel channel = sessioninfo.Channels.GetChannel(this.WsUrl); if (channel == null) { @@ -4905,7 +4923,7 @@ public int BindPatron( if (nRet == 0) { - strError = "帐户不存在或密码不正确"; + strError = "帐户 '"+strQueryWord+"' 不存在或密码不正确"; return -1; } @@ -4953,13 +4971,13 @@ public int BindPatron( if (string.IsNullOrEmpty(strRefID) == true) { DomUtil.SetElementText(readerdom.DocumentElement, "refID", Guid.NewGuid().ToString()); - m_bChanged = true; + bChanged = true; } if (strNewEmail != strEmail) { - DomUtil.SetElementText(readerdom.DocumentElement, "email", strEmail); - m_bChanged = true; + DomUtil.SetElementText(readerdom.DocumentElement, "email", strNewEmail); + bChanged = true; } if (bChanged == true) @@ -5000,7 +5018,7 @@ public int BindPatron( nRet = BuildReaderResults( sessioninfo, readerdom, - strXml, + readerdom.OuterXml, strResultTypeList, "", // strLibraryCode, recpaths, @@ -5052,7 +5070,33 @@ static string AddBindingString(string strText, return StringUtil.MakePathList(results); } else - return strText + "," + strBinding; + { + // 查重 + if (FindBindingString(strText, strBinding) != -1) + return strText; + return strText + "," + strBinding; + } + } + + static int FindBindingString(string strText, + string strBinding) + { + if (string.IsNullOrEmpty(strText) == true) + return -1; + + string[] parts = strText.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); + int i = 0; + foreach (string s in parts) + { + string strLine = s.Trim(); + if (string.IsNullOrEmpty(strLine)) + continue; + if (strLine == strBinding) + return i; // 忽视发现的号码 + i++; + } + + return -1; } // 去掉一个绑定号码 diff --git a/DigitalPlatform.LibraryService/LibraryService.cs b/DigitalPlatform.LibraryService/LibraryService.cs index c9a01893e..a6c5007c4 100644 --- a/DigitalPlatform.LibraryService/LibraryService.cs +++ b/DigitalPlatform.LibraryService/LibraryService.cs @@ -7716,29 +7716,42 @@ public LibraryServerResult BindPatron( { results = null; - LibraryServerResult result = this.PrepareEnvironment("BindingPatron", false); + LibraryServerResult result = this.PrepareEnvironment("BindingPatron", true); 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; + try + { + 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; + } + catch (Exception ex) + { + string strErrorText = "dp2Library BindPatron() API出现异常: " + ExceptionUtil.GetDebugText(ex); + app.WriteErrorLog(strErrorText); + + result.Value = -1; + result.ErrorCode = ErrorCode.SystemError; + result.ErrorInfo = strErrorText; + return result; + } } // 获得值列表 diff --git a/dp2-net40.sln b/dp2-net40.sln index b9a31748c..f20a0477d 100644 --- a/dp2-net40.sln +++ b/dp2-net40.sln @@ -14,6 +14,8 @@ EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "dp2Installer", "dp2Installer\dp2Installer.csproj", "{7D2AF716-8094-4DB9-8A09-0A4C001A4B28}" ProjectSection(ProjectDependencies) = postProject {017D8E01-B8D1-4671-BB2C-EECBC854FCEC} = {017D8E01-B8D1-4671-BB2C-EECBC854FCEC} + {E153CC55-DA01-4403-A53F-AF801BDDF4BA} = {E153CC55-DA01-4403-A53F-AF801BDDF4BA} + {FCB6E864-6415-4E58-B519-C0F099A396AF} = {FCB6E864-6415-4E58-B519-C0F099A396AF} {D91C6B98-886B-4181-9361-5214FFC992A9} = {D91C6B98-886B-4181-9361-5214FFC992A9} {47E73ADC-0C75-4018-A42F-C8CA68679F25} = {47E73ADC-0C75-4018-A42F-C8CA68679F25} {4DD877F6-796A-4F9C-BFF3-9D36590576CF} = {4DD877F6-796A-4F9C-BFF3-9D36590576CF} diff --git a/dp2Circulation/AboutDlg.cs b/dp2Circulation/AboutDlg.cs index d26d517a2..e5098f592 100644 --- a/dp2Circulation/AboutDlg.cs +++ b/dp2Circulation/AboutDlg.cs @@ -86,7 +86,7 @@ private void InitializeComponent() this.label1.Name = "label1"; this.label1.Size = new System.Drawing.Size(461, 17); this.label1.TabIndex = 0; - this.label1.Text = "dp2 内务/流通 dp2Circulation V2.12"; + this.label1.Text = "dp2 内务/流通 dp2Circulation V2.13"; this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; // // label_copyright diff --git a/dp2Circulation/CheckBorrowInfoForm.cs b/dp2Circulation/CheckBorrowInfoForm.cs index 673ac36d5..66a95996e 100644 --- a/dp2Circulation/CheckBorrowInfoForm.cs +++ b/dp2Circulation/CheckBorrowInfoForm.cs @@ -417,7 +417,9 @@ int CheckReaderRecords(List barcodes, } } - if (bFoundError && string.IsNullOrEmpty(strReaderXml) == false) + if (bFoundError + && bAutoRepair + && string.IsNullOrEmpty(strReaderXml) == false) { int nRet = RepairAllErrorFromReaderSide(strReaderRecPath, strReaderXml, @@ -890,6 +892,7 @@ int CheckItemRecords(List barcodes, Global.WriteHtml(this.webBrowser_resultInfo, strText); + if (bAutoRepair) { int nRet = RepairErrorFromItemSide(strItemBarcode, aDupPath[j], @@ -926,6 +929,8 @@ int CheckItemRecords(List barcodes, { Global.WriteHtml(this.webBrowser_resultInfo, "检查册记录 " + strItemBarcode + " 时发现问题: " + strError + "\r\n"); + + if (bAutoRepair) { int nRet = RepairErrorFromItemSide(strItemBarcode, "", diff --git a/dp2Circulation/dp2Circulation.csproj b/dp2Circulation/dp2Circulation.csproj index 1e75f6bad..3cac911f0 100644 --- a/dp2Circulation/dp2Circulation.csproj +++ b/dp2Circulation/dp2Circulation.csproj @@ -51,7 +51,7 @@ dp2 V2 true publish.htm - 44 + 45 2.10.0.%2a false true From ddc4275c9103692280341af9a79a2a85371c6475 Mon Sep 17 00:00:00 2001 From: XieTao Date: Fri, 15 Apr 2016 23:34:09 +0800 Subject: [PATCH 06/14] =?UTF-8?q?=E6=95=B4=E7=90=86=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DigitalPlatform.LibraryServer/AppBiblio.cs | 19 +++++-- DigitalPlatform.LibraryServer/AppReader.cs | 6 ++- .../ItemDatabase/ItemDatabase.cs | 51 ++++++++++--------- .../MessageConnection.cs | 18 ++++--- dp2Circulation/IM/MessageHub.cs | 32 +++++++++--- dp2Installer/dp2Installer.csproj | 2 +- dp2LibraryXE/dp2LibraryXE.csproj | 2 +- 7 files changed, 86 insertions(+), 44 deletions(-) diff --git a/DigitalPlatform.LibraryServer/AppBiblio.cs b/DigitalPlatform.LibraryServer/AppBiblio.cs index 9b695a067..798caf880 100644 --- a/DigitalPlatform.LibraryServer/AppBiblio.cs +++ b/DigitalPlatform.LibraryServer/AppBiblio.cs @@ -167,12 +167,20 @@ int BatchGetBiblioSummary( } // 获得书目信息 - // 可以用多种格式:xml html text @??? summary outputpath + // // TODO: 将来可以增加在strBiblioRecPath中允许多种检索入口的能力,比方说允许使用itembarcode和itemconfirmpath(甚至和excludebibliopath)结合起来定位种。这样就完全可以取代原有GetBiblioSummary API的功能 // parameters: // strBiblioRecPath 种记录路径。如果在最后接续"$prev" "$next",表示前一条或后一条。 // formats 希望获得信息的若干格式。如果 == null,表示希望只返回timestamp (results返回空) + // 可以用多种格式:xml html text @??? summary outputpath // Result.Value -1出错 0没有找到 1找到 + // 附注: + // 1) + // 如果 strBiblioRecPath 为 @path-list: 引导的成批检索式,并且 formats 为唯一一个 "summary" 元素,则表示希望批获取摘要 + // 批检索式,为逗号间隔的元素列表,每个元素为 @itemBarcode: 或 @bibliorecpath 引导的内容 + // results 中每个元素为一个 summary 内容 + // 2) + // 如果 strBiblioRecPath 为 @path-list: 引导的成批检索式,format 为多种格式,则 results 中会返回 格式个数 X 检索词数量 这么多的元素 public LibraryServerResult GetBiblioInfos( SessionInfo sessioninfo, string strBiblioRecPath, @@ -197,6 +205,7 @@ public LibraryServerResult GetBiblioInfos( } if (formats != null && formats.Length == 1 && formats[0] == "summary" + && strBiblioRecPath.StartsWith("@path-list:") // 2016/4/15 增加 && string.IsNullOrEmpty(strBiblioXmlParam) == true) { List temp_results = null; @@ -236,9 +245,13 @@ public LibraryServerResult GetBiblioInfos( List commands = new List(); List biblio_records = new List(); - if (StringUtil.HasHead(strBiblioRecPath, "@path-list:") == true) + if (StringUtil.HasHead(strBiblioRecPath, "@path-list:") == true + || strBiblioRecPath.IndexOf(",") != -1) // 2016/4/15 增加 { - string strText = strBiblioRecPath.Substring("@path-list:".Length); + string strText = strBiblioRecPath; + if (StringUtil.HasHead(strBiblioRecPath, "@path-list:") == true) + strText = strBiblioRecPath.Substring("@path-list:".Length); + commands = StringUtil.SplitList(strText); // 如果前端发来记录,需要切割为独立的字符串 diff --git a/DigitalPlatform.LibraryServer/AppReader.cs b/DigitalPlatform.LibraryServer/AppReader.cs index c3e8504b5..008770664 100644 --- a/DigitalPlatform.LibraryServer/AppReader.cs +++ b/DigitalPlatform.LibraryServer/AppReader.cs @@ -5078,6 +5078,10 @@ static string AddBindingString(string strText, } } + // 在一个绑定信息字符串里面,找到一个特定的 xxxx:xxxx 部分的下标 + // return: + // -1 没有找到 + // 其他 找到的位置下标。注,元素数量没有把空字符串元素计算在内 static int FindBindingString(string strText, string strBinding) { @@ -5092,7 +5096,7 @@ static int FindBindingString(string strText, if (string.IsNullOrEmpty(strLine)) continue; if (strLine == strBinding) - return i; // 忽视发现的号码 + return i; i++; } diff --git a/DigitalPlatform.LibraryServer/ItemDatabase/ItemDatabase.cs b/DigitalPlatform.LibraryServer/ItemDatabase/ItemDatabase.cs index 74c23e569..bfef50294 100644 --- a/DigitalPlatform.LibraryServer/ItemDatabase/ItemDatabase.cs +++ b/DigitalPlatform.LibraryServer/ItemDatabase/ItemDatabase.cs @@ -825,10 +825,10 @@ int DoOperDelete( } // 观察已存在的记录中,唯一性字段是否和要求的一致 - // return: - // -1 出错 - // 0 一致 - // 1 不一致。报错信息在strError中 + // return: + // -1 出错 + // 0 一致 + // 1 不一致。报错信息在strError中 nRet = IsLocateInfoCorrect( oldLocateParams, domExist, @@ -1701,7 +1701,7 @@ public LibraryServerResult SetItems( if (StringUtil.IsInList("restore", sessioninfo.RightsOrigin) == false) { result.Value = -1; - result.ErrorInfo = "带有风格 'force' 的修改"+this.ItemName+"信息的" + strAction + "操作被拒绝。不具备restore权限。"; + result.ErrorInfo = "带有风格 'force' 的修改" + this.ItemName + "信息的" + strAction + "操作被拒绝。不具备restore权限。"; result.ErrorCode = ErrorCode.AccessDenied; return result; } @@ -1713,7 +1713,7 @@ public LibraryServerResult SetItems( if (StringUtil.IsInList("restore", sessioninfo.RightsOrigin) == false) { result.Value = -1; - result.ErrorInfo = "带有风格 'nocheckdup' 的修改"+this.ItemName+"信息的" + strAction + "操作被拒绝。不具备restore权限。"; + result.ErrorInfo = "带有风格 'nocheckdup' 的修改" + this.ItemName + "信息的" + strAction + "操作被拒绝。不具备restore权限。"; result.ErrorCode = ErrorCode.AccessDenied; return result; } @@ -1725,7 +1725,7 @@ public LibraryServerResult SetItems( if (StringUtil.IsInList("restore", sessioninfo.RightsOrigin) == false) { result.Value = -1; - result.ErrorInfo = "带有风格 'noeventlog' 的修改"+this.ItemName+"信息的" + strAction + "操作被拒绝。不具备restore权限。"; + result.ErrorInfo = "带有风格 'noeventlog' 的修改" + this.ItemName + "信息的" + strAction + "操作被拒绝。不具备restore权限。"; result.ErrorCode = ErrorCode.AccessDenied; return result; } @@ -1831,7 +1831,7 @@ public LibraryServerResult SetItems( { // 再看strDbName是否至少是一个实体库 if (this.IsItemDbName(strDbName) == false) - strError = "RecPath中数据库名 '" + strDbName + "' 不正确,应为"+this.ItemName+"库名"; + strError = "RecPath中数据库名 '" + strDbName + "' 不正确,应为" + this.ItemName + "库名"; } else strError = "RecPath中数据库名 '" + strDbName + "' 不正确,应为 '" + strItemDbName + "'。(因为书目库名为 '" + strBiblioDbName + "',其对应的" + this.ItemName + "库名应为 '" + strItemDbName + "' )"; @@ -1841,7 +1841,7 @@ public LibraryServerResult SetItems( { // 要检查看看 strDbName 是否为一个实体库名 if (this.IsItemDbName(strDbName) == false) - strError = "RecPath中数据库名 '" + strDbName + "' 不正确,应为"+this.ItemName+"库名"; + strError = "RecPath中数据库名 '" + strDbName + "' 不正确,应为" + this.ItemName + "库名"; } if (strError != "") @@ -1978,7 +1978,7 @@ public LibraryServerResult SetItems( } nRet = this.IsLocateParamNullOrEmpty( - lockLocateParam, + lockLocateParam, out strError); if (nRet == -1) goto ERROR1; @@ -2153,7 +2153,7 @@ public LibraryServerResult SetItems( Debug.Assert(Char.IsLower(this.OperLogSetName[0]) == true, this.OperLogSetName + " 的第一个字符应当为小写字母,这是惯例"); // 和馆代码模糊有关。如果要写入馆代码,可以考虑滞后写入 DomUtil.SetElementText(domOperLog.DocumentElement, - "operation", + "operation", OperLogSetName /*"setIssue"*/); // 兑现一个命令 @@ -2383,7 +2383,7 @@ public LibraryServerResult SetItems( DomUtil.SetElementText(domOperLog.DocumentElement, "operator", sessioninfo.UserID); // 操作者 - DomUtil.SetElementText(domOperLog.DocumentElement, + DomUtil.SetElementText(domOperLog.DocumentElement, "operTime", strOperTime); // 操作时间 @@ -2551,8 +2551,11 @@ public LibraryServerResult GetItems( if (String.IsNullOrEmpty(strItemDbName) == true) { - strError = "书目库名 '" + strBiblioDbName + "' 对应的"+this.ItemName+"库名没有定义"; - goto ERROR1; + strError = "书目库名 '" + strBiblioDbName + "' 对应的" + this.ItemName + "库名没有定义"; + result.Value = -1; + result.ErrorInfo = strError; + result.ErrorCode = ErrorCode.ItemDbNotDef; // 2016/4/15 + return result; } RmsChannel channel = sessioninfo.Channels.GetChannel(this.App.WsUrl); @@ -2832,7 +2835,7 @@ public int SearchChildItems(RmsChannel channel, // 检索实体库中全部从属于特定id的记录 string strQueryXml = "" + strBiblioRecId + "exact=string-1" + "zh" + ""; @@ -2846,7 +2849,7 @@ public int SearchChildItems(RmsChannel channel, if (lRet == 0) { - strError = "没有找到属于书目记录 '" + strBiblioRecPath + "' 的任何"+this.ItemName+"记录"; + strError = "没有找到属于书目记录 '" + strBiblioRecPath + "' 的任何" + this.ItemName + "记录"; return 0; } @@ -2860,7 +2863,7 @@ public int SearchChildItems(RmsChannel channel, int nMaxCount = 10000; if (nResultCount > nMaxCount) { - strError = "命中"+this.ItemName+"记录数 " + nResultCount.ToString() + " 超过 "+nMaxCount.ToString()+", 暂时不支持针对它们的删除操作"; + strError = "命中" + this.ItemName + "记录数 " + nResultCount.ToString() + " 超过 " + nMaxCount.ToString() + ", 暂时不支持针对它们的删除操作"; goto ERROR1; } @@ -2918,7 +2921,7 @@ public int SearchChildItems(RmsChannel channel, if (channel.ErrorCode == ChannelErrorCode.NotFound) continue; - strError = "获取"+this.ItemName+"记录 '" + aPath[i] + "' 时发生错误: " + strError; + strError = "获取" + this.ItemName + "记录 '" + aPath[i] + "' 时发生错误: " + strError; goto ERROR1; // goto CONTINUE; } @@ -3205,7 +3208,7 @@ public int DeleteBiblioChildItems( if (domOperLog != null) { - root = domOperLog.CreateElement("deleted"+this.ItemNameInternal+"Records"); + root = domOperLog.CreateElement("deleted" + this.ItemNameInternal + "Records"); domOperLog.DocumentElement.AppendChild(root); } @@ -3248,7 +3251,7 @@ public int DeleteBiblioChildItems( { if (nRedoCount > 10) { - strError = "重试了10次还不行。删除"+this.ItemName+"记录 '" + info.RecPath + "' 时发生错误: " + strError; + strError = "重试了10次还不行。删除" + this.ItemName + "记录 '" + info.RecPath + "' 时发生错误: " + strError; goto ERROR1; } nRedoCount++; @@ -3270,7 +3273,7 @@ public int DeleteBiblioChildItems( if (channel.ErrorCode == ChannelErrorCode.NotFound) continue; - strError = "在删除"+this.ItemName+"记录 '" + info.RecPath + "' 时发生时间戳冲突,于是自动重新获取记录,但又发生错误: " + strError_1; + strError = "在删除" + this.ItemName + "记录 '" + info.RecPath + "' 时发生时间戳冲突,于是自动重新获取记录,但又发生错误: " + strError_1; goto ERROR1; // goto CONTINUE; } @@ -3288,7 +3291,7 @@ public int DeleteBiblioChildItems( } catch (Exception ex) { - strError = this.ItemName+"记录 '" + info.RecPath + "' XML装载进入DOM时发生错误: " + ex.Message; + strError = this.ItemName + "记录 '" + info.RecPath + "' XML装载进入DOM时发生错误: " + ex.Message; goto ERROR1; } @@ -3307,7 +3310,7 @@ public int DeleteBiblioChildItems( goto ERROR1; if (nRet == 1) { - strError = "拟删除的"+this.ItemName+"记录 '" + info.RecPath + "' 中"+strError+"(此种情况可能不限于这一条),不能删除。"; + strError = "拟删除的" + this.ItemName + "记录 '" + info.RecPath + "' 中" + strError + "(此种情况可能不限于这一条),不能删除。"; goto ERROR1; } @@ -3315,7 +3318,7 @@ public int DeleteBiblioChildItems( goto REDO_DELETE; } - strError = "删除"+this.ItemName+"记录 '" + info.RecPath + "' 时发生错误: " + strError; + strError = "删除" + this.ItemName + "记录 '" + info.RecPath + "' 时发生错误: " + strError; goto ERROR1; } } diff --git a/DigitalPlatform.MessageClient/MessageConnection.cs b/DigitalPlatform.MessageClient/MessageConnection.cs index d7854344b..3e87a970f 100644 --- a/DigitalPlatform.MessageClient/MessageConnection.cs +++ b/DigitalPlatform.MessageClient/MessageConnection.cs @@ -136,16 +136,19 @@ private void ConnectAsync(string strServerUrl) long, long, IList, - string>("responseSearch", (searchID, + string, + string>("responseSearch", (searchID, resultCount, start, records, - errorInfo) => + errorInfo, + errorCode) => OnSearchResponseRecieved(searchID, resultCount, start, records, - errorInfo) + errorInfo, + errorCode) ); HubProxy.On("setInfo", (searchParam) => OnSetInfoRecieved(searchParam) @@ -285,7 +288,8 @@ public virtual void OnSearchResponseRecieved(string searchID, long resultCount, long start, IList records, - string errorInfo) + string errorInfo, + string errorCode) { } @@ -546,7 +550,8 @@ public async void ResponseSearch( long resultCount, long start, IList records, - string errorInfo) + string errorInfo, + string errorCode) { try { @@ -555,7 +560,8 @@ public async void ResponseSearch( resultCount, start, records, - errorInfo); + errorInfo, + errorCode); if (result.Value == -1) { AddErrorLine(result.ErrorInfo); diff --git a/dp2Circulation/IM/MessageHub.cs b/dp2Circulation/IM/MessageHub.cs index 388f58211..1ef9c8071 100644 --- a/dp2Circulation/IM/MessageHub.cs +++ b/dp2Circulation/IM/MessageHub.cs @@ -288,6 +288,7 @@ public override void OnSetInfoRecieved(SetInfoRequest request) void GetPatronInfo(SearchRequest searchParam) { string strError = ""; + string strErrorCode = ""; IList records = new List(); if (string.IsNullOrEmpty(searchParam.FormatList) == true) @@ -310,6 +311,7 @@ void GetPatronInfo(SearchRequest searchParam) out strRecPath, out baTimestamp, out strError); + strErrorCode = channel.ErrorCode.ToString(); if (lRet == -1 || lRet == 0) { if (lRet == 0 @@ -321,7 +323,8 @@ void GetPatronInfo(SearchRequest searchParam) 0, 0, records, -strError); // 出错信息大概为 not found。 +strError, // 出错信息大概为 not found。 +strErrorCode); return; } goto ERROR1; @@ -348,7 +351,8 @@ void GetPatronInfo(SearchRequest searchParam) records.Count, // lHitCount, 0, // lStart, records, - ""); + "", + strErrorCode); } catch (Exception ex) { @@ -370,7 +374,8 @@ void GetPatronInfo(SearchRequest searchParam) -1, 0, records, -strError); +strError, +strErrorCode); } static void SetValue(Entity entity, EntityInfo info) @@ -428,6 +433,7 @@ void SearchAndResponse(SearchRequest searchParam) } string strError = ""; + string strErrorCode = ""; IList records = new List(); string strResultSetName = searchParam.ResultSetName; @@ -482,6 +488,8 @@ void SearchAndResponse(SearchRequest searchParam) strError = "无法识别的 Operation 值 '" + searchParam.Operation + "'"; } + strErrorCode = channel.ErrorCode.ToString(); + if (lRet == -1 || lRet == 0) { if (lRet == 0 @@ -493,7 +501,8 @@ void SearchAndResponse(SearchRequest searchParam) 0, 0, records, - strError); // 出错信息大概为 not found。 + strError, // 出错信息大概为 not found。 + strErrorCode); return; } goto ERROR1; @@ -512,7 +521,8 @@ void SearchAndResponse(SearchRequest searchParam) lHitCount, 0, records, -"本次没有返回任何记录"); +"本次没有返回任何记录", +strErrorCode); return; } @@ -549,6 +559,7 @@ void SearchAndResponse(SearchRequest searchParam) "zh", // this.Lang, out searchresults, out strError); + strErrorCode = channel.ErrorCode.ToString(); if (lRet == -1) goto ERROR1; @@ -575,7 +586,8 @@ void SearchAndResponse(SearchRequest searchParam) lHitCount, lStart, records, - ""); + "", + strErrorCode); lStart += searchresults.Length; @@ -607,7 +619,8 @@ void SearchAndResponse(SearchRequest searchParam) -1, 0, records, -strError); +strError, +strErrorCode); } // 写入实体库 @@ -686,7 +699,8 @@ public override void OnSearchResponseRecieved(string searchID, long resultCount, long start, IList records, - string errorInfo) + string errorInfo, + string errorCode) { #if NO int i = 0; @@ -705,6 +719,7 @@ public override void OnSearchResponseRecieved(string searchID, e.Start = start; e.Records = records; e.ErrorInfo = errorInfo; + e.ErrorCode = errorCode; this.SearchResponseEvent(this, e); } } @@ -791,5 +806,6 @@ public class SearchResponseEventArgs : EventArgs public long Start = 0; // Records 从整个结果集的何处开始 public IList Records = null; // 命中的书目记录集合 public string ErrorInfo = ""; // 错误信息 + public string ErrorCode = ""; // 错误代码。2016/4/15 增加 } } diff --git a/dp2Installer/dp2Installer.csproj b/dp2Installer/dp2Installer.csproj index 1c45c2d00..82dfa8066 100644 --- a/dp2Installer/dp2Installer.csproj +++ b/dp2Installer/dp2Installer.csproj @@ -34,7 +34,7 @@ dp2 V2 true publish.htm - 116 + 117 1.1.0.%2a false true diff --git a/dp2LibraryXE/dp2LibraryXE.csproj b/dp2LibraryXE/dp2LibraryXE.csproj index 612047319..b2ebb5a7c 100644 --- a/dp2LibraryXE/dp2LibraryXE.csproj +++ b/dp2LibraryXE/dp2LibraryXE.csproj @@ -36,7 +36,7 @@ dp2 V2 true publish.htm - 79 + 80 1.1.0.%2a false true From db9f659c3db42d58a4a45e9bf6d7545668fdd676 Mon Sep 17 00:00:00 2001 From: XieTao Date: Sat, 16 Apr 2016 08:32:21 +0800 Subject: [PATCH 07/14] =?UTF-8?q?=E5=8A=A0=E5=9B=BA=20GetReaderInfo()=20AP?= =?UTF-8?q?I=EF=BC=8C=E9=81=BF=E5=85=8D=E5=9C=A8=E8=BF=94=E5=9B=9E?= =?UTF-8?q?=E7=9A=84=E8=AF=BB=E8=80=85=E8=AE=B0=E5=BD=95=E4=B8=AD=E5=8C=85?= =?UTF-8?q?=E5=90=AB=20password=20=E5=85=83=E7=B4=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AppCirculation.cs | 36 ++++++++++++++++++- DigitalPlatform.LibraryServer/AppReader.cs | 8 +++-- 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/DigitalPlatform.LibraryServer/AppCirculation.cs b/DigitalPlatform.LibraryServer/AppCirculation.cs index 75917dbb6..7019e723d 100644 --- a/DigitalPlatform.LibraryServer/AppCirculation.cs +++ b/DigitalPlatform.LibraryServer/AppCirculation.cs @@ -1704,9 +1704,12 @@ out BorrowInfo borrow_info // 2007/12/6 "Borrow() 中写统计指标 耗时 "); strOutputItemXml = itemdom.OuterXml; + + // strOutputReaderXml 将用于构造读者记录返回格式 + DomUtil.DeleteElement(readerdom.DocumentElement, "password"); strOutputReaderXml = readerdom.OuterXml; - strBiblioRecID = DomUtil.GetElementText(itemdom.DocumentElement, "parent"); // + strBiblioRecID = DomUtil.GetElementText(itemdom.DocumentElement, "parent"); // } // 册记录锁定范围结束 finally { @@ -4658,7 +4661,15 @@ public LibraryServerResult Return( goto ERROR1; strOutputItemXml = itemdom.OuterXml; + strOutputReaderXml = strOldReaderXml; // strReaderXml; + nRet = RemovePassword(ref strOutputReaderXml, out strError); + if (nRet == -1) + { + strError = "从读者记录中去除 password 阶段出错: " + strError; + goto ERROR1; + } + strBiblioRecID = DomUtil.GetElementText(itemdom.DocumentElement, "parent"); // SetReturnInfo(ref return_info, itemdom); @@ -5350,7 +5361,11 @@ public LibraryServerResult Return( if (itemdom != null) strOutputItemXml = itemdom.OuterXml; + + // strOutputReaderXml 将用于构造读者记录返回格式 + DomUtil.DeleteElement(readerdom.DocumentElement, "password"); strOutputReaderXml = readerdom.OuterXml; + if (itemdom != null) { strBiblioRecID = DomUtil.GetElementText(itemdom.DocumentElement, "parent"); // @@ -5881,6 +5896,25 @@ public LibraryServerResult Return( return result; } + // 从读者记录中删除 password 元素 + static int RemovePassword(ref string strReaderXml, out string strError) + { + strError = ""; + XmlDocument readerdom = new XmlDocument(); + try + { + readerdom.LoadXml(strReaderXml); + } + catch(Exception ex) + { + strError = "读者记录 XML 装入 DOM 时出错:" + ex.Message; + return -1; + } + + DomUtil.DeleteElement(readerdom.DocumentElement, "password"); + return 0; + } + // 构造用于提示“读过”卷册的文字 static string GetReadCaption(string strBiblioRecPath, string strVolume) { diff --git a/DigitalPlatform.LibraryServer/AppReader.cs b/DigitalPlatform.LibraryServer/AppReader.cs index 008770664..0e9536d06 100644 --- a/DigitalPlatform.LibraryServer/AppReader.cs +++ b/DigitalPlatform.LibraryServer/AppReader.cs @@ -3503,7 +3503,7 @@ public LibraryServerResult GetReaderInfo( try { - // 测试读者记录 + // 返回测试读者记录 if (IsTestReaderBarcode(strBarcode)) { nRet = 1; @@ -3808,10 +3808,11 @@ public LibraryServerResult GetReaderInfo( goto ERROR1; } + DomUtil.DeleteElement(readerdom.DocumentElement, "password"); nRet = BuildReaderResults( sessioninfo, readerdom, - strXml, + readerdom.OuterXml, // strXml, 2016/4/16 被改掉 strResultTypeList, strLibraryCode, recpaths, @@ -4014,6 +4015,8 @@ public LibraryServerResult GetReaderInfo( return result; } + // 创建读者记录返回格式 + // 注:出于安全需要,readerdom 和 strXml 在调用前就应该把里面的 barcode 元素删除 // parameters: // readerdom 读者 XMLDocument 对象。如果为空,则 strXml 参数中应该有读者记录 // strXml 读者 XML 记录。如果 readerdom 为空,可以用这里的值 @@ -5015,6 +5018,7 @@ public int BindPatron( recpaths.Add(strOutputPath); // 构造读者记录的返回格式 + DomUtil.DeleteElement(readerdom.DocumentElement, "password"); nRet = BuildReaderResults( sessioninfo, readerdom, From 010436641e34b775a8f89654b305f579dfb2ab26 Mon Sep 17 00:00:00 2001 From: XieTao Date: Sat, 16 Apr 2016 10:50:26 +0800 Subject: [PATCH 08/14] =?UTF-8?q?=E5=8A=A0=E5=9B=BA=20GetOperLog()=20?= =?UTF-8?q?=E5=92=8C=20GetOperLogs()=20API=EF=BC=8C=E9=81=BF=E5=85=8D?= =?UTF-8?q?=E8=AE=A9=E5=89=8D=E7=AB=AF=E7=9C=8B=E5=88=B0=E6=97=A5=E5=BF=97?= =?UTF-8?q?=E8=AE=B0=E5=BD=95=E4=B8=AD=E8=AF=BB=E8=80=85=E8=AE=B0=E5=BD=95?= =?UTF-8?q?=E7=9A=84=20password=20=E5=85=83=E7=B4=A0=E3=80=82=E4=BD=86(?= =?UTF-8?q?=E5=BF=AB=E7=85=A7)=E6=97=A5=E5=BF=97=E6=81=A2=E5=A4=8D?= =?UTF-8?q?=E8=BF=87=E7=A8=8B=E4=B8=AD=E4=B8=8D=E8=A6=81=E8=BF=87=E6=BB=A4?= =?UTF-8?q?=20password=20=E5=85=83=E7=B4=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DigitalPlatform.LibraryServer/OperLog.cs | 105 +++++++++++++++++- .../OperLogRecover.cs | 10 +- .../LibraryService.cs | 7 +- 3 files changed, 110 insertions(+), 12 deletions(-) diff --git a/DigitalPlatform.LibraryServer/OperLog.cs b/DigitalPlatform.LibraryServer/OperLog.cs index 7b9769af7..f718deefd 100644 --- a/DigitalPlatform.LibraryServer/OperLog.cs +++ b/DigitalPlatform.LibraryServer/OperLog.cs @@ -1201,6 +1201,7 @@ public int WriteOperLog(XmlDocument dom, // lIndex 记录序号。从0开始计数。lIndex为-1时调用本函数,表示希望获得整个文件尺寸值,将返回在lHintNext中。 // lHint 记录位置暗示性参数。这是一个只有服务器才能明白含义的值,对于前端来说是不透明的。 // 目前的含义是记录起始位置。 + // strStyle 如果不包含 supervisor,则本函数会自动过滤掉日志记录中读者记录的 password 字段 // attachment 承载输出的附件部分的 Stream 对象。如果为 null,表示不输出附件部分 // return: // -1 error @@ -1341,6 +1342,8 @@ public int GetOperLog( if (nRet == -1) return -1; + // 后面会通过 strStyle 参数决定是否过滤读者记录的 password 元素 + // 限制记录观察范围 if (SessionInfo.IsGlobalUser(strLibraryCodeList) == false) { @@ -1417,6 +1420,8 @@ static int GetLevel(string strStyle) return 0; } + // parameters: + // strStyle 如果不包含 supervisor,则需要过滤读者记录的 password 元素 // return: // -1 出错 // 0 没有改变 @@ -1429,9 +1434,12 @@ static int ResizeXml( { strError = ""; + bool bSupervisor = StringUtil.IsInList("supervisor", strStyle); + int nLevel = -1; // 先检测一次,可以提高某些情况下的运行速度 - if (string.IsNullOrEmpty(strFilter) == true) + if (string.IsNullOrEmpty(strFilter) == true + && bSupervisor == true) { // 获得详细级别 // return: @@ -1463,6 +1471,12 @@ static int ResizeXml( return 1; } + if (bSupervisor == false) + { + // 过滤日志记录中,读者记录的 password 元素 + RemoveReaderPassword(ref dom); + } + if (nLevel == -1) { // 获得详细级别 @@ -1510,6 +1524,8 @@ static int ResizeXml( } // 检查和过滤日志XML记录 + // parameters: + // strStyle 如果不包含 supervisor,则需要过滤日志记录中读者记录的 password 元素 // return: // -1 出错 // 0 不允许返回当前日志记录 @@ -1549,6 +1565,12 @@ static int FilterXml( return 0; } + if (StringUtil.IsInList("supervisor", strStyle) == false) + { + // 过滤日志记录中,读者记录的 password 元素 + RemoveReaderPassword(ref dom); + } + // 2013/11/22 if (string.IsNullOrEmpty(strFilter) == false && StringUtil.IsInList(strOperation, strFilter) == false) @@ -1634,6 +1656,7 @@ static int FilterXml( } // 对日志记录进行减小尺寸的操作 + // 注:本函数不负责过滤读者记录中的 password 元素 static void ResizeXml(string strOperation, int nLevel, ref XmlDocument dom) @@ -1841,6 +1864,75 @@ static void RemoveItemRecord(int nLevel, } } + // 从日志记录中,删除读者记录的 password 元素 + static void RemoveReaderPassword(ref XmlDocument dom) + { + // operation:borrow -- readerRecord + // operation:return -- readerRecord + // operation:changeReaderPassword -- readerRecord 注意 newPassword 元素里面有新密码的 hash 字符串 + // operation:setReaderInfo -- record 和 newRecord 元素 + // operation:amerce -- readerRecord 和 oldReaderRecord 元素 + // operation:devolveReaderInfo -- sourceReaderRecord 和 targetRecordRecord 元素 + // operation:hire -- readerRecord + // operation:foregift -- readerRecord + // !TODO: operation:writeRes 要留意它是不是写入了读者库。如果是,则要防范泄露 password 元素内容 + + string strOperation = DomUtil.GetElementText(dom.DocumentElement, "operation"); + if (strOperation == "borrow" + || strOperation == "return" + || strOperation == "hire" + || strOperation == "foregift") + { + RemoveReaderPassword(ref dom, "readerRecord"); + return; + } + if (strOperation == "changeReaderPassword") + { + RemoveReaderPassword(ref dom, "readerRecord"); + DomUtil.DeleteElement(dom.DocumentElement, "newPassword"); + return; + } + if (strOperation == "setReaderInfo") + { + RemoveReaderPassword(ref dom, "record"); + RemoveReaderPassword(ref dom, "newRecord"); + return; + } + if (strOperation == "amerce") + { + RemoveReaderPassword(ref dom, "readerRecord"); + RemoveReaderPassword(ref dom, "oldReaderRecord"); + return; + } + if (strOperation == "devolveReaderInfo") + { + RemoveReaderPassword(ref dom, "sourceReaderRecord"); + RemoveReaderPassword(ref dom, "targetReaderRecord"); + return; + } + } + + static void RemoveReaderPassword(ref XmlDocument dom, string strElementName) + { + string strReaderRecord = DomUtil.GetElementText(dom.DocumentElement, strElementName); + if (string.IsNullOrEmpty(strReaderRecord)) + return; + XmlDocument reader_dom = new XmlDocument(); + try + { + reader_dom.LoadXml(strReaderRecord); + XmlNode node = reader_dom.DocumentElement.SelectSingleNode("password"); + if (node != null) + { + node.ParentNode.RemoveChild(node); + DomUtil.SetElementText(dom.DocumentElement, strElementName, reader_dom.DocumentElement.OuterXml); + } + } + catch + { + } + } + static void RemoveReaderRecord(int nLevel, string strElementName, ref XmlDocument dom) @@ -1849,8 +1941,8 @@ static void RemoveReaderRecord(int nLevel, return; { - string strReaderReacord = DomUtil.GetElementText(dom.DocumentElement, strElementName); - if (string.IsNullOrEmpty(strReaderReacord) == false) + string strReaderRecord = DomUtil.GetElementText(dom.DocumentElement, strElementName); + if (string.IsNullOrEmpty(strReaderRecord) == false) { if (nLevel == 2) { @@ -1862,7 +1954,7 @@ static void RemoveReaderRecord(int nLevel, XmlDocument reader_dom = new XmlDocument(); try { - reader_dom.LoadXml(strReaderReacord); + reader_dom.LoadXml(strReaderRecord); XmlNode node = reader_dom.DocumentElement.SelectSingleNode("borrowHistory"); if (node != null) node.ParentNode.RemoveChild(node); @@ -2161,6 +2253,7 @@ public int GetOperLogAttachment( // parameters: // nCount 本次希望获取的记录数。如果==-1,表示希望尽可能多地获取 + // strStyle 如果不包含 supervisor,则本函数会自动过滤掉日志记录中读者记录的 password 字段 // return: // -1 error // 0 file not found @@ -2279,6 +2372,7 @@ public int GetOperLogs( // lIndex 记录序号。从0开始计数。lIndex为-1时调用本函数,表示希望获得整个文件尺寸值,将返回在lHintNext中。 // lHint 记录位置暗示性参数。这是一个只有服务器才能明白含义的值,对于前端来说是不透明的。 // 目前的含义是记录起始位置。 + // strStyle 如果不包含 supervisor,则本函数会自动过滤掉日志记录中读者记录的 password 字段 // return: // -1 error // 0 file not found @@ -2441,6 +2535,8 @@ public int GetOperLog( if (nRet == -1) return -1; + // 后面会通过 strStyle 参数决定是否过滤读者记录的 password 元素 + // 限制记录观察范围 if (SessionInfo.IsGlobalUser(strLibraryCodeList) == false) { @@ -2508,7 +2604,6 @@ public int GetOperLog( // END1: lHintNext = cache_item.Stream.Position; - return 1; } finally diff --git a/DigitalPlatform.LibraryServer/OperLogRecover.cs b/DigitalPlatform.LibraryServer/OperLogRecover.cs index d388e9f6b..be4151a30 100644 --- a/DigitalPlatform.LibraryServer/OperLogRecover.cs +++ b/DigitalPlatform.LibraryServer/OperLogRecover.cs @@ -298,7 +298,7 @@ public override void Worker() } this.AppendResultText("循环结束\r\n"); - + this.App.WriteErrorLog("日志恢复 任务结束。"); return; @@ -339,13 +339,12 @@ int DoOneLogFile(string strFileName, { strError = ""; - this.AppendResultText("做文件 "+strFileName+"\r\n"); + this.AppendResultText("做文件 " + strFileName + "\r\n"); Debug.Assert(this.App != null, ""); string strTempFileName = this.App.GetTempFileName("logrecover"); // Path.GetTempFileName(); try { - long lIndex = 0; long lHint = -1; long lHintNext = -1; @@ -366,7 +365,6 @@ int DoOneLogFile(string strFileName, { // Debug.Assert(!(lIndex == 182 && strFileName == "20071225.log"), ""); - long lAttachmentLength = 0; // 获得一个日志记录 // parameters: @@ -383,7 +381,7 @@ int DoOneLogFile(string strFileName, strFileName, lIndex, lHint, - "", // level-0 + "supervisor", // level-0 "", // strFilter out lHintNext, out strXml, @@ -617,7 +615,7 @@ int DoOperLogRecord(string strXml, { string strAction = DomUtil.GetElementText(dom.DocumentElement, "action"); - strError = "operation=" +strOperation + ";action=" + strAction + ": " + strError; + strError = "operation=" + strOperation + ";action=" + strAction + ": " + strError; return -1; } diff --git a/DigitalPlatform.LibraryService/LibraryService.cs b/DigitalPlatform.LibraryService/LibraryService.cs index a6c5007c4..fa096e217 100644 --- a/DigitalPlatform.LibraryService/LibraryService.cs +++ b/DigitalPlatform.LibraryService/LibraryService.cs @@ -7873,6 +7873,9 @@ public LibraryServerResult GetOperLogs( } else { + // 从 strStyle 里移走 supervisor,避免前端通过本 API 看到日志记录中读者记录的 password 元素 + StringUtil.RemoveFromInList("supervisor", true, ref strStyle); + // return: // -1 error // 0 file not found @@ -7911,7 +7914,6 @@ public LibraryServerResult GetOperLogs( result.ErrorInfo = strErrorText; return result; } - } // 获得日志记录 @@ -7997,6 +7999,9 @@ public LibraryServerResult GetOperLog( return result; } + // 从 strStyle 里移走 supervisor,避免前端通过本 API 看到日志记录中读者记录的 password 元素 + StringUtil.RemoveFromInList("supervisor", true, ref strStyle); + OperLogInfo[] records = null; nRet = app.AccessLogDatabase.GetOperLogs( sessioninfo.LibraryCodeList, From bd5af2a2e36433bd407195318b98a0890c64da3c Mon Sep 17 00:00:00 2001 From: XieTao Date: Sat, 16 Apr 2016 12:08:41 +0800 Subject: [PATCH 09/14] =?UTF-8?q?GetOperLog()=20API=20=E5=92=8C=20GetOperL?= =?UTF-8?q?ogs()=20API=20=E5=A2=9E=E5=8A=A0=E8=BF=87=E6=BB=A4=E6=8E=89=20s?= =?UTF-8?q?etUser=20=E6=93=8D=E4=BD=9C=E6=97=A5=E5=BF=97=E8=AE=B0=E5=BD=95?= =?UTF-8?q?=E4=B8=AD=E7=9A=84=E5=AF=86=E7=A0=81=E6=95=8F=E6=84=9F=E4=BF=A1?= =?UTF-8?q?=E6=81=AF=E7=9A=84=E5=BC=BA=E5=8C=96=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DigitalPlatform.LibraryServer/AppUser.cs | 15 +++++++-------- DigitalPlatform.LibraryServer/OperLog.cs | 16 +++++++++++++--- 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/DigitalPlatform.LibraryServer/AppUser.cs b/DigitalPlatform.LibraryServer/AppUser.cs index 06ca5567e..b1a06490e 100644 --- a/DigitalPlatform.LibraryServer/AppUser.cs +++ b/DigitalPlatform.LibraryServer/AppUser.cs @@ -48,7 +48,7 @@ public static string GetDbOperRights(string strAccessString, // string[] segments = strAccessString.Split(new char[] {';'}); List segments = StringUtil.SplitString(strAccessString, ";", - new string [] {"()"}, + new string[] { "()" }, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < segments.Count; i++) { @@ -82,7 +82,7 @@ public static string GetDbOperRights(string strAccessString, new string[] { "()" }, StringSplitOptions.RemoveEmptyEntries); - for (int j = 0; j Date: Sat, 16 Apr 2016 16:52:43 +0800 Subject: [PATCH 10/14] =?UTF-8?q?BindPatron()=20API=20=E5=85=81=E8=AE=B8?= =?UTF-8?q?=E5=B7=A5=E4=BD=9C=E4=BA=BA=E5=91=98=E8=BA=AB=E4=BB=BD=E4=BD=BF?= =?UTF-8?q?=E7=94=A8=20null=5Fpassword=20Style=E6=9D=A5=E6=93=8D=E4=BD=9C?= =?UTF-8?q?=E3=80=82=E8=AF=BB=E8=80=85=E8=BA=AB=E4=BB=BD=E5=8F=AF=E4=BB=A5?= =?UTF-8?q?=E5=AF=B9=E8=87=AA=E5=B7=B1=E8=BF=9B=E8=A1=8C=E7=BB=91=E5=AE=9A?= =?UTF-8?q?=E6=93=8D=E4=BD=9C=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DigitalPlatform.LibraryServer/AppReader.cs | 33 ++++++++++++++++--- .../LibraryService.cs | 20 ++++++++++- dp2Circulation/userrightsdef.xml | 4 +++ 3 files changed, 52 insertions(+), 5 deletions(-) diff --git a/DigitalPlatform.LibraryServer/AppReader.cs b/DigitalPlatform.LibraryServer/AppReader.cs index 0e9536d06..0d93bf6be 100644 --- a/DigitalPlatform.LibraryServer/AppReader.cs +++ b/DigitalPlatform.LibraryServer/AppReader.cs @@ -4831,11 +4831,13 @@ public int AddFriends( // strBindingID 要绑定的号码。格式如 email:xxxx 或 weixinid:xxxxx // strStyle 风格。multiple/single。默认 single // multiple 表示允许多次绑定同一类型号码;sigle 表示同一类型号码只能绑定一次,如果多次绑定以前的同类型号码会被清除 + // 如果包含 null_password,表示不用读者密码,strPassword 参数无效。但这个功能只能被工作人员使用 // strResultTypeList 结果类型数组 xml/html/text/calendar/advancexml/recpaths/summary // 其中calendar表示获得读者所关联的日历名;advancexml表示经过运算了的提供了丰富附加信息的xml,例如具有超期和停借期附加信息 // advancexml_borrow_bibliosummary/advancexml_overdue_bibliosummary/advancexml_history_bibliosummary // results 返回操作成功后的读者记录 // return: + // -2 权限不够,操作被拒绝 // -1 出错 // 0 因为条件不具备功能没有成功执行 // 1 功能成功执行 @@ -4853,6 +4855,18 @@ public int BindPatron( strError = ""; results = null; + if (sessioninfo.UserType == "reader") + { + + } + else + { + // 工作人员如果权限足够,可以不输入读者密码。这一般用在解除绑定的时候,假如调用者能确认读者(已绑定号码的)身份。而绑定时候建议不要这样用,因为读者密码还没有验证过,其身份不明。除非工作人员经过验证证件确信就是这个读者。 + // 但,一旦没有读者密码,在登录名命中多个账户的时候,就失去了一重选择的机会 + if (StringUtil.IsInList("null_password", strStyle)) + strPassword = null; + } + // 检查 strBindID 参数 { if (strBindingID.IndexOf(",") != -1) @@ -4866,7 +4880,7 @@ public int BindPatron( if (string.IsNullOrEmpty(strLeft) || string.IsNullOrEmpty(strRight)) { - strError = "strBindID 参数值 '"+strBindingID+"' 不合法。应为 xxxx:xxxx 形态"; + strError = "strBindID 参数值 '" + strBindingID + "' 不合法。应为 xxxx:xxxx 形态"; return -1; } } @@ -4926,7 +4940,7 @@ public int BindPatron( if (nRet == 0) { - strError = "帐户 '"+strQueryWord+"' 不存在或密码不正确"; + strError = "帐户 '" + strQueryWord + "' 不存在或密码不正确"; return -1; } @@ -4946,9 +4960,20 @@ public int BindPatron( return -1; } + // 对读者身份的附加判断 + if (sessioninfo.UserType == "reader") + { + string strBarcode = DomUtil.GetElementText(readerdom.DocumentElement, "barcode"); + if (sessioninfo.Account.Barcode != strBarcode) + { + strError = "绑定号码的操作被拒绝。作为读者不能对其他读者的记录进行操作"; + return -2; + } + } + bool bChanged = false; - bool bMultiple = strStyle == "multiple"; + bool bMultiple = StringUtil.IsInList("multiple", strStyle); // 若 mutilple 和 single 都包含了,则 multiple 有压倒优势 // 修改读者记录的 email 字段 string strEmail = DomUtil.GetElementText(readerdom.DocumentElement, "email"); @@ -5078,7 +5103,7 @@ static string AddBindingString(string strText, // 查重 if (FindBindingString(strText, strBinding) != -1) return strText; - return strText + "," + strBinding; + return strText + "," + strBinding; } } diff --git a/DigitalPlatform.LibraryService/LibraryService.cs b/DigitalPlatform.LibraryService/LibraryService.cs index fa096e217..e36ebe4d1 100644 --- a/DigitalPlatform.LibraryService/LibraryService.cs +++ b/DigitalPlatform.LibraryService/LibraryService.cs @@ -7722,9 +7722,21 @@ public LibraryServerResult BindPatron( try { + + // 权限字符串 + if (sessioninfo.RightsOriginList.IsInList("bindpatron") == false) + { + result.Value = -1; + result.ErrorInfo = "绑定号码的操作被拒绝。不具备 bindpatron 权限。"; + result.ErrorCode = ErrorCode.AccessDenied; + return result; + } + + string strError = ""; // 不需要登录 // return: + // -2 权限不够,操作被拒绝 // -1 出错 // 0 因为条件不具备功能没有成功执行 // 1 功能成功执行 @@ -7738,7 +7750,13 @@ public LibraryServerResult BindPatron( strResultTypeList, out results, out strError); - result.Value = nRet; + if (nRet == -2) + { + result.Value = -1; + result.ErrorCode = ErrorCode.AccessDenied; + } + else + result.Value = nRet; result.ErrorInfo = strError; return result; } diff --git a/dp2Circulation/userrightsdef.xml b/dp2Circulation/userrightsdef.xml index f4a570dcc..51745b86d 100644 --- a/dp2Circulation/userrightsdef.xml +++ b/dp2Circulation/userrightsdef.xml @@ -373,6 +373,10 @@ 检查前端版本 Check Client Version + + 为读者绑定号码 + Bind Number to Patron + 前端允许界面直接修改订购记录 Client UI Allow Modify Order Record From b5a4f40ed1743d56fff183de64702cd6a189505e Mon Sep 17 00:00:00 2001 From: XieTao Date: Sat, 16 Apr 2016 18:02:51 +0800 Subject: [PATCH 11/14] =?UTF-8?q?=E6=95=B4=E7=90=86=E4=BB=A3=E7=A0=81;=20?= =?UTF-8?q?=E5=85=91=E7=8E=B0=E8=AF=BB=E8=80=85=E8=AE=B0=E5=BD=95=E4=B8=AD?= =?UTF-8?q?=20email=20=E5=85=83=E7=B4=A0=E5=86=85=E5=AE=B9=E7=9A=84?= =?UTF-8?q?=E6=96=B0=E7=94=A8=E6=B3=95;=20=E6=95=B4=E7=90=86=20dp2OPAC=20?= =?UTF-8?q?=E7=94=A8=20email=20=E7=99=BB=E5=BD=95=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DigitalPlatform.LibraryServer/AppBiblio.cs | 4 +- DigitalPlatform.LibraryServer/AppReader.cs | 43 ++++++++++++++++++- .../AppReservation.cs | 42 +++++++++--------- .../LibraryApplication.cs | 3 +- .../ReadersMonitor.cs | 30 ++++++++++--- .../ZhengyuanReplication.cs | 25 ++++++----- DigitalPlatform.OPAC.Web/LoginControl.cs | 3 +- DigitalPlatform.Text/StringUtil.cs | 25 +++++++++++ 8 files changed, 132 insertions(+), 43 deletions(-) diff --git a/DigitalPlatform.LibraryServer/AppBiblio.cs b/DigitalPlatform.LibraryServer/AppBiblio.cs index 798caf880..d11365389 100644 --- a/DigitalPlatform.LibraryServer/AppBiblio.cs +++ b/DigitalPlatform.LibraryServer/AppBiblio.cs @@ -3337,9 +3337,9 @@ public int MessageNotify( return -1; } } - strReaderEmailAddress = DomUtil.GetElementText(readerdom.DocumentElement, + string strValue = DomUtil.GetElementText(readerdom.DocumentElement, "email"); - + strReaderEmailAddress = LibraryApplication.GetEmailAddress(strValue); if (String.IsNullOrEmpty(strReaderEmailAddress) == true) continue; } diff --git a/DigitalPlatform.LibraryServer/AppReader.cs b/DigitalPlatform.LibraryServer/AppReader.cs index 0d93bf6be..12df13f1e 100644 --- a/DigitalPlatform.LibraryServer/AppReader.cs +++ b/DigitalPlatform.LibraryServer/AppReader.cs @@ -3808,11 +3808,24 @@ public LibraryServerResult GetReaderInfo( goto ERROR1; } - DomUtil.DeleteElement(readerdom.DocumentElement, "password"); + { + if (readerdom != null) + DomUtil.DeleteElement(readerdom.DocumentElement, "password"); + if (string.IsNullOrEmpty(strXml) == false) + { + nRet = RemovePassword(ref strXml, out strError); + if (nRet == -1) + { + strError = "从读者记录中去除 password 阶段出错: " + strError; + goto ERROR1; + } + } + } + nRet = BuildReaderResults( sessioninfo, readerdom, - readerdom.OuterXml, // strXml, 2016/4/16 被改掉 + strXml, strResultTypeList, strLibraryCode, recpaths, @@ -5107,6 +5120,32 @@ static string AddBindingString(string strText, } } + // 从读者记录 email 元素值中获得 email 地址部分 + public static string GetEmailAddress(string strValue) + { + if (string.IsNullOrEmpty(strValue)) + return ""; + + // 注: email 元素内容,现在是存储 email 和微信号等多种绑定途径 2016/4/16 + // return: + // null 没有找到前缀 + // "" 找到了前缀,并且值部分为空 + // 其他 返回值部分 + string strReaderEmailAddress = StringUtil.GetParameterByPrefix(strValue, + "email", + ":"); + // 读者记录中没有email地址,就无法进行email方式的通知了 + if (String.IsNullOrEmpty(strReaderEmailAddress) == true) + { + // 按照以前的 xxxx@xxxx 方式探索一下 + if (strValue.IndexOf(":") != -1 || strValue.IndexOf("@") == -1) + return ""; + return strValue; + } + + return strReaderEmailAddress; + } + // 在一个绑定信息字符串里面,找到一个特定的 xxxx:xxxx 部分的下标 // return: // -1 没有找到 diff --git a/DigitalPlatform.LibraryServer/AppReservation.cs b/DigitalPlatform.LibraryServer/AppReservation.cs index 063c073fe..03969e993 100644 --- a/DigitalPlatform.LibraryServer/AppReservation.cs +++ b/DigitalPlatform.LibraryServer/AppReservation.cs @@ -58,7 +58,7 @@ public LibraryServerResult Reservation( // text-level: 内部错误 result.ErrorInfo = string.Format(this.GetString("未知的strFunction参数值s"), // "未知的strFunction参数值 '{0}'" strFunction); - // "未知的strFunction参数值 '" + strFunction + "'"; + // "未知的strFunction参数值 '" + strFunction + "'"; result.ErrorCode = ErrorCode.InvalidParameter; return result; } @@ -75,7 +75,7 @@ public LibraryServerResult Reservation( // 被删除的已到书状态册集合 List ArriveItemBarcodes = new List(); - + // 加读者记录锁 #if DEBUG_LOCK_READER this.WriteErrorLog("Reservation 开始为读者加写锁 '" + strReaderBarcode + "'"); @@ -113,7 +113,7 @@ public LibraryServerResult Reservation( // text-level: 内部错误 strError = string.Format(this.GetString("读入读者记录时发生错误s"), // "读入读者记录时发生错误: {0}" strError); - // "读入读者记录时发生错误: " + strError; + // "读入读者记录时发生错误: " + strError; goto ERROR1; } @@ -163,7 +163,7 @@ public LibraryServerResult Reservation( // text-level: 内部错误 strError = string.Format(this.GetString("装载读者记录进入XMLDOM时发生错误s"), // "装载读者记录进入XML DOM时发生错误: {0}" strError); - // "装载读者记录进入XML DOM时发生错误: " + strError; + // "装载读者记录进入XML DOM时发生错误: " + strError; goto ERROR1; } @@ -316,7 +316,7 @@ public LibraryServerResult Reservation( // text-level: 内部错误 strError = string.Format(this.GetString("读入册记录时发生错误s"), // "读入册记录时发生错误: {0}" strError); - // "读入册记录时发生错误: " + strError; + // "读入册记录时发生错误: " + strError; goto ERROR1; } @@ -508,7 +508,7 @@ public LibraryServerResult Reservation( if (string.IsNullOrEmpty(strItemBarcode) == true) { - strError = "内部错误:OnShelfItemBarcodes 的第一个元素为空。数组情况 '"+StringUtil.MakePathList(OnShelfItemBarcodes)+"'"; + strError = "内部错误:OnShelfItemBarcodes 的第一个元素为空。数组情况 '" + StringUtil.MakePathList(OnShelfItemBarcodes) + "'"; goto ERROR1; } @@ -533,7 +533,7 @@ public LibraryServerResult Reservation( // text-level: 用户提示 strError = string.Format(this.GetString("预约操作已经成功, 但是在架立即通知功能失败, 原因s"), // "预约操作已经成功, 但是在架立即通知功能失败, 原因: {0}" strError); - // "预约操作已经成功, 但是在架立即通知功能失败, 原因: " + strError; + // "预约操作已经成功, 但是在架立即通知功能失败, 原因: " + strError; goto ERROR1; } @@ -550,17 +550,17 @@ public LibraryServerResult Reservation( // text-level: 用户提示 string strMessage = string.Format(this.GetString("请注意,您刚提交的预约请求立即就得到了兑现"), // "请注意,您刚提交的预约请求立即就得到了兑现(预约到书通知消息也向您发出了,请注意查收)。所预约的册 {0} 为在架状态,已为您保留,您从现在起就可来图书馆办理借阅手续。" strItemBarcode); - // "请注意,您刚提交的预约请求立即就得到了兑现(预约到书通知消息也向您发出了,请注意查收)。所预约的册 " + strItemBarcode + " 为在架状态,已为您保留,您从现在起就可来图书馆办理借阅手续。"; + // "请注意,您刚提交的预约请求立即就得到了兑现(预约到书通知消息也向您发出了,请注意查收)。所预约的册 " + strItemBarcode + " 为在架状态,已为您保留,您从现在起就可来图书馆办理借阅手续。"; if (OnShelfItemBarcodes.Count > 1) { OnShelfItemBarcodes.Remove(strItemBarcode); - string [] barcodelist = new string[OnShelfItemBarcodes.Count]; + string[] barcodelist = new string[OnShelfItemBarcodes.Count]; OnShelfItemBarcodes.CopyTo(barcodelist); // text-level: 用户提示 strMessage += string.Format(this.GetString("您在同一预约请求中也同时提交了其他在架状态的册"), // "您在同一预约请求中也同时提交了其他在架状态的册: {0}。因同一集合中的前述册 {1} 的生效,这些册同时被忽略。(如确要预约多个在架的册让它们都独立生效,请每次勾选一个后单独提交,而不要把多个册一次性提交。)" String.Join(",", barcodelist), strItemBarcode); - // "您在同一预约请求中也同时提交了其他在架状态的册: " + String.Join(",", barcodelist) + "。因同一集合中的前述册 " + strItemBarcode + " 的生效,这些册同时被忽略。(如确要预约多个在架的册让它们都独立生效,请每次勾选一个后单独提交,而不要把多个册一次性提交。)"; + // "您在同一预约请求中也同时提交了其他在架状态的册: " + String.Join(",", barcodelist) + "。因同一集合中的前述册 " + strItemBarcode + " 的生效,这些册同时被忽略。(如确要预约多个在架的册让它们都独立生效,请每次勾选一个后单独提交,而不要把多个册一次性提交。)"; } result.ErrorInfo = strMessage; @@ -574,7 +574,7 @@ public LibraryServerResult Reservation( // text-level: 用户提示 result.ErrorInfo += string.Format(this.GetString("册s在删除前已经处在到书状态"), // "册 {0} 在删除前已经处在“到书”状态。您刚刚删除了这(些)请求,这意味着您已经放弃取书。图书馆将顺次满足后面排队等待的预约者的请求,或允许其他读者借阅此书。(若您意图要去图书馆正常取书,请一定不要去删除这样的状态为“已到书”的请求,软件会在您取书后自动删除)" String.Join(",", barcodelist)); - // "册 " + String.Join(",", barcodelist) + " 在删除前已经处在“到书”状态。您刚刚删除了这(些)请求,这意味着您已经放弃取书。图书馆将顺次满足后面排队等待的预约者的请求,或允许其他读者借阅此书。(若您意图要去图书馆正常取书,请一定不要去删除这样的状态为“已到书”的请求,软件会在您取书后自动删除)"; + // "册 " + String.Join(",", barcodelist) + " 在删除前已经处在“到书”状态。您刚刚删除了这(些)请求,这意味着您已经放弃取书。图书馆将顺次满足后面排队等待的预约者的请求,或允许其他读者借阅此书。(若您意图要去图书馆正常取书,请一定不要去删除这样的状态为“已到书”的请求,软件会在您取书后自动删除)"; } } finally @@ -641,7 +641,7 @@ public int ReservationCheckDup( // text-level: 用户提示 strError = string.Format(this.GetString("读者类型s尚未定义可预约册数参数"), // "读者类型 '{0}' 尚未定义 可预约册数 参数, 预约操作被拒绝" strReaderType); - // "读者类型 '" + strReaderType + "' 尚未定义 可预约册数 参数, 预约操作被拒绝"; + // "读者类型 '" + strReaderType + "' 尚未定义 可预约册数 参数, 预约操作被拒绝"; return -1; } @@ -670,7 +670,7 @@ public int ReservationCheckDup( nodes.Count, strReaderType, nMaxReserveItems.ToString()); - // "本次预约前已经预约的事项数已经达到 " + nodes.Count + ",已经超过 读者类型 '" + strReaderType + "' 允许的可预约册数 " + nMaxReserveItems.ToString() + ",预约操作被拒绝"; + // "本次预约前已经预约的事项数已经达到 " + nodes.Count + ",已经超过 读者类型 '" + strReaderType + "' 允许的可预约册数 " + nMaxReserveItems.ToString() + ",预约操作被拒绝"; return -1; } @@ -729,7 +729,7 @@ public int ReservationCheckDup( // text-level: 用户提示 strError = string.Format(this.GetString("册s已经被当前读者借阅"), // "册 '{0}' 已被当前读者借阅,因此不能被预约..." strNewBarcode); - // "册 '" + strNewBarcode + "' 已被当前读者借阅,因此不能被预约..."; + // "册 '" + strNewBarcode + "' 已被当前读者借阅,因此不能被预约..."; return 1; } @@ -809,7 +809,7 @@ public int DoReservationItemXml( // text-level: 用户提示 strError = string.Format(this.GetString("不能预约在架的册s"), // "不能预约在架(未被借出的)册 {0}" strItemBarcode); - // "不能预约在架(未被借出的)册 " + strItemBarcode; + // "不能预约在架(未被借出的)册 " + strItemBarcode; return -1; } @@ -1486,7 +1486,7 @@ int AddNotifyRecordToQueue( { strError = ""; DeletedNotifyRecPaths = new List(); - + // 2010/12/31 if (String.IsNullOrEmpty(this.ArrivedDbName) == true) { @@ -1574,7 +1574,7 @@ int AddNotifyRecordToQueue( out strError); if (nRet == -1) { - strError = "装载册记录 '"+strItemBarcode+"' 的 XML 进入 DOM 时发生错误: " + strError; + strError = "装载册记录 '" + strItemBarcode + "' 的 XML 进入 DOM 时发生错误: " + strError; return -1; } @@ -1910,7 +1910,7 @@ int AddNotifyRecordToQueue( out strError); if (nRet == -1) { - strTotalError += "发送"+message_interface.Type+"消息时出错: " + strError + "\r\n"; + strTotalError += "发送" + message_interface.Type + "消息时出错: " + strError + "\r\n"; } } } @@ -1946,8 +1946,10 @@ int GetReaderNotifyInfo( return -1; } - strReaderEmailAddress = DomUtil.GetElementText(readerdom.DocumentElement, - "email"); + strReaderEmailAddress = + LibraryApplication.GetEmailAddress( + DomUtil.GetElementText(readerdom.DocumentElement, "email") + ); strName = DomUtil.GetElementText(readerdom.DocumentElement, "name"); diff --git a/DigitalPlatform.LibraryServer/LibraryApplication.cs b/DigitalPlatform.LibraryServer/LibraryApplication.cs index ea2f23c97..0f460b546 100644 --- a/DigitalPlatform.LibraryServer/LibraryApplication.cs +++ b/DigitalPlatform.LibraryServer/LibraryApplication.cs @@ -112,7 +112,8 @@ public partial class LibraryApplication : IDisposable // 2.68 (2016/1/9) Return() API 增加了 read action。会将动作记入操作日志。ChargingOperDatabase 库也会自动更新 // 2.69 (2016/1/29) 各个 API 都对读者身份加强了检查,防止出现权限漏洞。 // 2.70 (2016/4/10) 增加 MSMQ 消息队列功能,读者记录的修改、dp2mail 消息都自动发送到这个消息队列。dp2library 失效日期从 5.1 变为 7.1。ReadersMonitor 后台任务会自动给没有 refID 元素的读者记录增加此元素 - public static string Version = "2.70"; + // 2.71 (2016/4/15) 对各个环节的密码相关功能进行加固。GetReaderInfo() API 不会返回 password 元素;GetOperLog() GetOperLogs() API 会滤除各种密码 + public static string Version = "2.71"; #if NO int m_nRefCount = 0; public int AddRef() diff --git a/DigitalPlatform.LibraryServer/ReadersMonitor.cs b/DigitalPlatform.LibraryServer/ReadersMonitor.cs index 53d796de5..79bbc81ce 100644 --- a/DigitalPlatform.LibraryServer/ReadersMonitor.cs +++ b/DigitalPlatform.LibraryServer/ReadersMonitor.cs @@ -362,7 +362,7 @@ string GetBodyTypesDef() return def_node.GetAttribute("types"); } - // 处理一条记录 + // 处理一条读者记录 int DoOneRecord( List bodytypes, string strPath, @@ -419,8 +419,6 @@ int DoOneRecord( bool bChanged = false; - - // 每种 bodytype 做一次 for (int i = 0; i < bodytypes.Count; i++) { @@ -429,8 +427,26 @@ int DoOneRecord( string strReaderEmailAddress = ""; if (strBodyType == "email") { - strReaderEmailAddress = DomUtil.GetElementText(readerdom.DocumentElement, + string strValue = DomUtil.GetElementText(readerdom.DocumentElement, "email"); +#if NO + // 注: email 元素内容,现在是存储 email 和微信号等多种绑定途径 2016/4/16 + // return: + // null 没有找到前缀 + // "" 找到了前缀,并且值部分为空 + // 其他 返回值部分 + strReaderEmailAddress = StringUtil.GetParameterByPrefix(strReaderEmailAddress, + "email", + ":"); + // 读者记录中没有email地址,就无法进行email方式的通知了 + if (String.IsNullOrEmpty(strReaderEmailAddress) == true) + { + if (strValue.IndexOf(":") != -1) + continue; + strReaderEmailAddress = strValue; + } +#endif + strReaderEmailAddress = LibraryApplication.GetEmailAddress(strValue); // 读者记录中没有email地址,就无法进行email方式的通知了 if (String.IsNullOrEmpty(strReaderEmailAddress) == true) continue; @@ -1130,6 +1146,10 @@ public static string GetNotifiedChars(LibraryApplication app, { index = 1; } + else if (strBodyType == "mq") + { + index = 2; + } else { MessageInterface external_interface = app.GetMessageInterface(strBodyType); @@ -1147,7 +1167,7 @@ public static string GetNotifiedChars(LibraryApplication app, // return -1; return null; } - index += 2; + index += 3; // 原来是 2 } string strResult = ""; diff --git a/DigitalPlatform.LibraryServer/ZhengyuanReplication.cs b/DigitalPlatform.LibraryServer/ZhengyuanReplication.cs index 2a1cef978..62026cf45 100644 --- a/DigitalPlatform.LibraryServer/ZhengyuanReplication.cs +++ b/DigitalPlatform.LibraryServer/ZhengyuanReplication.cs @@ -20,7 +20,7 @@ namespace DigitalPlatform.LibraryServer public class ZhengyuanReplication : BatchTask { internal AutoResetEvent eventDownloadFinished = new AutoResetEvent(false); // true : initial state is signaled - + bool DownloadCancelled = false; Exception DownloadException = null; @@ -32,7 +32,7 @@ public override void Dispose() } // 构造函数 - public ZhengyuanReplication(LibraryApplication app, + public ZhengyuanReplication(LibraryApplication app, string strName) : base(app, strName) { @@ -343,7 +343,7 @@ public override void Worker() } if (nRet == 1) { - this.AppendResultText("下载数据文件"+strDataFileName+"被中断\r\n"); + this.AppendResultText("下载数据文件" + strDataFileName + "被中断\r\n"); this.Loop = false; return; } @@ -854,7 +854,7 @@ int WriteOneReaderInfo( string strExistingXml = ""; string strSavedXml = ""; string strSavedRecPath = ""; - byte [] baNewTimestamp = null; + byte[] baNewTimestamp = null; DigitalPlatform.rms.Client.rmsws_localhost.ErrorCodeValue kernel_errorcode = DigitalPlatform.rms.Client.rmsws_localhost.ErrorCodeValue.NoError; LibraryServerResult result = this.App.SetReaderInfo( @@ -932,7 +932,7 @@ int ModifyReaderRecord(ref XmlDocument readerdom, strError = ""; int nRet = 0; - + /* 100 @@ -1047,9 +1047,12 @@ int ModifyReaderRecord(ref XmlDocument readerdom, // email地址 string strEmail = DomUtil.GetElementText(zhengyuandom.DocumentElement, "EMAIL"); - DomUtil.SetElementText(readerdom.DocumentElement, - "email", - strEmail); + if (string.IsNullOrEmpty(strEmail) == false) + { + DomUtil.SetElementText(readerdom.DocumentElement, + "email", + "email:" + strEmail); + } string strRfcTime = ""; @@ -1178,7 +1181,7 @@ int GetDataCenterParam( out string strError) { strError = ""; - strServerUrl = + strServerUrl = strUserName = ""; strPassword = ""; @@ -1259,7 +1262,7 @@ int DownloadDataFile(string strDataFileName, } catch (WebException ex) { - strError = "下载数据文件 " + strPath+ " 失败: " + ex.ToString(); + strError = "下载数据文件 " + strPath + " 失败: " + ex.ToString(); return -1; } @@ -1322,7 +1325,7 @@ int DownloadDataFile(string strDataFileName, void request_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e) { - if ((e.BytesReceived % 1024*100) == 0) + if ((e.BytesReceived % 1024 * 100) == 0) this.AppendResultText("已下载: " + e.BytesReceived + "\r\n"); } diff --git a/DigitalPlatform.OPAC.Web/LoginControl.cs b/DigitalPlatform.OPAC.Web/LoginControl.cs index 92f3fb151..adb2c942e 100644 --- a/DigitalPlatform.OPAC.Web/LoginControl.cs +++ b/DigitalPlatform.OPAC.Web/LoginControl.cs @@ -13,7 +13,6 @@ using DigitalPlatform.Xml; using DigitalPlatform.OPAC.Server; -//using DigitalPlatform.CirculationClient; using DigitalPlatform.Text; namespace DigitalPlatform.OPAC.Web @@ -1473,7 +1472,7 @@ public int DoLogin(string strLibraryCode, strError = this.GetString("Email地址不能为空"); goto ERROR1; } - strUserName = "EM:" + email.Text; + strUserName = "EM:email:" + email.Text; // 2016/4/16 修改 } else if (this.ActiveLoginColumn == LoginColumn.Telephone) { diff --git a/DigitalPlatform.Text/StringUtil.cs b/DigitalPlatform.Text/StringUtil.cs index accae84b8..4a4c90372 100644 --- a/DigitalPlatform.Text/StringUtil.cs +++ b/DigitalPlatform.Text/StringUtil.cs @@ -16,6 +16,31 @@ public class StringUtil { public static string SpecialChars = "!·#¥%……—*()——+-=[]《》<>,。?/\|{}“”‘’•"; + // parameters: + // strPrefix 前缀。例如 "getreaderinfo" + // strDelimiter 前缀和后面参数的分隔符号。例如 ":" + // return: + // null 没有找到前缀 + // "" 找到了前缀,并且值部分为空 + // 其他 返回值部分 + public static string GetParameterByPrefix(string strList, + string strPrefix, + string strDelimiter = ":") + { + if (string.IsNullOrEmpty(strList) == true) + return ""; + string[] list = strList.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); + foreach (string s in list) + { + if (s.StartsWith(strPrefix + strDelimiter) == true) + return s.Substring(strPrefix.Length + strDelimiter.Length); + if (s == strPrefix) + return ""; + } + + return null; + } + public static bool IsValidCMIS(string strText) { if (string.IsNullOrEmpty(strText)) From 750e02d775edc33016f16ee21f78afaaffaa83c5 Mon Sep 17 00:00:00 2001 From: XieTao Date: Sun, 17 Apr 2016 21:46:13 +0800 Subject: [PATCH 12/14] =?UTF-8?q?BindPatron()=20API=20=E8=A6=81=E6=B1=82?= =?UTF-8?q?=E7=94=A8=E6=88=B7=E7=99=BB=E5=BD=95=E6=89=8D=E8=83=BD=E4=BD=BF?= =?UTF-8?q?=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../KernelService.cs | 8 +- .../LibraryService.cs | 10 +- DigitalPlatform.Text/StringUtil.cs | 1 + DigitalPlatform.rms.Client/RmsChannel.cs | 137 +++++++++--------- DigitalPlatform.rms.db/SessionInfo.cs | 2 +- 5 files changed, 77 insertions(+), 81 deletions(-) diff --git a/DigitalPlatform.KernelService/KernelService.cs b/DigitalPlatform.KernelService/KernelService.cs index 67dfbfb57..6c734b2a7 100644 --- a/DigitalPlatform.KernelService/KernelService.cs +++ b/DigitalPlatform.KernelService/KernelService.cs @@ -29,7 +29,7 @@ public static class GlobalVars * */ [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple, - Namespace="http://dp2003.com/dp2kernel/")] + Namespace = "http://dp2003.com/dp2kernel/")] public class KernelService : IKernelService, IDisposable { KernelApplication app = null; @@ -1381,8 +1381,7 @@ public Result GetRecords( // result: // Result对象, // value == -1 出错 - // >= 1 结果集的总数 - // == 0 0条 + // == 0 成功 public Result GetBrowse( string[] paths, string strStyle, @@ -1396,7 +1395,6 @@ public Result GetBrowse( try { - if (this.sessioninfo.UserName == "") { result.Value = -1; @@ -2824,7 +2822,7 @@ public Result BatchTask( string strName, string strAction, TaskInfo info, - out TaskInfo [] results) + out TaskInfo[] results) { string strError = ""; results = null; diff --git a/DigitalPlatform.LibraryService/LibraryService.cs b/DigitalPlatform.LibraryService/LibraryService.cs index e36ebe4d1..e03a36a4e 100644 --- a/DigitalPlatform.LibraryService/LibraryService.cs +++ b/DigitalPlatform.LibraryService/LibraryService.cs @@ -2749,7 +2749,7 @@ public LibraryServerResult GetRecord( // rights: // 没有限制 // return: - // result.Value -1 出错;>=0 结果集内记录的总数(注意,并不是本批返回的记录数) + // result.Value -1 出错;0 成功 public LibraryServerResult GetBrowseRecords( string[] paths, string strBrowseInfoStyle, @@ -7716,25 +7716,23 @@ public LibraryServerResult BindPatron( { results = null; - LibraryServerResult result = this.PrepareEnvironment("BindingPatron", true); + LibraryServerResult result = this.PrepareEnvironment("BindingPatron", true, true, true); if (result.Value == -1) return result; try { - // 权限字符串 if (sessioninfo.RightsOriginList.IsInList("bindpatron") == false) { result.Value = -1; - result.ErrorInfo = "绑定号码的操作被拒绝。不具备 bindpatron 权限。"; + // result.ErrorInfo = "绑定号码的操作被拒绝。当前用户 '"+sessioninfo.UserID+"' 不具备 bindpatron 权限。"; + result.ErrorInfo = "绑定号码的操作被拒绝。当前用户不具备 bindpatron 权限。"; result.ErrorCode = ErrorCode.AccessDenied; return result; } - string strError = ""; - // 不需要登录 // return: // -2 权限不够,操作被拒绝 // -1 出错 diff --git a/DigitalPlatform.Text/StringUtil.cs b/DigitalPlatform.Text/StringUtil.cs index 4a4c90372..06ac56ca3 100644 --- a/DigitalPlatform.Text/StringUtil.cs +++ b/DigitalPlatform.Text/StringUtil.cs @@ -16,6 +16,7 @@ public class StringUtil { public static string SpecialChars = "!·#¥%……—*()——+-=[]《》<>,。?/\|{}“”‘’•"; + // 注: 和 GetStyleParam() 函数相似 // parameters: // strPrefix 前缀。例如 "getreaderinfo" // strDelimiter 前缀和后面参数的分隔符号。例如 ":" diff --git a/DigitalPlatform.rms.Client/RmsChannel.cs b/DigitalPlatform.rms.Client/RmsChannel.cs index 9ed8b38be..dfee68a23 100644 --- a/DigitalPlatform.rms.Client/RmsChannel.cs +++ b/DigitalPlatform.rms.Client/RmsChannel.cs @@ -366,7 +366,7 @@ public KernelServiceClient ws } if (String.IsNullOrEmpty(this.Url) == true) { - throw(new Exception("Url值此时应当不等于空")); + throw (new Exception("Url值此时应当不等于空")); } Debug.Assert(this.Url != "", "Url值此时应当不等于空"); @@ -639,7 +639,7 @@ int ConvertWebError(Exception ex0, static string GetExceptionMessage(Exception ex) { string strResult = ex.GetType().ToString() + ":" + ex.Message; - while(ex != null) + while (ex != null) { if (ex.InnerException != null) strResult += "\r\n" + ex.InnerException.GetType().ToString() + ": " + ex.InnerException.Message; @@ -826,7 +826,7 @@ public int LoginOld(string strUserName, { strError = ""; - REDO: + REDO: Result result = null; try { @@ -941,7 +941,7 @@ public int Login(string strUserName, { strError = ""; - REDO: + REDO: try { IAsyncResult soapresult = this.ws.BeginLogin(strUserName, @@ -1049,7 +1049,7 @@ public int ChangePassword( } - REDO: + REDO: try { IAsyncResult soapresult = null; @@ -1182,7 +1182,7 @@ public long DoInitialDB(string strDBName, { strError = ""; - REDO: + REDO: try { REDOINITIAL: @@ -1256,11 +1256,11 @@ public long DoRefreshDB( out string strError) { strError = ""; - /* - int nOldTimeout = this.Timeout; - this.Timeout = 20 * 60 * 1000; // 加大超时时间 - * */ - REDO: + /* + int nOldTimeout = this.Timeout; + this.Timeout = 20 * 60 * 1000; // 加大超时时间 + * */ + REDO: try { REDO_REFRESH: @@ -1339,7 +1339,7 @@ public long DoDeleteDB(string strDBName, { strError = ""; - REDO: + REDO: try { REDOINITIAL: @@ -1890,7 +1890,7 @@ public int DoCopyRecord(string strOriginRecordPath, public int DoBatchTask(string strName, string strAction, TaskInfo info, - out TaskInfo [] results, + out TaskInfo[] results, out string strError) { results = null; @@ -2279,7 +2279,7 @@ public long DoSearch(string strQueryXml, // 0 not found // >=1 命中记录条数 public long DoSearchWithoutLoginDlg( - string strQueryXml, + string strQueryXml, string strResultSetName, string strOutputStyle, out string strError) @@ -2349,7 +2349,7 @@ public long GetBrowseRecords(string[] paths, strError = ""; searchresults = null; - REDO: + REDO: try { IAsyncResult soapresult = this.ws.BeginGetBrowse( @@ -2373,7 +2373,7 @@ public long GetBrowseRecords(string[] paths, } Record[] records = null; Result result = this.ws.EndGetBrowse( - out records,soapresult); + out records, soapresult); if (result.Value == -1) { @@ -2437,7 +2437,6 @@ public long GetBrowseRecords(string[] paths, return -1; goto REDO; } - } // 根据指定的记录路径获得浏览格式记录 @@ -2594,7 +2593,7 @@ public int GetRecords( } Record[] records = null; Result result = this.ws.EndGetRecords( - out records,soapresult); + out records, soapresult); if (result.Value == -1) { @@ -2701,7 +2700,7 @@ public int GetRichRecords( } RichRecord[] records = null; Result result = this.ws.EndGetRichRecords( - out records,soapresult); + out records, soapresult); if (result.Value == -1) { @@ -2836,7 +2835,7 @@ public long DoBrowse( return -1; } Result result = this.ws.EndGetRecords( - out records,soapresult); + out records, soapresult); if (result.Value == -1) { @@ -3016,7 +3015,7 @@ public long DoGetSearchResult( } } -REDO: + REDO: try { IAsyncResult soapresult = this.ws.BeginGetRecords( @@ -3042,7 +3041,7 @@ public long DoGetSearchResult( return -1; } Result result = this.ws.EndGetRecords( - out records,soapresult); + out records, soapresult); if (result.Value == -1) { @@ -3200,7 +3199,7 @@ public long DoGetSearchResultEx( return -1; } Result result = this.ws.EndGetRecords( - out records,soapresult); + out records, soapresult); if (result.Value == -1) { @@ -3287,8 +3286,8 @@ public long DoGetSearchResultEx( nPerCount = 1; // 修改为最小数量重做一次 else return -1; - } - + } + goto REDO; } } @@ -3332,7 +3331,7 @@ public long DoGetSearchFullResult( } - REDO: + REDO: try { IAsyncResult soapresult = this.ws.BeginGetRecords( @@ -3358,7 +3357,7 @@ public long DoGetSearchFullResult( return -1; } Result result = this.ws.EndGetRecords( - out records,soapresult); + out records, soapresult); if (result.Value == -1) { @@ -3451,8 +3450,8 @@ public long DoGetSearchFullResult( nPerCount = 1; // 修改为最小数量重做一次 else return -1; - } - + } + goto REDO; } } @@ -3498,7 +3497,7 @@ public long DoGetSearchResultOneColumn( } - REDO: + REDO: try { IAsyncResult soapresult = this.ws.BeginGetRecords( @@ -3524,7 +3523,7 @@ public long DoGetSearchResultOneColumn( return -1; } Result result = this.ws.EndGetRecords( - out records,soapresult); + out records, soapresult); if (result.Value == -1) { @@ -3859,7 +3858,7 @@ public long DoGetKeys( } - REDO: + REDO: try { IAsyncResult soapresult = this.ws.BeginCreateKeys( @@ -3886,7 +3885,7 @@ public long DoGetKeys( return -1; } Result result = this.ws.EndCreateKeys( - out keys,soapresult); + out keys, soapresult); if (result.Value == -1) { @@ -4019,7 +4018,7 @@ public long DoGetKeys( } - REDO: + REDO: try { IAsyncResult soapresult = this.ws.BeginCreateKeys( @@ -4046,7 +4045,7 @@ public long DoGetKeys( return -1; } Result result = this.ws.EndCreateKeys( - out keys,soapresult); + out keys, soapresult); if (result.Value == -1) { @@ -4219,7 +4218,7 @@ public long DoDir(string strPath, return -1; } Result result = this.ws.EndDir( - out items,soapresult); + out items, soapresult); if (result.Value == -1) { @@ -4332,7 +4331,7 @@ public long WriteRes(string strResPath, } Result result = this.ws.EndWriteRes( out strOutputResPath, - out baOutputTimestamp,soapresult); + out baOutputTimestamp, soapresult); this.ErrorInfo = result.ErrorString; // 无论是否返回错误,都将result的ErrorString放到Channel中 @@ -4485,7 +4484,7 @@ public long DoSaveTextRes(string strPath, } Result result = this.ws.EndWriteRes( out strOutputPath, - out output_timestamp/*baOutputTimeStamp*/,soapresult); + out output_timestamp/*baOutputTimeStamp*/, soapresult); this.ErrorInfo = result.ErrorString; // 无论是否返回错误,都将result的ErrorString放到Channel中 strError = result.ErrorString; // 2007/6/28 服务于 带有局部path的保存中返回值放在strError的情况 @@ -4556,7 +4555,7 @@ public long DoSaveTextRes(string strPath, } // 包装后的版本 - // 删除数据库记录 + // 删除数据库记录 public long DoDeleteRes(string strPath, byte[] timestamp, out byte[] output_timestamp, @@ -4594,7 +4593,7 @@ public long DoDeleteRes(string strPath, * */ // byte[] baOutputTimeStamp = null; - REDO: + REDO: try { IAsyncResult soapresult = this.ws.BeginDeleteRes(strPath, @@ -4617,7 +4616,7 @@ public long DoDeleteRes(string strPath, return -1; } Result result = this.ws.EndDeleteRes( - out output_timestamp,soapresult); + out output_timestamp, soapresult); if (result.Value == -1) { @@ -4715,7 +4714,7 @@ public long DoRebuildResKeys(string strPath, return -1; } Result result = this.ws.EndRebuildResKeys( - out strOutputResPath,soapresult); + out strOutputResPath, soapresult); if (result.Value == -1) { @@ -5023,7 +5022,7 @@ public long GetRes(string strResPath, // out strID, out strMetadata, out strOutputResPath, - out baOutputTimestamp,soapresult); + out baOutputTimestamp, soapresult); // 即便不是返回-1,也可能有错误码和错误信息字符串 ConvertErrorCode(result); @@ -5155,7 +5154,7 @@ public long GetRes(string strPath, // out id, out strMetaData, out strOutputResPath, - out baOutputTimeStamp,soapresult); + out baOutputTimeStamp, soapresult); // 即便不是返回-1,也可能有错误码和错误信息字符串 ConvertErrorCode(result); @@ -5341,7 +5340,7 @@ public long GetRes(string strPath, // 0 成功 public long GetRes(string strPath, Stream fileTarget, - FlushOutput flushOutputMethod, + FlushOutput flushOutputMethod, DigitalPlatform.Stop stop, string strStyleParam, byte[] input_timestamp, @@ -5411,7 +5410,7 @@ public long GetRes(string strPath, return -1; } - REDO: + REDO: try { @@ -5473,7 +5472,7 @@ public long GetRes(string strPath, // out id, out strMetaData, out strOutputPath, - out timestamp,soapresult); + out timestamp, soapresult); // 即便不是返回-1,也可能有错误码和错误信息字符串 ConvertErrorCode(result); @@ -5579,7 +5578,7 @@ public long GetRes(string strPath, strError = "FlushOutputMethod()用户中断"; return -1; } - } + } lStart += baContent.Length; } @@ -5706,7 +5705,7 @@ public long DoSaveResObject(string strPath, } Result result = this.ws.EndWriteRes( out strOutputPath, - out output_timestamp,soapresult); + out output_timestamp, soapresult); if (result.Value == -1) { @@ -5761,7 +5760,7 @@ public long DoSaveResObject(string strPath, } - this.ClearRedoCount(); + this.ClearRedoCount(); return 0; } @@ -5934,27 +5933,27 @@ public void DoStop() public int DoTest(string strText) { - IAsyncResult soapresult = this.ws.BeginDoTest( - strText, - null, - null); + IAsyncResult soapresult = this.ws.BeginDoTest( + strText, + null, + null); - for (; ; ) - { - DoIdle(); // 出让控制权,避免CPU资源耗费过度 - bool bRet = soapresult.AsyncWaitHandle.WaitOne(100, false); - if (bRet == true) - break; - } + for (; ; ) + { + DoIdle(); // 出让控制权,避免CPU资源耗费过度 + bool bRet = soapresult.AsyncWaitHandle.WaitOne(100, false); + if (bRet == true) + break; + } - try - { - return this.ws.EndDoTest(soapresult); - } - catch // (WebException ex) - { - return -1; - } + try + { + return this.ws.EndDoTest(soapresult); + } + catch // (WebException ex) + { + return -1; + } } diff --git a/DigitalPlatform.rms.db/SessionInfo.cs b/DigitalPlatform.rms.db/SessionInfo.cs index d0ef26565..a45d2706f 100644 --- a/DigitalPlatform.rms.db/SessionInfo.cs +++ b/DigitalPlatform.rms.db/SessionInfo.cs @@ -1077,7 +1077,7 @@ public int API_GetBrowse(string[] paths, if (info == null) { - strError = "ParsePath() (strPath='"+strPath+"') error, info == null"; + strError = "ParsePath() (strPath='" + strPath + "') error, info == null"; return -1; } From 21cde56c92a7a0123228c06676319e2eb56f2291 Mon Sep 17 00:00:00 2001 From: XieTao Date: Sun, 17 Apr 2016 22:19:24 +0800 Subject: [PATCH 13/14] =?UTF-8?q?=E4=BF=AE=E6=AD=A3=20Bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DigitalPlatform.rms.db/SessionInfo.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/DigitalPlatform.rms.db/SessionInfo.cs b/DigitalPlatform.rms.db/SessionInfo.cs index a45d2706f..911dad837 100644 --- a/DigitalPlatform.rms.db/SessionInfo.cs +++ b/DigitalPlatform.rms.db/SessionInfo.cs @@ -1145,7 +1145,7 @@ public int API_GetBrowse(string[] paths, { Result result = new Result(); result.Value = -1; - result.ErrorCode = KernelApplication.Ret2ErrorCode(nRet); + result.ErrorCode = KernelApplication.Ret2ErrorCode((int)lRet); result.ErrorString = strError; record.RecordBody.Result = result; // return (int)lRet; @@ -1187,7 +1187,7 @@ public int API_GetBrowse(string[] paths, { Result result = new Result(); result.Value = -1; - result.ErrorCode = KernelApplication.Ret2ErrorCode(nRet); + result.ErrorCode = KernelApplication.Ret2ErrorCode((int)lRet); result.ErrorString = strError; record.RecordBody.Result = result; // return (int)lRet; From 3cb2dc952f5f42178b9a09c7080977a70bda7f04 Mon Sep 17 00:00:00 2001 From: XieTao Date: Sun, 17 Apr 2016 23:10:39 +0800 Subject: [PATCH 14/14] =?UTF-8?q?GetReaderInfo()=20API=20=E8=BF=94?= =?UTF-8?q?=E5=9B=9E=E7=9A=84=E8=AF=BB=E8=80=85=E8=AE=B0=E5=BD=95=E4=B8=AD?= =?UTF-8?q?=E8=87=AA=E5=8A=A8=E5=A2=9E=E5=8A=A0=20libraryCode=20=E5=85=83?= =?UTF-8?q?=E7=B4=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DigitalPlatform.LibraryServer/AppCirculation.cs | 4 +++- DigitalPlatform.LibraryServer/AppReader.cs | 17 ++++++++++++++--- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/DigitalPlatform.LibraryServer/AppCirculation.cs b/DigitalPlatform.LibraryServer/AppCirculation.cs index 7019e723d..eb408a628 100644 --- a/DigitalPlatform.LibraryServer/AppCirculation.cs +++ b/DigitalPlatform.LibraryServer/AppCirculation.cs @@ -5897,7 +5897,8 @@ public LibraryServerResult Return( } // 从读者记录中删除 password 元素 - static int RemovePassword(ref string strReaderXml, out string strError) + static int RemovePassword(ref string strReaderXml, + out string strError) { strError = ""; XmlDocument readerdom = new XmlDocument(); @@ -5912,6 +5913,7 @@ static int RemovePassword(ref string strReaderXml, out string strError) } DomUtil.DeleteElement(readerdom.DocumentElement, "password"); + strReaderXml = readerdom.DocumentElement.OuterXml; return 0; } diff --git a/DigitalPlatform.LibraryServer/AppReader.cs b/DigitalPlatform.LibraryServer/AppReader.cs index 12df13f1e..3002a6da5 100644 --- a/DigitalPlatform.LibraryServer/AppReader.cs +++ b/DigitalPlatform.LibraryServer/AppReader.cs @@ -3810,15 +3810,26 @@ public LibraryServerResult GetReaderInfo( { if (readerdom != null) + { DomUtil.DeleteElement(readerdom.DocumentElement, "password"); + DomUtil.SetElementText(readerdom.DocumentElement, "libraryCode", strLibraryCode); + } if (string.IsNullOrEmpty(strXml) == false) { - nRet = RemovePassword(ref strXml, out strError); - if (nRet == -1) + XmlDocument temp = new XmlDocument(); + try { - strError = "从读者记录中去除 password 阶段出错: " + strError; + temp.LoadXml(strXml); + } + catch (Exception ex) + { + strError = "读者记录 XML 装入 DOM 时出错:" + ex.Message; goto ERROR1; } + + DomUtil.DeleteElement(temp.DocumentElement, "password"); + DomUtil.SetElementText(temp.DocumentElement, "libraryCode", strLibraryCode); + strXml = temp.DocumentElement.OuterXml; } }