消息推送初始化
diff --git a/backend/src/main/java/com/supwisdom/dlpay/api/bean/KafkaXgMessage.java b/backend/src/main/java/com/supwisdom/dlpay/api/bean/KafkaXgMessage.java
new file mode 100644
index 0000000..1378bcf
--- /dev/null
+++ b/backend/src/main/java/com/supwisdom/dlpay/api/bean/KafkaXgMessage.java
@@ -0,0 +1,103 @@
+package com.supwisdom.dlpay.api.bean;
+
+public class KafkaXgMessage {
+
+ private String title;//提醒标题
+ private String content;//提醒消息内容
+ private String gids;//gid发送列表,逗号隔开
+ private Boolean alltarget;//是否平台全发送
+ private String platform;//android,ios,all
+ private int type;//TYPE_NOTIFICATION = 1,TYPE_MESSAGE = 2
+
+ private String expiretime;//过期时间
+ private Boolean callback;//是否回调返回
+ private int retries;//最多重试次数
+ private String custom; //扩展参数,原样传递
+
+ //TODO: 下面的参数在epaymessager中已不用,要赋值请放入custom的json串中
+// private String url;//跳转url
+// private String msg_type;//提醒类型 字典 epay_pos_scan_code_pay、
+// private String refno;//流水参考号
+// private String amount;//消费金额,元,小数点后两位
+
+
+ public String getTitle() {
+ return title;
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ public String getContent() {
+ return content;
+ }
+
+ public void setContent(String content) {
+ this.content = content;
+ }
+
+ public String getGids() {
+ return gids;
+ }
+
+ public void setGids(String gids) {
+ this.gids = gids;
+ }
+
+ public Boolean getAlltarget() {
+ return alltarget;
+ }
+
+ public void setAlltarget(Boolean alltarget) {
+ this.alltarget = alltarget;
+ }
+
+ public String getPlatform() {
+ return platform;
+ }
+
+ public void setPlatform(String platform) {
+ this.platform = platform;
+ }
+
+ public int getType() {
+ return type;
+ }
+
+ public void setType(int type) {
+ this.type = type;
+ }
+
+ public String getExpiretime() {
+ return expiretime;
+ }
+
+ public void setExpiretime(String expiretime) {
+ this.expiretime = expiretime;
+ }
+
+ public Boolean getCallback() {
+ return callback;
+ }
+
+ public void setCallback(Boolean callback) {
+ this.callback = callback;
+ }
+
+ public int getRetries() {
+ return retries;
+ }
+
+ public void setRetries(int retries) {
+ this.retries = retries;
+ }
+
+ public String getCustom() {
+ return custom;
+ }
+
+ public void setCustom(String custom) {
+ this.custom = custom;
+ }
+}
diff --git a/backend/src/main/java/com/supwisdom/dlpay/portal/dao/impl/MsgTemplateRepositoryImpl.java b/backend/src/main/java/com/supwisdom/dlpay/portal/dao/impl/MsgTemplateRepositoryImpl.java
new file mode 100644
index 0000000..f6efb5b
--- /dev/null
+++ b/backend/src/main/java/com/supwisdom/dlpay/portal/dao/impl/MsgTemplateRepositoryImpl.java
@@ -0,0 +1,37 @@
+package com.supwisdom.dlpay.portal.dao.impl;
+
+import com.supwisdom.dlpay.framework.jpa.BaseRepository;
+import com.supwisdom.dlpay.framework.jpa.Finder;
+import com.supwisdom.dlpay.framework.jpa.page.Pagination;
+import com.supwisdom.dlpay.framework.util.StringUtil;
+import com.supwisdom.dlpay.portal.bean.MsgTemplateSearchBean;
+import com.supwisdom.dlpay.portal.dao.MsgTemplateRepository;
+import com.supwisdom.dlpay.portal.domain.TBMsgTemplate;
+import org.hibernate.transform.Transformers;
+import org.jetbrains.annotations.NotNull;
+
+public class MsgTemplateRepositoryImpl extends BaseRepository implements MsgTemplateRepository {
+ @NotNull
+ @Override
+ public Pagination getMsgTemplateList(@NotNull MsgTemplateSearchBean bean) {
+ String title = bean.getTitle();
+ String content = bean.getContent();
+ int pageno = bean.getPageno();
+ int pagesize = bean.getPagesize();
+ StringBuilder sql = new StringBuilder("select * from tb_msg_template where 1=1");
+ if (!StringUtil.isEmpty(title)) {
+ sql.append(" and title like :title");
+ }
+ if (!StringUtil.isEmpty(content)) {
+ sql.append(" and content like :content");
+ }
+ Finder f = Finder.create(sql.toString());
+ if (!StringUtil.isEmpty(title)) {
+ f.setParameter("title", "%" + title.trim() + "%");
+ }
+ if (!StringUtil.isEmpty(content)) {
+ f.setParameter("content", "%" + content.trim() + "%");
+ }
+ return findNative(f, Transformers.aliasToBean(TBMsgTemplate.class), pageno, pagesize);
+ }
+}
diff --git a/backend/src/main/java/com/supwisdom/dlpay/portal/domain/TBAnnex.java b/backend/src/main/java/com/supwisdom/dlpay/portal/domain/TBAnnex.java
index 2679855..729cc71 100644
--- a/backend/src/main/java/com/supwisdom/dlpay/portal/domain/TBAnnex.java
+++ b/backend/src/main/java/com/supwisdom/dlpay/portal/domain/TBAnnex.java
@@ -5,7 +5,9 @@
import javax.persistence.*;
@Entity
-@Table(name = "tb_annex")
+@Table(name = "tb_annex",indexes = {
+ @Index(name = "annex_idx",columnList = "fbid")
+})
public class TBAnnex {
@Id
@GenericGenerator(name = "idGenerator", strategy = "uuid")
diff --git a/backend/src/main/java/com/supwisdom/dlpay/portal/domain/TBFeedback.java b/backend/src/main/java/com/supwisdom/dlpay/portal/domain/TBFeedback.java
index 951b947..00db202 100644
--- a/backend/src/main/java/com/supwisdom/dlpay/portal/domain/TBFeedback.java
+++ b/backend/src/main/java/com/supwisdom/dlpay/portal/domain/TBFeedback.java
@@ -6,7 +6,9 @@
import java.util.List;
@Entity
-@Table(name = "tb_feedback")
+@Table(name = "tb_feedback",
+ indexes = {@Index(name = "feedback_idx1",columnList = "userid"),
+ @Index(name = "feedback_idx2",columnList = "fbtime,replystatus")})
public class TBFeedback {
@Id
@GenericGenerator(name = "idGenerator", strategy = "uuid")
diff --git a/backend/src/main/java/com/supwisdom/dlpay/portal/domain/TBMsgTemplate.java b/backend/src/main/java/com/supwisdom/dlpay/portal/domain/TBMsgTemplate.java
new file mode 100644
index 0000000..a15da35
--- /dev/null
+++ b/backend/src/main/java/com/supwisdom/dlpay/portal/domain/TBMsgTemplate.java
@@ -0,0 +1,67 @@
+package com.supwisdom.dlpay.portal.domain;
+
+import org.hibernate.annotations.GenericGenerator;
+
+import javax.persistence.*;
+
+@Entity
+@Table(name = "tb_msg_template")
+public class TBMsgTemplate {
+ @Id
+ @GenericGenerator(name = "idGenerator", strategy = "uuid")
+ @GeneratedValue(generator = "idGenerator")
+ @Column(name = "id", nullable = false, length = 32)
+ private String id;
+
+ @Column(name = "title", nullable = false, length = 30)
+ private String title;
+
+ @Column(name = "content", nullable = false, length = 200)
+ private String content;
+
+ @Column(name = "updatetime", length = 14)
+ private String updatetime;
+
+ @Column(name = "operid", length = 32)
+ private String operid;
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ public String getContent() {
+ return content;
+ }
+
+ public void setContent(String content) {
+ this.content = content;
+ }
+
+ public String getUpdatetime() {
+ return updatetime;
+ }
+
+ public void setUpdatetime(String updatetime) {
+ this.updatetime = updatetime;
+ }
+
+ public String getOperid() {
+ return operid;
+ }
+
+ public void setOperid(String operid) {
+ this.operid = operid;
+ }
+}
diff --git a/backend/src/main/java/com/supwisdom/dlpay/portal/domain/TBReply.java b/backend/src/main/java/com/supwisdom/dlpay/portal/domain/TBReply.java
index 4a65054..5fe72b9 100644
--- a/backend/src/main/java/com/supwisdom/dlpay/portal/domain/TBReply.java
+++ b/backend/src/main/java/com/supwisdom/dlpay/portal/domain/TBReply.java
@@ -5,7 +5,9 @@
import javax.persistence.*;
@Entity
-@Table(name = "tb_reply")
+@Table(name = "tb_reply",indexes = {
+ @Index(name = "reply_idx",columnList = "fbid")
+})
public class TBReply {
@Id
@GenericGenerator(name = "idGenerator", strategy = "uuid")
diff --git a/backend/src/main/kotlin/com/supwisdom/dlpay/api/async_tasks.kt b/backend/src/main/kotlin/com/supwisdom/dlpay/api/async_tasks.kt
new file mode 100644
index 0000000..63591dc
--- /dev/null
+++ b/backend/src/main/kotlin/com/supwisdom/dlpay/api/async_tasks.kt
@@ -0,0 +1,38 @@
+package com.supwisdom.dlpay.api
+
+import mu.KotlinLogging
+import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler
+import org.springframework.context.annotation.Bean
+import org.springframework.context.annotation.Configuration
+import org.springframework.scheduling.annotation.AsyncConfigurer
+import org.springframework.scheduling.annotation.EnableAsync
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor
+import java.lang.reflect.Method
+import java.util.concurrent.Executor
+
+@Configuration
+@EnableAsync
+class SpringAsyncConfig : AsyncConfigurer {
+
+ @Bean(name = ["kafkaSendMessageAsyncTask"])
+ fun kafkaSendMessageAsyncTaskExecutor(): Executor {
+ return ThreadPoolTaskExecutor().apply {
+ corePoolSize = 20
+ maxPoolSize = 100
+ setWaitForTasksToCompleteOnShutdown(true)
+ }
+ }
+
+ override fun getAsyncUncaughtExceptionHandler(): AsyncUncaughtExceptionHandler? {
+ return MyAsyncUncaughtExceptionHandler()
+ }
+}
+
+class MyAsyncUncaughtExceptionHandler : AsyncUncaughtExceptionHandler {
+ private val logger = KotlinLogging.logger { }
+ override fun handleUncaughtException(ex: Throwable, method: Method, vararg params: Any?) {
+ logger.error { "Async Task execute error: <${method.name}>, exception <${ex.message}>" }
+ }
+}
+
+
diff --git a/backend/src/main/kotlin/com/supwisdom/dlpay/api/service/impl/kafka_service_impl.kt b/backend/src/main/kotlin/com/supwisdom/dlpay/api/service/impl/kafka_service_impl.kt
new file mode 100644
index 0000000..7e35c90
--- /dev/null
+++ b/backend/src/main/kotlin/com/supwisdom/dlpay/api/service/impl/kafka_service_impl.kt
@@ -0,0 +1,77 @@
+package com.supwisdom.dlpay.api.service.impl
+
+import com.google.gson.Gson
+import com.supwisdom.dlpay.api.bean.KafkaXgMessage
+import com.supwisdom.dlpay.api.service.KafkaSendMsgService
+import com.supwisdom.dlpay.framework.util.DateUtil
+import com.supwisdom.dlpay.framework.util.TradeDict
+import com.supwisdom.dlpay.mobile.dao.MsgDao
+import com.supwisdom.dlpay.mobile.domain.TBMsg
+import com.supwisdom.dlpay.mobile.service.MobileApiService
+import mu.KotlinLogging
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.kafka.core.KafkaTemplate
+import org.springframework.scheduling.annotation.Async
+import org.springframework.stereotype.Service
+
+@Service
+class KafkaSendMsgServiceImpl : KafkaSendMsgService {
+ val logger = KotlinLogging.logger { }
+ @Autowired
+ private lateinit var kafkaTemplate: KafkaTemplate<String, String>
+ @Autowired
+ private lateinit var msgDao: MsgDao
+ @Autowired
+ private lateinit var mobileApiService: MobileApiService
+
+ val gson = Gson()
+
+ val topic = "jpush-messages"
+
+ @Async("kafkaSendMessageAsyncTask")
+ override fun sendJpushMessage(userid: String, title: String, content: String, refno: String, extras: MutableMap<String, String>, tenantId: String?) {
+ val musers = mobileApiService.findByUseridAndStatus(userid, TradeDict.STATUS_NORMAL)
+ var msg = TBMsg().apply {
+ this.content = content
+ this.title = title
+ this.refno = refno
+ this.userid = userid
+ this.lastupdate = DateUtil.getNow()
+ this.refno = refno
+ this.extras = gson.toJson(extras)
+ }
+ if (musers == null || musers.isEmpty()) {
+ msg.pushresult = "没有手机用户,消息未推送"
+ msgDao.save(msg)
+ return
+ }
+ msg = msgDao.save(msg)
+ var uids = ""
+ musers.forEach {
+ uids += "${it.uid},"
+ var platform = "android"
+ if ("ios".equals(it.lastloginplatform, true)) {
+ platform = "ios"
+ }
+ val message = KafkaXgMessage()
+ message.alltarget = false
+ message.callback = true
+ message.content = msg.content
+ message.title = msg.title
+ message.platform = platform
+ message.retries = 3
+ extras["refno"] = refno
+ message.custom = gson.toJson(extras)
+ message.expiretime = DateUtil.getNewTime(DateUtil.getNow(), 300)
+ message.gids = it.uid
+ if (it.lastloginplatform.isNullOrEmpty()) {
+ message.platform = "all"
+ kafkaTemplate.send(topic, msg.msgid, gson.toJson(message))
+ } else {
+ kafkaTemplate.send(topic, msg.msgid, gson.toJson(message))
+ }
+ }
+ msg.pusheduids = uids
+ msgDao.save(msg)
+ }
+}
diff --git a/backend/src/main/kotlin/com/supwisdom/dlpay/api/service/kafka_service.kt b/backend/src/main/kotlin/com/supwisdom/dlpay/api/service/kafka_service.kt
new file mode 100644
index 0000000..66d3f20
--- /dev/null
+++ b/backend/src/main/kotlin/com/supwisdom/dlpay/api/service/kafka_service.kt
@@ -0,0 +1,35 @@
+package com.supwisdom.dlpay.api.service
+
+import com.supwisdom.dlpay.mobile.dao.MsgDao
+import mu.KotlinLogging
+import org.apache.kafka.clients.consumer.ConsumerRecord
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.kafka.annotation.KafkaListener
+import org.springframework.stereotype.Component
+
+interface KafkaSendMsgService {
+ fun sendJpushMessage(userid: String, title: String, content: String, refno: String, extras: MutableMap<String, String>, tenantId: String?)
+}
+
+@Component
+class KafkaMsgListener {
+ val logger = KotlinLogging.logger { }
+ @Autowired
+ private lateinit var msgDao: MsgDao
+
+ @KafkaListener(topics = ["jpush-messages-result"],
+ autoStartup = "\${spring.kafka.listen.auto.start:true}",
+ groupId = "0")
+ fun listen(record: ConsumerRecord<String, String>) {
+ logger.debug { "${record.key()},${record.value()}" }
+ if (!record.key().isNullOrEmpty()) {
+ val opt = msgDao.findById(record.key())
+ if (opt.isPresent) {
+ val msg = opt.get()
+ msg.pushresult = record.value()
+ msgDao.save(msg)
+ return
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/backend/src/main/kotlin/com/supwisdom/dlpay/portal/PortalApi.kt b/backend/src/main/kotlin/com/supwisdom/dlpay/portal/PortalApi.kt
index 50f52a3..089c1a5 100644
--- a/backend/src/main/kotlin/com/supwisdom/dlpay/portal/PortalApi.kt
+++ b/backend/src/main/kotlin/com/supwisdom/dlpay/portal/PortalApi.kt
@@ -7,9 +7,14 @@
import com.supwisdom.dlpay.framework.service.OperatorDetailService
import com.supwisdom.dlpay.framework.service.SystemUtilService
import com.supwisdom.dlpay.framework.util.StringUtil
+import com.supwisdom.dlpay.mobile.domain.TBMsg
import com.supwisdom.dlpay.portal.bean.FeedbackSearchBean
+import com.supwisdom.dlpay.portal.bean.MsgTemplateSearchBean
+import com.supwisdom.dlpay.portal.bean.SendMsgBean
+import com.supwisdom.dlpay.portal.domain.TBMsgTemplate
import com.supwisdom.dlpay.portal.domain.TBReply
import com.supwisdom.dlpay.portal.service.FeedbackService
+import com.supwisdom.dlpay.portal.service.MsgService
import com.supwisdom.dlpay.portal.util.PortalConstant
import mu.KotlinLogging
import org.jose4j.jwt.ReservedClaimNames
@@ -32,6 +37,8 @@
lateinit var apiJwtRepository: ApiJwtRepository
@Autowired
lateinit var systemUtilService: SystemUtilService
+ @Autowired
+ lateinit var msgService: MsgService
val logger = KotlinLogging.logger { }
@RequestMapping("/test")
@@ -40,7 +47,7 @@
}
@RequestMapping("user/logout")
- fun logout(@RequestHeader("Authorization") auth: String?): ResponseEntity<Any>{
+ fun logout(@RequestHeader("Authorization") auth: String?): ResponseEntity<Any> {
if (auth == null) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build()
}
@@ -111,8 +118,8 @@
}
}
- @RequestMapping(value= ["/feedback/reply/save"],method = [RequestMethod.POST])
- fun saveFeedbackReply(@RequestBody reply:TBReply): JsonResult? {
+ @RequestMapping(value = ["/feedback/reply/save"], method = [RequestMethod.POST])
+ fun saveFeedbackReply(@RequestBody reply: TBReply): JsonResult? {
return try {
val p = SecurityContextHolder.getContext().authentication
val oper = operatorDetailService.findByOperid(p.name)
@@ -128,4 +135,43 @@
JsonResult.error("保存留言回复异常")
}
}
+
+ @RequestMapping("/template/list")
+ fun getMsgTemplateList(bean: MsgTemplateSearchBean): JsonResult? {
+ return try {
+ val page = msgService.getMsgTemplateList(bean)
+ if (page.list == null || page.list.size == 0) {
+ return JsonResult.ok().put("msg", "无数据")
+ }
+ return JsonResult.ok().put("page", page)
+ } catch (e: Exception) {
+ logger.error { e.message }
+ JsonResult.error("查询消息模板列表异常")
+ }
+ }
+
+ @RequestMapping(value = ["/template/save"],method = [RequestMethod.POST])
+ fun saveMsgTemplate(@RequestBody template:TBMsgTemplate):JsonResult?{
+ return try {
+ val p = SecurityContextHolder.getContext().authentication
+ val oper = operatorDetailService.findByOperid(p.name)
+ template.operid = oper.operid
+ msgService.saveMsgTemplate(template)
+ return JsonResult.ok()
+ } catch (e: Exception) {
+ logger.error { e.message }
+ JsonResult.error("保存消息推送模板异常")
+ }
+ }
+
+ @RequestMapping(value = ["/template/sendmsg"],method = [RequestMethod.POST])
+ fun sendMsg(@RequestBody bean: SendMsgBean):JsonResult?{
+ return try {
+ msgService.sendMsg(bean)
+ return JsonResult.ok()
+ } catch (e: Exception) {
+ logger.error { e.message }
+ JsonResult.error(e.message)
+ }
+ }
}
\ No newline at end of file
diff --git a/backend/src/main/kotlin/com/supwisdom/dlpay/portal/bean/MsgTemplateSearchBean.kt b/backend/src/main/kotlin/com/supwisdom/dlpay/portal/bean/MsgTemplateSearchBean.kt
new file mode 100644
index 0000000..0b3ca4a
--- /dev/null
+++ b/backend/src/main/kotlin/com/supwisdom/dlpay/portal/bean/MsgTemplateSearchBean.kt
@@ -0,0 +1,8 @@
+package com.supwisdom.dlpay.portal.bean
+
+class MsgTemplateSearchBean {
+ var title: String = ""
+ var content: String = ""
+ var pageno: Int = 0
+ var pagesize: Int = 10
+}
\ No newline at end of file
diff --git a/backend/src/main/kotlin/com/supwisdom/dlpay/portal/bean/SendMsgBean.kt b/backend/src/main/kotlin/com/supwisdom/dlpay/portal/bean/SendMsgBean.kt
new file mode 100644
index 0000000..de40251
--- /dev/null
+++ b/backend/src/main/kotlin/com/supwisdom/dlpay/portal/bean/SendMsgBean.kt
@@ -0,0 +1,8 @@
+package com.supwisdom.dlpay.portal.bean
+
+class SendMsgBean {
+ var templateid: String = ""
+ var userid: String = ""
+ var refno: String = ""
+ var data: Map<String,String> = HashMap()
+}
\ No newline at end of file
diff --git a/backend/src/main/kotlin/com/supwisdom/dlpay/portal/dao/MsgTemplateDao.kt b/backend/src/main/kotlin/com/supwisdom/dlpay/portal/dao/MsgTemplateDao.kt
new file mode 100644
index 0000000..2c5f093
--- /dev/null
+++ b/backend/src/main/kotlin/com/supwisdom/dlpay/portal/dao/MsgTemplateDao.kt
@@ -0,0 +1,10 @@
+package com.supwisdom.dlpay.portal.dao
+
+import com.supwisdom.dlpay.portal.domain.TBMsgTemplate
+import org.springframework.data.jpa.repository.JpaRepository
+import org.springframework.stereotype.Repository
+
+@Repository
+interface MsgTemplateDao : JpaRepository<TBMsgTemplate, String>,MsgTemplateRepository {
+
+}
\ No newline at end of file
diff --git a/backend/src/main/kotlin/com/supwisdom/dlpay/portal/dao/MsgTemplateRepository.kt b/backend/src/main/kotlin/com/supwisdom/dlpay/portal/dao/MsgTemplateRepository.kt
new file mode 100644
index 0000000..f6ca359
--- /dev/null
+++ b/backend/src/main/kotlin/com/supwisdom/dlpay/portal/dao/MsgTemplateRepository.kt
@@ -0,0 +1,8 @@
+package com.supwisdom.dlpay.portal.dao
+
+import com.supwisdom.dlpay.framework.jpa.page.Pagination
+import com.supwisdom.dlpay.portal.bean.MsgTemplateSearchBean
+
+interface MsgTemplateRepository {
+ fun getMsgTemplateList(bean: MsgTemplateSearchBean): Pagination
+}
\ No newline at end of file
diff --git a/backend/src/main/kotlin/com/supwisdom/dlpay/portal/service/Impl/MsgServiceImpl.kt b/backend/src/main/kotlin/com/supwisdom/dlpay/portal/service/Impl/MsgServiceImpl.kt
new file mode 100644
index 0000000..0c59f94
--- /dev/null
+++ b/backend/src/main/kotlin/com/supwisdom/dlpay/portal/service/Impl/MsgServiceImpl.kt
@@ -0,0 +1,62 @@
+package com.supwisdom.dlpay.portal.service.Impl
+
+import com.supwisdom.dlpay.api.service.KafkaSendMsgService
+import com.supwisdom.dlpay.framework.jpa.page.Pagination
+import com.supwisdom.dlpay.framework.service.SystemUtilService
+import com.supwisdom.dlpay.mobile.dao.MsgDao
+import com.supwisdom.dlpay.portal.bean.MsgTemplateSearchBean
+import com.supwisdom.dlpay.portal.bean.SendMsgBean
+import com.supwisdom.dlpay.portal.dao.MsgTemplateDao
+import com.supwisdom.dlpay.portal.domain.TBMsgTemplate
+import com.supwisdom.dlpay.portal.service.MsgService
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.stereotype.Service
+import java.lang.RuntimeException
+import java.util.regex.Pattern
+
+@Service
+class MsgServiceImpl : MsgService {
+ @Autowired
+ lateinit var msgTemplateDao: MsgTemplateDao
+ @Autowired
+ lateinit var msgDao: MsgDao
+ @Autowired
+ lateinit var systemUtilService: SystemUtilService
+ @Autowired
+ lateinit var kafkaSendMsgService: KafkaSendMsgService
+
+ override fun getMsgTemplateList(bean: MsgTemplateSearchBean): Pagination {
+ return msgTemplateDao.getMsgTemplateList(bean)
+ }
+
+ override fun saveMsgTemplate(template: TBMsgTemplate) {
+ template.updatetime = systemUtilService.sysdatetime.hostdatetime
+ msgTemplateDao.save(template)
+ }
+
+ override fun sendMsg(bean: SendMsgBean) {
+ val optional = msgTemplateDao.findById(bean.templateid)
+ if (optional.isPresent) {
+ val template = optional.get()
+ var content = template.content
+ val data = bean.data
+ //正则匹配所有${xx}
+ val pattern: Pattern = Pattern.compile("\\$\\{[\\w]*}")
+ val matcher = pattern.matcher(content)
+ while (matcher.find()) {
+ val source = matcher.group()
+ //截取${}括号中的内容
+ val param = source.substring(2, source.length - 1)
+ if (data.containsKey(param)) {
+ val value = data[param].toString()
+ content = content.replace(source, value)
+ } else {
+ throw RuntimeException("未设置参数<${param}>的值")
+ }
+ }
+ kafkaSendMsgService.sendJpushMessage(bean.userid,template.title,content,bean.refno,mutableMapOf(),"")
+ }else {
+ throw RuntimeException("未找到id为:<${bean.templateid}>的模板,请确认模板id")
+ }
+ }
+}
\ No newline at end of file
diff --git a/backend/src/main/kotlin/com/supwisdom/dlpay/portal/service/MsgService.kt b/backend/src/main/kotlin/com/supwisdom/dlpay/portal/service/MsgService.kt
new file mode 100644
index 0000000..ebec659
--- /dev/null
+++ b/backend/src/main/kotlin/com/supwisdom/dlpay/portal/service/MsgService.kt
@@ -0,0 +1,12 @@
+package com.supwisdom.dlpay.portal.service
+
+import com.supwisdom.dlpay.framework.jpa.page.Pagination
+import com.supwisdom.dlpay.portal.bean.MsgTemplateSearchBean
+import com.supwisdom.dlpay.portal.bean.SendMsgBean
+import com.supwisdom.dlpay.portal.domain.TBMsgTemplate
+
+interface MsgService {
+ fun getMsgTemplateList(bean:MsgTemplateSearchBean):Pagination
+ fun saveMsgTemplate(template:TBMsgTemplate)
+ fun sendMsg(bean: SendMsgBean)
+}
diff --git a/backend/src/test/java/test.java b/backend/src/test/java/test.java
new file mode 100644
index 0000000..1659da6
--- /dev/null
+++ b/backend/src/test/java/test.java
@@ -0,0 +1,32 @@
+import java.util.HashMap;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class test {
+ public static void main(String[] args) {
+ String sqlFragment = "您的验证码为:${code},订单号:${billno},本次消费:${money}元,请勿泄漏于他人。";
+ Map<String, String> map = new HashMap<>();
+ map.put("code", "23423");
+ map.put("billno", "6116c8e6e0c0464995f4e480473b6a1e");
+ map.put("money", "12.34");
+ Pattern pattern = Pattern.compile("\\$\\{[\\w]*}");
+ Matcher matcher = pattern.matcher(sqlFragment);
+ //循环,字符串中有多少个符合的,就循环多少次
+ while(matcher.find()){
+ //每一个符合正则的字符串
+ String e = matcher.group();
+ //截取出括号中的内容
+ String substring = e.substring(2, e.length()-1);
+ //字符串截取
+ //进行替换
+ String value = "init";
+ if (map.containsKey(substring)) {
+ value = map.get(substring);
+ }
+ sqlFragment = sqlFragment.replace(e, value);
+
+ }
+ System.out.println(sqlFragment);
+ }
+}
diff --git a/frontend/src/api/msg-template.js b/frontend/src/api/msg-template.js
new file mode 100644
index 0000000..3f19fca
--- /dev/null
+++ b/frontend/src/api/msg-template.js
@@ -0,0 +1,17 @@
+import request from '@/utils/request'
+
+export function getMsgTemplateList(query) {
+ return request({
+ url: '/template/list',
+ method: 'get',
+ params: query
+ })
+}
+
+export function saveMsgTemplateList(data) {
+ return request({
+ url: '/template/save',
+ method: 'post',
+ data
+ })
+}
diff --git a/frontend/src/views/pushmsg/index.vue b/frontend/src/views/pushmsg/index.vue
index cd8e058..6e9d286 100644
--- a/frontend/src/views/pushmsg/index.vue
+++ b/frontend/src/views/pushmsg/index.vue
@@ -1,8 +1,243 @@
<template>
- <div>消息推送</div>
+ <div class="app-container">
+ <div class="filter-container">
+ <div class="filter-item" style="margin-right:15px">模板标题</div>
+ <el-input
+ v-model="formData.title"
+ placeholder="标题"
+ style="width: 350px;margin-right:50px"
+ class="filter-item"
+ />
+ <div class="filter-item" style="margin-right:15px">模板内容</div>
+ <el-input
+ v-model="formData.content"
+ placeholder="内容"
+ style="width: 350px;margin-right:50px"
+ class="filter-item"
+ />
+ <el-button
+ class="filter-item"
+ type="primary"
+ icon="el-icon-search"
+ @click="handleFilter()"
+ >
+ 搜索
+ </el-button>
+ </div>
+ <el-button type="primary" icon="el-icon-circle-plus-outline" @click="addTemplate()">
+ 新增模板
+ </el-button>
+ <el-table
+ :key="tableKey"
+ v-loading="listLoading"
+ :data="list"
+ border
+ fit
+ highlight-current-row
+ style="width: 100%;margin-top:10px"
+ >
+ <el-table-column label="模板id" width="150">
+ <template slot-scope="{row}">
+ <span>{{ row.id }}</span>
+ </template>
+ </el-table-column>
+ <el-table-column label="模板标题" width="150" align="center">
+ <template slot-scope="{row}">
+ <span>{{ row.title }}</span>
+ </template>
+ </el-table-column>
+ <el-table-column label="模板内容" align="center">
+ <template slot-scope="{row}">
+ <span>{{ row.content }}</span>
+ </template>
+ </el-table-column>
+ <el-table-column label="修改日期" align="center" width="160">
+ <template slot-scope="{row}">
+ <span>{{ dateFormat(row.updatetime) }}</span>
+ </template>
+ </el-table-column>
+ <el-table-column label="操作" align="center" width="100">
+ <template slot-scope="{row}">
+ <el-tooltip class="item" effect="dark" content="修改" placement="bottom">
+ <el-button type="primary" icon="el-icon-edit" circle size="mini" @click="updateTemplate(row)" />
+ </el-tooltip>
+ </template>
+ </el-table-column>
+ </el-table>
+
+ <pagination
+ v-show="total>0"
+ :total="total"
+ :page.sync="formData.pageno"
+ :limit.sync="formData.pagesize"
+ style="margin-top:0;"
+ @pagination="getMsgTemplateList"
+ />
+ <el-dialog
+ :title="title"
+ :visible.sync="templateDialogVisible"
+ width="45%"
+ >
+ <div>
+ <el-form ref="templateForm" :model="templateForm" :rules="rules" label-width="100px">
+ <el-form-item label="模板标题" prop="title" class="form-input-item">
+ <el-input
+ v-model="templateForm.title"
+ maxlength="30"
+ show-word-limit
+ style="width:80%"
+ />
+ </el-form-item>
+ <el-form-item label="模板内容" prop="content">
+ <el-input
+ v-model="templateForm.content"
+ type="textarea"
+ maxlength="200"
+ :rows="8"
+ placeholder="变量格式:${xxx};
+ 示例:您本次食堂消费:${money}元,欢迎下次光临。"
+ show-word-limit
+ style="width:80%"
+ />
+ </el-form-item>
+ </el-form>
+ </div>
+ <div style="text-align:center">
+ <el-button
+ type="primary"
+ @click="saveTemplate('templateForm')"
+ >保存
+ </el-button>
+ <el-button @click="templateDialogVisible = false">取消</el-button>
+ </div>
+ </el-dialog>
+ </div>
</template>
<script>
+import {
+ getMsgTemplateList,
+ saveMsgTemplateList
+} from '@/api/msg-template'
+import moment from 'moment'
+import Pagination from '@/components/Pagination'
export default {
- name: 'PushMsg'
+ name: 'PushMsg',
+ components: {
+ Pagination
+ },
+ data() {
+ return {
+ formData: {
+ title: '',
+ content: '',
+ pageno: 1,
+ pagesize: 10
+ },
+ listLoading: false,
+ tableKey: 0,
+ list: null,
+ total: 0,
+ title: '',
+ templateDialogVisible: false,
+ templateForm: {
+ id: '',
+ title: '',
+ content: ''
+ },
+ rules: {
+ title: [
+ { required: true, message: '请输入模板标题', trigger: 'blur' }
+ ],
+ content: [
+ { required: true, message: '请输入模板内容', trigger: 'blur' }
+ ]
+ }
+ }
+ },
+ created() {
+ this.getMsgTemplateList()
+ },
+ methods: {
+ getMsgTemplateList() {
+ this.listLoading = true
+ getMsgTemplateList(this.formData).then(response => {
+ if (response.page) {
+ this.list = response.page.list
+ this.total = response.page.totalCount
+ } else {
+ this.list = null
+ this.total = 0
+ }
+ this.listLoading = false
+ }).catch(error => {
+ this.$message({
+ message: error.msg || '请求异常',
+ type: 'error'
+ })
+ this.listLoading = false
+ })
+ },
+ handleFilter() {
+ this.formData.pageno = 1
+ this.getMsgTemplateList()
+ },
+ dateFormat(date) {
+ if (date === null) {
+ return ''
+ }
+ return moment(date, 'YYYYMMDDHHmmss').format('YYYY-MM-DD HH:mm:ss')
+ },
+ addTemplate() {
+ this.title = '新增模板'
+ this.resetForm('templateForm')
+ this.templateDialogVisible = true
+ },
+ updateTemplate(row) {
+ this.title = '修改模板'
+ this.resetForm('templateForm')
+ this.templateForm = Object.assign({}, row)
+ this.templateDialogVisible = true
+ },
+ saveTemplate(formName) {
+ this.$refs[formName].validate((valid) => {
+ if (valid) {
+ saveMsgTemplateList(this.templateForm).then(response => {
+ this.$notify({
+ title: '成功',
+ message: '保存成功!',
+ type: 'success',
+ duration: 2000
+ })
+ this.templateDialogVisible = false
+ this.getMsgTemplateList()
+ }).catch(error => {
+ this.$message({
+ message: error.msg || '请求异常',
+ type: 'error'
+ })
+ })
+ } else {
+ return false
+ }
+ })
+ },
+ resetForm(formName) {
+ this.templateForm = {
+ id: '',
+ title: '',
+ content: ''
+ }
+ this.$nextTick(() => {
+ this.$refs[formName].clearValidate()
+ })
+ }
+ }
}
</script>
+<style>
+.form-input-item
+ .el-input__inner{
+ padding-right: 50px;
+ }
+
+</style>