-- SoonDesign 数据库结构 (UTF-8 无 BOM) SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; CREATE TABLE IF NOT EXISTS `users` ( `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, `email` VARCHAR(190) NOT NULL, `password_hash` VARCHAR(255) NOT NULL, `role` ENUM('user','admin') NOT NULL DEFAULT 'user', `admin_level` ENUM('full','ops') DEFAULT NULL, `status` ENUM('active','disabled') NOT NULL DEFAULT 'active', `created_at` DATETIME NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `email` (`email`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; CREATE TABLE IF NOT EXISTS `soon_files` ( `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, `user_id` INT UNSIGNED NOT NULL, `name` VARCHAR(190) NOT NULL, `json` LONGTEXT NOT NULL, `size` INT UNSIGNED NOT NULL DEFAULT 0, `version` INT UNSIGNED NOT NULL DEFAULT 1, `thumb` MEDIUMTEXT DEFAULT NULL, `created_at` DATETIME NOT NULL, `updated_at` DATETIME NOT NULL, `deleted_at` DATETIME DEFAULT NULL, PRIMARY KEY (`id`), KEY `user` (`user_id`, `deleted_at`, `updated_at`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; CREATE TABLE IF NOT EXISTS `plans` ( `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, `code` VARCHAR(64) NOT NULL, `name` VARCHAR(120) NOT NULL, `description` VARCHAR(255) DEFAULT NULL, `price_cents` INT UNSIGNED NOT NULL, `quota_mb` INT UNSIGNED NOT NULL, `max_files` INT UNSIGNED NOT NULL DEFAULT 0, `duration_days` INT UNSIGNED NOT NULL, `features` TEXT DEFAULT NULL, `sort_order` INT NOT NULL DEFAULT 0, `is_recommended` TINYINT(1) NOT NULL DEFAULT 0, `is_active` TINYINT(1) NOT NULL DEFAULT 1, PRIMARY KEY (`id`), UNIQUE KEY `code` (`code`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; INSERT INTO `plans` (`code`,`name`,`description`,`price_cents`,`quota_mb`,`max_files`,`duration_days`,`features`,`sort_order`,`is_recommended`,`is_active`) VALUES ('free','免费版','免费体验设计与编辑',0,2048,200,0, '["设计与编辑工具免费使用"]',0,0,1), ('member_lifetime','永久会员','一次激活,永久使用预览交付能力',100,2048,200,0, '["高清预览","成品打印","云端保存","导出设计文件","永久有效"]',10,1,1), ('member_monthly','月度订阅','按月灵活使用,随时续订',1999,2048,200,30, '["高清预览","成品打印","云端保存","导出设计文件","订阅周期:1 个月"]',20,0,0), ('member_quarterly','季度订阅','连续三个月,更省心',5299,2048,200,90, '["高清预览","成品打印","云端保存","导出设计文件","订阅周期:1 季"]',25,0,0), ('member_yearly','年度订阅','全年畅享,性价比更高',19999,2048,200,365, '["高清预览","成品打印","云端保存","导出设计文件","订阅周期:1 年"]',30,0,0) ON DUPLICATE KEY UPDATE name=VALUES(name), description=VALUES(description), price_cents=VALUES(price_cents), quota_mb=VALUES(quota_mb), max_files=VALUES(max_files), duration_days=VALUES(duration_days), features=VALUES(features), sort_order=VALUES(sort_order), is_recommended=VALUES(is_recommended), is_active=VALUES(is_active); CREATE TABLE IF NOT EXISTS `subscriptions` ( `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, `user_id` INT UNSIGNED NOT NULL, `plan_id` INT UNSIGNED NOT NULL, `source_order_id` BIGINT UNSIGNED DEFAULT NULL, `status` ENUM('active','expired','cancelled') NOT NULL DEFAULT 'active', `started_at` DATETIME NOT NULL, `expires_at` DATETIME NOT NULL, PRIMARY KEY (`id`), KEY `user` (`user_id`, `status`, `expires_at`), KEY `source_order` (`source_order_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; CREATE TABLE IF NOT EXISTS `pay_orders` ( `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, `order_no` VARCHAR(64) NOT NULL, `user_id` INT UNSIGNED NOT NULL, `plan_id` INT UNSIGNED NOT NULL, `channel` ENUM('alipay','wechat') NOT NULL, `amount_cents` INT UNSIGNED NOT NULL, `status` ENUM('pending','paid','cancelled','refunded') NOT NULL DEFAULT 'pending', `refund_status` ENUM('none','pending','approved','rejected') NOT NULL DEFAULT 'none', `refund_reason` TEXT DEFAULT NULL, `refund_note` TEXT DEFAULT NULL, `txn_id` VARCHAR(120) DEFAULT NULL, `client_ip` VARCHAR(64) DEFAULT NULL, `created_at` DATETIME NOT NULL, `paid_at` DATETIME DEFAULT NULL, `cancelled_at` DATETIME DEFAULT NULL, `refunded_at` DATETIME DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `order_no` (`order_no`), KEY `user` (`user_id`), KEY `status` (`status`), KEY `refund_status` (`refund_status`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; CREATE TABLE IF NOT EXISTS `audit_logs` ( `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, `admin_id` INT UNSIGNED NOT NULL, `action` VARCHAR(120) NOT NULL, `target` VARCHAR(190) NOT NULL, `context` TEXT, `ip` VARCHAR(64) DEFAULT NULL, `created_at` DATETIME NOT NULL, PRIMARY KEY (`id`), KEY `admin` (`admin_id`, `created_at`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; CREATE TABLE IF NOT EXISTS `soon_templates` ( `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, `name` VARCHAR(120) NOT NULL, `type` TINYINT UNSIGNED NOT NULL DEFAULT 1, `thumb` MEDIUMTEXT DEFAULT NULL, `file_size` INT UNSIGNED NOT NULL DEFAULT 0, `sort_order` INT NOT NULL DEFAULT 0, `is_active` TINYINT(1) NOT NULL DEFAULT 1, `created_at` DATETIME NOT NULL, `updated_at` DATETIME NOT NULL, PRIMARY KEY (`id`), KEY `active_sort` (`is_active`, `sort_order`, `id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; CREATE TABLE IF NOT EXISTS `settings` ( `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, `key` VARCHAR(120) NOT NULL, `value` TEXT NOT NULL, `updated_at` DATETIME NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `k` (`key`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; SET FOREIGN_KEY_CHECKS = 1;