通知
build / build-push (push) Failing after 1m18s

This commit is contained in:
wanghu
2026-09-10 15:39:41 +08:00
parent 2c8125a549
commit 3016a97f1b
86 changed files with 3427 additions and 1669 deletions
@@ -0,0 +1,49 @@
package com.yunhai.campusnotice.entity;
import com.yunhai.campusnotice.common.listener.NoticeAuditListener;
import lombok.Getter;
import lombok.Setter;
import javax.persistence.*;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* 所有实体的公共基类:自增主键 + 创建人/时间 + 更新人/时间(由 {@link NoticeAuditListener} 自动填充)。
*/
@MappedSuperclass
@Getter
@Setter
@EntityListeners(NoticeAuditListener.class)
public abstract class BaseEntity implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
/**
* 创建人登录账号
*/
@Column(name = "create_by", updatable = false)
private String createBy;
/**
* 创建时间
*/
@Column(name = "create_time", updatable = false)
private LocalDateTime createTime;
/**
* 更新人登录账号
*/
@Column(name = "update_by")
private String updateBy;
/**
* 更新时间
*/
@Column(name = "update_time")
private LocalDateTime updateTime;
}
@@ -0,0 +1,28 @@
package com.yunhai.campusnotice.entity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;
/**
* 联系组。对应原 .NET Contacts_Group 表。
*/
@NoArgsConstructor
@Data
@Entity
@Table(name = "contacts_group")
@EqualsAndHashCode(onlyExplicitlyIncluded = true, callSuper = false)
public class ContactsGroup extends BaseEntity {
/** 组名称 */
@Column(name = "group_name", length = 200)
private String groupName;
/** 创建人账号 */
@Column(name = "creator_account", length = 64)
private String creatorAccount;
}
@@ -0,0 +1,39 @@
package com.yunhai.campusnotice.entity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
/**
* 联系组-用户关联。对应原 .NET Contacts_Tea 表。
*/
@NoArgsConstructor
@Data
@Entity
@Table(name = "contacts_group_user",
uniqueConstraints = @UniqueConstraint(name = "uk_group_user",
columnNames = {"group_id", "user_id"}))
@EqualsAndHashCode(onlyExplicitlyIncluded = true, callSuper = false)
public class ContactsGroupUser extends BaseEntity {
/** 联系组ID */
@Column(name = "group_id", nullable = false)
private Integer groupId;
/** 用户ID(基础平台用户ID) */
@Column(name = "user_id", nullable = false)
private Integer userId;
/** 用户账号 */
@Column(name = "user_account", length = 64)
private String userAccount;
/** 用户姓名 */
@Column(name = "user_name", length = 64)
private String userName;
}
@@ -0,0 +1,174 @@
package com.yunhai.campusnotice.entity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;
import java.time.LocalDateTime;
/**
* 校园公告主表。对应原 .NET Notify_Message(已剔除短信/模板/门户等无关字段)。
* <p>
* 阅读状态不落主表:采用「懒标记」模型——读者首次查看时写入 {@link NoticeRead},
* 不存在阅读记录即视为未读,从而无需在发通知时枚举全校用户预插接收行。
*/
@NoArgsConstructor
@Data
@Entity
@Table(name = "notice")
@EqualsAndHashCode(onlyExplicitlyIncluded = true, callSuper = false)
public class Notice extends BaseEntity {
/**
* 通知标题
*/
@Column(name = "title", nullable = false, length = 200)
private String title;
/**
* 学校ID(多租户隔离:发布时从当前用户角色填充,查询时按校过滤)。
*/
@Column(name = "sch_id")
private Integer schId;
/**
* 通知内容
*/
@Column(name = "content", columnDefinition = "LONGTEXT")
private String content;
/**
* 通知类型:1 普通 / 2 重要(见 {@link com.yunhai.campusnotice.enums.NoticeTypeEnum})
*/
@Column(name = "type", nullable = false)
private Integer type = 1;
/**
* 发布人登录账号
*/
@Column(name = "publisher_account", length = 64)
private String publisherAccount;
/**
* 发布人姓名
*/
@Column(name = "publisher_name", length = 64)
private String publisherName;
/**
* 所属分类ID(原 DeptID)
*/
@Column(name = "dept_id", length = 64)
private String deptId;
/**
* 所属分类名称
*/
@Column(name = "dept_name", length = 128)
private String deptName;
/**
* 状态机值见 {@link com.yunhai.campusnotice.enums.NoticeStatusEnum}:
* 0 草稿 / 1 已发布 / 2 待审批 / 3 已驳回。
*/
@Column(name = "status", nullable = false)
private Integer status = 0;
/**
* 是否置顶:0 否 / 1 是(原 topmost)
*/
@Column(name = "topmost")
private Integer topmost = 0;
// ==================== 迁移补全字段(对应 C# Notify_Message) ====================
/**
* 接收人列表(JSON 数组,如 ["account1","account2"] 或接收组ID列表)。
* 对应 C# Notify_Message.ReceiveList
*/
@Column(name = "receive_list", columnDefinition = "LONGTEXT")
private String receiveList;
/**
* 密码发送(对应 C# Notify_Message.PwdSend)
*/
@Column(name = "pwd_send", length = 255)
private String pwdSend;
/**
* 抄送人列表(对应 C# Notify_Message.ChaoSend)
*/
@Column(name = "chao_send", length = 2000)
private String chaoSend;
/**
* 已读数(发送时初始化为 0,也可由 NoticeRead 表 COUNT 实时计算)。
* 对应 C# Notify_Message.readcount
*/
@Column(name = "read_count")
private Integer readCount = 0;
/**
* 应读数(接收人总数)。对应 C# Notify_Message.allowcount
*/
@Column(name = "allow_count")
private Integer allowCount = 0;
/**
* 父通知ID(转发时关联原通知)。对应 C# Notify_Message.fkid
*/
@Column(name = "parent_id")
private Integer parentId;
/**
* 回复ID。对应 C# Notify_Message.reid
*/
@Column(name = "reply_id", length = 255)
private String replyId;
/**
* 是否撤回:0 否 / 1 是。对应 C# Notify_Message.ispull
*/
@Column(name = "is_pulled")
private Integer isPulled = 0;
/**
* 定时发送时间(到时间后自动发布)。对应 C# Notify_Message.DsfsTime
*/
@Column(name = "timing_send_time")
private LocalDateTime timingSendTime;
/**
* 短信发送标记:0 不发短信 / 1 发短信。对应 C# Notify_Message.dxbit
*/
@Column(name = "sms_flag")
private Integer smsFlag = 0;
// ==================== 新版发布表单扩展字段(改造方案 2.1) ====================
/**
* 是否需要学员阅读回执:0 否 / 1 是。
* =1 时管理端展示已读/未读统计与「催收未读」入口,学员端展示回执提示;
* =0 时阅读仍照常记录(notice_read),但不出催收与回执提示(改动面最小)。
*/
@Column(name = "receipt_flag")
private Integer receiptFlag = 0;
/**
* 审批人快照(JSON 账号数组,如 ["account1","account2"]):提交审批时由发布人选定(可多选)。
* ApprovalList 据此过滤「待我审批」;或签任一处理后状态即离开待审批,快照留作历史追溯。
* 驳回重提并更换审批人后,该快照被新一轮提交覆盖(已知边界,见改造方案 4.4)。
*/
@Column(name = "approver_accounts", columnDefinition = "LONGTEXT")
private String approverAccounts;
/**
* 定时发送已真正发布标记:到点调度后回写为 1,避免重复触发(改造方案 4.2)。
* 立即发布的通知在真实发布时一并置 1。
*/
@Column(name = "timing_published")
private Integer timingPublished = 0;
}
@@ -0,0 +1,71 @@
package com.yunhai.campusnotice.entity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import javax.persistence.*;
import java.time.LocalDateTime;
/**
* 通知阅读记录(懒标记)。对应原 .NET Notify_ReceiveList 的「逐用户阅读状态」语义,
* 但仅在读者首次查看时落库,避免发通知时预插全员。
* <p>
* 唯一约束 (notice_id, reader_account):同一用户对同一通知只记一条已读。
*/
@NoArgsConstructor
@Data
@Entity
@Table(name = "notice_read",
uniqueConstraints = @UniqueConstraint(
name = "uk_notice_reader",
columnNames = {"notice_id", "reader_account"}))
@EqualsAndHashCode(onlyExplicitlyIncluded = true, callSuper = false)
public class NoticeRead extends BaseEntity {
/**
* 通知ID(关联 notice.id)
*/
@Column(name = "notice_id", nullable = false)
private Integer noticeId;
/**
* 读者登录账号
*/
@Column(name = "reader_account", nullable = false, length = 64)
private String readerAccount;
/**
* 读者姓名
*/
@Column(name = "reader_name", length = 64)
private String readerName;
/**
* 阅读时间
*/
@Column(name = "read_time")
private LocalDateTime readTime;
// ==================== 阅读身份快照(改造方案 2.3,学员阅读时带出) ====================
/** 学校ID(取通知 sch_id) */
@Column(name = "sch_id")
private Integer schId;
/** 年级ID快照 */
@Column(name = "grade_id")
private Integer gradeId;
/** 年级名称快照 */
@Column(name = "grade_name", length = 128)
private String gradeName;
/** 班级ID快照 */
@Column(name = "class_id")
private Integer classId;
/** 班级名称快照 */
@Column(name = "class_name", length = 128)
private String className;
}
@@ -0,0 +1,67 @@
package com.yunhai.campusnotice.entity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Index;
import javax.persistence.Table;
/**
* 通知接收人关联表(快照语义:真实发布时一次写入,后续组织调整不影响历史通知)。
* <p>
* 教师定向:全员通知(receive_list="ALL")不写明细行,读取时按 receive_list="ALL" 标识走旧逻辑兜底。
* 学员圈人(新版发布表单):推送范围按 bschclass 展开为学员账号集合批量写入,
* 并携带年级/班级身份快照,供学员端可见性过滤、回执分组(年级→班级→学生)、催收取数。
*/
@NoArgsConstructor
@Data
@Entity
@Table(name = "notice_receiver",
indexes = {
@Index(name = "idx_notice_id", columnList = "notice_id"),
@Index(name = "idx_account", columnList = "account")
})
@EqualsAndHashCode(onlyExplicitlyIncluded = true, callSuper = false)
public class NoticeReceiver extends BaseEntity {
/** 接收类型:1 教师(现状语义,存量数据全为 1) / 2 学员(推送范围解析快照) */
public static final int TYPE_TEACHER = 1;
public static final int TYPE_STUDENT = 2;
/** 通知ID(关联 notice.id) */
@Column(name = "notice_id", nullable = false)
private Integer noticeId;
/** 接收人登录账号(学员=SchStudent.account) */
@Column(name = "account", nullable = false, length = 64)
private String account;
/** 接收类型:1 教师 / 2 学员(原「2 抄送」从未写入过数据,语义重定义,存量无需迁移) */
@Column(name = "receive_type", nullable = false)
private Integer receiveType = TYPE_TEACHER;
// ==================== 学员身份快照(发布时从 bschclass 带出,仅 receive_type=2 使用) ====================
/** 学员姓名快照 */
@Column(name = "stu_name", length = 64)
private String stuName;
/** 年级ID快照 */
@Column(name = "grade_id")
private Integer gradeId;
/** 年级名称快照(如「初二年级」) */
@Column(name = "grade_name", length = 128)
private String gradeName;
/** 班级ID快照(sch_class.class_id) */
@Column(name = "class_id")
private Integer classId;
/** 班级名称快照 */
@Column(name = "class_name", length = 128)
private String className;
}
@@ -0,0 +1,40 @@
package com.yunhai.campusnotice.entity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;
/**
* 通知模板。对应原 .NET Notify_Template 表。
*/
@NoArgsConstructor
@Data
@Entity
@Table(name = "notice_template")
@EqualsAndHashCode(onlyExplicitlyIncluded = true, callSuper = false)
public class NoticeTemplate extends BaseEntity {
/** 模板标题 */
@Column(name = "title", length = 200)
private String title;
/** 模板内容(HTML) */
@Column(name = "content", columnDefinition = "LONGTEXT")
private String content;
/** 封面图片文件ID */
@Column(name = "cover")
private Integer cover;
/** 引用次数 */
@Column(name = "ref_count")
private Integer refCount = 0;
/** 模板类型ID */
@Column(name = "type_id")
private Integer typeId;
}
@@ -0,0 +1,28 @@
package com.yunhai.campusnotice.entity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;
/**
* 短信模块配置。对应原 .NET SchSms 表。
*/
@NoArgsConstructor
@Data
@Entity
@Table(name = "sms_module")
@EqualsAndHashCode(onlyExplicitlyIncluded = true, callSuper = false)
public class SmsModule extends BaseEntity {
/** 模块名称 */
@Column(name = "module_name", length = 100)
private String moduleName;
/** 模块标识 */
@Column(name = "module_code", length = 50)
private String moduleCode;
}
@@ -0,0 +1,37 @@
package com.yunhai.campusnotice.entity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;
/**
* 学校短信开通配置。对应原 .NET SchSms_Set 表。
* 记录某学校某模块是否开通短信。
*/
@NoArgsConstructor
@Data
@Entity
@Table(name = "sms_school_config")
@EqualsAndHashCode(onlyExplicitlyIncluded = true, callSuper = false)
public class SmsSchoolConfig extends BaseEntity {
/** 学校ID */
@Column(name = "school_id", nullable = false)
private Integer schoolId;
/** 学校名称 */
@Column(name = "school_name", length = 200)
private String schoolName;
/** 模块ID */
@Column(name = "module_id")
private Integer moduleId;
/** 是否开通短信 */
@Column(name = "is_sms")
private Boolean isSms = false;
}
@@ -0,0 +1,40 @@
package com.yunhai.campusnotice.entity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;
/**
* 系统字典(发文部门等)。对应原 .NET Common_DeptDic 表。
*/
@NoArgsConstructor
@Data
@Entity
@Table(name = "sys_dict")
@EqualsAndHashCode(onlyExplicitlyIncluded = true, callSuper = false)
public class SysDict extends BaseEntity {
/** 字典类型(如 "dept"=所属分类) */
@Column(name = "dict_type", length = 50)
private String dictType;
/** 字典 key(原 CodeID) */
@Column(name = "dict_key", length = 100)
private String dictKey;
/** 字典 value(显示名称,原 Name) */
@Column(name = "dict_value", length = 200)
private String dictValue;
/** 排序号 */
@Column(name = "sort_order")
private Integer sortOrder = 0;
/** 是否启用:0 禁用 / 1 启用(原 Enable) */
@Column(name = "enable_flag")
private Integer enableFlag = 1;
}
@@ -0,0 +1,28 @@
package com.yunhai.campusnotice.entity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;
/**
* 通知模板类型。对应原 .NET Notify_TemplateType 表。
*/
@NoArgsConstructor
@Data
@Entity
@Table(name = "template_type")
@EqualsAndHashCode(onlyExplicitlyIncluded = true, callSuper = false)
public class TemplateType extends BaseEntity {
/** 类型名称 */
@Column(name = "type_name", length = 100)
private String typeName;
/** 排序号 */
@Column(name = "sort_order")
private Integer sortOrder = 0;
}
@@ -0,0 +1,47 @@
package com.yunhai.campusnotice.entity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;
/**
* 附件文件记录。对应原 .NET Common_UpFiles 表。
* <p>
* 存储文件元信息(真实文件名、存储路径、大小、类型),物理文件存储在
* application.yml 的 file.upload-path 目录下。
*/
@NoArgsConstructor
@Data
@Entity
@Table(name = "up_file")
@EqualsAndHashCode(onlyExplicitlyIncluded = true, callSuper = false)
public class UpFile extends BaseEntity {
/** 应用类型(如 "notice"),用于区分不同业务的附件 */
@Column(name = "topic_type", length = 50)
private String topicType;
/** 关联主题ID(如通知 serid) */
@Column(name = "topic_id")
private Integer topicId;
/** 文件真实名称(用户上传时的原始文件名) */
@Column(name = "file_true_name", length = 255)
private String fileTrueName;
/** 文件存储路径(相对路径,如 notice/20260823/uuid.pdf) */
@Column(name = "file_name", length = 500)
private String fileName;
/** 文件大小(字节) */
@Column(name = "file_size")
private Integer fileSize;
/** 文件后缀名(如 pdf, docx, jpg) */
@Column(name = "file_type", length = 20)
private String fileType;
}