修改统计数据显示问题
This commit is contained in:
parent
1bf27164d3
commit
143a9e90be
|
|
@ -59,6 +59,10 @@
|
||||||
<artifactId>fastjson</artifactId>
|
<artifactId>fastjson</artifactId>
|
||||||
<version>1.2.83</version>
|
<version>1.2.83</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.ruoyi</groupId>
|
||||||
|
<artifactId>ruoyi-system</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -66,6 +66,9 @@ public class CustomerExportData implements Serializable {
|
||||||
*/
|
*/
|
||||||
private Date addDate;
|
private Date addDate;
|
||||||
|
|
||||||
|
//成交日期
|
||||||
|
private Date finishDate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 来源
|
* 来源
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -519,6 +519,20 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||||
GROUP_FIELD_MAP.put("AE组", "tagGroup18");
|
GROUP_FIELD_MAP.put("AE组", "tagGroup18");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final Map<String, String> GROUP_ATTR_MAP = new LinkedHashMap<>();
|
||||||
|
static {
|
||||||
|
GROUP_ATTR_MAP.put("N组", "tag_group1");
|
||||||
|
GROUP_ATTR_MAP.put("O组", "tag_group2");
|
||||||
|
GROUP_ATTR_MAP.put("P组", "tag_group3");
|
||||||
|
GROUP_ATTR_MAP.put("W组", "tag_group10");
|
||||||
|
GROUP_ATTR_MAP.put("X组", "tag_group11");
|
||||||
|
GROUP_ATTR_MAP.put("Y组", "tag_group12");
|
||||||
|
GROUP_ATTR_MAP.put("Z组", "tag_group13");
|
||||||
|
GROUP_ATTR_MAP.put("AA组", "tag_group14");
|
||||||
|
GROUP_ATTR_MAP.put("AC组", "tag_group16");
|
||||||
|
GROUP_ATTR_MAP.put("AD组", "tag_group17");
|
||||||
|
GROUP_ATTR_MAP.put("AE组", "tag_group18");
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* 字段反射缓存
|
* 字段反射缓存
|
||||||
*/
|
*/
|
||||||
|
|
@ -729,7 +743,6 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||||
String customerAttr = data.getTagGroup6();
|
String customerAttr = data.getTagGroup6();
|
||||||
if (customerAttr != null && !customerAttr.trim().isEmpty()) {
|
if (customerAttr != null && !customerAttr.trim().isEmpty()) {
|
||||||
stats.setTotalCustomerAttr(stats.getTotalCustomerAttr() + 1);
|
stats.setTotalCustomerAttr(stats.getTotalCustomerAttr() + 1);
|
||||||
|
|
||||||
if (customerAttr.contains("家长")) {
|
if (customerAttr.contains("家长")) {
|
||||||
stats.setParentCount(stats.getParentCount() + 1);
|
stats.setParentCount(stats.getParentCount() + 1);
|
||||||
//todo 存在订单未完成 但是有标签的场景
|
//todo 存在订单未完成 但是有标签的场景
|
||||||
|
|
@ -751,9 +764,24 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||||
if (matchesQValue(data, date) && isTimelyOrder(data)) {
|
if (matchesQValue(data, date) && isTimelyOrder(data)) {
|
||||||
stats.setStudentDailyOrderCount(stats.getStudentDailyOrderCount() + 1);
|
stats.setStudentDailyOrderCount(stats.getStudentDailyOrderCount() + 1);
|
||||||
}
|
}
|
||||||
|
} else if (customerAttr.contains("老师")) {
|
||||||
|
stats.setTeacherCount(stats.getTeacherCount() + 1);
|
||||||
|
stats.setTeacherOrderCount(stats.getTeacherOrderCount() + 1);
|
||||||
|
|
||||||
} else {
|
// 新增:N组老师出单率统计(当日)
|
||||||
stats.setUnknownAttrCount(stats.getUnknownAttrCount() + 1);
|
stats.setTeacherDailyCount(stats.getTeacherDailyCount() + 1);
|
||||||
|
if (matchesQValue(data, date) && isTimelyOrder(data)) {
|
||||||
|
stats.setTeacherDailyOrderCount(stats.getTeacherDailyOrderCount() + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
stats.setUnknownAttrCount(stats.getUnknownAttrCount() + 1);
|
||||||
|
stats.setUnkownOrderCount(stats.getUnkownOrderCount() + 1);
|
||||||
|
|
||||||
|
// 新增:N组未知出单率统计(当日)
|
||||||
|
stats.setUnkownDailyCount(stats.getUnkownDailyCount() + 1);
|
||||||
|
if (matchesQValue(data, date) && isTimelyOrder(data)) {
|
||||||
|
stats.setUnkownDailyOrderCount(stats.getUnkownDailyOrderCount() + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -825,6 +853,7 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||||
int sortNo = 0;
|
int sortNo = 0;
|
||||||
// 为每个组生成23个统计指标
|
// 为每个组生成23个统计指标
|
||||||
for (Map.Entry<String, StatisticsAccumulator.GroupStatistics> entry : accumulator.getGroupStatsMap().entrySet()) {
|
for (Map.Entry<String, StatisticsAccumulator.GroupStatistics> entry : accumulator.getGroupStatsMap().entrySet()) {
|
||||||
|
|
||||||
String groupName = entry.getKey();
|
String groupName = entry.getKey();
|
||||||
StatisticsAccumulator.GroupStatistics stats = entry.getValue();
|
StatisticsAccumulator.GroupStatistics stats = entry.getValue();
|
||||||
|
|
||||||
|
|
@ -834,7 +863,9 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||||
setIndicatorValue(corpId,indicatorMap,curDate, "成单成本(当日)", groupName, "需手工填写",(10*sortNo++));
|
setIndicatorValue(corpId,indicatorMap,curDate, "成单成本(当日)", groupName, "需手工填写",(10*sortNo++));
|
||||||
|
|
||||||
// 1. 成单数
|
// 1. 成单数
|
||||||
setIndicatorValue(corpId,indicatorMap,curDate, "成单数(当日)", groupName, String.valueOf(stats.getOrderCount()),(10*sortNo++));
|
//成单数 需要从历史的所有数据中获取 成交日期 = date的数据
|
||||||
|
Long finishCount = customerExportDataMapper.selectByFinishDate(corpId,curDate,GROUP_ATTR_MAP.get(groupName));
|
||||||
|
setIndicatorValue(corpId,indicatorMap,curDate, "成单数(当日)", groupName, String.valueOf(finishCount),(10*sortNo++));
|
||||||
|
|
||||||
// 2. 进粉数
|
// 2. 进粉数
|
||||||
setIndicatorValue(corpId,indicatorMap,curDate, "进粉数(当日)", groupName, String.valueOf(stats.getCustomerCount()),(10*sortNo++));
|
setIndicatorValue(corpId,indicatorMap,curDate, "进粉数(当日)", groupName, String.valueOf(stats.getCustomerCount()),(10*sortNo++));
|
||||||
|
|
@ -866,6 +897,11 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||||
setIndicatorValue(corpId,indicatorMap,curDate, "学生占比(当日)", groupName, studentRate,(10*sortNo++));
|
setIndicatorValue(corpId,indicatorMap,curDate, "学生占比(当日)", groupName, studentRate,(10*sortNo++));
|
||||||
setIndicatorValue(corpId,indicatorMap,curDate, "学生数量(当日)", groupName, String.valueOf(stats.getStudentCount()),(10*sortNo++),true);
|
setIndicatorValue(corpId,indicatorMap,curDate, "学生数量(当日)", groupName, String.valueOf(stats.getStudentCount()),(10*sortNo++),true);
|
||||||
|
|
||||||
|
// 8. 老师占比
|
||||||
|
String teacherRate = calculateRate(stats.getTeacherCount(), stats.getTotalCustomerAttr());
|
||||||
|
setIndicatorValue(corpId,indicatorMap,curDate, "老师占比(当日)", groupName, teacherRate,(10*sortNo++));
|
||||||
|
setIndicatorValue(corpId,indicatorMap,curDate, "老师数量(当日)", groupName, String.valueOf(stats.getTeacherCount()),(10*sortNo++),true);
|
||||||
|
|
||||||
// 9. 未知占比
|
// 9. 未知占比
|
||||||
String unknownRate = calculateRate(stats.getUnknownAttrCount(), stats.getTotalCustomerAttr());
|
String unknownRate = calculateRate(stats.getUnknownAttrCount(), stats.getTotalCustomerAttr());
|
||||||
setIndicatorValue(corpId,indicatorMap,curDate, "未知占比(当日)", groupName, unknownRate,(10*sortNo++));
|
setIndicatorValue(corpId,indicatorMap,curDate, "未知占比(当日)", groupName, unknownRate,(10*sortNo++));
|
||||||
|
|
@ -914,12 +950,12 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
// 19. 家长出单占比
|
// 19. 家长出单占比
|
||||||
String parentOrderRate = calculateRate(stats.getParentOrderCount(), stats.getParentCount());
|
String parentOrderRate = calculateRate(stats.getParentOrderCount(), stats.getParentCount());
|
||||||
setIndicatorValue(corpId,indicatorMap,curDate, "家长出单占比(当日)", groupName, parentOrderRate,(10*sortNo++));
|
setIndicatorValue(corpId,indicatorMap,curDate, "家长出单占比(当日)", groupName, parentOrderRate,(10*sortNo++),true);
|
||||||
setIndicatorValue(corpId,indicatorMap,curDate, "家长出单数量(当日)", groupName, String.valueOf(stats.getParentOrderCount()),(10*sortNo++),true);
|
setIndicatorValue(corpId,indicatorMap,curDate, "家长出单数量(当日)", groupName, String.valueOf(stats.getParentOrderCount()),(10*sortNo++),true);
|
||||||
|
|
||||||
// 20. 学生出单占比
|
// 20. 学生出单占比
|
||||||
String studentOrderRate = calculateRate(stats.getStudentOrderCount(), stats.getStudentCount());
|
String studentOrderRate = calculateRate(stats.getStudentOrderCount(), stats.getStudentCount());
|
||||||
setIndicatorValue(corpId,indicatorMap,curDate, "学生出单占比(当日)", groupName, studentOrderRate,(10*sortNo++));
|
setIndicatorValue(corpId,indicatorMap,curDate, "学生出单占比(当日)", groupName, studentOrderRate,(10*sortNo++),true);
|
||||||
setIndicatorValue(corpId,indicatorMap,curDate, "学生出单数量(当日)", groupName, String.valueOf(stats.getStudentOrderCount()),(10*sortNo++),true);
|
setIndicatorValue(corpId,indicatorMap,curDate, "学生出单数量(当日)", groupName, String.valueOf(stats.getStudentOrderCount()),(10*sortNo++),true);
|
||||||
|
|
||||||
// 21. 家长出单率(当日)
|
// 21. 家长出单率(当日)
|
||||||
|
|
|
||||||
|
|
@ -78,6 +78,10 @@ public class StatisticsAccumulator {
|
||||||
* 学生数
|
* 学生数
|
||||||
*/
|
*/
|
||||||
private int studentCount = 0;
|
private int studentCount = 0;
|
||||||
|
/**
|
||||||
|
* 老师
|
||||||
|
*/
|
||||||
|
private int teacherCount = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 未知(空白)数
|
* 未知(空白)数
|
||||||
|
|
@ -141,6 +145,13 @@ public class StatisticsAccumulator {
|
||||||
* 学生出单数
|
* 学生出单数
|
||||||
*/
|
*/
|
||||||
private int studentOrderCount = 0;
|
private int studentOrderCount = 0;
|
||||||
|
/**
|
||||||
|
* 老师出单数
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private int teacherOrderCount = 0;
|
||||||
|
|
||||||
|
private int unkownOrderCount = 0;
|
||||||
|
|
||||||
// ========== 新增:家长/学生出单率统计(当日) ==========
|
// ========== 新增:家长/学生出单率统计(当日) ==========
|
||||||
/**
|
/**
|
||||||
|
|
@ -158,10 +169,29 @@ public class StatisticsAccumulator {
|
||||||
*/
|
*/
|
||||||
private int studentDailyOrderCount = 0;
|
private int studentDailyOrderCount = 0;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 学生总数(当日进粉)- 用于出单率分母
|
* 学生总数(当日进粉)- 用于出单率分母
|
||||||
*/
|
*/
|
||||||
private int studentDailyCount = 0;
|
private int studentDailyCount = 0;
|
||||||
|
/**
|
||||||
|
* 老师总数(当日进粉)- 用于出单率分母
|
||||||
|
*/
|
||||||
|
private int teacherDailyCount = 0;
|
||||||
|
/**
|
||||||
|
* 未知总数(当日进粉)- 用于出单率分母
|
||||||
|
*/
|
||||||
|
private int unkownDailyCount = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 学生出单数(当日成交)- 满足Q列=当日 AND T列=已成交及时单9元+
|
||||||
|
*/
|
||||||
|
private int teacherDailyOrderCount = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 学生出单数(当日成交)- 满足Q列=当日 AND T列=已成交及时单9元+
|
||||||
|
*/
|
||||||
|
private int unkownDailyOrderCount = 0;
|
||||||
|
|
||||||
// ========== 成本数据 ==========
|
// ========== 成本数据 ==========
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -57,4 +57,42 @@ public interface CustomerExportDataMapper extends BaseMapper<CustomerExportData>
|
||||||
@Param("addUserAccount") String addUserAccount,
|
@Param("addUserAccount") String addUserAccount,
|
||||||
@Param("addTime") Date addTime
|
@Param("addTime") Date addTime
|
||||||
);
|
);
|
||||||
|
|
||||||
|
Long selectByFinishDate(
|
||||||
|
@Param("corpId") String corpId,@Param("date") Date date,@Param("attr") String attr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 统计客户导出数据VO数量(用于异步导出)
|
||||||
|
* @param corpId 企业ID
|
||||||
|
* @param startDate 开始日期
|
||||||
|
* @param endDate 结束日期
|
||||||
|
* @param customerName 客户名称(可选)
|
||||||
|
* @return 数据总数
|
||||||
|
*/
|
||||||
|
int countCustomerExportDataVOList(
|
||||||
|
@Param("corpId") String corpId,
|
||||||
|
@Param("startDate") Date startDate,
|
||||||
|
@Param("endDate") Date endDate,
|
||||||
|
@Param("customerName") String customerName
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分页查询客户导出数据VO列表(用于异步导出)
|
||||||
|
* @param corpId 企业ID
|
||||||
|
* @param startDate 开始日期
|
||||||
|
* @param endDate 结束日期
|
||||||
|
* @param customerName 客户名称(可选)
|
||||||
|
* @param offset 偏移量
|
||||||
|
* @param limit 每页数量
|
||||||
|
* @return 客户导出数据VO列表
|
||||||
|
*/
|
||||||
|
List<CustomerExportDataVO> selectCustomerExportDataVOListByPage(
|
||||||
|
@Param("corpId") String corpId,
|
||||||
|
@Param("startDate") Date startDate,
|
||||||
|
@Param("endDate") Date endDate,
|
||||||
|
@Param("customerName") String customerName,
|
||||||
|
@Param("offset") int offset,
|
||||||
|
@Param("limit") int limit
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -116,6 +116,7 @@ public class CustomerDataChangeTrackingService {
|
||||||
sb.append(data.getTagGroup15()).append("|");
|
sb.append(data.getTagGroup15()).append("|");
|
||||||
sb.append(data.getTagGroup16()).append("|");
|
sb.append(data.getTagGroup16()).append("|");
|
||||||
sb.append(data.getTagGroup17()).append("|");
|
sb.append(data.getTagGroup17()).append("|");
|
||||||
|
sb.append(data.getFinishDate()).append("|");
|
||||||
sb.append(data.getTagGroup18());
|
sb.append(data.getTagGroup18());
|
||||||
|
|
||||||
// 计算MD5
|
// 计算MD5
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,250 @@
|
||||||
|
package com.ruoyi.excel.wecom.service;
|
||||||
|
|
||||||
|
import com.ruoyi.common.config.RuoYiConfig;
|
||||||
|
import com.ruoyi.common.utils.DateUtils;
|
||||||
|
import com.ruoyi.excel.wecom.mapper.CustomerExportDataMapper;
|
||||||
|
import com.ruoyi.excel.wecom.vo.CustomerExportDataVO;
|
||||||
|
import com.ruoyi.system.service.ISysExportTaskService;
|
||||||
|
import org.apache.poi.ss.usermodel.*;
|
||||||
|
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.scheduling.annotation.Async;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 客户数据异步导出服务
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class CustomerExportAsyncService
|
||||||
|
{
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(CustomerExportAsyncService.class);
|
||||||
|
|
||||||
|
private static final int BATCH_SIZE = 5000;
|
||||||
|
private static final int ROW_ACCESS_WINDOW = 1000;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private CustomerExportDataMapper customerExportDataMapper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ISysExportTaskService exportTaskService;
|
||||||
|
|
||||||
|
@Async("threadPoolTaskExecutor")
|
||||||
|
public void executeExport(Long taskId, String corpId, Date startDate, Date endDate, String customerName)
|
||||||
|
{
|
||||||
|
log.info("开始执行异步导出任务,taskId: {}, corpId: {}", taskId, corpId);
|
||||||
|
String filePath = null;
|
||||||
|
String fileName = null;
|
||||||
|
File file = null;
|
||||||
|
SXSSFWorkbook workbook = null;
|
||||||
|
FileOutputStream fos = null;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
int totalCount = customerExportDataMapper.countCustomerExportDataVOList(corpId, startDate, endDate, customerName);
|
||||||
|
log.info("导出任务 taskId: {}, 总数据量: {}", taskId, totalCount);
|
||||||
|
|
||||||
|
if (totalCount == 0)
|
||||||
|
{
|
||||||
|
exportTaskService.markSuccess(taskId, "", "无数据.xlsx", 0L);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
exportTaskService.updateProgress(taskId, 0, totalCount);
|
||||||
|
|
||||||
|
String dateStr = DateUtils.dateTimeNow("yyyyMMddHHmmss");
|
||||||
|
fileName = "客户统计数据_" + dateStr + ".xlsx";
|
||||||
|
String downloadPath = RuoYiConfig.getDownloadPath();
|
||||||
|
File dir = new File(downloadPath);
|
||||||
|
if (!dir.exists())
|
||||||
|
{
|
||||||
|
dir.mkdirs();
|
||||||
|
}
|
||||||
|
filePath = downloadPath + fileName;
|
||||||
|
file = new File(filePath);
|
||||||
|
|
||||||
|
workbook = new SXSSFWorkbook(ROW_ACCESS_WINDOW);
|
||||||
|
Sheet sheet = workbook.createSheet("客户统计数据");
|
||||||
|
|
||||||
|
CellStyle headerStyle = createHeaderStyle(workbook);
|
||||||
|
CellStyle dataStyle = createDataStyle(workbook);
|
||||||
|
|
||||||
|
String[] headers = {
|
||||||
|
"客户名称", "描述", "添加人", "添加人账号", "添加人所属部门", "添加时间", "来源",
|
||||||
|
"手机", "企业", "邮箱", "地址", "职务", "电话",
|
||||||
|
"标签组1(投放)", "标签组2(公司孵化)", "标签组3(商务)", "标签组4(成交日期)", "标签组5(年级组)",
|
||||||
|
"标签组6(客户属性)", "标签组7(成交)", "标签组8(成交品牌)", "标签组9(线索通标签)", "标签组10(A1组)",
|
||||||
|
"标签组11(B1组)", "标签组12(C1组)", "标签组13(D1组)", "标签组14(E1组)", "标签组15(意向度)",
|
||||||
|
"标签组16(自然流)", "标签组17(F1组)", "标签组18(G1组)"
|
||||||
|
};
|
||||||
|
|
||||||
|
Row headerRow = sheet.createRow(0);
|
||||||
|
for (int i = 0; i < headers.length; i++)
|
||||||
|
{
|
||||||
|
Cell cell = headerRow.createCell(i);
|
||||||
|
cell.setCellValue(headers[i]);
|
||||||
|
cell.setCellStyle(headerStyle);
|
||||||
|
sheet.setColumnWidth(i, 20 * 256);
|
||||||
|
}
|
||||||
|
|
||||||
|
int processedCount = 0;
|
||||||
|
int rowIndex = 1;
|
||||||
|
int offset = 0;
|
||||||
|
|
||||||
|
while (offset < totalCount)
|
||||||
|
{
|
||||||
|
List<CustomerExportDataVO> dataList = customerExportDataMapper.selectCustomerExportDataVOListByPage(
|
||||||
|
corpId, startDate, endDate, customerName, offset, BATCH_SIZE);
|
||||||
|
|
||||||
|
if (dataList == null || dataList.isEmpty())
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (CustomerExportDataVO data : dataList)
|
||||||
|
{
|
||||||
|
Row row = sheet.createRow(rowIndex++);
|
||||||
|
fillRowData(row, data, dataStyle);
|
||||||
|
processedCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
offset += BATCH_SIZE;
|
||||||
|
|
||||||
|
exportTaskService.updateProgress(taskId, processedCount, totalCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
fos = new FileOutputStream(file);
|
||||||
|
workbook.write(fos);
|
||||||
|
fos.flush();
|
||||||
|
|
||||||
|
long fileSize = file.length();
|
||||||
|
exportTaskService.markSuccess(taskId, filePath, fileName, fileSize);
|
||||||
|
log.info("导出任务完成,taskId: {}, 文件: {}, 大小: {} bytes", taskId, fileName, fileSize);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
log.error("导出任务执行失败,taskId: {}", taskId, e);
|
||||||
|
exportTaskService.markFailed(taskId, "导出失败:" + e.getMessage());
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (fos != null)
|
||||||
|
{
|
||||||
|
fos.close();
|
||||||
|
}
|
||||||
|
if (workbook != null)
|
||||||
|
{
|
||||||
|
workbook.dispose();
|
||||||
|
workbook.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
log.error("关闭资源失败", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private CellStyle createHeaderStyle(Workbook workbook)
|
||||||
|
{
|
||||||
|
CellStyle style = workbook.createCellStyle();
|
||||||
|
style.setAlignment(HorizontalAlignment.CENTER);
|
||||||
|
style.setVerticalAlignment(VerticalAlignment.CENTER);
|
||||||
|
style.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
|
||||||
|
style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
|
||||||
|
style.setBorderRight(BorderStyle.THIN);
|
||||||
|
style.setRightBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
|
||||||
|
style.setBorderLeft(BorderStyle.THIN);
|
||||||
|
style.setLeftBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
|
||||||
|
style.setBorderTop(BorderStyle.THIN);
|
||||||
|
style.setTopBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
|
||||||
|
style.setBorderBottom(BorderStyle.THIN);
|
||||||
|
style.setBottomBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
|
||||||
|
Font font = workbook.createFont();
|
||||||
|
font.setBold(true);
|
||||||
|
font.setFontName("Arial");
|
||||||
|
font.setFontHeightInPoints((short) 10);
|
||||||
|
style.setFont(font);
|
||||||
|
return style;
|
||||||
|
}
|
||||||
|
|
||||||
|
private CellStyle createDataStyle(Workbook workbook)
|
||||||
|
{
|
||||||
|
CellStyle style = workbook.createCellStyle();
|
||||||
|
style.setAlignment(HorizontalAlignment.CENTER);
|
||||||
|
style.setVerticalAlignment(VerticalAlignment.CENTER);
|
||||||
|
style.setBorderRight(BorderStyle.THIN);
|
||||||
|
style.setRightBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
|
||||||
|
style.setBorderLeft(BorderStyle.THIN);
|
||||||
|
style.setLeftBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
|
||||||
|
style.setBorderTop(BorderStyle.THIN);
|
||||||
|
style.setTopBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
|
||||||
|
style.setBorderBottom(BorderStyle.THIN);
|
||||||
|
style.setBottomBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
|
||||||
|
Font font = workbook.createFont();
|
||||||
|
font.setFontName("Arial");
|
||||||
|
font.setFontHeightInPoints((short) 10);
|
||||||
|
style.setFont(font);
|
||||||
|
return style;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void fillRowData(Row row, CustomerExportDataVO data, CellStyle style)
|
||||||
|
{
|
||||||
|
int col = 0;
|
||||||
|
createCell(row, col++, data.getCustomerName(), style);
|
||||||
|
createCell(row, col++, data.getDescription(), style);
|
||||||
|
createCell(row, col++, data.getAddUserName(), style);
|
||||||
|
createCell(row, col++, data.getAddUserAccount(), style);
|
||||||
|
createCell(row, col++, data.getAddUserDepartment(), style);
|
||||||
|
createCell(row, col++, formatDate(data.getAddTime()), style);
|
||||||
|
createCell(row, col++, data.getSource(), style);
|
||||||
|
createCell(row, col++, data.getMobile(), style);
|
||||||
|
createCell(row, col++, data.getCompany(), style);
|
||||||
|
createCell(row, col++, data.getEmail(), style);
|
||||||
|
createCell(row, col++, data.getAddress(), style);
|
||||||
|
createCell(row, col++, data.getPosition(), style);
|
||||||
|
createCell(row, col++, data.getPhone(), style);
|
||||||
|
createCell(row, col++, data.getTagGroup1(), style);
|
||||||
|
createCell(row, col++, data.getTagGroup2(), style);
|
||||||
|
createCell(row, col++, data.getTagGroup3(), style);
|
||||||
|
createCell(row, col++, data.getTagGroup4(), style);
|
||||||
|
createCell(row, col++, data.getTagGroup5(), style);
|
||||||
|
createCell(row, col++, data.getTagGroup6(), style);
|
||||||
|
createCell(row, col++, data.getTagGroup7(), style);
|
||||||
|
createCell(row, col++, data.getTagGroup8(), style);
|
||||||
|
createCell(row, col++, data.getTagGroup9(), style);
|
||||||
|
createCell(row, col++, data.getTagGroup10(), style);
|
||||||
|
createCell(row, col++, data.getTagGroup11(), style);
|
||||||
|
createCell(row, col++, data.getTagGroup12(), style);
|
||||||
|
createCell(row, col++, data.getTagGroup13(), style);
|
||||||
|
createCell(row, col++, data.getTagGroup14(), style);
|
||||||
|
createCell(row, col++, data.getTagGroup15(), style);
|
||||||
|
createCell(row, col++, data.getTagGroup16(), style);
|
||||||
|
createCell(row, col++, data.getTagGroup17(), style);
|
||||||
|
createCell(row, col++, data.getTagGroup18(), style);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createCell(Row row, int column, String value, CellStyle style)
|
||||||
|
{
|
||||||
|
Cell cell = row.createCell(column);
|
||||||
|
cell.setCellValue(value == null ? "" : value);
|
||||||
|
cell.setCellStyle(style);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String formatDate(Date date)
|
||||||
|
{
|
||||||
|
if (date == null)
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return DateUtils.parseDateToStr("yyyy-MM-dd", date);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -235,6 +235,79 @@ public class CustomerExportService {
|
||||||
return exportData;
|
return exportData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Date parseCompleteDate(String orderDate, Date addDate) {
|
||||||
|
if (orderDate == null || orderDate.trim().isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (addDate == null) {
|
||||||
|
log.warn("parseCompleteDate: addDate is null, orderDate: {}", orderDate);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
String[] dates = orderDate.trim().split(",");
|
||||||
|
String lastDateStr = dates[dates.length - 1].trim();
|
||||||
|
log.debug("parseCompleteDate: input orderDate: {}, lastDateStr: {}", orderDate, lastDateStr);
|
||||||
|
|
||||||
|
Calendar orderCal = Calendar.getInstance();
|
||||||
|
orderCal.setTime(addDate);
|
||||||
|
orderCal.set(Calendar.HOUR_OF_DAY, 0);
|
||||||
|
orderCal.set(Calendar.MINUTE, 0);
|
||||||
|
orderCal.set(Calendar.SECOND, 0);
|
||||||
|
orderCal.set(Calendar.MILLISECOND, 0);
|
||||||
|
|
||||||
|
boolean parsed = false;
|
||||||
|
|
||||||
|
java.util.regex.Pattern fullDatePattern = java.util.regex.Pattern.compile("(\\d{4})[/\\-](\\d{1,2})[/\\-](\\d{1,2})");
|
||||||
|
java.util.regex.Matcher fullDateMatcher = fullDatePattern.matcher(lastDateStr);
|
||||||
|
if (fullDateMatcher.find()) {
|
||||||
|
int year = Integer.parseInt(fullDateMatcher.group(1));
|
||||||
|
int month = Integer.parseInt(fullDateMatcher.group(2));
|
||||||
|
int day = Integer.parseInt(fullDateMatcher.group(3));
|
||||||
|
orderCal.set(Calendar.YEAR, year);
|
||||||
|
orderCal.set(Calendar.MONTH, month - 1);
|
||||||
|
orderCal.set(Calendar.DAY_OF_MONTH, day);
|
||||||
|
parsed = true;
|
||||||
|
log.info("parseCompleteDate: matched full date pattern, input: {}, result: {}-{}-{}", lastDateStr, year, month, day);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!parsed) {
|
||||||
|
java.util.regex.Pattern monthDayPattern = java.util.regex.Pattern.compile("^(\\d{1,2})[.\\-/](\\d{1,2})");
|
||||||
|
java.util.regex.Matcher monthDayMatcher = monthDayPattern.matcher(lastDateStr);
|
||||||
|
if (monthDayMatcher.find()) {
|
||||||
|
int month = Integer.parseInt(monthDayMatcher.group(1));
|
||||||
|
int day = Integer.parseInt(monthDayMatcher.group(2));
|
||||||
|
orderCal.set(Calendar.MONTH, month - 1);
|
||||||
|
orderCal.set(Calendar.DAY_OF_MONTH, day);
|
||||||
|
Calendar tempCal = Calendar.getInstance();
|
||||||
|
tempCal.setTime(addDate);
|
||||||
|
tempCal.set(Calendar.MONTH, month - 1);
|
||||||
|
tempCal.set(Calendar.DAY_OF_MONTH, day);
|
||||||
|
tempCal.set(Calendar.HOUR_OF_DAY, 0);
|
||||||
|
tempCal.set(Calendar.MINUTE, 0);
|
||||||
|
tempCal.set(Calendar.SECOND, 0);
|
||||||
|
tempCal.set(Calendar.MILLISECOND, 0);
|
||||||
|
if (tempCal.getTime().before(addDate)) {
|
||||||
|
orderCal.add(Calendar.YEAR, 1);
|
||||||
|
}
|
||||||
|
parsed = true;
|
||||||
|
log.info("parseCompleteDate: matched month-day pattern, input: {}, result: {}-{}-{}", lastDateStr, orderCal.get(Calendar.YEAR), month, day);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!parsed) {
|
||||||
|
log.warn("parseCompleteDate: no pattern matched, input: {}", lastDateStr);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return orderCal.getTime();
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("parseCompleteDate error, orderDate: {}, addDate: {}", orderDate, addDate, e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 处理客户标签,按标签组分类填充到对应字段
|
* 处理客户标签,按标签组分类填充到对应字段
|
||||||
*
|
*
|
||||||
|
|
@ -277,8 +350,7 @@ public class CustomerExportService {
|
||||||
* @param tagNames 标签名称(逗号分隔)
|
* @param tagNames 标签名称(逗号分隔)
|
||||||
*/
|
*/
|
||||||
private void fillTagGroupField(CustomerExportData exportData, String groupName, String tagNames) {
|
private void fillTagGroupField(CustomerExportData exportData, String groupName, String tagNames) {
|
||||||
// 根据标签组名称映射到对应字段
|
|
||||||
// 这里的映射关系需要根据实际业务调整
|
|
||||||
if (groupName.contains("投放")) {
|
if (groupName.contains("投放")) {
|
||||||
exportData.setTagGroup1(tagNames);
|
exportData.setTagGroup1(tagNames);
|
||||||
} else if (groupName.contains("公司孵化")) {
|
} else if (groupName.contains("公司孵化")) {
|
||||||
|
|
@ -287,12 +359,15 @@ public class CustomerExportService {
|
||||||
exportData.setTagGroup3(tagNames);
|
exportData.setTagGroup3(tagNames);
|
||||||
} else if (groupName.contains("成交日期")) {
|
} else if (groupName.contains("成交日期")) {
|
||||||
exportData.setTagGroup4(tagNames);
|
exportData.setTagGroup4(tagNames);
|
||||||
|
Date finishDate = parseCompleteDate(tagNames, exportData.getAddTime());
|
||||||
|
exportData.setFinishDate(finishDate);
|
||||||
} else if (groupName.contains("年级组")) {
|
} else if (groupName.contains("年级组")) {
|
||||||
exportData.setTagGroup5(tagNames);
|
exportData.setTagGroup5(tagNames);
|
||||||
} else if (groupName.contains("客户属性")) {
|
} else if (groupName.contains("客户属性")) {
|
||||||
exportData.setTagGroup6(tagNames);
|
exportData.setTagGroup6(tagNames);
|
||||||
} else if (groupName.contains("成交") && !groupName.contains("日期") && !groupName.contains("品牌")) {
|
} else if (groupName.contains("成交") && !groupName.contains("日期") && !groupName.contains("品牌")) {
|
||||||
exportData.setTagGroup7(tagNames);
|
exportData.setTagGroup7(tagNames);
|
||||||
|
|
||||||
} else if (groupName.contains("成交品牌")) {
|
} else if (groupName.contains("成交品牌")) {
|
||||||
exportData.setTagGroup8(tagNames);
|
exportData.setTagGroup8(tagNames);
|
||||||
} else if (groupName.contains("线索通")) {
|
} else if (groupName.contains("线索通")) {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,22 @@
|
||||||
<?xml version="1.0" encoding="UTF-8" ?>
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
<mapper namespace="com.ruoyi.excel.wecom.mapper.CustomerExportDataMapper">
|
<mapper namespace="com.ruoyi.excel.wecom.mapper.CustomerExportDataMapper">
|
||||||
|
<select id="countCustomerExportDataVOList" resultType="int">
|
||||||
|
SELECT count(1)
|
||||||
|
FROM customer_export_data
|
||||||
|
<where>
|
||||||
|
corp_id = #{corpId}
|
||||||
|
<if test="startDate != null">
|
||||||
|
AND add_time >= #{startDate}
|
||||||
|
</if>
|
||||||
|
<if test="endDate != null">
|
||||||
|
AND add_time <= #{endDate}
|
||||||
|
</if>
|
||||||
|
<if test="customerName != null">
|
||||||
|
AND customer_name like concat('%',#{customerName},'%')
|
||||||
|
</if>
|
||||||
|
</where>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
|
||||||
<select id="getDistinctDate" resultType="java.util.Date">
|
<select id="getDistinctDate" resultType="java.util.Date">
|
||||||
|
|
@ -120,4 +136,116 @@
|
||||||
LIMIT 1
|
LIMIT 1
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
<select id="selectByFinishDate" resultType="java.lang.Long">
|
||||||
|
select count(1) from customer_export_data
|
||||||
|
WHERE
|
||||||
|
corp_id = #{corpId} and finish_date = #{date}
|
||||||
|
<if test="attr != null and attr != '' and attr == 'tag_group1'">
|
||||||
|
AND tag_group1 is not null
|
||||||
|
</if>
|
||||||
|
<if test="attr != null and attr != '' and attr == 'tag_group2'">
|
||||||
|
AND tag_group2 is not null
|
||||||
|
</if>
|
||||||
|
<if test="attr != null and attr != '' and attr == 'tag_group3'">
|
||||||
|
AND tag_group3 is not null
|
||||||
|
</if>
|
||||||
|
<if test="attr != null and attr != '' and attr == 'tag_group4'">
|
||||||
|
AND tag_group4 is not null
|
||||||
|
</if>
|
||||||
|
<if test="attr != null and attr != '' and attr == 'tag_group5'">
|
||||||
|
AND tag_group5 is not null
|
||||||
|
</if>
|
||||||
|
<if test="attr != null and attr != '' and attr == 'tag_group6'">
|
||||||
|
AND tag_group6 is not null
|
||||||
|
</if>
|
||||||
|
<if test="attr != null and attr != '' and attr == 'tag_group7'">
|
||||||
|
AND tag_group7 is not null
|
||||||
|
</if>
|
||||||
|
<if test="attr != null and attr != '' and attr == 'tag_group8'">
|
||||||
|
AND tag_group8 is not null
|
||||||
|
</if>
|
||||||
|
<if test="attr != null and attr != '' and attr == 'tag_group9'">
|
||||||
|
AND tag_group9 is not null
|
||||||
|
</if>
|
||||||
|
<if test="attr != null and attr != '' and attr == 'tag_group10'">
|
||||||
|
AND tag_group10 is not null
|
||||||
|
</if>
|
||||||
|
<if test="attr != null and attr != '' and attr == 'tag_group11'">
|
||||||
|
AND tag_group11 is not null
|
||||||
|
</if>
|
||||||
|
<if test="attr != null and attr != '' and attr == 'tag_group12'">
|
||||||
|
AND tag_group12 is not null
|
||||||
|
</if>
|
||||||
|
<if test="attr != null and attr != '' and attr == 'tag_group13'">
|
||||||
|
AND tag_group13 is not null
|
||||||
|
</if>
|
||||||
|
<if test="attr != null and attr != '' and attr == 'tag_group14'">
|
||||||
|
AND tag_group14 is not null
|
||||||
|
</if>
|
||||||
|
<if test="attr != null and attr != '' and attr == 'tag_group15'">
|
||||||
|
AND tag_group15 is not null
|
||||||
|
</if>
|
||||||
|
<if test="attr != null and attr != '' and attr == 'tag_group16'">
|
||||||
|
AND tag_group16 is not null
|
||||||
|
</if>
|
||||||
|
<if test="attr != null and attr != '' and attr == 'tag_group17'">
|
||||||
|
AND tag_group17 is not null
|
||||||
|
</if>
|
||||||
|
<if test="attr != null and attr != '' and attr == 'tag_group18'">
|
||||||
|
AND tag_group18 is not null
|
||||||
|
</if>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<!-- 分页查询客户导出数据VO列表(用于异步导出) -->
|
||||||
|
<select id="selectCustomerExportDataVOListByPage" resultType="com.ruoyi.excel.wecom.vo.CustomerExportDataVO">
|
||||||
|
SELECT
|
||||||
|
customer_name as customerName,
|
||||||
|
description,
|
||||||
|
add_user_name as addUserName,
|
||||||
|
add_user_account as addUserAccount,
|
||||||
|
add_user_department as addUserDepartment,
|
||||||
|
add_time as addTime,
|
||||||
|
add_date as addDate,
|
||||||
|
source,
|
||||||
|
mobile,
|
||||||
|
company,
|
||||||
|
email,
|
||||||
|
address,
|
||||||
|
position,
|
||||||
|
phone,
|
||||||
|
tag_group1 as tagGroup1,
|
||||||
|
tag_group2 as tagGroup2,
|
||||||
|
tag_group3 as tagGroup3,
|
||||||
|
tag_group4 as tagGroup4,
|
||||||
|
tag_group5 as tagGroup5,
|
||||||
|
tag_group6 as tagGroup6,
|
||||||
|
tag_group7 as tagGroup7,
|
||||||
|
tag_group8 as tagGroup8,
|
||||||
|
tag_group9 as tagGroup9,
|
||||||
|
tag_group10 as tagGroup10,
|
||||||
|
tag_group11 as tagGroup11,
|
||||||
|
tag_group12 as tagGroup12,
|
||||||
|
tag_group13 as tagGroup13,
|
||||||
|
tag_group14 as tagGroup14,
|
||||||
|
tag_group15 as tagGroup15,
|
||||||
|
tag_group16 as tagGroup16,
|
||||||
|
tag_group17 as tagGroup17,
|
||||||
|
tag_group18 as tagGroup18
|
||||||
|
FROM customer_export_data
|
||||||
|
<where>
|
||||||
|
corp_id = #{corpId}
|
||||||
|
<if test="startDate != null">
|
||||||
|
AND add_time >= #{startDate}
|
||||||
|
</if>
|
||||||
|
<if test="endDate != null">
|
||||||
|
AND add_time <= #{endDate}
|
||||||
|
</if>
|
||||||
|
<if test="customerName != null">
|
||||||
|
AND customer_name like concat('%',#{customerName},'%')
|
||||||
|
</if>
|
||||||
|
</where>
|
||||||
|
ORDER BY add_time DESC
|
||||||
|
LIMIT #{limit} OFFSET #{offset}
|
||||||
|
</select>
|
||||||
|
|
||||||
</mapper>
|
</mapper>
|
||||||
|
|
|
||||||
|
|
@ -2,19 +2,26 @@ package com.ruoyi.web.controller.wocom;
|
||||||
|
|
||||||
import com.ruoyi.common.annotation.Log;
|
import com.ruoyi.common.annotation.Log;
|
||||||
import com.ruoyi.common.core.controller.BaseController;
|
import com.ruoyi.common.core.controller.BaseController;
|
||||||
|
import com.ruoyi.common.core.domain.AjaxResult;
|
||||||
import com.ruoyi.common.core.page.TableDataInfo;
|
import com.ruoyi.common.core.page.TableDataInfo;
|
||||||
import com.ruoyi.common.enums.BusinessType;
|
import com.ruoyi.common.enums.BusinessType;
|
||||||
import com.ruoyi.common.utils.CorpContextHolder;
|
import com.ruoyi.common.utils.CorpContextHolder;
|
||||||
import com.ruoyi.common.utils.poi.ExcelUtil;
|
import com.ruoyi.common.utils.poi.ExcelUtil;
|
||||||
import com.ruoyi.excel.wecom.domain.CustomerExportData;
|
import com.ruoyi.excel.wecom.domain.CustomerExportData;
|
||||||
|
import com.ruoyi.excel.wecom.service.CustomerExportAsyncService;
|
||||||
import com.ruoyi.excel.wecom.service.ICustomerExportDataService;
|
import com.ruoyi.excel.wecom.service.ICustomerExportDataService;
|
||||||
import com.ruoyi.excel.wecom.vo.CustomerExportDataVO;
|
import com.ruoyi.excel.wecom.vo.CustomerExportDataVO;
|
||||||
|
import com.ruoyi.system.domain.SysExportTask;
|
||||||
|
import com.ruoyi.system.service.ISysExportTaskService;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.format.annotation.DateTimeFormat;
|
import org.springframework.format.annotation.DateTimeFormat;
|
||||||
import org.springframework.security.access.prepost.PreAuthorize;
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.File;
|
||||||
|
import java.net.URLEncoder;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
|
@ -23,11 +30,17 @@ import java.util.List;
|
||||||
*/
|
*/
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/wecom/customerExport")
|
@RequestMapping("/wecom/customerExport")
|
||||||
public class CustomerExportDataController extends BaseController {
|
public class CustomerExportDataController extends BaseController
|
||||||
|
{
|
||||||
@Autowired
|
@Autowired
|
||||||
private ICustomerExportDataService customerExportDataService;
|
private ICustomerExportDataService customerExportDataService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private CustomerExportAsyncService customerExportAsyncService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ISysExportTaskService exportTaskService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询客户统计数据列表
|
* 查询客户统计数据列表
|
||||||
*/
|
*/
|
||||||
|
|
@ -36,16 +49,17 @@ public class CustomerExportDataController extends BaseController {
|
||||||
public TableDataInfo list(
|
public TableDataInfo list(
|
||||||
@RequestParam(value = "startDate", required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") Date startDate,
|
@RequestParam(value = "startDate", required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") Date startDate,
|
||||||
@RequestParam(value = "endDate", required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") Date endDate,
|
@RequestParam(value = "endDate", required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") Date endDate,
|
||||||
@RequestParam(value = "customerName", required = false) String customerName) {
|
@RequestParam(value = "customerName", required = false) String customerName)
|
||||||
|
{
|
||||||
String corpId = CorpContextHolder.getCurrentCorpId();
|
String corpId = CorpContextHolder.getCurrentCorpId();
|
||||||
|
|
||||||
startPage();
|
startPage();
|
||||||
List<CustomerExportData> list = customerExportDataService.selectCustomerExportDataList(corpId,startDate, endDate, customerName);
|
List<CustomerExportData> list = customerExportDataService.selectCustomerExportDataList(corpId, startDate, endDate, customerName);
|
||||||
return getDataTable(list);
|
return getDataTable(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 导出客户统计数据列表
|
* 导出客户统计数据列表(同步方式,保留兼容)
|
||||||
*/
|
*/
|
||||||
@PreAuthorize("@ss.hasPermi('wecom:customerExport:export')")
|
@PreAuthorize("@ss.hasPermi('wecom:customerExport:export')")
|
||||||
@Log(title = "客户统计数据", businessType = BusinessType.EXPORT)
|
@Log(title = "客户统计数据", businessType = BusinessType.EXPORT)
|
||||||
|
|
@ -53,13 +67,149 @@ public class CustomerExportDataController extends BaseController {
|
||||||
public void export(HttpServletResponse response,
|
public void export(HttpServletResponse response,
|
||||||
@RequestParam(value = "startDate", required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") Date startDate,
|
@RequestParam(value = "startDate", required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") Date startDate,
|
||||||
@RequestParam(value = "endDate", required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") Date endDate,
|
@RequestParam(value = "endDate", required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") Date endDate,
|
||||||
@RequestParam(value = "customerName", required = false) String customerName) {
|
@RequestParam(value = "customerName", required = false) String customerName)
|
||||||
|
{
|
||||||
String corpId = CorpContextHolder.getCurrentCorpId();
|
String corpId = CorpContextHolder.getCurrentCorpId();
|
||||||
|
|
||||||
List<CustomerExportDataVO> list = customerExportDataService.selectCustomerExportDataVOList(corpId,startDate, endDate, customerName);
|
List<CustomerExportDataVO> list = customerExportDataService.selectCustomerExportDataVOList(corpId, startDate, endDate, customerName);
|
||||||
ExcelUtil<CustomerExportDataVO> util = new ExcelUtil<>(CustomerExportDataVO.class);
|
ExcelUtil<CustomerExportDataVO> util = new ExcelUtil<>(CustomerExportDataVO.class);
|
||||||
util.exportExcel(response, list, "客户统计数据");
|
util.exportExcel(response, list, "客户统计数据");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 异步导出客户统计数据列表
|
||||||
|
*/
|
||||||
|
@PreAuthorize("@ss.hasPermi('wecom:customerExport:export')")
|
||||||
|
@Log(title = "客户统计数据-异步导出", businessType = BusinessType.EXPORT)
|
||||||
|
@PostMapping("/exportAsync")
|
||||||
|
public AjaxResult exportAsync(
|
||||||
|
@RequestParam(value = "startDate", required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") Date startDate,
|
||||||
|
@RequestParam(value = "endDate", required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") Date endDate,
|
||||||
|
@RequestParam(value = "customerName", required = false) String customerName)
|
||||||
|
{
|
||||||
|
String corpId = CorpContextHolder.getCurrentCorpId();
|
||||||
|
|
||||||
|
SysExportTask task = new SysExportTask();
|
||||||
|
task.setTaskName("客户统计数据导出");
|
||||||
|
task.setTaskType("customer_export");
|
||||||
|
task.setCorpId(corpId);
|
||||||
|
task.setCreateBy(getUsername());
|
||||||
|
|
||||||
|
Long taskId = exportTaskService.createExportTask(task);
|
||||||
|
|
||||||
|
customerExportAsyncService.executeExport(taskId, corpId, startDate, endDate, customerName);
|
||||||
|
|
||||||
|
return AjaxResult.success("导出任务已创建,请稍后查看进度", taskId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询导出任务状态
|
||||||
|
*/
|
||||||
|
@PreAuthorize("@ss.hasPermi('wecom:customerExport:export')")
|
||||||
|
@GetMapping("/export/status/{taskId}")
|
||||||
|
public AjaxResult getExportStatus(@PathVariable Long taskId)
|
||||||
|
{
|
||||||
|
SysExportTask task = exportTaskService.selectExportTaskById(taskId);
|
||||||
|
if (task == null)
|
||||||
|
{
|
||||||
|
return AjaxResult.error("任务不存在");
|
||||||
|
}
|
||||||
|
return AjaxResult.success(task);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 下载导出文件
|
||||||
|
*/
|
||||||
|
@PreAuthorize("@ss.hasPermi('wecom:customerExport:export')")
|
||||||
|
@GetMapping("/export/download/{taskId}")
|
||||||
|
public void downloadExportFile(@PathVariable Long taskId, HttpServletResponse response)
|
||||||
|
{
|
||||||
|
SysExportTask task = exportTaskService.selectExportTaskById(taskId);
|
||||||
|
if (task == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!SysExportTask.STATUS_SUCCESS.equals(task.getStatus()))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String filePath = task.getFilePath();
|
||||||
|
if (filePath == null || filePath.isEmpty())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
File file = new File(filePath);
|
||||||
|
if (!file.exists())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||||
|
response.setCharacterEncoding("utf-8");
|
||||||
|
String fileName = URLEncoder.encode(task.getFileName(), StandardCharsets.UTF_8.toString()).replaceAll("\\+", "%20");
|
||||||
|
response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ";filename*=utf-8''" + fileName);
|
||||||
|
response.setHeader("Content-Length", String.valueOf(file.length()));
|
||||||
|
|
||||||
|
java.io.FileInputStream fis = new java.io.FileInputStream(file);
|
||||||
|
java.io.OutputStream os = response.getOutputStream();
|
||||||
|
byte[] buffer = new byte[4096];
|
||||||
|
int bytesRead;
|
||||||
|
while ((bytesRead = fis.read(buffer)) != -1)
|
||||||
|
{
|
||||||
|
os.write(buffer, 0, bytesRead);
|
||||||
|
}
|
||||||
|
fis.close();
|
||||||
|
os.flush();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
logger.error("下载文件失败", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询导出任务列表
|
||||||
|
*/
|
||||||
|
@PreAuthorize("@ss.hasPermi('wecom:customerExport:export')")
|
||||||
|
@GetMapping("/export/list")
|
||||||
|
public TableDataInfo exportTaskList(SysExportTask task)
|
||||||
|
{
|
||||||
|
String corpId = CorpContextHolder.getCurrentCorpId();
|
||||||
|
task.setCorpId(corpId);
|
||||||
|
task.setCreateBy(getUsername());
|
||||||
|
startPage();
|
||||||
|
List<SysExportTask> list = exportTaskService.selectExportTaskList(task);
|
||||||
|
return getDataTable(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除导出任务
|
||||||
|
*/
|
||||||
|
@PreAuthorize("@ss.hasPermi('wecom:customerExport:export')")
|
||||||
|
@Log(title = "客户统计数据-删除导出任务", businessType = BusinessType.DELETE)
|
||||||
|
@DeleteMapping("/export/{taskId}")
|
||||||
|
public AjaxResult deleteExportTask(@PathVariable Long taskId)
|
||||||
|
{
|
||||||
|
SysExportTask task = exportTaskService.selectExportTaskById(taskId);
|
||||||
|
if (task == null)
|
||||||
|
{
|
||||||
|
return AjaxResult.error("任务不存在");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (task.getFilePath() != null && !task.getFilePath().isEmpty())
|
||||||
|
{
|
||||||
|
File file = new File(task.getFilePath());
|
||||||
|
if (file.exists())
|
||||||
|
{
|
||||||
|
file.delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return toAjax(exportTaskService.deleteExportTaskById(taskId));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,209 @@
|
||||||
|
package com.ruoyi.system.domain;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.annotation.JSONField;
|
||||||
|
import com.ruoyi.common.annotation.Excel;
|
||||||
|
import com.ruoyi.common.annotation.Excel.ColumnType;
|
||||||
|
import com.ruoyi.common.core.domain.BaseEntity;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导出任务表 sys_export_task
|
||||||
|
*/
|
||||||
|
public class SysExportTask extends BaseEntity
|
||||||
|
{
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
public static final String STATUS_PENDING = "0";
|
||||||
|
public static final String STATUS_PROCESSING = "1";
|
||||||
|
public static final String STATUS_SUCCESS = "2";
|
||||||
|
public static final String STATUS_FAILED = "3";
|
||||||
|
|
||||||
|
@Excel(name = "任务ID", cellType = ColumnType.NUMERIC)
|
||||||
|
private Long taskId;
|
||||||
|
|
||||||
|
@Excel(name = "任务名称")
|
||||||
|
private String taskName;
|
||||||
|
|
||||||
|
@Excel(name = "任务类型")
|
||||||
|
private String taskType;
|
||||||
|
|
||||||
|
private String corpId;
|
||||||
|
|
||||||
|
private String queryParams;
|
||||||
|
|
||||||
|
@Excel(name = "状态", readConverterExp = "0=待处理,1=处理中,2=成功,3=失败")
|
||||||
|
private String status;
|
||||||
|
|
||||||
|
@Excel(name = "进度")
|
||||||
|
private Integer progress;
|
||||||
|
|
||||||
|
@Excel(name = "总数据量")
|
||||||
|
private Integer totalCount;
|
||||||
|
|
||||||
|
@Excel(name = "已处理数量")
|
||||||
|
private Integer processedCount;
|
||||||
|
|
||||||
|
private String filePath;
|
||||||
|
|
||||||
|
@Excel(name = "文件名")
|
||||||
|
private String fileName;
|
||||||
|
|
||||||
|
private Long fileSize;
|
||||||
|
|
||||||
|
private String errorMsg;
|
||||||
|
|
||||||
|
@JSONField(format = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
@Excel(name = "完成时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
private Date finishTime;
|
||||||
|
|
||||||
|
public Long getTaskId()
|
||||||
|
{
|
||||||
|
return taskId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTaskId(Long taskId)
|
||||||
|
{
|
||||||
|
this.taskId = taskId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTaskName()
|
||||||
|
{
|
||||||
|
return taskName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTaskName(String taskName)
|
||||||
|
{
|
||||||
|
this.taskName = taskName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTaskType()
|
||||||
|
{
|
||||||
|
return taskType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTaskType(String taskType)
|
||||||
|
{
|
||||||
|
this.taskType = taskType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCorpId()
|
||||||
|
{
|
||||||
|
return corpId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCorpId(String corpId)
|
||||||
|
{
|
||||||
|
this.corpId = corpId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getQueryParams()
|
||||||
|
{
|
||||||
|
return queryParams;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setQueryParams(String params)
|
||||||
|
{
|
||||||
|
this.queryParams = params;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getStatus()
|
||||||
|
{
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStatus(String status)
|
||||||
|
{
|
||||||
|
this.status = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getProgress()
|
||||||
|
{
|
||||||
|
return progress;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setProgress(Integer progress)
|
||||||
|
{
|
||||||
|
this.progress = progress;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getTotalCount()
|
||||||
|
{
|
||||||
|
return totalCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTotalCount(Integer totalCount)
|
||||||
|
{
|
||||||
|
this.totalCount = totalCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getProcessedCount()
|
||||||
|
{
|
||||||
|
return processedCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setProcessedCount(Integer processedCount)
|
||||||
|
{
|
||||||
|
this.processedCount = processedCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFilePath()
|
||||||
|
{
|
||||||
|
return filePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFilePath(String filePath)
|
||||||
|
{
|
||||||
|
this.filePath = filePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFileName()
|
||||||
|
{
|
||||||
|
return fileName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFileName(String fileName)
|
||||||
|
{
|
||||||
|
this.fileName = fileName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getFileSize()
|
||||||
|
{
|
||||||
|
return fileSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFileSize(Long fileSize)
|
||||||
|
{
|
||||||
|
this.fileSize = fileSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getErrorMsg()
|
||||||
|
{
|
||||||
|
return errorMsg;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setErrorMsg(String errorMsg)
|
||||||
|
{
|
||||||
|
this.errorMsg = errorMsg;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getFinishTime()
|
||||||
|
{
|
||||||
|
return finishTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFinishTime(Date finishTime)
|
||||||
|
{
|
||||||
|
this.finishTime = finishTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isFinished()
|
||||||
|
{
|
||||||
|
return STATUS_SUCCESS.equals(status) || STATUS_FAILED.equals(status);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isSuccess()
|
||||||
|
{
|
||||||
|
return STATUS_SUCCESS.equals(status);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,66 @@
|
||||||
|
package com.ruoyi.system.mapper;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import com.ruoyi.system.domain.SysExportTask;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导出任务 数据层
|
||||||
|
*/
|
||||||
|
public interface SysExportTaskMapper
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 新增导出任务
|
||||||
|
*
|
||||||
|
* @param task 导出任务对象
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
public int insertExportTask(SysExportTask task);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改导出任务
|
||||||
|
*
|
||||||
|
* @param task 导出任务对象
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
public int updateExportTask(SysExportTask task);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据ID查询导出任务
|
||||||
|
*
|
||||||
|
* @param taskId 任务ID
|
||||||
|
* @return 导出任务对象
|
||||||
|
*/
|
||||||
|
public SysExportTask selectExportTaskById(Long taskId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询导出任务列表
|
||||||
|
*
|
||||||
|
* @param task 导出任务对象
|
||||||
|
* @return 导出任务集合
|
||||||
|
*/
|
||||||
|
public List<SysExportTask> selectExportTaskList(SysExportTask task);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除导出任务
|
||||||
|
*
|
||||||
|
* @param taskId 任务ID
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
public int deleteExportTaskById(Long taskId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量删除导出任务
|
||||||
|
*
|
||||||
|
* @param taskIds 任务ID数组
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
public int deleteExportTaskByIds(Long[] taskIds);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询过期的导出任务
|
||||||
|
*
|
||||||
|
* @param expireDays 过期天数
|
||||||
|
* @return 导出任务集合
|
||||||
|
*/
|
||||||
|
public List<SysExportTask> selectExpiredExportTasks(int expireDays);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,93 @@
|
||||||
|
package com.ruoyi.system.service;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import com.ruoyi.system.domain.SysExportTask;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导出任务Service接口
|
||||||
|
*/
|
||||||
|
public interface ISysExportTaskService
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 创建导出任务
|
||||||
|
*
|
||||||
|
* @param task 导出任务对象
|
||||||
|
* @return 任务ID
|
||||||
|
*/
|
||||||
|
public Long createExportTask(SysExportTask task);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新导出任务
|
||||||
|
*
|
||||||
|
* @param task 导出任务对象
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
public int updateExportTask(SysExportTask task);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据ID查询导出任务
|
||||||
|
*
|
||||||
|
* @param taskId 任务ID
|
||||||
|
* @return 导出任务对象
|
||||||
|
*/
|
||||||
|
public SysExportTask selectExportTaskById(Long taskId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询导出任务列表
|
||||||
|
*
|
||||||
|
* @param task 导出任务对象
|
||||||
|
* @return 导出任务集合
|
||||||
|
*/
|
||||||
|
public List<SysExportTask> selectExportTaskList(SysExportTask task);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除导出任务
|
||||||
|
*
|
||||||
|
* @param taskId 任务ID
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
public int deleteExportTaskById(Long taskId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量删除导出任务
|
||||||
|
*
|
||||||
|
* @param taskIds 任务ID数组
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
public int deleteExportTaskByIds(Long[] taskIds);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新任务进度
|
||||||
|
*
|
||||||
|
* @param taskId 任务ID
|
||||||
|
* @param processedCount 已处理数量
|
||||||
|
* @param totalCount 总数量
|
||||||
|
*/
|
||||||
|
public void updateProgress(Long taskId, int processedCount, int totalCount);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 标记任务成功
|
||||||
|
*
|
||||||
|
* @param taskId 任务ID
|
||||||
|
* @param filePath 文件路径
|
||||||
|
* @param fileName 文件名
|
||||||
|
* @param fileSize 文件大小
|
||||||
|
*/
|
||||||
|
public void markSuccess(Long taskId, String filePath, String fileName, Long fileSize);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 标记任务失败
|
||||||
|
*
|
||||||
|
* @param taskId 任务ID
|
||||||
|
* @param errorMsg 错误信息
|
||||||
|
*/
|
||||||
|
public void markFailed(Long taskId, String errorMsg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询过期的导出任务
|
||||||
|
*
|
||||||
|
* @param expireDays 过期天数
|
||||||
|
* @return 导出任务集合
|
||||||
|
*/
|
||||||
|
public List<SysExportTask> selectExpiredExportTasks(int expireDays);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,107 @@
|
||||||
|
package com.ruoyi.system.service.impl;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import com.ruoyi.common.utils.DateUtils;
|
||||||
|
import com.ruoyi.system.domain.SysExportTask;
|
||||||
|
import com.ruoyi.system.mapper.SysExportTaskMapper;
|
||||||
|
import com.ruoyi.system.service.ISysExportTaskService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导出任务Service业务层处理
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class SysExportTaskServiceImpl implements ISysExportTaskService
|
||||||
|
{
|
||||||
|
@Autowired
|
||||||
|
private SysExportTaskMapper exportTaskMapper;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Long createExportTask(SysExportTask task)
|
||||||
|
{
|
||||||
|
task.setStatus(SysExportTask.STATUS_PENDING);
|
||||||
|
task.setProgress(0);
|
||||||
|
task.setCreateTime(DateUtils.getNowDate());
|
||||||
|
exportTaskMapper.insertExportTask(task);
|
||||||
|
return task.getTaskId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int updateExportTask(SysExportTask task)
|
||||||
|
{
|
||||||
|
return exportTaskMapper.updateExportTask(task);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SysExportTask selectExportTaskById(Long taskId)
|
||||||
|
{
|
||||||
|
return exportTaskMapper.selectExportTaskById(taskId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<SysExportTask> selectExportTaskList(SysExportTask task)
|
||||||
|
{
|
||||||
|
return exportTaskMapper.selectExportTaskList(task);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int deleteExportTaskById(Long taskId)
|
||||||
|
{
|
||||||
|
return exportTaskMapper.deleteExportTaskById(taskId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int deleteExportTaskByIds(Long[] taskIds)
|
||||||
|
{
|
||||||
|
return exportTaskMapper.deleteExportTaskByIds(taskIds);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateProgress(Long taskId, int processedCount, int totalCount)
|
||||||
|
{
|
||||||
|
SysExportTask task = new SysExportTask();
|
||||||
|
task.setTaskId(taskId);
|
||||||
|
task.setProcessedCount(processedCount);
|
||||||
|
task.setTotalCount(totalCount);
|
||||||
|
if (totalCount > 0)
|
||||||
|
{
|
||||||
|
int progress = (int) ((processedCount * 100.0) / totalCount);
|
||||||
|
task.setProgress(Math.min(progress, 99));
|
||||||
|
}
|
||||||
|
task.setStatus(SysExportTask.STATUS_PROCESSING);
|
||||||
|
exportTaskMapper.updateExportTask(task);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void markSuccess(Long taskId, String filePath, String fileName, Long fileSize)
|
||||||
|
{
|
||||||
|
SysExportTask task = new SysExportTask();
|
||||||
|
task.setTaskId(taskId);
|
||||||
|
task.setStatus(SysExportTask.STATUS_SUCCESS);
|
||||||
|
task.setProgress(100);
|
||||||
|
task.setFilePath(filePath);
|
||||||
|
task.setFileName(fileName);
|
||||||
|
task.setFileSize(fileSize);
|
||||||
|
task.setFinishTime(new Date());
|
||||||
|
exportTaskMapper.updateExportTask(task);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void markFailed(Long taskId, String errorMsg)
|
||||||
|
{
|
||||||
|
SysExportTask task = new SysExportTask();
|
||||||
|
task.setTaskId(taskId);
|
||||||
|
task.setStatus(SysExportTask.STATUS_FAILED);
|
||||||
|
task.setErrorMsg(errorMsg);
|
||||||
|
task.setFinishTime(new Date());
|
||||||
|
exportTaskMapper.updateExportTask(task);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<SysExportTask> selectExpiredExportTasks(int expireDays)
|
||||||
|
{
|
||||||
|
return exportTaskMapper.selectExpiredExportTasks(expireDays);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,134 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<!DOCTYPE mapper
|
||||||
|
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||||
|
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
|
<mapper namespace="com.ruoyi.system.mapper.SysExportTaskMapper">
|
||||||
|
|
||||||
|
<resultMap type="com.ruoyi.system.domain.SysExportTask" id="SysExportTaskResult">
|
||||||
|
<id property="taskId" column="task_id" />
|
||||||
|
<result property="taskName" column="task_name" />
|
||||||
|
<result property="taskType" column="task_type" />
|
||||||
|
<result property="corpId" column="corp_id" />
|
||||||
|
<result property="queryParams" column="query_params" />
|
||||||
|
<result property="status" column="status" />
|
||||||
|
<result property="progress" column="progress" />
|
||||||
|
<result property="totalCount" column="total_count" />
|
||||||
|
<result property="processedCount" column="processed_count" />
|
||||||
|
<result property="filePath" column="file_path" />
|
||||||
|
<result property="fileName" column="file_name" />
|
||||||
|
<result property="fileSize" column="file_size" />
|
||||||
|
<result property="errorMsg" column="error_msg" />
|
||||||
|
<result property="createBy" column="create_by" />
|
||||||
|
<result property="createTime" column="create_time" />
|
||||||
|
<result property="finishTime" column="finish_time" />
|
||||||
|
</resultMap>
|
||||||
|
|
||||||
|
<sql id="selectExportTaskVo">
|
||||||
|
select task_id, task_name, task_type, corp_id, query_params, status, progress, total_count, processed_count,
|
||||||
|
file_path, file_name, file_size, error_msg, create_by, create_time, finish_time
|
||||||
|
from sys_export_task
|
||||||
|
</sql>
|
||||||
|
|
||||||
|
<select id="selectExportTaskById" parameterType="Long" resultMap="SysExportTaskResult">
|
||||||
|
<include refid="selectExportTaskVo"/>
|
||||||
|
where task_id = #{taskId}
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="selectExportTaskList" parameterType="com.ruoyi.system.domain.SysExportTask" resultMap="SysExportTaskResult">
|
||||||
|
<include refid="selectExportTaskVo"/>
|
||||||
|
<where>
|
||||||
|
<if test="taskName != null and taskName != ''">
|
||||||
|
AND task_name like concat('%', #{taskName}, '%')
|
||||||
|
</if>
|
||||||
|
<if test="taskType != null and taskType != ''">
|
||||||
|
AND task_type = #{taskType}
|
||||||
|
</if>
|
||||||
|
<if test="corpId != null and corpId != ''">
|
||||||
|
AND corp_id = #{corpId}
|
||||||
|
</if>
|
||||||
|
<if test="status != null and status != ''">
|
||||||
|
AND status = #{status}
|
||||||
|
</if>
|
||||||
|
<if test="createBy != null and createBy != ''">
|
||||||
|
AND create_by = #{createBy}
|
||||||
|
</if>
|
||||||
|
</where>
|
||||||
|
order by create_time desc
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="selectExpiredExportTasks" parameterType="int" resultMap="SysExportTaskResult">
|
||||||
|
<include refid="selectExportTaskVo"/>
|
||||||
|
where status in ('2', '3')
|
||||||
|
and create_time < date_sub(now(), interval #{expireDays} day)
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<insert id="insertExportTask" parameterType="com.ruoyi.system.domain.SysExportTask" useGeneratedKeys="true" keyProperty="taskId">
|
||||||
|
insert into sys_export_task
|
||||||
|
<trim prefix="(" suffix=")" suffixOverrides=",">
|
||||||
|
<if test="taskName != null and taskName != ''">task_name,</if>
|
||||||
|
<if test="taskType != null and taskType != ''">task_type,</if>
|
||||||
|
<if test="corpId != null and corpId != ''">corp_id,</if>
|
||||||
|
<if test="queryParams != null">query_params,</if>
|
||||||
|
<if test="status != null and status != ''">status,</if>
|
||||||
|
<if test="progress != null">progress,</if>
|
||||||
|
<if test="totalCount != null">total_count,</if>
|
||||||
|
<if test="processedCount != null">processed_count,</if>
|
||||||
|
<if test="filePath != null and filePath != ''">file_path,</if>
|
||||||
|
<if test="fileName != null and fileName != ''">file_name,</if>
|
||||||
|
<if test="fileSize != null">file_size,</if>
|
||||||
|
<if test="errorMsg != null">error_msg,</if>
|
||||||
|
<if test="createBy != null and createBy != ''">create_by,</if>
|
||||||
|
<if test="createTime != null">create_time,</if>
|
||||||
|
<if test="finishTime != null">finish_time,</if>
|
||||||
|
</trim>
|
||||||
|
<trim prefix="values (" suffix=")" suffixOverrides=",">
|
||||||
|
<if test="taskName != null and taskName != ''">#{taskName},</if>
|
||||||
|
<if test="taskType != null and taskType != ''">#{taskType},</if>
|
||||||
|
<if test="corpId != null and corpId != ''">#{corpId},</if>
|
||||||
|
<if test="queryParams != null">#{queryParams},</if>
|
||||||
|
<if test="status != null and status != ''">#{status},</if>
|
||||||
|
<if test="progress != null">#{progress},</if>
|
||||||
|
<if test="totalCount != null">#{totalCount},</if>
|
||||||
|
<if test="processedCount != null">#{processedCount},</if>
|
||||||
|
<if test="filePath != null and filePath != ''">#{filePath},</if>
|
||||||
|
<if test="fileName != null and fileName != ''">#{fileName},</if>
|
||||||
|
<if test="fileSize != null">#{fileSize},</if>
|
||||||
|
<if test="errorMsg != null">#{errorMsg},</if>
|
||||||
|
<if test="createBy != null and createBy != ''">#{createBy},</if>
|
||||||
|
<if test="createTime != null">#{createTime},</if>
|
||||||
|
<if test="finishTime != null">#{finishTime},</if>
|
||||||
|
</trim>
|
||||||
|
</insert>
|
||||||
|
|
||||||
|
<update id="updateExportTask" parameterType="com.ruoyi.system.domain.SysExportTask">
|
||||||
|
update sys_export_task
|
||||||
|
<set>
|
||||||
|
<if test="taskName != null and taskName != ''">task_name = #{taskName},</if>
|
||||||
|
<if test="taskType != null and taskType != ''">task_type = #{taskType},</if>
|
||||||
|
<if test="corpId != null and corpId != ''">corp_id = #{corpId},</if>
|
||||||
|
<if test="queryParams != null">query_params = #{queryParams},</if>
|
||||||
|
<if test="status != null and status != ''">status = #{status},</if>
|
||||||
|
<if test="progress != null">progress = #{progress},</if>
|
||||||
|
<if test="totalCount != null">total_count = #{totalCount},</if>
|
||||||
|
<if test="processedCount != null">processed_count = #{processedCount},</if>
|
||||||
|
<if test="filePath != null">file_path = #{filePath},</if>
|
||||||
|
<if test="fileName != null">file_name = #{fileName},</if>
|
||||||
|
<if test="fileSize != null">file_size = #{fileSize},</if>
|
||||||
|
<if test="errorMsg != null">error_msg = #{errorMsg},</if>
|
||||||
|
<if test="finishTime != null">finish_time = #{finishTime},</if>
|
||||||
|
</set>
|
||||||
|
where task_id = #{taskId}
|
||||||
|
</update>
|
||||||
|
|
||||||
|
<delete id="deleteExportTaskById" parameterType="Long">
|
||||||
|
delete from sys_export_task where task_id = #{taskId}
|
||||||
|
</delete>
|
||||||
|
|
||||||
|
<delete id="deleteExportTaskByIds" parameterType="Long">
|
||||||
|
delete from sys_export_task where task_id in
|
||||||
|
<foreach item="taskId" collection="array" open="(" separator="," close=")">
|
||||||
|
#{taskId}
|
||||||
|
</foreach>
|
||||||
|
</delete>
|
||||||
|
|
||||||
|
</mapper>
|
||||||
|
|
@ -52,3 +52,37 @@ export function exportCustomerExport(query) {
|
||||||
responseType: 'blob'
|
responseType: 'blob'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 异步导出客户导出数据
|
||||||
|
export function exportAsync(query) {
|
||||||
|
return request({
|
||||||
|
url: '/wecom/customerExport/exportAsync',
|
||||||
|
method: 'post',
|
||||||
|
params: query
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询导出任务状态
|
||||||
|
export function getExportStatus(taskId) {
|
||||||
|
return request({
|
||||||
|
url: '/wecom/customerExport/export/status/' + taskId,
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询导出任务列表
|
||||||
|
export function listExportTask(query) {
|
||||||
|
return request({
|
||||||
|
url: '/wecom/customerExport/export/list',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除导出任务
|
||||||
|
export function delExportTask(taskId) {
|
||||||
|
return request({
|
||||||
|
url: '/wecom/customerExport/export/' + taskId,
|
||||||
|
method: 'delete'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,27 @@
|
||||||
size="mini"
|
size="mini"
|
||||||
@click="handleExport"
|
@click="handleExport"
|
||||||
v-hasPermi="['wecom:customerExport:export']"
|
v-hasPermi="['wecom:customerExport:export']"
|
||||||
>导出</el-button>
|
>同步导出</el-button>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
plain
|
||||||
|
icon="el-icon-download"
|
||||||
|
size="mini"
|
||||||
|
@click="handleAsyncExport"
|
||||||
|
v-hasPermi="['wecom:customerExport:export']"
|
||||||
|
>异步导出</el-button>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button
|
||||||
|
type="info"
|
||||||
|
plain
|
||||||
|
icon="el-icon-tickets"
|
||||||
|
size="mini"
|
||||||
|
@click="showExportTaskDialog"
|
||||||
|
v-hasPermi="['wecom:customerExport:export']"
|
||||||
|
>导出任务</el-button>
|
||||||
</el-col>
|
</el-col>
|
||||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||||
</el-row>
|
</el-row>
|
||||||
|
|
@ -99,45 +119,105 @@
|
||||||
:limit.sync="queryParams.pageSize"
|
:limit.sync="queryParams.pageSize"
|
||||||
@pagination="getList"
|
@pagination="getList"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<!-- 导出任务对话框 -->
|
||||||
|
<el-dialog title="导出任务列表" :visible.sync="taskDialogVisible" width="800px" append-to-body>
|
||||||
|
<el-table v-loading="taskLoading" :data="taskList">
|
||||||
|
<el-table-column label="任务ID" align="center" prop="taskId" width="80" />
|
||||||
|
<el-table-column label="任务名称" align="center" prop="taskName" width="150" />
|
||||||
|
<el-table-column label="状态" align="center" prop="status" width="100">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-tag :type="getStatusType(scope.row.status)">{{ getStatusLabel(scope.row.status) }}</el-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="进度" align="center" prop="progress" width="150">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-progress
|
||||||
|
:percentage="scope.row.progress || 0"
|
||||||
|
:status="scope.row.status === '2' ? 'success' : scope.row.status === '3' ? 'exception' : ''"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="文件大小" align="center" prop="fileSize" width="100">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<span>{{ formatFileSize(scope.row.fileSize) }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="创建时间" align="center" prop="createTime" width="160">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<span>{{ parseTime(scope.row.createTime) }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="操作" align="center" width="150" fixed="right">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-button
|
||||||
|
size="mini"
|
||||||
|
type="text"
|
||||||
|
icon="el-icon-download"
|
||||||
|
@click="handleDownload(scope.row)"
|
||||||
|
:disabled="scope.row.status !== '2'"
|
||||||
|
>下载</el-button>
|
||||||
|
<el-button
|
||||||
|
size="mini"
|
||||||
|
type="text"
|
||||||
|
icon="el-icon-delete"
|
||||||
|
@click="handleDeleteTask(scope.row)"
|
||||||
|
>删除</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<pagination
|
||||||
|
v-show="taskTotal>0"
|
||||||
|
:total="taskTotal"
|
||||||
|
:page.sync="taskQueryParams.pageNum"
|
||||||
|
:limit.sync="taskQueryParams.pageSize"
|
||||||
|
@pagination="getTaskList"
|
||||||
|
/>
|
||||||
|
</el-dialog>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { listCustomerExport, exportCustomerExport } from "@/api/wecom/customerExport"
|
import { listCustomerExport, exportAsync, getExportStatus, listExportTask, delExportTask } from "@/api/wecom/customerExport"
|
||||||
|
import { getToken } from "@/utils/auth"
|
||||||
|
import axios from 'axios'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "CustomerExport",
|
name: "CustomerExport",
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
// 遮罩层
|
|
||||||
loading: true,
|
loading: true,
|
||||||
// 选中数组
|
|
||||||
ids: [],
|
ids: [],
|
||||||
// 非单个禁用
|
|
||||||
single: true,
|
single: true,
|
||||||
// 非多个禁用
|
|
||||||
multiple: true,
|
multiple: true,
|
||||||
// 显示搜索条件
|
|
||||||
showSearch: true,
|
showSearch: true,
|
||||||
// 总条数
|
|
||||||
total: 0,
|
total: 0,
|
||||||
// 客户导出数据表格数据
|
|
||||||
dataList: [],
|
dataList: [],
|
||||||
// 查询参数
|
|
||||||
queryParams: {
|
queryParams: {
|
||||||
pageNum: 1,
|
pageNum: 1,
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
startDate: undefined,
|
startDate: undefined,
|
||||||
endDate: undefined,
|
endDate: undefined,
|
||||||
customerName: undefined
|
customerName: undefined
|
||||||
}
|
},
|
||||||
|
taskDialogVisible: false,
|
||||||
|
taskLoading: false,
|
||||||
|
taskList: [],
|
||||||
|
taskTotal: 0,
|
||||||
|
taskQueryParams: {
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 10
|
||||||
|
},
|
||||||
|
pollingTimers: {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
this.getList()
|
this.getList()
|
||||||
},
|
},
|
||||||
|
beforeDestroy() {
|
||||||
|
Object.values(this.pollingTimers).forEach(timer => clearTimeout(timer))
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
/** 查询客户导出数据列表 */
|
|
||||||
getList() {
|
getList() {
|
||||||
this.loading = true
|
this.loading = true
|
||||||
listCustomerExport(this.queryParams).then(response => {
|
listCustomerExport(this.queryParams).then(response => {
|
||||||
|
|
@ -146,27 +226,115 @@ export default {
|
||||||
this.loading = false
|
this.loading = false
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
/** 搜索按钮操作 */
|
|
||||||
handleQuery() {
|
handleQuery() {
|
||||||
this.queryParams.pageNum = 1
|
this.queryParams.pageNum = 1
|
||||||
this.getList()
|
this.getList()
|
||||||
},
|
},
|
||||||
/** 重置按钮操作 */
|
|
||||||
resetQuery() {
|
resetQuery() {
|
||||||
this.resetForm("queryForm")
|
this.resetForm("queryForm")
|
||||||
this.handleQuery()
|
this.handleQuery()
|
||||||
},
|
},
|
||||||
// 多选框选中数据
|
|
||||||
handleSelectionChange(selection) {
|
handleSelectionChange(selection) {
|
||||||
this.ids = selection.map(item => item.id)
|
this.ids = selection.map(item => item.id)
|
||||||
this.single = selection.length !== 1
|
this.single = selection.length !== 1
|
||||||
this.multiple = !selection.length
|
this.multiple = !selection.length
|
||||||
},
|
},
|
||||||
/** 导出按钮操作 */
|
|
||||||
handleExport() {
|
handleExport() {
|
||||||
this.download('/wecom/customerExport/export', {
|
this.download('/wecom/customerExport/export', {
|
||||||
...this.queryParams
|
...this.queryParams
|
||||||
}, `客户列表数据_${new Date().getTime()}.xlsx`)
|
}, `客户列表数据_${new Date().getTime()}.xlsx`)
|
||||||
|
},
|
||||||
|
handleAsyncExport() {
|
||||||
|
const params = {
|
||||||
|
startDate: this.queryParams.startDate,
|
||||||
|
endDate: this.queryParams.endDate,
|
||||||
|
customerName: this.queryParams.customerName
|
||||||
|
}
|
||||||
|
exportAsync(params).then(response => {
|
||||||
|
this.$modal.msgSuccess("导出任务已创建,请稍后在导出任务列表中查看")
|
||||||
|
const taskId = response.data
|
||||||
|
this.startPolling(taskId)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
startPolling(taskId) {
|
||||||
|
const poll = () => {
|
||||||
|
getExportStatus(taskId).then(response => {
|
||||||
|
const task = response.data
|
||||||
|
if (task.status === '2') {
|
||||||
|
this.$modal.msgSuccess(`导出任务完成,文件:${task.fileName}`)
|
||||||
|
delete this.pollingTimers[taskId]
|
||||||
|
} else if (task.status === '3') {
|
||||||
|
this.$modal.msgError(`导出任务失败:${task.errorMsg}`)
|
||||||
|
delete this.pollingTimers[taskId]
|
||||||
|
} else {
|
||||||
|
this.pollingTimers[taskId] = setTimeout(poll, 2000)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
this.pollingTimers[taskId] = setTimeout(poll, 2000)
|
||||||
|
},
|
||||||
|
showExportTaskDialog() {
|
||||||
|
this.taskDialogVisible = true
|
||||||
|
this.getTaskList()
|
||||||
|
},
|
||||||
|
getTaskList() {
|
||||||
|
this.taskLoading = true
|
||||||
|
listExportTask(this.taskQueryParams).then(response => {
|
||||||
|
this.taskList = response.rows
|
||||||
|
this.taskTotal = response.total
|
||||||
|
this.taskLoading = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
getStatusType(status) {
|
||||||
|
const map = {
|
||||||
|
'0': 'info',
|
||||||
|
'1': 'warning',
|
||||||
|
'2': 'success',
|
||||||
|
'3': 'danger'
|
||||||
|
}
|
||||||
|
return map[status] || 'info'
|
||||||
|
},
|
||||||
|
getStatusLabel(status) {
|
||||||
|
const map = {
|
||||||
|
'0': '待处理',
|
||||||
|
'1': '处理中',
|
||||||
|
'2': '已完成',
|
||||||
|
'3': '失败'
|
||||||
|
}
|
||||||
|
return map[status] || '未知'
|
||||||
|
},
|
||||||
|
formatFileSize(bytes) {
|
||||||
|
if (!bytes) return '-'
|
||||||
|
if (bytes < 1024) return bytes + ' B'
|
||||||
|
if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(2) + ' KB'
|
||||||
|
return (bytes / (1024 * 1024)).toFixed(2) + ' MB'
|
||||||
|
},
|
||||||
|
handleDownload(row) {
|
||||||
|
const url = process.env.VUE_APP_BASE_API + '/wecom/customerExport/export/download/' + row.taskId
|
||||||
|
axios({
|
||||||
|
method: 'get',
|
||||||
|
url: url,
|
||||||
|
responseType: 'blob',
|
||||||
|
headers: { 'Authorization': 'Bearer ' + getToken() }
|
||||||
|
}).then((res) => {
|
||||||
|
const blob = new Blob([res.data], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' })
|
||||||
|
const link = document.createElement('a')
|
||||||
|
link.href = window.URL.createObjectURL(blob)
|
||||||
|
link.download = row.fileName || '导出文件.xlsx'
|
||||||
|
link.click()
|
||||||
|
window.URL.revokeObjectURL(link.href)
|
||||||
|
}).catch((error) => {
|
||||||
|
console.error('下载失败', error)
|
||||||
|
this.$modal.msgError('下载失败,请重试')
|
||||||
|
})
|
||||||
|
},
|
||||||
|
handleDeleteTask(row) {
|
||||||
|
this.$modal.confirm('是否确认删除该导出任务?').then(() => {
|
||||||
|
return delExportTask(row.taskId)
|
||||||
|
}).then(() => {
|
||||||
|
this.getTaskList()
|
||||||
|
this.$modal.msgSuccess("删除成功")
|
||||||
|
}).catch(() => {})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
-- 导出任务表
|
||||||
|
DROP TABLE IF EXISTS sys_export_task;
|
||||||
|
CREATE TABLE sys_export_task (
|
||||||
|
task_id BIGINT NOT NULL AUTO_INCREMENT COMMENT '任务ID',
|
||||||
|
task_name VARCHAR(100) DEFAULT '' COMMENT '任务名称',
|
||||||
|
task_type VARCHAR(50) DEFAULT '' COMMENT '任务类型',
|
||||||
|
corp_id VARCHAR(64) DEFAULT '' COMMENT '企业ID',
|
||||||
|
query_params TEXT COMMENT '导出参数(JSON格式)',
|
||||||
|
status CHAR(1) DEFAULT '0' COMMENT '状态:0待处理,1处理中,2成功,3失败',
|
||||||
|
progress INT DEFAULT 0 COMMENT '进度百分比',
|
||||||
|
total_count INT DEFAULT 0 COMMENT '总数据量',
|
||||||
|
processed_count INT DEFAULT 0 COMMENT '已处理数量',
|
||||||
|
file_path VARCHAR(500) DEFAULT '' COMMENT '文件路径',
|
||||||
|
file_name VARCHAR(200) DEFAULT '' COMMENT '文件名',
|
||||||
|
file_size BIGINT DEFAULT 0 COMMENT '文件大小(字节)',
|
||||||
|
error_msg TEXT COMMENT '错误信息',
|
||||||
|
create_by VARCHAR(64) DEFAULT '' COMMENT '创建者',
|
||||||
|
create_time DATETIME COMMENT '创建时间',
|
||||||
|
finish_time DATETIME COMMENT '完成时间',
|
||||||
|
PRIMARY KEY (task_id),
|
||||||
|
INDEX idx_corp_id (corp_id),
|
||||||
|
INDEX idx_status (status),
|
||||||
|
INDEX idx_create_time (create_time)
|
||||||
|
) ENGINE=InnoDB AUTO_INCREMENT=1 COMMENT='导出任务表';
|
||||||
Loading…
Reference in New Issue