b1dd60ab6e
- 创建 AGENTS.md(前端编码规范、开发流程、Git 提交规范) - 创建 .opencode/workspace/frontend.json(前端工作区配置) - 更新 .gitignore
542 lines
11 KiB
Markdown
542 lines
11 KiB
Markdown
# rui-frontend AGENTS.md
|
||
|
||
> **睿核科技前端项目** — Vue 3 + TypeScript 前端工程
|
||
> **版本**: v1.0
|
||
> **更新日期**: 2026-06-04
|
||
|
||
---
|
||
|
||
## 一、项目概览
|
||
|
||
### 1.1 项目信息
|
||
|
||
| 属性 | 内容 |
|
||
|------|------|
|
||
| **项目名称** | rui-frontend |
|
||
| **项目类型** | Vue 3 前端工程(多项目管理)|
|
||
| **仓库地址** | https://gitee.com/rui/rui-frontend |
|
||
| **包管理器** | pnpm |
|
||
| **构建工具** | Vite |
|
||
|
||
### 1.2 仓库结构
|
||
|
||
```
|
||
rui-frontend/
|
||
├── admin-ui/ # 管理后台系统
|
||
│ ├── src/
|
||
│ │ ├── api/ # API 接口
|
||
│ │ ├── assets/ # 静态资源
|
||
│ │ ├── components/ # 公共组件
|
||
│ │ ├── composables/ # 组合式函数
|
||
│ │ ├── layouts/ # 布局组件
|
||
│ │ ├── locales/ # 国际化
|
||
│ │ ├── router/ # 路由配置
|
||
│ │ ├── service/ # 服务层(API 调用)
|
||
│ │ ├── stores/ # Pinia 状态管理
|
||
│ │ ├── styles/ # 全局样式
|
||
│ │ ├── types/ # 类型定义
|
||
│ │ ├── utils/ # 工具函数
|
||
│ │ └── views/ # 页面视图
|
||
│ ├── package.json
|
||
│ └── vite.config.ts
|
||
│
|
||
├── cashier-mobile/ # 收银系统移动端(待开发)
|
||
├── customer-mobile/ # 收银系统顾客端(待开发)
|
||
├── package.json # 根 package.json
|
||
├── pnpm-workspace.yaml # pnpm 工作区配置
|
||
└── README.md # 项目说明
|
||
```
|
||
|
||
### 1.3 技术栈
|
||
|
||
| 组件 | 版本 | 说明 |
|
||
|------|------|------|
|
||
| Vue | 3.5+ | 前端框架 |
|
||
| TypeScript | 5.4+ | 类型系统 |
|
||
| Vite | 5.x | 构建工具 |
|
||
| Element Plus | 2.9+ | UI 组件库(admin-ui)|
|
||
| Pinia | 2.2+ | 状态管理 |
|
||
| Vue Router | 4.4+ | 路由管理 |
|
||
| Axios | 1.7+ | HTTP 客户端 |
|
||
| pnpm | 8.x | 包管理器 |
|
||
|
||
---
|
||
|
||
## 二、编码规范
|
||
|
||
### 2.1 命名规范
|
||
|
||
| 类型 | 规范 | 示例 |
|
||
|------|------|------|
|
||
| **组件文件** | PascalCase | `UserForm.vue`, `OrderList.vue` |
|
||
| **组合式函数** | camelCase, use 前缀 | `useUser.ts`, `usePermission.ts` |
|
||
| **工具函数** | camelCase | `formatDate.ts`, `deepClone.ts` |
|
||
| **常量** | UPPER_SNAKE_CASE | `API_BASE_URL`, `DEFAULT_PAGE_SIZE` |
|
||
| **类型定义** | PascalCase, 后缀 Type | `UserType`, `OrderFormType` |
|
||
| **接口定义** | PascalCase, 前缀 I | `IUser`, `IOrder` |
|
||
| **枚举** | PascalCase, 后缀 Enum | `StatusEnum`, `GenderEnum` |
|
||
|
||
### 2.2 Vue 组件规范
|
||
|
||
#### 文件结构
|
||
|
||
```vue
|
||
<script setup lang="ts">
|
||
// 1. 类型导入
|
||
import type { UserType } from '@/types'
|
||
|
||
// 2. Vue 核心导入
|
||
import { ref, computed, onMounted } from 'vue'
|
||
|
||
// 3. 第三方库
|
||
import { ElMessage } from 'element-plus'
|
||
|
||
// 4. 本地模块
|
||
import { useUserStore } from '@/stores/user'
|
||
import { formatDate } from '@/utils/date'
|
||
|
||
// 5. 组合式函数
|
||
const userStore = useUserStore()
|
||
|
||
// 6. 类型定义
|
||
interface Props {
|
||
userId: number
|
||
}
|
||
|
||
// 7. Props & Emits
|
||
const props = defineProps<Props>()
|
||
const emit = defineEmits<{
|
||
submit: [data: UserType]
|
||
}>()
|
||
|
||
// 8. 响应式数据
|
||
const userList = ref<UserType[]>([])
|
||
const loading = ref(false)
|
||
|
||
// 9. 计算属性
|
||
const userCount = computed(() => userList.value.length)
|
||
|
||
// 10. 方法
|
||
async function fetchUserList() {
|
||
loading.value = true
|
||
try {
|
||
// API 调用
|
||
} catch (error) {
|
||
ElMessage.error('获取用户列表失败')
|
||
} finally {
|
||
loading.value = false
|
||
}
|
||
}
|
||
|
||
// 11. 生命周期
|
||
onMounted(() => {
|
||
fetchUserList()
|
||
})
|
||
</script>
|
||
|
||
<template>
|
||
<div class="user-list">
|
||
<!-- 模板内容 -->
|
||
</div>
|
||
</template>
|
||
|
||
<style scoped lang="scss">
|
||
.user-list {
|
||
// 样式
|
||
}
|
||
</style>
|
||
```
|
||
|
||
#### 组件编写原则
|
||
|
||
- **使用 `<script setup>`**:简洁、类型友好
|
||
- **使用 TypeScript**:所有组件必须 `lang="ts"`
|
||
- ** Props 必须定义类型**:使用 `defineProps<Props>()`
|
||
- **Emit 必须定义类型**:使用 `defineEmits<{}>()`
|
||
- **避免直接使用 any**:必须定义类型
|
||
|
||
### 2.3 API 服务层规范
|
||
|
||
```typescript
|
||
// service/userService.ts
|
||
import request from '@/utils/request'
|
||
import type { UserType, PageResult } from '@/types'
|
||
|
||
export const UserService = {
|
||
// 查询列表
|
||
getList(params: PageParams) {
|
||
return request.get<PageResult<UserType>>('/user/admin/list', { params })
|
||
},
|
||
|
||
// 查询详情
|
||
getById(id: number) {
|
||
return request.get<UserType>(`/user/admin/${id}`)
|
||
},
|
||
|
||
// 新增
|
||
create(data: UserFormType) {
|
||
return request.post('/user/admin', data)
|
||
},
|
||
|
||
// 修改
|
||
update(id: number, data: UserFormType) {
|
||
return request.put(`/user/admin/${id}`, data)
|
||
},
|
||
|
||
// 删除
|
||
delete(id: number) {
|
||
return request.delete(`/user/admin/${id}`)
|
||
}
|
||
}
|
||
```
|
||
|
||
**原则**:
|
||
- 使用对象封装相关 API
|
||
- 返回类型必须明确
|
||
- 统一错误处理在 request 拦截器中
|
||
|
||
### 2.4 请求工具封装
|
||
|
||
```typescript
|
||
// utils/request.ts
|
||
import axios from 'axios'
|
||
import { ElMessage } from 'element-plus'
|
||
|
||
const request = axios.create({
|
||
baseURL: import.meta.env.VITE_API_BASE_URL,
|
||
timeout: 10000
|
||
})
|
||
|
||
// 请求拦截器
|
||
request.interceptors.request.use(
|
||
(config) => {
|
||
const token = localStorage.getItem('token')
|
||
if (token) {
|
||
config.headers.Authorization = `Bearer ${token}`
|
||
}
|
||
return config
|
||
}
|
||
)
|
||
|
||
// 响应拦截器
|
||
request.interceptors.response.use(
|
||
(response) => {
|
||
const { code, msg, data } = response.data
|
||
if (code === 200) {
|
||
return data
|
||
}
|
||
ElMessage.error(msg || '请求失败')
|
||
return Promise.reject(new Error(msg))
|
||
},
|
||
(error) => {
|
||
ElMessage.error(error.message || '网络错误')
|
||
return Promise.reject(error)
|
||
}
|
||
)
|
||
|
||
export default request
|
||
```
|
||
|
||
### 2.5 状态管理(Pinia)
|
||
|
||
```typescript
|
||
// stores/user.ts
|
||
import { defineStore } from 'pinia'
|
||
import { ref, computed } from 'vue'
|
||
import type { UserType } from '@/types'
|
||
|
||
export const useUserStore = defineStore('user', () => {
|
||
// State
|
||
const userInfo = ref<UserType | null>(null)
|
||
const token = ref('')
|
||
|
||
// Getters
|
||
const isLoggedIn = computed(() => !!token.value)
|
||
|
||
// Actions
|
||
function setUserInfo(user: UserType) {
|
||
userInfo.value = user
|
||
}
|
||
|
||
function logout() {
|
||
userInfo.value = null
|
||
token.value = ''
|
||
}
|
||
|
||
return {
|
||
userInfo,
|
||
token,
|
||
isLoggedIn,
|
||
setUserInfo,
|
||
logout
|
||
}
|
||
})
|
||
```
|
||
|
||
**原则**:
|
||
- 使用 Setup Store 风格(函数式)
|
||
- State 使用 `ref()`
|
||
- Getters 使用 `computed()`
|
||
- Actions 使用普通函数
|
||
|
||
### 2.6 样式规范
|
||
|
||
- 使用 **UnoCSS** 原子化 CSS(已配置)
|
||
- 复杂样式使用 **SCSS**
|
||
- 组件样式使用 `<style scoped>`
|
||
- 全局样式放在 `styles/` 目录
|
||
|
||
```vue
|
||
<!-- 推荐:原子化 CSS -->
|
||
<template>
|
||
<div class="flex items-center justify-between p-4 bg-white rounded">
|
||
<span class="text-lg font-bold">标题</span>
|
||
<el-button type="primary">按钮</el-button>
|
||
</div>
|
||
</template>
|
||
|
||
<!-- 复杂组件使用 SCSS -->
|
||
<style scoped lang="scss">
|
||
.user-form {
|
||
&__header {
|
||
@apply flex items-center justify-between;
|
||
border-bottom: 1px solid #eee;
|
||
}
|
||
}
|
||
</style>
|
||
```
|
||
|
||
---
|
||
|
||
## 三、目录规范
|
||
|
||
### 3.1 新增页面步骤
|
||
|
||
1. 在 `views/` 下创建目录和文件
|
||
2. 在 `router/` 下添加路由配置
|
||
3. 在 `service/` 下添加 API(如需要)
|
||
4. 在 `types/` 下添加类型(如需要)
|
||
|
||
### 3.2 组件分类
|
||
|
||
| 位置 | 用途 | 示例 |
|
||
|------|------|------|
|
||
| `components/common/` | 全局通用组件 | `RuiTable.vue`, `IconPicker.vue` |
|
||
| `views/{module}/` | 页面级组件 | `views/user/Index.vue` |
|
||
| `views/{module}/components/` | 页面私有组件 | `views/user/components/UserForm.vue` |
|
||
|
||
---
|
||
|
||
## 四、开发流程
|
||
|
||
### 4.1 新增功能流程
|
||
|
||
```
|
||
1. 确认后端接口已就绪(Swagger 文档)
|
||
2. 创建类型定义(types/)
|
||
3. 创建 API 服务(service/)
|
||
4. 创建页面组件(views/)
|
||
5. 配置路由(router/)
|
||
6. 联调测试
|
||
7. 提交代码
|
||
```
|
||
|
||
### 4.2 与后端协作
|
||
|
||
1. **需要新接口**:
|
||
- 在 spring-ai 仓库创建 `[API-REQ]` Issue
|
||
- 等待后端实现并回复 Swagger 地址
|
||
- 根据 Swagger 开发前端
|
||
|
||
2. **接口变更**:
|
||
- 关注后端 Issue 更新
|
||
- 及时更新前端 service/
|
||
|
||
---
|
||
|
||
## 五、Git 提交规范
|
||
|
||
### 5.1 提交格式
|
||
|
||
```
|
||
type(scope): 中文描述
|
||
|
||
示例:
|
||
feat(user): 添加用户列表页面
|
||
fix(order): 修复订单金额显示错误
|
||
docs(readme): 更新项目说明
|
||
style(css): 优化表格样式
|
||
```
|
||
|
||
### 5.2 Type 类型
|
||
|
||
| 类型 | 说明 |
|
||
|------|------|
|
||
| `feat` | 新功能 |
|
||
| `fix` | 修复 Bug |
|
||
| `docs` | 文档更新 |
|
||
| `style` | 代码格式(不影响功能)|
|
||
| `refactor` | 重构 |
|
||
| `perf` | 性能优化 |
|
||
| `test` | 测试相关 |
|
||
| `chore` | 构建/工具链 |
|
||
|
||
### 5.3 Scope 范围
|
||
|
||
| Scope | 说明 |
|
||
|-------|------|
|
||
| `admin-ui` | 管理后台 |
|
||
| `cashier` | 收银系统 |
|
||
| `common` | 公共代码 |
|
||
| `deps` | 依赖更新 |
|
||
|
||
---
|
||
|
||
## 六、环境配置
|
||
|
||
### 6.1 环境变量
|
||
|
||
```bash
|
||
# .env.development
|
||
VITE_API_BASE_URL=http://localhost:8080
|
||
VITE_APP_TITLE=睿核管理系统
|
||
|
||
# .env.production
|
||
VITE_API_BASE_URL=https://api.vifo.cc
|
||
VITE_APP_TITLE=睿核管理系统
|
||
```
|
||
|
||
### 6.2 代理配置
|
||
|
||
```typescript
|
||
// vite.config.ts
|
||
server: {
|
||
proxy: {
|
||
'/api': {
|
||
target: 'http://localhost:8080',
|
||
changeOrigin: true
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 七、性能优化
|
||
|
||
### 7.1 代码分割
|
||
|
||
```typescript
|
||
// 路由懒加载
|
||
const UserList = () => import('@/views/user/Index.vue')
|
||
|
||
// 组件懒加载
|
||
const Dialog = defineAsyncComponent(() => import('./Dialog.vue'))
|
||
```
|
||
|
||
### 7.2 资源优化
|
||
|
||
- 图片使用 WebP 格式
|
||
- 大组件使用异步加载
|
||
- 使用 CDN 加载第三方库(生产环境)
|
||
|
||
---
|
||
|
||
## 八、测试规范
|
||
|
||
### 8.1 单元测试
|
||
|
||
```bash
|
||
# 待配置 Vitest
|
||
```
|
||
|
||
### 8.2 E2E 测试
|
||
|
||
```bash
|
||
# 待配置 Playwright
|
||
```
|
||
|
||
---
|
||
|
||
## 九、OpenCode 使用规范
|
||
|
||
### 9.1 启动方式
|
||
|
||
```bash
|
||
cd /Users/zhangsheng/rhkj/rui-frontend
|
||
opencode
|
||
```
|
||
|
||
### 9.2 启动提示词
|
||
|
||
```
|
||
你现在进入【前端开发模式】。
|
||
|
||
工作目录:/Users/zhangsheng/rhkj/rui-frontend
|
||
技术栈:Vue 3、TypeScript、Element Plus、Vite、pnpm
|
||
规则:
|
||
1. 只能修改前端项目目录下的代码
|
||
2. 需要后端接口时,提醒用户创建 Gitee Issue
|
||
3. 遵循本文档的编码规范
|
||
4. 使用 pnpm,不要混用 npm/yarn
|
||
|
||
当前任务:【描述具体任务】
|
||
```
|
||
|
||
### 9.3 禁止事项
|
||
|
||
- ❌ 修改 backend/ 或 app/ 目录下的代码
|
||
- ❌ 使用 npm/yarn(必须使用 pnpm)
|
||
- ❌ 提交 node_modules/ 到 Git
|
||
- ❌ 在代码中写死 API 地址(使用环境变量)
|
||
|
||
---
|
||
|
||
## 十、相关文档
|
||
|
||
- [项目 README](../README.md)
|
||
- [后端项目规范](../../spring-ai/AGENTS.md)
|
||
- [跨团队协作规范](../../spring-ai/docs/cross-team-workflow.md)
|
||
- [OpenCode 操作指南](../../spring-ai/docs/opencode-workflow.md)
|
||
|
||
---
|
||
|
||
## 十一、附录
|
||
|
||
### 11.1 常用命令
|
||
|
||
```bash
|
||
# 安装依赖
|
||
pnpm install
|
||
|
||
# 启动开发服务器
|
||
pnpm dev:admin
|
||
|
||
# 构建
|
||
pnpm build:admin
|
||
|
||
# 类型检查
|
||
pnpm type-check
|
||
|
||
# 代码检查
|
||
pnpm lint
|
||
|
||
# 安装子项目依赖
|
||
cd admin-ui && pnpm install
|
||
```
|
||
|
||
### 11.2 错误码对照
|
||
|
||
| 错误码 | 说明 |
|
||
|--------|------|
|
||
| 200 | 成功 |
|
||
| 400 | 请求参数错误 |
|
||
| 401 | 未授权 |
|
||
| 403 | 无权限 |
|
||
| 404 | 资源不存在 |
|
||
| 500 | 服务器内部错误 |
|
||
|
||
---
|
||
|
||
> **提示**:本文档是活文档,根据项目发展持续更新。如有建议请提交 PR。
|