From ed0d872dddf37672ceb9bc499099f65d63ed1ce3 Mon Sep 17 00:00:00 2001
From: liyong <18434998025@163.com>
Date: 星期四, 21 五月 2026 09:28:36 +0800
Subject: [PATCH] feat(approve): 添加企业新闻审批功能并完善审批实例管理

---
 src/main/java/com/ruoyi/project/system/mapper/SysUserDeptMapper.java                               |   25 +
 src/main/java/com/ruoyi/approve/controller/ApprovalInstanceController.java                         |    3 
 src/main/java/com/ruoyi/collaborativeApproval/controller/EnterpriseNewsScopeDeptController.java    |   18 
 src/main/java/com/ruoyi/collaborativeApproval/dto/EnterpriseNewsDto.java                           |   22 
 src/main/resources/mapper/system/SysNoticeMapper.xml                                               |    5 
 src/main/resources/mapper/approve/ApprovalInstanceMapper.xml                                       |   18 
 src/main/java/com/ruoyi/collaborativeApproval/mapper/EnterpriseNewsScopeDeptMapper.java            |   18 
 src/main/java/com/ruoyi/approve/service/impl/ApprovalInstanceServiceImpl.java                      |  128 ++++
 src/main/java/com/ruoyi/collaborativeApproval/mapper/EnterpriseNewsMapper.java                     |   24 
 src/main/java/com/ruoyi/collaborativeApproval/service/EnterpriseNewsService.java                   |   29 +
 src/main/java/com/ruoyi/staff/service/impl/StaffLeaveServiceImpl.java                              |    1 
 src/main/java/com/ruoyi/approve/controller/ApprovalInstanceNodeController.java                     |    3 
 src/main/java/com/ruoyi/collaborativeApproval/vo/EnterpriseNewsVo.java                             |   10 
 src/main/resources/mapper/collaborativeApproval/EnterpriseNewsScopeUserMapper.xml                  |   13 
 src/main/java/com/ruoyi/collaborativeApproval/service/impl/EnterpriseNewsServiceImpl.java          |  378 +++++++++++++++
 src/main/java/com/ruoyi/approve/bean/dto/ApprovalInstanceDto.java                                  |    4 
 src/main/java/com/ruoyi/collaborativeApproval/service/EnterpriseNewsScopeUserService.java          |   16 
 src/main/resources/mapper/collaborativeApproval/EnterpriseNewsScopeDeptMapper.xml                  |   13 
 src/main/resources/mapper/staff/StaffLeaveMapper.xml                                               |   21 
 src/main/java/com/ruoyi/collaborativeApproval/mapper/EnterpriseNewsScopeUserMapper.java            |   18 
 src/main/java/com/ruoyi/collaborativeApproval/pojo/EnterpriseNewsScopeUser.java                    |   59 ++
 src/main/java/com/ruoyi/collaborativeApproval/pojo/EnterpriseNewsScopeDept.java                    |   59 ++
 src/main/java/com/ruoyi/collaborativeApproval/service/EnterpriseNewsScopeDeptService.java          |   16 
 src/main/java/com/ruoyi/collaborativeApproval/service/impl/EnterpriseNewsScopeUserServiceImpl.java |   20 
 src/main/java/com/ruoyi/collaborativeApproval/controller/EnterpriseNewsScopeUserController.java    |   18 
 src/main/resources/mapper/collaborativeApproval/EnterpriseNewsMapper.xml                           |   46 +
 src/main/java/com/ruoyi/project/system/service/impl/SysNoticeServiceImpl.java                      |  169 +++++-
 src/main/java/com/ruoyi/common/enums/ApprovalStatusEnum.java                                       |    1 
 src/main/java/com/ruoyi/common/enums/EnterpriseNewsStatusEnum.java                                 |  143 +++++
 src/main/java/com/ruoyi/collaborativeApproval/service/impl/EnterpriseNewsScopeDeptServiceImpl.java |   20 
 src/main/java/com/ruoyi/approve/pojo/ApprovalInstance.java                                         |    4 
 src/main/java/com/ruoyi/collaborativeApproval/pojo/EnterpriseNews.java                             |   88 +++
 src/main/java/com/ruoyi/collaborativeApproval/controller/EnterpriseNewsController.java             |   55 ++
 33 files changed, 1,400 insertions(+), 65 deletions(-)

diff --git a/src/main/java/com/ruoyi/approve/bean/dto/ApprovalInstanceDto.java b/src/main/java/com/ruoyi/approve/bean/dto/ApprovalInstanceDto.java
index ab4dced..17e4921 100644
--- a/src/main/java/com/ruoyi/approve/bean/dto/ApprovalInstanceDto.java
+++ b/src/main/java/com/ruoyi/approve/bean/dto/ApprovalInstanceDto.java
@@ -9,4 +9,8 @@
     private String approveAction;
 
     private String approveComment;
+
+    private String createTimeEnd;
+
+    private String createTimeStart;
 }
diff --git a/src/main/java/com/ruoyi/approve/controller/ApprovalInstanceController.java b/src/main/java/com/ruoyi/approve/controller/ApprovalInstanceController.java
index c7225c2..f13e1b3 100644
--- a/src/main/java/com/ruoyi/approve/controller/ApprovalInstanceController.java
+++ b/src/main/java/com/ruoyi/approve/controller/ApprovalInstanceController.java
@@ -4,6 +4,7 @@
 import com.ruoyi.approve.bean.dto.ApprovalInstanceDto;
 import com.ruoyi.approve.bean.vo.ApprovalInstanceVo;
 import com.ruoyi.approve.service.ApprovalInstanceService;
+import com.ruoyi.framework.web.controller.BaseController;
 import com.ruoyi.framework.web.domain.R;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.tags.Tag;
@@ -24,7 +25,7 @@
 @RequestMapping("/approvalInstance")
 @Tag(name = "瀹℃壒瀹炰緥琛�")
 @AllArgsConstructor
-public class ApprovalInstanceController {
+public class ApprovalInstanceController extends BaseController {
 
     private final ApprovalInstanceService approvalInstanceService;
     @GetMapping("/listPage")
diff --git a/src/main/java/com/ruoyi/approve/controller/ApprovalInstanceNodeController.java b/src/main/java/com/ruoyi/approve/controller/ApprovalInstanceNodeController.java
index 186b2fd..e42af42 100644
--- a/src/main/java/com/ruoyi/approve/controller/ApprovalInstanceNodeController.java
+++ b/src/main/java/com/ruoyi/approve/controller/ApprovalInstanceNodeController.java
@@ -1,5 +1,6 @@
 package com.ruoyi.approve.controller;
 
+import com.ruoyi.framework.web.controller.BaseController;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 
@@ -13,6 +14,6 @@
  */
 @RestController
 @RequestMapping("/approvalInstanceNode")
-public class ApprovalInstanceNodeController {
+public class ApprovalInstanceNodeController extends BaseController {
 
 }
diff --git a/src/main/java/com/ruoyi/approve/pojo/ApprovalInstance.java b/src/main/java/com/ruoyi/approve/pojo/ApprovalInstance.java
index b58a836..77d8d58 100644
--- a/src/main/java/com/ruoyi/approve/pojo/ApprovalInstance.java
+++ b/src/main/java/com/ruoyi/approve/pojo/ApprovalInstance.java
@@ -1,11 +1,13 @@
 package com.ruoyi.approve.pojo;
 
 import com.baomidou.mybatisplus.annotation.*;
+import com.fasterxml.jackson.annotation.JsonFormat;
 import io.swagger.annotations.ApiModel;
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Getter;
 import lombok.Setter;
 import lombok.ToString;
+import org.springframework.format.annotation.DateTimeFormat;
 
 import java.io.Serializable;
 import java.time.LocalDateTime;
@@ -118,6 +120,8 @@
      */
     @Schema(description ="鍒涘缓鏃堕棿")
     @TableField(fill = FieldFill.INSERT)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private LocalDateTime createTime;
 
     /**
diff --git a/src/main/java/com/ruoyi/approve/service/impl/ApprovalInstanceServiceImpl.java b/src/main/java/com/ruoyi/approve/service/impl/ApprovalInstanceServiceImpl.java
index 1d7f217..c15ccb7 100644
--- a/src/main/java/com/ruoyi/approve/service/impl/ApprovalInstanceServiceImpl.java
+++ b/src/main/java/com/ruoyi/approve/service/impl/ApprovalInstanceServiceImpl.java
@@ -10,23 +10,29 @@
 import com.ruoyi.approve.bean.dto.ApprovalInstanceDto;
 import com.ruoyi.approve.bean.vo.ApprovalInstanceVo;
 import com.ruoyi.approve.mapper.ApprovalInstanceMapper;
-import com.ruoyi.approve.mapper.ApprovalTemplateMapper;
 import com.ruoyi.approve.pojo.*;
 import com.ruoyi.approve.service.*;
 import com.ruoyi.approve.utils.ApproveProcessConfigNodeUtils;
+import com.ruoyi.collaborativeApproval.pojo.EnterpriseNews;
+import com.ruoyi.collaborativeApproval.pojo.EnterpriseNewsScopeDept;
+import com.ruoyi.collaborativeApproval.pojo.EnterpriseNewsScopeUser;
+import com.ruoyi.collaborativeApproval.service.EnterpriseNewsScopeDeptService;
+import com.ruoyi.collaborativeApproval.service.EnterpriseNewsScopeUserService;
+import com.ruoyi.collaborativeApproval.service.EnterpriseNewsService;
 import com.ruoyi.common.enums.*;
 import com.ruoyi.common.utils.OrderUtils;
 import com.ruoyi.common.utils.SecurityUtils;
 import com.ruoyi.framework.security.LoginUser;
 import com.ruoyi.framework.web.domain.R;
 import com.ruoyi.procurementrecord.utils.StockUtils;
+import com.ruoyi.project.system.domain.SysDept;
+import com.ruoyi.project.system.domain.SysUser;
+import com.ruoyi.project.system.mapper.SysDeptMapper;
+import com.ruoyi.project.system.mapper.SysUserDeptMapper;
+import com.ruoyi.project.system.mapper.SysUserMapper;
 import com.ruoyi.project.system.service.ISysNoticeService;
 import com.ruoyi.purchase.mapper.PurchaseLedgerMapper;
 import com.ruoyi.purchase.pojo.PurchaseLedger;
-import com.ruoyi.quality.mapper.QualityInspectMapper;
-import com.ruoyi.quality.mapper.QualityInspectParamMapper;
-import com.ruoyi.quality.mapper.QualityTestStandardMapper;
-import com.ruoyi.quality.mapper.QualityTestStandardParamMapper;
 import com.ruoyi.quality.utils.QualityInspectHelper;
 import com.ruoyi.sales.mapper.SalesLedgerProductMapper;
 import com.ruoyi.sales.mapper.SalesQuotationMapper;
@@ -54,6 +60,9 @@
 @RequiredArgsConstructor
 public class ApprovalInstanceServiceImpl extends ServiceImpl<ApprovalInstanceMapper, ApprovalInstance> implements ApprovalInstanceService {
 
+    private static final String ENTERPRISE_NEWS_STATUS_PUBLISHED = "PUBLISHED";
+    private static final String ENTERPRISE_NEWS_STATUS_REJECTED = "REJECTED";
+
     private final ApprovalInstanceMapper approvalInstanceMapper;
     private final ApproveProcessConfigNodeUtils approveProcessConfigNodeUtils;
     private final ApprovalInstanceNodeService approvalInstanceNodeService;
@@ -65,14 +74,15 @@
     private final PurchaseLedgerMapper purchaseLedgerMapper;
     private final SalesLedgerProductMapper salesLedgerProductMapper;
     private final StockUtils stockUtils;
-    private final QualityInspectMapper qualityInspectMapper;
-    private final QualityTestStandardMapper qualityTestStandardMapper;
-    private final QualityTestStandardParamMapper qualityTestStandardParamMapper;
-    private final QualityInspectParamMapper qualityInspectParamMapper;
     private final SalesQuotationMapper salesQuotationMapper;
     private final ShippingInfoMapper shippingInfoMapper;
-    private final ApprovalTemplateMapper approvalTemplateMapper;
     private final QualityInspectHelper qualityInspectHelper;
+    private final EnterpriseNewsService enterpriseNewsService;
+    private final EnterpriseNewsScopeDeptService enterpriseNewsScopeDeptService;
+    private final EnterpriseNewsScopeUserService enterpriseNewsScopeUserService;
+    private final SysUserMapper sysUserMapper;
+    private final SysUserDeptMapper sysUserDeptMapper;
+    private final SysDeptMapper sysDeptMapper;
 
     @Override
     public R listPage(Page<ApprovalInstanceVo> page, ApprovalInstanceDto approvalInstanceDto) {
@@ -331,6 +341,28 @@
         }
         if (TypeEnums.SHIPPING_APPROVAL.getCode().equals(businessType)) {
             handleShippingApprovalFinished(instance, status);
+            return;
+        }
+        if (TypeEnums.ENTERPRISE_NEWS_APPROVAL.getCode().equals(businessType)) {
+            handleNewsApprovalFinished(instance, status);
+        }
+    }
+
+    private void handleNewsApprovalFinished(ApprovalInstance instance, String status) {
+        if (instance == null || instance.getBusinessId() == null) {
+            return;
+        }
+        EnterpriseNews enterpriseNews = new EnterpriseNews();
+        enterpriseNews.setId(instance.getBusinessId());
+        if ("APPROVED".equals(status)) {
+            enterpriseNews.setStatus(ENTERPRISE_NEWS_STATUS_PUBLISHED);
+            enterpriseNewsService.updateById(enterpriseNews);
+            sendEnterpriseNewsNotice(instance.getBusinessId());
+            return;
+        }
+        if ("REJECTED".equals(status)) {
+            enterpriseNews.setStatus(ENTERPRISE_NEWS_STATUS_REJECTED);
+            enterpriseNewsService.updateById(enterpriseNews);
         }
     }
 
@@ -474,6 +506,82 @@
         sysNoticeService.simpleNoticeByUser(title, message, approverIds, jumpPath);
     }
 
+    private void sendEnterpriseNewsNotice(Long newsId) {
+        EnterpriseNews enterpriseNews = enterpriseNewsService.getById(newsId);
+        if (enterpriseNews == null) {
+            return;
+        }
+        List<Long> userIds = getEnterpriseNewsNoticeUserIds(enterpriseNews);
+        if (userIds == null || userIds.isEmpty()) {
+            return;
+        }
+        String title = "浼佷笟鏂伴椈";
+        String message = "鎮ㄦ湁鏂扮殑浼佷笟鏂伴椈銆�" + enterpriseNews.getTitle() + "銆嬭鍙婃椂鏌ラ槄";
+        String jumpPath = "/enterpriseNews?id=" + newsId;
+        sysNoticeService.simpleNoticeByUser(title, message, userIds, jumpPath);
+    }
+
+    private List<Long> getEnterpriseNewsNoticeUserIds(EnterpriseNews enterpriseNews) {
+        if (enterpriseNews == null || !org.springframework.util.StringUtils.hasText(enterpriseNews.getReadScope())) {
+            return Collections.emptyList();
+        }
+        String readScope = enterpriseNews.getReadScope().trim();
+        if ("all".equals(readScope)) {
+            return sysUserMapper.selectList(new LambdaQueryWrapper<SysUser>()
+                            .select(SysUser::getUserId)
+                            .eq(SysUser::getDelFlag, "0"))
+                    .stream()
+                    .map(SysUser::getUserId)
+                    .filter(id -> id != null && id > 0)
+                    .distinct()
+                    .collect(Collectors.toList());
+        }
+        if ("dept".equals(readScope)) {
+            List<Long> deptIds = enterpriseNewsScopeDeptService.list(
+                            new LambdaQueryWrapper<EnterpriseNewsScopeDept>()
+                                    .eq(EnterpriseNewsScopeDept::getNewsId, enterpriseNews.getId()))
+                    .stream()
+                    .map(EnterpriseNewsScopeDept::getDeptId)
+                    .filter(id -> id != null && id > 0)
+                    .distinct()
+                    .collect(Collectors.toList());
+            if (deptIds.isEmpty()) {
+                return Collections.emptyList();
+            }
+            return sysUserDeptMapper.selectDistinctUserIdsByDeptIds(collectDeptIdsWithChildren(deptIds));
+        }
+        if ("custom".equals(readScope)) {
+            return enterpriseNewsScopeUserService.list(
+                            new LambdaQueryWrapper<EnterpriseNewsScopeUser>()
+                                    .eq(EnterpriseNewsScopeUser::getNewsId, enterpriseNews.getId()))
+                    .stream()
+                    .map(EnterpriseNewsScopeUser::getUserId)
+                    .filter(id -> id != null && id > 0)
+                    .distinct()
+                    .collect(Collectors.toList());
+        }
+        return Collections.emptyList();
+    }
+
+    private List<Long> collectDeptIdsWithChildren(List<Long> deptIds) {
+        Set<Long> allDeptIds = new LinkedHashSet<>();
+        for (Long deptId : deptIds) {
+            if (deptId == null) {
+                continue;
+            }
+            allDeptIds.add(deptId);
+            List<SysDept> children = sysDeptMapper.selectChildrenDeptById(deptId);
+            if (children != null && !children.isEmpty()) {
+                for (SysDept child : children) {
+                    if (child != null && child.getDeptId() != null) {
+                        allDeptIds.add(child.getDeptId());
+                    }
+                }
+            }
+        }
+        return new ArrayList<>(allDeptIds);
+    }
+
     private void closePendingTasks(Long instanceId, Long nodeId) {
         LambdaUpdateWrapper<ApprovalTask> updateWrapper = Wrappers.lambdaUpdate();
         updateWrapper.eq(ApprovalTask::getInstanceId, instanceId)
diff --git a/src/main/java/com/ruoyi/collaborativeApproval/controller/EnterpriseNewsController.java b/src/main/java/com/ruoyi/collaborativeApproval/controller/EnterpriseNewsController.java
new file mode 100644
index 0000000..88445fa
--- /dev/null
+++ b/src/main/java/com/ruoyi/collaborativeApproval/controller/EnterpriseNewsController.java
@@ -0,0 +1,55 @@
+package com.ruoyi.collaborativeApproval.controller;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.collaborativeApproval.dto.EnterpriseNewsDto;
+import com.ruoyi.collaborativeApproval.service.EnterpriseNewsService;
+import com.ruoyi.collaborativeApproval.vo.EnterpriseNewsVo;
+import com.ruoyi.framework.web.domain.R;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import lombok.AllArgsConstructor;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 浼佷笟鏂伴椈琛� 鍓嶇鎺у埗鍣�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-20 11:50:59
+ */
+@RestController
+@RequestMapping("/enterpriseNews")
+@Tag(name = "浼佷笟鏂伴椈琛�")
+@AllArgsConstructor
+public class EnterpriseNewsController {
+
+    private final EnterpriseNewsService enterpriseNewsService;
+
+    @Operation(summary = "鍒嗛〉鏌ヨ")
+    @GetMapping("/listPage")
+    public R listPage(Page<EnterpriseNewsVo>  page , EnterpriseNewsDto enterpriseNewsDto) {
+        return R.ok(enterpriseNewsService.listPage(page, enterpriseNewsDto));
+    }
+
+    @PostMapping("/save")
+    @Operation(summary = "淇濆瓨")
+    public R save(@RequestBody EnterpriseNewsDto enterpriseNewsDto) {
+        return R.ok(enterpriseNewsService.add(enterpriseNewsDto));
+    }
+
+    @PutMapping("/update")
+    @Operation(summary = "鏇存柊")
+    public R update(@RequestBody EnterpriseNewsDto enterpriseNewsDto) {
+        return R.ok(enterpriseNewsService.updateEnterpriseNewsDto(enterpriseNewsDto));
+    }
+
+    @DeleteMapping("/delete")
+    @Operation(summary = "鍒犻櫎")
+    public R delete(@RequestBody List<Long> ids) {
+        return R.ok(enterpriseNewsService.delete(ids));
+    }
+
+}
diff --git a/src/main/java/com/ruoyi/collaborativeApproval/controller/EnterpriseNewsScopeDeptController.java b/src/main/java/com/ruoyi/collaborativeApproval/controller/EnterpriseNewsScopeDeptController.java
new file mode 100644
index 0000000..8c68d1a
--- /dev/null
+++ b/src/main/java/com/ruoyi/collaborativeApproval/controller/EnterpriseNewsScopeDeptController.java
@@ -0,0 +1,18 @@
+package com.ruoyi.collaborativeApproval.controller;
+
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * <p>
+ * 浼佷笟鏂伴椈闃呰鑼冨洿閮ㄩ棬琛� 鍓嶇鎺у埗鍣�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-20 11:51:12
+ */
+@RestController
+@RequestMapping("/enterpriseNewsScopeDept")
+public class EnterpriseNewsScopeDeptController {
+
+}
diff --git a/src/main/java/com/ruoyi/collaborativeApproval/controller/EnterpriseNewsScopeUserController.java b/src/main/java/com/ruoyi/collaborativeApproval/controller/EnterpriseNewsScopeUserController.java
new file mode 100644
index 0000000..7ceba13
--- /dev/null
+++ b/src/main/java/com/ruoyi/collaborativeApproval/controller/EnterpriseNewsScopeUserController.java
@@ -0,0 +1,18 @@
+package com.ruoyi.collaborativeApproval.controller;
+
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * <p>
+ * 浼佷笟鏂伴椈闃呰鑼冨洿鐢ㄦ埛琛� 鍓嶇鎺у埗鍣�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-20 11:51:23
+ */
+@RestController
+@RequestMapping("/enterpriseNewsScopeUser")
+public class EnterpriseNewsScopeUserController {
+
+}
diff --git a/src/main/java/com/ruoyi/collaborativeApproval/dto/EnterpriseNewsDto.java b/src/main/java/com/ruoyi/collaborativeApproval/dto/EnterpriseNewsDto.java
new file mode 100644
index 0000000..3cde773
--- /dev/null
+++ b/src/main/java/com/ruoyi/collaborativeApproval/dto/EnterpriseNewsDto.java
@@ -0,0 +1,22 @@
+package com.ruoyi.collaborativeApproval.dto;
+
+import com.ruoyi.collaborativeApproval.pojo.EnterpriseNews;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class EnterpriseNewsDto extends EnterpriseNews {
+
+    private String createUserName;
+
+    private List<Long> deptIds;
+
+    private List<Long> userIds;
+
+    private Long templateId;
+    private String templateName;
+
+    private String createTimeStart;
+    private String createTimeEnd;
+}
diff --git a/src/main/java/com/ruoyi/collaborativeApproval/mapper/EnterpriseNewsMapper.java b/src/main/java/com/ruoyi/collaborativeApproval/mapper/EnterpriseNewsMapper.java
new file mode 100644
index 0000000..799ae82
--- /dev/null
+++ b/src/main/java/com/ruoyi/collaborativeApproval/mapper/EnterpriseNewsMapper.java
@@ -0,0 +1,24 @@
+package com.ruoyi.collaborativeApproval.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.collaborativeApproval.dto.EnterpriseNewsDto;
+import com.ruoyi.collaborativeApproval.pojo.EnterpriseNews;
+import com.ruoyi.collaborativeApproval.vo.EnterpriseNewsVo;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+/**
+ * <p>
+ * 浼佷笟鏂伴椈琛� Mapper 鎺ュ彛
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-20 11:50:59
+ */
+@Mapper
+public interface EnterpriseNewsMapper extends BaseMapper<EnterpriseNews> {
+
+    IPage<EnterpriseNewsVo> listPage(Page<EnterpriseNewsVo> page,@Param("enterpriseNewsDto") EnterpriseNewsDto enterpriseNewsDto);
+}
diff --git a/src/main/java/com/ruoyi/collaborativeApproval/mapper/EnterpriseNewsScopeDeptMapper.java b/src/main/java/com/ruoyi/collaborativeApproval/mapper/EnterpriseNewsScopeDeptMapper.java
new file mode 100644
index 0000000..5b4639f
--- /dev/null
+++ b/src/main/java/com/ruoyi/collaborativeApproval/mapper/EnterpriseNewsScopeDeptMapper.java
@@ -0,0 +1,18 @@
+package com.ruoyi.collaborativeApproval.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.ruoyi.collaborativeApproval.pojo.EnterpriseNewsScopeDept;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * <p>
+ * 浼佷笟鏂伴椈闃呰鑼冨洿閮ㄩ棬琛� Mapper 鎺ュ彛
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-20 11:51:12
+ */
+@Mapper
+public interface EnterpriseNewsScopeDeptMapper extends BaseMapper<EnterpriseNewsScopeDept> {
+
+}
diff --git a/src/main/java/com/ruoyi/collaborativeApproval/mapper/EnterpriseNewsScopeUserMapper.java b/src/main/java/com/ruoyi/collaborativeApproval/mapper/EnterpriseNewsScopeUserMapper.java
new file mode 100644
index 0000000..ab9a64f
--- /dev/null
+++ b/src/main/java/com/ruoyi/collaborativeApproval/mapper/EnterpriseNewsScopeUserMapper.java
@@ -0,0 +1,18 @@
+package com.ruoyi.collaborativeApproval.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.ruoyi.collaborativeApproval.pojo.EnterpriseNewsScopeUser;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * <p>
+ * 浼佷笟鏂伴椈闃呰鑼冨洿鐢ㄦ埛琛� Mapper 鎺ュ彛
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-20 11:51:23
+ */
+@Mapper
+public interface EnterpriseNewsScopeUserMapper extends BaseMapper<EnterpriseNewsScopeUser> {
+
+}
diff --git a/src/main/java/com/ruoyi/collaborativeApproval/pojo/EnterpriseNews.java b/src/main/java/com/ruoyi/collaborativeApproval/pojo/EnterpriseNews.java
new file mode 100644
index 0000000..f5e001b
--- /dev/null
+++ b/src/main/java/com/ruoyi/collaborativeApproval/pojo/EnterpriseNews.java
@@ -0,0 +1,88 @@
+package com.ruoyi.collaborativeApproval.pojo;
+
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModel;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+/**
+ * 浼佷笟鏂伴椈琛�
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-20 11:50:59
+ */
+@Getter
+@Setter
+@ToString
+@TableName("enterprise_news")
+@ApiModel(value = "EnterpriseNews瀵硅薄", description = "浼佷笟鏂伴椈琛�")
+public class EnterpriseNews implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @Schema(description = "缂栧彿 ID")
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    @Schema(description = "鏍囬 Title")
+    private String title;
+
+    @Schema(description = "鎽樿 Summary")
+    private String summary;
+
+    @Schema(description = "姝f枃 Content")
+    private String content;
+
+    @Schema(description = "鍒嗙被 Category")
+    private String category;
+
+    @Schema(description = "闃呰鑼冨洿 Read scope: all 鍏ㄥ憳, dept 閮ㄩ棬, custom 鑷畾涔�")
+    private String readScope;
+
+    @Schema(description = "鏄惁蹇呰 Required flag: 0 鍚�, 1 鏄�")
+    private Byte isRequired;
+
+    @Schema(description = "鐘舵�� Status: DRAFT 鑽夌, PENDING 寰呭鎵�, PUBLISHED 宸插彂甯�, REJECTED 椹冲洖, OFFLINE 宸蹭笅绾�")
+    private String status;
+
+    @Schema(description = "搴旇浜烘暟 Required read count")
+    private Integer requiredReadCount;
+
+    @Schema(description = "宸茶浜烘暟 Read count")
+    private Integer readCount;
+
+    @Schema(description = "鍒涘缓浜� Create user")
+    @TableField(fill = FieldFill.INSERT)
+    private Long createUser;
+
+    @Schema(description = "鍒涘缓鏃堕棿 Create time")
+    @TableField(fill = FieldFill.INSERT)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss", iso = DateTimeFormat.ISO.DATE_TIME)
+    private LocalDateTime createTime;
+
+    @Schema(description = "鏇存柊浜� Update user")
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    private Long updateUser;
+
+    @Schema(description = "鏇存柊鏃堕棿 Update time")
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss", iso = DateTimeFormat.ISO.DATE_TIME)
+    private LocalDateTime updateTime;
+
+    @Schema(description = "閮ㄩ棬ID Dept ID")
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
+}
diff --git a/src/main/java/com/ruoyi/collaborativeApproval/pojo/EnterpriseNewsScopeDept.java b/src/main/java/com/ruoyi/collaborativeApproval/pojo/EnterpriseNewsScopeDept.java
new file mode 100644
index 0000000..97ff9de
--- /dev/null
+++ b/src/main/java/com/ruoyi/collaborativeApproval/pojo/EnterpriseNewsScopeDept.java
@@ -0,0 +1,59 @@
+package com.ruoyi.collaborativeApproval.pojo;
+
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ * 浼佷笟鏂伴椈闃呰鑼冨洿閮ㄩ棬琛�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-20 11:51:12
+ */
+@Getter
+@Setter
+@ToString
+@TableName("enterprise_news_scope_dept")
+@ApiModel(value = "EnterpriseNewsScopeDept瀵硅薄", description = "浼佷笟鏂伴椈闃呰鑼冨洿閮ㄩ棬琛�")
+public class EnterpriseNewsScopeDept implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 缂栧彿
+     */
+    @ApiModelProperty("缂栧彿")
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * 浼佷笟鏂伴椈ID
+     */
+    @ApiModelProperty("浼佷笟鏂伴椈ID")
+    private Long newsId;
+
+    /**
+     * 閮ㄩ棬ID
+     */
+    @ApiModelProperty("閮ㄩ棬ID")
+    private Long deptId;
+
+    /**
+     * 鍒涘缓鏃堕棿
+     */
+    @ApiModelProperty("鍒涘缓鏃堕棿")
+    @TableField(fill = FieldFill.INSERT)
+    private LocalDateTime createTime;
+}
diff --git a/src/main/java/com/ruoyi/collaborativeApproval/pojo/EnterpriseNewsScopeUser.java b/src/main/java/com/ruoyi/collaborativeApproval/pojo/EnterpriseNewsScopeUser.java
new file mode 100644
index 0000000..9d43df2
--- /dev/null
+++ b/src/main/java/com/ruoyi/collaborativeApproval/pojo/EnterpriseNewsScopeUser.java
@@ -0,0 +1,59 @@
+package com.ruoyi.collaborativeApproval.pojo;
+
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ * 浼佷笟鏂伴椈闃呰鑼冨洿鐢ㄦ埛琛�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-20 11:51:23
+ */
+@Getter
+@Setter
+@ToString
+@TableName("enterprise_news_scope_user")
+@ApiModel(value = "EnterpriseNewsScopeUser瀵硅薄", description = "浼佷笟鏂伴椈闃呰鑼冨洿鐢ㄦ埛琛�")
+public class EnterpriseNewsScopeUser implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 缂栧彿
+     */
+    @ApiModelProperty("缂栧彿")
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * 浼佷笟鏂伴椈ID
+     */
+    @ApiModelProperty("浼佷笟鏂伴椈ID")
+    private Long newsId;
+
+    /**
+     * 鐢ㄦ埛ID
+     */
+    @ApiModelProperty("鐢ㄦ埛ID")
+    private Long userId;
+
+    /**
+     * 鍒涘缓鏃堕棿
+     */
+    @ApiModelProperty("鍒涘缓鏃堕棿")
+    @TableField(fill = FieldFill.INSERT)
+    private LocalDateTime createTime;
+}
diff --git a/src/main/java/com/ruoyi/collaborativeApproval/service/EnterpriseNewsScopeDeptService.java b/src/main/java/com/ruoyi/collaborativeApproval/service/EnterpriseNewsScopeDeptService.java
new file mode 100644
index 0000000..b41a7d8
--- /dev/null
+++ b/src/main/java/com/ruoyi/collaborativeApproval/service/EnterpriseNewsScopeDeptService.java
@@ -0,0 +1,16 @@
+package com.ruoyi.collaborativeApproval.service;
+
+import com.ruoyi.collaborativeApproval.pojo.EnterpriseNewsScopeDept;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ * 浼佷笟鏂伴椈闃呰鑼冨洿閮ㄩ棬琛� 鏈嶅姟绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-20 11:51:12
+ */
+public interface EnterpriseNewsScopeDeptService extends IService<EnterpriseNewsScopeDept> {
+
+}
diff --git a/src/main/java/com/ruoyi/collaborativeApproval/service/EnterpriseNewsScopeUserService.java b/src/main/java/com/ruoyi/collaborativeApproval/service/EnterpriseNewsScopeUserService.java
new file mode 100644
index 0000000..28ac6c7
--- /dev/null
+++ b/src/main/java/com/ruoyi/collaborativeApproval/service/EnterpriseNewsScopeUserService.java
@@ -0,0 +1,16 @@
+package com.ruoyi.collaborativeApproval.service;
+
+import com.ruoyi.collaborativeApproval.pojo.EnterpriseNewsScopeUser;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ * 浼佷笟鏂伴椈闃呰鑼冨洿鐢ㄦ埛琛� 鏈嶅姟绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-20 11:51:23
+ */
+public interface EnterpriseNewsScopeUserService extends IService<EnterpriseNewsScopeUser> {
+
+}
diff --git a/src/main/java/com/ruoyi/collaborativeApproval/service/EnterpriseNewsService.java b/src/main/java/com/ruoyi/collaborativeApproval/service/EnterpriseNewsService.java
new file mode 100644
index 0000000..21e7e6c
--- /dev/null
+++ b/src/main/java/com/ruoyi/collaborativeApproval/service/EnterpriseNewsService.java
@@ -0,0 +1,29 @@
+package com.ruoyi.collaborativeApproval.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.collaborativeApproval.dto.EnterpriseNewsDto;
+import com.ruoyi.collaborativeApproval.pojo.EnterpriseNews;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.collaborativeApproval.vo.EnterpriseNewsVo;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 浼佷笟鏂伴椈琛� 鏈嶅姟绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-20 11:50:59
+ */
+public interface EnterpriseNewsService extends IService<EnterpriseNews> {
+
+    IPage<EnterpriseNewsVo> listPage(Page<EnterpriseNewsVo> page, EnterpriseNewsDto enterpriseNewsDto);
+
+    Boolean add(EnterpriseNewsDto enterpriseNewsDto);
+
+    Boolean updateEnterpriseNewsDto(EnterpriseNewsDto enterpriseNewsDto);
+
+    Boolean delete(List<Long> ids);
+}
diff --git a/src/main/java/com/ruoyi/collaborativeApproval/service/impl/EnterpriseNewsScopeDeptServiceImpl.java b/src/main/java/com/ruoyi/collaborativeApproval/service/impl/EnterpriseNewsScopeDeptServiceImpl.java
new file mode 100644
index 0000000..22283c7
--- /dev/null
+++ b/src/main/java/com/ruoyi/collaborativeApproval/service/impl/EnterpriseNewsScopeDeptServiceImpl.java
@@ -0,0 +1,20 @@
+package com.ruoyi.collaborativeApproval.service.impl;
+
+import com.ruoyi.collaborativeApproval.pojo.EnterpriseNewsScopeDept;
+import com.ruoyi.collaborativeApproval.mapper.EnterpriseNewsScopeDeptMapper;
+import com.ruoyi.collaborativeApproval.service.EnterpriseNewsScopeDeptService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ * 浼佷笟鏂伴椈闃呰鑼冨洿閮ㄩ棬琛� 鏈嶅姟瀹炵幇绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-20 11:51:12
+ */
+@Service
+public class EnterpriseNewsScopeDeptServiceImpl extends ServiceImpl<EnterpriseNewsScopeDeptMapper, EnterpriseNewsScopeDept> implements EnterpriseNewsScopeDeptService {
+
+}
diff --git a/src/main/java/com/ruoyi/collaborativeApproval/service/impl/EnterpriseNewsScopeUserServiceImpl.java b/src/main/java/com/ruoyi/collaborativeApproval/service/impl/EnterpriseNewsScopeUserServiceImpl.java
new file mode 100644
index 0000000..db1521e
--- /dev/null
+++ b/src/main/java/com/ruoyi/collaborativeApproval/service/impl/EnterpriseNewsScopeUserServiceImpl.java
@@ -0,0 +1,20 @@
+package com.ruoyi.collaborativeApproval.service.impl;
+
+import com.ruoyi.collaborativeApproval.pojo.EnterpriseNewsScopeUser;
+import com.ruoyi.collaborativeApproval.mapper.EnterpriseNewsScopeUserMapper;
+import com.ruoyi.collaborativeApproval.service.EnterpriseNewsScopeUserService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ * 浼佷笟鏂伴椈闃呰鑼冨洿鐢ㄦ埛琛� 鏈嶅姟瀹炵幇绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-20 11:51:23
+ */
+@Service
+public class EnterpriseNewsScopeUserServiceImpl extends ServiceImpl<EnterpriseNewsScopeUserMapper, EnterpriseNewsScopeUser> implements EnterpriseNewsScopeUserService {
+
+}
diff --git a/src/main/java/com/ruoyi/collaborativeApproval/service/impl/EnterpriseNewsServiceImpl.java b/src/main/java/com/ruoyi/collaborativeApproval/service/impl/EnterpriseNewsServiceImpl.java
new file mode 100644
index 0000000..2cf7fae
--- /dev/null
+++ b/src/main/java/com/ruoyi/collaborativeApproval/service/impl/EnterpriseNewsServiceImpl.java
@@ -0,0 +1,378 @@
+package com.ruoyi.collaborativeApproval.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.approve.mapper.ApprovalInstanceMapper;
+import com.ruoyi.approve.mapper.ApprovalTemplateMapper;
+import com.ruoyi.approve.pojo.ApprovalInstance;
+import com.ruoyi.approve.pojo.ApprovalTask;
+import com.ruoyi.approve.pojo.ApprovalTemplate;
+import com.ruoyi.approve.utils.ApproveProcessConfigNodeUtils;
+import com.ruoyi.collaborativeApproval.dto.EnterpriseNewsDto;
+import com.ruoyi.collaborativeApproval.mapper.EnterpriseNewsMapper;
+import com.ruoyi.collaborativeApproval.pojo.EnterpriseNews;
+import com.ruoyi.collaborativeApproval.pojo.EnterpriseNewsScopeDept;
+import com.ruoyi.collaborativeApproval.pojo.EnterpriseNewsScopeUser;
+import com.ruoyi.collaborativeApproval.service.EnterpriseNewsScopeDeptService;
+import com.ruoyi.collaborativeApproval.service.EnterpriseNewsScopeUserService;
+import com.ruoyi.collaborativeApproval.service.EnterpriseNewsService;
+import com.ruoyi.collaborativeApproval.vo.EnterpriseNewsVo;
+import com.ruoyi.common.enums.TypeEnums;
+import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.common.utils.OrderUtils;
+import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.project.system.domain.SysDept;
+import com.ruoyi.project.system.domain.SysUser;
+import com.ruoyi.project.system.mapper.SysDeptMapper;
+import com.ruoyi.project.system.mapper.SysUserDeptMapper;
+import com.ruoyi.project.system.mapper.SysUserMapper;
+import com.ruoyi.project.system.service.ISysNoticeService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.beans.BeanUtils;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+/**
+ * 浼佷笟鏂伴椈琛ㄦ湇鍔″疄鐜扮被
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-20 11:50:59
+ */
+@Service
+@RequiredArgsConstructor
+public class EnterpriseNewsServiceImpl extends ServiceImpl<EnterpriseNewsMapper, EnterpriseNews> implements EnterpriseNewsService {
+
+    private static final String READ_SCOPE_ALL = "all";
+    private static final String READ_SCOPE_DEPT = "dept";
+    private static final String READ_SCOPE_CUSTOM = "custom";
+
+    private static final String STATUS_DRAFT = "DRAFT";
+    private static final String STATUS_PENDING = "PENDING";
+    private static final String STATUS_PUBLISHED = "PUBLISHED";
+    private static final String STATUS_REJECTED = "REJECTED";
+    private static final String STATUS_OFFLINE = "OFFLINE";
+
+    private final EnterpriseNewsMapper enterpriseNewsMapper;
+    private final EnterpriseNewsScopeDeptService enterpriseNewsScopeDeptService;
+    private final EnterpriseNewsScopeUserService enterpriseNewsScopeUserService;
+    private final SysUserMapper sysUserMapper;
+    private final SysDeptMapper sysDeptMapper;
+    private final SysUserDeptMapper sysUserDeptMapper;
+    private final ApprovalInstanceMapper approvalInstanceMapper;
+    private final ApprovalTemplateMapper approvalTemplateMapper;
+    private final ApproveProcessConfigNodeUtils approveProcessConfigNodeUtils;
+    private final ISysNoticeService sysNoticeService;
+
+    @Override
+    public IPage<EnterpriseNewsVo> listPage(Page<EnterpriseNewsVo> page, EnterpriseNewsDto enterpriseNewsDto) {
+        return enterpriseNewsMapper.listPage(page, enterpriseNewsDto);
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Boolean add(EnterpriseNewsDto enterpriseNewsDto) {
+        validateForSave(enterpriseNewsDto);
+        String readScope = normalizeReadScope(enterpriseNewsDto.getReadScope());
+        List<Long> deptIds = distinctIds(enterpriseNewsDto.getDeptIds());
+        List<Long> userIds = distinctIds(enterpriseNewsDto.getUserIds());
+
+        EnterpriseNews enterpriseNews = new EnterpriseNews();
+        BeanUtils.copyProperties(enterpriseNewsDto, enterpriseNews);
+        enterpriseNews.setReadScope(readScope);
+        enterpriseNews.setIsRequired(enterpriseNewsDto.getIsRequired() == null ? (byte) 0 : enterpriseNewsDto.getIsRequired());
+        enterpriseNews.setStatus(normalizeStatus(enterpriseNewsDto.getStatus(), STATUS_DRAFT));
+        enterpriseNews.setReadCount(0);
+        enterpriseNews.setRequiredReadCount(calculateRequiredReadCount(readScope, deptIds, userIds));
+
+        Long[] loginDeptIds = SecurityUtils.getDeptId();
+        if (StringUtils.isNotEmpty(loginDeptIds)) {
+            enterpriseNews.setDeptId(loginDeptIds[0]);
+        }
+
+        if (!save(enterpriseNews) || enterpriseNews.getId() == null) {
+            throw new ServiceException("鏂板浼佷笟鏂伴椈澶辫触");
+        }
+
+        saveReadScopeRelations(enterpriseNews.getId(), readScope, deptIds, userIds);
+        if (STATUS_PENDING.equals(enterpriseNews.getStatus())) {
+            startEnterpriseNewsApproval(enterpriseNews, enterpriseNewsDto);
+        }
+        return true;
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Boolean updateEnterpriseNewsDto(EnterpriseNewsDto enterpriseNewsDto) {
+        if (enterpriseNewsDto == null || enterpriseNewsDto.getId() == null) {
+            throw new ServiceException("浼佷笟鏂伴椈ID涓嶈兘涓虹┖");
+        }
+
+        EnterpriseNews oldEnterpriseNews = getById(enterpriseNewsDto.getId());
+        if (oldEnterpriseNews == null) {
+            throw new ServiceException("浼佷笟鏂伴椈涓嶅瓨鍦�");
+        }
+        if (!STATUS_DRAFT.equals(oldEnterpriseNews.getStatus())
+                && !STATUS_REJECTED.equals(oldEnterpriseNews.getStatus())) {
+            throw new ServiceException("寰呭鎵规垨宸插彂甯冪殑浼佷笟鏂伴椈涓嶅厑璁镐慨鏀�");
+        }
+
+        validateForSave(enterpriseNewsDto);
+        String readScope = normalizeReadScope(enterpriseNewsDto.getReadScope());
+        List<Long> deptIds = distinctIds(enterpriseNewsDto.getDeptIds());
+        List<Long> userIds = distinctIds(enterpriseNewsDto.getUserIds());
+
+        EnterpriseNews enterpriseNews = new EnterpriseNews();
+        BeanUtils.copyProperties(enterpriseNewsDto, enterpriseNews);
+        enterpriseNews.setReadScope(readScope);
+        enterpriseNews.setIsRequired(enterpriseNewsDto.getIsRequired() == null ? oldEnterpriseNews.getIsRequired() : enterpriseNewsDto.getIsRequired());
+        enterpriseNews.setStatus(normalizeStatus(enterpriseNewsDto.getStatus(), oldEnterpriseNews.getStatus()));
+        enterpriseNews.setReadCount(oldEnterpriseNews.getReadCount());
+        enterpriseNews.setRequiredReadCount(calculateRequiredReadCount(readScope, deptIds, userIds));
+        enterpriseNews.setCreateUser(oldEnterpriseNews.getCreateUser());
+        enterpriseNews.setCreateTime(oldEnterpriseNews.getCreateTime());
+        enterpriseNews.setDeptId(oldEnterpriseNews.getDeptId());
+
+        if (!updateById(enterpriseNews)) {
+            throw new ServiceException("淇敼浼佷笟鏂伴椈澶辫触");
+        }
+
+        clearReadScopeRelations(enterpriseNews.getId());
+        saveReadScopeRelations(enterpriseNews.getId(), readScope, deptIds, userIds);
+
+        if (STATUS_PENDING.equals(enterpriseNews.getStatus())) {
+            startEnterpriseNewsApproval(enterpriseNews, enterpriseNewsDto);
+        }
+        return true;
+    }
+
+    @Override
+    public Boolean delete(List<Long> ids) {
+        if (ids == null || ids.isEmpty()) {
+            return false;
+        }
+        if (!removeByIds(ids)) {
+            throw new ServiceException("鍒犻櫎浼佷笟鏂伴椈澶辫触");
+        }
+        ids.forEach(this::clearReadScopeRelations);
+        return true;
+    }
+
+    private void validateForSave(EnterpriseNewsDto enterpriseNewsDto) {
+        if (enterpriseNewsDto == null) {
+            throw new ServiceException("浼佷笟鏂伴椈鏁版嵁涓嶈兘涓虹┖");
+        }
+        if (StringUtils.isEmpty(enterpriseNewsDto.getTitle())) {
+            throw new ServiceException("鏍囬涓嶈兘涓虹┖");
+        }
+        if (StringUtils.isEmpty(enterpriseNewsDto.getContent())) {
+            throw new ServiceException("姝f枃涓嶈兘涓虹┖");
+        }
+
+        normalizeStatus(enterpriseNewsDto.getStatus(), STATUS_DRAFT);
+        String readScope = normalizeReadScope(enterpriseNewsDto.getReadScope());
+        List<Long> deptIds = distinctIds(enterpriseNewsDto.getDeptIds());
+        List<Long> userIds = distinctIds(enterpriseNewsDto.getUserIds());
+
+        if (READ_SCOPE_DEPT.equals(readScope) && StringUtils.isEmpty(deptIds)) {
+            throw new ServiceException("璇烽�夋嫨闃呰鑼冨洿閮ㄩ棬");
+        }
+        if (READ_SCOPE_CUSTOM.equals(readScope) && StringUtils.isEmpty(userIds)) {
+            throw new ServiceException("璇烽�夋嫨鑷畾涔夐槄璇讳汉鍛�");
+        }
+
+        validateDeptIds(deptIds);
+        validateUserIds(userIds);
+    }
+
+    private String normalizeReadScope(String readScope) {
+        String normalized = StringUtils.isEmpty(readScope) ? READ_SCOPE_ALL : readScope.trim();
+        if (!READ_SCOPE_ALL.equals(normalized)
+                && !READ_SCOPE_DEPT.equals(normalized)
+                && !READ_SCOPE_CUSTOM.equals(normalized)) {
+            throw new ServiceException("闃呰鑼冨洿涓嶅悎娉�");
+        }
+        return normalized;
+    }
+
+    private String normalizeStatus(String status, String defaultStatus) {
+        String normalized = StringUtils.isEmpty(status) ? defaultStatus : status.trim().toUpperCase();
+        if (!STATUS_DRAFT.equals(normalized)
+                && !STATUS_PENDING.equals(normalized)
+                && !STATUS_PUBLISHED.equals(normalized)
+                && !STATUS_REJECTED.equals(normalized)
+                && !STATUS_OFFLINE.equals(normalized)) {
+            throw new ServiceException("浼佷笟鏂伴椈鐘舵�佷笉鍚堟硶");
+        }
+        return normalized;
+    }
+
+    private void validateDeptIds(List<Long> deptIds) {
+        if (StringUtils.isEmpty(deptIds)) {
+            return;
+        }
+        for (Long deptId : deptIds) {
+            SysDept sysDept = sysDeptMapper.selectDeptById(deptId);
+            if (deptId == null || sysDept == null) {
+                throw new ServiceException("闃呰鑼冨洿閮ㄩ棬涓嶅瓨鍦�");
+            }
+        }
+    }
+
+    private void validateUserIds(List<Long> userIds) {
+        if (StringUtils.isEmpty(userIds)) {
+            return;
+        }
+        List<SysUser> users = sysUserMapper.selectUsersByIds(userIds);
+        if (users.size() != userIds.size()) {
+            throw new ServiceException("鑷畾涔夐槄璇讳汉鍛樺寘鍚棤鏁堢敤鎴�");
+        }
+    }
+
+    private Integer calculateRequiredReadCount(String readScope, List<Long> deptIds, List<Long> userIds) {
+        if (READ_SCOPE_ALL.equals(readScope)) {
+            Long count = sysUserMapper.selectCount(new LambdaQueryWrapper<SysUser>()
+                    .eq(SysUser::getDelFlag, "0"));
+            return count == null ? 0 : count.intValue();
+        }
+        if (READ_SCOPE_DEPT.equals(readScope)) {
+            List<Long> allDeptIds = collectDeptIdsWithChildren(deptIds);
+            if (StringUtils.isEmpty(allDeptIds)) {
+                return 0;
+            }
+            Long count = sysUserDeptMapper.countDistinctUserIdsByDeptIds(allDeptIds);
+            return count == null ? 0 : count.intValue();
+        }
+        return userIds.size();
+    }
+
+    private List<Long> collectDeptIdsWithChildren(List<Long> deptIds) {
+        Set<Long> allDeptIds = new LinkedHashSet<>();
+        for (Long deptId : deptIds) {
+            if (deptId == null) {
+                continue;
+            }
+            allDeptIds.add(deptId);
+            List<SysDept> children = sysDeptMapper.selectChildrenDeptById(deptId);
+            if (StringUtils.isNotEmpty(children)) {
+                for (SysDept child : children) {
+                    allDeptIds.add(child.getDeptId());
+                }
+            }
+        }
+        return new ArrayList<>(allDeptIds);
+    }
+
+    private void saveReadScopeRelations(Long newsId, String readScope, List<Long> deptIds, List<Long> userIds) {
+        if (READ_SCOPE_DEPT.equals(readScope)) {
+            List<EnterpriseNewsScopeDept> scopeDeptList = new ArrayList<>();
+            for (Long deptId : deptIds) {
+                EnterpriseNewsScopeDept scopeDept = new EnterpriseNewsScopeDept();
+                scopeDept.setNewsId(newsId);
+                scopeDept.setDeptId(deptId);
+                scopeDeptList.add(scopeDept);
+            }
+            if (StringUtils.isNotEmpty(scopeDeptList)) {
+                enterpriseNewsScopeDeptService.saveBatch(scopeDeptList);
+            }
+            return;
+        }
+
+        if (READ_SCOPE_CUSTOM.equals(readScope)) {
+            List<EnterpriseNewsScopeUser> scopeUserList = new ArrayList<>();
+            for (Long userId : userIds) {
+                EnterpriseNewsScopeUser scopeUser = new EnterpriseNewsScopeUser();
+                scopeUser.setNewsId(newsId);
+                scopeUser.setUserId(userId);
+                scopeUserList.add(scopeUser);
+            }
+            if (StringUtils.isNotEmpty(scopeUserList)) {
+                enterpriseNewsScopeUserService.saveBatch(scopeUserList);
+            }
+        }
+    }
+
+    private void clearReadScopeRelations(Long newsId) {
+        enterpriseNewsScopeDeptService.remove(new LambdaQueryWrapper<EnterpriseNewsScopeDept>()
+                .eq(EnterpriseNewsScopeDept::getNewsId, newsId));
+        enterpriseNewsScopeUserService.remove(new LambdaQueryWrapper<EnterpriseNewsScopeUser>()
+                .eq(EnterpriseNewsScopeUser::getNewsId, newsId));
+    }
+
+    private List<Long> distinctIds(List<Long> ids) {
+        if (StringUtils.isEmpty(ids)) {
+            return new ArrayList<>();
+        }
+        Set<Long> distinctSet = new LinkedHashSet<>();
+        for (Long id : ids) {
+            if (id != null) {
+                distinctSet.add(id);
+            }
+        }
+        return new ArrayList<>(distinctSet);
+    }
+
+    private void startEnterpriseNewsApproval(EnterpriseNews enterpriseNews, EnterpriseNewsDto enterpriseNewsDto) {
+        if (enterpriseNewsDto.getTemplateId() == null) {
+            throw new ServiceException("瀹℃壒妯℃澘涓嶈兘涓虹┖");
+        }
+
+        String templateName = enterpriseNewsDto.getTemplateName();
+        if (StringUtils.isEmpty(templateName)) {
+            ApprovalTemplate approvalTemplate = approvalTemplateMapper.selectById(enterpriseNewsDto.getTemplateId());
+            if (approvalTemplate == null) {
+                throw new ServiceException("瀹℃壒妯℃澘涓嶅瓨鍦�");
+            }
+            templateName = approvalTemplate.getTemplateName();
+        }
+
+        ApprovalInstance approvalInstance = new ApprovalInstance();
+        approvalInstance.setInstanceNo(OrderUtils.countTodayByCreateTime(approvalInstanceMapper, "SP", "instance_no"));
+        approvalInstance.setTemplateId(enterpriseNewsDto.getTemplateId());
+        approvalInstance.setTemplateName(templateName);
+        approvalInstance.setBusinessId(enterpriseNews.getId());
+        approvalInstance.setBusinessType(TypeEnums.ENTERPRISE_NEWS_APPROVAL.getCode());
+        approvalInstance.setTitle(enterpriseNews.getTitle());
+        approvalInstance.setStatus("PENDING");
+        approvalInstance.setCurrentLevel(1);
+        approvalInstance.setApplicantId(SecurityUtils.getUserId());
+        approvalInstance.setApplicantName(SecurityUtils.getLoginUser().getNickName());
+        approvalInstance.setApplyTime(LocalDateTime.now());
+        approvalInstance.setDeleted((byte) 0);
+        approvalInstance.setCreateUser(SecurityUtils.getUserId());
+        approvalInstance.setUpdateUser(SecurityUtils.getUserId());
+        approvalInstance.setDeptId(enterpriseNews.getDeptId());
+        approvalInstanceMapper.insert(approvalInstance);
+
+        approveProcessConfigNodeUtils.createCurrentNodeAndTasks(approvalInstance);
+        sendApproveNotice(approvalInstance, approveProcessConfigNodeUtils.getCurrentPendingTasks(approvalInstance.getId()));
+    }
+
+    private void sendApproveNotice(ApprovalInstance instance, List<ApprovalTask> tasks) {
+        if (instance == null || tasks == null || tasks.isEmpty()) {
+            return;
+        }
+        List<Long> approverIds = tasks.stream()
+                .map(ApprovalTask::getApproverId)
+                .filter(id -> id != null && id > 0)
+                .distinct()
+                .collect(Collectors.toList());
+        if (approverIds.isEmpty()) {
+            return;
+        }
+
+        String title = StringUtils.isNotEmpty(instance.getTemplateName()) ? instance.getTemplateName() : "瀹℃壒鎻愰啋";
+        String message = "瀹℃壒鍗曞彿 " + instance.getInstanceNo() + " 闇�瑕佹偍瀹℃壒";
+        String jumpPath = "/approvalInstance?id=" + instance.getId();
+        sysNoticeService.simpleNoticeByUser(title, message, approverIds, jumpPath);
+    }
+}
diff --git a/src/main/java/com/ruoyi/collaborativeApproval/vo/EnterpriseNewsVo.java b/src/main/java/com/ruoyi/collaborativeApproval/vo/EnterpriseNewsVo.java
new file mode 100644
index 0000000..ef40e65
--- /dev/null
+++ b/src/main/java/com/ruoyi/collaborativeApproval/vo/EnterpriseNewsVo.java
@@ -0,0 +1,10 @@
+package com.ruoyi.collaborativeApproval.vo;
+
+import com.ruoyi.collaborativeApproval.pojo.EnterpriseNews;
+import lombok.Data;
+
+@Data
+public class EnterpriseNewsVo extends EnterpriseNews {
+
+    private String createUserName;
+}
diff --git a/src/main/java/com/ruoyi/common/enums/ApprovalStatusEnum.java b/src/main/java/com/ruoyi/common/enums/ApprovalStatusEnum.java
index bece915..8913ebd 100644
--- a/src/main/java/com/ruoyi/common/enums/ApprovalStatusEnum.java
+++ b/src/main/java/com/ruoyi/common/enums/ApprovalStatusEnum.java
@@ -16,6 +16,7 @@
     APPROVED(3, "宸查�氳繃"),
     REJECTED(4, "宸查┏鍥�");
 
+
     private final Integer value;
     private final String label;
 
diff --git a/src/main/java/com/ruoyi/common/enums/EnterpriseNewsStatusEnum.java b/src/main/java/com/ruoyi/common/enums/EnterpriseNewsStatusEnum.java
new file mode 100644
index 0000000..8e6e480
--- /dev/null
+++ b/src/main/java/com/ruoyi/common/enums/EnterpriseNewsStatusEnum.java
@@ -0,0 +1,143 @@
+package com.ruoyi.common.enums;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonValue;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Getter;
+
+/**
+ * 浼佷笟鏂伴椈鐘舵�佹灇涓剧被
+ *
+ * @author ruoyi
+ * @date 2026-05-20
+ */
+@Schema(description = "浼佷笟鏂伴椈鐘舵�佹灇涓�")
+public enum EnterpriseNewsStatusEnum implements BaseEnum<String> {
+
+    /**
+     * 鑽夌
+     */
+    @Schema(description = "鑽夌")
+    DRAFT("DRAFT", "鑽夌"),
+
+    /**
+     * 寰呭鎵�
+     */
+    @Schema(description = "寰呭鎵�")
+    PENDING("PENDING", "寰呭鎵�"),
+
+    /**
+     * 宸插彂甯�
+     */
+    @Schema(description = "宸插彂甯�")
+    PUBLISHED("PUBLISHED", "宸插彂甯�"),
+
+    /**
+     * 椹冲洖
+     */
+    @Schema(description = "椹冲洖")
+    REJECTED("REJECTED", "椹冲洖"),
+
+    /**
+     * 宸蹭笅绾�
+     */
+    @Schema(description = "宸蹭笅绾�")
+    OFFLINE("OFFLINE", "宸蹭笅绾�");
+
+    /**
+     * 鐘舵�佺爜
+     */
+    private final String code;
+
+    /**
+     * 鐘舵�佹弿杩�
+     * -- GETTER --
+     *  鑾峰彇鐘舵�佹弿杩�
+     *
+     * @return 鐘舵�佹弿杩�
+
+     */
+    @Getter
+    private final String description;
+
+    EnterpriseNewsStatusEnum(String code, String description) {
+        this.code = code;
+        this.description = description;
+    }
+
+    /**
+     * 鑾峰彇鐘舵�佺爜
+     *
+     * @return 鐘舵�佺爜
+     */
+    @JsonValue
+    public String getCode() {
+        return code;
+    }
+
+    @Override
+    public String getValue() {
+        return "";
+    }
+
+    /**
+     * 鏍规嵁鐘舵�佺爜鑾峰彇鏋氫妇
+     *
+     * @param code 鐘舵�佺爜
+     * @return 鏋氫妇鍊�
+     */
+    @JsonCreator
+    public static EnterpriseNewsStatusEnum getByCode(String code) {
+        for (EnterpriseNewsStatusEnum status : values()) {
+            if (status.code.equals(code)) {
+                return status;
+            }
+        }
+        throw new IllegalArgumentException("Invalid enterprise news status code: " + code);
+    }
+
+    /**
+     * 鍒ゆ柇鏄惁涓鸿崏绋跨姸鎬�
+     *
+     * @return 鏄惁涓鸿崏绋跨姸鎬�
+     */
+    public boolean isDraft() {
+        return DRAFT.equals(this);
+    }
+
+    /**
+     * 鍒ゆ柇鏄惁涓哄緟瀹℃壒鐘舵��
+     *
+     * @return 鏄惁涓哄緟瀹℃壒鐘舵��
+     */
+    public boolean isPending() {
+        return PENDING.equals(this);
+    }
+
+    /**
+     * 鍒ゆ柇鏄惁涓哄凡鍙戝竷鐘舵��
+     *
+     * @return 鏄惁涓哄凡鍙戝竷鐘舵��
+     */
+    public boolean isPublished() {
+        return PUBLISHED.equals(this);
+    }
+
+    /**
+     * 鍒ゆ柇鏄惁涓洪┏鍥炵姸鎬�
+     *
+     * @return 鏄惁涓洪┏鍥炵姸鎬�
+     */
+    public boolean isRejected() {
+        return REJECTED.equals(this);
+    }
+
+    /**
+     * 鍒ゆ柇鏄惁涓哄凡涓嬬嚎鐘舵��
+     *
+     * @return 鏄惁涓哄凡涓嬬嚎鐘舵��
+     */
+    public boolean isOffline() {
+        return OFFLINE.equals(this);
+    }
+}
diff --git a/src/main/java/com/ruoyi/project/system/mapper/SysUserDeptMapper.java b/src/main/java/com/ruoyi/project/system/mapper/SysUserDeptMapper.java
index 8c0ca53..f5baaec 100644
--- a/src/main/java/com/ruoyi/project/system/mapper/SysUserDeptMapper.java
+++ b/src/main/java/com/ruoyi/project/system/mapper/SysUserDeptMapper.java
@@ -3,6 +3,7 @@
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.ruoyi.project.system.domain.SysUserDept;
 import com.ruoyi.project.system.domain.vo.SysUserDeptVo;
+import org.apache.ibatis.annotations.Select;
 import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Param;
 
@@ -15,4 +16,28 @@
     List<SysUserDeptVo> userLoginFacotryList(@Param("userDeptVo") SysUserDeptVo userDeptVo);
 
     List<Map<String, Object>> setSchemeApplicableStaffUserInfo(@Param("ids") List<Long> ids);
+
+    @Select("<script>" +
+            "select count(distinct sud.user_id) " +
+            "from sys_user_dept sud " +
+            "inner join sys_user su on su.user_id = sud.user_id " +
+            "where su.del_flag = '0' " +
+            "and sud.dept_id in " +
+            "<foreach collection='deptIds' item='deptId' open='(' separator=',' close=')'>" +
+            "#{deptId}" +
+            "</foreach>" +
+            "</script>")
+    Long countDistinctUserIdsByDeptIds(@Param("deptIds") List<Long> deptIds);
+
+    @Select("<script>" +
+            "select distinct sud.user_id " +
+            "from sys_user_dept sud " +
+            "inner join sys_user su on su.user_id = sud.user_id " +
+            "where su.del_flag = '0' " +
+            "and sud.dept_id in " +
+            "<foreach collection='deptIds' item='deptId' open='(' separator=',' close=')'>" +
+            "#{deptId}" +
+            "</foreach>" +
+            "</script>")
+    List<Long> selectDistinctUserIdsByDeptIds(@Param("deptIds") List<Long> deptIds);
 }
diff --git a/src/main/java/com/ruoyi/project/system/service/impl/SysNoticeServiceImpl.java b/src/main/java/com/ruoyi/project/system/service/impl/SysNoticeServiceImpl.java
index dcbcded..fdb610b 100644
--- a/src/main/java/com/ruoyi/project/system/service/impl/SysNoticeServiceImpl.java
+++ b/src/main/java/com/ruoyi/project/system/service/impl/SysNoticeServiceImpl.java
@@ -1,12 +1,14 @@
 package com.ruoyi.project.system.service.impl;
 
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.core.toolkit.Wrappers;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.ruoyi.common.utils.SecurityUtils;
-import com.ruoyi.project.system.domain.SysDept;
-import com.ruoyi.project.system.domain.SysNotice;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.collaborativeApproval.mapper.EnterpriseNewsMapper;
+import com.ruoyi.collaborativeApproval.pojo.EnterpriseNews;
+import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.project.system.domain.SysDept;
+import com.ruoyi.project.system.domain.SysNotice;
 import com.ruoyi.project.system.domain.SysUser;
 import com.ruoyi.project.system.domain.SysUserDept;
 import com.ruoyi.project.system.mapper.SysDeptMapper;
@@ -15,11 +17,15 @@
 import com.ruoyi.project.system.mapper.SysUserMapper;
 import com.ruoyi.project.system.service.ISysNoticeService;
 import lombok.RequiredArgsConstructor;
-import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
-
-import java.util.List;
-import java.util.stream.Collectors;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 /**
  * 鍏憡 鏈嶅姟灞傚疄鐜�
@@ -28,13 +34,16 @@
  */
 @Service
 @RequiredArgsConstructor
-public class SysNoticeServiceImpl  extends ServiceImpl<SysNoticeMapper, SysNotice> implements ISysNoticeService {
-
-    private final SysNoticeMapper noticeMapper;
-    private final SysUserMapper userMapper;
-    private final SysDeptMapper deptMapper;
-    private final SysUserDeptMapper userDeptMapper;
-    private final UnipushService unipushService;
+public class SysNoticeServiceImpl  extends ServiceImpl<SysNoticeMapper, SysNotice> implements ISysNoticeService {
+
+    private static final Pattern ENTERPRISE_NEWS_ID_PATTERN = Pattern.compile("[?&]id=(\\d+)");
+
+    private final SysNoticeMapper noticeMapper;
+    private final SysUserMapper userMapper;
+    private final SysDeptMapper deptMapper;
+    private final SysUserDeptMapper userDeptMapper;
+    private final UnipushService unipushService;
+    private final EnterpriseNewsMapper enterpriseNewsMapper;
 
     /**
      * 鏌ヨ鍏憡淇℃伅
@@ -77,11 +86,26 @@
      * @param notice 鍏憡淇℃伅
      * @return 缁撴灉
      */
-    @Override
-    public int updateNotice(SysNotice notice)
-    {
-        return noticeMapper.updateNotice(notice);
-    }
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public int updateNotice(SysNotice notice)
+    {
+        if (notice == null || notice.getNoticeId() == null) {
+            return 0;
+        }
+        SysNotice dbNotice = noticeMapper.selectNoticeById(notice.getNoticeId());
+        if (dbNotice == null) {
+            return 0;
+        }
+        boolean needSyncNewsReadCount = isEnterpriseNewsNotice(dbNotice)
+                && notice.getStatus() != null
+                && !notice.getStatus().equals(dbNotice.getStatus());
+        int rows = noticeMapper.updateNotice(notice);
+        if (rows > 0 && needSyncNewsReadCount) {
+            syncEnterpriseNewsReadCount(dbNotice.getJumpPath());
+        }
+        return rows;
+    }
 
     /**
      * 鍒犻櫎鍏憡瀵硅薄
@@ -115,13 +139,20 @@
     }
 
     @Override
-    public int readAll() {
-        Long userId = SecurityUtils.getUserId();
-        return noticeMapper.update(null, Wrappers.<SysNotice>lambdaUpdate()
-                .eq(SysNotice::getConsigneeId, userId)
-                .eq(SysNotice::getStatus, "0")
-                .set(SysNotice::getStatus, "1"));
-    }
+    public int readAll() {
+        Long userId = SecurityUtils.getUserId();
+        List<SysNotice> unreadNotices = noticeMapper.selectList(Wrappers.<SysNotice>lambdaQuery()
+                .eq(SysNotice::getConsigneeId, userId)
+                .eq(SysNotice::getStatus, "0"));
+        int rows = noticeMapper.update(null, Wrappers.<SysNotice>lambdaUpdate()
+                .eq(SysNotice::getConsigneeId, userId)
+                .eq(SysNotice::getStatus, "0")
+                .set(SysNotice::getStatus, "1"));
+        if (rows > 0) {
+            syncEnterpriseNewsReadCount(unreadNotices);
+        }
+        return rows;
+    }
 
     @Override
     public void simpleNoticeByUser(String title, String message, List<Long> consigneeId, String jumpPath) {
@@ -211,18 +242,72 @@
 
     @Override
     @Transactional(rollbackFor = Exception.class)
-    public boolean appReadNotice(Long noticeId) {
-        if (noticeId == null) {
-            return false;
+    public boolean appReadNotice(Long noticeId) {
+        if (noticeId == null) {
+            return false;
         }
         SysNotice sysNotice = noticeMapper.selectNoticeById(noticeId);
         if (sysNotice == null) {
             return false;
-        }
-        sysNotice.setStatus("1");
-        return noticeMapper.update(null, Wrappers.<SysNotice>lambdaUpdate()
-                .eq(SysNotice::getNoticeId, noticeId)
-                .eq(SysNotice::getStatus, "0")
-                .set(SysNotice::getStatus, "1")) > 0;
-    }
-}
+        }
+        sysNotice.setStatus("1");
+        boolean updated = noticeMapper.update(null, Wrappers.<SysNotice>lambdaUpdate()
+                .eq(SysNotice::getNoticeId, noticeId)
+                .eq(SysNotice::getStatus, "0")
+                .set(SysNotice::getStatus, "1")) > 0;
+        if (updated) {
+            syncEnterpriseNewsReadCount(sysNotice.getJumpPath());
+        }
+        return updated;
+    }
+
+    private boolean isEnterpriseNewsNotice(SysNotice sysNotice) {
+        return sysNotice != null
+                && sysNotice.getJumpPath() != null
+                && sysNotice.getJumpPath().startsWith("/enterpriseNews?id=");
+    }
+
+    private void syncEnterpriseNewsReadCount(List<SysNotice> notices) {
+        if (notices == null || notices.isEmpty()) {
+            return;
+        }
+        Set<String> jumpPaths = new HashSet<>();
+        for (SysNotice notice : notices) {
+            if (isEnterpriseNewsNotice(notice)) {
+                jumpPaths.add(notice.getJumpPath());
+            }
+        }
+        for (String jumpPath : jumpPaths) {
+            syncEnterpriseNewsReadCount(jumpPath);
+        }
+    }
+
+    private void syncEnterpriseNewsReadCount(String jumpPath) {
+        Long newsId = parseEnterpriseNewsId(jumpPath);
+        if (newsId == null) {
+            return;
+        }
+        long readCount = noticeMapper.selectCount(Wrappers.<SysNotice>lambdaQuery()
+                .eq(SysNotice::getStatus, "1")
+                .eq(SysNotice::getJumpPath, jumpPath));
+        EnterpriseNews enterpriseNews = new EnterpriseNews();
+        enterpriseNews.setId(newsId);
+        enterpriseNews.setReadCount((int) readCount);
+        enterpriseNewsMapper.updateById(enterpriseNews);
+    }
+
+    private Long parseEnterpriseNewsId(String jumpPath) {
+        if (jumpPath == null || !jumpPath.startsWith("/enterpriseNews")) {
+            return null;
+        }
+        Matcher matcher = ENTERPRISE_NEWS_ID_PATTERN.matcher(jumpPath);
+        if (!matcher.find()) {
+            return null;
+        }
+        try {
+            return Long.parseLong(matcher.group(1));
+        } catch (NumberFormatException e) {
+            return null;
+        }
+    }
+}
diff --git a/src/main/java/com/ruoyi/staff/service/impl/StaffLeaveServiceImpl.java b/src/main/java/com/ruoyi/staff/service/impl/StaffLeaveServiceImpl.java
index 548323d..4978d0f 100644
--- a/src/main/java/com/ruoyi/staff/service/impl/StaffLeaveServiceImpl.java
+++ b/src/main/java/com/ruoyi/staff/service/impl/StaffLeaveServiceImpl.java
@@ -59,6 +59,7 @@
         StaffLeave staffLeave = new StaffLeave();
         staffLeave.setStaffOnJobId(staffLeaveDto.getStaffOnJobId());
         staffLeave.setReason(staffLeaveDto.getReason());
+        staffLeave.setLeaveDate(staffLeaveDto.getLeaveDate());
         String reason = staffLeaveDto.getReason();
         if (StaffLeaveReasonOther.getCode().equals(reason)){
             staffLeave.setRemark(staffLeaveDto.getRemark());
diff --git a/src/main/resources/mapper/approve/ApprovalInstanceMapper.xml b/src/main/resources/mapper/approve/ApprovalInstanceMapper.xml
index 8f45b99..6b47daa 100644
--- a/src/main/resources/mapper/approve/ApprovalInstanceMapper.xml
+++ b/src/main/resources/mapper/approve/ApprovalInstanceMapper.xml
@@ -24,16 +24,28 @@
         <result column="deleted" property="deleted" />
     </resultMap>
     <select id="listPage" resultType="com.ruoyi.approve.bean.vo.ApprovalInstanceVo">
-        select ai.*,su.nick_name as create_user_name  from
+        select ai.*,su.nick_name as create_user_name from
         approval_instance ai
         left join sys_user su on ai.create_user = su.user_id
         <where>
             deleted = 0
             <if test="ew.instanceNo != null">
-                and instance_no like concat('%',#{ew.instanceNo},'%')
+                and ai.instance_no like concat('%',#{ew.instanceNo},'%')
             </if>
             <if test="ew.templateName != null">
-                and template_name like concat('%',#{ew.templateName},'%')
+                and ai.template_name like concat('%',#{ew.templateName},'%')
+            </if>
+            <if test="ew.templateId != null ">
+                and ai. template_id = #{ew.templateId}
+            </if>
+            <if test="ew.businessType != null ">
+                and ai. business_type = #{ew.businessType}
+            </if>
+            <if test="ew.createTime != null">
+                and ai.create_time between to_date(#{ew.createTimeStart}) and to_date(#{ew.createTimeEnd})
+            </if>
+            <if test="ew.status != null">
+                and ai.status = #{ew.status}
             </if>
         </where>
         order by ai.id desc
diff --git a/src/main/resources/mapper/collaborativeApproval/EnterpriseNewsMapper.xml b/src/main/resources/mapper/collaborativeApproval/EnterpriseNewsMapper.xml
new file mode 100644
index 0000000..fa45ea6
--- /dev/null
+++ b/src/main/resources/mapper/collaborativeApproval/EnterpriseNewsMapper.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.collaborativeApproval.mapper.EnterpriseNewsMapper">
+
+    <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
+    <resultMap id="BaseResultMap" type="com.ruoyi.collaborativeApproval.pojo.EnterpriseNews">
+        <id column="id" property="id" />
+        <result column="title" property="title" />
+        <result column="summary" property="summary" />
+        <result column="content" property="content" />
+        <result column="category" property="category" />
+        <result column="read_scope" property="readScope" />
+        <result column="is_required" property="isRequired" />
+        <result column="status" property="status" />
+        <result column="required_read_count" property="requiredReadCount" />
+        <result column="read_count" property="readCount" />
+        <result column="create_user" property="createUser" />
+        <result column="create_time" property="createTime" />
+        <result column="update_user" property="updateUser" />
+        <result column="update_time" property="updateTime" />
+        <result column="dept_id" property="deptId" />
+    </resultMap>
+    <select id="listPage" resultType="com.ruoyi.collaborativeApproval.vo.EnterpriseNewsVo">
+        select en.*, u.nick_name as create_user_name from
+        enterprise_news en
+        left join sys_user u on en.create_user = u.user_id
+        <where>
+            <if test="enterpriseNewsDto.title != null and enterpriseNewsDto.title != ''">
+                and en.title like concat('%',#{enterpriseNewsDto.title},'%')
+            </if>
+            <if test="enterpriseNewsDto.category != null and enterpriseNewsDto.category != ''">
+                and en.category = #{enterpriseNewsDto.category}
+            </if>
+            <if test="enterpriseNewsDto.status != null ">
+                and en.status = #{enterpriseNewsDto.status}
+            </if>
+            <if test="enterpriseNewsDto.createUser != null and enterpriseNewsDto.createUser != ''">
+                and en.create_user = #{enterpriseNewsDto.createUser}
+            </if>
+            <if test="enterpriseNewsDto.createTimeStart != null and enterpriseNewsDto.createTimeEnd != null">
+                and en.create_time between #{enterpriseNewsDto.createTimeStart} and #{enterpriseNewsDto.createTimeEnd}
+            </if>
+        </where>
+    </select>
+
+</mapper>
diff --git a/src/main/resources/mapper/collaborativeApproval/EnterpriseNewsScopeDeptMapper.xml b/src/main/resources/mapper/collaborativeApproval/EnterpriseNewsScopeDeptMapper.xml
new file mode 100644
index 0000000..0b13f67
--- /dev/null
+++ b/src/main/resources/mapper/collaborativeApproval/EnterpriseNewsScopeDeptMapper.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.collaborativeApproval.mapper.EnterpriseNewsScopeDeptMapper">
+
+    <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
+    <resultMap id="BaseResultMap" type="com.ruoyi.collaborativeApproval.pojo.EnterpriseNewsScopeDept">
+        <id column="id" property="id" />
+        <result column="news_id" property="newsId" />
+        <result column="dept_id" property="deptId" />
+        <result column="create_time" property="createTime" />
+    </resultMap>
+
+</mapper>
diff --git a/src/main/resources/mapper/collaborativeApproval/EnterpriseNewsScopeUserMapper.xml b/src/main/resources/mapper/collaborativeApproval/EnterpriseNewsScopeUserMapper.xml
new file mode 100644
index 0000000..7f4ac4b
--- /dev/null
+++ b/src/main/resources/mapper/collaborativeApproval/EnterpriseNewsScopeUserMapper.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.collaborativeApproval.mapper.EnterpriseNewsScopeUserMapper">
+
+    <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
+    <resultMap id="BaseResultMap" type="com.ruoyi.collaborativeApproval.pojo.EnterpriseNewsScopeUser">
+        <id column="id" property="id" />
+        <result column="news_id" property="newsId" />
+        <result column="user_id" property="userId" />
+        <result column="create_time" property="createTime" />
+    </resultMap>
+
+</mapper>
diff --git a/src/main/resources/mapper/staff/StaffLeaveMapper.xml b/src/main/resources/mapper/staff/StaffLeaveMapper.xml
index 4637ff0..8bc9607 100644
--- a/src/main/resources/mapper/staff/StaffLeaveMapper.xml
+++ b/src/main/resources/mapper/staff/StaffLeaveMapper.xml
@@ -18,15 +18,20 @@
         soj.emergency_contact as emergencyContact,
         soj.emergency_contact_phone as emergencyContactPhone,
         sp.post_name as postName,
-        sd.dept_name as deptName
+        sd.dept_name as deptName,
+        se.education as first_study,
+        se.major as profession
         FROM staff_leave
-        LEFT JOIN
-        staff_on_job soj ON soj.id = staff_leave.staff_on_job_id
-        LEFT JOIN
-        sys_post sp ON sp.post_id = soj.sys_post_id
-        LEFT JOIN
-        sys_dept sd ON sd.dept_id = soj.sys_dept_id
-        where 1=1
+        LEFT JOIN staff_on_job soj ON soj.id = staff_leave.staff_on_job_id
+        LEFT JOIN sys_post sp ON sp.post_id = soj.sys_post_id
+        LEFT JOIN sys_dept sd ON sd.dept_id = soj.sys_dept_id
+        LEFT JOIN staff_education se ON se.staff_on_job_id = staff_leave.staff_on_job_id
+        AND se.id = (
+        SELECT MAX(se2.id)
+        FROM staff_education se2
+        WHERE se2.staff_on_job_id = staff_leave.staff_on_job_id
+        )
+        WHERE 1=1
         <if test="c.staffName != null and c.staffName != '' ">
             AND soj.staff_name LIKE CONCAT('%',#{c.staffName},'%')
         </if>
diff --git a/src/main/resources/mapper/system/SysNoticeMapper.xml b/src/main/resources/mapper/system/SysNoticeMapper.xml
index 3dd5735..14372d8 100644
--- a/src/main/resources/mapper/system/SysNoticeMapper.xml
+++ b/src/main/resources/mapper/system/SysNoticeMapper.xml
@@ -10,11 +10,16 @@
         <result property="noticeType"     column="notice_type"     />
         <result property="noticeContent"  column="notice_content"  />
         <result property="status"         column="status"          />
+        <result property="senderId"       column="sender_id"       />
+        <result property="consigneeId"    column="consignee_id"    />
+        <result property="jumpPath"       column="jump_path"       />
+        <result property="appJumpPath"    column="app_jump_path"   />
         <result property="createBy"       column="create_by"       />
         <result property="createTime"     column="create_time"     />
         <result property="updateBy"       column="update_by"       />
         <result property="updateTime"     column="update_time"     />
         <result property="remark"         column="remark"          />
+        <result property="tenantId"       column="tenant_id"       />
     </resultMap>
 
     <sql id="selectNoticeVo">

--
Gitblit v1.9.3