137 lines
4.4 KiB
Dart
137 lines
4.4 KiB
Dart
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 getDownloadsDirectory() ?? 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.code;step_no 整数从 1 开始;position 形如 A1/B2;mixTime/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);
|
||
}
|
||
}
|