Преглед изворни кода

整合从IPEasy下载文档、比较文档功能,并添加了一个测试的整合form界面

luocaiyang пре 11 месеци
родитељ
комит
81f20740f4

+ 1 - 1
wispro.sp.utility/CompareDocx.cs

@@ -187,7 +187,7 @@ namespace wispro.sp.utility
 
             lastResult += oldtext.Substring(lastPos);
             _CompareResultString += oldtext.Substring(lastPos);
-            _CompareResultString = _CompareResultString.Replace("\r\n", "</p>\r\n<p>") + "</p>";
+            _CompareResultString = _CompareResultString.Replace("\r\n", "<br/>");
             
         }
 

+ 71 - 119
wispro.sp.utility/IPEasyUtility.cs

@@ -193,9 +193,7 @@ namespace wispro.sp.utility
                 try
                 {
                     WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(50));
-                    driver.Manage().Window.Maximize();
-                    driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(50);
-                    driver.Manage().Timeouts().PageLoad = TimeSpan.FromSeconds(100);
+                    
                     Login(driver, wait);
 
                     //点击顶部菜单栏中的案件管理菜单
@@ -233,7 +231,9 @@ namespace wispro.sp.utility
 
                     try
                     {
-                        var caseLink = driver.FindElement(By.XPath($"//a[contains(text(),'{caseNo}')]"));
+                        var caseLink = wait.Until((d) => { 
+                            return d.FindElement(By.XPath($"//a[contains(text(),'{caseNo}')]"));
+                        }); 
                         caseLink.Click();
                     }
                     catch(Exception ex)
@@ -342,7 +342,36 @@ namespace wispro.sp.utility
 
         private static void Download(dynamic retObject, IWebDriver driver, WebDriverWait wait, IWebElement table_filelist, string fileType)
         {
-            var finallyFile = table_filelist.FindElement(By.XPath($"//td[@colname='file_desc'][normalize-space()='{fileType}']"));
+            var finallyFile = wait.Until((d) =>
+            {
+                try { 
+                    return table_filelist.FindElement(By.XPath($"//td[@colname='file_desc'][normalize-space()='{fileType}']"));
+                }
+                catch (Exception ex) 
+                {
+                    
+                    return null;
+                }
+            });
+
+            if(finallyFile == null)
+            {
+                switch (fileType)
+                {
+                    case "新申请文档":
+                        retObject.finallyFile = null;
+                        break;
+                    case "新申请第一次返稿":
+                        retObject.firstReturnFile = null;
+                        break;
+                    case "新申请第一次内审":
+                        retObject.draftFile = null;
+                        break;
+                }
+
+                return;
+            }
+            
             var tdfileName = wait.Until((d) =>
             {
                 try
@@ -371,7 +400,8 @@ namespace wispro.sp.utility
             switch (fileType)
             {
                 case "新申请文档":
-                    retObject.finallyFile = filePath; break;
+                    retObject.finallyFile = filePath; 
+                    break;
                 case "新申请第一次返稿":
                     retObject.firstReturnFile = filePath;
                     break;
@@ -410,9 +440,7 @@ namespace wispro.sp.utility
                 try
                 {
                     WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(50));
-                    driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(50);
-                    driver.Manage().Timeouts().PageLoad = TimeSpan.FromSeconds(500);
-
+                    
                     Login(driver, wait);
 
                     //点击顶部菜单栏中的报表管理菜单
@@ -479,8 +507,12 @@ namespace wispro.sp.utility
             {
                 options.AddArgument("headless");
             }
-
-            return new OpenQA.Selenium.Chrome.ChromeDriver(ConfigHelper.GetSectionValue("IPEasySetting:ChormeDriverPath"), options);
+            var driver = new OpenQA.Selenium.Chrome.ChromeDriver(ConfigHelper.GetSectionValue("IPEasySetting:ChormeDriverPath"), options);
+            driver.Manage().Window.Maximize();
+            driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(50);
+            driver.Manage().Timeouts().PageLoad = TimeSpan.FromSeconds(100);
+            
+            return driver;
         }
 
         /// <summary>
@@ -500,11 +532,7 @@ namespace wispro.sp.utility
 
                     WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(20));
 
-                    Log($"{DateTime.Now}\tIWebDriver配置");
-                    driver.Manage().Window.Maximize();
-                    driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(50);
-                    driver.Manage().Timeouts().PageLoad = TimeSpan.FromSeconds(500);
-
+                    
                     Login(driver, wait);
                     //点击顶部菜单栏中的报表管理菜单
                     Log($"{DateTime.Now}\t点击顶部菜单栏中的报表管理菜单");
@@ -713,9 +741,7 @@ namespace wispro.sp.utility
                 try
                 {
                     WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(20));
-                    driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(5);
-                    driver.Manage().Timeouts().PageLoad = TimeSpan.FromSeconds(100);
-
+                    
                     Login(driver, wait);
 
                     //点击顶部菜单栏中的案件管理菜单
@@ -790,7 +816,6 @@ namespace wispro.sp.utility
             dynamic retObject = new ExpandoObject();
 
             retObject.CaseNo = caseNo.Trim();
-            //retObject.DoItem = doItemName;
 
             using (var Service = ChromeDriverService.CreateDefaultService(ConfigHelper.GetSectionValue("IPEasySetting:ChormeDriverPath")))
             {
@@ -801,8 +826,6 @@ namespace wispro.sp.utility
                     try
                     {
                         WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(20));
-                        driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(20);
-                        driver.Manage().Timeouts().PageLoad = TimeSpan.FromSeconds(100);
                         
                         Login(driver,wait);
 
@@ -985,6 +1008,7 @@ namespace wispro.sp.utility
         {
             if (caseNo.StartsWith("APCN"))
             {
+                //商标
                 return GetAPCNPerformanceRecord(caseNo, doItemName, caseStage);
             }
             
@@ -1001,49 +1025,21 @@ namespace wispro.sp.utility
                 {
                     try
                     {
-                        driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(20);
-                        driver.Manage().Timeouts().PageLoad = TimeSpan.FromSeconds(100);
-                        //driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(100);
                         WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(20));
 
-                        //进入登录界面
-                        driver.Navigate().GoToUrl(ConfigHelper.GetSectionValue("IPEasySetting:IPEasyWeb"));
-
-                        //输入用户名和密码
-                        driver.FindElement(By.Id("txtUser")).SendKeys(Account);
-                        driver.FindElement(By.Id("txtPwd")).SendKeys(Password);
-
-                        //点击登录按钮
-                        driver.FindElement(By.Id("btnLogin")).Click();
-
-                        //关闭提示遮罩层
-                        driver.FindElement(By.Id("jpwClose")).Click();
-
-                        //try
-                        //{
-                        //    var okBtn = driver.FindElement(By.ClassName("ui_state_highlight"));
-                        //    if (okBtn != null && okBtn.TagName == "input")
-                        //    {
-                        //        okBtn.Click();
-                        //    }
-                        //}
-                        //catch { }
+                        Login(driver, wait);
 
                         //点击顶部菜单栏中的案件管理菜单
-                        driver.FindElement(By.Name("71A7CC35-F597-40E1-9FEF-BE622A3A3B63")).Click();
-                        System.Threading.Thread.Sleep(500);
+                        waitGetElementByName(wait,"71A7CC35-F597-40E1-9FEF-BE622A3A3B63").Click();
 
                         //点击左侧 查询 菜单
-                        driver.FindElement(By.Name("c3266ab3-521a-4815-8aaf-7dd0bc5a76af")).Click();
+                        waitGetElementByName(wait, "c3266ab3-521a-4815-8aaf-7dd0bc5a76af").Click();
 
-                        
-                        //System.Threading.Thread.Sleep(500);
+                        driver.SwitchTo().Frame(1);
                         var inputSearch = wait.Until((d) =>
                         {
                             try
                             {
-                                //切换到自定义报表Frame
-                                d.SwitchTo().Frame(1);
                                 return d.FindElement(By.Id("case_volume"));
                             }
                             catch
@@ -1052,13 +1048,10 @@ namespace wispro.sp.utility
                             }
 
                         });
-                        //切换到自定义报表Frame
-                        //driver.SwitchTo().Frame(1);
-
-                        //var inputSearch = driver.FindElement(By.Id("case_volume"));
+                        
                         inputSearch.SendKeys(caseNo.Trim());
 
-                        var btnSearch = driver.FindElement(By.Id("btn_Search"));
+                        var btnSearch = waitGetElementById(wait,"btn_Search");
                         btnSearch.Click();
 
                         var caseLink = wait.Until((d) =>
@@ -1073,14 +1066,12 @@ namespace wispro.sp.utility
                             }
 
                         });
-                        //System.Threading.Thread.Sleep(500);
-
-                        //var caseLink = driver.FindElement(By.XPath($"//a[normalize-space()='{caseNo.Trim()}']"));
                         caseLink.Click();
-                        System.Threading.Thread.Sleep(500);
 
                         driver.SwitchTo().ParentFrame().SwitchTo().Frame(2);
-                        var DoItemLinks = driver.FindElements(By.XPath($"//td[@colname='ctrl_proc'][normalize-space()='{doItemName}']"));
+                        var DoItemLinks = wait.Until((d) => { 
+                            return d.FindElements(By.XPath($"//td[@colname='ctrl_proc'][normalize-space()='{doItemName}']"));
+                        }); 
                         if (DoItemLinks.Count > 0)
                         {
                             if (!string.IsNullOrEmpty(caseStage))
@@ -1098,10 +1089,8 @@ namespace wispro.sp.utility
                                         retObject.DoPersons = DoItemLink.FindElement(By.XPath("following-sibling::td[8]")).Text;   //处理人
                                         retObject.DoItemMemo = DoItemLink.FindElement(By.XPath("following-sibling::td[9]")).Text;   //处理事项备注
                                         retObject.Reviewer = DoItemLink.FindElement(By.XPath("following-sibling::td[10]")).Text;   //核稿人
-
-                                        System.Threading.Thread.Sleep(4000);
+                                        
                                         DoItemLink.Click();
-                                        //driver.ExecuteJavaScript("$(arguments[0]).click()", DoItemLink);
                                         break;
                                     }
                                 }
@@ -1118,10 +1107,7 @@ namespace wispro.sp.utility
                                 retObject.DoItemMemo = DoItemLink.FindElement(By.XPath("following-sibling::td[9]")).Text;   //处理事项备注
                                 retObject.Reviewer = DoItemLink.FindElement(By.XPath("following-sibling::td[10]")).Text;   //核稿人
 
-                                System.Threading.Thread.Sleep(4000);
-                                
                                 DoItemLink.Click();
-                                //new WebDriverWait(driver, TimeSpan.FromSeconds(20)).Until(ExpectedConditions.ElementToBeClickable(DoItemLink)).Click();
                                 
                             }
                         }
@@ -1138,7 +1124,6 @@ namespace wispro.sp.utility
                             }
 
                         });
-                        //System.Threading.Thread.Sleep(500);
 
                         retObject.FinalizationDate = p_proc_finish_doc_date.GetAttribute("value");   //定稿日
                         retObject.ReturnDate = driver.FindElement(By.Id("p_proc_info__back_date")).GetAttribute("value");               //返稿日
@@ -1146,8 +1131,7 @@ namespace wispro.sp.utility
                         retObject.DoItemCoefficient = driver.FindElement(By.Id("p_proc_info__proc_coefficient")).GetAttribute("value"); //处理事项系数
                         retObject.WordCount = driver.FindElement(By.Id("p_proc_info__translate_count")).GetAttribute("value");          //翻译字数
 
-
-                        driver.FindElement(By.Id("libase")).Click();
+                        waitGetElementById(wait, "libase").Click();
 
                         var p_case_info__case_name = wait.Until((d) =>
                         {
@@ -1161,7 +1145,6 @@ namespace wispro.sp.utility
                             }
 
                         });
-                        //System.Threading.Thread.Sleep(500);
                         retObject.CaseName = p_case_info__case_name.GetAttribute("value");  //案件名称
                         retObject.CustomerName = driver.FindElement(By.Id("p_case_info__customer_id")).GetAttribute("value");  //客户名称
                         retObject.BusinessType = driver.FindElement(By.Id("p_case_info__business_type_id")).GetAttribute("value");     //业务类型
@@ -1175,9 +1158,7 @@ namespace wispro.sp.utility
                         retObject.CaseMemo = driver.FindElement(By.Id("p_case_info__remark")).GetAttribute("value");    //案件备注
 
                         driver.FindElement(By.XPath($"//span[contains(text(),'扩展信息')]")).Click();
-                        //select[@id='p_case_info__case_coefficient_id']
                         retObject.CaseCoefficient = GetSelectText(driver.FindElement(By.Id("p_case_info__case_coefficient_id")));
-
                         
 
                     }
@@ -1215,33 +1196,9 @@ namespace wispro.sp.utility
                 {
                     try
                     {
-                        driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(20);
-                        driver.Manage().Timeouts().PageLoad = TimeSpan.FromSeconds(100);
-                        //driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(100);
                         WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(20));
 
-                        //进入登录界面
-                        driver.Navigate().GoToUrl(ConfigHelper.GetSectionValue("IPEasySetting:IPEasyWeb"));
-
-                        //输入用户名和密码
-                        driver.FindElement(By.Id("txtUser")).SendKeys(Account);
-                        driver.FindElement(By.Id("txtPwd")).SendKeys(Password);
-
-                        //点击登录按钮
-                        driver.FindElement(By.Id("btnLogin")).Click();
-
-                        //关闭提示遮罩层
-                        driver.FindElement(By.Id("jpwClose")).Click();
-
-                        //try
-                        //{
-                        //    var okBtn = driver.FindElement(By.ClassName("ui_state_highlight"));
-                        //    if (okBtn != null && okBtn.TagName == "input")
-                        //    {
-                        //        okBtn.Click();
-                        //    }
-                        //}
-                        //catch { }
+                        Login(driver, wait);
 
                         //点击顶部菜单栏中的案件管理菜单
                         driver.FindElement(By.Name("71A7CC35-F597-40E1-9FEF-BE622A3A3B63")).Click();
@@ -1249,15 +1206,13 @@ namespace wispro.sp.utility
 
                         //点击左侧 查询 菜单
                         driver.FindElement(By.Name("FF4E1FF9-FE36-4F0F-99DF-81E60817722E")).Click();
-
-
-                        //System.Threading.Thread.Sleep(500);
+                        driver.SwitchTo().Frame(1);
                         var inputSearch = wait.Until((d) =>
                         {
                             try
                             {
                                 //切换到自定义报表Frame
-                                d.SwitchTo().Frame(1);
+                                
                                 return d.FindElement(By.Id("case_volume"));
                             }
                             catch
@@ -1266,13 +1221,10 @@ namespace wispro.sp.utility
                             }
 
                         });
-                        //切换到自定义报表Frame
-                        //driver.SwitchTo().Frame(1);
-
-                        //var inputSearch = driver.FindElement(By.Id("case_volume"));
+                        
                         inputSearch.SendKeys(caseNo.Trim());
 
-                        var btnSearch = driver.FindElement(By.Id("btn_Search"));
+                        var btnSearch = waitGetElementById(wait,"btn_Search");
                         btnSearch.Click();
 
                         var caseLink = wait.Until((d) =>
@@ -1287,21 +1239,23 @@ namespace wispro.sp.utility
                             }
 
                         });
-                        //System.Threading.Thread.Sleep(500);
-
-                        //var caseLink = driver.FindElement(By.XPath($"//a[normalize-space()='{caseNo.Trim()}']"));
                         caseLink.Click();
-                        System.Threading.Thread.Sleep(500);
 
                         driver.SwitchTo().ParentFrame().SwitchTo().Frame(2);
-                        var DoItemLinks = driver.FindElements(By.XPath($"//td[@colname='ctrl_proc'][normalize-space()='{doItemName}']"));
+                        var DoItemLinks = wait.Until((d) => {
+                            return driver.FindElements(By.XPath($"//td[@colname='ctrl_proc'][normalize-space()='{doItemName}']"));
+                        }); 
+
                         if (DoItemLinks.Count > 0)
                         {
                             if (!string.IsNullOrEmpty(caseStage))
                             {
                                 foreach (var DoItemLink in DoItemLinks)
                                 {
-                                    var temCaseStage = DoItemLink.FindElement(By.XPath("following-sibling::td[1]")).Text;
+                                    var temCaseStage = wait.Until((d) => { 
+                                        return DoItemLink.FindElement(By.XPath("following-sibling::td[1]"));
+                                    }).Text; 
+
                                     if (temCaseStage == caseStage)
                                     {
                                         retObject.CaseStage = DoItemLink.FindElement(By.XPath("following-sibling::td[1]")).Text; //案件阶段
@@ -1313,7 +1267,6 @@ namespace wispro.sp.utility
                                         retObject.DoItemMemo = DoItemLink.FindElement(By.XPath("following-sibling::td[9]")).Text;   //处理事项备注
                                         retObject.Reviewer = DoItemLink.FindElement(By.XPath("following-sibling::td[10]")).Text;   //核稿人
 
-                                        System.Threading.Thread.Sleep(4000);
                                         DoItemLink.Click();
                                         //driver.ExecuteJavaScript("$(arguments[0]).click()", DoItemLink);
                                         break;
@@ -1332,7 +1285,6 @@ namespace wispro.sp.utility
                                 retObject.DoItemMemo = DoItemLink.FindElement(By.XPath("following-sibling::td[10]")).Text;   //处理事项备注
                                 //retObject.Reviewer = DoItemLink.FindElement(By.XPath("following-sibling::td[10]")).Text;   //核稿人
 
-                                System.Threading.Thread.Sleep(4000);
 
                                 DoItemLink.Click();
                                 //new WebDriverWait(driver, TimeSpan.FromSeconds(20)).Until(ExpectedConditions.ElementToBeClickable(DoItemLink)).Click();
@@ -1361,7 +1313,7 @@ namespace wispro.sp.utility
                         retObject.WordCount = driver.FindElement(By.Id("p_proc_info__translate_count")).GetAttribute("value");          //翻译字数
 
 
-                        driver.FindElement(By.Id("libase")).Click();
+                        waitGetElementById(wait,"libase").Click();
 
                         var p_case_info__case_name = wait.Until((d) =>
                         {

+ 9 - 66
wispro.sp.winClient/Form1.cs

@@ -1,4 +1,5 @@
-using System;
+using DocumentFormat.OpenXml.Wordprocessing;
+using System;
 using System.Collections.Generic;
 using System.ComponentModel;
 using System.Configuration;
@@ -50,77 +51,19 @@ namespace wispro.sp.winClient
             }
         }
 
-        private void ExtractZip(string zipFilePath,string extractPath)
-        {
-            Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
-            // 确保提取目录存在
-            Directory.CreateDirectory(extractPath);
-
-            // 使用 ZipArchive 解压缩 ZIP 文件
-            using (FileStream zipToOpen = new FileStream(zipFilePath, FileMode.Open))
-            {
-                using (ZipArchive archive = new ZipArchive(zipToOpen, ZipArchiveMode.Read, true, Encoding.GetEncoding("GB2312")))
-                {
-                    foreach (ZipArchiveEntry entry in archive.Entries)
-                    {
-                        if (entry.FullName.EndsWith("/", StringComparison.Ordinal) || entry.FullName.EndsWith("\\", StringComparison.Ordinal))
-                        {
-                            Console.WriteLine($"目录: {entry.FullName}");
-                        }
-                        else
-                        {
-                            string entryPath = Path.Combine(extractPath, entry.FullName);
-
-                            Directory.CreateDirectory(new System.IO.FileInfo(entryPath).Directory.FullName);
-                            entry.ExtractToFile(entryPath, true);
-                        }
-                    }
-                }
-            }
-        }
+        
         private void button2_Click(object sender, EventArgs e)
         {
-            DataTable dt = IPEasyUtility.DownloadReport("每月绩效统计--上个月递交完成案件", true);
+            
+            
             return;
-            //var retObj = IPEasyUtility.DownloadCaseFiles("S2418519-测试卷");
-            var retObj1 = IPEasyUtility.DownloadCaseFiles("S2435631-测试卷-压缩包");
 
-            if (((IDictionary<string, object>)retObj1).ContainsKey("finallyFile"))
-            {
-                if (!string.IsNullOrEmpty(retObj1.finallyFile))
-                {
-                    if (retObj1.finallyFile.EndsWith(".zip"))
-                    {
-                        ExtractZip(retObj1.finallyFile, $"c:\\temp\\{retObj1.CaseNo}\\finallyFile");
-                    }
-                }
-            }
-
-            if (((IDictionary<string, object>)retObj1).ContainsKey("firstReturnFile"))
-            {
-                if (!string.IsNullOrEmpty(retObj1.firstReturnFile))
-                {
-                    if (retObj1.firstReturnFile.EndsWith(".zip"))
-                    {
-                        ExtractZip(retObj1.firstReturnFile, $"c:\\temp\\{retObj1.CaseNo}\\firstReturnFile");
-                    }
-                }
-            }
+            IPEasyUtility.GetPerformanceRecord("S2435631-测试卷-压缩包", "新申请", "递交中");
+            return;
 
-            if (((IDictionary<string, object>)retObj1).ContainsKey("draftFile"))
-            {
-                if (!string.IsNullOrEmpty(retObj1.draftFile))
-                {
-                    if (retObj1.draftFile.EndsWith(".zip"))
-                    {
-                        ExtractZip(retObj1.draftFile, $"c:\\temp\\{retObj1.CaseNo}\\draftFile");
-                    }
-                }
-            }
+            DataTable dt = IPEasyUtility.DownloadReport("每月绩效统计--上个月递交完成案件", true);
+            return;
 
-            
-            
-            
             OpenFileDialog ofd = new OpenFileDialog()
             {
                 Multiselect = false,

+ 148 - 0
wispro.sp.winClient/HtmlToRtfConverter.cs

@@ -0,0 +1,148 @@
+using System.Windows.Forms;
+using System.Text.RegularExpressions;
+using System.Web;
+using System.Drawing;
+using System;
+using System.Linq;
+
+namespace wispro.sp.winClient
+{
+  
+    public class HtmlToRtfConverter
+    {
+        public string ConvertHtmlToRtf(string html)
+        {
+            try
+            {
+                using (RichTextBox rtBox = new RichTextBox())
+                {
+                    string decodedHtml = HttpUtility.HtmlDecode(html);
+                    ProcessHtmlContent(rtBox, decodedHtml);
+                    return rtBox.Rtf;
+                }
+            }
+            catch (Exception ex)
+            {
+                throw new Exception($"HTML转RTF时发生错误: {ex.Message}");
+            }
+        }
+
+        private void ProcessHtmlContent(RichTextBox rtBox, string html)
+        {
+            // 首先处理段落
+            var paragraphs = Regex.Split(html, @"</?p>")
+                                 .Where(p => !string.IsNullOrWhiteSpace(p));
+
+            foreach (var paragraph in paragraphs)
+            {
+                // 处理段落内的内联元素
+                ProcessInlineElements(rtBox, paragraph);
+
+                // 在段落后添加换行
+                if (!rtBox.Text.EndsWith(Environment.NewLine))
+                {
+                    rtBox.AppendText(Environment.NewLine);
+                }
+            }
+        }
+
+        private void ProcessInlineElements(RichTextBox rtBox, string html)
+        {
+            // 匹配内联元素,包括strike、u标签和br标签
+            string pattern = @"<(?<tag>strike|u)[^>]*style=['""](?<style>[^'""]*)['""]>(?<text>[^<]*)</\k<tag>>|<br\s*/>|(?<text>[^<]+)";
+
+            int lastIndex = 0;
+            foreach (Match match in Regex.Matches(html, pattern))
+            {
+                // 处理标签之间的纯文本
+                int textStart = match.Index;
+                if (textStart > lastIndex)
+                {
+                    string plainText = html.Substring(lastIndex, textStart - lastIndex);
+                    if (!string.IsNullOrWhiteSpace(plainText))
+                    {
+                        rtBox.AppendText(plainText);
+                    }
+                }
+
+                string tag = match.Groups["tag"].Value;
+                string style = match.Groups["style"].Value;
+                string text = match.Groups["text"].Value;
+
+                if (match.Value.StartsWith("<br"))
+                {
+                    // 处理换行标签
+                    rtBox.AppendText(Environment.NewLine);
+                }
+                else if (!string.IsNullOrEmpty(tag))
+                {
+                    // 处理格式化标签
+                    ApplyFormatting(rtBox, tag, style, text);
+                }
+                else if (!string.IsNullOrEmpty(text))
+                {
+                    // 处理纯文本
+                    rtBox.AppendText(text);
+                }
+
+                lastIndex = match.Index + match.Length;
+            }
+
+            // 处理剩余的文本
+            if (lastIndex < html.Length)
+            {
+                string remainingText = html.Substring(lastIndex);
+                if (!string.IsNullOrWhiteSpace(remainingText))
+                {
+                    rtBox.AppendText(remainingText);
+                }
+            }
+        }
+
+        private void ApplyFormatting(RichTextBox rtBox, string tag, string style, string text)
+        {
+            // 保存当前的格式设置
+            Font originalFont = rtBox.SelectionFont ?? rtBox.Font;
+            Color originalColor = rtBox.SelectionColor;
+
+            // 设置字体样式
+            FontStyle fontStyle = FontStyle.Regular;
+            Color textColor = originalColor;
+
+            // 根据标签和样式设置格式
+            if (tag == "strike" || style.Contains("line-through"))
+            {
+                fontStyle |= FontStyle.Strikeout;
+            }
+            if (tag == "u" || style.Contains("underline"))
+            {
+                fontStyle |= FontStyle.Underline;
+            }
+
+            // 处理颜色
+            var colorMatch = Regex.Match(style, @"color:\s*([^;]+)");
+            if (colorMatch.Success)
+            {
+                try
+                {
+                    string colorValue = colorMatch.Groups[1].Value.Trim();
+                    textColor = ColorTranslator.FromHtml(colorValue);
+                }
+                catch { /* 忽略无效的颜色值 */ }
+            }
+
+            // 应用格式
+            rtBox.SelectionStart = rtBox.TextLength;
+            rtBox.SelectionLength = 0;
+            rtBox.SelectionFont = new Font(originalFont.FontFamily, originalFont.Size, fontStyle);
+            rtBox.SelectionColor = textColor;
+
+            // 添加文本
+            rtBox.AppendText(text);
+
+            // 恢复原始格式
+            rtBox.SelectionFont = originalFont;
+            rtBox.SelectionColor = originalColor;
+        }
+    }
+}

+ 2 - 1
wispro.sp.winClient/Program.cs

@@ -17,7 +17,8 @@ namespace wispro.sp.winClient
             Application.SetHighDpiMode(HighDpiMode.SystemAware);
             Application.EnableVisualStyles();
             Application.SetCompatibleTextRenderingDefault(false);
-            Application.Run(new Form1());
+            //Application.Run(new Form1());
+            Application.Run(new frmCaseFileCompare());
         }
     }
 }

+ 1 - 1
wispro.sp.winClient/appsettings.json

@@ -4,7 +4,7 @@
     "isHeadless": "false",
     "Account": "caiyangl",
     "Password": "j)wx*lier*@3",
-    "ChormeDriverPath": "E:\\source\\repos\\StaffPerformance\\packages\\ChormeDriver\\130.0.6723.91",
+    "ChormeDriverPath": "D:\\source\\repos\\StaffPerformance\\packages\\ChormeDriver\\130.0.6723.69",
     "ScheduleSetting": "00 55 10 3 * ? *",
     "IPEasyWeb": "http://47.106.94.35/Login.aspx"
   },

+ 110 - 0
wispro.sp.winClient/frmCaseFileCompare.Designer.cs

@@ -0,0 +1,110 @@
+namespace wispro.sp.winClient
+{
+    partial class frmCaseFileCompare
+    {
+        /// <summary>
+        /// Required designer variable.
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary>
+        /// Clean up any resources being used.
+        /// </summary>
+        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Windows Form Designer generated code
+
+        /// <summary>
+        /// Required method for Designer support - do not modify
+        /// the contents of this method with the code editor.
+        /// </summary>
+        private void InitializeComponent()
+        {
+            button1 = new System.Windows.Forms.Button();
+            label1 = new System.Windows.Forms.Label();
+            txtCaseNo = new System.Windows.Forms.TextBox();
+            comboBox1 = new System.Windows.Forms.ComboBox();
+            richTextBox1 = new System.Windows.Forms.RichTextBox();
+            SuspendLayout();
+            // 
+            // button1
+            // 
+            button1.Location = new System.Drawing.Point(618, 27);
+            button1.Name = "button1";
+            button1.Size = new System.Drawing.Size(131, 40);
+            button1.TabIndex = 0;
+            button1.Text = "开始比较";
+            button1.UseVisualStyleBackColor = true;
+            button1.Click += button1_Click;
+            // 
+            // label1
+            // 
+            label1.AutoSize = true;
+            label1.Location = new System.Drawing.Point(26, 33);
+            label1.Name = "label1";
+            label1.Size = new System.Drawing.Size(138, 28);
+            label1.TabIndex = 1;
+            label1.Text = "请输入案号:";
+            label1.Click += label1_Click;
+            // 
+            // txtCaseNo
+            // 
+            txtCaseNo.Location = new System.Drawing.Point(179, 30);
+            txtCaseNo.Name = "txtCaseNo";
+            txtCaseNo.Size = new System.Drawing.Size(421, 34);
+            txtCaseNo.TabIndex = 2;
+            // 
+            // comboBox1
+            // 
+            comboBox1.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right;
+            comboBox1.FormattingEnabled = true;
+            comboBox1.Items.AddRange(new object[] { "比较结果", "初稿与第一次返稿文档修订文字", "第一次返稿与定稿文档修订文字" });
+            comboBox1.Location = new System.Drawing.Point(1028, 30);
+            comboBox1.Name = "comboBox1";
+            comboBox1.Size = new System.Drawing.Size(348, 36);
+            comboBox1.TabIndex = 4;
+            comboBox1.SelectedIndexChanged += comboBox1_SelectedIndexChanged;
+            // 
+            // richTextBox1
+            // 
+            richTextBox1.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right;
+            richTextBox1.Location = new System.Drawing.Point(26, 93);
+            richTextBox1.Name = "richTextBox1";
+            richTextBox1.Size = new System.Drawing.Size(1350, 626);
+            richTextBox1.TabIndex = 5;
+            richTextBox1.Text = "";
+            // 
+            // frmCaseFileCompare
+            // 
+            AutoScaleDimensions = new System.Drawing.SizeF(13F, 28F);
+            AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+            ClientSize = new System.Drawing.Size(1408, 747);
+            Controls.Add(richTextBox1);
+            Controls.Add(comboBox1);
+            Controls.Add(txtCaseNo);
+            Controls.Add(label1);
+            Controls.Add(button1);
+            Name = "frmCaseFileCompare";
+            Text = "专利案件初稿、返稿和定稿文件比较";
+            WindowState = System.Windows.Forms.FormWindowState.Maximized;
+            ResumeLayout(false);
+            PerformLayout();
+        }
+
+        #endregion
+
+        private System.Windows.Forms.Button button1;
+        private System.Windows.Forms.Label label1;
+        private System.Windows.Forms.TextBox txtCaseNo;
+        private System.Windows.Forms.ComboBox comboBox1;
+        private System.Windows.Forms.RichTextBox richTextBox1;
+    }
+}

+ 215 - 0
wispro.sp.winClient/frmCaseFileCompare.cs

@@ -0,0 +1,215 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.IO;
+using System.IO.Compression;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+using wispro.sp.utility;
+
+namespace wispro.sp.winClient
+{
+    public partial class frmCaseFileCompare : Form
+    {
+        private CompareDocx draft_fristReturn;
+        private CompareDocx fristReturn_Finally;
+        public frmCaseFileCompare()
+        {
+            InitializeComponent();
+        }
+
+        private void label1_Click(object sender, EventArgs e)
+        {
+
+        }
+
+        private void button1_Click(object sender, EventArgs e)
+        {
+            if (string.IsNullOrEmpty(this.txtCaseNo.Text))
+            {
+                MessageBox.Show("请输入案号!","提示框",MessageBoxButtons.OK);
+                this.txtCaseNo.Focus();
+                return;
+            }
+            var retObj1 = IPEasyUtility.DownloadCaseFiles(this.txtCaseNo.Text);
+
+            string draftFile = null;
+            string firstReFile = null;
+            string finallyFile = null;
+            if (((IDictionary<string, object>)retObj1).ContainsKey("finallyFile"))
+            {
+                if (!string.IsNullOrEmpty(retObj1.finallyFile))
+                {
+                    if (retObj1.finallyFile.EndsWith(".zip"))
+                    {
+                        ExtractZip(retObj1.finallyFile, $"c:\\temp\\{retObj1.CaseNo}\\finallyFile");
+
+                        foreach (string f in Directory.GetFiles($"c:\\temp\\{retObj1.CaseNo}\\finallyFile", "*.*", SearchOption.AllDirectories))
+                        {
+                            if (f.IndexOf("定稿", StringComparison.OrdinalIgnoreCase) > 0)
+                            {
+                                finallyFile = f;
+                                break;
+                            }
+                        }
+                    }
+                    else
+                    {
+                        finallyFile = retObj1.finallyFile;
+                    }
+                }
+            }
+
+            if (((IDictionary<string, object>)retObj1).ContainsKey("firstReturnFile"))
+            {
+                if (!string.IsNullOrEmpty(retObj1.firstReturnFile))
+                {
+                    if (retObj1.firstReturnFile.EndsWith(".zip"))
+                    {
+                        ExtractZip(retObj1.firstReturnFile, $"c:\\temp\\{retObj1.CaseNo}\\firstReturnFile");
+                        foreach (string f in Directory.GetFiles($"c:\\temp\\{retObj1.CaseNo}\\firstReturnFile", "*.*", SearchOption.AllDirectories))
+                        {
+                            if (f.IndexOf("v1F", StringComparison.OrdinalIgnoreCase) > 0)
+                            {
+                                firstReFile = f;
+                                break;
+                            }
+                        }
+                    }
+                    else
+                    {
+                        firstReFile = retObj1.firstReturnFile;
+                    }
+                }
+            }
+
+            if (((IDictionary<string, object>)retObj1).ContainsKey("draftFile"))
+            {
+                if (!string.IsNullOrEmpty(retObj1.draftFile))
+                {
+                    if (retObj1.draftFile.EndsWith(".zip"))
+                    {
+                        ExtractZip(retObj1.draftFile, $"c:\\temp\\{retObj1.CaseNo}\\draftFile");
+
+                        foreach (string f in Directory.GetFiles($"c:\\temp\\{retObj1.CaseNo}\\draftFile", "*.*", SearchOption.AllDirectories))
+                        {
+                            if (f.IndexOf("v1r0", StringComparison.OrdinalIgnoreCase) > 0)
+                            {
+                                draftFile = f;
+                                break;
+                            }
+                        }
+                    }
+                    else
+                    {
+                        draftFile = retObj1.draftFile;
+                    }
+                }
+
+            }
+
+            if(!string.IsNullOrEmpty(firstReFile) && !string.IsNullOrEmpty(draftFile))
+            {
+                draft_fristReturn = new CompareDocx();
+                draft_fristReturn.Compare(draftFile, firstReFile);
+            }
+
+            if (!string.IsNullOrEmpty(firstReFile) && !string.IsNullOrEmpty(finallyFile))
+            {
+                fristReturn_Finally = new CompareDocx();
+                fristReturn_Finally.Compare(firstReFile, finallyFile);
+            }
+            
+            if (!string.IsNullOrEmpty(retObj1.finallyFile))
+                File.Delete(retObj1.finallyFile);
+
+            if (!string.IsNullOrEmpty(retObj1.draftFile))
+                File.Delete(retObj1.draftFile);
+
+            if (!string.IsNullOrEmpty(retObj1.draftFile))
+                File.Delete(retObj1.firstReturnFile);
+
+            if (Directory.Exists($"c:\\temp\\{retObj1.CaseNo}"))
+            {
+                Directory.Delete($"c:\\temp\\{retObj1.CaseNo}", true);
+            }
+
+            comboBox1.SelectedIndex = 0;
+
+        }
+
+        private void ExtractZip(string zipFilePath, string extractPath)
+        {
+            Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
+            // 确保提取目录存在
+            Directory.CreateDirectory(extractPath);
+
+            // 使用 ZipArchive 解压缩 ZIP 文件
+            using (FileStream zipToOpen = new FileStream(zipFilePath, FileMode.Open))
+            {
+                using (ZipArchive archive = new ZipArchive(zipToOpen, ZipArchiveMode.Read, true, Encoding.GetEncoding("GB2312")))
+                {
+                    foreach (ZipArchiveEntry entry in archive.Entries)
+                    {
+                        if (entry.FullName.EndsWith("/", StringComparison.Ordinal) || entry.FullName.EndsWith("\\", StringComparison.Ordinal))
+                        {
+                            Console.WriteLine($"目录: {entry.FullName}");
+                        }
+                        else
+                        {
+                            string entryPath = Path.Combine(extractPath, entry.FullName);
+
+                            Directory.CreateDirectory(new System.IO.FileInfo(entryPath).Directory.FullName);
+                            entry.ExtractToFile(entryPath, true);
+                        }
+                    }
+                }
+            }
+        }
+
+        private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            if (draft_fristReturn != null || fristReturn_Finally != null)
+            {
+                richTextBox1.Clear();
+
+                switch (comboBox1.SelectedIndex)
+                {
+                    case 0:
+                        string strHtml = string.Empty;
+                        if(draft_fristReturn != null)
+                        {
+                            strHtml =  $"<p>初稿与第一次返稿比较结果:</p><p>初稿文件字数:{draft_fristReturn.oldDocumentCount}</p><p>删除文字数量:{draft_fristReturn.DeleteCount}</p><p>插入文字数量:{draft_fristReturn.InsertCount}</p><p>修改比率:{(draft_fristReturn.diffRate * 100).ToString("0.0000")}%</p>";
+                        }
+                        
+                        if(fristReturn_Finally != null)
+                        {
+                            strHtml = strHtml + $"<p></p><p>第一次返稿与定稿比较结果:</p><p>第一次返稿文件字数:{fristReturn_Finally.oldDocumentCount}</p><p>删除文字数量:{fristReturn_Finally.DeleteCount}</p><p>插入文字数量:{fristReturn_Finally.InsertCount}</p><p>修改比率:{(fristReturn_Finally.diffRate * 100).ToString("0.0000")}%</p>";
+                        }
+
+
+                        richTextBox1.Rtf = new HtmlToRtfConverter().ConvertHtmlToRtf(strHtml);
+
+                        break;
+                    case 1:
+                        if (draft_fristReturn != null)
+                        {
+                            richTextBox1.Rtf = new HtmlToRtfConverter().ConvertHtmlToRtf(draft_fristReturn.CompareResultString);
+                        }
+                        
+                        break;
+                    case 2:
+                        if(fristReturn_Finally!= null)
+                        {
+                            richTextBox1.Rtf = new HtmlToRtfConverter().ConvertHtmlToRtf(fristReturn_Finally.CompareResultString);
+                        }
+                        break;
+                }
+            }
+        }
+    }
+}

+ 120 - 0
wispro.sp.winClient/frmCaseFileCompare.resx

@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!--
+    Microsoft ResX Schema 
+
+    Version 2.0
+
+    The primary goals of this format is to allow a simple XML format
+    that is mostly human readable. The generation and parsing of the
+    various data types are done through the TypeConverter classes
+    associated with the data types.
+
+    Example:
+
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+
+    There are any number of "resheader" rows that contain simple
+    name/value pairs.
+
+    Each data row contains a name, and value. The row also contains a
+    type or mimetype. Type corresponds to a .NET class that support
+    text/value conversion through the TypeConverter architecture.
+    Classes that don't support this are serialized and stored with the
+    mimetype set.
+
+    The mimetype is used for serialized objects, and tells the
+    ResXResourceReader how to depersist the object. This is currently not
+    extensible. For a given mimetype the value must be set accordingly:
+
+    Note - application/x-microsoft.net.object.binary.base64 is the format
+    that the ResXResourceWriter will generate, however the reader can
+    read any of the formats listed below.
+
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+</root>