main
parent
e7fbd5e12c
commit
3a00844a57
|
|
@ -1,7 +1,6 @@
|
|||
import 'dart:io';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:image_picker/image_picker.dart';
|
||||
import 'package:qhd_prevention/tools/h_colors.dart';
|
||||
import 'package:wechat_assets_picker/wechat_assets_picker.dart';
|
||||
import 'package:photo_manager/photo_manager.dart';
|
||||
|
||||
|
|
@ -10,25 +9,32 @@ import 'ItemWidgetFactory.dart';
|
|||
/// 媒体选择类型
|
||||
enum MediaType { image, video }
|
||||
|
||||
/// 横向一行最多四个媒体的添加组件,支持拍摄和全屏相册多选
|
||||
/// 横向一行最多四个媒体的添加组件,支持拍摄、全屏相册多选,以及初始地址列表展示
|
||||
/// 使用示例:
|
||||
/// MediaPickerRow(
|
||||
/// maxCount: 4,
|
||||
/// mediaType: MediaType.video,
|
||||
/// onChanged: (List<File> medias) {
|
||||
/// // medias 列表更新
|
||||
/// },
|
||||
/// initialMediaPaths: ['https://...', '/local/path.png'],
|
||||
/// onChanged: (List<File> medias) {},
|
||||
/// onMediaAdded: (String path) {},
|
||||
/// onMediaRemoved: (String path) {},
|
||||
/// ),
|
||||
class MediaPickerRow extends StatefulWidget {
|
||||
final int maxCount;
|
||||
final MediaType mediaType;
|
||||
final List<String>? initialMediaPaths;
|
||||
final ValueChanged<List<File>> onChanged;
|
||||
final ValueChanged<String>? onMediaAdded;
|
||||
final ValueChanged<String>? onMediaRemoved;
|
||||
|
||||
const MediaPickerRow({
|
||||
Key? key,
|
||||
this.maxCount = 4,
|
||||
this.mediaType = MediaType.image,
|
||||
this.initialMediaPaths,
|
||||
required this.onChanged,
|
||||
this.onMediaAdded,
|
||||
this.onMediaRemoved,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
|
|
@ -37,13 +43,24 @@ class MediaPickerRow extends StatefulWidget {
|
|||
|
||||
class _MediaPickerRowState extends State<MediaPickerRow> {
|
||||
final ImagePicker _picker = ImagePicker();
|
||||
final List<File> _files = [];
|
||||
late List<String> _mediaPaths;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_mediaPaths = widget.initialMediaPaths != null
|
||||
? widget.initialMediaPaths!.take(widget.maxCount).toList()
|
||||
: [];
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
// 初始回调,转换为 File 列表
|
||||
widget.onChanged(_mediaPaths.map((p) => p.startsWith('http') ? File('') : File(p)).toList());
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> _showPickerOptions() async {
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
builder:
|
||||
(_) => SafeArea(
|
||||
builder: (_) => SafeArea(
|
||||
child: Wrap(
|
||||
children: [
|
||||
ListTile(
|
||||
|
|
@ -67,7 +84,9 @@ class _MediaPickerRowState extends State<MediaPickerRow> {
|
|||
: Icons.video_library,
|
||||
),
|
||||
title: Text(
|
||||
widget.mediaType == MediaType.image ? '从相册选择' : '从相册选择视频',
|
||||
widget.mediaType == MediaType.image
|
||||
? '从相册选择'
|
||||
: '从相册选择视频',
|
||||
),
|
||||
onTap: () {
|
||||
Navigator.of(context).pop();
|
||||
|
|
@ -86,7 +105,7 @@ class _MediaPickerRowState extends State<MediaPickerRow> {
|
|||
}
|
||||
|
||||
Future<void> _pickCamera() async {
|
||||
if (_files.length >= widget.maxCount) return;
|
||||
if (_mediaPaths.length >= widget.maxCount) return;
|
||||
try {
|
||||
XFile? picked;
|
||||
if (widget.mediaType == MediaType.image) {
|
||||
|
|
@ -95,10 +114,10 @@ class _MediaPickerRowState extends State<MediaPickerRow> {
|
|||
picked = await _picker.pickVideo(source: ImageSource.camera);
|
||||
}
|
||||
if (picked != null) {
|
||||
setState(() {
|
||||
_files.add(File(picked!.path));
|
||||
});
|
||||
widget.onChanged(_files);
|
||||
final path = picked.path;
|
||||
setState(() => _mediaPaths.add(path));
|
||||
widget.onChanged(_mediaPaths.map((p) => File(p)).toList());
|
||||
widget.onMediaAdded?.call(path);
|
||||
}
|
||||
} catch (e) {
|
||||
debugPrint('拍摄失败: $e');
|
||||
|
|
@ -106,22 +125,21 @@ class _MediaPickerRowState extends State<MediaPickerRow> {
|
|||
}
|
||||
|
||||
Future<void> _pickGallery() async {
|
||||
if (_files.length >= widget.maxCount) return;
|
||||
if (_mediaPaths.length >= widget.maxCount) return;
|
||||
final permission = await PhotoManager.requestPermissionExtend();
|
||||
if (permission != PermissionState.authorized &&
|
||||
permission != PermissionState.limited) {
|
||||
ScaffoldMessenger.of(
|
||||
context,
|
||||
).showSnackBar(const SnackBar(content: Text('请到设置中开启相册访问权限')));
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(content: Text('请到设置中开启相册访问权限')),
|
||||
);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
final remaining = widget.maxCount - _files.length;
|
||||
final remaining = widget.maxCount - _mediaPaths.length;
|
||||
final List<AssetEntity>? assets = await AssetPicker.pickAssets(
|
||||
context,
|
||||
pickerConfig: AssetPickerConfig(
|
||||
requestType:
|
||||
widget.mediaType == MediaType.image
|
||||
requestType: widget.mediaType == MediaType.image
|
||||
? RequestType.image
|
||||
: RequestType.video,
|
||||
maxAssets: remaining,
|
||||
|
|
@ -130,25 +148,27 @@ class _MediaPickerRowState extends State<MediaPickerRow> {
|
|||
);
|
||||
if (assets != null) {
|
||||
for (final asset in assets) {
|
||||
if (_files.length >= widget.maxCount) break;
|
||||
if (_mediaPaths.length >= widget.maxCount) break;
|
||||
final file = await asset.file;
|
||||
if (file != null) {
|
||||
_files.add(file);
|
||||
final path = file.path;
|
||||
_mediaPaths.add(path);
|
||||
widget.onMediaAdded?.call(path);
|
||||
}
|
||||
}
|
||||
setState(() {});
|
||||
widget.onChanged(_files);
|
||||
widget.onChanged(_mediaPaths.map((p) => File(p)).toList());
|
||||
}
|
||||
} catch (e) {
|
||||
debugPrint('相册选择失败: $e');
|
||||
}
|
||||
}
|
||||
|
||||
void _removeFile(int index) {
|
||||
setState(() {
|
||||
_files.removeAt(index);
|
||||
});
|
||||
widget.onChanged(_files);
|
||||
void _removeMedia(int index) {
|
||||
final removed = _mediaPaths[index];
|
||||
setState(() => _mediaPaths.removeAt(index));
|
||||
widget.onChanged(_mediaPaths.map((p) => File(p)).toList());
|
||||
widget.onMediaRemoved?.call(removed);
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
@ -157,25 +177,24 @@ class _MediaPickerRowState extends State<MediaPickerRow> {
|
|||
height: 80,
|
||||
child: ListView.separated(
|
||||
scrollDirection: Axis.horizontal,
|
||||
itemCount:
|
||||
_files.length < widget.maxCount
|
||||
? _files.length + 1
|
||||
itemCount: _mediaPaths.length < widget.maxCount
|
||||
? _mediaPaths.length + 1
|
||||
: widget.maxCount,
|
||||
separatorBuilder: (_, __) => const SizedBox(width: 8),
|
||||
itemBuilder: (context, index) {
|
||||
if (index < _files.length) {
|
||||
if (index < _mediaPaths.length) {
|
||||
final path = _mediaPaths[index];
|
||||
final isNetwork = path.startsWith('http');
|
||||
return Stack(
|
||||
children: [
|
||||
ClipRRect(
|
||||
borderRadius: BorderRadius.circular(5),
|
||||
child:
|
||||
widget.mediaType == MediaType.image
|
||||
? Image.file(
|
||||
_files[index],
|
||||
width: 80,
|
||||
height: 80,
|
||||
fit: BoxFit.cover,
|
||||
)
|
||||
child: widget.mediaType == MediaType.image
|
||||
? (isNetwork
|
||||
? Image.network(path,
|
||||
width: 80, height: 80, fit: BoxFit.cover)
|
||||
: Image.file(File(path),
|
||||
width: 80, height: 80, fit: BoxFit.cover))
|
||||
: Container(
|
||||
width: 80,
|
||||
height: 80,
|
||||
|
|
@ -189,11 +208,11 @@ class _MediaPickerRowState extends State<MediaPickerRow> {
|
|||
),
|
||||
),
|
||||
Positioned(
|
||||
top: -6,
|
||||
right: -6,
|
||||
top: -15,
|
||||
right: -15,
|
||||
child: IconButton(
|
||||
icon: const Icon(Icons.cancel, size: 20, color: Colors.red),
|
||||
onPressed: () => _removeFile(index),
|
||||
onPressed: () => _removeMedia(index),
|
||||
),
|
||||
),
|
||||
],
|
||||
|
|
@ -230,7 +249,10 @@ class RepairedPhotoSection extends StatelessWidget {
|
|||
final int maxCount;
|
||||
final MediaType mediaType;
|
||||
final String title;
|
||||
final List<String>? initialMediaPaths;
|
||||
final ValueChanged<List<File>> onChanged;
|
||||
final ValueChanged<String>? onMediaAdded;
|
||||
final ValueChanged<String>? onMediaRemoved;
|
||||
final VoidCallback onAiIdentify;
|
||||
final bool isShowAI;
|
||||
final double horizontalPadding;
|
||||
|
|
@ -240,10 +262,13 @@ class RepairedPhotoSection extends StatelessWidget {
|
|||
this.maxCount = 4,
|
||||
this.mediaType = MediaType.image,
|
||||
required this.title,
|
||||
this.initialMediaPaths,
|
||||
this.isShowAI = false,
|
||||
required this.onChanged,
|
||||
required this.onAiIdentify,
|
||||
this.horizontalPadding = 10,
|
||||
this.onMediaAdded,
|
||||
this.onMediaRemoved,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
|
|
@ -257,7 +282,7 @@ class RepairedPhotoSection extends StatelessWidget {
|
|||
padding: EdgeInsets.symmetric(horizontal: horizontalPadding),
|
||||
child: ListItemFactory.createRowSpaceBetweenItem(
|
||||
leftText: title,
|
||||
rightText: '0/$maxCount',
|
||||
rightText: '${initialMediaPaths?.length ?? 0}/$maxCount',
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
|
|
@ -265,7 +290,10 @@ class RepairedPhotoSection extends StatelessWidget {
|
|||
child: MediaPickerRow(
|
||||
maxCount: maxCount,
|
||||
mediaType: mediaType,
|
||||
initialMediaPaths: initialMediaPaths,
|
||||
onChanged: onChanged,
|
||||
onMediaAdded: onMediaAdded,
|
||||
onMediaRemoved: onMediaRemoved,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
|
|
|
|||
|
|
@ -714,7 +714,7 @@ U6Hzm1ninpWeE+awIDAQAB
|
|||
data: {
|
||||
"CORPINFO_ID":SessionService.instance.corpinfoId,
|
||||
"HOTWORK_ID": homeWorkId,
|
||||
"USER_ID":SessionService.instance.loginUserId,
|
||||
"CONFIRM_ID":SessionService.instance.loginUserId,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
|
@ -801,6 +801,60 @@ U6Hzm1ninpWeE+awIDAQAB
|
|||
);
|
||||
}
|
||||
|
||||
/// 上传图片
|
||||
static Future<Map<String, dynamic>> uploadSaveFile (
|
||||
String filePath,
|
||||
) async {
|
||||
final Map<String, dynamic> data = {
|
||||
"CORPINFO_ID":SessionService.instance.corpinfoId,
|
||||
};
|
||||
// 把文件路径填成 MultipartFile
|
||||
final path = filePath;
|
||||
data['file'] = await MultipartFile.fromFile(
|
||||
path,
|
||||
filename: path.split(Platform.pathSeparator).last,
|
||||
);
|
||||
return HttpManager().uploadFaceImage(
|
||||
baseUrl: basePath,
|
||||
path: '/app/eightwork/saveFile',
|
||||
fromData: data,
|
||||
);
|
||||
}
|
||||
///删除图片
|
||||
static Future<Map<String, dynamic>> deleteSaveFile(String FILE_PATH) {
|
||||
return HttpManager().request(
|
||||
basePath,
|
||||
'/app/eightwork/deleteFile',
|
||||
method: Method.post,
|
||||
data: {
|
||||
"FILE_PATH": FILE_PATH,
|
||||
},
|
||||
);
|
||||
}
|
||||
/// 安全措施个项保存
|
||||
static Future<Map<String, dynamic>> saveDangerousOptionsFile (
|
||||
List<String> filePaths,
|
||||
) async {
|
||||
// 复制一份 formData
|
||||
final Map<String, dynamic> data = {
|
||||
"CORPINFO_ID":SessionService.instance.corpinfoId,
|
||||
};
|
||||
// 把文件路径填成 MultipartFile
|
||||
for (var i = 0; i < filePaths.length; i++) {
|
||||
final path = filePaths[i];
|
||||
data['file$i'] = await MultipartFile.fromFile(
|
||||
path,
|
||||
filename: path.split(Platform.pathSeparator).last,
|
||||
);
|
||||
}
|
||||
return HttpManager().uploadFaceImage(
|
||||
baseUrl: basePath,
|
||||
path: '/app/eightwork/saveDangerousOptionsFile',
|
||||
fromData: data,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
///TODO -------------–-------------------- 我的 -------------–--------------------
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ class MyApp extends StatelessWidget {
|
|||
),
|
||||
primarySwatch: Colors.blue,
|
||||
// 统一设置页面背景颜色
|
||||
scaffoldBackgroundColor: const Color(0xFFF5F7FA), // 浅灰色背景
|
||||
scaffoldBackgroundColor: const Color(0xFFF1F1F1), // 浅灰色背景
|
||||
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
|
||||
inputDecorationTheme: const InputDecorationTheme(
|
||||
border: InputBorder.none,
|
||||
|
|
|
|||
|
|
@ -1,13 +1,17 @@
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:qhd_prevention/customWidget/custom_button.dart';
|
||||
|
||||
import '../../../customWidget/single_image_viewer.dart';
|
||||
import '../../../tools/tools.dart';
|
||||
|
||||
class ItemListWidget {
|
||||
|
||||
static const Color detailtextColor = Colors.black54;
|
||||
/// 单行水平排列:
|
||||
/// - 可编辑时:标题 + TextField
|
||||
/// - 不可编辑时:标题 + 带省略号的文本
|
||||
|
||||
static const Color detailtextColor = Colors.black54;
|
||||
|
||||
static Widget singleLineTitleText({
|
||||
required String label, // 标题文本
|
||||
required bool isEditable, // 是否可编辑
|
||||
|
|
|
|||
|
|
@ -35,7 +35,13 @@ class WorkDetailFormWidget extends StatelessWidget {
|
|||
this.relatedController,
|
||||
this.riskController,
|
||||
}) : assert(
|
||||
!isEditable || (contentController != null && locationController != null && methodController != null && hotworkPersonController != null && relatedController != null && riskController != null),
|
||||
!isEditable ||
|
||||
(contentController != null &&
|
||||
locationController != null &&
|
||||
methodController != null &&
|
||||
hotworkPersonController != null &&
|
||||
relatedController != null &&
|
||||
riskController != null),
|
||||
'Editable mode requires all TextEditingController parameters',
|
||||
),
|
||||
super(key: key);
|
||||
|
|
@ -43,7 +49,14 @@ class WorkDetailFormWidget extends StatelessWidget {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final pd = this.pd;
|
||||
return Column(
|
||||
return
|
||||
Container(
|
||||
padding: EdgeInsets.symmetric(vertical: 10),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(5),
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
ItemListWidget.singleLineTitleText(
|
||||
|
|
@ -116,7 +129,8 @@ class WorkDetailFormWidget extends StatelessWidget {
|
|||
onTap: () async {
|
||||
final val = await showDialog<String>(
|
||||
context: context,
|
||||
builder: (_) => SelectionPopup(
|
||||
builder:
|
||||
(_) => SelectionPopup(
|
||||
type: 'assignments',
|
||||
initialValue: pd['SPECIAL_WORK'] ?? '',
|
||||
onConfirm: (v) => Navigator.of(context).pop(v),
|
||||
|
|
@ -136,7 +150,8 @@ class WorkDetailFormWidget extends StatelessWidget {
|
|||
onTap: () async {
|
||||
final val = await showDialog<String>(
|
||||
context: context,
|
||||
builder: (_) => SelectionPopup(
|
||||
builder:
|
||||
(_) => SelectionPopup(
|
||||
type: 'identification',
|
||||
initialValue: pd['RISK_IDENTIFICATION'] ?? '',
|
||||
onConfirm: (v) => Navigator.of(context).pop(v),
|
||||
|
|
@ -158,6 +173,9 @@ class WorkDetailFormWidget extends StatelessWidget {
|
|||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,264 @@
|
|||
import 'dart:io';
|
||||
import 'dart:ui';
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:image_picker/image_picker.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:qhd_prevention/customWidget/ItemWidgetFactory.dart';
|
||||
import 'package:qhd_prevention/http/ApiService.dart';
|
||||
import 'package:qhd_prevention/http/HttpManager.dart';
|
||||
import 'package:qhd_prevention/pages/home/tap/item_list_widget.dart';
|
||||
import 'package:qhd_prevention/pages/my_appbar.dart';
|
||||
|
||||
import '../../../../../../customWidget/custom_button.dart';
|
||||
import '../../../../../../customWidget/photo_picker_row.dart';
|
||||
import '../../../../../../customWidget/single_image_viewer.dart';
|
||||
import '../../../../../../tools/tools.dart';
|
||||
import '../../../../../mine/mine_sign_page.dart';
|
||||
|
||||
/// 本地路径 + 线上路径模型
|
||||
class ImageData {
|
||||
String localPath;
|
||||
String? serverPath;
|
||||
ImageData({required this.localPath, this.serverPath});
|
||||
}
|
||||
|
||||
class DangerousOptionsPage extends StatefulWidget {
|
||||
final int index;
|
||||
final int status;
|
||||
final String measures;
|
||||
final List<ImageData> imgList;
|
||||
final List<String> signImgList;
|
||||
|
||||
const DangerousOptionsPage({
|
||||
Key? key,
|
||||
required this.index,
|
||||
this.status = 1,
|
||||
this.measures = '',
|
||||
this.imgList = const [],
|
||||
this.signImgList = const [],
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
_DangerousOptionsPageState createState() => _DangerousOptionsPageState();
|
||||
}
|
||||
|
||||
class _DangerousOptionsPageState extends State<DangerousOptionsPage> {
|
||||
late int index;
|
||||
late int status;
|
||||
late String measures;
|
||||
late List<ImageData> imgList;
|
||||
late List<String> signImgList;
|
||||
List<String> signTimes = [];
|
||||
|
||||
bool buttonLoading = false;
|
||||
final Dio _dio = Dio();
|
||||
final _picker = ImagePicker();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
index = widget.index;
|
||||
status = widget.status;
|
||||
measures = widget.measures;
|
||||
imgList = List<ImageData>.from(widget.imgList);
|
||||
signImgList = List<String>.from(widget.signImgList);
|
||||
}
|
||||
|
||||
/// 拍照或选图后的回调
|
||||
Future<void> _onImageAdded(String localPath) async {
|
||||
// 上传到服务器
|
||||
final res = await ApiService.uploadSaveFile(localPath);
|
||||
final url = res['FILE_PATH'] as String;
|
||||
setState(() {
|
||||
imgList.add(ImageData(localPath: localPath, serverPath: url));
|
||||
});
|
||||
}
|
||||
|
||||
/// 删除图片处理:调用删除接口并更新列表
|
||||
Future<void> _onImageRemoved(ImageData item) async {
|
||||
if (item.serverPath != null) {
|
||||
await ApiService.deleteSaveFile(item.serverPath!);
|
||||
}
|
||||
setState(() {
|
||||
imgList.remove(item);
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> _submit() async {
|
||||
if (signImgList.isEmpty) {
|
||||
ScaffoldMessenger.of(context)
|
||||
.showSnackBar(SnackBar(content: Text('请签字')));
|
||||
return;
|
||||
}
|
||||
await ApiService.saveDangerousOptionsFile(signImgList);
|
||||
setState(() => buttonLoading = true);
|
||||
Navigator.pop(context, {
|
||||
'imgList': imgList.map((e) => {'local': e.localPath, 'remote': e.serverPath}).toList(),
|
||||
'signImgList': signImgList,
|
||||
'index': index,
|
||||
'status': status,
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> _sign() async {
|
||||
final path = await Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(builder: (c) => MineSignPage()),
|
||||
);
|
||||
if (path != null) {
|
||||
final now = DateFormat('yyyy-MM-dd HH:mm').format(DateTime.now());
|
||||
setState(() {
|
||||
signImgList.add(path);
|
||||
signTimes.add(now);
|
||||
});
|
||||
FocusHelper.clearFocus(context);
|
||||
}
|
||||
}
|
||||
|
||||
Widget _signListWidget() {
|
||||
return Column(
|
||||
children: signImgList.map((path) {
|
||||
final idx = signImgList.indexOf(path);
|
||||
return Column(
|
||||
children: [
|
||||
const SizedBox(height: 10),
|
||||
const Divider(),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
GestureDetector(
|
||||
child: ConstrainedBox(
|
||||
constraints: const BoxConstraints(maxWidth: 200, maxHeight: 150),
|
||||
child: Image.file(File(path), fit: BoxFit.contain),
|
||||
),
|
||||
onTap: () => presentOpaque(SingleImageViewer(imageUrl: path), context),
|
||||
),
|
||||
Column(
|
||||
children: [
|
||||
CustomButton(
|
||||
text: '删除',
|
||||
height: 30,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10),
|
||||
backgroundColor: Colors.red,
|
||||
onPressed: () {
|
||||
setState(() => signImgList.removeAt(idx));
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 80),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
}).toList(),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: MyAppbar(title: '安全措施'),
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.all(12.0),
|
||||
child: Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 10, vertical: 10),
|
||||
color: Colors.white,
|
||||
child: ListView(
|
||||
children: [
|
||||
Table(
|
||||
border: TableBorder.all(color: Colors.grey.shade300),
|
||||
columnWidths: {0: FlexColumnWidth(3), 1: FlexColumnWidth(2)},
|
||||
children: [
|
||||
TableRow(
|
||||
decoration: BoxDecoration(color: Colors.grey.shade200),
|
||||
children: [
|
||||
Padding(
|
||||
padding: EdgeInsets.all(10),
|
||||
child: Center(
|
||||
child: Text('主要安全措施', style: TextStyle(fontWeight: FontWeight.bold)),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.all(10),
|
||||
child: Center(
|
||||
child: Text('操作', style: TextStyle(fontWeight: FontWeight.bold)),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
TableRow(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 5),
|
||||
child: Text(measures),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(0),
|
||||
child: Column(
|
||||
children: [
|
||||
RadioListTile<int>(
|
||||
value: -1,
|
||||
groupValue: status,
|
||||
title: Text('不涉及'),
|
||||
contentPadding: const EdgeInsets.symmetric(vertical: 0, horizontal: 8.0),
|
||||
visualDensity: VisualDensity(vertical: -4, horizontal: 0),
|
||||
onChanged: (v) => setState(() => status = v!),
|
||||
),
|
||||
RadioListTile<int>(
|
||||
value: 1,
|
||||
groupValue: status,
|
||||
title: Text('涉及'),
|
||||
contentPadding: const EdgeInsets.symmetric(vertical: 4.0, horizontal: 8.0),
|
||||
visualDensity: VisualDensity(vertical: -4, horizontal: 0),
|
||||
onChanged: (v) => setState(() => status = v!),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
RepairedPhotoSection(
|
||||
title: '上传图片',
|
||||
maxCount: 2,
|
||||
mediaType: MediaType.image,
|
||||
initialMediaPaths: imgList.map((e) => e.localPath).toList(),
|
||||
onChanged: (paths) {},
|
||||
onMediaAdded: _onImageAdded,
|
||||
onMediaRemoved: (path) {
|
||||
final item = imgList.firstWhere((e) => e.localPath == path);
|
||||
_onImageRemoved(item);
|
||||
},
|
||||
onAiIdentify: () {},
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text('签字:', style: TextStyle(fontSize: 16)),
|
||||
CustomButton(
|
||||
text: '新增手写签字',
|
||||
height: 36,
|
||||
backgroundColor: Colors.green,
|
||||
onPressed: _sign,
|
||||
),
|
||||
],
|
||||
),
|
||||
if (signImgList.isNotEmpty) _signListWidget(),
|
||||
const SizedBox(height: 30),
|
||||
CustomButton(
|
||||
text: '保存',
|
||||
backgroundColor: Colors.blue,
|
||||
onPressed: buttonLoading ? null : _submit,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,6 @@
|
|||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:qhd_prevention/customWidget/ItemWidgetFactory.dart';
|
||||
|
|
@ -10,8 +9,8 @@ import 'package:qhd_prevention/customWidget/department_person_picker.dart';
|
|||
import 'package:qhd_prevention/customWidget/department_picker.dart';
|
||||
import 'package:qhd_prevention/customWidget/toast_util.dart';
|
||||
import 'package:qhd_prevention/pages/home/tap/item_list_widget.dart';
|
||||
import 'package:qhd_prevention/pages/home/tap/tabList/special_wrok/aqcs_work_detail/dangerous_options_page.dart';
|
||||
import 'package:qhd_prevention/tools/tools.dart';
|
||||
import '../../../../../../customWidget/bottom_picker.dart';
|
||||
import '../../../../../../customWidget/custom_alert_dialog.dart';
|
||||
import '../../../../../../customWidget/single_image_viewer.dart';
|
||||
import '../../../../../../http/ApiService.dart';
|
||||
|
|
@ -20,6 +19,7 @@ import '../../../../../my_appbar.dart';
|
|||
import '../../special_Wrok/dh_work_detai/MeasuresListWidget.dart';
|
||||
import '../../special_Wrok/qtfx_work_detail/hotwork_gas_list.dart';
|
||||
import '../WorkDetailFormWidget.dart';
|
||||
|
||||
/// 安全措施确认
|
||||
class HotworkSafeFuncSure extends StatefulWidget {
|
||||
const HotworkSafeFuncSure({
|
||||
|
|
@ -45,6 +45,8 @@ class _HotworkSafeFuncSureState extends State<HotworkSafeFuncSure> {
|
|||
/// 详情
|
||||
late Map<String, dynamic> pd = {};
|
||||
late List<Map<String, dynamic>> measuresList = [];
|
||||
/// 其他安全措施
|
||||
final TextEditingController _otherController = TextEditingController();
|
||||
|
||||
/// 动火人及证书编号
|
||||
late List<dynamic> workUserList = [];
|
||||
|
|
@ -67,18 +69,6 @@ class _HotworkSafeFuncSureState extends State<HotworkSafeFuncSure> {
|
|||
return jsonEncode(jsonList);
|
||||
}
|
||||
|
||||
Widget _card(Widget child) {
|
||||
return Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(5),
|
||||
),
|
||||
child: child,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// 弹出单位选择
|
||||
void chooseUnitHandle(MeasureItem item) {
|
||||
showModalBottomSheet(
|
||||
|
|
@ -87,7 +77,8 @@ class _HotworkSafeFuncSureState extends State<HotworkSafeFuncSure> {
|
|||
barrierColor: Colors.black54,
|
||||
backgroundColor: Colors.transparent,
|
||||
builder:
|
||||
(_) => DepartmentPicker(
|
||||
(_) =>
|
||||
DepartmentPicker(
|
||||
onSelected: (id, name) async {
|
||||
setState(() {
|
||||
item.DEPARTMENT_ID = id;
|
||||
|
|
@ -265,7 +256,8 @@ class _HotworkSafeFuncSureState extends State<HotworkSafeFuncSure> {
|
|||
await showDialog<String>(
|
||||
context: context,
|
||||
builder:
|
||||
(_) => CustomAlertDialog(
|
||||
(_) =>
|
||||
CustomAlertDialog(
|
||||
title: '作废原因',
|
||||
mode: DialogMode.input,
|
||||
hintText: '请输入作废原因',
|
||||
|
|
@ -294,7 +286,8 @@ class _HotworkSafeFuncSureState extends State<HotworkSafeFuncSure> {
|
|||
await showDialog<String>(
|
||||
context: context,
|
||||
builder:
|
||||
(_) => CustomAlertDialog(
|
||||
(_) =>
|
||||
CustomAlertDialog(
|
||||
title: '提示',
|
||||
content: '请确认' + (status == '1' ? "通过" : "作废") + '本作业票?',
|
||||
cancelText: '取消',
|
||||
|
|
@ -380,6 +373,44 @@ class _HotworkSafeFuncSureState extends State<HotworkSafeFuncSure> {
|
|||
});
|
||||
}
|
||||
|
||||
Future<void> _itemToSign(Map<String, dynamic> measures, int index) async {
|
||||
// 签名图片列表
|
||||
final List<String> signImgList = measures['SIGN_ITEM'] ?? [];
|
||||
|
||||
// 操作图片路径列表
|
||||
final List<ImageData> imgList = [];
|
||||
if ((measures['IMG_PATH'] as String?)?.isNotEmpty ?? false) {
|
||||
for (var path in (measures['IMG_PATH'] as String).split(',')) {
|
||||
|
||||
imgList.add(ImageData(localPath: path));
|
||||
}
|
||||
}
|
||||
final result = await pushPage(DangerousOptionsPage(index: index,status: measures['STATUS'] ?? 1,
|
||||
measures: measures['PROTECTIVE_MEASURES'] ?? '',
|
||||
imgList: imgList,
|
||||
signImgList: signImgList), context);
|
||||
if (result != null) {
|
||||
setState(() {
|
||||
// 更新返回的图片列表(local + remote)
|
||||
final returned = result['imgList'] as List<dynamic>;
|
||||
measures['IMG_PATH'] = returned.map((m) {
|
||||
return ImageData(
|
||||
localPath: m['local'] as String,
|
||||
serverPath: m['remote'] as String?,
|
||||
);
|
||||
}).toList();
|
||||
|
||||
// 更新签字列表
|
||||
measures['SIGN_ITEM'] = List<String>.from(result['signImgList'] as List);
|
||||
|
||||
// 更新状态、序号等
|
||||
measures['STATUS'] = result['status'];
|
||||
index = result['index'] as int;
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// 安全防护措施
|
||||
Widget _setSafeDetailWidget() {
|
||||
return Container(
|
||||
|
|
@ -390,10 +421,10 @@ class _HotworkSafeFuncSureState extends State<HotworkSafeFuncSure> {
|
|||
padding: EdgeInsets.symmetric(horizontal: 5),
|
||||
child: Column(
|
||||
children: [
|
||||
if (measuresList.length > 0)
|
||||
if (measuresList.isNotEmpty)
|
||||
Column(
|
||||
children: [
|
||||
SizedBox(height: 20),
|
||||
SizedBox(height: 5),
|
||||
ListItemFactory.createBuildSimpleSection('安全防护措施'),
|
||||
Container(
|
||||
color: Colors.white,
|
||||
|
|
@ -401,10 +432,19 @@ class _HotworkSafeFuncSureState extends State<HotworkSafeFuncSure> {
|
|||
measuresList:
|
||||
measuresList, // List<Map<String, dynamic>>
|
||||
baseImgPath: ApiService.baseImgPath,
|
||||
isAllowEdit: true,
|
||||
onSign: (item) {
|
||||
_itemToSign(item, measuresList.indexOf(item));
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
ItemListWidget.singleLineTitleText(label: '其他安全措施:',
|
||||
isEditable: true,
|
||||
hintText: '请输入其他安全措施',
|
||||
controller
|
||||
:_otherController),
|
||||
SizedBox(height: 20),
|
||||
|
||||
Row(
|
||||
|
|
@ -468,13 +508,11 @@ class _HotworkSafeFuncSureState extends State<HotworkSafeFuncSure> {
|
|||
padding: EdgeInsets.all(12),
|
||||
child: Column(
|
||||
children: [
|
||||
// _card(_defaultDetail()),
|
||||
_card(
|
||||
WorkDetailFormWidget(
|
||||
pd: pd,
|
||||
isEditable: false,
|
||||
onChooseLevel: (){},
|
||||
onChooseHotworkUser: (){},
|
||||
onChooseLevel: () {},
|
||||
onChooseHotworkUser: () {},
|
||||
onAnalyzeTap: () {
|
||||
pushPage(
|
||||
HotworkGasList(HOTWORK_ID: widget.HOTWORK_ID),
|
||||
|
|
@ -482,7 +520,6 @@ class _HotworkSafeFuncSureState extends State<HotworkSafeFuncSure> {
|
|||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
SizedBox(height: 20),
|
||||
_setSafeDetailWidget(),
|
||||
SizedBox(height: 20),
|
||||
|
|
@ -514,7 +551,8 @@ class MeasureItem {
|
|||
List<Map<String, dynamic>>? userList,
|
||||
this.userIndex = -1,
|
||||
List<Map<String, dynamic>>? selectMeasures,
|
||||
}) : userList = userList ?? [],
|
||||
})
|
||||
: userList = userList ?? [],
|
||||
selectMeasures = selectMeasures ?? [];
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
|
|
|
|||
|
|
@ -11,18 +11,31 @@ import '../../../../../../tools/tools.dart';
|
|||
import 'hotwork_apply_detail.dart';
|
||||
|
||||
/// 表格组件,用于展示“安全防护措施”列表
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
/// 主安全措施列表组件,支持编辑与只读模式
|
||||
class MeasuresListWidget extends StatelessWidget {
|
||||
const MeasuresListWidget({
|
||||
super.key,
|
||||
required this.measuresList,
|
||||
required this.baseImgPath,
|
||||
required this.isAllowEdit,
|
||||
this.onSign,
|
||||
});
|
||||
/// 接口返回的原始 Map 列表
|
||||
final List<Map<String, dynamic>> measuresList;
|
||||
|
||||
/// 图片的基础路径
|
||||
final String baseImgPath;
|
||||
|
||||
const MeasuresListWidget({
|
||||
Key? key,
|
||||
required this.measuresList,
|
||||
required this.baseImgPath,
|
||||
}) : super(key: key);
|
||||
/// 是否允许编辑(输入答案 & 签字按钮)
|
||||
final bool isAllowEdit;
|
||||
|
||||
/// 签字按钮回调,回调当前行 item
|
||||
final void Function(Map<String, dynamic> item)? onSign;
|
||||
|
||||
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
|
@ -98,30 +111,44 @@ class MeasuresListWidget extends StatelessWidget {
|
|||
item['SIGN_TIME'] as String? ?? '',
|
||||
),
|
||||
|
||||
// 问题1~4 + 答案
|
||||
// 问题1~4 + 答案(可编辑或只读)
|
||||
for (var i = 1; i <= 4; i++)
|
||||
if (item.containsKey('QUESTION$i'))
|
||||
_buildQnA(
|
||||
item['QUESTION$i'] as String? ?? '',
|
||||
item['ANSWER$i'] as String? ?? '0',
|
||||
),
|
||||
if ((item['QUESTION$i'] as String?)?.isNotEmpty ?? false)
|
||||
_buildQnA(item, i),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
// 第二列:状态 + 图片
|
||||
// 第二列:状态文字/按钮 + 操作图片
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(8),
|
||||
child: Column(
|
||||
children: [
|
||||
// 状态
|
||||
Text(
|
||||
// 签字或状态
|
||||
isAllowEdit
|
||||
? TextButton(
|
||||
onPressed: () {
|
||||
if ((item['STATUS'] as String?) != '-1') {
|
||||
onSign?.call(item);
|
||||
}
|
||||
},
|
||||
child: Text(
|
||||
(item['SIGN_ITEM'] ?? '').toString().isNotEmpty
|
||||
? '已签字'
|
||||
: '签字',
|
||||
style: TextStyle(
|
||||
color: (item['STATUS'] as String?) == '-1'
|
||||
? Colors.grey
|
||||
: Colors.blue,
|
||||
),
|
||||
),
|
||||
)
|
||||
: Text(
|
||||
(item['STATUS'] as String?) == '-1'
|
||||
? '不涉及'
|
||||
: '涉及',
|
||||
style: TextStyle(
|
||||
color:
|
||||
(item['STATUS'] as String?) == '-1'
|
||||
color: (item['STATUS'] as String?) == '-1'
|
||||
? Colors.grey
|
||||
: Colors.black,
|
||||
),
|
||||
|
|
@ -148,27 +175,71 @@ class MeasuresListWidget extends StatelessWidget {
|
|||
);
|
||||
}
|
||||
|
||||
/// 构造“问题 + 答案”行
|
||||
Widget _buildQnA(String question, String answer) {
|
||||
/// 构造“问题 + 答案”行,编辑模式下显示数字输入框
|
||||
Widget _buildQnA(Map<String, dynamic> item, int index) {
|
||||
final question = item['QUESTION$index'] as String? ?? '';
|
||||
final key = 'ANSWER$index';
|
||||
final answer = item[key]?.toString() ?? '';
|
||||
|
||||
if (isAllowEdit) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(top: 8),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Text(
|
||||
'$question:',
|
||||
style: const TextStyle(fontWeight: FontWeight.w800),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
flex: 1,
|
||||
child: TextFormField(
|
||||
initialValue: answer,
|
||||
textAlign: TextAlign.center, // 输入文字居中对齐
|
||||
keyboardType: TextInputType.number,
|
||||
inputFormatters: [FilteringTextInputFormatter.digitsOnly],
|
||||
decoration: InputDecoration(
|
||||
isDense: true,
|
||||
contentPadding: const EdgeInsets.symmetric(vertical: 8, horizontal: 4),
|
||||
// 自定义边框颜色
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderSide: BorderSide(color: Colors.grey.shade300),
|
||||
),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderSide: BorderSide(color: Colors.grey.shade300),
|
||||
),
|
||||
),
|
||||
onChanged: (val) {
|
||||
item[key] = val;
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// 只读模式
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(top: 8),
|
||||
child: Column(
|
||||
children: [
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 12),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
'$question: ',
|
||||
'$question:',
|
||||
style: const TextStyle(fontWeight: FontWeight.w800),
|
||||
),
|
||||
Text(answer.isNotEmpty ? answer : '0'),
|
||||
],
|
||||
),
|
||||
),
|
||||
Divider(),
|
||||
const Divider(),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
|
@ -190,13 +261,12 @@ class MeasuresListWidget extends StatelessWidget {
|
|||
Navigator.of(context).push(
|
||||
PageRouteBuilder(
|
||||
opaque: false,
|
||||
pageBuilder:
|
||||
(_, __, ___) =>
|
||||
SingleImageViewer(imageUrl: '$baseImgPath$p'),
|
||||
pageBuilder: (_, __, ___) =>
|
||||
SingleImageViewer(imageUrl: '$baseImgPath\$p'),
|
||||
),
|
||||
);
|
||||
},
|
||||
child: Image.network('$baseImgPath$p', width: 80, height: 80),
|
||||
child: Image.network('$baseImgPath\$p', width: 80, height: 80),
|
||||
),
|
||||
if (time.isNotEmpty) ...[const SizedBox(width: 8), Text(time)],
|
||||
],
|
||||
|
|
@ -206,6 +276,7 @@ class MeasuresListWidget extends StatelessWidget {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/// 其他安全防护措施表格组件
|
||||
class OtherMeasuresWidget extends StatelessWidget {
|
||||
/// 其他安全防护措施数据列表
|
||||
|
|
@ -753,6 +824,7 @@ class _SelectionPopupState extends State<SelectionPopup> {
|
|||
});
|
||||
_getData();
|
||||
}
|
||||
|
||||
void _determine() {
|
||||
// 合并选中
|
||||
final result = selectValue.join(',');
|
||||
|
|
|
|||
|
|
@ -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/WorkDetailFormWidget.dart';
|
||||
import 'package:qhd_prevention/tools/h_colors.dart';
|
||||
import 'package:qhd_prevention/tools/tools.dart';
|
||||
import '../../../../../../customWidget/bottom_picker.dart';
|
||||
import '../../../../../../http/ApiService.dart';
|
||||
|
|
@ -188,6 +189,7 @@ class _HotworkApplyDetailState extends State<HotworkApplyDetail> {
|
|||
|
||||
Widget _card(Widget child) {
|
||||
return Container(
|
||||
padding: EdgeInsets.symmetric(vertical: 5),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(5),
|
||||
|
|
@ -283,22 +285,23 @@ class _HotworkApplyDetailState extends State<HotworkApplyDetail> {
|
|||
ToastUtil.showNormal(context, '请先选择$unitName');
|
||||
return;
|
||||
}
|
||||
|
||||
if (personList.isEmpty) { // 一般这种情况是因为重新编辑没有缓存对应部门的负责人,所以先拉取一下接口
|
||||
await _getPersonListForUnitId(unitId, type);
|
||||
final list = _personCache[type] ?? [];
|
||||
|
||||
if (list.isEmpty) { // 如果还是没数据,说明该部门没有可选的人
|
||||
ToastUtil.showNormal(context, '暂无数据,请选择其他单位');
|
||||
}else{
|
||||
choosePersonHandle(type);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (personList.isEmpty) {
|
||||
// 如果还是没数据,说明该部门没有可选的人
|
||||
ToastUtil.showNormal(context, '请先选择' + type.displayName);
|
||||
return;
|
||||
}
|
||||
// if (personList.isEmpty) { // 一般这种情况是因为重新编辑没有缓存对应部门的负责人,所以先拉取一下接口
|
||||
// await _getPersonListForUnitId(unitId, type);
|
||||
// final list = _personCache[type] ?? [];
|
||||
//
|
||||
// if (list.isEmpty) { // 如果还是没数据,说明该部门没有可选的人
|
||||
// ToastUtil.showNormal(context, '暂无数据,请选择其他单位');
|
||||
// }else{
|
||||
// choosePersonHandle(type);
|
||||
// }
|
||||
// return;
|
||||
// }
|
||||
DepartmentPersonPicker.show(
|
||||
context,
|
||||
personsData: personList,
|
||||
|
|
@ -481,6 +484,7 @@ class _HotworkApplyDetailState extends State<HotworkApplyDetail> {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
backgroundColor: h_backGroundColor(),
|
||||
appBar: MyAppbar(title: '动火安全作业申请'),
|
||||
body: SafeArea(
|
||||
child: SingleChildScrollView(
|
||||
|
|
@ -584,6 +588,7 @@ class _HotworkApplyDetailState extends State<HotworkApplyDetail> {
|
|||
measuresList:
|
||||
measuresList, // List<Map<String, dynamic>>
|
||||
baseImgPath: ApiService.baseImgPath,
|
||||
isAllowEdit: false,
|
||||
),
|
||||
),
|
||||
],
|
||||
|
|
|
|||
|
|
@ -68,15 +68,7 @@ class _HotworkSetSafeDetailState extends State<HotworkSetSafeDetail> {
|
|||
return jsonEncode(jsonList);
|
||||
}
|
||||
|
||||
Widget _card(Widget child) {
|
||||
return Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(5),
|
||||
),
|
||||
child: child,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Widget _chooseItem(MeasureItem item) {
|
||||
return Column(
|
||||
|
|
@ -255,7 +247,7 @@ class _HotworkSetSafeDetailState extends State<HotworkSetSafeDetail> {
|
|||
);
|
||||
}
|
||||
|
||||
/// 提交 1 提交 0暂存
|
||||
/// 作废 -1 通过 1
|
||||
Future<void> _submit(String status) async {
|
||||
if (imagePaths.isEmpty) {
|
||||
ToastUtil.showNormal(context, '请签字');
|
||||
|
|
@ -572,7 +564,6 @@ class _HotworkSetSafeDetailState extends State<HotworkSetSafeDetail> {
|
|||
child: Column(
|
||||
children: [
|
||||
// _card(_defaultDetail()),
|
||||
_card(
|
||||
WorkDetailFormWidget(
|
||||
pd: pd,
|
||||
isEditable: false,
|
||||
|
|
@ -585,7 +576,6 @@ class _HotworkSetSafeDetailState extends State<HotworkSetSafeDetail> {
|
|||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
SizedBox(height: 20),
|
||||
_setSafeDetailWidget(),
|
||||
SizedBox(height: 20),
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import 'dart:ffi';
|
||||
import 'dart:ui';
|
||||
|
||||
Color h_backGroundColor() => Color(0xFFF5F7FA);
|
||||
Color h_backGroundColor() => Color(0xFFF1F1F1);
|
||||
List<Color> riskLevelTextColors() {
|
||||
return [Color(0xFFE54D42),Color(0xFFF37B1D),Color(0xFFF9BD08),Color(0xFF3281FF)];
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue