From 55bdaa921197ae6a0f45404a5223f9da6a70e643 Mon Sep 17 00:00:00 2001 From: Developer <91611@user.local> Date: Thu, 4 Jun 2026 15:51:03 +0800 Subject: [PATCH] =?UTF-8?q?feat(programs):=20Excel=20=E5=AF=BC=E5=85=A5?= =?UTF-8?q?=E6=94=B9=E4=B8=BA=E5=85=A8=E9=87=8F=E8=A6=86=E7=9B=96=E6=A8=A1?= =?UTF-8?q?=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 已存在 code 的程序不再跳过,而是: - 用 Excel 中的字段更新 program(保留 id) - 删除该 program 的全部旧步骤 - 按 Excel 中的步骤重新写入 返回值变量名 importedCount -> processedCount 更准确。 Toast 文案同步:成功处理 / Excel 无有效数据。 --- .../programs/pages/programs_page.dart | 4 +- .../services/excel_import_service.dart | 48 ++++++++++++++----- 2 files changed, 39 insertions(+), 13 deletions(-) diff --git a/lib/features/programs/pages/programs_page.dart b/lib/features/programs/pages/programs_page.dart index 49259f2..1c070b4 100644 --- a/lib/features/programs/pages/programs_page.dart +++ b/lib/features/programs/pages/programs_page.dart @@ -441,9 +441,9 @@ class _ProgramsPageState extends ConsumerState { if (!context.mounted) return; if (importedCount > 0) { - ToastService.showSuccess(context, '成功导入 $importedCount 个程序'); + ToastService.showSuccess(context, '成功处理 $importedCount 个程序'); } else { - ToastService.showWarning(context, '未导入新程序(编号可能已存在)'); + ToastService.showWarning(context, 'Excel 中无有效程序数据'); } } catch (e) { if (!context.mounted) return; diff --git a/lib/features/programs/services/excel_import_service.dart b/lib/features/programs/services/excel_import_service.dart index 577b10a..ca5419b 100644 --- a/lib/features/programs/services/excel_import_service.dart +++ b/lib/features/programs/services/excel_import_service.dart @@ -18,7 +18,11 @@ class ExcelImportService { ExcelImportService._internal(); - /// 从 .xlsx 文件导入程序,返回成功导入的程序数量 + /// 从 .xlsx 文件导入程序,返回成功处理的程序数量(新建 + 覆盖) + /// + /// 行为: + /// - code 不存在:新建程序 + 写入步骤 + /// - code 已存在:全量覆盖程序字段,并删除旧步骤后写入新步骤 Future importFromExcel(File file) async { final bytes = await file.readAsBytes(); final excel = Excel.decodeBytes(bytes); @@ -33,9 +37,11 @@ class ExcelImportService { throw const ExcelImportException('Programs 表无有效数据'); } - // 读取已有 code,避免重复 + // 已有 code → 完整 Program(用于覆盖时取 id) final existing = await _programService.getAllPrograms(); - final existingCodes = existing.map((p) => p.code).toSet(); + final existingByCode = { + for (final p in existing) p.code: p, + }; // 解析步骤 final stepsSheet = _findSheet(excel, ExcelTemplateService.sheetSteps); @@ -43,17 +49,37 @@ class ExcelImportService { ? >{} : _parseSteps(stepsSheet); - int importedCount = 0; + int processedCount = 0; for (final program in programs) { try { - if (existingCodes.contains(program.code)) { - continue; + final existingProgram = existingByCode[program.code]; + final int programId; + if (existingProgram == null) { + programId = await _programService.addProgram(program); + } else { + // 全量覆盖:保留 id,其余字段取 Excel + programId = existingProgram.id!; + await _programService.updateProgram( + existingProgram.copyWith( + name: program.name, + temperature: program.temperature, + airflowTime: program.airflowTime, + status: program.status, + createdAt: program.createdAt, + ), + ); + // 清空旧步骤 + final oldSteps = + await _programService.getStepsByProgramId(programId); + if (oldSteps.isNotEmpty) { + await _programService.deleteSteps( + oldSteps.map((s) => s.id!).toList(), + ); + } } - final programId = await _programService.addProgram(program); - + // 写入新步骤(按 step_no 排序后重新编号为 1..N) final rawSteps = stepsByCode[program.code] ?? const <_RawStep>[]; - // 按 step_no 排序后写入 rawSteps.sort((a, b) => a.stepNo.compareTo(b.stepNo)); for (var i = 0; i < rawSteps.length; i++) { final raw = rawSteps[i]; @@ -71,14 +97,14 @@ class ExcelImportService { await _programService.addStep(step); } - importedCount++; + processedCount++; } catch (_) { // 单条失败不影响其他程序 continue; } } - return importedCount; + return processedCount; } Sheet? _findSheet(Excel excel, String name) {