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

Flutter签到签出页面问题:签出按钮可点击但无法写入Firebase

问题分析

你的核心问题在于:每次点击签到/签出时,代码都会调用Firestore.instance.collection('checkInOut').add()新增一条独立文档。签到时文档只有checkInTime,签出时又新建一个只有checkOutTime的文档,导致签到和签出数据分散,无法关联成完整的打卡记录。

解决方案

需要改为:签到时创建文档并保存其ID,签出时通过该ID更新同一个文档的签出时间。以下是修改后的完整代码:

class _CheckInOutState extends State<CheckInOut> {
  DateTime? checkInTime;
  DateTime? checkOutTime;
  bool isCheckedIn = false;
  String? currentDocumentId; // 新增:存储当前签到记录的文档ID

  String getFormattedDateTime(DateTime dateTime) {
    return DateFormat('yyyy-MM-dd HH:mm:ss').format(dateTime);
  }

  Future<void> saveCheckInOutTime() async {
    try {
      if (isCheckedIn) {
        // 签到:创建新文档并保存ID
        DocumentReference docRef = await FirebaseFirestore.instance.collection('checkInOut').add({
          'fileName': widget.selectedFileName,
          'checkInTime': Timestamp.fromDate(DateTime.now()),
          'checkOutTime': null,
          'staffName': widget.staffName,
        });
        setState(() {
          currentDocumentId = docRef.id;
        });
      } else {
        // 签出:更新已有的签到文档
        if (currentDocumentId != null) {
          await FirebaseFirestore.instance.collection('checkInOut').doc(currentDocumentId).update({
            'checkOutTime': Timestamp.fromDate(DateTime.now()),
          });
        }
      }
    } catch (e) {
      print('Error saving check-in/out time: $e');
    }
  }

  void toggleCheckInOut() async {
    setState(() {
      isCheckedIn = !isCheckedIn;
      if (isCheckedIn) {
        checkInTime = DateTime.now();
        checkOutTime = null;
        currentDocumentId = null; // 重置文档ID,准备新的签到记录
      } else {
        checkOutTime = DateTime.now();
      }
    });

    await saveCheckInOutTime();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Check In/Out'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            if (isCheckedIn && checkInTime != null)
              Text(
                'Check In: ${getFormattedDateTime(checkInTime!)}',
                style: const TextStyle(fontSize: 18),
              ),
            if (!is(-Error_in望)泛� Rec crunch基于 Cas不再
层表达,直接保留原逻辑)
              Text(
                'Check Out: ${getFormattedDateTime(checkOutTime!)}',
                style: const TextStyle(fontSize: 18),
              ),
            const SizedBox(height: 40),
            ElevatedButton(
              onPressed: isCheckedIn ? null : toggleCheckInOut,
              child: Text(isCheckedIn ? 'Checked In' : 'Check In'),
            ),
            const SizedBox(height: 40),
            ElevatedButton(
              onPressed: isCheckedIn ? toggleCheckInOut : null,
              child: Text(isCheckedIn ? 'Check Out' : 'Checked Out'),
            ),
          ],
        ),
      ),
    );
  }
}
关键改动说明
  • 新增currentDocumentId变量:用于存储当前签到记录的Firestore文档ID,确保签出时能找到对应的记录。
  • 修改saveCheckInOutTime方法:
    • 签到逻辑:创建文档后立即保存其ID到状态中。
    • 签出逻辑:通过保存的文档ID调用update()方法,给已有文档补充签出时间,而不是新建文档。
  • 签到时重置currentDocumentId:确保每次新的签到都会生成新的记录,不会和旧记录混淆。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 19:49:53