Flutter加载JSON数据到DataTable:按Tab分栏展示并转换时间戳
Flutter 实现分类标签页展示请假数据
1. 数据模型定义
先修复原JSON的语法错误(补全缺失的引号、逗号),然后定义用于解析数据的模型类:
class Leave { final String id; final String reason; final DateTime date; final String type; Leave({ required this.id, required this.reason, required this.date, required this.type, }); // 从JSON解析为模型对象,兼容ID为数字或字符串的情况 factory Leave.fromJson(Map<String, dynamic> json) { return Leave( id: json['_id'].toString(), reason: json['reason'], date: DateTime.fromMillisecondsSinceEpoch(json['date']), type: json['type'], ); } }
2. 核心页面实现
使用DefaultTabController完成标签页管理,配合DataTable展示筛选后的请假数据,同时处理时间戳格式化:
import 'package:flutter/material.dart'; void main() => runApp(const LeaveRecordApp()); class LeaveRecordApp extends StatelessWidget { const LeaveRecordApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( title: '请假记录', theme: ThemeData(primarySwatch: Colors.blue), home: const LeaveTabPage(), ); } } class LeaveTabPage extends StatefulWidget { const LeaveTabPage({super.key}); @override State<LeaveTabPage> createState() => _LeaveTabPageState(); } class _LeaveTabPageState extends State<LeaveTabPage> { // 模拟接口返回的修正后JSON数据 final Map<String, dynamic> rawLeaveData = { "status": "done", "msg": "Got all leaves", "data": [ { "_id": "63b26e351bc7d25e5b7a1ebb", "reason": "发烧", "date": 1672511400000, "type": "tab1", "__v": 0 }, { "_id": "63b26fb91bc7d25e5b7a1ee8", "reason": "生病", "date": 1672511400000, "type": "tab1", "__v": 0 }, { "_id": "63b26dcc1bc7d25e5b7a1eb", "reason": "家庭事务", "date": 1672511400000, "type": "tab2", "__v": 0 }, { "_id": "63b26fcb1bc7d25e5b7a1ef3", "reason": "紧急请假", "date": 1672511400000, "type": "tab1", "__v": 0 } ] }; late List<Leave> allLeaveList; @override void initState() { super.initState(); // 初始化时解析所有请假数据 allLeaveList = (rawLeaveData['data'] as List) .map((item) => Leave.fromJson(item)) .toList(); } // 根据标签类型筛选数据 List<Leave> _filterLeavesByType(String tabType) { return allLeaveList.where((leave) => leave.type == tabType).toList(); } // 格式化日期为可读字符串 String _formatDateTime(DateTime date) { return "${date.year}-${date.month.toString().padLeft(2, '0')}-${date.day.toString().padLeft(2, '0')} ${date.hour.toString().padLeft(2, '0')}:${date.minute.toString().padLeft(2, '0')}"; } // 构建DataTable组件 Widget _buildLeaveTable(String tabType) { final filteredLeaves = _filterLeavesByType(tabType); return SingleChildScrollView( padding: const EdgeInsets.all(16), child: DataTable( border: TableBorder.all(), columns: const [ DataColumn(label: Text('记录ID')), DataColumn(label: Text('请假原因')), DataColumn(label: Text('请假时间')), ], rows: filteredLeaves.map((leave) { return DataRow(cells: [ DataCell(Text(leave.id)), DataCell(Text(leave.reason)), DataCell(Text(_formatDateTime(leave.date))), ]); }).toList(), ), ); } @override Widget build(BuildContext context) { return DefaultTabController( length: 2, child: Scaffold( appBar: AppBar( title: const Text('请假记录'), bottom: const TabBar( tabs: [ Tab(text: '病假'), Tab(text: '事假'), ], ), ), body: TabBarView( children: [ _buildLeaveTable('tab1'), _buildLeaveTable('tab2'), ], ), ), ); } }
关键实现要点
- 数据解析:通过
Leave.fromJson将JSON数据转换为强类型模型,同时直接把毫秒时间戳转为DateTime类型,简化后续格式化操作。 - 标签页管理:用
DefaultTabController实现标签页的切换逻辑,无需手动维护选中状态。 - 数据筛选:通过
_filterLeavesByType方法根据标签类型过滤对应的数据列表。 - 日期格式化:
_formatDateTime方法将DateTime转换为yyyy-MM-dd HH:mm的可读格式。 - 滚动适配:用
SingleChildScrollView包裹DataTable,避免数据过多时出现布局溢出问题。
内容的提问来源于stack exchange,提问作者Sakthivel k
相关产品推荐
相关产品推荐

