480 lines
12 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using MilliSim.Common.Models;
namespace MilliSim.Common.Entities;
/// <summary>
/// 实体基类
/// </summary>
public abstract class BaseEntity
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public long Id { get; set; }
public DateTime CreatedAt { get; set; } = DateTime.Now;
public DateTime UpdatedAt { get; set; } = DateTime.Now;
public bool IsDeleted { get; set; } = false;
}
/// <summary>
/// 用户表(员工 + 客户)
/// </summary>
public class User : BaseEntity
{
[Required, StringLength(50)]
public string Username { get; set; } = string.Empty;
[Required, StringLength(255)]
public string Password { get; set; } = string.Empty;
[StringLength(50)]
public string Nickname { get; set; } = string.Empty;
[StringLength(500)]
public string Avatar { get; set; } = string.Empty;
[StringLength(20)]
public string Phone { get; set; } = string.Empty;
[StringLength(100)]
public string Email { get; set; } = string.Empty;
public UserRole Role { get; set; } = UserRole.Customer;
public UserStatus Status { get; set; } = UserStatus.Active;
/// <summary>
/// 创建人 ID销售创建客户时记录
/// </summary>
public long? CreatedBy { get; set; }
[NotMapped]
public string RoleName => Role.ToString();
}
/// <summary>
/// 项目表
/// </summary>
public class Project : BaseEntity
{
[Required, StringLength(100)]
public string Name { get; set; } = string.Empty;
public long CategoryId { get; set; }
[StringLength(500)]
public string CoverImage { get; set; } = string.Empty;
[StringLength(500)]
public string VideoUrl { get; set; } = string.Empty;
/// <summary>
/// 视频封面(已废弃,保留字段避免数据库迁移问题)
/// </summary>
[StringLength(500)]
public string VideoCover { get; set; } = string.Empty;
[StringLength(1000)]
public string Description { get; set; } = string.Empty;
public string Content { get; set; } = string.Empty;
/// <summary>
/// 平台标签(逗号分隔)
/// </summary>
[StringLength(200)]
public string Platforms { get; set; } = string.Empty;
public ProjectStatus Status { get; set; } = ProjectStatus.Offline;
/// <summary>
/// 是否推荐(已废弃,保留字段避免数据库迁移问题)
/// </summary>
public bool IsFeatured { get; set; } = false;
/// <summary>
/// 排序值(已废弃,保留字段避免数据库迁移问题)
/// </summary>
public int SortOrder { get; set; } = 0;
public int ViewCount { get; set; } = 0;
public int ExperienceCount { get; set; } = 0;
public int FavoriteCount { get; set; } = 0;
public DateTime? PublishedAt { get; set; }
[ForeignKey(nameof(CategoryId))]
public ProjectCategory? Category { get; set; }
}
/// <summary>
/// 项目分类表
/// </summary>
public class ProjectCategory : BaseEntity
{
[Required, StringLength(50)]
public string Name { get; set; } = string.Empty;
[StringLength(500)]
public string Icon { get; set; } = string.Empty;
public int SortOrder { get; set; } = 0;
public UserStatus Status { get; set; } = UserStatus.Active;
}
/// <summary>
/// 平台类型表
/// </summary>
public class PlatformType : BaseEntity
{
[Required, StringLength(50)]
public string Name { get; set; } = string.Empty;
[StringLength(500)]
public string Icon { get; set; } = string.Empty;
public int SortOrder { get; set; } = 0;
public UserStatus Status { get; set; } = UserStatus.Active;
}
/// <summary>
/// 特性标签表
/// </summary>
public class FeatureTag : BaseEntity
{
[Required, StringLength(50)]
public string Name { get; set; } = string.Empty;
[StringLength(500)]
public string Icon { get; set; } = string.Empty;
public int SortOrder { get; set; } = 0;
public UserStatus Status { get; set; } = UserStatus.Active;
}
/// <summary>
/// 项目标签关联表
/// </summary>
public class ProjectTagRelation : BaseEntity
{
public long ProjectId { get; set; }
public long TagId { get; set; }
[ForeignKey(nameof(ProjectId))]
public Project? Project { get; set; }
[ForeignKey(nameof(TagId))]
public FeatureTag? Tag { get; set; }
}
/// <summary>
/// 项目截图表(已废弃,保留表避免数据库迁移问题,不再使用)
/// </summary>
public class ProjectScreenshot : BaseEntity
{
public long ProjectId { get; set; }
[StringLength(500)]
public string Url { get; set; } = string.Empty;
public int SortOrder { get; set; } = 0;
[ForeignKey(nameof(ProjectId))]
public Project? Project { get; set; }
}
/// <summary>
/// 项目资源包表
/// </summary>
public class ProjectPackage : BaseEntity
{
public long ProjectId { get; set; }
public PackageType Type { get; set; }
/// <summary>
/// 原始文件名(上传时的文件名,非重命名后的对象键)
/// </summary>
[StringLength(255)]
public string FileName { get; set; } = string.Empty;
[StringLength(500)]
public string Url { get; set; } = string.Empty;
public long FileSize { get; set; }
/// <summary>
/// 唤醒协议前缀(固定为 millisimAndroid/PC 平台使用)
/// </summary>
[StringLength(50)]
public string WakeProtocolPrefix { get; set; } = string.Empty;
/// <summary>
/// 唤醒协议参数Android/PC 平台使用,用户输入)
/// </summary>
[StringLength(500)]
public string WakeProtocolParam { get; set; } = string.Empty;
/// <summary>
/// WebGL 解压后的根路径对象键(仅 WebGL 类型使用,用于在线运行)
/// </summary>
[StringLength(500)]
public string ExtractedPath { get; set; } = string.Empty;
[ForeignKey(nameof(ProjectId))]
public Project? Project { get; set; }
}
/// <summary>
/// 收藏表
/// </summary>
public class Favorite : BaseEntity
{
public long UserId { get; set; }
public long ProjectId { get; set; }
[ForeignKey(nameof(UserId))]
public User? User { get; set; }
[ForeignKey(nameof(ProjectId))]
public Project? Project { get; set; }
}
/// <summary>
/// 体验记录表
/// </summary>
public class ExperienceLog : BaseEntity
{
public long UserId { get; set; }
public long ProjectId { get; set; }
public int DurationSeconds { get; set; }
[ForeignKey(nameof(UserId))]
public User? User { get; set; }
[ForeignKey(nameof(ProjectId))]
public Project? Project { get; set; }
}
/// <summary>
/// 授权记录表(客户级授权,授权后可运行所有项目)
/// </summary>
public class Authorization : BaseEntity
{
public long UserId { get; set; }
/// <summary>
/// 项目 ID已废弃改为客户级授权保留字段避免数据库迁移问题
/// </summary>
public long? ProjectId { get; set; }
public long AuthorizedBy { get; set; }
public DateTime StartTime { get; set; } = DateTime.Now;
public DateTime EndTime { get; set; }
public AuthorizationStatus Status { get; set; } = AuthorizationStatus.Active;
[ForeignKey(nameof(UserId))]
public User? User { get; set; }
}
/// <summary>
/// 轮播图表
/// </summary>
public class Banner : BaseEntity
{
[StringLength(100)]
public string Title { get; set; } = string.Empty;
[Required, StringLength(500)]
public string Image { get; set; } = string.Empty;
[StringLength(500)]
public string Link { get; set; } = string.Empty;
public int SortOrder { get; set; } = 0;
public UserStatus Status { get; set; } = UserStatus.Active;
}
/// <summary>
/// 合作伙伴表
/// </summary>
public class Partner : BaseEntity
{
[Required, StringLength(100)]
public string Name { get; set; } = string.Empty;
[Required, StringLength(500)]
public string Logo { get; set; } = string.Empty;
[StringLength(500)]
public string Link { get; set; } = string.Empty;
public int SortOrder { get; set; } = 0;
public bool IsVisible { get; set; } = true;
}
/// <summary>
/// 咨询消息表
/// </summary>
public class Consultation : BaseEntity
{
[Required, StringLength(50)]
public string Name { get; set; } = string.Empty;
[Required, StringLength(20)]
public string Contact { get; set; } = string.Empty;
[StringLength(1000)]
public string Content { get; set; } = string.Empty;
public bool IsRead { get; set; } = false;
}
/// <summary>
/// 通知表
/// </summary>
public class Notification : BaseEntity
{
public NotificationType Type { get; set; }
[Required, StringLength(200)]
public string Title { get; set; } = string.Empty;
[StringLength(1000)]
public string Content { get; set; } = string.Empty;
public long? UserId { get; set; }
/// <summary>
/// 业务事件 ID防重复
/// </summary>
[StringLength(100)]
public string? EventId { get; set; }
}
/// <summary>
/// 通知已读记录表
/// </summary>
public class NotificationRead : BaseEntity
{
public long UserId { get; set; }
public long NotificationId { get; set; }
[ForeignKey(nameof(NotificationId))]
public Notification? Notification { get; set; }
}
/// <summary>
/// 操作日志表
/// </summary>
public class OperationLog : BaseEntity
{
public long UserId { get; set; }
[StringLength(50)]
public string Username { get; set; } = string.Empty;
[StringLength(50)]
public string Module { get; set; } = string.Empty;
[StringLength(50)]
public string Operation { get; set; } = string.Empty;
[StringLength(1000)]
public string Detail { get; set; } = string.Empty;
[StringLength(50)]
public string Ip { get; set; } = string.Empty;
}
/// <summary>
/// 系统设置表
/// </summary>
public class SystemSetting : BaseEntity
{
[Required, StringLength(100)]
public string Key { get; set; } = string.Empty;
[Column(TypeName = "longtext")]
public string Value { get; set; } = string.Empty;
[StringLength(200)]
public string Description { get; set; } = string.Empty;
}
/// <summary>
/// 备份记录表
/// </summary>
public class Backup : BaseEntity
{
[Required, StringLength(200)]
public string FileName { get; set; } = string.Empty;
public long FileSize { get; set; }
[StringLength(20)]
public string Type { get; set; } = "Manual";
[StringLength(500)]
public string Url { get; set; } = string.Empty;
}
/// <summary>
/// 唤醒协议配置表
/// </summary>
public class WakeProtocol : BaseEntity
{
[Required, StringLength(50)]
public string TerminalType { get; set; } = string.Empty;
[Required, StringLength(200)]
public string ProtocolPrefix { get; set; } = string.Empty;
[Column(TypeName = "text")]
public string ParamTemplate { get; set; } = string.Empty;
public UserStatus Status { get; set; } = UserStatus.Active;
}
/// <summary>
/// 待消费上传文件记录(用于垃圾资源清理跟踪)
/// </summary>
public class PendingUpload : BaseEntity
{
/// <summary>COS 对象键或本地访问 URL</summary>
[Required, StringLength(500)]
public string ObjectKey { get; set; } = string.Empty;
/// <summary>上传目录icons/videos/logos/packages 等)</summary>
[StringLength(50)]
public string Folder { get; set; } = string.Empty;
/// <summary>上传者用户 ID</summary>
public long? UploadedBy { get; set; }
/// <summary>上传时间</summary>
public DateTime UploadedAt { get; set; } = DateTime.Now;
/// <summary>消费时间null=待消费非null=已保存到实体)</summary>
public DateTime? ConsumedAt { get; set; }
}