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

如何实现选择日期范围调用API过滤后展示Flutter DataTable的页面

完全可以实现该需求,以下是完整的实现方案和可运行示例代码:

需求界面参考

1. 前置依赖准备

首先在pubspec.yaml中添加所需依赖:

dependencies:
  flutter:
    sdk: flutter
  http: ^1.1.0 # 用于API网络请求
  intl: ^0.18.1 # 用于日期格式化

修改完成后执行flutter pub get安装依赖。

2. 完整实现代码

import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'package:intl/intl.dart';

class DateRangeFilterPage extends StatefulWidget {
  const DateRangeFilterPage({super.key});

  @override
  State<DateRangeFilterPage> createState() => _DateRangeFilterPageState();
}

class _DateRangeFilterPageState extends State<DateRangeFilterPage> {
  DateTime? _startDate;
  DateTime? _endDate;
  List<Map<String, dynamic>> _tableData = [];
  bool _isLoading = false;
  final DateFormat _dateFormat = DateFormat('yyyy-MM-dd');

  // 调出系统自带的日期范围选择器
  Future<void> _pickDateRange() async {
    final pickedRange = await showDateRange(
      context: context,
      firstDate: DateTime(2020),
      lastDate: DateTime.now(),
      initialDateRange: _startDate != null && _endDate != null
          ? DateTimeRange(start: _startDate!, end: _endDate!)
          : null,
    );
    if (pickedRange != null) {
      setState(() {
        _startDate = pickedRange.start;
        _endDate = pickedRange.end;
      });
    }
  }

  // 点击搜索按钮调用API获取过滤后的数据
  Future<void> _searchData() async {
    if (_startDate == null || _endDate == null) {
      ScaffoldMessenger.of(context).showSnackBar(
        const SnackBar(content: Text('请先选择日期范围')),
      );
      return;
    }
    setState(() {
      _isLoading = true;
      _tableData.clear();
    });
    try {
      // 替换为你的实际API地址,请求参数名根据后端约定调整
      final response = await http.get(
        Uri.parse('https://your-api-domain.com/query/data').replace(queryParameters: {
          'startDate': _dateFormat.format(_startDate!),
          'endDate': _dateFormat.format(_endDate!),
        }),
      );
      if (response.statusCode == 200) {
        final res = json.decode(response.body);
        // 假设接口返回的列表数据在result字段下,根据实际返回结构调整
        setState(() {
          _tableData = List<Map<String, dynamic>>.from(res['result']);
        });
      }
    } catch (e) {
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text('数据请求失败:${e.toString()}')),
      );
    } finally {
      setState(() {
        _isLoading = false;
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('数据查询')),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            // 顶部日期选择+搜索按钮区域
            Row(
              children: [
                Expanded(
                  child: InkWell(
                    onTap: _pickDateRange,
                    child: InputDecorator(
                      decoration: const InputDecoration(
                        labelText: '日期范围',
                        border: OutlineInputBorder(),
                        suffixIcon: Icon(Icons.date_range),
                      ),
                      child: Text(
                        _startDate == null || _endDate == null
                            ? '请选择起止日期'
                            : '${_dateFormat.format(_startDate!)} 至 ${_dateFormat.format(_endDate!)}',
                      ),
                    ),
                  ),
                ),
                const SizedBox(width: 16),
                ElevatedButton(
                  onPressed: _searchData,
                  style: ElevatedButton.styleFrom(padding: const EdgeInsets.all(16)),
                  child: const Text('搜索'),
                ),
              ],
            ),
            const SizedBox(height: 20),
            // 底部表格展示区域
            Expanded(
              child: _isLoading
                  ? const Center(child: CircularProgressIndicator())
                  : _tableData.isEmpty
                      ? const Center(child: Text('暂无匹配数据'))
                      : SingleChildScrollView(
                          scrollDirection: Axis.horizontal,
                          child: DataTable(
                            border: TableBorder.all(color: Colors.grey.shade300),
                            columnSpacing: 40,
                            // 表头根据你的业务字段调整即可
                            columns: const [
                              DataColumn(label: Text('序号')),
                              DataColumn(label: Text('商品名称')),
                              DataColumn(label: Text('交易日期')),
                              DataColumn(label: Text('交易金额')),
                              DataColumn(label: Text('交易状态')),
                            ],
                            // 把接口数据映射为表格行
                            rows: _tableData.map((item) {
                              return DataRow(cells: [
                                DataCell(Text(item['id'].toString())),
                                DataCell(Text(item['goodsName'])),
                                DataCell(Text(item['tradeDate'])),
                                DataCell(Text(item['tradeAmount'].toString())),
                                DataCell(Text(item['tradeStatus'])),
                              ]);
                            }).toList(),
                          ),
                        ),
            ),
          ],
        ),
      ),
    );
  }
}

自定义调整说明

  • 可以修改showDateRange的firstDate和lastDate参数限制可选的日期范围
  • 替换代码中的API地址、请求参数名、返回数据解析逻辑为你实际的后端接口规则
  • 修改DataTable的columns配置和rows的映射逻辑,匹配你的业务字段即可
  • 如果需要支持分页、排序等表格功能,直接在DataTable基础上扩展即可

内容的提问来源于stack exchange,提问作者Kevin Valencia Cruz

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 04:15:02