|
@@ -1,17 +1,56 @@
|
|
|
+import { EyeInvisibleOutlined, EyeTwoTone } from '@ant-design/icons'
|
|
|
import { Input } from 'antd'
|
|
|
-import { PasswordProps } from 'antd/lib/input'
|
|
|
import React, { ChangeEvent, useState } from 'react'
|
|
|
import zxcvbn from 'zxcvbn'
|
|
|
+import { generatePsw } from '@/utils/util'
|
|
|
import './index.scss'
|
|
|
+interface StrengthMeterProps {
|
|
|
+ value?: string
|
|
|
+ onChange?: (value: string) => void
|
|
|
+}
|
|
|
+
|
|
|
+const StrengthMeter: React.FC<StrengthMeterProps> = (props) => {
|
|
|
|
|
|
-const Index: React.FC<PasswordProps> = (props) => {
|
|
|
+ const { value, onChange } = props
|
|
|
+ const [ psw, setPsw ] = useState<string>('')
|
|
|
const [ score, setScore ] = useState<number | null>(null)
|
|
|
+
|
|
|
+ const triggerChange = (newVal: string) => {
|
|
|
+ if (onChange) {
|
|
|
+ onChange(newVal)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
const handleChangeEvent = (event: ChangeEvent<HTMLInputElement>) => {
|
|
|
- setScore(event.target.value ? zxcvbn(event.target.value, []).score : null)
|
|
|
+ const newVal = event.target.value || ''
|
|
|
+ setScore(newVal ? zxcvbn(newVal, []).score : null)
|
|
|
+ if (!value) {
|
|
|
+ setPsw(newVal)
|
|
|
+ }
|
|
|
+ // 当使用随机密码时,如果在value为underfined时不将psw置空,则会读取使用随机密码设置的psw,而不是传进来的value
|
|
|
+ if (!newVal) {
|
|
|
+ setPsw('')
|
|
|
+ }
|
|
|
+ triggerChange(newVal)
|
|
|
+ }
|
|
|
+
|
|
|
+ const handlePsw = () => {
|
|
|
+ const newVal = generatePsw(12)
|
|
|
+ setScore(newVal ? zxcvbn(newVal, []).score : null)
|
|
|
+ if (!value) {
|
|
|
+ setPsw(newVal)
|
|
|
+ }
|
|
|
+ triggerChange(newVal)
|
|
|
}
|
|
|
return (
|
|
|
<div className="zh-strength-meter">
|
|
|
- <Input.Password {...props} onChange={handleChangeEvent}/>
|
|
|
+ <Input.Password
|
|
|
+ placeholder="密码支持英文数字及符号"
|
|
|
+ value={value || psw}
|
|
|
+ addonAfter={<span className="pi-pd-lr-11" onClick={() => handlePsw()}>随机密码</span>}
|
|
|
+ iconRender={visible => (visible ? <EyeTwoTone /> : <EyeInvisibleOutlined />)}
|
|
|
+ onChange={handleChangeEvent}
|
|
|
+ />
|
|
|
<div className="zh-strength-meter-bar">
|
|
|
<div className="zh-strength-meter-bar--fill" data-score={score} />
|
|
|
</div>
|
|
@@ -19,4 +58,4 @@ const Index: React.FC<PasswordProps> = (props) => {
|
|
|
)
|
|
|
}
|
|
|
|
|
|
-export default Index
|
|
|
+export default StrengthMeter
|