flutter_integrated_whb/lib/pages/home/hidden_roll_widget.dart

144 lines
4.3 KiB
Dart

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import '../../../http/ApiService.dart';
import '../../../tools/tools.dart';
class HiddenRollWidget extends StatefulWidget {
/// 隐患列表数据
final List<Map<String, dynamic>> hiddenList;
/// 每行高度
final double rowHeight;
/// 同一时间可见的行数
final int visibleCount;
/// 滚动间隔
final Duration interval;
/// 点击回调,传递 HIDDEN_ID
final ValueChanged<String>? onItemTap;
const HiddenRollWidget({
Key? key,
required this.hiddenList,
this.rowHeight = 35,
this.visibleCount = 5,
this.interval = const Duration(seconds: 3),
this.onItemTap,
}) : super(key: key);
@override
_HiddenRollWidgetState createState() => _HiddenRollWidgetState();
}
class _HiddenRollWidgetState extends State<HiddenRollWidget> {
late final ScrollController _ctrl;
late final Timer _timer;
int _currentIndex = 0;
@override
void initState() {
super.initState();
_ctrl = ScrollController();
_timer = Timer.periodic(widget.interval, (_) => _scrollToNext());
}
void _scrollToNext() {
if (!_ctrl.hasClients || widget.hiddenList.isEmpty) return;
_currentIndex++;
if (_currentIndex >= widget.hiddenList.length) {
_currentIndex = 0;
_ctrl.jumpTo(0);
} else {
_ctrl.animateTo(
widget.rowHeight * _currentIndex,
duration: const Duration(milliseconds: 400),
curve: Curves.easeInOut,
);
}
}
@override
void dispose() {
_timer.cancel();
_ctrl.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
// 容器高度 = 行高 * 可见行数
return SizedBox(
height: widget.rowHeight * widget.visibleCount,
child: ListView.builder(
controller: _ctrl,
physics: const NeverScrollableScrollPhysics(),
itemExtent: widget.rowHeight,
itemCount: widget.hiddenList.length,
itemBuilder: (_, idx) {
final item = widget.hiddenList[idx];
// 原始时间字符串
String rawTime = item['CREATTIME'] ?? '';
DateTime? dt;
if (rawTime.isNotEmpty) {
try {
dt = DateTime.parse(rawTime.replaceAll('-', '/'));
} catch (_) {}
}
// 去除年份,仅保留 MM-dd HH:mm
String displayTime;
if (dt != null) {
displayTime = DateFormat('MM-dd HH:mm').format(dt);
} else {
final parts = rawTime.split(' ');
if (parts.length >= 2) {
final datePart = parts[0];
final timePart = parts[1];
final mmdd = datePart.length >= 5 ? datePart.substring(5) : datePart;
final hm = timePart.length >= 5 ? timePart.substring(0, 5) : timePart;
displayTime = '$mmdd $hm';
} else {
displayTime = rawTime;
}
}
// 隐患描述裁剪
String descr = item['HIDDENDESCR'] ?? '';
final displayDescr = descr.length > 10 ? '${descr.substring(0, 10)}...' : descr;
return InkWell(
onTap: () => widget.onItemTap?.call(item['HIDDEN_ID'] as String),
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 15),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
flex: 3,
child: Text(
displayDescr,
overflow: TextOverflow.ellipsis,
),
),
Expanded(
flex: 2,
child: Text(
item['CREATORNAME'] ?? '',
textAlign: TextAlign.center,
overflow: TextOverflow.ellipsis,
),
),
Expanded(
flex: 2,
child: Text(
displayTime,
textAlign: TextAlign.right,
overflow: TextOverflow.ellipsis,
),
),
],
),
),
);
},
),
);
}
}