feat & fix: 修复注册后自动登录 Bug, 优化推荐页面, 对接搜索接口

liu
Spark 8 months ago
parent 5a8255ca6b
commit 7af268a24e

File diff suppressed because one or more lines are too long

@ -53,7 +53,7 @@ class LogoutApiClient {
///
class SetupApiClient{
final Dio dio = Dio();
Future<UniversalBean> register({
Future<LoginBean> register({
required String email,
required String password,
required String username,
@ -70,7 +70,7 @@ class SetupApiClient{
options: Options(headers:{'Content-Type':'application/json;charset=UTF-8'})
);
print(response.data);
return UniversalBean.formMap(response.data);
return LoginBean.formMap(response.data);
}
Future<UniversalBean> verification({required String email,}) async {

@ -3,8 +3,8 @@
import 'package:dio/dio.dart';
import 'package:music_player_miao/models/universal_bean.dart';
import '../models/MusicsListBean.dart';
import '../models/getComment_bean.dart';
import '../models/search_bean.dart';
const String _SearchURL = 'http://8.210.250.29:10010/musics/search';
const String _postComment = 'http://8.210.250.29:10010/comments';
@ -12,7 +12,7 @@ const String _postComment = 'http://8.210.250.29:10010/comments';
class SearchMusic {
final Dio dio = Dio();
Future<SearchBean> search({
Future<MusicsListBean> search({
required String keyword,
required String Authorization,
}) async {
@ -25,7 +25,7 @@ class SearchMusic {
}),
);
print(response.data);
return SearchBean.formMap(response.data);
return MusicsListBean.fromMap(response.data);
}
}

@ -12,6 +12,7 @@ import '../../api/api_client.dart';
import '../../common/password_manager.dart';
import '../../common_widget/app_data.dart';
import '../../models/getInfo_bean.dart';
import '../../models/login_bean.dart';
import '../../models/universal_bean.dart';
import '../../widget/my_text_field.dart';
@ -317,7 +318,7 @@ class _SignUpViewState extends State<SignUpView> {
passwordController.text.isNotEmpty &&
confirmPSWController.text.isNotEmpty &&
confirmController.text.isNotEmpty) {
UniversalBean bean = await SetupApiClient().register(
LoginBean bean = await SetupApiClient().register(
email: emailController.text,
password: passwordController.text,
username: nameController.text,

@ -284,25 +284,6 @@ class _HomeViewState extends State<HomeView>
color: Colors.grey[100],
child: const Icon(Icons.music_note, size: 30),
),
// loadingBuilder: (context, child, loadingProgress) {
// if (loadingProgress == null) return child;
// return Container(
// width: 60,
// height: 60,
// color: Colors.grey[100],
// child: Center(
// child: CircularProgressIndicator(
// strokeWidth: 2,
// valueColor: const AlwaysStoppedAnimation<Color>(
// Color(0xff429482)),
// value: loadingProgress.expectedTotalBytes != null
// ? loadingProgress.cumulativeBytesLoaded /
// loadingProgress.expectedTotalBytes!
// : null,
// ),
// ),
// );
// },
),
),
),
@ -326,7 +307,7 @@ class _HomeViewState extends State<HomeView>
),
trailing: Padding(
padding: const EdgeInsets.only(right: 16),
child: InkWell(
child: GestureDetector(
onTap: () async {
setState(() {
selectedSongs[index].likes = !selectedSongs[index].likes!;

@ -1,3 +1,7 @@
///
///
///
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:get/get.dart';

@ -1,10 +1,13 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../api/api_music_likes.dart';
import '../api/api_music_list.dart';
import '../api/api_music_return.dart';
import '../common/download_manager.dart';
import '../common_widget/Song_widegt.dart';
import '../common_widget/app_data.dart';
import '../models/MusicsListBean.dart';
import '../models/universal_bean.dart';
import 'main_tab_view/main_tab_view.dart';
import 'music_view.dart';
@ -18,12 +21,23 @@ class SearchView extends StatefulWidget {
class _SearchViewState extends State<SearchView> {
final List<Song> songs = [];
final TextEditingController _searchController = TextEditingController();
final FocusNode _searchFocusNode = FocusNode(); //
final downloadManager = Get.put(DownloadManager());
bool isSearching = false;
String lastSearchQuery = '';
@override
void initState() {
super.initState();
_loadRecommendData();
_searchController.addListener(_onSearchChanged);
}
@override
void dispose() {
_searchController.dispose();
_searchFocusNode.dispose();
super.dispose();
}
void _loadRecommendData() async {
@ -49,6 +63,72 @@ class _SearchViewState extends State<SearchView> {
}
}
//
void _onSearchChanged() {
final query = _searchController.text.trim();
if (query.isEmpty) {
// ,
if (lastSearchQuery.isNotEmpty) {
setState(() {
isSearching = false;
lastSearchQuery = '';
});
_loadRecommendData();
}
} else if (query != lastSearchQuery) {
//
setState(() {
isSearching = true;
lastSearchQuery = query;
});
_debounceSearch(query);
}
}
//
Future<void> _debounceSearch(String query) async {
// 300ms,
await Future.delayed(const Duration(milliseconds: 300));
if (query == _searchController.text.trim()) {
_searchSongs(query);
}
}
// API
Future<void> _searchSongs(String keyword) async {
try {
final response = await SearchMusic().search(
keyword: keyword,
Authorization: AppData().currentToken,
);
if (response.code == 200 && response.data != null) {
setState(() {
songs.clear();
for (var data in response.data!) {
songs.add(Song(
artistPic: data.coverPath ?? 'https://api.aspark.cc/image/1/6759856d288fd.jpg',
title: data.name!,
artist: data.singerName!,
musicurl: data.musicPath,
pic: data.coverPath ?? 'https://api.aspark.cc/image/1/6759856d288fd.jpg',
id: data.id!,
likes: data.likeOrNot,
collection: data.collectOrNot,
mid: data.mid,
));
}
});
}
} catch (error) {
print('Search error: $error');
//
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('搜索失败,请稍后重试')),
);
}
}
@override
Widget build(BuildContext context) {
return Container(
@ -60,18 +140,35 @@ class _SearchViewState extends State<SearchView> {
),
child: Scaffold(
backgroundColor: Colors.transparent,
body: Column(
children: [
const SizedBox(height: 60),
_buildSearchBar(),
const SizedBox(height: 20),
_buildPlayAllButton(),
Expanded(
child: _buildSongsList(),
),
MiniPlayer(),
const SizedBox(height: 10),
],
body: GestureDetector(
onTap: () {
if (_searchFocusNode.hasFocus) {
_searchFocusNode.unfocus();
}
},
behavior: HitTestBehavior.translucent, //
child: Column(
children: [
const SizedBox(height: 60),
_buildSearchBar(),
const SizedBox(height: 10),
_buildPlayAllButton(),
Expanded(
child: NotificationListener<ScrollNotification>(
onNotification: (scrollNotification) {
if (scrollNotification is ScrollStartNotification) {
if (_searchFocusNode.hasFocus) {
_searchFocusNode.unfocus();
}
}
return true;
},
child: _buildSongsList(),
),
),
MiniPlayer(),
],
),
),
),
);
@ -95,14 +192,29 @@ class _SearchViewState extends State<SearchView> {
),
child: TextField(
controller: _searchController,
focusNode: _searchFocusNode,
decoration: InputDecoration(
border: InputBorder.none,
hintText: '搜索你想找的音乐',
hintStyle: TextStyle(color: Colors.grey.shade400),
prefixIcon: Icon(Icons.search, color: Colors.grey.shade400),
suffixIcon: _searchController.text.isNotEmpty
? IconButton(
icon: Icon(Icons.clear, color: Colors.grey.shade400),
onPressed: () {
_searchController.clear();
_searchFocusNode.unfocus();
},
)
: null,
contentPadding:
const EdgeInsets.symmetric(horizontal: 20, vertical: 15),
),
onSubmitted: (value) {
if (value.isNotEmpty) {
_searchSongs(value);
}
},
),
),
);
@ -233,14 +345,43 @@ class _SearchViewState extends State<SearchView> {
],
),
),
IconButton(
icon: Icon(
Icons.more_vert,
color: Colors.grey.shade400,
Padding(
padding: const EdgeInsets.only(right: 16),
child: InkWell(
onTap: () async {
setState(() {
songs[index].likes = !songs[index].likes!;
});
UniversalBean response = await LikesApiMusic()
.likesMusic(
musicId: song.id,
Authorization: AppData().currentToken);
if (response.code != 200) {
setState(() {
songs[index].likes = !songs[index].likes!;
});
}
},
child: song.likes!
? Image.asset(
'assets/img/like.png',
width: 24,
height: 24,
)
: ColorFiltered(
colorFilter: ColorFilter.mode(
Colors.grey[700]!,
BlendMode.srcIn,
),
child: Image.asset(
'assets/img/unlike.png',
width: 24,
height: 24,
),
),
),
onPressed: () {
//
},
),
],
),

@ -280,28 +280,8 @@ class _SongRecommendationViewState extends State<SongRecommendationView> with Ti
Widget build(BuildContext context) {
final screenSize = MediaQuery.of(context).size;
final safeAreaPadding = MediaQuery.of(context).padding;
final refreshButtonPosition = Offset(screenSize.width / 2, screenSize.height / 2);
if (isLoading) {
return const Center(child: CircularProgressIndicator());
}
if (songs.isEmpty) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text('暂无推荐歌曲'),
ElevatedButton(
onPressed: _loadRecommendedSongs,
child: const Text('重试'),
),
],
),
);
}
return Container(
decoration: const BoxDecoration(
image: DecorationImage(
@ -312,7 +292,7 @@ class _SongRecommendationViewState extends State<SongRecommendationView> with Ti
child: Scaffold(
backgroundColor: Colors.transparent,
body: SafeArea(
child: Stack( // 使Stack
child: Stack(
children: [
LayoutBuilder(
builder: (context, constraints) {

Loading…
Cancel
Save