aslan-flutter/lib/chatvibe_features/family/index_family_page.dart
2026-07-01 18:25:58 +08:00

531 lines
21 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter_ninepatch_image/flutter_ninepatch_image.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:aslan/chatvibe_ui/components/at_debounce_widget.dart';
import 'package:aslan/chatvibe_data/sources/repositories/family_repository_impl.dart';
import 'package:marquee/marquee.dart';
import 'package:provider/provider.dart';
import 'package:pull_to_refresh/pull_to_refresh.dart';
import 'package:aslan/app_localizations.dart';
import 'package:aslan/chatvibe_ui/components/at_compontent.dart';
import 'package:aslan/chatvibe_ui/components/text/at_text.dart';
import 'package:aslan/chatvibe_core/routes/at_fluro_navigator.dart';
import 'package:aslan/chatvibe_domain/models/res/at_family_home_list_res.dart';
import 'package:aslan/chatvibe_managers/rtc_manager.dart';
import 'package:aslan/chatvibe_features/family/family_route.dart';
import 'package:aslan/chatvibe_core/constants/at_global_config.dart';
import 'package:aslan/chatvibe_core/config/business_logic_strategy.dart';
import 'package:aslan/chatvibe_ui/widgets/country/at_country_flag_image.dart';
class IndexFamilyPage extends StatefulWidget {
const IndexFamilyPage({super.key});
@override
IndexFamilyPageState createState() => IndexFamilyPageState();
}
class IndexFamilyPageState extends State<IndexFamilyPage> {
final RefreshController _refreshController = RefreshController(
initialRefresh: false,
);
Records? familyBaseInfo;
/// 获取业务逻辑策略
BusinessLogicStrategy get _strategy => ATGlobalConfig.businessLogicStrategy;
@override
void initState() {
super.initState();
loadData();
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.transparent,
body: SafeArea(
top: false,
child: SmartRefresher(
enablePullDown: true,
enablePullUp: false,
controller: _refreshController,
onRefresh: () {
loadData();
},
onLoading: () {},
child: _buildContent(),
),
),
);
}
Widget _buildContent() {
return SingleChildScrollView(
child: Container(
padding: EdgeInsets.symmetric(horizontal: 10.w).copyWith(top: 5.w),
child: Column(
children: [
_buidFamilyInfo(),
SizedBox(height: 8.w),
_buidFamilyOnlineUser(),
SizedBox(height: 8.w),
_buiRoomList(),
],
),
),
);
}
_buidFamilyInfo() {
// 使用业务逻辑策略处理家族通知和等级
final displayLevel = _strategy.getFamilyDisplayLevel(
familyBaseInfo?.level ?? 0,
);
final familyNotice = _strategy.getFamilyNoticeDisplayText(
familyBaseInfo?.familyNotice,
context,
);
return SizedBox(
width: ScreenUtil().screenWidth,
child: NinePatchImage(
alignment: Alignment.center,
imageProvider: AssetImage(
_strategy.getFamilyLevelBackgroundImage(displayLevel),
),
sliceCachedKey: _strategy.getFamilyLevelBackgroundImage(displayLevel),
child: Column(
children: [
SizedBox(height: 5.w),
Row(
children: [
SizedBox(width: 5.w),
ATDebounceWidget(
child: Container(
margin: EdgeInsetsDirectional.only(start: 8.w, top: 5.w),
child: netImage(
height: 80.w,
width: 80.w,
borderRadius: BorderRadius.circular(5.w),
url: familyBaseInfo?.familyAvatar ?? "",
),
),
onTap: () {
if ((familyBaseInfo?.familyId ?? "").isNotEmpty) {
ATNavigatorUtils.push(
context,
"${FamilyRoute.familyInfo}?familyId=${familyBaseInfo?.familyId}",
replace: false,
);
}
},
),
SizedBox(width: 10.w),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
constraints: BoxConstraints(
maxWidth: 135.w,
maxHeight: 24.w,
),
child:
(familyBaseInfo?.familyName?.length ?? 0) > 12
? Marquee(
text: familyBaseInfo?.familyName ?? "",
style: TextStyle(
fontSize: 16.sp,
color: Colors.white,
fontWeight: FontWeight.bold,
decoration: TextDecoration.none,
),
scrollAxis: Axis.horizontal,
crossAxisAlignment: CrossAxisAlignment.start,
blankSpace: 40.0,
velocity: 40.0,
pauseAfterRound: Duration(seconds: 1),
accelerationDuration: Duration(seconds: 1),
accelerationCurve: Curves.easeOut,
decelerationDuration: Duration(
milliseconds: 500,
),
decelerationCurve: Curves.easeOut,
)
: Text(
familyBaseInfo?.familyName ?? "",
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontSize: 16.sp,
color: Colors.white,
fontWeight: FontWeight.bold,
decoration: TextDecoration.none,
),
),
),
SizedBox(height: 5.w),
Row(
children: [
text(
"ID:${familyBaseInfo?.familyAccount ?? ""}",
fontWeight: FontWeight.w600,
fontSize: 13.sp,
textColor: Colors.white,
),
SizedBox(width: 2.w),
Container(
alignment: AlignmentDirectional.center,
height: 25.w,
width: 66.w,
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage(
"atu_images/family/at_icon_family_member_btn_bg.png",
),
fit: BoxFit.fill,
),
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Image.asset(
height: 15.w,
"atu_images/family/at_icon_family_member_tag.png",
),
SizedBox(width: 3.w),
text(
"${familyBaseInfo?.memberCount ?? 0}",
fontWeight: FontWeight.w600,
fontSize: 13.sp,
textColor: Colors.white,
),
],
),
),
],
),
],
),
),
Image.asset(
"atu_images/family/at_icon_family_level_${familyBaseInfo?.level ?? 0}.png",
height: 80.w,
),
// Image.asset(
// "images/family/at_icon_family_rank_tag.png",
// height: 80.w,
// ),
SizedBox(width: 5.w),
],
),
SizedBox(height: 8.w),
Container(
margin: EdgeInsets.symmetric(horizontal: 15.w),
padding: EdgeInsets.symmetric(vertical: 5.w, horizontal: 6.w),
// 外部容器用于实现渐变边框
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8.w),
border: Border.all(color: Color(0xFFF5F5F5), width: 0.2.w),
),
child: Row(
children: [
Image.asset(
"atu_images/family/at_icon_announcement_tag2.png",
height: 22.w,
),
SizedBox(width: 3.w),
Expanded(
child: SizedBox(
height: 22.w,
child:
familyNotice.length > 20
? Marquee(
text: familyNotice,
style: TextStyle(
fontSize: 14.sp,
color: Colors.white,
fontWeight: FontWeight.bold,
decoration: TextDecoration.none,
),
scrollAxis: Axis.horizontal,
crossAxisAlignment: CrossAxisAlignment.start,
blankSpace: 40.0,
velocity: 40.0,
pauseAfterRound: Duration(seconds: 1),
accelerationDuration: Duration(seconds: 1),
accelerationCurve: Curves.easeOut,
decelerationDuration: Duration(
milliseconds: 500,
),
decelerationCurve: Curves.easeOut,
)
: Text(
familyNotice,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontSize: 14.sp,
color: Colors.white,
fontWeight: FontWeight.bold,
decoration: TextDecoration.none,
),
),
),
),
],
), // 背景色,
),
SizedBox(height: 10.w),
],
),
),
);
}
/// 获取显示的成员数量,根据业务逻辑策略限制
int _getDisplayMemberCount() {
final memberCount = familyBaseInfo?.displayMembers?.length ?? 0;
final maxDisplayCount = _strategy.getFamilyOnlineUserDisplayCount();
return memberCount > maxDisplayCount ? maxDisplayCount : memberCount;
}
_buidFamilyOnlineUser() {
// 使用业务逻辑策略处理家族等级
final displayLevel = _strategy.getFamilyDisplayLevel(
familyBaseInfo?.level ?? 0,
);
return ATDebounceWidget(
child: SizedBox(
width: ScreenUtil().screenWidth,
child: NinePatchImage(
alignment: Alignment.center,
imageProvider: AssetImage(
_strategy.getFamilyLevelBackgroundImage(displayLevel),
),
sliceCachedKey: _strategy.getFamilyLevelBackgroundImage(displayLevel),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(height: 8.w),
Row(
children: [
SizedBox(width: 10.w),
text(
ATAppLocalizations.of(context)!.onlineUsers(
"${familyBaseInfo?.onlineCount ?? 0}",
"${familyBaseInfo?.memberCount ?? 0}",
),
fontSize: 15.sp,
fontWeight: FontWeight.w600,
textColor: Colors.white,
),
Spacer(),
Icon(
Icons.keyboard_arrow_right,
size: 20.w,
color: Colors.white,
),
SizedBox(width: 8.w),
],
),
SizedBox(height: 3.w),
SizedBox(
height: 45.w,
child: ListView.separated(
scrollDirection: Axis.horizontal,
shrinkWrap: true,
itemCount: _getDisplayMemberCount(),
// 列表项数量,根据业务逻辑策略限制显示数量
padding: EdgeInsets.only(left: 15.w, right: 15.w),
itemBuilder: (context, index) {
return Stack(
alignment: AlignmentDirectional.bottomEnd,
children: [
netImage(
url:
familyBaseInfo?.displayMembers?[index].avatar ??
"",
width: 45.w,
height: 45.w,
shape: BoxShape.circle,
defaultImg:
"atu_images/general/at_icon_avar_defalt.png",
),
(familyBaseInfo?.displayMembers?[index].online ?? false)
? PositionedDirectional(
bottom: 1.w,
child: Image.asset(
"atu_images/family/at_icon_family_user_online_tag.png",
height: 15.w,
),
)
: Container(),
],
);
},
separatorBuilder: (BuildContext context, int index) {
return Container(width: 5.w);
},
),
),
SizedBox(height: 8.w),
],
),
),
),
onTap: () {
ATNavigatorUtils.push(
context,
"${FamilyRoute.familyMemberList}?familyId=${familyBaseInfo?.familyId}&myFamilyRole=${familyBaseInfo?.myFamilyRole}",
replace: false,
).then((result) {
loadData();
});
},
);
}
_buiRoomList() {
return GridView.builder(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: _strategy.getFamilyRoomGridCrossAxisCount(),
),
itemBuilder: (c, i) {
OnlineRooms? roomRes = familyBaseInfo?.onlineRooms?[i];
return GestureDetector(
child: Container(
margin: EdgeInsets.symmetric(horizontal: 5.w, vertical: 5.w),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12.w),
color: Colors.transparent,
),
child: Stack(
alignment: Alignment.bottomCenter,
children: [
netImage(
url: roomRes?.roomCover ?? "",
borderRadius: BorderRadius.circular(12.w),
width: 200.w,
height: 200.w,
),
Container(
padding: EdgeInsets.symmetric(vertical: 5.w),
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(12.w),
bottomRight: Radius.circular(12.w),
),
color: Colors.black38,
),
child: Row(
children: [
SizedBox(width: 10.w),
ATCountryFlagImage(
countryName: roomRes?.countryName,
width: 20.w,
height: 13.w,
borderRadius: BorderRadius.circular(2.w),
),
SizedBox(width: 5.w),
Expanded(
child: SizedBox(
height: 21.w,
child:
(roomRes?.roomName?.length ?? 0) > 10
? Marquee(
text: roomRes?.roomName ?? "",
style: TextStyle(
fontSize: 15.sp,
color: Color(0xffffffff),
fontWeight: FontWeight.w400,
decoration: TextDecoration.none,
),
scrollAxis: Axis.horizontal,
crossAxisAlignment:
CrossAxisAlignment.start,
blankSpace: 20.0,
velocity: 40.0,
pauseAfterRound: Duration(seconds: 1),
accelerationDuration: Duration(seconds: 1),
accelerationCurve: Curves.easeOut,
decelerationDuration: Duration(
milliseconds: 500,
),
decelerationCurve: Curves.easeOut,
)
: Text(
roomRes?.roomName ?? "",
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontSize: 15.sp,
color: Color(0xffffffff),
fontWeight: FontWeight.w400,
decoration: TextDecoration.none,
),
),
),
),
SizedBox(width: 5.w),
// 根据业务逻辑策略显示房间图标
if (roomRes?.existsPassword == false) ...[
Image.asset(
"atu_images/general/at_icon_online_user.gif",
width: 14.w,
height: 14.w,
),
SizedBox(width: 3.w),
text(
"${roomRes?.onlineQuantity ?? 0}",
fontSize: 12.sp,
),
] else if (_strategy.shouldShowPasswordRoomIcon()) ...[
// 显示密码房间图标
Image.asset(
"atu_images/index/at_icon_room_suo.png",
width: 20.w,
height: 20.w,
),
SizedBox(height: 10.w), // 占位符以保持布局一致
] else ...[
// 不显示任何图标,使用占位符保持布局
SizedBox(width: 20.w, height: 20.w),
SizedBox(height: 10.w),
],
SizedBox(width: 10.w),
],
),
),
],
),
),
onTap: () {
Provider.of<RealTimeCommunicationManager>(
context,
listen: false,
).joinRoom(context, roomRes?.roomId ?? "");
},
);
},
itemCount: familyBaseInfo?.onlineRooms?.length ?? 0,
);
}
void loadData() {
GroupRepository()
.familyHomeList(pageNo: 1)
.then((res) {
familyBaseInfo = res.records?.first;
_refreshController.refreshCompleted();
_refreshController.loadComplete();
setState(() {});
})
.catchError((e) {
_refreshController.loadNoData();
_refreshController.refreshCompleted();
});
}
}