import 'package:flutter/material.dart'; import '../models/theme_template.dart'; /// 主题模板网格卡片(封面图 + 名称)。 /// /// 用于门店表单中「主题皮肤」选择;[selectedId] 高亮选中态, /// [onSelected] 回传选中模板的 [ThemeTemplate.id]。 class StoreThemeGrid extends StatelessWidget { const StoreThemeGrid({ super.key, required this.templates, required this.onSelected, this.selectedId, }); /// 可选主题模板列表。 final List templates; /// 选中回调,回传模板 id。 final ValueChanged onSelected; /// 当前选中的模板 id(高亮)。 final String? selectedId; @override Widget build(BuildContext context) { if (templates.isEmpty) { return const SizedBox( height: 80, child: Center(child: Text('暂无可用主题模板')), ); } return GridView.count( crossAxisCount: 3, shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), mainAxisSpacing: 12, crossAxisSpacing: 12, childAspectRatio: 0.9, children: templates.map((template) { final selected = template.id == selectedId; return _ThemeCard( template: template, selected: selected, onTap: () => onSelected(template.id), ); }).toList(), ); } } class _ThemeCard extends StatelessWidget { const _ThemeCard({ required this.template, required this.selected, required this.onTap, }); final ThemeTemplate template; final bool selected; final VoidCallback onTap; @override Widget build(BuildContext context) { final primary = _accentColor(template.name); final coverUrl = template.coverUrl; return InkWell( onTap: onTap, borderRadius: BorderRadius.circular(12), child: Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(12), border: Border.all( color: selected ? Theme.of(context).colorScheme.primary : Colors.transparent, width: selected ? 2.5 : 1, ), ), child: Column( children: [ // 封面预览(优先 coverUrl,否则用名称哈希色块)。 Expanded( child: Container( decoration: BoxDecoration( color: coverUrl == null || coverUrl.isEmpty ? primary : null, borderRadius: const BorderRadius.vertical(top: Radius.circular(10)), image: coverUrl != null && coverUrl.isNotEmpty ? DecorationImage( image: NetworkImage(coverUrl), fit: BoxFit.cover, ) : null, ), alignment: Alignment.center, child: coverUrl == null || coverUrl.isEmpty ? Text( template.name.isEmpty ? '主题' : template.name[0], style: const TextStyle( color: Colors.white, fontSize: 28, fontWeight: FontWeight.bold, ), ) : null, ), ), // 名称。 Container( height: 34, alignment: Alignment.center, padding: const EdgeInsets.symmetric(horizontal: 4), child: Text( template.name, maxLines: 1, overflow: TextOverflow.ellipsis, style: const TextStyle(fontSize: 13, fontWeight: FontWeight.w600), ), ), ], ), ), ); } static const _palette = [ Color(0xFF3B82F6), Color(0xFF8B5CF6), Color(0xFFEC4899), Color(0xFFF59E0B), Color(0xFF10B981), Color(0xFF6366F1), ]; static Color _accentColor(String name) { var hash = 0; for (var i = 0; i < name.length; i++) { hash = (hash + name.codeUnitAt(i) * (i + 1)) % _palette.length; } return _palette[hash]; } }