手机通知公告
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/api/bean/KafkaXgMessage.java b/payapi/src/main/java/com/supwisdom/dlpay/api/bean/KafkaXgMessage.java
index 9bc836a..1378bcf 100644
--- a/payapi/src/main/java/com/supwisdom/dlpay/api/bean/KafkaXgMessage.java
+++ b/payapi/src/main/java/com/supwisdom/dlpay/api/bean/KafkaXgMessage.java
@@ -6,18 +6,20 @@
private String content;//提醒消息内容
private String gids;//gid发送列表,逗号隔开
private Boolean alltarget;//是否平台全发送
- private String platform;//android,ios
+ private String platform;//android,ios,all
private int type;//TYPE_NOTIFICATION = 1,TYPE_MESSAGE = 2
- private String url;//跳转url
private String expiretime;//过期时间
private Boolean callback;//是否回调返回
- private String msg_type;//提醒类型 字典 epay_pos_scan_code_pay、
- private String refno;//流水参考号
private int retries;//最多重试次数
- private String amount;//消费金额,元,小数点后两位
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;
@@ -67,14 +69,6 @@
this.type = type;
}
- public String getUrl() {
- return url;
- }
-
- public void setUrl(String url) {
- this.url = url;
- }
-
public String getExpiretime() {
return expiretime;
}
@@ -91,22 +85,6 @@
this.callback = callback;
}
- public String getMsg_type() {
- return msg_type;
- }
-
- public void setMsg_type(String msg_type) {
- this.msg_type = msg_type;
- }
-
- public String getRefno() {
- return refno;
- }
-
- public void setRefno(String refno) {
- this.refno = refno;
- }
-
public int getRetries() {
return retries;
}
@@ -115,14 +93,6 @@
this.retries = retries;
}
- public String getAmount() {
- return amount;
- }
-
- public void setAmount(String amount) {
- this.amount = amount;
- }
-
public String getCustom() {
return custom;
}
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/framework/dao/NoticeDao.java b/payapi/src/main/java/com/supwisdom/dlpay/framework/dao/NoticeDao.java
new file mode 100644
index 0000000..800c10e
--- /dev/null
+++ b/payapi/src/main/java/com/supwisdom/dlpay/framework/dao/NoticeDao.java
@@ -0,0 +1,19 @@
+package com.supwisdom.dlpay.framework.dao;
+
+import com.supwisdom.dlpay.framework.domain.TNotice;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+import org.springframework.data.jpa.repository.Lock;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.stereotype.Repository;
+
+import javax.persistence.LockModeType;
+
+@Repository
+public interface NoticeDao extends JpaRepository<TNotice, String>, JpaSpecificationExecutor<TNotice> {
+ TNotice getById(String id);
+
+ @Lock(LockModeType.PESSIMISTIC_WRITE)
+ @Query("from TNotice t where t.id=?1 ")
+ TNotice getByIdForUpdate(String id);
+}
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/framework/dao/NoticeMsgDao.java b/payapi/src/main/java/com/supwisdom/dlpay/framework/dao/NoticeMsgDao.java
new file mode 100644
index 0000000..35a6dd4
--- /dev/null
+++ b/payapi/src/main/java/com/supwisdom/dlpay/framework/dao/NoticeMsgDao.java
@@ -0,0 +1,30 @@
+package com.supwisdom.dlpay.framework.dao;
+
+import com.supwisdom.dlpay.framework.domain.TNoticeMsg;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Lock;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.jpa.repository.QueryHints;
+import org.springframework.stereotype.Repository;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.persistence.LockModeType;
+import javax.persistence.QueryHint;
+import java.util.List;
+
+@Repository
+public interface NoticeMsgDao extends JpaRepository<TNoticeMsg, String> {
+ TNoticeMsg getByMsgid(String msgid);
+
+ @Transactional
+ @Lock(LockModeType.PESSIMISTIC_WRITE)
+ @QueryHints({@QueryHint(name = "javax.persistence.lock.timeout", value = "0")})
+ @Query("from TNoticeMsg where msgid=?1")
+ TNoticeMsg getByMsgidForUpdateNowait(String msgid);
+
+ @Query("from TNoticeMsg where noticeId=?1 order by createtime desc")
+ List<TNoticeMsg> findAllByNoticeId(String noticeid);
+
+ @Query("from TNoticeMsg t where t.status='normal' and t.pushmode='delay' and t.pushSettime<=?1 and t.sendkafka=false order by t.createtime")
+ List<TNoticeMsg> findAllDelayNoticeByDatetime(String datetime);
+}
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/framework/dao/RoleFunctionDao.java b/payapi/src/main/java/com/supwisdom/dlpay/framework/dao/RoleFunctionDao.java
index e125f7a..945f510 100644
--- a/payapi/src/main/java/com/supwisdom/dlpay/framework/dao/RoleFunctionDao.java
+++ b/payapi/src/main/java/com/supwisdom/dlpay/framework/dao/RoleFunctionDao.java
@@ -19,11 +19,11 @@
List<TRoleFunction> findByRoleId(String roleId);
@Query(value = "select tt.id,tt.pid,tt.name,tt.checked,tt.open from " +
- " ( select f.id||'' as id ,f.parentid||'' as pid,f.name,case when rf.id is null then 0 else 1 end as checked,case when f.parentid=-1 then 1 else 0 end as open from tb_function f " +
+ " ( select f.id||'' as id ,f.parentid||'' as pid,f.name,case when rf.id is null then 0 else 1 end as checked,case when f.parentid=-1 then 1 else 0 end as open,f.ordernum from tb_function f " +
" left join tb_role_function rf on rf.functionid = f.id and rf.roleid=?1 " +
" union all " +
- " select r.id||'_res' as id,r.function_id||'' as pid,r.name,case when p.id is null then 0 else 1 end as checked,0 as open from tb_resource r " +
- " left join tb_permission p on p.resid = r.id and p.roleid=?1 ) tt order by tt.id " , nativeQuery = true)
+ " select r.id||'_res' as id,r.function_id||'' as pid,r.name,case when p.id is null then 0 else 1 end as checked,0 as open,999999 as ordernum from tb_resource r " +
+ " left join tb_permission p on p.resid = r.id and p.roleid=?1 ) tt order by tt.pid,tt.ordernum" , nativeQuery = true)
List<NodeData> findByRoleIdNative(String roleId);
void deleteByRoleId(String roleId);
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/framework/domain/TNotice.java b/payapi/src/main/java/com/supwisdom/dlpay/framework/domain/TNotice.java
new file mode 100644
index 0000000..08e645d
--- /dev/null
+++ b/payapi/src/main/java/com/supwisdom/dlpay/framework/domain/TNotice.java
@@ -0,0 +1,149 @@
+package com.supwisdom.dlpay.framework.domain;
+
+import org.hibernate.annotations.GenericGenerator;
+
+import javax.persistence.*;
+import javax.validation.constraints.NotNull;
+
+/**
+ * 通知公告表(全体通知)
+ * */
+@Entity
+@Table(name = "TB_NOTICE")
+public class TNotice {
+ @Id
+ @GenericGenerator(name = "nidGenerator", strategy = "uuid")
+ @GeneratedValue(generator = "nidGenerator")
+ @Column(name = "ID", nullable = false, length = 32)
+ private String id;
+
+ @Column(name = "TITLE", nullable = false, length = 200)
+ private String title; //标题
+
+ @Column(name = "CONTENT", nullable = false, length = 2000)
+ private String content; //内容
+
+ @Column(name = "PLATFORM", nullable = false, length = 10)
+ private String platform; //all-全部;ios-苹果;android-安卓
+
+ @Column(name = "CREATEDATE", nullable = false, length = 8)
+ private String createdate; //创建日期yyyyMMdd
+
+ @Column(name = "CREATETIME", length = 6)
+ private String createtime; //创建日期hh24miss
+
+ @Column(name = "OPERID", length = 32)
+ private String operid; //创建者的operid
+
+ @Column(name = "CREATOR", length = 200)
+ private String creator; //创建者名称
+
+ @Column(name = "SENDCNT", nullable = false, precision = 9)
+ private Integer sendcnt = 0;
+
+ @Column(name = "LINKURL", length = 1000)
+ private String linkurl;
+
+ @Column(name = "LASTSAVED", length = 14)
+ private String lastsaved; //最后更新时间
+
+ @Column(name = "tenantid", length = 20)
+ @NotNull
+ private String tenantId;
+
+ 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 getPlatform() {
+ return platform;
+ }
+
+ public void setPlatform(String platform) {
+ this.platform = platform;
+ }
+
+ public String getCreatedate() {
+ return createdate;
+ }
+
+ public void setCreatedate(String createdate) {
+ this.createdate = createdate;
+ }
+
+ public String getCreatetime() {
+ return createtime;
+ }
+
+ public void setCreatetime(String createtime) {
+ this.createtime = createtime;
+ }
+
+ public String getOperid() {
+ return operid;
+ }
+
+ public void setOperid(String operid) {
+ this.operid = operid;
+ }
+
+ public String getCreator() {
+ return creator;
+ }
+
+ public void setCreator(String creator) {
+ this.creator = creator;
+ }
+
+ public Integer getSendcnt() {
+ return sendcnt;
+ }
+
+ public void setSendcnt(Integer sendcnt) {
+ this.sendcnt = sendcnt;
+ }
+
+ public String getLinkurl() {
+ return linkurl;
+ }
+
+ public void setLinkurl(String linkurl) {
+ this.linkurl = linkurl;
+ }
+
+ public String getLastsaved() {
+ return lastsaved;
+ }
+
+ public void setLastsaved(String lastsaved) {
+ this.lastsaved = lastsaved;
+ }
+
+ public String getTenantId() {
+ return tenantId;
+ }
+
+ public void setTenantId(String tenantId) {
+ this.tenantId = tenantId;
+ }
+}
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/framework/domain/TNoticeMsg.java b/payapi/src/main/java/com/supwisdom/dlpay/framework/domain/TNoticeMsg.java
new file mode 100644
index 0000000..2a417e0
--- /dev/null
+++ b/payapi/src/main/java/com/supwisdom/dlpay/framework/domain/TNoticeMsg.java
@@ -0,0 +1,160 @@
+package com.supwisdom.dlpay.framework.domain;
+
+import org.hibernate.annotations.GenericGenerator;
+
+import javax.persistence.*;
+import javax.validation.constraints.NotNull;
+
+/**
+ * 通知公告发布明细表(全体通知)
+ * */
+@Entity
+@Table(name = "TB_NOTICE_MSG")
+public class TNoticeMsg {
+ @Id
+ @GenericGenerator(name = "midGenerator", strategy = "uuid")
+ @GeneratedValue(generator = "midGenerator")
+ @Column(name = "msgid", nullable = false, length = 32)
+ private String msgid;
+
+ @Column(name = "notice_id", nullable = false, length = 32)
+ private String noticeId;
+
+ @Column(name = "alltarget", nullable = false, length = 10)
+ private Boolean alltarget = true; //是否全体通知公告
+
+ @Column(name = "pushmode", nullable = false, length = 10)
+ private String pushmode = "atonce"; //atonce-立即发布,delay-延迟定时发布
+
+ @Column(name = "push_settime", length = 14)
+ private String pushSettime; //定时发布的设定时间
+
+ @Column(name = "publisher", length = 200)
+ private String publisher; //发布者
+
+ @Column(name = "operid", length = 32)
+ private String operid; //发布者operid
+
+ @Column(name = "status", nullable = false, length = 10)
+ private String status;
+
+ @Column(name = "sendkafka", nullable = false, length = 10)
+ private Boolean sendkafka=false;
+
+ @Column(name = "pushtime", length = 14)
+ private String pushtime;
+
+ @Column(name = "createtime", length = 14)
+ private String createtime;
+
+ @Column(name = "pushresult", length = 600)
+ private String pushresult;
+
+ @Column(name = "tenantid", length = 20)
+ @NotNull
+ private String tenantId;
+
+ public String getMsgid() {
+ return msgid;
+ }
+
+ public void setMsgid(String msgid) {
+ this.msgid = msgid;
+ }
+
+ public String getNoticeId() {
+ return noticeId;
+ }
+
+ public void setNoticeId(String noticeId) {
+ this.noticeId = noticeId;
+ }
+
+ public Boolean getAlltarget() {
+ return alltarget;
+ }
+
+ public void setAlltarget(Boolean alltarget) {
+ this.alltarget = alltarget;
+ }
+
+ public String getPushmode() {
+ return pushmode;
+ }
+
+ public void setPushmode(String pushmode) {
+ this.pushmode = pushmode;
+ }
+
+ public String getPushSettime() {
+ return pushSettime;
+ }
+
+ public void setPushSettime(String pushSettime) {
+ this.pushSettime = pushSettime;
+ }
+
+ public String getPublisher() {
+ return publisher;
+ }
+
+ public void setPublisher(String publisher) {
+ this.publisher = publisher;
+ }
+
+ public String getOperid() {
+ return operid;
+ }
+
+ public void setOperid(String operid) {
+ this.operid = operid;
+ }
+
+ public String getStatus() {
+ return status;
+ }
+
+ public void setStatus(String status) {
+ this.status = status;
+ }
+
+ public Boolean getSendkafka() {
+ return sendkafka;
+ }
+
+ public void setSendkafka(Boolean sendkafka) {
+ this.sendkafka = sendkafka;
+ }
+
+ public String getPushtime() {
+ return pushtime;
+ }
+
+ public void setPushtime(String pushtime) {
+ this.pushtime = pushtime;
+ }
+
+ public String getCreatetime() {
+ return createtime;
+ }
+
+ public void setCreatetime(String createtime) {
+ this.createtime = createtime;
+ }
+
+ public String getPushresult() {
+ return pushresult;
+ }
+
+ public void setPushresult(String pushresult) {
+ this.pushresult = pushresult;
+ }
+
+ public String getTenantId() {
+ return tenantId;
+ }
+
+ public void setTenantId(String tenantId) {
+ this.tenantId = tenantId;
+ }
+}
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/system/controller/NoticeController.java b/payapi/src/main/java/com/supwisdom/dlpay/system/controller/NoticeController.java
new file mode 100644
index 0000000..71bfae7
--- /dev/null
+++ b/payapi/src/main/java/com/supwisdom/dlpay/system/controller/NoticeController.java
@@ -0,0 +1,192 @@
+package com.supwisdom.dlpay.system.controller;
+
+import com.supwisdom.dlpay.api.bean.JsonResult;
+import com.supwisdom.dlpay.api.service.KafkaSendMsgService;
+import com.supwisdom.dlpay.framework.data.SystemDateTime;
+import com.supwisdom.dlpay.framework.domain.TNotice;
+import com.supwisdom.dlpay.framework.domain.TNoticeMsg;
+import com.supwisdom.dlpay.framework.domain.TOperator;
+import com.supwisdom.dlpay.framework.service.SystemUtilService;
+import com.supwisdom.dlpay.framework.util.DateUtil;
+import com.supwisdom.dlpay.framework.util.PageResult;
+import com.supwisdom.dlpay.framework.util.StringUtil;
+import com.supwisdom.dlpay.framework.util.WebConstant;
+import com.supwisdom.dlpay.system.service.NoticeService;
+import com.supwisdom.dlpay.util.ConstantUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.security.core.annotation.AuthenticationPrincipal;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.*;
+
+@Controller
+@RequestMapping("/notice")
+public class NoticeController {
+ @Autowired
+ private NoticeService noticeService;
+ @Autowired
+ private SystemUtilService systemUtilService;
+ @Autowired
+ private KafkaSendMsgService kafkaSendMsgService;
+
+ @GetMapping("/index")
+ public String noticeIndex() {
+ return "system/notice/index";
+ }
+
+ @GetMapping("/list")
+ @PreAuthorize("hasPermission('/notice/index','')")
+ @ResponseBody
+ public PageResult<TNotice> searchNotice(@RequestParam("page") Integer pageNo,
+ @RequestParam("limit") Integer pageSize,
+ @RequestParam(value = "startdate", required = false) String startdate,
+ @RequestParam(value = "enddate", required = false) String enddate,
+ @RequestParam(value = "searchkey", required = false) String searchkey) {
+ try {
+ if (null == pageNo || pageNo < 1) pageNo = WebConstant.PAGENO_DEFAULT;
+ if (null == pageSize || pageSize < 1) pageSize = WebConstant.PAGESIZE_DEFAULT;
+ return noticeService.getNotice(startdate, enddate, searchkey, pageNo, pageSize);
+ } catch (Exception e) {
+ e.printStackTrace();
+ return new PageResult<>(99, "系统查询错误");
+ }
+ }
+
+ @GetMapping("/load4add")
+ @PreAuthorize("hasPermission('/notice/load4add','')")
+ public String load4Add() {
+ return "system/notice/add";
+ }
+
+ @PostMapping("/edit")
+ @PreAuthorize("hasPermission('/notice/edit','')")
+ @ResponseBody
+ public JsonResult edit(@RequestParam("noticeId") String noticeId,
+ @RequestParam("title") String title,
+ @RequestParam("content") String content,
+ @RequestParam("platform") String platform,
+ @RequestParam(value = "linkurl", required = false) String linkurl,
+ @AuthenticationPrincipal UserDetails operUser) {
+ try {
+ TOperator oper = (TOperator) operUser;
+ String prefix = "";
+ TNotice notice = null;
+ if (StringUtil.isEmpty(noticeId)) {
+ prefix = "新增";
+ notice = new TNotice();
+ SystemDateTime dt = systemUtilService.getSysdatetime();
+ notice.setCreatedate(dt.getHostdate());
+ notice.setCreatetime(dt.getHosttime());
+ notice.setOperid(oper.getOperid());
+ notice.setCreator(oper.getOpername());
+ notice.setTenantId(oper.getTenantId());
+ } else {
+ prefix = "修改";
+ notice = noticeService.getById(noticeId);
+ if (null == notice) return JsonResult.error("未找到原始记录,请重新查询后在操作。");
+ if (notice.getSendcnt() > 0) return JsonResult.error("公告已发布,不能修改");
+ }
+ if (StringUtil.isEmpty(title)) return JsonResult.error("公告标题不能为空");
+ if (StringUtil.isEmpty(content)) return JsonResult.error("公告内容不能为空");
+ if (!ConstantUtil.PHONE_PLATFORM_ALL.equals(platform) && !ConstantUtil.PHONE_PLATFORM_ANDROID.equals(platform) && !ConstantUtil.PHONE_PLATFORM_IOS.equals(platform))
+ return JsonResult.error("请选择推送终端");
+ notice.setPlatform(platform);
+ notice.setTitle(title.trim());
+ notice.setContent(content.trim());
+ if (StringUtil.isEmpty(linkurl)) {
+ notice.setLinkurl(null);
+ } else {
+ notice.setLinkurl(linkurl.trim());
+ }
+
+ if (noticeService.doSaveOrUpdateNotice(notice)) {
+ return JsonResult.ok(prefix + "成功!");
+ } else {
+ return JsonResult.error(prefix + "失败!");
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ if (StringUtil.isEmpty(noticeId)) {
+ return JsonResult.error("新增失败,业务异常!").put("exception", e);
+ } else {
+ return JsonResult.error("修改失败,业务异常!").put("exception", e);
+ }
+ }
+ }
+
+ @PostMapping("/delete")
+ @PreAuthorize("hasPermission('/notice/delete','')")
+ @ResponseBody
+ public JsonResult delete(@RequestParam("noticeId") String noticeId) {
+ try {
+ TNotice notice = noticeService.getById(noticeId);
+ if (null == notice) return JsonResult.error("未找到原始记录,请重新查询后在操作。");
+ if (notice.getSendcnt() > 0) return JsonResult.error("公告已发布,不能删除!");
+ if (noticeService.deleteNotice(notice)) {
+ return JsonResult.ok("删除成功!");
+ } else {
+ return JsonResult.error("删除失败!");
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ return JsonResult.error("删除失败,业务异常!").put("exception", e);
+ }
+ }
+
+ @GetMapping("/load4publish")
+ @PreAuthorize("hasPermission('/notice/load4publish','')")
+ public String load4Publish() {
+ return "system/notice/publish";
+ }
+
+ @PostMapping("/publish")
+ @PreAuthorize("hasPermission('/notice/publish','')")
+ @ResponseBody
+ public JsonResult publish(@RequestParam("noticeId") String noticeId,
+ @RequestParam("pushmode") String pushmode,
+ @RequestParam(value = "settime", required = false) String settime,
+ @AuthenticationPrincipal UserDetails operUser) {
+ try {
+ TOperator oper = (TOperator) operUser;
+ TNotice notice = noticeService.getById(noticeId);
+ if (null == notice) return JsonResult.error("未找到原始记录,请重新查询后在操作。");
+ if (!ConstantUtil.PHONE_NOTICE_PUSHMODE_ATONCE.equals(pushmode) && !ConstantUtil.PHONE_NOTICE_PUSHMODE_DELAY.equals(pushmode))
+ return JsonResult.error("请选择是立即发布还是定时发布");
+ if (!ConstantUtil.PHONE_NOTICE_PUSHMODE_ATONCE.equals(pushmode) && !DateUtil.checkDatetimeValid(settime, "yyyy-MM-dd HH:mm:ss"))
+ return JsonResult.error("定时发布请设定正确的发布时间");
+ if (!ConstantUtil.PHONE_NOTICE_PUSHMODE_ATONCE.equals(pushmode) && DateUtil.compareDatetime(DateUtil.unParseToDateFormat(settime), systemUtilService.getSysdatetime().getHostdatetime(), DateUtil.DATETIME_FMT) <= 0)
+ return JsonResult.error("设定的发布时间必须比当前时间大");
+
+ TNoticeMsg msg = noticeService.doPublishNotice(notice.getId(), pushmode, settime, oper);
+ if (ConstantUtil.PHONE_NOTICE_PUSHMODE_ATONCE.equals(pushmode)) {
+ kafkaSendMsgService.sendNoticeMessage(msg.getMsgid()); //异步立即推送
+ }
+ return JsonResult.ok("发布成功!");
+ } catch (Exception e) {
+ e.printStackTrace();
+ return JsonResult.error("发布失败,业务异常!").put("exception", e);
+ }
+ }
+
+ @GetMapping("/load4detail")
+ @PreAuthorize("hasPermission('/notice/load4detail','')")
+ public String load4PublishDetails() {
+ return "system/notice/details";
+ }
+
+ @GetMapping("/detaillist")
+ @PreAuthorize("hasPermission('/notice/load4detail','')")
+ @ResponseBody
+ public PageResult<TNoticeMsg> searchNoticePublishDetails(@RequestParam("noticeId") String noticeId) {
+ try {
+ return noticeService.getNoticePublishDetails(noticeId);
+ } catch (Exception e) {
+ e.printStackTrace();
+ return new PageResult<>(99, "系统查询错误");
+ }
+ }
+
+
+
+}
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/system/service/NoticeService.java b/payapi/src/main/java/com/supwisdom/dlpay/system/service/NoticeService.java
new file mode 100644
index 0000000..1bb9425
--- /dev/null
+++ b/payapi/src/main/java/com/supwisdom/dlpay/system/service/NoticeService.java
@@ -0,0 +1,34 @@
+package com.supwisdom.dlpay.system.service;
+
+import com.supwisdom.dlpay.framework.domain.TNotice;
+import com.supwisdom.dlpay.framework.domain.TNoticeMsg;
+import com.supwisdom.dlpay.framework.domain.TOperator;
+import com.supwisdom.dlpay.framework.util.PageResult;
+import org.springframework.transaction.annotation.Propagation;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.List;
+
+public interface NoticeService {
+ @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class, readOnly = true)
+ PageResult<TNotice> getNotice(String startdate, String enddate, String searchkey, int pageNo, int pageSize);
+
+ @Transactional(rollbackFor = Exception.class, readOnly = true)
+ TNotice getById(String id);
+
+ @Transactional(rollbackFor = Exception.class)
+ boolean doSaveOrUpdateNotice(TNotice notice);
+
+ @Transactional(rollbackFor = Exception.class)
+ boolean deleteNotice(TNotice notice);
+
+ @Transactional(rollbackFor = Exception.class)
+ TNoticeMsg doPublishNotice(String noticeId, String pushmode, String settime, TOperator oper)throws Exception;
+
+ @Transactional(rollbackFor = Exception.class, readOnly = true)
+ PageResult<TNoticeMsg> getNoticePublishDetails(String noticeId);
+
+ @Transactional(rollbackFor = Exception.class, readOnly = true)
+ List<TNoticeMsg> getDelayNoticeByDatetime(String datetime);
+
+}
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/system/service/impl/NoticeServiceImpl.java b/payapi/src/main/java/com/supwisdom/dlpay/system/service/impl/NoticeServiceImpl.java
new file mode 100644
index 0000000..7f26776
--- /dev/null
+++ b/payapi/src/main/java/com/supwisdom/dlpay/system/service/impl/NoticeServiceImpl.java
@@ -0,0 +1,128 @@
+package com.supwisdom.dlpay.system.service.impl;
+
+import com.supwisdom.dlpay.framework.dao.NoticeDao;
+import com.supwisdom.dlpay.framework.dao.NoticeMsgDao;
+import com.supwisdom.dlpay.framework.domain.TNotice;
+import com.supwisdom.dlpay.framework.domain.TNoticeMsg;
+import com.supwisdom.dlpay.framework.domain.TOperator;
+import com.supwisdom.dlpay.framework.service.SystemUtilService;
+import com.supwisdom.dlpay.framework.util.DateUtil;
+import com.supwisdom.dlpay.framework.util.PageResult;
+import com.supwisdom.dlpay.framework.util.StringUtil;
+import com.supwisdom.dlpay.framework.util.TradeDict;
+import com.supwisdom.dlpay.system.service.NoticeService;
+import com.supwisdom.dlpay.util.ConstantUtil;
+import com.supwisdom.dlpay.util.WebCheckException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.domain.Sort;
+import org.springframework.data.jpa.domain.Specification;
+import org.springframework.stereotype.Service;
+
+import javax.persistence.criteria.CriteriaBuilder;
+import javax.persistence.criteria.CriteriaQuery;
+import javax.persistence.criteria.Predicate;
+import javax.persistence.criteria.Root;
+import java.util.ArrayList;
+import java.util.List;
+
+@Service
+public class NoticeServiceImpl implements NoticeService {
+ @Autowired
+ private NoticeDao noticeDao;
+ @Autowired
+ private NoticeMsgDao noticeMsgDao;
+ @Autowired
+ private SystemUtilService systemUtilService;
+
+ @Override
+ public PageResult<TNotice> getNotice(String startdate, String enddate, String searchkey, int pageNo, int pageSize) {
+ Pageable pageable = PageRequest.of(pageNo - 1, pageSize, Sort.by(Sort.Direction.DESC, "createdate"));
+ Page<TNotice> page = noticeDao.findAll(new Specification<TNotice>() {
+ @Override
+ public Predicate toPredicate(Root<TNotice> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
+ List<Predicate> predicates = new ArrayList<>();
+ if (!StringUtil.isEmpty(startdate)) {
+ predicates.add(criteriaBuilder.greaterThanOrEqualTo(root.get("createdate").as(String.class), DateUtil.unParseToDateFormat(startdate)));
+ }
+ if (!StringUtil.isEmpty(enddate)) {
+ predicates.add(criteriaBuilder.lessThanOrEqualTo(root.get("createdate").as(String.class), DateUtil.unParseToDateFormat(enddate)));
+ }
+ if (!StringUtil.isEmpty(searchkey)) {
+ predicates.add(criteriaBuilder.like(root.get("title").as(String.class), "%" + searchkey.trim() + "%"));
+ }
+ return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
+ }
+ }, pageable);
+ return new PageResult<>(page);
+ }
+
+ @Override
+ public TNotice getById(String id) {
+ if (!StringUtil.isEmpty(id)) return noticeDao.getById(id.trim());
+ return null;
+ }
+
+ @Override
+ public boolean doSaveOrUpdateNotice(TNotice notice) {
+ if (null != notice) {
+ notice.setLastsaved(systemUtilService.getSysdatetime().getHostdatetime());
+ noticeDao.save(notice);
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public boolean deleteNotice(TNotice notice) {
+ if (null != notice) {
+ noticeDao.delete(notice);
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public TNoticeMsg doPublishNotice(String noticeId, String pushmode, String settime, TOperator oper) throws Exception {
+ TNotice notice = noticeDao.getByIdForUpdate(noticeId);
+ if (null == notice) throw new WebCheckException("未找到原始记录,请重新查询后在操作。");
+
+ TNoticeMsg msg = new TNoticeMsg();
+ msg.setNoticeId(notice.getId());
+ msg.setAlltarget(true);
+ msg.setPushmode(pushmode);
+ if (!ConstantUtil.PHONE_NOTICE_PUSHMODE_ATONCE.equals(pushmode)) {
+ msg.setPushSettime(DateUtil.unParseToDateFormat(settime));
+ }
+ msg.setPublisher(oper.getOpername());
+ msg.setOperid(oper.getOperid());
+ msg.setStatus(TradeDict.STATUS_NORMAL);
+ msg.setSendkafka(false);
+ msg.setCreatetime(systemUtilService.getSysdatetime().getHostdatetime());
+ msg.setTenantId(notice.getTenantId());
+ msg.setPushresult("待推送");
+
+ notice.setSendcnt(notice.getSendcnt() + 1);
+ notice.setLastsaved(systemUtilService.getSysdatetime().getHostdatetime());
+ noticeDao.save(notice);
+ return noticeMsgDao.save(msg);
+ }
+
+ @Override
+ public PageResult<TNoticeMsg> getNoticePublishDetails(String noticeId) {
+ if (!StringUtil.isEmpty(noticeId)) {
+ List<TNoticeMsg> list = noticeMsgDao.findAllByNoticeId(noticeId);
+ return new PageResult<>(list);
+ }
+ return new PageResult<>(99, "无数据");
+ }
+
+ @Override
+ public List<TNoticeMsg> getDelayNoticeByDatetime(String datetime) {
+ List<TNoticeMsg> list = noticeMsgDao.findAllDelayNoticeByDatetime(datetime);
+ if (!StringUtil.isEmpty(list)) return list;
+ return new ArrayList<>(0);
+ }
+}
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/util/ConstantUtil.java b/payapi/src/main/java/com/supwisdom/dlpay/util/ConstantUtil.java
index ba129e6..4f6d410 100644
--- a/payapi/src/main/java/com/supwisdom/dlpay/util/ConstantUtil.java
+++ b/payapi/src/main/java/com/supwisdom/dlpay/util/ConstantUtil.java
@@ -91,4 +91,17 @@
public static final String OPERCHK_CHKMODE_DELETE = "删除";
public static final String CHKFILE_DELIMITER = "|";
+
+ public static final String PHONE_PLATFORM_ALL = "all";
+ public static final String PHONE_PLATFORM_ANDROID = "android";
+ public static final String PHONE_PLATFORM_IOS = "ios";
+
+ public static final String PHONE_NOTICE_PUSHMODE_ATONCE = "atonce"; //立即发布
+ public static final String PHONE_NOTICE_PUSHMODE_DELAY = "delay"; //延时发布
+
+ /**
+ * kafka消息类型
+ * */
+ public static final String KAFKA_MAGTYPE_NOTICE = "dlsmk_phone_notice";
+ public static final String KAFKA_MAGTYPE_CONSUME = "dlsmk_card_consume";
}
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/PayApiApplication.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/PayApiApplication.kt
index d993aea..f489996 100644
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/PayApiApplication.kt
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/PayApiApplication.kt
@@ -4,6 +4,7 @@
import io.lettuce.core.ReadFrom
import net.javacrumbs.shedlock.core.LockProvider
import net.javacrumbs.shedlock.provider.redis.spring.RedisLockProvider
+import net.javacrumbs.shedlock.spring.annotation.EnableSchedulerLock
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.beans.factory.annotation.Value
import org.springframework.boot.SpringApplication
@@ -148,7 +149,7 @@
}
}
-
+@EnableSchedulerLock(defaultLockAtMostFor = "PT30M")
@SpringBootApplication
@EnableDiscoveryClient
@EnableScheduling
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/async_tasks.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/async_tasks.kt
index e771add..f01d870 100644
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/async_tasks.kt
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/async_tasks.kt
@@ -71,6 +71,15 @@
}
}
+ @Bean(name = ["kafkaSendMessageAsyncTask"])
+ fun kafkaSendMessageAsyncTaskExecutor(): Executor {
+ return ThreadPoolTaskExecutor().apply {
+ corePoolSize = 20
+ maxPoolSize = 100
+ setWaitForTasksToCompleteOnShutdown(true)
+ }
+ }
+
override fun getAsyncUncaughtExceptionHandler(): AsyncUncaughtExceptionHandler? {
return MyAsyncUncaughtExceptionHandler()
}
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/scheduler_task.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/scheduler_task.kt
index 1d8e2fc..e7caa77 100644
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/scheduler_task.kt
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/scheduler_task.kt
@@ -7,10 +7,12 @@
import com.supwisdom.dlpay.api.repositories.ShopaccService
import com.supwisdom.dlpay.api.service.ConsumePayService
import com.supwisdom.dlpay.api.service.DtlQueryResultService
+import com.supwisdom.dlpay.api.service.KafkaSendMsgService
import com.supwisdom.dlpay.api.service.TransactionServiceProxy
import com.supwisdom.dlpay.framework.service.SystemUtilService
import com.supwisdom.dlpay.framework.util.ApplicationUtil
import com.supwisdom.dlpay.framework.util.TradeDict
+import com.supwisdom.dlpay.system.service.NoticeService
import com.supwisdom.dlpay.util.ConstantUtil
import net.javacrumbs.shedlock.core.SchedulerLock
import org.springframework.beans.factory.annotation.Autowired
@@ -150,4 +152,34 @@
}
}
}
+}
+
+/**
+ * 定时通知公告的推送任务
+ * */
+@Component
+class NoticePushMessageTask {
+ @Autowired
+ private lateinit var noticeService: NoticeService
+ @Autowired
+ private lateinit var systemUtilService: SystemUtilService
+ @Autowired
+ private lateinit var kafkaSendMsgService: KafkaSendMsgService
+
+ @Scheduled(cron = "\${send.delay.notice.task.cron:-}")
+ @SchedulerLock(name = "SendDelayNoticeTask", lockAtMostForString = "PT10M")
+ fun doSendDelayNotice() {
+ try {
+ val hostdatetime = systemUtilService.sysdatetime.hostdatetime
+ noticeService.getDelayNoticeByDatetime(hostdatetime).forEach {
+ try {
+ kafkaSendMsgService.sendNoticeMessage(it.msgid)
+ } catch (e: Exception) {
+ e.printStackTrace()
+ }
+ }
+ } catch (ex: Exception) {
+ ex.printStackTrace()
+ }
+ }
}
\ No newline at end of file
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/impl/kafka_service_impl.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/impl/kafka_service_impl.kt
index 290bfaa..c913448 100644
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/impl/kafka_service_impl.kt
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/impl/kafka_service_impl.kt
@@ -3,11 +3,17 @@
import com.google.gson.Gson
import com.supwisdom.dlpay.api.bean.KafkaXgMessage
import com.supwisdom.dlpay.api.service.KafkaSendMsgService
+import com.supwisdom.dlpay.framework.dao.NoticeDao
+import com.supwisdom.dlpay.framework.dao.NoticeMsgDao
+import com.supwisdom.dlpay.framework.service.SystemUtilService
import com.supwisdom.dlpay.framework.util.DateUtil
+import com.supwisdom.dlpay.framework.util.StringUtil
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 com.supwisdom.dlpay.util.ConstantUtil
+import com.supwisdom.dlpay.util.WebCheckException
import mu.KotlinLogging
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.kafka.core.KafkaTemplate
@@ -15,19 +21,26 @@
import org.springframework.stereotype.Service
@Service
-class KafkaSendMsgServiceImpl:KafkaSendMsgService{
+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 noticeMsgDao: NoticeMsgDao
+ @Autowired
+ private lateinit var noticeDao: NoticeDao
+ @Autowired
private lateinit var mobileApiService: MobileApiService
+ @Autowired
+ private lateinit var systemUtilService: SystemUtilService
+
val gson = Gson()
val topic = "jpush-messages"
- @Async
+ @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 {
@@ -63,16 +76,60 @@
message.custom = gson.toJson(extras)
message.expiretime = DateUtil.getNewTime(DateUtil.getNow(), 300)
message.gids = it.uid
- if(it.lastloginplatform.isNullOrEmpty()){
- message.platform="ios"
+ if (it.lastloginplatform.isNullOrEmpty()) {
+ message.platform = "all"
kafkaTemplate.send(topic, msg.msgid, gson.toJson(message))
- message.platform="android"
- kafkaTemplate.send(topic, msg.msgid, gson.toJson(message))
- }else{
+// message.platform="ios"
+// kafkaTemplate.send(topic, msg.msgid, gson.toJson(message))
+// message.platform="android"
+// kafkaTemplate.send(topic, msg.msgid, gson.toJson(message))
+ } else {
kafkaTemplate.send(topic, msg.msgid, gson.toJson(message))
}
}
msg.pusheduids = uids
msgDao.save(msg)
}
+
+ @Async("kafkaSendMessageAsyncTask")
+ override fun sendNoticeMessage(noticeMsgid: String) {
+ val noticeMsg = noticeMsgDao.getByMsgidForUpdateNowait(noticeMsgid) ?: return
+ try {
+ if (noticeMsg.sendkafka) return
+ val notice = noticeDao.getById(noticeMsg.noticeId) ?: throw WebCheckException("未找到对应的通知公告")
+
+ val extras = mutableMapOf<String, String>("msgid" to noticeMsg.msgid, "msg_type" to ConstantUtil.KAFKA_MAGTYPE_NOTICE)
+ if (!StringUtil.isEmpty(notice.linkurl)) extras["url"] = notice.linkurl
+ val message = KafkaXgMessage().apply {
+ this.title = notice.title
+ this.content = notice.content
+ this.alltarget = true //gids不需要传递
+ this.platform = notice.platform
+ this.type = 1 //TYPE_NOTIFICATION = 1,TYPE_MESSAGE = 2
+ this.callback = true
+ this.retries = 3
+ this.custom = gson.toJson(extras)
+ }
+ println(gson.toJson(message))
+ kafkaTemplate.send(topic, noticeMsg.msgid, gson.toJson(message))
+
+ noticeMsg.sendkafka = true
+ noticeMsg.pushtime = systemUtilService.sysdatetime.hostdatetime
+ noticeMsg.pushresult = "已推送"
+ noticeMsgDao.save(noticeMsg)
+ } catch (wex: WebCheckException) {
+ noticeMsg.sendkafka = false
+ noticeMsg.pushtime = systemUtilService.sysdatetime.hostdatetime
+ noticeMsg.pushresult = "推送失败! ${wex.message}"
+ noticeMsgDao.save(noticeMsg)
+ return
+ } catch (e: Exception) {
+ e.printStackTrace()
+ noticeMsg.sendkafka = false
+ noticeMsg.pushtime = systemUtilService.sysdatetime.hostdatetime
+ noticeMsg.pushresult = "推送失败"
+ noticeMsgDao.save(noticeMsg)
+ return
+ }
+ }
}
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/kafka_service.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/kafka_service.kt
index a5cc0e8..b874abc 100644
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/kafka_service.kt
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/kafka_service.kt
@@ -1,5 +1,6 @@
package com.supwisdom.dlpay.api.service
+import com.supwisdom.dlpay.framework.dao.NoticeMsgDao
import com.supwisdom.dlpay.mobile.dao.MsgDao
import mu.KotlinLogging
import org.apache.kafka.clients.consumer.ConsumerRecord
@@ -9,22 +10,35 @@
interface KafkaSendMsgService {
fun sendJpushMessage(userid: String, title: String, content: String, refno: String, extras: MutableMap<String, String>, tenantId: String?)
+
+ fun sendNoticeMessage(noticeMsgid: String)
}
@Component
class KafkaMsgListener{
val logger = KotlinLogging.logger { }
@Autowired
private lateinit var msgDao: MsgDao
+ @Autowired
+ private lateinit var noticeMsgDao: NoticeMsgDao
@KafkaListener(topics = ["jpush-messages-result"],autoStartup = "\${spring.kafka.listen.auto.start:true}")
- fun listen(record :ConsumerRecord<String, String>) {
+ 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){
+ if (!record.key().isNullOrEmpty()) {
+ val opt = msgDao.findById(record.key())
+ if (opt.isPresent) {
var msg = opt.get()
msg.pushresult = record.value()
msgDao.save(msg)
+ return
+ }
+
+ val noticemsg = noticeMsgDao.findById(record.key())
+ if (noticemsg.isPresent) {
+ var nmsg = noticemsg.get()
+ nmsg.pushresult = record.value()
+ noticeMsgDao.save(nmsg)
+ return
}
}
}
diff --git a/payapi/src/main/resources/application.properties b/payapi/src/main/resources/application.properties
index 0a2b535..2c5c6a0 100644
--- a/payapi/src/main/resources/application.properties
+++ b/payapi/src/main/resources/application.properties
@@ -35,6 +35,7 @@
query.third.transdtl.result.cron=7 0/1 * * * ?
payapi.sourcetype.checker.scheduler=7 3/10 * * * ?
citizencard.dolosstask.cron=-
+send.delay.notice.task.cron=29 0/1 * * * ?
################################################
# user password
auth.password.bcrypt.length=10
diff --git a/payapi/src/main/resources/data.sql b/payapi/src/main/resources/data.sql
index bcdf83c..3bd9798 100644
--- a/payapi/src/main/resources/data.sql
+++ b/payapi/src/main/resources/data.sql
@@ -77,6 +77,8 @@
VALUES (37, NULL, 1, NULL, '', '/user/card', '市民卡查询', 1, 19, '{tenantid}');
INSERT INTO "tb_function" ("id", "createtime", "isleaf", "lastsaved", "menuicon", "menuurl", "name", "ordernum", "parentid", tenantid)
VALUES (38, NULL, 1, NULL, '', '/report/shoptodaybusiness', '商户当天统计表', 4, 20, '{tenantid}');
+INSERT INTO "tb_function" ("id", "createtime", "isleaf", "lastsaved", "menuicon", "menuurl", "name", "ordernum", "parentid", tenantid)
+VALUES (39, NULL, 1, NULL, '', '/notice/index', '手机通知公告', 6, 3, '{tenantid}');
INSERT INTO "tb_role_function" ("id", "functionid", "roleid", tenantid)
@@ -145,6 +147,8 @@
VALUES ('ff8080816db87e27016db88be41f0015', 37, 'd1yctWs5+ks0iQN3m9bUvRHus6HbKbrs', '{tenantid}');
INSERT INTO "tb_role_function" ("id", "functionid", "roleid", tenantid)
VALUES ('4028ee9f6e5d95d8016e5d99e8d50012', 38, 'd1yctWs5+ks0iQN3m9bUvRHus6HbKbrs', '{tenantid}');
+INSERT INTO "tb_role_function" ("id", "functionid", "roleid", tenantid)
+VALUES ('ff8080816f8d8258016f8d85e4d70005', 39, 'd1yctWs5+ks0iQN3m9bUvRHus6HbKbrs', '{tenantid}');
INSERT INTO "tb_resource" ("id", "code", "function_id", "name", "uri", tenantid)
@@ -311,6 +315,21 @@
VALUES (94, '', 37, '修改跳转', '/user/load4modifycard', '{tenantid}');
INSERT INTO "tb_resource" ("id", "code", "function_id", "name", "uri", tenantid)
VALUES (95, '', 37, '修改', '/user/cardupdate', '{tenantid}');
+INSERT INTO "tb_resource" ("id", "code", "function_id", "name", "uri", tenantid)
+VALUES (96, '', 39, '查询', '/notice/index', '{tenantid}');
+INSERT INTO "tb_resource" ("id", "code", "function_id", "name", "uri", tenantid)
+VALUES (97, '', 39, '新增修改跳转', '/notice/load4add', '{tenantid}');
+INSERT INTO "tb_resource" ("id", "code", "function_id", "name", "uri", tenantid)
+VALUES (98, '', 39, '新增修改', '/notice/edit', '{tenantid}');
+INSERT INTO "tb_resource" ("id", "code", "function_id", "name", "uri", tenantid)
+VALUES (99, '', 39, '删除', '/notice/delete', '{tenantid}');
+INSERT INTO "tb_resource" ("id", "code", "function_id", "name", "uri", tenantid)
+VALUES (100, '', 39, '发布跳转', '/notice/load4publish', '{tenantid}');
+INSERT INTO "tb_resource" ("id", "code", "function_id", "name", "uri", tenantid)
+VALUES (101, '', 39, '发布', '/notice/publish', '{tenantid}');
+INSERT INTO "tb_resource" ("id", "code", "function_id", "name", "uri", tenantid)
+VALUES (102, '', 39, '发布明细', '/notice/load4detail', '{tenantid}');
+
INSERT INTO "tb_permission" ("id", "resid", "role_func_id", "roleid", tenantid)
VALUES ('ff8080816b7947ed016b795577300036', 16, NULL, 'd1yctWs5+ks0iQN3m9bUvRHus6HbKbrs', '{tenantid}');
@@ -476,7 +495,20 @@
VALUES ('ff8080816ecaebf8016ecaeedcec0004', 94, NULL, 'd1yctWs5+ks0iQN3m9bUvRHus6HbKbrs', '{tenantid}');
INSERT INTO "tb_permission" ("id", "resid", "role_func_id", "roleid", "tenantid")
VALUES ('ff8080816ecafb4e016ecafd58400005', 95, NULL, 'd1yctWs5+ks0iQN3m9bUvRHus6HbKbrs', '{tenantid}');
-
+INSERT INTO "tb_permission" ("id", "resid", "role_func_id", "roleid", "tenantid")
+VALUES ('ff8080816f8d8258016f8d85e4e20006', 96, NULL, 'd1yctWs5+ks0iQN3m9bUvRHus6HbKbrs', '{tenantid}');
+INSERT INTO "tb_permission" ("id", "resid", "role_func_id", "roleid", "tenantid")
+VALUES ('ff8080816fa2c2b7016fa2d809780030', 97, NULL, 'd1yctWs5+ks0iQN3m9bUvRHus6HbKbrs', '{tenantid}');
+INSERT INTO "tb_permission" ("id", "resid", "role_func_id", "roleid", "tenantid")
+VALUES ('ff8080816fa2c2b7016fa2d80978002e', 98, NULL, 'd1yctWs5+ks0iQN3m9bUvRHus6HbKbrs', '{tenantid}');
+INSERT INTO "tb_permission" ("id", "resid", "role_func_id", "roleid", "tenantid")
+VALUES ('ff8080816fa2c2b7016fa2d809780031', 99, NULL, 'd1yctWs5+ks0iQN3m9bUvRHus6HbKbrs', '{tenantid}');
+INSERT INTO "tb_permission" ("id", "resid", "role_func_id", "roleid", "tenantid")
+VALUES ('ff8080816fa2c2b7016fa2d809780032', 100, NULL, 'd1yctWs5+ks0iQN3m9bUvRHus6HbKbrs', '{tenantid}');
+INSERT INTO "tb_permission" ("id", "resid", "role_func_id", "roleid", "tenantid")
+VALUES ('ff8080816fa2c2b7016fa2d80978002f', 101, NULL, 'd1yctWs5+ks0iQN3m9bUvRHus6HbKbrs', '{tenantid}');
+INSERT INTO "tb_permission" ("id", "resid", "role_func_id", "roleid", "tenantid")
+VALUES ('ff8080816fa2c2b7016fa2d80977002d', 102, NULL, 'd1yctWs5+ks0iQN3m9bUvRHus6HbKbrs', '{tenantid}');
INSERT INTO "tb_subject" ("subjid","subjno", "balflag", "displayflag", "endflag", "fsubjno", "opendate", "subjlevel", "subjname", "subjtype", "tenantid")
diff --git a/payapi/src/main/resources/static/libs/custom.js b/payapi/src/main/resources/static/libs/custom.js
index d034401..0307a2d 100644
--- a/payapi/src/main/resources/static/libs/custom.js
+++ b/payapi/src/main/resources/static/libs/custom.js
@@ -104,8 +104,9 @@
}
root.isempty = function (s) {
- if (s == null || s.length == 0)
+ if (undefined == s || null == s || '' == s || s.length == 0) {
return true;
- return /\s/.test(s);
+ }
+ return false;
}
}(window));
\ No newline at end of file
diff --git a/payapi/src/main/resources/templates/system/notice/add.html b/payapi/src/main/resources/templates/system/notice/add.html
new file mode 100644
index 0000000..1247eda
--- /dev/null
+++ b/payapi/src/main/resources/templates/system/notice/add.html
@@ -0,0 +1,85 @@
+<form id="notice-add-form" lay-filter="notice-add-form" class="layui-form model-form">
+ <input name="noticeId" id="hidden-notice-add-msgid" type="hidden"/>
+ <div class="layui-form-item">
+ <label class="layui-form-label"><span style="color: red;">*</span>推送终端</label>
+ <div class="layui-input-block">
+ <input type="radio" name="platform" value="all" title="全部" checked/>
+ <input type="radio" name="platform" value="android" title="安卓手机"/>
+ <input type="radio" name="platform" value="ios" title="苹果手机"/>
+ </div>
+ </div>
+ <div class="layui-form-item">
+ <label class="layui-form-label"><span style="color: red;">*</span>公告标题</label>
+ <div class="layui-input-block">
+ <input name="title" placeholder="请填写标题,不能超过16个字" type="text" class="layui-input" maxlength="16"
+ autocomplete="off" lay-verify="required" required/>
+ </div>
+ </div>
+ <div class="layui-form-item">
+ <label class="layui-form-label"><span style="color: red;">*</span>公告内容</label>
+ <div class="layui-input-block">
+ <textarea name="content" placeholder="请输入内容,不能超过200个字" autocomplete="off" maxlength="200" class="layui-textarea" rows="6" lay-verify="required" required></textarea>
+ </div>
+ </div>
+ <div class="layui-form-item">
+ <label class="layui-form-label">链接地址</label>
+ <div class="layui-input-block">
+ <textarea name="linkurl" placeholder="https://www.baidu.com" autocomplete="off" class="layui-textarea" lay-verify="linkurl"></textarea>
+ </div>
+ </div>
+
+ <div class="layui-form-item model-form-footer">
+ <button class="layui-btn layui-btn-primary" type="button" ew-event="closeDialog">取消</button>
+ <button class="layui-btn" lay-filter="notice-add-form-submit" lay-submit id="notice-add-submit-btn">保存</button>
+ </div>
+</form>
+
+<script>
+ layui.use(['layer', 'admin', 'form'], function () {
+ var layer = layui.layer;
+ var admin = layui.admin;
+ var form = layui.form;
+
+ form.render('radio');
+ form.verify({
+ linkurl: function (value, item) {
+ if ("" != value) {
+ if (!/(^#)|(^http(s*):\/\/[^\s]+\.[^\s]+)/.test(value)) {
+ return "链接格式不正确";
+ }
+ }
+ }
+ });
+
+ var bean = admin.getTempData('t_noticeTmp');
+ if (bean) {
+ form.val('notice-add-form', bean);
+ }
+ // 表单提交事件
+ form.on('submit(notice-add-form-submit)', function (data) {
+ layer.load(2);
+ var token = $("meta[name='_csrf_token']").attr("value");
+ var param = data.field;
+ param["_csrf"] = token;
+ admin.go('[[@{/notice/edit}]]', param, function (result) {
+ console.log(result);
+ layer.closeAll('loading');
+ if (result.code == 200) {
+ layer.msg(result.msg, {icon: 1});
+ admin.finishPopupCenter();
+ } else if (result.code == 401) {
+ layer.msg(result.msg, {icon: 2, time: 1500}, function () {
+ location.replace('[[@{/login}]]');
+ }, 1000);
+ return;
+ } else {
+ layer.msg(result.msg, {icon: 2});
+ }
+ }, function (ret) {
+ console.log(ret);
+ admin.errorBack(ret);
+ });
+ return false;
+ });
+ });
+</script>
\ No newline at end of file
diff --git a/payapi/src/main/resources/templates/system/notice/details.html b/payapi/src/main/resources/templates/system/notice/details.html
new file mode 100644
index 0000000..e2de243
--- /dev/null
+++ b/payapi/src/main/resources/templates/system/notice/details.html
@@ -0,0 +1,86 @@
+<form id="notice-publish-details" lay-filter="notice-publish-details" class="layui-form model-form" style="padding-top: 20px;">
+ <div class="layui-form-item">
+ <label class="layui-form-label">标题</label>
+ <div class="layui-input-block">
+ <input name="title" type="text" class="layui-input" readonly="readonly"/>
+ </div>
+ </div>
+ <div class="layui-form-item">
+ <label class="layui-form-label">内容</label>
+ <div class="layui-input-block">
+ <textarea name="content" class="layui-textarea" readonly="readonly" rows="5"></textarea>
+ </div>
+ </div>
+
+ <div class="layui-form-item">
+ <input type="hidden" name="noticeId" id="notice-publish-details-noticeId"/>
+ <div style="margin-left: 45px;" id="noticePublishDetailTableDiv">
+ <table class="layui-table" id="noticePublishDetailTable"
+ lay-filter="noticePublishDetailTable-filter"></table>
+ </div>
+ </div>
+
+ <div class="layui-form-item model-form-footer">
+ <button class="layui-btn layui-btn-primary" type="button" ew-event="closeDialog">关闭</button>
+ </div>
+</form>
+
+<script>
+ layui.use(['layer', 'admin', 'form', 'table'], function () {
+ var layer = layui.layer;
+ var admin = layui.admin;
+ var form = layui.form;
+ var table = layui.table;
+
+ var bean = admin.getTempData('t_noticePublishDetail');
+ if (bean) {
+ if (isempty(bean.linkurl)) {
+ form.val('notice-publish-details', {
+ noticeId: bean.id,
+ title: bean.title,
+ content: bean.content
+ });
+ } else {
+ form.val('notice-publish-details', {
+ noticeId: bean.id,
+ title: bean.title,
+ content: bean.content + '\n\n链接:' + bean.linkurl
+ });
+ }
+ }
+
+ table.render({
+ elem: '#noticePublishDetailTable',
+ url: '[[@{/notice/detaillist}]]',
+ where: {
+ noticeId: $("#notice-publish-details-noticeId").val()
+ },
+ page: false,
+ size: 'sm',
+ height: 275,
+ cols: [
+ [
+ {type: 'numbers', title: '编号', align: 'center', width: 65},
+ {field: 'publisher', title: '发布者', align: 'center', width: 100},
+ {
+ field: 'createtime', title: '发布时间', align: 'right', width: 150, templet: function (e) {
+ return admin.formatDate(e.createtime);
+ }
+ },
+ {
+ field: 'pushtime', title: '推送时间', align: 'right', width: 175, templet: function (e) {
+ if (null != e.pushtime) {
+ return admin.formatDate(e.pushtime);
+ } else if (null != e.pushSettime) {
+ return '<span style=\"color:red;\">预计</span> ' + admin.formatDate(e.pushSettime);
+ } else {
+ return '-';
+ }
+ }
+ },
+ {field: 'pushresult', title: '备注', align: 'center'},
+ ]
+ ]
+ });
+ });
+</script>
\ No newline at end of file
diff --git a/payapi/src/main/resources/templates/system/notice/index.html b/payapi/src/main/resources/templates/system/notice/index.html
new file mode 100644
index 0000000..02c000c
--- /dev/null
+++ b/payapi/src/main/resources/templates/system/notice/index.html
@@ -0,0 +1,250 @@
+<div class="layui-card">
+ <div class="layui-card-header">
+ <h2 class="header-title">手机通知公告</h2>
+ <span class="layui-breadcrumb pull-right">
+ <a href="#">系统中心</a>
+ <a><cite>手机通知公告</cite></a>
+ </span>
+ </div>
+ <div class="layui-card-body">
+ <div class="layui-form" lay-filter="notice-search-form">
+ <div class="layui-form-item" style="margin-bottom: 0;">
+ <div class="layui-inline">
+ <label class="layui-form-label">创建日期</label>
+ <div class="layui-input-inline">
+ <input type="text" name="startdate" id="notice-search-startdate" placeholder="起始日期"
+ autocomplete="off" class="layui-input"/>
+ </div>
+ <div class="layui-form-mid">-</div>
+ <div class="layui-input-inline">
+ <input type="text" name="enddate" id="notice-search-enddate" placeholder="截止日期"
+ autocomplete="off" class="layui-input"/>
+ </div>
+ </div>
+ <div class="layui-inline" style="margin-right: 20px;">
+ <label class="layui-form-label">标题</label>
+ <div class="layui-input-block" style="width: 265px;">
+ <input type="text" name="searchkey" id="notice-search-searchkey" maxlength="20"
+ autocomplete="off" class="layui-input"/>
+ </div>
+ </div>
+ <div class="layui-inline" style="margin-right: 20px;margin-top: 10px;">
+ <div class="layui-input-block" style="width: 200px;margin-left: 10px;">
+ <button id="notice-search-btn" class="layui-btn icon-btn"><i class="layui-icon"></i>搜 索
+ </button>
+ <button id="notice-search-btn-reset" class="layui-btn layui-btn-primary">清 空</button>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ <div class="layui-card-body">
+ <div class="layui-form toolbar">
+ <button class="layui-btn layui-btn-sm" id="btn-notice-add"><i
+ class="layui-icon"></i>新 增
+ </button>
+ </div>
+ <table class="layui-table" id="noticeSearchTable" lay-filter="noticeSearchTable-filter"></table>
+ </div>
+</div>
+
+<!-- 表格操作列 -->
+<script type="text/html" id="notice-table-bar">
+ <a class="layui-btn layui-btn-xs layui-btn-warm" lay-event="publish">发布</a>
+ {{# if(d.sendcnt == 0){ }}
+ <a class="layui-btn layui-btn-xs" lay-event="modify">修改</a>
+ <a class="layui-btn layui-btn-xs layui-btn-danger" lay-event="delete">删除</a>
+ {{# } else{ }}
+ <a class="layui-btn layui-btn-xs layui-btn-normal" lay-event="detail">发布详情</a>
+ {{# } }}
+</script>
+
+<script>
+ layui.use(['form', 'table', 'layer', 'admin', 'laydate'], function () {
+ var form = layui.form;
+ var table = layui.table;
+ var admin = layui.admin;
+ var laydate = layui.laydate;
+
+ laydate.render({
+ elem: '#notice-search-startdate',
+ trigger: 'click'
+ });
+ laydate.render({
+ elem: '#notice-search-enddate',
+ trigger: 'click'
+ });
+
+ table.render({
+ elem: '#noticeSearchTable',
+ url: '[[@{/notice/list}]]',
+ page: true,
+ cols: [
+ [
+ {align: 'left', title: '操作', width: 170, toolbar: '#notice-table-bar', fixed: 'left'},
+ {field: 'title', title: '消息标题', align: 'left', width: 160, fixed: 'left', sort: true},
+ {field: 'content', title: '消息内容', align: 'left'},
+ {
+ field: 'platform',
+ title: '推送终端',
+ align: 'center',
+ width: 120,
+ sort: true,
+ templet: function (d) {
+ if ('all' == d.platform) {
+ return '全部手机';
+ } else if ('ios' == d.platform) {
+ return '苹果手机';
+ } else if ('android' == d.platform) {
+ return '安卓手机';
+ } else {
+ return d.platform;
+ }
+ }
+ },
+ {field: 'sendcnt', title: '发布次数', align: 'center', width: 120, sort: true},
+ {field: 'creator', title: '创建者', align: 'center', width: 140, sort: true},
+ {
+ field: 'createdate',
+ title: '创建时间',
+ align: 'center',
+ width: 170,
+ sort: true,
+ templet: function (d) {
+ return admin.formatDate(d.createdate + '' + d.createtime);
+ }
+ },
+ {
+ field: 'lastsaved',
+ title: '最后更新时间',
+ align: 'center',
+ width: 170,
+ sort: true,
+ templet: function (d) {
+ return admin.formatDate(d.lastsaved);
+ }
+ }
+ ]
+ ]
+ });
+
+ $("#notice-search-btn").click(function () {
+ table.reload('noticeSearchTable', {
+ where: {
+ startdate: $("#notice-search-startdate").val(),
+ enddate: $("#notice-search-enddate").val(),
+ searchkey: $("#notice-search-searchkey").val()
+ }, page: {curr: 1}
+ });
+ });
+
+ $("#notice-search-btn-reset").click(function () {
+ $("#notice-search-startdate").val("");
+ $("#notice-search-enddate").val("");
+ $("#notice-search-searchkey").val("");
+ });
+
+ $("#btn-notice-add").click(function () {
+ showNoticeModel("新增公告", {
+ noticeId: '',
+ platform: 'all',
+ title: '',
+ content: '',
+ linkurl: ''
+ })
+ });
+
+ function showNoticeModel(title, data) {
+ admin.putTempData('t_noticeTmp', data);
+ admin.popupCenter({
+ title: title,
+ area: '650px',
+ path: '[[@{/notice/load4add}]]',
+ finish: function () {
+ table.reload('noticeSearchTable', {});
+ }
+ });
+ }
+
+ function showNoticePublishModel(data) {
+ admin.putTempData('t_noticePubidTmp', {
+ noticeId: data.id,
+ pushmode: 'atonce',
+ settime: ''
+ });
+ admin.popupCenter({
+ title: '发布通知公告【' + data.title + '】',
+ area: '550px',
+ path: '[[@{/notice/load4publish}]]',
+ finish: function () {
+ table.reload('noticeSearchTable', {});
+ }
+ });
+ }
+
+ function deleteNotice(data) {
+ layer.confirm('确定删除公告【' + data.title + '】吗?', function (i) {
+ layer.close(i);
+ layer.load(2);
+ admin.go('[[@{/notice/delete}]]', {
+ noticeId: data.id,
+ _csrf: $("meta[name='_csrf_token']").attr("value")
+ }, function (data) {
+ layer.closeAll('loading');
+ if (data.code == 200) {
+ layer.msg(data.msg, {icon: 1});
+ } else if (data.code == 401) {
+ layer.msg(data.msg, {icon: 2, time: 1500}, function () {
+ location.replace('[[@{/login}]]');
+ }, 1000);
+ return;
+ } else {
+ layer.msg(data.msg, {icon: 2});
+ }
+ table.reload('noticeSearchTable');
+ }, function (ret) {
+ console.log(ret);
+ admin.errorBack(ret);
+ });
+ })
+ }
+
+ function showNoticePublishDetailsModel(data) {
+ admin.putTempData('t_noticePublishDetail', data);
+ admin.popupCenter({
+ title: '通知公告【' + data.title + '】发布详情',
+ area: '750px',
+ path: '[[@{/notice/load4detail}]]',
+ finish: function () {
+ table.reload('noticeSearchTable', {});
+ }
+ });
+ }
+
+
+ //监听单元格
+ table.on('tool(noticeSearchTable-filter)', function (obj) {
+ var data = obj.data;
+ switch (obj.event) {
+ case "publish":
+ showNoticePublishModel(data);
+ break;
+ case "modify":
+ showNoticeModel("修改公告", {
+ noticeId: data.id,
+ platform: data.platform,
+ title: data.title,
+ content: data.content,
+ linkurl: data.linkurl
+ });
+ break;
+ case "delete":
+ deleteNotice(data);
+ break;
+ case "detail":
+ showNoticePublishDetailsModel(data);
+ break;
+ }
+ });
+ });
+</script>
diff --git a/payapi/src/main/resources/templates/system/notice/publish.html b/payapi/src/main/resources/templates/system/notice/publish.html
new file mode 100644
index 0000000..621749b
--- /dev/null
+++ b/payapi/src/main/resources/templates/system/notice/publish.html
@@ -0,0 +1,85 @@
+<form id="notice-publish-form" lay-filter="notice-publish-form" class="layui-form model-form">
+ <input name="noticeId" id="hidden-notice-publish-noticeid" type="hidden"/>
+ <div class="layui-form-item">
+ <label class="layui-form-label"><span style="color: red;">*</span>发布时间</label>
+ <div class="layui-input-block">
+ <input type="radio" name="pushmode" value="atonce" title="立即发布" lay-filter="notice-publish-form-pushmode-filter"/>
+ <input type="radio" name="pushmode" value="delay" title="定时发布" lay-filter="notice-publish-form-pushmode-filter"/>
+ </div>
+ </div>
+ <div class="layui-form-item" id="hidden-div-set-delaytime" style="display: none;">
+ <label class="layui-form-label"><span style="color: red;">*</span>设定时间</label>
+ <div class="layui-input-block">
+ <input name="settime" type="text" id="notice-publish-form-settime" style="width: 195px;" class="layui-input" autocomplete="off" lay-verify="pushmode"/>
+ </div>
+ </div>
+
+ <div class="layui-form-item model-form-footer">
+ <button class="layui-btn layui-btn-primary" type="button" ew-event="closeDialog">取消</button>
+ <button class="layui-btn" lay-filter="notice-publish-form-submit" lay-submit id="notice-publish-submit-btn">保存</button>
+ </div>
+</form>
+
+<script>
+ layui.use(['layer', 'admin', 'form', 'laydate'], function () {
+ var layer = layui.layer;
+ var admin = layui.admin;
+ var form = layui.form;
+ var laydate = layui.laydate;
+
+ form.render('radio');
+ form.verify({
+ pushmode: function (value, item) {
+ var pushmode = $("#notice-publish-form").find("input[name='pushmode']:checked").val();
+ if('atonce' != pushmode && isempty(value)){
+ return "定时发布请设定时间";
+ }
+ }
+ });
+ form.on('radio(notice-publish-form-pushmode-filter)', function (data) {
+ if('atonce'==data.value){
+ $("#notice-publish-form-settime").val("");
+ $("#hidden-div-set-delaytime").hide();
+ }else{
+ $("#hidden-div-set-delaytime").show();
+ }
+ });
+ laydate.render({
+ elem: '#notice-publish-form-settime',
+ type: 'datetime',
+ min: moment().locale('zh-cn').format('YYYY-MM-DD HH:mm:ss'),
+ trigger: 'click'
+ });
+ var bean = admin.getTempData('t_noticePubidTmp');
+ if (bean) {
+ form.val('notice-publish-form', bean);
+ }
+
+ // 表单提交事件
+ form.on('submit(notice-publish-form-submit)', function (data) {
+ layer.load(2);
+ var param = data.field;
+ var token = $("meta[name='_csrf_token']").attr("value");
+ param["_csrf"] = token;
+ admin.go('[[@{/notice/publish}]]', param, function (result) {
+ console.log(result);
+ layer.closeAll('loading');
+ if (result.code == 200) {
+ layer.msg(result.msg, {icon: 1});
+ admin.finishPopupCenter();
+ } else if (result.code == 401) {
+ layer.msg(result.msg, {icon: 2, time: 1500}, function () {
+ location.replace('[[@{/login}]]');
+ }, 1000);
+ return;
+ } else {
+ layer.msg(result.msg, {icon: 2});
+ }
+ }, function (ret) {
+ console.log(ret);
+ admin.errorBack(ret);
+ });
+ return false;
+ });
+ });
+</script>
\ No newline at end of file