11
This commit is contained in:
1 parent
60d9380a65
commit
fe6d988fa3
46 files changed
+5738
-1013
No files matched your search
@@ -1,6 +1,7 @@
|
||||
import 'package:common_utils/common_utils.dart';
|
||||
import 'package:ducafe_ui_core/ducafe_ui_core.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:forui/forui.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
@@ -55,3 +56,197 @@ Future<bool> settingPasswordDialog(BuildContext context) async {
|
||||
);
|
||||
return flag ?? false;
|
||||
}
|
||||
|
||||
/// 终端顶栏管理操作(进入设置、退出登录、唤醒终端)共用的二次验证。
|
||||
///
|
||||
/// 校验来源与主菜单的设置入口一致:当前登录账号的登录密码。
|
||||
Future<bool> terminalAdminPasswordDialog(
|
||||
BuildContext context, {
|
||||
required String actionLabel,
|
||||
}) async {
|
||||
final appUserSetting = await AppSettingTool.getUserSetting();
|
||||
final result = await showAppDialog<bool>(
|
||||
context: context,
|
||||
barrierDismissible: false,
|
||||
canPop: false,
|
||||
builder: (_) => _TerminalAdminPasswordDialog(
|
||||
actionLabel: actionLabel,
|
||||
expectedPassword: appUserSetting.password,
|
||||
),
|
||||
);
|
||||
return result ?? false;
|
||||
}
|
||||
|
||||
class _TerminalAdminPasswordDialog extends StatefulWidget {
|
||||
const _TerminalAdminPasswordDialog({
|
||||
required this.actionLabel,
|
||||
required this.expectedPassword,
|
||||
});
|
||||
|
||||
final String actionLabel;
|
||||
|
||||
final String? expectedPassword;
|
||||
|
||||
@override
|
||||
State<_TerminalAdminPasswordDialog> createState() =>
|
||||
_TerminalAdminPasswordDialogState();
|
||||
}
|
||||
|
||||
class _TerminalAdminPasswordDialogState
|
||||
extends State<_TerminalAdminPasswordDialog> {
|
||||
late final TextEditingController _controller;
|
||||
bool _obscureText = true;
|
||||
bool _closing = false;
|
||||
String? _errorText;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_controller = TextEditingController();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_controller.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void _submit() {
|
||||
if (_closing) return;
|
||||
final password = _controller.text.trim();
|
||||
if (password.isEmpty) {
|
||||
setState(() => _errorText = '请输入管理密码');
|
||||
return;
|
||||
}
|
||||
if (password != widget.expectedPassword) {
|
||||
setState(() => _errorText = '管理密码不正确,请重新输入');
|
||||
HapticFeedback.mediumImpact();
|
||||
return;
|
||||
}
|
||||
_close(true);
|
||||
}
|
||||
|
||||
void _close(bool result) {
|
||||
if (_closing) return;
|
||||
_closing = true;
|
||||
// 先释放输入法焦点,再由路由守卫等待弹窗退场后切换页面,避免 Overlay 与根路由同时拆除。
|
||||
FocusManager.instance.primaryFocus?.unfocus();
|
||||
Navigator.of(context).pop(result);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = FTheme.of(context);
|
||||
return AppDialog(
|
||||
title: Text(
|
||||
'终端操作验证',
|
||||
style: theme.typography.xl2.copyWith(
|
||||
color: XfjDesignTokens.ink,
|
||||
fontWeight: FontWeight.w800,
|
||||
height: 1,
|
||||
),
|
||||
),
|
||||
leading: Container(
|
||||
width: 48.w,
|
||||
height: 48.w,
|
||||
alignment: Alignment.center,
|
||||
decoration: BoxDecoration(
|
||||
color: XfjDesignTokens.primarySoft,
|
||||
borderRadius: BorderRadius.circular(XfjDesignTokens.controlRadius),
|
||||
),
|
||||
child: FIcon(
|
||||
FAssets.icons.shieldCheck,
|
||||
color: XfjDesignTokens.primary,
|
||||
size: 24.sp,
|
||||
),
|
||||
),
|
||||
width: 680.w,
|
||||
maxWidth: 680.w,
|
||||
contentPadding: EdgeInsets.symmetric(horizontal: 28.w, vertical: 36.h),
|
||||
onClose: () => _close(false),
|
||||
semanticLabel: '${widget.actionLabel}管理密码验证弹框',
|
||||
content: SizedBox(
|
||||
width: double.infinity,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'${widget.actionLabel}前需要验证管理密码。',
|
||||
style: theme.typography.base.copyWith(
|
||||
color: XfjDesignTokens.muted,
|
||||
),
|
||||
),
|
||||
SizedBox(height: 16.h),
|
||||
FTextField.password(
|
||||
controller: _controller,
|
||||
autofocus: true,
|
||||
label: const Text('管理密码'),
|
||||
hint: '请输入管理密码',
|
||||
maxLines: 1,
|
||||
obscureText: _obscureText,
|
||||
keyboardType: TextInputType.number,
|
||||
textInputAction: TextInputAction.done,
|
||||
inputFormatters: [
|
||||
FilteringTextInputFormatter.digitsOnly,
|
||||
],
|
||||
onChange: (_) {
|
||||
if (_errorText != null) setState(() => _errorText = null);
|
||||
},
|
||||
onSubmit: (_) => _submit(),
|
||||
suffixBuilder: (_, __, ___) => InkWell(
|
||||
onTap: () => setState(() => _obscureText = !_obscureText),
|
||||
borderRadius: BorderRadius.circular(
|
||||
XfjDesignTokens.controlRadius,
|
||||
),
|
||||
child: SizedBox(
|
||||
width: 48.w,
|
||||
height: 48.h,
|
||||
child: FIcon(
|
||||
_obscureText ? FAssets.icons.eye : FAssets.icons.eyeOff,
|
||||
color: XfjDesignTokens.muted,
|
||||
size: 22.sp,
|
||||
).center(),
|
||||
),
|
||||
),
|
||||
),
|
||||
if (_errorText != null) ...[
|
||||
SizedBox(height: 8.h),
|
||||
Row(
|
||||
children: [
|
||||
FIcon(
|
||||
FAssets.icons.circleAlert,
|
||||
color: XfjDesignTokens.danger,
|
||||
size: 18.sp,
|
||||
),
|
||||
SizedBox(width: 8.w),
|
||||
Text(
|
||||
_errorText!,
|
||||
style: theme.typography.sm.copyWith(
|
||||
color: XfjDesignTokens.danger,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
actions: [
|
||||
FButton(
|
||||
style: FButtonStyle.outline,
|
||||
label: Text('取消', style: theme.typography.base),
|
||||
onPress: () => _close(false),
|
||||
),
|
||||
FButton(
|
||||
label: Text(
|
||||
'验证并继续',
|
||||
style: theme.typography.base.copyWith(color: Colors.white),
|
||||
),
|
||||
onPress: _submit,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user