You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

286 lines
9.4 KiB

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../controllers/agent_controller.dart';
import 'circular_progress_button.dart';
/// 构建音乐项目
Widget buildMusicItem(BuildContext context, int id, String name, String url,
String singer, String image) {
final controller = Get.find<AgentController>(); // 获取控制器
final isDarkMode = Theme.of(context).brightness == Brightness.dark;
Map<String, dynamic> song = {
'id': id,
'url': url,
'title': name,
'artist': singer,
'coverUrl': image,
};
return Container(
padding: const EdgeInsets.all(14),
decoration: BoxDecoration(
color: isDarkMode ? const Color(0xFF1E1E1E) : Colors.white,
borderRadius: BorderRadius.circular(12),
boxShadow: [
BoxShadow(
color: Colors.black.withValues(alpha: isDarkMode ? 0.2 : 0.03),
blurRadius: 3,
spreadRadius: 1,
offset: const Offset(0, 1),
),
],
),
child: Row(
children: [
Container(
width: 50,
height: 50,
decoration: BoxDecoration(
color: Colors.grey[100],
borderRadius: BorderRadius.circular(8),
image: image.isNotEmpty
? DecorationImage(
image: NetworkImage(image),
fit: BoxFit.cover,
)
: null,
),
child: image.isEmpty
? Icon(
Icons.music_note,
size: 18,
color: Theme.of(context).primaryColor,
)
: null,
),
const SizedBox(width: 12),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
name,
style: TextStyle(
fontSize: 13,
fontWeight: FontWeight.w500,
color: Colors.grey[800],
),
overflow: TextOverflow.ellipsis,
),
SizedBox(height: 2),
Text(
singer,
style: TextStyle(
fontSize: 12,
color: Colors.grey[600],
),
overflow: TextOverflow.ellipsis,
),
],
),
),
Obx(() {
final isThisPlaying =
controller.isPlaying.value && controller.currentUrl.value == url;
// 只有当前播放的歌曲才显示进度
final currentProgress =
isThisPlaying ? controller.progress.value : 0.0;
return CircularProgressButton(
isPlaying: isThisPlaying,
progress: currentProgress,
primaryColor: Theme.of(context).primaryColor,
backgroundColor: Colors.grey,
size: 36.0,
strokeWidth: 2.0,
onPlayPause: () async {
try {
if (controller.isPlaying.value) {
if (controller.currentUrl.value == url) {
// 当前歌曲正在播放,暂停它
await controller.musicPause();
} else {
// 其他歌曲正在播放,播放这首歌
await controller.musicPlay(song);
}
} else {
if (controller.currentUrl.value == url) {
// 当前歌曲已暂停,恢复播放
await controller.musicResume();
} else {
// 播放新歌曲
await controller.musicPlay(song);
}
}
} catch (e) {
// 静默处理错误,避免影响用户体验
}
},
onSeek: isThisPlaying
? (seekProgress) {
// 只有当前播放的歌曲才允许跳转
final targetPosition =
(controller.duration.value * seekProgress).round();
controller.seekToPosition(targetPosition);
}
: null,
);
}),
],
),
);
}
/// 构建音乐内容卡片
Widget buildMusicContent(
BuildContext context, List<Map<String, dynamic>> playlist) {
final isDarkMode = Theme.of(context).brightness == Brightness.dark;
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'以下是一些推荐的音乐:',
style: TextStyle(
color:
isDarkMode ? Colors.white.withValues(alpha: 0.9) : Colors.black87,
fontSize: 14,
height: 1.4,
fontWeight: FontWeight.w400,
),
),
const SizedBox(height: 12),
// Container(
// padding: const EdgeInsets.all(12),
// decoration: BoxDecoration(
// color: Colors.white,
// borderRadius: BorderRadius.circular(12),
// boxShadow: [
// BoxShadow(
// color: Colors.black.withOpacity(0.03),
// blurRadius: 3,
// spreadRadius: 1,
// offset: const Offset(0, 1),
// ),
// ],
// ),
// child:
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Icon(
Icons.music_note,
size: 16,
// ignore: deprecated_member_use
color: Theme.of(context).primaryColor.withOpacity(0.7),
),
const SizedBox(width: 6),
Text(
'播放列表'.tr,
style: TextStyle(
fontSize: 13,
fontWeight: FontWeight.w600,
color: Theme.of(context).brightness == Brightness.dark
? Colors.grey[300]
: Colors.grey[700],
),
),
],
),
const SizedBox(height: 10),
// 动态生成音乐条目
...playlist.asMap().entries.take(4).map((entry) {
final index = entry.key;
final item = entry.value;
final id = item["id"] ?? 0;
final name = item["name"] ?? "未知歌曲";
final url = item["url"] ?? "";
final singer = item["sgener"] ?? "未知歌手";
final image = item["image"] ?? "";
return Column(
children: [
buildMusicItem(context, id, name, url, singer, image),
if (index != playlist.length - 1)
Divider(
height: 1,
thickness: 1,
color: Theme.of(context).brightness == Brightness.dark
? Colors.grey[800]
: Colors.grey[100],
),
],
);
}).toList(),
const SizedBox(height: 8),
Center(
child: TextButton(
onPressed: () {
// 跳转到完整歌单页面,传递完整的歌单数据
Get.toNamed('/music/playlist', arguments: playlist);
},
style: TextButton.styleFrom(
minimumSize: Size.zero,
padding:
const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
),
child: Text(
'查看更多推荐',
style: TextStyle(
fontSize: 12,
color: Theme.of(context).primaryColor,
fontWeight: FontWeight.w500,
),
),
),
),
],
),
//),
//const SizedBox(height: 10),
// Row(
// mainAxisSize: MainAxisSize.min,
// children: [
// Expanded(
// child: OutlinedButton.icon(
// onPressed: () {},
// icon: Icon(Icons.play_arrow, size: 16),
// label: Text('播放全部'),
// style: OutlinedButton.styleFrom(
// foregroundColor: Theme.of(context).primaryColor,
// side: BorderSide(
// color: Theme.of(context).primaryColor.withOpacity(0.5)),
// padding: EdgeInsets.symmetric(horizontal: 12, vertical: 4),
// shape: RoundedRectangleBorder(
// borderRadius: BorderRadius.circular(16),
// ),
// textStyle: TextStyle(fontSize: 12),
// ),
// ),
// ),
// SizedBox(width: 8),
// Expanded(
// child: OutlinedButton.icon(
// onPressed: () {},
// icon: Icon(Icons.shuffle, size: 16),
// label: Text('随机播放'),
// style: OutlinedButton.styleFrom(
// foregroundColor: Colors.grey[700],
// side: BorderSide(color: Colors.grey[400]!),
// padding: EdgeInsets.symmetric(horizontal: 12, vertical: 4),
// shape: RoundedRectangleBorder(
// borderRadius: BorderRadius.circular(16),
// ),
// textStyle: TextStyle(fontSize: 12),
// ),
// ),
// ),
// ],
// ),
],
);
}