feat: add hotel and vehicle option site modules

Add full support for hotel group and vehicle option site management features:
- Define SQLAlchemy models and alembic migration for the new database tables
- Add default sample content entries in content.py
- Extend admin and public API routes to support the new modules
- Update seed script to populate default hotel and vehicle data
- Update all relevant documentation and test cases
This commit is contained in:
duanshuwen
2026-07-03 20:26:44 +08:00
parent 72d388a047
commit 201e835eab
13 changed files with 426 additions and 34 deletions

View File

@@ -26,6 +26,7 @@
| `targetType` | `string \| null` | 否 | 点击目标类型 |
| `targetValue` | `string \| null` | 否 | 点击目标值 |
| `isActive` | `boolean` | 否 | 是否启用 |
| `sortOrder` | `number` | 否 | 后台排序值Public API 按该字段升序输出 |
### `Destination`
@@ -36,6 +37,7 @@
| `image` | `string \| null` | 否 | 图片 URL |
| `isHot` | `boolean` | 否 | 是否热门 |
| `isActive` | `boolean` | 否 | 是否启用 |
| `sortOrder` | `number` | 否 | 后台排序值Public API 按该字段升序输出 |
| `aliases` | `Array<{ id: string; alias: string }>` | 否 | 搜索别名 |
### `Theme`
@@ -44,21 +46,23 @@
| --- | --- | --- | --- |
| `id` | `string` | 是 | 主题 ID |
| `label` | `string` | 是 | 主题名称 |
| `image` | `string` | 是 | 图片 URL |
| `image` | `string` | 是 | 主题图片 URL |
| `targetType` | `string \| null` | 否 | 点击目标类型 |
| `targetValue` | `string \| null` | 否 | 点击目标值 |
| `isActive` | `boolean` | 否 | 是否启用 |
| `sortOrder` | `number` | 否 | 后台排序值Public API 按该字段升序输出 |
### `CtaBanner`
| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `id` | `string` | 是 | Banner ID |
| `alt` | `string` | 是 | 图片替代文案 |
| `image` | `string` | 是 | 图 URL |
| `id` | `string` | 是 | 服务卡片 ID |
| `alt` | `string` | 是 | 服务标题,展示在“更多服务”卡片上 |
| `image` | `string` | 是 | 服务卡片背景图 URL |
| `targetType` | `string \| null` | 否 | 点击目标类型 |
| `targetValue` | `string \| null` | 否 | 点击目标值 |
| `isActive` | `boolean` | 否 | 是否启用 |
| `sortOrder` | `number` | 否 | 后台排序值Public API 按该字段升序输出 |
### `Campaign`
@@ -87,12 +91,32 @@
| `subtitle` | `string \| null` | 否 | 分组副文案 |
| `productIds` | `string[]` | 是 | 该分组包含的产品 ID产品详情来自 `/api/public/products.items` |
| `isActive` | `boolean` | 否 | 是否启用Public API 通常只返回启用分组 |
| `sortOrder` | `number` | 否 | 后台展示顺序Public API 按该字段升序输出 |
Public API 输出规则:
- `GET /api/public/site-config` 只返回启用的 `routeSections`
- `routeSections[].productIds` 只包含已发布商品 ID未发布、归档或不存在的商品不得出现在 Public 响应中。
- 动态分组按后台 `sortOrder` 升序返回,`productIds` 的顺序就是用户侧商品卡展示顺序。
- MiniAPP 会按 `productIds` 匹配 `/api/public/products.items[].id`;接口缺失、`routeSections` 为空或没有可匹配商品时回退 `src/content.ts` 的本地精选线路兜底内容。
### `HomeCard`
`HomeCard` 用于首页“特色酒店”与“万趣用车”两个普通卡片模块。MiniAPP 只消费卡片展示字段,不在这两个模块里读取商品本体或线路商品关联。
| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `id` | `string` | 是 | 后端生成的卡片 ID |
| `title` | `string` | 是 | 卡片标题 |
| `description` | `string \| null` | 否 | 卡片描述 |
| `image` | `string \| null` | 否 | 卡片封面图 URL为空时客户端可使用本地兜底图 |
| `isActive` | `boolean` | 否 | 是否启用Public API 通常只返回启用卡片 |
| `sortOrder` | `number` | 否 | 后台展示顺序Public API 按该字段升序输出 |
Public API 输出规则:
- `GET /api/public/site-config` 只返回启用的 `hotelGroups``vehicleOptions`
- 两个数组按后台 `sortOrder` 升序返回。
- 字段缺失、数组为空或图片为空时MiniAPP 使用 `src/content.ts` 的本地特色酒店/万趣用车内容兜底。
### `PublicProduct`
| 字段 | 类型 | 必填 | 说明 |
@@ -156,7 +180,7 @@ Public API 输出规则:
### `GET /api/public/site-config`
用于首页轮播、目的地、主题入口和底部 CTA 配置。MiniAPP 启动时会和产品列表并行请求该接口;接口不可用或关键数组为空时,前台会回退本地静态内容。
用于首页轮播、目的地、主题入口和更多服务配置。MiniAPP 启动时会和产品列表并行请求该接口;接口不可用或关键数组为空时,前台会回退本地静态内容。
#### 响应字段
@@ -166,9 +190,11 @@ Public API 输出规则:
| `destinations` | `Destination[]` | 首页目的地入口 |
| `map` | `Array<{ id: string; image: string; isActive?: boolean }>` | 贵州地图图片MiniAPP 当前消费 `map[0].image` |
| `themes` | `Theme[]` | 主题甄选入口 |
| `ctaBanners` | `CtaBanner[]` | 底部 CTA Banner |
| `ctaBanners` | `CtaBanner[]` | “更多服务”卡片配置 |
| `campaigns` | `Campaign[]` | 活动元信息,可用于“特价优惠”入口;当前不包含活动产品结果列表 |
| `routeSections` | `RouteSection[]` | “精选线路”子分组定义 |
| `hotelGroups` | `HomeCard[]` | “特色酒店”卡片配置,只返回启用项 |
| `vehicleOptions` | `HomeCard[]` | “万趣用车”卡片配置,只返回启用项 |
#### 首页模块数据归属
@@ -176,6 +202,10 @@ Public API 输出规则:
| --- | --- | --- |
| 特价优惠 | `site-config.campaigns` + `/api/public/products` | 当前 Public API 只返回活动元信息不直接返回“特价优惠结果列表”。MiniAPP 若要展示活动线路,可按活动标题、标签或后续扩展的活动产品关联从 `/api/public/products` 中筛选。 |
| 精选线路 | `site-config.routeSections` + `/api/public/products` | `routeSections` 返回动态分组与 `productIds`;具体产品卡片数据由 `/api/public/products.items` 提供。后台可按任务新增、删除、停用和排序分组,用户侧不假设固定三组。 |
| 更多服务 | `site-config.ctaBanners` | 返回启用服务卡片,按后台排序展示;无有效配置时回退本地 `bottomCtas` 内容。 |
| 特色酒店 | `site-config.hotelGroups` | 返回启用酒店卡片,按后台排序展示;无有效配置时回退本地内容。 |
| 万趣用车 | `site-config.vehicleOptions` | 返回启用用车卡片,按后台排序展示;无有效配置时回退本地内容。 |
#### 响应示例
```json
@@ -247,6 +277,26 @@ Public API 输出规则:
"productIds": [],
"isActive": true
}
],
"hotelGroups": [
{
"id": "hotel-group-001",
"title": "经典酒店",
"description": "城市接驳、景区度假和温泉休整,适合首游贵州的小包团动线。",
"image": "/assets/guizhou/bailian-hot-spring.jpg",
"isActive": true,
"sortOrder": 0
}
],
"vehicleOptions": [
{
"id": "vehicle-option-001",
"title": "5座舒适用车",
"description": "适合2-4人家庭或好友小团城市接送、景区穿梭更灵活。",
"image": "/assets/guizhou/jiaxiu-tower.jpg",
"isActive": true,
"sortOrder": 0
}
]
}
```
@@ -425,6 +475,8 @@ Public API 输出规则:
- `products.items` 为空时MiniAPP 会使用本地产品兜底数据。
- “精选线路”由 `site-config.routeSections` 定义动态分组标题、副文案和商品 ID 顺序,由 `/api/public/products.items` 提供产品详情;客户端不依赖固定分组 ID 或固定三组数量。
- `routeSections` 缺失、为空或无法匹配到有效商品时MiniAPP 使用 `src/content.ts` 的本地精选线路内容回退。
- `ctaBanners` 缺失或为空时MiniAPP 使用 `src/content.ts` 的本地 `bottomCtas` 内容回退。
- “特色酒店”和“万趣用车”分别由 `site-config.hotelGroups``site-config.vehicleOptions` 提供;字段缺失、数组为空或图片为空时使用本地内容兜底。
- “特价优惠”当前没有独立 Public 结果列表字段;`site-config.campaigns` 只提供活动元信息,活动线路需通过产品标签/关键词筛选或后续扩展活动产品关联字段。
- 产品搜索当前主要在前端执行,依赖 `title``tags``destination.name``summary`
- 产品详情页当前使用已加载的产品列表数据;后续可改为进入详情页时请求 `GET /api/public/products/{product_id}`
@@ -434,9 +486,10 @@ Public API 输出规则:
## 后端验证建议
-`GET /health` 增加或保留健康检查测试。
-`GET /api/public/site-config` 验证返回 JSON 包含 `heroSlides``destinations``map``themes``ctaBanners``campaigns``routeSections` 数组字段。
-`GET /api/public/site-config` 验证返回 JSON 包含 `heroSlides``destinations``map``themes``ctaBanners``campaigns``routeSections``hotelGroups``vehicleOptions` 数组字段。
-`GET /api/public/site-config` 验证 `routeSections` 表达“精选线路”子分组;接口返回当前已配置且启用的分组,未配置时返回空数组并由 MiniAPP 本地内容兜底。
-`GET /api/public/site-config` 验证 `routeSections` 只返回启用分组,且 `productIds` 不包含未发布商品。
-`GET /api/public/site-config` 验证 `hotelGroups``vehicleOptions` 只返回启用卡片,并按 `sortOrder` 升序。
-`GET /api/public/products` 验证响应结构为 `{ items: [...] }`,并覆盖 `keyword``destinationId``status``take` 参数。
-`GET /api/public/products/{product_id}` 验证 UUID、数字 `sourceId` 和 404 场景。
-`GET /api/public/destinations` 验证只返回启用目的地及别名字段。