Files
kuaishai2/lib/features/programs/services/excel_template_service.dart
Developer d91791edaf feat(programs): Excel 模板下载 + .xlsx 解析导入
- 新增 excel 4.0.6 / path_provider 2.1.5 依赖
- ExcelTemplateService:生成 Programs + Steps 双表模板(保存到应用文档目录)
- ExcelImportService:解析 .xlsx 并写入数据库,跳过已存在 code、按 program_code 关联步骤
- programs_page 顶部新增「下载模板」按钮,导入按钮改用 Excel 解析
- 移除被取代的 program_import_service.dart
- AppLocalizations 新增 downloadTemplate 键
- 验证:flutter analyze 无新增 issue;flutter build apk --debug 通过
2026-06-04 15:27:34 +08:00

135 lines
4.3 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import 'dart:io';
import 'package:excel/excel.dart';
import 'package:path_provider/path_provider.dart';
/// Excel 模板服务
///
/// 生成 .xlsx 模板用于程序/步骤批量导入。
/// 模板包含两张表:
/// - Programs程序基础信息
/// - Steps步骤参数通过 program_code 与 Programs 关联)
class ExcelTemplateService {
static final ExcelTemplateService instance = ExcelTemplateService._internal();
ExcelTemplateService._internal();
/// 工作表名称
static const String sheetPrograms = 'Programs';
static const String sheetSteps = 'Steps';
/// 生成模板并保存到应用文档目录,返回文件对象
Future<File> generateTemplate() async {
final excel = Excel.createExcel();
final bytes = _buildTemplateBytes(excel);
final dir = await getApplicationDocumentsDirectory();
final file = File('${dir.path}/program_template.xlsx');
await file.writeAsBytes(bytes, flush: true);
return file;
}
/// 构建模板字节流(可在测试中直接调用)
List<int> _buildTemplateBytes(Excel excel) {
// 默认创建的第一个 sheet 重命名
final defaultSheet = excel.getDefaultSheet();
if (defaultSheet != null && defaultSheet != sheetPrograms) {
excel.rename(defaultSheet, sheetPrograms);
}
_writeProgramsSheet(excel);
_writeStepsSheet(excel);
return excel.encode()!;
}
void _writeProgramsSheet(Excel excel) {
final sheet = excel[sheetPrograms];
final headerStyle = CellStyle(
bold: true,
backgroundColorHex: ExcelColor.fromHexString('FFD9E1F2'),
horizontalAlign: HorizontalAlign.Center,
);
// 表头
final headers = ['code', 'name', 'temperature', 'airflowTime', 'status'];
sheet.appendRow(headers.map((h) => TextCellValue(h)).toList());
for (var i = 0; i < headers.length; i++) {
sheet
.cell(CellIndex.indexByColumnRow(columnIndex: i, rowIndex: 0))
.cellStyle = headerStyle;
}
// 示例行
final sample1 = ['P001', '示例程序-标准流程', 50, 60, 1];
final sample2 = ['P002', '示例程序-快速流程', 45, 30, 1];
sheet.appendRow(sample1.map((v) => TextCellValue(v.toString())).toList());
sheet.appendRow(sample2.map((v) => TextCellValue(v.toString())).toList());
// 说明行(用前缀标记,避免被解析)
final note = '说明code 必填且唯一name 必填temperature/airflowTime 整数status:1启用 0停用';
sheet.appendRow([TextCellValue(note)]);
// 列宽
sheet.setColumnWidth(0, 14);
sheet.setColumnWidth(1, 26);
sheet.setColumnWidth(2, 14);
sheet.setColumnWidth(3, 14);
sheet.setColumnWidth(4, 10);
}
void _writeStepsSheet(Excel excel) {
final sheet = excel[sheetSteps];
final headerStyle = CellStyle(
bold: true,
backgroundColorHex: ExcelColor.fromHexString('FFD9E1F2'),
horizontalAlign: HorizontalAlign.Center,
);
final headers = [
'program_code',
'step_no',
'position',
'name',
'mixTime',
'magnetTime',
'volume',
'blowTime',
'speed',
];
sheet.appendRow(headers.map((h) => TextCellValue(h)).toList());
for (var i = 0; i < headers.length; i++) {
sheet
.cell(CellIndex.indexByColumnRow(columnIndex: i, rowIndex: 0))
.cellStyle = headerStyle;
}
// 示例行P001 / P002 各两步
final samples = <List<Object>>[
['P001', 1, 'A1', '加样', 30, 0, 500, 0, 5],
['P001', 2, 'A2', '混合', 60, 10, 300, 30, 5],
['P002', 1, 'B1', '混合', 20, 5, 400, 0, 4],
];
for (final row in samples) {
sheet.appendRow(row.map((v) {
if (v is num) return IntCellValue(v.toInt());
return TextCellValue(v.toString());
}).toList());
}
// 说明行
final note =
'说明program_code 对应 Programs.codestep_no 整数从 1 开始position 形如 A1/B2mixTime/magnetTime/volume/blowTime 单位秒或微升speed 1-10';
sheet.appendRow([TextCellValue(note)]);
// 列宽
sheet.setColumnWidth(0, 14);
sheet.setColumnWidth(1, 10);
sheet.setColumnWidth(2, 12);
sheet.setColumnWidth(3, 14);
sheet.setColumnWidth(4, 10);
sheet.setColumnWidth(5, 12);
sheet.setColumnWidth(6, 10);
sheet.setColumnWidth(7, 10);
sheet.setColumnWidth(8, 8);
}
}