- 后台全面引入 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>
7.2 KiB
7.2 KiB
呼籁文旅官网 (hulai-website)
项目概述
呼籁文旅(呼伦贝尔旅行公司)的官方网站,包含前台展示和后台管理系统。
技术栈
| 层级 | 技术 | 版本 |
|---|---|---|
| 框架 | Nuxt 3 | 3.17.5 |
| 前端 | Vue 3 (Composition API + <script setup>) |
— |
| 服务端 | Nitro (Nuxt 内置) | — |
| 数据库 | SQLite + better-sqlite3 | 12.8.0 |
| ORM | Drizzle ORM | 0.45.1 |
| 样式 | LESS (全局变量 + Mixins) | — |
| 包管理 | pnpm | — |
项目结构
hulai-website/
├── assets/less/ # 全局 LESS 变量和 Mixins
├── components/
│ ├── admin/ # 后台复用组件
│ │ ├── DataTable.vue # 分页表格(搜索、分页、sticky 表头、插槽)
│ │ ├── ImageUpload.vue # 图片上传(拖拽、预览、URL 输入)
│ │ └── SeasonProduct.vue # 季节产品编辑器
│ └── ... # 前台组件
├── composables/
│ ├── useAdmin.js # 后台认证(token 管理、adminFetch)
│ ├── usePublicApi.js # 前台 API
│ └── useSEO.js # SEO 配置
├── layouts/
│ ├── admin.vue # 后台布局(侧栏 + 内容区)
│ └── default.vue # 前台布局
├── middleware/
│ └── admin.js # 后台路由守卫
├── pages/
│ ├── admin/ # 后台页面
│ │ ├── login.vue # 登录页(无 layout)
│ │ ├── index.vue # 仪表盘
│ │ ├── articles/ # 新闻管理(index.vue 列表 + [id].vue 编辑)
│ │ ├── blogs/ # 博客管理
│ │ ├── reviews/ # 评论管理
│ │ ├── faqs/ # FAQ 管理
│ │ ├── gallery/ # 图库管理
│ │ ├── stories/ # 故事管理
│ │ ├── submissions/ # 表单提交(只读)
│ │ ├── navigation.vue # 导航菜单编辑
│ │ └── content/ # 站点内容编辑
│ │ ├── [key].vue # JSON 编辑器(兜底)
│ │ ├── products/ # 夏季产品(index + [idx])
│ │ ├── autumn-products/
│ │ ├── winter-products/
│ │ ├── pricing/ # 价格配置
│ │ ├── selector/ # 产品选择器
│ │ ├── destinations-detail/
│ │ └── *.vue # 各内容可视化编辑器
│ └── ... # 前台页面
├── server/
│ ├── api/admin/ # 后台 REST API
│ ├── database/
│ │ ├── schema.js # Drizzle 表定义
│ │ ├── index.js # DB 连接单例
│ │ ├── migrate.js # 建表
│ │ └── seed.js # 种子数据(从 JSON 导入)
│ └── utils/
│ ├── auth.js # Session 管理(SQLite 存储,7 天过期)
│ ├── db.js # useDB() 服务端工具
│ ├── pagination.js # parsePagination() 分页参数解析
│ └── ...
└── public/uploads/ # 上传文件存储
多角色 Agent 工作流
本项目使用 5 个协作 Agent,通过 /workflow 命令调度:
| 角色 | 职责 | 约束 |
|---|---|---|
| PM | 分析需求、拆解任务、分配执行、验收结果 | 只分析不写代码 |
| Frontend | 前端页面开发(Vue 组件、页面、样式) | 只改前端代码 |
| Backend | 后端 API、数据库、服务端逻辑 | 只改 server/ 代码 |
| UI/UX | 出设计方案、页面结构、交互规格 | 只出方案不写代码 |
| Tester | 代码审查、质量检测、出测试报告 | 只测不改 |
工作流阶段
Phase 1: PM 分析需求 → 拆解任务
Phase 2: UI/UX 设计(如有新页面)
Phase 3: Backend 开发(如有 API 变更)
Phase 4: Frontend 开发
Phase 5: Tester 测试验证
Phase 6: 修复闭环(最多 3 轮)
Phase 7: PM 验收 → 提交代码
命令
| 命令 | 用途 |
|---|---|
/workflow |
全自动工作流,一条命令走完全流程 |
/pm |
单独启动产品经理分析 |
/frontend |
单独启动前端开发 |
/backend |
单独启动后端开发 |
/uiux |
单独启动 UI/UX 设计 |
/tester |
单独启动测试验证 |
编码规范
前端页面(pages/admin/)
列表 + 编辑分离模式:
- 列表页:
index.vue,使用AdminDataTable组件,带搜索、分页 - 编辑页:
[id].vue(数据库表)或[idx].vue(JSON 数组项) - 面包屑导航 + 返回链接
- 底部 sticky 保存栏
页面模板:
<script setup>
definePageMeta({ layout: 'admin', middleware: 'admin' })
const { adminFetch } = useAdmin()
</script>
API 调用统一用 adminFetch,自动带 token、401 自动登出。
后端 API(server/api/admin/)
认证中间件:
const user = await requireAdmin(event)
分页查询:
const { page, limit, offset, search, sort } = parsePagination(event)
响应格式(列表):
{ items: [...], total, page, limit, totalPages }
响应格式(单条):
{ id, ...fields }
数据库(Drizzle ORM)
- 表定义在
server/database/schema.js - 使用
useDB()获取数据库实例 - 导入操作符:
import { eq, desc, like } from 'drizzle-orm'
站点内容(site_content 表)
存储复杂 JSON 配置的键值对:
- 读取:
GET /api/admin/site-content?key=xxx - 更新:
PUT /api/admin/site-contentbody:{ key, data } - 单项读取:
GET /api/admin/site-content/item?key=xxx&index=0 - 单项更新:
PUT /api/admin/site-content/itembody:{ key, index, item }
样式规范
后台页面使用 scoped CSS,主色调:
- 主色:
#3a7d44(绿色) - 悬停:
#2d6235 - 文字:
#111827 - 次要文字:
#6b7280 - 边框:
#e5e7eb - 背景:
#f0f2f5
复用组件:
AdminDataTable— 带分页搜索的表格AdminImageUpload— 拖拽上传图片AdminSeasonProduct— 季节产品编辑器
命名约定
| 类型 | 命名 | 示例 |
|---|---|---|
| 页面文件 | kebab-case | winter-products/ |
| 组件 | PascalCase | DataTable.vue |
| API 路由 | kebab-case | site-content.get.js |
| 数据库表 | camelCase (Drizzle) | galleryItems |
| CSS class | kebab-case | .page-header |
记忆系统
每个 Agent 有 4 个记忆文件,存储在 .claude/agents/memory/{role}/ 下:
| 角色 | 文件 | 内容 |
|---|---|---|
| PM | decisions / patterns / lessons / priorities | 决策记录 / 业务模式 / 经验教训 / 优先级策略 |
| Frontend | patterns / pitfalls / components / pages | 代码模式 / 踩坑记录 / 组件清单 / 页面模式 |
| Backend | patterns / pitfalls / api-design / database | 代码模式 / 踩坑记录 / API 设计 / 数据库经验 |
| UI/UX | design-system / page-patterns / feedback / consistency | 设计系统 / 页面模式 / 反馈记录 / 一致性 |
| Tester | common-bugs / checklist / api-issues / quality-metrics | 常见 Bug / 检查清单 / API 问题 / 质量指标 |