flutter_integrated_whb/lib/customWidget/remote_file_page.dart

179 lines
5.2 KiB
Dart
Raw Normal View History

2025-07-22 13:34:34 +08:00
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:pdfx/pdfx.dart';
import 'package:path_provider/path_provider.dart';
2025-09-05 09:16:54 +08:00
import 'package:qhd_prevention/customWidget/toast_util.dart';
2025-07-22 13:34:34 +08:00
import 'package:qhd_prevention/pages/my_appbar.dart';
import 'package:qhd_prevention/customWidget/custom_button.dart';
import 'package:dio/dio.dart';
import 'package:qhd_prevention/tools/tools.dart';
class RemoteFilePage extends StatefulWidget {
final String fileUrl;
final int countdownSeconds;
const RemoteFilePage({
Key? key,
required this.fileUrl,
this.countdownSeconds = 3,
}) : super(key: key);
@override
_RemoteFilePageState createState() => _RemoteFilePageState();
}
class _RemoteFilePageState extends State<RemoteFilePage> {
String? _localPath;
bool _isLoading = true;
bool _hasScrolledToBottom = false;
bool _timerFinished = false;
late int _secondsRemaining;
Timer? _countdownTimer;
late PdfControllerPinch _pdfController;
int _totalPages = 0;
2025-09-18 21:45:41 +08:00
// 用于短文档(<=3页)的停留计时器兜底
Timer? _pageViewTimer;
2025-07-22 13:34:34 +08:00
@override
void initState() {
super.initState();
_secondsRemaining = widget.countdownSeconds;
_startCountdown();
_downloadAndLoad();
2025-09-15 15:54:03 +08:00
LoadingDialogHelper.hide();
2025-07-22 13:34:34 +08:00
}
Future<void> _downloadAndLoad() async {
try {
final url = widget.fileUrl;
final filename = url.split('/').last;
final dir = await getTemporaryDirectory();
final filePath = '${dir.path}/$filename';
final dio = Dio();
final response = await dio.get<List<int>>(
url,
options: Options(responseType: ResponseType.bytes),
);
final file = File(filePath);
await file.writeAsBytes(response.data!);
// 加载 PDF 控制器
_pdfController = PdfControllerPinch(
document: PdfDocument.openFile(filePath),
);
setState(() {
_localPath = filePath;
_isLoading = false;
});
} catch (e) {
// 下载或加载失败
setState(() {
_isLoading = false;
});
2025-09-05 09:16:54 +08:00
ToastUtil.showNormal(context, '文件加载失败: $e');
2025-07-22 13:34:34 +08:00
}
}
void _startCountdown() {
_countdownTimer = Timer.periodic(const Duration(seconds: 1), (timer) {
setState(() {
if (_secondsRemaining > 1) {
_secondsRemaining--;
} else {
_secondsRemaining = 0;
_timerFinished = true;
_countdownTimer?.cancel();
}
});
});
}
@override
void dispose() {
_countdownTimer?.cancel();
2025-09-18 21:45:41 +08:00
_pageViewTimer?.cancel();
2025-07-22 13:34:34 +08:00
if (!_isLoading) {
_pdfController.dispose();
}
super.dispose();
}
2025-09-18 21:45:41 +08:00
// 当页面改变时调用pdfx 的 page 是 1-based
void _onPageChanged(int page) {
// 取消可能存在的短页面计时器(重新开始)
_pageViewTimer?.cancel();
// 如果到达最后一页(注意页码从 1 开始)
if (_totalPages > 0 && page >= _totalPages) {
// 直接标记为已翻到底
setState(() => _hasScrolledToBottom = true);
return;
}
// 对于特别短的文档(例如 <=3 页),我们做一个停留计时器:如果用户停留在最后一页一小段时间,也视为已浏览完毕
if (_totalPages > 0 && _totalPages <= 3) {
// 如果当前页已经是最后一页page == _totalPages启动短计时器
if (page == _totalPages) {
_pageViewTimer = Timer(const Duration(seconds: 1), () {
if (mounted) setState(() => _hasScrolledToBottom = true);
});
}
}
}
2025-07-22 13:34:34 +08:00
@override
Widget build(BuildContext context) {
final isButtonEnabled = _timerFinished && _hasScrolledToBottom;
return Scaffold(
appBar: MyAppbar(title: '资料学习'),
backgroundColor: Colors.white,
body: SafeArea(
child: Column(
children: [
Expanded(
child: _isLoading
? const Center(child: CircularProgressIndicator())
: PdfViewPinch(
controller: _pdfController,
scrollDirection: Axis.vertical,
onDocumentLoaded: (document) {
setState(() {
_totalPages = document.pagesCount;
2025-09-18 21:45:41 +08:00
// 如果文档只有 1 页,直接视为已看完
if (_totalPages <= 1) {
_hasScrolledToBottom = true;
}
2025-07-22 13:34:34 +08:00
});
},
onPageChanged: (page) {
2025-09-18 21:45:41 +08:00
_onPageChanged(page);
2025-07-22 13:34:34 +08:00
},
),
),
Padding(
padding: const EdgeInsets.all(16),
child: CustomButton(
backgroundColor: isButtonEnabled ? Colors.blue : Colors.grey,
text: isButtonEnabled
? '我已学习完毕'
: _secondsRemaining == 0 ? '我已学习完毕' : '$_secondsRemaining s我已学习完毕',
onPressed: isButtonEnabled
? () {
// TODO: 完成回调
2025-09-15 15:54:03 +08:00
Navigator.pop(context, true);
2025-07-22 13:34:34 +08:00
}
: null,
),
),
],
),
),
);
}
}