Mimingguang ee078b61bc feat: 后台管理系统完整重构 + 前后台数据联通
- 后台全面引入 Naive UI 组件库,统一 UI 规范
- 前台 usePublicApi 切换到 API 调用(GET /api/content/[key])
- 前后台数据源统一(site_content 表)
- 产品线统一管理(tour/camp/course 三套编辑器)
- 产品数据归一化(itinerary/faq/pricing 格式统一)
- 表单提交 API 改写入 submissions 表
- 新增 submissions 标记已读 API
- site-content PUT 支持 upsert
- 修复前台 bug(stories 路由冲突、占位符警告、selector breadcrumb)
- 消除 PageHero 类型警告(useSEO reactive 修复)
- 25 个前台页面全部 HTTP 200,展示效果不变

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 17:48:02 +08:00

129 行
3.2 KiB
JavaScript

/**
* 数据库初始化脚本
* 运行: node server/database/migrate.js
*
* 创建所有表(如果不存在)
*/
import Database from 'better-sqlite3'
import { join } from 'path'
import { fileURLToPath } from 'url'
import { dirname } from 'path'
const __dirname = dirname(fileURLToPath(import.meta.url))
const DB_PATH = join(__dirname, 'hulai.db')
const db = new Database(DB_PATH)
db.pragma('journal_mode = WAL')
db.pragma('foreign_keys = ON')
// ── 建表 SQL ────────────────────────────────────────
const tables = `
CREATE TABLE IF NOT EXISTS admin_users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
username TEXT NOT NULL UNIQUE,
password_hash TEXT NOT NULL,
created_at TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE TABLE IF NOT EXISTS articles (
id INTEGER PRIMARY KEY AUTOINCREMENT,
slug TEXT NOT NULL UNIQUE,
title TEXT NOT NULL,
summary TEXT,
content TEXT,
category TEXT,
type TEXT NOT NULL DEFAULT 'news',
cover_image TEXT,
author TEXT,
tags TEXT,
seo_title TEXT,
seo_description TEXT,
seo_keywords TEXT,
published INTEGER DEFAULT 1,
sort_order INTEGER DEFAULT 0,
created_at TEXT NOT NULL DEFAULT (datetime('now')),
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE TABLE IF NOT EXISTS reviews (
id INTEGER PRIMARY KEY AUTOINCREMENT,
author TEXT NOT NULL,
rating INTEGER DEFAULT 5,
title TEXT,
content TEXT,
date TEXT,
verified INTEGER DEFAULT 0,
published INTEGER DEFAULT 1,
sort_order INTEGER DEFAULT 0,
created_at TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE TABLE IF NOT EXISTS faqs (
id INTEGER PRIMARY KEY AUTOINCREMENT,
question TEXT NOT NULL,
answer TEXT NOT NULL,
sort_order INTEGER DEFAULT 0,
published INTEGER DEFAULT 1
);
CREATE TABLE IF NOT EXISTS gallery_items (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT NOT NULL,
category TEXT,
location TEXT,
description TEXT,
image TEXT NOT NULL,
orientation TEXT,
published INTEGER DEFAULT 1,
sort_order INTEGER DEFAULT 0
);
CREATE TABLE IF NOT EXISTS stories (
id INTEGER PRIMARY KEY AUTOINCREMENT,
slug TEXT NOT NULL UNIQUE,
title TEXT NOT NULL,
subtitle TEXT,
family_type TEXT,
children_age TEXT,
from_city TEXT,
trip_product TEXT,
travel_date TEXT,
cover_image TEXT,
sections TEXT,
key_moments TEXT,
seo_title TEXT,
seo_description TEXT,
published INTEGER DEFAULT 1,
sort_order INTEGER DEFAULT 0,
created_at TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE TABLE IF NOT EXISTS submissions (
id INTEGER PRIMARY KEY AUTOINCREMENT,
type TEXT NOT NULL,
data TEXT NOT NULL,
ip TEXT,
read INTEGER DEFAULT 0,
created_at TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE TABLE IF NOT EXISTS site_content (
id INTEGER PRIMARY KEY AUTOINCREMENT,
key TEXT NOT NULL UNIQUE,
label TEXT NOT NULL,
data TEXT NOT NULL,
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE TABLE IF NOT EXISTS sessions (
token TEXT PRIMARY KEY,
user_id INTEGER NOT NULL,
created_at TEXT NOT NULL DEFAULT (datetime('now'))
);
`
db.exec(tables)
console.log('✅ 数据库表创建完成:', DB_PATH)
db.close()