分享懶人張RDLC報表(五、六)


來自蠟人張:RDLC報表(五)

        隨着Visual Studio 2005中文版的推出,Microsoft漢化了MSDN的大部分內容,開發者再也不用啃英文了,本來想介紹一下LocalReport的Render方法,現在您可以到http://msdn2.microsoft.com/zh-cn/library/ms252207(VS.80).aspx獲 得關於這部分的詳細信息。之所以以前想介紹這個方法,是因為我將想大家介紹一種在Crystal Report中無法實現的自定義票據打印紙張的方法。Anyway,現在我直接向大家介紹這種方法,可能這種方法並不是很好的,但是確實是我經過一段時間 的摸索總結出來的。蘿卜(http://luobos.cnblogs.com)曾經提到過的變通的方法不知道是不是我要介紹的這一種,歡迎和我進行交流!

        要想使用RDLC報表並進行頁面設置,我們先來看一下LocalReport是否有類似PageSettings的類、屬性、方法或事件等,我仔細找了一 下,發現Microsoft.Reporting.WinForms.ReportPageSettings類具有PaperSize屬性和Margin 屬性,但可惜的是它們都是只讀的,對我們來說沒有意義;另外,LocalReport具有GetDefaultPageSettings()方法,這也只 能是獲取當前報表的頁面設置。沒辦法,只能采用變通的方法了。在.NET中如果想使用自定義紙張,最好的方法莫過於使用 System.Drawing.Printing.PrintDocument類了,還記得我在前面提到的一個GotReportViewer的例子嗎?

View Code
 1         private int m_currentPageIndex;
 2         private IList<Stream> m_streams;
 3 
 4         private Stream CreateStream(string name, string fileNameExtension, Encoding encoding, string mimeType, bool willSeek)
 5         {
 6             Stream stream = new FileStream(name + "." + fileNameExtension, FileMode.Create);
 7             m_streams.Add(stream);
 8             return stream;
 9         }
10 
11         private void Export(LocalReport report)
12         {
13             string deviceInfo =
14               "<DeviceInfo>" +
15               "  <OutputFormat>EMF</OutputFormat>" +
16               "  <PageWidth>8.5in</PageWidth>" +
17               "  <PageHeight>11in</PageHeight>" +
18               "  <MarginTop>0.25in</MarginTop>" +
19               "  <MarginLeft>0.25in</MarginLeft>" +
20               "  <MarginRight>0.25in</MarginRight>" +
21               "  <MarginBottom>0.25in</MarginBottom>" +
22               "</DeviceInfo>";
23             Warning[] warnings;
24             m_streams = new List<Stream>();
25             report.Render("Image", deviceInfo, CreateStream, out warnings);
26 
27             foreach (Stream stream in m_streams)
28                 stream.Position = 0;
29         }
30 
31         private void PrintPage(object sender, PrintPageEventArgs ev)
32         {
33             Metafile pageImage = new Metafile(m_streams[m_currentPageIndex]);
34             ev.Graphics.DrawImage(pageImage, ev.PageBounds);
35 
36             m_currentPageIndex++;
37             ev.HasMorePages = (m_currentPageIndex < m_streams.Count);
38         }
39 
40         private void Print()
41         {
42             const string printerName = "Microsoft Office Document Image Writer";
43 
44             if (m_streams == null || m_streams.Count == 0)
45                 return;
46 
47             PrintDocument printDoc = new PrintDocument();
48             printDoc.PrinterSettings.PrinterName = printerName;
49             if (!printDoc.PrinterSettings.IsValid)
50             {
51                 string msg = String.Format("Can't find printer \"{0}\".", printerName);
52                 Console.WriteLine(msg);
53                 return;
54             }
55             printDoc.PrintPage += new PrintPageEventHandler(PrintPage);
56             printDoc.Print();
57         }
58 
59         private void Run()
60         {
61             LocalReport report = new LocalReport();
62             report.ReportPath = "Report.rdlc";
63             report.DataSources.Add(new ReportDataSource("Sales", LoadSalesData()));
64 
65             Export(report);
66 
67             m_currentPageIndex = 0;
68             Print();
69         }

      對,就是那個通過命令行而不是ReportViewer的GUI界面進行打印報表的例子,這個例子就使用LocalReport的Render方法將報表 的內容導出為EMF圖像流,然后在PrintDocument的PrintPage事件中使用時事件參數 System.Drawing.Printing.PrintEventArgs類的DrawImage方法將EMF圖像流輸出到打印機。我在上面說的變 通的方法也要使用這種方法。具體的細節將在以后的隨筆中陸續給出。

        既然我們使用這種方法進行報表的打印,那么Visual Studio的控件ReportViewer的工具欄就不再符合我們的要求了。因為這個報表瀏覽器的工具欄上的按鈕雖然可以設置屬性顯示或隱藏其中的一部 分,但是我們卻不能自己往這個工具欄上添加按鈕(顯然,我們需要實現自己的頁面設置、預覽和打印按鈕),在這一點上,建議Microsoft將工具欄和報 表瀏覽器分離,應該做得和BindingNavigator那樣就好了。
        我們先設置ReportViewer控件的ShowToolBar方法為false,然后在ReportViewer控件紙上添加除頁面設置、預覽、打印外的應該有的按鈕,像刷新、終止、導出、縮放、搜索、導航等,這些按鈕的Click事件定義如下:

View Code
  1         /// <summary>
  2         /// 獲取當前時間組成的字符串,用作生成不會重復的文件名
  3         /// </summary>
  4         /// <returns></returns>
  5         private string GetTimeStamp()
  6         {
  7             string strRet = string.Empty;
  8             System.DateTime dtNow = Pub.DateTimeEx.ServerTime;
  9             strRet += dtNow.Year.ToString() +
 10                         dtNow.Month.ToString("00") +
 11                         dtNow.Day.ToString("00") +
 12                         dtNow.Hour.ToString("00") +
 13                         dtNow.Minute.ToString("00") +
 14                         dtNow.Second.ToString("00") +
 15                         System.DateTime.Now.Millisecond.ToString("000");
 16             return strRet;
 17 
 18         }
 19 
 20         /// <summary>
 21         /// 導出到Excel
 22         /// </summary>
 23         /// <param name="sender"></param>
 24         /// <param name="e"></param>
 25         private void toolExcel_Click(object sender, EventArgs e)
 26         {
 27 
 28             Microsoft.Reporting.WinForms.Warning[] Warnings;
 29             string[] strStreamIds;
 30             string strMimeType;
 31             string strEncoding;
 32             string strFileNameExtension;
 33 
 34             byte[] bytes = this.reportViewer1.LocalReport.Render("Excel", null, out strMimeType, out strEncoding, out strFileNameExtension, out strStreamIds, out Warnings);
 35 
 36             string strFilePath = @"D:\" + this.GetTimeStamp() + ".xls";
 37 
 38             using (System.IO.FileStream fs = new FileStream(strFilePath, FileMode.Create))
 39             {
 40                 fs.Write(bytes, 0, bytes.Length);
 41             }
 42 
 43             if (Pub.WinForm.Msg.Question("報表打印: \r\n    成功導出Excel文件!" + strFilePath + "\r\n    要現在打開文件" + strFilePath + "嗎?") == DialogResult.Yes)
 44             {
 45                 System.Diagnostics.Process.Start(strFilePath);
 46             }
 47 
 48         }
 49 
 50         /// <summary>
 51         /// 刷新報表數據
 52         /// </summary>
 53         /// <param name="sender"></param>
 54         /// <param name="e"></param>
 55         private void tool刷新_Click(object sender, EventArgs e)
 56         {
 57             this.reportViewer1.RefreshReport();
 58         }
 59 
 60         /// <summary>
 61         /// 在加載報表數據時終止報表數據的加載
 62         /// </summary>
 63         /// <param name="sender"></param>
 64         /// <param name="e"></param>
 65         private void tool終止_Click(object sender, EventArgs e)
 66         {
 67             this.reportViewer1.CancelRendering(0);
 68         }
 69 
 70         /// <summary>
 71         /// 從DrillThrough報表返回到導航頁面
 72         /// </summary>
 73         /// <param name="sender"></param>
 74         /// <param name="e"></param>
 75         private void tool返回_Click(object sender, EventArgs e)
 76         {
 77             if (this.reportViewer1.LocalReport.IsDrillthroughReport)
 78                 this.reportViewer1.PerformBack();
 79         }
 80 
 81         /// <summary>
 82         /// 回到報表的第一頁
 83         /// </summary>
 84         /// <param name="sender"></param>
 85         /// <param name="e"></param>
 86         private void tool第一頁_Click(object sender, EventArgs e)
 87         {
 88             this.reportViewer1.CurrentPage = 1;
 89         }
 90 
 91         /// <summary>
 92         /// 跳轉到報表的最后一頁
 93         /// </summary>
 94         /// <param name="sender"></param>
 95         /// <param name="e"></param>
 96         private void tool最后一頁_Click(object sender, EventArgs e)
 97         {
 98             this.reportViewer1.CurrentPage = this.reportViewer1.LocalReport.GetTotalPages();
 99         }
100 
101         /// <summary>
102         /// 以25%的比例顯示報表
103         /// </summary>
104         /// <param name="sender"></param>
105         /// <param name="e"></param>
106         private void tool25_Click(object sender, EventArgs e)
107         {
108             this.reportViewer1.ZoomMode = ZoomMode.Percent;
109             this.reportViewer1.ZoomPercent = 25;
110         }
111 
112         /// <summary>
113         /// 以50%的比例顯示報表
114         /// </summary>
115         /// <param name="sender"></param>
116         /// <param name="e"></param>
117         private void tool50_Click(object sender, EventArgs e)
118         {
119             this.reportViewer1.ZoomMode = ZoomMode.Percent;
120             this.reportViewer1.ZoomPercent = 50;
121         }
122 
123         /// <summary>
124         /// 以100%的比例顯示報表
125         /// </summary>
126         /// <param name="sender"></param>
127         /// <param name="e"></param>
128         private void tool100_Click(object sender, EventArgs e)
129         {
130             this.reportViewer1.ZoomMode = ZoomMode.Percent;
131             this.reportViewer1.ZoomPercent = 100;
132         }
133 
134         /// <summary>
135         /// 以200%的比例顯示報表
136         /// </summary>
137         /// <param name="sender"></param>
138         /// <param name="e"></param>
139         private void tool200_Click(object sender, EventArgs e)
140         {
141             this.reportViewer1.ZoomMode = ZoomMode.Percent;
142             this.reportViewer1.ZoomPercent = 200;
143         }
144 
145         /// <summary>
146         /// 以400%的比例顯示報表
147         /// </summary>
148         /// <param name="sender"></param>
149         /// <param name="e"></param>
150         private void tool400_Click(object sender, EventArgs e)
151         {
152             this.reportViewer1.ZoomMode = ZoomMode.Percent;
153             this.reportViewer1.ZoomPercent = 400;
154         }
155 
156         /// <summary>
157         /// 將縮放模式設置為整頁
158         /// </summary>
159         /// <param name="sender"></param>
160         /// <param name="e"></param>
161         private void tool整頁_Click(object sender, EventArgs e)
162         {
163             this.reportViewer1.ZoomMode = ZoomMode.FullPage;
164         }
165 
166         /// <summary>
167         /// 將縮放模式設置為頁寬
168         /// </summary>
169         /// <param name="sender"></param>
170         /// <param name="e"></param>
171         private void tool頁寬_Click(object sender, EventArgs e)
172         {
173             this.reportViewer1.ZoomMode = ZoomMode.PageWidth;
174         }
175 
176         /// <summary>
177         /// 在報表中搜索txtSearch中的字符
178         /// </summary>
179         /// <param name="sender"></param>
180         /// <param name="e"></param>
181         private void tool搜索_Click(object sender, EventArgs e)
182         {
183             if (this.txtSearch.Text.Trim() == string.Empty)
184                 return;
185 
186             this.reportViewer1.Find(this.txtSearch.Text.Trim(), 1);
187         }
188 
189         /// <summary>
190         /// 搜索報表中下一處txtSearch中的字符
191         /// </summary>
192         /// <param name="sender"></param>
193         /// <param name="e"></param>
194         private void tool搜索下一個_Click(object sender, EventArgs e)
195         {
196             if (this.txtSearch.Text.Trim() == string.Empty)
197                 return;
198 
199             this.reportViewer1.FindNext();
200         }
201 
202         /// <summary>
203         /// 跳轉到上一頁
204         /// </summary>
205         /// <param name="sender"></param>
206         /// <param name="e"></param>
207         private void tool上一頁_Click(object sender, EventArgs e)
208         {
209             if (this.reportViewer1.CurrentPage != 1)
210                 this.reportViewer1.CurrentPage--;
211         }
212 
213         /// <summary>
214         /// 跳轉到下一頁
215         /// </summary>
216         /// <param name="sender"></param>
217         /// <param name="e"></param>
218         private void tool下一頁_Click(object sender, EventArgs e)
219         {
220             if (this.reportViewer1.CurrentPage != this.reportViewer1.LocalReport.GetTotalPages())
221                 this.reportViewer1.CurrentPage++;
222         }
223 
224         /// <summary>
225         /// 跳轉到由txt跳轉中指定的頁數
226         /// </summary>
227         /// <param name="sender"></param>
228         /// <param name="e"></param>
229         private void tool跳轉_Click(object sender, EventArgs e)
230         {
231             if (this.txt跳轉.Text.Trim() == string.Empty)
232                 return;
233 
234             int intJump = 0;
235 
236             if (System.Int32.TryParse(this.txt跳轉.Text.Trim(), out intJump))
237                 if (intJump <= this.reportViewer1.LocalReport.GetTotalPages())
238                     this.reportViewer1.CurrentPage = intJump;
239 
240         }

來自蠟人張:RDLC報表(六)

        你可能已經注意到了在調用LocalReport的Render方法時用到了一個XML格式的DeviceInfo結構,在SQL Server 2005 Report Services中,DeviceInfo結構是為了給特定的呈現格式傳遞參數。來看一個簡單的DeviceInfo結構:

< DeviceInfo >  
    
< OutputFormat > EMF </ OutputFormat >  
    
< PageWidth > 21cm </ PageWidth >  
    
< PageHeight > 29.70cm </ PageHeight >  
    
< MarginTop > 2cm </ MarginTop >  
    
< MarginLeft > 2cm </ MarginLeft >  
    
< MarginRight > 2cm </ MarginRight >  
    
< MarginBottom > 2cm </ MarginBottom >  
</ DeviceInfo >

        這個簡單的DeviceInfo結構至少為LocalReport的Render方法指定了輸出格式、頁寬、頁高、左邊距、右邊距、下邊距信息,在我們使 用PrintPage的方法將LocalReport呈現為EMF圖片時,EMF圖片在頁面上顯示的大小、邊距就是由這個DeviceInfo結構來決定 的,如果為DeviceInfo結構和PrintDocumnt設置不匹配的頁面大小或邊距,那么在PrintPage事件中使用DrawImage方法 畫出的圖片將出現放大或縮小的情況,這是我們不願意看到的結果。也就是說,在使用自定義紙張進行單據打印時,我們不僅要為PrintDocument設置 頁面大小和邊距,還要為LocalReport設置與PrintDocument相同的頁面大小和邊距。關於DeviceInfo的結構,可以參考http://msdn2.microsoft.com/zh-cn/library/ms155373.aspx

        下面是我封裝的一個為生成DeviceInfo結構使用的類:

View Code
  1 using System;
  2 using System.Collections.Generic;
  3 using System.Text;
  4 
  5 namespace RDLCReport
  6 {
  7     public class EMFDeviceInfo
  8     {
  9         private bool m_Landscape = false;
 10 
 11         public bool Landscape
 12         {
 13             get
 14             {
 15                 return this.m_Landscape;
 16             }
 17             set
 18             {
 19                 this.m_Landscape = value;
 20             }
 21         }
 22 
 23         /*
 24          * The pixel depth of the color range supported by the image output. 
 25          * Valid values are 1, 4, 8, 24, and 32. 
 26          * The default value is 24. 
 27          * ColorDepth is only supported for TIFF rendering and is otherwise ignored by the report server for other image output formats. 
 28          * Note: 
 29          * For this release of SQL Server, the value of this setting is ignored, and the TIFF image is always rendered as 24-bit.
 30          * 
 31          * 默認值為24,且只有當輸出格式為TIFF時才該項設置才起作用
 32          * 
 33         */
 34         private int m_ColorDepth = 24;
 35 
 36         public int ColorDepth
 37         {
 38             get
 39             {
 40                 return this.m_ColorDepth;
 41             }
 42         }
 43 
 44 
 45         /*
 46          * The number of columns to set for the report. This value overrides the report's original settings.
 47          * 
 48          * 未用到此項設置
 49          * 
 50         */
 51         private int m_Columns = 0;
 52 
 53         public int Columns
 54         {
 55             get
 56             {
 57                 return this.m_Columns;
 58             }
 59             set
 60             {
 61                 this.m_Columns = value;
 62             }
 63         }
 64 
 65 
 66         /*
 67          * The column spacing to set for the report. This value overrides the report's original settings.
 68          * 
 69          * 未用到此項設置
 70          * 
 71         */
 72         private int m_ColumnSpacing = 0;
 73 
 74         public int ColumnSpacing
 75         {
 76             get
 77             {
 78                 return this.m_ColumnSpacing;
 79             }
 80             set
 81             {
 82                 this.m_ColumnSpacing = value;
 83             }
 84         }
 85 
 86         /*
 87          * The resolution of the output device in x-direction. The default value is 96.
 88          * 
 89          * 解析度,默認值為96
 90          * 
 91         */
 92         private int m_DpiX = 96;
 93 
 94         public int DpiX
 95         {
 96             get
 97             {
 98                 return this.m_DpiX;
 99             }
100             set
101             {
102                 this.m_DpiX = value;
103             }
104         }
105 
106 
107         /*
108          * The resolution of the output device in y-direction. The default value is 96.
109          * 
110          * 解析度,默認值為96
111          * 
112         */
113         private int m_DpiY = 96;
114 
115         public int DpiY
116         {
117             get
118             {
119                 return this.m_DpiY;
120             }
121             set
122             {
123                 this.m_DpiY = value;
124             }
125         }
126 
127 
128         /*
129          * The last page of the report to render. The default value is the value for StartPage.
130          * 
131          * 要輸出的報表的最后一頁
132          * 
133          */
134         private int m_EndPage = 0;
135 
136         public int EndPage
137         {
138             get
139             {
140                 return this.m_EndPage;
141             }
142             set
143             {
144                 this.m_EndPage = value;
145             }
146         }
147 
148 
149         /*
150          * The first page of the report to render. A value of 0 indicates that all pages are rendered. The default value is 1.
151          * 
152          * 起始頁,0代表所有頁面都將輸出,默認值為1。
153          * 
154          */
155         private int m_StartPage = 1;
156 
157         public int StartPage
158         {
159             get
160             {
161                 return this.m_StartPage;
162             }
163             set
164             {
165                 this.m_StartPage = value;
166             }
167         }
168 
169         /*
170          * The bottom margin value, in inches, to set for the report. You must include an integer or decimal value followed by "in" (for example, 1in). This value overrides the report's original settings.
171          * 
172          * 底部邊距,必須加上單位如"in"
173          * 
174          */
175         private decimal m_MarginBottom = 0;
176 
177         public decimal MarginBottom
178         {
179             get
180             {
181                 return this.m_MarginBottom;
182             }
183             set
184             {
185                 this.m_MarginBottom = value;
186             }
187         }
188 
189 
190         /*
191          * The top margin value, in inches, to set for the report. You must include an integer or decimal value followed by "in" (for example, 1in). This value overrides the report's original settings.
192          * 
193          * 頂部邊距,必須加上單位如"in"
194          * 
195          */
196         private decimal m_MarginTop = 0;
197 
198         public decimal MarginTop
199         {
200             get
201             {
202                 return this.m_MarginTop;
203             }
204             set
205             {
206                 this.m_MarginTop = value;
207             }
208         }
209 
210 
211         /*
212          * The left margin value, in inches, to set for the report. You must include an integer or decimal value followed by "in" (for example, 1in). This value overrides the report's original settings.
213          * 
214          * 左邊距,必須加上單位如"in"
215          * 
216          */
217         private decimal m_MarginLeft = 0;
218 
219         public decimal MarginLeft
220         {
221             get
222             {
223                 return this.m_MarginLeft;
224             }
225             set
226             {
227                 this.m_MarginLeft = value;
228             }
229         }
230 
231 
232         /*
233          * The right margin value, in inches, to set for the report. You must include an integer or decimal value followed by "in" (for example, 1in). This value overrides the report's original settings.
234          * 
235          * 右邊距,必須加上單位如"in"
236          * 
237          */
238         private decimal m_MarginRight = 0;
239 
240         public decimal MarginRight
241         {
242             get
243             {
244                 return this.m_MarginRight;
245             }
246             set
247             {
248                 this.m_MarginRight = value;
249             }
250         }
251 
252         /*
253          * One of the Graphics Device Interface (GDI) supported output formats: BMP, EMF, GIF, JPEG, PNG, or TIFF.
254          * 
255          * 圖形設備接口(GDI)支持的一種輸出格式,可以是BMP, EMF, GIF, JPEG, PNG, 或 TIFF.
256          * 此處使用EMF
257          */
258         private string m_OutputFormat = "EMF";
259 
260         public string OutputFormat
261         {
262             get
263             {
264                 return this.m_OutputFormat;
265             }
266             set
267             {
268                 this.m_OutputFormat = value;
269             }
270         }
271 
272         /*
273          * The page height, in inches, to set for the report. You must include an integer or decimal value followed by "in" (for example, 11in). This value overrides the report's original settings.
274          * 
275          * 頁面高度,必須加上單位如"in"
276          * 
277          */
278         private decimal m_PageHeight = 0;
279 
280         public decimal PageHeight
281         {
282             get
283             {
284                 return this.m_PageHeight;
285             }
286             set
287             {
288                 this.m_PageHeight = value;
289             }
290         }
291 
292 
293         /*
294          * The page width, in inches, to set for the report. You must include an integer or decimal value followed by "in" (for example, 8.5in). This value overrides the report's original settings.
295          * 
296          * 頁面寬度,必須加上單位如"in"
297          * 
298         */
299         private decimal m_PageWidth = 0;
300 
301         public decimal PageWidth
302         {
303             get
304             {
305                 return this.m_PageWidth;
306             }
307             set
308             {
309                 this.m_PageWidth = value;
310             }
311         }
312 
313         /// <summary>
314         /// 返回包含DeviceInfo的字符串
315         /// </summary>
316         public string DeviceInfoString
317         {
318             get
319             {
320                 string strRet = string.Empty;
321 
322                 strRet += "<DeviceInfo>" +
323                     "  <OutputFormat>" + this.m_OutputFormat + "</OutputFormat>";
324 
325                 if (this.m_Landscape)
326                     strRet +=
327                         "  <PageWidth>" + this.m_PageHeight.ToString() + "cm</PageWidth>" +
328                         "  <PageHeight>" + this.m_PageWidth.ToString() + "cm</PageHeight>";
329                 else
330                     strRet +=
331                         "  <PageWidth>" + this.m_PageWidth.ToString() + "cm</PageWidth>" +
332                         "  <PageHeight>" + this.m_PageHeight.ToString() + "cm</PageHeight>";
333 
334                 strRet +=
335                         "  <MarginTop>" + this.m_MarginTop.ToString() + "cm</MarginTop>" +
336                         "  <MarginLeft>" + this.m_MarginLeft.ToString() + "cm</MarginLeft>" +
337                         "  <MarginRight>" + this.m_MarginRight.ToString() + "cm</MarginRight>" +
338                         "  <MarginBottom>" + this.m_MarginBottom.ToString() + "cm</MarginBottom>";
339 
340                 strRet += "</DeviceInfo>";
341 
342                 return strRet;
343 
344             }
345 
346         }   
347     }
348 }

        好了,解決了DeviceInfo,現在來看一下如何在PrintDocument的PrintPage事件中向打印機輸出由LocalReport呈現 的EMF圖片。使用的方法基本上就是在GotReportViewer的例程Print a report from a console app中使用的方法,但是需要指出的一點是例程中使用事件參數System.Drawing.Printing.PrintPageEventArgs類 的Graphics屬性的DrawImage方法向打印機輸出EMF圖片,在實際的應用中,發現DrawImage方法繪出的圖片會出現放大或縮小的情 況,即使為DrawImage方法指定了看起來正確的參數 ev.Graphics.DrawImageUnscaledAndClipped(this.m_PageImage, ev.PageBounds);,我使用的方法是DrawImageUnscaledAndClipped,在為DeviceInfo結構和 PrintDocument指定好適當且匹配的頁面設置時,輸出的結果是比較好的。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM