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 81ded7918beba5db38c18c009cceb65471e7856a..a847ae52abb8ad6c9b9e6cd80fc2cb967c12591a 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 @@ -23,6 +23,25 @@ public class IMConversationFactory extends AbstractFactory { super(business); } + + /** + * 根据 businessId 获取会话列表 并且成员包含person + * @param person + * @param businessId + * @return + * @throws Exception + */ + public List listConversationWithPersonAndBusinessId(String person, String businessId) throws Exception { + EntityManager em = this.entityManagerContainer().get(IMConversation.class); + CriteriaBuilder cb = em.getCriteriaBuilder(); + CriteriaQuery cq = cb.createQuery(IMConversation.class); + Root 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 diff --git a/o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/jaxrs/im/ActionConversationCreate.java b/o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/jaxrs/im/ActionConversationCreate.java index 04f9eaef56cd114b008ec2ce1b2b154ea465a326..120299994411ba8f2b27a3c1544136917ce1096a 100644 --- a/o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/jaxrs/im/ActionConversationCreate.java +++ b/o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/jaxrs/im/ActionConversationCreate.java @@ -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 workList; + private List workCompletedList; + + public List getWorkList() { + return workList; + } + + public void setWorkList(List workList) { + this.workList = workList; + } + + public List getWorkCompletedList() { + return workCompletedList; + } + + public void setWorkCompletedList(List 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; + } + } } diff --git a/o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/jaxrs/im/ActionConversationCreateByBusiness.java b/o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/jaxrs/im/ActionConversationCreateByBusiness.java new file mode 100644 index 0000000000000000000000000000000000000000..eb34679e7f1f4bad302cdef9d1bedb798f6cb9b3 --- /dev/null +++ b/o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/jaxrs/im/ActionConversationCreateByBusiness.java @@ -0,0 +1,66 @@ +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> execute(EffectivePerson effectivePerson, String businessId, String businessType) throws Exception { + ActionResult> 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 list = business.imConversationFactory().listConversationWithPersonAndBusinessId(effectivePerson.getDistinguishedName(), businessId); + if (list != null && !list.isEmpty()) { + // 存在 返回结果 + List 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 copier = WrapCopierFactory.wo(IMConversation.class, Wo.class, null, + JpaObject.FieldsInvisible); + } + + +} diff --git a/o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/jaxrs/im/ActionConversationFindByBusinessId.java b/o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/jaxrs/im/ActionConversationFindByBusinessId.java new file mode 100644 index 0000000000000000000000000000000000000000..6be55f8d5d62004012f60edd292c2ea8216bca4e --- /dev/null +++ b/o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/jaxrs/im/ActionConversationFindByBusinessId.java @@ -0,0 +1,55 @@ +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> execute(EffectivePerson effectivePerson, String businessId) throws Exception { + ActionResult> result = new ActionResult<>(); + if (StringUtils.isEmpty(businessId)) { + throw new ExceptionEmptyId(); + } + try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) { + Business business = new Business(emc); + List list = business.imConversationFactory().listConversationWithPersonAndBusinessId(effectivePerson.getDistinguishedName(), businessId); + if (list != null && !list.isEmpty()) { + // 存在 返回结果 + List 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 copier = WrapCopierFactory.wo(IMConversation.class, Wo.class, null, + JpaObject.FieldsInvisible); + } +} diff --git a/o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/jaxrs/im/ExceptionEmptyBusinessObject.java b/o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/jaxrs/im/ExceptionEmptyBusinessObject.java new file mode 100644 index 0000000000000000000000000000000000000000..46b8f1e3fa20e788a34d2b33a910efed4154c082 --- /dev/null +++ b/o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/jaxrs/im/ExceptionEmptyBusinessObject.java @@ -0,0 +1,15 @@ +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); + } + + +} diff --git a/o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/jaxrs/im/ExceptionEmptyBusinessType.java b/o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/jaxrs/im/ExceptionEmptyBusinessType.java new file mode 100644 index 0000000000000000000000000000000000000000..df30b01d3a283dd0072ac019187d6fdb8b2a90bf --- /dev/null +++ b/o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/jaxrs/im/ExceptionEmptyBusinessType.java @@ -0,0 +1,14 @@ +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 为空或内容错误!"); + } + + +} 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 05005acaef5fe5d3b5797180440f7d14905946e9..d7de9ca5e051ae2f752f2115d0603757a10f5235 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 @@ -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> 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) diff --git a/o2server/x_message_core_entity/src/main/java/com/x/message/core/entity/IMConversation.java b/o2server/x_message_core_entity/src/main/java/com/x/message/core/entity/IMConversation.java index f6549fd847f45eb0e9c0a411b00918b600647443..5bd1026f1b00d3024d69d604de245408aba01d97 100644 --- a/o2server/x_message_core_entity/src/main/java/com/x/message/core/entity/IMConversation.java +++ b/o2server/x_message_core_entity/src/main/java/com/x/message/core/entity/IMConversation.java @@ -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; } diff --git a/o2server/x_message_core_entity/src/main/java/com/x/message/core/entity/IMConversationExt.java b/o2server/x_message_core_entity/src/main/java/com/x/message/core/entity/IMConversationExt.java index fa2d925f8276c1cff715dc65ba9885b01ba62c5f..70e13f1050cd88cac17ed3ec1a1c55f04f35d79a 100644 --- a/o2server/x_message_core_entity/src/main/java/com/x/message/core/entity/IMConversationExt.java +++ b/o2server/x_message_core_entity/src/main/java/com/x/message/core/entity/IMConversationExt.java @@ -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 = { diff --git a/o2server/x_message_core_entity/src/main/java/com/x/message/core/entity/IMMsg.java b/o2server/x_message_core_entity/src/main/java/com/x/message/core/entity/IMMsg.java index f38b687d1f00e727ebfee1096f5b6c933669dc28..b32a5136c88be21f9ddbffb2be34564bbfaaa358 100644 --- a/o2server/x_message_core_entity/src/main/java/com/x/message/core/entity/IMMsg.java +++ b/o2server/x_message_core_entity/src/main/java/com/x/message/core/entity/IMMsg.java @@ -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 = { diff --git a/o2web/source/o2_core/o2/xScript/Environment.js b/o2web/source/o2_core/o2/xScript/Environment.js index 3876032d1cb065249f7016269b2202a33d39ea98..7646a743f8396353452a82bbda9d38995e14f29e 100644 --- a/o2web/source/o2_core/o2/xScript/Environment.js +++ b/o2web/source/o2_core/o2/xScript/Environment.js @@ -2930,6 +2930,20 @@ MWF.xScript.Environment = function(ev){ } }, + /**创建关联当前工作的聊天群。(仅流程表单中可用)
+ * 根据当前工作的关联人员创建聊天群。
+ * @method startIM + * @static + * @param {String} [jobId] - 当前工作的jobId
+ * + * @example + //带参数,启动创建界面 + this.form.startIM("jobId"); + */ + "startIM": function(jobId){ + _form.openIMChatStarter(jobId); + }, + /**弹出一个确认框,带确认和关闭按钮 * @method confirm * @static diff --git a/o2web/source/x_component_IMV2/$Main/default/chat.html b/o2web/source/x_component_IMV2/$Main/default/chat.html index 86bd79f2aa521a3627a9ce553df9fb4219eecbc9..f3d21649dc9333d97fefa97b7c8b353199a7304c 100644 --- a/o2web/source/x_component_IMV2/$Main/default/chat.html +++ b/o2web/source/x_component_IMV2/$Main/default/chat.html @@ -1,7 +1,9 @@
{{$.convName}} +
+
{{$.lp.modifyGroupName}}
@@ -9,6 +11,7 @@
+
diff --git a/o2web/source/x_component_IMV2/$Main/default/chooseBusinessWork.html b/o2web/source/x_component_IMV2/$Main/default/chooseBusinessWork.html new file mode 100644 index 0000000000000000000000000000000000000000..cc6518849ebd5ebb6d7b384c697a7f68bebd7e44 --- /dev/null +++ b/o2web/source/x_component_IMV2/$Main/default/chooseBusinessWork.html @@ -0,0 +1,46 @@ + +
+
+
+
+
+ {{$.lp.chooseBusinessWorkTitle}} +
+
+ X +
+
+
+ +
+
+
+ + \ No newline at end of file diff --git a/o2web/source/x_component_IMV2/$Main/default/chooseConversation.html b/o2web/source/x_component_IMV2/$Main/default/chooseConversation.html new file mode 100644 index 0000000000000000000000000000000000000000..25a6d07b5a64972e351978b11466e692e9d46895 --- /dev/null +++ b/o2web/source/x_component_IMV2/$Main/default/chooseConversation.html @@ -0,0 +1,54 @@ + +
+
+
+
+
+ {{$.lp.chooseConversation}} +
+
+ X +
+
+
+
{{$.lp.chooseConversationExistConversation}}
+
+ +
+
+ + +
+
+ + + \ No newline at end of file diff --git a/o2web/source/x_component_IMV2/$Main/default/choosePerson.html b/o2web/source/x_component_IMV2/$Main/default/choosePerson.html new file mode 100644 index 0000000000000000000000000000000000000000..3f31bad1c5e177ca91e89505899638bf425b37ae --- /dev/null +++ b/o2web/source/x_component_IMV2/$Main/default/choosePerson.html @@ -0,0 +1,68 @@ + +
+
+
+
+
+ {{$.lp.choosePerson}} +
+
+ X +
+
+
+
+ + +
+
+ + +
+
+ + \ No newline at end of file diff --git a/o2web/source/x_component_IMV2/$Main/default/im.html b/o2web/source/x_component_IMV2/$Main/default/im.html index e215e03344e97187c9a04b53749e7ddcbddef85f..5c0b99b5eb58e3dad9a0c43acc8a8fdef09eb50a 100644 --- a/o2web/source/x_component_IMV2/$Main/default/im.html +++ b/o2web/source/x_component_IMV2/$Main/default/im.html @@ -1,5 +1,5 @@
-
+
diff --git a/o2web/source/x_component_IMV2/$Main/default/style.css b/o2web/source/x_component_IMV2/$Main/default/style.css index c9c18ff0a2c2cf687f5fbc7cab7f1f297d9419dc..4e6faf54197098ee6a51fe7ab94a1b51f2fa05b1 100644 --- a/o2web/source/x_component_IMV2/$Main/default/style.css +++ b/o2web/source/x_component_IMV2/$Main/default/style.css @@ -1,37 +1,37 @@ - .o2_im_out { - width: 100%; - height: 100%; - overflow: hidden; + width: 100%; + height: 100%; + overflow: hidden; } .o2_im_chat_list { - border-top: 1px solid rgb(255, 255, 255); - border-right: 1px solid rgb(221, 221, 221); - float: left; - width: 257px; - height: 100%; - display: flex; - display: -webkit-box; - display: -webkit-flex; - flex-direction: column; - -ms-flex-direction: column; + border-top: 1px solid rgb(255, 255, 255); + border-right: 1px solid rgb(221, 221, 221); + float: left; + width: 257px; + height: 100%; + display: flex; + display: -webkit-box; + display: -webkit-flex; + flex-direction: column; + -ms-flex-direction: column; } .o2_im_chat_list_top { - margin-bottom: 20px; - height: 40px; - background-color: rgb(248, 248, 248); - border-bottom: 1px solid rgb(204, 204, 204); + margin-bottom: 20px; + height: 40px; + background-color: rgb(248, 248, 248); + border-bottom: 1px solid rgb(204, 204, 204); } .o2_im_chat_list_top .add { - background: url(../x_component_IMV2/$Main/default/icons/add.png) left center no-repeat; - height: 40px; - cursor: pointer; - margin-left: 14px; - text-align: center; - line-height: 40px; - color: #848484; - padding-left: 24px; - float: left; + background: url(../x_component_IMV2/$Main/default/icons/add.png) left center + no-repeat; + height: 40px; + cursor: pointer; + margin-left: 14px; + text-align: center; + line-height: 40px; + color: #848484; + padding-left: 24px; + float: left; } .o2_im_chat_list_top .group { @@ -45,7 +45,8 @@ float: left; } .o2_im_chat_list_top .im_setting { - background: url(../x_component_IMV2/$Main/default/icons/icon_setting.png) no-repeat center; + background: url(../x_component_IMV2/$Main/default/icons/icon_setting.png) + no-repeat center; height: 40px; float: right; width: 40px; @@ -54,145 +55,146 @@ } .o2_im_chat_list_top .search_out { - margin-right: 40px; - height: 40px; + margin-right: 40px; + height: 40px; } .o2_im_chat_list_top .search_icon { - float: left; - width: 40px; - height: 40px; - background: url(../x_component_IMV2/$Main/default/icons/search.png) center center no-repeat; - cursor: pointer; + float: left; + width: 40px; + height: 40px; + background: url(../x_component_IMV2/$Main/default/icons/search.png) center + center no-repeat; + cursor: pointer; } .o2_im_chat_list_top .search_input_out { - margin-left: 40px; text-align: left; + margin-left: 40px; + text-align: left; } .o2_im_chat_list_top .search_input { - margin-top: 7px; - width: 96%; - height: 24px; - line-height: 24px; - border: 0px; - font-family: "Microsoft YaHei"; - font-size: 12px; - color: rgb(153, 153, 153); - background: transparent; - user-select: auto; + margin-top: 7px; + width: 96%; + height: 24px; + line-height: 24px; + border: 0px; + font-family: "Microsoft YaHei"; + font-size: 12px; + color: rgb(153, 153, 153); + background: transparent; + user-select: auto; } - .o2_im_chat_list_top .add_button { - height: 50px; - width: 160px; - color: rgb(51, 51, 51); - font-size: 16px; - line-height: 50px; - padding-left: 10px; - padding-right: 10px; - cursor: pointer; - margin: 0 auto; - border:1px solid rgb(204, 204, 204); + height: 50px; + width: 160px; + color: rgb(51, 51, 51); + font-size: 16px; + line-height: 50px; + padding-left: 10px; + padding-right: 10px; + cursor: pointer; + margin: 0 auto; + border: 1px solid rgb(204, 204, 204); } .o2_im_chat_list_top .add_button .icon { - height: 50px; - width: 30px; - float: left; - background: url(../x_component_IMV2/$Main/default/icons/icon_newapply.png) center center no-repeat; + height: 50px; + width: 30px; + float: left; + background: url(../x_component_IMV2/$Main/default/icons/icon_newapply.png) + center center no-repeat; } .o2_im_chat_list_top .add_button .text { - line-height: 50px; - height: 50px; - float: left; + line-height: 50px; + height: 50px; + float: left; } .o2_im_chat_list .item { - overflow: hidden; - height: 60px; - margin: 0px; + overflow: hidden; + height: 60px; + margin: 0px; } .o2_im_chat_list .item .base { - height: 60px; - cursor: pointer; + height: 60px; + cursor: pointer; } .o2_im_chat_list .item .normal { - background-color: rgb(253, 253, 253); + background-color: rgb(253, 253, 253); } .o2_im_chat_list .item .check { - background-color: rgb(228, 228, 228); + background-color: rgb(228, 228, 228); } .o2_im_chat_list .item .avatar { - background-position: center center; - background-repeat: no-repeat; - margin-left: 16px; - height: 48px; - width: 48px; - border-radius: 24px; - margin-top: 6px; - background-color: rgb(255, 255, 255); - float: left; + background-position: center center; + background-repeat: no-repeat; + margin-left: 16px; + height: 48px; + width: 48px; + border-radius: 24px; + margin-top: 6px; + background-color: rgb(255, 255, 255); + float: left; } .o2_im_chat_list .item .avatar .img { - width: 48px; - height: 48px; - border: 0px; - border-radius: 24px; + width: 48px; + height: 48px; + border: 0px; + border-radius: 24px; } - + .o2_im_chat_list .item .body { - height: 59px; - margin-left: 16px; - border-bottom: 1px solid rgb(221, 221, 221); + height: 59px; + margin-left: 16px; + border-bottom: 1px solid rgb(221, 221, 221); } .o2_im_chat_list .item .body_up { - height:30px; - line-height: 30px; - margin-left: 56px; - margin-right: 14px; + height: 30px; + line-height: 30px; + margin-left: 56px; + margin-right: 14px; } .o2_im_chat_list .item .body_up .body_title { - float:left; - color: rgb(51, 51, 51); - overflow:hidden; - max-width: 170px; - text-overflow: ellipsis; - white-space: nowrap; + float: left; + color: rgb(51, 51, 51); + overflow: hidden; + max-width: 170px; + text-overflow: ellipsis; + white-space: nowrap; } .o2_im_chat_list .item .body_up .body_time { - float: right; - color: rgb(191, 191, 191); - font-size: 12px; - overflow:hidden; + float: right; + color: rgb(191, 191, 191); + font-size: 12px; + overflow: hidden; } .o2_im_chat_list .item .body_down { - margin-left: 8px; - margin-top: 5px; - max-width: 120px; - height:20px; - line-height: 20px; - float:left; - overflow:hidden; - font-size: 12px; - color: #aaaaaa; - white-space: nowrap; - text-overflow:ellipsis; + margin-left: 8px; + margin-top: 5px; + max-width: 120px; + height: 20px; + line-height: 20px; + float: left; + overflow: hidden; + font-size: 12px; + color: #aaaaaa; + white-space: nowrap; + text-overflow: ellipsis; } .o2_im_chat_list_conv { flex: 1; overflow: auto; } - .o2_im_chat_content { - height: 100%; - margin-left: 259px; - overflow: hidden; - background-color: rgb(255, 255, 255); - opacity: 1; - display: flex; - display: -webkit-box; - display: -webkit-flex; - flex-direction: column; - -ms-flex-direction: column; + height: 100%; + margin-left: 259px; + overflow: hidden; + background-color: rgb(255, 255, 255); + opacity: 1; + display: flex; + display: -webkit-box; + display: -webkit-flex; + flex-direction: column; + -ms-flex-direction: column; } .o2_im_chat_content_title_more { @@ -200,22 +202,35 @@ background-position: center center; background-repeat: no-repeat; height: 30px; - width: 64px; + width: 48px; + margin-right: 10px; + float: right; + cursor: pointer; + display: none; +} +.o2_im_chat_content_title_business_icon { + background-image: url(../x_component_process_ApplicationExplorer/$Main/default/icon/application.png); + background-position: center center; + background-repeat: no-repeat; + background-size: contain; + height: 30px; + width: 30px; float: right; + margin-right: 10px; cursor: pointer; display: none; } .o2_im_chat_content_title_menu { - width: 98px; - position: absolute; - right: 24px; - top: 61px; - background-color: white; - border-radius: 12px; - box-shadow: 2px 2px 2px 1px rgba(0, 0, 0, 0.2); - display: none; - z-index: 10000; + width: 98px; + position: absolute; + right: 24px; + top: 61px; + background-color: white; + border-radius: 12px; + box-shadow: 2px 2px 2px 1px rgba(0, 0, 0, 0.2); + display: none; + z-index: 10000; } .o2_im_chat_content_title_menu_item { height: 48px; @@ -224,273 +239,537 @@ cursor: pointer; } - /* 聊天界面 */ .chat-emoji-box { position: absolute; - width:630px; + width: 630px; height: 260px; left: 5px; bottom: 155px; background-color: #ffffff; - border: 1px solid #F1F1F1; + border: 1px solid #f1f1f1; padding-top: 8px; - border-radius: 8px; + border-radius: 8px; box-shadow: 5px 5px #1d1d1d10; z-index: 100; } .chat-emoji-img { width: 32px; - height: 32px; - float: left; + height: 32px; + float: left; margin: 5px; } .chat-title { - height: 30px; - text-align: center; - padding-top: 15px; - padding-bottom: 15px; - background-color: #ffffff; - border-bottom: 1px solid #F1F1F1; - } - - .chat-title span { - line-height: 30px; - } - - .chat-content { - background-color: #ebebeb; - overflow: auto; - flex:1; - } - - .chat-bottom-area { - height: 155px; - overflow: hidden; - border-top: 1px solid #F1F1F1; - background: #ffffff; - } - - .chat-bottom-area-tool { - position: relative; - padding: 0 8px; - height: 38px; - line-height: 38px; - font-size: 0; - } - - .chat-bottom-area-tool img { - margin: 7px 10px; - } - - .chat-bottom-area-textarea { - margin-left: 10px; - } - - .chat-bottom-area-textarea textarea { - display: block; - width: 100%; - padding: 5px 0 0; - height: 68px; - line-height: 20px; - border: none; - overflow: auto; - resize: none; - background: 0 0; - } - - .chat-bottom-area-send-space { - position: relative; - height: 46px; - } - - .chat-bottom-area-key-tips { - position: absolute; - right: 105px; - top: 3px; - height: 32px; - line-height: 32px; - color: #848484; - } - - .chat-bottom-area-send { - position: absolute; - right: 15px; - top: 3px; - height: 32px; - line-height: 32px; - cursor: pointer; - } - - .chat-bottom-area-send-btn { - border-radius: 3px 0 0 3px; - } - - .chat-bottom-area-send span { - display: inline-block; - vertical-align: top; - font-size: 14px; - line-height: 32px; - margin-left: 5px; - padding: 0 20px; - background-color: #5FB878; - color: #fff; - border-radius: 3px; - } - - - .chat-sender { - clear: both; - /* font-size: 80%; */ - float: left; - width: 75%; - } - - .chat-sender div:nth-of-type(1) { - float: left; - } - - .chat-sender div:nth-of-type(2) { - margin: 0 50px 2px 50px; - padding: 0px; - color: #848484; - /* font-size: 70%; */ - text-align: left; - } - - .chat-sender div:nth-of-type(3) { - background-color: white; - /*float: left;*/ - margin: 0 50px 10px 50px; - padding: 10px 10px 10px 10px; - border-radius: 7px; - text-indent: -12px; - word-wrap: break-word; - white-space: pre-line; - } - .chat-sender .img-chat { - width:192px; - height:144px; - display: table-cell; - vertical-align: middle; - } - .chat-sender .img-chat img { - max-width: 100%; - max-height: 100%; - display: block; - margin: auto; - } - - .chat-receiver { - clear: both; - /* font-size: 80%; */ - float: right; - width: 75%; - } - - .chat-receiver div:nth-of-type(1) { - float: right; - } - - .chat-receiver div:nth-of-type(2) { - margin: 0px 50px 2px 50px; - padding: 0px; - color: #848484; - /* font-size: 70%; */ - text-align: right; - } - .chat-receiver .img-chat { - width:192px; - height:144px; - display: table-cell; - vertical-align: middle; -} -.chat-receiver .img-chat img { - max-width: 100%; - max-height: 100%; - display: block; - margin: auto; -} - - .chat-receiver div:nth-of-type(3) { - /*float:right;*/ - background-color: #b2e281; - margin: 0px 50px 10px 50px; - padding: 10px 10px 10px 10px; - border-radius: 7px; - word-wrap: break-word; - white-space: pre-line; - } - - .chat-receiver div:first-child img, - .chat-sender div:first-child img { - width: 40px; - height: 40px; - /*border-radius: 10%;*/ - } - - .chat-left_triangle { - height: 0px; - width: 0px; - border-width: 6px; - border-style: solid; - border-color: transparent white transparent transparent; - position: relative; - left: -22px; - top: 3px; - } - - .chat-right_triangle { - height: 0px; - width: 0px; - border-width: 6px; - border-style: solid; - border-color: transparent transparent transparent #b2e281; - position: relative; - right: -22px; - top: 3px; - } - .chat-content-emoji { - width: 32px; - height: 32px; - margin: 5px; - } - .chat-notice { - clear: both; - font-size: 70%; - color: white; - text-align: center; - margin-top: 15px; - margin-bottom: 15px; - } - - .chat-notice span { - background-color: #cecece; - line-height: 25px; - border-radius: 5px; - padding: 5px 10px; - } - - /* 右键菜单 */ - .chat-menulist { - width: 130px; - background: #fff; - border: 1px solid #f2f2f5; - border-bottom: none; - border-radius: 2px; - box-shadow: 0 2px 8px 1px rgb(0 0 0 / 20%); - padding: 2px; - list-style-type: none; - } - .chat-menulist li { - font-size: 12px; - cursor: pointer; - line-height: 12px; - position: relative; - display: block; - white-space: nowrap; - min-width: 50px; - padding: 14px 35px 14px 16px; - color: #333; - list-style: none; - } \ No newline at end of file + height: 30px; + text-align: center; + padding-top: 15px; + padding-bottom: 15px; + background-color: #ffffff; + border-bottom: 1px solid #f1f1f1; +} + +.chat-title span { + line-height: 30px; +} + +.chat-content { + background-color: #ebebeb; + overflow: auto; + flex: 1; +} + +.chat-bottom-area { + height: 155px; + overflow: hidden; + border-top: 1px solid #f1f1f1; + background: #ffffff; +} + +.chat-bottom-area-tool { + position: relative; + padding: 0 8px; + height: 38px; + line-height: 38px; + font-size: 0; +} + +.chat-bottom-area-tool img { + margin: 7px 10px; +} + +.chat-bottom-area-textarea { + margin-left: 10px; +} + +.chat-bottom-area-textarea textarea { + display: block; + width: 100%; + padding: 5px 0 0; + height: 68px; + line-height: 20px; + border: none; + overflow: auto; + resize: none; + background: 0 0; +} + +.chat-bottom-area-send-space { + position: relative; + height: 46px; +} + +.chat-bottom-area-key-tips { + position: absolute; + right: 105px; + top: 3px; + height: 32px; + line-height: 32px; + color: #848484; +} + +.chat-bottom-area-send { + position: absolute; + right: 15px; + top: 3px; + height: 32px; + line-height: 32px; + cursor: pointer; +} + +.chat-bottom-area-send-btn { + border-radius: 3px 0 0 3px; +} + +.chat-bottom-area-send span { + display: inline-block; + vertical-align: top; + font-size: 14px; + line-height: 32px; + margin-left: 5px; + padding: 0 20px; + background-color: #5fb878; + color: #fff; + border-radius: 3px; +} + +.chat-sender { + clear: both; + /* font-size: 80%; */ + float: left; + width: 75%; +} + +.chat-sender div:nth-of-type(1) { + float: left; +} + +.chat-sender div:nth-of-type(2) { + margin: 0 50px 2px 50px; + padding: 0px; + color: #848484; + /* font-size: 70%; */ + text-align: left; +} + +.chat-sender div:nth-of-type(3) { + background-color: white; + /*float: left;*/ + margin: 0 50px 10px 50px; + padding: 10px 10px 10px 10px; + border-radius: 7px; + text-indent: -12px; + word-wrap: break-word; + white-space: pre-line; +} +.chat-sender .img-chat { + width: 192px; + height: 144px; + display: table-cell; + vertical-align: middle; +} +.chat-sender .img-chat img { + max-width: 100%; + max-height: 100%; + display: block; + margin: auto; +} + +.chat-receiver { + clear: both; + /* font-size: 80%; */ + float: right; + width: 75%; +} + +.chat-receiver div:nth-of-type(1) { + float: right; +} + +.chat-receiver div:nth-of-type(2) { + margin: 0px 50px 2px 50px; + padding: 0px; + color: #848484; + /* font-size: 70%; */ + text-align: right; +} +.chat-receiver .img-chat { + width: 192px; + height: 144px; + display: table-cell; + vertical-align: middle; +} +.chat-receiver .img-chat img { + max-width: 100%; + max-height: 100%; + display: block; + margin: auto; +} + +.chat-receiver div:nth-of-type(3) { + /*float:right;*/ + background-color: #b2e281; + margin: 0px 50px 10px 50px; + padding: 10px 10px 10px 10px; + border-radius: 7px; + word-wrap: break-word; + white-space: pre-line; +} + +.chat-receiver div:first-child img, +.chat-sender div:first-child img { + width: 40px; + height: 40px; + /*border-radius: 10%;*/ +} + +.chat-left_triangle { + height: 0px; + width: 0px; + border-width: 6px; + border-style: solid; + border-color: transparent white transparent transparent; + position: relative; + left: -22px; + top: 3px; +} + +.chat-right_triangle { + height: 0px; + width: 0px; + border-width: 6px; + border-style: solid; + border-color: transparent transparent transparent #b2e281; + position: relative; + right: -22px; + top: 3px; +} +.chat-content-emoji { + width: 32px; + height: 32px; + margin: 5px; +} +.chat-notice { + clear: both; + font-size: 70%; + color: white; + text-align: center; + margin-top: 15px; + margin-bottom: 15px; +} + +.chat-notice span { + background-color: #cecece; + line-height: 25px; + border-radius: 5px; + padding: 5px 10px; +} +.chat-msg-time { + margin-top: 10px; + color: #999; + text-align: center; + font-size: 12px; + clear: both; +} + +.chat-no-more-data { + margin: 10px auto; + color: #999; + text-align: center; + font-size: 12px; +} + +/* 右键菜单 */ +.chat-menulist { + width: 130px; + background: #fff; + border: 1px solid #f2f2f5; + border-bottom: none; + border-radius: 2px; + box-shadow: 0 2px 8px 1px rgb(0 0 0 / 20%); + padding: 2px; + list-style-type: none; +} +.chat-menulist li { + font-size: 12px; + cursor: pointer; + line-height: 12px; + position: relative; + display: block; + white-space: nowrap; + min-width: 50px; + padding: 14px 35px 14px 16px; + color: #333; + list-style: none; +} + + +/* starter */ +.person-outer { + display: flex; + justify-content: center; + align-items: center; + width: 100%; + height: 100%; + position: absolute; + left: 0; + top: 0; +} + +.person-mask { + opacity: 0.6; + position: absolute; + background-color: #CCC; + top: 0; + left: 0; + right: 0; + bottom: 0; +} + +.person-box { + background-color: rgb(255, 255, 255); + color: rgb(102, 102, 102); + z-index: 30000; + box-shadow: rgb(102 102 102) 3px 3px 15px; + border-radius: 6px; + width: 50%; + height: 50%; + min-width: 400px; + min-height: 300px; + max-width: 1000px; + max-height: 560px; + opacity: 1; + padding: 24px; + display: flex; + flex-direction: column; + +} + +.person-box-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 24px; + border-bottom: 1px solid #dededd; +} + +.person-box-header-title { + color: #000; + font-size: 18px; + text-align: left; +} + +.person-box-header-close { + color: #000; + font-size: 18px; + width: 36px; + height: 36px; + line-height: 36px; + margin: 10px; + text-align: center; + cursor: pointer; +} + +.person-box-body { + flex: 1; + overflow: auto; +} + +.person-box-body-list { + display: flex; + flex-direction: row; + flex-wrap: wrap; +} + +.person-tag { + font-size: 14px; + color: #000; + padding: 10px; + background: #fff; + box-shadow: rgb(102 102 102) 3px 3px 15px; + border-radius: 6px; + margin: 10px; + cursor: pointer; +} + +.person-tag-active { + background: #4A90E2; + color: #fff; +} + +.person-box-footer { + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; +} + +.person-box-footer-btn { + width: 100%; + text-align: center; + margin: 30px 20px 0 20px; + height: 30px; + line-height: 30px; + background: #4A90E2; + border-radius: 15px; + color: #FFFFFF; + cursor: pointer; + max-width: 200px; +} + +.business-work-item { + height: 60px; + border-radius: 8px; + background-color: #FFFFFF; + border: 1px solid #E6E6E6; + margin: 10px 12px; + box-shadow: rgb(102 102 102) 3px 3px 5px; + display: flex; + flex-direction: row; + align-items: center; +} +.business-work-item-btn { + height: 24px; + width: 64px; + line-height: 24px; + margin-right: 12px; + border-radius: 30px; + cursor: pointer; + font-size: 12px; + border: 1px solid #4A90E2; + background-color: #FFFFFF; + color: #4A90E2 !important; + text-align: center; +} + +.conversation-outer { + display: flex; + justify-content: center; + align-items: center; + width: 100%; + height: 100%; + position: absolute; + left: 0; + top: 0; +} + +.conversation-mask { + opacity: 0.6; + position: absolute; + background-color: #CCC; + top: 0; + left: 0; + right: 0; + bottom: 0; +} + +.conversation-box { + background-color: rgb(255, 255, 255); + color: rgb(102, 102, 102); + z-index: 30000; + box-shadow: rgb(102 102 102) 3px 3px 15px; + border-radius: 6px; + width: 50%; + height: 50%; + min-width: 400px; + min-height: 300px; + max-width: 1000px; + max-height: 560px; + opacity: 1; + padding: 24px; + display: flex; + flex-direction: column; + +} + +.conversation-box-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 24px; + border-bottom: 1px solid #dededd; +} + +.conversation-box-header-title { + color: #000; + font-size: 18px; + text-align: left; +} + +.conversation-box-header-close { + color: #000; + font-size: 18px; + width: 36px; + height: 36px; + line-height: 36px; + margin: 10px; + text-align: center; + cursor: pointer; +} + +.conversation-box-body { + flex: 1; + overflow: auto; +} +.conversation-box-desc { + color: #000; + font-size: 14px; + text-align: left; + margin-bottom: 24px; +} +.conversation-box-body-list { + display: flex; + flex-direction: row; + flex-wrap: wrap; +} + +.conversation-item { + font-size: 14px; + color: #000; + padding: 10px; + background: #fff; + box-shadow: rgb(102 102 102) 3px 3px 15px; + border-radius: 6px; + margin: 10px; + cursor: pointer; +} + + +.conversation-box-footer { + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; +} + +.conversation-box-footer-btn { + width: 100%; + text-align: center; + margin: 30px 20px 0 20px; + height: 30px; + line-height: 30px; + background: #4A90E2; + border-radius: 15px; + color: #FFFFFF; + cursor: pointer; + max-width: 200px; +} \ No newline at end of file diff --git a/o2web/source/x_component_IMV2/Main.js b/o2web/source/x_component_IMV2/Main.js index 3bf4aaeed473771b7bc04c60119e706db0573a77..3f6050d4c3b02c45a4e4f8931bcf85b8fcbe25a8 100644 --- a/o2web/source/x_component_IMV2/Main.js +++ b/o2web/source/x_component_IMV2/Main.js @@ -1,6 +1,8 @@ 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.xApplication.IMV2.options.multitask = true; //多窗口 MWF.xApplication.IMV2.Main = new Class({ Extends: MWF.xApplication.Common.Main, Implements: [Options, Events], @@ -15,13 +17,13 @@ MWF.xApplication.IMV2.Main = new Class({ "isResize": true, "isMax": true, "title": MWF.xApplication.IMV2.LP.title, - "conversationId": "" + "conversationId": "", // 传入的当前会话id + "mode": "default" // 展现模式:default onlyChat 。 onlyChat的模式需要传入conversationId 会打开这个会话的聊天窗口并隐藏左边的会话列表 }, onQueryLoad: function () { this.lp = MWF.xApplication.IMV2.LP; this.app = this; this.conversationNodeItemList = []; - this.conversationId = this.options.conversationId || ""; this.messageList = []; this.emojiList = []; //添加87个表情 @@ -32,8 +34,20 @@ MWF.xApplication.IMV2.Main = new Class({ }; this.emojiList.push(emoji); } + + if (!this.status) { + this.conversationId = this.options.conversationId || ""; + this.mode = this.options.mode || "default"; + } else { + this.conversationId = this.status.conversationId || ""; + this.mode = this.status.mode || "default"; + } }, + // 刷新的时候缓存数据 + recordStatus: function(){ + return {"conversationId": this.conversationId, "mode": this.mode}; + }, onQueryClose: function () { this.closeListening(); }, @@ -65,6 +79,15 @@ MWF.xApplication.IMV2.Main = new Class({ this.app.content = this.o2ImMainNode; //启动监听 this.startListening(); + // 处理窗口模式 + if (this.mode === "onlyChat" && this.conversationId != "") { + this.o2ConversationListNode.setStyle("display", "none"); + this.chatNode.setStyle("margin-left", "2px"); + } else { + this.o2ConversationListNode.setStyle("display", "flex"); + this.chatNode.setStyle("margin-left", "259px"); + } + //获取会话列表 this.conversationNodeItemList = []; o2.Actions.load("x_message_assemble_communicate").ImAction.myConversationList(function (json) { @@ -112,7 +135,10 @@ MWF.xApplication.IMV2.Main = new Class({ //查询会话数据 this._checkConversationMessage(); //查询聊天数据 - this._checkNewMessage(); + if (this.chatNodeBox) { + this.chatNodeBox._checkNewMessage(); + } + }, //加载会话列表 loadConversationList: function (list) { @@ -125,19 +151,7 @@ MWF.xApplication.IMV2.Main = new Class({ } } }, - //分页获取会话的消息列表数据 - loadMsgListByConvId: function (page, size, convId) { - var data = { "conversationId": convId }; - o2.Actions.load("x_message_assemble_communicate").ImAction.msgListByPaging(page, size, data, function (json) { - var list = json.data; - for (var i = 0; i < list.length; i++) { - this.messageList.push(list[i]); - this._buildMsgNode(list[i], true); - } - }.bind(this), function (error) { - console.log(error); - }.bind(this), false); - }, + // 点击设置按钮 tapOpenSettings: function() { this.openSettingsDialog(); @@ -198,209 +212,11 @@ MWF.xApplication.IMV2.Main = new Class({ //点击会话 tapConv: function (conv) { this._setCheckNode(conv); - var url = this.path + this.options.style + "/chat.html"; - 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) { - 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", "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"); - } - }.bind(this) - }); - } else { - this.chatTitleMoreBtnNode.setStyle("display", "none"); - } - } - //获取聊天信息 - this.messageList = []; - this.loadMsgListByConvId(1, 20, conv.id); - var scrollFx = new Fx.Scroll(this.chatContentNode); - scrollFx.toBottom(); - // 绑定事件 - this.chatBottomAreaTextareaNode.addEvents({ - "keyup": function (e) { - // debugger; - if (e.code === 13) { - if (e.control === true) { - var text = this.chatBottomAreaTextareaNode.value; - this.chatBottomAreaTextareaNode.value = text + "\n"; - } else { - this.sendMsg(); - } - e.stopPropagation(); - } - }.bind(this) - }); - }.bind(this)); - }, - //修改群名 - tapUpdateConvTitle: function () { - this.chatTitleMoreMenuNode.setStyle("display", "none"); - var title = ""; - for (var i = 0; i < this.conversationNodeItemList.length; i++) { - var c = this.conversationNodeItemList[i]; - if (this.conversationId == c.data.id) { - title = c.data.title; - } - } - var form = new MWF.xApplication.IMV2.UpdateConvTitleForm(this, {}, {"defaultValue": title}, { app: this.app }); - form.create(); - }, - //修改群成员 - tapUpdateConvMembers: function () { - this.chatTitleMoreMenuNode.setStyle("display", "none"); - var members = []; - for (var i = 0; i < this.conversationNodeItemList.length; i++) { - var c = this.conversationNodeItemList[i]; - if (this.conversationId == c.data.id) { - members = c.data.personList; - } - } - 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; - if (text) { - this.chatBottomAreaTextareaNode.value = ""; - this._newAndSendTextMsg(text, "text"); - } else { - console.log(this.lp.noMessage); - this.app.notice(this.lp.noMessage, "error", this.app.content); - } - }, - //点击表情按钮 - showEmojiBox: function () { - if (!this.emojiBoxNode) { - this.emojiBoxNode = new Element("div", { "class": "chat-emoji-box" }).inject(this.chatNode); - var _self = this; - for (var i = 0; i < this.emojiList.length; i++) { - var emoji = this.emojiList[i]; - var emojiNode = new Element("img", { "src": emoji.path, "class": "chat-emoji-img" }).inject(this.emojiBoxNode); - emojiNode.addEvents({ - "mousedown": function (ev) { - _self.sendEmojiMsg(this.emoji); - _self.hideEmojiBox(); - }.bind({ emoji: emoji }) - }); - } - } - this.emojiBoxNode.setStyle("display", "block"); - this.hideFun = this.hideEmojiBox.bind(this); - document.body.addEvent("mousedown", this.hideFun); - }, - // 点击发送文件消息 - showChooseFile: function () { - if (!this.uploadFileAreaNode) { - this.createUploadFileNode(); - } - this.fileUploadNode.click(); - }, - //创建文件选择框 - createUploadFileNode: function () { - this.uploadFileAreaNode = new Element("div"); - var html = ""; - this.uploadFileAreaNode.set("html", html); - this.fileUploadNode = this.uploadFileAreaNode.getFirst(); - this.fileUploadNode.addEvent("change", function () { - var files = this.fileUploadNode.files; - if (files.length) { - var file = files.item(0); - var formData = new FormData(); - formData.append('file', file); - formData.append('fileName', file.name); - var fileExt = file.name.substring(file.name.lastIndexOf(".")); - // 图片消息 - var type = "file" - if (fileExt.toLowerCase() == ".bmp" || fileExt.toLowerCase() == ".jpeg" - || fileExt.toLowerCase() == ".png" || fileExt.toLowerCase() == ".jpg") { - type = "image" - } else { // 文件消息 - type = "file" - } - //上传文件 - o2.Actions.load("x_message_assemble_communicate").ImAction.uploadFile(this.conversationId, type, formData, "{}", function (json) { - if (json.data) { - var fileId = json.data.id - var fileExtension = json.data.fileExtension - var fileName = json.data.fileName - this._newImageOrFileMsgAndSend(type, fileId, fileName, fileExtension) - } - }.bind(this), function (error) { - console.log(error); - }.bind(this)) - } - }.bind(this)); - }, - hideEmojiBox: function () { - //关闭emojiBoxNode - this.emojiBoxNode.setStyle("display", "none"); - document.body.removeEvent("mousedown", this.hideFun); - }, - //发送表情消息 - sendEmojiMsg: function (emoji) { - this._newAndSendTextMsg(emoji.key, "emoji"); + // new ChatNodeBox + this.chatNodeBox = new MWF.xApplication.IMV2.ChatNodeBox(conv, this); }, + //点击创建单聊按钮 tapCreateSingleConv: function () { // var form = new MWF.xApplication.IMV2.SingleForm(this, {}, {}, { app: this.app }); @@ -410,7 +226,7 @@ MWF.xApplication.IMV2.Main = new Class({ }, //点击创建群聊按钮 tapCreateGroupConv: function () { - var form = new MWF.xApplication.IMV2.CreateConversationForm(this, {}, { "title": this.lp.createDroup, "personCount": 0, "personSelected": [] }, { app: this.app }); + var form = new MWF.xApplication.IMV2.CreateConversationForm(this, {}, { "title": this.lp.createGroup, "personCount": 0, "personSelected": [] }, { app: this.app }); form.create() }, //更新群名 @@ -476,30 +292,526 @@ MWF.xApplication.IMV2.Main = new Class({ _self.tapConv(c); } } - if (!isOld) { - var itemNode = _self._createConvItemNode(newConv); - _self.conversationNodeItemList.push(itemNode); - _self.tapConv(newConv); - } - }.bind(this), function (error) { - console.log(error); - }.bind(this)) - }, - //创建会话ItemNode - _createConvItemNode: function (conv) { - return new MWF.xApplication.IMV2.ConversationItem(conv, this); - }, - //会话ItemNode 点击背景色 - _setCheckNode: function (conv) { - for (var i = 0; i < this.conversationNodeItemList.length; i++) { - var item = this.conversationNodeItemList[i]; - if (item.data.id == conv.id) { - item.addCheckClass(); - } else { - item.removeCheckClass(); + if (!isOld) { + var itemNode = _self._createConvItemNode(newConv); + _self.conversationNodeItemList.push(itemNode); + _self.tapConv(newConv); + } + }.bind(this), function (error) { + console.log(error); + }.bind(this)) + }, + //创建会话ItemNode + _createConvItemNode: function (conv) { + return new MWF.xApplication.IMV2.ConversationItem(conv, this); + }, + //会话ItemNode 点击背景色 + _setCheckNode: function (conv) { + for (var i = 0; i < this.conversationNodeItemList.length; i++) { + var item = this.conversationNodeItemList[i]; + if (item.data.id == conv.id) { + item.addCheckClass(); + } else { + item.removeCheckClass(); + } + } + }, + + //刷新会话Item里面的最后消息内容 + _refreshConvMessage: function (msg) { + for (var i = 0; i < this.conversationNodeItemList.length; i++) { + var node = this.conversationNodeItemList[i]; + if (node.data.id == this.conversationId) { + node.refreshLastMsg(msg); + } + } + }, + //检查会话列表是否有更新 + _checkConversationMessage: function () { + o2.Actions.load("x_message_assemble_communicate").ImAction.myConversationList(function (json) { + if (json.data && json.data instanceof Array) { + var newConList = json.data; + for (var j = 0; j < newConList.length; j++) { + var nCv = newConList[j]; + var isNew = true; + for (var i = 0; i < this.conversationNodeItemList.length; i++) { + var cv = this.conversationNodeItemList[i]; + if (cv.data.id == nCv.id) { + isNew = false; + //刷新 + cv.refreshLastMsg(nCv.lastMessage); + cv.refreshData(nCv); + if (this.conversationId === nCv.id) { + this.tapConv(nCv); + } + } + } + //新会话 创建 + if (isNew) { + var itemNode = this._createConvItemNode(nCv); + this.conversationNodeItemList.push(itemNode); + } + } + //this.loadConversationList(json.data); + } + }.bind(this)); + }, + + //用户头像 + _getIcon: function (id) { + var orgAction = MWF.Actions.get("x_organization_assemble_control") + var url = (id) ? orgAction.getPersonIcon(id) : "../x_component_IMV2/$Main/default/icons/group.png"; + return url + "?" + (new Date().getTime()); + }, + + //输出特殊的时间格式 + _friendlyTime: function (date) { + var day = date.getDate(); + var monthIndex = date.getMonth(); + var year = date.getFullYear(); + var time = date.getTime(); + var today = new Date(); + var todayDay = today.getDate(); + var todayMonthIndex = today.getMonth(); + var todayYear = today.getFullYear(); + var todayTime = today.getTime(); + + var retTime = ""; + //同一天 + if (day === todayDay && monthIndex === todayMonthIndex && year === todayYear) { + var hour = 0; + if (todayTime > time) { + hour = parseInt((todayTime - time) / 3600000); + if (hour == 0) { + retTime = Math.max(parseInt((todayTime - time) / 60000), 1) + this.lp.minutesBefore + } else { + retTime = hour + this.lp.hoursBefore + } + + } + return retTime; + } + var dates = parseInt(time / 86400000); + var todaydates = parseInt(todayTime / 86400000); + if (todaydates > dates) { + var days = (todaydates - dates); + if (days == 1) { + retTime = this.lp.yesterday; + } else if (days == 2) { + retTime = this.lp.beforeYesterday; + } else if (days > 2 && days < 31) { + retTime = days + this.lp.daysBefore; + } else if (days >= 31 && days <= 2 * 31) { + retTime = this.lp.monthAgo; + } else if (days > 2 * 31 && days <= 3 * 31) { + retTime = this.lp.towMonthAgo; + } else if (days > 3 * 31 && days <= 4 * 31) { + retTime = this.lp.threeMonthAgo; + } else { + retTime = this._formatDate(date); + } + } + + return retTime; + + }, + + + //yyyy-MM-dd + _formatDate: function (date) { + var month = date.getMonth() + 1; + var day = date.getDate(); + month = (month.toString().length == 1) ? ("0" + month) : month; + day = (day.toString().length == 1) ? ("0" + day) : day; + return date.getFullYear() + '-' + month + '-' + day; + } + +}); + +// 聊天窗口 +MWF.xApplication.IMV2.ChatNodeBox = new Class({ + initialize: function (data, main) { + this.data = data; + this.main = main; + this.container = this.main.chatNode; + this.lp = this.main.lp; + this.path = this.main.path; + this.options = this.main.options; + this.pageSize = 20; + this.page = 1; + this.isLoading = false; // 正在加载 + this.hasMoreMsgData = false; // 是否还有更多的消息 翻页 + this.load(); + }, + // 创建聊天窗口 + load: function() { + var url = this.path + this.options.style + "/chat.html"; + this.conversationId = this.data.id; + this.container.empty(); + if (this.emojiBoxNode) { + this.emojiBoxNode.destroy(); + this.emojiBoxNode = null; + } + this.container.loadHtml(url, { "bind": { "convName": this.data.title, "lp": this.lp }, "module": this }, function () { + var me = layout.session.user.distinguishedName; + if (this.data.type === "group" && me === this.data.adminPerson) { + 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", "block"); + this.chatTitleMoreMenuItem2Node.setStyle("display", "block"); + if (this.main.imConfig.enableClearMsg) { + this.chatTitleMoreMenuItem3Node.setStyle("display", "block"); + } else { + this.chatTitleMoreMenuItem3Node.setStyle("display", "none"); + } + } else { + this.chatTitleMoreMenuNode.setStyle("display", "none"); + } + }.bind(this) + }); + } else if (this.data.type !== "group") { + if (this.main.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"); + } + }.bind(this) + }); + } else { + this.chatTitleMoreBtnNode.setStyle("display", "none"); + } + } + //获取聊天信息 + this.page = 1; + this.loadMsgListByPage(); + var scrollFx = new Fx.Scroll(this.chatContentNode); + scrollFx.toBottom(); + // 绑定事件 + this.chatBottomAreaTextareaNode.addEvents({ + "keyup": function (e) { + // debugger; + if (e.code === 13) { + if (e.control === true) { + var text = this.chatBottomAreaTextareaNode.value; + this.chatBottomAreaTextareaNode.value = text + "\n"; + } else { + this.sendMsg(); + } + e.stopPropagation(); + } + }.bind(this) + }); + // 绑定时间 + this.chatContentNode.addEvents({ + "scroll": function(e) { + //滑到顶部时触发下次数据加载 + if (this.chatContentNode.scrollTop == 0) { + if (this.hasMoreMsgData) { // 有更多数据 + // 间隔1秒 防止频繁 + setTimeout(() => { + //将scrollTop置为10以便下次滑到顶部 + this.chatContentNode.scrollTop = 10; + //加载数据 + this.loadMoreMsgList(); + }, 1000); + } + } + }.bind(this) + }); + // 显示业务图标 + this.loadBusinessIcon(); + }.bind(this)); + + }, + // 如果有业务数据 头部展现应用图标 可以点击打开 + loadBusinessIcon: function() { + if (this.data.businessId && this.data.businessBody) { + if (this.data.businessType && this.data.businessType === "process") { + var work = JSON.parse(this.data.businessBody); + var applicationId = work.application; + this.chatTitleBusinessBtnNode.setStyles({"background-image": "url(../x_component_process_ApplicationExplorer/$Main/default/icon/application.png)", "display":"block"}); + this.chatTitleBusinessBtnNode.store("work", work); + this.chatTitleBusinessBtnNode.addEvent("click", function(e) { + this.loadProcessWork(e.target.retrieve("work")); + e.preventDefault(); + }.bind(this)); + o2.Actions.load("x_processplatform_assemble_surface").ApplicationAction.getIcon(applicationId, function(json) { + if (json.data && json.data.icon) { + this.chatTitleBusinessBtnNode.setStyles({"background-image": "url(data:image/png;base64," + json.data.icon + ")", "display":"block"}); + } + }.bind(this)); + } + } + }, + // 获取工作对象 + loadProcessWork(work) { + if (work && work.job) { + o2.Actions.load("x_processplatform_assemble_surface").JobAction.findWorkWorkCompleted(work.job, function(json){ + if (json.data ) { + var workList = []; + if (json.data.workList && json.data.workList.length > 0) { + workList = json.data.workList + } + var workCompletedList = []; + if (json.data.workCompletedList && json.data.workCompletedList.length > 0) { + workCompletedList = json.data.workCompletedList + } + this.showProcessWorkDialog(workList, workCompletedList); + } + }.bind(this), function(error){ + console.log(error); + }.bind(this)); + } + }, + // 打开关联工作 + showProcessWorkDialog: function(workList, workCompletedList) { + if (workList.length > 0 || workCompletedList.length > 0) { + var url = this.path + this.options.style + "/chooseBusinessWork.html"; + this.container.loadHtml(url, { "bind": { "lp": this.lp }, "module": this }, function(){ + // 工作展现 + if (workList.length > 0) { + for (let index = 0; index < workList.length; index++) { + const work = workList[index]; + var workItemNode = new Element("div", {"class":"business-work-item"}).inject(this.businessWorkListNode); + var workProcessNameNode = new Element("div", {"style":"flex: 1;"}).inject(workItemNode); + var title = work.title + if (title === "") { + title = this.lp.noTitle + } + workProcessNameNode.set("text", "【"+work.processName+"】" + title); + var openBtnNode = new Element("div", {"class":"business-work-item-btn"}).inject(workItemNode); + openBtnNode.store("work", work); + openBtnNode.set("text", this.lp.open); + openBtnNode.addEvents({ + "click": function(e) { + var thisWork = e.target.retrieve("work"); + if (thisWork) { + var opotions = { + "workId": thisWork.id, + } + layout.openApplication(null, "process.Work", opotions); + } + this.closeProcessWorkDialog(); + e.preventDefault(); + }.bind(this) + }) + } + } + if (workCompletedList.length > 0) { + for (let index = 0; index < workCompletedList.length; index++) { + const workCompleted = workCompletedList[index]; + var workItemNode = new Element("div", {"class":"business-work-item"}).inject(this.businessWorkListNode); + var workProcessNameNode = new Element("div", {"style":"flex: 1;"}).inject(workItemNode); + var title = workCompleted.title + if (title === "") { + title = this.lp.noTitle + } + workProcessNameNode.set("text", "【"+workCompleted.processName+"】" + title); + var openBtnNode = new Element("div", {"class":"business-work-item-btn"}).inject(workItemNode); + openBtnNode.store("work", workCompleted); + openBtnNode.set("text", this.lp.open); + openBtnNode.addEvents({ + "click": function(e) { + var thisWork = e.target.retrieve("work"); + if (thisWork) { + var opotions = { + "workCompletedId": thisWork.id, + } + layout.openApplication(null, "process.Work", opotions); + } + this.closeProcessWorkDialog(); + e.preventDefault(); + }.bind(this) + }) + } + } + + + // 关闭 + this.businessWorkChooseCloseBtnNode.addEvents({ + "click": function(e) { + this.closeProcessWorkDialog(); + e.preventDefault(); + }.bind(this) + }) + }.bind(this)); + } + }, + // + closeProcessWorkDialog: function() { + if (this.businessWorkChooseDialogNode) { + this.businessWorkChooseDialogNode.destroy(); + this.businessWorkChooseDialogNode = null; + } + }, + + //检查是否有新消息 + _checkNewMessage: function () { + if (this.conversationId && this.conversationId != "") {//是否有会话窗口 + var data = { "conversationId": this.conversationId }; + o2.Actions.load("x_message_assemble_communicate").ImAction.msgListByPaging(1, 10, data, function (json) { + var list = json.data; + if (list && list.length > 0) { + var msg = list[0]; + //检查聊天框是否有变化 + if (this.conversationId == msg.conversationId) { + for (var i = 0; i < list.length; i++) { + var isnew = true; + var m = list[i]; + for (var j = 0; j < this.messageList.length; j++) { + if (this.messageList[j].id == m.id) { + isnew = false; + } + } + if (isnew) { + this.messageList.push(m); + this._buildMsgNode(m, false); + // this._refreshConvMessage(m); + } + } + } + } + + }.bind(this), function (error) { + console.log(error); + }.bind(this), false); + } + }, + + // 加载更多 + loadMoreMsgList: function() { + this.page += 1; + this.loadMsgListByPage(); + }, + + //分页获取会话的消息列表数据 + loadMsgListByPage: function () { + if (this.isLoading) { + console.log("正在加载中。。。。。。"); + return ; + } + var data = { "conversationId": this.conversationId }; + this.isLoading = true; + if (this.page === 1) { + this.messageList = []; + } + o2.Actions.load("x_message_assemble_communicate").ImAction.msgListByPaging(this.page, this.pageSize, data, function (json) { + var list = json.data; + var size = 0; + if (list && list.length > 0) { + size = list.length; + for (var i = 0; i < list.length; i++) { + if (this.page == 1) { + this.messageList.push(list[i]); + } else { + this.messageList.unshift(list[i]); + } + this._buildMsgNode(list[i], true); + } + } + this.isLoading = false; + if (size < this.pageSize) { // 没有更多数据了 + this.noMoreDataNode = new Element("div", {"class": "chat-no-more-data"}).inject(this.chatContentNode, "top"); + this.noMoreDataNode.set("text", this.lp.msgLoadNoMoreData); + this.hasMoreMsgData = false; + } else { + if (this.noMoreDataNode) { + this.noMoreDataNode.destroy(); + this.noMoreDataNode = null; + } + this.hasMoreMsgData = true; + } + }.bind(this), function (error) { + console.log(error); + this.isLoading = false; + }.bind(this), false); + }, + + + //修改群名 + tapUpdateConvTitle: function () { + this.chatTitleMoreMenuNode.setStyle("display", "none"); + var title = ""; + for (var i = 0; i < this.main.conversationNodeItemList.length; i++) { + var c = this.main.conversationNodeItemList[i]; + if (this.conversationId == c.data.id) { + title = c.data.title; + } + } + var form = new MWF.xApplication.IMV2.UpdateConvTitleForm(this.main, {}, {"defaultValue": title}, { app: this.main.app }); + form.create(); + }, + //修改群成员 + tapUpdateConvMembers: function () { + this.chatTitleMoreMenuNode.setStyle("display", "none"); + var members = []; + for (var i = 0; i < this.main.conversationNodeItemList.length; i++) { + var c = this.main.conversationNodeItemList[i]; + if (this.conversationId == c.data.id) { + members = c.data.personList; + } + } + var form = new MWF.xApplication.IMV2.CreateConversationForm(this.main, {}, { "title": this.lp.modifyMember, "personCount": 0, "personSelected": members, "isUpdateMember": true }, { app: this.main.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"); + }, + + //点击表情按钮 + showEmojiBox: function () { + if (!this.emojiBoxNode) { + this.emojiBoxNode = new Element("div", { "class": "chat-emoji-box" }).inject(this.container); + var _self = this; + for (var i = 0; i < this.main.emojiList.length; i++) { + var emoji = this.main.emojiList[i]; + var emojiNode = new Element("img", { "src": emoji.path, "class": "chat-emoji-img" }).inject(this.emojiBoxNode); + emojiNode.addEvents({ + "mousedown": function (ev) { + _self.sendEmojiMsg(this.emoji); + _self.hideEmojiBox(); + }.bind({ emoji: emoji }) + }); + } + } + this.emojiBoxNode.setStyle("display", "block"); + this.hideFun = this.hideEmojiBox.bind(this); + document.body.addEvent("mousedown", this.hideFun); + }, + + _reclickConv: function() { + for (var i = 0; i < this.main.conversationNodeItemList.length; i++) { + var c = this.main.conversationNodeItemList[i]; + if (this.conversationId == c.data.id) { + this.main.tapConv(c.data); } } }, + //创建图片或文件消息 _newImageOrFileMsgAndSend: function (type, fileId, fileName, fileExt) { var distinguishedName = layout.session.user.distinguishedName; @@ -530,7 +842,7 @@ MWF.xApplication.IMV2.Main = new Class({ }.bind(this)); this.messageList.push(message); this._buildReceiver(body, distinguishedName, false, message); - this._refreshConvMessage(message); + this.main._refreshConvMessage(message); }, //创建文本消息 并发送 _newAndSendTextMsg: function (text, type) { @@ -557,79 +869,73 @@ MWF.xApplication.IMV2.Main = new Class({ }.bind(this)); this.messageList.push(textMessage); this._buildReceiver(body, distinguishedName, false, textMessage); - this._refreshConvMessage(textMessage); + this.main._refreshConvMessage(textMessage); }, - //刷新会话Item里面的最后消息内容 - _refreshConvMessage: function (msg) { - for (var i = 0; i < this.conversationNodeItemList.length; i++) { - var node = this.conversationNodeItemList[i]; - if (node.data.id == this.conversationId) { - node.refreshLastMsg(msg); - } + //点击发送消息 + sendMsg: function () { + var text = this.chatBottomAreaTextareaNode.value; + if (text) { + this.chatBottomAreaTextareaNode.value = ""; + this._newAndSendTextMsg(text, "text"); + } else { + console.log(this.lp.noMessage); + this.app.notice(this.lp.noMessage, "error", this.app.content); } }, - //检查会话列表是否有更新 - _checkConversationMessage: function () { - o2.Actions.load("x_message_assemble_communicate").ImAction.myConversationList(function (json) { - if (json.data && json.data instanceof Array) { - var newConList = json.data; - for (var j = 0; j < newConList.length; j++) { - var nCv = newConList[j]; - var isNew = true; - for (var i = 0; i < this.conversationNodeItemList.length; i++) { - var cv = this.conversationNodeItemList[i]; - if (cv.data.id == nCv.id) { - isNew = false; - //刷新 - cv.refreshLastMsg(nCv.lastMessage); - cv.refreshData(nCv); - if (this.conversationId === nCv.id) { - this.tapConv(nCv); - } - } - } - //新会话 创建 - if (isNew) { - var itemNode = this._createConvItemNode(nCv); - this.conversationNodeItemList.push(itemNode); - } + + // 点击发送文件消息 + showChooseFile: function () { + if (!this.uploadFileAreaNode) { + this.createUploadFileNode(); + } + this.fileUploadNode.click(); + }, + //创建文件选择框 + createUploadFileNode: function () { + this.uploadFileAreaNode = new Element("div"); + var html = ""; + this.uploadFileAreaNode.set("html", html); + this.fileUploadNode = this.uploadFileAreaNode.getFirst(); + this.fileUploadNode.addEvent("change", function () { + var files = this.fileUploadNode.files; + if (files.length) { + var file = files.item(0); + var formData = new FormData(); + formData.append('file', file); + formData.append('fileName', file.name); + var fileExt = file.name.substring(file.name.lastIndexOf(".")); + // 图片消息 + var type = "file" + if (fileExt.toLowerCase() == ".bmp" || fileExt.toLowerCase() == ".jpeg" + || fileExt.toLowerCase() == ".png" || fileExt.toLowerCase() == ".jpg") { + type = "image" + } else { // 文件消息 + type = "file" } - //this.loadConversationList(json.data); + //上传文件 + o2.Actions.load("x_message_assemble_communicate").ImAction.uploadFile(this.conversationId, type, formData, "{}", function (json) { + if (json.data) { + var fileId = json.data.id + var fileExtension = json.data.fileExtension + var fileName = json.data.fileName + this._newImageOrFileMsgAndSend(type, fileId, fileName, fileExtension) + } + }.bind(this), function (error) { + console.log(error); + }.bind(this)) } }.bind(this)); }, - //检查是否有新消息 - _checkNewMessage: function () { - if (this.conversationId && this.conversationId != "") {//是否有会话窗口 - var data = { "conversationId": this.conversationId }; - o2.Actions.load("x_message_assemble_communicate").ImAction.msgListByPaging(1, 10, data, function (json) { - var list = json.data; - if (list && list.length > 0) { - var msg = list[0]; - //检查聊天框是否有变化 - if (this.conversationId == msg.conversationId) { - for (var i = 0; i < list.length; i++) { - var isnew = true; - var m = list[i]; - for (var j = 0; j < this.messageList.length; j++) { - if (this.messageList[j].id == m.id) { - isnew = false; - } - } - if (isnew) { - this.messageList.push(m); - this._buildMsgNode(m, false); - // this._refreshConvMessage(m); - } - } - } - } - - }.bind(this), function (error) { - console.log(error); - }.bind(this), false); - } + hideEmojiBox: function () { + //关闭emojiBoxNode + this.emojiBoxNode.setStyle("display", "none"); + document.body.removeEvent("mousedown", this.hideFun); + }, + //发送表情消息 + sendEmojiMsg: function (emoji) { + this._newAndSendTextMsg(emoji.key, "emoji"); }, + //创建消息html节点 _buildMsgNode: function (msg, isTop) { var createPerson = msg.createPerson; @@ -643,17 +949,22 @@ MWF.xApplication.IMV2.Main = new Class({ } }, /** - * 消息发送体 + * 消息接收对象 + * 这里的方法名错了两者互换了无需理会 * @param msgBody 消息体 * @param createPerson 消息人员 * @param isTop 是否放在顶部 * @param msg 消息对象 */ _buildSender: function (msgBody, createPerson, isTop, msg) { + if (!isTop) { + // 添加消息时间 + this._buildMsgTime(isTop, msg); + } var receiverBodyNode = new Element("div", { "class": "chat-sender", "id": msg.id}).inject(this.chatContentNode, isTop ? "top" : "bottom"); this._addContextMenuEvent(receiverBodyNode, msg); var avatarNode = new Element("div").inject(receiverBodyNode); - var avatarUrl = this._getIcon(createPerson); + var avatarUrl = this.main._getIcon(createPerson); var name = createPerson; if (createPerson.indexOf("@") != -1) { name = name.substring(0, createPerson.indexOf("@")); @@ -665,9 +976,9 @@ MWF.xApplication.IMV2.Main = new Class({ //text if (msgBody.type == "emoji") { // 表情 var img = ""; - for (var i = 0; i < this.emojiList.length; i++) { - if (msgBody.body == this.emojiList[i].key) { - img = this.emojiList[i].path; + for (var i = 0; i < this.main.emojiList.length; i++) { + if (msgBody.body == this.main.emojiList[i].key) { + img = this.main.emojiList[i].path; } } new Element("img", { "src": img, "class": "chat-content-emoji" }).inject(lastNode); @@ -698,25 +1009,33 @@ MWF.xApplication.IMV2.Main = new Class({ } else {//text new Element("span", { "text": msgBody.body }).inject(lastNode); } - + if (isTop) { + // 添加消息时间 + this._buildMsgTime(isTop, msg); + } if (!isTop) { var scrollFx = new Fx.Scroll(this.chatContentNode); scrollFx.toBottom(); } }, /** - * 消息接收体 + * 消息发送对象 + * 这里的方法名错了两者互换了无需理会 * @param msgBody * @param createPerson 消息人员 * @param isTop 是否放在顶部 * @param msg 消息对象 */ _buildReceiver: function (msgBody, createPerson, isTop, msg) { + if (!isTop) { + // 添加消息时间 + this._buildMsgTime(isTop, msg); + } var receiverBodyNode = new Element("div", { "class": "chat-receiver", "id": msg.id}).inject(this.chatContentNode, isTop ? "top" : "bottom"); this._addContextMenuEvent(receiverBodyNode, msg); var avatarNode = new Element("div").inject(receiverBodyNode); - var avatarUrl = this._getIcon(createPerson); + var avatarUrl = this.main._getIcon(createPerson); var name = createPerson; if (createPerson.indexOf("@") != -1) { name = name.substring(0, createPerson.indexOf("@")); @@ -728,9 +1047,9 @@ MWF.xApplication.IMV2.Main = new Class({ if (msgBody.type == "emoji") { // 表情 var img = ""; - for (var i = 0; i < this.emojiList.length; i++) { - if (msgBody.body == this.emojiList[i].key) { - img = this.emojiList[i].path; + for (var i = 0; i < this.main.emojiList.length; i++) { + if (msgBody.body == this.main.emojiList[i].key) { + img = this.main.emojiList[i].path; } } new Element("img", { "src": img, "class": "chat-content-emoji" }).inject(lastNode); @@ -761,12 +1080,91 @@ MWF.xApplication.IMV2.Main = new Class({ } else {//text new Element("span", { "text": msgBody.body }).inject(lastNode); } - + if (isTop) { + // 添加消息时间 + this._buildMsgTime(isTop, msg); + } if (!isTop) { var scrollFx = new Fx.Scroll(this.chatContentNode); scrollFx.toBottom(); } }, + + // 消息体上是否显示消息时间 + _buildMsgTime: function(isTop, msg) { + // var flag = false; + // for (let index = 0; index < this.messageList.length; index++) { + // const element = this.messageList[index]; + // if (element.id && element.id === msg.id) { + // if (index > 0) { + // const before = this.messageList[index-1]; + // var thisTime = o2.common.toDate(msg.createTime); + // var beforeTime = o2.common.toDate(before.createTime); + // var minu = ( beforeTime.getTime() - thisTime.getTime() ) / 1000 / 60 ; + // if (minu > 1) { // 超过1分钟 + // flag = true; + // } + // } else { + // flag = true; + // } + // break + // } + // } + // if (flag ){ + // var timeNode = new Element("div", { "class": "chat-msg-time"}).inject(this.chatContentNode, isTop ? "top" : "bottom"); + // timeNode.set("text", this._msgShowTime(o2.common.toDate(msg.createTime))) + // } + + var timeNode = new Element("div", { "class": "chat-msg-time"}).inject(this.chatContentNode, isTop ? "top" : "bottom"); + timeNode.set("text", this._msgShowTime(o2.common.toDate(msg.createTime))) + }, + + // 消息时间 + _msgShowTime: function (date) { + var day = date.getDate(); + var monthIndex = date.getMonth(); + var year = date.getFullYear(); + var time = date.getTime(); + var today = new Date(); + var todayDay = today.getDate(); + var todayMonthIndex = today.getMonth(); + var todayYear = today.getFullYear(); + var todayTime = today.getTime(); + + var retTime = ""; + //同一天 + if (day === todayDay && monthIndex === todayMonthIndex && year === todayYear) { + var hour = date.getHours() > 9 ? ""+date.getHours() : "0" + date.getHours(); + var minute = date.getMinutes() > 9 ? ""+date.getMinutes() : "0" + date.getMinutes(); + retTime = hour + ":" +minute; + return retTime; + } + var dates = parseInt(time / 86400000); + var todaydates = parseInt(todayTime / 86400000); + if (todaydates > dates) { + var days = (todaydates - dates); + if (days == 1) { + var hour = date.getHours() > 9 ? ""+date.getHours() : "0" + date.getHours(); + var minute = date.getMinutes() > 9 ? ""+date.getMinutes() : "0" + date.getMinutes(); + retTime = this.lp.yesterday + " " + hour + ":" +minute; + } else if (days == 2) { + var hour = date.getHours() > 9 ? ""+date.getHours() : "0" + date.getHours(); + var minute = date.getMinutes() > 9 ? ""+date.getMinutes() : "0" + date.getMinutes(); + retTime = this.lp.beforeYesterday + " " + hour + ":" +minute; + }else { + var month = date.getMonth() + 1; + var day = date.getDate(); + month = (month.toString().length == 1) ? ("0" + month) : month; + day = (day.toString().length == 1) ? ("0" + day) : day; + var hour = date.getHours() > 9 ? ""+date.getHours() : "0" + date.getHours(); + var minute = date.getMinutes() > 9 ? ""+date.getMinutes() : "0" + date.getMinutes(); + retTime = month + '-' + day + " " + hour + ":" +minute; + } + } + + return retTime; + + }, // 绑定右键事件 _addContextMenuEvent: function(receiverBodyNode, msg) { receiverBodyNode.store("msg", msg); @@ -787,12 +1185,12 @@ MWF.xApplication.IMV2.Main = new Class({ var distinguishedName = layout.session.user.distinguishedName; var list = []; // 菜单列表 - if (this.imConfig.enableRevokeMsg) { // 是否启用撤回消息 + if (this.main.imConfig.enableRevokeMsg) { // 是否启用撤回消息 if (createPerson != distinguishedName) { // 判断是否群主 var isGroupAdmin = false; - for (var i = 0; i < this.conversationNodeItemList.length; i++) { - var c = this.conversationNodeItemList[i]; + for (var i = 0; i < this.main.conversationNodeItemList.length; i++) { + var c = this.main.conversationNodeItemList[i]; if (this.conversationId == c.data.id) { if (c.data.type === "group" && distinguishedName === c.data.adminPerson) { isGroupAdmin = true; @@ -812,7 +1210,7 @@ MWF.xApplication.IMV2.Main = new Class({ } if (list.length > 0) { // 生成菜单 - this.menuNode = new Element("ul", {"class": "chat-menulist", "styles": { "position": "fixed", "z-index": "9999", "top": menutop, "left": menuleft } }).inject(this.chatNode); + this.menuNode = new Element("ul", {"class": "chat-menulist", "styles": { "position": "fixed", "z-index": "9999", "top": menutop, "left": menuleft } }).inject(this.container); for (let index = 0; index < list.length; index++) { const element = list[index]; var menuItemNode = new Element("li", {"text": element.text}).inject(this.menuNode); @@ -834,10 +1232,10 @@ MWF.xApplication.IMV2.Main = new Class({ this.menuNode = null; } e.preventDefault(); - if( this.closeMsgContextMenuFun )this.app.content.removeEvent( "click", this.closeMsgContextMenuFun ); + if( this.closeMsgContextMenuFun )this.main.app.content.removeEvent( "click", this.closeMsgContextMenuFun ); }.bind(this); - this.app.content.addEvents({ + this.main.app.content.addEvents({ "click": this.closeMsgContextMenuFun }); } @@ -884,12 +1282,6 @@ MWF.xApplication.IMV2.Main = new Class({ var url = "https://api.map.baidu.com/marker?location=" + lat + "," + longt + "&title=" + address + "&content=" + content + "&output=html&src=net.o2oa.map"; return url; }, - //用户头像 - _getIcon: function (id) { - var orgAction = MWF.Actions.get("x_organization_assemble_control") - var url = (id) ? orgAction.getPersonIcon(id) : "../x_component_IMV2/$Main/default/icons/group.png"; - return url + "?" + (new Date().getTime()); - }, // 文件类型icon图 _getFileIcon: function (ext) { if (ext) { @@ -960,65 +1352,6 @@ MWF.xApplication.IMV2.Main = new Class({ return "icon_file_unkown.png"; } }, - //输出特殊的时间格式 - _friendlyTime: function (date) { - var day = date.getDate(); - var monthIndex = date.getMonth(); - var year = date.getFullYear(); - var time = date.getTime(); - var today = new Date(); - var todayDay = today.getDate(); - var todayMonthIndex = today.getMonth(); - var todayYear = today.getFullYear(); - var todayTime = today.getTime(); - - var retTime = ""; - //同一天 - if (day === todayDay && monthIndex === todayMonthIndex && year === todayYear) { - var hour = 0; - if (todayTime > time) { - hour = parseInt((todayTime - time) / 3600000); - if (hour == 0) { - retTime = Math.max(parseInt((todayTime - time) / 60000), 1) + this.lp.minutesBefore - } else { - retTime = hour + this.lp.hoursBefore - } - - } - return retTime; - } - var dates = parseInt(time / 86400000); - var todaydates = parseInt(todayTime / 86400000); - if (todaydates > dates) { - var days = (todaydates - dates); - if (days == 1) { - retTime = this.lp.yesterday; - } else if (days == 2) { - retTime = this.lp.beforeYesterday; - } else if (days > 2 && days < 31) { - retTime = days + this.lp.daysBefore; - } else if (days >= 31 && days <= 2 * 31) { - retTime = this.lp.monthAgo; - } else if (days > 2 * 31 && days <= 3 * 31) { - retTime = this.lp.towMonthAgo; - } else if (days > 3 * 31 && days <= 4 * 31) { - retTime = this.lp.threeMonthAgo; - } else { - retTime = this._formatDate(date); - } - } - - return retTime; - - }, - //yyyy-MM-dd - _formatDate: function (date) { - var month = date.getMonth() + 1; - var day = date.getDate(); - month = (month.toString().length == 1) ? ("0" + month) : month; - day = (day.toString().length == 1) ? ("0" + day) : day; - return date.getFullYear() + '-' + month + '-' + day; - }, //当前时间 yyyy-MM-dd HH:mm:ss _currentTime: function () { var today = new Date(); @@ -1037,10 +1370,9 @@ MWF.xApplication.IMV2.Main = new Class({ return year + "-" + month + "-" + date + " " + hour + ":" + minu + ":" + sec; } - }); -//会话对象 +// 会话对象 MWF.xApplication.IMV2.ConversationItem = new Class({ initialize: function (data, main) { this.data = data; diff --git a/o2web/source/x_component_IMV2/Starter.js b/o2web/source/x_component_IMV2/Starter.js new file mode 100644 index 0000000000000000000000000000000000000000..25f97ee148f2c25279539237e59c2eb6d3ca0826 --- /dev/null +++ b/o2web/source/x_component_IMV2/Starter.js @@ -0,0 +1,336 @@ +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]; + //
群聊1111 | 打开
+ 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 + " | 打开"); + 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]; + //
了国栋
+ 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 = "" + + "" + + " " + + "
"; + 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(); + } + } +}); diff --git a/o2web/source/x_component_IMV2/lp/en.js b/o2web/source/x_component_IMV2/lp/en.js index 93894cdebf6622abd3b6ce6f7390fe8a13ec3e77..838b57724938daf63522e7beb2548910cbf32e39 100644 --- a/o2web/source/x_component_IMV2/lp/en.js +++ b/o2web/source/x_component_IMV2/lp/en.js @@ -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: ", diff --git a/o2web/source/x_component_IMV2/lp/zh-cn.js b/o2web/source/x_component_IMV2/lp/zh-cn.js index 5e8911e808be0e4b2568e11b00c5f2dc8bbb9359..417a6c30c17ac26a1cb39c74ba5898ba54b79b39 100644 --- a/o2web/source/x_component_IMV2/lp/zh-cn.js +++ b/o2web/source/x_component_IMV2/lp/zh-cn.js @@ -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": "是否开启聊天消息清除功能:", diff --git a/o2web/source/x_component_process_Xform/Form.js b/o2web/source/x_component_process_Xform/Form.js index d8b129159aa4a6e6e97b43aba3c0e92d5c3d3397..03aa3bc65ec6b5cbf7f6d7c04a4cf11388aeca3f 100644 --- a/o2web/source/x_component_process_Xform/Form.js +++ b/o2web/source/x_component_process_Xform/Form.js @@ -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;