software copyright

This commit is contained in:
jiahong
2026-03-22 15:24:40 +08:00
parent e303bb868a
commit 60f336e345
155 changed files with 127262 additions and 0 deletions
@@ -0,0 +1,423 @@
/*
* 自然写教学资源管理与内容分发系统软件 V1.0
* model/Resource.java - 资源数据模型
* model/DotPattern.java - 点阵码模型
* model/AuditRecord.java - 审核记录模型
* config/OssConfig.java - OSS对象存储配置
* config/ElasticsearchConfig.java - ES配置
* security/ResourceSecurity.java - 资源安全(防盗链+水印)
*/
package com.writech.resource.model;
import java.util.*;
/**
* 资源数据模型(对应MySQL resource表)
*/
public class Resource {
/** 资源IDUUID */
private String id;
/** 资源名称 */
private String name;
/** 资源描述 */
private String description;
/** 资源类型(COURSEWARE/COPYBOOK/EXAM_PAPER/TEMPLATE/DOT_CODE/VIDEO */
private String type;
/** 学科 */
private String subject;
/** 适用年级 */
private String grade;
/** 出版社 */
private String publisher;
/** 版本号 */
private String version;
/** 审核状态(PENDING/APPROVED/REJECTED/WITHDRAWN */
private String auditStatus;
/** OSS文件存储Key */
private String fileKey;
/** 文件大小(字节) */
private long fileSize;
/** MIME类型 */
private String mimeType;
/** 缩略图URL */
private String thumbnailUrl;
/** 上传者ID */
private String uploaderId;
/** 上传者姓名 */
private String uploaderName;
/** 所属学校ID */
private String schoolId;
/** 标签(逗号分隔) */
private String tags;
/** 下载次数 */
private int downloadCount;
/** 使用次数 */
private int useCount;
/** 创建时间 */
private Date createdAt;
/** 更新时间 */
private Date updatedAt;
/** 是否已删除(软删除标记) */
private boolean deleted;
// ============================================================
// Getter / Setter
// ============================================================
public String getId() { return id; }
public void setId(String id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getDescription() { return description; }
public void setDescription(String description) { this.description = description; }
public String getType() { return type; }
public void setType(String type) { this.type = type; }
public String getSubject() { return subject; }
public void setSubject(String subject) { this.subject = subject; }
public String getGrade() { return grade; }
public void setGrade(String grade) { this.grade = grade; }
public String getPublisher() { return publisher; }
public void setPublisher(String publisher) { this.publisher = publisher; }
public String getVersion() { return version; }
public void setVersion(String version) { this.version = version; }
public String getAuditStatus() { return auditStatus; }
public void setAuditStatus(String auditStatus) { this.auditStatus = auditStatus; }
public String getFileKey() { return fileKey; }
public void setFileKey(String fileKey) { this.fileKey = fileKey; }
public long getFileSize() { return fileSize; }
public void setFileSize(long fileSize) { this.fileSize = fileSize; }
public String getMimeType() { return mimeType; }
public void setMimeType(String mimeType) { this.mimeType = mimeType; }
public String getThumbnailUrl() { return thumbnailUrl; }
public void setThumbnailUrl(String thumbnailUrl) { this.thumbnailUrl = thumbnailUrl; }
public String getUploaderId() { return uploaderId; }
public void setUploaderId(String uploaderId) { this.uploaderId = uploaderId; }
public String getSchoolId() { return schoolId; }
public void setSchoolId(String schoolId) { this.schoolId = schoolId; }
public String getTags() { return tags; }
public void setTags(String tags) { this.tags = tags; }
public int getDownloadCount() { return downloadCount; }
public int getUseCount() { return useCount; }
public Date getCreatedAt() { return createdAt; }
public Date getUpdatedAt() { return updatedAt; }
public boolean isDeleted() { return deleted; }
public void setDeleted(boolean deleted) { this.deleted = deleted; }
@Override
public String toString() {
return "Resource{id='" + id + "', name='" + name + "', type='" + type +
"', subject='" + subject + "', grade='" + grade + "'}";
}
}
/**
* 点阵码模型(对应MySQL dot_pattern表 + OSS文件)
*/
class DotPattern {
/** 点阵码ID(全局唯一) */
private long dotCodeId;
/** 关联的资源ID */
private String resourceId;
/** 页面序号 */
private int pageIndex;
/** 区域类型 */
private String areaType;
/** 区域坐标和尺寸(mm */
private double areaX;
private double areaY;
private double areaWidth;
private double areaHeight;
/** 点阵码图案文件OSS Key */
private String patternFileKey;
/** 生成参数JSON */
private String generateParams;
/** 状态(ACTIVE/REVOKED */
private String status;
/** 创建时间 */
private Date createdAt;
public long getDotCodeId() { return dotCodeId; }
public void setDotCodeId(long id) { this.dotCodeId = id; }
public String getResourceId() { return resourceId; }
public void setResourceId(String rid) { this.resourceId = rid; }
public int getPageIndex() { return pageIndex; }
public void setPageIndex(int idx) { this.pageIndex = idx; }
public String getAreaType() { return areaType; }
public void setAreaType(String type) { this.areaType = type; }
public double getAreaX() { return areaX; }
public double getAreaY() { return areaY; }
public double getAreaWidth() { return areaWidth; }
public double getAreaHeight() { return areaHeight; }
public String getPatternFileKey() { return patternFileKey; }
public String getStatus() { return status; }
public void setStatus(String status) { this.status = status; }
public Date getCreatedAt() { return createdAt; }
}
/**
* 审核记录模型(对应MySQL audit_record表)
*/
class AuditRecord {
/** 记录ID */
private String id;
/** 关联的资源ID */
private String resourceId;
/** 审核人ID */
private String auditorId;
/** 审核人姓名 */
private String auditorName;
/** 审核操作(APPROVE/REJECT/RETURN/WITHDRAW */
private String action;
/** 审核意见 */
private String comment;
/** 审核前状态 */
private String preStatus;
/** 审核后状态 */
private String postStatus;
/** 审核时间 */
private Date createdAt;
public String getId() { return id; }
public void setId(String id) { this.id = id; }
public String getResourceId() { return resourceId; }
public void setResourceId(String rid) { this.resourceId = rid; }
public String getAuditorId() { return auditorId; }
public void setAuditorId(String aid) { this.auditorId = aid; }
public String getAction() { return action; }
public void setAction(String action) { this.action = action; }
public String getComment() { return comment; }
public void setComment(String comment) { this.comment = comment; }
public String getPreStatus() { return preStatus; }
public String getPostStatus() { return postStatus; }
public Date getCreatedAt() { return createdAt; }
}
/**
* OSS对象存储配置
*
* 多副本冗余存储(99.99%数据持久性),
* 支持STS临时凭证直传,生命周期管理。
*/
class OssConfig {
/** OSS区域端点 */
private String endpoint;
/** 存储桶名称 */
private String bucketName;
/** AccessKey ID */
private String accessKeyId;
/** AccessKey Secret(加密存储) */
private String accessKeySecret;
/** STS角色ARN(用于前端直传临时授权) */
private String stsRoleArn;
/** STS会话名称 */
private String stsSessionName;
/** 资源前缀路径 */
private String resourcePrefix;
/** 缩略图前缀路径 */
private String thumbnailPrefix;
/** 临时文件过期天数 */
private int tempFileExpireDays;
public OssConfig() {
this.endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
this.bucketName = "writech-resources";
this.resourcePrefix = "resources/";
this.thumbnailPrefix = "thumbnails/";
this.tempFileExpireDays = 7;
this.stsSessionName = "writech-upload-session";
}
public String getEndpoint() { return endpoint; }
public void setEndpoint(String ep) { this.endpoint = ep; }
public String getBucketName() { return bucketName; }
public void setBucketName(String name) { this.bucketName = name; }
public String getAccessKeyId() { return accessKeyId; }
public void setAccessKeyId(String id) { this.accessKeyId = id; }
public String getAccessKeySecret() { return accessKeySecret; }
public void setAccessKeySecret(String secret) { this.accessKeySecret = secret; }
public String getStsRoleArn() { return stsRoleArn; }
public void setStsRoleArn(String arn) { this.stsRoleArn = arn; }
public String getResourcePrefix() { return resourcePrefix; }
public String getThumbnailPrefix() { return thumbnailPrefix; }
public int getTempFileExpireDays() { return tempFileExpireDays; }
}
/**
* Elasticsearch配置
*
* ES集群部署,索引按学科/年级分片,
* 支持IK中文分词器。
*/
class ElasticsearchConfig {
/** ES集群节点列表 */
private List<String> nodes;
/** 连接超时(毫秒) */
private int connectTimeout;
/** 读取超时(毫秒) */
private int socketTimeout;
/** 索引名称 */
private String indexName;
/** 分片数 */
private int shards;
/** 副本数 */
private int replicas;
/** 用户名(X-Pack安全) */
private String username;
/** 密码 */
private String password;
public ElasticsearchConfig() {
this.nodes = Arrays.asList("localhost:9200");
this.connectTimeout = 5000;
this.socketTimeout = 30000;
this.indexName = "writech_resources";
this.shards = 3;
this.replicas = 1;
}
public List<String> getNodes() { return nodes; }
public void setNodes(List<String> nodes) { this.nodes = nodes; }
public int getConnectTimeout() { return connectTimeout; }
public int getSocketTimeout() { return socketTimeout; }
public String getIndexName() { return indexName; }
public int getShards() { return shards; }
public int getReplicas() { return replicas; }
public String getUsername() { return username; }
public void setUsername(String u) { this.username = u; }
public String getPassword() { return password; }
public void setPassword(String p) { this.password = p; }
}
/**
* 资源安全服务
*
* 负责:
* - 防盗链(Referer校验 + 签名URL
* - 数字水印(PDF/图片添加学校教师标识水印)
* - 权限控制(按学校/区域授权)
* - 点阵码安全(全局唯一分配防冲突)
*/
class ResourceSecurity {
/** 防盗链Referer白名单 */
private static final Set<String> REFERER_WHITELIST = new HashSet<>(Arrays.asList(
"*.writech.com",
"localhost"
));
/**
* 校验资源访问权限
*
* 规则:
* - 管理员:可访问本校所有资源
* - 教师:可访问本校已授权资源
* - 学生/家长:仅可访问已分配的资源
*/
public boolean checkPermission(
String userId,
String userRole,
String userSchoolId,
String resourceSchoolId
) {
// 超级管理员无限制
if ("super_admin".equals(userRole)) {
return true;
}
// 校级管理员和教师:必须同校
if ("admin".equals(userRole) || "teacher".equals(userRole)) {
return userSchoolId != null && userSchoolId.equals(resourceSchoolId);
}
// 学生/家长:需要额外的资源分配记录校验
// return resourceAssignmentMapper.isAssigned(userId, resourceId);
return false;
}
/**
* 验证Referer防盗链
*/
public boolean validateReferer(String referer) {
if (referer == null || referer.isEmpty()) {
return false;
}
for (String pattern : REFERER_WHITELIST) {
if (pattern.startsWith("*.")) {
String domain = pattern.substring(2);
if (referer.contains(domain)) return true;
} else {
if (referer.contains(pattern)) return true;
}
}
return false;
}
/**
* 生成水印文本
* 格式:学校名称 + 教师姓名 + 日期
*/
public String generateWatermarkText(
String schoolName, String teacherName
) {
String dateStr = new java.text.SimpleDateFormat("yyyy-MM-dd")
.format(new Date());
return String.format("%s %s %s", schoolName, teacherName, dateStr);
}
}