feat(points): 实现积分流水列表功能

- 后端新增 GET /api/v1/points/ledger 接口
- 前端新增积分流水列表页面
- 积分中心添加「查看流水」入口
- 重命名 AccountDeleteScreen 为 AccountDataScreen
- 流水列表支持分页加载和空状态展示
This commit is contained in:
ZL-Q
2026-04-28 17:19:08 +08:00
parent a83001de0d
commit 940c67e642
12 changed files with 794 additions and 70 deletions
@@ -1,5 +1,6 @@
import 'package:dio/dio.dart';
import '../models/ledger_item.dart';
import '../models/package_info.dart';
class PointsApi {
@@ -11,4 +12,19 @@ class PointsApi {
final response = await _dio.get('/api/v1/points/packages');
return PackagesResult.fromJson(response.data as Map<String, dynamic>);
}
Future<LedgerListResult> getLedger({
int limit = 20,
String? cursor,
}) async {
final query = <String, dynamic>{'limit': limit};
if (cursor != null) {
query['cursor'] = cursor;
}
final response = await _dio.get(
'/api/v1/points/ledger',
queryParameters: query,
);
return LedgerListResult.fromJson(response.data as Map<String, dynamic>);
}
}
@@ -0,0 +1,50 @@
class LedgerItem {
const LedgerItem({
required this.id,
required this.direction,
required this.amount,
required this.balanceAfter,
required this.changeType,
required this.createdAt,
});
final String id;
final int direction;
final int amount;
final int balanceAfter;
final String changeType;
final String createdAt;
factory LedgerItem.fromJson(Map<String, dynamic> json) {
return LedgerItem(
id: json['id'] as String,
direction: json['direction'] as int,
amount: json['amount'] as int,
balanceAfter: json['balanceAfter'] as int,
changeType: json['changeType'] as String,
createdAt: json['createdAt'] as String,
);
}
}
class LedgerListResult {
const LedgerListResult({
required this.items,
this.nextCursor,
required this.hasMore,
});
final List<LedgerItem> items;
final String? nextCursor;
final bool hasMore;
factory LedgerListResult.fromJson(Map<String, dynamic> json) {
return LedgerListResult(
items: (json['items'] as List<dynamic>)
.map((e) => LedgerItem.fromJson(e as Map<String, dynamic>))
.toList(),
nextCursor: json['nextCursor'] as String?,
hasMore: json['hasMore'] as bool,
);
}
}