merge
This commit is contained in:
parent
39d621e5ad
commit
51ad2614f0
151
lib/IM/im_group_listeners.dart
Normal file
151
lib/IM/im_group_listeners.dart
Normal file
@ -0,0 +1,151 @@
|
||||
import 'package:logger/logger.dart';
|
||||
import 'package:tencent_cloud_chat_sdk/enum/V2TimGroupListener.dart';
|
||||
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_change_info.dart';
|
||||
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_member_change_info.dart';
|
||||
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_member_info.dart';
|
||||
import 'package:tencent_cloud_chat_sdk/models/v2_tim_topic_info.dart';
|
||||
import 'package:tencent_cloud_chat_sdk/native_im/adapter/tim_manager.dart';
|
||||
|
||||
final logger = Logger();
|
||||
|
||||
class ImGroupListeners {
|
||||
ImGroupListeners();
|
||||
|
||||
late final V2TimGroupListener _listener;
|
||||
|
||||
void register() {
|
||||
_listener = V2TimGroupListener(
|
||||
onGroupCreated: (String groupID) {
|
||||
logger.i('群被创建: $groupID');
|
||||
onGroupCreated(groupID);
|
||||
},
|
||||
onGroupDismissed: (String groupID, V2TimGroupMemberInfo opUser) {
|
||||
logger.i('群组被解散: $groupID, 操作人: ${opUser.nickName}');
|
||||
onGroupDismissed(groupID, opUser);
|
||||
},
|
||||
onGroupRecycled: (String groupID, V2TimGroupMemberInfo opUser) {
|
||||
logger.i('群组被回收: $groupID, 操作人: ${opUser.nickName}');
|
||||
},
|
||||
onGroupInfoChanged: (String groupID, List<V2TimGroupChangeInfo?> changeInfos) {
|
||||
logger.i('群信息变更: $groupID, $changeInfos');
|
||||
onGroupInfoChanged(groupID, changeInfos);
|
||||
},
|
||||
onMemberEnter: (String groupID, List<V2TimGroupMemberInfo> memberList) {
|
||||
logger.i('成员加入群 $groupID: ${memberList.map((e) => e.userID).join(', ')}');
|
||||
onMemberEnter(groupID, memberList);
|
||||
},
|
||||
onMemberLeave: (String groupID, V2TimGroupMemberInfo member) {
|
||||
logger.i('成员离开群 $groupID: ${member.userID}');
|
||||
onMemberLeave(groupID, member);
|
||||
},
|
||||
onMemberInvited: (String groupID, V2TimGroupMemberInfo opUser, List<V2TimGroupMemberInfo> memberList) {
|
||||
logger.i('成员被邀请 $groupID, inviter: ${opUser.userID}, members: ${memberList.map((e) => e.userID).join(', ')}');
|
||||
onMemberInvited(groupID, memberList);
|
||||
},
|
||||
onMemberKicked: (String groupID, V2TimGroupMemberInfo opUser, List<V2TimGroupMemberInfo> memberList) {
|
||||
logger.i('成员被踢 $groupID, opUser: ${opUser.userID}, members: ${memberList.map((e) => e.userID).join(', ')}');
|
||||
onMemberKicked(groupID, memberList);
|
||||
},
|
||||
onMemberInfoChanged: (String groupID, List<V2TimGroupMemberChangeInfo> v2TIMGroupMemberChangeInfoList) {
|
||||
logger.i('成员信息变更: $groupID, $v2TIMGroupMemberChangeInfoList');
|
||||
onMemberInfoChanged(groupID, v2TIMGroupMemberChangeInfoList);
|
||||
},
|
||||
onQuitFromGroup: (String groupID) {
|
||||
logger.i('主动退出群 $groupID');
|
||||
onQuitFromGroup(groupID);
|
||||
},
|
||||
onReceiveJoinApplication: (String groupID, V2TimGroupMemberInfo member, String opReason) {
|
||||
logger.i('收到入群申请 $groupID, member: ${member.userID}, reason: $opReason');
|
||||
onReceiveJoinApplication(groupID, member, opReason);
|
||||
},
|
||||
onApplicationProcessed: (String groupID, V2TimGroupMemberInfo opUser, bool isAgreeJoin, String opReason) {
|
||||
logger.i('入群申请已处理 $groupID, opUser: ${opUser.userID}, isAgree: $isAgreeJoin, reason: $opReason');
|
||||
onApplicationProcessed(groupID, opUser, isAgreeJoin, opUser);
|
||||
},
|
||||
onGrantAdministrator: (String groupID, V2TimGroupMemberInfo opUser, List<V2TimGroupMemberInfo> memberList) {
|
||||
logger.i('被授予管理员 $groupID, opUser: ${opUser.userID}, members: ${memberList.map((e) => e.userID).join(', ')}');
|
||||
onGrantAdministrator(groupID, opUser, memberList);
|
||||
},
|
||||
onRevokeAdministrator: (String groupID, V2TimGroupMemberInfo opUser, List<V2TimGroupMemberInfo> memberList) {
|
||||
logger.i('管理员权限被撤销 $groupID, opUser: ${opUser.userID}, members: ${memberList.map((e) => e.userID).join(', ')}');
|
||||
onRevokeAdministrator(groupID, opUser, memberList);
|
||||
},
|
||||
onReceiveRESTCustomData: (String groupID, String customData) {
|
||||
logger.i('收到自定义数据 $groupID: $customData');
|
||||
onReceiveRESTCustomData(groupID, customData);
|
||||
},
|
||||
onGroupAttributeChanged: (String groupID, Map<String, String> groupAttributeMap) {
|
||||
logger.i('群属性变更 $groupID: $groupAttributeMap');
|
||||
},
|
||||
onAllGroupMembersMuted: (String groupID, bool isMute) {
|
||||
logger.i('全体禁言状态变更 $groupID: $isMute');
|
||||
},
|
||||
onMemberMarkChanged: (String groupID, List<String> memberIDList, int markType, bool enableMark) {
|
||||
logger.i('成员标记变更 $groupID, members: ${memberIDList.join(', ')}, type: $markType, enable: $enableMark');
|
||||
},
|
||||
onGroupCounterChanged: (String groupID, String key, int newValue) {
|
||||
logger.i('群计数器变更 $groupID, key: $key, value: $newValue');
|
||||
},
|
||||
onTopicCreated: (String groupID, String topicID) {
|
||||
logger.i('话题创建 $groupID, topic: $topicID');
|
||||
},
|
||||
onTopicDeleted: (String groupID, List<String> topicIDList) {
|
||||
logger.i('话题删除 $groupID, topics: ${topicIDList.join(', ')}');
|
||||
},
|
||||
onTopicInfoChanged: (String groupID, V2TimTopicInfo topicInfo) {
|
||||
logger.i('话题信息变更 $groupID, topic: ${topicInfo.topicID}');
|
||||
},
|
||||
);
|
||||
|
||||
TIMManager.instance.addGroupListener(listener: _listener);
|
||||
|
||||
logger.i("群组监听器已注册");
|
||||
}
|
||||
|
||||
void unregister() {
|
||||
TIMManager.instance.removeGroupListener(listener: _listener);
|
||||
logger.i("群组监听器已移除");
|
||||
}
|
||||
|
||||
// 新群被创建
|
||||
void onGroupCreated(String groupID) {}
|
||||
|
||||
//解散群
|
||||
void onGroupDismissed(String groupID, V2TimGroupMemberInfo opUser) {}
|
||||
|
||||
// 群信息变更
|
||||
void onGroupInfoChanged(String groupID, List<V2TimGroupChangeInfo?> changeInfos) {}
|
||||
|
||||
// 成员加入群
|
||||
void onMemberEnter(String groupID, List<V2TimGroupMemberInfo> memberList) {}
|
||||
|
||||
// 成员离开群
|
||||
void onMemberLeave(String groupID, V2TimGroupMemberInfo member) {}
|
||||
|
||||
// 成员被邀请入群
|
||||
void onMemberInvited(String groupID, List<V2TimGroupMemberInfo> memberList) {}
|
||||
|
||||
// 成员被踢出群
|
||||
void onMemberKicked(String groupID, List<V2TimGroupMemberInfo> memberList) {}
|
||||
|
||||
// 成员信息变更
|
||||
void onMemberInfoChanged(String groupID, List<V2TimGroupMemberChangeInfo> v2timGroupMemberChangeInfoList) {}
|
||||
|
||||
// 主动退出群
|
||||
void onQuitFromGroup(String groupID) {}
|
||||
|
||||
// 入群申请
|
||||
void onReceiveJoinApplication(String groupID, V2TimGroupMemberInfo member, String opReason) {}
|
||||
|
||||
// 处理入群申请处理结果
|
||||
void onApplicationProcessed(String groupID, V2TimGroupMemberInfo opUser, bool isAgreeJoin, V2TimGroupMemberInfo opUser2) {}
|
||||
|
||||
// 册封管理员
|
||||
void onGrantAdministrator(String groupID, V2TimGroupMemberInfo opUser, List<V2TimGroupMemberInfo> memberList) {}
|
||||
|
||||
// 移除管理员权限
|
||||
void onRevokeAdministrator(String groupID, V2TimGroupMemberInfo opUser, List<V2TimGroupMemberInfo> memberList) {}
|
||||
|
||||
// 收到自定义消息
|
||||
void onReceiveRESTCustomData(String groupID, String customData) {}
|
||||
}
|
@ -7,6 +7,7 @@ import 'package:loopin/IM/controller/tab_bar_controller.dart';
|
||||
import 'package:loopin/IM/global_badge.dart';
|
||||
import 'package:loopin/IM/im_core.dart';
|
||||
import 'package:loopin/IM/im_friend_listeners.dart';
|
||||
import 'package:loopin/IM/im_group_listeners.dart';
|
||||
import 'package:loopin/IM/im_message_listeners.dart';
|
||||
import 'package:loopin/IM/im_result.dart';
|
||||
import 'package:loopin/IM/push_service.dart';
|
||||
@ -15,7 +16,9 @@ import 'package:loopin/utils/wxsdk.dart';
|
||||
import 'package:tencent_cloud_chat_sdk/enum/friend_application_type_enum.dart';
|
||||
import 'package:tencent_cloud_chat_sdk/enum/friend_response_type_enum.dart';
|
||||
import 'package:tencent_cloud_chat_sdk/enum/friend_type_enum.dart';
|
||||
import 'package:tencent_cloud_chat_sdk/enum/group_add_opt_enum.dart';
|
||||
import 'package:tencent_cloud_chat_sdk/enum/history_msg_get_type_enum.dart';
|
||||
import 'package:tencent_cloud_chat_sdk/manager/v2_tim_group_manager.dart';
|
||||
import 'package:tencent_cloud_chat_sdk/models/v2_tim_callback.dart';
|
||||
import 'package:tencent_cloud_chat_sdk/models/v2_tim_conversation.dart';
|
||||
import 'package:tencent_cloud_chat_sdk/models/v2_tim_conversation_filter.dart';
|
||||
@ -27,6 +30,7 @@ import 'package:tencent_cloud_chat_sdk/models/v2_tim_follow_type_check_result.da
|
||||
import 'package:tencent_cloud_chat_sdk/models/v2_tim_friend_info.dart';
|
||||
import 'package:tencent_cloud_chat_sdk/models/v2_tim_friend_info_result.dart';
|
||||
import 'package:tencent_cloud_chat_sdk/models/v2_tim_friend_operation_result.dart';
|
||||
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_member.dart';
|
||||
import 'package:tencent_cloud_chat_sdk/models/v2_tim_message.dart';
|
||||
import 'package:tencent_cloud_chat_sdk/models/v2_tim_message_change_info.dart';
|
||||
import 'package:tencent_cloud_chat_sdk/models/v2_tim_message_search_param.dart';
|
||||
@ -82,9 +86,13 @@ class ImService {
|
||||
// 登录成功后注册高级消息监听器
|
||||
final messageService = ImMessageListenerService();
|
||||
Get.put<ImMessageListenerService>(messageService, permanent: true);
|
||||
|
||||
await messageService.init();
|
||||
|
||||
// 注册群监听器
|
||||
final groupListener = ImGroupListeners();
|
||||
Get.put<ImGroupListeners>(groupListener, permanent: true);
|
||||
groupListener.register();
|
||||
|
||||
// 注册关系链监听器
|
||||
final friendListener = ImFriendListeners();
|
||||
Get.put<ImFriendListeners>(friendListener, permanent: true);
|
||||
@ -122,6 +130,10 @@ class ImService {
|
||||
Get.find<ImFriendListeners>().unregister();
|
||||
await Get.delete<ImFriendListeners>(force: true);
|
||||
|
||||
// 移除群监听器
|
||||
Get.find<ImGroupListeners>().unregister();
|
||||
await Get.delete<ImGroupListeners>(force: true);
|
||||
|
||||
/// 清理tabbar
|
||||
Get.find<TabBarController>().badgeMap.clear();
|
||||
|
||||
@ -721,4 +733,39 @@ class ImService {
|
||||
);
|
||||
return ImResult.wrap(res);
|
||||
}
|
||||
|
||||
/// 创建群
|
||||
Future<ImResult<String>> createGroup({
|
||||
String? groupID,
|
||||
required String groupType,
|
||||
required String groupName,
|
||||
String? notification,
|
||||
String? introduction,
|
||||
String? faceUrl,
|
||||
bool? isAllMuted,
|
||||
bool isSupportTopic = false,
|
||||
GroupAddOptTypeEnum? addOpt,
|
||||
List<V2TimGroupMember>? memberList,
|
||||
GroupAddOptTypeEnum? approveOpt,
|
||||
bool? isEnablePermissionGroup,
|
||||
int? defaultPermissions,
|
||||
}) async {
|
||||
final res = await V2TIMGroupManager().createGroup(
|
||||
groupID: groupID,
|
||||
groupType: groupType,
|
||||
groupName: groupName,
|
||||
notification: notification, // 群公告
|
||||
introduction: introduction, // 群简介
|
||||
faceUrl: faceUrl, // 群头像
|
||||
isAllMuted: isAllMuted, // true=全员禁言
|
||||
isSupportTopic: isSupportTopic, // 是否支持话题
|
||||
addOpt: addOpt, // 加群方式(非直播群有效)
|
||||
memberList: memberList, // 初始群成员(不支持直播群)
|
||||
approveOpt: approveOpt, //入群申请的处理方式(一般和 addOpt 配合使用)对 Work / Public 群有用
|
||||
isEnablePermissionGroup: isEnablePermissionGroup, // 是否开启权限组
|
||||
defaultPermissions: defaultPermissions, // 默认权限配置,搭配 isEnablePermissionGroup 使用
|
||||
);
|
||||
|
||||
return ImResult.wrap(res);
|
||||
}
|
||||
}
|
||||
|
@ -32,7 +32,15 @@ class _LayoutState extends State<Layout> {
|
||||
VideoModuleController videoModuleController = Get.put(VideoModuleController());
|
||||
|
||||
// page页面
|
||||
List pageList = [VideoPage(), IndexPage(), UploadVideoPage(), ChatPage(), MyPage()];
|
||||
List pageList = [
|
||||
VideoPage(),
|
||||
IndexPage(),
|
||||
UploadVideoPage(
|
||||
visible: false,
|
||||
),
|
||||
ChatPage(),
|
||||
MyPage()
|
||||
];
|
||||
// tabs选项
|
||||
List navItems = [
|
||||
BottomNavigationBarItem(icon: Icon(Icons.play_circle_outline), label: '视频'),
|
||||
@ -131,7 +139,9 @@ class _LayoutState extends State<Layout> {
|
||||
),
|
||||
Offstage(
|
||||
offstage: videoModuleController.layoutPageCurrent.value != 2,
|
||||
child: UploadVideoPage(), // 不需要保活
|
||||
child: UploadVideoPage(
|
||||
visible: videoModuleController.layoutPageCurrent.value == 2,
|
||||
), // 不需要保活
|
||||
),
|
||||
Offstage(
|
||||
offstage: videoModuleController.layoutPageCurrent.value != 3,
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,16 @@
|
||||
// 创建群聊
|
||||
import 'package:easy_refresh/easy_refresh.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:loopin/IM/controller/im_user_info_controller.dart';
|
||||
import 'package:loopin/IM/im_service.dart';
|
||||
import 'package:loopin/components/network_or_asset_image.dart';
|
||||
import 'package:loopin/styles/index.dart';
|
||||
import 'package:tencent_cloud_chat_sdk/enum/group_member_role_enum.dart';
|
||||
import 'package:tencent_cloud_chat_sdk/enum/group_type.dart';
|
||||
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_member.dart';
|
||||
import 'package:tencent_cloud_chat_sdk/models/v2_tim_user_full_info.dart';
|
||||
import 'package:tencent_cloud_chat_sdk/web/compatible_models/v2_tim_conversation.dart';
|
||||
|
||||
class StartGroupChatPage extends StatefulWidget {
|
||||
const StartGroupChatPage({super.key});
|
||||
@ -11,11 +22,12 @@ class StartGroupChatPage extends StatefulWidget {
|
||||
class _StartGroupChatPageState extends State<StartGroupChatPage> {
|
||||
final TextEditingController _searchController = TextEditingController();
|
||||
|
||||
List<Map<String, dynamic>> dataList = [];
|
||||
List<Map<String, dynamic>> filteredList = [];
|
||||
List<V2TimUserFullInfo> dataList = [];
|
||||
List<V2TimUserFullInfo> filteredList = [];
|
||||
Set<String> selectedIds = {}; // 已选中的用户 id
|
||||
int page = 1;
|
||||
String page = '';
|
||||
bool hasMore = true;
|
||||
bool isLoading = true;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
@ -29,29 +41,38 @@ class _StartGroupChatPageState extends State<StartGroupChatPage> {
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
// 分页获取陌关注列表数据
|
||||
Future<void> _loadData({bool reset = false}) async {
|
||||
if (reset) {
|
||||
page = 1;
|
||||
page = '';
|
||||
hasMore = true;
|
||||
dataList.clear();
|
||||
}
|
||||
|
||||
// 模拟网络请求
|
||||
await Future.delayed(const Duration(seconds: 1));
|
||||
|
||||
List<Map<String, dynamic>> newItems = List.generate(
|
||||
10,
|
||||
(index) => {"nickName": "用户 ${(page - 1) * 10 + index + 1}", "id": "${page}_$index"},
|
||||
final res = await ImService.instance.getMutualFollowersList(
|
||||
nextCursor: page,
|
||||
);
|
||||
if (res.success && res.data != null) {
|
||||
final userInfoList = res.data!.userFullInfoList ?? [];
|
||||
final isFinished = res.data!.nextCursor == null || res.data!.nextCursor!.isEmpty;
|
||||
logger.w('获取成功:${res.data!.nextCursor},是否还有更多:$isFinished');
|
||||
|
||||
if (newItems.isEmpty) {
|
||||
hasMore = false;
|
||||
if (isFinished) {
|
||||
setState(() {
|
||||
hasMore = false;
|
||||
});
|
||||
// 加载没数据了
|
||||
page = '';
|
||||
} else {
|
||||
page = res.data!.nextCursor ?? '';
|
||||
}
|
||||
logger.i('获取数据成功:$userInfoList');
|
||||
setState(() {
|
||||
dataList.addAll(userInfoList);
|
||||
_applySearch(_searchController.text);
|
||||
});
|
||||
} else {
|
||||
dataList.addAll(newItems);
|
||||
page++;
|
||||
logger.e('获取数据失败:${res.desc}');
|
||||
}
|
||||
|
||||
_applySearch(_searchController.text);
|
||||
}
|
||||
|
||||
void _applySearch(String query) {
|
||||
@ -59,7 +80,7 @@ class _StartGroupChatPageState extends State<StartGroupChatPage> {
|
||||
if (query.isEmpty) {
|
||||
filteredList = List.from(dataList);
|
||||
} else {
|
||||
filteredList = dataList.where((item) => item["nickName"].toString().contains(query.trim())).toList();
|
||||
filteredList = dataList.where((item) => (item.nickName ?? '').contains(query.trim())).toList();
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -74,6 +95,77 @@ class _StartGroupChatPageState extends State<StartGroupChatPage> {
|
||||
});
|
||||
}
|
||||
|
||||
/// 创建群聊
|
||||
void createGroup(Set<String> selectedIds) async {
|
||||
// dataList是原始数据List<V2TimUserFullInfo> dataList = [];
|
||||
// 通过dataList和selectedIds来构建memberList
|
||||
final ctl = Get.find<ImUserInfoController>();
|
||||
final memberList = dataList
|
||||
.where((user) => selectedIds.contains(user.userID))
|
||||
.map((user) => V2TimGroupMember(
|
||||
userID: user.userID!,
|
||||
role: GroupMemberRoleTypeEnum.V2TIM_GROUP_MEMBER_ROLE_MEMBER, // 加群的成员角色(默认普通成员)
|
||||
))
|
||||
.toList();
|
||||
final self = V2TimGroupMember(
|
||||
userID: ctl.userID.value,
|
||||
role: GroupMemberRoleTypeEnum.V2TIM_GROUP_MEMBER_ROLE_OWNER, // 建群的人为群主
|
||||
);
|
||||
memberList.insert(0, self);
|
||||
final groupName = buildGroupName(selectedIds);
|
||||
final res = await ImService.instance.createGroup(groupType: GroupType.Work, groupName: groupName, memberList: memberList);
|
||||
if (res.success) {
|
||||
final groupID = res.data;
|
||||
logger.w(groupID);
|
||||
final V2TimConversation conv = V2TimConversation(conversationID: 'group_$groupID');
|
||||
conv.showName = groupName;
|
||||
Get.toNamed('/chatGroup', arguments: conv);
|
||||
}
|
||||
}
|
||||
|
||||
// 构建默认群名称
|
||||
String buildGroupName(Set<String> selectedIds) {
|
||||
int maxLength = 20;
|
||||
// 根据 selectedIds 找到对应的昵称
|
||||
final memberNicknames = selectedIds.map((id) {
|
||||
final user = dataList.firstWhere(
|
||||
(u) => u.userID == id,
|
||||
orElse: () => V2TimUserFullInfo(userID: id, nickName: id),
|
||||
);
|
||||
return user.nickName?.isNotEmpty == true ? user.nickName! : user.userID;
|
||||
}).toList();
|
||||
final ctl = Get.find<ImUserInfoController>();
|
||||
// 插入群主的信息
|
||||
memberNicknames.insert(0, ctl.nickname.value);
|
||||
|
||||
// 拼接成群名
|
||||
String name = memberNicknames.join("、");
|
||||
|
||||
// 如果超过长度限制,截断
|
||||
if (name.length > maxLength) {
|
||||
name = "${name.substring(0, maxLength - 3)}...";
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
// 空状态提示
|
||||
Widget _emptyTip(String text) {
|
||||
return Center(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Image.asset('assets/images/empty.png', width: 100),
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
text,
|
||||
style: const TextStyle(color: Colors.grey, fontSize: 13),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildCard({
|
||||
required IconData icon,
|
||||
required String title,
|
||||
@ -96,7 +188,6 @@ class _StartGroupChatPageState extends State<StartGroupChatPage> {
|
||||
return Scaffold(
|
||||
backgroundColor: Colors.white,
|
||||
appBar: AppBar(
|
||||
// backgroundColor: Colors.white,
|
||||
centerTitle: true,
|
||||
forceMaterialTransparency: true,
|
||||
bottom: PreferredSize(
|
||||
@ -122,23 +213,23 @@ class _StartGroupChatPageState extends State<StartGroupChatPage> {
|
||||
icon: Icons.public,
|
||||
title: "创建公开群",
|
||||
onTap: () {
|
||||
print("跳转到 创建公开群");
|
||||
},
|
||||
),
|
||||
_buildCard(
|
||||
icon: Icons.group,
|
||||
title: "创建好友群",
|
||||
onTap: () {
|
||||
print("跳转到 创建好友群");
|
||||
logger.w("跳转到 创建公开群");
|
||||
},
|
||||
),
|
||||
// _buildCard(
|
||||
// icon: Icons.group,
|
||||
// title: "创建好友群",
|
||||
// onTap: () {
|
||||
// logger.w("跳转到 创建好友群");
|
||||
// },
|
||||
// ),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
const Divider(),
|
||||
|
||||
// 下半部分 - 搜索框 + 列表
|
||||
// 下半部分
|
||||
Expanded(
|
||||
child: Column(
|
||||
children: [
|
||||
@ -161,30 +252,56 @@ class _StartGroupChatPageState extends State<StartGroupChatPage> {
|
||||
// 列表
|
||||
Expanded(
|
||||
child: EasyRefresh(
|
||||
header: ClassicHeader(
|
||||
dragText: '下拉刷新',
|
||||
armedText: '释放刷新',
|
||||
readyText: '加载中...',
|
||||
processingText: '加载中...',
|
||||
processedText: '加载完成',
|
||||
failedText: '加载失败,请重试',
|
||||
messageText: '最后更新于 %T',
|
||||
),
|
||||
footer: ClassicFooter(
|
||||
dragText: '加载更多',
|
||||
armedText: '释放加载',
|
||||
readyText: '加载中...',
|
||||
processingText: '加载中...',
|
||||
processedText: hasMore ? '加载完成' : '没有更多了~',
|
||||
failedText: '加载失败,请重试',
|
||||
messageText: '最后更新于 %T',
|
||||
),
|
||||
onRefresh: () async => _loadData(reset: true),
|
||||
onLoad: () async {
|
||||
if (hasMore) await _loadData();
|
||||
},
|
||||
child: ListView.builder(
|
||||
itemCount: filteredList.length,
|
||||
itemBuilder: (context, index) {
|
||||
final item = filteredList[index];
|
||||
final id = item["id"] as String;
|
||||
final isSelected = selectedIds.contains(id);
|
||||
child: filteredList.isEmpty
|
||||
? _emptyTip('暂无数据')
|
||||
: ListView.builder(
|
||||
itemCount: filteredList.length,
|
||||
itemBuilder: (context, index) {
|
||||
final item = filteredList[index];
|
||||
final id = item.userID as String;
|
||||
final isSelected = selectedIds.contains(id);
|
||||
|
||||
return ListTile(
|
||||
leading: CircleAvatar(
|
||||
child: Text(item["nickName"].substring(0, 1)),
|
||||
return ListTile(
|
||||
leading: ClipOval(
|
||||
// child: Text((item.nickName ?? '未知').substring(0, 1)),
|
||||
child: NetworkOrAssetImage(
|
||||
imageUrl: item.faceUrl,
|
||||
width: 48,
|
||||
height: 48,
|
||||
),
|
||||
),
|
||||
title: Text(item.nickName ?? '未知'),
|
||||
trailing: Checkbox(
|
||||
value: isSelected,
|
||||
shape: const CircleBorder(),
|
||||
onChanged: (_) => _toggleSelection(id),
|
||||
),
|
||||
onTap: () => _toggleSelection(id),
|
||||
);
|
||||
},
|
||||
),
|
||||
title: Text(item["nickName"]),
|
||||
trailing: Checkbox(
|
||||
value: isSelected,
|
||||
onChanged: (_) => _toggleSelection(id),
|
||||
),
|
||||
onTap: () => _toggleSelection(id),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
@ -195,25 +312,39 @@ class _StartGroupChatPageState extends State<StartGroupChatPage> {
|
||||
|
||||
// 底部按钮
|
||||
bottomNavigationBar: SafeArea(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(12.0),
|
||||
child: ElevatedButton(
|
||||
onPressed: selectedIds.isEmpty
|
||||
? null
|
||||
: () {
|
||||
print("选择了用户:$selectedIds");
|
||||
},
|
||||
style: ElevatedButton.styleFrom(
|
||||
minimumSize: const Size.fromHeight(50),
|
||||
backgroundColor: selectedIds.isEmpty ? Colors.grey : Colors.blue,
|
||||
),
|
||||
child: const Text(
|
||||
"发起聊天",
|
||||
style: TextStyle(fontSize: 16),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(12.0),
|
||||
child: TweenAnimationBuilder<Color?>(
|
||||
duration: const Duration(milliseconds: 300),
|
||||
tween: ColorTween(
|
||||
begin: Colors.grey,
|
||||
end: selectedIds.isEmpty ? Colors.grey : FStyle.primaryColor,
|
||||
),
|
||||
builder: (context, bgColor, _) {
|
||||
return ElevatedButton(
|
||||
onPressed: selectedIds.isEmpty
|
||||
? null
|
||||
: () {
|
||||
logger.w("选择了用户:$selectedIds");
|
||||
createGroup(selectedIds);
|
||||
},
|
||||
style: ElevatedButton.styleFrom(
|
||||
minimumSize: const Size.fromHeight(50),
|
||||
backgroundColor: bgColor,
|
||||
shape: const StadiumBorder(), // 胶囊形状
|
||||
),
|
||||
child: AnimatedDefaultTextStyle(
|
||||
duration: const Duration(milliseconds: 300),
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
color: selectedIds.isEmpty ? Colors.black : Colors.white,
|
||||
),
|
||||
child: const Text("发起聊天"),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
)),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -853,7 +853,7 @@ class MyPageState extends State<MyPage> with SingleTickerProviderStateMixin {
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: [
|
||||
_buildOrderIcon('assets/images/ico_order.png', '订单', () {
|
||||
Get.toNamed('/order');
|
||||
Get.toNamed('/sellerOrder');
|
||||
}),
|
||||
_buildOrderIcon('assets/images/ico_dhx.png', '余额logout', () {
|
||||
showLogoutDialog(context);
|
||||
|
@ -18,8 +18,8 @@ class _OrderState extends State<Order> with SingleTickerProviderStateMixin {
|
||||
|
||||
List tabList = [
|
||||
{'name': "全部"},
|
||||
{'name': "待付款", 'badge': 1},
|
||||
{'name': "待核销"},
|
||||
{'name': "待退款", 'badge': 1},
|
||||
{'name': "待核销", 'badge': 1},
|
||||
{'name': "已完成"},
|
||||
{'name': "取消"}
|
||||
];
|
||||
@ -65,28 +65,33 @@ class _OrderState extends State<Order> with SingleTickerProviderStateMixin {
|
||||
forceMaterialTransparency: true,
|
||||
titleSpacing: 1.0,
|
||||
title: Container(
|
||||
height: 35.0,
|
||||
// height: 35.0,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.grey[50],
|
||||
// color: Colors.grey[50],
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(30.0),
|
||||
),
|
||||
child: TextField(
|
||||
decoration: InputDecoration(
|
||||
isDense: true,
|
||||
hintText: "搜索订单",
|
||||
hintStyle: TextStyle(color: Colors.black38, fontSize: 14.0),
|
||||
prefixIcon: Icon(
|
||||
Icons.search,
|
||||
color: Colors.black38,
|
||||
size: 21.0,
|
||||
),
|
||||
contentPadding: EdgeInsets.symmetric(vertical: 0, horizontal: 10.0),
|
||||
border: OutlineInputBorder(borderSide: BorderSide.none, borderRadius: BorderRadius.circular(30.0))),
|
||||
cursorColor: Colors.black,
|
||||
onChanged: (val) {
|
||||
debugPrint(val);
|
||||
},
|
||||
child: Text(
|
||||
'订单',
|
||||
style: TextStyle(fontSize: 18),
|
||||
),
|
||||
// child: TextField(
|
||||
// decoration: InputDecoration(
|
||||
// isDense: true,
|
||||
// hintText: "搜索订单",
|
||||
// hintStyle: TextStyle(color: Colors.black38, fontSize: 14.0),
|
||||
// prefixIcon: Icon(
|
||||
// Icons.search,
|
||||
// color: Colors.black38,
|
||||
// size: 21.0,
|
||||
// ),
|
||||
// contentPadding: EdgeInsets.symmetric(vertical: 0, horizontal: 10.0),
|
||||
// border: OutlineInputBorder(borderSide: BorderSide.none, borderRadius: BorderRadius.circular(30.0))),
|
||||
// cursorColor: Colors.black,
|
||||
// onChanged: (val) {
|
||||
// debugPrint(val);
|
||||
// },
|
||||
// ),
|
||||
),
|
||||
bottom: PreferredSize(
|
||||
preferredSize: Size.fromHeight(45.0),
|
||||
@ -99,10 +104,16 @@ class _OrderState extends State<Order> with SingleTickerProviderStateMixin {
|
||||
alignment: Alignment.center,
|
||||
height: 45.0,
|
||||
child: Badge.count(
|
||||
backgroundColor: Colors.red,
|
||||
count: item['badge'] ?? 0,
|
||||
isLabelVisible: item['badge'] != null ? true : false,
|
||||
child: Text(item['name'])),
|
||||
backgroundColor: Colors.red,
|
||||
count: item['badge'] ?? 0,
|
||||
isLabelVisible: item['badge'] != null ? true : false,
|
||||
child: Text(
|
||||
item['name'],
|
||||
style: TextStyle(fontSize: 16),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
softWrap: false,
|
||||
),
|
||||
),
|
||||
))
|
||||
.toList(),
|
||||
isScrollable: false,
|
||||
@ -129,188 +140,363 @@ class _OrderState extends State<Order> with SingleTickerProviderStateMixin {
|
||||
behavior: CustomScrollBehavior().copyWith(scrollbars: false),
|
||||
child: Container(
|
||||
color: Colors.grey[50],
|
||||
child: TabBarView(controller: tabController, children: [
|
||||
ListView(
|
||||
controller: scrollController,
|
||||
physics: BouncingScrollPhysics(),
|
||||
padding: EdgeInsets.all(10.0),
|
||||
children: [
|
||||
GestureDetector(
|
||||
child: Container(
|
||||
margin: EdgeInsets.only(bottom: 10.0),
|
||||
padding: EdgeInsets.all(10.0),
|
||||
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(15.0), boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.black.withAlpha(10),
|
||||
offset: Offset(0.0, 1.0),
|
||||
blurRadius: 1.0,
|
||||
spreadRadius: 0.0,
|
||||
),
|
||||
]),
|
||||
child: Column(
|
||||
spacing: 10.0,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Wrap(
|
||||
crossAxisAlignment: WrapCrossAlignment.center,
|
||||
spacing: 5.0,
|
||||
children: [
|
||||
ClipOval(
|
||||
child: Image.asset(
|
||||
'assets/images/avatar/img11.jpg',
|
||||
width: 25.0,
|
||||
),
|
||||
),
|
||||
Text('老白干自营旗舰店'),
|
||||
Icon(
|
||||
Icons.arrow_forward_ios_rounded,
|
||||
color: Colors.grey,
|
||||
size: 12.0,
|
||||
),
|
||||
],
|
||||
),
|
||||
Spacer(),
|
||||
Text(
|
||||
'待付款',
|
||||
style: TextStyle(color: Colors.red),
|
||||
)
|
||||
],
|
||||
child: TabBarView(
|
||||
controller: tabController,
|
||||
children: [
|
||||
ListView(
|
||||
controller: scrollController,
|
||||
physics: BouncingScrollPhysics(),
|
||||
padding: EdgeInsets.all(10.0),
|
||||
children: [
|
||||
GestureDetector(
|
||||
child: Container(
|
||||
margin: EdgeInsets.only(bottom: 10.0),
|
||||
padding: EdgeInsets.all(10.0),
|
||||
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(15.0), boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.black.withAlpha(10),
|
||||
offset: Offset(0.0, 1.0),
|
||||
blurRadius: 1.0,
|
||||
spreadRadius: 0.0,
|
||||
),
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
spacing: 10.0,
|
||||
children: [
|
||||
Image.network(
|
||||
'https://img13.360buyimg.com/n1/jfs/t1/263909/5/4187/123220/676eb220F3e481086/0cee829b1894fc4c.jpg',
|
||||
width: 80.0,
|
||||
),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
]),
|
||||
child: Column(
|
||||
spacing: 10.0,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Wrap(
|
||||
crossAxisAlignment: WrapCrossAlignment.center,
|
||||
spacing: 5.0,
|
||||
children: [
|
||||
Text(
|
||||
'茅台(MOUTAI)飞天 53度 酱香型白酒 500ml*2 海外版送礼袋年货送礼',
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
ClipOval(
|
||||
child: Image.asset(
|
||||
'assets/images/avatar/img11.jpg',
|
||||
width: 25.0,
|
||||
),
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Text(
|
||||
'¥3800',
|
||||
style: TextStyle(color: Colors.red),
|
||||
),
|
||||
Spacer(),
|
||||
Text(
|
||||
'x10',
|
||||
style: TextStyle(color: Colors.grey),
|
||||
),
|
||||
],
|
||||
Text('老白干自营旗舰店'),
|
||||
Icon(
|
||||
Icons.arrow_forward_ios_rounded,
|
||||
color: Colors.grey,
|
||||
size: 12.0,
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
// 提示信息
|
||||
Container(
|
||||
padding: EdgeInsets.all(5.0),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.grey[50],
|
||||
borderRadius: BorderRadius.circular(5.0),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Spacer(),
|
||||
Text.rich(
|
||||
TextSpan(children: [
|
||||
TextSpan(text: '实付款: '),
|
||||
TextSpan(
|
||||
text: '¥38000',
|
||||
style: TextStyle(color: Colors.red),
|
||||
),
|
||||
]),
|
||||
Text(
|
||||
'待付款',
|
||||
style: TextStyle(color: Colors.red),
|
||||
)
|
||||
],
|
||||
),
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
spacing: 10.0,
|
||||
children: [
|
||||
Image.network(
|
||||
'https://img13.360buyimg.com/n1/jfs/t1/263909/5/4187/123220/676eb220F3e481086/0cee829b1894fc4c.jpg',
|
||||
width: 80.0,
|
||||
),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
spacing: 5.0,
|
||||
children: [
|
||||
Text(
|
||||
'茅台(MOUTAI)飞天 53度 酱香型白酒 500ml*2 海外版送礼袋年货送礼',
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Text(
|
||||
'¥3800',
|
||||
style: TextStyle(color: Colors.red),
|
||||
),
|
||||
Spacer(),
|
||||
Text(
|
||||
'x10',
|
||||
style: TextStyle(color: Colors.grey),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
// 提示信息
|
||||
Container(
|
||||
padding: EdgeInsets.all(5.0),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.grey[50],
|
||||
borderRadius: BorderRadius.circular(5.0),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Spacer(),
|
||||
Text.rich(
|
||||
TextSpan(children: [
|
||||
TextSpan(text: '实付款: '),
|
||||
TextSpan(
|
||||
text: '¥38000',
|
||||
style: TextStyle(color: Colors.red),
|
||||
),
|
||||
]),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
// 按钮组
|
||||
Row(
|
||||
spacing: 10.0,
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
ElevatedButton(
|
||||
onPressed: () {},
|
||||
style: ButtonStyle(backgroundColor: WidgetStateProperty.all(Colors.white)),
|
||||
child: Text('取消订单'),
|
||||
),
|
||||
ElevatedButton(
|
||||
onPressed: () {},
|
||||
style: ButtonStyle(
|
||||
backgroundColor: WidgetStateProperty.all(Color(0xff07c160)), foregroundColor: WidgetStateProperty.all(Colors.white)),
|
||||
child: Text('去支付'),
|
||||
),
|
||||
],
|
||||
),
|
||||
Row(
|
||||
spacing: 10.0,
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
ElevatedButton(
|
||||
onPressed: () {},
|
||||
style: ButtonStyle(
|
||||
backgroundColor: WidgetStateProperty.all(Color(0xFF10B9FC)), foregroundColor: WidgetStateProperty.all(Colors.white)),
|
||||
child: Text('评价'),
|
||||
),
|
||||
],
|
||||
),
|
||||
Row(
|
||||
spacing: 10.0,
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
ElevatedButton(
|
||||
onPressed: () {},
|
||||
style: ButtonStyle(backgroundColor: WidgetStateProperty.all(Colors.white)),
|
||||
child: Text('申请退款'),
|
||||
),
|
||||
ElevatedButton(
|
||||
onPressed: () {},
|
||||
style: ButtonStyle(
|
||||
backgroundColor: WidgetStateProperty.all(Color(0xFFFCBE13)), foregroundColor: WidgetStateProperty.all(Colors.white)),
|
||||
child: Text('联系客服'),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
// 按钮组
|
||||
Row(
|
||||
spacing: 10.0,
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
ElevatedButton(
|
||||
onPressed: () {},
|
||||
style: ButtonStyle(backgroundColor: WidgetStateProperty.all(Colors.white)),
|
||||
child: Text('取消订单'),
|
||||
),
|
||||
ElevatedButton(
|
||||
onPressed: () {},
|
||||
style: ButtonStyle(
|
||||
backgroundColor: WidgetStateProperty.all(Color(0xff07c160)), foregroundColor: WidgetStateProperty.all(Colors.white)),
|
||||
child: Text('去支付'),
|
||||
),
|
||||
],
|
||||
),
|
||||
Row(
|
||||
spacing: 10.0,
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
ElevatedButton(
|
||||
onPressed: () {},
|
||||
style: ButtonStyle(
|
||||
backgroundColor: WidgetStateProperty.all(Color(0xFF10B9FC)), foregroundColor: WidgetStateProperty.all(Colors.white)),
|
||||
child: Text('评价'),
|
||||
),
|
||||
],
|
||||
),
|
||||
Row(
|
||||
spacing: 10.0,
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
ElevatedButton(
|
||||
onPressed: () {},
|
||||
style: ButtonStyle(backgroundColor: WidgetStateProperty.all(Colors.white)),
|
||||
child: Text('申请退款'),
|
||||
),
|
||||
ElevatedButton(
|
||||
onPressed: () {},
|
||||
style: ButtonStyle(
|
||||
backgroundColor: WidgetStateProperty.all(Color(0xFFFCBE13)), foregroundColor: WidgetStateProperty.all(Colors.white)),
|
||||
child: Text('联系客服'),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
Row(
|
||||
spacing: 10.0,
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
ElevatedButton(
|
||||
onPressed: () {},
|
||||
style: ButtonStyle(backgroundColor: WidgetStateProperty.all(Colors.white)),
|
||||
child: Text('删除'),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
Row(
|
||||
spacing: 10.0,
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
ElevatedButton(
|
||||
onPressed: () {},
|
||||
style: ButtonStyle(backgroundColor: WidgetStateProperty.all(Colors.white)),
|
||||
child: Text('删除'),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
onTap: () {
|
||||
Get.toNamed('/order/detail');
|
||||
},
|
||||
),
|
||||
onTap: () {
|
||||
Get.toNamed('/order/detail');
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
emptyTip(),
|
||||
emptyTip(),
|
||||
emptyTip(),
|
||||
emptyTip(),
|
||||
emptyTip(),
|
||||
]),
|
||||
],
|
||||
),
|
||||
emptyTip(),
|
||||
hexiao(),
|
||||
emptyTip(),
|
||||
emptyTip(),
|
||||
emptyTip(),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Widget hexiao() {
|
||||
return ListView(
|
||||
physics: BouncingScrollPhysics(),
|
||||
padding: EdgeInsets.all(10.0),
|
||||
children: [
|
||||
GestureDetector(
|
||||
child: Container(
|
||||
margin: EdgeInsets.only(bottom: 10.0),
|
||||
padding: EdgeInsets.all(10.0),
|
||||
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(15.0), boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.black.withAlpha(10),
|
||||
offset: Offset(0.0, 1.0),
|
||||
blurRadius: 1.0,
|
||||
spreadRadius: 0.0,
|
||||
),
|
||||
]),
|
||||
child: Column(
|
||||
spacing: 10.0,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Wrap(
|
||||
crossAxisAlignment: WrapCrossAlignment.center,
|
||||
spacing: 5.0,
|
||||
children: [
|
||||
ClipOval(
|
||||
child: Image.asset(
|
||||
'assets/images/avatar/img11.jpg',
|
||||
width: 25.0,
|
||||
),
|
||||
),
|
||||
Text('老白干自营旗舰店'),
|
||||
Icon(
|
||||
Icons.arrow_forward_ios_rounded,
|
||||
color: Colors.grey,
|
||||
size: 12.0,
|
||||
),
|
||||
],
|
||||
),
|
||||
Spacer(),
|
||||
Text(
|
||||
'待付款',
|
||||
style: TextStyle(color: Colors.red),
|
||||
)
|
||||
],
|
||||
),
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
spacing: 10.0,
|
||||
children: [
|
||||
Image.network(
|
||||
'https://img13.360buyimg.com/n1/jfs/t1/263909/5/4187/123220/676eb220F3e481086/0cee829b1894fc4c.jpg',
|
||||
width: 80.0,
|
||||
),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
spacing: 5.0,
|
||||
children: [
|
||||
Text(
|
||||
'茅台(MOUTAI)飞天 53度 酱香型白酒 500ml*2 海外版送礼袋年货送礼',
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Text(
|
||||
'¥3800',
|
||||
style: TextStyle(color: Colors.red),
|
||||
),
|
||||
Spacer(),
|
||||
Text(
|
||||
'x10',
|
||||
style: TextStyle(color: Colors.grey),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
// 提示信息
|
||||
Container(
|
||||
padding: EdgeInsets.all(5.0),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.grey[50],
|
||||
borderRadius: BorderRadius.circular(5.0),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Spacer(),
|
||||
Text.rich(
|
||||
TextSpan(children: [
|
||||
TextSpan(text: '实付款: '),
|
||||
TextSpan(
|
||||
text: '¥38000',
|
||||
style: TextStyle(color: Colors.red),
|
||||
),
|
||||
]),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
// 按钮组
|
||||
Row(
|
||||
spacing: 10.0,
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
ElevatedButton(
|
||||
onPressed: () {},
|
||||
style: ButtonStyle(backgroundColor: WidgetStateProperty.all(Colors.white)),
|
||||
child: Text('取消订单'),
|
||||
),
|
||||
ElevatedButton(
|
||||
onPressed: () {},
|
||||
style: ButtonStyle(backgroundColor: WidgetStateProperty.all(Color(0xff07c160)), foregroundColor: WidgetStateProperty.all(Colors.white)),
|
||||
child: Text('去支付'),
|
||||
),
|
||||
],
|
||||
),
|
||||
Row(
|
||||
spacing: 10.0,
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
ElevatedButton(
|
||||
onPressed: () {},
|
||||
style: ButtonStyle(backgroundColor: WidgetStateProperty.all(Color(0xFF10B9FC)), foregroundColor: WidgetStateProperty.all(Colors.white)),
|
||||
child: Text('评价'),
|
||||
),
|
||||
],
|
||||
),
|
||||
Row(
|
||||
spacing: 10.0,
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
ElevatedButton(
|
||||
onPressed: () {},
|
||||
style: ButtonStyle(backgroundColor: WidgetStateProperty.all(Colors.white)),
|
||||
child: Text('申请退款'),
|
||||
),
|
||||
ElevatedButton(
|
||||
onPressed: () {},
|
||||
style: ButtonStyle(backgroundColor: WidgetStateProperty.all(Color(0xFFFCBE13)), foregroundColor: WidgetStateProperty.all(Colors.white)),
|
||||
child: Text('联系客服'),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
Row(
|
||||
spacing: 10.0,
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
ElevatedButton(
|
||||
onPressed: () {},
|
||||
style: ButtonStyle(backgroundColor: WidgetStateProperty.all(Colors.white)),
|
||||
child: Text('删除'),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
onTap: () {
|
||||
Get.toNamed('/order/detail');
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
588
lib/pages/order/seller.dart
Normal file
588
lib/pages/order/seller.dart
Normal file
@ -0,0 +1,588 @@
|
||||
/// 商家的订单
|
||||
library;
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
import '../../behavior/custom_scroll_behavior.dart';
|
||||
|
||||
class Seller extends StatefulWidget {
|
||||
const Seller({super.key});
|
||||
|
||||
@override
|
||||
State<Seller> createState() => _SellerState();
|
||||
}
|
||||
|
||||
class _SellerState extends State<Seller> with SingleTickerProviderStateMixin {
|
||||
GlobalKey<ScaffoldState> scaffoldKey = GlobalKey();
|
||||
|
||||
List tabList = [
|
||||
{'name': "全部"},
|
||||
{'name': "已退款", 'badge': 1},
|
||||
{'name': "待核销", 'badge': 1},
|
||||
{'name': "已完成"},
|
||||
{'name': "取消"}
|
||||
];
|
||||
|
||||
late ScrollController scrollController = ScrollController();
|
||||
late TabController tabController = TabController(initialIndex: 0, length: tabList.length, vsync: this);
|
||||
|
||||
Widget emptyTip() {
|
||||
return Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
spacing: 5.0,
|
||||
children: [
|
||||
Image.asset(
|
||||
'assets/images/empty.png',
|
||||
width: 100.0,
|
||||
),
|
||||
Text(
|
||||
'还没有相关订单~',
|
||||
style: TextStyle(color: Colors.grey, fontSize: 12.0),
|
||||
)
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
scrollController.dispose();
|
||||
tabController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
key: scaffoldKey,
|
||||
backgroundColor: Colors.white,
|
||||
appBar: AppBar(
|
||||
titleSpacing: 1.0,
|
||||
title: Text(
|
||||
'商家订单',
|
||||
style: TextStyle(fontSize: 18),
|
||||
),
|
||||
bottom: PreferredSize(
|
||||
preferredSize: Size.fromHeight(45.0),
|
||||
child: Row(children: [
|
||||
Expanded(
|
||||
child: TabBar(
|
||||
controller: tabController,
|
||||
tabs: tabList
|
||||
.map((item) => Container(
|
||||
alignment: Alignment.center,
|
||||
height: 45.0,
|
||||
child: Badge.count(
|
||||
backgroundColor: Colors.red,
|
||||
offset: Offset(14, -4),
|
||||
count: item['badge'] ?? 0,
|
||||
isLabelVisible: item['badge'] != null ? true : false,
|
||||
child: Text(
|
||||
item['name'],
|
||||
style: TextStyle(fontSize: 16),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
softWrap: false,
|
||||
),
|
||||
),
|
||||
))
|
||||
.toList(),
|
||||
isScrollable: false,
|
||||
overlayColor: WidgetStateProperty.all(Colors.transparent),
|
||||
unselectedLabelColor: Colors.black87,
|
||||
labelColor: Color(0xFFFF5000),
|
||||
indicator: UnderlineTabIndicator(
|
||||
borderRadius: BorderRadius.circular(10.0),
|
||||
borderSide: BorderSide(color: Color(0xFFFF5000), width: 2.0),
|
||||
),
|
||||
indicatorSize: TabBarIndicatorSize.tab,
|
||||
unselectedLabelStyle: TextStyle(fontSize: 16.0, fontFamily: 'Microsoft YaHei'),
|
||||
labelStyle: TextStyle(fontSize: 18.0, fontFamily: 'Microsoft YaHei', fontWeight: FontWeight.w700),
|
||||
dividerHeight: 0,
|
||||
padding: EdgeInsets.symmetric(horizontal: 10.0),
|
||||
labelPadding: EdgeInsets.symmetric(horizontal: 10.0),
|
||||
indicatorPadding: EdgeInsets.symmetric(horizontal: 15.0, vertical: 5.0),
|
||||
),
|
||||
),
|
||||
]),
|
||||
),
|
||||
),
|
||||
body: ScrollConfiguration(
|
||||
behavior: CustomScrollBehavior().copyWith(scrollbars: false),
|
||||
child: Container(
|
||||
color: Colors.grey[50],
|
||||
child: TabBarView(
|
||||
controller: tabController,
|
||||
children: [
|
||||
ListView(
|
||||
controller: scrollController,
|
||||
physics: BouncingScrollPhysics(),
|
||||
padding: EdgeInsets.all(10.0),
|
||||
children: [
|
||||
GestureDetector(
|
||||
child: Container(
|
||||
margin: EdgeInsets.only(bottom: 10.0),
|
||||
padding: EdgeInsets.all(10.0),
|
||||
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(15.0), boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.black.withAlpha(10),
|
||||
offset: Offset(0.0, 1.0),
|
||||
blurRadius: 1.0,
|
||||
spreadRadius: 0.0,
|
||||
),
|
||||
]),
|
||||
child: Column(
|
||||
spacing: 10.0,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Wrap(
|
||||
crossAxisAlignment: WrapCrossAlignment.center,
|
||||
spacing: 5.0,
|
||||
children: [
|
||||
ClipOval(
|
||||
child: Image.asset(
|
||||
'assets/images/avatar/img11.jpg',
|
||||
width: 25.0,
|
||||
),
|
||||
),
|
||||
Text('人人乐超市'),
|
||||
Icon(
|
||||
Icons.arrow_forward_ios_rounded,
|
||||
color: Colors.grey,
|
||||
size: 12.0,
|
||||
),
|
||||
],
|
||||
),
|
||||
Spacer(),
|
||||
Text(
|
||||
'待付款',
|
||||
style: TextStyle(color: Colors.red),
|
||||
)
|
||||
],
|
||||
),
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
spacing: 10.0,
|
||||
children: [
|
||||
Image.network(
|
||||
'https://img13.360buyimg.com/n1/jfs/t1/263909/5/4187/123220/676eb220F3e481086/0cee829b1894fc4c.jpg',
|
||||
width: 80.0,
|
||||
),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
spacing: 5.0,
|
||||
children: [
|
||||
Text(
|
||||
'茅台(MOUTAI)飞天 53度 酱香型白酒 500ml*2 海外版送礼袋年货送礼',
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Text(
|
||||
'¥3800',
|
||||
style: TextStyle(color: Colors.red),
|
||||
),
|
||||
Spacer(),
|
||||
Text(
|
||||
'x10',
|
||||
style: TextStyle(color: Colors.grey),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
// 提示信息
|
||||
Container(
|
||||
padding: EdgeInsets.all(5.0),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.grey[50],
|
||||
borderRadius: BorderRadius.circular(5.0),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Spacer(),
|
||||
Text.rich(
|
||||
TextSpan(children: [
|
||||
TextSpan(text: '实付款: '),
|
||||
TextSpan(
|
||||
text: '¥38000',
|
||||
style: TextStyle(color: Colors.red),
|
||||
),
|
||||
]),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
// 按钮组
|
||||
Row(
|
||||
spacing: 10.0,
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
ElevatedButton(
|
||||
onPressed: () {},
|
||||
style: ButtonStyle(backgroundColor: WidgetStateProperty.all(Colors.white)),
|
||||
child: Text('取消订单'),
|
||||
),
|
||||
ElevatedButton(
|
||||
onPressed: () {},
|
||||
style: ButtonStyle(
|
||||
backgroundColor: WidgetStateProperty.all(Color(0xff07c160)), foregroundColor: WidgetStateProperty.all(Colors.white)),
|
||||
child: Text('去支付'),
|
||||
),
|
||||
],
|
||||
),
|
||||
Row(
|
||||
spacing: 10.0,
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
ElevatedButton(
|
||||
onPressed: () {},
|
||||
style: ButtonStyle(
|
||||
backgroundColor: WidgetStateProperty.all(Color(0xFF10B9FC)), foregroundColor: WidgetStateProperty.all(Colors.white)),
|
||||
child: Text('评价'),
|
||||
),
|
||||
],
|
||||
),
|
||||
Row(
|
||||
spacing: 10.0,
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
ElevatedButton(
|
||||
onPressed: () {},
|
||||
style: ButtonStyle(backgroundColor: WidgetStateProperty.all(Colors.white)),
|
||||
child: Text('申请退款'),
|
||||
),
|
||||
ElevatedButton(
|
||||
onPressed: () {},
|
||||
style: ButtonStyle(
|
||||
backgroundColor: WidgetStateProperty.all(Color(0xFFFCBE13)), foregroundColor: WidgetStateProperty.all(Colors.white)),
|
||||
child: Text('联系客服'),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
Row(
|
||||
spacing: 10.0,
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
ElevatedButton(
|
||||
onPressed: () {},
|
||||
style: ButtonStyle(backgroundColor: WidgetStateProperty.all(Colors.white)),
|
||||
child: Text('删除'),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
onTap: () {
|
||||
Get.toNamed('/order/detail');
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
emptyTip(),
|
||||
hexiao(),
|
||||
finish(),
|
||||
emptyTip(),
|
||||
emptyTip(),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Widget finish() {
|
||||
return ListView(
|
||||
physics: BouncingScrollPhysics(),
|
||||
padding: EdgeInsets.all(10.0),
|
||||
children: [
|
||||
GestureDetector(
|
||||
child: Container(
|
||||
margin: EdgeInsets.only(bottom: 10.0),
|
||||
padding: EdgeInsets.all(10.0),
|
||||
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(15.0), boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.black.withAlpha(10),
|
||||
offset: Offset(0.0, 1.0),
|
||||
blurRadius: 1.0,
|
||||
spreadRadius: 0.0,
|
||||
),
|
||||
]),
|
||||
child: Column(
|
||||
spacing: 10.0,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Wrap(
|
||||
crossAxisAlignment: WrapCrossAlignment.center,
|
||||
spacing: 5.0,
|
||||
children: [
|
||||
ClipOval(
|
||||
child: Image.asset(
|
||||
'assets/images/avatar/img12.jpg',
|
||||
width: 25.0,
|
||||
),
|
||||
),
|
||||
Text('人人乐超市'),
|
||||
Icon(
|
||||
Icons.arrow_forward_ios_rounded,
|
||||
color: Colors.grey,
|
||||
size: 12.0,
|
||||
),
|
||||
],
|
||||
),
|
||||
Spacer(),
|
||||
Text(
|
||||
'已完成',
|
||||
style: TextStyle(color: Colors.red),
|
||||
)
|
||||
],
|
||||
),
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
spacing: 10.0,
|
||||
children: [
|
||||
Image.network(
|
||||
'https://img13.360buyimg.com/n1/jfs/t1/263909/5/4187/123220/676eb220F3e481086/0cee829b1894fc4c.jpg',
|
||||
width: 80.0,
|
||||
),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
spacing: 5.0,
|
||||
children: [
|
||||
Text(
|
||||
'茅台(MOUTAI)飞天 53度 酱香型白酒 500ml 海外版送礼袋年货送礼',
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Text(
|
||||
'¥1900',
|
||||
style: TextStyle(color: Colors.red),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
// 提示信息
|
||||
Container(
|
||||
padding: EdgeInsets.all(5.0),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(5.0),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Spacer(),
|
||||
Text.rich(
|
||||
TextSpan(children: [
|
||||
TextSpan(text: '实付款: '),
|
||||
TextSpan(
|
||||
text: '¥1880',
|
||||
style: TextStyle(color: Colors.red),
|
||||
),
|
||||
]),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
onTap: () {
|
||||
Get.toNamed('/order/detail');
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget hexiao() {
|
||||
return ListView(
|
||||
physics: BouncingScrollPhysics(),
|
||||
padding: EdgeInsets.all(10.0),
|
||||
children: [
|
||||
GestureDetector(
|
||||
child: Container(
|
||||
margin: EdgeInsets.only(bottom: 10.0),
|
||||
padding: EdgeInsets.all(10.0),
|
||||
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(15.0), boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.black.withAlpha(10),
|
||||
offset: Offset(0.0, 1.0),
|
||||
blurRadius: 1.0,
|
||||
spreadRadius: 0.0,
|
||||
),
|
||||
]),
|
||||
child: Column(
|
||||
spacing: 10.0,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Wrap(
|
||||
crossAxisAlignment: WrapCrossAlignment.center,
|
||||
spacing: 5.0,
|
||||
children: [
|
||||
ClipOval(
|
||||
child: Image.asset(
|
||||
'assets/images/avatar/img11.jpg',
|
||||
width: 25.0,
|
||||
),
|
||||
),
|
||||
Text('老白干自营旗舰店'),
|
||||
Icon(
|
||||
Icons.arrow_forward_ios_rounded,
|
||||
color: Colors.grey,
|
||||
size: 12.0,
|
||||
),
|
||||
],
|
||||
),
|
||||
Spacer(),
|
||||
Text(
|
||||
'待付款',
|
||||
style: TextStyle(color: Colors.red),
|
||||
)
|
||||
],
|
||||
),
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
spacing: 10.0,
|
||||
children: [
|
||||
Image.network(
|
||||
'https://img13.360buyimg.com/n1/jfs/t1/263909/5/4187/123220/676eb220F3e481086/0cee829b1894fc4c.jpg',
|
||||
width: 80.0,
|
||||
),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
spacing: 5.0,
|
||||
children: [
|
||||
Text(
|
||||
'茅台(MOUTAI)飞天 53度 酱香型白酒 500ml*2 海外版送礼袋年货送礼',
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Text(
|
||||
'¥3800',
|
||||
style: TextStyle(color: Colors.red),
|
||||
),
|
||||
Spacer(),
|
||||
Text(
|
||||
'x10',
|
||||
style: TextStyle(color: Colors.grey),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
// 提示信息
|
||||
Container(
|
||||
padding: EdgeInsets.all(5.0),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.grey[50],
|
||||
borderRadius: BorderRadius.circular(5.0),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Spacer(),
|
||||
Text.rich(
|
||||
TextSpan(children: [
|
||||
TextSpan(text: '实付款: '),
|
||||
TextSpan(
|
||||
text: '¥38000',
|
||||
style: TextStyle(color: Colors.red),
|
||||
),
|
||||
]),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
// 按钮组
|
||||
Row(
|
||||
spacing: 10.0,
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
ElevatedButton(
|
||||
onPressed: () {},
|
||||
style: ButtonStyle(backgroundColor: WidgetStateProperty.all(Colors.white)),
|
||||
child: Text('取消订单'),
|
||||
),
|
||||
ElevatedButton(
|
||||
onPressed: () {},
|
||||
style: ButtonStyle(backgroundColor: WidgetStateProperty.all(Color(0xff07c160)), foregroundColor: WidgetStateProperty.all(Colors.white)),
|
||||
child: Text('去支付'),
|
||||
),
|
||||
],
|
||||
),
|
||||
Row(
|
||||
spacing: 10.0,
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
ElevatedButton(
|
||||
onPressed: () {},
|
||||
style: ButtonStyle(backgroundColor: WidgetStateProperty.all(Color(0xFF10B9FC)), foregroundColor: WidgetStateProperty.all(Colors.white)),
|
||||
child: Text('评价'),
|
||||
),
|
||||
],
|
||||
),
|
||||
Row(
|
||||
spacing: 10.0,
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
ElevatedButton(
|
||||
onPressed: () {},
|
||||
style: ButtonStyle(backgroundColor: WidgetStateProperty.all(Colors.white)),
|
||||
child: Text('申请退款'),
|
||||
),
|
||||
ElevatedButton(
|
||||
onPressed: () {},
|
||||
style: ButtonStyle(backgroundColor: WidgetStateProperty.all(Color(0xFFFCBE13)), foregroundColor: WidgetStateProperty.all(Colors.white)),
|
||||
child: Text('联系客服'),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
Row(
|
||||
spacing: 10.0,
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
ElevatedButton(
|
||||
onPressed: () {},
|
||||
style: ButtonStyle(backgroundColor: WidgetStateProperty.all(Colors.white)),
|
||||
child: Text('删除'),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
onTap: () {
|
||||
Get.toNamed('/order/detail');
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
@ -2,6 +2,7 @@ import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:loopin/IM/controller/im_user_info_controller.dart';
|
||||
import 'package:loopin/IM/im_service.dart';
|
||||
import 'package:loopin/api/common_api.dart';
|
||||
import 'package:loopin/api/video_api.dart';
|
||||
@ -13,7 +14,8 @@ import 'package:loopin/utils/snapshot.dart';
|
||||
import 'package:wechat_assets_picker/wechat_assets_picker.dart';
|
||||
|
||||
class UploadVideoPage extends StatefulWidget {
|
||||
const UploadVideoPage({super.key});
|
||||
final bool visible;
|
||||
const UploadVideoPage({super.key, required this.visible});
|
||||
|
||||
@override
|
||||
State<UploadVideoPage> createState() => _UploadVideoPageState();
|
||||
@ -36,13 +38,22 @@ class _UploadVideoPageState extends State<UploadVideoPage> {
|
||||
final videoPath = ''.obs; // 本地视频地址
|
||||
final imgPath = ''.obs; //本地图片地址
|
||||
final snapshot = ''.obs;
|
||||
// 文件id
|
||||
final fileId = ''.obs;
|
||||
|
||||
final FocusNode descFocusNode = FocusNode();
|
||||
late final FocusNode descFocusNode;
|
||||
|
||||
final TextEditingController descriptionController = TextEditingController();
|
||||
late TextEditingController descriptionController;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
descFocusNode = FocusNode();
|
||||
descriptionController = TextEditingController();
|
||||
}
|
||||
|
||||
Future<void> pickVideo() async {
|
||||
FocusScope.of(context).unfocus();
|
||||
descFocusNode.unfocus();
|
||||
|
||||
final result = await PhotoManager.requestPermissionExtend();
|
||||
|
||||
@ -82,7 +93,7 @@ class _UploadVideoPageState extends State<UploadVideoPage> {
|
||||
|
||||
// 选择封面图
|
||||
Future<void> pickCoverImage() async {
|
||||
FocusScope.of(context).unfocus();
|
||||
descFocusNode.unfocus();
|
||||
|
||||
final result = await PhotoManager.requestPermissionExtend();
|
||||
|
||||
@ -169,6 +180,7 @@ class _UploadVideoPageState extends State<UploadVideoPage> {
|
||||
status.value = '上传中...';
|
||||
videoPath.value = file.path;
|
||||
logger.w(videoPath.value);
|
||||
// vwidth.value = file.width;
|
||||
|
||||
snapshot.value = (await generateVideoThumbnail(file.path))!;
|
||||
logger.w(snapshot.value);
|
||||
@ -180,19 +192,25 @@ class _UploadVideoPageState extends State<UploadVideoPage> {
|
||||
fileKey: 'file',
|
||||
onSendProgress: (sent, total) {
|
||||
if (total > 0) {
|
||||
uploadProgress.value = sent / total;
|
||||
final pro = sent / total;
|
||||
uploadProgress.value = pro.clamp(0, 0.999);
|
||||
}
|
||||
},
|
||||
);
|
||||
logger.w('上传结果$res');
|
||||
uploadedVideoUrl.value = res['data']['url'];
|
||||
fileId.value = res['data']['ossId'];
|
||||
status.value = '上传成功';
|
||||
} catch (e) {
|
||||
descFocusNode.unfocus();
|
||||
uploading.value = false;
|
||||
} catch (e) {
|
||||
if (e is SocketException) {
|
||||
status.value = '网络错误,请检查连接';
|
||||
} else {
|
||||
status.value = '上传失败: ${e.toString()}';
|
||||
}
|
||||
logger.e(e);
|
||||
descFocusNode.unfocus();
|
||||
} finally {
|
||||
descFocusNode.unfocus();
|
||||
uploading.value = false;
|
||||
@ -203,8 +221,8 @@ class _UploadVideoPageState extends State<UploadVideoPage> {
|
||||
Future<void> submitForm() async {
|
||||
logger.w(descriptionController.text);
|
||||
|
||||
FocusScope.of(context).unfocus();
|
||||
if (uploadedVideoUrl.value.isEmpty) {
|
||||
descFocusNode.unfocus();
|
||||
if (fileId.value.isEmpty) {
|
||||
Get.snackbar('请先上传视频', '未检测到上传的视频');
|
||||
return;
|
||||
}
|
||||
@ -217,6 +235,10 @@ class _UploadVideoPageState extends State<UploadVideoPage> {
|
||||
final data = {
|
||||
'url': uploadedVideoUrl.value,
|
||||
'title': descriptionController.text.trim(),
|
||||
'fileId': fileId.value,
|
||||
'vlogerId': Get.find<ImUserInfoController>().userID.value,
|
||||
'width': selectedVideo.value!.width,
|
||||
'height': selectedVideo.value!.height,
|
||||
};
|
||||
if (uploadedImgUrl.value.isNotEmpty) {
|
||||
data['cover'] = uploadedImgUrl.value;
|
||||
@ -242,11 +264,14 @@ class _UploadVideoPageState extends State<UploadVideoPage> {
|
||||
uploadProgress.value = 0.0;
|
||||
uploadProgress2.value = 0.0;
|
||||
videoPath.value = '';
|
||||
// 本地回显
|
||||
snapshot.value = '';
|
||||
imgPath.value = '';
|
||||
}
|
||||
|
||||
// 预览视频
|
||||
void openVd() {
|
||||
FocusScope.of(context).unfocus();
|
||||
descFocusNode.unfocus();
|
||||
showGeneralDialog(
|
||||
context: context,
|
||||
// barrierDismissible: true,
|
||||
@ -282,10 +307,11 @@ class _UploadVideoPageState extends State<UploadVideoPage> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
FocusScope.of(context).unfocus();
|
||||
},
|
||||
return FocusScope(
|
||||
canRequestFocus: widget.visible,
|
||||
// 只有 UploadVideoPage 可见时才允许 TextField 聚焦
|
||||
child: GestureDetector(
|
||||
onTap: () => descFocusNode.unfocus(),
|
||||
child: Scaffold(
|
||||
appBar: AppBar(title: const Text('上传视频')),
|
||||
body: SingleChildScrollView(
|
||||
@ -303,12 +329,11 @@ class _UploadVideoPageState extends State<UploadVideoPage> {
|
||||
maxLines: 2,
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
// 视频
|
||||
// 视频上传区
|
||||
Obx(() {
|
||||
return Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
// 左侧封面预览
|
||||
snapshot.value.isNotEmpty
|
||||
? GestureDetector(
|
||||
onTap: () => openVd(),
|
||||
@ -329,10 +354,7 @@ class _UploadVideoPageState extends State<UploadVideoPage> {
|
||||
style: TextStyle(fontSize: 16),
|
||||
)),
|
||||
),
|
||||
|
||||
const SizedBox(width: 24),
|
||||
|
||||
// 右侧按钮/进度条
|
||||
Expanded(
|
||||
child: uploading.value
|
||||
? Column(
|
||||
@ -358,12 +380,11 @@ class _UploadVideoPageState extends State<UploadVideoPage> {
|
||||
);
|
||||
}),
|
||||
const SizedBox(height: 20),
|
||||
// 图片上传
|
||||
// 图片上传区
|
||||
Obx(() {
|
||||
return Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
// 左侧图片预览
|
||||
imgPath.value.isNotEmpty
|
||||
? GestureDetector(
|
||||
onTap: () => openImg(),
|
||||
@ -384,10 +405,7 @@ class _UploadVideoPageState extends State<UploadVideoPage> {
|
||||
style: TextStyle(fontSize: 16),
|
||||
)),
|
||||
),
|
||||
|
||||
const SizedBox(width: 24),
|
||||
|
||||
// 右侧按钮/进度条
|
||||
Expanded(
|
||||
child: uploading2.value
|
||||
? Column(
|
||||
@ -425,6 +443,8 @@ class _UploadVideoPageState extends State<UploadVideoPage> {
|
||||
],
|
||||
),
|
||||
),
|
||||
));
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ import 'package:loopin/pages/my/nick_name.dart';
|
||||
import 'package:loopin/pages/my/setting.dart';
|
||||
import 'package:loopin/pages/my/user_info.dart';
|
||||
import 'package:loopin/pages/my/vloger.dart';
|
||||
import 'package:loopin/pages/order/seller.dart';
|
||||
import 'package:loopin/pages/search/index.dart';
|
||||
import 'package:loopin/pages/search/search-result.dart';
|
||||
import 'package:loopin/pages/video/commonVideo.dart';
|
||||
@ -42,6 +43,7 @@ final Map<String, Widget> routes = {
|
||||
// '/chatNoFriend': const ChatNoFriend(),
|
||||
// '/chatGroup': const ChatGroup(),
|
||||
'/order': const Order(),
|
||||
'/sellerOrder': const Seller(),
|
||||
'/order/detail': const OrderDetail(),
|
||||
'/vloger': const Vloger(),
|
||||
'/report': const ReportPage(),
|
||||
|
@ -14,6 +14,9 @@ class HttpConfig {
|
||||
|
||||
// connectTimeout: Duration(seconds: 30),
|
||||
// receiveTimeout: Duration(seconds: 30),
|
||||
connectTimeout: const Duration(seconds: 30), // 建立连接超时
|
||||
receiveTimeout: const Duration(seconds: 300), // 接收响应超时(下载)
|
||||
sendTimeout: const Duration(minutes: 10), // 发送请求超时(上传)
|
||||
));
|
||||
|
||||
static final box = GetStorage();
|
||||
|
Loading…
x
Reference in New Issue
Block a user