|
@@ -74,7 +74,7 @@ class _ExpenseApplyDetailReportPageState
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- Future<void> _loadDetails({bool append = false}) async {
|
|
|
|
|
|
|
+ Future<void> _loadDetails() async {
|
|
|
if (_detailLoading) return;
|
|
if (_detailLoading) return;
|
|
|
setState(() => _detailLoading = true);
|
|
setState(() => _detailLoading = true);
|
|
|
try {
|
|
try {
|
|
@@ -82,7 +82,7 @@ class _ExpenseApplyDetailReportPageState
|
|
|
final result = await api.getExpenseApplyReportDetail(
|
|
final result = await api.getExpenseApplyReportDetail(
|
|
|
startDate: _startCtrl.text.isNotEmpty ? _startCtrl.text : null,
|
|
startDate: _startCtrl.text.isNotEmpty ? _startCtrl.text : null,
|
|
|
endDate: _endCtrl.text.isNotEmpty ? _endCtrl.text : null,
|
|
endDate: _endCtrl.text.isNotEmpty ? _endCtrl.text : null,
|
|
|
- page: append ? _detailPage : 1,
|
|
|
|
|
|
|
+ page: _detailPage,
|
|
|
);
|
|
);
|
|
|
if (!mounted) return;
|
|
if (!mounted) return;
|
|
|
final list =
|
|
final list =
|
|
@@ -91,13 +91,7 @@ class _ExpenseApplyDetailReportPageState
|
|
|
.toList() ??
|
|
.toList() ??
|
|
|
[];
|
|
[];
|
|
|
setState(() {
|
|
setState(() {
|
|
|
- if (append) {
|
|
|
|
|
- _details.addAll(list);
|
|
|
|
|
- _detailPage++;
|
|
|
|
|
- } else {
|
|
|
|
|
- _details = list;
|
|
|
|
|
- _detailPage = 2;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ _details = list;
|
|
|
_detailTotal = result['total'] as int? ?? 0;
|
|
_detailTotal = result['total'] as int? ?? 0;
|
|
|
_detailLoading = false;
|
|
_detailLoading = false;
|
|
|
});
|
|
});
|
|
@@ -606,6 +600,8 @@ class _ExpenseApplyDetailReportPageState
|
|
|
|
|
|
|
|
// ── 明细列表 ──
|
|
// ── 明细列表 ──
|
|
|
Widget _buildDetailList() {
|
|
Widget _buildDetailList() {
|
|
|
|
|
+ final l10n = AppLocalizations.of(context);
|
|
|
|
|
+ final colors = Theme.of(context).extension<AppColorsExtension>()!;
|
|
|
if (_detailLoading && _details.isEmpty) {
|
|
if (_detailLoading && _details.isEmpty) {
|
|
|
return const Padding(
|
|
return const Padding(
|
|
|
padding: EdgeInsets.only(top: 32),
|
|
padding: EdgeInsets.only(top: 32),
|
|
@@ -617,9 +613,32 @@ class _ExpenseApplyDetailReportPageState
|
|
|
),
|
|
),
|
|
|
);
|
|
);
|
|
|
}
|
|
}
|
|
|
- if (_details.isEmpty) return const SizedBox.shrink();
|
|
|
|
|
- final l10n = AppLocalizations.of(context);
|
|
|
|
|
- final colors = Theme.of(context).extension<AppColorsExtension>()!;
|
|
|
|
|
|
|
+ if (_details.isEmpty) {
|
|
|
|
|
+ return Padding(
|
|
|
|
|
+ padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
|
|
|
|
|
+ child: Container(
|
|
|
|
|
+ width: double.infinity,
|
|
|
|
|
+ decoration: BoxDecoration(
|
|
|
|
|
+ color: colors.bgCard,
|
|
|
|
|
+ borderRadius: BorderRadius.circular(8),
|
|
|
|
|
+ ),
|
|
|
|
|
+ child: Padding(
|
|
|
|
|
+ padding: const EdgeInsets.symmetric(vertical: 48),
|
|
|
|
|
+ child: Column(
|
|
|
|
|
+ mainAxisSize: MainAxisSize.min,
|
|
|
|
|
+ children: [
|
|
|
|
|
+ Icon(Icons.inbox_outlined, size: 48, color: colors.textPlaceholder),
|
|
|
|
|
+ const SizedBox(height: 12),
|
|
|
|
|
+ Text(
|
|
|
|
|
+ l10n.get('noDetailData'),
|
|
|
|
|
+ style: TextStyle(fontSize: 14, color: colors.textSecondary),
|
|
|
|
|
+ ),
|
|
|
|
|
+ ],
|
|
|
|
|
+ ),
|
|
|
|
|
+ ),
|
|
|
|
|
+ ),
|
|
|
|
|
+ );
|
|
|
|
|
+ }
|
|
|
final headerStyle = TextStyle(
|
|
final headerStyle = TextStyle(
|
|
|
fontSize: 12,
|
|
fontSize: 12,
|
|
|
fontWeight: FontWeight.w600,
|
|
fontWeight: FontWeight.w600,
|
|
@@ -653,11 +672,6 @@ class _ExpenseApplyDetailReportPageState
|
|
|
color: colors.textPrimary,
|
|
color: colors.textPrimary,
|
|
|
),
|
|
),
|
|
|
),
|
|
),
|
|
|
- const Spacer(),
|
|
|
|
|
- Text(
|
|
|
|
|
- '${_details.length} ${l10n.get('items')}',
|
|
|
|
|
- style: TextStyle(fontSize: 12, color: colors.textSecondary),
|
|
|
|
|
- ),
|
|
|
|
|
],
|
|
],
|
|
|
),
|
|
),
|
|
|
),
|
|
),
|
|
@@ -782,23 +796,23 @@ class _ExpenseApplyDetailReportPageState
|
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
|
children: [
|
|
children: [
|
|
|
GestureDetector(
|
|
GestureDetector(
|
|
|
- onTap: _detailPage > 2
|
|
|
|
|
|
|
+ onTap: _detailPage > 1
|
|
|
? () {
|
|
? () {
|
|
|
- _detailPage -= 2;
|
|
|
|
|
- _loadDetails(append: false);
|
|
|
|
|
|
|
+ _detailPage--;
|
|
|
|
|
+ _loadDetails();
|
|
|
}
|
|
}
|
|
|
: null,
|
|
: null,
|
|
|
child: Icon(
|
|
child: Icon(
|
|
|
Icons.chevron_left,
|
|
Icons.chevron_left,
|
|
|
size: 20,
|
|
size: 20,
|
|
|
- color: _detailPage > 2
|
|
|
|
|
|
|
+ color: _detailPage > 1
|
|
|
? colors.textPrimary
|
|
? colors.textPrimary
|
|
|
: colors.textPlaceholder,
|
|
: colors.textPlaceholder,
|
|
|
),
|
|
),
|
|
|
),
|
|
),
|
|
|
const SizedBox(width: 16),
|
|
const SizedBox(width: 16),
|
|
|
Text(
|
|
Text(
|
|
|
- _detailPage > 1 ? '${_detailPage - 1}' : '1',
|
|
|
|
|
|
|
+ '$_detailPage',
|
|
|
style: TextStyle(fontSize: 13, color: colors.textPrimary),
|
|
style: TextStyle(fontSize: 13, color: colors.textPrimary),
|
|
|
),
|
|
),
|
|
|
const SizedBox(width: 4),
|
|
const SizedBox(width: 4),
|
|
@@ -811,15 +825,16 @@ class _ExpenseApplyDetailReportPageState
|
|
|
),
|
|
),
|
|
|
const SizedBox(width: 16),
|
|
const SizedBox(width: 16),
|
|
|
GestureDetector(
|
|
GestureDetector(
|
|
|
- onTap: (_detailPage - 1) * 20 < _detailTotal
|
|
|
|
|
|
|
+ onTap: _detailPage * 20 < _detailTotal
|
|
|
? () {
|
|
? () {
|
|
|
- _loadDetails(append: true);
|
|
|
|
|
|
|
+ _detailPage++;
|
|
|
|
|
+ _loadDetails();
|
|
|
}
|
|
}
|
|
|
: null,
|
|
: null,
|
|
|
child: Icon(
|
|
child: Icon(
|
|
|
Icons.chevron_right,
|
|
Icons.chevron_right,
|
|
|
size: 20,
|
|
size: 20,
|
|
|
- color: (_detailPage - 1) * 20 < _detailTotal
|
|
|
|
|
|
|
+ color: _detailPage * 20 < _detailTotal
|
|
|
? colors.textPrimary
|
|
? colors.textPrimary
|
|
|
: colors.textPlaceholder,
|
|
: colors.textPlaceholder,
|
|
|
),
|
|
),
|