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
@@ -90,6 +90,32 @@ class _CoinCenterScreenState extends State<CoinCenterScreen> {
}
}
Future<void> _reloadPackages() async {
try {
final sessionStore = SessionStore(LocalKvStore());
final apiClient = ApiClient(
baseUrl: appDependencies.backendUrl,
tokenProvider: sessionStore.getToken,
);
final api = PointsApi(apiClient.rawDio);
final result = await api.getPackages();
await _iapService?.loadStoreKitProducts(result.packages);
if (mounted) {
setState(() {
_packages = result.packages;
});
}
} catch (e, stackTrace) {
_logger.warning(
message: 'Failed to reload packages after purchase',
extra: {'error': e.toString()},
);
}
}
void _onPurchaseStateChanged() {
final service = _iapService;
if (service == null || !mounted) return;
@@ -100,6 +126,7 @@ class _CoinCenterScreenState extends State<CoinCenterScreen> {
case PurchaseFlowState.success:
Toast.show(context, l10n.paymentSuccess, type: ToastType.success);
_refreshBalance();
_reloadPackages();
service.resetState();
break;
case PurchaseFlowState.failed:
@@ -265,7 +292,7 @@ class _CoinCenterScreenState extends State<CoinCenterScreen> {
if (product != null) {
return product.price;
}
return pkg.priceDisplay;
return '';
}
Future<void> _handlePurchase(PackageInfo pkg) async {
@@ -284,6 +311,9 @@ class _CoinCenterScreenState extends State<CoinCenterScreen> {
}
String? _getPackageBadge(PackageInfo pkg, AppLocalizations l10n) {
if (pkg.productCode == ProductCode.newUserPack) {
return l10n.settingsCoinPackNewUserBadge;
}
if (pkg.productCode == ProductCode.popularPack) {
return l10n.settingsCoinPackPopularBadge;
}
@@ -293,7 +323,7 @@ class _CoinCenterScreenState extends State<CoinCenterScreen> {
String _getPackageTitle(PackageInfo pkg, AppLocalizations l10n) {
return switch (pkg.productCode) {
ProductCode.newUserPack => l10n.settingsCoinPackStarter,
ProductCode.basicPack => l10n.settingsCoinPackBasic,
ProductCode.starterPack => l10n.settingsCoinPackBasic,
ProductCode.popularPack => l10n.settingsCoinPackPopular,
ProductCode.premiumPack => l10n.settingsCoinPackPremium,
};