368 lines
8.4 KiB
Markdown
368 lines
8.4 KiB
Markdown
# CLAUDE.md
|
||
|
||
本文件为 Claude Code (claude.ai/code) 提供本项目代码开发指导。
|
||
|
||
## 项目简介
|
||
|
||
**意心AI** - 基于 Vue 3.5 + TypeScript 开发的企业级 AI 聊天应用模板,仿豆包/通义 AI 平台。支持流式对话、AI 模型库、文件上传、Mermaid 图表渲染等功能。
|
||
|
||
## 技术栈
|
||
|
||
- **框架**: Vue 3.5+ (Composition API) + TypeScript 5.8+
|
||
- **构建工具**: Vite 6.3+
|
||
- **UI 组件**: Element Plus 2.10.4 + vue-element-plus-x 1.3.7
|
||
- **状态管理**: Pinia 3.0 + pinia-plugin-persistedstate
|
||
- **HTTP 请求**: hook-fetch(支持流式/SSE,替代 Axios)
|
||
- **CSS**: UnoCSS + SCSS
|
||
- **路由**: Vue Router 4
|
||
|
||
## 常用命令
|
||
|
||
```bash
|
||
# 安装依赖(必须用 pnpm)
|
||
pnpm install
|
||
|
||
# 启动开发服务器(端口 17001)
|
||
pnpm dev
|
||
|
||
# 生产构建
|
||
pnpm build
|
||
|
||
# 预览生产构建
|
||
pnpm preview
|
||
|
||
# 代码检查与修复
|
||
pnpm lint # ESLint 检查
|
||
pnpm fix # ESLint 自动修复
|
||
pnpm lint:stylelint # 样式检查
|
||
|
||
# 规范提交(使用 cz-git)
|
||
pnpm cz
|
||
```
|
||
|
||
## 如何新增页面
|
||
|
||
### 1. 创建页面文件
|
||
|
||
页面文件统一放在 `src/pages/` 目录下:
|
||
|
||
```
|
||
src/pages/
|
||
├── chat/ # 功能模块文件夹
|
||
│ ├── index.vue # 父级布局页
|
||
│ ├── conversation/ # 子页面文件夹
|
||
│ │ └── index.vue # 子页面
|
||
│ └── image/
|
||
│ └── index.vue
|
||
├── console/
|
||
│ └── index.vue
|
||
└── your-page/ # 新增页面在这里创建
|
||
└── index.vue
|
||
```
|
||
|
||
**单页面示例** (`src/pages/your-page/index.vue`):
|
||
|
||
```vue
|
||
<template>
|
||
<div class="your-page">
|
||
<h1>页面标题</h1>
|
||
</div>
|
||
</template>
|
||
|
||
<script setup lang="ts">
|
||
// 自动导入 Vue API,无需手动 import
|
||
const route = useRoute()
|
||
const router = useRouter()
|
||
|
||
// 如需使用状态管理
|
||
const userStore = useUserStore()
|
||
|
||
onMounted(() => {
|
||
console.log('页面加载')
|
||
})
|
||
</script>
|
||
|
||
<style scoped lang="scss">
|
||
.your-page {
|
||
padding: 20px;
|
||
}
|
||
</style>
|
||
```
|
||
|
||
### 2. 配置路由
|
||
|
||
路由配置在 `src/routers/modules/staticRouter.ts`。
|
||
|
||
**新增独立页面**(添加到 `layoutRouter` 的 children 中):
|
||
|
||
```typescript
|
||
{
|
||
path: 'your-page', // URL 路径,最终为 /your-page
|
||
name: 'yourPage', // 路由名称,必须唯一
|
||
component: () => import('@/pages/your-page/index.vue'),
|
||
meta: {
|
||
title: '页面标题', // 页面标题,会显示在浏览器标签
|
||
keepAlive: 0, // 是否缓存页面:0=缓存,1=不缓存
|
||
isDefaultChat: false, // 是否为默认聊天页
|
||
layout: 'default', // 布局类型:default/blankPage
|
||
},
|
||
}
|
||
```
|
||
|
||
**新增带子路由的功能模块**:
|
||
|
||
```typescript
|
||
{
|
||
path: 'module-name',
|
||
name: 'moduleName',
|
||
component: () => import('@/pages/module-name/index.vue'), // 父级布局页
|
||
redirect: '/module-name/sub-page', // 默认重定向
|
||
meta: {
|
||
title: '模块标题',
|
||
icon: 'HomeFilled', // Element Plus 图标名称
|
||
},
|
||
children: [
|
||
{
|
||
path: 'sub-page',
|
||
name: 'subPage',
|
||
component: () => import('@/pages/module-name/sub-page/index.vue'),
|
||
meta: {
|
||
title: '子页面标题',
|
||
},
|
||
},
|
||
// 带参数的路由
|
||
{
|
||
path: 'detail/:id',
|
||
name: 'detailPage',
|
||
component: () => import('@/pages/module-name/detail/index.vue'),
|
||
meta: {
|
||
title: '详情页',
|
||
},
|
||
},
|
||
],
|
||
}
|
||
```
|
||
|
||
**无需布局的独立页面**(添加到 `staticRouter`):
|
||
|
||
```typescript
|
||
{
|
||
path: '/test/page',
|
||
name: 'testPage',
|
||
component: () => import('@/pages/test/page.vue'),
|
||
meta: {
|
||
title: '测试页面',
|
||
},
|
||
}
|
||
```
|
||
|
||
### 3. 页面 Meta 配置说明
|
||
|
||
| 属性 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| title | string | 页面标题,显示在浏览器标签页 |
|
||
| keepAlive | number | 0=缓存页面,1=不缓存 |
|
||
| layout | string | 布局类型:'default' 使用默认布局,'blankPage' 使用空白布局 |
|
||
| isDefaultChat | boolean | 是否为默认聊天页面 |
|
||
| icon | string | Element Plus 图标名称,用于菜单显示 |
|
||
| isHide | string | '0'=在菜单中隐藏,'1'=显示 |
|
||
| isKeepAlive | string | '0'=缓存,'1'=不缓存(字符串版) |
|
||
|
||
### 4. 布局说明
|
||
|
||
布局组件位于 `src/layouts/`:
|
||
|
||
- **default**: 默认布局,包含侧边栏、顶部导航等
|
||
- **blankPage**: 空白布局,仅包含路由出口
|
||
|
||
在路由 meta 中通过 `layout` 字段指定:
|
||
|
||
```typescript
|
||
meta: {
|
||
layout: 'default', // 使用默认布局(有侧边栏)
|
||
// 或
|
||
layout: 'blankPage', // 使用空白布局(全屏页面)
|
||
}
|
||
```
|
||
|
||
### 5. 页面跳转示例
|
||
|
||
```typescript
|
||
// 在 script setup 中使用
|
||
const router = useRouter()
|
||
|
||
// 跳转页面
|
||
router.push('/chat/conversation')
|
||
router.push({ name: 'chatConversation' })
|
||
router.push({ path: '/chat/conversation/:id', params: { id: '123' } })
|
||
|
||
// 获取路由参数
|
||
const route = useRoute()
|
||
console.log(route.params.id)
|
||
```
|
||
|
||
### 6. 完整新增页面示例
|
||
|
||
假设要新增一个"数据统计"页面:
|
||
|
||
**步骤 1**: 创建页面文件 `src/pages/statistics/index.vue`
|
||
|
||
```vue
|
||
<template>
|
||
<div class="statistics-page">
|
||
<el-card>
|
||
<template #header>
|
||
<span>数据统计</span>
|
||
</template>
|
||
<div>页面内容</div>
|
||
</el-card>
|
||
</div>
|
||
</template>
|
||
|
||
<script setup lang="ts">
|
||
const { data, loading } = useFetch('/api/statistics').get().json()
|
||
</script>
|
||
|
||
<style scoped lang="scss">
|
||
.statistics-page {
|
||
padding: 20px;
|
||
}
|
||
</style>
|
||
```
|
||
|
||
**步骤 2**: 在 `src/routers/modules/staticRouter.ts` 中添加路由
|
||
|
||
```typescript
|
||
{
|
||
path: 'statistics',
|
||
name: 'statistics',
|
||
component: () => import('@/pages/statistics/index.vue'),
|
||
meta: {
|
||
title: '意心Ai-数据统计',
|
||
keepAlive: 0,
|
||
isDefaultChat: false,
|
||
layout: 'default',
|
||
},
|
||
}
|
||
```
|
||
|
||
**步骤 3**: 在菜单中添加入口(如需要)
|
||
|
||
如需在侧边栏显示,需在相应的位置添加菜单配置。
|
||
|
||
## 核心架构说明
|
||
|
||
### HTTP 请求封装
|
||
|
||
位于 `src/utils/request.ts`,使用 hook-fetch:
|
||
|
||
```typescript
|
||
import { get, post, put, del } from '@/utils/request'
|
||
|
||
// GET 请求
|
||
const { data } = await get('/api/endpoint').json()
|
||
|
||
// POST 请求
|
||
const result = await post('/api/endpoint', { key: 'value' }).json()
|
||
```
|
||
|
||
特点:
|
||
- 自动附加 JWT Token 到请求头
|
||
- 自动处理 401/403 错误
|
||
- 支持 Server-Sent Events (SSE) 流式响应
|
||
|
||
### 状态管理
|
||
|
||
Pinia stores 位于 `src/stores/modules/`:
|
||
|
||
| Store | 用途 |
|
||
|-------|------|
|
||
| user.ts | 用户认证、登录状态 |
|
||
| chat.ts | 聊天消息、流式输出 |
|
||
| session.ts | 会话列表、当前会话 |
|
||
| model.ts | AI 模型配置 |
|
||
|
||
使用方式:
|
||
|
||
```typescript
|
||
const userStore = useUserStore()
|
||
userStore.setToken(token, refreshToken)
|
||
userStore.logout()
|
||
```
|
||
|
||
### 自动导入
|
||
|
||
项目已配置 `unplugin-auto-import`,以下 API 无需手动 import:
|
||
|
||
- Vue API: `ref`, `reactive`, `computed`, `watch`, `onMounted` 等
|
||
- Vue Router: `useRoute`, `useRouter`
|
||
- Pinia: `createPinia`, `storeToRefs`
|
||
- VueUse: `useFetch`, `useStorage` 等
|
||
|
||
### 路径别名
|
||
|
||
| 别名 | 对应路径 |
|
||
|------|----------|
|
||
| `@/` | `src/` |
|
||
| `@components/` | `src/vue-element-plus-y/components/` |
|
||
|
||
### 环境变量
|
||
|
||
开发配置在 `.env.development`:
|
||
|
||
```
|
||
VITE_WEB_BASE_API=/dev-api # API 前缀
|
||
VITE_API_URL=http://localhost:19001/api/app # 后端地址
|
||
VITE_SSO_SEVER_URL=http://localhost:18001 # SSO 地址
|
||
```
|
||
|
||
Vite 开发服务器会自动将 `/dev-api` 代理到后端 API。
|
||
|
||
## 代码规范
|
||
|
||
### 提交规范
|
||
|
||
使用 `pnpm cz` 进行规范提交,类型包括:
|
||
- `feat`: 新功能
|
||
- `fix`: 修复
|
||
- `docs`: 文档
|
||
- `style`: 代码格式
|
||
- `refactor`: 重构
|
||
- `perf`: 性能优化
|
||
- `test`: 测试
|
||
- `build`: 构建
|
||
- `ci`: CI/CD
|
||
- `revert`: 回滚
|
||
- `chore`: 其他
|
||
|
||
### Git Hooks
|
||
|
||
- **pre-commit**: 自动运行 ESLint 修复
|
||
- **commit-msg**: 校验提交信息格式
|
||
|
||
## 构建优化
|
||
|
||
Vite 配置中的代码分割策略(`vite.config.ts`):
|
||
|
||
| Chunk 名称 | 包含内容 |
|
||
|-----------|---------|
|
||
| vue-vendor | Vue 核心库、Vue Router |
|
||
| pinia | Pinia 状态管理 |
|
||
| element-plus | Element Plus UI 库 |
|
||
| markdown | Markdown 解析相关 |
|
||
| utils | Lodash、VueUse 工具库 |
|
||
| highlight | 代码高亮库 |
|
||
| echarts | 图表库 |
|
||
| pdf | PDF 处理库 |
|
||
|
||
## 后端集成
|
||
|
||
后端为 .NET 8 项目,本地启动命令:
|
||
|
||
```bash
|
||
cd E:\devDemo\Yi\Yi.Abp.Net8\src\Yi.Abp.Web
|
||
dotnet run
|
||
```
|
||
|
||
前端开发时,后端默认运行在 `http://localhost:19001`。
|