diff --git a/lib/api/api_music_rank.dart b/lib/api/api_music_rank.dart new file mode 100644 index 0000000..02c7fc7 --- /dev/null +++ b/lib/api/api_music_rank.dart @@ -0,0 +1,17 @@ +import 'package:dio/dio.dart'; + +import '../models/getRank_bean.dart'; + +const String _getRank = 'http://flyingpig.fun:10010/musics/rank-list'; +///排行榜 +class GetRank { + final Dio dio = Dio(); + + Future getRank() async { + Response response = await dio.get( + _getRank, + ); + print(response.data); + return RankBean.formMap(response.data); + } +} \ No newline at end of file diff --git a/lib/api/api_music_return.dart b/lib/api/api_music_return.dart index 1146b61..ad2ffcf 100644 --- a/lib/api/api_music_return.dart +++ b/lib/api/api_music_return.dart @@ -4,7 +4,6 @@ import 'package:dio/dio.dart'; import 'package:music_player_miao/models/universal_bean.dart'; import '../models/getComment_bean.dart'; -import '../models/getInfo_bean.dart'; import '../models/search_bean.dart'; const String _SearchURL = 'http://flyingpig.fun:10010/musics/search'; diff --git a/lib/models/getRank_bean.dart b/lib/models/getRank_bean.dart new file mode 100644 index 0000000..574d5d1 --- /dev/null +++ b/lib/models/getRank_bean.dart @@ -0,0 +1,36 @@ +class RankBean { + int? code; + String? msg; + List? data; + + RankBean.formMap(Map map) { + code = map['code']; + msg = map['msg']; + if (map['data'] == null) return; + + List? dataList = map['data']; + if (dataList == null) return; + + data = dataList + .map((item) => DataBean._formMap(item)) + .toList(); + } +} + +class DataBean { + int? id; + String? singerName; + String? coverPath; + String? musicPath; + String? name; + + + + DataBean._formMap(Map map) { + id = map['id']; + singerName = map['singerName']; + coverPath = map['coverPath']; + musicPath = map['musicPath']; + name = map['name']; + } +} diff --git a/lib/view/home_view.dart b/lib/view/home_view.dart index 0728ab3..51ad755 100644 --- a/lib/view/home_view.dart +++ b/lib/view/home_view.dart @@ -30,20 +30,20 @@ class _HomeViewState extends State { final List songs = [ Song( artistPic: 'assets/img/music_artist.png', - title: '背对背拥抱1', - artist: '林俊杰 1', + title: 'Chuck', + artist: 'MAMAMOO', musicurl: 'audio/MAMAMOO.mp3', pic: 'assets/img/artist_pic.png'), Song( artistPic: 'assets/img/music_artist.png', - title: '背对背拥抱2', - artist: '林俊杰 2', + title: 'FLOWER', + artist: 'Jisoo', musicurl: 'audio/FLOWER.mp3', pic: 'assets/img/artist_pic.png'), Song( artistPic: 'assets/img/music_artist.png', - title: '背对背拥抱3', - artist: '林俊杰 3', + title: 'All eyes on me', + artist: 'Jisoo', musicurl: 'audio/All.mp3', pic: 'assets/img/artist_pic.png'), ]; diff --git a/lib/view/rank_view.dart b/lib/view/rank_view.dart index afe5a8b..505351c 100644 --- a/lib/view/rank_view.dart +++ b/lib/view/rank_view.dart @@ -1,6 +1,8 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; +import '../api/api_music_rank.dart'; import '../common_widget/rank_song_row.dart'; +import '../models/getRank_bean.dart'; import '../view_model/rank_view_model.dart'; class RankView extends StatefulWidget { @@ -12,6 +14,25 @@ class RankView extends StatefulWidget { class _RankViewState extends State { final rankVM = Get.put(RankViewModel()); + List rankNames = []; + List rankSingerName = []; + List rankCoverPath = []; + List rankMusicPath = []; + + void initState() { + super.initState(); + _fetchSonglistData(); + } + + Future _fetchSonglistData() async { + RankBean bean2 = await GetRank().getRank(); + setState(() { + rankNames = bean2.data!.map((data) => data.name!).toList(); + rankSingerName = bean2.data!.map((data) => data.singerName!).toList(); + rankCoverPath = bean2.data!.map((data) => data.coverPath!).toList(); + rankMusicPath = bean2.data!.map((data) => data.musicPath!).toList(); + }); + } @override Widget build(BuildContext context) { @@ -26,104 +47,303 @@ class _RankViewState extends State { resizeToAvoidBottomInset: false, backgroundColor: Colors.transparent, body: Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const SizedBox( + height: 40, + ), + //头部 + const Center( + child: Column( + children: [ + Text( + '喵听排行榜', + style: TextStyle(fontSize: 22, fontWeight: FontWeight.w400), + ), + SizedBox( + height: 10, + ), + Text( + 'Top50', + style: TextStyle( + color: Color(0xffCE0000), + fontSize: 40, + fontWeight: FontWeight.w500), + ), + SizedBox( + height: 10, + ), + Text( + '2023/12/12更新 1期', + style: TextStyle(fontSize: 16, fontWeight: FontWeight.w500), + ), + ], + ), + ), + const SizedBox( + height: 10, + ), + Container( + decoration: const BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.only( + topLeft: Radius.circular(20), + topRight: Radius.circular(20), + ), + ), + child: Row( + children: [ + IconButton( + onPressed: () {}, + icon: Image.asset( + "assets/img/button_play.png", + width: 20, + height: 20, + ), + ), + const Text( + '播放全部', + style: TextStyle(fontSize: 16), + ), + const SizedBox( + width: 5, + ), + const Text( + '50', + style: TextStyle(fontSize: 16), + ), + ], + ), + ), + Expanded( + child: SingleChildScrollView( + physics: const BouncingScrollPhysics(), + child: Container( + color: Colors.white, + child: Column( + children: [ + ListView.builder( + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + padding: const EdgeInsets.symmetric( + vertical: 5, horizontal: 10), + itemCount: rankNames.length, + itemBuilder: (context, index) { + int rankNum = index + 1; + return ListTile( + title: Column( + children: [ + Row( + children: [ + Row( + mainAxisAlignment: + MainAxisAlignment.center, + children: [ + SizedBox( + width: 25, + child: RichText( + text: TextSpan( + text: rankNum.toString(), + style: TextStyle( + fontSize: 20, + fontWeight: FontWeight.w700, + color: Color(0xffCE0000), + ), + ), + ), + ), + const SizedBox( + width: 10, + ), + ClipRRect( + borderRadius: + BorderRadius.circular(10), + child: Image.network( + rankCoverPath[index], + width: 60, + height: 60, + fit: BoxFit.cover, + errorBuilder: + (context, error, stackTrace) { + // 如果加载失败,返回一个默认图片 + return Image.asset( + 'assets/img/app_logo.png', + // 你的默认图片路径 + width: 60, + height: 60, + fit: BoxFit.cover, + ); + }, + ), + ), + const SizedBox( + width: 20, + ), + SizedBox( + width: 170, + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Text( + rankNames[index], + maxLines: 1, + style: TextStyle( + color: Colors.black, + fontSize: 16, + fontWeight: + FontWeight.w400), + ), + Text( + rankSingerName[index], + maxLines: 1, + style: TextStyle( + color: Colors.black, + fontSize: 14), + ) + ], + ), + ), + const SizedBox( + width: 20, + ), + ], + ), + IconButton( + onPressed: () { + _bottomSheet(context); + }, + icon: Image.asset( + "assets/img/More.png", + width: 25, + height: 25, + ), + ), + const SizedBox( + height: 20, + ) + ], + ), + const SizedBox( + height: 10, + ) + ], + )); + }), + ], + ), + ), + ), + ) + ], + ), + ), + ); + } + Future _bottomSheet(BuildContext context){ + return showModalBottomSheet( + context: context, + backgroundColor: Colors.white, + shape: const RoundedRectangleBorder(borderRadius: BorderRadius.vertical(top: Radius.circular(30))), + builder: (context) =>Container( + height: 210, + padding: const EdgeInsets.only(top: 20), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, children: [ - const SizedBox(height: 40,), - //头部 - const Center( - child: Column( - children: [ - Text( - '喵听排行榜', - style: TextStyle( - fontSize: 22, - fontWeight: FontWeight.w400 + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Column( + children: [ + IconButton( + onPressed: (){}, + icon: Image.asset("assets/img/list_add.png"), + iconSize: 60, ), - ), - SizedBox(height: 10,), - Text( - 'Top50', - style: TextStyle( - color: Color(0xffCE0000), - fontSize: 40, - fontWeight: FontWeight.w500 + Text("加入歌单") + ], + ), + Column( + children: [ + IconButton( + onPressed: (){}, + icon: Image.asset("assets/img/list_download.png"), + iconSize: 60, ), - ), - SizedBox(height: 10,), - Text( - '2023/12/12更新 1期', - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w500 + Text("下载") + ], + ), + Column( + children: [ + IconButton( + onPressed: (){}, + icon: Image.asset("assets/img/list_collection.png"), + iconSize: 60, ), - ), - ], - ), + Text("收藏") + ], + ), + Column( + children: [ + IconButton( + onPressed: (){}, + icon: Image.asset("assets/img/list_good.png"), + iconSize: 60, + ), + Text("点赞") + ], + ), + Column( + children: [ + IconButton( + onPressed: (){}, + icon: Image.asset("assets/img/list_comment.png"), + iconSize: 60, + ), + Text("评论") + ], + ), + ], ), const SizedBox(height: 10,), - Container( - decoration: const BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.only( - topLeft: Radius.circular(20), - topRight: Radius.circular(20), + ElevatedButton( + onPressed: () { + // Get.to(()=>const MainTabView()); + }, + child: Text( + "查看详情页", + style: const TextStyle(color:Colors.black,fontSize: 18), + ), + style: ElevatedButton.styleFrom( + backgroundColor: const Color(0xffE6F4F1), + padding: const EdgeInsets.symmetric(vertical: 8), + tapTargetSize: MaterialTapTargetSize.shrinkWrap, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.zero, ), ), - child: Row( - children: [ - IconButton( - onPressed: (){}, - icon: Image.asset( - "assets/img/button_play.png", - width: 20, - height: 20, - ), - ), - const Text( - '播放全部', - style: TextStyle( - fontSize: 16 - ), - ), - const SizedBox(width: 5,), - const Text( - '50', - style: TextStyle( - fontSize: 16 - ), - ), - ], - ), + + ), + ElevatedButton( + onPressed: () =>Navigator.pop(context), + child: Text( + "取消", + style: const TextStyle(color:Colors.black,fontSize: 18), + ), + style: ElevatedButton.styleFrom( + backgroundColor: const Color(0xff429482), + padding: const EdgeInsets.symmetric(vertical: 8), + tapTargetSize: MaterialTapTargetSize.shrinkWrap, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.zero, + ), + ), + ), - Expanded( - child: SingleChildScrollView( - physics: const BouncingScrollPhysics(), - child: Container( - color: Colors.white, - child: Column( - children: [ - ListView.builder( - physics: const NeverScrollableScrollPhysics(), - shrinkWrap: true, - padding: const EdgeInsets.symmetric(vertical: 5,horizontal: 15), - itemCount: rankVM.rankDetailArr.length, - itemBuilder: (context, index) { - var sObj = rankVM.rankDetailArr[index]; - return RankSongsRow( - sObj: sObj, - onPressed: () {}, - onPressedPlay: () {}, - rank: sObj["rank"], - ); - }), - ], - ), - ), - ), - ) ], ), - ), + ) ); } diff --git a/lib/view/release_view.dart b/lib/view/release_view.dart index 7cd0d2d..27d1f8f 100644 --- a/lib/view/release_view.dart +++ b/lib/view/release_view.dart @@ -88,9 +88,9 @@ class _ReleaseViewState extends State { const SizedBox(height: 30,), ], ), - ///上传列表 + ///音乐列表 const Text( - "上传列表", + "音乐列表", style: TextStyle( fontSize: 20 ), @@ -171,25 +171,6 @@ class _ReleaseViewState extends State { ), ), ), - ///固定的提交审核 - Center( - child: ElevatedButton( - onPressed: _submitForReview, - child: const Text( - "提交审核", - style: TextStyle(color: Colors.white, fontSize: 18), - ), - style: ButtonStyle( - backgroundColor: MaterialStateProperty.all(const Color(0xff429482)), - shape: MaterialStateProperty.all( - RoundedRectangleBorder( - borderRadius: BorderRadius.circular(30.0), - ), - ), - fixedSize: MaterialStateProperty.all(const Size(120.0, 50.0)), - ), - ), - ), ], ), ), @@ -303,10 +284,6 @@ class _ReleaseViewState extends State { ), ], ), - - - // Display selected cover image - // Placeholder for the image const SizedBox(height: 20), const Text("歌名"), TextFieldColor( @@ -478,17 +455,47 @@ class _ReleaseViewState extends State { songName: enteredSongName, artistName: enteredArtistName, )); - - print('Selected cover image: ${selectedCoverImage?.path}'); - print('Entered Song Name: $enteredSongName'); - print('Entered Artist Name: $enteredArtistName'); - - Navigator.pop(context); // Close the dialog after saving - } else { - // Handle the case where either selectedCoverImage or selectedMp3File is null - print('Error: Cover image or MP3 file is null.'); - } - }, + UniversalBean bean = await ReleaseApi().release( + coverFile:selectedCoverImage, + musicFile: selectedMp3File!, + Authorization: AppData().currentToken, + singerName: enteredArtistName, + name: enteredSongName, + introduce: '0'); + Navigator.pop(context); + showDialog( + context: context, + builder: (context) => AlertDialog( + shape: RoundedRectangleBorder( + borderRadius:BorderRadius.circular(10), + ), + title: Image.asset("assets/img/correct.png",width: 47,height: 46,), + content: const Column( + mainAxisSize: MainAxisSize.min, + children: [ + Text('提交审核成功'), + Text('审核通过后自动发布'), + ], + ), + actions: [ + TextButton( + onPressed: () { + Navigator.pop(context); + }, + style: TextButton.styleFrom( + backgroundColor: const Color(0xff429482), + minimumSize: const Size(double.infinity, 50), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(5.0), // Adjust the radius as needed + ), + ), + child: const Text('确认',style: TextStyle(color: Colors.white),), + ), + ], + ), + ); + } + }, style: TextButton.styleFrom( backgroundColor: const Color(0xff429482), @@ -535,83 +542,6 @@ class _ReleaseViewState extends State { return File(''); } - ///提交 - void _submitForReview() { - if (songInfoList.isNotEmpty) { - showDialog( - context: context, - builder: (context) => AlertDialog( - shape: RoundedRectangleBorder( - borderRadius:BorderRadius.circular(10), - ), - title: Image.asset("assets/img/correct.png",width: 47,height: 46,), - content: const Column( - mainAxisSize: MainAxisSize.min, - children: [ - Text('提交审核成功'), - Text('审核通过后自动发布'), - ], - ), - actions: [ - TextButton( - onPressed: () async{ - UniversalBean bean = await ReleaseApi().release( - coverFile:coverImages[0], - musicFile: selectedMp3File!, - Authorization: AppData().currentToken, - singerName: songInfoList[0].artistName, - name: songInfoList[0].songName, - introduce: '0'); - if (bean.code==200) { - setState((){ - coverImages.clear(); - songInfoList.clear(); - }); - } - Navigator.pop(context); - // Close the dialog - }, - style: TextButton.styleFrom( - backgroundColor: const Color(0xff429482), - minimumSize: const Size(double.infinity, 50), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(5.0), // Adjust the radius as needed - ), - ), - child: const Text('确认',style: TextStyle(color: Colors.white),), - ), - ], - ), - ); - } else { - // Display an error message if the list is empty - showDialog( - context: context, - builder: (context) => AlertDialog( - shape: RoundedRectangleBorder( - borderRadius:BorderRadius.circular(10), - ), - title: Image.asset("assets/img/warning.png",width: 47,height: 46,), - content: const Text('上传列表为空,无法提交审核。',textAlign: TextAlign.center,), - actions: [ - TextButton( - onPressed: () { - Navigator.pop(context); // Close the dialog - }, - style: TextButton.styleFrom( - backgroundColor: const Color(0xff429482), - minimumSize: const Size(double.infinity, 50), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(5.0), // Adjust the radius as needed - ), - ), - child: const Text('确定',style: TextStyle(color: Colors.white),), - ), - ], - ), - ); - } - } void _confirmDelete(BuildContext context, int index) { showDialog( context: context,