Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
bggRGjQaUbCoE
2025-07-23 16:47:11 +08:00
parent 148e0872b4
commit 418a1e8d39
821 changed files with 29467 additions and 25520 deletions

View File

@@ -40,17 +40,17 @@ class SearchAllController
@override
Future<LoadingState<SearchAllData>> customGetData() => SearchHttp.searchAll(
keyword: keyword,
page: page,
order: order.value,
duration: searchType == SearchType.video ? duration.value : null,
tids: tids,
orderSort: orderSort,
userType: userType,
categoryId: categoryId,
pubBegin: pubBegin,
pubEnd: pubEnd,
);
keyword: keyword,
page: page,
order: order.value,
duration: searchType == SearchType.video ? duration.value : null,
tids: tids,
orderSort: orderSort,
userType: userType,
categoryId: categoryId,
pubBegin: pubBegin,
pubEnd: pubEnd,
);
void onPushDetail(dynamic resultList) {
try {

View File

@@ -52,44 +52,46 @@ class _SearchAllPanelState
.map(
(item) => switch (item) {
SearchVideoItemModel() => SizedBox(
height: 120,
child: VideoCardH(
videoItem: item,
),
height: 120,
child: VideoCardH(
videoItem: item,
),
List<SearchPgcItemModel>() => item.length == 1
? SizedBox(
height: 160,
child: SearchPgcItem(item: item.first),
)
: SizedBox(
height: Grid.smallCardWidth / 2 / 0.75 +
MediaQuery.textScalerOf(context).scale(60),
child: ListView.builder(
padding: const EdgeInsets.only(bottom: 7),
physics: const AlwaysScrollableScrollPhysics(),
scrollDirection: Axis.horizontal,
itemCount: item.length,
itemBuilder: (context, index) {
return Container(
width: Grid.smallCardWidth / 2,
margin: EdgeInsets.only(
left: StyleString.safeSpace,
right: index == item.length - 1
? StyleString.safeSpace
: 0,
),
child: PgcCardVSearch(item: item[index]),
);
},
),
List<SearchPgcItemModel>() =>
item.length == 1
? SizedBox(
height: 160,
child: SearchPgcItem(item: item.first),
)
: SizedBox(
height:
Grid.smallCardWidth / 2 / 0.75 +
MediaQuery.textScalerOf(context).scale(60),
child: ListView.builder(
padding: const EdgeInsets.only(bottom: 7),
physics: const AlwaysScrollableScrollPhysics(),
scrollDirection: Axis.horizontal,
itemCount: item.length,
itemBuilder: (context, index) {
return Container(
width: Grid.smallCardWidth / 2,
margin: EdgeInsets.only(
left: StyleString.safeSpace,
right: index == item.length - 1
? StyleString.safeSpace
: 0,
),
child: PgcCardVSearch(item: item[index]),
);
},
),
),
),
SearchUserItemModel() => Padding(
padding: const EdgeInsets.only(bottom: 5),
child: SearchUserItem(
item: item,
),
padding: const EdgeInsets.only(bottom: 5),
child: SearchUserItem(
item: item,
),
),
_ => const SizedBox.shrink(),
},
)

View File

@@ -31,25 +31,27 @@ class PgcCardVSearch extends StatelessWidget {
children: [
AspectRatio(
aspectRatio: 0.75,
child: LayoutBuilder(builder: (context, boxConstraints) {
final double maxWidth = boxConstraints.maxWidth;
final double maxHeight = boxConstraints.maxHeight;
return Stack(
clipBehavior: Clip.none,
children: [
NetworkImgLayer(
src: item.cover,
width: maxWidth,
height: maxHeight,
),
PBadge(
text: item.seasonTypeName,
right: 6,
top: 6,
),
],
);
}),
child: LayoutBuilder(
builder: (context, boxConstraints) {
final double maxWidth = boxConstraints.maxWidth;
final double maxHeight = boxConstraints.maxHeight;
return Stack(
clipBehavior: Clip.none,
children: [
NetworkImgLayer(
src: item.cover,
width: maxWidth,
height: maxHeight,
),
PBadge(
text: item.seasonTypeName,
right: 6,
top: 6,
),
],
);
},
),
),
Padding(
padding: const EdgeInsets.fromLTRB(4, 5, 0, 3),
@@ -62,7 +64,7 @@ class PgcCardVSearch extends StatelessWidget {
maxLines: 2,
overflow: TextOverflow.ellipsis,
),
)
),
],
),
),

View File

@@ -22,9 +22,10 @@ class SearchArticleController
}
void jump2Article() {
String? cvid = RegExp(r'^cv(id)?(\d+)$', caseSensitive: false)
.matchAsPrefix(keyword)
?.group(2);
String? cvid = RegExp(
r'^cv(id)?(\d+)$',
caseSensitive: false,
).matchAsPrefix(keyword)?.group(2);
if (cvid != null) {
WidgetsBinding.instance.addPostFrameCallback((_) {
Get.toNamed(
@@ -108,8 +109,8 @@ class SearchArticleController
: null,
textColor:
item['value'] == currentOrderFilterval.value
? theme.colorScheme.onSecondaryContainer
: null,
? theme.colorScheme.onSecondaryContainer
: null,
),
)
.toList(),

View File

@@ -19,8 +19,13 @@ class SearchArticlePanel extends CommonSearchPanel {
State<SearchArticlePanel> createState() => _SearchArticlePanelState();
}
class _SearchArticlePanelState extends CommonSearchPanelState<
SearchArticlePanel, SearchArticleData, SearchArticleItemModel> {
class _SearchArticlePanelState
extends
CommonSearchPanelState<
SearchArticlePanel,
SearchArticleData,
SearchArticleItemModel
> {
@override
late final SearchArticleController controller = Get.put(
SearchArticleController(

View File

@@ -43,15 +43,17 @@ class SearchArticleItem extends StatelessWidget {
if (item.imageUrls?.isNotEmpty == true)
AspectRatio(
aspectRatio: StyleString.aspectRatio,
child: LayoutBuilder(builder: (context, boxConstraints) {
double maxWidth = boxConstraints.maxWidth;
double maxHeight = boxConstraints.maxHeight;
return NetworkImgLayer(
width: maxWidth,
height: maxHeight,
src: item.imageUrls?.firstOrNull,
);
}),
child: LayoutBuilder(
builder: (context, boxConstraints) {
double maxWidth = boxConstraints.maxWidth;
double maxHeight = boxConstraints.maxHeight;
return NetworkImgLayer(
width: maxWidth,
height: maxHeight,
src: item.imageUrls?.firstOrNull,
);
},
),
),
const SizedBox(width: 10),
Expanded(
@@ -62,16 +64,19 @@ class SearchArticleItem extends StatelessWidget {
Text.rich(
maxLines: 2,
TextSpan(
children: item.title
.map((e) => TextSpan(
text: e.text,
style: TextStyle(
color: e.isEm
? theme.colorScheme.primary
: theme.colorScheme.onSurface,
),
))
.toList()),
children: item.title
.map(
(e) => TextSpan(
text: e.text,
style: TextStyle(
color: e.isEm
? theme.colorScheme.primary
: theme.colorScheme.onSurface,
),
),
)
.toList(),
),
),
const Spacer(),
Text(

View File

@@ -52,18 +52,18 @@ class SearchPanelController<R extends SearchNumData<T>, T>
@override
Future<LoadingState<R>> customGetData() => SearchHttp.searchByType<R>(
searchType: searchType,
keyword: keyword,
page: page,
order: order.value,
duration: searchType == SearchType.video ? duration.value : null,
tids: tids,
orderSort: orderSort,
userType: userType,
categoryId: categoryId,
pubBegin: pubBegin,
pubEnd: pubEnd,
);
searchType: searchType,
keyword: keyword,
page: page,
order: order.value,
duration: searchType == SearchType.video ? duration.value : null,
tids: tids,
orderSort: orderSort,
userType: userType,
categoryId: categoryId,
pubBegin: pubBegin,
pubEnd: pubEnd,
);
@override
Future<void> onReload() {

View File

@@ -19,8 +19,13 @@ class SearchLivePanel extends CommonSearchPanel {
State<SearchLivePanel> createState() => _SearchLivePanelState();
}
class _SearchLivePanelState extends CommonSearchPanelState<SearchLivePanel,
SearchLiveData, SearchLiveItemModel> {
class _SearchLivePanelState
extends
CommonSearchPanelState<
SearchLivePanel,
SearchLiveData,
SearchLiveItemModel
> {
@override
late final controller = Get.put(
SearchPanelController<SearchLiveData, SearchLiveItemModel>(

View File

@@ -25,36 +25,38 @@ class LiveItem extends StatelessWidget {
children: [
AspectRatio(
aspectRatio: StyleString.aspectRatio,
child: LayoutBuilder(builder: (context, boxConstraints) {
double maxWidth = boxConstraints.maxWidth;
double maxHeight = boxConstraints.maxHeight;
return Stack(
clipBehavior: Clip.none,
children: [
NetworkImgLayer(
src: liveItem.cover,
width: maxWidth,
height: maxHeight,
radius: 0,
),
Positioned(
left: 0,
right: 0,
bottom: 0,
child: AnimatedOpacity(
opacity: 1,
duration: const Duration(milliseconds: 200),
child: liveStat(
liveItem.online,
liveItem.cateName,
child: LayoutBuilder(
builder: (context, boxConstraints) {
double maxWidth = boxConstraints.maxWidth;
double maxHeight = boxConstraints.maxHeight;
return Stack(
clipBehavior: Clip.none,
children: [
NetworkImgLayer(
src: liveItem.cover,
width: maxWidth,
height: maxHeight,
radius: 0,
),
Positioned(
left: 0,
right: 0,
bottom: 0,
child: AnimatedOpacity(
opacity: 1,
duration: const Duration(milliseconds: 200),
child: liveStat(
liveItem.online,
liveItem.cateName,
),
),
),
),
],
);
}),
],
);
},
),
),
liveContent(theme)
liveContent(theme),
],
),
),
@@ -62,40 +64,43 @@ class LiveItem extends StatelessWidget {
}
Widget liveContent(ThemeData theme) => Expanded(
child: Padding(
padding: const EdgeInsets.fromLTRB(9, 8, 9, 6),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text.rich(
TextSpan(
children: liveItem.title
.map((e) => TextSpan(
text: e.text,
style: TextStyle(
color: e.isEm
? theme.colorScheme.primary
: theme.colorScheme.onSurface,
),
))
.toList()),
),
SizedBox(
width: double.infinity,
child: Text(
liveItem.uname!,
maxLines: 1,
style: TextStyle(
fontSize: theme.textTheme.labelMedium!.fontSize,
color: theme.colorScheme.outline,
),
),
),
],
child: Padding(
padding: const EdgeInsets.fromLTRB(9, 8, 9, 6),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text.rich(
TextSpan(
children: liveItem.title
.map(
(e) => TextSpan(
text: e.text,
style: TextStyle(
color: e.isEm
? theme.colorScheme.primary
: theme.colorScheme.onSurface,
),
),
)
.toList(),
),
),
),
);
SizedBox(
width: double.infinity,
child: Text(
liveItem.uname!,
maxLines: 1,
style: TextStyle(
fontSize: theme.textTheme.labelMedium!.fontSize,
color: theme.colorScheme.outline,
),
),
),
],
),
),
);
Widget liveStat(int? online, String? cateName) {
return Container(
@@ -122,7 +127,7 @@ class LiveItem extends StatelessWidget {
Text(
'围观:${online.toString()}',
style: const TextStyle(fontSize: 11, color: Colors.white),
)
),
],
),
);

View File

@@ -18,8 +18,13 @@ class SearchPgcPanel extends CommonSearchPanel {
State<SearchPgcPanel> createState() => _SearchPgcPanelState();
}
class _SearchPgcPanelState extends CommonSearchPanelState<SearchPgcPanel,
SearchPgcData, SearchPgcItemModel> {
class _SearchPgcPanelState
extends
CommonSearchPanelState<
SearchPgcPanel,
SearchPgcData,
SearchPgcItemModel
> {
@override
late final controller = Get.put(
SearchPanelController<SearchPgcData, SearchPgcItemModel>(

View File

@@ -49,7 +49,7 @@ class SearchPgcItem extends StatelessWidget {
right: 4.0,
bottom: null,
left: null,
)
),
],
),
const SizedBox(width: 10),
@@ -60,16 +60,19 @@ class SearchPgcItem extends StatelessWidget {
const SizedBox(height: 4),
Text.rich(
TextSpan(
children: item.title
.map((e) => TextSpan(
text: e.text,
style: TextStyle(
color: e.isEm
? theme.colorScheme.primary
: theme.colorScheme.onSurface,
),
))
.toList()),
children: item.title
.map(
(e) => TextSpan(
text: e.text,
style: TextStyle(
color: e.isEm
? theme.colorScheme.primary
: theme.colorScheme.onSurface,
),
),
)
.toList(),
),
),
const SizedBox(height: 12),
Text('评分:${item.mediaScore?['score']}', style: style),

View File

@@ -81,8 +81,8 @@ class SearchUserController
: null,
textColor:
item['value'] == currentOrderFilterval.value
? theme.colorScheme.onSecondaryContainer
: null,
? theme.colorScheme.onSecondaryContainer
: null,
),
)
.toList(),
@@ -109,12 +109,12 @@ class SearchUserController
},
bgColor:
item['value'] == currentUserTypeFilterval.value
? theme.colorScheme.secondaryContainer
: null,
? theme.colorScheme.secondaryContainer
: null,
textColor:
item['value'] == currentUserTypeFilterval.value
? theme.colorScheme.onSecondaryContainer
: null,
? theme.colorScheme.onSecondaryContainer
: null,
),
)
.toList(),

View File

@@ -19,8 +19,13 @@ class SearchUserPanel extends CommonSearchPanel {
State<SearchUserPanel> createState() => _SearchUserPanelState();
}
class _SearchUserPanelState extends CommonSearchPanelState<SearchUserPanel,
SearchUserData, SearchUserItemModel> {
class _SearchUserPanelState
extends
CommonSearchPanelState<
SearchUserPanel,
SearchUserData,
SearchUserItemModel
> {
@override
late final SearchUserController controller = Get.put(
SearchUserController(

View File

@@ -66,7 +66,7 @@ class SearchUserItem extends StatelessWidget {
style: style,
),
],
)
),
],
),
),

View File

@@ -87,10 +87,12 @@ class SearchVideoController
// sort
late final List<Map> filterList = ArchiveFilterType.values
.map((type) => {
'label': type.desc,
'type': type,
})
.map(
(type) => {
'label': type.desc,
'type': type,
},
)
.toList();
late final Rx<ArchiveFilterType> selectedType =
ArchiveFilterType.values.first.obs;
@@ -152,8 +154,9 @@ class SearchVideoController
final theme = Theme.of(context);
Widget dateWidget([bool isFirst = true]) {
return SearchText(
text: DateUtil.longFormat
.format(isFirst ? pubBeginDate : pubEndDate),
text: DateUtil.longFormat.format(
isFirst ? pubBeginDate : pubEndDate,
),
textAlign: TextAlign.center,
onTap: (text) {
showDatePicker(
@@ -172,7 +175,8 @@ class SearchVideoController
}
currentPubTimeFilter = -1;
SmartDialog.dismiss();
pubBegin = DateTime(
pubBegin =
DateTime(
pubBeginDate.year,
pubBeginDate.month,
pubBeginDate.day,
@@ -181,7 +185,8 @@ class SearchVideoController
0,
).millisecondsSinceEpoch ~/
1000;
pubEnd = DateTime(
pubEnd =
DateTime(
pubEndDate.year,
pubEndDate.month,
pubEndDate.day,
@@ -197,11 +202,13 @@ class SearchVideoController
}
});
},
bgColor: currentPubTimeFilter == -1 &&
bgColor:
currentPubTimeFilter == -1 &&
(isFirst ? customPubBeginDate : customPubEndDate)
? theme.colorScheme.secondaryContainer
: theme.colorScheme.outline.withValues(alpha: 0.1),
textColor: currentPubTimeFilter == -1 &&
textColor:
currentPubTimeFilter == -1 &&
(isFirst ? customPubBeginDate : customPubEndDate)
? theme.colorScheme.onSecondaryContainer
: theme.colorScheme.outline.withValues(alpha: 0.8),
@@ -241,21 +248,23 @@ class SearchVideoController
pubBegin = null;
pubEnd = null;
} else {
pubBegin = DateTime(
pubBegin =
DateTime(
now.year,
now.month,
now.day -
(item['value'] == 0
? 0
: item['value'] == 1
? 6
: 179),
? 6
: 179),
0,
0,
0,
).millisecondsSinceEpoch ~/
1000;
pubEnd = DateTime(
pubEnd =
DateTime(
now.year,
now.month,
now.day,

View File

@@ -21,8 +21,13 @@ class SearchVideoPanel extends CommonSearchPanel {
State<SearchVideoPanel> createState() => _SearchVideoPanelState();
}
class _SearchVideoPanelState extends CommonSearchPanelState<SearchVideoPanel,
SearchVideoData, SearchVideoItemModel> {
class _SearchVideoPanelState
extends
CommonSearchPanelState<
SearchVideoPanel,
SearchVideoData,
SearchVideoItemModel
> {
@override
late final SearchVideoController controller = Get.put(
SearchVideoController(
@@ -59,19 +64,21 @@ class _SearchVideoPanelState extends CommonSearchPanelState<SearchVideoPanel,
bgColor: Colors.transparent,
textColor:
controller.selectedType.value == i['type']
? theme.colorScheme.primary
: theme.colorScheme.outline,
? theme.colorScheme.primary
: theme.colorScheme.outline,
onTap: (value) async {
controller.selectedType.value = i['type'];
controller.order.value =
i['type'].toString().split('.').last;
controller.order.value = i['type']
.toString()
.split('.')
.last;
SmartDialog.showLoading(msg: 'loading');
await controller.onReload();
SmartDialog.dismiss();
},
),
),
]
],
],
),
),

View File

@@ -27,9 +27,12 @@ abstract class CommonSearchPanel extends StatefulWidget {
}
abstract class CommonSearchPanelState<
S extends CommonSearchPanel,
R extends SearchNumData<T>,
T> extends State<S> with AutomaticKeepAliveClientMixin {
S extends CommonSearchPanel,
R extends SearchNumData<T>,
T
>
extends State<S>
with AutomaticKeepAliveClientMixin {
SearchPanelController<R, T> get controller;
@override
@@ -56,24 +59,23 @@ abstract class CommonSearchPanelState<
return SliverGrid(
gridDelegate: switch (widget.searchType) {
SearchType.media_bangumi ||
SearchType.media_ft =>
SliverGridDelegateWithExtentAndRatio(
mainAxisSpacing: 2,
maxCrossAxisExtent: Grid.smallCardWidth * 2,
childAspectRatio: StyleString.aspectRatio * 1.5,
minHeight: MediaQuery.textScalerOf(context).scale(155),
),
SearchType.media_ft => SliverGridDelegateWithExtentAndRatio(
mainAxisSpacing: 2,
maxCrossAxisExtent: Grid.smallCardWidth * 2,
childAspectRatio: StyleString.aspectRatio * 1.5,
minHeight: MediaQuery.textScalerOf(context).scale(155),
),
SearchType.live_room => SliverGridDelegateWithExtentAndRatio(
mainAxisSpacing: StyleString.cardSpace,
crossAxisSpacing: StyleString.cardSpace,
maxCrossAxisExtent: Grid.smallCardWidth,
childAspectRatio: StyleString.aspectRatio,
mainAxisExtent: MediaQuery.textScalerOf(context).scale(90),
),
mainAxisSpacing: StyleString.cardSpace,
crossAxisSpacing: StyleString.cardSpace,
maxCrossAxisExtent: Grid.smallCardWidth,
childAspectRatio: StyleString.aspectRatio,
mainAxisExtent: MediaQuery.textScalerOf(context).scale(90),
),
SearchType.bili_user => SliverGridDelegateWithMaxCrossAxisExtent(
maxCrossAxisExtent: Grid.smallCardWidth * 2,
mainAxisExtent: 66,
),
maxCrossAxisExtent: Grid.smallCardWidth * 2,
mainAxisExtent: 66,
),
_ => Grid.videoCardHDelegate(context),
},
delegate: SliverChildBuilderDelegate(
@@ -96,28 +98,31 @@ abstract class CommonSearchPanelState<
Widget _buildBody(ThemeData theme, LoadingState<List<T>?> loadingState) {
return switch (loadingState) {
Loading() => widget.searchType == SearchType.live_room
? SliverPadding(
padding: const EdgeInsets.only(
left: StyleString.cardSpace,
right: StyleString.cardSpace,
Loading() =>
widget.searchType == SearchType.live_room
? SliverPadding(
padding: const EdgeInsets.only(
left: StyleString.cardSpace,
right: StyleString.cardSpace,
),
sliver: _builLoading,
)
: _builLoading,
Success(:var response) =>
response?.isNotEmpty == true
? SliverPadding(
padding: EdgeInsets.only(
bottom: MediaQuery.paddingOf(context).bottom + 80,
),
sliver: buildList(theme, response!),
)
: HttpError(
onReload: controller.onReload,
),
sliver: _builLoading,
)
: _builLoading,
Success(:var response) => response?.isNotEmpty == true
? SliverPadding(
padding: EdgeInsets.only(
bottom: MediaQuery.paddingOf(context).bottom + 80),
sliver: buildList(theme, response!),
)
: HttpError(
onReload: controller.onReload,
),
Error(:var errMsg) => HttpError(
errMsg: errMsg,
onReload: controller.onReload,
),
errMsg: errMsg,
onReload: controller.onReload,
),
};
}