調整成API方式,關閉延遲
This commit is contained in:
parent
2bd6731f9c
commit
8fe8e7113c
181
lib/announcement.dart
Normal file
181
lib/announcement.dart
Normal file
@ -0,0 +1,181 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class Announcement {
|
||||||
|
final String date;
|
||||||
|
final String title;
|
||||||
|
final String preview;
|
||||||
|
final String full;
|
||||||
|
|
||||||
|
Announcement({
|
||||||
|
required this.date,
|
||||||
|
required this.title,
|
||||||
|
required this.preview,
|
||||||
|
required this.full,
|
||||||
|
});
|
||||||
|
|
||||||
|
factory Announcement.fromJson(Map<String, dynamic> json) {
|
||||||
|
return Announcement(
|
||||||
|
date: json['date'],
|
||||||
|
title: json['title'],
|
||||||
|
preview: json['preview'],
|
||||||
|
full: json['full'],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class AnnouncementWrapper extends StatefulWidget {
|
||||||
|
const AnnouncementWrapper({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<AnnouncementWrapper> createState() => _AnnouncementWrapperState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _AnnouncementWrapperState extends State<AnnouncementWrapper> {
|
||||||
|
List<Announcement> _announcements = [];
|
||||||
|
bool _isLoading = true;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_fetchAnnouncements();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _fetchAnnouncements() async {
|
||||||
|
// 模擬 API 延遲
|
||||||
|
//await Future.delayed(const Duration(milliseconds: 100));
|
||||||
|
|
||||||
|
// 模擬 API 回傳資料
|
||||||
|
final mockData = [
|
||||||
|
{
|
||||||
|
'date': '2025/04/28',
|
||||||
|
'title': '水塔清洗通知',
|
||||||
|
'preview': '本社區將於 2025/05/05 進行水塔清洗作業,請住戶提前儲水...',
|
||||||
|
'full': '本社區將於 2025/05/05 進行水塔清洗作業,請住戶提前儲水,造成不便敬請見諒。',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'date': '2025/04/25',
|
||||||
|
'title': '停電通知',
|
||||||
|
'preview': '台電預計於 5/1 上午進行電路維修,期間將暫時停電,請提前準備...',
|
||||||
|
'full': '台電預計於 2025/05/01 08:00~12:00 進行電路維修,期間將暫時停電,請提前準備。',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'date': '2025/04/20',
|
||||||
|
'title': '消防演練公告',
|
||||||
|
'preview': '消防演練將於 5/10 下午舉行,請住戶配合參與並聆聽安全說明...',
|
||||||
|
'full': '消防演練將於 2025/05/10 下午 3 點舉行,請各位住戶配合參與。',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
setState(() {
|
||||||
|
_announcements =
|
||||||
|
mockData.map((json) => Announcement.fromJson(json)).toList();
|
||||||
|
_isLoading = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void _showDetailModal(BuildContext context, String title, String content) {
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder:
|
||||||
|
(_) => AlertDialog(
|
||||||
|
title: Text(title),
|
||||||
|
content: Text(content),
|
||||||
|
actions: [
|
||||||
|
TextButton(
|
||||||
|
onPressed: () => Navigator.of(context).pop(),
|
||||||
|
child: const Text('關閉'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Container(
|
||||||
|
decoration: const BoxDecoration(
|
||||||
|
color: Colors.white,
|
||||||
|
borderRadius: BorderRadius.vertical(top: Radius.circular(16)),
|
||||||
|
),
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 24),
|
||||||
|
child:
|
||||||
|
_isLoading
|
||||||
|
? const Center(child: CircularProgressIndicator())
|
||||||
|
: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
IconButton(
|
||||||
|
icon: const Icon(Icons.arrow_back),
|
||||||
|
onPressed: () => Navigator.of(context).pop(),
|
||||||
|
),
|
||||||
|
const Expanded(
|
||||||
|
child: Center(
|
||||||
|
child: Text(
|
||||||
|
'公告列表',
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 18,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 48),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const SizedBox(height: 12),
|
||||||
|
const Align(
|
||||||
|
alignment: Alignment.centerLeft,
|
||||||
|
child: Text('📢 最新公告', style: TextStyle(fontSize: 16)),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 12),
|
||||||
|
..._announcements.map(
|
||||||
|
(item) => Column(
|
||||||
|
children: [
|
||||||
|
ListTile(
|
||||||
|
title: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
item.date,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 14,
|
||||||
|
color: Colors.black54,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
item.title,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
subtitle: Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 6.0),
|
||||||
|
child: Text(
|
||||||
|
item.preview,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 13,
|
||||||
|
color: Colors.black45,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
onTap:
|
||||||
|
() => _showDetailModal(
|
||||||
|
context,
|
||||||
|
item.title,
|
||||||
|
item.full,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Divider(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user