feat: add Flutter web build support
This commit is contained in:
@@ -1,5 +1,3 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:image_picker/image_picker.dart';
|
||||
@@ -42,14 +40,19 @@ class _WorkDetailPageState extends State<WorkDetailPage> {
|
||||
? widget.repository.deliveryDetail(widget.identity)
|
||||
: widget.repository.ticketDetail(widget.identity);
|
||||
|
||||
Future<void> _run(Future<void> Function(WorkItem) action, WorkItem item) async {
|
||||
Future<void> _run(
|
||||
Future<void> Function(WorkItem) action,
|
||||
WorkItem item,
|
||||
) async {
|
||||
setState(() => _busy = true);
|
||||
try {
|
||||
await action(item);
|
||||
setState(() => _future = _load());
|
||||
} catch (error) {
|
||||
if (mounted) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(error.toString())));
|
||||
ScaffoldMessenger.of(
|
||||
context,
|
||||
).showSnackBar(SnackBar(content: Text(error.toString())));
|
||||
}
|
||||
} finally {
|
||||
if (mounted) setState(() => _busy = false);
|
||||
@@ -68,7 +71,10 @@ class _WorkDetailPageState extends State<WorkDetailPage> {
|
||||
decoration: const InputDecoration(labelText: '原因'),
|
||||
),
|
||||
actions: [
|
||||
TextButton(onPressed: () => Navigator.pop(context), child: const Text('取消')),
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pop(context),
|
||||
child: const Text('取消'),
|
||||
),
|
||||
FilledButton(
|
||||
onPressed: () => Navigator.pop(context, controller.text.trim()),
|
||||
child: const Text('确认'),
|
||||
@@ -81,7 +87,10 @@ class _WorkDetailPageState extends State<WorkDetailPage> {
|
||||
}
|
||||
|
||||
Future<void> _receipt(WorkItem item) async {
|
||||
final existing = await widget.drafts.readDraft(widget.session.identity, item.identity);
|
||||
final existing = await widget.drafts.readDraft(
|
||||
widget.session.identity,
|
||||
item.identity,
|
||||
);
|
||||
if (!mounted) return;
|
||||
String? sealedName;
|
||||
if (existing?['kind'] == 'delivery_receipt' && existing?['sealed_name'] is String) {
|
||||
@@ -91,25 +100,34 @@ class _WorkDetailPageState extends State<WorkDetailPage> {
|
||||
title: const Text('发现未提交签收草稿'),
|
||||
content: const Text('是否继续提交上次加密保存的签收凭证?'),
|
||||
actions: [
|
||||
TextButton(onPressed: () => Navigator.pop(context, false), child: const Text('重新拍摄')),
|
||||
FilledButton(onPressed: () => Navigator.pop(context, true), child: const Text('继续提交')),
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pop(context, false),
|
||||
child: const Text('重新拍摄'),
|
||||
),
|
||||
FilledButton(
|
||||
onPressed: () => Navigator.pop(context, true),
|
||||
child: const Text('继续提交'),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
if (reuse == true) sealedName = existing!['sealed_name'] as String;
|
||||
}
|
||||
if (sealedName == null) {
|
||||
final image = await ImagePicker().pickImage(source: ImageSource.camera, imageQuality: 82);
|
||||
final image = await ImagePicker().pickImage(
|
||||
source: ImageSource.camera,
|
||||
imageQuality: 82,
|
||||
);
|
||||
if (image == null) return;
|
||||
sealedName = await widget.drafts.sealAttachment(
|
||||
accountIdentity: widget.session.identity,
|
||||
taskIdentity: item.identity,
|
||||
stage: 'receipt',
|
||||
sourcePath: image.path,
|
||||
source: image,
|
||||
);
|
||||
}
|
||||
setState(() => _busy = true);
|
||||
String? temporaryPath;
|
||||
XFile? temporaryFile;
|
||||
try {
|
||||
await widget.drafts.saveDraft(
|
||||
accountIdentity: widget.session.identity,
|
||||
@@ -122,7 +140,7 @@ class _WorkDetailPageState extends State<WorkDetailPage> {
|
||||
'captured_at': DateTime.now().toUtc().toIso8601String(),
|
||||
},
|
||||
);
|
||||
temporaryPath = await widget.drafts.materializeAttachment(
|
||||
temporaryFile = await widget.drafts.materializeAttachment(
|
||||
accountIdentity: widget.session.identity,
|
||||
sealedName: sealedName,
|
||||
);
|
||||
@@ -130,7 +148,7 @@ class _WorkDetailPageState extends State<WorkDetailPage> {
|
||||
identity: item.identity,
|
||||
recipientName: item.raw['contact_name'] as String? ?? '收货人',
|
||||
recipientPhone: item.raw['contact_phone'] as String? ?? '',
|
||||
proofFile: temporaryPath,
|
||||
proofFile: temporaryFile,
|
||||
);
|
||||
await widget.drafts.deleteDraft(widget.session.identity, item.identity);
|
||||
if (mounted) setState(() => _future = _load());
|
||||
@@ -141,9 +159,8 @@ class _WorkDetailPageState extends State<WorkDetailPage> {
|
||||
).showSnackBar(SnackBar(content: Text('签收提交失败,加密草稿已保留:$error')));
|
||||
}
|
||||
} finally {
|
||||
if (temporaryPath != null) {
|
||||
final file = File(temporaryPath);
|
||||
if (file.existsSync()) await file.delete();
|
||||
if (temporaryFile != null) {
|
||||
await widget.drafts.discardMaterializedAttachment(temporaryFile);
|
||||
}
|
||||
if (mounted) setState(() => _busy = false);
|
||||
}
|
||||
@@ -170,7 +187,10 @@ class _WorkDetailPageState extends State<WorkDetailPage> {
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(item.number, style: const TextStyle(color: Colors.white70)),
|
||||
Text(
|
||||
item.number,
|
||||
style: const TextStyle(color: Colors.white70),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
item.title,
|
||||
@@ -206,7 +226,10 @@ class _WorkDetailPageState extends State<WorkDetailPage> {
|
||||
onPressed: _busy
|
||||
? null
|
||||
: () => _run(
|
||||
(value) => widget.repository.start(value, widget.session.roleCode),
|
||||
(value) => widget.repository.start(
|
||||
value,
|
||||
widget.session.roleCode,
|
||||
),
|
||||
item,
|
||||
),
|
||||
child: const Text('开始处理'),
|
||||
@@ -216,7 +239,9 @@ class _WorkDetailPageState extends State<WorkDetailPage> {
|
||||
onPressed: _busy
|
||||
? null
|
||||
: () => _run(
|
||||
(value) => widget.repository.appendCurrentTrack(value.identity),
|
||||
(value) => widget.repository.appendCurrentTrack(
|
||||
value.identity,
|
||||
),
|
||||
item,
|
||||
),
|
||||
child: const Text('上报当前位置'),
|
||||
@@ -225,7 +250,10 @@ class _WorkDetailPageState extends State<WorkDetailPage> {
|
||||
ElevatedButton(
|
||||
onPressed: _busy
|
||||
? null
|
||||
: () => _run((value) => widget.repository.arrive(value.identity), item),
|
||||
: () => _run(
|
||||
(value) => widget.repository.arrive(value.identity),
|
||||
item,
|
||||
),
|
||||
child: const Text('到达并校验围栏'),
|
||||
),
|
||||
if (item.allowedActions.contains('submit_receipt'))
|
||||
@@ -253,8 +281,11 @@ class _WorkDetailPageState extends State<WorkDetailPage> {
|
||||
final reason = await _reason();
|
||||
if (reason != null && reason.isNotEmpty) {
|
||||
await _run(
|
||||
(value) =>
|
||||
widget.repository.exception(value, widget.session.roleCode, reason),
|
||||
(value) => widget.repository.exception(
|
||||
value,
|
||||
widget.session.roleCode,
|
||||
reason,
|
||||
),
|
||||
item,
|
||||
);
|
||||
}
|
||||
@@ -269,8 +300,11 @@ class _WorkDetailPageState extends State<WorkDetailPage> {
|
||||
final reason = await _reason();
|
||||
if (reason != null && reason.isNotEmpty) {
|
||||
await _run(
|
||||
(value) =>
|
||||
widget.repository.recover(value, widget.session.roleCode, reason),
|
||||
(value) => widget.repository.recover(
|
||||
value,
|
||||
widget.session.roleCode,
|
||||
reason,
|
||||
),
|
||||
item,
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user