393 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Dart
		
	
	
			
		
		
	
	
			393 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Dart
		
	
	
| import 'package:flutter/material.dart';
 | |
| import 'package:flutter/services.dart';
 | |
| import 'package:image_picker/image_picker.dart';
 | |
| import 'dart:io';
 | |
| import '../../../../../customWidget/photo_picker_row.dart';
 | |
| import 'package:qhd_prevention/pages/my_appbar.dart';
 | |
| 
 | |
| import '../../http/ApiService.dart';
 | |
| 
 | |
| // feedback_type.dart
 | |
| enum FeedbackType {
 | |
|   systemError,
 | |
|   uiOptimization,
 | |
|   designIssue,
 | |
|   performanceIssue,
 | |
|   other,
 | |
| }
 | |
| 
 | |
| ///问题反馈
 | |
| class FeedbackApp extends StatelessWidget {
 | |
|   const FeedbackApp({super.key});
 | |
| 
 | |
|   @override
 | |
|   Widget build(BuildContext context) {
 | |
|     return Scaffold(
 | |
|       appBar: MyAppbar(title:'问题反馈' ),
 | |
|       body: const FeedbackPage(),
 | |
|     );
 | |
|   }
 | |
| }
 | |
| 
 | |
| class FeedbackPage extends StatefulWidget {
 | |
|   const FeedbackPage({super.key});
 | |
| 
 | |
|   @override
 | |
|   State<FeedbackPage> createState() => _FeedbackPageState();
 | |
| }
 | |
| 
 | |
| class _FeedbackPageState extends State<FeedbackPage> {
 | |
|   final _formKey = GlobalKey<FormState>();
 | |
|   final TextEditingController _titleController = TextEditingController();
 | |
|   final TextEditingController _descriptionController = TextEditingController();
 | |
| 
 | |
|   // 反馈类型
 | |
|   FeedbackType? _selectedType = FeedbackType.other;
 | |
| 
 | |
|   // 上传的图片
 | |
|   List<String> _images = [];
 | |
| 
 | |
|   // 获取反馈类型名称
 | |
|   String _getTypeName(FeedbackType type) {
 | |
|     switch (type) {
 | |
|       case FeedbackType.systemError:
 | |
|         return '系统错误';
 | |
|       case FeedbackType.uiOptimization:
 | |
|         return '界面优化';
 | |
|       case FeedbackType.designIssue:
 | |
|         return '设计缺陷';
 | |
|       case FeedbackType.performanceIssue:
 | |
|         return '性能问题';
 | |
|       case FeedbackType.other:
 | |
|         return '其他';
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   // 获取反馈类型名称
 | |
|   String _getTypeNum(FeedbackType type) {
 | |
|     switch (type) {
 | |
|       case FeedbackType.systemError:
 | |
|         return '1';
 | |
|       case FeedbackType.uiOptimization:
 | |
|         return '2';
 | |
|       case FeedbackType.designIssue:
 | |
|         return '3';
 | |
|       case FeedbackType.performanceIssue:
 | |
|         return '4';
 | |
|       case FeedbackType.other:
 | |
|         return '9';
 | |
|     }
 | |
|   }
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
|   @override
 | |
|   Widget build(BuildContext context) {
 | |
|     return Scaffold(
 | |
|       appBar: MyAppbar(title: "问题反馈"),
 | |
|       body: Container(
 | |
|         color: Colors.white,
 | |
|         child: Form(
 | |
|           key: _formKey,
 | |
|           child: SingleChildScrollView(
 | |
|             padding: const EdgeInsets.all(16),
 | |
|             child: Column(
 | |
|               crossAxisAlignment: CrossAxisAlignment.start,
 | |
|               children: [
 | |
|                 // 标题输入
 | |
|                 const Text('标题', style: TextStyle(fontWeight: FontWeight.bold)),
 | |
|                 const SizedBox(height: 8),
 | |
|                 TextFormField(
 | |
|                   controller: _titleController,
 | |
|                   decoration: const InputDecoration(
 | |
|                     hintText: '请输入标题...',
 | |
|                     border: OutlineInputBorder(),
 | |
|                   ),
 | |
|                   validator: (value) {
 | |
|                     if (value == null || value.isEmpty) {
 | |
|                       return '请输入标题';
 | |
|                     }
 | |
|                     return null;
 | |
|                   },
 | |
|                 ),
 | |
|                 const SizedBox(height: 24),
 | |
| 
 | |
|                 // 问题描述
 | |
|                 const Text(
 | |
|                   '详细问题和意见',
 | |
|                   style: TextStyle(fontWeight: FontWeight.bold),
 | |
|                 ),
 | |
|                 const SizedBox(height: 8),
 | |
|                 TextFormField(
 | |
|                   controller: _descriptionController,
 | |
|                   maxLines: 5,
 | |
|                   decoration:
 | |
|                   const InputDecoration(
 | |
|                     hintText: '请补充详细问题和意见...',
 | |
|                     border: OutlineInputBorder(),
 | |
|                     contentPadding:  EdgeInsets.all(10),
 | |
|                   ),
 | |
|                   validator: (value) {
 | |
|                     if (value == null || value.isEmpty) {
 | |
|                       return '请补充详细问题和意见';
 | |
|                     }
 | |
|                     return null;
 | |
|                   },
 | |
|                 ),
 | |
|                 const SizedBox(height: 24),
 | |
| 
 | |
|                 // 反馈类型
 | |
|                 const Text(
 | |
|                   '反馈类型',
 | |
|                   style: TextStyle(fontWeight: FontWeight.bold),
 | |
|                 ),
 | |
|                 const SizedBox(height: 8),
 | |
|                 Wrap(
 | |
|                   spacing: 16,
 | |
|                   children:
 | |
|                       FeedbackType.values.map((type) {
 | |
|                         return ChoiceChip(
 | |
|                           label: Text(_getTypeName(type)),
 | |
|                           selected: _selectedType == type,
 | |
|                           onSelected: (selected) {
 | |
|                             setState(() {
 | |
|                               if (selected) {
 | |
|                                 _selectedType = type;
 | |
|                               }
 | |
|                             });
 | |
|                           },
 | |
|                         );
 | |
|                       }).toList(),
 | |
|                 ),
 | |
| 
 | |
|                 // const SizedBox(height: 14),
 | |
|                 // Row(
 | |
|                 //   mainAxisAlignment: MainAxisAlignment.spaceBetween,
 | |
|                 //   children: [
 | |
|                 //   const Text(
 | |
|                 //     '请提供相关问题的截图或照片',
 | |
|                 //     style: TextStyle(fontWeight: FontWeight.bold),
 | |
|                 //   ),
 | |
|                 //   Text(
 | |
|                 //     '${_images.length}/4',
 | |
|                 //     style: const TextStyle(color: Colors.grey),
 | |
|                 //   ),
 | |
|                 // ],),
 | |
| 
 | |
|                 // 图片上传
 | |
|                 const SizedBox(height: 16),
 | |
| 
 | |
|                 RepairedPhotoSection(
 | |
|                   horizontalPadding: 0,
 | |
|                   title: "请提供相关问题的截图或照片",
 | |
|                   maxCount: 4,
 | |
|                   mediaType: MediaType.image,
 | |
|                   onChanged: (files) {
 | |
|                     // 上传 files 到服务器
 | |
|                     _images.clear();
 | |
|                     for(int i=0;i<files.length;i++){
 | |
|                       _images.add(files[i].path);
 | |
|                     }
 | |
| 
 | |
|                   },
 | |
|                   onAiIdentify: () {
 | |
| 
 | |
|                   },
 | |
|                 ),
 | |
| 
 | |
|                 // GridView.builder(
 | |
|                 //   shrinkWrap: true,
 | |
|                 //   physics: const NeverScrollableScrollPhysics(),
 | |
|                 //   gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
 | |
|                 //     crossAxisCount: 4,
 | |
|                 //     crossAxisSpacing: 8,
 | |
|                 //     mainAxisSpacing: 8,
 | |
|                 //     childAspectRatio: 1,
 | |
|                 //   ),
 | |
|                 //   itemCount: _images.length + 1,
 | |
|                 //   itemBuilder: (context, index) {
 | |
|                 //     if (index < _images.length) {
 | |
|                 //       return Stack(
 | |
|                 //         children: [
 | |
|                 //           Container(
 | |
|                 //             decoration: BoxDecoration(
 | |
|                 //               borderRadius: BorderRadius.circular(8),
 | |
|                 //               image: DecorationImage(
 | |
|                 //                 image: FileImage(_images[index]),
 | |
|                 //                 fit: BoxFit.cover,
 | |
|                 //               ),
 | |
|                 //             ),
 | |
|                 //           ),
 | |
|                 //           Positioned(
 | |
|                 //             top: 4,
 | |
|                 //             right: 4,
 | |
|                 //             child: GestureDetector(
 | |
|                 //               onTap: () => _removeImage(index),
 | |
|                 //               child: Container(
 | |
|                 //                 padding: const EdgeInsets.all(2),
 | |
|                 //                 decoration: const BoxDecoration(
 | |
|                 //                   shape: BoxShape.circle,
 | |
|                 //                   color: Colors.black54,
 | |
|                 //                 ),
 | |
|                 //                 child: const Icon(
 | |
|                 //                   Icons.close,
 | |
|                 //                   size: 16,
 | |
|                 //                   color: Colors.white,
 | |
|                 //                 ),
 | |
|                 //               ),
 | |
|                 //             ),
 | |
|                 //           ),
 | |
|                 //         ],
 | |
|                 //       );
 | |
|                 //     } else {
 | |
|                 //       return _images.length < 4
 | |
|                 //           ? GestureDetector(
 | |
|                 //             onTap: _pickImage,
 | |
|                 //             child: Container(
 | |
|                 //               decoration: BoxDecoration(
 | |
|                 //                 border: Border.all(color: Colors.grey),
 | |
|                 //                 borderRadius: BorderRadius.circular(8),
 | |
|                 //               ),
 | |
|                 //               child: const Icon(
 | |
|                 //                 Icons.add,
 | |
|                 //                 size: 40,
 | |
|                 //                 color: Colors.grey,
 | |
|                 //               ),
 | |
|                 //             ),
 | |
|                 //           )
 | |
|                 //           : const SizedBox();
 | |
|                 //     }
 | |
|                 //   },
 | |
|                 // ),
 | |
|                 const SizedBox(height: 40),
 | |
| 
 | |
|                 // 提交按钮
 | |
|                 SizedBox(
 | |
|                   width: double.infinity,
 | |
|                   child: ElevatedButton(
 | |
|                     onPressed: _submitFeedback,
 | |
|                     style: ElevatedButton.styleFrom(
 | |
|                       backgroundColor: Colors.blue,
 | |
|                       padding: const EdgeInsets.symmetric(vertical: 16),
 | |
|                       shape: RoundedRectangleBorder(
 | |
|                         borderRadius: BorderRadius.circular(8),
 | |
|                       ),
 | |
|                     ),
 | |
|                     child: const Text(
 | |
|                       '提交',
 | |
|                       style: TextStyle(fontSize: 18, color: Colors.white),
 | |
|                     ),
 | |
|                   ),
 | |
|                 ),
 | |
|               ],
 | |
|             ),
 | |
|           ),
 | |
|         ),
 | |
|       ),
 | |
|     );
 | |
|   }
 | |
| 
 | |
|   // 提交反馈
 | |
|   Future<void> _submitFeedback() async {
 | |
| 
 | |
|     final title = _titleController.text.trim();
 | |
|     final text = _descriptionController.text.trim();
 | |
| 
 | |
|     if (title.isEmpty ) {
 | |
|       _showMessage('请填写标题');
 | |
|       return;
 | |
|     }
 | |
| 
 | |
|     if (text.isEmpty ) {
 | |
|       _showMessage('请填写问题和意见');
 | |
|       return;
 | |
|     }
 | |
| 
 | |
|     if (_images.isEmpty) {
 | |
|       _showMessage('请上传隐患图片');
 | |
|       return;
 | |
|     }
 | |
| 
 | |
|     String imagePaths="";
 | |
|     for(int i=0;i<_images.length;i++){
 | |
|       String imagePath=await _reloadFeedBack(_images[i]) ;
 | |
| 
 | |
|       if(0==i){
 | |
|         imagePaths=imagePath;
 | |
|       }else {
 | |
|         imagePaths = "$imagePaths;$imagePath";
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     String num=_getTypeNum(_selectedType!);
 | |
| 
 | |
|     _setFeedBack(title,text,imagePaths,num);
 | |
| 
 | |
|     // if (_formKey.currentState!.validate()) {
 | |
|     //   // 模拟提交过程
 | |
|     //   showDialog(
 | |
|     //     context: context,
 | |
|     //     barrierDismissible: false,
 | |
|     //     builder: (context) => const Center(child: CircularProgressIndicator()),
 | |
|     //   );
 | |
|     //
 | |
|     //   Future.delayed(const Duration(seconds: 2), () {
 | |
|     //     Navigator.pop(context); // 关闭加载对话框
 | |
|     //     ScaffoldMessenger.of(
 | |
|     //       context,
 | |
|     //     ).showSnackBar(const SnackBar(content: Text('反馈提交成功!')));
 | |
|     //
 | |
|     //     // 重置表单
 | |
|     //     _formKey.currentState!.reset();
 | |
|     //     setState(() {
 | |
|     //       _images.clear();
 | |
|     //       _selectedType = FeedbackType.other;
 | |
|     //     });
 | |
|     //   });
 | |
|     // }
 | |
|   }
 | |
| 
 | |
|   Future<String> _reloadFeedBack(String imagePath) async {
 | |
|     try {
 | |
| 
 | |
|       final raw = await ApiService.reloadFeedBack(imagePath);
 | |
|       if (raw['result'] == 'success') {
 | |
|         return raw['imgPath'];
 | |
|       }else{
 | |
|         // _showMessage('反馈提交失败');
 | |
|         return "";
 | |
|       }
 | |
| 
 | |
|     } catch (e) {
 | |
|       // 出错时可以 Toast 或者在页面上显示错误状态
 | |
|       print('加载首页数据失败:$e');
 | |
|       return "";
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   Future<void> _setFeedBack(String title, String text, String imagePaths, String num) async {
 | |
|     try {
 | |
| 
 | |
|       final raw = await ApiService.setFeedBack(title,text,num,imagePaths);
 | |
| 
 | |
|       if (raw['result'] == 'success') {
 | |
|             Navigator.pop(context); // 关闭加载对话框
 | |
|             _showMessage('反馈提交成功');
 | |
| 
 | |
|       }else{
 | |
|         _showMessage('反馈提交失败');
 | |
|       }
 | |
| 
 | |
|     } catch (e) {
 | |
|       // 出错时可以 Toast 或者在页面上显示错误状态
 | |
|       print('加载首页数据失败:$e');
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   void _showMessage(String msg) {
 | |
|     ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(msg)));
 | |
|   }
 | |
| }
 |