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

如何在Flutter的initState中从Firestore取数据并在PDF组件展示

问题分析与解决方案

你的代码目前未实现从Firestore获取数据并渲染到PDF的核心逻辑,主要问题点及修复方案如下:

核心问题

  • 仅调用Firestore的snapshots()但未订阅或获取实际数据,没有将数据保存到本地变量
  • PDF生成方法generateDocument中未集成Firestore数据获取逻辑,仅展示了日期
  • 全局dateStr未与传入的widget.date关联,可能导致集合路径错误

修复后的完整代码

import 'dart:typed_data';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:pdf/pdf.dart';
import 'package:pdf/widgets.dart' as pw;
import 'package:printing/printing.dart';

class Testing extends StatefulWidget {
  final String date;

  const Testing({required this.date, Key? key}) : super(key: key);

  @override
  State<Testing> createState() => _TestingState();
}

class _TestingState extends State<Testing> {
  // 存储从Firestore获取的失败评分数据
  List<Map<String, dynamic>> failedRatings = [];

  // 从Firestore获取数据的异步方法
  Future<void> fetchFailedRatings() async {
    try {
      // 使用传入的日期作为文档ID,获取对应集合数据
      QuerySnapshot snapshot = await FirebaseFirestore.instance
          .collection("ratings")
          .doc(widget.date)
          .collection('failed rating')
          .get();

      // 将查询结果转换为可直接使用的Map列表
      failedRatings = snapshot.docs.map((doc) => doc.data() as Map<String, dynamic>).toList();
    } catch (e) {
      print('获取数据失败: $e');
    }
  }

  @override
  Widget build(BuildContext context) {
    return PdfPreview(
      canChangeOrientation: false,
      canDebug: false,
      build: (format) => generateDocument(format),
    );
  }

  Future<Uint8List> generateDocument(PdfPageFormat format) async {
    // 先等待Firestore数据加载完成,再生成PDF
    await fetchFailedRatings();

    final doc = pw.Document(pageMode: PdfPageMode.outlines);
    final font1 = await PdfGoogleFonts.openSansRegular();
    final font2 = await PdfGoogleFonts.openSansBold();

    doc.addPage(
      pw.Page(
        pageTheme: pw.PageTheme(
          pageFormat: format.copyWith(
            marginBottom: 20,
            marginLeft: 20,
            marginRight: 20,
            marginTop: 20,
          ),
          orientation: pw.PageOrientation.portrait,
          theme: pw.ThemeData.withFont(
            base: font1,
            bold: font2,
          ),
        ),
        build: (context) {
          return pw.Column(
            crossAxisAlignment: pw.CrossAxisAlignment.start,
            children: [
              // 报表标题与日期
              pw.Center(
                child: pw.Text(
                  '失败评分报表',
                  style: pw.TextStyle(font: font2, fontSize: 20),
                ),
              ),
              pw.SizedBox(height: 10),
              pw.Center(child: pw.Text('日期: ${widget.date}')),
              pw.SizedBox(height: 20),
              // 渲染数据列表
              failedRatings.isEmpty
                  ? pw.Center(child: pw.Text('暂无数据'))
                  : pw.Expanded(
                      child: pw.ListView.builder(
                        itemCount: failedRatings.length,
                        itemBuilder: (ctx, index) {
                          final rating = failedRatings[index];
                          return pw.Container(
                            padding: pw.EdgeInsets.symmetric(vertical: 8, horizontal: 10),
                            margin: pw.EdgeInsets.only(bottom: 8),
                            decoration: pw.BoxDecoration(
                              border: pw.Border.all(color: PdfColors.grey),
                              borderRadius: pw.BorderRadius.circular(4),
                            ),
                            child: pw.Column(
                              crossAxisAlignment: pw.CrossAxisAlignment.start,
                              children: [
                                // 根据你的实际字段名修改,此处示例为userName和score
                                pw.Text('用户名: ${rating['userName'] ?? '未知'}', style: pw.TextStyle(font: font2)),
                                pw.Text('评分: ${rating['score'] ?? '无'}'),
                                // 可添加更多字段展示
                              ],
                            ),
                          );
                        },
                      ),
                    ),
            ],
          );
        },
      ),
    );
    return doc.save();
  }
}

关键修改说明

  1. 规范命名:将testing改为Testing,符合Dart类命名规范
  2. 数据获取:新增fetchFailedRatings方法,通过get()一次性获取Firestore集合数据(若需实时更新可改用snapshots()监听)
  3. PDF渲染:在generateDocument中先等待数据加载完成,再根据数据状态渲染空数据提示或列表内容,用ListView.builder高效循环展示每条数据
  4. 路径修正:使用传入的widget.date作为文档ID,确保获取对应日期的目标集合数据
  5. 布局优化:添加标题、边距和卡片样式,提升PDF内容可读性

使用示例:

Testing(date: '10-2024') // 替换为实际需要的日期格式

内容的提问来源于stack exchange,提问作者Marc louis Labitoria

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 14:44:59