feat: 新增重置密码功能并完善密码校验逻辑
1. 新增加速度传感器设备不稳定错误提示 2. 新增多套密码校验规则与多语言文案 3. 重构个人页面与密码设置面板的校验逻辑 4. 优化设备状态错误展示与UI布局 5. 新增重置密码相关的UI资源与逻辑
This commit is contained in:
parent
4c253a419e
commit
4d0448c80d
@ -1548,6 +1548,51 @@
|
||||
"key": "100310",
|
||||
"zh": "已同步 {0} 条记录",
|
||||
"en": "{0} records synced"
|
||||
},
|
||||
{
|
||||
"key": "100311",
|
||||
"zh": "设备不稳定",
|
||||
"en": "Device unstable"
|
||||
},
|
||||
{
|
||||
"key": "100312",
|
||||
"zh": "密码长度6位,仅允许使用数字字符",
|
||||
"en": "Fixed 6-digit numeric password only."
|
||||
},
|
||||
{
|
||||
"key": "100313",
|
||||
"zh": "密码长度8-16位,不能有空格;",
|
||||
"en": "8–16 characters, no spaces. "
|
||||
},
|
||||
{
|
||||
"key": "100314",
|
||||
"zh": "字符格式应至少包括大写字母、小写字母、数字、特殊字符的三种;",
|
||||
"en": "Include at least 3 types: uppercase, lowercase, digits, special chars. No 3+ consecutive or repeated digits/letters."
|
||||
},
|
||||
{
|
||||
"key": "100315",
|
||||
"zh": "不能包含连续或重复的三个及三个以上的数字或字母;",
|
||||
"en": "No 3+ consecutive or repeated digits/letters. "
|
||||
},
|
||||
{
|
||||
"key": "100316",
|
||||
"zh": "密码不能是登录名的一部分。",
|
||||
"en": "Cannot be part of login name."
|
||||
},
|
||||
{
|
||||
"key": "100317",
|
||||
"zh": "两次密码一致",
|
||||
"en": "Passwords match"
|
||||
},
|
||||
{
|
||||
"key": "100318",
|
||||
"zh": "重置密码",
|
||||
"en": "Reset Password"
|
||||
},
|
||||
{
|
||||
"key": "100319",
|
||||
"zh": "重置密码成功",
|
||||
"en": "Reset password successfully"
|
||||
}
|
||||
|
||||
|
||||
|
||||
BIN
Assets/Res/ui/common/texture/正确icon.png
Normal file
BIN
Assets/Res/ui/common/texture/正确icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 852 B |
127
Assets/Res/ui/common/texture/正确icon.png.meta
Normal file
127
Assets/Res/ui/common/texture/正确icon.png.meta
Normal file
@ -0,0 +1,127 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e4fedc13a812fd94ea43e1a648b671cb
|
||||
TextureImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 13
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
flipGreenChannel: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
vTOnly: 0
|
||||
ignoreMipmapLimit: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 1
|
||||
aniso: 1
|
||||
mipBias: 0
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: 0
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 1
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 8
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
flipbookRows: 1
|
||||
flipbookColumns: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
ignorePngGamma: 0
|
||||
applyGammaDecoding: 0
|
||||
swizzle: 50462976
|
||||
cookieLightType: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 3
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Android
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID: 5e97eb03825dee720800000000000000
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
nameFileIdTable: {}
|
||||
mipmapLimitGroupName:
|
||||
pSDRemoveMatte: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/Res/ui/common/texture/错误icon.png
Normal file
BIN
Assets/Res/ui/common/texture/错误icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 798 B |
127
Assets/Res/ui/common/texture/错误icon.png.meta
Normal file
127
Assets/Res/ui/common/texture/错误icon.png.meta
Normal file
@ -0,0 +1,127 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3cfdbe04679b2324d961926824c97222
|
||||
TextureImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 13
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
flipGreenChannel: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
vTOnly: 0
|
||||
ignoreMipmapLimit: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 1
|
||||
aniso: 1
|
||||
mipBias: 0
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: 0
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 1
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 8
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
flipbookRows: 1
|
||||
flipbookColumns: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
ignorePngGamma: 0
|
||||
applyGammaDecoding: 0
|
||||
swizzle: 50462976
|
||||
cookieLightType: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 3
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Android
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID: 5e97eb03825dee720800000000000000
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
nameFileIdTable: {}
|
||||
mipmapLimitGroupName:
|
||||
pSDRemoveMatte: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
File diff suppressed because it is too large
Load Diff
@ -433,7 +433,7 @@ GameObject:
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
m_IsActive: 0
|
||||
--- !u!224 &7655272676486550921
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
@ -451,10 +451,10 @@ RectTransform:
|
||||
- {fileID: 8098680310359255571}
|
||||
m_Father: {fileID: 4482340305028100583}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 0, y: 0}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 0, y: 100}
|
||||
m_AnchorMin: {x: 0, y: 1}
|
||||
m_AnchorMax: {x: 0, y: 1}
|
||||
m_AnchoredPosition: {x: 345, y: -454}
|
||||
m_SizeDelta: {x: 630, y: 100}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!222 &459455692708586888
|
||||
CanvasRenderer:
|
||||
@ -1209,7 +1209,7 @@ MonoBehaviour:
|
||||
m_HorizontalOverflow: 0
|
||||
m_VerticalOverflow: 0
|
||||
m_LineSpacing: 1
|
||||
m_Text: Simple Password
|
||||
m_Text: Reset Password
|
||||
--- !u!114 &6798849037590746149
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
@ -1222,7 +1222,7 @@ MonoBehaviour:
|
||||
m_Script: {fileID: 11500000, guid: 89f1d49b50a31514787b4e268b1c73bb, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
textKey: 100020
|
||||
textKey: 100318
|
||||
--- !u!1 &2636706380647424798
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@ -1593,7 +1593,7 @@ RectTransform:
|
||||
m_AnchorMin: {x: 0, y: 1}
|
||||
m_AnchorMax: {x: 1, y: 1}
|
||||
m_AnchoredPosition: {x: 0, y: -200}
|
||||
m_SizeDelta: {x: -60, y: 500}
|
||||
m_SizeDelta: {x: -60, y: 400}
|
||||
m_Pivot: {x: 0.5, y: 1}
|
||||
--- !u!222 &3376027943477643505
|
||||
CanvasRenderer:
|
||||
@ -2292,7 +2292,7 @@ GameObject:
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
m_IsActive: 0
|
||||
--- !u!224 &3480274442878060420
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
@ -2307,10 +2307,10 @@ RectTransform:
|
||||
m_Children: []
|
||||
m_Father: {fileID: 4482340305028100583}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 0, y: 0}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 0, y: 1}
|
||||
m_AnchorMin: {x: 0, y: 1}
|
||||
m_AnchorMax: {x: 0, y: 1}
|
||||
m_AnchoredPosition: {x: 345, y: -403.5}
|
||||
m_SizeDelta: {x: 630, y: 1}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!222 &9222182864204810855
|
||||
CanvasRenderer:
|
||||
@ -2363,7 +2363,7 @@ GameObject:
|
||||
- component: {fileID: 4334117203526359151}
|
||||
- component: {fileID: 173285266742594171}
|
||||
m_Layer: 5
|
||||
m_Name: "\u7B80\u5355\u5BC6\u7801"
|
||||
m_Name: "\u91CD\u7F6E\u5BC6\u7801"
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
@ -3384,12 +3384,7 @@ MonoBehaviour:
|
||||
countryText: {fileID: 869492382333240842}
|
||||
selectCountryButton: {fileID: 4981612120447436577}
|
||||
signoutButton: {fileID: 8124639496175450611}
|
||||
setPasswordButtons:
|
||||
- {fileID: 173285266742594171}
|
||||
- {fileID: 6647111382430836735}
|
||||
setPasswordButtonTexts:
|
||||
- {fileID: 8913907960913215519}
|
||||
- {fileID: 6070206944283714795}
|
||||
resetPassword: {fileID: 173285266742594171}
|
||||
signoutTip: {fileID: 1786064314622589889}
|
||||
--- !u!1 &8678496074108022521
|
||||
GameObject:
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1832,7 +1832,7 @@ namespace Kill.Bluetooth.Protocol
|
||||
public byte MotorError; // 电机错误 (0=无, 1=温度, 2=反馈)
|
||||
public byte LaserError; // 激光器错误 (0=无, 1=温度, 2=电压低, 3=电压高)
|
||||
public byte VisionError; // 视觉错误 (0=无, 1=通信)
|
||||
public byte AccelerometerError; // 加速度错误 (0=无, 1=通信)
|
||||
public byte AccelerometerError; // 加速度错误 (0=无, 1=通信,2=设备不稳定)
|
||||
public byte MillimeterWaveError; // 毫米波雷达错误 (0=无, 1=通信)
|
||||
public byte LidarError; // 激光雷达错误 (0=无, 1=通信)
|
||||
|
||||
|
||||
@ -404,6 +404,7 @@ namespace Kill.UI.Pages
|
||||
|
||||
isQueryingStatus = false;
|
||||
Debug.Log("[HomePageCtrl] 串行查询设备状态完成");
|
||||
if(!hasWifi)
|
||||
OnGetAllMosquitoDataClick();
|
||||
}
|
||||
|
||||
@ -1280,6 +1281,7 @@ namespace Kill.UI.Pages
|
||||
public void GetDeviceStatus()
|
||||
{
|
||||
List<string> errorlist = new List<string>();
|
||||
|
||||
BLECommunicationManager.Instance.ReadHardwareStatus((status) =>
|
||||
{
|
||||
Loom.QueueOnMainThread(() =>
|
||||
@ -1297,6 +1299,7 @@ namespace Kill.UI.Pages
|
||||
{
|
||||
error += LanguageManager.Instance.GetLanguage("100230");
|
||||
}
|
||||
errorlist.Add(error);
|
||||
}
|
||||
if (status.MotorError != 0)
|
||||
{
|
||||
@ -1334,28 +1337,35 @@ namespace Kill.UI.Pages
|
||||
{
|
||||
hasError = true;
|
||||
string error = LanguageManager.Instance.GetLanguage("100237");
|
||||
error += LanguageManager.Instance.GetLanguage("100232");
|
||||
error += LanguageManager.Instance.GetLanguage("100238");
|
||||
errorlist.Add(error);
|
||||
}
|
||||
if (status.AccelerometerError != 0)
|
||||
{
|
||||
hasError = true;
|
||||
string error = LanguageManager.Instance.GetLanguage("100239");
|
||||
error += LanguageManager.Instance.GetLanguage("100232");
|
||||
if (status.AccelerometerError == 1)
|
||||
{
|
||||
error += LanguageManager.Instance.GetLanguage("100238");
|
||||
}
|
||||
else
|
||||
{
|
||||
error += LanguageManager.Instance.GetLanguage("100311");
|
||||
}
|
||||
errorlist.Add(error);
|
||||
}
|
||||
if (status.MillimeterWaveError != 0)
|
||||
{
|
||||
hasError = true;
|
||||
string error = LanguageManager.Instance.GetLanguage("100240");
|
||||
error += LanguageManager.Instance.GetLanguage("100232");
|
||||
error += LanguageManager.Instance.GetLanguage("100238");
|
||||
errorlist.Add(error);
|
||||
}
|
||||
if (status.LidarError != 0)
|
||||
{
|
||||
hasError = true;
|
||||
string error = LanguageManager.Instance.GetLanguage("100241");
|
||||
error += LanguageManager.Instance.GetLanguage("100232");
|
||||
error += LanguageManager.Instance.GetLanguage("100238");
|
||||
errorlist.Add(error);
|
||||
}
|
||||
|
||||
@ -1364,9 +1374,11 @@ namespace Kill.UI.Pages
|
||||
int index = 1;
|
||||
foreach (string e in errorlist)
|
||||
{
|
||||
fullerror += $"{index}.{e}/n";
|
||||
fullerror += $"{index}.{e}\n";
|
||||
index++;
|
||||
}
|
||||
deiviceErrorTip.GetComponentInChildren<Text>().text=fullerror;
|
||||
Debug.Log("错误提示:" + fullerror);
|
||||
deiviceErrorTip.transform.Find("框").Find("提示").GetComponent<Text>().text = fullerror;
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
@ -4,6 +4,9 @@ using Kill.Utils;
|
||||
using Kill.Managers;
|
||||
using System.Threading.Tasks;
|
||||
using System;
|
||||
using System.Text.RegularExpressions;
|
||||
using UnityEngine.WSA;
|
||||
using Kill.UI.Components;
|
||||
|
||||
namespace Kill.UI.Pages
|
||||
{
|
||||
@ -13,22 +16,29 @@ namespace Kill.UI.Pages
|
||||
/// </summary>
|
||||
public class SetPasswordPanel : LoginSubPageBase
|
||||
{
|
||||
[Header("输入组件")]
|
||||
public InputField newPasswordInput;
|
||||
public InputField confirmPasswordInput;
|
||||
[Header("显示组件")]
|
||||
public Text errorText;
|
||||
/// <summary>
|
||||
/// 密码类型提示文本0:简单密码,1:复杂密码
|
||||
/// </summary>
|
||||
public Text[] passwordTypeTips;
|
||||
[Header("按钮")]
|
||||
public Button confirmBtn;
|
||||
public GameObject confirmBtnDisabled;
|
||||
/// <summary>
|
||||
/// 切换简单/复杂密码按钮 0简单密码选中 1简单密码未选中 2复杂密码选中 3复杂密码未选中 未选中可点击
|
||||
/// </summary>
|
||||
public GameObject[] changeTypeBtns;
|
||||
|
||||
[Header("密码规则验证")]
|
||||
public Sprite correctIconSprite;
|
||||
public Sprite incorrectIconSprite;
|
||||
public Image[] simplePasswordRules;
|
||||
public Image[] complexPasswordRules;
|
||||
public Image simpleConfirmMatchRule;
|
||||
public Image complexConfirmMatchRule;
|
||||
public GameObject simpleRulesContainer;
|
||||
public GameObject complexRulesContainer;
|
||||
|
||||
private int passwordType = 0;
|
||||
private bool isConfirmEnabled = false;
|
||||
|
||||
@ -43,6 +53,11 @@ namespace Kill.UI.Pages
|
||||
Register, // 注册设置密码
|
||||
ResetPassword // 忘记密码重置密码
|
||||
}
|
||||
void Start()
|
||||
{
|
||||
OnInitialize();
|
||||
OnShow();
|
||||
}
|
||||
protected override void OnInitialize()
|
||||
{
|
||||
if (confirmBtn != null)
|
||||
@ -52,25 +67,29 @@ namespace Kill.UI.Pages
|
||||
changeTypeBtns[1].GetComponent<Button>().onClick.AddListener(() => ChangePasswordType(0));
|
||||
changeTypeBtns[3].GetComponent<Button>().onClick.AddListener(() => ChangePasswordType(1));
|
||||
}
|
||||
newPasswordInput.onEndEdit.AddListener(CheckPasswordFormat);
|
||||
confirmPasswordInput.onEndEdit.AddListener(CheckPasswordFormat);
|
||||
errorText.text = "";
|
||||
newPasswordInput.onValueChanged.AddListener(OnPasswordValueChanged);
|
||||
confirmPasswordInput.onValueChanged.AddListener(OnPasswordValueChanged);
|
||||
}
|
||||
protected override void OnShow()
|
||||
{
|
||||
// 页面显示时初始化密码输入框
|
||||
newPasswordInput.text = "";
|
||||
confirmPasswordInput.text = "";
|
||||
errorText.text = "";
|
||||
ChangePasswordType(0);
|
||||
}
|
||||
|
||||
private void OnPasswordValueChanged(string value)
|
||||
{
|
||||
CheckPasswordRules();
|
||||
UpdateSubmitButton();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 切换密码类型
|
||||
/// </summary>
|
||||
/// <param name="type">密码类型0:简单密码,1:复杂密码</param>
|
||||
private void ChangePasswordType(int type)
|
||||
{
|
||||
errorText.text = "";
|
||||
passwordType = type;
|
||||
newPasswordInput.text = "";
|
||||
confirmPasswordInput.text = "";
|
||||
@ -98,37 +117,114 @@ namespace Kill.UI.Pages
|
||||
}
|
||||
passwordTypeTips[passwordType].gameObject.SetActive(true);
|
||||
passwordTypeTips[1 - passwordType].gameObject.SetActive(false);
|
||||
|
||||
// 切换规则容器并重置显示
|
||||
UpdateRulesContainerVisibility();
|
||||
ResetRulesDisplay();
|
||||
UpdateSubmitButton();
|
||||
}
|
||||
public void CheckPasswordFormat(string password)
|
||||
|
||||
/// <summary>
|
||||
/// 更新规则容器可见性
|
||||
/// </summary>
|
||||
private void UpdateRulesContainerVisibility()
|
||||
{
|
||||
isConfirmEnabled = true;
|
||||
errorText.text = "";
|
||||
if (simpleRulesContainer != null)
|
||||
simpleRulesContainer.SetActive(passwordType == 0);
|
||||
if (complexRulesContainer != null)
|
||||
complexRulesContainer.SetActive(passwordType == 1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 重置规则显示为未通过状态
|
||||
/// </summary>
|
||||
private void ResetRulesDisplay()
|
||||
{
|
||||
var rules = passwordType == 0 ? simplePasswordRules : complexPasswordRules;
|
||||
if (rules != null)
|
||||
{
|
||||
foreach (var image in rules)
|
||||
{
|
||||
if (image != null)
|
||||
image.sprite = incorrectIconSprite;
|
||||
}
|
||||
}
|
||||
var matchRule = passwordType == 0 ? simpleConfirmMatchRule : complexConfirmMatchRule;
|
||||
if (matchRule != null)
|
||||
matchRule.sprite = incorrectIconSprite;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 逐条检查密码规则并更新UI图标
|
||||
/// </summary>
|
||||
private void CheckPasswordRules()
|
||||
{
|
||||
string newPwd = newPasswordInput != null ? newPasswordInput.text : "";
|
||||
string confirmPwd = confirmPasswordInput != null ? confirmPasswordInput.text : "";
|
||||
|
||||
bool pwdRulesValid = false;
|
||||
|
||||
if (passwordType == 0)
|
||||
{
|
||||
if (!ValidationUtils.IsValidSimplePassword(newPasswordInput.text))
|
||||
{
|
||||
errorText.text = LanguageManager.Instance.GetLanguage("100025");
|
||||
isConfirmEnabled = false;
|
||||
return;
|
||||
}
|
||||
// 简单密码 - 1条规则:6位数字
|
||||
bool isValid = ValidationUtils.IsValidSimplePassword(newPwd);
|
||||
pwdRulesValid = isValid;
|
||||
if (simplePasswordRules != null && simplePasswordRules.Length > 0 && simplePasswordRules[0] != null)
|
||||
simplePasswordRules[0].sprite = isValid ? correctIconSprite : incorrectIconSprite;
|
||||
Debug.Log(isValid);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!ValidationUtils.IsValidComplexPassword(newPasswordInput.text))
|
||||
// 复杂密码 - 4条规则
|
||||
// 规则1:长度8-16位,不能有空格
|
||||
bool rule1Valid = newPwd.Length >= 8 && newPwd.Length <= 16 && !newPwd.Contains(" ");
|
||||
|
||||
// 规则2:至少包含大写字母、小写字母、数字、特殊字符中的三种
|
||||
bool hasUpper = Regex.IsMatch(newPwd, @"[A-Z]");
|
||||
bool hasLower = Regex.IsMatch(newPwd, @"[a-z]");
|
||||
bool hasDigit = Regex.IsMatch(newPwd, @"\d");
|
||||
bool hasSpecial = !string.IsNullOrEmpty(newPwd) && Regex.IsMatch(newPwd, @"[!@#$%^&*()_+\-=\[\]{};':""\\|,.<>\/?]|\p{P}");
|
||||
int typeCount = (hasUpper ? 1 : 0) + (hasLower ? 1 : 0) + (hasDigit ? 1 : 0) + (hasSpecial ? 1 : 0);
|
||||
bool rule2Valid = typeCount >= 3;
|
||||
|
||||
// 规则3:不能包含连续或重复的三个及以上的数字或字母(大小写不敏感)
|
||||
bool rule3Valid = ValidationUtils.IsValidNoRepeatOrConsecutive(newPwd);
|
||||
|
||||
// 规则4:密码不能包含邮箱中任意连续两个字符
|
||||
string email = LoginPageCtrl.Instance.GetCurrentEmail();
|
||||
bool rule4Valid = ValidationUtils.IsValidNotEmailPart(newPwd, email);
|
||||
|
||||
pwdRulesValid = rule1Valid && rule2Valid && rule3Valid && rule4Valid;
|
||||
|
||||
if (complexPasswordRules != null && complexPasswordRules.Length >= 4)
|
||||
{
|
||||
errorText.text = LanguageManager.Instance.GetLanguage("100029");
|
||||
isConfirmEnabled = false;
|
||||
return;
|
||||
if (complexPasswordRules[0] != null) complexPasswordRules[0].sprite = rule1Valid ? correctIconSprite : incorrectIconSprite;
|
||||
if (complexPasswordRules[1] != null) complexPasswordRules[1].sprite = rule2Valid ? correctIconSprite : incorrectIconSprite;
|
||||
if (complexPasswordRules[2] != null) complexPasswordRules[2].sprite = rule3Valid ? correctIconSprite : incorrectIconSprite;
|
||||
if (complexPasswordRules[3] != null) complexPasswordRules[3].sprite = rule4Valid ? correctIconSprite : incorrectIconSprite;
|
||||
}
|
||||
}
|
||||
|
||||
if (newPasswordInput.text != confirmPasswordInput.text)
|
||||
{
|
||||
errorText.text = LanguageManager.Instance.GetLanguage("100028");
|
||||
isConfirmEnabled = false;
|
||||
// 两条密码一致
|
||||
bool matchValid = !string.IsNullOrEmpty(newPwd) && newPwd == confirmPwd;
|
||||
var matchRule = passwordType == 0 ? simpleConfirmMatchRule : complexConfirmMatchRule;
|
||||
if (matchRule != null)
|
||||
matchRule.sprite = matchValid ? correctIconSprite : incorrectIconSprite;
|
||||
|
||||
isConfirmEnabled = pwdRulesValid && matchValid;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新提交按钮显示状态
|
||||
/// </summary>
|
||||
private void UpdateSubmitButton()
|
||||
{
|
||||
if (confirmBtn != null)
|
||||
confirmBtn.gameObject.SetActive(isConfirmEnabled);
|
||||
if (confirmBtnDisabled != null)
|
||||
confirmBtnDisabled.SetActive(!isConfirmEnabled);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置页面模式(注册或重置密码)
|
||||
/// </summary>
|
||||
@ -158,7 +254,7 @@ namespace Kill.UI.Pages
|
||||
},
|
||||
onError: (code, msg) =>
|
||||
{
|
||||
errorText.text =code.ToString();
|
||||
ToastUI.ShowText(code.ToString());
|
||||
}
|
||||
);
|
||||
}
|
||||
@ -173,7 +269,7 @@ namespace Kill.UI.Pages
|
||||
},
|
||||
onError: (code, msg) =>
|
||||
{
|
||||
errorText.text = code.ToString();
|
||||
ToastUI.ShowText(code.ToString());
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@ -32,14 +32,15 @@ namespace Kill.UI.Pages
|
||||
/// <summary>
|
||||
/// 0简单密码 1复杂密码
|
||||
/// </summary>
|
||||
public Button[] setPasswordButtons;
|
||||
public Text[] setPasswordButtonTexts;
|
||||
public Button resetPassword;
|
||||
public async Task Init(UserInfo userInfo)
|
||||
{
|
||||
this.userInfo = userInfo;
|
||||
UIManager.Instance.RegisterBackAction(OnBack);
|
||||
backButton.onClick.RemoveAllListeners();
|
||||
backButton.onClick.AddListener(OnBack);
|
||||
resetPassword.onClick.RemoveAllListeners();
|
||||
resetPassword.onClick.AddListener(OnSetPassword);
|
||||
renameButton.onClick.RemoveAllListeners();
|
||||
renameButton.onClick.AddListener(() =>
|
||||
{
|
||||
@ -73,8 +74,6 @@ namespace Kill.UI.Pages
|
||||
selectCountryButton.onClick.RemoveAllListeners();
|
||||
selectCountryButton.onClick.AddListener(OnSelectCountry);
|
||||
}
|
||||
|
||||
InitLanguageText();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -113,30 +112,6 @@ namespace Kill.UI.Pages
|
||||
public void InitLanguageText()
|
||||
{
|
||||
passwordSet = new List<string>();
|
||||
foreach (var key in passwordSetKeys)
|
||||
{
|
||||
passwordSet.Add(LanguageManager.Instance.GetLanguage(key));
|
||||
}
|
||||
if (userInfo.has_simple_password)
|
||||
{
|
||||
setPasswordButtonTexts[0].text = passwordSet[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
setPasswordButtonTexts[0].text = passwordSet[0];
|
||||
}
|
||||
if (userInfo.has_complex_password)
|
||||
{
|
||||
setPasswordButtonTexts[1].text = passwordSet[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
setPasswordButtonTexts[1].text = passwordSet[0];
|
||||
}
|
||||
setPasswordButtons[0].onClick.RemoveAllListeners();
|
||||
setPasswordButtons[0].onClick.AddListener(() => OnSetPassword(0));
|
||||
setPasswordButtons[1].onClick.RemoveAllListeners();
|
||||
setPasswordButtons[1].onClick.AddListener(() => OnSetPassword(1));
|
||||
|
||||
}
|
||||
public void CloseRenamePage(string newNickname)
|
||||
@ -148,11 +123,9 @@ namespace Kill.UI.Pages
|
||||
DataManager.Instance.userInfo.username = newNickname;
|
||||
UIManager.Instance.RegisterBackAction(OnBack);
|
||||
}
|
||||
int passwordType = -1;
|
||||
SelfVerificationCodePanel verificationCodePanel;
|
||||
public void OnSetPassword(int passwordType)
|
||||
public void OnSetPassword()
|
||||
{
|
||||
this.passwordType = passwordType;
|
||||
verificationCodePanel = Instantiate(verificationCodePanelPrefab, transform);
|
||||
verificationCodePanel.Init(OnSureVerificationCode);
|
||||
}
|
||||
@ -161,14 +134,13 @@ namespace Kill.UI.Pages
|
||||
{
|
||||
Destroy(verificationCodePanel.gameObject);
|
||||
setPasswordPanel = Instantiate(setPasswordPanelPrefab, transform);
|
||||
setPasswordPanel.Init(passwordType, OnSetPasswordSuccess);
|
||||
setPasswordPanel.Init(OnSetPasswordSuccess);
|
||||
}
|
||||
public void OnSetPasswordSuccess()
|
||||
{
|
||||
Destroy(setPasswordPanel.gameObject);
|
||||
OnSignOut();
|
||||
|
||||
UIManager.Instance.RegisterBackAction(OnBack);
|
||||
Init(DataManager.Instance.userInfo);
|
||||
}
|
||||
public void OnBack()
|
||||
{
|
||||
@ -187,7 +159,7 @@ namespace Kill.UI.Pages
|
||||
// 清除用户数据
|
||||
DataManager.Instance.ClearInfo();
|
||||
// 返回登录页面
|
||||
UIManager.Instance.OpenPage(UIManager.PageName.loginPage);
|
||||
UIManager.Instance.OpenMainPage(UIManager.PageName.loginPage);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -4,6 +4,7 @@ using Kill.Utils;
|
||||
using Kill.Managers;
|
||||
using System.Threading.Tasks;
|
||||
using System;
|
||||
using System.Text.RegularExpressions;
|
||||
using Kill.UI.Components;
|
||||
using Kill.Network;
|
||||
|
||||
@ -18,23 +19,33 @@ namespace Kill.UI.Pages
|
||||
[Header("输入组件")]
|
||||
public InputField newPasswordInput;
|
||||
public InputField confirmPasswordInput;
|
||||
[Header("显示组件")]
|
||||
public Text errorText;
|
||||
/// <summary>
|
||||
/// 密码类型提示文本0:简单密码,1:复杂密码
|
||||
/// </summary>
|
||||
public Text[] passwordTypeTips;
|
||||
[Header("按钮")]
|
||||
public Button confirmBtn;
|
||||
public GameObject confirmBtnDisabled;
|
||||
public Button backBtn;
|
||||
/// <summary>
|
||||
/// 切换简单/复杂密码按钮 0简单密码选中 1简单密码未选中 2复杂密码选中 3复杂密码未选中 未选中可点击
|
||||
/// </summary>
|
||||
public GameObject[] changeTypeBtns;
|
||||
|
||||
[Header("密码规则验证")]
|
||||
public Sprite correctIconSprite;
|
||||
public Sprite incorrectIconSprite;
|
||||
public Image[] simplePasswordRules;
|
||||
public Image[] complexPasswordRules;
|
||||
public Image simpleConfirmMatchRule;
|
||||
public Image complexConfirmMatchRule;
|
||||
public GameObject simpleRulesContainer;
|
||||
public GameObject complexRulesContainer;
|
||||
|
||||
private int passwordType = 0;
|
||||
private bool isConfirmEnabled = false;
|
||||
|
||||
Action callback;
|
||||
|
||||
public void Init(int type, Action callback)
|
||||
public void Init( Action callback)
|
||||
{
|
||||
passwordType = type;
|
||||
passwordType = 0;
|
||||
this.callback = callback;
|
||||
if (confirmBtn != null)
|
||||
{
|
||||
@ -46,23 +57,29 @@ namespace Kill.UI.Pages
|
||||
backBtn.onClick.RemoveAllListeners();
|
||||
backBtn.onClick.AddListener(OnBack);
|
||||
}
|
||||
|
||||
newPasswordInput.onEndEdit.AddListener(CheckPasswordFormat);
|
||||
confirmPasswordInput.onEndEdit.AddListener(CheckPasswordFormat);
|
||||
errorText.text = "";
|
||||
// 页面显示时初始化密码输入框
|
||||
newPasswordInput.text = "";
|
||||
confirmPasswordInput.text = "";
|
||||
errorText.text = "";
|
||||
ChangePasswordType(type);
|
||||
if (changeTypeBtns != null && changeTypeBtns.Length == 4)
|
||||
{
|
||||
changeTypeBtns[1].GetComponent<Button>().onClick.AddListener(() => ChangePasswordType(0));
|
||||
changeTypeBtns[3].GetComponent<Button>().onClick.AddListener(() => ChangePasswordType(1));
|
||||
}
|
||||
newPasswordInput.onValueChanged.AddListener(OnPasswordValueChanged);
|
||||
confirmPasswordInput.onValueChanged.AddListener(OnPasswordValueChanged);
|
||||
// 页面显示时初始化密码输入框
|
||||
ChangePasswordType(0);
|
||||
}
|
||||
|
||||
private void OnPasswordValueChanged(string value)
|
||||
{
|
||||
CheckPasswordRules();
|
||||
UpdateSubmitButton();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 切换密码类型
|
||||
/// </summary>
|
||||
/// <param name="type">密码类型0:简单密码,1:复杂密码</param>
|
||||
private void ChangePasswordType(int type)
|
||||
{
|
||||
errorText.text = "";
|
||||
passwordType = type;
|
||||
newPasswordInput.text = "";
|
||||
confirmPasswordInput.text = "";
|
||||
@ -72,6 +89,10 @@ namespace Kill.UI.Pages
|
||||
confirmPasswordInput.characterLimit = 6;
|
||||
newPasswordInput.contentType = InputField.ContentType.Pin;
|
||||
confirmPasswordInput.contentType = InputField.ContentType.Pin;
|
||||
changeTypeBtns[0].SetActive(true);
|
||||
changeTypeBtns[1].SetActive(false);
|
||||
changeTypeBtns[2].SetActive(false);
|
||||
changeTypeBtns[3].SetActive(true);
|
||||
|
||||
}
|
||||
else
|
||||
@ -80,40 +101,111 @@ namespace Kill.UI.Pages
|
||||
confirmPasswordInput.characterLimit = 16;
|
||||
newPasswordInput.contentType = InputField.ContentType.Password;
|
||||
confirmPasswordInput.contentType = InputField.ContentType.Password;
|
||||
changeTypeBtns[0].SetActive(false);
|
||||
changeTypeBtns[1].SetActive(true);
|
||||
changeTypeBtns[2].SetActive(true);
|
||||
changeTypeBtns[3].SetActive(false);
|
||||
|
||||
}
|
||||
passwordTypeTips[passwordType].gameObject.SetActive(true);
|
||||
passwordTypeTips[1 - passwordType].gameObject.SetActive(false);
|
||||
|
||||
// 切换规则容器并重置显示
|
||||
UpdateRulesContainerVisibility();
|
||||
ResetRulesDisplay();
|
||||
UpdateSubmitButton();
|
||||
}
|
||||
public void CheckPasswordFormat(string password)
|
||||
|
||||
private void UpdateRulesContainerVisibility()
|
||||
{
|
||||
isConfirmEnabled = true;
|
||||
errorText.text = "";
|
||||
if (simpleRulesContainer != null)
|
||||
simpleRulesContainer.SetActive(passwordType == 0);
|
||||
if (complexRulesContainer != null)
|
||||
complexRulesContainer.SetActive(passwordType == 1);
|
||||
}
|
||||
|
||||
private void ResetRulesDisplay()
|
||||
{
|
||||
var rules = passwordType == 0 ? simplePasswordRules : complexPasswordRules;
|
||||
if (rules != null)
|
||||
{
|
||||
foreach (var image in rules)
|
||||
{
|
||||
if (image != null)
|
||||
image.sprite = incorrectIconSprite;
|
||||
}
|
||||
}
|
||||
var matchRule = passwordType == 0 ? simpleConfirmMatchRule : complexConfirmMatchRule;
|
||||
if (matchRule != null)
|
||||
matchRule.sprite = incorrectIconSprite;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 逐条检查密码规则并更新UI图标
|
||||
/// </summary>
|
||||
private void CheckPasswordRules()
|
||||
{
|
||||
string newPwd = newPasswordInput != null ? newPasswordInput.text : "";
|
||||
string confirmPwd = confirmPasswordInput != null ? confirmPasswordInput.text : "";
|
||||
|
||||
bool pwdRulesValid = false;
|
||||
|
||||
if (passwordType == 0)
|
||||
{
|
||||
if (!ValidationUtils.IsValidSimplePassword(newPasswordInput.text))
|
||||
{
|
||||
errorText.text = LanguageManager.Instance.GetLanguage("100025");
|
||||
isConfirmEnabled = false;
|
||||
return;
|
||||
}
|
||||
// 简单密码 - 1条规则:6位数字
|
||||
bool isValid = ValidationUtils.IsValidSimplePassword(newPwd);
|
||||
pwdRulesValid = isValid;
|
||||
if (simplePasswordRules != null && simplePasswordRules.Length > 0 && simplePasswordRules[0] != null)
|
||||
simplePasswordRules[0].sprite = isValid ? correctIconSprite : incorrectIconSprite;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!ValidationUtils.IsValidComplexPassword(newPasswordInput.text))
|
||||
// 复杂密码 - 4条规则
|
||||
// 规则1:长度8-16位,不能有空格
|
||||
bool rule1Valid = newPwd.Length >= 8 && newPwd.Length <= 16 && !newPwd.Contains(" ");
|
||||
|
||||
// 规则2:至少包含大写字母、小写字母、数字、特殊字符中的三种
|
||||
bool hasUpper = Regex.IsMatch(newPwd, @"[A-Z]");
|
||||
bool hasLower = Regex.IsMatch(newPwd, @"[a-z]");
|
||||
bool hasDigit = Regex.IsMatch(newPwd, @"\d");
|
||||
bool hasSpecial = !string.IsNullOrEmpty(newPwd) && Regex.IsMatch(newPwd, @"[!@#$%^&*()_+\-=\[\]{};':""\\|,.<>\/?]|\p{P}");
|
||||
int typeCount = (hasUpper ? 1 : 0) + (hasLower ? 1 : 0) + (hasDigit ? 1 : 0) + (hasSpecial ? 1 : 0);
|
||||
bool rule2Valid = typeCount >= 3;
|
||||
|
||||
// 规则3:不能包含连续或重复的三个及以上的数字或字母(大小写不敏感)
|
||||
bool rule3Valid = ValidationUtils.IsValidNoRepeatOrConsecutive(newPwd);
|
||||
|
||||
// 规则4:密码不能包含邮箱中任意连续两个字符
|
||||
string email = DataManager.Instance.userInfo.email;
|
||||
bool rule4Valid = ValidationUtils.IsValidNotEmailPart(newPwd, email);
|
||||
|
||||
pwdRulesValid = rule1Valid && rule2Valid && rule3Valid && rule4Valid;
|
||||
|
||||
if (complexPasswordRules != null && complexPasswordRules.Length >= 4)
|
||||
{
|
||||
errorText.text = LanguageManager.Instance.GetLanguage("100029");
|
||||
isConfirmEnabled = false;
|
||||
return;
|
||||
if (complexPasswordRules[0] != null) complexPasswordRules[0].sprite = rule1Valid ? correctIconSprite : incorrectIconSprite;
|
||||
if (complexPasswordRules[1] != null) complexPasswordRules[1].sprite = rule2Valid ? correctIconSprite : incorrectIconSprite;
|
||||
if (complexPasswordRules[2] != null) complexPasswordRules[2].sprite = rule3Valid ? correctIconSprite : incorrectIconSprite;
|
||||
if (complexPasswordRules[3] != null) complexPasswordRules[3].sprite = rule4Valid ? correctIconSprite : incorrectIconSprite;
|
||||
}
|
||||
}
|
||||
|
||||
if (newPasswordInput.text != confirmPasswordInput.text)
|
||||
{
|
||||
errorText.text = LanguageManager.Instance.GetLanguage("100028");
|
||||
isConfirmEnabled = false;
|
||||
// 两条密码一致
|
||||
bool matchValid = !string.IsNullOrEmpty(newPwd) && newPwd == confirmPwd;
|
||||
var matchRule = passwordType == 0 ? simpleConfirmMatchRule : complexConfirmMatchRule;
|
||||
if (matchRule != null)
|
||||
matchRule.sprite = matchValid ? correctIconSprite : incorrectIconSprite;
|
||||
|
||||
isConfirmEnabled = pwdRulesValid && matchValid;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新提交按钮显示状态
|
||||
/// </summary>
|
||||
private void UpdateSubmitButton()
|
||||
{
|
||||
if (confirmBtn != null)
|
||||
confirmBtn.gameObject.SetActive(isConfirmEnabled);
|
||||
if (confirmBtnDisabled != null)
|
||||
confirmBtnDisabled.SetActive(!isConfirmEnabled);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -143,7 +235,7 @@ namespace Kill.UI.Pages
|
||||
},
|
||||
onError: (code, msg) =>
|
||||
{
|
||||
errorText.text = code.ToString();
|
||||
ToastUI.ShowText(code.ToString());
|
||||
}
|
||||
);
|
||||
|
||||
@ -174,6 +266,7 @@ namespace Kill.UI.Pages
|
||||
onSuccess: (data) =>
|
||||
{
|
||||
Debug.Log("重置密码成功");
|
||||
ToastUI.Show("100319");
|
||||
onSuccess?.Invoke();
|
||||
},
|
||||
onError: onError
|
||||
|
||||
@ -63,6 +63,61 @@ namespace Kill.Utils
|
||||
return hasDigit && hasLetter && hasSpecial;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查是否包含连续或重复的三个及以上数字或字母(大小写不敏感)
|
||||
/// </summary>
|
||||
public static bool IsValidNoRepeatOrConsecutive(string password)
|
||||
{
|
||||
for (int i = 0; i <= password.Length - 3; i++)
|
||||
{
|
||||
char c0 = password[i];
|
||||
char c1 = password[i + 1];
|
||||
char c2 = password[i + 2];
|
||||
|
||||
if (!char.IsLetterOrDigit(c0) || !char.IsLetterOrDigit(c1) || !char.IsLetterOrDigit(c2))
|
||||
continue;
|
||||
|
||||
bool isRepeated;
|
||||
if (char.IsLetter(c0))
|
||||
isRepeated = char.ToLower(c0) == char.ToLower(c1) && char.ToLower(c1) == char.ToLower(c2);
|
||||
else
|
||||
isRepeated = c0 == c1 && c1 == c2;
|
||||
|
||||
if (isRepeated) return false;
|
||||
|
||||
if (char.IsDigit(c0) && char.IsDigit(c1) && char.IsDigit(c2))
|
||||
{
|
||||
if ((c1 - c0 == 1 && c2 - c1 == 1) || (c0 - c1 == 1 && c1 - c2 == 1))
|
||||
return false;
|
||||
}
|
||||
else if (char.IsLetter(c0))
|
||||
{
|
||||
char l0 = char.ToLower(c0), l1 = char.ToLower(c1), l2 = char.ToLower(c2);
|
||||
if ((l1 - l0 == 1 && l2 - l1 == 1) || (l0 - l1 == 1 && l1 - l2 == 1))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查密码是否包含邮箱中任意连续两个字符
|
||||
/// </summary>
|
||||
public static bool IsValidNotEmailPart(string password, string email)
|
||||
{
|
||||
if (string.IsNullOrEmpty(email)) return true;
|
||||
|
||||
string emailName = email.Contains('@') ? email.Split('@')[0] : email;
|
||||
string pwdLower = password.ToLower();
|
||||
|
||||
for (int i = 0; i <= emailName.Length - 2; i++)
|
||||
{
|
||||
string pair = emailName.Substring(i, 2).ToLower();
|
||||
if (pwdLower.Contains(pair))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user