Browse Source

no message

ios
ZHR007 4 months ago
parent
commit
5d871a84f6
5 changed files with 493 additions and 5 deletions
  1. 151
      lib/controller/discover/visitor_controller.dart
  2. 8
      lib/controller/mine/mine_controller.dart
  3. 75
      lib/model/discover/visitor_model.dart
  4. 257
      lib/pages/discover/visitor_list_page.dart
  5. 7
      lib/pages/mine/mine_page.dart

151
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 = <VisitorModel>[].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<VisitorModel> _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();
}
}

8
lib/controller/mine/mine_controller.dart

@ -9,10 +9,10 @@ class MineController extends GetxController {
List<Map> 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<Map> blockList = [

75
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<String, dynamic> 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<String, dynamic> 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,
};
}
}

257
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<String>(
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);
});
}
}

7
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<InfoItem> {
),
)
],
);
).onTap((){
if(widget.item['type'] == 4){
Get.to(()=> VisitorListPage());
}
});
}
}

Loading…
Cancel
Save