提交 85509524 编写于 作者: F fancy

IM清空会话聊天记录

上级 99d5e395
......@@ -122,6 +122,22 @@ public class IMConversationFactory extends AbstractFactory {
.getResultList();
}
/**
* 根据会话id查询所有的消息id
* 清空聊天记录用
* @param conversationId 会话id
* @return
* @throws Exception
*/
public List<String> listAllMsgIdsWithConversationId(String conversationId) throws Exception {
EntityManager em = this.entityManagerContainer().get(IMMsg.class);
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<String> cq = cb.createQuery(String.class);
Root<IMMsg> 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();
}
/**
* 查询会话聊天消息总数
* 分页查询需要
......
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<Wo> execute(EffectivePerson effectivePerson, String conversationId) throws Exception {
ActionResult<Wo> 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<String> 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 {
}
}
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<Wo> execute(EffectivePerson effectivePerson, JsonElement jsonElement) throws Exception {
ActionResult<Wo> result = new ActionResult<Wo>();
Wi wi = this.convertToWrapIn(jsonElement, Wi.class);
LinkedHashMap<String, Object> map = new LinkedHashMap<>();
for (Map.Entry<String, JsonElement> 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;
}
}
}
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("没有权限清空聊天记录!");
}
}
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("会话不存在!");
}
}
......@@ -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<ActionWriteImConfig.Wo> 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<ActionDeleteConversationMsgs.Wo> 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 ************/
......
......@@ -6,6 +6,8 @@
<div class="o2_im_chat_content_title_menu_item" data-o2-element="chatTitleMoreMenuItem1Node" data-o2-events="click:tapUpdateConvTitle">{{$.lp.modifyGroupName}}</div>
<div class="o2_im_chat_content_title_menu_item" data-o2-element="chatTitleMoreMenuItem2Node" data-o2-events="click:tapUpdateConvMembers">
{{$.lp.modifyMember}}</div>
<div class="o2_im_chat_content_title_menu_item" data-o2-element="chatTitleMoreMenuItem3Node" data-o2-events="click:tapClearMsg" style="display: none;">
{{$.lp.clearAllMsg}}</div>
</div>
</div>
<!-- 聊天内容 -->
......@@ -21,7 +23,7 @@
<textarea data-o2-element="chatBottomAreaTextareaNode" placeholder="{{$.lp.enterMessage}}"></textarea>
</div>
<div class="chat-bottom-area-send-space">
<div class="chat-bottom-area-key-tips">Ctrl + Enter 换行</div>
<div class="chat-bottom-area-key-tips">{{$.lp.sendKeyTips}}</div>
<div class="chat-bottom-area-send" data-o2-element="chatBottomAreaSendAreaNode">
<span class="chat-bottom-area-send-btn" data-o2-element="chatBottomAreaSendBtnNode" data-o2-events="click:sendMsg">{{$.lp.send}}</span>
</div>
......
......@@ -8,6 +8,7 @@
<div class="group" data-o2-element="o2ImGroupConvCreateNode" data-o2-events="click:tapCreateGroupConv">
{{$.lp.createGroup}}
</div>
<div class="im_setting" style="display: none;" data-o2-element="o2ImAdminSettingNode" data-o2-events="click:tapOpenSettings"></div>
<!-- <div class="search_out">
<div title="搜索" class="search_icon"></div>
<div class="search_input_out">
......
......@@ -44,6 +44,14 @@
padding-left: 24px;
float: left;
}
.o2_im_chat_list_top .im_setting {
background: url(../x_component_IMV2/$Main/default/icons/icon_setting.png) no-repeat center;
height: 40px;
float: right;
width: 40px;
border-left: solid 1px #dedede;
cursor: pointer;
}
.o2_im_chat_list_top .search_out {
margin-right: 40px;
......
......@@ -56,6 +56,10 @@ MWF.xApplication.IMV2.Main = new Class({
this.app.notice(this.lp.messageXadminNotSupport, "error");
return;
}
// 先加载配置文件 放入imConfig对象
MWF.xDesktop.loadConfig(function () {
this.imConfig = layout.config.imConfig || {}
console.log("imConfig", this.imConfig);
var url = this.path + this.options.style + "/im.html";
this.content.loadHtml(url, { "bind": { "lp": this.lp, "data": {} }, "module": this }, function () {
//设置content
......@@ -69,8 +73,15 @@ MWF.xApplication.IMV2.Main = new Class({
this.loadConversationList(json.data);
}
}.bind(this));
// 管理员可见设置按钮
if (MWF.AC.isAdministrator()) {
this.o2ImAdminSettingNode.setStyle("display", "block");
} else {
this.o2ImAdminSettingNode.setStyle("display", "none");
}
}.bind(this));
}.bind(this));
this.loadComponentName();
},
// 监听ws消息
......@@ -128,6 +139,59 @@ MWF.xApplication.IMV2.Main = new Class({
console.log(error);
}.bind(this), false);
},
// 点击设置按钮
tapOpenSettings: function() {
this.openSettingsDialog();
},
// 打开IM配置文件
openSettingsDialog: function () {
var settingNode = new Element("div", {"style":"padding:10px;background-color:#fff;"});
// var imConfig = layout.config.imConfig || {}
var lineNode = new Element("div", {"style":"height:24px;line-height: 24px;", "text": "是否开启聊天消息清除功能:"}).inject(settingNode);
var isClearEnableNode = new Element("input", {"type":"checkbox", "checked": this.imConfig.enableClearMsg || false}).inject(lineNode);
var dlg = o2.DL.open({
"title": this.lp.setting,
"mask": true,
"content": settingNode,
"onQueryClose": function () {
settingNode.destroy();
}.bind(this),
"buttonList": [
{
"type": "ok",
"text": this.lp.ok,
"action": function () {
this.imConfig.enableClearMsg = isClearEnableNode.get("checked");
console.log(this.imConfig);
this.postIMConfig(this.imConfig);
// 保存配置文件
dlg.close();
}.bind(this)
},
{
"type": "cancel",
"text": this.lp.close,
"action": function () { dlg.close(); }
}
],
"onPostShow": function () {
dlg.reCenter();
}.bind(this),
"onPostClose": function(){
dlg = null;
}.bind(this)
});
},
// 保存IM配置文件
postIMConfig: function (imConfig) {
o2.Actions.load("x_message_assemble_communicate").ImAction.config(imConfig, function (json) {
console.log("保存配置完成", json.data);
this.refresh();//重新加载整个IM应用
}.bind(this), function (error) {
console.log(error);
this.app.notice(error, "error", this.app.content);
}.bind(this));
},
//点击会话
tapConv: function (conv) {
this._setCheckNode(conv);
......@@ -135,6 +199,10 @@ MWF.xApplication.IMV2.Main = new Class({
var data = { "convName": conv.title, "lp": this.lp };
this.conversationId = conv.id;
this.chatNode.empty();
if (this.emojiBoxNode) {
this.emojiBoxNode.destroy();
this.emojiBoxNode = null;
}
this.chatNode.loadHtml(url, { "bind": data, "module": this }, function () {
var me = layout.session.user.distinguishedName;
if (conv.type === "group" && me === conv.adminPerson) {
......@@ -144,6 +212,29 @@ MWF.xApplication.IMV2.Main = new Class({
var display = this.chatTitleMoreMenuNode.getStyle("display");
if (display === "none") {
this.chatTitleMoreMenuNode.setStyle("display", "block");
this.chatTitleMoreMenuItem1Node.setStyle("display", "block");
this.chatTitleMoreMenuItem2Node.setStyle("display", "block");
if (this.imConfig.enableClearMsg) {
this.chatTitleMoreMenuItem3Node.setStyle("display", "block");
} else {
this.chatTitleMoreMenuItem3Node.setStyle("display", "none");
}
} else {
this.chatTitleMoreMenuNode.setStyle("display", "none");
}
}.bind(this)
});
} else if (conv.type !== "group") {
if (this.imConfig.enableClearMsg) {
this.chatTitleMoreBtnNode.setStyle("display", "block");
this.chatTitleMoreBtnNode.addEvents({
"click": function (e) {
var display = this.chatTitleMoreMenuNode.getStyle("display");
if (display === "none") {
this.chatTitleMoreMenuNode.setStyle("display", "block");
this.chatTitleMoreMenuItem1Node.setStyle("display", "none");
this.chatTitleMoreMenuItem2Node.setStyle("display", "none");
this.chatTitleMoreMenuItem3Node.setStyle("display", "block");
} else {
this.chatTitleMoreMenuNode.setStyle("display", "none");
}
......@@ -152,6 +243,7 @@ MWF.xApplication.IMV2.Main = new Class({
} else {
this.chatTitleMoreBtnNode.setStyle("display", "none");
}
}
//获取聊天信息
this.messageList = [];
this.loadMsgListByConvId(1, 20, conv.id);
......@@ -200,6 +292,29 @@ MWF.xApplication.IMV2.Main = new Class({
var form = new MWF.xApplication.IMV2.CreateConversationForm(this, {}, { "title": this.lp.modifyMember, "personCount": 0, "personSelected": members, "isUpdateMember": true }, { app: this.app });
form.create()
},
// 点击菜单 清空聊天记录
tapClearMsg: function(e) {
var _self = this;
MWF.xDesktop.confirm("info", this.chatTitleNode, this.lp.alert, this.lp.messageClearAllMsgAlert, 400, 150, function() {
o2.Actions.load("x_message_assemble_communicate").ImAction.clearConversationMsg(_self.conversationId, function (json) {
_self._reclickConv();
}, function (error) {
console.log(error);
_self.app.notice(error, "error", _self.app.content);
});
this.close();
}, function(){
this.close();
}, null, null, "o2");
},
_reclickConv: function() {
for (var i = 0; i < this.conversationNodeItemList.length; i++) {
var c = this.conversationNodeItemList[i];
if (this.conversationId == c.data.id) {
this.tapConv(c.data);
}
}
},
//点击发送消息
sendMsg: function () {
var text = this.chatBottomAreaTextareaNode.value;
......@@ -208,6 +323,7 @@ MWF.xApplication.IMV2.Main = new Class({
this._newAndSendTextMsg(text, "text");
} else {
console.log(this.lp.noMessage);
this.app.notice(this.lp.noMessage, "error", this.app.content);
}
},
//点击表情按钮
......
......@@ -20,13 +20,17 @@ MWF.xApplication.IMV2.LP = {
"selectPerson": "Person",
"ok": "OK",
"close": "Close",
"alert": "Tips",
"setting": "Setting",
"modifyGroupName": "Modify Name",
"groupName": "Name",
"clearAllMsg": "Clear chat history",
"enterMessage": "Enter message content",
"send": "Send",
"sendKeyTips": "Ctrl + Enter Line feed",
"file": "[File]",
"messageXadminNotSupport": "The xadmin cannot use chat, please switch to normal user login!"
"messageXadminNotSupport": "The xadmin cannot use chat, please switch to normal user login!",
"messageClearAllMsgAlert": "Are you sure you want to clear the chat records? After clearing, everyone in the current session will not see these chat records?"
};
......@@ -20,13 +20,17 @@ MWF.xApplication.IMV2.LP = {
"selectPerson": "选择人员",
"ok": "确定",
"close": "关闭",
"alert": "提示",
"setting": "设置",
"modifyGroupName": "修改群名",
"groupName": "群名",
"clearAllMsg": "清空聊天记录",
"enterMessage": "输入消息内容",
"send": "发送",
"sendKeyTips": "Ctrl + Enter 换行",
"file": "[文件]",
"messageXadminNotSupport": "xadmin用户无法使用聊聊,请切换正常的用户登录!"
"messageXadminNotSupport": "xadmin用户无法使用聊聊,请切换正常的用户登录!",
"messageClearAllMsgAlert": "确定要清空聊天记录吗,清空后当前会话所有人都将看不到这些聊天记录?"
};
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册