coder-common-thin-frontend/CLAUDE.md
Leo 031efe042e docs(claude): 修复Vue组件代码块排布顺序说明
- 修正组件文件结构规范中的代码块排布顺序说明
- 将错误的 template → script → style 更正为 script → template → style
- 移除代码块语言标识避免ESLint解析错误
2025-07-06 19:01:45 +08:00

600 lines
19 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
### 第一部分:核心编程原则 (Guiding Principles)
这是我们合作的顶层思想,指导所有具体的行为。
可读性优先 (Readability First):始终牢记“代码是写给人看的,只是恰好机器可以执行”。清晰度高于一切。
DRY (Don't Repeat Yourself):绝不复制代码片段。通过抽象(如函数、类、模块)来封装和复用通用逻辑。
高内聚,低耦合 (High Cohesion, Low Coupling):功能高度相关的代码应该放在一起(高内聚),而模块之间应尽量减少依赖(低耦合),以增强模块独立性和可维护性。
### 第二部分:具体执行指令 (Actionable Instructions)
这是 Claude 在日常工作中需要严格遵守的具体操作指南。
沟通与语言规范
默认语言:请默认使用简体中文进行所有交流、解释和思考过程的陈述。
代码与术语:所有代码实体(变量名、函数名、类名等)及技术术语(如库名、框架名、设计模式等)必须保持英文原文。
注释规范:代码注释应使用中文。
批判性反馈与破框思维 (Critical Feedback & Out-of-the-Box Thinking)
审慎分析:必须以审视和批判的眼光分析我的输入,主动识别潜在的问题、逻辑谬误或认知偏差。
坦率直言:需要明确、直接地指出我思考中的盲点,并提供显著超越我当前思考框架的建议,以挑战我的预设。
严厉质询 (Tough Questioning):当我提出的想法或方案明显不合理、过于理想化或偏离正轨时,必须使用更直接、甚至尖锐的言辞进行反驳和质询,帮我打破思维定式,回归理性。
开发与调试策略 (Development & Debugging Strategy)
坚韧不拔的解决问题 (Tenacious Problem-Solving):当面对编译错误、逻辑不通或多次尝试失败时,绝不允许通过简化或伪造实现来“绕过”问题。
逐个击破 (Incremental Debugging):必须坚持对错误和问题进行逐一分析、定位和修复。
### 探索有效替代方案 (Explore Viable Alternatives):如果当前路径确实无法走通,应切换到另一个逻辑完整、功能健全的替代方案来解决问题,而不是退回到一个简化的、虚假的版本。
禁止伪造实现 (No Fake Implementations):严禁使用占位符逻辑(如空的循环)、虚假数据或不完整的函数来伪装功能已经实现。所有交付的代码都必须是意图明确且具备真实逻辑的。
战略性搁置 (Strategic Postponement):只有当一个问题被证实非常困难,且其当前优先级不高时,才允许被暂时搁置。搁置时,必须以 TODO 形式在代码中或任务列表中明确标记,并清晰说明遇到的问题。在核心任务完成后,必须回过头来重新审视并解决这些被搁置的问题。
规范化测试文件管理 (Standardized Test File Management):严禁为新功能在根目录或不相关位置创建孤立的测试文件。在添加测试时,必须首先检查项目中已有的测试套件(通常位于 tests/ 目录下),并将新的测试用例整合到与被测模块最相关的现有测试文件中。只有当确实没有合适的宿主文件时,才允许在 tests/ 目录下创建符合项目命名规范的新测试文件。
项目与代码维护 (Project & Code Maintenance)
统一文档维护 (Unified Documentation Maintenance):严禁为每个独立任务(如重构、功能实现)创建新的总结文档(例如 CODE_REFACTORING_SUMMARY.md。在任务完成后必须优先检查项目中已有的相关文档如 README.md、既有的设计文档等并将新的总结、变更或补充内容直接整合到现有文档中维护其完整性和时效性。
及时清理 (Timely Cleanup):在完成开发任务时,如果发现任何已无用(过时)的代码、文件或注释,应主动提出清理建议。
## 项目概述
Nova Admin 是一个基于 Vue3、Vite5、TypeScript 和 Naive UI 的简洁后台管理模板,实现了完整的认证、权限管理、路由管理等功能。
## 常用命令
### 开发环境
```bash
# 启动开发服务器 (端口 9980)
pnpm dev
# 不同环境启动
pnpm dev:test # 测试环境
pnpm dev:prod # 生产环境
```
### 构建项目
```bash
# 生产环境构建
pnpm build
# 不同环境构建
pnpm build:dev # 开发环境
pnpm build:test # 测试环境
```
### 代码检查
```bash
# 运行 ESLint 检查和类型检查
pnpm lint
# 自动修复代码问题
pnpm lint:fix
# 检查 ESLint 配置
pnpm lint:check
```
### 其他工具
```bash
# 预览构建结果 (端口 9981)
pnpm preview
# 查看打包体积分析
pnpm sizecheck
```
## 项目架构
### 核心技术栈
- **Vue 3.5.16** + **Composition API**
- **Vite 6.3.5** 构建工具
- **TypeScript 5.8.3** 类型安全
- **Naive UI 2.41.1** 组件库
- **Pinia 3.0.3** 状态管理
- **Vue Router 4.5.1** 路由管理
- **UnoCSS 66.2.0** 原子化CSS
- **Alova 3.3.2** HTTP客户端
### 目录结构要点
```
src/
├── store/ # Pinia状态管理
│ ├── auth.ts # 认证状态(登录、用户信息)
│ ├── router/ # 路由状态和菜单管理
│ ├── tab.ts # 标签页状态
│ └── app/ # 应用全局状态
├── router/ # 路由配置
│ ├── index.ts # 路由实例
│ ├── guard.ts # 路由守卫
│ ├── routes.inner.ts # 内置路由(登录、错误页等)
│ └── routes.static.ts # 静态路由配置
├── views/ # 页面组件
├── layouts/ # 布局组件
├── components/ # 通用组件
├── service/ # API服务层
│ ├── api/ # 接口定义
│ └── http/ # HTTP配置
├── hooks/ # 组合式函数
├── utils/ # 工具函数
├── typings/ # 类型定义
└── constants/ # 常量定义
```
## 核心系统架构
### 1. 认证系统
- 基于JWT Token的认证机制
- 支持双TokenAccessToken + RefreshToken
- 自动Token刷新和过期处理
- 本地存储管理localStorage
**关键文件**:
- `src/store/auth.ts` - 认证状态管理
- `src/views/login/` - 登录页面组件
- `src/service/api/login.ts` - 登录API接口
### 2. 权限系统
- 基于角色的访问控制RBAC
- 多层权限验证路由级、组件级、API级
- 权限指令 `v-permission` 和组合函数 `usePermission`
- 支持super角色绕过所有权限检查
**关键文件**:
- `src/hooks/usePermission.ts` - 权限验证组合函数
- `src/directives/permission.ts` - 权限指令
### 3. 路由系统
- 支持静态路由和动态路由
- 路由守卫实现权限验证
- 自动菜单生成和路由缓存
- 多种布局模式支持
**关键文件**:
- `src/router/guard.ts` - 路由守卫逻辑
- `src/store/router/` - 路由状态管理
- `src/store/router/helper.ts` - 路由处理工具函数
### 4. 状态管理
- 使用Pinia进行状态管理
- 支持状态持久化
- 模块化状态设计
**状态模块**:
- `authStore` - 用户认证状态
- `routeStore` - 路由和菜单状态
- `tabStore` - 标签页状态
- `appStore` - 应用全局状态
## 重要配置文件
### 环境配置
- 支持多环境配置dev、test、prod
- 环境变量通过 `.env.*` 文件管理
- 服务配置通过 `service.config.ts` 统一管理
### 路由配置
- 通过 `VITE_ROUTE_LOAD_MODE` 控制路由加载模式
- 静态路由配置在 `src/router/routes.static.ts`
- 动态路由通过API从后端获取
### 权限配置
- 角色类型super、admin、user、editor
- 权限验证支持单角色和多角色
- 默认无权限要求时直接通过
## 📝 命名规范(强制要求)
**1. 接口函数命名**
- 查询列表:`getList`, `get列表名List`
- 新增:`add项名`, `create项名`
- 修改:`update项名`, `edit项名`
- 删除:`delete项名`, `remove项名`
- 详情:`get项名ById`, `get项名Detail`
**2. 类型定义命名**
- 请求参数:`项名Bo` (Business Object)
- 响应数据:`项名Vo` (View Object)
- 查询参数:`项名QueryBo`
- 分页结果:`Page项名Vo`
**3. 枚举命名**
- 全大写,下划线分隔:`USER_LIST`, `ADD_USER`, `UPDATE_USER`
## ⚠️ 严格禁止事项
**1. 消息提示**
```typescript
// ❌ 严禁使用Element Plus原生消息
// ✅ 必须使用项目封装的消息函数
import { coiMsgError, coiMsgSuccess } from '@/utils/coi.ts'
ElMessage.success('操作成功')
this.$message.error('操作失败')
coiMsgSuccess('操作成功')
coiMsgError('操作失败')
```
**2. 类型定义**
```typescript
// ❌ 严禁使用any类型
const response: any = await getList()
// ✅ 必须使用完整的类型定义
const response: Result<ResponseVo[]> = await getList()
```
**3. 数据访问**
```typescript
// ❌ 错误的数据访问
const data = response
// ✅ 正确的数据访问
const data = response.data
```
### 消息提示规范
**强制使用 coi.ts 封装的消息提示方法**,严禁直接使用 Element Plus 的消息提示:
- **消息提示**:使用 `coiMsg`、`coiMsgSuccess`、`coiMsgError`、`coiMsgWarning`、`coiMsgInfo`
- **通知提示**:使用 `coiNotice`、`coiNoticeSuccess`、`coiNoticeError`、`coiNoticeWarning`、`coiNoticeInfo`
- **确认对话框**:使用 `coiMsgBox`、`coiMsgBoxHtml`、`coiMsgBoxAlert`
- **输入对话框**:使用 `coiMsgBoxPrompt`
```typescript
// 正确示例
import { coiMsgBox, coiMsgError, coiMsgSuccess } from '@/utils/coi'
// 成功提示
coiMsgSuccess('操作成功')
// 错误提示
coiMsgError('操作失败')
// 确认对话框
coiMsgBox('确定要删除吗?', '删除确认').then(() => {
// 确认操作
}).catch(() => {
// 取消操作
})
```
## 开发注意事项
### 添加新页面
1.`src/views/` 创建页面组件
2.`src/router/routes.static.ts` 添加路由配置
3. 配置权限要求roles字段
### 添加新API
1.`src/service/api/` 定义接口
2. 使用项目封装的alova实例
3. 遵循统一的响应处理格式
## 📁 API文件组织规范强制要求
**API文件必须按功能模块组织严格按模块导入严禁聚合导出或混合不同业务模块的API**
### 文件结构规范
```
src/service/api/
├── auth/ # 认证相关API
│ └── index.ts # 登录、注册、验证码等认证API
├── system/ # 系统管理模块
│ ├── user/index.ts # 用户管理API
│ ├── role/index.ts # 角色管理API
│ ├── menu/index.ts # 菜单管理API
│ └── ...
└── ...
```
### API模块创建规则
1. **模块化原则**: 每个业务功能模块必须创建独立的目录和文件
2. **统一导出**: 每个模块目录必须有 `index.ts` 文件导出所有API
3. **直接导入**: 必须从具体的模块路径导入API禁止聚合导出
4. **明确导入**: 导入路径必须明确指向具体的功能模块
### 示例正确的API组织和导入方式
```typescript
// src/service/api/auth/index.ts
// 页面中的正确导入方式
import {
fetchCaptchaPng,
fetchLogin,
fetchLogout
} from '@/service/api/auth'
import {
addUser,
getUserList,
updateUser
} from '@/service/api/system/user'
import {
assignUserRole,
getRoleList
} from '@/service/api/system/role'
import {
fetchUserRoutes
} from '@/service/api/system/menu'
export function fetchLogin(data: LoginRequest) { /* ... */ }
export function fetchLogout() { /* ... */ }
export function fetchCaptchaPng() { /* ... */ }
// src/service/api/system/user/index.ts
export interface UserQueryBo { /* ... */ }
export interface UserVo { /* ... */ }
export function getUserList(params: UserQueryBo) { /* ... */ }
export function addUser(data: UserVo) { /* ... */ }
```
### 强制要求
- ✅ 每个API模块独立维护和导入
- ✅ 导入路径指向具体功能模块
- ✅ 按功能拆分API到不同模块目录
- ✅ 类型定义与API函数放在同一模块目录下
### 严格禁止行为
- ❌ 创建 `system.ts` 等聚合导出文件
- ❌ 在单一文件中混合多个业务模块的API
- ❌ 从聚合文件导入API (如 `from '@/service/api/system'`)
- ❌ 创建功能不明确的API文件
- ❌ 在页面组件中重复定义类型应从API模块导入
## 📝 类型定义组织规范(强制要求)
**类型定义必须与API模块对应按功能模块组织禁止在页面组件中重复定义类型**
### 类型文件组织原则
1. **就近原则**: 类型定义与使用它们的API函数在同一模块
2. **单一职责**: 每个types.ts文件只包含一个业务模块的类型
3. **统一导出**: API模块的index.ts必须重新导出types.ts中的类型
4. **禁止重复**: 页面组件不得重复定义已有类型
### 正确的类型组织示例
```typescript
// src/service/api/system/user/types.ts
// src/service/api/system/user/index.ts
import type { UserQueryBo, UserSearchForm, UserVo } from './types'
// 页面组件中的正确使用方式
import {
getUserList
} from '@/service/api/system/user'
import type { UserSearchForm, UserVo } from '@/service/api/system/user'
export interface UserVo {
userId: number
loginName: string
userName: string
// ...其他字段
}
export interface UserQueryBo {
pageNo?: number
pageSize?: number
loginName?: string
// ...其他查询条件
}
export interface UserSearchForm {
loginName?: string
userName?: string
timeRange?: [number, number] | null
// ...其他搜索字段
}
// 重新导出类型供外部使用
export type { UserQueryBo, UserSearchForm, UserVo } from './types'
// API函数定义
export function getUserList(params: UserQueryBo) { /* ... */ }
// 使用统一类型,不重复定义
const tableData = ref<UserVo[]>([])
const searchForm = ref<UserSearchForm>({})
```
### 类型命名规范
- **请求参数类型**: `实体名QueryBo`, `实体名CreateBo`, `实体名UpdateBo`
- **响应数据类型**: `实体名Vo`
- **分页结果类型**: `Page实体名Vo`
- **表单类型**: `实体名SearchForm`, `实体名Form`
### 状态管理
1. 新增状态优先考虑使用现有store
2. 需要持久化的状态使用pinia-plugin-persist
3. 计算属性优先使用computed缓存
### 组件开发
1. 优先使用Naive UI组件
2. 自定义组件放在 `src/components/`
3. 使用TypeScript定义组件Props和Emits
## 🔥 自定义弹框组件规范(强制要求)
**在开发任何新页面或功能时,如果需要使用弹框/模态框,必须使用项目封装的 NovaDialog 组件,严禁使用 Naive UI 原生的 n-modal 组件。**
### NovaDialog 组件位置
- 组件文件:`src/components/common/NovaDialog.vue`
- 这是项目专门封装的统一弹框组件
### 使用方式
#### 1. 导入组件
```typescript
import NovaDialog from '@/components/common/NovaDialog.vue'
```
#### 2. 创建弹框引用
```typescript
// 为每个弹框创建独立的引用
const userDialogRef = ref()
const editDialogRef = ref()
const deleteDialogRef = ref()
```
#### 3. 模板中使用
```vue
<template>
<!-- 用户表单弹框示例 -->
<NovaDialog
ref="userDialogRef"
:title="modalTitle"
:width="800"
height="auto"
confirm-text="确定"
cancel-text="取消"
@nova-confirm="handleSubmit"
@nova-cancel="handleCancel"
>
<template #content>
<div class="px-3 py-2">
<!-- 弹框内容 -->
<n-form ref="formRef" :model="formData">
<!-- 表单内容 -->
</n-form>
</div>
</template>
</NovaDialog>
<!-- 仅查看类弹框示例无确认按钮 -->
<NovaDialog
ref="viewDialogRef"
title="查看详情"
:width="600"
height="auto"
cancel-text="关闭"
:show-confirm="false"
@nova-cancel="handleClose"
>
<template #content>
<div class="p-3">
<!-- 查看内容 -->
</div>
</template>
</NovaDialog>
</template>
```
#### 4. 控制弹框显示/隐藏
```typescript
// 显示弹框
function handleAdd() {
modalTitle.value = '新增用户'
// 初始化表单数据
formData.value = { /* ... */ }
userDialogRef.value?.novaOpen()
}
// 隐藏弹框
function handleCancel() {
userDialogRef.value?.novaClose()
}
// 提交成功后关闭弹框
async function handleSubmit() {
try {
await submitForm()
coiMsgSuccess('操作成功')
userDialogRef.value?.novaClose()
}
catch (error) {
coiMsgError('操作失败')
}
}
```
### NovaDialog 核心属性
| 属性 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| title | string | '' | 弹框标题 |
| width | number | 500 | 弹框宽度(px) |
| height | string | 'auto' | 弹框高度 |
| confirm-text | string | '确定' | 确认按钮文字 |
| cancel-text | string | '取消' | 取消按钮文字 |
| show-confirm | boolean | true | 是否显示确认按钮 |
| show-cancel | boolean | true | 是否显示取消按钮 |
### NovaDialog 核心事件
| 事件 | 说明 |
|------|------|
| @nova-confirm | 点击确认按钮时触发 |
| @nova-cancel | 点击取消按钮时触发 |
### NovaDialog 核心方法
| 方法 | 说明 |
|------|------|
| novaOpen() | 显示弹框 |
| novaClose() | 隐藏弹框 |
### 插槽支持
| 插槽 | 说明 |
|------|------|
| #header | 自定义弹框头部内容 |
| #content | 弹框主体内容(必需) |
### 已完成的集成示例
- ✅ 角色管理页面:`src/views/system/role/index.vue`
- ✅ 用户管理页面:`src/views/system/user/index.vue`
### 严格禁止行为
- ❌ 使用 `n-modal` 组件创建新弹框
- ❌ 使用 `v-model:show` 控制弹框显示/隐藏
- ❌ 忽略 NovaDialog 组件直接使用原生弹框
### 为什么必须使用 NovaDialog
1. **统一用户体验**:确保所有弹框具有一致的视觉风格和交互行为
2. **维护便利性**:统一的组件便于后续样式调整和功能增强
3. **团队协作**统一的组件API减少开发人员的学习成本
4. **质量保证**封装的组件经过充分测试避免重复开发和潜在bug
## 📝 Vue3组件文件结构规范强制要求
**所有Vue3组件必须严格按照以下顺序组织代码块**
### 组件代码块排布顺序
```
<!-- Vue 组件文件结构示例 -->
<script setup lang="ts">
// 脚本内容
</script>
<template>
<!-- 模板内容 -->
</template>
<style scoped>
/* 样式内容 */
</style>
```
### 强制要求
- ✅ 必须按照 `script``template``style` 的顺序排布
- ✅ 使用 `<script setup lang="ts">` 语法
- ✅ 样式块使用 `scoped` 属性确保样式隔离
- ✅ 每个代码块之间保持一个空行间隔
### 严格禁止行为
- ❌ 任何其他顺序的代码块排布
- ❌ 使用 `<script>` 而非 `<script setup>`
- ❌ 省略 `lang="ts"` 属性
- ❌ 在全局组件中省略 `scoped` 属性
## 文档资源
项目包含完整的文档系统:
- `doc/auth-system.md` - 认证系统文档
- `doc/permission-system.md` - 权限系统文档
- `doc/router-system.md` - 路由系统文档
- `doc/architecture.md` - 整体架构文档
## API接口
项目使用ApiFox进行接口Mock在线文档https://nova-admin.apifox.cn
## 开发环境要求
- Node.js 21.x
- pnpm 10.x
- 现代浏览器支持ES6+