From c6248935e79d83a3274ba566ffbaf6004b99e67b Mon Sep 17 00:00:00 2001 From: jasonchenwork Date: Fri, 9 May 2025 16:49:13 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=A0=B1=E4=BF=AE=E4=BB=8B?= =?UTF-8?q?=E9=9D=A2=E8=A8=AD=E8=A8=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- android/app/build.gradle.kts | 2 +- android/app/src/main/AndroidManifest.xml | 3 + lib/home_content_page.dart | 10 +- lib/personal_page.dart | 5 + lib/reapair.dart | 187 ++++++++++++++++++ linux/flutter/generated_plugin_registrant.cc | 4 + linux/flutter/generated_plugins.cmake | 1 + macos/Flutter/GeneratedPluginRegistrant.swift | 2 + pubspec.lock | 167 +++++++++++++++- pubspec.yaml | 2 +- .../flutter/generated_plugin_registrant.cc | 3 + windows/flutter/generated_plugins.cmake | 1 + 12 files changed, 383 insertions(+), 4 deletions(-) create mode 100644 lib/reapair.dart diff --git a/android/app/build.gradle.kts b/android/app/build.gradle.kts index 344defd..ccc26cb 100644 --- a/android/app/build.gradle.kts +++ b/android/app/build.gradle.kts @@ -8,7 +8,7 @@ plugins { android { namespace = "com.example.communityapp" compileSdk = flutter.compileSdkVersion - ndkVersion = flutter.ndkVersion + ndkVersion = "27.0.12077973" compileOptions { sourceCompatibility = JavaVersion.VERSION_11 diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 4f6d5f0..8da8b35 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -42,4 +42,7 @@ + + + diff --git a/lib/home_content_page.dart b/lib/home_content_page.dart index f178be3..a979564 100644 --- a/lib/home_content_page.dart +++ b/lib/home_content_page.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'reapair.dart'; class HomeContentPage extends StatelessWidget { const HomeContentPage({super.key}); @@ -79,7 +80,14 @@ class HomeContentPage extends StatelessWidget { ) { return GestureDetector( onTap: () { - // TODO: 各個按鈕的跳轉功能可以寫在這裡 + switch (title) { + case "報修": + Navigator.push( + context, + MaterialPageRoute(builder: (context) => const RepairPage()), + ); + default: + } }, child: Column( mainAxisAlignment: MainAxisAlignment.center, diff --git a/lib/personal_page.dart b/lib/personal_page.dart index f1faa4b..de42d2f 100644 --- a/lib/personal_page.dart +++ b/lib/personal_page.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'login_page.dart'; import 'edit_profile.dart'; import 'feedback.dart'; +import 'reapair.dart'; class PersonalPage extends StatelessWidget { const PersonalPage({super.key}); @@ -196,6 +197,10 @@ class PersonalPage extends StatelessWidget { }), _buildMenuItem('報修申請', 'repair.png', () { // TODO: 報修申請點擊 + Navigator.push( + context, + MaterialPageRoute(builder: (context) => const RepairPage()), + ); }), _buildMenuItem('包裹通知', 'package.png', () { // TODO: 包裹通知點擊 diff --git a/lib/reapair.dart b/lib/reapair.dart new file mode 100644 index 0000000..494d307 --- /dev/null +++ b/lib/reapair.dart @@ -0,0 +1,187 @@ +import 'package:flutter/material.dart'; +import 'package:image_picker/image_picker.dart'; + +class RepairPage extends StatefulWidget { + const RepairPage({super.key}); + + @override + State createState() => _RepairPageState(); +} + +class _RepairPageState extends State { + final _formKey = GlobalKey(); + String? _repairType; + final _locationController = TextEditingController(); + final _descriptionController = TextEditingController(); + XFile? _photo; + + final List> _repairRecords = [ + { + "date": "2025/04/20", + "type": "水管漏水", + "location": "A棟 2F", + "status": "處理中", + }, + { + "date": "2025/04/18", + "type": "網路異常", + "location": "C棟 5F", + "status": "已完成", + }, + { + "date": "2025/04/15", + "type": "電力問題", + "location": "B棟 6F", + "status": "待處理", + }, + ]; + + Future _pickImage() async { + final picker = ImagePicker(); + final picked = await picker.pickImage(source: ImageSource.gallery); + if (picked != null) { + setState(() { + _photo = picked; + }); + } + } + + void _submitForm() { + if (_formKey.currentState!.validate() && _repairType != null) { + ScaffoldMessenger.of( + context, + ).showSnackBar(const SnackBar(content: Text('報修已提交!'))); + // 可擴充送出資料到伺服器 + } + } + + @override + void dispose() { + _locationController.dispose(); + _descriptionController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: const Text('水電網路報修'), + backgroundColor: const Color(0xFF9eaf9f), + foregroundColor: Colors.white, + ), + body: ListView( + padding: const EdgeInsets.all(16), + children: [ + const Text('🛠️ 填寫報修單', style: TextStyle(fontSize: 16)), + const SizedBox(height: 12), + Form( + key: _formKey, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const Text( + '報修類別', + style: TextStyle(fontWeight: FontWeight.bold), + ), + DropdownButtonFormField( + value: _repairType, + items: const [ + DropdownMenuItem(value: '電力問題', child: Text('電力問題')), + DropdownMenuItem(value: '水管漏水', child: Text('水管漏水')), + DropdownMenuItem(value: '網路異常', child: Text('網路異常')), + DropdownMenuItem(value: '其他', child: Text('其他')), + ], + hint: const Text('請選擇'), + onChanged: (value) { + setState(() { + _repairType = value; + }); + }, + validator: (value) => value == null ? '請選擇報修類別' : null, + ), + const SizedBox(height: 12), + const Text( + '地點/房號', + style: TextStyle(fontWeight: FontWeight.bold), + ), + TextFormField( + controller: _locationController, + decoration: const InputDecoration(hintText: '如:B棟 3F'), + validator: + (value) => + value == null || value.isEmpty ? '請輸入地點' : null, + ), + const SizedBox(height: 12), + const Text( + '問題描述', + style: TextStyle(fontWeight: FontWeight.bold), + ), + TextFormField( + controller: _descriptionController, + maxLines: 3, + decoration: const InputDecoration( + hintText: '請簡要描述問題...', + border: OutlineInputBorder(), + ), + validator: + (value) => + value == null || value.isEmpty ? '請輸入問題描述' : null, + ), + const SizedBox(height: 12), + const Text( + '照片上傳(選填)', + style: TextStyle(fontWeight: FontWeight.bold), + ), + Row( + children: [ + ElevatedButton( + onPressed: _pickImage, + child: const Text( + '選擇照片', + style: TextStyle(color: Colors.purple), + ), + ), + const SizedBox(width: 8), + if (_photo != null) + Text('已選擇圖片', style: TextStyle(color: Colors.green)), + ], + ), + const SizedBox(height: 16), + ElevatedButton( + onPressed: _submitForm, + style: ElevatedButton.styleFrom( + backgroundColor: Colors.green, + minimumSize: const Size.fromHeight(48), + ), + child: const Text( + '送出報修', + style: TextStyle(color: Colors.white), + ), + ), + ], + ), + ), + const SizedBox(height: 24), + const Text('📋 已申報紀錄', style: TextStyle(fontSize: 16)), + const SizedBox(height: 12), + ..._repairRecords.map( + (record) => Padding( + padding: const EdgeInsets.symmetric(vertical: 8.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + '${record["date"]} - ${record["type"]}', + style: const TextStyle(fontWeight: FontWeight.bold), + ), + Text('地點:${record["location"]}|狀態:${record["status"]}'), + ], + ), + ), + ), + ], + ), + ); + } +} diff --git a/linux/flutter/generated_plugin_registrant.cc b/linux/flutter/generated_plugin_registrant.cc index e71a16d..64a0ece 100644 --- a/linux/flutter/generated_plugin_registrant.cc +++ b/linux/flutter/generated_plugin_registrant.cc @@ -6,6 +6,10 @@ #include "generated_plugin_registrant.h" +#include void fl_register_plugins(FlPluginRegistry* registry) { + g_autoptr(FlPluginRegistrar) file_selector_linux_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "FileSelectorPlugin"); + file_selector_plugin_register_with_registrar(file_selector_linux_registrar); } diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake index 2e1de87..2db3c22 100644 --- a/linux/flutter/generated_plugins.cmake +++ b/linux/flutter/generated_plugins.cmake @@ -3,6 +3,7 @@ # list(APPEND FLUTTER_PLUGIN_LIST + file_selector_linux ) list(APPEND FLUTTER_FFI_PLUGIN_LIST diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index cccf817..14b5f7c 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -5,6 +5,8 @@ import FlutterMacOS import Foundation +import file_selector_macos func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { + FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin")) } diff --git a/pubspec.lock b/pubspec.lock index d993b91..d2cdcba 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -41,6 +41,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.19.1" + cross_file: + dependency: transitive + description: + name: cross_file + sha256: "7caf6a750a0c04effbb52a676dce9a4a592e10ad35c34d6d2d0e4811160d5670" + url: "https://pub.dev" + source: hosted + version: "0.3.4+2" cupertino_icons: dependency: "direct main" description: @@ -57,6 +65,38 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.2" + file_selector_linux: + dependency: transitive + description: + name: file_selector_linux + sha256: "54cbbd957e1156d29548c7d9b9ec0c0ebb6de0a90452198683a7d23aed617a33" + url: "https://pub.dev" + source: hosted + version: "0.9.3+2" + file_selector_macos: + dependency: transitive + description: + name: file_selector_macos + sha256: "271ab9986df0c135d45c3cdb6bd0faa5db6f4976d3e4b437cf7d0f258d941bfc" + url: "https://pub.dev" + source: hosted + version: "0.9.4+2" + file_selector_platform_interface: + dependency: transitive + description: + name: file_selector_platform_interface + sha256: a3994c26f10378a039faa11de174d7b78eb8f79e4dd0af2a451410c1a5c3f66b + url: "https://pub.dev" + source: hosted + version: "2.6.2" + file_selector_windows: + dependency: transitive + description: + name: file_selector_windows + sha256: "320fcfb6f33caa90f0b58380489fc5ac05d99ee94b61aa96ec2bff0ba81d3c2b" + url: "https://pub.dev" + source: hosted + version: "0.9.3+4" flutter: dependency: "direct main" description: flutter @@ -70,11 +110,104 @@ packages: url: "https://pub.dev" source: hosted version: "5.0.0" + flutter_plugin_android_lifecycle: + dependency: transitive + description: + name: flutter_plugin_android_lifecycle + sha256: f948e346c12f8d5480d2825e03de228d0eb8c3a737e4cdaa122267b89c022b5e + url: "https://pub.dev" + source: hosted + version: "2.0.28" flutter_test: dependency: "direct dev" description: flutter source: sdk version: "0.0.0" + flutter_web_plugins: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + http: + dependency: transitive + description: + name: http + sha256: "2c11f3f94c687ee9bad77c171151672986360b2b001d109814ee7140b2cf261b" + url: "https://pub.dev" + source: hosted + version: "1.4.0" + http_parser: + dependency: transitive + description: + name: http_parser + sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571" + url: "https://pub.dev" + source: hosted + version: "4.1.2" + image_picker: + dependency: "direct main" + description: + name: image_picker + sha256: "021834d9c0c3de46bf0fe40341fa07168407f694d9b2bb18d532dc1261867f7a" + url: "https://pub.dev" + source: hosted + version: "1.1.2" + image_picker_android: + dependency: transitive + description: + name: image_picker_android + sha256: "317a5d961cec5b34e777b9252393f2afbd23084aa6e60fcf601dcf6341b9ebeb" + url: "https://pub.dev" + source: hosted + version: "0.8.12+23" + image_picker_for_web: + dependency: transitive + description: + name: image_picker_for_web + sha256: "717eb042ab08c40767684327be06a5d8dbb341fe791d514e4b92c7bbe1b7bb83" + url: "https://pub.dev" + source: hosted + version: "3.0.6" + image_picker_ios: + dependency: transitive + description: + name: image_picker_ios + sha256: "05da758e67bc7839e886b3959848aa6b44ff123ab4b28f67891008afe8ef9100" + url: "https://pub.dev" + source: hosted + version: "0.8.12+2" + image_picker_linux: + dependency: transitive + description: + name: image_picker_linux + sha256: "34a65f6740df08bbbeb0a1abd8e6d32107941fd4868f67a507b25601651022c9" + url: "https://pub.dev" + source: hosted + version: "0.2.1+2" + image_picker_macos: + dependency: transitive + description: + name: image_picker_macos + sha256: "1b90ebbd9dcf98fb6c1d01427e49a55bd96b5d67b8c67cf955d60a5de74207c1" + url: "https://pub.dev" + source: hosted + version: "0.2.1+2" + image_picker_platform_interface: + dependency: transitive + description: + name: image_picker_platform_interface + sha256: "886d57f0be73c4b140004e78b9f28a8914a09e50c2d816bdd0520051a71236a0" + url: "https://pub.dev" + source: hosted + version: "2.10.1" + image_picker_windows: + dependency: transitive + description: + name: image_picker_windows + sha256: "6ad07afc4eb1bc25f3a01084d28520496c4a3bb0cb13685435838167c9dcedeb" + url: "https://pub.dev" + source: hosted + version: "0.2.1+1" leak_tracker: dependency: transitive description: @@ -131,6 +264,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.16.0" + mime: + dependency: transitive + description: + name: mime + sha256: "41a20518f0cb1256669420fdba0cd90d21561e560ac240f26ef8322e45bb7ed6" + url: "https://pub.dev" + source: hosted + version: "2.0.0" path: dependency: transitive description: @@ -139,6 +280,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.9.1" + plugin_platform_interface: + dependency: transitive + description: + name: plugin_platform_interface + sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" + url: "https://pub.dev" + source: hosted + version: "2.1.8" sky_engine: dependency: transitive description: flutter @@ -192,6 +341,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.7.4" + typed_data: + dependency: transitive + description: + name: typed_data + sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006 + url: "https://pub.dev" + source: hosted + version: "1.4.0" vector_math: dependency: transitive description: @@ -208,6 +365,14 @@ packages: url: "https://pub.dev" source: hosted version: "14.3.1" + web: + dependency: transitive + description: + name: web + sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a" + url: "https://pub.dev" + source: hosted + version: "1.1.1" sdks: dart: ">=3.7.2 <4.0.0" - flutter: ">=3.18.0-18.0.pre.54" + flutter: ">=3.27.0" diff --git a/pubspec.yaml b/pubspec.yaml index 7937753..0dd41c2 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -30,7 +30,7 @@ environment: dependencies: flutter: sdk: flutter - + image_picker: ^1.0.4 # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^1.0.8 diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc index 8b6d468..77ab7a0 100644 --- a/windows/flutter/generated_plugin_registrant.cc +++ b/windows/flutter/generated_plugin_registrant.cc @@ -6,6 +6,9 @@ #include "generated_plugin_registrant.h" +#include void RegisterPlugins(flutter::PluginRegistry* registry) { + FileSelectorWindowsRegisterWithRegistrar( + registry->GetRegistrarForPlugin("FileSelectorWindows")); } diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index b93c4c3..a423a02 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -3,6 +3,7 @@ # list(APPEND FLUTTER_PLUGIN_LIST + file_selector_windows ) list(APPEND FLUTTER_FFI_PLUGIN_LIST