بنقرة واحدة
html-to-miniprogram
将 HTML/React/Vue 等前端 Demo 页面转换为微信小程序原生开发项目。重点是转换前端页面和简单交互(页面跳转、提醒等),不涉及业务逻辑,数据集中在 mock.js 中管理。
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
القائمة
将 HTML/React/Vue 等前端 Demo 页面转换为微信小程序原生开发项目。重点是转换前端页面和简单交互(页面跳转、提醒等),不涉及业务逻辑,数据集中在 mock.js 中管理。
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
استنادا إلى تصنيف SOC المهني
前端 API 治理工作站:从项目中的真实 API 调用扫描接口,生成结构化契约(contract.json)、MSW Mock、标准接口文档(Markdown + OpenAPI 3.1 YAML),并执行一致性校验与变更追踪。
自动生成计算机软件著作权申请资料
静态页面 API 化改造工具:自动发现页面中的隐式数据接口需求,改造页面为标准 API 调用并预留 Mock/真实接口切换层。不负责 contract/mock/docs 产物生成。
| name | html-to-miniprogram |
| description | 将 HTML/React/Vue 等前端 Demo 页面转换为微信小程序原生开发项目。重点是转换前端页面和简单交互(页面跳转、提醒等),不涉及业务逻辑,数据集中在 mock.js 中管理。 |
将任意前端 Demo(HTML/React/Vue 单文件或多文件)转换为微信小程序原生开发项目,精准还原 UI 和简单交互。
[!IMPORTANT] 转换范围:仅转换前端页面 UI 和简单交互(页面跳转、Tab 切换、Toast 提醒、弹窗等),不实现业务逻辑(如网络请求、用户认证、数据持久化等)。所有页面用到的数据统一整合在
utils/mock.js中管理。
[!IMPORTANT] 交互语言:与用户的所有对话、确认、提问、说明必须使用中文。包括但不限于:任务描述、设计决策询问、进度汇报、问题反馈等。代码中的变量名、文件路径等技术标识符保留英文。
[!CAUTION] 连续执行:用户确认设计决策(阶段 1)后,阶段 2 ~ 5(生成蓝图、初始化骨架、逐页转换、验证)必须一口气连续完成,中间不得暂停等待用户确认。不要在完成几个页面后就停下来汇报进度或请求继续——所有页面必须连续完成后再进入验证阶段。只有在遇到无法自主决策的问题时才暂停询问用户。
通读 Demo 源码,提取以下信息:
[!CAUTION] 页面提取是最关键的步骤,遗漏页面会导致最终产物缺页。 必须通过以下方式交叉验证,确保不遗漏任何页面:
- 路由配置:检查 Router 配置、hash 路由、Tab 定义等,提取所有注册的路由
- 导航链接:搜索源码中所有
href、to、router.push、navigate等跳转目标- JS 事件跳转:搜索
onClick、handleClick等事件处理函数中的页面跳转逻辑- 条件渲染的视图:检查
v-if、v-show、{condition && <Component>}等条件渲染,识别隐藏的子视图/页面- HTML 页面结构:如果是单 HTML 文件,搜索所有
section/div中通过 CSSdisplay:none或 JS 切换显示的独立视图分析完成后,必须明确告知用户总页面数(如"共发现 13 个页面:4 个 TabBar 页面 + 9 个子页面"),让用户确认是否有遗漏。
在生成蓝图之前,必须先与用户确认以下设计决策:
[!CAUTION] 以下决策直接影响蓝图内容和后续实现方式,必须在蓝图创建前完成确认,避免蓝图与实际执行脱节。
页面完整性确认模板(必须原样输出结构):
已识别页面总数:N(TabBar: X,子页面: Y)
TabBar 页面:
- pages/xxx/xxx
- pages/xxx/xxx
子页面:
- pages/xxx/xxx
- pages/xxx/xxx
疑似遗漏页面(若无则写“无”):
- ...
根据阶段 1 的分析结果和用户确认的设计决策,创建转换蓝图文件 conversion-blueprint.md,置于项目根目录。
[!IMPORTANT] 蓝图是整个转换过程的单一事实来源。蓝图内容必须与用户确认的设计决策一致。
蓝图包含以下内容:
# [项目名] 转换蓝图
## 一、页面清单
| 序号 | 页面名称 | 路径 | 类型 |
|------|---------|------|------|
| 1 | 首页 | pages/home/home | TabBar |
| 2 | 详情页 | pages/detail/detail | 子页面 |
| ... | ... | ... | ... |
## 二、路由结构
- TabBar 页面:[列表]
- 子页面:[列表]
- 页面间跳转关系:[描述]
## 三、组件层级
- 全局组件:[列表]
- 页面私有组件:[列表]
## 四、样式体系
- CSS 变量/设计 Token:[列出关键变量]
- 色板:[主色、辅色、背景色等]
- 字体:[字号体系]
## 五、图标方案:[Emoji / PNG]
<!-- 根据用户选择的方案填写不同内容 -->
### 如果选择 Emoji 方案:
| 原图标名称 | Emoji 字符 | 使用位置 |
|-----------|-----------|--------|
| chevron-left | ‹ | 所有子页面返回按钮 |
| home | 🏠 | TabBar-首页 |
| ... | ... | ... |
### 如果选择 PNG 方案:
| 图标名称 | 颜色 (Hex) | 文件名 | 使用位置 |
|---------|-----------|--------|--------|
| house | #94a3b8 | house.png | TabBar |
| ... | ... | ... | ... |
## 六、交互逻辑
| 交互类型 | 描述 | 所在页面 |
|---------|------|--------|
| Tab 切换 | 底部 TabBar 导航 | 全局 |
| 页面跳转 | 点击卡片进入详情 | 首页 |
| Toast 提醒 | 点击按钮弹出提醒 | ... |
| ... | ... | ... |
## 七、Mock 数据结构
- [列出每个页面需要的 Mock 数据字段和结构]
[!IMPORTANT] 小程序项目必须生成在一个单独的
miniprogram文件夹中,与源 Demo 文件分离,避免混淆。
按以下顺序创建文件:
miniprogram/
├── app.js # 全局入口
├── app.json # 页面注册 + TabBar + window 配置
├── app.wxss # 全局样式(CSS 变量 + 工具类)
├── project.config.json
├── sitemap.json
├── custom-tab-bar/ # 如需自定义 TabBar
│ ├── index.js / index.json / index.wxml / index.wxss
├── assets/
│ └── icons/ # 图标资源
├── utils/
│ ├── mock.js # 所有 Mock 数据集中管理
│ └── util.js # 工具函数
└── pages/ # 每个页面 4 个文件
├── page-name/
│ ├── page-name.js
│ ├── page-name.json
│ ├── page-name.wxml
│ └── page-name.wxss
[!IMPORTANT]
project.config.json必须配置"miniprogramRoot": "miniprogram/",确保微信开发者工具正确识别源码目录。
utils/mock.js 引入wx.navigateTo / wx.switchTab,提醒用 wx.showToast / wx.showModal)wx.showToast({ title: '功能开发中', icon: 'none' }) 占位单个页面的转换步骤:
.json(配置):设置页面标题、导航栏样式、引用的自定义组件等(组件声明是后续 WXML 中使用自定义组件的前提).wxml(结构):对照 Demo 源码逐元素转换,按标签映射表替换标签.wxss(样式):迁移对应 CSS,按样式转换规则处理单位、选择器和布局.js(数据 + 交互):从 mock.js 引入数据,在 onLoad 中 setData,绑定简单交互事件按照蓝图文件进行逐步验证(详见 第七节 验证流程)。
| HTML / React | 微信小程序 | 说明 |
|---|---|---|
<div> | <view> | 通用容器 |
<span> / <p> | <text> | 文本必须包在 text 中 |
<img> | <image> | 必须设宽高;常用 mode:aspectFill(裁剪填充)、aspectFit(完整显示)、widthFix(宽度固定高度自适应)、scaleToFill(默认拉伸) |
<input> | <input> | 保留,但事件名不同 |
<textarea> | <textarea> | 原生组件,层级最高 |
<button> | <button> / <view> | 视需求选择 |
<a href> | <navigator> / 事件 | 小程序无 a 标签 |
<ul> / <li> | <view> + wx:for | 列表渲染 |
<svg> | ❌ 不支持 | 用 image 替代(见图标方案) |
<select> | <picker> | 选择器组件 |
<form> | <form> | 保留,事件名变化 |
<scroll-view> | <scroll-view> | 必须设固定高度才能滚动 |
| 轮播图(JS 库) | <swiper> + <swiper-item> | 内置轮播组件,支持自动播放和循环 |
<video> | <video> | 原生组件,需用 cover-view 覆盖 |
<audio> | <audio> / wx.createInnerAudioContext | 推荐用 API 方式 |
<input type="radio"> | <radio-group> + <radio> | 单选框 |
<input type="checkbox"> | <checkbox-group> + <checkbox> | 多选框 |
| toggle / switch | <switch> | 开关组件 |
<input type="range"> | <slider> | 滑块组件 |
| 富文本 HTML 内容 | <rich-text nodes="{{html}}"> | 支持部分 HTML 标签渲染 |
| 覆盖原生组件的浮层 | <cover-view> / <cover-image> | 用于覆盖 video 等原生组件 |
| Web 事件 | 小程序事件 | 说明 |
|---|---|---|
onClick | bindtap | 点击事件(冒泡) |
onClick(阻止冒泡) | catchtap | 点击事件(阻止冒泡) |
| 长按 | bindlongpress | 超过 350ms 触发,推荐代替 longtap |
onTouchStart | bindtouchstart | 手指触摸开始 |
onTouchMove | bindtouchmove | 手指触摸后移动 |
onTouchEnd | bindtouchend | 手指触摸结束 |
onChange(input) | bindinput | 输入框内容变化 |
onChange(picker/switch) | bindchange | picker、switch、slider 等值变化 |
onFocus | bindfocus | 输入框获取焦点 |
onBlur | bindblur | 输入框失去焦点 |
onSubmit | bindsubmit | 表单提交 |
onScroll | bindscroll | 滚动事件(scroll-view) |
onLoad(img) | bindload | 图片/视频加载成功 |
onError(img) | binderror | 图片/视频加载失败 |
属性映射(非事件,但转换时同样重要):
| Web 属性 | 小程序属性 | 说明 |
|---|---|---|
className | class | 类名属性 |
style={{}} | style="" | 内联样式(字符串格式) |
dangerouslySetInnerHTML | <rich-text nodes> | 富文本渲染 |
hidden / v-show | hidden="{{bool}}" | 控制显隐(不销毁节点,比 wx:if 性能更好适合频繁切换) |
data-* | data-* | 自定义数据属性,通过 e.currentTarget.dataset 获取 |
[!TIP] 事件冒泡机制:
bind前缀允许事件冒泡,catch前缀阻止冒泡。需要阻止父元素响应事件时用catch(如弹窗遮罩的点击穿透问题)。
核心规则:
px → rpx(1px = 2rpx),除以下情况保留 px:
border:细边框保留 1px(避免在高分屏上过粗),粗边框正常按 1px=2rpx 换算font-size 可酌情使用 rpx 或 px.class {})#id {})>)、兄弟选择器(~、+):active、:first-child、:last-child、:not、:nth-child::before、::after(仅这两个)div {}, span {})* 通配符选择器[attr]、[type="text"])float:支持但在 Flex 容器内失效,推荐用 Flex 布局替代display: inline-block:行为可能与 Web 不完全一致,推荐用 Flex 布局替代position: fixed:支持,但父元素有 transform 时会失效;仅支持相对视口定位overflow: scroll:支持不稳定且受渲染引擎影响,推荐使用 <scroll-view> 组件实现可靠滚动display: flex 全系列(推荐首选布局方式)display: grid / grid-template-columnsbackdrop-filter: blur()linear-gradient()box-shadowvar(--xxx)(在 page {} 中定义,非 :root)border-radiusposition: sticky@import 导入外部样式表app.wxss 的 page {} 选择器中flex, grid, gap, rounded 等转为对应属性hover: 伪类可用 .active 类 + bindtouchstart/end 模拟,或省略app.wxss 的 page {} 中(不是 :root)app.wxss.wxss 文件中| Web 路由方式 | 小程序对应 |
|---|---|
| React Router / hash 路由 | app.json 的 pages 注册 |
| Tab 切换 | wx.switchTab({ url }) |
| 页面跳转 | wx.navigateTo({ url }) |
| 页面重定向(替换当前页) | wx.redirectTo({ url }) |
| 返回上一页 | wx.navigateBack() |
| 参数传递(query string) | options 参数 / globalData |
路由类型判断:
switchTab,不能用 navigateTo[!WARNING] 页面栈限制:小程序页面栈最多 10 层,超过后
navigateTo会失败。深层级跳转考虑用redirectTo(替换当前页,不增加栈)。
| Web 概念 | 小程序对应 |
|---|---|
useState / data() | Page({ data: {} }) |
setState / 赋值 | this.setData({ key: value }) |
useEffect / mounted | onLoad() / onShow() |
props | 组件的 properties |
context / provide | getApp().globalData |
fetch / axios | Mock 数据直接引入(不实现真实请求) |
localStorage | wx.setStorageSync() / getStorageSync() |
条件渲染 {cond && <X/>} | wx:if="{{cond}}" |
列表渲染 .map() | wx:for="{{list}}" wx:key="id" |
| 模板字符串 | {{}} 数据绑定 |
[!TIP]
wx:key用法:值为列表项的属性名字符串(不加item.前缀),如wx:key="id"。如果列表项本身是唯一字符串/数字,可用wx:key="*this"。不设wx:key会触发警告且影响渲染性能。
Mock 数据策略:
[!NOTE] 所有页面数据统一在
utils/mock.js中定义和导出,页面 JS 通过const mock = require('../../utils/mock.js')引入,在onLoad中setData。不实现wx.request等网络请求。
微信小程序不支持 SVG 标签,需要替换方案。图标方案应在阶段 1 中与用户确认,蓝图内容根据用户选择适配。
使用 Emoji 字符代替图标,无需额外资源文件,适合快速验证布局。
实施规范:
全局样式:在 app.wxss 中定义通用 Emoji 图标类:
/* Emoji 图标通用样式 */
.emoji-icon {
display: inline-flex;
align-items: center;
justify-content: center;
text-align: center;
line-height: 1;
}
WXML 写法:使用 <text> 标签包裹 Emoji,同时添加 emoji-icon 基础类和具体图标类:
<!-- 返回按钮(使用 Unicode 字符) -->
<text class="emoji-icon back-icon">‹</text>
<!-- 普通 Emoji 图标 -->
<text class="emoji-icon phone-icon">📞</text>
<!-- 右箭头 -->
<text class="emoji-icon arrow-icon">›</text>
WXSS 规则:图标样式使用 font-size 控制大小(不是 width/height):
/* ✅ 正确:用 font-size 控制 Emoji 大小 */
.back-icon {
font-size: 56rpx;
color: var(--slate-800);
}
/* ❌ 错误:width/height 对文本无效 */
.back-icon {
width: 52rpx;
height: 52rpx;
}
常用 Emoji 映射参考:
| 原图标用途 | 推荐 Emoji / 字符 | 说明 |
|---|---|---|
| 返回按钮 | ‹(U+2039) | Unicode 单左尖括号,比 < 更美观 |
| 右箭头 | ›(U+203A) | Unicode 单右尖括号 |
| 首页 | 🏠 | |
| 搜索 | 🔍 | |
| 用户/头像 | 👤 | |
| 设置 | ⚙️ | |
| 电话 | 📞 | |
| 编辑 | ✏️ | |
| 删除 | 🗑️ | |
| 添加 | ➕ | |
| 已认证/通过 | ✅ | |
| 禁止/下架 | 🚫 | |
| 文档 | 📄 | |
| 日历 | 📅 | |
| 位置 | 📍 | |
| 图表 | 📊 |
[!TIP] 蓝图中应包含完整的图标名称 → Emoji 字符映射表,确保全项目一致性。
如果用户选择精准视觉还原,使用以下工具将 SVG 图标转换为 PNG:
工具 1:Shell 脚本方式(generate_icons.sh)
从 Lucide 等图标库下载 SVG,替换颜色后用 sips 转为 PNG:
#!/bin/bash
set -euo pipefail
# 定义图标数组,格式:"图标名:颜色:文件名"
ICONS=(
"house:#94a3b8:house.png"
"house:#ffffff:house-active.png"
# ... 按蓝图中的图标清单填写
)
mkdir -p miniprogram/assets/icons
for item in "${ICONS[@]}"; do
IFS=':' read -r name color filename <<< "$item"
if ! curl -s -L -f "https://unpkg.com/lucide-static@latest/icons/$name.svg" -o temp.svg; then
echo "下载失败: $name" >&2
continue
fi
sed "s/currentColor/$color/g" temp.svg > colored.svg
sips -s format png colored.svg --out "miniprogram/assets/icons/$filename" -z 64 64 > /dev/null
rm temp.svg colored.svg
done
[!NOTE] 上述脚本依赖
sips(macOS)。非 macOS 环境可改用magick colored.svg "miniprogram/assets/icons/$filename"生成 PNG。
工具 2:HTML 页面方式(icon_generator.html)
在浏览器中用 Lucide JS 库渲染 SVG 到 Canvas,导出 PNG 的 base64 数据:
const ICONS_TO_GENERATE = [
{ name: 'house', color: '#94a3b8', filename: 'house.png' },
// ... 按蓝图中的图标清单填写
];
// 通过 Canvas 绘制 SVG 并导出 base64 PNG
[!TIP] 两种工具可按需在项目的
tools/目录下创建,根据蓝图中的图标清单填充具体的图标列表。
当 Demo 的 TabBar 不是标准样式时(如浮动胶囊、异形底栏),需使用自定义 TabBar:
app.json 中设置 "tabBar": { "custom": true, ... }
在项目根目录创建 custom-tab-bar/ 组件(固定路径名)
每个 TabBar 页面的 onShow 中更新选中态:
onShow() {
if (typeof this.getTabBar === 'function' && this.getTabBar()) {
this.getTabBar().setData({ selected: 0 }) // 当前页索引
}
}
注意:即使 custom: true,app.json 的 tabBar.list 仍需完整配置(框架要求)
当页面需要自定义顶部导航栏(渐变背景、大标题等):
页面 JSON 设置 "navigationStyle": "custom"
app.js 的 onLaunch 中获取系统信息:
const systemInfo = wx.getWindowInfo()
this.globalData.statusBarHeight = systemInfo.statusBarHeight
const menuButton = wx.getMenuButtonBoundingClientRect()
this.globalData.navBarHeight = (menuButton.top - systemInfo.statusBarHeight) * 2 + menuButton.height
页面顶部避让状态栏时,使用数据绑定到 style(不要把 {{}} 写进 .wxss):
<view class="nav-wrap" style="padding-top: {{statusBarHeight}}px;">
...
</view>
const app = getApp()
Page({
data: { statusBarHeight: 0 },
onLoad() {
this.setData({ statusBarHeight: app.globalData.statusBarHeight || 0 })
}
})
所有页面数据集中在 utils/mock.js 中管理:
// utils/mock.js
// 首页数据
const homeData = {
banners: [ /* ... */ ],
categories: [ /* ... */ ],
hotItems: [ /* ... */ ],
};
// 其他页面数据...
const profileData = { /* ... */ };
module.exports = {
homeData,
profileData,
// ...
};
页面中引用方式:
// pages/home/home.js
const mock = require('../../utils/mock.js')
Page({
data: {},
onLoad() {
this.setData(mock.homeData)
},
// 简单交互
onItemTap(e) {
const id = e.currentTarget.dataset.id
wx.navigateTo({ url: `/pages/detail/detail?id=${id}` })
},
onButtonTap() {
wx.showToast({ title: '功能开发中', icon: 'none' })
}
})
<text> 中,裸文本在某些场景样式不生效wx:for 的默认变量是 item 和 index,可通过 wx:for-item / wx:for-index 重命名image 组件必须设宽高,否则默认 320×240scroll-view 必须设固定高度才能触发滚动pages/home/home.jstextarea 是原生组件,层级最高,样式覆盖需注意this.animate() 或 WXS 响应事件(wx.createAnimation() 已不推荐使用)bindinput + setDatasetData 性能:单次 setData 数据量不宜过大,避免传入整个大对象;尽量只更新变化的字段wx:if vs hidden:wx:if 会销毁/重建节点,hidden 仅控制显隐不销毁。频繁切换时用 hidden 性能更好onLoad vs onShow:onLoad 仅在页面首次加载时执行一次,onShow 每次页面显示都执行(TabBar 页面切换回来时也会触发 onShow)完成所有页面转换后,结合蓝图文件 conversion-blueprint.md 进行逐项验证:
逐一核对蓝图中的页面清单,确认:
app.json 中页面注册是否完整核对蓝图中的路由结构,确认:
switchTab)navigateTo)navigateBack)核对蓝图中的样式体系,确认:
核对蓝图中的图标清单,根据所选方案进行验证:
Emoji 方案验证项:
app.wxss 中已定义 .emoji-icon 全局样式<image> 标签已替换为 <text class="emoji-icon ..."> 标签(非图标的图片如 banner、头像等仍使用 <image>)font-size(非 width/height)PNG 方案验证项:
assets/icons/核对蓝图中的交互逻辑,确认:
核对蓝图中的 Mock 数据结构,确认:
utils/mock.js 包含所有页面的数据[!TIP] 验证过程中每完成一项,仅在
conversion-blueprint.md的验证清单中标记[x]。发现问题立即修复后再继续。
转换时按以下优先级推进: