You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter技术实现:如何将反馈表单的用户反馈提交至Firestore数据库并在独立页面展示反馈报表

Hey there! Let's walk through connecting your feedback form to Firestore and building that report page—super straightforward once you break it down.

1. First, Make Sure Firebase & Firestore Are Set Up

Before jumping into code, double-check these basics:

  • You've added Firebase to your Flutter project (follow the Firebase console steps for Android/iOS if you haven't)
  • Add the cloud_firestore dependency to your pubspec.yaml:
    dependencies:
      flutter:
        sdk: flutter
      cloud_firestore: ^4.15.0 # Use the latest version available
    
  • Initialize Firebase in your main.dart:
    void main() async {
      WidgetsFlutterBinding.ensureInitialized();
      await Firebase.initializeApp();
      runApp(MyApp());
    }
    
2. Update Your FeedbackScreen to Submit to Firestore

We'll modify your handleSubmitFeedback method to send form data to Firestore instead of just printing it. Since Firestore operations are async, we'll make this method async and add error handling to keep things user-friendly.

Replace your existing handleSubmitFeedback with this:

Future<void> handleSubmitFeedback() async {
  bool complete = true;
  for (int i = 0; i < _feedbackValue.length; ++i) {
    if (_feedbackValue[i] == -1) {
      complete = false;
      _isFormFieldComplete[i] = true;
    } else {
      _isFormFieldComplete[i] = false;
    }
  }
  setState(() {});
  if (!complete) return;

  try {
    // Send feedback to a Firestore collection named "user_feedback"
    await FirebaseFirestore.instance.collection('user_feedback').add({
      'feedback_values': _feedbackValue, // Scores for each question
      'additional_comments': additionalComments ?? '', // Handle empty comments
      'submitted_at': Timestamp.now(), // Add timestamp for sorting in reports
      'questions': _questions, // Optional: Saves questions to avoid hardcoding later
    });

    // Show success message and navigate
    ScaffoldMessenger.of(context).showSnackBar(
      const SnackBar(content: Text('Feedback submitted successfully!')),
    );
    Navigator.pushReplacementNamed(context, SessionTwoScreen.routeName);
  } catch (e) {
    // Handle errors like no internet or permission issues
    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(content: Text('Failed to submit: ${e.toString()}')),
    );
  }
}

A quick breakdown:

  • add() creates a new document in the user_feedback collection (Firestore auto-generates a unique ID for each entry)
  • submitted_at helps sort feedback by date in the report page
  • The try/catch block ensures we gracefully handle issues and let the user know what went wrong
3. Build the Feedback Report Page

Now let's create a new screen that reads all feedback from Firestore and displays it in real time (using StreamBuilder so new feedback shows up automatically without refreshing).

Create this new widget:

class FeedbackReportScreen extends StatelessWidget {
  static const String routeName = 'feedback_report_screen';

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: const AppBar(title: Text('Feedback Report')),
      body: StreamBuilder<QuerySnapshot>(
        // Listen to the user_feedback collection, sorted by most recent first
        stream: FirebaseFirestore.instance
            .collection('user_feedback')
            .orderBy('submitted_at', descending: true)
            .snapshots(),
        builder: (context, snapshot) {
          // Handle loading state
          if (snapshot.connectionState == ConnectionState.waiting) {
            return const Center(child: CircularProgressIndicator());
          }

          // Handle errors
          if (snapshot.hasError) {
            return Center(child: Text('Error loading feedback: ${snapshot.error}'));
          }

          // Handle empty state
          if (!snapshot.hasData || snapshot.data!.docs.isEmpty) {
            return const Center(child: Text('No feedback submitted yet.'));
          }

          // Display feedback list
          return ListView.builder(
            itemCount: snapshot.data!.docs.length,
            itemBuilder: (context, index) {
              final feedbackDoc = snapshot.data!.docs[index];
              final feedbackData = feedbackDoc.data() as Map<String, dynamic>;

              // Parse data from Firestore
              final List<int> scores = List<int>.from(feedbackData['feedback_values']);
              final List<String> questions = List<String>.from(feedbackData['questions']);
              final String comments = feedbackData['additional_comments'] ?? 'No additional comments';
              final DateTime submitDate = (feedbackData['submitted_at'] as Timestamp).toDate();

              return Card(
                margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
                child: Padding(
                  padding: const EdgeInsets.all(16),
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: [
                      // Show submission date
                      Text(
                        'Submitted on: ${submitDate.toString().substring(0, 19)}',
                        style: TextStyle(color: Colors.grey[600], fontSize: 12),
                      ),
                      const SizedBox(height: 12),
                      // Show each question and its corresponding score (as emoji)
                      ...List.generate(questions.length, (qIndex) {
                        return Padding(
                          padding: const EdgeInsets.symmetric(vertical: 4),
                          child: Row(
                            mainAxisAlignment: MainAxisAlignment.spaceBetween,
                            children: [
                              Text(questions[qIndex]),
                              Text(_getEmojiForScore(scores[qIndex])),
                            ],
                          ),
                        );
                      }),
                      const SizedBox(height: 12),
                      // Show additional comments
                      const Text('Additional Comments:'),
                      const SizedBox(height: 4),
                      Text(comments),
                    ],
                  ),
                ),
              );
            },
          );
        },
      ),
    );
  }

  // Helper method to convert scores to emojis (match your form's labels)
  String _getEmojiForScore(int score) {
    switch (score) {
      case 0:
        return '😊'; // Tons emoji
      case 1:
        return '🙂'; // Alot emoji
      case 2:
        return '😐'; // So-so emoji
      case 3:
        return '😕'; // Not good emoji
      default:
        return '❓';
    }
  }
}

Don't forget to add this screen to your app's routes in MaterialApp:

routes: {
  // ... your existing routes
  FeedbackReportScreen.routeName: (context) => FeedbackReportScreen(),
},
4. Quick Extra Tips
  • Firestore Security Rules: For development, you can use temporary rules to allow read/write access, but lock them down for production:
    rules_version = '2';
    service cloud.firestore {
      match /databases/{database}/documents {
        match /user_feedback/{document} {
          allow read, write: if request.auth != null; // Adjust based on your auth setup
        }
      }
    }
    
  • UI Tweaks: For the report page, you could use a DataTable instead of a ListView for a more table-like layout, or add filters/sorting options
  • Validation: Add extra checks like limiting comment length if needed

That's it! Your form will now submit to Firestore, and the report page will display all feedback in real time.

内容的提问来源于stack exchange,提问作者peekaysjay

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 16:12:37