mod: 用户页跳转&样式修改
This commit is contained in:
BIN
assets/images/live.gif
Normal file
BIN
assets/images/live.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.6 KiB |
@ -199,6 +199,8 @@ class Api {
|
|||||||
|
|
||||||
// 用户信息 需要Wbi签名
|
// 用户信息 需要Wbi签名
|
||||||
// https://api.bilibili.com/x/space/wbi/acc/info?mid=503427686&token=&platform=web&web_location=1550101&w_rid=d709892496ce93e3d94d6d37c95bde91&wts=1689301482
|
// https://api.bilibili.com/x/space/wbi/acc/info?mid=503427686&token=&platform=web&web_location=1550101&w_rid=d709892496ce93e3d94d6d37c95bde91&wts=1689301482
|
||||||
static const String memberInfo =
|
static const String memberInfo = '/x/space/wbi/acc/info';
|
||||||
'https://api.bilibili.com/x/space/wbi/acc/info';
|
|
||||||
|
// 用户名片信息
|
||||||
|
static const String memberCardInfo = '/x/web-interface/card';
|
||||||
}
|
}
|
||||||
|
@ -19,10 +19,23 @@ class MemberHttp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static Future memberStat({int? mid}) async {
|
static Future memberStat({int? mid}) async {
|
||||||
var res = await Request().get(Api.userStat, data: {mid: mid});
|
var res = await Request().get(Api.userStat, data: {'vmid': mid});
|
||||||
if (res.data['code'] == 0) {
|
if (res.data['code'] == 0) {
|
||||||
print(res.data['data']);
|
return {'status': true, 'data': res.data['data']};
|
||||||
// return {'status': true, 'data': FansDataModel.fromJson(res.data['data'])};
|
} else {
|
||||||
|
return {
|
||||||
|
'status': false,
|
||||||
|
'data': [],
|
||||||
|
'msg': res.data['message'],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static Future memberCardInfo({int? mid}) async {
|
||||||
|
var res = await Request()
|
||||||
|
.get(Api.memberCardInfo, data: {'mid': mid, 'photo': true});
|
||||||
|
if (res.data['code'] == 0) {
|
||||||
|
return {'status': true, 'data': res.data['data']};
|
||||||
} else {
|
} else {
|
||||||
return {
|
return {
|
||||||
'status': false,
|
'status': false,
|
||||||
|
@ -7,6 +7,9 @@ class MemberInfoModel {
|
|||||||
this.sign,
|
this.sign,
|
||||||
this.level,
|
this.level,
|
||||||
this.isFollowed,
|
this.isFollowed,
|
||||||
|
this.topPhoto,
|
||||||
|
this.official,
|
||||||
|
this.vip,
|
||||||
});
|
});
|
||||||
|
|
||||||
int? mid;
|
int? mid;
|
||||||
@ -16,14 +19,73 @@ class MemberInfoModel {
|
|||||||
String? sign;
|
String? sign;
|
||||||
int? level;
|
int? level;
|
||||||
bool? isFollowed;
|
bool? isFollowed;
|
||||||
|
String? topPhoto;
|
||||||
|
Map? official;
|
||||||
|
Vip? vip;
|
||||||
|
LiveRoom? liveRoom;
|
||||||
|
|
||||||
MemberInfoModel.fromJson(Map<String, dynamic> json) {
|
MemberInfoModel.fromJson(Map<String, dynamic> json) {
|
||||||
mid = json['mid'];
|
mid = json['mid'];
|
||||||
name = json['name'];
|
name = json['name'];
|
||||||
sex = json['sex'];
|
sex = json['sex'];
|
||||||
face = json['face'];
|
face = json['face'];
|
||||||
sign = json['sign'];
|
sign = json['sign'] == '' ? '该用户还没有签名' : json['sign'];
|
||||||
level = json['level'];
|
level = json['level'];
|
||||||
isFollowed = json['is_followed'];
|
isFollowed = json['is_followed'];
|
||||||
|
topPhoto = json['top_photo'];
|
||||||
|
official = json['official'];
|
||||||
|
vip = Vip.fromJson(json['vip']);
|
||||||
|
liveRoom = LiveRoom.fromJson(json['live_room']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Vip {
|
||||||
|
Vip({
|
||||||
|
this.type,
|
||||||
|
this.status,
|
||||||
|
this.dueDate,
|
||||||
|
this.label,
|
||||||
|
});
|
||||||
|
|
||||||
|
int? type;
|
||||||
|
int? status;
|
||||||
|
int? dueDate;
|
||||||
|
Map? label;
|
||||||
|
|
||||||
|
Vip.fromJson(Map<String, dynamic> json) {
|
||||||
|
type = json['type'];
|
||||||
|
status = json['status'];
|
||||||
|
dueDate = json['due_date'];
|
||||||
|
label = json['label'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class LiveRoom {
|
||||||
|
LiveRoom({
|
||||||
|
this.roomStatus,
|
||||||
|
this.liveStatus,
|
||||||
|
this.url,
|
||||||
|
this.title,
|
||||||
|
this.cover,
|
||||||
|
this.roomId,
|
||||||
|
this.roundStatus,
|
||||||
|
});
|
||||||
|
|
||||||
|
int? roomStatus;
|
||||||
|
int? liveStatus;
|
||||||
|
String? url;
|
||||||
|
String? title;
|
||||||
|
String? cover;
|
||||||
|
int? roomId;
|
||||||
|
int? roundStatus;
|
||||||
|
|
||||||
|
LiveRoom.fromJson(Map<String, dynamic> json) {
|
||||||
|
roomStatus = json['room_status'];
|
||||||
|
liveStatus = json['live_status'];
|
||||||
|
url = json['url'];
|
||||||
|
title = json['title'];
|
||||||
|
cover = json['cover'];
|
||||||
|
roomId = json['room_id'];
|
||||||
|
roundStatus = json['round_status'];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -193,7 +193,7 @@ class SearchUserItemModel {
|
|||||||
usign = json['usign'];
|
usign = json['usign'];
|
||||||
fans = json['fans'];
|
fans = json['fans'];
|
||||||
videos = json['videos'];
|
videos = json['videos'];
|
||||||
upic = json['upic'];
|
upic = 'https:' + json['upic'];
|
||||||
faceNft = json['face_nft'];
|
faceNft = json['face_nft'];
|
||||||
faceNftType = json['face_nft_type'];
|
faceNftType = json['face_nft_type'];
|
||||||
verifyInfo = json['verify_info'];
|
verifyInfo = json['verify_info'];
|
||||||
|
@ -1,20 +1,29 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:pilipala/common/widgets/network_img_layer.dart';
|
import 'package:pilipala/common/widgets/network_img_layer.dart';
|
||||||
|
import 'package:pilipala/utils/utils.dart';
|
||||||
|
|
||||||
Widget author(item, context) {
|
Widget author(item, context) {
|
||||||
|
String heroTag = Utils.makeHeroTag(item.modules.moduleAuthor.mid);
|
||||||
return Container(
|
return Container(
|
||||||
padding: const EdgeInsets.fromLTRB(12, 12, 12, 8),
|
padding: const EdgeInsets.fromLTRB(12, 12, 12, 8),
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
GestureDetector(
|
GestureDetector(
|
||||||
onTap: () =>
|
onTap: () => Get.toNamed(
|
||||||
Get.toNamed('/member?mid=${item.modules.moduleAuthor.mid}'),
|
'/member?mid=${item.modules.moduleAuthor.mid}',
|
||||||
child: NetworkImgLayer(
|
arguments: {
|
||||||
width: 40,
|
'face': item.modules.moduleAuthor.face,
|
||||||
height: 40,
|
'heroTag': heroTag
|
||||||
type: 'avatar',
|
}),
|
||||||
src: item.modules.moduleAuthor.face,
|
child: Hero(
|
||||||
|
tag: heroTag,
|
||||||
|
child: NetworkImgLayer(
|
||||||
|
width: 40,
|
||||||
|
height: 40,
|
||||||
|
type: 'avatar',
|
||||||
|
src: item.modules.moduleAuthor.face,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(width: 10),
|
const SizedBox(width: 10),
|
||||||
|
@ -174,12 +174,13 @@ class _UpPanelState extends State<UpPanel> {
|
|||||||
Badge(
|
Badge(
|
||||||
smallSize: 8,
|
smallSize: 8,
|
||||||
label: data.type == 'live' ? const Text('Live') : null,
|
label: data.type == 'live' ? const Text('Live') : null,
|
||||||
textColor: Theme.of(context).colorScheme.onPrimary,
|
textColor: Theme.of(context).colorScheme.onSecondaryContainer,
|
||||||
alignment: AlignmentDirectional.bottomCenter,
|
alignment: AlignmentDirectional.bottomCenter,
|
||||||
padding: const EdgeInsets.only(left: 4, right: 4),
|
padding: const EdgeInsets.only(left: 6, right: 6),
|
||||||
isLabelVisible: data.type == 'live' ||
|
isLabelVisible: data.type == 'live' ||
|
||||||
(data.type == 'up' && (data.hasUpdate ?? false)),
|
(data.type == 'up' && (data.hasUpdate ?? false)),
|
||||||
backgroundColor: Theme.of(context).primaryColor,
|
backgroundColor:
|
||||||
|
Theme.of(context).colorScheme.secondaryContainer,
|
||||||
child: NetworkImgLayer(
|
child: NetworkImgLayer(
|
||||||
width: 49,
|
width: 49,
|
||||||
height: 49,
|
height: 49,
|
||||||
|
@ -1,14 +1,21 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:get/get.dart';
|
||||||
import 'package:pilipala/common/widgets/network_img_layer.dart';
|
import 'package:pilipala/common/widgets/network_img_layer.dart';
|
||||||
|
import 'package:pilipala/utils/utils.dart';
|
||||||
|
|
||||||
Widget fanItem({item}) {
|
Widget fanItem({item}) {
|
||||||
|
String heroTag = Utils.makeHeroTag(item!.mid);
|
||||||
return ListTile(
|
return ListTile(
|
||||||
onTap: () {},
|
onTap: () => Get.toNamed('/member?mid=${item.mid}',
|
||||||
leading: NetworkImgLayer(
|
arguments: {'face': item.face, 'heroTag': heroTag}),
|
||||||
width: 38,
|
leading: Hero(
|
||||||
height: 38,
|
tag: heroTag,
|
||||||
type: 'avatar',
|
child: NetworkImgLayer(
|
||||||
src: item.face,
|
width: 38,
|
||||||
|
height: 38,
|
||||||
|
type: 'avatar',
|
||||||
|
src: item.face,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
title: Text(item.uname),
|
title: Text(item.uname),
|
||||||
subtitle: Text(
|
subtitle: Text(
|
||||||
|
@ -1,15 +1,21 @@
|
|||||||
import 'package:flutter/cupertino.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:get/get.dart';
|
||||||
import 'package:pilipala/common/widgets/network_img_layer.dart';
|
import 'package:pilipala/common/widgets/network_img_layer.dart';
|
||||||
|
import 'package:pilipala/utils/utils.dart';
|
||||||
|
|
||||||
Widget followItem({item}) {
|
Widget followItem({item}) {
|
||||||
|
String heroTag = Utils.makeHeroTag(item!.mid);
|
||||||
return ListTile(
|
return ListTile(
|
||||||
onTap: () {},
|
onTap: () => Get.toNamed('/member?mid=${item.mid}',
|
||||||
leading: NetworkImgLayer(
|
arguments: {'face': item.face, 'heroTag': heroTag}),
|
||||||
width: 38,
|
leading: Hero(
|
||||||
height: 38,
|
tag: heroTag,
|
||||||
type: 'avatar',
|
child: NetworkImgLayer(
|
||||||
src: item.face,
|
width: 38,
|
||||||
|
height: 38,
|
||||||
|
type: 'avatar',
|
||||||
|
src: item.face,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
title: Text(item.uname),
|
title: Text(item.uname),
|
||||||
subtitle: Text(
|
subtitle: Text(
|
||||||
|
@ -23,7 +23,7 @@ class LiveRoomController extends GetxController {
|
|||||||
super.onInit();
|
super.onInit();
|
||||||
if (Get.arguments != null) {
|
if (Get.arguments != null) {
|
||||||
var args = Get.arguments['liveItem'];
|
var args = Get.arguments['liveItem'];
|
||||||
heroTag = Get.arguments['heroTag'];
|
heroTag = Get.arguments['heroTag'] ?? '';
|
||||||
liveItem = args;
|
liveItem = args;
|
||||||
roomId = liveItem.roomId!;
|
roomId = liveItem.roomId!;
|
||||||
if (args.pic != null && args.pic != '') {
|
if (args.pic != null && args.pic != '') {
|
||||||
|
@ -89,20 +89,21 @@ class _LiveRoomPageState extends State<LiveRoomPage> {
|
|||||||
controller: _meeduPlayerController!,
|
controller: _meeduPlayerController!,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Visibility(
|
if (_liveRoomController.liveItem.cover != null)
|
||||||
visible: isShowCover,
|
Visibility(
|
||||||
child: Positioned(
|
visible: isShowCover,
|
||||||
top: 0,
|
child: Positioned(
|
||||||
left: 0,
|
top: 0,
|
||||||
right: 0,
|
left: 0,
|
||||||
child: NetworkImgLayer(
|
right: 0,
|
||||||
type: 'emote',
|
child: NetworkImgLayer(
|
||||||
src: _liveRoomController.liveItem.cover,
|
type: 'emote',
|
||||||
width: Get.size.width,
|
src: _liveRoomController.liveItem.cover,
|
||||||
height: videoHeight,
|
width: Get.size.width,
|
||||||
|
height: videoHeight,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
|
||||||
],
|
],
|
||||||
)),
|
)),
|
||||||
if (_liveRoomController.liveItem.watchedShow != null)
|
if (_liveRoomController.liveItem.watchedShow != null)
|
||||||
|
@ -1,18 +1,26 @@
|
|||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:pilipala/http/member.dart';
|
import 'package:pilipala/http/member.dart';
|
||||||
|
import 'package:pilipala/models/member/info.dart';
|
||||||
import 'package:pilipala/utils/wbi_sign.dart';
|
import 'package:pilipala/utils/wbi_sign.dart';
|
||||||
|
|
||||||
class MemberController extends GetxController {
|
class MemberController extends GetxController {
|
||||||
late int mid;
|
late int mid;
|
||||||
|
Rx<MemberInfoModel> memberInfo = MemberInfoModel().obs;
|
||||||
|
Map? userStat;
|
||||||
|
String? face;
|
||||||
|
String? heroTag;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onInit() {
|
void onInit() {
|
||||||
super.onInit();
|
super.onInit();
|
||||||
mid = int.parse(Get.parameters['mid']!);
|
mid = int.parse(Get.parameters['mid']!);
|
||||||
getInfo();
|
face = Get.arguments['face']!;
|
||||||
|
heroTag = Get.arguments['heroTag']!;
|
||||||
}
|
}
|
||||||
|
|
||||||
getInfo() async {
|
// 获取用户信息
|
||||||
|
Future<Map<String, dynamic>> getInfo() async {
|
||||||
|
await getMemberStat();
|
||||||
String params = await WbiSign().makSign({
|
String params = await WbiSign().makSign({
|
||||||
'mid': mid,
|
'mid': mid,
|
||||||
'token': '',
|
'token': '',
|
||||||
@ -22,7 +30,25 @@ class MemberController extends GetxController {
|
|||||||
params = '?$params';
|
params = '?$params';
|
||||||
var res = await MemberHttp.memberInfo(params: params);
|
var res = await MemberHttp.memberInfo(params: params);
|
||||||
if (res['status']) {
|
if (res['status']) {
|
||||||
print(res['data']);
|
memberInfo.value = res['data'];
|
||||||
}
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取用户状态
|
||||||
|
Future<Map<String, dynamic>> getMemberStat() async {
|
||||||
|
var res = await MemberHttp.memberStat(mid: mid);
|
||||||
|
if (res['status']) {
|
||||||
|
userStat = res['data'];
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future getMemberCardInfo() async {
|
||||||
|
var res = await MemberHttp.memberCardInfo(mid: mid);
|
||||||
|
if (res['status']) {
|
||||||
|
print(userStat);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
import 'package:extended_nested_scroll_view/extended_nested_scroll_view.dart';
|
import 'package:extended_nested_scroll_view/extended_nested_scroll_view.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
|
import 'package:pilipala/common/widgets/network_img_layer.dart';
|
||||||
|
import 'package:pilipala/models/user/stat.dart';
|
||||||
import 'package:pilipala/pages/member/index.dart';
|
import 'package:pilipala/pages/member/index.dart';
|
||||||
|
import 'package:pilipala/utils/utils.dart';
|
||||||
|
|
||||||
class MemberPage extends StatefulWidget {
|
class MemberPage extends StatefulWidget {
|
||||||
const MemberPage({super.key});
|
const MemberPage({super.key});
|
||||||
@ -10,11 +13,379 @@ class MemberPage extends StatefulWidget {
|
|||||||
State<MemberPage> createState() => _MemberPageState();
|
State<MemberPage> createState() => _MemberPageState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _MemberPageState extends State<MemberPage> {
|
class _MemberPageState extends State<MemberPage>
|
||||||
|
with SingleTickerProviderStateMixin {
|
||||||
final MemberController _memberController = Get.put(MemberController());
|
final MemberController _memberController = Get.put(MemberController());
|
||||||
|
final ScrollController _extendNestCtr = ScrollController();
|
||||||
|
late TabController _tabController;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_tabController = TabController(length: 3, vsync: this);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold();
|
return Scaffold(
|
||||||
|
primary: true,
|
||||||
|
body: ExtendedNestedScrollView(
|
||||||
|
controller: _extendNestCtr,
|
||||||
|
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
|
||||||
|
return <Widget>[
|
||||||
|
SliverAppBar(
|
||||||
|
pinned: false,
|
||||||
|
primary: true,
|
||||||
|
elevation: 0,
|
||||||
|
scrolledUnderElevation: 0,
|
||||||
|
forceElevated: innerBoxIsScrolled,
|
||||||
|
expandedHeight: 300,
|
||||||
|
actions: [
|
||||||
|
IconButton(onPressed: () {}, icon: const Icon(Icons.more_vert)),
|
||||||
|
const SizedBox(width: 4),
|
||||||
|
],
|
||||||
|
flexibleSpace: FlexibleSpaceBar(
|
||||||
|
background: Stack(
|
||||||
|
children: [
|
||||||
|
Positioned.fill(
|
||||||
|
bottom: 10,
|
||||||
|
child: Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
image: DecorationImage(
|
||||||
|
fit: BoxFit.fitWidth,
|
||||||
|
image: NetworkImage(_memberController.face!),
|
||||||
|
alignment: Alignment.topCenter,
|
||||||
|
isAntiAlias: true,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
foregroundDecoration: BoxDecoration(
|
||||||
|
gradient: LinearGradient(
|
||||||
|
colors: [
|
||||||
|
Theme.of(context)
|
||||||
|
.colorScheme
|
||||||
|
.background
|
||||||
|
.withOpacity(0.44),
|
||||||
|
Theme.of(context).colorScheme.background,
|
||||||
|
],
|
||||||
|
begin: Alignment.topCenter,
|
||||||
|
end: Alignment.bottomCenter,
|
||||||
|
stops: const [0.0, 0.46],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Positioned(
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
bottom: 0,
|
||||||
|
height: 20,
|
||||||
|
child: Container(
|
||||||
|
color: Theme.of(context).colorScheme.background,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(left: 18, right: 18),
|
||||||
|
child: FutureBuilder(
|
||||||
|
future: _memberController.getInfo(),
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
if (snapshot.connectionState ==
|
||||||
|
ConnectionState.done) {
|
||||||
|
Map data = snapshot.data!;
|
||||||
|
if (data['status']) {
|
||||||
|
return Obx(
|
||||||
|
() => Stack(
|
||||||
|
alignment: AlignmentDirectional.center,
|
||||||
|
children: [
|
||||||
|
Column(
|
||||||
|
// mainAxisAlignment:
|
||||||
|
// MainAxisAlignment.center,
|
||||||
|
crossAxisAlignment:
|
||||||
|
CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
profile(
|
||||||
|
_memberController.memberInfo.value),
|
||||||
|
const SizedBox(height: 14),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
_memberController
|
||||||
|
.memberInfo.value.name!,
|
||||||
|
style: Theme.of(context)
|
||||||
|
.textTheme
|
||||||
|
.bodyLarge!
|
||||||
|
.copyWith(
|
||||||
|
fontWeight:
|
||||||
|
FontWeight.bold),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 6),
|
||||||
|
Image.asset(
|
||||||
|
'assets/images/lv/lv${_memberController.memberInfo.value.level}.png',
|
||||||
|
height: 11,
|
||||||
|
),
|
||||||
|
const SizedBox(width: 6),
|
||||||
|
if (_memberController.memberInfo
|
||||||
|
.value.vip!.status ==
|
||||||
|
1 &&
|
||||||
|
_memberController.memberInfo
|
||||||
|
.value.vip!.label![
|
||||||
|
'img_label_uri_hans'] !=
|
||||||
|
'') ...[
|
||||||
|
Image.network(
|
||||||
|
_memberController.memberInfo
|
||||||
|
.value.vip!.label![
|
||||||
|
'img_label_uri_hans'],
|
||||||
|
height: 20,
|
||||||
|
),
|
||||||
|
] else if (_memberController
|
||||||
|
.memberInfo
|
||||||
|
.value
|
||||||
|
.vip!
|
||||||
|
.status ==
|
||||||
|
1 &&
|
||||||
|
_memberController.memberInfo
|
||||||
|
.value.vip!.label![
|
||||||
|
'img_label_uri_hans_static'] !=
|
||||||
|
'') ...[
|
||||||
|
Image.network(
|
||||||
|
_memberController.memberInfo
|
||||||
|
.value.vip!.label![
|
||||||
|
'img_label_uri_hans_static'],
|
||||||
|
height: 20,
|
||||||
|
),
|
||||||
|
]
|
||||||
|
],
|
||||||
|
),
|
||||||
|
if (_memberController.memberInfo.value
|
||||||
|
.official!['title'] !=
|
||||||
|
'') ...[
|
||||||
|
const SizedBox(height: 6),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
_memberController
|
||||||
|
.memberInfo
|
||||||
|
.value
|
||||||
|
.official![
|
||||||
|
'role'] ==
|
||||||
|
1
|
||||||
|
? '个人认证:'
|
||||||
|
: '企业认证:',
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
_memberController.memberInfo
|
||||||
|
.value.official!['title']!,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
const SizedBox(height: 4),
|
||||||
|
if (_memberController
|
||||||
|
.memberInfo.value.sign !=
|
||||||
|
'')
|
||||||
|
Text(
|
||||||
|
_memberController
|
||||||
|
.memberInfo.value.sign!,
|
||||||
|
textAlign: TextAlign.left,
|
||||||
|
maxLines: 2,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return SizedBox();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 骨架屏
|
||||||
|
return profile(null, loadingStatus: true);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
];
|
||||||
|
},
|
||||||
|
pinnedHeaderSliverHeightBuilder: () {
|
||||||
|
return MediaQuery.of(context).padding.top + kToolbarHeight;
|
||||||
|
},
|
||||||
|
onlyOneScrollInBody: true,
|
||||||
|
body: Column(
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
width: double.infinity,
|
||||||
|
height: 50,
|
||||||
|
child: TabBar(controller: _tabController, tabs: [
|
||||||
|
Tab(text: '主页'),
|
||||||
|
Tab(text: '动态'),
|
||||||
|
Tab(text: '投稿'),
|
||||||
|
]),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: TabBarView(
|
||||||
|
controller: _tabController,
|
||||||
|
children: [
|
||||||
|
Text('主页'),
|
||||||
|
Text('动态'),
|
||||||
|
Text('投稿'),
|
||||||
|
],
|
||||||
|
))
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget profile(memberInfo, {loadingStatus = false}) {
|
||||||
|
return Padding(
|
||||||
|
padding: EdgeInsets.only(top: 3 * MediaQuery.of(context).padding.top),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Hero(
|
||||||
|
tag: _memberController.heroTag!,
|
||||||
|
child: Stack(
|
||||||
|
children: [
|
||||||
|
NetworkImgLayer(
|
||||||
|
width: 90,
|
||||||
|
height: 90,
|
||||||
|
type: 'avatar',
|
||||||
|
src: !loadingStatus
|
||||||
|
? memberInfo.face
|
||||||
|
: _memberController.face,
|
||||||
|
),
|
||||||
|
Positioned(
|
||||||
|
bottom: 0,
|
||||||
|
left: 14,
|
||||||
|
child: Container(
|
||||||
|
padding: const EdgeInsets.fromLTRB(6, 2, 6, 2),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Theme.of(context).colorScheme.primary,
|
||||||
|
borderRadius:
|
||||||
|
const BorderRadius.all(Radius.circular(10)),
|
||||||
|
),
|
||||||
|
child: Row(children: [
|
||||||
|
Image.asset(
|
||||||
|
'assets/images/live.gif',
|
||||||
|
height: 10,
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
' 直播中',
|
||||||
|
style: TextStyle(
|
||||||
|
color: Colors.white,
|
||||||
|
fontSize: Theme.of(context)
|
||||||
|
.textTheme
|
||||||
|
.labelSmall!
|
||||||
|
.fontSize),
|
||||||
|
)
|
||||||
|
]),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
)),
|
||||||
|
const SizedBox(width: 12),
|
||||||
|
Expanded(
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(left: 10, right: 10),
|
||||||
|
child: Row(
|
||||||
|
mainAxisSize: MainAxisSize.max,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||||
|
children: [
|
||||||
|
Column(
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
!loadingStatus
|
||||||
|
? _memberController.userStat!['following']
|
||||||
|
.toString()
|
||||||
|
: '-',
|
||||||
|
style: const TextStyle(fontWeight: FontWeight.bold),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
'关注',
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: Theme.of(context)
|
||||||
|
.textTheme
|
||||||
|
.labelMedium!
|
||||||
|
.fontSize),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Column(
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
!loadingStatus
|
||||||
|
? Utils.numFormat(
|
||||||
|
_memberController.userStat!['follower'],
|
||||||
|
)
|
||||||
|
: '-',
|
||||||
|
style:
|
||||||
|
const TextStyle(fontWeight: FontWeight.bold)),
|
||||||
|
Text('粉丝',
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: Theme.of(context)
|
||||||
|
.textTheme
|
||||||
|
.labelMedium!
|
||||||
|
.fontSize))
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Column(
|
||||||
|
children: [
|
||||||
|
const Text('-',
|
||||||
|
style: TextStyle(fontWeight: FontWeight.bold)),
|
||||||
|
Text(
|
||||||
|
'获赞',
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: Theme.of(context)
|
||||||
|
.textTheme
|
||||||
|
.labelMedium!
|
||||||
|
.fontSize),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 10),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
TextButton(
|
||||||
|
onPressed: () {},
|
||||||
|
style: TextButton.styleFrom(
|
||||||
|
padding: const EdgeInsets.only(left: 42, right: 42),
|
||||||
|
foregroundColor: !loadingStatus && memberInfo.isFollowed
|
||||||
|
? null
|
||||||
|
: Theme.of(context).colorScheme.onPrimary,
|
||||||
|
backgroundColor: !loadingStatus && memberInfo.isFollowed
|
||||||
|
? Theme.of(context).colorScheme.onInverseSurface
|
||||||
|
: Theme.of(context).colorScheme.primary, // 设置按钮背景色
|
||||||
|
),
|
||||||
|
child: Text(!loadingStatus && memberInfo.isFollowed
|
||||||
|
? '取关'
|
||||||
|
: '关注'),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 8),
|
||||||
|
TextButton(
|
||||||
|
onPressed: () {},
|
||||||
|
style: TextButton.styleFrom(
|
||||||
|
padding: const EdgeInsets.only(left: 42, right: 42),
|
||||||
|
backgroundColor:
|
||||||
|
Theme.of(context).colorScheme.onInverseSurface,
|
||||||
|
),
|
||||||
|
child: const Text('发消息'),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,13 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:get/get.dart';
|
||||||
import 'package:pilipala/common/widgets/network_img_layer.dart';
|
import 'package:pilipala/common/widgets/network_img_layer.dart';
|
||||||
|
import 'package:pilipala/utils/utils.dart';
|
||||||
|
|
||||||
Widget searchUserPanel(BuildContext context, ctr, list) {
|
Widget searchUserPanel(BuildContext context, ctr, list) {
|
||||||
TextStyle style = TextStyle(
|
TextStyle style = TextStyle(
|
||||||
fontSize: Theme.of(context).textTheme.labelSmall!.fontSize,
|
fontSize: Theme.of(context).textTheme.labelSmall!.fontSize,
|
||||||
color: Theme.of(context).colorScheme.outline);
|
color: Theme.of(context).colorScheme.outline);
|
||||||
|
|
||||||
return ListView.builder(
|
return ListView.builder(
|
||||||
controller: ctr!.scrollController,
|
controller: ctr!.scrollController,
|
||||||
addAutomaticKeepAlives: false,
|
addAutomaticKeepAlives: false,
|
||||||
@ -12,17 +15,22 @@ Widget searchUserPanel(BuildContext context, ctr, list) {
|
|||||||
itemCount: list!.length,
|
itemCount: list!.length,
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
var i = list![index];
|
var i = list![index];
|
||||||
|
String heroTag = Utils.makeHeroTag(i!.mid);
|
||||||
return InkWell(
|
return InkWell(
|
||||||
onTap: () {},
|
onTap: () => Get.toNamed('/member?mid=${i.mid}',
|
||||||
|
arguments: {'heroTag': heroTag, 'face': i.upic}),
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 10),
|
padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 10),
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
NetworkImgLayer(
|
Hero(
|
||||||
width: 42,
|
tag: heroTag,
|
||||||
height: 42,
|
child: NetworkImgLayer(
|
||||||
src: i.upic,
|
width: 42,
|
||||||
type: 'avatar',
|
height: 42,
|
||||||
|
src: i.upic,
|
||||||
|
type: 'avatar',
|
||||||
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(width: 10),
|
const SizedBox(width: 10),
|
||||||
Column(
|
Column(
|
||||||
|
@ -360,62 +360,80 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
|
|||||||
height: 26,
|
height: 26,
|
||||||
color: Theme.of(context).dividerColor.withOpacity(0.1),
|
color: Theme.of(context).dividerColor.withOpacity(0.1),
|
||||||
),
|
),
|
||||||
Row(
|
GestureDetector(
|
||||||
children: [
|
onTap: () {
|
||||||
NetworkImgLayer(
|
int mid = !widget.loadingStatus
|
||||||
type: 'avatar',
|
? widget.videoDetail!.owner!.mid
|
||||||
src: !widget.loadingStatus
|
: videoItem['owner'].mid;
|
||||||
? widget.videoDetail!.owner!.face
|
String face = !widget.loadingStatus
|
||||||
: videoItem['owner'].face,
|
? widget.videoDetail!.owner!.face
|
||||||
width: 38,
|
: videoItem['owner'].face;
|
||||||
height: 38,
|
Get.toNamed('/member?mid=$mid', arguments: {
|
||||||
fadeInDuration: Duration.zero,
|
'face': face,
|
||||||
fadeOutDuration: Duration.zero,
|
'heroTag': (mid + 99).toString()
|
||||||
),
|
});
|
||||||
const SizedBox(width: 14),
|
},
|
||||||
Column(
|
child: Row(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
children: [
|
||||||
children: [
|
Hero(
|
||||||
Text(!widget.loadingStatus
|
tag: videoItem['owner'].mid + 99,
|
||||||
? widget.videoDetail!.owner!.name
|
child: NetworkImgLayer(
|
||||||
: videoItem['owner'].name),
|
type: 'avatar',
|
||||||
// const SizedBox(width: 10),
|
src: !widget.loadingStatus
|
||||||
Text(
|
? widget.videoDetail!.owner!.face
|
||||||
widget.loadingStatus
|
: videoItem['owner'].face,
|
||||||
? '- 粉丝'
|
width: 38,
|
||||||
: '${Utils.numFormat(videoIntroController.userStat['follower'])}粉丝',
|
height: 38,
|
||||||
style: TextStyle(
|
fadeInDuration: Duration.zero,
|
||||||
fontSize: Theme.of(context)
|
fadeOutDuration: Duration.zero,
|
||||||
.textTheme
|
|
||||||
.labelSmall!
|
|
||||||
.fontSize,
|
|
||||||
color: Theme.of(context).colorScheme.outline),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
const Spacer(),
|
|
||||||
AnimatedOpacity(
|
|
||||||
opacity: widget.loadingStatus ? 0 : 1,
|
|
||||||
duration: const Duration(milliseconds: 150),
|
|
||||||
child: SizedBox(
|
|
||||||
height: 36,
|
|
||||||
child: Obx(
|
|
||||||
() => videoIntroController.followStatus.isNotEmpty
|
|
||||||
? ElevatedButton(
|
|
||||||
onPressed: () => videoIntroController
|
|
||||||
.actionRelationMod(),
|
|
||||||
child: Text(videoIntroController
|
|
||||||
.followStatus['attribute'] ==
|
|
||||||
0
|
|
||||||
? '关注'
|
|
||||||
: '已关注'),
|
|
||||||
)
|
|
||||||
: const SizedBox(),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
const SizedBox(width: 14),
|
||||||
],
|
Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(!widget.loadingStatus
|
||||||
|
? widget.videoDetail!.owner!.name
|
||||||
|
: videoItem['owner'].name),
|
||||||
|
// const SizedBox(width: 10),
|
||||||
|
Text(
|
||||||
|
widget.loadingStatus
|
||||||
|
? '- 粉丝'
|
||||||
|
: '${Utils.numFormat(videoIntroController.userStat['follower'])}粉丝',
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: Theme.of(context)
|
||||||
|
.textTheme
|
||||||
|
.labelSmall!
|
||||||
|
.fontSize,
|
||||||
|
color: Theme.of(context).colorScheme.outline),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const Spacer(),
|
||||||
|
AnimatedOpacity(
|
||||||
|
opacity: widget.loadingStatus ? 0 : 1,
|
||||||
|
duration: const Duration(milliseconds: 150),
|
||||||
|
child: SizedBox(
|
||||||
|
height: 36,
|
||||||
|
child: Obx(
|
||||||
|
() => videoIntroController.followStatus.isNotEmpty
|
||||||
|
? ElevatedButton(
|
||||||
|
onPressed: () => videoIntroController
|
||||||
|
.actionRelationMod(),
|
||||||
|
child: Text(videoIntroController
|
||||||
|
.followStatus['attribute'] ==
|
||||||
|
0
|
||||||
|
? '关注'
|
||||||
|
: '已关注'),
|
||||||
|
)
|
||||||
|
: const SizedBox(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
Divider(
|
Divider(
|
||||||
height: 26,
|
height: 26,
|
||||||
color: Theme.of(context).dividerColor.withOpacity(0.1),
|
color: Theme.of(context).dividerColor.withOpacity(0.1),
|
||||||
|
@ -128,115 +128,112 @@ class _VideoReplyPanelState extends State<VideoReplyPanel>
|
|||||||
_videoReplyController.currentPage = 0;
|
_videoReplyController.currentPage = 0;
|
||||||
return await _videoReplyController.queryReplyList();
|
return await _videoReplyController.queryReplyList();
|
||||||
},
|
},
|
||||||
child: Scaffold(
|
child: Stack(
|
||||||
resizeToAvoidBottomInset: false,
|
children: [
|
||||||
body: Stack(
|
CustomScrollView(
|
||||||
children: [
|
controller: _videoReplyController.scrollController,
|
||||||
CustomScrollView(
|
key: const PageStorageKey<String>('评论'),
|
||||||
controller: _videoReplyController.scrollController,
|
slivers: <Widget>[
|
||||||
key: const PageStorageKey<String>('评论'),
|
const SliverToBoxAdapter(child: SizedBox(height: 12)),
|
||||||
slivers: <Widget>[
|
FutureBuilder(
|
||||||
const SliverToBoxAdapter(child: SizedBox(height: 12)),
|
future: _futureBuilderFuture,
|
||||||
FutureBuilder(
|
builder: (context, snapshot) {
|
||||||
future: _futureBuilderFuture,
|
if (snapshot.connectionState == ConnectionState.done) {
|
||||||
builder: (context, snapshot) {
|
Map data = snapshot.data as Map;
|
||||||
if (snapshot.connectionState == ConnectionState.done) {
|
if (data['status']) {
|
||||||
Map data = snapshot.data as Map;
|
// 请求成功
|
||||||
if (data['status']) {
|
return Obx(
|
||||||
// 请求成功
|
() => SliverList(
|
||||||
return Obx(
|
delegate: SliverChildBuilderDelegate(
|
||||||
() => SliverList(
|
(context, index) {
|
||||||
delegate: SliverChildBuilderDelegate(
|
if (index ==
|
||||||
(context, index) {
|
_videoReplyController.replyList.length) {
|
||||||
if (index ==
|
return Container(
|
||||||
_videoReplyController.replyList.length) {
|
padding: EdgeInsets.only(
|
||||||
return Container(
|
bottom: MediaQuery.of(context)
|
||||||
padding: EdgeInsets.only(
|
.padding
|
||||||
bottom: MediaQuery.of(context)
|
.bottom),
|
||||||
.padding
|
height:
|
||||||
.bottom),
|
MediaQuery.of(context).padding.bottom +
|
||||||
height:
|
100,
|
||||||
MediaQuery.of(context).padding.bottom +
|
child: Center(
|
||||||
100,
|
child: Obx(() => Text(
|
||||||
child: Center(
|
_videoReplyController.noMore.value)),
|
||||||
child: Obx(() => Text(
|
),
|
||||||
_videoReplyController.noMore.value)),
|
);
|
||||||
),
|
} else {
|
||||||
);
|
return ReplyItem(
|
||||||
} else {
|
replyItem:
|
||||||
return ReplyItem(
|
_videoReplyController.replyList[index],
|
||||||
replyItem: _videoReplyController
|
showReplyRow: true,
|
||||||
.replyList[index],
|
replyLevel: replyLevel);
|
||||||
showReplyRow: true,
|
}
|
||||||
replyLevel: replyLevel);
|
},
|
||||||
}
|
childCount:
|
||||||
},
|
_videoReplyController.replyList.length + 1,
|
||||||
childCount:
|
|
||||||
_videoReplyController.replyList.length + 1,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
),
|
||||||
} else {
|
);
|
||||||
// 请求错误
|
|
||||||
return HttpError(
|
|
||||||
errMsg: data['msg'],
|
|
||||||
fn: () => setState(() {}),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// 骨架屏
|
// 请求错误
|
||||||
return SliverList(
|
return HttpError(
|
||||||
delegate: SliverChildBuilderDelegate((context, index) {
|
errMsg: data['msg'],
|
||||||
return const VideoReplySkeleton();
|
fn: () => setState(() {}),
|
||||||
}, childCount: 5),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
} else {
|
||||||
)
|
// 骨架屏
|
||||||
],
|
return SliverList(
|
||||||
),
|
delegate: SliverChildBuilderDelegate((context, index) {
|
||||||
Positioned(
|
return const VideoReplySkeleton();
|
||||||
bottom: MediaQuery.of(context).padding.bottom + 14,
|
}, childCount: 5),
|
||||||
right: 14,
|
|
||||||
child: SlideTransition(
|
|
||||||
position: Tween<Offset>(
|
|
||||||
begin: const Offset(0, 2),
|
|
||||||
// 评论内容为空/不足一屏
|
|
||||||
// begin: const Offset(0, 0),
|
|
||||||
end: const Offset(0, 0),
|
|
||||||
).animate(CurvedAnimation(
|
|
||||||
parent: fabAnimationCtr,
|
|
||||||
curve: Curves.easeInOut,
|
|
||||||
)),
|
|
||||||
child: FloatingActionButton(
|
|
||||||
heroTag: null,
|
|
||||||
onPressed: () {
|
|
||||||
showModalBottomSheet(
|
|
||||||
context: context,
|
|
||||||
isScrollControlled: true,
|
|
||||||
builder: (builder) {
|
|
||||||
return VideoReplyNewDialog(
|
|
||||||
replyLevel: '0',
|
|
||||||
oid: IdUtils.bv2av(Get.parameters['bvid']!),
|
|
||||||
root: 0,
|
|
||||||
parent: 0,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
).then(
|
|
||||||
(value) => {
|
|
||||||
// 完成评论,数据添加
|
|
||||||
if (value != null && value['data'])
|
|
||||||
{_videoReplyController.replyList.add(value['data'])}
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
},
|
}
|
||||||
tooltip: '发表评论',
|
},
|
||||||
child: const Icon(Icons.reply),
|
)
|
||||||
),
|
],
|
||||||
|
),
|
||||||
|
Positioned(
|
||||||
|
bottom: MediaQuery.of(context).padding.bottom + 14,
|
||||||
|
right: 14,
|
||||||
|
child: SlideTransition(
|
||||||
|
position: Tween<Offset>(
|
||||||
|
begin: const Offset(0, 2),
|
||||||
|
// 评论内容为空/不足一屏
|
||||||
|
// begin: const Offset(0, 0),
|
||||||
|
end: const Offset(0, 0),
|
||||||
|
).animate(CurvedAnimation(
|
||||||
|
parent: fabAnimationCtr,
|
||||||
|
curve: Curves.easeInOut,
|
||||||
|
)),
|
||||||
|
child: FloatingActionButton(
|
||||||
|
heroTag: null,
|
||||||
|
onPressed: () {
|
||||||
|
showModalBottomSheet(
|
||||||
|
context: context,
|
||||||
|
isScrollControlled: true,
|
||||||
|
builder: (builder) {
|
||||||
|
return VideoReplyNewDialog(
|
||||||
|
replyLevel: '0',
|
||||||
|
oid: IdUtils.bv2av(Get.parameters['bvid']!),
|
||||||
|
root: 0,
|
||||||
|
parent: 0,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
).then(
|
||||||
|
(value) => {
|
||||||
|
// 完成评论,数据添加
|
||||||
|
if (value != null && value['data'])
|
||||||
|
{_videoReplyController.replyList.add(value['data'])}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
tooltip: '发表评论',
|
||||||
|
child: const Icon(Icons.reply),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
),
|
||||||
),
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -46,16 +46,19 @@ class ReplyItem extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget lfAvtar(context) {
|
Widget lfAvtar(context, heroTag) {
|
||||||
return Container(
|
return Container(
|
||||||
margin: const EdgeInsets.only(top: 5),
|
margin: const EdgeInsets.only(top: 5),
|
||||||
child: Stack(
|
child: Stack(
|
||||||
children: [
|
children: [
|
||||||
NetworkImgLayer(
|
Hero(
|
||||||
src: replyItem!.member!.avatar,
|
tag: heroTag,
|
||||||
width: 34,
|
child: NetworkImgLayer(
|
||||||
height: 34,
|
src: replyItem!.member!.avatar,
|
||||||
type: 'avatar',
|
width: 34,
|
||||||
|
height: 34,
|
||||||
|
type: 'avatar',
|
||||||
|
),
|
||||||
),
|
),
|
||||||
if (replyItem!.member!.officialVerify != null &&
|
if (replyItem!.member!.officialVerify != null &&
|
||||||
replyItem!.member!.officialVerify!['type'] == 0)
|
replyItem!.member!.officialVerify!['type'] == 0)
|
||||||
@ -87,16 +90,18 @@ class ReplyItem extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget content(context) {
|
Widget content(context) {
|
||||||
|
String heroTag = Utils.makeHeroTag(replyItem!.mid);
|
||||||
return Column(
|
return Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
// 头像、昵称
|
// 头像、昵称
|
||||||
GestureDetector(
|
GestureDetector(
|
||||||
// onTap: () =>
|
onTap: () {
|
||||||
// Get.toNamed('/member/${reply.userName}', parameters: {
|
Get.toNamed('/member?mid=${replyItem!.mid}', arguments: {
|
||||||
// 'memberAvatar': reply.avatar,
|
'face': replyItem!.member!.avatar!,
|
||||||
// 'heroTag': reply.userName + heroTag,
|
'heroTag': heroTag
|
||||||
// }),
|
});
|
||||||
|
},
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
child: Stack(
|
child: Stack(
|
||||||
@ -105,7 +110,7 @@ class ReplyItem extends StatelessWidget {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
lfAvtar(context),
|
lfAvtar(context, heroTag),
|
||||||
const SizedBox(width: 12),
|
const SizedBox(width: 12),
|
||||||
Text(
|
Text(
|
||||||
replyItem!.member!.uname!,
|
replyItem!.member!.uname!,
|
||||||
@ -367,9 +372,16 @@ class ReplyItemRow extends StatelessWidget {
|
|||||||
color: Theme.of(context).colorScheme.primary,
|
color: Theme.of(context).colorScheme.primary,
|
||||||
),
|
),
|
||||||
recognizer: TapGestureRecognizer()
|
recognizer: TapGestureRecognizer()
|
||||||
..onTap = () => {
|
..onTap = () {
|
||||||
print('跳转至用户主页'),
|
String heroTag =
|
||||||
},
|
Utils.makeHeroTag(replies![i].member.mid);
|
||||||
|
Get.toNamed(
|
||||||
|
'/member?mid=${replies![i].member.mid}',
|
||||||
|
arguments: {
|
||||||
|
'face': replies![i].member.avatar,
|
||||||
|
'heroTag': heroTag
|
||||||
|
});
|
||||||
|
},
|
||||||
),
|
),
|
||||||
if (replies![i].isUp)
|
if (replies![i].isUp)
|
||||||
WidgetSpan(
|
WidgetSpan(
|
||||||
@ -521,9 +533,13 @@ InlineSpan buildContent(BuildContext context, content) {
|
|||||||
color: Theme.of(context).colorScheme.primary,
|
color: Theme.of(context).colorScheme.primary,
|
||||||
),
|
),
|
||||||
recognizer: TapGestureRecognizer()
|
recognizer: TapGestureRecognizer()
|
||||||
..onTap = () => {
|
..onTap = () {
|
||||||
print('跳转至用户主页'),
|
String heroTag = Utils.makeHeroTag(value);
|
||||||
},
|
Get.toNamed(
|
||||||
|
'/member?mid=$value',
|
||||||
|
arguments: {'face': '', 'heroTag': heroTag},
|
||||||
|
);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
Reference in New Issue
Block a user