Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
W
wangxiaolu-sfa-common-core
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
sfa
wangxiaolu-sfa-common-core
Commits
d7eccd54
提交
d7eccd54
authored
6月 24, 2025
作者:
000516
浏览文件
操作
浏览文件
下载
差异文件
1、添加飞书工具;2、CP状态;3、异常信息修改
上级
827aa7b7
0298612c
显示空白字符变更
内嵌
并排
正在显示
4 个修改的文件
包含
433 行增加
和
1 行删除
+433
-1
pom.xml
pom.xml
+5
-1
ECode.java
src/main/java/com/sfa/common/core/enums/ECode.java
+6
-0
PlanStatus.java
.../java/com/sfa/common/core/enums/promotion/PlanStatus.java
+40
-0
FeiShuUtil.java
src/main/java/com/sfa/common/core/utils/sdk/FeiShuUtil.java
+382
-0
没有找到文件。
pom.xml
浏览文件 @
d7eccd54
...
@@ -128,7 +128,11 @@
...
@@ -128,7 +128,11 @@
<groupId>
cn.hutool
</groupId>
<groupId>
cn.hutool
</groupId>
<artifactId>
hutool-all
</artifactId>
<artifactId>
hutool-all
</artifactId>
</dependency>
</dependency>
<!-- 飞书SDK -->
<dependency>
<groupId>
com.larksuite.oapi
</groupId>
<artifactId>
oapi-sdk
</artifactId>
</dependency>
</dependencies>
</dependencies>
</project>
</project>
src/main/java/com/sfa/common/core/enums/ECode.java
浏览文件 @
d7eccd54
...
@@ -9,6 +9,11 @@ import com.sfa.common.core.constant.StatusCode;
...
@@ -9,6 +9,11 @@ import com.sfa.common.core.constant.StatusCode;
*/
*/
public
enum
ECode
implements
StatusCode
{
public
enum
ECode
implements
StatusCode
{
/**
* 600+ :数据异常(不分模块)
*/
DATA_NULL_ERROR
(
600
,
"数据失效或为空;"
),
/**
/**
* 700+ :SQL统一异常(不分模块)
* 700+ :SQL统一异常(不分模块)
*/
*/
...
@@ -33,6 +38,7 @@ public enum ECode implements StatusCode {
...
@@ -33,6 +38,7 @@ public enum ECode implements StatusCode {
*/
*/
KQMX_CURRENTLY_TYPE_KQ_HAS
(
900
,
"不可重复打卡;"
),
KQMX_CURRENTLY_TYPE_KQ_HAS
(
900
,
"不可重复打卡;"
),
KQMX_CLOCK_IN_ERRPR
(
901
,
"考勤异常;"
),
KQMX_CLOCK_IN_ERRPR
(
901
,
"考勤异常;"
),
FS_CREATE_APPROVAL_ERROR
(
902
,
"%s"
),
/**
/**
...
...
src/main/java/com/sfa/common/core/enums/promotion/PlanStatus.java
0 → 100644
浏览文件 @
d7eccd54
package
com
.
sfa
.
common
.
core
.
enums
.
promotion
;
/**
* @author : liqiulin
* @date : 2025-02-12 17
* @describe :
*/
public
enum
PlanStatus
{
/**
* 是否执行:1:执行;0:未执行;
*/
EXECUTION
(
1
,
"执行"
),
NOT_EXECUTION
(
0
,
"未执行"
),
PENDING
(
2
,
"审批中"
),
REJECTED
(
3
,
"审批未通过"
),
WAIT
(
4
,
"待审批"
),
APPROVED
(
5
,
"已通过"
),
;
private
final
Integer
code
;
private
final
String
desc
;
PlanStatus
(
Integer
code
,
String
desc
)
{
this
.
code
=
code
;
this
.
desc
=
desc
;
}
public
static
String
getDesc
(
Integer
code
)
{
for
(
PlanStatus
planStatus
:
PlanStatus
.
values
())
{
if
(
planStatus
.
getCode
().
equals
(
code
))
{
return
planStatus
.
desc
;
}
}
return
null
;
}
public
Integer
getCode
()
{
return
code
;
}
}
src/main/java/com/sfa/common/core/utils/sdk/FeiShuUtil.java
0 → 100644
浏览文件 @
d7eccd54
package
com
.
sfa
.
common
.
core
.
utils
.
sdk
;
import
cn.hutool.http.HttpUtil
;
import
cn.hutool.http.Method
;
import
com.alibaba.fastjson2.JSONArray
;
import
com.alibaba.fastjson2.JSONObject
;
import
com.google.gson.JsonParser
;
import
com.lark.oapi.Client
;
import
com.lark.oapi.core.request.RequestOptions
;
import
com.lark.oapi.core.utils.Jsons
;
import
com.lark.oapi.okhttp.*
;
import
com.lark.oapi.service.approval.v4.model.*
;
import
com.lark.oapi.service.authen.v1.model.GetUserInfoResp
;
import
com.lark.oapi.service.authen.v1.model.GetUserInfoRespBody
;
import
com.lark.oapi.service.contact.v3.enums.ChildrenDepartmentDepartmentIdTypeEnum
;
import
com.lark.oapi.service.contact.v3.enums.FindByDepartmentUserDepartmentIdTypeEnum
;
import
com.lark.oapi.service.contact.v3.enums.FindByDepartmentUserUserIdTypeEnum
;
import
com.lark.oapi.service.contact.v3.model.ChildrenDepartmentReq
;
import
com.lark.oapi.service.contact.v3.model.ChildrenDepartmentResp
;
import
com.lark.oapi.service.contact.v3.model.FindByDepartmentUserReq
;
import
com.lark.oapi.service.contact.v3.model.FindByDepartmentUserResp
;
import
com.lark.oapi.service.corehr.v2.model.*
;
import
com.sfa.common.core.enums.ECode
;
import
com.sfa.common.core.exception.ServiceException
;
import
com.sfa.common.core.exception.auth.NotLoginException
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.beans.factory.annotation.Value
;
import
org.springframework.stereotype.Component
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.Map
;
/**
* @author : liqiulin
* @date : 2024-12-06 16
* @describe :
*/
@Component
public
class
FeiShuUtil
{
private
static
final
Logger
log
=
LoggerFactory
.
getLogger
(
FeiShuUtil
.
class
);
@Value
(
"${feishu.luzx.app_id}"
)
private
String
appId
;
@Value
(
"${feishu.luzx.app_secret}"
)
private
String
appSecret
;
@Value
(
"${feishu.bot_1.app_id}"
)
private
String
botAppId1
;
@Value
(
"${feishu.bot_1.app_secret}"
)
private
String
botAppSecret1
;
//飞书获取用户信息,注意值:最后的斜杆
@Value
(
"${feishu.redirectUri}"
)
private
String
redirectUri
;
private
static
final
String
UTF_8
=
"UTF-8"
;
private
static
final
String
CONTENT_TYPE
=
"application/json; charset=utf-8"
;
private
static
final
String
SHEET_URL
=
"https://open.feishu.cn/open-apis/sheets/v2/spreadsheets/"
;
private
static
final
String
TENANT_ACCESS_TOKEN_URL
=
"https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal"
;
private
static
final
String
VALUES_APPEND
=
"/values_append"
;
private
static
final
String
VALUES_IMAGE
=
"/values_image"
;
private
static
final
String
VALUES_BATCH_GET
=
"/values_batch_get"
;
private
static
final
String
VALUES
=
"/values"
;
private
static
final
String
STYLE
=
"/style"
;
/**
* 根据用户的登录临时code获取useraccessToken
* 应用:链路中心
*/
public
String
createUserAccessToken
(
String
code
)
{
try
{
HashMap
<
String
,
String
>
bodyMap
=
new
HashMap
<>();
bodyMap
.
put
(
"grant_type"
,
"authorization_code"
);
bodyMap
.
put
(
"client_id"
,
"cli_a7dbe3ec7d9e5013"
);
bodyMap
.
put
(
"client_secret"
,
"WxiT7uIJNDbDpEGfVCXEwNNfN1A3RgUo"
);
bodyMap
.
put
(
"redirect_uri"
,
redirectUri
);
bodyMap
.
put
(
"code"
,
code
);
OkHttpClient
client
=
new
OkHttpClient
();
RequestBody
body
=
RequestBody
.
create
(
MediaType
.
get
(
"application/json"
),
JSONObject
.
toJSONString
(
bodyMap
));
Request
build
=
new
Request
.
Builder
().
url
(
"https://open.feishu.cn/open-apis/authen/v2/oauth/token"
).
addHeader
(
"Content-Type"
,
"application/json; charset=utf-8"
).
post
(
body
).
build
();
Response
execute
=
client
.
newCall
(
build
).
execute
();
JSONObject
rj
=
JSONObject
.
parseObject
(
execute
.
body
().
string
());
if
(!
rj
.
containsKey
(
"access_token"
)){
log
.
error
(
"飞书用户获取失败!"
,
rj
.
toString
());
throw
new
NotLoginException
(
ECode
.
FEISHU_ACCESS_TOKEN_ERROR
);
}
return
rj
.
getString
(
"access_token"
);
}
catch
(
Exception
e
)
{
throw
new
NotLoginException
(
ECode
.
FEISHU_ACCESS_TOKEN_ERROR
);
}
}
/**
* 根据用户的userAccessToken获取用户信息
*/
public
GetUserInfoRespBody
getUserInfo
(
String
userAccessToken
)
{
try
{
Client
client
=
getClientLUZX
();
GetUserInfoResp
resp
=
client
.
authen
().
userInfo
().
get
(
RequestOptions
.
newBuilder
()
.
userAccessToken
(
userAccessToken
)
.
build
());
if
(!
resp
.
success
())
{
log
.
error
(
String
.
format
(
"code:%s,msg:%s,reqId:%s, resp:%s"
,
resp
.
getCode
(),
resp
.
getMsg
(),
resp
.
getRequestId
(),
Jsons
.
createGSON
(
true
,
false
).
toJson
(
JsonParser
.
parseString
(
new
String
(
resp
.
getRawResponse
().
getBody
(),
"UTF-8"
)))));
return
null
;
}
return
resp
.
getData
();
}
catch
(
Exception
e
)
{
log
.
error
(
"获取用户信息失败,停止执行!"
);
return
null
;
}
}
/**
* 批量获取飞书人事部门信息
* https://open.feishu.cn/document/corehr-v1/organization-management/department/batch_get?appId=cli_a8d8e0fc58d9100e
*/
public
Department
getDepartmentCorehr
(
String
deptId
)
{
// 判断部门ID,如果是"od-"开头,部门ID类型为"open_department_id",否则为"people_corehr_department_id"
String
departmentIdType
=
deptId
.
startsWith
(
"od-"
)
?
"open_department_id"
:
"people_corehr_department_id"
;
log
.
info
(
"部门ID<{}>所属类型为:{}"
,
deptId
,
departmentIdType
);
String
[]
deptIds
=
new
String
[]{
deptId
};
try
{
Client
client
=
getClientLUZX
();
// 创建请求对象
BatchGetDepartmentReq
req
=
BatchGetDepartmentReq
.
newBuilder
()
.
userIdType
(
"open_id"
)
.
departmentIdType
(
departmentIdType
)
.
batchGetDepartmentReqBody
(
BatchGetDepartmentReqBody
.
newBuilder
()
.
departmentIdList
(
deptIds
)
.
fields
(
new
String
[]{
"department_name"
,
"parent_department_id"
,
"code"
,
"manager"
,
"is_root"
,
"effective_date"
,
"expiration_date"
,
"active"
,
"custom_fields"
})
.
departmentNameList
(
new
String
[]{})
.
build
())
.
build
();
BatchGetDepartmentResp
resp
=
client
.
corehr
().
v2
().
department
().
batchGet
(
req
);
// 处理服务端错误
if
(!
resp
.
success
())
{
log
.
error
(
String
.
format
(
"code:%s,msg:%s,reqId:%s, resp:%s"
,
resp
.
getCode
(),
resp
.
getMsg
(),
resp
.
getRequestId
(),
Jsons
.
createGSON
(
true
,
false
).
toJson
(
JsonParser
.
parseString
(
new
String
(
resp
.
getRawResponse
().
getBody
(),
UTF_8
)))));
return
null
;
}
Department
[]
items
=
resp
.
getData
().
getItems
();
return
items
[
0
];
}
catch
(
Exception
e
)
{
log
.
error
(
"获取飞书人事部门失效,停止执行!"
);
throw
new
RuntimeException
(
e
);
}
}
/**
* 根据部门父编码获取子部门
* 公司编码:"0"
*/
public
JSONArray
getDeptByParentId
(
String
parentId
)
{
try
{
Client
client
=
getClientLUZX
();
ChildrenDepartmentReq
req
=
ChildrenDepartmentReq
.
newBuilder
()
.
departmentId
(
parentId
)
.
departmentIdType
(
ChildrenDepartmentDepartmentIdTypeEnum
.
DEPARTMENT_ID
)
.
pageSize
(
50
)
.
build
();
ChildrenDepartmentResp
resp
=
client
.
contact
().
department
().
children
(
req
);
if
(!
resp
.
success
())
{
log
.
error
(
String
.
format
(
"%s,code:%s,msg:%s,reqId:%s, resp:%s"
,
"根据部门父编码获取子部门失败"
,
resp
.
getCode
(),
resp
.
getMsg
(),
resp
.
getRequestId
(),
Jsons
.
createGSON
(
true
,
false
).
toJson
(
JsonParser
.
parseString
(
new
String
(
resp
.
getRawResponse
().
getBody
(),
UTF_8
)))));
return
null
;
}
JSONArray
items
=
JSONObject
.
parse
(
Jsons
.
DEFAULT
.
toJson
(
resp
.
getData
())).
getJSONArray
(
"items"
);
return
items
;
}
catch
(
Exception
e
)
{
log
.
error
(
"获取子部门列表失败,停止执行!"
);
}
return
null
;
}
/**
* 获取部门用户
*/
public
JSONArray
getUsersByDeptId
(
String
deptCode
)
{
try
{
Client
client
=
getClientLUZX
();
FindByDepartmentUserReq
req
=
FindByDepartmentUserReq
.
newBuilder
()
.
userIdType
(
FindByDepartmentUserUserIdTypeEnum
.
OPEN_ID
)
.
departmentIdType
(
FindByDepartmentUserDepartmentIdTypeEnum
.
DEPARTMENT_ID
)
.
departmentId
(
deptCode
)
.
pageSize
(
50
)
.
build
();
FindByDepartmentUserResp
resp
=
client
.
contact
().
user
().
findByDepartment
(
req
);
if
(!
resp
.
success
())
{
log
.
error
(
String
.
format
(
"%s,code:%s,msg:%s,reqId:%s, resp:%s"
,
"获取部门用户"
,
resp
.
getCode
(),
resp
.
getMsg
(),
resp
.
getRequestId
(),
Jsons
.
createGSON
(
true
,
false
).
toJson
(
JsonParser
.
parseString
(
new
String
(
resp
.
getRawResponse
().
getBody
(),
UTF_8
)))));
return
null
;
}
JSONArray
items
=
JSONObject
.
parse
(
Jsons
.
DEFAULT
.
toJson
(
resp
.
getData
())).
getJSONArray
(
"items"
);
return
items
;
}
catch
(
Exception
e
)
{
log
.
error
(
"获取部门用户失败,停止执行!部门id:{}"
,
deptCode
);
}
return
null
;
}
/**
* 获取电子表格数据
*/
public
JSONArray
pullSheet
(
String
sheetToken
,
String
autoToken
,
String
ranges
)
{
try
{
Map
<
String
,
Object
>
params
=
new
HashMap
<>();
params
.
put
(
"ranges"
,
ranges
);
String
result
=
HttpUtil
.
createGet
(
SHEET_URL
+
sheetToken
+
VALUES_BATCH_GET
).
form
(
params
).
auth
(
"Bearer "
+
autoToken
).
contentType
(
CONTENT_TYPE
).
execute
().
body
();
JSONObject
resultJson
=
JSONObject
.
parseObject
(
result
);
int
code
=
resultJson
.
getInteger
(
"code"
);
if
(
code
!=
0
)
{
throw
new
RuntimeException
(
"获取飞书表格范围数据错误:"
+
resultJson
.
getString
(
"msg"
));
}
return
resultJson
.
getJSONObject
(
"data"
).
getJSONArray
(
"valueRanges"
);
}
catch
(
Exception
e
)
{
log
.
error
(
"拉取表格数据失败,停止执行!"
,
e
);
}
return
new
JSONArray
();
}
/**
* 写入电子表格数据
*/
public
Integer
pushSetToSheet
(
String
range
,
List
<
Object
>
datas
,
String
sheetToken
,
String
autoToken
)
{
// 组装参数
Map
<
String
,
Map
<
String
,
Object
>>
bodyMap
=
new
HashMap
<>();
Map
<
String
,
Object
>
valueRange
=
new
HashMap
<>();
valueRange
.
put
(
"range"
,
range
);
valueRange
.
put
(
"values"
,
datas
);
bodyMap
.
put
(
"valueRange"
,
valueRange
);
String
bodyJson
=
JSONObject
.
toJSONString
(
bodyMap
);
// body上传
String
result
=
HttpUtil
.
createPost
(
SHEET_URL
+
sheetToken
+
VALUES_APPEND
)
.
auth
(
"Bearer "
+
autoToken
).
contentType
(
CONTENT_TYPE
)
.
body
(
bodyJson
)
.
execute
().
body
();
// 上传结果判断
JSONObject
resultJson
=
JSONObject
.
parseObject
(
result
);
return
resultJson
.
getInteger
(
"code"
);
}
/**
* 创建审批
*/
public
String
createApproval
(
Map
<
String
,
Object
>
approval
)
{
try
{
Client
client
=
getClientLUZX
();
CreateInstanceReq
req
=
CreateInstanceReq
.
newBuilder
()
.
instanceCreate
(
InstanceCreate
.
newBuilder
()
.
approvalCode
(
approval
.
get
(
"approval_code"
).
toString
())
.
form
(
JSONObject
.
toJSONString
(
approval
.
get
(
"form"
)))
.
userId
(
approval
.
get
(
"user_id"
).
toString
())
.
allowResubmit
(
Boolean
.
getBoolean
(
approval
.
get
(
"allow_resubmit"
).
toString
()))
.
allowSubmitAgain
(
Boolean
.
getBoolean
(
approval
.
get
(
"allow_submit_again"
).
toString
()))
.
build
()
).
build
();
CreateInstanceResp
resp
=
client
.
approval
().
v4
().
instance
().
create
(
req
);
if
(!
resp
.
success
())
{
throw
new
RuntimeException
(
String
.
format
(
"%s,code:%s,msg:%s,reqId:%s, resp:%s"
,
"创建飞书审批失败"
,
resp
.
getCode
(),
resp
.
getMsg
(),
resp
.
getRequestId
(),
Jsons
.
createGSON
(
true
,
false
).
toJson
(
JsonParser
.
parseString
(
new
String
(
resp
.
getRawResponse
().
getBody
(),
UTF_8
)))));
}
return
JSONObject
.
parseObject
(
JSONObject
.
toJSONString
(
resp
.
getData
())).
getString
(
"instance_code"
);
}
catch
(
Exception
e
)
{
throw
new
ServiceException
(
String
.
format
(
ECode
.
FS_CREATE_APPROVAL_ERROR
.
getMsg
(),
e
.
getMessage
()),
ECode
.
FS_CREATE_APPROVAL_ERROR
.
getCode
());
}
}
public
String
getApprovalInfo
(
String
approvalCode
){
try
{
Client
client
=
getClientLUZX
();
GetInstanceReq
req
=
GetInstanceReq
.
newBuilder
().
instanceId
(
approvalCode
).
build
();
GetInstanceResp
resp
=
client
.
approval
().
v4
().
instance
().
get
(
req
);
// 处理服务端错误
if
(!
resp
.
success
())
{
throw
new
RuntimeException
(
String
.
format
(
"%s,code:%s,msg:%s,reqId:%s, resp:%s"
,
"创建飞书审批失败"
,
resp
.
getCode
(),
resp
.
getMsg
(),
resp
.
getRequestId
(),
Jsons
.
createGSON
(
true
,
false
).
toJson
(
JsonParser
.
parseString
(
new
String
(
resp
.
getRawResponse
().
getBody
(),
UTF_8
)))));
}
return
JSONObject
.
toJSONString
(
resp
.
getData
());
}
catch
(
Exception
e
){
log
.
error
(
e
.
getMessage
());
return
null
;
}
}
/**
* 创建飞书客户端
* 应用:王小卤链路中心
*/
public
Client
getClientLUZX
()
{
return
Client
.
newBuilder
(
appId
,
appSecret
).
build
();
}
/**
* 创建飞书客户端
* 应用:飞书表格更新机器人_T1
*/
public
String
getBotToken1
()
{
Map
<
String
,
Object
>
bodyMap
=
new
HashMap
<>();
bodyMap
.
put
(
"app_id"
,
botAppId1
);
bodyMap
.
put
(
"app_secret"
,
botAppSecret1
);
String
bodyJson
=
JSONObject
.
toJSONString
(
bodyMap
);
String
result
=
HttpUtil
.
createPost
(
TENANT_ACCESS_TOKEN_URL
)
.
contentType
(
CONTENT_TYPE
)
.
body
(
bodyJson
)
.
execute
().
body
();
JSONObject
resultJson
=
JSONObject
.
parseObject
(
result
);
int
code
=
resultJson
.
getInteger
(
"code"
);
if
(
code
!=
0
)
{
throw
new
RuntimeException
(
"获取tenant_access_token错误"
);
}
return
resultJson
.
getString
(
"tenant_access_token"
);
}
public
void
appendStyle
(
String
sheetToken
,
Map
<
String
,
Object
>
body
,
String
autoToken
)
{
// body上传
String
result
=
HttpUtil
.
createRequest
(
Method
.
PUT
,
SHEET_URL
+
sheetToken
+
STYLE
)
.
auth
(
"Bearer "
+
autoToken
).
contentType
(
CONTENT_TYPE
)
.
body
(
JSONObject
.
toJSONString
(
body
))
.
execute
().
body
();
}
public
JSONObject
pullSheetOneRange
(
String
sheetToken
,
String
botToken1
,
String
ranges
)
{
return
pullSheet
(
sheetToken
,
botToken1
,
ranges
).
getJSONObject
(
0
);
}
/**
* 批量查询员工信息
* https://open.feishu.cn/document/corehr-v1/employee/batch_get?appId=cli_a8d8e0fc58d9100e
*/
public
Employee
getEmployeeReq
(
String
employmentId
)
{
try
{
Client
client
=
getClientLUZX
();
// 创建请求对象
BatchGetEmployeeReq
req
=
BatchGetEmployeeReq
.
newBuilder
()
.
userIdType
(
"people_corehr_id"
)
.
batchGetEmployeeReqBody
(
BatchGetEmployeeReqBody
.
newBuilder
()
.
fields
(
new
String
[]{
"employee_number"
,
"person_info.preferred_name"
,
"department_id"
,
"person_info.bank_account_list"
}).
employmentIds
(
new
String
[]{
employmentId
})
.
build
())
.
build
();
BatchGetEmployeeResp
resp
=
client
.
corehr
().
v2
().
employee
().
batchGet
(
req
);
// 处理服务端错误
if
(!
resp
.
success
())
{
log
.
error
(
String
.
format
(
"code:%s,msg:%s,reqId:%s, resp:%s"
,
resp
.
getCode
(),
resp
.
getMsg
(),
resp
.
getRequestId
(),
Jsons
.
createGSON
(
true
,
false
).
toJson
(
JsonParser
.
parseString
(
new
String
(
resp
.
getRawResponse
().
getBody
(),
UTF_8
)))));
return
null
;
}
// 只查询一个员工
Employee
item
=
resp
.
getData
().
getItems
()[
0
];
return
item
;
}
catch
(
Exception
e
)
{
throw
new
RuntimeException
(
e
);
}
}
}
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论