wx de8e3f9471 fix: 客户评价页补全截图/标签/关键词数据
- reviews表新增screenshot/scenes/concerns字段
- API映射从数据库读取这些字段,不再硬编码为空
- 修复客户高频关键词不显示的问题

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 16:33:05 +08:00

113 行
5.7 KiB
JavaScript

此文件含有模棱两可的 Unicode 字符

此文件含有可能会与其他字符混淆的 Unicode 字符。 如果您是想特意这样的,可以安全地忽略该警告。 使用 Escape 按钮显示他们。

import { sqliteTable, text, integer } from 'drizzle-orm/sqlite-core'
// ── 管理员 ──────────────────────────────────────────
export const adminUsers = sqliteTable('admin_users', {
id: integer('id').primaryKey({ autoIncrement: true }),
username: text('username').notNull().unique(),
// 存储 hash 后的密码
passwordHash: text('password_hash').notNull(),
createdAt: text('created_at').notNull().$defaultFn(() => new Date().toISOString()),
})
// ── 新闻/公告 ────────────────────────────────────────
export const articles = sqliteTable('articles', {
id: integer('id').primaryKey({ autoIncrement: true }),
slug: text('slug').notNull().unique(),
title: text('title').notNull(),
summary: text('summary'),
content: text('content'), // HTML 或 Markdown
category: text('category'), // 产品 / 公告 / 活动 / 攻略 / 亲子
type: text('type').notNull(), // news / blog
coverImage: text('cover_image'),
author: text('author'),
tags: text('tags'), // JSON 数组字符串
seoTitle: text('seo_title'),
seoDesc: text('seo_description'),
seoKeywords: text('seo_keywords'),
published: integer('published', { mode: 'boolean' }).default(true),
sortOrder: integer('sort_order').default(0),
createdAt: text('created_at').notNull().$defaultFn(() => new Date().toISOString()),
updatedAt: text('updated_at').notNull().$defaultFn(() => new Date().toISOString()),
})
// ── 客户评价 ─────────────────────────────────────────
export const reviews = sqliteTable('reviews', {
id: integer('id').primaryKey({ autoIncrement: true }),
author: text('author').notNull(),
rating: integer('rating').default(5),
title: text('title'),
content: text('content'),
date: text('date'),
screenshot: text('screenshot'), // 评价截图路径
scenes: text('scenes'), // JSON数组: 出行场景标签
concerns: text('concerns'), // JSON数组: 关注维度标签
verified: integer('verified', { mode: 'boolean' }).default(false),
published: integer('published', { mode: 'boolean' }).default(true),
sortOrder: integer('sort_order').default(0),
createdAt: text('created_at').notNull().$defaultFn(() => new Date().toISOString()),
})
// ── FAQ ──────────────────────────────────────────────
export const faqs = sqliteTable('faqs', {
id: integer('id').primaryKey({ autoIncrement: true }),
question: text('question').notNull(),
answer: text('answer').notNull(),
sortOrder: integer('sort_order').default(0),
published: integer('published', { mode: 'boolean' }).default(true),
})
// ── 相册/旅拍 ────────────────────────────────────────
export const galleryItems = sqliteTable('gallery_items', {
id: integer('id').primaryKey({ autoIncrement: true }),
title: text('title').notNull(),
category: text('category'), // 草原 / 森林 / 湖泊 / 冬季 ...
location: text('location'),
description: text('description'),
image: text('image').notNull(), // 图片路径
orientation: text('orientation'), // portrait / landscape
published: integer('published', { mode: 'boolean' }).default(true),
sortOrder: integer('sort_order').default(0),
})
// ── 客户故事 ─────────────────────────────────────────
export const stories = sqliteTable('stories', {
id: integer('id').primaryKey({ autoIncrement: true }),
slug: text('slug').notNull().unique(),
title: text('title').notNull(),
subtitle: text('subtitle'),
familyType: text('family_type'),
childrenAge: text('children_age'),
fromCity: text('from_city'),
tripProduct: text('trip_product'),
travelDate: text('travel_date'),
coverImage: text('cover_image'),
// sections 存为 JSON 字符串: [{ heading, content }]
sections: text('sections'),
keyMoments: text('key_moments'), // JSON 数组
seoTitle: text('seo_title'),
seoDesc: text('seo_description'),
published: integer('published', { mode: 'boolean' }).default(true),
sortOrder: integer('sort_order').default(0),
createdAt: text('created_at').notNull().$defaultFn(() => new Date().toISOString()),
})
// ── 表单提交记录 ─────────────────────────────────────
export const submissions = sqliteTable('submissions', {
id: integer('id').primaryKey({ autoIncrement: true }),
type: text('type').notNull(), // contact / customize
data: text('data').notNull(), // JSON 字符串,存完整表单数据
ip: text('ip'),
read: integer('read', { mode: 'boolean' }).default(false),
createdAt: text('created_at').notNull().$defaultFn(() => new Date().toISOString()),
})
// ── 站点配置catch-all,存复杂 JSON 内容)───────────
// 用于 products / destinations / courses / navigation 等复杂嵌套数据
export const siteContent = sqliteTable('site_content', {
id: integer('id').primaryKey({ autoIncrement: true }),
key: text('key').notNull().unique(), // 如 'products', 'navigation', 'brand'
label: text('label').notNull(), // 显示名称,如 '产品管理', '导航配置'
data: text('data').notNull(), // JSON 字符串
updatedAt: text('updated_at').notNull().$defaultFn(() => new Date().toISOString()),
})