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 createState() => _PromisePageState(); } class _PromisePageState extends State { bool _loading = true; Map info = {}; String? baseImgPath; @override void initState() { super.initState(); _loadData(); } Future _loadData() async { setState(() { _loading = true; }); try { final Map 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 resolved = {}; if (payload['TEXT'] is Map) { resolved.addAll(payload['TEXT'] as Map); } 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) { 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 _sign() async { await NativeOrientation.setLandscape(); final String path = await Navigator.push( context, MaterialPageRoute(builder: (c) => MineSignPage()), ); await NativeOrientation.setPortrait(); if (path != null) { setState(() { info['FILEPATH'] = path; }); FocusHelper.clearFocus(context); } } // 提交:占位实现 —— 请把下面的逻辑替换为你项目的上传/提交 API(例如 ApiService.editPeopleII 或类似) Future 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.fill, ); } else if (signImagePath.isNotEmpty && File(signImagePath).existsSync()) { signPreview = Image.file( File(signImagePath), width: 100, height: 50, fit: BoxFit.fill, ); } 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, ), ), ], ), ), ), ); } }