From 5d871a84f689cafd0c3344a3dbfcbc7b66fd9ffd Mon Sep 17 00:00:00 2001 From: ZHR007 Date: Fri, 14 Nov 2025 14:11:28 +0800 Subject: [PATCH] no message --- .../discover/visitor_controller.dart | 151 ++++++++++ lib/controller/mine/mine_controller.dart | 8 +- lib/model/discover/visitor_model.dart | 75 +++++ lib/pages/discover/visitor_list_page.dart | 257 ++++++++++++++++++ lib/pages/mine/mine_page.dart | 7 +- 5 files changed, 493 insertions(+), 5 deletions(-) create mode 100644 lib/controller/discover/visitor_controller.dart create mode 100644 lib/model/discover/visitor_model.dart create mode 100644 lib/pages/discover/visitor_list_page.dart diff --git a/lib/controller/discover/visitor_controller.dart b/lib/controller/discover/visitor_controller.dart new file mode 100644 index 0000000..d2eca07 --- /dev/null +++ b/lib/controller/discover/visitor_controller.dart @@ -0,0 +1,151 @@ +// controllers/visitor_controller.dart +import 'package:get/get.dart'; +import 'package:pull_to_refresh/pull_to_refresh.dart'; +import '../../model/discover/visitor_model.dart'; + +class VisitorController extends GetxController { + // 访客列表 + var visitors = [].obs; + + // Refresh controllers + final RefreshController refreshController = RefreshController(); + final RefreshController loadMoreController = RefreshController(); + + // 分页参数 + var currentPage = 1.obs; + final int pageSize = 15; + var hasMore = true.obs; + var isLoading = false.obs; + + @override + void onInit() { + super.onInit(); + _loadInitialData(); + } + + // 加载初始数据 + void _loadInitialData() async { + isLoading.value = true; + await Future.delayed(Duration(milliseconds: 800)); // 模拟网络延迟 + + final initialVisitors = _generateMockData(1, pageSize); + visitors.assignAll(initialVisitors); + + isLoading.value = false; + hasMore.value = initialVisitors.length == pageSize; + } + + // 下拉刷新 + void onRefresh() async { + currentPage.value = 1; + hasMore.value = true; + + await Future.delayed(Duration(milliseconds: 1000)); // 模拟网络延迟 + + final newVisitors = _generateMockData(1, pageSize); + visitors.assignAll(newVisitors); + + refreshController.refreshCompleted(); + hasMore.value = newVisitors.length == pageSize; + + if (newVisitors.isEmpty) { + refreshController.loadNoData(); + } else { + refreshController.loadComplete(); + } + } + + // 上拉加载更多 + void onLoadMore() async { + if (!hasMore.value) { + loadMoreController.loadNoData(); + return; + } + + currentPage.value++; + + await Future.delayed(Duration(milliseconds: 800)); // 模拟网络延迟 + + final newVisitors = _generateMockData(currentPage.value, pageSize); + + if (newVisitors.isEmpty) { + hasMore.value = false; + loadMoreController.loadNoData(); + } else { + visitors.addAll(newVisitors); + loadMoreController.loadComplete(); + hasMore.value = false; + } + } + + // 删除访客 + void deleteVisitor(String visitorId) { + // visitors.removeWhere((visitor) => visitor.id == visitorId); + Get.snackbar('成功', '已删除访客记录'); + } + + // 清空所有访客记录 + void clearAllVisitors() { + visitors.clear(); + Get.snackbar('成功', '已清空所有访客记录'); + } + + // 获取今日访客数量 + int get todayVisitorsCount { + return visitors.length; + } + + // 获取在线访客数量 + int get onlineVisitorsCount { + return visitors.length; + } + + // 模拟数据生成 + List _generateMockData(int page, int size) { + if (page > 3) return []; // 模拟只有3页数据 + + final names = [ + '张三', '李四', '王五', '赵六', '钱七', '孙八', '周九', '吴十', + '小明', '小红', '小刚', '小花', '大山', '小云', '星辰', '大海' + ]; + + final avatars = [ + 'https://randomuser.me/api/portraits/men/1.jpg', + 'https://randomuser.me/api/portraits/women/1.jpg', + 'https://randomuser.me/api/portraits/men/2.jpg', + 'https://randomuser.me/api/portraits/women/2.jpg', + 'https://randomuser.me/api/portraits/men/3.jpg', + 'https://randomuser.me/api/portraits/women/3.jpg', + 'https://randomuser.me/api/portraits/men/4.jpg', + 'https://randomuser.me/api/portraits/women/4.jpg', + ]; + + final pages = [ + '首页', '产品页', '关于我们', '博客', '联系方式', '服务页', '价格页', '案例页' + ]; + + final startIndex = (page - 1) * size; + final endIndex = startIndex + size; + + return List.generate(size, (index) { + final globalIndex = startIndex + index; + final isOnline = globalIndex % 3 == 0; // 每3个有一个在线 + + return VisitorModel( + miId: 'visitor_${globalIndex + 1}', + nickName: names[globalIndex % names.length], + profilePhoto: avatars[globalIndex % avatars.length], + visitTime: '2025-11-14 10:42:42', + onlineStatus: 2, + describeInfo: '阿萨德垃圾袋杰克伦敦撒娇克拉斯的健康拉屎的 金坷垃四大皆空拉屎的距离考试啊' + ); + }); + } + + @override + void onClose() { + refreshController.dispose(); + loadMoreController.dispose(); + super.onClose(); + } +} \ No newline at end of file diff --git a/lib/controller/mine/mine_controller.dart b/lib/controller/mine/mine_controller.dart index 29e7bf8..99e788e 100644 --- a/lib/controller/mine/mine_controller.dart +++ b/lib/controller/mine/mine_controller.dart @@ -9,10 +9,10 @@ class MineController extends GetxController { List infoList = [ - {"label": "我的关注", "num": 88}, - {"label": "关注我的", "num": 18988}, - {"label": "好友", "num": 8}, - {"label": "访客", "num": 357}, + {"label": "我的关注", "num": 88, "type": 1}, + {"label": "关注我的", "num": 18988, "type": 2}, + {"label": "好友", "num": 8, "type": 3}, + {"label": "访客", "num": 357, "type": 4}, ].obs; List blockList = [ diff --git a/lib/model/discover/visitor_model.dart b/lib/model/discover/visitor_model.dart new file mode 100644 index 0000000..66a7e0d --- /dev/null +++ b/lib/model/discover/visitor_model.dart @@ -0,0 +1,75 @@ +class VisitorModel { + final String? miId; + final String? profilePhoto; + final String? nickName; + final int? height; + final String? visitTime; + final String? education; + final int? age; + final int? minimumIncome; + final int? maximumIncome; + final String? income; + final String? describeInfo; + final int? vip; + final int? miSessionType; + final int? genderCode; + final int? onlineStatus; + + VisitorModel({ + this.miId, + this.profilePhoto, + this.nickName, + this.height, + this.visitTime, + this.education, + this.age, + this.minimumIncome, + this.maximumIncome, + this.income, + this.describeInfo, + this.vip, + this.miSessionType, + this.genderCode, + this.onlineStatus, + }); + + factory VisitorModel.fromJson(Map json) { + return VisitorModel( + miId: json['miId'] as String?, + profilePhoto: json['profilePhoto'] as String?, + nickName: json['nickName'] as String?, + height: json['height'] as int?, + visitTime: json['visitTime'] as String?, + education: json['education'] as String?, + age: json['age'] as int?, + minimumIncome: json['minimumIncome'] as int?, + maximumIncome: json['maximumIncome'] as int?, + income: json['income'] as String?, + describeInfo: json['describeInfo'] as String?, + vip: json['vip'] as int?, + miSessionType: json['miSessionType'] as int?, + genderCode: json['genderCode'] as int?, + onlineStatus: json['onlineStatus'] as int?, + ); + } + + Map toJson() { + return { + 'miId': miId, + 'profilePhoto': profilePhoto, + 'nickName': nickName, + 'height': height, + 'visitTime': visitTime, + 'education': education, + 'age': age, + 'minimumIncome': minimumIncome, + 'maximumIncome': maximumIncome, + 'income': income, + 'describeInfo': describeInfo, + 'vip': vip, + 'miSessionType': miSessionType, + 'genderCode': genderCode, + 'onlineStatus': onlineStatus, + }; + } +} \ No newline at end of file diff --git a/lib/pages/discover/visitor_list_page.dart b/lib/pages/discover/visitor_list_page.dart new file mode 100644 index 0000000..4f0639f --- /dev/null +++ b/lib/pages/discover/visitor_list_page.dart @@ -0,0 +1,257 @@ +// pages/visitor_list_page.dart +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:dating_touchme_app/extension/ex_widget.dart'; +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:pull_to_refresh/pull_to_refresh.dart'; + +import '../../controller/discover/visitor_controller.dart'; +import '../../model/discover/visitor_model.dart'; + +class VisitorListPage extends StatelessWidget { + final VisitorController visitorController = Get.put(VisitorController()); + + VisitorListPage({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: Color(0xffF5F5F5), + appBar: AppBar( + title: Obx(() => Text( + '最近访客 (${visitorController.todayVisitorsCount})', + style: TextStyle(fontSize: 16), + )), + backgroundColor: Colors.white, + actions: [ + // 更多操作 + PopupMenuButton( + onSelected: (value) { + if (value == 'clear') { + _showClearDialog(); + } else if (value == 'sort') { + _showSortDialog(); + } + }, + itemBuilder: (BuildContext context) => [ + PopupMenuItem(value: 'sort', child: Text('排序方式')), + PopupMenuItem(value: 'clear', child: Text('清空记录')), + ], + ), + ], + ), + body: Obx(() { + if (visitorController.isLoading.value && visitorController.visitors.isEmpty) { + return Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + CircularProgressIndicator(), + SizedBox(height: 16), + Text('加载访客数据中...'), + ], + ), + ); + } + + if (visitorController.visitors.isEmpty) { + return Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon(Icons.people_outline, size: 80, color: Colors.grey[300]), + SizedBox(height: 16), + Text( + '暂无访客记录', + style: TextStyle(fontSize: 18, color: Colors.grey), + ), + SizedBox(height: 8), + Text( + '下拉刷新获取数据', + style: TextStyle(color: Colors.grey), + ), + ], + ), + ); + } + + return SmartRefresher( + controller: visitorController.refreshController, + enablePullDown: true, + enablePullUp: visitorController.hasMore.value, + onRefresh: visitorController.onRefresh, + onLoading: visitorController.onLoadMore, + header: ClassicHeader( + idleText: '下拉刷新', + releaseText: '松开刷新', + refreshingText: '刷新中...', + completeText: '刷新完成', + failedText: '刷新失败', + height: 60, + ), + footer: CustomFooter( + builder: (BuildContext context, LoadStatus? mode) { + Widget body; + if (mode == LoadStatus.idle) { + body = Text("上拉加载更多"); + } else if (mode == LoadStatus.loading) { + body = CircularProgressIndicator(); + } else if (mode == LoadStatus.failed) { + body = Text("加载失败,点击重试"); + } else if (mode == LoadStatus.canLoading) { + body = Text("松开加载更多"); + } else { + body = Text("没有更多数据了"); + } + return SizedBox( + height: 36, + child: Center(child: body), + ); + }, + ), + child: ListView.builder( + padding: const EdgeInsets.only(top: 8, right: 10, left: 10), + itemCount: visitorController.visitors.length, + itemBuilder: (context, index) { + final visitor = visitorController.visitors[index]; + return VisitorListItem(visitor: visitor); + }, + ), + ); + }), + ); + } + + void _showClearDialog() { + Get.dialog( + AlertDialog( + title: Text('确认清空'), + content: Text('确定要清空所有访客记录吗?此操作不可恢复。'), + actions: [ + TextButton( + onPressed: () => Get.back(), + child: Text('取消'), + ), + TextButton( + onPressed: () { + visitorController.clearAllVisitors(); + Get.back(); + }, + child: Text('确定', style: TextStyle(color: Colors.red)), + ), + ], + ), + ); + } + + void _showSortDialog() { + Get.dialog( + AlertDialog( + title: Text('排序方式'), + content: Column( + mainAxisSize: MainAxisSize.min, + children: [ + ListTile( + title: Text('按访问时间'), + onTap: () { + // 实现排序逻辑 + Get.back(); + }, + ), + ListTile( + title: Text('按访问时长'), + onTap: () { + // 实现排序逻辑 + Get.back(); + }, + ), + ListTile( + title: Text('按访问次数'), + onTap: () { + // 实现排序逻辑 + Get.back(); + }, + ), + ], + ), + ), + ); + } +} + +class VisitorListItem extends StatelessWidget { + final VisitorModel visitor; + + const VisitorListItem({Key? key, required this.visitor}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Container( + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(12), + ), + padding: const EdgeInsets.all(12), + margin: EdgeInsets.only(bottom: 8), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + // 左侧图片 + Container( + width: 50, + height: 50, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(8), + color: Colors.blue[100], + image: DecorationImage( + image: NetworkImage(visitor.profilePhoto!), + fit: BoxFit.cover, + ), + ), + ), + SizedBox(width: 12), + Expanded( + child: Column( + children: [ + Row( + children: [ + Text( + visitor.nickName!, + style: TextStyle( + fontSize: 14, + ), + ), + Spacer(), + Text( + visitor.visitTime!, + style: TextStyle( + color: Colors.grey[500], + fontSize: 13, + ), + ), + ], + ), + SizedBox(height: 4), + SizedBox( + // height: 20, // 固定高度20 + child: Text( + visitor.describeInfo!, + style: TextStyle( + fontSize: 13, + color: Color.fromRGBO(51, 51, 51, 0.6), + ), + overflow: TextOverflow.ellipsis, // 文本超出显示... + maxLines: 1, // 限制为单行 + ), + ), + ], + ) + ) + ], + ), + ).onTap((){ + // _showVisitorDetail(visitor); + }); + } + +} \ No newline at end of file diff --git a/lib/pages/mine/mine_page.dart b/lib/pages/mine/mine_page.dart index 7b3f221..0f0081f 100644 --- a/lib/pages/mine/mine_page.dart +++ b/lib/pages/mine/mine_page.dart @@ -1,5 +1,6 @@ import 'package:dating_touchme_app/controller/mine/mine_controller.dart'; import 'package:dating_touchme_app/extension/ex_widget.dart'; +import 'package:dating_touchme_app/pages/discover/visitor_list_page.dart'; import 'package:dating_touchme_app/pages/mine/edit_info_page.dart'; import 'package:dating_touchme_app/pages/mine/vip_page.dart'; import 'package:flutter/material.dart'; @@ -224,7 +225,11 @@ class _InfoItemState extends State { ), ) ], - ); + ).onTap((){ + if(widget.item['type'] == 4){ + Get.to(()=> VisitorListPage()); + } + }); } }