import 'dart:async'; import 'package:flutter/material.dart'; import 'package:odf/bean/search_list_bean.dart'; import 'package:odf/tools/machine/machine_details_page.dart'; import 'package:odf/tools/search/search_model.dart'; import '../../bean/new_search_bean.dart'; import '../../bean/new_search_room_bean.dart'; import '../machine/machine_page.dart'; class SearchPage extends StatefulWidget { const SearchPage({super.key}); @override State createState() => _SearchPageState(); } class _SearchPageState extends State { late StreamSubscription subscription; final SearchModel _viewmodel = SearchModel(); List dataList = []; List roomList = []; // 控制列表滚动 final ScrollController _scrollController = ScrollController(); // 是否正在加载更多 bool _isLoadingMore = false; // 是否还有更多数据 final bool _hasMoreData = true; int pageNum = 1; @override void initState() { // TODO: implement initState super.initState(); // 监听滚动事件,实现上拉加载 _scrollController.addListener(_scrollListener); subscription = _viewmodel.streamController.stream.listen((event) { String code = event['code']; if (code.isNotEmpty) { switch (code) { case "newSearch": _isLoadingMore = false; NewSearchBean newSearchBean = event['data']; roomList.addAll(newSearchBean.rooms); dataList.addAll(newSearchBean.ports!.result!); // print("dataList==${dataList.length}"); break; } } setState(() {}); }); } @override void dispose() { // TODO: implement dispose _scrollController.dispose(); subscription.cancel(); super.dispose(); } String text = ""; void _textFieldChanged(String str) { text = str; setState(() {}); } void search(data) { text = data; roomList.clear(); dataList.clear(); _viewmodel.newSearch(data, 1, 20); } // 滚动监听 void _scrollListener() { // 判断是否滑到了列表底部 if (_scrollController.position.pixels >= _scrollController.position.maxScrollExtent - 100 && !_isLoadingMore && _hasMoreData) { _loadMoreData(); } } // 加载更多数据 Future _loadMoreData() async { if (_isLoadingMore) return; setState(() { _isLoadingMore = true; pageNum++; }); _viewmodel.searchDevice(text, pageNum, 20); } @override Widget build(BuildContext context) { final double statusBarHeight = MediaQuery.of(context).padding.top; final size = MediaQuery.of(context).size; final t10 = size.width / 36; final w25 = size.width / 14.4; final p5 = size.width / 72; final w9 = size.width / 40; final s21 = size.width / 17.142857142857; final t20 = size.width / 18; final l15 = size.width / 24; final h32 = size.width / 11.25; final c16 = size.width / 22.5; final t14 = size.width / 25.714285714285; final s12 = size.width / 30; final w60 = size.width / 6; return Scaffold( backgroundColor: const Color(0xFFD8D8D8), body: Container( decoration: const BoxDecoration( image: DecorationImage( image: AssetImage('assets/images/home_bg.png'), fit: BoxFit.cover, )), child: Column( crossAxisAlignment: CrossAxisAlignment.center, children: [ Container( margin: EdgeInsets.only(top: statusBarHeight + t10, left: t10, right: t10), child: Row( crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ GestureDetector( onTap: () { Navigator.pop(context); }, child: Container( width: w25, height: w25, padding: EdgeInsets.all(p5), child: Image( width: w9, image: const AssetImage('assets/images/ic_back.png'), ), ), ), Container( alignment: Alignment.center, child: Text( '搜索', style: TextStyle(fontSize: s21, fontWeight: FontWeight.w600), ), ), Container( width: w25, height: w25, padding: EdgeInsets.all(p5), ), ], ), ), Container( margin: EdgeInsets.only(top: t10, left: l15, right: l15, bottom: t10), child: Row( children: [ Expanded( child: Container( height: h32, alignment: Alignment.center, decoration: BoxDecoration( color: Colors.white, border: Border.all(width: 0.5, color: Colors.black12), borderRadius: BorderRadius.all(Radius.circular(c16)), ), child: Container( margin: EdgeInsets.only(left: t20), padding: EdgeInsets.only(top: t14), child: TextField( onChanged: _textFieldChanged, cursorColor: const Color(0xFF1A73EC), decoration: InputDecoration( hintText: '请输入要搜索的备注内容', border: InputBorder.none, enabledBorder: InputBorder.none, focusedBorder: InputBorder.none, hintStyle: TextStyle(color: const Color(0xFF999999), fontSize: s12), ), textInputAction: TextInputAction.search, style: TextStyle(fontSize: s12), onSubmitted: (value) { // 当用户点击键盘的 "搜索" 按钮时触发 // print("搜索内容: $value"); search(value); }, ), ), ), ), GestureDetector( onTap: () { search(text); }, child: Container( width: w60, height: h32, alignment: Alignment.center, margin: EdgeInsets.only(left: t20), decoration: BoxDecoration( color: const Color(0xFF1A73EC), borderRadius: BorderRadius.all(Radius.circular(c16)), ), child: Text( "搜索", style: TextStyle(color: Colors.white, fontSize: t14), ), ), ) ], ), ), Expanded( child: SingleChildScrollView( // 添加内边距,让内容与边缘有间距 padding: EdgeInsets.symmetric(horizontal: t10, vertical: t10), // 滚动物理效果(iOS风格的弹性滚动) physics: const BouncingScrollPhysics(), controller: _scrollController, child: Column( children: [ roomList.isNotEmpty ? Container( alignment: Alignment.centerLeft, margin: EdgeInsets.symmetric(vertical: 10, horizontal: 5), child: Text( '机房', style: TextStyle(fontSize: 16, color: Color(0xFF1A73EC)), ), ) : Container(), roomList.isNotEmpty ? ListView.builder( itemCount: roomList.length, shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), padding: const EdgeInsets.all(0), itemBuilder: (BuildContext context, int index) { return _roomItem(roomList[index], t10); }) : Container(), dataList.isNotEmpty ? Container( alignment: Alignment.centerLeft, margin: EdgeInsets.symmetric(vertical: 10, horizontal: 5), child: Text( '备注信息', style: TextStyle(fontSize: 16, color: Color(0xFF1A73EC)), ), ) : Container(), ListView.builder( itemCount: dataList.length, shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), padding: const EdgeInsets.all(0), itemBuilder: (BuildContext context, int index) { return _item(dataList[index], t10); }), ], ), ), ), ], ), ), ); } _roomItem(NewSearchRoomBean data, t10) { return GestureDetector( onTap: () { Navigator.push( context, MaterialPageRoute( builder: (context) => MachinePage( roomId: "${data.roomId}", roomName: "${data.roomName}", ), ), ); }, child: Card( color: Colors.white, child: Container( margin: EdgeInsets.only(bottom: t10), child: Column( children: [ Container( alignment: Alignment.centerLeft, margin: EdgeInsets.only(left: t10, top: t10), child: Text( "机房名: ${data.roomName}", style: const TextStyle(color: Color(0xFF666666)), ), ), ], ), ), ), ); } _item(SearchListBean data, t10) { return GestureDetector( onTap: () { Navigator.push( context, MaterialPageRoute( builder: (context) => MachineDetailsPage( rackId: '${data.rackId}', dofName: '${data.rackName}', isOpenPop: true, dropId: '${data.id}', roomName: '${data.roomName}', ), ), ); }, child: Card( color: Colors.white, child: Container( margin: EdgeInsets.only(bottom: t10), child: Column( children: [ Container( alignment: Alignment.centerLeft, margin: EdgeInsets.only(left: t10, top: t10), child: Text( "机房名: ${data.roomName}", style: const TextStyle(color: Color(0xFF666666)), ), ), Container( alignment: Alignment.centerLeft, margin: EdgeInsets.only(left: t10, top: t10, right: t10), child: Text( "地址: ${data.address}", style: const TextStyle(color: Color(0xFF666666)), ), ), Container( alignment: Alignment.centerLeft, margin: EdgeInsets.only(left: t10, top: t10, right: t10), child: Text("ODF名称: ${data.rackName}"), ), Container( alignment: Alignment.centerLeft, margin: EdgeInsets.only(left: t10, top: t10, right: t10), child: Text("点位置: ${data.frameName}${data.name}"), ), data.remarks != "" ? Container( alignment: Alignment.centerLeft, margin: EdgeInsets.only(left: t10, top: t10, right: t10), child: Text("备注: ${data.remarks}"), ) : Container(), data.opticalAttenuation != "" ? Container( alignment: Alignment.centerLeft, margin: EdgeInsets.only(left: t10, top: t10, right: t10), child: Text("光衰信息: ${data.opticalAttenuation}"), ) : Container(), data.historyRemarks != "" ? Container( alignment: Alignment.centerLeft, margin: EdgeInsets.only(left: t10, top: t10, right: t10), child: Text("历史故障原因及时间: ${data.historyRemarks}"), ) : Container(), data.opticalCableOffRemarks != "" ? Container( alignment: Alignment.centerLeft, margin: EdgeInsets.only(left: t10, top: t10, right: t10), child: Text("光缆段信息: ${data.opticalCableOffRemarks}"), ) : Container(), Container( alignment: Alignment.centerLeft, margin: EdgeInsets.only(left: t10, top: t10, right: t10), child: Row( children: [ Text( "当前状态:", style: TextStyle(fontSize: 12), ), Container( width: 12, height: 12, margin: EdgeInsets.only(left: t10, right: 5), decoration: BoxDecoration( color: data.status == 0 ? Colors.red : Colors.green, shape: BoxShape.circle, ), ), Container( child: Text( data.status == 0 ? "已断开" : "已连接", style: TextStyle(fontSize: 12), ), ) ], ), ) ], ), ), ), ); } }