| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144 |
- import 'package:flutter/material.dart';
- import 'package:tdesign_flutter/tdesign_flutter.dart';
- import '../../core/theme/app_colors.dart';
- import '../../core/theme/app_colors_extension.dart';
- import '../../core/i18n/app_localizations.dart';
- /// 审核过程明细弹窗
- ///
- /// 调用 [AuditTrailDialog.show] 弹出,自动拉取数据并展示。
- class AuditTrailDialog extends StatelessWidget {
- final Future<List<Map<String, dynamic>>> Function() fetcher;
- const AuditTrailDialog({super.key, required this.fetcher});
- /// 显示弹窗,[fetcher] 负责调 API 获取数据。
- static Future<void> show(
- BuildContext context, {
- required Future<List<Map<String, dynamic>>> Function() fetcher,
- }) {
- return Navigator.push(
- context,
- TDSlidePopupRoute(
- slideTransitionFrom: SlideTransitionFrom.bottom,
- builder: (_) => AuditTrailDialog(fetcher: fetcher),
- ),
- );
- }
- @override
- Widget build(BuildContext context) {
- final l10n = AppLocalizations.of(context);
- final colors = Theme.of(context).extension<AppColorsExtension>()!;
- return FutureBuilder<List<Map<String, dynamic>>>(
- future: fetcher(),
- builder: (ctx, snapshot) {
- return SafeArea(
- child: SizedBox(
- height: MediaQuery.of(context).size.height * 0.8,
- child: Container(
- decoration: BoxDecoration(
- color: colors.bgPage,
- borderRadius: const BorderRadius.vertical(top: Radius.circular(16)),
- ),
- child: Column(
- children: [
- Padding(
- padding: const EdgeInsets.fromLTRB(20, 16, 12, 12),
- child: Row(
- children: [
- Text(
- l10n.get('auditTrail'),
- style: TextStyle(fontSize: AppFontSizes.title, fontWeight: FontWeight.w600, color: colors.textPrimary),
- ),
- const Spacer(),
- GestureDetector(
- onTap: () => Navigator.pop(context),
- child: Icon(Icons.close, size: 20, color: colors.textSecondary),
- ),
- ],
- ),
- ),
- Divider(height: 1, color: colors.border),
- Flexible(
- child: _buildContent(snapshot, colors),
- ),
- ],
- ),
- ),
- ),
- );
- },
- );
- }
- Widget _buildContent(AsyncSnapshot<List<Map<String, dynamic>>> snapshot, AppColorsExtension colors) {
- if (snapshot.connectionState == ConnectionState.waiting) {
- return const Center(child: TDLoading(size: TDLoadingSize.medium, icon: TDLoadingIcon.activity));
- }
- if (snapshot.hasError || !snapshot.hasData || snapshot.data!.isEmpty) {
- return const Center(child: Text('—', style: TextStyle(fontSize: 14, color: Color(0xFF999999))));
- }
- final items = snapshot.data!;
- return ListView.builder(
- shrinkWrap: true,
- padding: const EdgeInsets.all(16),
- itemCount: items.length,
- itemBuilder: (_, i) {
- final item = items[i];
- final action = item['action']?.toString() ?? '';
- Color iconColor;
- IconData icon;
- if (action == 'Y') {
- icon = Icons.check_circle;
- iconColor = colors.success;
- } else if (action == 'N') {
- icon = Icons.cancel;
- iconColor = colors.danger;
- } else {
- icon = Icons.hourglass_empty;
- iconColor = colors.infoText;
- }
- return Padding(
- padding: const EdgeInsets.only(bottom: 12),
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- Row(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- Icon(icon, size: 18, color: iconColor),
- const SizedBox(width: 8),
- Expanded(
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- Row(
- children: [
- Expanded(child: Text(item['user']?.toString() ?? '', style: TextStyle(fontSize: 14, fontWeight: FontWeight.w600, color: colors.textPrimary))),
- Text(item['date']?.toString() ?? '', style: TextStyle(fontSize: 12, color: colors.textSecondary)),
- ],
- ),
- if ((item['node']?.toString() ?? '').isNotEmpty) ...[
- const SizedBox(height: 2),
- Text(item['node']?.toString() ?? '', style: TextStyle(fontSize: 13, color: colors.textSecondary)),
- ],
- ],
- ),
- ),
- ],
- ),
- if ((item['remark']?.toString() ?? '').isNotEmpty) ...[
- const SizedBox(height: 4),
- Padding(
- padding: const EdgeInsets.only(left: 26),
- child: Text(item['remark']?.toString() ?? '', style: TextStyle(fontSize: 13, color: colors.textSecondary)),
- ),
- ],
- ],
- ),
- );
- },
- );
- }
- }
|