5 changed files with 262 additions and 68 deletions
@ -0,0 +1,114 @@ |
|||
import React, { useState } from 'react'; |
|||
import { Card, Input, Button, message } from 'antd'; |
|||
import { LockOutlined } from '@ant-design/icons'; |
|||
|
|||
/** |
|||
* 高级配置密码验证组件 |
|||
*/ |
|||
const AdvancedConfigAuth = ({ verifyPassword, onUnlock }) => { |
|||
const [password, setPassword] = useState(''); |
|||
const [loading, setLoading] = useState(false); |
|||
|
|||
const handleVerify = async () => { |
|||
if (!password) { |
|||
message.warning('请输入密码'); |
|||
return; |
|||
} |
|||
|
|||
setLoading(true); |
|||
try { |
|||
const isValid = await verifyPassword(password); |
|||
|
|||
if (isValid) { |
|||
message.success('密码正确,已解锁高级配置'); |
|||
onUnlock && onUnlock(); |
|||
} else { |
|||
message.error('密码错误,请重试'); |
|||
setPassword(''); |
|||
} |
|||
} catch (error) { |
|||
console.error('密码验证失败:', error); |
|||
message.error('验证过程出错,请重试'); |
|||
} finally { |
|||
setLoading(false); |
|||
} |
|||
}; |
|||
|
|||
const handleKeyPress = (e) => { |
|||
if (e.key === 'Enter') { |
|||
handleVerify(); |
|||
} |
|||
}; |
|||
|
|||
return ( |
|||
<div |
|||
style={{ |
|||
display: 'flex', |
|||
alignItems: 'center', |
|||
justifyContent: 'center', |
|||
minHeight: 'calc(100vh - 92px)', |
|||
padding: '24px', |
|||
}} |
|||
> |
|||
<Card |
|||
style={{ |
|||
width: 400, |
|||
textAlign: 'center', |
|||
boxShadow: '0 2px 8px rgba(0,0,0,0.1)', |
|||
}} |
|||
> |
|||
<div |
|||
style={{ |
|||
width: 64, |
|||
height: 64, |
|||
borderRadius: '50%', |
|||
backgroundColor: '#e6f4ff', |
|||
display: 'flex', |
|||
alignItems: 'center', |
|||
justifyContent: 'center', |
|||
margin: '0 auto 24px', |
|||
}} |
|||
> |
|||
<LockOutlined style={{ fontSize: 32, color: '#1890ff' }} /> |
|||
</div> |
|||
|
|||
<h2 style={{ marginBottom: 8 }}>内部高级配置</h2> |
|||
<p style={{ color: '#999', marginBottom: 24 }}> |
|||
请输入管理员访问密码以继续 |
|||
</p> |
|||
|
|||
<Input.Password |
|||
size="large" |
|||
placeholder="请输入密码" |
|||
value={password} |
|||
onChange={(e) => setPassword(e.target.value)} |
|||
onKeyPress={handleKeyPress} |
|||
prefix={<LockOutlined style={{ color: '#999' }} />} |
|||
style={{ marginBottom: 16 }} |
|||
/> |
|||
|
|||
<Button |
|||
type="primary" |
|||
size="large" |
|||
block |
|||
loading={loading} |
|||
onClick={handleVerify} |
|||
> |
|||
解锁配置 |
|||
</Button> |
|||
|
|||
<div |
|||
style={{ |
|||
marginTop: 24, |
|||
fontSize: 12, |
|||
color: '#999', |
|||
}} |
|||
> |
|||
视觉位移计配置工具 v{window.env?.FS_VERSION || ''} Build {new Date().getFullYear()} |
|||
</div> |
|||
</Card> |
|||
</div> |
|||
); |
|||
}; |
|||
|
|||
export default AdvancedConfigAuth; |
|||
@ -0,0 +1 @@ |
|||
import { useState, useEffect, useCallback } from "react"; const CORRECT_PASSWORD_HASH = "77796ac7e66ecc44954287ed7de7096c4016dd6ffb2763091c4eb3bc4d28b6dc", AUTH_STATUS_KEY = "advanced_config_unlocked"; async function generatePasswordHash(e) { try { var t = (new TextEncoder).encode(e), c = await crypto.subtle.digest("SHA-256", t); return Array.from(new Uint8Array(c)).map(e => e.toString(16).padStart(2, "0")).join("") } catch (e) { throw console.error("密码哈希生成失败:", e), e } } function checkUnlockStatus() { return "true" === sessionStorage.getItem(AUTH_STATUS_KEY) } function setUnlockStatus(e) { e ? sessionStorage.setItem(AUTH_STATUS_KEY, "true") : sessionStorage.removeItem(AUTH_STATUS_KEY) } function useAuth() { let [e, t] = useState(checkUnlockStatus); return useEffect(() => { t(checkUnlockStatus()) }, []), { isUnlocked: e, verifyPassword: useCallback(async e => { try { return e ? await generatePasswordHash(e) === CORRECT_PASSWORD_HASH && (setUnlockStatus(!0), t(!0), !0) : !1 } catch (e) { return console.error("密码验证失败:", e), !1 } }, []), logout: useCallback(() => { setUnlockStatus(!1), t(!1) }, []) } } export { useAuth, generatePasswordHash, checkUnlockStatus }; |
|||
Loading…
Reference in new issue