import { sqliteTable, text, integer, real, primaryKey, index, uniqueIndex, } from "drizzle-orm/sqlite-core"; import { users } from "./auth"; // ============ CardType ENUM ============ export const CardTypes = [ "text", "image", "image-text", "portfolio", "project", ] as const; export type CardType = (typeof CardTypes)[number]; // ============ Category(分类表)============ export const categories = sqliteTable( "categories", { id: text("id").primaryKey(), // UUID name: text("name", { length: 100 }).notNull(), slug: text("slug", { length: 100 }).notNull(), image: text("image", { length: 500 }), parentId: text("parent_id"), // 自引用 FK,NULL=顶级 sortOrder: integer("sort_order").default(0).notNull(), count: integer("count").default(0).notNull(), createdAt: integer("created_at", { mode: "timestamp_ms" }) .defaultNow() .notNull(), updatedAt: integer("updated_at", { mode: "timestamp_ms" }) .defaultNow() .$onUpdate(() => new Date()) .notNull(), }, (table) => [ uniqueIndex("idx_category_slug").on(table.slug), index("idx_category_parent").on(table.parentId), ], ); // ============ Card(卡片表)============ export const cards = sqliteTable( "cards", { id: integer("id").primaryKey({ autoIncrement: true }), type: text("type", { enum: CardTypes }).notNull(), title: text("title", { length: 255 }).notNull(), description: text("description"), aspectRatio: real("aspect_ratio"), categoryId: text("category_id").references(() => categories.id), createdAt: integer("created_at", { mode: "timestamp_ms" }) .defaultNow() .notNull(), updatedAt: integer("updated_at", { mode: "timestamp_ms" }) .defaultNow() .$onUpdate(() => new Date()) .notNull(), }, (table) => [ index("idx_card_category").on(table.categoryId), index("idx_card_type").on(table.type), index("idx_card_created").on(table.createdAt), ], ); // ============ CardImage(卡片图片表)============ export const cardImages = sqliteTable( "card_images", { id: integer("id").primaryKey({ autoIncrement: true }), cardId: integer("card_id") .notNull() .references(() => cards.id), url: text("url", { length: 500 }).notNull(), sortOrder: integer("sort_order").default(0).notNull(), }, (table) => [index("idx_card_image_card").on(table.cardId)], ); // ============ Tag(标签表)============ export const tags = sqliteTable( "tags", { id: integer("id").primaryKey({ autoIncrement: true }), name: text("name", { length: 50 }).notNull(), slug: text("slug", { length: 50 }).notNull(), }, (table) => [uniqueIndex("idx_tag_slug").on(table.slug)], ); // ============ CardTag(卡片-标签关联表)============ export const cardTags = sqliteTable( "card_tags", { cardId: integer("card_id") .notNull() .references(() => cards.id), tagId: integer("tag_id") .notNull() .references(() => tags.id), }, (table) => [ primaryKey({ name: "card_tag_pk", columns: [table.cardId, table.tagId] }), index("idx_card_tag_card").on(table.cardId), index("idx_card_tag_tag").on(table.tagId), ], ); // ============ Favorite(收藏表)============ export const favorites = sqliteTable( "favorites", { userId: integer("user_id") .notNull() .references(() => users.id, { onDelete: "cascade" }), cardId: integer("card_id") .notNull() .references(() => cards.id, { onDelete: "cascade" }), createdAt: integer("created_at", { mode: "timestamp_ms" }) .defaultNow() .notNull(), }, (table) => [ primaryKey({ name: "favorite_pk", columns: [table.userId, table.cardId] }), index("idx_favorite_user").on(table.userId), index("idx_favorite_card").on(table.cardId), ], ); // ============ Tool(工具项表)============ export const tools = sqliteTable("tools", { id: text("id").primaryKey(), // UUID name: text("name", { length: 50 }).notNull(), slug: text("slug", { length: 50 }).notNull(), icon: text("icon", { length: 100 }), sortOrder: integer("sort_order").default(0).notNull(), });