8 Commits

Author SHA1 Message Date
Misaka
87f6229d49 Update package-lock.json
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-03-01 12:22:26 +08:00
Misaka
c66dc2ecf8 feat: define ERP page element locators
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-03-01 12:21:58 +08:00
Misaka
9ac8707921 feat: configure Vitest testing framework
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-03-01 12:12:33 +08:00
Misaka
3222e03cea feat: define core TypeScript interfaces
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-03-01 11:53:59 +08:00
Misaka
4364c71bf9 fix: resolve environment configuration issues from code review
- Remove UTF-8 BOM from .env file
- Add missing ERP settings (ERP_HEADLESS, ERP_IGNORE_HTTPS_ERRORS, ERP_AUTO_CLOSE_BROWSER) to .env.example
- Add legacy configurations to .env.example

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-03-01 11:51:46 +08:00
Misaka
752cfc28a1 feat: add environment configuration template
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-03-01 11:44:59 +08:00
Misaka
82d3130188 feat: add core dependencies for Playwright migration
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-03-01 11:35:01 +08:00
Misaka
9ef1c3baa2 Update .gitignore to include .env and ensure .claude is ignored 2026-03-01 11:14:08 +08:00
11 changed files with 12548 additions and 5 deletions

35
.env.example Normal file
View File

@@ -0,0 +1,35 @@
# ERP System Configuration
ERP_URL=https://your-erp-system.com
ERP_USERNAME=your_username
ERP_PASSWORD=your_password
# Additional ERP Settings
ERP_HEADLESS=true
ERP_IGNORE_HTTPS_ERRORS=true
ERP_AUTO_CLOSE_BROWSER=true
# Database Configuration - SQL Server
SQL_SERVER_HOST=localhost
SQL_SERVER_PORT=1433
SQL_SERVER_DATABASE=erp_db
SQL_SERVER_USERNAME=sa
SQL_SERVER_PASSWORD=your_password
MYSQL_HOST=localhost
MYSQL_PORT=3306
MYSQL_DATABASE=erp_db
MYSQL_USERNAME=root
MYSQL_PASSWORD=your_password
# Application Settings
LOG_LEVEL=info
DOWNLOAD_DIR=./downloads
TEMP_DIR=./temp
# Legacy configurations (if needed)
DB_SQLSERVER_DRIVER=ODBC Driver 18 for SQL Server
DB_TRUST_SERVER_CERTIFICATE=yes
DB_TYPE=mysql
DB_MYSQL_HOST=192.168.31.83
DB_MYSQL_PORT=3306
DB_MYSQL_CHARSET=utf8mb4

4
.gitignore vendored
View File

@@ -6,4 +6,6 @@ out
*.log*
#AI Agent
.claude
.claude
.env

12338
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -18,20 +18,34 @@
"build:unpack": "npm run build && electron-builder --dir",
"build:win": "npm run build && electron-builder --win",
"build:mac": "electron-vite build && electron-builder --mac",
"build:linux": "electron-vite build && electron-builder --linux"
"build:linux": "electron-vite build && electron-builder --linux",
"test": "vitest",
"test:run": "vitest run",
"test:coverage": "vitest run --coverage"
},
"dependencies": {
"@electron-toolkit/preload": "^3.0.2",
"@electron-toolkit/utils": "^4.0.0"
"@electron-toolkit/utils": "^4.0.0",
"date-fns": "^4.1.0",
"dotenv": "^17.3.1",
"exceljs": "^4.4.0",
"mssql": "^12.2.0",
"mysql2": "^3.18.2",
"playwright": "^1.58.2",
"uuid": "^13.0.0",
"zod": "^4.3.6"
},
"devDependencies": {
"@electron-toolkit/eslint-config-prettier": "^3.0.0",
"@electron-toolkit/eslint-config-ts": "^3.1.0",
"@electron-toolkit/tsconfig": "^2.0.0",
"@types/node": "^22.19.1",
"@playwright/test": "^1.58.2",
"@types/node": "^22.19.13",
"@types/react": "^19.2.7",
"@types/react-dom": "^19.2.3",
"@types/uuid": "^10.0.0",
"@vitejs/plugin-react": "^5.1.1",
"@vitest/coverage-v8": "^4.0.18",
"electron": "^39.2.6",
"electron-builder": "^26.0.12",
"electron-vite": "^5.0.0",
@@ -43,6 +57,7 @@
"react": "^19.2.1",
"react-dom": "^19.2.1",
"typescript": "^5.9.3",
"vite": "^7.2.6"
"vite": "^7.2.6",
"vitest": "^4.0.18"
}
}

View File

@@ -0,0 +1,44 @@
/**
* ERP Page Element Locators
* Reference: playwrite/utils/ discrete_material_plan_extractor.py
* Reference: playwrite/utils/ discrete_material_plan_cleaner.py
*/
export const ERP_LOCATORS = {
// Login Page
login: {
usernameInput: '#username',
passwordInput: '#password',
submitButton: 'button[type="submit"]',
},
// Main Frame
main: {
mainIframe: '#mainiframe',
loadingOverlay: '.loading-overlay',
contentFrame: '#contentframe',
},
// Extractor (Data Export) Page
extractor: {
orderNumberInput: 'input[name="orderNumber"]',
queryButton: 'button:has-text("查询")',
exportButton: 'button:has-text("导出")',
},
// Cleaner (Material Delete) Page
cleaner: {
orderNumberInput: 'input[name="orderNumber"]',
materialGrid: 'table.material-grid tbody tr',
saveButton: 'button:has-text("保存")',
},
// Common Elements
common: {
successMessage: '.message.success',
errorMessage: '.message.error',
confirmDialog: '.confirm-dialog',
confirmButton: 'button:has-text("确定")',
cancelButton: 'button:has-text("取消")',
},
};

View File

@@ -0,0 +1,21 @@
export interface CleanerInput {
orderNumbers: string[];
materialCodes: string[];
dryRun: boolean;
onProgress?: (message: string, progress: number) => void;
}
export interface CleanerResult {
ordersProcessed: number;
materialsDeleted: number;
materialsSkipped: number;
errors: string[];
details: OrderCleanDetail[];
}
export interface OrderCleanDetail {
orderNumber: string;
materialsDeleted: number;
materialsSkipped: number;
errors: string[];
}

View File

@@ -0,0 +1,16 @@
export interface ErpConfig {
url: string;
username: string;
password: string;
}
export interface ErpSession {
browser: import('playwright').Browser;
context: import('playwright').BrowserContext;
page: import('playwright').Page;
isLoggedIn: boolean;
}
export interface ProgressCallback {
(message: string, progress?: number): void;
}

View File

@@ -0,0 +1,17 @@
export interface ExtractorInput {
orderNumbers: string[];
batchSize?: number;
onProgress?: (message: string, progress: number) => void;
}
export interface ExtractorResult {
downloadedFiles: string[];
mergedFile: string | null;
recordCount: number;
errors: string[];
}
export interface OrderInfo {
orderNumber: string;
productionId: string;
}

15
tests/setup.ts Normal file
View File

@@ -0,0 +1,15 @@
import { beforeAll, afterAll } from 'vitest';
import dotenv from 'dotenv';
// Load environment variables
dotenv.config({ path: '.env' });
beforeAll(async () => {
// Global test setup
console.log('Test suite starting...');
});
afterAll(async () => {
// Global test teardown
console.log('Test suite completed.');
});

View File

@@ -0,0 +1,26 @@
import { describe, it, expect } from 'vitest';
import { ERP_LOCATORS } from '../../src/main/services/erp/locators';
describe('ERP Locators', () => {
it('should have login page locators defined', () => {
expect(ERP_LOCATORS.login.usernameInput).toBeDefined();
expect(ERP_LOCATORS.login.passwordInput).toBeDefined();
expect(ERP_LOCATORS.login.submitButton).toBeDefined();
});
it('should have main frame locator', () => {
expect(ERP_LOCATORS.main.mainIframe).toBeDefined();
});
it('should have extractor page locators', () => {
expect(ERP_LOCATORS.extractor.orderNumberInput).toBeDefined();
expect(ERP_LOCATORS.extractor.queryButton).toBeDefined();
expect(ERP_LOCATORS.extractor.exportButton).toBeDefined();
});
it('should have cleaner page locators', () => {
expect(ERP_LOCATORS.cleaner.orderNumberInput).toBeDefined();
expect(ERP_LOCATORS.cleaner.materialGrid).toBeDefined();
expect(ERP_LOCATORS.cleaner.saveButton).toBeDefined();
});
});

14
vitest.config.ts Normal file
View File

@@ -0,0 +1,14 @@
import { defineConfig } from 'vitest/config';
export default defineConfig({
test: {
globals: true,
environment: 'node',
include: ['tests/**/*.{test,spec}.{ts,tsx}'],
exclude: ['node_modules', 'dist', 'out'],
coverage: {
provider: 'v8',
reporter: ['text', 'json', 'html'],
},
},
});