# AGENTS.md

> 本文件是本仓库面向 AI 编程工具（Claude Code / Codex / Cursor / Copilot 等）的**唯一权威规范**。
> `CLAUDE.md`、`.cursor/rules/*` 均指向本文件，避免规则重复与漂移。
> 修改约定时只改这里。

## 项目概览

基于 **Vue3 + Vite + TypeScript + Element Plus** 的后台管理模板。通用的请求、工具、Hooks、UI 组件已抽离到 `@sud-web/*` 公共库，业务工程只保留页面与接口定义。

- 技术栈：Vue 3.5 `<script setup>` · Vite 7 · TS 5（strict）· Element Plus（按需）· Pinia · Vue Router 4 · vue-i18n · UnoCSS
- 公共库：`@sud-web/http`（Axios 封装）·`@sud-web/utils`·`@sud-web/vue-hooks`（`useTablePage`/`useModalForm`/`useDialogOut`）·`@sud-web/vue-ui`（`PcSearch`/`PcTable`/`Pagination`）
- 包管理：**npm**（锁文件为 `package-lock.json`，不要引入 pnpm/yarn 锁文件）

## 常用命令

| 目的 | 命令 |
| --- | --- |
| 启动开发 | `npm run start` |
| 生产打包 | `npm run build`（先 `vue-tsc` 类型检查） |
| 测试环境打包 | `npm run build:FAT` |
| 代码检查并自动修复 | `npm run lint` |
| 仅检查（不修复） | `npm run lint-test` |
| 单元测试 | `npm run test`（vitest） |

**改动代码后务必跑 `npm run lint`**，类型相关改动用 `npm run build` 或 `npx vue-tsc --noEmit` 验证。

## 代码风格（由 `@antfu/eslint-config` 强制）

ESLint 即格式化工具，提交前以 `npm run lint` 的结果为准。核心规则：

- **双引号** `"`，**不写分号**，**2 空格缩进**
- **不加尾随逗号**（`comma-dangle: never`）
- 大括号风格 `1tbs`
- Vue SFC 块顺序固定：`<script>` → `<template>` → `<style>`
- 禁止未使用的 import（`unused-imports/no-unused-imports: error`）
- `console` / `debugger` 不报错，但生产代码请勿遗留
- prettier 仅作辅助（`printWidth: 120`），冲突时以 ESLint 为准

约定补充：

- 路径别名 `@/` → `src/`（其余相对路径用 `./`）
- 每个页面组件写 `defineOptions({ name: "XxxView" })`
- Vue API（`ref`/`reactive`/`computed` 等）**显式从 `"vue"` import**（与现有代码一致，虽配置了 auto-import）
- 注释用中文，与现有代码保持一致的注释密度
- 类型用 `interface`（前缀 `I`，如 `IPayItem`）或 `type`，组件 props 用 `defineProps<...>()`

## 目录结构

```text
src/
├── api/          # 接口定义，按业务模块分目录（index.ts + types/）
├── assets/       # 静态资源
├── components/   # 业务组件（公共组件已移至 @sud-web/vue-ui）
├── config/       # 全局配置（白名单等）
├── constants/    # 常量（缓存 key 等）
├── directives/   # 自定义指令（如 permission）
├── hooks/        # 工程内 Hooks（通用 Hooks 已移至 @sud-web/vue-hooks）
├── lang/         # 国际化（vue-i18n）
├── layout/       # 布局（侧边栏 / 顶栏 / TagsView）
├── plugins/      # 插件加载
├── router/       # 路由（index.ts）与权限拦截（permission.ts）
├── store/        # Pinia（modules/ 下分模块）
├── styles/       # 全局样式
├── utils/        # 工程工具 + 请求实例（service.ts）
└── views/        # 页面
```

## 核心约定

### 请求 / API 模块

- 请求实例在 `src/utils/service.ts`，基于 `@sud-web/http` 的 `createAxios`；CSRF/Token 注入、401 自动刷新（`RefreshManager`）走库内默认方案，**不要自定义 baseURL**（统一走 vite 代理的 `/api`）。
- 业务接口从 `@/utils/service` 引入 `request`，按业务模块建目录：`src/api/<模块>/index.ts` + `src/api/<模块>/types/<模块>.ts`。
- 全局响应类型（见 `types/api.d.ts` / `src/api/type.d.ts`）：`IRequestResult<T>`、`IApiResponseData<T>`、`IApiTableRequestData<T>`（分页参数）。

```ts
// src/api/recharge/index.ts
import type * as Recharge from "./types/recharge"
import { request } from "@/utils/service"

/** 交易流水列表 */
export function getPayList(params: IApiTableRequestData) {
  return request<Recharge.GetPayListResponseData>({
    method: "get",
    url: "/api/fund/tx/list",
    params
  })
}
```

### 状态管理（Pinia）

- 模块放 `src/store/modules/*.ts`，用 **setup 语法** `defineStore("name", () => { ... })`，导出 `useXxxStore`。

### 路由

- `src/router/index.ts` 区分 `constantRoutes`（常驻）与动态路由（带权限）；**动态路由必须带 `name`**。
- `src/router/permission.ts` 负责登录态/权限拦截。
- `meta` 常用字段：`title`、`svgIcon`、`affix`、`keepAlive`、`hidden`、`Roles`。

### 公共组件

- `PcTable` / `PcSearch` 在 `src/main.ts` 通过 `app.use(...)` 注册一次后全局可用，并已引入 `@sud-web/vue-ui/style.css`，页面中**直接用，无需再 import**。

### 环境变量

- 自定义变量必须以 `VITE_` 开头，按 `.env.development` / `.env.fat` / `.env.production` 区分。

## 页面范式（最重要）

参考 `src/views/demo/`。详细分步指引见 `.agents/skills/`：

- **列表页**（`PcSearch` + `PcTable` + `useTablePage`）→ `.agents/skills/new-list-page/SKILL.md`
- **新增/编辑/查看弹窗**（`useDialogOut` + `useModalForm`）→ `.agents/skills/crud-modal/SKILL.md`
- **新建 API 模块** → `.agents/skills/new-api-module/SKILL.md`

要点：`requestApi(params)` 的分页字段由 `PcTable` 注入，业务只合并搜索条件；搜索触发 `@request` → `requestTable` → 表格重查；列内容用具名插槽 `#列prop="{ row }"`。

## 提交规范

Conventional Commits（中文描述），如：`feat(sso): 接入统一登录`、`refactor(api): 移除废弃接口`、`build(deps): 更新依赖`、`fix: 修复 xxx`。
**未经用户要求不要自动 commit / push。**

## Do / Don't

- ✅ 复用 `@sud-web/*` 提供的能力，不要在工程内重复造请求/工具/表格轮子
- ✅ 新增页面遵循 demo 范式与上述 skills
- ✅ 改完跑 `npm run lint`
- ❌ 不引入新依赖去做几行代码能解决的事；新增依赖前先确认现有栈无法满足
- ❌ 不写分号、不加尾随逗号、不用单引号（会被 ESLint 拦）
- ❌ 不改 `package-lock.json` 以外的锁文件管理方式
