// Author: fruit.com.cn import 'package:flutter/material.dart'; import '../config/app_config.dart'; import '../theme/app_colors.dart'; /// 封面图统一入口:后端给的是相对路径,这里补服务地址并处理加载失败。 class RemoteImage extends StatelessWidget { const RemoteImage( this.path, { super.key, this.width, this.height, this.fit = BoxFit.cover, this.showFallbackIcon = false, this.fallbackIconKey, this.fallbackAspectRatio, this.fallbackColor = AppColors.raised, }); final String path; final double? width; final double? height; final BoxFit fit; final bool showFallbackIcon; final Key? fallbackIconKey; final double? fallbackAspectRatio; final Color fallbackColor; @override Widget build(BuildContext context) { final url = AppConfig.mediaUrl(path); if (url.isEmpty) return _fallback(brand: showFallbackIcon); return Image.network( url, width: width, height: height, fit: fit, gaplessPlayback: true, errorBuilder: (_, _, _) => _fallback(brand: showFallbackIcon), frameBuilder: (context, child, frame, wasSynchronouslyLoaded) { if (wasSynchronouslyLoaded || frame != null) return child; return _fallback(brand: showFallbackIcon); }, ); } Widget _fallback({required bool brand}) { final mark = brand ? LayoutBuilder( builder: (context, constraints) { final width = constraints.maxWidth.isFinite ? constraints.maxWidth : 120.0; return Center( child: Image.asset( 'assets/icon/splash_logo.png', key: fallbackIconKey, width: width * 0.72, fit: BoxFit.contain, ), ); }, ) : null; final fallback = Container( width: width, height: height, color: brand ? AppColors.mediaBlack : fallbackColor, alignment: Alignment.center, child: mark, ); final ratio = fallbackAspectRatio; if (ratio == null) return fallback; return AspectRatio(aspectRatio: ratio, child: fallback); } }