统一用户暂存

master
hs 2025-12-24 16:07:53 +08:00
parent d39a355ede
commit bb4bf15dc6
58 changed files with 1609 additions and 406 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 345 KiB

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 345 KiB

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.9 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 299 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 334 KiB

View File

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 77 KiB

After

Width:  |  Height:  |  Size: 363 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 802 B

After

Width:  |  Height:  |  Size: 950 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.7 KiB

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.1 KiB

After

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 KiB

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.6 KiB

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.1 KiB

After

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.9 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.5 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 345 KiB

After

Width:  |  Height:  |  Size: 1.3 MiB

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -17,7 +17,6 @@ class FileApi {
}
final fileName = file.path.split(Platform.pathSeparator).last;
return HttpManager().uploadImages(
baseUrl: ApiService.basePath,
path: '/basicInfo/imgFiles/save',

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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),
//

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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, '注册失败,请稍后重试');
}
}

View File

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

View File

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

View File

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

View File

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