新增解答题拍照判分:百炼 Qwen-VL 按评分点逐点判分,无 API Key 时演示判分回退;混合卷按真实分值加权计分;判分照片与评分点进错题本;补齐历史迁移缺口(0005 模板生效方式/0006 五张缺失表+grammar_progress point_id)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
jacobxu666
2026-08-17 16:24:23 +08:00
co-authored by Claude Opus 4.8
parent 4033abc21d
commit f80a931ef0
21 changed files with 1377 additions and 45 deletions
+118
View File
@@ -0,0 +1,118 @@
-- xuchao: 修复历史迁移缺口。早期这些表是用 drizzle push/手工 DDL 建进生产的,
-- 仓库里一直没有对应迁移,导致全新数据库建不出这些表。本迁移全部幂等:
-- 表已存在则 CREATE TABLE IF NOT EXISTS 跳过,生产库重复执行无副作用。
CREATE TABLE IF NOT EXISTS `grammar_point` (
`id` bigint AUTO_INCREMENT NOT NULL,
`point_id` varchar(191) NOT NULL,
`level` varchar(20) NOT NULL,
`level_name` varchar(50) NOT NULL,
`title` varchar(200) NOT NULL,
`difficulty` int NOT NULL DEFAULT 1,
`summary` text,
`prereq` text,
`md` mediumtext NOT NULL,
`seq` int NOT NULL,
`updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT `grammar_point_id` PRIMARY KEY(`id`),
CONSTRAINT `uq_grammar_point_id` UNIQUE(`point_id`)
);
--> statement-breakpoint
CREATE TABLE IF NOT EXISTS `weekly_test` (
`id` bigint AUTO_INCREMENT NOT NULL,
`child_user_id` bigint NOT NULL,
`week_key` varchar(12) NOT NULL,
`score` int,
`correct` int,
`total` int,
`passed` boolean NOT NULL DEFAULT false,
`questions` mediumtext,
`taken_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT `weekly_test_id` PRIMARY KEY(`id`),
CONSTRAINT `uq_weekly_child_week` UNIQUE(`child_user_id`,`week_key`),
CONSTRAINT `fk_wt_child` FOREIGN KEY (`child_user_id`) REFERENCES `user`(`id`) ON DELETE cascade ON UPDATE no action
);
--> statement-breakpoint
CREATE TABLE IF NOT EXISTS `word_progress` (
`id` bigint AUTO_INCREMENT NOT NULL,
`child_user_id` bigint NOT NULL,
`day` int NOT NULL,
`learned` mediumtext,
`score` int,
`passed` boolean NOT NULL DEFAULT false,
`completed_at` datetime,
CONSTRAINT `word_progress_id` PRIMARY KEY(`id`),
CONSTRAINT `uq_word_child_day` UNIQUE(`child_user_id`,`day`),
CONSTRAINT `fk_wp_child` FOREIGN KEY (`child_user_id`) REFERENCES `user`(`id`) ON DELETE cascade ON UPDATE no action
);
--> statement-breakpoint
CREATE TABLE IF NOT EXISTS `word_recording` (
`id` bigint AUTO_INCREMENT NOT NULL,
`child_user_id` bigint NOT NULL,
`word` varchar(60) NOT NULL,
`day` int,
`oss_key` varchar(300) NOT NULL,
`created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT `word_recording_id` PRIMARY KEY(`id`),
KEY `idx_rec_child` (`child_user_id`),
CONSTRAINT `fk_wr_child` FOREIGN KEY (`child_user_id`) REFERENCES `user`(`id`) ON DELETE cascade ON UPDATE no action
);
--> statement-breakpoint
CREATE TABLE IF NOT EXISTS `wrong_book` (
`id` bigint AUTO_INCREMENT NOT NULL,
`child_user_id` bigint NOT NULL,
`source_type` varchar(10) NOT NULL,
`source_id` varchar(60) NOT NULL,
`source_title` varchar(200),
`question` mediumtext NOT NULL,
`user_answer` mediumtext,
`correct_answer` mediumtext,
`mastered` boolean NOT NULL DEFAULT false,
`created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT `wrong_book_id` PRIMARY KEY(`id`),
KEY `idx_wrong_child` (`child_user_id`,`mastered`),
CONSTRAINT `fk_wb_child` FOREIGN KEY (`child_user_id`) REFERENCES `user`(`id`) ON DELETE cascade ON UPDATE no action
);
--> statement-breakpoint
-- grammar_progress:0002 误用 seq 列建表,生产实际是 point_id。仅在缺 point_id 时转换。
-- 顺序关键:先加 point_id 与 uq_grammar_child_point(child_user_id 为最左前缀,可承接外键),
-- 之后才能安全删除被外键依赖的旧索引 uq_grammar_child_seq,全程不动外键本身。
SET @gp_has_point = (SELECT COUNT(*) FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'grammar_progress' AND column_name = 'point_id');
--> statement-breakpoint
SET @ddl = IF(@gp_has_point = 0, 'ALTER TABLE `grammar_progress` ADD COLUMN `point_id` varchar(191) NOT NULL', 'SELECT 1');
--> statement-breakpoint
PREPARE stmt FROM @ddl;
--> statement-breakpoint
EXECUTE stmt;
--> statement-breakpoint
DEALLOCATE PREPARE stmt;
--> statement-breakpoint
SET @gp_has_point_idx = (SELECT COUNT(*) FROM information_schema.statistics WHERE table_schema = DATABASE() AND table_name = 'grammar_progress' AND index_name = 'uq_grammar_child_point');
--> statement-breakpoint
SET @ddl = IF(@gp_has_point_idx = 0, 'ALTER TABLE `grammar_progress` ADD CONSTRAINT `uq_grammar_child_point` UNIQUE (`child_user_id`,`point_id`)', 'SELECT 1');
--> statement-breakpoint
PREPARE stmt FROM @ddl;
--> statement-breakpoint
EXECUTE stmt;
--> statement-breakpoint
DEALLOCATE PREPARE stmt;
--> statement-breakpoint
SET @gp_has_seq_idx = (SELECT COUNT(*) FROM information_schema.statistics WHERE table_schema = DATABASE() AND table_name = 'grammar_progress' AND index_name = 'uq_grammar_child_seq');
--> statement-breakpoint
SET @ddl = IF(@gp_has_seq_idx > 0, 'ALTER TABLE `grammar_progress` DROP INDEX `uq_grammar_child_seq`', 'SELECT 1');
--> statement-breakpoint
PREPARE stmt FROM @ddl;
--> statement-breakpoint
EXECUTE stmt;
--> statement-breakpoint
DEALLOCATE PREPARE stmt;
--> statement-breakpoint
SET @gp_has_seq = (SELECT COUNT(*) FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'grammar_progress' AND column_name = 'seq');
--> statement-breakpoint
SET @ddl = IF(@gp_has_seq > 0, 'ALTER TABLE `grammar_progress` DROP COLUMN `seq`', 'SELECT 1');
--> statement-breakpoint
PREPARE stmt FROM @ddl;
--> statement-breakpoint
EXECUTE stmt;
--> statement-breakpoint
DEALLOCATE PREPARE stmt;