AI出击:真实微信小程序项目–>支付宝小程序【2-框架层变更】

一切从这个微信小程序转换项目开始,本是抱着尝试一下的心态开始使用Trae 来转换结果弄了几个小时感觉很吃力,支付宝小程序上千个编译错误,后面就想着用阿里出品的 Qoder 是不是会对支付宝小程序了解多一些呢?整个转换过程难度适中,最大的开销就是得反复沟通、验证,有些时候需要找到支付宝小程序官方的说明文档地址让AI 参考进行修改。

改造后的效果可以看之前的文章:AI出击:真实微信小程序项目–>支付宝小程序【1-结果汇报

本文内容速读了解

1、复制微信小程序源码,让AI分析后转换成支付宝小程序

2、打开支付宝小程序开发IDE 复制报错信息让AI 逐步解决(尽量不要让AI 写批量操作脚本,否则可能会造成中文乱码,或给文件添加UTF-8 BOM头,导致成百上千的引用错误。这个看个人取舍如果不做批量脚本就需要让AI记录下涉及变更的文件名然后 依次修改,这个十分消耗token)

3、遇到问题除了直接复制错误让解决外,还时常可以提醒AI 这个是支付宝小程序项目,问下是不是因为现在写法是微信小程序写法导致的错误,这样能一定程度纠正AI

4、页面样式问题 先在支付宝小程序开发 IDE 里面复制“页面路径”然后直接告诉AI 这个页面路径存在什么问题,这样AI 会解决的快一点。另外布局有时候说不清除可以截图发给AI 让它修改,它理解能力还行。

5、如果是跟js逻辑、按钮事件有关,可以让它自己打印log以便帮助定位检车,到时候你直接复制打印出的日志给它分析就行。

6、及时让AI 进行项目修复经验总结,这样项目到后面遇到问题解决起来会越来越顺利,当然Qoder也会有自己的记忆

以下正文(内容较长,适合需要了解与AI 沟通交互过程的朋友看)

拿到微信小程序项目后已经有大概的执行思路了: 先变更整体框架确保支付宝小程序能正常运行& 盘点支付宝小程序各个功能页面 (也就是本文内容) ——> 针对微信支付宝差异化的登录、支付等功能进行修复 ——> 改造支付宝小程序UI 布局。

1、项目启动

项目下文件夹xxxx 是一个微信小程序项目,帮我转换为支付宝小程序,注意区别微信小程序及支付宝小程序之间的语法区别以及分包方式、登录方式、支付方式等,不能转化的逻辑需要另行记录成文档

一开始AI 给的脚本有bug修复后,它重新创建了脚本让我手动执行,因为文件太多只能照它说的操作了。

转换完支付宝小程序完全运行不起来,反复改了很多次,然后有的写法确实需要给支付宝小程序官方文档它才能正确修改!

AI 生成的批量替换脚本真是要消息,这种脚本的替换后好像并不会在Qoder里面产生变更记录,我中间怕麻烦执行后很多中文乱码了,然后批量有时候还会出错导致产生更大面积的错误,所以一定记得随时备份代码!

这个支付宝小程序目前还没启动真实后端接口的开发,所以需要复用之前的接口,AI擅自修改就会导致数据获取异常!另外支付宝小程序获取和设置Storage 的方式跟微信也不一样,这个问题也是调试了好一段时间才解决。

反复改不对的,可以给他丢官方的文档,最后让它整理修复经验。

将你的记忆结合本项目下的一些md文档,最终形成一个新的完整包含所有事项的项目md文档

2、启动后改不完的bug

上面一通修复后,支付宝小程序IDE 已经可以运行起来了,但是点击页面具体功能又是问题频出,这就没办法了只能one by one……

项目中有一个用到图形验证码点击校验的地方,一开始怎么都没解决后来让他添加打印日志后跟着步骤就解决了。

3、微信小程序迁移支付宝小程序经验指南

这次的项目转换经验和踩坑修复过程,我也让Qoder帮忙转换成文档了,有需要的直接拿去吧!

# 微信小程序转支付宝小程序 · 前端迁移指南

> 适用范围:已有微信小程序项目迁移至支付宝小程序(前端部分)

---

## 一、文件与命名映射

| 微信 | 支付宝 | 说明 |
|------|--------|------|
| `.wxml` | `.axml` | 模板文件,需重命名并替换指令 |
| `.wxss` | `.acss` | 样式文件,直接重命名 |
| `.js` | `.js` | 逻辑文件,修改 API 调用 |
| `.json` | `.json` | 配置文件,修改字段名 |
| `.wxs` | `.sjs` | 脚本文件,模板内引用方式也变更 |

**注意**:旧扩展名与新扩展名不能共存,转换后删除 `.wxml`/`.wxss`。

---

## 二、模板指令转换(WXML → AXML)

| 功能 | 微信 | 支付宝 |
|------|------|--------|
| 条件渲染 | `wx:if` / `wx:elif` / `wx:else` | `a:if` / `a:elif` / `a:else` |
| 列表渲染 | `wx:for` / `wx:for-item` / `wx:for-index` / `wx:key` | `a:for` / `a:for-item` / `a:for-index` / `a:key` |
| 列表 key(this) | `wx:key="*this"` | `a:key="this"` |
| 模板引用 | `<wxs src="..." module="..." />` | `<import-sjs name="..." from="..." />` |
| SJS 导出 | `module.exports` | `export default` |

**AXML 特殊约束**:`>` 字符必须转义为 `&gt;`,否则编译报错。

```xml
<!-- ❌ 错误 -->
<text>满100>50</text>
<!-- ✅ 正确 -->
<text>满100&gt;50</text>
```

---

## 三、事件绑定转换

| 类型 | 微信 | 支付宝 |
|------|------|--------|
| 普通点击 | `bindtap` / `bind:tap` | `onTap` |
| 阻止冒泡 | `catchtap` | `catchTap`(**T 大写**) |
| 输入 | `bindinput` | `onInput` |
| 改变 | `bindchange` | `onChange` |
| 滚动到底部 | `bindscrolltolower` | `onScrollToLower` |

**关键规则**:
- 支付宝事件名**严格区分大小写**,`catchTap` 正确,`catchtap` 无效。
- 支付宝小程序中 `<button>` 组件对 `onTap`/`catchTap` 支持存在兼容问题,**交互按钮统一改用 `<view>` + `catchTap`**。

```xml
<!-- ❌ 可能无响应 -->
<button catchTap="handler">点击</button>
<!-- ✅ 推荐 -->
<view class="btn" catchTap="handler">点击</view>
```

---

## 四、JS API 转换

| 功能 | 微信 | 支付宝 | 返回值/参数差异 |
|------|------|--------|----------------|
| 网络请求 | `wx.request` | `my.request` | 请求头用 `headers`,响应码用 `status` |
| 登录 | `wx.login` | `my.getAuthCode` | 必须传 `scopes`,返回 `authCode` |
| 支付 | `wx.requestPayment` | `my.tradePay` | 传 `tradeNO` 或 `orderStr` |
| Toast | `wx.showToast` | `my.showToast` | 图标类型:`icon: 'none'` → `type: 'none'` |
| Modal | `wx.showModal` | `my.confirm` | 支付宝不支持 `confirmColor` |
| 扫码 | `wx.scanCode` | `my.scan` | — |
| 获取存储 | `wx.getStorageSync` | `my.getStorageSync` | 支付宝返回 `{data, success}` |
| 设置存储 | `wx.setStorageSync` | `my.setStorageSync` | 支付宝传对象 `{key, data}` |
| 移除存储 | `wx.removeStorageSync` | `my.removeStorageSync` | 支付宝传对象 `{key}` |
| 清除存储 | `wx.clearStorageSync` | `my.clearStorageSync` | 支付宝传对象 `{}` |

**Storage 返回值差异**:

```javascript
// 微信:直接返回值
const value = wx.getStorageSync('key')

// 支付宝:返回对象 {data, success}
const result = my.getStorageSync('key')
const value = result && result.data !== undefined ? result.data : result
```

**removeStorageSync 参数差异(易踩坑)**:

```javascript
// 微信:直接传 key 字符串
wx.removeStorageSync('token')

// 支付宝:必须传对象
my.removeStorageSync({ key: 'token' })
```

**建议**:封装一个兼容函数统一处理 Storage。

---

## 五、组件事件通信(重大差异)

微信使用 `triggerEvent`,支付宝通过 `props` 直接调用父组件方法。

| 平台 | 子组件调用父组件 | 父组件接收事件 |
|------|------------------|--------------|
| 微信 | `this.triggerEvent('closeLayer', data)` | `bind:closeLayer="handler"` |
| 支付宝 | `this.props.onCloseLayer(data)` | `onCloseLayer="handler"` |

**子组件示例**:

```javascript
// components/orderLayer/orderLayer.js
Component({
  methods: {
    onCloseTap: function() {
      // ✅ 支付宝:通过 props 直接调用
      if (this.props.onCloseLayer) {
        this.props.onCloseLayer({ isShow: false })
      }
    }
  }
})
```

**父页面示例**:

```xml
<!-- 支付宝:事件绑定使用驼峰命名 -->
<order-layer layerData="{{layerData}}" onCloseLayer="closeLayer" />
```

```javascript
Page({
  closeLayer: function(data) {
    this.setData({ 'layerData.isShow': false })
  }
})
```

---

## 六、配置文件转换

### 6.1 app.json

| 项目 | 微信 | 支付宝 |
|------|------|--------|
| 导航栏标题 | `navigationBarTitleText` | `defaultTitle` |
| 导航栏背景 | `navigationBarBackgroundColor` | `titleBarColor` |
| tabBar 列表字段 | `list` | `items` |
| tabBar 文字字段 | `text` | `name` |
| tabBar 图标 | `iconPath` / `selectedIconPath` | `icon` / `activeIcon`(必须以 `/` 开头) |
| tabBar 颜色 | `color` | `textColor` |

### 6.2 分包路径

```json
// 微信
"subPackages": [{ "root": "pages/group/" }]

// 支付宝(末尾无斜杠)
"subPackages": [{ "root": "pages/group" }]
```

---

## 七、页面跳转规范

**必须使用绝对路径**,相对路径在跨分包跳转时必失败。

```javascript
// ❌ 错误
my.navigateTo({ url: '../card/store/index' })

// ✅ 正确
my.navigateTo({ url: '/pages/card/store/index' })
```

**排查步骤**:
1. 确认目标页面在 `app.json` 的 `pages` 或 `subPackages` 中已注册
2. 确认路径以 `/` 开头
3. 确认分包 `root` 末尾**无斜杠**

---

## 八、支付迁移(前端侧)

| 项目 | 微信 | 支付宝 |
|------|------|--------|
| 前端 API | `wx.requestPayment` | `my.tradePay` |
| 参数 | `timeStamp/nonceStr/package/signType/paySign` | `tradeNO`(支付宝交易号)或 `orderStr` |
| 成功判断 | `success` 回调 | `success` 回调中 `res.resultCode === '9000'` |

```javascript
// 支付宝小程序支付
my.tradePay({
  tradeNO: tradeNo,  // 从后端接口获取
  success: function(res) {
    if (res.resultCode === '9000') {
      // 支付成功
    } else {
      // 支付未完成(用户取消或其他)
    }
  },
  fail: function(err) {
    // 调用失败(参数错误、网络异常等)
  }
})
```

---

## 九、高频问题速查

### 9.1 按钮点击无反应

1. 检查事件语法:`catchTap`(T 大写),不是 `catchtap`
2. `<button>` 元素在支付宝可能不响应,**改为 `<view>`**
3. 检查 AXML 中使用的变量是否在 `data` 中定义

### 9.2 页面跳转无反应/白屏

1. 路径是否以 `/` 开头(绝对路径)
2. 目标页面是否在 `app.json` 中注册
3. 分包 `root` 末尾是否多了 `/`
4. 目标页面 JS 是否有语法错误(`node -c file.js` 检查)

### 9.3 弹窗不显示或关闭无效

1. 控制变量是否在 `data` 中定义并初始化为 `false`
2. 子组件关闭方法是否用了 `triggerEvent`(应改为 `this.props.onXxx()`)
3. 遮罩层应使用 `onTap`,不要用 `catchTap`(避免阻止关闭)

### 9.4 空值安全

```javascript
// ❌ 可能崩溃
const phone = my.getStorageSync('userInfo').phoneNum

// ✅ 安全访问
const userInfo = my.getStorageSync('userInfo') || {}
const phone = userInfo.phoneNum || ''
```

### 9.5 订单列表/商品列表点击区域失效

常见于外层容器使用 `onTap`,内层按钮使用 `catchTap`。检查内层交互元素是否意外阻止了事件冒泡;同时检查**跳转路径是否漏写了中间目录**(如 `/pages/detail/index` 实际应为 `/pages/order/detail/index`)。

---

## 十、批量转换脚本(PowerShell)

```powershell
# 1. 复制文件
Get-ChildItem -Recurse -Filter "*.wxss" | ForEach-Object {
    $newName = $_.FullName -replace '\.wxss$', '.acss'
    if (-not (Test-Path $newName)) { Copy-Item $_.FullName $newName }
}
Get-ChildItem -Recurse -Filter "*.wxml" | ForEach-Object {
    $newName = $_.FullName -replace '\.wxml$', '.axml'
    if (-not (Test-Path $newName)) { Copy-Item $_.FullName $newName }
}

# 2. 替换 AXML 内容
Get-ChildItem -Recurse -Filter "*.axml" | ForEach-Object {
    $c = Get-Content $_.FullName -Raw -Encoding UTF8
    $c = $c -replace 'wx:', 'a:'
    $c = $c -replace 'bindtap', 'onTap'
    $c = $c -replace 'bind:', 'on-'
    Set-Content $_.FullName $c -Encoding UTF8 -NoNewline
}

# 3. 替换 JS 内容
Get-ChildItem -Recurse -Filter "*.js" | ForEach-Object {
    $c = Get-Content $_.FullName -Raw -Encoding UTF8
    $c = $c -replace '\bwx\.', 'my.'
    Set-Content $_.FullName $c -Encoding UTF8 -NoNewline
}

# 4. 修复 ACSS 引用
Get-ChildItem -Recurse -Filter "*.acss" | ForEach-Object {
    $c = Get-Content $_.FullName -Raw -Encoding UTF8
    $c = $c -replace '\.wxss', '.acss'
    Set-Content $_.FullName $c -Encoding UTF8 -NoNewline
}
```

---

## 十一、测试检查项

- [ ] 首页加载无报错
- [ ] 登录流程(`my.getAuthCode`)正常
- [ ] 页面跳转(绝对路径、跨分包)正常
- [ ] TabBar 显示正常(`items` / `icon` 以 `/` 开头)
- [ ] 按钮点击响应正常(`<view>` + `catchTap`)
- [ ] 弹窗打开/关闭正常(`props` 方式通信)
- [ ] 支付流程(`my.tradePay`)正常
- [ ] 列表渲染无异常(`a:for` / `a:key`)
- [ ] 空值场景无崩溃(Storage / 接口返回)

未完待续

至此支付宝小程序的前端页面已经正常跑起来了,下一篇将介绍支付宝小程序登录以及支付宝支付接口的实现(纯AI 开发的几个后端接口)

发表评论