import 'package:flutter/material.dart'; import '../core/theme/app_theme.dart'; /// 移动端列表卡片的单个字段(label: value)。 class MobileCardField { final String label; final String? value; /// 自定义值控件(如带颜色的金额、状态徽章);提供后忽略 [value]。 final Widget? valueWidget; const MobileCardField(this.label, this.value, {this.valueWidget}); } /// 窄屏(手机)列表的通用卡片:标题 + 右上角徽章 + 字段竖排 + 底部操作。 /// 替代宽屏的表格行,使一行数据在手机上可一屏读完、操作可点。 class MobileListCard extends StatelessWidget { final Widget title; final Widget? subtitle; final Widget? trailing; final List fields; final List? actions; final VoidCallback? onTap; const MobileListCard({ super.key, required this.title, this.subtitle, this.trailing, this.fields = const [], this.actions, this.onTap, }); @override Widget build(BuildContext context) { return Card( margin: EdgeInsets.zero, elevation: 0, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8), side: BorderSide(color: Colors.grey.shade200), ), child: InkWell( borderRadius: BorderRadius.circular(8), onTap: onTap, child: Padding( padding: const EdgeInsets.all(12), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ DefaultTextStyle( style: const TextStyle( fontSize: 15, fontWeight: FontWeight.w600, color: AppTheme.textPrimary, ), child: title, ), if (subtitle != null) ...[ const SizedBox(height: 2), DefaultTextStyle( style: const TextStyle( fontSize: 12, color: AppTheme.textSecondary), child: subtitle!, ), ], ], ), ), if (trailing != null) ...[ const SizedBox(width: 8), trailing!, ], ], ), if (fields.isNotEmpty) ...[ const SizedBox(height: 10), ...fields.map(_buildField), ], if (actions != null && actions!.isNotEmpty) ...[ const Divider(height: 18), Align( alignment: Alignment.centerRight, child: Wrap( spacing: 4, children: actions!, ), ), ], ], ), ), ), ); } Widget _buildField(MobileCardField f) { return Padding( padding: const EdgeInsets.symmetric(vertical: 3), child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ SizedBox( width: 64, child: Text( f.label, style: const TextStyle( fontSize: 13, color: AppTheme.textSecondary), ), ), Expanded( child: f.valueWidget ?? Text( f.value ?? '—', style: const TextStyle( fontSize: 13, color: AppTheme.textPrimary), ), ), ], ), ); } }