...
parent
019fff8329
commit
4055de6723
|
|
@ -24,6 +24,7 @@ class ApiService {
|
|||
"http://192.168.20.240:8500/whb_stu_face/";
|
||||
/// 登录及其他管理后台接口
|
||||
// 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.0.37:8099/api";
|
||||
|
|
@ -1581,8 +1582,8 @@ U6Hzm1ninpWeE+awIDAQAB
|
|||
"CORPINFO_ID": SessionService.instance.corpinfoId,
|
||||
"USER_ID": SessionService.instance.loginUserId,
|
||||
"OPERATOR": SessionService.instance.loginUserId,
|
||||
"NAME": SessionService.instance.loginUser?["USERNAME"] ?? "",
|
||||
"USERNAME": SessionService.instance.loginUser?["USERNAME"] ?? "",
|
||||
"NAME": SessionService.instance.username,
|
||||
"USERNAME": SessionService.instance.username,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,6 +59,8 @@ class _CheckRecordDetailPageState extends State<CheckRecordDetailPage> {
|
|||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
// 先初始化 webview controller,使其尽早准备好
|
||||
_initLocation();
|
||||
// 启动时并行请求,UI 使用 setState 更新
|
||||
_fetchAll();
|
||||
}
|
||||
|
|
@ -112,12 +114,114 @@ class _CheckRecordDetailPageState extends State<CheckRecordDetailPage> {
|
|||
centerLng = lng;
|
||||
_loadingMap = false;
|
||||
});
|
||||
// 确保 controller 已初始化并注入最新参数,触发地图刷新
|
||||
if (_controller == null) {
|
||||
// 如果 controller 还没创建,先创建
|
||||
await _initLocation();
|
||||
} else {
|
||||
// controller 已存在,直接注入参数(页面若尚未完成加载,onPageFinished 会再次注入)
|
||||
await _injectLocationParams();
|
||||
}
|
||||
} catch (e, st) {
|
||||
debugPrint('getMapData error: $e\n$st');
|
||||
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) {
|
||||
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) {
|
||||
return Padding(padding: EdgeInsets.all(8), child: Center(child: Text(text, style: TextStyle(fontWeight: FontWeight.bold))));
|
||||
|
|
|
|||
|
|
@ -68,9 +68,11 @@ class _SafecheckSignDetailState extends State<SafecheckSignDetail> {
|
|||
|
||||
Future<void> _getData() async {
|
||||
try {
|
||||
LoadingDialogHelper.show();
|
||||
final result = await ApiService.getSafeCheckSureList(
|
||||
widget.INSPECTION_ID,
|
||||
);
|
||||
LoadingDialogHelper.hide();
|
||||
// 在 await 之后检查 mounted,避免页面已经被 pop 导致 setState 报错
|
||||
if (!mounted) return;
|
||||
setState(() {
|
||||
|
|
|
|||
|
|
@ -78,7 +78,6 @@ class _SafecheckAssignmentDetailPageState
|
|||
.map((item) => '${ApiService.baseImgPath}${item['FILEPATH']}')
|
||||
.toList();
|
||||
files = data['hImgs'];
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -166,7 +165,6 @@ class _SafecheckAssignmentDetailPageState
|
|||
Navigator.of(context).pop();
|
||||
} else {
|
||||
ToastUtil.showNormal(context, '保存失败');
|
||||
|
||||
}
|
||||
LoadingDialogHelper.hide();
|
||||
} catch (e) {
|
||||
|
|
@ -213,6 +211,12 @@ class _SafecheckAssignmentDetailPageState
|
|||
ItemListWidget.singleLineTitleText(
|
||||
label: '隐患类型',
|
||||
isEditable: false,
|
||||
text: form['HIDDENTYPE_NAME'] ?? '',
|
||||
),
|
||||
const Divider(),
|
||||
ItemListWidget.singleLineTitleText(
|
||||
label: '整改类型',
|
||||
isEditable: false,
|
||||
text:
|
||||
_rect_des[form['RECTIFICATIONTYPE'].toString()] ?? '',
|
||||
),
|
||||
|
|
@ -241,7 +245,6 @@ class _SafecheckAssignmentDetailPageState
|
|||
initialMediaPaths: hiddenVideo,
|
||||
onChanged: (files) {},
|
||||
onAiIdentify: () {},
|
||||
|
||||
),
|
||||
),
|
||||
],
|
||||
|
|
@ -322,13 +325,16 @@ class _SafecheckAssignmentDetailPageState
|
|||
),
|
||||
),
|
||||
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 ? '保存' : '返回',
|
||||
backgroundColor: Colors.blue,
|
||||
onPressed: () {
|
||||
_submit();
|
||||
},
|
||||
),)
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -67,9 +67,11 @@ class _SafecheckDangerDetailState extends State<SafecheckDangerDetail> {
|
|||
|
||||
Future<void> _getData() async {
|
||||
try {
|
||||
LoadingDialogHelper.show();
|
||||
final result = await ApiService.getSafeCheckSureList(
|
||||
widget.INSPECTION_ID,
|
||||
);
|
||||
LoadingDialogHelper.hide();
|
||||
// 在 await 之后检查 mounted,避免页面已经被 pop 导致 setState 报错
|
||||
if (!mounted) return;
|
||||
setState(() {
|
||||
|
|
|
|||
|
|
@ -34,7 +34,10 @@ class _DefendRecordDetailPageState extends State<DefendRecordDetailPage> {
|
|||
widget.INSPECTION_ID,
|
||||
);
|
||||
if (result['result'] == 'success') {
|
||||
setState(() {
|
||||
_list = result['list'];
|
||||
|
||||
});
|
||||
}
|
||||
LoadingDialogHelper.hide();
|
||||
} catch (e) {
|
||||
|
|
@ -53,6 +56,7 @@ class _DefendRecordDetailPageState extends State<DefendRecordDetailPage> {
|
|||
'申辩意见:${item['INSPECTED_EXPLAIN'] ?? ''}',
|
||||
),
|
||||
),
|
||||
const Divider(),
|
||||
ItemListWidget.singleLineTitleText(
|
||||
label: '申辩时间',
|
||||
isEditable: false,
|
||||
|
|
|
|||
|
|
@ -150,7 +150,7 @@ class _MineDutyApplicationPage extends State<MineDutyApplicationPage> {
|
|||
borderRadius: BorderRadius.circular(12),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.grey.withOpacity(0.1),
|
||||
color: Colors.blue.withOpacity(0.1),
|
||||
spreadRadius: 1,
|
||||
blurRadius: 6,
|
||||
offset: const Offset(0, 2),
|
||||
|
|
@ -160,6 +160,7 @@ class _MineDutyApplicationPage extends State<MineDutyApplicationPage> {
|
|||
child: TextField(
|
||||
controller: _reasonController,
|
||||
maxLines: 5,
|
||||
maxLength: 120, // 限制最大字数为 200
|
||||
decoration: const InputDecoration(
|
||||
hintText: "请输入离岗原因",
|
||||
hintStyle: TextStyle(color: Color(0xFF9E9E9E)),
|
||||
|
|
|
|||
|
|
@ -36,12 +36,10 @@ class MineDutyManagementPage extends StatefulWidget {
|
|||
}
|
||||
|
||||
class _MineDutyManagementPageState extends State<MineDutyManagementPage> {
|
||||
|
||||
int showCount = -1;
|
||||
int currentPage = 1;
|
||||
late List<dynamic> _list = [];
|
||||
|
||||
|
||||
Future<void> _onRefresh() async {
|
||||
// 模拟网络请求
|
||||
await Future.delayed(const Duration(seconds: 2));
|
||||
|
|
@ -55,7 +53,6 @@ class _MineDutyManagementPageState extends State<MineDutyManagementPage> {
|
|||
@override
|
||||
void initState() {
|
||||
_getListData();
|
||||
|
||||
}
|
||||
|
||||
void refreshData() {
|
||||
|
|
@ -64,10 +61,8 @@ class _MineDutyManagementPageState extends State<MineDutyManagementPage> {
|
|||
_getListData();
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
||||
// 模拟数据
|
||||
// final leaveRecords = [
|
||||
// LeaveRecord(
|
||||
|
|
@ -110,14 +105,16 @@ class _MineDutyManagementPageState extends State<MineDutyManagementPage> {
|
|||
|
||||
return Scaffold(
|
||||
backgroundColor: const Color(0xFFF5F7FA),
|
||||
appBar: MyAppbar(title: "离岗管理",actions: [
|
||||
appBar: MyAppbar(
|
||||
title: "离岗管理",
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => MineDutyApplicationPage(
|
||||
builder:
|
||||
(context) => MineDutyApplicationPage(
|
||||
onClose: (result) {
|
||||
// print('详情页面已关闭,返回结果: $result');
|
||||
refreshData();
|
||||
|
|
@ -127,10 +124,18 @@ class _MineDutyManagementPageState extends State<MineDutyManagementPage> {
|
|||
);
|
||||
// pushPage(MineDutyApplicationPage(), context);
|
||||
},
|
||||
child: Text("申请",style: TextStyle(color: Colors.white,fontSize: 16,fontWeight:FontWeight.bold),))
|
||||
],),
|
||||
body:
|
||||
RefreshIndicator(
|
||||
child: Text(
|
||||
"申请",
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
body: RefreshIndicator(
|
||||
onRefresh: _onRefresh,
|
||||
child:
|
||||
// Column(
|
||||
|
|
@ -150,7 +155,6 @@ class _MineDutyManagementPageState extends State<MineDutyManagementPage> {
|
|||
// ],
|
||||
// ),
|
||||
// ),
|
||||
|
||||
// 记录列表
|
||||
Expanded(
|
||||
child:
|
||||
|
|
@ -179,13 +183,11 @@ class _MineDutyManagementPageState extends State<MineDutyManagementPage> {
|
|||
// : "${dateFormat.format(record.startDate)} 至 ${dateFormat.format(record.endDate)}";
|
||||
final dateRange = "${item['STARTTIME']} 至 ${item['ENDTIME']}";
|
||||
|
||||
return
|
||||
GestureDetector(
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
pushPage(MineDutyDetailPage(item), context);
|
||||
},
|
||||
child:
|
||||
Container(
|
||||
child: Container(
|
||||
margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
|
|
@ -196,7 +198,7 @@ class _MineDutyManagementPageState extends State<MineDutyManagementPage> {
|
|||
spreadRadius: 1,
|
||||
blurRadius: 6,
|
||||
offset: const Offset(0, 2),
|
||||
)
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Padding(
|
||||
|
|
@ -230,16 +232,12 @@ class _MineDutyManagementPageState extends State<MineDutyManagementPage> {
|
|||
const SizedBox(height: 4),
|
||||
Text(
|
||||
"部门:${item['DEPARTMENTNAME']} \n岗位:${item['POSTNAME']}",
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
color: Colors.grey[600],
|
||||
style: TextStyle(fontSize: 13, color: Colors.grey[600]),
|
||||
),
|
||||
),
|
||||
|
||||
],
|
||||
),
|
||||
// const Spacer(),
|
||||
|
||||
// const Spacer(),
|
||||
],
|
||||
),
|
||||
|
||||
|
|
@ -248,7 +246,11 @@ class _MineDutyManagementPageState extends State<MineDutyManagementPage> {
|
|||
// 离岗时间
|
||||
Row(
|
||||
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),
|
||||
Expanded(
|
||||
child: Text(
|
||||
|
|
@ -256,7 +258,6 @@ class _MineDutyManagementPageState extends State<MineDutyManagementPage> {
|
|||
style: const TextStyle(color: Colors.grey),
|
||||
),
|
||||
),
|
||||
|
||||
],
|
||||
),
|
||||
|
||||
|
|
@ -276,14 +277,17 @@ class _MineDutyManagementPageState extends State<MineDutyManagementPage> {
|
|||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
// ),
|
||||
|
||||
// ),
|
||||
const SizedBox(height: 4),
|
||||
|
||||
// 操作按钮
|
||||
if( item["REVIEW_STATUS"]=="0"&&DateTime.now().isBefore(item["ENDTIME"])&&
|
||||
(item["REVIEW_USER_ID"]==SessionService.instance.loginUserId)&&
|
||||
SessionService.instance.loginUser?["USERNAME"]=="1"&&item['REVIEW_STATUS']=="0")
|
||||
if (item["REVIEW_STATUS"] == "0" &&
|
||||
isBeforeNow(item["ENDTIME"]) &&
|
||||
(item["REVIEW_USER_ID"] ==
|
||||
SessionService.instance.loginUserId) &&
|
||||
SessionService.instance.loginUser?["USERNAME"] == "1" &&
|
||||
item['REVIEW_STATUS'] == "0")
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
|
|
@ -291,13 +295,14 @@ class _MineDutyManagementPageState extends State<MineDutyManagementPage> {
|
|||
onPressed: () {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) => DutyDialog(
|
||||
item,1,
|
||||
builder:
|
||||
(context) => DutyDialog(
|
||||
item,
|
||||
1,
|
||||
onClose: (result) {
|
||||
// print('详情页面已关闭,返回结果: $result');
|
||||
refreshData();
|
||||
},
|
||||
|
||||
),
|
||||
);
|
||||
},
|
||||
|
|
@ -305,7 +310,10 @@ class _MineDutyManagementPageState extends State<MineDutyManagementPage> {
|
|||
backgroundColor: const Color(0xFF1976D2),
|
||||
// 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),
|
||||
|
|
@ -314,13 +322,14 @@ class _MineDutyManagementPageState extends State<MineDutyManagementPage> {
|
|||
onPressed: () {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) => DutyDialog(
|
||||
item,2,
|
||||
builder:
|
||||
(context) => DutyDialog(
|
||||
item,
|
||||
2,
|
||||
onClose: (result) {
|
||||
// print('详情页面已关闭,返回结果: $result');
|
||||
refreshData();
|
||||
},
|
||||
|
||||
),
|
||||
);
|
||||
},
|
||||
|
|
@ -328,9 +337,11 @@ class _MineDutyManagementPageState extends State<MineDutyManagementPage> {
|
|||
backgroundColor: Colors.red,
|
||||
// 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 {
|
||||
try {
|
||||
|
||||
final result = await ApiService.getDutyManagement(showCount, currentPage);
|
||||
if (result['result'] == 'success') {
|
||||
final List<dynamic> newList = result['varList'] ?? [];
|
||||
|
|
@ -356,7 +365,6 @@ class _MineDutyManagementPageState extends State<MineDutyManagementPage> {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
String _getTypeReturn(final item) {
|
||||
String type = item['REVIEW_STATUS'];
|
||||
if ("0" == type) {
|
||||
|
|
@ -380,16 +388,9 @@ class _MineDutyManagementPageState extends State<MineDutyManagementPage> {
|
|||
return "审批错误";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
enum FeedbackType {
|
||||
tongGuo,
|
||||
Dahui,
|
||||
}
|
||||
enum FeedbackType { tongGuo, Dahui }
|
||||
|
||||
class DutyDialog extends StatefulWidget {
|
||||
const DutyDialog(this.item, this.type, {super.key, required this.onClose});
|
||||
|
|
@ -398,14 +399,13 @@ class DutyDialog extends StatefulWidget {
|
|||
final item;
|
||||
final int type;
|
||||
|
||||
|
||||
@override
|
||||
State<DutyDialog> createState() => _DutyDialogState();
|
||||
}
|
||||
|
||||
class _DutyDialogState extends State<DutyDialog> {
|
||||
|
||||
final TextEditingController _reasonController = TextEditingController();
|
||||
|
||||
// 反馈类型
|
||||
FeedbackType? _selectedType = FeedbackType.tongGuo;
|
||||
|
||||
|
|
@ -419,10 +419,8 @@ class _DutyDialogState extends State<DutyDialog> {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
Future<void> _dutyApproval() async {
|
||||
try {
|
||||
|
||||
String typeString;
|
||||
if (FeedbackType.tongGuo == _selectedType) {
|
||||
typeString = "1";
|
||||
|
|
@ -430,7 +428,11 @@ class _DutyDialogState extends State<DutyDialog> {
|
|||
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') {
|
||||
widget.onClose('关闭提交'); // 触发回调
|
||||
}
|
||||
|
|
@ -441,8 +443,11 @@ class _DutyDialogState extends State<DutyDialog> {
|
|||
|
||||
Future<void> _dutyReturned() async {
|
||||
try {
|
||||
|
||||
final result = await ApiService.dutyReturned("-1",_reasonController.text,widget.item["OFFDUTY_ID"]);
|
||||
final result = await ApiService.dutyReturned(
|
||||
"-1",
|
||||
_reasonController.text,
|
||||
widget.item["OFFDUTY_ID"],
|
||||
);
|
||||
if (result['result'] == 'success') {
|
||||
widget.onClose('关闭提交'); // 触发回调
|
||||
}
|
||||
|
|
@ -500,7 +505,6 @@ class _DutyDialogState extends State<DutyDialog> {
|
|||
),
|
||||
),
|
||||
|
||||
|
||||
const SizedBox(height: 20),
|
||||
|
||||
// 输入框
|
||||
|
|
@ -509,7 +513,10 @@ class _DutyDialogState extends State<DutyDialog> {
|
|||
decoration: InputDecoration(
|
||||
border: OutlineInputBorder(),
|
||||
hintText: widget.type == 1 ? '请输入审批意见' : '请输入原因',
|
||||
contentPadding: EdgeInsets.symmetric(horizontal: 12, vertical: 16),
|
||||
contentPadding: EdgeInsets.symmetric(
|
||||
horizontal: 12,
|
||||
vertical: 16,
|
||||
),
|
||||
),
|
||||
maxLines: 4,
|
||||
),
|
||||
|
|
@ -525,7 +532,11 @@ class _DutyDialogState extends State<DutyDialog> {
|
|||
onPressed: () {
|
||||
if (_reasonController.text.isEmpty) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(content: Text(widget.type==1?'请输入审批意见':'请输入原因'))
|
||||
SnackBar(
|
||||
content: Text(
|
||||
widget.type == 1 ? '请输入审批意见' : '请输入原因',
|
||||
),
|
||||
),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
|
@ -541,7 +552,10 @@ class _DutyDialogState extends State<DutyDialog> {
|
|||
backgroundColor: Colors.blue,
|
||||
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),
|
||||
|
|
@ -554,7 +568,10 @@ class _DutyDialogState extends State<DutyDialog> {
|
|||
backgroundColor: Colors.grey,
|
||||
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> {
|
|||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -101,6 +101,7 @@ class _FeedbackPageState extends State<FeedbackPage> {
|
|||
const Text('标题', style: TextStyle(fontWeight: FontWeight.bold)),
|
||||
const SizedBox(height: 8),
|
||||
TextFormField(
|
||||
maxLength: 50,
|
||||
controller: _titleController,
|
||||
decoration: const InputDecoration(
|
||||
hintText: '请输入标题...',
|
||||
|
|
@ -124,6 +125,7 @@ class _FeedbackPageState extends State<FeedbackPage> {
|
|||
TextFormField(
|
||||
controller: _descriptionController,
|
||||
maxLines: 5,
|
||||
maxLength: 120,
|
||||
decoration:
|
||||
const InputDecoration(
|
||||
hintText: '请补充详细问题和意见...',
|
||||
|
|
|
|||
|
|
@ -284,24 +284,29 @@ String formatDate(DateTime? date, String fmt) {
|
|||
/// 把 'yyyy-MM-dd HH:mm'(或 'yyyy-MM-ddTHH:mm')解析为 DateTime,失败返回 null
|
||||
DateTime? _parseYMdHm(String s) {
|
||||
if (s.isEmpty) return null;
|
||||
// 允许传入 'yyyy-MM-dd HH:mm' 或 'yyyy-MM-ddTHH:mm'
|
||||
// 如果没有秒,补上 :00
|
||||
String t = s.trim();
|
||||
// 如果只有日期部分,直接返回 null(你也可以自行扩展)
|
||||
if (!RegExp(r'^\d{4}-\d{2}-\d{2}[ T]\d{2}:\d{2}$').hasMatch(t)) {
|
||||
// 试着容错:如果是 'yyyy-MM-dd HH:mm:ss' 也接受
|
||||
if (!RegExp(r'^\d{4}-\d{2}-\d{2}[ T]\d{2}:\d{2}:\d{2}$').hasMatch(t)) {
|
||||
return null;
|
||||
} else {
|
||||
// 已经带秒,直接 parse
|
||||
return DateTime.tryParse(t.replaceFirst(' ', 'T'));
|
||||
|
||||
// 只包含日期的情况:yyyy-MM-dd
|
||||
if (RegExp(r'^\d{4}-\d{2}-\d{2}$').hasMatch(t)) {
|
||||
return DateTime.tryParse(t); // 默认 00:00:00
|
||||
}
|
||||
}
|
||||
// 如果是 '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';
|
||||
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' 格式字符串
|
||||
/// 返回 1 (a>b), 0 (a==b), -1 (a<b)
|
||||
int compareYMdHmStrings(String a, String b) {
|
||||
|
|
@ -320,7 +325,14 @@ bool isAfterStr(String a, String b) => compareYMdHmStrings(a, b) == 1;
|
|||
|
||||
/// 便捷:a 是否 早于 b
|
||||
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());
|
||||
}
|
||||
/// ------------------------------------------------------
|
||||
/// 防多次点击
|
||||
/// ------------------------------------------------------
|
||||
|
|
|
|||
64
pubspec.lock
64
pubspec.lock
|
|
@ -765,6 +765,70 @@ packages:
|
|||
url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/"
|
||||
source: hosted
|
||||
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:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
|
|
|||
Loading…
Reference in New Issue