...
parent
4055de6723
commit
563d9d1dd7
|
@ -6,6 +6,11 @@
|
|||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
|
||||
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
|
||||
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
|
||||
|
||||
<!-- Android 13+ -->
|
||||
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
|
||||
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
|
||||
|
@ -69,7 +74,7 @@
|
|||
|
||||
<application
|
||||
android:label="@string/appName"
|
||||
android:name="${applicationName}"
|
||||
android:name=".MyApplication"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:usesCleartextTraffic="true"
|
||||
android:enableOnBackInvokedCallback="true">
|
||||
|
@ -87,6 +92,9 @@
|
|||
<meta-data
|
||||
android:name="io.flutter.embedding.android.NormalTheme"
|
||||
android:resource="@style/NormalTheme" />
|
||||
<meta-data
|
||||
android:name="com.baidu.lbsapi.API_KEY"
|
||||
android:value="43G1sKuHV6oRTrdR9VTIGPF9soej7V5a" />
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
package com.zhuoyun.qhdprevention.qhd_prevention
|
||||
|
||||
import android.app.Application
|
||||
import android.content.Context
|
||||
import android.util.Log
|
||||
|
||||
class MyApplication : Application() {
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
|
||||
// 通过反射调用 SDKInitializer,避免在编译期要求依赖存在
|
||||
try {
|
||||
val sdkClass = Class.forName("com.baidu.mapapi.SDKInitializer")
|
||||
// setAgreePrivacy(boolean) - 有些 SDK 要求先同意隐私
|
||||
try {
|
||||
val setAgree = sdkClass.getMethod("setAgreePrivacy", java.lang.Boolean::class.javaPrimitiveType)
|
||||
setAgree.invoke(null, true)
|
||||
Log.i("MyApplication", "SDKInitializer.setAgreePrivacy invoked via reflection")
|
||||
} catch (t: Throwable) {
|
||||
Log.w("MyApplication", "setAgreePrivacy not available or failed: ${t.message}")
|
||||
}
|
||||
|
||||
// initialize(Context)
|
||||
try {
|
||||
val initMethod = sdkClass.getMethod("initialize", Context::class.java)
|
||||
initMethod.invoke(null, this)
|
||||
Log.i("MyApplication", "SDKInitializer.initialize invoked via reflection")
|
||||
} catch (t: Throwable) {
|
||||
Log.w("MyApplication", "initialize(Context) not available or failed: ${t.message}")
|
||||
}
|
||||
} catch (e: ClassNotFoundException) {
|
||||
// 运行时没有找到该类(可能 plugin 未包含 SDK),记录日志但不崩溃
|
||||
Log.w("MyApplication", "Baidu SDKInitializer class not found at runtime: ${e.message}")
|
||||
} catch (e: Throwable) {
|
||||
Log.e("MyApplication", "Unexpected error while initializing Baidu SDK via reflection", e)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -8,6 +8,8 @@ PODS:
|
|||
- Flutter
|
||||
- connectivity_plus (0.0.1):
|
||||
- Flutter
|
||||
- device_info_plus (0.0.1):
|
||||
- Flutter
|
||||
- DKImagePickerController/Core (4.3.9):
|
||||
- DKImagePickerController/ImageDataManager
|
||||
- DKImagePickerController/Resource
|
||||
|
@ -50,6 +52,10 @@ PODS:
|
|||
- BaiduMapKit/Map (= 6.6.4)
|
||||
- Flutter
|
||||
- flutter_baidu_mapapi_base
|
||||
- flutter_baidu_mapapi_utils (3.9.0):
|
||||
- BaiduMapKit/Utils (= 6.6.4)
|
||||
- Flutter
|
||||
- flutter_baidu_mapapi_base
|
||||
- flutter_native_splash (2.4.3):
|
||||
- Flutter
|
||||
- flutter_new_badger (0.0.1):
|
||||
|
@ -66,6 +72,8 @@ PODS:
|
|||
- FlutterMacOS
|
||||
- nfc_manager (0.0.1):
|
||||
- Flutter
|
||||
- open_file_ios (0.0.1):
|
||||
- Flutter
|
||||
- package_info_plus (0.4.5):
|
||||
- Flutter
|
||||
- path_provider_foundation (0.0.1):
|
||||
|
@ -101,10 +109,12 @@ PODS:
|
|||
DEPENDENCIES:
|
||||
- camera_avfoundation (from `.symlinks/plugins/camera_avfoundation/ios`)
|
||||
- connectivity_plus (from `.symlinks/plugins/connectivity_plus/ios`)
|
||||
- device_info_plus (from `.symlinks/plugins/device_info_plus/ios`)
|
||||
- file_picker (from `.symlinks/plugins/file_picker/ios`)
|
||||
- Flutter (from `Flutter`)
|
||||
- flutter_baidu_mapapi_base (from `.symlinks/plugins/flutter_baidu_mapapi_base/ios`)
|
||||
- flutter_baidu_mapapi_map (from `.symlinks/plugins/flutter_baidu_mapapi_map/ios`)
|
||||
- flutter_baidu_mapapi_utils (from `.symlinks/plugins/flutter_baidu_mapapi_utils/ios`)
|
||||
- flutter_native_splash (from `.symlinks/plugins/flutter_native_splash/ios`)
|
||||
- flutter_new_badger (from `.symlinks/plugins/flutter_new_badger/ios`)
|
||||
- fluttertoast (from `.symlinks/plugins/fluttertoast/ios`)
|
||||
|
@ -112,6 +122,7 @@ DEPENDENCIES:
|
|||
- image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`)
|
||||
- mobile_scanner (from `.symlinks/plugins/mobile_scanner/darwin`)
|
||||
- nfc_manager (from `.symlinks/plugins/nfc_manager/ios`)
|
||||
- open_file_ios (from `.symlinks/plugins/open_file_ios/ios`)
|
||||
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
|
||||
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
|
||||
- pdfx (from `.symlinks/plugins/pdfx/ios`)
|
||||
|
@ -137,6 +148,8 @@ EXTERNAL SOURCES:
|
|||
:path: ".symlinks/plugins/camera_avfoundation/ios"
|
||||
connectivity_plus:
|
||||
:path: ".symlinks/plugins/connectivity_plus/ios"
|
||||
device_info_plus:
|
||||
:path: ".symlinks/plugins/device_info_plus/ios"
|
||||
file_picker:
|
||||
:path: ".symlinks/plugins/file_picker/ios"
|
||||
Flutter:
|
||||
|
@ -145,6 +158,8 @@ EXTERNAL SOURCES:
|
|||
:path: ".symlinks/plugins/flutter_baidu_mapapi_base/ios"
|
||||
flutter_baidu_mapapi_map:
|
||||
:path: ".symlinks/plugins/flutter_baidu_mapapi_map/ios"
|
||||
flutter_baidu_mapapi_utils:
|
||||
:path: ".symlinks/plugins/flutter_baidu_mapapi_utils/ios"
|
||||
flutter_native_splash:
|
||||
:path: ".symlinks/plugins/flutter_native_splash/ios"
|
||||
flutter_new_badger:
|
||||
|
@ -159,6 +174,8 @@ EXTERNAL SOURCES:
|
|||
:path: ".symlinks/plugins/mobile_scanner/darwin"
|
||||
nfc_manager:
|
||||
:path: ".symlinks/plugins/nfc_manager/ios"
|
||||
open_file_ios:
|
||||
:path: ".symlinks/plugins/open_file_ios/ios"
|
||||
package_info_plus:
|
||||
:path: ".symlinks/plugins/package_info_plus/ios"
|
||||
path_provider_foundation:
|
||||
|
@ -186,12 +203,14 @@ SPEC CHECKSUMS:
|
|||
BaiduMapKit: 84991811cb07b24c6ead7d59022c13245427782c
|
||||
camera_avfoundation: be3be85408cd4126f250386828e9b1dfa40ab436
|
||||
connectivity_plus: cb623214f4e1f6ef8fe7403d580fdad517d2f7dd
|
||||
device_info_plus: 21fcca2080fbcd348be798aa36c3e5ed849eefbe
|
||||
DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c
|
||||
DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60
|
||||
file_picker: a0560bc09d61de87f12d246fc47d2119e6ef37be
|
||||
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
|
||||
flutter_baidu_mapapi_base: 24dd82034374c6f52a73e90316834c63ff8d4f64
|
||||
flutter_baidu_mapapi_map: f799cc1bb3d39196b8d3d59399ca8635e690bd44
|
||||
flutter_baidu_mapapi_utils: 0c69394243d51e97f521f396e150aaaf31e84e29
|
||||
flutter_native_splash: c32d145d68aeda5502d5f543ee38c192065986cf
|
||||
flutter_new_badger: 133aaf93e9a5542bf905c8483d8b83c5ef4946ea
|
||||
fluttertoast: 2c67e14dce98bbdb200df9e1acf610d7a6264ea1
|
||||
|
@ -199,6 +218,7 @@ SPEC CHECKSUMS:
|
|||
image_picker_ios: 7fe1ff8e34c1790d6fff70a32484959f563a928a
|
||||
mobile_scanner: 9157936403f5a0644ca3779a38ff8404c5434a93
|
||||
nfc_manager: f6d5609c09b4640b914a3dc67479a2e392965fd0
|
||||
open_file_ios: 5ff7526df64e4394b4fe207636b67a95e83078bb
|
||||
package_info_plus: af8e2ca6888548050f16fa2f1938db7b5a5df499
|
||||
path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564
|
||||
pdfx: 77f4dddc48361fbb01486fa2bdee4532cbb97ef3
|
||||
|
|
|
@ -20,6 +20,10 @@
|
|||
<string>$(FLUTTER_BUILD_NAME)</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>LSApplicationQueriesSchemes</key>
|
||||
<array>
|
||||
<string>baidumap</string>
|
||||
</array>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>$(FLUTTER_BUILD_NUMBER)</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
|
|
|
@ -46,7 +46,7 @@ class ListItemFactory {
|
|||
Flexible(
|
||||
fit: FlexFit.loose,
|
||||
child: Text(
|
||||
_truncateText(rightText,17) ,
|
||||
_truncateText(rightText,20) ,
|
||||
style: TextStyle(fontSize: 13, color: Colors.grey),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
|
@ -280,7 +280,7 @@ class ListItemFactory {
|
|||
bottom: verticalPadding,
|
||||
),
|
||||
child: Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 10),
|
||||
padding: EdgeInsets.symmetric(horizontal: 10, vertical: isEdit ? 0 : verticalPadding),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(5),
|
||||
|
@ -418,8 +418,10 @@ class ListItemFactory {
|
|||
if (isRequired) Text('* ', style: TextStyle(color: Colors.red)),
|
||||
Text(
|
||||
title,
|
||||
maxLines: 5,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: const TextStyle(fontSize: 13, fontWeight: FontWeight.bold),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
|
|
|
@ -1028,28 +1028,32 @@ U6Hzm1ninpWeE+awIDAQAB
|
|||
|
||||
/// 安全措施个项保存
|
||||
static Future<Map<String, dynamic>> saveDangerousOptionsFile(
|
||||
List<String> filePaths,
|
||||
) async {
|
||||
// 复制一份 formData
|
||||
List signImgList,
|
||||
) async {
|
||||
final Map<String, dynamic> data = {
|
||||
"CORPINFO_ID": SessionService.instance.corpinfoId,
|
||||
};
|
||||
// 把文件路径填成 MultipartFile
|
||||
for (var i = 0; i < filePaths.length; i++) {
|
||||
final path = filePaths[i];
|
||||
if (path.contains('uploadFiles')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 根据 signImgList 的索引生成 file0, file1 ...
|
||||
for (var i = 0; i < signImgList.length; i++) {
|
||||
final path = signImgList[i];
|
||||
if (path == null || path.isEmpty) continue;
|
||||
if (path.contains('uploadFiles')) continue; // 已上传,跳过
|
||||
|
||||
final filename = path.split(Platform.pathSeparator).last;
|
||||
data['file$i'] = await MultipartFile.fromFile(
|
||||
path,
|
||||
filename: path.split(Platform.pathSeparator).last,
|
||||
filename: filename,
|
||||
);
|
||||
}
|
||||
return HttpManager().uploadFaceImage(
|
||||
|
||||
final resp = await HttpManager().uploadFaceImage(
|
||||
baseUrl: basePath,
|
||||
path: '/app/eightwork/saveDangerousOptionsFile',
|
||||
fromData: data,
|
||||
);
|
||||
|
||||
return resp;
|
||||
}
|
||||
|
||||
/// 受限空间台账信息
|
||||
|
@ -1283,7 +1287,6 @@ U6Hzm1ninpWeE+awIDAQAB
|
|||
static Future<Map<String, dynamic>> safeKeyprojectCheckSubmit(Map data) {
|
||||
return HttpManager().request(
|
||||
basePath,
|
||||
// 'http://192.168.0.45:28199',
|
||||
'/app/keyprojectcheck/add',
|
||||
method: Method.post,
|
||||
data: {...data},
|
||||
|
@ -1574,7 +1577,8 @@ U6Hzm1ninpWeE+awIDAQAB
|
|||
// 安全检查隐患指派
|
||||
static Future<Map<String, dynamic>> safeCheckDangerConfirm(Map data) {
|
||||
return HttpManager().request(
|
||||
basePath,
|
||||
// basePath,
|
||||
'http://192.168.0.45:28199',
|
||||
'/app/hidden/confirm',
|
||||
method: Method.post,
|
||||
data: {
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
// main.dart
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_localizations/flutter_localizations.dart';
|
||||
import 'package:qhd_prevention/pages/badge_manager.dart';
|
||||
import 'package:qhd_prevention/services/auth_service.dart';
|
||||
import 'package:qhd_prevention/tools/tools.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import './pages/login_page.dart';
|
||||
import './pages/main_tab.dart';
|
||||
|
@ -12,6 +11,9 @@ import 'package:intl/date_symbol_data_local.dart';
|
|||
import 'http/HttpManager.dart';
|
||||
import 'package:flutter_easyloading/flutter_easyloading.dart';
|
||||
import 'package:flutter/services.dart'; // for TextInput.hide
|
||||
import 'package:flutter_baidu_mapapi_base/flutter_baidu_mapapi_base.dart'
|
||||
show BMFMapSDK, BMF_COORD_TYPE;
|
||||
import 'package:flutter_baidu_mapapi_map/flutter_baidu_mapapi_map.dart';
|
||||
|
||||
// 全局导航键
|
||||
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
|
||||
|
@ -69,6 +71,20 @@ Future<T?> showModalBottomSheetAfterUnfocus<T>({
|
|||
|
||||
void main() async {
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
// 1) 同意 SDK 隐私(百度 SDK 要求)
|
||||
BMFMapSDK.setAgreePrivacy(true);
|
||||
|
||||
// 2) 初始化鉴权 / 坐标类型
|
||||
if (Platform.isIOS) {
|
||||
// iOS 可以通过接口直接设置 AK
|
||||
BMFMapSDK.setApiKeyAndCoordType('g3lZyqt0KkFnZGUsjIVO7U6lTCfpjSCt', BMF_COORD_TYPE.BD09LL);
|
||||
} else if (Platform.isAndroid) {
|
||||
// Android 插件示例:Android 的 AK 通过 Manifest 配置
|
||||
BMFMapSDK.setApiKeyAndCoordType('43G1sKuHV6oRTrdR9VTIGPF9soej7V5a', BMF_COORD_TYPE.BD09LL);
|
||||
await BMFAndroidVersion.initAndroidVersion(); // 可选,插件示例中有
|
||||
}
|
||||
|
||||
await SystemChrome.setPreferredOrientations([
|
||||
DeviceOrientation.portraitUp,
|
||||
DeviceOrientation.portraitDown,
|
||||
|
|
|
@ -37,10 +37,12 @@ class _DangerManagerDetailPageState extends State<DangerManagerDetailPage> {
|
|||
}
|
||||
|
||||
Future<void> _getData() async {
|
||||
LoadingDialogHelper.show();
|
||||
final result = await ApiService.getKeyprojectDangerFindHidden(
|
||||
widget.info['HIDDEN_ID'] ?? '',
|
||||
widget.info['OUTSOURCED_ID'] ?? '',
|
||||
);
|
||||
LoadingDialogHelper.hide();
|
||||
try {
|
||||
setState(() {
|
||||
hiddenForm = result['pd'] ?? {};
|
||||
|
|
|
@ -116,7 +116,7 @@ class _KeyprojectDetailState extends State<KeyprojectDetail> {
|
|||
label: '计划工期:',
|
||||
isEditable: false,
|
||||
text:
|
||||
'${info['STARTTIME'] ?? ''}至${info['ENDTIME'] ?? ''}',
|
||||
'${FormUtils.hasValue(info, 'STARTTIME') ? info['STARTTIME'] : ''}至${FormUtils.hasValue(info, 'ENDTIME') ? info['ENDTIME'] : ''}',
|
||||
),
|
||||
const Divider(),
|
||||
ItemListWidget.singleLineTitleText(
|
||||
|
|
|
@ -5,26 +5,15 @@ import 'package:qhd_prevention/customWidget/picker/CupertinoDatePicker.dart';
|
|||
import 'package:qhd_prevention/customWidget/toast_util.dart';
|
||||
import 'package:qhd_prevention/pages/home/tap/item_list_widget.dart';
|
||||
|
||||
/// punlish_modal.dart
|
||||
/// 把你提供的 uniapp 弹窗翻译为 Flutter 版本。
|
||||
/// 提供:
|
||||
/// - 可复用的 PunishModal Widget
|
||||
/// - showPunishDialog 辅助函数
|
||||
/// - 一个最小的 main() 示例展示如何调用
|
||||
/// punish_modal.dart
|
||||
/// 动态高度:isp == false 时较矮,isp == true 时较高;切换时带动画,并兼容键盘弹出。
|
||||
|
||||
class PunishModal extends StatefulWidget {
|
||||
/// 初始数据(可选),key 与原 uniapp 对应:
|
||||
/// "ISPUNISH" : '1' 或 '2'
|
||||
/// "REASON"
|
||||
/// "AMOUT"
|
||||
/// "RECTIFICATIONDEPT_NAME"
|
||||
/// "RECTIFICATIONOR_NAME"
|
||||
/// "DATE" (字符串)
|
||||
final Map<String, String>? initial;
|
||||
final void Function(Map<String, String> form) onSubmit;
|
||||
|
||||
const PunishModal({Key? key, this.initial, required this.onSubmit})
|
||||
: super(key: key);
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
_PunishModalState createState() => _PunishModalState();
|
||||
|
@ -44,26 +33,15 @@ class _PunishModalState extends State<PunishModal> {
|
|||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
reasonController = TextEditingController(
|
||||
text: widget.initial?['REASON'] ?? '',
|
||||
);
|
||||
amountController = TextEditingController(
|
||||
text: widget.initial?['AMOUT'] ?? '',
|
||||
);
|
||||
deptController = TextEditingController(
|
||||
text: widget.initial?['RECTIFICATIONDEPT_NAME'] ?? '',
|
||||
);
|
||||
personController = TextEditingController(
|
||||
text: widget.initial?['RECTIFICATIONOR_NAME'] ?? '',
|
||||
);
|
||||
reasonController = TextEditingController(text: widget.initial?['REASON'] ?? '');
|
||||
amountController = TextEditingController(text: widget.initial?['AMOUT'] ?? '');
|
||||
deptController = TextEditingController(text: widget.initial?['RECTIFICATIONDEPT_NAME'] ?? '');
|
||||
personController = TextEditingController(text: widget.initial?['RECTIFICATIONOR_NAME'] ?? '');
|
||||
dateText = widget.initial?['DATE'];
|
||||
isp = widget.initial?['ISPUNISH'] == '1' ? true : false;
|
||||
isp = widget.initial?['ISPUNISH'] == '1';
|
||||
|
||||
// 相当于 @blur=\"checkNumber\",监听焦点失去时做检查
|
||||
_amountFocus.addListener(() {
|
||||
if (!_amountFocus.hasFocus) {
|
||||
_checkNumber();
|
||||
}
|
||||
if (!_amountFocus.hasFocus) _checkNumber();
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -80,14 +58,11 @@ class _PunishModalState extends State<PunishModal> {
|
|||
void _checkNumber() {
|
||||
final text = amountController.text.trim();
|
||||
if (text.isEmpty) return;
|
||||
// 允许整数或两位小数
|
||||
final reg = RegExp(r"^\d+(?:\.\d{1,2})?$");
|
||||
if (!reg.hasMatch(text)) {
|
||||
// 显示错误提示,并做简单修正(可按需改变)
|
||||
ScaffoldMessenger.of(
|
||||
context,
|
||||
).showSnackBar(const SnackBar(content: Text('请输入有效的金额(最多两位小数)')));
|
||||
// 尝试提取数字部分
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(content: Text('请输入有效的金额(最多两位小数)')),
|
||||
);
|
||||
final match = RegExp(r"\d+(?:\.\d{1,2})?").firstMatch(text);
|
||||
if (match != null) {
|
||||
amountController.text = match.group(0)!;
|
||||
|
@ -107,7 +82,7 @@ class _PunishModalState extends State<PunishModal> {
|
|||
ToastUtil.showNormal(context, '请填写处罚金额');
|
||||
return;
|
||||
}
|
||||
if (dateText?.length == 0) {
|
||||
if (dateText?.isEmpty ?? true) {
|
||||
ToastUtil.showNormal(context, '请选择下发处罚时间');
|
||||
return;
|
||||
}
|
||||
|
@ -128,204 +103,185 @@ class _PunishModalState extends State<PunishModal> {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// 我们改为根据内容自动伸缩,但当内容过高时仍然限制最大高度并可滚动。
|
||||
final maxBodyHeight = MediaQuery.of(context).size.height * 0.6; // 可按需调整
|
||||
// 注意:showPunishDialog 会限制外层 maxHeight(可被键盘缩小)
|
||||
// 在这里我们读取父级给定的最大高度,并基于 isp 决定目标高度百分比
|
||||
return LayoutBuilder(builder: (context, constraints) {
|
||||
// constraints.maxHeight 是外部 ConstrainedBox(showPunishDialog)给的 availableHeight
|
||||
final double availableMaxHeight = constraints.maxHeight.isFinite ? constraints.maxHeight : MediaQuery.of(context).size.height * 0.8;
|
||||
final double maxWidth = constraints.maxWidth.isFinite ? constraints.maxWidth : MediaQuery.of(context).size.width * 0.9;
|
||||
|
||||
return Material(
|
||||
color: Colors.transparent,
|
||||
child: Center(
|
||||
child: Container(
|
||||
width: MediaQuery.of(context).size.width * 0.9,
|
||||
// 不再强制固定高度,使用 Column 的 min size,让弹窗高度随内容变化
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
// Header
|
||||
Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 12,
|
||||
vertical: 10,
|
||||
),
|
||||
decoration: const BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.vertical(top: Radius.circular(8)),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
const Expanded(
|
||||
child: Text(
|
||||
'处罚',
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
),
|
||||
IconButton(
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
icon: const Icon(Icons.close, color: Colors.red),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
// 比例配置:若想微调大小请改这里
|
||||
const double expandedRatio = 0.75; // isp == true 时占 availableMaxHeight 的比例
|
||||
const double collapsedRatio = 0.3; // isp == false 时占 availableMaxHeight 的比例
|
||||
|
||||
// Body (表单)
|
||||
// 使用 ConstrainedBox 限制最大高度,内部使用 SingleChildScrollView,这样当字段少时弹窗高度自动变小,字段多时会出现滚动。
|
||||
ConstrainedBox(
|
||||
constraints: BoxConstraints(maxHeight: maxBodyHeight),
|
||||
child: SingleChildScrollView(
|
||||
padding: const EdgeInsets.all(12),
|
||||
child: Form(
|
||||
key: _formKey,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
final double targetHeight = isp
|
||||
? (availableMaxHeight * expandedRatio).clamp(260.0, availableMaxHeight)
|
||||
: (availableMaxHeight * collapsedRatio).clamp(180.0, availableMaxHeight);
|
||||
|
||||
// AnimatedContainer 用于在 isp 切换时平滑过渡高度
|
||||
return Center(
|
||||
child: AnimatedContainer(
|
||||
duration: const Duration(milliseconds: 250),
|
||||
curve: Curves.easeInOut,
|
||||
width: maxWidth,
|
||||
height: targetHeight,
|
||||
child: Material(
|
||||
color: Colors.transparent,
|
||||
child: Container(
|
||||
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(8)),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
// Header
|
||||
Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10),
|
||||
decoration: const BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.vertical(top: Radius.circular(8)),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
// 是否进行罚款
|
||||
ListItemFactory.createYesNoSection(
|
||||
title: '是否进行罚款',
|
||||
horizontalPadding: 0,
|
||||
groupValue: isp,
|
||||
onChanged: (v) => setState(() => isp = v),
|
||||
),
|
||||
|
||||
const SizedBox(height: 8),
|
||||
|
||||
// 以下内容仅在 isp == '1' 时显示
|
||||
if (isp) ...[
|
||||
ItemListWidget.singleLineTitleText(
|
||||
label: '处罚原因',
|
||||
isEditable: true,
|
||||
controller: reasonController,
|
||||
hintText: '请输入处罚原因',
|
||||
),
|
||||
const Divider(),
|
||||
ItemListWidget.singleLineTitleText(
|
||||
label: '处罚金额(元)',
|
||||
isEditable: true,
|
||||
keyboardType: const TextInputType.numberWithOptions(
|
||||
decimal: true,
|
||||
),
|
||||
controller: amountController,
|
||||
hintText: '请输入处罚金额',
|
||||
),
|
||||
const Divider(),
|
||||
ItemListWidget.singleLineTitleText(
|
||||
label: '被处罚单位',
|
||||
isEditable: false,
|
||||
text:
|
||||
widget.initial?['RECTIFICATIONDEPT_NAME'] ?? '',
|
||||
),
|
||||
const Divider(),
|
||||
ItemListWidget.singleLineTitleText(
|
||||
label: '被处罚人',
|
||||
isEditable: false,
|
||||
text: widget.initial?['RECTIFICATIONOR_NAME'] ?? '',
|
||||
),
|
||||
const Divider(),
|
||||
ItemListWidget.selectableLineTitleTextRightButton(
|
||||
label: '下发处罚时间',
|
||||
isEditable: true,
|
||||
text: '',
|
||||
onTap: () async {
|
||||
DateTime? picked =
|
||||
await BottomDateTimePicker.showDate(
|
||||
context,
|
||||
);
|
||||
if (picked != null) {
|
||||
setState(() {
|
||||
dateText =
|
||||
DateFormat(
|
||||
'yyyy-MM-dd HH:mm',
|
||||
).format(picked);
|
||||
});
|
||||
}
|
||||
},
|
||||
),
|
||||
|
||||
],
|
||||
const SizedBox(height: 12),
|
||||
const Expanded(child: Text('处罚', style: TextStyle(fontSize: 18, fontWeight: FontWeight.w600))),
|
||||
IconButton(onPressed: () => Navigator.of(context).pop(), icon: const Icon(Icons.close, color: Colors.red)),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
// Footer 按钮
|
||||
Container(
|
||||
padding: const EdgeInsets.all(8),
|
||||
decoration: const BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.vertical(
|
||||
bottom: Radius.circular(8),
|
||||
// 中间内容:使用 Expanded + SingleChildScrollView 保证在高度受限时可以滚动
|
||||
Expanded(
|
||||
child: SingleChildScrollView(
|
||||
padding: const EdgeInsets.all(12),
|
||||
child: Form(
|
||||
key: _formKey,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
// 是否进行罚款(切换 isp 时会触发 setState,进而调整 AnimatedContainer 高度)
|
||||
ListItemFactory.createYesNoSection(
|
||||
title: '是否进行罚款',
|
||||
horizontalPadding: 0,
|
||||
groupValue: isp,
|
||||
onChanged: (v) => setState(() => isp = v),
|
||||
),
|
||||
|
||||
const SizedBox(height: 8),
|
||||
|
||||
if (isp) ...[
|
||||
ItemListWidget.singleLineTitleText(
|
||||
label: '处罚原因',
|
||||
isEditable: true,
|
||||
controller: reasonController,
|
||||
hintText: '请输入处罚原因',
|
||||
),
|
||||
const Divider(),
|
||||
ItemListWidget.singleLineTitleText(
|
||||
label: '处罚金额(元)',
|
||||
isEditable: true,
|
||||
keyboardType: const TextInputType.numberWithOptions(decimal: true),
|
||||
controller: amountController,
|
||||
hintText: '请输入处罚金额',
|
||||
),
|
||||
const Divider(),
|
||||
ItemListWidget.singleLineTitleText(
|
||||
label: '被处罚单位',
|
||||
isEditable: false,
|
||||
text: widget.initial?['RECTIFICATIONDEPT_NAME'] ?? '',
|
||||
),
|
||||
const Divider(),
|
||||
ItemListWidget.singleLineTitleText(
|
||||
label: '被处罚人',
|
||||
isEditable: false,
|
||||
text: widget.initial?['RECTIFICATIONOR_NAME'] ?? '',
|
||||
),
|
||||
const Divider(),
|
||||
ItemListWidget.selectableLineTitleTextRightButton(
|
||||
label: '下发处罚时间',
|
||||
isEditable: true,
|
||||
text: dateText ?? '',
|
||||
onTap: () async {
|
||||
DateTime? picked = await BottomDateTimePicker.showDate(context);
|
||||
if (picked != null) {
|
||||
setState(() {
|
||||
dateText = DateFormat('yyyy-MM-dd HH:mm').format(picked);
|
||||
});
|
||||
}
|
||||
},
|
||||
),
|
||||
] else ...[
|
||||
// isp == false 时,你或许希望显示少量提示或空白占位,这里留空
|
||||
const SizedBox(height: 6),
|
||||
],
|
||||
|
||||
const SizedBox(height: 12),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: OutlinedButton(
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
child: const Text('关闭'),
|
||||
),
|
||||
|
||||
// Footer 固定(不随内容滚动)
|
||||
Container(
|
||||
padding: const EdgeInsets.all(8),
|
||||
decoration: const BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.vertical(bottom: Radius.circular(8)),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Expanded(
|
||||
child: ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
foregroundColor: Colors.green,
|
||||
backgroundColor: Colors.white,
|
||||
side: const BorderSide(color: Colors.green),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(child: OutlinedButton(onPressed: () => Navigator.of(context).pop(), child: const Text('关闭'))),
|
||||
const SizedBox(width: 8),
|
||||
Expanded(
|
||||
child: ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
foregroundColor: Colors.green,
|
||||
backgroundColor: Colors.white,
|
||||
side: const BorderSide(color: Colors.green),
|
||||
),
|
||||
onPressed: _onConfirm,
|
||||
child: const Text('确认', style: TextStyle(color: Colors.green)),
|
||||
),
|
||||
),
|
||||
onPressed: _onConfirm,
|
||||
child: const Text(
|
||||
'确认',
|
||||
style: TextStyle(color: Colors.green),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
Widget _buildLabel(String text) => Padding(
|
||||
padding: const EdgeInsets.only(bottom: 6),
|
||||
child: Text(text, style: const TextStyle(fontWeight: FontWeight.w600)),
|
||||
);
|
||||
}
|
||||
|
||||
/// 显示showPunishDialog
|
||||
/// showPunishDialog:外层仅限制 maxHeight(受键盘影响)
|
||||
Future<void> showPunishDialog(
|
||||
BuildContext context, {
|
||||
Map<String, String>? initial,
|
||||
required void Function(Map<String, String>) onSubmit,
|
||||
}) {
|
||||
BuildContext context, {
|
||||
Map<String, String>? initial,
|
||||
required void Function(Map<String, String>) onSubmit,
|
||||
}) {
|
||||
final mq = MediaQuery.of(context);
|
||||
final viewInsets = mq.viewInsets; // 键盘高度
|
||||
// availableHeight = 屏高 - 键盘高度 - 外围 padding
|
||||
final double availableHeight = mq.size.height - viewInsets.vertical - 32.0;
|
||||
final double maxWidth = mq.size.width * 0.9;
|
||||
|
||||
return showDialog<void>(
|
||||
context: context,
|
||||
barrierDismissible: false,
|
||||
builder: (context) {
|
||||
final viewInsets = MediaQuery.of(context).viewInsets;
|
||||
return AnimatedPadding(
|
||||
padding: viewInsets + const EdgeInsets.all(16),
|
||||
duration: const Duration(milliseconds: 200),
|
||||
curve: Curves.decelerate,
|
||||
child: Align(
|
||||
alignment: Alignment.center,
|
||||
child: Material(
|
||||
color: Colors.transparent,
|
||||
child: Container(
|
||||
// 保持原来 Dialog 的圆角和背景
|
||||
decoration: BoxDecoration(borderRadius: BorderRadius.circular(8)),
|
||||
child: PunishModal(initial: initial, onSubmit: onSubmit),
|
||||
child: SafeArea(
|
||||
child: Center(
|
||||
child: ConstrainedBox(
|
||||
constraints: BoxConstraints(maxHeight: availableHeight, maxWidth: maxWidth),
|
||||
child: Material(
|
||||
color: Colors.transparent,
|
||||
child: PunishModal(initial: initial, onSubmit: onSubmit),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
|
@ -97,7 +97,7 @@ class _PunishmentListPageState extends State<PunishmentListPage> {
|
|||
}
|
||||
|
||||
Widget _buildListItem(Map<String, dynamic> item) {
|
||||
bool showBadge = item['cfcount'] > 0;
|
||||
int showBadge = item['cfcount'];
|
||||
return Card(
|
||||
color: Colors.white,
|
||||
margin: const EdgeInsets.all(8.0),
|
||||
|
@ -122,7 +122,7 @@ class _PunishmentListPageState extends State<PunishmentListPage> {
|
|||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
if (showBadge)
|
||||
if (showBadge > 0)
|
||||
Container(
|
||||
margin: const EdgeInsets.only(left: 8.0),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
|
@ -135,9 +135,9 @@ class _PunishmentListPageState extends State<PunishmentListPage> {
|
|||
color: const Color(0xFFdd514c),
|
||||
borderRadius: BorderRadius.circular(96),
|
||||
),
|
||||
child: const Text(
|
||||
'1',
|
||||
style: TextStyle(color: Colors.white, fontSize: 10),
|
||||
child: Text(
|
||||
'$showBadge',
|
||||
style: const TextStyle(color: Colors.white, fontSize: 10),
|
||||
),
|
||||
),
|
||||
],
|
||||
|
|
|
@ -99,8 +99,8 @@ class _PunishmentManagerPageState extends State<PunishmentManagerPage>
|
|||
context,
|
||||
initial: {
|
||||
'ISPUNISH': '2',
|
||||
'RECTIFICATIONDEPT_NAME': item['UNITS_NAME'],
|
||||
'RECTIFICATIONOR_NAME': item['RECTIFICATIONOR_NAME'],
|
||||
'RECTIFICATIONDEPT_NAME': item['UNITS_NAME'] ?? '',
|
||||
'RECTIFICATIONOR_NAME': item['RECTIFICATIONOR_NAME'] ?? '',
|
||||
},
|
||||
onSubmit: (form) {
|
||||
// 这里接收用户确认后的表单数据
|
||||
|
|
|
@ -59,6 +59,7 @@ class _SafeDrawerPageState extends State<SafeDrawerPage> {
|
|||
_isEdit = widget.editType != SafeEditType.see;
|
||||
_initHiddenForm();
|
||||
_loadHazardLevels();
|
||||
_getUnitPerson();
|
||||
}
|
||||
|
||||
void _initHiddenForm() {
|
||||
|
@ -325,23 +326,28 @@ class _SafeDrawerPageState extends State<SafeDrawerPage> {
|
|||
),
|
||||
] else ...[
|
||||
// limited rectify: department, person, date
|
||||
GestureDetector(
|
||||
onTap: _isEdit ? _pickDept : null,
|
||||
child: _section(
|
||||
ListItemFactory.createRowSpaceBetweenItem(
|
||||
leftText: '整改部门',
|
||||
rightText:
|
||||
_isEdit
|
||||
? (hiddenForm['RECTIFICATIONDEPT_NAME']
|
||||
?.toString() ??
|
||||
'请选择')
|
||||
: hiddenForm['RECTIFICATIONDEPT_NAME']
|
||||
?.toString() ??
|
||||
'',
|
||||
isRight: _isEdit,
|
||||
),
|
||||
),
|
||||
),
|
||||
// GestureDetector(
|
||||
// onTap: _isEdit ? _pickDept : null,
|
||||
// child: _section(
|
||||
// ListItemFactory.createRowSpaceBetweenItem(
|
||||
// leftText: '整改部门',
|
||||
// rightText:
|
||||
// _isEdit
|
||||
// ? (hiddenForm['RECTIFICATIONDEPT_NAME']
|
||||
// ?.toString() ??
|
||||
// '请选择')
|
||||
// : hiddenForm['RECTIFICATIONDEPT_NAME']
|
||||
// ?.toString() ??
|
||||
// '',
|
||||
// isRight: _isEdit,
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
ItemListWidget.itemContainer(horizontal: 15,ListItemFactory.createRowSpaceBetweenItem(
|
||||
leftText: '整改部门',
|
||||
rightText:hiddenForm['RECTIFICATIONDEPT_NAME'] ?? '',
|
||||
isRight: false,
|
||||
),),
|
||||
const SizedBox(height: 10),
|
||||
GestureDetector(
|
||||
onTap: _isEdit ? _pickResponsible : null,
|
||||
|
@ -471,31 +477,31 @@ class _SafeDrawerPageState extends State<SafeDrawerPage> {
|
|||
);
|
||||
}
|
||||
|
||||
Future<void> _pickDept() async {
|
||||
final choice = await BottomPicker.show<String>(
|
||||
context,
|
||||
items:
|
||||
widget.toCheckUnitList
|
||||
.map((val) => val['UNITS_NAME'] as String)
|
||||
.toList(),
|
||||
itemBuilder: (item) => Text(item, textAlign: TextAlign.center),
|
||||
initialIndex: 0,
|
||||
);
|
||||
if (choice != null) {
|
||||
// 用户点击确定并选择了 choice
|
||||
setState(() {
|
||||
hiddenForm['RECTIFICATIONDEPT_NAME'] = choice;
|
||||
Map target = widget.toCheckUnitList.firstWhere(
|
||||
(item) => item['UNITS_NAME'] == choice,
|
||||
orElse: () => {},
|
||||
);
|
||||
hiddenForm['RECTIFICATIONDEPT'] = target?['UNITS_ID'] ?? '';
|
||||
_getUnitPerson();
|
||||
|
||||
//FocusHelper.clearFocus(context);
|
||||
});
|
||||
}
|
||||
}
|
||||
// Future<void> _pickDept() async {
|
||||
// final choice = await BottomPicker.show<String>(
|
||||
// context,
|
||||
// items:
|
||||
// widget.toCheckUnitList
|
||||
// .map((val) => val['UNITS_NAME'] as String)
|
||||
// .toList(),
|
||||
// itemBuilder: (item) => Text(item, textAlign: TextAlign.center),
|
||||
// initialIndex: 0,
|
||||
// );
|
||||
// if (choice != null) {
|
||||
// // 用户点击确定并选择了 choice
|
||||
// setState(() {
|
||||
// hiddenForm['RECTIFICATIONDEPT_NAME'] = choice;
|
||||
// Map target = widget.toCheckUnitList.firstWhere(
|
||||
// (item) => item['UNITS_NAME'] == choice,
|
||||
// orElse: () => {},
|
||||
// );
|
||||
// hiddenForm['RECTIFICATIONDEPT'] = target?['UNITS_ID'] ?? '';
|
||||
// _getUnitPerson();
|
||||
//
|
||||
// //FocusHelper.clearFocus(context);
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
|
||||
Future<void> _getUnitPerson() async {
|
||||
final res = await ApiService.getSafeCheckPersonList(
|
||||
|
|
|
@ -246,6 +246,7 @@ class _SafecheckDetailState extends State<SafecheckDetail> {
|
|||
toCheckUnitList.isNotEmpty) {
|
||||
form['UNITS_ID'] = toCheckUnitList.first['UNITS_ID'];
|
||||
}
|
||||
|
||||
});
|
||||
} catch (e) {
|
||||
print('加载 toCheckUnitList 失败: $e');
|
||||
|
@ -751,9 +752,17 @@ class _SafecheckDetailState extends State<SafecheckDetail> {
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Map _getCheckUnit() {
|
||||
for (Map item in toCheckUnitList) {
|
||||
if (item['UNITS_ID'] == form['UNITS_ID']) {
|
||||
return item;
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Map checkUnitData = _getCheckUnit();
|
||||
return Scaffold(
|
||||
appBar: MyAppbar(title: "安全检查发起", actions: []),
|
||||
|
||||
|
@ -938,7 +947,10 @@ class _SafecheckDetailState extends State<SafecheckDetail> {
|
|||
backgroundColor: Colors.blue,
|
||||
onPressed: () {
|
||||
_openDrawer(
|
||||
{},
|
||||
{'RECTIFICATIONDEPT': checkUnitData['UNITS_ID'] ?? '',
|
||||
'RECTIFICATIONDEPT_NAME': form['UNITS_NAME'] ?? '',
|
||||
'RECTIFICATIONOR':form['PERSONNELMANAGEMENT_ID'],
|
||||
'RECTIFICATIONOR_NAME': form['PERSON_NAME']},
|
||||
-1,
|
||||
); // 添加括号和 await
|
||||
//FocusHelper.clearFocus(context);
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
// check_record_detail_page.dart
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_baidu_mapapi_base/flutter_baidu_mapapi_base.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';
|
||||
|
@ -16,7 +17,11 @@ import 'package:qhd_prevention/pages/app/hidden_record_detail_page.dart';
|
|||
import 'package:qhd_prevention/pages/my_appbar.dart';
|
||||
import 'package:qhd_prevention/services/location_service.dart';
|
||||
import 'package:qhd_prevention/tools/tools.dart';
|
||||
import 'package:webview_flutter/webview_flutter.dart';
|
||||
import 'dart:ui' as ui;
|
||||
import 'package:flutter/services.dart' show rootBundle;
|
||||
|
||||
// Baidu Map plugin
|
||||
import 'package:flutter_baidu_mapapi_map/flutter_baidu_mapapi_map.dart';
|
||||
|
||||
class CheckRecordDetailPage extends StatefulWidget {
|
||||
const CheckRecordDetailPage(this.id, this.type, {super.key});
|
||||
|
@ -29,11 +34,13 @@ class CheckRecordDetailPage extends StatefulWidget {
|
|||
}
|
||||
|
||||
class _CheckRecordDetailPageState extends State<CheckRecordDetailPage> {
|
||||
// map markers
|
||||
// map markers data (来自后端)
|
||||
List<Map<String, dynamic>> covers = [];
|
||||
double centerLat = 39.8883;
|
||||
double centerLng = 119.519;
|
||||
WebViewController? _controller;
|
||||
|
||||
// Baidu map controller
|
||||
BMFMapController? _mapController;
|
||||
|
||||
Map<String, dynamic> pd = {
|
||||
"LIST_NAME": "",
|
||||
|
@ -59,18 +66,18 @@ class _CheckRecordDetailPageState extends State<CheckRecordDetailPage> {
|
|||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
// 先初始化 webview controller,使其尽早准备好
|
||||
_initLocation();
|
||||
// 启动时并行请求,UI 使用 setState 更新
|
||||
// 并行请求(包含地图数据)
|
||||
_fetchAll();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_controller = null;
|
||||
// 若需要销毁 map controller,按插件要求执行(通常不需要手动释放)
|
||||
_mapController = null;
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
Future<void> _fetchAll() async {
|
||||
// 并行发请求,界面加载更快
|
||||
await Future.wait([
|
||||
_getInspectRecordsDetail(),
|
||||
_getInspectRecordsDetailTwo(),
|
||||
|
@ -92,6 +99,7 @@ class _CheckRecordDetailPageState extends State<CheckRecordDetailPage> {
|
|||
} else {
|
||||
resData = await ApiService.getNormalRecordMapInfo(data);
|
||||
}
|
||||
|
||||
final built = buildCoversFromRes(resData);
|
||||
double lat = centerLat;
|
||||
double lng = centerLng;
|
||||
|
@ -114,13 +122,11 @@ class _CheckRecordDetailPageState extends State<CheckRecordDetailPage> {
|
|||
centerLng = lng;
|
||||
_loadingMap = false;
|
||||
});
|
||||
// 确保 controller 已初始化并注入最新参数,触发地图刷新
|
||||
if (_controller == null) {
|
||||
// 如果 controller 还没创建,先创建
|
||||
await _initLocation();
|
||||
} else {
|
||||
// controller 已存在,直接注入参数(页面若尚未完成加载,onPageFinished 会再次注入)
|
||||
await _injectLocationParams();
|
||||
|
||||
// 如果 map 已创建,则刷新中心并添加 markers
|
||||
if (_mapController != null) {
|
||||
_moveToCenter();
|
||||
await _updateMarkers();
|
||||
}
|
||||
} catch (e, st) {
|
||||
debugPrint('getMapData error: $e\n$st');
|
||||
|
@ -128,102 +134,9 @@ class _CheckRecordDetailPageState extends State<CheckRecordDetailPage> {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
Future<void> _initLocation() async {
|
||||
try {
|
||||
// 如果已经有 controller,直接返回(避免重复创建)
|
||||
if (_controller != null) return;
|
||||
|
||||
// 创建 controller 并 setState 以触发重建,使 BaiduMapWebView 能拿到 controller
|
||||
setState(() {
|
||||
_controller = WebViewController()
|
||||
..setJavaScriptMode(JavaScriptMode.unrestricted)
|
||||
..addJavaScriptChannel('JS', onMessageReceived: (JavaScriptMessage message) {
|
||||
debugPrint('JS LOG: ${message.message}');
|
||||
})
|
||||
..setNavigationDelegate(
|
||||
NavigationDelegate(
|
||||
onPageFinished: (String url) async {
|
||||
debugPrint('网页加载完成: $url');
|
||||
// 页面加载完成后把最新的位置参数注入进去
|
||||
await _injectLocationParams();
|
||||
},
|
||||
onWebResourceError: (err) {
|
||||
debugPrint('Web resource error: ${err.description}');
|
||||
},
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
// 延迟一点再加载页面以确保 setState 已生效(非必需,但更稳健)
|
||||
await Future.delayed(const Duration(milliseconds: 50));
|
||||
|
||||
try {
|
||||
await _controller!.loadRequest(Uri.parse('http://47.92.102.56:7811/file/fluteightmap/index.html'));
|
||||
} catch (e, st) {
|
||||
debugPrint('loadRequest 错误: $e\n$st');
|
||||
}
|
||||
} catch (e, st) {
|
||||
debugPrint('_initLocation error: $e\n$st');
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _injectLocationParams() async {
|
||||
if (_controller == null) {
|
||||
debugPrint('_injectLocationParams: controller 为空,跳过注入');
|
||||
return;
|
||||
}
|
||||
|
||||
// 构造参数,确保使用当前最新 centerLat/centerLng
|
||||
final params = {
|
||||
'longitude': centerLng,
|
||||
'latitude': centerLat,
|
||||
'GSON': covers, // 你原来用空数组,这里把 covers 也注入给地图(可选)
|
||||
't': DateTime.now().millisecondsSinceEpoch,
|
||||
};
|
||||
|
||||
final jsonParams = jsonEncode(params);
|
||||
|
||||
try {
|
||||
await _controller!.runJavaScript('''
|
||||
(function(){
|
||||
try {
|
||||
if (typeof window.initWithData === 'function') {
|
||||
window.initWithData($jsonParams);
|
||||
} else if (typeof window.initMap === 'function') {
|
||||
window.initMap($jsonParams);
|
||||
} else {
|
||||
console.error('initWithData / initMap function not found');
|
||||
}
|
||||
} catch(e) {
|
||||
console.error('call initWithData error', e);
|
||||
}
|
||||
})();
|
||||
''');
|
||||
debugPrint('已注入地图初始化参数: $jsonParams');
|
||||
} catch (e, st) {
|
||||
debugPrint('注入位置参数失败: $e\n$st');
|
||||
// 如果注入失败且页面尚未加载,等待并重试一次(防止 race)
|
||||
await Future.delayed(const Duration(milliseconds: 200));
|
||||
try {
|
||||
if (_controller != null) {
|
||||
await _controller!.runJavaScript('''
|
||||
(function(){
|
||||
try {
|
||||
if (typeof window.initWithData === 'function') {
|
||||
window.initWithData($jsonParams);
|
||||
} else if (typeof window.initMap === 'function') {
|
||||
window.initMap($jsonParams);
|
||||
}
|
||||
} catch(e) {}
|
||||
})();
|
||||
''');
|
||||
}
|
||||
} catch (_) {}
|
||||
}
|
||||
}
|
||||
List<Map<String, dynamic>> buildCoversFromRes(Map res) {
|
||||
final list = <Map<String, dynamic>>[];
|
||||
const String defaultIconAsset = 'assets/map/50.png';
|
||||
|
||||
final cinfo = res['cinfo'];
|
||||
if (cinfo != null &&
|
||||
|
@ -237,7 +150,7 @@ class _CheckRecordDetailPageState extends State<CheckRecordDetailPage> {
|
|||
list.add({
|
||||
'latitude': lat,
|
||||
'longitude': lng,
|
||||
'icon': '', // 可替换为网络图片或 data uri
|
||||
'icon': defaultIconAsset,
|
||||
'data': {'type': 'cinfo'}
|
||||
});
|
||||
}
|
||||
|
@ -255,7 +168,7 @@ class _CheckRecordDetailPageState extends State<CheckRecordDetailPage> {
|
|||
list.add({
|
||||
'latitude': lat,
|
||||
'longitude': lng,
|
||||
'icon': '',
|
||||
'icon': defaultIconAsset,
|
||||
'data': {'type': 'checkrecord'}
|
||||
});
|
||||
}
|
||||
|
@ -275,7 +188,7 @@ class _CheckRecordDetailPageState extends State<CheckRecordDetailPage> {
|
|||
list.add({
|
||||
'latitude': lat,
|
||||
'longitude': lng,
|
||||
'icon': '',
|
||||
'icon': defaultIconAsset,
|
||||
'data': {'type': 'varList', 'item': item}
|
||||
});
|
||||
}
|
||||
|
@ -288,6 +201,184 @@ class _CheckRecordDetailPageState extends State<CheckRecordDetailPage> {
|
|||
return list;
|
||||
}
|
||||
|
||||
// 当 map 创建完成后会回调这里
|
||||
void _onBmfMapCreated(BMFMapController controller) async {
|
||||
_mapController = controller;
|
||||
// set center
|
||||
await _moveToCenter();
|
||||
// 若 covers 已有数据,则添加 markers
|
||||
await _updateMarkers();
|
||||
}
|
||||
|
||||
Future<void> _moveToCenter() async {
|
||||
if (_mapController == null) return;
|
||||
try {
|
||||
final coord = BMFCoordinate(centerLat, centerLng);
|
||||
try {
|
||||
await _mapController!.setCenterCoordinate(coord, true);
|
||||
} catch (_) {
|
||||
// 如果某个版本的方法名不同,使用 updateMapOptions 作为备选:
|
||||
try {
|
||||
await _mapController!.updateMapOptions(BMFMapOptions(
|
||||
center: coord,
|
||||
));
|
||||
} catch (_) {}
|
||||
}
|
||||
} catch (e) {
|
||||
debugPrint('moveToCenter error: $e');
|
||||
}
|
||||
}
|
||||
|
||||
// helper: load image bytes from asset and optionally resize to targetWidth
|
||||
Future<Uint8List?> _loadMarkerBytes(String assetPath, {int targetWidth = 64}) async {
|
||||
try {
|
||||
final ByteData data = await rootBundle.load(assetPath);
|
||||
final raw = data.buffer.asUint8List();
|
||||
debugPrint('_loadMarkerBytes: raw bytes length=${raw.length} for $assetPath');
|
||||
|
||||
// 尝试 decode + 缩放成 PNG bytes(提高兼容性)
|
||||
try {
|
||||
final codec = await ui.instantiateImageCodec(raw, targetWidth: targetWidth);
|
||||
final frame = await codec.getNextFrame();
|
||||
final bd = await frame.image.toByteData(format: ui.ImageByteFormat.png);
|
||||
final bytes = bd?.buffer.asUint8List();
|
||||
debugPrint('_loadMarkerBytes: decoded & resized bytes length=${bytes?.length}');
|
||||
return bytes ?? raw;
|
||||
} catch (e) {
|
||||
debugPrint('_loadMarkerBytes: instantiateImageCodec failed, fallback to raw: $e');
|
||||
return raw;
|
||||
}
|
||||
} catch (e, st) {
|
||||
debugPrint('_loadMarkerBytes: failed to load asset "$assetPath": $e\n$st');
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _updateMarkers() async {
|
||||
if (_mapController == null) {
|
||||
debugPrint('_updateMarkers: mapController is null');
|
||||
return;
|
||||
}
|
||||
|
||||
debugPrint('_updateMarkers: start, covers.length=${covers.length}');
|
||||
|
||||
// 先尝试使用 typed 调用清除已有 markers(优先 cleanAllMarkers)
|
||||
try {
|
||||
try {
|
||||
final res = await _mapController!.cleanAllMarkers();
|
||||
debugPrint('_updateMarkers: cleanAllMarkers result=$res');
|
||||
} catch (e) {
|
||||
debugPrint('_updateMarkers: cleanAllMarkers not available or failed: $e');
|
||||
}
|
||||
} catch (e) {
|
||||
debugPrint('_updateMarkers: _tryClear typed outer error: $e');
|
||||
}
|
||||
|
||||
// asset path
|
||||
const String defaultIconAsset = 'assets/map/50.png';
|
||||
|
||||
// 1) 尝试读取 asset bytes(并缩放到 targetWidth)
|
||||
Uint8List? markerBytes = await _loadMarkerBytes(defaultIconAsset, targetWidth: 64);
|
||||
if (markerBytes == null) {
|
||||
debugPrint('_updateMarkers: markerBytes is null after trying to load asset.');
|
||||
// 可以继续用 icon path 回退(如果插件支持)
|
||||
}
|
||||
|
||||
// 构造 marker 列表
|
||||
final List<BMFMarker> markers = [];
|
||||
for (var i = 0; i < covers.length; i++) {
|
||||
final item = covers[i];
|
||||
final lat = (item['latitude'] is double) ? item['latitude'] as double : double.tryParse(item['latitude'].toString());
|
||||
final lng = (item['longitude'] is double) ? item['longitude'] as double : double.tryParse(item['longitude'].toString());
|
||||
if (lat == null || lng == null) {
|
||||
debugPrint('_updateMarkers: skip invalid coord at index $i -> lat=$lat, lng=$lng');
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
if (markerBytes != null) {
|
||||
// 优先:iconData(更兼容)
|
||||
final marker = BMFMarker.iconData(
|
||||
position: BMFCoordinate(lat, lng),
|
||||
title: item['data'] != null ? jsonEncode(item['data']) : '',
|
||||
identifier: 'm_$i',
|
||||
iconData: markerBytes,
|
||||
);
|
||||
markers.add(marker);
|
||||
} else {
|
||||
// 退回:使用 asset 路径(某些版本可能也支持)
|
||||
final marker = BMFMarker.icon(
|
||||
position: BMFCoordinate(lat, lng),
|
||||
title: item['data'] != null ? jsonEncode(item['data']) : '',
|
||||
identifier: 'm_$i',
|
||||
icon: defaultIconAsset,
|
||||
);
|
||||
markers.add(marker);
|
||||
}
|
||||
} catch (e, st) {
|
||||
debugPrint('_updateMarkers: create marker failed at index $i: $e\n$st');
|
||||
// 继续下一个,不中断
|
||||
}
|
||||
}
|
||||
|
||||
debugPrint('_updateMarkers: prepared ${markers.length} markers');
|
||||
|
||||
// 2) 添加 markers(优先批量 addMarkers;若无此方法或失败则逐个 addMarker 回退)
|
||||
bool added = false;
|
||||
try {
|
||||
try {
|
||||
final res = await _mapController!.addMarkers(markers);
|
||||
debugPrint('_updateMarkers: addMarkers result=$res');
|
||||
if (res == true) added = true;
|
||||
} catch (e) {
|
||||
debugPrint('_updateMarkers: addMarkers not available or failed: $e');
|
||||
}
|
||||
|
||||
if (!added) {
|
||||
for (var i = 0; i < markers.length; i++) {
|
||||
try {
|
||||
final res = await _mapController!.addMarker(markers[i]);
|
||||
debugPrint('_updateMarkers: addMarker index $i result=$res');
|
||||
// 不把失败当作终止条件
|
||||
} catch (e) {
|
||||
debugPrint('_updateMarkers: addMarker index $i exception: $e');
|
||||
}
|
||||
}
|
||||
added = true; // 我们已经尝试过逐个添加(即使某些添加失败)
|
||||
}
|
||||
} catch (e, st) {
|
||||
debugPrint('_updateMarkers: add markers typed call failed: $e\n$st');
|
||||
}
|
||||
|
||||
// 3) 诊断:如果标点数量>0,打印第一个并尝试移动中心(避免点在视野外)
|
||||
if (covers.isNotEmpty) {
|
||||
final first = covers.first;
|
||||
debugPrint('_updateMarkers: first cover sample -> ${first.toString()}');
|
||||
// 强制把视角移动到第一个点(确保可见)
|
||||
try {
|
||||
final fl = (first['latitude'] is double) ? first['latitude'] as double : double.tryParse(first['latitude'].toString());
|
||||
final fn = (first['longitude'] is double) ? first['longitude'] as double : double.tryParse(first['longitude'].toString());
|
||||
if (fl != null && fn != null) {
|
||||
// tiny delay 确保 markers 已被渲染/添加
|
||||
await Future.delayed(const Duration(milliseconds: 200));
|
||||
try {
|
||||
await _mapController!.setCenterCoordinate(BMFCoordinate(fl, fn), true);
|
||||
debugPrint('_updateMarkers: moved center to first marker');
|
||||
} catch (_) {
|
||||
try {
|
||||
await _mapController!.updateMapOptions(BMFMapOptions(center: BMFCoordinate(fl, fn)));
|
||||
debugPrint('_updateMarkers: updateMapOptions center to first marker');
|
||||
} catch (_) {}
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
debugPrint('_updateMarkers: failed to move center: $e');
|
||||
}
|
||||
}
|
||||
|
||||
debugPrint('_updateMarkers: finished');
|
||||
}
|
||||
|
||||
Future<void> _getInspectRecordsDetail() async {
|
||||
setState(() => _loadingDetail = true);
|
||||
try {
|
||||
|
@ -350,7 +441,6 @@ class _CheckRecordDetailPageState extends State<CheckRecordDetailPage> {
|
|||
}
|
||||
}
|
||||
|
||||
// UI 构建
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
|
@ -363,7 +453,7 @@ class _CheckRecordDetailPageState extends State<CheckRecordDetailPage> {
|
|||
_buildCheckContentTable(),
|
||||
_buildSectionTitle("其他隐患信息"),
|
||||
_buildOtherHiddenTable(),
|
||||
_buildMapSection(), // 注意这里地图高度已固定
|
||||
_buildMapSection(), // 已改为原生百度地图
|
||||
_buildSectionTitle("清单信息"),
|
||||
_buildInfoList(),
|
||||
_buildSignPhotos(),
|
||||
|
@ -397,7 +487,6 @@ class _CheckRecordDetailPageState extends State<CheckRecordDetailPage> {
|
|||
_buildTableHeaderCell("检查内容"),
|
||||
_buildTableHeaderCell("状态"),
|
||||
]),
|
||||
// 若 varList 为空,显示空行或提示
|
||||
if (varList.isEmpty)
|
||||
TableRow(children: [
|
||||
Padding(padding: EdgeInsets.all(12), child: Text("暂无检查内容")),
|
||||
|
@ -417,7 +506,6 @@ class _CheckRecordDetailPageState extends State<CheckRecordDetailPage> {
|
|||
}
|
||||
|
||||
Widget _buildStatusCell(Map<String, dynamic> item) {
|
||||
// 兼容字符串/数字类型
|
||||
final isnormalStr = item["ISNORMAL"]?.toString() ?? '';
|
||||
final imgCount = int.tryParse(item["IMGCOUNT"]?.toString() ?? '') ?? 0;
|
||||
|
||||
|
@ -488,7 +576,6 @@ class _CheckRecordDetailPageState extends State<CheckRecordDetailPage> {
|
|||
}
|
||||
|
||||
Widget _buildMapSection() {
|
||||
// 给 webview 一个固定高度(与 uniapp 的 300px 对齐)
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 10),
|
||||
child: Container(
|
||||
|
@ -496,12 +583,14 @@ class _CheckRecordDetailPageState extends State<CheckRecordDetailPage> {
|
|||
decoration: BoxDecoration(borderRadius: BorderRadius.circular(4), border: Border.all(color: Colors.grey[300]!)),
|
||||
child: _loadingMap
|
||||
? Center(child: CircularProgressIndicator())
|
||||
: BaiduMapWebView(
|
||||
controller: _controller,
|
||||
isLoading: _loadingMap,
|
||||
errorMessage: null,
|
||||
onRetry: _initLocation,
|
||||
)
|
||||
: BMFMapWidget(
|
||||
onBMFMapCreated: (controller) => _onBmfMapCreated(controller),
|
||||
mapOptions: BMFMapOptions(
|
||||
center: BMFCoordinate(centerLat, centerLng),
|
||||
zoomLevel: 14,
|
||||
// 可根据需要配置更多选项,例如 logo 位置、地图类型等
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -55,9 +55,11 @@ class _CheckPersonDetailState extends State<CheckPersonDetail> {
|
|||
|
||||
Future<void> _getData() async {
|
||||
try {
|
||||
LoadingDialogHelper.show();
|
||||
final result = await ApiService.getSafeCheckStartGoEdit(
|
||||
widget.INSPECTION_ID,
|
||||
);
|
||||
LoadingDialogHelper.hide();
|
||||
// 在 await 之后检查 mounted,避免页面已经被 pop 导致 setState 报错
|
||||
if (!mounted) return;
|
||||
setState(() {
|
||||
|
|
|
@ -222,7 +222,6 @@ class _OtherPromisePageState extends State<OtherPromisePage> {
|
|||
Widget _buildFooter() {
|
||||
final type = (info['TYPE'] ?? '').toString();
|
||||
final signImagePath = (info['FILEPATH'] ?? '').toString();
|
||||
final signTime = (info['SIGNTIME'] ?? '').toString();
|
||||
final creatTime = (info['CREATTIME'] ?? '').toString();
|
||||
|
||||
Widget signPreview;
|
||||
|
@ -295,17 +294,6 @@ class _OtherPromisePageState extends State<OtherPromisePage> {
|
|||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
const SizedBox(),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
children: [Text(signTime.isNotEmpty ? _formatDateShort(signTime) : '')],
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
|
|
@ -26,7 +26,7 @@ class _SafetyCommitmentPageState extends State<SafetyCommitmentPage> {
|
|||
child: Column(
|
||||
children: [
|
||||
ItemListWidget.selectableLineTitleTextRightButton(
|
||||
label: '危化行业安全承诺:',
|
||||
label: '危化行业安全承诺',
|
||||
isEditable: true,
|
||||
isRequired: false,
|
||||
onTap: () {
|
||||
|
@ -36,7 +36,7 @@ class _SafetyCommitmentPageState extends State<SafetyCommitmentPage> {
|
|||
),
|
||||
const Divider(),
|
||||
ItemListWidget.selectableLineTitleTextRightButton(
|
||||
label: '其他行业安全承诺:',
|
||||
label: '其他行业安全承诺',
|
||||
isEditable: true,
|
||||
isRequired: false,
|
||||
onTap: () {
|
||||
|
|
|
@ -103,7 +103,7 @@ class _StrengthenStudyPageState extends State<StrengthenStudyPage> {
|
|||
pushPage(
|
||||
RemoteFilePage(
|
||||
fileUrl: ApiService.baseImgPath + row['VIDEOFILES'],
|
||||
countdownSeconds: 10,
|
||||
countdownSeconds: 30,
|
||||
),
|
||||
context,
|
||||
);
|
||||
|
|
|
@ -78,7 +78,9 @@ class _StudyDetailPageState extends State<StudyDetailPage>
|
|||
void dispose() {
|
||||
_tabController.dispose();
|
||||
WakelockPlus.disable();
|
||||
|
||||
SystemChrome.setPreferredOrientations([
|
||||
DeviceOrientation.portraitUp,
|
||||
]);
|
||||
// 让未完成的提交完成(非阻塞)
|
||||
if (_ongoingSubmit != null) {
|
||||
_ongoingSubmit!.whenComplete(() {});
|
||||
|
@ -213,7 +215,7 @@ class _StudyDetailPageState extends State<StudyDetailPage>
|
|||
await pushPage(
|
||||
RemoteFilePage(
|
||||
fileUrl: ApiService.baseImgPath + data['VIDEOFILES'],
|
||||
countdownSeconds: 10,
|
||||
countdownSeconds: 30,
|
||||
),
|
||||
context,
|
||||
);
|
||||
|
@ -597,7 +599,7 @@ class _StudyDetailPageState extends State<StudyDetailPage>
|
|||
await SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
|
||||
}
|
||||
|
||||
/// 恢复允许横竖(你可以按需修改恢复策略)
|
||||
/// 恢复允许横竖
|
||||
Future<void> _restoreDefaultOrientations() async {
|
||||
await SystemChrome.setPreferredOrientations([
|
||||
DeviceOrientation.portraitUp,
|
||||
|
|
|
@ -679,8 +679,8 @@ class ItemListWidget {
|
|||
imgPath.isNotEmpty
|
||||
? Image.network(
|
||||
'${ApiService.baseImgPath}${imgPath}',
|
||||
width: 50,
|
||||
height: 50,
|
||||
width: 80,
|
||||
height: 80,
|
||||
)
|
||||
: SizedBox(),
|
||||
),
|
||||
|
|
|
@ -24,12 +24,12 @@ class ImageData {
|
|||
class SignImageData {
|
||||
String SIGNER_TIME;
|
||||
String? filePath;
|
||||
int? key = 0;
|
||||
int? key;
|
||||
|
||||
SignImageData({
|
||||
required this.SIGNER_TIME,
|
||||
required this.filePath,
|
||||
required this.key,
|
||||
this.filePath,
|
||||
this.key,
|
||||
});
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
|
@ -38,18 +38,17 @@ class SignImageData {
|
|||
'key': key,
|
||||
};
|
||||
|
||||
factory SignImageData.fromJson(Map<String, dynamic> json) {
|
||||
factory SignImageData.fromJson(Map<String, dynamic> m) {
|
||||
return SignImageData(
|
||||
SIGNER_TIME: json['SIGNER_TIME'] as String,
|
||||
filePath: json['filePath'] as String?,
|
||||
key:
|
||||
json['key'] is int
|
||||
? json['key'] as int
|
||||
: int.tryParse(json['key']?.toString() ?? ''),
|
||||
SIGNER_TIME: m['SIGNER_TIME'] ?? '',
|
||||
filePath: m['filePath'],
|
||||
key: m['key'] != null ? int.tryParse(m['key'].toString()) : null,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() => 'SignImageData(key:$key, filePath:$filePath, SIGNER_TIME:$SIGNER_TIME)';
|
||||
}
|
||||
class DangerousOptionsPage extends StatefulWidget {
|
||||
final int index;
|
||||
final int status;
|
||||
|
@ -94,7 +93,9 @@ class _DangerousOptionsPageState extends State<DangerousOptionsPage> {
|
|||
/// 拍照或选图后的回调
|
||||
Future<void> _onImageAdded(String localPath) async {
|
||||
// 上传到服务器
|
||||
LoadingDialogHelper.show();
|
||||
final res = await ApiService.uploadSaveFile(localPath);
|
||||
LoadingDialogHelper.hide();
|
||||
final url = res['FILE_PATH'] as String;
|
||||
setState(() {
|
||||
imgList.add(ImageData(localPath: localPath, serverPath: url));
|
||||
|
|
|
@ -60,7 +60,9 @@ class _HotworkAqjdDetailState extends State<HotworkAqjdDetail> {
|
|||
/// 拍照或选图后的回调
|
||||
Future<void> _onImageAdded(String localPath) async {
|
||||
// 上传到服务器
|
||||
LoadingDialogHelper.show();
|
||||
final res = await ApiService.uploadSaveFile(localPath);
|
||||
LoadingDialogHelper.hide();
|
||||
final url = res['FILE_PATH'] as String;
|
||||
setState(() {
|
||||
imgList.add(ImageData(localPath: localPath, serverPath: url));
|
||||
|
|
|
@ -498,10 +498,8 @@ class _HotworkApplyDetailState extends State<HotworkApplyDetail> {
|
|||
// 如果不是二级,或者SAFETY_USER_ID有值就加上 AUDIT
|
||||
if (pd['WORK_LEVEL'] != '二级' || FormUtils.hasValue(pd, 'SAFETY_USER_ID'))
|
||||
EditUserType.AUDIT,
|
||||
EditUserType.AUDIT,
|
||||
// 如果既不是二级也不是一级,就加上 APPROVE
|
||||
if (pd['WORK_LEVEL'] == '特级') EditUserType.APPROVE,
|
||||
|
||||
EditUserType.MONITOR,
|
||||
EditUserType.WORK_START,
|
||||
EditUserType.WORK_END,
|
||||
|
@ -638,11 +636,7 @@ class _HotworkApplyDetailState extends State<HotworkApplyDetail> {
|
|||
_relatedController.text = pd['SPECIAL_WORK'] ?? '';
|
||||
_riskController.text = pd['RISK_IDENTIFICATION'] ?? '';
|
||||
});
|
||||
// final data = await ApiService.getHomeworkFindById('hotwork', widget.HOTWORK_ID);
|
||||
// setState(() {
|
||||
// pd = data['pd'];
|
||||
// });
|
||||
// LoadingDialogHelper.hide();
|
||||
|
||||
}
|
||||
Future<void> _getSigns(String homework_id) async {
|
||||
final data = await ApiService.listSignFinished(
|
||||
|
@ -692,8 +686,6 @@ class _HotworkApplyDetailState extends State<HotworkApplyDetail> {
|
|||
onContractorHandle: _chooseUnitManager,
|
||||
onWorkAreaHandle: _getWorkArea,
|
||||
onWorkAreaLocationHandle: _showLocationHandle,
|
||||
|
||||
|
||||
onAnalyzeTap: () {
|
||||
pushPage(
|
||||
HotworkGasList(HOTWORK_ID: widget.HOTWORK_ID),
|
||||
|
|
|
@ -113,7 +113,7 @@ class _HotWorkListPageState extends State<HotWorkListPage> {
|
|||
};
|
||||
final url = '/app/hotwork/list?showCount=-1¤tPage=$currentPage';
|
||||
final response = await ApiService.specialCheckListWorkCount(data, url);
|
||||
|
||||
LoadingDialogHelper.hide();
|
||||
setState(() {
|
||||
if (currentPage == 1) {
|
||||
list = response['varList'];
|
||||
|
@ -286,6 +286,7 @@ class _HotWorkListPageState extends State<HotWorkListPage> {
|
|||
default:
|
||||
break;
|
||||
}
|
||||
LoadingDialogHelper.show();
|
||||
setState(() {
|
||||
_fetchSteps();
|
||||
_fetchData();
|
||||
|
|
|
@ -336,6 +336,7 @@ class _HotworkJszyDetailState extends State<HotworkJszyDetail> {
|
|||
onTap: () async {
|
||||
DateTime? picked = await BottomDateTimePicker.showDate(
|
||||
mode: BottomPickerMode.dateTimeWithSeconds,
|
||||
minTimeStr: pd['WORK_START_DATE'],
|
||||
context,
|
||||
);
|
||||
if (picked != null) {
|
||||
|
|
|
@ -194,7 +194,7 @@ class _HotworkSzdwDetailState extends State<HotworkSzdwDetail> {
|
|||
/// 初始化拉取数据
|
||||
Future<void> _getData() async {
|
||||
final data = await ApiService.getHomeworkFindById(
|
||||
'highwork',
|
||||
'hotwork',
|
||||
widget.HOTWORK_ID,
|
||||
);
|
||||
setState(() {
|
||||
|
|
|
@ -67,7 +67,9 @@ class _HotworkYsgdDetailState extends State<HotworkYsgdDetail> {
|
|||
/// 拍照或选图后的回调
|
||||
Future<void> _onImageAdded(String localPath) async {
|
||||
// 上传到服务器
|
||||
LoadingDialogHelper.show();
|
||||
final res = await ApiService.uploadSaveFile(localPath);
|
||||
LoadingDialogHelper.hide();
|
||||
final url = res['FILE_PATH'] as String;
|
||||
setState(() {
|
||||
imgList.add(ImageData(localPath: localPath, serverPath: url));
|
||||
|
|
|
@ -59,7 +59,9 @@ class _CutroadAqjdDetailState extends State<CutroadAqjdDetail> {
|
|||
/// 拍照或选图后的回调
|
||||
Future<void> _onImageAdded(String localPath) async {
|
||||
// 上传到服务器
|
||||
LoadingDialogHelper.show();
|
||||
final res = await ApiService.uploadSaveFile(localPath);
|
||||
LoadingDialogHelper.hide();
|
||||
final url = res['FILE_PATH'] as String;
|
||||
setState(() {
|
||||
imgList.add(ImageData(localPath: localPath, serverPath: url));
|
||||
|
|
|
@ -308,6 +308,7 @@ class _CutroadJszyDetailState extends State<CutroadJszyDetail> {
|
|||
onTap: () async {
|
||||
DateTime? picked = await BottomDateTimePicker.showDate(
|
||||
mode: BottomPickerMode.dateTimeWithSeconds,
|
||||
minTimeStr: pd['WORK_START_DATE'],
|
||||
context,
|
||||
);
|
||||
|
||||
|
|
|
@ -66,7 +66,9 @@ class _CutroadYsgdDetailState extends State<CutroadYsgdDetail> {
|
|||
/// 拍照或选图后的回调
|
||||
Future<void> _onImageAdded(String localPath) async {
|
||||
// 上传到服务器
|
||||
LoadingDialogHelper.show();
|
||||
final res = await ApiService.uploadSaveFile(localPath);
|
||||
LoadingDialogHelper.hide();
|
||||
final url = res['FILE_PATH'] as String;
|
||||
setState(() {
|
||||
imgList.add(ImageData(localPath: localPath, serverPath: url));
|
||||
|
|
|
@ -242,7 +242,9 @@ setState(() {
|
|||
/// 拍照或选图后的回调
|
||||
Future<void> _onImageAdded(String localPath) async {
|
||||
// 上传到服务器
|
||||
LoadingDialogHelper.show();
|
||||
final res = await ApiService.uploadSaveFile(localPath);
|
||||
LoadingDialogHelper.hide();
|
||||
final url = res['FILE_PATH'] as String;
|
||||
setState(() {
|
||||
imgList.add(ImageData(localPath: localPath, serverPath: url));
|
||||
|
|
|
@ -52,11 +52,11 @@ class SpecialWorkFormBaseWork extends StatelessWidget {
|
|||
}
|
||||
|
||||
Widget signItemWidget(
|
||||
String signKey,
|
||||
String nameKey,
|
||||
String name,
|
||||
BuildContext context,
|
||||
) {
|
||||
String signKey,
|
||||
String nameKey,
|
||||
String name,
|
||||
BuildContext context,
|
||||
) {
|
||||
return _itemContainer(
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
|
@ -67,13 +67,16 @@ class SpecialWorkFormBaseWork extends StatelessWidget {
|
|||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(name, style: TextStyle(fontSize: 15, fontWeight: FontWeight.bold),),
|
||||
child: Text(
|
||||
name,
|
||||
style: TextStyle(fontSize: 13, fontWeight: FontWeight.bold),
|
||||
),
|
||||
),
|
||||
SizedBox(width: 10,),
|
||||
SizedBox(width: 10),
|
||||
if (FormUtils.hasValue(pd, nameKey))
|
||||
Text(
|
||||
pd[nameKey]?.toString() ?? '',
|
||||
style: const TextStyle(fontSize: 16),
|
||||
style: const TextStyle(fontSize: 13),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
@ -84,134 +87,162 @@ class SpecialWorkFormBaseWork extends StatelessWidget {
|
|||
...((signs[signKey] as List<dynamic>)
|
||||
.cast<Map<String, dynamic>>()
|
||||
.map((item) {
|
||||
// 解析 SIGN_PATH
|
||||
List<String> signPaths = [];
|
||||
final rawSP = FormUtils.hasValue(item, 'SIGN_PATH') ? item['SIGN_PATH'] : null;
|
||||
if (rawSP is String && rawSP.isNotEmpty) {
|
||||
signPaths = rawSP.split(',').map((s) => s.trim()).toList();
|
||||
} else if (rawSP is List) {
|
||||
signPaths = rawSP.cast<String>();
|
||||
}
|
||||
// 解析 SIGN_PATH
|
||||
List<String> signPaths = [];
|
||||
final rawSP =
|
||||
FormUtils.hasValue(item, 'SIGN_PATH')
|
||||
? item['SIGN_PATH']
|
||||
: null;
|
||||
if (rawSP is String && rawSP.isNotEmpty) {
|
||||
signPaths = rawSP.split(',').map((s) => s.trim()).toList();
|
||||
} else if (rawSP is List) {
|
||||
signPaths = rawSP.cast<String>();
|
||||
}
|
||||
|
||||
// 解析 SIGN_TIME 保留空格
|
||||
List<String> signTimes = [];
|
||||
final rawST = FormUtils.hasValue(item, 'SIGN_TIME') ? item['SIGN_TIME'] : null;
|
||||
if (rawST is String && rawST.isNotEmpty) {
|
||||
signTimes = rawST.split(',');
|
||||
} else if (rawST is List) {
|
||||
signTimes = rawST.cast<String>();
|
||||
}
|
||||
// 解析 SIGN_TIME 保留空格
|
||||
List<String> signTimes = [];
|
||||
final rawST =
|
||||
FormUtils.hasValue(item, 'SIGN_TIME')
|
||||
? item['SIGN_TIME']
|
||||
: null;
|
||||
if (rawST is String && rawST.isNotEmpty) {
|
||||
signTimes = rawST.split(',');
|
||||
} else if (rawST is List) {
|
||||
signTimes = rawST.cast<String>();
|
||||
}
|
||||
|
||||
final pairCount = math.min(signPaths.length, signTimes.length);
|
||||
final pairCount = math.min(
|
||||
signPaths.length,
|
||||
signTimes.length,
|
||||
);
|
||||
|
||||
// 解析 IMG_PATH, 最多 2 张
|
||||
List<String> imgPaths = [];
|
||||
final rawIP = FormUtils.hasValue(item, 'IMG_PATH') ? item['IMG_PATH'] : null;
|
||||
if (rawIP is String && rawIP.isNotEmpty) {
|
||||
imgPaths = rawIP.split(',').map((s) => s.trim()).take(2).toList();
|
||||
} else if (rawIP is List) {
|
||||
imgPaths = rawIP.cast<String>().take(2).toList();
|
||||
}
|
||||
// 解析 IMG_PATH, 最多 2 张
|
||||
List<String> imgPaths = [];
|
||||
final rawIP =
|
||||
FormUtils.hasValue(item, 'IMG_PATH')
|
||||
? item['IMG_PATH']
|
||||
: null;
|
||||
if (rawIP is String && rawIP.isNotEmpty) {
|
||||
imgPaths =
|
||||
rawIP.split(',').map((s) => s.trim()).take(2).toList();
|
||||
} else if (rawIP is List) {
|
||||
imgPaths = rawIP.cast<String>().take(2).toList();
|
||||
}
|
||||
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 10),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
if (imgPaths.isNotEmpty) ...[
|
||||
Row(
|
||||
children: imgPaths.map((p) {
|
||||
final fullUrl = '$baseImgPath$p';
|
||||
return GestureDetector(
|
||||
onTap: () => presentOpaque(
|
||||
SingleImageViewer(imageUrl: fullUrl),
|
||||
context,
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(right: 8.0),
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(2),
|
||||
child: Image.network(
|
||||
fullUrl,
|
||||
width: 50,
|
||||
height: 50,
|
||||
fit: BoxFit.fill,
|
||||
errorBuilder: (_, __, ___) => const Icon(
|
||||
Icons.broken_image,
|
||||
size: 40,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
],
|
||||
|
||||
// 签名及时间
|
||||
...List.generate(pairCount, (index) {
|
||||
final imgPath = signPaths[index];
|
||||
final timeLabel = signTimes[index];
|
||||
final fullUrl = '$baseImgPath$imgPath';
|
||||
const imageWidth = 200.0;
|
||||
const imageHeight = 100.0;
|
||||
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 8.0),
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
GestureDetector(
|
||||
onTap: () => presentOpaque(
|
||||
SingleImageViewer(imageUrl: fullUrl),
|
||||
context,
|
||||
),
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(4),
|
||||
child: Image.network(
|
||||
fullUrl,
|
||||
width: imageWidth,
|
||||
height: imageHeight,
|
||||
fit: BoxFit.fill,
|
||||
errorBuilder: (_, __, ___) =>
|
||||
const Icon(Icons.broken_image, size: 60),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
Expanded(
|
||||
child: SizedBox(
|
||||
height: imageHeight,
|
||||
child: Align(
|
||||
alignment: Alignment.bottomRight,
|
||||
child: Text(
|
||||
timeLabel,
|
||||
style: const TextStyle(
|
||||
fontSize: 14,
|
||||
color: Colors.black87,
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 8.0,
|
||||
horizontal: 10,
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
if (imgPaths.isNotEmpty) ...[
|
||||
Row(
|
||||
children:
|
||||
imgPaths.map((p) {
|
||||
final fullUrl = '$baseImgPath$p';
|
||||
return GestureDetector(
|
||||
onTap:
|
||||
() => presentOpaque(
|
||||
SingleImageViewer(imageUrl: fullUrl),
|
||||
context,
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
right: 8.0,
|
||||
),
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(2),
|
||||
child: Image.network(
|
||||
fullUrl,
|
||||
width: 50,
|
||||
height: 50,
|
||||
fit: BoxFit.fill,
|
||||
errorBuilder:
|
||||
(_, __, ___) => const Icon(
|
||||
Icons.broken_image,
|
||||
size: 40,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
],
|
||||
|
||||
// 签名及时间
|
||||
...List.generate(pairCount, (index) {
|
||||
final imgPath = signPaths[index];
|
||||
final timeLabel = signTimes[index];
|
||||
final fullUrl = '$baseImgPath$imgPath';
|
||||
const imageWidth = 200.0;
|
||||
const imageHeight = 100.0;
|
||||
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 8.0),
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
GestureDetector(
|
||||
onTap:
|
||||
() => presentOpaque(
|
||||
SingleImageViewer(
|
||||
imageUrl: fullUrl,
|
||||
),
|
||||
context,
|
||||
),
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(4),
|
||||
child: Image.network(
|
||||
fullUrl,
|
||||
width: imageWidth,
|
||||
height: imageHeight,
|
||||
fit: BoxFit.fill,
|
||||
errorBuilder:
|
||||
(_, __, ___) => const Icon(
|
||||
Icons.broken_image,
|
||||
size: 60,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
Expanded(
|
||||
child: SizedBox(
|
||||
height: imageHeight,
|
||||
child: Align(
|
||||
alignment: Alignment.bottomRight,
|
||||
child: Text(
|
||||
timeLabel,
|
||||
style: const TextStyle(
|
||||
fontSize: 14,
|
||||
color: Colors.black87,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
if (index < pairCount - 1)
|
||||
const Padding(
|
||||
padding: EdgeInsets.only(top: 8.0),
|
||||
child: Divider(height: 1),
|
||||
),
|
||||
],
|
||||
),
|
||||
if (index < pairCount - 1)
|
||||
const Padding(
|
||||
padding: EdgeInsets.only(top: 8.0),
|
||||
child: Divider(height: 1),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}),
|
||||
],
|
||||
),
|
||||
);
|
||||
}).toList()),
|
||||
);
|
||||
}),
|
||||
],
|
||||
),
|
||||
);
|
||||
})
|
||||
.toList()),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
@ -274,7 +305,12 @@ class SpecialWorkFormBaseWork extends StatelessWidget {
|
|||
signItemWidget('CONFESS', 'CONFESS_USER_NAME', '安全交底人', context),
|
||||
|
||||
if (FormUtils.hasValue(signs, 'ACCEPT_CONFESS'))
|
||||
signItemWidget('ACCEPT_CONFESS', 'ACCEPT_CONFESS_USER_NAME', '接受交底人', context),
|
||||
signItemWidget(
|
||||
'ACCEPT_CONFESS',
|
||||
'ACCEPT_CONFESS_USER_NAME',
|
||||
'接受交底人',
|
||||
context,
|
||||
),
|
||||
|
||||
// 作业负责人意见
|
||||
if (FormUtils.hasValue(signs, 'CONFIRM')) ...[
|
||||
|
@ -284,7 +320,10 @@ class SpecialWorkFormBaseWork extends StatelessWidget {
|
|||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Padding(padding: EdgeInsets.symmetric(horizontal: 8), child: ListItemFactory.headerTitle('作业负责人意见'),),
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 8),
|
||||
child: ListItemFactory.headerTitle('作业负责人意见'),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Text(signs['CONFIRM'][0]['DESCR'] ?? ''),
|
||||
|
@ -292,11 +331,10 @@ class SpecialWorkFormBaseWork extends StatelessWidget {
|
|||
],
|
||||
),
|
||||
),
|
||||
Divider(height: 1,),
|
||||
Divider(height: 1),
|
||||
signItemWidget('CONFIRM', 'CONFIRM_USER_NAME', '作业负责人', context),
|
||||
],
|
||||
)
|
||||
|
||||
),
|
||||
],
|
||||
|
||||
// 所在单位负责人意见
|
||||
|
@ -307,7 +345,10 @@ class SpecialWorkFormBaseWork extends StatelessWidget {
|
|||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Padding(padding: EdgeInsets.symmetric(horizontal: 8), child: ListItemFactory.headerTitle('所在单位意见'),),
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 8),
|
||||
child: ListItemFactory.headerTitle('所在单位意见'),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Text(signs['LEADER'][0]['DESCR'] ?? ''),
|
||||
|
@ -315,10 +356,10 @@ class SpecialWorkFormBaseWork extends StatelessWidget {
|
|||
],
|
||||
),
|
||||
),
|
||||
Divider(height: 1,),
|
||||
Divider(height: 1),
|
||||
signItemWidget('LEADER', 'LEADER_USER_NAME', '所在单位负责人', context),
|
||||
],
|
||||
)
|
||||
),
|
||||
],
|
||||
|
||||
// 安全管理部门负责人意见
|
||||
|
@ -329,7 +370,18 @@ class SpecialWorkFormBaseWork extends StatelessWidget {
|
|||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Padding(padding: EdgeInsets.symmetric(horizontal: 8), child: ListItemFactory.headerTitle('有关水、电、汽、工艺、设备、消防、安全等部门意见'),),
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 8),
|
||||
child: Text(
|
||||
'有关水、电、汽、工艺、设备、消防、安全等部门意见',
|
||||
maxLines: 5,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: const TextStyle(
|
||||
fontSize: 13,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Text(signs['SAFETY'][0]['DESCR'] ?? ''),
|
||||
|
@ -337,10 +389,15 @@ class SpecialWorkFormBaseWork extends StatelessWidget {
|
|||
],
|
||||
),
|
||||
),
|
||||
Divider(height: 1,),
|
||||
signItemWidget('SAFETY', 'SAFETY_USER_NAME', '有关水、电、汽、工艺、设备、消防、安全等部门负责人', context),
|
||||
Divider(height: 1),
|
||||
signItemWidget(
|
||||
'SAFETY',
|
||||
'SAFETY_USER_NAME',
|
||||
'有关水、电、汽、工艺、设备、消防、安全等部门负责人',
|
||||
context,
|
||||
),
|
||||
],
|
||||
)
|
||||
),
|
||||
],
|
||||
|
||||
// 审批人意见
|
||||
|
@ -351,7 +408,10 @@ class SpecialWorkFormBaseWork extends StatelessWidget {
|
|||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Padding(padding: EdgeInsets.symmetric(horizontal: 8), child: ListItemFactory.headerTitle('审批人意见'),),
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 8),
|
||||
child: ListItemFactory.headerTitle('审批人意见'),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Text(signs['APPROVE'][0]['DESCR'] ?? ''),
|
||||
|
@ -359,15 +419,20 @@ class SpecialWorkFormBaseWork extends StatelessWidget {
|
|||
],
|
||||
),
|
||||
),
|
||||
Divider(height: 1,),
|
||||
Divider(height: 1),
|
||||
signItemWidget('APPROVE', 'APPROVE_USER_NAME', '审批负责人', context),
|
||||
],
|
||||
)
|
||||
),
|
||||
],
|
||||
|
||||
// 作业开始负责人签字
|
||||
if (FormUtils.hasValue(signs, 'WORK_START'))
|
||||
signItemWidget('WORK_START', 'WORK_START_USER_NAME', '作业开始负责人', context),
|
||||
signItemWidget(
|
||||
'WORK_START',
|
||||
'WORK_START_USER_NAME',
|
||||
'作业开始负责人',
|
||||
context,
|
||||
),
|
||||
|
||||
// 作业结束负责人签字
|
||||
if (FormUtils.hasValue(signs, 'WORK_END'))
|
||||
|
@ -381,7 +446,10 @@ class SpecialWorkFormBaseWork extends StatelessWidget {
|
|||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Padding(padding: EdgeInsets.symmetric(horizontal: 8), child: ListItemFactory.headerTitle('完工验收意见'),),
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 8),
|
||||
child: ListItemFactory.headerTitle('完工验收意见'),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Text(signs['ACCEPT'][0]['DESCR'] ?? ''),
|
||||
|
@ -389,10 +457,10 @@ class SpecialWorkFormBaseWork extends StatelessWidget {
|
|||
],
|
||||
),
|
||||
),
|
||||
Divider(height: 1,),
|
||||
Divider(height: 1),
|
||||
signItemWidget('ACCEPT', 'ACCEPT_USER_NAME', '验收部门负责人', context),
|
||||
],
|
||||
)
|
||||
),
|
||||
],
|
||||
],
|
||||
);
|
||||
|
|
|
@ -59,7 +59,9 @@ class _BreakgroundAqjdDetailState extends State<BreakgroundAqjdDetail> {
|
|||
/// 拍照或选图后的回调
|
||||
Future<void> _onImageAdded(String localPath) async {
|
||||
// 上传到服务器
|
||||
LoadingDialogHelper.show();
|
||||
final res = await ApiService.uploadSaveFile(localPath);
|
||||
LoadingDialogHelper.hide();
|
||||
final url = res['FILE_PATH'] as String;
|
||||
setState(() {
|
||||
imgList.add(ImageData(localPath: localPath, serverPath: url));
|
||||
|
|
|
@ -437,28 +437,44 @@ class _BreakgroundListPageState extends State<BreakgroundListPage> {
|
|||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Expanded(child: Text("安全交底人: ${item['CONFESS_USER_NAME'] ?? ''}",softWrap: true,
|
||||
maxLines: null, // 不限制行数
|
||||
overflow: TextOverflow.visible,)
|
||||
Expanded(
|
||||
child: Text(
|
||||
"安全交底人: ${item['CONFESS_USER_NAME'] ?? ''}",
|
||||
softWrap: true,
|
||||
maxLines: null, // 不限制行数
|
||||
overflow: TextOverflow.visible,
|
||||
),
|
||||
),
|
||||
Expanded(child: Text("接受交底人: ${item['ACCEPT_CONFESS_USER_NAME'] ?? ''}",softWrap: true,
|
||||
textAlign: TextAlign.right,
|
||||
maxLines: null, // 不限制行数
|
||||
overflow: TextOverflow.visible,)
|
||||
Expanded(
|
||||
child: Text(
|
||||
"接受交底人: ${item['ACCEPT_CONFESS_USER_NAME'] ?? ''}",
|
||||
softWrap: true,
|
||||
textAlign: TextAlign.right,
|
||||
maxLines: null, // 不限制行数
|
||||
overflow: TextOverflow.visible,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Expanded(child: Text("作业负责人: ${item['CONFIRM_USER_NAME'] ?? ''}",softWrap: true,
|
||||
maxLines: null, // 不限制行数
|
||||
overflow: TextOverflow.visible,)
|
||||
Expanded(
|
||||
child: Text(
|
||||
"作业负责人: ${item['CONFIRM_USER_NAME'] ?? ''}",
|
||||
softWrap: true,
|
||||
maxLines: null, // 不限制行数
|
||||
overflow: TextOverflow.visible,
|
||||
),
|
||||
),
|
||||
Expanded(child: Text("所在单位负责人: ${item['LEADER_USER_NAME'] ?? ''}",softWrap: true,
|
||||
textAlign: TextAlign.right,
|
||||
maxLines: null, // 不限制行数
|
||||
overflow: TextOverflow.visible,)
|
||||
Expanded(
|
||||
child: Text(
|
||||
"所在单位负责人: ${item['LEADER_USER_NAME'] ?? ''}",
|
||||
softWrap: true,
|
||||
textAlign: TextAlign.right,
|
||||
maxLines: null, // 不限制行数
|
||||
overflow: TextOverflow.visible,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
@ -466,21 +482,30 @@ class _BreakgroundListPageState extends State<BreakgroundListPage> {
|
|||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
"有关水、电、汽、工艺、设备、消防安全等部门: ${item['SAFETY_USER_NAME'] ?? ''}",
|
||||
Expanded(
|
||||
child: Text(
|
||||
"有关水、电、汽、工艺、设备、消防安全等部门: ${item['SAFETY_USER_NAME'] ?? ''}",
|
||||
softWrap: true,
|
||||
maxLines: null, // 不限制行数
|
||||
overflow: TextOverflow.visible,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
if (FormUtils.hasValue(item, 'APPROVE_USER_NAME'))
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Expanded(child: Text("审批部门负责人: ${item['APPROVE_USER_NAME'] ?? ''}",softWrap: true,
|
||||
maxLines: null, // 不限制行数
|
||||
overflow: TextOverflow.visible,)
|
||||
),
|
||||
],
|
||||
),
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
"审批部门负责人: ${item['APPROVE_USER_NAME'] ?? ''}",
|
||||
softWrap: true,
|
||||
maxLines: null, // 不限制行数
|
||||
overflow: TextOverflow.visible,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
|
|
|
@ -544,11 +544,7 @@ class _BreakgroundApplyDetailState extends State<BreakgroundApplyDetail> {
|
|||
_relatedController.text = pd['SPECIAL_WORK'] ?? '';
|
||||
_riskController.text = pd['RISK_IDENTIFICATION'] ?? '';
|
||||
});
|
||||
// final data = await ApiService.getHomeworkFindById('breakground', widget.BREAKGROUND_ID);
|
||||
// setState(() {
|
||||
// pd = data['pd'];
|
||||
// });
|
||||
// LoadingDialogHelper.hide();
|
||||
|
||||
}
|
||||
|
||||
Future<void> _getSigns(String homework_id) async {
|
||||
|
|
|
@ -310,6 +310,7 @@ class _BreakgroundJszyDetailState extends State<BreakgroundJszyDetail> {
|
|||
onTap: () async {
|
||||
DateTime? picked = await BottomDateTimePicker.showDate(
|
||||
mode: BottomPickerMode.dateTimeWithSeconds,
|
||||
minTimeStr: pd['WORK_START_DATE'],
|
||||
context,
|
||||
);
|
||||
if (picked != null) {
|
||||
|
|
|
@ -67,7 +67,9 @@ class _BreakgroundYsgdDetailState extends State<BreakgroundYsgdDetail> {
|
|||
/// 拍照或选图后的回调
|
||||
Future<void> _onImageAdded(String localPath) async {
|
||||
// 上传到服务器
|
||||
LoadingDialogHelper.show();
|
||||
final res = await ApiService.uploadSaveFile(localPath);
|
||||
LoadingDialogHelper.hide();
|
||||
final url = res['FILE_PATH'] as String;
|
||||
setState(() {
|
||||
imgList.add(ImageData(localPath: localPath, serverPath: url));
|
||||
|
|
|
@ -343,8 +343,7 @@ class _BreakgroundZyrDetailState extends State<BreakgroundZyrDetail> {
|
|||
text: pd['WORK_CONTENT'] ?? '',
|
||||
),
|
||||
Divider(),
|
||||
|
||||
RepairedPhotoSection(
|
||||
Padding(padding: EdgeInsets.symmetric(horizontal: 8),child: RepairedPhotoSection(
|
||||
title: '作业内容、范围、方式简图',
|
||||
maxCount: 100,
|
||||
mediaType: MediaType.image,
|
||||
|
@ -354,12 +353,12 @@ class _BreakgroundZyrDetailState extends State<BreakgroundZyrDetail> {
|
|||
onMediaAdded: _onImageAdded,
|
||||
onMediaRemoved: (path) {
|
||||
final item = workImages.firstWhere(
|
||||
(e) => e.localPath == path,
|
||||
(e) => e.localPath == path,
|
||||
);
|
||||
_onImageRemoved(item);
|
||||
},
|
||||
onAiIdentify: () {},
|
||||
),
|
||||
),)
|
||||
],
|
||||
),
|
||||
),
|
||||
|
|
|
@ -59,7 +59,9 @@ class _HoistworkAqjdDetailState extends State<HoistworkAqjdDetail> {
|
|||
/// 拍照或选图后的回调
|
||||
Future<void> _onImageAdded(String localPath) async {
|
||||
// 上传到服务器
|
||||
LoadingDialogHelper.show();
|
||||
final res = await ApiService.uploadSaveFile(localPath);
|
||||
LoadingDialogHelper.hide();
|
||||
final url = res['FILE_PATH'] as String;
|
||||
setState(() {
|
||||
imgList.add(ImageData(localPath: localPath, serverPath: url));
|
||||
|
|
|
@ -310,6 +310,7 @@ class _HoistworkJszyDetailState extends State<HoistworkJszyDetail> {
|
|||
onTap: () async {
|
||||
DateTime? picked = await BottomDateTimePicker.showDate(
|
||||
mode: BottomPickerMode.dateTimeWithSeconds,
|
||||
minTimeStr: pd['WORK_START_DATE'],
|
||||
context,
|
||||
);
|
||||
if (picked != null) {
|
||||
|
|
|
@ -67,7 +67,9 @@ class _HoistworkYsgdDetailState extends State<HoistworkYsgdDetail> {
|
|||
/// 拍照或选图后的回调
|
||||
Future<void> _onImageAdded(String localPath) async {
|
||||
// 上传到服务器
|
||||
LoadingDialogHelper.show();
|
||||
final res = await ApiService.uploadSaveFile(localPath);
|
||||
LoadingDialogHelper.hide();
|
||||
final url = res['FILE_PATH'] as String;
|
||||
setState(() {
|
||||
imgList.add(ImageData(localPath: localPath, serverPath: url));
|
||||
|
|
|
@ -59,7 +59,9 @@ class _HighworkAqjdDetailState extends State<HighworkAqjdDetail> {
|
|||
/// 拍照或选图后的回调
|
||||
Future<void> _onImageAdded(String localPath) async {
|
||||
// 上传到服务器
|
||||
LoadingDialogHelper.show();
|
||||
final res = await ApiService.uploadSaveFile(localPath);
|
||||
LoadingDialogHelper.hide();
|
||||
final url = res['FILE_PATH'] as String;
|
||||
setState(() {
|
||||
imgList.add(ImageData(localPath: localPath, serverPath: url));
|
||||
|
|
|
@ -310,6 +310,7 @@ class _HighworkJszyDetailState extends State<HighworkJszyDetail> {
|
|||
onTap: () async {
|
||||
DateTime? picked = await BottomDateTimePicker.showDate(
|
||||
mode: BottomPickerMode.dateTimeWithSeconds,
|
||||
minTimeStr: pd['WORK_START_DATE'],
|
||||
context,
|
||||
);
|
||||
if (picked != null) {
|
||||
|
|
|
@ -67,7 +67,9 @@ class _HighworkYsgdDetailState extends State<HighworkYsgdDetail> {
|
|||
/// 拍照或选图后的回调
|
||||
Future<void> _onImageAdded(String localPath) async {
|
||||
// 上传到服务器
|
||||
LoadingDialogHelper.show();
|
||||
final res = await ApiService.uploadSaveFile(localPath);
|
||||
LoadingDialogHelper.hide();
|
||||
final url = res['FILE_PATH'] as String;
|
||||
setState(() {
|
||||
imgList.add(ImageData(localPath: localPath, serverPath: url));
|
||||
|
|
|
@ -60,7 +60,9 @@ class _ElectricityAqjdDetailState extends State<ElectricityAqjdDetail> {
|
|||
/// 拍照或选图后的回调
|
||||
Future<void> _onImageAdded(String localPath) async {
|
||||
// 上传到服务器
|
||||
LoadingDialogHelper.show();
|
||||
final res = await ApiService.uploadSaveFile(localPath);
|
||||
LoadingDialogHelper.hide();
|
||||
final url = res['FILE_PATH'] as String;
|
||||
setState(() {
|
||||
imgList.add(ImageData(localPath: localPath, serverPath: url));
|
||||
|
|
|
@ -316,6 +316,7 @@ class _ElectricityJszyDetailState extends State<ElectricityJszyDetail> {
|
|||
onTap: () async {
|
||||
DateTime? picked = await BottomDateTimePicker.showDate(
|
||||
mode: BottomPickerMode.dateTimeWithSeconds,
|
||||
minTimeStr: pd['WORK_START_DATE'],
|
||||
context,
|
||||
);
|
||||
if (picked != null) {
|
||||
|
|
|
@ -646,6 +646,8 @@ class _ElectricityApplyDetailState extends State<ElectricityApplyDetail> {
|
|||
ListItemFactory.createYesNoSection(
|
||||
title: '是否进行气体分析',
|
||||
horizontalPadding: 0,
|
||||
isEdit: isEditable,
|
||||
text: _isGasAnalyze ? '是' : '否',
|
||||
groupValue: _isGasAnalyze,
|
||||
onChanged: (val) {
|
||||
setState(() {
|
||||
|
@ -666,8 +668,6 @@ class _ElectricityApplyDetailState extends State<ElectricityApplyDetail> {
|
|||
|
||||
_card(_chooseItem(EditUserType.GUARDIAN)),
|
||||
SizedBox(height: 15),
|
||||
_card(_chooseItem(EditUserType.CONFESS)),
|
||||
SizedBox(height: 15),
|
||||
_card(_chooseItem(EditUserType.ELECTRICITY)),
|
||||
SizedBox(height: 15),
|
||||
_card(_chooseItem(EditUserType.CONFESS)),
|
||||
|
|
|
@ -194,7 +194,7 @@ class _ElectricityYddwDetailState extends State<ElectricityYddwDetail> {
|
|||
/// 初始化拉取数据
|
||||
Future<void> _getData() async {
|
||||
final data = await ApiService.getHomeworkFindById(
|
||||
'highwork',
|
||||
'electricity',
|
||||
widget.ELECTRICITY_ID,
|
||||
);
|
||||
setState(() {
|
||||
|
|
|
@ -67,7 +67,9 @@ class _ElectricityYsgdDetailState extends State<ElectricityYsgdDetail> {
|
|||
/// 拍照或选图后的回调
|
||||
Future<void> _onImageAdded(String localPath) async {
|
||||
// 上传到服务器
|
||||
LoadingDialogHelper.show();
|
||||
final res = await ApiService.uploadSaveFile(localPath);
|
||||
LoadingDialogHelper.hide();
|
||||
final url = res['FILE_PATH'] as String;
|
||||
setState(() {
|
||||
imgList.add(ImageData(localPath: localPath, serverPath: url));
|
||||
|
|
|
@ -60,7 +60,9 @@ class _BlindboardAqjdDetailState extends State<BlindboardAqjdDetail> {
|
|||
/// 拍照或选图后的回调
|
||||
Future<void> _onImageAdded(String localPath) async {
|
||||
// 上传到服务器
|
||||
LoadingDialogHelper.show();
|
||||
final res = await ApiService.uploadSaveFile(localPath);
|
||||
LoadingDialogHelper.hide();
|
||||
final url = res['FILE_PATH'] as String;
|
||||
setState(() {
|
||||
imgList.add(ImageData(localPath: localPath, serverPath: url));
|
||||
|
|
|
@ -248,7 +248,9 @@ setState(() {
|
|||
/// 拍照或选图后的回调
|
||||
Future<void> _onImageAdded(String localPath) async {
|
||||
// 上传到服务器
|
||||
LoadingDialogHelper.show();
|
||||
final res = await ApiService.uploadSaveFile(localPath);
|
||||
LoadingDialogHelper.hide();
|
||||
final url = res['FILE_PATH'] as String;
|
||||
setState(() {
|
||||
imgList.add(ImageData(localPath: localPath, serverPath: url));
|
||||
|
|
|
@ -313,6 +313,7 @@ class _BlindboardJszyDetailState extends State<BlindboardJszyDetail> {
|
|||
onTap: () async {
|
||||
DateTime? picked = await BottomDateTimePicker.showDate(
|
||||
mode: BottomPickerMode.dateTimeWithSeconds,
|
||||
minTimeStr: pd['WORK_START_DATE'],
|
||||
context,
|
||||
);
|
||||
if (picked != null) {
|
||||
|
|
|
@ -68,7 +68,9 @@ class _BlindboardYsgdDetailState extends State<BlindboardYsgdDetail> {
|
|||
/// 拍照或选图后的回调
|
||||
Future<void> _onImageAdded(String localPath) async {
|
||||
// 上传到服务器
|
||||
LoadingDialogHelper.show();
|
||||
final res = await ApiService.uploadSaveFile(localPath);
|
||||
LoadingDialogHelper.hide();
|
||||
final url = res['FILE_PATH'] as String;
|
||||
setState(() {
|
||||
imgList.add(ImageData(localPath: localPath, serverPath: url));
|
||||
|
|
|
@ -61,7 +61,9 @@ class _SpaceworkAqjdDetailState extends State<SpaceworkAqjdDetail> {
|
|||
/// 拍照或选图后的回调
|
||||
Future<void> _onImageAdded(String localPath) async {
|
||||
// 上传到服务器
|
||||
LoadingDialogHelper.show();
|
||||
final res = await ApiService.uploadSaveFile(localPath);
|
||||
LoadingDialogHelper.hide();
|
||||
final url = res['FILE_PATH'] as String;
|
||||
setState(() {
|
||||
imgList.add(ImageData(localPath: localPath, serverPath: url));
|
||||
|
|
|
@ -320,6 +320,7 @@ class _SpaceworkJszyDetailState extends State<SpaceworkJszyDetail> {
|
|||
onTap: () async {
|
||||
DateTime? picked = await BottomDateTimePicker.showDate(
|
||||
mode: BottomPickerMode.dateTimeWithSeconds,
|
||||
minTimeStr: pd['WORK_START_DATE'],
|
||||
context,
|
||||
);
|
||||
if (picked != null) {
|
||||
|
|
|
@ -35,6 +35,19 @@ class _SpaceworkGasListState extends State<SpaceworkGasList> {
|
|||
list = data['varList'] ?? [];
|
||||
isLoading = false;
|
||||
});
|
||||
final result = await ApiService.getConfinedspacegaswh(widget.CONFINEDSPACE_ID);
|
||||
if (FormUtils.hasValue(result, 'pd')) {
|
||||
setState(() {
|
||||
Map pd = result['pd'];
|
||||
for (Map item in list) {
|
||||
item['GAS_NAME1'] = pd['GAS_NAME1'] ?? '';
|
||||
item['GAS_NAME2'] = pd['GAS_NAME2'] ?? '';
|
||||
item['GAS_NAME3'] = pd['GAS_NAME3'] ?? '';
|
||||
item['GAS_NAME4'] = pd['GAS_NAME4'] ?? '';
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void _deleteItem(String id) async {
|
||||
|
@ -54,8 +67,8 @@ class _SpaceworkGasListState extends State<SpaceworkGasList> {
|
|||
|
||||
}
|
||||
|
||||
Widget _gas_new_widget(Map<String, dynamic> pd,String type) {
|
||||
return FormUtils.hasValue(widget.saveParams, 'GAS_NAME$type') ?
|
||||
Widget _gas_new_widget(Map<String, dynamic> item,String type) {
|
||||
return FormUtils.hasValue(item, 'GAS_NAME$type') ?
|
||||
Column(
|
||||
children: [
|
||||
const SizedBox(height: 6),
|
||||
|
@ -63,15 +76,15 @@ class _SpaceworkGasListState extends State<SpaceworkGasList> {
|
|||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text('${widget.saveParams['GAS_NAME$type']}: ${pd['DATA$type'] ?? ''}'),
|
||||
Text('计量单位: ${pd['GAS_UNIT$type'] ?? ''}'),
|
||||
Text('${item['GAS_NAME$type']}: ${item['DATA$type'] ?? ''}'),
|
||||
Text('计量单位: ${item['GAS_UNIT$type'] ?? ''}'),
|
||||
],
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text('上限: ${pd['UPPER_LIMIT$type'] ?? ''}'),
|
||||
Text('下限: ${pd['LOWER_LIMIT$type'] ?? ''}'),
|
||||
Text('上限: ${item['UPPER_LIMIT$type'] ?? ''}'),
|
||||
Text('下限: ${item['LOWER_LIMIT$type'] ?? ''}'),
|
||||
],
|
||||
),
|
||||
],
|
||||
|
|
|
@ -441,7 +441,8 @@ class _SpaceworkGasTestPageState extends State<SpaceworkGasTestPage> {
|
|||
const Divider(),
|
||||
ItemListWidget.singleLineTitleText(
|
||||
label: '氧气含量:',
|
||||
hintText: '请输入氧气含量',
|
||||
isNumericInput: true,
|
||||
hintText: '请输入氧气含量,数字保留两位小数',
|
||||
isEditable: true,
|
||||
controller: _O2Controller,
|
||||
),
|
||||
|
|
|
@ -8,6 +8,7 @@ import 'package:qhd_prevention/customWidget/department_picker.dart';
|
|||
import 'package:qhd_prevention/customWidget/toast_util.dart';
|
||||
import 'package:qhd_prevention/pages/home/tap/item_list_widget.dart';
|
||||
import 'package:qhd_prevention/pages/home/tap/tabList/special_wrok/sxkj_work/SpaceWorkDetailFormWidget.dart';
|
||||
import 'package:qhd_prevention/pages/home/tap/tabList/special_wrok/sxkj_work/qtfx_work_detail/spacework_gas_list.dart';
|
||||
import 'package:qhd_prevention/tools/h_colors.dart';
|
||||
import 'package:qhd_prevention/tools/tools.dart';
|
||||
import 'package:qhd_prevention/http/ApiService.dart';
|
||||
|
@ -626,7 +627,12 @@ class _SpaceworkApplyDetailState extends State<SpaceworkApplyDetail> {
|
|||
riskController: _riskController,
|
||||
onChooseLevel: _chooseLevel,
|
||||
onChooseSpaceName: _chooseSpaceName,
|
||||
onAnalyzeTap: () {},
|
||||
onAnalyzeTap: () {
|
||||
pushPage(
|
||||
SpaceworkGasList(CONFINEDSPACE_ID: widget.WORK_ID),
|
||||
context,
|
||||
);
|
||||
},
|
||||
// 新增
|
||||
onChooseVideoManager: _chooseVideoManager,
|
||||
onContractorHandle: _chooseUnitManager,
|
||||
|
|
|
@ -138,7 +138,7 @@ class _SxkjTzglDetailState extends State<SxkjTzglDetail> {
|
|||
pushPage(
|
||||
RemoteFilePage(
|
||||
fileUrl: ApiService.baseImgPath + pd['HASINSTRUCTOR_PATH'],
|
||||
countdownSeconds: 10,
|
||||
countdownSeconds: 30,
|
||||
),
|
||||
context,
|
||||
);
|
||||
|
|
|
@ -68,7 +68,9 @@ class _SpaceworkYsgdDetailState extends State<SpaceworkYsgdDetail> {
|
|||
/// 拍照或选图后的回调
|
||||
Future<void> _onImageAdded(String localPath) async {
|
||||
// 上传到服务器
|
||||
LoadingDialogHelper.show();
|
||||
final res = await ApiService.uploadSaveFile(localPath);
|
||||
LoadingDialogHelper.hide();
|
||||
final url = res['FILE_PATH'] as String;
|
||||
setState(() {
|
||||
imgList.add(ImageData(localPath: localPath, serverPath: url));
|
||||
|
|
|
@ -20,13 +20,58 @@ class WorkTabListPage extends StatefulWidget {
|
|||
}
|
||||
|
||||
class _WorkTabListPageState extends State<WorkTabListPage> {
|
||||
late List<Map<String, dynamic>> buttonInfos = [];
|
||||
late List<Map<String, dynamic>> buttonInfos = [
|
||||
{
|
||||
"icon": "assets/icon-apps/icon-807.png",
|
||||
"title": "动火作业",
|
||||
"unreadCount": 0,
|
||||
},
|
||||
{
|
||||
"icon": "assets/icon-apps/icon-803.png",
|
||||
"title": "高处作业",
|
||||
"unreadCount": 0,
|
||||
},
|
||||
{
|
||||
"icon": "assets/icon-apps/icon-804.png",
|
||||
"title": "吊装作业",
|
||||
"unreadCount": 0,
|
||||
},
|
||||
{
|
||||
"icon": "assets/icon-apps/icon-802.png",
|
||||
"title": "动土作业",
|
||||
"unreadCount": 0,
|
||||
},
|
||||
|
||||
{
|
||||
"icon": "assets/icon-apps/open-circuit.png",
|
||||
"title": "断路作业",
|
||||
"unreadCount": 0,
|
||||
},
|
||||
{
|
||||
"icon": "assets/icon-apps/icon-805.png",
|
||||
"title": "临时用电作业",
|
||||
"unreadCount": 0,
|
||||
},
|
||||
|
||||
{
|
||||
"icon": "assets/icon-apps/icon-806.png",
|
||||
"title": "受限空间\n安全作业",
|
||||
"unreadCount": 0,
|
||||
},
|
||||
|
||||
{
|
||||
"icon": "assets/icon-apps/icon-801.png",
|
||||
"title": "盲板抽堵作业",
|
||||
"unreadCount": 0,
|
||||
},
|
||||
];
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_getData();
|
||||
}
|
||||
|
||||
Future<void> _getData() async {
|
||||
final data = await ApiService.specialCheckWork();
|
||||
setState(() {
|
||||
|
@ -70,28 +115,45 @@ class _WorkTabListPageState extends State<WorkTabListPage> {
|
|||
"unreadCount": eight_work_count['CONFINEDSPACE_COUNT'],
|
||||
},
|
||||
|
||||
|
||||
{
|
||||
"icon": "assets/icon-apps/icon-801.png",
|
||||
"title": "盲板抽堵作业",
|
||||
"unreadCount": eight_work_count['BLIND_BOARD_COUNT'],
|
||||
}
|
||||
},
|
||||
];
|
||||
});
|
||||
}
|
||||
|
||||
void _handleItemPressed(int index) async {
|
||||
switch (index) {
|
||||
case 0:await pushPage(WorkTabDhList(), context); break;
|
||||
case 1:await pushPage(WorkTabGcList(), context); break;
|
||||
case 2:await pushPage(WorkTabDzList(), context); break;
|
||||
case 3:await pushPage(WorkTabDtList(), context); break;
|
||||
case 4:await pushPage(WorkTabDlList(), context); break;
|
||||
case 5:await pushPage(WorkTabLsydList(), context); break;
|
||||
case 6:await pushPage(WorkTabSxkjList(), context); break;
|
||||
case 7:await pushPage(WorkTabMbcdList(), context); break;
|
||||
case 0:
|
||||
await pushPage(WorkTabDhList(), context);
|
||||
break;
|
||||
case 1:
|
||||
await pushPage(WorkTabGcList(), context);
|
||||
break;
|
||||
case 2:
|
||||
await pushPage(WorkTabDzList(), context);
|
||||
break;
|
||||
case 3:
|
||||
await pushPage(WorkTabDtList(), context);
|
||||
break;
|
||||
case 4:
|
||||
await pushPage(WorkTabDlList(), context);
|
||||
break;
|
||||
case 5:
|
||||
await pushPage(WorkTabLsydList(), context);
|
||||
break;
|
||||
case 6:
|
||||
await pushPage(WorkTabSxkjList(), context);
|
||||
break;
|
||||
case 7:
|
||||
await pushPage(WorkTabMbcdList(), context);
|
||||
break;
|
||||
}
|
||||
_getData();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
|
|
|
@ -39,10 +39,15 @@ class _MineSetPageState extends State<MineSetPage> {
|
|||
}
|
||||
);
|
||||
}else{
|
||||
ToastUtil.showNormal(context, '已经是最新版本!');
|
||||
_loadAppVersion();
|
||||
|
||||
}
|
||||
}
|
||||
Future<void> _loadAppVersion() async {
|
||||
final versionInfo = await getAppVersion();
|
||||
ToastUtil.showNormal(context, '已经是最新版本!当前版本号:${versionInfo.fullVersion}');
|
||||
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
@ -93,7 +98,7 @@ class _MineSetPageState extends State<MineSetPage> {
|
|||
padding: const EdgeInsets.symmetric(vertical: 15),
|
||||
color: Colors.white,
|
||||
child: const Center(
|
||||
child: Text("退出当前账户", style: TextStyle(fontSize: 16)),
|
||||
child: Text("退出当前账户", style: TextStyle(fontSize: 14)),
|
||||
),
|
||||
),
|
||||
onTap: () async {
|
||||
|
@ -127,7 +132,7 @@ class _MineSetPageState extends State<MineSetPage> {
|
|||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(text, style: const TextStyle(fontSize: 16)),
|
||||
Text(text, style: const TextStyle(fontSize: 14)),
|
||||
const Icon(Icons.chevron_right),
|
||||
],
|
||||
),
|
||||
|
|
|
@ -47,7 +47,6 @@ class _SignatureConfirmPageState extends State<SignatureConfirmPage> {
|
|||
ToastUtil.showNormal(context, '请先签名');
|
||||
return;
|
||||
}
|
||||
|
||||
_saveSignPic();
|
||||
|
||||
// // 保存签名逻辑
|
||||
|
@ -59,6 +58,7 @@ class _SignatureConfirmPageState extends State<SignatureConfirmPage> {
|
|||
|
||||
// 保存签名
|
||||
void _saveSignPic() async {
|
||||
LoadingDialogHelper.show();
|
||||
RenderRepaintBoundary boundary = _signatureKey.currentContext!
|
||||
.findRenderObject() as RenderRepaintBoundary;
|
||||
var image = await boundary.toImage(pixelRatio: 1);
|
||||
|
@ -80,12 +80,12 @@ class _SignatureConfirmPageState extends State<SignatureConfirmPage> {
|
|||
var file = await File(path).create(recursive: true);
|
||||
if (byteData != null) {
|
||||
file.writeAsBytesSync(byteData.buffer.asInt8List(), flush: true);
|
||||
|
||||
setState(() {
|
||||
_postBytes = byteData.buffer.asUint8List();
|
||||
fileN = file;
|
||||
imagepath = file.path;
|
||||
Future.delayed(const Duration(milliseconds: 500), () {
|
||||
LoadingDialogHelper.hide();
|
||||
Navigator.pop(context, imagepath);
|
||||
});
|
||||
});
|
||||
|
@ -122,7 +122,6 @@ class _SignatureConfirmPageState extends State<SignatureConfirmPage> {
|
|||
// 标题区域
|
||||
_buildTitleBar(),
|
||||
// MyAppbar(title: "签字"),
|
||||
|
||||
// 签字区域
|
||||
Expanded(
|
||||
child: _buildSignatureArea(),
|
||||
|
|
|
@ -374,6 +374,14 @@ packages:
|
|||
url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/"
|
||||
source: hosted
|
||||
version: "3.9.5"
|
||||
flutter_baidu_mapapi_utils:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: flutter_baidu_mapapi_utils
|
||||
sha256: "8ff1127ed81e3a5ca48dae6c5377adaf601f90a3d4f6f07eebafc0e415f88fbb"
|
||||
url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/"
|
||||
source: hosted
|
||||
version: "3.9.5"
|
||||
flutter_easyloading:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
|
|
@ -110,6 +110,7 @@ dependencies:
|
|||
#百度地图
|
||||
flutter_baidu_mapapi_base: ^3.9.5
|
||||
flutter_baidu_mapapi_map: ^3.9.5
|
||||
flutter_baidu_mapapi_utils: ^3.9.5
|
||||
#文件处理
|
||||
video_compress: ^3.1.4
|
||||
#息屏处理
|
||||
|
@ -149,8 +150,6 @@ flutter:
|
|||
- assets/tabbar/
|
||||
- assets/study/
|
||||
|
||||
|
||||
|
||||
# - images/a_dot_burr.jpeg
|
||||
# - images/a_dot_ham.jpeg
|
||||
|
||||
|
|
Loading…
Reference in New Issue