提交 b855e0ea 作者: duanxincheng

迭代纪要生成大模型调用服务,转录文件上传至知识向量库,邮件推送开关

父级 20004cec
......@@ -357,6 +357,12 @@
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
<dependency>
<groupId>cn.chatbot</groupId>
<artifactId>meetingLLM</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>
<build>
......
......@@ -2,6 +2,8 @@ package com.cmeeting.ad.config;
import cn.hutool.core.util.ArrayUtil;
import com.cmeeting.ad.filter.RobotJwtAuthenticationTokenFilter;
import com.cmeeting.ad.handler.RobotAccessDeniedHandler;
import com.cmeeting.ad.handler.RobotAuthenticationEntryPointImpl;
import com.cmeeting.ad.service.CustomUserDetailsService;
import com.cmeeting.ad.service.UserService;
import lombok.extern.slf4j.Slf4j;
......@@ -119,10 +121,10 @@ public class RobotWebSecurityConfig extends WebSecurityConfigurerAdapter {
// 添加自定义异常入口
// httpSecurity
// .exceptionHandling()
// .authenticationEntryPoint(new RobotAuthenticationEntryPointImpl())
// .accessDeniedHandler(new RobotAccessDeniedHandler());
httpSecurity
.exceptionHandling()
.authenticationEntryPoint(new RobotAuthenticationEntryPointImpl())
.accessDeniedHandler(new RobotAccessDeniedHandler());
// 添加JWT filter 用户名登录
httpSecurity
......
package com.cmeeting.ad.handler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandler;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @Classname PreAccessDeniedHandler
* @Description 用来解决匿名用户访问无权限资源时的异常
* @Author Created by robot
* @Date 2019/12/19 3:35 下午
* @Version 1.0
*/
@Slf4j
public class RobotAccessDeniedHandler implements AccessDeniedHandler {
@Override
public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException e)
throws IOException, ServletException {
// log.error("请求访问: " + request.getRequestURI() + " 接口, 没有访问权限");
// SecurityUtil.writeJavaScript(R.error(HttpStatus.HTTP_UNAUTHORIZED,
// "请求访问:" + request.getRequestURI() + "接口,没有访问权限"), response);
}
}
package com.cmeeting.ad.handler;
import cn.hutool.json.JSONUtil;
import com.cmeeting.util.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Serializable;
/**
* 用来解决认证过的用户访问无权限资源时的异常
*
* @author robot
*/
@Slf4j
public class RobotAuthenticationEntryPointImpl implements AuthenticationEntryPoint, Serializable {
private static final long serialVersionUID = -8970718410437077606L;
@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) throws IOException {
log.error("请求访问: " + request.getRequestURI() + " 接口, 经jwt认证失败,无法访问系统资源.");
response.setContentType("application/json;charset=UTF-8");
PrintWriter writer = null;
try {
writer = response.getWriter();
writer.write(JSONUtil.toJsonPrettyStr(R.error(401, "登录超时,请重新登录")));
writer.flush();
} catch (IOException ex) {
log.error(ex.getMessage());
} finally {
if (writer != null) {
writer.close();
}
}
}
}
......@@ -231,18 +231,16 @@ public class UserServiceImpl implements UserService {
@Override
public Object tokenAuth(ApplicationUserVO.LoginDecrypt vo) {
// String aigcToken = vo.getData();
// String url = userAdminConfig.getSystemDomain() + "/cloud/info";
// JSONObject object = HttpClientUtils.httpGet(url, aigcToken);
// if("0".equals(object.get("code"))){
// return null;
// }
// JSONObject data = object.getJSONObject("data");
// RobotSecurityUser robotSecurityUser = JSON.parseObject(data.toJSONString(), RobotSecurityUser.class);
RobotSecurityUser robotSecurityUser = new RobotSecurityUser();
robotSecurityUser.setUsername("00010786");
robotSecurityUser.setNickName("黄飞");
UserVo.Auth authParams = UserVo.Auth.builder().id(robotSecurityUser.getUsername()).nick(robotSecurityUser.getNickName()).build();
String aigcToken = vo.getData();
String url = userAdminConfig.getSystemDomain() + "/cloud/info";
JSONObject object = HttpClientUtils.httpGet(url, aigcToken);
if("0".equals(object.get("code"))){
return null;
}
JSONObject data = object.getJSONObject("data");
RobotSecurityUser robotSecurityUser = JSON.parseObject(data.toJSONString(), RobotSecurityUser.class);
UserVo.Auth authParams = UserVo.Auth.builder().id(String.format("%08d", robotSecurityUser.getUserId())).nick(robotSecurityUser.getNickName()).build();
String token = auth(authParams);
return token;
}
......
package com.cmeeting.constant;
/**
* @author liuzhenmeng
* @date 2024/6/27 19:43
*/
public interface KnowledgePlatformRouteConstant {
/**
* 文档库相关接口路由
*/
interface DocLibrary {
/**
* 新增文档库
*/
String ADD_DOC_LIBRARY_URL = "/docLibrary/add";
/**
* 编辑文档库
*/
String EDIT_DOC_LIBRARY_URL = "/docLibrary/edit";
/**
* 删除文档库
*/
String REMOVE_DOC_LIBRARY_URL = "/docLibrary/delete";
/**
* 文档库详情
*/
String DOC_LIBRARY_INFO_URL = "/docLibrary/info";
/**
* 文档库列表
*/
String DOC_LIBRARY_LIST_URL = "/docLibrary/list";
/**
* 获取用户文档库权限
*/
String DOC_LIBRARY_AUTHORITY_URL = "/docLibrary/authority";
/**
* 查询用户所有有权限的文档库
*/
String DOC_LIBRARY_ALL_URL = "/docLibrary/all";
/**
* 文档库授权列表查询
*/
String DOC_LIBRARY_AUTH_LIST_URL = "/docLibrary/authList";
/**
* 文档库授权
*/
String DOC_LIBRARY_AUTH_URL = "/docLibrary/auth";
/**
* 移除文档库授权
*/
String DOC_LIBRARY_AUTH_REMOVE_URL = "/docLibrary/removeAuth";
String DOC_LIBRARY_AUTH_REMOVE_BY_RELID_URL = "/docLibrary/removeAuthByRelId";
String DOC_LIBRARY_AUTH_REMOVE_BY_RELIDS_URL = "/docLibrary/removeAuthByRelIds";
/**
* 咨询窗获取个人库和系统库分类id
*/
String DOC_LIBRARY_SYS_AND_PERSONAL_CATEGORY_URL = "/docLibrary/getSysAndPersonalCategoryId";
/**
* 修改分类文档名称
*/
String DOC_LIBRARY_UPDATE_CATEGORY_OR_DOC_NAME_URL = "/docLibrary/updateCategoryOrDocName";
/**
* 文档库数据报告
*/
String DOC_LIBRARY_REPORT_URL = "/docLibrary/getDocLibraryReportByTenant";
/**
* 个人库数据报告
*/
String PERSON_DOC_LIBRARY_REPORT_URL = "/docLibrary/getPersonDocLibraryReport";
/**
* 文档库权限设置
*/
String DOC_LIBRARY_PURVIEW_SET_URL = "/docLibraryPurview/set";
/**
* 文档库权限详情
*/
String DOC_LIBRARY_PURVIEW_INFO_URL = "/docLibraryPurview/info";
}
/**
* 文档分类相关接口路由
*/
interface DocCategory {
/**
* 创建文档分类
*/
String DOC_CATEGORY_ADD_URL = "/category/add";
/**
* 编辑文档分类
*/
String DOC_CATEGORY_EDIT_URL = "/category/edit";
/**
* 文档分类详情
*/
String DOC_CATEGORY_INFO_URL = "/category/info";
/**
* 删除文档分类
*/
String DOC_CATEGORY_REMOVE_URL = "/category/delete";
/**
* 文档分类树
*/
String DOC_CATEGORY_TREE_URL = "/category/tree";
/**
* 文档分类list
*/
String DOC_CATEGORY_LIST_URL = "/category/list";
/**
* 分类查询分类和文档树
*/
String DOC_CATEGORY_DOC_TREE_URL= "/category/docAndCategoryTree";
/**
* 分类查询分类和文档分页
*/
String DOC_CATEGORY_PAGE_URL = "/category/getDocAndCategoryPage";
String DOC_PAGE_URL = "/category/getDoc";
/**
* 个人库一级分类
*/
String PERSON_LIBRARY_LEVEL_CATEGORY_URL = "/category/personLibraryLevelCategory";
/**
* 获取当前分类的父类顺序list
*/
String DOC_CATEGORY_SORT_LIST_URL = "/category/getCategorySortList";
/**
* 获取分享分类list
*/
String DOC_CATEGORY_SHARE_LIST_URL = "/category/getShareCategory";
/**
* 个人库分类文档
*/
String PERSON_TREE_URL = "/category/personLibraryTree";
/**
* 文档分类list
*/
String DOC_CATEGORY_LIST_IDS_URL = "/category/listByCategoryIds";
/**
* 文档分类list
*/
String DOC_CATEGORY_MOVE_URL = "/category/move";
}
/**
* 文档操作相关接口路由
*/
interface DOC {
/**
* 新增文档
*/
String DOC_ADD_URL = "/doc/add";
/**
* 编辑文档
*/
String DOC_EDIT_URL = "/doc/edit";
/**
* 文档停启用
*/
String DOC_ENABLED_URL = "/doc/enabled";
/**
* 上传文档
*/
String DOC_UPLOAD_URL = "/doc/upload";
/**
* 删除文档
*/
String DOC_DELETE_URL = "/doc/delete";
/**
* 文档详情
*/
String DOC_INFO_URL = "/doc/info";
/**
* 获取文档详情包含附件文档用户鉴权
*/
String DOC_FILE_INFO_URL = "/doc/fileInfo";
/**
* 文档移动
*/
String DOC_MOVE_URL = "/doc/move";
/**
* 修改文档信息
*/
String DOC_MODIFY_URL = "/doc/modify";
/**
* 文档同步/取消同步
*/
String DOC_SYNC_URL = "/doc/synchronization";
/**
* 文档批量同步
*/
String DOC_BATCH_SYNC_URL = "/doc/batchSync";
/**
* 根据条件批量同步文档
*/
String DOC_BATCH_SYNC_BY_PARAM = "/doc/batchSyncDocByParam";
/**
* 获取文档列表
*/
String DOC_LIST_URL = "/doc/list";
/**
* 获取文档列表分页
*/
String DOC_LIST_BY_PAGE_URL = "/doc/listByPage";
/**
* 获取有权限的所有文档
*/
String DOC_AUTH_ALL_URL = "/doc/all";
/**
* 对接文档上传文件接口
*/
String SIMPLE_DOC_UPLOAD_URL = "/doc/simpleDocUpload";
/**
* 获取onlyoffice配置
*/
String ONLYOFFICE_FILE_CONFIG_URL = "/onlyoffice/getFileKey";
/**
* 模糊查询所有权限库的doc
*/
String DOC_SEARCH_FUZZY_LIST_URL = "/doc/searchFuzzyDocList";
/**
* DOC统计信息
*/
String DOC_PLATFORM_DOC_INFO_URL = "/doc/getPlatformDocInfoByTenantId";
/**
* 文档分享数据
*/
String DOC_SHARE_DOC_NUM_INFO_URL = "/doc/getShareDocNumInfo";
/**
*咨询窗根据分类查找子级分类和文档
*/
String DOC_AND_CATEGORY_BY_CATEGORYID_URL = "/doc/getDocsAndCategoriesByCategoryId";
/**
* 新增附件文档
*/
String DOC_ADD_ATTACH_URL = "/doc/addAttachDoc";
/**
* 编辑附件文档
*/
String DOC_EDIT_ATTACH_URL = "/doc/editAttachDoc";
/**
* 上传附件
*/
String DOC_UPLOAD_ATTACH_URL = "/doc/uploadAttach";
/**
* 获取文件路径(包含附件)
*/
String DOC_GET_FILE_PATH = "/doc/getFilePath";
/**
* 获取文档路径详情接口
*/
String DOC_CATEGORY_INFO_URL = "/doc/getDocInfoByLibraryId";
String MD_INFO = "/doc/mdInfo";
String EDIT_MD = "/doc/editMD";
String DOC_AUTH="/doc/auth";
/**
* 根据文件分类id集合获取文件id集合
*/
String DOC_GET_ALL_FILE_ID_URL = "/doc/getDocIdListByCategoryIdList";
String Check_MD_Language = "/doc/checkMdLanguage";
/**
* 获取当前租户下所有文档不同的状态的数量
*/
String DOC_GET_SYNC_COUNT = "/doc/getDocSyncStatusCountList";
String PUT_META_DATA = "/doc/putMetaData";
String COUNT_EXIST_DOC = "/doc/countExistDoc";
String DOC_ALL_LIST = "/doc/getDocListByVO";
}
interface KNOWLEDGE {
/**
* 知识库查询接口
*/
String KNOWLEDGE_TREE_URL = "/category/knowledge/tree";
}
interface SEARCH {
/**
* 搜索接口
*/
String MILVUS_SEARCH_URL = "/search";
/**
* 高级搜索
*/
String MILVUS_LLM_SEARCH_URL = "/llmSearch";
/**
* 知识采编搜索
*/
String KNOWLEDGE_COLLECT_SEARCH_URL = "/knowledgeCollectSearch";
/**
* embedding模型更换
*/
String EMBEDDING_CHANGE_URL = "/embeddingModel/change";
/**
* 获取答案来源切片
*/
String GET_ANSWER_SOURCE_URL = "/getAnswerSource";
/**
* 片段搜索
*/
String PARA_SEARCH_URL = "/searchParaByDocIds";
String CONTENT_SEARCH_URL = "/searchContentByDocIds";
}
interface KNOWLEDGECOLLECT {
/**
* 知识采编同步文档
*/
String KNOWLEDGE_COLLECT_SYNC_DOC_URL = "/knowledgeCollect/syncDoc";
/**
* 知识采编删除文档向量
*/
String KNOWLEDGE_COLLECT_DELETE_DOC_VECTOR_URL = "/knowledgeCollect/deleteDocVector";
/**
* 删除问题向量
*/
String KNOWLEDGE_COLLECT_DELETE_DOC_QUESTION_URL = "/knowledgeCollect/deleteDocVector";
/**
* 同步文档
*/
String SYNC_GENERATE_QUESTION_URL = "/knowledgeCollect/syncGenerateQuestions";
}
interface RELDOCVEC {
/**
* 查询切片向量列表
*/
String FIND_REL_DOC_VEC_LIST_URL = "/relDocVec/findByIds";
}
interface SYNC {
/**
* 查询切片向量列表
*/
String SYNC_FAQ_URL = "/faq/syncQa";
/**
* 删除知识点向量
*/
String DELETE_QA_VEC_URL = "/faq/deleteQaVec";
}
interface ES {
String QUERY = "/es/api/search";
String PURE_QUERY = "/es/api/search/pureEs";
String RELOAD = "/es/api/reload";
}
interface TAG {
String ADD = "/tag/add";
String EDIT = "/tag/edit";
String DELETE = "/tag/delete";
String LIST = "/tag/list";
String DETAIL = "/tag/detail";
String DATA_LIST = "/tag/dataList";
}
}
......@@ -3,4 +3,6 @@ package com.cmeeting.constant;
public class RecordTemplateConstant {
public static final String TEMPLATE_TYPE_SYSTEM = "system";
public static final String TEMPLATE_TYPE_CUSTOM = "custom";
public static final String REL_TYPE_DEPT = "1";
public static final String REL_TYPE_USER = "2";
}
......@@ -4,6 +4,8 @@ import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.cmeeting.ad.entity.RobotSecurityUser;
import com.cmeeting.ad.util.SecurityUtil;
import com.cmeeting.email.EmailSender;
import com.cmeeting.mapper.primary.MeetingRecordTemplateMapper;
import com.cmeeting.mapper.primary.UserIdMapper;
......@@ -25,6 +27,7 @@ import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ClassPathResource;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
......@@ -58,6 +61,10 @@ public class MeetingInfoController {
private MeetingRecordTemplateMapper meetingRecordTemplateMapper;
@Resource
private UserIdMapper userIdMapper;
@Value(value = "${permission.applicationId}")
private String permissionApplicationId;
@Value(value = "${userAdmin.file-download-path}")
private String fileDownloadPath;
@PostMapping("/updateRecordXml")
public R updateRecordXml(@RequestBody MeetingInfoVO vo) {
......@@ -84,6 +91,9 @@ public class MeetingInfoController {
@PostMapping("/detail")
public R detail(@RequestBody MeetingInfoVO vo) {
RobotSecurityUser user = SecurityUtil.getUser();
vo.setUserId(user.getId());
vo.setApplicationId(permissionApplicationId);
MeetingInfo meetingInfo = meetingInfoService.getById(vo.getId());
BeanUtils.copyProperties(meetingInfo,vo);
String recordXml = vo.getRecordXml();
......@@ -107,7 +117,7 @@ public class MeetingInfoController {
}
try {
if(StringUtils.isNotEmpty(recordContent)){
vo.setRecordContent(minioUtils.getFileText(recordContent));
vo.setRecordContent(minioUtils.getFileText(recordContent.replaceAll(fileDownloadPath,"")));
}
} catch (Exception e) {
e.printStackTrace();
......
......@@ -30,9 +30,14 @@ public class RecordTemplateController {
@PostMapping("/create")
public R create(@RequestBody MeetingRecordTemplate recordTemplate) {
RobotSecurityUser user = SecurityUtil.getUser();
recordTemplate.setCreateTime(LocalDateTime.now());
LocalDateTime now = LocalDateTime.now();
recordTemplate.setCreateTime(now);
recordTemplate.setUpdateTime(now);
recordTemplate.setIsDel(Boolean.FALSE);
recordTemplate.setCreateUser(user.getId());
recordTemplate.setUpdateUser(user.getId());
recordTemplate.setCreateUserName(user.getNickName());
recordTemplate.setUpdateUserName(user.getNickName());
boolean save = recordTemplateService.save(recordTemplate);
return R.ok(save);
}
......@@ -42,6 +47,7 @@ public class RecordTemplateController {
RobotSecurityUser user = SecurityUtil.getUser();
recordTemplate.setUpdateTime(LocalDateTime.now());
recordTemplate.setUpdateUser(user.getId());
recordTemplate.setUpdateUserName(user.getNickName());
boolean save = recordTemplateService.updateById(recordTemplate);
return R.ok(save);
}
......@@ -68,6 +74,17 @@ public class RecordTemplateController {
}
/**
* 用户下拉选择的模板列表(权限内)
* @param vo
* @return
*/
@PostMapping("/selectList")
public R selectList(@RequestBody RecordTemplateVO vo) {
List<MeetingRecordTemplate> records = recordTemplateService.getSelectList(vo);
return R.ok(records);
}
/**
* 普通用户纪要模板,查出有授权的系统模板和个人创建的自定义模板
* @param vo
* @return
......
package com.cmeeting.dto;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.Data;
import java.util.Date;
import java.util.List;
/**
* @author 吕轶伟
* @date 2024/6/26 下午4:17
*/
@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
public class DocResultDto {
/**
* 分类id
*/
private String categoryId;
/**
* 分类路径
*/
private String docPath;
/**
* 文档名称
*/
private String docName;
/**
* 文档标题
*/
private String docTitle;
/**
* 文档类型(0:word, 1: excel, 2: ppt, 3: pdf, 4: txt, 5: 用户自建文档)
*/
private String docType;
/**
* 文档内容(针对text文档)
*/
private String docContent;
/**
* 预览地址
*/
private String previewPath;
/**
* 文档状态(0: 启用, 1: 停用)
*/
private String docStatus;
private String size;
/**
* 同步状态(0: 上传成功, 1: 上传失败, 2: 同步中, 3: 处理中, 4: 同步成功, 5: 同步失败, 6: 用户取消同步)
*/
private String syncStatus;
/**
* 知识库id
*/
private String libraryId;
private boolean checked;
private boolean isSys;
private List<TagTypeResultDto> tagTypeList;
/**
* 主键ID
*/
private String id;
/**
* 0-正常,1-删除
*/
private boolean isDel;
/**
* 用户创建人
*/
private String createUser;
/**
* 更新者
*/
private String updateUser;
/**
* 修改时间
*/
private Date updateTime;
/**
* 创建时间
*/
private Date createTime;
/**
* 租户id
*/
private String tenantId;
private String parentId;
private String libraryName;
private String categoryName;
private List<RelAttachFileDto> relAttachFiles;
private RelAttachFileDto sourceFile;
private String pdfPath;
private String xlfFilePath;
private String authorId;
private String author;
}
\ No newline at end of file
package com.cmeeting.dto;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 文档附件信息表(RelAttachFile)实体类
*
* @author makejava
* @since 2024-07-16 19:05:34
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class RelAttachFileDto {
/**
* id
*/
private String id;
/**
* 文档id
*/
private String docId;
/**
* 附件名称
*/
private String name;
/**
* 附件地址
*/
private String filePath;
/**
* 文件大小
*/
private String size;
}
package com.cmeeting.dto;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
/**
* @author 吕轶伟
* @date 2024/6/26 下午4:17
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class TagTypeResultDto {
private String id;
/**
* 标签类型值
*/
private String tagTypeValue;
/**
* 标签颜色
*/
private String tagColor;
private List<Tag> tagList;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Tag{
/**
* 标签值
*/
private String tagValue;
/**
* 标签类型id
*/
private String tagTypeId;
/**
* 标签id
*/
private String id;
}
private String tenantId;
}
......@@ -48,6 +48,12 @@ public class EmailSender {
private String SENDER;
@Value("${email.sender-pwd}")
private String EMAIL_PWD;
@Value("${email.push-switch}")
private Boolean pushSwitch;
@Value("${email.environment}")
private String environment;
@Value("${email.test-receiver}")
private String testReceiver;
private String CLIENT_ID = "c06fe7cf-2a89-4099-9805-ce03031938f8";
private String CLIENT_SECRET = "wsu8Q~GxYxPLf2akioQZDRG8NR1EzCAHIAQRVc6u";
......@@ -177,12 +183,13 @@ public class EmailSender {
// 创建会话
log.info("sender->{},email_pwd->{}",SENDER, EMAIL_PWD);
if(!pushSwitch){
log.info("【邮箱推送】:应用未开启邮件推送功能");
}
AtomicInteger retryCount = new AtomicInteger(0);
boolean isSent = false;
String toEmail = emailPushBuilder.getToEmail();
// String toEmail = "duanxincheng@chatbot.cn";
String toEmail = "test".equals(environment) ? testReceiver : emailPushBuilder.getToEmail();
String subject = emailPushBuilder.getSubject();
String meetingId = emailPushBuilder.getMeetingId();
String subMeetingId = emailPushBuilder.getSubMeetingId();
......@@ -191,7 +198,7 @@ public class EmailSender {
String toUser = emailPushBuilder.getToUser();
if(StringUtils.isEmpty(toEmail)){
log.error("收件邮箱为空,推送失败");
processLogService.log(meetingId,null,"收件邮箱为空,推送失败");
processLogService.log(meetingId,null,"收件邮箱为空,推送失败。environment->"+environment+",testReceiver->"+testReceiver+",realEmail->"+emailPushBuilder.getToEmail());
return false;
}
log.info("准备开始邮件推送...");
......
package com.cmeeting.exception;
import com.cmeeting.util.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
/**
* @Classname BExceptionHandler
* @Description 自定义异常处理
* @Author robot
* @Date 2019-03-29 13:23
* @Version 1.0
*/
@Slf4j
@RestControllerAdvice
public class BExceptionHandler {
/**
* 处理自定义异常
*/
@ExceptionHandler(RobotBaseException.class)
public R handlerException(RobotBaseException e) {
return R.error(e.getCode(), e.getMessage());
}
/**
* @Description 请求参数值异常
* @param e
* @return
*/
@ExceptionHandler(MethodArgumentNotValidException.class)
public R handlerException(MethodArgumentNotValidException e) {
return R.error(-1, e.getMessage());
}
}
package com.cmeeting.exception;
import cn.hutool.core.collection.CollectionUtil;
import com.cmeeting.util.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.authentication.AccountExpiredException;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.NoHandlerFoundException;
import java.sql.SQLException;
/**
* 自定义异常处理
*
* @author 王长伟
*/
@Slf4j
@RestControllerAdvice
public class BizExceptionHandler {
/**
* 处理自定义异常
*/
@ExceptionHandler(RobotBaseException.class)
public R handlerException(RobotBaseException e) {
return R.error(e.getMsg());
}
/**
* 请求参数值异常(超过长度,或者类型不对等)
* @param e
* @return
*/
@ExceptionHandler(MethodArgumentNotValidException.class)
public R handlerMethodArgumentNotValidException(MethodArgumentNotValidException e) {
log.error(e.getMessage(), e);
if (CollectionUtil.isNotEmpty(e.getBindingResult().getFieldErrors())) {
String validateMessage = e.getBindingResult().getFieldErrors().get(0).getDefaultMessage();
return R.error(validateMessage);
}
return R.error("参数错误");
}
/**
* 请求参数key不对
* @param e
* @return
*/
@ExceptionHandler(MissingServletRequestParameterException.class)
public R handlerMissingServletRequestParameterException(Exception e) {
log.error(e.getMessage(), e);
return R.error(1001, "参数错误");
}
@ExceptionHandler(NoHandlerFoundException.class)
public R handlerNoFoundException(Exception e) {
log.error(e.getMessage(), e);
return R.error(404, "路径不存在,请检查路径是否正确");
}
/**
* 数据库中已存在该记录
* @param e
* @return
*/
@ExceptionHandler(DuplicateKeyException.class)
public R handleDuplicateKeyException(DuplicateKeyException e) {
log.error(e.getMessage(), e);
return R.error(300, "数据库中已存在该记录");
}
@ExceptionHandler(AccessDeniedException.class)
public R handleAuthorizationException(AccessDeniedException e) {
log.error(e.getMessage());
return R.error(403, "没有权限,请联系管理员授权");
}
@ExceptionHandler(AccountExpiredException.class)
public R handleAccountExpiredException(AccountExpiredException e) {
log.error(e.getMessage(), e);
return R.error(e.getMessage());
}
@ExceptionHandler(UsernameNotFoundException.class)
public R handleUsernameNotFoundException(UsernameNotFoundException e) {
log.error(e.getMessage(), e);
return R.error(e.getMessage());
}
@ExceptionHandler(Exception.class)
public R handleException(Exception e) {
log.error(e.getMessage(), e);
return R.error(e.getMessage());
}
@ExceptionHandler(SQLException.class)
public R handlerSqlException(SQLException e) {
log.error(e.getMessage(), e);
return R.error(e.getMessage());
}
@ExceptionHandler(ValidateCodeException.class)
public R handleValidateCodeException(ValidateCodeException e) {
log.error(e.getMessage(), e);
return R.error(e.getMessage());
}
}
......@@ -18,33 +18,33 @@ public class RobotBaseException extends RuntimeException implements Serializable
@Setter
@Getter
private String message;
private String msg;
@Setter
@Getter
private int code = 200;
private int code;
public RobotBaseException(String msg) {
super(msg);
this.message = msg;
}
public RobotBaseException(String msg, Throwable e) {
super(msg, e);
this.message = msg;
this.msg = msg;
}
public RobotBaseException(String msg, int code) {
super(msg);
this.message = msg;
this.msg = msg;
this.code = code;
}
public RobotBaseException(String msg, int code, Throwable e) {
public RobotBaseException(String msg, Throwable e) {
super(msg, e);
this.message = msg;
this.msg = msg;
}
public RobotBaseException(String msg, Throwable e, int code) {
super(msg, e);
this.msg = msg;
this.code = code;
}
}
package com.cmeeting.exception;
import org.springframework.security.core.AuthenticationException;
/**
* @Classname ValidateCodeException
* @Author Created by robot
* @Date 2019-07-07 23:06
* @Version 1.0
*/
public class ValidateCodeException extends AuthenticationException {
private static final long serialVersionUID = 5022575393500654459L;
public ValidateCodeException(String message) {
super(message);
}
}
package com.cmeeting.job;
import cn.chatbot.meeting.DebugOutputTool;
import cn.chatbot.meeting.LLMConfig;
import cn.chatbot.meeting.LLMResult;
import cn.chatbot.meeting.MeetingProcess;
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.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.cmeeting.ad.util.SecurityUtil;
import com.cmeeting.constant.KnowledgePlatformRouteConstant;
import com.cmeeting.constant.RecordTemplateConstant;
import com.cmeeting.constant.UserAdminRouteConstant;
import com.cmeeting.dto.DocResultDto;
import com.cmeeting.dto.UserDTO;
import com.cmeeting.email.EmailSender;
import com.cmeeting.log.service.ProcessLogService;
......@@ -17,7 +29,7 @@ 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.cmeeting.util.*;
import com.cmeeting.vo.EmailPush;
import com.deepoove.poi.XWPFTemplate;
import com.fasterxml.jackson.databind.JsonNode;
......@@ -44,6 +56,7 @@ import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;
import java.io.*;
import java.math.BigInteger;
......@@ -90,6 +103,12 @@ public class FileProcessTask {
private List<UserDTO.TemplateAuthorizedUserDTO> authorizedUsers;
//腾会id企微id对应关系
private Map<String,String> tidWidRelations;
private UserAdminConfig userAdminConfig;
//获取到的token
private String adminToken;
private String applicationId;
private String fileDownloadPath;
private String permTenantId;
// 实际处理逻辑
public void process() {
......@@ -249,10 +268,11 @@ public class FileProcessTask {
//获取系统模板
List<MeetingRecordTemplate> recordTemplateList = meetingRecordTemplateMapper.selectList(
new LambdaQueryWrapper<MeetingRecordTemplate>().eq(MeetingRecordTemplate::getType, RecordTemplateConstant.TEMPLATE_TYPE_SYSTEM)
.eq(MeetingRecordTemplate::getIsDel,Boolean.FALSE));
.eq(MeetingRecordTemplate::getIsDel,Boolean.FALSE).isNotNull(MeetingRecordTemplate::getTemplate));
Map<Integer, List<String>> authorizedUserMap = authorizedUsers.stream().collect(Collectors.toMap(item -> item.getRecordTemplateId(), item -> item.getUserIdList()));
List<EmailPush.Attachment> attachments = new ArrayList<>();
String hostUid = meetingInfo.getHostUid();
String toUserCode = tidWidRelations.get(meetingInfo.getHostUid());
if(!tidWidRelations.containsKey(hostUid)){
log.info("用户{}暂未关联企微信息,无法生成纪要文件",hostUid);
processLogService.log(meetingId,subMeetingId,"用户"+hostUid+"暂未关联企微信息,无法生成纪要文件");
......@@ -274,8 +294,8 @@ public class FileProcessTask {
log.info("用户{}允许应用模板{}",hostUid,template.getName());
processLogService.log(meetingId,subMeetingId,"用户"+hostUid+"允许应用模板"+template.getName());
}
String processedResult = processWithClaude(recordTextBuffer.toString(),meetingDate,template.getPrompt());
String minutesPath = saveResult(processedResult, recordTextBuffer.toString().getBytes(StandardCharsets.UTF_8), meetingInfo, template);
String processedResult = processWithClaude(recordTextBuffer.toString(),meetingDate,participantNames,template.getPrompt());
String minutesPath = saveResult(processedResult, recordTextBuffer.toString().getBytes(StandardCharsets.UTF_8), meetingInfo,toUserCode, template);
try(InputStream is = new FileInputStream(minutesPath)){
byte[] meetingMinutesBytes = IOUtils.toByteArray(is);
EmailPush.Attachment attachment = EmailPush.Attachment.builder().name(meetingInfo.getSubject()+"会议纪要_"+template.getName()).bytes(meetingMinutesBytes).build();
......@@ -303,7 +323,7 @@ public class FileProcessTask {
.subject(meetingInfo.getSubject())
.meetingInstanceId(meetingInfo.getId())
.subMeetingId(meetingInfo.getSubMeetingId())
.toUserCode(tidWidRelations.get(meetingInfo.getHostUid()))
.toUserCode(toUserCode)
.toUser(meetingInfo.getHost())
.build();
emailPush(emailPushBuilder);
......@@ -405,28 +425,39 @@ public class FileProcessTask {
/**
* 大模型生成纪要xml
* @param textContent 转录文件
* @param meetingDate 会议日期
* @param participantNames 参会人员
* @param prompt 提示词
* @return
*/
private String processWithClaude(String textContent, String meetingDate, String prompt) {
//将文件传送给大模型处理
String token = "AKIAXFAXF62IWJXGLVEE.LnKInaahcMZG9zLsGMH3nTLOw3S3lK5Vcu0+ifnO";
String apiAddr = llmApiAddr + "/llm/sse-invoke";
String model = "anthropic.claude-3-5-sonnet-20240620-v1:0";
int maxTokens = 5000;
List<Message> messages = new ArrayList<>();
ChatMessage chatMessage = new ChatMessage(ChatMessageRole.USER.value(), prompt.replaceAll("\\{transcript\\}",textContent).replaceAll("\\{meetingDate\\}",meetingDate));
messages.add(chatMessage);
// chatMessage = new ChatMessage(ChatMessageRole.ASSISTANT.value(), "好的请提供会议记录");
private String processWithClaude(String textContent, String meetingDate,String participantNames, String prompt) {
// //将文件传送给大模型处理
// String token = "AKIAXFAXF62IWJXGLVEE.LnKInaahcMZG9zLsGMH3nTLOw3S3lK5Vcu0+ifnO";
// String apiAddr = llmApiAddr + "/llm/sse-invoke";
// String model = "anthropic.claude-3-5-sonnet-20240620-v1:0";
// int maxTokens = 5000;
// List<Message> messages = new ArrayList<>();
//
// ChatMessage chatMessage = new ChatMessage(ChatMessageRole.USER.value(), prompt.replaceAll("\\{transcript\\}",textContent).replaceAll("\\{meetingDate\\}",meetingDate));
// messages.add(chatMessage);
// chatMessage = new ChatMessage(ChatMessageRole.USER.value(), textContent);
messages.add(chatMessage);
//// chatMessage = new ChatMessage(ChatMessageRole.ASSISTANT.value(), "好的请提供会议记录");
//// messages.add(chatMessage);
//// chatMessage = new ChatMessage(ChatMessageRole.USER.value(), textContent);
//
// messages.add(chatMessage);
//
// // 调用Claude API处理文件
// String ret = call_llm(apiAddr, model, token, messages, maxTokens);
// 调用Claude API处理文件
String ret = call_llm(apiAddr, model, token, messages, maxTokens);
return ret;
// String model = "arn:aws:bedrock:us-east-1:491822380689:inference-profile/us.anthropic.claude-3-7-sonnet-20250219-v1:0";
String model = "anthropic.claude-3-5-sonnet-20240620-v1:0";
LLMConfig baseLLM = new LLMConfig(model,
"https://bedrock.chatbot.cn/llm/sse-invoke",
"Bearer AKIAXFAXF62IWJXGLVEE.LnKInaahcMZG9zLsGMH3nTLOw3S3lK5Vcu0+ifnO",
20000);
LLMResult llmResult = MeetingProcess.processMeeting(prompt, textContent,meetingDate,participantNames, baseLLM, new ArrayList<>());
DebugOutputTool.println(llmResult.respond);
return llmResult.respond;
}
/**
......@@ -434,12 +465,14 @@ public class FileProcessTask {
* @param content 大模型返回的不规则xml
* @param recordData 转录文本
* @param meetingInfo 会议对象
* @param toUserCode 人员工号
* @param meetingRecordTemplate 模板信息
*/
private String saveResult(String content, byte[] recordData, MeetingInfo meetingInfo,MeetingRecordTemplate meetingRecordTemplate) {
private String saveResult(String content, byte[] recordData, MeetingInfo meetingInfo,String toUserCode,MeetingRecordTemplate meetingRecordTemplate) {
String meetingName;
//转录文件临时存储路径
String recordContentPath = meetingId + "-recordContent-" + IdUtil.fastSimpleUUID() + ".txt";
// String recordContentPath = meetingId + "-recordContent-" + IdUtil.fastSimpleUUID() + ".txt";
String recordContentPath;
//生成的xml临时存储路径
String recordXmlPath = meetingId + "-recordXmlPath-" + IdUtil.fastSimpleUUID() + ".xml";
//填充后的会议纪要名称
......@@ -447,9 +480,37 @@ public class FileProcessTask {
//填充后的会议纪要word文件临时路径
String meetingMinutesPath;
try {
String fileName = String.format(meetingInfo.getSubject() + "_转写原文_%s.txt", DateUtil.today());
MultipartFile multipartFile = new CustomMultipartFile(
"file", // 表单中的字段名
fileName, // 原始文件名
"text/plain; charset=utf-8", // MIME类型
recordData // 字节内容
);
//将转录文件存到知识向量库
String url = userAdminConfig.getUserAdminDomain() + "/robotcustom/upload";
Map<String, String> otherParams = new HashMap<>();
otherParams.put("userId", toUserCode);
otherParams.put("tenantId", permTenantId);
otherParams.put("layout", "V1");
String responseData = HttpClientKnowledgePlatformUtil.sendPostByFormDataFiles(userAdminConfig.getDocDomain() + KnowledgePlatformRouteConstant.DOC.SIMPLE_DOC_UPLOAD_URL, Arrays.asList(multipartFile), otherParams, null);
if (StringUtils.isNotBlank(responseData)) {
R result = JSON.parseObject(responseData, R.class);
List<DocResultDto> docResultDtoList = JSON.parseObject(JSONObject.toJSONString(result.getData()), new TypeReference<List<DocResultDto>>() {
});
DocResultDto docResultDto = docResultDtoList.get(0);
String previewPath = docResultDto.getPreviewPath();
recordContentPath = previewPath.replaceAll(fileDownloadPath,"");
meetingInfo.setTransDocId(docResultDto.getId());
}else{
processLogService.log(meetingId,subMeetingId,"填充会议纪要失败,上传转录文件到向量知识库失败");
throw new RuntimeException("填充会议纪要失败");
}
//去除内容中除了xml内容以外其他的信息,格式化xml
String xml = extractXmlFromMarkdown(content);
minioUtils.upload(recordContentPath,recordData);
// minioUtils.upload(recordContentPath,recordData);
minioUtils.upload(recordXmlPath,xml.getBytes(StandardCharsets.UTF_8));
//将xml格式的内容转换为map,用于填充模板
Map<String, Object> dataModel = convertXmlToMap(xml);
......@@ -492,6 +553,7 @@ public class FileProcessTask {
.set(MeetingInfo::getParticipantUsers,meetingInfo.getParticipantUsers())
.set(MeetingInfo::getIsGenerated,Boolean.TRUE)
.set(MeetingInfo::getTemplateId,meetingRecordTemplate.getId())
.set(MeetingInfo::getTransDocId,meetingInfo.getTransDocId())
);
meetingInfo.setRecordContent(recordContentPath);
meetingInfo.setRecordXml(recordXmlPath);
......@@ -642,7 +704,8 @@ 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, ProcessLogService processLogService,List<UserDTO.TemplateAuthorizedUserDTO> authorizedUsers,Map<String,String> tidWidRelations) {
String llmApiAddr, Boolean finalRetry, ProcessLogService processLogService,List<UserDTO.TemplateAuthorizedUserDTO> authorizedUsers,Map<String,String> tidWidRelations,
UserAdminConfig userAdminConfig, String adminToken, String applicationId,String fileDownloadPath, String permTenantId) {
this.recordFileIdList = recordFileIdList;
this.savePath = savePath;
this.metadata = metadata;
......@@ -662,5 +725,10 @@ public class FileProcessTask {
this.processLogService = processLogService;
this.authorizedUsers = authorizedUsers;
this.tidWidRelations = tidWidRelations;
this.userAdminConfig = userAdminConfig;
this.adminToken = adminToken;
this.applicationId = applicationId;
this.fileDownloadPath = fileDownloadPath;
this.permTenantId = permTenantId;
}
}
\ No newline at end of file
......@@ -2,6 +2,7 @@ package com.cmeeting.mapper.primary;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.cmeeting.pojo.MeetingInfo;
import com.cmeeting.vo.MeetingInfoVO;
import com.cmeeting.vo.TencentMeetingVO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
......@@ -15,4 +16,6 @@ public interface MeetingInfoMapper extends BaseMapper<MeetingInfo> {
List<TencentMeetingVO.SimpleMeetingInfo> getAllMeetingIds();
// List<MeetingInfo> selectList(MeetingInfoVO vo);
}
\ No newline at end of file
......@@ -13,7 +13,7 @@ import java.util.List;
public interface SysUserSysMapper extends BaseMapper<SysUserSync> {
String getCompanyEmail(String wid, String tenantId);
String getParentDeptId(String deptId, String tenantId);
String getParentDeptId(@Param(value = "deptId")String deptId,@Param(value = "tenantId") String tenantId);
List<UserDTO> getUserEmail(@Param(value = "tenantId")String tenantId);
......@@ -21,7 +21,7 @@ public interface SysUserSysMapper extends BaseMapper<SysUserSync> {
List<SysDept> getSimpleDeptList(@Param(value = "tenantId")String tenantId);
List<String> getSubDeptId(@Param(value = "deptId")String deptId);
List<String> getSubDeptId(@Param(value = "deptId")String deptId,@Param(value = "tenantId")String tenantId);
List<String> getUsersByDept(@Param(value = "deptIds") List<String> deptIds);
List<String> getUsersByDept(@Param(value = "deptIds") List<String> deptIds,@Param(value = "tenantId")String tenantId);
}
......@@ -133,4 +133,9 @@ public class MeetingInfo implements Serializable {
* 模板ID
*/
private Integer templateId;
/**
* 转录文件知识库id
*/
private String transDocId;
}
\ No newline at end of file
......@@ -72,11 +72,19 @@ public class MeetingRecordTemplate implements Serializable {
* 创建人
*/
private String createUser;
/**
* 创建人名称
*/
private String createUserName;
/**
* 更新人
*/
private String updateUser;
/**
* 更新人名称
*/
private String updateUserName;
/**
* 删除标识
......@@ -87,4 +95,12 @@ public class MeetingRecordTemplate implements Serializable {
* 模板文件
*/
private String template;
/**
* 引用的纪要模板id
*/
private Integer referTemplateId;
/**
* 引用的纪要模板名称
*/
private String referTemplateName;
}
\ No newline at end of file
......@@ -9,6 +9,8 @@ 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.UserAdminConfig;
import com.cmeeting.util.UserAdminTokenUtil;
import com.cmeeting.vo.TencentMeetingVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
......@@ -47,6 +49,10 @@ public class FileProcessProducer {
private String llmApiAddr;
@Value(value = "${tencent.base-save-path}")
private String baseSavePath;
@Value("${permission.applicationId}")
public String applicationId;
@Value("${permission.tenantId}")
public String permTenantId;
@Resource
private MeetingInfoMapper meetingInfoMapper;
@Resource
......@@ -57,6 +63,11 @@ public class FileProcessProducer {
private EmailSender emailSender;
@Resource
private ProcessLogService processLogService;
@Resource
private UserAdminConfig userAdminConfig;
//中集知识库文件的预览访问路径前缀
@Value("${userAdmin.file-download-path}")
private String fileDownloadPath;
/**
* 批量提交生成纪要任务
......@@ -68,7 +79,7 @@ public class FileProcessProducer {
*/
public void submitBatchTasks(List<TencentMeetingVO.RecordFile> recordFiles, List<UserDTO.TemplateAuthorizedUserDTO> authorizedUsers, Map<String,String> tidWidRelations, Boolean finalRetry) {
List<Future<?>> futures = new ArrayList<>();
String adminToken = UserAdminTokenUtil.getUserAdminToken();
for (TencentMeetingVO.RecordFile recordFile : recordFiles) {
// 为每个URL创建任务
FileProcessTask task = new FileProcessTask(
......@@ -90,7 +101,12 @@ public class FileProcessProducer {
finalRetry,
processLogService,
authorizedUsers,
tidWidRelations
tidWidRelations,
userAdminConfig,
adminToken,
applicationId,
fileDownloadPath,
permTenantId
);
// 提交任务到线程池
......
......@@ -37,4 +37,11 @@ public interface MeetingRecordTemplateService extends IService<MeetingRecordTemp
* @return
*/
List<UserDTO.TemplateAuthorizedUserDTO> selectAuthorizedUsers();
/**
* 用户下拉选择的模板列表(权限内)
* @param vo
* @return
*/
List<MeetingRecordTemplate> getSelectList(RecordTemplateVO vo);
}
package com.cmeeting.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.cmeeting.ad.entity.SysUserSync;
public interface SysUserSyncService extends IService<SysUserSync> {
String getDeptPathByUserId(String userId);
}
......@@ -15,6 +15,8 @@ import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cmeeting.ad.entity.RobotSecurityUser;
import com.cmeeting.ad.util.SecurityUtil;
import com.cmeeting.log.service.ProcessLogService;
import com.cmeeting.mapper.primary.MeetingInfoMapper;
import com.cmeeting.mapper.primary.MeetingRecordTemplateMapper;
......@@ -88,6 +90,8 @@ public class MeetingInfoServiceImpl extends ServiceImpl<MeetingInfoMapper, Meeti
@Override
public IPage<MeetingInfo> getPage(MeetingInfoVO vo) {
RobotSecurityUser user = SecurityUtil.getUser();
vo.setUserId(user.getId());
LambdaQueryWrapper<MeetingInfo> queryWrapper = new LambdaQueryWrapper<>();
IPage<MeetingInfo> resultPage = mapper.selectPage(new Page<>(vo.getCurrent(), vo.getSize()), queryWrapper);
return resultPage;
......
......@@ -19,9 +19,12 @@ import com.cmeeting.mapper.secondary.SysUserSysMapper;
import com.cmeeting.pojo.MeetingRecordTemplate;
import com.cmeeting.pojo.RecordTemplatePermission;
import com.cmeeting.service.MeetingRecordTemplateService;
import com.cmeeting.service.SysUserSyncService;
import com.cmeeting.util.MinioUtils;
import com.cmeeting.vo.RecordTemplateVO;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;
......@@ -41,15 +44,22 @@ public class MeetingRecordTemplateServiceImpl extends ServiceImpl<MeetingRecordT
private RecordTemplatePermissionMapper permissionMapper;
@Resource
private SysUserSysMapper sysUserSysMapper;
@Resource
private SysUserSyncService sysUserSyncService;
@Value(value = "${permission.tenantId}")
private String permissionTenantId;
@Override
public IPage<MeetingRecordTemplate> getPage(RecordTemplateVO vo) {
RobotSecurityUser user = SecurityUtil.getUser();
LambdaQueryWrapper<MeetingRecordTemplate> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(MeetingRecordTemplate::getIsDel,Boolean.FALSE);
queryWrapper.eq(vo.getType() != null,MeetingRecordTemplate::getType,vo.getType());
queryWrapper.like(vo.getName() != null,MeetingRecordTemplate::getName,vo.getName());
queryWrapper.like(vo.getMeetingType() != null,MeetingRecordTemplate::getMeetingType,vo.getMeetingType());
queryWrapper.eq(StringUtils.isNotEmpty(vo.getType()),MeetingRecordTemplate::getType,vo.getType());
queryWrapper.like(StringUtils.isNotEmpty(vo.getName()),MeetingRecordTemplate::getName,vo.getName());
queryWrapper.like(StringUtils.isNotEmpty(vo.getMeetingType()),MeetingRecordTemplate::getMeetingType,vo.getMeetingType());
queryWrapper.like(StringUtils.isNotEmpty(vo.getCreateUser()),MeetingRecordTemplate::getCreateUserName,vo.getCreateUser());
queryWrapper.between(vo.getStartTime() != null && vo.getEndTime() != null,MeetingRecordTemplate::getUpdateTime,vo.getStartTime(),vo.getEndTime());
queryWrapper.orderByDesc(MeetingRecordTemplate::getId);
IPage<MeetingRecordTemplate> resultPage = baseMapper.selectPage(new Page<>(vo.getCurrent(), vo.getSize()), queryWrapper);
List<MeetingRecordTemplate> records = resultPage.getRecords();
if(!CollectionUtils.isEmpty(records)){
......@@ -77,6 +87,9 @@ public class MeetingRecordTemplateServiceImpl extends ServiceImpl<MeetingRecordT
systemQueryWrapper.eq(MeetingRecordTemplate::getType,RecordTemplateConstant.TEMPLATE_TYPE_SYSTEM);
systemQueryWrapper.like(vo.getName() != null,MeetingRecordTemplate::getName,vo.getName());
systemQueryWrapper.like(vo.getMeetingType() != null,MeetingRecordTemplate::getMeetingType,vo.getMeetingType());
systemQueryWrapper.like(StringUtils.isNotEmpty(vo.getCreateUser()),MeetingRecordTemplate::getCreateUserName,vo.getCreateUser());
systemQueryWrapper.between(vo.getStartTime() != null && vo.getEndTime() != null,MeetingRecordTemplate::getUpdateTime,vo.getStartTime(),vo.getEndTime());
systemQueryWrapper.orderByDesc(MeetingRecordTemplate::getId);
List<MeetingRecordTemplate> systemTemplateList = baseMapper.selectList(systemQueryWrapper);
//用户可见的系统模板权限
List<MeetingRecordTemplate> authorizedSystemTemplateList = new ArrayList<>();
......@@ -96,6 +109,9 @@ public class MeetingRecordTemplateServiceImpl extends ServiceImpl<MeetingRecordT
customQueryWrapper.eq(MeetingRecordTemplate::getCreateUser, user.getId());
customQueryWrapper.like(vo.getName() != null,MeetingRecordTemplate::getName,vo.getName());
customQueryWrapper.like(vo.getMeetingType() != null,MeetingRecordTemplate::getMeetingType,vo.getMeetingType());
customQueryWrapper.like(StringUtils.isNotEmpty(vo.getCreateUser()),MeetingRecordTemplate::getCreateUserName,vo.getCreateUser());
customQueryWrapper.between(vo.getStartTime() != null && vo.getEndTime() != null,MeetingRecordTemplate::getUpdateTime,vo.getStartTime(),vo.getEndTime());
customQueryWrapper.orderByDesc(MeetingRecordTemplate::getId);
List<MeetingRecordTemplate> customTemplateList = baseMapper.selectList(customQueryWrapper);
List<MeetingRecordTemplate> resultList = new ArrayList<>();
......@@ -180,9 +196,9 @@ public class MeetingRecordTemplateServiceImpl extends ServiceImpl<MeetingRecordT
List<String> deptPath = new ArrayList<>();
for (RecordTemplatePermission deptPermission : deptPermissions) {
String deptId = deptPermission.getRelId();
getDeptPath(deptPath,deptId);
getDeptPath(deptPath,deptId,permissionTenantId);
}
List<String> usersByDept = sysUserSysMapper.getUsersByDept(deptPath);
List<String> usersByDept = sysUserSysMapper.getUsersByDept(deptPath,permissionTenantId);
if(!CollectionUtils.isEmpty(usersByDept))
authorizedUsers.addAll(usersByDept);
}
......@@ -192,21 +208,66 @@ public class MeetingRecordTemplateServiceImpl extends ServiceImpl<MeetingRecordT
return result;
}
@Override
public List<MeetingRecordTemplate> getSelectList(RecordTemplateVO vo) {
RobotSecurityUser user = SecurityUtil.getUser();
//查出所有系统模板
LambdaQueryWrapper<MeetingRecordTemplate> systemQueryWrapper = new LambdaQueryWrapper<>();
systemQueryWrapper.eq(MeetingRecordTemplate::getIsDel,Boolean.FALSE);
systemQueryWrapper.eq(MeetingRecordTemplate::getType,RecordTemplateConstant.TEMPLATE_TYPE_SYSTEM);
systemQueryWrapper.like(vo.getName() != null,MeetingRecordTemplate::getName,vo.getName());
systemQueryWrapper.like(vo.getMeetingType() != null,MeetingRecordTemplate::getMeetingType,vo.getMeetingType());
systemQueryWrapper.orderByDesc(MeetingRecordTemplate::getId);
List<MeetingRecordTemplate> systemTemplateList = baseMapper.selectList(systemQueryWrapper);
if(CollectionUtils.isEmpty(systemTemplateList)) return new ArrayList<>();
//用户可见的系统模板权限
List<MeetingRecordTemplate> records = new ArrayList<>();
//查出所有系统模板授权人员信息
List<RecordTemplatePermission> userPermissions = permissionMapper.selectList(new LambdaQueryWrapper<RecordTemplatePermission>()
.eq(RecordTemplatePermission::getTemplateType, RecordTemplateConstant.TEMPLATE_TYPE_SYSTEM)
.eq(RecordTemplatePermission::getRelId,user.getId())
.eq(RecordTemplatePermission::getRelType,RecordTemplateConstant.REL_TYPE_USER)
);
//当前登录人员被直接授权的模板
List<Integer> templateIdsAccepted = CollectionUtils.isEmpty(userPermissions)
? new ArrayList<>() : userPermissions.stream().map(RecordTemplatePermission::getTemplateId).collect(Collectors.toList());
//查出所有系统模板授权部门信息
List<RecordTemplatePermission> deptPermissions = permissionMapper.selectList(new LambdaQueryWrapper<RecordTemplatePermission>()
.eq(RecordTemplatePermission::getTemplateType, RecordTemplateConstant.TEMPLATE_TYPE_SYSTEM)
.eq(RecordTemplatePermission::getRelId,user.getId())
.eq(RecordTemplatePermission::getRelType,RecordTemplateConstant.REL_TYPE_DEPT));
//查出当前登录人的部门向上路径
String deptPathByUser = sysUserSyncService.getDeptPathByUserId(user.getId());
if(StringUtils.isNotEmpty(deptPathByUser) && !CollectionUtils.isEmpty(deptPermissions)){
List<Integer> templateIdsDeptAccepted = deptPermissions.stream().filter(item -> deptPathByUser.contains(item.getRelId()))
.map(RecordTemplatePermission::getTemplateId).collect(Collectors.toList());
if(!CollectionUtils.isEmpty(templateIdsDeptAccepted)) templateIdsAccepted.addAll(templateIdsDeptAccepted);
}
for (MeetingRecordTemplate template : systemTemplateList) {
if(templateIdsAccepted.contains(template.getId())){
records.add(template);
}
}
return records;
}
/**
* 获取部门的路径
* @param deptPath
* @param deptId
*/
private void getDeptPath(List<String> deptPath, String deptId) {
private void getDeptPath(List<String> deptPath, String deptId, String tenantId) {
if(!deptPath.contains(deptId)) deptPath.add(deptId);
List<String> subDeptIds = sysUserSysMapper.getSubDeptId(deptId);
List<String> subDeptIds = sysUserSysMapper.getSubDeptId(deptId,tenantId);
if(CollectionUtils.isEmpty(subDeptIds)) return;
for (String subDeptId : subDeptIds) {
//部门id去重
if(!deptPath.contains(subDeptId)){
deptPath.add(subDeptId);
getDeptPath(deptPath,subDeptId);
getDeptPath(deptPath,subDeptId,tenantId);
}
}
......
package com.cmeeting.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cmeeting.ad.entity.SysUserSync;
import com.cmeeting.mapper.secondary.SysUserSysMapper;
import com.cmeeting.service.SysUserSyncService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.util.ArrayList;
import java.util.List;
@Service
@Slf4j
public class SysUserSyncServiceImpl extends ServiceImpl<SysUserSysMapper, SysUserSync> implements SysUserSyncService {
@Value(value = "${permission.tenantId}")
private String perTenantId;
@Override
public String getDeptPathByUserId(String userId) {
SysUserSync sysUserSync = baseMapper.selectOne(new LambdaQueryWrapper<SysUserSync>().eq(SysUserSync::getTenantId, perTenantId).eq(SysUserSync::getUserId, userId));
String deptId = sysUserSync.getDeptId();
String deptPath = getDeptPath("/" + deptId, deptId);
return deptPath;
}
/**
* 向上获取某个部门的路径
* @param deptId
*/
private String getDeptPath(String deptPath,String deptId) {
String parentDeptId = baseMapper.getParentDeptId(deptId,perTenantId);
if(StringUtils.isEmpty(parentDeptId)) return deptPath;
return "/" + parentDeptId + deptPath;
}
}
......@@ -368,10 +368,11 @@ public class TencentMeetingServiceImpl extends ServiceImpl<TecentMeetingMapper,T
String subMeetingId = null;
LocalDateTime mediaStartTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(Long.valueOf(meeting.getMediaStartTime())), ZoneId.systemDefault());
try {
log.info("【周期会议扫描】:查询用户的已结束会议列表...userId->{}",meeting.getUserid());
String userid = meeting.getUserid();
log.info("【周期会议扫描】:查询用户的已结束会议列表...meetingCode->{},userId->{}",meeting.getMeetingCode(), userid);
//获取子会议id
MeetingsApi.ApiV1HistoryMeetingsUseridGetRequest historyMeetingRequest =
new MeetingsApi.ApiV1HistoryMeetingsUseridGetRequest.Builder(meeting.getUserid())
new MeetingsApi.ApiV1HistoryMeetingsUseridGetRequest.Builder(userid)
.pageSize("20")
.page("1")
.meetingCode(meeting.getMeetingCode())
......@@ -558,14 +559,14 @@ public class TencentMeetingServiceImpl extends ServiceImpl<TecentMeetingMapper,T
getDeptPath(deptPath,deptId,tenantId);
}
//已被授权部门下的userid
List<String> accessUserIds = !CollectionUtils.isEmpty(deptPath) ? sysUserSyncMapper.getUsersByDept(deptPath) : new ArrayList<>();
List<String> accessUserIds = !CollectionUtils.isEmpty(deptPath) ? sysUserSyncMapper.getUsersByDept(deptPath,permissionTenantId) : new ArrayList<>();
//已被直接授权的人员追加进去
accessUserIds.addAll(auths.stream().filter(item -> item.getType().equals(1)).map(CoreModulePermissions::getRelId).collect(Collectors.toList()));
if(!CollectionUtils.isEmpty(accessUserIds)){
//查出人员邮箱
List<UserDTO> userEmailList = sysUserSyncMapper.getUserEmail(permissionTenantId);
Map<String, String> userEmailMap = CollectionUtils.isEmpty(userEmailList) ? new HashMap<>()
: userEmailList.stream().collect(Collectors.toMap(UserDTO::getWid, UserDTO::getEmail));
: userEmailList.stream().collect(Collectors.toMap(UserDTO::getWid, UserDTO::getEmail,(existing, replacement) -> existing));
List<UserDTO> accessUsers = new ArrayList<>();
for (String accessUserId : accessUserIds) {
......@@ -598,7 +599,7 @@ public class TencentMeetingServiceImpl extends ServiceImpl<TecentMeetingMapper,T
*/
private void getDeptPath(List<String> deptPath, String deptId, String tenantId) {
if(!deptPath.contains(deptId)) deptPath.add(deptId);
List<String> subDeptIds = sysUserSyncMapper.getSubDeptId(deptId);
List<String> subDeptIds = sysUserSyncMapper.getSubDeptId(deptId,tenantId);
if(CollectionUtils.isEmpty(subDeptIds)) return;
for (String subDeptId : subDeptIds) {
......
package com.cmeeting.util;
import com.alibaba.fastjson.annotation.JSONField;
import org.springframework.web.multipart.MultipartFile;
import java.io.*;
public class CustomMultipartFile implements MultipartFile {
private final String name;
private final String originalFilename;
private final String contentType;
private final byte[] content;
public CustomMultipartFile(String name, String originalFilename, String contentType, byte[] content) {
this.name = name;
this.originalFilename = originalFilename;
this.contentType = contentType;
this.content = content;
}
@Override
public String getName() {
return name;
}
@Override
public String getOriginalFilename() {
return originalFilename;
}
@Override
public String getContentType() {
return contentType;
}
@Override
public boolean isEmpty() {
return content == null || content.length == 0;
}
@Override
public long getSize() {
return content.length;
}
@Override
public byte[] getBytes() throws IOException {
return content;
}
@JSONField(serialize = false)
@Override
public InputStream getInputStream() throws IOException {
return new ByteArrayInputStream(content);
}
@JSONField(serialize = false)
@Override
public void transferTo(File dest) throws IOException, IllegalStateException {
try (OutputStream os = new FileOutputStream(dest)) {
os.write(content);
}
}
}
package com.cmeeting.util;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import com.alibaba.fastjson.JSON;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.util.EntityUtils;
import org.springframework.web.multipart.MultipartFile;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.List;
import java.util.Map;
/**
* @author liuzhenmeng
* @date 2024/6/27 19:48
*/
public class HttpClientKnowledgePlatformUtil {
private static PoolingHttpClientConnectionManager connPoolMng;
private static RequestConfig requestConfig;
private static int maxTotal = 500;
private static final Log log = LogFactory.get();
/**
* 私有构造方法
* 单例中连接池初始化一次
*/
private HttpClientKnowledgePlatformUtil(){
//初始化http连接池
SSLContext sslContext = getSSLContext();
Registry<ConnectionSocketFactory> socketFactoryRegistry =
RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", PlainConnectionSocketFactory.INSTANCE)
.register("https", new SSLConnectionSocketFactory(sslContext)).build();
connPoolMng = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
connPoolMng.setMaxTotal(maxTotal);
connPoolMng.setDefaultMaxPerRoute(maxTotal/5);
//初始化请求超时控制参数
requestConfig = RequestConfig.custom()
.setConnectTimeout(1000) //连接超时时间
.setConnectionRequestTimeout(5000) //从线程池中获取线程超时时间
.setSocketTimeout(1000) //设置数据超时时间
.build();
}
/**
* 获取client客户端
* @return
*/
public static CloseableHttpClient getClient() {
CloseableHttpClient httpClient = HttpClients.custom()
.setConnectionManager(connPoolMng)
.setDefaultRequestConfig(requestConfig)
.build();
return httpClient;
}
/**
* 发送get请求
*
* @param url 路径
* @return
*/
public static String sendHttpGet(String url) {
log.info("请求地址:【{}】", url);
log.info("请求方式:GET");
// get请求返回结果
// 发送get请求
HttpGet request = new HttpGet(url);
request.setConfig(requestConfig);
CloseableHttpResponse response = null;
String result = "";
try {
response = getClient().execute(request);
// 请求发送成功,并得到响应
HttpEntity responseEntity = response.getEntity();
if (responseEntity != null) {
// 将响应内容转换为字符串
result = EntityUtils.toString(responseEntity, StandardCharsets.UTF_8);
}
log.info("请求返回结果:【{}】", result);
} catch (IOException e) {
log.error("get请求提交失败:" + url, e);
} finally {
if (response != null){
try {
//此处调优重点,多线程模式下可提高性能。
EntityUtils.consume(response.getEntity());
response.close();
} catch (IOException e) {
System.out.println("关闭response失败:" + e);
}
}
request.releaseConnection();
}
return result;
}
/**
* 发送POST请求
*
* @param url
* @param parametersBody
* @return
*/
public static String sendPostJsonRequest(String url, String parametersBody) {
log.info("请求地址:【{}】", url);
log.info("请求方式:POST");
log.info("请求参数:【{}】", parametersBody);
HttpPost post = new HttpPost(url);
post.addHeader("Content-Type", "application/json;charset=UTF-8");
post.addHeader("Accept", "application/json");
post.setConfig(requestConfig);
StringEntity entity = new StringEntity(parametersBody, "UTF-8");
post.setEntity(entity);
//设置请求头
// if (StringUtils.isNotBlank(token)){
// post.setHeader("Authorization", token);
// }
String result = "";
CloseableHttpResponse response = null;
try {
response = getClient().execute(post);
HttpEntity responseEntity = response.getEntity();
if (responseEntity != null) {
// 将响应内容转换为字符串
result = EntityUtils.toString(responseEntity, StandardCharsets.UTF_8);
}
log.info("请求返回结果:【{}】", result);
return result;
} catch (ClientProtocolException e) {
throw new RuntimeException("postRequest -- Client protocol exception!", e);
} catch (IOException e) {
throw new RuntimeException("postRequest -- IO error!", e);
} finally {
if (response != null){
try {
//此处调优重点,多线程模式下可提高性能。
EntityUtils.consume(response.getEntity());
response.close();
} catch (IOException e) {
log.error("关闭response失败:" + e);
}
}
post.releaseConnection();
}
}
/**
* 发送POST请求
*
* @param url
* @param parametersBody
* @return
*/
public static String sendPostJsonBySearch(String url, String parametersBody) {
log.info("请求地址:【{}】", url);
log.info("请求方式:POST");
log.info("请求参数:【{}】", parametersBody);
HttpPost post = new HttpPost(url);
post.addHeader("Content-Type", "application/json;charset=UTF-8");
post.addHeader("Accept", "application/json");
post.setConfig(requestConfig);
StringEntity entity = new StringEntity(parametersBody, "UTF-8");
post.setEntity(entity);
String result = "";
CloseableHttpResponse response = null;
try {
response = getClient().execute(post);
HttpEntity responseEntity = response.getEntity();
if (responseEntity != null) {
// 将响应内容转换为字符串
result = EntityUtils.toString(responseEntity, StandardCharsets.UTF_8);
}
return result;
} catch (ClientProtocolException e) {
throw new RuntimeException("postRequest -- Client protocol exception!", e);
} catch (IOException e) {
throw new RuntimeException("postRequest -- IO error!", e);
} finally {
if (response != null){
try {
//此处调优重点,多线程模式下可提高性能。
EntityUtils.consume(response.getEntity());
response.close();
} catch (IOException e) {
log.error("关闭response失败:" + e);
}
}
post.releaseConnection();
}
}
/**
* 使用httpclint 发送文件,如果不传输文件,直接设置fileParams=null,
* 如果不设置请求头参数,直接设置headerParams=null,就可以进行普通参数的POST请求了
*
* @param url 请求路径
* @param file 文件参数
* @param otherParams 其他字符串参数
* @return
*/
public static String sendPostByFormData(String url, MultipartFile file, Map<String, String> otherParams) {
log.info("请求地址:{}", url);
log.info("请求方式:POST");
log.info("请求参数:{}", JSON.toJSONString(otherParams));
String result = "";
CloseableHttpResponse response = null;
HttpPost httpPost = new HttpPost(url);
try {
httpPost.setConfig(requestConfig);
//设置请求头
// if (headerParams != null && headerParams.size() > 0) {
// for (Map.Entry<String, String> e : headerParams.entrySet()) {
// String value = e.getValue();
// String key = e.getKey();
// if (StringUtils.isNotBlank(value)) {
// httpPost.setHeader(key, value);
// }
// }
// }
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setCharset(StandardCharsets.UTF_8);
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
ContentType contentType = ContentType.create("multipart/form-data", StandardCharsets.UTF_8);
// 文件传输http请求头(multipart/form-data)
if (file != null) {
builder.addBinaryBody("file", file.getBytes(), ContentType.MULTIPART_FORM_DATA, file.getOriginalFilename());
}
// 字节传输http请求头
if (otherParams != null && otherParams.size() > 0) {
for (Map.Entry<String, String> e : otherParams.entrySet()) {
String value = e.getValue();
if (StringUtils.isNotBlank(value)) {
builder.addTextBody(e.getKey(), value, contentType);// 类似浏览器表单提交,对应input的name和value
}
}
}
HttpEntity entity = builder.build();
httpPost.setEntity(entity);
response = getClient().execute(httpPost);
HttpEntity responseEntity = response.getEntity();
if (responseEntity != null) {
// 将响应内容转换为字符串
result = EntityUtils.toString(responseEntity, StandardCharsets.UTF_8);
}
log.info("响应数据:{}", JSON.toJSONString(result));
} catch (Exception e) {
e.printStackTrace();
} finally {
if (response != null){
try {
//此处调优重点,多线程模式下可提高性能。
EntityUtils.consume(response.getEntity());
response.close();
} catch (IOException e) {
log.error("关闭response失败:" + e);
}
}
httpPost.releaseConnection();
}
return result;
}
/**
* 使用httpclint 发送文件,如果不传输文件,直接设置fileParams=null,
* 如果不设置请求头参数,直接设置headerParams=null,就可以进行普通参数的POST请求了
*
* @param url 请求路径
* @param fileList 文件参数
* @param otherParams 其他字符串参数
* @return
*/
public static String sendPostByFormDataFiles(String url, List<MultipartFile> fileList, Map<String, String> otherParams, String fileKey) {
log.info("请求地址:{}", url);
log.info("请求方式:POST");
log.info("请求参数:{}", JSON.toJSONString(otherParams));
String result = "";
CloseableHttpResponse response = null;
HttpPost httpPost = new HttpPost(url);
try {
httpPost.setConfig(requestConfig);
//设置请求头
// if (headerParams != null && headerParams.size() > 0) {
// for (Map.Entry<String, String> e : headerParams.entrySet()) {
// String value = e.getValue();
// String key = e.getKey();
// if (StringUtils.isNotBlank(value)) {
// httpPost.setHeader(key, value);
// }
// }
// }
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setCharset(StandardCharsets.UTF_8);
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
ContentType contentType = ContentType.create("multipart/form-data",Charset.forName("UTF-8"));
// 文件传输http请求头(multipart/form-data)
String key = fileKey==null?"files":fileKey;
if (CollectionUtil.isNotEmpty(fileList)) {
for (MultipartFile file:fileList){
builder.addBinaryBody(key, file.getBytes(), ContentType.MULTIPART_FORM_DATA, file.getOriginalFilename());
}
}
// 字节传输http请求头
if (otherParams != null && otherParams.size() > 0) {
for (Map.Entry<String, String> e : otherParams.entrySet()) {
String value = e.getValue();
if (StringUtils.isNotBlank(value)) {
builder.addTextBody(e.getKey(), value, contentType);// 类似浏览器表单提交,对应input的name和value
}
}
}
HttpEntity entity = builder.build();
httpPost.setEntity(entity);
response = getClient().execute(httpPost);
HttpEntity responseEntity = response.getEntity();
if (responseEntity != null) {
// 将响应内容转换为字符串
result = EntityUtils.toString(responseEntity, StandardCharsets.UTF_8);
}
log.info("响应数据:{}", JSON.toJSONString(result));
} catch (Exception e) {
e.printStackTrace();
} finally {
if (response != null){
try {
//此处调优重点,多线程模式下可提高性能。
EntityUtils.consume(response.getEntity());
response.close();
} catch (IOException e) {
log.error("关闭response失败:" + e);
}
}
httpPost.releaseConnection();
}
return result;
}
private static SSLContext getSSLContext() {
try {
// 这里可以填两种值 TLS和LLS , 具体差别可以自行搜索
SSLContext sc = SSLContext.getInstance("TLS");
// 构建新对象
X509TrustManager manager = new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
}
@Override
public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
}
// 这里返回Null
@Override
public X509Certificate[] getAcceptedIssuers() {
return null;
}
};
sc.init(null, new TrustManager[]{manager}, null);
return sc;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
package com.cmeeting.util;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.Builder;
import lombok.Data;
import lombok.ToString;
import lombok.*;
import lombok.experimental.Accessors;
import java.io.Serializable;
......@@ -18,6 +16,8 @@ import java.io.Serializable;
@ToString
@Accessors(chain = true)
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class R implements Serializable {
public static final int SUCCESS_CODE = 0;
......
......@@ -12,4 +12,6 @@ public class UserAdminConfig {
private String userAdminDomain;
@Value("${userAdmin.systemDomain}")
private String systemDomain;
@Value("${userAdmin.docDomain}")
private String docDomain;
}
package com.cmeeting.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
......@@ -61,11 +63,15 @@ public class MeetingInfoVO {
/**
* 会议开始时间(时间戳)
*/
@DateTimeFormat(pattern = "yyy-MM-dd HH:mm:ss")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", locale = "zh", timezone = "GMT+8")
private LocalDateTime startTime;
/**
* 会议结束时间(时间戳)
*/
@DateTimeFormat(pattern = "yyy-MM-dd HH:mm:ss")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", locale = "zh", timezone = "GMT+8")
private LocalDateTime endTime;
/**
......@@ -91,6 +97,8 @@ public class MeetingInfoVO {
/**
* 同步时间
*/
@DateTimeFormat(pattern = "yyy-MM-dd HH:mm:ss")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", locale = "zh", timezone = "GMT+8")
private LocalDateTime syncTime;
/**
......@@ -113,6 +121,8 @@ public class MeetingInfoVO {
/**
* 同步时间
*/
@DateTimeFormat(pattern = "yyy-MM-dd HH:mm:ss")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", locale = "zh", timezone = "GMT+8")
private LocalDateTime updateTime;
/**
......@@ -123,4 +133,14 @@ public class MeetingInfoVO {
* 会议纪要json
*/
private String recordJson;
/**
* 用户信息
*/
private String userId;
private String applicationId;
/**
* 转录文件知识库id
*/
private String transDocId;
}
\ No newline at end of file
package com.cmeeting.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import java.util.List;
/**
......@@ -48,6 +51,25 @@ public class RecordTemplateVO {
*/
private Integer size;
/**
* 创建人查询条件
*/
private String createUser;
/**
* 时间查询条件开始
*/
@DateTimeFormat(pattern = "yyy-MM-dd HH:mm:ss")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", locale = "zh", timezone = "GMT+8")
private LocalDateTime startTime;
/**
* 时间查询条件结束
*/
@DateTimeFormat(pattern = "yyy-MM-dd HH:mm:ss")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", locale = "zh", timezone = "GMT+8")
private LocalDateTime endTime;
@Data
public static class TemplatePermissionVO{
/**
......
server:
port: 8080
port: 8081
############################################################## minio
MINIO_ADDRESS: http://192.168.10.154:9000
......@@ -110,6 +110,9 @@ email:
sender: ${EMAIL_SENDER}
sender-pwd: ${EMAIL_SENDER_PWD}
smtp-host: ${EMAIL_SMTP_HOST}
push-switch: true #邮件推送总开关,高优先级
environment: test #test推给本公司人员,prod推给用户
test-receiver: duanxincheng@chatbot.cn #用于测试的收方邮箱
llm:
api-addr: ${LLM_API_ADDR}
......@@ -127,10 +130,12 @@ ldap:
domain: '@cimc.com'
userAdmin:
domain: http://192.168.10.154:9103
systemDomain: http://192.168.10.154:9101
domain: http://192.168.10.154:8303
systemDomain: http://192.168.10.154:8301
appId: af94e0ec9cc0bef2bfa63f470f6f4351
secret: 4luHTMYMyXzOmDHN0ZOSMwOst702plcr9EKqAHtT8Nag6EPlP0VSFvqv9Zq0NRDE
file-download-path: /download/minio/
docDomain: http://192.168.10.154:8302/knowledgePlatform
removeMenus: 关键词回复,业务词库,同义词管理,答案库
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论