统一用户暂存
|
Before Width: | Height: | Size: 345 KiB After Width: | Height: | Size: 1.3 MiB |
|
Before Width: | Height: | Size: 345 KiB After Width: | Height: | Size: 1.3 MiB |
|
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 4.6 KiB |
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 6.6 KiB |
|
Before Width: | Height: | Size: 8.9 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 299 B |
|
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 334 KiB |
|
|
@ -491,7 +491,7 @@
|
|||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
CURRENT_PROJECT_VERSION = 62;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
|
|
@ -503,10 +503,11 @@
|
|||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.company.myapp2;
|
||||
MARKETING_VERSION = 2.2.3;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = uni.UNI85F7A17;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "qa-zsaq";
|
||||
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "qa-zsaq-des";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||
SWIFT_VERSION = 5.0;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
|
|
@ -685,7 +686,7 @@
|
|||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
CURRENT_PROJECT_VERSION = 62;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
|
|
@ -697,10 +698,11 @@
|
|||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.company.myapp2;
|
||||
MARKETING_VERSION = 2.2.3;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = uni.UNI85F7A17;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "qa-zsaq";
|
||||
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "qa-zsaq-des";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 5.0;
|
||||
|
|
@ -716,7 +718,7 @@
|
|||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
CURRENT_PROJECT_VERSION = 62;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
|
|
@ -728,10 +730,11 @@
|
|||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.company.myapp2;
|
||||
MARKETING_VERSION = 2.2.3;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = uni.UNI85F7A17;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "qa-zsaq";
|
||||
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "qa-zsaq-des";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||
SWIFT_VERSION = 5.0;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 77 KiB After Width: | Height: | Size: 363 KiB |
|
Before Width: | Height: | Size: 802 B After Width: | Height: | Size: 950 B |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 3.6 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 3.4 KiB |
|
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 6.0 KiB |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 5.3 KiB |
|
Before Width: | Height: | Size: 7.1 KiB After Width: | Height: | Size: 9.5 KiB |
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 5.7 KiB After Width: | Height: | Size: 7.5 KiB |
|
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 3.4 KiB |
|
Before Width: | Height: | Size: 6.6 KiB After Width: | Height: | Size: 8.7 KiB |
|
Before Width: | Height: | Size: 7.1 KiB After Width: | Height: | Size: 9.5 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 4.6 KiB |
|
Before Width: | Height: | Size: 8.9 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 4.9 KiB |
|
Before Width: | Height: | Size: 9.5 KiB After Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 345 KiB After Width: | Height: | Size: 1.3 MiB |
|
|
@ -1,91 +1,91 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CADisableMinimumFrameDurationOnPhone</key>
|
||||
<true/>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<dict>
|
||||
<key>CADisableMinimumFrameDurationOnPhone</key>
|
||||
<true/>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>${PRODUCT_NAME}</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>秦港双控</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>$(FLUTTER_BUILD_NAME)</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>$(FLUTTER_BUILD_NUMBER)</string>
|
||||
<key>LSApplicationQueriesSchemes</key>
|
||||
<array>
|
||||
<string>baidumap</string>
|
||||
</array>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>秦港双控</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>$(FLUTTER_BUILD_NAME)</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>$(FLUTTER_BUILD_NUMBER)</string>
|
||||
<key>LSApplicationQueriesSchemes</key>
|
||||
<array>
|
||||
<string>baidumap</string>
|
||||
</array>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>NFCReaderUsageDescription</key>
|
||||
<string>需要NFC权限来读取和写入标签</string>
|
||||
<key>NSAppTransportSecurity</key>
|
||||
<dict>
|
||||
<key>NSAllowsArbitraryLoads</key>
|
||||
<true/>
|
||||
<key>NFCReaderUsageDescription</key>
|
||||
<string>需要NFC权限来读取和写入标签</string>
|
||||
<key>NSAppTransportSecurity</key>
|
||||
<dict>
|
||||
<key>NSAllowsArbitraryLoads</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>NSBluetoothAlwaysUsageDescription</key>
|
||||
<string>app需要蓝牙权限连接设备</string>
|
||||
<key>NSCameraUsageDescription</key>
|
||||
<string>app需要相机权限来扫描二维码</string>
|
||||
<key>NSContactsUsageDescription</key>
|
||||
<string>app需要通讯录权限添加好友</string>
|
||||
<key>NSHealthShareUsageDescription</key>
|
||||
<string>app需要读取健康数据</string>
|
||||
<key>NSHealthUpdateUsageDescription</key>
|
||||
<string>app需要写入健康数据</string>
|
||||
<key>NSLocalNetworkUsageDescription</key>
|
||||
<string>app需要发现本地网络设备</string>
|
||||
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
|
||||
<string>我们需要访问您的位置来提供基于位置的服务,例如获取位置展示地图。您的位置数据不会用于其他目的。</string>
|
||||
<key>NSLocationAlwaysUsageDescription</key>
|
||||
<string>我们需要访问您的位置来提供基于位置的服务,例如获取位置展示地图。您的位置数据不会用于其他目的。</string>
|
||||
<key>NSLocationWhenInUseUsageDescription</key>
|
||||
<string>我们需要访问您的位置来提供基于位置的服务,例如获取位置展示地图。您的位置数据不会用于其他目的。</string>
|
||||
<key>NSMicrophoneUsageDescription</key>
|
||||
<string>app需要麦克风权限进行语音通话</string>
|
||||
<key>NSMotionUsageDescription</key>
|
||||
<string>app需要访问运动数据统计步数</string>
|
||||
<key>NSPhotoLibraryAddUsageDescription</key>
|
||||
<string>app需要保存图片到相册</string>
|
||||
<key>NSPhotoLibraryUsageDescription</key>
|
||||
<string>app需要访问相册以上传图片</string>
|
||||
<key>NSUserNotificationsUsageDescription</key>
|
||||
<string>app需要发送通知提醒重要信息</string>
|
||||
<key>UIApplicationSupportsIndirectInputEvents</key>
|
||||
<true/>
|
||||
<key>UIBackgroundModes</key>
|
||||
<array>
|
||||
<string>remote-notification</string>
|
||||
</array>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>LaunchScreen</string>
|
||||
<key>UIMainStoryboardFile</key>
|
||||
<string>Main</string>
|
||||
<key>UIStatusBarHidden</key>
|
||||
<false/>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||
</array>
|
||||
<key>com.apple.developer.nfc.readersession.formats</key>
|
||||
<array>
|
||||
<string>TAG</string>
|
||||
<string>NDEF</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
<key>NSBluetoothAlwaysUsageDescription</key>
|
||||
<string>app需要蓝牙权限连接设备</string>
|
||||
<key>NSCameraUsageDescription</key>
|
||||
<string>app需要相机权限来扫描二维码</string>
|
||||
<key>NSContactsUsageDescription</key>
|
||||
<string>app需要通讯录权限添加好友</string>
|
||||
<key>NSHealthShareUsageDescription</key>
|
||||
<string>app需要读取健康数据</string>
|
||||
<key>NSHealthUpdateUsageDescription</key>
|
||||
<string>app需要写入健康数据</string>
|
||||
<key>NSLocalNetworkUsageDescription</key>
|
||||
<string>app需要发现本地网络设备</string>
|
||||
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
|
||||
<string>我们需要访问您的位置来提供基于位置的服务,例如获取位置展示地图。您的位置数据不会用于其他目的。</string>
|
||||
<key>NSLocationAlwaysUsageDescription</key>
|
||||
<string>我们需要访问您的位置来提供基于位置的服务,例如获取位置展示地图。您的位置数据不会用于其他目的。</string>
|
||||
<key>NSLocationWhenInUseUsageDescription</key>
|
||||
<string>我们需要访问您的位置来提供基于位置的服务,例如获取位置展示地图。您的位置数据不会用于其他目的。</string>
|
||||
<key>NSMicrophoneUsageDescription</key>
|
||||
<string>app需要麦克风权限进行语音通话</string>
|
||||
<key>NSMotionUsageDescription</key>
|
||||
<string>app需要访问运动数据统计步数</string>
|
||||
<key>NSPhotoLibraryAddUsageDescription</key>
|
||||
<string>app需要保存图片到相册</string>
|
||||
<key>NSPhotoLibraryUsageDescription</key>
|
||||
<string>app需要访问相册以上传图片</string>
|
||||
<key>NSUserNotificationsUsageDescription</key>
|
||||
<string>app需要发送通知提醒重要信息</string>
|
||||
<key>UIApplicationSupportsIndirectInputEvents</key>
|
||||
<true/>
|
||||
<key>UIBackgroundModes</key>
|
||||
<array>
|
||||
<string>remote-notification</string>
|
||||
</array>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>LaunchScreen</string>
|
||||
<key>UIMainStoryboardFile</key>
|
||||
<string>Main</string>
|
||||
<key>UIStatusBarHidden</key>
|
||||
<false/>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||
</array>
|
||||
<key>com.apple.developer.nfc.readersession.formats</key>
|
||||
<array>
|
||||
<string>TAG</string>
|
||||
<string>NDEF</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
|
|||
|
|
@ -1,9 +1,12 @@
|
|||
// custom_alert_dialog.dart
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:qhd_prevention/customWidget/custom_button.dart';
|
||||
import 'package:qhd_prevention/main.dart'; // 导入全局 navigatorKey
|
||||
|
||||
/// 对话框模式
|
||||
enum DialogMode { text, input }
|
||||
enum DialogMode { text, input, inputWithCode }
|
||||
|
||||
class CustomAlertDialog extends StatefulWidget {
|
||||
final String title;
|
||||
|
|
@ -17,6 +20,10 @@ class CustomAlertDialog extends StatefulWidget {
|
|||
final DialogMode mode;
|
||||
final bool force;
|
||||
|
||||
/// 新增:获取验证码回调,若提供则在用户点击获取验证码时调用。
|
||||
/// 回调返回 true 表示获取成功(开始倒计时),返回 false 表示获取失败(不开始倒计时)。
|
||||
final Future<bool> Function()? onGetCode;
|
||||
|
||||
const CustomAlertDialog({
|
||||
Key? key,
|
||||
required this.title,
|
||||
|
|
@ -29,85 +36,119 @@ class CustomAlertDialog extends StatefulWidget {
|
|||
this.onInputConfirm,
|
||||
this.mode = DialogMode.text,
|
||||
this.force = false,
|
||||
this.onGetCode,
|
||||
}) : super(key: key);
|
||||
|
||||
// ------------------ 静态快捷方法 ------------------
|
||||
|
||||
static Future<bool> showConfirm(
|
||||
BuildContext context, {
|
||||
required String title,
|
||||
String content = '',
|
||||
String cancelText = '取消',
|
||||
String confirmText = '确定',
|
||||
bool barrierDismissible = true,
|
||||
VoidCallback? onConfirm,
|
||||
bool force = false,
|
||||
}) async {
|
||||
BuildContext context, {
|
||||
required String title,
|
||||
String content = '',
|
||||
String cancelText = '取消',
|
||||
String confirmText = '确定',
|
||||
bool barrierDismissible = true,
|
||||
VoidCallback? onConfirm,
|
||||
bool force = false,
|
||||
}) async {
|
||||
final result = await showDialog<bool>(
|
||||
context: context,
|
||||
barrierDismissible: force ? false : barrierDismissible,
|
||||
builder: (_) => PopScope(
|
||||
canPop: false,
|
||||
child: CustomAlertDialog(
|
||||
title: title,
|
||||
content: content,
|
||||
cancelText: cancelText,
|
||||
confirmText: confirmText,
|
||||
onConfirm: onConfirm,
|
||||
force: force,
|
||||
),)
|
||||
builder:
|
||||
(_) => PopScope(
|
||||
canPop: false,
|
||||
child: CustomAlertDialog(
|
||||
title: title,
|
||||
content: content,
|
||||
cancelText: cancelText,
|
||||
confirmText: confirmText,
|
||||
onConfirm: onConfirm,
|
||||
force: force,
|
||||
),
|
||||
),
|
||||
);
|
||||
return result == true;
|
||||
}
|
||||
|
||||
static Future<void> showAlert(
|
||||
BuildContext context, {
|
||||
required String title,
|
||||
String content = '',
|
||||
String confirmText = '确定',
|
||||
bool barrierDismissible = true,
|
||||
VoidCallback? onConfirm,
|
||||
bool force = false,
|
||||
}) async {
|
||||
BuildContext context, {
|
||||
required String title,
|
||||
String content = '',
|
||||
String confirmText = '确定',
|
||||
bool barrierDismissible = true,
|
||||
VoidCallback? onConfirm,
|
||||
bool force = false,
|
||||
}) async {
|
||||
await showDialog<void>(
|
||||
context: context,
|
||||
barrierDismissible: force ? false : barrierDismissible,
|
||||
builder: (_) => CustomAlertDialog(
|
||||
title: title,
|
||||
content: content,
|
||||
cancelText: '',
|
||||
confirmText: confirmText,
|
||||
onConfirm: onConfirm,
|
||||
force: force,
|
||||
),
|
||||
builder:
|
||||
(_) => CustomAlertDialog(
|
||||
title: title,
|
||||
content: content,
|
||||
cancelText: '',
|
||||
confirmText: confirmText,
|
||||
onConfirm: onConfirm,
|
||||
force: force,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
static Future<String?> showInput(
|
||||
BuildContext context, {
|
||||
required String title,
|
||||
String hintText = '',
|
||||
String cancelText = '取消',
|
||||
String confirmText = '确定',
|
||||
bool barrierDismissible = true,
|
||||
bool force = false,
|
||||
}) async {
|
||||
BuildContext context, {
|
||||
required String title,
|
||||
String hintText = '',
|
||||
String cancelText = '取消',
|
||||
String confirmText = '确定',
|
||||
bool barrierDismissible = true,
|
||||
bool force = false,
|
||||
}) async {
|
||||
final result = await showDialog<String?>(
|
||||
context: context,
|
||||
barrierDismissible: force ? false : barrierDismissible,
|
||||
builder: (_) => CustomAlertDialog(
|
||||
title: title,
|
||||
hintText: hintText,
|
||||
cancelText: cancelText,
|
||||
confirmText: confirmText,
|
||||
mode: DialogMode.input,
|
||||
force: force,
|
||||
),
|
||||
builder:
|
||||
(_) => CustomAlertDialog(
|
||||
title: title,
|
||||
hintText: hintText,
|
||||
cancelText: cancelText,
|
||||
confirmText: confirmText,
|
||||
mode: DialogMode.input,
|
||||
force: force,
|
||||
),
|
||||
);
|
||||
// 取消/点遮罩会得到 null;确认会得到 String(可能为空串)
|
||||
return result;
|
||||
}
|
||||
|
||||
/// 新增:快捷方法——输入框 + 获取验证码
|
||||
static Future<String?> showInputWithCode(
|
||||
BuildContext context, {
|
||||
required String title,
|
||||
String hintText = '',
|
||||
String cancelText = '取消',
|
||||
String confirmText = '确定',
|
||||
bool barrierDismissible = true,
|
||||
bool force = false,
|
||||
Future<bool> Function()? onGetCode,
|
||||
ValueChanged<String>? onConfirm, // <-- 这里改为带参数的回调
|
||||
}) async {
|
||||
final result = await showDialog<String?>(
|
||||
context: context,
|
||||
barrierDismissible: force ? false : barrierDismissible,
|
||||
builder:
|
||||
(_) => CustomAlertDialog(
|
||||
title: title,
|
||||
hintText: hintText,
|
||||
cancelText: cancelText,
|
||||
confirmText: confirmText,
|
||||
mode: DialogMode.inputWithCode,
|
||||
force: force,
|
||||
onGetCode: onGetCode,
|
||||
onInputConfirm: onConfirm, // 把回调传给内部使用的 onInputConfirm
|
||||
),
|
||||
);
|
||||
return result;
|
||||
}
|
||||
|
||||
@override
|
||||
_CustomAlertDialogState createState() => _CustomAlertDialogState();
|
||||
|
|
@ -117,6 +158,11 @@ class _CustomAlertDialogState extends State<CustomAlertDialog> {
|
|||
late TextEditingController _controller;
|
||||
bool _isClosing = false;
|
||||
|
||||
// 验证码计时器相关
|
||||
Timer? _timer;
|
||||
int _seconds = 0;
|
||||
static const int _defaultCountdown = 60;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
|
@ -125,6 +171,7 @@ class _CustomAlertDialogState extends State<CustomAlertDialog> {
|
|||
|
||||
@override
|
||||
void dispose() {
|
||||
_timer?.cancel();
|
||||
_controller.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
|
@ -144,6 +191,41 @@ class _CustomAlertDialogState extends State<CustomAlertDialog> {
|
|||
}
|
||||
}
|
||||
|
||||
void _startCountdown([int seconds = _defaultCountdown]) {
|
||||
_timer?.cancel();
|
||||
setState(() {
|
||||
_seconds = seconds;
|
||||
});
|
||||
_timer = Timer.periodic(const Duration(seconds: 1), (t) {
|
||||
if (!mounted) {
|
||||
t.cancel();
|
||||
return;
|
||||
}
|
||||
if (_seconds <= 1) {
|
||||
t.cancel();
|
||||
setState(() {
|
||||
_seconds = 0;
|
||||
});
|
||||
} else {
|
||||
setState(() {
|
||||
_seconds -= 1;
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> _onGetCodePressed() async {
|
||||
if (_seconds > 0) return; // 正在倒计时,忽略
|
||||
// 如果外部提供了回调,等待其执行并根据返回值决定是否开始倒计时
|
||||
if (widget.onGetCode != null) {
|
||||
await widget.onGetCode!();
|
||||
_startCountdown();
|
||||
} else {
|
||||
// 未提供回调:默认直接开始倒计时(方便调试)
|
||||
_startCountdown();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return PopScope(
|
||||
|
|
@ -177,14 +259,11 @@ class _CustomAlertDialogState extends State<CustomAlertDialog> {
|
|||
padding: const EdgeInsets.symmetric(horizontal: 24),
|
||||
child: Text(
|
||||
widget.content,
|
||||
style: const TextStyle(
|
||||
fontSize: 16,
|
||||
color: Colors.black54,
|
||||
),
|
||||
style: const TextStyle(fontSize: 16, color: Colors.black54),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
)
|
||||
else
|
||||
else if (widget.mode == DialogMode.input)
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 20),
|
||||
child: TextField(
|
||||
|
|
@ -204,6 +283,45 @@ class _CustomAlertDialogState extends State<CustomAlertDialog> {
|
|||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
else // DialogMode.inputWithCode
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: TextField(
|
||||
controller: _controller,
|
||||
autofocus: true,
|
||||
decoration: InputDecoration(
|
||||
hintText: widget.hintText,
|
||||
border: const OutlineInputBorder(),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderSide: BorderSide(
|
||||
color: Colors.blue,
|
||||
width: 1,
|
||||
),
|
||||
borderRadius: BorderRadius.circular(4),
|
||||
),
|
||||
isDense: true,
|
||||
contentPadding: const EdgeInsets.symmetric(
|
||||
vertical: 10,
|
||||
horizontal: 10,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
SizedBox(
|
||||
height: 44,
|
||||
width: 100,
|
||||
child: CustomButton(
|
||||
text: _seconds > 0 ? '$_seconds s' : '发送验证码',
|
||||
onPressed: _seconds > 0 ? null : _onGetCodePressed,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
const Divider(height: 1),
|
||||
|
|
@ -298,4 +416,4 @@ class _CustomAlertDialogState extends State<CustomAlertDialog> {
|
|||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ class ApiService {
|
|||
static final String baseImgPath =
|
||||
isProduct
|
||||
? "https://jpfz.qhdsafety.com/gbsFileTest/"
|
||||
: "http://192.168.20.100:9787/mnt/"; //内网图片地址
|
||||
: "http://192.168.20.240:9787/mnt/"; //内网图片地址
|
||||
|
||||
static const publicKey =
|
||||
'0402df2195296d4062ac85ad766994d73e871b887e18efb9a9a06b4cebc72372869b7da6c347c129dee2b46a0f279ff066b01c76208c2a052af75977c722a2ccee';
|
||||
|
|
|
|||
|
|
@ -76,6 +76,7 @@ class HttpManager {
|
|||
CancelToken? cancelToken,
|
||||
String? contentType, // Content-Type,默认为 jsonContentType
|
||||
bool isHeartbeat = false,
|
||||
bool isHaveToken = true,
|
||||
}) async {
|
||||
printLongString('参数:${jsonEncode(data)}');
|
||||
Response resp;
|
||||
|
|
@ -87,7 +88,7 @@ class HttpManager {
|
|||
};
|
||||
final token = SessionService.instance.token ?? '';
|
||||
// final token = 'jjb-saas-auth:oauth:eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ7XCJjbGllbnRJZFwiOlwieGdmemRcIixcImFjY291bnRJZFwiOjE5OTE2NzQ0MzEzMzY4NDk0MDgsXCJ1c2VyVHlwZUVudW1cIjpcIlBMQVRGT1JNXCIsXCJ1c2VySWRcIjoxOTkxNjc0NDI4MjYxNTMxNjQ4LFwidGVuYW50SWRcIjoxOTkxNjc0NDI4MjYxNTMxNjQ4LFwidGVuYW50TmFtZVwiOlwi5Yas5rOz55u45YWz5pa5XCIsXCJ0ZW5hbnRUeXBlSWRcIjoxOTkwNjkzMzg4MDcyMTI0NDE2LFwidGVuYW50UGFyZW50SWRzXCI6XCIwLDE5ODM3NzMwMTMwODYwNDgyNTYsMTk5MTY3NDQyODI2MTUzMTY0OFwiLFwibmFtZVwiOlwi5Yas5rOz55u45YWz5pa5XCIsXCJhY2Nlc3NUaWNrZXRcIjpcIkg0YXBlMkFaRVcxZFR1OTIwOXNzSDREc3pPWjBoTkZ4eEVlZzRmYTJZaFRVUFA0QkZVZXZmSklhTVdoS1wiLFwicmVmcmVzaFRpY2tldFwiOlwiRlRlZUxIaXJVblhueTBMcXNMcUdyc2dFaGpqVlRRN0pncVptVTBLS0JHVkFCU1ExeENtT3RTWmxRbUdpXCIsXCJleHBpcmVJblwiOjYwNDgwMCxcInJlZnJlc2hFeHBpcmVzSW5cIjo2MDQ4MDAsXCJvcmdJZFwiOjE5OTE2NzQ0MjgyNjE1MzE2NDgsXCJvcmdOYW1lXCI6XCLlhqzms7Pnm7jlhbPmlrlcIixcIm9yZ0lkc1wiOlsxOTkxNjc0NDI4MjYxNTMxNjQ4XSxcInJvbGVzVHlwZXNcIjpbXCJHT1ZfQ0hJTERfQUNDT1VOVFwiXSxcInJvbGVJZHNcIjpbMTk5MDY5MjE3NTA2NjgyNDcwNV0sXCJzY29wZXNcIjpbXSxcInJwY1R5cGVFbnVtXCI6XCJIVFRQXCIsXCJiaW5kTW9iaWxlU2lnblwiOlwiRkFMU0VcIn0iLCJpc3MiOiJwcm8tc2VydmVyIiwiZXhwIjoxNzY1OTU4NDIzfQ.RphPGGnh18RdGZ2vB0-2gKHp6bQg3-rKR4xPvDgH1ek';
|
||||
if (token != null && token.isNotEmpty && !isHeartbeat) {
|
||||
if (token != null && token.isNotEmpty && !isHeartbeat && isHaveToken) {
|
||||
headers['token'] = token;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ class AuthApi {
|
|||
ApiService.basePath,
|
||||
'/login/captcha',
|
||||
method: Method.get,
|
||||
isHaveToken: false,
|
||||
data: {},
|
||||
);
|
||||
}
|
||||
|
|
@ -60,7 +61,8 @@ class AuthApi {
|
|||
static Future<Map<String, dynamic>> getUserData() {
|
||||
return HttpManager().request(
|
||||
ApiService.basePath,
|
||||
'/basicInfo/user/getInfo',
|
||||
// '/basicInfo/user/getInfo',
|
||||
'/basicInfo/user/${SessionService.instance.accountId}',
|
||||
method: Method.get,
|
||||
data: {},
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import 'package:dio/dio.dart';
|
||||
import 'package:qhd_prevention/http/ApiService.dart';
|
||||
import 'package:qhd_prevention/http/HttpManager.dart';
|
||||
import 'package:qhd_prevention/services/SessionService.dart';
|
||||
|
||||
class BasicInfoApi {
|
||||
/// 注册
|
||||
|
|
@ -12,6 +13,17 @@ class BasicInfoApi {
|
|||
data: {...data},
|
||||
);
|
||||
}
|
||||
/// 注销
|
||||
static Future<Map<String, dynamic>> logout(Map data) {
|
||||
return HttpManager().request(
|
||||
ApiService.basePath + (ApiService.isProduct ? '/basicInfo' : '/basicInfo') ,
|
||||
'/appuser/logOut',
|
||||
method: Method.post,
|
||||
data: {
|
||||
...data
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/// 发送验证码
|
||||
static Future<Map<String, dynamic>> sendRegisterSms(Map data) {
|
||||
|
|
@ -42,15 +54,6 @@ class BasicInfoApi {
|
|||
data: {...data},
|
||||
);
|
||||
}
|
||||
// 就职信息
|
||||
static Future<Map<String, dynamic>> getEntryInfo(String id) {
|
||||
return HttpManager().request(
|
||||
ApiService.basePath + (ApiService.isProduct ? '/basicInfo' : '/basicInfo') ,
|
||||
'/app/userCorpRecord/getInfoById/$id',
|
||||
method: Method.get,
|
||||
data: {},
|
||||
);
|
||||
}
|
||||
/// 获取用户信息
|
||||
static Future<Map<String, dynamic>> getUserMessage(String value) {
|
||||
return HttpManager().request(
|
||||
|
|
@ -79,6 +82,44 @@ class BasicInfoApi {
|
|||
data: {...data},
|
||||
);
|
||||
}
|
||||
/// 就职单位列表
|
||||
static Future<Map<String, dynamic>> getFirmListByUser(Map data) {
|
||||
return HttpManager().request(
|
||||
ApiService.basePath + (ApiService.isProduct ? '/basicInfo' : '/basicInfo') ,
|
||||
'/app/userCorpRecord/list',
|
||||
method: Method.post,
|
||||
data: {...data},
|
||||
);
|
||||
}
|
||||
/// 企业入职详情
|
||||
static Future<Map<String, dynamic>> getFirmInfo(String id) {
|
||||
return HttpManager().request(
|
||||
ApiService.basePath + (ApiService.isProduct ? '/basicInfo' : '/basicInfo') ,
|
||||
'/app/userCorpRecord/getInfoById/$id',
|
||||
method: Method.get,
|
||||
data: {},
|
||||
);
|
||||
}
|
||||
/// 离职申请
|
||||
static Future<Map<String, dynamic>> leaveApply(Map data) {
|
||||
return HttpManager().request(
|
||||
ApiService.basePath + (ApiService.isProduct ? '/basicInfo' : '/basicInfo') ,
|
||||
'/appuser/appUserResignation',
|
||||
method: Method.post,
|
||||
data: {...data},
|
||||
);
|
||||
}
|
||||
/// 在职企业列表
|
||||
static Future<Map<String, dynamic>> getJoinFirmList() {
|
||||
return HttpManager().request(
|
||||
ApiService.basePath + (ApiService.isProduct ? '/basicInfo' : '/basicInfo') ,
|
||||
'/appuser/getUserCorpList/${SessionService.instance.accountId}',
|
||||
method: Method.post,
|
||||
data: {},
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@ class FileApi {
|
|||
}
|
||||
final fileName = file.path.split(Platform.pathSeparator).last;
|
||||
|
||||
|
||||
return HttpManager().uploadImages(
|
||||
baseUrl: ApiService.basePath,
|
||||
path: '/basicInfo/imgFiles/save',
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import 'package:qhd_prevention/customWidget/custom_button.dart';
|
|||
import 'package:qhd_prevention/pages/home/scan_page.dart';
|
||||
import 'package:qhd_prevention/pages/home/unit/unit_tab_page.dart';
|
||||
import 'package:qhd_prevention/pages/main_tab.dart';
|
||||
import 'package:qhd_prevention/pages/user/choose_userFirm_page.dart';
|
||||
import 'package:qhd_prevention/pages/user/firm_list_page.dart';
|
||||
import 'package:qhd_prevention/tools/h_colors.dart';
|
||||
import 'package:qhd_prevention/tools/tools.dart';
|
||||
|
|
@ -422,6 +423,10 @@ class HomePageState extends RouteAwareState<HomePage>
|
|||
);
|
||||
}
|
||||
|
||||
Future<void> _joinFirm() async {
|
||||
pushPage(FirmListPage(isBack: true,), context);
|
||||
}
|
||||
|
||||
// 固定在屏幕右上角的图标(不会随页面滚动)
|
||||
Widget _buildFixedTopIcons(BuildContext context) {
|
||||
final double statusBar = MediaQuery.of(context).padding.top;
|
||||
|
|
@ -446,6 +451,19 @@ class HomePageState extends RouteAwareState<HomePage>
|
|||
),
|
||||
),
|
||||
),
|
||||
GestureDetector(
|
||||
onTap: _joinFirm,
|
||||
child: Container(
|
||||
width: 38,
|
||||
height: 38,
|
||||
alignment: Alignment.center,
|
||||
child: Image.asset(
|
||||
"assets/icon-apps/home_add.png",
|
||||
width: 22,
|
||||
height: 22,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
|
@ -594,7 +612,7 @@ class HomePageState extends RouteAwareState<HomePage>
|
|||
CustomButton(
|
||||
text: '点击入职企业',
|
||||
onPressed: () {
|
||||
pushPage(FirmListPage(), context);
|
||||
pushPage(FirmListPage(isBack: true,), context);
|
||||
},
|
||||
)
|
||||
],
|
||||
|
|
|
|||
|
|
@ -0,0 +1,475 @@
|
|||
import 'dart:convert';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:qhd_prevention/constants/app_enums.dart';
|
||||
import 'package:qhd_prevention/customWidget/ItemWidgetFactory.dart';
|
||||
import 'package:qhd_prevention/customWidget/bottom_picker.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/toast_util.dart';
|
||||
import 'package:qhd_prevention/http/ApiService.dart';
|
||||
import 'package:qhd_prevention/pages/main_tab.dart';
|
||||
import 'package:qhd_prevention/pages/my_appbar.dart';
|
||||
import 'package:qhd_prevention/services/SessionService.dart';
|
||||
import 'package:qhd_prevention/tools/tools.dart';
|
||||
|
||||
class UnitJoinDetailPage extends StatefulWidget {
|
||||
const UnitJoinDetailPage({super.key, required this.firmId});
|
||||
final String firmId;
|
||||
@override
|
||||
State<UnitJoinDetailPage> createState() => _UnitJoinDetailPageState();
|
||||
}
|
||||
|
||||
class _UnitJoinDetailPageState extends State<UnitJoinDetailPage> {
|
||||
Map<String, dynamic> pd = {
|
||||
};
|
||||
late bool _isEdit;
|
||||
|
||||
String _genderText = '';
|
||||
String _birthText = '';
|
||||
List<String> _idCardImgList = [];
|
||||
List<String> _idCartImgIds = [];
|
||||
List<String> _idCardImgRemoveList = [];
|
||||
|
||||
List<dynamic> _wenhuachengduList = [];
|
||||
List<dynamic> _zhengzhimianmaoList = [];
|
||||
List<dynamic> _hunyinList = [
|
||||
{"name": "已婚", "value": 1},
|
||||
{"name": "未婚", "value": 0},
|
||||
];
|
||||
List<String> idPhotos = [];
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_isEdit = false;
|
||||
_getUserDetail();
|
||||
|
||||
_getKeyValues();
|
||||
}
|
||||
|
||||
Future<void> _getUserDetail() async {
|
||||
final res = await BasicInfoApi.getFirmInfo(
|
||||
widget.firmId,
|
||||
);
|
||||
if (res['success']) {
|
||||
final data = res['data'];
|
||||
_genderText = data['sex'] ?? '';
|
||||
_birthText = data['birthday'] ?? '';
|
||||
final eqForeignKey = data['userId'];
|
||||
await FileApi.getImagePathWithType(
|
||||
eqForeignKey,
|
||||
'',
|
||||
UploadFileType.idCardPhoto,
|
||||
).then((result) {
|
||||
if (result['success']) {
|
||||
List files = result['data'] ?? [];
|
||||
_idCardImgList =
|
||||
files.map((item) => item['filePath'].toString()).toList();
|
||||
_idCartImgIds = files.map((item) => item['id'].toString()).toList();
|
||||
// final filePath = fileData.first['filePath'] ?? '';
|
||||
}
|
||||
});
|
||||
|
||||
setState(() {
|
||||
pd = data;
|
||||
try{
|
||||
final idCardBase64 = utf8.decode(base64.decode(pd['userIdCard']));
|
||||
if (idCardBase64.isNotEmpty) {
|
||||
pd['userIdCard'] =idCardBase64;
|
||||
}
|
||||
}catch(e){
|
||||
print(e);
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _getKeyValues() async {
|
||||
await BasicInfoApi.getDictValues('wenhuachengdu').then((res) {
|
||||
_wenhuachengduList = res['data'];
|
||||
});
|
||||
await BasicInfoApi.getDictValues('zhengzhimianmao').then((res) {
|
||||
_zhengzhimianmaoList = res['data'];
|
||||
});
|
||||
}
|
||||
|
||||
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;
|
||||
if (!_isEdit && FormUtils.hasValue(pd, 'id')) {
|
||||
isShow = true;
|
||||
}
|
||||
return Scaffold(
|
||||
appBar: MyAppbar(
|
||||
title: '查看信息',
|
||||
),
|
||||
|
||||
body: SafeArea(
|
||||
child: ItemListWidget.itemContainer(
|
||||
horizontal: 5,
|
||||
isShow ? ListView(
|
||||
children: [
|
||||
RepairedPhotoSection(
|
||||
title: '照片',
|
||||
inlineSingle: true,
|
||||
isRequired: _isEdit,
|
||||
initialMediaPaths:
|
||||
FormUtils.hasValue(pd, 'userAvatarUrl')
|
||||
? [
|
||||
'${ApiService.baseImgPath}${pd['userAvatarUrl'] ?? ''}',
|
||||
]
|
||||
: [],
|
||||
horizontalPadding: _isEdit ? 12 : 0,
|
||||
inlineImageWidth: 60,
|
||||
isFaceImage: true,
|
||||
isEdit: _isEdit,
|
||||
onChanged: (files) {
|
||||
if (files.isEmpty) {
|
||||
return;
|
||||
}
|
||||
pd['faceFiles'] = files.first.path;
|
||||
},
|
||||
onAiIdentify: () {},
|
||||
// onMediaRemovedForIndex: (index) async {
|
||||
// final deleFile = pd['userAvatarUrl'] ?? '';
|
||||
// if (deleFile.contains(UploadFileType.idCardPhoto.path)) {
|
||||
// _idCardImgRemoveList.add(deleFile);
|
||||
// }
|
||||
// },
|
||||
),
|
||||
if (_isEdit)
|
||||
ItemListWidget.itemContainer(
|
||||
const Text(
|
||||
'温馨提示:该照片为进入项目施工场所口门人脸识别使用',
|
||||
style: TextStyle(color: Colors.red, fontSize: 10),
|
||||
),
|
||||
),
|
||||
const Divider(),
|
||||
ItemListWidget.singleLineTitleText(
|
||||
label: '姓名:',
|
||||
isRequired: true,
|
||||
hintText: '请输入姓名',
|
||||
text: pd['name'] ?? '',
|
||||
isEditable: _isEdit,
|
||||
onChanged: (value) {
|
||||
pd['name'] = value;
|
||||
},
|
||||
),
|
||||
const Divider(),
|
||||
ItemListWidget.singleLineTitleText(
|
||||
label: '手机号:',
|
||||
isRequired: true,
|
||||
text: pd['username'] ?? '',
|
||||
isNumericInput: true,
|
||||
hintText: '请输入手机号',
|
||||
strongRequired: _isEdit,
|
||||
isEditable: false,
|
||||
),
|
||||
const Divider(),
|
||||
// 身份证输入:只使用 onChanged 回调(value 是实时输入框的值)
|
||||
ItemListWidget.singleLineTitleText(
|
||||
label: '身份证:',
|
||||
isRequired: true,
|
||||
hintText: '请输入身份证号',
|
||||
text: pd['userIdCard'] ?? '',
|
||||
isEditable: _isEdit,
|
||||
onChanged: (value) {
|
||||
},
|
||||
),
|
||||
const Divider(),
|
||||
ItemListWidget.selectableLineTitleTextRightButton(
|
||||
label: '民族:',
|
||||
isEditable: _isEdit,
|
||||
text: pd['nationName'] ?? '请选择',
|
||||
isRequired: _isEdit,
|
||||
onTap: () async {
|
||||
final found = await BottomPicker.show(
|
||||
context,
|
||||
items: nationMapList,
|
||||
itemBuilder:
|
||||
(i) =>
|
||||
Text(i['name']!, textAlign: TextAlign.center),
|
||||
initialIndex: 0,
|
||||
);
|
||||
//FocusHelper.clearFocus(context);
|
||||
|
||||
if (found != null) {
|
||||
setState(() {
|
||||
pd['nationName'] = found['name'];
|
||||
pd['nation'] = found['code'];
|
||||
});
|
||||
}
|
||||
},
|
||||
),
|
||||
const Divider(),
|
||||
// 性别:不可编辑,显示解析结果(也允许手动覆盖)
|
||||
ItemListWidget.selectableLineTitleTextRightButton(
|
||||
label: '性别:',
|
||||
isEditable: false,
|
||||
text: _genderText,
|
||||
|
||||
strongRequired: _isEdit,
|
||||
isRequired: true,
|
||||
onTap: () {
|
||||
// 允许手动选择覆盖解析结果
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
builder: (_) {
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
ListTile(
|
||||
title: const Text('男'),
|
||||
onTap: () {
|
||||
setState(() {
|
||||
pd['gender'] = '男';
|
||||
_genderText = '男';
|
||||
});
|
||||
Navigator.pop(context);
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
title: const Text('女'),
|
||||
onTap: () {
|
||||
setState(() {
|
||||
pd['gender'] = '女';
|
||||
_genderText = '女';
|
||||
});
|
||||
Navigator.pop(context);
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
const Divider(),
|
||||
// 出生年月:显示解析结果,但仍然可以手动修改
|
||||
ItemListWidget.selectableLineTitleTextRightButton(
|
||||
label: '出生年月:',
|
||||
isEditable: false,
|
||||
text: _birthText,
|
||||
strongRequired: _isEdit,
|
||||
isRequired: true,
|
||||
onTap: () async {
|
||||
},
|
||||
),
|
||||
const Divider(),
|
||||
|
||||
ItemListWidget.singleLineTitleText(
|
||||
label: '户口所在地:',
|
||||
isRequired: _isEdit,
|
||||
hintText: '请输入户口所在地',
|
||||
text: pd['locationAddress'] ?? '',
|
||||
isEditable: _isEdit,
|
||||
onChanged: (value) {
|
||||
pd['locationAddress'] = value;
|
||||
},
|
||||
),
|
||||
const Divider(),
|
||||
ItemListWidget.singleLineTitleText(
|
||||
label: '现住址:',
|
||||
isRequired: true,
|
||||
text: pd['currentAddress'] ?? '',
|
||||
hintText: '请输入现住址',
|
||||
isEditable: _isEdit,
|
||||
onChanged: (value) {
|
||||
pd['currentAddress'] = value;
|
||||
},
|
||||
),
|
||||
const Divider(),
|
||||
if (_isEdit || _idCardImgList.isNotEmpty)
|
||||
RepairedPhotoSection(
|
||||
title: '身份证照片',
|
||||
isRequired: _isEdit,
|
||||
maxCount: 2,
|
||||
initialMediaPaths:
|
||||
_idCardImgList
|
||||
.map(
|
||||
(item) =>
|
||||
ApiService.baseImgPath + item,
|
||||
)
|
||||
.toList(),
|
||||
isEdit: _isEdit,
|
||||
horizontalPadding: _isEdit ? 12 : 0,
|
||||
inlineImageWidth: 60,
|
||||
onChanged: (files) {
|
||||
idPhotos = files.map((file) => file.path).toList();
|
||||
},
|
||||
onMediaRemovedForIndex: (index) async {
|
||||
final deleFile = _idCardImgList[index];
|
||||
final deleId = _idCartImgIds[index];
|
||||
if (deleFile.contains(UploadFileType.idCardPhoto.path)) {
|
||||
_idCardImgList.removeAt(index);
|
||||
_idCartImgIds.removeAt(index);
|
||||
_idCardImgRemoveList.add(deleId);
|
||||
}
|
||||
},
|
||||
|
||||
onAiIdentify: () {
|
||||
/* ... */
|
||||
},
|
||||
),
|
||||
if (_isEdit)
|
||||
ItemListWidget.itemContainer(
|
||||
const Text(
|
||||
'温馨提示:用户要上传身份证正反面(身份证照片数量是2张才能进行人员培训)',
|
||||
style: TextStyle(color: Colors.red, fontSize: 10),
|
||||
),
|
||||
),
|
||||
const Divider(),
|
||||
ItemListWidget.selectableLineTitleTextRightButton(
|
||||
label: '文化程度:',
|
||||
isEditable: _isEdit,
|
||||
text: pd['culturalLevelName'] ?? '请选择',
|
||||
isRequired: _isEdit,
|
||||
onTap: () async {
|
||||
final found = await BottomPicker.show(
|
||||
context,
|
||||
items: _wenhuachengduList,
|
||||
itemBuilder:
|
||||
(i) => Text(
|
||||
i['dictLabel']!,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
initialIndex: 0,
|
||||
);
|
||||
//FocusHelper.clearFocus(context);
|
||||
|
||||
if (found != null) {
|
||||
setState(() {
|
||||
pd['culturalLevelName'] = found['dictLabel'];
|
||||
pd['culturalLevel'] = found['dictValue'];
|
||||
});
|
||||
}
|
||||
},
|
||||
),
|
||||
const Divider(),
|
||||
ItemListWidget.selectableLineTitleTextRightButton(
|
||||
label: '政治面貌:',
|
||||
isEditable: _isEdit,
|
||||
text: pd['politicalAffiliationName'] ?? '请选择',
|
||||
isRequired: _isEdit,
|
||||
onTap: () async {
|
||||
final found = await BottomPicker.show(
|
||||
context,
|
||||
items: _zhengzhimianmaoList,
|
||||
itemBuilder:
|
||||
(i) => Text(
|
||||
i['dictLabel']!,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
initialIndex: 0,
|
||||
);
|
||||
//FocusHelper.clearFocus(context);
|
||||
|
||||
if (found != null) {
|
||||
setState(() {
|
||||
pd['politicalAffiliationName'] = found['dictLabel'];
|
||||
pd['politicalAffiliation'] = found['dictValue'];
|
||||
});
|
||||
}
|
||||
},
|
||||
),
|
||||
const Divider(),
|
||||
ItemListWidget.selectableLineTitleTextRightButton(
|
||||
label: '婚姻状态:',
|
||||
isEditable: _isEdit,
|
||||
text: pd['maritalStatusName'] ?? '请选择',
|
||||
isRequired: _isEdit,
|
||||
onTap: () async {
|
||||
final found = await BottomPicker.show(
|
||||
context,
|
||||
items: _hunyinList,
|
||||
itemBuilder:
|
||||
(i) =>
|
||||
Text(i['name']!, textAlign: TextAlign.center),
|
||||
initialIndex: 0,
|
||||
);
|
||||
//FocusHelper.clearFocus(context);
|
||||
|
||||
if (found != null) {
|
||||
setState(() {
|
||||
pd['maritalStatusName'] = found['name'];
|
||||
pd['maritalStatus'] = found['value'];
|
||||
});
|
||||
}
|
||||
},
|
||||
),
|
||||
const Divider(),
|
||||
ListItemFactory.createYesNoSection(
|
||||
title: "是否流动人员:",
|
||||
horizontalPadding: 2,
|
||||
verticalPadding: 0,
|
||||
yesLabel: "是",
|
||||
noLabel: "否",
|
||||
text: pd['flowFlag'] == 1 ? '是' : '否',
|
||||
isRequired: true,
|
||||
isEdit: _isEdit,
|
||||
groupValue: (pd['flowFlag'] ?? 0) == 1,
|
||||
onChanged: (val) {
|
||||
setState(() {
|
||||
pd['flowFlag'] = val ? 1 : 0;
|
||||
});
|
||||
},
|
||||
),
|
||||
const Divider(),
|
||||
ItemListWidget.singleLineTitleText(
|
||||
label: '电子邮箱:',
|
||||
isRequired: false,
|
||||
isNumericInput: false,
|
||||
hintText: '请输入电子邮箱',
|
||||
text: pd['email'] ?? '',
|
||||
isEditable: _isEdit,
|
||||
onChanged: (value) {
|
||||
pd['email'] = value;
|
||||
},
|
||||
),
|
||||
const Divider(),
|
||||
ItemListWidget.singleLineTitleText(
|
||||
label: '部门:',
|
||||
isRequired: false,
|
||||
isNumericInput: false,
|
||||
hintText: '',
|
||||
text: pd['departmentName'] ?? '',
|
||||
isEditable: _isEdit,
|
||||
|
||||
),
|
||||
const Divider(),
|
||||
ItemListWidget.singleLineTitleText(
|
||||
label: '岗位(工种):',
|
||||
isRequired: false,
|
||||
isNumericInput: false,
|
||||
hintText: '',
|
||||
text: pd['postName'] ?? '',
|
||||
isEditable: _isEdit,
|
||||
),
|
||||
const Divider(),
|
||||
],
|
||||
) : NoDataWidget.show(),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,249 @@
|
|||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:qhd_prevention/pages/home/unit/unit_join_detail_page.dart';
|
||||
import 'package:qhd_prevention/pages/home/unit/unit_quit_apply_page.dart';
|
||||
import 'package:qhd_prevention/pages/my_appbar.dart';
|
||||
import 'package:qhd_prevention/services/SessionService.dart';
|
||||
import 'package:qhd_prevention/services/StorageService.dart';
|
||||
|
||||
import 'package:qhd_prevention/tools/tools.dart';
|
||||
import 'package:qhd_prevention/customWidget/custom_button.dart';
|
||||
import 'package:qhd_prevention/http/ApiService.dart';
|
||||
|
||||
class UnitJoinListPage extends StatefulWidget {
|
||||
const UnitJoinListPage({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_UnitJoinListPageState createState() => _UnitJoinListPageState();
|
||||
}
|
||||
|
||||
class _UnitJoinListPageState extends State<UnitJoinListPage> {
|
||||
// Data and state variables
|
||||
List<dynamic> list = [];
|
||||
int currentPage = 1;
|
||||
int rows = 10;
|
||||
int totalPage = 1;
|
||||
bool isLoading = false;
|
||||
|
||||
List<Map<String, dynamic>> flowList = [];
|
||||
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
|
||||
final ScrollController _scrollController = ScrollController();
|
||||
final employmentFlag = {'0': '离职', '1': '在职', '3': '未入职'};
|
||||
final statusInfo = {
|
||||
'1': '待审批',
|
||||
'2': '通过',
|
||||
'3': '驳回',
|
||||
};
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_fetchData();
|
||||
_scrollController.addListener(_onScroll);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_scrollController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void _onScroll() {
|
||||
if (_scrollController.position.pixels >=
|
||||
_scrollController.position.maxScrollExtent &&
|
||||
!isLoading) {
|
||||
if (currentPage < totalPage) {
|
||||
currentPage++;
|
||||
_fetchData();
|
||||
}
|
||||
}
|
||||
}
|
||||
String formatDate(String dateTimeStr) {
|
||||
if (dateTimeStr == null || dateTimeStr.isEmpty) {
|
||||
return '';
|
||||
}
|
||||
// 解析字符串为DateTime对象
|
||||
DateTime dateTime = DateTime.parse(dateTimeStr);
|
||||
final time = dateTime == null ? '' : '${dateTime.year}年${dateTime.month}月${dateTime.day}日';
|
||||
// 格式化为年月日
|
||||
return time;
|
||||
}
|
||||
Future<void> _fetchData() async {
|
||||
if (isLoading) return;
|
||||
setState(() => isLoading = true);
|
||||
|
||||
try {
|
||||
|
||||
final data = {
|
||||
'pageIndex': currentPage,
|
||||
'pageSize': rows,
|
||||
'eqUserId': SessionService.instance.accountId
|
||||
};
|
||||
final response = await BasicInfoApi.getFirmListByUser(data);
|
||||
setState(() {
|
||||
if (currentPage == 1) {
|
||||
list = response['data'];
|
||||
} else {
|
||||
list.addAll(response['data']);
|
||||
}
|
||||
Map<String, dynamic> page = response['page'];
|
||||
totalPage = page['totalPage'] ?? 1;
|
||||
isLoading = false;
|
||||
});
|
||||
} catch (e) {
|
||||
print('Error fetching data: $e');
|
||||
setState(() => isLoading = false);
|
||||
}
|
||||
}
|
||||
|
||||
//查看
|
||||
void _goToDetail(Map<String, dynamic> item) async {
|
||||
await pushPage(
|
||||
UnitJoinDetailPage(firmId: item['id'],),
|
||||
context,
|
||||
);
|
||||
_fetchData();
|
||||
}
|
||||
|
||||
// 指派
|
||||
void _leaveFirm(Map<String, dynamic> item) async {
|
||||
await pushPage(
|
||||
UnitQuitApplyPage(firmInfo: item,),
|
||||
context,
|
||||
);
|
||||
_fetchData();
|
||||
}
|
||||
|
||||
|
||||
Widget _buildListItem(Map<String, dynamic> item) {
|
||||
final startTime = formatDate(item['startTime'] ?? '');
|
||||
final endTime = item['employmentFlag'] == 1 ? '至今' : formatDate(item['endTime'] ?? '');
|
||||
return Card(
|
||||
color: Colors.white,
|
||||
margin: const EdgeInsets.all(8.0),
|
||||
child: InkWell(
|
||||
onTap: () => _goToDetail(item),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(12.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
'单位名称:${item['corpinfoName'] ?? ''}',
|
||||
style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
if (startTime.isNotEmpty && endTime.isNotEmpty)
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [Text("就职时间:$startTime - $endTime")],
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [Text("就职状态: ${employmentFlag['${item['employmentFlag']}'] ?? ''}")],
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
"审核状态: ${statusInfo['${item['status']}'] ?? ''}",
|
||||
maxLines: 5,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
_statusButtons(item),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _statusButtons(Map<String, dynamic> item) {
|
||||
final List<Widget> buttons = [];
|
||||
final List<Widget> buttonRowChildren = [];
|
||||
|
||||
buttons.add(
|
||||
CustomButton(
|
||||
text: '查看',
|
||||
backgroundColor: Colors.blue,
|
||||
onPressed: () {
|
||||
_goToDetail(item);
|
||||
},
|
||||
),
|
||||
);
|
||||
if (item['employmentFlag'] == 1) {
|
||||
buttons.add(
|
||||
CustomButton(
|
||||
text: '离职',
|
||||
backgroundColor: Colors.blue,
|
||||
onPressed: () {
|
||||
_leaveFirm(item);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
for (int i = 0; i < buttons.length; i++) {
|
||||
buttonRowChildren.add(
|
||||
Expanded(child: SizedBox(height: 40, child: buttons[i])),
|
||||
);
|
||||
if (i != buttons.length - 1) {
|
||||
buttonRowChildren.add(const SizedBox(width: 10));
|
||||
}
|
||||
}
|
||||
return Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: buttonRowChildren,
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildListContent() {
|
||||
if (isLoading && list.isEmpty) {
|
||||
// 初始加载时显示居中的加载指示器
|
||||
return Center(child: CircularProgressIndicator());
|
||||
} else if (list.isEmpty) {
|
||||
// 没有数据
|
||||
return NoDataWidget.show();
|
||||
} else {
|
||||
// 有数据或加载更多
|
||||
return ListView.builder(
|
||||
padding: EdgeInsets.zero,
|
||||
|
||||
controller: _scrollController,
|
||||
itemCount: list.length + (isLoading ? 1 : 0),
|
||||
itemBuilder: (context, index) {
|
||||
if (index >= list.length) {
|
||||
// 加载更多时在列表底部显示加载指示器
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 16.0),
|
||||
child: Center(child: CircularProgressIndicator()),
|
||||
);
|
||||
}
|
||||
return _buildListItem(list[index]);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
key: _scaffoldKey,
|
||||
appBar: MyAppbar(title: '就职单位', actions: []),
|
||||
|
||||
body: SafeArea(child: _buildListContent()),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,96 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:qhd_prevention/customWidget/custom_button.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/pages/my_appbar.dart';
|
||||
import 'package:qhd_prevention/services/SessionService.dart';
|
||||
import 'package:qhd_prevention/tools/tools.dart';
|
||||
|
||||
class UnitQuitApplyPage extends StatefulWidget {
|
||||
const UnitQuitApplyPage({super.key, required this.firmInfo});
|
||||
|
||||
final Map firmInfo;
|
||||
@override
|
||||
State<UnitQuitApplyPage> createState() => _UnitQuitApplyPageState();
|
||||
}
|
||||
|
||||
class _UnitQuitApplyPageState extends State<UnitQuitApplyPage> {
|
||||
String _resignationReason = '';
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
}
|
||||
|
||||
Future<void> _submit() async {
|
||||
final Map data = {
|
||||
'corpinfoId' : widget.firmInfo['corpinfoId'],
|
||||
'id' : widget.firmInfo['userId'],
|
||||
'resignationReason' : _resignationReason,
|
||||
};
|
||||
LoadingDialogHelper.show();
|
||||
try {
|
||||
final result = await BasicInfoApi.leaveApply(data);
|
||||
LoadingDialogHelper.hide();
|
||||
if (result['success'] == true) {
|
||||
ToastUtil.showNormal(context, '申请已提交');
|
||||
Navigator.pop(context);
|
||||
}else{
|
||||
ToastUtil.showNormal(context, result['errMessage']);
|
||||
}
|
||||
}catch(e){
|
||||
LoadingDialogHelper.hide();
|
||||
ToastUtil.showNormal(context, '申请失败');
|
||||
}
|
||||
|
||||
}
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: MyAppbar(title: '离职申请'),
|
||||
body: SafeArea(
|
||||
child: ItemListWidget.itemContainer(
|
||||
Column(
|
||||
children: [
|
||||
ItemListWidget.singleLineTitleText(
|
||||
label: '离职申请单位',
|
||||
text: widget.firmInfo['corpinfoName'] ?? '',
|
||||
isEditable: false,
|
||||
),
|
||||
const Divider(),
|
||||
ItemListWidget.multiLineTitleTextField(
|
||||
label: '离职原因',
|
||||
isEditable: true,
|
||||
isRequired: false,
|
||||
hintText: '请输入原因',
|
||||
onChanged: (value) {
|
||||
_resignationReason = value;
|
||||
},
|
||||
),
|
||||
const Divider(),
|
||||
ItemListWidget.singleLineTitleText(
|
||||
label: '申请时间',
|
||||
text: DateFormat('yyyy年MM月dd日').format(DateTime.now()),
|
||||
isEditable: false,
|
||||
),
|
||||
const Divider(),
|
||||
ItemListWidget.singleLineTitleText(
|
||||
label: '申请人',
|
||||
text: SessionService.instance.name,
|
||||
isEditable: false,
|
||||
),
|
||||
const Divider(),
|
||||
const SizedBox(height: 30,),
|
||||
CustomButton(text: '提交', onPressed: () {
|
||||
_submit();
|
||||
},)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@ import 'package:flutter/material.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';
|
||||
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';
|
||||
|
|
@ -42,6 +43,11 @@ class _UnitTabPageState extends RouteAwareState<UnitTabPage> {
|
|||
switch (index) {
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
pushPage(UnitJoinListPage(), context);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
_getData();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -131,6 +131,7 @@ class _ForgotPwdPageState extends State<ForgotPwdPage> {
|
|||
}
|
||||
if (!_canSend) return;
|
||||
|
||||
|
||||
setState(() => _isSending = true);
|
||||
LoadingDialogHelper.show();
|
||||
try {
|
||||
|
|
@ -140,7 +141,7 @@ class _ForgotPwdPageState extends State<ForgotPwdPage> {
|
|||
ToastUtil.showNormal(context, '验证码已发送');
|
||||
_startCountdown(60);
|
||||
} else {
|
||||
ToastUtil.showNormal(context, res?['message'] ?? '发送验证码失败');
|
||||
ToastUtil.showNormal(context, res?['errMessage'] ?? '发送验证码失败');
|
||||
}
|
||||
} catch (e) {
|
||||
LoadingDialogHelper.hide();
|
||||
|
|
@ -244,7 +245,6 @@ class _ForgotPwdPageState extends State<ForgotPwdPage> {
|
|||
return null;
|
||||
},
|
||||
),
|
||||
|
||||
const SizedBox(height: 12),
|
||||
|
||||
// 验证码行
|
||||
|
|
|
|||
|
|
@ -0,0 +1,161 @@
|
|||
import 'dart:io';
|
||||
import 'dart:convert';
|
||||
import 'package:qhd_prevention/services/StorageService.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:qhd_prevention/customWidget/custom_alert_dialog.dart';
|
||||
import 'package:qhd_prevention/customWidget/toast_util.dart';
|
||||
import 'package:qhd_prevention/http/ApiService.dart';
|
||||
import 'package:qhd_prevention/pages/main_tab.dart';
|
||||
import 'package:qhd_prevention/pages/my_appbar.dart';
|
||||
import 'package:qhd_prevention/services/SessionService.dart';
|
||||
import 'package:qhd_prevention/services/auth_service.dart';
|
||||
import 'package:qhd_prevention/tools/tools.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
class MineChangeFirmPage extends StatefulWidget {
|
||||
const MineChangeFirmPage({super.key});
|
||||
|
||||
@override
|
||||
State<MineChangeFirmPage> createState() => _MineChangeFirmPageState();
|
||||
}
|
||||
|
||||
class _MineChangeFirmPageState extends State<MineChangeFirmPage> {
|
||||
// 入职企业列表
|
||||
List<dynamic> list = [];
|
||||
String joinedUnitId = '';
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
Map jsonData = json.decode(
|
||||
StorageService.instance.getString('key.saveJoinFirmInfo') ?? '{}',
|
||||
);
|
||||
joinedUnitId = jsonData['unitId'] ?? '';
|
||||
_getList();
|
||||
}
|
||||
|
||||
void _getList() async {
|
||||
LoadingDialogHelper.show();
|
||||
var res = await BasicInfoApi.getJoinFirmList();
|
||||
LoadingDialogHelper.dismiss();
|
||||
if (res['success'] == true) {
|
||||
setState(() {
|
||||
list = res['data'];
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 切换账号
|
||||
Future<void> _changeAccount(dynamic data) async {
|
||||
await CustomAlertDialog.showConfirm(
|
||||
context,
|
||||
title: '温馨提示',
|
||||
content: '确认切换到企业"${data['corpName']}"?',
|
||||
onConfirm: () async {
|
||||
LoadingDialogHelper.show();
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
final phone = prefs.getString('savePhone') ?? '';
|
||||
final pwd = prefs.getString('savePass') ?? '';
|
||||
var params = {'unitId': data['id']};
|
||||
try {
|
||||
var res = await AuthService.gbsLogin(phone, pwd, params);
|
||||
LoadingDialogHelper.dismiss();
|
||||
if (res['success'] == true) {
|
||||
Navigator.pushReplacement(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (_) => const MainPage(isChooseFirm: true),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
ToastUtil.showNormal(context, res['errMessage'] ?? '切换账户失败,请重试');
|
||||
}
|
||||
} catch (e) {
|
||||
LoadingDialogHelper.dismiss();
|
||||
ToastUtil.showNormal(context, '切换账户失败,请重试');
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
// backgroundColor: Colors.white,
|
||||
appBar: MyAppbar(title: '切换账号'),
|
||||
body: Column(
|
||||
children: [
|
||||
Container(
|
||||
width: MediaQuery.of(context).size.width,
|
||||
color: Colors.blue.shade50,
|
||||
padding: const EdgeInsets.symmetric(vertical: 8),
|
||||
// height: 40,
|
||||
child: Center(child: Text('点击企业名称以切换账号')),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Container(
|
||||
height: 40.0 * list.length,
|
||||
width: MediaQuery.of(context).size.width - 24,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
border: Border.all(color: Colors.grey.shade300),
|
||||
),
|
||||
child:
|
||||
list.isEmpty
|
||||
? NoDataWidget.show()
|
||||
: ListView.builder(
|
||||
padding: EdgeInsets.zero,
|
||||
itemCount: list.length,
|
||||
itemBuilder: (context, index) {
|
||||
if (index >= list.length) {
|
||||
// 加载更多时在列表底部显示加载指示器
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 16.0),
|
||||
child: Center(child: CircularProgressIndicator()),
|
||||
);
|
||||
}
|
||||
var data = list[index];
|
||||
return SizedBox(
|
||||
height: 40.0,
|
||||
child: Column(
|
||||
children: [
|
||||
GestureDetector(
|
||||
onTap: () async {
|
||||
_changeAccount(data);
|
||||
},
|
||||
child: SizedBox(
|
||||
height: 39.0,
|
||||
child: Center(
|
||||
child: Row(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.center,
|
||||
children: [
|
||||
Text('${data['corpName'] ?? 'aaaa'}'),
|
||||
if (joinedUnitId ==
|
||||
data['id']) ...[
|
||||
const Icon(
|
||||
Icons.check,
|
||||
size: 20,
|
||||
color: Colors.green,
|
||||
),
|
||||
] else ...[
|
||||
const SizedBox(width: 20),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
if (index < list.length - 1)
|
||||
const Divider(height: 1),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:image_picker/image_picker.dart';
|
||||
import 'package:qhd_prevention/customWidget/custom_button.dart';
|
||||
import 'package:qhd_prevention/customWidget/toast_util.dart';
|
||||
import 'dart:io';
|
||||
import '../../../../../customWidget/photo_picker_row.dart';
|
||||
|
|
@ -274,20 +275,7 @@ class _FeedbackPageState extends State<FeedbackPage> {
|
|||
// 提交按钮
|
||||
SizedBox(
|
||||
width: double.infinity,
|
||||
child: ElevatedButton(
|
||||
onPressed: _submitFeedback,
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: Colors.blue,
|
||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
),
|
||||
child: const Text(
|
||||
'提交',
|
||||
style: TextStyle(fontSize: 18, color: Colors.white),
|
||||
),
|
||||
),
|
||||
child: CustomButton(text: '提交', onPressed: _submitFeedback,)
|
||||
),
|
||||
],
|
||||
),
|
||||
|
|
|
|||
|
|
@ -4,9 +4,11 @@ import 'package:flutter/material.dart';
|
|||
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/scan_page.dart';
|
||||
import 'package:qhd_prevention/pages/home/userinfo_page.dart';
|
||||
import 'package:qhd_prevention/pages/mine/face_ecognition_page.dart';
|
||||
import 'package:qhd_prevention/pages/mine/mine_change_firm_page.dart';
|
||||
import 'package:qhd_prevention/pages/mine/mine_feedback_page.dart';
|
||||
import 'package:qhd_prevention/pages/mine/mine_set_pwd_page.dart';
|
||||
import 'package:qhd_prevention/pages/mine/onboarding_full_page.dart';
|
||||
|
|
@ -107,7 +109,7 @@ class MinePageState extends State<MinePage> {
|
|||
MaterialPageRoute(
|
||||
builder: (context) => const LoginPage(),
|
||||
),
|
||||
(Route<dynamic> route) => false,
|
||||
(Route<dynamic> route) => false,
|
||||
);
|
||||
},
|
||||
);
|
||||
|
|
@ -154,6 +156,69 @@ class MinePageState extends State<MinePage> {
|
|||
);
|
||||
}
|
||||
|
||||
Future<void> _logout() async {
|
||||
|
||||
LoadingDialogHelper.show();
|
||||
|
||||
/// 获取用户在职列表
|
||||
final firmData = await BasicInfoApi.getJoinFirmList();
|
||||
if (firmData['success'] == true) {
|
||||
final firmList = firmData['data'];
|
||||
LoadingDialogHelper.dismiss();
|
||||
if (firmList.isNotEmpty) {
|
||||
CustomAlertDialog.showAlert(
|
||||
context,
|
||||
title: '温馨提示',
|
||||
content: '您目前还有入职信息无法直接注销。\n请先在“就职单位”页面中离职。',
|
||||
);
|
||||
} else {
|
||||
CustomAlertDialog.showConfirm(
|
||||
context,
|
||||
title: '温馨提示',
|
||||
content: '注销后您的所有信息将会被删除\n请确认是否注销。 ',
|
||||
onConfirm: () async {
|
||||
CustomAlertDialog.showInputWithCode(
|
||||
context,
|
||||
title: '手机号:${SessionService.instance.phone}',
|
||||
onGetCode: () async {
|
||||
LoadingDialogHelper.show();
|
||||
final res = await BasicInfoApi.sendRegisterSms({
|
||||
'phone': phone,
|
||||
});
|
||||
LoadingDialogHelper.dismiss();
|
||||
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'] ?? '');
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
} else {
|
||||
LoadingDialogHelper.dismiss();
|
||||
ToastUtil.showNormal(context, firmData['errMessage'] ?? '');
|
||||
}
|
||||
}
|
||||
|
||||
Widget _buildSloganSection() {
|
||||
return Container(
|
||||
margin: EdgeInsets.fromLTRB(0, 100, 0, 0),
|
||||
|
|
@ -180,11 +245,11 @@ class MinePageState extends State<MinePage> {
|
|||
],
|
||||
),
|
||||
const SizedBox(width: 16),
|
||||
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildSettingsList() {
|
||||
return Container(
|
||||
margin: const EdgeInsets.fromLTRB(20, 0, 20, 0),
|
||||
|
|
@ -206,14 +271,18 @@ class MinePageState extends State<MinePage> {
|
|||
title: "我的信息",
|
||||
icon: "assets/images/ico9.png",
|
||||
value: notificationsEnabled,
|
||||
num: 0,
|
||||
onChanged: (value) => setState(() => notificationsEnabled = value!),
|
||||
onChanged: (value) {
|
||||
pushPage(
|
||||
FullUserinfoPage(isEidt: false, isChooseFirm: true),
|
||||
context,
|
||||
);
|
||||
},
|
||||
),
|
||||
|
||||
_buildSettingItem(
|
||||
title: "修改密码",
|
||||
icon: "assets/images/ico16.png",
|
||||
value: notificationsEnabled,
|
||||
num: 1,
|
||||
onChanged: (value) async {
|
||||
await pushPage(MineSetPwdPage('0'), context);
|
||||
},
|
||||
|
|
@ -222,23 +291,38 @@ class MinePageState extends State<MinePage> {
|
|||
title: "扫码入职",
|
||||
icon: "assets/images/ico10.png",
|
||||
value: scanAuthentication,
|
||||
num: 2,
|
||||
onChanged: (value) async {},
|
||||
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,
|
||||
num: 3,
|
||||
onChanged: (value) => setState(() => faceAuthentication = value!),
|
||||
onChanged: (value) {
|
||||
pushPage(
|
||||
const FaceRecognitionPage(
|
||||
studentId: '',
|
||||
data: {},
|
||||
mode: FaceMode.setUpdata,
|
||||
),
|
||||
context,
|
||||
);
|
||||
},
|
||||
),
|
||||
|
||||
_buildSettingItem(
|
||||
title: "证书信息",
|
||||
icon: "assets/images/ico12.png",
|
||||
value: passwordChanged,
|
||||
num: 4,
|
||||
onChanged: (value) => setState(() => passwordChanged = value!),
|
||||
),
|
||||
|
||||
|
|
@ -246,7 +330,6 @@ class MinePageState extends State<MinePage> {
|
|||
title: "问题反馈",
|
||||
icon: "assets/images/ico13.png",
|
||||
value: passwordChanged,
|
||||
num: 5,
|
||||
onChanged: (value) => setState(() => passwordChanged = value!),
|
||||
),
|
||||
|
||||
|
|
@ -255,7 +338,6 @@ class MinePageState extends State<MinePage> {
|
|||
title: "版本更新",
|
||||
icon: "assets/images/ico14.png",
|
||||
value: updateAvailable,
|
||||
num: 6,
|
||||
onChanged: (value) => setState(() => updateAvailable = value!),
|
||||
),
|
||||
|
||||
|
|
@ -263,21 +345,24 @@ class MinePageState extends State<MinePage> {
|
|||
title: "关于我们",
|
||||
icon: "assets/images/ico15.png",
|
||||
value: logoutSelected,
|
||||
num: 7,
|
||||
onChanged: (value) {
|
||||
setState(() => logoutSelected = value!);
|
||||
// if (value == true) {
|
||||
// _showLogoutConfirmation();
|
||||
// }
|
||||
},
|
||||
),
|
||||
_buildSettingItem(
|
||||
title: "切换账户",
|
||||
icon: "assets/images/ico15.png",
|
||||
value: logoutSelected,
|
||||
onChanged: (value) {
|
||||
pushPage(MineChangeFirmPage(), context);
|
||||
},
|
||||
),
|
||||
_buildSettingItem(
|
||||
title: "账户注销",
|
||||
icon: "assets/images/ico15.png",
|
||||
value: logoutSelected,
|
||||
num: 8,
|
||||
onChanged: (value) {
|
||||
|
||||
_logout();
|
||||
},
|
||||
),
|
||||
],
|
||||
|
|
@ -289,53 +374,11 @@ class MinePageState extends State<MinePage> {
|
|||
required String title,
|
||||
required String icon,
|
||||
required bool value,
|
||||
required int num,
|
||||
required ValueChanged<bool?> onChanged,
|
||||
}) {
|
||||
return GestureDetector(
|
||||
onTap: () async {
|
||||
switch (num) {
|
||||
case 0:
|
||||
pushPage(FullUserinfoPage(isEidt: false, isChooseFirm: true,), context);
|
||||
break;
|
||||
case 1:
|
||||
await pushPage(MineSetPwdPage('0'), context);
|
||||
|
||||
break;
|
||||
case 2:
|
||||
final result = await pushPage(
|
||||
ScanPage(type: ScanType.Onboarding),
|
||||
context,
|
||||
);
|
||||
if (result == null) {
|
||||
return;
|
||||
}
|
||||
pushPage(OnboardingFullPage(scanData: result), context);
|
||||
|
||||
break;
|
||||
|
||||
case 3:
|
||||
pushPage(
|
||||
const FaceRecognitionPage(
|
||||
studentId: '',
|
||||
data: {},
|
||||
mode: FaceMode.setUpdata,
|
||||
),
|
||||
context,
|
||||
);
|
||||
// pushPage(ChangePassPage(), context);
|
||||
break;
|
||||
case 4:
|
||||
// _showLogoutConfirmation();
|
||||
break;
|
||||
case 5:
|
||||
pushPage(FeedbackPage(), context);
|
||||
break;
|
||||
case 6:
|
||||
break;
|
||||
case 7:
|
||||
break;
|
||||
}
|
||||
onChanged(value);
|
||||
},
|
||||
child: ListTile(
|
||||
leading: Container(
|
||||
|
|
@ -366,84 +409,8 @@ class MinePageState extends State<MinePage> {
|
|||
);
|
||||
}
|
||||
|
||||
Widget _buildActionButton() {
|
||||
return SizedBox(
|
||||
width: double.infinity,
|
||||
child: ElevatedButton(
|
||||
onPressed: () {
|
||||
// 保存设置逻辑
|
||||
_saveSettings();
|
||||
},
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: const Color(0xFF1A237E),
|
||||
foregroundColor: Colors.white,
|
||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
elevation: 3, // 注意:elevation应该放在styleFrom内部
|
||||
),
|
||||
child: const Text(
|
||||
"保存设置",
|
||||
style: TextStyle(fontSize: 18, fontWeight: FontWeight.w600),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _saveSettings() {
|
||||
// 这里可以添加保存设置到服务器的逻辑
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: const Text("设置已保存成功"),
|
||||
backgroundColor: Colors.green[700],
|
||||
duration: const Duration(seconds: 2),
|
||||
behavior: SnackBarBehavior.floating,
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _clearUserSession() async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
await prefs.remove('isLoggedIn'); // 清除登录状态
|
||||
}
|
||||
}
|
||||
|
||||
class _StatItem extends StatelessWidget {
|
||||
final String number;
|
||||
final String label;
|
||||
|
||||
const _StatItem({required this.number, required this.label});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
children: [
|
||||
// 数字圆圈
|
||||
Center(
|
||||
child: Text(
|
||||
number,
|
||||
style: const TextStyle(
|
||||
color: Colors.black,
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
const SizedBox(height: 8),
|
||||
|
||||
// 标签
|
||||
Text(
|
||||
label,
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: Colors.grey[600],
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,13 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:qhd_prevention/customWidget/bottom_picker.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/toast_util.dart';
|
||||
import 'package:qhd_prevention/http/modules/basic_info_api.dart';
|
||||
import 'package:qhd_prevention/pages/main_tab.dart';
|
||||
import 'package:qhd_prevention/pages/my_appbar.dart';
|
||||
import 'package:qhd_prevention/pages/user/login_page.dart';
|
||||
import 'package:qhd_prevention/services/SessionService.dart';
|
||||
import 'package:qhd_prevention/services/auth_service.dart';
|
||||
import 'package:qhd_prevention/tools/tools.dart';
|
||||
|
|
@ -13,20 +15,25 @@ import 'package:shared_preferences/shared_preferences.dart';
|
|||
|
||||
class OnboardingFullPage extends StatefulWidget {
|
||||
const OnboardingFullPage({super.key, required this.scanData});
|
||||
|
||||
final Map scanData;
|
||||
|
||||
@override
|
||||
State<OnboardingFullPage> createState() => _OnboardingFullPageState();
|
||||
}
|
||||
|
||||
class _OnboardingFullPageState extends State<OnboardingFullPage> {
|
||||
Map<String, dynamic> pd = {};
|
||||
// 部门列表
|
||||
|
||||
// 部门列表
|
||||
List<dynamic> _deptList = [];
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_getDept();
|
||||
}
|
||||
|
||||
// 获取部门
|
||||
Future<void> _getDept() async {
|
||||
try {
|
||||
|
|
@ -36,57 +43,57 @@ class _OnboardingFullPageState extends State<OnboardingFullPage> {
|
|||
};
|
||||
final result = await BasicInfoApi.getDeptTree(data);
|
||||
if (result['success'] == true) {
|
||||
_deptList = result['data'];
|
||||
final list = result['data'] ?? [];
|
||||
if (list.length > 0) {
|
||||
setState(() {
|
||||
_deptList = list[0]['childrenList'] ?? [];
|
||||
});
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
}
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
// 提交
|
||||
Future<void> _saveSuccess() async {
|
||||
if (!FormUtils.hasValue(pd, 'corpinfoId')) {
|
||||
ToastUtil.showNormal(context, '请选择部门');
|
||||
return;
|
||||
}
|
||||
if (!FormUtils.hasValue(pd, 'postName')) {
|
||||
ToastUtil.showNormal(context, '请输入岗位');
|
||||
return;
|
||||
}
|
||||
LoadingDialogHelper.show();
|
||||
pd['id'] = widget.scanData['id'];
|
||||
try {
|
||||
final result = await BasicInfoApi.userFirmEntry(pd);
|
||||
LoadingDialogHelper.hide();
|
||||
if (result['success'] == true) {
|
||||
ToastUtil.showNormal(context, '操作成功');
|
||||
_relogin();
|
||||
}
|
||||
} catch (e) {
|
||||
LoadingDialogHelper.hide();
|
||||
ToastUtil.showNormal(context, '操作成功');
|
||||
}
|
||||
}
|
||||
/// 重新登录
|
||||
Future<void> _relogin() async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
final username = prefs.getString('savePhone') ?? '';
|
||||
final password = prefs.getString('savePass') ?? '';
|
||||
|
||||
try {
|
||||
Map data = {
|
||||
'id': widget.scanData['id'] ?? '',
|
||||
'corpinfoId':widget.scanData['corpinfoId'] ?? '',
|
||||
};
|
||||
final result = await AuthService.gbsLogin(username, password, data);
|
||||
if (result['success'] == true) {
|
||||
Navigator.pushReplacement(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (_) => const MainPage(isChooseFirm: true,)),
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
ToastUtil.showNormal(context, '重新登录失败');
|
||||
if (!FormUtils.hasValue(pd, 'corpinfoId')) {
|
||||
ToastUtil.showNormal(context, '请选择部门');
|
||||
return;
|
||||
}
|
||||
if (!FormUtils.hasValue(pd, 'postName')) {
|
||||
ToastUtil.showNormal(context, '请输入岗位');
|
||||
return;
|
||||
}
|
||||
await CustomAlertDialog.showConfirm(
|
||||
context,
|
||||
title: '温馨提示',
|
||||
content: '确定加入${widget.scanData['corpName'] ?? ''}?',
|
||||
onConfirm: () async {
|
||||
LoadingDialogHelper.show();
|
||||
pd['id'] = SessionService.instance.accountId;
|
||||
try {
|
||||
final result = await BasicInfoApi.userFirmEntry(pd);
|
||||
LoadingDialogHelper.hide();
|
||||
if (result['success'] == true) {
|
||||
ToastUtil.showNormal(context, '申请成功');
|
||||
_relogin();
|
||||
} else {
|
||||
ToastUtil.showNormal(context, result['errMessage']);
|
||||
}
|
||||
} catch (e) {
|
||||
LoadingDialogHelper.hide();
|
||||
ToastUtil.showNormal(context, '操作失败,请重试');
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/// 回到首页
|
||||
Future<void> _relogin() async {
|
||||
bool isChooseFirm = (SessionService.instance.token ?? '').isNotEmpty;
|
||||
Navigator.pushReplacement(
|
||||
context,
|
||||
MaterialPageRoute(builder: (_) => MainPage(isChooseFirm: isChooseFirm)),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
@ -98,6 +105,11 @@ class _OnboardingFullPageState extends State<OnboardingFullPage> {
|
|||
horizontal: 5,
|
||||
ListView(
|
||||
children: [
|
||||
ItemListWidget.singleLineTitleText(
|
||||
label: '企业名称',
|
||||
isEditable: false,
|
||||
text: widget.scanData['corpName'] ?? '',
|
||||
),
|
||||
ItemListWidget.selectableLineTitleTextRightButton(
|
||||
verticalInset: 15,
|
||||
label: '选择入职部门:',
|
||||
|
|
@ -113,8 +125,7 @@ class _OnboardingFullPageState extends State<OnboardingFullPage> {
|
|||
context,
|
||||
items: _deptList,
|
||||
itemBuilder:
|
||||
(i) =>
|
||||
Text(i['name']!, textAlign: TextAlign.center),
|
||||
(i) => Text(i['name']!, textAlign: TextAlign.center),
|
||||
initialIndex: 0,
|
||||
);
|
||||
//FocusHelper.clearFocus(context);
|
||||
|
|
@ -125,7 +136,6 @@ class _OnboardingFullPageState extends State<OnboardingFullPage> {
|
|||
pd['departmentName'] = found['name'];
|
||||
pd['corpinfoId'] = found['corpinfoId'];
|
||||
pd['corpinfoName'] = found['corpinfoName'];
|
||||
|
||||
});
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -53,8 +53,7 @@ class _ChooseUserfirmPageState extends State<ChooseUserfirmPage> {
|
|||
return;
|
||||
}
|
||||
final params = {
|
||||
'corpId': widget.firms[_selectedIndex]['id'],
|
||||
'corpName': widget.firms[_selectedIndex]['corpName'],
|
||||
'unitId': widget.firms[_selectedIndex]['id'],
|
||||
};
|
||||
LoadingDialogHelper.show();
|
||||
final result = await AuthService.gbsLogin(widget.userName, widget.password, params);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:qhd_prevention/customWidget/search_bar_widget.dart';
|
||||
import 'package:qhd_prevention/http/ApiService.dart';
|
||||
import 'package:qhd_prevention/pages/main_tab.dart';
|
||||
import 'package:qhd_prevention/pages/mine/onboarding_full_page.dart';
|
||||
import 'package:qhd_prevention/pages/my_appbar.dart';
|
||||
|
||||
|
|
@ -9,7 +10,9 @@ import 'package:lpinyin/lpinyin.dart';
|
|||
import 'package:qhd_prevention/tools/tools.dart';
|
||||
|
||||
class FirmListPage extends StatefulWidget {
|
||||
const FirmListPage({super.key});
|
||||
const FirmListPage({super.key, required this.isBack});
|
||||
|
||||
final bool isBack;
|
||||
|
||||
@override
|
||||
State<FirmListPage> createState() => _FirmListPageState();
|
||||
|
|
@ -274,11 +277,29 @@ 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 - 100;
|
||||
return Scaffold(
|
||||
backgroundColor: Colors.white,
|
||||
|
||||
appBar: MyAppbar(title: '选择企业'),
|
||||
appBar: MyAppbar(
|
||||
title: '选择企业',
|
||||
isBack: widget.isBack,
|
||||
actions: [
|
||||
if (!widget.isBack)
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Navigator.pushReplacement(
|
||||
context,
|
||||
MaterialPageRoute(builder: (_) => MainPage(isChooseFirm: false)),
|
||||
);
|
||||
},
|
||||
child: const Text(
|
||||
'跳过',
|
||||
style: TextStyle(color: Colors.white, fontSize: 17),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
body: SafeArea(
|
||||
child: Column(
|
||||
children: [
|
||||
|
|
|
|||
|
|
@ -15,9 +15,11 @@ import 'package:qhd_prevention/http/ApiService.dart';
|
|||
import 'package:qhd_prevention/pages/main_tab.dart';
|
||||
import 'package:qhd_prevention/pages/mine/face_ecognition_page.dart';
|
||||
import 'package:qhd_prevention/pages/my_appbar.dart';
|
||||
import 'package:qhd_prevention/pages/user/firm_list_page.dart';
|
||||
import 'package:qhd_prevention/services/SessionService.dart';
|
||||
import 'package:qhd_prevention/tools/id_cart_util.dart';
|
||||
import 'package:qhd_prevention/tools/tools.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
class FullUserinfoPage extends StatefulWidget {
|
||||
const FullUserinfoPage({super.key, required this.isEidt, required this.isChooseFirm});
|
||||
|
|
@ -61,6 +63,7 @@ class _FullUserinfoPageState extends State<FullUserinfoPage> {
|
|||
String _genderText = '';
|
||||
String _birthText = '';
|
||||
String _idValue = '';
|
||||
String? _userId = SessionService.instance.userId;
|
||||
List<String> _idCardImgList = [];
|
||||
List<String> _idCartImgIds = [];
|
||||
/// 是否修改了身份证
|
||||
|
|
@ -83,7 +86,6 @@ class _FullUserinfoPageState extends State<FullUserinfoPage> {
|
|||
if (!_isEdit) {
|
||||
_getUserDetail();
|
||||
} else {
|
||||
pd['username'] = SessionService.instance.userName;
|
||||
pd['id'] = SessionService.instance.accountId;
|
||||
pd['flowFlag'] = 0;
|
||||
}
|
||||
|
|
@ -129,12 +131,18 @@ class _FullUserinfoPageState extends State<FullUserinfoPage> {
|
|||
}
|
||||
|
||||
Future<void> _getKeyValues() async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
final phone = await prefs.getString("savePhone");
|
||||
pd['username'] = phone;
|
||||
await BasicInfoApi.getDictValues('wenhuachengdu').then((res) {
|
||||
_wenhuachengduList = res['data'];
|
||||
});
|
||||
await BasicInfoApi.getDictValues('zhengzhimianmao').then((res) {
|
||||
_zhengzhimianmaoList = res['data'];
|
||||
});
|
||||
setState(() {
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> _saveSuccess() async {
|
||||
|
|
@ -160,7 +168,7 @@ class _FullUserinfoPageState extends State<FullUserinfoPage> {
|
|||
return;
|
||||
}
|
||||
LoadingDialogHelper.show();
|
||||
// 签字上传
|
||||
// 人脸上传
|
||||
final signResult = await _checkFaceImage();
|
||||
// 证件上传图片
|
||||
final situationResult = await _checkIDCartImages();
|
||||
|
|
@ -173,12 +181,13 @@ class _FullUserinfoPageState extends State<FullUserinfoPage> {
|
|||
LoadingDialogHelper.hide();
|
||||
if (res['success']) {
|
||||
ToastUtil.showNormal(context, '保存成功');
|
||||
bool ischange = _isChange ? true: false;
|
||||
Navigator.pushReplacement(
|
||||
context,
|
||||
MaterialPageRoute(builder: (_) => const MainPage(isChooseFirm: false)),
|
||||
MaterialPageRoute(builder: (_) => FirmListPage(isBack: false,)),
|
||||
);
|
||||
} else {
|
||||
ToastUtil.showNormal(context, '保存失败');
|
||||
ToastUtil.showNormal(context, res['errMessage']);
|
||||
}
|
||||
});
|
||||
}else{
|
||||
|
|
@ -211,7 +220,7 @@ class _FullUserinfoPageState extends State<FullUserinfoPage> {
|
|||
late bool isSuccess = true;
|
||||
if (faceImgPath.isNotEmpty) {
|
||||
try {
|
||||
await FileApi.uploadFile(faceImgPath, fileType, '').then((result) {
|
||||
await FileApi.uploadFile(faceImgPath, fileType, _userId ?? '').then((result) {
|
||||
if (result['success']) {
|
||||
pd['userAvatarUrl'] = result['data']['filePath'] ?? '';
|
||||
isSuccess = true;
|
||||
|
|
@ -223,7 +232,7 @@ class _FullUserinfoPageState extends State<FullUserinfoPage> {
|
|||
});
|
||||
} catch (e) {
|
||||
LoadingDialogHelper.hide();
|
||||
ToastUtil.showNormal(context, '签名上传失败');
|
||||
ToastUtil.showNormal(context, '人脸照片上传失败');
|
||||
isSuccess = false;
|
||||
}
|
||||
}
|
||||
|
|
@ -241,10 +250,9 @@ class _FullUserinfoPageState extends State<FullUserinfoPage> {
|
|||
await FileApi.uploadFiles(
|
||||
idPhotos,
|
||||
UploadFileType.idCardPhoto,
|
||||
pd['userId'] ?? '',
|
||||
_userId ?? '',
|
||||
).then((result) {
|
||||
if (result['success']) {
|
||||
pd['userId'] = result['data']['foreignKey'] ?? '';
|
||||
} else {
|
||||
LoadingDialogHelper.hide();
|
||||
ToastUtil.showNormal(context, '图片上传失败');
|
||||
|
|
@ -282,8 +290,6 @@ class _FullUserinfoPageState extends State<FullUserinfoPage> {
|
|||
});
|
||||
} else {
|
||||
// 解析失败或校验位不正确 — 清除解析字段但保留输入
|
||||
ToastUtil.showNormal(context, '请输入正确格式身份证号');
|
||||
|
||||
setState(() {
|
||||
pd.remove('birthday');
|
||||
pd.remove('age');
|
||||
|
|
|
|||
|
|
@ -67,13 +67,18 @@ class _LoginPageState extends State<LoginPage> {
|
|||
}
|
||||
|
||||
Future<void> _getCaptcha() async {
|
||||
final response = await AuthApi.getUserCaptcha();
|
||||
if (response['success']) {
|
||||
setState(() {
|
||||
_captchaImageBase64 = response['data']['img'];
|
||||
_captchaIdentifier = response['data']['captchaKey'];
|
||||
});
|
||||
try{
|
||||
final response = await AuthApi.getUserCaptcha();
|
||||
if (response['success']) {
|
||||
setState(() {
|
||||
_captchaImageBase64 = response['data']['img'];
|
||||
_captchaIdentifier = response['data']['captchaKey'];
|
||||
});
|
||||
}
|
||||
}catch(e){
|
||||
print(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Future<void> _getData() async {
|
||||
|
|
@ -122,7 +127,7 @@ class _LoginPageState extends State<LoginPage> {
|
|||
children: [
|
||||
const SizedBox(height: 70), // 顶部间距
|
||||
Image.asset(
|
||||
"assets/images/logo.png",
|
||||
"assets/images/g_logo.png",
|
||||
width: 40,
|
||||
height: 40,
|
||||
),
|
||||
|
|
@ -282,17 +287,14 @@ class _LoginPageState extends State<LoginPage> {
|
|||
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 25,
|
||||
horizontal: 10,
|
||||
),
|
||||
child: _buildCaptchaImage(),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const Divider(
|
||||
height: 0.5,
|
||||
color: Colors.black26,
|
||||
),
|
||||
const Divider(),
|
||||
|
||||
const SizedBox(height: 10),
|
||||
|
||||
|
|
|
|||
|
|
@ -167,7 +167,9 @@ class _RegisterPageState extends State<RegisterPage> {
|
|||
'newPassword': pwd,
|
||||
'confirmPassword': pwd,
|
||||
};
|
||||
LoadingDialogHelper.show();
|
||||
final resp = await BasicInfoApi.register(data);
|
||||
LoadingDialogHelper.hide();
|
||||
|
||||
if (resp != null && resp['success'] == true) {
|
||||
ToastUtil.showNormal(context, '注册成功,请登录');
|
||||
|
|
@ -181,6 +183,7 @@ class _RegisterPageState extends State<RegisterPage> {
|
|||
ToastUtil.showNormal(context, resp?['message'] ?? '注册失败,请重试');
|
||||
}
|
||||
} catch (e) {
|
||||
LoadingDialogHelper.hide();
|
||||
ToastUtil.showNormal(context, '注册失败,请稍后重试');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import 'dart:convert';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:qhd_prevention/tools/tools.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
class BizAttr {
|
||||
|
|
@ -342,8 +343,8 @@ class SessionService {
|
|||
|
||||
/// 从完整的API响应更新会话数据
|
||||
void updateFromApiResponse(Map<String, dynamic> responseJson) {
|
||||
if (responseJson['data'] != null) {
|
||||
userData = UserData.fromJson(responseJson['data'] as Map<String, dynamic>);
|
||||
if (responseJson != null) {
|
||||
userData = UserData.fromJson(responseJson);
|
||||
}
|
||||
// 注意:token可能需要从响应头或其他地方单独设置
|
||||
}
|
||||
|
|
@ -401,6 +402,7 @@ class SessionService {
|
|||
print('姓名: ${userData!.name}');
|
||||
print('部门: ${userData!.departmentName}');
|
||||
print('租户ID: ${userData!.tenantId}');
|
||||
// printLongString(text)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,14 +29,20 @@ class AuthService {
|
|||
return {};
|
||||
}
|
||||
final resData = res['data'];
|
||||
if (resData == null) {
|
||||
Fluttertoast.showToast(msg: '登录失败');
|
||||
return {};
|
||||
}
|
||||
bool isInfoComplete = resData['isInfoComplete'] ?? false;
|
||||
List firmList = resData['corpInfoCOList'] ?? [];
|
||||
/// 保存用户信息
|
||||
SessionService.instance.updateFromApiResponse(resData['userCO']);
|
||||
await SessionService.instance.saveToPrefs();
|
||||
|
||||
if (firmList.length == 1 && isInfoComplete) {
|
||||
// 入职一个企业直接进行底座登录传入企业
|
||||
Map data = {
|
||||
'id': firmList.first['id'] ?? '',
|
||||
'corpinfoId': firmList.first['corpinfoId'] ?? '',
|
||||
'unitId': firmList.first['id'] ?? '',
|
||||
};
|
||||
return AuthService.gbsLogin(username, password, data);
|
||||
} else if (firmList.length > 1) {
|
||||
|
|
@ -94,6 +100,7 @@ class AuthService {
|
|||
_data['password'] = encrypted;
|
||||
// printLongString(jsonEncode(_data));
|
||||
final result = await AuthApi.loginCheck(_data);
|
||||
|
||||
final success = result['success'] as bool;
|
||||
if (!success) {
|
||||
Fluttertoast.showToast(msg: result['errMessage'] ?? '');
|
||||
|
|
@ -116,11 +123,25 @@ class AuthService {
|
|||
json.encode(params),
|
||||
);
|
||||
|
||||
await AuthApi.getUserData().then((result) async {
|
||||
SessionService.instance.updateFromApiResponse(result);
|
||||
await SessionService.instance.saveToPrefs();
|
||||
SessionService.instance.setToken(token);
|
||||
});
|
||||
try {
|
||||
await AuthApi.getUserData().then((result) async {
|
||||
if (!result['success']) {
|
||||
LoadingDialogHelper.hide();
|
||||
Fluttertoast.showToast(msg: result['errMessage'] ?? '');
|
||||
return {};
|
||||
}
|
||||
SessionService.instance.updateFromApiResponse(result['data']);
|
||||
await SessionService.instance.saveToPrefs();
|
||||
SessionService.instance.setToken(token);
|
||||
SessionService.instance.printUserInfo();
|
||||
|
||||
});
|
||||
} catch (e) {
|
||||
LoadingDialogHelper.hide();
|
||||
Fluttertoast.showToast(msg: '用户信息获取失败,请重试');
|
||||
return {};
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -316,6 +316,17 @@ class LoadingDialogHelper {
|
|||
_timer?.cancel();
|
||||
_timer = null;
|
||||
|
||||
try {
|
||||
EasyLoading.dismiss();
|
||||
} catch (e) {
|
||||
debugPrint('EasyLoading.dismiss error: $e');
|
||||
}
|
||||
}
|
||||
static void dismiss() {
|
||||
// 清理计时器
|
||||
_timer?.cancel();
|
||||
_timer = null;
|
||||
|
||||
try {
|
||||
EasyLoading.dismiss();
|
||||
} catch (e) {
|
||||
|
|
|
|||
|
|
@ -32,9 +32,13 @@ environment:
|
|||
# ios: true
|
||||
# image_path: "assets/images/app-logo.png"
|
||||
# min_sdk_android: 21 # (可选) Android 最低支持
|
||||
flutter_launcher_icons:
|
||||
android: true
|
||||
ios: true
|
||||
image_path: "assets/images/logo.png"
|
||||
|
||||
flutter_native_splash:
|
||||
background_image: assets/images/bg-login.png
|
||||
background_image: assets/images/lun.jpg
|
||||
android: true
|
||||
ios: true
|
||||
web: false
|
||||
|
|
|
|||