提交 e17de092 编写于 作者: 小柒2012

系统消息通知推送

上级 76683369
package com.tools.module.app.entity;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.tools.common.model.PageBean;
import lombok.Data;
import javax.persistence.*;
import java.io.Serializable;
import java.sql.Timestamp;
import static javax.persistence.GenerationType.IDENTITY;
@Data
@Entity
@Table(name = "app_notice")
public class AppNotice extends PageBean implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 自增主键
*/
@Id
@GeneratedValue(strategy = IDENTITY)
@Column(name = "id", unique = true, nullable = false)
private Long id;
/**
* 通道
*/
@Column(name = "channel", nullable = false, length = 200)
private String channel;
/**
* 发送内容
*/
@Column(name = "content", nullable = false, length = 65535)
private String content;
/**
* 创建时间
*/
@Column(name = "gmt_create")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Timestamp gmtCreate;
/**
* 创建人ID
*/
@Column(name="user_create", length = 20)
private Long userCreate;
/**
* 创建人(昵称)
*/
@Column(name = "nickname", length = 50)
private String nickname;
}
\ No newline at end of file
package com.tools.module.app.repository;
import com.tools.module.app.entity.AppNotice;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface AppNoticeRepository extends JpaRepository<AppNotice, Long> {
}
\ No newline at end of file
package com.tools.module.app.service.impl;
import com.tools.common.dynamicquery.DynamicQuery;
import com.tools.common.model.PageBean;
import com.tools.common.model.Result;
import com.tools.common.util.DateUtils;
import com.tools.module.app.repository.AppNoticeRepository;
import com.tools.module.app.entity.AppNotice;
import com.tools.module.app.service.AppNoticeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@Service
public class AppNoticeServiceImpl implements AppNoticeService {
@Autowired
private DynamicQuery dynamicQuery;
@Autowired
private AppNoticeRepository noticeRepository;
@Override
@Transactional(rollbackFor = Exception.class)
public Result save(AppNotice notice) {
notice.setGmtCreate(DateUtils.getTimestamp());
noticeRepository.saveAndFlush(notice);
return Result.ok("保存成功");
}
@Override
public Result get(Long id) {
AppNotice notice = noticeRepository.getOne(id);
return Result.ok(notice);
}
@Override
@Transactional(rollbackFor = Exception.class)
public Result delete(Long id) {
noticeRepository.deleteById(id);
return Result.ok("删除成功");
}
@Override
public Result list(AppNotice notice) {
String nativeSql = "SELECT COUNT(*) FROM app_notice";
Long count = dynamicQuery.nativeQueryCount(nativeSql);
PageBean<AppNotice> data = new PageBean<>();
if(count>0){
nativeSql = "SELECT * FROM app_notice ORDER BY gmt_create desc";
Pageable pageable = PageRequest.of(notice.getPageNo(),notice.getPageSize());
List<AppNotice> list = dynamicQuery.nativeQueryPagingList(AppNotice.class,pageable,nativeSql);
data = new PageBean(list,count);
}
return Result.ok(data);
}
}
package com.tools.module.app.util;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
@Data
@ConfigurationProperties(prefix = "push")
public class PushProperties {
/**
* 区域
*/
private String url;
/**
* 既可以发送消息或也可以订阅channel来接收消息
*/
private String commonKey;
/**
* 只能用来订阅channel来接收消息
*/
private String subscribeKey;
}
package com.tools.module.app.util;
import com.tools.common.model.Result;
import com.tools.module.app.entity.AppNotice;
import org.json.JSONObject;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
/**
* 消息推送
*/
@Component
@Configuration
@EnableConfigurationProperties({PushProperties.class})
public class PushUtils {
private PushProperties push;
public PushUtils(PushProperties push) {
this.push = push;
}
public String send(AppNotice notice){
RestTemplate client = new RestTemplate();
MultiValueMap<String, Object> paramMap = new LinkedMultiValueMap<>();
paramMap.add("content", notice.getContent());
paramMap.add("channel", notice.getChannel()==null?"SPTools":notice.getChannel());
paramMap.add("appkey", push.getCommonKey());
return client.postForObject(push.getUrl(), paramMap , String.class);
}
}
......@@ -135,7 +135,7 @@ public class GenController {
/**
* 生成后端代码 service 实现
*/
createCode("java/serviceImplFile.ftl", gen,serviceImplFile);
createCode("java/serviceImpl.ftl", gen,serviceImplFile);
/**
* 生成后端代码 controller 实现
*/
......
package com.tools.module.app.web;
import com.tools.common.config.AbstractController;
import com.tools.common.model.Result;
import com.tools.common.util.ShiroUtils;
import com.tools.module.app.entity.AppNotice;
import com.tools.module.app.service.AppNoticeService;
import com.tools.module.app.util.PushUtils;
import com.tools.module.sys.entity.SysUser;
import io.swagger.annotations.Api;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 消息管理
* 爪哇笔记:https://blog.52itstyle.vip
*/
@Api(tags ="消息管理")
@RestController
@RequestMapping("/app/notice")
public class NoticeController extends AbstractController {
@Autowired
private PushUtils pushUtils;
@Autowired
private AppNoticeService noticeService;
/**
* 推送
*/
@PostMapping("/save")
public Result save(@RequestBody AppNotice notice){
String msg = pushUtils.send(notice);
JSONObject json = new JSONObject(msg);
String code = json.get("code").toString();
if("200".equals(code)){
SysUser user = ShiroUtils.getUserEntity();
notice.setUserCreate(user.getUserId());
notice.setNickname(user.getNickname());
noticeService.save(notice);
return Result.ok();
}else{
return Result.error();
}
}
/**
* 列表
*/
@PostMapping("/list")
public Result list(AppNotice notice){
return noticeService.list(notice);
}
/**
* 查询
*/
@PostMapping("/get")
public Result get(Long id){
return noticeService.get(id);
}
/**
* 删除
*/
@PostMapping("/delete")
public Result delete(Long id){
return noticeService.delete(id);
}
}
......@@ -149,4 +149,11 @@ ali-yun.oss.url = **********
# ===================================
bai-du.appId = **********
bai-du.apiKey = **********
bai-du.accessKeySecret = **********
\ No newline at end of file
bai-du.accessKeySecret = **********
# ===================================
# 消息推送
# ===================================
push.url= **********
push.commonKey = **********
push.subscribeKey= **********
\ No newline at end of file
#镜像信息
FROM tomcat:8.5
#维护者
MAINTAINER 10000@qq.com
#将webapp下的全部删除
RUN rm -rf /usr/local/tomcat/webapps/*
#ROOT.war拷贝到/usr/local/tomcat/webapps/下
ADD ROOT.war /usr/local/tomcat/webapps/
#端口
EXPOSE 8080
#设置启动命令
ENTRYPOINT ["/usr/local/tomcat/bin/catalina.sh","run"]
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<!-- scan 配置文件如果发生改变,将会被重新加载 scanPeriod 检测间隔时间 BY 科帮网 小柒2012 欢迎关注博客https://blog.52itstyle.com-->
<configuration scan="true" scanPeriod="60 seconds" debug="false">
<contextName>picture-bed</contextName>
<contextName>SPTools</contextName>
<include resource="org/springframework/boot/logging/logback/base.xml"/>
<!-- 普通日志 -->
<appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
......@@ -9,7 +9,7 @@
<!-- 循环政策:基于时间创建日志文件 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志命名:单个文件大于128MB 按照时间+自增i 生成log文件 -->
<fileNamePattern>log/picture-bed-info-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<fileNamePattern>log/SPTools-info-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>128MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
......@@ -33,7 +33,7 @@
<!-- 循环政策:基于时间创建日志文件 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志命名:单个文件大于2MB 按照时间+自增i 生成log文件 -->
<fileNamePattern>log/picture-bed-error-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<fileNamePattern>log/SPTools-error-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>2MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
......
layui.use(["okUtils", "okLayer"], function () {
var okLayer = layui.okLayer;
//消息推送
var goEasy = new GoEasy({
host:'hangzhou.goeasy.io',
appkey: "BS-261fbed4d0f249859b554aa16303df49",
});
goEasy.subscribe({
channel: "SPTools",
onMessage: function (message) {
okLayer.confirm(message.content);
}
});
});
\ No newline at end of file
......@@ -87,7 +87,7 @@ layui.use(["okUtils", "okLayer"], function () {
pageNo : 1,
description:''
},
tableSize : 50,
tableSize : 0,
}
},
methods: {
......
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head th:replace="common/head :: head(links)"/>
<body>
<div class="ok-body" id="app" v-cloak>
<template>
<i-form ref="checkForm" :model="notice" :rules="ruleValidate" :label-width="100">
<form-item prop="content" label="内容:">
<i-input maxlength="500" v-model="notice.content" :autosize="{minRows: 5,maxRows: 5}" type="textarea" placeholder="请输入内容"></i-input>
</form-item>
</i-form>
</template>
</div>
<div th:replace="common/foot :: foot(script)"></div>
<script th:inline="none">
var vm = new Vue({
el: '#app',
data:{
notice:{
channel:'SPTools'
},
ruleValidate : {
content: [
{ required: true, message: '内容不能为空', trigger: 'blur' }
]
}
},
methods: {
acceptClick : function(dialog){
vm.$refs.checkForm.validate(function(valid){
if (valid) {
layui.use(["okUtils", "okLayer"], function () {
okUtils = layui.okUtils;
okLayer = layui.okLayer;
okUtils.ajaxCloud({
url:"/app/notice/save",
param : vm.notice,
json:true,
success : function(result) {
okLayer.msg.greenTick(result.msg, function () {
dialog.load();
})
}
});
});
}
});
}
},
created: function() {
}
});
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head th:replace="common/head :: head(link)"/>
<body>
<div id="app" class="ok-body" v-cloak>
<!--模糊搜索区域-->
<template>
<div style="margin-bottom: 8px;margin-top: 8px;">
<i-input placeholder="输入内容" v-model="table.description" style="width: 300px"></i-input>
<i-button type="primary" icon="ios-search" @click="load()">搜索</i-button>
<i-button type="primary" icon="ios-redo" @click="reload()" >重置</i-button>
<i-button type="primary" style="float:right;" icon="md-add" @click="add()">新增</i-button>
</div>
</template>
<template>
<i-table size="small" :columns="tableTitle" :data="tableData">
</i-table>
<br>
<Page style="float: right;" :current="table.pageNo" :total="tableSize" :page-size="table.pageSize" @on-change="changePage" @on-page-size-change="changePageSize" show-elevator show-sizer show-total></Page>
</template>
</div>
<div th:replace="common/foot :: foot(script)"></div>
<script th:inline="none">
layui.use(["okUtils", "okLayer"], function () {
var okUtils = layui.okUtils;
var okLayer = layui.okLayer;
var vm = new Vue({
el: '#app',
data: function(){
var that = this;
return {
tableTitle : [{
title: '序号',
minWidth : 100,
render: function(h, params) {
return h('span', params.index + (that.table.pageNo- 1) * that.table.pageSize + 1);
}
},{
key : "channel",
title : "通道",
minWidth:100
},{
key : "content",
title : "内容",
minWidth:100
},{
key : "gmtCreate",
title : "创建时间",
minWidth:100
},{
key : "nickname",
title : "创建人",
minWidth:100
},{
title : '操作',
key : 'action',
minWidth : 300,
align : 'center',
render : function(h, params) {
var functionList = [];
var remove = h('Button', {
props : {
type : 'primary',
size : 'small',
icon : 'md-trash'
},
style : {
marginRight : '8px'
},
on : {
click : function() {
vm.remove(params.row);
}
}
}, '删除');
functionList.push(remove);
return h('div', functionList);
}
} ],
tableData : [],
table : {
pageSize : 10,
pageNo : 1,
description:''
},
tableSize : 50,
}
},
methods: {
load : function() {
var that = this;
okUtils.ajaxCloud({
url:"/app/notice/list",
param : that.table,
success : function(result) {
that.tableData = result.msg.pageData;
that.tableSize = result.msg.totalCount;
}
});
},
reload : function(){
vm.table.pageSize = 10;
vm.table.pageNo = 1;
vm.table.description = '';
this.load();
},
changePage : function(pageNo) {
vm.table.pageNo = pageNo;
vm.load();
},
changePageSize : function(pageSize) {
vm.table.pageSize = pageSize;
vm.load();
},
add:function(){
okUtils.dialogOpen({
title: '推送',
url: "app/notice/form.html",
scroll : true,
width: '30%',
height: '40%',
yes : function(dialog) {
dialog.vm.acceptClick(vm);
}
});
},
remove : function (notice) {
okLayer.confirm("确定要删除吗?", function () {
okUtils.ajaxCloud({
url:"/app/notice/delete",
param : {id: notice.id},
success : function(result) {
okLayer.msg.greenTick(result.msg, function () {
vm.load();
});
}
});
});
},
},
created: function() {
this.load()
}
})
});
</script>
</body>
</html>
......@@ -152,6 +152,9 @@
</div>
<script type="text/javascript" th:src="@{/lib/layui/layui.js}"></script>
<script type="text/javascript" th:src="@{/js/console.js}"></script>
<!---消息推送--->
<script type="text/javascript" src="https://cdn.goeasy.io/goeasy-1.0.6.js"></script>
<script type="text/javascript" th:src="@{/js/common.js}"></script>
</body>
</html>
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册