统一用户、证照

master
hs 2026-01-14 09:55:23 +08:00
parent bb4bf15dc6
commit 256a8bec1a
26 changed files with 1520 additions and 619 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 529 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 155 KiB

View File

@ -20,7 +20,7 @@ enum UploadFileType {
/// - : '4', : 'hidden_danger_rectification_photo'
hiddenDangerRectificationPhoto('4', 'hidden_danger_rectification_photo'),
/// - : '5', : 'hidden_danger_verification_photo'
/// - : '5', : 'hidden_danger_verification_photo'
hiddenDangerVerificationPhoto('5', 'hidden_danger_verification_photo'),
/// - : '6', : 'certificate_photo'
@ -215,18 +215,57 @@ enum UploadFileType {
/// - : '147', : 'hidden_qualified_listInspection_signature'
hiddenQualifiedListInspectionSignature('147', 'hidden_qualified_listInspection_signature'),
/// - : '150', : 'promise_bookmark_photo'
/// - - : '148', : 'special_qualification'
specialQualification('148', 'special_qualification'),
/// -使148 - : '149', : 'safety_qualification'
safetyQualificationDeprecated('149', 'safety_qualification'),
/// - : '150', : 'promise_bookmark_photo'
promiseBookmarkPhoto('150', 'promise_bookmark_photo'),
/// - : '151', : 'project_related_materials'
/// - - : '151', : 'project_related_materials'
projectRelatedMaterials('151', 'project_related_materials'),
/// - : '152', : 'legal_and_regulatory_database'
legalAndRegulatoryDatabase('152', 'legal_and_regulatory_database'),
/// - : '153', : 'regulations_resource_library'
regulationsResourceLibrary('153', 'regulations_resource_library'),
/// - : '154', : 'responsibility_based_resource_library'
responsibilityBasedResourceLibrary('154', 'responsibility_based_resource_library'),
/// - : '155', : 'institutional_resource_library'
institutionalResourceLibrary('155', 'institutional_resource_library'),
/// - - : '156', : 'security_management_agreement'
securityManagementAgreement('156', 'security_management_agreement'),
/// - : '157', : 'supervision_personnel_vehicle'
supervisionPersonnelVehicle('157', 'supervision_personnel_vehicle'),
/// - : '158', : 'supervision_personnel_vehicle_license'
supervisionPersonnelVehicleLicense('158', 'supervision_personnel_vehicle_license'),
/// - : '159', : 'special_operation_personnel_photo'
specialOperationPersonnelPhoto('159', 'special_operation_personnel_photo'),
/// - : '160', : 'special_equipment_operator_photo'
specialEquipmentOperatorPhoto('160', 'special_equipment_operator_photo'),
/// - : '161', : 'main_responsible_person_photo'
mainResponsiblePersonPhoto('161', 'main_responsible_person_photo'),
/// - : '162', : 'photos_safety_production_management_personnel'
photosSafetyProductionManagementPersonnel('162', 'photos_safety_production_management_personnel'),
/// - : '300', : 'facial_recognition_images'
facialRecognitionImages('300', 'facial_recognition_images'),
/// ai - : '301', : 'ai_recognition_images'
aiRecognitionImages('301', 'ai_recognition_images'),
/// - : '601', : 'gate_access_vehicle_license_photo'
gateAccessVehicleLicensePhoto('601', 'gate_access_vehicle_license_photo'),
@ -319,4 +358,4 @@ enum UploadFileType {
/// print(allPaths.contains('hidden_danger_video')); // : true
/// ```
static List<String> get allPaths => values.map((e) => e.path).toList();
}
}

View File

@ -14,7 +14,7 @@ import 'package:flutter/material.dart';
/// }
enum BottomPickerMode {
dateTime, //
date, //
date, // //
dateTimeWithSeconds, //
}

View File

@ -6,7 +6,7 @@ export 'modules/special_work_api.dart';
class ApiService {
///
static final bool isProduct = false;
static final bool isProduct = true;
///
static final String basePath =
@ -14,6 +14,7 @@ class ApiService {
? "https://gbs-gateway.qhdsafety.com"
: "http://192.168.20.100:30140";
///
static final String baseImgPath =
isProduct

View File

@ -43,24 +43,29 @@ class HttpManager {
..add(LogInterceptor(request: true, responseBody: true, error: true))
..add(InterceptorsWrapper(onError: (err, handler) {
// TODO
String message = err.response?.data?['errMessage'] ?? '';
// 401
if (err.response?.statusCode == 401) {
//
onUnauthorized?.call();
//
final apiException = ApiException(
'提示',
'您的账号已在其他设备登录,已自动下线'
);
//
return handler.reject(
DioException(
requestOptions: err.requestOptions,
error: apiException,
response: err.response,
type: DioExceptionType.badResponse,
),
);
if (err.response?.statusCode == 401 || message.contains('客户端Token值验证未通过')) {
//
onUnauthorized?.call();
//
final apiException = ApiException(
'提示',
'下线'
);
//
return handler.reject(
DioException(
requestOptions: err.requestOptions,
error: apiException,
response: err.response,
type: DioExceptionType.badResponse,
),
);
}
handler.next(err);
}));

View File

@ -36,12 +36,14 @@ class BasicInfoApi {
}
///
static Future<Map<String, dynamic>> updateUserInfo(Map data) {
static Future<Map<String, dynamic>> updateUserInfo(Map data, String userIdCard) {
return HttpManager().request(
ApiService.basePath + (ApiService.isProduct ? '/basicInfo' : '/basicInfo') ,
'/appuser/perfectUserInfo',
method: Method.post,
data: {...data},
data: {...data,
'userIdCard' : userIdCard
},
);
}
@ -160,3 +162,53 @@ class BasicInfoApi {
}
}
///
class CertificateApi {
//
static Future<Map<String, dynamic>> getCertificateList(Map data) {
return HttpManager().request(
ApiService.basePath + '/certificate',
'/userCertificate/list',
method: Method.post,
data: {...data},
);
}
//
static Future<Map<String, dynamic>> addCertificate(Map data) {
return HttpManager().request(
ApiService.basePath + '/certificate',
'/userCertificate/save',
method: Method.post,
data: {...data},
);
}
// getCertificateDetail
static Future<Map<String, dynamic>> getCertificateDetail(String id) {
return HttpManager().request(
ApiService.basePath + '/certificate',
'/userCertificate/getInfoById/$id',
method: Method.get,
data: {},
);
}
/// updateCertificate
static Future<Map<String, dynamic>> updateCertificate(Map data) {
return HttpManager().request(
ApiService.basePath + '/certificate',
'/userCertificate/edit',
method: Method.put,
data: {...data},
);
}
/// deleteCertificate
static Future<Map<String, dynamic>> deleteCertificate(String id) {
return HttpManager().request(
ApiService.basePath + '/certificate',
'/userCertificate/delete/$id',
method: Method.delete,
data: {},
);
}
}

View File

@ -69,9 +69,10 @@ class FileApi {
}
///
static Future<Map<String, dynamic>> deleteImages(List<String> ids) {
final idInts = ids.map((e) => int.parse(e)).toList();
return HttpManager().request(
ApiService.basePath,
'/basicInfo/imgFiles/ids?ids=${ids.join(",")}',
'/basicInfo/imgFiles/ids?ids=${idInts.join(",")}',
method: Method.delete,
data: {
},
@ -93,17 +94,21 @@ class FileApi {
}
///
static Future<Map<String, dynamic>> getImagePathWithType(String eqForeignKey,String inForeignKey, UploadFileType typeEnum) {
final data = {
/// id
"eqForeignKey": eqForeignKey,
"eqType": typeEnum.type,
};
if (inForeignKey.isNotEmpty) {
/// ids,
data['inForeignKey'] = inForeignKey;
}
return HttpManager().request(
ApiService.basePath,
'/basicInfo/imgFiles/listAll',
method: Method.get,
data: {
/// id
"eqForeignKey": eqForeignKey,
/// ids,
"inForeignKey": inForeignKey,
"eqType": typeEnum.type,
},
data: data,
);
}
}

View File

@ -109,7 +109,7 @@ void main( ) async {
bool _isDialogShowing = false;
HttpManager.onUnauthorized = () async {
return;
// return;
final navState = navigatorKey.currentState;
if (navState == null) return;
@ -143,7 +143,7 @@ void main( ) async {
// Android
child: AlertDialog(
title: const Text('提示'),
content: const Text('您的账号已在其他设备登录,已自动下线,请使用单一设备进行学习。'),
content: const Text('登录状态已过期,请重新登录'),
actions: [
TextButton(
onPressed: () {

View File

@ -1,13 +1,48 @@
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:qhd_prevention/constants/app_enums.dart';
import 'package:qhd_prevention/customWidget/custom_alert_dialog.dart';
import 'package:qhd_prevention/customWidget/custom_button.dart';
import 'package:qhd_prevention/customWidget/item_list_widget.dart';
import 'package:qhd_prevention/customWidget/photo_picker_row.dart';
import 'package:qhd_prevention/customWidget/picker/CupertinoDatePicker.dart';
import 'package:qhd_prevention/customWidget/toast_util.dart';
import 'package:qhd_prevention/http/ApiService.dart';
import 'package:qhd_prevention/http/modules/basic_info_api.dart';
import 'package:qhd_prevention/pages/home/certificate/certificate_list_page.dart';
import 'package:qhd_prevention/pages/my_appbar.dart';
import 'package:qhd_prevention/customWidget/bottom_picker.dart';
import 'package:qhd_prevention/services/SessionService.dart';
import 'package:qhd_prevention/tools/tools.dart';
import 'dart:io';
enum CertifitcateTypeMode {
//
specialEquipment('tzsbczry', 2),
//
principal('zyfzr', 3),
//
safetyManager('aqscglry', 4),
//
specialWorker('tezhongzuoye', 1),
//
normal('nor', 0);
const CertifitcateTypeMode(this.value, this.type);
final String value;
final int type;
}
class CertificateDetailPage extends StatefulWidget {
const CertificateDetailPage({super.key, required this.model});
const CertificateDetailPage({
super.key,
required this.model,
required this.id,
});
final String id;
final CertifitcateEditMode model;
@override
@ -15,115 +50,669 @@ class CertificateDetailPage extends StatefulWidget {
}
class _CertificateDetailPageState extends State<CertificateDetailPage> {
final pd = {};
late Map pd = {};
Future<void> _saveSuccess() async {
//
List _cerTypes = [];
///
List _specialWorkList = [];
List _chooseWorkTypeList = [];
//
List<String> _cerImgList = [];
List<String> _idCartImgIds = [];
//
List<String> _cerImgRemoveList = [];
List<String> cerPhotos = [];
///
List _equipmentList = [];
List _chooseEquipmentTypeList = [];
bool _isEdit = false;
late CertifitcateTypeMode _chooseMode = CertifitcateTypeMode.normal;
@override
void initState() {
super.initState();
_isEdit =
widget.model == CertifitcateEditMode.add ||
widget.model == CertifitcateEditMode.edit;
_getKeyValues();
}
Future<void> _getData() async {
try {
final result = await CertificateApi.getCertificateDetail(widget.id);
LoadingDialogHelper.dismiss();
if (result['success'] == true) {
setState(() {
pd = result['data'];
_chooseMode = CertifitcateTypeMode.normal;
if (pd['type'] == CertifitcateTypeMode.principal.value) {
_chooseMode = CertifitcateTypeMode.principal;
}
if (pd['type'] == CertifitcateTypeMode.specialEquipment.value) {
_chooseMode = CertifitcateTypeMode.specialEquipment;
for (Map item in _equipmentList) {
if (item['dictValue'] == pd['assignmentOperatingItemsCode']) {
_chooseEquipmentTypeList = item['children'];
break;
}
}
}
if (pd['type'] == CertifitcateTypeMode.specialWorker.value) {
_chooseMode = CertifitcateTypeMode.specialWorker;
for (Map item in _specialWorkList) {
if (item['dictValue'] == pd['industryCategoryCode']) {
_chooseWorkTypeList = item['children'];
break;
}
}
}
for (Map item in _cerTypes) {
if (item['dictValue'] == pd['type']) {
pd['typeName'] = item['dictLabel'] ?? '';
break;
}
}
_getCertificatePhotos(pd['userCertificateId']);
});
} else {
ToastUtil.showNormal(context, result['errMessage'] ?? '');
}
} catch (e) {
LoadingDialogHelper.dismiss();
}
}
//
Future<void> _getCertificatePhotos(String userCertificateId) async {
var fileEnum = _getFileType();
try {
final result = await FileApi.getImagePath(userCertificateId, fileEnum);
setState(() {
List resultList = result['data'];
_cerImgList =
resultList.map((item) => item['filePath'].toString()).toList();
_idCartImgIds =
resultList.map((item) => item['id'].toString()).toList();
});
} catch (e) {
print(e);
}
}
UploadFileType _getFileType() {
switch (_chooseMode) {
case CertifitcateTypeMode.specialWorker:
return UploadFileType.specialOperationPersonnelPhoto;
case CertifitcateTypeMode.specialEquipment:
return UploadFileType.specialEquipmentOperatorPhoto;
case CertifitcateTypeMode.principal:
return UploadFileType.mainResponsiblePersonPhoto;
case CertifitcateTypeMode.safetyManager:
return UploadFileType.photosSafetyProductionManagementPersonnel;
default:
return UploadFileType.specialOperationPersonnelPhoto;
}
}
Future<void> _getKeyValues() async {
LoadingDialogHelper.show();
try {
await BasicInfoApi.getDictValues('zslx').then((res) {
_cerTypes = res['data'];
});
///
await BasicInfoApi.getDictValues('tzzyryhylb0000').then((res) {
_specialWorkList = res['data'];
});
///
await BasicInfoApi.getDictValues('tzsbczryczxmzylb0000').then((res) {
_equipmentList = res['data'];
});
if (widget.model == CertifitcateEditMode.edit ||
widget.model == CertifitcateEditMode.detail) {
_getData();
} else {
LoadingDialogHelper.dismiss();
}
} catch (e) {
print(e);
LoadingDialogHelper.dismiss();
}
}
void _uploadChooseType(Map found) {
String typeCode = found['dictValue'];
String typeName = found['dictLabel'];
setState(() {
if (typeCode == CertifitcateTypeMode.principal.value) {
//
_chooseMode = CertifitcateTypeMode.principal;
}
if (typeCode == CertifitcateTypeMode.specialEquipment.value) {
//
_chooseMode = CertifitcateTypeMode.specialEquipment;
}
if (typeCode == CertifitcateTypeMode.specialWorker.value) {
//
_chooseMode = CertifitcateTypeMode.specialWorker;
}
if (typeCode == CertifitcateTypeMode.safetyManager.value) {
//
_chooseMode = CertifitcateTypeMode.safetyManager;
}
pd['type'] = typeCode;
pd['typeName'] = typeName;
});
}
Future<void> _submit() async {
if (!_checkSubmit()) {
return;
}
LoadingDialogHelper.show();
//
await _checkDeleteImage();
//
if (!await _uploadCertificatePhotos()) {
return;
}
try {
if (!FormUtils.hasValue(pd, 'corpinfoId')) {
pd['corpinfoId'] = SessionService.instance.tenantId;
}
if (!FormUtils.hasValue(pd, 'userId')) {
pd['userId'] = SessionService.instance.accountId;
}
final result;
if (widget.model == CertifitcateEditMode.add) {
result = await CertificateApi.addCertificate(pd);
} else {
result = await CertificateApi.updateCertificate(pd);
}
LoadingDialogHelper.hide();
if (result['success'] == true) {
ToastUtil.showNormal(context, '保存成功');
Navigator.of(context).pop();
} else {
ToastUtil.showNormal(context, result['errMessage'] ?? '保存失败');
}
LoadingDialogHelper.dismiss();
} catch (e) {
print(e);
ToastUtil.showNormal(context, '保存失败');
LoadingDialogHelper.dismiss();
}
}
Future<bool> _checkDeleteImage() async {
late bool isSuccess = true;
if (_cerImgRemoveList.isNotEmpty) {
final delIds = _cerImgRemoveList;
try {
await FileApi.deleteImages(delIds).then((result) {
if (result['success']) {
isSuccess = true;
} else {
isSuccess = false;
}
});
} catch (e) {
LoadingDialogHelper.hide();
}
} else {
isSuccess = true;
}
return isSuccess;
}
//
Future<bool> _uploadCertificatePhotos() async {
if (cerPhotos.isEmpty) {
return true;
}
var fileEnum = _getFileType();
try {
final result = await FileApi.uploadFiles(
cerPhotos,
fileEnum,
pd['userCertificateId'] ?? '',
);
if (result['success'] == true) {
if (!FormUtils.hasValue(pd, 'userCertificateId')) {
//
pd['userCertificateId'] = result['data']['foreignKey'] ?? '';
}
return true;
}else{
ToastUtil.showNormal(context, result['errMessage'] ?? '保存失败');
}
} catch (e) {
LoadingDialogHelper.hide();
return false;
print(e);
}
return false;
}
bool _checkSubmit() {
if (cerPhotos.length + _cerImgList.length < 2) {
ToastUtil.showNormal(context, '请上传证书正面和反面照片');
return false;
}
if (!FormUtils.hasValue(pd, 'typeName')) {
ToastUtil.showNormal(context, '请选择证书类型');
return false;
}
if (!FormUtils.hasValue(pd, 'certificateName')) {
ToastUtil.showNormal(context, '请填写证书名称');
return false;
}
if (!FormUtils.hasValue(pd, 'certificateCode')) {
ToastUtil.showNormal(context, '请填写证书编号');
return false;
}
if (_chooseMode == CertifitcateTypeMode.principal ||
_chooseMode == CertifitcateTypeMode.safetyManager) {
if (!FormUtils.hasValue(pd, 'postName')) {
ToastUtil.showNormal(context, '请填写岗位名称');
return false;
}
}
if (!FormUtils.hasValue(pd, 'issuingAuthority')) {
ToastUtil.showNormal(context, '请填写发证机构');
return false;
}
if (_chooseMode == CertifitcateTypeMode.specialWorker) {
if (!FormUtils.hasValue(pd, 'industryCategoryName')) {
ToastUtil.showNormal(context, '请选择行业类型');
return false;
}
if (!FormUtils.hasValue(pd, 'industryOperatingItemsName')) {
ToastUtil.showNormal(context, '请选择操作项目');
return false;
}
}
if (_chooseMode == CertifitcateTypeMode.specialEquipment) {
if (!FormUtils.hasValue(pd, 'assignmentOperatingItemsName')) {
ToastUtil.showNormal(context, '请选择操作项目');
return false;
}
if (!FormUtils.hasValue(pd, 'assignmentCategoryName')) {
ToastUtil.showNormal(context, '请选择作业类型');
return false;
}
}
if (!FormUtils.hasValue(pd, 'dateIssue')) {
ToastUtil.showNormal(context, '请选择发证日期');
return false;
}
if (!FormUtils.hasValue(pd, 'certificateDateStart')) {
ToastUtil.showNormal(context, '请选择有效期开始时间');
return false;
}
if (!FormUtils.hasValue(pd, 'certificateDateEnd')) {
ToastUtil.showNormal(context, '请选择有效期结束时间');
return false;
}
if (!FormUtils.hasValue(pd, 'reviewDate')) {
ToastUtil.showNormal(context, '请选择复审时间');
return false;
}
return true;
}
@override
Widget build(BuildContext context) {
bool isShowIdImg = false;
bool isDetail =
widget.model == CertifitcateEditMode.edit ||
widget.model == CertifitcateEditMode.detail;
if (isDetail && _cerImgList.isNotEmpty) {
isShowIdImg = true;
} else {
if (widget.model == CertifitcateEditMode.add) {
isShowIdImg = true;
}
}
return Scaffold(
appBar: MyAppbar(title: widget.model == CertifitcateEditMode.edit ?'证书信息添加': '查看信息', isBack: true),
appBar: MyAppbar(
title: widget.model == CertifitcateEditMode.edit ? '证书信息添加' : '查看信息',
isBack: true,
),
body: SafeArea(
child: ItemListWidget.itemContainer(
horizontal: 5,
ListView(
children: [
RepairedPhotoSection(
title: '证书正面图片',
inlineSingle: true,
isRequired: true,
horizontalPadding: 12,
inlineImageWidth: 60,
onChanged: (files) {
/* files 长度 <= 1 */
},
onAiIdentify: () {
/* ... */
},
),
const Divider(),
RepairedPhotoSection(
title: '证书反面图片',
inlineSingle: true,
isRequired: true,
horizontalPadding: 12,
inlineImageWidth: 60,
onChanged: (files) {
/* files 长度 <= 1 */
},
onAiIdentify: () {
/* ... */
},
),
if (isShowIdImg) ...[
RepairedPhotoSection(
title: '证书照片',
isRequired: _isEdit,
maxCount: 2,
initialMediaPaths:
_cerImgList
.map((item) => ApiService.baseImgPath + item)
.toList(),
isEdit: _isEdit,
horizontalPadding: _isEdit ? 12 : 0,
inlineImageWidth: 60,
onChanged: (files) {
cerPhotos = files.map((file) => file.path).toList();
},
onMediaRemovedForIndex: (index) async {
final deleFile = _cerImgList[index];
final deleId = _idCartImgIds[index];
var fileEnum = _getFileType();
if (deleFile.contains(fileEnum.path)) {
_cerImgList.removeAt(index);
_idCartImgIds.removeAt(index);
_cerImgRemoveList.add(deleId);
}
},
onAiIdentify: () {},
),
if (_isEdit)
ItemListWidget.itemContainer(
const Text(
'温馨提示用户要上传证书正反面证书照片数量是2张才能保存',
style: TextStyle(color: Colors.red, fontSize: 10),
),
),
const Divider(),
],
const Divider(),
ItemListWidget.selectableLineTitleTextRightButton(
label: '证书作业类型:',
isEditable: true,
text: '请选择',
isRequired: true,
onTap: () {
/* ... */
isEditable: widget.model == CertifitcateEditMode.add,
text: pd['typeName'] ?? '请选择',
isRequired: widget.model == CertifitcateEditMode.add,
onTap: () async {
final found = await BottomPicker.show(
context,
items: _cerTypes,
itemBuilder:
(i) =>
Text(i['dictLabel']!, textAlign: TextAlign.center),
initialIndex: 0,
);
//FocusHelper.clearFocus(context);
if (found != null) {
_uploadChooseType(found);
}
},
),
const Divider(),
ItemListWidget.singleLineTitleText(
label: '证书名称:',
isRequired: true,
isRequired: _isEdit,
text: pd['certificateName'] ?? '',
hintText: '请输入证书名称',
isEditable: true,
isEditable: _isEdit,
onChanged: (value) {
pd['address'] = value;
pd['certificateName'] = value;
},
),
const Divider(),
ItemListWidget.singleLineTitleText(
label: '证书编号:',
isRequired: true,
isRequired: _isEdit,
text: pd['certificateCode'] ?? '',
hintText: '请输入证书编号',
isEditable: true,
isEditable: _isEdit,
onChanged: (value) {
pd['address'] = value;
pd['certificateCode'] = value;
},
),
const Divider(),
if (!(_chooseMode == CertifitcateTypeMode.specialEquipment ||
_chooseMode == CertifitcateTypeMode.specialWorker)) ...[
ItemListWidget.singleLineTitleText(
label: '岗位名称:',
isRequired: _isEdit,
text: pd['postName'] ?? '',
hintText: '请输入岗位名称',
isEditable: _isEdit,
onChanged: (value) {
pd['postName'] = value;
},
),
const Divider(),
],
ItemListWidget.singleLineTitleText(
label: '发证机构:',
isRequired: _isEdit,
text: pd['issuingAuthority'] ?? '',
hintText: '请输入发证机构',
isEditable: _isEdit,
onChanged: (value) {
pd['issuingAuthority'] = value;
},
),
const Divider(),
if (_chooseMode == CertifitcateTypeMode.specialWorker) ...[
ItemListWidget.selectableLineTitleTextRightButton(
label: '行业类型:',
isEditable: _isEdit,
text: pd['industryCategoryName'] ?? '请选择',
isRequired: _isEdit,
onTap: () async {
final found = await BottomPicker.show(
context,
items: _specialWorkList,
itemBuilder:
(i) => Text(
i['dictLabel']!,
textAlign: TextAlign.center,
),
initialIndex: 0,
);
//FocusHelper.clearFocus(context);
if (found != null) {
setState(() {
pd['industryCategoryName'] = found['dictLabel'];
pd['industryCategoryCode'] = found['dictValue'];
_chooseWorkTypeList = found['children'];
pd['industryOperatingItemsName'] = '';
pd['industryOperatingItemsCode'] = '';
});
}
},
),
const Divider(),
ItemListWidget.selectableLineTitleTextRightButton(
label: '操作项目:',
isEditable: _isEdit,
text: pd['industryOperatingItemsName'] ?? '请选择',
isRequired: _isEdit,
onTap: () async {
final found = await BottomPicker.show(
context,
items: _chooseWorkTypeList,
itemBuilder:
(i) => Text(
i['dictLabel']!,
textAlign: TextAlign.center,
),
initialIndex: 0,
);
//FocusHelper.clearFocus(context);
if (found != null) {
pd['industryOperatingItemsName'] = found['dictLabel'];
pd['industryOperatingItemsCode'] = found['dictValue'];
}
},
),
const Divider(),
],
if (_chooseMode == CertifitcateTypeMode.specialEquipment) ...[
ItemListWidget.selectableLineTitleTextRightButton(
label: '操作项目:',
isEditable: _isEdit,
text: pd['assignmentOperatingItemsName'] ?? '请选择',
isRequired: _isEdit,
onTap: () async {
final found = await BottomPicker.show(
context,
items: _equipmentList,
itemBuilder:
(i) => Text(
i['dictLabel']!,
textAlign: TextAlign.center,
),
initialIndex: 0,
);
//FocusHelper.clearFocus(context);
if (found != null) {
setState(() {
pd['assignmentOperatingItemsName'] = found['dictLabel'];
pd['assignmentOperatingItemsCode'] = found['dictValue'];
_chooseEquipmentTypeList = found['children'];
pd['assignmentCategoryName'] = '';
pd['assignmentCategoryCode'] = '';
});
}
},
),
const Divider(),
ItemListWidget.selectableLineTitleTextRightButton(
label: '行业类型:',
isEditable: _isEdit,
text: pd['assignmentCategoryName'] ?? '请选择',
isRequired: _isEdit,
onTap: () async {
final found = await BottomPicker.show(
context,
items: _chooseEquipmentTypeList,
itemBuilder:
(i) => Text(
i['dictLabel']!,
textAlign: TextAlign.center,
),
initialIndex: 0,
);
//FocusHelper.clearFocus(context);
if (found != null) {
pd['assignmentCategoryName'] = found['dictLabel'];
pd['assignmentCategoryCode'] = found['dictValue'];
}
},
),
const Divider(),
],
ItemListWidget.selectableLineTitleTextRightButton(
label: '发证日期:',
isEditable: _isEdit,
text: pd['dateIssue'] ?? '请选择',
isRequired: _isEdit,
onTap: () async {
DateTime? picked = await BottomDateTimePicker.showDate(
mode: BottomPickerMode.date,
context,
);
if (picked != null) {
setState(() {
pd['dateIssue'] = DateFormat('yyyy-MM-dd').format(picked);
});
//FocusHelper.clearFocus(context);
}
},
),
const Divider(),
ItemListWidget.selectableLineTitleTextRightButton(
label: '有效期开始时间:',
isEditable: true,
text: '请选择',
isRequired: true,
onTap: () {
/* ... */
isEditable: _isEdit,
text: pd['certificateDateStart'] ?? '请选择',
isRequired: _isEdit,
onTap: () async {
DateTime? picked = await BottomDateTimePicker.showDate(
mode: BottomPickerMode.date,
context,
);
if (picked != null) {
setState(() {
pd['certificateDateStart'] = DateFormat(
'yyyy-MM-dd',
).format(picked);
});
//FocusHelper.clearFocus(context);
}
},
),
const Divider(),
ItemListWidget.selectableLineTitleTextRightButton(
label: '有效期结束时间:',
isEditable: true,
text: '请选择',
isRequired: true,
onTap: () {
/* ... */
isEditable: _isEdit,
text: pd['certificateDateEnd'] ?? '请选择',
isRequired: _isEdit,
onTap: () async {
DateTime? picked = await BottomDateTimePicker.showDate(
mode: BottomPickerMode.date,
context,
);
if (picked != null) {
setState(() {
pd['certificateDateEnd'] = DateFormat(
'yyyy-MM-dd',
).format(picked);
});
//FocusHelper.clearFocus(context);
}
},
),
const Divider(),
ItemListWidget.selectableLineTitleTextRightButton(
label: '复审时间:',
isEditable: true,
text: '请选择',
isRequired: true,
onTap: () {
/* ... */
},
),
const Divider(),
const SizedBox(height: 20),
CustomButton(text: '保存', backgroundColor: Colors.blue, onPressed: () {
if (_chooseMode == CertifitcateTypeMode.specialWorker ||
_chooseMode == CertifitcateTypeMode.specialEquipment) ...[
ItemListWidget.selectableLineTitleTextRightButton(
label: '复审时间:',
isEditable: _isEdit,
text: pd['reviewDate'] ?? '请选择',
isRequired: _isEdit,
onTap: () async {
DateTime? picked = await BottomDateTimePicker.showDate(
mode: BottomPickerMode.date,
context,
);
if (picked != null) {
setState(() {
pd['reviewDate'] = DateFormat(
'yyyy-MM-dd',
).format(picked);
});
//FocusHelper.clearFocus(context);
}
},
),
const Divider(),
],
},)
const SizedBox(height: 20),
if (_isEdit)
CustomButton(
text: '保存',
backgroundColor: Colors.blue,
onPressed: () {
_submit();
},
),
],
),
),

View File

@ -1,23 +1,23 @@
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:qhd_prevention/customWidget/custom_alert_dialog.dart';
import 'package:qhd_prevention/customWidget/item_list_widget.dart';
import 'package:qhd_prevention/customWidget/toast_util.dart';
import 'package:qhd_prevention/http/ApiService.dart';
import 'package:qhd_prevention/http/modules/safety_check_api.dart';
import 'package:qhd_prevention/pages/home/certificate/certificate_detail_page.dart';
import 'package:qhd_prevention/pages/my_appbar.dart';
import 'package:qhd_prevention/services/SessionService.dart';
import 'package:qhd_prevention/tools/tools.dart';
import 'package:qhd_prevention/customWidget/bottom_picker.dart';
import 'package:qhd_prevention/customWidget/custom_button.dart';
import 'package:qhd_prevention/customWidget/search_bar_widget.dart';
///
enum CertifitcateEditMode { delete, detail, edit }
enum CertifitcateEditMode { add, detail, edit }
class CertificateListPage extends StatefulWidget {
final String flow;
const CertificateListPage({Key? key, required this.flow}) : super(key: key);
const CertificateListPage({Key? key}) : super(key: key);
@override
_CertificateListPageState createState() => _CertificateListPageState();
@ -60,33 +60,27 @@ class _CertificateListPageState extends State<CertificateListPage> {
}
Future<void> _fetchData() async {
if (isLoading) return;
setState(() {
isLoading = false;
list = [
{'name': 1},
];
});
try {
// final data = {
// 'status': _computeStatusParam(),
// 'pageSize': rows,
// 'pageIndex': currentPage,
// 'keywords': _searchController.text.trim(),
// };
// final response = await SafetyCheckApi.safeCheckList(data);
//
// setState(() {
// final newData = response['data'] as List<dynamic>? ?? [];
// if (currentPage == 1) {
// list = newData;
// } else {
// list.addAll(newData);
// }
// totalPage = response['totalPage'] ?? 1;
// isLoading = false;
// });
final data = {
'eqCorpinfoId': SessionService.instance.tenantId,
'eqUserId': SessionService.instance.accountId,
'pageSize': rows,
'pageIndex': currentPage,
'isAppQuery': 1,
// 'keywords': _searchController.text.trim(),
};
final response = await CertificateApi.getCertificateList(data);
setState(() {
final newData = response['data'] as List<dynamic>? ?? [];
if (currentPage == 1) {
list = newData;
} else {
list.addAll(newData);
}
totalPage = response['totalPage'] ?? 1;
isLoading = false;
});
} catch (e) {
print('Error fetching data: $e');
setState(() => isLoading = false);
@ -100,40 +94,44 @@ class _CertificateListPageState extends State<CertificateListPage> {
_fetchData();
}
///
Future<void> _openFlowDrawer(String id) async {
try {
final response = await SafetyCheckApi.safeCheckFlow(id);
final List<dynamic>? newFlow = response['data']?['flowCOList'];
printLongString(jsonEncode(response['data']));
if (newFlow == null || newFlow.isEmpty) {
ToastUtil.showNormal(context, '暂无流程图数据');
return;
}
setState(() {
flowData = response['data'] ?? {};
});
Future.microtask(() {
_scaffoldKey.currentState?.openEndDrawer();
});
} catch (e) {
print('Error fetching flow data: $e');
ToastUtil.showNormal(context, '获取流程图失败: $e');
}
}
///
Future<void> _goToDetail(
Map<String, dynamic> item,
CertifitcateEditMode type,
) async {
await pushPage(CertificateDetailPage(model: CertifitcateEditMode.detail), context);
await pushPage(
CertificateDetailPage(model: type, id: item['id'] ?? ''),
context,
);
//
currentPage = 1;
_fetchData();
}
///
Future<void> _deleteCertificate(Map<String, dynamic> item) async {
await CustomAlertDialog.showAlert(
context,
title: '温馨提示',
content: '确定要删除此证书吗?',
onConfirm: () async {
try {
final response = await CertificateApi.deleteCertificate(item['id']);
if (response['success'] == true) {
ToastUtil.showNormal(context, '删除成功');
currentPage = 1;
_fetchData();
} else {
ToastUtil.showNormal(context, response['errMessage'] ?? '删除失败');
}
} catch (e) {
print('Error fetching data: $e');
ToastUtil.showNormal(context, '删除失败');
}
},
);
}
Widget _buildListItem(Map<String, dynamic> item) {
return Card(
color: Colors.white,
@ -146,24 +144,28 @@ class _CertificateListPageState extends State<CertificateListPage> {
children: [
Row(
children: [
Image.asset('assets/images/g_logo.png', width: 80, height: 80),
const SizedBox(width: 16),
const SizedBox(width: 5),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"单位名称:${item['name'] ?? ''}",
style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
"证书名称:${item['certificateName'] ?? ''}",
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
Text("证书编号: ${item['inspectionOriginatorUserName'] ?? ''}"),
Text("复审时间: ${item['type'] ?? ''}"),
Text(
"证书编号: ${item['certificateCode'] ?? ''}",
),
Text("证书有效期: ${item['certificateDateStart'] ?? ''} -- ${item['certificateDateEnd']}"),
const SizedBox(height: 8),
// 10
],
),
],
),
const SizedBox(height: 20,),
const SizedBox(height: 10),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
@ -171,11 +173,7 @@ class _CertificateListPageState extends State<CertificateListPage> {
text: '删除',
padding: EdgeInsets.symmetric(horizontal: 20),
height: 35,
onPressed:
() => _goToDetail(
item,
CertifitcateEditMode.delete,
),
onPressed: () => _deleteCertificate(item),
backgroundColor: Colors.red,
),
Row(
@ -185,28 +183,22 @@ class _CertificateListPageState extends State<CertificateListPage> {
text: '编辑',
height: 35,
onPressed:
() => _goToDetail(
item,
CertifitcateEditMode.edit,
),
() => _goToDetail(item, CertifitcateEditMode.edit),
),
CustomButton(
text: '查看',
padding: EdgeInsets.symmetric(horizontal: 20),
height: 35,
onPressed:
() => _goToDetail(
item,
CertifitcateEditMode.detail,
),
() =>
_goToDetail(item, CertifitcateEditMode.detail),
),
],
),
],
),
],
)
),
),
),
);
@ -239,7 +231,24 @@ class _CertificateListPageState extends State<CertificateListPage> {
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldKey,
appBar: MyAppbar(title: '${widget.flow}'),
appBar: MyAppbar(
title: '证书信息',
actions: [
TextButton(
onPressed: () async {
await pushPage(
CertificateDetailPage(model: CertifitcateEditMode.add, id: ''),
context,
);
_fetchData();
},
child: Text(
'添加',
style: TextStyle(color: Colors.white, fontSize: 16),
),
),
],
),
body: SafeArea(
child: Column(children: [Expanded(child: _buildListContent())]),
),

View File

@ -95,24 +95,6 @@ class _UnitJoinDetailPageState extends State<UnitJoinDetailPage> {
});
}
Future<void> _saveSuccess() async {
pd['userIdCard'] = base64.encode(utf8.encode(pd['userIdCard']));
await BasicInfoApi.updateUserInfo(pd).then((res) {
LoadingDialogHelper.hide();
if (res['success']) {
ToastUtil.showNormal(context, '保存成功');
Navigator.pushReplacement(
context,
MaterialPageRoute(builder: (_) => const MainPage(isChooseFirm: false)),
);
} else {
ToastUtil.showNormal(context, '保存失败');
}
});
}
@override
Widget build(BuildContext context) {
bool isShow = _isEdit;

View File

@ -183,7 +183,7 @@ class _UnitJoinListPageState extends State<UnitJoinListPage> {
},
),
);
if (item['employmentFlag'] == 1) {
if (item['employmentFlag'] == 1 && item['status'] != 1) {
buttons.add(
CustomButton(
text: '离职',

View File

@ -50,7 +50,10 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver {
WidgetsBinding.instance.addObserver(this);
// Tab
_tabVisibility = [true, true, true];
_pages = <Widget>[HomePage(key: _homeKey, isChooseFirm: widget.isChooseFirm,), MinePage(key: _mineKey)];
_pages = <Widget>[
HomePage(key: _homeKey, isChooseFirm: widget.isChooseFirm),
MinePage(key: _mineKey, isChooseFirm: widget.isChooseFirm),
];
//
// HeartbeatService().start();
}

View File

@ -204,7 +204,7 @@ class _ForgotPwdPageState extends State<ForgotPwdPage> {
(Route<dynamic> route) => false,
);
} else {
ToastUtil.showNormal(context, res?['message'] ?? '重置密码失败');
ToastUtil.showNormal(context, res?['errMessage'] ?? '重置密码失败');
}
} catch (e) {
LoadingDialogHelper.hide();

View File

@ -36,13 +36,22 @@ class _MineChangeFirmPageState extends State<MineChangeFirmPage> {
void _getList() async {
LoadingDialogHelper.show();
var res = await BasicInfoApi.getJoinFirmList();
LoadingDialogHelper.dismiss();
if (res['success'] == true) {
setState(() {
list = res['data'];
});
try {
var res = await BasicInfoApi.getJoinFirmList();
LoadingDialogHelper.dismiss();
if (res['success'] == true) {
setState(() {
list = res['data'];
});
}else{
ToastUtil.showNormal(context, res['errMessage'] ?? '');
}
} catch (e) {
LoadingDialogHelper.dismiss();
ToastUtil.showNormal(context, '暂无数据');
}
}
//
@ -56,7 +65,7 @@ class _MineChangeFirmPageState extends State<MineChangeFirmPage> {
final prefs = await SharedPreferences.getInstance();
final phone = prefs.getString('savePhone') ?? '';
final pwd = prefs.getString('savePass') ?? '';
var params = {'unitId': data['id']};
var params = {'unitId': data['corpinfoId']};
try {
var res = await AuthService.gbsLogin(phone, pwd, params);
LoadingDialogHelper.dismiss();
@ -130,9 +139,9 @@ class _MineChangeFirmPageState extends State<MineChangeFirmPage> {
mainAxisAlignment:
MainAxisAlignment.center,
children: [
Text('${data['corpName'] ?? 'aaaa'}'),
Text('${data['corpName'] ?? ''}'),
if (joinedUnitId ==
data['id']) ...[
data['corpinfoId']) ...[
const Icon(
Icons.check,
size: 20,

View File

@ -5,6 +5,7 @@ import 'package:qhd_prevention/customWidget/custom_alert_dialog.dart';
import 'package:qhd_prevention/customWidget/custom_button.dart';
import 'package:qhd_prevention/customWidget/toast_util.dart';
import 'package:qhd_prevention/http/ApiService.dart';
import 'package:qhd_prevention/pages/home/certificate/certificate_list_page.dart';
import 'package:qhd_prevention/pages/home/scan_page.dart';
import 'package:qhd_prevention/pages/home/userinfo_page.dart';
import 'package:qhd_prevention/pages/mine/face_ecognition_page.dart';
@ -19,8 +20,8 @@ import 'package:qhd_prevention/tools/tools.dart';
import 'package:shared_preferences/shared_preferences.dart';
class MinePage extends StatefulWidget {
const MinePage({super.key});
const MinePage({super.key, required this.isChooseFirm});
final bool isChooseFirm;
@override
State<MinePage> createState() => MinePageState();
}
@ -172,12 +173,15 @@ class MinePageState extends State<MinePage> {
content: '您目前还有入职信息无法直接注销。\n请先在“就职单位”页面中离职。',
);
} else {
CustomAlertDialog.showConfirm(
final result = await CustomAlertDialog.showConfirm(
context,
title: '温馨提示',
content: '注销后您的所有信息将会被删除\n请确认是否注销。 ',
onConfirm: () async {
CustomAlertDialog.showInputWithCode(
onConfirm: () {
},
);
if (result) {
CustomAlertDialog.showInputWithCode(
context,
title: '手机号:${SessionService.instance.phone}',
onGetCode: () async {
@ -189,29 +193,10 @@ class MinePageState extends State<MinePage> {
return true;
},
onConfirm: (code) async {
LoadingDialogHelper.show();
Map data = {
'id' : SessionService.instance.accountId,
'phoneCode' : code,
};
await BasicInfoApi.logout(data).then((res) async {
LoadingDialogHelper.dismiss();
if (res['success'] == true) {
ToastUtil.showNormal(context, '账号已注销');
await SessionService.instance.clear(clearPrefs: true);
Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (_) => const LoginPage()),
);
} else {
ToastUtil.showNormal(context, res['errMessage'] ?? '');
}
});
_quit(code);
}
);
},
);
);
}
}
} else {
LoadingDialogHelper.dismiss();
@ -219,6 +204,29 @@ class MinePageState extends State<MinePage> {
}
}
//
Future<void> _quit(String code) async {
LoadingDialogHelper.show();
Map data = {
'id' : SessionService.instance.accountId,
'phoneCode' : code,
};
await BasicInfoApi.logout(data).then((res) async {
LoadingDialogHelper.dismiss();
if (res['success'] == true) {
ToastUtil.showNormal(context, '账号已注销');
await SessionService.instance.clear(clearPrefs: true);
Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (_) => const LoginPage()),
);
} else {
ToastUtil.showNormal(context, res['errMessage'] ?? '');
}
});
}
Widget _buildSloganSection() {
return Container(
margin: EdgeInsets.fromLTRB(0, 100, 0, 0),
@ -323,7 +331,12 @@ class MinePageState extends State<MinePage> {
title: "证书信息",
icon: "assets/images/ico12.png",
value: passwordChanged,
onChanged: (value) => setState(() => passwordChanged = value!),
onChanged: (value) {
pushPage(
const CertificateListPage(),
context,
);
},
),
_buildSettingItem(
@ -349,6 +362,7 @@ class MinePageState extends State<MinePage> {
setState(() => logoutSelected = value!);
},
),
if (widget.isChooseFirm)
_buildSettingItem(
title: "切换账户",
icon: "assets/images/ico15.png",

View File

@ -177,14 +177,12 @@ class _MineSetPwdPageState extends State<MineSetPwdPage> {
MaterialPageRoute(builder: (context) => const LoginPage()),
(Route<dynamic> route) => false,
);
} else if (raw['success'] == false) {
ToastUtil.showNormal(context, '当前密码密码有误');
} else {
ToastUtil.showNormal(context, '登录错误!请联系管理员');
ToastUtil.showNormal(context, raw['errMessage'] ?? '请求失败,请重试');
}
} catch (e) {
print('修改密码出错:$e');
ToastUtil.showNormal(context, '登录错误!请联系管理员');
ToastUtil.showNormal(context, '请求失败,请重试');
}
}

View File

@ -89,7 +89,8 @@ class _OnboardingFullPageState extends State<OnboardingFullPage> {
///
Future<void> _relogin() async {
bool isChooseFirm = (SessionService.instance.token ?? '').isNotEmpty;
String token = SessionService.instance.token ?? '';
bool isChooseFirm = token.isNotEmpty;
Navigator.pushReplacement(
context,
MaterialPageRoute(builder: (_) => MainPage(isChooseFirm: isChooseFirm)),
@ -110,6 +111,7 @@ class _OnboardingFullPageState extends State<OnboardingFullPage> {
isEditable: false,
text: widget.scanData['corpName'] ?? '',
),
const Divider(),
ItemListWidget.selectableLineTitleTextRightButton(
verticalInset: 15,
label: '选择入职部门:',
@ -144,7 +146,7 @@ class _OnboardingFullPageState extends State<OnboardingFullPage> {
ItemListWidget.singleLineTitleText(
label: '岗位(工种):',
isRequired: true,
hintText: '请输入姓名',
hintText: '请输入岗位名称',
text: "",
isEditable: true,
onChanged: (value) {

View File

@ -53,7 +53,7 @@ class _ChooseUserfirmPageState extends State<ChooseUserfirmPage> {
return;
}
final params = {
'unitId': widget.firms[_selectedIndex]['id'],
'unitId': widget.firms[_selectedIndex]['corpinfoId'],
};
LoadingDialogHelper.show();
final result = await AuthService.gbsLogin(widget.userName, widget.password, params);
@ -97,7 +97,7 @@ class _ChooseUserfirmPageState extends State<ChooseUserfirmPage> {
children: [
const SizedBox(height: 70), //
Image.asset(
"assets/images/logo.png",
"assets/images/g_logo.png",
width: 40,
height: 40,
),

View File

@ -40,7 +40,7 @@ class _FirmListPageState extends State<FirmListPage> {
Future<void> _getFirmList() async {
try {
LoadingDialogHelper.show();
final result = await BasicInfoApi.getFirmList({'enterpriseType': 3});
final result = await BasicInfoApi.getFirmList({'enterpriseType': 3, 'pageSize':99999, });
LoadingDialogHelper.hide();
if (result['success'] == true && result['data'] is List) {
setState(() {
@ -277,7 +277,7 @@ class _FirmListPageState extends State<FirmListPage> {
// 使
final mq = MediaQuery.of(context);
final fixedIndexHeight =
mq.size.height - kToolbarHeight - mq.padding.top - 24 - 100;
mq.size.height - kToolbarHeight - mq.padding.top - 24 - 30;
return Scaffold(
backgroundColor: Colors.white,
@ -461,7 +461,8 @@ class _FirmListPageState extends State<FirmListPage> {
horizontal: 4,
),
alignment: Alignment.center,
child: Text(
child:
Text(
l,
style: TextStyle(
fontSize: 11,

View File

@ -49,11 +49,12 @@ class _FullUserinfoPageState extends State<FullUserinfoPage> {
"name": "请输入姓名",
"userIdCard": "请输入身份证号码",
"nationName": "请选择民族",
"maritalStatus": "请选择婚姻状况",
"locationAddress": "请输入户口所在地",
"currentAddress": "请输入现居住地址",
"culturalLevel": "请选择文化程度",
"politicalAffiliation": "请选择政治面貌",
"currentAddress": "请输入现居住地址",
"locationAddress": "请输入户口所在地",
"maritalStatus": "请选择婚姻状况",
};
late bool _isEdit;
@ -176,18 +177,23 @@ class _FullUserinfoPageState extends State<FullUserinfoPage> {
final deleteResult = await _checkDeleteImage();
if (signResult && situationResult && deleteResult) {
pd['userIdCard'] = base64.encode(utf8.encode(pd['userIdCard']));
await BasicInfoApi.updateUserInfo(pd).then((res) {
final userIdCard = base64.encode(utf8.encode(pd['userIdCard']));
await BasicInfoApi.updateUserInfo(pd, userIdCard).then((res) {
LoadingDialogHelper.hide();
if (res['success']) {
ToastUtil.showNormal(context, '保存成功');
bool ischange = _isChange ? true: false;
Navigator.pushReplacement(
context,
MaterialPageRoute(builder: (_) => FirmListPage(isBack: false,)),
);
if (widget.isChooseFirm || _isChange) {
Navigator.pop(context);
}else{
Navigator.pushReplacement(
context,
MaterialPageRoute(builder: (_) => FirmListPage(isBack: false,)),
);
}
} else {
ToastUtil.showNormal(context, res['errMessage']);
ToastUtil.showNormal(context, res['errMessage'] ?? '保存失败');
}
});
}else{
@ -199,13 +205,17 @@ class _FullUserinfoPageState extends State<FullUserinfoPage> {
late bool isSuccess = true;
if (_idCardImgRemoveList.isNotEmpty) {
final delIds = _idCardImgRemoveList;
await FileApi.deleteImages(delIds).then((result) {
if (result['success']) {
isSuccess = true;
} else {
isSuccess = false;
}
});
try{
await FileApi.deleteImages(delIds).then((result) {
if (result['success']) {
isSuccess = true;
} else {
isSuccess = false;
}
});
}catch(e){
LoadingDialogHelper.hide();
}
}else{
isSuccess = true;
}
@ -335,6 +345,7 @@ class _FullUserinfoPageState extends State<FullUserinfoPage> {
if (!_isEdit && FormUtils.hasValue(pd, 'id')) {
isShow = true;
}
String token = SessionService.instance.token ?? '';
return Scaffold(
appBar: MyAppbar(
title: '信息补充',
@ -467,7 +478,7 @@ class _FullUserinfoPageState extends State<FullUserinfoPage> {
if (found != null) {
setState(() {
pd['nationName'] = found['name'];
pd['nation'] = found['code'];
pd['nation'] = found['bianma'];
});
}
},
@ -677,10 +688,11 @@ class _FullUserinfoPageState extends State<FullUserinfoPage> {
noLabel: "",
text: pd['flowFlag'] == 1 ? '' : '',
isRequired: true,
isEdit: _isEdit,
isEdit: _isEdit ? (token.isEmpty ? true : false) : false,
groupValue: (pd['flowFlag'] ?? 0) == 1,
onChanged: (val) {
setState(() {
pd['flowFlag'] = val ? 1 : 0;
});
},

View File

@ -102,7 +102,7 @@ class _LoginPageState extends State<LoginPage> {
@override
Widget build(BuildContext context) {
final screenHeight = MediaQuery.of(context).size.height;
double height = 230.0;
double height = MediaQuery.of(context).size.width * 636/1125;
return Scaffold(
backgroundColor: Colors.white,
resizeToAvoidBottomInset: true,
@ -114,7 +114,7 @@ class _LoginPageState extends State<LoginPage> {
top: 0,
right: 0,
child: Image.asset(
'assets/images/loginbg.png',
'assets/images/login_top_bg.png',
fit: BoxFit.fitWidth,
),
),
@ -156,284 +156,293 @@ class _LoginPageState extends State<LoginPage> {
bottom: 0,
left: 0,
right: 0,
top: height,
top: height-20,
child: GestureDetector(
onTap: () => FocusScope.of(context).unfocus(),
child: SafeArea(
child: Form(
key: _formKey,
child: SingleChildScrollView(
//
child: ConstrainedBox(
constraints: BoxConstraints(minHeight: screenHeight-height-50),
child: IntrinsicHeight(
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
//
Container(
// color: Colors.white,
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 20,
child: Form(
key: _formKey,
child: SingleChildScrollView(
//
child: ConstrainedBox(
constraints: BoxConstraints(minHeight: screenHeight-height),
child: IntrinsicHeight(
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 16),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: const BorderRadius.only(
topLeft: Radius.circular(20),
topRight: Radius.circular(20),
),
// boxShadow: [
// BoxShadow(
// color: Colors.grey.withOpacity(0.5),
// spreadRadius: 5,
// blurRadius: 7,
// )
// ]
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
//
Padding(
padding: const EdgeInsets.symmetric(
horizontal: 20,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
const SizedBox(height: 40),
CustomInput.buildInput(
_phoneController,
title: "手机号",
hint: "请输入您的手机号",
keyboardType: TextInputType.phone,
suffix:
_phoneController.text.isEmpty
? SizedBox()
: IconButton(
icon: const Icon(
Icons.cancel,
size: 20,
color: Colors.grey,
),
onPressed:
() => setState(
() =>
_phoneController
.clear(),
),
),
validator: (v) {
if (v == null || v.isEmpty)
return '请输入您的手机号';
return null;
},
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
const SizedBox(height: 20),
CustomInput.buildInput(
title: "密码",
_passwordController,
hint: "请输入您的密码",
obscure: _obscurePassword,
suffix: IconButton(
icon: Icon(
_obscurePassword
? Icons.visibility_off
: Icons.visibility,
color: Colors.grey,
),
onPressed:
() => setState(
() =>
_obscurePassword =
!_obscurePassword,
),
),
validator: (v) {
if (v == null || v.isEmpty)
return '请输入密码';
return null;
},
),
const SizedBox(height: 20),
Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
// const SizedBox(height: 60),
CustomInput.buildInput(
_phoneController,
title: "手机号",
hint: "请输入您的手机号",
keyboardType: TextInputType.phone,
suffix:
_phoneController.text.isEmpty
? SizedBox()
: IconButton(
icon: const Icon(
Icons.cancel,
size: 20,
color: Colors.grey,
),
onPressed:
() => setState(
() =>
_phoneController
.clear(),
),
),
validator: (v) {
if (v == null || v.isEmpty)
return '请输入您的手机号';
return null;
},
),
const SizedBox(height: 20),
CustomInput.buildInput(
title: "密码",
_passwordController,
hint: "请输入您的密码",
obscure: _obscurePassword,
suffix: IconButton(
icon: Icon(
_obscurePassword
? Icons.visibility_off
: Icons.visibility,
color: Colors.grey,
),
onPressed:
() => setState(
() =>
_obscurePassword =
!_obscurePassword,
),
),
validator: (v) {
if (v == null || v.isEmpty)
return '请输入密码';
return null;
},
),
const SizedBox(height: 20),
Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Text(
'验证码',
style: TextStyle(
fontSize: 17,
fontWeight: FontWeight.bold,
),
),
const SizedBox(),
],
),
//
SizedBox(
height: 60,
child: Row(
children: [
Expanded(
child: Padding(
padding: const EdgeInsets.only(
left: 0,
right: 10,
),
child: TextFormField(
controller: _codeController,
focusNode: _codeFocusNode,
keyboardType:
TextInputType.number,
decoration: const InputDecoration(
hintText: '请输入验证码',
hintStyle: TextStyle(
color: Colors.black26,
),
border: InputBorder.none,
contentPadding: EdgeInsets.zero,
),
style: const TextStyle(
color: Colors.black,
),
),
),
),
Padding(
padding: const EdgeInsets.symmetric(
horizontal: 10,
),
child: _buildCaptchaImage(),
),
],
Text(
'验证码',
style: TextStyle(
fontSize: 17,
fontWeight: FontWeight.bold,
),
),
const Divider(),
const SizedBox(height: 10),
if (_errorMessage.isNotEmpty)
Padding(
padding: const EdgeInsets.symmetric(
horizontal: 25,
),
child: Text(
_errorMessage,
style: const TextStyle(
color: Colors.red,
),
),
),
_remenbemberPWDAndRegister(),
const SizedBox(height: 10),
CustomButton(
text: '登录',
backgroundColor: const Color(0xFF2A75F8),
height: 50,
textStyle: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.w500,
),
borderRadius: 25,
onPressed: _handleLogin,
),
const SizedBox(height: 10),
CustomButton(
text: '注册',
height: 50,
textColor: Colors.black87,
textStyle: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.w500,
),
backgroundColor: Color(0xFFF3F4F8),
borderRadius: 25,
onPressed: () {
pushPage(RegisterPage(), context);
},
),
const SizedBox(height: 20),
const SizedBox(),
],
),
),
),
//
Padding(
padding: const EdgeInsets.symmetric(
horizontal: 10,
vertical: 10,
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Checkbox(
value: _agreed,
activeColor: Colors.blue,
checkColor: Colors.white,
side: const BorderSide(color: Colors.grey),
onChanged: (value) {
setState(() {
_agreed = value ?? false;
});
},
//
SizedBox(
height: 60,
child: Row(
children: [
Expanded(
child: Padding(
padding: const EdgeInsets.only(
left: 0,
right: 10,
),
child: TextFormField(
controller: _codeController,
focusNode: _codeFocusNode,
keyboardType:
TextInputType.number,
decoration: const InputDecoration(
hintText: '请输入验证码',
hintStyle: TextStyle(
color: Colors.black26,
),
border: InputBorder.none,
contentPadding: EdgeInsets.zero,
),
style: const TextStyle(
color: Colors.black,
),
),
),
),
Padding(
padding: const EdgeInsets.symmetric(
horizontal: 10,
),
child: _buildCaptchaImage(),
),
],
),
Flexible(
child: RichText(
text: TextSpan(
children: [
const TextSpan(
text: '我已阅读并同意',
style: TextStyle(
color: Colors.black,
fontSize: 12,
),
),
TextSpan(
text: '《服务协议》',
style: const TextStyle(
color: Colors.blue,
fontSize: 12,
),
// recognizer recognizer
recognizer:
TapGestureRecognizer()
..onTap = () {
pushPage(
const WebViewPage(
name: "用户服务协议",
url:
'http://47.92.102.56:7811/file/xieyi/zsyhxy.htm',
),
context,
);
},
),
const TextSpan(
text: '',
style: TextStyle(
color: Colors.black,
fontSize: 12,
),
),
TextSpan(
text: '《隐私政策》',
style: const TextStyle(
color: Colors.blue,
fontSize: 12,
),
recognizer:
TapGestureRecognizer()
..onTap = () {
pushPage(
const WebViewPage(
name: "隐私政策",
url:
'http://47.92.102.56:7811/file/xieyi/zsysq.htm',
),
context,
);
},
),
],
),
const Divider(),
const SizedBox(height: 10),
if (_errorMessage.isNotEmpty)
Padding(
padding: const EdgeInsets.symmetric(
horizontal: 25,
),
child: Text(
_errorMessage,
style: const TextStyle(
color: Colors.red,
),
),
),
],
),
_remenbemberPWDAndRegister(),
const SizedBox(height: 10),
CustomButton(
text: '登录',
backgroundColor: const Color(0xFF2A75F8),
height: 50,
textStyle: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.w500,
),
borderRadius: 25,
onPressed: _handleLogin,
),
const SizedBox(height: 10),
CustomButton(
text: '注册',
height: 50,
textColor: Colors.black87,
textStyle: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.w500,
),
backgroundColor: Color(0xFFF3F4F8),
borderRadius: 25,
onPressed: () {
pushPage(RegisterPage(), context);
},
),
const SizedBox(height: 20),
],
),
const SizedBox(height: 10),
],
),
),
//
Padding(
padding: const EdgeInsets.symmetric(
horizontal: 10,
vertical: 10,
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Checkbox(
value: _agreed,
activeColor: Colors.blue,
checkColor: Colors.white,
side: const BorderSide(color: Colors.grey),
onChanged: (value) {
setState(() {
_agreed = value ?? false;
});
},
),
Flexible(
child: RichText(
text: TextSpan(
children: [
const TextSpan(
text: '我已阅读并同意',
style: TextStyle(
color: Colors.black,
fontSize: 12,
),
),
TextSpan(
text: '《服务协议》',
style: const TextStyle(
color: Colors.blue,
fontSize: 12,
),
// recognizer recognizer
recognizer:
TapGestureRecognizer()
..onTap = () {
pushPage(
const WebViewPage(
name: "用户服务协议",
url:
'http://47.92.102.56:7811/file/xieyi/zsyhxy.htm',
),
context,
);
},
),
const TextSpan(
text: '',
style: TextStyle(
color: Colors.black,
fontSize: 12,
),
),
TextSpan(
text: '《隐私政策》',
style: const TextStyle(
color: Colors.blue,
fontSize: 12,
),
recognizer:
TapGestureRecognizer()
..onTap = () {
pushPage(
const WebViewPage(
name: "隐私政策",
url:
'http://47.92.102.56:7811/file/xieyi/zsysq.htm',
),
context,
);
},
),
],
),
),
),
],
),
),
const SizedBox(height: 10),
],
),
),
),
@ -586,11 +595,13 @@ class _LoginPageState extends State<LoginPage> {
} else {
if (FormUtils.hasValue(data, 'isInfoComplete') &&
data['isInfoComplete'] == false) { //
await CustomAlertDialog.showAlert(context, title: '温馨提示', content: '首次登录,请完善个人信息完成注册');
Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (_) => const FullUserinfoPage(isEidt: true, isChooseFirm: false,)),
);
} else if (FormUtils.hasValue(data, 'isChooseFirm') &&
data['isChooseFirm'] == false) { //
{ //

View File

@ -8,6 +8,7 @@ import 'package:qhd_prevention/pages/my_appbar.dart';
import 'package:qhd_prevention/pages/user/CustomInput.dart';
import 'package:qhd_prevention/pages/user/login_page.dart';
import 'package:qhd_prevention/tools/tools.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../../http/ApiService.dart'; // API
class RegisterPage extends StatefulWidget {
@ -107,7 +108,7 @@ class _RegisterPageState extends State<RegisterPage> {
ToastUtil.showNormal(context, '验证码已发送');
_startCountdown(60);
} else {
ToastUtil.showNormal(context, resp?['message'] ?? '发送验证码失败');
ToastUtil.showNormal(context, resp?['errMessage'] ?? '发送验证码失败');
}
} catch (e) {
LoadingDialogHelper.hide();
@ -173,6 +174,9 @@ class _RegisterPageState extends State<RegisterPage> {
if (resp != null && resp['success'] == true) {
ToastUtil.showNormal(context, '注册成功,请登录');
final prefs = await SharedPreferences.getInstance();
await prefs.setString("savePhone", phone);
await prefs.setString("savePass", '');
//
Navigator.pushAndRemoveUntil(
context,
@ -180,7 +184,7 @@ class _RegisterPageState extends State<RegisterPage> {
(route) => false,
);
} else {
ToastUtil.showNormal(context, resp?['message'] ?? '注册失败,请重试');
ToastUtil.showNormal(context, resp?['errMessage'] ?? '注册失败,请重试');
}
} catch (e) {
LoadingDialogHelper.hide();
@ -208,11 +212,7 @@ class _RegisterPageState extends State<RegisterPage> {
title: '手机号',
hint: '请输入手机号',
keyboardType: TextInputType.phone,
validator: (v) {
if (v == null || v.isEmpty) return '请输入手机号';
if (!_isPhoneValid(v.trim())) return '请输入有效的手机号';
return null;
},
),
const SizedBox(height: 16),
@ -227,10 +227,6 @@ class _RegisterPageState extends State<RegisterPage> {
title: '验证码',
hint: '请输入验证码',
keyboardType: TextInputType.number,
validator: (v) {
if (v == null || v.isEmpty) return '请输入验证码';
return null;
},
),
),
const SizedBox(width: 12),
@ -270,11 +266,6 @@ class _RegisterPageState extends State<RegisterPage> {
icon: Icon(_obscurePwd ? Icons.visibility_off : Icons.visibility, color: Colors.grey),
onPressed: () => setState(() => _obscurePwd = !_obscurePwd),
),
validator: (v) {
if (v == null || v.isEmpty) return '请输入密码';
if (v.length < 8) return '密码长度至少 8 位';
return null;
},
),
const SizedBox(height: 16),
@ -289,10 +280,7 @@ class _RegisterPageState extends State<RegisterPage> {
icon: Icon(_obscureConfirm ? Icons.visibility_off : Icons.visibility, color: Colors.grey),
onPressed: () => setState(() => _obscureConfirm = !_obscureConfirm),
),
validator: (v) {
if (v == null || v.isEmpty) return '请确认密码';
return null;
},
),
const SizedBox(height: 12),

View File

@ -23,6 +23,7 @@ class AuthService {
String password,
) async {
final data = {'phone': username, 'password': password, ...formData};
final res = await AuthApi.userlogin(data);
if (!res['success']) {
Fluttertoast.showToast(msg: res['errMessage'] ?? '');
@ -34,25 +35,43 @@ class AuthService {
return {};
}
bool isInfoComplete = resData['isInfoComplete'] ?? false;
List firmList = resData['corpInfoCOList'] ?? [];
List firmList = resData['userCorpInfoCOList'] ?? [];
///
SessionService.instance.updateFromApiResponse(resData['userCO']);
await SessionService.instance.saveToPrefs();
// token
SessionService.instance.setToken('');
if (firmList.length == 1 && isInfoComplete) {
//
Map data = {
'unitId': firmList.first['id'] ?? '',
'unitId': firmList.first['corpinfoId'] ?? '',
};
return AuthService.gbsLogin(username, password, data);
} else if (firmList.length > 1) {
//
if (StorageService.instance.getString('key.saveJoinFirmInfo') != null) {
//
Map jsonData = json.decode(
StorageService.instance.getString('key.saveJoinFirmInfo') ?? '{}',
);
return AuthService.gbsLogin(username, password, jsonData);
//
String firmInfoStr = StorageService.instance.getString('key.saveJoinFirmInfo') ?? '{}';
for (Map Item in firmList) {
String firmId = Item['corpinfoId'] ?? '';
if (firmInfoStr.contains(firmId)) {
Map jsonData = json.decode(
StorageService.instance.getString('key.saveJoinFirmInfo') ?? '{}',
);
return AuthService.gbsLogin(username, password, jsonData);
}
}
//
return {
'isChooseFirm': false,
'isInfoComplete': isInfoComplete,
'firmList': firmList,
'userName': username,
'password': password,
};
} else {
//
return {

View File

@ -676,60 +676,222 @@ String md5Hex(String input) {
/// 56
List<Map<String, String>> nationMapList = [
{"code": "01", "name": "汉族"},
{"code": "02", "name": "蒙古族"},
{"code": "03", "name": "回族"},
{"code": "04", "name": "藏族"},
{"code": "05", "name": "维吾尔族"},
{"code": "06", "name": "苗族"},
{"code": "07", "name": "彝族"},
{"code": "08", "name": "壮族"},
{"code": "09", "name": "布依族"},
{"code": "10", "name": "朝鲜族"},
{"code": "11", "name": "满族"},
{"code": "12", "name": "侗族"},
{"code": "13", "name": "瑶族"},
{"code": "14", "name": "白族"},
{"code": "15", "name": "土家族"},
{"code": "16", "name": "哈尼族"},
{"code": "17", "name": "哈萨克族"},
{"code": "18", "name": "傣族"},
{"code": "19", "name": "黎族"},
{"code": "20", "name": "傈僳族"},
{"code": "21", "name": "佤族"},
{"code": "22", "name": "畲族"},
{"code": "23", "name": "高山族"},
{"code": "24", "name": "拉祜族"},
{"code": "25", "name": "水族"},
{"code": "26", "name": "东乡族"},
{"code": "27", "name": "纳西族"},
{"code": "28", "name": "景颇族"},
{"code": "29", "name": "柯尔克孜族"},
{"code": "30", "name": "土族"},
{"code": "31", "name": "达斡尔族"},
{"code": "32", "name": "仫佬族"},
{"code": "33", "name": "羌族"},
{"code": "34", "name": "布朗族"},
{"code": "35", "name": "撒拉族"},
{"code": "36", "name": "毛南族"},
{"code": "37", "name": "仡佬族"},
{"code": "38", "name": "锡伯族"},
{"code": "39", "name": "阿昌族"},
{"code": "40", "name": "普米族"},
{"code": "41", "name": "塔吉克族"},
{"code": "42", "name": "怒族"},
{"code": "43", "name": "乌孜别克族"},
{"code": "44", "name": "俄罗斯族"},
{"code": "45", "name": "鄂温克族"},
{"code": "46", "name": "德昂族"},
{"code": "47", "name": "保安族"},
{"code": "48", "name": "裕固族"},
{"code": "49", "name": "京族"},
{"code": "50", "name": "塔塔尔族"},
{"code": "51", "name": "独龙族"},
{"code": "52", "name": "鄂伦春族"},
{"code": "53", "name": "赫哲族"},
{"code": "54", "name": "门巴族"},
{"code": "55", "name": "珞巴族"},
{"code": "56", "name": "基诺族"}
];
{
"name": "汉族",
"bianma": "hanzu"
},
{
"name": "满族",
"bianma": "manzu"
},
{
"name": "藏族",
"bianma": "zangzu"
},
{
"name": "蒙古族",
"bianma": "mengguzu"
},
{
"name": "回族",
"bianma": "huizu"
},
{
"name": "维吾尔族",
"bianma": "weiwu'erzu"
},
{
"name": "壮族",
"bianma": "zhuangzu"
},
{
"name": "苗族",
"bianma": "miaozu"
},
{
"name": "彝族",
"bianma": "yizu"
},
{
"name": "布依族",
"bianma": "buyizuu"
},
{
"name": "侗族",
"bianma": "dongzu"
},
{
"name": "瑶族",
"bianma": "yaozu"
},
{
"name": "白族",
"bianma": "baizu"
},
{
"name": "哈尼族",
"bianma": "hanizu"
},
{
"name": "哈萨克族",
"bianma": "hasakezu"
},
{
"name": "黎族",
"bianma": "lizu"
},
{
"name": "傣族",
"bianma": "daizu"
},
{
"name": "畲族",
"bianma": "shezu"
},
{
"name": "傈僳族",
"bianma": "lisuzu"
},
{
"name": "仡佬族",
"bianma": "gelaozu"
},
{
"name": "东乡族",
"bianma": "dongxiangzu"
},
{
"name": "高山族",
"bianma": "gaoshanzu"
},
{
"name": "拉祜族",
"bianma": "lahuzu"
},
{
"name": "水族",
"bianma": "shuizu"
},
{
"name": "佤族",
"bianma": "wazu"
},
{
"name": "纳西族",
"bianma": "naxizu"
},
{
"name": "羌族",
"bianma": "qiangzu"
},
{
"name": "土族",
"bianma": "tuzu"
},
{
"name": "仫佬族",
"bianma": "mulaozu"
},
{
"name": "锡伯族",
"bianma": "xibozu"
},
{
"name": "柯尔克孜族",
"bianma": "keerkezizu"
},
{
"name": "达斡尔族",
"bianma": "dawuerzu"
},
{
"name": "景颇族",
"bianma": "jingpozu"
},
{
"name": "毛南族",
"bianma": "maonanzu"
},
{
"name": "撒拉族",
"bianma": "salaizu"
},
{
"name": "布朗族",
"bianma": "bulangzu"
},
{
"name": "塔吉克族",
"bianma": "tajikezu"
},
{
"name": "阿昌族",
"bianma": "achangzu"
},
{
"name": "普米族",
"bianma": "pumizu"
},
{
"name": "鄂温克族",
"bianma": "ewenkezu"
},
{
"name": "怒族",
"bianma": "nuzu"
},
{
"name": "京族",
"bianma": "jingzu"
},
{
"name": "基诺族",
"bianma": "jinuozu"
},
{
"name": "德昂族",
"bianma": "deangzu"
},
{
"name": "保安族",
"bianma": "baoanzu"
},
{
"name": "俄罗斯族",
"bianma": "eluosizu"
},
{
"name": "裕固族",
"bianma": "yuguzu"
},
{
"name": "乌孜别克族",
"bianma": "wuzibiekezu"
},
{
"name": "门巴族",
"bianma": "menbazu"
},
{
"name": "鄂伦春族",
"bianma": "elunchunzu"
},
{
"name": "独龙族",
"bianma": "dulongzu"
},
{
"name": "塔塔尔族",
"bianma": "tataerzu"
},
{
"name": "赫哲族",
"bianma": "hezhezu"
},
{
"name": "珞巴族",
"bianma": "luobazu"
}
]
;