chore: release v1.0.18
Deploy / build-linux-web (push) Successful in 53s
Deploy / build-windows (push) Successful in 1m48s
Deploy / build-macos (push) Successful in 1m17s
Deploy / build-android (push) Successful in 4m13s
Deploy / build-ios (push) Successful in 9s
Deploy / release-deploy (push) Successful in 1m37s
Deploy / build-linux-web (push) Successful in 53s
Deploy / build-windows (push) Successful in 1m48s
Deploy / build-macos (push) Successful in 1m17s
Deploy / build-android (push) Successful in 4m13s
Deploy / build-ios (push) Successful in 9s
Deploy / release-deploy (push) Successful in 1m37s
移动端响应式适配(抽屉导航/列表卡片/弹窗自适应)、Android 正式签名与 APK 发布、 iOS(TestFlight) 工程与 CI、多平台构建流水线、相关文档同步。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -1,9 +1,11 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import '../../core/responsive/responsive.dart';
|
||||
import '../../core/theme/app_theme.dart';
|
||||
import '../../models/finance.dart';
|
||||
import '../../providers/finance_provider.dart';
|
||||
import '../../widgets/data_table_card.dart';
|
||||
import '../../widgets/mobile_list_card.dart';
|
||||
import '../../widgets/multi_select_dropdown.dart' show ColDef, ColumnToggleButton, FilterableColumnHeader;
|
||||
import '../../widgets/page_scaffold.dart';
|
||||
import '../../providers/connectivity_provider.dart';
|
||||
@@ -129,6 +131,47 @@ class _FinanceTabState extends ConsumerState<_FinanceTab> {
|
||||
);
|
||||
}
|
||||
|
||||
/// 财务记录:窄屏卡片
|
||||
Widget _financeCard(FinanceRecord r) {
|
||||
final canClose = (r.type == 'payable' || r.type == 'receivable') &&
|
||||
r.status == 'open';
|
||||
final showStatus = r.type == 'payable' || r.type == 'receivable';
|
||||
return MobileListCard(
|
||||
title: Text(r.partnerName?.isNotEmpty == true ? r.partnerName! : r.typeLabel),
|
||||
subtitle: Text(r.recordDate?.substring(0, 10) ?? '-'),
|
||||
trailing: _TypeBadge(r.typeLabel),
|
||||
fields: [
|
||||
MobileCardField('金额', '¥${r.amount.toStringAsFixed(2)}'),
|
||||
MobileCardField('余额', null,
|
||||
valueWidget: Text(
|
||||
'¥${r.balance.toStringAsFixed(2)}',
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
color: r.balance > 0
|
||||
? AppTheme.danger
|
||||
: AppTheme.textSecondary,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
)),
|
||||
if (r.refType != null && r.refId != null)
|
||||
MobileCardField(
|
||||
'关联单据', '${r.refType!.replaceAll('_', '-')}#${r.refId}'),
|
||||
if (showStatus)
|
||||
MobileCardField('状态', null, valueWidget: _StatusBadge(r.status)),
|
||||
if (r.remark?.isNotEmpty == true) MobileCardField('备注', r.remark),
|
||||
],
|
||||
actions: canClose
|
||||
? [
|
||||
TextButton(
|
||||
onPressed: () => _closeRecord(r),
|
||||
child: const Text('结清',
|
||||
style: TextStyle(fontSize: 13, color: AppTheme.success)),
|
||||
),
|
||||
]
|
||||
: null,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
ref.listen(networkRecoveryCountProvider, (_, __) => _refetch());
|
||||
@@ -302,34 +345,44 @@ class _FinanceTabState extends ConsumerState<_FinanceTab> {
|
||||
return Column(
|
||||
children: [
|
||||
if (widget.typeFilter.isNotEmpty && records.isNotEmpty)
|
||||
Container(
|
||||
color: AppTheme.background,
|
||||
padding: const EdgeInsets.all(12),
|
||||
child: Row(
|
||||
children: [
|
||||
_SummaryCard(
|
||||
title: '合计金额',
|
||||
value: '¥${(totalAmount / 10000).toStringAsFixed(2)}万',
|
||||
icon: Icons.account_balance_wallet,
|
||||
color: AppTheme.primary,
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
_SummaryCard(
|
||||
title: '未结清',
|
||||
value: '¥${(openAmount / 10000).toStringAsFixed(2)}万',
|
||||
icon: Icons.pending_actions,
|
||||
color: AppTheme.danger,
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
_SummaryCard(
|
||||
title: '已结清',
|
||||
value: '¥${(closedAmount / 10000).toStringAsFixed(2)}万',
|
||||
icon: Icons.check_circle,
|
||||
color: AppTheme.success,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Builder(builder: (context) {
|
||||
final w = context.isMobile ? 150.0 : null;
|
||||
final cards = [
|
||||
_SummaryCard(
|
||||
title: '合计金额',
|
||||
value: '¥${(totalAmount / 10000).toStringAsFixed(2)}万',
|
||||
icon: Icons.account_balance_wallet,
|
||||
color: AppTheme.primary,
|
||||
width: w,
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
_SummaryCard(
|
||||
title: '未结清',
|
||||
value: '¥${(openAmount / 10000).toStringAsFixed(2)}万',
|
||||
icon: Icons.pending_actions,
|
||||
color: AppTheme.danger,
|
||||
width: w,
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
_SummaryCard(
|
||||
title: '已结清',
|
||||
value: '¥${(closedAmount / 10000).toStringAsFixed(2)}万',
|
||||
icon: Icons.check_circle,
|
||||
color: AppTheme.success,
|
||||
width: w,
|
||||
),
|
||||
];
|
||||
return Container(
|
||||
color: AppTheme.background,
|
||||
padding: const EdgeInsets.all(12),
|
||||
child: context.isMobile
|
||||
? SingleChildScrollView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
child: Row(children: cards),
|
||||
)
|
||||
: Row(children: cards),
|
||||
);
|
||||
}),
|
||||
if (widget.typeFilter.isNotEmpty && records.isNotEmpty)
|
||||
const Divider(height: 1),
|
||||
Expanded(
|
||||
@@ -405,6 +458,7 @@ class _FinanceTabState extends ConsumerState<_FinanceTab> {
|
||||
),
|
||||
columns: columns,
|
||||
rows: rows,
|
||||
mobileCards: records.map(_financeCard).toList(),
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -487,7 +541,7 @@ class _AddPaymentDialogState extends State<_AddPaymentDialog> {
|
||||
return AlertDialog(
|
||||
title: Text(_title),
|
||||
content: SizedBox(
|
||||
width: 360,
|
||||
width: context.dialogWidth(360),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
@@ -611,18 +665,19 @@ class _SummaryCard extends StatelessWidget {
|
||||
final String value;
|
||||
final IconData icon;
|
||||
final Color color;
|
||||
final double? width;
|
||||
|
||||
const _SummaryCard({
|
||||
required this.title,
|
||||
required this.value,
|
||||
required this.icon,
|
||||
required this.color,
|
||||
this.width,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Expanded(
|
||||
child: Container(
|
||||
final card = Container(
|
||||
height: 72,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
decoration: BoxDecoration(
|
||||
@@ -659,8 +714,10 @@ class _SummaryCard extends StatelessWidget {
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
);
|
||||
return width != null
|
||||
? SizedBox(width: width, child: card)
|
||||
: Expanded(child: card);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user