Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
智布道
OneBlog
提交
88e3489e
O
OneBlog
项目概览
智布道
/
OneBlog
大约 1 年 前同步成功
通知
11
Star
2
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
O
OneBlog
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
88e3489e
编写于
6月 01, 2019
作者:
智布道
👁
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
✨
后台支持关闭匿名评论
上级
98ca5cb1
变更
8
隐藏空白更改
内联
并排
Showing
8 changed file
with
198 addition
and
100 deletion
+198
-100
blog-core/src/main/java/com/zyd/blog/business/dto/BizCommentDTO.java
...rc/main/java/com/zyd/blog/business/dto/BizCommentDTO.java
+4
-3
blog-core/src/main/java/com/zyd/blog/business/entity/Comment.java
...e/src/main/java/com/zyd/blog/business/entity/Comment.java
+4
-0
blog-core/src/main/java/com/zyd/blog/business/service/impl/AuthServiceImpl.java
...a/com/zyd/blog/business/service/impl/AuthServiceImpl.java
+2
-0
blog-core/src/main/java/com/zyd/blog/business/service/impl/BizCommentServiceImpl.java
...zyd/blog/business/service/impl/BizCommentServiceImpl.java
+97
-32
blog-core/src/main/java/com/zyd/blog/persistence/beans/BizComment.java
.../main/java/com/zyd/blog/persistence/beans/BizComment.java
+3
-0
blog-core/src/main/resources/mybatis/BizCommentMapper.xml
blog-core/src/main/resources/mybatis/BizCommentMapper.xml
+18
-2
blog-web/src/main/resources/static/js/zhyd.comment.js
blog-web/src/main/resources/static/js/zhyd.comment.js
+69
-63
blog-web/src/main/resources/templates/layout/footer.ftl
blog-web/src/main/resources/templates/layout/footer.ftl
+1
-0
未找到文件。
blog-core/src/main/java/com/zyd/blog/business/dto/BizCommentDTO.java
浏览文件 @
88e3489e
...
...
@@ -2,6 +2,7 @@ package com.zyd.blog.business.dto;
import
com.fasterxml.jackson.annotation.JsonFormat
;
import
com.fasterxml.jackson.annotation.JsonIgnore
;
import
com.zyd.blog.business.enums.UserTypeEnum
;
import
lombok.Data
;
import
lombok.EqualsAndHashCode
;
...
...
@@ -39,10 +40,10 @@ public class BizCommentDTO {
private
Integer
oppose
;
@JsonIgnore
private
Long
userId
;
private
UserTypeEnum
userType
;
public
boolean
is
Admin
()
{
return
null
!=
user
Id
&&
userId
!=
0
;
public
boolean
is
Root
()
{
return
null
!=
user
Type
&&
userType
==
UserTypeEnum
.
ROOT
;
}
@JsonFormat
(
pattern
=
"yyyy-MM-dd HH:mm"
,
timezone
=
"GMT+8"
)
...
...
blog-core/src/main/java/com/zyd/blog/business/entity/Comment.java
浏览文件 @
88e3489e
...
...
@@ -292,5 +292,9 @@ public class Comment {
this
.
bizComment
.
setArticle
(
article
);
}
public
User
getUser
()
{
return
null
==
this
.
bizComment
.
getUser
()
?
null
:
new
User
(
this
.
bizComment
.
getUser
());
}
}
blog-core/src/main/java/com/zyd/blog/business/service/impl/AuthServiceImpl.java
浏览文件 @
88e3489e
package
com.zyd.blog.business.service.impl
;
import
com.zyd.blog.business.entity.User
;
import
com.zyd.blog.business.enums.UserTypeEnum
;
import
com.zyd.blog.business.service.AuthService
;
import
com.zyd.blog.business.service.SysUserService
;
import
com.zyd.blog.plugin.oauth.RequestFactory
;
...
...
@@ -40,6 +41,7 @@ public class AuthServiceImpl implements AuthService {
newUser
.
setGender
(
authUser
.
getGender
().
getCode
());
}
User
user
=
userService
.
getByUuidAndSource
(
authUser
.
getUuid
(),
authUser
.
getSource
().
toString
());
newUser
.
setUserType
(
UserTypeEnum
.
USER
);
if
(
null
!=
user
)
{
newUser
.
setId
(
user
.
getId
());
userService
.
updateSelective
(
newUser
);
...
...
blog-core/src/main/java/com/zyd/blog/business/service/impl/BizCommentServiceImpl.java
浏览文件 @
88e3489e
...
...
@@ -34,7 +34,6 @@ import org.springframework.util.Assert;
import
org.springframework.util.CollectionUtils
;
import
org.springframework.util.StringUtils
;
import
javax.servlet.http.HttpServletRequest
;
import
java.util.*
;
import
java.util.concurrent.TimeUnit
;
...
...
@@ -107,6 +106,9 @@ public class BizCommentServiceImpl implements BizCommentService {
for
(
Comment
comment
:
list
)
{
BizCommentDTO
dto
=
BeanConvertUtil
.
doConvert
(
comment
,
BizCommentDTO
.
class
);
dto
.
setParentDTO
(
BeanConvertUtil
.
doConvert
(
comment
.
getParent
(),
BizCommentDTO
.
class
));
if
(
null
!=
comment
.
getUser
())
{
dto
.
setUserType
(
comment
.
getUser
().
getUserTypeEnum
());
}
dtoList
.
add
(
dto
);
}
return
dtoList
;
...
...
@@ -151,10 +153,45 @@ public class BizCommentServiceImpl implements BizCommentService {
throw
new
ZhydCommentException
(
"站长已关闭匿名评论,请先登录!"
);
}
}
if
(
StringUtils
.
isEmpty
(
comment
.
getNickname
()))
{
throw
new
ZhydCommentException
(
"必须输入昵称"
);
this
.
filterContent
(
comment
);
if
(
SessionUtil
.
isLogin
())
{
this
.
setCurrentLoginUserInfo
(
comment
);
}
else
{
this
.
setCurrentAnonymousUserInfo
(
comment
);
}
List
<
String
>
avatars
=
configService
.
getRandomUserAvatar
();
if
(
StringUtils
.
isEmpty
(
comment
.
getAvatar
())
&&
!
CollectionUtils
.
isEmpty
(
avatars
))
{
Collections
.
shuffle
(
avatars
);
int
randomIndex
=
new
Random
().
nextInt
(
avatars
.
size
());
comment
.
setAvatar
(
avatars
.
get
(
randomIndex
));
}
if
(
StringUtils
.
isEmpty
(
comment
.
getStatus
()))
{
comment
.
setStatus
(
CommentStatusEnum
.
VERIFYING
.
toString
());
}
this
.
setCurrentDeviceInfo
(
comment
);
this
.
setCurrentLocation
(
comment
);
this
.
insert
(
comment
);
this
.
sendEmail
(
comment
);
return
comment
;
}
/**
* 过滤评论内容
*
* @param comment
*/
private
void
filterContent
(
Comment
comment
)
{
String
content
=
comment
.
getContent
();
if
(
StringUtils
.
isEmpty
(
content
)
||
"\n"
.
equals
(
content
))
{
throw
new
ZhydCommentException
(
"说点什么吧"
);
}
// 过滤非法属性和无用的空标签
if
(!
XssKillerUtil
.
isValid
(
content
))
{
throw
new
ZhydCommentException
(
"请不要使用特殊标签"
);
}
...
...
@@ -162,27 +199,50 @@ public class BizCommentServiceImpl implements BizCommentService {
if
(
StringUtils
.
isEmpty
(
content
)
||
"\n"
.
equals
(
content
))
{
throw
new
ZhydCommentException
(
"说点什么吧"
);
}
// 过滤非法属性和无用的空标签
comment
.
setContent
(
content
);
}
/**
* 保存当前匿名用户的信息
*
* @param comment
*/
private
void
setCurrentAnonymousUserInfo
(
Comment
comment
)
{
if
(
StringUtils
.
isEmpty
(
comment
.
getNickname
()))
{
throw
new
ZhydCommentException
(
"必须输入昵称"
);
}
comment
.
setNickname
(
HtmlUtil
.
html2Text
(
comment
.
getNickname
()));
comment
.
setQq
(
HtmlUtil
.
html2Text
(
comment
.
getQq
()));
comment
.
setAvatar
(
HtmlUtil
.
html2Text
(
comment
.
getAvatar
()));
List
<
String
>
avatars
=
configService
.
getRandomUserAvatar
();
if
(
StringUtils
.
isEmpty
(
comment
.
getAvatar
())
&&
!
CollectionUtils
.
isEmpty
(
avatars
))
{
Collections
.
shuffle
(
avatars
);
int
randomIndex
=
new
Random
().
nextInt
(
avatars
.
size
());
comment
.
setAvatar
(
avatars
.
get
(
randomIndex
));
}
comment
.
setEmail
(
HtmlUtil
.
html2Text
(
comment
.
getEmail
()));
comment
.
setUrl
(
HtmlUtil
.
html2Text
(
comment
.
getUrl
()));
HttpServletRequest
request
=
RequestHolder
.
getRequest
();
String
ua
=
request
.
getHeader
(
"User-Agent"
);
}
/**
* 保存当前登录用户的信息
*
* @param comment
*/
private
void
setCurrentLoginUserInfo
(
Comment
comment
)
{
User
loginUser
=
SessionUtil
.
getUser
();
comment
.
setNickname
(
HtmlUtil
.
html2Text
(
loginUser
.
getNickname
()));
comment
.
setQq
(
HtmlUtil
.
html2Text
(
loginUser
.
getQq
()));
comment
.
setAvatar
(
HtmlUtil
.
html2Text
(
loginUser
.
getAvatar
()));
comment
.
setEmail
(
HtmlUtil
.
html2Text
(
loginUser
.
getEmail
()));
comment
.
setUrl
(
HtmlUtil
.
html2Text
(
loginUser
.
getBlog
()));
comment
.
setUserId
(
loginUser
.
getId
());
}
/**
* 保存当前评论时的设备信息
*
* @param comment
*/
private
void
setCurrentDeviceInfo
(
Comment
comment
)
{
String
ua
=
RequestUtil
.
getUa
();
UserAgent
agent
=
UserAgent
.
parseUserAgentString
(
ua
);
Browser
browser
=
agent
.
getBrowser
();
String
browserInfo
=
browser
.
getName
();
// comment.setBrowserShortName(browser.getShortName());// 此处需开发者自己处理
Version
version
=
agent
.
getBrowserVersion
();
if
(
version
!=
null
)
{
browserInfo
+=
" "
+
version
.
getVersion
();
...
...
@@ -190,34 +250,39 @@ public class BizCommentServiceImpl implements BizCommentService {
comment
.
setBrowser
(
browserInfo
);
OperatingSystem
os
=
agent
.
getOperatingSystem
();
comment
.
setOs
(
os
.
getName
());
// comment.setOsShortName(os.getShortName());// 此处需开发者自己处理
comment
.
setIp
(
IpUtil
.
getRealIp
(
request
));
String
address
=
""
;
comment
.
setIp
(
RequestUtil
.
getIp
());
}
/**
* 保存当前评论时的位置信息
*
* @param comment
*/
private
void
setCurrentLocation
(
Comment
comment
)
{
Map
config
=
configService
.
getConfigs
();
try
{
String
locationJson
=
RestClientUtil
.
get
(
UrlBuildUtil
.
getLocationByIp
(
comment
.
getIp
(),
(
String
)
config
.
get
(
ConfigKeyEnum
.
BAIDU_API_AK
.
getKey
())));
JSONObject
localtionContent
=
JSONObject
.
parseObject
(
locationJson
).
getJSONObject
(
"content"
);
JSONObject
addressDetail
=
localtionContent
.
getJSONObject
(
"address_detail"
);
String
city
=
addressDetail
.
getString
(
"city"
);
String
district
=
addressDetail
.
getString
(
"district"
);
String
street
=
addressDetail
.
getString
(
"street"
);
address
=
addressDetail
.
getString
(
"province"
)
+
(
StringUtils
.
isEmpty
(
city
)
?
""
:
city
)
+
(
StringUtils
.
isEmpty
(
district
)
?
""
:
district
)
+
(
StringUtils
.
isEmpty
(
street
)
?
""
:
street
);
JSONObject
point
=
localtionContent
.
getJSONObject
(
"point"
);
comment
.
setLat
(
point
.
getString
(
"y"
));
comment
.
setLng
(
point
.
getString
(
"x"
));
comment
.
setAddress
(
address
);
if
(
localtionContent
.
containsKey
(
"address_detail"
))
{
JSONObject
addressDetail
=
localtionContent
.
getJSONObject
(
"address_detail"
);
String
city
=
addressDetail
.
getString
(
"city"
);
String
district
=
addressDetail
.
getString
(
"district"
);
String
street
=
addressDetail
.
getString
(
"street"
);
String
address
=
addressDetail
.
getString
(
"province"
)
+
(
StringUtils
.
isEmpty
(
city
)
?
""
:
city
)
+
(
StringUtils
.
isEmpty
(
district
)
?
""
:
district
)
+
(
StringUtils
.
isEmpty
(
street
)
?
""
:
street
);
comment
.
setAddress
(
address
);
}
}
catch
(
Exception
e
)
{
comment
.
setAddress
(
"未知"
);
log
.
error
(
"获取地址失败"
,
e
);
}
if
(
StringUtils
.
isEmpty
(
comment
.
get
Statu
s
()))
{
comment
.
set
Status
(
CommentStatusEnum
.
VERIFYING
.
toString
()
);
if
(
StringUtils
.
isEmpty
(
comment
.
get
Addres
s
()))
{
comment
.
set
Address
(
"未知"
);
}
this
.
insert
(
comment
);
this
.
sendEmail
(
comment
);
return
comment
;
}
...
...
blog-core/src/main/java/com/zyd/blog/persistence/beans/BizComment.java
浏览文件 @
88e3489e
...
...
@@ -41,4 +41,7 @@ public class BizComment extends AbstractDO {
private
String
remark
;
private
Integer
support
;
private
Integer
oppose
;
@Transient
private
SysUser
user
;
}
blog-core/src/main/resources/mybatis/BizCommentMapper.xml
浏览文件 @
88e3489e
...
...
@@ -36,6 +36,12 @@
<result
property=
"id"
jdbcType=
"BIGINT"
column=
"article_id"
/>
<result
property=
"title"
jdbcType=
"VARCHAR"
column=
"article_title"
/>
</association>
<association
property=
"user"
javaType=
"com.zyd.blog.persistence.beans.SysUser"
>
<result
property=
"id"
jdbcType=
"BIGINT"
column=
"u_id"
/>
<result
property=
"username"
jdbcType=
"VARCHAR"
column=
"u_username"
/>
<result
property=
"nickname"
jdbcType=
"VARCHAR"
column=
"u_nickname"
/>
<result
property=
"userType"
jdbcType=
"CHAR"
column=
"u_user_type"
/>
</association>
</resultMap>
<select
id=
"findPageBreakByCondition"
parameterType=
"com.zyd.blog.business.vo.CommentConditionVO"
resultMap=
"rm"
>
...
...
@@ -45,11 +51,16 @@
f.nickname AS parent_nickname,
f.content AS parent_content,
a.id AS article_id,
a.title AS article_title
a.title AS article_title,
u.id AS u_id,
u.username AS u_username,
u.nickname AS u_nickname,
u.user_type AS u_user_type
FROM
biz_comment t
LEFT JOIN biz_comment f ON t.pid = f.id
LEFT JOIN biz_article a ON a.id = t.sid
LEFT JOIN sys_user u ON u.id = t.user_id
WHERE
1 = 1
<if
test=
"userId != null"
>
...
...
@@ -85,11 +96,16 @@
f.nickname AS parent_nickname,
f.content AS parent_content,
a.id AS article_id,
a.title AS article_title
a.title AS article_title,
u.id AS u_id,
u.username AS u_username,
u.nickname AS u_nickname,
u.user_type AS u_user_type
FROM
biz_comment t
LEFT JOIN biz_comment f ON t.pid = f.id
LEFT JOIN biz_article a ON a.id = t.sid
LEFT JOIN sys_user u ON u.id = t.user_id
WHERE t.id = #{id}
</select>
...
...
blog-web/src/main/resources/static/js/zhyd.comment.js
浏览文件 @
88e3489e
...
...
@@ -126,7 +126,7 @@ $.extend({
var
userUrl
=
comment
.
url
||
"
javascript:void(0)
"
;
var
parent
=
comment
.
parent
;
var
adminIcon
=
''
;
if
(
comment
.
admin
){
if
(
comment
.
root
){
adminIcon
=
'
<img src="/img/author.png" alt="" class="author-icon" title="管理员">
'
;
}
var
parentQuote
=
parent
?
'
<a href="#comment-
'
+
parent
.
id
+
'
" class="comment-quote">@
'
+
parent
.
nickname
+
'
</a><div style="background-color: #f5f5f5;padding: 5px;margin: 5px;border-radius: 4px;"><i class="fa fa-quote-left"></i><p></p><div style="padding-left: 10px;">
'
+
filterXSS
(
parent
.
content
)
+
'
</div></div>
'
:
''
;
...
...
@@ -221,75 +221,81 @@ $.extend({
submit
:
function
(
target
)
{
var
$this
=
$
(
target
);
$this
.
button
(
'
loading
'
);
var
detail
=
localStorage
.
getItem
(
this
.
detailKey
);
var
data
=
$
(
"
#comment-form
"
).
serialize
();
if
(
!
detail
){
}
else
{
var
detailInfoJson
=
$
.
tool
.
parseFormSerialize
(
detail
);
$
.
comment
.
_detailForm
.
find
(
"
input
"
).
each
(
function
()
{
if
(
!
oauthConfig
.
loginUserId
)
{
var
detail
=
localStorage
.
getItem
(
this
.
detailKey
);
if
(
!
detail
){
}
else
{
var
detailInfoJson
=
$
.
tool
.
parseFormSerialize
(
detail
);
$
.
comment
.
_detailForm
.
find
(
"
input
"
).
each
(
function
()
{
var
$this
=
$
(
this
);
var
inputName
=
$this
.
attr
(
"
name
"
);
if
(
detailInfoJson
[
inputName
]){
$this
.
val
(
detailInfoJson
[
inputName
]);
}
});
var
$img
=
$
.
comment
.
_detailForm
.
find
(
'
img
'
);
$img
.
attr
(
'
src
'
,
detailInfoJson
.
avatar
);
$img
.
removeClass
(
'
hide
'
);
}
this
.
_commentDetailModal
.
modal
(
'
show
'
);
this
.
_closeBtn
.
unbind
(
'
click
'
);
this
.
_closeBtn
.
click
(
function
()
{
setTimeout
(
function
()
{
$this
.
html
(
"
<i class='fa fa-close'></i>取消操作...
"
);
setTimeout
(
function
()
{
$this
.
button
(
'
reset
'
);
},
1000
);
},
500
);
});
// 模态框抖动
this
.
_commentDetailModal
.
find
(
'
.modal-content
'
).
addClass
(
"
shake
"
);
$
.
comment
.
_detailForm
.
find
(
"
input[name=qq]
"
).
unbind
(
'
change
'
);
$
.
comment
.
_detailForm
.
find
(
"
input[name=qq]
"
).
change
(
function
()
{
var
$this
=
$
(
this
);
var
inputName
=
$this
.
attr
(
"
name
"
);
if
(
detailInfoJson
[
inputName
]){
$this
.
val
(
detailInfoJson
[
inputName
]);
var
qq
=
$this
.
val
();
var
$nextImg
=
$this
.
next
(
'
img
'
);
if
(
qq
){
$
.
ajax
({
type
:
"
post
"
,
url
:
"
/api/qq/
"
+
qq
,
success
:
function
(
json
)
{
$
.
alert
.
ajaxSuccess
(
json
);
var
data
=
json
.
data
;
$
.
comment
.
_detailForm
.
find
(
"
input
"
).
each
(
function
()
{
var
$this
=
$
(
this
);
var
inputName
=
$this
.
attr
(
"
name
"
);
if
(
data
[
inputName
]){
$this
.
val
(
data
[
inputName
]);
}
});
$nextImg
.
attr
(
'
src
'
,
data
.
avatar
);
$nextImg
.
removeClass
(
'
hide
'
);
},
error
:
$
.
alert
.
ajaxError
});
}
else
{
$nextImg
.
addClass
(
'
hide
'
);
}
});
var
$img
=
$
.
comment
.
_detailForm
.
find
(
'
img
'
);
$img
.
attr
(
'
src
'
,
detailInfoJson
.
avatar
);
$img
.
removeClass
(
'
hide
'
);
});
// 提交评论
this
.
_detailFormBtn
.
unbind
(
'
click
'
);
this
.
_detailFormBtn
.
click
(
function
()
{
$
.
comment
.
_detailForm
.
bootstrapValidator
(
"
validate
"
);
if
(
_form
.
valid
(
$
.
comment
.
_detailForm
))
{
data
=
data
+
"
&
"
+
$
.
comment
.
_detailForm
.
serialize
();
localStorage
.
setItem
(
$
.
comment
.
detailKey
,
$
.
comment
.
_detailForm
.
serialize
());
submitForm
(
data
);
}
});
}
else
{
submitForm
(
data
);
}
this
.
_commentDetailModal
.
modal
(
'
show
'
);
this
.
_closeBtn
.
unbind
(
'
click
'
);
this
.
_closeBtn
.
click
(
function
()
{
setTimeout
(
function
()
{
$this
.
html
(
"
<i class='fa fa-close'></i>取消操作...
"
);
setTimeout
(
function
()
{
$this
.
button
(
'
reset
'
);
},
1000
);
},
500
);
});
// 模态框抖动
this
.
_commentDetailModal
.
find
(
'
.modal-content
'
).
addClass
(
"
shake
"
);
$
.
comment
.
_detailForm
.
find
(
"
input[name=qq]
"
).
unbind
(
'
change
'
);
$
.
comment
.
_detailForm
.
find
(
"
input[name=qq]
"
).
change
(
function
()
{
var
$this
=
$
(
this
);
var
qq
=
$this
.
val
();
var
$nextImg
=
$this
.
next
(
'
img
'
);
if
(
qq
){
$
.
ajax
({
type
:
"
post
"
,
url
:
"
/api/qq/
"
+
qq
,
success
:
function
(
json
)
{
$
.
alert
.
ajaxSuccess
(
json
);
var
data
=
json
.
data
;
$
.
comment
.
_detailForm
.
find
(
"
input
"
).
each
(
function
()
{
var
$this
=
$
(
this
);
var
inputName
=
$this
.
attr
(
"
name
"
);
if
(
data
[
inputName
]){
$this
.
val
(
data
[
inputName
]);
}
});
$nextImg
.
attr
(
'
src
'
,
data
.
avatar
);
$nextImg
.
removeClass
(
'
hide
'
);
},
error
:
$
.
alert
.
ajaxError
});
}
else
{
$nextImg
.
addClass
(
'
hide
'
);
}
});
// 提交评论
this
.
_detailFormBtn
.
unbind
(
'
click
'
);
this
.
_detailFormBtn
.
click
(
function
()
{
$
.
comment
.
_detailForm
.
bootstrapValidator
(
"
validate
"
);
if
(
_form
.
valid
(
$
.
comment
.
_detailForm
))
{
data
=
data
+
"
&
"
+
$
.
comment
.
_detailForm
.
serialize
();
localStorage
.
setItem
(
$
.
comment
.
detailKey
,
$
.
comment
.
_detailForm
.
serialize
());
submitForm
(
data
);
}
});
function
submitForm
(
data
)
{
console
.
log
(
data
);
...
...
blog-web/src/main/resources/templates/layout/footer.ftl
浏览文件 @
88e3489e
...
...
@@ -166,6 +166,7 @@
};
var oauthConfig = {
loginUserId: '${user.id}',
loginUserName: '${user.username}',
loginUserAvatar: '${user.avatar}'
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录