1
This commit is contained in:
@@ -0,0 +1,226 @@
|
||||
package com.ruoyi.jarvis.domain;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.ruoyi.common.core.domain.BaseEntity;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 腾讯文档批量推送记录
|
||||
*/
|
||||
public class TencentDocBatchPushRecord extends BaseEntity {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** 主键ID */
|
||||
private Long id;
|
||||
|
||||
/** 批次ID */
|
||||
private String batchId;
|
||||
|
||||
/** 文件ID */
|
||||
private String fileId;
|
||||
|
||||
/** 工作表ID */
|
||||
private String sheetId;
|
||||
|
||||
/** 推送类型:AUTO-自动推送,MANUAL-手动推送 */
|
||||
private String pushType;
|
||||
|
||||
/** 触发来源:DELAYED_TIMER-延迟定时器,USER-用户手动 */
|
||||
private String triggerSource;
|
||||
|
||||
/** 推送开始时间 */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date startTime;
|
||||
|
||||
/** 推送结束时间 */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date endTime;
|
||||
|
||||
/** 推送耗时(毫秒) */
|
||||
private Long durationMs;
|
||||
|
||||
/** 起始行号 */
|
||||
private Integer startRow;
|
||||
|
||||
/** 结束行号 */
|
||||
private Integer endRow;
|
||||
|
||||
/** 总行数 */
|
||||
private Integer totalRows;
|
||||
|
||||
/** 成功数量 */
|
||||
private Integer successCount;
|
||||
|
||||
/** 跳过数量 */
|
||||
private Integer skipCount;
|
||||
|
||||
/** 错误数量 */
|
||||
private Integer errorCount;
|
||||
|
||||
/** 状态:RUNNING-执行中,SUCCESS-成功,PARTIAL-部分成功,FAILED-失败 */
|
||||
private String status;
|
||||
|
||||
/** 结果消息 */
|
||||
private String resultMessage;
|
||||
|
||||
/** 错误信息 */
|
||||
private String errorMessage;
|
||||
|
||||
/** 关联的操作日志列表(非数据库字段) */
|
||||
private List<TencentDocOperationLog> operationLogs;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getBatchId() {
|
||||
return batchId;
|
||||
}
|
||||
|
||||
public void setBatchId(String batchId) {
|
||||
this.batchId = batchId;
|
||||
}
|
||||
|
||||
public String getFileId() {
|
||||
return fileId;
|
||||
}
|
||||
|
||||
public void setFileId(String fileId) {
|
||||
this.fileId = fileId;
|
||||
}
|
||||
|
||||
public String getSheetId() {
|
||||
return sheetId;
|
||||
}
|
||||
|
||||
public void setSheetId(String sheetId) {
|
||||
this.sheetId = sheetId;
|
||||
}
|
||||
|
||||
public String getPushType() {
|
||||
return pushType;
|
||||
}
|
||||
|
||||
public void setPushType(String pushType) {
|
||||
this.pushType = pushType;
|
||||
}
|
||||
|
||||
public String getTriggerSource() {
|
||||
return triggerSource;
|
||||
}
|
||||
|
||||
public void setTriggerSource(String triggerSource) {
|
||||
this.triggerSource = triggerSource;
|
||||
}
|
||||
|
||||
public Date getStartTime() {
|
||||
return startTime;
|
||||
}
|
||||
|
||||
public void setStartTime(Date startTime) {
|
||||
this.startTime = startTime;
|
||||
}
|
||||
|
||||
public Date getEndTime() {
|
||||
return endTime;
|
||||
}
|
||||
|
||||
public void setEndTime(Date endTime) {
|
||||
this.endTime = endTime;
|
||||
}
|
||||
|
||||
public Long getDurationMs() {
|
||||
return durationMs;
|
||||
}
|
||||
|
||||
public void setDurationMs(Long durationMs) {
|
||||
this.durationMs = durationMs;
|
||||
}
|
||||
|
||||
public Integer getStartRow() {
|
||||
return startRow;
|
||||
}
|
||||
|
||||
public void setStartRow(Integer startRow) {
|
||||
this.startRow = startRow;
|
||||
}
|
||||
|
||||
public Integer getEndRow() {
|
||||
return endRow;
|
||||
}
|
||||
|
||||
public void setEndRow(Integer endRow) {
|
||||
this.endRow = endRow;
|
||||
}
|
||||
|
||||
public Integer getTotalRows() {
|
||||
return totalRows;
|
||||
}
|
||||
|
||||
public void setTotalRows(Integer totalRows) {
|
||||
this.totalRows = totalRows;
|
||||
}
|
||||
|
||||
public Integer getSuccessCount() {
|
||||
return successCount;
|
||||
}
|
||||
|
||||
public void setSuccessCount(Integer successCount) {
|
||||
this.successCount = successCount;
|
||||
}
|
||||
|
||||
public Integer getSkipCount() {
|
||||
return skipCount;
|
||||
}
|
||||
|
||||
public void setSkipCount(Integer skipCount) {
|
||||
this.skipCount = skipCount;
|
||||
}
|
||||
|
||||
public Integer getErrorCount() {
|
||||
return errorCount;
|
||||
}
|
||||
|
||||
public void setErrorCount(Integer errorCount) {
|
||||
this.errorCount = errorCount;
|
||||
}
|
||||
|
||||
public String getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(String status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public String getResultMessage() {
|
||||
return resultMessage;
|
||||
}
|
||||
|
||||
public void setResultMessage(String resultMessage) {
|
||||
this.resultMessage = resultMessage;
|
||||
}
|
||||
|
||||
public String getErrorMessage() {
|
||||
return errorMessage;
|
||||
}
|
||||
|
||||
public void setErrorMessage(String errorMessage) {
|
||||
this.errorMessage = errorMessage;
|
||||
}
|
||||
|
||||
public List<TencentDocOperationLog> getOperationLogs() {
|
||||
return operationLogs;
|
||||
}
|
||||
|
||||
public void setOperationLogs(List<TencentDocOperationLog> operationLogs) {
|
||||
this.operationLogs = operationLogs;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,9 @@ public class TencentDocOperationLog extends BaseEntity {
|
||||
/** 主键ID */
|
||||
private Long id;
|
||||
|
||||
/** 批次ID(关联批量推送记录) */
|
||||
private String batchId;
|
||||
|
||||
/** 文档ID */
|
||||
private String fileId;
|
||||
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
package com.ruoyi.jarvis.mapper;
|
||||
|
||||
import com.ruoyi.jarvis.domain.TencentDocBatchPushRecord;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 腾讯文档批量推送记录 Mapper
|
||||
*/
|
||||
public interface TencentDocBatchPushRecordMapper {
|
||||
|
||||
/**
|
||||
* 插入批量推送记录
|
||||
*/
|
||||
int insertBatchPushRecord(TencentDocBatchPushRecord record);
|
||||
|
||||
/**
|
||||
* 更新批量推送记录
|
||||
*/
|
||||
int updateBatchPushRecord(TencentDocBatchPushRecord record);
|
||||
|
||||
/**
|
||||
* 根据批次ID查询
|
||||
*/
|
||||
TencentDocBatchPushRecord selectByBatchId(@Param("batchId") String batchId);
|
||||
|
||||
/**
|
||||
* 查询批量推送记录列表
|
||||
*/
|
||||
List<TencentDocBatchPushRecord> selectBatchPushRecordList(TencentDocBatchPushRecord record);
|
||||
|
||||
/**
|
||||
* 查询最近的推送记录
|
||||
*/
|
||||
List<TencentDocBatchPushRecord> selectRecentRecords(@Param("fileId") String fileId,
|
||||
@Param("limit") int limit);
|
||||
|
||||
/**
|
||||
* 查询最后一次成功的推送记录
|
||||
*/
|
||||
TencentDocBatchPushRecord selectLastSuccessRecord(@Param("fileId") String fileId,
|
||||
@Param("sheetId") String sheetId);
|
||||
}
|
||||
|
||||
@@ -37,5 +37,13 @@ public interface TencentDocOperationLogMapper {
|
||||
* @return 操作日志集合
|
||||
*/
|
||||
List<TencentDocOperationLog> selectRecentLogs(@Param("fileId") String fileId, @Param("limit") int limit);
|
||||
|
||||
/**
|
||||
* 根据批次ID查询操作日志
|
||||
*
|
||||
* @param batchId 批次ID
|
||||
* @return 操作日志集合
|
||||
*/
|
||||
List<TencentDocOperationLog> selectLogsByBatchId(@Param("batchId") String batchId);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
package com.ruoyi.jarvis.service;
|
||||
|
||||
import com.ruoyi.jarvis.domain.TencentDocBatchPushRecord;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 腾讯文档批量推送记录服务
|
||||
*/
|
||||
public interface ITencentDocBatchPushService {
|
||||
|
||||
/**
|
||||
* 创建批量推送记录
|
||||
*/
|
||||
String createBatchPushRecord(String fileId, String sheetId, String pushType,
|
||||
String triggerSource, Integer startRow, Integer endRow);
|
||||
|
||||
/**
|
||||
* 更新批量推送记录
|
||||
*/
|
||||
void updateBatchPushRecord(String batchId, String status, Integer successCount,
|
||||
Integer skipCount, Integer errorCount, String resultMessage, String errorMessage);
|
||||
|
||||
/**
|
||||
* 根据批次ID查询
|
||||
*/
|
||||
TencentDocBatchPushRecord getBatchPushRecord(String batchId);
|
||||
|
||||
/**
|
||||
* 查询批量推送记录列表(带操作日志)
|
||||
*/
|
||||
List<TencentDocBatchPushRecord> getBatchPushRecordListWithLogs(String fileId, String sheetId, Integer limit);
|
||||
|
||||
/**
|
||||
* 查询最后一次成功的推送记录
|
||||
*/
|
||||
TencentDocBatchPushRecord getLastSuccessRecord(String fileId, String sheetId);
|
||||
|
||||
/**
|
||||
* 获取推送状态和倒计时信息
|
||||
*/
|
||||
Map<String, Object> getPushStatusAndCountdown();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,159 @@
|
||||
package com.ruoyi.jarvis.service.impl;
|
||||
|
||||
import com.ruoyi.common.core.redis.RedisCache;
|
||||
import com.ruoyi.jarvis.domain.TencentDocBatchPushRecord;
|
||||
import com.ruoyi.jarvis.domain.TencentDocOperationLog;
|
||||
import com.ruoyi.jarvis.mapper.TencentDocBatchPushRecordMapper;
|
||||
import com.ruoyi.jarvis.mapper.TencentDocOperationLogMapper;
|
||||
import com.ruoyi.jarvis.service.ITencentDocBatchPushService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* 腾讯文档批量推送记录服务实现
|
||||
*/
|
||||
@Service
|
||||
public class TencentDocBatchPushServiceImpl implements ITencentDocBatchPushService {
|
||||
|
||||
@Resource
|
||||
private TencentDocBatchPushRecordMapper batchPushRecordMapper;
|
||||
|
||||
@Resource
|
||||
private TencentDocOperationLogMapper operationLogMapper;
|
||||
|
||||
@Resource
|
||||
private RedisCache redisCache;
|
||||
|
||||
private static final String DELAYED_PUSH_TASK_KEY = "tendoc:delayed_push:task_scheduled";
|
||||
private static final String DELAYED_PUSH_SCHEDULE_TIME_KEY = "tendoc:delayed_push:schedule_time";
|
||||
|
||||
@Override
|
||||
public String createBatchPushRecord(String fileId, String sheetId, String pushType,
|
||||
String triggerSource, Integer startRow, Integer endRow) {
|
||||
String batchId = UUID.randomUUID().toString().replace("-", "");
|
||||
|
||||
TencentDocBatchPushRecord record = new TencentDocBatchPushRecord();
|
||||
record.setBatchId(batchId);
|
||||
record.setFileId(fileId);
|
||||
record.setSheetId(sheetId);
|
||||
record.setPushType(pushType);
|
||||
record.setTriggerSource(triggerSource);
|
||||
record.setStartTime(new Date());
|
||||
record.setStartRow(startRow);
|
||||
record.setEndRow(endRow);
|
||||
record.setTotalRows(endRow - startRow + 1);
|
||||
record.setSuccessCount(0);
|
||||
record.setSkipCount(0);
|
||||
record.setErrorCount(0);
|
||||
record.setStatus("RUNNING");
|
||||
|
||||
batchPushRecordMapper.insertBatchPushRecord(record);
|
||||
|
||||
return batchId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBatchPushRecord(String batchId, String status, Integer successCount,
|
||||
Integer skipCount, Integer errorCount, String resultMessage, String errorMessage) {
|
||||
TencentDocBatchPushRecord record = new TencentDocBatchPushRecord();
|
||||
record.setBatchId(batchId);
|
||||
record.setEndTime(new Date());
|
||||
record.setStatus(status);
|
||||
record.setSuccessCount(successCount);
|
||||
record.setSkipCount(skipCount);
|
||||
record.setErrorCount(errorCount);
|
||||
record.setResultMessage(resultMessage);
|
||||
record.setErrorMessage(errorMessage);
|
||||
|
||||
// 计算耗时
|
||||
TencentDocBatchPushRecord existingRecord = batchPushRecordMapper.selectByBatchId(batchId);
|
||||
if (existingRecord != null && existingRecord.getStartTime() != null) {
|
||||
long durationMs = new Date().getTime() - existingRecord.getStartTime().getTime();
|
||||
record.setDurationMs(durationMs);
|
||||
}
|
||||
|
||||
batchPushRecordMapper.updateBatchPushRecord(record);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TencentDocBatchPushRecord getBatchPushRecord(String batchId) {
|
||||
TencentDocBatchPushRecord record = batchPushRecordMapper.selectByBatchId(batchId);
|
||||
if (record != null) {
|
||||
// 加载关联的操作日志
|
||||
List<TencentDocOperationLog> logs = operationLogMapper.selectLogsByBatchId(batchId);
|
||||
record.setOperationLogs(logs);
|
||||
}
|
||||
return record;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TencentDocBatchPushRecord> getBatchPushRecordListWithLogs(String fileId, String sheetId, Integer limit) {
|
||||
TencentDocBatchPushRecord query = new TencentDocBatchPushRecord();
|
||||
query.setFileId(fileId);
|
||||
query.setSheetId(sheetId);
|
||||
|
||||
List<TencentDocBatchPushRecord> records = limit != null && limit > 0
|
||||
? batchPushRecordMapper.selectRecentRecords(fileId, limit)
|
||||
: batchPushRecordMapper.selectBatchPushRecordList(query);
|
||||
|
||||
// 为每条记录加载操作日志
|
||||
for (TencentDocBatchPushRecord record : records) {
|
||||
List<TencentDocOperationLog> logs = operationLogMapper.selectLogsByBatchId(record.getBatchId());
|
||||
record.setOperationLogs(logs);
|
||||
}
|
||||
|
||||
return records;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TencentDocBatchPushRecord getLastSuccessRecord(String fileId, String sheetId) {
|
||||
TencentDocBatchPushRecord record = batchPushRecordMapper.selectLastSuccessRecord(fileId, sheetId);
|
||||
if (record != null) {
|
||||
List<TencentDocOperationLog> logs = operationLogMapper.selectLogsByBatchId(record.getBatchId());
|
||||
record.setOperationLogs(logs);
|
||||
}
|
||||
return record;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> getPushStatusAndCountdown() {
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
|
||||
// 检查是否有定时任务
|
||||
Boolean isScheduled = redisCache.getCacheObject(DELAYED_PUSH_TASK_KEY);
|
||||
Long scheduleTime = redisCache.getCacheObject(DELAYED_PUSH_SCHEDULE_TIME_KEY);
|
||||
|
||||
result.put("isScheduled", isScheduled != null && isScheduled);
|
||||
|
||||
if (isScheduled != null && isScheduled && scheduleTime != null) {
|
||||
long now = System.currentTimeMillis();
|
||||
long remainingMs = scheduleTime - now;
|
||||
|
||||
if (remainingMs > 0) {
|
||||
result.put("scheduledTime", new Date(scheduleTime));
|
||||
result.put("remainingSeconds", remainingMs / 1000);
|
||||
result.put("remainingMs", remainingMs);
|
||||
|
||||
// 格式化倒计时显示
|
||||
long minutes = remainingMs / 60000;
|
||||
long seconds = (remainingMs % 60000) / 1000;
|
||||
result.put("countdownText", String.format("%d分%d秒", minutes, seconds));
|
||||
} else {
|
||||
result.put("remainingSeconds", 0);
|
||||
result.put("remainingMs", 0);
|
||||
result.put("countdownText", "即将执行");
|
||||
}
|
||||
} else {
|
||||
result.put("scheduledTime", null);
|
||||
result.put("remainingSeconds", 0);
|
||||
result.put("remainingMs", 0);
|
||||
result.put("countdownText", "无定时任务");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,16 @@
|
||||
package com.ruoyi.jarvis.service.impl;
|
||||
|
||||
import com.ruoyi.common.core.redis.RedisCache;
|
||||
import com.ruoyi.jarvis.config.TencentDocConfig;
|
||||
import com.ruoyi.jarvis.service.ITencentDocBatchPushService;
|
||||
import com.ruoyi.jarvis.service.ITencentDocDelayedPushService;
|
||||
import com.ruoyi.jarvis.service.ITencentDocTokenService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.annotation.PreDestroy;
|
||||
@@ -33,6 +37,15 @@ public class TencentDocDelayedPushServiceImpl implements ITencentDocDelayedPushS
|
||||
|
||||
@Autowired
|
||||
private RedisCache redisCache;
|
||||
|
||||
@Autowired
|
||||
private ITencentDocBatchPushService batchPushService;
|
||||
|
||||
@Autowired
|
||||
private TencentDocConfig tencentDocConfig;
|
||||
|
||||
@Autowired
|
||||
private ITencentDocTokenService tokenService;
|
||||
|
||||
/**
|
||||
* 延迟时间(分钟),可通过配置文件修改
|
||||
@@ -237,15 +250,36 @@ public class TencentDocDelayedPushServiceImpl implements ITencentDocDelayedPushS
|
||||
/**
|
||||
* 执行批量同步
|
||||
*
|
||||
* 说明:这里通过HTTP调用本地接口,避免复杂的依赖注入
|
||||
* 说明:创建批量推送记录,然后通过HTTP调用本地接口
|
||||
*/
|
||||
private void executeBatchSync() {
|
||||
String batchId = null;
|
||||
try {
|
||||
log.info("开始执行批量同步...");
|
||||
|
||||
// 使用RestTemplate或HttpClient调用本地接口
|
||||
// 这里简化处理,直接发送HTTP请求到本地
|
||||
java.net.URL url = new java.net.URL("http://localhost:30313/jarvis-api/jarvis/tendoc/fillLogisticsByOrderNo");
|
||||
// 获取配置信息
|
||||
String fileId = tencentDocConfig.getFileId();
|
||||
String sheetId = tencentDocConfig.getSheetId();
|
||||
Integer startRow = tencentDocConfig.getStartRow();
|
||||
|
||||
if (StringUtils.isEmpty(fileId) || StringUtils.isEmpty(sheetId)) {
|
||||
log.error("腾讯文档配置不完整,无法执行批量同步");
|
||||
return;
|
||||
}
|
||||
|
||||
// 创建批量推送记录
|
||||
batchId = batchPushService.createBatchPushRecord(
|
||||
fileId,
|
||||
sheetId,
|
||||
"AUTO",
|
||||
"DELAYED_TIMER",
|
||||
startRow,
|
||||
startRow + 199 // 暂定范围
|
||||
);
|
||||
log.info("✓ 创建批量推送记录,批次ID: {}", batchId);
|
||||
|
||||
// 调用批量同步接口,传递批次ID
|
||||
java.net.URL url = new java.net.URL("http://localhost:30313/jarvis-api/jarvis/tendoc/fillLogisticsByOrderNo?batchId=" + batchId);
|
||||
java.net.HttpURLConnection conn = (java.net.HttpURLConnection) url.openConnection();
|
||||
conn.setRequestMethod("POST");
|
||||
conn.setRequestProperty("Content-Type", "application/json");
|
||||
@@ -273,10 +307,24 @@ public class TencentDocDelayedPushServiceImpl implements ITencentDocDelayedPushS
|
||||
}
|
||||
} else {
|
||||
log.error("批量同步调用失败,响应码: {}", responseCode);
|
||||
// 更新批量推送记录为失败状态
|
||||
if (batchId != null) {
|
||||
batchPushService.updateBatchPushRecord(batchId, "FAILED", 0, 0, 0,
|
||||
null, "批量同步调用失败,响应码: " + responseCode);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("执行批量同步失败", e);
|
||||
// 更新批量推送记录为失败状态
|
||||
if (batchId != null) {
|
||||
try {
|
||||
batchPushService.updateBatchPushRecord(batchId, "FAILED", 0, 0, 0,
|
||||
null, "执行批量同步失败: " + e.getMessage());
|
||||
} catch (Exception ex) {
|
||||
log.error("更新批量推送记录失败", ex);
|
||||
}
|
||||
}
|
||||
throw new RuntimeException("执行批量同步失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user