diff --git a/src/main/resources/sql/homework_add_sch_id.sql b/src/main/resources/sql/homework_add_sch_id.sql new file mode 100644 index 0000000..2842a06 --- /dev/null +++ b/src/main/resources/sql/homework_add_sch_id.sql @@ -0,0 +1,16 @@ +-- ============================================================ +-- homework 表补 sch_id 列(多租户隔离) +-- 决策 D3:发布时从 BoaUser.currentRole.schId 填充,查询时按校过滤 +-- +-- 对应实体:Homework.schId / HomeworkRepository 多租户统计方法 +-- +-- 执行方式:由 DBA 手动在对应环境执行,AI 不代跑 +-- MySQL 5.7+ 兼容 +-- ============================================================ + +-- 1) 加列 +ALTER TABLE `homework` + ADD COLUMN `sch_id` INT NULL COMMENT '学校ID(多租户隔离:发布时从当前用户角色填充)'; + +-- 2) 加索引(用于按学校过滤查询) +CREATE INDEX `idx_homework_sch_id` ON `homework` (`sch_id`); diff --git a/src/main/resources/sql/homework_data_backfill.sql b/src/main/resources/sql/homework_data_backfill.sql new file mode 100644 index 0000000..89d6433 --- /dev/null +++ b/src/main/resources/sql/homework_data_backfill.sql @@ -0,0 +1,162 @@ +-- ============================================================ +-- 存量数据回填脚本 +-- 1. homework.sch_id:按发布人所属学校回填(从用户中心/平台用户表按发布人ID取 sch_id) +-- 2. homework_receiver:从 homework.receive_list JSON 字符串展开为关联表行 +-- +-- 人员标识口径:教师/学生一律为用户中心数字ID(publisher_id / receiver_id), +-- 不再使用登录账号(*account 列已由 v3_account_to_id_refactor.sql 删除)。 +-- receive_list 中的历史登录名(非数字)条目直接跳过,不落库。 +-- +-- 幂等设计:可重复执行,已存在的数据不会重复插入 +-- 执行方式:由 DBA 手动在对应环境执行,AI 不代跑 +-- 执行顺序:务必在 v3_account_to_id_refactor.sql 之后执行(依赖 publisher_id / receiver_id 列) +-- MySQL 5.7+ 兼容 +-- ============================================================ + +-- ============================================================ +-- Part 1:回填 homework.sch_id +-- ============================================================ + +-- 方式一:如果平台用户表有 sch_id 字段,按发布人ID(publisher_id)关联回填 +-- 注意:base_user 为平台库表示例,id/sch_id 列名需按实际平台库结构调整 +UPDATE `homework` n + INNER JOIN ( + SELECT DISTINCT u.id, u.sch_id + FROM base_user u + WHERE u.sch_id IS NOT NULL + ) t ON n.publisher_id = t.id +SET n.sch_id = t.sch_id +WHERE n.sch_id IS NULL + AND n.publisher_id IS NOT NULL; + +-- 方式二(备用):如果用户学校关系在 sys_user_role_rel 表 +-- 取每个用户的主身份学校(is_main=1),按用户ID回填 +-- 取消注释后执行(视实际库表结构选用,r 表用户ID列名需按实际结构调整) +-- +-- UPDATE `homework` n +-- INNER JOIN ( +-- SELECT r.user_id, r.sch_id +-- FROM sys_user_role_rel r +-- WHERE r.is_main = 1 +-- AND r.sch_id IS NOT NULL +-- ) t ON n.publisher_id = t.user_id +-- SET n.sch_id = t.sch_id +-- WHERE n.sch_id IS NULL +-- AND n.publisher_id IS NOT NULL; + + +-- ============================================================ +-- Part 2:从 homework.receive_list 展开到 homework_receiver 关联表 +-- ============================================================ + +-- 说明: +-- - homework.receive_list 存储格式有两种: +-- 1) "ALL"(全员作业)—— 不写明细行,跳过 +-- 2) JSON 数组 ["10012","10013",...](用户中心数字ID)或逗号分隔串 +-- - 仅数字条目落库(receiver_id 为 INT 非空);历史登录名条目跳过 +-- - 本脚本使用 MySQL 函数解析(MySQL 5.7+ 支持) +-- - 对于非标准 JSON 格式(逗号分隔串),使用循环逐条插入 +-- - 幂等:每次插入前先删除该作业的旧接收人记录 + +-- 注意:MySQL 5.7 的 JSON_TABLE 不可用,这里用存储过程逐条解析 + +DELIMITER $$ + +-- 存储过程:展开单个作业的接收人列表 +DROP PROCEDURE IF EXISTS `expand_homework_receivers`$$ +CREATE PROCEDURE `expand_homework_receivers`() +BEGIN + DECLARE v_done INT DEFAULT 0; + DECLARE v_homework_id INT; + DECLARE v_receive_list TEXT; + DECLARE cur CURSOR FOR + SELECT id, receive_list + FROM homework + WHERE receive_list IS NOT NULL + AND TRIM(receive_list) != '' + AND UPPER(TRIM(receive_list)) != 'ALL' + AND NOT EXISTS ( + SELECT 1 FROM homework_receiver WHERE homework_id = homework.id LIMIT 1 + ); + DECLARE CONTINUE HANDLER FOR NOT FOUND SET v_done = 1; + + OPEN cur; + read_loop: LOOP + FETCH cur INTO v_homework_id, v_receive_list; + IF v_done = 1 THEN + LEAVE read_loop; + END IF; + + -- 清理旧数据(幂等) + DELETE FROM homework_receiver WHERE homework_id = v_homework_id; + + SET v_receive_list = TRIM(v_receive_list); + + -- 去除首尾方括号(如有) + IF LEFT(v_receive_list, 1) = '[' AND RIGHT(v_receive_list, 1) = ']' THEN + SET v_receive_list = SUBSTRING(v_receive_list, 2, CHAR_LENGTH(v_receive_list) - 2); + END IF; + + -- 替换引号为空,按逗号分隔 + SET v_receive_list = REPLACE(REPLACE(v_receive_list, '"', ''), '''', ''); + + -- 逐条插入 + BEGIN + DECLARE v_entry VARCHAR(64); + DECLARE v_remaining TEXT; + SET v_remaining = v_receive_list; + + WHILE v_remaining IS NOT NULL AND TRIM(v_remaining) != '' DO + IF LOCATE(',', v_remaining) > 0 THEN + SET v_entry = TRIM(SUBSTRING_INDEX(v_remaining, ',', 1)); + SET v_remaining = SUBSTRING(v_remaining, LOCATE(',', v_remaining) + 1); + ELSE + SET v_entry = TRIM(v_remaining); + SET v_remaining = NULL; + END IF; + + -- 仅落数字条目(用户中心数字ID);历史登录名跳过 + IF v_entry != '' AND v_entry IS NOT NULL + AND v_entry REGEXP '^[0-9]+$' THEN + INSERT INTO homework_receiver + (homework_id, receiver_id, receive_type, create_time) + VALUES + (v_homework_id, CAST(v_entry AS UNSIGNED), 1, NOW()); + END IF; + END WHILE; + END; + END LOOP; + + CLOSE cur; +END$$ + +DELIMITER ; + +-- 执行存储过程 +CALL expand_homework_receivers(); + +-- 清理临时存储过程 +DROP PROCEDURE IF EXISTS `expand_homework_receivers`; + +-- ============================================================ +-- 回填结果验证查询(执行后手动检查) +-- ============================================================ + +-- 检查1:sch_id 回填覆盖率 +-- SELECT +-- COUNT(*) AS total, +-- SUM(CASE WHEN sch_id IS NOT NULL THEN 1 ELSE 0 END) AS sch_id_filled, +-- SUM(CASE WHEN sch_id IS NULL THEN 1 ELSE 0 END) AS sch_id_null +-- FROM homework; + +-- 检查2:homework_receiver 展开行数 +-- SELECT COUNT(*) FROM homework_receiver; + +-- 检查3:未展开的作业(receive_list 非空非 ALL 但 receiver 表无记录) +-- SELECT n.id, n.receive_list +-- FROM homework n +-- LEFT JOIN homework_receiver r ON r.homework_id = n.id +-- WHERE n.receive_list IS NOT NULL +-- AND TRIM(n.receive_list) != '' +-- AND UPPER(TRIM(n.receive_list)) != 'ALL' +-- AND r.id IS NULL; diff --git a/src/main/resources/sql/homework_receiver_create.sql b/src/main/resources/sql/homework_receiver_create.sql new file mode 100644 index 0000000..b414f22 --- /dev/null +++ b/src/main/resources/sql/homework_receiver_create.sql @@ -0,0 +1,26 @@ +-- ============================================================ +-- homework_receiver 建表(替代 homework.receive_list JSON 字符串存储) +-- 决策 D2-B:拆关联表,支撑阅读情况/催收/统计 SQL 化 +-- +-- 对应实体:com.yunhai.homework.entity.HomeworkReceiver +-- 人员口径:接收人存「用户ID + 姓名快照」(receiver_id + receiver_name),不含登录账号 +-- 索引:idx_homework_id(homework_id) + idx_receiver(receiver_id) +-- +-- 执行方式:由 DBA 手动在对应环境执行,AI 不代跑 +-- MySQL 5.7+ 兼容 +-- ============================================================ + +CREATE TABLE IF NOT EXISTS `homework_receiver` ( + `id` INT NOT NULL AUTO_INCREMENT COMMENT '自增主键', + `homework_id` INT NOT NULL COMMENT '作业ID(关联 homework.id)', + `receiver_id` INT NOT NULL COMMENT '接收人ID(用户中心数字ID)', + `receiver_name` VARCHAR(64) NULL COMMENT '接收人姓名快照', + `receive_type` INT NOT NULL DEFAULT 1 COMMENT '接收类型:1 接收 / 2 抄送', + `create_by` VARCHAR(64) NULL COMMENT '创建人ID(审计填充)', + `create_time` DATETIME NULL COMMENT '创建时间(审计填充)', + `update_by` VARCHAR(64) NULL COMMENT '更新人ID(审计填充)', + `update_time` DATETIME NULL COMMENT '更新时间(审计填充)', + PRIMARY KEY (`id`), + KEY `idx_homework_id` (`homework_id`), + KEY `idx_receiver` (`receiver_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='作业接收人关联表'; diff --git a/src/main/resources/sql/v3_account_to_id_refactor.sql b/src/main/resources/sql/v3_account_to_id_refactor.sql new file mode 100644 index 0000000..c5e67f9 --- /dev/null +++ b/src/main/resources/sql/v3_account_to_id_refactor.sql @@ -0,0 +1,92 @@ +-- ============================================================ +-- 去账号化改造迁移脚本:人员标识统一为「用户ID + 姓名快照」 +-- +-- 背景:业务表中教师/学生身份原以登录账号(account)承载,现统一改为 +-- 平台用户ID + 姓名快照,登录身份口径变为 LoginUser.userId: +-- homework.publisher_account → publisher_id(+ publisher_name 既有) +-- homework_read.reader_account → reader_id(+ reader_name 既有) +-- homework_receiver.account → receiver_id + receiver_name +-- class_student.user_account → 删除(student_id 即平台用户ID) +-- notification.receiver_account → receiver_id + receiver_name +-- homework_submission.reviewed_by → 语义改为批阅人ID,新增 reviewed_by_name +-- contacts_group.creator_account → creator_id +-- contacts_group_user.user_account→ 删除(保留 user_id + user_name) +-- 审计列 create_by / update_by 语义同步改为「用户ID」,存量登录名不强改。 +-- +-- 回填口径:存量的 *account 列原样拷贝到对应 *_id 列(历史值可能是登录名, +-- 也可能是历史数字ID),不做远程换算;读取侧已有「按登录名查不到 +-- 再按数字ID查」的兜底。如需精确换算可另行按用户中心批量清洗。 +-- +-- 执行方式:由 DBA 手动在对应环境执行,AI 不代跑 +-- 执行顺序:务必先执行本脚本,再部署新版应用(新版仅新增列,不会删除旧账号列; +-- 先部署会导致 uk_homework_reader 同名唯一键冲突、旧列残留) +-- MySQL 5.7+ 兼容(不支持 ADD COLUMN IF NOT EXISTS,重复执行前先核对列/索引) +-- ============================================================ + +-- --------------------------------------------------------------------- +-- 1. homework:发布人 账号 → ID +-- --------------------------------------------------------------------- +ALTER TABLE `homework` + ADD COLUMN `publisher_id` VARCHAR(64) NULL COMMENT '发布人ID(平台用户ID)' AFTER `publisher_account`; +UPDATE `homework` SET `publisher_id` = `publisher_account` WHERE `publisher_id` IS NULL; +ALTER TABLE `homework` DROP COLUMN `publisher_account`; + +-- --------------------------------------------------------------------- +-- 2. homework_read:读者 账号 → ID(唯一键同步重建) +-- --------------------------------------------------------------------- +ALTER TABLE `homework_read` + ADD COLUMN `reader_id` VARCHAR(64) NULL COMMENT '读者ID(平台用户ID)' AFTER `homework_id`; +UPDATE `homework_read` SET `reader_id` = `reader_account` WHERE `reader_id` IS NULL; +ALTER TABLE `homework_read` MODIFY `reader_id` VARCHAR(64) NOT NULL COMMENT '读者ID(平台用户ID)'; +ALTER TABLE `homework_read` DROP INDEX `uk_homework_reader`; +ALTER TABLE `homework_read` DROP COLUMN `reader_account`; +ALTER TABLE `homework_read` ADD UNIQUE KEY `uk_homework_reader` (`homework_id`, `reader_id`); + +-- --------------------------------------------------------------------- +-- 3. homework_receiver:接收人 账号 → ID + 姓名快照 +-- (表由 homework_receiver_create.sql 单独建,低环境不存在时跳过本节) +-- --------------------------------------------------------------------- +ALTER TABLE `homework_receiver` + ADD COLUMN `receiver_id` VARCHAR(64) NULL COMMENT '接收人ID(平台用户ID)' AFTER `homework_id`, + ADD COLUMN `receiver_name` VARCHAR(64) NULL COMMENT '接收人姓名快照' AFTER `receiver_id`; +UPDATE `homework_receiver` SET `receiver_id` = `account` WHERE `receiver_id` IS NULL; +ALTER TABLE `homework_receiver` MODIFY `receiver_id` VARCHAR(64) NOT NULL COMMENT '接收人ID(平台用户ID)'; +ALTER TABLE `homework_receiver` DROP INDEX `idx_account`; +ALTER TABLE `homework_receiver` DROP COLUMN `account`; +ALTER TABLE `homework_receiver` ADD INDEX `idx_receiver` (`receiver_id`); + +-- --------------------------------------------------------------------- +-- 4. class_student:删除登录账号列(身份口径 = student_id 即平台用户ID) +-- --------------------------------------------------------------------- +ALTER TABLE `class_student` DROP INDEX `idx_account`; +ALTER TABLE `class_student` DROP COLUMN `user_account`; + +-- --------------------------------------------------------------------- +-- 5. notification:接收人 账号 → ID + 姓名快照 +-- --------------------------------------------------------------------- +ALTER TABLE `notification` + ADD COLUMN `receiver_id` VARCHAR(64) NULL COMMENT '接收人ID(学生=student_id,教师=平台用户ID)' AFTER `content`, + ADD COLUMN `receiver_name` VARCHAR(64) NULL COMMENT '接收人姓名快照' AFTER `receiver_id`; +UPDATE `notification` SET `receiver_id` = `receiver_account` WHERE `receiver_id` IS NULL; +ALTER TABLE `notification` MODIFY `receiver_id` VARCHAR(64) NOT NULL COMMENT '接收人ID(学生=student_id,教师=平台用户ID)'; +ALTER TABLE `notification` DROP INDEX `idx_receiver`; +ALTER TABLE `notification` DROP COLUMN `receiver_account`; +ALTER TABLE `notification` ADD INDEX `idx_receiver` (`receiver_id`, `is_read`); + +-- --------------------------------------------------------------------- +-- 6. homework_submission:reviewed_by 语义改为批阅人ID,补姓名快照列 +-- --------------------------------------------------------------------- +ALTER TABLE `homework_submission` + ADD COLUMN `reviewed_by_name` VARCHAR(64) NULL COMMENT '批阅人姓名快照' AFTER `reviewed_by`; +ALTER TABLE `homework_submission` + MODIFY `reviewed_by` VARCHAR(64) NULL COMMENT '批阅人ID(平台用户ID)'; + +-- --------------------------------------------------------------------- +-- 7. contacts_group / contacts_group_user:联系组去账号 +-- --------------------------------------------------------------------- +ALTER TABLE `contacts_group` + ADD COLUMN `creator_id` VARCHAR(64) NULL COMMENT '创建人ID(平台用户ID)' AFTER `group_name`; +UPDATE `contacts_group` SET `creator_id` = `creator_account` WHERE `creator_id` IS NULL; +ALTER TABLE `contacts_group` DROP COLUMN `creator_account`; + +ALTER TABLE `contacts_group_user` DROP COLUMN `user_account`; diff --git a/src/main/resources/sql/v3_schema.sql b/src/main/resources/sql/v3_schema.sql new file mode 100644 index 0000000..571f162 --- /dev/null +++ b/src/main/resources/sql/v3_schema.sql @@ -0,0 +1,182 @@ +-- ===================================================================== +-- 课堂作业 V3(PRD V1.0)全量 DDL —— classwork-homework-plan-v3.md §5 +-- 库:classhomework(MySQL 5.7+) +-- 说明: +-- 1) 开发环境 ddl-auto=update 会自动建表/加列,本脚本用于生产与手工初始化; +-- 2) MySQL 5.7 不支持 ADD COLUMN IF NOT EXISTS,重复执行前请先核对列是否存在; +-- 3) 定时发布时间复用 homework.timing_send_time(PRD scheduled_at 同义),不新增列。 +-- 4) 人员标识口径:教师/学生一律为用户中心数字ID(INT),不存登录账号 +-- (与 v3_account_to_id_refactor.sql / v4_person_id_to_int.sql 收敛后的最终形态一致)。 +-- ===================================================================== + +-- --------------------------------------------------------------------- +-- 1. homework 扩展列(§5.1) +-- --------------------------------------------------------------------- +ALTER TABLE `homework` + ADD COLUMN `subject` VARCHAR(50) NULL COMMENT '学科(字典值)', + ADD COLUMN `deadline_at` DATETIME NULL COMMENT '截止时间(精确到分钟;空=仅查阅型)', + ADD COLUMN `hw_status` VARCHAR(20) NOT NULL DEFAULT 'DRAFT_UNPUBLISHED' + COMMENT 'DRAFT_UNPUBLISHED/DRAFT_SCHEDULED/PUBLISHED/CLOSED/ARCHIVED', + ADD COLUMN `published_at` DATETIME NULL COMMENT '发布时间(立即/定时到点均写)', + ADD COLUMN `submit_type` VARCHAR(100) NULL COMMENT 'JSON 数组 ["image","attach","text","none"]', + ADD COLUMN `allow_late` TINYINT NOT NULL DEFAULT 0 COMMENT '截止后是否允许逾期提交', + ADD COLUMN `remind_1d` TINYINT NOT NULL DEFAULT 1 COMMENT '截止前 1 天提醒', + ADD COLUMN `remind_1h` TINYINT NOT NULL DEFAULT 1 COMMENT '截止前 1 小时提醒', + ADD COLUMN `archived_at` DATETIME NULL COMMENT '归档时间'; + +-- --------------------------------------------------------------------- +-- 2. homework_class 作业-班级关联(§5.2) +-- --------------------------------------------------------------------- +CREATE TABLE IF NOT EXISTS `homework_class` ( + `id` INT NOT NULL AUTO_INCREMENT, + `homework_id` INT NOT NULL, + `class_id` VARCHAR(64) NOT NULL, + `class_name` VARCHAR(50) NULL COMMENT '班级名快照', + `create_by` VARCHAR(64) NULL, + `create_time` DATETIME NULL, + `update_by` VARCHAR(64) NULL, + `update_time` DATETIME NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `uk_hw_class` (`homework_id`, `class_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='作业班级关联'; + +-- --------------------------------------------------------------------- +-- 3. homework_attachment 作业附件(§5.3) +-- --------------------------------------------------------------------- +CREATE TABLE IF NOT EXISTS `homework_attachment` ( + `id` INT NOT NULL AUTO_INCREMENT, + `homework_id` INT NOT NULL, + `file_id` INT NULL COMMENT 'up_file.id', + `file_url` VARCHAR(500) NOT NULL, + `file_type` VARCHAR(20) NULL COMMENT 'image/file/...', + `file_name` VARCHAR(200) NULL, + `sort` INT NOT NULL DEFAULT 0, + `create_by` VARCHAR(64) NULL, + `create_time` DATETIME NULL, + `update_by` VARCHAR(64) NULL, + `update_time` DATETIME NULL, + KEY `idx_hw` (`homework_id`), + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='作业附件'; + +-- --------------------------------------------------------------------- +-- 4. homework_read_record 学生阅读记录(§5.4) +-- --------------------------------------------------------------------- +CREATE TABLE IF NOT EXISTS `homework_read_record` ( + `id` INT NOT NULL AUTO_INCREMENT, + `homework_id` INT NOT NULL, + `student_id` INT NOT NULL COMMENT '学生ID(用户中心数字ID,即 SchStudent.UserStuSerID)', + `student_name` VARCHAR(50) NULL, + `class_id` VARCHAR(64) NULL, + `is_read` TINYINT NOT NULL DEFAULT 0 COMMENT '0 UNREAD / 1 READ', + `first_read_at` DATETIME NULL, + `last_read_at` DATETIME NULL, + `read_count` INT NOT NULL DEFAULT 0, + `create_by` VARCHAR(64) NULL, + `create_time` DATETIME NULL, + `update_by` VARCHAR(64) NULL, + `update_time` DATETIME NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `uk_hw_student` (`homework_id`, `student_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='学生作业阅读记录'; + +-- --------------------------------------------------------------------- +-- 5. homework_submission 提交(多版本,§5.5) +-- --------------------------------------------------------------------- +CREATE TABLE IF NOT EXISTS `homework_submission` ( + `id` INT NOT NULL AUTO_INCREMENT, + `homework_id` INT NOT NULL, + `student_id` INT NOT NULL COMMENT '学生ID(用户中心数字ID,即 SchStudent.UserStuSerID)', + `student_name` VARCHAR(50) NOT NULL, + `class_id` VARCHAR(64) NOT NULL, + `class_name` VARCHAR(50) NOT NULL, + `version` INT NOT NULL DEFAULT 1 COMMENT '提交版本,同一学生单调递增', + `is_latest` TINYINT NOT NULL DEFAULT 1 COMMENT '1 当前版本 / 0 历史', + `status` VARCHAR(20) NOT NULL DEFAULT 'SUBMITTED' + COMMENT 'NOT_SUBMITTED/SUBMITTED/LATE_SUBMITTED/RETURNED/REVIEWED', + `is_late` TINYINT NOT NULL DEFAULT 0, + `submitted_at` DATETIME NULL, + `text` TEXT NULL, + `score` DECIMAL(6,2) NULL, + `comment` TEXT NULL COMMENT '评语(打回时=订正原因)', + `review_status` VARCHAR(20) NOT NULL DEFAULT 'PENDING' COMMENT 'PENDING/REVIEWED/RETURNED', + `reviewed_by` INT NULL COMMENT '批阅人ID(用户中心数字ID,同教师ID空间)', + `reviewed_by_name` VARCHAR(64) NULL COMMENT '批阅人姓名快照', + `reviewed_at` DATETIME NULL, + `create_by` VARCHAR(64) NULL, + `create_time` DATETIME NULL, + `update_by` VARCHAR(64) NULL, + `update_time` DATETIME NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `uk_hw_student_ver` (`homework_id`, `student_id`, `version`), + KEY `idx_latest` (`homework_id`, `student_id`, `is_latest`), + KEY `idx_status` (`homework_id`, `status`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='作业提交(多版本)'; + +-- --------------------------------------------------------------------- +-- 6. submission_attachment 提交附件(§5.6) +-- --------------------------------------------------------------------- +CREATE TABLE IF NOT EXISTS `submission_attachment` ( + `id` INT NOT NULL AUTO_INCREMENT, + `submission_id` INT NOT NULL, + `homework_id` INT NOT NULL COMMENT '冗余,便于统计与清理', + `student_id` INT NULL COMMENT '学生ID(用户中心数字ID)', + `file_id` INT NULL COMMENT 'up_file.id', + `file_url` VARCHAR(500) NOT NULL, + `file_type` VARCHAR(20) NULL COMMENT 'image/file', + `file_name` VARCHAR(200) NULL, + `sort` INT NOT NULL DEFAULT 0, + `create_by` VARCHAR(64) NULL, + `create_time` DATETIME NULL, + `update_by` VARCHAR(64) NULL, + `update_time` DATETIME NULL, + KEY `idx_sub` (`submission_id`), + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='提交附件'; + +-- --------------------------------------------------------------------- +-- 7. class_student 班级学生名册快照(§5.7,沿用 V2.1 §7.3) +-- --------------------------------------------------------------------- +CREATE TABLE IF NOT EXISTS `class_student` ( + `id` INT NOT NULL AUTO_INCREMENT, + `school_id` INT NOT NULL, + `class_id` VARCHAR(64) NOT NULL, + `class_name` VARCHAR(50) NULL, + `grade_name` VARCHAR(50) NULL, + `student_id` INT NOT NULL COMMENT '学生ID(用户中心数字ID,即 SchStudent.UserStuSerID)', + `student_name` VARCHAR(50) NOT NULL, + `status` TINYINT NOT NULL DEFAULT 1 COMMENT '1 在班 0 已转出/退课', + `leave_at` DATETIME NULL, + `create_by` VARCHAR(64) NULL, + `create_time` DATETIME NULL, + `update_by` VARCHAR(64) NULL, + `update_time` DATETIME NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `uk_class_student` (`class_id`, `student_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='班级学生名册快照'; + +-- --------------------------------------------------------------------- +-- 8. notification 站内通知(§5.8) +-- --------------------------------------------------------------------- +CREATE TABLE IF NOT EXISTS `notification` ( + `id` INT NOT NULL AUTO_INCREMENT, + `type` VARCHAR(30) NOT NULL + COMMENT 'HOMEWORK_PUBLISHED/DEADLINE_REMINDER/NOT_SUBMITTED/NOT_READ/REVIEW_DONE/RETURNED/SCHEDULE_FAILED/DEADLINE_CHANGED', + `homework_id` INT NULL, + `related_id` INT NULL COMMENT '关联业务 id(submissionId;截止提醒存档位 1=1天档 2=1小时档)', + `title` VARCHAR(200) NOT NULL, + `content` VARCHAR(1000) NULL, + `receiver_id` INT NOT NULL COMMENT '接收人ID(用户中心数字ID:学生=student_id,教师=同域数字ID)', + `receiver_name` VARCHAR(64) NULL COMMENT '接收人姓名快照', + `receiver_role` VARCHAR(20) NOT NULL DEFAULT 'student' COMMENT 'student/teacher', + `is_read` TINYINT NOT NULL DEFAULT 0, + `read_at` DATETIME NULL, + `send_channel` VARCHAR(20) NOT NULL DEFAULT 'inapp' COMMENT 'inapp/sms', + `create_by` VARCHAR(64) NULL, + `create_time` DATETIME NULL, + `update_by` VARCHAR(64) NULL, + `update_time` DATETIME NULL, + KEY `idx_receiver` (`receiver_id`, `is_read`), + KEY `idx_hw_type` (`homework_id`, `type`), + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='站内通知'; diff --git a/src/main/resources/sql/v3_seed.sql b/src/main/resources/sql/v3_seed.sql new file mode 100644 index 0000000..96c8cbc --- /dev/null +++ b/src/main/resources/sql/v3_seed.sql @@ -0,0 +1,33 @@ +-- ===================================================================== +-- 课堂作业 V3 本地联调种子数据 +-- 用途:bschclass 名册/任教开放接口未就绪期间(计划 §13-1),填充 +-- class_student(名册/班级树)与 sch_class_teach(任教关系/任教学科) +-- 供学生端身份映射(用户中心数字ID ↔ student_id)、教师学科下拉联调。 +-- 注意:仅限本地/联调环境执行;school_id=3(云海中学)、tea_id=10008(李晶) +-- 请按实际登录账号的学校/教师 id 调整; +-- student_id / tea_id 为用户中心数字ID(INT),非登录账号。 +-- sub_id 本地无学科字典时编码即展示名(如 '数学')。 +-- ===================================================================== + +-- 初一(1)班 C1:3 名学生 +INSERT INTO `class_student` + (`school_id`, `class_id`, `class_name`, `grade_name`, `student_id`, `student_name`, `status`, `create_time`, `update_time`) +VALUES + (3, 'C1', '初一(1)班', '初一', 10001, '张一', 1, NOW(), NOW()), + (3, 'C1', '初一(1)班', '初一', 10002, '王二', 1, NOW(), NOW()), + (3, 'C1', '初一(1)班', '初一', 10003, '李三', 1, NOW(), NOW()); + +-- 初一(2)班 C2:3 名学生 +INSERT INTO `class_student` + (`school_id`, `class_id`, `class_name`, `grade_name`, `student_id`, `student_name`, `status`, `create_time`, `update_time`) +VALUES + (3, 'C2', '初一(2)班', '初一', 10004, '赵四', 1, NOW(), NOW()), + (3, 'C2', '初一(2)班', '初一', 10005, '钱五', 1, NOW(), NOW()), + (3, 'C2', '初一(2)班', '初一', 10006, '孙六', 1, NOW(), NOW()); + +-- 任教关系:李晶(10008) 任教 C1/C2 数学(bschclass 不可用时的任教学科降级数据源) +INSERT INTO `sch_class_teach` + (`school_id`, `class_id`, `tea_id`, `sub_id`, `status`, `create_time`, `update_time`) +VALUES + (3, 'C1', 10008, '数学', 1, NOW(), NOW()), + (3, 'C2', 10008, '数学', 1, NOW(), NOW()); diff --git a/src/main/resources/sql/v4_person_id_to_int.sql b/src/main/resources/sql/v4_person_id_to_int.sql new file mode 100644 index 0000000..60e2349 --- /dev/null +++ b/src/main/resources/sql/v4_person_id_to_int.sql @@ -0,0 +1,106 @@ +-- ============================================================ +-- 人员标识数字化迁移脚本:教师/学生 ID 列 VARCHAR(64) → INT +-- +-- 背景:人员身份统一为用户中心数字ID(BoaUser.id,与 bschclass 的 +-- SchTeacher.UserTeaSerID / SchStudent.UserStuSerID 同一 ID 空间), +-- 应用侧实体字段已同步改为 Integer,当前登录人经 +-- utils/UserContext.getUserId() 解析(LoginUser.userId 非数字时 +-- 回退用户中心按登录名反查)。 +-- +-- 覆盖列(人员标识,不含 create_by/update_by 审计列): +-- homework.publisher_id 发布人(教师) +-- homework_read.reader_id 读者(教师) +-- homework_receiver.receiver_id 接收人(教师/学生) +-- homework_submission.student_id 学生 +-- homework_submission.reviewed_by 批阅人(教师) +-- homework_read_record.student_id 学生 +-- submission_attachment.student_id 学生 +-- class_student.student_id 学生 +-- notification.receiver_id 接收人(教师/学生) +-- contacts_group.creator_id 联系组创建人(教师) +-- +-- 存量清洗口径:v3_account_to_id_refactor 回填时可能带入历史登录名(非数字)。 +-- 可空列:非数字置 NULL(*_name 姓名快照保留,展示侧兜底); +-- 非空列:非数字行物理删除(如需保留请 DBA 先按用户中心人工换算后再执行)。 +-- homework.receive_list JSON 内的历史登录名条目由应用读取侧忽略(仅取数字条目)。 +-- +-- 执行方式:由 DBA 手动在对应环境执行,AI 不代跑 +-- 执行顺序:务必先执行本脚本,再部署新版应用 +-- MySQL 5.7+ 兼容;低环境不存在 homework_receiver 表时跳过对应小节; +-- 重复执行前先核对列类型 +-- ============================================================ + +-- --------------------------------------------------------------------- +-- 1. homework:发布人ID → INT(可空) +-- --------------------------------------------------------------------- +UPDATE `homework` + SET `publisher_id` = NULL + WHERE `publisher_id` IS NOT NULL AND `publisher_id` NOT REGEXP '^[0-9]+$'; +ALTER TABLE `homework` + MODIFY `publisher_id` INT NULL COMMENT '发布人ID(用户中心数字ID,同教师ID空间)'; + +-- --------------------------------------------------------------------- +-- 2. homework_read:读者ID → INT(NOT NULL,uk_homework_reader 不变) +-- --------------------------------------------------------------------- +DELETE FROM `homework_read` WHERE `reader_id` NOT REGEXP '^[0-9]+$'; +ALTER TABLE `homework_read` + MODIFY `reader_id` INT NOT NULL COMMENT '读者ID(用户中心数字ID,同教师ID空间)'; + +-- --------------------------------------------------------------------- +-- 3. homework_receiver:接收人ID → INT(NOT NULL) +-- (表由 homework_receiver_create.sql 单独建,低环境不存在时跳过本节) +-- --------------------------------------------------------------------- +DELETE FROM `homework_receiver` WHERE `receiver_id` NOT REGEXP '^[0-9]+$'; +ALTER TABLE `homework_receiver` + MODIFY `receiver_id` INT NOT NULL COMMENT '接收人ID(用户中心数字ID)'; + +-- --------------------------------------------------------------------- +-- 4. homework_submission:学生ID → INT(NOT NULL,uk/idx 不变)+ 批阅人ID → INT(可空) +-- --------------------------------------------------------------------- +DELETE FROM `homework_submission` WHERE `student_id` NOT REGEXP '^[0-9]+$'; +ALTER TABLE `homework_submission` + MODIFY `student_id` INT NOT NULL COMMENT '学生ID(用户中心数字ID,即 SchStudent.UserStuSerID)'; +UPDATE `homework_submission` + SET `reviewed_by` = NULL + WHERE `reviewed_by` IS NOT NULL AND `reviewed_by` NOT REGEXP '^[0-9]+$'; +ALTER TABLE `homework_submission` + MODIFY `reviewed_by` INT NULL COMMENT '批阅人ID(用户中心数字ID,同教师ID空间)'; + +-- --------------------------------------------------------------------- +-- 5. homework_read_record:学生ID → INT(NOT NULL,uk_hw_student 不变) +-- --------------------------------------------------------------------- +DELETE FROM `homework_read_record` WHERE `student_id` NOT REGEXP '^[0-9]+$'; +ALTER TABLE `homework_read_record` + MODIFY `student_id` INT NOT NULL COMMENT '学生ID(用户中心数字ID,即 SchStudent.UserStuSerID)'; + +-- --------------------------------------------------------------------- +-- 6. submission_attachment:学生ID → INT(可空) +-- --------------------------------------------------------------------- +UPDATE `submission_attachment` + SET `student_id` = NULL + WHERE `student_id` IS NOT NULL AND `student_id` NOT REGEXP '^[0-9]+$'; +ALTER TABLE `submission_attachment` + MODIFY `student_id` INT NULL COMMENT '学生ID(用户中心数字ID)'; + +-- --------------------------------------------------------------------- +-- 7. class_student:学生ID → INT(NOT NULL,uk_class_student 不变) +-- --------------------------------------------------------------------- +DELETE FROM `class_student` WHERE `student_id` NOT REGEXP '^[0-9]+$'; +ALTER TABLE `class_student` + MODIFY `student_id` INT NOT NULL COMMENT '学生ID(用户中心数字ID,即 SchStudent.UserStuSerID)'; + +-- --------------------------------------------------------------------- +-- 8. notification:接收人ID → INT(NOT NULL,idx_receiver 不变) +-- --------------------------------------------------------------------- +DELETE FROM `notification` WHERE `receiver_id` NOT REGEXP '^[0-9]+$'; +ALTER TABLE `notification` + MODIFY `receiver_id` INT NOT NULL COMMENT '接收人ID(学生=student_id,教师=用户中心数字ID,同一 ID 空间)'; + +-- --------------------------------------------------------------------- +-- 9. contacts_group:创建人ID → INT(可空) +-- --------------------------------------------------------------------- +UPDATE `contacts_group` + SET `creator_id` = NULL + WHERE `creator_id` IS NOT NULL AND `creator_id` NOT REGEXP '^[0-9]+$'; +ALTER TABLE `contacts_group` + MODIFY `creator_id` INT NULL COMMENT '创建人ID(用户中心数字ID,同教师ID空间)';