feat: add automatic database import after ERP data extraction

- Add DataImportService for reading Excel and importing to database
- Extend DiscreteMaterialPlanDAO with deleteBySourceNumbers and batchInsert
- Auto-trigger database write after successful Excel merge
- Support batch delete by SourceNumber and batch insert (1000/batch)
- Update ExtractorPage UI to show import results
- Fix SQL Server query to handle undefined recordset for DELETE/INSERT

Co-Authored-By: Claude (glm-5) <noreply@anthropic.com>
This commit is contained in:
Misaka_Company
2026-03-04 11:26:54 +08:00
parent abe51d17fa
commit 63ea81e0d6
8 changed files with 887 additions and 5 deletions

View File

@@ -1,5 +1,15 @@
import React, { useState, useEffect } from 'react'
import { Download, Play, Terminal } from 'lucide-react'
import { Download, Play, Terminal, Database } from 'lucide-react'
// Import result type (matches the type from main process)
interface ImportResult {
success: boolean
recordsRead: number
recordsDeleted: number
recordsImported: number
uniqueSourceNumbers: number
errors: string[]
}
// Extractor result type (matches the type from main process)
interface ExtractorResult {
@@ -7,6 +17,7 @@ interface ExtractorResult {
mergedFile: string | null
recordCount: number
errors: string[]
importResult?: ImportResult
}
interface ExtractorProgress {
@@ -212,6 +223,54 @@ const ExtractorPage: React.FC = () => {
</div>
)}
{/* Database import results */}
{result?.importResult && (
<div className="bg-white rounded-xl shadow-sm border border-slate-200 p-6 flex flex-col gap-4">
<h3 className="font-semibold text-lg border-b pb-2 flex items-center gap-2">
<Database size={20} className={result.importResult.success ? 'text-emerald-600' : 'text-red-500'} />
<span className={result.importResult.success ? 'text-emerald-600' : 'text-red-500'}>
</span>
</h3>
<div className="grid grid-cols-4 gap-4">
<div className="bg-slate-50 p-4 rounded-lg border border-slate-100 flex flex-col items-center justify-center">
<span className="text-slate-500 text-sm"></span>
<span className="text-2xl font-bold text-slate-800">
{result.importResult.recordsRead}
</span>
</div>
<div className="bg-slate-50 p-4 rounded-lg border border-slate-100 flex flex-col items-center justify-center">
<span className="text-slate-500 text-sm"></span>
<span className="text-2xl font-bold text-amber-600">
{result.importResult.recordsDeleted}
</span>
</div>
<div className="bg-slate-50 p-4 rounded-lg border border-slate-100 flex flex-col items-center justify-center">
<span className="text-slate-500 text-sm"></span>
<span className="text-2xl font-bold text-emerald-600">
{result.importResult.recordsImported}
</span>
</div>
<div className="bg-slate-50 p-4 rounded-lg border border-slate-100 flex flex-col items-center justify-center">
<span className="text-slate-500 text-sm"></span>
<span className="text-2xl font-bold text-blue-600">
{result.importResult.uniqueSourceNumbers}
</span>
</div>
</div>
{result.importResult.errors.length > 0 && (
<div className="bg-red-50 p-4 rounded-lg border border-red-200">
<span className="text-red-600 text-sm font-medium block mb-1"></span>
<ul className="text-sm text-red-500 list-disc list-inside">
{result.importResult.errors.map((err, idx) => (
<li key={idx}>{err}</li>
))}
</ul>
</div>
)}
</div>
)}
<div className="bg-slate-900 rounded-xl shadow-lg border border-slate-700 overflow-hidden flex flex-col h-[500px]">
<div className="bg-slate-800 px-4 py-2 flex items-center justify-between border-b border-slate-700">
<div className="flex items-center gap-2 text-slate-400 text-sm">