# 二次开发规范指南

## 文档说明

> 本文档面向基于 `estate-lookhouse-samplecode` 进行二次开发的开发者，详细说明项目架构、目录职责、开发规范和扩展指引。

---

## 一、技术栈

| 技术 | 版本 | 说明 |
|---|---|---|
| Vue 3 | ^3.5 | 前端框架，使用 Composition API + `<script setup>` |
| TypeScript | ~5.9 | 类型系统 |
| Pinia | ^3.0 | 状态管理 |
| Vue Router | ^5.0 | 路由管理 |
| Vue I18n | ^11.2 | 国际化（中/英/日） |
| Vite | ^7.3 | 构建工具 |
| SCSS | sass-embedded ^1.97 | CSS 预处理器 |
| Swiper | ^12.1 | 图片轮播组件 |
| zqsdk | UMD 全局加载 | VR 展示核心 SDK |

---

## 二、项目目录结构

```
src/
├── main.ts                          # 应用入口
├── App.vue                          # 根组件（全局样式重置）
│
├── config/                          # 常量与配置
│   └── constants.ts                 # 全局常量（模式、尺寸、容器 ID 等）
│
├── types/                           # TypeScript 类型定义
│   ├── index.ts                     # 类型统一导出
│   ├── vr.ts                        # VR / SDK 相关类型
│   ├── floor-plan.ts                # 户型图相关类型
│   ├── house-detail.ts              # 房源详情相关类型
│   └── lecture.ts                   # 讲房相关类型（含 POI）
│
├── utils/                           # 工具函数
│   ├── url.ts                       # URL 参数解析
│   └── sdk-helpers.ts               # SDK 数据处理辅助函数
│
├── composables/                     # Vue 组合式函数
│   ├── use-device-detect.ts         # 设备检测（PC/Mobile）
│   └── use-qrcode.ts                # 二维码生成
│
├── i18n/                            # 国际化
│   ├── index.ts                     # i18n 实例配置
│   └── locales/                     # 语言包
│       ├── zh-CN.ts                 # 简体中文
│       ├── en.ts                    # 英文
│       └── ja.ts                    # 日文
│
├── stores/                          # Pinia 状态管理
│   ├── vr.ts                        # VR 核心（SDK 生命周期、事件）
│   ├── floor-plan.ts                # 户型图数据管理
│   ├── floor.ts                     # 楼层列表与切换
│   ├── toolbar.ts                   # 底部工具栏状态
│   ├── scene-tour.ts                # 导览功能状态
│   ├── introduce.ts                 # 讲房功能状态（含 POI）
│   └── house-info.ts                # 房源详情状态
│
├── components/                      # 公共 UI 组件
│   └── common/
│       └── pc/                      # PC 端公共组件
│           ├── NestRadarIcon.vue        # 雷达定位图标
│           ├── NestLoadingOverlay.vue   # 加载遮罩
│           ├── NestErrorDisplay.vue     # 错误提示
│           ├── NestModeButton.vue       # 模式切换按钮
│           ├── NestHouseInfo.vue        # 房源信息卡片
│           ├── NestHouseMap.vue         # 嵌入式百度地图
│           ├── NestModalMap.vue         # 模态大地图（含 POI）
│           ├── NestModalImgSwiper.vue   # 模态图片轮播
│           ├── NestModalIframe.vue      # 模态 iframe
│           └── NestCommunityPhotos.vue  # 小区图片展示
│
├── modules/                         # 业务模块（按平台/功能分）
│   └── pc/                          # PC 端业务组件
│       ├── vr-player/               # VR 播放器
│       │   ├── NestVrPlayer.vue         # SDK 容器 + 加载/错误 UI
│       │   └── NestInitialLoading.vue   # 初始加载动画
│       ├── right-panel/             # 右侧面板
│       │   └── NestRightPanel.vue       # 模式切换按钮组
│       ├── floor-plan/              # 户型图
│       │   ├── NestFloorPlan.vue        # 全屏户型图
│       │   ├── NestMiniFloorPlan.vue    # 迷你户型图
│       │   └── NestFloorBar.vue         # 楼层切换栏
│       ├── toolbar/                 # 工具栏
│       │   └── NestBottomBar.vue        # 底部工具栏
│       ├── pano-ruler/              # 全景标尺
│       │   └── NestPanoSize.vue         # 标尺显示组件
│       ├── scene-tour/              # 导览
│       │   └── NestSceneTourPanel.vue   # 导览面板
│       ├── introduce/               # AI 讲房
│       │   ├── NestIntroduceBtn.vue         # 讲房入口按钮
│       │   ├── NestIntroducePanel.vue       # 讲房控制面板
│       │   ├── NestIntroduceActionPanel.vue # 讲房弹出 UI 容器
│       │   ├── NestLectureBigMap.vue        # 讲房大地图（含 POI）
│       │   ├── NestLectureImgSwiper.vue     # 讲房图片轮播
│       │   ├── NestLectureBigHangpai.vue    # 讲房航拍面板
│       │   └── NestLectureHouseInfo.vue     # 讲房房源信息
│       ├── house-info/              # 房源详情
│       │   ├── NestHouseTopBar.vue      # 顶部房源标题栏
│       │   └── NestHouseDetailPanel.vue # 房源详情面板
│       └── common/                  # 通用业务组件
│           ├── NestCompanyLogo.vue      # 公司 Logo
│           ├── NestPanoramaBtn.vue      # 全景入口按钮
│           ├── NestDisclaimer.vue       # 免责声明
│           ├── NestHelpTip.vue          # 帮助提示
│           ├── NestLanguageSwitcher.vue # 语言切换器
│           └── NestWechatQrOverlay.vue  # 微信二维码弹窗
│
├── layouts/                         # 布局层
│   └── pc/
│       └── PcHouseLayout.vue        # PC 端组件编排
│
├── views/                           # 页面视图
│   └── HouseView.vue                # 唯一页面，选择 PC/Mobile 布局
│
├── assets/                          # 静态资源
│   ├── icons/                       # 图标文件
│   └── sprite/                      # 雪碧图
│
└── router/                          # 路由配置
    └── index.ts
```

---

## 三、核心架构分层

项目采用 **自上而下** 的分层架构，各层职责明确：

```
┌──────────────────────────────────────┐
│           views/HouseView            │  页面入口，设备分流
├──────────────────────────────────────┤
│      layouts/pc | layouts/mobile     │  平台布局编排
├──────────────────────────────────────┤
│      modules/pc | modules/mobile     │  平台业务组件（按功能分组）
├──────────────────────────────────────┤
│          components/common           │  跨平台公共 UI 组件
├──────────────────────────────────────┤
│               stores                 │  业务逻辑 & 状态管理
├──────────────────────────────────────┤
│            composables               │  Vue 组合式函数
├──────────────────────────────────────┤
│     utils / config / types / i18n    │  工具、常量、类型、国际化
└──────────────────────────────────────┘
```

**依赖方向**：上层可以引用下层，下层不得引用上层。同层之间避免交叉引用。

---

## 四、各目录职责与开发指引

### 4.1 `config/` — 常量配置

**职责**：集中管理全局常量，避免硬编码。

**开发规范**：
- 新增功能涉及的常量（如新模式名称、UI 尺寸阈值）都应在此定义
- 使用 `as const` 确保类型安全
- 命名采用 `UPPER_SNAKE_CASE`

**示例**：

```typescript
export const VR_MODE = {
  PANORAMA: 'panorama',
  FLOORPLAN: 'floorplan',
  DOLLHOUSE: 'dollhouse',
} as const
```

---

### 4.2 `types/` — 类型定义

**职责**：定义项目所有 TypeScript 接口和类型。

**现有类型文件**：

| 文件 | 内容 |
|---|---|
| `vr.ts` | SDK 相关类型（HousePlayInstance、事件类型等） |
| `floor-plan.ts` | 户型图相关类型 |
| `house-detail.ts` | 房源详情相关类型 |
| `lecture.ts` | 讲房相关类型（含 POI 数据结构） |

**开发规范**：
- 按业务模块拆分文件
- 新增模块请创建对应的类型文件并在 `index.ts` 中导出
- SDK 相关类型定义在 `vr.ts`

---

### 4.3 `utils/` — 工具函数

**职责**：存放纯函数，不依赖 Vue 响应式系统或 Store。

**现有工具文件**：

| 文件 | 内容 |
|---|---|
| `url.ts` | URL 参数解析（modelId 等） |
| `sdk-helpers.ts` | SDK 数据格式转换、兼容性处理 |

---

### 4.4 `composables/` — 组合式函数

**职责**：存放可复用的 Vue Composition API 逻辑。

**现有组合式函数**：

| 文件 | 功能 |
|---|---|
| `use-device-detect.ts` | 设备检测（PC/Mobile 判断） |
| `use-qrcode.ts` | 二维码生成 |

---

### 4.5 `i18n/` — 国际化

**职责**：管理多语言支持。

**支持语言**：
- `zh-CN.ts` — 简体中文（默认）
- `en.ts` — 英文
- `ja.ts` — 日文

**使用方式**：

```vue
<template>
  <span>{{ $t('lookMapCommunity') }}</span>
</template>
```

---

### 4.6 `stores/` — 状态管理

**职责**：使用 Pinia 管理业务状态和 SDK 事件桥接。

**现有 Store 职责划分**：

| Store | 文件 | 职责 |
|---|---|---|
| `useVrStore` | `vr.ts` | SDK 初始化、模式切换、事件监听、状态维护 |
| `useFloorPlanStore` | `floor-plan.ts` | 户型图展示数据管理 |
| `useFloorStore` | `floor.ts` | 楼层列表与当前楼层索引 |
| `useToolbarStore` | `toolbar.ts` | 底部工具栏状态（标尺/标签/帮助等） |
| `useSceneTourStore` | `scene-tour.ts` | 导览功能状态 |
| `useIntroduceStore` | `introduce.ts` | 讲房功能状态（含 POI） |
| `useHouseInfoStore` | `house-info.ts` | 房源详情状态 |

**开发规范**：
- 使用 Composition API 风格（`defineStore` + `setup` 函数）
- SDK 对象使用 `shallowRef` + `markRaw` 避免 Vue Proxy 冲突
- SDK 事件统一由 `vr.ts` 接收后分发给对应 Store

> **重要**：`vr.ts` 是 SDK 事件的唯一入口。新功能模块的 Store 不应直接监听 SDK 事件，而是由 `vr.ts` 在事件回调中转发数据。

---

### 4.7 `components/common/pc/` — 公共 UI 组件

**职责**：存放可复用的纯 UI 组件，通过 Props 接收数据，通过 Emit 通知父组件。

**现有公共组件**：

| 组件 | 用途 |
|---|---|
| `NestRadarIcon` | 雷达定位图标 |
| `NestLoadingOverlay` | 加载遮罩层 |
| `NestErrorDisplay` | 错误提示面板 |
| `NestModeButton` | 模式切换按钮 |
| `NestHouseInfo` | 房源信息卡片 |
| `NestHouseMap` | 嵌入式百度地图 |
| `NestModalMap` | 模态大地图（支持 POI 标记、分类切换、路径规划） |
| `NestModalImgSwiper` | 模态图片轮播（Swiper 实现） |
| `NestModalIframe` | 模态 iframe 容器 |
| `NestCommunityPhotos` | 小区图片展示 |

**开发规范**：
- 文件命名采用 **PascalCase**，以 `Nest` 为前缀
- **不得直接引用 Store**，保持与业务逻辑解耦
- 样式使用 `<style scoped lang="scss">` + BEM 命名

---

### 4.8 `modules/pc/` — PC 端业务组件

**职责**：存放 PC 端专属的业务组件，可引用 Store 和公共组件。

**按功能分组**：

| 目录 | 功能模块 | 主要组件 |
|---|---|---|
| `vr-player/` | VR 播放器 | NestVrPlayer、NestInitialLoading |
| `right-panel/` | 右侧面板 | NestRightPanel |
| `floor-plan/` | 户型图 | NestFloorPlan、NestMiniFloorPlan、NestFloorBar |
| `toolbar/` | 工具栏 | NestBottomBar |
| `pano-ruler/` | 全景标尺 | NestPanoSize |
| `scene-tour/` | 导览 | NestSceneTourPanel |
| `introduce/` | AI 讲房 | NestIntroduceBtn、NestIntroducePanel、NestLecture* |
| `house-info/` | 房源详情 | NestHouseTopBar、NestHouseDetailPanel |
| `common/` | 通用业务 | NestCompanyLogo、NestDisclaimer、NestHelpTip 等 |

**开发规范**：
- 可以引用 `stores/`、`components/common/`、`config/`、`utils/`
- 每个组件文件头部写清楚职责注释
- 新增功能建议按功能创建子目录

---

### 4.9 `layouts/pc/` — 布局编排层

**职责**：组合 `modules/` 中的业务组件，决定它们在页面上的排列方式。

**当前 PC 布局组件引用**：

```vue
<!-- layouts/pc/PcHouseLayout.vue -->
<template>
  <NestVrPlayer />
  <NestCompanyLogo />
  <NestLanguageSwitcher />
  <NestPanoSize />
  <NestFloorPlan />
  <NestMiniFloorPlan />
  <NestPanoramaBtn />
  <NestRightPanel />
  <NestFloorBar />
  <NestDisclaimer />
  <NestBottomBar />
  <NestIntroduceBtn />
  <NestHouseTopBar />
  <NestIntroducePanel />
  <NestIntroduceActionPanel />
  <NestSceneTourPanel />
  <NestHouseDetailPanel />
  <NestHelpTip />
  <NestWechatQrOverlay />
</template>
```

**开发规范**：
- Layout 组件只负责 **引入和排列** 业务组件，不包含业务逻辑
- 新增 PC 功能组件后，需要在 `PcHouseLayout.vue` 中添加引用

---

## 五、新增功能模块的标准流程

以新增一个功能模块为例，标准开发步骤如下：

### 步骤 1：定义类型

```
types/xxx.ts          → 定义相关接口
types/index.ts        → 添加 export * from './xxx'
```

### 步骤 2：添加常量（如有）

```
config/constants.ts   → 添加相关常量
```

### 步骤 3：创建 Store

```
stores/xxx.ts         → 定义 useXxxStore
```

### 步骤 4：在 VR Store 中桥接 SDK 事件（如需要）

```
stores/vr.ts          → 在 registerEvents 中监听相关事件并转发
```

### 步骤 5：开发 UI 组件

```
components/common/pc/NestXxx.vue   → 公共 UI 组件（如有）
modules/pc/xxx/NestXxxPanel.vue    → 业务组件
```

### 步骤 6：注册到 Layout

```
layouts/pc/PcHouseLayout.vue       → 引入并排列组件
```

---

## 六、文件命名规范

| 类型 | 命名风格 | 示例 |
|---|---|---|
| Vue 组件（`.vue`） | **PascalCase**，`Nest` 前缀 | `NestMiniFloorPlan.vue` |
| TypeScript 文件（`.ts`） | **kebab-case** | `floor-plan.ts`、`sdk-helpers.ts` |
| 目录 | **kebab-case** | `components/common/`、`modules/pc/` |
| 常量 | `UPPER_SNAKE_CASE` | `VR_MODE`、`MINI_FLOOR_PLAN` |
| Store ID | `camelCase` | `defineStore('floorPlan', ...)` |

---

## 七、编码规范

### 7.1 Vue 组件

- 必须使用 `<script setup lang="ts">` + Composition API
- 组件文件头部添加 JSDoc 注释说明职责
- 样式使用 `<style scoped lang="scss">`
- CSS 类名使用 BEM 命名（如 `.mini-floor-plan__area`）

### 7.2 响应式与 SDK 对象

- SDK 返回的复杂对象使用 `shallowRef` 存储
- 传入 Store 的 SDK 对象使用 `markRaw` 包裹，防止 Vue Proxy 代理
- 调用 SDK 方法传入 position 等对象前，务必先 `clone()`

### 7.3 Store 间通信

- Store 之间使用直接方法调用
- 避免循环依赖：只能由上游 Store 调用下游 Store 的方法
- SDK 事件统一由 `vrStore` 接收后分发

### 7.4 样式规范

- 全局样式仅在 `App.vue` 中定义
- 组件样式必须使用 `scoped`
- 使用 SCSS 嵌套和 `&` 语法简化 BEM 写法

---

## 八、SDK 相关注意事项

### 8.1 加载顺序

SDK 依赖通过 `index.html` 的同步 `<script>` 标签加载，顺序不可更改：

```
jQuery → TWEEN.js → zqsdk → main.ts (module)
```

### 8.2 全局变量

| 变量 | 说明 |
|---|---|
| `window.zqsdk` | SDK 入口，提供 `init` 方法 |
| `window.housePlay` | SDK 初始化后挂载的实例，提供全部 API |
| `window.jQuery` / `window.$` | jQuery（SDK 内部依赖） |
| `window.TWEEN` | TWEEN.js（SDK 内部依赖） |

### 8.3 扩展 SDK 接口类型

如需使用新的 SDK 方法，请在 `types/vr.ts` 中的 `HousePlayInstance` 接口补充定义。

---

## 九、已实现功能模块

| 功能 | Store | 组件目录 | 说明 |
|---|---|---|---|
| VR 播放器 | `vr.ts` | `modules/pc/vr-player/` | SDK 容器、加载、错误处理 |
| 模式切换 | `vr.ts` | `modules/pc/right-panel/` | 全景/3D/户型图切换 |
| 户型图 | `floor-plan.ts` | `modules/pc/floor-plan/` | 全屏/迷你户型图、楼层切换 |
| 底部工具栏 | `toolbar.ts` | `modules/pc/toolbar/` | 标尺、标签、帮助、全屏等 |
| 全景标尺 | `toolbar.ts` | `modules/pc/pano-ruler/` | 三向标尺显示 |
| 导览 | `scene-tour.ts` | `modules/pc/scene-tour/` | 场景导览面板 |
| AI 讲房 | `introduce.ts` | `modules/pc/introduce/` | 讲房控制、地图、图片、航拍、POI |
| 房源详情 | `house-info.ts` | `modules/pc/house-info/` | 顶部标题、详情面板 |
| 国际化 | - | `i18n/` | 中/英/日多语言 |

---

## 十、开发命令

```bash
# 安装依赖
npm install

# 开发服务器（热重载）
npm run dev

# 类型检查 + 构建生产版本
npm run build

# 仅类型检查
npm run type-check

# 代码检查 & 修复
npm run lint

# 代码格式化
npm run format
```

---

## 十一、快速参考表：我该在哪里开发？

| 我要做什么 | 在哪里开发 |
|---|---|
| 新增全局常量 / 配置 | `config/constants.ts` |
| 新增 TypeScript 类型 | `types/` 下新建或扩展文件 |
| 新增工具函数 | `utils/` 下新建或扩展文件 |
| 新增组合式函数 | `composables/` 下新建文件 |
| 新增多语言文案 | `i18n/locales/` 下各语言文件 |
| 新增业务状态管理 | `stores/` 下新建 Store 文件 |
| 桥接新的 SDK 事件 | `stores/vr.ts` 的 `registerEvents` 函数 |
| 新增可复用 UI 组件 | `components/common/pc/` |
| 新增 PC 端业务组件 | `modules/pc/` 下对应功能目录 |
| 将组件加入页面 | `layouts/pc/PcHouseLayout.vue` |
| 扩展 SDK 接口类型 | `types/vr.ts` 的 `HousePlayInstance` |
| 修改全局样式 | `App.vue` |
| 新增静态图片资源 | `assets/icons/` 或 `assets/sprite/` |

---

## 十二、相关文档

| 文档 | 说明 |
|---|---|
| [VR 初始化展示指南](./VR初始化展示指南.md) | SDK 初始化流程 |
| [户型图集成指南](./户型图集成指南.md) | 户型图功能实现 |
| [导览集成指南](./导览集成指南.md) | 导览功能实现 |
| [AI 讲房集成指南](./AI讲房集成指南.md) | 讲房功能实现（含 POI） |
| [标尺显隐集成指南](./标尺显隐集成指南.md) | 全景标尺功能实现 |
