服务器之家

服务器之家 > 正文

详解二维码生成工厂

时间:2021-12-15 13:06     来源/作者:神牛步行3

本次主要分享的是3个免费的二维码接口的对接代码和测试得出的注意点及区别,有更好处理方式多多交流,相互促进进步;最近在学习JavsScript的扩展TypeScript,感觉语法糖很甜,大部分与C#更为类似,可能都是微软项目的原因吧,有兴趣的朋友可以多多相互交流下;

以上是个人的看法,下面来正式分享今天的文章吧:

  • Google的Api二维码生成接口
  • 2d-code的Api二维码生成接口
  • topscan的Api二维码生成接口
  • 使用面向对象+加载程序集创建对象合并以上接口封装成二维码生成工厂

下面一步一个脚印的来分享:

Google的Api二维码生成接口

首先,这里给出Google接口文档的链接qr_codes文档,热情的朋友马上就会打开此链接吧,详细看下里面的参数这就不做截图了,大致通常用到的参数是:api地址,内容参数,生成图片的高宽这3个参数,其他的几个参数都采用默认的吧,不同需要大家可以更详细的看下;其实第一次看到文档里面的参数,感觉少了一些东西,比如怎么不能传递二维码中间那个图标的图片地址和扫描二维码过后怎么跳转到我想重定向的url链接呢,带着这个疑问我进行了多次的尝试;下面给出自己尝试的结果说明:

  •  接口关键参数是:cht(固定值qr),chl(内容参数),chs(生成出来二维码图片尺寸,格式如:200x200,这里是xyz的x不是*)
  • api接口只会生成一个二维码的图片流,如果需要把图片保存到本地需要通过浏览器直接get访问接口或者通过程序下载这个二维码
  • 内容参数如果传递文本信息,在生成出来的二维码图片中间不会显示文本内容,只有用手机扫描二维码才能在手机上显示传递的文本信息
  • 内容参数如果传递单纯的http://格式的链接地址,那么手机扫描后会自动重定向到改http://链接地址上(这个扫描重定向可以用来做一些商品或者文章的查看)
  • google接口暂未研究出此Logo图标地址参数(希望有朋友研究出来后与我分享,谢谢)
  • 由于api地址是国外的,调用接口响应不是那么快速

其次,上面是个人的一些总结,下面我们来看下封装的请求接口方法和下载二维码图片方法:

#region 生成二维码

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/// <summary>
/// 生成二维码
/// </summary>
/// <param name="content">展示内容(文本内容 或者 扫描后的跳转http://格式的地址)</param>
/// <param name="savePath">保存二维码的磁盘路径(默认程序跟目录+QRCode)</param>
/// <param name="logoUrl"> Logo图标地址(格式:http://),(注:google接口暂未研究出此参数)</param>
/// <param name="apiUrl">接口地址(内置默认api地址)</param>
/// <param name="wAndh">宽度和高度(二维码正方形的,高宽一至,默认200)</param>
/// <returns></returns>
public virtual string CreateQRCode(string content = null, string savePath = null, string logoUrl = null, string apiUrl = null, int? wAndh = null)
{
var qrName = string.Empty;
#region 参数初始化
ApiUrl = apiUrl ?? ApiUrl;
Content = content ?? Content;
SaveQRPath = savePath ?? SaveQRPath;
LogoUrl = logoUrl ?? LogoUrl;
WAndH = wAndh ?? WAndH;
#endregion
if (string.IsNullOrEmpty(ApiUrl)) { return qrName; }
ApiUrl = string.Format("{0}?cht=qr&chl={1}&chs={2}x{2}",
ApiUrl,
HttpUtility.UrlEncode(Content),
WAndH);
qrName = DownImg(ApiUrl, SaveQRPath, ImageFormat.Jpeg);
return qrName;
}
#endregion

下载二维码图片保存到程序根目录:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#region 下载图片
 /// <summary>
 /// 下载图片
 /// </summary>
 /// <param name="url">图片下载地址</param>
 /// <param name="savePath">保存路径默认:Img文件夹</param>
 /// <param name="format">默认:Jpeg</param>
 /// <returns>新图片名称</returns>
 public virtual string DownImg(string url, string savePath = "QRCode", ImageFormat format = null)
 {
 var qrName = string.Empty;
 try
 {
 format = format ?? ImageFormat.Jpeg;
 HttpClient http = new HttpClient();
 http.Timeout = new TimeSpan(0, 1, 0);
 using (var stream = http.GetStreamAsync(url).Result)
 {
 if (!Directory.Exists(SaveQRPath)) { Directory.CreateDirectory(SaveQRPath); }
 qrName = DateTime.Now.ToString("yyyyMMddHHmmssfff") + "." + format;
 var path = Path.Combine(savePath, qrName);
 using (Image img = Image.FromStream(stream))
 {
 img.Save(path, format);
 }
 }
 }
 catch (Exception ex)
 {
 qrName = string.Empty;
 }
 return qrName;
 }
#endregion

上面两个方法使用的是虚方法,因为我这里是吧google接口当做默认的二维码生成器来使用,后面要讲的另外两个接口都是重写与此;下载图片的方法都是公用的,暂不需要重写;这里需要提到的是调用api接口时有一个固定的参数cht=qr,这个参数表示采用QR方法生成二维码,因为这个api接口还有生成图标的功能,所以只想要生成二维码这里就固定,更多的生成图标功能不在本章分享中,谢谢。

2d-code的Api二维码生成接口

首先,该接口需要通过他们官网注册一个key,然后从后台获取到这个key后才能调用接口地址,当然注册后有个功能是,凡是您通过api接口生成的二维码,除了自己通过流下载,还能通过他们后台一起下载所有生成的图片,本人暂时没有去关注是否生成量大了会收费哈哈,下面列举下接口参数说明和测试得出的注意点:

  • 接口关键参数是:key(注册获取),text(文本参数),url(扫描后重定向地址),logo(Logo图标地址),size(二维码正方形,高宽)
  • 接口的文本参数只能传递文本,不能当做扫描后重定向的地址参数使用和Google等接口有点不一样
  • 扫描后重定向地址和Logo图标地址都是可访问的http://格式的地址链接
  • Logo图标地址,官方说不建议使用png格式,测试只有jpg成功(可能是测试不够多这里只单纯介绍我的结果)
  • 生成速度比较快,而且还有一个艺术字的生成接口,挺不错
  • api接口只会生成一个二维码的图片流,如果需要把图片保存到本地需要通过浏览器直接get访问接口或者通过程序下载这个二维码

其次,下面给出封装的代码,由于下载和上面介绍的代码一样是公用的这里就不做陈述:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public QR_2dCode()
 {
 ApiUrl = "http://www.2d-code.cn/2dcode/api.php";
 }
 #region 生成二维码
 /// <summary>
 /// 生成二维码
 /// </summary>
 /// <param name="content">展示内容(文本内容 或者 扫描后的跳转http://格式的地址)</param>
 /// <param name="savePath">保存二维码的磁盘路径(默认程序跟目录+QRCode)</param>
 /// <param name="logoUrl"> Logo图标地址(格式:http://),官方不建议使用png格式,测试只有jpg成功</param>
 /// <param name="directUrl">扫描后重定向地址(http://)</param>
 /// <param name="apiUrl">接口地址(内置默认api地址)</param>
 /// <param name="wAndh">宽度和高度(二维码正方形的,高宽一至,默认200)</param>
 /// <returns></returns>
 public override string CreateQRCode(string content = null, string savePath = null, string logoUrl = null, string apiUrl = null, int? wAndh = null)
 {
 var qrName = string.Empty;
 #region 参数初始化
 ApiUrl = apiUrl ?? ApiUrl;
 Content = content ?? Content;
 SaveQRPath = savePath ?? SaveQRPath;
 LogoUrl = logoUrl ?? LogoUrl;
 WAndH = wAndh ?? WAndH;
 #endregion
 if (string.IsNullOrEmpty(ApiUrl)) { return qrName; }
 ApiUrl = string.Format("{0}?key=c_d800OBbu6hDzJtXPE2Yd02IMtmpuK9VdCqHe6vrtar4&text={1}&url={2}&logo={3}&size={4}",
 ApiUrl,
 HttpUtility.UrlEncode(Content.Contains("http") ? "" : Content),
 HttpUtility.UrlEncode(Content),
 HttpUtility.UrlEncode(LogoUrl),
 WAndH);
 qrName = DownImg(ApiUrl, SaveQRPath);
 return qrName;
 }
#endregion

topscan的Api二维码生成接口

首先,该接口肯定是免费的,参数描述和google的差不多,不同处在于可以传递Logo图标地址(当然可能我还没发现google的可以传递logo的参数,故此朋友们可以忽略);下面列举下接口参数说明和测试得出的注意点:

  • 接口关键参数是:text(内容参数),logo(Logo图标地址),w(生成出来二维码图片尺寸,格式如:200x200,这里是xyz的x不是*)
  • api接口只会生成一个二维码的图片流,如果需要把图片保存到本地需要通过浏览器直接get访问接口或者通过程序下载这个二维码
  • 内容参数如果传递文本信息,在生成出来的二维码图片中间不会显示文本内容,只有用手机扫描二维码才能在手机上显示传递的文本信息
  • 内容参数如果传递单纯的http://格式的链接地址,那么手机扫描后会自动重定向到改http://链接地址上(这个扫描重定向可以用来做一些商品或者文章的查看)
  • Logo图标地址(格式:http://),jpg,png测试通过
  • 测试得出有时候请求生成二维码不返回数据,有可能是我网路问题吧,正常生成二维码的速度还是挺快

其次,下面给出封装的代码,由于下载和上面介绍的代码一样是公用的这里就不做陈述:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public QR_TopScan()
 {
 ApiUrl = "http://qr.topscan.com/api.php";
 }
 #region 生成二维码
 /// <summary>
 /// 生成二维码
 /// </summary>
 /// <param name="content">展示内容(文本内容 或者 扫描后的跳转http://格式的地址)</param>
 /// <param name="savePath">保存二维码的磁盘路径(默认程序跟目录+QRCode)</param>
 /// <param name="logoUrl"> Logo图标地址(格式:http://),jpg,png测试通过,测试得出有不能成功的,原因不知是否和地址有关</param>
 /// <param name="apiUrl">接口地址(内置默认api地址)</param>
 /// <param name="wAndh">宽度和高度(二维码正方形的,高宽一至,默认200)</param>
 /// <returns></returns>
 public override string CreateQRCode(string content = null, string savePath = null, string logoUrl = null, string apiUrl = null, int? wAndh = null)
 {
 var qrName = string.Empty;
 #region 参数初始化
 ApiUrl = apiUrl ?? ApiUrl;
 Content = content ?? Content;
 SaveQRPath = savePath ?? SaveQRPath;
 LogoUrl = logoUrl ?? LogoUrl;
 WAndH = wAndh ?? WAndH;
 #endregion
 if (string.IsNullOrEmpty(ApiUrl)) { return qrName; }
 ApiUrl = string.Format("{0}?text={1}&logo={2}&w={3}",
 ApiUrl,
 HttpUtility.UrlEncode(Content),
 HttpUtility.UrlEncode(LogoUrl),
 WAndH);
 qrName = DownImg(ApiUrl, SaveQRPath);
 return qrName;
 }
#endregion

使用面向对象+加载程序集创建对象合并以上接口封装成二维码生成工厂

首先,分析上面3个接口的参数可以看出,都需要固定的参数:接口api,内容(文本或跳转http地址),Logo图片地址(google暂时除外),宽度和高度等这几个参数,这样一来咋们可以定义个统一参数类,来传递该参数信息,这里还要提下由于这几个接口都是从别人接口获取图片流,如果想要吧图片在执行程序时候直接保存在我们的程序本地,都需要下载,所以又多一个参数: 保存二维码的磁盘路径,所以才有了一下公共的属性:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#region 基础配置信息
 /// <summary>
 /// 接口地址(必填)
 /// </summary>
 protected string ApiUrl = "https://chart.googleapis.com/chart";
 /// <summary>
 /// 展示内容(文本内容),google文本参数直接传递http地址直接重定向
 /// </summary>
 protected string Content = "http://www.cnblogs.com/wangrudong003/";
 /// <summary>
 /// 保存二维码的磁盘路径(默认程序跟目录+QRCode)
 /// </summary>
 protected string SaveQRPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "QRCode");
 /// <summary>
 /// Logo图片地址(http://)
 /// </summary>
 protected string LogoUrl = "http://a.hiphotos.baidu.com/baike/w%3D268%3Bg%3D0/sign=9a34e44d8bd4b31cf03c93bdbfed4042/2cf5e0fe9925bc318cb9fe965edf8db1ca1370dc.jpg";
 /// <summary>
 /// 宽度和高度(二维码正方形的,高宽一至,默认200)
 /// </summary>
 protected int WAndH = 200;
#endregion

然后,这里我不想每个接口都手动new一次来创建对象,所以用了加载程序集的模块的方式来创建所需要的对象,因此有了工厂类的入口:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
/// <summary>
 /// 二维码生成工厂
 /// </summary>
 public class QRCodeReposity
 {
 public static BaseQRCode Current(QREmType qrEmType = QREmType.BaseQRCode)
 {
 var nspace = typeof(BaseQRCode);
 var fullName = nspace.FullName;
 var nowspace = fullName.Substring(0, fullName.LastIndexOf('.') + 1);
 return Assembly.GetExecutingAssembly().CreateInstance(nowspace + qrEmType.ToString(), true) as BaseQRCode;
 }
 }

这里和之前的缓存工厂文章设计差不多,可以查阅下之前的分享篇,也多多点赞,谢谢;下面在给出说有的代码如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
/// <summary>
 /// 工厂模块定义
 /// </summary>
 public enum QREmType
 {
 /// <summary>
 /// google接口
 /// </summary>
 BaseQRCode,
 /// <summary>
 /// 2d-code接口
 /// </summary>
 QR_2dCode,
 /// <summary>
 /// topscan接口
 /// </summary>
 QR_TopScan
 }
 /// <summary>
 /// 二维码生成工厂
 /// </summary>
 public class QRCodeReposity
 {
 public static BaseQRCode Current(QREmType qrEmType = QREmType.BaseQRCode)
 {
 var nspace = typeof(BaseQRCode);
 var fullName = nspace.FullName;
 var nowspace = fullName.Substring(0, fullName.LastIndexOf('.') + 1);
 return Assembly.GetExecutingAssembly().CreateInstance(nowspace + qrEmType.ToString(), true) as BaseQRCode;
 }
 }
 /// <summary>
 /// 基类使用Google提供Api:https://developers.google.com/chart/infographics/docs/qr_codes ,由于是国外地址,相对来说有点慢
 /// </summary>
 public class BaseQRCode
 {
 #region 基础配置信息
 /// <summary>
 /// 接口地址(必填)
 /// </summary>
 protected string ApiUrl = "https://chart.googleapis.com/chart";
 /// <summary>
 /// 展示内容(文本内容),google文本参数直接传递http地址直接重定向
 /// </summary>
 protected string Content = "http://www.cnblogs.com/wangrudong003/";
 /// <summary>
 /// 保存二维码的磁盘路径(默认程序跟目录+QRCode)
 /// </summary>
 protected string SaveQRPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "QRCode");
 /// <summary>
 /// Logo图片地址(http://)
 /// </summary>
 protected string LogoUrl = "http://a.hiphotos.baidu.com/baike/w%3D268%3Bg%3D0/sign=9a34e44d8bd4b31cf03c93bdbfed4042/2cf5e0fe9925bc318cb9fe965edf8db1ca1370dc.jpg";
 /// <summary>
 /// 宽度和高度(二维码正方形的,高宽一至,默认200)
 /// </summary>
 protected int WAndH = 200;
 #endregion
 #region 方法
 #region 生成二维码
 /// <summary>
 /// 生成二维码
 /// </summary>
 /// <param name="content">展示内容(文本内容 或者 扫描后的跳转http://格式的地址)</param>
 /// <param name="savePath">保存二维码的磁盘路径(默认程序跟目录+QRCode)</param>
 /// <param name="logoUrl"> Logo图标地址(格式:http://),(注:google接口暂未研究出此参数)</param>
 /// <param name="apiUrl">接口地址(内置默认api地址)</param>
 /// <param name="wAndh">宽度和高度(二维码正方形的,高宽一至,默认200)</param>
 /// <returns></returns>
 public virtual string CreateQRCode(string content = null, string savePath = null, string logoUrl = null, string apiUrl = null, int? wAndh = null)
 {
 var qrName = string.Empty;
 #region 参数初始化
 ApiUrl = apiUrl ?? ApiUrl;
 Content = content ?? Content;
 SaveQRPath = savePath ?? SaveQRPath;
 LogoUrl = logoUrl ?? LogoUrl;
 WAndH = wAndh ?? WAndH;
 #endregion
 if (string.IsNullOrEmpty(ApiUrl)) { return qrName; }
 ApiUrl = string.Format("{0}?cht=qr&chl={1}&chs={2}x{2}",
 ApiUrl,
 HttpUtility.UrlEncode(Content),
 WAndH);
 qrName = DownImg(ApiUrl, SaveQRPath, ImageFormat.Jpeg);
 return qrName;
 }
 #endregion
 #region 下载图片
 /// <summary>
 /// 下载图片
 /// </summary>
 /// <param name="url">图片下载地址</param>
 /// <param name="savePath">保存路径默认:Img文件夹</param>
 /// <param name="format">默认:Jpeg</param>
 /// <returns>新图片名称</returns>
 public virtual string DownImg(string url, string savePath = "QRCode", ImageFormat format = null)
 {
 var qrName = string.Empty;
 try
 {
 format = format ?? ImageFormat.Jpeg;
 HttpClient http = new HttpClient();
 http.Timeout = new TimeSpan(0, 1, 0);
 using (var stream = http.GetStreamAsync(url).Result)
 {
 if (!Directory.Exists(SaveQRPath)) { Directory.CreateDirectory(SaveQRPath); }
 qrName = DateTime.Now.ToString("yyyyMMddHHmmssfff") + "." + format;
 var path = Path.Combine(savePath, qrName);
 using (Image img = Image.FromStream(stream))
 {
 img.Save(path, format);
 }
 }
 }
 catch (Exception ex)
 {
 qrName = string.Empty;
 }
 return qrName;
 }
 #endregion
 #endregion
 }
 /// <summary>
 /// 使用2d-code提供Api,需要去官网注册获取Key
 /// </summary>
 public class QR_2dCode : BaseQRCode
 {
 public QR_2dCode()
 {
 ApiUrl = "http://www.2d-code.cn/2dcode/api.php";
 }
 #region 生成二维码
 /// <summary>
 /// 生成二维码
 /// </summary>
 /// <param name="content">展示内容(文本内容 或者 扫描后的跳转http://格式的地址)</param>
 /// <param name="savePath">保存二维码的磁盘路径(默认程序跟目录+QRCode)</param>
 /// <param name="logoUrl"> Logo图标地址(格式:http://),官方不建议使用png格式,测试只有jpg成功</param>
 /// <param name="directUrl">扫描后重定向地址(http://)</param>
 /// <param name="apiUrl">接口地址(内置默认api地址)</param>
 /// <param name="wAndh">宽度和高度(二维码正方形的,高宽一至,默认200)</param>
 /// <returns></returns>
 public override string CreateQRCode(string content = null, string savePath = null, string logoUrl = null, string apiUrl = null, int? wAndh = null)
 {
 var qrName = string.Empty;
 #region 参数初始化
 ApiUrl = apiUrl ?? ApiUrl;
 Content = content ?? Content;
 SaveQRPath = savePath ?? SaveQRPath;
 LogoUrl = logoUrl ?? LogoUrl;
 WAndH = wAndh ?? WAndH;
 #endregion
 if (string.IsNullOrEmpty(ApiUrl)) { return qrName; }
 ApiUrl = string.Format("{0}?key=c_d800OBbu6hDzJtXPE2Yd02IMtmpuK9VdCqHe6vrtar4&text={1}&url={2}&logo={3}&size={4}",
 ApiUrl,
 HttpUtility.UrlEncode(Content.Contains("http") ? "" : Content),
 HttpUtility.UrlEncode(Content),
 HttpUtility.UrlEncode(LogoUrl),
 WAndH);
 qrName = DownImg(ApiUrl, SaveQRPath);
 return qrName;
 }
 #endregion
 }
 /// <summary>
 /// 使用topscan提供Api
 /// </summary>
 public class QR_TopScan : BaseQRCode
 {
 public QR_TopScan()
 {
 ApiUrl = "http://qr.topscan.com/api.php";
 }
 #region 生成二维码
 /// <summary>
 /// 生成二维码
 /// </summary>
 /// <param name="content">展示内容(文本内容 或者 扫描后的跳转http://格式的地址)</param>
 /// <param name="savePath">保存二维码的磁盘路径(默认程序跟目录+QRCode)</param>
 /// <param name="logoUrl"> Logo图标地址(格式:http://),jpg,png测试通过,测试得出有不能成功的,原因不知是否和地址有关</param>
 /// <param name="apiUrl">接口地址(内置默认api地址)</param>
 /// <param name="wAndh">宽度和高度(二维码正方形的,高宽一至,默认200)</param>
 /// <returns></returns>
 public override string CreateQRCode(string content = null, string savePath = null, string logoUrl = null, string apiUrl = null, int? wAndh = null)
 {
 var qrName = string.Empty;
 #region 参数初始化
 ApiUrl = apiUrl ?? ApiUrl;
 Content = content ?? Content;
 SaveQRPath = savePath ?? SaveQRPath;
 LogoUrl = logoUrl ?? LogoUrl;
 WAndH = wAndh ?? WAndH;
 #endregion
 if (string.IsNullOrEmpty(ApiUrl)) { return qrName; }
 ApiUrl = string.Format("{0}?text={1}&logo={2}&w={3}",
 ApiUrl,
 HttpUtility.UrlEncode(Content),
 HttpUtility.UrlEncode(LogoUrl),
 WAndH);
 qrName = DownImg(ApiUrl, SaveQRPath);
 return qrName;
 }
 #endregion
 }

本篇的分享内容在程序设计方面没有太多,重点是分装下这几个接口和分享下接口的差异,方面朋友们可以拿来主义和正在对接二维码生成的朋友做下交流,仅此而已;关键代码的备注都在分享代码里,有更好或者不清楚的地方欢迎留言,谢谢。

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持服务器之家!

原文链接:http://www.cnblogs.com/wangrudong003/p/5854094.html

相关文章

热门资讯

yue是什么意思 网络流行语yue了是什么梗
yue是什么意思 网络流行语yue了是什么梗 2020-10-11
背刺什么意思 网络词语背刺是什么梗
背刺什么意思 网络词语背刺是什么梗 2020-05-22
2020微信伤感网名听哭了 让对方看到心疼的伤感网名大全
2020微信伤感网名听哭了 让对方看到心疼的伤感网名大全 2019-12-26
2021年耽改剧名单 2021要播出的59部耽改剧列表
2021年耽改剧名单 2021要播出的59部耽改剧列表 2021-03-05
苹果12mini价格表官网报价 iPhone12mini全版本价格汇总
苹果12mini价格表官网报价 iPhone12mini全版本价格汇总 2020-11-13
返回顶部