提交 e0b7d23d 作者: duanxincheng

二次重试机制;模板创建与维护;会议纪要生成权限控制

父级 b87c127c
...@@ -330,11 +330,11 @@ ...@@ -330,11 +330,11 @@
</exclusion> </exclusion>
</exclusions> </exclusions>
</dependency> </dependency>
<dependency> <dependency>
<groupId>junit</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>junit</artifactId> <artifactId>spring-boot-starter-data-redis</artifactId>
<version>RELEASE</version> <version>2.7.0</version> <!-- 与你的Spring Boot版本一致 -->
<scope>test</scope>
</dependency> </dependency>
</dependencies> </dependencies>
......
...@@ -146,7 +146,7 @@ public class TencentMeetingCallbackController { ...@@ -146,7 +146,7 @@ public class TencentMeetingCallbackController {
//通过智能体id查询该id下的部门和用户 //通过智能体id查询该id下的部门和用户
String targetId = "1815393211829587968";//职能体id String targetId = "1815393211829587968";//职能体id
String tenantId = "1806976109082972160";//租户id String tenantId = "1806976109082972160";//租户id
List<CoreModulePermissions> auths = authMapper.getAuthByTargrtId(targetId, tenantId); List<CoreModulePermissions> auths = authMapper.getAuthByTargetId(targetId, tenantId);
// 创建两个集合分别存储type=0(部门)和type=1(员工)的数据 // 创建两个集合分别存储type=0(部门)和type=1(员工)的数据
List<CoreModulePermissions> type0List = new ArrayList<>(); List<CoreModulePermissions> type0List = new ArrayList<>();
List<CoreModulePermissions> type1List = new ArrayList<>(); List<CoreModulePermissions> type1List = new ArrayList<>();
......
...@@ -11,7 +11,6 @@ import org.springframework.web.bind.annotation.RestController; ...@@ -11,7 +11,6 @@ import org.springframework.web.bind.annotation.RestController;
import java.util.List; import java.util.List;
import static com.cmeeting.WeComAndTencentMeeting.*;
@RestController @RestController
@RequestMapping("/tencent") @RequestMapping("/tencent")
...@@ -24,8 +23,8 @@ public class TencentMeetingController { ...@@ -24,8 +23,8 @@ public class TencentMeetingController {
tecentMeetingService.doUsers(); tecentMeetingService.doUsers();
} }
@GetMapping("/getMeetingFiles") // @GetMapping("/getMeetingFiles")
public void getMeetingFiles(){ // public void getMeetingFiles(){
tecentMeetingService.getMeetingFiles(); // tecentMeetingService.getMeetingFiles();
} // }
} }
...@@ -127,32 +127,32 @@ public class UnifiedController { ...@@ -127,32 +127,32 @@ public class UnifiedController {
//取消预约会议 //取消预约会议
} }
//todo 待测试 // //todo 待测试
@GetMapping("/sameNameInsertTid") // @GetMapping("/sameNameInsertTid")
public void sameNameInsertTid(String corpid, String corpsecret) throws IOException { // public void sameNameInsertTid(String corpid, String corpsecret) throws IOException {
String weComToken = getWeComToken(corpid,corpsecret); // String weComToken = getWeComToken(corpid,corpsecret);
List<WeComUser> sameNameUsers = weComUserMapper.getSameName(); // List<WeComUser> sameNameUsers = weComUserMapper.getSameName();
List<UserId> userIds = new ArrayList<>(); // List<UserId> userIds = new ArrayList<>();
for (WeComUser user : sameNameUsers) { // for (WeComUser user : sameNameUsers) {
Map<String, String> meetingCodeAndMeetingid = createMeeting(user.getUserId(), weComToken); // Map<String, String> meetingCodeAndMeetingid = createMeeting(user.getUserId(), weComToken);
String meetingId = meetingCodeAndMeetingid.get("meetingid"); // String meetingId = meetingCodeAndMeetingid.get("meetingid");
String meetingCode = meetingCodeAndMeetingid.get("meeting_code"); // String meetingCode = meetingCodeAndMeetingid.get("meeting_code");
if (meetingCode == null || meetingCode.isEmpty()) { // if (meetingCode == null || meetingCode.isEmpty()) {
System.err.println("会议创建失败,跳过用户: " + user.getUserId()); // System.err.println("会议创建失败,跳过用户: " + user.getUserId());
continue; // continue;
} // }
// 3.2 查询会议详情,获取主持人腾讯会议 userid(假设是 host_userid) // // 3.2 查询会议详情,获取主持人腾讯会议 userid(假设是 host_userid)
String hostUserId = getMeetingHost(meetingCode); // String hostUserId = getMeetingHost(meetingCode);
if (hostUserId == null || hostUserId.isEmpty()) { // if (hostUserId == null || hostUserId.isEmpty()) {
System.err.println("获取主持人失败,跳过会议: " + meetingCode); // System.err.println("获取主持人失败,跳过会议: " + meetingCode);
cancelMeeting(meetingId, weComToken); // 尝试取消无效会议 // cancelMeeting(meetingId, weComToken); // 尝试取消无效会议
continue; // continue;
} // }
UserId userId = new UserId(user.getUserName(), user.getUserId(), hostUserId); // UserId userId = new UserId(user.getUserName(), user.getUserId(), hostUserId);
userIds.add(userId); // userIds.add(userId);
} // }
userIdMapper.insertUsers(userIds); // userIdMapper.insertUsers(userIds);
} // }
/** /**
* 通过企业微信接口取消预约会议 * 通过企业微信接口取消预约会议
......
...@@ -18,7 +18,6 @@ import java.net.URL; ...@@ -18,7 +18,6 @@ import java.net.URL;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import static com.cmeeting.WeComAndTencentMeeting.*;
@RestController @RestController
@RequestMapping("/wecom") @RequestMapping("/wecom")
......
// vo/LoginVO.java
package com.cmeeting.dto;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class UserDTO {
/**
* 员工姓名
*/
private String userName;
/**
* 企业微信userid
*/
private String wid;
/**
* 腾讯会议userid
*/
private String tid;
/**
* 邮箱
*/
private String email;
}
\ No newline at end of file
package com.cmeeting.email; package com.cmeeting.email;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
...@@ -29,10 +30,10 @@ public class EmailSender { ...@@ -29,10 +30,10 @@ public class EmailSender {
* @param toEmail 收件人 * @param toEmail 收件人
* @param subject 邮件主题 * @param subject 邮件主题
* @param attachmentPath 附件路径 * @param attachmentPath 附件路径
* @param recordFileId 转录文件ID * @param meetingId 会议id
* @return * @return
*/ */
public boolean sendEmailWithAttachment(String toEmail, String subject, String attachmentPath, String recordFileId) throws Exception { public boolean sendEmailWithAttachment(String toEmail, String subject, String attachmentPath, String meetingId) {
// 邮件服务器配置 // 邮件服务器配置
Properties props = new Properties(); Properties props = new Properties();
props.put("mail.smtp.host", SMTP_HOST); props.put("mail.smtp.host", SMTP_HOST);
...@@ -62,6 +63,10 @@ public class EmailSender { ...@@ -62,6 +63,10 @@ public class EmailSender {
AtomicInteger retryCount = new AtomicInteger(0); AtomicInteger retryCount = new AtomicInteger(0);
boolean isSent = false; boolean isSent = false;
if(StringUtils.isEmpty(toEmail)){
log.error("收件邮箱为空,推送失败");
return false;
}
while (retryCount.intValue() < MAX_RETRY && !isSent){ while (retryCount.intValue() < MAX_RETRY && !isSent){
try { try {
// 创建邮件消息 // 创建邮件消息
...@@ -95,14 +100,14 @@ public class EmailSender { ...@@ -95,14 +100,14 @@ public class EmailSender {
// 发送邮件 // 发送邮件
Transport.send(message); Transport.send(message);
log.error("邮件已成功发送: recordFileId->{}", recordFileId); log.error("邮件已成功发送: meetingId->{}", meetingId);
isSent = true; isSent = true;
} catch (MessagingException e) { } catch (MessagingException e) {
//todo 邮件失败记录 //todo 邮件失败记录
// 异常处理 // 异常处理
retryCount.getAndIncrement(); retryCount.getAndIncrement();
if (retryCount.intValue() > MAX_RETRY) { if (retryCount.intValue() > MAX_RETRY) {
log.error("邮件发送达到最大重试次数: recordFileId->{}", recordFileId); log.error("邮件发送达到最大重试次数: meetingId->{}", meetingId);
throw new RuntimeException(e); throw new RuntimeException(e);
} }
// 指数退避 // 指数退避
...@@ -112,9 +117,8 @@ public class EmailSender { ...@@ -112,9 +117,8 @@ public class EmailSender {
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();
throw new RuntimeException("邮件发送重试失败", ie); throw new RuntimeException("邮件发送重试失败", ie);
} }
return false;
} }
} }
return true; return isSent;
} }
} }
\ No newline at end of file
package com.cmeeting.job;
import cn.chatbot.openai.completion.chat.ChatCompletionRequest;
import cn.chatbot.openai.completion.chat.ChatMessage;
import cn.chatbot.openai.completion.chat.ChatMessageRole;
import cn.chatbot.openai.completion.chat.Message;
import cn.chatbot.openai.service.LLMService;
import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.cmeeting.email.EmailSender;
import com.cmeeting.mapper.primary.MeetingInfoMapper;
import com.cmeeting.mapper.primary.MeetingRecordTemplateMapper;
import com.cmeeting.pojo.MeetingInfo;
import com.cmeeting.pojo.MeetingRecordTemplate;
import com.cmeeting.util.MinioUtils;
import com.deepoove.poi.XWPFTemplate;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.tencentcloudapi.wemeet.Client;
import com.tencentcloudapi.wemeet.core.authenticator.AuthenticatorBuilder;
import com.tencentcloudapi.wemeet.core.authenticator.JWTAuthenticator;
import com.tencentcloudapi.wemeet.service.meetings.api.MeetingsApi;
import com.tencentcloudapi.wemeet.service.meetings.model.V1MeetingsMeetingIdParticipantsGet200Response;
import com.tencentcloudapi.wemeet.service.meetings.model.V1MeetingsMeetingIdParticipantsGet200ResponseParticipantsInner;
import com.tencentcloudapi.wemeet.service.records.api.RecordsApi;
import com.tencentcloudapi.wemeet.service.records.model.V1AddressesRecordFileIdGet200Response;
import com.tencentcloudapi.wemeet.service.records.model.V1AddressesRecordFileIdGet200ResponseAiMeetingTranscriptsInner;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import okhttp3.OkHttpClient;
import okhttp3.Request;
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.stereotype.Service;
import java.io.*;
import java.math.BigInteger;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.SecureRandom;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
@Data
@NoArgsConstructor
@Slf4j
@Service
public class EmailPushTask {
private String meetingId;
private String subMeetingId;
private String savePath;
private Map<String, Object> metadata;
private static final int MAX_RETRY = 3;
private MeetingInfoMapper meetingInfoMapper;
private MinioUtils minioUtils;
private EmailSender emailSender;
private MeetingRecordTemplateMapper meetingRecordTemplateMapper;
// 实际处理逻辑
public void process() {
Boolean isSuccess = Boolean.FALSE;
AtomicInteger retryCount = new AtomicInteger(0);
MeetingInfo meetingInfo = meetingInfoMapper.selectOne(new LambdaQueryWrapper<MeetingInfo>()
.eq(MeetingInfo::getMeetingId,meetingId)
.eq(subMeetingId != null, MeetingInfo::getSubMeetingId, subMeetingId));
while (retryCount.intValue() <= MAX_RETRY && !isSuccess) {
try {
String nowTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd-HHmmss"));
String targetFileName;
String meetingName;
String recordXmlPath = meetingId + "-recordXmlPath-" + IdUtil.fastSimpleUUID() + "xml";
String xml;
try(InputStream is = minioUtils.getFile(recordXmlPath)){
xml = convertInputStreamToString(is);
}catch (Exception e){
log.error(e.getMessage());
continue;
}
//将xml格式的内容转换为map,用于填充模板
Map<String, Object> dataModel = convertXmlToMap(xml);
//追加参会人员信息
Map<String,Object> participantsMap = new ConcurrentHashMap<>();
participantsMap.put("meeting_date",meetingInfo.getStartTime().toLocalDate().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
participantsMap.put("meeting_location","线上腾讯会议");
participantsMap.put("meeting_participants", meetingInfo.getParticipantUsers());
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);
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"));
minioUtils.upload(recordXmlPath,recordXmlData);
//邮件推送
isSuccess = emailSender.sendEmailWithAttachment("duanxincheng@chatbot.cn",meetingName,savePath + targetFileName + ".docx",meetingId);
} catch (Exception e) {
// 异常处理
int currentRetryCount = retryCount.getAndIncrement();
if (currentRetryCount > MAX_RETRY) {
log.error("达到最大重试次数:meetingId {}", meetingId);
}else{
// 指数退避
try {
Thread.sleep((long) Math.pow(2, currentRetryCount) * 1000);
} catch (InterruptedException ie) {
Thread.currentThread().interrupt();
log.error("重试失败: {}", ie.getMessage());
}
}
}
}
meetingInfoMapper.update(meetingInfo,
new LambdaUpdateWrapper<MeetingInfo>()
.eq(MeetingInfo::getMeetingId,meetingId)
.eq(subMeetingId != null,MeetingInfo::getSubMeetingId,subMeetingId)
.set(MeetingInfo::getIsPushed,isSuccess)
.set(MeetingInfo::getPushRetry,Boolean.TRUE)
);
}
public static Map<String, Object> convertXmlToMap(String xml) throws Exception {
XmlMapper xmlMapper = new XmlMapper();
ObjectMapper objectMapper = new ObjectMapper();
// 先将 XML 读取为 Map
Map<?, ?> xmlMap = xmlMapper.readValue(xml, Map.class);
// 转换为更标准的 Map<String, Object>
Map<String,Object> map = objectMapper.convertValue(xmlMap, Map.class);
//特殊处理map格式
for (Map.Entry<String, Object> entry : map.entrySet()) {
Map<String,Object> value = (Map<String, Object>) entry.getValue();
Object realValue = value.get("");
entry.setValue(realValue);
}
return map;
}
public static String convertInputStreamToString(InputStream inputStream) throws IOException {
StringBuilder result = new StringBuilder();
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(inputStream, StandardCharsets.UTF_8))) {
String line;
while ((line = reader.readLine()) != null) {
result.append(line);
// 如果需要保留换行符,可添加:result.append("\n");
}
}
return result.toString();
}
public EmailPushTask(String meetingId, String subMeetingId, String savePath, Map<String, Object> metadata,
MeetingInfoMapper meetingInfoMapper, MinioUtils minioUtils, EmailSender emailSender, MeetingRecordTemplateMapper meetingRecordTemplateMapper) {
this.savePath = savePath;
this.metadata = metadata;
this.meetingId = meetingId;
this.subMeetingId = subMeetingId;
this.meetingInfoMapper = meetingInfoMapper;
this.minioUtils = minioUtils;
this.emailSender = emailSender;
this.meetingRecordTemplateMapper = meetingRecordTemplateMapper;
}
}
\ No newline at end of file
...@@ -8,5 +8,6 @@ import java.util.List; ...@@ -8,5 +8,6 @@ import java.util.List;
@Mapper @Mapper
public interface AuthMapper { public interface AuthMapper {
List<CoreModulePermissions> getAuthByTargrtId(@Param("targetId") String targetId, @Param("tenantId") String tenantId);
List<CoreModulePermissions> getAuthByTargetId(@Param("targetId") String targetId, @Param("tenantId") String tenantId);
} }
package com.cmeeting.mapper.primary;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.cmeeting.pojo.MeetingRecordTemplate;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface MeetingRecordTemplateMapper extends BaseMapper<MeetingRecordTemplate> {
}
\ No newline at end of file
package com.cmeeting.mapper.primary; package com.cmeeting.mapper.primary;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.cmeeting.pojo.UserId; import com.cmeeting.pojo.UserId;
import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Mapper;
import java.util.List; import java.util.List;
@Mapper @Mapper
public interface UserIdMapper { public interface UserIdMapper extends BaseMapper<UserId> {
void insertUsers (List<UserId> userIds); void insertUsers (List<UserId> userIds);
List<UserId> getUsers(); List<UserId> getUsers();
......
...@@ -7,7 +7,7 @@ import java.util.List; ...@@ -7,7 +7,7 @@ import java.util.List;
public interface WeComUserMapper extends BaseMapper<WeComUser> { public interface WeComUserMapper extends BaseMapper<WeComUser> {
List<WeComUser> getSameName() ; List<WeComUser> noBindUsers() ;
WeComUser selectById(Integer id); WeComUser selectById(Integer id);
int insert(WeComUser user); int insert(WeComUser user);
......
package com.cmeeting.mapper.secondary; package com.cmeeting.mapper.secondary;
import com.cmeeting.dto.UserDTO;
import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@Mapper @Mapper
public interface SysUserSysMapper { public interface SysUserSysMapper {
String getCompanyEmail(String wid, String tenantId); String getCompanyEmail(String wid, String tenantId);
String getParentDeptId(String deptId, String tenantId);
List<String> getSubDeptId(@Param(value = "deptId")String deptId,@Param(value = "tenantId") String tenantId);
List<String> getUsersByDept(@Param(value = "deptIds") List<String> deptIds,@Param(value = "tenantId") String tenantId);
List<UserDTO> getUserEmail(@Param(value = "tenantId")String tenantId);
} }
...@@ -20,6 +20,8 @@ import java.time.LocalDateTime; ...@@ -20,6 +20,8 @@ import java.time.LocalDateTime;
@Accessors(chain = true) @Accessors(chain = true)
@TableName("cmt_meeting_info") @TableName("cmt_meeting_info")
public class MeetingInfo implements Serializable { public class MeetingInfo implements Serializable {
private static final long serialVersionUID = -26238487532381000L;
/** /**
* 主键id * 主键id
*/ */
...@@ -48,12 +50,17 @@ public class MeetingInfo implements Serializable { ...@@ -48,12 +50,17 @@ public class MeetingInfo implements Serializable {
/** /**
* 主持人 * 主持人
*/ */
private String hostId; private String host;
/**
* 主持人uid
*/
private String hostUid;
/** /**
* 参会人员名单 * 参会人员名单
*/ */
private String participantUserIds; private String participantUsers;
/** /**
* 会议开始时间(时间戳) * 会议开始时间(时间戳)
...@@ -78,6 +85,14 @@ public class MeetingInfo implements Serializable { ...@@ -78,6 +85,14 @@ public class MeetingInfo implements Serializable {
*/ */
private Boolean isPushed; private Boolean isPushed;
/** /**
* 会议纪要重新生成标识
*/
private Boolean generateRetry;
/**
* 邮件推送重试标识
*/
private Boolean pushRetry;
/**
* 同步时间 * 同步时间
*/ */
private LocalDateTime syncTime; private LocalDateTime syncTime;
...@@ -91,4 +106,12 @@ public class MeetingInfo implements Serializable { ...@@ -91,4 +106,12 @@ public class MeetingInfo implements Serializable {
* 纪要xml * 纪要xml
*/ */
private String recordXml; private String recordXml;
/**
* 每个会议对应的转录文件id,多个用逗号分隔,按参会前后升序
*/
private String recordFileId;
/**
* 邮箱
*/
private String email;
} }
\ No newline at end of file
package com.cmeeting.pojo;
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("cmt_meeting_record_template")
public class MeetingRecordTemplate implements Serializable {
private static final long serialVersionUID = -26238487532381000L;
/**
* 主键id
*/
@TableId(type = IdType.AUTO)
private Integer id;
/**
* 模板名称
*/
private String name;
/**
* 模板类型(系统模板/自定义模板)
*/
private String type;
/**
* 会议类型
*/
private String meetingType;
/**
* 会议类型描述
*/
private String typeDetail;
/**
* 提示词内容
*/
private String prompt;
/**
* 创建时间
*/
private LocalDateTime createTime;
/**
* 创建时间
*/
private LocalDateTime updateTime;
/**
* 创建人
*/
private String createUser;
/**
* 更新人
*/
private String updateUser;
}
\ No newline at end of file
package com.cmeeting.pojo; package com.cmeeting.pojo;
import lombok.Data; import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.*;
import lombok.experimental.Accessors;
@Data import java.io.Serializable;
public class TencentMeetingUser { @Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("user_tencentmeeting")
public class TencentMeetingUser implements Serializable {
private static final long serialVersionUID = -26238487532381000L;
/** /**
* 主键ID * 主键ID
*/ */
@TableId(type = IdType.AUTO)
private Integer id; private Integer id;
/** /**
...@@ -25,26 +37,4 @@ public class TencentMeetingUser { ...@@ -25,26 +37,4 @@ public class TencentMeetingUser {
* 是否是重名用户(1:重名, 0:不重名) * 是否是重名用户(1:重名, 0:不重名)
*/ */
private String isrepeatName; private String isrepeatName;
// 无参构造方法
public TencentMeetingUser() {
}
// 全参构造方法
public TencentMeetingUser(Integer id, String userName, String userId, String isrepeatName) {
this.id = id;
this.userName = userName;
this.userId = userId;
this.isrepeatName = isrepeatName;
}
@Override
public String toString() {
return "TencentMeetingUser{" +
"id=" + id +
", userName='" + userName + '\'' +
", userId='" + userId + '\'' +
", isrepeatName='" + isrepeatName + '\'' +
'}';
}
} }
package com.cmeeting.pojo; package com.cmeeting.pojo;
import lombok.Data; import com.baomidou.mybatisplus.annotation.TableName;
import lombok.*;
import lombok.experimental.Accessors;
@Data @Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("userid")
public class UserId { public class UserId {
/** /**
* 主键ID * 主键ID
...@@ -24,23 +32,4 @@ public class UserId { ...@@ -24,23 +32,4 @@ public class UserId {
*/ */
private String tid; private String tid;
// 无参构造方法
public UserId() {
}
// 全参构造方法
public UserId(Integer id, String userName, String wid, String tid) {
this.id = id;
this.userName = userName;
this.wid = wid;
this.tid = tid;
}
// 全参构造方法
public UserId( String userName, String wid, String tid) {
this.userName = userName;
this.wid = wid;
this.tid = tid;
}
} }
package com.cmeeting.pojo; package com.cmeeting.pojo;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.activerecord.Model; import com.baomidou.mybatisplus.extension.activerecord.Model;
import lombok.Data; import lombok.*;
import lombok.experimental.Accessors;
import java.io.Serializable; import java.io.Serializable;
@Data @Data
public class WeComUser extends Model implements Serializable { @AllArgsConstructor
@NoArgsConstructor
@Builder
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("user_wecom")
public class WeComUser implements Serializable {
private static final long serialVersionUID = -26238487532381000L;
@TableId(type = IdType.AUTO)
private Integer id; private Integer id;
private String userName; private String userName;
private String userId; private String userId;
private String isRepeatName; private String isRepeatName;
private String email; private String email;
public WeComUser() {
}
public WeComUser(Integer id, String userName, String userId, String isRepeatName) {
this.id = id;
this.userName = userName;
this.userId = userId;
this.isRepeatName = isRepeatName;
}
@Override
public String toString() {
return "WeComUser{" +
"id=" + id +
", userName='" + userName + '\'' +
", userId='" + userId + '\'' +
", isRepeatName='" + isRepeatName + '\'' +
", email='" + email + '\'' +
'}';
}
} }
...@@ -11,7 +11,7 @@ public class FileProcessCallbackHandler { ...@@ -11,7 +11,7 @@ public class FileProcessCallbackHandler {
// 单个任务完成回调 // 单个任务完成回调
public void onComplete(FileProcessTask task) { public void onComplete(FileProcessTask task) {
// 可以记录任务状态、发送通知等 // 可以记录任务状态、发送通知等
log.info("任务处理完成: {}", task.getRecordFileId()); log.info("任务处理完成: meetingId {}", task.getMeetingId());
// 更新数据库状态等 // 更新数据库状态等
// taskRepository.updateStatus(task.getId(), "COMPLETED"); // taskRepository.updateStatus(task.getId(), "COMPLETED");
......
package com.cmeeting.service; package com.cmeeting.service;
import com.cmeeting.dto.UserDTO;
import com.cmeeting.email.EmailSender; import com.cmeeting.email.EmailSender;
import com.cmeeting.job.EmailPushTask;
import com.cmeeting.job.FileProcessTask; import com.cmeeting.job.FileProcessTask;
import com.cmeeting.mapper.primary.MeetingInfoMapper; import com.cmeeting.mapper.primary.MeetingInfoMapper;
import com.cmeeting.mapper.primary.MeetingRecordTemplateMapper;
import com.cmeeting.pojo.UserId;
import com.cmeeting.util.MinioUtils; import com.cmeeting.util.MinioUtils;
import com.cmeeting.vo.TencentMeetingVO; import com.cmeeting.vo.TencentMeetingVO;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
...@@ -37,24 +41,33 @@ public class FileProcessProducer { ...@@ -37,24 +41,33 @@ public class FileProcessProducer {
private String tencentSecretKey; private String tencentSecretKey;
@Value(value = "${tencent.admin.userId}") @Value(value = "${tencent.admin.userId}")
private String tencentAdminUserId; private String tencentAdminUserId;
@Value(value = "${llm.api-addr}")
private String llmApiAddr;
@Resource @Resource
private MeetingInfoMapper meetingInfoMapper; private MeetingInfoMapper meetingInfoMapper;
@Resource @Resource
private MeetingRecordTemplateMapper meetingRecordTemplateMapper;
@Resource
private MinioUtils minioUtils; private MinioUtils minioUtils;
@Resource @Resource
private EmailSender emailSender; private EmailSender emailSender;
// 批量提交任务 /**
public void submitBatchTasks(List<TencentMeetingVO.RecordFile> recordFiles, String baseSavePath) { * 批量提交生成纪要任务
* @param recordFiles 转录文件信息
* @param baseSavePath 存储临时路径
* @param finalRetry
*/
public void submitBatchTasks(List<TencentMeetingVO.RecordFile> recordFiles, String baseSavePath, Boolean finalRetry) {
List<Future<?>> futures = new ArrayList<>(); List<Future<?>> futures = new ArrayList<>();
for (TencentMeetingVO.RecordFile recordFile : recordFiles) { for (TencentMeetingVO.RecordFile recordFile : recordFiles) {
// 为每个URL创建任务 // 为每个URL创建任务
FileProcessTask task = new FileProcessTask( FileProcessTask task = new FileProcessTask(
recordFile.getRecordFileId(), recordFile.getRecordFileIdList(),
recordFile.getMeetingId(), recordFile.getMeetingId(),
recordFile.getSubMeetingId(), recordFile.getSubMeetingId(),
"/save/", baseSavePath,
Collections.emptyMap(), Collections.emptyMap(),
tencentAppId, tencentAppId,
tencentSdkId, tencentSdkId,
...@@ -63,7 +76,10 @@ public class FileProcessProducer { ...@@ -63,7 +76,10 @@ public class FileProcessProducer {
tencentAdminUserId, tencentAdminUserId,
meetingInfoMapper, meetingInfoMapper,
minioUtils, minioUtils,
emailSender emailSender,
meetingRecordTemplateMapper,
llmApiAddr,
finalRetry
); );
// 提交任务到线程池 // 提交任务到线程池
...@@ -79,6 +95,35 @@ public class FileProcessProducer { ...@@ -79,6 +95,35 @@ public class FileProcessProducer {
monitorTaskCompletion(futures); monitorTaskCompletion(futures);
} }
// 批量提交邮箱推送重试任务
public void submitEmailPushTasks(List<TencentMeetingVO.RecordFile> recordFiles, String baseSavePath) {
List<Future<?>> futures = new ArrayList<>();
for (TencentMeetingVO.RecordFile recordFile : recordFiles) {
// 为每个URL创建任务
EmailPushTask task = new EmailPushTask(
recordFile.getMeetingId(),
recordFile.getSubMeetingId(),
baseSavePath,
Collections.emptyMap(),
meetingInfoMapper,
minioUtils,
emailSender,
meetingRecordTemplateMapper
);
// 提交任务到线程池
Future<?> future = fileProcessExecutor.submit(() -> {
task.process();
});
futures.add(future);
}
// 可以添加一个监控线程来检查所有任务完成情况
monitorTaskCompletion(futures);
}
private void monitorTaskCompletion(List<Future<?>> futures) { private void monitorTaskCompletion(List<Future<?>> futures) {
new Thread(() -> { new Thread(() -> {
for (Future<?> future : futures) { for (Future<?> future : futures) {
......
package com.cmeeting.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.cmeeting.pojo.MeetingRecordTemplate;
public interface MeetingRecordTemplateService extends IService<MeetingRecordTemplate> {
}
package com.cmeeting.service; package com.cmeeting.service;
import com.baomidou.mybatisplus.extension.service.IService; import com.baomidou.mybatisplus.extension.service.IService;
import com.cmeeting.dto.UserDTO;
import com.cmeeting.pojo.TencentMeetingUser; import com.cmeeting.pojo.TencentMeetingUser;
import com.cmeeting.pojo.UserId;
import com.cmeeting.vo.TencentMeetingVO; import com.cmeeting.vo.TencentMeetingVO;
import java.util.List; import java.util.List;
...@@ -11,6 +13,10 @@ public interface TecentMeetingService extends IService<TencentMeetingUser> { ...@@ -11,6 +13,10 @@ public interface TecentMeetingService extends IService<TencentMeetingUser> {
void doUsers(); void doUsers();
List<TencentMeetingVO.RecordFile> getMeetingFiles(); List<TencentMeetingVO.RecordFile> getMeetingFiles(List<UserDTO> accessUserIds);
List<UserDTO> getAccessUserIds();
String getMeetingHost(String meetingCode);
} }
...@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.extension.service.IService; ...@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.extension.service.IService;
import com.cmeeting.pojo.WeComUser; import com.cmeeting.pojo.WeComUser;
import java.util.List; import java.util.List;
import java.util.Map;
public interface WeComService extends IService<WeComUser> { public interface WeComService extends IService<WeComUser> {
...@@ -12,4 +13,10 @@ public interface WeComService extends IService<WeComUser> { ...@@ -12,4 +13,10 @@ public interface WeComService extends IService<WeComUser> {
void doUsers() throws Exception; void doUsers() throws Exception;
String getToken(); String getToken();
List<WeComUser> noBindUsers();
Map<String, String> createTempMeeting(String wid, String token);
void cancelMeeting(String meetingId, String weComToken);
} }
package com.cmeeting.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cmeeting.mapper.primary.MeetingRecordTemplateMapper;
import com.cmeeting.pojo.MeetingRecordTemplate;
import com.cmeeting.service.MeetingRecordTemplateService;
import org.springframework.stereotype.Service;
@Service
public class MeetingRecordTemplateServiceImpl extends ServiceImpl<MeetingRecordTemplateMapper, MeetingRecordTemplate> implements MeetingRecordTemplateService {
}
\ No newline at end of file
...@@ -33,6 +33,16 @@ public class MinioUtils { ...@@ -33,6 +33,16 @@ public class MinioUtils {
} }
} }
public InputStream getFile(String fileName){
try{
getMinioClient();
InputStream inputStream = minioClient.getObject(bucketName, fileName);
return inputStream;
}catch (Exception e){
throw new RuntimeException(e);
}
}
public InputStream getFile(MinioClient minioClient, String fileName){ public InputStream getFile(MinioClient minioClient, String fileName){
try{ try{
InputStream inputStream = minioClient.getObject(bucketName, fileName); InputStream inputStream = minioClient.getObject(bucketName, fileName);
......
...@@ -9,8 +9,6 @@ import com.google.gson.JsonElement; ...@@ -9,8 +9,6 @@ import com.google.gson.JsonElement;
import java.util.*; import java.util.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static com.cmeeting.WeComAndTencentMeeting.getUserListByDepartment;
public class WeComUserService { public class WeComUserService {
// 假设这是你的MyBatis Mapper // 假设这是你的MyBatis Mapper
...@@ -21,23 +19,6 @@ public class WeComUserService { ...@@ -21,23 +19,6 @@ public class WeComUserService {
} }
/** /**
* 处理部门用户数据并存入数据库
*/
public void processAndSaveDepartmentUsers(int departmentId) throws Exception {
// 1. 获取企业微信API数据
JsonObject result = getUserListByDepartment(departmentId);
// 2. 转换为WeComUser集合
List<WeComUser> users = convertJsonToWeComUsers(result);
// 3. 检查重名并设置标志
markDuplicateNames(users);
// 4. 批量插入数据库
weComUserMapper.batchInsert(users);
}
/**
* 将企业微信返回的JSON转换为WeComUser列表 * 将企业微信返回的JSON转换为WeComUser列表
*/ */
private List<WeComUser> convertJsonToWeComUsers(JsonObject json) { private List<WeComUser> convertJsonToWeComUsers(JsonObject json) {
......
...@@ -6,6 +6,8 @@ import lombok.Builder; ...@@ -6,6 +6,8 @@ import lombok.Builder;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import java.util.List;
@Data @Data
@Builder @Builder
public class TencentMeetingVO { public class TencentMeetingVO {
...@@ -30,6 +32,6 @@ public class TencentMeetingVO { ...@@ -30,6 +32,6 @@ public class TencentMeetingVO {
public static class RecordFile{ public static class RecordFile{
private String meetingId;//如果是周期会议,这个id表示主会议 private String meetingId;//如果是周期会议,这个id表示主会议
private String subMeetingId;//如果是周期会议,这个id表示子会议 private String subMeetingId;//如果是周期会议,这个id表示子会议
private String recordFileId; private List<String> recordFileIdList;
} }
} }
\ No newline at end of file
server: server:
port: 8080 port: 8080
# ???????? ############################################################## minio
# application.yml MINIO_ADDRESS: http://192.168.10.154:9000
# spring.datasource.url=jdbc:mysql://192.168.10.155:3306/cmeeting?useSSL=false&characterEncoding=utf8 MINIO_BUCKET: zhongji
# spring.datasource.username=root MINIO_USERNAME: minio
# spring.datasource.password=qizhi123 MINIO_PASSWORD: minio123
# spring.datasource.driver-class-name=com.mysql.jdbc.Driver ############################################################## redis
REDIS_ADDRESS: 192.168.10.154
REDIS_PORT: 6380
REDIS_PASS: standard123
REDIS_DATABASE: 8
############################################################## llm
# local
LLM_API_ADDR: https://bedrock.chatbot.cn
# prod
#LLM_API_ADDR: http://10.56.1.150:8000
############################################################## tencent meeting
# local
#TENCENT_APPID: 211153201
#TENCENT_SDKID: 28370276340
#TENCENT_SECRETID: BKOMDZVbvh0iT7k6UHsSizAWBCOVDtT6
#TENCENT_SECRETKEY: 3Y1j0mzNp7KChKFJGyaEnZHLobFoAQ8eLwfaMx8nLbtXAerO
#TENCENT_ADMIN_USERID: woaJARCQAAhkyWGuf8n9InhZsxQstjjA
#TENCENT_ADMIN_USERID: woaJARCQAAJU1EsO73Ww5rn8YHMW6iYA
# prod
TENCENT_APPID: 210468336
TENCENT_SDKID: 28790143843
TENCENT_SECRETID: 0ks7u8cgQ8DGVtlYZeRA9TxZCjvUT3oL
TENCENT_SECRETKEY: gQU09rkJjiQfiGcUYdhiKq5Ol6LebXg4w7F7Ol0rwvvdv3Xy
TENCENT_ADMIN_USERID: woaJARCQAAftcvU6GGoOn66rdSZ4IrOA
############################################################## email
EMAIL_SENDER: cmeeting_assistant@cimc.com
EMAIL_SENDER_PWD: scyou@xih45g6@xih4
EMAIL_SMTP_HOST: smtp.office365.com
############################################################## permission
PERMISSION_APPLiCATION_ID: 1928343847335759872
PERMISSION_TENANT_ID: 1928343652791357440
# ?????primary?
#spring.datasource.primary.jdbc-url=jdbc:mysql://192.168.10.154:3307/aigc-zhongji-test?useSSL=false&characterEncoding=utf8&serverTimezone=UTC
##spring.datasource.primary.username=root
##spring.datasource.primary.password=123456
##spring.datasource.primary.driver-class-name=com.mysql.jdbc.Driver
##
### ?????secondary?
##spring.datasource.secondary.jdbc-url=jdbc:mysql://192.168.10.154:3307/useradmin-zhongji-test?useSSL=false&characterEncoding=utf8&serverTimezone=UTC
##spring.datasource.secondary.username=root
##spring.datasource.secondary.password=123456
##spring.datasource.secondary.driver-class-name=com.mysql.jdbc.Driver
spring: spring:
datasource: datasource:
...@@ -34,12 +56,23 @@ spring: ...@@ -34,12 +56,23 @@ spring:
username: root username: root
password: 123456 password: 123456
driver-class-name: com.mysql.jdbc.Driver driver-class-name: com.mysql.jdbc.Driver
redis:
database: ${REDIS_DATABASE}
host: ${REDIS_ADDRESS}
jedis:
pool:
max-active: 8
max-idle: 8
max-wait: 30000ms
min-idle: 1
port: ${REDIS_PORT}
timeout: 6000ms
password: ${REDIS_PASS}
# MyBatis ?? # MyBatis ??
# mybatis.mapper-locations=classpath:mapper/primary/*.xml # mybatis.mapper-locations=classpath:mapper/primary/*.xml
mybatis.type-aliases-package: com.cmeeting.pojo\ mybatis.type-aliases-package: com.cmeeting.pojo\
# ??????
mybatis: mybatis:
configuration: configuration:
map-underscore-to-camel-case: true map-underscore-to-camel-case: true
...@@ -52,19 +85,6 @@ global-config: ...@@ -52,19 +85,6 @@ global-config:
db-config: db-config:
column-underline: true column-underline: true
#logging:
# level:
# com:
# zaxxer:
# hikari: INFO
############################################################## minIO
MINIO_ADDRESS: http://192.168.10.154:9000
MINIO_BUCKET: zhongji
MINIO_USERNAME: minio
MINIO_PASSWORD: minio123
#Minio服务所在地址 #Minio服务所在地址
minio.endpoint: ${MINIO_ADDRESS} minio.endpoint: ${MINIO_ADDRESS}
#存储桶名称 #存储桶名称
...@@ -73,33 +93,28 @@ minio.bucketName: ${MINIO_BUCKET} ...@@ -73,33 +93,28 @@ minio.bucketName: ${MINIO_BUCKET}
minio.accessKey: ${MINIO_USERNAME} minio.accessKey: ${MINIO_USERNAME}
#访问的秘钥 #访问的秘钥
minio.secretKey: ${MINIO_PASSWORD} minio.secretKey: ${MINIO_PASSWORD}
############################################################## minIO
############################################################## tencent meeting
# local
#tencent.appId=211153201
#tencent.sdkId=28370276340
#tencent.secretId=BKOMDZVbvh0iT7k6UHsSizAWBCOVDtT6
#tencent.secretKey=3Y1j0mzNp7KChKFJGyaEnZHLobFoAQ8eLwfaMx8nLbtXAerO
#tencent.admin.userId=woaJARCQAAJU1EsO73Ww5rn8YHMW6iYA
#tencent.admin.userId=woaJARCQAAhkyWGuf8n9InhZsxQstjjA
# prod
tencent: tencent:
appId: 210468336 appId: ${TENCENT_APPID}
sdkId: 28790143843 sdkId: ${TENCENT_SDKID}
secretId: 0ks7u8cgQ8DGVtlYZeRA9TxZCjvUT3oL secretId: ${TENCENT_SECRETID}
secretKey: gQU09rkJjiQfiGcUYdhiKq5Ol6LebXg4w7F7Ol0rwvvdv3Xy secretKey: ${TENCENT_SECRETKEY}
admin.userId: woaJARCQAAftcvU6GGoOn66rdSZ4IrOA admin.userId: ${TENCENT_ADMIN_USERID}
meeting: meeting:
token: QQZNb7xWQB47MpZF4C2DFAkv8 token: QQZNb7xWQB47MpZF4C2DFAkv8
aesKey: agy6ALUePp34lljWz1uIQWa7yQq3dgxxQNmfaN9GROm aesKey: agy6ALUePp34lljWz1uIQWa7yQq3dgxxQNmfaN9GROm
email: email:
sender: cmeeting_assistant@cimc.com sender: ${EMAIL_SENDER}
sender-pwd: scyou@xih45g6@xih4 sender-pwd: ${EMAIL_SENDER_PWD}
smtp-host: smtp.office365.com smtp-host: ${EMAIL_SMTP_HOST}
############################################################## tencent meeting
llm:
api-addr: ${LLM_API_ADDR}
permission:
applicationId: ${PERMISSION_APPLiCATION_ID}
tenantId: ${PERMISSION_TENANT_ID}
logging: logging:
level: level:
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<!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.cmeeting.mapper.primary.AuthMapper"> <mapper namespace="com.cmeeting.mapper.primary.AuthMapper">
<select id="getAuthByTargrtId" resultType="com.cmeeting.pojo.CoreModulePermissions"> <select id="getAuthByTargetId" resultType="com.cmeeting.pojo.CoreModulePermissions">
SELECT SELECT
id, id,
type, type,
...@@ -16,7 +16,8 @@ ...@@ -16,7 +16,8 @@
FROM FROM
core_module_permissions core_module_permissions
WHERE WHERE
target_id = #{targetId} user_type = 2
and target_id = #{targetId}
<if test="tenantId != null and tenantId != ''"> <if test="tenantId != null and tenantId != ''">
AND tenant_id = #{tenantId} AND tenant_id = #{tenantId}
</if> </if>
......
...@@ -2,16 +2,17 @@ ...@@ -2,16 +2,17 @@
<!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.cmeeting.mapper.primary.MeetingInfoMapper"> <mapper namespace="com.cmeeting.mapper.primary.MeetingInfoMapper">
<insert id="batchInsert" parameterType="list"> <insert id="batchInsert" parameterType="list">
INSERT IGNORE INTO cmt_meeting_info (subject, meeting_id, meeting_code, host_id, participant_user_ids, start_time, INSERT IGNORE INTO cmt_meeting_info (subject, meeting_id, meeting_code, host, participant_users, start_time,
end_time, is_generated, email_push_access, is_pushed, sync_time, sub_meeting_id, record_content, record_xml) end_time, is_generated, email_push_access, is_pushed, sync_time, sub_meeting_id, record_content, record_xml, generate_retry,
push_retry, record_file_id,email)
VALUES VALUES
<foreach collection="meetingSaveList" item="meeting" separator=","> <foreach collection="meetingSaveList" item="meeting" separator=",">
( (
#{meeting.subject}, #{meeting.subject},
#{meeting.meetingId}, #{meeting.meetingId},
#{meeting.meetingCode}, #{meeting.meetingCode},
#{meeting.hostId}, #{meeting.host},
#{meeting.participantUserIds}, #{meeting.participantUsers},
#{meeting.startTime}, #{meeting.startTime},
#{meeting.endTime}, #{meeting.endTime},
#{meeting.isGenerated}, #{meeting.isGenerated},
...@@ -20,7 +21,11 @@ end_time, is_generated, email_push_access, is_pushed, sync_time, sub_meeting_id, ...@@ -20,7 +21,11 @@ end_time, is_generated, email_push_access, is_pushed, sync_time, sub_meeting_id,
#{meeting.syncTime}, #{meeting.syncTime},
#{meeting.subMeetingId}, #{meeting.subMeetingId},
#{meeting.recordContent}, #{meeting.recordContent},
#{meeting.recordXml} #{meeting.recordXml},
#{meeting.generateRetry},
#{meeting.pushRetry},
#{meeting.recordFileId},
#{meeting.email}
) )
</foreach> </foreach>
</insert> </insert>
......
...@@ -4,9 +4,9 @@ ...@@ -4,9 +4,9 @@
<!-- 批量插入用户ID信息 --> <!-- 批量插入用户ID信息 -->
<insert id="insertUsers" parameterType="List"> <insert id="insertUsers" parameterType="List">
INSERT INTO userid ( INSERT INTO userid (
userName, user_name,
Wid, wid,
Tid tid
) VALUES ) VALUES
<foreach collection="list" item="item" separator=","> <foreach collection="list" item="item" separator=",">
( (
...@@ -19,14 +19,14 @@ ...@@ -19,14 +19,14 @@
<!-- 更新 Tid 字段 --> <!-- 更新 Tid 字段 -->
<update id="updateUser" parameterType="com.cmeeting.pojo.UserId"> <update id="updateUser" parameterType="com.cmeeting.pojo.UserId">
UPDATE userid UPDATE userid
SET Tid = #{tid} SET tid = #{tid}
WHERE wid = #{wid} WHERE wid = #{wid}
</update> </update>
<select id="getUsers" resultType="com.cmeeting.pojo.UserId"> <select id="getUsers" resultType="com.cmeeting.pojo.UserId">
select * from userid select * from userid
</select> </select>
<select id="getWidByTid" resultType="java.lang.String"> <select id="getWidByTid" resultType="java.lang.String">
select Wid from userid WHERE Tid = #{operatorUserId} select wid from userid WHERE Tid = #{operatorUserId}
</select> </select>
</mapper> </mapper>
\ No newline at end of file
...@@ -30,8 +30,10 @@ ...@@ -30,8 +30,10 @@
<select id="getAlluser" resultType="com.cmeeting.pojo.WeComUser"> <select id="getAlluser" resultType="com.cmeeting.pojo.WeComUser">
SELECT * FROM user_wecom SELECT * FROM user_wecom
</select> </select>
<select id="getSameName" resultType="com.cmeeting.pojo.WeComUser"> <select id="noBindUsers" resultType="com.cmeeting.pojo.WeComUser">
SELECT * FROM user_wecom SELECT t1.*
WHERE isrepeat_name = "1" FROM user_wecom t1
left join userid t2 on t1.user_id = t2.Wid
WHERE t2.id is null
</select> </select>
</mapper> </mapper>
\ No newline at end of file
...@@ -9,4 +9,31 @@ ...@@ -9,4 +9,31 @@
AND tenant_id = #{tenantId} AND tenant_id = #{tenantId}
LIMIT 1 LIMIT 1
</select> </select>
<select id="getParentDeptId" resultType="java.lang.String">
SELECT parent_id
FROM sys_user_sync_category
WHERE dept_id = #{deptId}
AND tenant_id = #{tenantId}
LIMIT 1
</select>
<select id="getSubDeptId" resultType="java.lang.String">
SELECT dept_id
FROM sys_user_sync_category
WHERE parent_id = #{deptId}
AND tenant_id = #{tenantId}
</select>
<select id="getUsersByDept" resultType="java.lang.String">
select t1.user_id as wId
from sys_user_sync t1
where t1.dept_id in
<foreach collection="deptIds" item="deptId" separator="," open="(" close=")">
#{deptId}
</foreach>
</select>
<select id="getUserEmail" resultType="com.cmeeting.dto.UserDTO">
select t1.user_id as wId,IFNULL(t1.email,t1.company_email) as email
from sys_user_sync t1
where t1.email is not null
or t1.company_email is not null
</select>
</mapper> </mapper>
\ No newline at end of file
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论