提交 1a40d520 作者: duanxincheng

纪要周期流程日志;解决主持人找不到的问题;

父级 e0b7d23d
......@@ -4,9 +4,10 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>tencent_callback</artifactId>
<groupId>com.robot</groupId>
<artifactId>cmeeting </artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<!--<profiles>
<profile>
......@@ -338,6 +339,24 @@
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>com.cmeeting.TencentMeetingCallbackApplication</mainClass> <!-- 指定主类 -->
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
<version>2.7.0</version>
</plugin>
</plugins>
</build>
</project>
\ No newline at end of file
Manifest-Version: 1.0
Main-Class: com.cmeeting.TencentMeetingCallbackApplication
package com.cmeeting.email;
import com.cmeeting.log.service.ProcessLogService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
......@@ -8,9 +9,12 @@ import org.springframework.stereotype.Service;
import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.annotation.Resource;
import javax.mail.*;
import javax.mail.internet.*;
import java.io.File;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Properties;
import java.util.concurrent.atomic.AtomicInteger;
......@@ -23,6 +27,8 @@ public class EmailSender {
private String EMAIL_PWD;
@Value("${email.smtp-host}")
private String SMTP_HOST;
@Resource
private ProcessLogService processLogService;
private static final Integer MAX_RETRY = 3;
......@@ -65,6 +71,7 @@ public class EmailSender {
boolean isSent = false;
if(StringUtils.isEmpty(toEmail)){
log.error("收件邮箱为空,推送失败");
processLogService.log(meetingId,null,"收件邮箱为空,推送失败");
return false;
}
while (retryCount.intValue() < MAX_RETRY && !isSent){
......@@ -103,9 +110,12 @@ public class EmailSender {
log.error("邮件已成功发送: meetingId->{}", meetingId);
isSent = true;
} catch (MessagingException e) {
//todo 邮件失败记录
// 异常处理
retryCount.getAndIncrement();
// 异常处理
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
processLogService.log(meetingId,null,"【邮件推送异常】:"+sw.toString());
if (retryCount.intValue() > MAX_RETRY) {
log.error("邮件发送达到最大重试次数: meetingId->{}", meetingId);
throw new RuntimeException(e);
......
......@@ -17,6 +17,7 @@ import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import javax.annotation.PostConstruct;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
......@@ -37,6 +38,16 @@ public class CmeetingJob {
@Autowired
private FileProcessProducer producer;
// @PostConstruct
// public void weComUserInit(){
// weComUserSync();
// }
//
// @PostConstruct
// public void tencentUserInit(){
// TencentUserSync();
// }
/**
* 企微人员定时同步
*/
......@@ -122,8 +133,8 @@ public class CmeetingJob {
userIdMapper.insertUsers(userIds);
}
@Scheduled(fixedRate = 5 * 60 * 1000,initialDelay = 2 * 60 * 1000)
// @Scheduled(fixedRate = 5 * 60 * 1000)
// @Scheduled(fixedRate = 5 * 60 * 1000,initialDelay = 2 * 60 * 1000)
@Scheduled(fixedRate = 5 * 60 * 1000)
public void execute() {
// 定义时间格式化器
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
......
......@@ -36,6 +36,7 @@ import okhttp3.Response;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.xwpf.extractor.XWPFWordExtractor;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;
import java.io.*;
......@@ -90,7 +91,7 @@ public class EmailPushTask {
xml = convertInputStreamToString(is);
}catch (Exception e){
log.error(e.getMessage());
continue;
throw new RuntimeException(e);
}
//将xml格式的内容转换为map,用于填充模板
......@@ -103,15 +104,22 @@ public class EmailPushTask {
participantsMap.put("meeting_host",meetingInfo.getHost());
dataModel.putAll(participantsMap);
String path = Thread.currentThread().getContextClassLoader().getResource("").getPath();
XWPFTemplate template = XWPFTemplate.compile(path + "template/data_net_template.docx").render(dataModel);
ClassPathResource resource = new ClassPathResource("template/data_net_template.docx");
meetingName = dataModel.get("meeting_name") != null ? String.valueOf(dataModel.get("meeting_name")) : "腾讯会议纪要";
targetFileName = meetingName + "_" + nowTime;
template.writeAndClose(new FileOutputStream(savePath + targetFileName + ".docx"));
byte[] recordXmlData = Files.readAllBytes(Paths.get(savePath + targetFileName + ".docx"));
try (InputStream inputStream = resource.getInputStream()) {
XWPFTemplate template = XWPFTemplate.compile(inputStream).render(dataModel);
template.writeAndClose(new FileOutputStream(path + targetFileName + ".docx"));
byte[] recordXmlData = Files.readAllBytes(Paths.get(path + targetFileName + ".docx"));
minioUtils.upload(recordXmlPath,recordXmlData);
} catch (IOException e) {
e.printStackTrace();
}
//邮件推送
isSuccess = emailSender.sendEmailWithAttachment("duanxincheng@chatbot.cn",meetingName,savePath + targetFileName + ".docx",meetingId);
// isSuccess = emailSender.sendEmailWithAttachment("duanxincheng@chatbot.cn",meetingName,savePath + targetFileName + ".docx",meetingId);
isSuccess = emailSender.sendEmailWithAttachment(meetingInfo.getEmail(),meetingName,savePath + targetFileName + ".docx",meetingId);
} catch (Exception e) {
// 异常处理
int currentRetryCount = retryCount.getAndIncrement();
......
......@@ -12,6 +12,7 @@ import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.cmeeting.dto.UserDTO;
import com.cmeeting.email.EmailSender;
import com.cmeeting.log.service.ProcessLogService;
import com.cmeeting.mapper.primary.MeetingInfoMapper;
import com.cmeeting.mapper.primary.MeetingRecordTemplateMapper;
import com.cmeeting.pojo.MeetingInfo;
......@@ -86,6 +87,7 @@ public class FileProcessTask {
private MinioUtils minioUtils;
private EmailSender emailSender;
private MeetingRecordTemplateMapper meetingRecordTemplateMapper;
private ProcessLogService processLogService;
// 实际处理逻辑
public void process() {
......@@ -156,6 +158,7 @@ public class FileProcessTask {
}
if(StringUtils.isEmpty(recordTextBuffer.toString().replaceAll("\\n","").trim())){
log.info("获取的转录文本为空,跳过纪要生成,meetingId:{},fileRecordId:{}",meetingId,recordFileIdList.toString());
processLogService.log(meetingId,subMeetingId,"获取的转录文本为空,跳过纪要生成");
throw new RuntimeException("获取的转录文本为空,跳过纪要生成");
}
// 3. 处理文件 (调用Claude API等)
......@@ -166,6 +169,10 @@ public class FileProcessTask {
isSuccess = true;
} catch (Exception e) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
processLogService.log(meetingId,subMeetingId,sw.toString());
// 异常处理
retryCount++;
if (retryCount > MAX_RETRY) {
......@@ -279,20 +286,24 @@ public class FileProcessTask {
dataModel.putAll(participantsMap);
ClassPathResource resource = new ClassPathResource("template/data_net_template.docx");
Properties properties = new Properties();
meetingName = dataModel.get("meeting_name") != null ? String.valueOf(dataModel.get("meeting_name")) : "腾讯会议纪要";
targetFileName = meetingName + "_" + nowTime;
XWPFTemplate template;
try (InputStream inputStream = resource.getInputStream()) {
XWPFTemplate template = XWPFTemplate.compile(inputStream).render(dataModel);
template = XWPFTemplate.compile(inputStream).render(dataModel);
} catch (IOException e) {
throw new RuntimeException(e);
}
template.writeAndClose(new FileOutputStream(path + targetFileName + ".docx"));
byte[] recordXmlData = Files.readAllBytes(Paths.get(path + targetFileName + ".docx"));
minioUtils.upload(recordXmlPath,recordXmlData);
} catch (IOException e) {
e.printStackTrace();
}
processLogService.log(meetingId,subMeetingId,"填充会议纪要成功");
} catch (Exception e) {
log.error("填充会议纪要失败: {}", e.getMessage(), e);
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
processLogService.log(meetingId,subMeetingId,"填充会议纪要失败"+sw.toString());
throw new RuntimeException("填充会议纪要失败");
}
......@@ -301,11 +312,15 @@ public class FileProcessTask {
if(meetingInfo.getEmailPushAccess()){
log.info("用户允许邮件推送,准备推送邮件至{}------",meetingInfo.getEmail());
//邮件推送
isPushed = emailSender.sendEmailWithAttachment("duanxincheng@chatbot.cn",meetingName,path + targetFileName + ".docx",meetingId);
// isPushed = emailSender.sendEmailWithAttachment("duanxincheng@chatbot.cn",meetingName,path + targetFileName + ".docx",meetingId);
isPushed = emailSender.sendEmailWithAttachment(meetingInfo.getEmail(),meetingName,path + targetFileName + ".docx",meetingId);
if(isPushed)
processLogService.log(meetingId,subMeetingId,"用户允许邮件推送,推送邮件至"+meetingInfo.getEmail());
// emailSender.sendEmailWithAttachment("xuwentao@chatbot.cn",meetingName,path + targetFileName + ".docx",meetingId);
// emailSender.sendEmailWithAttachment("jiaqi.cai@cimc.com",meetingName,path + targetFileName + ".docx",meetingId);
}else{
log.info("用户关闭了邮件推送,推送终止------");
processLogService.log(meetingId,subMeetingId,"用户关闭了邮件推送,推送终止");
isPushed = Boolean.FALSE;
}
......@@ -349,7 +364,7 @@ public class FileProcessTask {
return json;
}
public static String call_llm(String apiAddr, String model, String token, List<Message> messages, int maxTokens) {
private String call_llm(String apiAddr, String model, String token, List<Message> messages, int maxTokens) {
LLMService service = new LLMService(token, apiAddr);
StringBuilder stringBuilder = new StringBuilder();
try {
......@@ -373,6 +388,10 @@ public class FileProcessTask {
});
});
} catch (Exception e) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
processLogService.log(meetingId,subMeetingId,"【大模型处理异常】:"+sw.toString());
throw new RuntimeException(e);
}
service.shutdownExecutor();
......@@ -422,7 +441,7 @@ public class FileProcessTask {
public FileProcessTask(List<String> recordFileIdList, String meetingId, String subMeetingId, String savePath, Map<String, Object> metadata, String tencentAppId,
String tencentSdkId, String tencentSecretId, String tencentSecretKey, String tencentAdminUserId,
MeetingInfoMapper meetingInfoMapper, MinioUtils minioUtils, EmailSender emailSender, MeetingRecordTemplateMapper meetingRecordTemplateMapper,
String llmApiAddr, Boolean finalRetry) {
String llmApiAddr, Boolean finalRetry, ProcessLogService processLogService) {
this.recordFileIdList = recordFileIdList;
this.savePath = savePath;
this.metadata = metadata;
......@@ -439,5 +458,6 @@ public class FileProcessTask {
this.meetingRecordTemplateMapper = meetingRecordTemplateMapper;
this.llmApiAddr = llmApiAddr;
this.finalRetry = finalRetry;
this.processLogService = processLogService;
}
}
\ No newline at end of file
package com.cmeeting.log.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.*;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* 纪要生成周期流程日志
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("log_process_log")
public class ProcessLog implements Serializable {
private static final long serialVersionUID = -26238487532381000L;
/**
* 主键id
*/
@TableId(type = IdType.AUTO)
private Integer id;
/**
* 会议ID(字符串类型)
*/
private String meetingId;
/**
* 子会议ID
*/
private String subMeetingId;
/**
* 消息
*/
private String message;
/**
* 处理时间
*/
private LocalDateTime operateTime;
}
\ No newline at end of file
package com.cmeeting.log.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.cmeeting.log.entity.ProcessLog;
public interface ProcessLogService extends IService<ProcessLog> {
boolean log(String meetingId, String subMeetingId, String message);
}
package com.cmeeting.log.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cmeeting.log.entity.ProcessLog;
import com.cmeeting.mapper.primary.ProcessLogMapper;
import com.cmeeting.log.service.ProcessLogService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
@Service
@Slf4j
public class ProcessLogServiceImpl extends ServiceImpl<ProcessLogMapper, ProcessLog> implements ProcessLogService {
@Override
public boolean log(String meetingId, String subMeetingId, String message) {
ProcessLog processLog = ProcessLog.builder().meetingId(meetingId).subMeetingId(subMeetingId).message(message).operateTime(LocalDateTime.now()).build();
boolean save = save(processLog);
return save;
}
}
package com.cmeeting.mapper.primary;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.cmeeting.log.entity.ProcessLog;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface ProcessLogMapper extends BaseMapper<ProcessLog> {
}
\ No newline at end of file
......@@ -10,4 +10,6 @@ import java.util.List;
public interface TecentMeetingMapper extends BaseMapper<TencentMeetingUser> {
void batchInsertUsers(@Param("userList") List<TencentMeetingUser> userList);
List<TencentMeetingUser> getAlluser();
String getUsernameByUserId(@Param("userId")String userId);
}
......@@ -4,6 +4,7 @@ import com.cmeeting.dto.UserDTO;
import com.cmeeting.email.EmailSender;
import com.cmeeting.job.EmailPushTask;
import com.cmeeting.job.FileProcessTask;
import com.cmeeting.log.service.ProcessLogService;
import com.cmeeting.mapper.primary.MeetingInfoMapper;
import com.cmeeting.mapper.primary.MeetingRecordTemplateMapper;
import com.cmeeting.pojo.UserId;
......@@ -51,6 +52,8 @@ public class FileProcessProducer {
private MinioUtils minioUtils;
@Resource
private EmailSender emailSender;
@Resource
private ProcessLogService processLogService;
/**
* 批量提交生成纪要任务
......@@ -79,7 +82,8 @@ public class FileProcessProducer {
emailSender,
meetingRecordTemplateMapper,
llmApiAddr,
finalRetry
finalRetry,
processLogService
);
// 提交任务到线程池
......
......@@ -2,6 +2,7 @@ package com.cmeeting.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cmeeting.dto.UserDTO;
import com.cmeeting.log.service.ProcessLogService;
import com.cmeeting.mapper.primary.AuthMapper;
import com.cmeeting.mapper.primary.MeetingInfoMapper;
import com.cmeeting.mapper.primary.TecentMeetingMapper;
......@@ -28,6 +29,7 @@ import com.tencentcloudapi.wemeet.service.user_manager.model.V1UsersListGet200Re
import com.tencentcloudapi.wemeet.service.user_manager.model.V1UsersListGet200ResponseUsersInner;
import lombok.extern.slf4j.Slf4j;
import okhttp3.Headers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
......@@ -35,6 +37,8 @@ import org.springframework.util.CollectionUtils;
import javax.annotation.Resource;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
......@@ -64,6 +68,8 @@ public class TecentMeetingServiceImpl extends ServiceImpl<TecentMeetingMapper,Te
private UserIdMapper userIdMapper;
@Resource
private RedisUtils redisUtils;
@Resource
private ProcessLogService processLogService;
private static final String HMAC_ALGORITHM = "HmacSHA256";
private static final char[] HEX_CHAR = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
......@@ -154,7 +160,11 @@ public class TecentMeetingServiceImpl extends ServiceImpl<TecentMeetingMapper,Te
}
for (V1RecordsGet200ResponseRecordMeetingsInner meeting : meetings) {
//会议没结束,跳过
if(meeting.getState() != 3) continue;
if(meeting.getState() != 3){
processLogService.log(meeting.getMeetingId(),null,"会议未结束,跳过生成");
continue;
}
log.info("【会议检索】转录文件的meetingId->{},recordFileId->{}",meeting.getMeetingId(),meeting.getMeetingRecordId());
......@@ -190,6 +200,7 @@ public class TecentMeetingServiceImpl extends ServiceImpl<TecentMeetingMapper,Te
.findFirst();
if(!subMeeting.isPresent()){
System.out.println("周期会议"+meetingId+"未知子会议ID");
processLogService.log(meeting.getMeetingId(),subMeetingId,"周期会议"+meetingId+"未知子会议ID");
continue;
}
subMeetingId = subMeeting.get().getSubMeetingId();
......@@ -229,21 +240,37 @@ public class TecentMeetingServiceImpl extends ServiceImpl<TecentMeetingMapper,Te
List<V1MeetingsMeetingIdParticipantsGet200ResponseParticipantsInner> participants = participantsData.getParticipants();
Optional<V1MeetingsMeetingIdParticipantsGet200ResponseParticipantsInner> host = participants.stream().filter(item -> hostRoleList.contains(item.getUserRole())).findFirst();
String email;
String hostId;
String hostName;
//判断主持人是否存在,如果主持人未参会,是查不到主持人的
//如果主持人未参会,使用会议详情中的创建人作为主持人
if(host.isPresent()) {
String tid = host.get().getUserid();
hostId = host.get().getUserid();
hostName = new String(Base64.getDecoder().decode(host.get().getUserName()));
}else{
//未找到主持人,读取会议详情中的创建人作为主持人
List<V1MeetingsGet200ResponseMeetingInfoListInnerCurrentCoHostsInner> currentHosts = meetingInfo.getCurrentHosts();
if(CollectionUtils.isEmpty(currentHosts)){
log.error("未找到主持人,默认没有生成纪要权限");
processLogService.log(meeting.getMeetingId(),subMeetingId,"未找到主持人,默认没有生成纪要权限");
continue;
}
hostId = currentHosts.get(0).getUserid();
hostName = tecentMeetingMapper.getUsernameByUserId(hostId);
log.info("主持人会中缺席,默认会议创建人为主持人");
processLogService.log(meeting.getMeetingId(),subMeetingId,"未找到主持人,默认会议创建人为主持人");
}
//判断是否有权限生成纪要
boolean generateAccess = accessUserIds.stream().anyMatch(item -> item.getTid().equals(tid));
boolean generateAccess = accessUserIds.stream().anyMatch(item -> item.getTid().equals(hostId));
if(!generateAccess){
log.error("【权限校验】主持人{}没有生成纪要权限,跳过生成",tid);
log.error("【权限校验】主持人{}没有生成纪要权限,跳过生成",hostId);
processLogService.log(meeting.getMeetingId(),subMeetingId,"【权限校验】主持人"+hostId+"没有生成纪要权限,跳过生成");
continue;
}
log.info("【权限校验】主持人{}允许生成纪要",tid);
UserDTO userDTO = accessUserIds.stream().filter(item -> item.getTid().equals(tid)).findFirst().get();
log.info("【权限校验】主持人{}允许生成纪要",hostId);
processLogService.log(meeting.getMeetingId(),subMeetingId,"【权限校验】主持人"+hostId+"允许生成纪要");
UserDTO userDTO = accessUserIds.stream().filter(item -> item.getTid().equals(hostId)).findFirst().get();
email = userDTO.getEmail();
}else{
log.error("未找到主持人,默认没有生成纪要权限");
continue;
}
//会议基本信息保存
MeetingInfo meetingItem = MeetingInfo.builder().meetingId(meetingId).meetingCode(meetingInfo.getMeetingCode())
......@@ -252,8 +279,8 @@ public class TecentMeetingServiceImpl extends ServiceImpl<TecentMeetingMapper,Te
.endTime(LocalDateTime.ofInstant(Instant.ofEpochSecond(Long.valueOf(meetingInfo.getEndTime())), ZoneId.systemDefault()))
.isGenerated(Boolean.FALSE).emailPushAccess(Boolean.TRUE).isPushed(Boolean.FALSE).syncTime(LocalDateTime.now())
.subMeetingId(subMeetingId).generateRetry(Boolean.FALSE).pushRetry(Boolean.FALSE)
.host(host.isPresent() ? new String(Base64.getDecoder().decode(host.get().getUserName())) : "未知主持人")
.hostUid(host.isPresent() ? host.get().getUserid() : null)
.host(hostName)
.hostUid(hostId)
.participantUsers(participants.stream()
.map(item->new String(Base64.getDecoder().decode(item.getUserName()))).distinct().collect(Collectors.joining("、")))
.recordFileId(recordFileIdList.stream().collect(Collectors.joining(",")))
......@@ -285,6 +312,10 @@ public class TecentMeetingServiceImpl extends ServiceImpl<TecentMeetingMapper,Te
}
} catch (Exception e) {
log.error(e.getMessage());
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
processLogService.log(null,null,sw.toString());
throw new RuntimeException(e.getMessage());
}
return recordFileUrlList;
......@@ -296,6 +327,7 @@ public class TecentMeetingServiceImpl extends ServiceImpl<TecentMeetingMapper,Te
*/
@Override
public List<UserDTO> getAccessUserIds() {
try{
//权限控制
List<CoreModulePermissions> auths = authMapper.getAuthByTargetId(permissionApplicationId, permissionTenantId);
//授权的部门,type为1的为人员,为0表示部门
......@@ -332,6 +364,13 @@ public class TecentMeetingServiceImpl extends ServiceImpl<TecentMeetingMapper,Te
return accessUsers;
}
return new ArrayList<>();
}catch (Exception e){
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
processLogService.log(null,null,sw.toString());
throw new RuntimeException(e);
}
}
/**
......
Manifest-Version: 1.0
Main-Class: com.cmeeting.TencentMeetingCallbackApplication
<?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.cmeeting.mapper.primary.ProcessLogMapper">
</mapper>
\ No newline at end of file
......@@ -21,4 +21,7 @@
<select id="getAlluser" resultType="com.cmeeting.pojo.TencentMeetingUser">
SELECT * FROM user_tencentmeeting
</select>
<select id="getUsernameByUserId" resultType="java.lang.String">
SELECT user_name FROM user_tencentmeeting where user_id = #{userId}
</select>
</mapper>
\ No newline at end of file
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论