# Design Document

## Overview

本设计文档描述了将「农小禹智慧农业系统」从 uni-app Vue2 (Options API) 迁移到 uni-app Vue3 (Composition API) 的技术方案。迁移的核心目标是支持 HarmonyOS 打包,同时确保在 Android、iOS 和 H5 平台上的功能和行为完全一致。

### 迁移原则

1. **零业务逻辑改动** - 所有业务逻辑、API 调用、数据处理保持不变
2. **零 UI 结构改动** - 所有模板结构、样式、布局保持不变
3. **语法层面迁移** - 仅进行 Vue2 到 Vue3 的语法和 API 转换
4. **跨平台一致性** - 确保所有平台行为一致
5. **HarmonyOS 兼容** - 移除浏览器特定 API,使用 uni-app 跨平台 API
6. **可维护性优先** - 遵循 Vue3 最佳实践,添加清晰的注释

### 项目现状分析

**当前技术栈:**
- Vue 2.6.14 + Options API
- Vuex 3.6.2
- uni-app 2.x
- uview-ui 2.0.38
- 第三方插件: Jessibuca (视频播放)、高德地图 SDK

**项目规模:**
- 约 40+ 页面组件
- 4 个公共组件
- 15+ API 服务模块
- 1 个 Vuex store
- 多个工具函数模块

## Architecture

### 迁移架构设计

```
┌─────────────────────────────────────────────────────────────┐
│                     迁移执行层                                │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐      │
│  │ 组件迁移引擎  │  │ Store迁移引擎 │  │ 配置迁移引擎  │      │
│  └──────────────┘  └──────────────┘  └──────────────┘      │
└─────────────────────────────────────────────────────────────┘
                            ↓
┌─────────────────────────────────────────────────────────────┐
│                     转换规则层                                │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐      │
│  │ 语法转换规则  │  │ API映射规则   │  │ 生命周期映射  │      │
│  └──────────────┘  └──────────────┘  └──────────────┘      │
└─────────────────────────────────────────────────────────────┘
                            ↓
┌─────────────────────────────────────────────────────────────┐
│                     验证层                                    │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐      │
│  │ 语法验证器    │  │ 功能测试器    │  │ 性能测试器    │      │
│  └──────────────┘  └──────────────┘  └──────────────┘      │
└─────────────────────────────────────────────────────────────┘
```

### 分层职责

**迁移执行层:**
- 组件迁移引擎: 负责 .vue 文件的转换
- Store 迁移引擎: 负责 Vuex store 的升级
- 配置迁移引擎: 负责 package.json、manifest.json 等配置文件的更新

**转换规则层:**
- 语法转换规则: Options API → Composition API 的转换规则
- API 映射规则: Vue2 API → Vue3 API 的映射关系
- 生命周期映射: Vue2 生命周期钩子 → Vue3 生命周期钩子的映射

**验证层:**
- 语法验证器: 验证转换后的代码符合 Vue3 规范
- 功能测试器: 验证业务逻辑和功能一致性
- 性能测试器: 验证性能指标不低于原版本

## Components and Interfaces

### 核心组件

#### 1. 组件迁移引擎 (ComponentMigrationEngine)

**职责:** 将 Vue2 单文件组件转换为 Vue3 Composition API 格式

**接口:**
```typescript
interface ComponentMigrationEngine {
  // 迁移单个组件文件
  migrateComponent(filePath: string): MigrationResult
  
  // 批量迁移组件
  migrateComponents(filePaths: string[]): MigrationResult[]
  
  // 验证迁移结果
  validateMigration(result: MigrationResult): ValidationResult
}
```

**转换流程:**
1. 解析 Vue2 组件的 script、template、style 部分
2. 转换 script 部分: Options API → Composition API
3. 更新 template 部分: 移除 Vue2 特有语法
4. 保持 style 部分不变
5. 生成 Vue3 组件文件

#### 2. Store 迁移引擎 (StoreMigrationEngine)

**职责:** 将 Vuex 3.x store 升级到 Vuex 4.x 或迁移到 Pinia

**接口:**
```typescript
interface StoreMigrationEngine {
  // 迁移 store 文件
  migrateStore(storePath: string, target: 'vuex4' | 'pinia'): MigrationResult
  
  // 更新组件中的 store 使用
  updateStoreUsage(componentPath: string): MigrationResult
}
```


**转换策略:**
- 选项 A: 升级到 Vuex 4.x (保持 API 相似性,迁移成本低)
- 选项 B: 迁移到 Pinia (更现代,更好的 TypeScript 支持)
- 推荐: Vuex 4.x (项目已有 Vuex 使用经验,迁移风险低)

#### 3. 配置迁移引擎 (ConfigMigrationEngine)

**职责:** 更新项目配置文件以支持 Vue3

**接口:**
```typescript
interface ConfigMigrationEngine {
  // 更新 package.json 依赖
  updateDependencies(): void
  
  // 更新 manifest.json 配置
  updateManifest(): void
  
  // 更新 main.js 入口文件
  updateMainEntry(): void
}
```

**需要更新的配置:**
- package.json: 升级 Vue、Vuex、uni-app 等依赖
- manifest.json: 更新 vueVersion 为 "3"
- main.js: 使用 createApp 替代 new Vue

### 转换规则定义

#### Options API → Composition API 转换规则

| Vue2 Options API | Vue3 Composition API | 说明 |
|-----------------|---------------------|------|
| `data()` | `ref()` / `reactive()` | 基本类型用 ref,对象用 reactive |
| `methods` | 函数定义 | 在 setup 中定义普通函数 |
| `computed` | `computed()` | 使用 computed 函数包装 |
| `watch` | `watch()` / `watchEffect()` | 使用 watch 函数 |
| `props` | `defineProps()` | 使用 defineProps 声明 |
| `$emit` | `defineEmits()` | 使用 defineEmits 声明 |
| `this.$refs` | `ref()` | 使用 ref 创建模板引用 |
| `this.$store` | `useStore()` | 使用 useStore 获取 store |
| `this.$route` | `useRoute()` | 使用 useRoute 获取路由 |
| `this.$router` | `useRouter()` | 使用 useRouter 获取路由器 |

#### 生命周期钩子映射

| Vue2 生命周期 | Vue3 生命周期 | 说明 |
|--------------|--------------|------|
| `beforeCreate` | `setup()` 顶层 | 逻辑移至 setup 顶层 |
| `created` | `setup()` 顶层 | 逻辑移至 setup 顶层 |
| `beforeMount` | `onBeforeMount()` | 导入并使用 |
| `mounted` | `onMounted()` | 导入并使用 |
| `beforeUpdate` | `onBeforeUpdate()` | 导入并使用 |
| `updated` | `onUpdated()` | 导入并使用 |
| `beforeDestroy` | `onBeforeUnmount()` | 名称变更 |
| `destroyed` | `onUnmounted()` | 名称变更 |
| `activated` | `onActivated()` | 导入并使用 |
| `deactivated` | `onDeactivated()` | 导入并使用 |
| `errorCaptured` | `onErrorCaptured()` | 导入并使用 |
| uni-app 生命周期 | 保持不变 | onLoad, onShow, onHide 等 |

#### 模板语法转换规则

| Vue2 语法 | Vue3 语法 | 说明 |
|----------|----------|------|
| `v-model` | `v-model` | 自定义组件需调整 |
| `.sync` | `v-model:propName` | .sync 修饰符已移除 |
| `$listeners` | 移除 | 已合并到 $attrs |
| `v-bind="$attrs"` | `v-bind="$attrs"` | 保持不变 |
| 自定义指令钩子 | 更新钩子名称 | bind→beforeMount 等 |

## Data Models

### 迁移结果数据模型

```typescript
interface MigrationResult {
  // 文件路径
  filePath: string
  
  // 迁移状态
  status: 'success' | 'partial' | 'failed'
  
  // 转换后的代码
  code: string
  
  // 警告信息
  warnings: Warning[]
  
  // 错误信息
  errors: Error[]
  
  // TODO 项
  todos: TodoItem[]
}

interface Warning {
  line: number
  column: number
  message: string
  rule: string
}

interface TodoItem {
  line: number
  message: string
  reason: string
  recommendation: string
}

interface ValidationResult {
  isValid: boolean
  errors: ValidationError[]
  warnings: ValidationWarning[]
}
```

### 组件转换示例

**Vue2 组件 (Before):**
```vue
<script>
export default {
  data() {
    return {
      count: 0,
      user: {
        name: 'John',
        age: 30
      }
    }
  },
  computed: {
    doubleCount() {
      return this.count * 2
    }
  },
  methods: {
    increment() {
      this.count++
    }
  },
  mounted() {
    console.log('Component mounted')
  }
}
</script>
```

**Vue3 组件 (After):**
```vue
<script setup>
import { ref, reactive, computed, onMounted } from 'vue'

const count = ref(0)
const user = reactive({
  name: 'John',
  age: 30
})

const doubleCount = computed(() => count.value * 2)

const increment = () => {
  count.value++
}

onMounted(() => {
  console.log('Component mounted')
})
</script>
```


### Store 转换示例

**Vuex 3.x (Before):**
```javascript
// store/index.js
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment(state) {
      state.count++
    }
  }
})

export default store
```

**Vuex 4.x (After):**
```javascript
// store/index.js
import { createStore } from 'vuex'

const store = createStore({
  state: {
    count: 0
  },
  mutations: {
    increment(state) {
      state.count++
    }
  }
})

export default store
```

**组件中使用 Store (Before):**
```vue
<script>
export default {
  computed: {
    count() {
      return this.$store.state.count
    }
  },
  methods: {
    increment() {
      this.$store.commit('increment')
    }
  }
}
</script>
```

**组件中使用 Store (After):**
```vue
<script setup>
import { computed } from 'vue'
import { useStore } from 'vuex'

const store = useStore()

const count = computed(() => store.state.count)

const increment = () => {
  store.commit('increment')
}
</script>
```

### 全局配置转换示例

**main.js (Before):**
```javascript
import Vue from 'vue'
import App from './App'
import store from './store'
import uView from 'uview-ui'

// 全局过滤器
Vue.filter('formatDate', (value) => {
  // ...
})

// 全局属性
Vue.prototype.$api = api

Vue.use(store)
Vue.use(uView)

const app = new Vue({
  store,
  ...App
})
app.$mount()
```

**main.js (After):**
```javascript
import { createSSRApp } from 'vue'
import App from './App.vue'
import store from './store'
import uView from 'uview-ui' // 需要 Vue3 兼容版本

// 全局方法 (替代过滤器)
import { formatDate } from './utils/filters'

export function createApp() {
  const app = createSSRApp(App)
  
  app.use(store)
  app.use(uView)
  
  // 全局属性
  app.config.globalProperties.$api = api
  app.config.globalProperties.$formatDate = formatDate
  
  return {
    app
  }
}
```

## Correctness Properties

*属性 (Property) 是关于系统应该如何行为的形式化陈述,它应该在所有有效执行中保持为真。属性是人类可读规范和机器可验证正确性保证之间的桥梁。通过属性测试,我们可以验证代码在各种输入下的正确性。*

### Property 1: Options API 完整转换

*对于任意* Vue2 组件,如果它包含 data、methods、computed、watch 中的任意选项,转换后的 Vue3 组件应该使用对应的 Composition API (ref/reactive、函数定义、computed()、watch()),并且不包含 Options API 的选项对象。

**Validates: Requirements 1.1, 1.3**

### Property 2: 生命周期钩子正确映射

*对于任意* Vue2 组件,如果它包含生命周期钩子 (mounted、created、beforeDestroy、destroyed 等),转换后的 Vue3 组件应该使用对应的 Composition API 钩子 (onMounted、setup 顶层、onBeforeUnmount、onUnmounted 等),并且钩子内的业务逻辑保持不变。

**Validates: Requirements 1.2, 2.1, 2.2, 2.3, 2.4**

### Property 3: uni-app 生命周期保持不变

*对于任意* 包含 uni-app 特有生命周期 (onLoad、onShow、onHide、onPullDownRefresh 等) 的组件,转换后这些生命周期钩子的名称和用法应该保持完全不变。

**Validates: Requirements 2.5**

### Property 4: this 关键字完全移除

*对于任意* 转换后的 Vue3 组件,代码中不应该包含 `this.` 的引用 (除了在注释中),所有数据和方法访问应该使用 Composition API 的直接引用。

**Validates: Requirements 1.4**

### Property 5: script setup 语法使用

*对于任意* 转换后的 Vue3 组件,应该使用 `<script setup>` 语法糖,而不是传统的 `<script>` + `export default` 方式。

**Validates: Requirements 1.5**

### Property 6: Store 使用方式转换

*对于任意* 在组件中使用 Vuex store 的代码,转换后应该使用 `useStore()` 获取 store 实例,而不是 `this.$store`,并且所有 store 状态访问应该使用 `computed()` 包装以保持响应性。

**Validates: Requirements 3.2, 3.3**

### Property 7: Props 和 Emits 声明

*对于任意* 接收 props 或发出事件的组件,转换后应该使用 `defineProps()` 和 `defineEmits()` 进行声明,并且保持原有的类型定义、默认值和验证规则。

**Validates: Requirements 7.1, 7.2, 7.3**

### Property 8: 模板引用转换

*对于任意* 使用 `this.$refs` 的代码,转换后应该使用 `ref()` 创建模板引用,并且在模板中使用 `ref` 属性绑定。

**Validates: Requirements 6.3**

### Property 9: 计算属性和侦听器转换

*对于任意* 包含 computed 或 watch 的组件,转换后应该使用 `computed()` 和 `watch()` 函数,并且保持原有的选项 (如 deep、immediate)。

**Validates: Requirements 8.1, 8.2, 8.4**

### Property 10: 浏览器 API 移除

*对于任意* 转换后的代码,不应该包含 `window.` 或 `document.` 的直接引用,所有浏览器特定功能应该使用 uni-app 提供的跨平台 API 替代。

**Validates: Requirements 10.1, 10.2**

### Property 11: 条件编译正确使用

*对于任意* 平台特定的代码,应该使用 uni-app 的条件编译标记 (`#ifdef`、`#ifndef` 等) 进行隔离,并且包含对 HarmonyOS 平台的支持。

**Validates: Requirements 10.5, 13.5**

### Property 12: 模板结构保持不变

*对于任意* Vue 组件,转换前后的 `<template>` 部分的 DOM 结构、元素层级、class 和 style 绑定应该保持完全一致 (除了必要的语法更新如 .sync → v-model:propName)。

**Validates: Requirements 12.1, 12.3**

### Property 13: 样式保持不变

*对于任意* Vue 组件,转换前后的 `<style>` 部分的内容应该保持完全一致,包括所有 CSS/SCSS 规则、选择器和属性。

**Validates: Requirements 12.2**

### Property 14: v-model 语法更新

*对于任意* 在模板中使用 v-model 的自定义组件,转换后应该符合 Vue3 的 v-model 语法规范,并且 .sync 修饰符应该转换为 v-model:propName 语法。

**Validates: Requirements 5.1, 5.4**

### Property 15: $listeners 移除

*对于任意* 使用 `$listeners` 的代码,转换后应该移除 `$listeners` 的引用,因为 Vue3 已将其合并到 `$attrs` 中。

**Validates: Requirements 5.3**

### Property 16: 自定义指令钩子更新

*对于任意* 自定义指令,转换后应该更新指令钩子名称 (bind → beforeMount, inserted → mounted, update → updated, componentUpdated → updated, unbind → unmounted)。

**Validates: Requirements 5.2**

### Property 17: TODO 注释添加

*对于任意* 无法自动迁移的代码,转换后应该添加明确的 TODO 注释,包含问题原因和推荐的解决方案。

**Validates: Requirements 14.2, 17.1, 17.2**


## Error Handling

### 错误分类

#### 1. 语法错误 (Syntax Errors)
- **描述:** 转换后的代码不符合 Vue3 语法规范
- **处理策略:** 
  - 添加 TODO 注释标记问题位置
  - 提供详细的错误信息和修复建议
  - 在迁移报告中记录错误详情

#### 2. 不兼容的第三方库 (Incompatible Dependencies)
- **描述:** 第三方库不支持 Vue3
- **处理策略:**
  - uview-ui: 升级到 uview-plus (Vue3 版本)
  - Jessibuca: 保持现有实现,使用条件编译隔离 H5 平台
  - 其他库: 寻找 Vue3 兼容的替代方案或自行实现

#### 3. 复杂的 this 引用 (Complex this References)
- **描述:** 某些复杂的 this 引用难以自动转换
- **处理策略:**
  - 添加 TODO 注释
  - 提供手动转换指南
  - 示例:
    ```javascript
    // TODO: 手动转换复杂的 this 引用
    // 原因: 动态属性访问难以自动推断
    // 推荐: 使用明确的变量引用替代 this[dynamicKey]
    ```

#### 4. 全局混入 (Global Mixins)
- **描述:** 全局混入在 Vue3 中不推荐使用
- **处理策略:**
  - 评估是否可以转换为组合式函数
  - 如果必须保留,添加 TODO 注释说明
  - 提供组合式函数的重构建议

#### 5. 过滤器 (Filters)
- **描述:** Vue3 移除了过滤器功能
- **处理策略:**
  - 转换为全局方法: `app.config.globalProperties.$filterName`
  - 或转换为组合式函数
  - 在模板中使用方法调用替代管道语法

### 错误恢复机制

```typescript
interface ErrorRecovery {
  // 尝试自动修复
  autoFix(error: MigrationError): FixResult
  
  // 回退到安全状态
  rollback(filePath: string): void
  
  // 生成修复建议
  generateSuggestion(error: MigrationError): Suggestion
}
```

### 日志和报告

**迁移日志格式:**
```
[INFO] 开始迁移: pages/dashboard/index.vue
[SUCCESS] 转换 data → ref/reactive
[SUCCESS] 转换 methods → 函数定义
[SUCCESS] 转换 computed → computed()
[WARNING] 发现复杂的 this 引用,已添加 TODO 注释
[SUCCESS] 转换 mounted → onMounted
[INFO] 迁移完成: pages/dashboard/index.vue (1 warning, 0 errors)
```

**迁移报告结构:**
```markdown
# 迁移报告

## 概览
- 总文件数: 45
- 成功: 40
- 部分成功: 4
- 失败: 1

## 详细信息

### 成功迁移 (40)
- pages/dashboard/index.vue
- pages/login/index.vue
- ...

### 部分成功 (4)
- pages/device/index.vue (1 warning)
  - 警告: 复杂的 this 引用需要手动处理
- ...

### 失败 (1)
- components/complex-component.vue
  - 错误: 使用了不支持的第三方库

## TODO 清单
1. pages/device/index.vue:123 - 手动转换复杂的 this 引用
2. components/complex-component.vue:45 - 替换不兼容的第三方库
```

## Testing Strategy

### 测试方法论

本项目采用**双重测试策略**:
1. **单元测试** - 验证具体示例、边缘情况和错误条件
2. **属性测试** - 验证通用属性在所有输入下的正确性

两种测试方法互补:
- 单元测试捕获具体的 bug 和边缘情况
- 属性测试验证通用的正确性保证

### 属性测试配置

**测试框架:** 
- JavaScript/TypeScript: fast-check
- 最小迭代次数: 100 次
- 每个正确性属性对应一个属性测试

**测试标记格式:**
```javascript
// Feature: vue2-to-vue3-migration, Property 1: Options API 完整转换
test('Options API should be fully converted to Composition API', () => {
  fc.assert(
    fc.property(
      generateVue2Component(), // 生成器
      (component) => {
        const result = migrateComponent(component)
        // 验证转换后不包含 Options API
        expect(result.code).not.toMatch(/export default\s*{/)
        expect(result.code).toMatch(/<script setup>/)
      }
    ),
    { numRuns: 100 }
  )
})
```

### 单元测试策略

#### 1. 语法转换测试
- 测试 data → ref/reactive 转换
- 测试 methods → 函数定义转换
- 测试 computed → computed() 转换
- 测试 watch → watch() 转换
- 测试生命周期钩子映射

#### 2. 边缘情况测试
- 空组件
- 只有 template 的组件
- 复杂嵌套的数据结构
- 动态属性访问
- 异步操作

#### 3. 集成测试
- 完整页面的迁移
- Store 与组件的集成
- 路由与组件的集成
- 第三方库的集成

#### 4. 功能测试
- 用户登录流程
- 数据列表加载和展示
- 表单提交和验证
- 页面跳转和参数传递
- 地图定位功能
- 视频播放功能

#### 5. 跨平台测试
- Android 平台功能测试
- iOS 平台功能测试
- H5 平台功能测试
- HarmonyOS 平台功能测试

### 性能测试

**关键指标:**
- 应用启动时间
- 页面首次渲染时间
- 页面切换时间
- 列表滚动流畅度
- 内存占用

**测试方法:**
- 使用 uni-app 性能分析工具
- 在真机上进行测试
- 对比迁移前后的性能数据

### 视觉回归测试

**工具:** Percy 或 BackstopJS

**测试范围:**
- 所有主要页面的截图对比
- 不同屏幕尺寸的适配
- 不同主题的显示

### 测试覆盖率目标

- 单元测试覆盖率: > 80%
- 集成测试覆盖率: > 60%
- 关键业务流程: 100%

## Implementation Notes

### 迁移顺序

**阶段 1: 基础设施迁移**
1. 更新 package.json 依赖
2. 更新 manifest.json 配置
3. 迁移 main.js 入口文件
4. 迁移 Vuex store

**阶段 2: 工具函数和服务迁移**
1. 迁移 utils 工具函数
2. 迁移 API 服务模块
3. 更新全局配置和常量

**阶段 3: 组件迁移**
1. 迁移公共组件 (components/common)
2. 迁移页面组件 (pages)
   - 优先级: 登录页 → 首页 → 其他页面
3. 迁移 App.vue

**阶段 4: 测试和验证**
1. 运行单元测试
2. 运行属性测试
3. 进行功能测试
4. 进行跨平台测试
5. 进行性能测试

### 关键技术决策

#### 1. 状态管理: Vuex 4.x vs Pinia

**决策: 使用 Vuex 4.x**

**理由:**
- 项目已有 Vuex 使用经验
- Vuex 4.x API 与 3.x 高度相似,迁移成本低
- 不需要重新培训团队
- 风险较低

#### 2. UI 组件库: uview-ui 升级方案

**决策: 升级到 uview-plus**

**理由:**
- uview-plus 是 uview-ui 的 Vue3 版本
- API 基本保持一致
- 官方维护,稳定性有保障

**迁移步骤:**
1. 安装 uview-plus: `npm install uview-plus`
2. 更新导入语句
3. 测试所有使用的组件
4. 处理 API 差异 (如有)

#### 3. 视频播放: Jessibuca 处理方案

**决策: 保持现有实现,使用条件编译**

**理由:**
- Jessibuca 主要用于 H5 平台
- 不影响其他平台
- 使用条件编译隔离

**实现:**
```javascript
// #ifdef H5
import JessibucaPlugin from './utils/jessibuca-plugin'
app.use(JessibucaPlugin)
// #endif
```

### HarmonyOS 特殊处理

#### 1. 条件编译标记

```javascript
// #ifdef H5 || MP-WEIXIN || APP-PLUS
// 通用代码
// #endif

// #ifdef APP-PLUS-NVUE
// nvue 特定代码
// #endif

// 添加 HarmonyOS 支持
// #ifdef H5 || MP-WEIXIN || APP-PLUS || MP-HARMONY
// 跨平台代码
// #endif
```

#### 2. API 兼容性处理

**地图功能:**
```javascript
// 使用 uni-app 统一 API
uni.getLocation({
  type: 'gcj02',
  success: (res) => {
    // 处理定位结果
  }
})
```

**存储功能:**
```javascript
// 使用 uni-app 统一 API
uni.setStorageSync('key', 'value')
const value = uni.getStorageSync('key')
```

### 不可自动迁移的场景

以下场景需要手动处理,迁移工具会添加 TODO 注释:

1. **动态组件名称**
```javascript
// TODO: 手动转换动态组件引用
// 原因: 动态 import 需要根据具体情况调整
// 推荐: 使用 defineAsyncComponent 包装
const component = () => import(`@/components/${dynamicName}.vue`)
```

2. **复杂的 this 上下文**
```javascript
// TODO: 手动转换复杂的 this 引用
// 原因: 动态属性访问难以自动推断
// 推荐: 重构为明确的变量引用
const value = this[computedKey]
```

3. **render 函数**
```javascript
// TODO: 手动转换 render 函数
// 原因: render 函数在 Vue3 中有 API 变更
// 推荐: 参考 Vue3 render 函数文档
render(h) {
  return h('div', 'content')
}
```

4. **全局混入**
```javascript
// TODO: 评估是否可以转换为组合式函数
// 原因: 全局混入在 Vue3 中不推荐使用
// 推荐: 使用组合式函数替代
Vue.mixin({
  // ...
})
```

### 迁移检查清单

- [ ] package.json 依赖已更新
- [ ] manifest.json vueVersion 已更新为 "3"
- [ ] main.js 使用 createSSRApp
- [ ] Vuex store 已升级到 4.x
- [ ] 所有组件使用 `<script setup>`
- [ ] 所有 this 引用已移除
- [ ] 所有生命周期钩子已更新
- [ ] 所有 store 使用已更新为 useStore()
- [ ] 所有过滤器已转换为方法
- [ ] 所有全局属性已迁移到 globalProperties
- [ ] 所有 window/document 引用已移除
- [ ] 所有条件编译已包含 HarmonyOS 支持
- [ ] uview-ui 已升级到 uview-plus
- [ ] 所有单元测试通过
- [ ] 所有属性测试通过
- [ ] 所有平台功能测试通过
- [ ] 性能指标不低于原版本
