flutter_integrated_whb/lib/pages/home/SafetyCommitment/other_promise_page.dart

356 lines
12 KiB
Dart
Raw Permalink Normal View History

2025-08-22 09:02:35 +08:00
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:qhd_prevention/customWidget/custom_button.dart';
import 'package:qhd_prevention/customWidget/single_image_viewer.dart';
import 'package:qhd_prevention/pages/main_tab.dart';
import 'package:qhd_prevention/pages/mine/mine_sign_page.dart';
import 'package:qhd_prevention/pages/my_appbar.dart';
import 'package:qhd_prevention/customWidget/toast_util.dart';
import 'package:qhd_prevention/http/ApiService.dart';
import 'package:qhd_prevention/tools/tools.dart';
/// 完整翻译自你提供的 uniapp 页面逻辑。
/// 注意:下面的 ApiService 方法名goEditII / editIsReadII / submitCorppromiseSign
/// 仅为示例占位,与你项目中实际的方法名若不同请替换。
class OtherPromisePage extends StatefulWidget {
const OtherPromisePage({
super.key,
required this.TabCur,
required this.PROMISE_ID,
required this.PROMISEPEOPLE_ID,
});
final int TabCur;
final String PROMISE_ID;
final String PROMISEPEOPLE_ID;
@override
State<OtherPromisePage> createState() => _OtherPromisePageState();
}
class _OtherPromisePageState extends State<OtherPromisePage> {
bool _loading = true;
Map<String, dynamic> info = {};
String? baseImgPath = ApiService.baseImgPath;
@override
void initState() {
super.initState();
// 按照原 uniapp 的 onLoad先获取数据
_loadData();
// 如果来自 TabCur == 1需要标记为已读uniapp 中是if(option.TabCur=='1') this.setPromiseIsRead
if (widget.TabCur == 1) {
_setPromiseIsRead();
}
}
Future<void> _loadData() async {
setState(() => _loading = true);
try {
// 请将下面的方法替换为你项目中实际的 ApiService 调用并传入 widget.PROMISE_ID / PROMISEPEOPLE_ID
final res = await ApiService.getWorkshopSafetyOtherCommitmen(
widget.PROMISE_ID,
widget.PROMISEPEOPLE_ID,
);
final coll = (res['promistDetail'] as List?) ?? (res['promistdetail'] as List?) ?? [];
final DETAIL = coll
.map((e) => {
'value': e?['COLLATERAL']?.toString() ?? e?['collateral']?.toString() ?? '',
'id': e?['PROMISEDETAIL_ID']?.toString() ?? e?['promiseDetail_id']?.toString() ?? '',
})
.toList();
final Map<String, dynamic> merged = {};
if (res['varList'] is Map) merged.addAll(Map<String, dynamic>.from(res['varList']));
if (res['people'] is Map) merged.addAll(Map<String, dynamic>.from(res['people']));
merged['TEXT'] = res['TEXT']?.toString() ?? res['text']?.toString() ?? merged['TEXT'] ?? '';
merged['DETAIL'] = DETAIL;
if (res['coverpeople'] is List && (res['coverpeople'] as List).isNotEmpty) {
merged['COVERPEOPLE'] = (res['coverpeople'][0]['USERNAME'] ?? res['coverpeople'][0]['username'])?.toString() ?? '';
} else if (res['coverpeople'] is String) {
merged['COVERPEOPLE'] = res['coverpeople'];
}
res.forEach((k, v) {
if (!merged.containsKey(k)) merged[k] = v;
});
merged['PROMISEPEOPLE_ID'] = res['PROMISEPEOPLE_ID'] ?? widget.PROMISEPEOPLE_ID;
merged['SIGNTIME'] = merged['SIGNTIME'] ?? merged['signtime'] ?? '';
merged['CREATTIME'] = merged['CREATTIME'] ?? merged['creattime'] ?? merged['CREATTIME'] ?? '';
setState(() {
info = merged;
_loading = false;
});
} catch (e, st) {
debugPrint('加载承诺详情失败:$e\n$st');
setState(() => _loading = false);
ToastUtil.showNormal(context, '加载失败,请稍后重试');
}
}
Future<void> _setPromiseIsRead() async {
try {
await ApiService.getWorkshopSafetyOthercorppromise(widget.PROMISEPEOPLE_ID);
} catch (e) {
debugPrint('标记已读失败: $e');
// 不打断用户流程uniapp 中也是静默处理失败
}
}
String _formatDateShort(dynamic s) {
if (s == null) return '';
final str = s.toString();
if (str.length >= 10) return str.substring(0, 10);
return str;
}
Future<void> _sign() async {
// 如果你的签字页面需要横屏,请在 MineSignPage 内或调用签字前后处理屏幕方向。
// 下面直接跳转并等待返回签名图片路径String与原 uniapp 的行为一致。
final result = await Navigator.push<String>(
context,
MaterialPageRoute(builder: (_) => const MineSignPage()),
);
if (result != null && result.isNotEmpty) {
setState(() {
info['FILEPATH'] = result;
});
// 清除焦点,防止键盘/输入问题
FocusScope.of(context).unfocus();
}
}
Future<void> submitSignedPromise() async {
final filePath = (info['FILEPATH'] ?? '').toString();
if (filePath.isEmpty) {
ToastUtil.showNormal(context, '请签字');
return;
}
try {
LoadingDialogHelper.show();
// 请替换为你项目的实际提交方法和参数;下面示例使用 submitCorppromiseSign(filePath, info)
final res = await ApiService.submitCorppromiseSign(filePath, info);
LoadingDialogHelper.hide();
if (res is Map && (res['result'] == 'success' || res['code'] == 0 || res['status'] == 'success')) {
ToastUtil.showSuccess(context, '提交成功');
// 和 uniapp 行为类似:提交后导航回主页面
Navigator.pushReplacement(context, MaterialPageRoute(builder: (_) => const MainPage()));
} else {
final msg = (res is Map) ? (res['message'] ?? res['msg'] ?? '提交失败') : '提交失败';
ToastUtil.showNormal(context, msg.toString());
}
} catch (e, st) {
LoadingDialogHelper.hide();
debugPrint('提交签字失败:$e\n$st');
ToastUtil.showNormal(context, '提交失败,请重试');
}
}
Widget _buildTitle() {
final type = (info['TYPE'] ?? '').toString();
final title = type == '0' ? '安全生产承诺书' : '安全生产责任状';
return Padding(
padding: const EdgeInsets.symmetric(vertical: 12.0),
child: Text(
title,
style: const TextStyle(fontSize: 22, fontWeight: FontWeight.bold),
textAlign: TextAlign.center,
),
);
}
Widget _buildHeaderName() {
final type = (info['TYPE'] ?? '').toString();
if (type == '0') {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0),
child: Text(
'${info['COVERPEOPLE'] ?? ''}',
style: const TextStyle(fontSize: 16),
),
);
}
return const SizedBox.shrink();
}
Widget _buildParagraph(String text) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 8.0),
child: RichText(
textAlign: TextAlign.justify,
text: TextSpan(
style: const TextStyle(
height: 1.6,
letterSpacing: 0.5,
color: Colors.black,
),
children: [
const WidgetSpan(child: SizedBox(width: 28)),
TextSpan(text: text),
],
),
),
);
}
Widget _buildCollateralList() {
final detail = (info['DETAIL'] as List?) ?? [];
if (detail.isEmpty) return const SizedBox.shrink();
return Padding(
padding: const EdgeInsets.only(left: 0, right: 8.0, top: 6.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: detail.map<Widget>((e) {
return _buildParagraph(e['value']?.toString() ?? '');
}).toList(),
),
);
}
Widget _buildFooter() {
final type = (info['TYPE'] ?? '').toString();
final signImagePath = (info['FILEPATH'] ?? '').toString();
final signTime = (info['SIGNTIME'] ?? '').toString();
final creatTime = (info['CREATTIME'] ?? '').toString();
Widget signPreview;
if (signImagePath.isNotEmpty && (signImagePath.startsWith('http') || signImagePath.startsWith('https'))) {
signPreview = Image.network(
signImagePath,
width: 100,
height: 50,
fit: BoxFit.cover,
);
} else if (signImagePath.isNotEmpty && File(signImagePath).existsSync()) {
signPreview = Image.file(
File(signImagePath),
width: 100,
height: 50,
fit: BoxFit.cover,
);
} else if (signImagePath.isNotEmpty && baseImgPath != null) {
// 如果后端只给了相对路径,前端需要拼接 baseImgPath
signPreview = Image.network(
'${baseImgPath!}$signImagePath',
width: 100,
height: 50,
fit: BoxFit.cover,
);
} else {
signPreview = const SizedBox(width: 100, height: 50);
}
return Padding(
padding: const EdgeInsets.only(top: 12.0, left: 8.0, right: 8.0, bottom: 20.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
if (type == '0')
const Align(alignment: Alignment.centerRight, child: Text('承诺单位(盖章)')),
if (type == '1')
Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Text('发状人:${info['COVERPEOPLE'] ?? ''}'),
const SizedBox(height: 6),
Text(creatTime.isNotEmpty ? _formatDateShort(creatTime) : ''),
],
),
const SizedBox(height: 12),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: Row(
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisAlignment: MainAxisAlignment.end,
children: [
Text(type == '0' ? '主要负责人签字:' : '受状人:'),
const SizedBox(width: 8),
GestureDetector(
onTap: () {
if ((info['FILEPATH'] ?? '').toString().isNotEmpty) {
presentOpaque(
SingleImageViewer(imageUrl: info['FILEPATH'] ?? ''),
context,
);
}
},
child: signPreview,
),
],
),
),
],
),
const SizedBox(height: 10),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const SizedBox(),
Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: [Text(signTime.isNotEmpty ? _formatDateShort(signTime) : '')],
),
],
),
],
),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: const MyAppbar(title: '安全承诺'),
body: _loading
? const Center(child: CircularProgressIndicator())
: SingleChildScrollView(
child: Container(
color: Colors.white,
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 5),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Center(child: _buildTitle()),
_buildHeaderName(),
_buildParagraph(info['TEXT']?.toString() ?? ''),
_buildCollateralList(),
if ((info['TYPE'] ?? '').toString() == '0') ...[
_buildParagraph(
'若违反上述承诺和未履行安全生产职责,或发生责任事故的,接受政府或公司事故调查组做出的处罚决定。',
),
_buildParagraph(
'承诺期限自${_formatDateShort(info['PROMISE_TERM_START'])}${_formatDateShort(info['PROMISE_TERM_END'])}',
),
] else ...[
_buildParagraph(
'若未履行安全生产职责,或发生生产安全事故的,接受公司或政府事故调查组做出的处罚。',
),
_buildParagraph(
'责任期限自${_formatDateShort(info['PROMISE_TERM_START'])}${_formatDateShort(info['PROMISE_TERM_END'])}',
),
],
const SizedBox(height: 8),
_buildFooter(),
],
),
),
),
);
}
}