#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ MySQL 数据库初始化脚本 KaMiXiTong 软件授权管理系统 使用 MySQL 数据库的完整版本,支持多用户和高性能 """ import os import sys from datetime import datetime, timedelta, timezone from werkzeug.security import generate_password_hash # 添加项目根目录到Python路径 sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) def load_env_config(): """从.env文件加载配置""" env_file = '.env' if os.path.exists(env_file): print(f"正在从 {env_file} 加载配置...") with open(env_file, 'r', encoding='utf-8') as f: for line in f: line = line.strip() # 跳过注释和空行 if line and not line.startswith('#'): # 解析键值对 if '=' in line: key, value = line.split('=', 1) key = key.strip() value = value.strip().strip('"').strip("'") os.environ[key] = value print("配置加载完成") else: print(f"警告: 未找到 {env_file} 文件") def init_mysql_database(): """初始化 MySQL 数据库""" print("=" * 50) print("KaMiXiTong MySQL 数据库初始化开始...") print("=" * 50) # 从.env文件加载配置 load_env_config() # 获取数据库URL database_url = os.environ.get('DATABASE_URL') if not database_url: print("❌ 未设置DATABASE_URL环境变量") print("💡 请在.env文件中配置DATABASE_URL") print("示例: DATABASE_URL=mysql+pymysql://用户名:密码@主机:端口/数据库名") return False try: # 设置数据库URL到环境变量 os.environ['DATABASE_URL'] = database_url # 导入应用 from app import create_app, db from app.models import Admin, Product, Version, License, Device, Ticket from app.models.audit_log import AuditLog # 创建应用实例 app = create_app() print(f"数据库类型: MySQL") print(f"数据库URL: {database_url}") with app.app_context(): # 1. 删除所有表(如果存在) print("\n1. 清理现有数据库表...") db.drop_all() print(" ✓ 已删除所有现有表") # 2. 创建所有表 print("\n2. 创建数据库表结构...") db.create_all() print(" ✓ 已创建所有数据表") # 显式提交事务以确保表被创建 db.session.commit() # 2.1 验证表创建 print("\n2.1 验证表创建...") from sqlalchemy import inspect inspector = inspect(db.engine) tables = inspector.get_table_names() print(f" ✓ 成功创建 {len(tables)} 个表: {', '.join(tables)}") if not tables: raise Exception("表创建失败,没有找到任何表") # 3. 插入初始数据 print("\n3. 插入初始数据...") insert_mysql_data() # 显式提交并关闭会话 db.session.commit() db.session.close() # 4. 显示数据库信息 print("\n4. MySQL 数据库初始化完成!") show_mysql_database_info() return True except Exception as e: print(f"\n❌ MySQL 数据库初始化失败: {e}") import traceback traceback.print_exc() return False def insert_mysql_data(): """插入 MySQL 初始数据""" from app import db from app.models import Admin, Product, Version, License, Device, Ticket from app.models.audit_log import AuditLog # 1. 创建默认管理员账号 print(" 创建默认管理员账号...") admin = Admin( username='admin', email='admin@kamaxitong.com', role=1, # 超级管理员 status=1 # 正常 ) admin.set_password('admin123') db.session.add(admin) # 创建测试管理员账号 test_admin = Admin( username='test_admin', email='test@kamaxitong.com', role=0, # 普通管理员 status=1 # 正常 ) test_admin.set_password('test123') db.session.add(test_admin) print(" ✓ 已创建管理员账号 (admin/admin123, test_admin/test123)") # 2. 创建示例产品 print(" 创建示例产品...") products = [ Product( product_id='KMX001', product_name='KaMiXiTong 专业版', description='专业的软件授权管理系统,支持多种授权模式和完整的设备管理', status=1 ), Product( product_id='KMX002', product_name='KaMiXiTong 企业版', description='企业级软件授权管理解决方案,支持分布式部署和高并发访问', status=1 ) ] for product in products: db.session.add(product) print(" ✓ 已创建2个示例产品") # 3. 创建版本信息 print(" 创建版本信息...") versions = [ Version( product_id='KMX001', version_num='1.0.0', update_log='初始版本发布', download_url='https://download.kamaxitong.com/v1.0.0/professional.exe', min_license_version='1.0.0', force_update=0, download_status=1, publish_status=1 ), Version( product_id='KMX001', version_num='1.1.0', update_log='功能增强版本', download_url='https://download.kamaxitong.com/v1.1.0/professional.exe', min_license_version='1.0.0', force_update=0, download_status=1, publish_status=1 ), Version( product_id='KMX002', version_num='2.0.0', update_log='企业版初始版本', download_url='https://download.kamaxitong.com/v2.0.0/enterprise.exe', min_license_version='2.0.0', force_update=0, download_status=1, publish_status=1 ) ] for version in versions: db.session.add(version) print(" ✓ 已创建3个版本信息") # 4. 创建示例许可证 print(" 创建示例许可证...") # 使用时区感知的 datetime 对象替换 utcnow() current_time = datetime.now(timezone.utc) licenses = [ # 永久许可证 License( license_key=License.generate_license_key(), product_id='KMX001', type=1, # 正式版 status=1, # 已激活 valid_days=-1, # 永久 bind_machine_code='DEMO-MACHINE-CODE-001', activate_time=current_time - timedelta(days=30), expire_time=None, # 永久不过期 last_verify_time=current_time - timedelta(days=1), unbind_count=0 ), # 1年试用期许可证 License( license_key=License.generate_license_key(), product_id='KMX001', type=0, # 试用版 status=1, # 已激活 valid_days=365, # 1年 bind_machine_code='DEMO-MACHINE-CODE-002', activate_time=current_time - timedelta(days=15), expire_time=current_time + timedelta(days=350), # 还有350天过期 last_verify_time=current_time - timedelta(hours=6), unbind_count=1 ), # 未激活许可证 License( license_key=License.generate_license_key(), product_id='KMX002', type=1, # 正式版 status=0, # 未激活 valid_days=365, # 1年 bind_machine_code=None, activate_time=None, expire_time=None, last_verify_time=None, unbind_count=0 ) ] for license_obj in licenses: db.session.add(license_obj) print(" ✓ 已创建3个示例许可证") # 5. 创建示例设备 print(" 创建示例设备...") devices = [ Device( machine_code='DEMO-MACHINE-CODE-001', license_id=1, # 对应第一个许可证 product_id='KMX001', software_version='1.1.0', status=1, # 正常 activate_time=current_time - timedelta(days=30), last_verify_time=current_time - timedelta(days=1) ), Device( machine_code='DEMO-MACHINE-CODE-002', license_id=2, # 对应第二个许可证 product_id='KMX001', software_version='1.0.0', status=1, # 正常 activate_time=current_time - timedelta(days=15), last_verify_time=current_time - timedelta(hours=6) ) ] for device in devices: db.session.add(device) print(" ✓ 已创建2个示例设备") # 6. 创建示例工单 print(" 创建示例工单...") tickets = [ Ticket( title='许可证激活失败', product_id='KMX001', software_version='1.0.0', machine_code='CUSTOMER-MACHINE-001', license_key='DEMO-LICENSE-KEY-001', description='客户反馈无法激活许可证', priority=2, # 高优先级 status=2, # 已解决 operator='admin', remark='问题已解决', create_time=current_time - timedelta(days=5), update_time=current_time - timedelta(days=4), resolve_time=current_time - timedelta(days=4) ), Ticket( title='功能咨询', product_id='KMX002', software_version='2.0.0', machine_code=None, license_key=None, description='客户咨询批量购买事宜', priority=1, # 中优先级 status=0, # 待处理 operator=None, remark=None, create_time=current_time - timedelta(days=2), update_time=current_time - timedelta(days=2) ) ] for ticket in tickets: db.session.add(ticket) print(" ✓ 已创建2个示例工单") # 7. 创建审计日志示例数据 print(" 创建示例审计日志...") audit_logs = [ AuditLog( admin_id=1, action='login', target_type='system', target_id=None, details='管理员登录系统', ip_address='127.0.0.1', user_agent='Mozilla/5.0...', create_time=current_time - timedelta(days=30) ), AuditLog( admin_id=1, action='create', target_type='product', target_id=1, details='创建产品 KaMiXiTong 专业版', ip_address='127.0.0.1', user_agent='Mozilla/5.0...', create_time=current_time - timedelta(days=29) ) ] for log in audit_logs: db.session.add(log) print(" ✓ 已创建2条示例审计日志") # 提交所有更改 db.session.commit() print(" ✓ 所有初始数据插入完成") def show_mysql_database_info(): """显示 MySQL 数据库信息""" from app import db from app.models import Admin, Product, Version, License, Device, Ticket from app.models.audit_log import AuditLog print("\n" + "=" * 50) print("MySQL 数据库初始化信息统计") print("=" * 50) # 统计各表的记录数 tables_info = [ ('管理员账号', Admin.query.count()), ('产品', Product.query.count()), ('版本', Version.query.count()), ('许可证', License.query.count()), ('设备', Device.query.count()), ('工单', Ticket.query.count()), ('审计日志', AuditLog.query.count()) ] for table_name, count in tables_info: print(f" {table_name:8} : {count:3} 条记录") print("\n" + "=" * 50) print("默认登录信息") print("=" * 50) print(" 超级管理员: admin / admin123") print(" 普通管理员: test_admin / test123") print("\n注意事项:") print(" 1. 请在生产环境中修改默认密码") print(" 2. 确保MySQL服务正常运行") print(" 3. 修改 .env 文件中的 DATABASE_URL 为正确的MySQL配置") print(" 4. 定期备份数据库") print("=" * 50) def main(): """主函数""" try: # 检查是否安装了PyMySQL try: import pymysql except ImportError: print("❌ 未安装PyMySQL,请运行: pip install PyMySQL") sys.exit(1) # 初始化MySQL数据库 success = init_mysql_database() if success: print("\n🎉 MySQL 数据库初始化成功!") print("\n启动服务器:") print(" python run.py") print(" 或") print(" python start.py") print("\n访问: http://localhost:5000") else: print("\n❌ MySQL 数据库初始化失败!") sys.exit(1) except Exception as e: print(f"\n❌ 初始化失败: {e}") sys.exit(1) if __name__ == '__main__': main()