flutter/lib/pages/my/index.dart
2025-09-17 11:51:54 +08:00

938 lines
33 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_svg/svg.dart';
import 'package:get/get.dart';
import 'package:get/get_rx/src/rx_typedefs/rx_typedefs.dart';
import 'package:loopin/IM/controller/im_user_info_controller.dart';
import 'package:loopin/IM/im_service.dart';
import 'package:loopin/api/video_api.dart';
import 'package:loopin/api/common_api.dart';
import 'package:loopin/utils/index.dart';
import 'package:loopin/components/custom_sticky_header.dart';
import 'package:loopin/components/my_confirm.dart';
import 'package:loopin/components/network_or_asset_image.dart';
import 'package:loopin/components/only_down_scroll_physics.dart';
import 'package:loopin/controller/video_module_controller.dart';
import 'package:loopin/service/http.dart';
import 'package:nested_scroll_view_plus/nested_scroll_view_plus.dart';
import 'package:shirne_dialog/shirne_dialog.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_follow_info.dart';
import '../../utils/common.dart';
class PageParams {
int page;
int pageSize;
bool isLoading;
RxBool hasMore;
int total;
bool isInitLoading;
PageParams({
this.page = 1,
this.pageSize = 10,
this.isLoading = false,
bool hasMore = true,
this.total = 0,
this.isInitLoading = true,
}) : hasMore = hasMore.obs;
void init() {
page = 1;
pageSize = 10;
isLoading = false;
hasMore.value = true;
total = 0;
isInitLoading = true;
}
}
class MyPage extends StatefulWidget {
const MyPage({super.key});
@override
State<MyPage> createState() => MyPageState();
}
class MyPageState extends State<MyPage> with SingleTickerProviderStateMixin {
late RxInt currentTabIndex = 0.obs;
late RxList items = [].obs;
late RxList favoriteItems = [].obs;
RxBool isLogin = Common.isLogin().obs;
//用户基本信息
// late Rx<V2TimUserFullInfo?> userInfo = Rx<V2TimUserFullInfo?>(null);
ImUserInfoController? imUserInfoController;
// 关注,互关,粉丝数量
late Rx<V2TimFollowInfo?> followInfo = Rx<V2TimFollowInfo?>(null);
RxBool get shouldFixHeader => (currentTabIndex.value == 0 && items.isEmpty) || (currentTabIndex.value == 1 && favoriteItems.isEmpty) ? true.obs : false.obs;
List tabList = [
{'name': "作品"},
{'name': "喜欢"},
];
PageParams itemsParams = PageParams();
PageParams favoriteParams = PageParams();
late TabController tabController;
late ScrollController scrollController;
RxDouble positions = 0.0.obs;
late Callback tabListener;
late Callback scrollListener;
late int vlogLikeCount = 0; // 点赞数量
RxBool isPinned = false.obs; // 是否吸顶
@override
void initState() {
super.initState();
initControllers();
scrollListener = () {
final pos = scrollController.position;
final isNearBottom = pos.pixels >= pos.maxScrollExtent - 100;
if (!isNearBottom) return;
if (currentTabIndex.value == 0 && !itemsParams.isLoading && itemsParams.hasMore.value) {
loadData(0);
} else if (currentTabIndex.value == 1 && !favoriteParams.isLoading && favoriteParams.hasMore.value) {
loadData(1);
}
};
scrollController.addListener(scrollListener);
tabListener = () {
currentTabIndex.value = tabController.index;
if (tabController.index == 0 && items.isEmpty) {
loadData(0);
scrollInnerList();
} else if (tabController.index == 1 && favoriteItems.isEmpty) {
loadData(1);
scrollInnerList();
}
};
tabController.addListener(tabListener);
getUserLikesCount();
// loadData(0);
}
@override
void dispose() {
tabController.removeListener(tabListener);
scrollController.removeListener(scrollListener);
tabController.dispose();
scrollController.dispose();
super.dispose();
}
// 获取用户的所有视频的点赞数量
void getUserLikesCount() async {
try {
final resData = await Http.get(CommonApi.accountInfo);
if(resData != null && resData['code'] == 200){
vlogLikeCount = resData['data']['vlogLikeCount']??0;
}
} catch (e) {
}
}
// 添加控制子列表滚动的方法
void scrollInnerList([double? offset]) async {
if (isPinned.value) {
// 如果已经吸顶,先给父滚动权限
WidgetsBinding.instance.addPostFrameCallback((_) {
isPinned.value = false;
// 直接滚动到指定位置
scrollController.jumpTo(positions.value);
// 重置滚动位置
positions.value = 0.0;
});
}
}
Future<void> loadData([int? tabIndex]) async {
final index = tabIndex ?? currentTabIndex.value;
if (index == 0) {
if (itemsParams.isLoading || !itemsParams.hasMore.value) return;
itemsParams.isLoading = true;
// itemsParams.isInitLoading = true;
final res = await Http.post(VideoApi.myPublicList, data: {
"userId": imUserInfoController?.userID.value,
"yesOrNo": 0,
"current": itemsParams.page,
"size": itemsParams.pageSize,
});
final obj = res['data'];
final total = obj['total'];
final row = obj['records'] ?? [];
logger.i(res['data']);
// 判断是否还有更多数据
logger.e(items.length);
// 添加新数据,触发响应式更新
items.addAll(row);
logger.e(obj);
if (items.length >= total) {
itemsParams.hasMore.value = false;
}
// 页码加一
itemsParams.page++;
//
itemsParams.isLoading = false;
itemsParams.isInitLoading = false;
} else if (index == 1) {
if (favoriteParams.isLoading || !favoriteParams.hasMore.value) return;
favoriteParams.isLoading = true;
// favoriteParams.isInitLoading = true;
final res = await Http.post(VideoApi.myLikedList, data: {
"userId": imUserInfoController?.userID.value,
"yesOrNo": 0,
"current": favoriteParams.page,
"size": favoriteParams.pageSize,
});
final obj = res['data'];
final total = obj['total'];
final row = obj['records'] ?? [];
favoriteItems.addAll(row);
if (favoriteItems.length >= total) {
favoriteParams.hasMore.value = false;
}
favoriteParams.page++;
favoriteParams.isLoading = false;
favoriteParams.isInitLoading = false;
}
}
void initControllers() {
tabController = TabController(initialIndex: 0, length: tabList.length, vsync: this);
scrollController = ScrollController();
if (Common.isLogin()) {
imUserInfoController = Get.find<ImUserInfoController>();
}
}
// 初始化页面数据
void refreshData([int? tabIndex]) async {
if (!mounted) {
logger.i('未挂载');
return;
}
isLogin.value = Common.isLogin();
if (!Common.isLogin()) return;
final idx = tabIndex ?? currentTabIndex.value;
// 恢复位置
WidgetsBinding.instance.addPostFrameCallback((_) {
scrollInnerList();
});
items.clear();
favoriteItems.clear();
itemsParams.init();
favoriteParams.init();
// currentTabIndex.value = 0;
selfInfo();
loadData(idx);
}
// 获取当前登录用户基本信息
void selfInfo() async {
// imUserInfoController = Get.find<ImUserInfoController>();
if (!Get.isRegistered<ImUserInfoController>()) {
logger.e('用户信息controller未注册');
return;
}
final res = await ImService.instance.getUserFollowInfo(userIDList: [imUserInfoController?.userID.value ?? '']);
if (res.success) {
//这里少个点赞,从服务端获取
// followersCount粉丝多少人关注了我,mutualFollowersCount互关,followingCount我关注了多少人
followInfo.value = res.data!.first;
logger.i(followInfo.value!.toJson());
}
}
// 删除当前用户发布的视频
void deletePersonalVideo(videoId) async {
logger.i('删除视频${videoId}');
try {
final res = await Http.post('${VideoApi.deleteVideo}', data: {
'vlogerId':videoId
});
logger.i('删除成功响应${res}');
if(res != null && res['code'] == 200){
MyDialog.toast('删除成功', icon: const Icon(Icons.check_circle), style: ToastStyle(backgroundColor: Colors.green.withAlpha(200)));
loadData(0);
}
} catch (e) {
}
}
// 二维码名片弹窗
void qrcodeAlertDialog(BuildContext context) {
showDialog(
context: context,
builder: (context) {
return UnconstrainedBox(
constrainedAxis: Axis.vertical,
child: SizedBox(
width: 350.0,
child: AlertDialog(
contentPadding: const EdgeInsets.symmetric(horizontal: 10.0, vertical: 20.0),
backgroundColor: const Color(0xff07c160),
surfaceTintColor: Colors.white,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(15.0)),
content: Padding(
padding: const EdgeInsets.symmetric(horizontal: 10.0),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Image.asset('assets/images/pic1.jpg', width: 250.0, fit: BoxFit.contain),
const SizedBox(height: 15.0),
const Text('扫一扫,加好友',
style: TextStyle(
color: Colors.white38,
fontSize: 14.0,
)),
],
),
),
),
),
);
},
);
}
// 退出登录弹窗
void showLogoutDialog(BuildContext context) {
showDialog(
context: context,
builder: (context) {
return AlertDialog(
content: const Text('确认退出当前账号吗?', style: TextStyle(fontSize: 16.0)),
backgroundColor: Colors.white,
surfaceTintColor: Colors.white,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(15.0)),
elevation: 2.0,
actionsPadding: const EdgeInsets.all(15.0),
actions: [
TextButton(
onPressed: () {
Get.back();
},
child: const Text('取消', style: TextStyle(color: Colors.black54)),
),
TextButton(onPressed: handleLogout, child: const Text('退出登录', style: TextStyle(color: Colors.red))),
],
);
},
);
}
// 退出登录
void handleLogout() async {
final loginRes = await ImService.instance.logout();
if (loginRes.success) {
// 清除存储信息
Common.logout();
// 初始化视频
final videoController = Get.find<VideoModuleController>();
videoController.init();
Get.back();
}
}
@override
Widget build(BuildContext context) {
// 如果没登录,直接返回一个登录提示页面
return Obx(() {
if (!isLogin.value) {
return SizedBox();
} else {
return Scaffold(
backgroundColor: const Color(0xFFFAF6F9),
body: NestedScrollViewPlus(
controller: scrollController,
physics: shouldFixHeader.value
? OnlyDownScrollPhysics(parent: AlwaysScrollableScrollPhysics())
: isPinned.value
? NeverScrollableScrollPhysics()
: AlwaysScrollableScrollPhysics(),
// physics: shouldFixHeader.value ? OnlyDownScrollPhysics(parent: AlwaysScrollableScrollPhysics()) : AlwaysScrollableScrollPhysics(),
overscrollBehavior: OverscrollBehavior.outer,
headerSliverBuilder: (context, innerBoxIsScrolled) {
return [
SliverAppBar(
backgroundColor: Colors.transparent,
surfaceTintColor: Colors.transparent,
expandedHeight: 180.0,
collapsedHeight: 120.0,
pinned: true,
stretch: true,
onStretchTrigger: () async {
logger.i('触发 stretch 拉伸');
// 加载刷新逻辑
},
actions: [
// _buildIcon('assets/images/svg/service.svg', () {
// logger.i('点击客服按钮');
// }),
const SizedBox(width: 8.0),
_buildIcon('assets/images/svg/setting.svg', () {
logger.i('点击设置按钮');
Get.toNamed('/setting');
}),
const SizedBox(width: 10.0),
],
flexibleSpace: _buildFlexibleSpace(),
),
SliverToBoxAdapter(
child: Padding(
padding: const EdgeInsets.all(10.0),
child: Column(
children: [
const SizedBox(height: 10),
Obx(() => _buildStatsCard()),
const SizedBox(height: 10),
Obx(() => _buildInfoDesc(context)),
const SizedBox(height: 10.0),
_buildOrderCard(context),
const SizedBox(height: 10.0),
],
),
),
),
SliverPersistentHeader(
pinned: true,
delegate: CustomStickyHeader(
isPinned: isPinned,
positions: positions,
child: PreferredSize(
preferredSize: const Size.fromHeight(48.0),
child: Container(
color: Colors.white,
child: TabBar(
controller: tabController,
tabs: tabList.map((item) {
return Tab(
child: Badge.count(
backgroundColor: Colors.red,
count: item['badge'] ?? 0,
isLabelVisible: item['badge'] != null,
alignment: Alignment.topRight,
offset: const Offset(14, -6),
child: Text(item['name'], style: const TextStyle(fontWeight: FontWeight.bold)),
),
);
}).toList(),
isScrollable: false,
overlayColor: WidgetStateProperty.all(Colors.transparent),
unselectedLabelColor: Colors.black87,
labelColor: const Color(0xFFFF5000),
indicator: const UnderlineTabIndicator(borderSide: BorderSide(color: Color(0xFFFF5000), width: 2.0)),
indicatorSize: TabBarIndicatorSize.tab,
unselectedLabelStyle: const TextStyle(fontSize: 16.0, fontFamily: 'Microsoft YaHei'),
labelStyle: const TextStyle(fontSize: 18.0, fontFamily: 'Microsoft YaHei', fontWeight: FontWeight.bold),
dividerHeight: 0,
padding: const EdgeInsets.symmetric(horizontal: 10.0),
labelPadding: const EdgeInsets.symmetric(horizontal: 15.0),
),
),
),
),
),
];
},
body: TabBarView(
controller: tabController,
children: [
// Tab 1:
_buildGridTab(0),
// Tab 2:
_buildGridTab(1)
],
),
),
);
}
});
}
// 空状态提示
Widget emptyTip(String text) {
return CustomScrollView(
physics: const OnlyDownScrollPhysics(),
slivers: [
SliverFillRemaining(
hasScrollBody: false,
child: Align(
alignment: Alignment.topCenter,
child: Padding(
padding: const EdgeInsets.only(top: 50.0),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Image.asset('assets/images/empty.png', width: 100.0),
const SizedBox(height: 8.0),
Text(
text,
style: const TextStyle(color: Colors.grey, fontSize: 13.0),
),
],
),
),
),
),
],
);
}
Widget _buildInfoDesc(BuildContext context) {
final tx = imUserInfoController?.signature;
if (tx == null || tx.isEmpty) {
return const SizedBox.shrink();
}
return Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(15.0),
boxShadow: [BoxShadow(color: Colors.black.withAlpha(10), offset: const Offset(0.0, 1.0), blurRadius: 2.0, spreadRadius: 0.0)],
),
clipBehavior: Clip.antiAlias,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
padding: const EdgeInsets.all(12),
width: double.infinity,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(8),
),
child: Text(
'${imUserInfoController!.signature}',
style: const TextStyle(fontSize: 16),
),
),
],
));
}
Widget _buildGridTab(int tabIndex) {
final listToShow = tabIndex == 0 ? items : favoriteItems;
PageParams params = tabIndex == 0 ? itemsParams : favoriteParams;
if (params.isInitLoading) {
return Center(child: CircularProgressIndicator());
}
if (listToShow.isEmpty) {
return emptyTip('暂无相关数据');
}
return Obx(() {
return CustomScrollView(
// physics: !isPinned.value ? NeverScrollableScrollPhysics() : AlwaysScrollableScrollPhysics(),
// physics: AlwaysScrollableScrollPhysics(),
key: PageStorageKey('myindex_$tabIndex'),
slivers: [
SliverPadding(
padding: EdgeInsets.all(10.0),
sliver: SliverGrid(
delegate: SliverChildBuilderDelegate(
(context, index) {
return Container(
decoration: BoxDecoration(
color: Colors.blue[100 * ((index % 8) + 1)],
borderRadius: BorderRadius.circular(10.0),
),
alignment: Alignment.center,
child: _buildVdCard(listToShow[index],tabIndex),
);
},
childCount: listToShow.length,
),
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
crossAxisSpacing: 10.0,
mainAxisSpacing: 10.0,
childAspectRatio: 0.6,
),
),
),
SliverToBoxAdapter(
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 20.0),
child: Center(
child: params.hasMore.value ? CircularProgressIndicator() : Text('没有更多数据了'),
),
),
),
],
);
});
}
Widget _buildVdCard(item,tabIndex) {
return InkWell(
onTap: () {
//去视频详情
Get.toNamed('/videoDetail', arguments: {'videoId': item['id']});
},
onLongPress: () {
if(tabIndex == 0){ // 个人发布作品可以长按删除
showModalBottomSheet(
context: Get.context!,
backgroundColor: Colors.white,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(top: Radius.circular(16)),
),
builder: (context) {
return SafeArea(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
// ListTile(
// leading: const Icon(Icons.lock, color: Colors.black),
// title: const Text('设为私密', style: TextStyle(color: Colors.black)),
// onTap: () {
// Navigator.pop(context);
// // TODO: 修改为私密逻辑
// },
// ),
ListTile(
leading: const Icon(Icons.delete, color: Colors.redAccent),
title: const Text('删除视频', style: TextStyle(color: Colors.redAccent)),
onTap: () async {
Get.back();
final confirmed = await ConfirmDialog.show(
title: "提示",
content: "确认要删除吗?",
);
if (confirmed == true) {
Get.back();
deletePersonalVideo(item['id']);
}
},
),
],
),
);
},
);
}
},
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12.0),
color: Colors.grey[900],
),
child: Stack(
children: [
/// 视频缩略图
ClipRRect(
borderRadius: BorderRadius.circular(12.0),
child: NetworkOrAssetImage(
imageUrl: item['cover'] ?? item['firstFrameImg'] ?? '',
placeholderAsset: 'assets/images/bk.jpg',
fit: BoxFit.cover,
width: double.infinity,
height: double.infinity,
),
),
/// 右下角的点赞数
Positioned(
right: 8,
bottom: 8,
child: Row(
children: [
const Icon(Icons.favorite, color: Colors.white, size: 16),
const SizedBox(width: 4),
Text(
'${item['likeCounts'] ?? 0}',
style: const TextStyle(
color: Colors.white,
fontSize: 12,
fontWeight: FontWeight.bold,
),
),
],
),
),
],
),
),
);
}
Widget _buildIcon(String assetPath, VoidCallback onTap) {
return InkWell(
onTap: onTap,
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 5.0, vertical: 5.0),
decoration: BoxDecoration(color: Colors.black.withAlpha((0.3 * 255).round()), borderRadius: BorderRadius.circular(20.0)),
child: SvgPicture.asset(assetPath, height: 20.0, width: 20.0, colorFilter: const ColorFilter.mode(Colors.white70, BlendMode.srcIn)),
),
);
}
Widget _buildFlexibleSpace() {
return LayoutBuilder(
builder: (context, constraints) {
final double maxHeight = 180;
final double minHeight = 120;
final currentHeight = constraints.maxHeight;
double ratio = ((currentHeight - minHeight) / (maxHeight - minHeight)).clamp(0.0, 1.0);
return Stack(
fit: StackFit.expand,
children: [
// 背景图 Obx
Obx(() {
final bgUrl = imUserInfoController?.customInfo['coverBg'] ?? '';
return NetworkOrAssetImage(
imageUrl: bgUrl,
placeholderAsset: 'assets/images/bk.jpg',
fit: BoxFit.cover,
);
}),
Positioned(
left: 15,
bottom: 0,
right: 15,
child: Container(
padding: const EdgeInsets.symmetric(vertical: 10),
child: Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
// 头像 Obx
Obx(() {
final faceUrl = imUserInfoController?.faceUrl.value ?? '';
return ClipOval(
child: NetworkOrAssetImage(
imageUrl: faceUrl,
width: 80,
height: 80,
),
);
}),
const SizedBox(width: 15),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
// 昵称 Obx
Obx(() {
final nickname = imUserInfoController?.nickname.value ?? '';
return Container(
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5),
decoration: BoxDecoration(
color: Colors.black.withAlpha(76),
borderRadius: BorderRadius.circular(20),
),
child: Text(
nickname.isNotEmpty ? nickname : '昵称',
style: const TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
);
}),
const SizedBox(width: 8),
InkWell(
onTap: () => qrcodeAlertDialog(context),
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 5, vertical: 5),
decoration: BoxDecoration(
color: Colors.black.withAlpha(76),
borderRadius: BorderRadius.circular(20),
),
child: const Icon(Icons.qr_code_outlined, size: 18, color: Colors.white),
),
),
],
),
const SizedBox(height: 8),
// 用户ID Obx
Obx(() {
final userId = imUserInfoController?.userID.value ?? '';
return Container(
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5),
decoration: BoxDecoration(
color: Colors.black.withAlpha(76),
borderRadius: BorderRadius.circular(20),
),
child: InkWell(
onTap: () {
Clipboard.setData(ClipboardData(text: userId));
MyDialog.toast(
'ID已复制',
icon: const Icon(Icons.check_circle),
style: ToastStyle(backgroundColor: Colors.green.withAlpha(200)),
);
},
child: Text('ID:$userId', style: const TextStyle(fontSize: 12, color: Colors.white)),
),
);
}),
],
),
),
],
),
),
),
],
);
},
);
}
Widget _buildStatsCard() {
return Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(15.0),
boxShadow: [BoxShadow(color: Colors.black.withAlpha(10), offset: const Offset(0.0, 1.0), blurRadius: 2.0, spreadRadius: 0.0)],
),
clipBehavior: Clip.antiAlias,
child: Padding(
padding: const EdgeInsets.all(10.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
// '已售${Utils.graceNumber(int.tryParse(vlogLikeCount?.toString() ?? '0') ?? 0)}',
Column(children: [Text('${Utils.graceNumber(vlogLikeCount)}', style: TextStyle(fontSize: 16.0, fontWeight: FontWeight.bold)), SizedBox(height: 3.0), Text('获赞')]),
GestureDetector(
onTap: () async {
// 互相关注
await Get.toNamed('/eachFlow');
refreshData();
},
child: Column(children: [
Text('${followInfo.value?.mutualFollowersCount ?? 0}', style: TextStyle(fontSize: 16.0, fontWeight: FontWeight.bold)),
SizedBox(height: 3.0),
Text('互关')
]),
),
GestureDetector(
onTap: () async {
// 关注
await Get.toNamed('/flow');
refreshData();
},
child: Column(children: [
Text('${followInfo.value?.followingCount ?? 0}', style: TextStyle(fontSize: 16.0, fontWeight: FontWeight.bold)),
SizedBox(height: 3.0),
Text('关注')
]),
),
GestureDetector(
onTap: () async {
await Get.toNamed('/fans');
refreshData();
},
child: Column(
children: [
Text(
'${followInfo.value?.followersCount ?? 0}',
style: const TextStyle(fontSize: 16.0, fontWeight: FontWeight.bold),
),
const SizedBox(height: 3.0),
const Text('粉丝'),
],
),
)
],
)),
);
}
Widget _buildOrderCard(BuildContext context) {
return Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(15.0),
boxShadow: [BoxShadow(color: Colors.black.withAlpha(10), offset: const Offset(0.0, 1.0), blurRadius: 2.0, spreadRadius: 0.0)],
),
clipBehavior: Clip.antiAlias,
child: Column(
children: [
GestureDetector(
child: Container(
padding: const EdgeInsets.all(10.0),
child: Row(
children: [
Row(
children: [
Image.asset('assets/images/more.png', width: 16.0),
const SizedBox(width: 5.0),
const Text('常用功能', style: TextStyle(fontSize: 15.0, fontWeight: FontWeight.bold)),
],
),
const Spacer(),
const Text('全部', style: TextStyle(color: Colors.grey, fontSize: 12.0)),
const Icon(Icons.arrow_forward_ios_rounded, color: Colors.grey, size: 12.0),
],
),
),
onTap: () {
Get.toNamed('/functions');
},
),
Padding(
padding: const EdgeInsets.all(10.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
_buildOrderIcon('assets/images/ico_order.png', '订单', () {
Get.toNamed('/myOrder');
}),
_buildOrderIcon('assets/images/ico_dhx.png', '余额logout', () {
showLogoutDialog(context);
}),
_buildOrderIcon('assets/images/ico_sh.png', '提现vloger', () {
Get.toNamed('/vloger');
}),
_buildOrderIcon('assets/images/ico_tgm.png', '推广码', () {
logger.e('推广码');
}),
],
),
),
],
),
);
}
Widget _buildOrderIcon(String assetPath, String label, VoidCallback onTap) {
return GestureDetector(
onTap: onTap,
child: Column(
children: [
Image.asset(assetPath, width: 24.0),
const SizedBox(height: 3.0),
Text(label),
],
),
);
}
}