merge
This commit is contained in:
parent
a000a4aeea
commit
27001b12d6
@ -14,7 +14,12 @@ import 'package:loopin/utils/scan_code_type.dart';
|
|||||||
import 'package:pretty_qr_code/pretty_qr_code.dart';
|
import 'package:pretty_qr_code/pretty_qr_code.dart';
|
||||||
|
|
||||||
class MyQrcode extends StatelessWidget {
|
class MyQrcode extends StatelessWidget {
|
||||||
MyQrcode({super.key});
|
MyQrcode({
|
||||||
|
super.key,
|
||||||
|
this.prefix,
|
||||||
|
});
|
||||||
|
|
||||||
|
final String? prefix;
|
||||||
|
|
||||||
final controller = Get.find<ImUserInfoController>();
|
final controller = Get.find<ImUserInfoController>();
|
||||||
|
|
||||||
@ -22,12 +27,14 @@ class MyQrcode extends StatelessWidget {
|
|||||||
final GlobalKey _qrKey = GlobalKey();
|
final GlobalKey _qrKey = GlobalKey();
|
||||||
|
|
||||||
/// 将 Widget 渲染为 Uint8List
|
/// 将 Widget 渲染为 Uint8List
|
||||||
Future<Uint8List?> capturePng() async {
|
Future<Uint8List?> capturePng(BuildContext context) async {
|
||||||
try {
|
try {
|
||||||
final boundary = _qrKey.currentContext?.findRenderObject() as RenderRepaintBoundary?;
|
final boundary = _qrKey.currentContext?.findRenderObject() as RenderRepaintBoundary?;
|
||||||
if (boundary == null) return null;
|
if (boundary == null) return null;
|
||||||
|
|
||||||
final image = await boundary.toImage(pixelRatio: ui.window.devicePixelRatio);
|
// final image = await boundary.toImage(pixelRatio: ui.window.devicePixelRatio);
|
||||||
|
final pixelRatio = View.of(context).devicePixelRatio;
|
||||||
|
final image = await boundary.toImage(pixelRatio: pixelRatio);
|
||||||
final byteData = await image.toByteData(format: ui.ImageByteFormat.png);
|
final byteData = await image.toByteData(format: ui.ImageByteFormat.png);
|
||||||
return byteData?.buffer.asUint8List();
|
return byteData?.buffer.asUint8List();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -39,7 +46,7 @@ class MyQrcode extends StatelessWidget {
|
|||||||
/// 保存二维码到相册
|
/// 保存二维码到相册
|
||||||
Future<void> saveQrToGallery() async {
|
Future<void> saveQrToGallery() async {
|
||||||
logger.w('长安了');
|
logger.w('长安了');
|
||||||
final pngBytes = await capturePng();
|
final pngBytes = await capturePng(Get.context!);
|
||||||
if (pngBytes == null) return;
|
if (pngBytes == null) return;
|
||||||
|
|
||||||
final result = await ImageGallerySaverPlus.saveImage(
|
final result = await ImageGallerySaverPlus.saveImage(
|
||||||
@ -67,6 +74,8 @@ class MyQrcode extends StatelessWidget {
|
|||||||
face = CachedNetworkImageProvider(faceUrl);
|
face = CachedNetworkImageProvider(faceUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final data = '${prefix ?? QrTypeCode.hym}$userID';
|
||||||
|
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
onLongPress: () {
|
onLongPress: () {
|
||||||
showModalBottomSheet(
|
showModalBottomSheet(
|
||||||
@ -104,7 +113,7 @@ class MyQrcode extends StatelessWidget {
|
|||||||
key: _qrKey,
|
key: _qrKey,
|
||||||
child: PrettyQrView.data(
|
child: PrettyQrView.data(
|
||||||
errorCorrectLevel: QrErrorCorrectLevel.H, // 高容错
|
errorCorrectLevel: QrErrorCorrectLevel.H, // 高容错
|
||||||
data: '${QrTypeCode.hym}$userID',
|
data: data, // 二维码内容
|
||||||
decoration: PrettyQrDecoration(
|
decoration: PrettyQrDecoration(
|
||||||
background: Colors.transparent,
|
background: Colors.transparent,
|
||||||
shape: const PrettyQrShape.custom(
|
shape: const PrettyQrShape.custom(
|
||||||
|
@ -1713,26 +1713,54 @@ class _ChatNoFriendState extends State<ChatNoFriend> with SingleTickerProviderSt
|
|||||||
),
|
),
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
// 回关
|
// 回关
|
||||||
final res = await ImService.instance.followUser(userIDList: [arguments.value.userID!]);
|
final ctl = Get.find<ChatController>();
|
||||||
if (res.success) {
|
|
||||||
|
final chatRes = await ImService.instance.followUser(userIDList: [arguments.value.userID!]);
|
||||||
|
if (chatRes.success) {
|
||||||
controller.isFriend.value = true;
|
controller.isFriend.value = true;
|
||||||
controller.followType.value = 3;
|
controller.followType.value = 3;
|
||||||
if (arguments.value.conversationGroupList?.isNotEmpty == true) {
|
final res = await ImService.instance.getConversation(conversationID: 'c2c_${arguments.value.userID}');
|
||||||
//把会话数据从陌生人分组移除
|
if (res.success) {
|
||||||
final ctl = Get.find<ChatController>();
|
V2TimConversation conversation = res.data;
|
||||||
ctl.removeNoFriend(conversationID: arguments.value.conversationID);
|
if (conversation.conversationGroupList?.isNotEmpty ?? false) {
|
||||||
ctl.updateNoFriendMenu();
|
await ImService.instance.deleteConversationsFromGroup(
|
||||||
|
groupName: conversation.conversationGroupList!.first!,
|
||||||
|
conversationIDList: [conversation.conversationID],
|
||||||
|
);
|
||||||
|
await ctl.updateNoFriendMenu();
|
||||||
|
// 跳转到chat地址,销毁当前页面
|
||||||
|
Get.offAllNamed(
|
||||||
|
'/chat',
|
||||||
|
arguments: arguments.value,
|
||||||
|
predicate: (route) {
|
||||||
|
// 清理栈,只保留 `/`
|
||||||
|
return route.settings.name == '/';
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// 跳转到chat地址,销毁当前页面
|
|
||||||
Get.offAllNamed(
|
|
||||||
'/chat',
|
|
||||||
arguments: arguments.value,
|
|
||||||
predicate: (route) {
|
|
||||||
// 清理栈,只保留 `/`
|
|
||||||
return route.settings.name == '/';
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
// 回关
|
||||||
|
// final res = await ImService.instance.followUser(userIDList: [arguments.value.userID!]);
|
||||||
|
// if (res.success) {
|
||||||
|
// controller.isFriend.value = true;
|
||||||
|
// controller.followType.value = 3;
|
||||||
|
// if (arguments.value.conversationGroupList?.isNotEmpty == true) {
|
||||||
|
// //把会话数据从陌生人分组移除
|
||||||
|
// final ctl = Get.find<ChatController>();
|
||||||
|
// await ctl.removeNoFriend(conversationID: arguments.value.conversationID);
|
||||||
|
// ctl.updateNoFriendMenu();
|
||||||
|
// // 跳转到chat地址,销毁当前页面
|
||||||
|
// Get.offAllNamed(
|
||||||
|
// '/chat',
|
||||||
|
// arguments: arguments.value,
|
||||||
|
// predicate: (route) {
|
||||||
|
// // 清理栈,只保留 `/`
|
||||||
|
// return route.settings.name == '/';
|
||||||
|
// },
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
// }
|
||||||
},
|
},
|
||||||
child: const Text('回关', style: TextStyle(color: Colors.white)),
|
child: const Text('回关', style: TextStyle(color: Colors.white)),
|
||||||
),
|
),
|
||||||
|
@ -107,11 +107,15 @@ class _AddFriendState extends State<AddFriend> {
|
|||||||
suffixIcon: TextButton(
|
suffixIcon: TextButton(
|
||||||
child: Text('搜索'),
|
child: Text('搜索'),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
// 点击按钮时触发的逻辑
|
// 点击按钮搜索
|
||||||
final value = txtcontroller.text.trim();
|
final value = txtcontroller.text.trim();
|
||||||
if (value.isNotEmpty) {
|
if (value.isNotEmpty) {
|
||||||
// 跳转搜索页
|
// 跳转搜索页
|
||||||
focusNode.unfocus();
|
focusNode.unfocus();
|
||||||
|
Get.toNamed(
|
||||||
|
'/search-result',
|
||||||
|
arguments: {'searchWords': value, 'tab': 2},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@ -124,8 +128,12 @@ class _AddFriendState extends State<AddFriend> {
|
|||||||
),
|
),
|
||||||
onSubmitted: (value) {
|
onSubmitted: (value) {
|
||||||
if (value.trim().isNotEmpty) {
|
if (value.trim().isNotEmpty) {
|
||||||
focusNode.unfocus();
|
|
||||||
// 跳转搜索页
|
// 跳转搜索页
|
||||||
|
focusNode.unfocus();
|
||||||
|
Get.toNamed(
|
||||||
|
'/search-result',
|
||||||
|
arguments: {'searchWords': value, 'tab': 2},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@ -155,6 +163,7 @@ class _AddFriendState extends State<AddFriend> {
|
|||||||
|
|
||||||
SizedBox(height: 20),
|
SizedBox(height: 20),
|
||||||
|
|
||||||
|
// 我的二维码
|
||||||
MyQrcode(),
|
MyQrcode(),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
@ -42,7 +42,6 @@ class _GoodsState extends State<Goods> {
|
|||||||
double scrollOffset = 0;
|
double scrollOffset = 0;
|
||||||
// 分享列表
|
// 分享列表
|
||||||
List shareList = [
|
List shareList = [
|
||||||
{'icon': 'assets/images/share-wx.png', 'label': '好友'},
|
|
||||||
{'icon': 'assets/images/share-wx.png', 'label': '微信'},
|
{'icon': 'assets/images/share-wx.png', 'label': '微信'},
|
||||||
{'icon': 'assets/images/share-pyq.png', 'label': '朋友圈'},
|
{'icon': 'assets/images/share-pyq.png', 'label': '朋友圈'},
|
||||||
];
|
];
|
||||||
@ -105,11 +104,12 @@ class _GoodsState extends State<Goods> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void handleShareClick(int index) {
|
void handleShareClick(int index) {
|
||||||
final description = shopObj['describe']; // 商品描述
|
logger.w(shopObj);
|
||||||
if (index == 1) {
|
final description = shopObj['describe'] ?? '未上传商品描述'; // 商品描述
|
||||||
|
if (index == 0) {
|
||||||
// 好友
|
// 好友
|
||||||
Wxsdk.shareToFriend(title: '快看看我分享的商品', description: description, webpageUrl: '${ShareType.shop.name}?id=${shopObj['id']}');
|
Wxsdk.shareToFriend(title: '快看看我分享的商品', description: description, webpageUrl: '${ShareType.shop.name}?id=${shopObj['id']}');
|
||||||
} else if (index == 2) {
|
} else if (index == 1) {
|
||||||
// 朋友圈
|
// 朋友圈
|
||||||
Wxsdk.shareToTimeline(title: '快看看我分享的商品', webpageUrl: '${ShareType.shop.name}?id=${shopObj['id']}');
|
Wxsdk.shareToTimeline(title: '快看看我分享的商品', webpageUrl: '${ShareType.shop.name}?id=${shopObj['id']}');
|
||||||
}
|
}
|
||||||
@ -178,7 +178,9 @@ class _GoodsState extends State<Goods> {
|
|||||||
padding: EdgeInsets.symmetric(horizontal: 0, vertical: 20.0),
|
padding: EdgeInsets.symmetric(horizontal: 0, vertical: 20.0),
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
onTap: () => handleShareClick(index),
|
onTap: () {
|
||||||
|
handleShareClick(index);
|
||||||
|
},
|
||||||
child: Container(
|
child: Container(
|
||||||
width: 64,
|
width: 64,
|
||||||
margin: EdgeInsets.symmetric(horizontal: 8.0),
|
margin: EdgeInsets.symmetric(horizontal: 8.0),
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_svg/flutter_svg.dart';
|
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
|
import 'package:loopin/IM/controller/im_user_info_controller.dart';
|
||||||
|
import 'package:loopin/components/my_qrcode.dart';
|
||||||
|
import 'package:loopin/pages/my/merchant/balance/balance.dart';
|
||||||
|
import 'package:loopin/pages/my/merchant/balance/controller.dart';
|
||||||
|
import 'package:loopin/utils/scan_code_type.dart';
|
||||||
|
|
||||||
class AllFunctionsPage extends StatefulWidget {
|
class AllFunctionsPage extends StatefulWidget {
|
||||||
const AllFunctionsPage({super.key});
|
const AllFunctionsPage({super.key});
|
||||||
@ -29,6 +33,7 @@ class _AllFunctionsPageState extends State<AllFunctionsPage> {
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
final ImUserInfoController controller = Get.find<ImUserInfoController>();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@ -106,7 +111,12 @@ class _AllFunctionsPageState extends State<AllFunctionsPage> {
|
|||||||
itemCount: (section['items'] as List).length,
|
itemCount: (section['items'] as List).length,
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
final item = (section['items'] as List)[index];
|
final item = (section['items'] as List)[index];
|
||||||
return _buildFunctionItem(item);
|
final role = controller.role.value;
|
||||||
|
if (item['id'] == 'home_promo' && role != 4) {
|
||||||
|
return SizedBox();
|
||||||
|
} else {
|
||||||
|
return _buildFunctionItem(item);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
||||||
@ -137,7 +147,7 @@ class _AllFunctionsPageState extends State<AllFunctionsPage> {
|
|||||||
child: Column(
|
child: Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
Container(
|
SizedBox(
|
||||||
width: 36,
|
width: 36,
|
||||||
height: 36,
|
height: 36,
|
||||||
child: Center(
|
child: Center(
|
||||||
@ -176,18 +186,25 @@ class _AllFunctionsPageState extends State<AllFunctionsPage> {
|
|||||||
Get.toNamed('/myOrder');
|
Get.toNamed('/myOrder');
|
||||||
break;
|
break;
|
||||||
case 'home_balance':
|
case 'home_balance':
|
||||||
showLogoutDialog(context);
|
// 钱包
|
||||||
|
Get.put(BalanceController());
|
||||||
|
Get.to(() => Balance());
|
||||||
|
// showLogoutDialog(context);
|
||||||
break;
|
break;
|
||||||
case 'home_withdraw':
|
case 'home_withdraw':
|
||||||
Get.toNamed('/vloger');
|
Get.toNamed('/vloger');
|
||||||
break;
|
break;
|
||||||
case 'home_promo':
|
case 'home_promo':
|
||||||
|
// 推广码
|
||||||
|
Get.to(() => MyQrcode(
|
||||||
|
prefix: QrTypeCode.tgm,
|
||||||
|
));
|
||||||
break;
|
break;
|
||||||
case 'more_seller_order':
|
case 'more_seller_order':
|
||||||
Get.toNamed('/sellerOrder');
|
Get.toNamed('/sellerOrder');
|
||||||
break;
|
break;
|
||||||
case 'more_seller_income':
|
case 'more_seller_income':
|
||||||
Get.toNamed('/merchant/income');
|
Get.toNamed('/merchant/income');
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -211,10 +228,10 @@ class _AllFunctionsPageState extends State<AllFunctionsPage> {
|
|||||||
},
|
},
|
||||||
child: const Text('取消', style: TextStyle(color: Colors.black54)),
|
child: const Text('取消', style: TextStyle(color: Colors.black54)),
|
||||||
),
|
),
|
||||||
TextButton(onPressed: ()=>{}, child: const Text('退出登录', style: TextStyle(color: Colors.red))),
|
TextButton(onPressed: () => {}, child: const Text('退出登录', style: TextStyle(color: Colors.red))),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,15 +5,18 @@ import 'package:get/get.dart';
|
|||||||
import 'package:get/get_rx/src/rx_typedefs/rx_typedefs.dart';
|
import 'package:get/get_rx/src/rx_typedefs/rx_typedefs.dart';
|
||||||
import 'package:loopin/IM/controller/im_user_info_controller.dart';
|
import 'package:loopin/IM/controller/im_user_info_controller.dart';
|
||||||
import 'package:loopin/IM/im_service.dart';
|
import 'package:loopin/IM/im_service.dart';
|
||||||
import 'package:loopin/api/video_api.dart';
|
|
||||||
import 'package:loopin/api/common_api.dart';
|
import 'package:loopin/api/common_api.dart';
|
||||||
import 'package:loopin/utils/index.dart';
|
import 'package:loopin/api/video_api.dart';
|
||||||
import 'package:loopin/components/custom_sticky_header.dart';
|
import 'package:loopin/components/custom_sticky_header.dart';
|
||||||
import 'package:loopin/components/my_confirm.dart';
|
import 'package:loopin/components/my_confirm.dart';
|
||||||
|
import 'package:loopin/components/my_qrcode.dart';
|
||||||
import 'package:loopin/components/network_or_asset_image.dart';
|
import 'package:loopin/components/network_or_asset_image.dart';
|
||||||
import 'package:loopin/components/only_down_scroll_physics.dart';
|
import 'package:loopin/components/only_down_scroll_physics.dart';
|
||||||
import 'package:loopin/controller/video_module_controller.dart';
|
import 'package:loopin/controller/video_module_controller.dart';
|
||||||
import 'package:loopin/service/http.dart';
|
import 'package:loopin/service/http.dart';
|
||||||
|
import 'package:loopin/styles/index.dart';
|
||||||
|
import 'package:loopin/utils/index.dart';
|
||||||
|
import 'package:loopin/utils/scan_code_type.dart';
|
||||||
import 'package:nested_scroll_view_plus/nested_scroll_view_plus.dart';
|
import 'package:nested_scroll_view_plus/nested_scroll_view_plus.dart';
|
||||||
import 'package:shirne_dialog/shirne_dialog.dart';
|
import 'package:shirne_dialog/shirne_dialog.dart';
|
||||||
import 'package:tencent_cloud_chat_sdk/models/v2_tim_follow_info.dart';
|
import 'package:tencent_cloud_chat_sdk/models/v2_tim_follow_info.dart';
|
||||||
@ -131,17 +134,14 @@ class MyPageState extends State<MyPage> with SingleTickerProviderStateMixin {
|
|||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取用户的所有视频的点赞数量
|
// 获取用户的所有视频的点赞数量
|
||||||
void getUserLikesCount() async {
|
void getUserLikesCount() async {
|
||||||
try {
|
try {
|
||||||
final resData = await Http.get(CommonApi.accountInfo);
|
final resData = await Http.get(CommonApi.accountInfo);
|
||||||
if(resData != null && resData['code'] == 200){
|
if (resData != null && resData['code'] == 200) {
|
||||||
vlogLikeCount = resData['data']['vlogLikeCount']??0;
|
vlogLikeCount = resData['data']['vlogLikeCount'] ?? 0;
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
} catch (e) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 添加控制子列表滚动的方法
|
// 添加控制子列表滚动的方法
|
||||||
@ -263,121 +263,20 @@ class MyPageState extends State<MyPage> with SingleTickerProviderStateMixin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 删除当前用户发布的视频
|
||||||
// 删除当前用户发布的视频
|
// 删除当前用户发布的视频
|
||||||
void deletePersonalVideo(videoId) async {
|
void deletePersonalVideo(videoId) async {
|
||||||
logger.i('删除视频${videoId}');
|
logger.i('删除视频$videoId');
|
||||||
try {
|
try {
|
||||||
final res = await Http.post('${VideoApi.deleteVideo}?id=${videoId}', data: {});
|
final res = await Http.post('${VideoApi.deleteVideo}?id=$videoId', data: {});
|
||||||
logger.i('删除成功响应${res}');
|
logger.i('删除成功响应$res');
|
||||||
if(res != null && res['code'] == 200){
|
if (res != null && res['code'] == 200) {
|
||||||
MyDialog.toast('删除成功', icon: const Icon(Icons.check_circle), style: ToastStyle(backgroundColor: Colors.green.withAlpha(200)));
|
MyDialog.toast('删除成功', icon: const Icon(Icons.check_circle), style: ToastStyle(backgroundColor: Colors.green.withAlpha(200)));
|
||||||
loadData(0);
|
loadData(0);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {}
|
||||||
logger.e('删除视频失败: $e');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 显示删除确认对话框
|
|
||||||
void showDeleteConfirmDialog(String videoId) {
|
|
||||||
Get.dialog(
|
|
||||||
Dialog(
|
|
||||||
backgroundColor: Colors.white,
|
|
||||||
surfaceTintColor: Colors.white,
|
|
||||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20.0)),
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.all(20.0),
|
|
||||||
child: Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
// 图标
|
|
||||||
Container(
|
|
||||||
width: 60,
|
|
||||||
height: 60,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: Colors.red.withOpacity(0.1),
|
|
||||||
shape: BoxShape.circle,
|
|
||||||
),
|
|
||||||
child: Icon(
|
|
||||||
Icons.delete_outline,
|
|
||||||
color: Colors.red,
|
|
||||||
size: 30,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SizedBox(height: 16),
|
|
||||||
|
|
||||||
// 标题
|
|
||||||
Text(
|
|
||||||
'删除视频',
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 18,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
color: Colors.black87,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SizedBox(height: 8),
|
|
||||||
|
|
||||||
// 描述
|
|
||||||
Text(
|
|
||||||
'确认要删除这个视频吗?\n删除后将无法恢复',
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 14,
|
|
||||||
color: Colors.grey[600],
|
|
||||||
height: 1.4,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SizedBox(height: 24),
|
|
||||||
|
|
||||||
// 按钮区域
|
|
||||||
Row(
|
|
||||||
children: [
|
|
||||||
// 取消按钮
|
|
||||||
Expanded(
|
|
||||||
child: OutlinedButton(
|
|
||||||
onPressed: () => Get.back(),
|
|
||||||
style: OutlinedButton.styleFrom(
|
|
||||||
backgroundColor: Colors.transparent,
|
|
||||||
foregroundColor: Colors.grey[700],
|
|
||||||
side: BorderSide(color: Colors.grey[300]!),
|
|
||||||
padding: EdgeInsets.symmetric(vertical: 12),
|
|
||||||
shape: RoundedRectangleBorder(
|
|
||||||
borderRadius: BorderRadius.circular(12),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
child: Text('取消'),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SizedBox(width: 12),
|
|
||||||
|
|
||||||
// 确认按钮
|
|
||||||
Expanded(
|
|
||||||
child: ElevatedButton(
|
|
||||||
onPressed: () {
|
|
||||||
Get.back();
|
|
||||||
deletePersonalVideo(videoId);
|
|
||||||
},
|
|
||||||
style: ElevatedButton.styleFrom(
|
|
||||||
backgroundColor: Colors.red,
|
|
||||||
foregroundColor: Colors.white,
|
|
||||||
padding: EdgeInsets.symmetric(vertical: 12),
|
|
||||||
shape: RoundedRectangleBorder(
|
|
||||||
borderRadius: BorderRadius.circular(12),
|
|
||||||
),
|
|
||||||
elevation: 0,
|
|
||||||
),
|
|
||||||
child: Text('确认删除'),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
barrierDismissible: true,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
// 二维码名片弹窗
|
// 二维码名片弹窗
|
||||||
void qrcodeAlertDialog(BuildContext context) {
|
void qrcodeAlertDialog(BuildContext context) {
|
||||||
showDialog(
|
showDialog(
|
||||||
@ -397,13 +296,14 @@ class MyPageState extends State<MyPage> with SingleTickerProviderStateMixin {
|
|||||||
child: Column(
|
child: Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
Image.asset('assets/images/pic1.jpg', width: 250.0, fit: BoxFit.contain),
|
MyQrcode(prefix: QrTypeCode.tgm)
|
||||||
const SizedBox(height: 15.0),
|
// Image.asset('assets/images/pic1.jpg', width: 250.0, fit: BoxFit.contain),
|
||||||
const Text('扫一扫,加好友',
|
// const SizedBox(height: 15.0),
|
||||||
style: TextStyle(
|
// const Text('扫一扫,加好友',
|
||||||
color: Colors.white38,
|
// style: TextStyle(
|
||||||
fontSize: 14.0,
|
// color: Colors.white38,
|
||||||
)),
|
// fontSize: 14.0,
|
||||||
|
// )),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -657,7 +557,7 @@ class MyPageState extends State<MyPage> with SingleTickerProviderStateMixin {
|
|||||||
borderRadius: BorderRadius.circular(10.0),
|
borderRadius: BorderRadius.circular(10.0),
|
||||||
),
|
),
|
||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
child: _buildVdCard(listToShow[index],tabIndex),
|
child: _buildVdCard(listToShow[index], tabIndex),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
childCount: listToShow.length,
|
childCount: listToShow.length,
|
||||||
@ -683,48 +583,55 @@ class MyPageState extends State<MyPage> with SingleTickerProviderStateMixin {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildVdCard(item,tabIndex) {
|
Widget _buildVdCard(item, tabIndex) {
|
||||||
return InkWell(
|
return InkWell(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
//去视频详情
|
//去视频详情
|
||||||
Get.toNamed('/videoDetail', arguments: {'videoId': item['id']});
|
Get.toNamed('/videoDetail', arguments: {'videoId': item['id']});
|
||||||
},
|
},
|
||||||
onLongPress: () {
|
onLongPress: () {
|
||||||
if(tabIndex == 0){ // 个人发布作品可以长按删除
|
if (tabIndex == 0) {
|
||||||
|
// 个人发布作品可以长按删除
|
||||||
showModalBottomSheet(
|
showModalBottomSheet(
|
||||||
context: Get.context!,
|
context: Get.context!,
|
||||||
backgroundColor: Colors.white,
|
backgroundColor: Colors.white,
|
||||||
shape: const RoundedRectangleBorder(
|
shape: const RoundedRectangleBorder(
|
||||||
borderRadius: BorderRadius.vertical(top: Radius.circular(16)),
|
borderRadius: BorderRadius.vertical(top: Radius.circular(16)),
|
||||||
),
|
),
|
||||||
builder: (context) {
|
builder: (context) {
|
||||||
return SafeArea(
|
return SafeArea(
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
// ListTile(
|
// ListTile(
|
||||||
// leading: const Icon(Icons.lock, color: Colors.black),
|
// leading: const Icon(Icons.lock, color: Colors.black),
|
||||||
// title: const Text('设为私密', style: TextStyle(color: Colors.black)),
|
// title: const Text('设为私密', style: TextStyle(color: Colors.black)),
|
||||||
// onTap: () {
|
// onTap: () {
|
||||||
// Navigator.pop(context);
|
// Navigator.pop(context);
|
||||||
// // TODO: 修改为私密逻辑
|
// // TODO: 修改为私密逻辑
|
||||||
// },
|
// },
|
||||||
// ),
|
// ),
|
||||||
ListTile(
|
ListTile(
|
||||||
leading: const Icon(Icons.delete, color: Colors.redAccent),
|
leading: const Icon(Icons.delete, color: Colors.redAccent),
|
||||||
title: const Text('删除视频', style: TextStyle(color: Colors.redAccent)),
|
title: const Text('删除视频', style: TextStyle(color: Colors.redAccent)),
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
Get.back();
|
Get.back();
|
||||||
showDeleteConfirmDialog(item['id']);
|
final confirmed = await ConfirmDialog.show(
|
||||||
},
|
title: "提示",
|
||||||
),
|
content: "确认要删除吗?",
|
||||||
],
|
);
|
||||||
),
|
if (confirmed == true) {
|
||||||
);
|
Get.back();
|
||||||
},
|
deletePersonalVideo(item['id']);
|
||||||
);
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
child: Container(
|
child: Container(
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
@ -830,35 +737,72 @@ class MyPageState extends State<MyPage> with SingleTickerProviderStateMixin {
|
|||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
// 昵称 Obx
|
// 昵称 Obx
|
||||||
Obx(() {
|
Obx(
|
||||||
final nickname = imUserInfoController?.nickname.value ?? '';
|
() {
|
||||||
return Container(
|
final nickname = imUserInfoController?.nickname.value ?? '';
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5),
|
return Container(
|
||||||
decoration: BoxDecoration(
|
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5),
|
||||||
color: Colors.black.withAlpha(76),
|
decoration: BoxDecoration(
|
||||||
borderRadius: BorderRadius.circular(20),
|
color: Colors.black.withAlpha(76),
|
||||||
),
|
borderRadius: BorderRadius.circular(20),
|
||||||
child: Text(
|
|
||||||
nickname.isNotEmpty ? nickname : '昵称',
|
|
||||||
style: const TextStyle(
|
|
||||||
fontSize: 20,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
color: Colors.white,
|
|
||||||
),
|
),
|
||||||
),
|
child: Text(
|
||||||
);
|
nickname.isNotEmpty ? nickname : '昵称',
|
||||||
}),
|
style: const TextStyle(
|
||||||
const SizedBox(width: 8),
|
fontSize: 20,
|
||||||
InkWell(
|
fontWeight: FontWeight.bold,
|
||||||
onTap: () => qrcodeAlertDialog(context),
|
color: Colors.white,
|
||||||
child: Container(
|
),
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 5, vertical: 5),
|
),
|
||||||
decoration: BoxDecoration(
|
);
|
||||||
color: Colors.black.withAlpha(76),
|
},
|
||||||
borderRadius: BorderRadius.circular(20),
|
),
|
||||||
),
|
|
||||||
child: const Icon(Icons.qr_code_outlined, size: 18, color: Colors.white),
|
// 团长的二维码
|
||||||
),
|
Obx(
|
||||||
|
() {
|
||||||
|
// MERCHANT(2, "商家"),
|
||||||
|
// AGENT(3, "代理"),
|
||||||
|
// PLATFORM(4, "平台"),
|
||||||
|
// REFERENCE(5, "团长")
|
||||||
|
final role = imUserInfoController?.role.value;
|
||||||
|
if (role == 4) {
|
||||||
|
return Row(children: [
|
||||||
|
SizedBox(width: 8),
|
||||||
|
//
|
||||||
|
InkWell(
|
||||||
|
onTap: () => qrcodeAlertDialog(context),
|
||||||
|
child: Container(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 5, vertical: 5),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.black.withAlpha(176),
|
||||||
|
borderRadius: BorderRadius.circular(20),
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Icon(
|
||||||
|
Icons.qr_code_outlined,
|
||||||
|
size: 18,
|
||||||
|
color: FStyle.secondaryColor,
|
||||||
|
),
|
||||||
|
SizedBox(width: 4),
|
||||||
|
Text(
|
||||||
|
'团长邀请码',
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 12,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
color: FStyle.secondaryColor, // 彩色文字
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]);
|
||||||
|
} else {
|
||||||
|
return const SizedBox();
|
||||||
|
}
|
||||||
|
},
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@ -912,7 +856,11 @@ class MyPageState extends State<MyPage> with SingleTickerProviderStateMixin {
|
|||||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||||
children: [
|
children: [
|
||||||
// '已售${Utils.graceNumber(int.tryParse(vlogLikeCount?.toString() ?? '0') ?? 0)}',
|
// '已售${Utils.graceNumber(int.tryParse(vlogLikeCount?.toString() ?? '0') ?? 0)}',
|
||||||
Column(children: [Text('${Utils.graceNumber(vlogLikeCount)}', style: TextStyle(fontSize: 16.0, fontWeight: FontWeight.bold)), SizedBox(height: 3.0), Text('获赞')]),
|
Column(children: [
|
||||||
|
Text(Utils.graceNumber(vlogLikeCount), style: TextStyle(fontSize: 16.0, fontWeight: FontWeight.bold)),
|
||||||
|
SizedBox(height: 3.0),
|
||||||
|
Text('获赞')
|
||||||
|
]),
|
||||||
GestureDetector(
|
GestureDetector(
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
// 互相关注
|
// 互相关注
|
||||||
|
125
lib/pages/my/merchant/balance/balance.dart
Normal file
125
lib/pages/my/merchant/balance/balance.dart
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
// 钱包页面
|
||||||
|
import 'package:easy_refresh/easy_refresh.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:get/get.dart';
|
||||||
|
import 'package:loopin/IM/im_service.dart';
|
||||||
|
import 'package:loopin/behavior/custom_scroll_behavior.dart';
|
||||||
|
import 'package:loopin/pages/my/merchant/balance/controller.dart';
|
||||||
|
|
||||||
|
class Balance extends StatefulWidget {
|
||||||
|
const Balance({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<Balance> createState() => _BalanceState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _BalanceState extends State<Balance> {
|
||||||
|
final controller = Get.put(BalanceController());
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(title: const Text("我的钱包")),
|
||||||
|
body: ScrollConfiguration(
|
||||||
|
behavior: CustomScrollBehavior().copyWith(scrollbars: false),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
// 上半部分:余额 + 充值
|
||||||
|
Container(
|
||||||
|
padding: const EdgeInsets.all(16),
|
||||||
|
color: Colors.blueAccent,
|
||||||
|
width: double.infinity,
|
||||||
|
child: Obx(() {
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
const Text(
|
||||||
|
"钱包余额",
|
||||||
|
style: TextStyle(color: Colors.white, fontSize: 16),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
Text(
|
||||||
|
"¥ ${controller.balance.value.toStringAsFixed(2)}",
|
||||||
|
style: const TextStyle(
|
||||||
|
color: Colors.white,
|
||||||
|
fontSize: 28,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 12),
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: () => controller.recharge(100.0),
|
||||||
|
style: ElevatedButton.styleFrom(
|
||||||
|
backgroundColor: Colors.orange,
|
||||||
|
),
|
||||||
|
child: const Text("充值 100 元"),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
|
||||||
|
// 下半部分:流水记录分页列表
|
||||||
|
Expanded(
|
||||||
|
child: Obx(() {
|
||||||
|
return EasyRefresh.builder(
|
||||||
|
callLoadOverOffset: 20, //触底距离
|
||||||
|
callRefreshOverOffset: 20, // 下拉距离
|
||||||
|
header: ClassicHeader(
|
||||||
|
dragText: '下拉刷新',
|
||||||
|
armedText: '释放刷新',
|
||||||
|
readyText: '加载中...',
|
||||||
|
processingText: '加载中...',
|
||||||
|
processedText: '加载完成',
|
||||||
|
failedText: '加载失败,请重试',
|
||||||
|
messageText: '最后更新于 %T',
|
||||||
|
),
|
||||||
|
footer: ClassicFooter(
|
||||||
|
dragText: '加载更多',
|
||||||
|
armedText: '释放加载',
|
||||||
|
readyText: '加载中...',
|
||||||
|
processingText: '加载中...',
|
||||||
|
processedText: controller.hasMore.value ? '加载完成' : '没有更多了~',
|
||||||
|
failedText: '加载失败,请重试',
|
||||||
|
messageText: '最后更新于 %T',
|
||||||
|
succeededIcon: controller.hasMore.value ? Icon(Icons.check_circle, color: Colors.green) : Icon(Icons.warning, color: Colors.orange),
|
||||||
|
),
|
||||||
|
onRefresh: () async {
|
||||||
|
await controller.getData(reset: true);
|
||||||
|
},
|
||||||
|
onLoad: () async {
|
||||||
|
if (controller.hasMore.value) {
|
||||||
|
await controller.getData();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
childBuilder: (context, physics) {
|
||||||
|
return ListView.builder(
|
||||||
|
physics: physics,
|
||||||
|
itemCount: controller.data.length,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
final tx = controller.data[index];
|
||||||
|
logger.w(tx.source);
|
||||||
|
|
||||||
|
return ListTile(
|
||||||
|
title: Text(tx.source),
|
||||||
|
subtitle: Text(tx.createTime),
|
||||||
|
trailing: Text(
|
||||||
|
"变动金额:${tx.changeType == 1 ? '+' : '-'}${tx.changeAmount}", // 变动金额
|
||||||
|
style: TextStyle(
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
color: tx.changeType == 1 ? Colors.green : Colors.red,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
56
lib/pages/my/merchant/balance/controller.dart
Normal file
56
lib/pages/my/merchant/balance/controller.dart
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
import 'package:get/get.dart';
|
||||||
|
import 'package:loopin/pages/my/merchant/balance/model.dart';
|
||||||
|
|
||||||
|
class BalanceController extends GetxController {
|
||||||
|
/// 钱包余额
|
||||||
|
final balance = 0.0.obs;
|
||||||
|
|
||||||
|
final data = <AccountBill>[].obs;
|
||||||
|
|
||||||
|
int currentPage = 1;
|
||||||
|
|
||||||
|
final isLoading = false.obs;
|
||||||
|
|
||||||
|
/// 是否还有更多
|
||||||
|
var hasMore = true.obs;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void onInit() {
|
||||||
|
super.onInit();
|
||||||
|
getData(reset: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 充值
|
||||||
|
void recharge(double amount) {
|
||||||
|
balance.value += amount;
|
||||||
|
// 同时加一条流水
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 分页数据
|
||||||
|
Future<void> getData({bool reset = false}) async {
|
||||||
|
if (isLoading.value) return;
|
||||||
|
isLoading.value = true;
|
||||||
|
|
||||||
|
if (reset) {
|
||||||
|
currentPage = 1;
|
||||||
|
data.clear();
|
||||||
|
hasMore.value = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
await Future.delayed(const Duration(seconds: 3)); // 模拟网络延迟
|
||||||
|
|
||||||
|
List<AccountBill> newData = List.generate(
|
||||||
|
10,
|
||||||
|
(index) => AccountBill(id: index),
|
||||||
|
);
|
||||||
|
|
||||||
|
data.addAll(newData);
|
||||||
|
currentPage++;
|
||||||
|
|
||||||
|
if (currentPage > 3) {
|
||||||
|
hasMore.value = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
isLoading.value = false;
|
||||||
|
}
|
||||||
|
}
|
49
lib/pages/my/merchant/balance/model.dart
Normal file
49
lib/pages/my/merchant/balance/model.dart
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
class AccountBill {
|
||||||
|
final int id;
|
||||||
|
final int? memberId;
|
||||||
|
final int? accountId;
|
||||||
|
final double moneyBalance; // 当前余额
|
||||||
|
final double beforeBalance; // 变动前余额
|
||||||
|
final double afterBalance; // 变动后余额
|
||||||
|
final double changeAmount; // 变动金额
|
||||||
|
final int changeType; // 变动类型(1收入 2支出)
|
||||||
|
final String changeDesc; // 变动描述
|
||||||
|
final String source; // 变动来源
|
||||||
|
final String createTime; // 创建时间
|
||||||
|
final int createBy;
|
||||||
|
final String updateTime;
|
||||||
|
|
||||||
|
AccountBill({
|
||||||
|
required this.id,
|
||||||
|
this.memberId,
|
||||||
|
this.accountId,
|
||||||
|
this.moneyBalance = 0.0,
|
||||||
|
this.beforeBalance = 0.0,
|
||||||
|
this.afterBalance = 0.0,
|
||||||
|
this.changeAmount = 0.0,
|
||||||
|
this.changeType = 1,
|
||||||
|
this.changeDesc = '',
|
||||||
|
this.source = '未知来源',
|
||||||
|
this.createTime = '',
|
||||||
|
this.createBy = 0,
|
||||||
|
this.updateTime = '',
|
||||||
|
});
|
||||||
|
|
||||||
|
factory AccountBill.fromJson(Map<String, dynamic> json) {
|
||||||
|
return AccountBill(
|
||||||
|
id: json['id'] ?? 0,
|
||||||
|
memberId: json['member_id'],
|
||||||
|
accountId: json['account_id'],
|
||||||
|
moneyBalance: (json['money_balance'] as num?)?.toDouble() ?? 0.0,
|
||||||
|
beforeBalance: (json['before_balance'] as num?)?.toDouble() ?? 0.0,
|
||||||
|
afterBalance: (json['after_balance'] as num?)?.toDouble() ?? 0.0,
|
||||||
|
changeAmount: (json['change_amount'] as num?)?.toDouble() ?? 0.0,
|
||||||
|
changeType: json['change_type'] ?? 1,
|
||||||
|
changeDesc: json['change_desc'] ?? '',
|
||||||
|
source: json['source'] ?? '未知来源',
|
||||||
|
createTime: json['create_time'] ?? '',
|
||||||
|
createBy: json['create_by'] ?? 0,
|
||||||
|
updateTime: json['update_time'] ?? '',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user