Replace pandas+openpyxl with exceljs for Excel file processing. This migration enables seamless integration with the Electron main process and maintains 1:1 functional parity with the Python implementation. Key changes: - Add exceljs dependency (v4.4.0) - Implement ExcelConverter class in TypeScript with strict types - Add comprehensive unit tests (13 test cases, all passing) - Support field name mapping, order parsing, and material extraction - Handle empty data tables and file conflicts gracefully Verification: - Successfully tested with sample Excel file (99 orders, 625 records) - All unit tests passing - Output format matches Python version Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
114 lines
6.0 KiB
Markdown
114 lines
6.0 KiB
Markdown
## 1. 项目背景与概述
|
||
|
||
本项目(ERPAuto)旨在将原先基于 `Python + Tkinter + Playwright (Sync)` 构建的内部 ERP(用友 BIP)自动化辅助工具,重构为现代化的 `Electron + React + TypeScript` 桌面端应用。
|
||
|
||
- **代码参考源**:原项目挂载在 `playwrite/` 目录下。
|
||
|
||
- **重构目标**:
|
||
|
||
1. 彻底移除 Python 运行时依赖。
|
||
|
||
2. 将原有的同步阻塞自动化流程重构为纯异步的 Node.js/TypeScript 实现。
|
||
|
||
3. 解耦 UI 层与业务逻辑层,实现高可测试性。
|
||
|
||
4. 利用 Electron 原生能力处理文件 I/O 与数据持久化。
|
||
|
||
|
||
## 2. 整体架构设计
|
||
|
||
项目采用 Electron 标准的主进程(Main)与渲染进程(Renderer)隔离架构:
|
||
|
||
```
|
||
electron-app/
|
||
├── src/
|
||
│ ├── main/ # 核心后端逻辑 (原 Python utils/ 目录的归宿)
|
||
│ │ ├── config/ # 集中式配置管理 (环境变量解析 env.ts)
|
||
│ │ ├── services/ # 核心自动化业务流
|
||
│ │ │ ├── authService.ts # (已完成) 登录/登出模块
|
||
│ │ │ ├── cleanerService.ts # 待迁移:物料计划清理器
|
||
│ │ │ └── extractorService.ts # 待迁移:物料计划提取器
|
||
│ │ ├── utils/ # 通用工具
|
||
│ │ │ └── excelConverter.ts # 待迁移:Excel 数据转换器
|
||
│ │ └── index.ts # IPC 通信注册与 Electron 生命周期
|
||
│ ├── preload/ # 安全网桥 (ContextBridge)
|
||
│ └── renderer/ # React 前端 UI
|
||
├── tests/ # 单元测试 (Vitest)
|
||
└── .env # 环境变量配置
|
||
```
|
||
|
||
## 3. 技术栈选型
|
||
|
||
|模块|旧版 Python 技术栈|新版 Electron 技术栈|备注|
|
||
|---|---|---|---|
|
||
|**整体框架**|Tkinter + Python|**Electron + Vite**|提升跨平台性能与 UI 现代化|
|
||
|**前端界面**|Tkinter Canvas/Grid|**React 18 + TS + UI组件库**|原有弹窗、进度条改为 Web 形式|
|
||
|**网页自动化**|`playwright-python`|**`playwright-core`**|**核心!** 使用 `playwright-core` 直接调用系统本地浏览器,避免 Electron 打包体积膨胀|
|
||
|**表格处理**|`pandas`|**`exceljs`**|用于内存中合并 Excel 批次数据,不再依赖沉重的科学计算库|
|
||
|**数据库**|`pymysql` / `pymssql`|**`mysql2` / `mssql`**|直接在 Node.js 中维持连接池|
|
||
|**单元测试**|`pytest`|**`vitest`**|提供极速的 TS 测试环境|
|
||
|
||
## 4. 核心技术规范与避坑指南(接手 AI 必读)
|
||
|
||
为了避免重蹈覆辙,后续接手的 AI 助手在生成代码时,**必须**严格遵守以下规范:
|
||
|
||
### 4.1. 严禁猜测 DOM 选择器 (No Guessing Locators)
|
||
|
||
原 Python 代码中有极其精确的页面定位逻辑。在翻译 `extractor` 和 `cleaner` 时,**必须先完整阅读**原 `.py` 源码。
|
||
|
||
- 例如:原代码使用了 `get_by_role("textbox", name="用户名")`,在 TS 中必须 1:1 翻译为 `getByRole('textbox', { name: '用户名' })`,绝对禁止凭空捏造如 `.u-input` 等 CSS 选择器。
|
||
|
||
|
||
### 4.2. 跨越 Iframe 陷阱 (Iframe Penetration)
|
||
|
||
用友 BIP 系统的核心工作台全部嵌套在 `id="forwardFrame"` 这个 iframe 中。
|
||
|
||
- **规则**:绝大部分页面操作(如填表、点击查询)都必须基于 `frameElement.contentFrame()` 获取到的 `mainFrame` 进行,而非直接操作外层 `page` 对象。需要时刻注意操作上下文是否已因页面刷新而销毁 (Detached)。
|
||
|
||
|
||
### 4.3. 同步转异步范式 (Strict Async/Await)
|
||
|
||
原 Python 代码为同步范式(如 `time.sleep(1)`,`btn.click()`)。
|
||
|
||
- **规则**:在 TS 中,所有的 Playwright 操作都必须前置 `await`。
|
||
|
||
- `time.sleep(n)` 必须翻译为 `await page.waitForTimeout(n * 1000)`。
|
||
|
||
|
||
### 4.4. 环境变量与空值合并 (Env & Nullish Coalescing)
|
||
|
||
- 读取配置时,必须使用 `??`(空值合并操作符)替代 `||`(逻辑或),以防止空字符串 `''` 触发了意外的 Fallback(即 `options.username ?? ENV.ERP_USERNAME`)。
|
||
|
||
- 所有的环境变量通过 `src/main/config/env.ts` 集中挂载,严禁在业务代码中到处写 `process.env.XXX`。
|
||
|
||
|
||
### 4.5. 依赖注入与 TDD (Dependency Injection & Testing)
|
||
|
||
- 诸如 `ExtractorService` 这样的庞大类,其内部不应直接 `new ExcelConverter()`,而应通过构造函数注入依赖,以保证单元测试的可行性。
|
||
|
||
- 每完成一个 `XXXService.ts` 的编写,必须同步在 `tests/unit/` 目录下交付对应的 Vitest 单元测试。
|
||
|
||
- 在编写 Playwright 相关的测试时,必须提供深度的 `vi.mock('playwright-core', ...)` 模拟,确保测试用例可以在无真实浏览器的 CI 环境下瞬间跑通。
|
||
|
||
|
||
## 5. 待执行的迁移任务清单
|
||
|
||
接下来的开发工作应严格按照从底层数据流向高层业务逻辑的顺序进行:
|
||
|
||
- [x] **Task 1: Auth 模块** (`utils/auth.py` -> `authService.ts`) - **已完成**
|
||
|
||
- [ ] **Task 2: 数据清理模块** (`utils/excel_converter.py` -> `excelConverter.ts`)
|
||
|
||
- **难点**:无。纯逻辑处理,需使用 `exceljs` 替代 `pandas.concat`,将提取的数据整理成标准 JSON/Array 供写入数据库使用。
|
||
|
||
- [ ] **Task 3: 自动化清洗核心** (`utils/discrete_material_plan_cleaner.py` -> `cleanerService.ts`)
|
||
|
||
- **难点**:涉及复杂的循环逻辑,需要在网页表格中比对物料集合并逐行执行“点击删除按钮”的操作。注意处理翻页与异步等待。
|
||
|
||
- [ ] **Task 4: 自动化提取核心** (`utils/discrete_material_plan_extractor.py` -> `extractorService.ts`)
|
||
|
||
- **难点**:需要接管浏览器的“文件下载”事件 (`expect_download`),处理分页逻辑,并将下载的 Excel 暂存后移交给 Task 2 的转换器。
|
||
|
||
- [ ] **Task 5: React 前端与 IPC 集成**
|
||
|
||
- 待底层 Service 全部跑通脱机测试后,绘制 UI 界面,打通主进程与渲染进程的通信,绑定“开始”、“停止”按钮,及实时日志输出。 |