mod: 个人主页
This commit is contained in:
47
lib/pages/member_seasons/controller.dart
Normal file
47
lib/pages/member_seasons/controller.dart
Normal file
@ -0,0 +1,47 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:pilipala/http/member.dart';
|
||||
import 'package:pilipala/models/member/seasons.dart';
|
||||
|
||||
class MemberSeasonsController extends GetxController {
|
||||
final ScrollController scrollController = ScrollController();
|
||||
late int mid;
|
||||
late int seasonId;
|
||||
int pn = 1;
|
||||
int ps = 30;
|
||||
int count = 0;
|
||||
RxList<MemberArchiveItem> seasonsList = <MemberArchiveItem>[].obs;
|
||||
late Map page;
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
mid = int.parse(Get.parameters['mid']!);
|
||||
seasonId = int.parse(Get.parameters['seasonId']!);
|
||||
}
|
||||
|
||||
// 获取专栏详情
|
||||
Future getSeasonDetail(type) async {
|
||||
if (type == 'onRefresh') {
|
||||
pn = 1;
|
||||
}
|
||||
var res = await MemberHttp.getSeasonDetail(
|
||||
mid: mid,
|
||||
seasonId: seasonId,
|
||||
pn: pn,
|
||||
ps: ps,
|
||||
sortReverse: false,
|
||||
);
|
||||
if (res['status']) {
|
||||
seasonsList.addAll(res['data'].archives);
|
||||
page = res['data'].page;
|
||||
pn += 1;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// 上拉加载
|
||||
Future onLoad() async {
|
||||
getSeasonDetail('onLoad');
|
||||
}
|
||||
}
|
||||
4
lib/pages/member_seasons/index.dart
Normal file
4
lib/pages/member_seasons/index.dart
Normal file
@ -0,0 +1,4 @@
|
||||
library member_seasons;
|
||||
|
||||
export 'controller.dart';
|
||||
export 'view.dart';
|
||||
103
lib/pages/member_seasons/view.dart
Normal file
103
lib/pages/member_seasons/view.dart
Normal file
@ -0,0 +1,103 @@
|
||||
import 'package:easy_debounce/easy_throttle.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:pilipala/common/constants.dart';
|
||||
import 'controller.dart';
|
||||
import 'widgets/item.dart';
|
||||
|
||||
class MemberSeasonsPage extends StatefulWidget {
|
||||
const MemberSeasonsPage({super.key});
|
||||
|
||||
@override
|
||||
State<MemberSeasonsPage> createState() => _MemberSeasonsPageState();
|
||||
}
|
||||
|
||||
class _MemberSeasonsPageState extends State<MemberSeasonsPage> {
|
||||
final MemberSeasonsController _memberSeasonsController =
|
||||
Get.put(MemberSeasonsController());
|
||||
late Future _futureBuilderFuture;
|
||||
late ScrollController scrollController;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_futureBuilderFuture =
|
||||
_memberSeasonsController.getSeasonDetail('onRefresh');
|
||||
scrollController = _memberSeasonsController.scrollController;
|
||||
scrollController.addListener(
|
||||
() {
|
||||
if (scrollController.position.pixels >=
|
||||
scrollController.position.maxScrollExtent - 200) {
|
||||
EasyThrottle.throttle(
|
||||
'member_archives', const Duration(milliseconds: 500), () {
|
||||
_memberSeasonsController.onLoad();
|
||||
});
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('他的专栏'),
|
||||
),
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
left: StyleString.safeSpace,
|
||||
right: StyleString.safeSpace,
|
||||
),
|
||||
child: SingleChildScrollView(
|
||||
controller: _memberSeasonsController.scrollController,
|
||||
child: FutureBuilder(
|
||||
future: _futureBuilderFuture,
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.connectionState == ConnectionState.done) {
|
||||
if (snapshot.data != null) {
|
||||
Map data = snapshot.data as Map;
|
||||
List list = _memberSeasonsController.seasonsList;
|
||||
if (data['status']) {
|
||||
return Obx(
|
||||
() => list.isNotEmpty
|
||||
? LayoutBuilder(
|
||||
builder: (context, boxConstraints) {
|
||||
return GridView.builder(
|
||||
gridDelegate:
|
||||
const SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: 2,
|
||||
crossAxisSpacing: StyleString.safeSpace,
|
||||
mainAxisSpacing: StyleString.safeSpace,
|
||||
childAspectRatio: 0.94,
|
||||
),
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
shrinkWrap: true,
|
||||
itemCount: _memberSeasonsController
|
||||
.seasonsList.length,
|
||||
itemBuilder: (context, i) {
|
||||
return MemberSeasonsItem(
|
||||
seasonItem: _memberSeasonsController
|
||||
.seasonsList[i],
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
)
|
||||
: const SizedBox(),
|
||||
);
|
||||
} else {
|
||||
return const SizedBox();
|
||||
}
|
||||
} else {
|
||||
return const SizedBox();
|
||||
}
|
||||
} else {
|
||||
return const SizedBox();
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
98
lib/pages/member_seasons/widgets/item.dart
Normal file
98
lib/pages/member_seasons/widgets/item.dart
Normal file
@ -0,0 +1,98 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:pilipala/common/constants.dart';
|
||||
import 'package:pilipala/common/widgets/badge.dart';
|
||||
import 'package:pilipala/common/widgets/network_img_layer.dart';
|
||||
import 'package:pilipala/common/widgets/stat/view.dart';
|
||||
import 'package:pilipala/http/search.dart';
|
||||
import 'package:pilipala/utils/utils.dart';
|
||||
|
||||
class MemberSeasonsItem extends StatelessWidget {
|
||||
final dynamic seasonItem;
|
||||
|
||||
const MemberSeasonsItem({
|
||||
Key? key,
|
||||
required this.seasonItem,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
String heroTag = Utils.makeHeroTag(seasonItem.aid);
|
||||
return Card(
|
||||
elevation: 0,
|
||||
clipBehavior: Clip.hardEdge,
|
||||
margin: EdgeInsets.zero,
|
||||
child: InkWell(
|
||||
onTap: () async {
|
||||
int cid =
|
||||
await SearchHttp.ab2c(aid: seasonItem.aid, bvid: seasonItem.bvid);
|
||||
Get.toNamed('/video?bvid=${seasonItem.bvid}&cid=$cid',
|
||||
arguments: {'videoItem': seasonItem, 'heroTag': heroTag});
|
||||
},
|
||||
child: Column(
|
||||
children: [
|
||||
AspectRatio(
|
||||
aspectRatio: StyleString.aspectRatio,
|
||||
child: LayoutBuilder(builder: (context, boxConstraints) {
|
||||
double maxWidth = boxConstraints.maxWidth;
|
||||
double maxHeight = boxConstraints.maxHeight;
|
||||
return Stack(
|
||||
children: [
|
||||
Hero(
|
||||
tag: heroTag,
|
||||
child: NetworkImgLayer(
|
||||
src: seasonItem.pic,
|
||||
width: maxWidth,
|
||||
height: maxHeight,
|
||||
),
|
||||
),
|
||||
if (seasonItem.duration != null)
|
||||
PBadge(
|
||||
bottom: 6,
|
||||
right: 6,
|
||||
type: 'gray',
|
||||
text: Utils.timeFormat(seasonItem.duration),
|
||||
)
|
||||
],
|
||||
);
|
||||
}),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(5, 6, 0, 0),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
seasonItem.title,
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Row(
|
||||
children: [
|
||||
StatView(
|
||||
view: seasonItem.view,
|
||||
theme: 'gray',
|
||||
),
|
||||
const Spacer(),
|
||||
Text(
|
||||
Utils.CustomStamp_str(
|
||||
timestamp: seasonItem.pubdate, date: 'MM-DD'),
|
||||
style: TextStyle(
|
||||
fontSize: 11,
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 6)
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user