Merge remote-tracking branch 'origin/main'

# Conflicts:
#	lib/pages/home/home_page.dart
#	pubspec.lock
#	pubspec.yaml
main
hs 2025-07-24 09:43:29 +08:00
commit ccb9eb4f55
24 changed files with 2954 additions and 339 deletions

View File

@ -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及以下 -->

BIN
assets/image/videostart.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -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>

View File

@ -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(

View File

@ -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,
),
),
);
}
}

View File

@ -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&currentPage=$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",
},
);
}
}

View File

@ -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');
}
}
}

View File

@ -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)));
}
}

View File

@ -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)));
}
}

View File

@ -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)));
}
}

View File

@ -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)));
}
}

View File

@ -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,};
}
}

View File

@ -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 "限期整改";
}
}
}

View File

@ -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 ?? "",

View File

@ -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'];
});

View File

@ -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 '';
}
}
}

View File

@ -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),
),
),
),
],
),
);
}
}

View File

@ -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, // iOSfalse使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')),
);
}
}

View File

@ -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),
),
),
),
],
),
);
}
}

View File

@ -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),
),
),
),
],
),
);
}
}

View File

@ -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)));
}
}

View File

@ -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;
}

File diff suppressed because it is too large Load Diff

View File

@ -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: