|
|
@@ -1,242 +0,0 @@
|
|
|
-# Trae Skills for UniApp Migration (Granular)
|
|
|
-# UniApp 迁移技能 (细粒度)
|
|
|
-
|
|
|
-This document contains highly granular skills derived from `WX_TO_UNIAPP_RULES.md` for precise context injection in Trae.
|
|
|
-本文档包含源自 `WX_TO_UNIAPP_RULES.md` 的高细粒度技能,用于 Trae 的精准上下文注入。
|
|
|
-
|
|
|
-## Skill: File Extension & Project Structure Migration
|
|
|
-## 技能:文件扩展名与项目结构迁移
|
|
|
-**Description**: Rules for converting file types and mapping project configuration. (文件类型转换与项目配置映射规则)
|
|
|
-**Instructions**:
|
|
|
-1. **File Merging (文件合并)**:
|
|
|
- - Merge `.wxml`, `.wxss`, and `.js` into a single `.vue` file. (将 .wxml, .wxss, .js 合并为单个 .vue 文件)
|
|
|
- - `.wxml` content goes into `<template>`. (.wxml 内容放入 <template>)
|
|
|
- - `.wxss` content goes into `<style lang="scss">`. (.wxss 内容放入 <style lang="scss">)
|
|
|
- - `.js` content goes into `<script setup lang="ts">`. (.js 内容放入 <script setup lang="ts">)
|
|
|
-2. **Configuration Files (配置文件)**:
|
|
|
- - **DELETE** `.json` page configuration files. (删除页面 .json 配置文件)
|
|
|
- - **Migration**: Extract `navigationBarTitleText` from `.json` and move to `pages.json` (`style` or `globalStyle`). (提取标题配置迁移至 pages.json)
|
|
|
- - **Subpackages**: Move `app.json` `subpackages` to `pages.json` `subPackages` field. (迁移分包配置)
|
|
|
- - **Global Styles**: Move `app.wxss` content to `App.vue` `<style>` or `@import` a global css file. (全局样式迁移至 App.vue)
|
|
|
- - **Route Check**: If a file is a page (not in `components/`) and has no route, **MUST** register it in `pages.json`. (页面必须在 pages.json 注册)
|
|
|
-3. **Independent Files (独立文件)**:
|
|
|
- - Rename public `.wxss` to `.scss`. (公共 .wxss 重命名为 .scss)
|
|
|
- - Rename util `.js` to `.ts`. (工具 .js 重命名为 .ts)
|
|
|
- - Update all `@import` paths in code to reflect new extensions. (更新代码中的 @import 路径)
|
|
|
-4. **Cleanup (清理)**:
|
|
|
- - After verification, DELETE the original `.wxml`, `.wxss`, `.js`, `.json` files. (验证后删除原文件)
|
|
|
-
|
|
|
----
|
|
|
-
|
|
|
-## Skill: WXML to Vue Template Conversion
|
|
|
-## 技能:WXML 到 Vue 模板转换
|
|
|
-**Description**: Syntax mapping from WeChat Mini Program templates to Vue 3 templates. (微信小程序模板到 Vue 3 模板的语法映射)
|
|
|
-**Instructions**:
|
|
|
-1. **Directives (指令)**:
|
|
|
- - `wx:if`, `wx:elif`, `wx:else` -> `v-if`, `v-else-if`, `v-else`.
|
|
|
- - `wx:for="{{list}}"` -> `v-for="(item, index) in list" :key="index"`.
|
|
|
- - `wx:key="id"` -> `:key="item.id"`.
|
|
|
- - **Slicing**: For `v-if="index < 3"`, REPLACE with `v-for="... in list.slice(0, 3)"`. (限制循环数量使用 slice)
|
|
|
-2. **Events (事件)**:
|
|
|
- - `bindtap="fn"` -> `@click="fn"`.
|
|
|
- - `catchtap="fn"` -> `@click.stop="fn"`.
|
|
|
- - `bindinput="fn"` -> `@input="fn"`.
|
|
|
-3. **Dataset & Attributes (数据集与属性)**:
|
|
|
- - `data-xxx="{{val}}"` -> Prefer passing args: `@click="fn(val)"`. (优先传参替代 dataset)
|
|
|
- - If preserving dataset (Required for `menuClick`): Use `:data-xxx="val"`. Access in JS via `e.currentTarget?.dataset?.xxx` (Must use optional chaining). (保留 dataset 时需使用可选链访问)
|
|
|
- - `style="{{...}}"` -> `:style="..."`.
|
|
|
-4. **Logic Constraints (逻辑约束)**:
|
|
|
- - **NEVER** use `v-if` and `v-for` on the same element. Use `<template v-for>` wrapper. (禁止同时使用 v-if 和 v-for)
|
|
|
- - **Deep Access**: `v-if="menuObj?.Children?.[0]?.Children"` (Use optional chaining for all deep paths). (深层对象访问必须使用可选链)
|
|
|
-
|
|
|
----
|
|
|
-
|
|
|
-## Skill: JS Logic & Lifecycle Migration
|
|
|
-## 技能:JS 逻辑与生命周期迁移
|
|
|
-**Description**: Converting Mini Program JS logic to Vue 3 Composition API. (将小程序 JS 逻辑转换为 Vue 3 组合式 API)
|
|
|
-**Instructions**:
|
|
|
-1. **Structure (结构)**:
|
|
|
- - Replace `Page({})` with `<script setup lang="ts">`. (替换 Page 为 script setup)
|
|
|
- - Remove `app.js` logic; move to `App.vue` or Hooks. (移除 app.js 逻辑)
|
|
|
-2. **State Management (状态管理)**:
|
|
|
- - `data: { x: 1 }` -> `const x = ref(1)`.
|
|
|
- - `this.setData({ x: 2 })` -> `x.value = 2`.
|
|
|
- - `this.setData({ 'a.b': 2 })` -> `a.value.b = 2`.
|
|
|
- - **FORBIDDEN**: Do not use `this` keyword for state. (禁止使用 this)
|
|
|
-3. **Lifecycle (生命周期)**:
|
|
|
- - `onLoad` -> `onLoad` (from `@dcloudio/uni-app`) or `useOnLoad`.
|
|
|
- - `onShow` -> `onShow`.
|
|
|
- - `onReady` -> `onReady`.
|
|
|
- - **Context**: `getCurrentPages()` is allowed for page stack checks. (允许使用 getCurrentPages)
|
|
|
-4. **Components (组件)**:
|
|
|
- - `properties` -> `withDefaults(defineProps<{...}>(), {...})`.
|
|
|
- - `triggerEvent` -> `const emit = defineEmits([...]); emit('event')`.
|
|
|
- - `this.selectComponent` targets -> Child component must use `defineExpose({ method })`. (子组件需 expose 方法)
|
|
|
- - **Observers**: Replace `properties: { observer: ... }` with `watch(() => props.propName, (val) => { ... })`. (使用 watch 替代 observer)
|
|
|
-5. **Safety (安全)**:
|
|
|
- - `onLoad` params: `JSON.parse` MUST be inside `try-catch` to prevent white screen crashes. (JSON.parse 必须加 try-catch)
|
|
|
-
|
|
|
----
|
|
|
-
|
|
|
-## Skill: Page & App Instance Management
|
|
|
-## 技能:页面与 App 实例管理
|
|
|
-**Description**: Correctly obtaining and using `proxy` and `app` instances. (正确获取和使用 proxy 及 app 实例)
|
|
|
-**Instructions**:
|
|
|
-1. **Setup (初始化)**:
|
|
|
- - **MUST** be at the top of `<script setup>` (必须在 script setup 顶部):
|
|
|
- ```ts
|
|
|
- import { getCurrentInstance } from 'vue';
|
|
|
- const { proxy } = getCurrentInstance() as any;
|
|
|
- const app = getApp();
|
|
|
- ```
|
|
|
-2. **Restrictions (限制)**:
|
|
|
- - **NEVER** call `getCurrentInstance()` or `getApp()` repeatedly inside functions. (禁止在函数内重复调用)
|
|
|
- - **NEVER** use `this` in setup; use `proxy` instead. (setup 中禁止使用 this,用 proxy 替代)
|
|
|
-3. **Global Data (全局数据)**:
|
|
|
- - `app.globalData` is still used for runtime context (`hosId`, `channelId`, `config`). Do NOT remove these usages unless moving to Store. (保留 app.globalData 的运行时上下文)
|
|
|
-
|
|
|
----
|
|
|
-
|
|
|
-## Skill: API Service Encapsulation & Import
|
|
|
-## 技能:API 服务封装与导入
|
|
|
-**Description**: Strict standards for defining and calling API services. (定义和调用 API 服务的严格标准)
|
|
|
-**Instructions**:
|
|
|
-1. **Import Rules (CRITICAL) (导入规则-关键)**:
|
|
|
- - **MUST** use Named Imports: `import { apiName } from '@/service/...'`. (必须使用命名导入)
|
|
|
- - **NEVER** use default imports (`import api from ...`) or wildcard imports. (禁止默认导入或通配符导入)
|
|
|
- - **NEVER** use relative paths or `config/api`. Use aliases `@/pagesPersonal/...` etc. (禁止相对路径,使用别名)
|
|
|
- - **NO `api.ts`**: Do NOT import/use `api.ts` objects. Explicitly concat URLs. (禁止使用 api.ts 对象)
|
|
|
-2. **Service Definition (服务定义)**:
|
|
|
- - Import `handle`, `request` from `@kasite/uni-app-base`. (引入 handle, request)
|
|
|
- - Use `handle.promistHandleNew` (New version). (使用 promistHandleNew)
|
|
|
- - Return format: `return handle.catchPromiseNew(resp, () => resp)`. (返回格式规范)
|
|
|
- - URL: Construct explicitly: `${REQUEST_CONFIG.BASE_URL}path/to/api`. (显式构造 URL)
|
|
|
- - **Structure**: Group by business (e.g., `base/`, `home/`) and export via `index.ts`. (按业务分组并统一导出)
|
|
|
-3. **Calling APIs (调用 API)**:
|
|
|
- - **MUST** destructure result: `let { resp, resData } = await apiName(params)`. (必须解构结果)
|
|
|
- - **Validation**: **MUST** check `if (common.isNotEmpty(resp))` before processing data. (处理前必须校验 resp)
|
|
|
- - **Variable Declaration**: Use `let resp`, **NEVER** `const resp`. (使用 let resp)
|
|
|
- - **Naming Conflicts**: If API name matches local variable, RENAME local variable (e.g., `acceptCredit` -> `targetStatus`). (避免变量名冲突)
|
|
|
- - **Serial Calls**: Rename result: `let { resp: listResp } = await nextApi(...)`. (串行调用需重命名结果)
|
|
|
-
|
|
|
----
|
|
|
-
|
|
|
-## Skill: Utils, Hooks & Common Tools
|
|
|
-## 技能:工具、Hooks 与常用方法
|
|
|
-**Description**: Replacement rules for legacy utility libraries and global functions. (遗留工具库和全局函数的替换规则)
|
|
|
-**Instructions**:
|
|
|
-1. **Removed Objects (移除的对象)**:
|
|
|
- - `publicFn` (Object) -> REMOVED. Use Named Import. (移除 publicFn 对象)
|
|
|
- - `util` object -> REMOVED. (移除 util 对象)
|
|
|
-2. **Specific Replacements (特定替换)**:
|
|
|
- - `publicFn.getMember` -> `await useGetMember()`.
|
|
|
- - `util.getAuthorize.call(proxy)` -> `common.getAuthorize`.
|
|
|
- - `publicFn.getLocation` -> `import { getLocation } from '@/utils'`.
|
|
|
- - `publicFn.menuClick` -> `import { menuClick } from '@/utils'`.
|
|
|
- - `getState.js` / `pagesPatientFn.js` -> `import { getState, pagesPatientFn } from '@/uni-app-base/utils'`. (必须使用 uni-app-base/utils 下的 TS 版本)
|
|
|
-3. **Menu Click Standard (菜单点击标准)**:
|
|
|
- - Template: `:data-item="item" @click="fn"`.
|
|
|
- - JS: `const fn = (e) => { menuClick(e, proxy, 'navigateTo'); }`. (3rd arg `skipWay` is optional).
|
|
|
-4. **Import Standards (导入标准 - CRITICAL)**:
|
|
|
- - **common**: `import { common } from '@/utils'` (Named Import ONLY). (必须解构导入)
|
|
|
- - **publicFn**: `import { publicFn } from '@/utils'` (Named Import ONLY). (必须解构导入)
|
|
|
- - **icon**: `import icon from '@/utils/icon'` (Default Import ONLY). (必须默认导入)
|
|
|
-5. **Common Methods (常用方法)**:
|
|
|
- - Use `common.deepCopy(obj)` for deep copying. (深拷贝)
|
|
|
- - Use `common.throttle(fn, time)` for throttling. (节流)
|
|
|
-6. **Icon Usage (图标使用)**:
|
|
|
- - JS: `const iconUrl = ref(icon.someIcon)`.
|
|
|
- - Template: `<image :src="iconUrl" />`.
|
|
|
-
|
|
|
----
|
|
|
-
|
|
|
-## Skill: Styling, Units & Assets
|
|
|
-## 技能:样式、单位与资源
|
|
|
-**Description**: Rules for CSS units, static assets, and style migration. (CSS 单位、静态资源和样式迁移规则)
|
|
|
-**Instructions**:
|
|
|
-1. **Units (单位)**:
|
|
|
- - **Strictly** convert all `rpx` to `upx`. (严格将 rpx 转换为 upx)
|
|
|
-2. **Images (图片)**:
|
|
|
- - Background images in CSS: Use absolute paths (`/static/...`) or full URLs. (CSS 背景图使用绝对路径)
|
|
|
- - Template images: Use `iconUrl` ref pattern. (模板图片使用 iconUrl ref 模式)
|
|
|
-3. **Preservation (保留)**:
|
|
|
- - Keep original CSS logic. Only fix layout breaks caused by platform differences. (保留原 CSS 逻辑,仅修复布局错误)
|
|
|
-
|
|
|
----
|
|
|
-
|
|
|
-## Skill: General UniApp API & Platform Differences
|
|
|
-## 技能:通用 UniApp API 与平台差异
|
|
|
-**Description**: Mapping WeChat APIs to UniApp and handling platform quirks. (微信 API 映射到 UniApp 及平台特性处理)
|
|
|
-**Instructions**:
|
|
|
-1. **Namespace (命名空间)**:
|
|
|
- - Replace `wx.` with `uni.` (e.g., `wx.request` -> `uni.request`). (wx. 替换为 uni.)
|
|
|
-2. **Specific API Adjustments (特定 API 调整)**:
|
|
|
- - `wx.getStorageSync` -> `uni.getStorageSync`.
|
|
|
- - `wx.createSelectorQuery()` -> `uni.createSelectorQuery().in(this)` (MUST add `.in(this)`). (必须添加 .in(this))
|
|
|
- - `wx.navigateToMiniProgram` -> `uni.navigateToMiniProgram`.
|
|
|
-3. **Compatibility (兼容性)**:
|
|
|
- - `uni.getDeviceInfo`: If unavailable, fallback to `uni.getSystemInfoSync()`. (设备信息获取降级处理)
|
|
|
-4. **Environment (环境)**:
|
|
|
- - **H5**: Uses proxy (`/api` -> `VITE_APP_PROXY_API_BASE_URL`). (H5 使用代理)
|
|
|
- - **Mini Program**: Must use absolute URL (from `REQUEST_CONFIG` or `useDomain()`). (小程序使用绝对路径)
|
|
|
-
|
|
|
----
|
|
|
-
|
|
|
-## Skill: State Management (Store)
|
|
|
-## 技能:状态管理 (Store)
|
|
|
-**Description**: Using `@kasite/uni-app-base` store and replacing globalData. (使用 store 替换 globalData)
|
|
|
-**Instructions**:
|
|
|
-1. **Access (访问)**:
|
|
|
- - Use `import { useStore } from 'vuex'; const store = useStore();`.
|
|
|
- - Replaces `getApp().globalData` for reactive state (token, currentUser). (替换 globalData 中的响应式状态)
|
|
|
-2. **Token/OpenId**:
|
|
|
- - **FORBIDDEN**: `uni.getStorageSync('token'|'openid')`. (禁止直接读取缓存 token/openid)
|
|
|
- - **MUST USE**: `store.state.token`, `store.state.openId`, `store.state.smallProOpenId`. (必须通过 store 获取)
|
|
|
-3. **Helpers (辅助函数)**:
|
|
|
- - Use `mapState`, `mapMutations` from `@kasite/uni-app-base/store` if needed.
|
|
|
-
|
|
|
----
|
|
|
-
|
|
|
-## Skill: Third-Party Libraries & Components
|
|
|
-## 技能:第三方库与组件
|
|
|
-**Description**: Handling external libraries (xbossTrack) and Easycom components. (处理外部库和 Easycom 组件)
|
|
|
-**Instructions**:
|
|
|
-1. **xbossTrack (Tracking) (埋点)**:
|
|
|
- - `Page` constructor hijacking DOES NOT WORK in UniApp. (UniApp 中 Page 劫持无效)
|
|
|
- - Use **Global Mixin** in `main.js` or `App.vue` for `onShow` tracking. (使用全局 Mixin 处理 onShow 埋点)
|
|
|
- - For element tracking: Add explicit `@click="trackEvent"` or use a custom directive. (元素埋点显式添加事件)
|
|
|
- - **Integrity**: Do NOT delete tracking logic; migrate or add TODO. (不要删除埋点逻辑)
|
|
|
-2. **Rich Text (富文本)**:
|
|
|
- - **REPLACE** `towxml` with `mp-html` (`uni_modules`). (使用 mp-html 替换 towxml)
|
|
|
- - Usage: `<mp-html :content="html" :domain="domain" />`.
|
|
|
-3. **Easycom**:
|
|
|
- - Components in `uni_modules` are auto-imported. No need for `import` + `components: {}`. (uni_modules 组件自动导入)
|
|
|
-
|
|
|
----
|
|
|
-
|
|
|
-## Skill: Project Specific Hooks & Startup
|
|
|
-## 技能:项目特定 Hooks 与启动流程
|
|
|
-**Description**: Custom hooks required by the specific project architecture. (项目架构要求的自定义 Hooks)
|
|
|
-**Instructions**:
|
|
|
-1. **Load & Member (加载与成员)**:
|
|
|
- - `useOnLoad(async (opt) => { ... })`: Wraps onLoad logic. (封装 onLoad 逻辑)
|
|
|
- - `usePreserMember()`: Pre-processes patient/member info. (预处理成员信息)
|
|
|
- - `useGetDefaultMember()`: Gets default member. (获取默认成员)
|
|
|
- - `useIsToAuthPage()`: Auth check. (授权检查)
|
|
|
-2. **Startup Flow (App.vue) (启动流程)**:
|
|
|
- - Sequence: Version -> Config -> State -> Login -> Menu -> WebSocket. (启动顺序)
|
|
|
-3. **Optimization Rule (优化规则)**:
|
|
|
- - IF `queryMemberCardList_V3` is called with ONLY `memberId`, REPLACE with `queryMemberCardList_V3` from hook. (特定 API 替换为 Hook)
|
|
|
-
|
|
|
----
|
|
|
-
|
|
|
-## Skill: Migration Workflow (Reference)
|
|
|
-## 技能:迁移工作流 (参考)
|
|
|
-**Description**: Recommended step-by-step process for high-quality migration. (高质量迁移的推荐步骤)
|
|
|
-**Instructions**:
|
|
|
-1. **Step 1: Template (模板)**: Convert WXML to Vue template. Fix directives, events, and bindings. (转换模板,修复指令/事件/绑定)
|
|
|
-2. **Step 2: Logic (逻辑)**: Convert JS to TS setup. Handle `proxy`, `app`, `ref`, and lifecycle. (转换逻辑,处理实例与生命周期)
|
|
|
-3. **Step 3: Hooks (Hooks)**: Integrate `useOnLoad`, `usePreserMember`, etc. (接入 Hooks)
|
|
|
-4. **Step 4: API (API)**: Replace `wx.request` with named service imports. (替换 API 请求)
|
|
|
-5. **Step 5: Styles (样式)**: Convert `wxss` to `scss`, replace `rpx` with `upx`. (转换样式,替换单位)
|
|
|
-6. **Step 6: Verify (验证)**: Check rendering, interactions, and console for errors. (验证渲染、交互和报错)
|