init local code

This commit is contained in:
chenxing
2026-09-07 09:09:39 +08:00
commit 99cd26b3d2
259 changed files with 20554 additions and 0 deletions
@@ -0,0 +1,43 @@
package com.yunhai.cms.entity;
import com.yunhai.cms.common.CmsAuditListener;
import lombok.Getter;
import lombok.Setter;
import javax.persistence.Column;
import javax.persistence.EntityListeners;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* 所有实体的公共基类:自增主键 + 创建人/时间 + 更新人/时间(由 CmsAuditListener 自动填充)。
* 操作日志独立表为演进项(方案 §2),MVP 靠本审计四字段追溯。
*/
@MappedSuperclass
@Getter
@Setter
@EntityListeners(CmsAuditListener.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,84 @@
package com.yunhai.cms.entity;
import lombok.Getter;
import lombok.Setter;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Index;
import javax.persistence.Table;
import java.time.LocalDateTime;
/**
* CMS 文章(方案 §5.1 表3)。
* 审核状态机为演进项(触发后加 audit_status 列);ext_json 保留键:
* {@code wechat}(推送回执,本期不写)、{@code albums}(图集演进)。
*/
@Getter
@Setter
@Entity
@Table(name = "cms_article", indexes = {
@Index(name = "idx_art_list", columnList = "site_id, category_id, status, publish_time"),
@Index(name = "idx_art_site_top", columnList = "site_id, status, topmost")})
public class CmsArticle extends BaseEntity {
/** 所属站点(隔离/查询维度;文章不冗余 sch_id,权限经 site 一跳映射) */
@Column(name = "site_id", nullable = false)
private Integer siteId;
/** 所属栏目(逻辑外键 → cms_category.id) */
@Column(name = "category_id", nullable = false)
private Integer categoryId;
/** 标题 */
@Column(name = "title", nullable = false, length = 200)
private String title;
/** 摘要(列表/SEO 用,空=截取正文) */
@Column(name = "summary", length = 500)
private String summary;
/** 正文 HTML(wangEditor 产出,保存时 jsoup 白名单清洗,方案 §8.5) */
@Column(name = "content", columnDefinition = "LONGTEXT")
private String content;
/** 封面图 URL */
@Column(name = "cover_image", length = 500)
private String coverImage;
/** 作者账号(发布时从 BoaUser 填充) */
@Column(name = "author_account", length = 64)
private String authorAccount;
/** 作者姓名(冗余展示) */
@Column(name = "author_name", length = 64)
private String authorName;
/** 来源(转载出处) */
@Column(name = "source", length = 128)
private String source;
/** 状态:0=草稿 1=已发布 2=已下架(见 ArticleStatusEnum) */
@Column(name = "status", nullable = false)
private Integer status = 0;
/** 置顶:0/1 */
@Column(name = "topmost", nullable = false)
private Integer topmost = 0;
/** 发布时间(空=保存即发布;未来=定时发布) */
@Column(name = "publish_time")
private LocalDateTime publishTime;
/** 下架时间(可选,@Scheduled 每分钟扫描到期记录) */
@Column(name = "offline_time")
private LocalDateTime offlineTime;
/** 浏览量(MVP 异步累加,量大后改缓存聚合) */
@Column(name = "view_count", nullable = false)
private Integer viewCount = 0;
/** 扩展字段 JSON(wechat/albums 预留,免 DDL 演进) */
@Column(name = "ext_json", columnDefinition = "JSON")
private String extJson;
}
@@ -0,0 +1,50 @@
package com.yunhai.cms.entity;
import lombok.Getter;
import lombok.Setter;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Index;
import javax.persistence.Table;
/**
* CMS 附件(正文图片 + 文档附件 + 轮播图/友链 Logo 复用同一上传链路,方案 §7.3)。
* 文章删除时附件记录保留、article_id 置空成"孤儿",由附件管理页清理。
*/
@Getter
@Setter
@Entity
@Table(name = "cms_attachment", indexes = {
@Index(name = "idx_att_article", columnList = "article_id"),
@Index(name = "idx_att_site", columnList = "site_id")})
public class CmsAttachment extends BaseEntity {
/** 所属站点 */
@Column(name = "site_id", nullable = false)
private Integer siteId;
/** 关联文章(编辑器图片保存时回填) */
@Column(name = "article_id")
private Integer articleId;
/** 原始文件名 */
@Column(name = "file_name", nullable = false, length = 255)
private String fileName;
/** 存储路径(相对 FILE_PATH) */
@Column(name = "file_path", nullable = false, length = 500)
private String filePath;
/** Web 访问 URL */
@Column(name = "web_url", nullable = false, length = 500)
private String webUrl;
/** 字节数 */
@Column(name = "file_size")
private Long fileSize;
/** MIME 类型 */
@Column(name = "mime_type", length = 128)
private String mimeType;
}
@@ -0,0 +1,62 @@
package com.yunhai.cms.entity;
import lombok.Getter;
import lombok.Setter;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Index;
import javax.persistence.Table;
import java.time.LocalDateTime;
/**
* CMS 轮播/推荐位(首页 banner、图片新闻位等,方案 §5.1 表5)。
* 定时上下线靠门户渲染时过滤 start/end(无需调度任务改状态)。
* 广告投放统计不做(方案 §2)。
*/
@Getter
@Setter
@Entity
@Table(name = "cms_banner", indexes = @Index(name = "idx_banner", columnList = "site_id, position, status, sort_no"))
public class CmsBanner extends BaseEntity {
/** 所属站点 */
@Column(name = "site_id", nullable = false)
private Integer siteId;
/** 展示位标识(home=首页轮播;皮肤包约定其他位) */
@Column(name = "position", nullable = false, length = 32)
private String position = "home";
/** 标题(alt 文案/无图兜底) */
@Column(name = "title", nullable = false, length = 200)
private String title;
/** 图片 URL(上传至 FILE_PATH) */
@Column(name = "image_url", nullable = false, length = 500)
private String imageUrl;
/** 跳转类型:1=文章 2=栏目 3=外链(见 LinkTypeEnum) */
@Column(name = "link_type", nullable = false)
private Integer linkType = 1;
/** 跳转目标(文章ID/栏目ID/URL,按 link_type 解释) */
@Column(name = "link_value", length = 500)
private String linkValue;
/** 同级排序(升序) */
@Column(name = "sort_no", nullable = false)
private Integer sortNo = 0;
/** 上线时间(空=立即;未来=定时上线) */
@Column(name = "start_time")
private LocalDateTime startTime;
/** 下线时间(可选,门户渲染时过滤) */
@Column(name = "end_time")
private LocalDateTime endTime;
/** 状态:0=停用 1=启用 */
@Column(name = "status", nullable = false)
private Integer status = 1;
}
@@ -0,0 +1,67 @@
package com.yunhai.cms.entity;
import lombok.Getter;
import lombok.Setter;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Index;
import javax.persistence.Table;
/**
* CMS 栏目(站点内树形,方案 §5.1 表2)。
* 旧 CMS3.0 的"频道"层收敛为本表 type(列表/单页/外链),覆盖原频道全部用法。
*/
@Getter
@Setter
@Entity
@Table(name = "cms_category", indexes = @Index(name = "idx_cat_tree", columnList = "site_id, parent_id, sort_no"))
public class CmsCategory extends BaseEntity {
/** 所属站点(逻辑外键 → cms_site.id) */
@Column(name = "site_id", nullable = false)
private Integer siteId;
/** 父栏目ID(0=根) */
@Column(name = "parent_id", nullable = false)
private Integer parentId = 0;
/** 栏目名称 */
@Column(name = "name", nullable = false, length = 64)
private String name;
/** 栏目类型:1=文章列表 2=单页 3=外链(见 CategoryTypeEnum) */
@Column(name = "type", nullable = false)
private Integer type = 1;
/** 外链地址(type=3 必填) */
@Column(name = "link_url", length = 500)
private String linkUrl;
/** 栏目模板覆盖(空=按 type 取默认,预留能力,方案 §8.2) */
@Column(name = "template", length = 64)
private String template;
/**
* 单页栏目内容(type=2 时门户直接渲染;经 jsoup 白名单清洗入库)。
* 注:方案 §8.1 要求单页直接渲染 content,但 §5.1 DDL 漏列,此处补齐(ddl-auto=update 自动加列)。
*/
@Column(name = "content", columnDefinition = "LONGTEXT")
private String content;
/** 同级排序(升序) */
@Column(name = "sort_no", nullable = false)
private Integer sortNo = 0;
/** SEO 标题(空=用栏目名) */
@Column(name = "seo_title", length = 200)
private String seoTitle;
/** SEO 描述 */
@Column(name = "seo_description", length = 500)
private String seoDescription;
/** 状态:0=隐藏 1=显示 */
@Column(name = "status", nullable = false)
private Integer status = 1;
}
@@ -0,0 +1,48 @@
package com.yunhai.cms.entity;
import lombok.Getter;
import lombok.Setter;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Index;
import javax.persistence.Table;
/**
* CMS 友情链接(页脚/首页分组成员,方案 §5.1 表6)。
* 分组即旧 linkCategory:上级部门/兄弟院校/合作单位…,group_name 字符串直接分组。
*/
@Getter
@Setter
@Entity
@Table(name = "cms_link", indexes = @Index(name = "idx_link", columnList = "site_id, group_name, sort_no"))
public class CmsLink extends BaseEntity {
/** 所属站点 */
@Column(name = "site_id", nullable = false)
private Integer siteId;
/** 分组(上级部门/兄弟院校/合作单位…) */
@Column(name = "group_name", nullable = false, length = 64)
private String groupName = "default";
/** 链接名称 */
@Column(name = "name", nullable = false, length = 128)
private String name;
/** Logo URL(可选,文字链可空) */
@Column(name = "logo_url", length = 500)
private String logoUrl;
/** 链接地址 */
@Column(name = "link_url", nullable = false, length = 500)
private String linkUrl;
/** 组内排序(升序) */
@Column(name = "sort_no", nullable = false)
private Integer sortNo = 0;
/** 状态:0=隐藏 1=显示 */
@Column(name = "status", nullable = false)
private Integer status = 1;
}
@@ -0,0 +1,62 @@
package com.yunhai.cms.entity;
import lombok.Getter;
import lombok.Setter;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Index;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
/**
* CMS 站点(多租户根,方案 §5.1 表1)。
*
* <p>站点层级(《院系子站方案》):{@code parent_site_id}=0 为顶层校站点(一校一主站),
* &gt;0 为该院系子站(挂主站 id,层级固定两层)。
*
* <p>config_json 保留键(方案 §8.6):{@code domain}(学校绑定域名台账)、
* {@code public_base_url}(对外基地址,默认派生自 base 域,绑学校域名后覆盖)、
* {@code colleges_label}(门户"专业院系"下拉文案,默认"专业院系")、
* {@code wechat}(公众号配置节点,本期不写,见微信平台对接方案)。
*/
@Getter
@Setter
@Entity
@Table(name = "cms_site",
uniqueConstraints = @UniqueConstraint(name = "uk_site_code", columnNames = "code"),
indexes = @Index(name = "idx_site_sch", columnList = "sch_id"))
public class CmsSite extends BaseEntity {
/** 站点编码,URL 路径用(/portal/{code}) */
@Column(name = "code", nullable = false, length = 64)
private String code;
/** 上级站点ID(0=顶层校站点;院系子站挂主站 id,层级固定两层) */
@Column(name = "parent_site_id", nullable = false)
private Integer parentSiteId = 0;
/** 学校ID(逻辑外键 → UserBase sys_group.id) */
@Column(name = "sch_id")
private Integer schId;
/** 学校名称(冗余展示) */
@Column(name = "sch_name", length = 128)
private String schName;
/** 站点名称 */
@Column(name = "name", nullable = false, length = 128)
private String name;
/** 皮肤包名(classpath:/templates/themes/{theme}/) */
@Column(name = "theme", length = 64)
private String theme = "default";
/** 站点配置 JSON(logo/联系方式/页脚/domain/public_base_url) */
@Column(name = "config_json", columnDefinition = "JSON")
private String configJson;
/** 状态:0=停用 1=启用 */
@Column(name = "status", nullable = false)
private Integer status = 1;
}