Explorar el Código

feat(upms): 新增公告管理功能模块

- 新增 Announcement 实体类,支持文字公告和文件资料两种类型
- 新增 AnnouncementDTO 数据传输对象,包含新增和更新的分组校验
- 新增 AnnouncementMapper 数据访问接口,继承通用 MyMapper
- 新增 AnnouncementService 接口及实现类,支持发布、下架、恢复显示、批量删除等操作
- 新增 AnnouncementController 控制器,提供公告 CRUD、分页查询、前台最新公告列表等接口
- 实现前台公告栏按置顶优先和发布时间倒序展示,支持有效期过滤
- 管理端分页查询支持按标题、类型、状态条件筛选
dazhaxie hace 1 semana
padre
commit
1ec1edabf9

+ 112 - 0
platform-dao/src/main/java/com/platform/dao/dto/upms/AnnouncementDTO.java

@@ -0,0 +1,112 @@
+package com.platform.dao.dto.upms;
+
+import com.platform.common.bean.BaseDTO;
+import com.platform.common.validation.group.UpdateGroup;
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+import javax.validation.constraints.NotNull;
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+/**
+ * @Description 公告DTO
+ * @Author sunzhongwei
+ * @Date 2026-10-22
+ * @Version Copyright (c) 2019,北京乾元坤和科技有限公司 All rights reserved.
+ */
+@Data
+@Accessors(chain = true)
+public class AnnouncementDTO extends BaseDTO implements Serializable {
+
+    /**
+     * ID
+     */
+    @NotNull(groups = {UpdateGroup.class}, message = "ID不能为空")
+    private String id;
+
+    /**
+     * 类型:1文字公告 2文件资料
+     */
+    private Integer type;
+
+    /**
+     * 标题
+     */
+    private String title;
+
+    /**
+     * 文字公告内容(富文本 HTML)
+     */
+    private String content;
+
+    /**
+     * 文件地址(/files/... 相对路径)
+     */
+    private String fileUrl;
+
+    /**
+     * 文件名称(含后缀)
+     */
+    private String fileName;
+
+    /**
+     * 文件大小(字节)
+     */
+    private Long fileSize;
+
+    /**
+     * 状态:0草稿 1已发布 2已下架
+     */
+    private Integer status;
+
+    /**
+     * 是否置顶:1是 0否
+     */
+    private Integer topFlag;
+
+    /**
+     * 发布时间
+     */
+    private LocalDateTime publishTime;
+
+    /**
+     * 有效期至,空表示长期有效
+     */
+    private LocalDateTime expireTime;
+
+    /**
+     * 备注
+     */
+    private String remark;
+
+    /**
+     * 创建时间
+     */
+    private LocalDateTime createdTime;
+
+    /**
+     * 创建人ID
+     */
+    private String createdUserId;
+
+    /**
+     * 创建人名称
+     */
+    private String createdUserName;
+
+    /**
+     * 更新人ID
+     */
+    private String updateUserId;
+
+    /**
+     * 更新用户
+     */
+    private String updateUserName;
+
+    /**
+     * 更新时间
+     */
+    private LocalDateTime updateTime;
+}

+ 107 - 0
platform-dao/src/main/java/com/platform/dao/entity/upms/Announcement.java

@@ -0,0 +1,107 @@
+package com.platform.dao.entity.upms;
+
+import com.platform.common.bean.DataScope;
+import lombok.Data;
+
+import javax.persistence.Id;
+import javax.persistence.Table;
+import javax.persistence.Transient;
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+/**
+ * @Description 公告实体类
+ * @Author sunzhongwei
+ * @Date 2026-10-22
+ * @Version Copyright (c) 2019,北京乾元坤和科技有限公司 All rights reserved.
+ */
+@Table(name = "t_announcement")
+@Data
+public class Announcement implements Serializable {
+
+    /**
+     * ID
+     */
+    @Id
+    private String id;
+    /**
+     * 类型:1文字公告 2文件资料
+     */
+    private Integer type;
+    /**
+     * 标题
+     */
+    private String title;
+    /**
+     * 文字公告内容(富文本 HTML)
+     */
+    private String content;
+    /**
+     * 文件地址(/files/... 相对路径)
+     */
+    private String fileUrl;
+    /**
+     * 文件名称(含后缀)
+     */
+    private String fileName;
+    /**
+     * 文件大小(字节)
+     */
+    private Long fileSize;
+    /**
+     * 状态:0草稿 1已发布 2已下架
+     */
+    private Integer status;
+    /**
+     * 是否置顶:1是 0否
+     */
+    private Integer topFlag;
+    /**
+     * 发布时间
+     */
+    private LocalDateTime publishTime;
+    /**
+     * 有效期至,空表示长期有效
+     */
+    private LocalDateTime expireTime;
+    /**
+     * 备注
+     */
+    private String remark;
+    /**
+     * 是否删除:1.表示是,0表示否
+     */
+    private Integer delFlag;
+    /**
+     * 创建时间
+     */
+    private LocalDateTime createdTime;
+    /**
+     * 创建人ID
+     */
+    private String createdUserId;
+    /**
+     * 创建人名称
+     */
+    private String createdUserName;
+    /**
+     * 更新人ID
+     */
+    private String updateUserId;
+    /**
+     * 更新用户
+     */
+    private String updateUserName;
+    /**
+     * 更新时间
+     */
+    private LocalDateTime updateTime;
+
+    /**
+     * 数据权限
+     */
+    @Transient
+    private DataScope dataScope;
+
+}
+

+ 17 - 0
platform-dao/src/main/java/com/platform/dao/mapper/upms/AnnouncementMapper.java

@@ -0,0 +1,17 @@
+package com.platform.dao.mapper.upms;
+
+import com.platform.dao.config.MyMapper;
+import com.platform.dao.entity.upms.Announcement;
+import org.springframework.stereotype.Component;
+
+
+/**
+ * @Description 公告 mapper
+ * @Author sunzhongwei
+ * @Date 2026-10-22
+ * @Version Copyright (c) 2019,北京乾元坤和科技有限公司 All rights reserved.
+ */
+@Component
+public interface AnnouncementMapper extends MyMapper<Announcement> {
+
+}

+ 165 - 0
platform-rest/src/main/java/com/platform/rest/controller/upms/AnnouncementController.java

@@ -0,0 +1,165 @@
+package com.platform.rest.controller.upms;
+
+import com.platform.common.bean.AbstractPageResultBean;
+import com.platform.common.util.R;
+import com.platform.dao.dto.upms.AnnouncementDTO;
+import com.platform.dao.entity.upms.Announcement;
+import com.platform.rest.log.annotation.SysLog;
+import com.platform.service.upms.AnnouncementService;
+import com.platform.common.validation.group.AddGroup;
+import com.platform.common.validation.group.UpdateGroup;
+import lombok.AllArgsConstructor;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * @Description 公告 控制器
+ * @Author sunzhongwei
+ * @Date 2026-10-22
+ * @Version Copyright (c) 2019,北京乾元坤和科技有限公司 All rights reserved.
+ */
+@RestController
+@AllArgsConstructor
+@RequestMapping("/upms/announcements")
+public class AnnouncementController {
+
+    private final AnnouncementService announcementService;
+
+    /**
+     * 通过id查询单条记录
+     *
+     * @param id 主键
+     * @return R
+     */
+    @GetMapping("/{id}")
+    public R<Announcement> getById(@PathVariable("id") String id) {
+        return new R<>(announcementService.getModelById(id));
+    }
+
+    /**
+     * 前台公告栏:已发布且未最新的公告列表,所有登录用户可访问
+     *
+     * @param limit 条数,默认10
+     * @return R
+     */
+    @GetMapping("/latest")
+    public R<List<Announcement>> latest(@RequestParam(defaultValue = "10") int limit) {
+        return new R<>(announcementService.getPublishedList(limit));
+    }
+
+    /**
+     * 获取分页(管理端)
+     *
+     * @param pageNum        当前页码
+     * @param pageSize       每页条数
+     * @param announcementDTO 公告DTO
+     * @return R
+     */
+    @GetMapping("/page")
+    public R<AbstractPageResultBean<Announcement>> query(AnnouncementDTO announcementDTO,
+                                                         @RequestParam(defaultValue = "1") int pageNum,
+                                                         @RequestParam(defaultValue = "20") int pageSize) {
+        return new R<>(announcementService.selectPageInfo(announcementDTO, pageNum, pageSize));
+    }
+
+    /**
+     * 新增记录(默认草稿)
+     *
+     * @param announcementDTO 公告DTO
+     * @return R
+     */
+    @SysLog("新增公告")
+    @PostMapping
+    @PreAuthorize("@pms.hasPermission('announcement-add')")
+    public R save(@Validated({AddGroup.class}) @RequestBody AnnouncementDTO announcementDTO) {
+        return new R<>(announcementService.saveModelByDTO(announcementDTO));
+    }
+
+    /**
+     * 修改记录
+     *
+     * @param announcementDTO 公告DTO
+     * @return R
+     */
+    @SysLog("修改公告")
+    @PutMapping("/{id}")
+    @PreAuthorize("@pms.hasPermission('announcement-edit')")
+    public R update(@PathVariable("id") String id, @Validated({UpdateGroup.class}) @RequestBody AnnouncementDTO announcementDTO) {
+        announcementService.modModelByDTO(announcementDTO);
+        return new R<>();
+    }
+
+    /**
+     * 发布
+     *
+     * @param id 主键
+     * @return R
+     */
+    @SysLog("发布公告")
+    @PutMapping("/{id}/publish")
+    @PreAuthorize("@pms.hasPermission('announcement-publish')")
+    public R publish(@PathVariable("id") String id) {
+        announcementService.publish(id);
+        return new R<>();
+    }
+
+    /**
+     * 下架(用于过期公告从前台移除)
+     *
+     * @param id 主键
+     * @return R
+     */
+    @SysLog("下架公告")
+    @PutMapping("/{id}/hide")
+    @PreAuthorize("@pms.hasPermission('announcement-publish')")
+    public R hide(@PathVariable("id") String id) {
+        announcementService.hide(id);
+        return new R<>();
+    }
+
+    /**
+     * 恢复显示
+     *
+     * @param id 主键
+     * @return R
+     */
+    @SysLog("恢复公告")
+    @PutMapping("/{id}/show")
+    @PreAuthorize("@pms.hasPermission('announcement-publish')")
+    public R show(@PathVariable("id") String id) {
+        announcementService.show(id);
+        return new R<>();
+    }
+
+    /**
+     * 通过id删除一条记录
+     *
+     * @param id 主键
+     * @return R
+     */
+    @SysLog("删除公告")
+    @DeleteMapping("/{id}")
+    @PreAuthorize("@pms.hasPermission('announcement-del')")
+    public R removeById(@PathVariable String id) {
+        announcementService.deleteByPrimaryKey(id);
+        return new R<>();
+    }
+
+    /**
+     * 批量删除
+     *
+     * @param ids 主键集合
+     * @return R
+     */
+    @SysLog("批量删除公告")
+    @DeleteMapping("")
+    @PreAuthorize("@pms.hasPermission('announcement-del')")
+    public R removeIds(@RequestBody List<String> ids) {
+        announcementService.batchDelete(ids);
+        return new R<>();
+    }
+
+}

+ 67 - 0
platform-service/src/main/java/com/platform/service/upms/AnnouncementService.java

@@ -0,0 +1,67 @@
+package com.platform.service.upms;
+
+import com.platform.common.bean.AbstractPageResultBean;
+import com.platform.dao.dto.upms.AnnouncementDTO;
+import com.platform.dao.entity.upms.Announcement;
+import com.platform.service.base.IBaseService;
+
+import java.util.List;
+
+/**
+ * @Description 公告 service
+ * @Author sunzhongwei
+ * @Date 2026-10-22
+ * @Version Copyright (c) 2019,北京乾元坤和科技有限公司 All rights reserved.
+ */
+public interface AnnouncementService extends IBaseService<Announcement, AnnouncementDTO> {
+
+    /**
+     * 批量删除
+     *
+     * @param ids :主键集合
+     * @return :
+     */
+    int batchDelete(List<String> ids);
+
+    /**
+     * 发布:status=1 并写入发布时间
+     *
+     * @param id 主键
+     * @return :
+     */
+    int publish(String id);
+
+    /**
+     * 下架:status=2
+     *
+     * @param id 主键
+     * @return :
+     */
+    int hide(String id);
+
+    /**
+     * 恢复显示:status=1,不改发布时间
+     *
+     * @param id 主键
+     * @return :
+     */
+    int show(String id);
+
+    /**
+     * 前台已发布且未过期公告列表:置顶优先、发布时间倒序
+     *
+     * @param limit 条数
+     * @return :
+     */
+    List<Announcement> getPublishedList(int limit);
+
+    /**
+     * 管理端分页:支持标题/类型/状态条件,按发布时间倒序
+     *
+     * @param record   查询条件
+     * @param pageNum  当前页码
+     * @param pageSize 每页条数
+     * @return :
+     */
+    AbstractPageResultBean<Announcement> selectPageInfo(AnnouncementDTO record, int pageNum, int pageSize);
+}

+ 114 - 0
platform-service/src/main/java/com/platform/service/upms/impl/AnnouncementServiceImpl.java

@@ -0,0 +1,114 @@
+package com.platform.service.upms.impl;
+
+import com.github.pagehelper.PageHelper;
+import com.platform.common.bean.AbstractPageResultBean;
+import com.platform.common.util.StringUtils;
+import com.platform.dao.bean.MyPage;
+import com.platform.dao.dto.upms.AnnouncementDTO;
+import com.platform.dao.entity.upms.Announcement;
+import com.platform.dao.mapper.upms.AnnouncementMapper;
+import com.platform.service.base.impl.BaseServiceImpl;
+import com.platform.service.upms.AnnouncementService;
+import lombok.AllArgsConstructor;
+import org.springframework.stereotype.Service;
+import tk.mybatis.mapper.weekend.Weekend;
+import tk.mybatis.mapper.weekend.WeekendCriteria;
+
+import java.time.LocalDateTime;
+import java.util.List;
+
+/**
+ * @Description 公告 service 实现类
+ * @Author sunzhongwei
+ * @Date 2026-10-22
+ * @Version Copyright (c) 2019,北京乾元坤和科技有限公司 All rights reserved.
+ */
+@AllArgsConstructor
+@Service("announcementService")
+public class AnnouncementServiceImpl extends BaseServiceImpl<AnnouncementMapper, Announcement, AnnouncementDTO> implements AnnouncementService {
+
+    /**
+     * 状态:草稿
+     */
+    private static final int STATUS_DRAFT = 0;
+    /**
+     * 状态:已发布
+     */
+    private static final int STATUS_PUBLISHED = 1;
+    /**
+     * 状态:已下架
+     */
+    private static final int STATUS_HIDDEN = 2;
+
+    @Override
+    public int batchDelete(List<String> ids) {
+        Weekend<Announcement> weekend = new Weekend<>(Announcement.class);
+        WeekendCriteria<Announcement, Object> weekendCriteria = weekend.weekendCriteria();
+        weekendCriteria.andIn(Announcement::getId, ids);
+        mapper.deleteByExample(weekend);
+        return 1;
+    }
+
+    @Override
+    public int publish(String id) {
+        Announcement update = new Announcement();
+        update.setId(id);
+        update.setStatus(STATUS_PUBLISHED);
+        update.setPublishTime(LocalDateTime.now());
+        update.setUpdateTime(LocalDateTime.now());
+        return mapper.updateByPrimaryKeySelective(update);
+    }
+
+    @Override
+    public int hide(String id) {
+        Announcement update = new Announcement();
+        update.setId(id);
+        update.setStatus(STATUS_HIDDEN);
+        update.setUpdateTime(LocalDateTime.now());
+        return mapper.updateByPrimaryKeySelective(update);
+    }
+
+    @Override
+    public int show(String id) {
+        // 恢复显示,不改发布时间
+        Announcement update = new Announcement();
+        update.setId(id);
+        update.setStatus(STATUS_PUBLISHED);
+        update.setUpdateTime(LocalDateTime.now());
+        return mapper.updateByPrimaryKeySelective(update);
+    }
+
+    @Override
+    public List<Announcement> getPublishedList(int limit) {
+        Weekend<Announcement> weekend = new Weekend<>(Announcement.class);
+        // status=1 且 (expire_time is null 或 expire_time > now)
+        WeekendCriteria<Announcement, Object> criteria = weekend.weekendCriteria();
+        criteria.andEqualTo(Announcement::getStatus, STATUS_PUBLISHED);
+        criteria.andCondition("(expire_time is null or expire_time > now())");
+
+        weekend.setOrderByClause("top_flag desc, publish_time desc");
+        if (limit > 0) {
+            PageHelper.startPage(1, limit);
+        }
+        return mapper.selectByExample(weekend);
+    }
+
+    @Override
+    public AbstractPageResultBean<Announcement> selectPageInfo(AnnouncementDTO record, int pageNum, int pageSize) {
+        PageHelper.startPage(pageNum, pageSize);
+        Weekend<Announcement> weekend = new Weekend<>(Announcement.class);
+        WeekendCriteria<Announcement, Object> criteria = weekend.weekendCriteria();
+        String title = record.getTitle();
+        if (StringUtils.isNotEmpty(title)) {
+            criteria.andLike(Announcement::getTitle, "%" + title + "%");
+        }
+        if (record.getType() != null) {
+            criteria.andEqualTo(Announcement::getType, record.getType());
+        }
+        if (record.getStatus() != null) {
+            criteria.andEqualTo(Announcement::getStatus, record.getStatus());
+        }
+        weekend.setOrderByClause("top_flag desc, publish_time desc, created_time desc");
+        return new MyPage<>(mapper.selectByExample(weekend));
+    }
+}