|
@@ -0,0 +1,602 @@
|
|
|
|
|
+# <!-- Powered by BMAD™ Core -->
|
|
|
|
|
+
|
|
|
|
|
+# Story 016.002: 搬迁配置和工具函数到独立模块并添加类型定义
|
|
|
|
|
+
|
|
|
|
|
+## Status
|
|
|
|
|
+
|
|
|
|
|
+Approved
|
|
|
|
|
+
|
|
|
|
|
+## Story
|
|
|
|
|
+
|
|
|
|
|
+**作为** 图表库开发者,
|
|
|
|
|
+**我想要** 将 u-charts 核心库中的配置和工具函数**搬迁**到独立模块并添加 TypeScript 类型定义,
|
|
|
|
|
+**以便** 提高代码的可维护性、可测试性和类型安全性,为后续 React 组件封装打下基础。
|
|
|
|
|
+
|
|
|
|
|
+## Acceptance Criteria
|
|
|
|
|
+
|
|
|
|
|
+1. `config.ts` 创建完成,包含 config、assign、util 并有完整类型注解
|
|
|
|
|
+2. `utils/` 目录下所有文件创建完成,每个函数都有类型注解
|
|
|
|
|
+3. 类型检查通过(pnpm typecheck),无 any 类型(除非必要)
|
|
|
|
|
+4. 每个文件控制在 500 行以内
|
|
|
|
|
+5. 代码逻辑与原始 u-charts.ts 完全一致
|
|
|
|
|
+
|
|
|
|
|
+## Tasks / Subtasks
|
|
|
|
|
+
|
|
|
|
|
+- [ ] Task 1: 分析配置和工具函数 (AC: 1, 2, 5)
|
|
|
|
|
+ - [ ] 1.1 识别 config、assign、util 等配置对象
|
|
|
|
|
+ - [ ] 1.2 识别颜色工具(hexToRgb等)
|
|
|
|
|
+ - [ ] 1.3 识别数学工具(findRange、normalInt等)
|
|
|
|
|
+ - [ ] 1.4 识别坐标转换工具(convertCoordinateOrigin等)
|
|
|
|
|
+ - [ ] 1.5 识别文本测量工具(measureText等)
|
|
|
|
|
+ - [ ] 1.6 识别碰撞检测工具(avoidCollision等)
|
|
|
|
|
+ - [ ] 1.7 识别其他工具函数(getH5Offset、isInAngleRange等)
|
|
|
|
|
+
|
|
|
|
|
+- [ ] Task 2: 创建模块化目录结构 (AC: 1, 2)
|
|
|
|
|
+ - [ ] 2.1 创建 `src/lib/config.ts`
|
|
|
|
|
+ - [ ] 2.2 创建 `src/lib/utils/` 目录
|
|
|
|
|
+ - [ ] 2.3 创建 `src/lib/utils/color.ts`
|
|
|
|
|
+ - [ ] 2.4 创建 `src/lib/utils/math.ts`
|
|
|
|
|
+ - [ ] 2.5 创建 `src/lib/utils/coordinate.ts`
|
|
|
|
|
+ - [ ] 2.6 创建 `src/lib/utils/text.ts`
|
|
|
|
|
+ - [ ] 2.7 创建 `src/lib/utils/collision.ts`
|
|
|
|
|
+ - [ ] 2.8 创建 `src/lib/utils/misc.ts`(其他工具函数)
|
|
|
|
|
+ - [ ] 2.9 创建 `src/lib/utils/index.ts` 统一导出
|
|
|
|
|
+
|
|
|
|
|
+- [ ] Task 3: **搬迁**配置对象并添加类型注解 (AC: 1, 3, 4, 5)
|
|
|
|
|
+ - [ ] 3.1 将 config 对象**搬迁**到 config.ts,添加类型注解
|
|
|
|
|
+ - [ ] 3.2 将 assign 函数**搬迁**到 config.ts,添加类型注解
|
|
|
|
|
+ - [ ] 3.3 将 util 对象**搬迁**到 config.ts,添加类型注解
|
|
|
|
|
+ - [ ] 3.4 为 config、assign、util 添加完整的 TypeScript 类型定义
|
|
|
|
|
+
|
|
|
|
|
+- [ ] Task 4: **搬迁**颜色工具函数并添加类型注解 (AC: 2, 3, 4, 5)
|
|
|
|
|
+ - [ ] 4.1 将 hexToRgb 函数**搬迁**到 utils/color.ts
|
|
|
|
|
+ - [ ] 4.2 为 hexToRgb 添加参数和返回值类型注解
|
|
|
|
|
+ - [ ] 4.3 导出函数并验证类型正确性
|
|
|
|
|
+
|
|
|
|
|
+- [ ] Task 5: **搬迁**数学工具函数并添加类型注解 (AC: 2, 3, 4, 5)
|
|
|
|
|
+ - [ ] 5.1 将 findRange 函数**搬迁**到 utils/math.ts
|
|
|
|
|
+ - [ ] 5.2 将 calCandleMA 函数**搬迁**到 utils/math.ts
|
|
|
|
|
+ - [ ] 5.3 为数学函数添加参数和返回值类型注解
|
|
|
|
|
+ - [ ] 5.4 导出函数并验证类型正确性
|
|
|
|
|
+
|
|
|
|
|
+- [ ] Task 6: **搬迁**坐标转换工具函数并添加类型注解 (AC: 2, 3, 4, 5)
|
|
|
|
|
+ - [ ] 6.1 将 convertCoordinateOrigin 函数**搬迁**到 utils/coordinate.ts
|
|
|
|
|
+ - [ ] 6.2 将 isInAngleRange 函数**搬迁**到 utils/coordinate.ts
|
|
|
|
|
+ - [ ] 6.3 为坐标转换函数添加参数和返回值类型注解
|
|
|
|
|
+ - [ ] 6.4 定义坐标点、中心点等类型接口
|
|
|
|
|
+ - [ ] 6.5 导出函数和类型并验证类型正确性
|
|
|
|
|
+
|
|
|
|
|
+- [ ] Task 7: **搬迁**文本测量工具函数并添加类型注解 (AC: 2, 3, 4, 5)
|
|
|
|
|
+ - [ ] 7.1 将 measureText 函数**搬迁**到 utils/text.ts
|
|
|
|
|
+ - [ ] 7.2 为 measureText 添加参数和返回值类型注解
|
|
|
|
|
+ - [ ] 7.3 定义文本度量相关类型接口
|
|
|
|
|
+ - [ ] 7.4 导出函数和类型并验证类型正确性
|
|
|
|
|
+
|
|
|
|
|
+- [ ] Task 8: **搬迁**碰撞检测工具函数并添加类型注解 (AC: 2, 3, 4, 5)
|
|
|
|
|
+ - [ ] 8.1 将 avoidCollision 函数**搬迁**到 utils/collision.ts
|
|
|
|
|
+ - [ ] 8.2 将 util.isCollision 函数**搬迁**到 utils/collision.ts
|
|
|
|
|
+ - [ ] 8.3 为碰撞检测函数添加参数和返回值类型注解
|
|
|
|
|
+ - [ ] 8.4 定义碰撞对象类型接口
|
|
|
|
|
+ - [ ] 8.5 导出函数和类型并验证类型正确性
|
|
|
|
|
+
|
|
|
|
|
+- [ ] Task 9: **搬迁**其他工具函数并添加类型注解 (AC: 2, 3, 4, 5)
|
|
|
|
|
+ - [ ] 9.1 将 getH5Offset 函数**搬迁**到 utils/misc.ts
|
|
|
|
|
+ - [ ] 9.2 将 createCurveControlPoints 函数**搬迁**到 utils/misc.ts
|
|
|
|
|
+ - [ ] 9.3 将 calValidDistance 函数**搬迁**到 utils/misc.ts
|
|
|
|
|
+ - [ ] 9.4 将 getTouches 函数**搬迁**到 utils/misc.ts
|
|
|
|
|
+ - [ ] 9.5 为其他工具函数添加参数和返回值类型注解
|
|
|
|
|
+ - [ ] 9.6 定义相关类型接口
|
|
|
|
|
+ - [ ] 9.7 导出函数和类型并验证类型正确性
|
|
|
|
|
+
|
|
|
|
|
+- [ ] Task 10: 更新导出和验证搬迁结果 (AC: 1, 2, 3, 5)
|
|
|
|
|
+ - [ ] 10.1 更新 src/lib/utils/index.ts 统一导出所有工具函数
|
|
|
|
|
+ - [ ] 10.2 更新 src/index.ts 导出新模块
|
|
|
|
|
+ - [ ] 10.3 运行类型检查验证所有类型注解正确
|
|
|
|
|
+ - [ ] 10.4 确保所有工具函数正确导出
|
|
|
|
|
+ - [ ] 10.5 确认代码逻辑与原始文件完全一致
|
|
|
|
|
+ - [ ] 10.6 验证每个文件控制在 500 行以内
|
|
|
|
|
+
|
|
|
|
|
+## Dev Notes
|
|
|
|
|
+
|
|
|
|
|
+### 前置故事见解
|
|
|
|
|
+
|
|
|
|
|
+**故事 016.001 完成状态**:
|
|
|
|
|
+- ✅ 已创建 `mini-charts` 包基础结构
|
|
|
|
|
+- ✅ 已迁移 u-charts 核心库到 `src/lib/u-charts.ts`(7680行代码)
|
|
|
|
|
+- ✅ 包可以成功构建和类型检查通过
|
|
|
|
|
+- ⚠️ 使用 `@ts-nocheck` 绕过原始库中的类型问题
|
|
|
|
|
+- ⚠️ 存在变量重复声明问题(将在本故事中通过模块化解决)
|
|
|
|
|
+
|
|
|
|
|
+**故事 016.001 关键技术决策**:
|
|
|
|
|
+- 使用 `@ts-nocheck` 绕过原始 u-charts 库的类型问题
|
|
|
|
|
+- 修复了 `process` 变量与 Node.js 全局对象的冲突(重命名为 `chartProcess`)
|
|
|
|
|
+- 修复了 `uChartsEvent` 类语法问题
|
|
|
|
|
+- 保留了原始 u-charts 库的所有功能逻辑
|
|
|
|
|
+
|
|
|
|
|
+**迁移策略**: 保持 u-charts 核心绘制逻辑不变,渐进式模块化并添加类型定义
|
|
|
|
|
+
|
|
|
|
|
+### 技术栈要求
|
|
|
|
|
+
|
|
|
|
|
+**来源**: [tech-stack.md](../../architecture/tech-stack.md)
|
|
|
|
|
+
|
|
|
|
|
+- **TypeScript**: 5.4.5 [来源: tech-stack.md]
|
|
|
|
|
+- **React**: 18.0.0(mini 包使用 React 18,不是 React 19)[来源: 故事 016.001 Dev Notes]
|
|
|
|
|
+- **Taro**: 4.1.4 [来源: tech-stack.md]
|
|
|
|
|
+- **Node.js**: 20.18.3(运行时环境)[来源: tech-stack.md]
|
|
|
|
|
+- **包管理器**: pnpm workspace [来源: source-tree.md]
|
|
|
|
|
+
|
|
|
|
|
+### 项目结构指南
|
|
|
|
|
+
|
|
|
|
|
+**来源**: [source-tree.md](../../architecture/source-tree.md)
|
|
|
|
|
+
|
|
|
|
|
+```
|
|
|
|
|
+mini-ui-packages/
|
|
|
|
|
+└── mini-charts/ # mini-charts 包
|
|
|
|
|
+ ├── src/
|
|
|
|
|
+ │ ├── index.ts # 主入口文件
|
|
|
|
|
+ │ └── lib/
|
|
|
|
|
+ │ ├── u-charts.ts # u-charts 核心库(7680行)
|
|
|
|
|
+ │ ├── config.ts # [新增] 配置对象
|
|
|
|
|
+ │ └── utils/ # [新增] 工具函数目录
|
|
|
|
|
+ │ ├── index.ts # 工具函数统一导出
|
|
|
|
|
+ │ ├── color.ts # 颜色工具函数
|
|
|
|
|
+ │ ├── math.ts # 数学工具函数
|
|
|
|
|
+ │ ├── coordinate.ts # 坐标转换工具
|
|
|
|
|
+ │ ├── text.ts # 文本测量工具
|
|
|
|
|
+ │ ├── collision.ts # 碰撞检测工具
|
|
|
|
|
+ │ └── misc.ts # 其他工具函数
|
|
|
|
|
+ ├── tests/
|
|
|
|
|
+ │ └── u-charts.test.ts
|
|
|
|
|
+ ├── package.json
|
|
|
|
|
+ ├── tsconfig.json
|
|
|
|
|
+ └── jest.config.cjs
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### TypeScript 配置规范
|
|
|
|
|
+
|
|
|
|
|
+**来源**: [ui-package-standards.md](../../architecture/ui-package-standards.md#typescript配置)
|
|
|
|
|
+
|
|
|
|
|
+```json
|
|
|
|
|
+{
|
|
|
|
|
+ "compilerOptions": {
|
|
|
|
|
+ "target": "ES2020",
|
|
|
|
|
+ "lib": ["DOM", "DOM.Iterable", "ES2020"],
|
|
|
|
|
+ "module": "ESNext",
|
|
|
|
|
+ "skipLibCheck": true,
|
|
|
|
|
+ "moduleResolution": "bundler",
|
|
|
|
|
+ "allowImportingTsExtensions": true,
|
|
|
|
|
+ "resolveJsonModule": true,
|
|
|
|
|
+ "isolatedModules": true,
|
|
|
|
|
+ "noEmit": true,
|
|
|
|
|
+ "jsx": "react-jsx",
|
|
|
|
|
+ "strict": true,
|
|
|
|
|
+ "noUnusedLocals": true,
|
|
|
|
|
+ "noUnusedParameters": true,
|
|
|
|
|
+ "noFallthroughCasesInSwitch": true
|
|
|
|
|
+ },
|
|
|
|
|
+ "include": ["src"]
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+**本故事重要**: 需要移除 `@ts-nocheck`,为所有函数添加完整的类型注解,确保 `strict: true` 模式下无类型错误。
|
|
|
|
|
+
|
|
|
|
|
+### u-charts 源文件分析
|
|
|
|
|
+
|
|
|
|
|
+**来源**: [mini-charts/src/lib/u-charts.ts](../../mini-ui-packages/mini-charts/src/lib/u-charts.ts)
|
|
|
|
|
+
|
|
|
|
|
+**文件统计**:
|
|
|
|
|
+- 总行数: 7680 行
|
|
|
|
|
+- 导出函数: 约 60+ 个工具/数据处理函数
|
|
|
|
|
+
|
|
|
|
|
+**配置对象**:
|
|
|
|
|
+1. **config**: 默认配置对象,包含版本、颜色、字体等配置
|
|
|
|
|
+2. **assign**: 深度合并对象的函数
|
|
|
|
|
+3. **util**: 工具函数集合(toFixed、isFloat、approximatelyEqual、isSameSign、isSameXCoordinateArea、isCollision)
|
|
|
|
|
+
|
|
|
|
|
+**颜色工具函数**:
|
|
|
|
|
+- `hexToRgb(hexValue, opc)`: 十六进制颜色转 RGBA
|
|
|
|
|
+
|
|
|
|
|
+**数学工具函数**:
|
|
|
|
|
+- `findRange(num, type, limit)`: 计算数值范围
|
|
|
|
|
+- `calCandleMA(dayArr, nameArr, colorArr, kdata)`: 计算 K 线图移动平均线
|
|
|
|
|
+- `createCurveControlPoints(points, i)`: 创建曲线控制点
|
|
|
|
|
+
|
|
|
|
|
+**坐标转换工具函数**:
|
|
|
|
|
+- `convertCoordinateOrigin(x, y, center)`: 坐标原点转换
|
|
|
|
|
+- `isInAngleRange(angle, startAngle, endAngle)`: 判断角度是否在范围内
|
|
|
|
|
+- `calValidDistance(self, distance, chartData, config, opts)`: 计算有效滚动距离
|
|
|
|
|
+
|
|
|
|
|
+**文本测量工具函数**:
|
|
|
|
|
+- `measureText(text, fontSize, context)`: 测量文本宽度
|
|
|
|
|
+
|
|
|
|
|
+**碰撞检测工具函数**:
|
|
|
|
|
+- `avoidCollision(obj, target)`: 避免碰撞
|
|
|
|
|
+- `util.isCollision(obj1, obj2)`: 检测两个对象是否碰撞
|
|
|
|
|
+
|
|
|
|
|
+**其他工具函数**:
|
|
|
|
|
+- `getH5Offset(e)`: 兼容 H5 点击事件
|
|
|
|
|
+- `getTouches(touches, opts, e)`: 获取触摸点坐标
|
|
|
|
|
+- `dataCombine(series)`: 数据合并
|
|
|
|
|
+- `dataCombineStack(series, len)`: 堆叠数据合并
|
|
|
|
|
+- `fixPieSeries(series, opts, config)`: 修复饼图系列数据
|
|
|
|
|
+- `fillSeries(series, opts, config)`: 填充系列数据
|
|
|
|
|
+- `fillCustomColor(linearType, customColor, series, config)`: 填充自定义颜色
|
|
|
|
|
+- `getDataRange(minData, maxData)`: 获取数据范围
|
|
|
|
|
+
|
|
|
|
|
+### 类型定义规范
|
|
|
|
|
+
|
|
|
|
|
+**来源**: [ui-package-standards.md](../../architecture/ui-package-standards.md#类型定义规范)
|
|
|
|
|
+
|
|
|
|
|
+**本故事重要**: 必须为所有函数添加完整的类型注解,避免使用 `any` 类型(除非必要)。
|
|
|
|
|
+
|
|
|
|
|
+**类型定义示例**:
|
|
|
|
|
+
|
|
|
|
|
+```typescript
|
|
|
|
|
+// config.ts 类型定义示例
|
|
|
|
|
+export interface UChartsConfig {
|
|
|
|
|
+ version: string;
|
|
|
|
|
+ yAxisWidth: number;
|
|
|
|
|
+ xAxisHeight: number;
|
|
|
|
|
+ padding: [number, number, number, number];
|
|
|
|
|
+ rotate: boolean;
|
|
|
|
|
+ fontSize: number;
|
|
|
|
|
+ fontColor: string;
|
|
|
|
|
+ dataPointShape: string[];
|
|
|
|
|
+ color: string[];
|
|
|
|
|
+ linearColor: string[];
|
|
|
|
|
+ pieChartLinePadding: number;
|
|
|
|
|
+ pieChartTextPadding: number;
|
|
|
|
|
+ titleFontSize: number;
|
|
|
|
|
+ subtitleFontSize: number;
|
|
|
|
|
+ radarLabelTextMargin: number;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+export const config: UChartsConfig = {
|
|
|
|
|
+ version: 'v2.5.0-20230101',
|
|
|
|
|
+ yAxisWidth: 15,
|
|
|
|
|
+ // ... 其他配置
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+export function assign<T>(target: T, ...varArgs: Partial<T>[]): T {
|
|
|
|
|
+ // 实现逻辑
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+export interface Util {
|
|
|
|
|
+ toFixed(num: number, limit?: number): number | string;
|
|
|
|
|
+ isFloat(num: number): boolean;
|
|
|
|
|
+ approximatelyEqual(num1: number, num2: number): boolean;
|
|
|
|
|
+ isSameSign(num1: number, num2: number): boolean;
|
|
|
|
|
+ isSameXCoordinateArea(p1: Point, p2: Point): boolean;
|
|
|
|
|
+ isCollision(obj1: CollisionObject, obj2: CollisionObject): boolean;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+export const util: Util = {
|
|
|
|
|
+ toFixed: function toFixed(num, limit = 2) {
|
|
|
|
|
+ // 实现逻辑
|
|
|
|
|
+ },
|
|
|
|
|
+ // ... 其他工具函数
|
|
|
|
|
+};
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+```typescript
|
|
|
|
|
+// utils/color.ts 类型定义示例
|
|
|
|
|
+export interface RgbColor {
|
|
|
|
|
+ r: number;
|
|
|
|
|
+ g: number;
|
|
|
|
|
+ b: number;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+export function hexToRgb(hexValue: string, opc: number): string {
|
|
|
|
|
+ // 实现逻辑
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+```typescript
|
|
|
|
|
+// utils/math.ts 类型定义示例
|
|
|
|
|
+export function findRange(num: number, type?: 'upper' | 'lower', limit?: number): number {
|
|
|
|
|
+ // 实现逻辑
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+export interface CandleDataPoint {
|
|
|
|
|
+ [key: string]: number;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+export interface MASeriesItem {
|
|
|
|
|
+ data: (number | null)[];
|
|
|
|
|
+ name: string;
|
|
|
|
|
+ color: string;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+export function calCandleMA(
|
|
|
|
|
+ dayArr: number[],
|
|
|
|
|
+ nameArr: string[],
|
|
|
|
|
+ colorArr: string[],
|
|
|
|
|
+ kdata: CandleDataPoint[]
|
|
|
|
|
+): MASeriesItem[] {
|
|
|
|
|
+ // 实现逻辑
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+```typescript
|
|
|
|
|
+// utils/coordinate.ts 类型定义示例
|
|
|
|
|
+export interface Point {
|
|
|
|
|
+ x: number;
|
|
|
|
|
+ y: number;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+export interface Center {
|
|
|
|
|
+ x: number;
|
|
|
|
|
+ y: number;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+export function convertCoordinateOrigin(x: number, y: number, center: Center): Point {
|
|
|
|
|
+ // 实现逻辑
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+export function isInAngleRange(
|
|
|
|
|
+ angle: number,
|
|
|
|
|
+ startAngle: number,
|
|
|
|
|
+ endAngle: number
|
|
|
|
|
+): boolean {
|
|
|
|
|
+ // 实现逻辑
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+```typescript
|
|
|
|
|
+// utils/text.ts 类型定义示例
|
|
|
|
|
+export interface TextMeasure {
|
|
|
|
|
+ width: number;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+export function measureText(
|
|
|
|
|
+ text: string,
|
|
|
|
|
+ fontSize: number,
|
|
|
|
|
+ context: CanvasRenderingContext2D
|
|
|
|
|
+): TextMeasure {
|
|
|
|
|
+ // 实现逻辑
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+```typescript
|
|
|
|
|
+// utils/collision.ts 类型定义示例
|
|
|
|
|
+export interface CollisionObject {
|
|
|
|
|
+ start: Point;
|
|
|
|
|
+ end?: Point;
|
|
|
|
|
+ width: number;
|
|
|
|
|
+ height: number;
|
|
|
|
|
+ center?: Point;
|
|
|
|
|
+ area?: {
|
|
|
|
|
+ start: Point;
|
|
|
|
|
+ end: Point;
|
|
|
|
|
+ width: number;
|
|
|
|
|
+ height: number;
|
|
|
|
|
+ };
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+export interface Point {
|
|
|
|
|
+ x: number;
|
|
|
|
|
+ y: number;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+export function avoidCollision(
|
|
|
|
|
+ obj: CollisionObject,
|
|
|
|
|
+ target: CollisionObject[]
|
|
|
|
|
+): CollisionObject[] {
|
|
|
|
|
+ // 实现逻辑
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+export function isCollision(obj1: CollisionObject, obj2: CollisionObject): boolean {
|
|
|
|
|
+ // 实现逻辑(来自 util.isCollision)
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+```typescript
|
|
|
|
|
+// utils/misc.ts 类型定义示例
|
|
|
|
|
+export interface H5Event {
|
|
|
|
|
+ offsetX: number;
|
|
|
|
|
+ offsetY: number;
|
|
|
|
|
+ mp: {
|
|
|
|
|
+ changedTouches: Array<{ x: number; y: number }>;
|
|
|
|
|
+ };
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+export function getH5Offset(e: { offsetX: number; offsetY: number }): H5Event {
|
|
|
|
|
+ // 实现逻辑
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+export interface TouchPoint {
|
|
|
|
|
+ x: number;
|
|
|
|
|
+ y: number;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+export function getTouches(
|
|
|
|
|
+ touches: TouchPoint[],
|
|
|
|
|
+ opts: { width: number; area: number[] },
|
|
|
|
|
+ e: any
|
|
|
|
|
+): TouchPoint[] {
|
|
|
|
|
+ // 实现逻辑
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### 编码标准
|
|
|
|
|
+
|
|
|
|
|
+**来源**: [coding-standards.md](../../architecture/coding-standards.md)
|
|
|
|
|
+
|
|
|
|
|
+- **代码风格**: TypeScript 严格模式,一致的缩进和命名
|
|
|
|
|
+- **类型注解**: 必须为所有函数参数和返回值添加类型注解
|
|
|
|
|
+- **接口定义**: 为复杂数据结构定义 TypeScript 接口
|
|
|
|
|
+- **导出规范**: 使用 ES6 `export` 语法导出函数和类型
|
|
|
|
|
+
|
|
|
|
|
+### 测试策略
|
|
|
|
|
+
|
|
|
|
|
+**来源**: [testing-strategy.md](../../architecture/testing-strategy.md)
|
|
|
|
|
+
|
|
|
|
|
+**测试框架**: Jest(mini 包使用 Jest,不是 Vitest)
|
|
|
|
|
+
|
|
|
|
|
+**测试位置**: `tests/` 目录(与源码并列)
|
|
|
|
|
+
|
|
|
|
|
+**测试类型**:
|
|
|
|
|
+- 单元测试: 测试工具函数的正确性
|
|
|
|
|
+- **不要求**集成测试和 E2E 测试(这些在后续故事中)
|
|
|
|
|
+
|
|
|
|
|
+**测试要求**:
|
|
|
|
|
+1. 为每个工具函数编写单元测试
|
|
|
|
|
+2. 测试覆盖率目标: 基础测试即可,不要求高覆盖率
|
|
|
|
|
+3. Mock Canvas 上下文以支持依赖 Canvas 的函数测试
|
|
|
|
|
+
|
|
|
|
|
+**测试命令**:
|
|
|
|
|
+```bash
|
|
|
|
|
+# 进入包目录
|
|
|
|
|
+cd mini-ui-packages/mini-charts
|
|
|
|
|
+
|
|
|
|
|
+# 运行所有测试
|
|
|
|
|
+pnpm test
|
|
|
|
|
+
|
|
|
|
|
+# 运行特定测试
|
|
|
|
|
+pnpm test --testNamePattern "工具函数测试"
|
|
|
|
|
+
|
|
|
|
|
+# 类型检查
|
|
|
|
|
+pnpm typecheck
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### 构建和发布规范
|
|
|
|
|
+
|
|
|
|
|
+**来源**: [ui-package-standards.md](../../architecture/ui-package-standards.md#构建和发布规范)
|
|
|
|
|
+
|
|
|
|
|
+mini-charts 包在 PNPM 工作空间中:
|
|
|
|
|
+- **开发模式**: 直接使用 TypeScript 源码
|
|
|
|
|
+- **构建**: 使用 `tsc` 编译到 `dist/` 目录
|
|
|
|
|
+- **类型检查**: 使用 `tsc --noEmit` 验证类型
|
|
|
|
|
+- **发布**: 本故事不要求发布,仅验证本地构建成功
|
|
|
|
|
+
|
|
|
|
|
+**重要**: 本故事完成后,应该可以:
|
|
|
|
|
+1. ✅ 运行 `pnpm build` 成功生成 `dist/` 目录
|
|
|
|
|
+2. ✅ 运行 `pnpm typecheck` 无类型错误
|
|
|
|
|
+3. ✅ 所有新模块正确导出,可以被主入口文件引用
|
|
|
|
|
+
|
|
|
|
|
+### 开发流程
|
|
|
|
|
+
|
|
|
|
|
+**来源**: [development-workflow.md](../../architecture/development-workflow.md)
|
|
|
|
|
+
|
|
|
|
|
+**开发命令**:
|
|
|
|
|
+```bash
|
|
|
|
|
+# 进入包目录
|
|
|
|
|
+cd mini-ui-packages/mini-charts
|
|
|
|
|
+
|
|
|
|
|
+# 安装依赖(在根目录)
|
|
|
|
|
+pnpm install
|
|
|
|
|
+
|
|
|
|
|
+# 开发模式(监听文件变化)
|
|
|
|
|
+pnpm dev
|
|
|
|
|
+
|
|
|
|
|
+# 类型检查
|
|
|
|
|
+pnpm typecheck
|
|
|
|
|
+
|
|
|
|
|
+# 运行测试
|
|
|
|
|
+pnpm test
|
|
|
|
|
+
|
|
|
|
|
+# 构建
|
|
|
|
|
+pnpm build
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### 环境配置
|
|
|
|
|
+
|
|
|
|
|
+**来源**: [CLAUDE.md](../../CLAUDE.md)
|
|
|
|
|
+
|
|
|
|
|
+- **Node.js**: 20.19.2
|
|
|
|
|
+- **包管理器**: pnpm
|
|
|
|
|
+- **测试调试**: 使用 `pnpm test --testNamePattern "测试名称"` 运行特定测试
|
|
|
|
|
+- **Mini 测试**: 需要 Jest,不是 Vitest
|
|
|
|
|
+- **类型检查**: 使用 `pnpm typecheck` 加 grep 来过滤要检查的指定文件
|
|
|
|
|
+
|
|
|
|
|
+### 文件位置规范
|
|
|
|
|
+
|
|
|
|
|
+**来源**: [source-tree.md](../../architecture/source-tree.md)
|
|
|
|
|
+
|
|
|
|
|
+所有新文件应创建在:
|
|
|
|
|
+- 配置文件: `mini-ui-packages/mini-charts/src/lib/config.ts`
|
|
|
|
|
+- 工具函数目录: `mini-ui-packages/mini-charts/src/lib/utils/`
|
|
|
|
|
+- 工具函数文件:
|
|
|
|
|
+ - `color.ts`: 颜色工具函数
|
|
|
|
|
+ - `math.ts`: 数学工具函数
|
|
|
|
|
+ - `coordinate.ts`: 坐标转换工具
|
|
|
|
|
+ - `text.ts`: 文本测量工具
|
|
|
|
|
+ - `collision.ts`: 碰撞检测工具
|
|
|
|
|
+ - `misc.ts`: 其他工具函数
|
|
|
|
|
+ - `index.ts`: 工具函数统一导出
|
|
|
|
|
+- 主入口: `mini-ui-packages/mini-charts/src/index.ts`(需要更新导出)
|
|
|
|
|
+- 测试文件: `mini-ui-packages/mini-charts/tests/`(可选,本故事不强制要求)
|
|
|
|
|
+
|
|
|
|
|
+### 技术约束
|
|
|
|
|
+
|
|
|
|
|
+1. **搬迁原则**: 保持代码逻辑完全不变,只改变文件组织方式
|
|
|
|
|
+2. **类型注解**: 只在搬迁过程中添加 TypeScript 类型注解,不修改代码的实现逻辑
|
|
|
|
|
+3. **文件大小**: 每个文件控制在 500 行以内
|
|
|
|
|
+4. **类型安全**: 避免使用 `any` 类型(除非必要)
|
|
|
|
|
+5. **向后兼容**: 保持与原始 u-charts.ts 的功能兼容性
|
|
|
|
|
+
|
|
|
|
|
+### 验证标准
|
|
|
|
|
+
|
|
|
|
|
+完成本故事后,应该满足:
|
|
|
|
|
+1. ✅ `src/lib/config.ts` 文件存在,包含 config、assign、util 并有完整类型注解
|
|
|
|
|
+2. ✅ `src/lib/utils/` 目录下所有文件存在,每个函数都有类型注解
|
|
|
|
|
+3. ✅ 运行 `pnpm typecheck` 无类型错误
|
|
|
|
|
+4. ✅ 每个文件控制在 500 行以内
|
|
|
|
|
+5. ✅ 代码逻辑与原始 u-charts.ts 完全一致
|
|
|
|
|
+6. ✅ 所有新模块正确导出,可以被主入口文件引用
|
|
|
|
|
+
|
|
|
|
|
+### 不包含在本故事中的工作
|
|
|
|
|
+
|
|
|
|
|
+**来源**: [epic-016 故事列表](../../prd/epic-016-mini-charts-package.md#故事列表)
|
|
|
|
|
+
|
|
|
|
|
+以下工作**不在**本故事范围内:
|
|
|
|
|
+- ❌ 数据处理函数模块化(故事 016.003)
|
|
|
|
|
+- ❌ 图表数据点计算函数模块化(故事 016.004)
|
|
|
|
|
+- ❌ 绘制函数模块化(故事 016.005)
|
|
|
|
|
+- ❌ 核心类模块化(故事 016.006)
|
|
|
|
|
+- ❌ React 组件封装(故事 016.007)
|
|
|
|
|
+
|
|
|
|
|
+### Testing
|
|
|
|
|
+
|
|
|
|
|
+**测试框架**: Jest(不是 Vitest)
|
|
|
|
|
+
|
|
|
|
|
+**测试位置**: `tests/` 目录(与源码并列)
|
|
|
|
|
+
|
|
|
|
|
+**测试要求**:
|
|
|
|
|
+1. 创建基础测试验证工具函数的正确导入和导出
|
|
|
|
|
+2. 测试工具函数的基本功能(可选,本故事不强制要求)
|
|
|
|
|
+3. Mock Canvas 上下文以支持依赖 Canvas 的函数测试(如需要)
|
|
|
|
|
+4. 测试覆盖率目标: 基础测试即可,不要求高覆盖率
|
|
|
|
|
+
|
|
|
|
|
+**测试命令**:
|
|
|
|
|
+```bash
|
|
|
|
|
+# 运行所有测试
|
|
|
|
|
+pnpm test
|
|
|
|
|
+
|
|
|
|
|
+# 运行特定测试
|
|
|
|
|
+pnpm test --testNamePattern "配置和工具函数测试"
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+**参考**: [testing-strategy.md](../../architecture/testing-strategy.md)
|
|
|
|
|
+
|
|
|
|
|
+## Change Log
|
|
|
|
|
+
|
|
|
|
|
+| Date | Version | Description | Author |
|
|
|
|
|
+|------|---------|-------------|--------|
|
|
|
|
|
+| 2025-12-24 | 1.0 | 创建故事文档 | Bob (Scrum Master) |
|
|
|
|
|
+
|
|
|
|
|
+## Dev Agent Record
|
|
|
|
|
+
|
|
|
|
|
+*此部分由开发代理在实施过程中填写*
|
|
|
|
|
+
|
|
|
|
|
+### Agent Model Used
|
|
|
|
|
+
|
|
|
|
|
+### Debug Log References
|
|
|
|
|
+
|
|
|
|
|
+### Completion Notes List
|
|
|
|
|
+
|
|
|
|
|
+### File List
|
|
|
|
|
+
|
|
|
|
|
+## QA Results
|
|
|
|
|
+
|
|
|
|
|
+*此部分由 QA 代理在审查完成后填写*
|