feat: 完成智能电网电工端 Flutter 应用初始化
创建完整的 Flutter 项目结构,包含 Android 和 iOS 平台配置、核心网络层、路由、状态管理及业务模块(订单、收益、认证),适配原 uni-app 项目功能逻辑
This commit is contained in:
commit
56830e94ec
108 files changed
+9272
No files matched your search
@@ -0,0 +1,16 @@
|
||||
import '../../../core/network/api_client.dart';
|
||||
import '../../../core/network/api_response.dart';
|
||||
import 'earnings_models.dart';
|
||||
|
||||
/// 收益接口,对应后端 `/api/worker-app/earnings/summary`。
|
||||
class EarningsApi {
|
||||
EarningsApi(this._client);
|
||||
|
||||
final ApiClient _client;
|
||||
|
||||
Future<ApiResponse<EarningsSummary>> summary() =>
|
||||
_client.get<EarningsSummary>(
|
||||
'/worker-app/earnings/summary',
|
||||
parse: (d) => EarningsSummary.fromJson((d as Map).cast<String, dynamic>()),
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
import '../../../core/utils/id_util.dart';
|
||||
|
||||
/// 收益流水,对应后端 `earningsSummary().data.transactions[]`。
|
||||
///
|
||||
/// 说明:后端没有提现记录来源,因此实际只会返回 `type == 'earning'` 的入账流水。
|
||||
class EarningTransaction {
|
||||
const EarningTransaction({
|
||||
required this.id,
|
||||
required this.type,
|
||||
required this.title,
|
||||
required this.subtitle,
|
||||
required this.amount,
|
||||
required this.status,
|
||||
required this.icon,
|
||||
});
|
||||
|
||||
final String id;
|
||||
|
||||
/// earning | withdrawal
|
||||
final String type;
|
||||
final String title;
|
||||
final String subtitle;
|
||||
final double amount;
|
||||
|
||||
/// settled | pending | completed
|
||||
final String status;
|
||||
final String icon;
|
||||
|
||||
bool get isWithdrawal => type == 'withdrawal';
|
||||
|
||||
String get statusText => switch (status) {
|
||||
'settled' => '已结算',
|
||||
'pending' => '处理中',
|
||||
'completed' => '已完成',
|
||||
_ => status,
|
||||
};
|
||||
|
||||
factory EarningTransaction.fromJson(Map<String, dynamic> json) =>
|
||||
EarningTransaction(
|
||||
id: json['id'] as String? ?? '',
|
||||
type: json['type'] as String? ?? 'earning',
|
||||
title: json['title'] as String? ?? '',
|
||||
subtitle: json['subtitle'] as String? ?? '',
|
||||
amount: toDoubleOr(json['amount'], 0),
|
||||
status: json['status'] as String? ?? 'settled',
|
||||
icon: json['icon'] as String? ?? '',
|
||||
);
|
||||
}
|
||||
|
||||
/// 收益汇总,对应 `GET /api/worker-app/earnings/summary`。
|
||||
class EarningsSummary {
|
||||
const EarningsSummary({
|
||||
required this.totalBalance,
|
||||
required this.withdrawableAmount,
|
||||
required this.monthlyEarnings,
|
||||
required this.weeklyTrend,
|
||||
required this.transactions,
|
||||
});
|
||||
|
||||
final double totalBalance;
|
||||
final double withdrawableAmount;
|
||||
final double monthlyEarnings;
|
||||
|
||||
/// 近 7 天每日收益(index 6 = 今天)。
|
||||
final List<double> weeklyTrend;
|
||||
final List<EarningTransaction> transactions;
|
||||
|
||||
/// 柱状图高度百分比:以 7 日峰值为 100%,全 0 时给一个最小可见高度。
|
||||
List<double> get trendPercents {
|
||||
final max = weeklyTrend.isEmpty
|
||||
? 0.0
|
||||
: weeklyTrend.reduce((a, b) => a > b ? a : b);
|
||||
if (max <= 0) return List.filled(weeklyTrend.length, 8);
|
||||
return weeklyTrend.map((v) => (v / max * 100).clamp(8, 100).toDouble()).toList();
|
||||
}
|
||||
|
||||
factory EarningsSummary.fromJson(Map<String, dynamic> json) => EarningsSummary(
|
||||
totalBalance: toDoubleOr(json['totalBalance'], 0),
|
||||
withdrawableAmount: toDoubleOr(json['withdrawableAmount'], 0),
|
||||
monthlyEarnings: toDoubleOr(json['monthlyEarnings'], 0),
|
||||
weeklyTrend:
|
||||
(json['weeklyTrend'] as List?)?.map((e) => toDoubleOr(e, 0)).toList() ??
|
||||
const [0, 0, 0, 0, 0, 0, 0],
|
||||
transactions:
|
||||
(json['transactions'] as List?)
|
||||
?.map(
|
||||
(e) => EarningTransaction.fromJson(
|
||||
(e as Map).cast<String, dynamic>(),
|
||||
),
|
||||
)
|
||||
.toList() ??
|
||||
const [],
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user