feat: 修改文件
parent
d8bfdb21fa
commit
af5c658bd9
|
|
@ -301,17 +301,40 @@ public class MeetingController {
|
||||||
return markdown;
|
return markdown;
|
||||||
}
|
}
|
||||||
if (!markdown.startsWith("---")) {
|
if (!markdown.startsWith("---")) {
|
||||||
return markdown;
|
return unwrapMarkdownFence(markdown);
|
||||||
}
|
}
|
||||||
int second = markdown.indexOf("\n---", 3);
|
int second = markdown.indexOf("\n---", 3);
|
||||||
if (second < 0) {
|
if (second < 0) {
|
||||||
return markdown;
|
return unwrapMarkdownFence(markdown);
|
||||||
}
|
}
|
||||||
int contentStart = second + 4;
|
int contentStart = second + 4;
|
||||||
if (contentStart < markdown.length() && markdown.charAt(contentStart) == '\n') {
|
if (contentStart < markdown.length() && markdown.charAt(contentStart) == '\n') {
|
||||||
contentStart++;
|
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}")
|
@GetMapping("/transcripts/{id}")
|
||||||
|
|
@ -423,6 +446,9 @@ public class MeetingController {
|
||||||
return ApiResponse.error("无权修改此会议信息");
|
return ApiResponse.error("无权修改此会议信息");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (meeting.getSummaryContent() != null) {
|
||||||
|
meetingService.updateSummaryContent(meeting.getId(), meeting.getSummaryContent());
|
||||||
|
}
|
||||||
return ApiResponse.ok(meetingService.updateById(meeting));
|
return ApiResponse.ok(meetingService.updateById(meeting));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -34,4 +34,7 @@ public class Meeting extends BaseEntity {
|
||||||
private String creatorName;
|
private String creatorName;
|
||||||
|
|
||||||
private Long latestSummaryTaskId;
|
private Long latestSummaryTaskId;
|
||||||
|
|
||||||
|
@TableField(exist = false)
|
||||||
|
private String summaryContent;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ public interface MeetingService extends IService<Meeting> {
|
||||||
void completeRealtimeMeeting(Long meetingId, String audioUrl);
|
void completeRealtimeMeeting(Long meetingId, String audioUrl);
|
||||||
void updateSpeakerInfo(Long meetingId, String speakerId, String newName, String label);
|
void updateSpeakerInfo(Long meetingId, String speakerId, String newName, String label);
|
||||||
void updateMeetingParticipants(Long meetingId, String participants);
|
void updateMeetingParticipants(Long meetingId, String participants);
|
||||||
|
void updateSummaryContent(Long meetingId, String summaryContent);
|
||||||
void reSummary(Long meetingId, Long summaryModelId, Long promptId);
|
void reSummary(Long meetingId, Long summaryModelId, Long promptId);
|
||||||
java.util.Map<String, Object> getDashboardStats(Long tenantId, Long userId, boolean isAdmin);
|
java.util.Map<String, Object> getDashboardStats(Long tenantId, Long userId, boolean isAdmin);
|
||||||
List<MeetingVO> getRecentMeetings(Long tenantId, Long userId, boolean isAdmin, int limit);
|
List<MeetingVO> getRecentMeetings(Long tenantId, Long userId, boolean isAdmin, int limit);
|
||||||
|
|
|
||||||
|
|
@ -333,7 +333,7 @@ public class AiTaskServiceImpl extends ServiceImpl<AiTaskMapper, AiTask> impleme
|
||||||
JsonNode respNode = objectMapper.readTree(response.body());
|
JsonNode respNode = objectMapper.readTree(response.body());
|
||||||
|
|
||||||
if (response.statusCode() == 200 && respNode.has("choices")) {
|
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
|
// Save to File
|
||||||
String timestamp = java.time.format.DateTimeFormatter.ofPattern("yyyyMMdd_HHmmss").format(LocalDateTime.now());
|
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();
|
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) {
|
private void updateMeetingStatus(Long id, int status) {
|
||||||
Meeting m = new Meeting(); m.setId(id); m.setStatus(status); meetingMapper.updateById(m);
|
Meeting m = new Meeting(); m.setId(id); m.setStatus(status); meetingMapper.updateById(m);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -256,6 +256,35 @@ public class MeetingServiceImpl extends ServiceImpl<MeetingMapper, Meeting> impl
|
||||||
.set(Meeting::getParticipants, participants == null ? "" : participants));
|
.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
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public void reSummary(Long meetingId, Long summaryModelId, Long promptId) {
|
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) {
|
private String loadSummaryContent(Meeting meeting) {
|
||||||
try {
|
try {
|
||||||
AiTask summaryTask = null;
|
AiTask summaryTask = findLatestSummaryTask(meeting);
|
||||||
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"));
|
|
||||||
}
|
|
||||||
if (summaryTask == null || summaryTask.getResultFilePath() == null || summaryTask.getResultFilePath().isBlank()) {
|
if (summaryTask == null || summaryTask.getResultFilePath() == null || summaryTask.getResultFilePath().isBlank()) {
|
||||||
return null;
|
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) {
|
private Integer resolveMeetingDuration(Long meetingId) {
|
||||||
MeetingTranscript latestTranscript = transcriptMapper.selectOne(new LambdaQueryWrapper<MeetingTranscript>()
|
MeetingTranscript latestTranscript = transcriptMapper.selectOne(new LambdaQueryWrapper<MeetingTranscript>()
|
||||||
.eq(MeetingTranscript::getMeetingId, meetingId)
|
.eq(MeetingTranscript::getMeetingId, meetingId)
|
||||||
|
|
@ -492,16 +567,16 @@ public class MeetingServiceImpl extends ServiceImpl<MeetingMapper, Meeting> impl
|
||||||
return markdown;
|
return markdown;
|
||||||
}
|
}
|
||||||
if (!markdown.startsWith("---")) {
|
if (!markdown.startsWith("---")) {
|
||||||
return markdown;
|
return normalizeSummaryMarkdown(markdown);
|
||||||
}
|
}
|
||||||
int second = markdown.indexOf("\n---", 3);
|
int second = markdown.indexOf("\n---", 3);
|
||||||
if (second < 0) {
|
if (second < 0) {
|
||||||
return markdown;
|
return normalizeSummaryMarkdown(markdown);
|
||||||
}
|
}
|
||||||
int contentStart = second + 4;
|
int contentStart = second + 4;
|
||||||
if (contentStart < markdown.length() && markdown.charAt(contentStart) == '\n') {
|
if (contentStart < markdown.length() && markdown.charAt(contentStart) == '\n') {
|
||||||
contentStart++;
|
contentStart++;
|
||||||
}
|
}
|
||||||
return markdown.substring(contentStart).trim();
|
return normalizeSummaryMarkdown(markdown.substring(contentStart).trim());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,12 +3,12 @@
|
||||||
|
|
||||||
spring:
|
spring:
|
||||||
datasource:
|
datasource:
|
||||||
url: jdbc:postgresql://192.168.1.55:5432/imeeting_db
|
url: jdbc:postgresql://10.100.51.199:5432/imeeting_db
|
||||||
username: postgres
|
username: postgres
|
||||||
password: postgres
|
password: postgres
|
||||||
data:
|
data:
|
||||||
redis:
|
redis:
|
||||||
host: 192.168.1.55
|
host: 10.100.51.199
|
||||||
port: 6379
|
port: 6379
|
||||||
password: unis@123
|
password: unis@123
|
||||||
database: 15
|
database: 15
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue