查看關鍵文件,整理項目規範文檔。
[6 tools called]
整理四個規範文件內容:
[3 tools called]
四個規範文件內容如下:
1. .cursor/team-rules.md
# 團隊開發規則
## 核心原則
- 簡潔直接,避免冗餘
- 代碼優先,註釋僅複雜邏輯
- 統一規範,保持一致性
- 性能優先,用户體驗至上
## 技術棧
- **框架**: Vue 3 + TypeScript + Vite
- **狀態管理**: Pinia
- **路由**: Vue Router 4
- **UI庫**: @gcommon/gcommon-ui
- **圖表**: ECharts 5
- **樣式**: SCSS
- **工具庫**: lodash, date-fns, moment
- **代碼規範**: ESLint + Prettier
## 項目結構
src/
├── views/ # 頁面組件(按業務模塊劃分)
├── components/ # 公共組件
│ └── CommonComp/ # 通用業務組件(圖表、表格等)
├── services/ # API 服務層
├── utils/ # 工具函數
├── stores/ # Pinia 狀態管理
├── router/ # 路由配置
├── locales/ # 國際化(i18n)
└── assets/ # 靜態資源
## 快速規則
### 組件開發
- 使用 `defineComponent` + JSX (tsx)
- Composition API (`setup`)
- Props 必須類型定義
- 組件名 PascalCase,文件名一致
### 代碼風格
- 單引號,無分號(Prettier 配置)
- 行寬 100 字符
- TypeScript strict 模式關閉(項目配置)
- 避免 `any`,優先具體類型
### API 調用
- 統一使用 `services/` 目錄
- 使用 `useRequest` / `useTableRequest` hooks
- 錯誤處理在 axios 攔截器
### 狀態管理
- Pinia stores 放在 `stores/`
- 避免組件直接修改 store
- 使用 actions 處理異步
### 性能
- 路由懶加載
- 大組件按需加載
- 圖表監聽 resize 事件
- 大數據虛擬列表
## 禁止事項
- ❌ 生產代碼禁止 `console.log`
- ❌ 禁止使用 `v-html`(XSS 風險)
- ❌ 禁止硬編碼配置
- ❌ 禁止在循環中創建組件
## 詳細規範
查看 [code-conventions.md](./code-conventions.md)
## AI 協作
查看 [ai-prompt-templates.md](./ai-prompt-templates.md)
## 項目上下文
查看 [project-context.md](./project-context.md)
2. .cursor/code-conventions.md
# 編碼規範
## TypeScript
### 類型定義
```tsx
// ✅ 優先 interface
interface UserInfo {
id: number
name: string
}
// ✅ Props 類型
props: {
title: {
type: String,
required: true
},
data: {
type: Array as PropType<UserInfo[]>,
default: () => []
}
}
類型使用
- 避免
any,使用unknown或具體類型 - 函數參數必須類型標註
- 返回值類型明確標註
Vue 組件
組件結構
import { defineComponent, reactive, onMounted, ref } from 'vue'
import './index.scss'
export default defineComponent({
name: 'ComponentName',
props: {
title: {
type: String,
required: true
}
},
setup(props, { emit }) {
const state = reactive({
loading: false,
data: []
})
const chartRef = ref(null)
onMounted(() => {
// 初始化
})
return () => (
<div class="component-name">
{/* JSX 內容 */}
</div>
)
}
})
響應式數據
// ✅ 對象使用 reactive
const state = reactive({
count: 0,
list: []
})
// ✅ 基本類型使用 ref
const loading = ref(false)
const chartRef = ref<HTMLDivElement | null>(null)
// ✅ 解構使用 toRefs
const { data, loading } = toRefs(state)
Props 規範
- 必須定義類型
- required 明確標註
- default 值合理設置
- 複雜類型使用
PropType
事件處理
// ✅ emit 事件
emit('change', { value: 123 })
// ✅ 事件名 kebab-case
emit('update-value', data)
樣式規範
SCSS 使用
// ✅ 組件樣式文件與組件同目錄
.component-name {
padding: 16px;
&__header {
font-size: 16px;
}
&--active {
color: #409eff;
}
}
類名規範
- BEM 命名:
block__element--modifier - 或 kebab-case:
component-name - 避免全局樣式污染
API 服務
服務函數
// ✅ services/xxx.ts
import axios from '../utils/axios'
import { brandMap } from '../utils/zutils_z'
export async function getUserInfo(params: any) {
const { brand_name } = params
return axios.post(`/${brandMap[brand_name]}/getUserInfo`, params)
}
使用 Hooks
// ✅ 普通請求
const { data, loading, run } = useRequest(getUserInfo)
// ✅ 表格請求
const { state, run } = useTableRequest(getTableData)
圖表組件
ECharts 使用
// ✅ 使用 ChartRender 組件
<ChartRender
option={chartOption}
height="400px"
handleClick={handleChartClick}
/>
// ✅ 自定義圖表組件
const chartRef = ref<HTMLDivElement | null>(null)
const chartInstance = ref<ECharts | null>(null)
onMounted(() => {
if (chartRef.value) {
chartInstance.value = echarts.init(chartRef.value)
}
})
onBeforeUnmount(() => {
window.removeEventListener('resize', handleResize)
chartInstance.value?.dispose()
})
圖表響應式
- 監聽
window.resize事件 - 使用
_.throttle節流 - 組件卸載時
dispose()
狀態管理
Pinia Store
// ✅ stores/xxx.ts
import { defineStore } from 'pinia'
export const useXxxStore = defineStore('xxx', {
state: () => ({
value: false
}),
actions: {
setValue(value: boolean) {
this.value = value
}
}
})
Store 使用
// ✅ 在組件中使用
import { useXxxStore } from '@/stores/xxx'
const store = useXxxStore()
store.setValue(true)
工具函數
工具函數規範
// ✅ utils/xxx.ts
/**
* 格式化 NPS 數據
* @param nps - NPS 值
* @returns 格式化後的字符串
*/
export const formatNps = (nps: number | null | undefined): string => {
return nps !== null && nps !== undefined
? `${nps === 0 ? '0' : nps}%`
: ''
}
工具庫使用
- 日期:
date-fns/moment - 工具:
lodash/lodash-es - 避免重複造輪子
路由
路由配置
// ✅ 懶加載
{
path: '/UserProfile',
name: 'UserProfile',
component: () => import('../views/UserProfile')
}
路由命名
- 路由名 PascalCase
- meta 字段存儲頁面信息
命名規範
文件命名
- 組件:PascalCase (
UserProfile.tsx) - 工具:camelCase (
formatDate.ts) - 服務:PascalCase (
UserService.ts)
變量命名
- 變量/函數:camelCase
- 常量:UPPER_SNAKE_CASE
- 組件:PascalCase
- 類型/接口:PascalCase(I 前綴可選)
註釋規範
JSDoc
/**
* 獲取用户信息
* @param userId - 用户ID
* @returns 用户信息對象
*/
export async function getUserInfo(userId: number) {
// ...
}
代碼註釋
- 複雜邏輯必須註釋
- 避免冗餘註釋
- 使用中文註釋
Git 提交
提交格式
<type>(<scope>): <subject>
<body>
類型
feat: 新功能fix: 修復refactor: 重構style: 樣式chore: 構建/工具docs: 文檔perf: 性能優化
示例
feat(views): 添加用户畫像頁面
- 新增用户畫像數據展示
- 集成 ECharts 圖表組件
## 3. `.cursor/ai-prompt-templates.md`
```markdown
# AI 提示詞模板
## 組件開發模板
### 創建新組件
創建一個 Vue 3 組件 [組件名],要求:
- 使用 defineComponent + JSX (tsx)
- Props: [列出 props 及類型]
- 功能: [描述功能]
- 樣式: SCSS,使用 BEM 命名
- 參考項目現有組件風格
### 修改現有組件
修改 [組件路徑] 組件:
- 添加 [功能描述]
- 保持現有代碼風格
- 確保類型安全
- 添加必要的註釋
## API 集成模板
### 創建 API 服務
在 services/ 目錄創建 [服務名].ts:
- 使用 axios 工具(src/utils/axios.ts)
- 函數命名:動詞開頭(get/update/create/delete)
- 參數類型定義
- 參考現有 services 文件結構
### 使用 API
在 [組件路徑] 中集成 API:
- 使用 useRequest 或 useTableRequest hook
- 處理 loading 狀態
- 錯誤處理(已在 axios 攔截器)
- 參考 src/views/ChnRetailNps/index.tsx
## 圖表開發模板
### 創建圖表組件
創建 ECharts 圖表組件:
- 使用 ChartRender 組件或自定義
- 響應式處理(監聽 resize)
- 組件卸載時 dispose
- 參考 src/components/CommonComp/ChartRender.tsx
### 圖表配置
配置 ECharts 圖表:
- 圖表類型: [bar/line/pie/scatter]
- 數據格式: [描述數據結構]
- 交互需求: [點擊、縮放等]
- 參考項目現有圖表實現
## 樣式開發模板
### 添加樣式
為 [組件名] 添加樣式:
- 使用 SCSS
- BEM 命名規範
- 響應式設計
- 參考 src/assets/styles/common.scss
## 重構模板
### 代碼重構
重構 [文件/功能]:
- 保持功能不變
- 優化代碼結構
- 提升類型安全
- 遵循項目規範
## 調試模板
### 問題排查
排查 [問題描述]:
- 相關文件: [列出文件路徑]
- 錯誤信息: [如有]
- 預期行為: [描述]
- 實際行為: [描述]
## 性能優化模板
### 性能優化
優化 [組件/功能] 性能:
- 當前問題: [描述]
- 優化目標: [描述]
- 參考項目性能優化實踐
- 確保不影響功能
## 類型定義模板
### 添加類型
為 [功能/組件] 添加 TypeScript 類型:
- 參考 src/components/EbdTable/EbdTable.d.ts
- 使用 interface 定義
- 導出類型供其他文件使用
## 國際化模板
### 添加多語言
添加 [功能] 的國際化支持:
- 中文: [文本]
- 英文: [文本]
- 使用 vue-i18n
- 參考 src/locales/lang/zh-CN.ts
## 狀態管理模板
### 創建 Store
創建 Pinia store [store名]:
- state: [描述狀態]
- actions: [描述操作]
- 參考 src/stores/switchStore.ts
## 工具函數模板
### 創建工具函數
創建工具函數 [函數名]:
- 功能: [描述]
- 參數類型: [類型]
- 返回值類型: [類型]
- 添加 JSDoc 註釋
- 放在 utils/ 目錄
## 常用提示詞
### 代碼審查
審查以下代碼是否符合項目規範:
[代碼片段]
### 代碼解釋
解釋以下代碼的功能和實現邏輯:
[代碼片段]
### 最佳實踐
在項目中實現 [功能] 的最佳實踐是什麼?
參考項目現有實現
4. .cursor/project-context.md
# 項目上下文
## 項目概述
**ipd-nps-web** - NPS(Net Promoter Score)數據分析平台
## 技術架構
### 核心技術棧
- **Vue 3.5.13** - Composition API
- **TypeScript 5.7.3** - 類型系統(strict 模式關閉)
- **Vite 6.1.1** - 構建工具
- **Pinia 3.0.1** - 狀態管理
- **Vue Router 4.5.0** - 路由
- **ECharts 5.2.2** - 圖表庫
- **@gcommon/gcommon-ui 3.5.3** - UI 組件庫
### 構建配置
- **Base URL**: `/nps/`
- **代碼分割**: 手動分包(vue/lodash/echarts/vendor)
- **資源內聯**: < 4KB
- **CSS 分割**: 啓用
- **代理配置**: `/api`, `/qlyServer`, `/external`
## 項目結構詳解
### Views(頁面)
views/
├── ChnRetailNps/ #
│ ├── Overall/ #
│ ├── Online/ #
│ ├── Offline/ #
│ └── BrowsePurchase/ #
├── ChnServiceNps/ #
├── SalesServiceNps/ #
├── ProductMonthly/ #
├── RetailMonthly/ #
└── IndustryNps/ #
### Components(組件)
components/
├── CommonComp/ # 通用業務組件
│ ├── ChartRender.tsx # 圖表渲染器
│ ├── BarChart.tsx # 柱狀圖
│ ├── EbdTable/ # 表格組件
│ └── ...
├── EbdTable/ # 表格組件(導出)
└── Pine/ # 圖表容器
### Services(API)
- 按業務模塊劃分文件
- 統一使用 `axios` 工具
- 函數命名:動詞開頭
- 使用 `brandMap` 映射品牌
### Utils(工具)
- **axios.ts** - HTTP 請求封裝
- **assist.ts** - 通用工具函數
- **bhooks.ts** - Vue Hooks(useRequest, useTableRequest)
- **eventBus.ts** - 事件總線
- **zutils_z.ts** - 業務工具函數
### Stores(狀態)
- **switchStore.ts** - 開關狀態
- **phoneType.ts** - 手機類型
## 核心功能
### 數據可視化
- ECharts 圖表集成
- 響應式圖表(監聽 resize)
- 圖表交互(點擊、縮放)
### 數據表格
- EbdTable 組件(基於 el-table)
- 支持樹形結構
- 分頁功能
- 自定義列渲染
### 國際化
- vue-i18n
- 支持中文/英文
- 語言檢測(URL 參數 > Cookie > 瀏覽器)
### 性能監控
- RUM(Real User Monitoring)
- 集成 @heytap/cloud-observation-rum
- 自動上報性能數據
## 關鍵工具函數
### useRequest
```tsx
const { data, loading, run } = useRequest(apiFunction)
useTableRequest
const { state, run } = useTableRequest(apiFunction)
// state: { data, loading, pagination }
EventBus
// 訂閲
$eventBus.on('eventName', callback)
// 發佈
$eventBus.emit('eventName', data)
// 取消訂閲
$eventBus.off('eventName', callback)
樣式系統
全局樣式
src/assets/styles/common.scss- 通用樣式src/assets/styles/gcommon-ui.scss- UI 庫樣式src/assets/main.css- 主樣式
組件樣式
- 組件目錄下
index.scss - BEM 或 kebab-case 命名
環境配置
環境變量
public/env.js- 運行時環境配置window.env.baseURL- API 基礎路徑window.env.rumCollectionUrl- RUM 收集地址
語言檢測
// URL 參數: ?locale=zh
// Cookie: lang
// 瀏覽器默認語言
路由配置
路由結構
- 懶加載:
() => import('../views/xxx') - meta 字段:
keepAlive等 - 路由名:PascalCase
主要路由
/ProductMonthly/ChnRetailNps/ChnServiceNps/SalesServiceNps/IndustryNps
數據流
API 調用流程
組件 → useRequest/useTableRequest → services → axios → 後端
狀態管理流程
組件 → Pinia Store → Actions → State
事件通信
組件 A → EventBus.emit → EventBus.on → 組件 B
業務邏輯
NPS 計算
- 使用
formatNps工具函數格式化 - 顯示格式:
${nps}%
品牌映射
- 使用
brandMap(zutils_z.ts) - API 路徑動態構建
數據篩選
- 級聯選擇器(Cascader)
- 多選/單選組件
- 日期範圍選擇
性能優化
已實現
- 路由懶加載
- 代碼分割(手動分包)
- 圖表 resize 節流
- 資源內聯(小文件)
建議優化
- 大數據虛擬列表
- 圖片懶加載
- 組件按需加載
開發工具
VS Code 插件
- Volar(Vue 3 支持)
- ESLint
- Prettier
- TypeScript Vue Plugin
腳本命令
npm run dev # 開發
npm run build # 構建
npm run lint # 代碼檢查
npm run type-check # 類型檢查
常見問題
TypeScript 類型
- 項目 strict 模式關閉
- 使用
any需謹慎 - 類型定義在
.d.ts文件
組件通信
- 父子:Props + Emit
- 跨組件:EventBus
- 全局狀態:Pinia
圖表問題
- 必須監聽 resize
- 組件卸載時 dispose
- 使用 ChartRender 組件簡化