31cc1e02ce
- 新增 AffiliateProgram / AffiliateLink / AffiliateClick 规范化 Prisma 模型 取代原手写裸表 affiliate_stats / affiliate_clicks - 新增迁移 prisma/migrations/20260711000000_add_affiliate_models - 重构 affiliate.service.ts 改用 Prisma ORM,消除 $queryRawUnsafe SQL 注入 - 重构 affiliate.controller.ts 接口:programs / links(?skillId,?toolId) / stats / click - 前端 affiliate 页接入真实接口,移除硬编码 demo 数据 - 技能详情页新增「学此技能推荐使用的工具」联盟链接区块 - 新增 affiliate.service.spec.ts(4 用例通过)与幂等种子 seed-affiliate.ts - 更新 docs/progress/current.md,明确无 ICP 经营许可证下以联盟返佣为合规变现主路径 - 含此前工作区未提交改动(工具 slug 路由、支付/订单、SEO 等) Co-Authored-By: opencode <opencode@anthropic.com>
63 lines
2.7 KiB
SQL
63 lines
2.7 KiB
SQL
-- 联盟返佣系统:规范化数据模型
|
|
-- 替换原先手写的 affiliate_stats / affiliate_clicks 裸表,改用 ORM 管理
|
|
|
|
CREATE TABLE IF NOT EXISTS `affiliate_programs` (
|
|
`id` INT NOT NULL AUTO_INCREMENT,
|
|
`name` VARCHAR(191) NOT NULL,
|
|
`slug` VARCHAR(191) NOT NULL,
|
|
`provider` VARCHAR(191),
|
|
`description` TEXT,
|
|
`commission_rate` VARCHAR(191),
|
|
`cookie_days` INT,
|
|
`homepage_url` VARCHAR(191),
|
|
`logo` VARCHAR(191),
|
|
`active` TINYINT(1) NOT NULL DEFAULT 1,
|
|
`sort_order` INT NOT NULL DEFAULT 0,
|
|
`created_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
|
`updated_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
|
|
PRIMARY KEY (`id`),
|
|
UNIQUE INDEX `affiliate_programs_slug_key` (`slug`)
|
|
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
|
|
|
CREATE TABLE IF NOT EXISTS `affiliate_links` (
|
|
`id` INT NOT NULL AUTO_INCREMENT,
|
|
`program_id` INT NOT NULL,
|
|
`title` VARCHAR(191) NOT NULL,
|
|
`description` TEXT,
|
|
`url` TEXT NOT NULL,
|
|
`thumbnail` VARCHAR(191),
|
|
`tool_id` INT,
|
|
`skill_id` VARCHAR(191),
|
|
`tags` TEXT,
|
|
`estimated_commission` DOUBLE NOT NULL DEFAULT 0,
|
|
`sort_order` INT NOT NULL DEFAULT 0,
|
|
`is_featured` TINYINT(1) NOT NULL DEFAULT 0,
|
|
`active` TINYINT(1) NOT NULL DEFAULT 1,
|
|
`created_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
|
`updated_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
|
|
PRIMARY KEY (`id`),
|
|
INDEX `affiliate_links_program_id_idx` (`program_id`),
|
|
INDEX `affiliate_links_tool_id_idx` (`tool_id`),
|
|
INDEX `affiliate_links_skill_id_idx` (`skill_id`),
|
|
CONSTRAINT `affiliate_links_program_id_fkey` FOREIGN KEY (`program_id`) REFERENCES `affiliate_programs` (`id`) ON DELETE CASCADE,
|
|
CONSTRAINT `affiliate_links_tool_id_fkey` FOREIGN KEY (`tool_id`) REFERENCES `tools` (`id`) ON DELETE SET NULL,
|
|
CONSTRAINT `affiliate_links_skill_id_fkey` FOREIGN KEY (`skill_id`) REFERENCES `skills` (`id`) ON DELETE SET NULL
|
|
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
|
|
|
CREATE TABLE IF NOT EXISTS `affiliate_clicks` (
|
|
`id` INT NOT NULL AUTO_INCREMENT,
|
|
`link_id` INT NOT NULL,
|
|
`user_id` INT,
|
|
`ip` VARCHAR(191),
|
|
`user_agent` TEXT,
|
|
`ref` VARCHAR(191),
|
|
`created_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
|
PRIMARY KEY (`id`),
|
|
INDEX `affiliate_clicks_link_id_idx` (`link_id`),
|
|
CONSTRAINT `affiliate_clicks_link_id_fkey` FOREIGN KEY (`link_id`) REFERENCES `affiliate_links` (`id`) ON DELETE CASCADE
|
|
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
|
|
|
-- 清理旧的手写裸表(被本迁移的规范化模型取代)
|
|
DROP TABLE IF EXISTS `affiliate_stats`;
|
|
DROP TABLE IF EXISTS `affiliate_clicks_old`;
|