feat: add Flutter web build support

This commit is contained in:
2026-08-02 01:30:07 +08:00
parent 98bf7ed6a9
commit f0b8af0bc8
24 changed files with 708 additions and 329 deletions

View File

@@ -1,5 +1,3 @@
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:uuid/uuid.dart';
@@ -44,12 +42,17 @@ class _EvidencePageState extends State<EvidencePage> {
}
Future<void> _restore() async {
final draft = await widget.drafts.readDraft(widget.session.identity, widget.taskIdentity);
final draft = await widget.drafts.readDraft(
widget.session.identity,
widget.taskIdentity,
);
if (draft == null || !mounted) return;
final values = draft['evidence'];
if (values is List) {
for (final value in values.whereType<Map<Object?, Object?>>()) {
final mapped = value.map<String, Object?>((key, item) => MapEntry(key.toString(), item));
final mapped = value.map<String, Object?>(
(key, item) => MapEntry(key.toString(), item),
);
final stage = mapped['stage'] as String? ?? '';
if (stage.isNotEmpty) _evidence[stage] = mapped;
}
@@ -70,7 +73,7 @@ class _EvidencePageState extends State<EvidencePage> {
accountIdentity: widget.session.identity,
taskIdentity: widget.taskIdentity,
stage: stage,
sourcePath: image.path,
source: image,
);
_evidence[stage] = {
'stage': stage,
@@ -97,25 +100,27 @@ class _EvidencePageState extends State<EvidencePage> {
Future<void> _submit() async {
if (!_requiredStages.every(_evidence.containsKey) || _result.text.trim().isEmpty) {
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('请完成结果说明和全部必需取证项')));
ScaffoldMessenger.of(
context,
).showSnackBar(const SnackBar(content: Text('请完成结果说明和全部必需取证项')));
return;
}
setState(() => _busy = true);
final temporaryFiles = <String>[];
final temporaryFiles = <XFile>[];
try {
await _save();
final inputs = <EvidenceInput>[];
for (final item in _evidence.values) {
final path = await widget.drafts.materializeAttachment(
final file = await widget.drafts.materializeAttachment(
accountIdentity: widget.session.identity,
sealedName: item['sealed_name'] as String,
);
temporaryFiles.add(path);
temporaryFiles.add(file);
inputs.add(
EvidenceInput(
evidenceType: item['stage'] as String,
mediaType: item['media_type'] as String,
filePath: path,
file: file,
capturedAt: DateTime.parse(item['captured_at'] as String),
requestNo: item['request_no'] as String,
),
@@ -127,16 +132,20 @@ class _EvidencePageState extends State<EvidencePage> {
conclusion: _conclusion,
evidence: inputs,
);
await widget.drafts.deleteDraft(widget.session.identity, widget.taskIdentity);
await widget.drafts.deleteDraft(
widget.session.identity,
widget.taskIdentity,
);
if (mounted) Navigator.pop(context, true);
} catch (error) {
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('提交失败,草稿仍安全保留:$error')));
ScaffoldMessenger.of(
context,
).showSnackBar(SnackBar(content: Text('提交失败,草稿仍安全保留:$error')));
}
} finally {
for (final path in temporaryFiles) {
final file = File(path);
if (file.existsSync()) await file.delete();
for (final file in temporaryFiles) {
await widget.drafts.discardMaterializedAttachment(file);
}
if (mounted) setState(() => _busy = false);
}