import 'dart:io'; import 'package:cached_network_image/cached_network_image.dart'; import 'package:carousel_slider/carousel_controller.dart' as cslider; import 'package:carousel_slider/carousel_slider.dart'; import 'package:eitc_erm_app/select_clinic.dart'; import 'package:eitc_erm_app/select_doctor.dart'; import 'package:eitc_erm_app/select_patient.dart'; import 'package:eitc_erm_app/utils/Component.dart'; import 'package:eitc_erm_app/utils/Constants.dart'; import 'package:eitc_erm_app/utils/Utils.dart'; import 'package:eitc_erm_app/utils/logger.dart'; import 'package:eitc_erm_app/widget/circular_loading.dart'; import 'package:eitc_erm_app/widget/image_error.dart'; import 'package:eitc_erm_app/widget/loading.dart'; import 'package:eitc_erm_app/widget/marquee_widget.dart'; import 'package:eitc_erm_app/widget/user_header.dart'; import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; import 'Introduce.dart'; import 'bean/doctor_list.dart'; import 'bean/hospital_detail.dart'; import 'bean/notice_manage_list.dart'; import 'bean/user_info.dart'; import 'doctor_detail.dart'; import 'login.dart'; import 'notice_list.dart'; /*void main() { WidgetsFlutterBinding.ensureInitialized(); runApp(Home()); }*/ late BuildContext parentCxt; class Home extends StatefulWidget { Home(BuildContext context) { parentCxt = context; } @override State createState() => HomeState(); } class HomeState extends State { NoticeManageList mNoticeManageList = new NoticeManageList(); List noticeList = [" "]; @override void initState() { super.initState(); getInfo(); noticeManageList(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( backgroundColor: Global.StatusBarColor, title: Text( Global.clinic, style: const TextStyle(color: Colors.white), ), centerTitle: true, actions: [ IconButton( color: Colors.white, icon: const Icon( Icons.loop, ), onPressed: () { Navigator.pushReplacement( context, MaterialPageRoute( builder: (context) => SelectClinic("fromHome")), ); }), ], ), body: SafeArea( child: SingleChildScrollView( child: Column( mainAxisSize: MainAxisSize.min, //横向大小 crossAxisAlignment: CrossAxisAlignment.center, //纵向对齐方式 children: [ const Banner(), const Padding( padding: EdgeInsets.all(10), child: Row(children: [ SizedBox(width: 1), Text( '▊', style: TextStyle(fontSize: 15, color: Colors.blue), ), SizedBox(width: 20), Text( '门诊服务', style: TextStyle(fontSize: 15), ), ])), Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, //元素与空白互相间隔 children: [ Padding( padding: const EdgeInsets.all(10), child: GestureDetector( onTap: () { Navigator.push( context, MaterialPageRoute( builder: (context) => SelectPatient("")), ); }, child: Container( decoration: BoxDecoration( color: Colors.green[300], border: Border.all(color: Colors.green)), width: 160, child: const Column( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ SizedBox(height: 10), Icon( Icons.account_balance_wallet_outlined, color: Colors.white, ), SizedBox(height: 10), Text("预约挂号", style: TextStyle( fontSize: 15, color: Colors.white)), SizedBox(height: 10), Text("点击在线预约挂号", style: TextStyle( fontSize: 15, color: Colors.white)), SizedBox(height: 10), ], ), ), ), ), Padding( padding: const EdgeInsets.all(10), child: GestureDetector( onTap: () { // if(Global.selectDoctor == -1) { Navigator.push( context, MaterialPageRoute( builder: (context) => SelectDoctor("")), ); /*} else { */ /*Navigator.push( context, MaterialPageRoute(builder: (context) => ChatHome()), );*/ /* Navigator.push( context, MaterialPageRoute(builder: (context) => OnlineConsultationDetail()), ); }*/ }, child: Container( decoration: BoxDecoration( color: Colors.orange[300], border: Border.all(color: Colors.orange)), width: 160, child: const Column(children: [ SizedBox(height: 10), Icon( Icons.chat_outlined, color: Colors.white, ), SizedBox(height: 10), Text("线上咨询", style: TextStyle( fontSize: 15, color: Colors.white)), SizedBox(height: 10), Text("点击在线咨询医生", style: TextStyle( fontSize: 15, color: Colors.white)), SizedBox(height: 10), ]), ), ), ), ], ), Padding( padding: const EdgeInsets.only(left: 6), child: Row(children: [ const Icon( Icons.notifications, color: Colors.lightGreen, size: 18, ), const SizedBox(width: 18), Expanded( child: Container( alignment: Alignment.center, width: double.infinity, height: 24, child: noticeList.isNotEmpty ? buildMarqueeWidget(noticeList) : const Text( '', ), ), ), ])), const Padding( padding: EdgeInsets.all(10), child: Row( // mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ SizedBox(width: 1), Text( '▊', style: TextStyle(fontSize: 15, color: Colors.blue), ), SizedBox(width: 20), Text( '医生推荐', style: TextStyle(fontSize: 15), ), /*SizedBox(width: 190), Text( '查看更多>>', style: const TextStyle(fontSize: 13, color: Colors.grey), ),*/ ])), const DoctorRecommend(), ], ), ), )); } MarqueeWidget buildMarqueeWidget(List loopList) { ///上下轮播 安全提示 return MarqueeWidget( //子Item构建器 itemBuilder: (BuildContext context, int index) { String itemStr = loopList[index]; //通常可以是一个 Text文本 return GestureDetector( onTap: () { Navigator.push( context, MaterialPageRoute( builder: (context) => NoticeList(mNoticeManageList)), ); }, child: Text( itemStr, style: const TextStyle( fontSize: 16, color: Colors.lightGreen, fontWeight: FontWeight.w700, ), )); }, //循环的提示消息数量 count: loopList.length, ); } Future getInfo() async { logd(Global.token); final response = await http.get(Uri.parse('${Global.BaseUrl}user/getInfo'), headers: jsonHeaders(withToken: true)); if (response.statusCode == 200) { final json = decodeBodyToJson(response.bodyBytes); logd("用户信息=$json"); UserInfo mUserInfo = UserInfo.fromJson(json); if (mUserInfo.code == Global.responseSuccessCode) { final data = mUserInfo.data; if (data != null) { Global.userId = data.id!; Global.userIdentificationCard = data.identificationCard!; Global.loginPhoneNo = data.phoneNumber!; Utils.saveData( "userIdentificationCard", Global.userIdentificationCard); Utils.saveData("loginPhoneNo", Global.loginPhoneNo); } } else { Component.toast(mUserInfo.msg.toString(), 0); } return mUserInfo; } else { Component.toast("获取用户信息出错!", 0); } } Future noticeManageList() async { Map headers = { 'token': '${Global.token}', }; final response = await http.get( Uri.parse('${Global.BaseUrl}notice-manage/list'), headers: headers); logd(response.body.toString()); if (response.statusCode == 200) { final json = decodeBodyToJson(response.bodyBytes); logd("公告=$json"); mNoticeManageList = NoticeManageList.fromJson(json); if (mNoticeManageList.code == Global.responseSuccessCode) { noticeList.clear(); for (int i = 0; i < mNoticeManageList.data!.length; i++) { String line = mNoticeManageList.data![i].noticeTitle.toString(); if (line.length > 18) line = "${line.substring(0, 18)}..."; noticeList.add(line); } setState(() {}); return mNoticeManageList; } else { Component.toast(mNoticeManageList.msg.toString(), 0); } return null; } else { Component.toast("获取通知出错!", 0); return null; } } } class Banner extends StatefulWidget { const Banner({super.key}); @override BannerState createState() => BannerState(); } class BannerState extends State { HospitalDetail mHospitalDetail = new HospitalDetail(); @override void initState() { super.initState(); fetchHospitalData(); } Future fetchHospitalData() async { logd(Global.token); final response = await http .get(Uri.parse('${Global.BaseUrl}clinic-info/detail'), headers: jsonHeaders(withToken: true)); if (response.statusCode == 200) { final json = decodeBodyToJson(response.bodyBytes); logd("诊所详情=$json"); mHospitalDetail = HospitalDetail.fromJson(json); if (mHospitalDetail.code == Global.responseSuccessCode) { if (mHospitalDetail.data != null) { if (mHospitalDetail.data?.bannerPic1 != null) { list.add(Global.ImageUrl + mHospitalDetail.data!.bannerPic1!); } else { list.add(""); } if (mHospitalDetail.data?.bannerPic2 != null) { list.add(Global.ImageUrl + mHospitalDetail.data!.bannerPic2!); } if (mHospitalDetail.data?.bannerPic3 != null) { list.add(Global.ImageUrl + mHospitalDetail.data!.bannerPic3!); } } setState(() {}); } else if (mHospitalDetail.code == 401 || mHospitalDetail.code == 403) { Navigator.pushReplacementNamed(parentCxt, '/login'); } else { Component.toast(mHospitalDetail.msg.toString(), 0); } return mHospitalDetail; } else { Component.toast("获取顶部滚动条出错!", 0); } } final List list = []; int _current = 0; final cslider.CarouselSliderController _controller = cslider.CarouselSliderController(); @override Widget build(BuildContext context) { if (list.isEmpty) { return const SizedBox( height: 250, ); } if (list.length == 1) { return SizedBox( height: 250, child: GestureDetector( behavior: HitTestBehavior.opaque, onTap: () => _gotoHspitalDetail(context), child: _getBannerImage(list[0]), ), ); } return Stack( alignment: AlignmentDirectional.bottomCenter, children: [ CarouselSlider.builder( carouselController: _controller, options: CarouselOptions( height: 250, autoPlay: true, viewportFraction: 1.0, autoPlayInterval: const Duration(seconds: 3), onPageChanged: (index, reason) { setState(() { _current = index; }); }, ), itemCount: list.length, itemBuilder: (BuildContext context, int index, int pageViewIndex) { return GestureDetector( behavior: HitTestBehavior.opaque, onTap: () { switch (index) { case 0: _gotoHspitalDetail(context); break; case 1: break; case 2: break; } }, child: _getBannerImage(list[index]), ); }, ), Row( mainAxisAlignment: MainAxisAlignment.center, children: list.asMap().entries.map((entry) { return GestureDetector( onTap: () => _controller.animateToPage(entry.key), child: Container( width: 10.0, height: 10.0, margin: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 4.0), decoration: BoxDecoration( shape: BoxShape.circle, color: (Theme.of(context).brightness == Brightness.dark ? Colors.white : Colors.black) .withOpacity(_current == entry.key ? 0.9 : 0.4)), ), ); }).toList(), ), ], ); } void _gotoHspitalDetail(BuildContext context) { Navigator.push( context, MaterialPageRoute( builder: (context) => Introduce(hospitalDetail: mHospitalDetail, key: const Key(''))), ); } Widget _getBannerImage(String url) { return CachedNetworkImage( imageUrl: url, width: double.infinity, fit: BoxFit.cover, progressIndicatorBuilder: (ctx, _, progress) => Circularloading( value: progress.progress, ), errorWidget: (ctx, _, __) => const ImageError( size: 80, ), ); } } DoctorListEntity? data = DoctorListEntity(); class DoctorRecommend extends StatefulWidget { const DoctorRecommend({super.key}); @override State createState() => DoctorRecommendState(); } class DoctorRecommendState extends State { late Future _future; late BuildContext cxt; @override void initState() { super.initState(); _future = fetchData(); } Future fetchData() async { Map headers = { 'token': Global.token, }; final response = await http.get(Uri.parse('${Global.BaseUrl}doctor/list'), headers: jsonHeaders(withToken: true)); logd(Uri.parse('${Global.BaseUrl}doctor/list')); if (response.statusCode == 200) { final json = decodeBodyToJson(response.bodyBytes); logd("推荐医生=$json"); DoctorListEntity mDoctorListEntity = DoctorListEntity.fromJson(json); if (mDoctorListEntity.code == Global.responseSuccessCode) { return mDoctorListEntity; } else if (mDoctorListEntity.code == 401 || mDoctorListEntity.code == 403) { Navigator.of(context).pop(); Navigator.push( context, MaterialPageRoute(builder: (context) => Login()), ); return null; } else { Component.toast(mDoctorListEntity.msg.toString(), 0); return null; } } else { Component.toast("出错了,请稍后再试!", 0); } } @override Widget build(BuildContext context) { cxt = context; return Center( child: FutureBuilder( future: _future, builder: (context, snapshot) { if (snapshot.hasData) { data = snapshot.data; return GridView.builder( padding: const EdgeInsets.all(10), shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( //注意此行 crossAxisCount: 2, //每行 widget 数量 crossAxisSpacing: 10, //widget 水平之间的距离 mainAxisSpacing: 10, //widget 垂直之间的距离 ), itemCount: data?.data?.length, // itemCount: 2, itemBuilder: _customWidget, ); } else if (snapshot.hasError) { return Text('Error: ${snapshot.error}'); } return const ColorLoader(); }, ), ); } Widget _customWidget(BuildContext context, int index) { return GestureDetector( onTap: () { Global.doctor = data!; Global.selectDoctor = index; Navigator.push( cxt, MaterialPageRoute( builder: (context) => DoctorDetail( doctorListEntity: data, key: const Key(''), which: index)), ); }, child: Container( decoration: BoxDecoration( border: Border.all(color: Colors.grey), borderRadius: BorderRadius.circular(8), color: Colors.white, ), child: Column( children: [ const SizedBox( height: 10, ), UserHeader( url: "${Global.ImageUrl}${data?.data?[index].avatar}", ), Column( mainAxisSize: MainAxisSize.min, children: [ Text( data?.data?[index].nickName ?? "", style: Theme.of(context).textTheme.titleMedium, ), Text( "${data?.data?[index].deptName ?? ""} ${data?.data?[index].postNames ?? ""}", overflow: TextOverflow.ellipsis, style: Theme.of(context).textTheme.bodyMedium, ) ], ), const Spacer(), Padding( padding: const EdgeInsets.only(bottom: 10), child: _getProficientWidget( context, data?.data?[index].doctorProficient), ), ], ), ), ); } Widget _getProficientWidget(BuildContext context, String? proficients) { if (proficients == null || proficients.isEmpty) { return const SizedBox(); } List list = proficients.split(","); Widget row; if (list.isNotEmpty) { row = Row( mainAxisAlignment: MainAxisAlignment.center, children: [ _getProficientItem(list, 0, list.length > 1 ? Alignment.centerRight : Alignment.center), Visibility( visible: list.length > 1, child: const SizedBox( width: 10, )), Visibility( visible: list.length > 1, child: _getProficientItem(list, 1, Alignment.centerLeft), ), ], ); } else { row = const SizedBox(); } return Padding( padding: const EdgeInsets.symmetric(horizontal: 5), child: row, ); } Widget _getProficientItem(List list, int index, Alignment alignment) { if (list.length <= index) { return const SizedBox(); } return Expanded( child: Align( alignment: alignment, child: Container( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 3), decoration: BoxDecoration( borderRadius: BorderRadius.circular(30), color: Colors.lightBlueAccent), child: Text( textAlign: TextAlign.center, maxLines: 1, overflow: TextOverflow.ellipsis, list[index], style: const TextStyle(color: Colors.white, fontSize: 10), ), ), )); } }