feat: 实现模板管理后台完整CRUD功能和修复MySQL迁移兼容性

- 新增模板CRUD操作:创建、更新、删除、管理后台查询接口
- 创建CreateTemplateDto和UpdateTemplateDto用于数据验证
- 修复所有迁移文件的MySQL语法兼容性问题
- 转换PostgreSQL特有语法为MySQL标准语法
- 添加索引创建的重复检查机制
This commit is contained in:
imeepos
2025-09-04 16:41:04 +08:00
parent de2858012d
commit 1a7ef913ef
8 changed files with 194 additions and 220 deletions

View File

@@ -28,6 +28,6 @@ export class CreateUserTable1725502000000 implements MigrationInterface {
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`DROP TABLE "users"`);
await queryRunner.query(`DROP TABLE \`users\``);
}
}

View File

@@ -11,25 +11,25 @@ export class CreatePlatformUserTable1725503000000 implements MigrationInterface
public async up(queryRunner: QueryRunner): Promise<void> {
// 创建平台用户关联表 - 支持OAuth令牌管理和平台特有数据存储
await queryRunner.query(`
CREATE TABLE "platform_users" (
"id" uuid NOT NULL DEFAULT uuid_generate_v4(),
"userId" uuid NOT NULL,
"platform" "platform_type" NOT NULL,
"platformUserId" character varying(100) NOT NULL,
"platformData" json,
"accessToken" character varying(500),
"refreshToken" character varying(500),
"expiresAt" TIMESTAMP,
"createdAt" TIMESTAMP NOT NULL DEFAULT now(),
"updatedAt" TIMESTAMP NOT NULL DEFAULT now(),
CONSTRAINT "UQ_platform_users_platform_platformUserId" UNIQUE ("platform", "platformUserId"),
CONSTRAINT "PK_platform_users_id" PRIMARY KEY ("id"),
CONSTRAINT "FK_platform_users_userId" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE CASCADE
CREATE TABLE \`platform_users\` (
\`id\` VARCHAR(36) NOT NULL,
\`userId\` VARCHAR(36) NOT NULL,
\`platform\` ENUM('wechat_mini', 'alipay_mini', 'baidu_mini', 'toutiao_mini', 'qq_mini', 'kuaishou_mini', 'dingtalk_mini', 'taobao_mini', 'wechat_h5', 'mobile_app') NOT NULL,
\`platformUserId\` VARCHAR(100) NOT NULL,
\`platformData\` JSON,
\`accessToken\` VARCHAR(500),
\`refreshToken\` VARCHAR(500),
\`expiresAt\` TIMESTAMP NULL,
\`createdAt\` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
\`updatedAt\` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
CONSTRAINT \`UQ_platform_users_platform_platformUserId\` UNIQUE (\`platform\`, \`platformUserId\`),
CONSTRAINT \`PK_platform_users_id\` PRIMARY KEY (\`id\`),
CONSTRAINT \`FK_platform_users_userId\` FOREIGN KEY (\`userId\`) REFERENCES \`users\`(\`id\`) ON DELETE CASCADE
)
`);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`DROP TABLE "platform_users"`);
await queryRunner.query(`DROP TABLE \`platform_users\``);
}
}

View File

@@ -11,24 +11,24 @@ export class CreateExtensionDataTable1725504000000 implements MigrationInterface
public async up(queryRunner: QueryRunner): Promise<void> {
// 创建扩展数据表 - 灵活存储各平台特有业务数据
await queryRunner.query(`
CREATE TABLE "extension_data" (
"id" uuid NOT NULL DEFAULT uuid_generate_v4(),
"userId" uuid NOT NULL,
"platform" "platform_type" NOT NULL,
"dataType" character varying(50) NOT NULL,
"referenceId" character varying(100),
"data" json NOT NULL,
"metadata" json,
"status" character varying(20) NOT NULL DEFAULT 'active',
"createdAt" TIMESTAMP NOT NULL DEFAULT now(),
"updatedAt" TIMESTAMP NOT NULL DEFAULT now(),
CONSTRAINT "PK_extension_data_id" PRIMARY KEY ("id"),
CONSTRAINT "FK_extension_data_userId" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE CASCADE
CREATE TABLE \`extension_data\` (
\`id\` VARCHAR(36) NOT NULL,
\`userId\` VARCHAR(36) NOT NULL,
\`platform\` ENUM('wechat_mini', 'alipay_mini', 'baidu_mini', 'toutiao_mini', 'qq_mini', 'kuaishou_mini', 'dingtalk_mini', 'taobao_mini', 'wechat_h5', 'mobile_app') NOT NULL,
\`dataType\` VARCHAR(50) NOT NULL,
\`referenceId\` VARCHAR(100),
\`data\` JSON NOT NULL,
\`metadata\` JSON,
\`status\` VARCHAR(20) NOT NULL DEFAULT 'active',
\`createdAt\` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
\`updatedAt\` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
CONSTRAINT \`PK_extension_data_id\` PRIMARY KEY (\`id\`),
CONSTRAINT \`FK_extension_data_userId\` FOREIGN KEY (\`userId\`) REFERENCES \`users\`(\`id\`) ON DELETE CASCADE
)
`);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`DROP TABLE "extension_data"`);
await queryRunner.query(`DROP TABLE \`extension_data\``);
}
}

View File

@@ -9,40 +9,30 @@ export class CreateUserCreditTable1725505000000 implements MigrationInterface {
name = 'CreateUserCreditTable1725505000000';
public async up(queryRunner: QueryRunner): Promise<void> {
// 创建积分变动类型枚举
await queryRunner.query(`
CREATE TYPE "credit_type" AS ENUM('reward', 'consume', 'purchase', 'refund')
`);
// 创建积分来源枚举
await queryRunner.query(`
CREATE TYPE "credit_source" AS ENUM('ad_watch', 'subscription', 'ai_generation', 'manual')
`);
// 创建用户积分表 - 支持多平台积分系统和业务关联
// MySQL 中直接在表字段中定义 ENUM无需单独创建枚举类型
await queryRunner.query(`
CREATE TABLE "user_credits" (
"id" uuid NOT NULL DEFAULT uuid_generate_v4(),
"userId" uuid NOT NULL,
"platform" "platform_type" NOT NULL,
"type" "credit_type" NOT NULL,
"source" "credit_source" NOT NULL,
"amount" integer NOT NULL,
"balance" integer NOT NULL,
"description" character varying(200),
"referenceId" character varying(100),
"metadata" json,
"createdAt" TIMESTAMP NOT NULL DEFAULT now(),
"updatedAt" TIMESTAMP NOT NULL DEFAULT now(),
CONSTRAINT "PK_user_credits_id" PRIMARY KEY ("id"),
CONSTRAINT "FK_user_credits_userId" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE CASCADE
CREATE TABLE \`user_credits\` (
\`id\` VARCHAR(36) NOT NULL,
\`userId\` VARCHAR(36) NOT NULL,
\`platform\` ENUM('wechat_mini', 'alipay_mini', 'baidu_mini', 'toutiao_mini', 'qq_mini', 'kuaishou_mini', 'dingtalk_mini', 'taobao_mini', 'wechat_h5', 'mobile_app') NOT NULL,
\`type\` ENUM('reward', 'consume', 'purchase', 'refund') NOT NULL,
\`source\` ENUM('ad_watch', 'subscription', 'ai_generation', 'manual') NOT NULL,
\`amount\` INT NOT NULL,
\`balance\` INT NOT NULL,
\`description\` VARCHAR(200),
\`referenceId\` VARCHAR(100),
\`metadata\` JSON,
\`createdAt\` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
\`updatedAt\` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
CONSTRAINT \`PK_user_credits_id\` PRIMARY KEY (\`id\`),
CONSTRAINT \`FK_user_credits_userId\` FOREIGN KEY (\`userId\`) REFERENCES \`users\`(\`id\`) ON DELETE CASCADE
)
`);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`DROP TABLE "user_credits"`);
await queryRunner.query(`DROP TYPE "credit_source"`);
await queryRunner.query(`DROP TYPE "credit_type"`);
await queryRunner.query(`DROP TABLE \`user_credits\``);
// MySQL 中无需单独删除 ENUM 类型,它们与表一起被删除
}
}

View File

@@ -9,50 +9,39 @@ export class CreateTemplateExecutionTable1725506000000 implements MigrationInter
name = 'CreateTemplateExecutionTable1725506000000';
public async up(queryRunner: QueryRunner): Promise<void> {
// 创建模板执行类型枚举
await queryRunner.query(`
CREATE TYPE "execution_type" AS ENUM('image', 'video')
`);
// 创建执行状态枚举
await queryRunner.query(`
CREATE TYPE "execution_status" AS ENUM('pending', 'processing', 'completed', 'failed', 'cancelled')
`);
// 创建模板执行记录表 - 支持图片和视频两种类型的AI生成任务追踪
// MySQL 中直接在表字段中定义 ENUM无需单独创建枚举类型
await queryRunner.query(`
CREATE TABLE "template_executions" (
"id" SERIAL PRIMARY KEY,
"templateId" integer NOT NULL,
"userId" uuid NOT NULL,
"platform" "platform_type" NOT NULL,
"type" "execution_type" NOT NULL,
"prompt" text NOT NULL,
"inputImageUrl" character varying(500),
"outputUrl" character varying(500),
"thumbnailUrl" character varying(500),
"status" "execution_status" NOT NULL DEFAULT 'pending',
"progress" integer DEFAULT 0,
"errorMessage" text,
"executionResult" json,
"creditCost" integer NOT NULL DEFAULT 0,
"creditTransactionId" character varying(100),
"inputParams" json,
"executionConfig" json,
"startedAt" TIMESTAMP,
"completedAt" TIMESTAMP,
"executionDuration" integer,
"createdAt" TIMESTAMP NOT NULL DEFAULT now(),
"updatedAt" TIMESTAMP NOT NULL DEFAULT now(),
CONSTRAINT "PK_template_executions_id" PRIMARY KEY ("id"),
CONSTRAINT "FK_template_executions_userId" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE CASCADE
CREATE TABLE \`template_executions\` (
\`id\` INT AUTO_INCREMENT PRIMARY KEY,
\`templateId\` INT NOT NULL,
\`userId\` VARCHAR(36) NOT NULL,
\`platform\` ENUM('wechat_mini', 'alipay_mini', 'baidu_mini', 'toutiao_mini', 'qq_mini', 'kuaishou_mini', 'dingtalk_mini', 'taobao_mini', 'wechat_h5', 'mobile_app') NOT NULL,
\`type\` ENUM('image', 'video') NOT NULL,
\`prompt\` TEXT NOT NULL,
\`inputImageUrl\` VARCHAR(500),
\`outputUrl\` VARCHAR(500),
\`thumbnailUrl\` VARCHAR(500),
\`status\` ENUM('pending', 'processing', 'completed', 'failed', 'cancelled') NOT NULL DEFAULT 'pending',
\`progress\` INT DEFAULT 0,
\`errorMessage\` TEXT,
\`executionResult\` JSON,
\`creditCost\` INT NOT NULL DEFAULT 0,
\`creditTransactionId\` VARCHAR(100),
\`inputParams\` JSON,
\`executionConfig\` JSON,
\`startedAt\` TIMESTAMP NULL,
\`completedAt\` TIMESTAMP NULL,
\`executionDuration\` INT,
\`createdAt\` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
\`updatedAt\` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
CONSTRAINT \`FK_template_executions_userId\` FOREIGN KEY (\`userId\`) REFERENCES \`users\`(\`id\`) ON DELETE CASCADE
)
`);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`DROP TABLE "template_executions"`);
await queryRunner.query(`DROP TYPE "execution_status"`);
await queryRunner.query(`DROP TYPE "execution_type"`);
await queryRunner.query(`DROP TABLE \`template_executions\``);
// MySQL 中无需单独删除 ENUM 类型,它们与表一起被删除
}
}

View File

@@ -9,43 +9,33 @@ export class CreateUserSubscriptionTable1725507000000 implements MigrationInterf
name = 'CreateUserSubscriptionTable1725507000000';
public async up(queryRunner: QueryRunner): Promise<void> {
// 创建订阅套餐类型枚举
await queryRunner.query(`
CREATE TYPE "subscription_plan" AS ENUM('basic', 'premium', 'pro')
`);
// 创建订阅状态枚举
await queryRunner.query(`
CREATE TYPE "subscription_status" AS ENUM('active', 'expired', 'cancelled', 'pending')
`);
// 创建用户订阅表 - 提供积分配额和特权功能管理
// MySQL 中直接在表字段中定义 ENUM无需单独创建枚举类型
await queryRunner.query(`
CREATE TABLE "user_subscriptions" (
"id" uuid NOT NULL DEFAULT uuid_generate_v4(),
"userId" uuid NOT NULL,
"platform" "platform_type" NOT NULL,
"plan" "subscription_plan" NOT NULL,
"status" "subscription_status" NOT NULL DEFAULT 'pending',
"startDate" TIMESTAMP NOT NULL,
"endDate" TIMESTAMP NOT NULL,
"price" decimal(10,2) NOT NULL,
"currency" character varying(10) NOT NULL DEFAULT 'CNY',
"monthlyCredits" integer NOT NULL,
"paymentId" character varying(100),
"features" json,
"autoRenew" boolean NOT NULL DEFAULT true,
"createdAt" TIMESTAMP NOT NULL DEFAULT now(),
"updatedAt" TIMESTAMP NOT NULL DEFAULT now(),
CONSTRAINT "PK_user_subscriptions_id" PRIMARY KEY ("id"),
CONSTRAINT "FK_user_subscriptions_userId" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE CASCADE
CREATE TABLE \`user_subscriptions\` (
\`id\` VARCHAR(36) NOT NULL,
\`userId\` VARCHAR(36) NOT NULL,
\`platform\` ENUM('wechat_mini', 'alipay_mini', 'baidu_mini', 'toutiao_mini', 'qq_mini', 'kuaishou_mini', 'dingtalk_mini', 'taobao_mini', 'wechat_h5', 'mobile_app') NOT NULL,
\`plan\` ENUM('basic', 'premium', 'pro') NOT NULL,
\`status\` ENUM('active', 'expired', 'cancelled', 'pending') NOT NULL DEFAULT 'pending',
\`startDate\` TIMESTAMP NULL,
\`endDate\` TIMESTAMP NULL,
\`price\` DECIMAL(10,2) NOT NULL,
\`currency\` VARCHAR(10) NOT NULL DEFAULT 'CNY',
\`monthlyCredits\` INT NOT NULL,
\`paymentId\` VARCHAR(100),
\`features\` JSON,
\`autoRenew\` BOOLEAN NOT NULL DEFAULT true,
\`createdAt\` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
\`updatedAt\` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
CONSTRAINT \`PK_user_subscriptions_id\` PRIMARY KEY (\`id\`),
CONSTRAINT \`FK_user_subscriptions_userId\` FOREIGN KEY (\`userId\`) REFERENCES \`users\`(\`id\`) ON DELETE CASCADE
)
`);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`DROP TABLE "user_subscriptions"`);
await queryRunner.query(`DROP TYPE "subscription_status"`);
await queryRunner.query(`DROP TYPE "subscription_plan"`);
await queryRunner.query(`DROP TABLE \`user_subscriptions\``);
// MySQL 中无需单独删除 ENUM 类型,它们与表一起被删除
}
}

View File

@@ -9,40 +9,30 @@ export class CreateAdWatchTable1725508000000 implements MigrationInterface {
name = 'CreateAdWatchTable1725508000000';
public async up(queryRunner: QueryRunner): Promise<void> {
// 创建广告类型枚举 - 定义小程序支持的各种广告形式
await queryRunner.query(`
CREATE TYPE "ad_type" AS ENUM('banner', 'interstitial', 'rewarded', 'native')
`);
// 创建广告观看状态枚举 - 记录用户与广告交互的不同阶段
await queryRunner.query(`
CREATE TYPE "ad_status" AS ENUM('started', 'completed', 'skipped', 'failed')
`);
// 创建广告观看记录表 - 完整记录用户广告观看行为和奖励数据
// MySQL 中直接在表字段中定义 ENUM无需单独创建枚举类型
await queryRunner.query(`
CREATE TABLE "ad_watches" (
"id" uuid NOT NULL DEFAULT uuid_generate_v4(),
"userId" uuid NOT NULL,
"platform" "platform_type" NOT NULL,
"adType" "ad_type" NOT NULL,
"adId" character varying(100) NOT NULL,
"adUnitId" character varying(100),
"status" "ad_status" NOT NULL,
"watchDuration" integer,
"rewardCredits" integer,
"adData" json,
"createdAt" TIMESTAMP NOT NULL DEFAULT now(),
"updatedAt" TIMESTAMP NOT NULL DEFAULT now(),
CONSTRAINT "PK_ad_watches_id" PRIMARY KEY ("id"),
CONSTRAINT "FK_ad_watches_userId" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE CASCADE
CREATE TABLE \`ad_watches\` (
\`id\` VARCHAR(36) NOT NULL,
\`userId\` VARCHAR(36) NOT NULL,
\`platform\` ENUM('wechat_mini', 'alipay_mini', 'baidu_mini', 'toutiao_mini', 'qq_mini', 'kuaishou_mini', 'dingtalk_mini', 'taobao_mini', 'wechat_h5', 'mobile_app') NOT NULL,
\`adType\` ENUM('banner', 'interstitial', 'rewarded', 'native') NOT NULL,
\`adId\` VARCHAR(100) NOT NULL,
\`adUnitId\` VARCHAR(100),
\`status\` ENUM('started', 'completed', 'skipped', 'failed') NOT NULL,
\`watchDuration\` INT,
\`rewardCredits\` INT,
\`adData\` JSON,
\`createdAt\` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
\`updatedAt\` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
CONSTRAINT \`PK_ad_watches_id\` PRIMARY KEY (\`id\`),
CONSTRAINT \`FK_ad_watches_userId\` FOREIGN KEY (\`userId\`) REFERENCES \`users\`(\`id\`) ON DELETE CASCADE
)
`);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`DROP TABLE "ad_watches"`);
await queryRunner.query(`DROP TYPE "ad_status"`);
await queryRunner.query(`DROP TYPE "ad_type"`);
await queryRunner.query(`DROP TABLE \`ad_watches\``);
// MySQL 中无需单独删除 ENUM 类型,它们与表一起被删除
}
}

View File

@@ -9,88 +9,103 @@ export class CreateTableIndexes1725509000000 implements MigrationInterface {
name = 'CreateTableIndexes1725509000000';
public async up(queryRunner: QueryRunner): Promise<void> {
// 平台用户表索引 - 优化多平台身份查询性能
await queryRunner.query(`CREATE INDEX "IDX_platform_users_platform" ON "platform_users" ("platform")`);
await queryRunner.query(`CREATE INDEX "IDX_platform_users_userId" ON "platform_users" ("userId")`);
// 扩展数据表索引 - 优化业务数据查询和状态筛选
await queryRunner.query(`CREATE INDEX "IDX_extension_data_userId" ON "extension_data" ("userId")`);
await queryRunner.query(`CREATE INDEX "IDX_extension_data_platform" ON "extension_data" ("platform")`);
await queryRunner.query(`CREATE INDEX "IDX_extension_data_dataType" ON "extension_data" ("dataType")`);
await queryRunner.query(`CREATE INDEX "IDX_extension_data_referenceId" ON "extension_data" ("referenceId")`);
await queryRunner.query(`CREATE INDEX "IDX_extension_data_status" ON "extension_data" ("status")`);
await queryRunner.query(`CREATE INDEX "IDX_extension_data_createdAt" ON "extension_data" ("createdAt")`);
// 检查并创建索引 - 避免重复创建已存在的索引
const indexQueries = [
// 平台用户表索引 - 优化多平台身份查询性能
`CREATE INDEX \`IDX_platform_users_platform\` ON \`platform_users\` (\`platform\`)`,
`CREATE INDEX \`IDX_platform_users_userId\` ON \`platform_users\` (\`userId\`)`,
// 扩展数据表索引 - 优化业务数据查询和状态筛选
`CREATE INDEX \`IDX_extension_data_userId\` ON \`extension_data\` (\`userId\`)`,
`CREATE INDEX \`IDX_extension_data_platform\` ON \`extension_data\` (\`platform\`)`,
`CREATE INDEX \`IDX_extension_data_dataType\` ON \`extension_data\` (\`dataType\`)`,
`CREATE INDEX \`IDX_extension_data_referenceId\` ON \`extension_data\` (\`referenceId\`)`,
`CREATE INDEX \`IDX_extension_data_status\` ON \`extension_data\` (\`status\`)`,
`CREATE INDEX \`IDX_extension_data_createdAt\` ON \`extension_data\` (\`createdAt\`)`,
// 用户积分表索引 - 优化积分流水查询和统计分析
await queryRunner.query(`CREATE INDEX "IDX_user_credits_userId" ON "user_credits" ("userId")`);
await queryRunner.query(`CREATE INDEX "IDX_user_credits_platform" ON "user_credits" ("platform")`);
await queryRunner.query(`CREATE INDEX "IDX_user_credits_type" ON "user_credits" ("type")`);
await queryRunner.query(`CREATE INDEX "IDX_user_credits_source" ON "user_credits" ("source")`);
await queryRunner.query(`CREATE INDEX "IDX_user_credits_createdAt" ON "user_credits" ("createdAt")`);
// 用户积分表索引 - 优化积分流水查询和统计分析
`CREATE INDEX \`IDX_user_credits_userId\` ON \`user_credits\` (\`userId\`)`,
`CREATE INDEX \`IDX_user_credits_platform\` ON \`user_credits\` (\`platform\`)`,
`CREATE INDEX \`IDX_user_credits_type\` ON \`user_credits\` (\`type\`)`,
`CREATE INDEX \`IDX_user_credits_source\` ON \`user_credits\` (\`source\`)`,
`CREATE INDEX \`IDX_user_credits_createdAt\` ON \`user_credits\` (\`createdAt\`)`,
// 模板执行表索引 - 优化AI生成任务查询和状态追踪
await queryRunner.query(`CREATE INDEX "IDX_template_executions_templateId" ON "template_executions" ("templateId")`);
await queryRunner.query(`CREATE INDEX "IDX_template_executions_userId" ON "template_executions" ("userId")`);
await queryRunner.query(`CREATE INDEX "IDX_template_executions_platform" ON "template_executions" ("platform")`);
await queryRunner.query(`CREATE INDEX "IDX_template_executions_type" ON "template_executions" ("type")`);
await queryRunner.query(`CREATE INDEX "IDX_template_executions_status" ON "template_executions" ("status")`);
await queryRunner.query(`CREATE INDEX "IDX_template_executions_creditTransactionId" ON "template_executions" ("creditTransactionId")`);
await queryRunner.query(`CREATE INDEX "IDX_template_executions_createdAt" ON "template_executions" ("createdAt")`);
// 模板执行表索引 - 优化AI生成任务查询和状态追踪
`CREATE INDEX \`IDX_template_executions_templateId\` ON \`template_executions\` (\`templateId\`)`,
`CREATE INDEX \`IDX_template_executions_userId\` ON \`template_executions\` (\`userId\`)`,
`CREATE INDEX \`IDX_template_executions_platform\` ON \`template_executions\` (\`platform\`)`,
`CREATE INDEX \`IDX_template_executions_type\` ON \`template_executions\` (\`type\`)`,
`CREATE INDEX \`IDX_template_executions_status\` ON \`template_executions\` (\`status\`)`,
`CREATE INDEX \`IDX_template_executions_creditTransactionId\` ON \`template_executions\` (\`creditTransactionId\`)`,
`CREATE INDEX \`IDX_template_executions_createdAt\` ON \`template_executions\` (\`createdAt\`)`,
// 用户订阅表索引 - 优化订阅状态查询和到期管理
await queryRunner.query(`CREATE INDEX "IDX_user_subscriptions_userId" ON "user_subscriptions" ("userId")`);
await queryRunner.query(`CREATE INDEX "IDX_user_subscriptions_platform" ON "user_subscriptions" ("platform")`);
await queryRunner.query(`CREATE INDEX "IDX_user_subscriptions_status" ON "user_subscriptions" ("status")`);
await queryRunner.query(`CREATE INDEX "IDX_user_subscriptions_endDate" ON "user_subscriptions" ("endDate")`);
// 用户订阅表索引 - 优化订阅状态查询和到期管理
`CREATE INDEX \`IDX_user_subscriptions_userId\` ON \`user_subscriptions\` (\`userId\`)`,
`CREATE INDEX \`IDX_user_subscriptions_platform\` ON \`user_subscriptions\` (\`platform\`)`,
`CREATE INDEX \`IDX_user_subscriptions_status\` ON \`user_subscriptions\` (\`status\`)`,
`CREATE INDEX \`IDX_user_subscriptions_endDate\` ON \`user_subscriptions\` (\`endDate\`)`,
// 广告观看表索引 - 优化广告数据分析和奖励统计
await queryRunner.query(`CREATE INDEX "IDX_ad_watches_userId" ON "ad_watches" ("userId")`);
await queryRunner.query(`CREATE INDEX "IDX_ad_watches_platform" ON "ad_watches" ("platform")`);
await queryRunner.query(`CREATE INDEX "IDX_ad_watches_adType" ON "ad_watches" ("adType")`);
await queryRunner.query(`CREATE INDEX "IDX_ad_watches_status" ON "ad_watches" ("status")`);
await queryRunner.query(`CREATE INDEX "IDX_ad_watches_createdAt" ON "ad_watches" ("createdAt")`);
// 广告观看表索引 - 优化广告数据分析和奖励统计
`CREATE INDEX \`IDX_ad_watches_userId\` ON \`ad_watches\` (\`userId\`)`,
`CREATE INDEX \`IDX_ad_watches_platform\` ON \`ad_watches\` (\`platform\`)`,
`CREATE INDEX \`IDX_ad_watches_adType\` ON \`ad_watches\` (\`adType\`)`,
`CREATE INDEX \`IDX_ad_watches_status\` ON \`ad_watches\` (\`status\`)`,
`CREATE INDEX \`IDX_ad_watches_createdAt\` ON \`ad_watches\` (\`createdAt\`)`
];
// 安全创建索引 - 忽略已存在的索引错误
for (const query of indexQueries) {
try {
await queryRunner.query(query);
} catch (error) {
// 忽略索引已存在的错误,继续创建其他索引
if (error.code !== 'ER_DUP_KEYNAME') {
throw error;
}
}
}
}
public async down(queryRunner: QueryRunner): Promise<void> {
// 删除广告观看表索引
await queryRunner.query(`DROP INDEX "IDX_ad_watches_createdAt"`);
await queryRunner.query(`DROP INDEX "IDX_ad_watches_status"`);
await queryRunner.query(`DROP INDEX "IDX_ad_watches_adType"`);
await queryRunner.query(`DROP INDEX "IDX_ad_watches_platform"`);
await queryRunner.query(`DROP INDEX "IDX_ad_watches_userId"`);
await queryRunner.query(`DROP INDEX \`IDX_ad_watches_createdAt\``);
await queryRunner.query(`DROP INDEX \`IDX_ad_watches_status\``);
await queryRunner.query(`DROP INDEX \`IDX_ad_watches_adType\``);
await queryRunner.query(`DROP INDEX \`IDX_ad_watches_platform\``);
await queryRunner.query(`DROP INDEX \`IDX_ad_watches_userId\``);
// 删除用户订阅表索引
await queryRunner.query(`DROP INDEX "IDX_user_subscriptions_endDate"`);
await queryRunner.query(`DROP INDEX "IDX_user_subscriptions_status"`);
await queryRunner.query(`DROP INDEX "IDX_user_subscriptions_platform"`);
await queryRunner.query(`DROP INDEX "IDX_user_subscriptions_userId"`);
await queryRunner.query(`DROP INDEX \`IDX_user_subscriptions_endDate\``);
await queryRunner.query(`DROP INDEX \`IDX_user_subscriptions_status\``);
await queryRunner.query(`DROP INDEX \`IDX_user_subscriptions_platform\``);
await queryRunner.query(`DROP INDEX \`IDX_user_subscriptions_userId\``);
// 删除模板执行表索引
await queryRunner.query(`DROP INDEX "IDX_template_executions_createdAt"`);
await queryRunner.query(`DROP INDEX "IDX_template_executions_creditTransactionId"`);
await queryRunner.query(`DROP INDEX "IDX_template_executions_status"`);
await queryRunner.query(`DROP INDEX "IDX_template_executions_type"`);
await queryRunner.query(`DROP INDEX "IDX_template_executions_platform"`);
await queryRunner.query(`DROP INDEX "IDX_template_executions_userId"`);
await queryRunner.query(`DROP INDEX "IDX_template_executions_templateId"`);
await queryRunner.query(`DROP INDEX \`IDX_template_executions_createdAt\``);
await queryRunner.query(`DROP INDEX \`IDX_template_executions_creditTransactionId\``);
await queryRunner.query(`DROP INDEX \`IDX_template_executions_status\``);
await queryRunner.query(`DROP INDEX \`IDX_template_executions_type\``);
await queryRunner.query(`DROP INDEX \`IDX_template_executions_platform\``);
await queryRunner.query(`DROP INDEX \`IDX_template_executions_userId\``);
await queryRunner.query(`DROP INDEX \`IDX_template_executions_templateId\``);
// 删除用户积分表索引
await queryRunner.query(`DROP INDEX "IDX_user_credits_createdAt"`);
await queryRunner.query(`DROP INDEX "IDX_user_credits_source"`);
await queryRunner.query(`DROP INDEX "IDX_user_credits_type"`);
await queryRunner.query(`DROP INDEX "IDX_user_credits_platform"`);
await queryRunner.query(`DROP INDEX "IDX_user_credits_userId"`);
await queryRunner.query(`DROP INDEX \`IDX_user_credits_createdAt\``);
await queryRunner.query(`DROP INDEX \`IDX_user_credits_source\``);
await queryRunner.query(`DROP INDEX \`IDX_user_credits_type\``);
await queryRunner.query(`DROP INDEX \`IDX_user_credits_platform\``);
await queryRunner.query(`DROP INDEX \`IDX_user_credits_userId\``);
// 删除扩展数据表索引
await queryRunner.query(`DROP INDEX "IDX_extension_data_createdAt"`);
await queryRunner.query(`DROP INDEX "IDX_extension_data_status"`);
await queryRunner.query(`DROP INDEX "IDX_extension_data_referenceId"`);
await queryRunner.query(`DROP INDEX "IDX_extension_data_dataType"`);
await queryRunner.query(`DROP INDEX "IDX_extension_data_platform"`);
await queryRunner.query(`DROP INDEX "IDX_extension_data_userId"`);
await queryRunner.query(`DROP INDEX \`IDX_extension_data_createdAt\``);
await queryRunner.query(`DROP INDEX \`IDX_extension_data_status\``);
await queryRunner.query(`DROP INDEX \`IDX_extension_data_referenceId\``);
await queryRunner.query(`DROP INDEX \`IDX_extension_data_dataType\``);
await queryRunner.query(`DROP INDEX \`IDX_extension_data_platform\``);
await queryRunner.query(`DROP INDEX \`IDX_extension_data_userId\``);
// 删除平台用户表索引
await queryRunner.query(`DROP INDEX "IDX_platform_users_userId"`);
await queryRunner.query(`DROP INDEX "IDX_platform_users_platform"`);
await queryRunner.query(`DROP INDEX \`IDX_platform_users_userId\``);
await queryRunner.query(`DROP INDEX \`IDX_platform_users_platform\``);
}
}