feat: 接入Ts配置

This commit is contained in:
zdl
2025-11-14 16:15:29 +08:00
parent e23feb3c23
commit 48fdca203c
10 changed files with 663 additions and 31 deletions

92
.eslintrc.js Normal file
View File

@@ -0,0 +1,92 @@
module.exports = {
root: true,
/* 环境配置 */
env: {
browser: true,
es2021: true,
node: true,
},
/* 扩展配置 */
extends: [
'react-app', // Create React App 默认规则
'react-app/jest', // Jest 测试规则
'eslint:recommended', // ESLint 推荐规则
'plugin:react/recommended', // React 推荐规则
'plugin:react-hooks/recommended', // React Hooks 规则
'plugin:prettier/recommended', // Prettier 集成
],
/* 解析器选项 */
parserOptions: {
ecmaVersion: 'latest',
sourceType: 'module',
ecmaFeatures: {
jsx: true,
},
},
/* 插件 */
plugins: ['react', 'react-hooks', 'prettier'],
/* 规则配置 */
rules: {
// React
'react/react-in-jsx-scope': 'off', // React 17+ 不需要导入 React
'react/prop-types': 'off', // 使用 TypeScript 类型检查,不需要 PropTypes
'react/display-name': 'off', // 允许匿名组件
// 通用
'no-console': ['warn', { allow: ['warn', 'error'] }], // 仅警告 console.log
'no-unused-vars': ['warn', {
argsIgnorePattern: '^_', // 忽略以 _ 开头的未使用参数
varsIgnorePattern: '^_', // 忽略以 _ 开头的未使用变量
}],
'prettier/prettier': ['warn', {}, { usePrettierrc: true }], // 使用项目的 Prettier 配置
},
/* 设置 */
settings: {
react: {
version: 'detect', // 自动检测 React 版本
},
},
/* TypeScript 文件特殊配置 */
overrides: [
{
files: ['**/*.ts', '**/*.tsx'], // 仅对 TS 文件应用以下配置
parser: '@typescript-eslint/parser', // 使用 TypeScript 解析器
parserOptions: {
project: './tsconfig.json', // 关联 tsconfig.json
},
extends: [
'plugin:@typescript-eslint/recommended', // TypeScript 推荐规则
],
plugins: ['@typescript-eslint'],
rules: {
// TypeScript 特定规则
'@typescript-eslint/no-explicit-any': 'warn', // 警告使用 any允许但提示
'@typescript-eslint/explicit-module-boundary-types': 'off', // 不强制导出函数类型
'@typescript-eslint/no-unused-vars': ['warn', {
argsIgnorePattern: '^_',
varsIgnorePattern: '^_',
}],
'@typescript-eslint/no-non-null-assertion': 'warn', // 警告使用 !(非空断言)
// 覆盖基础规则(避免与 TS 规则冲突)
'no-unused-vars': 'off', // 使用 TS 版本的规则
},
},
],
/* 忽略文件(与 .eslintignore 等效)*/
ignorePatterns: [
'node_modules/',
'build/',
'dist/',
'*.config.js',
'public/mockServiceWorker.js',
],
};

159
CLAUDE.md
View File

@@ -20,6 +20,7 @@
**开发指南**:
- [开发工作流](#开发工作流) - 路由、组件、API、Redux 开发指南
- [TypeScript 接入](#typescript-接入) - TypeScript 渐进式迁移方案与指南
- [常见开发任务](#常见开发任务) - 5 个详细的开发任务教程
- [技术路径与开发指南](#技术路径与开发指南) - UI 框架选型、技术栈演进、最佳实践
@@ -42,6 +43,7 @@
**前端**
- **核心框架**: React 18.3.1
- **类型系统**: TypeScript 5.9.3(渐进式接入中,支持 JS/TS 混合开发)
- **UI 组件库**: Chakra UI 2.8.2(主要) + Ant Design 5.27.4(表格/表单)
- **状态管理**: Redux Toolkit 2.9.2
- **路由**: React Router v6.30.1 配合 React.lazy() 实现代码分割
@@ -81,6 +83,10 @@ npm test # 运行 React 测试套件CRACO
npm run lint:check # 检查 ESLint 规则(退出码 0
npm run lint:fix # 自动修复 ESLint 问题
npm run type-check # TypeScript 类型检查(不生成输出)
npm run type-check:watch # TypeScript 类型检查监听模式
npm run clean # 删除 node_modules 和 package-lock.json
npm run reinstall # 清洁安装(运行 clean + install
```
@@ -1386,6 +1392,159 @@ src/views/Community/components/
---
## TypeScript 接入
### 概述
项目已于 **2025-11-13** 完成 TypeScript 环境配置,采用**渐进式迁移策略**,支持 JavaScript 和 TypeScript 混合开发。
**当前状态**: 环境配置完成,准备开始代码迁移
**迁移策略**: 新代码使用 TypeScript旧代码按优先级逐步迁移
**类型严格度**: 推荐模式(`noImplicitAny: true`,其他严格检查待后续开启)
### 已完成的环境配置
**TypeScript 编译器**: v5.9.3
**tsconfig.json**: 推荐模式配置,支持 JS/TS 混合开发
**CRACO 配置**: 支持 `.ts``.tsx` 文件编译
**ESLint 配置**: 支持 TypeScript 语法检查
**路径别名**: 与现有 `@/` 别名保持一致
**全局类型定义**: 基础类型文件已创建在 `src/types/`
### 可用类型定义
项目已创建以下基础类型定义文件:
**`src/types/api.ts`** - API 相关类型
- `ApiResponse<T>` - 通用 API 响应结构
- `PaginatedResponse<T>` - 分页响应
- `ApiError` - API 错误类型
- `ListQueryParams` - 列表查询参数
**`src/types/stock.ts`** - 股票相关类型
- `StockInfo` - 股票基础信息
- `StockQuote` - 股票行情数据
- `KLineData` - K 线数据
- `StockFinancials` - 财务指标
- `StockPosition` - 股票持仓
- `Sector` - 概念/行业板块
**`src/types/user.ts`** - 用户相关类型
- `UserInfo` - 用户基础信息
- `AuthInfo` - 认证信息
- `LoginParams` / `RegisterParams` - 登录/注册参数
- `UserSubscription` - 订阅信息
- `UserAccount` - 资金账户
- `UserSettings` - 用户设置
**使用方式**:
```typescript
// 统一导入
import type { StockQuote, UserInfo, ApiResponse } from '@/types';
// 或从具体文件导入
import type { StockQuote } from '@/types/stock';
```
### TypeScript 命令
```bash
# 类型检查(不生成输出文件)
npm run type-check
# 类型检查 + 监听模式
npm run type-check:watch
# ESLint 检查(包含 TS 文件)
npm run lint:check
# ESLint 自动修复
npm run lint:fix
```
### 迁移路线图
详细的迁移指南请参考 **[TYPESCRIPT_MIGRATION.md](./TYPESCRIPT_MIGRATION.md)** 文档。
**简要路线图**:
1. **优先级 1⃣**: 工具层(`src/utils/`, `src/constants/`
- 纯函数,迁移成本低,收益高
- 提供类型定义给其他模块使用
2. **优先级 2⃣**: 类型定义层(扩展 `src/types/`
- 添加 `trading.ts`, `community.ts`, `chart.ts`
3. **优先级 3⃣**: 服务层(`src/services/`
- 定义 API 请求/响应类型
- 使用 `ApiResponse<T>` 包装响应
4. **优先级 4⃣**: Redux 状态层(`src/store/slices/`
- 定义 `RootState``AppDispatch` 类型
- 创建类型化的 hooks
5. **优先级 5⃣**: 自定义 Hooks`src/hooks/`
- 添加泛型支持
- 定义完整返回值类型
6. **优先级 6⃣**: 组件层(`src/components/`, `src/views/`
- Atoms → Molecules → Organisms → Pages
- 优先迁移复用度高的组件
### 开发规范
**新代码**:
-**必须使用 TypeScript**`.ts``.tsx`
- ✅ 所有函数参数和返回值添加类型
- ✅ 组件 Props 使用 `interface` 定义
- ✅ 避免使用 `any`(特殊情况需添加注释说明)
**旧代码迁移**:
- 按优先级迁移,不强制一次性完成
- 迁移前先阅读 [TYPESCRIPT_MIGRATION.md](./TYPESCRIPT_MIGRATION.md)
- 迁移后运行 `npm run type-check` 验证
**类型定义**:
- 公共类型定义导出到 `src/types/`
- 组件内部类型可定义在组件文件中
- 使用 `type` 还是 `interface` 参考 [迁移指南](./TYPESCRIPT_MIGRATION.md)
### 常见问题
**Q: 路径别名 `@/types` 无法识别?**
A: 确保在 `tsconfig.json` 中配置了 `paths`,并重启 IDE。使用 `npm run type-check` 而非命令行 `tsc`
**Q: 如何处理第三方库没有类型定义?**
A:
1. 尝试安装 `@types/library-name`
2. 创建自定义类型声明文件 `src/types/library-name.d.ts`
3. 临时使用 `as any`(需添加 TODO 注释)
**Q: 迁移期间如何处理 any 类型?**
A: 添加 ESLint 禁用注释和 TODO 说明:
```typescript
/* eslint-disable @typescript-eslint/no-explicit-any */
// TODO: 待完善类型定义
const legacyFunction = (data: any): any => { ... };
```
**Q: React 组件的 children 类型如何定义?**
A: 使用 `React.ReactNode`
```typescript
interface Props {
children: React.ReactNode;
}
```
### 参考资源
- [TYPESCRIPT_MIGRATION.md](./TYPESCRIPT_MIGRATION.md) - 完整迁移指南
- [TypeScript 官方文档](https://www.typescriptlang.org/docs/)
- [React TypeScript Cheatsheet](https://react-typescript-cheatsheet.netlify.app/)
- [Redux Toolkit TypeScript 指南](https://redux-toolkit.js.org/usage/usage-with-typescript)
---
## 更新本文档
本 CLAUDE.md 文件是一个持续更新的文档。在以下情况下应更新它:

View File

@@ -133,8 +133,8 @@ module.exports = {
'@variables': path.resolve(__dirname, 'src/variables'),
'@views': path.resolve(__dirname, 'src/views'),
},
// 减少文件扩展名搜索
extensions: ['.js', '.jsx', '.json'],
// 减少文件扩展名搜索(优先 TypeScript
extensions: ['.ts', '.tsx', '.js', '.jsx', '.json'],
// 优化模块查找路径
modules: [
path.resolve(__dirname, 'src'),

View File

@@ -1,27 +0,0 @@
{
"compilerOptions": {
"baseUrl": "src",
"paths": {
"@/*": ["./*"],
"@assets/*": ["assets/*"],
"@components/*": ["components/*"],
"@constants/*": ["constants/*"],
"@contexts/*": ["contexts/*"],
"@data/*": ["data/*"],
"@hooks/*": ["hooks/*"],
"@layouts/*": ["layouts/*"],
"@lib/*": ["lib/*"],
"@mocks/*": ["mocks/*"],
"@providers/*": ["providers/*"],
"@routes/*": ["routes/*"],
"@services/*": ["services/*"],
"@store/*": ["store/*"],
"@styles/*": ["styles/*"],
"@theme/*": ["theme/*"],
"@utils/*": ["utils/*"],
"@variables/*": ["variables/*"],
"@views/*": ["views/*"]
}
},
"exclude": ["node_modules", "build", "dist"]
}

View File

@@ -106,13 +106,20 @@
"deploy": "bash scripts/deploy-from-local.sh",
"deploy:setup": "bash scripts/setup-deployment.sh",
"rollback": "bash scripts/rollback-from-local.sh",
"lint:check": "eslint . --ext=js,jsx; exit 0",
"lint:fix": "eslint . --ext=js,jsx --fix; exit 0",
"lint:check": "eslint . --ext=js,jsx,ts,tsx; exit 0",
"lint:fix": "eslint . --ext=js,jsx,ts,tsx --fix; exit 0",
"type-check": "tsc --noEmit",
"type-check:watch": "tsc --noEmit --watch",
"clean": "rm -rf node_modules/ package-lock.json",
"reinstall": "npm run clean && npm install"
},
"devDependencies": {
"@craco/craco": "^7.1.0",
"@types/node": "^20.19.25",
"@types/react": "^18.2.0",
"@types/react-dom": "^18.2.0",
"@typescript-eslint/eslint-plugin": "^8.46.4",
"@typescript-eslint/parser": "^8.46.4",
"ajv": "^8.17.1",
"autoprefixer": "^10.4.21",
"concurrently": "^8.2.2",
@@ -131,6 +138,7 @@
"react-error-overlay": "6.0.9",
"sharp": "^0.34.4",
"ts-node": "^10.9.2",
"typescript": "^5.9.3",
"webpack-bundle-analyzer": "^4.10.2",
"yn": "^5.1.0"
},

68
src/types/api.ts Normal file
View File

@@ -0,0 +1,68 @@
/**
* API 相关类型定义
*
* 包含通用的 API 请求/响应类型、错误类型等
*/
/**
* API 响应基础结构
*/
export interface ApiResponse<T = any> {
code: number;
message: string;
data: T;
}
/**
* API 错误类型
*/
export interface ApiError {
code: number;
message: string;
details?: any;
}
/**
* 分页请求参数
*/
export interface PaginationParams {
page: number;
pageSize: number;
total?: number;
}
/**
* 分页响应数据
*/
export interface PaginatedResponse<T> {
list: T[];
pagination: {
current: number;
pageSize: number;
total: number;
totalPages: number;
};
}
/**
* 排序参数
*/
export interface SortParams {
field: string;
order: 'asc' | 'desc';
}
/**
* 过滤参数
*/
export interface FilterParams {
[key: string]: any;
}
/**
* 通用列表查询参数
*/
export interface ListQueryParams extends Partial<PaginationParams> {
sort?: SortParams;
filters?: FilterParams;
}

40
src/types/index.ts Normal file
View File

@@ -0,0 +1,40 @@
/**
* 全局类型定义汇总导出
*
* 使用方式:
* import { StockQuote, UserInfo, ApiResponse } from '@/types';
*/
// API 相关类型
export type {
ApiResponse,
ApiError,
PaginationParams,
PaginatedResponse,
SortParams,
FilterParams,
ListQueryParams,
} from './api';
// 股票相关类型
export type {
StockInfo,
StockQuote,
KLineData,
StockFinancials,
StockPosition,
Sector,
StockSearchResult,
} from './stock';
// 用户相关类型
export type {
UserInfo,
AuthInfo,
LoginParams,
RegisterParams,
UserPermissions,
UserSubscription,
UserAccount,
UserSettings,
} from './user';

103
src/types/stock.ts Normal file
View File

@@ -0,0 +1,103 @@
/**
* 股票相关类型定义
*
* 包含股票数据、行情、指标等类型
*/
/**
* 股票基础信息
*/
export interface StockInfo {
code: string; // 股票代码(如 '600000.SH'
name: string; // 股票名称
market: 'SH' | 'SZ' | 'BJ'; // 市场(上海/深圳/北京)
industry?: string; // 所属行业
concept?: string[]; // 所属概念
listingDate?: string; // 上市日期
}
/**
* 股票行情数据
*/
export interface StockQuote {
code: string; // 股票代码
name: string; // 股票名称
current: number; // 当前价格
open: number; // 开盘价
close: number; // 收盘价(前一交易日)
high: number; // 最高价
low: number; // 最低价
volume: number; // 成交量
amount: number; // 成交额
change: number; // 涨跌额
changePercent: number; // 涨跌幅(百分比)
turnoverRate?: number; // 换手率
timestamp: number; // 时间戳
}
/**
* K 线数据(日线/分钟线)
*/
export interface KLineData {
date: string; // 日期YYYY-MM-DD 或 YYYY-MM-DD HH:mm:ss
open: number; // 开盘价
high: number; // 最高价
low: number; // 最低价
close: number; // 收盘价
volume: number; // 成交量
amount?: number; // 成交额
}
/**
* 股票财务指标
*/
export interface StockFinancials {
code: string; // 股票代码
reportDate: string; // 报告期
revenue: number; // 营业收入
netProfit: number; // 净利润
eps: number; // 每股收益EPS
roe: number; // 净资产收益率ROE
pe: number; // 市盈率PE
pb: number; // 市净率PB
grossProfitMargin?: number; // 毛利率
debtToAssetRatio?: number; // 资产负债率
}
/**
* 股票持仓
*/
export interface StockPosition {
code: string; // 股票代码
name: string; // 股票名称
quantity: number; // 持仓数量
availableQuantity: number; // 可用数量T+1
costPrice: number; // 成本价
currentPrice: number; // 当前价
marketValue: number; // 市值
profit: number; // 盈亏金额
profitPercent: number; // 盈亏比例
}
/**
* 概念/行业板块
*/
export interface Sector {
id: string; // 板块 ID
name: string; // 板块名称
type: 'industry' | 'concept'; // 类型(行业/概念)
changePercent: number; // 板块涨跌幅
leadingStock?: string; // 领涨股
stockCount?: number; // 成分股数量
description?: string; // 描述
}
/**
* 股票搜索结果
*/
export interface StockSearchResult {
code: string;
name: string;
market: string;
industry?: string;
}

108
src/types/user.ts Normal file
View File

@@ -0,0 +1,108 @@
/**
* 用户相关类型定义
*
* 包含用户信息、认证、权限等类型
*/
/**
* 用户基础信息
*/
export interface UserInfo {
id: string | number; // 用户 ID
username: string; // 用户名
email?: string; // 邮箱
phone?: string; // 手机号
avatar?: string; // 头像 URL
nickname?: string; // 昵称
realName?: string; // 真实姓名
gender?: 'male' | 'female' | 'other'; // 性别
birthday?: string; // 生日
createdAt?: string; // 注册时间
updatedAt?: string; // 更新时间
}
/**
* 用户认证信息
*/
export interface AuthInfo {
token: string; // 访问令牌
refreshToken?: string; // 刷新令牌
expiresIn?: number; // 过期时间(秒)
tokenType?: string; // 令牌类型(如 'Bearer'
}
/**
* 登录请求参数
*/
export interface LoginParams {
username: string; // 用户名或手机号
password: string; // 密码
captcha?: string; // 验证码
remember?: boolean; // 记住登录状态
}
/**
* 注册请求参数
*/
export interface RegisterParams {
username: string; // 用户名
password: string; // 密码
confirmPassword?: string; // 确认密码
phone?: string; // 手机号
email?: string; // 邮箱
verificationCode?: string; // 短信验证码
agreeTerm?: boolean; // 是否同意条款
}
/**
* 用户权限
*/
export interface UserPermissions {
roles: string[]; // 角色列表
permissions: string[]; // 权限列表
}
/**
* 用户订阅信息
*/
export interface UserSubscription {
userId: string | number; // 用户 ID
plan: 'free' | 'basic' | 'pro' | 'enterprise'; // 订阅套餐
status: 'active' | 'expired' | 'cancelled'; // 状态
startDate: string; // 开始日期
endDate: string; // 结束日期
autoRenew?: boolean; // 是否自动续费
features?: string[]; // 可用功能列表
}
/**
* 用户资金账户
*/
export interface UserAccount {
userId: string | number; // 用户 ID
balance: number; // 可用余额
frozenBalance: number; // 冻结资金
totalAssets: number; // 总资产
marketValue: number; // 持仓市值
profit: number; // 盈亏金额
profitPercent: number; // 盈亏比例
currency: string; // 币种(默认 'CNY'
}
/**
* 用户设置
*/
export interface UserSettings {
userId: string | number; // 用户 ID
theme?: 'light' | 'dark'; // 主题
language?: 'zh-CN' | 'en-US'; // 语言
notifications?: {
email: boolean; // 邮件通知
sms: boolean; // 短信通知
push: boolean; // 推送通知
};
privacy?: {
showProfile: boolean; // 显示个人资料
showPositions: boolean; // 显示持仓
};
}

81
tsconfig.json Normal file
View File

@@ -0,0 +1,81 @@
{
"compilerOptions": {
/* */
"target": "ES2020", // 编译目标(支持现代浏览器)
"lib": ["DOM", "DOM.Iterable", "ES2020"], // 类型库
"jsx": "react-jsx", // JSX 编译模式React 17+ 新 JSX 转换)
"module": "ESNext", // 模块系统
"moduleResolution": "node", // 模块解析策略
/* - */
"strict": false, // 关闭全部严格检查(初期)
"noImplicitAny": true, // 禁止隐式 any推荐启用
"strictNullChecks": false, // 暂不启用空值检查(后续开启)
"strictFunctionTypes": false, // 暂不启用函数类型严格检查
"strictBindCallApply": false, // 暂不启用 bind/call/apply 严格检查
"strictPropertyInitialization": false, // 暂不启用属性初始化检查
"noImplicitThis": true, // 禁止隐式 this
"alwaysStrict": true, // 总是以严格模式解析
/* */
"noUnusedLocals": false, // 初期不检查未使用的局部变量
"noUnusedParameters": false, // 初期不检查未使用的参数
"noImplicitReturns": false, // 初期不强制所有路径都返回值
"noFallthroughCasesInSwitch": true, // 检查 switch 语句穿透
/* - JS/TS */
"allowJs": true, // 允许编译 JS 文件
"checkJs": false, // 不检查 JS 文件(避免大量错误)
"isolatedModules": true, // 确保每个文件都可以独立编译
"esModuleInterop": true, // ES 模块互操作性
"allowSyntheticDefaultImports": true, // 允许默认导入
"skipLibCheck": true, // 跳过库文件类型检查(加快编译)
"forceConsistentCasingInFileNames": true, // 强制文件名大小写一致
"resolveJsonModule": true, // 支持导入 JSON 文件
/* */
"noEmit": true, // 不生成输出文件(由 Babel/Webpack 处理)
"declaration": false, // 不生成类型声明文件
"sourceMap": false, // 不生成 source map由 Webpack 处理)
/* - craco.config.js */
"baseUrl": ".",
"paths": {
"@/*": ["src/*"],
"@assets/*": ["src/assets/*"],
"@components/*": ["src/components/*"],
"@constants/*": ["src/constants/*"],
"@contexts/*": ["src/contexts/*"],
"@data/*": ["src/data/*"],
"@hooks/*": ["src/hooks/*"],
"@layouts/*": ["src/layouts/*"],
"@lib/*": ["src/lib/*"],
"@mocks/*": ["src/mocks/*"],
"@providers/*": ["src/providers/*"],
"@routes/*": ["src/routes/*"],
"@services/*": ["src/services/*"],
"@store/*": ["src/store/*"],
"@styles/*": ["src/styles/*"],
"@theme/*": ["src/theme/*"],
"@utils/*": ["src/utils/*"],
"@variables/*": ["src/variables/*"],
"@views/*": ["src/views/*"]
}
},
/* / */
"include": [
"src/**/*", // 包含 src 目录下所有 .ts, .tsx, .js, .jsx 文件
"src/**/*.json" // 包含 JSON 文件
],
"exclude": [
"node_modules", // 排除依赖
"build", // 排除构建输出
"dist", // 排除打包输出
"scripts", // 排除脚本
"**/*.spec.ts", // 排除测试文件(可选)
"**/*.test.ts",
"**/*.spec.tsx",
"**/*.test.tsx"
]
}