import 'package:flutter/material.dart'; import '../../../../core/constants/app_breakpoints.dart'; import '../../../../core/constants/app_sizes.dart'; import '../../../../core/theme/app_colors.dart'; import '../../../../core/theme/app_text_styles.dart'; import '../../domain/models/link_item.dart'; import '../../domain/models/link_section.dart'; import 'link_card.dart'; /// 一个分组:标题 + 自适应网格。 class LinkSectionView extends StatelessWidget { const LinkSectionView({ super.key, required this.section, required this.onOpen, }); /// 分组数据。 final LinkSection section; /// 打开某个站点。 final ValueChanged onOpen; @override Widget build(BuildContext context) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ _SectionTitle(title: section.title), const SizedBox(height: AppSizes.sectionTitleGap), LayoutBuilder( builder: (BuildContext context, BoxConstraints constraints) { final int columns = AppBreakpoints.gridColumnsFor( constraints.maxWidth, minItemWidth: AppSizes.gridMinItemWidth, gap: AppSizes.gridGap, ); final double itemWidth = (constraints.maxWidth - AppSizes.gridGap * (columns - 1)) / columns; return Wrap( spacing: AppSizes.gridGap, runSpacing: AppSizes.gridGap, children: [ for (final LinkItem item in section.items) SizedBox( width: itemWidth, child: LinkCard(item: item, onOpen: () => onOpen(item)), ), ], ); }, ), ], ); } } /// 分组标题:左侧一条 4×16 的主色竖条 + 文字(`.section-title::before`)。 class _SectionTitle extends StatelessWidget { const _SectionTitle({required this.title}); final String title; @override Widget build(BuildContext context) { return Row( children: [ Container( width: AppSizes.sectionAccentWidth, height: AppSizes.sectionAccentHeight, decoration: BoxDecoration( color: AppColors.primary, borderRadius: BorderRadius.circular(AppSizes.sectionAccentRadius), ), ), const SizedBox(width: AppSizes.sectionAccentGap), // 用 Flexible 包住:窄屏(侧栏展开后主内容只剩一百多像素)时 // 「素材资源 - UI 设计」这类长标题会溢出,这里退化成省略号。 Flexible( child: Text( title, style: AppTextStyles.sectionTitle, maxLines: 1, overflow: TextOverflow.ellipsis, ), ), ], ); } }