初始化
This commit is contained in:
@@ -0,0 +1,173 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:hgdj/assets_tool/app_colors.dart';
|
||||
import 'package:hgdj/hj_utils/pay/pay_manager.dart';
|
||||
import 'package:hgdj/extension/extensions.dart';
|
||||
import 'package:hgdj/hj_utils/screen.dart';
|
||||
import 'package:hgdj/routers/jump_router.dart';
|
||||
import 'package:hgdj/tools_base/global_store/store.dart';
|
||||
import 'package:hgdj/tools_base/widget/sheet_handle_bar.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import '../model/im_group_list_model.dart';
|
||||
|
||||
class GroupBuyBottomSheet extends StatefulWidget {
|
||||
final IMGroupItemModel groupModel;
|
||||
|
||||
const GroupBuyBottomSheet({super.key, required this.groupModel});
|
||||
|
||||
@override
|
||||
State<GroupBuyBottomSheet> createState() => _GroupBuyBottomSheetState();
|
||||
}
|
||||
|
||||
class _GroupBuyBottomSheetState extends State<GroupBuyBottomSheet> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
globalStore.updateUserInfo();
|
||||
globalStore.refreshWallet();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Consumer<GlobalStore>(
|
||||
builder: (_, store, __) {
|
||||
final enough =
|
||||
(store.wallet?.amount ?? 0) >= (widget.groupModel.price ?? 0);
|
||||
return _buildNormal(enough, store);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildNormal(bool enough, GlobalStore store) {
|
||||
return Container(
|
||||
width: double.infinity,
|
||||
padding: EdgeInsets.symmetric(horizontal: 16, vertical: 18),
|
||||
decoration: BoxDecoration(
|
||||
color: AppColors.primaryColor,
|
||||
borderRadius: BorderRadius.vertical(top: Radius.circular(20)),
|
||||
),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const SheetHandleBar(),
|
||||
18.sizeBoxH,
|
||||
Text(
|
||||
'购买',
|
||||
style: TextStyle(
|
||||
color: Color(0xE5ffffff),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
36.sizeBoxH,
|
||||
Row(
|
||||
children: [
|
||||
Text(
|
||||
'解锁群聊',
|
||||
style: TextStyle(
|
||||
color: Color(0xE5ffffff),
|
||||
fontSize: 14,
|
||||
),
|
||||
),
|
||||
Spacer(),
|
||||
GestureDetector(
|
||||
onTap: () => pushToWalletPage(tabPosition: 1),
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
'${widget.groupModel.price ?? 0} 金币',
|
||||
style:
|
||||
TextStyle(color: AppColors.actionRed, fontSize: 14),
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
18.sizeBoxH,
|
||||
0.5.line,
|
||||
18.sizeBoxH,
|
||||
Row(
|
||||
children: [
|
||||
Text(
|
||||
'我的金币',
|
||||
style: TextStyle(
|
||||
color: Color(0xE5ffffff),
|
||||
fontSize: 14,
|
||||
),
|
||||
),
|
||||
Spacer(),
|
||||
Row(
|
||||
children: [
|
||||
Text(
|
||||
'${GlobalStore().wallet?.amount?.toDouble().fixed(2) ?? 0}',
|
||||
style: TextStyle(
|
||||
color: Color(0xE5ffffff),
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
12.sizeBoxW,
|
||||
InkWell(
|
||||
enableFeedback: false,
|
||||
onTap: () => pushToWalletPage(tabPosition: 1),
|
||||
child: Text(
|
||||
'充值',
|
||||
style: TextStyle(
|
||||
color: Color(0xffA4634D),
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w400,
|
||||
decoration: TextDecoration.underline,
|
||||
decorationColor: Color(0xffA4634D),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
18.sizeBoxH,
|
||||
GestureDetector(
|
||||
behavior: HitTestBehavior.translucent,
|
||||
onTap: () => _doPayAction(enough),
|
||||
child: Container(
|
||||
width: double.infinity,
|
||||
height: 44,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(3),
|
||||
color: AppColors.actionRed,
|
||||
),
|
||||
alignment: Alignment.center,
|
||||
child: Text(
|
||||
enough
|
||||
? '${widget.groupModel.price ?? 0} 金币/立即支付'
|
||||
: '余额不足,前往充值',
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w500),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _doPayAction(bool enough) async {
|
||||
if (!enough) {
|
||||
await pushToWalletPage(tabPosition: 1);
|
||||
return;
|
||||
}
|
||||
await PayManager().buy(
|
||||
widget.groupModel.id,
|
||||
ProductType.group,
|
||||
source: 'group_buy',
|
||||
onSuccess: (data) {
|
||||
globalStore.refreshWallet();
|
||||
Get.back(result: true);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:hgdj/tools_base/debug_log.dart';
|
||||
import 'package:hgdj/tools_base/global_store/store.dart';
|
||||
import 'package:hgdj/tools_base/toast.dart';
|
||||
import 'package:pull_to_refresh/pull_to_refresh.dart';
|
||||
|
||||
import '../../../../hj_utils/api_service/group_service.dart';
|
||||
import '../../../../tools_base/file_upload/file_upload_tool.dart';
|
||||
import '../../../../tools_base/file_upload/upload_result_model.dart';
|
||||
import '../../../comment/comment_input_view.dart';
|
||||
import '../model/im_group_list_model.dart';
|
||||
import '../model/im_message_resp.dart';
|
||||
|
||||
class GroupChatDetailLogic extends GetxController {
|
||||
final IMGroupItemModel model;
|
||||
|
||||
GroupChatDetailLogic(this.model);
|
||||
|
||||
int pageNum = 1;
|
||||
List<IMMessageModel>? msgList;
|
||||
RefreshController? refreshController;
|
||||
TextEditingController textEditController = TextEditingController();
|
||||
Rx<String?> selectedImagePath = Rx<String?>(null);
|
||||
RxBool isSendingMsg = false.obs;
|
||||
|
||||
@override
|
||||
void onReady() {
|
||||
refreshData();
|
||||
super.onReady();
|
||||
}
|
||||
|
||||
void refreshData() {
|
||||
_loadData();
|
||||
}
|
||||
|
||||
void loadMoreData() {
|
||||
_loadData(page: pageNum + 1);
|
||||
}
|
||||
|
||||
void _loadData({int page = 1, int size = 20}) async {
|
||||
try {
|
||||
final retResp = await GroupService.getMessages(model.groupId, page, size);
|
||||
pageNum = page;
|
||||
msgList ??= [];
|
||||
if (pageNum == 1) {
|
||||
msgList?.clear();
|
||||
}
|
||||
msgList?.addAll(retResp.list ?? []);
|
||||
retResp.hasNext == true
|
||||
? refreshController?.loadComplete()
|
||||
: refreshController?.loadNoData();
|
||||
} catch (e) {
|
||||
debugLog(e);
|
||||
refreshController?.loadComplete();
|
||||
}
|
||||
refreshController?.refreshCompleted();
|
||||
update();
|
||||
}
|
||||
|
||||
Future readySendMsg({bool? isSend}) async {
|
||||
if (isSend == true &&
|
||||
(textEditController.text.isNotEmpty ||
|
||||
selectedImagePath.value?.isNotEmpty == true)) {
|
||||
// 点击发送按钮有内容,直接发送内容, 否则弹出输入框
|
||||
sendMsgEvent();
|
||||
} else {
|
||||
final result = await Get.bottomSheet(
|
||||
CommentInputView(
|
||||
hint: "请输入消息",
|
||||
textCtr: textEditController,
|
||||
imgPath: selectedImagePath.value,
|
||||
onImgChange: (value) => selectedImagePath.value = value,
|
||||
),
|
||||
backgroundColor: Colors.transparent,
|
||||
barrierColor: Colors.transparent,
|
||||
enableDrag: false,
|
||||
settings: RouteSettings(name: CommentInputView.routeName),
|
||||
useRootNavigator: true,
|
||||
);
|
||||
if (result == true) {
|
||||
update();
|
||||
}
|
||||
sendMsgEvent();
|
||||
}
|
||||
}
|
||||
|
||||
Future sendMsgEvent() async {
|
||||
if (textEditController.text.isEmpty &&
|
||||
selectedImagePath.value?.isNotEmpty != true) {
|
||||
showToast("请输入消息内容");
|
||||
return;
|
||||
}
|
||||
if (isSendingMsg.value) return;
|
||||
isSendingMsg.value = true;
|
||||
String? sendImagePath;
|
||||
if (selectedImagePath.value?.isNotEmpty == true) {
|
||||
try {
|
||||
ImageUploadResultModel? imgResult =
|
||||
await FileUploadTool().uploadImage(selectedImagePath.value!);
|
||||
sendImagePath = imgResult?.coverImg ?? "";
|
||||
if (sendImagePath.isEmpty) {
|
||||
isSendingMsg.value = false;
|
||||
showToast("图片上传失败!");
|
||||
return;
|
||||
}
|
||||
} catch (e) {
|
||||
debugLog(e);
|
||||
isSendingMsg.value = false;
|
||||
showToast("图片上传失败!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
try {
|
||||
var ret = await GroupService.sendMessage(
|
||||
model.groupId, textEditController.text, sendImagePath);
|
||||
if (ret.isSuccess) {
|
||||
textEditController.text = "";
|
||||
selectedImagePath.value = null;
|
||||
showToast("消息已发送");
|
||||
if (ret.data is Map && (ret.data['message'] is Map)) {
|
||||
IMMessageModel sendModel =
|
||||
IMMessageModel.fromJson(ret.data['message']);
|
||||
sendModel.portrait = globalStore.meInfo?.portrait;
|
||||
sendModel.name = globalStore.meInfo?.name;
|
||||
msgList?.insert(0, sendModel);
|
||||
update();
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
showToast("消息发送失败!");
|
||||
debugLog(e);
|
||||
}
|
||||
isSendingMsg.value = false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:hgdj/hj_page/comment/widget/comment_foot_view.dart';
|
||||
|
||||
import 'package:hgdj/tools_base/refresh/pull_refresh.dart';
|
||||
|
||||
import '../model/im_group_list_model.dart';
|
||||
import 'soul_group_detail_logic.dart';
|
||||
import 'widget/chat_item_cell.dart';
|
||||
|
||||
class GroupChatDetailPage extends StatelessWidget {
|
||||
final IMGroupItemModel model;
|
||||
|
||||
const GroupChatDetailPage(this.model, {super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return GetBuilder<GroupChatDetailLogic>(
|
||||
global: false,
|
||||
init: GroupChatDetailLogic(model),
|
||||
builder: (logic) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(model.name ?? ""),
|
||||
),
|
||||
body: Column(
|
||||
children: [
|
||||
Expanded(
|
||||
child: pullYsRefresh(
|
||||
onInit: (ctr) => logic.refreshController = ctr,
|
||||
onRefresh: (ctr) => logic.refreshData(),
|
||||
onLoading: (ctr) => logic.loadMoreData(),
|
||||
child: ListView.builder(
|
||||
itemCount: logic.msgList?.length ?? 0,
|
||||
reverse: true,
|
||||
padding: EdgeInsets.only(bottom: 12, top: 12),
|
||||
itemBuilder: (context, index) {
|
||||
return ChatItemCell(model: logic.msgList![index]);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
Obx(
|
||||
() => CommentFootView(
|
||||
imgPath: logic.selectedImagePath.value,
|
||||
isSending: logic.isSendingMsg.value,
|
||||
onImgChange: (value) => logic.selectedImagePath.value = value,
|
||||
onComment: (isSend) => logic.readySendMsg(isSend: isSend),
|
||||
textCtr: logic.textEditController,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,276 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hgdj/assets_tool/app_colors.dart';
|
||||
import 'package:hgdj/routers/jump_router.dart';
|
||||
import 'package:hgdj/tools_base/widget/net_image_widget.dart';
|
||||
|
||||
import '../../../../../tools_base/global_store/store.dart';
|
||||
import 'package:hgdj/tools_base/widget/image_browser_page.dart';
|
||||
import '../../model/im_message_resp.dart';
|
||||
|
||||
class ChatItemCell extends StatefulWidget {
|
||||
final IMMessageModel? model;
|
||||
|
||||
ChatItemCell({super.key, this.model});
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() {
|
||||
return _ChatItemCellState();
|
||||
}
|
||||
}
|
||||
|
||||
class _ChatItemCellState extends State<ChatItemCell> {
|
||||
bool get isImg => widget.model?.image?.isNotEmpty == true;
|
||||
|
||||
bool get isMe => globalStore.isMe(widget.model?.uid);
|
||||
|
||||
double imageWidth = 173;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
}
|
||||
|
||||
void _showImageScan(String imageUrl) {
|
||||
if (imageUrl.isNotEmpty) {
|
||||
ImageBrowserPage.open([widget.model?.image ?? '']);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (isMe) {
|
||||
return _buildRightStyle();
|
||||
} else {
|
||||
return _buildLeftStyle();
|
||||
}
|
||||
}
|
||||
|
||||
Widget _buildLeftStyle() {
|
||||
return Container(
|
||||
padding: EdgeInsets.fromLTRB(0, 12, 0, 6),
|
||||
child: Column(
|
||||
children: [
|
||||
_buildTime(),
|
||||
Container(
|
||||
padding: EdgeInsets.fromLTRB(16, 0, 50, 0),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
pushToPersonCenter(widget.model?.uid);
|
||||
},
|
||||
child: SizedBox(
|
||||
width: 40,
|
||||
height: 40,
|
||||
child: NetworkImageLoader(
|
||||
imageUrl: widget.model?.portrait ?? "",
|
||||
width: 40,
|
||||
height: 40,
|
||||
borderRadius: 20,
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(width: 12),
|
||||
Flexible(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
widget.model?.name ?? "",
|
||||
style: TextStyle(
|
||||
color: Colors.white.withValues(alpha: 0.9),
|
||||
fontSize: 14,
|
||||
),
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
if (widget.model?.content?.isNotEmpty == true)
|
||||
Container(
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 20, vertical: 10),
|
||||
margin: EdgeInsets.only(top: 5),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white.withValues(alpha: 0.05),
|
||||
borderRadius: BorderRadius.only(
|
||||
bottomLeft: Radius.circular(12),
|
||||
bottomRight: Radius.circular(12),
|
||||
topRight: Radius.circular(12),
|
||||
topLeft: Radius.circular(2)),
|
||||
),
|
||||
child: Text(
|
||||
widget.model?.content ?? "",
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 14,
|
||||
),
|
||||
),
|
||||
),
|
||||
if (isImg)
|
||||
InkWell(
|
||||
enableFeedback: false,
|
||||
onTap: () {
|
||||
_showImageScan(widget.model?.image ?? "");
|
||||
},
|
||||
child: Container(
|
||||
margin: EdgeInsets.only(top: 5),
|
||||
alignment: Alignment.centerLeft,
|
||||
constraints: BoxConstraints(maxWidth: 173),
|
||||
child: _buildImageWidget(isLeft: true),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildRightStyle() {
|
||||
return Container(
|
||||
padding: EdgeInsets.fromLTRB(0, 12, 0, 6),
|
||||
child: Column(
|
||||
children: [
|
||||
_buildTime(),
|
||||
Container(
|
||||
padding: EdgeInsets.fromLTRB(50, 0, 16, 0),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
Flexible(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
children: [
|
||||
Text(
|
||||
widget.model?.name ?? "",
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 14,
|
||||
),
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
if (widget.model?.content?.isNotEmpty == true)
|
||||
Container(
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 20, vertical: 10),
|
||||
margin: EdgeInsets.only(top: 5),
|
||||
decoration: BoxDecoration(
|
||||
color: Color(0xff1DC194),
|
||||
borderRadius: BorderRadius.only(
|
||||
bottomLeft: Radius.circular(12),
|
||||
bottomRight: Radius.circular(12),
|
||||
topLeft: Radius.circular(12),
|
||||
topRight: Radius.circular(4)),
|
||||
),
|
||||
child: Text(
|
||||
widget.model?.content ?? "",
|
||||
style: TextStyle(
|
||||
color: Color(0xff141414),
|
||||
fontSize: 14,
|
||||
),
|
||||
),
|
||||
),
|
||||
if (isImg)
|
||||
InkWell(
|
||||
enableFeedback: false,
|
||||
onTap: () {
|
||||
_showImageScan(widget.model?.image ?? "");
|
||||
},
|
||||
child: Container(
|
||||
margin: EdgeInsets.only(top: 5),
|
||||
alignment: Alignment.centerRight,
|
||||
constraints: BoxConstraints(maxWidth: 173),
|
||||
child: _buildImageWidget(isLeft: false),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(width: 12),
|
||||
GestureDetector(
|
||||
onTap: () {},
|
||||
child: SizedBox(
|
||||
width: 40,
|
||||
height: 40,
|
||||
child: NetworkImageLoader(
|
||||
imageUrl: widget.model?.portrait,
|
||||
width: 40,
|
||||
height: 40,
|
||||
borderRadius: 20,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildImageWidget({bool isLeft = false}) {
|
||||
return Stack(
|
||||
children: [
|
||||
NetworkImageLoader(
|
||||
imageUrl: widget.model?.image ?? "",
|
||||
width: imageWidth,
|
||||
imgBorderRadius: BorderRadius.only(
|
||||
bottomLeft: Radius.circular(12),
|
||||
bottomRight: Radius.circular(12),
|
||||
topRight: Radius.circular(isLeft ? 12 : 0),
|
||||
topLeft: Radius.circular(isLeft ? 0 : 12),
|
||||
),
|
||||
),
|
||||
if (isLeft)
|
||||
Positioned(
|
||||
bottom: 12,
|
||||
left: 0,
|
||||
right: 0,
|
||||
child: Container(
|
||||
alignment: Alignment.bottomCenter,
|
||||
child: Container(
|
||||
width: 72,
|
||||
height: 26,
|
||||
alignment: Alignment.center,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(30),
|
||||
color: AppColors.actionRed,
|
||||
),
|
||||
child: Text(
|
||||
'查看原图',
|
||||
style: TextStyle(fontSize: 12, color: Colors.white),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildTime() {
|
||||
// if (widget.model?.isShowTime == true) {
|
||||
// return Container(
|
||||
// margin: EdgeInsets.fromLTRB(0, 12, 0, 12),
|
||||
// padding: EdgeInsets.symmetric(horizontal: 20, vertical: 2),
|
||||
// // decoration: BoxDecoration(
|
||||
// // borderRadius: BorderRadius.circular(30),
|
||||
// // color: Color(0xfff7f7f7).withValues(alpha: 0.42),
|
||||
// // ),
|
||||
// child: Text(
|
||||
// widget.model?.createAtDesc ?? "",
|
||||
// style: TextStyle(
|
||||
// color: Color(0xff666666),
|
||||
// fontSize: 12,
|
||||
// ),
|
||||
// ),
|
||||
// );
|
||||
// }
|
||||
return SizedBox();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
import 'package:get/get.dart';
|
||||
import 'package:hgdj/tools_base/debug_log.dart';
|
||||
import 'package:pull_to_refresh/pull_to_refresh.dart';
|
||||
|
||||
import '../../../hj_utils/api_service/group_service.dart';
|
||||
import 'model/im_group_list_model.dart';
|
||||
|
||||
class GroupChatLogic extends GetxController {
|
||||
int pageNum = 1;
|
||||
List<IMGroupItemModel>? groupList;
|
||||
RefreshController? refreshController;
|
||||
|
||||
@override
|
||||
void onReady() {
|
||||
refreshData();
|
||||
super.onReady();
|
||||
}
|
||||
|
||||
void refreshData() {
|
||||
_loadData();
|
||||
}
|
||||
|
||||
void loadMoreData() {
|
||||
_loadData(page: pageNum + 1);
|
||||
}
|
||||
|
||||
void _loadData({int page = 1}) async {
|
||||
try {
|
||||
final retResp = await GroupService.getList(page);
|
||||
pageNum = page;
|
||||
groupList ??= [];
|
||||
if (pageNum == 1) {
|
||||
groupList?.clear();
|
||||
}
|
||||
groupList?.addAll(retResp?.list ?? []);
|
||||
retResp?.hasNext == true
|
||||
? refreshController?.loadComplete()
|
||||
: refreshController?.loadNoData();
|
||||
} catch (e) {
|
||||
debugLog(e);
|
||||
refreshController?.loadComplete();
|
||||
}
|
||||
refreshController?.refreshCompleted();
|
||||
update();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:hgdj/hj_page/main_page/provider/bottom_bar_provider.dart';
|
||||
import 'package:hgdj/hj_utils/const.dart';
|
||||
import 'package:hgdj/tools_base/banner/ads_grid_view_widget.dart';
|
||||
import 'package:hgdj/tools_base/loading/loading_center_widget.dart';
|
||||
import 'package:hgdj/tools_base/refresh/pull_refresh.dart';
|
||||
|
||||
import 'group_chat_logic.dart';
|
||||
import 'widget/chat_group_cell.dart';
|
||||
|
||||
class GroupChatPage extends StatelessWidget {
|
||||
const GroupChatPage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return GetBuilder<GroupChatLogic>(
|
||||
global: false,
|
||||
init: GroupChatLogic(),
|
||||
builder: (logic) {
|
||||
return pullYsRefresh(
|
||||
onInit: (ctr) => logic.refreshController = ctr,
|
||||
onRefresh: (ctr) => logic.refreshData(),
|
||||
onLoading: (ctr) => logic.loadMoreData(),
|
||||
child: CustomScrollView(
|
||||
controller:
|
||||
CommunityBottomProvider().scrollCtr(MediaStyle.GroupChat, 0),
|
||||
slivers: [
|
||||
SliverToBoxAdapter(
|
||||
child: AdsGridViewWidget(
|
||||
6,
|
||||
accordingAdsType: true,
|
||||
padding: EdgeInsets.fromLTRB(16, 12, 16, 18),
|
||||
),
|
||||
),
|
||||
if (logic.groupList == null)
|
||||
SliverToBoxAdapter(child: LoadingCenterWidget(height: 400))
|
||||
else if (logic.groupList!.isEmpty)
|
||||
SliverToBoxAdapter(
|
||||
child: SizedBox(
|
||||
height: 400,
|
||||
child: CErrorWidget(
|
||||
retryOnTap: () => logic.refreshData(),
|
||||
),
|
||||
),
|
||||
)
|
||||
else
|
||||
SliverList.builder(
|
||||
itemBuilder: (ctx, index) =>
|
||||
ChatGroupCell(logic.groupList![index]),
|
||||
itemCount: logic.groupList!.length,
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
class IMGroupListModel {
|
||||
bool? hasNext;
|
||||
List<IMGroupItemModel>? list;
|
||||
int? total;
|
||||
|
||||
IMGroupListModel({this.hasNext, this.list, this.total});
|
||||
|
||||
IMGroupListModel.fromJson(Map<String, dynamic> json) {
|
||||
hasNext = json['hasNext'];
|
||||
if (json['list'] != null) {
|
||||
list = <IMGroupItemModel>[];
|
||||
json['list'].forEach((v) {
|
||||
list!.add(new IMGroupItemModel.fromJson(v));
|
||||
});
|
||||
}
|
||||
total = json['total'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = new Map<String, dynamic>();
|
||||
data['hasNext'] = this.hasNext;
|
||||
if (this.list != null) {
|
||||
data['list'] = this.list!.map((v) => v.toJson()).toList();
|
||||
}
|
||||
data['total'] = this.total;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
class IMGroupItemModel {
|
||||
String? cover;
|
||||
String? createdAt;
|
||||
|
||||
///成员数量(假的)
|
||||
int? fakeMemberNum;
|
||||
int? groupId;
|
||||
String? id;
|
||||
|
||||
///成员数量(真实)
|
||||
int? memberNum;
|
||||
String? name;
|
||||
|
||||
///加入群聊价格 0-免费
|
||||
int? price;
|
||||
String? summary;
|
||||
String? updatedAt;
|
||||
|
||||
IMGroupItemModel(
|
||||
{this.cover,
|
||||
this.createdAt,
|
||||
this.fakeMemberNum,
|
||||
this.groupId,
|
||||
this.id,
|
||||
this.memberNum,
|
||||
this.name,
|
||||
this.price,
|
||||
this.summary,
|
||||
this.updatedAt});
|
||||
|
||||
IMGroupItemModel.fromJson(Map<String, dynamic> json) {
|
||||
cover = json['cover'];
|
||||
createdAt = json['createdAt'];
|
||||
fakeMemberNum = json['fakeMemberNum'];
|
||||
groupId = json['groupId'];
|
||||
id = json['id'];
|
||||
memberNum = json['memberNum'];
|
||||
name = json['name'];
|
||||
price = json['price'];
|
||||
summary = json['summary'];
|
||||
updatedAt = json['updatedAt'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = new Map<String, dynamic>();
|
||||
data['cover'] = this.cover;
|
||||
data['createdAt'] = this.createdAt;
|
||||
data['fakeMemberNum'] = this.fakeMemberNum;
|
||||
data['groupId'] = this.groupId;
|
||||
data['id'] = this.id;
|
||||
data['memberNum'] = this.memberNum;
|
||||
data['name'] = this.name;
|
||||
data['price'] = this.price;
|
||||
data['summary'] = this.summary;
|
||||
data['updatedAt'] = this.updatedAt;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
class IMMessageResp {
|
||||
bool? hasNext;
|
||||
List<IMMessageModel>? list;
|
||||
int? total;
|
||||
|
||||
IMMessageResp({this.hasNext, this.list, this.total});
|
||||
|
||||
IMMessageResp.fromJson(Map<String, dynamic> json) {
|
||||
hasNext = json['hasNext'];
|
||||
if (json['list'] is List) {
|
||||
list = <IMMessageModel>[];
|
||||
json['list'].forEach((v) {
|
||||
list!.add(IMMessageModel.fromJson(v));
|
||||
});
|
||||
}
|
||||
total = json['total'];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class IMMessageModel {
|
||||
|
||||
String? id;
|
||||
int? groupId;
|
||||
int? uid;
|
||||
String? name;
|
||||
String? gender;
|
||||
String? portrait;
|
||||
String? content;
|
||||
String? image;
|
||||
String? createdAt;
|
||||
|
||||
|
||||
IMMessageModel.fromJson(Map<String, dynamic> json) {
|
||||
id = json['id'];
|
||||
groupId = json['groupId'];
|
||||
uid = json['uid'];
|
||||
name = json['name'];
|
||||
// gender = json['gender'];
|
||||
portrait = json['portrait'];
|
||||
content = json['content'];
|
||||
image = json['image'];
|
||||
createdAt = json['createdAt'];
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:hgdj/tools_base/toast.dart';
|
||||
import 'package:hgdj/hj_utils/screen.dart';
|
||||
import 'package:hgdj/tools_base/debug_log.dart';
|
||||
import 'package:hgdj/tools_base/global_store/store.dart';
|
||||
import 'package:hgdj/tools_base/loading/loading_alert_widget.dart';
|
||||
|
||||
import '../../../../alert/mine/vip_level_dialog.dart';
|
||||
import '../../../../assets_tool/app_colors.dart';
|
||||
import '../../../../hj_utils/api_service/group_service.dart';
|
||||
import '../../../../tools_base/widget/header_widget.dart';
|
||||
import '../alert/group_buy_bottom_sheet.dart';
|
||||
import '../detail/soul_group_detail_page.dart';
|
||||
import '../model/im_group_list_model.dart';
|
||||
import 'package:hgdj/extension/extensions.dart';
|
||||
|
||||
class ChatGroupCell extends StatefulWidget {
|
||||
final IMGroupItemModel model;
|
||||
|
||||
ChatGroupCell(this.model, {super.key});
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() {
|
||||
return _ChatGroupCellState();
|
||||
}
|
||||
}
|
||||
|
||||
class _ChatGroupCellState extends State<ChatGroupCell> {
|
||||
IMGroupItemModel get model => widget.model;
|
||||
|
||||
void _addGroupEvent() async {
|
||||
if (!globalStore.isVIPTopLevel) {
|
||||
showVipLevelDialog('本内容需要开通至尊VIP会员\n\n开通会员 即可畅享高级群聊特权');
|
||||
return;
|
||||
}
|
||||
try {
|
||||
LoadingAlertWidget.show();
|
||||
final retResp = await GroupService.getHasJoin(model.groupId);
|
||||
LoadingAlertWidget.cancel();
|
||||
if (retResp.isSuccess) {
|
||||
int status = retResp.data['status']; // 0-已被禁言 1-可发言 2-未加入
|
||||
if (status == 0) {
|
||||
showToast("您已被禁言");
|
||||
} else if (status == 1) {
|
||||
Get.to(GroupChatDetailPage(model));
|
||||
} else if (status == 2) {
|
||||
var ret = await Get.bottomSheet(
|
||||
GroupBuyBottomSheet(groupModel: widget.model));
|
||||
if (ret == true) {
|
||||
Get.to(GroupChatDetailPage(model));
|
||||
}
|
||||
} else {
|
||||
showToast("群未知状态");
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
LoadingAlertWidget.cancel();
|
||||
showToast("网络数据异常");
|
||||
debugLog(e);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
margin: EdgeInsets.only(left: 16, right: 16, bottom: 12),
|
||||
padding: EdgeInsets.all(12),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white.withValues(alpha: .05),
|
||||
borderRadius: BorderRadius.circular(6),
|
||||
),
|
||||
child: InkWell(
|
||||
enableFeedback: false,
|
||||
onTap: _addGroupEvent,
|
||||
child: Row(
|
||||
children: [
|
||||
HeaderWidget(
|
||||
headPath: model.cover ?? '',
|
||||
level: 1,
|
||||
headWidth: 64,
|
||||
headHeight: 64,
|
||||
isCircle: false,
|
||||
radius: 32,
|
||||
),
|
||||
12.sizeBoxW,
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(
|
||||
model.name ?? '',
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w500),
|
||||
),
|
||||
2.sizeBoxH,
|
||||
Text(
|
||||
model.summary ?? '',
|
||||
maxLines: 1,
|
||||
style: TextStyle(
|
||||
color: Colors.white.withValues(alpha: 0.55),
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
6.sizeBoxH,
|
||||
Row(
|
||||
children: [
|
||||
Text(
|
||||
'ID: ${model.groupId ?? 0} ${model.fakeMemberNum.countStr}人在玩',
|
||||
style: TextStyle(
|
||||
color: Colors.white.withValues(alpha: 0.55),
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
Spacer(),
|
||||
GestureDetector(
|
||||
onTap: _addGroupEvent,
|
||||
child: Container(
|
||||
width: 52,
|
||||
height: 24,
|
||||
alignment: Alignment.center,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(3),
|
||||
color: AppColors.actionRed),
|
||||
child: Text(
|
||||
'加入群聊',
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 10,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user