Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
justauth
JustAuth
提交
74ee17b2
J
JustAuth
项目概览
justauth
/
JustAuth
1 年多 前同步成功
通知
391
Star
15212
Fork
2708
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
J
JustAuth
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
74ee17b2
编写于
8月 10, 2021
作者:
智布道
👁
提交者:
Gitee
8月 10, 2021
浏览文件
操作
浏览文件
下载
差异文件
!27 获取三方实例 部分 进行重构,使之可以进行更简单的获取对应的实例。
Merge pull request !27 from 陈宁/master
上级
af8fda70
b77de0bd
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
146 addition
and
47 deletion
+146
-47
src/main/java/me/zhyd/oauth/config/AuthDefaultSource.java
src/main/java/me/zhyd/oauth/config/AuthDefaultSource.java
+91
-43
src/main/java/me/zhyd/oauth/request/AuthAlipayRequest.java
src/main/java/me/zhyd/oauth/request/AuthAlipayRequest.java
+12
-3
src/test/java/me/zhyd/oauth/config/AuthExtendSource.java
src/test/java/me/zhyd/oauth/config/AuthExtendSource.java
+30
-1
src/test/java/me/zhyd/oauth/request/AuthWeChatMpRequestTest.java
...t/java/me/zhyd/oauth/request/AuthWeChatMpRequestTest.java
+13
-0
未找到文件。
src/main/java/me/zhyd/oauth/config/AuthDefaultSource.java
浏览文件 @
74ee17b2
package
me.zhyd.oauth.config
;
import
me.zhyd.oauth.cache.AuthStateCache
;
import
me.zhyd.oauth.enums.AuthResponseStatus
;
import
me.zhyd.oauth.exception.AuthException
;
import
me.zhyd.oauth.request.*
;
import
java.util.Arrays
;
/**
* JustAuth内置的各api需要的url, 用枚举类分平台类型管理
...
...
@@ -13,7 +17,7 @@ public enum AuthDefaultSource implements AuthSource {
/**
* Github
*/
GITHUB
{
GITHUB
(
AuthGithubRequest
.
class
)
{
@Override
public
String
authorize
()
{
return
"https://github.com/login/oauth/authorize"
;
...
...
@@ -32,7 +36,7 @@ public enum AuthDefaultSource implements AuthSource {
/**
* 新浪微博
*/
WEIBO
{
WEIBO
(
AuthWeiboRequest
.
class
)
{
@Override
public
String
authorize
()
{
return
"https://api.weibo.com/oauth2/authorize"
;
...
...
@@ -56,7 +60,7 @@ public enum AuthDefaultSource implements AuthSource {
/**
* gitee
*/
GITEE
{
GITEE
(
AuthGiteeRequest
.
class
)
{
@Override
public
String
authorize
()
{
return
"https://gitee.com/oauth/authorize"
;
...
...
@@ -75,7 +79,7 @@ public enum AuthDefaultSource implements AuthSource {
/**
* 钉钉扫码登录
*/
DINGTALK
{
DINGTALK
(
AuthDingTalkRequest
.
class
)
{
@Override
public
String
authorize
()
{
return
"https://oapi.dingtalk.com/connect/qrconnect"
;
...
...
@@ -94,7 +98,7 @@ public enum AuthDefaultSource implements AuthSource {
/**
* 钉钉账号登录
*/
DINGTALK_ACCOUNT
{
DINGTALK_ACCOUNT
(
AuthDingTalkAccountRequest
.
class
)
{
@Override
public
String
authorize
()
{
return
"https://oapi.dingtalk.com/connect/oauth2/sns_authorize"
;
...
...
@@ -113,7 +117,7 @@ public enum AuthDefaultSource implements AuthSource {
/**
* 百度
*/
BAIDU
{
BAIDU
(
AuthBaiduRequest
.
class
)
{
@Override
public
String
authorize
()
{
return
"https://openapi.baidu.com/oauth/2.0/authorize"
;
...
...
@@ -142,7 +146,7 @@ public enum AuthDefaultSource implements AuthSource {
/**
* csdn
*/
CSDN
{
CSDN
(
AuthCsdnRequest
.
class
)
{
@Override
public
String
authorize
()
{
return
"https://api.csdn.net/oauth2/authorize"
;
...
...
@@ -164,7 +168,7 @@ public enum AuthDefaultSource implements AuthSource {
* 参考 https://help.coding.net/docs/project/open/oauth.html#%E7%94%A8%E6%88%B7%E6%8E%88%E6%9D%83 中的说明,
* 新版的 coding API 地址需要传入用户团队名,这儿使用动态参数,方便在 request 中使用
*/
CODING
{
CODING
(
AuthCodingRequest
.
class
)
{
@Override
public
String
authorize
()
{
return
"https://%s.coding.net/oauth_authorize.html"
;
...
...
@@ -183,7 +187,7 @@ public enum AuthDefaultSource implements AuthSource {
/**
* oschina 开源中国
*/
OSCHINA
{
OSCHINA
(
AuthOschinaRequest
.
class
)
{
@Override
public
String
authorize
()
{
return
"https://www.oschina.net/action/oauth2/authorize"
;
...
...
@@ -202,7 +206,7 @@ public enum AuthDefaultSource implements AuthSource {
/**
* 支付宝
*/
ALIPAY
{
ALIPAY
(
AuthAlipayRequest
.
class
)
{
@Override
public
String
authorize
()
{
return
"https://openauth.alipay.com/oauth2/publicAppAuthorize.htm"
;
...
...
@@ -221,7 +225,7 @@ public enum AuthDefaultSource implements AuthSource {
/**
* QQ
*/
QQ
{
QQ
(
AuthQqRequest
.
class
)
{
@Override
public
String
authorize
()
{
return
"https://graph.qq.com/oauth2.0/authorize"
;
...
...
@@ -245,7 +249,7 @@ public enum AuthDefaultSource implements AuthSource {
/**
* 微信开放平台
*/
WECHAT_OPEN
{
WECHAT_OPEN
(
AuthWeChatOpenRequest
.
class
)
{
@Override
public
String
authorize
()
{
return
"https://open.weixin.qq.com/connect/qrconnect"
;
...
...
@@ -269,7 +273,7 @@ public enum AuthDefaultSource implements AuthSource {
/**
* 微信公众平台
*/
WECHAT_MP
{
WECHAT_MP
(
AuthWeChatMpRequest
.
class
)
{
@Override
public
String
authorize
()
{
return
"https://open.weixin.qq.com/connect/oauth2/authorize"
;
...
...
@@ -293,7 +297,7 @@ public enum AuthDefaultSource implements AuthSource {
/**
* 淘宝
*/
TAOBAO
{
TAOBAO
(
AuthTaobaoRequest
.
class
)
{
@Override
public
String
authorize
()
{
return
"https://oauth.taobao.com/authorize"
;
...
...
@@ -312,7 +316,7 @@ public enum AuthDefaultSource implements AuthSource {
/**
* Google
*/
GOOGLE
{
GOOGLE
(
AuthGoogleRequest
.
class
)
{
@Override
public
String
authorize
()
{
return
"https://accounts.google.com/o/oauth2/v2/auth"
;
...
...
@@ -331,7 +335,7 @@ public enum AuthDefaultSource implements AuthSource {
/**
* Facebook
*/
FACEBOOK
{
FACEBOOK
(
AuthFacebookRequest
.
class
)
{
@Override
public
String
authorize
()
{
return
"https://www.facebook.com/v10.0/dialog/oauth"
;
...
...
@@ -350,7 +354,7 @@ public enum AuthDefaultSource implements AuthSource {
/**
* 抖音
*/
DOUYIN
{
DOUYIN
(
AuthDouyinRequest
.
class
)
{
@Override
public
String
authorize
()
{
return
"https://open.douyin.com/platform/oauth/connect"
;
...
...
@@ -374,7 +378,7 @@ public enum AuthDefaultSource implements AuthSource {
/**
* 领英
*/
LINKEDIN
{
LINKEDIN
(
AuthLinkedinRequest
.
class
)
{
@Override
public
String
authorize
()
{
return
"https://www.linkedin.com/oauth/v2/authorization"
;
...
...
@@ -398,7 +402,7 @@ public enum AuthDefaultSource implements AuthSource {
/**
* 微软
*/
MICROSOFT
{
MICROSOFT
(
AuthMicrosoftRequest
.
class
)
{
@Override
public
String
authorize
()
{
return
"https://login.microsoftonline.com/common/oauth2/v2.0/authorize"
;
...
...
@@ -422,7 +426,7 @@ public enum AuthDefaultSource implements AuthSource {
/**
* 小米
*/
MI
{
MI
(
AuthMiRequest
.
class
)
{
@Override
public
String
authorize
()
{
return
"https://account.xiaomi.com/oauth2/authorize"
;
...
...
@@ -446,7 +450,7 @@ public enum AuthDefaultSource implements AuthSource {
/**
* 今日头条
*/
TOUTIAO
{
TOUTIAO
(
AuthToutiaoRequest
.
class
)
{
@Override
public
String
authorize
()
{
return
"https://open.snssdk.com/auth/authorize"
;
...
...
@@ -465,7 +469,7 @@ public enum AuthDefaultSource implements AuthSource {
/**
* Teambition
*/
TEAMBITION
{
TEAMBITION
(
AuthTeambitionRequest
.
class
)
{
@Override
public
String
authorize
()
{
return
"https://account.teambition.com/oauth2/authorize"
;
...
...
@@ -490,7 +494,7 @@ public enum AuthDefaultSource implements AuthSource {
/**
* 人人网
*/
RENREN
{
RENREN
(
AuthRenrenRequest
.
class
)
{
@Override
public
String
authorize
()
{
return
"https://graph.renren.com/oauth/authorize"
;
...
...
@@ -515,7 +519,7 @@ public enum AuthDefaultSource implements AuthSource {
/**
* Pinterest
*/
PINTEREST
{
PINTEREST
(
AuthPinterestRequest
.
class
)
{
@Override
public
String
authorize
()
{
return
"https://api.pinterest.com/oauth"
;
...
...
@@ -535,7 +539,7 @@ public enum AuthDefaultSource implements AuthSource {
/**
* Stack Overflow
*/
STACK_OVERFLOW
{
STACK_OVERFLOW
(
AuthStackOverflowRequest
.
class
)
{
@Override
public
String
authorize
()
{
return
"https://stackoverflow.com/oauth"
;
...
...
@@ -557,7 +561,7 @@ public enum AuthDefaultSource implements AuthSource {
*
* @since 1.10.0
*/
HUAWEI
{
HUAWEI
(
AuthHuaweiRequest
.
class
)
{
@Override
public
String
authorize
()
{
return
"https://oauth-login.cloud.huawei.com/oauth2/v2/authorize"
;
...
...
@@ -584,7 +588,7 @@ public enum AuthDefaultSource implements AuthSource {
*
* @since 1.10.0
*/
WECHAT_ENTERPRISE
{
WECHAT_ENTERPRISE
(
AuthWeChatEnterpriseQrcodeRequest
.
class
)
{
@Override
public
String
authorize
()
{
return
"https://open.work.weixin.qq.com/wwopen/sso/qrConnect"
;
...
...
@@ -604,7 +608,7 @@ public enum AuthDefaultSource implements AuthSource {
/**
* 企业微信网页登录
*/
WECHAT_ENTERPRISE_WEB
{
WECHAT_ENTERPRISE_WEB
(
AuthWeChatEnterpriseWebRequest
.
class
)
{
@Override
public
String
authorize
()
{
return
"https://open.weixin.qq.com/connect/oauth2/authorize"
;
...
...
@@ -626,7 +630,7 @@ public enum AuthDefaultSource implements AuthSource {
*
* @since 1.11.0
*/
KUJIALE
{
KUJIALE
(
AuthKujialeRequest
.
class
)
{
@Override
public
String
authorize
()
{
return
"https://oauth.kujiale.com/oauth2/show"
;
...
...
@@ -653,7 +657,7 @@ public enum AuthDefaultSource implements AuthSource {
*
* @since 1.11.0
*/
GITLAB
{
GITLAB
(
AuthGitlabRequest
.
class
)
{
@Override
public
String
authorize
()
{
return
"https://gitlab.com/oauth/authorize"
;
...
...
@@ -675,7 +679,7 @@ public enum AuthDefaultSource implements AuthSource {
*
* @since 1.12.0
*/
MEITUAN
{
MEITUAN
(
AuthMeituanRequest
.
class
)
{
@Override
public
String
authorize
()
{
return
"https://openapi.waimai.meituan.com/oauth/authorize"
;
...
...
@@ -704,7 +708,7 @@ public enum AuthDefaultSource implements AuthSource {
*
* @since 1.12.0
*/
ELEME
{
ELEME
(
AuthElemeRequest
.
class
)
{
@Override
public
String
authorize
()
{
return
"https://open-api.shop.ele.me/authorize"
;
...
...
@@ -731,7 +735,7 @@ public enum AuthDefaultSource implements AuthSource {
*
* @since 1.13.0
*/
TWITTER
{
TWITTER
(
AuthTwitterRequest
.
class
)
{
@Override
public
String
authorize
()
{
return
"https://api.twitter.com/oauth/authenticate"
;
...
...
@@ -755,7 +759,7 @@ public enum AuthDefaultSource implements AuthSource {
*
* @since 1.15.9
*/
FEISHU
{
FEISHU
(
AuthFeishuRequest
.
class
)
{
@Override
public
String
authorize
()
{
return
"https://open.feishu.cn/open-apis/authen/v1/index"
;
...
...
@@ -781,7 +785,7 @@ public enum AuthDefaultSource implements AuthSource {
*
* @since 1.15.0
*/
JD
{
JD
(
AuthJdRequest
.
class
)
{
@Override
public
String
authorize
()
{
return
"https://open-oauth.jd.com/oauth2/to_login"
;
...
...
@@ -806,7 +810,7 @@ public enum AuthDefaultSource implements AuthSource {
/**
* 阿里云
*/
ALIYUN
{
ALIYUN
(
AuthAliyunRequest
.
class
)
{
@Override
public
String
authorize
()
{
return
"https://signin.aliyun.com/oauth2/v1/auth"
;
...
...
@@ -831,7 +835,7 @@ public enum AuthDefaultSource implements AuthSource {
/**
* 喜马拉雅
*/
XMLY
{
XMLY
(
AuthXmlyRequest
.
class
)
{
@Override
public
String
authorize
()
{
return
"https://api.ximalaya.com/oauth2/js/authorize"
;
...
...
@@ -858,7 +862,7 @@ public enum AuthDefaultSource implements AuthSource {
*
* @since 1.16.0
*/
AMAZON
{
AMAZON
(
AuthAmazonRequest
.
class
)
{
@Override
public
String
authorize
()
{
return
"https://www.amazon.com/ap/oa"
;
...
...
@@ -884,7 +888,7 @@ public enum AuthDefaultSource implements AuthSource {
*
* @since 1.16.0
*/
SLACK
{
SLACK
(
AuthSlackRequest
.
class
)
{
@Override
public
String
authorize
()
{
return
"https://slack.com/oauth/v2/authorize"
;
...
...
@@ -917,7 +921,7 @@ public enum AuthDefaultSource implements AuthSource {
*
* @since 1.16.0
*/
LINE
{
LINE
(
AuthLineRequest
.
class
)
{
@Override
public
String
authorize
()
{
return
"https://access.line.me/oauth2/v2.1/authorize"
;
...
...
@@ -950,7 +954,7 @@ public enum AuthDefaultSource implements AuthSource {
*
* @since 1.16.0
*/
OKTA
{
OKTA
(
AuthOktaRequest
.
class
)
{
@Override
public
String
authorize
()
{
return
"https://%s.okta.com/oauth2/%s/v1/authorize"
;
...
...
@@ -981,7 +985,7 @@ public enum AuthDefaultSource implements AuthSource {
*
* @since 1.16.2
*/
PROGINN
{
PROGINN
(
AuthProginnRequest
.
class
)
{
@Override
public
String
authorize
()
{
return
"https://www.proginn.com/oauth2/authorize"
;
...
...
@@ -996,5 +1000,49 @@ public enum AuthDefaultSource implements AuthSource {
public
String
userInfo
()
{
return
"https://www.proginn.com/openapi/user/basic_info"
;
}
},
};
/** 对应的实现类 */
private
Class
<?
extends
AuthDefaultRequest
>
targetClass
;
AuthDefaultSource
(
Class
<?
extends
AuthDefaultRequest
>
targetClass
)
{
this
.
targetClass
=
targetClass
;
}
/**
* 根据source获取对应的AuthSource枚举
* @param source 枚举名
* @return AuthDefaultSource
*/
public
static
AuthDefaultSource
getAuthSource
(
String
source
){
return
Arrays
.
stream
(
AuthDefaultSource
.
values
()).
filter
(
authSource
->
authSource
.
name
().
equalsIgnoreCase
(
source
)).
findAny
().
orElseThrow
(()->
new
AuthException
(
"未获取到有效的AuthSource配置"
));
}
/**
* 根据配置获取 AuthRequest 实例
* @param authConfig 配置
* @return AuthRequest
*/
public
AuthRequest
getAuthRequestInstance
(
AuthConfig
authConfig
)
{
return
getAuthRequestInstance
(
authConfig
,
null
);
}
/**
* 利用反射 生成 AuthRequest 实例
* @param authConfig 配置
* @param authStateCache 缓存配置
* @return AuthRequest
*/
public
AuthRequest
getAuthRequestInstance
(
AuthConfig
authConfig
,
AuthStateCache
authStateCache
)
{
try
{
if
(
authStateCache
==
null
){
return
this
.
targetClass
.
getDeclaredConstructor
(
AuthConfig
.
class
).
newInstance
(
authConfig
);
}
else
{
return
this
.
targetClass
.
getDeclaredConstructor
(
AuthConfig
.
class
,
AuthStateCache
.
class
).
newInstance
(
authConfig
,
authStateCache
);
}
}
catch
(
Exception
e
)
{
throw
new
AuthException
(
"未获取到有效的Auth配置"
);
}
}
}
src/main/java/me/zhyd/oauth/request/AuthAlipayRequest.java
浏览文件 @
74ee17b2
...
...
@@ -21,6 +21,8 @@ import me.zhyd.oauth.model.AuthUser;
import
me.zhyd.oauth.utils.StringUtils
;
import
me.zhyd.oauth.utils.UrlBuilder
;
import
java.net.InetSocketAddress
;
/**
* 支付宝登录
*
...
...
@@ -39,8 +41,15 @@ public class AuthAlipayRequest extends AuthDefaultRequest {
public
AuthAlipayRequest
(
AuthConfig
config
,
AuthStateCache
authStateCache
)
{
super
(
config
,
AuthDefaultSource
.
ALIPAY
,
authStateCache
);
this
.
alipayClient
=
new
DefaultAlipayClient
(
AuthDefaultSource
.
ALIPAY
.
accessToken
(),
config
.
getClientId
(),
config
.
getClientSecret
(),
"json"
,
"UTF-8"
,
config
.
getAlipayPublicKey
(),
"RSA2"
);
if
(
config
.
getHttpConfig
()
!=
null
&&
config
.
getHttpConfig
().
getProxy
()
!=
null
&&
config
.
getHttpConfig
().
getProxy
().
address
()
instanceof
InetSocketAddress
)
{
InetSocketAddress
address
=
(
InetSocketAddress
)
config
.
getHttpConfig
().
getProxy
().
address
();
this
.
alipayClient
=
new
DefaultAlipayClient
(
AuthDefaultSource
.
ALIPAY
.
accessToken
(),
config
.
getClientId
(),
config
.
getClientSecret
(),
"json"
,
"UTF-8"
,
config
.
getAlipayPublicKey
(),
"RSA2"
,
address
.
getHostName
(),
address
.
getPort
());
}
else
{
this
.
alipayClient
=
new
DefaultAlipayClient
(
AuthDefaultSource
.
ALIPAY
.
accessToken
(),
config
.
getClientId
(),
config
.
getClientSecret
(),
"json"
,
"UTF-8"
,
config
.
getAlipayPublicKey
(),
"RSA2"
);
}
}
public
AuthAlipayRequest
(
AuthConfig
config
,
AuthStateCache
authStateCache
,
String
proxyHost
,
Integer
proxyPort
)
{
...
...
@@ -54,7 +63,7 @@ public class AuthAlipayRequest extends AuthDefaultRequest {
AlipaySystemOauthTokenRequest
request
=
new
AlipaySystemOauthTokenRequest
();
request
.
setGrantType
(
"authorization_code"
);
request
.
setCode
(
authCallback
.
getAuth_code
());
AlipaySystemOauthTokenResponse
response
=
null
;
AlipaySystemOauthTokenResponse
response
;
try
{
response
=
this
.
alipayClient
.
execute
(
request
);
}
catch
(
Exception
e
)
{
...
...
src/test/java/me/zhyd/oauth/config/AuthExtendSource.java
浏览文件 @
74ee17b2
package
me.zhyd.oauth.config
;
import
me.zhyd.oauth.cache.AuthStateCache
;
import
me.zhyd.oauth.exception.AuthException
;
import
me.zhyd.oauth.request.AuthDefaultRequest
;
import
me.zhyd.oauth.request.AuthExtendRequest
;
import
me.zhyd.oauth.request.AuthRequest
;
/**
* 测试自定义实现{@link AuthSource}接口后的枚举类
*
...
...
@@ -9,7 +15,7 @@ package me.zhyd.oauth.config;
*/
public
enum
AuthExtendSource
implements
AuthSource
{
OTHER
{
OTHER
(
AuthExtendRequest
.
class
)
{
/**
* 授权的api
*
...
...
@@ -59,5 +65,28 @@ public enum AuthExtendSource implements AuthSource {
public
String
refresh
()
{
return
null
;
}
};
private
Class
<?
extends
AuthDefaultRequest
>
targetClass
;
AuthExtendSource
(
Class
<?
extends
AuthDefaultRequest
>
targetClass
)
{
this
.
targetClass
=
targetClass
;
}
public
AuthRequest
getAuthRequestInstance
(
AuthConfig
authConfig
)
{
return
this
.
getAuthRequestInstance
(
authConfig
,
null
);
}
public
AuthRequest
getAuthRequestInstance
(
AuthConfig
authConfig
,
AuthStateCache
authStateCache
)
{
try
{
if
(
authStateCache
==
null
){
return
this
.
targetClass
.
getDeclaredConstructor
(
AuthConfig
.
class
).
newInstance
(
authConfig
);
}
else
{
return
this
.
targetClass
.
getDeclaredConstructor
(
AuthConfig
.
class
,
AuthStateCache
.
class
).
newInstance
(
authConfig
,
authStateCache
);
}
}
catch
(
Exception
e
)
{
throw
new
AuthException
(
"未获取到有效的Auth配置"
);
}
}
}
src/test/java/me/zhyd/oauth/request/AuthWeChatMpRequestTest.java
浏览文件 @
74ee17b2
package
me.zhyd.oauth.request
;
import
me.zhyd.oauth.config.AuthConfig
;
import
me.zhyd.oauth.config.AuthDefaultSource
;
import
me.zhyd.oauth.utils.AuthStateUtils
;
import
org.junit.Assert
;
import
org.junit.Test
;
public
class
AuthWeChatMpRequestTest
{
...
...
@@ -16,4 +18,15 @@ public class AuthWeChatMpRequestTest {
.
build
());
System
.
out
.
println
(
request
.
authorize
(
AuthStateUtils
.
createState
()));
}
@Test
public
void
authorize1
()
{
AuthRequest
request
=
AuthDefaultSource
.
getAuthSource
(
"wechat_mp"
).
getAuthRequestInstance
(
AuthConfig
.
builder
()
.
clientId
(
"a"
)
.
clientSecret
(
"a"
)
.
redirectUri
(
"https://www.justauth.cn"
)
.
build
());
Assert
.
assertTrue
(
request
instanceof
AuthWeChatMpRequest
);
System
.
out
.
println
(
request
.
authorize
(
AuthStateUtils
.
createState
()));
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录