提交 3829cc92 编写于 作者: 楼国栋

Merge branch 'feat/im_process' into 'develop'

流程关联IM,发起群组讨论功能

See merge request o2oa/o2oa!389
......@@ -23,6 +23,25 @@ public class IMConversationFactory extends AbstractFactory {
super(business);
}
/**
* 根据 businessId 获取会话列表 并且成员包含person
* @param person
* @param businessId
* @return
* @throws Exception
*/
public List<IMConversation> listConversationWithPersonAndBusinessId(String person, String businessId) throws Exception {
EntityManager em = this.entityManagerContainer().get(IMConversation.class);
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<IMConversation> cq = cb.createQuery(IMConversation.class);
Root<IMConversation> root = cq.from(IMConversation.class);
Predicate p = cb.isMember(person, root.get(IMConversation_.personList));
p = cb.and(p, cb.equal(root.get(IMConversation_.businessId), businessId));
cq.select(root).where(p);
return em.createQuery(cq).getResultList();
}
/**
* 获取成员包含person的会话id 列表
* @param person
......
......@@ -10,15 +10,20 @@ import com.x.base.core.container.EntityManagerContainer;
import com.x.base.core.container.factory.EntityManagerContainerFactory;
import com.x.base.core.entity.JpaObject;
import com.x.base.core.entity.annotation.CheckPersistType;
import com.x.base.core.project.Application;
import com.x.base.core.project.bean.WrapCopier;
import com.x.base.core.project.bean.WrapCopierFactory;
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.logger.Logger;
import com.x.base.core.project.logger.LoggerFactory;
import com.x.base.core.project.tools.ListTools;
import com.x.base.core.project.x_processplatform_assemble_surface;
import com.x.message.assemble.communicate.Business;
import com.x.message.assemble.communicate.ThisApplication;
import com.x.message.core.entity.IMConversation;
import org.apache.commons.lang3.StringUtils;
public class ActionConversationCreate extends BaseAction {
......@@ -70,7 +75,7 @@ public class ActionConversationCreate extends BaseAction {
}
//处理标题
if (conversation.getTitle() == null || conversation.getTitle().isEmpty()) {
if (StringUtils.isEmpty(conversation.getTitle())) {
String title = "";
if (conversation.getType().equals(CONVERSATION_TYPE_SINGLE)) {
for (int i = 0; i < conversation.getPersonList().size(); i++) {
......@@ -91,9 +96,40 @@ public class ActionConversationCreate extends BaseAction {
title += person.substring(0, person.indexOf("@")) + "、";
}
}
if (title.endsWith("、")) {
title = title.substring(0, title.length()-1);
}
}
conversation.setTitle(title);
}
// 处理业务对象
if (StringUtils.isNotEmpty(conversation.getBusinessId())) {
if (StringUtils.isEmpty(conversation.getBusinessType()) || !conversation.getBusinessType().equals(IMConversation.CONVERSATION_BUSINESS_TYPE_PROCESS)) {
throw new ExceptionEmptyBusinessType();
}
//todo 当前只有流程
FindByJobIdWo jobIdWo = getProcessWork(conversation.getBusinessId());
if (jobIdWo == null) {
throw new ExceptionEmptyBusinessObject(conversation.getBusinessId());
}
String businessBody = "";
if (jobIdWo.getWorkList() != null && !jobIdWo.getWorkList().isEmpty()) {
WorkWo workWo = jobIdWo.getWorkList().get(0);
businessBody = workWo.toString();
}
if (StringUtils.isEmpty(businessBody)) {
if (jobIdWo.getWorkCompletedList() != null && !jobIdWo.getWorkCompletedList().isEmpty()) {
WorkCompletedWo workWo = jobIdWo.getWorkCompletedList().get(0);
businessBody = workWo.toString();
}
}
if (StringUtils.isEmpty(businessBody)) {
throw new ExceptionEmptyBusinessObject(conversation.getBusinessId());
}
conversation.setBusinessBody(businessBody);
}
emc.beginTransaction(IMConversation.class);
emc.persist(conversation, CheckPersistType.all);
emc.commit();
......@@ -107,6 +143,19 @@ public class ActionConversationCreate extends BaseAction {
/**
* 根据jobId查询工作
* @param jobId
* @return
* @throws Exception
*/
private FindByJobIdWo getProcessWork(String jobId) throws Exception {
Application process = ThisApplication.context().applications()
.randomWithWeight(x_processplatform_assemble_surface.class.getName());
return ThisApplication.context().applications().getQuery(process, "job/" + jobId + "/find/work/workcompleted").getData(FindByJobIdWo.class);
}
public static class Wo extends IMConversation {
private static final long serialVersionUID = 3434938936805201380L;
......@@ -115,4 +164,517 @@ public class ActionConversationCreate extends BaseAction {
}
public static class FindByJobIdWo extends GsonPropertyObject {
private List<WorkWo> workList;
private List<WorkCompletedWo> workCompletedList;
public List<WorkWo> getWorkList() {
return workList;
}
public void setWorkList(List<WorkWo> workList) {
this.workList = workList;
}
public List<WorkCompletedWo> getWorkCompletedList() {
return workCompletedList;
}
public void setWorkCompletedList(List<WorkCompletedWo> workCompletedList) {
this.workCompletedList = workCompletedList;
}
}
public static class WorkWo extends GsonPropertyObject {
private String id;
private String job;
private String title;
private String startTime;
private String startTimeMonth;
private String creatorPerson;
private String creatorIdentity;
private String creatorUnit;
private String application;
private String applicationName;
private String applicationAlias;
private String process;
private String processName;
private String processAlias;
private String activity;
private String activityType;
private String activityName;
private String activityAlias;
private String activityDescription;
private String activityToken;
private String activityArrivedTime;
private String serial;
private boolean dataChanged;
private boolean workThroughManual;
private String workCreateType;
private String workStatus;
private boolean beforeExecuted;
private String manualTaskIdentityText;
private boolean splitting;
private String form;
private String destinationRoute;
private String destinationRouteName;
private String destinationActivityType;
private String destinationActivity;
private String createTime;
private String updateTime;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getJob() {
return job;
}
public void setJob(String job) {
this.job = job;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getStartTime() {
return startTime;
}
public void setStartTime(String startTime) {
this.startTime = startTime;
}
public String getStartTimeMonth() {
return startTimeMonth;
}
public void setStartTimeMonth(String startTimeMonth) {
this.startTimeMonth = startTimeMonth;
}
public String getCreatorPerson() {
return creatorPerson;
}
public void setCreatorPerson(String creatorPerson) {
this.creatorPerson = creatorPerson;
}
public String getCreatorIdentity() {
return creatorIdentity;
}
public void setCreatorIdentity(String creatorIdentity) {
this.creatorIdentity = creatorIdentity;
}
public String getCreatorUnit() {
return creatorUnit;
}
public void setCreatorUnit(String creatorUnit) {
this.creatorUnit = creatorUnit;
}
public String getApplication() {
return application;
}
public void setApplication(String application) {
this.application = application;
}
public String getApplicationName() {
return applicationName;
}
public void setApplicationName(String applicationName) {
this.applicationName = applicationName;
}
public String getApplicationAlias() {
return applicationAlias;
}
public void setApplicationAlias(String applicationAlias) {
this.applicationAlias = applicationAlias;
}
public String getProcess() {
return process;
}
public void setProcess(String process) {
this.process = process;
}
public String getProcessName() {
return processName;
}
public void setProcessName(String processName) {
this.processName = processName;
}
public String getProcessAlias() {
return processAlias;
}
public void setProcessAlias(String processAlias) {
this.processAlias = processAlias;
}
public String getActivity() {
return activity;
}
public void setActivity(String activity) {
this.activity = activity;
}
public String getActivityType() {
return activityType;
}
public void setActivityType(String activityType) {
this.activityType = activityType;
}
public String getActivityName() {
return activityName;
}
public void setActivityName(String activityName) {
this.activityName = activityName;
}
public String getActivityAlias() {
return activityAlias;
}
public void setActivityAlias(String activityAlias) {
this.activityAlias = activityAlias;
}
public String getActivityDescription() {
return activityDescription;
}
public void setActivityDescription(String activityDescription) {
this.activityDescription = activityDescription;
}
public String getActivityToken() {
return activityToken;
}
public void setActivityToken(String activityToken) {
this.activityToken = activityToken;
}
public String getActivityArrivedTime() {
return activityArrivedTime;
}
public void setActivityArrivedTime(String activityArrivedTime) {
this.activityArrivedTime = activityArrivedTime;
}
public String getSerial() {
return serial;
}
public void setSerial(String serial) {
this.serial = serial;
}
public boolean isDataChanged() {
return dataChanged;
}
public void setDataChanged(boolean dataChanged) {
this.dataChanged = dataChanged;
}
public boolean isWorkThroughManual() {
return workThroughManual;
}
public void setWorkThroughManual(boolean workThroughManual) {
this.workThroughManual = workThroughManual;
}
public String getWorkCreateType() {
return workCreateType;
}
public void setWorkCreateType(String workCreateType) {
this.workCreateType = workCreateType;
}
public String getWorkStatus() {
return workStatus;
}
public void setWorkStatus(String workStatus) {
this.workStatus = workStatus;
}
public boolean isBeforeExecuted() {
return beforeExecuted;
}
public void setBeforeExecuted(boolean beforeExecuted) {
this.beforeExecuted = beforeExecuted;
}
public String getManualTaskIdentityText() {
return manualTaskIdentityText;
}
public void setManualTaskIdentityText(String manualTaskIdentityText) {
this.manualTaskIdentityText = manualTaskIdentityText;
}
public boolean isSplitting() {
return splitting;
}
public void setSplitting(boolean splitting) {
this.splitting = splitting;
}
public String getForm() {
return form;
}
public void setForm(String form) {
this.form = form;
}
public String getDestinationRoute() {
return destinationRoute;
}
public void setDestinationRoute(String destinationRoute) {
this.destinationRoute = destinationRoute;
}
public String getDestinationRouteName() {
return destinationRouteName;
}
public void setDestinationRouteName(String destinationRouteName) {
this.destinationRouteName = destinationRouteName;
}
public String getDestinationActivityType() {
return destinationActivityType;
}
public void setDestinationActivityType(String destinationActivityType) {
this.destinationActivityType = destinationActivityType;
}
public String getDestinationActivity() {
return destinationActivity;
}
public void setDestinationActivity(String destinationActivity) {
this.destinationActivity = destinationActivity;
}
public String getCreateTime() {
return createTime;
}
public void setCreateTime(String createTime) {
this.createTime = createTime;
}
public String getUpdateTime() {
return updateTime;
}
public void setUpdateTime(String updateTime) {
this.updateTime = updateTime;
}
}
public static class WorkCompletedWo extends GsonPropertyObject {
private String id;
private String job;
private String title;
private String startTime;
private String startTimeMonth;
private String creatorPerson;
private String creatorIdentity;
private String creatorUnit;
private String application;
private String applicationName;
private String applicationAlias;
private String process;
private String processName;
private String processAlias;
private String serial;
private String form;
private String createTime;
private String updateTime;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getJob() {
return job;
}
public void setJob(String job) {
this.job = job;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getStartTime() {
return startTime;
}
public void setStartTime(String startTime) {
this.startTime = startTime;
}
public String getStartTimeMonth() {
return startTimeMonth;
}
public void setStartTimeMonth(String startTimeMonth) {
this.startTimeMonth = startTimeMonth;
}
public String getCreatorPerson() {
return creatorPerson;
}
public void setCreatorPerson(String creatorPerson) {
this.creatorPerson = creatorPerson;
}
public String getCreatorIdentity() {
return creatorIdentity;
}
public void setCreatorIdentity(String creatorIdentity) {
this.creatorIdentity = creatorIdentity;
}
public String getCreatorUnit() {
return creatorUnit;
}
public void setCreatorUnit(String creatorUnit) {
this.creatorUnit = creatorUnit;
}
public String getApplication() {
return application;
}
public void setApplication(String application) {
this.application = application;
}
public String getApplicationName() {
return applicationName;
}
public void setApplicationName(String applicationName) {
this.applicationName = applicationName;
}
public String getApplicationAlias() {
return applicationAlias;
}
public void setApplicationAlias(String applicationAlias) {
this.applicationAlias = applicationAlias;
}
public String getProcess() {
return process;
}
public void setProcess(String process) {
this.process = process;
}
public String getProcessName() {
return processName;
}
public void setProcessName(String processName) {
this.processName = processName;
}
public String getProcessAlias() {
return processAlias;
}
public void setProcessAlias(String processAlias) {
this.processAlias = processAlias;
}
public String getSerial() {
return serial;
}
public void setSerial(String serial) {
this.serial = serial;
}
public String getForm() {
return form;
}
public void setForm(String form) {
this.form = form;
}
public String getCreateTime() {
return createTime;
}
public void setCreateTime(String createTime) {
this.createTime = createTime;
}
public String getUpdateTime() {
return updateTime;
}
public void setUpdateTime(String updateTime) {
this.updateTime = updateTime;
}
}
}
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.entity.JpaObject;
import com.x.base.core.project.Application;
import com.x.base.core.project.bean.WrapCopier;
import com.x.base.core.project.bean.WrapCopierFactory;
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.logger.Logger;
import com.x.base.core.project.logger.LoggerFactory;
import com.x.base.core.project.x_processplatform_assemble_surface;
import com.x.message.assemble.communicate.Business;
import com.x.message.assemble.communicate.ThisApplication;
import com.x.message.core.entity.IMConversation;
import org.apache.commons.lang3.StringUtils;
import java.util.List;
/**
* Created by fancyLou on 2022/3/7.
* Copyright © 2022 O2. All rights reserved.
*/
public class ActionConversationCreateByBusiness extends BaseAction {
private static Logger logger = LoggerFactory.getLogger(ActionConversationCreateByBusiness.class);
ActionResult<List<Wo>> execute(EffectivePerson effectivePerson, String businessId, String businessType) throws Exception {
ActionResult<List<Wo>> result = new ActionResult<>();
if (StringUtils.isEmpty(businessId)) {
throw new ExceptionEmptyId();
}
if (StringUtils.isEmpty(businessType) || !(businessType.equals(IMConversation.CONVERSATION_BUSINESS_TYPE_PROCESS) || businessType.equals(IMConversation.CONVERSATION_BUSINESS_TYPE_CMS))) {
throw new ExceptionEmptyBusinessType();
}
try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
Business business = new Business(emc);
List<IMConversation> list = business.imConversationFactory().listConversationWithPersonAndBusinessId(effectivePerson.getDistinguishedName(), businessId);
if (list != null && !list.isEmpty()) {
// 存在 返回结果
List<Wo> wos = Wo.copier.copy(list);
result.setData(wos);
} else {
// 不存在 创建
if (businessType.equals(IMConversation.CONVERSATION_BUSINESS_TYPE_PROCESS)) { //流程
}
}
}
return result;
}
public static class Wo extends IMConversation {
private static final long serialVersionUID = 5379640808709337246L;
static WrapCopier<IMConversation, Wo> copier = WrapCopierFactory.wo(IMConversation.class, Wo.class, null,
JpaObject.FieldsInvisible);
}
}
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.entity.JpaObject;
import com.x.base.core.project.bean.WrapCopier;
import com.x.base.core.project.bean.WrapCopierFactory;
import com.x.base.core.project.http.ActionResult;
import com.x.base.core.project.http.EffectivePerson;
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 org.apache.commons.lang3.StringUtils;
import java.util.ArrayList;
import java.util.List;
/**
* Created by fancyLou on 2022/3/8.
* Copyright © 2022 O2. All rights reserved.
*/
public class ActionConversationFindByBusinessId extends BaseAction {
private static Logger logger = LoggerFactory.getLogger(ActionConversationFindByBusinessId.class);
ActionResult<List<Wo>> execute(EffectivePerson effectivePerson, String businessId) throws Exception {
ActionResult<List<Wo>> result = new ActionResult<>();
if (StringUtils.isEmpty(businessId)) {
throw new ExceptionEmptyId();
}
try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
Business business = new Business(emc);
List<IMConversation> list = business.imConversationFactory().listConversationWithPersonAndBusinessId(effectivePerson.getDistinguishedName(), businessId);
if (list != null && !list.isEmpty()) {
// 存在 返回结果
List<Wo> wos = Wo.copier.copy(list);
result.setData(wos);
}else {
result.setData(new ArrayList<>());
}
}
return result;
}
public static class Wo extends IMConversation {
private static final long serialVersionUID = -3327091155757964236L;
static WrapCopier<IMConversation, Wo> copier = WrapCopierFactory.wo(IMConversation.class, Wo.class, null,
JpaObject.FieldsInvisible);
}
}
package com.x.message.assemble.communicate.jaxrs.im;
import com.x.base.core.project.exception.PromptException;
class ExceptionEmptyBusinessObject extends PromptException {
private static final long serialVersionUID = 1486583753209029281L;
ExceptionEmptyBusinessObject(String businessId) {
super("无法查询到对应的业务对象!businessId: " + businessId);
}
}
package com.x.message.assemble.communicate.jaxrs.im;
import com.x.base.core.project.exception.PromptException;
class ExceptionEmptyBusinessType extends PromptException {
private static final long serialVersionUID = 4132300948670472899L;
ExceptionEmptyBusinessType() {
super("businessType 为空或内容错误!");
}
}
......@@ -129,6 +129,26 @@ public class ImAction extends StandardJaxrsAction {
asyncResponse.resume(ResponseFactory.getEntityTagActionResultResponse(request, result));
}
@JaxrsMethodDescribe(value = "根据业务id查询会话,当前用户在会话中.", action = ActionConversationFindByBusinessId.class)
@GET
@Path("conversation/business/{businessId}")
@Produces(HttpMediaType.APPLICATION_JSON_UTF_8)
@Consumes(MediaType.APPLICATION_JSON)
public void conversationFindByBusinessId(@Suspended final AsyncResponse asyncResponse, @Context HttpServletRequest request,
@JaxrsParameterDescribe("业务id") @PathParam("businessId") String businessId) {
ActionResult<List<ActionConversationFindByBusinessId.Wo>> result = new ActionResult<>();
EffectivePerson effectivePerson = this.effectivePerson(request);
try {
result = new ActionConversationFindByBusinessId().execute( effectivePerson, businessId );
} catch (Exception e) {
logger.error(e, effectivePerson, request, null);
result.error(e);
}
asyncResponse.resume(ResponseFactory.getEntityTagActionResultResponse(request, result));
}
//conversation/{id}/read 阅读消息 PUT
@JaxrsMethodDescribe(value = "会话阅读消息.", action = ActionConversationRead.class)
......
......@@ -16,6 +16,9 @@ import java.util.Date;
import java.util.List;
/**
* 聊天 会话对象
*/
@Entity
@ContainerEntity(dumpSize = 1000, type = ContainerEntity.Type.content, reference = ContainerEntity.Reference.strong)
@Table(name = PersistenceProperties.IMConversation.table, uniqueConstraints = {
......@@ -98,6 +101,56 @@ public class IMConversation extends SliceJpaObject {
private Date lastMessageTime;
public static final String businessId_FIELDNAME = "businessId";
@FieldDescribe("业务对象Id. (流程的jobId)")
@Column(length = length_128B, name = ColumnNamePrefix + businessId_FIELDNAME)
@CheckPersist(allowEmpty = true)
private String businessId;
public static final String businessBody_FIELDNAME = "businessBody";
@FieldDescribe("业务对象内容.")
@Lob
@Basic(fetch = FetchType.EAGER)
@Column(length = length_10M, name = ColumnNamePrefix + businessBody_FIELDNAME)
private String businessBody;
//业务类型 process 流程
public static final String CONVERSATION_BUSINESS_TYPE_PROCESS = "process";
public static final String CONVERSATION_BUSINESS_TYPE_CMS = "cms";
public static final String businessType_FIELDNAME = "businessType";
@FieldDescribe("业务类型. process")
@Column(length = length_16B, name = ColumnNamePrefix + businessType_FIELDNAME)
@CheckPersist(allowEmpty = true)
private String businessType;
public String getBusinessId() {
return businessId;
}
public void setBusinessId(String businessId) {
this.businessId = businessId;
}
public String getBusinessBody() {
return businessBody;
}
public void setBusinessBody(String businessBody) {
this.businessBody = businessBody;
}
public String getBusinessType() {
return businessType;
}
public void setBusinessType(String businessType) {
this.businessType = businessType;
}
public String getType() {
return type;
}
......
......@@ -16,6 +16,9 @@ import java.util.Date;
import java.util.List;
/**
* 会话的扩展对象 每个人一个,保存当前用户的会话扩展属性
*/
@Entity
@ContainerEntity(dumpSize = 1000, type = ContainerEntity.Type.content, reference = ContainerEntity.Reference.strong)
@Table(name = PersistenceProperties.IMConversationExt.table, uniqueConstraints = {
......
......@@ -9,7 +9,9 @@ import org.apache.openjpa.persistence.jdbc.Index;
import javax.persistence.*;
/**
* 会话消息
*/
@Entity
@ContainerEntity(dumpSize = 1000, type = ContainerEntity.Type.content, reference = ContainerEntity.Reference.strong)
@Table(name = PersistenceProperties.IMMsg.table, uniqueConstraints = {
......
......@@ -2930,6 +2930,20 @@ MWF.xScript.Environment = function(ev){
}
},
/**创建关联当前工作的聊天群。<b>(仅流程表单中可用)</b><br/>
* 根据当前工作的关联人员创建聊天群。<br/>
* @method startIM
* @static
* @param {String} [jobId] - 当前工作的jobId<br/>
*
* @example
//带参数,启动创建界面
this.form.startIM("jobId");
*/
"startIM": function(jobId){
_form.openIMChatStarter(jobId);
},
/**弹出一个确认框,带确认和关闭按钮
* @method confirm
* @static
......
<!-- title -->
<div class="chat-title" data-o2-element="chatTitleNode">
<span>{{$.convName}}</span>
<div class="o2_im_chat_content_title_more" data-o2-element="chatTitleMoreBtnNode"></div>
<div class="o2_im_chat_content_title_business_icon" data-o2-element="chatTitleBusinessBtnNode"></div>
<div class="o2_im_chat_content_title_menu" data-o2-element="chatTitleMoreMenuNode">
<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">
......@@ -9,6 +11,7 @@
<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>
<!-- 业务对象的应用icon 流程默认图标"../x_component_process_ApplicationExplorer/$Main/default/icon/application.png" -->
</div>
<!-- 聊天内容 -->
<div class="chat-content" data-o2-element="chatContentNode">
......
<!-- <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>选择</title>
<style>
html,
body {
width: 100%;
height: 100%;
overflow: auto;
position: relative;
margin: 0;
padding: 0;
}
</style>
<link rel="stylesheet" href="./style.css">
</head>
<body> -->
<div class="person-outer" data-o2-element="businessWorkChooseDialogNode">
<div class="person-mask"></div>
<div class="person-box">
<div class="person-box-header">
<div class="person-box-header-title">
<span>{{$.lp.chooseBusinessWorkTitle}}</span>
</div>
<div class="person-box-header-close" data-o2-element="businessWorkChooseCloseBtnNode">
<span>X</span>
</div>
</div>
<div class="person-box-body" data-o2-element="businessWorkListNode">
</div>
</div>
</div>
<!--
</body>
</html> -->
\ No newline at end of file
<!-- <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>选择</title>
<style>
html,
body {
width: 100%;
height: 100%;
overflow: auto;
position: relative;
margin: 0;
padding: 0;
}
</style>
<link rel="stylesheet" href="./style.css">
</head>
<body> -->
<div class="conversation-outer" data-o2-element="conversationChooseDialogNode">
<div class="conversation-mask"></div>
<div class="conversation-box">
<div class="conversation-box-header">
<div class="conversation-box-header-title">
<span>{{$.lp.chooseConversation}}</span>
</div>
<div class="conversation-box-header-close" data-o2-element="conversationChooseCloseNode">
<span>X</span>
</div>
</div>
<div class="conversation-box-body">
<div class="conversation-box-desc">{{$.lp.chooseConversationExistConversation}}</div>
<div class="conversation-box-body-list" data-o2-element="conversationChooseListNode">
<!-- <div class="conversation-item">群聊1111 | <span style="color: #4A90E2;">打开</span></div>
<div class="conversation-item">楼国栋、灵灵了、的丁大... | <span style="color: #4A90E2;">打开</span></div> -->
</div>
</div>
<div class="conversation-box-footer">
<div class="conversation-box-footer-btn" data-o2-element="conversationCreateNewNode">{{$.lp.chooseConversationCreateNew}}</div>
</div>
</div>
</div>
<!-- </body>
</html> -->
\ No newline at end of file
<!-- <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>选择</title>
<style>
html,
body {
width: 100%;
height: 100%;
overflow: auto;
position: relative;
margin: 0;
padding: 0;
}
</style>
<link rel="stylesheet" href="./style.css">
</head>
<body> -->
<div class="person-outer" data-o2-element="personChooseDialogNode">
<div class="person-mask"></div>
<div class="person-box">
<div class="person-box-header">
<div class="person-box-header-title">
<span>{{$.lp.choosePerson}}</span>
</div>
<div class="person-box-header-close" data-o2-element="personChooseCloseBtnNode">
<span>X</span>
</div>
</div>
<div class="person-box-body">
<div class="person-box-body-list" data-o2-element="personListNode">
<!-- <div class="person-tag">了国栋</div>
<div class="person-tag">国栋</div>
<div class="person-tag">了国栋</div>
<div class="person-tag">了国栋</div>
<div class="person-tag person-tag-active">了国栋</div>
<div class="person-tag person-tag-active">国栋</div>
<div class="person-tag person-tag-active">了国栋</div>
<div class="person-tag person-tag-active">国栋</div>
<div class="person-tag person-tag-active">了国栋</div>
<div class="person-tag person-tag-active">了国栋</div>
<div class="person-tag person-tag-active">国栋</div>
<div class="person-tag person-tag-active">了国栋</div>
<div class="person-tag">了国栋</div>
<div class="person-tag">了国栋</div>
<div class="person-tag person-tag-active">国栋</div>
<div class="person-tag person-tag-active">了国栋</div> -->
</div>
</div>
<div class="person-box-footer">
<div class="person-box-footer-btn" data-o2-element="personChooseCreateNode">{{$.lp.choosePersonCreate}}</div>
</div>
</div>
</div>
<!--
</body>
</html> -->
\ No newline at end of file
<div class="o2_im_out" data-o2-element="o2ImMainNode">
<div class="o2_im_chat_list">
<div class="o2_im_chat_list" data-o2-element="o2ConversationListNode">
<!--top-->
<div class="o2_im_chat_list_top">
<div class="add" data-o2-element="o2ImConvCreateNode" data-o2-events="click:tapCreateSingleConv">
......
MWF.require("MWF.widget.UUID", null, false);
MWF.xDesktop.requireApp("Template", "MForm", null, false);
MWF.xDesktop.requireApp("Template", "MPopupForm", null, false);
MWF.xApplication.IMV2 = MWF.xApplication.IMV2 || {};
MWF.require("MWF.widget.Mask", null, false);
MWF.xDesktop.requireApp("IMV2", "lp."+o2.language, null, false);
MWF.xApplication.IMV2.Starter = new Class({
Extends: MWF.widget.Common,
Implements: [Options, Events],
options: {
"style": "default",
"businessType" : "none", // 业务类型 :none, process, cms 。启动聊天 是否带业务类型
"businessId": null, // 业务ID 新创建为空
"includePersonList": [], // 在规定范围内的人员进行选择, 如果为空,则不限制
"conversationId": null, // 传入的会话id, 新创建为空
"mode": "default" // 展现模式:default onlyChat 。 onlyChat的模式需要传入conversationId 会打开这个会话的聊天窗口并隐藏左边的会话列表
},
initialize: function(data, app, options){
console.log("init IMV2.Starter " );
this.setOptions(options);
this.path = "../x_component_IMV2/$Main/";
MWF.xDesktop.requireApp("IMV2", "lp."+o2.language, null, false);
this.lp = MWF.xApplication.IMV2.LP;
this.data = data;
this.app = app;
},
load: function(){
console.log("init IMV2.load " );
debugger;
// 打开聊天会话
if (this.options.conversationId && this.options.conversationId !== "") {
this.openConversationWindow(this.options.conversationId);
} else {
// 创建聊天
var me = layout.session.user.distinguishedName;
var exclude = [];
if (me) {
exclude = [me];
}
// 默认创建聊天
if ( !(this.options.businessType) || this.options.businessType === "none" || !(this.options.businessId) || this.options.businessId === "" ) {
var form = new MWF.xApplication.IMV2.Starter.CreateConversationForm(this);
form.create()
} else if (this.options.businessType === "process") {
if (this.options.businessId) {
//TODO 如果已经存在是否考虑可创建多个,那就需要提示创建新的还是打开老的
console.log("根据流程的job id查询,会话是否存在,如果存在,则打开,如果不存在,则创建。jobId: " + this.options.businessId);
this.findConversationByBusinessId();
} else {
this.app.notice(this.lp.msgNoBusinessId, "error");
}
//打开工作 o2.env.form.openJob
} else {
this.app.notice(this.lp.msgNotSupport, "error");
}
}
},
// 打开会话聊天窗口
openConversationWindow: function(conversationId) {
var options = {
conversationId: conversationId,
mode: this.options.mode || "default"
}
layout.openApplication(null, "IMV2", options);
},
// 创建会话
newConversation: function(personList) {
console.log("newConversation", personList);
var cType = "single"; // cType 会话类型 "single" "group"
if (personList.length > 1) {
cType = "group"
}
var conv = {
type: cType,
personList: personList,
};
if (this.options.businessId) {
conv.businessId = this.options.businessId;
conv.businessType = this.options.businessType;
}
o2.Actions.load("x_message_assemble_communicate").ImAction.create(conv, function (json) {
var newConv = json.data;
if (this.app.refreshAll) this.app.refreshAll();
this.openConversationWindow(newConv.id);
}.bind(this), function (error) {
console.log(error);
this.app.notice(error, "error");
if (this.app.refreshAll) this.app.refreshAll();
}.bind(this))
},
// 根据流程的job id查询,会话是否存在
findConversationByBusinessId: function() {
o2.Actions.load("x_message_assemble_communicate").ImAction.conversationFindByBusinessId(this.options.businessId, function(json){
if (json.data && json.data.length > 0) {
this.showChooseConversationDialog(json.data);
} else {
if (this.options.businessType === "process") {
this.getProcessReviewByJobId();
}
}
}.bind(this), function (error) {
console.log(error);
if (this.options.businessType === "process") {
this.getProcessReviewByJobId();
}
}.bind(this));
},
// 有存在的会话 展现可以点击打开会话聊天
showChooseConversationDialog: function(conversationList) {
if (conversationList && conversationList.length > 0) {
var cssPath = this.path + "default/style.css";
var chooseConversationHtmlPath = this.path + "default/chooseConversation.html";
this.app.content.loadAll({
"css": [cssPath],
"html": chooseConversationHtmlPath,
}, { "bind": { "lp": this.lp, "data": {} }, "module": this }, function(){
// 会话列表
for (let index = 0; index < conversationList.length; index++) {
const conv = conversationList[index];
// <div class="conversation-item">群聊1111 | <span style="color: #4A90E2;">打开</span></div>
var conversationItem = new Element("div", {"class": "conversation-item"}).inject(this.conversationChooseListNode);
new Element("span", {"text": ""+conv.title+""}).inject(conversationItem);
new Element("span", {"text": "打开", "style": "color: #4A90E2;"}).inject(conversationItem);
// conversationItem.set("text", conv.title + " | <span style=\"color: #4A90E2;\">打开</span>");
conversationItem.store("conversation", conv);
conversationItem.addEvents({
"click": function(e){
debugger;
var myConv = null;
if (e.target.get("tag") === "span") {
myConv = e.target.parentNode.retrieve("conversation");
} else {
myConv = e.target.retrieve("conversation");
}
if (myConv) {
this.openConversationWindow(myConv.id);
this.closeChooseConversationDialog();
}
}.bind(this)
});
}
// 关闭按钮
this.conversationChooseCloseNode.addEvents({
"click": function(e){
this.closeChooseConversationDialog();
}.bind(this)
});
// 新建聊天按钮
this.conversationCreateNewNode.addEvents({
"click": function(e){
this.closeChooseConversationDialog();
if (this.options.businessType === "process") {
this.getProcessReviewByJobId();
}
}.bind(this)
})
}.bind(this));
}
},
// 关闭会话选择窗口
closeChooseConversationDialog: function() {
if (this.conversationChooseDialogNode) {
this.conversationChooseDialogNode.destroy();
this.conversationChooseDialogNode = null;
}
if (this.app.refreshAll) this.app.refreshAll();
},
// 显示创建会话的表单,上面列示出人员列表,可以选择人员
showCreateConversationWithPersonsDialog: function(personList) {
if (personList && personList.length > 0) {
var cssPath = this.path + "default/style.css";
var choosePersonHtmlPath = this.path + "default/choosePerson.html";
this.app.content.loadAll({
"css": [cssPath],
"html": choosePersonHtmlPath,
}, { "bind": { "lp": this.lp, "data": {} }, "module": this }, function(){
//载入完成后的回调
// 人员列表
for (let index = 0; index < personList.length; index++) {
const person = personList[index];
// <div class="person-tag person-tag-active">了国栋</div>
var personTag = new Element("div", {"class": "person-tag person-tag-active"}).inject(this.personListNode);
var name = person;
if (person.indexOf("@") != -1) {
name = name.substring(0, person.indexOf("@"));
}
personTag.set("text", name);
personTag.store("person", person);
personTag.addEvents({
"click": function(e){
if (e.target.get("class") == "person-tag person-tag-active") {
e.target.set("class", "person-tag");
} else {
e.target.set("class", "person-tag person-tag-active");
}
}
});
}
// 创建会话按钮
this.personChooseCreateNode.addEvents({
"click": function(e){
var personList = []
this.personListNode.getChildren().each(function(tag){
if (tag.get("class") == "person-tag person-tag-active") {
personList.push(tag.retrieve("person"));
}
});
if (personList.length > 0) {
this.newConversation(personList);
this.closeChoosePersonDialog();
} else {
this.app.notice(this.lp.msgNeedChoosePerson, "error");
}
}.bind(this)
});
// 关闭按钮
this.personChooseCloseBtnNode.addEvents({
"click": function(e){
this.closeChoosePersonDialog();
}.bind(this)
})
}.bind(this));
} else {
this.app.notice(this.lp.msgNoBusinessPerson, "error");
}
},
// 关闭人员选择
closeChoosePersonDialog: function(){
if (this.personChooseDialogNode) {
this.personChooseDialogNode.destroy();
this.personChooseDialogNode = null;
}
if (this.app.refreshAll) this.app.refreshAll();
},
// 根据jobid查询review,获取所有相关的人员
getProcessReviewByJobId: function() {
o2.Actions.load("x_processplatform_assemble_surface").ReviewAction.listWithJob(this.options.businessId, function(json){
if (json.data && json.data.length > 0) {
var personList = [];
json.data.each(function(review){
if (review.person && review.person !== layout.session.user.distinguishedName) {
personList.push(review.person);
}
});
this.showCreateConversationWithPersonsDialog(personList);
} else {
this.showCreateConversationWithPersonsDialog([]);
}
}.bind(this), function(error){
console.log(error);
this.showCreateConversationWithPersonsDialog([]);
}.bind(this));
}
});
//创建聊天 弹出窗表单
MWF.xApplication.IMV2.Starter.CreateConversationForm = new Class({
Extends: MPopupForm,
Implements: [Options, Events],
options: {
"style": "minder",
"width": 700,
"height": "200",
"hasTop": true,
"hasIcon": false,
"draggable": true,
"title": MWF.xApplication.IMV2.LP.createConversation,
"includePersonList": [], // 在规定范围内的人员进行选择, 如果为空,则不限制
"personSelected": []
},
_createTableContent: function () {
var html = "<table width='100%' bordr='0' cellpadding='7' cellspacing='0' styles='formTable' style='margin-top: 20px; '>" +
"<tr><td styles='formTableTitle' lable='person' width='25%'></td>" +
" <td styles='formTableValue14' item='person' colspan='3'></td></tr>" +
"</table>";
this.formTableArea.set("html", html);
var me = layout.session.user.distinguishedName;
var exclude = [];
if (me) {
exclude = [me];
}
this.form = new MForm(this.formTableArea, this.data || {}, {
isEdited: true,
style: "minder",
hasColon: true,
itemTemplate: {
person: {
text: MWF.xApplication.IMV2.LP.selectPerson,
type: "org",
orgType: "person",
notEmpty: true,
exclude: exclude,
count: 0, // 可选人数 0是不限制人数
value: this.options["personSelected"] },
}
}, this.app);
this.form.load();
},
_createBottomContent: function () {
if (this.isNew || this.isEdited) {
this.okActionNode = new Element("button.inputOkButton", {
"styles": this.css.inputOkButton,
"text": MWF.xApplication.IMV2.LP.ok
}).inject(this.formBottomNode);
this.okActionNode.addEvent("click", function (e) {
this.save(e);
}.bind(this));
}
this.cancelActionNode = new Element("button.inputCancelButton", {
"styles": (this.isEdited || this.isNew || this.getEditPermission()) ? this.css.inputCancelButton : this.css.inputCancelButton_long,
"text": MWF.xApplication.IMV2.LP.close
}).inject(this.formBottomNode);
this.cancelActionNode.addEvent("click", function (e) {
this.close(e);
}.bind(this));
},
save: function () {
var data = this.form.getResult(true, null, true, false, true);
if (data) {
this.explorer.newConversation(data.person);
this.close();
}
}
});
......@@ -3,6 +3,7 @@ MWF.xApplication.IMV2.LP = {
"modifyMember": "Members",
"noMessage": "No Message!",
"createConversation": "Create a chat session",
"createSingle": "Single Chat",
"createGroup": "Group Chat",
......@@ -23,12 +24,28 @@ MWF.xApplication.IMV2.LP = {
"alert": "Tips",
"setting": "Setting",
"chooseConversation":"Select Conversation",
"chooseConversationExistConversation":"Currently there is an associated chat conversation:",
"chooseConversationCreateNew":"Create a new chat",
"choosePerson":"Select personnel",
"choosePersonCreate":"Create chat",
"chooseBusinessWorkTitle":"Associated work",
"open": "open",
"noTitle": "Untitled",
"modifyGroupName": "Modify Name",
"groupName": "Name",
"clearAllMsg": "Clear chat history",
"msgMenuItemRevokeMemberMsg": "Revoke member message",
"msgMenuItemRevokeMsg": "Revoke",
"msgLoadNoMoreData": "No more data!",
"msgNoBusinessId": "No business ID!",
"msgNoBusinessPerson": "No business related personnel found, unable to create chat!",
"msgNotSupport": "Temporarily not supported!",
"msgNeedChoosePerson": "Please select at least one person!",
"settingsClearMsg": "Enable Clearing msg: ",
......
......@@ -3,6 +3,7 @@ MWF.xApplication.IMV2.LP = {
"modifyMember": "修改成员",
"noMessage": "没有消息内容!",
"createConversation": "创建聊天会话",
"createSingle": "创建单聊",
"createGroup": "创建群聊",
......@@ -23,12 +24,28 @@ MWF.xApplication.IMV2.LP = {
"alert": "提示",
"setting": "设置",
"chooseConversation":"选择会话",
"chooseConversationExistConversation":"当前已存在关联的聊天会话:",
"chooseConversationCreateNew":"创建新的聊天",
"choosePerson":"选择人员",
"choosePersonCreate":"创建聊天",
"chooseBusinessWorkTitle":"关联工作",
"open": "打开",
"noTitle": "无标题",
"modifyGroupName": "修改群名",
"groupName": "群名",
"clearAllMsg": "清空聊天记录",
"msgMenuItemRevokeMemberMsg": "撤回成员消息",
"msgMenuItemRevokeMsg": "撤回",
"msgLoadNoMoreData": "没有更多数据了!",
"msgNoBusinessId": "没有业务ID!",
"msgNoBusinessPerson": "没有查询到业务相关的人员,无法创建聊天!",
"msgNotSupport": "暂不支持!",
"msgNeedChoosePerson": "请选择至少一个人员!",
"settingsClearMsg": "是否开启聊天消息清除功能:",
......
......@@ -4636,6 +4636,18 @@ debugger;
}
}.bind(this))
},
// 打开工作关联聊天
openIMChatStarter: function(jobId) {
MWF.xDesktop.requireApp("IMV2", "Starter", function () {
var starter = new MWF.xApplication.IMV2.Starter({}, this.app, {
"businessId":jobId,
"businessType": "process"
});
starter.load();
}.bind(this));
},
//移动端页面 工作处理完成后
finishOnMobile: function () {
var _self = this;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册