From 421d71f7c92aeaba2c0fe9d651bd49f8f807a93e Mon Sep 17 00:00:00 2001 From: hs <873121290@qq.com> Date: Tue, 19 Aug 2025 11:06:16 +0800 Subject: [PATCH] =?UTF-8?q?=E7=AC=AC=E4=B8=80=E7=89=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ios/Podfile.lock | 16 +- .../BaiDuMap/BaiduMapWebView.dart | 342 +++++++++++ lib/customWidget/custom_alert_dialog.dart | 7 + lib/customWidget/full_screen_video_page.dart | 236 +------- lib/customWidget/photo_picker_row.dart | 38 +- lib/http/ApiService.dart | 14 + lib/main.dart | 68 +-- .../check_record_detail_page.dart | 548 +++++++++--------- lib/pages/app/danner_repair.dart | 29 +- .../pending_rectification_detail_page.dart | 156 ++--- lib/pages/badge_manager.dart | 36 +- .../Start/safeCheck_drawer_page.dart | 2 +- lib/pages/home/home_danger_page.dart | 11 - lib/pages/home/home_page.dart | 522 ++++++++++++----- lib/pages/login_page.dart | 162 ++---- lib/pages/main_tab.dart | 20 +- lib/pages/mine/mine_set_page.dart | 147 +++-- lib/tools/auth_service.dart | 102 ++++ pubspec.lock | 324 ++++++----- pubspec.yaml | 5 + 20 files changed, 1654 insertions(+), 1131 deletions(-) create mode 100644 lib/customWidget/BaiDuMap/BaiduMapWebView.dart create mode 100644 lib/tools/auth_service.dart diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 8ee615f..b225011 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -4,7 +4,7 @@ PODS: - connectivity_plus (0.0.1): - Flutter - Flutter (1.0.0) - - flutter_app_badger (1.3.0): + - flutter_new_badger (0.0.1): - Flutter - fluttertoast (0.0.2): - Flutter @@ -36,6 +36,8 @@ PODS: - video_player_avfoundation (0.0.1): - Flutter - FlutterMacOS + - wakelock_plus (0.0.1): + - Flutter - webview_flutter_wkwebview (0.0.1): - Flutter - FlutterMacOS @@ -44,7 +46,7 @@ DEPENDENCIES: - camera_avfoundation (from `.symlinks/plugins/camera_avfoundation/ios`) - connectivity_plus (from `.symlinks/plugins/connectivity_plus/ios`) - Flutter (from `Flutter`) - - flutter_app_badger (from `.symlinks/plugins/flutter_app_badger/ios`) + - flutter_new_badger (from `.symlinks/plugins/flutter_new_badger/ios`) - fluttertoast (from `.symlinks/plugins/fluttertoast/ios`) - geolocator_apple (from `.symlinks/plugins/geolocator_apple/darwin`) - image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`) @@ -57,6 +59,7 @@ DEPENDENCIES: - shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`) - url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`) - video_player_avfoundation (from `.symlinks/plugins/video_player_avfoundation/darwin`) + - wakelock_plus (from `.symlinks/plugins/wakelock_plus/ios`) - webview_flutter_wkwebview (from `.symlinks/plugins/webview_flutter_wkwebview/darwin`) EXTERNAL SOURCES: @@ -66,8 +69,8 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/connectivity_plus/ios" Flutter: :path: Flutter - flutter_app_badger: - :path: ".symlinks/plugins/flutter_app_badger/ios" + flutter_new_badger: + :path: ".symlinks/plugins/flutter_new_badger/ios" fluttertoast: :path: ".symlinks/plugins/fluttertoast/ios" geolocator_apple: @@ -92,6 +95,8 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/url_launcher_ios/ios" video_player_avfoundation: :path: ".symlinks/plugins/video_player_avfoundation/darwin" + wakelock_plus: + :path: ".symlinks/plugins/wakelock_plus/ios" webview_flutter_wkwebview: :path: ".symlinks/plugins/webview_flutter_wkwebview/darwin" @@ -99,7 +104,7 @@ SPEC CHECKSUMS: camera_avfoundation: be3be85408cd4126f250386828e9b1dfa40ab436 connectivity_plus: cb623214f4e1f6ef8fe7403d580fdad517d2f7dd Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7 - flutter_app_badger: 16b371e989d04cd265df85be2c3851b49cb68d18 + flutter_new_badger: 133aaf93e9a5542bf905c8483d8b83c5ef4946ea fluttertoast: 2c67e14dce98bbdb200df9e1acf610d7a6264ea1 geolocator_apple: ab36aa0e8b7d7a2d7639b3b4e48308394e8cef5e image_picker_ios: 7fe1ff8e34c1790d6fff70a32484959f563a928a @@ -112,6 +117,7 @@ SPEC CHECKSUMS: shared_preferences_foundation: 9e1978ff2562383bd5676f64ec4e9aa8fa06a6f7 url_launcher_ios: 694010445543906933d732453a59da0a173ae33d video_player_avfoundation: 2cef49524dd1f16c5300b9cd6efd9611ce03639b + wakelock_plus: e29112ab3ef0b318e58cfa5c32326458be66b556 webview_flutter_wkwebview: 1821ceac936eba6f7984d89a9f3bcb4dea99ebb2 PODFILE CHECKSUM: 4305caec6b40dde0ae97be1573c53de1882a07e5 diff --git a/lib/customWidget/BaiDuMap/BaiduMapWebView.dart b/lib/customWidget/BaiDuMap/BaiduMapWebView.dart new file mode 100644 index 0000000..e17039a --- /dev/null +++ b/lib/customWidget/BaiDuMap/BaiduMapWebView.dart @@ -0,0 +1,342 @@ +// baidu_map_webview_debug.dart +import 'dart:async'; +import 'dart:convert'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:webview_flutter/webview_flutter.dart'; + +/// 更健壮的 BaiduMapWebView(带 JS 错误回传、ready 检测、超时/重试) +class BaiduMapWebView extends StatefulWidget { + final String ak; // 请确保这是 web (JS API) 可用的 AK + final double latitude; + final double longitude; + final int zoom; // 对应 uniapp 的 scale + final List> covers; + final ValueChanged>? onMarkerTap; + final Duration readyTimeout; + + const BaiduMapWebView({ + Key? key, + required this.ak, + required this.latitude, + required this.longitude, + this.zoom = 13, + this.covers = const [], + this.onMarkerTap, + this.readyTimeout = const Duration(seconds: 8), + }) : super(key: key); + + @override + State createState() => _BaiduMapWebViewState(); +} + +class _BaiduMapWebViewState extends State { + late final WebViewController _controller; + bool _pageLoaded = false; + bool _mapReady = false; + String? _lastJsMessage; + Timer? _readyTimer; + bool _showError = false; + String _errorText = ''; + + String _html(String ak) { + // HTML 模板:创建 map,定义 setCenter / setMarkersFromFlutter,转发 console 与 onerror + return ''' + + + + + + + + +
+ + + + +'''; + } + + String _escapeForJs(String s) => s.replaceAll(r'\', r'\\').replaceAll("'", r"\\'").replaceAll('\n', r' '); + + @override + void initState() { + super.initState(); + + _controller = WebViewController() + ..setJavaScriptMode(JavaScriptMode.unrestricted) + ..addJavaScriptChannel('Bridge', onMessageReceived: _onJsMessage) + ..setNavigationDelegate(NavigationDelegate( + onPageFinished: (url) { + _pageLoaded = true; + _startReadyTimer(); + // inject initial center & markers AFTER slight delay to allow JS to define functions + Future.delayed(const Duration(milliseconds: 300), () async { + await _controller.runJavaScript('setCenter(${widget.latitude}, ${widget.longitude}, ${widget.zoom});'); + final coversJson = jsonEncode(widget.covers); + await _controller.runJavaScript("setMarkersFromFlutter('${_escapeForJs(coversJson)}');"); + }); + }, + onWebResourceError: (err) { + _reportError('WebResourceError: ${err.description}'); + }, + )) + ..loadHtmlString(_html(widget.ak)); + } + + void _startReadyTimer() { + _readyTimer?.cancel(); + _readyTimer = Timer(widget.readyTimeout, () { + if (!mounted) return; + if (!_mapReady) { + setState(() { + _showError = true; + _errorText = '地图初始化超时,可能 AK 无效或网络受限。请检查 AK(需为百度 JS API Key)与网络。'; + }); + } + }); + } + + void _onJsMessage(JavaScriptMessage msg) { + _lastJsMessage = msg.message; + // 解析 message + try { + final m = jsonDecode(msg.message); + if (m is Map && m.containsKey('__mapReady') && m['__mapReady'] == true) { + // JS 报告地图已 ready + _readyTimer?.cancel(); + if (mounted) { + setState(() { + _mapReady = true; + _showError = false; + _errorText = ''; + }); + } + return; + } + } catch (_) { + // not json meta, maybe marker data or console log + } + + // handle console / error wrapper shape: {__bridge:true, kind:..., msg:...} + try { + final decoded = jsonDecode(msg.message); + if (decoded is Map && decoded['__bridge'] == true) { + final kind = decoded['kind']; + final mm = decoded['msg']; + if (kind == 'error' || kind == 'onerror') { + _reportError('JS error: $mm'); + } else { + // console log: keep last message (debug only) + debugPrint('JS log: $mm'); + } + return; + } + } catch (_) {} + + // otherwise treat as marker click payload (likely non-meta JSON) + try { + final payload = jsonDecode(msg.message) as Map; + if (widget.onMarkerTap != null) widget.onMarkerTap!(payload); + } catch (e) { + // not JSON? ignore + debugPrint('Unrecognized JS message: ${msg.message}'); + } + } + + void _reportError(String text) { + debugPrint(text); + if (!mounted) return; + setState(() { + _showError = true; + _errorText = text; + }); + } + + @override + void didUpdateWidget(covariant BaiduMapWebView oldWidget) { + super.didUpdateWidget(oldWidget); + if (_pageLoaded) { + if (oldWidget.latitude != widget.latitude || + oldWidget.longitude != widget.longitude || + oldWidget.zoom != widget.zoom) { + _controller.runJavaScript('setCenter(${widget.latitude}, ${widget.longitude}, ${widget.zoom});'); + } + if (!listEquals(oldWidget.covers, widget.covers)) { + final coversJson = jsonEncode(widget.covers); + _controller.runJavaScript("setMarkersFromFlutter('${_escapeForJs(coversJson)}');"); + } + } + } + + @override + void dispose() { + _readyTimer?.cancel(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Stack( + children: [ + WebViewWidget(controller: _controller), + if (!_mapReady && !_showError) + const Center(child: CircularProgressIndicator()), + if (_showError) + Positioned.fill( + child: Container( + color: Colors.white70, + child: Center( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 20.0), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Text('地图加载失败', style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold)), + const SizedBox(height: 8), + Text(_errorText, textAlign: TextAlign.center), + const SizedBox(height: 12), + ElevatedButton( + onPressed: () { + setState(() { + _showError = false; + _mapReady = false; + }); + // 重新加载页面 + _controller.loadHtmlString(_html(widget.ak)); + }, + child: const Text('重试'), + ), + const SizedBox(height: 6), + ElevatedButton( + onPressed: () { + // 把最后一条 js message 展示出来,便于你贴错误给我 + showDialog( + context: context, + builder: (_) => AlertDialog( + title: const Text('JS 消息'), + content: SingleChildScrollView(child: Text(_lastJsMessage ?? '无')), + actions: [ + TextButton(onPressed: () => Navigator.pop(context), child: const Text('关闭')), + ], + ), + ); + }, + child: const Text('查看 JS 日志'), + ), + ], + ), + ), + ), + ), + ), + ], + ); + } +} diff --git a/lib/customWidget/custom_alert_dialog.dart b/lib/customWidget/custom_alert_dialog.dart index 16399e6..8b08150 100644 --- a/lib/customWidget/custom_alert_dialog.dart +++ b/lib/customWidget/custom_alert_dialog.dart @@ -41,6 +41,8 @@ class CustomAlertDialog extends StatefulWidget { String cancelText = '取消', String confirmText = '确定', bool barrierDismissible = true, + final VoidCallback? onConfirm, + }) async { final result = await showDialog( context: context, @@ -52,6 +54,7 @@ class CustomAlertDialog extends StatefulWidget { cancelText: cancelText, confirmText: confirmText, mode: DialogMode.text, + onConfirm: onConfirm, ); }, ); @@ -65,6 +68,8 @@ class CustomAlertDialog extends StatefulWidget { String content = '', String confirmText = '确定', bool barrierDismissible = true, + final VoidCallback? onConfirm, + }) async { await showDialog( context: context, @@ -76,6 +81,8 @@ class CustomAlertDialog extends StatefulWidget { cancelText: '', // 隐藏取消按钮使其成为单按钮 confirmText: confirmText, mode: DialogMode.text, + onConfirm: onConfirm, + ); }, ); diff --git a/lib/customWidget/full_screen_video_page.dart b/lib/customWidget/full_screen_video_page.dart index 37558d6..d71d8e2 100644 --- a/lib/customWidget/full_screen_video_page.dart +++ b/lib/customWidget/full_screen_video_page.dart @@ -1,118 +1,49 @@ - import 'package:flutter/material.dart'; import 'package:video_player/video_player.dart'; -import 'package:flutter/services.dart'; +import 'package:chewie/chewie.dart'; -///弹窗组件:VideoPlayerPopup +/// 弹窗组件:Chewie 版 VideoPlayerPopup class VideoPlayerPopup extends StatefulWidget { - /// 视频地址 final String videoUrl; const VideoPlayerPopup({Key? key, required this.videoUrl}) : super(key: key); @override State createState() => _VideoPlayerPopupState(); - } class _VideoPlayerPopupState extends State { - late VideoPlayerController _controller; - bool _showControls = true; + late VideoPlayerController _videoController; + ChewieController? _chewieController; @override void initState() { super.initState(); - _controller = VideoPlayerController.networkUrl( - Uri.parse(widget.videoUrl), - )..initialize().then((_) { + _videoController = VideoPlayerController.networkUrl(Uri.parse(widget.videoUrl)) + ..initialize().then((_) { setState(() {}); - _controller.play(); }); - // 自动隐藏控件 - _controller.addListener(() { - if (_controller.value.isPlaying && _showControls) { - Future.delayed(const Duration(seconds: 3), () { - if (_controller.value.isPlaying && mounted) { - setState(() => _showControls = false); - } - }); - } - }); + + _chewieController = ChewieController( + videoPlayerController: _videoController, + autoPlay: true, + looping: false, + showOptions:false, + allowFullScreen: true, + allowPlaybackSpeedChanging: true, + allowMuting: true, + showControlsOnInitialize: true, + materialProgressColors: ChewieProgressColors(playedColor: Colors.blue,backgroundColor: Colors.white, handleColor:Colors.blue,bufferedColor:Colors.red), + aspectRatio: _videoController.value.aspectRatio, + ); } @override void dispose() { - _controller.dispose(); + _chewieController?.dispose(); + _videoController.dispose(); super.dispose(); } - Widget _buildControls() { - final pos = _controller.value.position; - final dur = _controller.value.duration; - String fmt(Duration d) => - '${d.inMinutes.remainder(60).toString().padLeft(2, '0')}:' - '${d.inSeconds.remainder(60).toString().padLeft(2, '0')}'; - - return Positioned.fill( - child: AnimatedOpacity( - opacity: _showControls ? 1 : 0, - duration: const Duration(milliseconds: 300), - child: GestureDetector( - onTap: () => setState(() => _showControls = !_showControls), - child: Container( - color: Colors.black45, - child: Column( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - // 进度条 - Slider( - value: pos.inMilliseconds.toDouble().clamp(0, dur.inMilliseconds.toDouble()), - max: dur.inMilliseconds.toDouble(), - onChanged: (v) { - _controller.seekTo(Duration(milliseconds: v.toInt())); - }, - ), - // 时间 + 控制按钮 - Padding( - padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), - child: Row( - children: [ - IconButton( - icon: Icon( - _controller.value.isPlaying ? Icons.pause : Icons.play_arrow, - color: Colors.white, - ), - onPressed: () { - setState(() { - _controller.value.isPlaying - ? _controller.pause() - : _controller.play(); - }); - }, - ), - Text( - '${fmt(pos)} / ${fmt(dur)}', - style: const TextStyle(color: Colors.white), - ), - const Spacer(), - IconButton( - icon: const Icon(Icons.fullscreen, color: Colors.white), - onPressed: () { - Navigator.of(context).push(MaterialPageRoute( - builder: (_) => FullScreenVideoPage( - controller: _controller))); - }, - ), - ], - ), - ), - ], - ), - ), - ), - ), - ); - } - @override Widget build(BuildContext context) { return Center( @@ -121,20 +52,18 @@ class _VideoPlayerPopupState extends State { child: Container( constraints: BoxConstraints( maxWidth: MediaQuery.of(context).size.width * 0.9, - maxHeight: MediaQuery.of(context).size.height * 0.8, + maxHeight: 500, ), decoration: BoxDecoration( - color: Colors.white, + color: Colors.black, borderRadius: BorderRadius.circular(8), ), child: Stack( children: [ - // 视频内容 - if (_controller.value.isInitialized) - AspectRatio( - aspectRatio: _controller.value.aspectRatio, - child: VideoPlayer(_controller), - ) + // 视频播放器 + if (_chewieController != null && + _videoController.value.isInitialized) + Chewie(controller: _chewieController!) else const Center(child: CircularProgressIndicator()), @@ -143,13 +72,10 @@ class _VideoPlayerPopupState extends State { top: 4, right: 4, child: IconButton( - icon: const Icon(Icons.close, color: Colors.black54), + icon: const Icon(Icons.close, color: Colors.white), onPressed: () => Navigator.of(context).pop(), ), ), - - // 播放控制 - if (_controller.value.isInitialized) _buildControls(), ], ), ), @@ -157,109 +83,3 @@ class _VideoPlayerPopupState extends State { ); } } - -/// 全屏横屏播放页面:FullScreenVideoPage -class FullScreenVideoPage extends StatefulWidget { - final VideoPlayerController controller; - const FullScreenVideoPage({Key? key, required this.controller}) : super(key: key); - - @override - State createState() => _FullScreenVideoPageState(); -} - -class _FullScreenVideoPageState extends State { - VideoPlayerController get _controller => widget.controller; - - @override - void initState() { - super.initState(); - // 进入横屏、沉浸式 - SystemChrome.setPreferredOrientations([ - DeviceOrientation.landscapeLeft, - DeviceOrientation.landscapeRight, - ]); - SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersiveSticky); - } - - @override - void dispose() { - // 恢复竖屏 - SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge); - SystemChrome.setPreferredOrientations([ - DeviceOrientation.portraitUp, - DeviceOrientation.portraitDown, - ]); - super.dispose(); - } - - @override - Widget build(BuildContext context) { - return Scaffold( - backgroundColor: Colors.black, - body: Center( - child: Stack( - children: [ - // 全屏视频 - if (_controller.value.isInitialized) - SizedBox.expand(child: VideoPlayer(_controller)) - else - const Center(child: CircularProgressIndicator()), - - // 简单控制:点击画面切换播放/暂停 - GestureDetector( - onTap: () { - setState(() { - _controller.value.isPlaying - ? _controller.pause() - : _controller.play(); - }); - }, - ), - - // 返回按钮 - Positioned( - top: 20, - left: 20, - child: IconButton( - icon: const Icon(Icons.arrow_back, color: Colors.white, size: 28), - onPressed: () => Navigator.of(context).pop(), - ), - ), - - // 时间 & 进度条(简单版) - if (_controller.value.isInitialized) - Positioned( - bottom: 20, - left: 20, - right: 20, - child: Row( - children: [ - Text( - '${_format(_controller.value.position)} / ${_format(_controller.value.duration)}', - style: const TextStyle(color: Colors.white), - ), - const SizedBox(width: 12), - Expanded( - child: VideoProgressIndicator( - _controller, - allowScrubbing: true, - colors: VideoProgressColors( - playedColor: Colors.red, - bufferedColor: Colors.white54, - backgroundColor: Colors.white30, - ), - ), - ), - ], - ), - ), - ], - ), - ), - ); - } - - String _format(Duration d) => - '${d.inMinutes.remainder(60).toString().padLeft(2, '0')}:' - '${d.inSeconds.remainder(60).toString().padLeft(2, '0')}'; -} diff --git a/lib/customWidget/photo_picker_row.dart b/lib/customWidget/photo_picker_row.dart index e8e5d46..04a2f0d 100644 --- a/lib/customWidget/photo_picker_row.dart +++ b/lib/customWidget/photo_picker_row.dart @@ -1,5 +1,4 @@ import 'dart:io'; -import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:image_picker/image_picker.dart'; import 'package:wechat_assets_picker/wechat_assets_picker.dart'; @@ -49,31 +48,12 @@ class _MediaPickerGridState extends State { ? widget.initialMediaPaths!.take(widget.maxCount).toList() : []; WidgetsBinding.instance.addPostFrameCallback((_) { - // 改动点:不要把网络地址换成 File(''),保持 File(path)(path 可能是本地也可能是 http) widget.onChanged( - _mediaPaths.map((p) => File(p)).toList(), + _mediaPaths.map((p) => p.startsWith('http') ? File('') : File(p)).toList(), ); }); } - @override - void didUpdateWidget(covariant MediaPickerRow oldWidget) { - super.didUpdateWidget(oldWidget); - // 当父组件传入的 initialMediaPaths 变化时,更新内部 _mediaPaths 并触发 onChanged - if (!listEquals(oldWidget.initialMediaPaths, widget.initialMediaPaths)) { - _mediaPaths = widget.initialMediaPaths != null - ? widget.initialMediaPaths!.take(widget.maxCount).toList() - : []; - setState(() {}); // 触发 rebuild - WidgetsBinding.instance.addPostFrameCallback((_) { - // 改动点:同上,保持 File(path) - widget.onChanged( - _mediaPaths.map((p) => File(p)).toList(), - ); - }); - } - } - Future _showPickerOptions() async { if (!widget.isEdit) return; // 不可编辑时直接返回 @@ -140,7 +120,6 @@ class _MediaPickerGridState extends State { if (picked != null) { final path = picked.path; setState(() => _mediaPaths.add(path)); - // 这里本来就是 File(p) widget.onChanged(_mediaPaths.map((p) => File(p)).toList()); widget.onMediaAdded?.call(path); } @@ -329,19 +308,6 @@ class _RepairedPhotoSectionState extends State { }); } - @override - void didUpdateWidget(covariant RepairedPhotoSection oldWidget) { - super.didUpdateWidget(oldWidget); - // 父组件传入 initialMediaPaths 变更时,同步内部 _mediaPaths 并触发 onChanged - if (!listEquals(oldWidget.initialMediaPaths, widget.initialMediaPaths)) { - _mediaPaths = widget.initialMediaPaths?.take(widget.maxCount).toList() ?? []; - setState(() {}); - WidgetsBinding.instance.addPostFrameCallback((_) { - widget.onChanged(_mediaPaths.map((p) => File(p)).toList()); - }); - } - } - @override Widget build(BuildContext context) { return Container( @@ -406,4 +372,4 @@ class _RepairedPhotoSectionState extends State { ), ); } -} +} \ No newline at end of file diff --git a/lib/http/ApiService.dart b/lib/http/ApiService.dart index d216b68..0fea833 100644 --- a/lib/http/ApiService.dart +++ b/lib/http/ApiService.dart @@ -194,6 +194,20 @@ U6Hzm1ninpWeE+awIDAQAB data: {}, ); } + /// 检查记录详情地图信息 + static Future> getRecordMapInfo(String CHECKRECORD_ID) { + return HttpManager().request( + basePath, + '/app/customCheckRecord/goMap', + method: Method.post, + data: { + 'USER_ID': SessionService.instance.loginUserId, + 'CORPINFO_ID': SessionService.instance.corpinfoId, + 'CHECKRECORD_ID': CHECKRECORD_ID + }, + ); + } + /// 月隐患 1 月隐患,2年隐患 static Future> getDanger(int type) { diff --git a/lib/main.dart b/lib/main.dart index 23b1401..725c363 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:qhd_prevention/pages/badge_manager.dart'; +import 'package:qhd_prevention/tools/auth_service.dart'; import 'package:shared_preferences/shared_preferences.dart'; import './pages/login_page.dart'; import './pages/main_tab.dart'; @@ -27,65 +28,69 @@ class GlobalMessage { } void main() async { - // 确保Flutter引擎初始化完成 WidgetsFlutterBinding.ensureInitialized(); // 初始化 EasyLoading - // 配置 EasyLoading 全局实例 EasyLoading.instance ..displayDuration = const Duration(seconds: 20) - ..indicatorType = EasyLoadingIndicatorType.ring // 使用环形指示器 - ..loadingStyle = EasyLoadingStyle.custom // 必须使用自定义样式 - ..indicatorSize = 36.0 // 接近系统默认大小 - ..radius = 0 // 无圆角 - ..progressColor = Colors.blue // 进度条颜色为系统蓝色 + ..indicatorType = EasyLoadingIndicatorType.ring + ..loadingStyle = EasyLoadingStyle.custom + ..indicatorSize = 36.0 + ..radius = 0 + ..progressColor = Colors.blue ..backgroundColor = Colors.grey.shade300 - ..indicatorColor = Colors.blue // 指示器颜色为系统蓝色 - ..textColor = Colors.black // 隐藏文字 - ..userInteractions = false // 允许用户交互(系统指示器不阻止交互) + ..indicatorColor = Colors.blue + ..textColor = Colors.black + ..userInteractions = false ..dismissOnTap = false; await initializeDateFormatting('zh_CN', null); - // 获取共享首选项实例 - final prefs = await SharedPreferences.getInstance(); - // 获取登录状态 - final isLoggedIn = prefs.getBool('isLoggedIn') ?? false; - - // 初始化HTTP管理器 + // 初始化HTTP管理器未授权回调 HttpManager.onUnauthorized = () async { - // 清除登录状态 final prefs = await SharedPreferences.getInstance(); await prefs.setBool('isLoggedIn', false); - await prefs.remove('token'); // 如果有token的话 - - // 导航到登录页 + await prefs.remove('token'); navigatorKey.currentState?.pushNamedAndRemoveUntil( '/login', (route) => false, ); - // 等一帧让页面构建完成 Future.delayed(const Duration(milliseconds: 100), () { GlobalMessage.showError('会话已过期,请重新登录'); }); }; + // 自动登录逻辑 + final prefs = await SharedPreferences.getInstance(); + final savedLogin = prefs.getBool('isLoggedIn') ?? false; + bool isLoggedIn = false; + + if (savedLogin) { + // 如果本地标记已登录,进一步验证 token 是否有效 + try { + isLoggedIn = await AuthService.isLoggedIn(); + // 这里建议 AuthService.isLoggedIn() 内部实际请求一次用户信息接口 + // 如果失败,就返回 false + } catch (e) { + isLoggedIn = false; + } + } + runApp(MyApp(isLoggedIn: isLoggedIn)); } class MyApp extends StatelessWidget { final bool isLoggedIn; - MyApp({super.key, required this.isLoggedIn}); + const MyApp({super.key, required this.isLoggedIn}); @override Widget build(BuildContext context) { return MaterialApp( title: '', - navigatorKey: navigatorKey, // 设置全局导航键 + navigatorKey: navigatorKey, builder: (context, child) { - // 修复:正确集成 EasyLoading 和 GestureDetector return EasyLoading.init( builder: (context, widget) { return GestureDetector( @@ -101,13 +106,12 @@ class MyApp extends StatelessWidget { theme: ThemeData( dividerTheme: const DividerThemeData( color: Colors.black12, - thickness: .5, // 线高 - indent: 0, // 左缩进 - endIndent: 0, // 右缩进 + thickness: .5, + indent: 0, + endIndent: 0, ), primarySwatch: Colors.blue, - // 统一设置页面背景颜色 - scaffoldBackgroundColor: const Color(0xFFF1F1F1), // 浅灰色背景 + scaffoldBackgroundColor: const Color(0xFFF1F1F1), colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple), inputDecorationTheme: const InputDecorationTheme( border: InputBorder.none, @@ -120,16 +124,14 @@ class MyApp extends StatelessWidget { ), ), progressIndicatorTheme: const ProgressIndicatorThemeData( - color: Colors.blue, // 统一颜色 + color: Colors.blue, ), ), - // 根据登录状态决定初始页面 home: isLoggedIn ? const MainPage() : const LoginPage(), debugShowCheckedModeBanner: false, routes: { '/login': (_) => const LoginPage(), - // ... 其他路由 }, ); } -} \ No newline at end of file +} diff --git a/lib/pages/app/Danger_paicha/check_record_detail_page.dart b/lib/pages/app/Danger_paicha/check_record_detail_page.dart index cfbcf10..58b140d 100644 --- a/lib/pages/app/Danger_paicha/check_record_detail_page.dart +++ b/lib/pages/app/Danger_paicha/check_record_detail_page.dart @@ -1,7 +1,11 @@ -import 'package:flutter/material.dart'; +import 'dart:convert'; +import 'dart:io'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; import 'package:photo_view/photo_view.dart'; import 'package:photo_view/photo_view_gallery.dart'; +import 'package:qhd_prevention/customWidget/BaiDuMap/BaiduMapWebView.dart'; import 'package:qhd_prevention/customWidget/ItemWidgetFactory.dart'; import 'package:qhd_prevention/customWidget/single_image_viewer.dart'; import 'package:qhd_prevention/customWidget/toast_util.dart'; @@ -12,29 +16,21 @@ import 'package:qhd_prevention/pages/app/hidden_record_detail_page.dart'; import 'package:qhd_prevention/pages/my_appbar.dart'; import 'package:qhd_prevention/tools/tools.dart'; - - class CheckRecordDetailPage extends StatefulWidget { const CheckRecordDetailPage(this.id, this.type, {super.key}); final int type; final String id; + @override _CheckRecordDetailPageState createState() => _CheckRecordDetailPageState(); } class _CheckRecordDetailPageState extends State { - // 模拟数据 - // List> varList = [ - // {"RISKPOINT_ID": "1", "CHECK_CONTENT": "安全设备检查", "ISNORMAL": "0", "IMGCOUNT": 2, "RECORDITEM_ID": "1001"}, - // {"RISKPOINT_ID": "2", "CHECK_CONTENT": "消防设施检查", "ISNORMAL": "1", "HIDDEN_ID": "2001"}, - // {"RISKPOINT_ID": "3", "CHECK_CONTENT": "电气线路检查", "ISNORMAL": "2"}, - // ]; - - // List> otherHiddenList = [ - // {"HIDDEN_ID": "3001", "HIDDENDESCR": "应急通道堵塞"}, - // {"HIDDEN_ID": "3002", "HIDDENDESCR": "安全标识缺失"}, - // ]; + // map markers + List> covers = []; + double centerLat = 39.8883; + double centerLng = 119.519; Map pd = { "LIST_NAME": "", @@ -49,102 +45,201 @@ class _CheckRecordDetailPageState extends State { "END_DATE": "", }; + List imageList = []; + List varList = []; + List hiddenList = []; - - // 地图相关 - // final LatLng _center = const LatLng(39.8883, 119.519); - // final Set _markers = {}; - double _scale = 13.0; - - int _currentImageIndex = 0; - bool _showImageViewer = false; - - - // dynamic pd; - List imageList =[]; - List varList =[]; - List hiddenList =[]; + bool _loadingDetail = true; + bool _loadingDetailTwo = true; + bool _loadingMap = true; @override void initState() { super.initState(); - // 添加地图标记 - // _markers.add(Marker( - // markerId: MarkerId("checkpoint"), - // position: _center, - // icon: BitmapDescriptor.defaultMarkerWithHue(BitmapDescriptor.hueBlue), - // )); + // 启动时并行请求,UI 使用 setState 更新 + _fetchAll(); + } + Future _fetchAll() async { + // 并行发请求,界面加载更快 + await Future.wait([ + _getInspectRecordsDetail(), + _getInspectRecordsDetailTwo(), + _getMapData(), + ]); + } - _getInspectRecordsDetail(); - _getInspectRecordsDetailTwo(); + Future _getMapData() async { + setState(() => _loadingMap = true); + try { + final resData = await ApiService.getRecordMapInfo(widget.id); + if (resData == null) { + // 接口返回空的处理 + setState(() => _loadingMap = false); + return; + } + + final built = buildCoversFromRes(resData); + double lat = centerLat; + double lng = centerLng; + + if (resData['cinfo'] != null) { + final cinfo = resData['cinfo']; + final latStr = (cinfo['LATITUDE'] ?? '').toString(); + final lngStr = (cinfo['LONGITUDE'] ?? '').toString(); + final parsedLat = double.tryParse(latStr); + final parsedLng = double.tryParse(lngStr); + if (parsedLat != null && parsedLng != null) { + lat = parsedLat; + lng = parsedLng; + } + } + + setState(() { + covers = built; + centerLat = lat; + centerLng = lng; + _loadingMap = false; + }); + } catch (e, st) { + debugPrint('getMapData error: $e\n$st'); + setState(() => _loadingMap = false); + } + } + + List> buildCoversFromRes(Map res) { + final list = >[]; + + final cinfo = res['cinfo']; + if (cinfo != null && + cinfo['LONGITUDE'] != null && + cinfo['LATITUDE'] != null && + cinfo['LONGITUDE'].toString().isNotEmpty && + cinfo['LATITUDE'].toString().isNotEmpty) { + final lat = double.tryParse(cinfo['LATITUDE'].toString()); + final lng = double.tryParse(cinfo['LONGITUDE'].toString()); + if (lat != null && lng != null) { + list.add({ + 'latitude': lat, + 'longitude': lng, + 'icon': '', // 可替换为网络图片或 data uri + 'data': {'type': 'cinfo'} + }); + } + } + + final check = res['checkrecord']; + if (check != null && + check['LONGITUDE'] != null && + check['LATITUDE'] != null && + check['LONGITUDE'].toString().isNotEmpty && + check['LATITUDE'].toString().isNotEmpty) { + final lat = double.tryParse(check['LATITUDE'].toString()); + final lng = double.tryParse(check['LONGITUDE'].toString()); + if (lat != null && lng != null) { + list.add({ + 'latitude': lat, + 'longitude': lng, + 'icon': '', + 'data': {'type': 'checkrecord'} + }); + } + } + + final vlist = (res['varList'] as List?) ?? []; + for (final item in vlist) { + try { + if (item != null && + item['LONGITUDE'] != null && + item['LATITUDE'] != null && + item['LONGITUDE'].toString().isNotEmpty && + item['LATITUDE'].toString().isNotEmpty) { + final lat = double.tryParse(item['LATITUDE'].toString()); + final lng = double.tryParse(item['LONGITUDE'].toString()); + if (lat != null && lng != null) { + list.add({ + 'latitude': lat, + 'longitude': lng, + 'icon': '', + 'data': {'type': 'varList', 'item': item} + }); + } + } + } catch (_) { + // 忽略单条解析错误 + } + } + + return list; } Future _getInspectRecordsDetail() async { + setState(() => _loadingDetail = true); try { - final Map result; - if(widget.type==1){ + if (widget.type == 1) { result = await ApiService.getInspectRecordsDetailYin(widget.id); - }else{ + } else { result = await ApiService.getInspectRecordsDetail(widget.id); } - // final result = await ApiService.getInspectRecordsDetail(widget.id); + if (result['result'] == 'success') { final List qianmingList = result['qianming'] ?? []; + // 清空旧数据,防止重复 + final List newImages = []; + for (final item in qianmingList) { + final fp = item?["FILEPATH"]?.toString(); + if (fp != null && fp.isNotEmpty) newImages.add(fp); + } setState(() { - pd= result['pd']; - varList = result['varList'] ?? []; - for(int i=0;i?) ?? pd; + varList = (result['varList'] as List?) ?? []; + imageList = newImages; + _loadingDetail = false; }); - - }else{ + } else { + setState(() => _loadingDetail = false); ToastUtil.showNormal(context, "加载数据失败"); - // _showMessage('加载数据失败'); } - } catch (e) { - // 出错时可以 Toast 或者在页面上显示错误状态 - print('加载数据失败:$e'); + } catch (e, st) { + debugPrint('getInspectRecordsDetail error: $e\n$st'); + setState(() => _loadingDetail = false); + ToastUtil.showNormal(context, "加载数据失败"); } } Future _getInspectRecordsDetailTwo() async { + setState(() => _loadingDetailTwo = true); try { - final Map result; - if(widget.type==1){ + if (widget.type == 1) { result = await ApiService.getInspectRecordsDetailTwoYin(widget.id); - }else{ + } else { result = await ApiService.getInspectRecordsDetailTwo(widget.id); } - // final result = await ApiService.getInspectRecordsDetailTwo(widget.id); + if (result['result'] == 'success') { - final List newList = result['hiddenList'] ?? []; + final List newList = (result['hiddenList'] as List?) ?? []; setState(() { - hiddenList.addAll(newList); - - + hiddenList = newList; + _loadingDetailTwo = false; }); - - }else{ + } else { + setState(() => _loadingDetailTwo = false); ToastUtil.showNormal(context, "加载数据失败"); - // _showMessage('加载数据失败'); } - } catch (e) { - // 出错时可以 Toast 或者在页面上显示错误状态 - print('加载数据失败:$e'); + } catch (e, st) { + debugPrint('getInspectRecordsDetailTwo error: $e\n$st'); + setState(() => _loadingDetailTwo = false); + ToastUtil.showNormal(context, "加载数据失败"); } } - + // UI 构建 @override Widget build(BuildContext context) { return Scaffold( appBar: MyAppbar(title: "检查记录详情"), - // _buildAppBar(), body: SingleChildScrollView( child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -153,7 +248,7 @@ class _CheckRecordDetailPageState extends State { _buildCheckContentTable(), _buildSectionTitle("其他隐患信息"), _buildOtherHiddenTable(), - // _buildMapSection(), + _buildMapSection(), // 注意这里地图高度已固定 _buildSectionTitle("清单信息"), _buildInfoList(), _buildSignPhotos(), @@ -163,36 +258,13 @@ class _CheckRecordDetailPageState extends State { ); } - // AppBar _buildAppBar() { - // return AppBar( - // leading: IconButton( - // icon: Icon(Icons.arrow_back, color: Colors.white), - // onPressed: () => Navigator.pop(context), - // ), - // title: Text("检查记录详情", style: TextStyle(color: Colors.white)), - // backgroundColor: Colors.blue, - // centerTitle: true, - // ); - // } - Widget _buildSectionTitle(String title) { return Padding( padding: EdgeInsets.symmetric(horizontal: 20, vertical: 15), child: Row( children: [ - Container( - width: 4, - height: 16, - color: Colors.blue, - margin: EdgeInsets.only(right: 10), - ), - Text( - title, - style: TextStyle( - fontWeight: FontWeight.bold, - fontSize: 16, - ), - ), + Container(width: 4, height: 16, color: Colors.blue, margin: EdgeInsets.only(right: 10)), + Text(title, style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16)), ], ), ); @@ -201,74 +273,64 @@ class _CheckRecordDetailPageState extends State { Widget _buildCheckContentTable() { return Container( margin: EdgeInsets.symmetric(horizontal: 15), - decoration: BoxDecoration( - border: Border.all(color: Colors.grey[300]!), - borderRadius: BorderRadius.circular(4), - ), + decoration: BoxDecoration(border: Border.all(color: Colors.grey[300]!), borderRadius: BorderRadius.circular(4)), child: Table( - border: TableBorder.all(color: Colors.grey[300]!), - columnWidths: const { - 0: FlexColumnWidth(3), - 1: FlexColumnWidth(1), - }, - children: [ - TableRow( - decoration: BoxDecoration(color: Colors.grey[100]), - children: [ - _buildTableHeaderCell("检查内容"), - _buildTableHeaderCell("状态"), - ], - ), - ...varList.map((item) => TableRow( - children: [ - Padding( - padding: EdgeInsets.all(8), - child: Text(item["CHECK_CONTENT"]), - ), - _buildStatusCell(item) - ], - )), - ], - ), + border: TableBorder.all(color: Colors.grey[300]!), + columnWidths: const {0: FlexColumnWidth(3), 1: FlexColumnWidth(1)}, + children: [ + TableRow(decoration: BoxDecoration(color: Colors.grey[100]), children: [ + _buildTableHeaderCell("检查内容"), + _buildTableHeaderCell("状态"), + ]), + // 若 varList 为空,显示空行或提示 + if (varList.isEmpty) + TableRow(children: [ + Padding(padding: EdgeInsets.all(12), child: Text("暂无检查内容")), + SizedBox(), + ]) + else + ...varList.map((item) { + final mi = (item is Map) ? item as Map : Map.from(item); + return TableRow(children: [ + Padding(padding: EdgeInsets.all(8), child: Text(mi["CHECK_CONTENT"]?.toString() ?? "")), + _buildStatusCell(mi), + ]); + }).toList(), + ], + ), ); } Widget _buildStatusCell(Map item) { + // 兼容字符串/数字类型 + final isnormalStr = item["ISNORMAL"]?.toString() ?? ''; + final imgCount = int.tryParse(item["IMGCOUNT"]?.toString() ?? '') ?? 0; + String status; Color color = Colors.black; VoidCallback? onTap; - switch (item["ISNORMAL"]) { - case 0: - status = "合格"; - color = Colors.blue; - if (item["IMGCOUNT"] > 0) { - onTap = () => _goToImgs(item["RECORDITEM_ID"]); - } - break; - case 1: - status = "不合格"; - color = Colors.blue; - onTap = () => _goToDetail(item["HIDDEN_ID"]); - break; - case 2: - status = "不涉及"; - color = Colors.blue; - break; - default: - status = "存在未整改隐患"; + if (isnormalStr == '0') { + status = "合格"; + color = imgCount > 0 ? Colors.blue : Colors.black; + if (imgCount > 0) onTap = () => _goToImgs(item["RECORDITEM_ID"]?.toString() ?? ''); + } else if (isnormalStr == '1') { + status = "不合格"; + color = Colors.blue; + onTap = () => _goToDetail(item["HIDDEN_ID"]?.toString() ?? ''); + } else if (isnormalStr == '2') { + status = "不涉及"; + color = Colors.blue; + } else { + status = "存在未整改隐患"; + color = Colors.black; } return GestureDetector( onTap: onTap, child: Padding( padding: EdgeInsets.all(8), - child: Center( - child: Text( - status, - style: TextStyle(color: color), - ), - ), + child: Center(child: Text(status, style: TextStyle(color: color))), ), ); } @@ -276,94 +338,87 @@ class _CheckRecordDetailPageState extends State { Widget _buildOtherHiddenTable() { return Container( margin: EdgeInsets.symmetric(horizontal: 15, vertical: 10), - decoration: BoxDecoration( - border: Border.all(color: Colors.grey[300]!), - borderRadius: BorderRadius.circular(4), - ), + decoration: BoxDecoration(border: Border.all(color: Colors.grey[300]!), borderRadius: BorderRadius.circular(4)), child: Table( - border: TableBorder.all(color: Colors.grey[300]!), - columnWidths: const { - 0: FlexColumnWidth(3), - 1: FlexColumnWidth(1), - }, - children: [ - TableRow( - decoration: BoxDecoration(color: Colors.grey[100]), - children: [ - _buildTableHeaderCell("隐患描述"), - _buildTableHeaderCell("操作"), - ], - ), - ...hiddenList.map((item) => TableRow( - children: [ - Padding( - padding: EdgeInsets.all(8), - child: Text(item["HIDDENDESCR"]), - ), - GestureDetector( - onTap: () => _goToDetail(item["HIDDEN_ID"]), - child: Padding( - padding: EdgeInsets.all(8), - child: Center( - child: Text( - "查看", - style: TextStyle(color: Colors.blue), - ), - ), - ), - ), - ], - )), - ], - ), + border: TableBorder.all(color: Colors.grey[300]!), + columnWidths: const {0: FlexColumnWidth(3), 1: FlexColumnWidth(1)}, + children: [ + TableRow(decoration: BoxDecoration(color: Colors.grey[100]), children: [ + _buildTableHeaderCell("隐患描述"), + _buildTableHeaderCell("操作"), + ]), + if (hiddenList.isEmpty) + TableRow(children: [Padding(padding: EdgeInsets.all(12), child: Text("暂无数据")), SizedBox()]) + else + ...hiddenList.map((item) { + final mi = (item is Map) ? item as Map : Map.from(item); + return TableRow(children: [ + Padding(padding: EdgeInsets.all(8), child: Text(mi["HIDDENDESCR"]?.toString() ?? "")), + GestureDetector( + onTap: () => _goToDetail(mi["HIDDEN_ID"]?.toString() ?? ''), + child: Padding( + padding: EdgeInsets.all(8), + child: Center(child: Text("查看", style: TextStyle(color: Colors.blue))), + ), + ), + ]); + }).toList(), + ], + ), ); - } + } Widget _buildTableHeaderCell(String text) { + return Padding(padding: EdgeInsets.all(8), child: Center(child: Text(text, style: TextStyle(fontWeight: FontWeight.bold)))); + } + + Widget _buildMapSection() { + // 给 webview 一个固定高度(与 uniapp 的 300px 对齐) return Padding( - padding: EdgeInsets.all(8), - child: Center( - child: Text( - text, - style: TextStyle(fontWeight: FontWeight.bold), + padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 10), + child: Container( + height: 300, + decoration: BoxDecoration(borderRadius: BorderRadius.circular(4), border: Border.all(color: Colors.grey[300]!)), + child: _loadingMap + ? Center(child: CircularProgressIndicator()) + : BaiduMapWebView( + ak: Platform.isIOS ? 'g3lZyqt0KkFnZGUsjIVO7U6lTCfpjSCt' : '43G1sKuHV6oRTrdR9VTIGPF9soej7V5a', + latitude: centerLat, + longitude: centerLng, + zoom: 13, + covers: covers, + onMarkerTap: (data) { + debugPrint('marker click: $data'); + // 如果 data 中包含 item 或 id,可用于跳转 + final type = data['type'] ?? ''; + if (type == 'varList' && data['item'] != null) { + // 示例:打开对应检查项详情 + final item = data['item']; + if (item is Map && item['HIDDEN_ID'] != null) { + _goToDetail(item['HIDDEN_ID'].toString()); + } + } + }, ), ), ); } - // Widget _buildMapSection() { - // return Container( - // height: 300, - // margin: EdgeInsets.symmetric(vertical: 10), - // child: GoogleMap( - // initialCameraPosition: CameraPosition( - // target: _center, - // zoom: _scale, - // ), - // markers: _markers, - // ), - // ); - // } - Widget _buildInfoList() { return Container( margin: EdgeInsets.symmetric(horizontal: 15), - decoration: BoxDecoration( - border: Border.all(color: Colors.grey[300]!), - borderRadius: BorderRadius.circular(4), - ), + decoration: BoxDecoration(border: Border.all(color: Colors.grey[300]!), borderRadius: BorderRadius.circular(4)), child: Column( children: [ - _buildInfoRow("清单名称", pd["LIST_NAME"]?? ''), - _buildInfoRow("排查清单类型", pd["SCREENTYPENAME"]?? ''), - _buildInfoRow("检查人", pd["USERS"]?? ''), - _buildInfoRow("检查时间", pd["CHECK_TIME"]?? ''), - _buildInfoRow("所属部门", pd["DEPARTMENT_NAME"]?? ''), - _buildInfoRow("所属岗位", pd["POST_NAME"]?? ''), - _buildInfoRow("排查周期", pd["PERIODNAME"]?? ''), - _buildInfoRow("清单类型", pd["TYPENAME"]?? ''), - if (pd["TYPENAME"] == "临时") - _buildInfoRow("排查日期", "${pd["START_DATE"]} - ${pd["END_DATE"]}"), + _buildInfoRow("清单名称", pd["LIST_NAME"]?.toString() ?? ''), + _buildInfoRow("排查清单类型", pd["SCREENTYPENAME"]?.toString() ?? ''), + _buildInfoRow("检查人", pd["USERS"]?.toString() ?? ''), + _buildInfoRow("检查时间", pd["CHECK_TIME"]?.toString() ?? ''), + _buildInfoRow("所属部门", pd["DEPARTMENT_NAME"]?.toString() ?? ''), + _buildInfoRow("所属岗位", pd["POST_NAME"]?.toString() ?? ''), + _buildInfoRow("排查周期", pd["PERIODNAME"]?.toString() ?? ''), + _buildInfoRow("清单类型", pd["TYPENAME"]?.toString() ?? ''), + if (pd["TYPENAME"]?.toString() == "临时") _buildInfoRow("排查日期", "${pd["START_DATE"] ?? ''} - ${pd["END_DATE"] ?? ''}"), ], ), ); @@ -372,16 +427,11 @@ class _CheckRecordDetailPageState extends State { Widget _buildInfoRow(String title, String value) { return Container( padding: EdgeInsets.symmetric(vertical: 12, horizontal: 15), - decoration: BoxDecoration( - border: Border(bottom: BorderSide(color: Colors.grey[300]!)), - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text(title, style: TextStyle(fontSize: 14)), - Text(value, style: TextStyle(fontSize: 14, color: Colors.grey[600])), - ], - ), + decoration: BoxDecoration(border: Border(bottom: BorderSide(color: Colors.grey[300]!))), + child: Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ + Text(title, style: TextStyle(fontSize: 14)), + Text(value, style: TextStyle(fontSize: 14, color: Colors.grey[600])), + ]), ); } @@ -392,44 +442,20 @@ class _CheckRecordDetailPageState extends State { text: "签字照片", imageUrls: imageList, onImageTapped: (index) { - presentOpaque( - SingleImageViewer(imageUrl:ApiService.baseImgPath + imageList[index]), - context, - ); + presentOpaque(SingleImageViewer(imageUrl: ApiService.baseImgPath + imageList[index]), context); }, ), ); } void _goToDetail(String hiddenId) { - dynamic item={"HIDDEN_RISKSTANDARD":"2","HIDDEN_ID":hiddenId}; - pushPage(HiddenRecordDetailPage(DangerType.detailsHiddenInvestigationRecord,item), context); - // Navigator.push( - // context, - // MaterialPageRoute( - // builder: (context) => Scaffold( - // appBar: AppBar(title: Text("隐患详情")), - // body: Center(child: Text("隐患ID: $hiddenId")), - // ), - // ), - // ); + if (hiddenId.isEmpty) return; + final dynamic item = {"HIDDEN_RISKSTANDARD": "2", "HIDDEN_ID": hiddenId}; + pushPage(HiddenRecordDetailPage(DangerType.detailsHiddenInvestigationRecord, item), context); } void _goToImgs(String recordItemId) { - pushPage(DetailImagesPage(recordItemId), context); - // Navigator.push( - // context, - // MaterialPageRoute( - // builder: (context) => Scaffold( - // appBar: AppBar(title: Text("图片详情")), - // body: Center(child: Text("记录项ID: $recordItemId")), - // ), - // ), - // ); - + if (recordItemId == null) return; + pushPage(DetailImagesPage(recordItemId.toString()), context); } - - - - -} \ No newline at end of file +} diff --git a/lib/pages/app/danner_repair.dart b/lib/pages/app/danner_repair.dart index d6c5e4d..2599f73 100644 --- a/lib/pages/app/danner_repair.dart +++ b/lib/pages/app/danner_repair.dart @@ -5,6 +5,7 @@ import 'package:qhd_prevention/customWidget/department_person_picker.dart'; import 'package:qhd_prevention/customWidget/department_picker.dart'; import 'package:qhd_prevention/customWidget/toast_util.dart'; import 'package:qhd_prevention/http/ApiService.dart'; +import 'package:qhd_prevention/pages/home/tap/item_list_widget.dart'; import '../../customWidget/ItemWidgetFactory.dart'; import '../../customWidget/custom_button.dart'; import '../../customWidget/date_picker_dialog.dart'; @@ -189,20 +190,22 @@ class DannerRepairState extends State { ), ), Divider(), - RepairedPhotoSection( - title: "整改后照片", - maxCount: 4, - mediaType: MediaType.image, - onChanged: (files) { - // 上传 files 到服务器 - gaiHouImages.clear(); - for(int i=0;i filesZheng = data['rImgs'] ?? []; for (var img in data['rImgs']) { @@ -199,85 +197,91 @@ class _PendingRectificationDetailPageState extends State _showImageGallery(files, index)), - ListItemFactory.createTextImageItem( - text: "隐患照片", - imageUrls: files, - onImageTapped: (index) { - presentOpaque( - SingleImageViewer(imageUrl:ApiService.baseImgPath + files[index]), - context, - ); - }, + if (pd['RECTIFICATIONTYPE'] == '2') + _buildInfoItem('整改期限', pd['RECTIFICATIONDEADLINE'] ?? ''), + Divider(height: 1), + // 隐患照片 + // const Text('隐患照片', style: TextStyle(fontWeight: FontWeight.bold)), + // _buildImageGrid(files, onTap: (index) => _showImageGallery(files, index)), + ListItemFactory.createTextImageItem( + text: "隐患照片", + imageUrls: files, + onImageTapped: (index) { + presentOpaque( + SingleImageViewer(imageUrl:ApiService.baseImgPath + files[index]), + context, + ); + }, + ), + + // 隐患视频 + if (videoList.isNotEmpty) ...[ + const SizedBox(height: 16), + const Text('隐患视频', style: TextStyle(fontWeight: FontWeight.bold)), + GestureDetector( + onTap: () { + + showDialog( + context: context, + barrierColor: Colors.black54, + builder: (_) => VideoPlayerPopup(videoUrl: ApiService.baseImgPath + videoList[0]['FILEPATH']), + ); + // present( + // BigVideoViewer(videoUrl:ApiService.baseImgPath + videoList[0]['FILEPATH']), + // context, + // ); + }, + // => _playVideo(ApiService.baseImgPath + videoList[0]['FILEPATH']), + child: Image.asset( + 'assets/image/videostart.png', // 替换为你的视频占位图 + color: Colors.blue, + width: 120, + height: 120, + ), + ), + ], + ], + ) ), - - // 隐患视频 - if (videoList.isNotEmpty) ...[ - const SizedBox(height: 16), - const Text('隐患视频', style: TextStyle(fontWeight: FontWeight.bold)), - GestureDetector( - onTap: () { - - showDialog( - context: context, - barrierColor: Colors.black54, - builder: (_) => VideoPlayerPopup(videoUrl: ApiService.baseImgPath + videoList[0]['FILEPATH']), - ); - // present( - // BigVideoViewer(videoUrl:ApiService.baseImgPath + videoList[0]['FILEPATH']), - // context, - // ); - }, - // => _playVideo(ApiService.baseImgPath + videoList[0]['FILEPATH']), - child: Image.asset( - 'assets/image/videostart.png', // 替换为你的视频占位图 - color: Colors.blue, - width: 120, - height: 120, - ), - ), - ], - SizedBox(height: 10,), // 整改信息部分 // if (pd['STATE'] != null && int.parse(pd['STATE']) >= 2 && int.parse(pd['STATE']) <= 4) ...[ diff --git a/lib/pages/badge_manager.dart b/lib/pages/badge_manager.dart index c87bcc3..dd3e1bb 100644 --- a/lib/pages/badge_manager.dart +++ b/lib/pages/badge_manager.dart @@ -6,7 +6,9 @@ import 'package:qhd_prevention/tools/tools.dart'; /// 单例角标管理,多接口分模块更新及全局原生角标同步 class BadgeManager extends ChangeNotifier { BadgeManager._internal(); + static final BadgeManager _instance = BadgeManager._internal(); + factory BadgeManager() => _instance; // 各模块未读 @@ -19,24 +21,30 @@ class BadgeManager extends ChangeNotifier { /// 总未读角标数 int get count => _appCount + _notifCount + _envInspectCount + _eightWorkCount; + /// MainPage 整体“应用”角标 int get appCount => _appCount; + /// MainPage “待验收”子项 int get appDysCount => _appDysCount; + /// MainPage “待整改”子项 int get appDzgCount => _appDzgCount; + int get notifCount => _notifCount; + int get envInspectCount => _envInspectCount; + int get eightWorkCount => _eightWorkCount; /// 登录后或有用户上下文时,初始化所有接口汇总数,并同步原生角标 Future initAllModules() async { try { final results = await Future.wait([ - ApiService.getWork(), // 应用中心 - ApiService.getNotifRedPoint(), // 通知公告 + ApiService.getWork(), // 应用中心 + ApiService.getNotifRedPoint(), // 通知公告 ApiService.getSafetyEnvironmentalInspectionCount(), // 安全巡检 - ApiService.getRedPoint(), // 八项作业 + ApiService.getRedPoint(), // 八项作业 ]); // 应用中心部分 @@ -53,14 +61,14 @@ class BadgeManager extends ChangeNotifier { // 安全巡检部分 final checkJson = results[2]; _envInspectCount = - (checkJson['confirmCount']?['confirmCount'] ?? 0) - (checkJson['repulseCount']?['repulseCount'] ?? 0) - (checkJson['repulseAndCheckCount']?['repulseAndCheckCount'] ?? 0) as int; + checkJson['repulseCount']?['repulseCount'] ?? 0; // 八项作业部分 final redPointJson = results[3]; _eightWorkCount = 0; - (redPointJson['count'] as Map? ?? {}).values.forEach((v) { + (redPointJson['count'] as Map? ?? {}).values.forEach(( + v, + ) { _eightWorkCount += (v ?? 0) as int; }); @@ -99,11 +107,13 @@ class BadgeManager extends ChangeNotifier { /// 更新 HomePage 安全巡检角标 void updateEnvInspectCount() async { try { - final checkJson = await ApiService.getSafetyEnvironmentalInspectionCount(); + final checkJson = + await ApiService.getSafetyEnvironmentalInspectionCount(); _envInspectCount = - (checkJson['confirmCount']?['confirmCount'] ?? 0) - (checkJson['repulseCount']?['repulseCount'] ?? 0) - (checkJson['repulseAndCheckCount']?['repulseAndCheckCount'] ?? 0) as int; + (checkJson['confirmCount']?['confirmCount'] ?? 0)( + checkJson['repulseCount']?['repulseCount'] ?? 0, + )(checkJson['repulseAndCheckCount']?['repulseAndCheckCount'] ?? 0) + as int; _onModuleChanged(); } catch (e) { debugPrint('updateEnvInspectCount error: $e'); @@ -115,7 +125,9 @@ class BadgeManager extends ChangeNotifier { try { final redPointJson = await ApiService.getRedPoint(); int sum = 0; - (redPointJson['count'] as Map? ?? {}).values.forEach((v) { + (redPointJson['count'] as Map? ?? {}).values.forEach(( + v, + ) { sum += (v ?? 0) as int; }); _eightWorkCount = sum; diff --git a/lib/pages/home/SafeCheck/Start/safeCheck_drawer_page.dart b/lib/pages/home/SafeCheck/Start/safeCheck_drawer_page.dart index 4eb8890..adbfecf 100644 --- a/lib/pages/home/SafeCheck/Start/safeCheck_drawer_page.dart +++ b/lib/pages/home/SafeCheck/Start/safeCheck_drawer_page.dart @@ -161,7 +161,7 @@ class _SafeCheckDrawerPageState extends State { List _getSelectedVideos() { return (hiddenForm['hiddenVideos'] as List>) - .map((e) => '${e['FILEPATH']}') + .map((e) => '${ApiService.baseImgPath}${e['FILEPATH']}') .toList(); } diff --git a/lib/pages/home/home_danger_page.dart b/lib/pages/home/home_danger_page.dart index 63012ea..ac33954 100644 --- a/lib/pages/home/home_danger_page.dart +++ b/lib/pages/home/home_danger_page.dart @@ -25,14 +25,6 @@ class _HomeDangerPageState extends State late TabController _tabController; int _selectedTab = 0; - // // 模拟数据 - // final List _notifications = List.generate(10, (i) { - // bool read = i % 3 == 0; - // String title = '测试数据标题标题 ${i + 1}'; - // String time = '2025-06-${10 + i} 12:3${i}'; - // return NotificationItem(title, time); - // }); - final TextEditingController _searchController = TextEditingController(); String appBarTitle=""; @@ -41,9 +33,6 @@ class _HomeDangerPageState extends State String searchName=""; bool showBottomTags=true; - - - List listOne = []; List listTwo = []; diff --git a/lib/pages/home/home_page.dart b/lib/pages/home/home_page.dart index 3d11130..965f0f8 100644 --- a/lib/pages/home/home_page.dart +++ b/lib/pages/home/home_page.dart @@ -1,18 +1,21 @@ import 'dart:async'; +import 'dart:convert'; import 'package:flutter/material.dart'; +import 'package:qhd_prevention/customWidget/custom_alert_dialog.dart'; +import 'package:qhd_prevention/customWidget/toast_util.dart'; +import 'package:qhd_prevention/tools/auth_service.dart'; +import 'package:shared_preferences/shared_preferences.dart'; import 'package:qhd_prevention/customWidget/ItemWidgetFactory.dart'; import 'package:qhd_prevention/pages/KeyProjects/keyProjects_tab_list.dart'; import 'package:qhd_prevention/pages/badge_manager.dart'; import 'package:qhd_prevention/pages/home/NFC/home_nfc_list_page.dart'; import 'package:qhd_prevention/pages/home/SafeCheck/safeCheck_tab_list.dart'; import 'package:qhd_prevention/pages/home/home_danger_page.dart'; -import 'package:qhd_prevention/pages/home/low_page.dart'; import 'package:qhd_prevention/pages/home/risk/riskControl_page.dart'; import 'package:qhd_prevention/pages/home/study/study_garden_page.dart'; import 'package:qhd_prevention/pages/home/tap/tabList/work_tab_list_page.dart'; import 'package:qhd_prevention/pages/home/userInfo_page.dart'; -import 'package:qhd_prevention/pages/home/work/danger_page.dart'; import 'package:qhd_prevention/pages/app/danger_wait_list_page.dart'; import 'package:qhd_prevention/pages/home/work/laws_regulations_page.dart'; import 'package:qhd_prevention/pages/home/workSet_page.dart'; @@ -34,51 +37,127 @@ class HomePage extends StatefulWidget { class _HomePageState extends State { int _eight_work_count = 0; int _safetyEnvironmentalInspection = 0; + + // 缓存 key + static const String _hiddenCacheKey = 'hidden_roll_cache'; + String _workKey(int idx) { switch (idx) { case 1: - return 'dpc'; // 待排查 + return 'dpc'; // 待排查 case 2: - return 'dzg'; // 待整改 + return 'dzg'; // 待整改 case 3: - return 'ycq'; // 已超期 + return 'ycq'; // 已超期 case 4: - return 'dys'; // 待验收 + return 'dys'; // 待验收 case 5: - return 'yys'; // 已验收 + return 'yys'; // 已验收 default: return ''; } } + /// 按钮信息 List> buttonInfos = [ - {"icon": "assets/icon-apps/home-base.png", "title": "人员信息", "unreadCount": 0}, - {"icon": "assets/icon-apps/home-rili.png", "title": "工作安排", "unreadCount": 0}, - {"icon": "assets/icon-apps/home-risk.png", "title": "风险布控", "unreadCount": 0}, + { + "icon": "assets/icon-apps/home-base.png", + "title": "人员信息", + "unreadCount": 0, + }, + { + "icon": "assets/icon-apps/home-rili.png", + "title": "工作安排", + "unreadCount": 0, + }, + { + "icon": "assets/icon-apps/home-risk.png", + "title": "风险布控", + "unreadCount": 0, + }, {"icon": "assets/icon-apps/home-fl.png", "title": "法律法规", "unreadCount": 0}, {"icon": "assets/icon-apps/home-gw.png", "title": "特殊作业", "unreadCount": 0}, - {"icon": "assets/icon-apps/home-zdgcgl.jpg", "title": "重点工程管理", "unreadCount": 0}, - {"icon": "assets/icon-apps/home-cns.png", "title": "安全承诺", "unreadCount": 0}, - {"icon": "assets/icon-apps/home-study.png", "title": "学习园地", "unreadCount": 0}, - {"icon": "assets/icon-apps/home-base.png", "title": "安全检查", "unreadCount": 0}, - {"icon": "assets/icon-apps/home-speEquip.jpg", "title": "设备巡检", "unreadCount": 0}, - {"icon": "assets/icon-apps/safetymeeting.png", "title": "安全例会", "unreadCount": 0}, - {"icon": "assets/icon-apps/home-xj.png", "title": "燃气巡检", "unreadCount": 0}, + { + "icon": "assets/icon-apps/home-zdgcgl.jpg", + "title": "重点工程管理", + "unreadCount": 0, + }, + { + "icon": "assets/icon-apps/home-cns.png", + "title": "安全承诺", + "unreadCount": 0, + }, + { + "icon": "assets/icon-apps/home-study.png", + "title": "学习园地", + "unreadCount": 0, + }, + { + "icon": "assets/icon-apps/home-base.png", + "title": "安全检查", + "unreadCount": 0, + }, + { + "icon": "assets/icon-apps/home-speEquip.jpg", + "title": "设备巡检", + "unreadCount": 0, + }, + { + "icon": "assets/icon-apps/safetymeeting.png", + "title": "安全例会", + "unreadCount": 0, + }, + // {"icon": "assets/icon-apps/home-xj.png", "title": "燃气巡检", "unreadCount": 0}, ]; + /// 我的工作 List> workInfos = [ - {"icon": "assets/icon-apps/jobico1.png", "index": 1, "detail": "待排查", "num": '0'}, - {"icon": "assets/icon-apps/jobico2.png", "index": 2, "detail": "待整改", "num": '0'}, - {"icon": "assets/icon-apps/jobico3.png", "index": 3, "detail": "已超期", "num": '0'}, - {"icon": "assets/icon-apps/jobico4.png", "index": 4, "detail": "待验收", "num": '0'}, - {"icon": "assets/icon-apps/jobico5.png", "index": 5, "detail": "已验收", "num": '0'}, + { + "icon": "assets/icon-apps/jobico1.png", + "index": 1, + "detail": "待排查", + "num": '0', + }, + { + "icon": "assets/icon-apps/jobico2.png", + "index": 2, + "detail": "待整改", + "num": '0', + }, + { + "icon": "assets/icon-apps/jobico3.png", + "index": 3, + "detail": "已超期", + "num": '0', + }, + { + "icon": "assets/icon-apps/jobico4.png", + "index": 4, + "detail": "待验收", + "num": '0', + }, + { + "icon": "assets/icon-apps/jobico5.png", + "index": 5, + "detail": "已验收", + "num": '0', + }, ]; /// 排查数据 List> pcData = [ - {"index": 1, "detail": {"jiancha": '0', "yinhuan": '0', "yanshou": '0'}}, - {"index": 2, "detail": {"jiancha": '0', "yinhuan": '0', "yanshou": '0'}}, - {"index": 3, "detail": {"jiancha": '0', "yinhuan": '0', "yanshou": '0'}}, + { + "index": 1, + "detail": {"jiancha": '0', "yinhuan": '0', "yanshou": '0'}, + }, + { + "index": 2, + "detail": {"jiancha": '0', "yinhuan": '0', "yanshou": '0'}, + }, + { + "index": 3, + "detail": {"jiancha": '0', "yinhuan": '0', "yanshou": '0'}, + }, ]; /// 隐患播报列表及状态 @@ -94,31 +173,109 @@ class _HomePageState extends State { @override void initState() { super.initState(); + // 使用初始化加载:先恢复缓存(若存在则直接显示),然后再发起网络请求(成功则覆盖缓存) + _initialLoad(); + BadgeManager().initAllModules(); + } - _onRefresh(); + /// 首次加载:先恢复缓存(如果有),然后在后台去刷新(只有当无缓存时才显示 loading) + Future _initialLoad() async { + final result = await AuthService.checkUpdate(); + if (FormUtils.hasValue(result, 'pd')) { + // 有更新 提示更新 + Map pd = result['pd']; + CustomAlertDialog.showAlert( + context, + title: '更新通知', + content: pd['UPLOAD_CONTENT'] ?? '', + onConfirm: () { + ToastUtil.showNormal(context, '更新去吧!'); + }, + ); + return; + } + await _loadHiddenCache(); + // 拉取其他数据 + 隐患列表(当 hiddenList 为空时显示 loading,否则不显示) + await _fetchData(); + await _fetchHiddenList(showLoading: hiddenList.isEmpty); } Future _onRefresh() async { await BadgeManager().initAllModules(); await Future.wait([ _fetchData(), + // 下拉刷新时不展示 loading(因为用户主动触发),但仍会更新缓存(成功时) _fetchHiddenList(showLoading: false), ]); } - - Future _fetchHiddenList({bool showLoading = true}) async { - // 保留已有列表,仅首次显示loading - if (showLoading && hiddenList.isEmpty) setState(() {}); + /// 从 SharedPreferences 读取缓存并设置 hiddenList(如果存在) + Future _loadHiddenCache() async { try { - final res = await ApiService.getHiddenRoll().timeout(Duration(seconds: 10)); + final prefs = await SharedPreferences.getInstance(); + final jsonStr = prefs.getString(_hiddenCacheKey); + if (jsonStr != null && jsonStr.isNotEmpty) { + final parsed = jsonDecode(jsonStr) as List; + final list = + parsed.map((e) => Map.from(e as Map)).toList(); + setState(() { + hiddenList = list; + _initialLoadingHidden = false; // 有缓存则不显示首次loading + }); + } else { + // 无缓存:保持 _initialLoadingHidden = true(只在需要显示 loading 时 setState) + setState(() { + _initialLoadingHidden = true; + }); + } + } catch (e) { + debugPrint('加载 hidden cache 失败: $e'); + // 出错时认为无缓存 + setState(() { + _initialLoadingHidden = true; + }); + } + } + + /// 保存 hiddenList 到 SharedPreferences(调用时确保传入最新 list) + Future _saveHiddenCache(List> list) async { + try { + final prefs = await SharedPreferences.getInstance(); + final jsonStr = jsonEncode(list); + await prefs.setString(_hiddenCacheKey, jsonStr); + } catch (e) { + debugPrint('保存 hidden cache 失败: $e'); + } + } + + /// 获取隐患播报列表(带缓存/加载控制逻辑) + Future _fetchHiddenList({bool showLoading = true}) async { + // 仅在需要展示 loading 且当前没有数据时 setState 显示 loading indicator + if (showLoading && hiddenList.isEmpty) { + setState(() { + _initialLoadingHidden = true; + }); + } + + try { + final res = await ApiService.getHiddenRoll().timeout( + const Duration(seconds: 10), + ); final list = (res['hiddenList'] as List).cast>(); + + // 请求成功:覆盖 UI 与缓存(始终覆盖) setState(() { hiddenList = list; _initialLoadingHidden = false; }); + + // 保存缓存(覆盖) + await _saveHiddenCache(list); } catch (e) { - // 超时或失败且已有数据,则不处理 + debugPrint('fetchHiddenList error: $e'); + + // 请求失败:如果已有缓存(hiddenList 非空),就保留缓存(什么也不做) + // 如果没有缓存(首次且失败),需要把 loading 关掉(避免一直转圈) if (hiddenList.isEmpty) { setState(() { _initialLoadingHidden = false; @@ -143,64 +300,62 @@ class _HomePageState extends State { ApiService.getDeptData(), ApiService.getSuperviseDeptData(), ]); - final myData = results[0]; - final deptData = results[1]; - final superDeptData= results[2]; + final myData = results[0]; + final deptData = results[1]; + final superDeptData = results[2]; //更新页面状态 setState(() { // ———— 更新 workInfos ———— - workInfos = workInfos.map((info) { - final idx = info['index'] as int; - final key = _workKey(idx); - final num = (hidCount[key] ?? 0).toString(); - return {...info, 'num': num}; - }).toList(); + workInfos = + workInfos.map((info) { + final idx = info['index'] as int; + final key = _workKey(idx); + final num = (hidCount[key] ?? 0).toString(); + return {...info, 'num': num}; + }).toList(); // ———— 从 BadgeManager 拿最新的本页角标 ———— _safetyEnvironmentalInspection = BadgeManager().envInspectCount; - _eight_work_count = BadgeManager().eightWorkCount; + _eight_work_count = BadgeManager().eightWorkCount; // ———— 更新 buttonInfos 中两个角标位置 ———— - buttonInfos = buttonInfos.map((info) { - switch (info['title'] as String) { - case '特殊作业': - info['unreadCount'] = _eight_work_count; - break; - case '安全检查': - info['unreadCount'] = _safetyEnvironmentalInspection; - break; - default: - // 其它保持原样 - break; - } - return info; - }).toList(); + buttonInfos = + buttonInfos.map((info) { + switch (info['title'] as String) { + case '特殊作业': + info['unreadCount'] = _eight_work_count; + break; + case '安全检查': + info['unreadCount'] = _safetyEnvironmentalInspection; + break; + default: + // 其它保持原样 + break; + } + return info; + }).toList(); // ———— 更新排查数据 pcData ———— - pcData = [ - myData, - deptData, - superDeptData, - ].asMap().entries.map((entry) { - final idx = entry.key; - final pdMap = (entry.value['pd'] as Map? ) ?? {}; - return { - 'index': idx + 1, - 'detail': { - 'jiancha': pdMap['check_count']?.toString() ?? '0', - 'yinhuan': pdMap['hidden_count']?.toString() ?? '0', - 'yanshou': pdMap['rectify_count']?.toString() ?? '0', - }, - }; - }).toList(); + pcData = + [myData, deptData, superDeptData].asMap().entries.map((entry) { + final idx = entry.key; + final pdMap = (entry.value['pd'] as Map?) ?? {}; + return { + 'index': idx + 1, + 'detail': { + 'jiancha': pdMap['check_count']?.toString() ?? '0', + 'yinhuan': pdMap['hidden_count']?.toString() ?? '0', + 'yanshou': pdMap['rectify_count']?.toString() ?? '0', + }, + }; + }).toList(); }); } catch (e) { debugPrint('加载首页数据失败:$e'); } } - @override Widget build(BuildContext context) { return Scaffold( @@ -223,19 +378,18 @@ class _HomePageState extends State { decoration: BoxDecoration( borderRadius: BorderRadius.circular(5), color: Colors.white, - ), child: Column( children: [ ListItemFactory.createBuildSimpleSection("隐患播报"), - _initialLoadingHidden && hiddenList.isEmpty + hiddenList.isEmpty ? SizedBox( - height: 150, - child: Center(child: CircularProgressIndicator()), - ) + height: 150, + child: Center(child: CircularProgressIndicator()), + ) : HiddenRollWidget(hiddenList: hiddenList), ], - ) + ), ), const SizedBox(height: 10), _buildPCDataSection(), @@ -266,18 +420,19 @@ class _HomePageState extends State { return Wrap( spacing: spacing, runSpacing: spacing, - children: workInfos.map((info) { - return SizedBox( - width: itemWidth, - child: _buildGridItem( - context, - icon: info["icon"]!, - title: info["num"]!, - subtitle: info["detail"]!, - index: info["index"]!, - ), - ); - }).toList(), + children: + workInfos.map((info) { + return SizedBox( + width: itemWidth, + child: _buildGridItem( + context, + icon: info["icon"]!, + title: info["num"]!, + subtitle: info["detail"]!, + index: info["index"]!, + ), + ); + }).toList(), ); }, ), @@ -303,7 +458,8 @@ class _HomePageState extends State { ); } - double _itemWidth(BuildContext context) => (MediaQuery.of(context).size.width - 20) / 4; + double _itemWidth(BuildContext context) => + (MediaQuery.of(context).size.width - 20) / 4; Widget _buildIconSection(BuildContext context) { return Container( @@ -314,58 +470,59 @@ class _HomePageState extends State { ), child: Wrap( runSpacing: 16, - children: buttonInfos.asMap().entries.map((entry) { - final idx = entry.key; - final info = entry.value; - return _buildIconButton( - context: context, - iconPath: info["icon"] as String, - label: info["title"] as String, - unreadCount: info["unreadCount"] as int, - onPressed: () async { - switch (idx) { - case 0:// 人员信息 - pushPage(UserinfoPage(), context); - break; - case 1:// 法律法规 - pushPage(WorkSetPage(), context); - break; - case 2:// 风险布控 - pushPage(RiskControlPage(), context); - break; - case 3:// 法律法规 - pushPage(LawsRegulationsPage(), context); - break; - case 4:// 八项作业 - await pushPage(WorkTabListPage(), context); - break; - case 5: // 重点工程管理 - await pushPage(KeyprojectsTabList(), context); - break; - case 6://安全承诺 - pushPage(SafetyCommitmentPage(), context); - break; - case 7: - pushPage(StudyGardenPage(), context); - break; - case 9: - pushPage(EquipmentInspectionListPage(), context); - break; - case 8: // 安全检查 - await pushPage(SafecheckTabList(), context); - break; - case 10: - pushPage(SafetyMeetingListPage(), context); - break; - case 11: - pushPage(HomeNfcListPage(), context); - break; - } + children: + buttonInfos.asMap().entries.map((entry) { + final idx = entry.key; + final info = entry.value; + return _buildIconButton( + context: context, + iconPath: info["icon"] as String, + label: info["title"] as String, + unreadCount: info["unreadCount"] as int, + onPressed: () async { + switch (idx) { + case 0: // 人员信息 + pushPage(UserinfoPage(), context); + break; + case 1: // 法律法规 + pushPage(WorkSetPage(), context); + break; + case 2: // 风险布控 + pushPage(RiskControlPage(), context); + break; + case 3: // 法律法规 + pushPage(LawsRegulationsPage(), context); + break; + case 4: // 八项作业 + await pushPage(WorkTabListPage(), context); + break; + case 5: // 重点工程管理 + await pushPage(KeyprojectsTabList(), context); + break; + case 6: //安全承诺 + pushPage(SafetyCommitmentPage(), context); + break; + case 7: + pushPage(StudyGardenPage(), context); + break; + case 9: + pushPage(EquipmentInspectionListPage(), context); + break; + case 8: // 安全检查 + await pushPage(SafecheckTabList(), context); + break; + case 10: + pushPage(SafetyMeetingListPage(), context); + break; + case 11: + pushPage(HomeNfcListPage(), context); + break; + } - _onRefresh(); - }, - ); - }).toList(), + _onRefresh(); + }, + ); + }).toList(), ), ); } @@ -402,16 +559,29 @@ class _HomePageState extends State { right: 20, top: -5, child: Container( - padding: const EdgeInsets.symmetric(horizontal: 4, vertical: 2), - decoration: BoxDecoration(color: Colors.red, borderRadius: BorderRadius.circular(10)), - constraints: const BoxConstraints(minWidth: 16, minHeight: 16), + padding: const EdgeInsets.symmetric( + horizontal: 4, + vertical: 2, + ), + decoration: BoxDecoration( + color: Colors.red, + borderRadius: BorderRadius.circular(10), + ), + constraints: const BoxConstraints( + minWidth: 16, + minHeight: 16, + ), child: Center( - child: Text( + child: Text( unreadCount > 99 ? '99+' : '$unreadCount', - style: const TextStyle(color: Colors.white, fontSize: 11, height: 1), + style: const TextStyle( + color: Colors.white, + fontSize: 11, + height: 1, + ), textAlign: TextAlign.center, ), - ) + ), ), ), ], @@ -437,9 +607,19 @@ class _HomePageState extends State { for (var i = 0; i < 3; i++) Column( children: [ - Text(values[i], style: TextStyle(color: colors[i], fontSize: 18, fontWeight: FontWeight.bold)), + Text( + values[i], + style: TextStyle( + color: colors[i], + fontSize: 18, + fontWeight: FontWeight.bold, + ), + ), const SizedBox(height: 4), - Text(labels[i], style: TextStyle(color: Colors.black38, fontSize: 15)), + Text( + labels[i], + style: TextStyle(color: Colors.black38, fontSize: 15), + ), ], ), Container( @@ -449,8 +629,14 @@ class _HomePageState extends State { child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ - Text(tagLabels[idx][0], style: TextStyle(color: Colors.white, fontSize: 12)), - Text(tagLabels[idx][1], style: TextStyle(color: Colors.white, fontSize: 12)), + Text( + tagLabels[idx][0], + style: TextStyle(color: Colors.white, fontSize: 12), + ), + Text( + tagLabels[idx][1], + style: TextStyle(color: Colors.white, fontSize: 12), + ), ], ), ), @@ -463,7 +649,13 @@ class _HomePageState extends State { ); } - Widget _buildGridItem(BuildContext context, {required String icon, required String title, required String subtitle, required int index}) { + Widget _buildGridItem( + BuildContext context, { + required String icon, + required String title, + required String subtitle, + required int index, + }) { return GestureDetector( onTap: () { if (index == 1) { @@ -480,7 +672,10 @@ class _HomePageState extends State { }, child: Container( padding: const EdgeInsets.all(8), - decoration: BoxDecoration(color: const Color(0xfbf9f9ff), borderRadius: BorderRadius.circular(6)), + decoration: BoxDecoration( + color: const Color(0xfbf9f9ff), + borderRadius: BorderRadius.circular(6), + ), child: Row( children: [ Image.asset(icon, width: 35, height: 35), @@ -489,9 +684,22 @@ class _HomePageState extends State { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text(title, style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold), maxLines: 1, overflow: TextOverflow.ellipsis), + Text( + title, + style: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.bold, + ), + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), const SizedBox(height: 4), - Text(subtitle, style: const TextStyle(fontSize: 14, color: Colors.black), maxLines: 1, overflow: TextOverflow.ellipsis), + Text( + subtitle, + style: const TextStyle(fontSize: 14, color: Colors.black), + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), ], ), ), diff --git a/lib/pages/login_page.dart b/lib/pages/login_page.dart index 8183aef..eea3cef 100644 --- a/lib/pages/login_page.dart +++ b/lib/pages/login_page.dart @@ -1,17 +1,9 @@ -// ignore_for_file: use_build_context_synchronously - -import 'dart:convert'; - -import 'package:encrypt/encrypt.dart' as encrypt; +import 'package:qhd_prevention/customWidget/custom_alert_dialog.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; -import 'package:dio/dio.dart'; import 'package:fluttertoast/fluttertoast.dart'; -import 'package:qhd_prevention/tools/StorageService.dart'; -import 'package:shared_preferences/shared_preferences.dart'; -import '../http/ApiService.dart'; -import 'package:pointycastle/asymmetric/api.dart' show RSAPublicKey; -import '../http/HttpManager.dart'; +import 'package:qhd_prevention/customWidget/toast_util.dart'; +import 'package:qhd_prevention/tools/auth_service.dart'; import '../tools/tools.dart'; import 'main_tab.dart'; @@ -45,14 +37,44 @@ class LoginPage extends StatefulWidget { } class _LoginPageState extends State { - final TextEditingController _phoneController = TextEditingController(text: '13293211008'); - final TextEditingController _passwordController = TextEditingController(text: 'Zsaq@123456'); + final TextEditingController _phoneController = TextEditingController( + text: '13293211008', + ); + final TextEditingController _passwordController = TextEditingController( + text: 'Zsaq@123456', + ); final GlobalKey _formKey = GlobalKey(); String _errorMessage = ''; bool _isLoading = false; bool _obscurePassword = true; bool _agreed = false; + @override + void initState() { + // TODO: implement initState + super.initState(); + _checkUpdata(); + } + + Future _checkUpdata() async { + final result = await AuthService.checkUpdate(); + if (FormUtils.hasValue(result, 'pd')) { + // 有更新 提示更新 + Map pd = result['pd']; + CustomAlertDialog.showConfirm( + context, + title: '更新通知', + cancelText: '', + confirmText: '我知道了', + content: pd['UPLOAD_CONTENT'] ?? '', + onConfirm: () { + ToastUtil.showNormal(context, '更新去吧!'); + } + ); + return; + } + } + @override Widget build(BuildContext context) { return Scaffold( @@ -105,8 +127,7 @@ class _LoginPageState extends State { hintText: "请输入手机号...", keyboardType: TextInputType.phone, validator: (value) { - if (value == null || value.isEmpty) - return '请输入手机号'; + if (value == null || value.isEmpty) return '请输入手机号'; // if (!RegExp(r'^1[3-9]\d{9}\$').hasMatch(value)) // return '请输入有效的手机号'; return null; @@ -130,14 +151,12 @@ class _LoginPageState extends State { color: Colors.white, ), onPressed: - () => - setState( - () => _obscurePassword = !_obscurePassword, + () => setState( + () => _obscurePassword = !_obscurePassword, ), ), validator: (value) { - if (value == null || value.isEmpty) - return '请输入密码'; + if (value == null || value.isEmpty) return '请输入密码'; return null; }, ), @@ -162,15 +181,14 @@ class _LoginPageState extends State { height: 48, child: ElevatedButton( onPressed: - (!_isLoading && _agreed) ? _handleLogin : null, + (!_isLoading && _agreed) ? _handleLogin : null, style: ElevatedButton.styleFrom( backgroundColor: Colors.blue, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8), ), ), - child: - const Text( + child: const Text( '登录', style: TextStyle( fontSize: 18, @@ -210,10 +228,10 @@ class _LoginPageState extends State { color: Color(0xFF0D1D8C), ), recognizer: - TapGestureRecognizer() - ..onTap = () { - // 打开用户协议 - }, + TapGestureRecognizer() + ..onTap = () { + // 打开用户协议 + }, ), TextSpan( text: '和', @@ -227,10 +245,10 @@ class _LoginPageState extends State { color: Color(0xFF0D1D8C), ), recognizer: - TapGestureRecognizer() - ..onTap = () { - // 打开隐私政策 - }, + TapGestureRecognizer() + ..onTap = () { + // 打开隐私政策 + }, ), ], ), @@ -294,26 +312,11 @@ class _LoginPageState extends State { } Future _handleLogin() async { - // 表单校验 if (!(_formKey.currentState?.validate() ?? false)) return; final userName = _phoneController.text.trim(); final userPwd = _passwordController.text; - // RSA 加密:encrypt 包的用法 - final parser = encrypt.RSAKeyParser(); - final pub = parser.parse(ApiService.publicKey) as RSAPublicKey; - final encrypter = encrypt.Encrypter(encrypt.RSA(publicKey: pub)); - final plain = 'zcloudchina$userName,zy,$userPwd'; - - String keydataVal; - try { - keydataVal = encrypter.encrypt(plain).base64; - } catch (e) { - Fluttertoast.showToast(msg: '加密失败:$e', toastLength: Toast.LENGTH_LONG); - return; - } - setState(() => _isLoading = true); showDialog( context: context, @@ -322,68 +325,21 @@ class _LoginPageState extends State { ); try { - final data = await ApiService.loginCheck(keydataVal); - final result = data['result'] as String? ?? ''; + final success = await AuthService.login(userName, userPwd); - if (result == 'success') { - // 存储用户信息 - final prefs = await SharedPreferences.getInstance(); - await prefs.setString('USER', json.encode(data)); - await prefs.setStringList('remember', [userName, userPwd]); + Navigator.of(context).pop(); // 关loading + setState(() => _isLoading = false); - SessionService.instance - ..setLoginUserId(data['USER_ID'] as String) - ..setCorpinfoId(data['CORPINFO_ID'] as String) - ..setDeptId(data['DEPARTMENT_ID'] as String) - ..setDeptLevel(data['DEPARTMENT_LEVEL'] as String) - ..setIsRest(data['ISREST'] as String) - ..setUsername(data['NAME'] as String) - ..setLoginUser(data); // 这里 data 保存整个用户 JSON - - final weak = data['WEAK_PASSWORD'] == '1'; - final longTerm = data['LONG_TERM_PASSWORD_NOT_CHANGED'] == '1'; - - Navigator.of(context).pop(); // 关 loading - setState(() => _isLoading = false); - - if (weak) { - // uni.redirectTo({ - // url: '/pages/login/forget/forget-reset?canBack=1' - // }); - } else if (longTerm) { - // uni.redirectTo({ - // url: '/pages/login/forget/forget-reset?canBack=2' - // }); - - } else { - Navigator.pushReplacement( - context, - MaterialPageRoute(builder: (_) => const MainPage()), - ); - } - - } else { - // 理论上不会走这里,非 'success' 会抛 ApiException + if (success) { + Navigator.pushReplacement( + context, + MaterialPageRoute(builder: (_) => const MainPage()), + ); } - - } on ApiException catch (e) { - // 业务错误: - Navigator.of(context).pop(); - setState(() => _isLoading = false); - - String tip = e.message; - - Fluttertoast.showToast(msg: tip, toastLength: Toast.LENGTH_LONG); - } catch (e) { - // 网络或其它未预期错误 Navigator.of(context).pop(); setState(() => _isLoading = false); - Fluttertoast.showToast( - msg: '服务器正在升级,请稍后再试。\n${e.toString()}', - toastLength: Toast.LENGTH_LONG, - ); + Fluttertoast.showToast(msg: '登录失败: $e'); } } - -} \ No newline at end of file +} diff --git a/lib/pages/main_tab.dart b/lib/pages/main_tab.dart index aca804d..21b97c2 100644 --- a/lib/pages/main_tab.dart +++ b/lib/pages/main_tab.dart @@ -90,20 +90,20 @@ class _MainPageState extends State { ? null : MyAppbar( title: - _currentIndex == 0 ? "泰盛安全首页" : _titles[_currentIndex], + _currentIndex == 0 ? "智守安全首页" : _titles[_currentIndex], backgroundColor: Colors.blue, isBack: false, actions: [ if (_currentIndex == 0) ...[ - IconButton( - onPressed: () => Navigator.push( - context, - MaterialPageRoute( - builder: (_) => NfcTestPage()), - ), - icon: Image.asset("assets/images/ai_img.png", - width: 20, height: 20), - ), + // IconButton( + // onPressed: () => Navigator.push( + // context, + // MaterialPageRoute( + // builder: (_) => NfcTestPage()), + // ), + // icon: Image.asset("assets/images/ai_img.png", + // width: 20, height: 20), + // ), IconButton( onPressed: () => Navigator.push( context, diff --git a/lib/pages/mine/mine_set_page.dart b/lib/pages/mine/mine_set_page.dart index e19b227..204daf8 100644 --- a/lib/pages/mine/mine_set_page.dart +++ b/lib/pages/mine/mine_set_page.dart @@ -1,21 +1,47 @@ import 'package:flutter/material.dart'; +import 'package:qhd_prevention/customWidget/custom_alert_dialog.dart'; +import 'package:qhd_prevention/customWidget/toast_util.dart'; import 'package:qhd_prevention/pages/home/study/face_ecognition_page.dart'; import 'package:qhd_prevention/pages/login_page.dart'; import 'package:qhd_prevention/pages/mine/mine_first_sign_page.dart'; import 'package:qhd_prevention/pages/mine/mine_set_pwd_page.dart'; -import 'package:qhd_prevention/pages/mine/mine_sign_page.dart'; import 'package:qhd_prevention/pages/my_appbar.dart'; +import 'package:qhd_prevention/tools/auth_service.dart'; import 'package:qhd_prevention/tools/h_colors.dart'; -import 'package:shared_preferences/shared_preferences.dart'; import '../../tools/tools.dart'; -class MineSetPage extends StatelessWidget { +class MineSetPage extends StatefulWidget { const MineSetPage({super.key}); - Future _clearUserSession() async { - final prefs = await SharedPreferences.getInstance(); - await prefs.remove('isLoggedIn'); // 清除登录状态 + @override + State createState() => _MineSetPageState(); +} + +class _MineSetPageState extends State { + + /// 检查更新 + Future _checkUpdate() async { + LoadingDialogHelper.show(); + final result = await AuthService.checkUpdate(); + LoadingDialogHelper.hide(); + if (FormUtils.hasValue(result, 'pd')) { + // 有更新 提示更新 + Map pd = result['pd']; + CustomAlertDialog.showConfirm( + context, + title: '更新通知', + cancelText: '', + confirmText: '我知道了', + content: pd['UPLOAD_CONTENT'] ?? '', + onConfirm: () { + ToastUtil.showNormal(context, '更新去吧!'); + } + ); + }else{ + ToastUtil.showNormal(context, '已经是最新版本!'); + + } } @override @@ -28,70 +54,65 @@ class MineSetPage extends StatelessWidget { GestureDetector( child: _setItemWidget("修改密码"), onTap: () { - pushPage(MineSetPwdPage(), context); + pushPage(const MineSetPwdPage(), context); }, ), - Divider(height: 1, color: Colors.black12), + const Divider(height: 1, color: Colors.black12), + GestureDetector( child: _setItemWidget("更新人脸信息"), onTap: () { - pushPage(FaceRecognitionPage(studentId: '', mode: FaceMode.manual,), context); + pushPage( + const FaceRecognitionPage(studentId: '', mode: FaceMode.manual), + context, + ); + }, + ), + const Divider(height: 1, color: Colors.black12), + + GestureDetector( + child: _setItemWidget("更新签字信息"), + onTap: () { + pushPage(const FirstSignPage(), context); + // pushPage(MineSignPage(), context); + }, + ), + const Divider(height: 1, color: Colors.black12), + + GestureDetector( + child: _setItemWidget("检查更新"), + onTap: () { + _checkUpdate(); }, ), - Divider(height: 1, color: Colors.black12), + const SizedBox(height: 15), + GestureDetector( - child: _setItemWidget("更新签字信息"), - onTap: () { - pushPage(FirstSignPage(), context); - // pushPage(MineSignPage(), context); - } + child: Container( + padding: const EdgeInsets.symmetric(vertical: 15), + color: Colors.white, + child: const Center( + child: Text("退出当前账户", style: TextStyle(fontSize: 16)), + ), + ), + onTap: () async { + CustomAlertDialog.showConfirm( + context, + title: '确认退出', + content: '确定要退出当前账号吗', + onConfirm: () async { + await AuthService.logout(); // ✅ 等待登出完成 + if (!mounted) return; + Navigator.pushAndRemoveUntil( + context, + MaterialPageRoute(builder: (context) => const LoginPage()), + (Route route) => false, + ); + }, + ); + }, ), - - Divider(height: 1, color: Colors.black12), - GestureDetector(child: _setItemWidget("检查更新"), onTap: () {}), - - SizedBox(height: 15), - - GestureDetector( - child: Container( - padding: EdgeInsets.symmetric(vertical: 15), - color: Colors.white, - child: Center(child: Text("退出当前账户", style: TextStyle(fontSize: 16),)), - ), - onTap: () async { - // 显示确认对话框 - bool? confirm = await showDialog( - context: context, - builder: (context) => AlertDialog( - title: Text("确认退出"), - content: Text("确定要退出当前账号吗?"), - actions: [ - TextButton( - onPressed: () => Navigator.pop(context, false), - child: Text("取消"), - ), - TextButton( - onPressed: () => Navigator.pop(context, true), - child: Text("确定", style: TextStyle(color: Colors.red)), - ), - ], - ), - ); - - if (confirm == true) { - // 清除用户登录状态 - await _clearUserSession(); - - // 跳转到登录页并清除所有历史路由 - Navigator.pushAndRemoveUntil( - context, - MaterialPageRoute(builder: (context) => LoginPage()), - (Route route) => false, // 移除所有历史路由 - ); - } - }, - ), ], ), ); @@ -102,12 +123,12 @@ class MineSetPage extends StatelessWidget { height: 55, color: Colors.white, child: Padding( - padding: EdgeInsets.all(15), + padding: const EdgeInsets.all(15), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text(text, style: TextStyle(fontSize: 16)), - Icon(Icons.chevron_right), + Text(text, style: const TextStyle(fontSize: 16)), + const Icon(Icons.chevron_right), ], ), ), diff --git a/lib/tools/auth_service.dart b/lib/tools/auth_service.dart new file mode 100644 index 0000000..c6b5646 --- /dev/null +++ b/lib/tools/auth_service.dart @@ -0,0 +1,102 @@ +import 'dart:convert'; +import 'package:encrypt/encrypt.dart' as encrypt; +import 'package:pointycastle/asymmetric/api.dart' show RSAPublicKey; +import 'package:qhd_prevention/tools/tools.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:fluttertoast/fluttertoast.dart'; + +import '../http/ApiService.dart'; + +class AuthService { + static const _keyUser = 'USER'; + static const _keyRemember = 'remember'; + static const _keyIsLoggedIn = 'isLoggedIn'; + + /// 登录 + static Future login(String username, String password) async { + final parser = encrypt.RSAKeyParser(); + final pub = parser.parse(ApiService.publicKey) as RSAPublicKey; + final encrypter = encrypt.Encrypter(encrypt.RSA(publicKey: pub)); + + final plain = 'zcloudchina$username,zy,$password'; + + String encrypted; + try { + encrypted = encrypter.encrypt(plain).base64; + } catch (e) { + Fluttertoast.showToast(msg: '加密失败:$e'); + return false; + } + + final data = await ApiService.loginCheck(encrypted); + final result = data['result'] as String? ?? ''; + if (result != 'success') { + return false; + } + + final prefs = await SharedPreferences.getInstance(); + await prefs.setString(_keyUser, json.encode(data)); + await prefs.setStringList(_keyRemember, [username, password]); + await prefs.setBool(_keyIsLoggedIn, true); + + SessionService.instance + ..setLoginUserId(data['USER_ID'] as String) + ..setCorpinfoId(data['CORPINFO_ID'] as String) + ..setDeptId(data['DEPARTMENT_ID'] as String) + ..setDeptLevel(data['DEPARTMENT_LEVEL'] as String) + ..setIsRest(data['ISREST'] as String) + ..setUsername(data['NAME'] as String) + ..setLoginUser(data); + + return true; + } + /// 检查更新 + static Future> checkUpdate() async { + final data = await ApiService.getUpdateInfo(); + final result = data['result'] as String? ?? ''; + if (result == 'success') { + return data; + } + return {}; + } + + + + /// 验证是否已登录(通过重新登录) + static Future isLoggedIn() async { + final prefs = await SharedPreferences.getInstance(); + final isLocalLoggedIn = prefs.getBool(_keyIsLoggedIn) ?? false; + if (!isLocalLoggedIn) return false; + + final remember = prefs.getStringList(_keyRemember); + if (remember == null || remember.length < 2) return false; + + final username = remember[0]; + final password = remember[1]; + + // 用存储的账号密码重新登录 + final success = await login(username, password); + if (!success) { + await logout(); + return false; + } + return true; + } + + + /// 获取已保存的用户信息 + static Future?> getUser() async { + final prefs = await SharedPreferences.getInstance(); + final jsonStr = prefs.getString(_keyUser); + if (jsonStr == null) return null; + return json.decode(jsonStr); + } + + /// 登出 + static Future logout() async { + final prefs = await SharedPreferences.getInstance(); + await prefs.remove(_keyUser); + await prefs.remove(_keyRemember); + await prefs.setBool(_keyIsLoggedIn, false); + } +} diff --git a/pubspec.lock b/pubspec.lock index deba681..3ff5f30 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -6,7 +6,7 @@ packages: description: name: args sha256: d0481093c50b1da8910eb0bb301626d4d8eb7284aa739614d2b394ee09e3ea04 - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "2.7.0" asn1lib: @@ -14,7 +14,7 @@ packages: description: name: asn1lib sha256: "9a8f69025044eb466b9b60ef3bc3ac99b4dc6c158ae9c56d25eeccf5bc56d024" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "1.6.5" async: @@ -22,7 +22,7 @@ packages: description: name: async sha256: "758e6d74e971c3e5aceb4110bfd6698efc7f501675bcfe0c775459a8140750eb" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "2.13.0" boolean_selector: @@ -30,7 +30,7 @@ packages: description: name: boolean_selector sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "2.1.2" camera: @@ -38,7 +38,7 @@ packages: description: name: camera sha256: d6ec2cbdbe2fa8f5e0d07d8c06368fe4effa985a4a5ddade9cc58a8cd849557d - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "0.11.2" camera_android_camerax: @@ -46,7 +46,7 @@ packages: description: name: camera_android_camerax sha256: "58b8fe843a3c83fd1273c00cb35f5a8ae507f6cc9b2029bcf7e2abba499e28d8" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "0.6.19+1" camera_avfoundation: @@ -54,7 +54,7 @@ packages: description: name: camera_avfoundation sha256: e4aca5bccaf897b70cac87e5fdd789393310985202442837922fd40325e2733b - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "0.9.21+1" camera_platform_interface: @@ -62,7 +62,7 @@ packages: description: name: camera_platform_interface sha256: "2f757024a48696ff4814a789b0bd90f5660c0fb25f393ab4564fb483327930e2" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "2.10.0" camera_web: @@ -70,7 +70,7 @@ packages: description: name: camera_web sha256: "595f28c89d1fb62d77c73c633193755b781c6d2e0ebcd8dc25b763b514e6ba8f" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "0.3.5" characters: @@ -78,15 +78,23 @@ packages: description: name: characters sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803 - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "1.4.0" + chewie: + dependency: "direct main" + description: + name: chewie + sha256: "19b93a1e60e4ba640a792208a6543f1c7d5b124d011ce0199e2f18802199d984" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "1.12.1" clock: dependency: transitive description: name: clock sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "1.1.2" collection: @@ -94,7 +102,7 @@ packages: description: name: collection sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "1.19.1" connectivity_plus: @@ -102,7 +110,7 @@ packages: description: name: connectivity_plus sha256: b5e72753cf63becce2c61fd04dfe0f1c430cc5278b53a1342dc5ad839eab29ec - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "6.1.5" connectivity_plus_platform_interface: @@ -110,7 +118,7 @@ packages: description: name: connectivity_plus_platform_interface sha256: "42657c1715d48b167930d5f34d00222ac100475f73d10162ddf43e714932f204" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "2.0.1" convert: @@ -118,7 +126,7 @@ packages: description: name: convert sha256: b30acd5944035672bc15c6b7a8b47d773e41e2f17de064350988c5d02adb1c68 - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "3.1.2" cross_file: @@ -126,7 +134,7 @@ packages: description: name: cross_file sha256: "7caf6a750a0c04effbb52a676dce9a4a592e10ad35c34d6d2d0e4811160d5670" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "0.3.4+2" crypto: @@ -134,7 +142,7 @@ packages: description: name: crypto sha256: "1e445881f28f22d6140f181e07737b22f1e099a5e1ff94b0af2f9e4a463f4855" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "3.0.6" csslib: @@ -142,7 +150,7 @@ packages: description: name: csslib sha256: "09bad715f418841f976c77db72d5398dc1253c21fb9c0c7f0b0b985860b2d58e" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "1.0.2" cupertino_icons: @@ -150,7 +158,7 @@ packages: description: name: cupertino_icons sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6 - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "1.0.8" dbus: @@ -158,7 +166,7 @@ packages: description: name: dbus sha256: "79e0c23480ff85dc68de79e2cd6334add97e48f7f4865d17686dd6ea81a47e8c" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "0.7.11" dio: @@ -166,7 +174,7 @@ packages: description: name: dio sha256: d90ee57923d1828ac14e492ca49440f65477f4bb1263575900be731a3dac66a9 - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "5.9.0" dio_web_adapter: @@ -174,7 +182,7 @@ packages: description: name: dio_web_adapter sha256: "7586e476d70caecaf1686d21eee7247ea43ef5c345eab9e0cc3583ff13378d78" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "2.1.1" dotted_border: @@ -182,7 +190,7 @@ packages: description: name: dotted_border sha256: "99b091ec6891ba0c5331fdc2b502993c7c108f898995739a73c6845d71dad70c" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "3.1.0" encrypt: @@ -190,7 +198,7 @@ packages: description: name: encrypt sha256: "62d9aa4670cc2a8798bab89b39fc71b6dfbacf615de6cf5001fb39f7e4a996a2" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "5.0.3" extended_image: @@ -198,7 +206,7 @@ packages: description: name: extended_image sha256: f6cbb1d798f51262ed1a3d93b4f1f2aa0d76128df39af18ecb77fa740f88b2e0 - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "10.0.1" extended_image_library: @@ -206,7 +214,7 @@ packages: description: name: extended_image_library sha256: "1f9a24d3a00c2633891c6a7b5cab2807999eb2d5b597e5133b63f49d113811fe" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "5.0.1" extension: @@ -214,7 +222,7 @@ packages: description: name: extension sha256: be3a6b7f8adad2f6e2e8c63c895d19811fcf203e23466c6296267941d0ff4f24 - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "0.6.0" fake_async: @@ -222,7 +230,7 @@ packages: description: name: fake_async sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "1.3.3" ffi: @@ -230,7 +238,7 @@ packages: description: name: ffi sha256: "289279317b4b16eb2bb7e271abccd4bf84ec9bdcbe999e278a94b804f5630418" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "2.1.4" file: @@ -238,7 +246,7 @@ packages: description: name: file sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4 - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "7.0.1" file_selector_linux: @@ -246,7 +254,7 @@ packages: description: name: file_selector_linux sha256: "54cbbd957e1156d29548c7d9b9ec0c0ebb6de0a90452198683a7d23aed617a33" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "0.9.3+2" file_selector_macos: @@ -254,7 +262,7 @@ packages: description: name: file_selector_macos sha256: "19124ff4a3d8864fdc62072b6a2ef6c222d55a3404fe14893a3c02744907b60c" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "0.9.4+4" file_selector_platform_interface: @@ -262,7 +270,7 @@ packages: description: name: file_selector_platform_interface sha256: a3994c26f10378a039faa11de174d7b78eb8f79e4dd0af2a451410c1a5c3f66b - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "2.6.2" file_selector_windows: @@ -270,7 +278,7 @@ packages: description: name: file_selector_windows sha256: "320fcfb6f33caa90f0b58380489fc5ac05d99ee94b61aa96ec2bff0ba81d3c2b" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "0.9.3+4" fixnum: @@ -278,7 +286,7 @@ packages: description: name: fixnum sha256: b6dc7065e46c974bc7c5f143080a6764ec7a4be6da1285ececdc37be96de53be - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "1.1.1" flutter: @@ -286,12 +294,28 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_baidu_mapapi_base: + dependency: "direct main" + description: + name: flutter_baidu_mapapi_base + sha256: c8b372f0862690a438ec12e7978d937d775d71a5027632a149448ac4e52b1259 + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "3.9.5" + flutter_baidu_mapapi_map: + dependency: "direct main" + description: + name: flutter_baidu_mapapi_map + sha256: a4ab01a32ffb76c93bcb9b6629736064ce7f0918c58ea3b8468dcb886326d5fb + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "3.9.5" flutter_easyloading: dependency: "direct main" description: name: flutter_easyloading sha256: ba21a3c883544e582f9cc455a4a0907556714e1e9cf0eababfcb600da191d17c - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "3.0.5" flutter_html: @@ -299,7 +323,7 @@ packages: description: name: flutter_html sha256: "38a2fd702ffdf3243fb7441ab58aa1bc7e6922d95a50db76534de8260638558d" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "3.0.0" flutter_lints: @@ -307,7 +331,7 @@ packages: description: name: flutter_lints sha256: "5398f14efa795ffb7a33e9b6a08798b26a180edac4ad7db3f231e40f82ce11e1" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "5.0.0" flutter_new_badger: @@ -315,7 +339,7 @@ packages: description: name: flutter_new_badger sha256: d3742ace8009663db1ac6ba0377b092f479c35deb33e05514ba05cc0b0a5aaaa - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "1.1.1" flutter_plugin_android_lifecycle: @@ -323,7 +347,7 @@ packages: description: name: flutter_plugin_android_lifecycle sha256: "6382ce712ff69b0f719640ce957559dde459e55ecd433c767e06d139ddf16cab" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "2.0.29" flutter_spinkit: @@ -331,7 +355,7 @@ packages: description: name: flutter_spinkit sha256: "77850df57c00dc218bfe96071d576a8babec24cf58b2ed121c83cca4a2fdce7f" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "5.2.2" flutter_test: @@ -349,7 +373,7 @@ packages: description: name: fluttertoast sha256: "25e51620424d92d3db3832464774a6143b5053f15e382d8ffbfd40b6e795dcf1" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "8.2.12" geolocator: @@ -357,7 +381,7 @@ packages: description: name: geolocator sha256: f4efb8d3c4cdcad2e226af9661eb1a0dd38c71a9494b22526f9da80ab79520e5 - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "10.1.1" geolocator_android: @@ -365,7 +389,7 @@ packages: description: name: geolocator_android sha256: fcb1760a50d7500deca37c9a666785c047139b5f9ee15aa5469fae7dbbe3170d - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "4.6.2" geolocator_apple: @@ -373,7 +397,7 @@ packages: description: name: geolocator_apple sha256: dbdd8789d5aaf14cf69f74d4925ad1336b4433a6efdf2fce91e8955dc921bf22 - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "2.3.13" geolocator_platform_interface: @@ -381,7 +405,7 @@ packages: description: name: geolocator_platform_interface sha256: "30cb64f0b9adcc0fb36f628b4ebf4f731a2961a0ebd849f4b56200205056fe67" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "4.2.6" geolocator_web: @@ -389,7 +413,7 @@ packages: description: name: geolocator_web sha256: "102e7da05b48ca6bf0a5bda0010f886b171d1a08059f01bfe02addd0175ebece" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "2.2.1" geolocator_windows: @@ -397,7 +421,7 @@ packages: description: name: geolocator_windows sha256: "175435404d20278ffd220de83c2ca293b73db95eafbdc8131fe8609be1421eb6" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "0.2.5" html: @@ -405,7 +429,7 @@ packages: description: name: html sha256: "6d1264f2dffa1b1101c25a91dff0dc2daee4c18e87cd8538729773c073dbf602" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "0.15.6" http: @@ -413,7 +437,7 @@ packages: description: name: http sha256: bb2ce4590bc2667c96f318d68cac1b5a7987ec819351d32b1c987239a815e007 - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "1.5.0" http_client_helper: @@ -421,7 +445,7 @@ packages: description: name: http_client_helper sha256: "8a9127650734da86b5c73760de2b404494c968a3fd55602045ffec789dac3cb1" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "3.0.0" http_parser: @@ -429,7 +453,7 @@ packages: description: name: http_parser sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "4.1.2" image_picker: @@ -437,7 +461,7 @@ packages: description: name: image_picker sha256: "736eb56a911cf24d1859315ad09ddec0b66104bc41a7f8c5b96b4e2620cf5041" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "1.2.0" image_picker_android: @@ -445,7 +469,7 @@ packages: description: name: image_picker_android sha256: e83b2b05141469c5e19d77e1dfa11096b6b1567d09065b2265d7c6904560050c - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "0.8.13" image_picker_for_web: @@ -453,7 +477,7 @@ packages: description: name: image_picker_for_web sha256: "40c2a6a0da15556dc0f8e38a3246064a971a9f512386c3339b89f76db87269b6" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "3.1.0" image_picker_ios: @@ -461,7 +485,7 @@ packages: description: name: image_picker_ios sha256: eb06fe30bab4c4497bad449b66448f50edcc695f1c59408e78aa3a8059eb8f0e - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "0.8.13" image_picker_linux: @@ -469,7 +493,7 @@ packages: description: name: image_picker_linux sha256: "1f81c5f2046b9ab724f85523e4af65be1d47b038160a8c8deed909762c308ed4" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "0.2.2" image_picker_macos: @@ -477,7 +501,7 @@ packages: description: name: image_picker_macos sha256: d58cd9d67793d52beefd6585b12050af0a7663c0c2a6ece0fb110a35d6955e04 - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "0.2.2" image_picker_platform_interface: @@ -485,7 +509,7 @@ packages: description: name: image_picker_platform_interface sha256: "9f143b0dba3e459553209e20cc425c9801af48e6dfa4f01a0fcf927be3f41665" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "2.11.0" image_picker_windows: @@ -493,7 +517,7 @@ packages: description: name: image_picker_windows sha256: d248c86554a72b5495a31c56f060cf73a41c7ff541689327b1a7dbccc33adfae - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "0.2.2" intl: @@ -501,7 +525,7 @@ packages: description: name: intl sha256: "3df61194eb431efc39c4ceba583b95633a403f46c9fd341e550ce0bfa50e9aa5" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "0.20.2" js: @@ -509,7 +533,7 @@ packages: description: name: js sha256: "53385261521cc4a0c4658fd0ad07a7d14591cf8fc33abbceae306ddb974888dc" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "0.7.2" leak_tracker: @@ -517,7 +541,7 @@ packages: description: name: leak_tracker sha256: "6bb818ecbdffe216e81182c2f0714a2e62b593f4a4f13098713ff1685dfb6ab0" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "10.0.9" leak_tracker_flutter_testing: @@ -525,7 +549,7 @@ packages: description: name: leak_tracker_flutter_testing sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573 - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "3.0.9" leak_tracker_testing: @@ -533,7 +557,7 @@ packages: description: name: leak_tracker_testing sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "3.0.1" lints: @@ -541,7 +565,7 @@ packages: description: name: lints sha256: c35bb79562d980e9a453fc715854e1ed39e24e7d0297a880ef54e17f9874a9d7 - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "5.1.1" list_counter: @@ -549,7 +573,7 @@ packages: description: name: list_counter sha256: c447ae3dfcd1c55f0152867090e67e219d42fe6d4f2807db4bbe8b8d69912237 - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "1.0.2" matcher: @@ -557,7 +581,7 @@ packages: description: name: matcher sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2 - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "0.12.17" material_color_utilities: @@ -565,7 +589,7 @@ packages: description: name: material_color_utilities sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "0.11.1" meta: @@ -573,7 +597,7 @@ packages: description: name: meta sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "1.16.0" mime: @@ -581,7 +605,7 @@ packages: description: name: mime sha256: "41a20518f0cb1256669420fdba0cd90d21561e560ac240f26ef8322e45bb7ed6" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "2.0.0" mobile_scanner: @@ -589,7 +613,7 @@ packages: description: name: mobile_scanner sha256: "54005bdea7052d792d35b4fef0f84ec5ddc3a844b250ecd48dc192fb9b4ebc95" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "7.0.1" ndef_record: @@ -597,7 +621,7 @@ packages: description: name: ndef_record sha256: "0c72dfac0d5c16fc264846d103ee5d8249cd3858261a5a537b455a24c1bd5857" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "1.2.1" nested: @@ -605,7 +629,7 @@ packages: description: name: nested sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "1.0.0" nfc_manager: @@ -613,7 +637,7 @@ packages: description: name: nfc_manager sha256: "164cc0223dee528d4d05a542da921f0b3a31ca0312400701c93ebf4ce757f676" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "4.0.2" nfc_manager_ndef: @@ -621,7 +645,7 @@ packages: description: name: nfc_manager_ndef sha256: "676e741c42b63ab1fda5a981015cb706ab4fdb76e5d0eec6611993bb27d7e7bf" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "1.0.1" nm: @@ -629,7 +653,7 @@ packages: description: name: nm sha256: "2c9aae4127bdc8993206464fcc063611e0e36e72018696cd9631023a31b24254" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "0.5.0" package_info_plus: @@ -637,7 +661,7 @@ packages: description: name: package_info_plus sha256: "16eee997588c60225bda0488b6dcfac69280a6b7a3cf02c741895dd370a02968" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "8.3.1" package_info_plus_platform_interface: @@ -645,7 +669,7 @@ packages: description: name: package_info_plus_platform_interface sha256: "202a487f08836a592a6bd4f901ac69b3a8f146af552bbd14407b6b41e1c3f086" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "3.2.1" path: @@ -653,7 +677,7 @@ packages: description: name: path sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "1.9.1" path_provider: @@ -661,7 +685,7 @@ packages: description: name: path_provider sha256: "50c5dd5b6e1aaf6fb3a78b33f6aa3afca52bf903a8a5298f53101fdaee55bbcd" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "2.1.5" path_provider_android: @@ -669,7 +693,7 @@ packages: description: name: path_provider_android sha256: d0d310befe2c8ab9e7f393288ccbb11b60c019c6b5afc21973eeee4dda2b35e9 - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "2.2.17" path_provider_foundation: @@ -677,7 +701,7 @@ packages: description: name: path_provider_foundation sha256: "16eef174aacb07e09c351502740fa6254c165757638eba1e9116b0a781201bbd" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "2.4.2" path_provider_linux: @@ -685,7 +709,7 @@ packages: description: name: path_provider_linux sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279 - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "2.2.1" path_provider_platform_interface: @@ -693,7 +717,7 @@ packages: description: name: path_provider_platform_interface sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "2.1.2" path_provider_windows: @@ -701,7 +725,7 @@ packages: description: name: path_provider_windows sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7 - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "2.3.0" pdfx: @@ -709,7 +733,7 @@ packages: description: name: pdfx sha256: "29db9b71d46bf2335e001f91693f2c3fbbf0760e4c2eb596bf4bafab211471c1" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "2.9.2" petitparser: @@ -717,7 +741,7 @@ packages: description: name: petitparser sha256: "1a97266a94f7350d30ae522c0af07890c70b8e62c71e8e3920d1db4d23c057d1" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "7.0.1" photo_manager: @@ -725,7 +749,7 @@ packages: description: name: photo_manager sha256: a0d9a7a9bc35eda02d33766412bde6d883a8b0acb86bbe37dac5f691a0894e8a - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "3.7.1" photo_manager_image_provider: @@ -733,7 +757,7 @@ packages: description: name: photo_manager_image_provider sha256: b6015b67b32f345f57cf32c126f871bced2501236c405aafaefa885f7c821e4f - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "2.2.0" photo_view: @@ -741,7 +765,7 @@ packages: description: name: photo_view sha256: "1fc3d970a91295fbd1364296575f854c9863f225505c28c46e0a03e48960c75e" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "0.15.0" platform: @@ -749,7 +773,7 @@ packages: description: name: platform sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "3.1.6" plugin_platform_interface: @@ -757,7 +781,7 @@ packages: description: name: plugin_platform_interface sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "2.1.8" pointycastle: @@ -765,7 +789,7 @@ packages: description: name: pointycastle sha256: "4be0097fcf3fd3e8449e53730c631200ebc7b88016acecab2b0da2f0149222fe" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "3.9.1" provider: @@ -773,7 +797,7 @@ packages: description: name: provider sha256: "4abbd070a04e9ddc287673bf5a030c7ca8b685ff70218720abab8b092f53dd84" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "6.1.5" shared_preferences: @@ -781,7 +805,7 @@ packages: description: name: shared_preferences sha256: "6e8bf70b7fef813df4e9a36f658ac46d107db4b4cfe1048b477d4e453a8159f5" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "2.5.3" shared_preferences_android: @@ -789,7 +813,7 @@ packages: description: name: shared_preferences_android sha256: "5bcf0772a761b04f8c6bf814721713de6f3e5d9d89caf8d3fe031b02a342379e" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "2.4.11" shared_preferences_foundation: @@ -797,7 +821,7 @@ packages: description: name: shared_preferences_foundation sha256: "6a52cfcdaeac77cad8c97b539ff688ccfc458c007b4db12be584fbe5c0e49e03" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "2.5.4" shared_preferences_linux: @@ -805,7 +829,7 @@ packages: description: name: shared_preferences_linux sha256: "580abfd40f415611503cae30adf626e6656dfb2f0cee8f465ece7b6defb40f2f" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "2.4.1" shared_preferences_platform_interface: @@ -813,7 +837,7 @@ packages: description: name: shared_preferences_platform_interface sha256: "57cbf196c486bc2cf1f02b85784932c6094376284b3ad5779d1b1c6c6a816b80" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "2.4.1" shared_preferences_web: @@ -821,7 +845,7 @@ packages: description: name: shared_preferences_web sha256: c49bd060261c9a3f0ff445892695d6212ff603ef3115edbb448509d407600019 - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "2.4.3" shared_preferences_windows: @@ -829,7 +853,7 @@ packages: description: name: shared_preferences_windows sha256: "94ef0f72b2d71bc3e700e025db3710911bd51a71cefb65cc609dd0d9a982e3c1" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "2.4.1" simple_gesture_detector: @@ -837,7 +861,7 @@ packages: description: name: simple_gesture_detector sha256: ba2cd5af24ff20a0b8d609cec3f40e5b0744d2a71804a2616ae086b9c19d19a3 - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "0.2.1" sky_engine: @@ -850,7 +874,7 @@ packages: description: name: source_span sha256: "254ee5351d6cb365c859e20ee823c3bb479bf4a293c22d17a9f1bf144ce86f7c" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "1.10.1" sprintf: @@ -858,7 +882,7 @@ packages: description: name: sprintf sha256: "1fc9ffe69d4df602376b52949af107d8f5703b77cda567c4d7d86a0693120f23" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "7.0.0" stack_trace: @@ -866,7 +890,7 @@ packages: description: name: stack_trace sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "1.12.1" stream_channel: @@ -874,7 +898,7 @@ packages: description: name: stream_channel sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "2.1.4" stream_transform: @@ -882,7 +906,7 @@ packages: description: name: stream_transform sha256: ad47125e588cfd37a9a7f86c7d6356dde8dfe89d071d293f80ca9e9273a33871 - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "2.1.1" string_scanner: @@ -890,7 +914,7 @@ packages: description: name: string_scanner sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "1.4.1" synchronized: @@ -898,7 +922,7 @@ packages: description: name: synchronized sha256: c254ade258ec8282947a0acbbc90b9575b4f19673533ee46f2f6e9b3aeefd7c0 - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "3.4.0" table_calendar: @@ -906,7 +930,7 @@ packages: description: name: table_calendar sha256: "0c0c6219878b363a2d5f40c7afb159d845f253d061dc3c822aa0d5fe0f721982" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "3.2.0" term_glyph: @@ -914,7 +938,7 @@ packages: description: name: term_glyph sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "1.2.2" test_api: @@ -922,7 +946,7 @@ packages: description: name: test_api sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "0.7.4" typed_data: @@ -930,7 +954,7 @@ packages: description: name: typed_data sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006 - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "1.4.0" universal_platform: @@ -938,7 +962,7 @@ packages: description: name: universal_platform sha256: "64e16458a0ea9b99260ceb5467a214c1f298d647c659af1bff6d3bf82536b1ec" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "1.1.0" url_launcher: @@ -946,7 +970,7 @@ packages: description: name: url_launcher sha256: f6a7e5c4835bb4e3026a04793a4199ca2d14c739ec378fdfe23fc8075d0439f8 - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "6.3.2" url_launcher_android: @@ -954,7 +978,7 @@ packages: description: name: url_launcher_android sha256: "0aedad096a85b49df2e4725fa32118f9fa580f3b14af7a2d2221896a02cd5656" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "6.3.17" url_launcher_ios: @@ -962,7 +986,7 @@ packages: description: name: url_launcher_ios sha256: d80b3f567a617cb923546034cc94bfe44eb15f989fe670b37f26abdb9d939cb7 - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "6.3.4" url_launcher_linux: @@ -970,7 +994,7 @@ packages: description: name: url_launcher_linux sha256: "4e9ba368772369e3e08f231d2301b4ef72b9ff87c31192ef471b380ef29a4935" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "3.2.1" url_launcher_macos: @@ -978,7 +1002,7 @@ packages: description: name: url_launcher_macos sha256: c043a77d6600ac9c38300567f33ef12b0ef4f4783a2c1f00231d2b1941fea13f - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "3.2.3" url_launcher_platform_interface: @@ -986,7 +1010,7 @@ packages: description: name: url_launcher_platform_interface sha256: "552f8a1e663569be95a8190206a38187b531910283c3e982193e4f2733f01029" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "2.3.2" url_launcher_web: @@ -994,7 +1018,7 @@ packages: description: name: url_launcher_web sha256: "4bd2b7b4dc4d4d0b94e5babfffbca8eac1a126c7f3d6ecbc1a11013faa3abba2" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "2.4.1" url_launcher_windows: @@ -1002,7 +1026,7 @@ packages: description: name: url_launcher_windows sha256: "3284b6d2ac454cf34f114e1d3319866fdd1e19cdc329999057e44ffe936cfa77" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "3.1.4" uuid: @@ -1010,7 +1034,7 @@ packages: description: name: uuid sha256: a5be9ef6618a7ac1e964353ef476418026db906c4facdedaa299b7a2e71690ff - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "4.5.1" vector_math: @@ -1018,7 +1042,7 @@ packages: description: name: vector_math sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "2.1.4" video_player: @@ -1026,7 +1050,7 @@ packages: description: name: video_player sha256: "0d55b1f1a31e5ad4c4967bfaa8ade0240b07d20ee4af1dfef5f531056512961a" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "2.10.0" video_player_android: @@ -1034,7 +1058,7 @@ packages: description: name: video_player_android sha256: "53f3b57c7ac88c18e6074d0f94c7146e128c515f0a4503c3061b8e71dea3a0f2" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "2.8.12" video_player_avfoundation: @@ -1042,7 +1066,7 @@ packages: description: name: video_player_avfoundation sha256: f9a780aac57802b2892f93787e5ea53b5f43cc57dc107bee9436458365be71cd - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "2.8.4" video_player_platform_interface: @@ -1050,7 +1074,7 @@ packages: description: name: video_player_platform_interface sha256: cf2a1d29a284db648fd66cbd18aacc157f9862d77d2cc790f6f9678a46c1db5a - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "6.4.0" video_player_web: @@ -1058,7 +1082,7 @@ packages: description: name: video_player_web sha256: "9f3c00be2ef9b76a95d94ac5119fb843dca6f2c69e6c9968f6f2b6c9e7afbdeb" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "2.4.0" visibility_detector: @@ -1066,7 +1090,7 @@ packages: description: name: visibility_detector sha256: dd5cc11e13494f432d15939c3aa8ae76844c42b723398643ce9addb88a5ed420 - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "0.4.0+2" vm_service: @@ -1074,15 +1098,31 @@ packages: description: name: vm_service sha256: ddfa8d30d89985b96407efce8acbdd124701f96741f2d981ca860662f1c0dc02 - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "15.0.0" + wakelock_plus: + dependency: transitive + description: + name: wakelock_plus + sha256: a474e314c3e8fb5adef1f9ae2d247e57467ad557fa7483a2b895bc1b421c5678 + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "1.3.2" + wakelock_plus_platform_interface: + dependency: transitive + description: + name: wakelock_plus_platform_interface + sha256: e10444072e50dbc4999d7316fd303f7ea53d31c824aa5eb05d7ccbdd98985207 + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" + source: hosted + version: "1.2.3" web: dependency: transitive description: name: web sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "1.1.1" webview_flutter: @@ -1090,7 +1130,7 @@ packages: description: name: webview_flutter sha256: c3e4fe614b1c814950ad07186007eff2f2e5dd2935eba7b9a9a1af8e5885f1ba - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "4.13.0" webview_flutter_android: @@ -1098,7 +1138,7 @@ packages: description: name: webview_flutter_android sha256: "0a42444056b24ed832bdf3442d65c5194f6416f7e782152384944053c2ecc9a3" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "4.10.0" webview_flutter_platform_interface: @@ -1106,7 +1146,7 @@ packages: description: name: webview_flutter_platform_interface sha256: "63d26ee3aca7256a83ccb576a50272edd7cfc80573a4305caa98985feb493ee0" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "2.14.0" webview_flutter_wkwebview: @@ -1114,7 +1154,7 @@ packages: description: name: webview_flutter_wkwebview sha256: fb46db8216131a3e55bcf44040ca808423539bc6732e7ed34fb6d8044e3d512f - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "3.23.0" wechat_assets_picker: @@ -1122,7 +1162,7 @@ packages: description: name: wechat_assets_picker sha256: c307e50394c1e6dfcd5c4701e84efb549fce71444fedcf2e671c50d809b3e2a1 - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "9.8.0" wechat_picker_library: @@ -1130,7 +1170,7 @@ packages: description: name: wechat_picker_library sha256: "5cb61b9aa935b60da5b043f8446fbb9c5077419f20ccc4856bf444aec4f44bc1" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "1.0.7" win32: @@ -1138,7 +1178,7 @@ packages: description: name: win32 sha256: "66814138c3562338d05613a6e368ed8cfb237ad6d64a9e9334be3f309acfca03" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "5.14.0" xdg_directories: @@ -1146,7 +1186,7 @@ packages: description: name: xdg_directories sha256: "7a3f37b05d989967cdddcbb571f1ea834867ae2faa29725fd085180e0883aa15" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "1.1.0" xml: @@ -1154,7 +1194,7 @@ packages: description: name: xml sha256: "971043b3a0d3da28727e40ed3e0b5d18b742fa5a68665cca88e74b7876d5e025" - url: "https://pub.flutter-io.cn" + url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" source: hosted version: "6.6.1" sdks: diff --git a/pubspec.yaml b/pubspec.yaml index 4cf613b..1c19da8 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -79,6 +79,11 @@ dependencies: flutter_new_badger: ^1.1.1 #loading flutter_easyloading: ^3.0.5 + #视频播放器 + chewie: ^1.12.1 + #百度地图 + flutter_baidu_mapapi_base: ^3.9.5 + flutter_baidu_mapapi_map: ^3.9.5 dev_dependencies: flutter_test: