---
description: 前端特定的开发规范（仅作用于 frontend 目录）
globs:
alwaysApply: true
---

# 前端特定规范

本规则仅作用于 `frontend/` 目录。

## Ant Design Vue 组件使用

### 表格组件

```vue
<template>
  <a-table
    :columns="columns"
    :data-source="dataSource"
    :loading="loading"
    :pagination="pagination"
    @change="handleTableChange"
  >
    <template #bodyCell="{ column, record }">
      <template v-if="column.key === 'action'">
        <a-space>
          <a-button type="link" @click="handleEdit(record)">编辑</a-button>
          <a-popconfirm
            title="确定要删除吗？"
            @confirm="handleDelete(record.id)"
          >
            <a-button type="link" danger>删除</a-button>
          </a-popconfirm>
        </a-space>
      </template>
    </template>
  </a-table>
</template>
```

### 表单组件

```vue
<template>
  <a-form
    :model="formState"
    :rules="rules"
    layout="vertical"
    @finish="onFinish"
  >
    <a-form-item label="用户名" name="username">
      <a-input v-model:value="formState.username" />
    </a-form-item>
    
    <a-form-item>
      <a-button type="primary" html-type="submit">提交</a-button>
    </a-form-item>
  </a-form>
</template>
```

### Modal 弹窗

```vue
<template>
  <a-modal
    v-model:open="visible"
    title="编辑用户"
    @ok="handleOk"
  >
    <a-form :model="formState">
      <!-- 表单内容 -->
    </a-form>
  </a-modal>
</template>
```

## 消息提示

```typescript
import { message, notification } from 'ant-design-vue';

// 成功提示
message.success('操作成功');

// 错误提示
message.error('操作失败');

// 通知
notification.success({
  message: '成功',
  description: '用户创建成功',
});
```

## Tailwind CSS 常用类

```html
<!-- 布局 -->
<div class="flex items-center justify-between">
<div class="grid grid-cols-3 gap-4">
<div class="p-4 m-2">

<!-- 响应式 -->
<div class="w-full md:w-1/2 lg:w-1/3">

<!-- 文本 -->
<p class="text-lg font-bold text-gray-800">

<!-- 状态 -->
<button class="hover:bg-blue-600 active:bg-blue-700">
```

## 权限指令

使用自定义指令 `v-permission`：

```vue
<template>
  <a-button v-permission="'user:create'" type="primary">
    创建用户
  </a-button>
  
  <a-button v-permission="['user:update', 'user:delete']" type="link">
    编辑
  </a-button>
</template>
```

## 租户路由

所有路由必须包含租户编码：

```typescript
// ✅ 正确
router.push(`/${tenantCode}/users`);

// ❌ 错误
router.push('/users');
```

获取租户编码：

```typescript
import { useRoute } from 'vue-router';

const route = useRoute();
const tenantCode = route.params.tenantCode as string;
```

## 常用组合式函数

### 使用权限检查

```typescript
import { useAuthStore } from '@/stores/auth';

const authStore = useAuthStore();

// 检查权限
const hasPermission = authStore.hasPermission('user:create');

// 检查多个权限（任一）
const hasAnyPermission = authStore.hasAnyPermission(['user:create', 'user:update']);
```

### 表格分页

```typescript
import { ref, reactive } from 'vue';

const loading = ref(false);
const dataSource = ref([]);
const pagination = reactive({
  current: 1,
  pageSize: 10,
  total: 0,
});

const handleTableChange = (pag: any) => {
  pagination.current = pag.current;
  pagination.pageSize = pag.pageSize;
  fetchData();
};

const fetchData = async () => {
  loading.value = true;
  try {
    const { data, total } = await getUsers({
      skip: (pagination.current - 1) * pagination.pageSize,
      take: pagination.pageSize,
    });
    dataSource.value = data;
    pagination.total = total;
  } finally {
    loading.value = false;
  }
};
```

## 项目结构

```
src/
├── api/            # API 接口
├── assets/         # 静态资源
├── components/     # 公共组件
├── composables/    # 组合式函数
├── directives/     # 自定义指令
├── layouts/        # 布局组件
├── router/         # 路由配置
├── stores/         # Pinia 状态
├── styles/         # 全局样式
├── types/          # TypeScript 类型
├── utils/          # 工具函数
└── views/          # 页面组件
    ├── auth/       # 认证相关
    ├── users/      # 用户管理
    ├── school/     # 学校管理
    └── contests/   # 竞赛管理
```

## 常用脚本

```bash
# 开发
pnpm dev

# 构建
pnpm build

# 预览
pnpm preview

# 代码检查
pnpm lint
```
