package cn.com.ty.lift.common.model; import cn.com.ty.lift.common.utils.ValuePool; import cn.hutool.core.collection.IterUtil; import lombok.Data; import lombok.extern.slf4j.Slf4j; import org.springframework.jms.core.JmsMessagingTemplate; import org.springframework.messaging.support.GenericMessage; import java.io.Serializable; import java.time.LocalDate; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; /** * 推送消息 * * @author wcz * @since 2020/4/14 */ @Slf4j @Data public class PushMessage implements Serializable { private static final long serialVersionUID = 4125096758372084309L; private String title; private String content; private List toList; //the count of try again. Increase 1 for each failure, maximum times 100 private int tryCount = 0; private PushMessage() { } private PushMessage(String title, String content) { this.title = title; this.content = content; } private static PushMessage create(String title, String content) { return new PushMessage(title, content); } private static PushMessage team(String content) { return create("团队消息", content); } private static PushMessage work(String content) { return create("工作消息", content); } private static PushMessage maintain(String content) { return create("保养消息", content); } private static PushMessage emergency(String content) { return create("急修消息", content); } private static PushMessage manager(String content) { return create("提醒", content); } private static PushMessage inspection(String content) { return create("年检消息", content); } /** * PC * 所有文员 * 申请团队 * 【申请人】申请加入【团队名称】。 */ public static PushMessage teamApply(String applyName, String teamName) { String message = "%s申请加入%s。"; String content = String.format(message, applyName, teamName); return team(content); } /** * 移动端 * 区域主管、申请人 * 加入团队成功 * 【申请人】已经成功加入【团队名称】。 */ public static PushMessage teamJoin(String applyName, String teamName) { String message = "%s已经成功加入%s。"; String content = String.format(message, applyName, teamName); return team(content); } /** * 移动端 * 区域主管、被踢人 * 移出团队 * 【被踢人】已经被移出【团队名称】 */ public static PushMessage teamKickOut(String kickName, String teamName) { String message = "%s已经被踢出%s。"; String content = String.format(message, kickName, teamName); return team(content); } /** * PC/移动端 * 区域主管(项目所属)、所有文员 * 物业申请项目 * 物业【申请人】申请【项目名称】【评价/查看】权限。 */ public static PushMessage workApplyPermission(String applyName, String projectName, String permission) { String message = "物业%s申请%s的%s权限。"; String content = String.format(message, applyName, projectName, permission); return work(content); } /** * 移动端 * 区域主管(项目所属) * 物业获得权限 * 物业【申请人】成功获得【项目名称】【评价/查看】权限。 */ public static PushMessage workObtainPermission(String applyName, String projectName, String permission) { String message = "物业%s成功获得%s的%s权限。"; String content = String.format(message, applyName, projectName, permission); return work(content); } /** * 移动端 * 区域主管(项目所属) * 取消物业权限 * 物业【申请人】失去【项目名称】【评价/查看】权限。 */ public static PushMessage workAbolishPermission(String applyName, String projectName, String permission) { String message = "物业%s失去%s的%s权限。"; String content = String.format(message, applyName, projectName, permission); return work(content); } /** * PC/移动端 * 超管、区域主管(项目所属)、所有文员(项目所属) * 新增项目 * 【区域名称】新增【项目名称】项目,共计【台量】台,生效时间【生效时间】,区域主管【区域主管】。 */ public static PushMessage workAddProject(String areaName, String projectName, int num, String startDate, String directorName) { String message = "%s新增%s项目,共计%s台,生效时间%s,区域主管%s。"; String content = String.format(message, areaName, projectName, num, startDate, directorName); return work(content); } /** * PC/移动端 * 超管、区域主管(项目所属)、所有文员(项目所属) * 项目开始生效 * 【区域名称】【项目名称】项目进入服务期。 */ public static PushMessage workStartProject(String areaName, String projectName) { String message = "%s的%s项目进入服务期。"; String content = String.format(message, areaName, projectName); return work(content); } /** * PC/移动端 * 超管、区域主管(项目所属)、所有文员(项目所属) * 项目逾期 * 【区域名称】【项目名称】已经逾期,请尽快办理合同续签或停止服务手续。 */ public static PushMessage workProjectOverdue(String areaName, String projectName) { String message = "%s的%s已经逾期,请尽快办理合同续签或停止服务手续。"; String content = String.format(message, areaName, projectName); return work(content); } /** * PC/移动端 * 超管、区域主管(项目所属)、所有文员(项目所属) * 停止服务 * 【区域名称】【项目名称】已经停止服务,共计【台量】台。 */ public static PushMessage workProjectStopService(String areaName, String projectName, int num) { String message = "%s的%s已经停止服务,共计%s台。"; String content = String.format(message, areaName, projectName, num); return work(content); } /** * PC/移动端 * 超管、区域主管(项目所属)、所有文员(项目所属) * 恢复逾期 * 【区域名称】【项目名称】已经续签完毕。 */ public static PushMessage workProjectRecoverService(String areaName, String projectName) { String message = "%s的%s已经续签完毕。"; String content = String.format(message, areaName, projectName); return work(content); } /** * PC/移动端 * 超管、区域主管(项目所属)、所有文员(项目所属) * 区域更换负责人 * 【区域名称】的负责人,由【原区域主管】变更为【新区域主管】 */ public static PushMessage workReplaceRegionCharger(String areaName, String original, String newer) { String message = "%s的负责人,由%s变更为%s"; String content = String.format(message, areaName, original, newer); return work(content); } /** * PC/移动端 * 超管、区域主管(项目所属)、所有文员(项目所属) * 创建电梯 * 【创建人】为【项目名称】新增电梯位于【电梯位置】,注册代码【注册代码】 */ public static PushMessage workCreateLift(String operator, String projectName, String devicePosition, String registrationCode) { String message = "%s为%s新增电梯位于%s,注册代码%s"; String content = String.format(message, operator, projectName, devicePosition, registrationCode); return work(content); } /** * PC/移动端 * 超管、区域主管(项目所属)、所有文员(项目所属) * 更新电梯信息(除定位、更换负责人) * 【更新人】更新【项目名称】【电梯位置】的电梯信息,注册代码【注册代码】 */ public static PushMessage workModifyLift(String operator, String projectName, String devicePosition, String registrationCode) { String message = "%s更新%s的%s的电梯信息,注册代码%s"; String content = String.format(message, operator, projectName, devicePosition, registrationCode); return work(content); } /** * PC/移动端 * 超管、区域主管(项目所属)、所有文员(项目所属) * 更新电梯定位 * 【更新人】更新【项目名称】【电梯位置】的电梯定位为【电梯位置新】,注册代码【注册代码】 */ public static PushMessage workModifyLiftPosition(String operator, String projectName, String devicePosition, String newPosition, String registrationCode) { String message = "%s更新%s的%s的电梯定位为%s,注册代码%s"; String content = String.format(message, operator, projectName, devicePosition, newPosition, registrationCode); return work(content); } /** * PC/移动端 * 超管、区域主管(项目所属)、所有文员(项目所属)、相关维保工 * 电梯更换主要负责人 * 【区域名称】的【项目名称】的【电梯位置】电梯,【注册代码】,主要负责人由【原负责人】更换为【新负责人】。 */ public static PushMessage workReplaceLiftCharger(String areaName, String projectName, String devicePosition, String registrationCode, String original, String newer) { String message = "%s的%s的%s电梯,注册代码%s,主要负责人由%s更换为%s。"; String content = String.format(message, areaName, projectName, devicePosition, registrationCode, original, newer); return work(content); } //保养类型 1.半月,2.季度,3.半年,4.全年 private static String getMaintainType(int type) { switch (type) { case 1: return "半月保"; case 2: return "季度保"; case 3: return "半年保"; case 4: return "全年保"; default: return "未知类型"; } } /** * 移动端 * 区域主管、相关维保工 * 制定保养计划 * 维保计划制定:【区域名称】【项目名称】的【电梯位置】电梯,【注册代码】,保养间隔时间【x】天,下次保养时间【下次保养时间】,保养类型【保养类型】,负责人【电梯负责人】。制定人【操作人】 * 保养类型 1.半月,2.季度,3.半年,4.全年 */ public static PushMessage maintainCreatePlan(String areaName, String projectName, String devicePosition, String registrationCode, int interval, LocalDate planDate, int type, String liftCharge, String operator) { String message = "维保计划制定:%s%s的%s电梯,%s,保养间隔时间%s天,下次保养时间%tF,保养类型%s,负责人%s。制定人%s"; String content = String.format(message, areaName, projectName, devicePosition, registrationCode, interval, planDate, getMaintainType(type), liftCharge, operator); return maintain(content); } /** * 移动端 * 区域主管、相关维保工 * 修改保养计划 * 维保计划修改:【区域名称】【项目名称】的【电梯位置】电梯,【注册代码】,保养间隔时间【x】天,下次保养时间【下次保养时间】,保养类型【保养类型】,负责人【电梯负责人】。修改人【操作人】 */ public static PushMessage maintainModifyPlan(String areaName, String projectName, String devicePosition, String registrationCode, int interval, LocalDate planDate, int type, String liftCharge, String operator) { String message = "维保计划修改:%s%s的%s电梯,%s,保养间隔时间%s天,下次保养时间%tF,保养类型%s,负责人%s。修改人%s"; String content = String.format(message, areaName, projectName, devicePosition, registrationCode, interval, planDate, getMaintainType(type), liftCharge, operator); return maintain(content); } /** * 移动端 * 相关维保工 * 每天有维保任务 * 您今天有需要保养的电梯【x】台,请查看任务! */ public static PushMessage maintainHasTaskDaily(int num) { String message = "您今天有需要保养的电梯%s台,请查看任务!"; String content = String.format(message, num); return maintain(content); } private static String getTrappedDesc(int isTrapped) { return isTrapped == 1 ? "已" : "未"; } /** * 移动端 * 总经理、区域主管(项目所属)、相关维保工 * 急修指派 * 【区域名称】的【项目名称】的【电梯位置】电梯,注册代码【注册代码】,于【报修时间】接到召修信息,【已/未】困人,请【被派单人】立即响应。 */ public static PushMessage emergencyAssign(String areaName, String projectName, String devicePosition, String registrationCode, LocalDateTime callerDate, int isTrapped, String callerFaultDescription, String workerName) { String message = "%s的%s的%s电梯,注册代码%s,于%tF %tT接到召修信息,%s困人,召修描述:%s,请%s立即响应。"; String content = String.format(message, areaName, projectName, devicePosition, registrationCode, callerDate, callerDate, getTrappedDesc(isTrapped), callerFaultDescription, workerName); return emergency(content); } /** * PC/移动端 * 总经理、区域主管(项目所属)、所有文员(项目所属)、相关维保工 * 物业发起急修 * 【区域名称】的【项目名称】的【电梯位置】电梯,注册代码【注册代码】,物业端于【报修时间】发出召修信息,【已/未】困人,请【电梯主要负责人】立即响应。 */ public static PushMessage emergencyAssignByProperty(String areaName, String projectName, String devicePosition, String registrationCode, LocalDateTime callerDate, int isTrapped, String callerFaultDescription, String workerName) { String message = "%s的%s的%s电梯,注册代码%s,物业端于%tF %tT发出召修信息,%s困人,召修描述:%s,请%s立即响应。"; String content = String.format(message, areaName, projectName, devicePosition, registrationCode, callerDate, callerDate, getTrappedDesc(isTrapped), callerFaultDescription, workerName); return emergency(content); } /** * 移动端 * 总经理、区域主管(项目所属)、相关维保工 * 转派 * 【区域名称】的【项目名称】的【电梯位置】电梯,注册代码【注册代码】,物业端于【报修时间】发出召修信息,【已/未】困人,请【被派单人】立即响应。 * 【原被派单人】:【区域名称】的【项目名称】的【电梯位置】电梯,注册代码【注册代码】,急修信息已经转派给【被派单人】。 */ public static PushMessage emergencyTransfer(String areaName, String projectName, String devicePosition, String registrationCode, LocalDateTime callerDate, int isTrapped, String callerFaultDescription, String workerName) { String message = "%s的%s的%s电梯,注册代码%s,物业端于%tF %tT发出召修信息,%s困人,召修描述:%s,请%s立即响应。"; String content = String.format(message, areaName, projectName, devicePosition, registrationCode, callerDate, callerDate, getTrappedDesc(isTrapped), callerFaultDescription, workerName); return emergency(content); } /** * 移动端 * 【原被派单人】收到消息:【区域名称】的【项目名称】的【电梯位置】电梯,注册代码【注册代码】,急修信息已经转派给【被派单人】。 */ public static PushMessage emergencyTransferForOriginal(String areaName, String projectName, String devicePosition, String registrationCode, String workerName) { String message = "%s的%s的%s电梯,注册代码%s,急修信息已经转派给%s。"; String content = String.format(message, areaName, projectName, devicePosition, registrationCode, workerName); return emergency(content); } /** * PC/移动端 * 总经理、区域主管(项目所属)、所有文员(项目所属) * 维保工接收急修通知 * 【区域名称】的【项目名称】的【电梯位置】电梯,注册代码【注册代码】,于【报修时间】接到召修信息,维保工已确认。 */ public static PushMessage emergencyTaking(String areaName, String projectName, String devicePosition, String registrationCode, LocalDateTime callerDate) { String message = "%s的%s的%s电梯,注册代码%s,于%tF %tT接到召修信息,维保工已接收通知。"; String content = String.format(message, areaName, projectName, devicePosition, registrationCode, callerDate, callerDate); return emergency(content); } /** * PC/移动端 * 总经理、区域主管(项目所属)、所有文员(项目所属) * 维保工到达现场 * 【区域名称】的【项目名称】的【电梯位置】电梯,注册代码【注册代码】,于【报修时间】接到召修信息,维保工已于【到达时间】到达现场。 */ public static PushMessage emergencyArrive(String areaName, String projectName, String devicePosition, String registrationCode, LocalDateTime callerDate, LocalDateTime arriveTime) { String message = "%s的%s的%s电梯,注册代码%s,于%tF %tT接到召修信息,维保工已于%tF %tT到达现场。"; String content = String.format(message, areaName, projectName, devicePosition, registrationCode, callerDate, callerDate, arriveTime, arriveTime); return emergency(content); } /** * PC/移动端 * 总经理、区域主管(项目所属)、所有文员(项目所属) * 维保工提交急修单 * 【区域名称】的【项目名称】的【电梯位置】电梯,注册代码【注册代码】,于【报修时间】接到召修信息,电梯已于【恢复时间】恢复正常。 */ public static PushMessage emergencyOrder(String areaName, String projectName, String devicePosition, String registrationCode, LocalDateTime callerDate, LocalDateTime recoveryDate) { String message = "%s的%s的%s电梯,注册代码%s,于%tF %tT接到召修信息,电梯已于%tF %tT恢复正常。"; String content = String.format(message, areaName, projectName, devicePosition, registrationCode, callerDate, callerDate, recoveryDate, recoveryDate); return emergency(content); } /** * PC/移动端 * 所有人 * 公司发送公告 * 有一条公司公告,请查收 */ public static PushMessage announcementNotice() { return create("公司公告", "有一条公司公告,请查收"); } /** * PC * 所有文员 * 早上8点 * 即时提醒:今天计划有X台电梯需保养,X台电梯正在维修中。 */ public static PushMessage managerMaintainDaily(int needs, int doings) { String message = "即时提醒:今天计划有%s台电梯需保养,%s台电梯正在维修中。"; String content = String.format(message, needs, doings); return manager(content); } /** * 移动端 * 区域主管(项目所属) * 下午4点 * 即时提醒:【区域名称】今天共发生急修X次,已维修完毕X次,X次仍在处理中;X台电梯计划保养未完成。 */ public static PushMessage managerTaskForRegionChargerDaily(String areaName, int total, int finish, int doings, int todos) { String message = "即时提醒:%s今天共发生急修%s次,已维修完毕%s次,%s次仍在处理中;%s台电梯计划保养未完成。"; String content = String.format(message, areaName, total, finish, doings, todos); return manager(content); } /** * 移动端 * 总经理 * 下午4点 * 即时提醒:今天共发生急修X次,已维修完毕X次,X次仍在处理中;X台电梯计划保养未完成。 */ public static PushMessage managerTaskForLeaderDaily(String areaName, int total, int finish, int doings, int todos) { String message = "即时提醒:%s今天共发生急修%s次,已维修完毕%s次,%s次仍在处理中;%s台电梯计划保养未完成。"; String content = String.format(message, areaName, total, finish, doings, todos); return manager(content); } /** * 移动端 * 总经理,区域主管(项目所属) * 晚上8点 * 日报:截止目前,今天应保养X台,已完成X台,X台即将超期;今天共发起急修X起,已处理完成X起,X起正在处理中。 */ public static PushMessage managerReportDaily(int needs, int finish, int overdue, int totalRepair, int finishRepair, int doingRepair) { String message = "日报:截止目前,今天应保养%s台,已完成%s台,%s台即将超期;今天共发起急修%s起,已处理完成%s起,%s起正在处理中。"; String content = String.format(message, needs, finish, overdue, totalRepair, finishRepair, doingRepair); return manager(content); } /** * PC/移动端 * 区域主管(项目所属),文员(所属文员),电梯主要负责人 * 年检到期前45天 * 【项目名称】的【电梯位置】电梯,注册代码【注册代码】,将于45日后年检到期。 */ public static PushMessage inspectionAdvance45daysNotice(String projectName, String devicePosition, String registrationCode) { String message = "%s的%s电梯,注册代码%s,将于45日后年检到期。"; String content = String.format(message, projectName, devicePosition, registrationCode); return inspection(content); } /** * PC/移动端 * 区域主管(项目所属),文员(所属文员),电梯主要负责人 * 年检到期前15天 * 【项目名称】的【电梯位置】电梯,注册代码【注册代码】,仍未启动年检,将于15日后年检到期。 */ public static PushMessage inspectionAdvance15daysNotice(String projectName, String devicePosition, String registrationCode) { String message = "%s的%s电梯,注册代码%s,仍未启动年检,将于15日后年检到期。"; String content = String.format(message, projectName, devicePosition, registrationCode); return inspection(content); } /** * PC/移动端 * 区域主管(项目所属),电梯负责人 * 确认现场检验时间 * 【项目名称】的【电梯位置】电梯,注册代码【注册代码】,已确认现场检验时间为【现场检验时间】。 */ public static PushMessage inspectionConfirmCheckDate(String projectName, String devicePosition, String registrationCode, LocalDate checkDate) { String message = "%s的%s电梯,注册代码%s,已确认现场检验时间为%tF。"; String content = String.format(message, projectName, devicePosition, registrationCode, checkDate); return inspection(content); } /** * 移动端 * 所有人 * 【新闻标题】 */ public static PushMessage newsNotice(String title) { return create("发布新闻", title); } public boolean needSplit() { return toList != null && toList.size() > ValuePool.PUSH_MAX_SIZE; } public List> doSplit(final int length) { List> splits = new ArrayList<>(); int size = toList.size(); log.info("the size of toList is {}, need to split.", size); //0 1000 2000 for (int i = 0; i < size; i += length) { if (i + length > size) { splits.add(new ArrayList<>(toList.subList(i, size))); } else { splits.add(new ArrayList<>(toList.subList(i, i + length))); } } log.info("the size of splits : {}", splits.size()); return splits; } /** * 同时推送到android和ios的指定设备token * * @param jmsMessagingTemplate jms * @param toAndroid 推到安卓平台的Token列表 * @param toIos 推到ios平台的Token列表 */ public boolean sendTokenOnPlatform(JmsMessagingTemplate jmsMessagingTemplate, List toAndroid, List toIos) { try { if (IterUtil.isNotEmpty(toAndroid)) { this.setToList(toAndroid); jmsMessagingTemplate.send(ValuePool.QUEUE_ANDROID_TOKEN, new GenericMessage<>(this)); } else if (IterUtil.isNotEmpty(toIos)) { this.setToList(toIos); jmsMessagingTemplate.send(ValuePool.QUEUE_IOS_TOKEN, new GenericMessage<>(this)); } else { return false; } return true; } catch (Exception e) { log.error("Failed to Send pushMessage to ANDROID & IOS TOKEN Message Queue: ", e); return false; } } /** * 同时推送android和ios全平台 * * @param jmsMessagingTemplate jms */ public boolean sendAllOnPlatform(JmsMessagingTemplate jmsMessagingTemplate) { try { jmsMessagingTemplate.send(ValuePool.QUEUE_ANDROID_ALL, new GenericMessage<>(this)); jmsMessagingTemplate.send(ValuePool.QUEUE_IOS_ALL, new GenericMessage<>(this)); return true; } catch (Exception e) { log.error("Failed to Send pushMessage to ANDROID & IOS ALL Message Queue: ", e); return false; } } /** * 只推送到android平台的指定设备token * * @param jmsMessagingTemplate jms * @param toList 推到安卓平台的设备token */ public boolean sendTokenOnAndroid(JmsMessagingTemplate jmsMessagingTemplate, List toList) { try { if (IterUtil.isEmpty(toList)) { return false; } this.setToList(toList); jmsMessagingTemplate.send(ValuePool.QUEUE_ANDROID_TOKEN, new GenericMessage<>(this)); return true; } catch (Exception e) { log.error("Failed to Send pushMessage to ANDROID_TOKEN Message Queue: ", e); return false; } } /** * 只推送到ios的指定设备token * @param jmsMessagingTemplate * @param toList ios设备token * @return */ public boolean sendTokenOnIos(JmsMessagingTemplate jmsMessagingTemplate, List toList) { try { if (IterUtil.isEmpty(toList)) { return false; } this.setToList(toList); jmsMessagingTemplate.send(ValuePool.QUEUE_IOS_TOKEN, new GenericMessage<>(this)); return true; } catch (Exception e) { log.error("Failed to Send pushMessage to IOS_TOKEN Message Queue: ", e); return false; } } }