fix:增加图片选择和拍照功能

This commit is contained in:
jingyun
2026-06-23 10:07:35 +08:00
parent 75ba309e8c
commit 8cf919283b
16 changed files with 1288 additions and 45 deletions
@@ -1,4 +1,6 @@
import 'package:flutter/material.dart';
import 'dart:io';
import 'package:flutter/material.dart' hide AssetImage;
import 'package:go_router/go_router.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:shadcn_ui/shadcn_ui.dart';
@@ -10,6 +12,7 @@ import '../../profile/application/price_color_theme.dart';
import '../../profile/application/profile_settings_controller.dart';
import '../application/asset_portfolio_controller.dart';
import '../data/asset_models.dart';
import 'asset_image_preview_page.dart';
class HoldingDetailPage extends ConsumerWidget {
const HoldingDetailPage({super.key, this.id});
@@ -240,6 +243,8 @@ class HoldingDetailPage extends ConsumerWidget {
),
),
const SizedBox(height: 12),
_buildImageSection(context, ref, holding),
const SizedBox(height: 12),
Row(
children: [
Expanded(
@@ -362,6 +367,135 @@ class HoldingDetailPage extends ConsumerWidget {
).showSnackBar(const SnackBar(content: Text('已标记卖出 / 转赠')));
Navigator.of(context).pop();
}
Widget _buildImageSection(
BuildContext context,
WidgetRef ref,
GoldAssetHolding holding,
) {
final images = holding.images;
return PrototypeCard(
padding: const EdgeInsets.fromLTRB(16, 16, 16, 16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'凭证照片',
style: TextStyle(fontSize: 13, color: Color(0xFF8A8780)),
),
const SizedBox(height: 12),
if (images.isEmpty)
const Text(
'暂无凭证照片,可在添加资产时上传发票、证书或实物照片。',
style: TextStyle(fontSize: 12, color: Color(0xFFB3AFA5)),
)
else
Wrap(
spacing: 8,
runSpacing: 8,
children: [
for (var index = 0; index < images.length; index++)
_buildDetailImageTile(
context,
ref,
holding,
images[index],
index,
),
],
),
],
),
);
}
Widget _buildDetailImageTile(
BuildContext context,
WidgetRef ref,
GoldAssetHolding holding,
AssetImage image,
int index,
) {
return GestureDetector(
onTap: () => _openImagePreview(context, holding.images, index),
onLongPress: () => _confirmDeleteImage(context, ref, holding, image),
child: ClipRRect(
borderRadius: BorderRadius.circular(12),
child: Stack(
children: [
Image.file(
File(image.localPath),
width: 84,
height: 84,
fit: BoxFit.cover,
),
Positioned(
right: 4,
top: 4,
child: Container(
width: 20,
height: 20,
decoration: const BoxDecoration(
color: Color(0xAA000000),
shape: BoxShape.circle,
),
child: const Icon(Icons.remove, size: 14, color: Colors.white),
),
),
],
),
),
);
}
void _openImagePreview(
BuildContext context,
List<AssetImage> images,
int initialIndex,
) {
Navigator.of(context).push(
MaterialPageRoute<void>(
builder: (_) => AssetImagePreviewPage(
images: images,
initialIndex: initialIndex,
),
),
);
}
void _confirmDeleteImage(
BuildContext context,
WidgetRef ref,
GoldAssetHolding holding,
AssetImage image,
) {
showDialog<void>(
context: context,
builder: (ctx) => AlertDialog(
title: const Text('删除照片'),
content: const Text('确认删除这张凭证照片吗?'),
actions: [
TextButton(
onPressed: () => Navigator.of(ctx).pop(),
child: const Text('取消'),
),
TextButton(
onPressed: () {
Navigator.of(ctx).pop();
final updated = holding.copyWith(
images: List<AssetImage>.unmodifiable(
holding.images.where((item) => item.localId != image.localId).toList(),
),
updatedAt: DateTime.now(),
);
ref.read(assetPortfolioControllerProvider.notifier).updateHolding(updated);
},
child: const Text('删除'),
),
],
),
);
}
}
class _ActionMenuTile extends StatelessWidget {