239 lines
8.8 KiB
Python
239 lines
8.8 KiB
Python
|
|
#!/usr/bin/env python3
|
||
|
|
"""
|
||
|
|
数据库迁移脚本
|
||
|
|
连接到远程 MySQL 数据库并执行 SQL 建表语句
|
||
|
|
"""
|
||
|
|
|
||
|
|
import mysql.connector
|
||
|
|
from mysql.connector import Error
|
||
|
|
|
||
|
|
# 数据库配置
|
||
|
|
DB_CONFIG = {
|
||
|
|
'host': '8.148.151.56',
|
||
|
|
'port': 3306,
|
||
|
|
'user': 'root',
|
||
|
|
'password': 'reading_platform_pwd',
|
||
|
|
'database': 'reading_platform',
|
||
|
|
'charset': 'utf8mb4',
|
||
|
|
'autocommit': True
|
||
|
|
}
|
||
|
|
|
||
|
|
# SQL 建表语句
|
||
|
|
SQL_STATEMENTS = [
|
||
|
|
# 1. 课程套餐表
|
||
|
|
"""
|
||
|
|
CREATE TABLE IF NOT EXISTS course_package (
|
||
|
|
id BIGINT NOT NULL AUTO_INCREMENT,
|
||
|
|
name VARCHAR(255) NOT NULL COMMENT '套餐名称',
|
||
|
|
description TEXT COMMENT '套餐描述',
|
||
|
|
price BIGINT NOT NULL COMMENT '价格(分)',
|
||
|
|
discount_price BIGINT COMMENT '折后价格(分)',
|
||
|
|
discount_type VARCHAR(50) COMMENT '折扣类型',
|
||
|
|
grade_levels VARCHAR(500) COMMENT '适用年级',
|
||
|
|
course_count INT NOT NULL DEFAULT 0 COMMENT '课程数量',
|
||
|
|
status VARCHAR(50) NOT NULL DEFAULT 'DRAFT' COMMENT '状态',
|
||
|
|
submitted_at DATETIME COMMENT '提交时间',
|
||
|
|
submitted_by BIGINT COMMENT '提交人ID',
|
||
|
|
reviewed_at DATETIME COMMENT '审核时间',
|
||
|
|
reviewed_by BIGINT COMMENT '审核人ID',
|
||
|
|
review_comment TEXT COMMENT '审核意见',
|
||
|
|
published_at DATETIME COMMENT '发布时间',
|
||
|
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||
|
|
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||
|
|
PRIMARY KEY (id),
|
||
|
|
KEY idx_status (status)
|
||
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='课程套餐表'
|
||
|
|
""",
|
||
|
|
|
||
|
|
# 2. 套餐课程关联表
|
||
|
|
"""
|
||
|
|
CREATE TABLE IF NOT EXISTS course_package_course (
|
||
|
|
id BIGINT NOT NULL AUTO_INCREMENT,
|
||
|
|
package_id BIGINT NOT NULL COMMENT '套餐ID',
|
||
|
|
course_id BIGINT NOT NULL COMMENT '课程ID',
|
||
|
|
grade_level VARCHAR(50) COMMENT '适用年级',
|
||
|
|
sort_order INT NOT NULL DEFAULT 0 COMMENT '排序号',
|
||
|
|
PRIMARY KEY (id),
|
||
|
|
UNIQUE KEY uk_package_course (package_id, course_id)
|
||
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='套餐课程关联表'
|
||
|
|
""",
|
||
|
|
|
||
|
|
# 3. 租户套餐关联表
|
||
|
|
"""
|
||
|
|
CREATE TABLE IF NOT EXISTS tenant_package (
|
||
|
|
id BIGINT NOT NULL AUTO_INCREMENT,
|
||
|
|
tenant_id BIGINT NOT NULL COMMENT '租户ID',
|
||
|
|
package_id BIGINT NOT NULL COMMENT '套餐ID',
|
||
|
|
start_date DATE NOT NULL COMMENT '开始日期',
|
||
|
|
end_date DATE NOT NULL COMMENT '结束日期',
|
||
|
|
price_paid BIGINT NOT NULL DEFAULT 0 COMMENT '实付价格',
|
||
|
|
status VARCHAR(50) NOT NULL DEFAULT 'ACTIVE' COMMENT '状态',
|
||
|
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||
|
|
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||
|
|
PRIMARY KEY (id),
|
||
|
|
KEY idx_tenant_id (tenant_id)
|
||
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='租户套餐关联表'
|
||
|
|
""",
|
||
|
|
|
||
|
|
# 4. 课程环节表
|
||
|
|
"""
|
||
|
|
CREATE TABLE IF NOT EXISTS course_lesson (
|
||
|
|
id BIGINT NOT NULL AUTO_INCREMENT,
|
||
|
|
course_id BIGINT NOT NULL COMMENT '课程ID',
|
||
|
|
lesson_type VARCHAR(50) NOT NULL COMMENT '课程类型',
|
||
|
|
name VARCHAR(255) NOT NULL COMMENT '课程名称',
|
||
|
|
description TEXT COMMENT '课程描述',
|
||
|
|
duration INT COMMENT '时长(分钟)',
|
||
|
|
video_path VARCHAR(500) COMMENT '视频路径',
|
||
|
|
video_name VARCHAR(255) COMMENT '视频名称',
|
||
|
|
ppt_path VARCHAR(500) COMMENT 'PPT路径',
|
||
|
|
ppt_name VARCHAR(255) COMMENT 'PPT名称',
|
||
|
|
pdf_path VARCHAR(500) COMMENT 'PDF路径',
|
||
|
|
pdf_name VARCHAR(255) COMMENT 'PDF名称',
|
||
|
|
objectives TEXT COMMENT '教学目标',
|
||
|
|
preparation TEXT COMMENT '教学准备',
|
||
|
|
extension TEXT COMMENT '教学延伸',
|
||
|
|
reflection TEXT COMMENT '教学反思',
|
||
|
|
assessment_data TEXT COMMENT '评测数据',
|
||
|
|
use_template TINYINT(1) DEFAULT 0 COMMENT '是否使用模板',
|
||
|
|
sort_order INT NOT NULL DEFAULT 0 COMMENT '排序号',
|
||
|
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||
|
|
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||
|
|
PRIMARY KEY (id),
|
||
|
|
UNIQUE KEY uk_course_lesson_type (course_id, lesson_type)
|
||
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='课程环节表'
|
||
|
|
""",
|
||
|
|
|
||
|
|
# 5. 教学环节表
|
||
|
|
"""
|
||
|
|
CREATE TABLE IF NOT EXISTS lesson_step (
|
||
|
|
id BIGINT NOT NULL AUTO_INCREMENT,
|
||
|
|
lesson_id BIGINT NOT NULL COMMENT '课程环节ID',
|
||
|
|
name VARCHAR(255) NOT NULL COMMENT '环节名称',
|
||
|
|
content TEXT COMMENT '环节内容',
|
||
|
|
duration INT NOT NULL DEFAULT 5 COMMENT '时长(分钟)',
|
||
|
|
objective TEXT COMMENT '教学目标',
|
||
|
|
resource_ids TEXT COMMENT '资源ID列表',
|
||
|
|
sort_order INT NOT NULL DEFAULT 0 COMMENT '排序号',
|
||
|
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||
|
|
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||
|
|
PRIMARY KEY (id),
|
||
|
|
KEY idx_lesson_id (lesson_id)
|
||
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='教学环节表'
|
||
|
|
""",
|
||
|
|
|
||
|
|
# 6. 环节资源关联表
|
||
|
|
"""
|
||
|
|
CREATE TABLE IF NOT EXISTS lesson_step_resource (
|
||
|
|
id BIGINT NOT NULL AUTO_INCREMENT,
|
||
|
|
step_id BIGINT NOT NULL COMMENT '环节ID',
|
||
|
|
resource_id BIGINT NOT NULL COMMENT '资源ID',
|
||
|
|
sort_order INT NOT NULL DEFAULT 0 COMMENT '排序号',
|
||
|
|
PRIMARY KEY (id),
|
||
|
|
KEY idx_step_id (step_id)
|
||
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='环节资源关联表'
|
||
|
|
""",
|
||
|
|
|
||
|
|
# 7. 主题字典表
|
||
|
|
"""
|
||
|
|
CREATE TABLE IF NOT EXISTS theme (
|
||
|
|
id BIGINT NOT NULL AUTO_INCREMENT,
|
||
|
|
name VARCHAR(255) NOT NULL COMMENT '主题名称',
|
||
|
|
description TEXT COMMENT '主题描述',
|
||
|
|
sort_order INT NOT NULL DEFAULT 0 COMMENT '排序号',
|
||
|
|
status VARCHAR(50) NOT NULL DEFAULT 'ACTIVE' COMMENT '状态',
|
||
|
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||
|
|
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||
|
|
PRIMARY KEY (id),
|
||
|
|
KEY idx_status (status)
|
||
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='主题字典表'
|
||
|
|
"""
|
||
|
|
]
|
||
|
|
|
||
|
|
def execute_migration():
|
||
|
|
"""执行数据库迁移"""
|
||
|
|
print("=" * 50)
|
||
|
|
print("开始执行数据库迁移...")
|
||
|
|
print("=" * 50)
|
||
|
|
print(f"数据库: {DB_CONFIG['host']}:{DB_CONFIG['port']}/{DB_CONFIG['database']}")
|
||
|
|
print("-" * 50)
|
||
|
|
|
||
|
|
# 表名列表
|
||
|
|
table_names = ['course_package', 'course_package_course', 'tenant_package',
|
||
|
|
'course_lesson', 'lesson_step', 'lesson_step_resource', 'theme']
|
||
|
|
|
||
|
|
try:
|
||
|
|
# 连接数据库
|
||
|
|
print("正在连接数据库...")
|
||
|
|
conn = mysql.connector.connect(**DB_CONFIG)
|
||
|
|
cursor = conn.cursor()
|
||
|
|
print("✓ 数据库连接成功\n")
|
||
|
|
|
||
|
|
# 执行 SQL 语句
|
||
|
|
success_count = 0
|
||
|
|
skip_count = 0
|
||
|
|
error_count = 0
|
||
|
|
|
||
|
|
for i, sql in enumerate(SQL_STATEMENTS, 1):
|
||
|
|
table_name = table_names[i - 1]
|
||
|
|
print(f"[{i}/{len(SQL_STATEMENTS)}] 创建表: {table_name}")
|
||
|
|
|
||
|
|
try:
|
||
|
|
cursor.execute(sql)
|
||
|
|
print(f" ✓ 成功\n")
|
||
|
|
success_count += 1
|
||
|
|
except Error as e:
|
||
|
|
if "already exists" in str(e):
|
||
|
|
print(f" ⚠ 表已存在,跳过\n")
|
||
|
|
skip_count += 1
|
||
|
|
else:
|
||
|
|
print(f" ✗ 失败: {e}\n")
|
||
|
|
error_count += 1
|
||
|
|
|
||
|
|
# 验证表创建
|
||
|
|
print("-" * 50)
|
||
|
|
print("验证表创建...")
|
||
|
|
cursor.execute("SHOW TABLES")
|
||
|
|
tables = cursor.fetchall()
|
||
|
|
print(f"✓ 数据库中共有 {len(tables)} 张表")
|
||
|
|
|
||
|
|
# 检查新创建的表
|
||
|
|
existing_tables = [t[0] for t in tables]
|
||
|
|
|
||
|
|
print("\n新创建的表:")
|
||
|
|
for table in table_names:
|
||
|
|
if table in existing_tables:
|
||
|
|
print(f" ✓ {table}")
|
||
|
|
else:
|
||
|
|
print(f" ✗ {table} (未找到)")
|
||
|
|
|
||
|
|
# 关闭连接
|
||
|
|
cursor.close()
|
||
|
|
conn.close()
|
||
|
|
|
||
|
|
# 总结
|
||
|
|
print("\n" + "=" * 50)
|
||
|
|
print("数据库迁移完成!")
|
||
|
|
print("=" * 50)
|
||
|
|
print(f"成功: {success_count}, 跳过: {skip_count}, 失败: {error_count}")
|
||
|
|
print(f"总计: {len(SQL_STATEMENTS)} 张表需要创建")
|
||
|
|
|
||
|
|
return success_count > 0
|
||
|
|
|
||
|
|
except Error as e:
|
||
|
|
print(f"\n✗ 数据库连接失败: {e}")
|
||
|
|
return False
|
||
|
|
except Exception as e:
|
||
|
|
print(f"\n✗ 执行失败: {e}")
|
||
|
|
import traceback
|
||
|
|
traceback.print_exc()
|
||
|
|
return False
|
||
|
|
|
||
|
|
if __name__ == "__main__":
|
||
|
|
try:
|
||
|
|
success = execute_migration()
|
||
|
|
exit(0 if success else 1)
|
||
|
|
except KeyboardInterrupt:
|
||
|
|
print("\n\n用户中断")
|
||
|
|
exit(1)
|