Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
kt-keystone
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
Matrix
kt-keystone
Commits
8fc71498
提交
8fc71498
authored
3月 11, 2022
作者:
Matrix
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
fix(缓存): 添加了测试用例接口的缓存代码
上级
04d3bc87
隐藏空白字符变更
内嵌
并排
正在显示
9 个修改的文件
包含
108 行增加
和
33 行删除
+108
-33
pom.xml
kt-base/pom.xml
+9
-0
BaseBootApplication.java
kt-base/src/main/java/org/matrix/BaseBootApplication.java
+2
-0
IDataSourceServiceImpl.java
...g/matrix/actuators/datasource/IDataSourceServiceImpl.java
+2
-1
MoveActuator.java
...src/main/java/org/matrix/actuators/move/MoveActuator.java
+23
-23
CacheConfig.java
kt-base/src/main/java/org/matrix/config/CacheConfig.java
+36
-0
pom.xml
kt-web/pom.xml
+1
-0
WebBootApplication.java
kt-web/src/main/java/org/matrix/WebBootApplication.java
+3
-1
TestCaseController.java
...va/org/matrix/autotest/controller/TestCaseController.java
+29
-5
readme.md
readme.md
+3
-3
没有找到文件。
kt-base/pom.xml
浏览文件 @
8fc71498
...
@@ -33,6 +33,15 @@
...
@@ -33,6 +33,15 @@
<version>
4.5.10
</version>
<version>
4.5.10
</version>
</dependency>
</dependency>
<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter-cache
</artifactId>
</dependency>
<dependency>
<groupId>
com.github.ben-manes.caffeine
</groupId>
<artifactId>
caffeine
</artifactId>
</dependency>
<!-- httpclient缓存-->
<!-- httpclient缓存-->
<dependency>
<dependency>
<groupId>
org.apache.httpcomponents
</groupId>
<groupId>
org.apache.httpcomponents
</groupId>
...
...
kt-base/src/main/java/org/matrix/BaseBootApplication.java
浏览文件 @
8fc71498
...
@@ -8,6 +8,7 @@ import org.springframework.beans.factory.annotation.Value;
...
@@ -8,6 +8,7 @@ import org.springframework.beans.factory.annotation.Value;
import
org.springframework.boot.CommandLineRunner
;
import
org.springframework.boot.CommandLineRunner
;
import
org.springframework.boot.SpringApplication
;
import
org.springframework.boot.SpringApplication
;
import
org.springframework.boot.autoconfigure.SpringBootApplication
;
import
org.springframework.boot.autoconfigure.SpringBootApplication
;
import
org.springframework.cache.annotation.EnableCaching
;
import
java.io.BufferedReader
;
import
java.io.BufferedReader
;
import
java.io.IOException
;
import
java.io.IOException
;
...
@@ -22,6 +23,7 @@ import java.net.Socket;
...
@@ -22,6 +23,7 @@ import java.net.Socket;
* @author matrix
* @author matrix
*/
*/
@Slf4j
@Slf4j
@EnableCaching
@SpringBootApplication
@SpringBootApplication
@MapperScan
(
basePackages
=
{
"org.matrix.database.mapper"
,
"org.matrix.zentao.mapper"
})
@MapperScan
(
basePackages
=
{
"org.matrix.database.mapper"
,
"org.matrix.zentao.mapper"
})
public
class
BaseBootApplication
implements
CommandLineRunner
{
public
class
BaseBootApplication
implements
CommandLineRunner
{
...
...
kt-base/src/main/java/org/matrix/actuators/datasource/IDataSourceServiceImpl.java
浏览文件 @
8fc71498
...
@@ -42,7 +42,8 @@ public class IDataSourceServiceImpl implements IDataSourceService {
...
@@ -42,7 +42,8 @@ public class IDataSourceServiceImpl implements IDataSourceService {
}
}
/**
/**
* 将当前使用的数据替换为参数提供的数据源,如果还没有,则会添加,如果已经有了,则不会添加
* 将当前使用的数据替换为参数提供的数据源
* 如果还没有该数据则会添加,如果已经有了,则不会添加
*
*
* @param dto 数据源信息
* @param dto 数据源信息
* @return 当前存在的数据源集合
* @return 当前存在的数据源集合
...
...
kt-base/src/main/java/org/matrix/actuators/move/MoveActuator.java
浏览文件 @
8fc71498
...
@@ -97,7 +97,7 @@ public class MoveActuator implements Actuator {
...
@@ -97,7 +97,7 @@ public class MoveActuator implements Actuator {
if
(
matcher
.
find
())
{
if
(
matcher
.
find
())
{
col
=
matcher
.
group
(
"col"
);
col
=
matcher
.
group
(
"col"
);
if
(
StringUtils
.
isEmpty
(
col
))
{
if
(
StringUtils
.
isEmpty
(
col
))
{
throw
new
GlobalException
(
"动作语法里必须包含形如${pre1.name}这样的字符串!您提供的是: "
+
dynamicString
);
throw
new
GlobalException
(
"
[行为执行器]
动作语法里必须包含形如${pre1.name}这样的字符串!您提供的是: "
+
dynamicString
);
}
}
row
=
matcher
.
group
(
"row"
);
row
=
matcher
.
group
(
"row"
);
...
@@ -114,7 +114,7 @@ public class MoveActuator implements Actuator {
...
@@ -114,7 +114,7 @@ public class MoveActuator implements Actuator {
pathResolution
=
true
;
pathResolution
=
true
;
}
}
}
else
{
}
else
{
throw
new
GlobalException
(
"提供的语法不正确!正确的语法应当是形如 ${pre1.name}[0]<$.book> 这样的,您提供的是 :"
+
dynamicString
);
throw
new
GlobalException
(
"
[行为执行器]
提供的语法不正确!正确的语法应当是形如 ${pre1.name}[0]<$.book> 这样的,您提供的是 :"
+
dynamicString
);
}
}
// 解析,解释 col、row、jp
// 解析,解释 col、row、jp
...
@@ -188,7 +188,7 @@ public class MoveActuator implements Actuator {
...
@@ -188,7 +188,7 @@ public class MoveActuator implements Actuator {
}
else
if
(
actionType
==
WAIT_ACTION
)
{
}
else
if
(
actionType
==
WAIT_ACTION
)
{
waitActionHandler
(
runtimeDetail
);
waitActionHandler
(
runtimeDetail
);
}
else
{
}
else
{
throw
new
GlobalException
(
"不支持的行为类型: "
+
actionType
);
throw
new
GlobalException
(
"
[行为执行器]
不支持的行为类型: "
+
actionType
);
}
}
log
.
info
(
"[动作执行器] 动作执行完毕"
);
log
.
info
(
"[动作执行器] 动作执行完毕"
);
...
@@ -202,6 +202,22 @@ public class MoveActuator implements Actuator {
...
@@ -202,6 +202,22 @@ public class MoveActuator implements Actuator {
resSet
=
ThreadLocal
.
withInitial
(
HashMap:
:
new
);
resSet
=
ThreadLocal
.
withInitial
(
HashMap:
:
new
);
}
}
/**
* 线程等待执行器
*
* @param runtimeDetail 要等待的时间,单位毫秒ms
*/
private
void
waitActionHandler
(
String
runtimeDetail
)
{
try
{
int
sleepMills
=
Integer
.
parseInt
(
runtimeDetail
);
Thread
.
sleep
(
sleepMills
);
}
catch
(
InterruptedException
e
)
{
log
.
error
(
"[线程异常] 线程休眠时发生异常,异常信息 : "
+
e
.
getMessage
());
}
catch
(
Exception
e
)
{
log
.
error
(
"[参数/转换异常] 执行行为时参数抓换时发生异常,异常信息 "
+
e
.
getMessage
());
}
}
/**
/**
* 将行为语法里的col部分转化为threadLocal里的key值
* 将行为语法里的col部分转化为threadLocal里的key值
*
*
...
@@ -211,39 +227,23 @@ public class MoveActuator implements Actuator {
...
@@ -211,39 +227,23 @@ public class MoveActuator implements Actuator {
private
MoveRegularObject
col2RegularObj
(
String
col
)
{
private
MoveRegularObject
col2RegularObj
(
String
col
)
{
String
[]
colArray
=
col
.
split
(
"\\."
);
String
[]
colArray
=
col
.
split
(
"\\."
);
if
(
colArray
.
length
!=
2
)
{
if
(
colArray
.
length
!=
2
)
{
throw
new
GlobalException
(
"行为语法里定位部分的语法不符合规范,您提供的部分是: "
+
col
);
throw
new
GlobalException
(
"
[行为执行器]
行为语法里定位部分的语法不符合规范,您提供的部分是: "
+
col
);
}
}
String
strategy
=
colArray
[
0
].
substring
(
0
,
3
).
toUpperCase
()
+
"_MOVE"
;
String
strategy
=
colArray
[
0
].
substring
(
0
,
3
).
toUpperCase
()
+
"_MOVE"
;
if
(!
STRATEGY_LIST
.
contains
(
strategy
))
{
if
(!
STRATEGY_LIST
.
contains
(
strategy
))
{
throw
new
GlobalException
(
"行为语法里定位部分的语法不符合规范(需要至少包含pre/mid/aft),您提供的部分是:"
+
col
);
throw
new
GlobalException
(
"
[行为执行器]
行为语法里定位部分的语法不符合规范(需要至少包含pre/mid/aft),您提供的部分是:"
+
col
);
}
}
int
actionId
;
int
actionId
;
try
{
try
{
actionId
=
Integer
.
parseInt
(
colArray
[
0
].
substring
(
3
));
actionId
=
Integer
.
parseInt
(
colArray
[
0
].
substring
(
3
));
}
catch
(
NumberFormatException
e
)
{
}
catch
(
NumberFormatException
e
)
{
throw
new
GlobalException
(
"行为语法里定位部分的语法没有提供合适的actionId!例如需要提供pre1,pre2,您提供的部分是: "
+
col
);
throw
new
GlobalException
(
"
[行为执行器]
行为语法里定位部分的语法没有提供合适的actionId!例如需要提供pre1,pre2,您提供的部分是: "
+
col
);
}
}
String
key
=
strategy
+
"_"
+
actionId
;
String
key
=
strategy
+
"_"
+
actionId
;
LogQueueRuntime
.
addNewLog
(
"行为执行器KEY值拼接完成,KEY值 = "
+
key
);
LogQueueRuntime
.
addNewLog
(
"行为执行器
]
KEY值拼接完成,KEY值 = "
+
key
);
return
new
MoveRegularObject
(
key
,
colArray
[
1
]);
return
new
MoveRegularObject
(
key
,
colArray
[
1
]);
}
}
/**
* 线程等待执行器
*
* @param runtimeDetail 要等待的时间,单位毫秒ms
*/
private
void
waitActionHandler
(
String
runtimeDetail
)
{
try
{
int
sleepMills
=
Integer
.
parseInt
(
runtimeDetail
);
Thread
.
sleep
(
sleepMills
);
}
catch
(
InterruptedException
e
)
{
log
.
error
(
"[线程异常] 线程休眠时发生异常,异常信息 : "
+
e
.
getMessage
());
}
catch
(
Exception
e
)
{
log
.
error
(
"[参数/转换异常] 执行行为时参数抓换时发生异常,异常信息 "
+
e
.
getMessage
());
}
}
/**
/**
* 用例行为解析器
* 用例行为解析器
*
*
...
...
kt-base/src/main/java/org/matrix/config/CacheConfig.java
0 → 100644
浏览文件 @
8fc71498
package
org
.
matrix
.
config
;
import
com.github.benmanes.caffeine.cache.Caffeine
;
import
org.springframework.boot.autoconfigure.cache.CacheProperties
;
import
org.springframework.cache.CacheManager
;
import
org.springframework.cache.annotation.Cacheable
;
import
org.springframework.cache.caffeine.CaffeineCacheManager
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Configuration
;
import
java.util.concurrent.TimeUnit
;
/**
* CacheConfig. 缓存组件的配置
*
* @author Matrix <xhyrzldf@gmail.com>
* @since 2022/3/10 at 3:12 PM
* Suffering is the most powerful teacher of life.
*/
@Configuration
public
class
CacheConfig
{
@Bean
public
Caffeine
caffeineConfig
(){
return
Caffeine
.
newBuilder
().
expireAfterWrite
(
60
,
TimeUnit
.
MINUTES
);
}
@Bean
public
CacheManager
cacheManager
(
Caffeine
caffeine
)
{
CaffeineCacheManager
caffeineCacheManager
=
new
CaffeineCacheManager
();
caffeineCacheManager
.
setCaffeine
(
caffeine
);
return
caffeineCacheManager
;
}
}
kt-web/pom.xml
浏览文件 @
8fc71498
...
@@ -24,6 +24,7 @@
...
@@ -24,6 +24,7 @@
<artifactId>
mybatis-plus-generator
</artifactId>
<artifactId>
mybatis-plus-generator
</artifactId>
<version>
3.5.1
</version>
<version>
3.5.1
</version>
</dependency>
</dependency>
<dependency>
<dependency>
<groupId>
junit
</groupId>
<groupId>
junit
</groupId>
<artifactId>
junit
</artifactId>
<artifactId>
junit
</artifactId>
...
...
kt-web/src/main/java/org/matrix/
App
.java
→
kt-web/src/main/java/org/matrix/
WebBootApplication
.java
浏览文件 @
8fc71498
...
@@ -2,14 +2,16 @@ package org.matrix;
...
@@ -2,14 +2,16 @@ package org.matrix;
import
org.springframework.boot.SpringApplication
;
import
org.springframework.boot.SpringApplication
;
import
org.springframework.boot.autoconfigure.SpringBootApplication
;
import
org.springframework.boot.autoconfigure.SpringBootApplication
;
import
org.springframework.cache.annotation.EnableCaching
;
/**
/**
* Hello world!
* Hello world!
*
*
* @author 27795
* @author 27795
*/
*/
@EnableCaching
@SpringBootApplication
@SpringBootApplication
public
class
App
{
public
class
WebBootApplication
{
public
static
void
main
(
String
[]
args
)
{
public
static
void
main
(
String
[]
args
)
{
SpringApplication
.
run
(
BaseBootApplication
.
class
);
SpringApplication
.
run
(
BaseBootApplication
.
class
);
}
}
...
...
kt-web/src/main/java/org/matrix/autotest/controller/TestCaseController.java
浏览文件 @
8fc71498
...
@@ -14,6 +14,10 @@ import org.matrix.database.vo.CommonResultObj;
...
@@ -14,6 +14,10 @@ import org.matrix.database.vo.CommonResultObj;
import
org.matrix.database.vo.MoveAction
;
import
org.matrix.database.vo.MoveAction
;
import
org.matrix.database.vo.TestCaseData
;
import
org.matrix.database.vo.TestCaseData
;
import
org.matrix.exception.GlobalException
;
import
org.matrix.exception.GlobalException
;
import
org.springframework.cache.annotation.CacheEvict
;
import
org.springframework.cache.annotation.CachePut
;
import
org.springframework.cache.annotation.Cacheable
;
import
org.springframework.cache.annotation.Caching
;
import
org.springframework.http.ResponseEntity
;
import
org.springframework.http.ResponseEntity
;
import
org.springframework.transaction.annotation.Transactional
;
import
org.springframework.transaction.annotation.Transactional
;
import
org.springframework.util.StringUtils
;
import
org.springframework.util.StringUtils
;
...
@@ -57,8 +61,12 @@ public class TestCaseController {
...
@@ -57,8 +61,12 @@ public class TestCaseController {
* @param projectId 项目id
* @param projectId 项目id
* @return 分页查询的结果, 用例
* @return 分页查询的结果, 用例
*/
*/
@ApiOperation
(
value
=
"分页查询用例"
)
@GetMapping
(
"/{projectId}"
)
@GetMapping
(
"/{projectId}"
)
@ApiOperation
(
value
=
"分页查询用例"
)
@Cacheable
(
cacheNames
=
"casePageCache"
,
key
=
"#pageNum + '_' + #pageSize"
,
condition
=
"#pageSize != null && #pageNum !=null"
,
unless
=
"#result.statusCodeValue != 200"
)
public
ResponseEntity
<
CommonResultObj
<
Page
<
TestCase
>>>
findPageTestCase
(
public
ResponseEntity
<
CommonResultObj
<
Page
<
TestCase
>>>
findPageTestCase
(
@RequestParam
(
defaultValue
=
"10"
)
int
pageSize
,
@RequestParam
(
defaultValue
=
"10"
)
int
pageSize
,
@RequestParam
(
defaultValue
=
"1"
)
int
pageNum
,
@RequestParam
(
defaultValue
=
"1"
)
int
pageNum
,
...
@@ -79,8 +87,9 @@ public class TestCaseController {
...
@@ -79,8 +87,9 @@ public class TestCaseController {
* @param testCaseId 用例id
* @param testCaseId 用例id
* @return {@link TestCaseData}
* @return {@link TestCaseData}
*/
*/
@ApiOperation
(
value
=
"根据用例id查,用例以及,用例下的数据组"
)
@GetMapping
(
"/testCase/{testCaseId}"
)
@GetMapping
(
"/testCase/{testCaseId}"
)
@ApiOperation
(
value
=
"根据用例id查,用例以及,用例下的数据组"
)
@Cacheable
(
cacheNames
=
"caseCache"
,
key
=
"#testCaseId"
,
condition
=
"#p0 !=null"
,
unless
=
"#result.statusCodeValue != 200"
)
public
ResponseEntity
<
CommonResultObj
<
TestCaseData
>>
findByIdTestCaseData
(
@PathVariable
Long
testCaseId
)
{
public
ResponseEntity
<
CommonResultObj
<
TestCaseData
>>
findByIdTestCaseData
(
@PathVariable
Long
testCaseId
)
{
TestCase
byId
=
testCaseService
.
getById
(
testCaseId
);
TestCase
byId
=
testCaseService
.
getById
(
testCaseId
);
if
(
byId
==
null
)
{
if
(
byId
==
null
)
{
...
@@ -101,8 +110,13 @@ public class TestCaseController {
...
@@ -101,8 +110,13 @@ public class TestCaseController {
* @param testCaseData 用例以及用例下的数据组
* @param testCaseData 用例以及用例下的数据组
* @return 添加的用例和数据组, 以及是否添加成功的提示信息
* @return 添加的用例和数据组, 以及是否添加成功的提示信息
*/
*/
@ApiOperation
(
value
=
"添加用例和数据组"
)
@PostMapping
@PostMapping
@ApiOperation
(
value
=
"添加用例和数据组"
)
@Caching
(
put
=
{
@CachePut
(
cacheNames
=
"caseCache"
,
key
=
"#result.body.data.testCase.id"
,
condition
=
"#p0 !=null"
,
unless
=
"#result.statusCodeValue != 200"
)
},
evict
=
{
@CacheEvict
(
cacheNames
=
"casePageCache"
,
allEntries
=
true
)})
public
ResponseEntity
<
CommonResultObj
<
TestCaseData
>>
insertTestCaseData
(
@RequestBody
TestCaseData
testCaseData
)
{
public
ResponseEntity
<
CommonResultObj
<
TestCaseData
>>
insertTestCaseData
(
@RequestBody
TestCaseData
testCaseData
)
{
Boolean
testCaseBoolean
=
Optional
.
of
(
testCaseService
.
saveOrUpdate
(
testCaseData
.
getTestCase
()))
Boolean
testCaseBoolean
=
Optional
.
of
(
testCaseService
.
saveOrUpdate
(
testCaseData
.
getTestCase
()))
.
orElseThrow
(
GlobalException:
:
new
);
.
orElseThrow
(
GlobalException:
:
new
);
...
@@ -128,9 +142,16 @@ public class TestCaseController {
...
@@ -128,9 +142,16 @@ public class TestCaseController {
* @param testCaseData 用例以及用例下的数据组
* @param testCaseData 用例以及用例下的数据组
* @return {@link TestCaseData}
* @return {@link TestCaseData}
*/
*/
@ApiOperation
(
value
=
"修改用例以及数据组"
)
@PutMapping
@PutMapping
@ApiOperation
(
value
=
"修改用例以及数据组"
)
@Transactional
(
rollbackFor
=
Exception
.
class
)
@Transactional
(
rollbackFor
=
Exception
.
class
)
@Caching
(
put
=
{
@CachePut
(
cacheNames
=
"caseCache"
,
key
=
"#result.body.data.testCase.id"
,
condition
=
"#p0 !=null"
,
unless
=
"#result.statusCodeValue != 200"
)
},
evict
=
{
@CacheEvict
(
cacheNames
=
"casePageCache"
,
allEntries
=
true
,
condition
=
"#p0 != null "
),
@CacheEvict
(
cacheNames
=
"caseCache"
,
key
=
"#p0.testCase.id"
,
condition
=
"#p0 != null "
)})
public
ResponseEntity
<
CommonResultObj
<
TestCaseData
>>
updateTestCaseData
(
@RequestBody
TestCaseData
testCaseData
)
{
public
ResponseEntity
<
CommonResultObj
<
TestCaseData
>>
updateTestCaseData
(
@RequestBody
TestCaseData
testCaseData
)
{
Boolean
update
=
Optional
.
of
(
testCaseService
.
updateById
(
testCaseData
.
getTestCase
()))
Boolean
update
=
Optional
.
of
(
testCaseService
.
updateById
(
testCaseData
.
getTestCase
()))
.
orElseThrow
(
GlobalException:
:
new
);
.
orElseThrow
(
GlobalException:
:
new
);
...
@@ -154,9 +175,12 @@ public class TestCaseController {
...
@@ -154,9 +175,12 @@ public class TestCaseController {
* @param testCaseId 用例id
* @param testCaseId 用例id
* @return 是否删除成功
* @return 是否删除成功
*/
*/
@ApiOperation
(
value
=
"删除行用例和数据组"
)
@DeleteMapping
(
"/{testCaseId}"
)
@DeleteMapping
(
"/{testCaseId}"
)
@ApiOperation
(
value
=
"删除行用例和数据组"
)
@Transactional
(
rollbackFor
=
Exception
.
class
)
@Transactional
(
rollbackFor
=
Exception
.
class
)
@Caching
(
evict
=
{
@CacheEvict
(
cacheNames
=
"casePageCache"
,
allEntries
=
true
,
condition
=
"#p0 != null "
),
@CacheEvict
(
cacheNames
=
"caseCache"
,
key
=
"#testCaseId"
,
condition
=
"#p0 != null"
)})
public
ResponseEntity
<
CommonResultObj
<
MoveAction
>>
deleteTestCaseData
(
@PathVariable
Long
testCaseId
)
{
public
ResponseEntity
<
CommonResultObj
<
MoveAction
>>
deleteTestCaseData
(
@PathVariable
Long
testCaseId
)
{
Boolean
testCaseBoolean
=
Optional
.
of
(
testCaseService
.
removeById
(
testCaseId
))
Boolean
testCaseBoolean
=
Optional
.
of
(
testCaseService
.
removeById
(
testCaseId
))
.
orElseThrow
(()
->
new
GlobalException
(
String
.
format
(
"没有查到指定的用例,你提供的用例id是%d"
,
testCaseId
)));
.
orElseThrow
(()
->
new
GlobalException
(
String
.
format
(
"没有查到指定的用例,你提供的用例id是%d"
,
testCaseId
)));
...
...
readme.md
浏览文件 @
8fc71498
...
@@ -261,7 +261,7 @@ parseVarByName("$name[1]") - 附带了 name 与 index0
...
@@ -261,7 +261,7 @@ parseVarByName("$name[1]") - 附带了 name 与 index0
#### 图片示例
#### 图片示例


### 测试结果(**zt_testresult**)
### 测试结果(**zt_testresult**)
...
@@ -284,4 +284,4 @@ parseVarByName("$name[1]") - 附带了 name 与 index0
...
@@ -284,4 +284,4 @@ parseVarByName("$name[1]") - 附带了 name 与 index0
#### 图片示例
#### 图片示例


\ No newline at end of file
\ No newline at end of file
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论