feat(消息中心): 消息中心新增项目id和组织id

This commit is contained in:
guoyuqi 2024-03-05 19:35:13 +08:00 committed by 刘瑞斌
parent ebf7d5ca5f
commit 4d8b2292e4
10 changed files with 310 additions and 8 deletions

View File

@ -52,6 +52,16 @@ public class Notification implements Serializable {
@Size(min = 1, max = 50, message = "{notification.resource_id.length_range}", groups = {Created.class, Updated.class})
private String resourceId;
@Schema(description = "项目id", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "{notification.project_id.not_blank}", groups = {Created.class})
@Size(min = 1, max = 50, message = "{notification.project_id.length_range}", groups = {Created.class, Updated.class})
private String projectId;
@Schema(description = "组织id", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "{notification.organization_id.not_blank}", groups = {Created.class})
@Size(min = 1, max = 50, message = "{notification.organization_id.length_range}", groups = {Created.class, Updated.class})
private String organizationId;
@Schema(description = "资源类型", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "{notification.resource_type.not_blank}", groups = {Created.class})
@Size(min = 1, max = 64, message = "{notification.resource_type.length_range}", groups = {Created.class, Updated.class})
@ -79,6 +89,8 @@ public class Notification implements Serializable {
operator("operator", "operator", "VARCHAR", true),
operation("operation", "operation", "VARCHAR", true),
resourceId("resource_id", "resourceId", "VARCHAR", false),
projectId("project_id", "projectId", "VARCHAR", false),
organizationId("organization_id", "organizationId", "VARCHAR", false),
resourceType("resource_type", "resourceType", "VARCHAR", false),
resourceName("resource_name", "resourceName", "VARCHAR", false),
content("content", "content", "LONGVARCHAR", false);

View File

@ -714,6 +714,146 @@ public class NotificationExample {
return (Criteria) this;
}
public Criteria andProjectIdIsNull() {
addCriterion("project_id is null");
return (Criteria) this;
}
public Criteria andProjectIdIsNotNull() {
addCriterion("project_id is not null");
return (Criteria) this;
}
public Criteria andProjectIdEqualTo(String value) {
addCriterion("project_id =", value, "projectId");
return (Criteria) this;
}
public Criteria andProjectIdNotEqualTo(String value) {
addCriterion("project_id <>", value, "projectId");
return (Criteria) this;
}
public Criteria andProjectIdGreaterThan(String value) {
addCriterion("project_id >", value, "projectId");
return (Criteria) this;
}
public Criteria andProjectIdGreaterThanOrEqualTo(String value) {
addCriterion("project_id >=", value, "projectId");
return (Criteria) this;
}
public Criteria andProjectIdLessThan(String value) {
addCriterion("project_id <", value, "projectId");
return (Criteria) this;
}
public Criteria andProjectIdLessThanOrEqualTo(String value) {
addCriterion("project_id <=", value, "projectId");
return (Criteria) this;
}
public Criteria andProjectIdLike(String value) {
addCriterion("project_id like", value, "projectId");
return (Criteria) this;
}
public Criteria andProjectIdNotLike(String value) {
addCriterion("project_id not like", value, "projectId");
return (Criteria) this;
}
public Criteria andProjectIdIn(List<String> values) {
addCriterion("project_id in", values, "projectId");
return (Criteria) this;
}
public Criteria andProjectIdNotIn(List<String> values) {
addCriterion("project_id not in", values, "projectId");
return (Criteria) this;
}
public Criteria andProjectIdBetween(String value1, String value2) {
addCriterion("project_id between", value1, value2, "projectId");
return (Criteria) this;
}
public Criteria andProjectIdNotBetween(String value1, String value2) {
addCriterion("project_id not between", value1, value2, "projectId");
return (Criteria) this;
}
public Criteria andOrganizationIdIsNull() {
addCriterion("organization_id is null");
return (Criteria) this;
}
public Criteria andOrganizationIdIsNotNull() {
addCriterion("organization_id is not null");
return (Criteria) this;
}
public Criteria andOrganizationIdEqualTo(String value) {
addCriterion("organization_id =", value, "organizationId");
return (Criteria) this;
}
public Criteria andOrganizationIdNotEqualTo(String value) {
addCriterion("organization_id <>", value, "organizationId");
return (Criteria) this;
}
public Criteria andOrganizationIdGreaterThan(String value) {
addCriterion("organization_id >", value, "organizationId");
return (Criteria) this;
}
public Criteria andOrganizationIdGreaterThanOrEqualTo(String value) {
addCriterion("organization_id >=", value, "organizationId");
return (Criteria) this;
}
public Criteria andOrganizationIdLessThan(String value) {
addCriterion("organization_id <", value, "organizationId");
return (Criteria) this;
}
public Criteria andOrganizationIdLessThanOrEqualTo(String value) {
addCriterion("organization_id <=", value, "organizationId");
return (Criteria) this;
}
public Criteria andOrganizationIdLike(String value) {
addCriterion("organization_id like", value, "organizationId");
return (Criteria) this;
}
public Criteria andOrganizationIdNotLike(String value) {
addCriterion("organization_id not like", value, "organizationId");
return (Criteria) this;
}
public Criteria andOrganizationIdIn(List<String> values) {
addCriterion("organization_id in", values, "organizationId");
return (Criteria) this;
}
public Criteria andOrganizationIdNotIn(List<String> values) {
addCriterion("organization_id not in", values, "organizationId");
return (Criteria) this;
}
public Criteria andOrganizationIdBetween(String value1, String value2) {
addCriterion("organization_id between", value1, value2, "organizationId");
return (Criteria) this;
}
public Criteria andOrganizationIdNotBetween(String value1, String value2) {
addCriterion("organization_id not between", value1, value2, "organizationId");
return (Criteria) this;
}
public Criteria andResourceTypeIsNull() {
addCriterion("resource_type is null");
return (Criteria) this;

View File

@ -11,6 +11,8 @@
<result column="operator" jdbcType="VARCHAR" property="operator" />
<result column="operation" jdbcType="VARCHAR" property="operation" />
<result column="resource_id" jdbcType="VARCHAR" property="resourceId" />
<result column="project_id" jdbcType="VARCHAR" property="projectId" />
<result column="organization_id" jdbcType="VARCHAR" property="organizationId" />
<result column="resource_type" jdbcType="VARCHAR" property="resourceType" />
<result column="resource_name" jdbcType="VARCHAR" property="resourceName" />
</resultMap>
@ -77,7 +79,7 @@
</sql>
<sql id="Base_Column_List">
id, `type`, receiver, subject, `status`, create_time, `operator`, `operation`, resource_id,
resource_type, resource_name
project_id, organization_id, resource_type, resource_name
</sql>
<sql id="Blob_Column_List">
content
@ -134,13 +136,13 @@
insert into notification (id, `type`, receiver,
subject, `status`, create_time,
`operator`, `operation`, resource_id,
resource_type, resource_name, content
)
project_id, organization_id, resource_type,
resource_name, content)
values (#{id,jdbcType=BIGINT}, #{type,jdbcType=VARCHAR}, #{receiver,jdbcType=VARCHAR},
#{subject,jdbcType=VARCHAR}, #{status,jdbcType=VARCHAR}, #{createTime,jdbcType=BIGINT},
#{operator,jdbcType=VARCHAR}, #{operation,jdbcType=VARCHAR}, #{resourceId,jdbcType=VARCHAR},
#{resourceType,jdbcType=VARCHAR}, #{resourceName,jdbcType=VARCHAR}, #{content,jdbcType=LONGVARCHAR}
)
#{projectId,jdbcType=VARCHAR}, #{organizationId,jdbcType=VARCHAR}, #{resourceType,jdbcType=VARCHAR},
#{resourceName,jdbcType=VARCHAR}, #{content,jdbcType=LONGVARCHAR})
</insert>
<insert id="insertSelective" parameterType="io.metersphere.project.domain.Notification">
insert into notification
@ -172,6 +174,12 @@
<if test="resourceId != null">
resource_id,
</if>
<if test="projectId != null">
project_id,
</if>
<if test="organizationId != null">
organization_id,
</if>
<if test="resourceType != null">
resource_type,
</if>
@ -210,6 +218,12 @@
<if test="resourceId != null">
#{resourceId,jdbcType=VARCHAR},
</if>
<if test="projectId != null">
#{projectId,jdbcType=VARCHAR},
</if>
<if test="organizationId != null">
#{organizationId,jdbcType=VARCHAR},
</if>
<if test="resourceType != null">
#{resourceType,jdbcType=VARCHAR},
</if>
@ -257,6 +271,12 @@
<if test="record.resourceId != null">
resource_id = #{record.resourceId,jdbcType=VARCHAR},
</if>
<if test="record.projectId != null">
project_id = #{record.projectId,jdbcType=VARCHAR},
</if>
<if test="record.organizationId != null">
organization_id = #{record.organizationId,jdbcType=VARCHAR},
</if>
<if test="record.resourceType != null">
resource_type = #{record.resourceType,jdbcType=VARCHAR},
</if>
@ -282,6 +302,8 @@
`operator` = #{record.operator,jdbcType=VARCHAR},
`operation` = #{record.operation,jdbcType=VARCHAR},
resource_id = #{record.resourceId,jdbcType=VARCHAR},
project_id = #{record.projectId,jdbcType=VARCHAR},
organization_id = #{record.organizationId,jdbcType=VARCHAR},
resource_type = #{record.resourceType,jdbcType=VARCHAR},
resource_name = #{record.resourceName,jdbcType=VARCHAR},
content = #{record.content,jdbcType=LONGVARCHAR}
@ -300,6 +322,8 @@
`operator` = #{record.operator,jdbcType=VARCHAR},
`operation` = #{record.operation,jdbcType=VARCHAR},
resource_id = #{record.resourceId,jdbcType=VARCHAR},
project_id = #{record.projectId,jdbcType=VARCHAR},
organization_id = #{record.organizationId,jdbcType=VARCHAR},
resource_type = #{record.resourceType,jdbcType=VARCHAR},
resource_name = #{record.resourceName,jdbcType=VARCHAR}
<if test="_parameter != null">
@ -333,6 +357,12 @@
<if test="resourceId != null">
resource_id = #{resourceId,jdbcType=VARCHAR},
</if>
<if test="projectId != null">
project_id = #{projectId,jdbcType=VARCHAR},
</if>
<if test="organizationId != null">
organization_id = #{organizationId,jdbcType=VARCHAR},
</if>
<if test="resourceType != null">
resource_type = #{resourceType,jdbcType=VARCHAR},
</if>
@ -355,6 +385,8 @@
`operator` = #{operator,jdbcType=VARCHAR},
`operation` = #{operation,jdbcType=VARCHAR},
resource_id = #{resourceId,jdbcType=VARCHAR},
project_id = #{projectId,jdbcType=VARCHAR},
organization_id = #{organizationId,jdbcType=VARCHAR},
resource_type = #{resourceType,jdbcType=VARCHAR},
resource_name = #{resourceName,jdbcType=VARCHAR},
content = #{content,jdbcType=LONGVARCHAR}
@ -370,6 +402,8 @@
`operator` = #{operator,jdbcType=VARCHAR},
`operation` = #{operation,jdbcType=VARCHAR},
resource_id = #{resourceId,jdbcType=VARCHAR},
project_id = #{projectId,jdbcType=VARCHAR},
organization_id = #{organizationId,jdbcType=VARCHAR},
resource_type = #{resourceType,jdbcType=VARCHAR},
resource_name = #{resourceName,jdbcType=VARCHAR}
where id = #{id,jdbcType=BIGINT}
@ -377,14 +411,14 @@
<insert id="batchInsert" parameterType="map">
insert into notification
(id, `type`, receiver, subject, `status`, create_time, `operator`, `operation`, resource_id,
resource_type, resource_name, content)
project_id, organization_id, resource_type, resource_name, content)
values
<foreach collection="list" item="item" separator=",">
(#{item.id,jdbcType=BIGINT}, #{item.type,jdbcType=VARCHAR}, #{item.receiver,jdbcType=VARCHAR},
#{item.subject,jdbcType=VARCHAR}, #{item.status,jdbcType=VARCHAR}, #{item.createTime,jdbcType=BIGINT},
#{item.operator,jdbcType=VARCHAR}, #{item.operation,jdbcType=VARCHAR}, #{item.resourceId,jdbcType=VARCHAR},
#{item.resourceType,jdbcType=VARCHAR}, #{item.resourceName,jdbcType=VARCHAR}, #{item.content,jdbcType=LONGVARCHAR}
)
#{item.projectId,jdbcType=VARCHAR}, #{item.organizationId,jdbcType=VARCHAR}, #{item.resourceType,jdbcType=VARCHAR},
#{item.resourceName,jdbcType=VARCHAR}, #{item.content,jdbcType=LONGVARCHAR})
</foreach>
</insert>
<insert id="batchInsertSelective" parameterType="map">
@ -424,6 +458,12 @@
<if test="'resource_id'.toString() == column.value">
#{item.resourceId,jdbcType=VARCHAR}
</if>
<if test="'project_id'.toString() == column.value">
#{item.projectId,jdbcType=VARCHAR}
</if>
<if test="'organization_id'.toString() == column.value">
#{item.organizationId,jdbcType=VARCHAR}
</if>
<if test="'resource_type'.toString() == column.value">
#{item.resourceType,jdbcType=VARCHAR}
</if>

View File

@ -303,6 +303,8 @@ CREATE TABLE IF NOT EXISTS notification(
`operator` VARCHAR(50) NOT NULL COMMENT '操作人' ,
`operation` VARCHAR(50) NOT NULL COMMENT '操作' ,
`resource_id` VARCHAR(50) NOT NULL COMMENT '资源ID' ,
`project_id` VARCHAR(50) NOT NULL COMMENT '项目id' ,
`organization_id` VARCHAR(50) NOT NULL COMMENT '组织id' ,
`resource_type` VARCHAR(64) NOT NULL COMMENT '资源类型' ,
`resource_name` VARCHAR(255) NOT NULL COMMENT '资源名称' ,
`content` TEXT NOT NULL COMMENT '通知内容' ,
@ -320,6 +322,8 @@ CREATE INDEX idx_subject ON notification(subject);
CREATE INDEX idx_resource_type ON notification(resource_type);
CREATE INDEX idx_operator ON notification(operator);
CREATE INDEX idx_resource_id ON notification(resource_id);
CREATE INDEX idx_project_id ON notification(project_id);
CREATE INDEX idx_organization_id ON notification(organization_id);
CREATE TABLE IF NOT EXISTS project_robot(

View File

@ -0,0 +1,35 @@
package io.metersphere.system.job;
import com.fit2cloud.quartz.anno.QuartzScheduled;
import io.metersphere.sdk.util.LogUtils;
import io.metersphere.system.mapper.BaseNotificationMapper;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
import java.time.ZoneId;
@Component
public class CleanNotificationJob {
@Resource
private BaseNotificationMapper baseNotificationMapper;
/**
* 清理状态为删除的项目 每天凌晨三点执行
*/
@QuartzScheduled(cron = "0 0 3 * * ?")
public void cleanupNotification() {
LogUtils.info("clean up notification start.");
LocalDateTime dateTime = LocalDateTime.now().minusDays(90);
long timestamp = dateTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
this.doCleanupNotification(timestamp);
LogUtils.info("clean up notification end.");
}
private void doCleanupNotification(long timestamp) {
//获取所有站内通知
baseNotificationMapper.deleteByTime(timestamp);
}
}

View File

@ -11,4 +11,6 @@ public interface BaseNotificationMapper {
List<NotificationDTO> listNotification(@Param("request") NotificationRequest notificationRequest);
void deleteByTime(@Param("timestamp") long timestamp);
}

View File

@ -23,4 +23,8 @@
ORDER BY notification.create_time DESC
</select>
<delete id="deleteByTime" parameterType="java.lang.Long">
DELETE FROM notification WHERE create_time &lt; #{timestamp}
</delete>
</mapper>

View File

@ -2,6 +2,8 @@ package io.metersphere.system.notice.sender.impl;
import io.metersphere.project.domain.Notification;
import io.metersphere.project.domain.Project;
import io.metersphere.project.mapper.ProjectMapper;
import io.metersphere.sdk.util.LogUtils;
import io.metersphere.system.notice.MessageDetail;
import io.metersphere.system.notice.NoticeModel;
@ -21,17 +23,22 @@ public class InSiteNoticeSender extends AbstractNoticeSender {
@Resource
private NotificationService notificationService;
@Resource
private ProjectMapper projectMapper;
public void sendAnnouncement(MessageDetail messageDetail, NoticeModel noticeModel, String context) {
List<Receiver> receivers = super.getReceivers(noticeModel.getReceivers(), noticeModel.isExcludeSelf(), noticeModel.getOperator());
if (CollectionUtils.isEmpty(receivers)) {
return;
}
Project project = projectMapper.selectByPrimaryKey(messageDetail.getProjectId());
LogUtils.info("发送站内通知: {}", receivers);
receivers.forEach(receiver -> {
Map<String, Object> paramMap = noticeModel.getParamMap();
Notification notification = new Notification();
notification.setSubject(noticeModel.getSubject());
notification.setProjectId(messageDetail.getProjectId());
notification.setOrganizationId(project.getOrganizationId());
notification.setOperator(noticeModel.getOperator());
notification.setOperation(noticeModel.getEvent());
notification.setResourceId((String) paramMap.get("id"));

View File

@ -39,6 +39,8 @@ public class NotificationControllerTests extends BaseTest {
notification.setOperator("admin");
notification.setOperation("UPDATE");
notification.setResourceType("FUNCTIONAL_CASE_TASK");
notification.setOrganizationId("10001");
notification.setProjectId("10000100001");
notification.setResourceName("功能用例导入测4");
notification.setType("SYSTEM_NOTICE");
notification.setStatus(NotificationConstants.Status.UNREAD.name());

View File

@ -0,0 +1,56 @@
package io.metersphere.system.job;
import io.metersphere.project.domain.Notification;
import io.metersphere.project.domain.NotificationExample;
import io.metersphere.project.mapper.NotificationMapper;
import io.metersphere.system.notice.constants.NotificationConstants;
import jakarta.annotation.Resource;
import org.apache.commons.collections.CollectionUtils;
import org.junit.jupiter.api.*;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
@SpringBootTest(webEnvironment= SpringBootTest.WebEnvironment.RANDOM_PORT)
@AutoConfigureMockMvc
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class CleanNotificationJobTests {
@Resource
private CleanNotificationJob cleanNotificationJob;
@Resource
private NotificationMapper notificationMapper;
void saveNotice() {
Notification notification = new Notification();
notification.setSubject("功能用例更新通知");
notification.setOperator("admin");
notification.setOperation("UPDATE");
notification.setResourceType("FUNCTIONAL_CASE_TASK");
notification.setOrganizationId("10001");
notification.setProjectId("10000100001");
notification.setResourceName("功能用例导入测4");
notification.setType("SYSTEM_NOTICE");
notification.setStatus(NotificationConstants.Status.UNREAD.name());
notification.setCreateTime(1701659702000L);
notification.setReceiver("admin");
notification.setResourceId("cleanNotification");
notification.setContent("nihao");
notificationMapper.insert(notification);
}
@Test
@Order(0)
public void cleanupNotificationSuccess(){
saveNotice();
NotificationExample notificationExample = new NotificationExample();
notificationExample.createCriteria().andResourceIdEqualTo("cleanNotification");
List<Notification> notifications = notificationMapper.selectByExample(notificationExample);
Assertions.assertTrue(CollectionUtils.isNotEmpty(notifications));
cleanNotificationJob.cleanupNotification();
notifications = notificationMapper.selectByExample(notificationExample);
Assertions.assertTrue(CollectionUtils.isEmpty(notifications));
}
}