fix:增加图片选择和拍照功能
This commit is contained in:
@@ -1,5 +1,58 @@
|
||||
import '../../../common/domain/metal_type.dart';
|
||||
|
||||
class AssetImage {
|
||||
const AssetImage({
|
||||
required this.localId,
|
||||
required this.localPath,
|
||||
required this.createdAt,
|
||||
this.remoteUrl,
|
||||
this.thumbnailUrl,
|
||||
});
|
||||
|
||||
final String localId;
|
||||
final String localPath;
|
||||
final String? remoteUrl;
|
||||
final String? thumbnailUrl;
|
||||
final DateTime createdAt;
|
||||
|
||||
AssetImage copyWith({
|
||||
String? localId,
|
||||
String? localPath,
|
||||
String? remoteUrl,
|
||||
String? thumbnailUrl,
|
||||
DateTime? createdAt,
|
||||
}) {
|
||||
return AssetImage(
|
||||
localId: localId ?? this.localId,
|
||||
localPath: localPath ?? this.localPath,
|
||||
remoteUrl: remoteUrl ?? this.remoteUrl,
|
||||
thumbnailUrl: thumbnailUrl ?? this.thumbnailUrl,
|
||||
createdAt: createdAt ?? this.createdAt,
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'localId': localId,
|
||||
'localPath': localPath,
|
||||
'remoteUrl': remoteUrl,
|
||||
'thumbnailUrl': thumbnailUrl,
|
||||
'createdAt': createdAt.toIso8601String(),
|
||||
};
|
||||
}
|
||||
|
||||
factory AssetImage.fromJson(Map<String, dynamic> json) {
|
||||
return AssetImage(
|
||||
localId: json['localId'] as String? ?? '',
|
||||
localPath: json['localPath'] as String? ?? '',
|
||||
remoteUrl: json['remoteUrl'] as String?,
|
||||
thumbnailUrl: json['thumbnailUrl'] as String?,
|
||||
createdAt: DateTime.tryParse(json['createdAt'] as String? ?? '') ??
|
||||
DateTime.fromMillisecondsSinceEpoch(0),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
enum AssetCategory {
|
||||
bar('金条'),
|
||||
necklace('项链'),
|
||||
@@ -28,6 +81,7 @@ class GoldAssetHolding {
|
||||
required this.weightGram,
|
||||
required this.createdAt,
|
||||
required this.updatedAt,
|
||||
this.images = const [],
|
||||
this.costAmount,
|
||||
this.purchaseDate,
|
||||
this.channel,
|
||||
@@ -42,6 +96,7 @@ class GoldAssetHolding {
|
||||
final double purity;
|
||||
final String purityLabel;
|
||||
final double weightGram;
|
||||
final List<AssetImage> images;
|
||||
final double? costAmount;
|
||||
final DateTime? purchaseDate;
|
||||
final String? channel;
|
||||
@@ -50,7 +105,92 @@ class GoldAssetHolding {
|
||||
final DateTime updatedAt;
|
||||
final HoldingStatus status;
|
||||
|
||||
GoldAssetHolding copyWith({
|
||||
String? id,
|
||||
String? name,
|
||||
MetalType? metal,
|
||||
AssetCategory? category,
|
||||
double? purity,
|
||||
String? purityLabel,
|
||||
double? weightGram,
|
||||
List<AssetImage>? images,
|
||||
double? costAmount,
|
||||
DateTime? purchaseDate,
|
||||
String? channel,
|
||||
String? note,
|
||||
DateTime? createdAt,
|
||||
DateTime? updatedAt,
|
||||
HoldingStatus? status,
|
||||
}) {
|
||||
return GoldAssetHolding(
|
||||
id: id ?? this.id,
|
||||
name: name ?? this.name,
|
||||
metal: metal ?? this.metal,
|
||||
category: category ?? this.category,
|
||||
purity: purity ?? this.purity,
|
||||
purityLabel: purityLabel ?? this.purityLabel,
|
||||
weightGram: weightGram ?? this.weightGram,
|
||||
images: images ?? this.images,
|
||||
costAmount: costAmount ?? this.costAmount,
|
||||
purchaseDate: purchaseDate ?? this.purchaseDate,
|
||||
channel: channel ?? this.channel,
|
||||
note: note ?? this.note,
|
||||
createdAt: createdAt ?? this.createdAt,
|
||||
updatedAt: updatedAt ?? this.updatedAt,
|
||||
status: status ?? this.status,
|
||||
);
|
||||
}
|
||||
|
||||
double materialValue(double spotPrice) => weightGram * purity * spotPrice;
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'id': id,
|
||||
'name': name,
|
||||
'metalId': metal.id,
|
||||
'categoryId': category.name,
|
||||
'purity': purity,
|
||||
'purityLabel': purityLabel,
|
||||
'weightGram': weightGram,
|
||||
'images': images.map((item) => item.toJson()).toList(growable: false),
|
||||
'costAmount': costAmount,
|
||||
'purchaseDate': purchaseDate?.toIso8601String(),
|
||||
'channel': channel,
|
||||
'note': note,
|
||||
'createdAt': createdAt.toIso8601String(),
|
||||
'updatedAt': updatedAt.toIso8601String(),
|
||||
'status': status.name,
|
||||
};
|
||||
}
|
||||
|
||||
factory GoldAssetHolding.fromJson(Map<String, dynamic> json) {
|
||||
final rawImages = json['images'];
|
||||
return GoldAssetHolding(
|
||||
id: json['id'] as String? ?? '',
|
||||
name: json['name'] as String? ?? '',
|
||||
metal: _metalFromId(json['metalId'] as String?),
|
||||
category: _categoryFromId(json['categoryId'] as String?),
|
||||
purity: (json['purity'] as num?)?.toDouble() ?? 1,
|
||||
purityLabel: json['purityLabel'] as String? ?? '',
|
||||
weightGram: (json['weightGram'] as num?)?.toDouble() ?? 0,
|
||||
images: rawImages is List
|
||||
? [
|
||||
for (final raw in rawImages)
|
||||
if (raw is Map)
|
||||
AssetImage.fromJson(Map<String, dynamic>.from(raw)),
|
||||
]
|
||||
: const [],
|
||||
costAmount: (json['costAmount'] as num?)?.toDouble(),
|
||||
purchaseDate: DateTime.tryParse(json['purchaseDate'] as String? ?? ''),
|
||||
channel: json['channel'] as String?,
|
||||
note: json['note'] as String?,
|
||||
createdAt: DateTime.tryParse(json['createdAt'] as String? ?? '') ??
|
||||
DateTime.fromMillisecondsSinceEpoch(0),
|
||||
updatedAt: DateTime.tryParse(json['updatedAt'] as String? ?? '') ??
|
||||
DateTime.fromMillisecondsSinceEpoch(0),
|
||||
status: _statusFromName(json['status'] as String?),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class HoldingValuation {
|
||||
@@ -100,3 +240,26 @@ class PortfolioSummary {
|
||||
final List<MetalBreakdown> breakdowns;
|
||||
final List<HoldingValuation> holdings;
|
||||
}
|
||||
|
||||
MetalType _metalFromId(String? id) {
|
||||
return switch (id) {
|
||||
'gold' => MetalType.gold,
|
||||
'platinum' => MetalType.platinum,
|
||||
'silver' => MetalType.silver,
|
||||
_ => MetalType.gold,
|
||||
};
|
||||
}
|
||||
|
||||
AssetCategory _categoryFromId(String? id) {
|
||||
return AssetCategory.values.firstWhere(
|
||||
(item) => item.name == id,
|
||||
orElse: () => AssetCategory.bar,
|
||||
);
|
||||
}
|
||||
|
||||
HoldingStatus _statusFromName(String? value) {
|
||||
return HoldingStatus.values.firstWhere(
|
||||
(item) => item.name == value,
|
||||
orElse: () => HoldingStatus.active,
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user