Pārlūkot izejas kodu

perf: 更新readme,调整antdAppInstance.tsx 的位置

BaiLuoYan 4 nedēļas atpakaļ
vecāks
revīzija
bf0c8cb658

+ 89 - 711
README.md

@@ -1,753 +1,131 @@
 # Visa Card H5
 
-这是一个基于 React + TypeScript + Vite 的现代化 H5 项目。
+基于 React + TypeScript + Vite 的 H5 前端项目。
 
 ## 环境要求
 
 - Node.js >= 18.20.7
 - pnpm >= 9
-- 现代浏览器支持
 
-## 浏览器支持
-
-- Chrome >= 87
-- Firefox >= 78
-- Safari >= 14
-- Edge >= 88
-- Android >= 4.4
-- iOS >= 9
-
-## 技术栈
-
-- **核心框架**:React 18 + TypeScript
-- **构建工具**:Vite 6
-- **包管理器**:pnpm
-- **UI 框架**:Ant Design 5
-- **路由**:React Router 7
-- **状态管理**:
-  - 基于 React Context + Hooks 的自定义方案,类似 UmiJS max 中的 model
-- **样式解决方案**:
-  - Tailwind CSS
-  - SCSS
-  - Less
-- **国际化**:i18next
-- **HTTP 客户端**:Axios
-- **工具库**:
-  - lodash-es
-  - ramda
-  - dayjs
-- **图标解决方案**:
-  - @iconify/react
-  - 自定义 Vite 插件(SVG 转 Iconify)
-  - Ant Design Icon
-- **代码规范**:
-  - ESLint
-  - Prettier
-  - Stylelint
-  - Commitlint
-- **Git 工作流**:
-  - Husky
-  - lint-staged
-
-## 开发命令
+## 快速开始
 
 ```bash
-# 安装依赖
 pnpm install --frozen-lockfile
-
-# 启动开发服务器
 pnpm dev
+```
 
-# 构建生产环境
-pnpm build
+浏览器访问控制台输出的本地地址即可。
 
-# 构建测试环境
-pnpm build:test
+## 脚本说明
 
-# 预览构建结果
-pnpm preview
+| 命令 | 说明 |
+|------|------|
+| `pnpm dev` | 本地开发(使用 `.env.localdev` + `.env`) |
+| `pnpm build` | 生产构建(等价于 `build:prod`) |
+| `pnpm build:dev` | 开发模式构建(`.env.development`) |
+| `pnpm build:prod` | 生产模式构建(`.env.production`) |
+| `pnpm build:test` | 测试环境构建(`.env.test`) |
+| `pnpm preview` | 预览构建产物(使用 localdev 模式) |
+| `pnpm lint` / `pnpm lint:fix` | ESLint 检查 / 自动修复 |
+| `pnpm stylelint` / `pnpm stylelint:fix` | 样式检查 / 自动修复 |
 
-# 代码检查
-pnpm lint           # 检查 TypeScript/JavaScript 代码
-pnpm lint:fix       # 自动修复 TypeScript/JavaScript 代码问题
-pnpm stylelint      # 检查样式文件
-pnpm stylelint:fix  # 自动修复样式文件问题
-```
+## 环境配置
 
-## 开发规范
+通过不同 `.env` 文件区分环境,Vite 按 **mode** 加载:
 
-- 遵循 TypeScript 严格模式
-- 使用 ESLint 和 Prettier 进行代码格式化
-- 使用 Conventional Commits 规范提交信息
-- 组件采用函数式组件和 Hooks
-- 样式优先使用 Tailwind CSS,必要时使用 SCSS 或 Less
+| 文件 | 何时加载 |
+|------|----------|
+| `.env` | 始终加载(公共默认) |
+| `.env.localdev` | `pnpm dev` / `pnpm preview`(`--mode localdev`) |
+| `.env.development` | `pnpm build:dev` |
+| `.env.production` | `pnpm build` / `pnpm build:prod` |
+| `.env.test` | `pnpm build:test` |
+| `.env.local` | 本地覆盖,除 test 外都会加载(一般不提交) |
 
-## 部署
+需在环境文件中配置的变量见 `.env` 内注释或项目文档。
 
-项目支持多环境部署,通过 `.env` 文件配置不同环境的变量:
+## 技术栈
 
-- `.env.development` - 开发环境
-- `.env.test` - 测试环境
-- `.env.production` - 生产环境
+- **框架**:React 18、TypeScript
+- **构建**:Vite 6、pnpm
+- **UI**:Ant Design 5、Tailwind CSS、SCSS/Less
+- **路由**:React Router 7
+- **状态**:基于 Context + Hooks 的 Model 方案(类 Umi max)
+- **国际化**:i18next(zh-CN / en-US / fa-IR)
+- **请求**:Axios 封装(`src/utils/request`)
+- **图标**:@iconify/react + 自定义 SVG 转 Iconify 插件
+- **规范**:ESLint、Prettier、Stylelint、Commitlint、Husky、lint-staged
 
 ## 项目结构
 
 ```
-├── build/          # 构建相关配置和脚本
-├── public/         # 静态资源目录
-│   ├── favicon.ico # 网站图标
-│   └── index.html  # HTML 模板
+├── build/              # Vite 构建相关(插件、工具)
+├── public/             # 静态资源
 ├── src/
-│   ├── assets/     # 项目资源文件
-│   │   ├── single-color/  # 单色图标
-│   │   └── multi-color/   # 多色图标
-│   ├── components/ # 公共组件
-│   ├── config/     # 配置文件
-│   │   └── request/      # 请求相关配置
-│   │       ├── index.ts  # 请求基础配置
-│   │       ├── authHeaderInterceptor.ts  # 认证拦截器
-│   │       ├── encryptionInterceptors.ts # 加密解密拦截器
-│   │       └── errorHandler.ts # 错误处理
-│   ├── defines/    # 枚举和常量定义
-│   │   ├── index.ts  # 导出入口
-│   │   ├── errorShowType.ts # 错误展示类型枚举
-│   │   └── ...  # 其他常量/枚举定义文件
-│   ├── firebase.tsx # Firebase 配置
-│   ├── i18n/       # 国际化配置
-│   ├── layouts/    # 布局组件
-│   ├── locales/    # 国际化语言包
-│   ├── main.tsx    # 应用入口
-│   ├── models/     # 数据模型
-│   ├── pages/      # 页面组件
-│   ├── router/     # 路由配置
-│   ├── services/   # API 服务
-│   ├── styles/     # 全局样式
-│   ├── utils/      # 工具函数
-│   └── App.tsx     # 根组件
-├── types/          # TypeScript 类型定义
-└── dist/           # 构建输出目录
+│   ├── assets/         # 资源
+│   │   └── iconify/    # 单色 single-color、多色 multi-color 图标
+│   ├── components/     # 公共组件
+│   ├── config/         # 应用与请求配置(含 request 拦截器、错误处理)
+│   ├── defines/        # 枚举与常量
+│   ├── hooks/          # 公共 Hooks
+│   ├── i18n/           # 国际化配置
+│   ├── layouts/        # 布局
+│   ├── locales/        # 多语言文案(zh-CN、en-US、fa-IR)
+│   ├── models/         # 全局状态 Model
+│   ├── pages/          # 页面(按页面分目录)
+│   ├── router/         # 路由配置
+│   ├── services/       # API 接口(按模块分目录)
+│   ├── styles/         # 全局样式
+│   ├── utils/          # 工具与 request 封装
+│   ├── App.tsx
+│   └── main.tsx
+├── types/              # 全局类型与 env 类型
+├── index.html
+├── vite.config.ts
+└── package.json
 ```
 
-### 目录说明
-
-- **build/** - 包含构建相关的配置文件和脚本
-  - 构建脚本
-  - 环境配置
-  - 部署配置
-
-- **public/** - 静态资源目录
-  - 存放不需要通过构建工具处理的静态文件
-  - 包含网站图标、HTML 模板等
-  - 构建时会被直接复制到输出目录
-
-- **src/** - 源代码目录
-  - 包含所有需要编译的源代码
-  - 按功能模块组织代码结构
-
-- **src/pages/** - 页面组件目录
-  - 遵循"一个页面一个目录"的原则
-  - 每个页面的目录结构应该类似下面的结构:
-    ```
-    pages/
-    ├── home/                # 首页
-    │   ├── index.tsx       # 页面主组件
-    │   ├── components/     # 页面级组件
-    │   ├── hooks/         # 页面级 Hooks
-    │   ├── styles/        # 页面级样式
-    │   └── types.ts       # 页面级类型定义
-    ├── about/             # 关于页面
-    │   ├── index.tsx
-    │   ├── components/
-    │   ├── hooks/
-    │   ├── styles/
-    │   └── types.ts
-    └── ...
-    ```
-  - 页面级组件、Hooks、样式等资源应放在对应页面目录下
-  - 页面间共享的组件应放在 `src/components` 目录下
+## 开发规范摘要
 
-- **types/** - TypeScript 类型定义目录
-  - 存放全局类型声明文件
-  - 第三方库的类型定义
+- 严格 TypeScript,遵循项目 ESLint/Prettier 配置
+- 提交信息使用 Conventional Commits
+- 组件:函数组件 + Hooks;样式优先 Tailwind,必要时 SCSS/Less
+- 用户可见文案全部走 `locales`,禁止在代码中硬编码
+- 常量与枚举放在 `src/defines/`,请求在 `src/services/` 按模块组织
+- 新页面:在 `src/pages/` 下建目录、在 `routes` 与 `locales` 中注册
 
-- **dist/** - 构建输出目录
-  - 存放构建后的生产环境代码
-  - 包含优化后的静态资源
-  - 部署时使用此目录的内容
+## 状态管理(Model)
 
-## 状态管理
-
-项目使用基于 React Context 和 Hooks 的 Model 方案进行状态管理,类似 UmiJS Max 的 model 方案。
-
-### 目录结构
-
-```
-src/
-  └── models/              # 模型目录
-      ├── userModel.ts    # 用户模型
-      └── ...            # 其他模型
-```
+- Model 定义在 `src/models/`,通过 `createModel(hook, name)` 创建。
+- 在组件中:`const user = userModel.useModel()`,使用返回的状态与方法。
+- 根组件已通过 `autoImportModels` 注入所有 Model 的 Provider。
 
-#### 使用示例
+详见 `src/utils/model/` 与现有 `userModel`、`dialogModel`、`userConfigModel` 实现。
 
-1. 创建模型:
+## 图标
 
-```typescript
-// src/models/userModel.ts
-import { useState } from 'react';
-import { createModel } from '@/utils/model/createModel';
+- 单色图标:放入 `src/assets/iconify/single-color/`,会转为 `currentColor`,可用 `className` 控制颜色。
+- 多色图标:放入 `src/assets/iconify/multi-color/`,保留原色。
+- 使用:`import icon from '@/assets/iconify/single-color/xxx.svg'`,再 `<Icon icon={icon} />`(@iconify/react)。
 
-// 定义状态类型
-interface UserState {
-    name: string;
-    age: number;
-}
+## 多语言
 
-// 创建自定义 Hook
-const useUserModel = () => {
-    const [state, setState] = useState<UserState>({
-        name: 'John Doe',
-        age: 30
-    });
+- 文案在 `src/locales/` 下按语言分目录(zh-CN、en-US、fa-IR),每语言含 common、components、menus、pages 等模块。
+- 组件内:`const { t } = useTranslation();`,`t('key')` 或带命名空间的 key。
+- 禁止在页面/组件中写死中文或英文字符串。
 
-    const updateName = (name: string) => {
-        setState(prev => ({ ...prev, name }));
-    };
+## 请求与接口
 
-    const updateAge = (age: number) => {
-        setState(prev => ({ ...prev, age }));
-    };
+- 请求封装:`src/utils/request`,基础配置与拦截器在 `src/config/request/`(认证、加解密、错误处理)。
+- 接口按模块放在 `src/services/`,每模块可有 `typings.d.ts` + `index.ts`。
+- 调用:`import { fetchXxx } from '@/services/xxx'`,错误由统一错误处理兜底,可选 `skipErrorHandler` 自行处理。
 
-    const incrementAge = () => {
-        setState(prev => ({ ...prev, age: prev.age + 1 }));
-    };
-
-    return {
-        ...state,
-        updateName,
-        updateAge,
-        incrementAge
-    };
-};
-
-// 创建 model
-export const userModel = createModel(useUserModel, 'user');
-```
-
-2. 在组件中使用:
-
-```typescript
-// src/pages/home/index.tsx
-import { userModel } from '@/models/userModel';
-
-const Home = () => {
-    const user = userModel.useModel();
-    
-    return (
-        <div>
-            <h1>Hello, {user.name}!</h1>
-            <p>Age: {user.age}</p>
-            <button onClick={() => user.updateName('张三')}>修改名字</button>
-            <button onClick={() => user.incrementAge()}>年龄+1</button>
-        </div>
-    );
-};
-```
-
-## 图标使用说明
-
-项目使用了自定义的 Vite 插件,可以将指定目录的 SVG 图标转换为 Iconify 格式。
-
-### 使用方法
-
-1. 将需要转换的图标文件存放在以下目录:
-
-- `src/assets/single-color/` - 单色图标
-- `src/assets/multi-color/` - 多色图标
-
-2. 直接导入图标:
-
-```tsx
-import singleColorIcon from '@/assets/single-color/icon.svg';
-import multiColorIcon from '@/assets/multi-color/icon.svg';
-```
-
-3. 在组件中使用:
-
-```tsx
-import { Icon } from '@iconify/react';
-
-// 单色图标
-<Icon icon={singleColorIcon} className="text-red-500" />
-
-// 多色图标
-<Icon icon={multiColorIcon} />
-```
-
-### 图标特性
-
-- 单色图标可以通过 `className` 或 `color` 属性修改颜色
-- 多色图标保持原始颜色
-- 支持自定义大小(通过 `width` 和 `height` 属性)
-- 支持所有 Iconify 组件的属性
-
-## 多语言使用说明
-
-项目使用 i18next 实现多语言支持,目前支持英文和波斯语。
-
-### 目录结构
-
-```
-src/
-├── i18n/           # i18n 配置
-│   └── index.ts    # i18n 初始化配置
-└── locales/        # 语言包
-    ├── en-US.ts    # 英文语言包入口
-    ├── fa-IR.ts    # 波斯语语言包入口
-    ├── en-US/      # 英文语言包模块
-    │   ├── common.ts     # 通用翻译
-    │   ├── components.ts # 组件相关翻译
-    │   ├── menus.ts      # 菜单相关翻译
-    │   └── pages.ts      # 页面相关翻译
-    └── fa-IR/      # 波斯语语言包模块
-        ├── common.ts     # 通用翻译
-        ├── components.ts # 组件相关翻译
-        ├── menus.ts      # 菜单相关翻译
-        └── pages.ts      # 页面相关翻译
-```
-
-### 翻译文件说明
-
-1. **common.ts** - 通用翻译
-   - 包含按钮文本、提示信息、错误信息等通用文案
-   - 适用于整个应用的共享文本
-
-2. **components.ts** - 组件相关翻译
-   - 包含各个组件的标签、提示、占位符等文本
-   - 按组件名称组织翻译 key
-
-3. **menus.ts** - 菜单相关翻译
-   - 包含导航菜单、侧边栏等菜单项的文本
-   - 按菜单层级组织翻译 key
-
-4. **pages.ts** - 页面相关翻译
-   - 包含各个页面的标题、描述、提示等文本
-   - 按页面名称组织翻译 key
-
-### 使用方法
-
-1. 在组件中使用:
-
-```tsx
-import { useTranslation } from 'react-i18next';
-
-const MyComponent = () => {
-  const { t } = useTranslation();
-  
-  return (
-    <div>
-      <h1>{t('common.title')}</h1>
-      <p>{t('common.description')}</p>
-    </div>
-  );
-};
-```
-
-2. 语言包格式示例:
-
-```typescript
-// en-US/common.ts
-export default {
-  yes: 'Yes',
-  no: 'No',
-  ok: 'OK',
-  cancel: 'Cancel',
-  loading: 'Loading...'
-};
-```
-
-### 注意事项
-
-- 所有用户可见的文本都应该使用翻译函数
-- 动态内容使用插值语法:`t('key', { value: dynamicValue })`
-- 复数形式使用:`t('key', { count: number })`
-- 默认语言为英文
-- 波斯语文本需要从右到左(RTL)显示,注意布局适配
-
-## 网络请求使用说明
-
-项目使用 Axios 作为 HTTP 客户端,并封装了一套完整的请求工具。
-
-### 目录结构
-
-```
-src/
-├── config/
-│   └── request/           # 请求配置
-│       ├── index.ts       # 基础配置
-│       ├── authHeaderInterceptor.ts  # 认证拦截器
-│       ├── encryptionInterceptors.ts # 加密解密拦截器
-│       └── requestErrorConfig.ts # 错误处理配置
-├── services/             # API 服务
-│   ├── login/           # 登录相关接口
-│   │   ├── index.ts     # 接口实现
-│   │   └── typings.d.ts # 类型定义
-│   └── ...             # 其他模块接口
-└── utils/
-    └── request/        # 请求工具
-        ├── index.ts    # 请求实例
-        └── types.ts    # 类型定义
-```
-
-### 配置说明
-
-1. **基础配置** (`config/request/index.ts`)
-
-```typescript
-import { stringify } from 'qs';
-import { RequestConfig } from '@/utils/request/types';
-import { authHeaderInterceptor } from './authHeaderInterceptor';
-import { requestEncryptionInterceptor, responseDecryptionInterceptor } from './encryptionInterceptors';
-import { errorConfig } from './requestErrorConfig';
-
-const config: RequestConfig = {
-    baseURL: import.meta.env.VITE_API_BASE_URL!,
-    timeout: 15000,
-    headers: {
-        Accept: 'application/json, text/plain, */*',
-        'Content-Type': 'application/json',
-        'X-Requested-With': 'XMLHttpRequest',
-    },
-    paramsSerializer: (params) => stringify(params),
-    ...errorConfig,
-    requestInterceptors: [authHeaderInterceptor, requestEncryptionInterceptor],
-    responseInterceptors: [responseDecryptionInterceptor],
-};
-```
-
-2. **认证拦截器** (`config/request/authHeaderInterceptor.ts`)
-
-用于处理请求认证,自动添加 token 等认证信息。
-
-3. **加密解密配置**
-
-通过环境变量配置加密密钥:
-
-```env
-VITE_REQUEST_ENCRYPTION_KEY=your-encryption-key
-VITE_ENABLE_REQUEST_ENCRYPTION=true
-```
+## 本地存储
 
-4. **加密解密拦截器** (`config/request/encryptionInterceptors.ts`)
+- `src/utils/localUtils`、`src/utils/sessionUtils` 提供 `createLocalTools` / `createSessionTools`,支持按 key/value 加密与命名空间。
+- 通过环境变量配置加密密钥与存储命名空间,敏感数据建议开启加密选项。
 
-用于处理请求和响应的数据加密解密。可以通过请求配置选项控制单个请求是否启用加密:
-
-```typescript
-// 单个请求启用加密
-request('/api/data', {
-    encryption: {
-        enabled: true,
-        key: 'custom-key' // 可选,使用自定义密钥
-    }
-});
-
-// 单个请求禁用加密
-request('/api/data', {
-    encryption: {
-        enabled: false
-    }
-});
-```
-
-5. **错误处理配置** (`config/request/requestErrorConfig.ts`)
-
-统一处理请求错误,包括网络错误、业务错误等。
-
-可以通过配置 `skipErrorHandler: true` 来跳过默认的错误处理,自行处理错误。
-
-### API 服务定义
-
-在 `services` 目录下按模块定义 API 服务,每个模块包含类型定义和接口实现:
-
-1. **类型定义** (`services/[module]/typings.d.ts`)
-
-```typescript
-declare namespace API {
-    // 用户信息类型
-    type UserInfo = {
-        accessToken?: string;
-        refreshToken?: string;
-        expires?: number;
-        username?: string;
-        nickname?: string;
-        avatar?: string;
-        roles?: Array<string>;
-        permissions?: Array<string>;
-    };
-
-    // 登录参数类型
-    type LoginParams = {
-        username: string;
-        password: string;
-        captchaId: string;
-        captchaCode: string;
-    };
-
-    // 登录结果类型
-    type LoginResult = Result<UserInfo>;
-}
-```
-
-2. **接口实现** (`services/[module]/index.ts`)
-
-```typescript
-import { request } from '@/utils/request';
-
-// 登录接口
-export async function fetchLogin(body: API.LoginParams, options?: { [key: string]: any }) {
-    return request<API.LoginResult>('/user/login', {
-        method: 'POST',
-        data: body,
-        ...(options || {}),
-        requireToken: false,
-    });
-}
-
-// 获取验证码
-export async function fetchCaptcha(options?: { [key: string]: any }) {
-    return request<API.CaptchaResult>('/captcha/get', {
-        method: 'POST',
-        ...(options || {}),
-        requireToken: false,
-    });
-}
-```
-
-### 使用示例
-
-1. **在组件中使用**
-
-```typescript
-import { fetchLogin, fetchCaptcha } from '@/services/login';
-
-const LoginPage = () => {
-    const handleLogin = async () => {
-        try {
-            // 获取验证码
-            const captchaResult = await fetchCaptcha();
-            
-            // 登录
-            const result = await fetchLogin({
-                username: 'test',
-                password: '123456',
-                captchaId: captchaResult.id,
-                captchaCode: '1234',
-            });
-            
-            // 处理登录成功
-            // 注意:request 已经处理了 success 判断,这里直接使用返回的数据
-            console.log('登录成功:', result);
-            
-        } catch (error) {
-            // 处理错误
-        }
-    };
-};
-```
-
-2. **在 Model 中使用**
-
-```typescript
-// models/userModel.ts
-import { fetchLogin, fetchCaptcha } from '@/services/login';
-
-const useUserModel = () => {
-    const login = async (params: API.LoginParams) => {
-        try {
-            const result = await fetchLogin(params);
-            // 直接使用返回的数据,不需要判断 success
-            return result;
-        } catch (error) {
-            // 处理错误
-            throw error;
-        }
-    };
-
-    const getCaptcha = async () => {
-        return fetchCaptcha();
-    };
-
-    return {
-        login,
-        getCaptcha,
-    };
-};
-```
-
-### 请求配置选项
-
-```typescript
-interface IRequestOptions {
-    method?: 'GET' | 'POST' | 'PUT' | 'DELETE';
-    data?: any;
-    params?: any;
-    headers?: Record<string, string>;
-    timeout?: number;
-    getResponse?: boolean;  // 是否返回完整响应
-    requireToken?: boolean; // 是否需要 token
-    skipErrorHandler?: boolean; // 是否跳过默认的错误处理
-    requestInterceptors?: IRequestInterceptorTuple[];  // 请求拦截器
-    responseInterceptors?: IResponseInterceptorTuple[];  // 响应拦截器
-}
-```
-
-### 错误处理
-
-项目提供了统一的错误处理机制:
-
-1. 网络错误(如超时、断网等)
-2. HTTP 错误(如 404、500 等)
-3. 业务错误(后端返回的错误信息)
-
-可以通过配置 `skipErrorHandler: true` 来跳过默认的错误处理,自行处理错误。
-
-### 响应数据
-
-默认情况下,请求会直接返回服务器响应的数据。如果需要获取完整的响应信息(包括状态码、响应头等),可以配置 `getResponse: true`。
-
-示例:
-```typescript
-// 获取完整响应信息
-const response = await request('/api/data', {
-    getResponse: true,
-});
-// response 包含完整的响应信息
-console.log(response.status); // HTTP 状态码
-console.log(response.headers); // 响应头
-console.log(response.data); // 响应数据
-```
-
-### 注意事项
-
-1. 所有 API 请求都应该在 `services` 目录下按模块组织
-2. 每个模块包含 `typings.d.ts`(类型定义)和 `index.ts`(接口实现)
-3. 使用 TypeScript 类型定义请求参数和响应数据
-4. 需要认证的接口设置 `requireToken: true`
-5. 支持请求和响应拦截器,可以针对特定请求添加自定义拦截器
-
-## 本地存储使用说明
-
-项目提供了统一的本地存储工具,支持 localStorage 和 sessionStorage,并支持数据加密存储。
-
-### 目录结构
-
-```
-src/
-└── utils/
-    ├── storage/        # 存储工具
-    │   ├── index.ts    # 存储工具入口
-    │   └── types.ts    # 类型定义
-    ├── localUtils.ts   # localStorage 工具
-    └── sessionUtils.ts # sessionStorage 工具
-```
-
-### 配置说明
-
-1. **加密配置**
-
-通过环境变量配置加密密钥:
-```env
-VITE_STORAGE_ENCRYPTION_KEY=your-encryption-key
-```
-
-2. **命名空间配置**
-
-通过环境变量配置存储命名空间:
-```env
-VITE_APP_STORAGE_NAMESPACE=your-app-namespace
-```
-
-### 使用示例
-
-1. **创建存储工具实例**
-
-```typescript
-import { createLocalTools, createSessionTools } from '@/utils/localUtils';
-
-// 创建 localStorage 工具实例
-const ls = createLocalTools({
-    encryptKey: true,  // 是否加密 key
-    encryptValue: true,  // 是否加密 value
-});
-
-// 创建 sessionStorage 工具实例
-const ss = createSessionTools({
-    encryptKey: true,
-    encryptValue: true,
-});
-```
-
-2. **使用 localStorage**
-
-```typescript
-// 存储数据
-ls.setLocal('userInfo', { name: 'John', age: 30 });
-
-// 获取数据
-const userInfo = ls.getLocal<{ name: string; age: number }>('userInfo');
-
-// 删除数据
-ls.removeLocal('userInfo');
-
-// 清除所有数据
-ls.clearLocal();
-```
-
-3. **使用 sessionStorage**
-
-```typescript
-// 存储数据
-ss.setSession('tempData', { id: 1, status: 'pending' });
-
-// 获取数据
-const tempData = ss.getSession<{ id: number; status: string }>('tempData');
-
-// 删除数据
-ss.removeSession('tempData');
-
-// 清除所有数据
-ss.clearSession();
-```
-
-### 注意事项
-
-1. 所有存储的 key 都会自动添加应用命名空间前缀
-2. 加密存储的配置(key 和 value 是否加密)由创建存储工具实例时的参数决定
-3. 清除操作会清除所有属于当前应用的数据(包括加密和未加密的数据)
-4. 对于敏感数据,建议在创建存储工具实例时启用加密选项
-5. 每个存储操作都可以通过 opts 参数覆盖全局配置
-6. 建议在应用初始化时创建存储工具实例,并在整个应用中复用
-
-### 类型定义
-
-```typescript
-interface StorageOptions {
-    expire?: number;         // 过期时间,单位秒
-    encryptKey?: boolean;    // 是否加密 key
-    encryptValue?: boolean;  // 是否加密 value
-}
-
-interface LocalStorageInstance {
-    setLocal: <T = any>(key: string, value: T, opts?: StorageOptions) => void;
-    getLocal: <T = any>(key: string, opts?: StorageOptions) => T | null;
-    removeLocal: (key: string, opts?: StorageOptions) => void;
-    clearLocal: () => void;
-}
+## 部署
 
-interface SessionStorageInstance {
-    setSession: <T = any>(key: string, value: T, opts?: StorageOptions) => void;
-    getSession: <T = any>(key: string, opts?: StorageOptions) => T | null;
-    removeSession: (key: string, opts?: StorageOptions) => void;
-    clearSession: () => void;
-}
-```
+- 构建产物在 `dist/`,将对应环境(如 test/production)的构建结果部署到静态服务器或 CDN 即可。
+- 多环境通过上述 `build:dev` / `build:test` / `build:prod` 与对应 `.env.*` 区分。

+ 1 - 1
src/App.tsx

@@ -7,7 +7,7 @@ import zhCN from 'antd/locale/zh_CN';
 import { useTranslation } from 'react-i18next';
 import { RouterProvider } from 'react-router-dom';
 
-import { AntdAppInstanceCapture } from '@/config/request/antdAppInstance';
+import { AntdAppInstanceCapture } from '@/utils/antdAppInstance';
 import { DialogContainer } from './components/Dialog/DialogContainer';
 import router from './router';
 import models from './utils/model/autoImportModels';

+ 1 - 1
src/config/request/requestErrorConfig.ts

@@ -5,7 +5,7 @@ import { reportError } from '@/firebase';
 import { RequestConfig } from '@/utils/request/types';
 // import { toLoginPage } from '@/utils/routerUtils';
 
-import { message, notification } from './antdAppInstance';
+import { message, notification } from '@/utils/antdAppInstance';
 
 /**
  * @name 错误处理

+ 1 - 1
src/pages/pricing/useAction.tsx

@@ -3,7 +3,7 @@ import { useCallback } from 'react';
 import { Trans, useTranslation } from 'react-i18next';
 
 import LoginForm from '@/components/LoginForm';
-import { message } from '@/config/request/antdAppInstance';
+import { message } from '@/utils/antdAppInstance';
 import { PayUrlShowType } from '@/defines';
 import { useAppUrls } from '@/hooks/useAppUrls';
 import { dialogModel } from '@/models/dialogModel';

+ 0 - 0
src/config/request/antdAppInstance.tsx → src/utils/antdAppInstance.tsx