Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
提交反馈
为 GitLab 提交贡献
登录
切换导航
I
ibznotify
项目
项目
详情
动态
版本
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
ibiz4jteam
ibznotify
提交
aafde99e
提交
aafde99e
编写于
8月 16, 2020
作者:
zhouweidong
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
钉钉、微信、阿里消息集成
上级
2fdfdb16
变更
5
显示空白字符变更
内嵌
并排
正在显示
5 个修改的文件
包含
223 行增加
和
70 行删除
+223
-70
RefreshTokenAspect.java
...cn/ibizlab/core/extensions/aspect/RefreshTokenAspect.java
+1
-1
Msg.java
.../src/main/java/cn/ibizlab/core/extensions/domain/Msg.java
+24
-0
Template.java
...main/java/cn/ibizlab/core/extensions/domain/Template.java
+20
-0
NotifyCoreService.java
...cn/ibizlab/core/extensions/service/NotifyCoreService.java
+169
-44
NotifyCoreResource.java
...va/cn/ibizlab/api/rest/extensions/NotifyCoreResource.java
+9
-25
未找到文件。
ibznotify-core/src/main/java/cn/ibizlab/core/extensions/aspect/RefreshTokenAspect.java
浏览文件 @
aafde99e
...
...
@@ -44,7 +44,7 @@ public class RefreshTokenAspect {
*/
private
void
refreshToken
(
JoinPoint
point
){
Object
[]
args
=
point
.
getArgs
();
if
(
args
.
length
>
0
)
{
if
(
args
.
length
>
0
&&
args
[
0
]
instanceof
MsgOpenAccess
)
{
MsgOpenAccess
msgOpenAccess
=
(
MsgOpenAccess
)
args
[
0
];
if
(
msgOpenAccess
.
getOpenType
().
equals
(
"wechat"
)
||
msgOpenAccess
.
getOpenType
().
equals
(
"dingtalk"
)){
notifyCoreService
.
refreshToken
(
msgOpenAccess
);
...
...
ibznotify-core/src/main/java/cn/ibizlab/core/extensions/domain/Msg.java
0 → 100644
浏览文件 @
aafde99e
package
cn
.
ibizlab
.
core
.
extensions
.
domain
;
import
lombok.Data
;
import
javax.validation.constraints.NotBlank
;
import
java.util.Map
;
@Data
public
class
Msg
{
@NotBlank
(
message
=
"系统标识不能为空"
)
private
String
system
;
@NotBlank
(
message
=
"模板标识不能为空"
)
private
String
templateid
;
@NotBlank
(
message
=
"模板类型不能为空"
)
private
String
msgtypes
;
@NotBlank
(
message
=
"用户标识不能为空"
)
private
String
userids
;
private
Map
templparams
;
}
ibznotify-core/src/main/java/cn/ibizlab/core/extensions/domain/Template.java
0 → 100644
浏览文件 @
aafde99e
package
cn
.
ibizlab
.
core
.
extensions
.
domain
;
import
com.alibaba.fastjson.JSONArray
;
import
lombok.Data
;
import
javax.validation.constraints.NotBlank
;
import
javax.validation.constraints.NotNull
;
@Data
public
class
Template
{
@NotBlank
(
message
=
"系统标识不能为空"
)
private
String
system
;
@NotNull
(
message
=
"模板不能为空"
)
private
JSONArray
template
;
@NotBlank
(
message
=
"模板类型不能为空"
)
private
String
templtypes
;
}
ibznotify-core/src/main/java/cn/ibizlab/core/extensions/service/NotifyCoreService.java
浏览文件 @
aafde99e
package
cn
.
ibizlab
.
core
.
extensions
.
service
;
import
cn.ibizlab.core.extensions.domain.Msg
;
import
cn.ibizlab.core.extensions.domain.Template
;
import
cn.ibizlab.core.notify.domain.MsgOpenAccess
;
import
cn.ibizlab.core.notify.domain.MsgTemplate
;
import
cn.ibizlab.core.notify.domain.MsgUserAccount
;
...
...
@@ -7,10 +9,12 @@ import cn.ibizlab.core.notify.service.IMsgOpenAccessService;
import
cn.ibizlab.core.notify.service.IMsgTemplateService
;
import
cn.ibizlab.core.notify.service.IMsgUserAccountService
;
import
cn.ibizlab.util.errors.BadRequestAlertException
;
import
com.alibaba.fastjson.JSONArray
;
import
com.alibaba.fastjson.JSONObject
;
import
com.aliyuncs.CommonRequest
;
import
com.aliyuncs.DefaultAcsClient
;
import
com.aliyuncs.IAcsClient
;
import
com.aliyuncs.dm.model.v20151123.BatchSendMailRequest
;
import
com.aliyuncs.dm.model.v20151123.SingleSendMailRequest
;
import
com.aliyuncs.http.MethodType
;
import
com.aliyuncs.profile.DefaultProfile
;
...
...
@@ -30,12 +34,8 @@ import org.springframework.http.ResponseEntity;
import
org.springframework.stereotype.Service
;
import
org.springframework.util.StringUtils
;
import
org.springframework.web.client.RestTemplate
;
import
java.sql.Timestamp
;
import
java.util.Calendar
;
import
java.util.Date
;
import
java.util.HashMap
;
import
java.util.Map
;
import
java.util.*
;
@Service
@Slf4j
...
...
@@ -62,9 +62,17 @@ public class NotifyCoreService {
*/
private
final
String
aliSmsDomain
=
"dysmsapi.aliyuncs.com"
;
/**
* 阿里短信服务方法名
* 阿里短信服务单处理行为
*/
private
final
String
aliSendSmsAction
=
"SendSms"
;
/**
* 阿里短信服批处理行为
*/
private
final
String
aliSmsAction
=
"SendSms"
;
private
final
String
aliSendBatchSmsAction
=
"SendBatchSms"
;
/**
* 阿里邮件批处理行为
*/
private
final
String
aliBatchSendMailAction
=
"BatchSendMail"
;
/**
* 消息类型
*/
...
...
@@ -79,7 +87,7 @@ public class NotifyCoreService {
RestTemplate
restTemplate
;
@Autowired
@Lazy
IMsgOpenAccessService
smsConfig
Service
;
IMsgOpenAccessService
openAccess
Service
;
@Autowired
@Lazy
IMsgTemplateService
templateService
;
...
...
@@ -89,12 +97,11 @@ public class NotifyCoreService {
/**
* 获取钉钉token
* @param
accessId
* @param
openAccess
* @return
*/
@SneakyThrows
public
String
getDingTalkToken
(
String
accessId
){
MsgOpenAccess
openAccess
=
smsConfigService
.
get
(
accessId
);
public
String
getDingTalkToken
(
MsgOpenAccess
openAccess
){
String
accessKey
=
openAccess
.
getAccessKey
();
String
accessSecret
=
openAccess
.
getSecretKey
();
DingTalkClient
client
=
new
DefaultDingTalkClient
(
dingTalkTokenApi
);
...
...
@@ -109,11 +116,10 @@ public class NotifyCoreService {
/**
* 获取微信token
* @param
accessId
* @param
openAccess
* @return
*/
public
String
getWeChatToken
(
String
accessId
){
MsgOpenAccess
openAccess
=
smsConfigService
.
get
(
accessId
);
public
String
getWeChatToken
(
MsgOpenAccess
openAccess
){
String
accessKey
=
openAccess
.
getAccessKey
();
String
accessSecret
=
openAccess
.
getSecretKey
();
ResponseEntity
<
String
>
result
=
restTemplate
.
getForEntity
(
String
.
format
(
weChatGetTokenApi
,
accessKey
,
accessSecret
),
String
.
class
);
...
...
@@ -127,7 +133,7 @@ public class NotifyCoreService {
* @param userId
*/
@SneakyThrows
p
ublic
boolean
sendDingTalkMsg
(
String
tid
,
String
userId
){
p
rivate
boolean
sendDingTalkMsg
(
String
tid
,
String
userId
){
String
authUserId
=
getAuthUserId
(
userId
,
MsgType
.
dingtalk
);
MsgTemplate
template
=
templateService
.
get
(
tid
);
MsgOpenAccess
openAccess
=
template
.
getOpenaccess
();
...
...
@@ -152,7 +158,7 @@ public class NotifyCoreService {
* @param userId
*/
@SneakyThrows
p
ublic
boolean
SendAliSms
(
String
tid
,
String
userId
){
p
rivate
boolean
sendAliSms
(
String
tid
,
String
userId
,
Map
templParams
){
String
authUserId
=
getAuthUserId
(
userId
,
MsgType
.
aliyun
);
MsgTemplate
template
=
templateService
.
get
(
tid
);
MsgOpenAccess
openAccess
=
template
.
getOpenaccess
();
...
...
@@ -164,14 +170,25 @@ public class NotifyCoreService {
CommonRequest
request
=
new
CommonRequest
();
request
.
setSysMethod
(
MethodType
.
POST
);
request
.
setSysDomain
(
aliSmsDomain
);
request
.
setSysAction
(
aliSmsAction
);
if
(
authUserId
.
contains
(
","
)){
request
.
setSysAction
(
aliSendBatchSmsAction
);
request
.
putQueryParameter
(
"RegionId"
,
region
);
request
.
putQueryParameter
(
"PhoneNumbers"
,
Arrays
.
asList
(
authUserId
.
split
(
","
)).
toString
());
request
.
putQueryParameter
(
"SignName"
,
Arrays
.
asList
(
template
.
getTemplateName
().
split
(
","
)).
toString
());
request
.
putQueryParameter
(
"TemplateCode"
,
template
.
getTemplateId
());
request
.
putQueryParameter
(
"TemplateParam"
,
templParams
.
toString
());
client
.
getCommonResponse
(
request
);
}
else
{
request
.
setSysAction
(
aliSendSmsAction
);
request
.
putQueryParameter
(
"RegionId"
,
region
);
request
.
putQueryParameter
(
"PhoneNumbers"
,
authUserId
);
request
.
putQueryParameter
(
"SignName"
,
template
.
getTemplateName
());
request
.
putQueryParameter
(
"TemplateCode"
,
template
.
getTemplateId
());
request
.
putQueryParameter
(
"TemplateParam"
,
""
);
request
.
putQueryParameter
(
"TemplateParam"
,
templParams
.
toString
()
);
client
.
getCommonResponse
(
request
);
log
.
info
(
String
.
format
(
"成功向用户[%s]发送一条短信!"
,
authUserId
));
}
log
.
info
(
String
.
format
(
"成功向用户[%s]发送一条短信"
,
authUserId
));
return
true
;
}
...
...
@@ -181,7 +198,8 @@ public class NotifyCoreService {
* @param userId
*/
@SneakyThrows
public
boolean
sendAliEMail
(
String
tid
,
String
userId
){
private
boolean
sendAliEMail
(
String
tid
,
String
userId
){
String
authUserId
=
getAuthUserId
(
userId
,
MsgType
.
aliyun
);
MsgTemplate
template
=
templateService
.
get
(
tid
);
MsgOpenAccess
openAccess
=
template
.
getOpenaccess
();
...
...
@@ -190,6 +208,16 @@ public class NotifyCoreService {
String
accessSecret
=
openAccess
.
getSecretKey
();
DefaultProfile
profile
=
DefaultProfile
.
getProfile
(
StringUtils
.
isEmpty
(
region
)?
"cn-hangzhou"
:
region
,
accessKey
,
accessSecret
);
IAcsClient
client
=
new
DefaultAcsClient
(
profile
);
if
(
authUserId
.
contains
(
","
)){
BatchSendMailRequest
request
=
new
BatchSendMailRequest
();
request
.
setTemplateName
(
template
.
getTemplateName
());
request
.
setAccountName
(
template
.
getTemplateId
());
request
.
setReceiversName
(
authUserId
);
request
.
setAddressType
(
1
);
request
.
setActionName
(
aliBatchSendMailAction
);
}
else
{
SingleSendMailRequest
request
=
new
SingleSendMailRequest
();
request
.
setAccountName
(
template
.
getTemplateId
());
request
.
setAddressType
(
1
);
...
...
@@ -198,23 +226,25 @@ public class NotifyCoreService {
request
.
setSubject
(
template
.
getTemplateName
());
request
.
setHtmlBody
(
template
.
getContent
());
client
.
getAcsResponse
(
request
);
log
.
info
(
String
.
format
(
"成功向用户[%s]发送一条邮件!"
,
authUserId
));
}
log
.
info
(
String
.
format
(
"成功向用户[%s]发送一条邮件"
,
authUserId
));
return
true
;
}
/**
* 发送微信消息
* @param tid
* @param userId
*/
p
ublic
boolean
sendWeChatMsg
(
String
tid
,
String
userId
){
p
rivate
boolean
sendWeChatMsg
(
String
tid
,
String
userId
,
Map
templParams
){
String
authUserId
=
getAuthUserId
(
userId
,
MsgType
.
wechat
);
MsgTemplate
template
=
templateService
.
get
(
tid
);
MsgOpenAccess
openAccess
=
template
.
getOpenaccess
();
Map
paramMap
=
new
HashMap
();
paramMap
.
put
(
"template_id"
,
template
.
getTemplateId
());
paramMap
.
put
(
"touser"
,
authUserId
);
paramMap
.
put
(
"data"
,
new
HashMap
()
);
paramMap
.
put
(
"data"
,
templParams
);
HttpEntity
request
=
new
HttpEntity
(
paramMap
);
ResponseEntity
<
String
>
result
=
restTemplate
.
postForEntity
(
String
.
format
(
weChatSendMsgApi
,
openAccess
.
getAccessToken
()),
request
,
String
.
class
);
getResult
(
result
.
getBody
());
...
...
@@ -228,14 +258,30 @@ public class NotifyCoreService {
*/
private
String
getAuthUserId
(
String
userId
,
MsgType
type
){
QueryWrapper
<
MsgUserAccount
>
qw
=
new
QueryWrapper
();
qw
.
eq
(
"userid"
,
userId
);
qw
.
eq
(
"identity_type"
,
type
);
if
(
userId
.
contains
(
","
)){
qw
.
in
(
"userid"
,
userId
.
split
(
","
));
List
<
MsgUserAccount
>
userAccounts
=
userAccountService
.
list
(
qw
);
if
(
userAccounts
==
null
||
userAccounts
.
size
()==
0
)
throw
new
BadRequestAlertException
(
"未能获取到授权用户"
,
"NotifyCoreService"
,
"sendDingTalkMsg"
);
StringBuffer
authUserIds
=
new
StringBuffer
();
for
(
MsgUserAccount
userAccount:
userAccounts
){
if
(
StringUtils
.
isEmpty
(
authUserIds
.
toString
())){
authUserIds
.
append
(
userAccount
.
getIdentifier
());
}
else
{
authUserIds
.
append
(
","
+
userAccount
.
getIdentifier
());
}
}
return
authUserIds
.
toString
();
}
else
{
qw
.
eq
(
"userid"
,
userId
);
MsgUserAccount
userAccount
=
userAccountService
.
getOne
(
qw
);
if
(
userAccount
==
null
||
StringUtils
.
isEmpty
(
userAccount
.
getIdentifier
()))
throw
new
BadRequestAlertException
(
"未能获取到授权用户"
,
"NotifyCoreService"
,
"sendDingTalkMsg"
);
return
userAccount
.
getIdentifier
();
}
}
/**
* 解析接口返回结果
...
...
@@ -246,7 +292,7 @@ public class NotifyCoreService {
if
(
resultJo
.
containsKey
(
"errcode"
)
&&
resultJo
.
getInteger
(
"errcode"
)!=
0
)
throw
new
BadRequestAlertException
(
String
.
format
(
"发送消息失败,%s"
,
resultJo
.
toString
()),
""
,
""
);
else
log
.
info
(
"发送消息成功
!
"
);
log
.
info
(
"发送消息成功"
);
}
/**
...
...
@@ -258,10 +304,10 @@ public class NotifyCoreService {
String
tempToken
=
null
;
switch
(
openAccess
.
getOpenType
()){
case
"wechat"
:
tempToken
=
getWeChatToken
(
openAccess
.
getId
()
);
tempToken
=
getWeChatToken
(
openAccess
);
break
;
case
"dingtalk"
:
tempToken
=
getDingTalkToken
(
openAccess
.
getId
()
);
tempToken
=
getDingTalkToken
(
openAccess
);
break
;
}
if
(!
StringUtils
.
isEmpty
(
tempToken
)){
...
...
@@ -277,4 +323,83 @@ public class NotifyCoreService {
}
return
openAccess
;
}
/**
* 创建模板
* @param template
* @return
*/
public
boolean
createMsgTemplate
(
Template
template
){
String
system
=
template
.
getSystem
()
;
JSONArray
templates
=
template
.
getTemplate
();
String
templateTypes
=
template
.
getTempltypes
();
for
(
int
a
=
0
;
a
<
templates
.
size
();
a
++){
List
<
MsgOpenAccess
>
openAccesses
=
new
ArrayList
<>();
List
<
MsgTemplate
>
msgTemplates
=
new
ArrayList
<>();
for
(
String
templateType
:
templateTypes
.
split
(
","
)){
//创建消息平台
MsgOpenAccess
openAccess
=
openAccessService
.
getById
(
system
+
templateType
);
if
(
openAccess
==
null
)
{
openAccess
=
new
MsgOpenAccess
();
openAccess
.
setId
(
system
+
templateType
);
openAccess
.
setName
(
templateType
);
openAccess
.
setDisabled
(
0
);
openAccess
.
setOpenType
(
templateType
);
openAccesses
.
add
(
openAccess
);
}
//创建消息模板
MsgTemplate
msgTemplate
=
JSONObject
.
toJavaObject
(
templates
.
getJSONObject
(
a
),
MsgTemplate
.
class
);
msgTemplate
.
setAccessId
(
openAccess
.
getId
());
msgTemplate
.
setOpenType
(
templateType
);
msgTemplate
.
setTemplateType
(
templateType
);
msgTemplate
.
setTid
(
system
+
msgTemplate
.
getTid
()+
templateType
);
msgTemplates
.
add
(
msgTemplate
);
}
if
(
openAccesses
.
size
()>
0
)
openAccessService
.
saveOrUpdateBatch
(
openAccesses
);
if
(
msgTemplates
.
size
()>
0
)
templateService
.
saveOrUpdateBatch
(
msgTemplates
);
}
return
true
;
}
/**
* 发送消息
* @param msg
* @return
*/
public
boolean
sendMsg
(
Msg
msg
){
String
system
=
msg
.
getSystem
();
String
templateId
=
msg
.
getTemplateid
();
String
msgTypes
=
msg
.
getMsgtypes
();
String
userIds
=
msg
.
getUserids
();
Map
templParams
=
msg
.
getTemplparams
();
for
(
String
msgType:
msgTypes
.
split
(
","
)){
MsgTemplate
msgTemplate
=
templateService
.
getById
(
system
+
templateId
+
msgType
);
if
(
msgTemplate
==
null
){
throw
new
BadRequestAlertException
(
String
.
format
(
"发送消息失败,无法获取到[%s]对应的rt模板"
,
templateId
),
""
,
""
);
}
else
{
switch
(
msgType
){
case
"aliyun-sms"
:
sendAliSms
(
msgTemplate
.
getTid
(),
userIds
,
templParams
);
break
;
case
"aliyun-email"
:
sendAliEMail
(
msgTemplate
.
getTid
(),
userIds
);
break
;
case
"dingtalk"
:
sendDingTalkMsg
(
msgTemplate
.
getTid
(),
userIds
);
break
;
case
"wechat"
:
sendWeChatMsg
(
msgTemplate
.
getTid
(),
userIds
,
templParams
);
break
;
default
:
throw
new
BadRequestAlertException
(
String
.
format
(
"发送消息失败,尚未提供[%s]类型对应的消息服务"
,
msgType
),
""
,
""
);
}
}
}
return
true
;
}
}
ibznotify-provider/ibznotify-provider-api/src/main/java/cn/ibizlab/api/rest/extensions/NotifyCoreResource.java
浏览文件 @
aafde99e
package
cn
.
ibizlab
.
api
.
rest
.
extensions
;
import
cn.ibizlab.core.extensions.domain.Msg
;
import
cn.ibizlab.core.extensions.domain.Template
;
import
cn.ibizlab.core.extensions.service.NotifyCoreService
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.http.HttpStatus
;
import
org.springframework.http.ResponseEntity
;
import
org.springframework.validation.annotation.Validated
;
import
org.springframework.web.bind.annotation.RequestMapping
;
import
org.springframework.web.bind.annotation.RequestMethod
;
import
org.springframework.web.bind.annotation.RequestParam
;
import
org.springframework.web.bind.annotation.RestController
;
import
org.springframework.web.bind.annotation.*
;
@RestController
public
class
NotifyCoreResource
{
...
...
@@ -16,28 +15,13 @@ public class NotifyCoreResource {
@Autowired
NotifyCoreService
notifyCoreService
;
@RequestMapping
(
method
=
RequestMethod
.
GET
,
value
=
"/sendDingTalkMsg"
)
public
ResponseEntity
<
Boolean
>
sendDingTalkMsg
(
@Validated
@RequestParam
String
tid
,
@RequestParam
String
userId
){
return
ResponseEntity
.
status
(
HttpStatus
.
OK
).
body
(
notifyCoreService
.
sendDingTalkMsg
(
tid
,
userId
));
// return ResponseEntity.status(HttpStatus.OK).body(notifyCoreService.sendDingTalkMsg("6c2e3779dd159ceba3e70e7502f4cf6f","760fd9aae5bb9475cb4e18b80d689ea7"));
@RequestMapping
(
method
=
RequestMethod
.
POST
,
value
=
"/SendMsg"
)
public
ResponseEntity
<
Boolean
>
SendMsg
(
@Validated
@RequestBody
Msg
msg
){
return
ResponseEntity
.
status
(
HttpStatus
.
OK
).
body
(
notifyCoreService
.
sendMsg
(
msg
));
}
@RequestMapping
(
method
=
RequestMethod
.
GET
,
value
=
"/sendWeChatMsg"
)
public
ResponseEntity
<
Boolean
>
sendWeChatMsg
(
@Validated
@RequestParam
String
tid
,
@RequestParam
String
userId
){
return
ResponseEntity
.
status
(
HttpStatus
.
OK
).
body
(
notifyCoreService
.
sendWeChatMsg
(
tid
,
userId
));
// return ResponseEntity.status(HttpStatus.OK).body(notifyCoreService.sendWeChatMsg("8ddcea1f2a9743f159bd765133443684","760fd9aae5bb9475cb4e18b80d689ea7"));
@RequestMapping
(
method
=
RequestMethod
.
POST
,
value
=
"/createMsgTemplate"
)
public
ResponseEntity
<
Boolean
>
createMsgTemplate
(
@Validated
@RequestBody
Template
template
){
return
ResponseEntity
.
status
(
HttpStatus
.
OK
).
body
(
notifyCoreService
.
createMsgTemplate
(
template
));
}
@RequestMapping
(
method
=
RequestMethod
.
GET
,
value
=
"/sendAliEMail"
)
public
ResponseEntity
<
Boolean
>
sendAliEMail
(
@Validated
@RequestParam
String
tid
,
@RequestParam
String
userId
){
return
ResponseEntity
.
status
(
HttpStatus
.
OK
).
body
(
notifyCoreService
.
sendAliEMail
(
tid
,
userId
));
// return ResponseEntity.status(HttpStatus.OK).body(notifyCoreService.sendAliEMail("5f4c72e0eb1eb3cf5b57c319a021d5b9","760fd9aae5bb9475cb4e18b80d689ea7"));
}
@RequestMapping
(
method
=
RequestMethod
.
GET
,
value
=
"/SendAliSms"
)
public
ResponseEntity
<
Boolean
>
SendAliSms
(
@Validated
@RequestParam
String
tid
,
@RequestParam
String
userId
){
return
ResponseEntity
.
status
(
HttpStatus
.
OK
).
body
(
notifyCoreService
.
SendAliSms
(
tid
,
userId
));
// return ResponseEntity.status(HttpStatus.OK).body(notifyCoreService.SendAliSms("Vufzr1HEvhntkIOK8HkT_poUTLAmpwSbjzK0ncOkSuw","18677074230"));
}
}
编辑
预览
Markdown
格式
0%
请重试
or
添加新附件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
先完成此消息的编辑!
取消
想要评论请
注册
或
登录