349 lines
11 KiB
Dart
349 lines
11 KiB
Dart
import 'dart:convert';
|
||
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';
|
||
|
||
class PromisePage extends StatefulWidget {
|
||
const PromisePage({super.key});
|
||
|
||
@override
|
||
State<PromisePage> createState() => _PromisePageState();
|
||
}
|
||
|
||
class _PromisePageState extends State<PromisePage> {
|
||
bool _loading = true;
|
||
|
||
Map<String, dynamic> info = {};
|
||
String? baseImgPath;
|
||
|
||
@override
|
||
void initState() {
|
||
super.initState();
|
||
_loadData();
|
||
}
|
||
|
||
Future<void> _loadData() async {
|
||
setState(() {
|
||
_loading = true;
|
||
});
|
||
|
||
try {
|
||
final Map<String, dynamic> payload =
|
||
await ApiService.safeCorppromiseDetail();
|
||
|
||
final coll = (payload['COLLATERAL'] as List?) ?? [];
|
||
final DETAIL =
|
||
coll.map((e) {
|
||
return {
|
||
'value': e?['COLLATERAL']?.toString() ?? '',
|
||
'id': e?['PROMISEDETAIL_ID']?.toString() ?? '',
|
||
};
|
||
}).toList();
|
||
|
||
final Map<String, dynamic> resolved = {};
|
||
if (payload['TEXT'] is Map) {
|
||
resolved.addAll(payload['TEXT'] as Map<String, dynamic>);
|
||
} else {
|
||
resolved['TEXT'] = payload['TEXT']?.toString() ?? '';
|
||
}
|
||
resolved['DETAIL'] = DETAIL;
|
||
resolved['SIGNTIME'] =
|
||
DateTime.now().millisecondsSinceEpoch.toString();
|
||
resolved['COVERPEOPLE'] =
|
||
(payload['COVERPEOPLE'] is List && payload['COVERPEOPLE'].isNotEmpty)
|
||
? payload['COVERPEOPLE'][0]['USERNAME']?.toString() ?? ''
|
||
: '';
|
||
// 合并其他顶层字段(保留现有字段)
|
||
if (payload is Map<String, dynamic>) {
|
||
payload.forEach((k, v) {
|
||
if (!resolved.containsKey(k)) resolved[k] = v;
|
||
});
|
||
}
|
||
resolved['PROMISEPEOPLE_ID'] = payload['PROMISEPEOPLE_ID'] ?? '';
|
||
|
||
setState(() {
|
||
info = resolved;
|
||
_loading = false;
|
||
});
|
||
} catch (e, st) {
|
||
debugPrint('safeCorppromiseDetail error: $e\n$st');
|
||
setState(() {
|
||
_loading = false;
|
||
});
|
||
ToastUtil.showNormal(context, '加载失败,请稍后重试');
|
||
}
|
||
}
|
||
|
||
String _formatDateShort(String? s) {
|
||
if (s == null) return '';
|
||
if (s.length >= 10) return s.substring(0, 10);
|
||
return s;
|
||
}
|
||
|
||
// 点击签字:导航到你自己实现的签字页面,等待返回签字路径(String)
|
||
Future<void> _sign() async {
|
||
await NativeOrientation.setLandscape();
|
||
final String path = await Navigator.push(
|
||
context,
|
||
MaterialPageRoute(builder: (c) => MineSignPage()),
|
||
);
|
||
if (path != null) {
|
||
setState(() {
|
||
info['FILEPATH'] = path;
|
||
});
|
||
FocusHelper.clearFocus(context);
|
||
}
|
||
}
|
||
|
||
// 提交:占位实现 —— 请把下面的逻辑替换为你项目的上传/提交 API(例如 ApiService.editPeopleII 或类似)
|
||
Future<void> submitSignedPromise() async {
|
||
LoadingDialogHelper.show();
|
||
final filePath = (info['FILEPATH'] ?? '').toString();
|
||
if (filePath.isEmpty) {
|
||
ToastUtil.showNormal(context, '请签字');
|
||
return;
|
||
}
|
||
final result = await ApiService.submitCorppromiseSign(filePath,info);
|
||
LoadingDialogHelper.hide();
|
||
if (result['result'] == 'success') {
|
||
ToastUtil.showSuccess(context, '提交成功');
|
||
Navigator.pushReplacement(
|
||
context,
|
||
MaterialPageRoute(builder: (_) => const MainPage()),
|
||
);
|
||
}
|
||
}
|
||
|
||
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), // 缩进2个汉字宽度
|
||
),
|
||
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((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')) {
|
||
signPreview = Image.network(
|
||
(baseImgPath ?? '') + 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 {
|
||
signPreview = const SizedBox.shrink();
|
||
}
|
||
|
||
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(height: 8),
|
||
GestureDetector(
|
||
onTap: () {
|
||
presentOpaque(
|
||
SingleImageViewer(imageUrl: info['FILEPATH'] ?? ''),
|
||
context,
|
||
);
|
||
},
|
||
child: signPreview,
|
||
),
|
||
const SizedBox(height: 8),
|
||
CustomButton(
|
||
text:
|
||
(info['FILEPATH'] ?? '').toString().isNotEmpty
|
||
? '重签'
|
||
: '手写签字',
|
||
backgroundColor: Colors.blue,
|
||
padding: EdgeInsets.symmetric(
|
||
vertical: 0,
|
||
horizontal: 20,
|
||
),
|
||
height: 35,
|
||
onPressed: _sign,
|
||
),
|
||
],
|
||
),
|
||
),
|
||
],
|
||
),
|
||
const SizedBox(height: 10),
|
||
Row(
|
||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||
children: [
|
||
const SizedBox(),
|
||
Column(
|
||
crossAxisAlignment: CrossAxisAlignment.end,
|
||
children: [Text(signTime)],
|
||
),
|
||
],
|
||
),
|
||
],
|
||
),
|
||
);
|
||
}
|
||
|
||
@override
|
||
Widget build(BuildContext context) {
|
||
return Scaffold(
|
||
appBar: const MyAppbar(title: '安全承诺', isBack: false),
|
||
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: [
|
||
Row(
|
||
mainAxisAlignment: MainAxisAlignment.center,
|
||
children: [_buildTitle()],
|
||
),
|
||
_buildHeaderName(),
|
||
_buildParagraph(info['TEXT']?.toString() ?? ''),
|
||
_buildCollateralList(),
|
||
if ((info['TYPE'] ?? '').toString() == '0') ...[
|
||
_buildParagraph(
|
||
'若违反上述承诺和未履行安全生产职责,或发生责任事故的,接受政府或公司事故调查组做出的处罚决定。',
|
||
),
|
||
_buildParagraph(
|
||
'承诺期限自${_formatDateShort(info['PROMISE_TERM_START']?.toString())}至${_formatDateShort(info['PROMISE_TERM_END']?.toString())}。',
|
||
),
|
||
] else ...[
|
||
_buildParagraph(
|
||
'若未履行安全生产职责,或发生生产安全事故的,接受公司或政府事故调查组做出的处罚。',
|
||
),
|
||
_buildParagraph(
|
||
'责任期限自${_formatDateShort(info['PROMISE_TERM_START']?.toString())}至${_formatDateShort(info['PROMISE_TERM_END']?.toString())}。',
|
||
),
|
||
],
|
||
const SizedBox(height: 8),
|
||
_buildFooter(),
|
||
const SizedBox(height: 12),
|
||
SizedBox(
|
||
width: double.infinity,
|
||
child: CustomButton(
|
||
text: '提 交',
|
||
backgroundColor: Colors.blue,
|
||
onPressed: submitSignedPromise,
|
||
),
|
||
),
|
||
],
|
||
),
|
||
),
|
||
),
|
||
);
|
||
}
|
||
}
|