@doubao-apps/ai 0.0.20 → 0.0.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,334 @@
1
+ ---
2
+ name: uniapp-to-doubao
3
+ description: Migrate uni-app mini program projects to Doubao Apps SDK (React Lynx). Use when converting uni-app Vue2 SFC pages/components, pages.json, App.vue, main.js, or uni.* APIs.
4
+ ---
5
+
6
+ # uni-app 2.0.0 to Doubao Apps Migration Skill
7
+
8
+ ## When to Use
9
+
10
+ - Converting `uni-app` mini program projects to Doubao Apps
11
+ - User mentions "uni-app 转豆包小程序", "uniapp to doubao", "Vue SFC 小程序迁移"
12
+ - Working with `App.vue`, `main.js`, `pages.json`, `manifest.json`, `.vue` page/component files
13
+ - Replacing `uni.*` APIs and uni-app template syntax with Doubao Apps patterns
14
+
15
+ ---
16
+
17
+ ## Core Principles
18
+
19
+ **CRITICAL RULES - MUST FOLLOW:**
20
+
21
+ 1. **Lock Source Major Version**: This skill targets **uni-app `2.0.0` 系列**。Do not assume Vue3, Composition API, `<script setup>`, or APIs/components introduced in later uni-app versions.
22
+ 2. **Preserve Business Logic**: Only change framework APIs and syntax, never alter business rules.
23
+ 3. **Plan Before Execute**: Always analyze the source project and present a migration plan before editing files.
24
+ 4. **Mapping First**: Read mapping docs first; only fall back to raw source docs for uncovered cases.
25
+ 5. **Incremental Migration**: Convert page by page / component by component and keep a migration report.
26
+ 6. **Record Gaps**: Document platform-specific or version-ambiguous capabilities instead of guessing.
27
+
28
+ ---
29
+
30
+ ## 官方文档入口(已于 2026-04-09 校验可访问)
31
+
32
+ 以下链接用于确认 `uni-app 2.0.0` 的官方历史版本与基础语法入口:
33
+
34
+ - 历史版本归档(包含 `2.0.0` 系列历史构建): `https://uniapp.dcloud.net.cn/release-archive.html`
35
+ - `2.0.0` 系列发布记录:见归档页中 `2.0.0.x` 相关条目(如 `2.0.0.20190610`)
36
+ - 页面与生命周期: `https://uniapp.dcloud.io/tutorial/page.html`
37
+ - `pages.json` 配置: `https://uniapp.dcloud.io/collocation/pages.html`
38
+ - 网络请求 / `uni.request`: `https://uniapp.dcloud.io/api/request/request.html`
39
+ - 条件编译: `https://uniapp.dcloud.io/tutorial/platform`
40
+ - 组件总览入口: `https://uniapp.dcloud.io/component/`
41
+
42
+ **使用约束**:
43
+
44
+ - 当前官网文档会持续更新,因此它们只能用来确认 **uni-app 的基础语法形态**。
45
+ - 只要当前文档中出现了 `2.0.0` 系列之后新增的能力,均不得迁入目标代码。
46
+ - 本 skill 内部所有示例均按 **Vue2 Options API + uni-app 2.0.0** 口径编写。
47
+
48
+ ---
49
+
50
+ ## 知识来源速查
51
+
52
+ ### 目标框架文档(按需读取)
53
+
54
+ 安装路径(`$SKILLS_BASE`,由 Step 0 检测确定):
55
+
56
+ | Agent 环境 | 知识库路径 |
57
+ |------------|-----------|
58
+ | Codex / Cursor / Cline | `.agents/skills/doubao-apps-dev` |
59
+ | Claude Code | `.claude/skills/doubao-apps-dev` |
60
+
61
+ 通过以下命令安装:
62
+
63
+ ```bash
64
+ npx @doubao-apps/ai skills add doubao-apps-dev --agent codex
65
+ ```
66
+
67
+ | 文档 | 路径 | 用途 |
68
+ |------|------|------|
69
+ | 框架 API 速查 | `$SKILLS_BASE/.ai/reference/framework-api-quick-ref.md` | `definePage` / `defineApp` / `getViewData` 等 |
70
+ | 开发规则 | `$SKILLS_BASE/.ai/rules/dos-and-donts.md` | 必须遵守的目标框架规范 |
71
+ | 组件开发指南 | `$SKILLS_BASE/.ai/guides/component-development.md` | 页面/组件组织方式 |
72
+ | 组件库参考 | `$SKILLS_BASE/.ai/reference/components-quick-ref.md` | 目标组件 API |
73
+
74
+ ### 映射文档(迁移核心依据)
75
+
76
+ | 文档 | 路径 |
77
+ |------|------|
78
+ | 核心 API 映射 | `./references/mapping/core-api-mapping.md` |
79
+ | 生命周期映射 | `./references/mapping/lifecycle-mapping.md` |
80
+ | 组件映射 | `./references/mapping/component-mapping.md` |
81
+ | 样式映射 | `./references/mapping/style-mapping.md` |
82
+ | 事件映射 | `./references/mapping/event-mapping.md` |
83
+
84
+ ### 源框架文档(按问题读取)
85
+
86
+ | 文档 | 路径 | 何时读取 |
87
+ |------|------|----------|
88
+ | uni-app 2.0.0 API / 配置参考 | `./references/source-framework/api-reference.md` | 识别 `uni.*`、`App.vue`、`pages.json`、条件编译 |
89
+ | uni-app 2.0.0 组件 / 模板参考 | `./references/source-framework/components.md` | 识别模板语法、内置组件、`v-if` / `v-for` / `@tap` 等 |
90
+
91
+ ### 代码导入来源
92
+
93
+ | 包名 | 用途 | 示例 |
94
+ |------|------|------|
95
+ | `@doubao-apps/framework` | 框架 API 和 React Hooks | `import { definePage, useEffect } from '@doubao-apps/framework'` |
96
+ | `@doubao-apps/framework/api` | 端能力 API(替代 `uni.*`) | `import { request, showToast, navigateTo } from '@doubao-apps/framework/api'` |
97
+ | `@doubao-apps/framework/components` | 目标组件库导出;大部分已支持的小写标签会由 loader 自动注入 import | `import { PickerView, PickerColumn } from '@doubao-apps/framework/components'` |
98
+
99
+ > 当前工程已支持直接写小写标签:`<view>`、`<text>`、`<image>`、`<input>`、`<textarea>`、`<scroll-view>`、`<list>`、`<list-item>`、`<button>`、`<switch>`、`<slider>`、`<swiper>`、`<swiper-item>`、`<map>`、`<map-marker>`、`<movable-area>`、`<movable-view>`、`<popup>`、`<radio>`、`<radio-group>`、`<picker-view>`、`<picker-column>`、`<web-view>`、`<svg>`。其中大部分标签会由 loader 自动补 import;`<list-item>` 当前主要依赖 JSX intrinsic / Lynx 原生标签能力,不要假设 loader 会补组件导入。
100
+
101
+ ---
102
+
103
+ ## 迁移流程
104
+
105
+ ### Step 0: 环境检查
106
+
107
+ **1. 确定知识库路径(`$SKILLS_BASE`)**
108
+
109
+ 依次检测以下路径,取第一个存在的作为 `$SKILLS_BASE`:
110
+
111
+ ```bash
112
+ ls .agents/skills/doubao-apps-dev/AGENTS.md 2>/dev/null && echo "SKILLS_BASE=.agents/skills/doubao-apps-dev"
113
+ ls .claude/skills/doubao-apps-dev/AGENTS.md 2>/dev/null && echo "SKILLS_BASE=.claude/skills/doubao-apps-dev"
114
+ ```
115
+
116
+ **2. 如未安装,执行安装**
117
+
118
+ ```bash
119
+ npx @doubao-apps/ai skills add doubao-apps-dev --agent codex
120
+ ```
121
+
122
+ **3. 初始化 Doubao Apps 目标项目**
123
+
124
+ 询问用户目标项目目录名(默认为源项目目录名加 `-doubao` 后缀),然后创建空项目:
125
+
126
+ ```bash
127
+ npx @doubao-apps/create <target-dir> --template empty -y
128
+ ```
129
+
130
+ 创建成功后,将 `<target-dir>` 记录为 `$TARGET_PROJECT_PATH`,后续迁移产物统一输出到该目录。
131
+
132
+ ---
133
+
134
+ ### Step 1: 分析源项目
135
+
136
+ 扫描 uni-app `2.0.0` 项目,识别:
137
+
138
+ - `App.vue`、`main.js`、`pages.json`、`manifest.json` 是否齐全
139
+ - `.vue` 页面和组件数量及目录分布
140
+ - 使用的 `uni.*` API 清单
141
+ - 是否存在平台原生 API 穿透:`wx.*`、`my.*`、`swan.*`、`tt.*` 等
142
+ - 模板指令:`v-if` / `v-else` / `v-for` / `:prop` / `@tap` / `@click` / `v-model`
143
+ - 样式特征:`scoped`、`lang="scss"`、`rpx`、全局样式、`@import`
144
+ - 条件编译:`#ifdef` / `#ifndef` / `#endif`
145
+ - 页面路由、导航栏、下拉刷新、tabBar 等 `pages.json` 配置
146
+
147
+ **输出示例**:
148
+
149
+ ```text
150
+ 📊 项目分析报告
151
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
152
+ 源框架:uni-app 2.0.0(Vue2 Options API)
153
+
154
+ 文件数量:22 个页面/组件
155
+ └─ 页面(pages/):14 个
156
+ └─ 组件(components/):8 个
157
+
158
+ uni.* API:
159
+ ✅ 可直接迁移:uni.request, uni.showToast, uni.navigateTo, uni.setStorageSync
160
+ ⚠️ 需人工决策:uni.login, 条件编译下的 wx.* 原生调用
161
+
162
+ 模板语法:
163
+ ✅ 常规:v-if, v-for, :prop, @tap, @input
164
+ ⚠️ 需重写:v-model, slot, scoped 样式深层选择器
165
+
166
+ pages.json:
167
+ ⚠️ 需重建:tabBar、navigationBarTitleText、enablePullDownRefresh
168
+
169
+ 复杂度评估:中高
170
+ ```
171
+
172
+ ---
173
+
174
+ ### Step 2: 读取映射文档
175
+
176
+ 按以下顺序读取,建立转换规则索引:
177
+
178
+ 1. `./references/mapping/core-api-mapping.md`
179
+ 2. `./references/mapping/lifecycle-mapping.md`
180
+ 3. `./references/mapping/component-mapping.md`
181
+ 4. `./references/mapping/style-mapping.md`
182
+ 5. `./references/mapping/event-mapping.md`
183
+
184
+ 遇到未覆盖场景时,再回读源框架文档:
185
+
186
+ 1. `./references/source-framework/api-reference.md`
187
+ 2. `./references/source-framework/components.md`
188
+
189
+ ---
190
+
191
+ ### Step 3: 生成迁移计划
192
+
193
+ 基于项目分析和映射规则,生成迁移计划并**展示给用户确认**:
194
+
195
+ ```text
196
+ 📋 迁移计划
197
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
198
+ 迁移顺序(共 22 个文件):
199
+ [1] pages/index/index.vue → 简单,纯展示页
200
+ [2] pages/list/index.vue → 中等,含 uni.request / scroll-view
201
+ [3] components/goods-card.vue → 中等,含 props / emit / scoped 样式
202
+ ...
203
+
204
+ 风险点:
205
+ ⚠️ uni.login 需要重接登录链路
206
+ ⚠️ pages.json 的 tabBar / 下拉刷新要在目标工程重建
207
+ ⚠️ 条件编译里的平台原生 API 不能机械迁移
208
+
209
+ 是否开始迁移?(y/n)
210
+ ```
211
+
212
+ ---
213
+
214
+ ### Step 4: 执行迁移
215
+
216
+ #### 4.1 文件转换规则
217
+
218
+ uni-app `2.0.0` 页面/组件通常以 `.vue` 单文件组件存在;迁移后统一拆为 Doubao Apps 的 `index.tsx` + `index.scss`:
219
+
220
+ | uni-app 2.0.0 | Doubao Apps | 说明 |
221
+ |--------------|-------------|------|
222
+ | `page.vue` 的 `<template>` | `index.tsx` TSX 部分 | 模板转 TSX |
223
+ | `page.vue` 的 `<script>` | `index.tsx` 逻辑部分 | Vue2 Options API 转 React / `definePage` |
224
+ | `page.vue` 的 `<style>` | `index.scss` | 样式尽量保留 class 语义 |
225
+ | `pages.json` | 目标工程路由与页面元信息 | 逐项重建,不直接复制 |
226
+ | `App.vue` + `main.js` | `src/app.ts` | 应用生命周期与入口重写 |
227
+
228
+ > **⚠️ 命名约束**:页面/组件目录下的入口文件必须命名为 **`index.tsx`**,样式文件为 **`index.scss`**。
229
+
230
+ #### 4.2 单文件转换步骤(每个页面/组件)
231
+
232
+ 1. **入口与配置拆分**:`App.vue` / `main.js` / `pages.json` / 单个 `.vue`
233
+ 2. **Vue2 Options API 转换**:`data` / `props` / `computed` / `watch` / `methods`
234
+ 3. **页面定义方式**:页面输出为 `definePage({ ... })`,子组件输出为 `FC<Props>`
235
+ 4. **页面输入获取**:不要假设存在 uni-app 同名页面参数钩子,优先通过 `getViewData()` / `getViewContext()` 或页面容器注入
236
+ 5. **模板转 TSX**:`v-if` / `v-for` / `:prop` / `@tap` / `slot`
237
+ 6. **样式转 `index.scss`**:保留 class 语义,动态值才用内联 `style`
238
+ 7. **`uni.*` API 替换**:迁到 `@doubao-apps/framework/api`;必须按目标 API 的真实参数签名改写,不能只做同名替换
239
+ 8. **条件编译拆分**:`#ifdef` 中的宿主原生代码单独评估
240
+
241
+ #### 4.3 转换策略(优先级从高到低)
242
+
243
+ ```text
244
+ 映射文档 → 官方源文档 / 2.0.0 系列发布记录 → 目标框架文档 → AI 推断 → 询问用户
245
+ ```
246
+
247
+ ---
248
+
249
+ ### Step 5: 迁移摘要
250
+
251
+ ```text
252
+ 📋 迁移摘要
253
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
254
+ 已迁移:22/22 文件
255
+ └─ 页面:14 个 └─ 组件:8 个
256
+
257
+ 需重建配置:
258
+ - pages.json tabBar
259
+ - 页面导航栏标题
260
+ - 下拉刷新配置
261
+
262
+ 需人工处理:
263
+ - uni.login × 1 处
264
+ - #ifdef MP-WEIXIN 内的 wx.chooseAddress × 2 处
265
+ ```
266
+
267
+ ---
268
+
269
+ ### Step 6: 质量门禁(Quality Gate)
270
+
271
+ **⚠️ 必须完成三层质量门禁,迁移才算完成。**
272
+
273
+ 参数:
274
+
275
+ | 参数 | 值 |
276
+ |------|----|
277
+ | `source_code_path` | uni-app 源项目路径 |
278
+ | `target_code_path` | `$TARGET_PROJECT_PATH` |
279
+ | `source_platform` | `uniapp` |
280
+ | `target_platform` | `doubao` |
281
+ | `framework_rules` | `$SKILLS_BASE/.ai/rules/dos-and-donts.md` |
282
+
283
+ **根据当前 Agent 环境选择调用方式**:
284
+
285
+ - **Claude Code**(支持 Skill tool):
286
+ ```text
287
+ Skill(skill="quality-gate", args="source_code_path=<源项目路径> target_code_path=<目标项目路径> source_platform=uniapp target_platform=doubao")
288
+ ```
289
+
290
+ - **Codex / 其他 Agent**:
291
+ 读取 `packages/ai/skills/quality-gate/SKILL.md`,按其中流程执行。
292
+
293
+ ---
294
+
295
+ ## uni-app 2.0.0 专项规则
296
+
297
+ ### 1. 只按 Vue2 Options API 迁移
298
+
299
+ 遇到以下写法时,**不要**把它们当作 `uni-app 2.0.0` 的标准能力:
300
+
301
+ - `<script setup>`
302
+ - Composition API(`setup`, `ref`, `reactive`, `computed()` 等)
303
+ - Vue3 专有语法
304
+ - 后续版本新增的 uni-app API / 组件 / 条件编译能力
305
+
306
+ 如果源项目出现这些写法,先标记为“源项目版本已超出本 skill 范围”。
307
+
308
+ ### 2. `pages.json` 是关键迁移点
309
+
310
+ uni-app 页面注册、首页、导航栏、下拉刷新、tabBar 都依赖 `pages.json`。迁移时:
311
+
312
+ - 必须完整扫描 `pages`、`subPackages`、`globalStyle`、`tabBar`
313
+ - 不要只迁 `.vue` 文件而忽略页面配置
314
+ - 不要把 `pages.json` 原样复制到目标工程
315
+
316
+ ### 3. 条件编译不能机械搬运
317
+
318
+ `#ifdef MP-WEIXIN`、`#ifdef APP-PLUS` 等代码说明源项目包含平台分支:
319
+
320
+ - 先确认该分支是否是“小程序业务必须逻辑”
321
+ - 再确认目标 Doubao 工程是否存在等价能力
322
+ - 无等价物时必须记录缺口,不得默默删除或假造实现
323
+
324
+ ### 4. uni-app 不等于纯微信小程序
325
+
326
+ 虽然 uni-app `2.0.0` 很多 API / 组件语义接近微信小程序,但它仍有:
327
+
328
+ - Vue2 单文件组件结构
329
+ - `pages.json` 配置中心
330
+ - `uni.$on / $emit / $off / $once`
331
+ - 条件编译
332
+ - `App.vue` / `main.js` 入口组织方式
333
+
334
+ 因此不要简单套用微信小程序 skill;必须优先使用本 skill 的映射规则。
@@ -0,0 +1,145 @@
1
+ # uni-app 2.0.0 → Doubao Apps 迁移检查清单
2
+
3
+ > 对每个迁移的页面 / 组件,逐项执行本清单。
4
+
5
+ ---
6
+
7
+ ## 前置准备
8
+
9
+ - [ ] 确认源项目按 `uni-app 2.0.0` 系列口径处理
10
+ - [ ] 安装 Doubao Apps 知识库:`npx @doubao-apps/ai skills add doubao-apps-dev --agent codex`
11
+ - [ ] 梳理 `App.vue`、`main.js`、`pages.json`、`manifest.json`
12
+ - [ ] 梳理所有 `.vue` 页面与组件
13
+ - [ ] 识别所有 `uni.*` API
14
+ - [ ] 识别所有条件编译块(`#ifdef` / `#ifndef`)
15
+ - [ ] 识别所有平台原生 API 穿透(`wx.*` / `tt.*` / `my.*` / `swan.*`)
16
+
17
+ ---
18
+
19
+ ## 依赖与入口处理
20
+
21
+ - [ ] 移除 Vue / uni-app 运行时依赖
22
+ - [ ] 添加 `@doubao-apps/framework`
23
+ - [ ] `main.js` 入口迁到 `src/app.ts`
24
+ - [ ] `App.vue` 生命周期迁到 `defineApp`
25
+ - [ ] `pages.json` 配置逐项重建
26
+
27
+ ---
28
+
29
+ ## 逐文件迁移清单
30
+
31
+ 对每个 `.vue` 文件,执行以下步骤:
32
+
33
+ ### 1. 文件拆分
34
+
35
+ - [ ] `<template>` → `index.tsx`
36
+ - [ ] `<script>` → `index.tsx`
37
+ - [ ] `<style>` → `index.scss`
38
+ - [ ] 添加 `import './index.scss'`
39
+
40
+ ### 2. 页面 / 组件定义转换
41
+
42
+ - [ ] 页面 `.vue` → `definePage({ ..., render() { return <PageView /> } })`
43
+ - [ ] 组件 `.vue` → `FC<Props>`
44
+ - [ ] `App.vue` → `defineApp({...})`
45
+
46
+ ### 3. Vue2 Options API 转换
47
+
48
+ - [ ] `data()` → `useState`
49
+ - [ ] `computed` → `useMemo`
50
+ - [ ] `watch` → `useEffect`
51
+ - [ ] `methods` → 普通函数
52
+ - [ ] `props` → `interface Props`
53
+ - [ ] `this.$emit(...)` → `props.onXxx?.(...)`
54
+
55
+ ### 4. 生命周期转换
56
+
57
+ - [ ] `onLoad(options)` → `getViewData()` + `onMounted` / `useEffect`
58
+ - [ ] `onShow / onHide` → 目标页面生命周期
59
+ - [ ] `onReady` → `onMounted` / `useEffect`
60
+ - [ ] `onUnload` → `onDestroy`
61
+ - [ ] `App.vue onShow / onHide` → `onForeground / onBackground`
62
+
63
+ ### 5. 模板转 TSX
64
+
65
+ - [ ] `{{ expression }}` → `{expression}`
66
+ - [ ] `v-if / v-else-if / v-else` → 条件表达式
67
+ - [ ] `v-for` → `.map(...)`
68
+ - [ ] `:prop="expr"` → `prop={expr}`
69
+ - [ ] `@tap` / `@click` → `onClick`
70
+ - [ ] `v-model` → 受控组件
71
+ - [ ] `<template>` / `<block>` → Fragment 或移除
72
+ - [ ] 直接文本内容统一包裹 `<text>`
73
+
74
+ ### 6. 样式迁移
75
+
76
+ - [ ] `<style>` 内容迁到 `index.scss`
77
+ - [ ] `class="xxx"` → `className="xxx"`
78
+ - [ ] 动态 class → 字符串拼接 / 条件 class
79
+ - [ ] 只有动态值才使用 `style={{}}`
80
+ - [ ] `scoped` 样式改成局部 class 组织
81
+
82
+ ### 7. `uni.*` API 替换
83
+
84
+ - [ ] `uni.request(...)` → `request(...)`
85
+ - [ ] `uni.navigateTo / redirectTo / navigateBack / reLaunch` → 改写为对应路由 API
86
+ - [ ] `uni.switchTab` → 重建 tab 导航能力或记录缺口,不假设存在同名 API
87
+ - [ ] `uni.showToast({ title })` → `showToast({ message })`
88
+ - [ ] `uni.showLoading / hideLoading / showModal` → 改为页面内交互方案或记录缺口
89
+ - [ ] `uni.setStorageSync / getStorageSync / removeStorageSync` → 改为对象参数签名
90
+ - [ ] `uni.$on / $emit / $off / $once` → 显式 props / 状态提升 / 容器协调
91
+
92
+ ### 8. 配置与宿主能力
93
+
94
+ - [ ] 重建 `pages.json -> pages`
95
+ - [ ] 评估 `pages.json -> globalStyle`
96
+ - [ ] 重建 `pages.json -> tabBar` 或记录缺口
97
+ - [ ] 重写 `enablePullDownRefresh` 或记录缺口
98
+ - [ ] 将 `navigationBarTitleText` 转到目标页面元信息
99
+ - [ ] 逐项处理条件编译块
100
+
101
+ ### 9. 组件专项处理
102
+
103
+ - [ ] 将 `scroll-view` 的滚动事件改写到目标事件模型
104
+ - [ ] `swiper / swiper-item` 优先保留小写标签
105
+ - [ ] `navigator` → 改成显式路由 API
106
+ - [ ] `picker` 按 `mode` 分流处理,而不是统一按单列弹层重写
107
+ - [ ] 确认 `editor` 是否存在目标等价能力
108
+
109
+ ---
110
+
111
+ ## 验证步骤
112
+
113
+ - [ ] TypeScript 编译无报错:`npx tsc --noEmit`
114
+ - [ ] 构建成功:`pnpm run build`
115
+ - [ ] 页面可正常渲染
116
+ - [ ] 事件触发正常
117
+ - [ ] 状态更新正常
118
+ - [ ] 网络请求正常
119
+ - [ ] 路由跳转正常
120
+ - [ ] 样式结构正确
121
+ - [ ] `pages.json` 相关页面能力已核对
122
+
123
+ ---
124
+
125
+ ## 能力缺口记录
126
+
127
+ | 功能 | 原因 | 处理状态 |
128
+ |------|------|---------|
129
+ | | | |
130
+
131
+ ---
132
+
133
+ ## 迁移报告模板
134
+
135
+ ```text
136
+ 迁移完成时间:YYYY-MM-DD
137
+ 迁移文件数量:____ 个(页面 ____ + 组件 ____)
138
+ 完成率:____/____(____%)
139
+
140
+ 未完成项:
141
+ - [文件] [原因]
142
+
143
+ 能力缺口:
144
+ - [能力名称] × [调用次数]:[处理建议]
145
+ ```
@@ -0,0 +1,157 @@
1
+ # Component Mapping
2
+
3
+ > **Mapping Version**: 1.0.0
4
+ > **Source Framework**: uni-app `2.0.0`
5
+ > **Target Framework**: Doubao Apps (React Lynx)
6
+ > **Last Updated**: 2026-04-09
7
+
8
+ ## 当前项目组件现状
9
+
10
+ 基于 `packages/components/src`、`packages/framework/jsx-runtime.d.ts` 与 `packages/kit/src/builder/loader/components-loader/index.ts`,当前工程已支持以下小写标签直接写入 TSX:
11
+
12
+ - 基础标签:`<view>`、`<text>`、`<image>`、`<input>`、`<textarea>`、`<scroll-view>`、`<list>`、`<list-item>`、`<svg>`
13
+ - 扩展标签:`<button>`、`<switch>`、`<slider>`、`<swiper>`、`<swiper-item>`、`<map>`、`<map-marker>`、`<movable-area>`、`<movable-view>`、`<popup>`、`<radio>`、`<radio-group>`、`<picker-view>`、`<picker-column>`、`<web-view>`
14
+
15
+ 迁移 uni-app 时,能保留这些小写标签就优先保留;需要显式 ref、类型或更高层封装时,再使用命名导入。
16
+
17
+ - 大部分标签会由 loader 自动补 `@doubao-apps/framework/components` 导入
18
+ - `list-item` 当前主要由 JSX intrinsic / Lynx 原生标签能力提供,不要假设 loader 会自动补组件 import
19
+
20
+ ---
21
+
22
+ ## 文件结构转换
23
+
24
+ uni-app 页面 / 组件通常是单个 `.vue` 文件,迁移后统一收敛为 `index.tsx` + `index.scss`:
25
+
26
+ | uni-app 2.0.0 | Doubao Apps | 内容 |
27
+ |--------------|-------------|------|
28
+ | `<template>` | `index.tsx` | 模板结构 |
29
+ | `<script>` | `index.tsx` | 逻辑 |
30
+ | `<style>` | `index.scss` | 样式 |
31
+
32
+ ---
33
+
34
+ ## 模板语法映射
35
+
36
+ | uni-app 2.0.0 | Doubao Apps | 说明 |
37
+ |--------------|-------------|------|
38
+ | `{{ expr }}` | `{expr}` | 文本插值 |
39
+ | `v-if="cond"` | `{cond && ...}` | 条件渲染 |
40
+ | `v-else-if` / `v-else` | 三元表达式 | 条件分支 |
41
+ | `v-for="item in list"` | `list.map(...)` | 列表渲染 |
42
+ | `:key="item.id"` | `key={item.id}` | 列表键 |
43
+ | `:prop="expr"` | `prop={expr}` | 动态属性 |
44
+ | `@tap="handleTap"` | `onClick={handleTap}` | 事件绑定 |
45
+ | `<template>` / `<block>` | `<>...</>` | 结构块 |
46
+
47
+ ### 示例
48
+
49
+ ```tsx
50
+ // Before (uni-app 2.0.0)
51
+ <view class="list">
52
+ <view v-for="item in list" :key="item.id" class="item" @tap="handleTap(item)">
53
+ <text>{{ item.title }}</text>
54
+ </view>
55
+ </view>
56
+
57
+ // After (Doubao Apps)
58
+ <view className="list">
59
+ {list.map((item) => (
60
+ <view key={item.id} className="item" onClick={() => handleTap(item)}>
61
+ <text>{item.title}</text>
62
+ </view>
63
+ ))}
64
+ </view>
65
+ ```
66
+
67
+ ---
68
+
69
+ ## 页面容器
70
+
71
+ | uni-app 2.0.0 | Doubao Apps | 说明 |
72
+ |--------------|-------------|------|
73
+ | `<view>` | `<view>` | 通用容器 |
74
+ | `<scroll-view scroll-y>` | `<scroll-view>` | 垂直滚动容器 |
75
+ | `<scroll-view scroll-x>` | `<scroll-view>` | 水平滚动容器,属性按目标组件改写 |
76
+ | `<swiper>` / `<swiper-item>` | `<swiper>` / `<swiper-item>` | 优先保留 |
77
+
78
+ ---
79
+
80
+ ## 文本与媒体
81
+
82
+ | uni-app 2.0.0 | Doubao Apps | 说明 |
83
+ |--------------|-------------|------|
84
+ | `<text>` | `<text>` | 文本组件 |
85
+ | 直接文本节点 | `<text>` 包裹 | 统一文本容器语义 |
86
+ | `<image>` | `<image>` | 图片组件 |
87
+ | `<video>` | `<video>` 或等价组件 | 纯播放可迁 |
88
+ | `<web-view>` | `<web-view>` | 需补宿主校验 |
89
+ | `<editor>` | 需专项确认 | `2.0.0` 新增,不能默认可迁 |
90
+
91
+ ---
92
+
93
+ ## 表单组件
94
+
95
+ | uni-app 2.0.0 | Doubao Apps | 说明 |
96
+ |--------------|-------------|------|
97
+ | `<button>` | `<button>` | 直接保留 |
98
+ | `<input>` | `<input>` | 受控写法 |
99
+ | `<textarea>` | `<textarea>` | 受控写法 |
100
+ | `<switch>` | `<switch>` | 布尔回调 |
101
+ | `<slider>` | `<slider>` | 数值回调 |
102
+ | `<picker mode="selector">` | `<popup>` + `<picker-view>` / `<picker-column>`,或宿主等价选择器 | 普通单列选择可这样重写 |
103
+ | `<picker mode="multiSelector">` | `<popup>` + 多列 `<picker-column>` | 需要按列重建 |
104
+ | `<picker mode="time" / "date" / "region">` | 优先查目标宿主是否有等价能力;无则记录缺口或以业务可接受方式重构 | 不要一律降级成普通滚轮选择器 |
105
+ | `<picker-view>` | `<picker-view>` + `<picker-column>` | 优先保留 |
106
+ | `<radio-group>` | `<radio-group>` + `<radio>` | 优先保留 |
107
+
108
+ ---
109
+
110
+ ## 导航组件
111
+
112
+ | uni-app 2.0.0 | Doubao Apps | 说明 |
113
+ |--------------|-------------|------|
114
+ | `<navigator :url="...">` | `onClick={() => navigateTo({ url })}` | 显式路由 |
115
+
116
+ ```tsx
117
+ // Before
118
+ <navigator :url="`/pages/detail/index?id=${item.id}`">
119
+ <view class="link">查看详情</view>
120
+ </navigator>
121
+
122
+ // After
123
+ import { navigateTo } from '@doubao-apps/framework/api';
124
+
125
+ <view className="link" onClick={() => navigateTo({ url: `/pages/detail/index?id=${item.id}` })}>
126
+ <text>查看详情</text>
127
+ </view>
128
+ ```
129
+
130
+ ---
131
+
132
+ ## `v-model` 规则
133
+
134
+ `v-model` 不应机械迁移。统一改成受控组件:
135
+
136
+ ```tsx
137
+ // Before
138
+ <input v-model="keyword" />
139
+
140
+ // After
141
+ <input
142
+ value={keyword}
143
+ onInput={(e) => setKeyword(e.detail.value)}
144
+ />
145
+ ```
146
+
147
+ ---
148
+
149
+ ## 条件编译里的组件
150
+
151
+ 以下组件若出现在条件编译块中,不要直接平移:
152
+
153
+ - 平台原生组件
154
+ - 只在某个小程序宿主存在的开放组件
155
+ - 依赖平台审核能力、登录态、订阅消息或分享链路的组件
156
+
157
+ 这些应在迁移计划中单列。