hs 2025-09-05 11:27:45 +08:00
parent 019fff8329
commit 4055de6723
11 changed files with 456 additions and 312 deletions

View File

@ -24,6 +24,7 @@ class ApiService {
"http://192.168.20.240:8500/whb_stu_face/"; "http://192.168.20.240:8500/whb_stu_face/";
/// ///
// static const String basePath = "https://qaaqwh.qhdsafety.com/integrated_whb"; // static const String basePath = "https://qaaqwh.qhdsafety.com/integrated_whb";
// static const String basePath = "http://192.168.20.240:8500/integrated_whb";
static const String basePath = "http://192.168.20.240:8500/integrated_whb"; static const String basePath = "http://192.168.20.240:8500/integrated_whb";
// static const String basePath = "http://192.168.0.37:8099/api"; // static const String basePath = "http://192.168.0.37:8099/api";
@ -1581,8 +1582,8 @@ U6Hzm1ninpWeE+awIDAQAB
"CORPINFO_ID": SessionService.instance.corpinfoId, "CORPINFO_ID": SessionService.instance.corpinfoId,
"USER_ID": SessionService.instance.loginUserId, "USER_ID": SessionService.instance.loginUserId,
"OPERATOR": SessionService.instance.loginUserId, "OPERATOR": SessionService.instance.loginUserId,
"NAME": SessionService.instance.loginUser?["USERNAME"] ?? "", "NAME": SessionService.instance.username,
"USERNAME": SessionService.instance.loginUser?["USERNAME"] ?? "", "USERNAME": SessionService.instance.username,
}, },
); );
} }

View File

@ -59,6 +59,8 @@ class _CheckRecordDetailPageState extends State<CheckRecordDetailPage> {
@override @override
void initState() { void initState() {
super.initState(); super.initState();
// webview controller使
_initLocation();
// UI 使 setState // UI 使 setState
_fetchAll(); _fetchAll();
} }
@ -112,12 +114,114 @@ class _CheckRecordDetailPageState extends State<CheckRecordDetailPage> {
centerLng = lng; centerLng = lng;
_loadingMap = false; _loadingMap = false;
}); });
// controller
if (_controller == null) {
// controller
await _initLocation();
} else {
// controller onPageFinished
await _injectLocationParams();
}
} catch (e, st) { } catch (e, st) {
debugPrint('getMapData error: $e\n$st'); debugPrint('getMapData error: $e\n$st');
setState(() => _loadingMap = false); setState(() => _loadingMap = false);
} }
} }
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) { List<Map<String, dynamic>> buildCoversFromRes(Map res) {
final list = <Map<String, dynamic>>[]; final list = <Map<String, dynamic>>[];
@ -378,72 +482,6 @@ class _CheckRecordDetailPageState extends State<CheckRecordDetailPage> {
), ),
); );
} }
/// WebView
Future<void> _initLocation() async {
//
_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}');
},
),
);
// loadRequest
try {
await _controller!.loadRequest(Uri.parse('http://47.92.102.56:7811/file/fluteightmap/index.html'));
} catch (e, st) {
debugPrint('loadRequest 错误: $e\n$st');
}
}
Future<void> _injectLocationParams() async {
if (_controller == null) {
debugPrint('_injectLocationParams: controller 为空,跳过注入');
return;
}
final params = {
'longitude': centerLng,
'latitude': centerLat,
'GSON': [],
'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('已注入地图初始化参数');
} catch (e) {
debugPrint('注入位置参数失败: $e');
}
}
Widget _buildTableHeaderCell(String text) { Widget _buildTableHeaderCell(String text) {
return Padding(padding: EdgeInsets.all(8), child: Center(child: Text(text, style: TextStyle(fontWeight: FontWeight.bold)))); return Padding(padding: EdgeInsets.all(8), child: Center(child: Text(text, style: TextStyle(fontWeight: FontWeight.bold))));

View File

@ -68,9 +68,11 @@ class _SafecheckSignDetailState extends State<SafecheckSignDetail> {
Future<void> _getData() async { Future<void> _getData() async {
try { try {
LoadingDialogHelper.show();
final result = await ApiService.getSafeCheckSureList( final result = await ApiService.getSafeCheckSureList(
widget.INSPECTION_ID, widget.INSPECTION_ID,
); );
LoadingDialogHelper.hide();
// await mounted pop setState // await mounted pop setState
if (!mounted) return; if (!mounted) return;
setState(() { setState(() {

View File

@ -78,7 +78,6 @@ class _SafecheckAssignmentDetailPageState
.map((item) => '${ApiService.baseImgPath}${item['FILEPATH']}') .map((item) => '${ApiService.baseImgPath}${item['FILEPATH']}')
.toList(); .toList();
files = data['hImgs']; files = data['hImgs'];
}); });
} }
} }
@ -166,7 +165,6 @@ class _SafecheckAssignmentDetailPageState
Navigator.of(context).pop(); Navigator.of(context).pop();
} else { } else {
ToastUtil.showNormal(context, '保存失败'); ToastUtil.showNormal(context, '保存失败');
} }
LoadingDialogHelper.hide(); LoadingDialogHelper.hide();
} catch (e) { } catch (e) {
@ -213,6 +211,12 @@ class _SafecheckAssignmentDetailPageState
ItemListWidget.singleLineTitleText( ItemListWidget.singleLineTitleText(
label: '隐患类型', label: '隐患类型',
isEditable: false, isEditable: false,
text: form['HIDDENTYPE_NAME'] ?? '',
),
const Divider(),
ItemListWidget.singleLineTitleText(
label: '整改类型',
isEditable: false,
text: text:
_rect_des[form['RECTIFICATIONTYPE'].toString()] ?? '', _rect_des[form['RECTIFICATIONTYPE'].toString()] ?? '',
), ),
@ -241,7 +245,6 @@ class _SafecheckAssignmentDetailPageState
initialMediaPaths: hiddenVideo, initialMediaPaths: hiddenVideo,
onChanged: (files) {}, onChanged: (files) {},
onAiIdentify: () {}, onAiIdentify: () {},
), ),
), ),
], ],
@ -322,13 +325,16 @@ class _SafecheckAssignmentDetailPageState
), ),
), ),
SizedBox(height: 15), SizedBox(height: 15),
Padding(padding: EdgeInsets.symmetric(horizontal: 50, vertical: 10), child: CustomButton( Padding(
padding: EdgeInsets.symmetric(horizontal: 50, vertical: 10),
child: CustomButton(
text: _isEdit ? '保存' : '返回', text: _isEdit ? '保存' : '返回',
backgroundColor: Colors.blue, backgroundColor: Colors.blue,
onPressed: () { onPressed: () {
_submit(); _submit();
}, },
),) ),
),
], ],
), ),
), ),

View File

@ -67,9 +67,11 @@ class _SafecheckDangerDetailState extends State<SafecheckDangerDetail> {
Future<void> _getData() async { Future<void> _getData() async {
try { try {
LoadingDialogHelper.show();
final result = await ApiService.getSafeCheckSureList( final result = await ApiService.getSafeCheckSureList(
widget.INSPECTION_ID, widget.INSPECTION_ID,
); );
LoadingDialogHelper.hide();
// await mounted pop setState // await mounted pop setState
if (!mounted) return; if (!mounted) return;
setState(() { setState(() {

View File

@ -34,7 +34,10 @@ class _DefendRecordDetailPageState extends State<DefendRecordDetailPage> {
widget.INSPECTION_ID, widget.INSPECTION_ID,
); );
if (result['result'] == 'success') { if (result['result'] == 'success') {
setState(() {
_list = result['list']; _list = result['list'];
});
} }
LoadingDialogHelper.hide(); LoadingDialogHelper.hide();
} catch (e) { } catch (e) {
@ -53,6 +56,7 @@ class _DefendRecordDetailPageState extends State<DefendRecordDetailPage> {
'申辩意见:${item['INSPECTED_EXPLAIN'] ?? ''}', '申辩意见:${item['INSPECTED_EXPLAIN'] ?? ''}',
), ),
), ),
const Divider(),
ItemListWidget.singleLineTitleText( ItemListWidget.singleLineTitleText(
label: '申辩时间', label: '申辩时间',
isEditable: false, isEditable: false,

View File

@ -150,7 +150,7 @@ class _MineDutyApplicationPage extends State<MineDutyApplicationPage> {
borderRadius: BorderRadius.circular(12), borderRadius: BorderRadius.circular(12),
boxShadow: [ boxShadow: [
BoxShadow( BoxShadow(
color: Colors.grey.withOpacity(0.1), color: Colors.blue.withOpacity(0.1),
spreadRadius: 1, spreadRadius: 1,
blurRadius: 6, blurRadius: 6,
offset: const Offset(0, 2), offset: const Offset(0, 2),
@ -160,6 +160,7 @@ class _MineDutyApplicationPage extends State<MineDutyApplicationPage> {
child: TextField( child: TextField(
controller: _reasonController, controller: _reasonController,
maxLines: 5, maxLines: 5,
maxLength: 120, // 200
decoration: const InputDecoration( decoration: const InputDecoration(
hintText: "请输入离岗原因", hintText: "请输入离岗原因",
hintStyle: TextStyle(color: Color(0xFF9E9E9E)), hintStyle: TextStyle(color: Color(0xFF9E9E9E)),

View File

@ -36,12 +36,10 @@ class MineDutyManagementPage extends StatefulWidget {
} }
class _MineDutyManagementPageState extends State<MineDutyManagementPage> { class _MineDutyManagementPageState extends State<MineDutyManagementPage> {
int showCount = -1; int showCount = -1;
int currentPage = 1; int currentPage = 1;
late List<dynamic> _list = []; late List<dynamic> _list = [];
Future<void> _onRefresh() async { Future<void> _onRefresh() async {
// //
await Future.delayed(const Duration(seconds: 2)); await Future.delayed(const Duration(seconds: 2));
@ -55,7 +53,6 @@ class _MineDutyManagementPageState extends State<MineDutyManagementPage> {
@override @override
void initState() { void initState() {
_getListData(); _getListData();
} }
void refreshData() { void refreshData() {
@ -64,10 +61,8 @@ class _MineDutyManagementPageState extends State<MineDutyManagementPage> {
_getListData(); _getListData();
} }
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
// //
// final leaveRecords = [ // final leaveRecords = [
// LeaveRecord( // LeaveRecord(
@ -110,14 +105,16 @@ class _MineDutyManagementPageState extends State<MineDutyManagementPage> {
return Scaffold( return Scaffold(
backgroundColor: const Color(0xFFF5F7FA), backgroundColor: const Color(0xFFF5F7FA),
appBar: MyAppbar(title: "离岗管理",actions: [ appBar: MyAppbar(
title: "离岗管理",
actions: [
TextButton( TextButton(
onPressed: () { onPressed: () {
Navigator.push( Navigator.push(
context, context,
MaterialPageRoute( MaterialPageRoute(
builder: (context) => MineDutyApplicationPage( builder:
(context) => MineDutyApplicationPage(
onClose: (result) { onClose: (result) {
// print('详情页面已关闭,返回结果: $result'); // print('详情页面已关闭,返回结果: $result');
refreshData(); refreshData();
@ -127,10 +124,18 @@ class _MineDutyManagementPageState extends State<MineDutyManagementPage> {
); );
// pushPage(MineDutyApplicationPage(), context); // pushPage(MineDutyApplicationPage(), context);
}, },
child: Text("申请",style: TextStyle(color: Colors.white,fontSize: 16,fontWeight:FontWeight.bold),)) child: Text(
],), "申请",
body: style: TextStyle(
RefreshIndicator( color: Colors.white,
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
),
],
),
body: RefreshIndicator(
onRefresh: _onRefresh, onRefresh: _onRefresh,
child: child:
// Column( // Column(
@ -150,7 +155,6 @@ class _MineDutyManagementPageState extends State<MineDutyManagementPage> {
// ], // ],
// ), // ),
// ), // ),
// //
Expanded( Expanded(
child: child:
@ -179,13 +183,11 @@ class _MineDutyManagementPageState extends State<MineDutyManagementPage> {
// : "${dateFormat.format(record.startDate)}${dateFormat.format(record.endDate)}"; // : "${dateFormat.format(record.startDate)}${dateFormat.format(record.endDate)}";
final dateRange = "${item['STARTTIME']}${item['ENDTIME']}"; final dateRange = "${item['STARTTIME']}${item['ENDTIME']}";
return return GestureDetector(
GestureDetector(
onTap: () { onTap: () {
pushPage(MineDutyDetailPage(item), context); pushPage(MineDutyDetailPage(item), context);
}, },
child: child: Container(
Container(
margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.white, color: Colors.white,
@ -196,7 +198,7 @@ class _MineDutyManagementPageState extends State<MineDutyManagementPage> {
spreadRadius: 1, spreadRadius: 1,
blurRadius: 6, blurRadius: 6,
offset: const Offset(0, 2), offset: const Offset(0, 2),
) ),
], ],
), ),
child: Padding( child: Padding(
@ -230,16 +232,12 @@ class _MineDutyManagementPageState extends State<MineDutyManagementPage> {
const SizedBox(height: 4), const SizedBox(height: 4),
Text( Text(
"部门:${item['DEPARTMENTNAME']} \n岗位:${item['POSTNAME']}", "部门:${item['DEPARTMENTNAME']} \n岗位:${item['POSTNAME']}",
style: TextStyle( style: TextStyle(fontSize: 13, color: Colors.grey[600]),
fontSize: 13,
color: Colors.grey[600],
), ),
),
], ],
), ),
// const Spacer(),
// const Spacer(),
], ],
), ),
@ -248,7 +246,11 @@ class _MineDutyManagementPageState extends State<MineDutyManagementPage> {
// //
Row( Row(
children: [ children: [
const Icon(Icons.calendar_today, size: 18, color: Colors.grey), const Icon(
Icons.calendar_today,
size: 18,
color: Colors.grey,
),
const SizedBox(width: 8), const SizedBox(width: 8),
Expanded( Expanded(
child: Text( child: Text(
@ -256,7 +258,6 @@ class _MineDutyManagementPageState extends State<MineDutyManagementPage> {
style: const TextStyle(color: Colors.grey), style: const TextStyle(color: Colors.grey),
), ),
), ),
], ],
), ),
@ -276,14 +277,17 @@ class _MineDutyManagementPageState extends State<MineDutyManagementPage> {
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
), ),
), ),
// ),
// ),
const SizedBox(height: 4), const SizedBox(height: 4),
// //
if( item["REVIEW_STATUS"]=="0"&&DateTime.now().isBefore(item["ENDTIME"])&& if (item["REVIEW_STATUS"] == "0" &&
(item["REVIEW_USER_ID"]==SessionService.instance.loginUserId)&& isBeforeNow(item["ENDTIME"]) &&
SessionService.instance.loginUser?["USERNAME"]=="1"&&item['REVIEW_STATUS']=="0") (item["REVIEW_USER_ID"] ==
SessionService.instance.loginUserId) &&
SessionService.instance.loginUser?["USERNAME"] == "1" &&
item['REVIEW_STATUS'] == "0")
Row( Row(
mainAxisAlignment: MainAxisAlignment.end, mainAxisAlignment: MainAxisAlignment.end,
children: [ children: [
@ -291,13 +295,14 @@ class _MineDutyManagementPageState extends State<MineDutyManagementPage> {
onPressed: () { onPressed: () {
showDialog( showDialog(
context: context, context: context,
builder: (context) => DutyDialog( builder:
item,1, (context) => DutyDialog(
item,
1,
onClose: (result) { onClose: (result) {
// print('详情页面已关闭,返回结果: $result'); // print('详情页面已关闭,返回结果: $result');
refreshData(); refreshData();
}, },
), ),
); );
}, },
@ -305,7 +310,10 @@ class _MineDutyManagementPageState extends State<MineDutyManagementPage> {
backgroundColor: const Color(0xFF1976D2), backgroundColor: const Color(0xFF1976D2),
// padding: const EdgeInsets.symmetric(horizontal: 10), // padding: const EdgeInsets.symmetric(horizontal: 10),
), ),
child: const Text("审 批", style: TextStyle(color: Colors.white,fontSize: 12)), child: const Text(
"审 批",
style: TextStyle(color: Colors.white, fontSize: 12),
),
), ),
const SizedBox(width: 16), const SizedBox(width: 16),
@ -314,13 +322,14 @@ class _MineDutyManagementPageState extends State<MineDutyManagementPage> {
onPressed: () { onPressed: () {
showDialog( showDialog(
context: context, context: context,
builder: (context) => DutyDialog( builder:
item,2, (context) => DutyDialog(
item,
2,
onClose: (result) { onClose: (result) {
// print('详情页面已关闭,返回结果: $result'); // print('详情页面已关闭,返回结果: $result');
refreshData(); refreshData();
}, },
), ),
); );
}, },
@ -328,9 +337,11 @@ class _MineDutyManagementPageState extends State<MineDutyManagementPage> {
backgroundColor: Colors.red, backgroundColor: Colors.red,
// padding: const EdgeInsets.symmetric(horizontal: 10), // padding: const EdgeInsets.symmetric(horizontal: 10),
), ),
child: const Text("取 消", style: TextStyle(color: Colors.white,fontSize: 12)), child: const Text(
) "取 消",
style: TextStyle(color: Colors.white, fontSize: 12),
),
),
], ],
), ),
], ],
@ -338,12 +349,10 @@ class _MineDutyManagementPageState extends State<MineDutyManagementPage> {
), ),
), ),
); );
} }
Future<void> _getListData() async { Future<void> _getListData() async {
try { try {
final result = await ApiService.getDutyManagement(showCount, currentPage); final result = await ApiService.getDutyManagement(showCount, currentPage);
if (result['result'] == 'success') { if (result['result'] == 'success') {
final List<dynamic> newList = result['varList'] ?? []; final List<dynamic> newList = result['varList'] ?? [];
@ -356,7 +365,6 @@ class _MineDutyManagementPageState extends State<MineDutyManagementPage> {
} }
} }
String _getTypeReturn(final item) { String _getTypeReturn(final item) {
String type = item['REVIEW_STATUS']; String type = item['REVIEW_STATUS'];
if ("0" == type) { if ("0" == type) {
@ -380,16 +388,9 @@ class _MineDutyManagementPageState extends State<MineDutyManagementPage> {
return "审批错误"; return "审批错误";
} }
} }
} }
enum FeedbackType { tongGuo, Dahui }
enum FeedbackType {
tongGuo,
Dahui,
}
class DutyDialog extends StatefulWidget { class DutyDialog extends StatefulWidget {
const DutyDialog(this.item, this.type, {super.key, required this.onClose}); const DutyDialog(this.item, this.type, {super.key, required this.onClose});
@ -398,14 +399,13 @@ class DutyDialog extends StatefulWidget {
final item; final item;
final int type; final int type;
@override @override
State<DutyDialog> createState() => _DutyDialogState(); State<DutyDialog> createState() => _DutyDialogState();
} }
class _DutyDialogState extends State<DutyDialog> { class _DutyDialogState extends State<DutyDialog> {
final TextEditingController _reasonController = TextEditingController(); final TextEditingController _reasonController = TextEditingController();
// //
FeedbackType? _selectedType = FeedbackType.tongGuo; FeedbackType? _selectedType = FeedbackType.tongGuo;
@ -419,10 +419,8 @@ class _DutyDialogState extends State<DutyDialog> {
} }
} }
Future<void> _dutyApproval() async { Future<void> _dutyApproval() async {
try { try {
String typeString; String typeString;
if (FeedbackType.tongGuo == _selectedType) { if (FeedbackType.tongGuo == _selectedType) {
typeString = "1"; typeString = "1";
@ -430,7 +428,11 @@ class _DutyDialogState extends State<DutyDialog> {
typeString = "-1"; typeString = "-1";
} }
final result = await ApiService.dutyApproval(typeString,_reasonController.text,widget.item["OFFDUTY_ID"]); final result = await ApiService.dutyApproval(
typeString,
_reasonController.text,
widget.item["OFFDUTY_ID"],
);
if (result['result'] == 'success') { if (result['result'] == 'success') {
widget.onClose('关闭提交'); // widget.onClose('关闭提交'); //
} }
@ -441,8 +443,11 @@ class _DutyDialogState extends State<DutyDialog> {
Future<void> _dutyReturned() async { Future<void> _dutyReturned() async {
try { try {
final result = await ApiService.dutyReturned(
final result = await ApiService.dutyReturned("-1",_reasonController.text,widget.item["OFFDUTY_ID"]); "-1",
_reasonController.text,
widget.item["OFFDUTY_ID"],
);
if (result['result'] == 'success') { if (result['result'] == 'success') {
widget.onClose('关闭提交'); // widget.onClose('关闭提交'); //
} }
@ -500,7 +505,6 @@ class _DutyDialogState extends State<DutyDialog> {
), ),
), ),
const SizedBox(height: 20), const SizedBox(height: 20),
// //
@ -509,7 +513,10 @@ class _DutyDialogState extends State<DutyDialog> {
decoration: InputDecoration( decoration: InputDecoration(
border: OutlineInputBorder(), border: OutlineInputBorder(),
hintText: widget.type == 1 ? '请输入审批意见' : '请输入原因', hintText: widget.type == 1 ? '请输入审批意见' : '请输入原因',
contentPadding: EdgeInsets.symmetric(horizontal: 12, vertical: 16), contentPadding: EdgeInsets.symmetric(
horizontal: 12,
vertical: 16,
),
), ),
maxLines: 4, maxLines: 4,
), ),
@ -525,7 +532,11 @@ class _DutyDialogState extends State<DutyDialog> {
onPressed: () { onPressed: () {
if (_reasonController.text.isEmpty) { if (_reasonController.text.isEmpty) {
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(widget.type==1?'请输入审批意见':'请输入原因')) SnackBar(
content: Text(
widget.type == 1 ? '请输入审批意见' : '请输入原因',
),
),
); );
return; return;
} }
@ -541,7 +552,10 @@ class _DutyDialogState extends State<DutyDialog> {
backgroundColor: Colors.blue, backgroundColor: Colors.blue,
padding: const EdgeInsets.symmetric(vertical: 14), padding: const EdgeInsets.symmetric(vertical: 14),
), ),
child: const Text('提交',style: TextStyle(color: Colors.white),), child: const Text(
'提交',
style: TextStyle(color: Colors.white),
),
), ),
), ),
const SizedBox(width: 15), const SizedBox(width: 15),
@ -554,7 +568,10 @@ class _DutyDialogState extends State<DutyDialog> {
backgroundColor: Colors.grey, backgroundColor: Colors.grey,
padding: const EdgeInsets.symmetric(vertical: 14), padding: const EdgeInsets.symmetric(vertical: 14),
), ),
child: const Text('关闭',style: TextStyle(color: Colors.white),), child: const Text(
'关闭',
style: TextStyle(color: Colors.white),
),
), ),
), ),
], ],
@ -564,9 +581,4 @@ class _DutyDialogState extends State<DutyDialog> {
), ),
); );
} }
} }

View File

@ -101,6 +101,7 @@ class _FeedbackPageState extends State<FeedbackPage> {
const Text('标题', style: TextStyle(fontWeight: FontWeight.bold)), const Text('标题', style: TextStyle(fontWeight: FontWeight.bold)),
const SizedBox(height: 8), const SizedBox(height: 8),
TextFormField( TextFormField(
maxLength: 50,
controller: _titleController, controller: _titleController,
decoration: const InputDecoration( decoration: const InputDecoration(
hintText: '请输入标题...', hintText: '请输入标题...',
@ -124,6 +125,7 @@ class _FeedbackPageState extends State<FeedbackPage> {
TextFormField( TextFormField(
controller: _descriptionController, controller: _descriptionController,
maxLines: 5, maxLines: 5,
maxLength: 120,
decoration: decoration:
const InputDecoration( const InputDecoration(
hintText: '请补充详细问题和意见...', hintText: '请补充详细问题和意见...',

View File

@ -284,24 +284,29 @@ String formatDate(DateTime? date, String fmt) {
/// 'yyyy-MM-dd HH:mm' 'yyyy-MM-ddTHH:mm' DateTime null /// 'yyyy-MM-dd HH:mm' 'yyyy-MM-ddTHH:mm' DateTime null
DateTime? _parseYMdHm(String s) { DateTime? _parseYMdHm(String s) {
if (s.isEmpty) return null; if (s.isEmpty) return null;
// 'yyyy-MM-dd HH:mm' 'yyyy-MM-ddTHH:mm'
// :00
String t = s.trim(); String t = s.trim();
// null
if (!RegExp(r'^\d{4}-\d{2}-\d{2}[ T]\d{2}:\d{2}$').hasMatch(t)) { // yyyy-MM-dd
// 'yyyy-MM-dd HH:mm:ss' if (RegExp(r'^\d{4}-\d{2}-\d{2}$').hasMatch(t)) {
if (!RegExp(r'^\d{4}-\d{2}-\d{2}[ T]\d{2}:\d{2}:\d{2}$').hasMatch(t)) { return DateTime.tryParse(t); // 00:00:00
return null;
} else {
// parse
return DateTime.tryParse(t.replaceFirst(' ', 'T'));
} }
}
// 'yyyy-MM-dd HH:mm'使 ISO // yyyy-MM-dd HH:mm yyyy-MM-ddTHH:mm
if (RegExp(r'^\d{4}-\d{2}-\d{2}[ T]\d{2}:\d{2}$').hasMatch(t)) {
final iso = t.replaceFirst(' ', 'T') + ':00'; final iso = t.replaceFirst(' ', 'T') + ':00';
return DateTime.tryParse(iso); return DateTime.tryParse(iso);
} }
// yyyy-MM-dd HH:mm:ss yyyy-MM-ddTHH:mm:ss
if (RegExp(r'^\d{4}-\d{2}-\d{2}[ T]\d{2}:\d{2}:\d{2}$').hasMatch(t)) {
return DateTime.tryParse(t.replaceFirst(' ', 'T'));
}
// null
return null;
}
/// 'yyyy-MM-dd HH:mm' /// 'yyyy-MM-dd HH:mm'
/// 1 (a>b), 0 (a==b), -1 (a<b) /// 1 (a>b), 0 (a==b), -1 (a<b)
int compareYMdHmStrings(String a, String b) { int compareYMdHmStrings(String a, String b) {
@ -320,7 +325,14 @@ bool isAfterStr(String a, String b) => compareYMdHmStrings(a, b) == 1;
/// 便a b /// 便a b
bool isBeforeStr(String a, String b) => compareYMdHmStrings(a, b) == -1; bool isBeforeStr(String a, String b) => compareYMdHmStrings(a, b) == -1;
/// (yyyy-MM-dd HH:mm)
bool isBeforeNow(String timeStr) {
final dt = _parseYMdHm(timeStr);
if (dt == null) {
throw FormatException("时间格式错误,期望 'yyyy-MM-dd HH:mm' 或 'yyyy-MM-dd HH:mm:ss'");
}
return dt.isBefore(DateTime.now());
}
/// ------------------------------------------------------ /// ------------------------------------------------------
/// ///
/// ------------------------------------------------------ /// ------------------------------------------------------

View File

@ -765,6 +765,70 @@ packages:
url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/" url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/"
source: hosted source: hosted
version: "0.5.0" version: "0.5.0"
open_file:
dependency: "direct main"
description:
name: open_file
sha256: d17e2bddf5b278cb2ae18393d0496aa4f162142ba97d1a9e0c30d476adf99c0e
url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/"
source: hosted
version: "3.5.10"
open_file_android:
dependency: transitive
description:
name: open_file_android
sha256: "58141fcaece2f453a9684509a7275f231ac0e3d6ceb9a5e6de310a7dff9084aa"
url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/"
source: hosted
version: "1.0.6"
open_file_ios:
dependency: transitive
description:
name: open_file_ios
sha256: "02996f01e5f6863832068e97f8f3a5ef9b613516db6897f373b43b79849e4d07"
url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/"
source: hosted
version: "1.0.3"
open_file_linux:
dependency: transitive
description:
name: open_file_linux
sha256: d189f799eecbb139c97f8bc7d303f9e720954fa4e0fa1b0b7294767e5f2d7550
url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/"
source: hosted
version: "0.0.5"
open_file_mac:
dependency: transitive
description:
name: open_file_mac
sha256: "1440b1e37ceb0642208cfeb2c659c6cda27b25187a90635c9d1acb7d0584d324"
url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/"
source: hosted
version: "1.0.3"
open_file_platform_interface:
dependency: transitive
description:
name: open_file_platform_interface
sha256: "101b424ca359632699a7e1213e83d025722ab668b9fd1412338221bf9b0e5757"
url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/"
source: hosted
version: "1.0.3"
open_file_web:
dependency: transitive
description:
name: open_file_web
sha256: e3dbc9584856283dcb30aef5720558b90f88036360bd078e494ab80a80130c4f
url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/"
source: hosted
version: "0.0.4"
open_file_windows:
dependency: transitive
description:
name: open_file_windows
sha256: d26c31ddf935a94a1a3aa43a23f4fff8a5ff4eea395fe7a8cb819cf55431c875
url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/"
source: hosted
version: "0.0.3"
package_info_plus: package_info_plus:
dependency: "direct main" dependency: "direct main"
description: description: