diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json new file mode 100644 index 0000000..5472856 --- /dev/null +++ b/.vscode/c_cpp_properties.json @@ -0,0 +1,18 @@ +{ + "configurations": [ + { + "name": "windows-gcc-x64", + "includePath": [ + "${workspaceFolder}/**" + ], + "compilerPath": "C:/mingw64/bin/gcc.exe", + "cStandard": "${default}", + "cppStandard": "${default}", + "intelliSenseMode": "windows-gcc-x64", + "compilerArgs": [ + "" + ] + } + ], + "version": 4 +} \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..b02ad94 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,24 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "C/C++ Runner: Debug Session", + "type": "cppdbg", + "request": "launch", + "args": [], + "stopAtEntry": false, + "externalConsole": true, + "cwd": "e:/Flutter/MusicAPP/MTMusic/linux/flutter", + "program": "e:/Flutter/MusicAPP/MTMusic/linux/flutter/build/Debug/outDebug", + "MIMode": "gdb", + "miDebuggerPath": "gdb", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + } + ] + } + ] +} \ No newline at end of file diff --git a/assets/img/list_collection.png b/assets/img/list_collection.png index 0b6fb02..5f60bba 100644 Binary files a/assets/img/list_collection.png and b/assets/img/list_collection.png differ diff --git a/assets/img/list_collection_un.png b/assets/img/list_collection_un.png new file mode 100644 index 0000000..0b6fb02 Binary files /dev/null and b/assets/img/list_collection_un.png differ diff --git a/assets/img/list_good.png b/assets/img/list_good.png index 99fd85a..5dca998 100644 Binary files a/assets/img/list_good.png and b/assets/img/list_good.png differ diff --git a/assets/img/list_good_act.png b/assets/img/list_good_act.png deleted file mode 100644 index 5dca998..0000000 Binary files a/assets/img/list_good_act.png and /dev/null differ diff --git a/assets/img/list_good_un.png b/assets/img/list_good_un.png new file mode 100644 index 0000000..99fd85a Binary files /dev/null and b/assets/img/list_good_un.png differ diff --git a/lib/api/api_music_likes_list.dart b/lib/api/api_music_likes_list.dart new file mode 100644 index 0000000..1cd6357 --- /dev/null +++ b/lib/api/api_music_likes_list.dart @@ -0,0 +1,32 @@ +import 'package:dio/dio.dart'; +import '../models/getLikeList_bean.dart'; + +const String _LikesListURL = 'http://8.210.250.29:10010/likes/user-like-list'; + +class LikesListApi { + final Dio dio = Dio(); + + /// 获取用户点赞歌曲列表 + Future getUserLikesList({ + required String Authorization, + }) async { + try { + Response response = await dio.get( + _LikesListURL, + options: Options( + headers: { + 'Authorization': Authorization, + 'Content-Type': 'application/json;charset=UTF-8' + } + ), + ); + + print('点赞列表响应数据: ${response.data}'); + return LikeListBean.formMap(response.data); + + } catch (e) { + print('获取点赞列表失败: $e'); + rethrow; + } + } +} \ No newline at end of file diff --git a/lib/models/getLikeList_bean.dart b/lib/models/getLikeList_bean.dart new file mode 100644 index 0000000..3c26c3a --- /dev/null +++ b/lib/models/getLikeList_bean.dart @@ -0,0 +1,51 @@ +class LikeListBean { + int? code; + String? msg; + List? data; + + LikeListBean.formMap(Map map) { + code = map['code']; + msg = map['msg']; + if (map['data'] is! List) return; + + data = (map['data'] as List) + .map((item) => LikeListData._formMap(item)) + .toList(); + } +} + +class LikeListData { + int? id; + String? name; + String? coverPath; + String? musicPath; + String? singerName; + String? uploadUserName; + bool? likes; + bool? collection; + + LikeListData._formMap(Map map) { + id = map['id']; + name = map['name']; + coverPath = map['coverPath']; + musicPath = map['musicPath']; + singerName = map['singerName']; + uploadUserName = map['uploadUserName']; + likes = map['likes']; + collection = map['collection']; + } + + // 转换为Map方法,用于数据存储 + Map toJson() { + return { + 'id': id, + 'name': name, + 'coverPath': coverPath, + 'musicPath': musicPath, + 'singerName': singerName, + 'uploadUserName': uploadUserName, + 'likes': likes, + 'collection': collection, + }; + } +} \ No newline at end of file diff --git a/lib/view/home_view.dart b/lib/view/home_view.dart index 314eaef..c57204b 100644 --- a/lib/view/home_view.dart +++ b/lib/view/home_view.dart @@ -15,6 +15,9 @@ import '../models/MusicsListBean.dart'; import '../models/getMusicList_bean.dart'; import '../models/universal_bean.dart'; import 'music_view.dart'; +import '../api/api_collection.dart'; +import '../api/api_music_likes.dart'; +import '../models/universal_bean.dart'; class HomeView extends StatefulWidget { const HomeView({super.key}); @@ -94,7 +97,7 @@ class _HomeViewState extends State // 如果请求成功且返回的数据不为空 if (bean.code == 200 && bean.data != null) { - // 创建一个临时列表来存储所有异步请求 + // 创���一个临时列表来存储所有异步请求 List> songDetailsFutures = []; // 循环处理每个搜索结果,通过 id 请求详细信息 @@ -458,16 +461,15 @@ class _HomeViewState extends State builder: (context) => MusicView( songList: selectedSongs, initialSongIndex: index, - onSongStatusChanged: - (index, isCollected, isLiked) { + onSongStatusChanged: (index, isCollected, isLiked) { setState(() { - selectedSongs[index].collection = - isCollected; + selectedSongs[index].collection = isCollected; selectedSongs[index].likes = isLiked; downloadManager.updateSongInfo( - selectedSongs[index].id, - isCollected, - isLiked); + selectedSongs[index].id, + isCollected, + isLiked + ); }); }, ), @@ -502,19 +504,20 @@ class _HomeViewState extends State borderRadius: BorderRadius.vertical(top: Radius.circular(30)), ), builder: (context) => StatefulBuilder( - // 使用StatefulBuilder以便动态修改状态 builder: (context, setState) { - bool likesnot = false; // 初始状态,假设未点赞 + // 获取当前歌曲的点赞和收藏状态 + bool likesnot = selectedSongs[index].likes ?? false; + bool collectionsnot = selectedSongs[index].collection ?? false; return Container( height: 150, padding: const EdgeInsets.only(top: 20), child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ + // 加入歌单按钮 Column( children: [ IconButton( @@ -525,6 +528,8 @@ class _HomeViewState extends State const Text("加入歌单"), ], ), + + // 下载按钮 Column( children: [ IconButton( @@ -535,37 +540,122 @@ class _HomeViewState extends State const Text("下载"), ], ), + + // 收藏按钮及功能 Column( children: [ IconButton( - onPressed: () {}, - icon: Image.asset("assets/img/list_collection.png"), - iconSize: 60, + onPressed: () async { + // 1. 立即更新UI状态,提供即时反馈 + setState(() { + collectionsnot = !collectionsnot; + selectedSongs[index].collection = collectionsnot; + }); + + // 2. 调用收藏API + UniversalBean response = await CollectionApiMusic().addCollection( + musicId: selectedSongs[index].id, + Authorization: AppData().currentToken, + ); + + // 3. 处理API响应 + if (response.code != 200) { + // 3.1 如果API调用失败,回滚状态变化 + setState(() { + collectionsnot = !collectionsnot; + selectedSongs[index].collection = collectionsnot; + }); + } else { + // 3.2 API调用成功,更新全局状态管理器 + downloadManager.updateSongInfo( + selectedSongs[index].id, // 当前歌曲ID + collectionsnot, // 新的收藏状态 + selectedSongs[index].likes ?? false // 保持原有的点赞状态 + ); + } + }, + icon: SizedBox( + width: 60, + height: 60, + child: Image.asset( + // 根据收藏状态显示对应图标 + collectionsnot + ? "assets/img/list_collection.png" // 已收藏状态图标 + : "assets/img/list_collection_un.png" // 未收藏状态图标 + ), + ), ), const Text("收藏"), ], ), + + // 点赞按钮及功能 Column( children: [ IconButton( - onPressed: () {}, - icon: Image.asset("assets/img/list_good.png"), - iconSize: 60, + onPressed: () async { + // 1. 立即更新UI状态,提供即时反馈 + setState(() { + likesnot = !likesnot; + selectedSongs[index].likes = likesnot; + }); + + // 2. 调用点赞API + UniversalBean response = await LikesApiMusic().likesMusic( + musicId: selectedSongs[index].id, + Authorization: AppData().currentToken, + ); + + // 3. 处理API响应 + if (response.code != 200) { + // 3.1 如果API调用失败,回滚状态变化 + setState(() { + likesnot = !likesnot; + selectedSongs[index].likes = likesnot; + }); + } else { + // 3.2 API调用成功,更新全局状态管理器 + downloadManager.updateSongInfo( + selectedSongs[index].id, // 当前歌曲ID + selectedSongs[index].collection ?? false, // 保持原有的收藏状态 + likesnot // 新的点赞状态 + ); + } + }, + icon: SizedBox( + width: 60, + height: 60, + child: Image.asset( + // 根据点赞状态显示对应图标 + likesnot + ? "assets/img/list_good.png" // 已点赞状态图标 + : "assets/img/list_good_un.png" // 未点赞状态图标 + ), + ), ), - const Text("点赞") + const Text("点赞"), ], ), + + // 评论按钮 Column( children: [ IconButton( onPressed: () { + // 关闭底部弹出栏 Navigator.pop(context); - // Get.to(() => - // CommentView( - // id:, - // song:, - // singer:, - // )); + // 导航到评论页面 + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => CommentView( + id: selectedSongs[index].id, + song: selectedSongs[index].title, + singer: selectedSongs[index].artist, + cover: selectedSongs[index].artistPic, + ), + ), + ); }, icon: Image.asset("assets/img/list_comment.png"), iconSize: 60, diff --git a/lib/view/rank_view.dart b/lib/view/rank_view.dart index ab19711..3b9265f 100644 --- a/lib/view/rank_view.dart +++ b/lib/view/rank_view.dart @@ -7,6 +7,12 @@ import '../models/getRank_bean.dart'; import '../view_model/rank_view_model.dart'; import 'music_view.dart'; import '../common_widget/Song_widegt.dart'; +import '../api/api_collection.dart'; +import '../api/api_music_likes.dart'; +import '../api/api_music_list.dart'; +import '../models/universal_bean.dart'; +import 'comment_view.dart'; +import '../models/getMusicList_bean.dart'; class RankView extends StatefulWidget { const RankView({super.key}); @@ -321,77 +327,167 @@ class _RankViewState extends State with AutomaticKeepAliveClientMixin Future _bottomSheet(BuildContext context, int index) { return showModalBottomSheet( - context: context, - backgroundColor: Colors.white, - shape: const RoundedRectangleBorder( - borderRadius: BorderRadius.vertical(top: Radius.circular(30)) - ), - builder: (context) => Container( - height: 150, - padding: const EdgeInsets.only(top: 20), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - Column( - children: [ - IconButton( - onPressed: (){}, - icon: Image.asset("assets/img/list_add.png"), - iconSize: 60, - ), - const Text("加入歌单") - ], - ), - Column( - children: [ - IconButton( - onPressed: (){}, - icon: Image.asset("assets/img/list_download.png"), - iconSize: 60, - ), - const Text("下载") - ], - ), - Column( - children: [ - IconButton( - onPressed: (){}, - icon: Image.asset("assets/img/list_collection.png"), - iconSize: 60, - ), - const Text("收藏") - ], - ), - Column( - children: [ - IconButton( - onPressed: (){}, - icon: Image.asset("assets/img/list_good.png"), - iconSize: 60, - ), - const Text("点赞") - ], - ), - Column( - children: [ - IconButton( - onPressed: (){ - Navigator.pop(context); - }, - icon: Image.asset("assets/img/list_comment.png"), - iconSize: 60, - ), - const Text("评论") - ], - ), - ], - ), - ], - ), - ) + context: context, + backgroundColor: Colors.white, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.vertical(top: Radius.circular(30)), + ), + builder: (context) => StatefulBuilder( + builder: (context, setState) { + // 获取当前歌曲的点赞和收藏状态 + bool likesnot = songs[index].likes ?? false; + bool collectionsnot = songs[index].collection ?? false; + + return Container( + height: 150, + padding: const EdgeInsets.only(top: 20), + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Column( + children: [ + IconButton( + onPressed: (){}, + icon: Image.asset("assets/img/list_add.png"), + iconSize: 60, + ), + const Text("加入歌单") + ], + ), + Column( + children: [ + IconButton( + onPressed: (){}, + icon: Image.asset("assets/img/list_download.png"), + iconSize: 60, + ), + const Text("下载") + ], + ), + Column( + children: [ + IconButton( + onPressed: () async { + // 1. 立即更新UI显示,优化用户体验 + setState(() { + collectionsnot = !collectionsnot; + songs[index].collection = collectionsnot; + }); + + // 2. 调用收藏API + UniversalBean response = await CollectionApiMusic().addCollection( + musicId: songs[index].id, + Authorization: AppData().currentToken, + ); + + // 3. 处理API响应 + if (response.code != 200) { + // 如果API调用失败,恢复原状态 + setState(() { + collectionsnot = !collectionsnot; + songs[index].collection = collectionsnot; + }); + } else { + // 4. API调用成功,更新全局状态 + downloadManager.updateSongInfo( + songs[index].id, // 歌曲ID + collectionsnot, // 新的收藏状态 + songs[index].likes ?? false // 保持原有的点赞状态 + ); + } + }, + icon: SizedBox( + width: 60, + height: 60, + child: Image.asset( + // 根据收藏状态显示不同图标 + collectionsnot + ? "assets/img/list_collection.png" // 已收藏图标 + : "assets/img/list_collection_un.png" // 未收藏图标 + ), + ), + ), + const Text("收藏"), + ], + ), + Column( + children: [ + IconButton( + onPressed: () async { + // 1. 立即更新UI显示,优化用户体验 + setState(() { + likesnot = !likesnot; + songs[index].likes = likesnot; + }); + + // 2. 调用点赞API + UniversalBean response = await LikesApiMusic().likesMusic( + musicId: songs[index].id, + Authorization: AppData().currentToken, + ); + + // 3. 处理API响应 + if (response.code != 200) { + // 如果API调用失败,恢复原状态 + setState(() { + likesnot = !likesnot; + songs[index].likes = likesnot; + }); + } else { + // 4. API调用成功,更新全局状态 + downloadManager.updateSongInfo( + songs[index].id, // 歌曲ID + songs[index].collection ?? false, // 保持原有的收藏状态 + likesnot // 新的点赞状态 + ); + } + }, + icon: SizedBox( + width: 60, + height: 60, + child: Image.asset( + // 根据点赞状态显示不同图标 + likesnot + ? "assets/img/list_good.png" // 已点赞图标 + : "assets/img/list_good_un.png" // 未点赞图标 + ), + ), + ), + const Text("点赞"), + ], + ), + Column( + children: [ + IconButton( + onPressed: () { + Navigator.pop(context); + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => CommentView( + id: songs[index].id, + song: songs[index].title, + singer: songs[index].artist, + cover: songs[index].artistPic, + ), + ), + ); + }, + icon: Image.asset("assets/img/list_comment.png"), + iconSize: 60, + ), + const Text("评论") + ], + ), + ], + ), + ], + ), + ); + }, + ), ); } } \ No newline at end of file diff --git a/lib/view/user/my_likes_view.dart b/lib/view/user/my_likes_view.dart new file mode 100644 index 0000000..d3048ff --- /dev/null +++ b/lib/view/user/my_likes_view.dart @@ -0,0 +1,409 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:music_player_miao/api/api_music_likes_list.dart'; +import 'package:music_player_miao/common_widget/app_data.dart'; +import 'package:music_player_miao/models/getLikeList_bean.dart'; +import 'package:music_player_miao/view_model/home_view_model.dart'; +import '../music_view.dart'; +import '../../common_widget/Song_widegt.dart'; +import '../../common/download_manager.dart'; + +/// 我的点赞页面 +class MyLikesView extends StatefulWidget { + const MyLikesView({Key? key}) : super(key: key); + + @override + State createState() => _MyLikesViewState(); +} + +class _MyLikesViewState extends State { + // 存储已点赞歌曲的列表 + List likedSongs = []; + // 是否处于多选模式 + bool _isSelectMode = false; + // 记录每首歌曲是否被选中的状态 + List _selectedItems = []; + // 获取全局状态管理器实例 + final listVM = Get.put(HomeViewModel()); + final downloadManager = Get.put(DownloadManager()); + + @override + void initState() { + super.initState(); + // 页面初始化时获取点赞歌曲列表 + _fetchLikedSongs(); + } + + /// 从服务器获取用户点赞的歌曲列表 + Future _fetchLikedSongs() async { + try { + // 调用API获取点赞列表 + LikeListBean response = await LikesListApi().getUserLikesList( + Authorization: AppData().currentToken, + ); + + // 如果请求成功且数据不为空,更新状态 + if (response.code == 200 && response.data != null) { + setState(() { + likedSongs = response.data!; + // 初始化选中状态列表,默认全部未选中 + _selectedItems = List.generate(likedSongs.length, (index) => false); + }); + } + } catch (error) { + print('Error fetching liked songs: $error'); + } + } + + @override + Widget build(BuildContext context) { + return Container( + // 设置背景图片 + decoration: const BoxDecoration( + image: DecorationImage( + image: AssetImage("assets/img/app_bg.png"), + fit: BoxFit.cover, + ), + ), + child: Scaffold( + backgroundColor: Colors.transparent, + // 自定义应用栏 + appBar: AppBar( + backgroundColor: Colors.transparent, + centerTitle: true, + elevation: 0, + // 根据是否是多选模式显示不同的前导图标 + leading: !_isSelectMode + ? IconButton( // 非多选模式显示返回按钮 + onPressed: () { + Get.back(result: true); + }, + icon: Image.asset( + "assets/img/back.png", + width: 25, + height: 25, + fit: BoxFit.contain, + ), + ) + : TextButton( // 多选模式显示全选按钮 + onPressed: () { + setState(() { + _selectedItems = List.generate(likedSongs.length, (index) => true); + }); + }, + style: TextButton.styleFrom( + foregroundColor: Colors.black, + minimumSize: const Size(50, 40), + padding: const EdgeInsets.symmetric(horizontal: 8), + ), + child: const Text( + '全选', + style: TextStyle(fontSize: 18), + ), + ), + // 根据是否是多选模式显示不同的标题 + title: _isSelectMode + ? Text( + '已选中 ${_selectedItems.where((item) => item).length} 首歌曲', + style: const TextStyle( + color: Colors.black, + ), + ) + : const Text( + '我的点赞', + style: TextStyle(color: Colors.black), + ), + // 多选模式下显示完成按钮 + actions: [ + if (_isSelectMode) + TextButton( + onPressed: () { + setState(() { + _isSelectMode = false; + _selectedItems = List.generate(likedSongs.length, (index) => false); + }); + }, + child: const Text( + "完成", + style: TextStyle(color: Colors.black, fontSize: 18), + )) + ], + ), + // 主体内容 + body: Container( + decoration: const BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.vertical(top: Radius.circular(30)), + ), + child: Column( + children: [ + // 顶部操作栏 + Padding( + padding: const EdgeInsets.symmetric(horizontal: 16.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + // 播放全部按钮组 + Row( + children: [ + IconButton( + onPressed: likedSongs.isEmpty + ? null + : () { + // TODO: 实现播放全部功能 + }, + icon: Image.asset( + "assets/img/button_play.png", + width: 20, + height: 20, + ), + ), + const Text( + '播放全部', + style: TextStyle(fontSize: 16), + ), + const SizedBox(width: 5), + Text( + '(${likedSongs.length})', + style: const TextStyle(fontSize: 16), + ), + ], + ), + // 多选模式切换按钮 + IconButton( + onPressed: likedSongs.isEmpty ? null : () { + setState(() { + _isSelectMode = !_isSelectMode; + if (!_isSelectMode) { + _selectedItems = List.generate(likedSongs.length, (index) => false); + } + }); + }, + icon: Image.asset( + "assets/img/list_op.png", + width: 20, + height: 20, + ), + ), + ], + ), + ), + // 歌曲列表 + Expanded( + child: ListView.builder( + itemCount: likedSongs.length, + padding: EdgeInsets.zero, + itemBuilder: (context, index) { + final song = likedSongs[index]; + return ListTile( + contentPadding: const EdgeInsets.symmetric(horizontal: 16.0), + // 根据是否是多选模式执行不同的点击操作 + onTap: _isSelectMode + ? () { + setState(() { + _selectedItems[index] = !_selectedItems[index]; + }); + } + : () async { + // 创建Song对象列表用于播放 + List songList = likedSongs.map((song) => Song( + id: song.id ?? 0, + title: song.name ?? '未知歌曲', + artist: song.singerName ?? '未知歌手', + artistPic: song.coverPath ?? '', + pic: song.coverPath ?? '', + musicurl: song.musicPath ?? '', + likes: song.likes, + collection: song.collection, + )).toList(); + + // 导航到音乐播放页面 + final result = await Navigator.push( + context, + MaterialPageRoute( + builder: (context) => MusicView( + songList: songList, + initialSongIndex: index, + // 歌曲状态变化回调 + onSongStatusChanged: (index, isCollected, isLiked) { + setState(() { + songList[index].collection = isCollected; + songList[index].likes = isLiked; + downloadManager.updateSongInfo( + songList[index].id, + isCollected, + isLiked, + ); + }); + }, + ), + ), + ); + + // 从播放页面返回时刷新列表 + if (result != null) { + _fetchLikedSongs(); + } + }, + // 歌曲列表项布局 + title: Row( + children: [ + // 多选模式下显示复选框 + if (_isSelectMode) + Checkbox( + value: _selectedItems[index], + onChanged: (value) { + setState(() { + _selectedItems[index] = value!; + }); + }, + shape: const CircleBorder(), + activeColor: const Color(0xff429482), + ), + // 歌曲封面图 + ClipRRect( + borderRadius: BorderRadius.circular(10), + child: Image.network( + song.coverPath ?? '', + width: 60, + height: 60, + fit: BoxFit.cover, + errorBuilder: (context, error, stackTrace) { + return Image.asset( + "assets/img/artist_pic.png", + width: 60, + height: 60, + ); + }, + ), + ), + const SizedBox(width: 12), + // 歌曲信息 + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + song.name ?? '未知歌曲', + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: const TextStyle( + fontSize: 16, + color: Colors.black, + ), + ), + Text( + song.singerName ?? '未知歌手', + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: const TextStyle( + fontSize: 14, + color: Colors.black54, + ), + ), + ], + ), + ), + ], + ), + ); + }, + ), + ), + ], + ), + ), + // 多选模式下显示底部操作栏 + bottomNavigationBar: _isSelectMode + ? BottomAppBar( + height: 140, + child: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + // 底部操作按钮 + Padding( + padding: const EdgeInsets.symmetric(vertical: 8), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + // "添加到"按钮 + Expanded( + child: InkWell( + onTap: () { + // TODO: 实现添加到功能 + }, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SizedBox( + width: 25, + height: 25, + child: Image.asset("assets/img/add.png"), + ), + const SizedBox(width: 4), + const Text("添加到"), + ], + ), + ), + ), + // 分隔线 + Container( + height: 50, + width: 2, + color: const Color(0xff429482), + ), + // "删除"按钮 + Expanded( + child: InkWell( + onTap: () { + // TODO: 实现批量删除功能 + }, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SizedBox( + width: 22, + height: 22, + child: Image.asset("assets/img/delete.png"), + ), + const SizedBox(width: 4), + const Text("删除"), + ], + ), + ), + ), + ], + ), + ), + // 取消按钮 + ElevatedButton( + onPressed: () { + setState(() { + _isSelectMode = false; + _selectedItems = List.generate(likedSongs.length, (index) => false); + }); + }, + style: ElevatedButton.styleFrom( + backgroundColor: const Color(0xff429482), + padding: const EdgeInsets.symmetric(vertical: 14), + tapTargetSize: MaterialTapTargetSize.shrinkWrap, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.zero, + ), + ), + child: const Text( + '取消', + style: TextStyle(color: Colors.black, fontSize: 16), + ), + ), + ], + ), + ), + ) + : null, + ), + ); + } +} \ No newline at end of file diff --git a/lib/view/user/user_view.dart b/lib/view/user/user_view.dart index fac7a56..2a0e0ab 100644 --- a/lib/view/user/user_view.dart +++ b/lib/view/user/user_view.dart @@ -19,6 +19,9 @@ import '../../common/download_manager.dart'; import '../../common/password_manager.dart'; import '../../models/search_bean.dart'; import 'my_work_view.dart'; +import 'my_likes_view.dart'; +import 'package:music_player_miao/api/api_music_likes_list.dart'; // 点赞列表API +import 'package:music_player_miao/models/getLikeList_bean.dart'; // 点赞列表数据模型 class UserView extends StatefulWidget { const UserView({super.key}); @@ -37,6 +40,8 @@ class UserViewState extends State with AutomaticKeepAliveClientMixin { String avatar = AppData().currentAvatar; String username = AppData().currentUsername; final audioController = Get.find(); + int likesCount = 0; + final downloadManager = Get.put(DownloadManager()); final downloadCountController = Get.put(DownloadCountController()); @@ -48,6 +53,8 @@ class UserViewState extends State with AutomaticKeepAliveClientMixin { super.initState(); _fetchSonglistData(); downloadCountController.refreshCount(downloadManager); + downloadCount = downloadManager.completedNumber(); + _fetchLikesCount(); } Future _fetchSonglistData() async { @@ -66,6 +73,22 @@ class UserViewState extends State with AutomaticKeepAliveClientMixin { } } + Future _fetchLikesCount() async { + try { + LikeListBean response = await LikesListApi().getUserLikesList( + Authorization: AppData().currentToken, + ); + + if (response.code == 200 && response.data != null) { + setState(() { + likesCount = response.data!.length; + }); + } + } catch (error) { + print('Error fetching likes count: $error'); + } + } + @override Widget build(BuildContext context) { super.build(context); @@ -129,10 +152,50 @@ class UserViewState extends State with AutomaticKeepAliveClientMixin { padding: const EdgeInsets.only( left: 15, right: 15, top: 20, bottom: 20), - //我的收藏 + //我的收藏,点赞,下载 child: Column( mainAxisAlignment: MainAxisAlignment.start, children: [ + // 我的点赞 + InkWell( + onTap: () async { + final result = await Navigator.push( + context, + MaterialPageRoute( + builder: (context) => const MyLikesView(), + ), + ); + + if (result == true) { + _fetchLikesCount(); + } + }, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Image.asset("assets/img/artist_pic.png"), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const Text( + "我的点赞", + style: TextStyle(fontSize: 20), + ), + Text( + "$likesCount首", + style: const TextStyle(fontSize: 16), + ), + ], + ), + const SizedBox(width: 80), + Image.asset("assets/img/user_next.png") + ], + ), + ), + + const SizedBox(height: 10), + + // 我的收藏 InkWell( onTap: () { Navigator.push( @@ -178,9 +241,9 @@ class UserViewState extends State with AutomaticKeepAliveClientMixin { onTap: () async { final result = await Navigator.push( context, - MaterialPageRoute( + MaterialPageRoute( builder: (context) => const MyDownloadView(), - ), + ), ); if (result == true) {