This commit is contained in:
Developer
2026-04-03 03:26:06 +08:00
parent 3063deb34c
commit cba04235c8
49 changed files with 3955 additions and 1421 deletions

View File

@@ -11,6 +11,7 @@ import '../../../services/get/theme_controller.dart';
import '../../../utils/http/poetry_api.dart';
import '../../../utils/audio_manager.dart';
import 'set/home_components.dart';
import 'components/skeleton_widgets.dart';
/// 诗词卡片组件 - 优化版本,防止拉伸和处理文本溢出
class PoetryCard extends StatefulWidget {
@@ -130,65 +131,61 @@ class _PoetryCardState extends State<PoetryCard> {
),
],
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
_buildTimeBar(isDark, themeColor),
Padding(
padding: const EdgeInsets.all(20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
_buildTitleSection(isDark, themeColor),
if (widget.poetryData.drtime.isNotEmpty) ...[
_buildContentSection(context, isDark, themeColor),
const SizedBox(height: 3),
],
Align(
alignment: Alignment.centerRight,
child: Container(
margin: EdgeInsets.zero,
padding: const EdgeInsets.symmetric(
horizontal: 12,
vertical: 2,
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Text(
'精选诗句',
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.w500,
color: themeColor,
),
),
const SizedBox(width: 4),
Icon(
Icons.format_quote,
color: themeColor,
size: 14,
),
],
),
),
child: Padding(
padding: const EdgeInsets.only(
left: 20,
right: 20,
bottom: 20,
top: 50,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
_buildTitleSection(isDark, themeColor),
if (widget.poetryData.drtime.isNotEmpty) ...[
_buildContentSection(context, isDark, themeColor),
const SizedBox(height: 3),
],
Align(
alignment: Alignment.centerRight,
child: Container(
margin: EdgeInsets.zero,
padding: const EdgeInsets.symmetric(
horizontal: 12,
vertical: 2,
),
_buildNameSection(isDark, themeColor),
const SizedBox(height: 12),
if (widget.keywordList.isNotEmpty) ...[
_buildKeywordSection(isDark, themeColor),
const SizedBox(height: 16),
],
if (widget.poetryData.introduce.isNotEmpty) ...[
_buildIntroductionSection(context, isDark, themeColor),
],
],
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Text(
'精选诗句',
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.w500,
color: themeColor,
),
),
const SizedBox(width: 4),
Icon(Icons.format_quote, color: themeColor, size: 14),
],
),
),
),
),
],
_buildNameSection(isDark, themeColor),
const SizedBox(height: 12),
if (widget.keywordList.isNotEmpty) ...[
_buildKeywordSection(isDark, themeColor),
const SizedBox(height: 16),
],
if (widget.poetryData.introduce.isNotEmpty) ...[
_buildIntroductionSection(context, isDark, themeColor),
],
],
),
),
),
_buildTimeBar(isDark, themeColor),
_buildCopyTip(isDark, themeColor),
],
),
@@ -201,52 +198,57 @@ class _PoetryCardState extends State<PoetryCard> {
}
Widget _buildTimeBar(bool isDark, Color themeColor) {
return GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () {
setState(() {
_showRecommendation = !_showRecommendation;
});
},
child: Container(
width: double.infinity,
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 12),
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [themeColor.withAlpha(204), themeColor],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
return Positioned(
top: 16,
left: 16,
right: 16,
child: GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () {
setState(() {
_showRecommendation = !_showRecommendation;
});
},
child: Container(
width: double.infinity,
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 12),
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [themeColor.withAlpha(204), themeColor],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
borderRadius: const BorderRadius.vertical(top: Radius.circular(16)),
),
borderRadius: const BorderRadius.vertical(top: Radius.circular(16)),
),
child: Row(
children: [
Icon(
_showRecommendation ? Icons.lightbulb : Icons.wb_sunny,
color: Colors.white,
size: 20,
),
const SizedBox(width: 8),
Expanded(
child: Text(
_showRecommendation
? _getRecommendation()
: _getTimeOfDayGreeting(),
style: const TextStyle(
color: Colors.white,
fontSize: 14,
fontWeight: FontWeight.w500,
),
overflow: TextOverflow.ellipsis,
maxLines: 1,
child: Row(
children: [
Icon(
_showRecommendation ? Icons.lightbulb : Icons.wb_sunny,
color: Colors.white,
size: 20,
),
),
Icon(
_showRecommendation ? Icons.expand_less : Icons.expand_more,
color: Colors.white70,
size: 20,
),
],
const SizedBox(width: 8),
Expanded(
child: Text(
_showRecommendation
? _getRecommendation()
: _getTimeOfDayGreeting(),
style: const TextStyle(
color: Colors.white,
fontSize: 14,
fontWeight: FontWeight.w500,
),
overflow: TextOverflow.ellipsis,
maxLines: 1,
),
),
Icon(
_showRecommendation ? Icons.expand_less : Icons.expand_more,
color: Colors.white70,
size: 20,
),
],
),
),
),
);
@@ -258,7 +260,7 @@ class _PoetryCardState extends State<PoetryCard> {
}
return Positioned(
top: 56,
top: 80,
right: 24,
child: GestureDetector(
onTap: () => setState(() => _showCopyTip = false),
@@ -299,6 +301,8 @@ class _PoetryCardState extends State<PoetryCard> {
Widget _buildTitleSection(bool isDark, Color themeColor) {
final isLoading = widget.sectionLoadingStates?['title'] ?? false;
final baseColor = isDark ? const Color(0xFF3A3A3A) : Colors.grey[300];
final highlightColor = isDark ? const Color(0xFF4A4A4A) : Colors.grey[100];
return SizedBox(
height: 28,
@@ -314,30 +318,12 @@ class _PoetryCardState extends State<PoetryCard> {
isDark: isDark,
),
child: isLoading
? Row(
children: [
SizedBox(
width: 16,
height: 16,
child: CircularProgressIndicator(
strokeWidth: 2,
valueColor: AlwaysStoppedAnimation<Color>(
themeColor,
),
),
),
const SizedBox(width: 8),
Text(
'出处加载中...',
style: TextStyle(
fontSize: 14,
color: isDark
? Colors.grey[400]
: Colors.grey[600],
fontStyle: FontStyle.italic,
),
),
],
? SkeletonContainer(
width: double.infinity,
height: 20,
borderRadius: 4,
baseColor: baseColor,
highlightColor: highlightColor,
)
: Text(
"出处: ${widget.poetryData.url}",
@@ -360,6 +346,8 @@ class _PoetryCardState extends State<PoetryCard> {
Widget _buildNameSection(bool isDark, Color themeColor) {
final isLoading = widget.sectionLoadingStates?['name'] ?? false;
final baseColor = isDark ? const Color(0xFF3A3A3A) : Colors.grey[300];
final highlightColor = isDark ? const Color(0xFF4A4A4A) : Colors.grey[100];
return Container(
width: double.infinity,
@@ -402,23 +390,20 @@ class _PoetryCardState extends State<PoetryCard> {
? Center(
child: Column(
children: [
SizedBox(
width: 20,
height: 20,
child: CircularProgressIndicator(
strokeWidth: 2,
valueColor: AlwaysStoppedAnimation<Color>(
themeColor,
),
),
SkeletonContainer(
width: 120,
height: 28,
borderRadius: 4,
baseColor: baseColor,
highlightColor: highlightColor,
),
const SizedBox(height: 8),
Text(
'诗句加载中...',
style: TextStyle(
fontSize: 14,
color: isDark ? Colors.grey[400] : Colors.grey[600],
),
SkeletonContainer(
width: 80,
height: 16,
borderRadius: 4,
baseColor: baseColor,
highlightColor: highlightColor,
),
],
),
@@ -454,6 +439,8 @@ class _PoetryCardState extends State<PoetryCard> {
Widget _buildKeywordSection(bool isDark, Color themeColor) {
final isLoading = widget.sectionLoadingStates?['keywords'] ?? false;
final baseColor = isDark ? const Color(0xFF3A3A3A) : Colors.grey[300];
final highlightColor = isDark ? const Color(0xFF4A4A4A) : Colors.grey[100];
return Column(
children: [
@@ -461,32 +448,33 @@ class _PoetryCardState extends State<PoetryCard> {
children: [
Expanded(
child: isLoading
? Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SizedBox(
width: 16,
height: 8,
child: CircularProgressIndicator(
strokeWidth: 2,
valueColor: AlwaysStoppedAnimation<Color>(
themeColor,
),
),
),
const SizedBox(width: 4),
Text(
'关键词加载中...',
style: TextStyle(
fontSize: 12,
color: isDark
? Colors.grey[400]
: Colors.grey[600],
),
),
],
),
? Wrap(
spacing: 8,
runSpacing: 8,
alignment: WrapAlignment.center,
children: [
SkeletonContainer(
width: 60,
height: 24,
borderRadius: 12,
baseColor: baseColor,
highlightColor: highlightColor,
),
SkeletonContainer(
width: 80,
height: 24,
borderRadius: 12,
baseColor: baseColor,
highlightColor: highlightColor,
),
SkeletonContainer(
width: 70,
height: 24,
borderRadius: 12,
baseColor: baseColor,
highlightColor: highlightColor,
),
],
)
: Wrap(
spacing: 8,
@@ -602,6 +590,8 @@ class _PoetryCardState extends State<PoetryCard> {
Color themeColor,
) {
final isLoading = widget.sectionLoadingStates?['content'] ?? false;
final baseColor = isDark ? const Color(0xFF3A3A3A) : Colors.grey[300];
final highlightColor = isDark ? const Color(0xFF4A4A4A) : Colors.grey[100];
return Builder(
builder: (context) => GestureDetector(
@@ -622,28 +612,41 @@ class _PoetryCardState extends State<PoetryCard> {
borderRadius: BorderRadius.circular(8),
),
child: isLoading
? Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SizedBox(
width: 16,
height: 16,
child: CircularProgressIndicator(
strokeWidth: 2,
valueColor: AlwaysStoppedAnimation<Color>(themeColor),
),
),
const SizedBox(width: 8),
Text(
'时间加载中...',
style: TextStyle(
fontSize: 14,
color: isDark ? Colors.grey[400] : Colors.grey[600],
),
),
],
),
? Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SkeletonContainer(
width: 80,
height: 18,
borderRadius: 4,
baseColor: baseColor,
highlightColor: highlightColor,
),
const SizedBox(height: 12),
SkeletonContainer(
width: double.infinity,
height: 16,
borderRadius: 4,
baseColor: baseColor,
highlightColor: highlightColor,
),
const SizedBox(height: 8),
SkeletonContainer(
width: double.infinity,
height: 16,
borderRadius: 4,
baseColor: baseColor,
highlightColor: highlightColor,
),
const SizedBox(height: 8),
SkeletonContainer(
width: 150,
height: 16,
borderRadius: 4,
baseColor: baseColor,
highlightColor: highlightColor,
),
],
)
: Column(
crossAxisAlignment: CrossAxisAlignment.start,