126 lines
3.6 KiB
Dart
126 lines
3.6 KiB
Dart
|
|
import 'package:flutter/material.dart';
|
||
|
|
|
||
|
|
import '../models/theme_template.dart';
|
||
|
|
|
||
|
|
/// 模拟门店主页头部预览浮层。
|
||
|
|
///
|
||
|
|
/// 依据选中的 [ThemeTemplate] 渲染一个模拟的门店主页头部
|
||
|
|
///(主色背景 + 门店名 + Logo 占位),用于主题选择时实时预览效果。
|
||
|
|
class StoreThemePreview extends StatelessWidget {
|
||
|
|
const StoreThemePreview({
|
||
|
|
super.key,
|
||
|
|
this.template,
|
||
|
|
this.storeName = '示例门店',
|
||
|
|
});
|
||
|
|
|
||
|
|
/// 选中的主题模板;空时回退默认主题。
|
||
|
|
final ThemeTemplate? template;
|
||
|
|
|
||
|
|
/// 预览中的门店名称。
|
||
|
|
final String storeName;
|
||
|
|
|
||
|
|
@override
|
||
|
|
Widget build(BuildContext context) {
|
||
|
|
final primary = _accentColor(template?.name ?? '');
|
||
|
|
final label = template?.name ?? '默认主题';
|
||
|
|
final onColor = Colors.white;
|
||
|
|
|
||
|
|
return Container(
|
||
|
|
width: double.infinity,
|
||
|
|
padding: const EdgeInsets.all(16),
|
||
|
|
decoration: BoxDecoration(
|
||
|
|
gradient: LinearGradient(
|
||
|
|
colors: [primary, primary.withOpacity(0.75)],
|
||
|
|
begin: Alignment.topLeft,
|
||
|
|
end: Alignment.bottomRight,
|
||
|
|
),
|
||
|
|
borderRadius: BorderRadius.circular(12),
|
||
|
|
),
|
||
|
|
child: Column(
|
||
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||
|
|
children: [
|
||
|
|
Row(
|
||
|
|
children: [
|
||
|
|
_placeholderLogo(primary, onColor),
|
||
|
|
const SizedBox(width: 12),
|
||
|
|
Expanded(
|
||
|
|
child: Column(
|
||
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||
|
|
children: [
|
||
|
|
Text(
|
||
|
|
storeName,
|
||
|
|
style: const TextStyle(
|
||
|
|
color: Colors.white,
|
||
|
|
fontSize: 18,
|
||
|
|
fontWeight: FontWeight.bold,
|
||
|
|
),
|
||
|
|
),
|
||
|
|
const SizedBox(height: 4),
|
||
|
|
Container(
|
||
|
|
padding: const EdgeInsets.symmetric(
|
||
|
|
horizontal: 8,
|
||
|
|
vertical: 2,
|
||
|
|
),
|
||
|
|
decoration: BoxDecoration(
|
||
|
|
color: Colors.white.withOpacity(0.25),
|
||
|
|
borderRadius: BorderRadius.circular(999),
|
||
|
|
),
|
||
|
|
child: Text(
|
||
|
|
label,
|
||
|
|
style: const TextStyle(
|
||
|
|
color: Colors.white,
|
||
|
|
fontSize: 12,
|
||
|
|
),
|
||
|
|
),
|
||
|
|
),
|
||
|
|
],
|
||
|
|
),
|
||
|
|
),
|
||
|
|
],
|
||
|
|
),
|
||
|
|
const SizedBox(height: 16),
|
||
|
|
// 模拟内容卡占位。
|
||
|
|
Container(
|
||
|
|
height: 56,
|
||
|
|
decoration: BoxDecoration(
|
||
|
|
color: Colors.white.withOpacity(0.18),
|
||
|
|
borderRadius: BorderRadius.circular(8),
|
||
|
|
),
|
||
|
|
),
|
||
|
|
],
|
||
|
|
),
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
Widget _placeholderLogo(Color primary, Color onColor) {
|
||
|
|
return Container(
|
||
|
|
width: 48,
|
||
|
|
height: 48,
|
||
|
|
decoration: BoxDecoration(
|
||
|
|
color: Colors.white,
|
||
|
|
shape: BoxShape.circle,
|
||
|
|
border: Border.all(color: primary, width: 2),
|
||
|
|
),
|
||
|
|
alignment: Alignment.center,
|
||
|
|
child: Icon(Icons.storefront, color: primary, size: 26),
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
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];
|
||
|
|
}
|
||
|
|
}
|