diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 00000000..f92631b5 --- /dev/null +++ b/.eslintrc.js @@ -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', + ], +}; diff --git a/CLAUDE.md b/CLAUDE.md index 3995dbee..f3e5d132 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -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` - 通用 API 响应结构 +- `PaginatedResponse` - 分页响应 +- `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` 包装响应 + +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 文件是一个持续更新的文档。在以下情况下应更新它: diff --git a/craco.config.js b/craco.config.js index ea82db97..946850d5 100644 --- a/craco.config.js +++ b/craco.config.js @@ -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'), diff --git a/jsconfig.json b/jsconfig.json deleted file mode 100755 index 7e20b6c2..00000000 --- a/jsconfig.json +++ /dev/null @@ -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"] -} diff --git a/package.json b/package.json index 4e18f16a..d9aaacee 100755 --- a/package.json +++ b/package.json @@ -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" }, diff --git a/src/types/api.ts b/src/types/api.ts new file mode 100644 index 00000000..f1cc8b3f --- /dev/null +++ b/src/types/api.ts @@ -0,0 +1,68 @@ +/** + * API 相关类型定义 + * + * 包含通用的 API 请求/响应类型、错误类型等 + */ + +/** + * API 响应基础结构 + */ +export interface ApiResponse { + 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 { + 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 { + sort?: SortParams; + filters?: FilterParams; +} diff --git a/src/types/index.ts b/src/types/index.ts new file mode 100644 index 00000000..7907e403 --- /dev/null +++ b/src/types/index.ts @@ -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'; diff --git a/src/types/stock.ts b/src/types/stock.ts new file mode 100644 index 00000000..b6c19e51 --- /dev/null +++ b/src/types/stock.ts @@ -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; +} diff --git a/src/types/user.ts b/src/types/user.ts new file mode 100644 index 00000000..f13dd64d --- /dev/null +++ b/src/types/user.ts @@ -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; // 显示持仓 + }; +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 00000000..81e69849 --- /dev/null +++ b/tsconfig.json @@ -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" + ] +}