feat: 官网代码全量更新 (2026-04-18)
这个提交包含在:
@@ -52,6 +52,9 @@ CREATE TABLE IF NOT EXISTS reviews (
|
||||
title TEXT,
|
||||
content TEXT,
|
||||
date TEXT,
|
||||
screenshot TEXT,
|
||||
scenes TEXT,
|
||||
concerns TEXT,
|
||||
verified INTEGER DEFAULT 0,
|
||||
published INTEGER DEFAULT 1,
|
||||
sort_order INTEGER DEFAULT 0,
|
||||
@@ -104,6 +107,8 @@ CREATE TABLE IF NOT EXISTS submissions (
|
||||
data TEXT NOT NULL,
|
||||
ip TEXT,
|
||||
read INTEGER DEFAULT 0,
|
||||
replied INTEGER DEFAULT 0,
|
||||
replied_at TEXT,
|
||||
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||
);
|
||||
|
||||
@@ -125,4 +130,15 @@ CREATE TABLE IF NOT EXISTS sessions (
|
||||
db.exec(tables)
|
||||
console.log('✅ 数据库表创建完成:', DB_PATH)
|
||||
|
||||
// ── 增量迁移:为已有表补齐新列(幂等)───────────────
|
||||
function addColumnIfMissing(table, column, ddl) {
|
||||
const info = db.prepare(`PRAGMA table_info(${table})`).all()
|
||||
if (!info.some(c => c.name === column)) {
|
||||
db.exec(`ALTER TABLE ${table} ADD COLUMN ${column} ${ddl}`)
|
||||
console.log(` + ${table}.${column} 列已添加`)
|
||||
}
|
||||
}
|
||||
addColumnIfMissing('submissions', 'replied', 'INTEGER DEFAULT 0')
|
||||
addColumnIfMissing('submissions', 'replied_at', 'TEXT')
|
||||
|
||||
db.close()
|
||||
|
||||
@@ -81,6 +81,10 @@ export const stories = sqliteTable('stories', {
|
||||
tripProduct: text('trip_product'),
|
||||
travelDate: text('travel_date'),
|
||||
coverImage: text('cover_image'),
|
||||
summary: text('summary'), // 卡片展示的 2 行摘要
|
||||
author: text('author'), // 客户昵称/作者
|
||||
sourceUrl: text('source_url'), // 小红书等外链(有则前台卡片外跳)
|
||||
tags: text('tags'), // JSON 数组(标签)
|
||||
// sections 存为 JSON 字符串: [{ heading, content }]
|
||||
sections: text('sections'),
|
||||
keyMoments: text('key_moments'), // JSON 数组
|
||||
@@ -98,6 +102,8 @@ export const submissions = sqliteTable('submissions', {
|
||||
data: text('data').notNull(), // JSON 字符串,存完整表单数据
|
||||
ip: text('ip'),
|
||||
read: integer('read', { mode: 'boolean' }).default(false),
|
||||
replied: integer('replied', { mode: 'boolean' }).default(false),
|
||||
repliedAt: text('replied_at'),
|
||||
createdAt: text('created_at').notNull().$defaultFn(() => new Date().toISOString()),
|
||||
})
|
||||
|
||||
|
||||
@@ -140,6 +140,7 @@ console.log(`✅ 客户故事导入: ${storiesData.stories.length} 条`)
|
||||
|
||||
// ── 导入站点配置(复杂 JSON 直接存)──────────────────
|
||||
const siteConfigs = [
|
||||
{ key: 'product-lines', label: '产品线列表', file: 'product-lines.json' },
|
||||
{ key: 'products', label: '产品管理', file: 'products.json' },
|
||||
{ key: 'autumn-products', label: '秋季产品', file: 'autumn-products.json' },
|
||||
{ key: 'winter-products', label: '冬季产品', file: 'winter-products.json' },
|
||||
@@ -149,6 +150,8 @@ const siteConfigs = [
|
||||
{ key: 'courses', label: '研学课程', file: 'courses.json' },
|
||||
{ key: 'calendar', label: '出行日历', file: 'calendar.json' },
|
||||
{ key: 'guides', label: '出行指南', file: 'guides.json' },
|
||||
{ key: 'guide-custom', label: '定制游怎么选 (文章)', file: 'guide-custom.json' },
|
||||
{ key: 'section-titles', label: '栏目标题', file: 'section-titles.json' },
|
||||
{ key: 'navigation', label: '导航配置', file: 'navigation.json' },
|
||||
{ key: 'brand', label: '品牌信息', file: 'brand.json' },
|
||||
{ key: 'contact', label: '联系方式', file: 'contact.json' },
|
||||
|
||||
在新工单中引用
屏蔽一个用户