import '../../../core/utils/avatar_urls.dart'; /// 跟单仓位 class CopyPosition { final String id; final String symbol; final String direction; // 'long' | 'short' final String positionType; // '全仓' | '逐仓' final int leverage; final String traderId; final String traderName; final String? traderAvatar; final double openPrice; final double currentPrice; final double quantity; final double unrealizedPnl; final double roi; final DateTime openTime; final double margin; // 当前保证金 USDT final bool isNoLoss; // 是否为无损跟单(L5交易员,跟单员不可手动平仓) final double? closePrice; // 平仓均价(历史跟单) final DateTime? closeTime; // 平仓时间(历史跟单) const CopyPosition({ required this.id, required this.symbol, required this.direction, required this.positionType, required this.leverage, required this.traderId, required this.traderName, this.traderAvatar, required this.openPrice, required this.currentPrice, required this.quantity, required this.unrealizedPnl, required this.roi, required this.openTime, this.margin = 0, this.isNoLoss = false, this.closePrice, this.closeTime, }); bool get isLong => direction == 'long'; /// 从 API FollowOrder Map 构建 factory CopyPosition.fromApi(Map json) { double _d(String key) => double.tryParse((json[key] ?? '0').toString()) ?? 0.0; int _i(String key) => int.tryParse((json[key] ?? '0').toString()) ?? 0; final directionInt = _i('direction'); final direction = directionInt == 0 ? 'long' : 'short'; DateTime _fromMs(dynamic ms) { if (ms == null) return DateTime.now(); return DateTime.fromMillisecondsSinceEpoch((ms as num).toInt()); } final closeMs = json['closeTime']; final closePriceVal = json['closePrice']; return CopyPosition( id: json['positionId']?.toString() ?? '', symbol: json['symbol']?.toString() ?? '', direction: direction, positionType: '全仓', leverage: _i('leverage'), traderId: json['traderId']?.toString() ?? '', traderName: json['traderNickname']?.toString() ?? '', traderAvatar: normalizeAvatarHttpUrl(json['traderAvatar']?.toString() ?? json['avatar']?.toString() ?? json['headImg']?.toString()), openPrice: _d('openPrice'), currentPrice: _d('currentPrice'), quantity: _d('totalPosition'), unrealizedPnl: _d('profit'), roi: _d('profitRate'), openTime: _fromMs(json['openTime']), margin: _d('principalAmount'), isNoLoss: json['specialTrader'] == true, closePrice: closePriceVal != null ? double.tryParse(closePriceVal.toString()) : null, closeTime: closeMs != null ? _fromMs(closeMs) : null, ); } }