Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
提交反馈
为 GitLab 提交贡献
登录
切换导航
P
pica-cloud-account
项目
项目
详情
动态
版本
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
1
合并请求
1
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
收起侧边栏
Close sidebar
动态
分支图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
com.pica.cloud.account
pica-cloud-account
提交
875b527f
提交
875b527f
编写于
3月 11, 2020
作者:
Chongwen.jiang
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
微信/苹果登录 验证码校验注册业务时需要原子性校验
上级
7edca772
流水线
#22631
已失败 于阶段
in 0 second
变更
5
流水线
1
显示空白字符变更
内嵌
并排
正在显示
5 个修改的文件
包含
35 行增加
和
56 行删除
+35
-56
Constants.java
...ica/cloud/account/account/server/constants/Constants.java
+3
-0
LoginController.java
...ud/account/account/server/controller/LoginController.java
+0
-1
LoginServiceImpl.java
...account/account/server/service/impl/LoginServiceImpl.java
+25
-5
RegisterServiceImpl.java
...ount/account/server/service/impl/RegisterServiceImpl.java
+5
-48
AccountUtils.java
.../pica/cloud/account/account/server/util/AccountUtils.java
+2
-2
未找到文件。
server/src/main/java/com/pica/cloud/account/account/server/constants/Constants.java
浏览文件 @
875b527f
...
@@ -63,4 +63,7 @@ public class Constants {
...
@@ -63,4 +63,7 @@ public class Constants {
/** 验证码缓存key前缀 */
/** 验证码缓存key前缀 */
public
static
final
String
AUTH_CODE_PREFIX
=
"authCode-"
;
public
static
final
String
AUTH_CODE_PREFIX
=
"authCode-"
;
/** 注册逻辑幂等处理缓存key */
public
static
final
String
REPEAT_REGISTER_PREFIX
=
"repeat-register—"
;
}
}
server/src/main/java/com/pica/cloud/account/account/server/controller/LoginController.java
浏览文件 @
875b527f
...
@@ -118,7 +118,6 @@ public class LoginController extends AccountBaseController {
...
@@ -118,7 +118,6 @@ public class LoginController extends AccountBaseController {
@PostMapping
(
value
=
"/login/wechat/step2"
)
@PostMapping
(
value
=
"/login/wechat/step2"
)
public
PicaResponse
<
LoginResult
>
loginByWeChatStep
(
@RequestBody
EncryptEntity
entity
)
throws
Exception
{
public
PicaResponse
<
LoginResult
>
loginByWeChatStep
(
@RequestBody
EncryptEntity
entity
)
throws
Exception
{
BaseRequest
request
=
CryptoUtil
.
decrypt
(
entity
,
BaseRequest
.
class
);
BaseRequest
request
=
CryptoUtil
.
decrypt
(
entity
,
BaseRequest
.
class
);
accountUtils
.
checkMobilePhoneAndAuthCode
(
request
.
getMobile
(),
AccountTypeEnum
.
SYSCODE_TYPE_WE_CHAT
.
getCode
()
+
""
,
request
.
getAuthCode
());
request
.
setProductType
(
super
.
getProductType
());
request
.
setProductType
(
super
.
getProductType
());
request
.
setSourceType
(
super
.
getSourceType
());
request
.
setSourceType
(
super
.
getSourceType
());
request
.
setLoginIp
(
super
.
getIpAddr
());
request
.
setLoginIp
(
super
.
getIpAddr
());
...
...
server/src/main/java/com/pica/cloud/account/account/server/service/impl/LoginServiceImpl.java
浏览文件 @
875b527f
...
@@ -245,6 +245,7 @@ public class LoginServiceImpl implements LoginService {
...
@@ -245,6 +245,7 @@ public class LoginServiceImpl implements LoginService {
public
LoginResult
loginAndRegister
(
BaseRequest
baseRequest
)
{
public
LoginResult
loginAndRegister
(
BaseRequest
baseRequest
)
{
String
mobile
=
baseRequest
.
getMobile
();
String
mobile
=
baseRequest
.
getMobile
();
AccountInfoEntity
accountInfoEntity
=
accountInfoDetailMapper
.
selectByMobile
(
AESUtil
.
encryptV0
(
mobile
));
AccountInfoEntity
accountInfoEntity
=
accountInfoDetailMapper
.
selectByMobile
(
AESUtil
.
encryptV0
(
mobile
));
logger
.
info
(
"loginAndRegister-accountInfoEntity is null {}, clientIp:{}"
,
(
accountInfoEntity
==
null
),
baseRequest
.
getLoginIp
());
if
(
accountInfoEntity
==
null
)
{
if
(
accountInfoEntity
==
null
)
{
//说明是注册功能
//说明是注册功能
accountUtils
.
checkRegisterMobilePhoneAndAuthCode
(
baseRequest
.
getMobile
(),
baseRequest
.
getFlag
()
+
""
,
baseRequest
.
getAuthCode
());
accountUtils
.
checkRegisterMobilePhoneAndAuthCode
(
baseRequest
.
getMobile
(),
baseRequest
.
getFlag
()
+
""
,
baseRequest
.
getAuthCode
());
...
@@ -359,8 +360,13 @@ public class LoginServiceImpl implements LoginService {
...
@@ -359,8 +360,13 @@ public class LoginServiceImpl implements LoginService {
public
LoginResult
loginByWeChatStep
(
BaseRequest
request
)
{
public
LoginResult
loginByWeChatStep
(
BaseRequest
request
)
{
//判断当前手机号是否注册过,注册过,直接登录;没有注册过,进行注册操操作
//判断当前手机号是否注册过,注册过,直接登录;没有注册过,进行注册操操作
AccountInfoEntity
accountInfoEntity
=
accountInfoDetailMapper
.
selectByMobile
(
AESUtil
.
encryptV0
(
request
.
getMobile
()));
AccountInfoEntity
accountInfoEntity
=
accountInfoDetailMapper
.
selectByMobile
(
AESUtil
.
encryptV0
(
request
.
getMobile
()));
logger
.
info
(
"loginByWeChatStep-accountInfoEntity is null {}, clientIp:{}"
,
(
accountInfoEntity
==
null
),
request
.
getLoginIp
());
LoginResult
result
;
LoginResult
result
;
if
(
accountInfoEntity
==
null
)
{
if
(
accountInfoEntity
==
null
)
{
accountUtils
.
checkRegisterMobilePhoneAndAuthCode
(
request
.
getMobile
(),
AccountTypeEnum
.
SYSCODE_TYPE_WE_CHAT
.
getCode
()
+
""
,
request
.
getAuthCode
());
result
=
registerService
.
register
(
request
);
result
=
registerService
.
register
(
request
);
if
(
doubleWritingMode
)
{
if
(
doubleWritingMode
)
{
//双写模式下,要在doctor表存储unionId
//双写模式下,要在doctor表存储unionId
...
@@ -372,6 +378,10 @@ public class LoginServiceImpl implements LoginService {
...
@@ -372,6 +378,10 @@ public class LoginServiceImpl implements LoginService {
}
}
}
}
}
else
{
}
else
{
accountUtils
.
checkMobilePhoneAndAuthCode
(
request
.
getMobile
(),
AccountTypeEnum
.
SYSCODE_TYPE_WE_CHAT
.
getCode
()
+
""
,
request
.
getAuthCode
());
result
=
processLogin
(
request
,
accountInfoEntity
.
getId
(),
AccountTypeEnum
.
LOGIN_WE_CHAT
.
getCode
());
result
=
processLogin
(
request
,
accountInfoEntity
.
getId
(),
AccountTypeEnum
.
LOGIN_WE_CHAT
.
getCode
());
}
}
result
.
setMobile
(
request
.
getMobile
());
result
.
setMobile
(
request
.
getMobile
());
...
@@ -776,25 +786,35 @@ public class LoginServiceImpl implements LoginService {
...
@@ -776,25 +786,35 @@ public class LoginServiceImpl implements LoginService {
*/
*/
@Override
@Override
public
LoginResult
loginByAppleStep
(
BaseRequest
request
)
{
public
LoginResult
loginByAppleStep
(
BaseRequest
request
)
{
// 验证码校验
accountUtils
.
checkMobilePhoneAndAuthCode
(
request
.
getMobile
(),
AccountTypeEnum
.
SYSCODE_TYPE_APPLE
.
getCode
()
+
""
,
request
.
getAuthCode
());
// 判断当前手机号是否注册过: 没有注册过,进行注册操操作, 注册过,直接登录;
// 判断当前手机号是否注册过: 没有注册过,进行注册操操作, 注册过,直接登录;
AccountInfoEntity
accountInfoDb
=
accountInfoDetailMapper
.
selectByMobile
(
AESUtil
.
encryptV0
(
request
.
getMobile
()));
AccountInfoEntity
accountInfoDb
=
accountInfoDetailMapper
.
selectByMobile
(
AESUtil
.
encryptV0
(
request
.
getMobile
()));
logger
.
info
(
"loginByAppleStep-account is null {}, request:{}"
,
accountInfoDb
==
null
,
JSON
.
toJSONString
(
request
));
LoginResult
result
;
LoginResult
result
;
accountInfoDb
=
null
;
if
(
accountInfoDb
==
null
)
{
if
(
accountInfoDb
==
null
)
{
// 验证码校验
accountUtils
.
checkRegisterMobilePhoneAndAuthCode
(
request
.
getMobile
(),
AccountTypeEnum
.
SYSCODE_TYPE_APPLE
.
getCode
()
+
""
,
request
.
getAuthCode
());
result
=
registerService
.
register
(
request
);
result
=
registerService
.
register
(
request
);
logger
.
info
(
"loginByAppleStep-register"
);
}
else
{
}
else
{
// 验证码校验
accountUtils
.
checkMobilePhoneAndAuthCode
(
request
.
getMobile
(),
AccountTypeEnum
.
SYSCODE_TYPE_APPLE
.
getCode
()
+
""
,
request
.
getAuthCode
());
result
=
processLogin
(
request
,
accountInfoDb
.
getId
(),
result
=
processLogin
(
request
,
accountInfoDb
.
getId
(),
AccountTypeEnum
.
LOGIN_APPLE
.
getCode
());
AccountTypeEnum
.
LOGIN_APPLE
.
getCode
());
logger
.
info
(
"loginByAppleStep-processLogin"
);
}
}
result
.
setMobile
(
request
.
getMobile
());
result
.
setMobile
(
request
.
getMobile
());
AccountInfoEntity
accountInfo
=
accountInfoDetailMapper
.
selectByMobile
(
AESUtil
.
encryptV0
(
request
.
getMobile
()));
AccountInfoEntity
accountInfo
=
accountInfoDetailMapper
.
selectByMobile
(
AESUtil
.
encryptV0
(
request
.
getMobile
()));
Integer
acctId
=
accountInfo
.
getId
();
Integer
acctId
=
accountInfo
.
getId
();
// insert account_apple_info表数据
// insert account_apple_info表数据
logger
.
info
(
"loginByAppleStep-insert-account_apple_info-start"
);
processAccountUnionApple
(
acctId
,
request
.
getAppleUserId
());
processAccountUnionApple
(
acctId
,
request
.
getAppleUserId
());
logger
.
info
(
"loginByAppleStep-insert-account_apple_info-end"
);
return
result
;
return
result
;
}
}
...
...
server/src/main/java/com/pica/cloud/account/account/server/service/impl/RegisterServiceImpl.java
浏览文件 @
875b527f
package
com
.
pica
.
cloud
.
account
.
account
.
server
.
service
.
impl
;
package
com
.
pica
.
cloud
.
account
.
account
.
server
.
service
.
impl
;
import
com.pica.cloud.account.account.common.req.OCINRequest
;
import
com.pica.cloud.account.account.common.req.OCINRequest
;
import
com.pica.cloud.account.account.server.constants.Constants
;
import
com.pica.cloud.account.account.server.entity.*
;
import
com.pica.cloud.account.account.server.entity.*
;
import
com.pica.cloud.account.account.server.enums.AccountExceptionEnum
;
import
com.pica.cloud.account.account.server.enums.AccountExceptionEnum
;
import
com.pica.cloud.account.account.server.enums.AccountTypeEnum
;
import
com.pica.cloud.account.account.server.enums.AccountTypeEnum
;
...
@@ -30,9 +31,6 @@ import java.util.concurrent.ExecutorService;
...
@@ -30,9 +31,6 @@ import java.util.concurrent.ExecutorService;
@Service
@Service
public
class
RegisterServiceImpl
implements
RegisterService
{
public
class
RegisterServiceImpl
implements
RegisterService
{
private
final
String
REPEAT_REGISTER_PREFIX
=
"repeat-register—"
;
private
Logger
logger
=
LoggerFactory
.
getLogger
(
this
.
getClass
());
private
Logger
logger
=
LoggerFactory
.
getLogger
(
this
.
getClass
());
@Autowired
@Autowired
...
@@ -41,9 +39,6 @@ public class RegisterServiceImpl implements RegisterService {
...
@@ -41,9 +39,6 @@ public class RegisterServiceImpl implements RegisterService {
@Autowired
@Autowired
private
AccountInfoDetailMapper
accountInfoDetailMapper
;
private
AccountInfoDetailMapper
accountInfoDetailMapper
;
@Autowired
private
AccountPatientInfoMapper
accountUserInfoMapper
;
@Autowired
@Autowired
private
AccountMapper
accountMapper
;
private
AccountMapper
accountMapper
;
...
@@ -56,9 +51,6 @@ public class RegisterServiceImpl implements RegisterService {
...
@@ -56,9 +51,6 @@ public class RegisterServiceImpl implements RegisterService {
@Autowired
@Autowired
private
TokenUtils
tokenUtils
;
private
TokenUtils
tokenUtils
;
// @Autowired
// private QueueProducer queueProducer;
@Autowired
@Autowired
private
AgreementEntityMapper
agreementEntityMapper
;
private
AgreementEntityMapper
agreementEntityMapper
;
...
@@ -87,12 +79,12 @@ public class RegisterServiceImpl implements RegisterService {
...
@@ -87,12 +79,12 @@ public class RegisterServiceImpl implements RegisterService {
public
LoginResult
register
(
BaseRequest
baseRequest
,
QueryMobileEntity
queryMobileEntity
)
{
public
LoginResult
register
(
BaseRequest
baseRequest
,
QueryMobileEntity
queryMobileEntity
)
{
String
mobile
=
baseRequest
.
getMobile
();
String
mobile
=
baseRequest
.
getMobile
();
//对注册接口做幂等性处理:注册成功,删除缓存,注册失败提示用户
//对注册接口做幂等性处理:注册成功,删除缓存,注册失败提示用户
String
exist
=
redisClient
.
get
(
REPEAT_REGISTER_PREFIX
+
mobile
);
String
exist
=
redisClient
.
get
(
Constants
.
REPEAT_REGISTER_PREFIX
+
mobile
);
if
(
StringUtils
.
isBlank
(
exist
))
{
if
(
StringUtils
.
isBlank
(
exist
))
{
String
mobileEncrypt
=
AESUtil
.
encryptV0
(
mobile
);
String
mobileEncrypt
=
AESUtil
.
encryptV0
(
mobile
);
AccountInfoEntity
accountInfoEntity
=
accountInfoDetailMapper
.
selectByMobile
(
mobileEncrypt
);
AccountInfoEntity
accountInfoEntity
=
accountInfoDetailMapper
.
selectByMobile
(
mobileEncrypt
);
if
(
accountInfoEntity
==
null
)
{
if
(
accountInfoEntity
==
null
)
{
redisClient
.
set
(
REPEAT_REGISTER_PREFIX
+
mobile
,
mobile
,
30
);
redisClient
.
set
(
Constants
.
REPEAT_REGISTER_PREFIX
+
mobile
,
mobile
,
30
);
try
{
try
{
Date
currentTime
=
new
Date
();
Date
currentTime
=
new
Date
();
int
productType
=
baseRequest
.
getProductType
();
int
productType
=
baseRequest
.
getProductType
();
...
@@ -146,14 +138,6 @@ public class RegisterServiceImpl implements RegisterService {
...
@@ -146,14 +138,6 @@ public class RegisterServiceImpl implements RegisterService {
result
.
setEntireFlag
(
1
);
result
.
setEntireFlag
(
1
);
result
.
setDoctorId
(
EncryptUtils
.
encryptContent
(
userId
+
""
,
EncryptConstants
.
ENCRYPT_TYPE_ID
));
result
.
setDoctorId
(
EncryptUtils
.
encryptContent
(
userId
+
""
,
EncryptConstants
.
ENCRYPT_TYPE_ID
));
result
.
setMobile
(
mobile
);
result
.
setMobile
(
mobile
);
/* ByteArrayOutputStream bos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(bos);
try {
dos.writeLong(userId);
} catch (IOException e) {
e.printStackTrace();
}
queueProducer.send(bos.toByteArray());*/
LogLoginEntity
entity
=
AccountLogEntityUtils
.
getLogLoginEntity
(
acctId
,
productType
,
baseRequest
.
getSourceType
(),
LogLoginEntity
entity
=
AccountLogEntityUtils
.
getLogLoginEntity
(
acctId
,
productType
,
baseRequest
.
getSourceType
(),
AccountTypeEnum
.
LOGIN_REGISTER
.
getCode
(),
baseRequest
.
getLoginIp
(),
AccountTypeEnum
.
LOGIN_STATUS_SUCCESS
.
getCode
(),
AccountTypeEnum
.
LOGIN_REGISTER
.
getCode
(),
baseRequest
.
getLoginIp
(),
AccountTypeEnum
.
LOGIN_STATUS_SUCCESS
.
getCode
(),
AccountTypeEnum
.
LOG_TYPE_LOGIN
.
getCode
());
AccountTypeEnum
.
LOG_TYPE_LOGIN
.
getCode
());
...
@@ -163,7 +147,7 @@ public class RegisterServiceImpl implements RegisterService {
...
@@ -163,7 +147,7 @@ public class RegisterServiceImpl implements RegisterService {
picaLogUtils
.
info
(
entity
);
picaLogUtils
.
info
(
entity
);
processAgreement
(
userId
);
processAgreement
(
userId
);
processRoleMap
(
userId
);
processRoleMap
(
userId
);
redisClient
.
del
(
REPEAT_REGISTER_PREFIX
+
mobile
);
redisClient
.
del
(
Constants
.
REPEAT_REGISTER_PREFIX
+
mobile
);
return
result
;
return
result
;
}
catch
(
Exception
e
)
{
}
catch
(
Exception
e
)
{
//向上抛出异常,让异常处理框架捕获到
//向上抛出异常,让异常处理框架捕获到
...
@@ -171,7 +155,7 @@ public class RegisterServiceImpl implements RegisterService {
...
@@ -171,7 +155,7 @@ public class RegisterServiceImpl implements RegisterService {
throw
new
AccountException
(
AccountExceptionEnum
.
PICA_REGISTER_FAIL
);
throw
new
AccountException
(
AccountExceptionEnum
.
PICA_REGISTER_FAIL
);
}
finally
{
}
finally
{
//如果在注册过程中抛出异常,就删除redis中的注册标记
//如果在注册过程中抛出异常,就删除redis中的注册标记
redisClient
.
del
(
REPEAT_REGISTER_PREFIX
+
mobile
);
redisClient
.
del
(
Constants
.
REPEAT_REGISTER_PREFIX
+
mobile
);
}
}
}
else
{
}
else
{
throw
new
AccountException
(
AccountExceptionEnum
.
PICA_ALREADY_REGISTER
);
throw
new
AccountException
(
AccountExceptionEnum
.
PICA_ALREADY_REGISTER
);
...
@@ -277,33 +261,6 @@ public class RegisterServiceImpl implements RegisterService {
...
@@ -277,33 +261,6 @@ public class RegisterServiceImpl implements RegisterService {
private
void
processAgreement
(
Long
userId
)
{
private
void
processAgreement
(
Long
userId
)
{
ExecutorService
executor
=
ExecutorServiceUtils
.
getExecutor
();
ExecutorService
executor
=
ExecutorServiceUtils
.
getExecutor
();
executor
.
submit
(()
->
{
executor
.
submit
(()
->
{
// //用户协议
// Date currentTime = new Date();
// Integer userVersion = agreementEntityMapper.selectByType(AccountAgreementEnum.USER_AGREEMENT.getCode());
// AgreementLogEntity userAgreementLogEntity = new AgreementLogEntity();
// userAgreementLogEntity.setAgreement_type(AccountAgreementEnum.USER_AGREEMENT.getCode());
// userAgreementLogEntity.setDoctor_id(userId);
// userAgreementLogEntity.setVersion(userVersion.toString());
// userAgreementLogEntity.setCreated_id(userId);
// userAgreementLogEntity.setCreated_time(currentTime);
// userAgreementLogEntity.setModified_id(userId);
// userAgreementLogEntity.setModified_time(currentTime);
// userAgreementLogEntity.setDelete_flag(1);
// agreementLogEntityMapper.insert(userAgreementLogEntity);
// //隐私协议
// Integer privateVersion = agreementEntityMapper.selectByType(AccountAgreementEnum.PRIVACY_AGREEMENT.getCode());
// AgreementLogEntity privateAgreementLogEntity = new AgreementLogEntity();
// privateAgreementLogEntity.setAgreement_type(AccountAgreementEnum.PRIVACY_AGREEMENT.getCode());
// privateAgreementLogEntity.setDoctor_id(userId);
// privateAgreementLogEntity.setVersion(privateVersion.toString());
// privateAgreementLogEntity.setCreated_id(userId);
// privateAgreementLogEntity.setCreated_time(currentTime);
// privateAgreementLogEntity.setModified_id(userId);
// privateAgreementLogEntity.setModified_time(currentTime);
// privateAgreementLogEntity.setDelete_flag(1);
// agreementLogEntityMapper.insert(privateAgreementLogEntity);
Integer
protocolId
=
agreementLogEntityMapper
.
getLatestProtocolId
(
2
);
//获取最新用户协议ID
Integer
protocolId
=
agreementLogEntityMapper
.
getLatestProtocolId
(
2
);
//获取最新用户协议ID
PProtocolLog
log
=
new
PProtocolLog
();
PProtocolLog
log
=
new
PProtocolLog
();
log
.
setUserId
(
userId
.
toString
());
log
.
setUserId
(
userId
.
toString
());
...
...
server/src/main/java/com/pica/cloud/account/account/server/util/AccountUtils.java
浏览文件 @
875b527f
...
@@ -50,7 +50,7 @@ public class AccountUtils {
...
@@ -50,7 +50,7 @@ public class AccountUtils {
}
}
//获取验证码redis key
//获取验证码redis key
public
static
String
getAuthCodeKey
(
String
mobilePhone
,
String
flag
)
{
public
String
getAuthCodeKey
(
String
mobilePhone
,
String
flag
)
{
return
Constants
.
AUTH_CODE_PREFIX
+
flag
+
"-"
+
AESUtil
.
encryptV0
(
mobilePhone
);
return
Constants
.
AUTH_CODE_PREFIX
+
flag
+
"-"
+
AESUtil
.
encryptV0
(
mobilePhone
);
}
}
...
@@ -85,7 +85,7 @@ public class AccountUtils {
...
@@ -85,7 +85,7 @@ public class AccountUtils {
logger
.
info
(
"key"
+
authCodeKey
);
logger
.
info
(
"key"
+
authCodeKey
);
logger
.
info
(
"success"
+
num
);
logger
.
info
(
"success"
+
num
);
if
(
num
==
-
1
)
{
if
(
num
==
-
1
)
{
throw
new
PicaException
(
PicaResultCode
.
RESULE_DATA_NONE
.
code
(),
"
短信验证码已失效,请重新获取
"
);
throw
new
PicaException
(
PicaResultCode
.
RESULE_DATA_NONE
.
code
(),
"
验证码错误,请重新输入
"
);
}
}
if
(
num
>
0
&&
num
<
99
)
{
if
(
num
>
0
&&
num
<
99
)
{
throw
new
PicaException
(
PicaResultCode
.
RESULE_DATA_NONE
.
code
(),
"您已注册成功,请直接登录"
);
throw
new
PicaException
(
PicaResultCode
.
RESULE_DATA_NONE
.
code
(),
"您已注册成功,请直接登录"
);
...
...
写
预览
Markdown
格式
0%
请重试
or
附加一个文件
附加文件
取消
您添加了
0
人
到此讨论。请谨慎行事。
先完成此消息的编辑!
取消
想要评论请
注册
或
登录