diff --git a/ant-design-vue-jeecg/package.json b/ant-design-vue-jeecg/package.json
index 5002671..8506971 100644
--- a/ant-design-vue-jeecg/package.json
+++ b/ant-design-vue-jeecg/package.json
@@ -32,6 +32,7 @@
     "lodash.get": "^4.4.2",
     "lodash.pick": "^4.4.0",
     "md5": "^2.2.1",
+    "moment": "^2.29.4",
     "nprogress": "^0.2.0",
     "qiankun": "^2.5.1",
     "tinymce": "5.4.1",
diff --git a/ant-design-vue-jeecg/src/main.js b/ant-design-vue-jeecg/src/main.js
index 28420a6..82a9e9e 100644
--- a/ant-design-vue-jeecg/src/main.js
+++ b/ant-design-vue-jeecg/src/main.js
@@ -25,6 +25,10 @@ import Print from 'vue-print-nb-jeecg'
 import preview from 'vue-photo-preview'
 import 'vue-photo-preview/dist/skin.css'
 import SSO from '@/cas/sso.js'
+
+import moment from "moment"
+Vue.prototype.$moment = moment
+
 import {
   ACCESS_TOKEN,
   DEFAULT_COLOR,
diff --git a/ant-design-vue-jeecg/src/views/system/monitor/ApiLogList.vue b/ant-design-vue-jeecg/src/views/system/monitor/ApiLogList.vue
index dc6a964..08e88f0 100644
--- a/ant-design-vue-jeecg/src/views/system/monitor/ApiLogList.vue
+++ b/ant-design-vue-jeecg/src/views/system/monitor/ApiLogList.vue
@@ -23,47 +23,50 @@
               <j-input placeholder="请输入响应方名称" v-model="queryParam.responseBy"></j-input>
             </a-form-item>
           </a-col>
-          <template v-if="toggleSearchStatus">
-            <a-col :xl="6" :lg="7" :md="8" :sm="24">
-              <a-form-item label="请求地址">
-                <j-input placeholder="请输入请求地址" v-model="queryParam.url"></j-input>
-              </a-form-item>
-            </a-col>
-            <a-col :xl="6" :lg="7" :md="8" :sm="24">
-              <a-form-item label="请求内容">
-                <j-input placeholder="请输入请求内容" v-model="queryParam.requestBody"></j-input>
-              </a-form-item>
-            </a-col>
-            <a-col :xl="12" :lg="14" :md="16" :sm="24">
-              <a-form-item label="请求时间">
-                <j-date
-                  :show-time="true"
-                  date-format="YYYY-MM-DD HH:mm:ss"
-                  placeholder="请选择开始时间"
-                  class="query-group-cust"
-                  v-model="queryParam.requestTime_begin"
-                />
-                <span class="query-group-split-cust"></span>
-                <j-date
-                  :show-time="true"
-                  date-format="YYYY-MM-DD HH:mm:ss"
-                  placeholder="请选择结束时间"
-                  class="query-group-cust"
-                  v-model="queryParam.requestTime_end"
-                />
-              </a-form-item>
-            </a-col>
-            <a-col :xl="6" :lg="7" :md="8" :sm="24">
-              <a-form-item label="业务响应码">
-                <a-input placeholder="请输入业务响应码" v-model="queryParam.retCode"></a-input>
-              </a-form-item>
-            </a-col>
-            <a-col :xl="6" :lg="7" :md="8" :sm="24">
-              <a-form-item label="响应耗时(毫秒)">
-                <a-input placeholder="请输入大于响应耗时" v-model="queryParam.duration_begin"></a-input>
-              </a-form-item>
-            </a-col>
-          </template>
+          <a-col :xl="6" :lg="7" :md="8" :sm="24">
+            <a-form-item label="请求地址">
+              <j-input placeholder="请输入请求地址" v-model="queryParam.url"></j-input>
+            </a-form-item>
+          </a-col>
+          <a-col :xl="6" :lg="7" :md="8" :sm="24">
+            <a-form-item label="请求内容">
+              <j-input placeholder="请输入请求内容" v-model="queryParam.requestBody"></j-input>
+            </a-form-item>
+          </a-col>
+          <a-col :xl="6" :lg="7" :md="8" :sm="24">
+            <a-form-item label="响应内容">
+              <j-input placeholder="请输入请求内容" v-model="queryParam.responseBody"></j-input>
+            </a-form-item>
+          </a-col>
+          <a-col :xl="12" :lg="14" :md="16" :sm="24">
+            <a-form-item label="请求时间">
+              <j-date
+                :show-time="true"
+                date-format="YYYY-MM-DD HH:mm:ss"
+                placeholder="请选择开始时间"
+                class="query-group-cust"
+                v-model="queryParam.requestTime_begin"
+              />
+              <span class="query-group-split-cust"></span>
+              <j-date
+                :show-time="true"
+                date-format="YYYY-MM-DD HH:mm:ss"
+                placeholder="请选择结束时间"
+                class="query-group-cust"
+                v-model="queryParam.requestTime_end"
+              />
+            </a-form-item>
+          </a-col>
+          <a-col :xl="6" :lg="7" :md="8" :sm="24">
+            <a-form-item label="业务响应码">
+              <a-input placeholder="请输入业务响应码" v-model="queryParam.retCode"></a-input>
+            </a-form-item>
+          </a-col>
+          <a-col :xl="6" :lg="7" :md="8" :sm="24">
+            <a-form-item label="响应耗时(毫秒)">
+              <a-input placeholder="请输入大于响应耗时" v-model="queryParam.duration_begin"></a-input>
+            </a-form-item>
+          </a-col>
           <a-col :xl="6" :lg="7" :md="8" :sm="24">
             <span style="float: left;overflow: hidden;" class="table-page-search-submitButtons">
               <a-button type="primary" @click="searchQuery" icon="search">查询</a-button>
@@ -134,6 +137,7 @@
 </template>
 
 <script>
+import moment from 'moment'
 import '@/assets/less/TableExpand.less'
 import { mixinDevice } from '@/utils/mixin'
 import { JeecgListMixin } from '@/mixins/JeecgListMixin'
@@ -153,6 +157,9 @@ export default {
     return {
       description: '接口日志管理页面',
       apiNameList: [],
+      queryParam: {
+        requestTime_begin: this.getDefaultDate()
+      },
       // 表头
       columns: [
         {
@@ -236,6 +243,11 @@ export default {
     }
   },
   methods: {
+    getDefaultDate() {
+      var tempDate = new Date()
+      tempDate.setDate(tempDate.getDate() - 7)
+      return moment(tempDate).utcOffset(480).format('YYYY-MM-DD HH:mm:ss');
+    },
     loadFrom() {
       getApiNameList().then((res) => {
         if (res.success) {
diff --git a/huaheng-wms-core/pom.xml b/huaheng-wms-core/pom.xml
index aba8680..1b36c8a 100644
--- a/huaheng-wms-core/pom.xml
+++ b/huaheng-wms-core/pom.xml
@@ -22,6 +22,17 @@
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter</artifactId>
         </dependency>
+        
+        <!--         <dependency> -->
+<!--             <groupId>net.javacrumbs.shedlock</groupId> -->
+<!--             <artifactId>shedlock-spring</artifactId> -->
+<!--             <version>4.46.0</version> -->
+<!--         </dependency> -->
+<!--         <dependency> -->
+<!--             <groupId>net.javacrumbs.shedlock</groupId> -->
+<!--             <artifactId>shedlock-provider-jdbc-template</artifactId> -->
+<!--             <version>4.46.0</version> -->
+<!--         </dependency> -->
 
         <dependency>
             <groupId>org.jeecgframework.boot</groupId>
diff --git a/huaheng-wms-core/src/main/java/org/jeecg/JeecgSystemApplication.java b/huaheng-wms-core/src/main/java/org/jeecg/JeecgSystemApplication.java
index 1d1c0bd..6a35023 100644
--- a/huaheng-wms-core/src/main/java/org/jeecg/JeecgSystemApplication.java
+++ b/huaheng-wms-core/src/main/java/org/jeecg/JeecgSystemApplication.java
@@ -18,6 +18,7 @@ import org.springframework.context.annotation.ComponentScan;
 import org.springframework.context.annotation.ComponentScan.Filter;
 import org.springframework.context.annotation.FilterType;
 import org.springframework.core.env.Environment;
+import org.springframework.scheduling.annotation.EnableScheduling;
 
 import lombok.extern.slf4j.Slf4j;
 
@@ -26,6 +27,8 @@ import lombok.extern.slf4j.Slf4j;
  */
 @Slf4j
 @EnableCaching
+@EnableScheduling
+//@EnableSchedulerLock(defaultLockAtMostFor = "PT30S") // 默认最长等待时间30秒
 @SpringBootApplication
 @EnableAutoConfiguration(exclude = {MongoAutoConfiguration.class})
 @ComponentScan(excludeFilters = {@Filter(type = FilterType.REGEX, pattern = {"org.jeecg.config.mybatis.MybatisInterceptor", "org.jeecg.config.Swagger2Config"})})
diff --git a/huaheng-wms-core/src/main/java/org/jeecg/modules/message/websocket/WebSocket.java b/huaheng-wms-core/src/main/java/org/jeecg/modules/message/websocket/WebSocket.java
index 7eba3e8..4070a46 100644
--- a/huaheng-wms-core/src/main/java/org/jeecg/modules/message/websocket/WebSocket.java
+++ b/huaheng-wms-core/src/main/java/org/jeecg/modules/message/websocket/WebSocket.java
@@ -17,6 +17,7 @@ import javax.websocket.server.ServerEndpoint;
 import org.jeecg.common.base.BaseMap;
 import org.jeecg.common.constant.WebsocketConst;
 import org.jeecg.common.modules.redis.client.JeecgRedisClient;
+import org.jeecg.modules.system.entity.SysAnnouncement;
 import org.jeecg.modules.system.entity.SysUser;
 import org.springframework.scheduling.annotation.Async;
 import org.springframework.stereotype.Component;
@@ -160,6 +161,35 @@ public class WebSocket {
     }
 
     /**
+     * 发送系统消息
+     * @param userId
+     * @param sysAnnouncement
+     */
+    public void sendMessage(int userId, SysAnnouncement sysAnnouncement){
+        sendMessage(String.valueOf(userId), createJson(sysAnnouncement));
+    }
+
+    public void sendMessage(List<SysUser> userList, SysAnnouncement announcement){
+        userList.forEach(user -> sendMessage(user.getId(), announcement));
+    }
+
+    private String createJson(SysAnnouncement announcement){
+        JSONObject obj = new JSONObject();
+        obj.put(WebsocketConst.MSG_CMD, WebsocketConst.CMD_TOPIC);
+        obj.put(WebsocketConst.MSG_ID, announcement.getId());
+        obj.put(WebsocketConst.MSG_TXT, announcement.getTitile());
+        return obj.toJSONString();
+    }
+
+    /**
+     * 广播系统消息
+     * @param sysAnnouncement
+     */
+    public void sendMessage(SysAnnouncement sysAnnouncement){
+        sendMessage(createJson(sysAnnouncement));
+    }
+
+    /**
      * 此为单点消息(多人)
      * @param userIds
      * @param message
diff --git a/huaheng-wms-core/src/main/java/org/jeecg/modules/system/controller/LoginController.java b/huaheng-wms-core/src/main/java/org/jeecg/modules/system/controller/LoginController.java
index aa52702..f6d4fc5 100644
--- a/huaheng-wms-core/src/main/java/org/jeecg/modules/system/controller/LoginController.java
+++ b/huaheng-wms-core/src/main/java/org/jeecg/modules/system/controller/LoginController.java
@@ -22,7 +22,6 @@ import org.apache.shiro.SecurityUtils;
 import org.jeecg.common.api.vo.Result;
 import org.jeecg.common.constant.CacheConstant;
 import org.jeecg.common.constant.CommonConstant;
-import org.jeecg.common.constant.WebsocketConst;
 import org.jeecg.common.system.api.ISysBaseAPI;
 import org.jeecg.common.system.util.JwtUtil;
 import org.jeecg.common.system.vo.LoginUser;
@@ -34,7 +33,6 @@ import org.jeecg.common.util.RedisUtil;
 import org.jeecg.common.util.oConvertUtils;
 import org.jeecg.common.util.encryption.EncryptedString;
 import org.jeecg.modules.base.service.BaseCommonService;
-import org.jeecg.modules.message.websocket.WebSocket;
 import org.jeecg.modules.system.entity.SysDepart;
 import org.jeecg.modules.system.entity.SysTenant;
 import org.jeecg.modules.system.entity.SysUser;
@@ -46,7 +44,6 @@ import org.jeecg.modules.system.service.ISysLogService;
 import org.jeecg.modules.system.service.ISysTenantService;
 import org.jeecg.modules.system.service.ISysUserService;
 import org.jeecg.modules.system.util.RandImageUtil;
-import org.jeecg.modules.wms.framework.service.IHuahengMultiHandlerService;
 import org.jeecg.utils.HuahengJwtUtil;
 import org.jeecg.utils.HuahengRedisUtil;
 import org.jeecg.utils.StringUtils;
@@ -59,8 +56,6 @@ import org.springframework.beans.factory.annotation.Value;
 import org.springframework.context.annotation.Bean;
 import org.springframework.core.io.DefaultResourceLoader;
 import org.springframework.core.io.ResourceLoader;
-import org.springframework.scheduling.annotation.Async;
-import org.springframework.scheduling.annotation.EnableAsync;
 import org.springframework.util.FileCopyUtils;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.PathVariable;
@@ -79,7 +74,6 @@ import com.auth0.jwt.JWTVerifier;
 import com.auth0.jwt.algorithms.Algorithm;
 import com.auth0.jwt.exceptions.JWTVerificationException;
 import com.auth0.jwt.exceptions.TokenExpiredException;
-import com.auth0.jwt.interfaces.DecodedJWT;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.IdWorker;
 
@@ -204,7 +198,7 @@ public class LoginController {
         baseCommonService.addLog("用户名:" + username + ",登录成功!", CommonConstant.LOG_TYPE_1, null, loginUser);
         // update-end--Author:wangshuai Date:20200714 for:登录日志没有记录人员
 
-        systemSync.sendMaterialAlarm(sysUser);
+        systemSync.sendSysAnnouncement(sysUser);
         return result;
     }
 
diff --git a/huaheng-wms-core/src/main/java/org/jeecg/modules/system/controller/SysAnnouncementController.java b/huaheng-wms-core/src/main/java/org/jeecg/modules/system/controller/SysAnnouncementController.java
index 49606e2..0660842 100644
--- a/huaheng-wms-core/src/main/java/org/jeecg/modules/system/controller/SysAnnouncementController.java
+++ b/huaheng-wms-core/src/main/java/org/jeecg/modules/system/controller/SysAnnouncementController.java
@@ -3,10 +3,8 @@ package org.jeecg.modules.system.controller;
 import static org.jeecg.common.constant.CommonConstant.ANNOUNCEMENT_SEND_STATUS_1;
 
 import java.io.IOException;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
+import java.util.stream.Collectors;
 
 import javax.annotation.Resource;
 import javax.servlet.http.HttpServletRequest;
@@ -345,9 +343,12 @@ public class SysAnnouncementController {
         querySaWrapper.eq(SysAnnouncement::getSendStatus, CommonConstant.HAS_SEND); // 已发布
         querySaWrapper.ge(SysAnnouncement::getEndTime, new Date()); // 新注册用户不看结束通知
         // update-begin--Author:liusq Date:20210108 for:[JT-424] 【开源issue】bug处理--------------------
-        querySaWrapper.notInSql(SysAnnouncement::getId, "select annt_id from sys_announcement_send where user_id ='" + userId + "'");
+        querySaWrapper.notInSql(SysAnnouncement::getId, "select annt_id from sys_announcement_send where user_id ='" + userId + "' and read_flag='1'");
         // update-begin--Author:liusq Date:20210108 for: [JT-424] 【开源issue】bug处理--------------------
         List<SysAnnouncement> announcements = sysAnnouncementService.list(querySaWrapper);
+        announcements = announcements.stream().filter(a-> CommonConstant.MSG_TYPE_ALL.equals(a.getMsgType())
+                || (a.getUserIds() != null && Arrays.stream(a.getUserIds().split(",")).anyMatch(i->i.equals(userId)))).collect(Collectors.toList());
+
         if (announcements.size() > 0) {
             for (int i = 0; i < announcements.size(); i++) {
                 // update-begin--Author:wangshuai Date:20200803 for: 通知公告消息重复LOWCOD-759--------------------
diff --git a/huaheng-wms-core/src/main/java/org/jeecg/modules/system/service/ISysAnnouncementService.java b/huaheng-wms-core/src/main/java/org/jeecg/modules/system/service/ISysAnnouncementService.java
index 862f16c..7fec723 100644
--- a/huaheng-wms-core/src/main/java/org/jeecg/modules/system/service/ISysAnnouncementService.java
+++ b/huaheng-wms-core/src/main/java/org/jeecg/modules/system/service/ISysAnnouncementService.java
@@ -4,6 +4,11 @@ import org.jeecg.modules.system.entity.SysAnnouncement;
 
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.IService;
+import org.jeecg.modules.system.entity.SysRole;
+import org.jeecg.modules.system.entity.SysUser;
+
+import java.util.Date;
+import java.util.List;
 
 /**
  * @Description: 系统通告表
@@ -21,4 +26,8 @@ public interface ISysAnnouncementService extends IService<SysAnnouncement> {
 
     public Page<SysAnnouncement> querySysCementPageByUserId(Page<SysAnnouncement> page, String userId, String msgCategory);
 
+    public void quickAnnouncementToUser(List<SysUser> userList, String title, String msg, Date endTime, String level);
+
+    public void quickAnnouncementToRole(List<SysRole> roleList, String title, String msg, Date endTime, String level);
+
 }
diff --git a/huaheng-wms-core/src/main/java/org/jeecg/modules/system/service/impl/SysAnnouncementServiceImpl.java b/huaheng-wms-core/src/main/java/org/jeecg/modules/system/service/impl/SysAnnouncementServiceImpl.java
index ab6f896..0c90090 100644
--- a/huaheng-wms-core/src/main/java/org/jeecg/modules/system/service/impl/SysAnnouncementServiceImpl.java
+++ b/huaheng-wms-core/src/main/java/org/jeecg/modules/system/service/impl/SysAnnouncementServiceImpl.java
@@ -1,16 +1,20 @@
 package org.jeecg.modules.system.service.impl;
 
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Date;
-import java.util.List;
+import java.util.*;
+import java.util.stream.Collectors;
 
 import javax.annotation.Resource;
 
+import com.baomidou.mybatisplus.core.metadata.IPage;
 import org.jeecg.common.constant.CommonConstant;
+import org.jeecg.common.constant.CommonSendStatus;
+import org.jeecg.common.exception.JeecgBootException;
 import org.jeecg.common.util.oConvertUtils;
+import org.jeecg.modules.message.websocket.WebSocket;
 import org.jeecg.modules.system.entity.SysAnnouncement;
 import org.jeecg.modules.system.entity.SysAnnouncementSend;
+import org.jeecg.modules.system.entity.SysRole;
+import org.jeecg.modules.system.entity.SysUser;
 import org.jeecg.modules.system.mapper.SysAnnouncementMapper;
 import org.jeecg.modules.system.mapper.SysAnnouncementSendMapper;
 import org.jeecg.modules.system.service.ISysAnnouncementService;
@@ -36,10 +40,19 @@ public class SysAnnouncementServiceImpl extends ServiceImpl<SysAnnouncementMappe
     @Resource
     private SysAnnouncementSendMapper sysAnnouncementSendMapper;
 
+    @Resource
+    private SysAnnouncementSendServiceImpl sysAnnouncementSendService;
+
+    @Resource
+    private WebSocket webSocket;
+
+    @Resource
+    private SysUserServiceImpl sysUserService;
+
     @Transactional
     @Override
     public void saveAnnouncement(SysAnnouncement sysAnnouncement) {
-        if (sysAnnouncement.getMsgType().equals(CommonConstant.MSG_TYPE_ALL)) {
+        if (CommonConstant.MSG_TYPE_ALL.equals(sysAnnouncement.getMsgType())) {
             sysAnnouncementMapper.insert(sysAnnouncement);
         } else {
             // 1.插入通告表记录
@@ -60,6 +73,104 @@ public class SysAnnouncementServiceImpl extends ServiceImpl<SysAnnouncementMappe
         }
     }
 
+
+    /**
+     * 快速发送系统消息
+     * @param userList  目标用户, 为null时发送广播消息
+     * @param title     消息标题
+     * @param msg       消息内容
+     * @param endTime   消息有效期
+     * @param level     消息级别,H   M   L
+     */
+    @Override
+    public void quickAnnouncementToUser(List<SysUser> userList, String title, String msg, Date endTime, String level){
+        SysAnnouncement sysAnnouncement = new SysAnnouncement();
+        sysAnnouncement.setTitile(title);
+        sysAnnouncement.setMsgContent(msg);
+        sysAnnouncement.setEndTime(endTime);
+        sysAnnouncement.setPriority(level);
+        sysAnnouncement.setSendTime(new Date());
+        sysAnnouncement.setMsgCategory(CommonConstant.MSG_CATEGORY_2);
+        sysAnnouncement.setMsgAbstract(title);
+        sysAnnouncement.setMsgType(CommonConstant.MSG_TYPE_ALL);
+        sysAnnouncement.setSender("WMS");
+        sysAnnouncement.setDelFlag(CommonConstant.DEL_FLAG_0.toString());
+        sysAnnouncement.setSendStatus(CommonSendStatus.PUBLISHED_STATUS_1);
+        saveAnnouncement(sysAnnouncement);
+
+        if(userList == null) {
+            //发送广播消息
+            webSocket.sendMessage(sysAnnouncement);
+        }else if (userList.size() == 0){
+            throw new JeecgBootException("发送系统消息时,用户列表为空");
+        } else {
+            //发送给指定用户
+            // 2.插入用户通告阅读标记表记录
+            sysAnnouncement.setMsgType(CommonConstant.MSG_TYPE_UESR);
+            List<String> userIds = userList.stream().map(SysUser::getId).distinct().map(Object::toString).collect(Collectors.toList());
+            sysAnnouncement.setUserIds(String.join(",", userIds));
+            webSocket.sendMessage(userList, sysAnnouncement);
+        }
+        updateById(sysAnnouncement);
+    }
+
+    /**
+     * 快速发送系统消息
+     * @param roleList  目标角色
+     * @param title     消息标题
+     * @param msg       消息内容
+     * @param endTime   消息有效期
+     * @param level     消息级别,H   M   L
+     */
+    @Override
+    public void quickAnnouncementToRole(List<SysRole> roleList, String title, String msg, Date endTime, String level){
+        List<SysUser> userList = new ArrayList<>();
+        roleList.forEach(sysRole -> {
+            Page<SysUser> page = new Page<SysUser>(1, 9999);
+            String roleId = String.valueOf(sysRole.getId());
+            IPage<SysUser> pageList = sysUserService.getUserByRoleId(page, roleId, null);
+            userList.addAll(pageList.getRecords());
+        });
+        quickAnnouncementToUser(userList, title, msg, endTime, level);
+    }
+
+    /**
+     * 获取用户的新的通知消息,生成未读的消息记录
+     * @param sysUser
+     * @return
+     */
+    public List<SysAnnouncement> getNewAnnouncementOfUser(SysUser sysUser){
+        String userId = String.valueOf(sysUser.getId());
+        LambdaQueryWrapper<SysAnnouncement> querySaWrapper = new LambdaQueryWrapper<SysAnnouncement>();
+        // 未删除
+        querySaWrapper.eq(SysAnnouncement::getDelFlag, CommonConstant.DEL_FLAG_0.toString());
+        // 已发布
+        querySaWrapper.eq(SysAnnouncement::getSendStatus, CommonConstant.HAS_SEND);
+        // 新注册用户不看结束通知
+        querySaWrapper.ge(SysAnnouncement::getEndTime, new Date());
+        querySaWrapper.notInSql(SysAnnouncement::getId, "select annt_id from sys_announcement_send where user_id ='" + sysUser.getId() + "' and read_flag='1'");
+        List<SysAnnouncement> announcements = list(querySaWrapper);
+        announcements = announcements.stream().filter(a-> CommonConstant.MSG_TYPE_ALL.equals(a.getMsgType())
+                || (a.getUserIds() != null && Arrays.stream(a.getUserIds().split(",")).anyMatch(i->i.equals(userId)))).collect(Collectors.toList());
+
+        if (announcements.size() > 0) {
+            for (int i = 0; i < announcements.size(); i++) {
+                LambdaQueryWrapper<SysAnnouncementSend> query = new LambdaQueryWrapper<>();
+                query.eq(SysAnnouncementSend::getAnntId, announcements.get(i).getId());
+                query.eq(SysAnnouncementSend::getUserId, sysUser.getId());
+                SysAnnouncementSend one = sysAnnouncementSendService.getOne(query);
+                if (null == one) {
+                    SysAnnouncementSend announcementSend = new SysAnnouncementSend();
+                    announcementSend.setAnntId(announcements.get(i).getId());
+                    announcementSend.setUserId(Integer.valueOf(sysUser.getId()));
+                    announcementSend.setReadFlag(CommonConstant.NO_READ_FLAG);
+                    sysAnnouncementSendService.save(announcementSend);
+                }
+            }
+        }
+        return announcements;
+    }
+
     /**
      * @功能:编辑消息信息
      */
diff --git a/huaheng-wms-core/src/main/java/org/jeecg/modules/wms/api/wcs/controller/WcsController.java b/huaheng-wms-core/src/main/java/org/jeecg/modules/wms/api/wcs/controller/WcsController.java
index 7358cc8..8123345 100644
--- a/huaheng-wms-core/src/main/java/org/jeecg/modules/wms/api/wcs/controller/WcsController.java
+++ b/huaheng-wms-core/src/main/java/org/jeecg/modules/wms/api/wcs/controller/WcsController.java
@@ -157,8 +157,7 @@ public class WcsController extends HuahengBaseController {
         Result result = handleMultiProcess("completeTaskByWMS", lockKey, new MultiProcessListener() {
             @Override
             public Result<?> doProcess() {
-                Result result = taskHeaderService.completeTaskByWMS(Integer.parseInt(taskNo), foldFlag);
-                return result;
+                return taskHeaderService.completeTaskByWMS(Integer.parseInt(taskNo), foldFlag);
             }
         });
         return result;
diff --git a/huaheng-wms-core/src/main/java/org/jeecg/modules/wms/config/materialWarning/entity/MaterialLevelAlarm.java b/huaheng-wms-core/src/main/java/org/jeecg/modules/wms/config/materialWarning/entity/MaterialLevelAlarm.java
index e8516f8..a22ae14 100644
--- a/huaheng-wms-core/src/main/java/org/jeecg/modules/wms/config/materialWarning/entity/MaterialLevelAlarm.java
+++ b/huaheng-wms-core/src/main/java/org/jeecg/modules/wms/config/materialWarning/entity/MaterialLevelAlarm.java
@@ -50,13 +50,13 @@ public class MaterialLevelAlarm extends MaterialWarning {
     public String toString() {
         String str = "<ul>";
         if (inLower) {
-            str = str +  "<li><b>" + getMaterialName() + "</b> &nbsp;&nbsp;" + getMaterialCode() + " 库存数" + getQtySum() + "&nbsp;&nbsp;低于下限预警值" + getLower() + "</li>";
+            str = str +  "<li><b>" + getMaterialName() + "</b> &nbsp;&nbsp;" + getMaterialCode() + " 库存数 <b>" + getQtySum() + "</b>&nbsp;&nbsp;低于下限预警值<b> " + getLower() + "</b></li>";
         } else if (inUpper) {
-            str = str +  "<li><b>" + getMaterialName() + "</b> &nbsp;&nbsp;" + getMaterialCode() + " 库存数" + getQtySum() + "&nbsp;&nbsp;高于上限预警值" + getUpper() + "</li>";
+            str = str +  "<li><b>" + getMaterialName() + "</b> &nbsp;&nbsp;" + getMaterialCode() + " 库存数 <b>" + getQtySum() + "</b>&nbsp;&nbsp;高于上限预警值<b> " + getUpper() + "</b></li>";
         } else if (inMin) {
-            str = str +  "<li><b>" + getMaterialName() + "</b> &nbsp;&nbsp;" + getMaterialCode() + " 库存数" + getQtySum() + "&nbsp;&nbsp;低于最低值" + getMin() + "</li>";
+            str = str +  "<li><b>" + getMaterialName() + "</b> &nbsp;&nbsp;" + getMaterialCode() + " 库存数 <b>" + getQtySum() + "</b>&nbsp;&nbsp;低于最低值<b> " + getMin() + "</b></li>";
         } else if (inMax) {
-            str = str +  "<li><b>" + getMaterialName() + "</b> &nbsp;&nbsp;" + getMaterialCode() + " 库存数" + getQtySum() + "&nbsp;&nbsp;超过最高值" + getMax() + "</li>";
+            str = str +  "<li><b>" + getMaterialName() + "</b> &nbsp;&nbsp;" + getMaterialCode() + " 库存数 <b>" + getQtySum() + "</b>&nbsp;&nbsp;超过最高值<b> " + getMax() + "</b></li>";
         }
         return str + "</ul>";
     }
diff --git a/huaheng-wms-core/src/main/java/org/jeecg/modules/wms/monitor/apiLog/service/impl/ApiLogServiceImpl.java b/huaheng-wms-core/src/main/java/org/jeecg/modules/wms/monitor/apiLog/service/impl/ApiLogServiceImpl.java
index 2fc5af2..d4c5760 100644
--- a/huaheng-wms-core/src/main/java/org/jeecg/modules/wms/monitor/apiLog/service/impl/ApiLogServiceImpl.java
+++ b/huaheng-wms-core/src/main/java/org/jeecg/modules/wms/monitor/apiLog/service/impl/ApiLogServiceImpl.java
@@ -8,6 +8,7 @@ import org.jeecg.modules.wms.monitor.apiLog.entity.ApiLog;
 import org.jeecg.modules.wms.monitor.apiLog.mapper.ApiLogMapper;
 import org.jeecg.modules.wms.monitor.apiLog.service.IApiLogService;
 import org.springframework.cache.annotation.Cacheable;
+import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.stereotype.Service;
 
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
@@ -26,7 +27,9 @@ import cn.hutool.core.date.DateUtil;
 public class ApiLogServiceImpl extends ServiceImpl<ApiLogMapper, ApiLog> implements IApiLogService {
 
     @Override
-    @Cacheable(cacheNames = "getApiNameList#7200", key = "#root.methodName", unless = "#result == null ")
+    @Scheduled(fixedDelay = 1800 * 1000) // 计划任务:每次方法执行后1800秒执行
+//  @SchedulerLock(name = "getApiNameList", lockAtLeastFor = "PT900S", lockAtMostFor = "PT3600S") // 计划任务锁:最短等待时间1800秒,最长等待时间3600秒
+    @Cacheable(cacheNames = "getApiNameList#1800", key = "#root.methodName", unless = "#result == null ")
     public List<String> getApiNameList() {
         LambdaQueryWrapper<ApiLog> lambdaQueryWrapper = Wrappers.lambdaQuery();
         lambdaQueryWrapper.select(ApiLog::getApiName).groupBy(ApiLog::getApiName).ge(ApiLog::getCreateTime, DateUtil.offsetDay(new Date(), -7));
diff --git a/huaheng-wms-core/src/main/java/org/jeecg/modules/wms/monitor/job/MaterialLevelAlarmTask.java b/huaheng-wms-core/src/main/java/org/jeecg/modules/wms/monitor/job/MaterialLevelAlarmTask.java
index c106e6f..c65f7ee 100644
--- a/huaheng-wms-core/src/main/java/org/jeecg/modules/wms/monitor/job/MaterialLevelAlarmTask.java
+++ b/huaheng-wms-core/src/main/java/org/jeecg/modules/wms/monitor/job/MaterialLevelAlarmTask.java
@@ -2,28 +2,19 @@ package org.jeecg.modules.wms.monitor.job;
 
 import cn.hutool.core.date.DateUtil;
 import cn.hutool.core.util.StrUtil;
-import com.alibaba.fastjson.JSONObject;
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.ibatis.session.SqlSession;
-import org.jeecg.common.constant.CommonConstant;
-import org.jeecg.common.constant.CommonSendStatus;
-import org.jeecg.common.constant.WebsocketConst;
 import org.jeecg.common.util.DateUtils;
 import org.jeecg.modules.message.websocket.WebSocket;
-import org.jeecg.modules.system.controller.SysAnnouncementController;
-import org.jeecg.modules.system.entity.SysAnnouncement;
 import org.jeecg.modules.system.entity.SysUser;
-import org.jeecg.modules.system.mapper.SysUserMapper;
 import org.jeecg.modules.system.service.impl.SysAnnouncementServiceImpl;
 import org.jeecg.modules.system.service.impl.SysRoleServiceImpl;
 import org.jeecg.modules.system.service.impl.SysUserServiceImpl;
 import org.jeecg.modules.wms.config.materialWarning.entity.MaterialLevelAlarm;
 import org.jeecg.modules.wms.config.materialWarning.service.impl.MaterialWarningServiceImpl;
-import org.jeecg.utils.SpringUtils;
 import org.quartz.*;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.util.CollectionUtils;
 
 import javax.annotation.Resource;
 import java.util.ArrayList;
@@ -68,57 +59,26 @@ public class MaterialLevelAlarmTask implements Job {
     @Override
     public void execute(JobExecutionContext context) throws JobExecutionException {
         log.info(StrUtil.format("定时任务 MaterialLevelAlarmTask 参数:{},执行时间:{}", this.parameter, DateUtils.getTimestamp()));
+
         List<MaterialLevelAlarm> alarmList = materialWarningService.getLevelAlarm(null);
-        if (alarmList == null && alarmList.size() == 0) {
+        if (CollectionUtils.isEmpty(alarmList)) {
             return;
         }
 
         List<String> list = alarmList.stream().map(MaterialLevelAlarm::toString).collect(Collectors.toList());
         String msg = String.join("\n", list);
 
-        SysAnnouncement sysAnnouncement = new SysAnnouncement();
-        String title = "物料水位预警";
-        sysAnnouncement.setTitile(title);
-        sysAnnouncement.setMsgContent(msg);
-        sysAnnouncement.setEndTime(DateUtil.offsetDay(new Date(), 1));
-        sysAnnouncement.setPriority("H");
-        sysAnnouncement.setSendTime(new Date());
-        sysAnnouncement.setMsgCategory(CommonConstant.MSG_CATEGORY_2);
-        sysAnnouncement.setMsgType(CommonConstant.MSG_TYPE_ALL);
-        sysAnnouncement.setMsgAbstract(title);
-        sysAnnouncement.setSender("WMS");
-        sysAnnouncement.setDelFlag(CommonConstant.DEL_FLAG_0.toString());
-        sysAnnouncement.setSendStatus(CommonSendStatus.PUBLISHED_STATUS_1);
-        sysAnnouncementService.saveAnnouncement(sysAnnouncement);
-
-        List<SysUser> userList = new ArrayList<>();
+
+        List<SysUser> userList;
         try {
             String[] userOrRoleArr = this.parameter.split(",");
             userList = sysUserService.getUserByRoleNameArray(userOrRoleArr);
+            if(userList.size() == 0){
+                userList = null;
+            }
+            sysAnnouncementService.quickAnnouncementToUser(userList, "物料水位预警", msg, DateUtil.offsetDay(new Date(), 1), "H");
         } catch (Exception e) {
             log.error("获取预警通知用户出错", e);
         }
-
-        if (userList.size() == 0) {
-            sysAnnouncement.setMsgType(CommonConstant.MSG_TYPE_ALL);
-            JSONObject obj = new JSONObject();
-            obj.put(WebsocketConst.MSG_CMD, WebsocketConst.CMD_TOPIC);
-            obj.put(WebsocketConst.MSG_ID, sysAnnouncement.getId());
-            obj.put(WebsocketConst.MSG_TXT, sysAnnouncement.getTitile());
-            webSocket.sendMessage(obj.toJSONString());
-        } else {
-            // 2.插入用户通告阅读标记表记录
-            sysAnnouncement.setMsgType(CommonConstant.MSG_TYPE_UESR);
-            List<String> userIds = userList.stream().map(SysUser::getId).map(Object::toString).collect(Collectors.toList());
-            sysAnnouncement.setUserIds(String.join(",", userIds));
-
-            JSONObject obj = new JSONObject();
-            obj.put(WebsocketConst.MSG_CMD, WebsocketConst.CMD_USER);
-            obj.put(WebsocketConst.MSG_ID, sysAnnouncement.getId());
-            obj.put(WebsocketConst.MSG_TXT, sysAnnouncement.getTitile());
-            webSocket.sendMessage(userIds, obj.toJSONString());
-        }
-
-        sysAnnouncementService.updateById(sysAnnouncement);
     }
 }
diff --git a/huaheng-wms-core/src/main/java/org/jeecg/modules/wms/task/taskHeader/controller/TaskHeaderController.java b/huaheng-wms-core/src/main/java/org/jeecg/modules/wms/task/taskHeader/controller/TaskHeaderController.java
index 571dc9e..18b8bb7 100644
--- a/huaheng-wms-core/src/main/java/org/jeecg/modules/wms/task/taskHeader/controller/TaskHeaderController.java
+++ b/huaheng-wms-core/src/main/java/org/jeecg/modules/wms/task/taskHeader/controller/TaskHeaderController.java
@@ -341,11 +341,10 @@ public class TaskHeaderController extends HuahengBaseController {
             return Result.error("taskHeader不能为空");
         }
         Integer taskId = taskHeader.getId();
-        Result result = handleMultiProcess("completeTaskByWMS", new MultiProcessListener() {
+        Result result = handleMultiProcess("completeTaskByWMS", taskId + "", new MultiProcessListener() {
             @Override
             public Result<?> doProcess() {
-                Result result = taskHeaderService.completeTaskByWMS(taskId, false);
-                return result;
+                return taskHeaderService.completeTaskByWMS(taskId, false);
             }
         });
         return result;
diff --git a/huaheng-wms-core/src/main/java/org/jeecg/utils/support/SystemSync.java b/huaheng-wms-core/src/main/java/org/jeecg/utils/support/SystemSync.java
index ecc7db1..676bacf 100644
--- a/huaheng-wms-core/src/main/java/org/jeecg/utils/support/SystemSync.java
+++ b/huaheng-wms-core/src/main/java/org/jeecg/utils/support/SystemSync.java
@@ -1,14 +1,19 @@
 package org.jeecg.utils.support;
 
 import java.math.BigDecimal;
+import java.util.Date;
 import java.util.List;
 import java.util.concurrent.Future;
 
 import javax.annotation.Resource;
 
+import org.jeecg.common.constant.CommonConstant;
 import org.jeecg.common.constant.WebsocketConst;
 import org.jeecg.modules.message.websocket.WebSocket;
+import org.jeecg.modules.system.entity.SysAnnouncement;
+import org.jeecg.modules.system.entity.SysAnnouncementSend;
 import org.jeecg.modules.system.entity.SysUser;
+import org.jeecg.modules.system.service.impl.SysAnnouncementServiceImpl;
 import org.jeecg.modules.wms.inventory.inventoryTransaction.entity.InventoryTransaction;
 import org.jeecg.modules.wms.inventory.inventoryTransaction.service.IInventoryTransactionService;
 import org.jeecg.modules.wms.monitor.apiLog.entity.ApiLog;
@@ -34,20 +39,25 @@ public class SystemSync {
 
     @Autowired
     private IInventoryTransactionService inventoryTransactionService;
-    
+
     @Autowired
     private WebSocket webSocket;
-    
+
+    @Autowired
+    private SysAnnouncementServiceImpl sysAnnouncementService;
+
+    /**
+     * 登录弹框后发送未读消息
+     * @param sysUser
+     */
     @Async("asyncPoolTaskExecutor")
-    public void sendMaterialAlarm(SysUser sysUser) {
+    public void sendSysAnnouncement(SysUser sysUser) {
         try {
             Thread.sleep(20000);
-            JSONObject obj = new JSONObject();
-            obj.put(WebsocketConst.MSG_CMD, WebsocketConst.CMD_TOPIC);
-            obj.put(WebsocketConst.MSG_ID, "111");
-            obj.put(WebsocketConst.MSG_TXT, "登录通知测试");
-            webSocket.sendMessage(obj.toJSONString());
+            List<SysAnnouncement> sysAnnouncementList = sysAnnouncementService.getNewAnnouncementOfUser(sysUser);
+            sysAnnouncementList.forEach(a->webSocket.sendMessage(sysUser.getId(), a));
         } catch (Exception e) {
+            log.error("websocket系统消息发送失败", e);
         }
     }