import 'dart:convert'; import 'package:environmental_protection/common/user_information.dart'; import 'package:environmental_protection/icon/material_design_icons.dart'; import 'package:flutter/material.dart'; class HomePage extends StatefulWidget { const HomePage({super.key}); @override State createState() => _HomePageState(); } class _HomePageState extends State { @override Widget build(BuildContext context) { return ListView( padding: const EdgeInsetsDirectional.all(10), children: const [ Advantage(), Notifications(), Applications(), Activities(), Dynamics(), Reminders() ], ); } } class Advantage extends StatefulWidget { const Advantage({super.key}); @override State createState() => _AdvantageState(); } class _AdvantageState extends State { List urls = []; int _index = 0; @override void initState() { super.initState(); _fetchAdvImages(); } Future _fetchAdvImages() async { final response = await GlobalInformation.getInstance() .requester .get(resolve('/api/adv/list')); if (response.statusCode == 200) { final data = jsonDecode(response.body); setState(() { urls = (data['data'] as List) .map((adv) => adv['image'] as String) .toList(); }); } } @override Widget build(BuildContext context) { List container = []; double width = 10; double height = 10; for (var i = 0; i < urls.length; i++) { var c = Container( width: width, height: height, decoration: const BoxDecoration(shape: BoxShape.circle, color: Colors.grey), margin: const EdgeInsetsDirectional.all(2)); if (i == _index) { c = Container( width: width, height: height, decoration: const BoxDecoration(shape: BoxShape.circle, color: Colors.blue), margin: const EdgeInsetsDirectional.all(2)); } container.add(c); } return Column( children: [ if (urls.isNotEmpty) SizedBox( height: 200, child: PageView( scrollDirection: Axis.horizontal, children: urls .map((e) => Image( image: NetworkImage( "http://124.93.196.45:10091/Neusoft/community$e"))) .toList(), onPageChanged: (index) { setState(() { _index = index; }); }, ), ), Container( margin: const EdgeInsetsDirectional.only(top: 10), child: Flex( direction: Axis.horizontal, mainAxisAlignment: MainAxisAlignment.center, children: container, ), ) ], ); } } class Notifications extends StatefulWidget { const Notifications({super.key}); @override State createState() => _NotificationsState(); } class _NotificationsState extends State { String _notification = "通知"; @override void initState() { super.initState(); _fetchNotices(); } Future _fetchNotices() async { final response = await GlobalInformation.getInstance() .requester .get(resolve('/api/notice/list')); if (response.statusCode == 200) { final data = jsonDecode(response.body); setState(() { _notification = data['rows'][0]['noticeTitle']; }); } } @override Widget build(BuildContext context) { return Row( children: [ const Icon(MaterialDesign.sms, color: Colors.blue), Text(_notification) ], ); } } class Application extends StatelessWidget { final IconData icon; final String title; const Application({super.key, required this.icon, required this.title}); @override Widget build(BuildContext context) { return Container( width: 60, height: 60, decoration: BoxDecoration( border: Border.all(color: Colors.blue), borderRadius: BorderRadius.circular(10)), alignment: Alignment.center, margin: const EdgeInsetsDirectional.all(10), child: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [Icon(icon), Text(title)], ), ); } } class Applications extends StatefulWidget { const Applications({super.key}); @override State createState() => _ApplicationsState(); } class _ApplicationsState extends State { @override Widget build(BuildContext context) { return SizedBox( height: 200, child: GridView( gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 4), children: const [ Application(icon: MaterialDesign.exit_to_app, title: "开门"), Application(icon: MaterialDesign.home, title: "我的房屋"), Application(icon: MaterialDesign.directions_car, title: "我的车位"), Application(icon: Icons.account_balance_wallet, title: "物业缴费"), Application(icon: MaterialDesign.crop_free, title: "扫码取件"), Application(icon: MaterialDesign.sms, title: "社区公告"), Application(icon: MaterialDesign.call, title: "社区电话"), Application(icon: MaterialDesign.email, title: "投诉建议"), ], ), ); } } class Activity extends StatelessWidget { final String title; final double kmDistance; final String imageUrl; const Activity( {super.key, required this.title, required this.kmDistance, required this.imageUrl}); @override Widget build(BuildContext context) { return Container( width: 200, height: 50, margin: const EdgeInsetsDirectional.all(5), padding: const EdgeInsetsDirectional.all(5), decoration: BoxDecoration( border: Border.all( color: const Color.fromARGB(50, 0, 0, 100), width: 1, ), borderRadius: BorderRadius.circular(10), ), child: Row( children: [ SizedBox( width: 80, height: 50, child: Image.network(imageUrl, fit: BoxFit.fill), ), SizedBox( width: 100, child: Column( children: [ Container( margin: const EdgeInsetsDirectional.only(start: 10, top: 10), child: Text( title, softWrap: true, ), ), Container( alignment: Alignment.centerLeft, margin: const EdgeInsetsDirectional.only(start: 10, top: 5), child: Text( "距您$kmDistance km", style: const TextStyle( color: Colors.grey, fontSize: 10, ), textAlign: TextAlign.left, ), ) ], ), ) ], ), ); } } class Activities extends StatefulWidget { const Activities({super.key}); @override State createState() => _ActivitiesState(); } class _ActivitiesState extends State { List> _activities = []; @override void initState() { super.initState(); _fetchActivities(); } Future _fetchActivities() async { final response = await GlobalInformation.getInstance() .requester .get(resolve('/api/cms/article/list')); if (response.statusCode == 200) { final data = jsonDecode(response.body); setState(() { _activities = (data['rows'] as List) .map((activity) => { 'title': activity['title'], 'kmDistance': double.parse(activity['location']), 'imageUrl': "http://124.93.196.45:10091/Neusoft/community${activity['cover']}", }) .toList(); }); } } @override Widget build(BuildContext context) { return ShowMoreContainer( title: "社区活动", showMore: true, child: SizedBox( height: 100, child: ListView( scrollDirection: Axis.horizontal, children: _activities.map((activity) { return Activity( title: activity['title'], kmDistance: activity['kmDistance'], imageUrl: activity['imageUrl'], ); }).toList(), ), ), ); } } class Dynamic extends StatelessWidget { final String title; final String source; final int commentCount; final DateTime sendTime; final String imageUrl; const Dynamic({ super.key, required this.title, required this.source, required this.commentCount, required this.sendTime, required this.imageUrl, }); @override Widget build(BuildContext context) { var beforeTime = DateTime.now().difference(sendTime); var hour = beforeTime.inHours; var time = "$hour 小时前"; if (hour > 24) { time = "1 天前"; } return Flex( direction: Axis.horizontal, mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Padding( padding: const EdgeInsetsDirectional.all(10), child: Column( children: [ SizedBox( width: 170, child: Text( title, softWrap: true, maxLines: 2, overflow: TextOverflow.ellipsis, style: const TextStyle( fontSize: 24, fontWeight: FontWeight.w900), ), ), Text( "$source $commentCount评论 $time", style: const TextStyle(color: Colors.grey), ), ], ), ), Expanded( child: SizedBox( height: 100, child: Padding( padding: const EdgeInsetsDirectional.all(2), child: Image.network(imageUrl, fit: BoxFit.fitHeight) ) ), ), ], ); } } class Dynamics extends StatefulWidget { const Dynamics({super.key}); @override State createState() => _DynamicsState(); } class _DynamicsState extends State { List> _dynamics = []; @override void initState() { super.initState(); _fetchDynamics(); } Future _fetchDynamics() async { final response = await GlobalInformation.getInstance() .requester .get(resolve('/api/cms/article/list')); if (response.statusCode == 200) { final data = jsonDecode(response.body); setState(() { _dynamics = (data['rows'] as List) .map((dynamic) => { 'title': dynamic['title'], 'commentCount': dynamic['commentNum'], 'sendTime': DateTime.parse(dynamic['createTime']), 'imageUrl': "http://124.93.196.45:10091/Neusoft/community${dynamic['cover']}", }) .toList(); }); } } @override Widget build(BuildContext context) { return ShowMoreContainer( title: "社区动态", showMore: true, child: Column( children: _dynamics.map((dynamic) { return Dynamic( title: dynamic['title'], source: "内容来源", commentCount: dynamic['commentCount'], sendTime: dynamic['sendTime'], imageUrl: dynamic['imageUrl'], ); }).toList(), ), ); } } class Reminder extends StatelessWidget { final String message; final IconData icon; const Reminder({super.key, required this.message, required this.icon}); @override Widget build(BuildContext context) { return Container( margin: const EdgeInsetsDirectional.only(top: 10), child: Row( children: [ SizedBox( width: 50, height: 50, child: Icon(icon, color: Colors.green), ), Expanded( child: Container( margin: const EdgeInsetsDirectional.only(start: 10), child: Flex( direction: Axis.vertical, crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( "认证申请进度提醒", style: TextStyle( fontWeight: FontWeight.w700, fontSize: 20, ), ), SizedBox( width: 300, child: Text( message, style: const TextStyle( color: Colors.grey, fontSize: 12, overflow: TextOverflow.ellipsis), ), ) ], ), ), ), Row( children: [ Container( width: 5, height: 5, decoration: const BoxDecoration( color: Colors.red, shape: BoxShape.circle), ), const Icon(Icons.keyboard_arrow_right, color: Colors.grey) ], ) ], ), ); } } class Reminders extends StatefulWidget { const Reminders({super.key}); @override State createState() => _RemindersState(); } class _RemindersState extends State { final List> _reminders = []; @override void initState() { super.initState(); _fetchReminders(); } Future _fetchReminders() async { final response = await GlobalInformation.getInstance() .requester .get(resolve('/api/house/list')); if (response.statusCode == 200) { final data = jsonDecode(response.body); setState(() { data['data'].forEach((e) => _reminders.add(e)); }); } } @override Widget build(BuildContext context) { return ShowMoreContainer( title: "认证提醒", showMore: false, child: SizedBox( height: 300, child: ListView.builder( itemCount: _reminders.length, itemBuilder: (BuildContext context, int index) { var reminder = _reminders[index]; var status = reminder['status']; var unitName = reminder['unitName']; var roomName = reminder['roomName']; var estateName = reminder['estateName']; var buildingName = reminder['buildingName']; var address = reminder['address']; var houseName = "您位于$address$estateName$buildingName$unitName$roomName的房屋"; var data = "已经$status"; var icon = MaterialDesign.check_circle; if (status == "认证中") { data = "正在认证中"; icon = MaterialDesign.cancel; } var message = houseName + data; return Reminder( message: message, icon: icon, ); }, ), ), ); } } class ShowMoreContainer extends StatelessWidget { final String title; final Widget child; final bool showMore; const ShowMoreContainer( {super.key, required this.title, required this.child, required this.showMore}); @override Widget build(BuildContext context) { var titleWidget = [ Positioned( left: 0, top: 0, child: Text( title, style: const TextStyle(fontSize: 20), ), ), ]; if (showMore) { titleWidget.add( Positioned( right: 0, top: 0, child: InkWell( onTap: () {}, child: const Row( children: [ Text("查看更多"), Icon(MaterialDesign.keyboard_arrow_right), ], ), ), ), ); } return Column( children: [ SizedBox( height: 30, child: Stack( children: titleWidget, ), ), Container( margin: const EdgeInsetsDirectional.only(top: 10), child: child, ), ], ); } }