Merge remote-tracking branch 'origin/main'
# Conflicts: # lib/pages/home/home_page.dart # pubspec.lock # pubspec.yamlmain
commit
ccb9eb4f55
|
@ -4,6 +4,7 @@
|
|||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" /> <!-- 后台定位 -->
|
||||
|
||||
|
||||
<!-- 相册 -->
|
||||
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" /> <!-- Android 13+ -->
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <!-- Android 12及以下 -->
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 1.2 KiB |
|
@ -57,6 +57,10 @@
|
|||
<string>app需要访问相册以上传图片</string>
|
||||
<key>NSUserNotificationsUsageDescription</key>
|
||||
<string>app需要发送通知提醒重要信息</string>
|
||||
<key>NSLocationWhenInUseUsageDescription</key>
|
||||
<string>需要位置权限以提供定位服务</string>
|
||||
<key>NSLocationAlwaysUsageDescription</key>
|
||||
<string>需要位置权限以提供定位服务</string>
|
||||
<key>UIApplicationSupportsIndirectInputEvents</key>
|
||||
<true/>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../http/ApiService.dart';
|
||||
import '../tools/tools.dart';
|
||||
|
||||
/// 自定义组件
|
||||
|
@ -115,7 +116,7 @@ class ListItemFactory {
|
|||
spacing: 8, // 水平间距
|
||||
runSpacing: 8, // 垂直间距
|
||||
children: List.generate(imageUrls.length, (i) {
|
||||
final url = imageUrls[i];
|
||||
final url =ApiService.baseImgPath + imageUrls[i];
|
||||
Widget img;
|
||||
if (url.startsWith('http')) {
|
||||
img = Image.network(
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:photo_view/photo_view.dart';
|
||||
import 'package:qhd_prevention/customWidget/video_player_widget.dart';
|
||||
import 'package:qhd_prevention/pages/my_appbar.dart';
|
||||
import 'package:video_player/video_player.dart';
|
||||
// 查看视频
|
||||
class BigVideoViewer extends StatefulWidget {
|
||||
const BigVideoViewer({Key? key, required this.videoUrl}) : super(key: key);
|
||||
|
||||
final String videoUrl;
|
||||
|
||||
@override
|
||||
State<BigVideoViewer> createState() => _BigVideoViewerState();
|
||||
}
|
||||
|
||||
class _BigVideoViewerState extends State<BigVideoViewer> {
|
||||
|
||||
VideoPlayerController? _videoController;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
// TODO: implement initState
|
||||
super.initState();
|
||||
|
||||
_videoController?.removeListener(_controllerListener);
|
||||
_videoController?.dispose();
|
||||
_videoController = VideoPlayerController.networkUrl(Uri.parse(widget.videoUrl))
|
||||
..initialize().then((_) {
|
||||
_videoController!
|
||||
..play()
|
||||
..addListener(_controllerListener);
|
||||
});
|
||||
}
|
||||
|
||||
void _controllerListener() {
|
||||
if (mounted) setState(() {});
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_videoController?.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: Colors.black,
|
||||
appBar: MyAppbar(
|
||||
backgroundColor: Colors.transparent, title: '',
|
||||
),
|
||||
body: Center(
|
||||
child: VideoPlayerWidget(
|
||||
allowSeek: false,
|
||||
controller: _videoController,
|
||||
coverUrl:"",
|
||||
aspectRatio: _videoController?.value.aspectRatio ?? 16/9,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -939,6 +939,161 @@ U6Hzm1ninpWeE+awIDAQAB
|
|||
);
|
||||
}
|
||||
|
||||
/// 获取隐患记录详情
|
||||
static Future<Map<String, dynamic>> getDangerDetail(String id) {
|
||||
return HttpManager().request(
|
||||
basePath,
|
||||
'/app/hidden/goEdit',
|
||||
method: Method.post,
|
||||
data: {
|
||||
"HIDDEN_ID": id,
|
||||
"CORPINFO_ID": SessionService.instance.corpinfoId,
|
||||
"USER_ID": SessionService.instance.loginUserId,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/// 获取个人信息
|
||||
static Future<Map<String, dynamic>> getUserInfo() {
|
||||
return HttpManager().request(
|
||||
basePath,
|
||||
'/app/user/goEditUser',
|
||||
method: Method.post,
|
||||
data: {
|
||||
"CORPINFO_ID": SessionService.instance.corpinfoId,
|
||||
"USER_ID": SessionService.instance.loginUserId,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/// 获取本日工作提醒
|
||||
static Future<Map<String, dynamic>> getAnPai() {
|
||||
return HttpManager().request(
|
||||
basePath,
|
||||
'/app/listmanager/checkListIndex',
|
||||
method: Method.post,
|
||||
data: {
|
||||
"tm":DateTime.now().millisecondsSinceEpoch.toString(),
|
||||
"DEPARTMENT_ID":SessionService.instance.corpinfoId,
|
||||
"CORPINFO_ID":SessionService.instance.corpinfoId,
|
||||
"USER_ID":SessionService.instance.loginUserId,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/// 获取本日日程安排
|
||||
static Future<Map<String, dynamic>> getRiCheng(String data) {
|
||||
return HttpManager().request(
|
||||
basePath,
|
||||
'/app/schedule/getData',
|
||||
method: Method.post,
|
||||
data: {
|
||||
"CDATA": data,
|
||||
"USERNAME": SessionService.instance.loginUser?["USERNAME"]??"",
|
||||
"CORPINFO_ID":SessionService.instance.corpinfoId,
|
||||
"USER_ID":SessionService.instance.loginUserId,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/// 增加本日日程安排
|
||||
static Future<Map<String, dynamic>> addRiCheng(String data,String title, String content,String id,String urlPath) {
|
||||
return HttpManager().request(
|
||||
basePath,
|
||||
'/app/schedule/$urlPath',
|
||||
method: Method.post,
|
||||
data: {
|
||||
"CDATA": data,
|
||||
"USERNAME":SessionService.instance.loginUser?["USERNAME"]??"",
|
||||
"CORPINFO_ID":SessionService.instance.corpinfoId,
|
||||
"USER_ID":SessionService.instance.loginUserId,
|
||||
"SCHEDULE_ID": id,
|
||||
"TITLE": title,
|
||||
"FHDESC":content,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/// 获取风险分布列表
|
||||
static Future<Map<String, dynamic>> getRiskRecordList(int currentPage,
|
||||
String riskId,String dept,String level,String keyWord) {
|
||||
return HttpManager().request(
|
||||
basePath,
|
||||
'/app/riskpoint/list?showCount=-1¤tPage=$currentPage',
|
||||
method: Method.post,
|
||||
data: {
|
||||
"CORPINFOID": SessionService.instance.corpinfoId,
|
||||
"RISK_UNIT_ID": riskId,
|
||||
"DEPARTMENT_ID": dept,
|
||||
"LEVELID": level,
|
||||
"IS_APP": 1,
|
||||
"tm": DateTime.now().millisecondsSinceEpoch.toString(),
|
||||
"KEYWORDS": keyWord, //关键字模糊查询
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/// 获取风险分布详情
|
||||
static Future<Map<String, dynamic>> getForIdentification(String id) {
|
||||
return HttpManager().request(
|
||||
basePath,
|
||||
'/app/riskpoint/getForIdentification',
|
||||
method: Method.post,
|
||||
data: {
|
||||
"CHECK_IDENTIFICATION_ID": id,
|
||||
"CORPINFO_ID":SessionService.instance.corpinfoId,
|
||||
"USER_ID":SessionService.instance.loginUserId,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/// 获取风险分布详情提交坐标
|
||||
static Future<Map<String, dynamic>> addCoordinate(String id,String longitude,String latitude) {
|
||||
return HttpManager().request(
|
||||
basePath,
|
||||
'/app/riskpoint/editLonAndLat',
|
||||
method: Method.post,
|
||||
data: {
|
||||
"IDENTIFICATIONPARTS_ID": id,
|
||||
"CORPINFO_ID":SessionService.instance.corpinfoId,
|
||||
"USER_ID":SessionService.instance.loginUserId,
|
||||
"LONGITUDE" : longitude,
|
||||
"LATITUDE" : latitude,
|
||||
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/// 获取风险分布列表侧滑菜单第二个选框数据
|
||||
static Future<Map<String, dynamic>> getTreeListUnit(String id) {
|
||||
return HttpManager().request(
|
||||
basePath,
|
||||
'/app/riskpoint/listUnit',
|
||||
method: Method.post,
|
||||
data: {
|
||||
"DEPARTMENT_ID": id,
|
||||
"tm": DateTime.now().millisecondsSinceEpoch.toString(),
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/// 获取法律法规类表
|
||||
static Future<Map<String, dynamic>> getLowList(String keyWord) {
|
||||
return HttpManager().request(
|
||||
basePath,
|
||||
'/app/mfolderStipulate/appListTree',
|
||||
method: Method.post,
|
||||
data: {
|
||||
"CORPINFO_ID":SessionService.instance.corpinfoId,
|
||||
"USER_ID":SessionService.instance.loginUserId,
|
||||
"KEYWORDS":keyWord,
|
||||
"SHARE": "yes",
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ import 'package:qhd_prevention/pages/home/tap/tabList/work_tab_list_page.dart';
|
|||
import 'package:qhd_prevention/pages/home/userInfo_page.dart';
|
||||
import 'package:qhd_prevention/pages/home/work/danger_page.dart';
|
||||
import 'package:qhd_prevention/pages/home/work/danger_wait_list_page.dart';
|
||||
import 'package:qhd_prevention/pages/home/work/laws_regulations_page.dart';
|
||||
import 'package:qhd_prevention/pages/home/workSet_page.dart';
|
||||
|
||||
import '../../customWidget/hidden_roll_widget.dart';
|
||||
|
@ -189,7 +190,8 @@ class _HomePageState extends State<HomePage> {
|
|||
} else if (index == 2) {
|
||||
pushPage(RiskControlPage(), context);
|
||||
} else if (index == 3) {
|
||||
pushPage(LowPage(), context);
|
||||
// pushPage(LowPage(), context);
|
||||
pushPage(LawsRegulationsPage(), context);
|
||||
} else if (index == 4) {
|
||||
pushPage(WorkTabListPage(), context);
|
||||
} else if (index == 7) {
|
||||
|
@ -552,5 +554,4 @@ class _HomePageState extends State<HomePage> {
|
|||
print('加载首页数据失败:$e');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:qhd_prevention/pages/my_appbar.dart';
|
||||
import 'package:qhd_prevention/tools/tools.dart';
|
||||
import '../../http/ApiService.dart';
|
||||
import '/customWidget/search_bar_widget.dart';
|
||||
|
||||
class LowPage extends StatefulWidget {
|
||||
|
@ -17,7 +18,35 @@ class _LowPagePageState extends State<LowPage> {
|
|||
'title': '测试数据标题标题 ${i + 1}',
|
||||
};
|
||||
});
|
||||
|
||||
final TextEditingController _searchController = TextEditingController();
|
||||
String treeJson="";
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
// TODO: implement initState
|
||||
super.initState();
|
||||
|
||||
_getLowList();
|
||||
}
|
||||
|
||||
Future<void> _getLowList() async {
|
||||
try {
|
||||
|
||||
final result = await ApiService.getHiddenTreatmentListTree();
|
||||
if (result['result'] == 'success') {
|
||||
setState(() {
|
||||
treeJson= result['zTreeNodes'];
|
||||
});
|
||||
|
||||
}else{
|
||||
_showMessage('加载数据失败');
|
||||
}
|
||||
} catch (e) {
|
||||
// 出错时可以 Toast 或者在页面上显示错误状态
|
||||
print('加载数据失败:$e');
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
@ -25,7 +54,9 @@ class _LowPagePageState extends State<LowPage> {
|
|||
appBar: MyAppbar(
|
||||
title: "法律法规",
|
||||
),
|
||||
body: SafeArea(child: _vcDetailWidget()),
|
||||
body: SafeArea(
|
||||
child: _vcDetailWidget()
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -74,4 +105,8 @@ class _LowPagePageState extends State<LowPage> {
|
|||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _showMessage(String msg) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(msg)));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,8 @@ import 'package:qhd_prevention/pages/home/work/custom_driver_drawer.dart';
|
|||
import 'package:qhd_prevention/pages/home/risk/risk_detail_page.dart';
|
||||
import 'package:qhd_prevention/pages/my_appbar.dart';
|
||||
import 'package:qhd_prevention/tools/tools.dart';
|
||||
import '../../../http/ApiService.dart';
|
||||
import '../../../tools/h_colors.dart';
|
||||
import '/customWidget/search_bar_widget.dart';
|
||||
|
||||
class RiskControlPage extends StatefulWidget {
|
||||
|
@ -14,16 +16,17 @@ class RiskControlPage extends StatefulWidget {
|
|||
}
|
||||
|
||||
class _RiskControlPageState extends State<RiskControlPage> {
|
||||
// 模拟数据
|
||||
final List<Map<String, dynamic>> _dataInfos = List.generate(10, (i) {
|
||||
bool read = i % 3 == 0;
|
||||
return {
|
||||
'title': '测试数据标题标题 ${i + 1}',
|
||||
'label1': '2025-06-${10 + i} 12:3${i}',
|
||||
'label2': '2025-06-${1 + i} 2:1${i}',
|
||||
'level': getRandomWithNum(1, 4),
|
||||
};
|
||||
});
|
||||
|
||||
int _page = 1;
|
||||
String searchKey="";
|
||||
int _totalPage=1;
|
||||
late List<dynamic> _list = [];
|
||||
bool _isLoading = false;
|
||||
bool _hasMore = true;
|
||||
|
||||
String treeJson="";
|
||||
|
||||
|
||||
|
||||
// 风险等级颜色
|
||||
final List<Color> _fxColors = [
|
||||
|
@ -38,6 +41,18 @@ class _RiskControlPageState extends State<RiskControlPage> {
|
|||
final List<String> _levelTexts = ["重大风险/A级", "较大风险/B级", "一般风险/C级", "低风险/D级"];
|
||||
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
|
||||
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
getListData(false,"");
|
||||
_getListTree();
|
||||
SessionService.instance.setRiskWaitInfo("");
|
||||
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// 取屏幕宽度
|
||||
|
@ -60,15 +75,35 @@ class _RiskControlPageState extends State<RiskControlPage> {
|
|||
),
|
||||
],
|
||||
),
|
||||
|
||||
//弹窗
|
||||
endDrawer: Drawer(
|
||||
// 用 Container 限制宽度为屏幕的 3/5
|
||||
child: Container(
|
||||
width: screenWidth * 3 / 5,
|
||||
color: Colors.white,
|
||||
child: const CustomDriverDrawer(),
|
||||
child: CustomDriverDrawer(
|
||||
treeJson,
|
||||
onClose: (String riskId,String dept,String level) {
|
||||
|
||||
// _getDangerRecord(-1,_page,startDate,endDate,hazardLevelOption,investigationMethodOption,
|
||||
// dangerStatusOption,selectedCategoryId,selectedDepartmentId,"",searchKey,false);
|
||||
_page=1;
|
||||
_getRiskRecord(_page,riskId,dept,level,searchKey,false);
|
||||
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
body: SafeArea(child: _vcDetailWidget()),
|
||||
|
||||
|
||||
body: SafeArea(
|
||||
child: NotificationListener<ScrollNotification>(
|
||||
onNotification: _onScroll,
|
||||
child:_vcDetailWidget()
|
||||
)
|
||||
),
|
||||
backgroundColor: Colors.white,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -81,16 +116,24 @@ class _RiskControlPageState extends State<RiskControlPage> {
|
|||
controller: _searchController,
|
||||
onSearch: (keyboard) {
|
||||
// 输入请求接口
|
||||
_page=1;
|
||||
searchKey=keyboard;
|
||||
getListData(false,keyboard);
|
||||
},
|
||||
),
|
||||
),
|
||||
|
||||
Container(
|
||||
height: 5,
|
||||
color: h_backGroundColor(),
|
||||
),
|
||||
Expanded(
|
||||
child: ListView.separated(
|
||||
child: _list.isEmpty
|
||||
? Center(child: Text('暂无数据'))
|
||||
: ListView.separated(
|
||||
separatorBuilder: (_, __) => const Divider(height: 1),
|
||||
itemCount: _dataInfos.length,
|
||||
itemCount: _list.length,
|
||||
itemBuilder: (context, index) {
|
||||
final item = _dataInfos[index];
|
||||
final item = _list[index];
|
||||
return _fxitemCell(item);
|
||||
},
|
||||
),
|
||||
|
@ -99,10 +142,23 @@ class _RiskControlPageState extends State<RiskControlPage> {
|
|||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Widget _fxitemCell(final item) {
|
||||
int level = item['level'] as int;
|
||||
int level;
|
||||
// 确保level在有效范围内 (1-4)
|
||||
level = level.clamp(1, 4) - 1;
|
||||
// level = level.clamp(1, 4) - 1;
|
||||
if(item['LEVELID']=="levelA"){
|
||||
level=0;
|
||||
}else if(item['LEVELID']=="levelB"){
|
||||
level=1;
|
||||
}else if(item['LEVELID']=="levelC"){
|
||||
level=2;
|
||||
}else {
|
||||
level=3;
|
||||
}
|
||||
|
||||
// 使用GestureDetector包裹整个列表项以添加点击事件
|
||||
return GestureDetector(
|
||||
|
@ -129,19 +185,19 @@ class _RiskControlPageState extends State<RiskControlPage> {
|
|||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
item['title'] ?? '',
|
||||
'部位名称:${item['PARTSNAME'] ?? ''}',
|
||||
style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
SizedBox(height: 8),
|
||||
Text(
|
||||
item['label1'] ?? '',
|
||||
'风险点(单元):${item['RISKUNITNAME'] ?? ''}',
|
||||
style: TextStyle(fontSize: 14, color: Colors.grey),
|
||||
),
|
||||
SizedBox(height: 4),
|
||||
Text(
|
||||
item['label2'] ?? '',
|
||||
'管控部门:${item['DEPT_NAME'] ?? ''}',
|
||||
style: TextStyle(fontSize: 14, color: Colors.grey),
|
||||
),
|
||||
],
|
||||
|
@ -188,6 +244,88 @@ class _RiskControlPageState extends State<RiskControlPage> {
|
|||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
void getListData(bool addList,String keyWord){
|
||||
_getRiskRecord(_page,"","","",keyWord,addList);
|
||||
|
||||
}
|
||||
|
||||
Future<void> _getRiskRecord(int currentPage,
|
||||
String riskId,String dept,String level,String keyWord,bool loadMore) async {
|
||||
try {
|
||||
if (_isLoading) return;
|
||||
_isLoading = true;
|
||||
|
||||
|
||||
final result = await ApiService.getRiskRecordList( currentPage,
|
||||
riskId, dept, level, keyWord);
|
||||
|
||||
if (result['result'] == 'success') {
|
||||
|
||||
_totalPage =result["page"]['totalPage'] ?? 1;
|
||||
final List<dynamic> newList = result['varList'] ?? [];
|
||||
// setState(() {
|
||||
// _list.addAll(newList);
|
||||
// });
|
||||
|
||||
setState(() {
|
||||
if (loadMore) {
|
||||
_list.addAll(newList);
|
||||
} else {
|
||||
_list = newList;
|
||||
}
|
||||
_hasMore = _page < _totalPage;
|
||||
// if (_hasMore) _page++;
|
||||
});
|
||||
|
||||
}else{
|
||||
_showMessage('加载数据失败');
|
||||
}
|
||||
|
||||
} catch (e) {
|
||||
// 出错时可以 Toast 或者在页面上显示错误状态
|
||||
print('加载数据失败:$e');
|
||||
} finally {
|
||||
// if (!loadMore) LoadingDialogHelper.hide(context);
|
||||
_isLoading = false;
|
||||
}
|
||||
}
|
||||
|
||||
bool _onScroll(ScrollNotification n) {
|
||||
if (n.metrics.pixels > n.metrics.maxScrollExtent - 100 &&
|
||||
_hasMore && !_isLoading) {
|
||||
|
||||
_page++;
|
||||
getListData(true,"");
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
Future<void> _getListTree() async {
|
||||
try {
|
||||
|
||||
final result = await ApiService.getHiddenTreatmentListTree();
|
||||
if (result['result'] == 'success') {
|
||||
setState(() {
|
||||
treeJson= result['zTreeNodes'];
|
||||
});
|
||||
|
||||
}else{
|
||||
_showMessage('加载数据失败');
|
||||
}
|
||||
} catch (e) {
|
||||
// 出错时可以 Toast 或者在页面上显示错误状态
|
||||
print('加载数据失败:$e');
|
||||
}
|
||||
}
|
||||
|
||||
void _showMessage(String msg) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(msg)));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:qhd_prevention/pages/my_appbar.dart';
|
||||
import 'package:qhd_prevention/tools/tools.dart';
|
||||
import 'package:geolocator/geolocator.dart';
|
||||
|
||||
import '../../../http/ApiService.dart';
|
||||
import '../../../tools/h_colors.dart';
|
||||
|
||||
class RiskDetailPage extends StatefulWidget {
|
||||
|
@ -14,25 +16,72 @@ class RiskDetailPage extends StatefulWidget {
|
|||
}
|
||||
|
||||
class _RiskDetailPageState extends State<RiskDetailPage> {
|
||||
final List<Map<String, dynamic>> _dataInfos = [
|
||||
{
|
||||
"title": "存在风险",
|
||||
"detail": ["测试", "测试去外地恰逢其会发起违反去和我i回复IQ请勿凤求凰IQ佛ifi哦好气哦hi哦发i哦前期我放弃"],
|
||||
},
|
||||
{
|
||||
"title": "主要管控措施",
|
||||
"detail": ["测试去外地恰逢其会发起违反去和我i回复IQ请勿凤求凰IQ佛ifi哦好气哦hi哦发i哦前期我放"],
|
||||
},
|
||||
{
|
||||
"title": "管控部门",
|
||||
"detail": ["哈哈"],
|
||||
},
|
||||
{
|
||||
"title": "事故类型",
|
||||
"detail": ["物体打击,车辆伤害"],
|
||||
},
|
||||
|
||||
|
||||
late List<dynamic> _list = [];
|
||||
// 风险等级文本
|
||||
final List<String> _levelTexts = ["重大风险", "较大风险", "一般风险", "低风险"];
|
||||
// 风险等级颜色
|
||||
final List<Color> _fxColors = [
|
||||
const Color(0xFFFADBD9),
|
||||
const Color(0xFFFCE6D2),
|
||||
const Color(0xFFFDF2CE),
|
||||
const Color(0xFFCCE6FF),
|
||||
];
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
// TODO: implement initState
|
||||
super.initState();
|
||||
|
||||
_getForIdentification();
|
||||
}
|
||||
|
||||
|
||||
Future<void> _getForIdentification() async {
|
||||
try {
|
||||
|
||||
final result = await ApiService.getForIdentification( widget.itemData["IDENTIFICATIONPARTS_ID"]);
|
||||
|
||||
if (result['result'] == 'success') {
|
||||
final List<dynamic> newList = result['varList'] ?? [];
|
||||
setState(() {
|
||||
_list.addAll(newList);
|
||||
});
|
||||
|
||||
|
||||
}else{
|
||||
_showMessage('加载数据失败');
|
||||
}
|
||||
|
||||
} catch (e) {
|
||||
// 出错时可以 Toast 或者在页面上显示错误状态
|
||||
print('加载数据失败:$e');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Future<void> _addCoordinate() async {
|
||||
try {
|
||||
|
||||
Position position = await _determinePosition();
|
||||
final result = await ApiService.addCoordinate( widget.itemData["IDENTIFICATIONPARTS_ID"],
|
||||
position.longitude.toString(),position.latitude.toString());
|
||||
if (result['result'] == 'success') {
|
||||
setState(() {
|
||||
_showMessage('提交成功');
|
||||
Navigator.pop(context);
|
||||
});
|
||||
|
||||
}else{
|
||||
_showMessage('加载数据失败');
|
||||
}
|
||||
} catch (e) {
|
||||
// 出错时可以 Toast 或者在页面上显示错误状态
|
||||
print('加载数据失败:$e');
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
@ -78,17 +127,24 @@ class _RiskDetailPageState extends State<RiskDetailPage> {
|
|||
physics: const ClampingScrollPhysics(),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: _dataInfos.map(_itemCell).toList(),
|
||||
children: [
|
||||
_itemCell("存在风险",0),
|
||||
_itemCell("主要管控措施",1),
|
||||
_itemCell("管控部门",2),
|
||||
_itemCell("事故类型",3),
|
||||
const Divider(
|
||||
height: .5,
|
||||
thickness: .5,
|
||||
color: Colors.grey,
|
||||
),
|
||||
_buildFooter(),
|
||||
],
|
||||
// children: _dataInfos.map(_itemCell).toList(),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
const Divider(
|
||||
height: .5,
|
||||
thickness: .5,
|
||||
color: Colors.grey,
|
||||
),
|
||||
_buildFooter(),
|
||||
|
||||
],
|
||||
),
|
||||
),
|
||||
|
@ -112,12 +168,12 @@ class _RiskDetailPageState extends State<RiskDetailPage> {
|
|||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
const Text(
|
||||
"风险点位",
|
||||
Text(
|
||||
widget.itemData['RISKUNITNAME']?? "",
|
||||
style: TextStyle(fontSize: 16, color: Colors.black54),
|
||||
),
|
||||
Text(
|
||||
widget.itemData?['location'] ?? "未知地区",
|
||||
widget.itemData['PARTSNAME'] ?? "未知地区",
|
||||
style: const TextStyle(fontSize: 16, color: Colors.black54),
|
||||
),
|
||||
],
|
||||
|
@ -135,12 +191,12 @@ class _RiskDetailPageState extends State<RiskDetailPage> {
|
|||
margin: const EdgeInsets.only(bottom: 8),
|
||||
padding: const EdgeInsets.all(5),
|
||||
decoration: BoxDecoration(
|
||||
color: const Color(0xFFFADBD9),
|
||||
color: _getLevelColor(),
|
||||
borderRadius: BorderRadius.circular(2),
|
||||
),
|
||||
child: Text(
|
||||
"风险等级",
|
||||
style: TextStyle(color: const Color(0xFFE54D42)),
|
||||
_getLevel(),
|
||||
style: TextStyle(color: Colors.black),
|
||||
),
|
||||
),
|
||||
const Spacer(),
|
||||
|
@ -149,6 +205,38 @@ class _RiskDetailPageState extends State<RiskDetailPage> {
|
|||
);
|
||||
}
|
||||
|
||||
String _getLevel(){
|
||||
int level;
|
||||
// 确保level在有效范围内 (1-4)
|
||||
// level = level.clamp(1, 4) - 1;
|
||||
if(widget.itemData['LEVELID']=="levelA"){
|
||||
level=0;
|
||||
}else if(widget.itemData['LEVELID']=="levelB"){
|
||||
level=1;
|
||||
}else if(widget.itemData['LEVELID']=="levelC"){
|
||||
level=2;
|
||||
}else {
|
||||
level=3;
|
||||
}
|
||||
return _levelTexts[level];
|
||||
}
|
||||
|
||||
Color _getLevelColor(){
|
||||
int level;
|
||||
// 确保level在有效范围内 (1-4)
|
||||
// level = level.clamp(1, 4) - 1;
|
||||
if(widget.itemData['LEVELID']=="levelA"){
|
||||
level=0;
|
||||
}else if(widget.itemData['LEVELID']=="levelB"){
|
||||
level=1;
|
||||
}else if(widget.itemData['LEVELID']=="levelC"){
|
||||
level=2;
|
||||
}else {
|
||||
level=3;
|
||||
}
|
||||
return _fxColors[level];
|
||||
}
|
||||
|
||||
// 底部按钮
|
||||
Widget _buildBottomButton() {
|
||||
return Padding(
|
||||
|
@ -167,6 +255,7 @@ class _RiskDetailPageState extends State<RiskDetailPage> {
|
|||
),
|
||||
onPressed: () {
|
||||
// 按钮点击事件
|
||||
_addCoordinate();
|
||||
},
|
||||
child: const Text(
|
||||
"提交位置",
|
||||
|
@ -177,9 +266,11 @@ class _RiskDetailPageState extends State<RiskDetailPage> {
|
|||
);
|
||||
}
|
||||
|
||||
// 单项信息组件
|
||||
Widget _itemCell(Map<String, dynamic> item) {
|
||||
final details = item["detail"] as List<String>;
|
||||
|
||||
|
||||
// 多项项信息组件
|
||||
Widget _itemCell(String title,int type) {
|
||||
// final details = item["detail"] as List<String>;
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 8),
|
||||
child: Column(
|
||||
|
@ -198,7 +289,7 @@ class _RiskDetailPageState extends State<RiskDetailPage> {
|
|||
),
|
||||
const SizedBox(width: 5),
|
||||
Text(
|
||||
item["title"],
|
||||
title,
|
||||
style: const TextStyle(
|
||||
fontSize: 15,
|
||||
fontWeight: FontWeight.bold,
|
||||
|
@ -208,13 +299,76 @@ class _RiskDetailPageState extends State<RiskDetailPage> {
|
|||
],
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
// 内容区域
|
||||
...details.map((text) => _textItem(text, false)).toList(),
|
||||
// // 内容区域
|
||||
// ...details.map((text) => _textItem(text, false)).toList(),
|
||||
|
||||
if(0==type||1==type)
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
for(int i = 0; i < _list.length; i++)
|
||||
_getWitchItem(type, i),
|
||||
],)
|
||||
else
|
||||
_getWitchItemTwo(type, type),
|
||||
|
||||
|
||||
|
||||
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
Widget _getWitchItem(int type,int position) {
|
||||
String text="";
|
||||
switch(type){
|
||||
case 0:
|
||||
text= "$position.${_list[position]["RISK_DESCR"]}";
|
||||
break;
|
||||
case 1:
|
||||
text= "$position.${_list[position]["MEASURES"]}";
|
||||
break;
|
||||
// case 2:
|
||||
// text= _list[position]["RISK_DESCR"];
|
||||
// break;
|
||||
// case 3:
|
||||
// text= _list[position]["RISK_DESCR"];
|
||||
// break;
|
||||
}
|
||||
|
||||
return _textItem(text,false);
|
||||
}
|
||||
|
||||
Widget _getWitchItemTwo(int type,int position) {
|
||||
String text="";
|
||||
switch(type){
|
||||
// case 0:
|
||||
// text= _list[position]["RISK_DESCR"];
|
||||
// break;
|
||||
// case 1:
|
||||
// text= _list[position]["MEASURES"];
|
||||
// break;
|
||||
case 2:
|
||||
text= widget.itemData["DEPT_NAME"];
|
||||
break;
|
||||
case 3:
|
||||
for(int i=0;i<_list.length;i++){
|
||||
if(text.isEmpty){
|
||||
text=_list[i]["ACCIDENTS_NAME"];
|
||||
}else{
|
||||
text="$text,${_list[i]["ACCIDENTS_NAME"]}";
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return _textItem(text,false);
|
||||
}
|
||||
|
||||
// 文本项组件
|
||||
Widget _textItem(String text, bool isInfinity) {
|
||||
return Container(
|
||||
|
@ -235,4 +389,36 @@ class _RiskDetailPageState extends State<RiskDetailPage> {
|
|||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<Position> _determinePosition() async {
|
||||
bool serviceEnabled;
|
||||
LocationPermission permission;
|
||||
|
||||
// 检查定位服务是否启用
|
||||
serviceEnabled = await Geolocator.isLocationServiceEnabled();
|
||||
if (!serviceEnabled) {
|
||||
return Future.error('Location services are disabled.');
|
||||
}
|
||||
|
||||
// 获取权限
|
||||
permission = await Geolocator.checkPermission();
|
||||
if (permission == LocationPermission.denied) {
|
||||
permission = await Geolocator.requestPermission();
|
||||
if (permission == LocationPermission.denied) {
|
||||
return Future.error('Location permissions are denied');
|
||||
}
|
||||
}
|
||||
|
||||
if (permission == LocationPermission.deniedForever) {
|
||||
return Future.error(
|
||||
'Location permissions are permanently denied, we cannot request permissions.');
|
||||
}
|
||||
|
||||
// 获取当前位置
|
||||
return await Geolocator.getCurrentPosition(desiredAccuracy: LocationAccuracy.high);
|
||||
}
|
||||
|
||||
void _showMessage(String msg) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(msg)));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:qhd_prevention/pages/my_appbar.dart';
|
||||
|
||||
import '../../http/ApiService.dart';
|
||||
|
||||
class UserinfoPage extends StatefulWidget {
|
||||
const UserinfoPage({super.key});
|
||||
|
||||
|
@ -9,6 +11,35 @@ class UserinfoPage extends StatefulWidget {
|
|||
}
|
||||
|
||||
class _UserinfoPageState extends State<UserinfoPage> {
|
||||
|
||||
Map<String, dynamic> user = {};
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
// TODO: implement initState
|
||||
super.initState();
|
||||
|
||||
_getUserInfo();
|
||||
}
|
||||
|
||||
Future<void> _getUserInfo() async {
|
||||
try {
|
||||
|
||||
final result = await ApiService.getUserInfo();
|
||||
if (result['result'] == 'success') {
|
||||
setState(() {
|
||||
user= result['pd'];
|
||||
});
|
||||
|
||||
}else{
|
||||
_showMessage('加载数据失败');
|
||||
}
|
||||
} catch (e) {
|
||||
// 出错时可以 Toast 或者在页面上显示错误状态
|
||||
print('加载数据失败:$e');
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
|
@ -16,9 +47,19 @@ class _UserinfoPageState extends State<UserinfoPage> {
|
|||
body: SafeArea(
|
||||
child: ListView(
|
||||
children: [
|
||||
_userItemCell("姓名", "-----", false),
|
||||
_userItemCell("部门", "-----", false),
|
||||
_userItemCell("岗位", "-----", true),
|
||||
_userItemCell("姓名", user["NAME"]??"", false),
|
||||
Divider(height: 1),
|
||||
_userItemCell("性别", user["SEX_NAME"]??"", false),
|
||||
Divider(height: 1),
|
||||
_userItemCell("部门", user["DEPARTMENT_NAME"]??"", false),
|
||||
Divider(height: 1),
|
||||
_userItemCell("岗位", user["DUTIES_NAME"]??"", true),
|
||||
Divider(height: 1),
|
||||
_userItemCell("人员类型", user["PERSONNEL_TYPE_NAME"]??"", false),
|
||||
Divider(height: 1),
|
||||
_userItemCell("入职时间", user["ENTRY_DATE"]??"", false),
|
||||
Divider(height: 1),
|
||||
_userItemCell("工种", user["TYPE_OF_WORK_NAME"]??"", false),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
@ -47,11 +88,11 @@ class _UserinfoPageState extends State<UserinfoPage> {
|
|||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Text(title, style: const TextStyle(fontSize: 16, color: Colors.grey)),
|
||||
Text(title, style: const TextStyle(fontSize: 16, )),
|
||||
Flexible(
|
||||
child: Text(
|
||||
detail,
|
||||
style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w500),
|
||||
style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w500,color: Colors.grey),
|
||||
textAlign: TextAlign.right,
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
|
@ -61,4 +102,9 @@ class _UserinfoPageState extends State<UserinfoPage> {
|
|||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _showMessage(String msg) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(msg)));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,61 +1,145 @@
|
|||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:qhd_prevention/customWidget/department_picker.dart';
|
||||
import 'package:qhd_prevention/pages/home/work/risk_list_picker.dart';
|
||||
import 'package:qhd_prevention/pages/home/work/wait_list_picker.dart';
|
||||
import '../../../customWidget/bottom_picker.dart';
|
||||
import '../../../http/ApiService.dart';
|
||||
import '../../../tools/h_colors.dart';
|
||||
import '/customWidget/custom_button.dart';
|
||||
import '../../../tools/tools.dart';
|
||||
|
||||
/// 自定义抽屉
|
||||
class CustomDriverDrawer extends StatefulWidget {
|
||||
const CustomDriverDrawer({super.key});
|
||||
const CustomDriverDrawer(this.treeJson, {super.key,required this.onClose});
|
||||
|
||||
final Function(String,String,String) onClose; // 回调函数
|
||||
final String treeJson;
|
||||
|
||||
@override
|
||||
_CustomDriverDrawerState createState() => _CustomDriverDrawerState();
|
||||
}
|
||||
|
||||
class _CustomDriverDrawerState extends State<CustomDriverDrawer> {
|
||||
// 四个选项的单选 index
|
||||
int _selectedOption = -1;
|
||||
// 已选择的分类 id
|
||||
String? _selectedCategoryId;
|
||||
|
||||
// 管控部门 id
|
||||
String? riskId;
|
||||
// 风险点(单元)id
|
||||
String? dept;
|
||||
|
||||
//风险等级
|
||||
int _levelOption = -1;
|
||||
List<String> dangerStatusId = ["levelA", "levelB", "levelC", "levelD"];
|
||||
|
||||
List<WaitListBean> jsonList =[];
|
||||
String itemNameOne="请选择";
|
||||
String itemNameTwo="请选择";
|
||||
late List<RiskListBean> _list = [];
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
// TODO: implement initState
|
||||
super.initState();
|
||||
|
||||
setState(() {
|
||||
|
||||
try {
|
||||
String? dangerJson = SessionService.instance.riskJson;
|
||||
if(null!=dangerJson&&dangerJson.isNotEmpty) {
|
||||
Map<String, dynamic> dangerWaitBean = json.decode(dangerJson);
|
||||
riskId= dangerWaitBean["riskId"];
|
||||
dept= dangerWaitBean["dept"];
|
||||
_levelOption= dangerWaitBean["levelOption"];
|
||||
|
||||
itemNameOne= dangerWaitBean["itemNameOne"];
|
||||
itemNameTwo= dangerWaitBean["itemNameTwo"];
|
||||
}
|
||||
|
||||
jsonList = parseDepartments(widget.treeJson);
|
||||
} catch (e) {
|
||||
print("解析失败: $e");
|
||||
}
|
||||
|
||||
// // 解析JSON字符串
|
||||
// jsonList = json.decode(widget.treeJson);
|
||||
// departmentList = List<Map<String, dynamic>>.from(jsonList);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
List<WaitListBean> parseDepartments(String jsonString) {
|
||||
// 1. 解码 JSON 字符串
|
||||
final List<dynamic> jsonList = json.decode(jsonString);
|
||||
|
||||
// 2. 转换为部门对象列表
|
||||
return jsonList
|
||||
.map((jsonItem) => WaitListBean.fromJson(jsonItem))
|
||||
.toList();
|
||||
}
|
||||
|
||||
List<RiskListBean> parseRiskListBean(List<dynamic> jsonList) {
|
||||
|
||||
// 2. 转换为部门对象列表
|
||||
return jsonList
|
||||
.map((jsonItem) => RiskListBean.fromJson(jsonItem))
|
||||
.toList();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final List<String> items = ["重大风险", "较大风险", "一般风险", "低风险"];
|
||||
final List<Category> data = [
|
||||
Category(
|
||||
id: '1',
|
||||
title: '分类一1',
|
||||
children: [
|
||||
Category(id: '1-1', title: '子项 1-1'),
|
||||
Category(id: '1-2', title: '子项 1-2'),
|
||||
],
|
||||
),
|
||||
Category(id: '2', title: '分类二'),
|
||||
Category(
|
||||
id: '3',
|
||||
title: '分类三',
|
||||
children: [
|
||||
Category(id: '3-1', title: '子项 3-1', children: [
|
||||
Category(id: '3-1-1', title: '子项 3-1-1'),
|
||||
]),
|
||||
],
|
||||
),
|
||||
];
|
||||
final List<String> dangerStatus = ["重大风险", "较大风险", "一般风险", "低风险"];
|
||||
|
||||
|
||||
// 显示分类选择器
|
||||
void showCategoryPicker() {
|
||||
void showCategoryPicker(String type) {
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
isScrollControlled: true,
|
||||
barrierColor: Colors.black54,
|
||||
backgroundColor: Colors.transparent,
|
||||
builder: (ctx) => DepartmentPicker(
|
||||
data: data,
|
||||
onSelected: (selectedId) {
|
||||
builder: (ctx) => WaitListPicker(
|
||||
data: jsonList,
|
||||
onSelected: (item) {
|
||||
setState(() {
|
||||
_selectedCategoryId = selectedId;
|
||||
// if("1"==type){
|
||||
dept= item?.id;
|
||||
itemNameOne= item!.name;
|
||||
// }else{
|
||||
riskId = null;
|
||||
itemNameTwo="";
|
||||
// }
|
||||
|
||||
setResult();
|
||||
});
|
||||
_getTreeListUnit();
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// 显示分类选择器
|
||||
void showCategoryPickerTwo(String type) {
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
isScrollControlled: true,
|
||||
barrierColor: Colors.black54,
|
||||
backgroundColor: Colors.transparent,
|
||||
builder: (ctx) => RiskListPicker(
|
||||
data: _list,
|
||||
onSelected: (item) {
|
||||
setState(() {
|
||||
// if("1"==type){
|
||||
// dept= item?.id;
|
||||
// itemNameOne= item!.name;
|
||||
// }else{
|
||||
riskId = item?.id;
|
||||
itemNameTwo=item!.name;
|
||||
// }
|
||||
|
||||
setResult();
|
||||
});
|
||||
|
||||
},
|
||||
),
|
||||
);
|
||||
|
@ -77,32 +161,24 @@ class _CustomDriverDrawerState extends State<CustomDriverDrawer> {
|
|||
),
|
||||
const Divider(height: 24, color: Colors.grey),
|
||||
|
||||
|
||||
// 管控部门
|
||||
_buildDropdownBox(
|
||||
"管控部门",
|
||||
display: _selectedCategoryId ?? '请选择',
|
||||
onTap: showCategoryPicker,
|
||||
"管控部门",
|
||||
display: itemNameOne ?? '请选择',
|
||||
onTap: () {
|
||||
showCategoryPicker("1");
|
||||
}
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
|
||||
// 风险点(单元)
|
||||
_buildDropdownBox(
|
||||
"风险点(单元)",
|
||||
display: '请选择',
|
||||
onTap: () {
|
||||
final choice = BottomPicker.show<String>(
|
||||
context,
|
||||
items: ['未知'],
|
||||
itemBuilder: (item) => Text(item, textAlign: TextAlign.center),
|
||||
initialIndex: 0,
|
||||
);
|
||||
if (choice != null) {
|
||||
// 用户点击确定并选择了 choice
|
||||
setState(() {
|
||||
|
||||
});
|
||||
"风险点(单元)",
|
||||
display: itemNameTwo ?? '请选择',
|
||||
onTap: () {
|
||||
showCategoryPickerTwo("2");
|
||||
}
|
||||
},
|
||||
),
|
||||
|
||||
const SizedBox(height: 24),
|
||||
|
@ -114,21 +190,28 @@ class _CustomDriverDrawerState extends State<CustomDriverDrawer> {
|
|||
|
||||
// 风险等级:一行一个
|
||||
Column(
|
||||
children: List.generate(items.length, (idx) {
|
||||
final bool selected = _selectedOption == idx;
|
||||
children: List.generate(dangerStatus.length, (idx) {
|
||||
final bool selected = _levelOption == idx;
|
||||
return GestureDetector(
|
||||
onTap: () => setState(() => _selectedOption = idx),
|
||||
onTap: (){
|
||||
setState(() {
|
||||
_levelOption = idx;
|
||||
|
||||
setResult();
|
||||
});
|
||||
} ,
|
||||
// onTap: () => setState(() => _dangerStatusOption = idx),
|
||||
child: Container(
|
||||
width: double.infinity,
|
||||
margin: const EdgeInsets.only(bottom: 8),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 6),
|
||||
decoration: BoxDecoration(
|
||||
color: selected ? Colors.blue : Colors.transparent,
|
||||
borderRadius: BorderRadius.circular(4),
|
||||
border: Border.all(color: Colors.blue, width: 1),
|
||||
),
|
||||
child: Text(
|
||||
items[idx],
|
||||
dangerStatus[idx],
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: selected ? Colors.white : Colors.blue,
|
||||
|
@ -150,8 +233,14 @@ class _CustomDriverDrawerState extends State<CustomDriverDrawer> {
|
|||
textStyle: const TextStyle(color: Colors.black45),
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
_selectedOption = -1;
|
||||
_selectedCategoryId = null;
|
||||
|
||||
riskId = null;
|
||||
dept=null;
|
||||
_levelOption = -1;
|
||||
itemNameOne="请选择";
|
||||
itemNameTwo="请选择";
|
||||
// widget.onClose("","","",);
|
||||
setResult();
|
||||
});
|
||||
},
|
||||
),
|
||||
|
@ -164,6 +253,7 @@ class _CustomDriverDrawerState extends State<CustomDriverDrawer> {
|
|||
backgroundColor: Colors.blue,
|
||||
onPressed: () {
|
||||
// TODO: 提交筛选条件
|
||||
Navigator.pop(context); // 关闭加载对话框
|
||||
},
|
||||
),
|
||||
),
|
||||
|
@ -193,7 +283,7 @@ class _CustomDriverDrawerState extends State<CustomDriverDrawer> {
|
|||
const Spacer(),
|
||||
Row(
|
||||
children: [
|
||||
Text(display),
|
||||
Text(_truncateText(display,9)),
|
||||
const Icon(Icons.arrow_drop_down, color: Colors.grey),
|
||||
],
|
||||
),
|
||||
|
@ -202,4 +292,100 @@ class _CustomDriverDrawerState extends State<CustomDriverDrawer> {
|
|||
),
|
||||
);
|
||||
}
|
||||
|
||||
// 文本截取函数
|
||||
String _truncateText(String text, int maxLength) {
|
||||
if (text.runes.length <= maxLength) {
|
||||
return text;
|
||||
}
|
||||
return String.fromCharCodes(text.runes.take(maxLength)) + '...';
|
||||
}
|
||||
|
||||
void setResult(){
|
||||
|
||||
DangerRiskBean waitBean= DangerRiskBean.fromJson(
|
||||
riskId ?? "", dept?? "",
|
||||
_levelOption,itemNameOne, itemNameTwo);
|
||||
|
||||
String jsonString = jsonEncode(waitBean.toJson());
|
||||
SessionService.instance.setRiskWaitInfo(jsonString);
|
||||
|
||||
widget.onClose(
|
||||
riskId ?? "",
|
||||
dept ?? "",
|
||||
_levelOption!=-1?dangerStatusId[_levelOption]:"",
|
||||
); // 触发回调
|
||||
}
|
||||
|
||||
Future<void> _getTreeListUnit( ) async {
|
||||
try {
|
||||
_list.clear();
|
||||
final result = await ApiService.getTreeListUnit( dept!);
|
||||
|
||||
if (result['result'] == 'success') {
|
||||
final List<dynamic> newList = result['unitList'] ?? [];
|
||||
|
||||
setState(() {
|
||||
_list.addAll(parseRiskListBean(newList));
|
||||
// _list.addAll(newList);
|
||||
});
|
||||
|
||||
|
||||
}else{
|
||||
_showMessage('加载数据失败');
|
||||
}
|
||||
|
||||
} catch (e) {
|
||||
// 出错时可以 Toast 或者在页面上显示错误状态
|
||||
print('加载数据失败:$e');
|
||||
}
|
||||
}
|
||||
|
||||
void _showMessage(String msg) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(msg)));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
class DangerRiskBean {
|
||||
|
||||
final String? riskId;
|
||||
final String? dept;
|
||||
|
||||
//风险等级
|
||||
final int levelOption;
|
||||
|
||||
final String itemNameOne;
|
||||
final String itemNameTwo;
|
||||
|
||||
DangerRiskBean({
|
||||
required this.riskId,
|
||||
required this.dept,
|
||||
required this.levelOption,
|
||||
required this.itemNameOne,
|
||||
required this.itemNameTwo,
|
||||
|
||||
|
||||
});
|
||||
|
||||
|
||||
factory DangerRiskBean.fromJson(String riskId, String dept,
|
||||
int levelOption,
|
||||
String itemNameOne, String itemNameTwo,) {
|
||||
return DangerRiskBean(
|
||||
riskId: riskId,
|
||||
dept: dept,
|
||||
levelOption: levelOption,
|
||||
itemNameOne: itemNameOne,
|
||||
itemNameTwo: itemNameTwo,
|
||||
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {"riskId": riskId, "dept": dept,
|
||||
"levelOption": levelOption,
|
||||
"itemNameOne": itemNameOne, "itemNameTwo": itemNameTwo,};
|
||||
}
|
||||
}
|
|
@ -8,12 +8,16 @@ import 'package:qhd_prevention/pages/home/work/danger_wait_list_page.dart';
|
|||
import 'package:qhd_prevention/pages/my_appbar.dart';
|
||||
import 'package:qhd_prevention/tools/h_colors.dart';
|
||||
import '../../../customWidget/ItemWidgetFactory.dart';
|
||||
import '../../../customWidget/single_image_viewer.dart';
|
||||
import '../../../http/ApiService.dart';
|
||||
import '../../../tools/tools.dart';
|
||||
import 'dangerTypeItems/finish/danner_repair_finish.dart';
|
||||
|
||||
class DangerRepairPage extends StatefulWidget {
|
||||
const DangerRepairPage(this.dangerType, {Key? key}) : super(key: key);
|
||||
const DangerRepairPage(this.dangerType, this.item, {Key? key}) : super(key: key);
|
||||
|
||||
final DangerType dangerType;
|
||||
final item;
|
||||
|
||||
@override
|
||||
State<DangerRepairPage> createState() => _DangerRepairPageState();
|
||||
|
@ -22,6 +26,29 @@ class DangerRepairPage extends StatefulWidget {
|
|||
class _DangerRepairPageState extends State<DangerRepairPage> {
|
||||
// 是否整改
|
||||
bool _accepted = false;
|
||||
List<dynamic> hImgs = [];
|
||||
List<dynamic> rImgs = [];
|
||||
dynamic pd;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
// TODO: implement initState
|
||||
super.initState();
|
||||
if (widget.dangerType == DangerType.ristRecord){// 跳转到隐患记录页面
|
||||
_getDangerDetail();
|
||||
}else if (widget.dangerType == DangerType.wait){// 跳转到待整改隐患页面
|
||||
|
||||
}else if (widget.dangerType == DangerType.expired){// 跳转到超期未整改页面
|
||||
|
||||
}else if (widget.dangerType == DangerType.waitAcceptance){// 跳转到隐患验收页面
|
||||
|
||||
}else{// 跳转到已验收隐患页面
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
|
@ -37,7 +64,9 @@ class _DangerRepairPageState extends State<DangerRepairPage> {
|
|||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
// 隐患详情
|
||||
DangerDetail(),
|
||||
// DangerDetail(),
|
||||
DangerPageDetail(),
|
||||
|
||||
SizedBox(height: 15),
|
||||
if (widget.dangerType == DangerType.wait) // 隐患整改
|
||||
_danner_type_wait()
|
||||
|
@ -155,4 +184,195 @@ class _DangerRepairPageState extends State<DangerRepairPage> {
|
|||
],
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Future<void> _getDangerDetail() async {
|
||||
try {
|
||||
|
||||
final result = await ApiService.getDangerDetail(widget.item['HIDDEN_ID']);
|
||||
if (result['result'] == 'success') {
|
||||
setState(() {
|
||||
hImgs= result['hImgs'];
|
||||
rImgs= result['rImgs'];
|
||||
pd= result['pd'];
|
||||
|
||||
});
|
||||
}else{
|
||||
_showMessage('加载数据失败');
|
||||
}
|
||||
} catch (e) {
|
||||
// 出错时可以 Toast 或者在页面上显示错误状态
|
||||
print('加载数据失败:$e');
|
||||
}
|
||||
}
|
||||
|
||||
void _showMessage(String msg) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(msg)));
|
||||
}
|
||||
|
||||
|
||||
final List<String> imgUrls = [
|
||||
"https://picsum.photos/id/237/200/300",
|
||||
"https://pic.rmb.bdstatic.com/bjh/news/100b8b78cbd136ede03249d9f3b3f5c42221.jpeg",
|
||||
];
|
||||
Widget DangerPageDetail() {
|
||||
return Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(5),
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
ListView(
|
||||
shrinkWrap: true,
|
||||
physics: NeverScrollableScrollPhysics(),
|
||||
children: [
|
||||
ListItemFactory.createRowSpaceBetweenItem(
|
||||
leftText: "隐患描述",
|
||||
rightText: pd["HIDDENDESCR"],
|
||||
),
|
||||
Divider(height: 1),
|
||||
ListItemFactory.createRowSpaceBetweenItem(
|
||||
leftText: "隐患来源",
|
||||
rightText: _getSourceDangers(pd),
|
||||
),
|
||||
Divider(height: 1),
|
||||
ListItemFactory.createRowSpaceBetweenItem(
|
||||
leftText: "风险点(单元)",
|
||||
rightText: pd["RISK_UNIT"],
|
||||
),
|
||||
Divider(height: 1),
|
||||
ListItemFactory.createRowSpaceBetweenItem(
|
||||
leftText: "辨识部位",
|
||||
rightText: pd["IDENTIFICATION"],
|
||||
),
|
||||
Divider(height: 1),
|
||||
ListItemFactory.createColumnTextItem(
|
||||
topText: "存在风险",
|
||||
bottomText: pd["RISK_DESCR"],
|
||||
),
|
||||
Divider(height: 1),
|
||||
ListItemFactory.createRowSpaceBetweenItem(
|
||||
leftText: "风险分级",
|
||||
rightText: pd["LEVEL"],
|
||||
),
|
||||
Divider(height: 1),
|
||||
|
||||
ListItemFactory.createColumnTextItem(
|
||||
topText: "检测内容",
|
||||
bottomText: pd["CHECK_CONTENT"],
|
||||
),
|
||||
Divider(height: 1),
|
||||
ListItemFactory.createRowSpaceBetweenItem(
|
||||
leftText: "隐患部位",
|
||||
rightText: pd["HIDDENPART"],
|
||||
),
|
||||
Divider(height: 1),
|
||||
ListItemFactory.createRowSpaceBetweenItem(
|
||||
leftText: "发现人",
|
||||
rightText: pd["CREATORNAME"],
|
||||
),
|
||||
Divider(height: 1),
|
||||
ListItemFactory.createRowSpaceBetweenItem(
|
||||
leftText: "发现时间",
|
||||
rightText: pd["CREATTIME"],
|
||||
),
|
||||
Divider(height: 1),
|
||||
ListItemFactory.createRowSpaceBetweenItem(
|
||||
leftText: "隐患类型",
|
||||
rightText: pd["HIDDENTYPE_NAME"],
|
||||
),
|
||||
Divider(height: 1),
|
||||
ListItemFactory.createRowSpaceBetweenItem(
|
||||
leftText: "整改类型",
|
||||
rightText: _getZhengGaiType(pd),
|
||||
),
|
||||
Divider(height: 1),
|
||||
|
||||
|
||||
],
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// itemCount: 16,
|
||||
// separatorBuilder: (_, __) => const Divider(height: 1),
|
||||
// itemBuilder: (context, index) {
|
||||
// Widget item;
|
||||
// // if (index == 0) {
|
||||
// // item = ListItemFactory.createAloneTextItem(
|
||||
// // text: "地坪漆漆未分配全皮肤期漆未分配全皮肤期漆未分配全皮肤期未分配全皮肤期间哦飞机哦脾气金佛怕",
|
||||
// // );
|
||||
// // } else
|
||||
// if ((index == 0 && index < 4) ||
|
||||
// index == 5 ||
|
||||
// (index > 6 && index < 15)) {
|
||||
// item = ListItemFactory.createRowSpaceBetweenItem(
|
||||
// leftText: "隐患来源",
|
||||
// rightText: "隐患排查",
|
||||
// );
|
||||
// } else if (index == 4 || index == 6) {
|
||||
// item = ListItemFactory.createColumnTextItem(
|
||||
// topText: "存在风险",
|
||||
// bottomText: "哦IQ好然后前后hi前后哦i",
|
||||
// );
|
||||
// } else {
|
||||
// item = ListItemFactory.createTextImageItem(
|
||||
// text: "隐患照片",
|
||||
// imageUrls: imgUrls,
|
||||
// onImageTapped: (index) {
|
||||
// present(
|
||||
// SingleImageViewer(imageUrl: imgUrls[index]),
|
||||
// context,
|
||||
// );
|
||||
// },
|
||||
// );
|
||||
// }
|
||||
//
|
||||
// // 给每个 item 单独加左右内边距
|
||||
// return Padding(
|
||||
// padding: const EdgeInsets.symmetric(
|
||||
// horizontal: 12,
|
||||
// vertical: 8,
|
||||
// ),
|
||||
// child: item,
|
||||
// );
|
||||
// },
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
String _getSourceDangers(final item) {
|
||||
String type = item["SOURCE"];
|
||||
if("1"==type){
|
||||
return "隐患来源:隐患快报";
|
||||
}else if("2"==type){
|
||||
return "隐患来源:隐患排查清单检查";
|
||||
}else if("3"==type){
|
||||
return "隐患来源:标准排查清单检查";
|
||||
}else if("4"==type){
|
||||
return "隐患来源:专项检查";
|
||||
}else{
|
||||
return "隐患来源:安全检查";
|
||||
}
|
||||
}
|
||||
|
||||
String _getZhengGaiType(final item) {
|
||||
String type = item["RECTIFICATIONTYPE"];
|
||||
if("1"==type){
|
||||
return "立即整改";
|
||||
}else {
|
||||
return "限期整改";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -3,23 +3,97 @@ import 'dart:convert';
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:qhd_prevention/customWidget/department_picker.dart';
|
||||
import 'package:qhd_prevention/pages/home/work/wait_list_picker.dart';
|
||||
import '../../../customWidget/bottom_picker.dart';
|
||||
import '../../../tools/h_colors.dart';
|
||||
import '/customWidget/custom_button.dart';
|
||||
import '../../../tools/tools.dart';
|
||||
|
||||
|
||||
class DangerWaitBean {
|
||||
|
||||
final String? selectedCategoryId;
|
||||
final String? selectedDepartmentId;
|
||||
|
||||
// 排查方式
|
||||
final int investigationMethodOption;
|
||||
final int investigationMethodId;
|
||||
//隐患级别
|
||||
final int hazardLevelOption ;
|
||||
//风险等级
|
||||
final int dangerStatusOption ;
|
||||
|
||||
// 新增:开始/结束时间
|
||||
final String startTime;
|
||||
final String endTime;
|
||||
final String itemNameOne;
|
||||
final String itemNameTwo;
|
||||
|
||||
DangerWaitBean({
|
||||
required this.selectedCategoryId,
|
||||
required this.selectedDepartmentId,
|
||||
required this.investigationMethodOption,
|
||||
required this.investigationMethodId,
|
||||
required this.hazardLevelOption,
|
||||
required this.dangerStatusOption,
|
||||
|
||||
required this.startTime,
|
||||
required this.endTime,
|
||||
required this.itemNameOne,
|
||||
required this.itemNameTwo,
|
||||
|
||||
|
||||
});
|
||||
|
||||
|
||||
factory DangerWaitBean.fromJson(String selectedCategoryId,String selectedDepartmentId,
|
||||
int investigationMethodOption, int investigationMethodId,
|
||||
int hazardLevelOption, int dangerStatusOption,
|
||||
|
||||
String startTime,String endTime,
|
||||
String itemNameOne,String itemNameTwo,
|
||||
) {
|
||||
return DangerWaitBean(
|
||||
selectedCategoryId:selectedCategoryId,
|
||||
selectedDepartmentId:selectedDepartmentId,
|
||||
investigationMethodOption:investigationMethodOption,
|
||||
investigationMethodId:investigationMethodId,
|
||||
hazardLevelOption:hazardLevelOption,
|
||||
dangerStatusOption:dangerStatusOption,
|
||||
|
||||
startTime:startTime,
|
||||
endTime:endTime,
|
||||
itemNameOne:itemNameOne,
|
||||
itemNameTwo:itemNameTwo,
|
||||
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {"selectedCategoryId":selectedCategoryId,"selectedDepartmentId":selectedDepartmentId,
|
||||
"investigationMethodOption":investigationMethodOption,"investigationMethodId":investigationMethodId,
|
||||
"hazardLevelOption":hazardLevelOption,"dangerStatusOption":dangerStatusOption,
|
||||
"startTime":startTime,"endTime":endTime,
|
||||
"itemNameOne":itemNameOne,"itemNameTwo":itemNameTwo,};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// 自定义抽屉
|
||||
class DangerWaitDrawer extends StatefulWidget {
|
||||
const DangerWaitDrawer(this.treeJson, {super.key,required this.onClose});
|
||||
|
||||
final Function(String,String,String,String,String,String,String) onClose; // 回调函数
|
||||
final String treeJson;
|
||||
// final DangerWaitBean waitBean;
|
||||
|
||||
|
||||
|
||||
@override
|
||||
_DangerWaitDrawerState createState() => _DangerWaitDrawerState();
|
||||
DangerWaitDrawerState createState() => DangerWaitDrawerState();
|
||||
}
|
||||
|
||||
class _DangerWaitDrawerState extends State<DangerWaitDrawer> {
|
||||
class DangerWaitDrawerState extends State<DangerWaitDrawer> {
|
||||
|
||||
// 检查部门分类 id
|
||||
String? _selectedCategoryId;
|
||||
|
@ -43,20 +117,64 @@ class _DangerWaitDrawerState extends State<DangerWaitDrawer> {
|
|||
DateTime? _endDate;
|
||||
String startTime="";
|
||||
String endTime="";
|
||||
List<WaitListBean> jsonList =[];
|
||||
String itemNameOne="请选择";
|
||||
String itemNameTwo="请选择";
|
||||
|
||||
// 转换为List<Map<String, dynamic>>
|
||||
late List<Map<String, dynamic>> departmentList ;
|
||||
|
||||
|
||||
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
// TODO: implement initState
|
||||
super.initState();
|
||||
// 解析JSON字符串
|
||||
List<dynamic> jsonList = json.decode(widget.treeJson);
|
||||
|
||||
departmentList = List<Map<String, dynamic>>.from(jsonList);
|
||||
setState(() {
|
||||
|
||||
try {
|
||||
String? dangerJson = SessionService.instance.dangerJson;
|
||||
if(null!=dangerJson&&dangerJson.isNotEmpty) {
|
||||
Map<String, dynamic> dangerWaitBean = json.decode(dangerJson);
|
||||
_selectedCategoryId= dangerWaitBean["selectedCategoryId"];
|
||||
_selectedDepartmentId= dangerWaitBean["selectedDepartmentId"];
|
||||
|
||||
_investigationMethodOption= dangerWaitBean["investigationMethodOption"];
|
||||
investigationMethodId= dangerWaitBean["investigationMethodId"];
|
||||
_hazardLevelOption= dangerWaitBean["hazardLevelOption"];
|
||||
_dangerStatusOption= dangerWaitBean["dangerStatusOption"];
|
||||
|
||||
startTime= dangerWaitBean["startTime"];
|
||||
endTime= dangerWaitBean["endTime"];
|
||||
itemNameOne= dangerWaitBean["itemNameOne"];
|
||||
itemNameTwo= dangerWaitBean["itemNameTwo"];
|
||||
}
|
||||
|
||||
jsonList = parseDepartments(widget.treeJson);
|
||||
} catch (e) {
|
||||
print("解析失败: $e");
|
||||
}
|
||||
|
||||
// // 解析JSON字符串
|
||||
// jsonList = json.decode(widget.treeJson);
|
||||
// departmentList = List<Map<String, dynamic>>.from(jsonList);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
List<WaitListBean> parseDepartments(String jsonString) {
|
||||
// 1. 解码 JSON 字符串
|
||||
final List<dynamic> jsonList = json.decode(jsonString);
|
||||
|
||||
// 2. 转换为部门对象列表
|
||||
return jsonList
|
||||
.map((jsonItem) => WaitListBean.fromJson(jsonItem))
|
||||
.toList();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
@ -67,42 +185,50 @@ class _DangerWaitDrawerState extends State<DangerWaitDrawer> {
|
|||
|
||||
|
||||
|
||||
final List<Category> data = [
|
||||
Category(
|
||||
id: '1',
|
||||
title: '分类一1',
|
||||
children: [
|
||||
Category(id: '1-1', title: '子项 1-1'),
|
||||
Category(id: '1-2', title: '子项 1-2'),
|
||||
],
|
||||
),
|
||||
Category(id: '2', title: '分类二'),
|
||||
Category(
|
||||
id: '3',
|
||||
title: '分类三',
|
||||
children: [
|
||||
Category(id: '3-1', title: '子项 3-1', children: [
|
||||
Category(id: '3-1-1', title: '子项 3-1-1'),
|
||||
]),
|
||||
],
|
||||
),
|
||||
];
|
||||
// final List<WaitListBean> data = [
|
||||
// Category(
|
||||
// id: '1',
|
||||
// title: '分类一1',
|
||||
// children: [
|
||||
// Category(id: '1-1', title: '子项 1-1'),
|
||||
// Category(id: '1-2', title: '子项 1-2'),
|
||||
// ],
|
||||
// ),
|
||||
// Category(id: '2', title: '分类二'),
|
||||
// Category(
|
||||
// id: '3',
|
||||
// title: '分类三',
|
||||
// children: [
|
||||
// Category(id: '3-1', title: '子项 3-1', children: [
|
||||
// Category(id: '3-1-1', title: '子项 3-1-1'),
|
||||
// ]),
|
||||
// ],
|
||||
// ),
|
||||
// ];
|
||||
|
||||
|
||||
|
||||
|
||||
// 显示分类选择器
|
||||
void showCategoryPicker() {
|
||||
void showCategoryPicker(String type) {
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
isScrollControlled: true,
|
||||
barrierColor: Colors.black54,
|
||||
backgroundColor: Colors.transparent,
|
||||
builder: (ctx) => DepartmentPicker(
|
||||
data: data,
|
||||
onSelected: (selectedId) {
|
||||
builder: (ctx) => WaitListPicker(
|
||||
data: jsonList,
|
||||
onSelected: (item) {
|
||||
setState(() {
|
||||
_selectedCategoryId = selectedId;
|
||||
if("1"==type){
|
||||
_selectedCategoryId = item?.id;
|
||||
itemNameOne= item!.name;
|
||||
}else{
|
||||
_selectedDepartmentId= item?.id;
|
||||
itemNameTwo=item!.name;
|
||||
}
|
||||
|
||||
setResult();
|
||||
});
|
||||
},
|
||||
),
|
||||
|
@ -128,29 +254,35 @@ class _DangerWaitDrawerState extends State<DangerWaitDrawer> {
|
|||
// 管控部门
|
||||
_buildDropdownBox(
|
||||
"检查部门",
|
||||
display: _selectedCategoryId ?? '请选择',
|
||||
onTap: showCategoryPicker,
|
||||
display: itemNameOne ?? '请选择',
|
||||
onTap: () {
|
||||
showCategoryPicker("1");
|
||||
}
|
||||
),
|
||||
const SizedBox(height: 6),
|
||||
|
||||
// 风险点(单元)
|
||||
_buildDropdownBox(
|
||||
"整改部门",
|
||||
display: '请选择',
|
||||
onTap: () {
|
||||
final choice = BottomPicker.show<String>(
|
||||
context,
|
||||
items: ['未知'],
|
||||
itemBuilder: (item) => Text(item, textAlign: TextAlign.center),
|
||||
initialIndex: 0,
|
||||
);
|
||||
if (choice != null) {
|
||||
// 用户点击确定并选择了 choice
|
||||
setState(() {
|
||||
|
||||
});
|
||||
display: itemNameTwo ?? '请选择',
|
||||
onTap: () {
|
||||
showCategoryPicker("2");
|
||||
}
|
||||
},
|
||||
// display: '请选择',
|
||||
// onTap: () {
|
||||
// final choice = BottomPicker.show<String>(
|
||||
// context,
|
||||
// items: ['未知'],
|
||||
// itemBuilder: (item) => Text(item, textAlign: TextAlign.center),
|
||||
// initialIndex: 0,
|
||||
// );
|
||||
// if (choice != null) {
|
||||
// // 用户点击确定并选择了 choice
|
||||
// setState(() {
|
||||
//
|
||||
// });
|
||||
// }
|
||||
// },
|
||||
),
|
||||
|
||||
const SizedBox(height: 12),
|
||||
|
@ -329,7 +461,11 @@ class _DangerWaitDrawerState extends State<DangerWaitDrawer> {
|
|||
_startDate = null;
|
||||
_endDate = null;
|
||||
|
||||
widget.onClose("","","","","","","");
|
||||
itemNameOne="请选择";
|
||||
itemNameTwo="请选择";
|
||||
|
||||
setResult();
|
||||
// widget.onClose("","","","","","","");
|
||||
|
||||
});
|
||||
},
|
||||
|
@ -373,7 +509,7 @@ class _DangerWaitDrawerState extends State<DangerWaitDrawer> {
|
|||
const Spacer(),
|
||||
Row(
|
||||
children: [
|
||||
Text(display),
|
||||
Text(_truncateText(display,9)),
|
||||
const Icon(Icons.arrow_drop_down, color: Colors.grey),
|
||||
],
|
||||
),
|
||||
|
@ -384,6 +520,15 @@ class _DangerWaitDrawerState extends State<DangerWaitDrawer> {
|
|||
|
||||
}
|
||||
|
||||
|
||||
// 文本截取函数
|
||||
String _truncateText(String text, int maxLength) {
|
||||
if (text.runes.length <= maxLength) {
|
||||
return text;
|
||||
}
|
||||
return String.fromCharCodes(text.runes.take(maxLength)) + '...';
|
||||
}
|
||||
|
||||
Future<void> _pickStartDate() async {
|
||||
final now = DateTime.now();
|
||||
final picked = await showDatePicker(
|
||||
|
@ -467,7 +612,18 @@ class _DangerWaitDrawerState extends State<DangerWaitDrawer> {
|
|||
);
|
||||
}
|
||||
|
||||
|
||||
void setResult(){
|
||||
|
||||
DangerWaitBean waitBean= DangerWaitBean.fromJson(
|
||||
_selectedCategoryId ?? "", _selectedDepartmentId?? "",
|
||||
_investigationMethodOption,investigationMethodId,
|
||||
_hazardLevelOption, _dangerStatusOption,
|
||||
startTime, endTime,itemNameOne, itemNameTwo);
|
||||
|
||||
String jsonString = jsonEncode(waitBean.toJson());
|
||||
SessionService.instance.setDangerWaitInfo(jsonString);
|
||||
|
||||
widget.onClose(
|
||||
_selectedCategoryId ?? "",
|
||||
_selectedDepartmentId ?? "",
|
||||
|
|
|
@ -9,6 +9,7 @@ import '../../../http/ApiService.dart';
|
|||
import '../../app/application_page.dart';
|
||||
import '/customWidget/search_bar_widget.dart';
|
||||
import 'danger_wait_deawer.dart';
|
||||
import 'hidden_record_detail_page.dart';
|
||||
|
||||
enum DangerType {
|
||||
|
||||
|
@ -43,6 +44,9 @@ class _DangerWaitListPageState extends State<DangerWaitListPage> {
|
|||
bool _hasMore = true;
|
||||
|
||||
String treeJson="";
|
||||
// late DangerWaitBean waitBean;
|
||||
|
||||
|
||||
|
||||
|
||||
// 隐患等级颜色
|
||||
|
@ -61,7 +65,7 @@ class _DangerWaitListPageState extends State<DangerWaitListPage> {
|
|||
super.initState();
|
||||
|
||||
getListData(widget.appItem,false,"");
|
||||
_getListTree();
|
||||
SessionService.instance.setDangerWaitInfo("");
|
||||
|
||||
}
|
||||
|
||||
|
@ -69,6 +73,7 @@ class _DangerWaitListPageState extends State<DangerWaitListPage> {
|
|||
switch(widget.appItem ){
|
||||
case 1://隐患记录
|
||||
_getDangerRecord(-1,_page,"","","","","","","","",keyWord,addList);
|
||||
_getListTree();
|
||||
break;
|
||||
case 2://待整改隐患
|
||||
_getDangerRecord(2,_page,"","","","","","","","",keyWord,addList);
|
||||
|
@ -117,12 +122,14 @@ class _DangerWaitListPageState extends State<DangerWaitListPage> {
|
|||
child: Container(
|
||||
width: screenWidth * 3 / 5,
|
||||
color: Colors.white,
|
||||
child: DangerWaitDrawer( treeJson,
|
||||
child: DangerWaitDrawer(
|
||||
treeJson,
|
||||
onClose: (String selectedCategoryId,String selectedDepartmentId,String investigationMethodOption,
|
||||
String hazardLevelOption,String dangerStatusOption,String startDate,String endDate) {
|
||||
|
||||
_page=1;
|
||||
_getDangerRecord(-1,_page,startDate,endDate,hazardLevelOption,investigationMethodOption,
|
||||
dangerStatusOption,"","","",searchKey,false);
|
||||
dangerStatusOption,selectedCategoryId,selectedDepartmentId,"",searchKey,false);
|
||||
|
||||
},
|
||||
),
|
||||
|
@ -193,8 +200,25 @@ class _DangerWaitListPageState extends State<DangerWaitListPage> {
|
|||
// type: item.type,
|
||||
// context: context,
|
||||
// );
|
||||
pushPage(DangerRepairPage(widget.dangerType), context);
|
||||
|
||||
switch(widget.appItem ){
|
||||
case 1://隐患记录
|
||||
pushPage(HiddenRecordDetailPage(widget.dangerType,item), context);
|
||||
break;
|
||||
case 2://待整改隐患
|
||||
// _getDangerRecord(2,_page,"","","","","","","","",keyWord,addList);
|
||||
break;
|
||||
case 3://超期未整改
|
||||
// _getDangerRecord(5,_page,"","","","","-1","","","",keyWord,addList);
|
||||
break;
|
||||
case 4://隐患验收
|
||||
// _getDangerRecord(3,_page,"","","","","","3","","",keyWord,addList);
|
||||
break;
|
||||
case 5://已验收隐患
|
||||
// _getDangerRecord(4,_page,"","","","","","4","","1",keyWord,addList);
|
||||
break;
|
||||
|
||||
}
|
||||
},
|
||||
child: Container(
|
||||
// height: 100,
|
||||
|
@ -369,14 +393,9 @@ class _DangerWaitListPageState extends State<DangerWaitListPage> {
|
|||
|
||||
Future<void> _getListTree() async {
|
||||
try {
|
||||
if (_isLoading) return;
|
||||
_isLoading = true;
|
||||
|
||||
|
||||
final result = await ApiService.getHiddenTreatmentListTree();
|
||||
|
||||
if (result['result'] == 'success') {
|
||||
|
||||
setState(() {
|
||||
treeJson= result['zTreeNodes'];
|
||||
});
|
||||
|
|
|
@ -0,0 +1,266 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:qhd_prevention/customWidget/big_video_viewer.dart';
|
||||
import 'package:qhd_prevention/pages/my_appbar.dart';
|
||||
import 'dart:convert';
|
||||
import 'package:video_player/video_player.dart';
|
||||
|
||||
import '../../../customWidget/ItemWidgetFactory.dart';
|
||||
import '../../../customWidget/single_image_viewer.dart';
|
||||
import '../../../customWidget/video_player_widget.dart';
|
||||
import '../../../http/ApiService.dart';
|
||||
import '../../../tools/tools.dart';
|
||||
import 'danger_wait_list_page.dart';
|
||||
|
||||
|
||||
class HiddenRecordDetailPage extends StatefulWidget {
|
||||
const HiddenRecordDetailPage(this.dangerType, this.item, {Key? key}) : super(key: key);
|
||||
|
||||
final DangerType dangerType;
|
||||
final item;
|
||||
|
||||
@override
|
||||
_HiddenRecordDetailPageState createState() => _HiddenRecordDetailPageState();
|
||||
}
|
||||
|
||||
class _HiddenRecordDetailPageState extends State<HiddenRecordDetailPage> {
|
||||
late Map<String, dynamic> pd = {};
|
||||
late Map<String, dynamic> hs = {};
|
||||
List<String> files = [];
|
||||
List<String> files2 = [];
|
||||
List<dynamic> files4 = [];
|
||||
List<dynamic> files5 = [];
|
||||
List<dynamic> files6 = [];
|
||||
List<dynamic> videoList = [];
|
||||
List<dynamic> checkList = [];
|
||||
|
||||
bool modalShow = false;
|
||||
String videoSrc = "";
|
||||
VideoPlayerController? _videoController;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
getData();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_videoController?.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
Future<void> getData() async {
|
||||
try {
|
||||
final data = await ApiService.getDangerDetail(widget.item['HIDDEN_ID']);
|
||||
if (data['result'] == 'success') {
|
||||
|
||||
setState(() {
|
||||
pd = data['pd'];
|
||||
hs = data['hs'] ?? {};
|
||||
|
||||
// 处理图片和视频
|
||||
for (var img in data['hImgs']) {
|
||||
if (img['FILEPATH'].toString().endsWith('.mp4')) {
|
||||
videoList.add(img);
|
||||
} else {
|
||||
files.add(img["FILEPATH"]);
|
||||
}
|
||||
}
|
||||
|
||||
// List<dynamic> filesZheng = data['rImgs'] ?? [];
|
||||
for (var img in data['rImgs']) {
|
||||
files2.add(img["FILEPATH"]);
|
||||
}
|
||||
// files2=data['rImgs'] ?? [];
|
||||
files4 = data['sImgs'] ?? [];
|
||||
files5 = data['pImgs'] ?? [];
|
||||
files6 = data['yImgs'] ?? [];
|
||||
checkList = data['checkList'] ?? [];
|
||||
});
|
||||
}
|
||||
|
||||
} catch (e) {
|
||||
print('Error fetching data: $e');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Widget _buildInfoItem(String title, String value) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 8),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
SizedBox(
|
||||
width: 120,
|
||||
child: Text(
|
||||
title,
|
||||
style: const TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
),
|
||||
Expanded(child: Text(value,textAlign: TextAlign.right,)),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: MyAppbar(title: "隐患记录-详情"),
|
||||
body: pd.isEmpty
|
||||
? const Center(child: CircularProgressIndicator())
|
||||
: LayoutBuilder(
|
||||
builder: (context, constraints) {
|
||||
return SingleChildScrollView(
|
||||
child: ConstrainedBox(
|
||||
constraints: BoxConstraints(
|
||||
minHeight: constraints.maxHeight,
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
_buildInfoItem('隐患描述', pd['HIDDENDESCR'] ?? ''),
|
||||
|
||||
Divider(height: 1),
|
||||
// 隐患来源
|
||||
_buildInfoItem('隐患来源', _getSourceText(pd['SOURCE'])),
|
||||
Divider(height: 1),
|
||||
// 条件渲染部分
|
||||
if (pd['SOURCE'] == '2') ...[
|
||||
_buildInfoItem('风险点(单元)', pd['RISK_UNIT'] ?? ''),
|
||||
Divider(height: 1),
|
||||
_buildInfoItem('辨识部位', pd['IDENTIFICATION'] ?? ''),
|
||||
Divider(height: 1),
|
||||
_buildInfoItem('存在风险', pd['RISK_DESCR'] ?? ''),
|
||||
Divider(height: 1),
|
||||
_buildInfoItem('风险分级', pd['LEVEL'] ?? ''),
|
||||
Divider(height: 1),
|
||||
_buildInfoItem('检查内容', pd['CHECK_CONTENT'] ?? ''),
|
||||
Divider(height: 1),
|
||||
],
|
||||
|
||||
_buildInfoItem('隐患部位', pd['HIDDENPART'] ?? ''),
|
||||
Divider(height: 1),
|
||||
_buildInfoItem('发现人', pd['CREATORNAME'] ?? ''),
|
||||
Divider(height: 1),
|
||||
_buildInfoItem('发现时间', pd['CREATTIME'] ?? ''),
|
||||
Divider(height: 1),
|
||||
|
||||
if (pd['HIDDEN_CATEGORY']?.isNotEmpty == true)
|
||||
_buildInfoItem('隐患类别', pd['HIDDEN_CATEGORY_NAME'] ?? ''),
|
||||
|
||||
_buildInfoItem('隐患类型', pd['HIDDENTYPE_NAME'] ?? ''),
|
||||
Divider(height: 1),
|
||||
_buildInfoItem('整改类型', _getRectificationType(pd['RECTIFICATIONTYPE'])),
|
||||
|
||||
if (pd['RECTIFICATIONTYPE'] == '2')
|
||||
_buildInfoItem('整改期限', pd['RECTIFICATIONDEADLINE'] ?? ''),
|
||||
Divider(height: 1),
|
||||
// 隐患照片
|
||||
// const Text('隐患照片', style: TextStyle(fontWeight: FontWeight.bold)),
|
||||
// _buildImageGrid(files, onTap: (index) => _showImageGallery(files, index)),
|
||||
ListItemFactory.createTextImageItem(
|
||||
text: "隐患照片",
|
||||
imageUrls: files,
|
||||
onImageTapped: (index) {
|
||||
present(
|
||||
SingleImageViewer(imageUrl:ApiService.baseImgPath + files[index]),
|
||||
context,
|
||||
);
|
||||
},
|
||||
),
|
||||
|
||||
|
||||
// 隐患视频
|
||||
if (videoList.isNotEmpty) ...[
|
||||
const SizedBox(height: 16),
|
||||
const Text('隐患视频', style: TextStyle(fontWeight: FontWeight.bold)),
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
present(
|
||||
BigVideoViewer(videoUrl:ApiService.baseImgPath + videoList[0]['FILEPATH']),
|
||||
context,
|
||||
);
|
||||
},
|
||||
// => _playVideo(ApiService.baseImgPath + videoList[0]['FILEPATH']),
|
||||
child: Image.asset(
|
||||
'assets/image/videostart.png', // 替换为你的视频占位图
|
||||
color: Colors.blue,
|
||||
width: 120,
|
||||
height: 120,
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
SizedBox(height: 10,),
|
||||
// 整改信息部分
|
||||
if (pd['STATE'] != null && int.parse(pd['STATE']) >= 2 && int.parse(pd['STATE']) <= 4) ...[
|
||||
// const Divider(height: 10,color: Colors.grey,),
|
||||
const Text('整改信息', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
|
||||
Divider(height: 1),
|
||||
_buildInfoItem('整改描述', pd['RECTIFYDESCR'] ?? ''),
|
||||
Divider(height: 1),
|
||||
_buildInfoItem('整改部门', pd['RECTIFICATIONDEPTNAME'] ?? ''),
|
||||
Divider(height: 1),
|
||||
_buildInfoItem('整改人', pd['RECTIFICATIONORNAME'] ?? ''),
|
||||
Divider(height: 1),
|
||||
_buildInfoItem('整改时间', pd['RECTIFICATIONTIME'] ?? ''),
|
||||
Divider(height: 1),
|
||||
// const Text('整改后图片', style: TextStyle(fontWeight: FontWeight.bold)),
|
||||
// _buildImageGrid(files2, onTap: (index) => _showImageGallery(files2, index)),
|
||||
ListItemFactory.createTextImageItem(
|
||||
text: "整改后图片",
|
||||
imageUrls: files2,
|
||||
onImageTapped: (index) {
|
||||
present(
|
||||
SingleImageViewer(imageUrl: ApiService.baseImgPath +files2[index]),
|
||||
context,
|
||||
);
|
||||
},
|
||||
),
|
||||
|
||||
// ... 其他整改信息字段
|
||||
],
|
||||
|
||||
// 添加底部安全区域间距
|
||||
SizedBox(height: MediaQuery.of(context).padding.bottom + 20),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
String _getSourceText(String? source) {
|
||||
switch (source) {
|
||||
case '1': return '隐患快报';
|
||||
case '2': return '隐患排查清单检查';
|
||||
case '3': return '标准排查清单检查';
|
||||
case '4': return '专项检查';
|
||||
case '5': return '安全检查';
|
||||
default: return '';
|
||||
}
|
||||
}
|
||||
|
||||
String _getRectificationType(String? type) {
|
||||
switch (type) {
|
||||
case '1': return '立即整改';
|
||||
case '2': return '限期整改';
|
||||
default: return '';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,169 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
class LawsListBean {
|
||||
final String id;
|
||||
final String name;
|
||||
final String parentId;
|
||||
final List<LawsListBean> children;
|
||||
|
||||
LawsListBean({
|
||||
required this.id,
|
||||
required this.name,
|
||||
required this.parentId,
|
||||
this.children = const [],
|
||||
});
|
||||
|
||||
factory LawsListBean.fromJson(Map<String, dynamic> json) {
|
||||
return LawsListBean(
|
||||
id: json['id'] ?? '',
|
||||
name: json['title'] ?? '',
|
||||
parentId: json['pId'] ?? '',
|
||||
children: json['children'] != null
|
||||
? (json['children'] as List)
|
||||
.map((child) => LawsListBean.fromJson(child))
|
||||
.toList()
|
||||
: [],
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class LawsListPicker extends StatefulWidget {
|
||||
final List<LawsListBean> data;
|
||||
final String? initialSelectedId;
|
||||
final Set<String>? initialExpandedSet;
|
||||
final ValueChanged<LawsListBean?> onSelected;
|
||||
|
||||
const LawsListPicker({
|
||||
Key? key,
|
||||
required this.data,
|
||||
this.initialSelectedId,
|
||||
this.initialExpandedSet,
|
||||
required this.onSelected,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
_LawsListPickerState createState() => _LawsListPickerState();
|
||||
}
|
||||
|
||||
class _LawsListPickerState extends State<LawsListPicker> {
|
||||
late String? selectedId;
|
||||
late Set<String> expandedSet;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
selectedId = widget.initialSelectedId;
|
||||
expandedSet = Set<String>.from(widget.initialExpandedSet ?? {});
|
||||
}
|
||||
|
||||
Widget _buildRow(LawsListBean cat, int indent) {
|
||||
final bool hasChildren = cat.children.isNotEmpty;
|
||||
final bool isExpanded = expandedSet.contains(cat.id);
|
||||
final bool isSelected = cat.id == selectedId;
|
||||
|
||||
return Column(
|
||||
children: [
|
||||
InkWell(
|
||||
onTap: () {
|
||||
setState(() {
|
||||
if (hasChildren) {
|
||||
if (isExpanded) {
|
||||
expandedSet.remove(cat.id);
|
||||
} else {
|
||||
expandedSet.add(cat.id);
|
||||
}
|
||||
}
|
||||
selectedId = cat.id;
|
||||
widget.onSelected(cat);
|
||||
});
|
||||
},
|
||||
child: Container(
|
||||
color: Colors.white,
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
// 左侧缩进
|
||||
SizedBox(width: 16.0 * indent),
|
||||
// 展开/占位图标
|
||||
SizedBox(
|
||||
width: 24,
|
||||
child: hasChildren
|
||||
? Icon(
|
||||
isExpanded ? Icons.expand_less : Icons.expand_more,
|
||||
size: 20,
|
||||
color: Colors.grey[600],
|
||||
)
|
||||
: const SizedBox.shrink(),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
// 标题
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 12),
|
||||
child: Text(cat.name),
|
||||
),
|
||||
),
|
||||
// 单选圈保持右侧对齐
|
||||
// Padding(
|
||||
// padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
// child: Icon(
|
||||
// isSelected
|
||||
// ? Icons.radio_button_checked
|
||||
// : Icons.radio_button_unchecked,
|
||||
// color: Colors.green,
|
||||
// ),
|
||||
// ),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
if (hasChildren && isExpanded)
|
||||
...cat.children.map((c) => _buildRow(c, indent + 1)),
|
||||
// const Divider(height: 1),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
width: MediaQuery.of(context).size.width,
|
||||
height: MediaQuery.of(context).size.height * 0.7,
|
||||
color: Colors.transparent,
|
||||
child: Column(
|
||||
children: [
|
||||
// 顶部操作栏
|
||||
// Container(
|
||||
// color: Colors.white,
|
||||
// padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
|
||||
// child: Row(
|
||||
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
// children: [
|
||||
// GestureDetector(
|
||||
// onTap: () => Navigator.of(context).pop(),
|
||||
// child: const Text('取消', style: TextStyle(fontSize: 16)),
|
||||
// ),
|
||||
// GestureDetector(
|
||||
// onTap: () => Navigator.of(context).pop(selectedId),
|
||||
// child: const Text('确定', style: TextStyle(fontSize: 16, color: Colors.green),),
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// const Divider(height: 1),
|
||||
// 列表区
|
||||
Expanded(
|
||||
child: Container(
|
||||
color: Colors.white,
|
||||
child: ListView.builder(
|
||||
itemCount: widget.data.length,
|
||||
itemBuilder: (ctx, idx) => _buildRow(widget.data[idx], 0),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,358 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'dart:convert';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:qhd_prevention/pages/home/work/risk_list_picker.dart';
|
||||
import 'package:qhd_prevention/pages/my_appbar.dart';
|
||||
|
||||
import '../../../customWidget/search_bar_widget.dart';
|
||||
import '../../../http/ApiService.dart';
|
||||
import 'laws_list_picker.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
|
||||
class LawsRegulationsPage extends StatefulWidget {
|
||||
const LawsRegulationsPage({super.key});
|
||||
|
||||
@override
|
||||
State<LawsRegulationsPage> createState() => _LawsRegulationsPage();
|
||||
}
|
||||
|
||||
class _LawsRegulationsPage extends State<LawsRegulationsPage> {
|
||||
final TextEditingController _searchController = TextEditingController();
|
||||
List<LawsListBean> _accordionList = [];
|
||||
List<dynamic> _fileList = [];
|
||||
String _keywords = '';
|
||||
String treeJson = "";
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_getLowList("");
|
||||
}
|
||||
|
||||
Future<void> _getLowList(String keyWord) async {
|
||||
try {
|
||||
_accordionList.clear();
|
||||
_fileList.clear();
|
||||
final result = await ApiService.getLowList(keyWord);
|
||||
if (result['result'] == 'success') {
|
||||
final List<dynamic> newList = result['varList'] ?? [];
|
||||
setState(() {
|
||||
if(keyWord.isEmpty) {
|
||||
treeJson = result['zTreeNodes']??"";
|
||||
_accordionList = parseDepartments(treeJson);
|
||||
}else {
|
||||
_fileList.addAll(newList);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
_showMessage('加载数据失败');
|
||||
}
|
||||
} catch (e) {
|
||||
// 出错时可以 Toast 或者在页面上显示错误状态
|
||||
print('加载数据失败:$e');
|
||||
}
|
||||
}
|
||||
|
||||
List<LawsListBean> parseDepartments(String jsonString) {
|
||||
// 1. 解码 JSON 字符串
|
||||
final List<dynamic> jsonList = json.decode(jsonString);
|
||||
|
||||
// 2. 转换为部门对象列表
|
||||
return jsonList
|
||||
.map((jsonItem) => LawsListBean.fromJson(jsonItem))
|
||||
.toList();
|
||||
}
|
||||
|
||||
void _goToDetail(String id) {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(builder: (context) => StudyDetailPage(parentId: id)),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _downloadFile(String filePath) async {
|
||||
//下载
|
||||
try {
|
||||
final Uri url = Uri.parse(ApiService.baseImgPath + filePath);
|
||||
if (!await launchUrl(url,mode:LaunchMode.externalApplication)) {
|
||||
throw Exception('Could not launch $url');
|
||||
}
|
||||
} catch (e) {
|
||||
print(e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _showFile(dynamic file) async {
|
||||
//预览
|
||||
try {
|
||||
final url =ApiService.baseImgPath + file["FILEPATH"];
|
||||
openFile(url);
|
||||
} catch (e) {
|
||||
print(e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Future<void> openFile(String url) async {
|
||||
// final Uri _url = Uri.file(filePath);
|
||||
|
||||
if (await canLaunch(url)) {
|
||||
await launch(
|
||||
url,
|
||||
forceSafariVC: false, // 仅在iOS上有效,设置为false以避免使用SafariViewController。
|
||||
forceWebView: false, // 设置为false以避免使用WebView。
|
||||
enableJavaScript: true, // 启用JavaScript。
|
||||
);
|
||||
} else {
|
||||
throw 'Could not launch $url';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
String _formatDate(String dateString) {
|
||||
try {
|
||||
final date = DateTime.parse(dateString);
|
||||
return DateFormat('yyyy-MM-dd HH:mm:ss').format(date);
|
||||
} catch (e) {
|
||||
return dateString;
|
||||
}
|
||||
}
|
||||
|
||||
String _getFileType(String extension) {
|
||||
switch (extension) {
|
||||
case '.docx':
|
||||
case '.doc':
|
||||
return '文件属性:文档';
|
||||
case '.xls':
|
||||
case '.xlsx':
|
||||
return '文件属性:表格';
|
||||
case '.ppt':
|
||||
case '.pptx':
|
||||
return '文件属性:幻灯片';
|
||||
case '.pdf':
|
||||
return '文件属性:PDF';
|
||||
default:
|
||||
return '文件属性:';
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: MyAppbar(title: "法律法规"),
|
||||
body: Column(
|
||||
children: [
|
||||
// 搜索栏
|
||||
Padding(
|
||||
padding: EdgeInsets.all(10),
|
||||
child: SearchBarWidget(
|
||||
controller: _searchController,
|
||||
onSearch: (keyboard) {
|
||||
// 输入请求接口
|
||||
_getLowList(keyboard);
|
||||
},
|
||||
),
|
||||
),
|
||||
|
||||
Expanded(child: _buildContent()),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildContent() {
|
||||
if (_accordionList.isNotEmpty) {
|
||||
return LawsListPicker(
|
||||
data: _accordionList,
|
||||
onSelected: (item) {
|
||||
setState(() {
|
||||
// riskId = item?.id;
|
||||
// itemNameTwo=item!.name;
|
||||
// setResult();
|
||||
});
|
||||
|
||||
},
|
||||
);
|
||||
|
||||
// return ListView.builder(
|
||||
// itemCount: _accordionList.length,
|
||||
// itemBuilder:
|
||||
// (context, index) =>
|
||||
// CustomCollapse(item: _accordionList[index], onTap: _goToDetail),
|
||||
// );
|
||||
} else if (_fileList.isNotEmpty) {
|
||||
return ListView.builder(
|
||||
itemCount: _fileList.length,
|
||||
itemBuilder:
|
||||
(context, index) => FileCard(
|
||||
file: _fileList[index],
|
||||
onDownload: _downloadFile,
|
||||
onPreview: _showFile,
|
||||
formatDate: _formatDate,
|
||||
getFileType: _getFileType,
|
||||
),
|
||||
);
|
||||
} else {
|
||||
return const Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Icon(Icons.folder_open, size: 64, color: Colors.grey),
|
||||
SizedBox(height: 16),
|
||||
Text('暂无数据', style: TextStyle(fontSize: 18, color: Colors.grey)),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void _showMessage(String msg) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(msg)));
|
||||
}
|
||||
}
|
||||
|
||||
class CustomCollapse extends StatefulWidget {
|
||||
final dynamic item;
|
||||
final Function(String) onTap;
|
||||
|
||||
const CustomCollapse({super.key, required this.item, required this.onTap});
|
||||
|
||||
@override
|
||||
State<CustomCollapse> createState() => _CustomCollapseState();
|
||||
}
|
||||
|
||||
class _CustomCollapseState extends State<CustomCollapse> {
|
||||
bool _isExpanded = false;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final hasChildren =
|
||||
widget.item['children'] != null &&
|
||||
(widget.item['children'] as List).isNotEmpty;
|
||||
|
||||
return Card(
|
||||
margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
||||
child: Column(
|
||||
children: [
|
||||
ListTile(
|
||||
title: Text(
|
||||
widget.item['name'] ?? '未命名',
|
||||
style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 16),
|
||||
),
|
||||
trailing:
|
||||
hasChildren
|
||||
? Icon(
|
||||
_isExpanded ? Icons.expand_less : Icons.expand_more,
|
||||
color: Colors.blue,
|
||||
)
|
||||
: null,
|
||||
onTap:
|
||||
hasChildren
|
||||
? () => setState(() => _isExpanded = !_isExpanded)
|
||||
: () => widget.onTap(widget.item['id'] ?? ''),
|
||||
),
|
||||
if (_isExpanded && hasChildren)
|
||||
...(widget.item['children'] as List).map<Widget>((child) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(left: 16.0),
|
||||
child: ListTile(
|
||||
title: Text(child['name']),
|
||||
leading: const Icon(Icons.description, color: Colors.blue),
|
||||
onTap: () => widget.onTap(child['id'] ?? ''),
|
||||
),
|
||||
);
|
||||
}).toList(),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class FileCard extends StatelessWidget {
|
||||
final dynamic file;
|
||||
final Function(String) onDownload;
|
||||
final Function(dynamic) onPreview;
|
||||
final String Function(String) formatDate;
|
||||
final String Function(String) getFileType;
|
||||
|
||||
const FileCard({
|
||||
super.key,
|
||||
required this.file,
|
||||
required this.onDownload,
|
||||
required this.onPreview,
|
||||
required this.formatDate,
|
||||
required this.getFileType,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Card(
|
||||
margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(12.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
file['NAME'] ?? '未命名文件',
|
||||
style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
getFileType(file['extension_name'] ?? ''),
|
||||
style: TextStyle(color: Colors.grey[600]),
|
||||
),
|
||||
const SizedBox(height: 5),
|
||||
Text(
|
||||
'上传日期:${formatDate(file['CTIME'] ?? '')}',
|
||||
style: TextStyle(color: Colors.grey[600]),
|
||||
),
|
||||
const SizedBox(height: 15),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
OutlinedButton.icon(
|
||||
icon: const Icon(Icons.download, size: 18),
|
||||
label: const Text('下载'),
|
||||
onPressed: () => onDownload(file['FILEPATH'] ?? ''),
|
||||
style: OutlinedButton.styleFrom(
|
||||
foregroundColor: Colors.blue,
|
||||
side: const BorderSide(color: Colors.blue),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
ElevatedButton.icon(
|
||||
icon: const Icon(Icons.visibility, size: 18),
|
||||
label: const Text('预览'),
|
||||
onPressed: () => onPreview(file),
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: Colors.cyan,
|
||||
foregroundColor: Colors.white,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
//详情页
|
||||
class StudyDetailPage extends StatelessWidget {
|
||||
final String parentId;
|
||||
|
||||
const StudyDetailPage({super.key, required this.parentId});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: const Text('详情页面')),
|
||||
body: Center(child: Text('父级ID: $parentId')),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,169 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
class RiskListBean {
|
||||
final String id;
|
||||
final String name;
|
||||
// final String parentId;
|
||||
// final List<RiskListBean> children;
|
||||
|
||||
RiskListBean({
|
||||
required this.id,
|
||||
required this.name,
|
||||
// required this.parentId,
|
||||
// this.children = const [],
|
||||
});
|
||||
|
||||
factory RiskListBean.fromJson(Map<String, dynamic> json) {
|
||||
return RiskListBean(
|
||||
id: json['RISKUNIT_ID'] ?? '',
|
||||
name: json['RISKUNITNAME'] ?? '',
|
||||
// parentId: json['PARENT_ID'] ?? '',
|
||||
// children: json['children'] != null
|
||||
// ? (json['children'] as List)
|
||||
// .map((child) => RiskListBean.fromJson(child))
|
||||
// .toList()
|
||||
// : [],
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class RiskListPicker extends StatefulWidget {
|
||||
final List<RiskListBean> data;
|
||||
final String? initialSelectedId;
|
||||
final Set<String>? initialExpandedSet;
|
||||
final ValueChanged<RiskListBean?> onSelected;
|
||||
|
||||
const RiskListPicker({
|
||||
Key? key,
|
||||
required this.data,
|
||||
this.initialSelectedId,
|
||||
this.initialExpandedSet,
|
||||
required this.onSelected,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
_RiskListPickerState createState() => _RiskListPickerState();
|
||||
}
|
||||
|
||||
class _RiskListPickerState extends State<RiskListPicker> {
|
||||
late String? selectedId;
|
||||
late Set<String> expandedSet;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
selectedId = widget.initialSelectedId;
|
||||
expandedSet = Set<String>.from(widget.initialExpandedSet ?? {});
|
||||
}
|
||||
|
||||
Widget _buildRow(RiskListBean cat, int indent) {
|
||||
// final bool hasChildren = cat.children.isNotEmpty;
|
||||
final bool isExpanded = expandedSet.contains(cat.id);
|
||||
final bool isSelected = cat.id == selectedId;
|
||||
|
||||
return Column(
|
||||
children: [
|
||||
InkWell(
|
||||
onTap: () {
|
||||
setState(() {
|
||||
// if (hasChildren) {
|
||||
// if (isExpanded) {
|
||||
// expandedSet.remove(cat.id);
|
||||
// } else {
|
||||
// expandedSet.add(cat.id);
|
||||
// }
|
||||
// }
|
||||
selectedId = cat.id;
|
||||
widget.onSelected(cat);
|
||||
});
|
||||
},
|
||||
child: Container(
|
||||
color: Colors.white,
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
// 左侧缩进
|
||||
SizedBox(width: 16.0 * indent),
|
||||
// 展开/占位图标
|
||||
// SizedBox(
|
||||
// width: 24,
|
||||
// child: hasChildren
|
||||
// ? Icon(
|
||||
// isExpanded ? Icons.expand_less : Icons.expand_more,
|
||||
// size: 20,
|
||||
// color: Colors.grey[600],
|
||||
// )
|
||||
// : const SizedBox.shrink(),
|
||||
// ),
|
||||
const SizedBox(width: 8),
|
||||
// 标题
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 12),
|
||||
child: Text(cat.name),
|
||||
),
|
||||
),
|
||||
// 单选圈保持右侧对齐
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: Icon(
|
||||
isSelected
|
||||
? Icons.radio_button_checked
|
||||
: Icons.radio_button_unchecked,
|
||||
color: Colors.green,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
// if (hasChildren && isExpanded)
|
||||
// ...cat.children.map((c) => _buildRow(c, indent + 1)),
|
||||
// const Divider(height: 1),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
width: MediaQuery.of(context).size.width,
|
||||
height: MediaQuery.of(context).size.height * 0.7,
|
||||
color: Colors.transparent,
|
||||
child: Column(
|
||||
children: [
|
||||
// 顶部操作栏
|
||||
Container(
|
||||
color: Colors.white,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
GestureDetector(
|
||||
onTap: () => Navigator.of(context).pop(),
|
||||
child: const Text('取消', style: TextStyle(fontSize: 16)),
|
||||
),
|
||||
GestureDetector(
|
||||
onTap: () => Navigator.of(context).pop(selectedId),
|
||||
child: const Text('确定', style: TextStyle(fontSize: 16, color: Colors.green),),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const Divider(height: 1),
|
||||
// 列表区
|
||||
Expanded(
|
||||
child: Container(
|
||||
color: Colors.white,
|
||||
child: ListView.builder(
|
||||
itemCount: widget.data.length,
|
||||
itemBuilder: (ctx, idx) => _buildRow(widget.data[idx], 0),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,169 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
class WaitListBean {
|
||||
final String id;
|
||||
final String name;
|
||||
final String parentId;
|
||||
final List<WaitListBean> children;
|
||||
|
||||
WaitListBean({
|
||||
required this.id,
|
||||
required this.name,
|
||||
required this.parentId,
|
||||
this.children = const [],
|
||||
});
|
||||
|
||||
factory WaitListBean.fromJson(Map<String, dynamic> json) {
|
||||
return WaitListBean(
|
||||
id: json['id'] ?? '',
|
||||
name: json['name'] ?? '',
|
||||
parentId: json['PARENT_ID'] ?? '',
|
||||
children: json['children'] != null
|
||||
? (json['children'] as List)
|
||||
.map((child) => WaitListBean.fromJson(child))
|
||||
.toList()
|
||||
: [],
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class WaitListPicker extends StatefulWidget {
|
||||
final List<WaitListBean> data;
|
||||
final String? initialSelectedId;
|
||||
final Set<String>? initialExpandedSet;
|
||||
final ValueChanged<WaitListBean?> onSelected;
|
||||
|
||||
const WaitListPicker({
|
||||
Key? key,
|
||||
required this.data,
|
||||
this.initialSelectedId,
|
||||
this.initialExpandedSet,
|
||||
required this.onSelected,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
_WaitListPickerState createState() => _WaitListPickerState();
|
||||
}
|
||||
|
||||
class _WaitListPickerState extends State<WaitListPicker> {
|
||||
late String? selectedId;
|
||||
late Set<String> expandedSet;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
selectedId = widget.initialSelectedId;
|
||||
expandedSet = Set<String>.from(widget.initialExpandedSet ?? {});
|
||||
}
|
||||
|
||||
Widget _buildRow(WaitListBean cat, int indent) {
|
||||
final bool hasChildren = cat.children.isNotEmpty;
|
||||
final bool isExpanded = expandedSet.contains(cat.id);
|
||||
final bool isSelected = cat.id == selectedId;
|
||||
|
||||
return Column(
|
||||
children: [
|
||||
InkWell(
|
||||
onTap: () {
|
||||
setState(() {
|
||||
if (hasChildren) {
|
||||
if (isExpanded) {
|
||||
expandedSet.remove(cat.id);
|
||||
} else {
|
||||
expandedSet.add(cat.id);
|
||||
}
|
||||
}
|
||||
selectedId = cat.id;
|
||||
widget.onSelected(cat);
|
||||
});
|
||||
},
|
||||
child: Container(
|
||||
color: Colors.white,
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
// 左侧缩进
|
||||
SizedBox(width: 16.0 * indent),
|
||||
// 展开/占位图标
|
||||
SizedBox(
|
||||
width: 24,
|
||||
child: hasChildren
|
||||
? Icon(
|
||||
isExpanded ? Icons.expand_less : Icons.expand_more,
|
||||
size: 20,
|
||||
color: Colors.grey[600],
|
||||
)
|
||||
: const SizedBox.shrink(),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
// 标题
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 12),
|
||||
child: Text(cat.name),
|
||||
),
|
||||
),
|
||||
// 单选圈保持右侧对齐
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: Icon(
|
||||
isSelected
|
||||
? Icons.radio_button_checked
|
||||
: Icons.radio_button_unchecked,
|
||||
color: Colors.green,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
if (hasChildren && isExpanded)
|
||||
...cat.children.map((c) => _buildRow(c, indent + 1)),
|
||||
// const Divider(height: 1),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
width: MediaQuery.of(context).size.width,
|
||||
height: MediaQuery.of(context).size.height * 0.7,
|
||||
color: Colors.transparent,
|
||||
child: Column(
|
||||
children: [
|
||||
// 顶部操作栏
|
||||
Container(
|
||||
color: Colors.white,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
GestureDetector(
|
||||
onTap: () => Navigator.of(context).pop(),
|
||||
child: const Text('取消', style: TextStyle(fontSize: 16)),
|
||||
),
|
||||
GestureDetector(
|
||||
onTap: () => Navigator.of(context).pop(selectedId),
|
||||
child: const Text('确定', style: TextStyle(fontSize: 16, color: Colors.green),),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const Divider(height: 1),
|
||||
// 列表区
|
||||
Expanded(
|
||||
child: Container(
|
||||
color: Colors.white,
|
||||
child: ListView.builder(
|
||||
itemCount: widget.data.length,
|
||||
itemBuilder: (ctx, idx) => _buildRow(widget.data[idx], 0),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,3 +1,5 @@
|
|||
import 'dart:math';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:qhd_prevention/pages/home/work_alert.dart';
|
||||
import 'package:qhd_prevention/pages/my_appbar.dart';
|
||||
|
@ -5,6 +7,7 @@ import 'package:qhd_prevention/tools/tools.dart';
|
|||
import 'package:table_calendar/table_calendar.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
|
||||
import '../../http/ApiService.dart';
|
||||
import '../../tools/h_colors.dart';
|
||||
|
||||
class WorkSetPage extends StatefulWidget {
|
||||
|
@ -18,11 +21,108 @@ class _WorkSetPageState extends State<WorkSetPage> {
|
|||
DateTime _focusedDay = DateTime.now();
|
||||
DateTime _selectedDay = DateTime.now();
|
||||
|
||||
Map<String, dynamic> dayWork = {};
|
||||
late List<dynamic> _list = [];
|
||||
String title="";
|
||||
String content="";
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
// TODO: implement initState
|
||||
super.initState();
|
||||
|
||||
_getAnPai();
|
||||
String data= DateFormat('yyyy-MM-dd').format(DateTime.now());
|
||||
_getRiCheng(data,false);
|
||||
}
|
||||
|
||||
Future<void> _getAnPai() async {
|
||||
try {
|
||||
|
||||
final result = await ApiService.getAnPai();
|
||||
if (result['result'] == 'success') {
|
||||
setState(() {
|
||||
dayWork= result;
|
||||
});
|
||||
|
||||
}else{
|
||||
_showMessage('加载数据失败');
|
||||
}
|
||||
} catch (e) {
|
||||
// 出错时可以 Toast 或者在页面上显示错误状态
|
||||
print('加载数据失败:$e');
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _getRiCheng(String data, bool bool) async {
|
||||
try {
|
||||
_list.clear();
|
||||
|
||||
final result = await ApiService.getRiCheng(data);
|
||||
|
||||
if (result['result'] == 'success') {
|
||||
setState(() {
|
||||
final List<dynamic> newList = result['varList'] ?? [];
|
||||
_list.addAll(newList);
|
||||
|
||||
});
|
||||
if(bool) {
|
||||
if ( _list.isNotEmpty) {
|
||||
title = _list[0]["title"];
|
||||
content = _list[0]["desc"];
|
||||
selectDate();
|
||||
} else {
|
||||
title = "";
|
||||
content = "";
|
||||
selectDate();
|
||||
}
|
||||
}
|
||||
}else{
|
||||
_showMessage('加载数据失败');
|
||||
}
|
||||
|
||||
} catch (e) {
|
||||
// 出错时可以 Toast 或者在页面上显示错误状态
|
||||
print('加载数据失败:$e');
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _addRiCheng(String title, String content) async {
|
||||
try {
|
||||
|
||||
String urlPath;
|
||||
String id;
|
||||
if(_list.isNotEmpty){
|
||||
urlPath="edit";
|
||||
id=_list[0]["id"];
|
||||
}else{
|
||||
urlPath="add";
|
||||
id=Random().nextDouble().toString();
|
||||
}
|
||||
String data= DateFormat('yyyy-MM-dd').format(_selectedDay);
|
||||
final result = await ApiService.addRiCheng(data,title,content,id,urlPath);
|
||||
if (result['result'] == 'success') {
|
||||
setState(() {
|
||||
_showMessage('保存成功');
|
||||
String data= DateFormat('yyyy-MM-dd').format(_selectedDay);
|
||||
_getRiCheng(data,false);
|
||||
});
|
||||
|
||||
}else{
|
||||
_showMessage('加载数据失败');
|
||||
}
|
||||
} catch (e) {
|
||||
// 出错时可以 Toast 或者在页面上显示错误状态
|
||||
print('加载数据失败:$e');
|
||||
}
|
||||
}
|
||||
|
||||
void _goToToday() {
|
||||
setState(() {
|
||||
_focusedDay = DateTime.now();
|
||||
_selectedDay = DateTime.now();
|
||||
selectDate();
|
||||
// selectDate();
|
||||
getInfoDate();
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -38,23 +138,35 @@ class _WorkSetPageState extends State<WorkSetPage> {
|
|||
});
|
||||
}
|
||||
|
||||
void getInfoDate() {
|
||||
String data= DateFormat('yyyy-MM-dd').format(_selectedDay);
|
||||
_getRiCheng(data,true);
|
||||
}
|
||||
void selectDate() {
|
||||
|
||||
print("======$_selectedDay");
|
||||
|
||||
showWorkAlert(
|
||||
context: context,
|
||||
alertTitle: "标题:",
|
||||
inputHint: "请输入",
|
||||
contentHint: "请输入",
|
||||
initialTitle: title,
|
||||
initialContent: content,
|
||||
onConfirm: (title, content) {
|
||||
// 处理确定后的逻辑
|
||||
print("标题: $title");
|
||||
print("内容: $content");
|
||||
// print("标题: $title");
|
||||
// print("内容: $content");
|
||||
|
||||
_addRiCheng(title,content);
|
||||
},
|
||||
onCancel: () {
|
||||
// 处理取消逻辑
|
||||
print("用户取消了操作");
|
||||
},
|
||||
);
|
||||
|
||||
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -81,7 +193,8 @@ class _WorkSetPageState extends State<WorkSetPage> {
|
|||
setState(() {
|
||||
_selectedDay = selectedDay;
|
||||
_focusedDay = focusedDay;
|
||||
selectDate();
|
||||
// selectDate();
|
||||
getInfoDate();
|
||||
});
|
||||
},
|
||||
daysOfWeekStyle: DaysOfWeekStyle(
|
||||
|
@ -136,8 +249,10 @@ class _WorkSetPageState extends State<WorkSetPage> {
|
|||
),
|
||||
),
|
||||
),
|
||||
Container(color: h_backGroundColor(), height: 20),
|
||||
Container(color: h_backGroundColor(), height: 10),
|
||||
_workTipWidget(),
|
||||
Container(color: h_backGroundColor(), height: 10),
|
||||
_workRiCheng(),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
@ -161,16 +276,54 @@ class _WorkSetPageState extends State<WorkSetPage> {
|
|||
Column(
|
||||
spacing: 5,
|
||||
children: [
|
||||
_itemCell("需进行2项隐患排查", true),
|
||||
_itemCell("需进行2项隐患排查", false),
|
||||
_itemCell("需进行${dayWork["fxyjcNum"]??"0"}项隐患排查", true),
|
||||
_itemCell("需进行${dayWork["fxwjcNum"]??"0"}项隐患排查", false),
|
||||
_itemCell("需进行${dayWork["yhyjcNum"]??"0"}项标准排查", true),
|
||||
_itemCell("需进行${dayWork["yhwjcNum"]??"0"}项标准排查", false),
|
||||
],
|
||||
|
||||
),
|
||||
|
||||
|
||||
],
|
||||
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/// 本日工作题型
|
||||
Widget _workRiCheng() {
|
||||
return Container(
|
||||
color: Colors.white,
|
||||
padding: EdgeInsets.all(12),
|
||||
child: Column(
|
||||
spacing: 20,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text("本日日程安排", style: TextStyle(fontSize: 16)),
|
||||
Spacer(),
|
||||
],
|
||||
),
|
||||
|
||||
if(_list.isNotEmpty)
|
||||
_itemRiCheng(_list[0]["desc"])
|
||||
// if(_list.isEmpty)
|
||||
// ListView.separated(
|
||||
// separatorBuilder: (_, __) => const Divider(height: 1),
|
||||
// itemCount: _list.length,
|
||||
// itemBuilder: (context, index) {
|
||||
// final item = _list[index];
|
||||
// return _itemRiCheng(item);
|
||||
// },
|
||||
// ),
|
||||
],
|
||||
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _itemCell(final String title, bool isFinish) {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
|
@ -186,6 +339,23 @@ class _WorkSetPageState extends State<WorkSetPage> {
|
|||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget _itemRiCheng(final String title) {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Row(
|
||||
spacing: 5,
|
||||
children: [
|
||||
Icon(Icons.circle, size: 10, color: Colors.blue),
|
||||
Text(title, style: TextStyle(color: Colors.black45),),
|
||||
],
|
||||
),
|
||||
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
///日历头
|
||||
Widget _calendarHeader() {
|
||||
return Container(
|
||||
|
@ -289,4 +459,8 @@ class _WorkSetPageState extends State<WorkSetPage> {
|
|||
],
|
||||
);
|
||||
}
|
||||
|
||||
void _showMessage(String msg) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(msg)));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -155,6 +155,8 @@ class SessionService {
|
|||
String? isRest;
|
||||
List<dynamic>? permission;
|
||||
bool updateInfo = false;
|
||||
String? dangerJson;
|
||||
String? riskJson;
|
||||
|
||||
/// 如果以下任何一项为空,则跳转到登录页
|
||||
void loginSession(BuildContext context) {
|
||||
|
@ -188,6 +190,10 @@ class SessionService {
|
|||
|
||||
void setUpdateInfo(bool flag) => updateInfo = flag;
|
||||
|
||||
void setDangerWaitInfo(String json) => dangerJson = json;
|
||||
|
||||
void setRiskWaitInfo(String json) => riskJson = json;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
388
pubspec.lock
388
pubspec.lock
File diff suppressed because it is too large
Load Diff
|
@ -69,6 +69,11 @@ dependencies:
|
|||
# nfc相关
|
||||
nfc_manager: ^4.0.2
|
||||
nfc_manager_ndef: ^1.0.1
|
||||
#定位
|
||||
geolocator: ^10.0.0
|
||||
#打开外部预览app
|
||||
url_launcher: ^6.0.9
|
||||
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
|
Loading…
Reference in New Issue