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,249 @@
/**
* 自然写互动课堂教学管理云平台软件 V1.0
*
* 数据模型 - 设备实体 / 作业实体 / 笔迹数据实体
* 设备表(device)MySQL
* 作业表(assignment)MySQL
* 笔迹数据(stroke_data)MongoDB
*/
package com.writech.cloud.model;
import javax.persistence.*;
import java.time.LocalDateTime;
import java.util.*;
// ==================== 设备实体 ====================
/**
* 设备注册表实体(MySQL
* 管理点阵笔、网关、终端设备、算力盒
*/
@Entity
@Table(name = "device", indexes = {
@Index(name = "idx_mac", columnList = "macAddr", unique = true),
@Index(name = "idx_school_type", columnList = "schoolId, type"),
@Index(name = "idx_classroom", columnList = "classroomId")
})
class Device {
@Id
@Column(length = 32)
private String id;
/** 设备类型:pen/gateway/terminal/edge_box */
@Column(nullable = false, length = 16)
private String type;
/** 设备MAC地址(全局唯一) */
@Column(nullable = false, length = 17, unique = true)
private String macAddr;
/** 设备序列号 */
@Column(length = 32)
private String serialNumber;
/** 固件版本号 */
@Column(length = 16)
private String firmwareVersion;
/** 绑定用户ID */
@Column(length = 32)
private String bindUserId;
/** 所属学校ID */
@Column(length = 32)
private String schoolId;
/** 所属教室ID */
@Column(length = 32)
private String classroomId;
/** 设备状态:1=在线, 0=离线, -1=故障 */
@Column(nullable = false)
private int status = 0;
/** 电池电量百分比(0-100,仅笔设备) */
private Integer batteryLevel;
/** 当前连接的笔数量(仅网关设备) */
private Integer connectedPenCount;
/** CPU使用率(仅网关/算力盒) */
private Double cpuUsage;
/** 内存使用率(仅网关/算力盒) */
private Double memoryUsage;
/** 注册时间 */
@Column(nullable = false)
private LocalDateTime registerTime;
/** 最后心跳时间 */
private LocalDateTime lastHeartbeat;
// Getter/Setter
public String getId() { return id; }
public void setId(String id) { this.id = id; }
public String getType() { return type; }
public void setType(String type) { this.type = type; }
public String getMacAddr() { return macAddr; }
public void setMacAddr(String macAddr) { this.macAddr = macAddr; }
public String getSerialNumber() { return serialNumber; }
public void setSerialNumber(String sn) { this.serialNumber = sn; }
public String getFirmwareVersion() { return firmwareVersion; }
public void setFirmwareVersion(String v) { this.firmwareVersion = v; }
public String getBindUserId() { return bindUserId; }
public void setBindUserId(String id) { this.bindUserId = id; }
public String getSchoolId() { return schoolId; }
public void setSchoolId(String id) { this.schoolId = id; }
public String getClassroomId() { return classroomId; }
public void setClassroomId(String id) { this.classroomId = id; }
public int getStatus() { return status; }
public void setStatus(int s) { this.status = s; }
public Integer getBatteryLevel() { return batteryLevel; }
public void setBatteryLevel(Integer l) { this.batteryLevel = l; }
public Integer getConnectedPenCount() { return connectedPenCount; }
public void setConnectedPenCount(Integer c) { this.connectedPenCount = c; }
public Double getCpuUsage() { return cpuUsage; }
public void setCpuUsage(Double u) { this.cpuUsage = u; }
public Double getMemoryUsage() { return memoryUsage; }
public void setMemoryUsage(Double u) { this.memoryUsage = u; }
public LocalDateTime getRegisterTime() { return registerTime; }
public void setRegisterTime(LocalDateTime t) { this.registerTime = t; }
public LocalDateTime getLastHeartbeat() { return lastHeartbeat; }
public void setLastHeartbeat(LocalDateTime t) { this.lastHeartbeat = t; }
}
// ==================== 作业实体 ====================
/**
* 作业/试卷发布表实体(MySQL)
*/
@Entity
@Table(name = "assignment", indexes = {
@Index(name = "idx_class_status", columnList = "classId, status"),
@Index(name = "idx_teacher", columnList = "teacherId")
})
class Assignment {
@Id
@Column(length = 32)
private String id;
/** 发布教师ID */
@Column(nullable = false, length = 32)
private String teacherId;
/** 班级ID */
@Column(nullable = false, length = 32)
private String classId;
/** 作业标题 */
@Column(nullable = false, length = 128)
private String title;
/** 类型:homework(作业)/exam(考试)/practice(练习) */
@Column(nullable = false, length = 16)
private String type;
/** 学科 */
@Column(length = 32)
private String subject;
/** 截止时间 */
private LocalDateTime deadline;
/** 状态:draft/published/closed/graded */
@Column(nullable = false, length = 16)
private String status;
/** 发布时间 */
private LocalDateTime publishTime;
/** 满分值 */
private double totalScore;
/** 题目总数 */
private int questionCount;
/** 关联的点阵码页面ID列表(JSON数组) */
@Column(columnDefinition = "TEXT")
private String dotCodePagesJson;
@Transient
private List<String> dotCodePages;
// Getter/Setter
public String getId() { return id; }
public void setId(String id) { this.id = id; }
public String getTeacherId() { return teacherId; }
public void setTeacherId(String id) { this.teacherId = id; }
public String getClassId() { return classId; }
public void setClassId(String id) { this.classId = id; }
public String getTitle() { return title; }
public void setTitle(String t) { this.title = t; }
public String getType() { return type; }
public void setType(String t) { this.type = t; }
public String getSubject() { return subject; }
public void setSubject(String s) { this.subject = s; }
public LocalDateTime getDeadline() { return deadline; }
public void setDeadline(LocalDateTime d) { this.deadline = d; }
public String getStatus() { return status; }
public void setStatus(String s) { this.status = s; }
public LocalDateTime getPublishTime() { return publishTime; }
public void setPublishTime(LocalDateTime t) { this.publishTime = t; }
public double getTotalScore() { return totalScore; }
public void setTotalScore(double s) { this.totalScore = s; }
public int getQuestionCount() { return questionCount; }
public void setQuestionCount(int c) { this.questionCount = c; }
public List<String> getDotCodePages() { return dotCodePages; }
public void setDotCodePages(List<String> p) { this.dotCodePages = p; }
}
// ==================== 笔迹数据实体 ====================
/**
* 笔迹原始数据实体(MongoDB)
*
* JSON文档结构:
* {
* student_id: "...",
* assignment_id: "...",
* pen_id: "...",
* page_id: "...",
* strokes: [{x, y, pressure, timestamp, penUp}, ...],
* createTime: "...",
* processingStatus: "received/processing/completed/failed"
* }
*/
class StrokeData {
private String id;
private String studentId;
private String assignmentId;
private String penId;
private String pageId;
private List<Map<String, Object>> strokes;
private LocalDateTime createTime;
private LocalDateTime processedTime;
private String processingStatus; // received/processing/completed/failed
public String getId() { return id; }
public void setId(String id) { this.id = id; }
public String getStudentId() { return studentId; }
public void setStudentId(String id) { this.studentId = id; }
public String getAssignmentId() { return assignmentId; }
public void setAssignmentId(String id) { this.assignmentId = id; }
public String getPenId() { return penId; }
public void setPenId(String id) { this.penId = id; }
public String getPageId() { return pageId; }
public void setPageId(String id) { this.pageId = id; }
public List<Map<String, Object>> getStrokes() { return strokes; }
public void setStrokes(List<Map<String, Object>> s) { this.strokes = s; }
public LocalDateTime getCreateTime() { return createTime; }
public void setCreateTime(LocalDateTime t) { this.createTime = t; }
public LocalDateTime getProcessedTime() { return processedTime; }
public void setProcessedTime(LocalDateTime t) { this.processedTime = t; }
public String getProcessingStatus() { return processingStatus; }
public void setProcessingStatus(String s) { this.processingStatus = s; }
}
@@ -0,0 +1,139 @@
/**
* 自然写互动课堂教学管理云平台软件 V1.0
*
* 数据模型 - 用户实体
* 对应数据表:user (MySQL)
* 支持教师/学生/管理员/家长四种角色
*/
package com.writech.cloud.model;
import javax.persistence.*;
import java.time.LocalDateTime;
/**
* 用户主表实体类
*
* RBAC角色定义:
* - admin:系统管理员(学校/用户/设备管理全权限)
* - teacher:教师(班级管理/作业发布/学情查看)
* - student:学生(作业查看/学习数据查询)
* - parent:家长(子女学情查看/消息接收)
*
* 安全设计:
* - 手机号使用AES-256加密存储(encryptedPhone字段)
* - 密码使用BCrypt哈希存储
* - 身份证号等敏感信息加密后存储
*/
@Entity
@Table(name = "user", indexes = {
@Index(name = "idx_phone", columnList = "encryptedPhone"),
@Index(name = "idx_school_role", columnList = "schoolId, role"),
@Index(name = "idx_wechat", columnList = "wechatOpenId")
})
public class User {
/** 用户唯一IDUUID格式) */
@Id
@Column(length = 32)
private String id;
/** 用户姓名 */
@Column(nullable = false, length = 64)
private String name;
/** 手机号(明文,仅用于内部处理,不直接存储) */
@Transient
private String phone;
/** 加密后的手机号(AES-256-CBC加密存储) */
@Column(length = 128)
private String encryptedPhone;
/** 密码哈希(BCrypt,强度因子10) */
@Column(length = 128)
private String passwordHash;
/** 用户角色:admin/teacher/student/parent */
@Column(nullable = false, length = 16)
private String role;
/** 所属学校ID */
@Column(length = 32)
private String schoolId;
/** 所属学校名称(冗余存储,减少关联查询) */
@Column(length = 128)
private String schoolName;
/** 头像URL */
@Column(length = 256)
private String avatar;
/** 微信OpenID(第三方登录绑定) */
@Column(length = 64)
private String wechatOpenId;
/** 钉钉用户ID(第三方登录绑定) */
@Column(length = 64)
private String dingtalkUserId;
/** 账户状态:1=正常, 0=禁用, -1=注销 */
@Column(nullable = false)
private int status = 1;
/** Token版本号(用于使所有旧Token失效) */
@Column(nullable = false)
private int tokenVersion = 0;
/** 账户创建时间 */
@Column(nullable = false)
private LocalDateTime createTime;
/** 最后登录时间 */
private LocalDateTime lastLoginTime;
/** 最后登录IP */
@Column(length = 45)
private String lastLoginIp;
// ==================== 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 getPhone() { return phone; }
public void setPhone(String phone) { this.phone = phone; }
public String getEncryptedPhone() { return encryptedPhone; }
public void setEncryptedPhone(String encryptedPhone) { this.encryptedPhone = encryptedPhone; }
public String getPasswordHash() { return passwordHash; }
public void setPasswordHash(String passwordHash) { this.passwordHash = passwordHash; }
public String getRole() { return role; }
public void setRole(String role) { this.role = role; }
public String getSchoolId() { return schoolId; }
public void setSchoolId(String schoolId) { this.schoolId = schoolId; }
public String getSchoolName() { return schoolName; }
public void setSchoolName(String schoolName) { this.schoolName = schoolName; }
public String getAvatar() { return avatar; }
public void setAvatar(String avatar) { this.avatar = avatar; }
public String getWechatOpenId() { return wechatOpenId; }
public void setWechatOpenId(String wechatOpenId) { this.wechatOpenId = wechatOpenId; }
public String getDingtalkUserId() { return dingtalkUserId; }
public void setDingtalkUserId(String dingtalkUserId) { this.dingtalkUserId = dingtalkUserId; }
public int getStatus() { return status; }
public void setStatus(int status) { this.status = status; }
public int getTokenVersion() { return tokenVersion; }
public void setTokenVersion(int tokenVersion) { this.tokenVersion = tokenVersion; }
public LocalDateTime getCreateTime() { return createTime; }
public void setCreateTime(LocalDateTime createTime) { this.createTime = createTime; }
public LocalDateTime getLastLoginTime() { return lastLoginTime; }
public void setLastLoginTime(LocalDateTime lastLoginTime) { this.lastLoginTime = lastLoginTime; }
public String getLastLoginIp() { return lastLoginIp; }
public void setLastLoginIp(String lastLoginIp) { this.lastLoginIp = lastLoginIp; }
@Override
public String toString() {
return "User{id='" + id + "', name='" + name + "', role='" + role
+ "', schoolId='" + schoolId + "', status=" + status + "}";
}
}