核心代码 直接复制我的核心代码去改就可以了。。。我这算是最简单的方法了
const [codeLoading, setcodeLoading] = useState<boolean>(false) // 验证码的loading
const [timeTip, settimeTip] = useState<any>("60秒后重发") // 定时器倒计时提示
// 倒计时 执行这个函数就行
const setIntervalFn = () => {
let defaultTime = 60
let time = 60
let tip = `${time}秒后重发`
let timeObj2 = setInterval(() => {
if (time === 0) {
time = defaultTime
tip = `${time}秒后重发`
settimeTip(tip)
setcodeLoading(false)
clearInterval(timeObj2)
return false
}
--time
tip = `${time}秒后重发`
settimeTip(tip)
}, 1000)
}
完整代码 仅供参考修改
import React, { useState, useEffect } from "react"
import { history, connect, Dispatch } from "umi"
import { useLocation, useHistory } from "react-router"
import { Button, Form, Input, Upload, message, Modal, Popconfirm, Spin, Select, Checkbox } from "antd"
import { LoadingOutlined, PlusOutlined, MinusCircleFilled } from "@ant-design/icons"
import { userPopOut } from "@/services/components/treeGroupMemberSearch"
import { userHospitalApi, userSwitchApi, updatePasswordApi, setNewPasswordApi, sendVerifyCodeApi } from "@/services/login"
// import { GroupUser, IconsultGroupAddinPam } from "@/typings/consultationTeam.d"
import styles from "./index.less"
import { trim } from "lodash"
interface IseleType {
label: string,
value: any,
}
const Index: React.FC<any> = (props) => {
const { userInfo } = props
let query = history.location.query as any
const [current, setCurrent] = useState<number>(1) // 默认个人信息1 修改密码2
const [loading, setLoading] = useState<boolean>(false)
const [seleOption, setSeleOption] = useState<IseleType[]>([])
const [seleValue, setSeleValue] = useState<string>("") // 切换的医院
const [hospitalId, setHospitalId] = useState<string>("") // 医院id
const activeChange = (num: number) => {
setCurrent(num)
}
// 切换医院
const seleChange = (value: any, obj: any) => {
console.log(111122, value, obj)
setSeleValue(obj.label)
setHospitalId(obj.value)
}
// 根据手机号查询所在医院
const userHospitalApiFn = async () => {
setLoading(true)
let phone = userInfo.contactPhone
const [err, res] = await userHospitalApi(phone)
setLoading(false)
if (err) {
console.log("userHospitalApi:err", err)
// return message.error(err.message)
}
let arr: IseleType[] = []
let isAdd = false
if (res.data && res.data.length >= 1) {
res.data.forEach((i) => {
if (String(userInfo.hospitalId) === i.id) {
isAdd = true
setSeleValue(i.hospitalName)
setHospitalId(i.id)
}
let obj = { value: i.id, label: i.hospitalName }
arr.push(obj)
})
setSeleOption(arr)
if (!isAdd) {
setSeleValue(arr[0].label)
setHospitalId(arr[0].value)
}
}
}
// 切换所选的医院
const switchFn = async () => {
if (String(userInfo.hospitalId) === hospitalId) {
return message.error("当前已经是该单位,无需切换")
}
setLoading(true)
const [err, res] = await userSwitchApi(hospitalId)
setLoading(false)
if (err) {
return message.error(err.message)
}
props.dispatch({
type: "indexModel/updateUserInfo",
payload: res.data
})
// 获取数据字典
props.dispatch({
type: "indexModel/getAllEnum",
payload: {}
})
setLoading(false)
history.push({
pathname: "/index",
query: {
},
})
}
// 个人信息界面
const InfoView = () => {
return (
<div style={{ padding: "0 40px" }}>
{loading ? <Spin className="spinClass" tip="加载中..." /> : null}
<div className={styles.mgb30}>
<span className={styles.leftT}>用户名</span>: <span className={styles.rightV}>{userInfo.name}</span>
</div>
<div className={styles.mgb30}>
<span className={styles.leftT}>手机号</span>: <span className={styles.rightV}>{userInfo.contactPhone}</span>
</div>
<div className={styles.mgb30}>
<span className={styles.leftT}>单位</span>: <Select value={seleValue} onChange={seleChange} options={seleOption} className={styles.selectClass} />
</div>
<div className={styles.mgb30}>
<span className={styles.leftT}>部门</span>: <span className={styles.rightV}>{userInfo.deptName}</span>
</div>
<div style={{ textAlign: "center", paddingTop: "1.5rem" }}>
<Button className={styles.cancel} >
取消
</Button>
<Button onClick={switchFn} disabled={loading} className={styles.determine} style={{ marginLeft: "16px" }} type="primary" >
保存
</Button>
</div>
</div >
)
}
const [passType, setPassType] = useState<number>(1) // 1原密码 2动态密码
const passOnChange = (e: any, type: number) => {
// let c = e.target.checked
setPassType(type)
}
// 原密码
const Ymm = () => {
interface IpassType {
oldPwd: string
newPwd: string
confirmNewPwd: string
}
const [loading1, setLoading1] = useState<boolean>(false)
const [oldPwd, setoldPwd] = useState<string>("")
const [newPwd, setnewPwd] = useState<string>("")
const [confirmNewPwd, setconfirmNewPwd] = useState<string>("")
// 密码长度6-24位,至少包含字母,数字,符号2种组合
const [form] = Form.useForm()
const layout = {
labelCol: { span: 5 },
// wrapperCol: { span: 16 },
}
// 验证正确后回调
const onFinish = async (obj: IpassType) => {
console.log(11, obj)
if (obj.newPwd !== obj.confirmNewPwd) {
return message.error("2次数输入密码不相同")
}
setLoading1(true)
const [err, res] = await updatePasswordApi(obj)
setLoading1(false)
if (err) {
return message.error(err.message)
}
message.success(res.message)
history.replace({
pathname: "/login",
query: {
},
})
}
// 触发提交
const submit = () => {
form.submit()
}
return (
<div>
{loading1 ? <Spin className="spinClass" tip="加载中..." /> : null}
<Form
{...layout}
form={form}
onFinish={onFinish}
name="basic"
>
<Form.Item
label="原密码"
name="oldPwd"
rules={[
{
required: true,
validator: async (_, names) => {
let reg = new RegExp(/^(?![\d]+$)(?![a-zA-Z]+$)(?![^\da-zA-Z]+$).{6,24}$/) // 6-24位,至少带字母数字符号中的两种的正则
let result = reg.test(oldPwd)
if (oldPwd.indexOf(" ") !== -1) {
return Promise.reject(new Error("不允许输入空格"))
}
// if (!result) {
// return Promise.reject(new Error("请输入密码长度6-24位,至少包含字母,数字,符号2种组合"))
// }
},
}
]}
>
<Input maxLength={24} placeholder="请输入原密码" value={oldPwd} onChange={(e) => setoldPwd(e.target.value)} />
</Form.Item>
<Form.Item
label="新密码"
name="newPwd"
rules={[
{
required: true,
validator: async (_, names) => {
let reg = new RegExp(/^(?![\d]+$)(?![a-zA-Z]+$)(?![^\da-zA-Z]+$).{6,24}$/) // 6-24位,至少带字母数字符号中的两种的正则
let result = reg.test(newPwd)
if (newPwd.indexOf(" ") !== -1) {
return Promise.reject(new Error("不允许输入空格"))
}
if (!result) {
return Promise.reject(new Error("请输入密码长度6-24位,至少包含字母,数字,符号2种组合"))
}
},
}
]}
>
<Input.Password maxLength={24} placeholder="请输入新密码" value={newPwd} onChange={(e) => setnewPwd(e.target.value)} />
</Form.Item>
<Form.Item
label="确认密码"
name="confirmNewPwd"
rules={[
{
required: true,
validator: async (_, names) => {
let reg = new RegExp(/^(?![\d]+$)(?![a-zA-Z]+$)(?![^\da-zA-Z]+$).{6,24}$/) // 6-24位,至少带字母数字符号中的两种的正则
let result = reg.test(confirmNewPwd)
if (confirmNewPwd.indexOf(" ") !== -1) {
return Promise.reject(new Error("不允许输入空格"))
}
if (!result) {
return Promise.reject(new Error("请输入密码长度6-24位,至少包含字母,数字,符号2种组合"))
}
},
}
]}
>
<Input.Password maxLength={24} placeholder="请输入确认密码" value={confirmNewPwd} onChange={(e) => setconfirmNewPwd(e.target.value)} />
</Form.Item>
</Form>
<div style={{ textAlign: "center", paddingTop: "1.5rem" }}>
<Button className={styles.cancel} >
取消
</Button>
<Button onClick={submit} disabled={loading1} className={styles.determine} style={{ marginLeft: "16px" }} type="primary" >
保存
</Button>
</div>
</div >
)
}
// 动态密码
const Dtmm = () => {
interface IpassType {
phone?: string
verifyCode: string
newPwd: string
confirmNewPwd: string
}
const [loading2, setLoading2] = useState<boolean>(false)
const [codeLoading, setcodeLoading] = useState<boolean>(false) // 验证码的loading
const [timeTip, settimeTip] = useState<any>("60秒后重发") // 定时器倒计时提示
const [phone, setphone] = useState<string>("")
const [verifyCode, setverifyCode] = useState<string>("")
const [newPwd, setnewPwd] = useState<string>("")
const [confirmNewPwd, setconfirmNewPwd] = useState<string>("")
const [form2] = Form.useForm()
const layout = {
labelCol: { span: 5 },
// wrapperCol: { span: 16 },
}
// 验证正确后回调
const onFinish = async (obj: IpassType) => {
obj.phone = userInfo.contactPhone
console.log(11, obj)
if (obj.newPwd !== obj.confirmNewPwd) {
return message.error("2次数输入密码不相同")
}
setLoading2(true)
const [err, res] = await setNewPasswordApi(obj)
setLoading2(false)
if (err) {
return message.error(err.message)
}
message.success(res.message)
history.replace({
pathname: "/login",
query: {
},
})
}
// 倒计时
const setIntervalFn = () => {
let defaultTime = 60
let time = 60
let tip = `${time}秒后重发`
let timeObj2 = setInterval(() => {
if (time === 0) {
time = defaultTime
tip = `${time}秒后重发`
settimeTip(tip)
setcodeLoading(false)
clearInterval(timeObj2)
return false
}
--time
tip = `${time}秒后重发`
settimeTip(tip)
}, 1000)
}
// 发送验证码api
const getCodeApi = async () => {
let obj = {
type: "newPwd",
phone: userInfo.contactPhone
}
setLoading2(true)
const [err, res] = await sendVerifyCodeApi(obj)
setLoading2(false)
if (err) {
return message.error(err.message)
}
setIntervalFn()
message.success(res.message)
}
// 获取验证码
const getCode = () => {
if (userInfo.contactPhone === "" || userInfo.contactPhone === null) {
return message.error("暂无手机号,不能发送验证码")
}
setcodeLoading(true)
getCodeApi()
}
// 触发提交
const submit = () => {
form2.submit()
}
return (
<div>
{loading2 ? <Spin className="spinClass" tip="加载中..." /> : null}
<Form
{...layout}
form={form2}
onFinish={onFinish}
name="basic2"
>
<Form.Item label="手机号码">
<span style={{ color: "rgba(0, 0, 0, 0.45)" }}>{userInfo.contactPhone}</span>
</Form.Item>
<Form.Item
label="验证码"
name="verifyCode"
rules={[
{
required: true,
validator: async (_, names) => {
if (verifyCode.indexOf(" ") !== -1) {
return Promise.reject(new Error("不允许输入空格"))
}
if (verifyCode.length !== 4 || verifyCode === null) {
return Promise.reject(new Error("请输入4位验证码"))
}
},
}
]}
>
<div style={{ display: "flex" }}>
<Input placeholder="请输入验证码" maxLength={4} value={verifyCode} onChange={(e) => setverifyCode(e.target.value)} />
<Button disabled={codeLoading} onClick={getCode} style={{ marginLeft: "10px", width: "110px" }} type="primary" >
{codeLoading ? timeTip : "获取验证码"}
</Button>
</div>
</Form.Item>
<Form.Item
label="新密码"
name="newPwd"
rules={[
{
required: true,
validator: async (_, names) => {
let reg = new RegExp(/^(?![\d]+$)(?![a-zA-Z]+$)(?![^\da-zA-Z]+$).{6,24}$/) // 6-24位,至少带字母数字符号中的两种的正则
let result = reg.test(newPwd)
if (newPwd.indexOf(" ") !== -1) {
return Promise.reject(new Error("不允许输入空格"))
}
if (!result) {
return Promise.reject(new Error("请输入密码长度6-24位,至少包含字母,数字,符号2种组合"))
}
},
}
]}
>
<Input.Password placeholder="请输入新密码" maxLength={24} onChange={(e) => setnewPwd(e.target.value)} />
</Form.Item>
<Form.Item
label="确认密码"
name="confirmNewPwd"
rules={[
{
required: true,
validator: async (_, names) => {
let reg = new RegExp(/^(?![\d]+$)(?![a-zA-Z]+$)(?![^\da-zA-Z]+$).{6,24}$/) // 6-24位,至少带字母数字符号中的两种的正则
let result = reg.test(confirmNewPwd)
if (confirmNewPwd.indexOf(" ") !== -1) {
return Promise.reject(new Error("不允许输入空格"))
}
if (!result) {
return Promise.reject(new Error("请输入密码长度6-24位,至少包含字母,数字,符号2种组合"))
}
},
}
]}
>
<Input.Password placeholder="请输入确认密码" maxLength={24} value={confirmNewPwd} onChange={(e) => setconfirmNewPwd(e.target.value)} />
</Form.Item>
</Form>
<div style={{ textAlign: "center", paddingTop: "1.5rem" }}>
<Button className={styles.cancel} >
取消
</Button>
<Button onClick={submit} disabled={loading2} className={styles.determine} style={{ marginLeft: "16px" }} type="primary" >
保存
</Button>
</div>
</div >
)
}
// 修改密码界面
const PassView = () => {
return (
<div>
<div style={{ textAlign: "center", marginBottom: "1.5rem" }}>
<Checkbox checked={passType === 1 ? true : false} onChange={(e) => passOnChange(e, 1)}><span>原密码</span></Checkbox>
<Checkbox checked={passType === 2 ? true : false} style={{ marginLeft: "22%" }} onChange={(e) => passOnChange(e, 2)}><span>动态密码</span></Checkbox>
</div>
{
passType === 1 ? <Ymm /> : <Dtmm />
}
</div>
)
}
useEffect(() => {
userHospitalApiFn()
}, [])
return (
<div className={styles.informationWrap}>
<div className={styles.setWrap}>
<div className={styles.topBar}>
<div onClick={() => activeChange(1)} className={`${styles.leftBtn} ${current === 1 ? styles.activeLeft : null} `}>个人信息</div>
<div onClick={() => activeChange(2)} className={`${styles.rightBtn} ${current === 2 ? styles.activeRight : null} `}>修改密码</div>
</div>
</div>
<div className={styles.conten}>
<div className={styles.conWrap}>
{
current === 1 ? <InfoView /> : <PassView />
}
</div>
</div>
</div >
)
}
function mapStateToProps(state: any) {
return state.indexModel
}
export default connect(mapStateToProps)(Index)