14 KiB
14 KiB
Web 转小程序 - 完整流程提示词
用法:在对话中 @ 本文件(
scripts/Web转小程序并上传-提示词.md),请 AI 按本提示词执行:先枚举要转换的页面 → 按规则 100% 转为小程序 → 自检清单逐项通过 → 可选打开微信开发者工具。
一、你的任务(当被 @ 本文件时)
按顺序执行:
- 枚举页面:扫描
app/下所有**/page.tsx(排除app/api/、app/admin/),得到需上小程序的页面列表及对应小程序路径(见二)。 - 转换:将上述每个 Web 页面完整、一致转为小程序代码到
miniprogram/,样式、按钮、布局、交互、图标零丢失(见三、四)。 - 检查:按「六、自检清单」逐项自检,确保可运行且与 Web 逐页对照无遗漏。
- 打开微信开发者工具(可选):若用户未说「仅转换」,则执行
start miniprogram(Windows)或open miniprogram(Mac),或调用微信开发者工具 CLI 打开miniprogram/。
触发约定:用户只说「转换」或「只转」→ 只做 1~3;用户说「完整流程」或仅 @ 本文件 → 做 1~4。
二、项目结构对照(按规则推导,不写死页面)
先扫描 app/ 得到页面列表,再按规则生成小程序路径与四件套;新增 Web 页面时同样适用。
-
Web 路由 → 小程序页面路径
- 通用:
app/<path>/page.tsx→pages/<name>/<name>,<name>取该路由最后一层目录名。 - 特例:
app/page.tsx→pages/index/index。- 动态路由
app/<a>/[id]/page.tsx→pages/<a>/<a>,参数在onLoad(options)中取options.id等。 - 嵌套路由(如
app/my/referral/page.tsx)→ 单层页面pages/referral/referral,避免深层路径。
- 新增:每增加一个需上小程序的
app/xxx/page.tsx,就在miniprogram/pages/下新增pages/xxx/xxx四件套(.js/.json/.wxml/.wxss),并在app.json的pages中追加"pages/xxx/xxx"。
- 通用:
-
枚举要转换的页面
- 遍历
app/下所有含page.tsx的路径,排除:app/api/、app/admin/及仅 Web/后台用的路由。 - 对每个需上小程序的页面,按上条得到路径,确保
miniprogram/pages/<name>/存在四件套且已在app.json的pages中注册。
- 遍历
-
API
app/api/*不转为小程序代码;小程序用wx.request调同域名接口(与miniprogram/utils、baseURL 一致),不写死 localhost。接口路径、参数、返回格式与app/api/保持一致。
-
tabBar
- 仅首页、目录、找伙伴、我的等需底部 tab 的页面配置
app.json的tabBar.list;其余为普通页面。新增 tab 时在tabBar.list与pages中同步追加。
- 仅首页、目录、找伙伴、我的等需底部 tab 的页面配置
三、转换规则(Web → 小程序)
原则:以 Web 为唯一真相来源,逐块对照,不猜测、不省略;无法 1:1 处用最接近实现并注释说明。
3.1 完整性要求(零丢失)
- 样式:颜色、字体、字号、行高、间距、圆角、阴影、背景、边框与 Web 一致,在 WXSS 中完整实现。
- 按钮与可点击:每个按钮、链接、可点击区域保留,文案、图标、跳转/弹窗/提交与 Web 一致;禁用态、加载态需体现。
- 布局与结构:区块划分、顺序、折叠/展开、列表/卡片与 Web 一致,不漏模块。
- 图片与图标:Web 中出现的图片、图标、占位图在小程序侧存在并正确引用;菜单、列表、统计、标签、按钮等处图标逐项对照补全(可用 emoji 或图片),路径用
miniprogram/images/或 assets。 - 表单:输入框、选择器、校验、提交与 Web 一致,不丢字段与校验。
3.2 组件与语法
- React/JSX → WXML:
wx:if、wx:for、bindtap等;禁止在 WXML 中写 JS 方法(见 4.1)。 - Tailwind/CSS → WXSS:逐条对照 Web 样式,可保留 class 名,视觉效果一致;主题色/字体与
globals.css或设计一致。 - 状态与生命周期:
useState/useEffect→ Page 的data、onLoad、onShow等。 - 路由:
useRouter/Link→wx.navigateTo、wx.switchTab(tab 页用 switchTab)。 - 接口:
wx.request+ 项目 baseURL;路径、参数、返回与app/api/一致。图片放miniprogram/images/或 assets,引用用相对路径或/images/xxx。
四、踩坑与必做项(必须遵守)
以下为实际转换中的踩坑总结,转换与检查时必须按此处理,否则会出现编译错误、模拟器启动失败或界面被遮挡。
4.1 WXML 禁止在模板里调用 JS 方法
- 禁止:WXML 中不得出现任何 JS 方法调用,例如:
{{ (user.earnings || 0).toFixed(2) }}、{{ user.nickname.charAt(0) }}、{{ user.id.slice(-8) }}、{{ authorInfo.name.charAt(0) }},会报「unexpected token」等编译错误。 - 必须:在对应页的
.js中(onLoad、onShow、syncUser、数据更新处)预先计算展示用字符串,写入data,WXML 只引用 data 变量。推荐命名示例:- 金额两位小数 →
earningsText、balanceText等; - 用户/作者首字 →
userInitial、authorInitial; - 用户 ID 后几位 →
userIdSuffix。
- 金额两位小数 →
4.2 启动不阻塞、不因网络报错导致模拟器启动失败
- 问题:
App.onLaunch里若依赖异步请求(如loadFeatureConfig、loadBookData)且未处理好,或对无返回值的函数链式调用.catch(),会导致「模拟器启动失败 / TypeError: Failed to fetch」或「Cannot read property 'catch' of undefined」。 - 做法:
onLaunch中不要 await 异步请求;只调用loadFeatureConfig().catch(() => {})(仅对返回 Promise 的方法链式 catch),loadBookData()内部已有 catch 则不要写loadBookData().catch()(避免对 undefined 调 catch)。request的fail回调里统一打日志并 reject 友好错误,不把未捕获异常抛到启动流程。- 本地调试可在
project.config.json的setting中设"urlCheck": false,避免域名未配置时请求被拦截;正式发布前再按需改回。
4.3 底部「找伙伴」Tab 默认不显示,避免闪一下再隐藏
- 问题:若 custom-tab-bar 里「找伙伴」初始为
hidden: false,等接口返回matchEnabled: false后再隐藏,会先显示再消失,观感差。 - 做法:custom-tab-bar 的
list里「找伙伴」项默认hidden: true;在attached里先执行一次syncMatchEnabled()(用当前globalData.matchEnabled),再app.loadFeatureConfig().then(() => this.syncMatchEnabled()),仅当接口返回matchEnabled === true时把该项设为hidden: false。
4.4 顶部安全区:状态栏 + 胶囊会遮挡,必须预留
- 问题:
navigationStyle: "custom"时,状态栏和胶囊按钮会覆盖页面顶部,标题、返回、按钮被遮挡或点不到。 - 必须:
- 占位高度:统一使用
navBarHeight(不用固定statusBarHeight + 44)。在App.getSystemInfo中用wx.getSystemInfoSync()+wx.getMenuButtonBoundingClientRect()计算navBarHeight(状态栏 + 胶囊区域总高),无菜单按钮时回退statusBarHeight + 44。每页占位条高度设为{{ navBarHeight }}px,onLoad/onShow从getApp().globalData取navBarHeight、statusBarHeight写入页面data。 - 头部右侧留白:所有带标题/按钮的头部容器加
.safe-header-right(app.wxss中定义padding-right: 200rpx; box-sizing: border-box;),或使用globalData.capsulePaddingRight内联,避免被胶囊遮挡。 - 占位页统一模板:无复杂导航的页面(如
address-edit、address-list、purchases、referral、settings)必须使用同一套顶部安全区:顶部占位条高度navBarHeight,其内padding-top: {{ statusBarHeight || 44 }}px,导航容器使用display: flex; flex-direction: column; justify-content: flex-end; box-sizing: border-box;,并加safe-header-right,保证标题与返回按钮不被遮挡且右侧留白一致。
- 占位高度:统一使用
4.5 图标与样式逐页对照,不得遗漏
- 问题:转换后容易漏掉搜索图标、菜单图标、统计/标签图标、返回箭头等,导致与 Web 不一致。
- 做法:逐页对照 Web(如
components/bottom-nav.tsx、各app/**/page.tsx):- 底部 Tab:每个 tab 有图标(如 🏠📋👥👤 或图片),「找伙伴」若居中凸起需保留样式。
- 首页:搜索栏左侧有搜索图标;Banner/卡片/列表中的箭头、标签与 Web 一致。
- 我的:用户卡片「创业伙伴」旁有星标;收益卡片有收益图标;菜单项(订单、推广、关于、设置)各有图标;概览/我的足迹 Tab 及阅读统计、最近阅读、匹配记录等区块有对应图标或标题图标。
- 关于:作者首字用 data 中的
authorInitial;标签(直播时间、平台)带图标;统计四项带图标;「加入派对群」按钮带图标;返回为「← 返回」。 - 阅读/搜索/目录/找伙伴:返回、分享、锁、类型图标等与 Web 一致。所有导航返回统一用「← 返回」等可识别样式。
4.6 卡片与按钮布局错位(如「我的收益」与「推广中心」按钮)
- 问题:卡片内标题行(如「我的收益」+「推广中心 ›」)与底部全宽按钮(如「推广中心 / 提现」)出现错位、溢出或与卡片边缘不对齐,与 Web 不一致。
- 做法:
- 盒子模型:页面根容器与所有卡片统一加
box-sizing: border-box,避免 padding 导致总宽度超出或视觉偏移。 - 卡片内标题行:若为 flex 布局(如左侧标题 + 右侧链接),给容器加
gap、min-width: 0;左侧标题区加flex-shrink: 0、min-width: 0,标题与链接加white-space: nowrap,右侧链接加flex-shrink: 0、white-space: nowrap,防止挤压、换行或重叠错位。 - 全宽按钮:卡片内的「全宽」按钮使用
display: block、width: 100%、box-sizing: border-box,保证与卡片内容区同宽、与上方内容左右对齐;不得因缺 box-sizing 或未 block 导致宽度计算错误而错位。
- 盒子模型:页面根容器与所有卡片统一加
4.7 「我的」-「我的足迹」-「匹配记录」需随 matchEnabled 控制
- 要求:与 Web 一致,当全局配置
matchEnabled === false时,「我的」页「我的足迹」Tab 下的「匹配记录」区块不展示;仅当matchEnabled === true时展示。小程序侧从getApp().globalData.matchEnabled读取,在 WXML 中用wx:if="{{ matchEnabled }}"控制该区块显隐,并在onShow或数据刷新时同步该值到页面data。
五、必须保留的小程序配置
- AppID:
wxb8bbb2b10dec74aa(见miniprogram/project.config.json、.cursorrules)。 - app.json:
pages、window、tabBar(含custom: true时保留custom-tab-bar)、permission、requiredPrivateInfos等按现有或微信规范保留。 - project.config.json:保持现有编译与项目配置,不随意改 appid;本地调试可设
urlCheck: false,见 4.2。 - custom-tab-bar:若使用自定义 tabBar,保留
custom-tab-bar组件实现,并遵守 4.3 的「找伙伴」默认隐藏规则。
六、转换完成后的自检清单
- 页面注册:
app.json的pages与miniprogram/pages/下目录、四件套一一对应,无缺页。 - 组件引用:各页
.json的usingComponents与自定义组件路径正确(若有)。 - WXML 合规:无语法错误;WXML 中无
.toFixed()、.charAt()、.slice()等 JS 方法,展示用数值/字符串均已预先写入 data 并在模板中引用。 - 接口:baseURL 为线上或配置项,非 localhost(仅本地调试可例外)。
- tabBar:与 Web 一级入口一致;「找伙伴」项默认
hidden: true,仅当接口返回matchEnabled === true后显示(见 4.3)。 - 顶部安全区:所有自定义头部页使用
navBarHeight占位,头部容器加safe-header-right;占位页(address-edit、address-list、purchases、referral、settings)使用统一顶部安全区模板(见 4.4)。 - 卡片与按钮:含标题行+链接+全宽按钮的卡片使用
box-sizing: border-box,标题行防挤压/换行,全宽按钮display: block、width: 100%、box-sizing: border-box,与内容区左右对齐无错位(见 4.6)。 - 「我的足迹」-「匹配记录」:该区块随
globalData.matchEnabled显隐,matchEnabled === false时不展示(见 4.7)。 - 完整性:逐页对照 Web,样式、按钮、链接、图片、图标、表单、列表/卡片无遗漏;无法 1:1 处已用最接近实现并注释说明。
七、转换完成后的步骤
转换完成后,打开微信开发者工具:
- 方式一:执行
start miniprogram(Windows)或open miniprogram(Mac)打开文件夹,将miniprogram文件夹拖入微信开发者工具导入项目。 - 方式二:若已安装微信开发者工具 CLI,可直接调用其打开项目(如 Windows:
"C:\Program Files (x86)\Tencent\微信web开发者工具\cli.bat" open --project miniprogram)。
在微信开发者工具中可预览、调试;需要上传时,使用工具内的「上传」功能,或执行 python scripts/autosysc-weixin.py。
八、参考文件位置
- Web 对照:
app/**/page.tsx、components/;接口路径、参数、返回格式参照app/api/,保证与 Web 一致。 - 小程序结构:
miniprogram/app.json、miniprogram/pages/、miniprogram/utils/、miniprogram/custom-tab-bar/、miniprogram/app.js。 - 上传:
scripts/autosysc-weixin.py(项目根运行,需先配置miniprogram/private.key)。 - 配置说明:
miniprogram/小程序快速配置指南.md、miniprogram/小程序部署说明.md。
当你被 @ 本文件时:按「一、你的任务」顺序执行(枚举页面 → 转换 → 自检 → 可选打开开发者工具),并严格遵循二(结构对照)、三(转换规则)、四(踩坑必做项)、五(配置保留)、六(自检清单);四、六中的条目为必做项,不可省略。