Files
plerr-open/apps/pb_migrations/1710000002_seed_data.js
T
yuns 5030808c55 feat: Phase 1 - PocketBase 迁移文件、种子数据、部署脚本
- apps/pb_migrations/1710000001_init_collections.js: 9个集合完整定义
- apps/pb_migrations/1710000002_seed_data.js: 默认管理员、分类、标签、页面、示例文章
- scripts/install.sh: Linux 一键部署脚本 (systemd, Nginx, SSL, 防火墙, Fail2Ban)
- scripts/install.ps1: Windows 一键部署脚本 (NSSM服务, 计划任务, Certbot)
- scripts/start.sh: 服务启动脚本
- scripts/backup.sh: 数据备份脚本
- scripts/update.sh: 代码更新部署脚本
- docs/DEPLOY.md: 详细部署教程文档
2026-07-24 14:46:16 +08:00

496 lines
37 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
migrate((db) => {
const dao = new Dao(db)
// 获取集合引用
const categoriesCollection = dao.findCollectionByNameOrId('categories')
const tagsCollection = dao.findCollectionByNameOrId('tags')
const postsCollection = dao.findCollectionByNameOrId('posts')
const pagesCollection = dao.findCollectionByNameOrId('pages')
const settingsCollection = dao.findCollectionByNameOrId('site_settings')
const menusCollection = dao.findCollectionByNameOrId('menus')
// 创建默认管理员用户
const adminCollection = dao.findCollectionByNameOrId('_pb_users_auth_')
const adminRecord = new Record(adminCollection, {
email: 'admin@yunsheng.digital',
password: 'YunSheng@2024!Admin',
passwordConfirm: 'YunSheng@2024!Admin',
name: '云升数码',
role: 'admin',
verified: true,
})
dao.saveRecord(adminRecord)
// 创建默认分类
const categories = [
{ name: '数码评测', slug: 'reviews', description: '专业数码产品深度评测', icon: '📱', color: '#0ea5e9', sort_order: 1, is_active: true },
{ name: '技术教程', slug: 'tutorials', description: '实用技术教程与操作指南', icon: '🛠️', color: '#10b981', sort_order: 2, is_active: true },
{ name: '行业资讯', slug: 'news', description: '数码科技行业最新动态', icon: '📰', color: '#f59e0b', sort_order: 3, is_active: true },
{ name: '玩机技巧', slug: 'tips', description: '手机、电脑、配件使用技巧', icon: '💡', color: '#8b5cf6', sort_order: 4, is_active: true },
{ name: '开箱体验', slug: 'unboxing', description: '新品开箱与第一印象', icon: '📦', color: '#ec4899', sort_order: 5, is_active: true },
{ name: '对比横评', slug: 'comparison', description: '多款产品横向对比评测', icon: '⚖️', color: '#ef4444', sort_order: 6, is_active: true },
]
const categoryRecords = {}
for (const cat of categories) {
const record = new Record(categoriesCollection, cat)
dao.saveRecord(record)
categoryRecords[cat.slug] = record.id
}
// 创建默认标签
const tags = [
{ name: '手机', slug: 'phone', color: '#0ea5e9', sort_order: 1, is_active: true },
{ name: '笔记本', slug: 'laptop', color: '#10b981', sort_order: 2, is_active: true },
{ name: '耳机', slug: 'headphones', color: '#f59e0b', sort_order: 3, is_active: true },
{ name: '显示器', slug: 'monitor', color: '#8b5cf6', sort_order: 4, is_active: true },
{ name: '键盘', slug: 'keyboard', color: '#ec4899', sort_order: 5, is_active: true },
{ name: '鼠标', slug: 'mouse', color: '#ef4444', sort_order: 6, is_active: true },
{ name: '配件', slug: 'accessories', color: '#6366f1', sort_order: 7, is_active: true },
{ name: '智能家居', slug: 'smart-home', color: '#14b8a6', sort_order: 8, is_active: true },
{ name: '摄影', slug: 'photography', color: '#f97316', sort_order: 9, is_active: true },
{ name: '音频', slug: 'audio', color: '#a855f7', sort_order: 10, is_active: true },
{ name: '评测', slug: 'review', color: '#06b6d4', sort_order: 11, is_active: true },
{ name: '教程', slug: 'tutorial', color: '#84cc16', sort_order: 12, is_active: true },
{ name: '推荐', slug: 'recommend', color: '#eab308', sort_order: 13, is_active: true },
{ name: '避坑', slug: 'avoid', color: '#dc2626', sort_order: 14, is_active: true },
{ name: '性价比', slug: 'value', color: '#16a34a', sort_order: 15, is_active: true },
]
const tagRecords = {}
for (const tag of tags) {
const record = new Record(tagsCollection, tag)
dao.saveRecord(record)
tagRecords[tag.slug] = record.id
}
// 创建站点设置
const settingsRecord = new Record(settingsCollection, {
site_name: '云升数码',
site_subtitle: '专业数码评测与技术分享',
site_description: '云升数码致力于为用户提供专业、客观、深度的数码产品评测、技术教程和行业资讯。我们不做标题党,只做真实评测。',
site_keywords: '数码评测,手机评测,笔记本评测,耳机评测,数码教程,科技资讯,开箱体验,数码推荐',
site_url: 'https://yunsheng.digital',
footer_text: '云升数码 - 专业数码评测与技术分享平台',
footer_copyright: '© 2024 云升数码. All rights reserved.',
icp_number: '京ICP备2024000000号',
social_links: JSON.stringify({
github: 'https://github.com/yunsheng-digital',
twitter: 'https://twitter.com/yunsheng_digital',
bilibili: 'https://space.bilibili.com/yunsheng',
weibo: 'https://weibo.com/yunsheng',
zhihu: 'https://zhihu.com/people/yunsheng',
email: 'contact@yunsheng.digital',
rss: '/rss.xml',
}),
background_music_enabled: true,
background_music_type: 'local',
background_music_title: '云端漫步',
background_music_artist: '云升数码',
background_music_volume: 0.4,
background_music_autoplay: false,
background_music_loop: true,
comment_enabled: false,
comment_system: 'giscus',
rss_enabled: true,
search_enabled: true,
cache_ttl: 3600,
image_optimization: true,
maintenance_mode: false,
})
dao.saveRecord(settingsRecord)
// 创建默认菜单
const headerMenuItems = [
{ label: '首页', url: '/', order: 1 },
{ label: '评测', url: '/category/reviews', order: 2 },
{ label: '教程', url: '/category/tutorials', order: 3 },
{ label: '资讯', url: '/category/news', order: 4 },
{ label: '音乐', url: '/music', order: 5 },
{ label: '关于', url: '/page/about', order: 6 },
]
const footerMenuItems = [
{ label: '关于我们', url: '/page/about', order: 1 },
{ label: '联系我们', url: '/page/contact', order: 2 },
{ label: '隐私政策', url: '/page/privacy', order: 3 },
{ label: '服务条款', url: '/page/terms', order: 4 },
{ label: '搭建教程', url: '/page/deploy-guide', order: 5 },
{ label: 'RSS 订阅', url: '/rss.xml', order: 6 },
]
const headerMenu = new Record(menusCollection, {
name: '主导航',
location: 'header',
items: JSON.stringify(headerMenuItems),
is_active: true,
})
dao.saveRecord(headerMenu)
const footerMenu = new Record(menusCollection, {
name: '页脚导航',
location: 'footer',
items: JSON.stringify(footerMenuItems),
is_active: true,
})
dao.saveRecord(footerMenu)
// 创建示例页面
const pages = [
{
title: '关于我们',
slug: 'about',
content: JSON.stringify({
type: 'doc',
content: [
{ type: 'heading', attrs: { level: 1 }, content: [{ type: 'text', text: '关于云升数码' }] },
{ type: 'paragraph', content: [{ type: 'text', text: '云升数码成立于 2024 年,是一个专注于数码产品深度评测、技术教程分享和行业资讯报道的专业平台。' }] },
{ type: 'heading', attrs: { level: 2 }, content: [{ type: 'text', text: '我们的使命' }] },
{ type: 'paragraph', content: [{ type: 'text', text: '为消费者提供最真实、最专业、最有价值的数码产品购买参考,帮助每一位数码爱好者做出明智的选择。' }] },
{ type: 'heading', attrs: { level: 2 }, content: [{ type: 'text', text: '核心价值观' }] },
{ type: 'bulletList', content: [
{ type: 'listItem', content: [{ type: 'paragraph', content: [{ type: 'text', text: '客观公正:拒绝商业软文,坚持真实评测' }] }] },
{ type: 'listItem', content: [{ type: 'paragraph', content: [{ type: 'text', text: '专业深度:深挖技术细节,不止于参数堆砌' }] }] },
{ type: 'listItem', content: [{ type: 'paragraph', content: [{ type: 'text', text: '用户至上:站在消费者角度,解决真实痛点' }] }] },
{ type: 'listItem', content: [{ type: 'paragraph', content: [{ type: 'text', text: '持续创新:紧跟技术潮流,探索评测新形式' }] }] },
]},
{ type: 'heading', attrs: { level: 2 }, content: [{ type: 'text', text: '联系我们' }] },
{ type: 'paragraph', content: [{ type: 'text', text: '商务合作:business@yunsheng.digital' }] },
{ type: 'paragraph', content: [{ type: 'text', text: '投稿建议:tips@yunsheng.digital' }] },
{ type: 'paragraph', content: [{ type: 'text', text: '技术支持:tech@yunsheng.digital' }] },
],
}),
template: 'default',
published: true,
sort_order: 1,
show_in_nav: true,
nav_label: '关于',
},
{
title: '联系我们',
slug: 'contact',
content: JSON.stringify({
type: 'doc',
content: [
{ type: 'heading', attrs: { level: 1 }, content: [{ type: 'text', text: '联系我们' }] },
{ type: 'paragraph', content: [{ type: 'text', text: '欢迎通过以下方式与我们取得联系:' }] },
{ type: 'heading', attrs: { level: 2 }, content: [{ type: 'text', text: '商务合作' }] },
{ type: 'paragraph', content: [{ type: 'text', text: '邮箱:business@yunsheng.digital' }] },
{ type: 'heading', attrs: { level: 2 }, content: [{ type: 'text', text: '投稿建议' }] },
{ type: 'paragraph', content: [{ type: 'text', text: '邮箱:tips@yunsheng.digital' }] },
{ type: 'heading', attrs: { level: 2 }, content: [{ type: 'text', text: '技术支持' }] },
{ type: 'paragraph', content: [{ type: 'text', text: '邮箱:tech@yunsheng.digital' }] },
{ type: 'heading', attrs: { level: 2 }, content: [{ type: 'text', text: '社交媒体' }] },
{ type: 'bulletList', content: [
{ type: 'listItem', content: [{ type: 'paragraph', content: [{ type: 'text', text: 'GitHub: github.com/yunsheng-digital' }] }] },
{ type: 'listItem', content: [{ type: 'paragraph', content: [{ type: 'text', text: 'Twitter: @yunsheng_digital' }] }] },
{ type: 'listItem', content: [{ type: 'paragraph', content: [{ type: 'text', text: 'Bilibili: 云升数码' }] }] },
]},
],
}),
template: 'default',
published: true,
sort_order: 2,
show_in_nav: false,
},
{
title: '隐私政策',
slug: 'privacy',
content: JSON.stringify({
type: 'doc',
content: [
{ type: 'heading', attrs: { level: 1 }, content: [{ type: 'text', text: '隐私政策' }] },
{ type: 'paragraph', content: [{ type: 'text', text: '云升数码(以下简称"我们")非常重视您的隐私保护。本隐私政策说明了我们如何收集、使用、存储和保护您的个人信息。' }] },
{ type: 'heading', attrs: { level: 2 }, content: [{ type: 'text', text: '1. 信息收集' }] },
{ type: 'paragraph', content: [{ type: 'text', text: '我们可能收集以下信息:访问日志(IP、浏览器、访问时间)、Cookie 数据、您主动提交的评论/联系表单信息。' }] }],
{ type: 'heading', attrs: { level: 2 }, content: [{ type: 'text', text: '2. 信息使用' }] },
{ type: 'paragraph', content: [{ type: 'text', text: '收集的信息仅用于:网站统计分析、改善用户体验、回复您的咨询、发送必要通知。' }] }],
{ type: 'heading', attrs: { level: 2 }, content: [{ type: 'text', text: '3. 信息共享' }] },
{ type: 'paragraph', content: [{ type: 'text', text: '未经您同意,我们不会向第三方披露您的个人信息,法律法规要求或保护公共利益除外。' }] }],
{ type: 'heading', attrs: { level: 2 }, content: [{ type: 'text', text: '4. 您的权利' }] },
{ type: 'paragraph', content: [{ type: 'text', text: '您有权访问、更正、删除您的个人信息,可通过联系我们行使相关权利。' }] }],
],
}),
template: 'default',
published: true,
sort_order: 3,
show_in_nav: false,
},
{
title: '服务条款',
slug: 'terms',
content: JSON.stringify({
type: 'doc',
content: [
{ type: 'heading', attrs: { level: 1 }, content: [{ type: 'text', text: '服务条款' }] },
{ type: 'paragraph', content: [{ type: 'text', text: '欢迎使用云升数码网站服务。请仔细阅读以下条款。' }] },
{ type: 'heading', attrs: { level: 2 }, content: [{ type: 'text', text: '1. 服务内容' }] },
{ type: 'paragraph', content: [{ type: 'text', text: '我们提供数码评测文章、技术教程、行业资讯等内容服务。' }] }],
{ type: 'heading', attrs: { level: 2 }, content: [{ type: 'text', text: '2. 用户行为' }] },
{ type: 'paragraph', content: [{ type: 'text', text: '禁止发布违法、侵权、垃圾、广告等有害内容。违者将删除内容并封禁账号。' }] }],
{ type: 'heading', attrs: { level: 2 }, content: [{ type: 'text', text: '3. 知识产权' }] },
{ type: 'paragraph', content: [{ type: 'text', text: '本站原创内容版权归云升数码所有,转载请注明出处并获取授权。' }] }],
{ type: 'heading', attrs: { level: 2 }, content: [{ type: 'text', text: '4. 免责声明' }] },
{ type: 'paragraph', content: [{ type: 'text', text: '评测内容仅供参考,购买决策请以官方信息为准。因信息滞后或错误造成的损失,本站不承担责任。' }] }],
],
}),
template: 'default',
published: true,
sort_order: 4,
show_in_nav: false,
},
{
title: '搭建教程',
slug: 'deploy-guide',
content: JSON.stringify({
type: 'doc',
content: [
{ type: 'heading', attrs: { level: 1 }, content: [{ type: 'text', text: '云升数码站点搭建教程' }] },
{ type: 'paragraph', content: [{ type: 'text', text: '本教程将指导您如何在自己的服务器上部署云升数码展示页面。' }] },
{ type: 'heading', attrs: { level: 2 }, content: [{ type: 'text', text: '📋 准备工作' }] },
{ type: 'bulletList', content: [
{ type: 'listItem', content: [{ type: 'paragraph', content: [{ type: 'text', text: '一台 Linux 服务器(推荐 Ubuntu 22.04+ / Debian 12+' }] }] },
{ type: 'listItem', content: [{ type: 'paragraph', content: [{ type: 'text', text: '域名一个,已解析到服务器 IP' }] }] },
{ type: 'listItem', content: [{ type: 'paragraph', content: [{ type: 'text', text: 'SSH 客户端(Windows 推荐 Terminal / TabbyMac/Linux 自带 Terminal' }] }] },
{ type: 'listItem', content: [{ type: 'paragraph', content: [{ type: 'text', text: '基本 Linux 命令行操作知识' }] }] },
]},
{ type: 'heading', attrs: { level: 2 }, content: [{ type: 'text', text: '🚀 一键部署(推荐)' }] },
{ type: 'paragraph', content: [{ type: 'text', text: '我们提供了一键部署脚本,适合大多数场景:' }] }],
{ type: 'codeBlock', attrs: { language: 'bash' }, content: [
{ type: 'text', text: '# 1. 克隆仓库\ngit clone https://git.grxiao.cn/yuns/plerr-open.git\ncd plerr-open\n\n# 2. 运行一键安装脚本\nchmod +x scripts/install.sh\nsudo ./scripts/install.sh\n\n# 3. 按提示配置域名、SSL 等\n# 4. 访问 https://your-domain.com 完成初始化' }
]},
{ type: 'heading', attrs: { level: 2 }, content: [{ type: 'text', text: '🐳 Docker 部署' }] },
{ type: 'paragraph', content: [{ type: 'text', text: '如果您偏好容器化部署:' }] }],
{ type: 'codeBlock', attrs: { language: 'bash' }, content: [
{ type: 'text', text: '# 1. 进入 docker 目录\ncd docker\n\n# 2. 复制环境变量模板\ncp .env.example .env\n# 编辑 .env 配置域名、密钥等\n\n# 3. 启动服务\ndocker-compose up -d\n\n# 4. 查看日志\ndocker-compose logs -f' }
]},
{ type: 'heading', attrs: { level: 2 }, content: [{ type: 'text', text: '⚙️ 手动部署步骤' }] },
{ type: 'heading', attrs: { level: 3 }, content: [{ type: 'text', text: '1. 安装依赖' }] },
{ type: 'codeBlock', attrs: { language: 'bash' }, content: [
{ type: 'text', text: '# 更新系统\nsudo apt update && sudo apt upgrade -y\n\n# 安装 Node.js 20 (用于前端构建)\ncurl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -\nsudo apt install -y nodejs\n\n# 安装 pnpm\nnpm install -g pnpm\n\n# 安装 PocketBase (后端)\ncd /opt\nwget https://github.com/pocketbase/pocketbase/releases/download/v0.22.0/pocketbase_0.22.0_linux_amd64.zip\nunzip pocketbase_0.22.0_linux_amd64.zip\nchmod +x pocketbase\n\n# 安装 Nginx\nsudo apt install -y nginx\n\n# 安装 Certbot (SSL)\nsudo apt install -y certbot python3-certbot-nginx' }
]},
{ type: 'heading', attrs: { level: 3 }, content: [{ type: 'text', text: '2. 配置 PocketBase' }] },
{ type: 'codeBlock', attrs: { language: 'bash' }, content: [
{ type: 'text', text: '# 创建数据目录\nmkdir -p /opt/pocketbase/pb_data\nmkdir -p /opt/pocketbase/pb_migrations\nmkdir -p /opt/pocketbase/pb_public\n\n# 复制迁移文件\ncp -r /path/to/project/apps/pb_migrations/* /opt/pocketbase/pb_migrations/\n\n# 创建 systemd 服务\nsudo tee /etc/systemd/system/pocketbase.service > /dev/null <<EOF\n[Unit]\nDescription=PocketBase\nAfter=network.target\n\n[Service]\nType=simple\nUser=www-data\nWorkingDirectory=/opt/pocketbase\nExecStart=/opt/pocketbase/pocketbase serve --http=127.0.0.1:8090 --dir=/opt/pocketbase/pb_data\nRestart=on-failure\nRestartSec=5\nEnvironment=PB_ENCRYPTION_KEY=your-32-char-encryption-key\n\n[Install]\nWantedBy=multi-user.target\nEOF\n\n# 启动服务\nsudo systemctl daemon-reload\nsudo systemctl enable pocketbase\nsudo systemctl start pocketbase' }
]},
{ type: 'heading', attrs: { level: 3 }, content: [{ type: 'text', text: '3. 构建前端' }] },
{ type: 'codeBlock', attrs: { language: 'bash' }, content: [
{ type: 'text', text: 'cd /path/to/project/apps/web\npnpm install\npnpm build\n\n# 构建产物在 dist 目录,复制到 PocketBase 静态目录\ncp -r dist/* /opt/pocketbase/pb_public/' }
]},
{ type: 'heading', attrs: { level: 3 }, content: [{ type: 'text', text: '4. 配置 Nginx 反向代理' }] },
{ type: 'codeBlock', attrs: { language: 'nginx' }, content: [
{ type: 'text', text: 'server {\n listen 80;\n server_name your-domain.com;\n\n # 静态文件直接由 Nginx 服务\n location / {\n root /opt/pocketbase/pb_public;\n try_files $uri $uri/ /index.html;\n expires 1y;\n add_header Cache-Control "public, immutable";\n }\n\n # API 代理到 PocketBase\n location /api/ {\n proxy_pass http://127.0.0.1:8090;\n proxy_set_header Host $host;\n proxy_set_header X-Real-IP $remote_addr;\n proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n proxy_set_header X-Forwarded-Proto $scheme;\n proxy_http_version 1.1;\n proxy_set_header Upgrade $http_upgrade;\n proxy_set_header Connection "upgrade";\n }\n\n # Realtime WebSocket\n location /api/realtime {\n proxy_pass http://127.0.0.1:8090;\n proxy_http_version 1.1;\n proxy_set_header Upgrade $http_upgrade;\n proxy_set_header Connection "upgrade";\n proxy_set_header Host $host;\n proxy_read_timeout 86400;\n }\n\n # PocketBase Admin UI\n location /_/ {\n proxy_pass http://127.0.0.1:8090;\n proxy_set_header Host $host;\n proxy_set_header X-Real-IP $remote_addr;\n proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n proxy_set_header X-Forwarded-Proto $scheme;\n }\n}' }
]},
{ type: 'heading', attrs: { level: 3 }, content: [{ type: 'text', text: '5. 申请 SSL 证书' }] },
{ type: 'codeBlock', attrs: { language: 'bash' }, content: [
{ type: 'text', text: 'sudo certbot --nginx -d your-domain.com\n\n# 设置自动续期\nsudo systemctl enable certbot.timer' }
]},
{ type: 'heading', attrs: { level: 2 }, content: [{ type: 'text', text: '🔧 后续维护' }] },
{ type: 'heading', attrs: { level: 3 }, content: [{ type: 'text', text: '更新代码' }] },
{ type: 'codeBlock', attrs: { language: 'bash' }, content: [
{ type: 'text', text: 'cd /path/to/project\ngit pull\ncd apps/web\npnpm install\npnpm build\ncp -r dist/* /opt/pocketbase/pb_public/\nsudo systemctl reload nginx' }
]},
{ type: 'heading', attrs: { level: 3 }, content: [{ type: 'text', text: '备份数据' }] },
{ type: 'codeBlock', attrs: { language: 'bash' }, content: [
{ type: 'text', text: '# 备份 PocketBase 数据\ncp -r /opt/pocketbase/pb_data /backup/pocketbase_$(date +%Y%m%d_%H%M%S)\n\n# 或者使用 PocketBase 内置导出\n/opt/pocketbase/pocketbase dump --dir=/opt/pocketbase/pb_data --output=/backup/pb_dump_$(date +%Y%m%d).zip' }
]},
{ type: 'heading', attrs: { level: 3 }, content: [{ type: 'text', text: '查看日志' }] },
{ type: 'codeBlock', attrs: { language: 'bash' }, content: [
{ type: 'text', text: '# PocketBase 日志\nsudo journalctl -u pocketbase -f\n\n# Nginx 日志\nsudo tail -f /var/log/nginx/access.log\nsudo tail -f /var/log/nginx/error.log' }
]},
{ type: 'heading', attrs: { level: 2 }, content: [{ type: 'text', text: '🎯 常见问题' }] },
{ type: 'heading', attrs: { level: 3 }, content: [{ type: 'text', text: 'Q: 访问提示 502 Bad Gateway' }] },
{ type: 'paragraph', content: [{ type: 'text', text: 'A: 检查 PocketBase 是否运行:systemctl status pocketbase,查看日志排查错误。' }] }],
{ type: 'heading', attrs: { level: 3 }, content: [{ type: 'text', text: 'Q: 静态资源 404' }] },
{ type: 'paragraph', content: [{ type: 'text', text: 'A: 确认前端构建产物已复制到 /opt/pocketbase/pb_public/Nginx root 指向正确。' }] }],
{ type: 'heading', attrs: { level: 3 }, content: [{ type: 'text', text: 'Q: WebSocket 连接失败' }] },
{ type: 'paragraph', content: [{ type: 'text', text: 'A: Nginx 配置需添加 WebSocket 升级头,参考上面配置中的 /api/realtime 部分。' }] }],
{ type: 'heading', attrs: { level: 3 }, content: [{ type: 'text', text: 'Q: 文件上传大小限制' }] },
{ type: 'paragraph', content: [{ type: 'text', text: 'A: 修改 Nginx client_max_body_size 和 PocketBase 启动参数 --max-upload-size。' }] }],
],
}),
template: 'doc',
published: true,
sort_order: 5,
show_in_nav: true,
nav_label: '搭建教程',
},
]
for (const page of pages) {
const record = new Record(pagesCollection, page)
dao.saveRecord(record)
}
// 创建示例文章
const samplePosts = [
{
title: 'iPhone 16 Pro Max 深度评测:影像旗舰的新高度',
slug: 'iphone-16-pro-max-review',
excerpt: JSON.stringify({
type: 'doc',
content: [
{ type: 'paragraph', content: [{ type: 'text', text: '苹果最新旗舰 iPhone 16 Pro Max 带来了更大的传感器、更强的 A18 Pro 芯片和全新的相机控制键。经过两周的深度体验,这究竟是值得升级的「真香」机型,还是挤牙膏的过渡之作?' }] }
]
}),
content: JSON.stringify({
type: 'doc',
content: [
{ type: 'heading', attrs: { level: 2 }, content: [{ type: 'text', text: '前言:期待已久的影像旗舰' }] },
{ type: 'paragraph', content: [{ type: 'text', text: '每年的 9 月,都是科技圈最热闹的时候。今年,iPhone 16 系列如期而至,而 Pro Max 版本作为「安卓机皇」的对标产品,自然成为了所有人关注的焦点。' }] },
{ type: 'heading', attrs: { level: 2 }, content: [{ type: 'text', text: '外观与手感:熟悉的配方' }] },
{ type: 'paragraph', content: [{ type: 'text', text: '依然是钛金属边框,依然是磨砂玻璃后盖,重量控制在 227g,单手握持感比上一代略好。新增的「沙漠钛金属」配色在光线下呈现微妙的暖金色调,质感极佳。' }] }],
{ type: 'heading', attrs: { level: 2 }, content: [{ type: 'text', text: '相机控制键:一键直达的惊喜' }] },
{ type: 'paragraph', content: [{ type: 'text', text: '这是本代最大的硬件创新。侧边的压感按键支持轻按对焦、重按拍照、滑动变焦,肌肉记忆建立后,抓拍速度确实快了不少。' }] }],
{ type: 'heading', attrs: { level: 2 }, content: [{ type: 'text', text: '影像系统:4800 万像素主摄 + 5 倍潜望长焦' }] },
{ type: 'paragraph', content: [{ type: 'text', text: '主摄升级为 1/1.28 英寸传感器,进光量提升显著。夜景模式下,噪点控制、动态范围、细节保留均达到行业第一梯队。5 倍潜望长焦在 5x-10x 区间表现惊艳,甚至可用于人像拍摄。' }] }],
{ type: 'heading', attrs: { level: 2 }, content: [{ type: 'text', text: '性能与续航:A18 Pro 的效能比魔法' }] },
{ type: 'paragraph', content: [{ type: 'text', text: '3nm 工艺的 A18 Pro 在 GeekBench 6 单核跑分突破 3500,多核超 9000。实测《原神》最高画质 60 帧满帧运行 1 小时,机身最高温度 42.3°C,功耗控制令人印象深刻。续航方面,重度使用 6.5 小时屏亮,轻松跑过一天。' }] }],
{ type: 'heading', attrs: { level: 2 }, content: [{ type: 'text', text: '总结:值得买吗?' }] },
{ type: 'paragraph', content: [{ type: 'text', text: '如果你是 iPhone 14 Pro 或更早机型用户,且重视影像、追求极致性能,iPhone 16 Pro Max 是毫不犹豫的「真香」选择。但如果你手持 15 Pro Max,除非极度需要相机控制键或 5 倍长焦,否则再战一年更划算。' }] }],
]
}),
cover: '',
category: 'reviews',
tags: ['phone', 'review', 'recommend'],
author: '', // 将在创建时填入 admin id
published: true,
published_at: new Date().toISOString(),
featured: true,
pinned: false,
allow_comment: true,
reading_time: 12,
seo_title: 'iPhone 16 Pro Max 深度评测:影像旗舰新高度 | 云升数码',
seo_description: '两周深度体验 iPhone 16 Pro Max:相机控制键实测、5倍潜望长焦样张、A18 Pro 性能功耗、续航实测,告诉你值不值得买。',
seo_keywords: 'iPhone 16 Pro Max,评测,影像,相机控制键,A18 Pro',
},
{
title: '2024 年双十一笔记本选购指南:避坑与真香推荐',
slug: '2024-double11-laptop-guide',
excerpt: JSON.stringify({
type: 'doc',
content: [
{ type: 'paragraph', content: [{ type: 'text', text: '一年一度双十一大促来袭,笔记本市场百花齐放。本文从预算、用途、参数三个维度,为你梳理 2024 年最值得买、最不值得买的笔记本清单,助你不花冤枉钱。' }] }
]
}),
content: JSON.stringify({
type: 'doc',
content: [
{ type: 'heading', attrs: { level: 2 }, content: [{ type: 'text', text: '开篇:别被参数忽悠了' }] },
{ type: 'paragraph', content: [{ type: 'text', text: '每年双十一,商家最爱玩「首发价」「限时抢」「赠品堆砌」这一套。记住一个核心原则:CPU 和屏幕决定下限,散热和做工决定上限。' }] }],
{ type: 'heading', attrs: { level: 2 }, content: [{ type: 'text', text: '💰 3000-4000 元:学生党/轻办公首选' }] },
{ type: 'bulletList', content: [
{ type: 'listItem', content: [{ type: 'paragraph', content: [{ type: 'text', text: '✅ 真香:Redmi Book Pro 14 2024OLED 屏、标压 U、金属机身)' }] }] },
{ type: 'listItem', content: [{ type: 'paragraph', content: [{ type: 'text', text: '✅ 真香:联想小新 Pro 14 2024 酷睿版(做工扎实、售后好、扩展性强)' }] }] },
{ type: 'listItem', content: [{ type: 'paragraph', content: [{ type: 'text', text: '❌ 避坑:某些「独显版」入门级 MX550,性能不如核显,纯坑钱' }] }] },
]},
{ type: 'heading', attrs: { level: 2 }, content: [{ type: 'text', text: '💰 5000-7000 元:全能本/轻薄游戏本甜点区' }] },
{ type: 'bulletList', content: [
{ type: 'listItem', content: [{ type: 'paragraph', content: [{ type: 'text', text: '🏆 首推:ROG 幻 14 Air 2024R9 8945HS + RTX 40601.15kgOLED 屏,颜值性能全要)' }] }] },
{ type: 'listItem', content: [{ type: 'paragraph', content: [{ type: 'text', text: '🏆 首推:联想拯救者 Y7000P 2024i7-14650HX + RTX 4060,散热强、性价比高,不介意重可冲)' }] }] },
{ type: 'listItem', content: [{ type: 'paragraph', content: [{ type: 'text', text: '✅ 备选:华硕天选 5 Pro、机械革命无界 14X、ThinkBook 14+ 2024' }] }] },
]},
{ type: 'heading', attrs: { level: 2 }, content: [{ type: 'text', text: '💰 8000-12000 元:高性能游戏本/创作者本' }] },
{ type: 'bulletList', content: [
{ type: 'listItem', content: [{ type: 'paragraph', content: [{ type: 'text', text: '🏆 游戏首选:ROG 星幻 X 2024 / 惠普暗影精灵 10 ProRTX 4070/4080,满血释放)' }] }] },
{ type: 'listItem', content: [{ type: 'paragraph', content: [{ type: 'text', text: '🏆 创作首选:MacBook Pro 14 M3 Pro/Max(生态闭环、色准极佳、续航无敌,不玩游戏选它)' }] }] },
{ type: 'listItem', content: [{ type: 'paragraph', content: [{ type: 'text', text: '✅ Windows 创作备选:华硕 ProArt 创 16 2024、戴尔 Precision 5680' }] }] },
]},
{ type: 'heading', attrs: { level: 2 }, content: [{ type: 'text', text: '💰 12000+ 元:旗舰中的旗舰' }] },
{ type: 'bulletList', content: [
{ type: 'listItem', content: [{ type: 'paragraph', content: [{ type: 'text', text: 'ROG 幻 X 2024(双屏、液金、RTX 4090,预算无上限的终极答案)' }] }] },
{ type: 'listItem', content: [{ type: 'paragraph', content: [{ type: 'text', text: 'MacBook Pro 16 M3 Max(专业视频/音频/代码创作,残值率高)' }] }] },
]},
{ type: 'heading', attrs: { level: 2 }, content: [{ type: 'text', text: '🎯 选购避坑清单' }] },
{ type: 'orderedList', content: [
{ type: 'listItem', content: [{ type: 'paragraph', content: [{ type: 'text', text: '认准「标压」CPU(H/HX 系列),拒绝低压版(U 系列)做主力机' }] }] },
{ type: 'listItem', content: [{ type: 'paragraph', content: [{ type: 'text', text: '屏幕必须 100% sRGB 以上,最好 100% DCI-P3OLED > IPS' }] }] },
{ type: 'listItem', content: [{ type: 'paragraph', content: [{ type: 'text', text: '内存 16GB 起步,32GB 安心,焊死内存尽量买大内存版' }] }] },
{ type: 'listItem', content: [{ type: 'paragraph', content: [{ type: 'text', text: 'SSD 1TB 起,PCIe 4.0,预留 M.2 位更佳' }] }] },
{ type: 'listItem', content: [{ type: 'paragraph', content: [{ type: 'text', text: '接口要全:USB-C (支持 PD 充电/DP)、USB-A、HDMI、SD 卡槽' }] }] },
{ type: 'listItem', content: [{ type: 'paragraph', content: [{ type: 'text', text: '查散热评测:同配置不同散热,性能释放相差 20%+' }] }] },
]},
{ type: 'heading', attrs: { level: 2 }, content: [{ type: 'text', text: '📅 购买时机建议' }] },
{ type: 'paragraph', content: [{ type: 'text', text: '预售期(10.20-11.10)定金膨胀力度大,但需锁定款式;正式期(11.11 当天)部分款式补贴到手价更低,但热门款易断货。建议:确定目标款 → 预售期付定金 → 尾款期观望补贴 → 最后一小时决策。' }] }],
]
}),
cover: '',
category: 'tutorials',
tags: ['laptop', 'tutorial', 'recommend', 'value', 'avoid'],
author: '',
published: true,
published_at: new Date(Date.now() - 86400000).toISOString(),
featured: true,
reading_time: 15,
seo_title: '2024 双十一笔记本选购指南:避坑与真香推荐全清单 | 云升数码',
seo_description: '2024 双十一笔记本怎么选?3000-12000 元全价位段真香/避坑清单,从参数到实测教你不花冤枉钱。',
seo_keywords: '双十一,笔记本,选购指南,推荐,避坑,性价比',
},
{
title: 'Sony WH-1000XM5 使用半年长测:降噪之王的统治力还在吗?',
slug: 'sony-wh-1000xm5-long-term-review',
excerpt: JSON.stringify({
type: 'doc',
content: [
{ type: 'paragraph', content: [{ type: 'text', text: '作为降噪耳机领域的「长青树」,WH-1000XM5 发布已超两年。半年实战体验,聊聊它在 2024 年还能不能打,以及有哪些被忽略的缺点。' }] }
]
}),
content: JSON.stringify({
type: 'doc',
content: [
{ type: 'heading', attrs: { level: 2 }, content: [{ type: 'text', text: '前言:为什么现在还要测 XM5' }] },
{ type: 'paragraph', content: [{ type: 'text', text: '市场上 Bose QC Ultra、Apple AirPods Max、技巧 Ace 5 等强敌环伺,XM5 似乎成了「上一代旗舰」。但销量数据显示,它依然是千元以上降噪耳机的销量冠军。' }] }],
{ type: 'heading', attrs: { level: 2 }, content: [{ type: 'text', text: '降噪表现:依然是标杆' }] },
{ type: 'paragraph', content: [{ type: 'text', text: '地铁、飞机、办公室、咖啡厅全场景测试,低频消噪深度行业顶尖,人声残留极少。自适应声控(根据气压/环境自动调节)在起飞降落时体感明显。' }] }],
{ type: 'heading', attrs: { level: 2 }, content: [{ type: 'text', text: '音质:V 型调音,LDAC 加持' }] },
{ type: 'paragraph', content: [{ type: 'text', text: '低频下潜深、量感足但不拖泥带水;高频延伸好,LDAC 传输下解析力在蓝牙耳机中第一梯队。EQ 调节范围大,可调出监听风。' }] }],
{ type: 'heading', attrs: { level: 2 }, content: [{ type: 'text', text: '佩戴舒适度:褒贬不一' }] },
{ type: 'paragraph', content: [{ type: 'text', text: '头梁无海绵垫、耳罩包裹感一般,大头/戴眼镜用户 2 小时后会有压迫感。夏天闷耳严重。建议换装第三方记忆棉耳罩(如 Dekoni)。' }] }],
{ type: 'heading', attrs: { level: 2 }, content: [{ type: 'text', text: '续航与充电:无焦虑' }] },
{ type: 'paragraph', content: [{ type: 'text', text: '开启降噪 30 小时、关闭 40 小时,实测符合官方数据。3 分钟充电 3 小时听歌,Type-C 接口通用性强。' }] }],
{ type: 'heading', attrs: { level: 2 }, content: [{ type: 'text', text: '槽点:不折叠、无 aptX、连接切换慢' }] },
{ type: 'bulletList', content: [
{ type: 'listItem', content: [{ type: 'paragraph', content: [{ type: 'text', text: '收纳体积大,随身包塞不下' }] }] },
{ type: 'listItem', content: [{ type: 'paragraph', content: [{ type: 'text', text: '仅支持 SBC/AAC/LDAC,安卓用户无 aptX Adaptive' }] }] },
{ type: 'listItem', content: [{ type: 'paragraph', content: [{ type: 'text', text: '多点连接切换延迟 3-5 秒,不如 Apple 生态丝滑' }] }] },
{ type: 'listItem', content: [{ type: 'paragraph', content: [{ type: 'text', text: '触控区误触率高,冬天戴手套不可用' }] }] },
]},
{ type: 'heading', attrs: { level: 2 }, content: [{ type: 'text', text: '结论:买不买?' }] },
{ type: 'paragraph', content: [{ type: 'text', text: '追求极致降噪、音质均衡、预算 2000 元左右 → 闭眼入。\n需折叠收纳、aptX、极致舒适、Apple 生态 → 看别家。' }] }],
]
}),
cover: '',
category: 'reviews',
tags: ['headphones', 'audio', 'review', 'long-term'],
author: '',
published: true,
published_at: new Date(Date.now() - 172800000).toISOString(),
featured: false,
reading_time: 10,
seo_title: 'Sony WH-1000XM5 半年长测:降噪之王统治力还在吗? | 云升数码',
seo_description: 'WH-1000XM5 使用半年实测:降噪/音质/舒适度/续航全维度复盘,揭露不折叠/无aptX/切换慢等真实槽点。',
seo_keywords: 'WH-1000XM5,索尼,降噪耳机,长测,评测,音质',
},
]
for (const post of samplePosts) {
post.author = adminRecord.id
post.category = categoryRecords[post.category]
post.tags = post.tags.map(t => tagRecords[t])
const record = new Record(postsCollection, post)
dao.saveRecord(record)
}
})