import 'package:flutter/material.dart'; import 'package:skeletonizer/skeletonizer.dart'; import '../../core/theme/app_colors_extension.dart'; /// 骨架占位卡片容器(列表加载态) class SkeletonLoadingList extends StatelessWidget { final int cardCount; final Widget Function() cardBuilder; final EdgeInsetsGeometry padding; const SkeletonLoadingList({ super.key, this.cardCount = 5, this.cardBuilder = _defaultBuilder, this.padding = const EdgeInsets.fromLTRB(16, 16, 16, 24), }); static Widget _defaultBuilder() => const SkeletonListCard(); @override Widget build(BuildContext context) { return SingleChildScrollView( padding: padding, child: Skeletonizer( enabled: true, child: Column( children: List.generate( cardCount, (_) => Padding( padding: const EdgeInsets.only(bottom: 16), child: cardBuilder(), ), ), ), ), ); } } /// 匹配 ListCard 的骨架占位 class SkeletonListCard extends StatelessWidget { const SkeletonListCard({super.key}); @override Widget build(BuildContext context) { final colors = Theme.of(context).extension()!; return Skeletonizer( enabled: true, child: Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: colors.bgCard, borderRadius: BorderRadius.circular(8), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Bone.text(width: 120), Bone.text(width: 80), ], ), SizedBox(height: 6), Bone.text(width: 140), SizedBox(height: 6), Bone.text(), SizedBox(height: 8), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Bone.text(width: 100), Bone(width: 48, height: 20, borderRadius: BorderRadius.circular(4)), ], ), ], ), ), ); } } /// 匹配车辆列表卡片的骨架占位 class SkeletonVehicleCard extends StatelessWidget { const SkeletonVehicleCard({super.key}); @override Widget build(BuildContext context) { final colors = Theme.of(context).extension()!; return Skeletonizer( enabled: true, child: Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: colors.bgCard, borderRadius: BorderRadius.circular(8), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Bone.text(width: 100), Bone(width: 48, height: 20, borderRadius: BorderRadius.circular(4)), ], ), SizedBox(height: 6), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Bone.text(width: 140), Bone(width: 40, height: 16, borderRadius: BorderRadius.circular(4)), ], ), SizedBox(height: 6), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Expanded(child: Bone.text()), const SizedBox(width: 8), Bone.text(width: 120), ], ), ], ), ), ); } } /// 匹配外勤日志卡片的骨架占位 class SkeletonOutingLogCard extends StatelessWidget { const SkeletonOutingLogCard({super.key}); @override Widget build(BuildContext context) { final colors = Theme.of(context).extension()!; return Skeletonizer( enabled: true, child: Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: colors.bgCard, borderRadius: BorderRadius.circular(8), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Bone.text(width: 100), SizedBox(height: 4), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Expanded(flex: 3, child: Bone.text()), const SizedBox(width: 8), Bone(width: 48, height: 20, borderRadius: BorderRadius.circular(4)), ], ), SizedBox(height: 4), Bone.text(), SizedBox(height: 4), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Expanded(flex: 2, child: Bone.text()), const SizedBox(width: 8), Bone.text(width: 80), ], ), ], ), ), ); } } /// 匹配公告卡片的骨架占位 class SkeletonAnnouncementCard extends StatelessWidget { const SkeletonAnnouncementCard({super.key}); @override Widget build(BuildContext context) { final colors = Theme.of(context).extension()!; return Skeletonizer( enabled: true, child: Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: colors.bgCard, borderRadius: BorderRadius.circular(8), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Bone.text(), SizedBox(height: 8), Row( children: [ Bone(width: 56, height: 20, borderRadius: BorderRadius.circular(4)), const SizedBox(width: 8), Bone.text(width: 60), const Spacer(), Bone.text(width: 120), ], ), ], ), ), ); } } /// 匹配费用申请导入列表卡片的骨架占位 class SkeletonImportCard extends StatelessWidget { const SkeletonImportCard({super.key}); @override Widget build(BuildContext context) { final colors = Theme.of(context).extension()!; return Skeletonizer( enabled: true, child: Container( padding: const EdgeInsets.fromLTRB(16, 12, 16, 8), decoration: BoxDecoration( color: colors.bgCard, borderRadius: BorderRadius.circular(12), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Bone.square(size: 22, borderRadius: BorderRadius.circular(4)), const SizedBox(width: 8), Expanded(flex: 3, child: Bone.text()), const Spacer(), Bone.text(width: 80), ], ), SizedBox(height: 8), Row(children: [const SizedBox(width: 30), Bone.text(width: 140)]), SizedBox(height: 8), Row( children: [ Bone.square(size: 18, borderRadius: BorderRadius.circular(4)), const SizedBox(width: 4), Bone.text(width: 24), const SizedBox(width: 8), Expanded(flex: 3, child: Bone.text()), const Spacer(), Bone.text(width: 64), ], ), SizedBox(height: 8), Row(children: [const SizedBox(width: 54), Expanded(flex: 2, child: Bone.text())]), ], ), ), ); } } /// 匹配消息卡片的骨架占位 class SkeletonMessageCard extends StatelessWidget { const SkeletonMessageCard({super.key}); @override Widget build(BuildContext context) { final colors = Theme.of(context).extension()!; return Skeletonizer( enabled: true, child: Container( height: 88, padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: colors.bgCard, borderRadius: BorderRadius.circular(8), ), child: Row( children: [ Bone.circle(size: 40), SizedBox(width: 12), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Expanded(flex: 3, child: Bone.text()), const Spacer(), Bone.text(width: 80), ], ), SizedBox(height: 2), Bone.text(width: 80), SizedBox(height: 2), Expanded(flex: 2, child: Bone.text()), ], ), ), SizedBox(width: 12), Bone(width: 8, height: 8, borderRadius: BorderRadius.circular(4)), ], ), ), ); } }