feat: add WonderQ admin UI
1
.env.example
Normal file
@@ -0,0 +1 @@
|
||||
VITE_API_BASE_URL="http://localhost:4000"
|
||||
141
.gitignore
vendored
@@ -1,138 +1,7 @@
|
||||
# ---> Node
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
lerna-debug.log*
|
||||
.pnpm-debug.log*
|
||||
|
||||
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
*.lcov
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
bower_components
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# Snowpack dependency directory (https://snowpack.dev/)
|
||||
web_modules/
|
||||
|
||||
# TypeScript cache
|
||||
*.tsbuildinfo
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Optional stylelint cache
|
||||
.stylelintcache
|
||||
|
||||
# Microbundle cache
|
||||
.rpt2_cache/
|
||||
.rts2_cache_cjs/
|
||||
.rts2_cache_es/
|
||||
.rts2_cache_umd/
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
# dotenv environment variable files
|
||||
node_modules/
|
||||
dist/
|
||||
.env
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
.env.local
|
||||
|
||||
# parcel-bundler cache (https://parceljs.org/)
|
||||
.cache
|
||||
.parcel-cache
|
||||
|
||||
# Next.js build output
|
||||
.next
|
||||
out
|
||||
|
||||
# Nuxt.js build / generate output
|
||||
.nuxt
|
||||
dist
|
||||
|
||||
# Gatsby files
|
||||
.cache/
|
||||
# Comment in the public line in if your project uses Gatsby and not Next.js
|
||||
# https://nextjs.org/blog/next-9-1#public-directory-support
|
||||
# public
|
||||
|
||||
# vuepress build output
|
||||
.vuepress/dist
|
||||
|
||||
# vuepress v2.x temp and cache directory
|
||||
.temp
|
||||
.cache
|
||||
|
||||
# vitepress build output
|
||||
**/.vitepress/dist
|
||||
|
||||
# vitepress cache directory
|
||||
**/.vitepress/cache
|
||||
|
||||
# Docusaurus cache and generated files
|
||||
.docusaurus
|
||||
|
||||
# Serverless directories
|
||||
.serverless/
|
||||
|
||||
# FuseBox cache
|
||||
.fusebox/
|
||||
|
||||
# DynamoDB Local files
|
||||
.dynamodb/
|
||||
|
||||
# TernJS port file
|
||||
.tern-port
|
||||
|
||||
# Stores VSCode versions used for testing VSCode extensions
|
||||
.vscode-test
|
||||
|
||||
# yarn v2
|
||||
.yarn/cache
|
||||
.yarn/unplugged
|
||||
.yarn/build-state.yml
|
||||
.yarn/install-state.gz
|
||||
.pnp.*
|
||||
|
||||
*.log
|
||||
coverage/
|
||||
.vite/
|
||||
|
||||
140
AGENTS.md
Normal file
@@ -0,0 +1,140 @@
|
||||
# WonderQ-Admin-UI Agent 工作说明
|
||||
|
||||
## 项目定位
|
||||
|
||||
WonderQ-Admin-UI 是独立的 WonderQ 后台管理前端,用于维护小程序/H5 前台的首页结构、目的地、线路商品、活动入口和客户需求线索。
|
||||
|
||||
当前项目是一个轻量单页后台应用,技术栈为 Vite + React + TypeScript + 普通 CSS。前端通过 `/api/admin/...` 调用后端管理接口,本地开发时由 Vite 代理到后端服务。
|
||||
|
||||
## 目录结构
|
||||
|
||||
```text
|
||||
WonderQ-Admin-UI/
|
||||
├─ AGENTS.md # Agent 项目规则
|
||||
├─ README.md # 项目启动说明
|
||||
├─ docs/
|
||||
│ ├─ README.md # 文档索引
|
||||
│ └─ admin-backend-plan.md # 后台管理规划文档
|
||||
├─ public/
|
||||
│ └─ assets/
|
||||
│ ├─ guizhou/ # 贵州目的地展示图
|
||||
│ └─ source/ # 原始/通用静态素材与 manifest
|
||||
├─ src/
|
||||
│ ├─ App.tsx # 后台主界面、页面状态、表单和业务 UI
|
||||
│ ├─ api.ts # Admin API 类型、Token 管理和请求封装
|
||||
│ ├─ main.tsx # React 挂载入口
|
||||
│ ├─ styles.css # 全局样式与响应式布局
|
||||
│ └─ vite-env.d.ts # Vite 类型声明
|
||||
├─ index.html # Vite HTML 入口
|
||||
├─ package.json # 脚本与依赖
|
||||
├─ tsconfig.json # TypeScript 严格模式配置
|
||||
├─ vite.config.ts # Vite/React/本地 API 代理配置
|
||||
└─ yarn.lock # Yarn 依赖锁文件
|
||||
```
|
||||
|
||||
## 模块分工
|
||||
|
||||
- `src/App.tsx`:集中实现登录页、侧边导航、结构维护、首页/目的地维护、商品维护、线索跟进、Toast 提示等后台 UI。
|
||||
- `src/api.ts`:定义 `Product`、`Destination`、`Lead`、`SiteConfig` 等接口类型,封装登录、商品、目的地、站点配置、线索、发布和重置接口。
|
||||
- `src/styles.css`:全局布局、后台工作台、表格/表单、商品编辑器、移动端适配等样式。
|
||||
- `public/assets/`:前台/后台预览用静态图片资源,代码中保留 `/assets/...` 路径引用。
|
||||
- `docs/`:后台规划与后续协作边界,涉及后端 API 和数据模型时先参考这里,再看后端仓库文档。
|
||||
|
||||
## 启动与构建
|
||||
|
||||
依赖安装:
|
||||
|
||||
```bash
|
||||
yarn install
|
||||
```
|
||||
|
||||
本地开发:
|
||||
|
||||
```bash
|
||||
yarn dev
|
||||
```
|
||||
|
||||
默认访问地址:
|
||||
|
||||
```text
|
||||
http://localhost:5601
|
||||
```
|
||||
|
||||
本地联调要求:
|
||||
|
||||
- 后端 Admin API 默认运行在 `http://localhost:4000`。
|
||||
- `vite.config.ts` 将 `/api` 代理到本地后端。
|
||||
- 如需改 API 地址,优先使用环境变量 `VITE_API_BASE_URL`,不要硬编码生产地址。
|
||||
|
||||
类型检查与生产构建:
|
||||
|
||||
```bash
|
||||
yarn build
|
||||
```
|
||||
|
||||
构建产物预览:
|
||||
|
||||
```bash
|
||||
yarn preview
|
||||
```
|
||||
|
||||
默认预览端口为 `5602`。
|
||||
|
||||
## 测试流程
|
||||
|
||||
当前 `package.json` 未配置独立测试脚本。提交前至少执行:
|
||||
|
||||
```bash
|
||||
yarn build
|
||||
```
|
||||
|
||||
该命令会先运行 `tsc --noEmit`,再执行 Vite 生产构建。涉及 UI 布局、交互或接口行为时,还需本地启动页面并手动验证关键流程。
|
||||
|
||||
## 部署规范
|
||||
|
||||
- 生产发布使用 `yarn build` 生成 `dist/`。
|
||||
- `dist/` 可交给 Nginx、CDN 或静态托管服务部署。
|
||||
- 生产环境 API 地址必须通过部署环境变量配置,不要提交 `.env`、`.env.local` 或任何包含密钥的配置。
|
||||
- 后台接口、数据库、权限、发布/回滚能力属于后端仓库边界,本仓库只维护管理前端。
|
||||
|
||||
## 代码风格
|
||||
|
||||
- 使用 TypeScript 严格模式,新增代码必须有明确类型,避免 `any`。
|
||||
- React 采用函数组件和 Hooks,不引入 class component。
|
||||
- 遵循现有单文件轻量结构;未获授权前不要主动拆分大型组件或引入状态管理库。
|
||||
- UI 图标优先复用 `lucide-react`。
|
||||
- 样式优先沿用 `src/styles.css` 的类名、色彩、间距和 6-8px 圆角习惯。
|
||||
- API 访问统一走 `src/api.ts` 的 `request` 封装,不在组件里重复拼接鉴权逻辑。
|
||||
- 中文文案文件按 UTF-8 处理;修改前确认编辑器编码,避免造成乱码。
|
||||
|
||||
## 命名规范
|
||||
|
||||
- 组件、类型使用 PascalCase,例如 `ProductManager`、`SiteConfig`。
|
||||
- 函数、变量使用 camelCase,例如 `getProducts`、`selectedId`。
|
||||
- 联合类型字面量使用小写英文,例如 `"draft"`、`"published"`、`"leads"`。
|
||||
- CSS class 沿用 kebab-case,例如 `.admin-shell`、`.product-table`。
|
||||
- API 类型与后端字段保持同名,避免在前端私自改字段语义。
|
||||
|
||||
## 开发准则
|
||||
|
||||
- 默认先读相关文件和现有模式,再修改。
|
||||
- 只处理用户明确要求的范围,不额外加功能。
|
||||
- 修改前确认是否涉及接口契约、登录鉴权、发布操作或静态资源路径。
|
||||
- 不展示、不输出、不提交 Token、密码、密钥、真实客户手机号等敏感信息。
|
||||
- 不新增依赖,除非用户明确授权并说明理由。
|
||||
- 不提交 `node_modules/`、`dist/`、`.env`、`.env.local`、日志或覆盖率文件。
|
||||
- 涉及删除、批量移动、重命名资源文件时必须先征得用户明确授权。
|
||||
|
||||
## 锁定文件与高风险区域
|
||||
|
||||
未经用户明确授权,不得改动:
|
||||
|
||||
- `.env`、`.env.local`、任何生产环境变量或密钥配置。
|
||||
- `vite.config.ts` 中的代理、端口和构建配置。
|
||||
- `tsconfig.json` 的严格类型配置。
|
||||
- `package.json`、`yarn.lock` 的依赖与脚本。
|
||||
- `src/api.ts` 的接口路径、Token 存储键、鉴权头和类型契约。
|
||||
- `public/assets/` 下已被页面引用的图片资源和 `manifest.json`。
|
||||
- `docs/admin-backend-plan.md` 中的后端规划,除非任务明确要求更新文档。
|
||||
|
||||
本仓库没有数据库配置文件;数据库、Prisma、权限和生产后端配置在后端仓库维护。
|
||||
31
README.md
@@ -1,2 +1,31 @@
|
||||
# WonderQ-Admin-UI
|
||||
# WonderQ-Admin-UI
|
||||
|
||||
独立的 WonderQ 后台管理前端,基于 Vite、React、TypeScript 和普通 CSS。
|
||||
|
||||
## 本地启动
|
||||
|
||||
1. 安装依赖:
|
||||
|
||||
```bash
|
||||
yarn install
|
||||
```
|
||||
|
||||
2. 确认后端 API 运行在 `http://localhost:4000`。
|
||||
|
||||
3. 启动后台 UI:
|
||||
|
||||
```bash
|
||||
yarn dev
|
||||
```
|
||||
|
||||
访问:http://localhost:5601
|
||||
|
||||
默认后台账号由 `WonderQ-Admin` 提供:`admin@example.com / ChangeMe123!`。
|
||||
|
||||
## 目录说明
|
||||
|
||||
- `src/`:后台管理 UI 和 API 客户端。
|
||||
- `public/assets/`:后台预览所需静态资源,保留 `/assets/...` 引用方式。
|
||||
- `vite.config.ts`:开发环境将 `/api` 代理到 `http://localhost:4000`。
|
||||
|
||||
本仓库已经独立,不再依赖 `WonderQ-MiniAPP` 的相对路径。
|
||||
|
||||
7
docs/README.md
Normal file
@@ -0,0 +1,7 @@
|
||||
# WonderQ-Admin-UI 文档
|
||||
|
||||
本目录存放后台管理前端相关文档。
|
||||
|
||||
- `admin-backend-plan.md`:从原 MiniAPP 迁出的后台管理规划,保留管理模块、页面能力和与后端 API 的协作边界。
|
||||
|
||||
后端 API 文档位于 `D:\www\znkj\WonderQ-Admin\docs`。
|
||||
404
docs/admin-backend-plan.md
Normal file
@@ -0,0 +1,404 @@
|
||||
# H5 后台管理系统规划
|
||||
|
||||
## 目标
|
||||
|
||||
为当前鸿鹄逸游 H5 项目建设一套可真实上线维护的后台系统,让运营人员可以管理首页内容、目的地、线路产品、活动专题、客户需求、订单线索、消息和客服配置,而不是继续依赖改代码发布。
|
||||
|
||||
当前 H5 主要是一个静态 Vite + React 应用:
|
||||
|
||||
- 首页配置来自 `src/content.ts`:轮播、目的地、主题卡、线路分区、底部 CTA。
|
||||
- 线路产品来自 `src/generated-products.json`:48 条产品卡片。
|
||||
- 目的地搜索、活动页、需求表单、消息、订单、客服经理等流程目前集中写在 `src/App.tsx`。
|
||||
- 图片资源在 `public/assets/source`,约 115 个文件。
|
||||
|
||||
后台建设的核心不是简单加一个管理页面,而是把这些静态内容拆成稳定的数据模型,并提供发布、审核、回滚、权限、日志和运维能力。
|
||||
|
||||
## 推荐架构
|
||||
|
||||
### 代码组织
|
||||
|
||||
建议从单一前端项目演进为 TypeScript monorepo:
|
||||
|
||||
```text
|
||||
apps/
|
||||
h5/ # 当前 Vite React H5,可从现有 src/ 迁移
|
||||
admin/ # 后台管理端,React + Ant Design Pro 或 shadcn/ui
|
||||
api/ # 后端 API,NestJS 或 Fastify
|
||||
packages/
|
||||
shared/ # 共享类型、校验 schema、接口 DTO
|
||||
config/ # eslint/tsconfig 等公共配置
|
||||
```
|
||||
|
||||
保守可落地方案:
|
||||
|
||||
- 前台 H5:继续 Vite + React,先只改数据来源。
|
||||
- 后台 Admin:React + Ant Design Pro。原因是后台表格、筛选、表单、权限、布局成熟,开发快。
|
||||
- API:NestJS + Prisma。原因是 TypeScript 体系一致,权限、模块化、OpenAPI、测试更规整。
|
||||
- 数据库:PostgreSQL。
|
||||
- 缓存/队列:Redis,先用于发布缓存、短信/通知任务、操作频控。
|
||||
- 文件存储:阿里 OSS、腾讯 COS 或 S3 兼容对象存储。
|
||||
- 部署:Docker + Nginx + CDN,后续可上云托管或 Kubernetes。
|
||||
|
||||
### 服务边界
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
H5["H5 前台"] --> API["Public API"]
|
||||
Admin["后台管理端"] --> AdminAPI["Admin API"]
|
||||
API --> DB[("PostgreSQL")]
|
||||
AdminAPI --> DB
|
||||
AdminAPI --> OSS["对象存储"]
|
||||
AdminAPI --> Redis[("Redis")]
|
||||
CDN["CDN"] --> H5
|
||||
CDN --> OSS
|
||||
```
|
||||
|
||||
## 后台功能模块
|
||||
|
||||
### 1. 工作台
|
||||
|
||||
- 今日新增需求、待跟进需求、待确认订单、上架线路数。
|
||||
- 最近发布记录、失败任务、异常日志。
|
||||
- 快捷入口:新建线路、新建活动、发布首页、导出需求。
|
||||
|
||||
### 2. 首页装修
|
||||
|
||||
对应当前 `src/content.ts`。
|
||||
|
||||
- 轮播管理:图片、标题、副标题、跳转类型、排序、上下架。
|
||||
- 锚点分类:探索世界、主题甄选、精选线路、一生一次、鸿鹄稀缺。
|
||||
- 目的地宫格:名称、图片、跳转关键词、排序、是否推荐。
|
||||
- 主题卡片:主题名、封面、关联线路或活动专题。
|
||||
- 线路分区:分区标题图、分区名称、展示线路、排序规则。
|
||||
- 底部 CTA:权益卡、公众号、目的地搜索、需求表单等入口。
|
||||
- 页脚与品牌图:图片、服务承诺、备案信息。
|
||||
- 预览与发布:草稿预览、定时发布、回滚上一版。
|
||||
|
||||
### 3. 线路产品管理
|
||||
|
||||
对应当前 `src/generated-products.json` 和产品详情页。
|
||||
|
||||
- 基础信息:标题、副标题、目的地、产品类型、价格、起价单位、标签。
|
||||
- 封面与图集:列表图、详情头图、行程图片。
|
||||
- 详情内容:特色、玩法、美食、行程日程、费用包含/不含、预订须知。
|
||||
- 售卖配置:上架状态、推荐权重、活动归属、库存/席位说明。
|
||||
- 搜索配置:关键词、别名、目的地关联、主题标签。
|
||||
- SEO/分享:分享标题、描述、海报图。
|
||||
- 批量能力:导入、导出、批量上下架、批量改标签。
|
||||
|
||||
### 4. 目的地管理
|
||||
|
||||
对应当前首页目的地、目的地搜索页和搜索别名逻辑。
|
||||
|
||||
- 国家/城市/地区层级。
|
||||
- 热门目的地、出境/国内分类。
|
||||
- 搜索别名:例如 `马代 -> 马尔代夫`、`内蒙 -> 内蒙古`。
|
||||
- 目的地封面图、推荐线路、活动专题绑定。
|
||||
- 排序和上下架。
|
||||
|
||||
### 5. 活动专题管理
|
||||
|
||||
对应当前端午甄选、早鸟尊享、鸿鹄逸游等活动页。
|
||||
|
||||
- 专题标题、封面、介绍文案、活动时间。
|
||||
- 关联线路列表。
|
||||
- CTA:提交需求、联系客服、跳转线路。
|
||||
- 发布状态:草稿、待审核、已发布、已下线。
|
||||
- 合规文案:例如活动免责声明。
|
||||
|
||||
### 6. 客户需求管理
|
||||
|
||||
对应当前 `DemandPage`,上线后这是最重要的转化入口。
|
||||
|
||||
- 表单字段:目的地、手机号、出行时间、预算、人数、备注、来源页面、来源线路。
|
||||
- 线索状态:新建、已分配、已联系、方案中、已成交、无效。
|
||||
- 客户经理分配:手动分配、自动轮询分配。
|
||||
- 跟进记录:电话、微信、备注、下次提醒。
|
||||
- 防刷:手机号频控、验证码、IP 风控、黑名单。
|
||||
- 导出:Excel/CSV,按时间、状态、顾问筛选。
|
||||
|
||||
### 7. 客户与订单管理
|
||||
|
||||
对应当前消息、订单中心的真实业务化。
|
||||
|
||||
- 客户档案:手机号、姓名、微信、偏好、历史需求。
|
||||
- 订单/方案:关联客户、线路、顾问、出行时间、人数、报价、状态。
|
||||
- 状态流转:需求单 -> 方案 -> 合同/支付 -> 出行中 -> 已完成/售后。
|
||||
- 附件:合同、方案 PDF、发票、签证材料。
|
||||
- 订单备注和操作日志。
|
||||
|
||||
### 8. 消息与客服配置
|
||||
|
||||
- 后台通知:需求分配、订单状态变化、发布失败。
|
||||
- 前台消息:活动通知、顾问消息、订单提醒。
|
||||
- 客服入口:在线联系、电话、服务时间、企业微信/IM 配置。
|
||||
- 短信:验证码、需求提交确认、顾问跟进提醒。
|
||||
|
||||
### 9. 媒体库
|
||||
|
||||
- 图片上传、裁剪、压缩、WebP 转换。
|
||||
- 图片分组:轮播、目的地、线路、活动、品牌。
|
||||
- 文件引用关系:防止删除正在使用的图片。
|
||||
- CDN URL、缩略图、多尺寸版本。
|
||||
|
||||
### 10. 权限与审计
|
||||
|
||||
- 角色:超级管理员、运营、产品、客服主管、客户经理、只读审计。
|
||||
- 权限粒度:菜单权限、按钮权限、数据范围权限。
|
||||
- 审核流:重要内容先提交审核再发布。
|
||||
- 操作日志:谁在什么时候改了什么,从什么值改到什么值。
|
||||
- 登录安全:强密码、二次验证可选、登录 IP 记录。
|
||||
|
||||
## 核心数据模型
|
||||
|
||||
第一期建议覆盖这些表:
|
||||
|
||||
| 表 | 用途 |
|
||||
| --- | --- |
|
||||
| `admin_users` | 后台用户 |
|
||||
| `roles` / `permissions` | RBAC 权限 |
|
||||
| `media_assets` | 图片和文件资源 |
|
||||
| `site_versions` | 首页/站点配置发布版本 |
|
||||
| `home_sections` | 首页模块配置 |
|
||||
| `hero_slides` | 首页轮播 |
|
||||
| `destinations` | 目的地 |
|
||||
| `destination_aliases` | 搜索别名 |
|
||||
| `themes` | 主题甄选 |
|
||||
| `products` | 线路产品 |
|
||||
| `product_images` | 产品图片 |
|
||||
| `product_itineraries` | 行程日程 |
|
||||
| `product_fee_items` | 费用说明 |
|
||||
| `campaigns` | 活动专题 |
|
||||
| `campaign_products` | 专题与线路关联 |
|
||||
| `leads` | 客户需求/线索 |
|
||||
| `lead_followups` | 跟进记录 |
|
||||
| `customers` | 客户档案 |
|
||||
| `orders` | 订单/方案 |
|
||||
| `messages` | 前台消息 |
|
||||
| `audit_logs` | 操作审计 |
|
||||
|
||||
### 示例:产品表
|
||||
|
||||
```sql
|
||||
products (
|
||||
id uuid primary key,
|
||||
title text not null,
|
||||
subtitle text,
|
||||
destination_id uuid,
|
||||
price_amount integer,
|
||||
price_unit varchar(20),
|
||||
tags text[],
|
||||
cover_asset_id uuid,
|
||||
summary text,
|
||||
status varchar(20), -- draft, published, archived
|
||||
sort_weight integer default 0,
|
||||
published_at timestamptz,
|
||||
created_at timestamptz not null,
|
||||
updated_at timestamptz not null
|
||||
)
|
||||
```
|
||||
|
||||
### 示例:线索表
|
||||
|
||||
```sql
|
||||
leads (
|
||||
id uuid primary key,
|
||||
destination text,
|
||||
phone varchar(30) not null,
|
||||
travel_date date,
|
||||
people_count integer,
|
||||
budget_min integer,
|
||||
budget_max integer,
|
||||
source_page text,
|
||||
source_product_id uuid,
|
||||
status varchar(30) not null,
|
||||
assigned_user_id uuid,
|
||||
created_at timestamptz not null,
|
||||
updated_at timestamptz not null
|
||||
)
|
||||
```
|
||||
|
||||
## API 设计
|
||||
|
||||
### Public API 给 H5 使用
|
||||
|
||||
- `GET /api/public/site-config`:首页配置、模块排序、底部导航。
|
||||
- `GET /api/public/products`:线路列表,支持目的地、主题、活动、关键词筛选。
|
||||
- `GET /api/public/products/:id`:线路详情。
|
||||
- `GET /api/public/destinations`:目的地和热门分类。
|
||||
- `GET /api/public/campaigns/:slug`:活动专题详情。
|
||||
- `POST /api/public/leads`:提交出行需求。
|
||||
- `POST /api/public/sms/send-code`:发送验证码。
|
||||
|
||||
### Admin API 给后台使用
|
||||
|
||||
- `POST /api/admin/auth/login`
|
||||
- `GET /api/admin/dashboard`
|
||||
- `CRUD /api/admin/products`
|
||||
- `CRUD /api/admin/destinations`
|
||||
- `CRUD /api/admin/campaigns`
|
||||
- `CRUD /api/admin/home-config`
|
||||
- `CRUD /api/admin/media-assets`
|
||||
- `GET /api/admin/leads`
|
||||
- `PATCH /api/admin/leads/:id/status`
|
||||
- `POST /api/admin/leads/:id/followups`
|
||||
- `CRUD /api/admin/orders`
|
||||
- `GET /api/admin/audit-logs`
|
||||
- `POST /api/admin/publish`
|
||||
- `POST /api/admin/rollback`
|
||||
|
||||
## 前台改造路径
|
||||
|
||||
### 第一步:数据层抽离
|
||||
|
||||
先不大改 UI,把硬编码内容替换成数据适配层。
|
||||
|
||||
- 新建 `src/api/client.ts` 和 `src/api/types.ts`。
|
||||
- 新建 `src/adapters/siteConfig.ts`,把接口数据转成当前组件需要的结构。
|
||||
- 保留本地 JSON fallback,便于本地开发和接口故障降级。
|
||||
- 把 `heroSlides`、`destinations`、`themeCards`、`sectionHeaders`、`bottomCtas` 从静态 import 改成接口加载。
|
||||
|
||||
### 第二步:产品和目的地接口化
|
||||
|
||||
- `generated-products.json` 改为接口 seed 数据。
|
||||
- 搜索逻辑从前端 `keywordAliases` 迁移到后端。
|
||||
- 产品详情页从 `getDetailMeta` 这类本地推断改为真实详情字段。
|
||||
|
||||
### 第三步:需求表单真实提交
|
||||
|
||||
- `DemandPage` 接入 `POST /api/public/leads`。
|
||||
- 增加手机号校验、验证码、提交成功页。
|
||||
- 后台线索列表能看到来源页面和来源产品。
|
||||
|
||||
### 第四步:消息与订单真实化
|
||||
|
||||
- 登录态、客户身份、订单列表需要独立规划。
|
||||
- 如果短期不做会员体系,可先保留“提交需求后的查询链接/手机号验证码查询”。
|
||||
|
||||
## 发布与运维
|
||||
|
||||
### 发布策略
|
||||
|
||||
- 内容发布与代码发布分离。
|
||||
- 运营修改内容后生成草稿版本。
|
||||
- 审核通过后写入 `site_versions`,Public API 默认返回当前发布版本。
|
||||
- CDN 缓存使用短 TTL 或发布后主动刷新。
|
||||
- 每次发布可回滚到上一版本。
|
||||
|
||||
### 环境
|
||||
|
||||
| 环境 | 用途 |
|
||||
| --- | --- |
|
||||
| local | 本地开发 |
|
||||
| dev | 联调环境 |
|
||||
| staging | 预发布,连接准生产数据或脱敏数据 |
|
||||
| production | 正式环境 |
|
||||
|
||||
### 监控与备份
|
||||
|
||||
- API 错误率、响应时间、数据库连接数。
|
||||
- 需求提交成功率、短信发送成功率。
|
||||
- 每日数据库自动备份,至少保留 14 到 30 天。
|
||||
- 对象存储开启版本控制或回收站。
|
||||
- 关键操作日志不可被普通管理员删除。
|
||||
|
||||
### 安全
|
||||
|
||||
- 后台必须 HTTPS。
|
||||
- 管理端登录限流。
|
||||
- 所有 Admin API 校验权限。
|
||||
- Public API 做参数校验和频控。
|
||||
- 手机号等隐私信息后台脱敏展示,导出需要高权限。
|
||||
- 防止任意文件上传:限制 MIME、大小、后缀,图片重新编码。
|
||||
|
||||
## 分阶段交付计划
|
||||
|
||||
### Phase 1:后台 MVP,约 2 到 3 周
|
||||
|
||||
目标:运营可以维护首页和线路,H5 可以读取接口。
|
||||
|
||||
- 搭建 monorepo、API、Admin、数据库。
|
||||
- 建立媒体库、产品、目的地、首页配置数据表。
|
||||
- 写 seed 脚本,把当前 `content.ts` 和 `generated-products.json` 导入数据库。
|
||||
- 后台完成登录、产品列表/编辑、首页配置、图片上传。
|
||||
- H5 接入 `site-config` 和 `products`,保留本地 fallback。
|
||||
|
||||
### Phase 2:线索闭环,约 2 周
|
||||
|
||||
目标:出行需求可以真实提交、分配、跟进。
|
||||
|
||||
- 需求表单接口。
|
||||
- 后台线索列表、状态流转、跟进记录。
|
||||
- 客户经理分配。
|
||||
- 短信验证码和提交通知。
|
||||
- 导出和基础统计。
|
||||
|
||||
### Phase 3:活动和发布体系,约 2 到 3 周
|
||||
|
||||
目标:专题页和首页可以安全发布。
|
||||
|
||||
- 活动专题管理。
|
||||
- 草稿/审核/发布/回滚。
|
||||
- 发布日志和操作审计。
|
||||
- CDN 刷新。
|
||||
- 预发布环境验收。
|
||||
|
||||
### Phase 4:订单、客户和消息,约 3 到 5 周
|
||||
|
||||
目标:从线索进一步进入服务履约。
|
||||
|
||||
- 客户档案。
|
||||
- 订单/方案管理。
|
||||
- 前台消息和订单查询。
|
||||
- 附件上传。
|
||||
- 顾问工作台。
|
||||
|
||||
### Phase 5:生产加固,持续迭代
|
||||
|
||||
目标:稳定上线维护。
|
||||
|
||||
- 监控告警、备份恢复演练。
|
||||
- 权限细化、数据脱敏。
|
||||
- 性能优化和缓存。
|
||||
- 自动化测试、CI/CD。
|
||||
- 数据分析看板。
|
||||
|
||||
## MVP 优先级
|
||||
|
||||
必须先做:
|
||||
|
||||
1. 后台登录与权限。
|
||||
2. 媒体库。
|
||||
3. 线路产品管理。
|
||||
4. 首页配置管理。
|
||||
5. H5 读取接口并保留 fallback。
|
||||
6. 需求表单真实提交。
|
||||
7. 线索后台跟进。
|
||||
8. 发布、回滚、操作日志。
|
||||
|
||||
可以后做:
|
||||
|
||||
1. 完整会员登录。
|
||||
2. 真实支付。
|
||||
3. 复杂订单履约。
|
||||
4. 企业微信深度集成。
|
||||
5. 多语言/多品牌站点。
|
||||
|
||||
## 近期可执行清单
|
||||
|
||||
1. 建立 `apps/h5`、`apps/admin`、`apps/api` 结构。
|
||||
2. 设计 Prisma schema,并先覆盖产品、首页、媒体、目的地、线索。
|
||||
3. 编写 seed 脚本,把现有静态内容导入数据库。
|
||||
4. 做 Public API,先返回与当前 H5 兼容的数据。
|
||||
5. 改造 H5 数据加载层,保证 UI 不变。
|
||||
6. 做 Admin 的产品管理和首页装修。
|
||||
7. 接通需求表单和后台线索列表。
|
||||
8. 补充发布版本、回滚、审计日志。
|
||||
|
||||
## 风险与建议
|
||||
|
||||
- 不建议一开始就做完整电商订单和支付,旅游定制业务更适合先做线索和顾问跟进闭环。
|
||||
- 不建议让后台直接编辑任意 JSON,短期快但长期容易把数据结构搞乱。
|
||||
- 不建议 H5 只依赖实时接口,首页配置应支持发布版本和缓存,避免后台故障影响前台展示。
|
||||
- 不建议图片继续只放在代码仓库里,真实上线后要进入对象存储和 CDN。
|
||||
- 如果预算有限,第一期可以先用单台云服务器 + PostgreSQL + 对象存储;但备份、HTTPS、日志和权限不能省。
|
||||
12
index.html
Normal file
@@ -0,0 +1,12 @@
|
||||
<!doctype html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>万趣小程序管理端</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script type="module" src="/src/main.tsx"></script>
|
||||
</body>
|
||||
</html>
|
||||
24
package.json
Normal file
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"name": "wonderq-admin-ui",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite --host 0.0.0.0 --port 5601",
|
||||
"build": "tsc --noEmit && vite build",
|
||||
"preview": "vite preview --host 0.0.0.0 --port 5602"
|
||||
},
|
||||
"dependencies": {
|
||||
"@vitejs/plugin-react": "^6.0.3",
|
||||
"lucide-react": "^1.21.0",
|
||||
"react": "^19.2.7",
|
||||
"react-dom": "^19.2.7",
|
||||
"vite": "^8.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "^19.2.17",
|
||||
"@types/react-dom": "^19.2.3",
|
||||
"typescript": "^6.0.3"
|
||||
}
|
||||
}
|
||||
|
||||
BIN
public/assets/guizhou/baili-azalea.jpg
Normal file
|
After Width: | Height: | Size: 1.3 MiB |
BIN
public/assets/guizhou/bailian-hot-spring.jpg
Normal file
|
After Width: | Height: | Size: 1.3 MiB |
BIN
public/assets/guizhou/cave-sunbeam.jpg
Normal file
|
After Width: | Height: | Size: 4.9 MiB |
BIN
public/assets/guizhou/chishui-danxia.jpg
Normal file
|
After Width: | Height: | Size: 1.4 MiB |
BIN
public/assets/guizhou/dong-village.jpg
Normal file
|
After Width: | Height: | Size: 1.1 MiB |
BIN
public/assets/guizhou/fanjing-mountain.jpg
Normal file
|
After Width: | Height: | Size: 695 KiB |
BIN
public/assets/guizhou/gorge-paddle.jpg
Normal file
|
After Width: | Height: | Size: 14 MiB |
BIN
public/assets/guizhou/huangguoshu-waterfall.jpg
Normal file
|
After Width: | Height: | Size: 1.3 MiB |
BIN
public/assets/guizhou/intangible-masks.jpg
Normal file
|
After Width: | Height: | Size: 18 MiB |
BIN
public/assets/guizhou/jiabang-terrace.jpg
Normal file
|
After Width: | Height: | Size: 1.2 MiB |
BIN
public/assets/guizhou/jianhe-hot-spring.jpg
Normal file
|
After Width: | Height: | Size: 4.6 MiB |
BIN
public/assets/guizhou/jiaxiu-tower.jpg
Normal file
|
After Width: | Height: | Size: 961 KiB |
BIN
public/assets/guizhou/karst-cave-explorer.jpg
Normal file
|
After Width: | Height: | Size: 1.6 MiB |
BIN
public/assets/guizhou/libo-water-forest.jpg
Normal file
|
After Width: | Height: | Size: 1.3 MiB |
BIN
public/assets/guizhou/libo-xiaoqikong.jpg
Normal file
|
After Width: | Height: | Size: 1.7 MiB |
BIN
public/assets/guizhou/miao-costume.jpg
Normal file
|
After Width: | Height: | Size: 1.3 MiB |
BIN
public/assets/guizhou/miao-dragon-boat.jpg
Normal file
|
After Width: | Height: | Size: 4.1 MiB |
BIN
public/assets/guizhou/miao-lusheng-dance.jpg
Normal file
|
After Width: | Height: | Size: 802 KiB |
BIN
public/assets/guizhou/miao-village-street.jpg
Normal file
|
After Width: | Height: | Size: 32 MiB |
BIN
public/assets/guizhou/mountain-resort.jpg
Normal file
|
After Width: | Height: | Size: 3.6 MiB |
BIN
public/assets/guizhou/shuichunhe-rafting.jpg
Normal file
|
After Width: | Height: | Size: 951 KiB |
BIN
public/assets/guizhou/tiankeng-pool.jpg
Normal file
|
After Width: | Height: | Size: 11 MiB |
BIN
public/assets/guizhou/tiankeng-sunbeam-group.jpg
Normal file
|
After Width: | Height: | Size: 955 KiB |
BIN
public/assets/guizhou/wanfenglin.jpg
Normal file
|
After Width: | Height: | Size: 1023 KiB |
BIN
public/assets/guizhou/wumeng-grassland.jpg
Normal file
|
After Width: | Height: | Size: 1.7 MiB |
BIN
public/assets/guizhou/xijiang-miao-village.jpg
Normal file
|
After Width: | Height: | Size: 465 KiB |
BIN
public/assets/guizhou/zhenyuan-ancient-town.jpg
Normal file
|
After Width: | Height: | Size: 1.2 MiB |
BIN
public/assets/guizhou/zhijin-cave-pool.jpg
Normal file
|
After Width: | Height: | Size: 1.9 MiB |
BIN
public/assets/guizhou/zhijin-cave.jpg
Normal file
|
After Width: | Height: | Size: 1020 KiB |
BIN
public/assets/source/asset-000-6130f5faf6.jpg
Normal file
|
After Width: | Height: | Size: 166 KiB |
BIN
public/assets/source/asset-001-e3ccdf0858.jpg
Normal file
|
After Width: | Height: | Size: 208 KiB |
BIN
public/assets/source/asset-002-60f1781bad.jpg
Normal file
|
After Width: | Height: | Size: 89 KiB |
BIN
public/assets/source/asset-003-67c94551ff.jpg
Normal file
|
After Width: | Height: | Size: 278 KiB |
BIN
public/assets/source/asset-004-74801a9861.jpg
Normal file
|
After Width: | Height: | Size: 265 KiB |
BIN
public/assets/source/asset-005-5f88616344.jpg
Normal file
|
After Width: | Height: | Size: 236 KiB |
BIN
public/assets/source/asset-006-065f65e89a.png
Normal file
|
After Width: | Height: | Size: 3.0 KiB |
BIN
public/assets/source/asset-007-bfd23e4423.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
public/assets/source/asset-008-b69a2ebdf1.png
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
BIN
public/assets/source/asset-009-7c60387849.png
Normal file
|
After Width: | Height: | Size: 882 B |
BIN
public/assets/source/asset-010-8614b34e80.png
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
public/assets/source/asset-011-398553c792.png
Normal file
|
After Width: | Height: | Size: 8.1 KiB |
BIN
public/assets/source/asset-012-486ac8f1a1.png
Normal file
|
After Width: | Height: | Size: 7.8 KiB |
BIN
public/assets/source/asset-013-babb337ba2.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
public/assets/source/asset-014-fd57beac6b.png
Normal file
|
After Width: | Height: | Size: 9.0 KiB |
BIN
public/assets/source/asset-015-94835fc601.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
public/assets/source/asset-016-306236a4af.png
Normal file
|
After Width: | Height: | Size: 6.0 KiB |
BIN
public/assets/source/asset-017-e4a0e59bd4.png
Normal file
|
After Width: | Height: | Size: 9.9 KiB |
BIN
public/assets/source/asset-018-30bc451049.jpg
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
public/assets/source/asset-019-8b7f71737e.jpg
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
public/assets/source/asset-020-5207a45c09.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
public/assets/source/asset-021-267958c0d6.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
public/assets/source/asset-022-f982dcf65e.png
Normal file
|
After Width: | Height: | Size: 30 KiB |
BIN
public/assets/source/asset-023-20ebf544be.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
public/assets/source/asset-024-6e6ee3998c.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
public/assets/source/asset-025-980c7ac168.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
public/assets/source/asset-026-6e4d686b97.png
Normal file
|
After Width: | Height: | Size: 497 B |
BIN
public/assets/source/asset-027-22aef1d83b.png
Normal file
|
After Width: | Height: | Size: 703 B |
BIN
public/assets/source/asset-028-912019b131.png
Normal file
|
After Width: | Height: | Size: 67 KiB |
BIN
public/assets/source/asset-029-9eccbb7131.png
Normal file
|
After Width: | Height: | Size: 66 KiB |
BIN
public/assets/source/asset-030-a77d1ef23a.jpg
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
public/assets/source/asset-031-802555e02b.png
Normal file
|
After Width: | Height: | Size: 158 KiB |
BIN
public/assets/source/asset-032-1257cf8865.jpg
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
public/assets/source/asset-033-4f39bbaba6.jpg
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
public/assets/source/asset-034-393944f522.png
Normal file
|
After Width: | Height: | Size: 149 KiB |
BIN
public/assets/source/asset-035-9d6bac22b3.jpg
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
public/assets/source/asset-036-60d6309202.jpg
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
public/assets/source/asset-037-b6dee37086.jpg
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
public/assets/source/asset-038-90f983ea37.jpg
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
public/assets/source/asset-039-a02a731cec.jpg
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
public/assets/source/asset-040-10c33d1558.jpg
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
public/assets/source/asset-041-c5a7b61b99.jpg
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
public/assets/source/asset-042-263c1d8958.jpg
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
public/assets/source/asset-043-a1bbc0007e.jpg
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
public/assets/source/asset-044-80ccc16363.jpg
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
public/assets/source/asset-045-014a557086.png
Normal file
|
After Width: | Height: | Size: 38 KiB |
BIN
public/assets/source/asset-046-5b4ca8173b.png
Normal file
|
After Width: | Height: | Size: 766 B |
BIN
public/assets/source/asset-047-14415ef235.jpg
Normal file
|
After Width: | Height: | Size: 89 KiB |
BIN
public/assets/source/asset-048-cdb636ea72.jpg
Normal file
|
After Width: | Height: | Size: 27 KiB |
BIN
public/assets/source/asset-049-662d6cd220.jpg
Normal file
|
After Width: | Height: | Size: 31 KiB |
BIN
public/assets/source/asset-050-b1dcc1ad8e.jpg
Normal file
|
After Width: | Height: | Size: 34 KiB |
BIN
public/assets/source/asset-051-5873b802e1.jpg
Normal file
|
After Width: | Height: | Size: 35 KiB |
BIN
public/assets/source/asset-052-8454c19a8f.jpg
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
public/assets/source/asset-053-9298156002.jpg
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
public/assets/source/asset-054-c936b44502.jpg
Normal file
|
After Width: | Height: | Size: 49 KiB |
BIN
public/assets/source/asset-055-0cd651d9e1.jpg
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
public/assets/source/asset-056-209a8a139f.jpg
Normal file
|
After Width: | Height: | Size: 32 KiB |
BIN
public/assets/source/asset-057-7c54fd675c.jpg
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
public/assets/source/asset-058-77303eee5e.jpg
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
public/assets/source/asset-059-a8a6b2886f.jpg
Normal file
|
After Width: | Height: | Size: 50 KiB |
BIN
public/assets/source/asset-060-4906700f3d.jpg
Normal file
|
After Width: | Height: | Size: 51 KiB |
BIN
public/assets/source/asset-061-34916cd0eb.jpg
Normal file
|
After Width: | Height: | Size: 33 KiB |
BIN
public/assets/source/asset-062-d0571e4731.jpg
Normal file
|
After Width: | Height: | Size: 18 KiB |