Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
D
device-back
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
1
议题
1
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
Matrix
device-back
Commits
4f01d03b
提交
4f01d03b
authored
10月 09, 2020
作者:
邓砥奕
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
[自查模块]增加自查定时任务
上级
80810f3e
显示空白字符变更
内嵌
并排
正在显示
3 个修改的文件
包含
208 行增加
和
72 行删除
+208
-72
TaskBeanConfig.java
...fig/src/main/java/com/tykj/dev/config/TaskBeanConfig.java
+13
-0
SelfCheckSchedulerTask.java
...ykj/dev/device/selfcheck/base/SelfCheckSchedulerTask.java
+61
-29
SelfCheckController.java
.../dev/device/selfcheck/controller/SelfCheckController.java
+134
-43
没有找到文件。
dev-config/src/main/java/com/tykj/dev/config/TaskBeanConfig.java
浏览文件 @
4f01d03b
package
com
.
tykj
.
dev
.
config
;
import
lombok.Data
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.scheduling.TaskScheduler
;
import
org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler
;
...
...
@@ -8,6 +9,18 @@ import org.springframework.stereotype.Component;
@Component
public
class
TaskBeanConfig
{
private
static
final
ThreadPoolTaskScheduler
THREAD_POOL_TASK_SCHEDULER
;
static
{
THREAD_POOL_TASK_SCHEDULER
=
new
ThreadPoolTaskScheduler
();
THREAD_POOL_TASK_SCHEDULER
.
setPoolSize
(
10
);
THREAD_POOL_TASK_SCHEDULER
.
initialize
();
}
public
static
ThreadPoolTaskScheduler
getThreadPoolTaskScheduler
()
{
return
THREAD_POOL_TASK_SCHEDULER
;
}
@Bean
public
TaskScheduler
taskScheduler
()
{
ThreadPoolTaskScheduler
taskScheduler
=
new
ThreadPoolTaskScheduler
();
...
...
dev-selfcheck/src/main/java/com/tykj/dev/device/selfcheck/base/SelfCheckSchedulerTask.java
浏览文件 @
4f01d03b
package
com
.
tykj
.
dev
.
device
.
selfcheck
.
base
;
import
com.tykj.dev.config.GlobalMap
;
import
com.tykj.dev.config.TaskBeanConfig
;
import
com.tykj.dev.device.task.service.TaskService
;
import
com.tykj.dev.device.task.subject.bto.TaskBto
;
import
com.tykj.dev.device.user.subject.dao.UnitsDao
;
import
com.tykj.dev.device.user.subject.entity.Units
;
import
com.tykj.dev.misc.base.BeanHelper
;
import
com.tykj.dev.misc.base.StatusEnum
;
import
com.tykj.dev.misc.utils.SpringUtils
;
import
lombok.Data
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.scheduling.annotation.Async
;
import
org.springframework.scheduling.annotation.EnableAsync
;
import
org.springframework.scheduling.annotation.Scheduled
;
import
org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler
;
import
org.springframework.scheduling.support.CronTrigger
;
import
org.springframework.stereotype.Component
;
import
java.lang.reflect.Field
;
import
java.lang.reflect.InvocationHandler
;
import
java.lang.reflect.Proxy
;
import
java.util.ArrayList
;
import
java.util.List
;
import
java.util.concurrent.ScheduledFuture
;
/**
* @author dengdiyi
*/
@Slf4j
@Component
@EnableAsync
@Data
public
class
SelfCheckSchedulerTask
{
/**
* 月度
*/
private
String
cron1
=
"0 0 0 1 1/1 ? "
;
/**
* 季度
*/
private
String
cron2
=
"0 0 0 1 3,6,9,12 ? "
;
/**
* 年度
*/
private
String
cron3
=
"0 0 0 1 1 ? *"
;
// @Async
// @Scheduled(cron = "0 0 0 1 1/1 ? ")
// public void createSelfCheckTask() {
// UnitsDao unitsDao = SpringUtils.getBean("unitsDao");
// TaskService taskService = SpringUtils.getBean("taskServiceImpl");
// if (unitsDao != null && taskService!=null) {
// List<Units> unitsList = unitsDao.findAll();
// unitsList.forEach(units -> {
// //发起待自查任务
// List<Integer> userIds = new ArrayList<>();
// userIds.add(0);
// TaskBto taskBto = new TaskBto(StatusEnum.WAIT_SELF_CHECK.id,"自查业务",null,".",0,4,units.getUnitId(),0,null,userIds);
// taskService.start(taskBto);
// });
// }
// }
private
String
cron
=
"0 0 0 1 3,6,9,12 ? "
;
private
UnitsDao
unitsDao
=
SpringUtils
.
getBean
(
"unitsDao"
);
private
TaskService
taskService
=
SpringUtils
.
getBean
(
"taskServiceImpl"
);
private
ScheduledFuture
scheduledFuture
;
public
SelfCheckSchedulerTask
()
{
scheduledFuture
=
TaskBeanConfig
.
getThreadPoolTaskScheduler
().
schedule
(
new
SelfCheckTask
(),
triggerContext
->
new
CronTrigger
(
cron
).
nextExecutionTime
(
triggerContext
));
}
public
class
SelfCheckTask
implements
Runnable
{
@Override
public
void
run
()
{
if
(
unitsDao
!=
null
&&
taskService
!=
null
)
{
List
<
Units
>
unitsList
=
unitsDao
.
findAll
();
unitsList
.
forEach
(
units
->
{
//发起待自查任务
List
<
Integer
>
userIds
=
new
ArrayList
<>();
userIds
.
add
(
0
);
TaskBto
taskBto
=
new
TaskBto
(
StatusEnum
.
WAIT_SELF_CHECK
.
id
,
"自查业务"
,
null
,
"."
,
0
,
4
,
units
.
getUnitId
(),
0
,
null
,
userIds
);
taskService
.
start
(
taskBto
);
});
}
log
.
info
(
"[自查模块]:自查定时任务执行了"
);
}
}
public
void
startTask
(){
scheduledFuture
=
TaskBeanConfig
.
getThreadPoolTaskScheduler
().
schedule
(
new
SelfCheckTask
(),
triggerContext
->
new
CronTrigger
(
cron
).
nextExecutionTime
(
triggerContext
));
}
}
dev-selfcheck/src/main/java/com/tykj/dev/device/selfcheck/controller/SelfCheckController.java
浏览文件 @
4f01d03b
...
...
@@ -13,26 +13,42 @@ import com.tykj.dev.device.selfcheck.subject.vo.*;
import
com.tykj.dev.device.task.service.TaskLogService
;
import
com.tykj.dev.device.task.service.TaskService
;
import
com.tykj.dev.device.task.subject.bto.TaskBto
;
import
com.tykj.dev.device.task.subject.bto.TaskLogBto
;
import
com.tykj.dev.device.user.subject.dao.UnitsDao
;
import
com.tykj.dev.device.user.subject.entity.Units
;
import
com.tykj.dev.device.user.subject.service.UserPublicService
;
import
com.tykj.dev.device.user.util.UserUtils
;
import
com.tykj.dev.misc.base.BusinessEnum
;
import
com.tykj.dev.misc.base.StatusEnum
;
import
com.tykj.dev.misc.exception.ApiException
;
import
com.tykj.dev.misc.utils.ResultUtil
;
import
com.tykj.dev.misc.utils.SpringUtils
;
import
com.tykj.dev.socket.MyWebSocket
;
import
io.swagger.annotations.Api
;
import
io.swagger.annotations.ApiOperation
;
import
lombok.extern.slf4j.Slf4j
;
import
org.apache.commons.lang3.time.DateUtils
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.data.domain.Page
;
import
org.springframework.http.ResponseEntity
;
import
org.springframework.scheduling.TaskScheduler
;
import
org.springframework.scheduling.Trigger
;
import
org.springframework.scheduling.TriggerContext
;
import
org.springframework.scheduling.annotation.Scheduled
;
import
org.springframework.scheduling.annotation.SchedulingConfigurer
;
import
org.springframework.scheduling.config.ScheduledTaskRegistrar
;
import
org.springframework.scheduling.config.Task
;
import
org.springframework.scheduling.support.CronTrigger
;
import
org.springframework.web.bind.annotation.*
;
import
java.lang.reflect.Field
;
import
java.lang.reflect.InvocationHandler
;
import
java.lang.reflect.Proxy
;
import
java.util.ArrayList
;
import
java.util.Date
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.concurrent.ScheduledFuture
;
/**
* @author dengdiyi
...
...
@@ -40,7 +56,8 @@ import java.util.Map;
@RestController
@RequestMapping
(
value
=
"/selfCheck"
)
@AutoDocument
@Api
(
tags
=
"自查模块"
,
description
=
"自查接口"
)
@Api
(
tags
=
"自查模块"
,
description
=
"自查接口"
)
@Slf4j
public
class
SelfCheckController
{
@Autowired
...
...
@@ -70,6 +87,9 @@ public class SelfCheckController {
@Autowired
private
MyWebSocket
myWebSocket
;
@Autowired
private
UnitsDao
unitsDao
;
/**
* 月度
*/
...
...
@@ -82,27 +102,52 @@ public class SelfCheckController {
* 年度
*/
private
String
cron3
=
"0 0 0 1 1 ? *"
;
/**
* 定时任务cron修改触发器的标志,1:月度,2:季度,3:年度(默认季度)
*/
private
int
tag
=
2
;
private
String
cron4
=
"0 0/1 * * * ? "
;
private
final
SelfCheckSchedulerTask
selfCheckSchedulerTask
=
SpringUtils
.
getBean
(
"selfCheckSchedulerTask"
);
@ApiOperation
(
value
=
"设置自查周期"
,
notes
=
"可以通过这个接口设置自查周期"
)
@PostMapping
(
value
=
"/set/cycle/{type}"
)
public
ResponseEntity
setCycle
(
@PathVariable
(
"type"
)
int
type
)
throws
NoSuchMethodException
,
IllegalAccessException
,
NoSuchFieldException
{
public
ResponseEntity
setCycle
(
@PathVariable
(
"type"
)
int
type
){
if
(
selfCheckSchedulerTask
!=
null
)
{
switch
(
type
)
{
case
1
:
setCorn
(
cron1
);
selfCheckSchedulerTask
.
setCron
(
cron1
);
ScheduledFuture
scheduledFuture
=
selfCheckSchedulerTask
.
getScheduledFuture
();
scheduledFuture
.
cancel
(
true
);
selfCheckSchedulerTask
.
startTask
();
return
ResponseEntity
.
ok
(
"自查周期更改为月度"
);
case
2
:
setCorn
(
cron2
);
selfCheckSchedulerTask
.
setCron
(
cron2
);
ScheduledFuture
scheduledFuture2
=
selfCheckSchedulerTask
.
getScheduledFuture
();
scheduledFuture2
.
cancel
(
true
);
selfCheckSchedulerTask
.
startTask
();
return
ResponseEntity
.
ok
(
"自查周期更改为季度"
);
case
3
:
setCorn
(
cron3
);
selfCheckSchedulerTask
.
setCron
(
cron3
);
ScheduledFuture
scheduledFuture3
=
selfCheckSchedulerTask
.
getScheduledFuture
();
scheduledFuture3
.
cancel
(
true
);
selfCheckSchedulerTask
.
startTask
();
return
ResponseEntity
.
ok
(
"自查周期更改为年度"
);
case
4
:
setCorn
(
"0 0/1 * * * ? "
);
selfCheckSchedulerTask
.
setCron
(
cron4
);
ScheduledFuture
scheduledFuture4
=
selfCheckSchedulerTask
.
getScheduledFuture
();
scheduledFuture4
.
cancel
(
true
);
selfCheckSchedulerTask
.
startTask
();
return
ResponseEntity
.
ok
(
"自查周期更改为每分钟"
);
default
:
return
ResponseEntity
.
ok
(
ResultUtil
.
failed
(
"设置失败:type只能为1,2,3"
));
}
}
else
{
throw
new
ApiException
(
ResultUtil
.
failed
(
"selfCheckSchedulerTask为null"
));
}
}
@ApiOperation
(
value
=
"装备比较"
,
notes
=
"可以通过这个接口发起比较装备"
)
@PostMapping
(
value
=
"/compare"
)
...
...
@@ -124,9 +169,9 @@ public class SelfCheckController {
//取交集
list1
.
retainAll
(
list2
);
//遍历应查装备
for
(
DeviceLibrary
d
:
deviceLibraryEntities
)
{
for
(
DeviceLibrary
d
:
deviceLibraryEntities
)
{
//如果在交集中,检查结果为正常
if
(
list1
.
contains
(
d
.
getRfidCardId
()))
{
if
(
list1
.
contains
(
d
.
getRfidCardId
())){
d
.
setCheckResult
(
1
);
}
//否则检查结果为丢失
...
...
@@ -135,19 +180,19 @@ public class SelfCheckController {
}
}
//遍历扫码结果
for
(
String
s
:
list2
)
{
for
(
String
s
:
list2
)
{
//如果不在交集中,则为新增
if
(!
list1
.
contains
(
s
))
{
if
(!
list1
.
contains
(
s
)){
List
<
DeviceLibrary
>
d
=
deviceLibraryDao
.
getAllByRfidCardId
(
s
);
//如果新增的为系统中存在的装备
if
(
d
.
size
()
>
0
)
{
for
(
DeviceLibrary
deviceLibraryEntity
:
d
)
{
if
(
d
.
size
()
>
0
)
{
for
(
DeviceLibrary
deviceLibraryEntity
:
d
)
{
deviceLibraryEntity
.
setCheckResult
(
2
);
resultList
.
add
(
deviceLibraryEntity
);
}
}
//如果为系统中不存在的装备,添加到newList
if
(
d
.
isEmpty
())
{
if
(
d
.
isEmpty
()){
DeviceLibrary
deviceLibraryEntity
=
new
DeviceLibrary
();
deviceLibraryEntity
.
setCheckResult
(
2
);
deviceLibraryEntity
.
setSeqNumber
(
"-"
);
...
...
@@ -162,14 +207,14 @@ public class SelfCheckController {
}
}
//在新增后面加丢失的装备
for
(
DeviceLibrary
d
:
deviceLibraryEntities
)
{
if
(
d
.
getCheckResult
()
==
0
)
{
for
(
DeviceLibrary
d
:
deviceLibraryEntities
)
{
if
(
d
.
getCheckResult
()
==
0
)
{
resultList
.
add
(
d
);
}
}
//最后加正常的装备
for
(
DeviceLibrary
d
:
deviceLibraryEntities
)
{
if
(
d
.
getCheckResult
()
==
1
)
{
for
(
DeviceLibrary
d
:
deviceLibraryEntities
)
{
if
(
d
.
getCheckResult
()
==
1
)
{
resultList
.
add
(
d
);
}
}
...
...
@@ -206,16 +251,16 @@ public class SelfCheckController {
List
<
Integer
>
userIds
=
new
ArrayList
<>();
userIds
.
add
(
userId
);
userIds
.
add
(
selfExaminationBillEntity1
.
getUserbId
());
TaskBto
taskBto
=
new
TaskBto
(
StatusEnum
.
SELF_CHECK_CONFIRM
.
id
,
"自查业务"
,
null
,
"."
,
selfExaminationBillEntity1
.
getId
(),
4
,
userUtils
.
getCurrentUnitId
(),
1
,
null
,
userIds
);
TaskBto
taskBto
=
new
TaskBto
(
StatusEnum
.
SELF_CHECK_CONFIRM
.
id
,
"自查业务"
,
null
,
"."
,
selfExaminationBillEntity1
.
getId
(),
4
,
userUtils
.
getCurrentUnitId
(),
1
,
null
,
userIds
);
TaskBto
saveEntity
=
taskService
.
start
(
taskBto
);
//存业务日志
// TaskLogBto taskLogBto = new TaskLogBto(saveEntity.getId(),"发起自查",null);
// taskLogService.addLog(taskLogBto);
//添加装备日志
for
(
String
s
:
strings
)
{
if
(
s
.
length
()
>=
2
)
{
for
(
String
s
:
strings
)
{
if
(
s
.
length
()
>=
2
)
{
Integer
id
=
Integer
.
parseInt
(
s
.
substring
(
0
,
s
.
length
()
-
1
));
DeviceLogDto
deviceLogDto
=
new
DeviceLogDto
(
id
,
"发起自查"
,
null
);
DeviceLogDto
deviceLogDto
=
new
DeviceLogDto
(
id
,
"发起自查"
,
null
);
deviceLogService
.
addLog
(
deviceLogDto
);
}
}
...
...
@@ -237,10 +282,10 @@ public class SelfCheckController {
// taskLogService.addLog(taskLogBto);
selfExaminationBillEntity
.
setCheckStatus
(
2
);
selfExaminationBillService
.
update
(
selfExaminationBillEntity
);
for
(
String
s
:
strings
)
{
if
(
s
.
length
()
>=
2
)
{
for
(
String
s
:
strings
)
{
if
(
s
.
length
()
>=
2
)
{
Integer
id
=
Integer
.
parseInt
(
s
.
substring
(
0
,
s
.
length
()
-
1
));
DeviceLogDto
deviceLogDto
=
new
DeviceLogDto
(
id
,
"自查审核成功"
,
null
);
DeviceLogDto
deviceLogDto
=
new
DeviceLogDto
(
id
,
"自查审核成功"
,
null
);
deviceLogService
.
addLog
(
deviceLogDto
);
}
}
...
...
@@ -248,22 +293,23 @@ public class SelfCheckController {
return
ResultUtil
.
success
(
"审核通过自查完成"
);
}
//审核不通过,改变账单和任务状态
if
(
selfCheckConfirmVo
.
getStatus
()
==
1
)
{
if
(
selfCheckConfirmVo
.
getStatus
()
==
1
)
{
taskService
.
update
(
taskService
.
moveToArchive
(
taskBto
));
// TaskLogBto taskLogBto = new TaskLogBto(taskBto.getId(),"自查审核失败",null);
// taskLogService.addLog(taskLogBto);
selfExaminationBillEntity
.
setCheckStatus
(
1
);
selfExaminationBillService
.
update
(
selfExaminationBillEntity
);
for
(
String
s
:
strings
)
{
if
(
s
.
length
()
>=
2
)
{
for
(
String
s
:
strings
)
{
if
(
s
.
length
()
>=
2
)
{
Integer
id
=
Integer
.
parseInt
(
s
.
substring
(
0
,
s
.
length
()
-
1
));
DeviceLogDto
deviceLogDto
=
new
DeviceLogDto
(
id
,
"自查审核失败"
,
null
);
DeviceLogDto
deviceLogDto
=
new
DeviceLogDto
(
id
,
"自查审核失败"
,
null
);
deviceLogService
.
addLog
(
deviceLogDto
);
}
}
myWebSocket
.
sendMessage1
();
return
ResultUtil
.
success
(
"自查审核失败"
);
}
else
{
}
else
{
return
ResultUtil
.
failed
(
"status只能为0或1"
);
}
}
...
...
@@ -304,12 +350,12 @@ public class SelfCheckController {
String
str4
=
selfExaminationBillEntity
.
getNewDeviceDetail
();
String
[]
split
=
str3
.
split
(
"x"
);
//添加新增不在系统的装备
if
(
str4
!=
null
)
{
if
(
str4
!=
null
)
{
//分隔字符获得rfid卡号
String
[]
split2
=
str4
.
split
(
"\\."
);
List
<
DeviceLibrary
>
newDeviceList
=
new
ArrayList
<>();
for
(
String
rfid
:
split2
)
{
if
(
rfid
.
length
()
>
0
)
{
for
(
String
rfid
:
split2
)
{
if
(
rfid
.
length
()
>
0
)
{
DeviceLibrary
d
=
new
DeviceLibrary
();
d
.
setCheckResult
(
2
);
d
.
setSeqNumber
(
"-"
);
...
...
@@ -325,10 +371,10 @@ public class SelfCheckController {
}
List
<
DeviceLibrary
>
libraryEntities1
=
new
ArrayList
<>();
//添加自查装备
for
(
String
s
:
split
)
{
if
(
s
.
length
()
>=
2
)
{
for
(
String
s
:
split
)
{
if
(
s
.
length
()
>=
2
)
{
Integer
i
=
Integer
.
parseInt
(
s
.
substring
(
0
,
s
.
length
()
-
1
));
Integer
checkResult
=
Integer
.
parseInt
(
s
.
substring
(
s
.
length
()
-
1
));
Integer
checkResult
=
Integer
.
parseInt
(
s
.
substring
(
s
.
length
()
-
1
));
DeviceLibrary
deviceLibraryEntity
=
deviceLibraryService
.
getOne
(
i
);
deviceLibraryEntity
.
setCheckResult
(
checkResult
);
libraryEntities1
.
add
(
deviceLibraryEntity
);
...
...
@@ -340,12 +386,57 @@ public class SelfCheckController {
return
ResultUtil
.
success
(
list
);
}
private
void
setCorn
(
String
cron
)
throws
NoSuchMethodException
,
NoSuchFieldException
,
IllegalAccessException
{
Scheduled
scheduled
=
SelfCheckSchedulerTask
.
class
.
getDeclaredMethod
(
"createSelfCheckTask"
).
getAnnotation
(
Scheduled
.
class
);
InvocationHandler
h
=
Proxy
.
getInvocationHandler
(
scheduled
);
Field
field
=
h
.
getClass
().
getDeclaredField
(
"memberValues"
);
field
.
setAccessible
(
true
);
Map
memberValues
=
(
Map
)
field
.
get
(
h
);
memberValues
.
put
(
"cron"
,
cron
);
}
// private void setCorn(String cron) throws NoSuchMethodException, NoSuchFieldException, IllegalAccessException {
// Scheduled scheduled = SelfCheckSchedulerTask.class.getDeclaredMethod("createSelfCheckTask").getAnnotation(Scheduled.class);
// InvocationHandler h = Proxy.getInvocationHandler(scheduled);
// Field field = h.getClass().getDeclaredField("memberValues");
// field.setAccessible(true);
// Map memberValues = (Map)field.get(h);
// memberValues.put("cron",cron);
// }
//
// /**
// * Callback allowing a {@link TaskScheduler
// * TaskScheduler} and specific {@link Task Task}
// * instances to be registered against the given the {@link ScheduledTaskRegistrar}.
// *
// * @param taskRegistrar the registrar to be configured.
// */
// @Override
// public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
// taskRegistrar.addTriggerTask(() -> {
// // 自查任务
// List<Units> unitsList = unitsDao.findAll();
// unitsList.forEach(units -> {
// //发起待自查任务
// List<Integer> userIds = new ArrayList<>();
// userIds.add(0);
// TaskBto taskBto = new TaskBto(StatusEnum.WAIT_SELF_CHECK.id,"自查业务",null,".",0,4,units.getUnitId(),0,null,userIds);
// taskService.start(taskBto);
// });
// log.info("[自查模块]定时任务执行");
// } ,(triggerContext) -> {
// CronTrigger cronTrigger;
// if (this.tag == 1) {
// log.info("[自查模块]定时任务动态修改corn表达式:" + cron1 +"(月度)");
// cronTrigger = new CronTrigger(cron1);
// }
// else if (this.tag == 2){
// log.info("[自查模块]定时任务动态修改corn表达式:" + cron2 +"(季度)");
// cronTrigger = new CronTrigger(cron2);
// }
// else if (this.tag == 3){
// log.info("[自查模块]定时任务动态修改corn表达式:" + cron3 +"(年度)");
// cronTrigger = new CronTrigger(cron3);
// }
// else if (this.tag == 4){
// log.info("[自查模块]定时任务动态修改corn表达式:" + cron4 +"(每分钟)");
// cronTrigger = new CronTrigger(cron4);
// }
// else {
// throw new ApiException(ResultUtil.failed("tag只能为1,2,3"));
// }
// return cronTrigger.nextExecutionTime(triggerContext);
// });
// }
}
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论