查看關鍵文件,整理項目規範文檔。

[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 組件簡化