feat: add ERP login debug tool with documentation
Add interactive debugging tool for ERP login flow analysis: - Add tsx dependency for TypeScript script execution - Add npm scripts: debug:erp-login and debug:config-path - Add erp-login-debug.ts with automated login and element inspection - Add comprehensive usage guide and quick reference documentation The debug tool automates ERP login and provides pause points for manual element inspection using browser DevTools or Playwright Inspector. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
236
docs/erp-login-debug-guide.md
Normal file
236
docs/erp-login-debug-guide.md
Normal file
@@ -0,0 +1,236 @@
|
||||
# ERP 登录调试工具使用说明
|
||||
|
||||
## 目的
|
||||
|
||||
用于人工调试 ERP 登录流程,定位主界面特征元素,以便优化登录成功的判定逻辑。
|
||||
|
||||
## 前置准备
|
||||
|
||||
### 1. 配置 ERP 登录信息
|
||||
|
||||
编辑 `src/main/tools/erp-login-debug.ts` 文件,修改以下配置:
|
||||
|
||||
```typescript
|
||||
const ERP_CONFIG = {
|
||||
url: 'https://your-erp-server.com', // ← 修改为你的 ERP 地址
|
||||
username: 'your_username', // ← 修改为你的用户名
|
||||
password: 'your_password' // ← 修改为你的密码
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 确保 tsx 已安装
|
||||
|
||||
如果运行时报错提示找不到 `tsx`,请安装:
|
||||
|
||||
```bash
|
||||
npm install -g tsx
|
||||
# 或作为项目依赖
|
||||
npm install --save-dev tsx
|
||||
```
|
||||
|
||||
## 使用方法
|
||||
|
||||
### 方式一:使用 npm 脚本(推荐)
|
||||
|
||||
```bash
|
||||
npm run debug:erp-login
|
||||
```
|
||||
|
||||
### 方式二:直接运行
|
||||
|
||||
```bash
|
||||
npx tsx src/main/tools/erp-login-debug.ts
|
||||
```
|
||||
|
||||
## 调试流程
|
||||
|
||||
### 步骤 1:启动脚本
|
||||
|
||||
运行命令后,脚本会显示配置信息并等待你确认:
|
||||
|
||||
```
|
||||
============================================================
|
||||
ERP 登录调试工具
|
||||
============================================================
|
||||
目标 URL: https://your-erp-server.com
|
||||
用户名:your_username
|
||||
密码: ***
|
||||
============================================================
|
||||
|
||||
操作步骤:
|
||||
1. 浏览器将自动打开并尝试登录
|
||||
2. 如果登录失败,请检查配置或手动重试
|
||||
3. 登录成功后,会自动暂停并打开开发者工具
|
||||
4. 使用元素选择器定位主界面特征元素
|
||||
5. 记录元素选择器,按 Ctrl+C 退出脚本
|
||||
|
||||
按 Enter 键开始...
|
||||
```
|
||||
|
||||
### 步骤 2:自动登录
|
||||
|
||||
脚本会自动执行:
|
||||
|
||||
- 打开浏览器
|
||||
- 导航到登录页面
|
||||
- 输入用户名和密码
|
||||
- 点击登录按钮
|
||||
- 处理强制登录确认对话框(如果有)
|
||||
|
||||
### 步骤 3:人工元素定位
|
||||
|
||||
登录成功后,脚本会暂停并显示:
|
||||
|
||||
```
|
||||
============================================================
|
||||
✓ 登录成功!
|
||||
============================================================
|
||||
|
||||
现在进入调试模式,请进行以下操作:
|
||||
|
||||
1. 按 F12 打开浏览器开发者工具
|
||||
2. 使用元素选择器 (Ctrl+Shift+C) 点击主界面特征元素
|
||||
3. 在 Elements 面板中右键元素 → Copy → Copy selector
|
||||
4. 或者使用 Playwright Inspector:
|
||||
- 在控制台输入:await page.pause()
|
||||
- 使用 Inspector 的元素选择工具
|
||||
|
||||
建议定位的特征元素:
|
||||
- 主界面顶部导航栏
|
||||
- 侧边菜单栏
|
||||
- 主内容区域的唯一标识
|
||||
- 用户信息显示区域
|
||||
- 任何登录后独有的界面元素
|
||||
|
||||
============================================================
|
||||
```
|
||||
|
||||
### 步骤 4:记录元素选择器
|
||||
|
||||
在开发者工具中:
|
||||
|
||||
1. **使用元素选择器** (Ctrl+Shift+C) 点击界面元素
|
||||
2. **在 Elements 面板** 查看元素 HTML
|
||||
3. **右键元素** → Copy → 选择以下之一:
|
||||
- `Copy selector` - CSS 选择器
|
||||
- `Copy XPath` - XPath 路径
|
||||
- `Copy JS path` - JavaScript 路径
|
||||
|
||||
### 步骤 5:更新 locators.ts
|
||||
|
||||
将找到的元素选择器添加到 `src/main/services/erp/locators.ts`:
|
||||
|
||||
```typescript
|
||||
export const ERP_LOCATORS = {
|
||||
// ... 现有配置 ...
|
||||
|
||||
// 新增:主界面特征元素(用于登录成功判定)
|
||||
mainPage: {
|
||||
topNavigationBar: '#top-nav', // 顶部导航栏
|
||||
sideMenu: '.side-menu', // 侧边菜单
|
||||
userProfile: '.user-profile', // 用户信息
|
||||
welcomeMessage: 'internal:has-text="欢迎"' // 欢迎消息
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 步骤 6:退出脚本
|
||||
|
||||
按 `Ctrl+C` 终止脚本,浏览器会在 5 秒后自动关闭。
|
||||
|
||||
## Playwright Inspector 使用技巧
|
||||
|
||||
### 开启 Inspector
|
||||
|
||||
在脚本暂停时,在浏览器控制台输入:
|
||||
|
||||
```javascript
|
||||
await page.pause()
|
||||
```
|
||||
|
||||
会打开 Playwright Inspector,提供:
|
||||
|
||||
- 元素选择器
|
||||
- 实时 locator 测试
|
||||
- 代码生成
|
||||
|
||||
### 测试 Locator
|
||||
|
||||
在 Inspector 控制台测试 locator 是否有效:
|
||||
|
||||
```javascript
|
||||
// 测试 CSS 选择器
|
||||
await page.locator('#top-nav').count()
|
||||
|
||||
// 测试 role-based 选择器
|
||||
await page.getByRole('navigation').count()
|
||||
|
||||
// 测试文本选择器
|
||||
await page.getByText('欢迎').count()
|
||||
```
|
||||
|
||||
如果返回数量 > 0,说明选择器有效。
|
||||
|
||||
## 推荐的特征元素
|
||||
|
||||
选择登录成功判定元素时,优先选择:
|
||||
|
||||
1. **唯一性** - 只在登录后出现
|
||||
2. **稳定性** - 不易随版本变更
|
||||
3. **易定位** - 有明确的 id、class 或文本
|
||||
|
||||
### 推荐元素示例
|
||||
|
||||
| 元素类型 | 选择器示例 | 说明 |
|
||||
| ------------ | ----------------------- | ---------------------- |
|
||||
| 顶部导航栏 | `#top-nav` | 登录后才会显示的主导航 |
|
||||
| 用户菜单 | `.user-menu` | 显示当前用户名的菜单 |
|
||||
| 欢迎消息 | `text=欢迎` | 包含用户名的欢迎语 |
|
||||
| 工作台标题 | `h1:has-text("工作台")` | 主界面标题 |
|
||||
| 功能模块网格 | `.module-grid` | 功能模块入口区域 |
|
||||
|
||||
## 常见问题
|
||||
|
||||
### Q: 登录失败,提示找不到元素
|
||||
|
||||
**A**: 检查以下几点:
|
||||
|
||||
1. ERP URL 是否正确
|
||||
2. 用户名密码是否正确
|
||||
3. 网络连接是否正常
|
||||
4. ERP 系统是否可访问
|
||||
5. 是否需要验证码(如果 ERP 有验证码,需要手动输入)
|
||||
|
||||
### Q: 登录后没有暂停
|
||||
|
||||
**A**: 检查控制台输出,可能登录流程中抛出了异常。查看错误信息并修复。
|
||||
|
||||
### Q: 如何调试特定页面?
|
||||
|
||||
**A**: 修改脚本中的登录后逻辑,导航到特定页面:
|
||||
|
||||
```typescript
|
||||
// 登录后导航到特定页面
|
||||
await page.goto(`${ERP_CONFIG.url}/yonbip/sc`)
|
||||
await page.waitForTimeout(3000)
|
||||
```
|
||||
|
||||
### Q: 如何保存调试会话?
|
||||
|
||||
**A**: Playwright 支持录制 trace:
|
||||
|
||||
```typescript
|
||||
await context.tracing.start({ screenshots: true, snapshots: true })
|
||||
// ... 操作 ...
|
||||
await context.tracing.stop({ path: 'trace.zip' })
|
||||
```
|
||||
|
||||
然后使用 `npx playwright show-trace trace.zip` 查看。
|
||||
|
||||
## 下一步
|
||||
|
||||
找到稳定的主界面元素后,修改以下文件优化登录判定:
|
||||
|
||||
1. **更新 locators.ts** - 添加主界面元素定位器
|
||||
2. **修改 erp-auth.ts** - 在登录成功后等待主界面元素
|
||||
3. **更新测试** - 验证新的登录判定逻辑
|
||||
241
docs/erp-login-debug-quickref.md
Normal file
241
docs/erp-login-debug-quickref.md
Normal file
@@ -0,0 +1,241 @@
|
||||
# ERP 登录调试工具 - 快速参考
|
||||
|
||||
## 创建的文件
|
||||
|
||||
### 1. 调试脚本
|
||||
|
||||
**路径**: `src/main/tools/erp-login-debug.ts`
|
||||
|
||||
用途:人工调试 ERP 登录流程,定位主界面特征元素
|
||||
|
||||
### 2. 使用文档
|
||||
|
||||
**路径**: `docs/erp-login-debug-guide.md`
|
||||
|
||||
详细的调试工具使用说明
|
||||
|
||||
### 3. package.json 更新
|
||||
|
||||
添加了新的 npm 脚本和依赖:
|
||||
|
||||
- `debug:erp-login` - 运行调试脚本
|
||||
- `debug:config-path` - 运行配置路径调试(已有)
|
||||
- `tsx` - TypeScript 执行器依赖
|
||||
|
||||
## 快速开始
|
||||
|
||||
### 步骤 1:配置登录信息
|
||||
|
||||
编辑 `src/main/tools/erp-login-debug.ts` 第 19-23 行:
|
||||
|
||||
```typescript
|
||||
const ERP_CONFIG = {
|
||||
url: 'https://your-erp-server.com', // ← 修改
|
||||
username: 'your_username', // ← 修改
|
||||
password: 'your_password' // ← 修改
|
||||
}
|
||||
```
|
||||
|
||||
### 步骤 2:运行调试
|
||||
|
||||
```bash
|
||||
npm run debug:erp-login
|
||||
```
|
||||
|
||||
### 步骤 3:定位元素
|
||||
|
||||
登录成功后:
|
||||
|
||||
1. 按 **F12** 打开开发者工具
|
||||
2. 按 **Ctrl+Shift+C** 启用元素选择器
|
||||
3. 点击主界面特征元素
|
||||
4. 右键 → Copy → Copy selector
|
||||
|
||||
### 步骤 4:更新定位器
|
||||
|
||||
将找到的元素添加到 `src/main/services/erp/locators.ts`:
|
||||
|
||||
```typescript
|
||||
export const ERP_LOCATORS = {
|
||||
// ... 现有配置 ...
|
||||
|
||||
// 新增:主界面特征元素
|
||||
mainPage: {
|
||||
// 在此添加找到的元素
|
||||
topNav: '#top-nav',
|
||||
userMenu: '.user-menu'
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 脚本功能
|
||||
|
||||
### 自动执行
|
||||
|
||||
- ✅ 启动浏览器(可见窗口,非无头模式)
|
||||
- ✅ 导航到登录页面
|
||||
- ✅ 输入用户名和密码
|
||||
- ✅ 点击登录按钮
|
||||
- ✅ 处理强制登录确认对话框
|
||||
|
||||
### 调试支持
|
||||
|
||||
- ✅ 登录成功后自动暂停
|
||||
- ✅ 保持浏览器打开
|
||||
- ✅ 支持 F12 开发者工具
|
||||
- ✅ 支持 Playwright Inspector
|
||||
|
||||
### 安全特性
|
||||
|
||||
- ✅ 密码显示为星号
|
||||
- ✅ 需要按 Enter 确认后才开始
|
||||
- ✅ 退出前 5 秒缓冲时间
|
||||
|
||||
## 常用命令
|
||||
|
||||
```bash
|
||||
# 运行调试脚本
|
||||
npm run debug:erp-login
|
||||
|
||||
# 或使用 npx 直接运行
|
||||
npx tsx src/main/tools/erp-login-debug.ts
|
||||
|
||||
# 查看帮助
|
||||
npx tsx --help
|
||||
```
|
||||
|
||||
## 调试技巧
|
||||
|
||||
### 测试 Locator 有效性
|
||||
|
||||
在浏览器控制台(登录后暂停时):
|
||||
|
||||
```javascript
|
||||
// 测试 CSS 选择器
|
||||
await page.locator('#top-nav').count()
|
||||
|
||||
// 测试文本选择器
|
||||
await page.getByText('欢迎').isVisible()
|
||||
|
||||
// 测试 role 选择器
|
||||
await page.getByRole('navigation').count()
|
||||
```
|
||||
|
||||
返回值 > 0 或 true 表示选择器有效。
|
||||
|
||||
### 查看元素详细信息
|
||||
|
||||
```javascript
|
||||
// 获取元素 HTML
|
||||
const element = await page.$('#top-nav')
|
||||
console.log(await element.innerHTML())
|
||||
|
||||
// 获取元素属性
|
||||
console.log(await element.getAttributes())
|
||||
```
|
||||
|
||||
### 截图保存
|
||||
|
||||
```javascript
|
||||
// 全屏截图
|
||||
await page.screenshot({ path: 'login-success.png' })
|
||||
|
||||
// 元素截图
|
||||
const element = await page.$('#top-nav')
|
||||
await element.screenshot({ path: 'top-nav.png' })
|
||||
```
|
||||
|
||||
## 推荐的特征元素
|
||||
|
||||
选择登录成功判定元素的标准:
|
||||
|
||||
| 标准 | 说明 | 示例 |
|
||||
| ---------- | -------------- | ------------------- |
|
||||
| **唯一性** | 只在登录后出现 | 用户菜单、工作台 |
|
||||
| **稳定性** | 不易随版本变更 | ID 选择器优于 class |
|
||||
| **易定位** | 有明确的标识 | 有 id、独特文本 |
|
||||
|
||||
### 推荐元素类型
|
||||
|
||||
1. **顶部导航栏** - `#top-nav`, `.navbar`
|
||||
2. **用户信息区域** - `.user-info`, `.user-menu`
|
||||
3. **欢迎消息** - 包含用户名的文本
|
||||
4. **功能模块入口** - 主界面的模块网格
|
||||
5. **侧边菜单栏** - `.sidebar`, `.menu`
|
||||
|
||||
## 故障排查
|
||||
|
||||
### 问题:脚本启动后立即退出
|
||||
|
||||
**原因**: tsx 未安装
|
||||
|
||||
**解决**:
|
||||
|
||||
```bash
|
||||
npm install
|
||||
```
|
||||
|
||||
### 问题:找不到用户名/密码输入框
|
||||
|
||||
**原因**:
|
||||
|
||||
1. ERP URL 不正确
|
||||
2. 页面结构已变更
|
||||
3. 登录页面加载超时
|
||||
|
||||
**解决**:
|
||||
|
||||
1. 检查 ERP_CONFIG.url 是否正确
|
||||
2. 手动打开 URL 确认页面结构
|
||||
3. 增加 timeout 值(第 25 行)
|
||||
|
||||
### 问题:登录后没有暂停
|
||||
|
||||
**原因**: 登录流程抛出异常
|
||||
|
||||
**解决**: 查看控制台错误信息,检查:
|
||||
|
||||
- 网络连接
|
||||
- ERP 系统可用性
|
||||
- 用户名密码正确性
|
||||
|
||||
### 问题:无法定位元素
|
||||
|
||||
**原因**:
|
||||
|
||||
1. 元素在 iframe 中
|
||||
2. 元素动态加载
|
||||
3. 选择器不正确
|
||||
|
||||
**解决**:
|
||||
|
||||
1. 检查元素是否在嵌套 iframe 中
|
||||
2. 增加等待时间 `await page.waitForTimeout(2000)`
|
||||
3. 使用更具体的选择器
|
||||
|
||||
## 下一步
|
||||
|
||||
找到稳定的主界面元素后:
|
||||
|
||||
1. **更新 locators.ts**
|
||||
- 添加 `mainPage` 配置节
|
||||
- 定义登录成功判定元素
|
||||
|
||||
2. **修改 erp-auth.ts**
|
||||
- 在 `login()` 方法末尾
|
||||
- 等待主界面元素出现
|
||||
- 作为登录成功的最终判定
|
||||
|
||||
3. **验证修改**
|
||||
- 重新运行调试脚本
|
||||
- 确认新的判定逻辑有效
|
||||
- 更新相关文档
|
||||
|
||||
## 相关文件
|
||||
|
||||
| 文件 | 用途 |
|
||||
| ----------------------------------- | ---------- |
|
||||
| `src/main/tools/erp-login-debug.ts` | 调试脚本 |
|
||||
| `src/main/services/erp/locators.ts` | 元素定位器 |
|
||||
| `src/main/services/erp/erp-auth.ts` | 登录服务 |
|
||||
| `docs/erp-login-debug-guide.md` | 详细文档 |
|
||||
544
package-lock.json
generated
544
package-lock.json
generated
@@ -54,6 +54,7 @@
|
||||
"react": "^19.2.1",
|
||||
"react-dom": "^19.2.1",
|
||||
"tailwindcss": "^4.2.1",
|
||||
"tsx": "^4.19.3",
|
||||
"typescript": "^5.9.3",
|
||||
"vite": "^7.2.6",
|
||||
"vitest": "^4.0.18"
|
||||
@@ -7149,6 +7150,19 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/get-tsconfig": {
|
||||
"version": "4.13.6",
|
||||
"resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.6.tgz",
|
||||
"integrity": "sha512-shZT/QMiSHc/YBLxxOkMtgSid5HFoauqCE3/exfsEcwg1WkeqjG+V40yBbBrsD+jW2HDXcs28xOfcbm2jI8Ddw==",
|
||||
"devOptional": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"resolve-pkg-maps": "^1.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/privatenumber/get-tsconfig?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/glob": {
|
||||
"version": "7.2.3",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
|
||||
@@ -10582,6 +10596,16 @@
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/resolve-pkg-maps": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz",
|
||||
"integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==",
|
||||
"devOptional": true,
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/responselike": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz",
|
||||
@@ -11861,6 +11885,526 @@
|
||||
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
|
||||
"license": "0BSD"
|
||||
},
|
||||
"node_modules/tsx": {
|
||||
"version": "4.21.0",
|
||||
"resolved": "https://registry.npmjs.org/tsx/-/tsx-4.21.0.tgz",
|
||||
"integrity": "sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==",
|
||||
"devOptional": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"esbuild": "~0.27.0",
|
||||
"get-tsconfig": "^4.7.5"
|
||||
},
|
||||
"bin": {
|
||||
"tsx": "dist/cli.mjs"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"fsevents": "~2.3.3"
|
||||
}
|
||||
},
|
||||
"node_modules/tsx/node_modules/@esbuild/aix-ppc64": {
|
||||
"version": "0.27.3",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.3.tgz",
|
||||
"integrity": "sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg==",
|
||||
"cpu": [
|
||||
"ppc64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"aix"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/tsx/node_modules/@esbuild/android-arm": {
|
||||
"version": "0.27.3",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.3.tgz",
|
||||
"integrity": "sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/tsx/node_modules/@esbuild/android-arm64": {
|
||||
"version": "0.27.3",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.3.tgz",
|
||||
"integrity": "sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/tsx/node_modules/@esbuild/android-x64": {
|
||||
"version": "0.27.3",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.3.tgz",
|
||||
"integrity": "sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/tsx/node_modules/@esbuild/darwin-arm64": {
|
||||
"version": "0.27.3",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.3.tgz",
|
||||
"integrity": "sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/tsx/node_modules/@esbuild/darwin-x64": {
|
||||
"version": "0.27.3",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.3.tgz",
|
||||
"integrity": "sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/tsx/node_modules/@esbuild/freebsd-arm64": {
|
||||
"version": "0.27.3",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.3.tgz",
|
||||
"integrity": "sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/tsx/node_modules/@esbuild/freebsd-x64": {
|
||||
"version": "0.27.3",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.3.tgz",
|
||||
"integrity": "sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/tsx/node_modules/@esbuild/linux-arm": {
|
||||
"version": "0.27.3",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.3.tgz",
|
||||
"integrity": "sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/tsx/node_modules/@esbuild/linux-arm64": {
|
||||
"version": "0.27.3",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.3.tgz",
|
||||
"integrity": "sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/tsx/node_modules/@esbuild/linux-ia32": {
|
||||
"version": "0.27.3",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.3.tgz",
|
||||
"integrity": "sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/tsx/node_modules/@esbuild/linux-loong64": {
|
||||
"version": "0.27.3",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.3.tgz",
|
||||
"integrity": "sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA==",
|
||||
"cpu": [
|
||||
"loong64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/tsx/node_modules/@esbuild/linux-mips64el": {
|
||||
"version": "0.27.3",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.3.tgz",
|
||||
"integrity": "sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw==",
|
||||
"cpu": [
|
||||
"mips64el"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/tsx/node_modules/@esbuild/linux-ppc64": {
|
||||
"version": "0.27.3",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.3.tgz",
|
||||
"integrity": "sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA==",
|
||||
"cpu": [
|
||||
"ppc64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/tsx/node_modules/@esbuild/linux-riscv64": {
|
||||
"version": "0.27.3",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.3.tgz",
|
||||
"integrity": "sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ==",
|
||||
"cpu": [
|
||||
"riscv64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/tsx/node_modules/@esbuild/linux-s390x": {
|
||||
"version": "0.27.3",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.3.tgz",
|
||||
"integrity": "sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw==",
|
||||
"cpu": [
|
||||
"s390x"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/tsx/node_modules/@esbuild/linux-x64": {
|
||||
"version": "0.27.3",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.3.tgz",
|
||||
"integrity": "sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/tsx/node_modules/@esbuild/netbsd-arm64": {
|
||||
"version": "0.27.3",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.3.tgz",
|
||||
"integrity": "sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"netbsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/tsx/node_modules/@esbuild/netbsd-x64": {
|
||||
"version": "0.27.3",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.3.tgz",
|
||||
"integrity": "sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"netbsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/tsx/node_modules/@esbuild/openbsd-arm64": {
|
||||
"version": "0.27.3",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.3.tgz",
|
||||
"integrity": "sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"openbsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/tsx/node_modules/@esbuild/openbsd-x64": {
|
||||
"version": "0.27.3",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.3.tgz",
|
||||
"integrity": "sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"openbsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/tsx/node_modules/@esbuild/openharmony-arm64": {
|
||||
"version": "0.27.3",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.3.tgz",
|
||||
"integrity": "sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"openharmony"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/tsx/node_modules/@esbuild/sunos-x64": {
|
||||
"version": "0.27.3",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.3.tgz",
|
||||
"integrity": "sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"sunos"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/tsx/node_modules/@esbuild/win32-arm64": {
|
||||
"version": "0.27.3",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.3.tgz",
|
||||
"integrity": "sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/tsx/node_modules/@esbuild/win32-ia32": {
|
||||
"version": "0.27.3",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.3.tgz",
|
||||
"integrity": "sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/tsx/node_modules/@esbuild/win32-x64": {
|
||||
"version": "0.27.3",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.3.tgz",
|
||||
"integrity": "sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/tsx/node_modules/esbuild": {
|
||||
"version": "0.27.3",
|
||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.3.tgz",
|
||||
"integrity": "sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg==",
|
||||
"devOptional": true,
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"esbuild": "bin/esbuild"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@esbuild/aix-ppc64": "0.27.3",
|
||||
"@esbuild/android-arm": "0.27.3",
|
||||
"@esbuild/android-arm64": "0.27.3",
|
||||
"@esbuild/android-x64": "0.27.3",
|
||||
"@esbuild/darwin-arm64": "0.27.3",
|
||||
"@esbuild/darwin-x64": "0.27.3",
|
||||
"@esbuild/freebsd-arm64": "0.27.3",
|
||||
"@esbuild/freebsd-x64": "0.27.3",
|
||||
"@esbuild/linux-arm": "0.27.3",
|
||||
"@esbuild/linux-arm64": "0.27.3",
|
||||
"@esbuild/linux-ia32": "0.27.3",
|
||||
"@esbuild/linux-loong64": "0.27.3",
|
||||
"@esbuild/linux-mips64el": "0.27.3",
|
||||
"@esbuild/linux-ppc64": "0.27.3",
|
||||
"@esbuild/linux-riscv64": "0.27.3",
|
||||
"@esbuild/linux-s390x": "0.27.3",
|
||||
"@esbuild/linux-x64": "0.27.3",
|
||||
"@esbuild/netbsd-arm64": "0.27.3",
|
||||
"@esbuild/netbsd-x64": "0.27.3",
|
||||
"@esbuild/openbsd-arm64": "0.27.3",
|
||||
"@esbuild/openbsd-x64": "0.27.3",
|
||||
"@esbuild/openharmony-arm64": "0.27.3",
|
||||
"@esbuild/sunos-x64": "0.27.3",
|
||||
"@esbuild/win32-arm64": "0.27.3",
|
||||
"@esbuild/win32-ia32": "0.27.3",
|
||||
"@esbuild/win32-x64": "0.27.3"
|
||||
}
|
||||
},
|
||||
"node_modules/tsx/node_modules/fsevents": {
|
||||
"version": "2.3.3",
|
||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
|
||||
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/type-check": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
|
||||
|
||||
@@ -24,7 +24,9 @@
|
||||
"test:coverage": "vitest run --coverage",
|
||||
"test:e2e": "playwright test",
|
||||
"test:e2e:ui": "playwright test --ui",
|
||||
"test:e2e:report": "playwright show-report"
|
||||
"test:e2e:report": "playwright show-report",
|
||||
"debug:erp-login": "tsx src/main/tools/erp-login-debug.ts",
|
||||
"debug:config-path": "tsx src/main/tools/config-path-debug.ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"@electron-toolkit/preload": "^3.0.2",
|
||||
@@ -74,6 +76,7 @@
|
||||
"tailwindcss": "^4.2.1",
|
||||
"typescript": "^5.9.3",
|
||||
"vite": "^7.2.6",
|
||||
"vitest": "^4.0.18"
|
||||
"vitest": "^4.0.18",
|
||||
"tsx": "^4.19.3"
|
||||
}
|
||||
}
|
||||
|
||||
232
src/main/tools/erp-login-debug.ts
Normal file
232
src/main/tools/erp-login-debug.ts
Normal file
@@ -0,0 +1,232 @@
|
||||
/**
|
||||
* ERP 登录调试脚本
|
||||
*
|
||||
* 用途:人工调试 ERP 登录流程,定位主界面特征元素
|
||||
* 使用方式:
|
||||
* 1. 修改下方的 ERP_CONFIG 配置(URL、用户名、密码)
|
||||
* 2. 运行:npx ts-node src/main/tools/erp-login-debug.ts
|
||||
* 3. 登录后会自动暂停,打开 Playwright Inspector 进行元素定位
|
||||
* 4. 在 Inspector 中点击主界面元素,获取选择器
|
||||
* 5. 将找到的元素选择器添加到 locators.ts
|
||||
*
|
||||
* 调试模式说明:
|
||||
* - headless: false - 显示浏览器窗口
|
||||
* - slowMo: 100 - 放慢操作速度便于观察
|
||||
* - debugger 语句会暂停执行,打开开发者工具
|
||||
*/
|
||||
|
||||
import { chromium } from 'playwright'
|
||||
import path from 'path'
|
||||
|
||||
// ==================== 配置区域 ====================
|
||||
const ERP_CONFIG = {
|
||||
url: 'https://68.11.34.30:8082/', // ← 修改为你的 ERP 地址
|
||||
username: 'BLDpengqiangqiang', // ← 修改为你的用户名
|
||||
password: 'Cqbld123456.' // ← 修改为你的密码
|
||||
}
|
||||
|
||||
// 调试配置
|
||||
const DEBUG_CONFIG = {
|
||||
headless: false, // 必须为 false,需要看到浏览器
|
||||
slowMo: 100, // 操作间隔(毫秒)
|
||||
timeout: 60000 // 超时时间(毫秒)
|
||||
}
|
||||
// ================================================
|
||||
|
||||
async function debugErpLogin(): Promise<void> {
|
||||
console.log('='.repeat(60))
|
||||
console.log('ERP 登录调试工具')
|
||||
console.log('='.repeat(60))
|
||||
console.log('目标 URL:', ERP_CONFIG.url)
|
||||
console.log('用户名:', ERP_CONFIG.username)
|
||||
console.log('密码:', '***'.repeat(ERP_CONFIG.password.length))
|
||||
console.log('='.repeat(60))
|
||||
console.log()
|
||||
console.log('操作步骤:')
|
||||
console.log('1. 浏览器将自动打开并尝试登录')
|
||||
console.log('2. 如果登录失败,请检查配置或手动重试')
|
||||
console.log('3. 登录成功后,会自动暂停并打开开发者工具')
|
||||
console.log('4. 使用元素选择器定位主界面特征元素')
|
||||
console.log('5. 记录元素选择器,按 Ctrl+C 退出脚本')
|
||||
console.log()
|
||||
console.log('按 Enter 键开始...')
|
||||
|
||||
// 等待用户确认
|
||||
await new Promise<void>((resolve) => {
|
||||
process.stdin.resume()
|
||||
process.stdin.once('data', () => {
|
||||
process.stdin.pause()
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
|
||||
let browser: any = null
|
||||
let context: any = null
|
||||
let page: any = null
|
||||
|
||||
try {
|
||||
console.log('\n正在启动浏览器...')
|
||||
|
||||
// 启动浏览器(带调试配置)
|
||||
browser = await chromium.launch({
|
||||
headless: DEBUG_CONFIG.headless,
|
||||
slowMo: DEBUG_CONFIG.slowMo,
|
||||
args: ['--ignore-certificate-errors', '--ignore-ssl-errors', '--disable-web-security']
|
||||
})
|
||||
|
||||
context = await browser.newContext({
|
||||
acceptDownloads: true,
|
||||
viewport: { width: 1920, height: 1080 },
|
||||
ignoreHTTPSErrors: true,
|
||||
javaScriptEnabled: true
|
||||
})
|
||||
|
||||
page = await context.newPage()
|
||||
|
||||
// 启用详细的控制台日志
|
||||
page.on('console', (msg: any) => {
|
||||
console.log(`[Page Console] ${msg.type()}: ${msg.text()}`)
|
||||
})
|
||||
|
||||
page.on('pageerror', (error: any) => {
|
||||
console.error(`[Page Error] ${error.message}`)
|
||||
})
|
||||
|
||||
// 导航到登录页面
|
||||
const loginUrl = `${ERP_CONFIG.url}/yonbip/resources/uap/rbac/login/main/index.html`
|
||||
console.log(`正在加载登录页面:${loginUrl}`)
|
||||
await page.goto(loginUrl, { timeout: DEBUG_CONFIG.timeout })
|
||||
await page.waitForLoadState('domcontentloaded')
|
||||
console.log('登录页面已加载')
|
||||
|
||||
// 等待并定位登录表单 iframe
|
||||
console.log('等待登录表单...')
|
||||
await page.waitForSelector('#forwardFrame', { state: 'attached', timeout: 15000 })
|
||||
const frameLocator = page.locator('#forwardFrame')
|
||||
const contentFrame = await frameLocator.contentFrame()
|
||||
|
||||
if (!contentFrame) {
|
||||
throw new Error('无法访问 forwardFrame 内容框架')
|
||||
}
|
||||
|
||||
const mainFrame = contentFrame
|
||||
console.log('登录表单框架已就绪')
|
||||
|
||||
// 填充用户名
|
||||
console.log('正在输入用户名...')
|
||||
try {
|
||||
const usernameInput = mainFrame.getByRole('textbox', { name: '用户名' })
|
||||
await usernameInput.waitFor({ state: 'visible', timeout: 5000 })
|
||||
await usernameInput.fill(ERP_CONFIG.username)
|
||||
console.log('用户名已输入')
|
||||
} catch (e: any) {
|
||||
console.error('找不到用户名输入框:', e.message)
|
||||
throw new Error('找不到用户名输入框,请检查页面结构是否改变')
|
||||
}
|
||||
|
||||
// 填充密码
|
||||
console.log('正在输入密码...')
|
||||
try {
|
||||
const passwordInput = mainFrame.getByRole('textbox', { name: '密码' })
|
||||
await passwordInput.waitFor({ state: 'visible', timeout: 5000 })
|
||||
await passwordInput.fill(ERP_CONFIG.password)
|
||||
console.log('密码已输入')
|
||||
} catch (e: any) {
|
||||
console.error('找不到密码输入框:', e.message)
|
||||
throw new Error('找不到密码输入框,请检查页面结构是否改变')
|
||||
}
|
||||
await page.pause()
|
||||
// 点击登录按钮
|
||||
console.log('正在点击登录按钮...')
|
||||
try {
|
||||
const loginButton = mainFrame.getByRole('button', { name: '登录' })
|
||||
await loginButton.waitFor({ state: 'visible', timeout: 5000 })
|
||||
await loginButton.click()
|
||||
console.log('已点击登录按钮')
|
||||
} catch (e: any) {
|
||||
console.error('找不到登录按钮:', e.message)
|
||||
throw new Error('找不到登录按钮,请检查页面结构是否改变')
|
||||
}
|
||||
|
||||
// 等待页面加载
|
||||
console.log('等待登录响应...')
|
||||
await page.waitForLoadState('domcontentloaded', { timeout: 10000 })
|
||||
await page.waitForTimeout(2000) // 额外等待,确保页面完全加载
|
||||
|
||||
// 处理强制登录确认对话框
|
||||
try {
|
||||
const confirmBtn = mainFrame.getByRole('button', { name: '确定' })
|
||||
const count = await confirmBtn.count()
|
||||
if (count > 0) {
|
||||
console.log('检测到强制登录确认对话框,正在确认...')
|
||||
await confirmBtn.first().click()
|
||||
await page.waitForTimeout(2000)
|
||||
console.log('已确认强制登录')
|
||||
} else {
|
||||
console.log('普通登录,无需确认')
|
||||
}
|
||||
} catch {
|
||||
console.log('未检测到确认对话框')
|
||||
}
|
||||
|
||||
// ==================== 登录成功,进入调试模式 ====================
|
||||
console.log()
|
||||
console.log('='.repeat(60))
|
||||
console.log('✓ 登录成功!')
|
||||
console.log('='.repeat(60))
|
||||
console.log()
|
||||
console.log('现在进入调试模式,请进行以下操作:')
|
||||
console.log()
|
||||
console.log('1. 按 F12 打开浏览器开发者工具')
|
||||
console.log('2. 使用元素选择器 (Ctrl+Shift+C) 点击主界面特征元素')
|
||||
console.log('3. 在 Elements 面板中右键元素 → Copy → Copy selector')
|
||||
console.log('4. 或者使用 Playwright Inspector:')
|
||||
console.log(' - 在控制台输入: await page.pause()')
|
||||
console.log(' - 使用 Inspector 的元素选择工具')
|
||||
console.log()
|
||||
console.log('建议定位的特征元素:')
|
||||
console.log('- 主界面顶部导航栏')
|
||||
console.log('- 侧边菜单栏')
|
||||
console.log('- 主内容区域的唯一标识')
|
||||
console.log('- 用户信息显示区域')
|
||||
console.log('- 任何登录后独有的界面元素')
|
||||
console.log()
|
||||
console.log('按 Ctrl+C 退出脚本')
|
||||
console.log('='.repeat(60))
|
||||
|
||||
// 保持浏览器打开,等待用户调试
|
||||
// 使用 pause 可以让用户手动恢复或使用 Inspector
|
||||
await page.pause()
|
||||
} catch (error: any) {
|
||||
console.error()
|
||||
console.error('='.repeat(60))
|
||||
console.error('错误:', error.message)
|
||||
console.error('='.repeat(60))
|
||||
console.error()
|
||||
console.error('调试提示:')
|
||||
console.error('1. 检查 ERP_CONFIG 配置是否正确')
|
||||
console.error('2. 检查网络连接')
|
||||
console.error('3. 确认 ERP 系统可访问')
|
||||
console.error('4. 如果是元素找不到,可能需要更新 locators.ts')
|
||||
} finally {
|
||||
// 清理资源(给用户时间保存信息)
|
||||
console.log()
|
||||
console.log('等待 5 秒后关闭浏览器...')
|
||||
await new Promise((resolve) => setTimeout(resolve, 5000))
|
||||
|
||||
if (context) {
|
||||
await context.close()
|
||||
}
|
||||
if (browser) {
|
||||
await browser.close()
|
||||
}
|
||||
console.log('浏览器已关闭')
|
||||
process.exit(0)
|
||||
}
|
||||
}
|
||||
|
||||
// 运行调试脚本
|
||||
debugErpLogin().catch((err) => {
|
||||
console.error('脚本执行失败:', err)
|
||||
process.exit(1)
|
||||
})
|
||||
Reference in New Issue
Block a user