。。。

master
hs 2026-03-12 10:23:21 +08:00
parent 96c52d91bb
commit 7415673fec
13 changed files with 1826 additions and 1059 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

581
assets/route/routes.txt Normal file
View File

@ -0,0 +1,581 @@
{
"extValues": {},
"success": true,
"errCode": null,
"errMessage": null,
"exception": null,
"traceId": "18491030037470208",
"data": [
{
"extValues": {},
"id": "2030925300149387265",
"menuName": "首页",
"menuUrl": "/dashboard",
"parentId": "0",
"parentIds": null,
"menuPerms": "dashboard",
"menuType": 1,
"menuAttribution": "QINGANG_RELATED_PARTIES",
"sort": 0,
"showFlag": 1,
"children": [
{
"extValues": {},
"id": "2030925300149387268",
"menuName": "单位管理",
"menuUrl": "/dashboard/Unit/Management",
"parentId": "2030925300149387265",
"parentIds": null,
"menuPerms": "dashboard-Unit-Management",
"menuType": 2,
"menuAttribution": "QINGANG_RELATED_PARTIES",
"sort": 3,
"showFlag": 1,
"children": [
{
"extValues": {},
"id": "2030925300149387286",
"menuName": "就职单位",
"menuUrl": "/dashboard/Unit/Management/Employment/Unit",
"parentId": "2030925300149387268",
"parentIds": null,
"menuPerms": "dashboard-Unit-Management-Employment-Unit",
"menuType": 2,
"menuAttribution": "QINGANG_RELATED_PARTIES",
"sort": 21,
"showFlag": 1,
"children": null
},
{
"extValues": {},
"id": "2030925300149387287",
"menuName": "服务单位管理",
"menuUrl": "/dashboard/Unit/Management/Managee/Service/Unit/Management",
"parentId": "2030925300149387268",
"parentIds": null,
"menuPerms": "dashboard-Unit-Management-Managee-Service-Unit-Management",
"menuType": 2,
"menuAttribution": "QINGANG_RELATED_PARTIES",
"sort": 22,
"showFlag": 1,
"children": null
}
]
},
{
"extValues": {},
"id": "2030925300149387269",
"menuName": "通知公告",
"menuUrl": "/dashboard/Notice/Announcement",
"parentId": "2030925300149387265",
"parentIds": null,
"menuPerms": "dashboard-Notice-Announcement",
"menuType": 2,
"menuAttribution": "QINGANG_RELATED_PARTIES",
"sort": 4,
"showFlag": 1,
"children": null
},
{
"extValues": {},
"id": "2030925300149387270",
"menuName": "口门门禁",
"menuUrl": "/dashboard/Gate/Access/Control",
"parentId": "2030925300149387265",
"parentIds": null,
"menuPerms": "dashboard-Gate-Access-Control",
"menuType": 2,
"menuAttribution": "QINGANG_RELATED_PARTIES",
"sort": 5,
"showFlag": 1,
"children": [
{
"extValues": {},
"id": "2030925300149387288",
"menuName": "进港口门申请",
"menuUrl": "/dashboard/Gate/Access/Control/Port/Gate/Entry/Application",
"parentId": "2030925300149387270",
"parentIds": null,
"menuPerms": "dashboard-Gate-Access-Control-Port-Gate-Entry-Application",
"menuType": 2,
"menuAttribution": "QINGANG_RELATED_PARTIES",
"sort": 23,
"showFlag": 1,
"children": [
{
"extValues": {},
"id": "2030925300149387292",
"menuName": "人员申请",
"menuUrl": "/dashboard/Port/Gate/Entry/Application/Personnel/Application",
"parentId": "2030925300149387288",
"parentIds": null,
"menuPerms": "dashboard-Port-Gate-Entry-Application-Personnel-Application",
"menuType": 2,
"menuAttribution": "QINGANG_RELATED_PARTIES",
"sort": 27,
"showFlag": 1,
"children": null
},
{
"extValues": {},
"id": "2030925300149387293",
"menuName": "车辆申请",
"menuUrl": "/dashboard/Port/Gate/Entry/Application/Vehicle/Application",
"parentId": "2030925300149387288",
"parentIds": null,
"menuPerms": "dashboard-Port-Gate-Entry-Application-Vehicle-Application",
"menuType": 2,
"menuAttribution": "QINGANG_RELATED_PARTIES",
"sort": 28,
"showFlag": 1,
"children": null
}
]
},
{
"extValues": {},
"id": "2030925300149387289",
"menuName": "进港口门申请记录",
"menuUrl": "/dashboard/Gate/Access/Crdtrol/Port/Gate/Entry/Record",
"parentId": "2030925300149387270",
"parentIds": null,
"menuPerms": "dashboard-Gate-Access-Crdtrol-Port-Gate-Entry-Record",
"menuType": 2,
"menuAttribution": "QINGANG_RELATED_PARTIES",
"sort": 24,
"showFlag": 1,
"children": [
{
"extValues": {},
"id": "2030925300149387294",
"menuName": "人员申请记录",
"menuUrl": "/dashboard/Port/Gate/Entry/Record/Record/Personnel/Application/Record",
"parentId": "2030925300149387289",
"parentIds": null,
"menuPerms": "dashboard-Port-Gate-Entry-Record-Record-Personnel-Application-Record",
"menuType": 2,
"menuAttribution": "QINGANG_RELATED_PARTIES",
"sort": 29,
"showFlag": 1,
"children": null
},
{
"extValues": {},
"id": "2030925300149387295",
"menuName": "车辆申请记录",
"menuUrl": "/dashboard/Port/Gate/Entry/Record/Record/Vehicle/Application/Record",
"parentId": "2030925300149387289",
"parentIds": null,
"menuPerms": "dashboard-Port-Gate-Entry-Record-Record-Vehicle-Application-Record",
"menuType": 2,
"menuAttribution": "QINGANG_RELATED_PARTIES",
"sort": 30,
"showFlag": 1,
"children": null
}
]
},
{
"extValues": {},
"id": "2030925300149387290",
"menuName": "封闭区域口门申请",
"menuUrl": "/dashboard/Area/Access/Cionsedrol/Closed/Area/Gate/Application",
"parentId": "2030925300149387270",
"parentIds": null,
"menuPerms": "dashboard-Area-Access-Cionsedrol-Closed-Area-Gate-Application",
"menuType": 2,
"menuAttribution": "QINGANG_RELATED_PARTIES",
"sort": 25,
"showFlag": 1,
"children": [
{
"extValues": {},
"id": "2030925300149387296",
"menuName": "人员申请",
"menuUrl": "/dashboard/Closed/Area/Gate/Application/Personnel/Application",
"parentId": "2030925300149387290",
"parentIds": null,
"menuPerms": "dashboard-Closed-Area-Gate-Application-Personnel-Application",
"menuType": 2,
"menuAttribution": "QINGANG_RELATED_PARTIES",
"sort": 31,
"showFlag": 1,
"children": null
},
{
"extValues": {},
"id": "2030925300149387297",
"menuName": "车辆申请",
"menuUrl": "/dashboard/Closed/Area/Gate/Application/Vehicle/Application",
"parentId": "2030925300149387290",
"parentIds": null,
"menuPerms": "dashboard-Closed-Area-Gate-Application-Vehicle-Application",
"menuType": 2,
"menuAttribution": "QINGANG_RELATED_PARTIES",
"sort": 32,
"showFlag": 1,
"children": null
}
]
},
{
"extValues": {},
"id": "2030925300149387291",
"menuName": "封闭区域口门申请记录",
"menuUrl": "/dashboard/Area/Access/Crdsedrol/Closed/Area/Gate/Record",
"parentId": "2030925300149387270",
"parentIds": null,
"menuPerms": "dashboard-Area-Access-Crdsedrol-Closed-Area-Gate-Record",
"menuType": 2,
"menuAttribution": "QINGANG_RELATED_PARTIES",
"sort": 26,
"showFlag": 1,
"children": [
{
"extValues": {},
"id": "2030925300149387298",
"menuName": "人员申请记录",
"menuUrl": "/dashboard/Closed/Area/Gate/Record/Record/Personnel/Application/Record",
"parentId": "2030925300149387291",
"parentIds": null,
"menuPerms": "dashboard-Closed-Area-Gate-Record-Record-Personnel-Application-Record",
"menuType": 2,
"menuAttribution": "QINGANG_RELATED_PARTIES",
"sort": 33,
"showFlag": 1,
"children": null
},
{
"extValues": {},
"id": "2030925300149387299",
"menuName": "车辆申请记录",
"menuUrl": "/dashboard/Closed/Area/Gate/Record/Record/Vehicle/Application/Record",
"parentId": "2030925300149387291",
"parentIds": null,
"menuPerms": "dashboard-Closed-Area-Gate-Record-Record-Vehicle-Application-Record",
"menuType": 2,
"menuAttribution": "QINGANG_RELATED_PARTIES",
"sort": 34,
"showFlag": 1,
"children": null
}
]
}
]
},
{
"extValues": {},
"id": "2030925300149387271",
"menuName": "现场监管",
"menuUrl": "/dashboard/Site/Supervision",
"parentId": "2030925300149387265",
"parentIds": null,
"menuPerms": "dashboard-Site-Supervision",
"menuType": 2,
"menuAttribution": "QINGANG_RELATED_PARTIES",
"sort": 6,
"showFlag": 1,
"children": null
},
{
"extValues": {},
"id": "2030925300149387272",
"menuName": "危险作业",
"menuUrl": "/dashboard/Hazardous/Work",
"parentId": "2030925300149387265",
"parentIds": null,
"menuPerms": "dashboard-Hazardous-Work",
"menuType": 2,
"menuAttribution": "QINGANG_RELATED_PARTIES",
"sort": 7,
"showFlag": 1,
"children": null
},
{
"extValues": {},
"id": "2030925300149387273",
"menuName": "隐患治理",
"menuUrl": "/dashboard/Hazard/Management",
"parentId": "2030925300149387265",
"parentIds": null,
"menuPerms": "dashboard-Hazard-Management",
"menuType": 2,
"menuAttribution": "QINGANG_RELATED_PARTIES",
"sort": 8,
"showFlag": 1,
"children": null
},
{
"extValues": {},
"id": "2030935458707537921",
"menuName": "入港培训",
"menuUrl": "/dashboard/Study/Training",
"parentId": "2030925300149387265",
"parentIds": null,
"menuPerms": "dashboard-Study-Training",
"menuType": 1,
"menuAttribution": "QINGANG_RELATED_PARTIES",
"sort": 11,
"showFlag": 1,
"children": null
},
{
"extValues": {},
"id": "2030925300149387300",
"menuName": "首页扫码",
"menuUrl": "/dashboard/scan",
"parentId": "2030925300149387265",
"parentIds": null,
"menuPerms": "dashboard-scan",
"menuType": 2,
"menuAttribution": "QINGANG_RELATED_PARTIES",
"sort": 35,
"showFlag": 1,
"children": null
},
{
"extValues": {},
"id": "2030925300149387301",
"menuName": "首页滚动通知",
"menuUrl": "/dashboard/roll-notice",
"parentId": "2030925300149387265",
"parentIds": null,
"menuPerms": "dashboard-roll-notice",
"menuType": 2,
"menuAttribution": "QINGANG_RELATED_PARTIES",
"sort": 36,
"showFlag": 1,
"children": null
},
{
"extValues": {},
"id": "2030925300149387302",
"menuName": "首页待办梳理",
"menuUrl": "/dashboard/todo-sort",
"parentId": "2030925300149387265",
"parentIds": null,
"menuPerms": "dashboard-todo-sort",
"menuType": 2,
"menuAttribution": "QINGANG_RELATED_PARTIES",
"sort": 37,
"showFlag": 1,
"children": null
},
{
"extValues": {},
"id": "2030925300149387303",
"menuName": "首页待办事项",
"menuUrl": "/dashboard/todo-list",
"parentId": "2030925300149387265",
"parentIds": null,
"menuPerms": "dashboard-todo-list",
"menuType": 2,
"menuAttribution": "QINGANG_RELATED_PARTIES",
"sort": 38,
"showFlag": 1,
"children": null
}
]
},
{
"extValues": {},
"id": "2030925300149387266",
"menuName": "通知",
"menuUrl": "/notice",
"parentId": "0",
"parentIds": null,
"menuPerms": "notice",
"menuType": 2,
"menuAttribution": "QINGANG_RELATED_PARTIES",
"sort": 1,
"showFlag": 1,
"children": [
{
"extValues": {},
"id": "2030925300149387274",
"menuName": "公告通知",
"menuUrl": "/notice/Announcement/Notice",
"parentId": "2030925300149387266",
"parentIds": null,
"menuPerms": "notice-Announcement-Notice",
"menuType": 2,
"menuAttribution": "QINGANG_RELATED_PARTIES",
"sort": 9,
"showFlag": 1,
"children": null
}
]
},
{
"extValues": {},
"id": "2030925300149387267",
"menuName": "我的",
"menuUrl": "/my-center",
"parentId": "0",
"parentIds": null,
"menuPerms": "my-center",
"menuType": 2,
"menuAttribution": "QINGANG_RELATED_PARTIES",
"sort": 2,
"showFlag": 1,
"children": [
{
"extValues": {},
"id": "2030925300149387275",
"menuName": "我的信息",
"menuUrl": "/my-center/My/Information",
"parentId": "2030925300149387267",
"parentIds": null,
"menuPerms": "my-center-My-Information",
"menuType": 2,
"menuAttribution": "QINGANG_RELATED_PARTIES",
"sort": 10,
"showFlag": 1,
"children": null
},
{
"extValues": {},
"id": "2030925300149387276",
"menuName": "扫码入职",
"menuUrl": "/my-center/Scan/Code/Onboarding",
"parentId": "2030925300149387267",
"parentIds": null,
"menuPerms": "my-center-Scan-Code-Onboarding",
"menuType": 2,
"menuAttribution": "QINGANG_RELATED_PARTIES",
"sort": 11,
"showFlag": 1,
"children": null
},
{
"extValues": {},
"id": "2030925300149387277",
"menuName": "人脸认证",
"menuUrl": "/my-center/Face/Authentication",
"parentId": "2030925300149387267",
"parentIds": null,
"menuPerms": "my-center-Face-Authentication",
"menuType": 2,
"menuAttribution": "QINGANG_RELATED_PARTIES",
"sort": 12,
"showFlag": 1,
"children": null
},
{
"extValues": {},
"id": "2030925300149387278",
"menuName": "证书信息",
"menuUrl": "/my-center/Certificate/Information",
"parentId": "2030925300149387267",
"parentIds": null,
"menuPerms": "my-center-Certificate-Information",
"menuType": 2,
"menuAttribution": "QINGANG_RELATED_PARTIES",
"sort": 13,
"showFlag": 1,
"children": null
},
{
"extValues": {},
"id": "2030925300149387279",
"menuName": "问题反馈",
"menuUrl": "/my-center/Feedback",
"parentId": "2030925300149387267",
"parentIds": null,
"menuPerms": "my-center-Feedback",
"menuType": 2,
"menuAttribution": "QINGANG_RELATED_PARTIES",
"sort": 14,
"showFlag": 1,
"children": null
},
{
"extValues": {},
"id": "2030925300149387280",
"menuName": "版本更新",
"menuUrl": "/my-center/Version/Update",
"parentId": "2030925300149387267",
"parentIds": null,
"menuPerms": "my-center-Version-Update",
"menuType": 2,
"menuAttribution": "QINGANG_RELATED_PARTIES",
"sort": 15,
"showFlag": 1,
"children": null
},
{
"extValues": {},
"id": "2030925300149387281",
"menuName": "关于我们",
"menuUrl": "/my-center/About/Us",
"parentId": "2030925300149387267",
"parentIds": null,
"menuPerms": "my-center-About-Us",
"menuType": 2,
"menuAttribution": "QINGANG_RELATED_PARTIES",
"sort": 16,
"showFlag": 1,
"children": null
},
{
"extValues": {},
"id": "2030925300149387282",
"menuName": "切换账号",
"menuUrl": "/my-center/Switch/Account",
"parentId": "2030925300149387267",
"parentIds": null,
"menuPerms": "my-center-Switch-Account",
"menuType": 2,
"menuAttribution": "QINGANG_RELATED_PARTIES",
"sort": 17,
"showFlag": 1,
"children": null
},
{
"extValues": {},
"id": "2030925300149387283",
"menuName": "修改密码",
"menuUrl": "/my-center/Change/Password",
"parentId": "2030925300149387267",
"parentIds": null,
"menuPerms": "my-center-Change-Password",
"menuType": 2,
"menuAttribution": "QINGANG_RELATED_PARTIES",
"sort": 18,
"showFlag": 1,
"children": null
},
{
"extValues": {},
"id": "2030925300149387284",
"menuName": "用户注销",
"menuUrl": "/my-center/User/Logout",
"parentId": "2030925300149387267",
"parentIds": null,
"menuPerms": "my-center-User-Logout",
"menuType": 2,
"menuAttribution": "QINGANG_RELATED_PARTIES",
"sort": 19,
"showFlag": 1,
"children": null
},
{
"extValues": {},
"id": "2030925300149387285",
"menuName": "退出登录",
"menuUrl": "/my-center/Logout",
"parentId": "2030925300149387267",
"parentIds": null,
"menuPerms": "my-center-Logout",
"menuType": 2,
"menuAttribution": "QINGANG_RELATED_PARTIES",
"sort": 20,
"showFlag": 1,
"children": null
}
]
}
],
"notEmpty": true,
"empty": false
}

View File

@ -9,19 +9,19 @@ class ApiService {
static final bool isProduct = true;
///
// static final String basePath = "http://192.168.198.8:30140";
static final String basePath =
isProduct
? "https://gbs-gateway.qhdsafety.com"
: "http://192.168.20.100:30140";
static final String basePath = "http://192.168.198.8:30140";
// static final String basePath =
// isProduct
// ? "https://gbs-gateway.qhdsafety.com"
// : "http://192.168.20.100:30140";
///
static final String baseImgPath =
isProduct
? "https://jpfz.qhdsafety.com/gbsFileTest/"
: "http://192.168.20.240:9787/mnt/"; //
// static final String baseImgPath = "https://skqhdg.porthebei.com:9004/file/";
// static final String baseImgPath =
// isProduct
// ? "https://jpfz.qhdsafety.com/gbsFileTest/"
// : "http://192.168.20.240:9787/mnt/"; //
static final String baseImgPath = "https://skqhdg.porthebei.com:9004/file/";
static const publicKey =

View File

@ -57,7 +57,7 @@ class EduApi {
static Future<Map<String, dynamic>> getSignInList(Map data) async {
return HttpManager().request(
'${ApiService.basePath}/edu',
'/app/studentSign/listAll',
'/app/studentSign/listAllNoGroup',
method: Method.post,
data: {
...data,

View File

@ -70,6 +70,7 @@ Future<T?> showModalBottomSheetAfterUnfocus<T>({
void main( ) async {
WidgetsFlutterBinding.ensureInitialized();
StorageService.instance.init();
/**
// 1) SDK SDK
BMFMapSDK.setAgreePrivacy(true);
@ -82,7 +83,7 @@ void main( ) async {
BMFMapSDK.setApiKeyAndCoordType('43G1sKuHV6oRTrdR9VTIGPF9soej7V5a', BMF_COORD_TYPE.BD09LL);
await BMFAndroidVersion.initAndroidVersion(); //
}
*/
await SystemChrome.setPreferredOrientations([
DeviceOrientation.portraitUp,
DeviceOrientation.portraitDown,

View File

@ -13,6 +13,7 @@ import 'package:qhd_prevention/pages/mine/face_ecognition_page.dart';
import 'package:qhd_prevention/pages/mine/mine_sign_page.dart';
import 'package:qhd_prevention/pages/my_appbar.dart';
import 'package:qhd_prevention/services/SessionService.dart';
import 'package:qhd_prevention/services/scan_service.dart';
import 'package:qhd_prevention/tools/tools.dart';
import 'package:qhd_prevention/customWidget/custom_button.dart';
import 'package:qhd_prevention/customWidget/search_bar_widget.dart';
@ -146,6 +147,7 @@ class _StudyClassListPageState extends State<StudyClassListPage> {
await pushPage(SigninInformationListPage(info: item), context);
},
),
if (item['examination'] != 0)
CustomButton(
text: '考试记录',
height: 35,
@ -225,7 +227,11 @@ class _StudyClassListPageState extends State<StudyClassListPage> {
child: Center(child: CircularProgressIndicator()),
);
}
return _buildListItem(list[index]);
final item = list[index];
if (item['state'] != 1) {
return _buildListItem(item);
}
return SizedBox(height: 0);
},
);
}
@ -237,68 +243,7 @@ class _StudyClassListPageState extends State<StudyClassListPage> {
ToastUtil.showNormal(context, '未扫描到二维码');
return;
}
int type = result['type'] ?? 0;
final data = {
...result,
'phone': SessionService.instance.userData?.phone ?? '',
'type': type,
};
LoadingDialogHelper.show();
//
final response = await EduApi.checkSignIn(data);
LoadingDialogHelper.hide();
if (response['success']) {
//
final filePath = await pushPage(
const FaceRecognitionPage(
studentId: '',
data: {},
mode: FaceMode.study,
),
context,
);
final faceData = response['data'];
if (filePath != null) {
//
try {
LoadingDialogHelper.show();
final response = await EduApi.compareFace({
'type': data['type'],
'studentId': faceData['studentId'],
}, filePath);
final faceResultData = response['data'];
if (response['success']) {
final signData = {
'id': faceResultData['id'] ?? '',
'studentId': faceResultData['studentId'] ?? '',
'type': data['type']?? '',
'classId': faceResultData['classId'] ?? '',
'studentSignId':faceResultData['studentSignId']??''
};
_signUpload(signData, type);
} else {
LoadingDialogHelper.hide();
ToastUtil.showNormal(context, response['errMessage'] ?? '验证失败');
}
} catch (e) {
ToastUtil.showNormal(context,'验证失败');
LoadingDialogHelper.hide();
print(e);
}
} else {
LoadingDialogHelper.hide();
ToastUtil.showNormal(context, '签到失败');
}
} else {
ToastUtil.showNormal(context, response['errMessage'] ?? '签到失败');
}
ScanService.scan(context, result);
}
//

View File

@ -244,7 +244,7 @@ class _StudyTakeExamPageState extends State<StudyTakeExamPage> {
final score = data['examScore'] ?? 0;
var passed = data['result'] == 1;
//
final remain = data['surplusExamNum'] ?? 0 <= 0;
bool remain = (data['surplusExamNum'] ?? 0) <= 0;
// /
final result = await CustomAlertDialog.showConfirm(
@ -267,7 +267,7 @@ class _StudyTakeExamPageState extends State<StudyTakeExamPage> {
_resetForRetry();
} else {
//
final msg = res['message'] ?? '提交失败,请重试';
final msg = res['errMessage'] ?? '提交失败,请重试';
ToastUtil.showError(context, msg);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,7 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:qhd_prevention/common/route_model.dart';
import 'package:qhd_prevention/customWidget/toast_util.dart';
import 'package:qhd_prevention/customWidget/work_tab_icon_grid.dart';
import 'package:qhd_prevention/http/ApiService.dart';
import 'package:qhd_prevention/customWidget/IconBadgeButton.dart';
@ -6,6 +9,7 @@ import 'package:qhd_prevention/pages/home/unit/unit_join_list_page.dart';
import 'package:qhd_prevention/pages/my_appbar.dart';
import 'package:qhd_prevention/tools/tools.dart';
import 'package:qhd_prevention/common/route_aware_state.dart';
import 'package:qhd_prevention/common/route_service.dart';
class UnitTabPage extends StatefulWidget {
const UnitTabPage({super.key});
@ -15,47 +19,166 @@ class UnitTabPage extends StatefulWidget {
}
class _UnitTabPageState extends RouteAwareState<UnitTabPage> {
late List<Map<String, dynamic>> buttonInfos = [
// master
final List<Map<String, dynamic>> _masterButtons = [
{
"icon": "assets/images/unit_ico1.png",
"title": "服务单位管理",
"unreadCount": 0,
}
,{
},
{
"icon": "assets/images/unit_ico2.png",
"title": "就职单位管理",
"unreadCount": 0,
}
},
];
// title -> menuPerm
final Map<String, String> _permMapping = {
"服务单位管理": "dashboard-Unit-Management-Managee-Service-Unit-Management",
"就职单位管理": "dashboard-Unit-Management-Employment-Unit",
};
// master
late List<bool> _visible;
@override
void initState() {
super.initState();
}
Future<void> onVisible() async {
_getData();
}
Future<void> _getData() async {
//
_visible = List<bool>.filled(_masterButtons.length, true);
//
RouteService().addListener(_onRouteUpdated);
//
WidgetsBinding.instance.addPostFrameCallback((_) => _updateVisibilityFromRoute());
}
@override
void dispose() {
try {
RouteService().removeListener(_onRouteUpdated);
} catch (_) {}
super.dispose();
}
void _onRouteUpdated() {
//
_updateVisibilityFromRoute();
}
void _updateVisibilityFromRoute() {
final routeService = RouteService();
// routesLoaded: mainTabs
final bool routesLoaded = routeService.mainTabs.isNotEmpty;
final List<bool> next = List<bool>.filled(_masterButtons.length, false);
for (int i = 0; i < _masterButtons.length; i++) {
final title = _masterButtons[i]['title'] as String;
final perm = _permMapping[title] ?? '';
if (!routesLoaded) {
//
next[i] = true;
continue;
}
if (perm.isEmpty) {
//
next[i] = false;
continue;
}
// 使 RouteService.findRouteByPerm visible
final RouteModel? node = routeService.findRouteByPerm(perm);
if (node != null) {
// showFlag == 1
next[i] = (node.showFlag == 1) || (node.visible);
} else {
// menuPerm使 perms
// menuPerm findRouteByPerm
RouteModel? fallback;
for (final top in routeService.allRoutes) {
fallback = _findRouteRecursiveByPerm(top, perm);
if (fallback != null) break;
}
next[i] = fallback != null ? ((fallback.showFlag == 1) || (fallback.visible)) : false;
}
}
// setState
if (!listEquals(next, _visible)) {
setState(() {
_visible = next;
});
}
}
/// node menuPerms targetPerm
/// RouteService.findRouteByPerm fallback
RouteModel? _findRouteRecursiveByPerm(RouteModel node, String targetPerm) {
if ((node.menuPerms ?? '') == targetPerm) return node;
for (final c in node.children) {
final res = _findRouteRecursiveByPerm(c, targetPerm);
if (res != null) return res;
}
return null;
}
//
@override
Future<void> onVisible() async {
await _getData();
}
Future<void> _getData() async {
// TODO: / setState _masterButtons[*]['unreadCount']
// await Future.delayed(Duration(milliseconds: 100));
}
void _handleIconTap(int index) async {
switch (index) {
case 0:
final title = _masterButtons[index]['title'] as String;
switch (title) {
case '服务单位管理':
ToastUtil.showNormal(context, '您还没有参与项目');
break;
case 1:
case '就职单位管理':
pushPage(UnitJoinListPage(), context);
break;
default:
break;
}
_getData();
//
await _getData();
}
@override
Widget build(BuildContext context) {
double bannerHeight = 618/1125 * MediaQuery.of(context).size.width;
const double iconSectionHeight = 150.0;
const double iconOverlapBanner = 30.0; // banner
final double screenW = MediaQuery.of(context).size.width;
final double bannerHeight = 618 / 1125 * screenW;
// icon 4
final visibleButtons = <Map<String, dynamic>>[];
for (int i = 0; i < _masterButtons.length; i++) {
if (i < _visible.length && _visible[i]) visibleButtons.add(_masterButtons[i]);
}
final int visibleCount = visibleButtons.length;
final int perRow = 4;
final int rows = visibleCount == 0 ? 0 : ((visibleCount + perRow - 1) ~/ perRow);
//
const double verticalPadding = 30.0;
const double perRowHeight = 110.0; // + +
const double rowSpacing = 20.0;
final double iconSectionHeight = visibleCount == 0 ? 150.0 : (verticalPadding + rows * perRowHeight + (rows - 1) * rowSpacing);
const double iconOverlapBanner = 30.0;
return PopScope(
canPop: true,
child: Scaffold(
@ -85,7 +208,7 @@ class _UnitTabPageState extends RouteAwareState<UnitTabPage> {
right: 10,
top: bannerHeight - iconOverlapBanner,
height: iconSectionHeight,
child: _buildIconSection(context),
child: _buildIconSection(context, visibleButtons, rows),
),
],
),
@ -94,13 +217,12 @@ class _UnitTabPageState extends RouteAwareState<UnitTabPage> {
),
),
);
}
// Banner
// Banner
Widget _buildBannerSection(double height) {
return Stack(
children: [
//
Image.asset(
"assets/images/unit_banner.jpg",
width: MediaQuery.of(context).size.width,
@ -110,54 +232,80 @@ class _UnitTabPageState extends RouteAwareState<UnitTabPage> {
],
);
}
Widget _buildIconSection(BuildContext context) {
// visibleButtons icon
Widget _buildIconSection(BuildContext context, List<Map<String, dynamic>> visibleButtons, int rows) {
if (visibleButtons.isEmpty) {
if (RouteService().mainTabs.isNotEmpty) {
return Container(
padding: const EdgeInsets.symmetric(vertical: 30, horizontal: 5),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12),
boxShadow: const [BoxShadow(color: Colors.black12, blurRadius: 6, offset: Offset(0, 2))],
),
child: const Center(child: Text('暂无权限访问的功能')),
);
} else {
return Container(
padding: const EdgeInsets.symmetric(vertical: 30, horizontal: 5),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12),
boxShadow: const [BoxShadow(color: Colors.black12, blurRadius: 6, offset: Offset(0, 2))],
),
child: const Center(child: SizedBox()),
);
}
}
// 4
final List<Widget> rowsWidgets = [];
final int perRow = 4;
for (int r = 0; r < rows; r++) {
final start = r * perRow;
final end = (start + perRow) > visibleButtons.length ? visibleButtons.length : (start + perRow);
final rowItems = visibleButtons.sublist(start, end);
rowsWidgets.add(
Row(
children: List.generate(perRow, (i) {
final idx = start + i;
if (idx < visibleButtons.length) {
final btn = visibleButtons[idx];
// master onTap
final masterIndex = _masterButtons.indexWhere((m) => m['title'] == btn['title']);
return Expanded(
child: Center(child: _buildIconButton(btn, masterIndex)),
);
} else {
return const Expanded(child: SizedBox.shrink());
}
}),
),
);
if (r != rows - 1) rowsWidgets.add(const SizedBox(height: 20));
}
return Container(
padding: const EdgeInsets.symmetric(vertical: 30, horizontal: 5),
padding: const EdgeInsets.symmetric(vertical: 18, horizontal: 5),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12),
boxShadow: const [
BoxShadow(
color: Colors.black12,
blurRadius: 6,
offset: Offset(0, 2),
),
],
),
child: Column(
children: [
_buildIconRow(startIndex: 0),
],
boxShadow: const [BoxShadow(color: Colors.black12, blurRadius: 6, offset: Offset(0, 2))],
),
child: Column(children: rowsWidgets),
);
}
Widget _buildIconRow({required int startIndex}) {
final List<Widget> cells = List.generate(4, (i) {
final int idx = startIndex + i;
if (idx < buttonInfos.length) {
return Expanded(
child: Center(child: _buildIconButton(buttonInfos[idx], idx, context)),
);
} else {
return const Expanded(
child: SizedBox.shrink(),
);
}
});
return Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: cells,
);
}
Widget _buildIconButton(Map<String, dynamic> info, int index, BuildContext context) {
Widget _buildIconButton(Map<String, dynamic> info, int masterIndex) {
final unread = (info['unreadCount'] ?? 0) is int ? info['unreadCount'] as int : int.tryParse('${info['unreadCount']}') ?? 0;
return IconBadgeButton(
iconPath: info['icon'] ?? '',
title: info['title'] ?? '',
unreadCount: (info['unreadCount'] ?? 0) is int ? info['unreadCount'] as int : int.tryParse('${info['unreadCount']}') ?? 0,
onTap: () => _handleIconTap(index),
unreadCount: unread,
onTap: () => _handleIconTap(masterIndex),
);
}
}
}

View File

@ -1,15 +1,22 @@
// lib/pages/new/main_page.dart
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart' show rootBundle;
import 'package:qhd_prevention/common/route_service.dart';
import 'package:qhd_prevention/http/modules/appmenu_api.dart';
import 'package:qhd_prevention/pages/badge_manager.dart';
import 'package:qhd_prevention/pages/home/home_page.dart';
import 'package:qhd_prevention/pages/mine/mine_page.dart';
import 'package:qhd_prevention/pages/my_appbar.dart';
import 'package:qhd_prevention/pages/notif/notif_page.dart';
import 'package:qhd_prevention/services/heartbeat_service.dart';
import 'package:qhd_prevention/tools/tools.dart';
import 'mine/mine_page.dart';
/// tab
class CurrentTabNotifier extends InheritedWidget {
final int currentIndex;
const CurrentTabNotifier({
required this.currentIndex,
required Widget child,
@ -38,10 +45,14 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver {
int _currentIndex = 0;
final GlobalKey<HomePageState> _homeKey = GlobalKey<HomePageState>();
final GlobalKey<NotifPageState> _notifKey = GlobalKey<NotifPageState>();
// final GlobalKey<ApplicationPageTwoState> _appKey = GlobalKey<ApplicationPageTwoState>();
final GlobalKey<MinePageState> _mineKey = GlobalKey<MinePageState>();
late List<Widget> _pages;
late List<bool> _tabVisibility; // Tab
// _tabVisibility
late final List<Widget> _pages;
// Tab _pages
// [, , ]
late List<bool> _tabVisibility;
// BadgeManager
late final BadgeManager _badgeManager;
@ -49,53 +60,156 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver {
@override
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
// BadgeManager
_badgeManager = BadgeManager();
_badgeManager.initAllModules();
// BadgeManager
_badgeManager.addListener(_onBadgeChanged);
//
WidgetsBinding.instance.addObserver(this);
// Tab
_tabVisibility = [true, true, true];
// ****
_pages = <Widget>[
HomePage(key: _homeKey, isChooseFirm: widget.isChooseFirm),
NotifPage(key: _notifKey),
MinePage(key: _mineKey, isChooseFirm: widget.isChooseFirm),
];
//
HeartbeatService().start();
// tab
_tabVisibility = [false, false, false];
// RouteService /
RouteService().addListener(_onRoutesUpdated);
// 退 assets
_getRoute();
}
/// 退 assets/route/routes.txt
Future<void> _getRoute() async {
try {
LoadingDialogHelper.show(message: '加载中...');
Map? route;
//
// try {
// final res = await AppMenuApi.getAppMenu();
// if (res != null && res['success'] == true && res['data'] is List) {
// route = res;
// } else {
// debugPrint('AppMenuApi.getAppMenu returned no data or failed; fallback to local assets.');
// }
// } catch (e) {
// debugPrint('AppMenuApi.getAppMenu error: $e -> fallback to local assets.');
// }
//
try {
final routeString = await loadFromAssets();
route = jsonDecode(routeString) as Map<String, dynamic>;
} catch (e) {
debugPrint('loadFromAssets error: $e');
}
if (route != null && route['data'] is List) {
final data = route['data'] as List<dynamic>;
RouteService().initializeRoutes(data);
// initializeRoutes notifyListeners -> _onRoutesUpdated
} else {
debugPrint('No valid route data to initialize RouteService.');
}
} catch (e) {
debugPrint('获取路由配置失败: $e');
} finally {
LoadingDialogHelper.hide();
}
}
Future<String> loadFromAssets() async {
return await rootBundle.loadString('assets/route/routes.txt');
}
void _onRoutesUpdated() {
//
_updateTabVisibilityFromRoutes();
}
/// RouteService _tabVisibility
///
/// - menuPerms == 'dashboard'
/// - menuPerms == 'notice'
/// - menuPerms == 'my-center'
void _updateTabVisibilityFromRoutes() {
final routeService = RouteService();
// 使 mainTabs _tabVisibility
final mainTabs = routeService.mainTabs;
if (mainTabs.isEmpty) {
return;
}
bool homeVisible = false;
bool notifVisible = false;
bool mineVisible = false;
for (final m in mainTabs) {
final perms = (m.menuPerms ?? '').toString();
if (!homeVisible && perms == 'dashboard' && m.visible) {
homeVisible = true;
}
if (!notifVisible && perms == 'notice'&& m.visible) {
notifVisible = true;
}
if (!mineVisible && perms == 'my-center'&& m.visible) {
mineVisible = true;
}
if (homeVisible && notifVisible && mineVisible) break;
}
//
setState(() {
_tabVisibility = [homeVisible, notifVisible, mineVisible];
// tab tab tab 0
if (!_isIndexVisible(_currentIndex)) {
final first = _firstVisibleIndexOrDefault(_currentIndex);
_currentIndex = first;
}
});
}
// tab fallback0
int _firstVisibleIndexOrDefault([int fallback = 0]) {
for (int i = 0; i < _tabVisibility.length; i++) {
if (_tabVisibility[i]) return i;
}
return fallback;
}
bool _isIndexVisible(int index) {
if (index < 0 || index >= _tabVisibility.length) return false;
return _tabVisibility[index];
}
@override
void dispose() {
//
_badgeManager.removeListener(_onBadgeChanged);
//
RouteService().removeListener(_onRoutesUpdated);
WidgetsBinding.instance.removeObserver(this);
//
HeartbeatService().stop();
super.dispose();
}
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
super.didChangeAppLifecycleState(state);
switch (state) {
case AppLifecycleState.resumed:
//
HeartbeatService().resume();
break;
case AppLifecycleState.paused:
case AppLifecycleState.inactive:
case AppLifecycleState.detached:
case AppLifecycleState.hidden:
//
HeartbeatService().pause();
break;
}
@ -134,33 +248,53 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver {
);
}
// ( 0..n) (visiblePages )
// originalIndex 0
int _originalToVisibleIndex(int originalIndex, List<bool> visibility) {
int visibleIndex = 0;
for (int i = 0; i < visibility.length; i++) {
if (!visibility[i]) continue;
if (i == originalIndex) return visibleIndex;
visibleIndex++;
}
// originalIndex -> 0
return visibility.contains(true) ? 0 : 0;
}
// BottomNavigationBar onTap
// visibleIndex 0
int _visibleToOriginalIndex(int visibleIndex, List<bool> visibility) {
int count = 0;
for (int i = 0; i < visibility.length; i++) {
if (!visibility[i]) continue;
if (count == visibleIndex) return i;
count++;
}
// 0
for (int i = 0; i < visibility.length; i++) {
if (visibility[i]) return i;
}
return 0;
}
@override
Widget build(BuildContext context) {
// 使 _badgeManager BadgeManager()
final bm = _badgeManager;
//
// _tabVisibility
final List<BottomNavigationBarItem> visibleItems = [];
final List<Widget> visiblePages = [];
for (int i = 0; i < _tabVisibility.length; i++) {
for (int i = 0; i < _pages.length; i++) {
if (_tabVisibility[i]) {
switch (i) {
case 0:
visibleItems.add(
BottomNavigationBarItem(
icon: Image.asset(
'assets/tabbar/basics.png',
width: 24,
height: 24,
),
activeIcon: Image.asset(
'assets/tabbar/basics_cur.png',
width: 24,
height: 24,
),
label: '首页',
),
);
visibleItems.add(BottomNavigationBarItem(
icon: Image.asset('assets/tabbar/basics.png', width: 24, height: 24),
activeIcon: Image.asset('assets/tabbar/basics_cur.png', width: 24, height: 24),
label: '首页',
));
visiblePages.add(_pages[i]);
break;
case 1:
@ -178,83 +312,105 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver {
visiblePages.add(_pages[i]);
break;
case 2:
visibleItems.add(
BottomNavigationBarItem(
icon: Image.asset(
'assets/tabbar/my.png',
width: 24,
height: 24,
),
activeIcon: Image.asset(
'assets/tabbar/my_cur.png',
width: 24,
height: 24,
),
label: '我的',
),
);
visibleItems.add(BottomNavigationBarItem(
icon: Image.asset('assets/tabbar/my.png', width: 24, height: 24),
activeIcon: Image.asset('assets/tabbar/my_cur.png', width: 24, height: 24),
label: '我的',
));
visiblePages.add(_pages[i]);
break;
}
}
}
// Tab
int getVisibleIndex(int originalIndex) {
int visibleIndex = 0;
for (int i = 0; i <= originalIndex; i++) {
if (_tabVisibility[i]) {
if (i == originalIndex) return visibleIndex;
visibleIndex++;
}
}
return 0; // Tab
}
// body
final bool hasVisiblePages = visiblePages.isNotEmpty;
final visibleCurrentIndex = getVisibleIndex(_currentIndex);
// Tab IndexedStack/BottomNavigationBar
final visibleCurrentIndex = _originalToVisibleIndex(_currentIndex, _tabVisibility);
// ---------- visibleItems ----------
Widget? bottomBarWidget;
if (visibleItems.length >= 2) {
// 使 BottomNavigationBar 2 item
bottomBarWidget = BottomNavigationBar(
currentIndex: visibleCurrentIndex,
type: BottomNavigationBarType.fixed,
selectedItemColor: Colors.blue,
unselectedItemColor: Colors.grey,
onTap: (visibleIndex) {
final originalIndex = _visibleToOriginalIndex(visibleIndex, _tabVisibility);
setState(() => _currentIndex = originalIndex);
},
items: visibleItems,
);
} else if (visibleItems.length == 1) {
// tab BottomNavigationBar
final single = visibleItems[0];
final singleVisibleOriginalIndex = _visibleToOriginalIndex(0, _tabVisibility);
final isSelected = _currentIndex == singleVisibleOriginalIndex;
// icon
final Widget iconWidget = isSelected && single.activeIcon != null ? single.activeIcon! : single.icon;
bottomBarWidget = Material(
elevation: 8,
child: InkWell(
onTap: () {
setState(() {
_currentIndex = singleVisibleOriginalIndex;
});
},
child: Container(
height: kBottomNavigationBarHeight,
color: Colors.white,
child: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
//
SizedBox(
width: 28,
height: 28,
child: Center(child: iconWidget),
),
const SizedBox(height: 4),
//
Text(
single.label ?? '',
style: TextStyle(
color: isSelected ? Colors.blue : Colors.grey,
fontSize: 12,
),
),
],
),
),
),
),
);
} else {
// ->
bottomBarWidget = null;
}
return CurrentTabNotifier(
currentIndex: _currentIndex,
child: Scaffold(
appBar: null,
body: IndexedStack(index: visibleCurrentIndex, children: visiblePages),
bottomNavigationBar:
visibleItems.length >= 2
? BottomNavigationBar(
currentIndex: visibleCurrentIndex,
type: BottomNavigationBarType.fixed,
selectedItemColor: Colors.blue,
unselectedItemColor: Colors.grey,
onTap: (visibleIndex) {
int originalIndex = 0;
int count = 0;
for (int i = 0; i < _tabVisibility.length; i++) {
if (_tabVisibility[i]) {
if (count == visibleIndex) {
originalIndex = i;
break;
}
count++;
}
}
setState(() => _currentIndex = originalIndex);
},
items: visibleItems,
)
: null, // Tab
body: hasVisiblePages
? IndexedStack(
index: visibleCurrentIndex,
children: visiblePages,
)
: const SizedBox.shrink(),
bottomNavigationBar: bottomBarWidget,
),
);
}
void _onBadgeChanged() {
//
// build
if (mounted) {
setState(() {
//
});
}
if (mounted) setState(() {});
}
}
}

View File

@ -1,5 +1,7 @@
// file: mine_page.dart
import 'dart:convert';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:qhd_prevention/customWidget/custom_alert_dialog.dart';
import 'package:qhd_prevention/customWidget/custom_button.dart';
@ -19,10 +21,13 @@ import 'package:qhd_prevention/tools/tools.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'certificate/certificate_list_page.dart';
import 'package:qhd_prevention/common/route_service.dart';
import 'package:qhd_prevention/common/route_model.dart';
class MinePage extends StatefulWidget {
const MinePage({super.key, required this.isChooseFirm});
final bool isChooseFirm;
final bool isChooseFirm;
@override
State<MinePage> createState() => MinePageState();
}
@ -39,22 +44,152 @@ class MinePageState extends State<MinePage> {
String name = '登录/注册';
String phone = '';
/// UI // menuPerm(s)
/// perm
final List<Map<String, dynamic>> _allSettings = [
{
'title': '我的信息',
'icon': 'assets/images/ico9.png',
'perms': ['my-center-My-Information'],
'action': 'userinfo',
},
{
'title': '修改密码',
'icon': 'assets/images/ico16.png',
'perms': ['my-center-Change-Password'],
'action': 'changePwd',
},
{
'title': '扫码入职',
'icon': 'assets/images/ico10.png',
// perm []
'perms': ['dashboard-scan'],
'action': 'scanOnboarding',
},
{
'title': '人脸认证',
'icon': 'assets/images/ico11.png',
'perms': ['my-center-Face-Authentication'],
'action': 'face',
},
{
'title': '证书信息',
'icon': 'assets/images/ico12.png',
'perms': ['my-center-Certificate-Information'],
'action': 'certificate',
},
// {
// 'title': '版本更新',
// 'icon': 'assets/images/ico14.png',
// 'perms': ['my-center-Version-Update'],
// 'action': 'version',
// },
// {
// 'title': '关于我们',
// 'icon': 'assets/images/ico15.png',
// 'perms': ['my-center-About-Us'],
// 'action': 'about',
// },
{
'title': '切换账户',
'icon': 'assets/images/ico_switch.png',
// widget.isChooseFirm true
'perms': ['my-center-Switch-Account'],
'action': 'changeAccount',
},
{
'title': '账户注销',
'icon': 'assets/images/ico_quit.png',
//
'perms': ['my-center-User-Logout', 'my-center-Logout'],
'action': 'logout',
},
];
// _allSettings
late List<bool> _visible;
void onRouteConfigLoaded() {
if (mounted) {
setState(() {
// _updateMenuVisibility();
// update listener
});
}
}
@override
void initState() {
// TODO: implement initState
super.initState();
_getUserInfo();
// /
_visible = List<bool>.filled(_allSettings.length, true);
//
RouteService().addListener(_onRouteServiceUpdated);
// route
WidgetsBinding.instance.addPostFrameCallback((_) => _updateVisibilityFromRoute());
}
//
@override
void dispose() {
try {
RouteService().removeListener(_onRouteServiceUpdated);
} catch (_) {}
super.dispose();
}
void _onRouteServiceUpdated() {
_updateVisibilityFromRoute();
}
/// RouteService
void _updateVisibilityFromRoute() {
final rs = RouteService();
// mainTabs visible
if (rs.mainTabs.isEmpty) {
return;
}
final List<bool> next = List<bool>.filled(_allSettings.length, false);
for (int i = 0; i < _allSettings.length; i++) {
final perms = (_allSettings[i]['perms'] ?? []) as List<String>;
if (perms.isEmpty) {
// /
next[i] = true;
continue;
}
// perm
bool anyFound = false;
for (final p in perms) {
final node = rs.findRouteByPerm(p);
if (node != null) {
// rs.findRouteByPerm visible RouteService
// showFlag==1 showFlag==0 ()
if (node.showFlag == 1 || node.visible) {
anyFound = true;
break;
}
}
}
next[i] = anyFound;
}
// _visible setState
if (!listEquals(next, _visible)) {
setState(() {
_visible = next;
});
}
}
//
Future<void> _getUserInfo() async {
final res = await BasicInfoApi.getUserMessage(
'${SessionService.instance.accountId}',
@ -69,111 +204,8 @@ class MinePageState extends State<MinePage> {
});
}
}
@override
Widget build(BuildContext context) {
final double headerHeight = 300.0;
final double overlap = 100.0;
return SizedBox(
height: MediaQuery.of(context).size.height,
child: Stack(
children: [
Positioned(
top: 0,
left: 0,
right: 0,
height: headerHeight,
child: _buildHeaderSection(),
),
Positioned.fill(
child: NotificationListener<OverscrollIndicatorNotification>(
onNotification: (overscroll) {
overscroll.disallowIndicator();
return false;
},
child: ListView(
padding: EdgeInsets.only(
top: headerHeight - overlap,
bottom: 24,
left: 0,
right: 0,
),
children: [
_buildSettingsList(),
SizedBox(height: 15),
Padding(
padding: EdgeInsetsGeometry.symmetric(horizontal: 15),
child: CustomButton(
text: '退出登录',
textStyle: TextStyle(fontSize: 16),
backgroundColor: Colors.blue,
// borderRadius: 15,
onPressed: () {
CustomAlertDialog.showConfirm(
context,
title: '确认退出',
content: '确定要退出当前账号吗',
onConfirm: () async {
// await AuthService.logout(); //
// if (!mounted) return;
//
await _clearUserSession();
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(
builder: (context) => const LoginPage(),
),
(Route<dynamic> route) => false,
);
},
);
},
),
),
],
),
),
),
],
),
);
}
Widget _buildHeaderSection() {
return Stack(
alignment: const FractionalOffset(0.5, 0),
children: [
Padding(
padding: EdgeInsets.fromLTRB(0, 0, 0, 10),
child:
Image.asset(
"assets/images/my_bg.png",
width: MediaQuery.of(context).size.width, //
fit: BoxFit.cover,
),
),
Positioned(
top: 51,
child: Text(
"我的",
style: TextStyle(
color: Colors.white,
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
),
//
_buildSloganSection(),
],
);
}
Future<void> _logout() async {
LoadingDialogHelper.show();
///
@ -192,8 +224,7 @@ class MinePageState extends State<MinePage> {
context,
title: '温馨提示',
content: '注销后您的所有信息将会被删除\n请确认是否注销。 ',
onConfirm: () {
},
onConfirm: () {},
);
if (result) {
CustomAlertDialog.showInputWithCode(
@ -209,8 +240,7 @@ class MinePageState extends State<MinePage> {
},
onConfirm: (code) async {
_quit(code);
}
);
});
}
}
} else {
@ -223,8 +253,8 @@ class MinePageState extends State<MinePage> {
Future<void> _quit(String code) async {
LoadingDialogHelper.show();
Map data = {
'id' : SessionService.instance.accountId,
'phoneCode' : code,
'id': SessionService.instance.accountId,
'phoneCode': code,
};
await BasicInfoApi.logout(data).then((res) async {
LoadingDialogHelper.dismiss();
@ -233,8 +263,7 @@ class MinePageState extends State<MinePage> {
await SessionService.instance.clear(clearPrefs: true);
Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (_) => const LoginPage()),
MaterialPageRoute(builder: (_) => const LoginPage()),
);
} else {
ToastUtil.showNormal(context, res['errMessage'] ?? '');
@ -246,28 +275,21 @@ class MinePageState extends State<MinePage> {
final headerUrl = SessionService.instance.userData?.userAvatarUrl ?? '';
return Container(
margin: EdgeInsets.fromLTRB(0, 100, 0, 0),
margin: const EdgeInsets.fromLTRB(0, 100, 0, 0),
padding: const EdgeInsets.symmetric(vertical: 16, horizontal: 20),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, //
// crossAxisAlignment: CrossAxisAlignment.center, //
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
children: [
headerUrl.isEmpty
? const CircleAvatar(
backgroundImage: AssetImage("assets/images/my_bg.png"),
radius: 30,
)
: CircleAvatar(
backgroundImage: NetworkImage(ApiService.baseImgPath + headerUrl),
radius: 30,
),
const CircleAvatar(
backgroundImage: AssetImage("assets/images/yingyong11.png"),
radius: 30,
),
const SizedBox(width: 16),
Text(
name,
style: TextStyle(
style: const TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: Colors.white,
@ -281,136 +303,6 @@ class MinePageState extends State<MinePage> {
);
}
Widget _buildSettingsList() {
return Container(
margin: const EdgeInsets.fromLTRB(20, 0, 20, 0),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(16),
boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.1),
spreadRadius: 2,
blurRadius: 8,
offset: const Offset(0, 4),
),
],
),
child: Column(
children: [
_buildSettingItem(
title: "我的信息",
icon: "assets/images/ico9.png",
value: notificationsEnabled,
onChanged: (value) async {
await pushPage(
FullUserinfoPage(isEidt: false, isChooseFirm: true),
context,
);
},
),
_buildSettingItem(
title: "修改密码",
icon: "assets/images/ico16.png",
value: notificationsEnabled,
onChanged: (value) async {
await pushPage(MineSetPwdPage('0'), context);
},
),
_buildSettingItem(
title: "扫码入职",
icon: "assets/images/ico10.png",
value: scanAuthentication,
onChanged: (value) async {
final result = await pushPage(
ScanPage(type: ScanType.Onboarding),
context,
);
if (result == null) {
return;
}
pushPage(OnboardingFullPage(scanData: result), context);
},
),
_buildSettingItem(
title: "人脸认证",
icon: "assets/images/ico11.png",
value: faceAuthentication,
onChanged: (value) {
pushPage(
const FaceRecognitionPage(
studentId: '',
data: {},
mode: FaceMode.setUpdata,
),
context,
);
},
),
_buildSettingItem(
title: "证书信息",
icon: "assets/images/ico12.png",
value: passwordChanged,
onChanged: (value) {
pushPage(
const CertificateListPage(),
context,
);
},
),
// _buildSettingItem(
// title: "问题反馈",
// icon: "assets/images/ico13.png",
// value: passwordChanged,
// onChanged: (value) {
// ToastUtil.showNormal(context, '需求待定');
// // pushPage(FeedbackPage(), context);
// },
// ),
// const Divider(height: 1, indent: 60),
_buildSettingItem(
title: "版本更新",
icon: "assets/images/ico14.png",
value: updateAvailable,
onChanged: (value) => setState(() => updateAvailable = value!),
),
_buildSettingItem(
title: "关于我们",
icon: "assets/images/ico15.png",
value: logoutSelected,
onChanged: (value) {
setState(() => logoutSelected = value!);
},
),
if (widget.isChooseFirm)
_buildSettingItem(
title: "切换账户",
icon: "assets/images/ico_switch.png",
value: logoutSelected,
onChanged: (value) {
pushPage(MineChangeFirmPage(), context);
},
),
_buildSettingItem(
title: "账户注销",
icon: "assets/images/ico_quit.png",
value: logoutSelected,
onChanged: (value) {
_logout();
},
),
],
),
);
}
Widget _buildSettingItem({
required String title,
required String icon,
@ -435,16 +327,9 @@ class MinePageState extends State<MinePage> {
title,
style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w500),
),
trailing: Transform.scale(
scale: 1.2,
child: Icon(Icons.chevron_right),
// Image.asset(
// "assets/images/right.png",
// fit: BoxFit.cover,
// width: 15,
// height: 15,
// ),
child: const Icon(Icons.chevron_right),
),
),
);
@ -454,4 +339,160 @@ class MinePageState extends State<MinePage> {
final prefs = await SharedPreferences.getInstance();
await prefs.remove('isLoggedIn'); //
}
}
void _onSettingTapAction(String action) async {
switch (action) {
case 'userinfo':
await pushPage(FullUserinfoPage(isEidt: false, isChooseFirm: true), context);
break;
case 'changePwd':
await pushPage(MineSetPwdPage('0'), context);
break;
case 'scanOnboarding':
final result = await pushPage(ScanPage(type: ScanType.Onboarding), context);
if (result == null) return;
pushPage(OnboardingFullPage(scanData: result), context);
break;
case 'face':
pushPage(const FaceRecognitionPage(studentId: '', data: {}, mode: FaceMode.setUpdata), context);
break;
case 'certificate':
pushPage(const CertificateListPage(), context);
break;
case 'version':
//
ToastUtil.showNormal(context, '功能开发中...');
break;
case 'about':
//
ToastUtil.showNormal(context, '功能开发中...');
break;
case 'changeAccount':
pushPage(MineChangeFirmPage(), context);
break;
case 'logout':
_logout();
break;
default:
break;
}
}
Widget _buildSettingsList() {
final children = <Widget>[];
for (int i = 0; i < _allSettings.length; i++) {
// _visible
if (i >= _visible.length) continue;
if (!_visible[i]) continue;
final item = _allSettings[i];
final title = item['title'] as String;
// '切换账户' isChooseFirm true
if (title == '切换账户' && !widget.isChooseFirm) continue;
children.add(_buildSettingItem(
title: title,
icon: item['icon'] as String,
value: false,
onChanged: (_) => _onSettingTapAction(item['action'] as String),
));
}
return Container(
margin: const EdgeInsets.fromLTRB(20, 0, 20, 0),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(16),
boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.1),
spreadRadius: 2,
blurRadius: 8,
offset: const Offset(0, 4),
),
],
),
child: Column(
children: children,
),
);
}
@override
Widget build(BuildContext context) {
final double headerHeight = 300.0;
final double overlap = 100.0;
return SizedBox(
height: MediaQuery.of(context).size.height,
child: Stack(
children: [
Positioned(top: 0, left: 0, right: 0, height: headerHeight, child: _buildHeaderSection()),
Positioned.fill(
child: NotificationListener<OverscrollIndicatorNotification>(
onNotification: (overscroll) {
overscroll.disallowIndicator();
return false;
},
child: ListView(
padding: EdgeInsets.only(top: headerHeight - overlap, bottom: 24, left: 0, right: 0),
children: [
_buildSettingsList(),
const SizedBox(height: 15),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 15),
child: CustomButton(
text: '退出登录',
textStyle: const TextStyle(fontSize: 16),
backgroundColor: Colors.blue,
onPressed: () {
CustomAlertDialog.showConfirm(
context,
title: '确认退出',
content: '确定要退出当前账号吗',
onConfirm: () async {
await _clearUserSession();
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(builder: (context) => const LoginPage()),
(Route<dynamic> route) => false,
);
},
);
},
),
),
],
),
),
),
],
),
);
}
Widget _buildHeaderSection() {
return Stack(
alignment: const FractionalOffset(0.5, 0),
children: [
Padding(
padding: const EdgeInsets.fromLTRB(0, 0, 0, 10),
child: Image.asset(
"assets/images/my_bg.png",
width: MediaQuery.of(context).size.width,
fit: BoxFit.cover,
),
),
const Positioned(
top: 51,
child: Text(
"我的",
style: TextStyle(color: Colors.white, fontSize: 20, fontWeight: FontWeight.bold),
),
),
_buildSloganSection(),
],
);
}
}

View File

@ -0,0 +1,131 @@
import 'package:flutter/material.dart';
import 'package:qhd_prevention/constants/app_enums.dart';
import 'package:qhd_prevention/customWidget/toast_util.dart';
import 'package:qhd_prevention/http/modules/edu_api.dart';
import 'package:qhd_prevention/http/modules/file_api.dart';
import 'package:qhd_prevention/pages/home/Study/study_take_exam_page.dart';
import 'package:qhd_prevention/pages/mine/face_ecognition_page.dart';
import 'package:qhd_prevention/pages/mine/mine_sign_page.dart';
import 'package:qhd_prevention/pages/mine/onboarding_full_page.dart';
import 'package:qhd_prevention/services/SessionService.dart';
import 'package:qhd_prevention/tools/tools.dart';
class ScanService {
static void scan(BuildContext context, final result) async {
if (FormUtils.hasValue(result, 'classId')) { // 线
int type = result['type'] ?? 0;
final data = {
...result,
'phone': SessionService.instance.userData?.phone ?? '',
'type': type,
};
LoadingDialogHelper.show();
//
final response = await EduApi.checkSignIn(data);
LoadingDialogHelper.hide();
if (response['success']) {
//
final filePath = await pushPage(
const FaceRecognitionPage(
studentId: '',
data: {},
mode: FaceMode.study,
),
context,
);
final faceData = response['data'];
if (filePath != null) {
//
try {
LoadingDialogHelper.show();
final response = await EduApi.compareFace({
'type': data['type'],
'studentId': faceData['studentId'],
}, filePath);
final faceResultData = response['data'];
if (response['success']) {
final signData = {
'id': faceResultData['id'] ?? '',
'studentId': faceResultData['studentId'] ?? '',
'type': data['type']?? '',
'classId': faceResultData['classId'] ?? '',
'studentSignId':faceResultData['studentSignId']??''
};
ScanService.signUpload(signData, type, context);
} else {
LoadingDialogHelper.hide();
ToastUtil.showNormal(context, response['errMessage'] ?? '验证失败');
}
} catch (e) {
ToastUtil.showNormal(context,'验证失败');
LoadingDialogHelper.hide();
print(e);
}
} else {
LoadingDialogHelper.hide();
ToastUtil.showNormal(context, '签到失败');
}
} else {
ToastUtil.showNormal(context, response['errMessage'] ?? '签到失败');
}
}
if (FormUtils.hasValue(result, 'corpinfoId')) { //
pushPage(OnboardingFullPage(scanData: result), context);
}
}
//
static Future<void> signUpload(Map data, int type, BuildContext context) async {
LoadingDialogHelper.hide();
UploadFileType fileType =
type == 1
? UploadFileType.onlineLearningSignSignature
: UploadFileType.onlineLearningExamSignature;
final signPath = await pushPage(MineSignPage(), context);
if (signPath != null) {
//
try {
LoadingDialogHelper.show();
//
final response = await FileApi.uploadFile(signPath, fileType, '');
if (response['success']) {
data['signUrl'] = response['data']['filePath'];
final signResult = await EduApi.uploadSignature(data);
LoadingDialogHelper.hide();
if (signResult['success']) {
if (type == 1) {
ToastUtil.showNormal(context, '签到成功');
} else {
//
final examResult = await EduApi.getExamDetail(
data['classId'] ?? '',
);
LoadingDialogHelper.hide();
//
pushPage(
StudyTakeExamPage(
examInfo: examResult['data'] ?? {}, signInfo: data),
context,
);
}
} else {
LoadingDialogHelper.hide();
ToastUtil.showNormal(context, signResult['errMessage'] ?? '');
}
} else {
LoadingDialogHelper.hide();
ToastUtil.showNormal(context, response['errMessage'] ?? '');
}
} catch (e) {
LoadingDialogHelper.hide();
print(e);
}
}
}
}

View File

@ -155,6 +155,7 @@ flutter:
- assets/map/
- assets/tabbar/
- assets/study/
- assets/route/routes.txt
# - images/a_dot_burr.jpeg
# - images/a_dot_ham.jpeg