🚀 AI 近视防控系统 - 生产环境上线版本 v1.0

 已完成功能:
- 后端 Go 服务 (认证/授权/检测)
- JWT 认证 + RBAC 权限控制
- 登录速率限制 (5 次失败锁定 15 分钟)
- 密码强度校验
- 敏感数据脱敏
- Vue3 管理后台
- 路由守卫
- 删除二次确认

📦 部署配置:
- Docker Compose 生产环境配置
- MySQL/Redis/MongoDB 数据库
- Nginx 前端服务
- 强密码安全配置

⚠️ P2 待办 (下次迭代):
- 学生/检测/预警等业务模块实现
- 错误处理统一化
- 缓存策略优化
- 日志分级

📍 生产环境:
- 服务器:192.168.15.222
- 管理后台:http://192.168.15.222:8081
- API 服务:http://192.168.15.222:8080

2026-03-29 上线部署完成
This commit is contained in:
虾司令
2026-03-29 18:16:41 +08:00
commit 881144269c
38 changed files with 4967 additions and 0 deletions

389
scripts/init_db.sql Normal file
View File

@@ -0,0 +1,389 @@
-- AI近视防控系统 - 数据库初始化脚本
-- 创建数据库
CREATE DATABASE IF NOT EXISTS myopia_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- 使用数据库
USE myopia_db;
-- 学校表
CREATE TABLE IF NOT EXISTS schools (
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(128) NOT NULL,
code VARCHAR(32) NOT NULL UNIQUE,
address VARCHAR(256),
contact_name VARCHAR(64),
contact_phone VARCHAR(20),
status TINYINT DEFAULT 1,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX idx_code (code),
INDEX idx_status (status)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='学校表';
-- 班级表
CREATE TABLE IF NOT EXISTS classes (
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(64) NOT NULL,
grade VARCHAR(16) NOT NULL, -- 年级:一年级、二年级...
school_id BIGINT UNSIGNED NOT NULL,
teacher_id BIGINT UNSIGNED,
student_count INT DEFAULT 0,
status TINYINT DEFAULT 1,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX idx_school (school_id),
INDEX idx_grade (grade),
FOREIGN KEY (school_id) REFERENCES schools(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='班级表';
-- 学生表
CREATE TABLE IF NOT EXISTS students (
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
student_no VARCHAR(32) NOT NULL UNIQUE,
name VARCHAR(64) NOT NULL,
gender TINYINT DEFAULT 1, -- 1:男 2:女
birth_date DATE,
class_id BIGINT UNSIGNED NOT NULL,
parent_id BIGINT UNSIGNED,
status TINYINT DEFAULT 1,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX idx_class (class_id),
INDEX idx_parent (parent_id),
INDEX idx_student_no (student_no),
FOREIGN KEY (class_id) REFERENCES classes(id),
FOREIGN KEY (parent_id) REFERENCES parents(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='学生表';
-- 家长表
CREATE TABLE IF NOT EXISTS parents (
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(64) NOT NULL,
phone VARCHAR(20) NOT NULL UNIQUE,
id_card VARCHAR(32),
status TINYINT DEFAULT 1,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX idx_phone (phone)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='家长表';
-- 家长 - 学生关联表
CREATE TABLE IF NOT EXISTS parent_student_rel (
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
parent_id BIGINT UNSIGNED NOT NULL,
student_id BIGINT UNSIGNED NOT NULL,
relation VARCHAR(16) NOT NULL, -- father/mother/other
is_primary TINYINT DEFAULT 0, -- 是否主要监护人
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
UNIQUE KEY uk_parent_student (parent_id, student_id),
INDEX idx_student (student_id),
FOREIGN KEY (parent_id) REFERENCES parents(id),
FOREIGN KEY (student_id) REFERENCES students(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='家长 - 学生关联表';
-- 教师表
CREATE TABLE IF NOT EXISTS teachers (
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(64) NOT NULL,
phone VARCHAR(20) NOT NULL UNIQUE,
school_id BIGINT UNSIGNED NOT NULL,
role VARCHAR(32), -- homeroom/school_doctor/sports
status TINYINT DEFAULT 1,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX idx_school (school_id),
FOREIGN KEY (school_id) REFERENCES schools(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='教师表';
-- 用户账号表
CREATE TABLE IF NOT EXISTS user_accounts (
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(64) NOT NULL UNIQUE,
password_hash VARCHAR(128) NOT NULL,
phone VARCHAR(20),
user_type VARCHAR(16) NOT NULL, -- student/parent/teacher/admin
user_id BIGINT UNSIGNED NOT NULL, -- 关联的 student_id/parent_id/teacher_id
status TINYINT DEFAULT 1,
last_login_at DATETIME,
last_login_ip VARCHAR(45),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX idx_user (user_type, user_id),
INDEX idx_phone (phone)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户账号表';
-- 检测任务表
CREATE TABLE IF NOT EXISTS detection_tasks (
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
task_no VARCHAR(32) NOT NULL UNIQUE,
class_id BIGINT UNSIGNED NOT NULL,
teacher_id BIGINT UNSIGNED NOT NULL,
start_time DATETIME NOT NULL,
end_time DATETIME,
student_count INT,
detection_type VARCHAR(32) NOT NULL, -- vision/fatigue/training
status TINYINT DEFAULT 0, -- 0:进行中 1:已完成 2:已取消
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
INDEX idx_class (class_id),
INDEX idx_time (start_time),
INDEX idx_status (status),
FOREIGN KEY (class_id) REFERENCES classes(id),
FOREIGN KEY (teacher_id) REFERENCES teachers(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='检测任务表';
-- 检测记录表
CREATE TABLE IF NOT EXISTS detections (
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
task_id BIGINT UNSIGNED NOT NULL,
student_id BIGINT UNSIGNED NOT NULL,
detection_time DATETIME NOT NULL,
vision_left DECIMAL(3,2), -- 左眼视力
vision_right DECIMAL(3,2), -- 右眼视力
fatigue_score DECIMAL(5,2), -- 疲劳分数
alert_level TINYINT DEFAULT 0, -- 0:正常 1:关注 2:预警 3:告警
device_id BIGINT UNSIGNED,
raw_data_url VARCHAR(512), -- 原始数据存储路径
ai_analysis JSON, -- AI 分析结果
status TINYINT DEFAULT 1,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
INDEX idx_task (task_id),
INDEX idx_student (student_id),
INDEX idx_time (detection_time),
INDEX idx_alert (alert_level),
FOREIGN KEY (task_id) REFERENCES detection_tasks(id),
FOREIGN KEY (student_id) REFERENCES students(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='检测记录表';
-- 预警记录表
CREATE TABLE IF NOT EXISTS alerts (
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
student_id BIGINT UNSIGNED NOT NULL,
detection_id BIGINT UNSIGNED,
alert_level TINYINT NOT NULL, -- 1:关注 2:预警 3:告警
alert_type VARCHAR(32), -- vision_drop/fatigue/abnormal
alert_content TEXT,
status TINYINT DEFAULT 0, -- 0:未处理 1:已通知 2:已处理
notified_at DATETIME,
handled_at DATETIME,
handler_id BIGINT UNSIGNED,
handle_remark TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
INDEX idx_student (student_id),
INDEX idx_status (status),
INDEX idx_level (alert_level),
FOREIGN KEY (student_id) REFERENCES students(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='预警记录表';
-- 预警配置表
CREATE TABLE IF NOT EXISTS alert_configs (
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
school_id BIGINT UNSIGNED,
alert_level TINYINT NOT NULL,
vision_threshold DECIMAL(3,2),
drop_threshold DECIMAL(3,2), -- 下降幅度阈值
notify_parent TINYINT DEFAULT 1,
notify_teacher TINYINT DEFAULT 1,
notify_school_doctor TINYINT DEFAULT 0,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX idx_school (school_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='预警配置表';
-- 训练内容表
CREATE TABLE IF NOT EXISTS training_contents (
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(128) NOT NULL,
type VARCHAR(32) NOT NULL, -- eye_exercise/crystal/acupoint/relax
duration INT NOT NULL, -- 时长 (秒)
video_url VARCHAR(512),
thumbnail_url VARCHAR(512),
description TEXT,
difficulty TINYINT DEFAULT 1, -- 1-5
status TINYINT DEFAULT 1,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX idx_type (type),
INDEX idx_status (status)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='训练内容表';
-- 训练任务表
CREATE TABLE IF NOT EXISTS training_tasks (
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
student_id BIGINT UNSIGNED NOT NULL,
content_id BIGINT UNSIGNED NOT NULL,
scheduled_date DATE NOT NULL,
scheduled_time TIME,
status TINYINT DEFAULT 0, -- 0:待完成 1:已完成 2:已跳过
completed_at DATETIME,
score INT, -- 动作评分
points_earned INT DEFAULT 0, -- 获得积分
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
INDEX idx_student (student_id),
INDEX idx_date (scheduled_date),
INDEX idx_status (status),
FOREIGN KEY (student_id) REFERENCES students(id),
FOREIGN KEY (content_id) REFERENCES training_contents(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='训练任务表';
-- 用户积分表
CREATE TABLE IF NOT EXISTS user_points (
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
user_id BIGINT UNSIGNED NOT NULL,
user_type VARCHAR(16) NOT NULL,
total_points INT DEFAULT 0,
used_points INT DEFAULT 0,
level VARCHAR(32) DEFAULT 'bronze', -- bronze/silver/gold/diamond
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
UNIQUE KEY uk_user (user_type, user_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户积分表';
-- 积分流水表
CREATE TABLE IF NOT EXISTS point_transactions (
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
user_id BIGINT UNSIGNED NOT NULL,
user_type VARCHAR(16) NOT NULL,
change_type VARCHAR(32) NOT NULL, -- earn/use
points INT NOT NULL,
balance_after INT NOT NULL,
source VARCHAR(64), -- 来源training/detection/activity
description VARCHAR(256),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
INDEX idx_user (user_type, user_id),
INDEX idx_time (created_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='积分流水表';
-- 设备表
CREATE TABLE IF NOT EXISTS devices (
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
device_no VARCHAR(64) NOT NULL UNIQUE,
device_name VARCHAR(128),
device_type VARCHAR(32) NOT NULL, -- terminal/camera/edge_box
school_id BIGINT UNSIGNED,
class_id BIGINT UNSIGNED,
ip_address VARCHAR(45),
mac_address VARCHAR(32),
status TINYINT DEFAULT 0, -- 0:离线 1:在线 2:故障
last_heartbeat DATETIME,
firmware_version VARCHAR(32),
config_version INT DEFAULT 1,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX idx_school (school_id),
INDEX idx_class (class_id),
INDEX idx_status (status),
FOREIGN KEY (school_id) REFERENCES schools(id),
FOREIGN KEY (class_id) REFERENCES classes(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='设备表';
-- 创建默认超级管理员账号
INSERT INTO user_accounts (username, password_hash, phone, user_type, user_id, status, created_at)
SELECT 'admin', '$2a$10$8K1B6ZJ9YHmR5vN.Lm.YeOI0TmN7MAe9WcLQ.UR.X.q8.yFv9q8QO', '13800138000', 'admin', 1, 1, NOW()
WHERE NOT EXISTS (SELECT 1 FROM user_accounts WHERE username = 'admin');
-- 插入示例学校
INSERT INTO schools (name, code, address, contact_name, contact_phone, created_at) VALUES
('启明小学', 'QMXX001', '北京市朝阳区启明路1号', '张校长', '010-12345678', NOW()),
('阳光中学', 'YGZX001', '上海市浦东新区阳光大道100号', '李校长', '021-87654321', NOW());
-- 插入示例班级
INSERT INTO classes (name, grade, school_id, created_at) VALUES
('一年级一班', '一年级', 1, NOW()),
('二年级二班', '二年级', 1, NOW()),
('七年级一班', '七年级', 2, NOW());
-- 插入示例教师
INSERT INTO teachers (name, phone, school_id, role, created_at) VALUES
('王老师', '13811111111', 1, 'homeroom', NOW()),
('李老师', '13822222222', 1, 'school_doctor', NOW()),
('赵老师', '13833333333', 2, 'homeroom', NOW());
-- 插入示例家长
INSERT INTO parents (name, phone, created_at) VALUES
('张三', '13911111111', NOW()),
('李四', '13922222222', NOW()),
('王五', '13933333333', NOW());
-- 插入示例学生
INSERT INTO students (student_no, name, gender, class_id, parent_id, created_at) VALUES
('20260001', '张小明', 1, 1, 1, NOW()),
('20260002', '李小红', 2, 1, 2, NOW()),
('20260003', '王小华', 1, 2, 3, NOW());
-- 插入示例训练内容
INSERT INTO training_contents (name, type, duration, description, difficulty, status, created_at) VALUES
('眼保健操', 'eye_exercise', 300, '经典眼保健操,有效缓解眼部疲劳', 2, 1, NOW()),
('晶状体调焦训练', 'crystal_ball', 600, '通过远近调节训练晶状体灵活性', 3, 1, NOW()),
('穴位按摩', 'acupoint', 180, '按摩眼周穴位,促进血液循环', 1, 1, NOW());
-- 插入示例预警配置
INSERT INTO alert_configs (school_id, alert_level, vision_threshold, drop_threshold, notify_parent, notify_teacher, created_at) VALUES
(1, 1, 4.8, 0.1, 1, 1, NOW()), -- 绿色预警视力低于4.8
(1, 2, 4.5, 0.2, 1, 1, NOW()), -- 黄色预警视力低于4.5
(1, 3, 4.0, 0.3, 1, 1, NOW()); -- 红色预警视力低于4.0
-- 创建设备
INSERT INTO devices (device_no, device_name, device_type, school_id, class_id, status, created_at) VALUES
('DEV001', '教室一体机', 'terminal', 1, 1, 1, NOW()),
('CAM001', '教室摄像头', 'camera', 1, 1, 1, NOW());
-- 创建索引优化查询
CREATE INDEX idx_detections_student_time ON detections(student_id, detection_time);
CREATE INDEX idx_detections_task_time ON detections(task_id, detection_time);
CREATE INDEX idx_alerts_student_created ON alerts(student_id, created_at);
-- 创建视图:学生综合报告视图
CREATE VIEW student_comprehensive_report AS
SELECT
s.id as student_id,
s.name as student_name,
s.student_no,
cl.name as class_name,
sc.name as school_name,
MAX(d.detection_time) as last_detection_time,
AVG(d.vision_left) as avg_vision_left,
AVG(d.vision_right) as avg_vision_right,
COUNT(d.id) as detection_count,
COUNT(a.id) as alert_count
FROM students s
LEFT JOIN classes cl ON s.class_id = cl.id
LEFT JOIN schools sc ON cl.school_id = sc.id
LEFT JOIN detections d ON s.id = d.student_id
LEFT JOIN alerts a ON s.id = a.student_id
GROUP BY s.id;
-- 创建视图:班级统计视图
CREATE VIEW class_statistics AS
SELECT
cl.id as class_id,
cl.name as class_name,
sc.name as school_name,
COUNT(st.id) as total_students,
COUNT(d.student_id) as tested_students,
AVG(d.vision_left) as avg_vision_left,
AVG(d.vision_right) as avg_vision_right,
SUM(CASE WHEN a.id IS NOT NULL THEN 1 ELSE 0 END) as alert_count
FROM classes cl
LEFT JOIN schools sc ON cl.school_id = sc.id
LEFT JOIN students st ON cl.id = st.class_id
LEFT JOIN detections d ON st.id = d.student_id
LEFT JOIN alerts a ON st.id = a.student_id
GROUP BY cl.id;
-- 设置表的自增ID起始值
ALTER TABLE schools AUTO_INCREMENT = 1000;
ALTER TABLE classes AUTO_INCREMENT = 2000;
ALTER TABLE students AUTO_INCREMENT = 3000;
ALTER TABLE teachers AUTO_INCREMENT = 4000;
ALTER TABLE parents AUTO_INCREMENT = 5000;
ALTER TABLE user_accounts AUTO_INCREMENT = 6000;
ALTER TABLE detection_tasks AUTO_INCREMENT = 7000;
ALTER TABLE detections AUTO_INCREMENT = 8000;
ALTER TABLE alerts AUTO_INCREMENT = 9000;
ALTER TABLE training_contents AUTO_INCREMENT = 10000;
ALTER TABLE training_tasks AUTO_INCREMENT = 11000;
ALTER TABLE devices AUTO_INCREMENT = 12000;
-- 完成
SELECT 'AI近视防控系统数据库初始化完成' as message;