import { sql } from "drizzle-orm"; import { datetime, index, int, mysqlTable, text, uniqueIndex, varchar, } from "drizzle-orm/mysql-core"; const timestamp = (name: string) => datetime(name, { mode: "string", fsp: 3 }) .notNull() .default(sql`CURRENT_TIMESTAMP(3)`); export const partners = mysqlTable("partners", { id: varchar("id", { length: 64 }).primaryKey(), name: varchar("name", { length: 255 }).notNull(), wecomName: varchar("wecom_name", { length: 255 }).notNull(), owner: varchar("owner", { length: 255 }).notNull().default("运营组"), claimedTotal: int("claimed_total").notNull().default(0), completedTotal: int("completed_total").notNull().default(0), createdAt: timestamp("created_at"), }); export const tasks = mysqlTable( "tasks", { id: varchar("id", { length: 64 }).primaryKey(), name: varchar("name", { length: 255 }).notNull(), brand: varchar("brand", { length: 255 }).notNull(), quantity: int("quantity").notNull(), claimedQuantity: int("claimed_quantity").notNull().default(0), dueAt: varchar("due_at", { length: 32 }).notNull(), status: varchar("status", { length: 32 }).notNull().default("active"), taskType: varchar("task_type", { length: 32 }) .notNull() .default("content_publish"), platform: varchar("platform", { length: 32 }).notNull().default("小红书"), contentFormat: varchar("content_format", { length: 32 }) .notNull() .default("image_text"), sourceUrl: text("source_url").notNull(), sourceSheetId: varchar("source_sheet_id", { length: 255 }).notNull().default(""), sourceSheetName: varchar("source_sheet_name", { length: 255 }).notNull().default(""), sourceSyncedAt: datetime("source_synced_at", { mode: "string", fsp: 3 }), shareToken: varchar("share_token", { length: 128 }), collectionStartDate: varchar("collection_start_date", { length: 32 }), collectionDays: text("collection_days").notNull(), collectionScheduleUpdatedAt: datetime("collection_schedule_updated_at", { mode: "string", fsp: 3, }), createdAt: timestamp("created_at"), }, (table) => [uniqueIndex("tasks_share_token_idx").on(table.shareToken)], ); export const contents = mysqlTable("contents", { id: varchar("id", { length: 64 }).primaryKey(), taskId: varchar("task_id", { length: 64 }).notNull(), title: text("title").notNull(), body: text("body").notNull(), imageAssets: text("image_assets").notNull(), videoAssets: text("video_assets").notNull(), status: varchar("status", { length: 32 }).notNull().default("available"), source: varchar("source", { length: 255 }).notNull().default("飞书内容表"), sourceRow: int("source_row"), createdAt: timestamp("created_at"), }); export const accounts = mysqlTable( "accounts", { id: varchar("id", { length: 64 }).primaryKey(), platform: varchar("platform", { length: 32 }).notNull().default("小红书"), platformUid: varchar("platform_uid", { length: 255 }).notNull(), publicAccountId: varchar("public_account_id", { length: 255 }).notNull().default(""), nickname: varchar("nickname", { length: 255 }).notNull(), profileUrl: text("profile_url").notNull(), ipLocation: varchar("ip_location", { length: 255 }).notNull().default("待识别"), followers: int("followers").notNull().default(0), gender: varchar("gender", { length: 16 }).notNull().default(""), bio: text("bio").notNull().default(""), tags: varchar("tags", { length: 500 }).notNull().default(""), postCount: int("post_count").notNull().default(0), avgViews: int("avg_views").notNull().default(0), cooperationSource: varchar("cooperation_source", { length: 500 }) .notNull() .default(""), currentContact: varchar("current_contact", { length: 255 }) .notNull() .default(""), firstSeenAt: timestamp("first_seen_at"), lastSeenAt: timestamp("last_seen_at"), }, (table) => [ uniqueIndex("accounts_platform_uid_idx").on(table.platform, table.platformUid), ], ); export const claims = mysqlTable( "claims", { id: varchar("id", { length: 64 }).primaryKey(), taskId: varchar("task_id", { length: 64 }).notNull(), partnerId: varchar("partner_id", { length: 64 }).notNull(), claimantName: varchar("claimant_name", { length: 255 }).notNull(), claimToken: varchar("claim_token", { length: 128 }).notNull(), quantity: int("quantity").notNull(), createdAt: timestamp("created_at"), }, (table) => [ uniqueIndex("claims_claim_token_idx").on(table.claimToken), index("claims_task_partner_created_idx").on( table.taskId, table.partnerId, table.createdAt, ), ], ); export const delegationBundles = mysqlTable( "delegation_bundles", { id: varchar("id", { length: 64 }).primaryKey(), taskId: varchar("task_id", { length: 64 }).notNull(), claimId: varchar("claim_id", { length: 64 }).notNull(), partnerId: varchar("partner_id", { length: 64 }).notNull(), label: varchar("label", { length: 255 }).notNull(), shareToken: varchar("share_token", { length: 128 }).notNull(), quantity: int("quantity").notNull(), status: varchar("status", { length: 32 }).notNull().default("active"), createdAt: timestamp("created_at"), updatedAt: timestamp("updated_at"), revokedAt: datetime("revoked_at", { mode: "string", fsp: 3 }), }, (table) => [ uniqueIndex("delegation_bundles_share_token_idx").on(table.shareToken), index("delegation_bundles_claim_created_idx").on(table.claimId, table.createdAt), ], ); export const distributions = mysqlTable("distributions", { id: varchar("id", { length: 64 }).primaryKey(), taskId: varchar("task_id", { length: 64 }).notNull(), contentId: varchar("content_id", { length: 64 }).notNull(), partnerId: varchar("partner_id", { length: 64 }).notNull(), claimId: varchar("claim_id", { length: 64 }), delegationBundleId: varchar("delegation_bundle_id", { length: 64 }), accountId: varchar("account_id", { length: 64 }), publishUrl: text("publish_url"), publishTime: datetime("publish_time", { mode: "string", fsp: 3 }), publishScreenshotKey: varchar("publish_screenshot_key", { length: 512 }), resultScreenshotKey: text("result_screenshot_key"), resultSubmittedAt: datetime("result_submitted_at", { mode: "string", fsp: 3 }), status: varchar("status", { length: 32 }).notNull().default("claimed"), claimedAt: timestamp("claimed_at"), screenshotKey: varchar("screenshot_key", { length: 512 }), ocrStatus: varchar("ocr_status", { length: 32 }).notNull().default("none"), exposure: int("exposure"), views: int("views"), d2Likes: int("d2_likes"), d2Comments: int("d2_comments"), d2Collects: int("d2_collects"), d5Likes: int("d5_likes"), d5Comments: int("d5_comments"), d5Collects: int("d5_collects"), d7Likes: int("d7_likes"), d7Comments: int("d7_comments"), d7Collects: int("d7_collects"), latestLikes: int("latest_likes"), latestComments: int("latest_comments"), latestCollects: int("latest_collects"), latestShares: int("latest_shares"), collectionStatus: varchar("collection_status", { length: 32 }) .notNull() .default("pending"), collectionStatusDescription: text("collection_status_description"), collectionUpdatedAt: datetime("collection_updated_at", { mode: "string", fsp: 3 }), lastCollectionDay: int("last_collection_day"), updatedAt: timestamp("updated_at"), }); export const collectionRuns = mysqlTable( "collection_runs", { id: varchar("id", { length: 64 }).primaryKey(), taskId: varchar("task_id", { length: 64 }).notNull(), distributionId: varchar("distribution_id", { length: 64 }).notNull(), scheduledDate: varchar("scheduled_date", { length: 32 }).notNull(), scheduleDay: int("schedule_day"), scheduledAt: datetime("scheduled_at", { mode: "string", fsp: 3 }).notNull(), status: varchar("status", { length: 32 }).notNull().default("pending"), likes: int("likes"), comments: int("comments"), collects: int("collects"), shares: int("shares"), statusDescription: text("status_description"), startedAt: datetime("started_at", { mode: "string", fsp: 3 }), completedAt: datetime("completed_at", { mode: "string", fsp: 3 }), createdAt: timestamp("created_at"), }, (table) => [ uniqueIndex("collection_runs_distribution_date_idx").on( table.distributionId, table.scheduledDate, ), index("collection_runs_task_date_idx").on(table.taskId, table.scheduledDate), ], ); export const users = mysqlTable( "users", { id: varchar("id", { length: 64 }).primaryKey(), username: varchar("username", { length: 255 }).notNull(), passwordHash: varchar("password_hash", { length: 255 }).notNull(), passwordSalt: varchar("password_salt", { length: 255 }).notNull(), passwordIterations: int("password_iterations").notNull(), role: varchar("role", { length: 32 }).notNull(), createdAt: timestamp("created_at"), updatedAt: timestamp("updated_at"), }, (table) => [uniqueIndex("users_username_idx").on(table.username)], ); export const authSessions = mysqlTable( "auth_sessions", { tokenHash: varchar("token_hash", { length: 128 }).primaryKey(), userId: varchar("user_id", { length: 64 }).notNull(), expiresAt: datetime("expires_at", { mode: "string", fsp: 3 }).notNull(), createdAt: timestamp("created_at"), }, (table) => [ index("auth_sessions_user_id_idx").on(table.userId), index("auth_sessions_expires_at_idx").on(table.expiresAt), ], ); export const mcpExportTokens = mysqlTable( "mcp_export_tokens", { tokenHash: varchar("token_hash", { length: 128 }).primaryKey(), kind: varchar("kind", { length: 64 }).notNull(), payload: text("payload").notNull(), expiresAt: datetime("expires_at", { mode: "string", fsp: 3 }).notNull(), createdAt: timestamp("created_at"), }, (table) => [index("mcp_export_tokens_expires_at_idx").on(table.expiresAt)], ); export const backgroundJobs = mysqlTable( "background_jobs", { id: varchar("id", { length: 64 }).primaryKey(), type: varchar("type", { length: 64 }).notNull(), payload: text("payload").notNull(), status: varchar("status", { length: 32 }).notNull().default("pending"), attempts: int("attempts").notNull().default(0), availableAt: datetime("available_at", { mode: "string", fsp: 3 }).notNull(), lockedAt: datetime("locked_at", { mode: "string", fsp: 3 }), completedAt: datetime("completed_at", { mode: "string", fsp: 3 }), lastError: text("last_error"), createdAt: timestamp("created_at"), updatedAt: timestamp("updated_at"), }, (table) => [index("background_jobs_pending_idx").on(table.status, table.availableAt)], );