架构师_程序员_码农网

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

搜索
查看: 39740|回复: 1

[资料] aspose.words 操作word生成试卷

[复制链接]
发表于 2016-4-8 16:44:24 | 显示全部楼层 |阅读模式

最近做了一个在线组卷的项目。主要功能实现word排版、预览,生成试卷。刚开始涉及到word操作一心想到的就是 office COM组件 来操作word 。大概两周时间就写好整个系统的代码。然后就开始反复测试,本地感觉良好,能够顺利生成一份word试卷,并且性能还行。于是迫不及待的发布到了服务器。

下面说说发布遇到的一些情况,首先一个就是遇到索 COM 类工厂中 CLSID 为 {000209FF-0000-0000-C000-000000000046} 的组件失败,原因是出现以下错误: 8000401a 因为配置标识不正确,系统无法开始服务器进程。请检查用户名和密码。 (异常来自 HRESULT:0x8000401A)。

首先这中问题全都是权限所导致,解决的办法只要配置权限就可以了。不光对excel和word有用,对所有的office产品都有效果。

进入正题,首先,在运行中输入dcomcnfg打开组件服务管理器->组件服务->我的电脑->DCOM->找到对应的Microsoft excel applicotion/Microsoft word 97-2003文档,然后右键属性激活启动权限都给足够了就ok了。 --------没问题这个问题解决了。



下面再说说第二个情况》性能问题:由于我们该系统是我们网站下一个子系统。所以有一定的用户基础。该系统一上线就有大量的用户访问。刚开始一天组卷四五百份,慢慢的组卷量越来越大,这是系统就开始出问题了。首先一个就是在进程里面出现了很多 winWord.exe进程。不能结束掉。虽然系统代码里面Quit进程,并且对资源也进行了回收,但是问题始终得不到解决。大量winword.exe进程的后果就是服务器变慢了。应为该组件办本身就特别耗内存。

没办法问题要解决呀。最后的无赖之举就是KIll 写了一个定时服务,定时Kill掉没有运行的winword进程。这样做治标不治本的。、



这里要说一下微软Office是主要针对普通用户开发的桌面办公应用软件,它具有丰富的UI(用户界面)元素,是一套纯粹的本地运行软件或者说是客户端软件。Word自动化接口主要是为了方便窗口应用程序调用而设计的。例如Delphi、VB、C# Winform等开发的本地应用程序。虽然可以强制Visible为false,Word可以运行在服务器端代码里,但毕竟还是会带来许多棘手问题。

1. ASP.NET是基于B/S架构的。B/S架构下用户访问都是并发的,也就是说经常会出现同时N个用户对一个服务器页面发出请求。在这种情况下Word自动化调用会时常出现死进程。

2. 由于隐藏界面运行,一些涉及界面的可以在窗口程序里成功调用的接口,在服务器端调用就会失败,甚至崩溃,这种情况也会经常导致死进程。

3. 由于Word是复杂的桌面程序,并不符合一般Web服务程序简洁高效的标准,所以在服务器端运行时速度慢,并且还会消耗大量资源(CPU、内存),尤其不能支持大量用户同时访问,资源会很快耗尽。

4. 绝大部分开发者对COM技术比较陌生,在编程调用Word接口时经常存在一些代码错误,而又很难检查到问题所在,这又是导致死进程的经常因素。Word死进程不仅会消耗服务器资源,还经常会导致服务器页面不能创建新的Word自动化对象而无法继续工作。有网友提出死进程解决方法:编程Kill掉Word死进程,这样是治标不治本的做法,Word死进程是不在了,可是Word非正常关闭会导致很多资源无法及时释放。这样的Web服务器能持续工作多久恐怕就很难说了。



为了解决这些问题,笔者经过全面研究比较,发现网上有一款组件件aspose.words,完全消除了以上问题,推荐给大家分享。



下面我把aspose.words组件的一些操作代码分享给大家希望对需要的人有所帮助


  1. private DocumentBuilder oWordApplic; //   a   reference   to   Word   application
  2.         private Aspose.Words.Document oDoc; //   a   reference   to   the   document
  3.         public void OpenWithTemplate(string strFileName)
  4.         {
  5.             if (!string.IsNullOrEmpty(strFileName))
  6.             {
  7.                 oDoc = new Aspose.Words.Document(strFileName);
  8.             }
  9.         }

  10.         public void Open()
  11.         {
  12.             oDoc = new Aspose.Words.Document();
  13.         }

  14.         public void Builder()
  15.         {
  16.             oWordApplic = new DocumentBuilder(oDoc);
  17.             
  18.             
  19.         }
  20.         /// <summary>
  21.         /// 保存文件
  22.         /// </summary>
  23.         /// <param name="strFileName"></param>
  24.         public void SaveAs(string strFileName)
  25.         {

  26.             if (this.Docversion == 2007)
  27.             {
  28.                 oDoc.Save(strFileName,SaveFormat.Docx);
  29.             }else
  30.             {
  31.                 oDoc.Save(strFileName,SaveFormat.Doc);
  32.             }
  33.            
  34.         }

  35.         /// <summary>
  36.         /// 添加内容
  37.         /// </summary>
  38.         /// <param name="strText"></param>
  39.         public void InsertText(string strText, double conSize, bool conBold, string conAlign)
  40.         {
  41.             oWordApplic.Bold = conBold;
  42.             oWordApplic.Font.Size = conSize;
  43.             switch (conAlign)
  44.             {
  45.                 case "left":
  46.                     oWordApplic.ParagraphFormat.Alignment = ParagraphAlignment.Left;
  47.                     break;
  48.                 case "center":
  49.                     oWordApplic.ParagraphFormat.Alignment = ParagraphAlignment.Center;
  50.                     break;
  51.                 case "right":
  52.                     oWordApplic.ParagraphFormat.Alignment = ParagraphAlignment.Right;
  53.                     break;
  54.                 default:
  55.                     oWordApplic.ParagraphFormat.Alignment = ParagraphAlignment.Left;
  56.                     break;
  57.             }
  58.             oWordApplic.Writeln(strText);
  59.             
  60.         }

  61.         /// <summary>
  62.         /// 添加内容
  63.         /// </summary>
  64.         /// <param name="strText"></param>
  65.         public void WriteText(string strText, double conSize, bool conBold, string conAlign)
  66.         {
  67.             oWordApplic.Bold = conBold;
  68.             oWordApplic.Font.Size = conSize;
  69.             switch (conAlign)
  70.             {
  71.                 case "left":
  72.                     oWordApplic.ParagraphFormat.Alignment = ParagraphAlignment.Left;
  73.                     break;
  74.                 case "center":
  75.                     oWordApplic.ParagraphFormat.Alignment = ParagraphAlignment.Center;
  76.                     break;
  77.                 case "right":
  78.                     oWordApplic.ParagraphFormat.Alignment = ParagraphAlignment.Right;
  79.                     break;
  80.                 default:
  81.                     oWordApplic.ParagraphFormat.Alignment = ParagraphAlignment.Left;
  82.                     break;
  83.             }
  84.             oWordApplic.Write(strText);

  85.         }


  86.         #region 设置纸张
  87.         public void setPaperSize(string papersize)
  88.         {

  89.             switch (papersize)
  90.             {
  91.                 case "A4":
  92.                     foreach (Aspose.Words.Section section in oDoc)
  93.                     {
  94.                         section.PageSetup.PaperSize = PaperSize.A4;
  95.                         section.PageSetup.Orientation = Orientation.Portrait;
  96.                         section.PageSetup.VerticalAlignment = Aspose.Words.PageVerticalAlignment.Top;
  97.                     }
  98.                     break;
  99.                 case "A4H"://A4横向
  100.                     foreach (Aspose.Words.Section section in oDoc)
  101.                     {
  102.                         section.PageSetup.PaperSize = PaperSize.A4;
  103.                         section.PageSetup.Orientation = Orientation.Landscape;
  104.                         section.PageSetup.TextColumns.SetCount(2);
  105.                         section.PageSetup.TextColumns.EvenlySpaced = true;
  106.                         section.PageSetup.TextColumns.LineBetween =true;
  107.                         //section.PageSetup.LeftMargin = double.Parse("3.35");
  108.                         //section.PageSetup.RightMargin =double.Parse("0.99");
  109.                     }
  110.                     break;
  111.                 case "A3":
  112.                     foreach (Aspose.Words.Section section in oDoc)
  113.                     {
  114.                         section.PageSetup.PaperSize = PaperSize.A3;
  115.                         section.PageSetup.Orientation = Orientation.Portrait;
  116.                        
  117.                     }
  118.                   
  119.                     break;
  120.                 case "A3H"://A3横向

  121.                     foreach (Aspose.Words.Section section in oDoc)
  122.                     {
  123.                         section.PageSetup.PaperSize = PaperSize.A3;
  124.                         section.PageSetup.Orientation = Orientation.Landscape;
  125.                         section.PageSetup.TextColumns.SetCount(2);
  126.                         section.PageSetup.TextColumns.EvenlySpaced = true;
  127.                         section.PageSetup.TextColumns.LineBetween = true;

  128.                     }

  129.                     break;

  130.                 case "16K":

  131.                     foreach (Aspose.Words.Section section in oDoc)
  132.                     {
  133.                         section.PageSetup.PaperSize = PaperSize.B5;
  134.                         section.PageSetup.Orientation = Orientation.Portrait;

  135.                     }
  136.                   
  137.                     break;

  138.                 case "8KH":

  139.                     foreach (Aspose.Words.Section section in oDoc)
  140.                     {

  141.                         section.PageSetup.PageWidth = double.Parse("36.4 ");//纸张宽度
  142.                         section.PageSetup.PageHeight = double.Parse("25.7");//纸张高度
  143.                         section.PageSetup.Orientation = Orientation.Landscape;
  144.                         section.PageSetup.TextColumns.SetCount(2);
  145.                         section.PageSetup.TextColumns.EvenlySpaced = true;
  146.                         section.PageSetup.TextColumns.LineBetween = true;
  147.                         //section.PageSetup.LeftMargin = double.Parse("3.35");
  148.                         //section.PageSetup.RightMargin = double.Parse("0.99");
  149.                     }

  150.                  

  151.                     break;
  152.             }
  153.         }
  154.         #endregion

  155.         public void SetHeade(string strBookmarkName, string text)
  156.         {
  157.             if (oDoc.Range.Bookmarks[strBookmarkName] != null)
  158.             {
  159.                 Aspose.Words.Bookmark mark = oDoc.Range.Bookmarks[strBookmarkName];
  160.                 mark.Text = text;
  161.             }
  162.         }
  163.         public void InsertFile(string vfilename)
  164.         {
  165.             Aspose.Words.Document srcDoc = new Aspose.Words.Document(vfilename);
  166.                       Node insertAfterNode = oWordApplic.CurrentParagraph.PreviousSibling;
  167.                       InsertDocument(insertAfterNode, oDoc, srcDoc);
  168.            
  169.         }

  170.         public void InsertFile(string vfilename, string strBookmarkName,int pNum)
  171.         {
  172.             //Aspose.Words.Document srcDoc = new Aspose.Words.Document(vfilename);
  173.             //Aspose.Words.Bookmark bookmark = oDoc.Range.Bookmarks[strBookmarkName];
  174.             //InsertDocument(bookmark.BookmarkStart.ParentNode, srcDoc);
  175.             //替换插入word内容
  176.             oWordApplic.Document.Range.Replace(new System.Text.RegularExpressions.Regex(strBookmarkName),
  177.                 new InsertDocumentAtReplaceHandler(vfilename, pNum), false);
  178.            

  179.         }
  180.         /// <summary>
  181.         /// 插入word内容
  182.         /// </summary>
  183.         /// <param name="insertAfterNode"></param>
  184.         /// <param name="mainDoc"></param>
  185.         /// <param name="srcDoc"></param>
  186.         public static void InsertDocument(Node insertAfterNode, Aspose.Words.Document mainDoc, Aspose.Words.Document srcDoc)
  187.         {
  188.             // Make sure that the node is either a pargraph or table.
  189.             if ((insertAfterNode.NodeType != NodeType.Paragraph)
  190.                 & (insertAfterNode.NodeType != NodeType.Table))
  191.                 throw new Exception("The destination node should be either a paragraph or table.");

  192.             //We will be inserting into the parent of the destination paragraph.

  193.             CompositeNode dstStory = insertAfterNode.ParentNode;

  194.             //Remove empty paragraphs from the end of document

  195.             while (null != srcDoc.LastSection.Body.LastParagraph && !srcDoc.LastSection.Body.LastParagraph.HasChildNodes)
  196.             {
  197.                 srcDoc.LastSection.Body.LastParagraph.Remove();
  198.             }
  199.             NodeImporter importer = new NodeImporter(srcDoc, mainDoc, ImportFormatMode.KeepSourceFormatting);

  200.             //Loop through all sections in the source document.

  201.             int sectCount = srcDoc.Sections.Count;

  202.             for (int sectIndex = 0; sectIndex < sectCount; sectIndex++)
  203.             {
  204.                 Aspose.Words.Section srcSection = srcDoc.Sections[sectIndex];
  205.                 //Loop through all block level nodes (paragraphs and tables) in the body of the section.
  206.                 int nodeCount = srcSection.Body.ChildNodes.Count;
  207.                 for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++)
  208.                 {
  209.                     Node srcNode = srcSection.Body.ChildNodes[nodeIndex];
  210.                     Node newNode = importer.ImportNode(srcNode, true);
  211.                     dstStory.InsertAfter(newNode, insertAfterNode);
  212.                     insertAfterNode = newNode;
  213.                 }
  214.             }


  215.         }

  216.         static void InsertDocument(Node insertAfterNode, Aspose.Words.Document srcDoc)
  217.         {
  218.             // Make sure that the node is either a paragraph or table.
  219.             if ((!insertAfterNode.NodeType.Equals(NodeType.Paragraph)) &
  220.               (!insertAfterNode.NodeType.Equals(NodeType.Table)))
  221.                 throw new ArgumentException("The destination node should be either a paragraph or table.");

  222.             // We will be inserting into the parent of the destination paragraph.
  223.             CompositeNode dstStory = insertAfterNode.ParentNode;

  224.             // This object will be translating styles and lists during the import.
  225.             NodeImporter importer = new NodeImporter(srcDoc, insertAfterNode.Document, ImportFormatMode.KeepSourceFormatting);

  226.             // Loop through all sections in the source document.
  227.             foreach (Aspose.Words.Section srcSection in srcDoc.Sections)
  228.             {
  229.                 // Loop through all block level nodes (paragraphs and tables) in the body of the section.
  230.                 foreach (Node srcNode in srcSection.Body)
  231.                 {
  232.                     // Let's skip the node if it is a last empty paragraph in a section.
  233.                     if (srcNode.NodeType.Equals(NodeType.Paragraph))
  234.                     {
  235.                         Aspose.Words.Paragraph para = (Aspose.Words.Paragraph)srcNode;
  236.                         if (para.IsEndOfSection && !para.HasChildNodes)
  237.                             continue;
  238.                     }

  239.                     // This creates a clone of the node, suitable for insertion into the destination document.
  240.                     Node newNode = importer.ImportNode(srcNode, true);

  241.                     // Insert new node after the reference node.
  242.                     dstStory.InsertAfter(newNode, insertAfterNode);
  243.                     insertAfterNode = newNode;
  244.                 }
  245.             }
  246.         }
  247.         /// <summary>
  248.         /// 换行
  249.         /// </summary>
  250.         public void InsertLineBreak()
  251.         {
  252.             oWordApplic.InsertBreak(BreakType.LineBreak);
  253.         }
  254.         /// <summary>
  255.         /// 换多行
  256.         /// </summary>
  257.         /// <param name="nline"></param>
  258.         public void InsertLineBreak(int nline)
  259.         {
  260.             for (int i = 0; i < nline; i++)
  261.                 oWordApplic.InsertBreak(BreakType.LineBreak);
  262.         }

  263.         #region InsertScoreTable
  264.         public bool InsertScoreTable(bool dishand, bool distab, string handText)
  265.         {
  266.             try
  267.             {

  268.             
  269.                 oWordApplic.StartTable();//开始画Table
  270.                 oWordApplic.ParagraphFormat.Alignment = ParagraphAlignment.Left;
  271.                 //添加Word表格
  272.                 oWordApplic.InsertCell();
  273.                 oWordApplic.CellFormat.Width = 115.0;
  274.                 oWordApplic.CellFormat.PreferredWidth = Aspose.Words.Tables.PreferredWidth.FromPoints(115);
  275.                 oWordApplic.CellFormat.Borders.LineStyle = LineStyle.None;
  276.                
  277.                 oWordApplic.StartTable();//开始画Table
  278.                 oWordApplic.RowFormat.Height = 20.2;
  279.                 oWordApplic.InsertCell();
  280.                 oWordApplic.CellFormat.Borders.LineStyle = LineStyle.Single;
  281.                 oWordApplic.Font.Size = 10.5;
  282.                 oWordApplic.Bold = false;
  283.                 oWordApplic.Write("评卷人");

  284.                 oWordApplic.CellFormat.VerticalAlignment = Aspose.Words.Tables.CellVerticalAlignment.Center;//垂直居中对齐
  285.                 oWordApplic.ParagraphFormat.Alignment = ParagraphAlignment.Center;
  286.                 oWordApplic.CellFormat.Width = 50.0;
  287.                 oWordApplic.CellFormat.PreferredWidth = Aspose.Words.Tables.PreferredWidth.FromPoints(50);
  288.                 oWordApplic.RowFormat.Height = 20.0;
  289.                 oWordApplic.InsertCell();
  290.                 oWordApplic.CellFormat.Borders.LineStyle = LineStyle.Single;
  291.                 oWordApplic.Font.Size = 10.5;
  292.                 oWordApplic.Bold = false;
  293.                 oWordApplic.Write("得分");
  294.                 oWordApplic.CellFormat.VerticalAlignment = Aspose.Words.Tables.CellVerticalAlignment.Center;//垂直居中对齐
  295.                 oWordApplic.ParagraphFormat.Alignment = ParagraphAlignment.Center;
  296.                 oWordApplic.CellFormat.Width = 50.0;
  297.                 oWordApplic.CellFormat.PreferredWidth = Aspose.Words.Tables.PreferredWidth.FromPoints(50);
  298.                 oWordApplic.EndRow();
  299.                 oWordApplic.RowFormat.Height = 25.0;
  300.                 oWordApplic.InsertCell();
  301.                 oWordApplic.RowFormat.Height = 25.0;
  302.                 oWordApplic.InsertCell();
  303.                 oWordApplic.EndRow();
  304.                 oWordApplic.EndTable();

  305.                 oWordApplic.InsertCell();
  306.                 oWordApplic.CellFormat.Width = 300.0;
  307.                 oWordApplic.CellFormat.PreferredWidth = Aspose.Words.Tables.PreferredWidth.Auto;
  308.                 oWordApplic.CellFormat.Borders.LineStyle = LineStyle.None;

  309.                
  310.                 oWordApplic.CellFormat.VerticalAlignment = Aspose.Words.Tables.CellVerticalAlignment.Center;//垂直居中对齐
  311.                 oWordApplic.ParagraphFormat.Alignment = ParagraphAlignment.Left;
  312.                 oWordApplic.Font.Size = 11;
  313.                 oWordApplic.Bold = true;
  314.                 oWordApplic.Write(handText);
  315.                 oWordApplic.EndRow();
  316.                 oWordApplic.RowFormat.Height = 28;
  317.                 oWordApplic.EndTable();
  318.                 return true;
  319.             }
  320.             catch
  321.             {

  322.                 return false;
  323.             }

  324.         }
  325.         #endregion
  326.          #region 插入表格
  327.         public bool InsertTable(System.Data.DataTable dt, bool haveBorder)
  328.         {
  329.             Aspose.Words.Tables.Table  table= oWordApplic.StartTable();//开始画Table
  330.             ParagraphAlignment paragraphAlignmentValue = oWordApplic.ParagraphFormat.Alignment;
  331.             oWordApplic.ParagraphFormat.Alignment = ParagraphAlignment.Center;
  332.             //添加Word表格
  333.             for (int row = 0; row < dt.Rows.Count; row++)
  334.             {
  335.                  oWordApplic.RowFormat.Height =25;
  336.                 for (int col = 0; col < dt.Columns.Count; col++)
  337.                 {
  338.                     oWordApplic.InsertCell();
  339.                     oWordApplic.Font.Size = 10.5;
  340.                     oWordApplic.Font.Name = "宋体";
  341.                     oWordApplic.CellFormat.VerticalAlignment = Aspose.Words.Tables.CellVerticalAlignment.Center;//垂直居中对齐
  342.                     oWordApplic.ParagraphFormat.Alignment = ParagraphAlignment.Center;//水平居中对齐
  343.                     oWordApplic.CellFormat.Width = 50.0;
  344.                     oWordApplic.CellFormat.PreferredWidth = Aspose.Words.Tables.PreferredWidth.FromPoints(50);
  345.                     if (haveBorder == true)
  346.                     {
  347.                         //设置外框样式   
  348.                         oWordApplic.CellFormat.Borders.LineStyle = LineStyle.Single;
  349.                         //样式设置结束   
  350.                     }

  351.                     oWordApplic.Write(dt.Rows[row][col].ToString());
  352.                 }

  353.                 oWordApplic.EndRow();

  354.             }
  355.             oWordApplic.EndTable();
  356.             oWordApplic.ParagraphFormat.Alignment = paragraphAlignmentValue;
  357.             table.Alignment=Aspose.Words.Tables.TableAlignment.Center;
  358.             table.PreferredWidth = Aspose.Words.Tables.PreferredWidth.Auto;
  359.          


  360.             return true;
  361.         }
  362.         #endregion


  363.         public void InsertPagebreak( )
  364.         {
  365.             oWordApplic.InsertBreak(BreakType.PageBreak);
  366.             
  367.         }
  368.         public void InsertBookMark(string BookMark)
  369.         {
  370.             oWordApplic.StartBookmark(BookMark);
  371.             oWordApplic.EndBookmark(BookMark);

  372.         }
  373.         public void GotoBookMark(string strBookMarkName)
  374.         {
  375.             oWordApplic.MoveToBookmark(strBookMarkName);
  376.         }
  377.         public void ClearBookMark()
  378.         {
  379.             oDoc.Range.Bookmarks.Clear();
  380.         }

  381.         public void ReplaceText(string oleText, string newText)
  382.         {
  383.             //System.Text.RegularExpressions.Regex reg = new System.Text.RegularExpressions.Regex(oleText);
  384.             oDoc.Range.Replace(oleText, newText, false,false);

  385.         }
  386.         private class InsertDocumentAtReplaceHandler : IReplacingCallback
  387.         {
  388.             private string vfilename;
  389.             private int pNum;

  390.             public InsertDocumentAtReplaceHandler(string filename, int _pNum)
  391.             {
  392.                 this.vfilename = filename;
  393.                 this.pNum = _pNum;
  394.             }
  395.             ReplaceAction IReplacingCallback.Replacing(ReplacingArgs e)
  396.             {
  397.                 Document subDoc = new Document(this.vfilename);
  398.                 subDoc.FirstSection.Body.FirstParagraph.InsertAfter(new Run(subDoc, this.pNum + "."), null);
  399.                
  400.                 // Insert a document after the paragraph, containing the match text.
  401.                 Node currentNode = e.MatchNode;
  402.                 Paragraph para = (Paragraph)e.MatchNode.ParentNode;
  403.                 InsertDocument(para, subDoc);
  404.                 // Remove the paragraph with the match text.
  405.                 e.MatchNode.Remove();
  406.                 e.MatchNode.Range.Delete();



  407.                 return ReplaceAction.Skip;
  408.             }
  409.         }
  410.     }
  411. }
复制代码



原文链接:http://blog.csdn.net/fraing/article/details/8989736




上一篇:【求助】求会建站的,会html的来帮我修改下单页源码。。求帮
下一篇:Aspose.Words操作word生成PDF文档
码农网,只发表在实践过程中,遇到的技术难题,不误导他人。
发表于 2020-5-3 09:07:08 | 显示全部楼层
很好的贴子,有帮助
码农网,只发表在实践过程中,遇到的技术难题,不误导他人。
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

免责声明:
码农网所发布的一切软件、编程资料或者文章仅限用于学习和研究目的;不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负。本站信息来自网络,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑中彻底删除上述内容。如果您喜欢该程序,请支持正版软件,购买注册,得到更好的正版服务。如有侵权请邮件与我们联系处理。

Mail To:help@itsvse.com

QQ|小黑屋|架构师 ( 鲁ICP备14021824号-2 )|网站地图

GMT+8, 2026-4-12 22:10

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表