From 13018028f9555878e88c034dbfee04df75b38d0a Mon Sep 17 00:00:00 2001 From: wzp Date: Wed, 28 Aug 2024 18:46:58 +0800 Subject: [PATCH] day 1 --- lib/common/user_information.dart | 6 +- lib/main.dart | 1 + lib/views/home.dart | 465 +++++++++++++++++++++---------- 3 files changed, 320 insertions(+), 152 deletions(-) diff --git a/lib/common/user_information.dart b/lib/common/user_information.dart index fd5f68f..5f51e83 100644 --- a/lib/common/user_information.dart +++ b/lib/common/user_information.dart @@ -22,7 +22,7 @@ class UserInformation { late String _sex; late int _userId; late int _userName; - + } class GlobalInformation { String _token = ""; @@ -58,5 +58,9 @@ class GlobalInformation { } Uri resolve(String uri){ + if (uri.startsWith("/")){ + uri = uri.replaceFirst("/", ""); + } + print(uri); return GlobalInformation.baseUrl.resolve(uri); } \ No newline at end of file diff --git a/lib/main.dart b/lib/main.dart index af61ce5..c247d4d 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -14,6 +14,7 @@ main() async { 'username': 'WUvFG3gY', 'password': 'ZogPgBF6' })); + print(response.body); global.token = jsonDecode(response.body)['token']; runApp(const DigitalLife()); } diff --git a/lib/views/home.dart b/lib/views/home.dart index 48314ed..7cf9291 100644 --- a/lib/views/home.dart +++ b/lib/views/home.dart @@ -1,3 +1,5 @@ +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'; @@ -25,6 +27,7 @@ class _HomePageState extends State { ); } } + class Advantage extends StatefulWidget { const Advantage({super.key}); @@ -33,40 +36,70 @@ class Advantage extends StatefulWidget { } class _AdvantageState extends State { - List urls = [ - "/profile/upload/2021/11/27/12qw.jpg", - "/profile/upload/2021/11/27/34qw.jpg", - "/profile/upload/2021/11/27/56qw.jpg", - "/profile/upload/2021/11/27/78qw.jpg", - "/profile/upload/2023/12/28/5a48fd02-4232-4b1d-8ce3-3420d2447c5e.jpg" - ]; + 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)); + 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: [ - 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; - }); - }, - ) - ), + 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( @@ -88,21 +121,41 @@ class Notifications extends StatefulWidget { } class _NotificationsState extends State { - GlobalInformation? global; - final String _notifiction = "通知"; + 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(_notifiction) + Text(_notification) ], ); } } + class Application extends StatelessWidget { final IconData icon; final String title; + const Application({super.key, required this.icon, required this.title}); @override @@ -110,22 +163,20 @@ class Application extends StatelessWidget { return Container( width: 60, height: 60, - decoration: BoxDecoration(border: Border.all(color: Colors.blue), borderRadius: BorderRadius.circular(10)), + 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) - ], + children: [Icon(icon), Text(title)], ), ); } } - class Applications extends StatefulWidget { const Applications({super.key}); @@ -137,20 +188,21 @@ 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: "投诉建议",) - ] - ) + 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: "投诉建议"), + ], + ), ); } } @@ -158,7 +210,13 @@ class _ApplicationsState extends State { class Activity extends StatelessWidget { final String title; final double kmDistance; - const Activity({super.key, required this.title, required this.kmDistance}); + final String imageUrl; + + const Activity( + {super.key, + required this.title, + required this.kmDistance, + required this.imageUrl}); @override Widget build(BuildContext context) { @@ -169,16 +227,16 @@ class Activity extends StatelessWidget { decoration: BoxDecoration( border: Border.all( color: const Color.fromARGB(50, 0, 0, 100), - width: 1 + width: 1, ), - borderRadius: BorderRadius.circular(10) + borderRadius: BorderRadius.circular(10), ), child: Row( children: [ - const SizedBox( + SizedBox( width: 80, height: 50, - child: Placeholder() + child: Image.network(imageUrl, fit: BoxFit.cover), ), SizedBox( width: 100, @@ -212,7 +270,6 @@ class Activity extends StatelessWidget { } } - class Activities extends StatefulWidget { const Activities({super.key}); @@ -220,79 +277,52 @@ class Activities extends StatefulWidget { State createState() => _ActivitiesState(); } - -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}); +class _ActivitiesState extends State { + List> _activities = []; @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, - ) - ], - ); + 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(); + }); + } + } - -class _ActivitiesState extends State { @override Widget build(BuildContext context) { return ShowMoreContainer( - title: "社区活动", - showMore: true, - child: SizedBox( - height: 100, - child: ListView( - scrollDirection: Axis.horizontal, - children: const [ - Activity(title: "红星社区地毯清洗活动", kmDistance: 3.6), - Activity(title: "红星社区地毯清洗活动", kmDistance: 3.6), - Activity(title: "红星社区地毯清洗活动", kmDistance: 3.6), - Activity(title: "红星社区地毯清洗活动", kmDistance: 3.6) - ], - ) - ) + 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(), + ), + ), ); } } @@ -302,16 +332,26 @@ class Dynamic extends StatelessWidget { final String source; final int commentCount; final DateTime sendTime; - const Dynamic({super.key, required this.title, required this.source, required this.commentCount, required this.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){ + if (hour > 24) { time = "1 天前"; } + return SizedBox( width: 500, height: 150, @@ -330,28 +370,24 @@ class Dynamic extends StatelessWidget { maxLines: 2, overflow: TextOverflow.ellipsis, style: const TextStyle( - fontSize: 24, - fontWeight: FontWeight.w900 - ), + fontSize: 24, fontWeight: FontWeight.w900), ), ), Text( - "$source $commentCount评论 $time", - style: const TextStyle( - color: Colors.grey - ), - ) + "$source $commentCount评论 $time", + style: const TextStyle(color: Colors.grey), + ), ], ), ), - const Positioned( + Positioned( right: 0, top: 0, child: SizedBox( width: 200, height: 100, - child: Placeholder(), - ) + child: Image.network(imageUrl, fit: BoxFit.cover), + ), ) ], ), @@ -359,7 +395,6 @@ class Dynamic extends StatelessWidget { } } - class Dynamics extends StatefulWidget { const Dynamics({super.key}); @@ -368,6 +403,34 @@ class Dynamics extends StatefulWidget { } 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( @@ -376,19 +439,26 @@ class _DynamicsState extends State { child: SizedBox( height: 300, child: ListView( - children: [ - Dynamic(title: "内容标题示例内容标题示例内容标题示例内容标题示例内容标题示例内容标题示例内容标题示例内容标题示例内容标题示例内容标题示例", source: "内容来源", commentCount: 15, sendTime: DateTime.now().subtract(Duration(hours: 1))), - Dynamic(title: "内容标题示例内容标题示例内容标题示例内容标题示例内容标题示例内容标题示例内容标题示例内容标题示例内容标题示例内容标题示例", source: "内容来源", commentCount: 15, sendTime: DateTime.now().subtract(Duration(hours: 1))), - Dynamic(title: "内容标题示例内容标题示例内容标题示例内容标题示例内容标题示const 例内容标题示例内容标题示例内容标题示例内容标题示例内容标题示例", source: "内容来源", commentCount: 15, sendTime: DateTime.now().subtract(Duration(hours: 1))) - ], + 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; - const Reminder({super.key, required this.message}); + final IconData icon; + + const Reminder({super.key, required this.message, required this.icon}); @override Widget build(BuildContext context) { @@ -396,10 +466,10 @@ class Reminder extends StatelessWidget { margin: const EdgeInsetsDirectional.only(top: 10), child: Row( children: [ - const SizedBox( + SizedBox( width: 50, height: 50, - child: Placeholder(), + child: Icon(icon, color: Colors.green), ), Container( margin: const EdgeInsetsDirectional.only(start: 10), @@ -421,8 +491,7 @@ class Reminder extends StatelessWidget { style: const TextStyle( color: Colors.grey, fontSize: 12, - overflow: TextOverflow.ellipsis - ), + overflow: TextOverflow.ellipsis), ), ) ], @@ -434,9 +503,7 @@ class Reminder extends StatelessWidget { width: 5, height: 5, decoration: const BoxDecoration( - color: Colors.red, - shape: BoxShape.circle - ), + color: Colors.red, shape: BoxShape.circle), ), const Icon(Icons.keyboard_arrow_right, color: Colors.grey) ], @@ -455,6 +522,26 @@ class Reminders extends StatefulWidget { } 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( @@ -462,13 +549,89 @@ class _RemindersState extends State { showMore: false, child: SizedBox( height: 300, - child: ListView( - children: const [ - Reminder(message: "认证已通过,查看认证已通过,查看认证已通过,查看认证已通过,查看认证已通过,查看认证已通过,查看"), - Reminder(message: "认证已通过,查看认证已通过,查看认证已通过,查看认证已通过,查看认证已通过,查看认证已通过,查看") - ], + 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, + ), + ], ); } }