vr-shopxo-plugin/docs/city-diy-implementation-pla...

136 lines
4.9 KiB
Markdown
Raw Permalink Normal View History

# 城市DIY模板 — VR Plugin 端实施计划
> 创建日期2026-06-10
> 基于审查文档:[city-diy-plan-review.md](file:///Users/bigemon/WorkSpace/vr-shopxo-uniapp/docs/city-diy-plan-review.md)
> 目标零核心文件改动通过插件钩子实现「用户坐标→城市→DIY模板」动态路由
---
## 架构概述
```
UniApp 发送 user_lng, user_lat → /api.php?s=index/index
app/api/controller/Index::Index() ← 无需修改
DiyService::AppClientHomeDiyData() ← 无需修改
钩子: plugins_service_diy_app_client_home_diy_data ← 🔑 新增
DiyHomeCityRouter::handle()
├─ input('user_lng'), input('user_lat') → 直接读请求参数
├─ GeoCityService::FindNearestCityId() → 城市ID
├─ Db::name('Diy')->where(['name'=>"home_{city_id}",'is_enable'=>1])->value('id')
└─ 通过引用 &$diy_id 设置模板ID未找到则回退默认
```
---
## 实施步骤
### 步骤1注册钩子 — 修改 [config.json](file:///Users/bigemon/WorkSpace/vr-shopxo-plugin/shopxo/app/plugins/vr_ticket/config.json)
**文件**`shopxo/app/plugins/vr_ticket/config.json`
**操作**:在 `hook` 对象中新增一条记录
**当前状态**hooks 末尾):
```json
"plugins_view_admin_goods_content_inside_bottom": [
"app\\plugins\\vr_ticket\\hook\\AdminGoodsIndex"
]
```
**修改后**(在末尾追加逗号+新钩子):
```json
"plugins_view_admin_goods_content_inside_bottom": [
"app\\plugins\\vr_ticket\\hook\\AdminGoodsIndex"
],
"plugins_service_diy_app_client_home_diy_data": [
"app\\plugins\\vr_ticket\\hook\\DiyHomeCityRouter"
]
```
> [!NOTE]
> 钩子名 `plugins_service_diy_app_client_home_diy_data` 来自 [DiyService.php:48](file:///Users/bigemon/WorkSpace/vr-shopxo-plugin/shopxo/app/service/DiyService.php#L48)
---
### 步骤2新建钩子处理类 — 创建 [DiyHomeCityRouter.php](file:///Users/bigemon/WorkSpace/vr-shopxo-plugin/shopxo/app/plugins/vr_ticket/hook/DiyHomeCityRouter.php)
**文件**`shopxo/app/plugins/vr_ticket/hook/DiyHomeCityRouter.php`(新建)
**命名空间**`app\plugins\vr_ticket\hook`
**类名**`DiyHomeCityRouter`
**参考实现**[Hook.php OnGoodsListBegin](file:///Users/bigemon/WorkSpace/vr-shopxo-plugin/shopxo/app/plugins/vr_ticket/Hook.php#L400-L436) — 已有相同的「坐标→城市ID」逻辑
**关键设计点**
1. `is_backend` 检查:仅前端请求生效(`is_backend === true` 时才处理,与 DiyService 传来的参数一致)
2. `input('user_lat')` / `input('user_lng')`:直接从 ThinkPHP 请求参数读取,无需依赖 `$params['params']`
3. `GeoCityService::FindNearestCityId()`:复用已有的最近城市查找方法
4. `&$diy_id`:通过引用修改,无需返回值
5. 兜底策略:找不到城市场景模板时 `diy_id` 保持原值,`DiyService` 会走 `AppClientHomeDiyId()` 的默认逻辑
**模板命名约定**
- `home_110100` → 北京市
- `home_310100` → 上海市
- `home_440100` → 广州市
- `home_default` → 默认模板(兜底,由 DiyService 自动匹配)
---
### 步骤3验证测试
**3a. 后端验证**
直接用浏览器访问 API 端点,模拟带坐标的 UniApp 请求:
```
http://localhost:10000/api.php?s=index/index&user_lng=118.110652&user_lat=24.585
```
**预期行为**
- 无坐标:返回默认 DIY 模板(与现有行为一致,向下兼容)
- 有坐标且城市存在对应模板:返回该城市的 DIY 配置
- 有坐标但城市无对应模板:回退到默认模板
**验证方法**
1. 先在后台创建一个测试用 DIY 模板,`name` 设为 `home_{测试城市ID}`
2. 用该城市的坐标访问 API检查返回的 JSON 是否为该模板的配置
3. 用一个不存在模板的城市坐标访问,确认回退到默认模板
**3b. GitNexus 变更检测**
在提交前运行:
```bash
npx gitnexus detect-changes
```
验证改动只影响预期的符号和执行流。
---
## 文件变更清单
| 文件 | 操作 | 行数变化 |
|------|------|----------|
| [config.json](file:///Users/bigemon/WorkSpace/vr-shopxo-plugin/shopxo/app/plugins/vr_ticket/config.json) | 修改 | +4 行 |
| [DiyHomeCityRouter.php](file:///Users/bigemon/WorkSpace/vr-shopxo-plugin/shopxo/app/plugins/vr_ticket/hook/DiyHomeCityRouter.php) | 新建 | ~35 行 |
| **核心文件** | **无修改** | **0 行** |
---
## 风险评估
| 风险 | 等级 | 缓解措施 |
|------|------|----------|
| 无坐标时走默认逻辑 | 🟢 无风险 | 向下兼容,行为不变 |
| GeoCityService 性能 | 🟢 低 | 已有内存+文件双层缓存1小时过期 |
| 钩子未注册 | 🟢 低 | config.json 改动量极小,可快速验证 |
| 模板命名冲突 | 🟡 中 | 使用 `home_{city_id}` 前缀约定,后台创建时需遵守 |
| 核心升级冲突 | 🟢 无 | 零核心文件修改 |
---
> [!TIP]
> 实施顺序步骤1 → 步骤2 → 步骤3共约 40 行代码改动。任何中断都可以从此文档恢复。