Skip to content

Commit

Permalink
feat(page): 完善搜索页面
Browse files Browse the repository at this point in the history
  • Loading branch information
d1y committed Mar 31, 2022
1 parent 877a97c commit 9df809c
Show file tree
Hide file tree
Showing 5 changed files with 383 additions and 96 deletions.
54 changes: 54 additions & 0 deletions lib/api/send.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import 'package:dan211/api/parse_utils.dart';
import 'package:dan211/modules/art_detail.dart';
import 'package:dan211/modules/vod_detail.dart';
import 'package:dan211/modules/vod_play.dart' as vodplay;
import 'package:dan211/modules/vod_search.dart';
import 'package:flutter/foundation.dart';
import 'package:html/parser.dart' as parser;
import 'package:dan211/modules/vod_movie.dart';
import 'package:dan211/utils/http.dart';
Expand Down Expand Up @@ -128,6 +130,7 @@ class SendHttp {
return vodplay.MovieVodPlay(
player: VodPlayer(
url: _data.url,

/// 暂时写死。。。
title: '在线播放',
),
Expand All @@ -138,4 +141,55 @@ class SendHttp {
// throw Error();
// }
}

static Future<VodSearchRespData> getSearch(PageQueryStringUtils page) async {
var resp = await XHttp.dio.get(page.toString());
var document = parser.parseFragment(resp.data);
var listNode = document.querySelectorAll("#list-focus li");

List<VodCard> cards = listNode.map((e) {
var playIMG = e.querySelector(".play-img");
var img = playIMG?.querySelector("img");
var title = img?.attributes["alt"]?.trim() ?? "";
var id =
playIMG?.attributes["href"]?.split("/")[2].split(".html")[0] ?? "";
var image = img?.attributes["src"]?.trim() ?? "";
return VodCard(
cover: image,
id: id,
title: title,
);
}).toList();

int total = -1;
int current = -1;
int totalPage = -1;

var pageTip = document.querySelector(".page_tip")?.text.trim() ?? "";
if (pageTip == "共0条数据,当前/页") {
debugPrint("搜索的内容为空");
} else {
// 共1443条数据,当前1/145页
var _pageCache = pageTip.split("条数据");
total = int.tryParse(_pageCache[0].substring(1)) ?? 0;
var _pageNumberCache1 = _pageCache[1].split(",当前")[1];
var _pageNumberCache = _pageNumberCache1.substring(
0,
_pageNumberCache1.length - 1,
);
var _pageNumberTarget = _pageNumberCache.split("/");
current = int.tryParse(_pageNumberTarget[0]) ?? 0;
totalPage = int.tryParse(_pageNumberTarget[1]) ?? 0;
debugPrint("total: $total\n");
debugPrint("current: $current\n");
debugPrint("total_page: $totalPage\n");
}

return VodSearchRespData(
data: cards,
total: total,
current: current,
totalPage: totalPage,
);
}
}
94 changes: 86 additions & 8 deletions lib/app/modules/vod_search/controllers/vod_search_controller.dart
Original file line number Diff line number Diff line change
@@ -1,20 +1,98 @@
import 'package:dan211/api/helper.dart';
import 'package:dan211/api/send.dart';
import 'package:dan211/app/modules/vod_search/views/page_bar.dart';
import 'package:dan211/modules/vod_search.dart';
import 'package:flutter/cupertino.dart';
import 'package:get/get.dart';

class VodSearchController extends GetxController {
//TODO: Implement VodSearchController
/// 搜索内容
VodSearchRespData respData = VodSearchRespData(
current: -1,
total: -1,
totalPage: -1,
data: [],
);

final count = 0.obs;
@override
void onInit() {
super.onInit();
/// 是否加载
bool isLoading = false;

/// 错误栈
String errorStack = "";

/// 一个 `flag`
/// 用来判断是否是第一次操作
bool firstRun = true;

TextEditingController searchController = TextEditingController();

handleSearch(String keyword) {
debugPrint("keyword: $keyword");
pageQuery.data = keyword;
pageQuery.page = 1;
fetchData();
}

PageQueryStringUtils pageQuery = PageQueryStringUtils(
data: '',
);

bool isShowPageBar = false;

/// 是否显示错误页面
///
/// 判断条件
///
/// [respData.data] 内容为空, 并且 [errorStack] 不为空
bool get canShowErrorCase {
return respData.data.isEmpty && errorStack.isNotEmpty;
}

fetchData() async {
if (pageQuery.data.isEmpty) return;
isShowPageBar = true;
isLoading = true;
update();
try {
var data = await SendHttp.getSearch(pageQuery);
if (firstRun) {
firstRun = false;
}
isLoading = false;
respData = data;
errorStack = "";
update();
} catch (e) {
isLoading = false;
errorStack = e.toString();
if (respData.data.isEmpty) {
isShowPageBar = false;
}
update();
}
}

handlePrevAndNext(CupertinoPageBarActionType _type) async {
var _p = pageQuery.page;
if (_type == CupertinoPageBarActionType.prev) {
pageQuery.page--;
} else {
pageQuery.page++;
}
await fetchData();

/// 从缓存中判断若失败了, 则回退操作的 [pageQuery.page]
if (errorStack.isNotEmpty) {
pageQuery.page = _p;
}
}

@override
void onReady() {
super.onReady();
void onInit() {
super.onInit();
// fetchData();
}

@override
void onClose() {}
void increment() => count.value++;
}
145 changes: 95 additions & 50 deletions lib/app/modules/vod_search/views/page_bar.dart
Original file line number Diff line number Diff line change
@@ -1,77 +1,122 @@
import 'package:flutter/cupertino.dart';

enum CupertinoPageBarActionType {
prev,
next,
}

class CupertinoPageBar extends StatelessWidget {
const CupertinoPageBar({
Key? key,
this.isInit = false,
this.total = 1,
this.current = 1,
this.totalPage = 1,
required this.onTap,
this.isLoading = true,
this.loadingText = "搜索中",
this.prevText = "上一页",
this.nextText = "下一页",
}) : super(key: key);

/// 是否初始化操作
///
/// [true] => 只显示 `搜索中` 文本
///
/// [false] => 显示操作按钮 `上一页/下一页/跳转`
final bool isInit;
final bool isLoading;

final String loadingText;

final String prevText;

final String nextText;

final int total;

final int current;

final int totalPage;

final ValueChanged<CupertinoPageBarActionType> onTap;

bool get _isPrev {
return current <= 1;
return current > 1;
}

bool get _isNext {
return true;
return current < totalPage;
}

bool get _canShowToolBar => total == -1;

MainAxisAlignment get _mainAxisAlignment {
if (_canShowToolBar) return MainAxisAlignment.center;
return MainAxisAlignment.spaceBetween;
}

double get _opacity {
return isLoading ? 1.0 : 0.0;
}

@override
Widget build(BuildContext context) {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
children: [
CupertinoButton(
padding: EdgeInsets.zero,
child: Row(
children: [
Icon(CupertinoIcons.back),
Text("上一页"),
],
),
onPressed: () {},
),
Padding(
padding: const EdgeInsets.symmetric(
horizontal: 12,
),
child: Text("1/24"),
),
CupertinoButton(
padding: EdgeInsets.zero,
child: Row(
children: [
Text("下一页"),
Icon(CupertinoIcons.right_chevron),
],
),
onPressed: () {},
return Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
mainAxisAlignment: _mainAxisAlignment,
children: [
Builder(builder: (context) {
if (_canShowToolBar) return const SizedBox.shrink();
return Row(
children: [
CupertinoButton(
padding: EdgeInsets.zero,
child: Row(
children: [
const Icon(CupertinoIcons.back),
Text(prevText),
],
),
onPressed: !_isPrev ? null : () {
onTap(CupertinoPageBarActionType.prev);
},
),
Padding(
padding: const EdgeInsets.symmetric(
horizontal: 12,
),
child: Text("$current/$totalPage"),
),
CupertinoButton(
padding: EdgeInsets.zero,
child: Row(
children: [
Text(nextText),
const Icon(CupertinoIcons.right_chevron),
],
),
onPressed: !_isNext ? null : () {
onTap(CupertinoPageBarActionType.next);
},
),
],
);
}),
AnimatedOpacity(
opacity: _opacity,
duration: const Duration(
milliseconds: 420,
),
],
),
Row(
children: [
CupertinoActivityIndicator(),
SizedBox(
width: 6,
child: Row(
children: [
const CupertinoActivityIndicator(),
const SizedBox(
width: 6,
),
Text(loadingText),
const SizedBox(
width: 3,
),
],
),
Text("搜索中"),
],
)
],
)
],
),
);
}
}
Loading

0 comments on commit 9df809c

Please sign in to comment.