# AGENTS.md - haha-mp 智能体代码生成规则
> 本文件为 AI Agent 代码生成提供强制规则约束,定义生成边界与规范。
> 所有规则均为强制性,Agent 生成代码时必须严格遵守。违反规则的代码不可提交。
---
## 1. 项目边界
### 1.1 技术栈版本锁定
| 技术 | 版本 | 禁止事项 |
|------|------|----------|
| uni-app | 3.0.0-5000720260410001 | 禁止使用 uni-app v2 |
| Vue | 3.5.32 | Composition API only,禁止 Options API |
| TypeScript | ^4.9.4 | 注意:uni-app 限制,不可升级到 TS 5 |
| Vite | 5.2.8 | 禁止升级到 Vite 6+(uni-app 兼容性) |
| Pinia | ^3.0.4 | 禁止 Vuex |
| Sass | ^1.99.0 | 样式预处理统一使用 SCSS |
| 微信小程序 appid | `wxef6ffc2591d04b1b` | 禁止修改 |
### 1.2 目标平台
- **主要平台**:微信小程序(`mp-weixin`)
- 构建命令:`pnpm dev:mp-weixin`(开发)、`pnpm build:mp-weixin`(构建)
- 代码需兼容小程序运行时限制(无 DOM、无 window、无 axios)
### 1.3 后端 API 对接
| 配置项 | 值 |
|--------|-----|
| 后端服务地址 | `https://dev-haha.kuaiyuman.cn/api`(开发环境) |
| 后端应用 | `haha-miniapp`(端口 7077,context-path: /api) |
| 请求方式 | `uni.request`(封装在 `src/utils/request.ts`) |
| 认证方式 | 请求头 `accessToken: {token}` |
| 请求超时 | 30000ms |
### 1.4 目录职责(严格遵循)
```
src/
├── api/ # API 请求函数(每个模块一个文件)
├── components/ # 公共组件
├── pages/ # 小程序页面(每个页面一个目录,含 .vue 文件)
├── static/ # 静态资源(图标、图片、动画样式)
│ ├── icons/ # SVG 图标
│ └── images/ # 图片资源
├── styles/ # 全局样式
├── utils/ # 工具函数
│ ├── request.ts # HTTP 请求封装
│ ├── auth.ts # 认证工具
│ └── config.ts # API 配置
├── App.vue # 应用入口(onLaunch/onShow/onHide)
├── main.ts # 创建应用(createSSRApp + Pinia)
├── manifest.json # 小程序配置
├── pages.json # 页面路由与导航栏配置
└── uni.scss # 全局 SCSS 变量(Design Tokens)
```
---
## 2. 代码生成规则
### 2.1 页面 (pages/)
**强制结构**:每个页面是一个独立目录,包含同名的 `.vue` 文件
```
pages/{pageName}/
└── {pageName}.vue # 页面组件
```
**页面 Vue 文件模板**:
```vue
```
**页面注册**:新增页面必须在 `pages.json` 中注册
```json
{
"path": "pages/xxx/xxx",
"style": {
"navigationBarTitleText": "页面标题",
"navigationBarBackgroundColor": "#FFD700",
"navigationBarTextStyle": "black"
}
}
```
**强制规则**:
- 导航栏背景色统一 `#FFD700`(品牌黄)
- 导航栏文字颜色统一 `black`
- 使用 `` 代替 ``,`
` 代替 ``
- 使用 `` 代替 `
`,必须指定 `mode` 属性
- 使用 `uni.xxx` API 代替浏览器原生 API
- 使用 `rpx` 单位代替 `px`(1rpx = 屏幕宽度/750)
- 使用 `@dcloudio/uni-app` 生命周期钩子(`onLoad`、`onShow`、`onHide`)
- 禁止使用 DOM API(`document`、`window`、`localStorage`)
- 使用 `uni.getStorageSync/setStorageSync` 代替 `localStorage`
- 路由跳转使用 `uni.navigateTo`/`uni.reLaunch`/`uni.switchTab`
### 2.2 API 层 (api/)
**强制规则**:
1. 每个 API 文件对应一个后端模块
2. 统一使用 `src/utils/request.ts` 中的 `request`/`get`/`post`/`put`/`del`
3. 必须定义 TypeScript 接口,导出供页面使用
**API 文件模板**:
```ts
/**
* xxx相关API
*/
import { get, post } from '../utils/request';
/**
* 数据接口定义
*/
export interface XxxInfo {
id: string; // 雪花ID,必须为 string 类型
name: string;
status: number;
createTime: string;
}
/**
* 请求参数接口
*/
export interface XxxListRequest {
page?: number;
pageSize?: number;
status?: number;
}
/**
* 获取xxx列表
* @param params 查询参数
*/
export const getXxxList = (params?: XxxListRequest): Promise => {
return post('/xxx/list', params || {});
};
/**
* 获取xxx详情
* @param id xxx ID
*/
export const getXxxDetail = (id: string): Promise => {
return get(`/xxx/${id}`);
};
```
**禁止事项**:
- 禁止直接使用 `uni.request`(必须通过 `request.ts` 封装)
- 禁止在 API 函数中处理 UI 逻辑(如 `uni.showToast`)
- 禁止使用 `axios`(小程序不支持)
- 禁止硬编码后端地址(使用 `API_CONFIG.baseUrl`)
### 2.3 请求封装 (utils/request.ts)
**已有封装,禁止重写**。关键行为:
- 请求拦截:自动添加 `accessToken` 请求头
- 响应拦截:`code === 200 || code === 0` 为成功,返回 `data` 字段
- 401 处理:清除 token + 1.5s 后跳转登录页
- 错误处理:自动 `uni.showToast` 提示
- 支持 `skipAuth` 参数跳过认证(仅用于免登录接口)
**免登录接口示例**:
```ts
export const getDeviceProducts = (deviceId: string): Promise => {
return get(`/device/products/${deviceId}`, undefined, { skipAuth: true });
};
```
### 2.4 认证工具 (utils/auth.ts)
**已有封装,禁止重写**。关键行为:
| 函数 | 用途 |
|------|------|
| `getToken()` | 获取 accessToken |
| `setToken(token)` | 存储 accessToken |
| `removeToken()` | 清除 accessToken |
| `isLoggedIn()` | 判断是否已登录 |
| `checkAuth(redirectUrl?)` | 路由守卫,未登录跳转登录页 |
| `clearAuth()` | 清除所有登录信息 + 购物流程数据 |
| `logout()` | 清除登录信息 + reLaunch 到登录页 |
**Token 存储 key**:`accessToken`(uni.getStorageSync)
---
## 3. 样式规则
### 3.1 Design Token 变量
**必须使用 `uni.scss` 中定义的 Design Token**,禁止硬编码:
```scss
/* 主色系 */
$color-primary: #FFC107; // 品牌黄
$color-primary-light: #FFE082;
$color-primary-dark: #FFA000;
/* 文字颜色 */
$color-text-primary: #2C2C2C; // 主文字
$color-text-secondary: #8C8C8C; // 辅助文字
$color-text-tertiary: #BDBDBD; // 三级文字
/* 背景色 */
$color-bg-primary: #FFFFFF;
$color-bg-secondary: #FAFAFA;
$color-bg-tertiary: #F5F5F5;
/* 边框/阴影 */
$color-border: #EEEEEE;
$shadow-primary: 0 8rpx 24rpx rgba(255, 193, 7, 0.25);
/* 间距系统 */
$spacing-xs: 8rpx;
$spacing-sm: 16rpx;
$spacing-md: 24rpx;
$spacing-lg: 32rpx;
$spacing-xl: 48rpx;
$spacing-xxl: 64rpx;
/* 圆角 */
$radius-sm: 8rpx;
$radius-md: 16rpx;
$radius-lg: 24rpx;
$radius-xl: 32rpx;
/* 动画 */
$duration-fast: 150ms;
$duration-normal: 300ms;
$ease-out: cubic-bezier(0.25, 0.1, 0.25, 1);
$bounce: cubic-bezier(0.68, -0.55, 0.265, 1.55);
```
### 3.2 样式编写规范
| 规则 | 说明 |
|------|------|
| 单位 | 统一使用 `rpx`(设计稿 750rpx 宽度),禁止 `px`/`rem`/`em` |
| 颜色 | 使用 Design Token 变量,禁止硬编码颜色值 |
| 间距 | 使用 `$spacing-xxx` 变量 |
| 圆角 | 使用 `$radius-xxx` 变量 |
| 阴影 | 使用 `$shadow-xxx` 变量 |
| 动画 | 使用 `$duration-xxx` + `$ease-out` |
| 作用域 | 全局样式不加 scoped,页面级样式尽量加 `scoped` |
| 性能 | 动画元素添加 `will-change: transform, opacity` + `transform: translateZ(0)` |
### 3.3 禁止事项
- 禁止使用 `px` 作为布局单位(仅 `rpx`)
- 禁止硬编码颜色值(必须使用变量)
- 禁止使用 CSS `filter` 属性(小程序性能差)
- 禁止使用 `backdrop-filter`(兼容性问题)
- 禁止使用 `position: fixed` 在列表项中(性能问题)
- 禁止复杂 `box-shadow` 动画
---
## 4. 路由与导航规则
### 4.1 路由方式
| 场景 | API | 说明 |
|------|-----|------|
| 普通跳转 | `uni.navigateTo` | 可返回,最多 10 层栈 |
| 不可返回跳转 | `uni.reLaunch` | 关闭所有页面,打开目标页 |
| Tab 切换 | `uni.switchTab` | 用于 tabBar 页面(当前无 tabBar) |
| 返回上一页 | `uni.navigateBack` | -- |
| 重定向 | `uni.redirectTo` | 关闭当前页,打开目标页 |
### 4.2 路由传参
```ts
// 传递参数
uni.navigateTo({
url: '/pages/xxx/xxx?id=' + String(id) + '&name=' + name
});
// 接收参数
onLoad((options: any) => {
const id = options.id; // 字符串
});
```
**强制规则**:
- 雪花 ID 传参必须 `String(id)` 防止精度丢失
- 登录页支持 `redirect` 参数:`/pages/login/login?redirect=/pages/index/index`
### 4.3 页面白名单
以下页面允许未登录用户直接访问(定义在 `App.vue`):
```ts
const LOGIN_WHITE_LIST = [
'pages/login/login',
'pages/products/products', // 柜内商品展示
];
```
新增免登录页面时,必须同步更新此白名单。
---
## 5. 业务规则约束
### 5.1 扫码开门流程
```
用户扫码 → 检查登录 → 检查支付分 → 调用 scanDoor API → 存储 deviceId/outTradeNo/orderNo → 跳转购物页
```
**强制规则**:
- 扫码前必须检查登录状态
- 扫码前必须检查微信支付分开通状态
- 二维码格式:`https://hh.hahabianli.com/B142977?_wxpmm0=...`
- 设备 ID 提取:正则 `/\/([A-Z0-9]+)(\?|$)/`
### 5.2 订单金额显示
- **实付金额字段**:`paidAmount || totalAmount`(优先使用 paidAmount)
- 格式化:`(amount || 0).toFixed(2)`
- 前缀:`¥`
### 5.3 退款时效
- 仅已完成订单(`status === 1`)可申请退款
- 退款期限:支付时间后 7 天内
- 超过 7 天自动隐藏退款按钮
### 5.4 登录认证
- **唯一登录方式**:微信手机号快速登录(`open-type="getPhoneNumber"`)
- API:`/login/miniapp-phone`,参数 `{ code, phoneCode }`
- 登录成功后存储 token + userInfo
- 支持登录后跳转回原页面(redirect 参数)
---
## 6. 小程序特有约束
### 6.1 兼容性规则
| 编号 | 约束 | 说明 |
|------|------|------|
| C1 | 禁止 DOM API | 无 `document`/`window`/`localStorage` |
| C2 | 禁止 axios | 小程序不支持 XHR,必须用 `uni.request` |
| C3 | 图片必须指定 mode | `` |
| C4 | 禁止 v-html | 小程序不支持 |
| C5 | 禁止动态组件 | `` 有限制 |
| C6 | 使用 rpx 单位 | 适配不同屏幕宽度 |
| C7 | 事件使用 @tap | 优先使用 `@tap` 代替 `@click` |
| C8 | 按钮反馈 | 操作按钮添加 `hover-class` |
| C9 | 安全区适配 | 底部 `padding-bottom: env(safe-area-inset-bottom)` |
| C10 | 包体积 | 单个包不超过 2MB,主包不超过 2MB |
### 6.2 性能优化规则
| 编号 | 规则 | 说明 |
|------|------|------|
| P1 | 动画使用 `transform` + `opacity` | 避免触发 layout/paint |
| P2 | 动画元素添加 `will-change` | `will-change: transform, opacity` |
| P3 | 动画元素添加 `transform: translateZ(0)` | 开启 GPU 加速 |
| P4 | 禁止 `filter: blur()` | 小程序性能极差 |
| P5 | 禁止复杂 `box-shadow` 动画 | 改用静态阴影 |
| P6 | 长列表使用虚拟列表 | 超过 100 项必须虚拟滚动 |
| P7 | 图片懒加载 | `` |
| P8 | 轮询必须有超时和清理 | 避免页面切换后持续请求 |
### 6.3 小程序 API 使用规范
| 需求 | 使用 | 禁止 |
|------|------|------|
| 存储 | `uni.getStorageSync/setStorageSync` | `localStorage` |
| 路由 | `uni.navigateTo/reLaunch` | `router.push` |
| 提示 | `uni.showToast/showLoading/showModal` | 自定义 toast |
| 扫码 | `uni.scanCode` | 第三方扫码 |
| 拨号 | `uni.makePhoneCall` | `tel:` 链接 |
| 震动 | `uni.vibrateShort` | -- |
| 登录 | `uni.login` | -- |
---
## 7. 常见陷阱
| 编号 | 陷阱 | 规则 |
|------|------|------|
| T1 | 雪花 ID 使用 number 类型 | 禁止。必须为 `string` 类型,防止 JS 精度丢失 |
| T2 | 路由传参直接传 number ID | 禁止。必须 `String(id)` |
| T3 | 使用 `localStorage` | 禁止。必须 `uni.getStorageSync/setStorageSync` |
| T4 | 使用 `axios` | 禁止。小程序不支持,使用封装的 `request.ts` |
| T5 | 使用 `document/window` | 禁止。小程序无 DOM |
| T6 | 使用 `px` 单位 | 禁止。统一使用 `rpx` |
| T7 | 硬编码颜色值 | 禁止。使用 `uni.scss` 中的 Design Token |
| T8 | 新页面不注册 pages.json | 禁止。每个新页面必须在 pages.json 中配置 |
| T9 | 免登录页面不更新白名单 | 禁止。同步更新 App.vue 中 LOGIN_WHITE_LIST |
| T10 | 轮询不设置超时 | 禁止。所有轮询必须有 timeout + 页面卸载清理 |
| T11 | 在 API 层处理 UI 逻辑 | 禁止。API 层只负责请求 |
| T12 | 使用 `/
/
` | 禁止。使用 `//` |
| T13 | 导航栏颜色不一致 | 禁止。统一 `#FFD700` 背景 + `black` 文字 |
| T14 | 实付金额取 totalAmount | 禁止。优先取 `paidAmount`,fallback `totalAmount` |
| T15 | 不处理安全区 | 禁止。底部内容必须适配 `safe-area-inset-bottom` |