mirror of
https://codeup.aliyun.com/67762337eccfc218f6110e0e/per-boe/java-servers.git
synced 2025-12-12 12:26:51 +08:00
fix: 增加下载excel接口
This commit is contained in:
@@ -8,8 +8,6 @@ import com.xboe.module.boecase.service.ICaseAiChatService;
|
|||||||
import com.xboe.module.boecase.service.ICaseAiPermissionService;
|
import com.xboe.module.boecase.service.ICaseAiPermissionService;
|
||||||
import com.xboe.module.boecase.service.IElasticSearchIndexService;
|
import com.xboe.module.boecase.service.IElasticSearchIndexService;
|
||||||
import com.xboe.module.boecase.vo.CaseAiMessageVo;
|
import com.xboe.module.boecase.vo.CaseAiMessageVo;
|
||||||
import com.xboe.module.excel.ExportsExcelSenderUtil;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
@@ -17,12 +15,8 @@ import org.springframework.web.bind.annotation.*;
|
|||||||
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
|
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import java.io.IOException;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.time.format.DateTimeFormatter;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -110,32 +104,9 @@ public class CaseAiChatApi extends ApiBaseController {
|
|||||||
public void downloadConversationExcel(@RequestParam String startTime,
|
public void downloadConversationExcel(@RequestParam String startTime,
|
||||||
@RequestParam String endTime,
|
@RequestParam String endTime,
|
||||||
HttpServletResponse response) {
|
HttpServletResponse response) {
|
||||||
try {
|
LocalDateTime start = LocalDateTime.parse(startTime);
|
||||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
LocalDateTime end = LocalDateTime.parse(endTime);
|
||||||
LocalDateTime start = LocalDateTime.parse(startTime, formatter);
|
caseAiChatService.getConversationExcel(start, end, response);
|
||||||
LocalDateTime end = LocalDateTime.parse(endTime, formatter);
|
|
||||||
|
|
||||||
// TODO: 这里需要修改为实际返回数据的方法
|
|
||||||
caseAiChatService.downloadConversationExcel(start, end);
|
|
||||||
|
|
||||||
response.setContentType("application/vnd.ms-excel");
|
|
||||||
response.setHeader("Content-Disposition", "attachment; filename=conversations.xls");
|
|
||||||
|
|
||||||
// 示例数据,实际应该从Service获取
|
|
||||||
LinkedHashMap<String, String> headers = new LinkedHashMap<>();
|
|
||||||
headers.put("会话ID", "conversationId");
|
|
||||||
headers.put("会话名称", "conversationName");
|
|
||||||
headers.put("用户", "user");
|
|
||||||
headers.put("开始时间", "startTime");
|
|
||||||
headers.put("会话时长", "duration");
|
|
||||||
|
|
||||||
List<ConversationExcelVo> dataList = new ArrayList<>();
|
|
||||||
// 这里应该填充实际数据
|
|
||||||
|
|
||||||
ExportsExcelSenderUtil.export(headers, dataList, response.getOutputStream(), "yyyy-MM-dd HH:mm:ss");
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("导出会话记录为Excel异常", e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -191,16 +162,4 @@ public class CaseAiChatApi extends ApiBaseController {
|
|||||||
}
|
}
|
||||||
return error("创建失败");
|
return error("创建失败");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 用于Excel导出的VO类
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
static class ConversationExcelVo {
|
|
||||||
private String conversationId;
|
|
||||||
private String conversationName;
|
|
||||||
private String user;
|
|
||||||
private String startTime;
|
|
||||||
private String duration;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -6,6 +6,7 @@ import com.xboe.module.boecase.entity.CaseAiConversations;
|
|||||||
import com.xboe.module.boecase.vo.CaseAiMessageVo;
|
import com.xboe.module.boecase.vo.CaseAiMessageVo;
|
||||||
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
|
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -40,6 +41,14 @@ public interface ICaseAiChatService {
|
|||||||
*/
|
*/
|
||||||
List<CaseAiMessageVo> getConversationMessages(String conversationId);
|
List<CaseAiMessageVo> getConversationMessages(String conversationId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导出会话记录为Excel
|
||||||
|
* @param startTime 开始时间
|
||||||
|
* @param endTime 结束时间
|
||||||
|
* @param response
|
||||||
|
*/
|
||||||
|
void getConversationExcel(LocalDateTime startTime, LocalDateTime endTime, HttpServletResponse response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 导出会话记录为Excel
|
* 导出会话记录为Excel
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -61,6 +61,7 @@ import org.springframework.transaction.annotation.Transactional;
|
|||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
|
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
@@ -390,92 +391,24 @@ public class CaseAiChatServiceImpl implements ICaseAiChatService {
|
|||||||
return elasticSearchIndexService.queryData(conversationId);
|
return elasticSearchIndexService.queryData(conversationId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void getConversationExcel(LocalDateTime startTime, LocalDateTime endTime, HttpServletResponse response) {
|
||||||
|
Workbook workbook = getChatMessageExcel(startTime, endTime);
|
||||||
|
// 写入response.getOutputStream()
|
||||||
|
try (OutputStream out = response.getOutputStream()) {
|
||||||
|
response.setContentType("application/octet-stream");
|
||||||
|
response.setHeader("Content-Disposition", "attachment;filename=chat_message.xlsx");
|
||||||
|
workbook.write(out);
|
||||||
|
out.flush();
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("导出Excel异常", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void downloadConversationExcel(LocalDateTime startTime, LocalDateTime endTime) {
|
public void downloadConversationExcel(LocalDateTime startTime, LocalDateTime endTime) {
|
||||||
// 1. 根据startTime和endTime,查询在这个时间区间内的CaseAiConversations数据
|
Workbook workbook = getChatMessageExcel(startTime, endTime);
|
||||||
List<CaseAiConversations> conversations = caseAiConversationsDao.getGenericDao().findList(
|
// 创建Excel文件并保存
|
||||||
CaseAiConversations.class,
|
|
||||||
FieldFilters.ge("sysCreateTime", startTime),
|
|
||||||
FieldFilters.le("sysCreateTime", endTime)
|
|
||||||
);
|
|
||||||
|
|
||||||
// 准备Excel数据
|
|
||||||
List<ConversationExcelVo> excelDataList = new ArrayList<>();
|
|
||||||
|
|
||||||
// 2. 遍历这组数据,根据aiConversationId从es中查询数据(可调用getConversationMessages()方法)
|
|
||||||
for (CaseAiConversations conversation : conversations) {
|
|
||||||
String aiConversationId = conversation.getAiConversationId();
|
|
||||||
String conversationName = conversation.getConversationName();
|
|
||||||
String conversationUser = conversation.getConversationUser();
|
|
||||||
|
|
||||||
List<CaseAiMessageVo> messages = getConversationMessages(aiConversationId);
|
|
||||||
|
|
||||||
// 计算会话时长
|
|
||||||
long duration = 0; // 默认为0,如果需要精确计算,需要从消息中提取时间信息
|
|
||||||
|
|
||||||
// 3. 写入Excel,包括每个会话的用户,会话标题,会话内的问答记录,每次对话时长等
|
|
||||||
ConversationExcelVo excelData = new ConversationExcelVo();
|
|
||||||
excelData.setConversationId(aiConversationId);
|
|
||||||
excelData.setConversationName(conversationName);
|
|
||||||
excelData.setUser(conversationUser);
|
|
||||||
excelData.setMessages(messages);
|
|
||||||
|
|
||||||
excelDataList.add(excelData);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 写入Excel文件
|
|
||||||
Workbook workbook = new XSSFWorkbook();
|
|
||||||
Sheet sheet = workbook.createSheet("AI会话数据");
|
|
||||||
// 标题行
|
|
||||||
Row headerRow = sheet.createRow(0);
|
|
||||||
headerRow.createCell(0).setCellValue("会话ID");
|
|
||||||
headerRow.createCell(1).setCellValue("会话名称");
|
|
||||||
headerRow.createCell(2).setCellValue("用户");
|
|
||||||
headerRow.createCell(3).setCellValue("提问");
|
|
||||||
headerRow.createCell(4).setCellValue("回答");
|
|
||||||
headerRow.createCell(5).setCellValue("开始时间");
|
|
||||||
headerRow.createCell(6).setCellValue("问答时长(秒)");
|
|
||||||
|
|
||||||
// 内容行
|
|
||||||
if (!excelDataList.isEmpty()) {
|
|
||||||
int rowNum = 1; // 从第二行开始写入数据
|
|
||||||
for (ConversationExcelVo excelData : excelDataList) {
|
|
||||||
List<CaseAiMessageVo> messages = excelData.getMessages();
|
|
||||||
|
|
||||||
if (messages != null && !messages.isEmpty()) {
|
|
||||||
// 记录起始行号,用于后续合并单元格
|
|
||||||
int startRow = rowNum;
|
|
||||||
|
|
||||||
// 遍历每个消息
|
|
||||||
for (CaseAiMessageVo message : messages) {
|
|
||||||
Row row = sheet.createRow(rowNum++);
|
|
||||||
// 填充每行数据
|
|
||||||
row.createCell(0).setCellValue(excelData.getConversationId());
|
|
||||||
row.createCell(1).setCellValue(excelData.getConversationName());
|
|
||||||
row.createCell(2).setCellValue(excelData.getUser());
|
|
||||||
row.createCell(3).setCellValue(message.getQuery() != null ? message.getQuery() : "");
|
|
||||||
row.createCell(4).setCellValue(message.getAnswer() != null ? message.getAnswer() : "");
|
|
||||||
row.createCell(5).setCellValue(""); // 开始时间字段暂留空
|
|
||||||
row.createCell(6).setCellValue(message.getDurationSeconds() != null ? message.getDurationSeconds() : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 合并单元格(会话ID、会话名称、用户三列)
|
|
||||||
// 参数说明:起始行号,结束行号,起始列号,结束列号
|
|
||||||
if (rowNum > startRow + 1) { // 只有当有多行时才合并
|
|
||||||
sheet.addMergedRegion(new CellRangeAddress(startRow, rowNum - 1, 0, 0));
|
|
||||||
sheet.addMergedRegion(new CellRangeAddress(startRow, rowNum - 1, 1, 1));
|
|
||||||
sheet.addMergedRegion(new CellRangeAddress(startRow, rowNum - 1, 2, 2));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// 如果没有消息,则仍然创建一行显示基本信息
|
|
||||||
Row row = sheet.createRow(rowNum++);
|
|
||||||
row.createCell(0).setCellValue(excelData.getConversationId());
|
|
||||||
row.createCell(1).setCellValue(excelData.getConversationName());
|
|
||||||
row.createCell(2).setCellValue(excelData.getUser());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 3. 创建Excel文件并保存
|
|
||||||
if (caseAiProperties.isAiChatDataSendEmail()) {
|
if (caseAiProperties.isAiChatDataSendEmail()) {
|
||||||
// TODO 发送邮件附件
|
// TODO 发送邮件附件
|
||||||
} else {
|
} else {
|
||||||
@@ -814,4 +747,92 @@ public class CaseAiChatServiceImpl implements ICaseAiChatService {
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Workbook getChatMessageExcel(LocalDateTime startTime, LocalDateTime endTime) {
|
||||||
|
// 1. 根据startTime和endTime,查询在这个时间区间内的CaseAiConversations数据
|
||||||
|
List<CaseAiConversations> conversations = caseAiConversationsDao.getGenericDao().findList(
|
||||||
|
CaseAiConversations.class,
|
||||||
|
FieldFilters.ge("sysCreateTime", startTime),
|
||||||
|
FieldFilters.le("sysCreateTime", endTime)
|
||||||
|
);
|
||||||
|
|
||||||
|
// 准备Excel数据
|
||||||
|
List<ConversationExcelVo> excelDataList = new ArrayList<>();
|
||||||
|
|
||||||
|
// 2. 遍历这组数据,根据aiConversationId从es中查询数据(可调用getConversationMessages()方法)
|
||||||
|
for (CaseAiConversations conversation : conversations) {
|
||||||
|
String aiConversationId = conversation.getAiConversationId();
|
||||||
|
String conversationName = conversation.getConversationName();
|
||||||
|
String conversationUser = conversation.getConversationUser();
|
||||||
|
|
||||||
|
List<CaseAiMessageVo> messages = getConversationMessages(aiConversationId);
|
||||||
|
|
||||||
|
// 计算会话时长
|
||||||
|
long duration = 0; // 默认为0,如果需要精确计算,需要从消息中提取时间信息
|
||||||
|
|
||||||
|
// 3. 写入Excel,包括每个会话的用户,会话标题,会话内的问答记录,每次对话时长等
|
||||||
|
ConversationExcelVo excelData = new ConversationExcelVo();
|
||||||
|
excelData.setConversationId(aiConversationId);
|
||||||
|
excelData.setConversationName(conversationName);
|
||||||
|
excelData.setUser(conversationUser);
|
||||||
|
excelData.setMessages(messages);
|
||||||
|
|
||||||
|
excelDataList.add(excelData);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 写入Excel文件
|
||||||
|
Workbook workbook = new XSSFWorkbook();
|
||||||
|
Sheet sheet = workbook.createSheet("AI会话数据");
|
||||||
|
// 标题行
|
||||||
|
Row headerRow = sheet.createRow(0);
|
||||||
|
headerRow.createCell(0).setCellValue("会话ID");
|
||||||
|
headerRow.createCell(1).setCellValue("会话名称");
|
||||||
|
headerRow.createCell(2).setCellValue("用户");
|
||||||
|
headerRow.createCell(3).setCellValue("提问");
|
||||||
|
headerRow.createCell(4).setCellValue("回答");
|
||||||
|
headerRow.createCell(5).setCellValue("开始时间");
|
||||||
|
headerRow.createCell(6).setCellValue("问答时长(秒)");
|
||||||
|
|
||||||
|
// 内容行
|
||||||
|
if (!excelDataList.isEmpty()) {
|
||||||
|
int rowNum = 1; // 从第二行开始写入数据
|
||||||
|
for (ConversationExcelVo excelData : excelDataList) {
|
||||||
|
List<CaseAiMessageVo> messages = excelData.getMessages();
|
||||||
|
|
||||||
|
if (messages != null && !messages.isEmpty()) {
|
||||||
|
// 记录起始行号,用于后续合并单元格
|
||||||
|
int startRow = rowNum;
|
||||||
|
|
||||||
|
// 遍历每个消息
|
||||||
|
for (CaseAiMessageVo message : messages) {
|
||||||
|
Row row = sheet.createRow(rowNum++);
|
||||||
|
// 填充每行数据
|
||||||
|
row.createCell(0).setCellValue(excelData.getConversationId());
|
||||||
|
row.createCell(1).setCellValue(excelData.getConversationName());
|
||||||
|
row.createCell(2).setCellValue(excelData.getUser());
|
||||||
|
row.createCell(3).setCellValue(message.getQuery() != null ? message.getQuery() : "");
|
||||||
|
row.createCell(4).setCellValue(message.getAnswer() != null ? message.getAnswer() : "");
|
||||||
|
row.createCell(5).setCellValue(""); // 开始时间字段暂留空
|
||||||
|
row.createCell(6).setCellValue(message.getDurationSeconds() != null ? message.getDurationSeconds() : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 合并单元格(会话ID、会话名称、用户三列)
|
||||||
|
// 参数说明:起始行号,结束行号,起始列号,结束列号
|
||||||
|
if (rowNum > startRow + 1) { // 只有当有多行时才合并
|
||||||
|
sheet.addMergedRegion(new CellRangeAddress(startRow, rowNum - 1, 0, 0));
|
||||||
|
sheet.addMergedRegion(new CellRangeAddress(startRow, rowNum - 1, 1, 1));
|
||||||
|
sheet.addMergedRegion(new CellRangeAddress(startRow, rowNum - 1, 2, 2));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 如果没有消息,则仍然创建一行显示基本信息
|
||||||
|
Row row = sheet.createRow(rowNum++);
|
||||||
|
row.createCell(0).setCellValue(excelData.getConversationId());
|
||||||
|
row.createCell(1).setCellValue(excelData.getConversationName());
|
||||||
|
row.createCell(2).setCellValue(excelData.getUser());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return workbook;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user