From 8550952435c0719f2cfca539e4fc44d996088042 Mon Sep 17 00:00:00 2001 From: fancy Date: Sun, 30 Jan 2022 15:13:01 +0800 Subject: [PATCH] =?UTF-8?q?IM=E6=B8=85=E7=A9=BA=E4=BC=9A=E8=AF=9D=E8=81=8A?= =?UTF-8?q?=E5=A4=A9=E8=AE=B0=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../factory/IMConversationFactory.java | 16 ++ .../im/ActionDeleteConversationMsgs.java | 60 ++++++ .../jaxrs/im/ActionWriteImConfig.java | 177 ++++++++++++++++++ .../ExceptionConvClearMsgsNoPermission.java | 14 ++ .../im/ExceptionConversationNotExist.java | 12 ++ .../communicate/jaxrs/im/ImAction.java | 46 ++++- .../x_component_IMV2/$Main/default/chat.html | 4 +- .../$Main/default/icons/icon_setting.png | Bin 0 -> 592 bytes .../x_component_IMV2/$Main/default/im.html | 1 + .../x_component_IMV2/$Main/default/style.css | 8 + o2web/source/x_component_IMV2/Main.js | 144 ++++++++++++-- o2web/source/x_component_IMV2/lp/en.js | 6 +- o2web/source/x_component_IMV2/lp/zh-cn.js | 6 +- 13 files changed, 470 insertions(+), 24 deletions(-) create mode 100644 o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/jaxrs/im/ActionDeleteConversationMsgs.java create mode 100644 o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/jaxrs/im/ActionWriteImConfig.java create mode 100644 o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/jaxrs/im/ExceptionConvClearMsgsNoPermission.java create mode 100644 o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/jaxrs/im/ExceptionConversationNotExist.java create mode 100644 o2web/source/x_component_IMV2/$Main/default/icons/icon_setting.png diff --git a/o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/factory/IMConversationFactory.java b/o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/factory/IMConversationFactory.java index 34a09f4659..81ded7918b 100644 --- a/o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/factory/IMConversationFactory.java +++ b/o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/factory/IMConversationFactory.java @@ -122,6 +122,22 @@ public class IMConversationFactory extends AbstractFactory { .getResultList(); } + /** + * 根据会话id查询所有的消息id + * 清空聊天记录用 + * @param conversationId 会话id + * @return + * @throws Exception + */ + public List listAllMsgIdsWithConversationId(String conversationId) throws Exception { + EntityManager em = this.entityManagerContainer().get(IMMsg.class); + CriteriaBuilder cb = em.getCriteriaBuilder(); + CriteriaQuery cq = cb.createQuery(String.class); + Root root = cq.from(IMMsg.class); + Predicate p = cb.equal(root.get(IMMsg_.conversationId), conversationId); + return em.createQuery(cq.select(root.get(IMMsg_.id)).where(p)).getResultList(); + } + /** * 查询会话聊天消息总数 * 分页查询需要 diff --git a/o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/jaxrs/im/ActionDeleteConversationMsgs.java b/o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/jaxrs/im/ActionDeleteConversationMsgs.java new file mode 100644 index 0000000000..d1378362d2 --- /dev/null +++ b/o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/jaxrs/im/ActionDeleteConversationMsgs.java @@ -0,0 +1,60 @@ +package com.x.message.assemble.communicate.jaxrs.im; + +import com.x.base.core.container.EntityManagerContainer; +import com.x.base.core.container.factory.EntityManagerContainerFactory; +import com.x.base.core.project.http.ActionResult; +import com.x.base.core.project.http.EffectivePerson; +import com.x.base.core.project.http.WrapOutBoolean; +import com.x.base.core.project.logger.Logger; +import com.x.base.core.project.logger.LoggerFactory; +import com.x.message.assemble.communicate.Business; +import com.x.message.core.entity.IMConversation; +import com.x.message.core.entity.IMMsg; +import org.apache.commons.lang3.StringUtils; + +import java.util.List; + + +public class ActionDeleteConversationMsgs extends BaseAction { + + private static Logger logger = LoggerFactory.getLogger(ActionDeleteConversationMsgs.class); + + ActionResult execute(EffectivePerson effectivePerson, String conversationId) throws Exception { + ActionResult result = new ActionResult<>(); + if (StringUtils.isEmpty(conversationId)) { + throw new ExceptionEmptyId(); + } + try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) { + Wo wo = new Wo(); + Business business = new Business(emc); + // 判断权限 群聊只有管理员能清空 + IMConversation conversation = emc.find(conversationId, IMConversation.class); + if (conversation == null) { + throw new ExceptionConversationNotExist(); + } + if (conversation.getType().equals(IMConversation.CONVERSATION_TYPE_GROUP) && + !effectivePerson.getDistinguishedName().equals(conversation.getAdminPerson())) { + throw new ExceptionConvClearMsgsNoPermission(); + } + + List msgIds = business.imConversationFactory().listAllMsgIdsWithConversationId(conversationId); + if (msgIds == null || msgIds.isEmpty()) { + logger.info("没有聊天记录,无需清空! conversationId:"+conversationId); + } else { + // 这里是1条条删除的 优化一下? + emc.beginTransaction(IMMsg.class); + emc.delete(IMMsg.class, msgIds); + emc.commit(); + logger.info("成功清空聊天记录!conversationId:" + conversationId + " msg size:" + msgIds.size() + " person:" + effectivePerson.getDistinguishedName()); + } + wo.setValue(true); + result.setData(wo); + } + return result; + } + + + static class Wo extends WrapOutBoolean { + + } +} diff --git a/o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/jaxrs/im/ActionWriteImConfig.java b/o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/jaxrs/im/ActionWriteImConfig.java new file mode 100644 index 0000000000..41b332eb81 --- /dev/null +++ b/o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/jaxrs/im/ActionWriteImConfig.java @@ -0,0 +1,177 @@ +package com.x.message.assemble.communicate.jaxrs.im; + +import com.google.gson.JsonElement; +import com.x.base.core.project.annotation.FieldDescribe; +import com.x.base.core.project.config.Config; +import com.x.base.core.project.config.WebServers; +import com.x.base.core.project.connection.ActionResponse; +import com.x.base.core.project.connection.CipherConnectionAction; +import com.x.base.core.project.gson.GsonPropertyObject; +import com.x.base.core.project.http.ActionResult; +import com.x.base.core.project.http.EffectivePerson; +import com.x.base.core.project.http.WrapOutBoolean; +import com.x.base.core.project.logger.Logger; +import com.x.base.core.project.logger.LoggerFactory; + +import java.util.LinkedHashMap; +import java.util.Map; + +public class ActionWriteImConfig extends BaseAction { + + private static Logger logger = LoggerFactory.getLogger(ActionWriteImConfig.class); + + + ActionResult execute(EffectivePerson effectivePerson, JsonElement jsonElement) throws Exception { + ActionResult result = new ActionResult(); + Wi wi = this.convertToWrapIn(jsonElement, Wi.class); + LinkedHashMap map = new LinkedHashMap<>(); + for (Map.Entry en : Config.web().entrySet()) { + map.put(en.getKey(), en.getValue()); + } + map.put(Wi.IM_CONFIG_KEY_NAME, wi); + String content = gson.toJson(map); + String fileName = "web.json"; + logger.info("更新配置文件。。。。。。。。。。。。。。"); + logger.info("文件:" + fileName); + logger.info("内容:" + content); + WebConfigSaveWi saveWi = new WebConfigSaveWi(); + saveWi.setFileName(fileName); + saveWi.setFileContent(content); + ActionResponse response = CipherConnectionAction.post(false, Config.url_x_program_center_jaxrs("config", "save"), saveWi); + Wo wo = new Wo(); + if (response != null) { + SaveConfigWo saveWo = response.getData(SaveConfigWo.class); + if (saveWo != null && saveWo.getStatus() != null) { + logger.info("修改保存["+fileName+"]配置文件成功!"); + try { + WebServers.updateWebServerConfigJson(); + logger.info("更新 config.json 成功!!!!"); + wo.setValue(true); + result.setData(wo); + } catch (Exception e) { + logger.info("更新前端 config.json 出错"); + wo.setValue(false); + result.setData(wo); + logger.error(e); + } + } else { + logger.info("保存["+fileName+"]配置文件data返回为空!!!!"); + wo.setValue(false); + result.setData(wo); + } + } else { + logger.info("保存["+fileName+"]配置文件 返回为空!!"); + wo.setValue(false); + result.setData(wo); + } + + return result; + } + + + + public static class WebConfigSaveWi extends GsonPropertyObject { + private String fileName; + private String fileContent; + + public String getFileName() { + return fileName; + } + + public void setFileName(String fileName) { + this.fileName = fileName; + } + + public String getFileContent() { + return fileContent; + } + + public void setFileContent(String fileContent) { + this.fileContent = fileContent; + } + } + + /** + * IM的配置文件,这个配置文件默认写入到 web.json key=imConfig + */ + static class Wi extends GsonPropertyObject { + + public static final String IM_CONFIG_KEY_NAME = "imConfig"; // 这个配置会已对象写入到 web.json ,已imConfig作为key名称 + + + @FieldDescribe("是否开启清空聊天记录的功能.") + private Boolean enableClearMsg; + + public Boolean getEnableClearMsg() { + return enableClearMsg; + } + + public void setEnableClearMsg(Boolean enableClearMsg) { + this.enableClearMsg = enableClearMsg; + } + } + + static class Wo extends WrapOutBoolean { + + } + + + public static class SaveConfigWo extends GsonPropertyObject { + + @FieldDescribe("执行时间") + private String time; + + @FieldDescribe("执行结果") + private String status; + + @FieldDescribe("执行消息") + private String message; + + @FieldDescribe("config文件内容") + private String fileContent; + + @FieldDescribe("是否Sample") + private boolean isSample; + + public String getTime() { + return time; + } + + public void setTime(String time) { + this.time = time; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public String getFileContent() { + return fileContent; + } + + public void setFileContent(String fileContent) { + this.fileContent = fileContent; + } + + public boolean isSample() { + return isSample; + } + + public void setSample(boolean isSample) { + this.isSample = isSample; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + } +} diff --git a/o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/jaxrs/im/ExceptionConvClearMsgsNoPermission.java b/o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/jaxrs/im/ExceptionConvClearMsgsNoPermission.java new file mode 100644 index 0000000000..ea568232eb --- /dev/null +++ b/o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/jaxrs/im/ExceptionConvClearMsgsNoPermission.java @@ -0,0 +1,14 @@ +package com.x.message.assemble.communicate.jaxrs.im; + +import com.x.base.core.project.exception.PromptException; + +class ExceptionConvClearMsgsNoPermission extends PromptException { + + private static final long serialVersionUID = 4132300948670472899L; + + ExceptionConvClearMsgsNoPermission() { + super("没有权限清空聊天记录!"); + } + + +} diff --git a/o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/jaxrs/im/ExceptionConversationNotExist.java b/o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/jaxrs/im/ExceptionConversationNotExist.java new file mode 100644 index 0000000000..e694fe7e5e --- /dev/null +++ b/o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/jaxrs/im/ExceptionConversationNotExist.java @@ -0,0 +1,12 @@ +package com.x.message.assemble.communicate.jaxrs.im; + +import com.x.base.core.project.exception.PromptException; + +class ExceptionConversationNotExist extends PromptException { + + private static final long serialVersionUID = 4132300948670472899L; + + ExceptionConversationNotExist() { + super("会话不存在!"); + } +} diff --git a/o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/jaxrs/im/ImAction.java b/o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/jaxrs/im/ImAction.java index 99becb5f7f..12b0c0e7a3 100644 --- a/o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/jaxrs/im/ImAction.java +++ b/o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/jaxrs/im/ImAction.java @@ -3,13 +3,7 @@ package com.x.message.assemble.communicate.jaxrs.im; import java.util.List; import javax.servlet.http.HttpServletRequest; -import javax.ws.rs.Consumes; -import javax.ws.rs.GET; -import javax.ws.rs.POST; -import javax.ws.rs.PUT; -import javax.ws.rs.Path; -import javax.ws.rs.PathParam; -import javax.ws.rs.Produces; +import javax.ws.rs.*; import javax.ws.rs.container.AsyncResponse; import javax.ws.rs.container.Suspended; import javax.ws.rs.core.Context; @@ -39,6 +33,26 @@ public class ImAction extends StandardJaxrsAction { private static Logger logger = LoggerFactory.getLogger(ImAction.class); + /**************** im manager ************/ + + + @JaxrsMethodDescribe(value = "更新IM配置.", action = ActionWriteImConfig.class) + @POST + @Path("manager/config") + @Produces(HttpMediaType.APPLICATION_JSON_UTF_8) + @Consumes(MediaType.APPLICATION_JSON) + public void config(@Suspended final AsyncResponse asyncResponse, @Context HttpServletRequest request, + JsonElement jsonElement) { + ActionResult result = new ActionResult<>(); + EffectivePerson effectivePerson = this.effectivePerson(request); + try { + result = new ActionWriteImConfig().execute( effectivePerson, jsonElement ); + } catch (Exception e) { + logger.error(e, effectivePerson, request, jsonElement); + result.error(e); + } + asyncResponse.resume(ResponseFactory.getEntityTagActionResultResponse(request, result)); + } /************* im conversation ************/ @@ -174,6 +188,24 @@ public class ImAction extends StandardJaxrsAction { asyncResponse.resume(ResponseFactory.getEntityTagActionResultResponse(request, result)); } + @JaxrsMethodDescribe(value = "清空会话的所有消息.", action = ActionDeleteConversationMsgs.class) + @DELETE + @Path("conversation/{id}/clear/all/msg") + @Produces(HttpMediaType.APPLICATION_JSON_UTF_8) + @Consumes(MediaType.APPLICATION_JSON) + public void clearConversationMsg(@Suspended final AsyncResponse asyncResponse, @Context HttpServletRequest request, + @JaxrsParameterDescribe("会话ID") @PathParam("id") String id) { + ActionResult result = new ActionResult<>(); + EffectivePerson effectivePerson = this.effectivePerson(request); + try { + result = new ActionDeleteConversationMsgs().execute(effectivePerson, id); + } catch (Exception e) { + logger.error(e, effectivePerson, request, null); + result.error(e); + } + asyncResponse.resume(ResponseFactory.getEntityTagActionResultResponse(request, result)); + } + /************* im message ************/ diff --git a/o2web/source/x_component_IMV2/$Main/default/chat.html b/o2web/source/x_component_IMV2/$Main/default/chat.html index af70936981..86bd79f2aa 100644 --- a/o2web/source/x_component_IMV2/$Main/default/chat.html +++ b/o2web/source/x_component_IMV2/$Main/default/chat.html @@ -6,6 +6,8 @@
{{$.lp.modifyGroupName}}
{{$.lp.modifyMember}}
+ @@ -21,7 +23,7 @@
-
Ctrl + Enter 换行
+
{{$.lp.sendKeyTips}}
{{$.lp.send}}
diff --git a/o2web/source/x_component_IMV2/$Main/default/icons/icon_setting.png b/o2web/source/x_component_IMV2/$Main/default/icons/icon_setting.png new file mode 100644 index 0000000000000000000000000000000000000000..7055fc6f69b6edd735274e44f86f0e3c4c0839d3 GIT binary patch literal 592 zcmV-W0Px%3Q0skR7gv`RZWi!VGw?*FXCVL2-%YhegTOCyIh8KvAYqGIJ{Mc3vtCk%v8M- zSDAIe*o)nbIPecRI1nF^@B^F$Ntg6wx6{)*-8~yS`u27`Z#}81=Y5JW<&P%GZ)OVs z_7t)1{y{{ZHQjF{FtcL-UR5MI&djgtNE!)L^#Tzsk4xh23nKDpTLdx2OKF-WNs{zK z2*1qi27o&iNp3Rp-5BGpG))(iB>53SSSeyhDloHq0InARUjQ6v=<`PaGX>0TX1=v~ z&IwfY5D~p=8rmdrcb^fFPZ_pIFd(8ub;sRjMPz+gL5y+M-B&A=a<)qEW_B3Bn{oGuXeory&s$_>Z2*%EMcxOb7y1**}=@_0X)tXK%^mrs|^GX09+|x&NK6qEh@@>sOmW) z%7gB%BC;(4cb^xLr&|cdwFtm-Woz89|8rn58kJ!imUpVD {{$.lp.createGroup}}
+