# AGENTS.md - Vue 3 Frontend

**Generated:** 2026-03-03
**Stack:** Vue 3.4 + TypeScript 4.9 + Element Plus 2.5 + Pinia 2.0 + Vite 4.3

## Overview

Vue 3 SPA with custom composables for data fetching. Element Plus for UI.

## Structure

```
cloud-ui/src/
├── api/           # API modules (one per entity)
├── components/    # Reusable components
├── hooks/         # Composables (useDict, useTable, etc.)
├── stores/        # Pinia stores
├── router/        # Vue Router config
├── views/         # Page components (flat per module)
├── const/         # Constants (non-standard name)
├── utils/         # Utilities (request.ts for HTTP)
└── types/         # TypeScript types
```

## Key Hooks

| Hook                                | Purpose                      |
| ----------------------------------- | ---------------------------- |
| `useDict(type1, type2)`             | Dictionary data with caching |
| `useTable({ pageList, queryForm })` | Table + pagination           |
| `useMessage()`                      | Toast notifications          |
| `useMessageBox()`                   | Confirm dialogs              |
| `useParam(type)`                    | System parameters            |

## API Pattern

```typescript
import request from '/@/utils/request';

// One file per entity: api/module/entity.ts
export const fetchList = (params) => request.get('/module/entity/page', { params });
export const addObj = (data) => request.post('/module/entity', data);
export const putObj = (data) => request.post('/module/entity/edit', data);
export const delObj = (id) => request.post('/module/entity/delete', id);
```

## Hooks Usage

```typescript
// Dictionary
const { dict } = useDict('sex', 'status');
// Access: dict.sex, dict.status

// Table
const { tableData, loading, getData, pagination } = useTable({
	pageList: fetchList,
	queryForm: reactive({ name: '' }),
});

// Message
const { msgSuccess, msgError } = useMessage();
msgSuccess('操作成功');

// Confirm
const { msgBoxConfirm } = useMessageBox();
await msgBoxConfirm('确定删除?');
```

## Constraints

| Rule            | Details                                       |
| --------------- | --------------------------------------------- |
| **Hardcoding**  | NO hardcoded strings. Define constants first. |
| **Line width**  | 150 chars (Prettier)                          |
| **Indentation** | Tabs (Prettier)                               |
| **Quotes**      | Single quotes                                 |
| **API updates** | POST /edit (NOT PUT)                          |
| **API deletes** | POST /delete (NOT DELETE)                     |

## Commands

```bash
npm run dev           # Development server
npm run build         # Production build
npm run lint:eslint   # Lint + fix
npm run prettier      # Format code
```

## Non-Standard

| Location                             | Issue                         |
| ------------------------------------ | ----------------------------- |
| `src/composables/` + `src/hooks/`    | Both exist (prefer hooks/)    |
| `src/directive/` + `src/directives/` | Both exist                    |
| `src/const/`                         | Named "const" not "constants" |

## ESLint Relaxed Rules

Many TypeScript rules are OFF:

- `@typescript-eslint/no-explicit-any`: OFF
- `@typescript-eslint/explicit-function-return-type`: OFF
- `vue/require-default-prop`: OFF

Follow existing patterns in codebase.
