feat: 修改文件

dev_na
chenhao 2026-03-17 10:24:50 +08:00
parent d8bfdb21fa
commit af5c658bd9
6 changed files with 154 additions and 22 deletions

View File

@ -301,17 +301,40 @@ public class MeetingController {
return markdown;
}
if (!markdown.startsWith("---")) {
return markdown;
return unwrapMarkdownFence(markdown);
}
int second = markdown.indexOf("\n---", 3);
if (second < 0) {
return markdown;
return unwrapMarkdownFence(markdown);
}
int contentStart = second + 4;
if (contentStart < markdown.length() && markdown.charAt(contentStart) == '\n') {
contentStart++;
}
return markdown.substring(contentStart).trim();
return unwrapMarkdownFence(markdown.substring(contentStart).trim());
}
private String unwrapMarkdownFence(String markdown) {
if (markdown == null) {
return null;
}
String normalized = markdown.trim();
if (!normalized.startsWith("```")) {
return normalized;
}
int firstLineEnd = normalized.indexOf('\n');
if (firstLineEnd < 0) {
return normalized;
}
String firstLine = normalized.substring(0, firstLineEnd).trim().toLowerCase();
if (!"```".equals(firstLine) && !"```markdown".equals(firstLine) && !"```md".equals(firstLine)) {
return normalized;
}
int lastFence = normalized.lastIndexOf("\n```");
if (lastFence <= firstLineEnd) {
return normalized.substring(firstLineEnd + 1).trim();
}
return normalized.substring(firstLineEnd + 1, lastFence).trim();
}
@GetMapping("/transcripts/{id}")
@ -423,6 +446,9 @@ public class MeetingController {
return ApiResponse.error("无权修改此会议信息");
}
if (meeting.getSummaryContent() != null) {
meetingService.updateSummaryContent(meeting.getId(), meeting.getSummaryContent());
}
return ApiResponse.ok(meetingService.updateById(meeting));
}

View File

@ -34,4 +34,7 @@ public class Meeting extends BaseEntity {
private String creatorName;
private Long latestSummaryTaskId;
@TableField(exist = false)
private String summaryContent;
}

View File

@ -21,6 +21,7 @@ public interface MeetingService extends IService<Meeting> {
void completeRealtimeMeeting(Long meetingId, String audioUrl);
void updateSpeakerInfo(Long meetingId, String speakerId, String newName, String label);
void updateMeetingParticipants(Long meetingId, String participants);
void updateSummaryContent(Long meetingId, String summaryContent);
void reSummary(Long meetingId, Long summaryModelId, Long promptId);
java.util.Map<String, Object> getDashboardStats(Long tenantId, Long userId, boolean isAdmin);
List<MeetingVO> getRecentMeetings(Long tenantId, Long userId, boolean isAdmin, int limit);

View File

@ -333,7 +333,7 @@ public class AiTaskServiceImpl extends ServiceImpl<AiTaskMapper, AiTask> impleme
JsonNode respNode = objectMapper.readTree(response.body());
if (response.statusCode() == 200 && respNode.has("choices")) {
String content = respNode.path("choices").path(0).path("message").path("content").asText();
String content = sanitizeSummaryContent(respNode.path("choices").path(0).path("message").path("content").asText());
// Save to File
String timestamp = java.time.format.DateTimeFormatter.ofPattern("yyyyMMdd_HHmmss").format(LocalDateTime.now());
@ -387,6 +387,33 @@ public class AiTaskServiceImpl extends ServiceImpl<AiTaskMapper, AiTask> impleme
return httpClient.send(HttpRequest.newBuilder().uri(URI.create(url)).GET().build(), HttpResponse.BodyHandlers.ofString()).body();
}
private String sanitizeSummaryContent(String content) {
if (content == null || content.isBlank()) {
return content;
}
String normalized = content.trim();
int thinkEndIndex = normalized.lastIndexOf("</think>");
if (thinkEndIndex >= 0) {
normalized = normalized.substring(thinkEndIndex + "</think>".length()).trim();
}
if (!normalized.startsWith("```")) {
return normalized;
}
int firstLineEnd = normalized.indexOf('\n');
if (firstLineEnd < 0) {
return normalized;
}
String firstLine = normalized.substring(0, firstLineEnd).trim().toLowerCase();
if (!"```".equals(firstLine) && !"```markdown".equals(firstLine) && !"```md".equals(firstLine)) {
return normalized;
}
int lastFence = normalized.lastIndexOf("\n```");
if (lastFence <= firstLineEnd) {
return normalized.substring(firstLineEnd + 1).trim();
}
return normalized.substring(firstLineEnd + 1, lastFence).trim();
}
private void updateMeetingStatus(Long id, int status) {
Meeting m = new Meeting(); m.setId(id); m.setStatus(status); meetingMapper.updateById(m);
}

View File

@ -256,6 +256,35 @@ public class MeetingServiceImpl extends ServiceImpl<MeetingMapper, Meeting> impl
.set(Meeting::getParticipants, participants == null ? "" : participants));
}
@Override
@Transactional(rollbackFor = Exception.class)
public void updateSummaryContent(Long meetingId, String summaryContent) {
Meeting meeting = this.getById(meetingId);
if (meeting == null) {
throw new RuntimeException("Meeting not found");
}
AiTask summaryTask = findLatestSummaryTask(meeting);
if (summaryTask == null || summaryTask.getResultFilePath() == null || summaryTask.getResultFilePath().isBlank()) {
throw new RuntimeException("Summary file not found");
}
String basePath = uploadPath.endsWith("/") ? uploadPath : uploadPath + "/";
Path summaryPath = Paths.get(basePath, summaryTask.getResultFilePath().replace("\\", "/"));
try {
Path parent = summaryPath.getParent();
if (parent != null) {
Files.createDirectories(parent);
}
String existingContent = Files.exists(summaryPath) ? Files.readString(summaryPath, StandardCharsets.UTF_8) : "";
String frontMatter = extractFrontMatter(existingContent, meeting, summaryTask);
Files.writeString(summaryPath, frontMatter + normalizeSummaryMarkdown(summaryContent), StandardCharsets.UTF_8);
} catch (Exception e) {
throw new RuntimeException("Update summary file failed", e);
}
}
@Override
@Transactional(rollbackFor = Exception.class)
public void reSummary(Long meetingId, Long summaryModelId, Long promptId) {
@ -435,19 +464,7 @@ public class MeetingServiceImpl extends ServiceImpl<MeetingMapper, Meeting> impl
private String loadSummaryContent(Meeting meeting) {
try {
AiTask summaryTask = null;
if (meeting.getLatestSummaryTaskId() != null) {
summaryTask = aiTaskMapper.selectById(meeting.getLatestSummaryTaskId());
}
if (summaryTask == null || summaryTask.getResultFilePath() == null || summaryTask.getResultFilePath().isBlank()) {
summaryTask = aiTaskMapper.selectOne(new LambdaQueryWrapper<AiTask>()
.eq(AiTask::getMeetingId, meeting.getId())
.eq(AiTask::getTaskType, "SUMMARY")
.eq(AiTask::getStatus, 2)
.isNotNull(AiTask::getResultFilePath)
.orderByDesc(AiTask::getId)
.last("LIMIT 1"));
}
AiTask summaryTask = findLatestSummaryTask(meeting);
if (summaryTask == null || summaryTask.getResultFilePath() == null || summaryTask.getResultFilePath().isBlank()) {
return null;
}
@ -466,6 +483,64 @@ public class MeetingServiceImpl extends ServiceImpl<MeetingMapper, Meeting> impl
}
}
private AiTask findLatestSummaryTask(Meeting meeting) {
AiTask summaryTask = null;
if (meeting.getLatestSummaryTaskId() != null) {
summaryTask = aiTaskMapper.selectById(meeting.getLatestSummaryTaskId());
}
if (summaryTask == null || summaryTask.getResultFilePath() == null || summaryTask.getResultFilePath().isBlank()) {
summaryTask = aiTaskMapper.selectOne(new LambdaQueryWrapper<AiTask>()
.eq(AiTask::getMeetingId, meeting.getId())
.eq(AiTask::getTaskType, "SUMMARY")
.eq(AiTask::getStatus, 2)
.isNotNull(AiTask::getResultFilePath)
.orderByDesc(AiTask::getId)
.last("LIMIT 1"));
}
return summaryTask;
}
private String extractFrontMatter(String markdown, Meeting meeting, AiTask summaryTask) {
if (markdown != null && markdown.startsWith("---")) {
int second = markdown.indexOf("\n---", 3);
if (second >= 0) {
int end = second + 4;
if (end < markdown.length() && markdown.charAt(end) == '\n') {
end++;
}
return markdown.substring(0, end);
}
}
return "---\n" +
"updatedAt: " + LocalDateTime.now() + "\n" +
"meetingId: " + meeting.getId() + "\n" +
"summaryTaskId: " + summaryTask.getId() + "\n" +
"---\n\n";
}
private String normalizeSummaryMarkdown(String markdown) {
if (markdown == null) {
return "";
}
String normalized = markdown.trim();
if (!normalized.startsWith("```")) {
return normalized;
}
int firstLineEnd = normalized.indexOf('\n');
if (firstLineEnd < 0) {
return normalized;
}
String firstLine = normalized.substring(0, firstLineEnd).trim().toLowerCase();
if (!"```".equals(firstLine) && !"```markdown".equals(firstLine) && !"```md".equals(firstLine)) {
return normalized;
}
int lastFence = normalized.lastIndexOf("\n```");
if (lastFence <= firstLineEnd) {
return normalized.substring(firstLineEnd + 1).trim();
}
return normalized.substring(firstLineEnd + 1, lastFence).trim();
}
private Integer resolveMeetingDuration(Long meetingId) {
MeetingTranscript latestTranscript = transcriptMapper.selectOne(new LambdaQueryWrapper<MeetingTranscript>()
.eq(MeetingTranscript::getMeetingId, meetingId)
@ -492,16 +567,16 @@ public class MeetingServiceImpl extends ServiceImpl<MeetingMapper, Meeting> impl
return markdown;
}
if (!markdown.startsWith("---")) {
return markdown;
return normalizeSummaryMarkdown(markdown);
}
int second = markdown.indexOf("\n---", 3);
if (second < 0) {
return markdown;
return normalizeSummaryMarkdown(markdown);
}
int contentStart = second + 4;
if (contentStart < markdown.length() && markdown.charAt(contentStart) == '\n') {
contentStart++;
}
return markdown.substring(contentStart).trim();
return normalizeSummaryMarkdown(markdown.substring(contentStart).trim());
}
}

View File

@ -3,12 +3,12 @@
spring:
datasource:
url: jdbc:postgresql://192.168.1.55:5432/imeeting_db
url: jdbc:postgresql://10.100.51.199:5432/imeeting_db
username: postgres
password: postgres
data:
redis:
host: 192.168.1.55
host: 10.100.51.199
port: 6379
password: unis@123
database: 15