chengc 1 неделя назад
Родитель
Сommit
70602b4eb7

+ 2 - 1
lib/features/expense/expense_create_page.dart

@@ -1193,8 +1193,9 @@ class _ExpenseCreatePageState extends ConsumerState<ExpenseCreatePage> {
   String? _extractErrorMessage(Object e) {
   String? _extractErrorMessage(Object e) {
     if (e is DioException) {
     if (e is DioException) {
       if (e.error is ApiException) return (e.error as ApiException).message;
       if (e.error is ApiException) return (e.error as ApiException).message;
-      if (e.error is NetworkException)
+      if (e.error is NetworkException) {
         return (e.error as NetworkException).message;
         return (e.error as NetworkException).message;
+      }
     }
     }
     return null;
     return null;
   }
   }

+ 16 - 15
lib/features/expense/expense_detail_page.dart

@@ -284,8 +284,8 @@ class _ExpenseDetailPageState extends ConsumerState<ExpenseDetailPage> {
         const SizedBox(height: 16),
         const SizedBox(height: 16),
         FormFieldRow(
         FormFieldRow(
           label: l10n.get('expensePersonnel'),
           label: l10n.get('expensePersonnel'),
-          value: expense.applicantName.isNotEmpty
-              ? '${expense.applicantId}/${expense.applicantName}'
+          value: expense.applicantId.isNotEmpty
+              ? '${expense.applicantId}${expense.applicantName.isNotEmpty ? '/${expense.applicantName}' : ''}'
               : '-',
               : '-',
           readOnly: true,
           readOnly: true,
           showArrow: false,
           showArrow: false,
@@ -293,8 +293,8 @@ class _ExpenseDetailPageState extends ConsumerState<ExpenseDetailPage> {
         const SizedBox(height: 16),
         const SizedBox(height: 16),
         FormFieldRow(
         FormFieldRow(
           label: l10n.get('expenseDept'),
           label: l10n.get('expenseDept'),
-          value: expense.deptName.isNotEmpty
-              ? '${expense.deptId}/${expense.deptName}'
+          value: expense.deptId.isNotEmpty
+              ? '${expense.deptId}${expense.deptName.isNotEmpty ? '/${expense.deptName}' : ''}'
               : '-',
               : '-',
           readOnly: true,
           readOnly: true,
           showArrow: false,
           showArrow: false,
@@ -471,9 +471,9 @@ class _ExpenseDetailPageState extends ConsumerState<ExpenseDetailPage> {
                                 color: colors.textSecondary,
                                 color: colors.textSecondary,
                               ),
                               ),
                             ),
                             ),
-                          if (d.acctSubjectName.isNotEmpty)
+                          if (d.acctSubjectId.isNotEmpty)
                             Text(
                             Text(
-                              '${l10n.get('acctSubject')}: ${d.acctSubjectId}/${d.acctSubjectName}',
+                              '${l10n.get('acctSubject')}: ${d.acctSubjectId}${d.acctSubjectName.isNotEmpty ? '/${d.acctSubjectName}' : ''}',
                               maxLines: 1,
                               maxLines: 1,
                               overflow: TextOverflow.ellipsis,
                               overflow: TextOverflow.ellipsis,
                               style: TextStyle(
                               style: TextStyle(
@@ -499,9 +499,9 @@ class _ExpenseDetailPageState extends ConsumerState<ExpenseDetailPage> {
                                 color: colors.textSecondary,
                                 color: colors.textSecondary,
                               ),
                               ),
                             ),
                             ),
-                          if (d.projectName.isNotEmpty)
+                          if (d.projectId.isNotEmpty)
                             Text(
                             Text(
-                              '${l10n.get('project')}: ${d.projectId}/${d.projectName}',
+                              '${l10n.get('project')}: ${d.projectId}${d.projectName.isNotEmpty ? '/${d.projectName}' : ''}',
                               maxLines: 1,
                               maxLines: 1,
                               overflow: TextOverflow.ellipsis,
                               overflow: TextOverflow.ellipsis,
                               style: TextStyle(
                               style: TextStyle(
@@ -509,9 +509,9 @@ class _ExpenseDetailPageState extends ConsumerState<ExpenseDetailPage> {
                                 color: colors.textSecondary,
                                 color: colors.textSecondary,
                               ),
                               ),
                             ),
                             ),
-                          if (d.costDeptName.isNotEmpty)
+                          if (d.costDeptId.isNotEmpty)
                             Text(
                             Text(
-                              '${l10n.get('costDept')}: ${d.costDeptId}/${d.costDeptName}',
+                              '${l10n.get('costDept')}: ${d.costDeptId}${d.costDeptName.isNotEmpty ? '/${d.costDeptName}' : ''}',
                               maxLines: 1,
                               maxLines: 1,
                               overflow: TextOverflow.ellipsis,
                               overflow: TextOverflow.ellipsis,
                               style: TextStyle(
                               style: TextStyle(
@@ -519,9 +519,9 @@ class _ExpenseDetailPageState extends ConsumerState<ExpenseDetailPage> {
                                 color: colors.textSecondary,
                                 color: colors.textSecondary,
                               ),
                               ),
                             ),
                             ),
-                          if (d.customerVendorName.isNotEmpty)
+                          if (d.customerVendorId.isNotEmpty)
                             Text(
                             Text(
-                              '${l10n.get('customerVendor')}: ${d.customerVendorId}/${d.customerVendorName}',
+                              '${l10n.get('customerVendor')}: ${d.customerVendorId}${d.customerVendorName.isNotEmpty ? '/${d.customerVendorName}' : ''}',
                               maxLines: 1,
                               maxLines: 1,
                               overflow: TextOverflow.ellipsis,
                               overflow: TextOverflow.ellipsis,
                               style: TextStyle(
                               style: TextStyle(
@@ -529,9 +529,9 @@ class _ExpenseDetailPageState extends ConsumerState<ExpenseDetailPage> {
                                 color: colors.textSecondary,
                                 color: colors.textSecondary,
                               ),
                               ),
                             ),
                             ),
-                          if (d.sqManName.isNotEmpty)
+                          if (d.sqMan.isNotEmpty)
                             Text(
                             Text(
-                              '${l10n.get('applicant')}: ${d.sqMan}/${d.sqManName}',
+                              '${l10n.get('applicant')}: ${d.sqMan}${d.sqManName.isNotEmpty ? '/${d.sqManName}' : ''}',
                               style: TextStyle(
                               style: TextStyle(
                                 fontSize: AppFontSizes.caption,
                                 fontSize: AppFontSizes.caption,
                                 color: colors.textSecondary,
                                 color: colors.textSecondary,
@@ -915,11 +915,12 @@ class _ExpAttachmentThumbnailState extends State<_ExpAttachmentThumbnail> {
   Future<void> _load() async {
   Future<void> _load() async {
     try {
     try {
       final bytes = await widget.api.downloadAttachment(widget.attachment.id);
       final bytes = await widget.api.downloadAttachment(widget.attachment.id);
-      if (mounted)
+      if (mounted) {
         setState(() {
         setState(() {
           _bytes = bytes;
           _bytes = bytes;
           _loading = false;
           _loading = false;
         });
         });
+      }
     } catch (_) {
     } catch (_) {
       if (mounted) setState(() => _loading = false);
       if (mounted) setState(() => _loading = false);
     }
     }

+ 10 - 10
lib/features/expense/expense_edit_page.dart

@@ -730,9 +730,9 @@ class _ExpenseEditPageState extends ConsumerState<ExpenseEditPage> {
                                 color: colors.textSecondary,
                                 color: colors.textSecondary,
                               ),
                               ),
                             ),
                             ),
-                          if (d.acctSubjectName.isNotEmpty)
+                          if (d.acctSubjectId.isNotEmpty)
                             Text(
                             Text(
-                              '${l10n.get('acctSubject')}: ${d.acctSubjectId}/${d.acctSubjectName}',
+                              '${l10n.get('acctSubject')}: ${d.acctSubjectId}${d.acctSubjectName.isNotEmpty ? '/${d.acctSubjectName}' : ''}',
                               maxLines: 1,
                               maxLines: 1,
                               overflow: TextOverflow.ellipsis,
                               overflow: TextOverflow.ellipsis,
                               style: TextStyle(
                               style: TextStyle(
@@ -758,9 +758,9 @@ class _ExpenseEditPageState extends ConsumerState<ExpenseEditPage> {
                                 color: colors.textSecondary,
                                 color: colors.textSecondary,
                               ),
                               ),
                             ),
                             ),
-                          if (d.projectName.isNotEmpty)
+                          if (d.projectId.isNotEmpty)
                             Text(
                             Text(
-                              '${l10n.get('project')}: ${d.projectId}/${d.projectName}',
+                              '${l10n.get('project')}: ${d.projectId}${d.projectName.isNotEmpty ? '/${d.projectName}' : ''}',
                               maxLines: 1,
                               maxLines: 1,
                               overflow: TextOverflow.ellipsis,
                               overflow: TextOverflow.ellipsis,
                               style: TextStyle(
                               style: TextStyle(
@@ -768,9 +768,9 @@ class _ExpenseEditPageState extends ConsumerState<ExpenseEditPage> {
                                 color: colors.textSecondary,
                                 color: colors.textSecondary,
                               ),
                               ),
                             ),
                             ),
-                          if (d.costDeptName.isNotEmpty)
+                          if (d.costDeptId.isNotEmpty)
                             Text(
                             Text(
-                              '${l10n.get('costDept')}: ${d.costDeptId}/${d.costDeptName}',
+                              '${l10n.get('costDept')}: ${d.costDeptId}${d.costDeptName.isNotEmpty ? '/${d.costDeptName}' : ''}',
                               maxLines: 1,
                               maxLines: 1,
                               overflow: TextOverflow.ellipsis,
                               overflow: TextOverflow.ellipsis,
                               style: TextStyle(
                               style: TextStyle(
@@ -778,9 +778,9 @@ class _ExpenseEditPageState extends ConsumerState<ExpenseEditPage> {
                                 color: colors.textSecondary,
                                 color: colors.textSecondary,
                               ),
                               ),
                             ),
                             ),
-                          if (d.customerVendorName.isNotEmpty)
+                          if (d.customerVendorId.isNotEmpty)
                             Text(
                             Text(
-                              '${l10n.get('customerVendor')}: ${d.customerVendorId}/${d.customerVendorName}',
+                              '${l10n.get('customerVendor')}: ${d.customerVendorId}${d.customerVendorName.isNotEmpty ? '/${d.customerVendorName}' : ''}',
                               maxLines: 1,
                               maxLines: 1,
                               overflow: TextOverflow.ellipsis,
                               overflow: TextOverflow.ellipsis,
                               style: TextStyle(
                               style: TextStyle(
@@ -788,9 +788,9 @@ class _ExpenseEditPageState extends ConsumerState<ExpenseEditPage> {
                                 color: colors.textSecondary,
                                 color: colors.textSecondary,
                               ),
                               ),
                             ),
                             ),
-                          if (d.sqManName.isNotEmpty)
+                          if (d.sqMan.isNotEmpty)
                             Text(
                             Text(
-                              '${l10n.get('applicant')}: ${d.sqMan}/${d.sqManName}',
+                              '${l10n.get('applicant')}: ${d.sqMan}${d.sqManName.isNotEmpty ? '/${d.sqManName}' : ''}',
                               style: TextStyle(
                               style: TextStyle(
                                 fontSize: AppFontSizes.caption,
                                 fontSize: AppFontSizes.caption,
                                 color: colors.textSecondary,
                                 color: colors.textSecondary,

+ 8 - 4
lib/features/expense/expense_list_page.dart

@@ -373,13 +373,14 @@ class _ExpenseListContent extends ConsumerWidget {
   Widget build(BuildContext context, WidgetRef ref) {
   Widget build(BuildContext context, WidgetRef ref) {
     final r = ResponsiveHelper.of(context);
     final r = ResponsiveHelper.of(context);
     final itemsAsync = ref.watch(expenseMyListProvider(''));
     final itemsAsync = ref.watch(expenseMyListProvider(''));
-    if (itemsAsync.isLoading && !itemsAsync.hasValue)
+    if (itemsAsync.isLoading && !itemsAsync.hasValue) {
       return Center(
       return Center(
         child: ConstrainedBox(
         child: ConstrainedBox(
           constraints: BoxConstraints(maxWidth: r.listMaxWidth),
           constraints: BoxConstraints(maxWidth: r.listMaxWidth),
           child: const SkeletonLoadingList(),
           child: const SkeletonLoadingList(),
         ),
         ),
       );
       );
+    }
     return Center(
     return Center(
       child: ConstrainedBox(
       child: ConstrainedBox(
         constraints: BoxConstraints(maxWidth: r.listMaxWidth),
         constraints: BoxConstraints(maxWidth: r.listMaxWidth),
@@ -401,13 +402,14 @@ class _ExpenseListContent extends ConsumerWidget {
     final l10n = AppLocalizations.of(context);
     final l10n = AppLocalizations.of(context);
     if (itemsAsync.isReloading) {
     if (itemsAsync.isReloading) {
       final oldItems = itemsAsync.valueOrNull ?? [];
       final oldItems = itemsAsync.valueOrNull ?? [];
-      if (oldItems.isEmpty)
+      if (oldItems.isEmpty) {
         return ListView(
         return ListView(
           children: [
           children: [
             const SizedBox(height: 120),
             const SizedBox(height: 120),
             EmptyState(message: l10n.get('noExpenses')),
             EmptyState(message: l10n.get('noExpenses')),
           ],
           ],
         );
         );
+      }
       return ListView.builder(
       return ListView.builder(
         padding: const EdgeInsets.fromLTRB(16, 16, 16, 24),
         padding: const EdgeInsets.fromLTRB(16, 16, 16, 24),
         itemCount: oldItems.length,
         itemCount: oldItems.length,
@@ -437,21 +439,23 @@ class _ExpenseListContent extends ConsumerWidget {
         },
         },
       );
       );
     }
     }
-    if (itemsAsync.hasError)
+    if (itemsAsync.hasError) {
       return ListView(
       return ListView(
         children: [
         children: [
           const SizedBox(height: 120),
           const SizedBox(height: 120),
           EmptyState(message: l10n.get('loadFailed')),
           EmptyState(message: l10n.get('loadFailed')),
         ],
         ],
       );
       );
+    }
     final items = itemsAsync.requireValue;
     final items = itemsAsync.requireValue;
-    if (items.isEmpty)
+    if (items.isEmpty) {
       return ListView(
       return ListView(
         children: [
         children: [
           const SizedBox(height: 120),
           const SizedBox(height: 120),
           EmptyState(message: l10n.get('noExpenses')),
           EmptyState(message: l10n.get('noExpenses')),
         ],
         ],
       );
       );
+    }
     return ListView.builder(
     return ListView.builder(
       padding: const EdgeInsets.fromLTRB(16, 16, 16, 24),
       padding: const EdgeInsets.fromLTRB(16, 16, 16, 24),
       itemCount: items.length + 1,
       itemCount: items.length + 1,

+ 1 - 1
lib/features/expense/widgets/expense_detail_dialog.dart

@@ -991,7 +991,7 @@ class _ExpenseDetailDialogState extends State<ExpenseDetailDialog> {
         : widget.initialData?.acctSubjectName ?? '';
         : widget.initialData?.acctSubjectName ?? '';
     return _readOnlyCard(
     return _readOnlyCard(
       label: _l10n.get('acctSubject'),
       label: _l10n.get('acctSubject'),
-      value: id.isNotEmpty ? '$id/$name' : '',
+      value: id.isNotEmpty ? '$id${name.isNotEmpty ? '/$name' : ''}' : '',
       colors: colors,
       colors: colors,
     );
     );
   }
   }

+ 4 - 4
lib/features/expense/widgets/expense_detail_view_dialog.dart

@@ -82,12 +82,12 @@ class ExpenseDetailViewDialog extends StatelessWidget {
                     if (d.taxRate > 0)
                     if (d.taxRate > 0)
                       _row(l10n.get('taxRate'), '${d.taxRate.toStringAsFixed(0)}%', colors),
                       _row(l10n.get('taxRate'), '${d.taxRate.toStringAsFixed(0)}%', colors),
                     _row(l10n.get('acctSubject'), d.acctSubjectId.isNotEmpty ? '${d.acctSubjectId}${d.acctSubjectName.isNotEmpty ? '/${d.acctSubjectName}' : ''}' : '-', colors),
                     _row(l10n.get('acctSubject'), d.acctSubjectId.isNotEmpty ? '${d.acctSubjectId}${d.acctSubjectName.isNotEmpty ? '/${d.acctSubjectName}' : ''}' : '-', colors),
-                    _row(l10n.get('project'), d.projectId.isNotEmpty && d.projectName.isNotEmpty ? '${d.projectId}/${d.projectName}' : '-', colors),
-                    _row(l10n.get('costDept'), d.costDeptId.isNotEmpty && d.costDeptName.isNotEmpty ? '${d.costDeptId}/${d.costDeptName}' : '-', colors),
-                    _row(l10n.get('customerVendor'), d.customerVendorName.isNotEmpty ? '${d.customerVendorId}/${d.customerVendorName}' : '-', colors),
+                    _row(l10n.get('project'), d.projectId.isNotEmpty ? '${d.projectId}${d.projectName.isNotEmpty ? '/${d.projectName}' : ''}' : '-', colors),
+                    _row(l10n.get('costDept'), d.costDeptId.isNotEmpty ? '${d.costDeptId}${d.costDeptName.isNotEmpty ? '/${d.costDeptName}' : ''}' : '-', colors),
+                    _row(l10n.get('customerVendor'), d.customerVendorId.isNotEmpty ? '${d.customerVendorId}${d.customerVendorName.isNotEmpty ? '/${d.customerVendorName}' : ''}' : '-', colors),
                     _row(l10n.get('expenseApplyNo'), d.aeNo.isNotEmpty ? d.aeNo : '-', colors),
                     _row(l10n.get('expenseApplyNo'), d.aeNo.isNotEmpty ? d.aeNo : '-', colors),
                     _row(l10n.get('applyDate'), d.aeDd.isNotEmpty ? _formatDate(d.aeDd) : '-', colors),
                     _row(l10n.get('applyDate'), d.aeDd.isNotEmpty ? _formatDate(d.aeDd) : '-', colors),
-                    _row(l10n.get('applicant'), d.sqManName.isNotEmpty ? '${d.sqMan}/${d.sqManName}' : '-', colors),
+                    _row(l10n.get('applicant'), d.sqMan.isNotEmpty ? '${d.sqMan}${d.sqManName.isNotEmpty ? '/${d.sqManName}' : ''}' : '-', colors),
                     _row(l10n.get('bankName'), d.bankName.isNotEmpty ? d.bankName : '-', colors),
                     _row(l10n.get('bankName'), d.bankName.isNotEmpty ? d.bankName : '-', colors),
                     _row(l10n.get('bankAccountName'), d.bankAccountName.isNotEmpty ? d.bankAccountName : '-', colors),
                     _row(l10n.get('bankAccountName'), d.bankAccountName.isNotEmpty ? d.bankAccountName : '-', colors),
                     _row(l10n.get('bankAccount'), d.bankAccount.isNotEmpty ? d.bankAccount : '-', colors),
                     _row(l10n.get('bankAccount'), d.bankAccount.isNotEmpty ? d.bankAccount : '-', colors),

+ 2 - 1
lib/features/expense_apply/expense_apply_create_page.dart

@@ -1078,8 +1078,9 @@ class _ExpenseApplyCreatePageState
   String? _extractErrorMessage(Object e) {
   String? _extractErrorMessage(Object e) {
     if (e is DioException) {
     if (e is DioException) {
       if (e.error is ApiException) return (e.error as ApiException).message;
       if (e.error is ApiException) return (e.error as ApiException).message;
-      if (e.error is NetworkException)
+      if (e.error is NetworkException) {
         return (e.error as NetworkException).message;
         return (e.error as NetworkException).message;
+      }
     }
     }
     return null;
     return null;
   }
   }

+ 10 - 11
lib/features/expense_apply/expense_apply_detail_page.dart

@@ -301,8 +301,8 @@ class _ExpenseApplyDetailPageState
         const SizedBox(height: 16),
         const SizedBox(height: 16),
         FormFieldRow(
         FormFieldRow(
           label: l10n.get('applicant'),
           label: l10n.get('applicant'),
-          value: app.applicantName.isNotEmpty
-              ? '${app.applicantId}/${app.applicantName}'
+          value: app.applicantId.isNotEmpty
+              ? '${app.applicantId}${app.applicantName.isNotEmpty ? '/${app.applicantName}' : ''}'
               : '-',
               : '-',
           readOnly: true,
           readOnly: true,
           showArrow: false,
           showArrow: false,
@@ -310,8 +310,8 @@ class _ExpenseApplyDetailPageState
         const SizedBox(height: 16),
         const SizedBox(height: 16),
         FormFieldRow(
         FormFieldRow(
           label: l10n.get('department'),
           label: l10n.get('department'),
-          value: app.deptName.isNotEmpty
-              ? '${app.deptId}/${app.deptName}'
+          value: app.deptId.isNotEmpty
+              ? '${app.deptId}${app.deptName.isNotEmpty ? '/${app.deptName}' : ''}'
               : '-',
               : '-',
           readOnly: true,
           readOnly: true,
           showArrow: false,
           showArrow: false,
@@ -433,11 +433,10 @@ class _ExpenseApplyDetailPageState
                               ),
                               ),
                             ),
                             ),
                           ],
                           ],
-                          if (d.projectId.isNotEmpty &&
-                              d.projectName.isNotEmpty) ...[
+                          if (d.projectId.isNotEmpty) ...[
                             const SizedBox(height: 4),
                             const SizedBox(height: 4),
                             Text(
                             Text(
-                              '${l10n.get('project')}: ${d.projectId}/${d.projectName}',
+                              '${l10n.get('project')}: ${d.projectId}${d.projectName.isNotEmpty ? '/${d.projectName}' : ''}',
                               maxLines: 1,
                               maxLines: 1,
                               overflow: TextOverflow.ellipsis,
                               overflow: TextOverflow.ellipsis,
                               style: TextStyle(
                               style: TextStyle(
@@ -446,11 +445,10 @@ class _ExpenseApplyDetailPageState
                               ),
                               ),
                             ),
                             ),
                           ],
                           ],
-                          if (d.costDeptId.isNotEmpty &&
-                              d.costDeptName.isNotEmpty) ...[
+                          if (d.costDeptId.isNotEmpty) ...[
                             const SizedBox(height: 4),
                             const SizedBox(height: 4),
                             Text(
                             Text(
-                              '${l10n.get('costDept')}: ${d.costDeptId}/${d.costDeptName}',
+                              '${l10n.get('costDept')}: ${d.costDeptId}${d.costDeptName.isNotEmpty ? '/${d.costDeptName}' : ''}',
                               maxLines: 1,
                               maxLines: 1,
                               overflow: TextOverflow.ellipsis,
                               overflow: TextOverflow.ellipsis,
                               style: TextStyle(
                               style: TextStyle(
@@ -786,11 +784,12 @@ class _AttachmentThumbnailState extends State<_AttachmentThumbnail> {
   Future<void> _load() async {
   Future<void> _load() async {
     try {
     try {
       final bytes = await widget.api.downloadAttachment(widget.attachment.id);
       final bytes = await widget.api.downloadAttachment(widget.attachment.id);
-      if (mounted)
+      if (mounted) {
         setState(() {
         setState(() {
           _bytes = bytes;
           _bytes = bytes;
           _loading = false;
           _loading = false;
         });
         });
+      }
     } catch (_) {
     } catch (_) {
       if (mounted) setState(() => _loading = false);
       if (mounted) setState(() => _loading = false);
     }
     }

+ 7 - 9
lib/features/expense_apply/expense_apply_edit_page.dart

@@ -559,7 +559,7 @@ class _ExpenseApplyEditPageState extends ConsumerState<ExpenseApplyEditPage> {
                             children: [
                             children: [
                               Expanded(
                               Expanded(
                                 child: Text(
                                 child: Text(
-                                  '${d.category}/${d.categoryName}',
+                                  '${d.category}${d.categoryName.isNotEmpty ? '/${d.categoryName}' : ''}',
                                   maxLines: 1,
                                   maxLines: 1,
                                   overflow: TextOverflow.ellipsis,
                                   overflow: TextOverflow.ellipsis,
                                   style: TextStyle(
                                   style: TextStyle(
@@ -579,11 +579,10 @@ class _ExpenseApplyEditPageState extends ConsumerState<ExpenseApplyEditPage> {
                               ),
                               ),
                             ],
                             ],
                           ),
                           ),
-                          if (d.acctSubjectId.isNotEmpty &&
-                              d.acctSubjectName.isNotEmpty) ...[
+                          if (d.acctSubjectId.isNotEmpty) ...[
                             const SizedBox(height: 4),
                             const SizedBox(height: 4),
                             Text(
                             Text(
-                              '${l10n.get('acctSubject')}: ${d.acctSubjectId}/${d.acctSubjectName}',
+                              '${l10n.get('acctSubject')}: ${d.acctSubjectId}${d.acctSubjectName.isNotEmpty ? '/${d.acctSubjectName}' : ''}',
                               maxLines: 1,
                               maxLines: 1,
                               overflow: TextOverflow.ellipsis,
                               overflow: TextOverflow.ellipsis,
                               style: TextStyle(
                               style: TextStyle(
@@ -592,10 +591,10 @@ class _ExpenseApplyEditPageState extends ConsumerState<ExpenseApplyEditPage> {
                               ),
                               ),
                             ),
                             ),
                           ],
                           ],
-                          if (d.projectId.isNotEmpty && d.projectName.isNotEmpty) ...[
+                          if (d.projectId.isNotEmpty) ...[
                             const SizedBox(height: 4),
                             const SizedBox(height: 4),
                             Text(
                             Text(
-                              '${l10n.get('project')}: ${d.projectId}/${d.projectName}',
+                              '${l10n.get('project')}: ${d.projectId}${d.projectName.isNotEmpty ? '/${d.projectName}' : ''}',
                               maxLines: 1,
                               maxLines: 1,
                               overflow: TextOverflow.ellipsis,
                               overflow: TextOverflow.ellipsis,
                               style: TextStyle(
                               style: TextStyle(
@@ -604,11 +603,10 @@ class _ExpenseApplyEditPageState extends ConsumerState<ExpenseApplyEditPage> {
                               ),
                               ),
                             ),
                             ),
                           ],
                           ],
-                          if (d.costDeptId.isNotEmpty &&
-                              d.costDeptName.isNotEmpty) ...[
+                          if (d.costDeptId.isNotEmpty) ...[
                             const SizedBox(height: 4),
                             const SizedBox(height: 4),
                             Text(
                             Text(
-                              '${l10n.get('costDept')}: ${d.costDeptId}/${d.costDeptName}',
+                              '${l10n.get('costDept')}: ${d.costDeptId}${d.costDeptName.isNotEmpty ? '/${d.costDeptName}' : ''}',
                               maxLines: 1,
                               maxLines: 1,
                               overflow: TextOverflow.ellipsis,
                               overflow: TextOverflow.ellipsis,
                               style: TextStyle(
                               style: TextStyle(

+ 3 - 1
lib/features/expense_apply/widgets/expense_apply_detail_dialog.dart

@@ -473,7 +473,9 @@ class _ExpenseApplyDetailDialogState extends State<ExpenseApplyDetailDialog> {
     final displayValue = hasValue
     final displayValue = hasValue
         ? (_selCat.acctSubjectName.startsWith(_selCat.acctSubjectId)
         ? (_selCat.acctSubjectName.startsWith(_selCat.acctSubjectId)
             ? _selCat.acctSubjectName
             ? _selCat.acctSubjectName
-            : '${_selCat.acctSubjectId}/${_selCat.acctSubjectName.toString()}')
+            : (_selCat.acctSubjectName.toString().isNotEmpty
+                ? '${_selCat.acctSubjectId}/${_selCat.acctSubjectName}'
+                : _selCat.acctSubjectId))
         : _l10n.get('pleaseSelect');
         : _l10n.get('pleaseSelect');
     return GestureDetector(
     return GestureDetector(
       onTap: () {
       onTap: () {

+ 2 - 2
lib/features/expense_apply/widgets/expense_apply_detail_view_dialog.dart

@@ -76,8 +76,8 @@ class ExpenseApplyDetailViewDialog extends StatelessWidget {
                     _row(l10n.get('expenseCategory'), catLabel, colors),
                     _row(l10n.get('expenseCategory'), catLabel, colors),
                     _row(l10n.get('estimatedAmount'), '¥${d.estimatedAmount.toStringAsFixed(2)}', colors),
                     _row(l10n.get('estimatedAmount'), '¥${d.estimatedAmount.toStringAsFixed(2)}', colors),
                     _row(l10n.get('acctSubject'), d.acctSubjectId.isNotEmpty ? '${d.acctSubjectId}${d.acctSubjectName.isNotEmpty ? '/${d.acctSubjectName}' : ''}' : '-', colors),
                     _row(l10n.get('acctSubject'), d.acctSubjectId.isNotEmpty ? '${d.acctSubjectId}${d.acctSubjectName.isNotEmpty ? '/${d.acctSubjectName}' : ''}' : '-', colors),
-                    _row(l10n.get('project'), d.projectId.isNotEmpty && d.projectName.isNotEmpty ? '${d.projectId}/${d.projectName}' : '-', colors),
-                    _row(l10n.get('costDept'), d.costDeptId.isNotEmpty && d.costDeptName.isNotEmpty ? '${d.costDeptId}/${d.costDeptName}' : '-', colors),
+                    _row(l10n.get('project'), d.projectId.isNotEmpty ? '${d.projectId}${d.projectName.isNotEmpty ? '/${d.projectName}' : ''}' : '-', colors),
+                    _row(l10n.get('costDept'), d.costDeptId.isNotEmpty ? '${d.costDeptId}${d.costDeptName.isNotEmpty ? '/${d.costDeptName}' : ''}' : '-', colors),
                     _row(l10n.get('estimatedDate'), d.estimatedStartDate != null ? '${du.DateUtils.formatDate(d.estimatedStartDate!)}${d.estimatedEndDate != null ? ' ~ ${du.DateUtils.formatDate(d.estimatedEndDate!)}' : ''}' : '-', colors),
                     _row(l10n.get('estimatedDate'), d.estimatedStartDate != null ? '${du.DateUtils.formatDate(d.estimatedStartDate!)}${d.estimatedEndDate != null ? ' ~ ${du.DateUtils.formatDate(d.estimatedEndDate!)}' : ''}' : '-', colors),
                     _row(l10n.get('expenseNo'), d.bxNo.isNotEmpty ? d.bxNo : '-', colors),
                     _row(l10n.get('expenseNo'), d.bxNo.isNotEmpty ? d.bxNo : '-', colors),
                     _row(l10n.get('remark'), d.remark.isNotEmpty ? d.remark : '-', colors),
                     _row(l10n.get('remark'), d.remark.isNotEmpty ? d.remark : '-', colors),

+ 2 - 1
lib/features/report/expense_apply_detail_report_page.dart

@@ -66,11 +66,12 @@ class _ExpenseApplyDetailReportPageState
         _loadDetails();
         _loadDetails();
       }
       }
     } catch (e) {
     } catch (e) {
-      if (mounted)
+      if (mounted) {
         setState(() {
         setState(() {
           _error = e.toString();
           _error = e.toString();
           _loading = false;
           _loading = false;
         });
         });
+      }
     }
     }
   }
   }