整理项目规范文档

查看关键文件,整理项目规范文档。

[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 组件简化
posted @ 2025-12-23 15:15  XiaoZhengTou  阅读(38)  评论(0)    收藏  举报