/** * DusunIoT 重建版 PostgreSQL 数据模型(Drizzle ORM) * * 按业务域组织:content / products / commerce / inquiries / ops。 * 每张表保留 legacy_id 以便对照原 WordPress 数据并支持增量同步。 */ import { pgTable, serial, varchar, text, integer, bigint, boolean, timestamp, numeric, jsonb, index, uniqueIndex, primaryKey, } from "drizzle-orm/pg-core"; /* ============================= 内容域 ============================= */ /** # 数据库表 * 内容主表(页面 page / 文章 post / 落地页 landing),默认语言(英文)的正本。 * Elementor 原始 JSON 存于 meta.elementor,供 1:1 还原渲染器使用。 */ export const contents = pgTable( "contents", { /** # 数据库字段 内容 ID */ id: serial("id").primaryKey(), /** # 数据库字段 内容类型:page | post | landing */ type: varchar("type", { length: 32 }).notNull(), /** # 数据库字段 URL 别名(默认语言) */ slug: varchar("slug", { length: 255 }).notNull(), /** # 数据库字段 标题 */ title: text("title").notNull(), /** # 数据库字段 摘要 */ excerpt: text("excerpt").default("").notNull(), /** # 数据库字段 正文 HTML */ html: text("html").default("").notNull(), /** # 数据库字段 状态:draft | review | published */ status: varchar("status", { length: 16 }).default("published").notNull(), /** # 数据库字段 作者 */ authorId: integer("author_id"), /** # 数据库字段 特色图片 */ featuredMediaId: integer("featured_media_id"), /** # 数据库字段 页面模板名(home / product / blog / blank …) */ template: varchar("template", { length: 64 }).default("default").notNull(), /** # 数据库字段 菜单排序 */ menuOrder: integer("menu_order").default(0).notNull(), /** # 数据库字段 浏览次数 */ views: integer("views").default(0).notNull(), /** # 数据库字段 是否置顶 */ sticky: boolean("sticky").default(false).notNull(), /** # 数据库字段 SEO 标题 */ seoTitle: text("seo_title"), /** # 数据库字段 SEO 描述 */ seoDescription: text("seo_description"), /** # 数据库字段 扩展数据(elementor JSON 等) */ meta: jsonb("meta").default({}).notNull(), /** # 数据库字段 原 WordPress post ID */ legacyId: integer("legacy_id"), /** # 数据库字段 发布时间 */ publishedAt: timestamp("published_at", { withTimezone: true }), /** # 数据库字段 创建时间 */ createdAt: timestamp("created_at", { withTimezone: true }).defaultNow().notNull(), /** # 数据库字段 更新时间 */ updatedAt: timestamp("updated_at", { withTimezone: true }).defaultNow().notNull(), }, (t) => [ uniqueIndex("contents_slug_type_idx").on(t.slug, t.type), index("contents_type_status_idx").on(t.type, t.status), index("contents_legacy_idx").on(t.legacyId), ], ); /** # 数据库表 * 内容多语言翻译版本(每种语言独立 slug/标题/正文/SEO;缺翻译时不生成伪语言页面)。 */ export const contentTranslations = pgTable( "content_translations", { /** # 数据库字段 翻译 ID */ id: serial("id").primaryKey(), /** # 数据库字段 内容 ID */ contentId: integer("content_id").notNull(), /** # 数据库字段 语言代码(BCP47,如 fr / de) */ lang: varchar("lang", { length: 16 }).notNull(), /** # 数据库字段 该语言的 URL 别名 */ slug: varchar("slug", { length: 255 }).notNull(), /** # 数据库字段 标题 */ title: text("title").notNull(), /** # 数据库字段 摘要 */ excerpt: text("excerpt").default("").notNull(), /** # 数据库字段 正文 HTML */ html: text("html").default("").notNull(), /** # 数据库字段 状态:draft | review | published */ status: varchar("status", { length: 16 }).default("draft").notNull(), /** # 数据库字段 SEO 标题 */ seoTitle: text("seo_title"), /** # 数据库字段 SEO 描述 */ seoDescription: text("seo_description"), /** # 数据库字段 翻译时间 */ createdAt: timestamp("created_at", { withTimezone: true }).defaultNow().notNull(), /** # 数据库字段 更新时间 */ updatedAt: timestamp("updated_at", { withTimezone: true }).defaultNow().notNull(), }, (t) => [ uniqueIndex("content_translations_content_lang_idx").on(t.contentId, t.lang), index("content_translations_lang_status_idx").on(t.lang, t.status), ], ); /** # 数据库表 * 内容修订快照(发布前留档,支持回滚)。 */ export const contentRevisions = pgTable("content_revisions", { /** # 数据库字段 修订 ID */ id: serial("id").primaryKey(), /** # 数据库字段 内容 ID */ contentId: integer("content_id").notNull(), /** # 数据库字段 语言(缺省为默认语言) */ lang: varchar("lang", { length: 16 }).default("en").notNull(), /** # 数据库字段 标题快照 */ title: text("title").notNull(), /** # 数据库字段 正文 HTML 快照 */ html: text("html").notNull(), /** # 数据库字段 修订人 */ authorId: integer("author_id"), /** # 数据库字段 修订时间 */ createdAt: timestamp("created_at", { withTimezone: true }).defaultNow().notNull(), }); /** # 数据库表 * 分类/标签(taxonomy:category / post_tag / product_cat / product_tag / 属性 pa_*)。 */ export const categories = pgTable( "categories", { /** # 数据库字段 分类 ID */ id: serial("id").primaryKey(), /** # 数据库字段 taxonomy 名称 */ taxonomy: varchar("taxonomy", { length: 64 }).notNull(), /** # 数据库字段 名称 */ name: varchar("name", { length: 255 }).notNull(), /** # 数据库字段 URL 别名 */ slug: varchar("slug", { length: 255 }).notNull(), /** # 数据库字段 父级分类 */ parentId: integer("parent_id"), /** # 数据库字段 描述 */ description: text("description").default("").notNull(), /** # 数据库字段 分类图片 */ imageMediaId: integer("image_media_id"), /** # 数据库字段 排序 */ sort: integer("sort").default(0).notNull(), /** # 数据库字段 原 WordPress term_id */ legacyId: integer("legacy_id"), }, (t) => [ uniqueIndex("categories_taxonomy_slug_idx").on(t.taxonomy, t.slug), index("categories_parent_idx").on(t.parentId), ], ); /** # 数据库表 * 内容与分类/标签的关联。 */ export const contentTerms = pgTable( "content_terms", { /** # 数据库字段 内容 ID */ contentId: integer("content_id").notNull(), /** # 数据库字段 分类 ID */ categoryId: integer("category_id").notNull(), }, (t) => [ primaryKey({ columns: [t.contentId, t.categoryId] }), index("content_terms_category_idx").on(t.categoryId), ], ); /** # 数据库表 * 导航菜单定义(header / footer / account 等位置)。 */ export const menus = pgTable("menus", { /** # 数据库字段 菜单 ID */ id: serial("id").primaryKey(), /** # 数据库字段 菜单名称 */ name: varchar("name", { length: 128 }).notNull(), /** # 数据库字段 位置别名(menu-1 / menu-2 / max_mega_menu_1 …) */ location: varchar("location", { length: 64 }).notNull(), /** # 数据库字段 原菜单 term_id */ legacyId: integer("legacy_id"), }); /** # 数据库表 * 菜单项(支持多级树)。 */ export const menuItems = pgTable( "menu_items", { /** # 数据库字段 菜单项 ID */ id: serial("id").primaryKey(), /** # 数据库字段 所属菜单 */ menuId: integer("menu_id").notNull(), /** # 数据库字段 父菜单项 */ parentId: integer("parent_id"), /** # 数据库字段 显示文字 */ title: varchar("title", { length: 255 }).notNull(), /** # 数据库字段 链接地址 */ url: text("url").notNull(), /** # 数据库字段 打开方式:_self | _blank */ target: varchar("target", { length: 16 }).default("_self").notNull(), /** # 数据库字段 排序 */ sort: integer("sort").default(0).notNull(), /** # 数据库字段 原 menu_item post_id */ legacyId: integer("legacy_id"), }, (t) => [index("menu_items_menu_idx").on(t.menuId, t.sort)], ); /* ============================= 产品域 ============================= */ /** # 数据库表 * 产品主表(WooCommerce 迁移)。 */ export const products = pgTable( "products", { /** # 数据库字段 产品 ID */ id: serial("id").primaryKey(), /** # 数据库字段 SKU */ sku: varchar("sku", { length: 128 }), /** # 数据库字段 URL 别名 */ slug: varchar("slug", { length: 255 }).notNull(), /** # 数据库字段 名称 */ title: text("title").notNull(), /** # 数据库字段 短描述 */ shortDescription: text("short_description").default("").notNull(), /** # 数据库字段 详细描述 HTML */ description: text("description").default("").notNull(), /** # 数据库字段 现价 */ price: numeric("price", { precision: 12, scale: 2 }), /** # 数据库字段 原价 */ regularPrice: numeric("regular_price", { precision: 12, scale: 2 }), /** # 数据库字段 库存数量 */ stock: integer("stock"), /** # 数据库字段 库存状态:instock | outofstock | onbackorder */ stockStatus: varchar("stock_status", { length: 32 }).default("instock").notNull(), /** # 数据库字段 特色图片 */ featuredMediaId: integer("featured_media_id"), /** # 数据库字段 图廊(媒体 ID 数组) */ gallery: jsonb("gallery").default([]).notNull(), /** # 数据库字段 状态:draft | published */ status: varchar("status", { length: 16 }).default("published").notNull(), /** # 数据库字段 是否主推产品 */ featured: boolean("featured").default(false).notNull(), /** # 数据库字段 浏览次数 */ views: integer("views").default(0).notNull(), /** # 数据库字段 SEO 标题 */ seoTitle: text("seo_title"), /** # 数据库字段 SEO 描述 */ seoDescription: text("seo_description"), /** # 数据库字段 规格书下载地址 */ specUrl: text("spec_url"), /** # 数据库字段 Elementor 原始 JSON */ meta: jsonb("meta").default({}).notNull(), /** # 数据库字段 原 WordPress post ID */ legacyId: integer("legacy_id"), /** # 数据库字段 创建时间 */ createdAt: timestamp("created_at", { withTimezone: true }).defaultNow().notNull(), /** # 数据库字段 更新时间 */ updatedAt: timestamp("updated_at", { withTimezone: true }).defaultNow().notNull(), }, (t) => [ uniqueIndex("products_slug_idx").on(t.slug), index("products_status_idx").on(t.status), index("products_sku_idx").on(t.sku), index("products_legacy_idx").on(t.legacyId), ], ); /** # 数据库表 * 产品多语言翻译。 */ export const productTranslations = pgTable( "product_translations", { /** # 数据库字段 翻译 ID */ id: serial("id").primaryKey(), /** # 数据库字段 产品 ID */ productId: integer("product_id").notNull(), /** # 数据库字段 语言代码 */ lang: varchar("lang", { length: 16 }).notNull(), /** # 数据库字段 该语言 slug */ slug: varchar("slug", { length: 255 }).notNull(), /** # 数据库字段 名称 */ title: text("title").notNull(), /** # 数据库字段 短描述 */ shortDescription: text("short_description").default("").notNull(), /** # 数据库字段 详细描述 */ description: text("description").default("").notNull(), /** # 数据库字段 状态:draft | review | published */ status: varchar("status", { length: 16 }).default("draft").notNull(), /** # 数据库字段 SEO 标题 */ seoTitle: text("seo_title"), /** # 数据库字段 SEO 描述 */ seoDescription: text("seo_description"), /** # 数据库字段 更新时间 */ updatedAt: timestamp("updated_at", { withTimezone: true }).defaultNow().notNull(), }, (t) => [uniqueIndex("product_translations_product_lang_idx").on(t.productId, t.lang)], ); /** # 数据库表 * 产品属性定义(RAM / Flash / Chip Platform / Downlink 等,原 WooCommerce 全局属性)。 */ export const productAttributes = pgTable( "product_attributes", { /** # 数据库字段 属性 ID */ id: serial("id").primaryKey(), /** # 数据库字段 属性名 */ name: varchar("name", { length: 128 }).notNull(), /** # 数据库字段 属性 slug(attribute_id,如 ram / chip-platform) */ slug: varchar("slug", { length: 128 }).notNull(), /** # 数据库字段 是否作为筛选条件 */ filterable: boolean("filterable").default(true).notNull(), /** # 数据库字段 排序 */ sort: integer("sort").default(0).notNull(), }, (t) => [uniqueIndex("product_attributes_slug_idx").on(t.slug)], ); /** # 数据库表 * 产品属性可选值。 */ export const productAttributeValues = pgTable( "product_attribute_values", { /** # 数据库字段 值 ID */ id: serial("id").primaryKey(), /** # 数据库字段 所属属性 */ attributeId: integer("attribute_id").notNull(), /** # 数据库字段 显示值 */ value: varchar("value", { length: 255 }).notNull(), /** # 数据库字段 值 slug */ slug: varchar("slug", { length: 255 }).notNull(), /** # 数据库字段 排序 */ sort: integer("sort").default(0).notNull(), }, (t) => [ uniqueIndex("product_attr_values_attr_slug_idx").on(t.attributeId, t.slug), index("product_attr_values_attr_idx").on(t.attributeId), ], ); /** # 数据库表 * 产品 ↔ 属性值 关联(筛选查询主路径,建立复合索引)。 */ export const productAttributeMap = pgTable( "product_attribute_map", { /** # 数据库字段 产品 ID */ productId: integer("product_id").notNull(), /** # 数据库字段 属性值 ID */ valueId: integer("value_id").notNull(), }, (t) => [ primaryKey({ columns: [t.productId, t.valueId] }), index("product_attr_map_value_idx").on(t.valueId, t.productId), ], ); /** # 数据库表 * 产品 ↔ 产品分类 关联。 */ export const productTerms = pgTable( "product_terms", { /** # 数据库字段 产品 ID */ productId: integer("product_id").notNull(), /** # 数据库字段 分类 ID(taxonomy=product_cat) */ categoryId: integer("category_id").notNull(), }, (t) => [ primaryKey({ columns: [t.productId, t.categoryId] }), index("product_terms_category_idx").on(t.categoryId), ], ); /* ============================= 商城域 ============================= */ /** # 数据库表 * 用户(后台账号 + 商城注册客户)。保留 WordPress phpass 密码哈希用于存量客户登录兼容。 */ export const users = pgTable( "users", { /** # 数据库字段 用户 ID */ id: serial("id").primaryKey(), /** # 数据库字段 邮箱(登录名) */ email: varchar("email", { length: 255 }).notNull(), /** # 数据库字段 用户名 */ username: varchar("username", { length: 128 }), /** # 数据库字段 显示名称 */ displayName: varchar("display_name", { length: 255 }).default("").notNull(), /** # 数据库字段 密码哈希(新账号 bcrypt) */ passwordHash: varchar("password_hash", { length: 255 }), /** # 数据库字段 WordPress 旧密码哈希(phpass $P$) */ legacyPasswordHash: varchar("legacy_password_hash", { length: 255 }), /** # 数据库字段 角色:admin | editor | manager | customer */ role: varchar("role", { length: 32 }).default("customer").notNull(), /** # 数据库字段 头像 URL(媒体库选择,空 = 默认图标) */ avatar: varchar("avatar", { length: 512 }).default("").notNull(), /** # 数据库字段 默认后台语言(BCP47,空 = 跟随浏览器/默认 en) */ locale: varchar("locale", { length: 16 }).default("").notNull(), /** # 数据库字段 默认后台主题:light | dark(空 = 浅色) */ theme: varchar("theme", { length: 16 }).default("").notNull(), /** # 数据库字段 MCP 访问令牌(Agent 经 MCP 网关调用时鉴权;空 = 未启用) */ mcpToken: varchar("mcp_token", { length: 64 }).default("").notNull(), /** # 数据库字段 账单地址 */ billing: jsonb("billing").default({}).notNull(), /** # 数据库字段 收货地址 */ shipping: jsonb("shipping").default({}).notNull(), /** # 数据库字段 原 WP user ID */ legacyId: integer("legacy_id"), /** # 数据库字段 创建时间 */ createdAt: timestamp("created_at", { withTimezone: true }).defaultNow().notNull(), }, (t) => [ uniqueIndex("users_email_idx").on(t.email), index("users_legacy_idx").on(t.legacyId), ], ); /** # 数据库表 * 服务端会话(HttpOnly Cookie → 会话记录)。 */ export const sessions = pgTable( "sessions", { /** # 数据库字段 会话令牌 */ token: varchar("token", { length: 64 }).primaryKey(), /** # 数据库字段 用户 ID */ userId: integer("user_id").notNull(), /** # 数据库字段 过期时间 */ expiresAt: timestamp("expires_at", { withTimezone: true }).notNull(), /** # 数据库字段 创建时间 */ createdAt: timestamp("created_at", { withTimezone: true }).defaultNow().notNull(), }, (t) => [index("sessions_user_idx").on(t.userId)], ); /** # 数据库表 * 购物车(登录用户或匿名 session_key 维度)。 */ export const carts = pgTable("carts", { /** # 数据库字段 购物车 ID */ id: serial("id").primaryKey(), /** # 数据库字段 用户 ID(登录用户) */ userId: integer("user_id"), /** # 数据库字段 匿名会话键 */ sessionKey: varchar("session_key", { length: 64 }), /** # 数据库字段 创建时间 */ createdAt: timestamp("created_at", { withTimezone: true }).defaultNow().notNull(), /** # 数据库字段 更新时间 */ updatedAt: timestamp("updated_at", { withTimezone: true }).defaultNow().notNull(), }); /** # 数据库表 * 购物车明细。 */ export const cartItems = pgTable( "cart_items", { /** # 数据库字段 明细 ID */ id: serial("id").primaryKey(), /** # 数据库字段 购物车 ID */ cartId: integer("cart_id").notNull(), /** # 数据库字段 产品 ID */ productId: integer("product_id").notNull(), /** # 数据库字段 数量 */ qty: integer("qty").default(1).notNull(), }, (t) => [index("cart_items_cart_idx").on(t.cartId)], ); /** # 数据库表 * 订单主表。 */ export const orders = pgTable( "orders", { /** # 数据库字段 订单 ID */ id: serial("id").primaryKey(), /** # 数据库字段 订单号(对外展示) */ orderNumber: varchar("order_number", { length: 32 }).notNull(), /** # 数据库字段 客户 ID */ userId: integer("user_id"), /** # 数据库字段 状态:pending | on-hold | processing | completed | cancelled | refunded */ status: varchar("status", { length: 24 }).default("pending").notNull(), /** # 数据库字段 币种 */ currency: varchar("currency", { length: 8 }).default("USD").notNull(), /** # 数据库字段 商品小计 */ subtotal: numeric("subtotal", { precision: 12, scale: 2 }).default("0").notNull(), /** # 数据库字段 运费 */ shippingTotal: numeric("shipping_total", { precision: 12, scale: 2 }).default("0").notNull(), /** # 数据库字段 税费 */ taxTotal: numeric("tax_total", { precision: 12, scale: 2 }).default("0").notNull(), /** # 数据库字段 订单总额 */ total: numeric("total", { precision: 12, scale: 2 }).default("0").notNull(), /** # 数据库字段 支付方式 */ paymentMethod: varchar("payment_method", { length: 64 }), /** # 数据库字段 支付状态 */ paymentStatus: varchar("payment_status", { length: 24 }).default("unpaid").notNull(), /** # 数据库字段 支付交易号 */ transactionId: varchar("transaction_id", { length: 128 }), /** # 数据库字段 账单信息 */ billing: jsonb("billing").default({}).notNull(), /** # 数据库字段 收货信息 */ shipping: jsonb("shipping").default({}).notNull(), /** # 数据库字段 客户备注 */ customerNote: text("customer_note").default("").notNull(), /** # 数据库字段 原 WP order ID */ legacyId: integer("legacy_id"), /** # 数据库字段 下单时间 */ createdAt: timestamp("created_at", { withTimezone: true }).defaultNow().notNull(), /** # 数据库字段 更新时间 */ updatedAt: timestamp("updated_at", { withTimezone: true }).defaultNow().notNull(), }, (t) => [ uniqueIndex("orders_number_idx").on(t.orderNumber), index("orders_status_idx").on(t.status), index("orders_user_idx").on(t.userId), ], ); /** # 数据库表 * 订单明细(下单时快照商品名/价格)。 */ export const orderItems = pgTable( "order_items", { /** # 数据库字段 明细 ID */ id: serial("id").primaryKey(), /** # 数据库字段 订单 ID */ orderId: integer("order_id").notNull(), /** # 数据库字段 产品 ID */ productId: integer("product_id"), /** # 数据库字段 商品名快照 */ name: text("name").notNull(), /** # 数据库字段 SKU 快照 */ sku: varchar("sku", { length: 128 }), /** # 数据库字段 数量 */ qty: integer("qty").default(1).notNull(), /** # 数据库字段 单价 */ price: numeric("price", { precision: 12, scale: 2 }).default("0").notNull(), /** # 数据库字段 小计 */ total: numeric("total", { precision: 12, scale: 2 }).default("0").notNull(), }, (t) => [index("order_items_order_idx").on(t.orderId)], ); /** # 数据库表 * 支付流水(含第三方回调原始报文,幂等键 transaction_id)。 */ export const payments = pgTable( "payments", { /** # 数据库字段 支付 ID */ id: serial("id").primaryKey(), /** # 数据库字段 订单 ID */ orderId: integer("order_id").notNull(), /** # 数据库字段 支付方式 */ method: varchar("method", { length: 64 }).notNull(), /** # 数据库字段 状态:succeeded | failed | refunded | pending */ status: varchar("status", { length: 24 }).default("pending").notNull(), /** # 数据库字段 交易号(唯一,回调幂等) */ transactionId: varchar("transaction_id", { length: 128 }), /** # 数据库字段 金额 */ amount: numeric("amount", { precision: 12, scale: 2 }).default("0").notNull(), /** # 数据库字段 回调原始数据 */ raw: jsonb("raw").default({}).notNull(), /** # 数据库字段 创建时间 */ createdAt: timestamp("created_at", { withTimezone: true }).defaultNow().notNull(), }, (t) => [ index("payments_order_idx").on(t.orderId), uniqueIndex("payments_txn_idx").on(t.transactionId), ], ); /* ============================= 询盘域 ============================= */ /** # 数据库表 * 询盘表单定义(Contact Form 7 迁移,字段结构存 JSON)。 */ export const inquiryForms = pgTable( "inquiry_forms", { /** # 数据库字段 表单 ID */ id: serial("id").primaryKey(), /** # 数据库字段 表单名称 */ name: varchar("name", { length: 255 }).notNull(), /** # 数据库字段 表单 key(slug) */ formKey: varchar("form_key", { length: 128 }).notNull(), /** # 数据库字段 字段定义 JSON */ fields: jsonb("fields").default([]).notNull(), /** # 数据库字段 收件邮箱 */ mailTo: varchar("mail_to", { length: 255 }), /** # 数据库字段 是否启用 */ enabled: boolean("enabled").default(true).notNull(), /** # 数据库字段 原 CF7 form_id */ legacyId: integer("legacy_id"), }, (t) => [uniqueIndex("inquiry_forms_key_idx").on(t.formKey)], ); /** # 数据库表 * 询盘记录(CF7/Flamingo 与 Elementor Form 提交合并归一)。 */ export const inquiries = pgTable( "inquiries", { /** # 数据库字段 询盘 ID */ id: serial("id").primaryKey(), /** # 数据库字段 来源表单名 */ formName: varchar("form_name", { length: 255 }).default("").notNull(), /** # 数据库字段 表单 ID */ formId: integer("form_id"), /** # 数据库字段 姓名 */ name: varchar("name", { length: 255 }).default("").notNull(), /** # 数据库字段 邮箱 */ email: varchar("email", { length: 255 }).default("").notNull(), /** # 数据库字段 电话 */ phone: varchar("phone", { length: 128 }).default("").notNull(), /** # 数据库字段 公司 */ company: varchar("company", { length: 255 }).default("").notNull(), /** # 数据库字段 国家/地区 */ country: varchar("country", { length: 128 }).default("").notNull(), /** # 数据库字段 询盘内容 */ message: text("message").default("").notNull(), /** # 数据库字段 感兴趣的产品 */ productInterest: varchar("product_interest", { length: 255 }).default("").notNull(), /** # 数据库字段 完整原始字段(含 annualdemand、utm 等) */ fields: jsonb("fields").default({}).notNull(), /** # 数据库字段 状态:new | read | replied | spam | archived */ status: varchar("status", { length: 16 }).default("new").notNull(), /** # 数据库字段 来源渠道(channel / subject,可能很长用 text) */ channel: text("channel").default("").notNull(), /** # 数据库字段 来源页面 */ sourcePage: text("source_page").default("").notNull(), /** # 数据库字段 来源 IP */ ip: varchar("ip", { length: 64 }).default("").notNull(), /** # 数据库字段 UTM 参数 */ utm: jsonb("utm").default({}).notNull(), /** # 数据库字段 原 Flamingo/Elementor 记录 ID */ legacyId: integer("legacy_id"), /** # 数据库字段 提交时间 */ createdAt: timestamp("created_at", { withTimezone: true }).defaultNow().notNull(), }, (t) => [ index("inquiries_status_idx").on(t.status, t.createdAt), index("inquiries_email_idx").on(t.email), index("inquiries_created_idx").on(t.createdAt), ], ); /* ============================= 运营域 ============================= */ /** # 数据库表 * 媒体库(原 wp-content/uploads 附件)。 */ export const media = pgTable( "media", { /** # 数据库字段 媒体 ID */ id: serial("id").primaryKey(), /** # 数据库字段 相对路径(uploads 下) */ path: varchar("path", { length: 512 }).notNull(), /** # 数据库字段 访问 URL */ url: text("url").notNull(), /** # 数据库字段 MIME 类型 */ mimeType: varchar("mime_type", { length: 128 }).default("").notNull(), /** # 数据库字段 宽 */ width: integer("width"), /** # 数据库字段 高 */ height: integer("height"), /** # 数据库字段 文件大小 */ size: bigint("size", { mode: "number" }), /** # 数据库字段 替代文本 */ altText: text("alt_text").default("").notNull(), /** # 数据库字段 标题 */ title: text("title").default("").notNull(), /** # 数据库字段 引用次数 */ refCount: integer("ref_count").default(0).notNull(), /** # 数据库字段 原 WP attachment ID */ legacyId: integer("legacy_id"), /** # 数据库字段 上传时间 */ createdAt: timestamp("created_at", { withTimezone: true }).defaultNow().notNull(), }, (t) => [ uniqueIndex("media_path_idx").on(t.path), index("media_legacy_idx").on(t.legacyId), ], ); /** # 数据库表 * 301/302 重定向(Redirection 插件迁移)。 */ export const redirects = pgTable( "redirects", { /** # 数据库字段 重定向 ID */ id: serial("id").primaryKey(), /** # 数据库字段 源路径(支持正则) */ source: text("source").notNull(), /** # 数据库字段 目标地址 */ target: text("target").notNull(), /** # 数据库字段 状态码 */ code: integer("code").default(301).notNull(), /** # 数据库字段 是否正则匹配 */ isRegex: boolean("is_regex").default(false).notNull(), /** # 数据库字段 命中次数 */ hits: integer("hits").default(0).notNull(), /** # 数据库字段 是否启用 */ enabled: boolean("enabled").default(true).notNull(), /** # 数据库字段 原 redirection item id */ legacyId: integer("legacy_id"), }, (t) => [index("redirects_source_idx").on(t.source)], ); /** # 数据库表 * 筛选配置(Filter Everything 迁移,前台产品筛选器)。 */ export const filters = pgTable( "filters", { /** # 数据库字段 筛选 ID */ id: serial("id").primaryKey(), /** # 数据库字段 筛选名称 */ name: varchar("name", { length: 128 }).notNull(), /** # 数据库字段 URL 参数名(如 chip-platform) */ slug: varchar("slug", { length: 128 }).notNull(), /** # 数据库字段 类型:attribute | category | price */ type: varchar("type", { length: 24 }).default("attribute").notNull(), /** # 数据库字段 关联属性 ID(type=attribute 时) */ attributeId: integer("attribute_id"), /** # 数据库字段 关联 taxonomy */ taxonomy: varchar("taxonomy", { length: 64 }), /** # 数据库字段 显示位置 */ position: integer("position").default(0).notNull(), /** # 数据库字段 是否启用 */ enabled: boolean("enabled").default(true).notNull(), /** # 数据库字段 原 filter-field post_id */ legacyId: integer("legacy_id"), }, (t) => [uniqueIndex("filters_slug_idx").on(t.slug)], ); /** # 数据库表 * 语言配置(GTranslate 迁移:启用的语言与默认语言)。 */ export const languages = pgTable( "languages", { /** # 数据库字段 语言代码(BCP47) */ code: varchar("code", { length: 16 }).primaryKey(), /** # 数据库字段 显示名 */ name: varchar("name", { length: 64 }).notNull(), /** # 数据库字段 是否默认语言 */ isDefault: boolean("is_default").default(false).notNull(), /** # 数据库字段 是否启用(可发布真实页面) */ enabled: boolean("enabled").default(false).notNull(), /** # 数据库字段 是否机器翻译(GTranslate 存量) */ machine: boolean("machine").default(false).notNull(), /** # 数据库字段 排序 */ sort: integer("sort").default(0).notNull(), }, ); /** # 数据库表 * 持久化任务队列(独立于 Web 请求的后台任务,带重试)。 */ export const jobs = pgTable( "jobs", { /** # 数据库字段 任务 ID */ id: serial("id").primaryKey(), /** # 数据库字段 任务类型(email.send / media.reindex …) */ type: varchar("type", { length: 64 }).notNull(), /** # 数据库字段 任务参数 */ payload: jsonb("payload").default({}).notNull(), /** # 数据库字段 状态:pending | running | done | failed */ status: varchar("status", { length: 16 }).default("pending").notNull(), /** # 数据库字段 已重试次数 */ attempts: integer("attempts").default(0).notNull(), /** # 数据库字段 最大重试次数 */ maxAttempts: integer("max_attempts").default(3).notNull(), /** # 数据库字段 计划执行时间 */ runAt: timestamp("run_at", { withTimezone: true }).defaultNow().notNull(), /** # 数据库字段 最近错误 */ lastError: text("last_error"), /** # 数据库字段 创建时间 */ createdAt: timestamp("created_at", { withTimezone: true }).defaultNow().notNull(), /** # 数据库字段 更新时间 */ updatedAt: timestamp("updated_at", { withTimezone: true }).defaultNow().notNull(), }, (t) => [index("jobs_status_runat_idx").on(t.status, t.runAt)], ); /** # 数据库表 * 审计日志(后台敏感操作留痕)。 */ export const auditLogs = pgTable( "audit_logs", { /** # 数据库字段 日志 ID */ id: serial("id").primaryKey(), /** # 数据库字段 操作人 */ actorId: integer("actor_id"), /** # 数据库字段 动作(如 product.update) */ action: varchar("action", { length: 128 }).notNull(), /** # 数据库字段 实体类型 */ entity: varchar("entity", { length: 64 }).notNull(), /** # 数据库字段 实体 ID */ entityId: varchar("entity_id", { length: 64 }), /** # 数据库字段 附加数据 */ meta: jsonb("meta").default({}).notNull(), /** # 数据库字段 操作 IP */ ip: varchar("ip", { length: 64 }).default("").notNull(), /** # 数据库字段 操作时间 */ createdAt: timestamp("created_at", { withTimezone: true }).defaultNow().notNull(), }, (t) => [index("audit_logs_time_idx").on(t.createdAt)], ); /** # 数据库表 * 站点设置(键值 JSON:导航、邮件、支付、缓存开关等)。 */ export const settings = pgTable("settings", { /** # 数据库字段 设置键 */ key: varchar("key", { length: 128 }).primaryKey(), /** # 数据库字段 设置值 */ value: jsonb("value").default({}).notNull(), /** # 数据库字段 更新时间 */ updatedAt: timestamp("updated_at", { withTimezone: true }).defaultNow().notNull(), }); /** # 数据库表 * 旧 ID 映射(WordPress ID → 新系统 ID,迁移校验与增量同步用)。 */ export const legacyIdMappings = pgTable( "legacy_id_mappings", { /** # 数据库字段 映射 ID */ id: serial("id").primaryKey(), /** # 数据库字段 实体类型(post/product/user/order/media …) */ entity: varchar("entity", { length: 64 }).notNull(), /** # 数据库字段 原 WP ID */ legacyId: integer("legacy_id").notNull(), /** # 数据库字段 新系统 ID */ newId: integer("new_id").notNull(), }, (t) => [uniqueIndex("legacy_map_entity_id_idx").on(t.entity, t.legacyId)], );