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

Flutter中如何计算Firebase Firestore集合指定字段的总和?

解答

1. payment字段存储方式修正

你当前的存储方式存在问题:你将payment字段以字符串类型存入Firebase,后续做数值计算时需要额外做类型转换,也容易出现计算错误,建议改为存储数值类型:
修改topup方法中存储payment的逻辑:

topup() async {
try {
  FirebaseFirestore.instance.collection('topup').doc().set({
    "fullName": topfullName.text,
    "card": topcard.text,
    "date": topdate.text,
    "cvc": "***",
    // 把字符串转成int类型存储
    "payment": int.parse(topamount.text),
    "cardNumber": cardno.text,
  });
} catch (e) {
  print(e);
}}

如果需要支持小数,可以改用double.parse(topamount.text)。

2. 求和功能实现

你可以在StreamBuilder拿到Firebase返回的文档列表后,直接遍历累加所有payment字段的值,示例代码如下:

Row(
  mainAxisAlignment: MainAxisAlignment.center,
  children: [
    Expanded(
      child: SizedBox(
        height: 250,
        width: 330,
        child: ListView(
          padding: EdgeInsets.all(25),
          children: [
            StreamBuilder<QuerySnapshot>(
              stream: FirebaseFirestore.instance.collection('topup').snapshots(),
              builder: (context, snapshot){
                if(snapshot.hasData){
                  // 计算总和
                  num totalPayment = 0;
                  for (var doc in snapshot.data!.docs) {
                    totalPayment += doc['payment'] as num;
                  }
                  return Column(
                    children: [
                      // 显示总和
                      Padding(
                        padding: const EdgeInsets.all(15),
                        child: Text("总充值金额:$totalPayment.00"),
                      ),
                      SizedBox(
                        height: 400,
                        child: ListView.builder(
                          itemCount: snapshot.data!.docs.length,
                          itemBuilder: (context, index){
                            QueryDocumentSnapshot pay = snapshot.data!.docs[index];
                            return Container(
                              width: 100,
                              child: Card(
                                child: Padding(
                                  padding: EdgeInsets.all(15),
                                  child: Row(
                                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
                                    crossAxisAlignment: CrossAxisAlignment.center,
                                    children: [
                                      Column(
                                        crossAxisAlignment: CrossAxisAlignment.start,
                                        children: [
                                          Row(
                                            children: [
                                              Column(
                                                children: const [
                                                  Text("Date"),
                                                  Text(" "),
                                                  Text("Amount"),
                                                ],
                                              ),
                                              Text("  "),
                                              Column(
                                                children: [
                                                  Text(pay['date']),
                                                  Text(" "),
                                                  Text("${pay['payment']}.00"),
                                                ],
                                              ),
                                            ],
                                          ),

                                        ],
                                      ),
                                    ],
                                  ),
                                ),
                              ),
                            );
                          },
                        ),
                      ),
                    ],
                  );
                }else{
                  return const Center(
                    child: CircularProgressIndicator(),
                  );
                }
              }
            ),
          ],
        ),
      ),
    ),
  ],
),

注意:原代码中StreamBuilder返回的Expanded嵌套在ListView内部会导致布局报错,我已经把外层的Expanded替换为Column组件,避免布局异常。

如果你不想修改原有存储逻辑,还是用字符串存储的话,求和时把取值逻辑改成int.parse(doc['payment'])也可以实现计算,但更推荐存储为数值类型,减少后续维护成本。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 02:36:05