Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

475 строки
27 KiB

  1. import { useFormik } from 'formik';
  2. import * as yup from 'yup';
  3. import * as React from "react";
  4. import * as HttpUtils from "utils/HttpUtils";
  5. import * as UrlUtils from "utils/ApiPathConst";
  6. import { useNavigate } from "react-router-dom";
  7. import { useDispatch } from "react-redux";
  8. import { handleLogoutFunction,
  9. // handleLogin
  10. } from 'auth/index';
  11. import useJwt from "auth/jwt/useJwt";
  12. import {
  13. Grid,
  14. Typography,
  15. Button,
  16. // RadioGroup,
  17. // Dialog, DialogTitle, DialogContent, DialogActions,
  18. Stack,
  19. InputLabel,
  20. // OutlinedInput,
  21. FormHelperText,
  22. TextField,
  23. IconButton, InputAdornment,
  24. // Box,
  25. // FormControl
  26. } from '@mui/material';
  27. import Loadable from 'components/Loadable';
  28. const LoadingComponent = Loadable(React.lazy(() => import('pages/extra-pages/LoadingComponent')));
  29. import titleBackgroundImg from 'assets/images/dashboard/gazette-bar.png'
  30. // import ForwardIcon from '@mui/icons-material/Forward';
  31. import MainCard from 'components/MainCard';
  32. import {PNSPS_LONG_BUTTON_THEME} from "themes/buttonConst";
  33. import {ThemeProvider} from "@emotion/react";
  34. import {FormattedMessage, useIntl} from "react-intl";
  35. import { EyeInvisibleOutlined, EyeOutlined } from '@ant-design/icons';
  36. import axios from 'axios';
  37. import { useParams,Link } from 'react-router-dom';
  38. import CancelOutlinedIcon from '@mui/icons-material/CancelOutlined';
  39. // ==============================|| DASHBOARD - DEFAULT ||============================== //
  40. const Index = () => {
  41. const dispatch = useDispatch()
  42. const navigate = useNavigate()
  43. const [showPassword, setShowPassword] = React.useState(false);
  44. const [showConfirmPassword, setshowConfirmPassword] = React.useState(false);
  45. const [isLoading, setLoding] = React.useState(true);
  46. const [verifyState, setVerifyState] = React.useState(null)
  47. const [enterUseEffect, setEnterUseEffect] = React.useState(false)
  48. const [username, setUsername] = React.useState("")
  49. // const { setLocale } = React.useContext(LocaleContext);
  50. const params = useParams()
  51. const intl = useIntl();
  52. React.useEffect(() => {
  53. // console.log(params);
  54. setEnterUseEffect(true)
  55. }, []);
  56. React.useEffect(() => {
  57. // console.log("if (enterUseEffect) handleVerify()");
  58. if (enterUseEffect){
  59. handleVerify()
  60. }
  61. }, [enterUseEffect])
  62. const handleVerify = async () => {
  63. // console.log(params);
  64. await axios.get(UrlUtils.GET_FORGOT_PASSWORD_VERIFY_USER_ACCOUNT, {
  65. params: {
  66. email: decodeURIComponent(params.email),
  67. emailVerifyHash: decodeURIComponent(params.verifyCode)
  68. }
  69. }).then(
  70. (response)=>{
  71. if (response.status === 200 && response.data) {
  72. // console.log(response)
  73. setUsername(response.data.username)
  74. setVerifyState(true)
  75. } else {
  76. setVerifyState(false)
  77. }
  78. setLoding(false)
  79. }
  80. ).catch(error => {
  81. console.log(error)
  82. setVerifyState(false)
  83. setLoding(false)
  84. });
  85. }
  86. const goLogin = async (values) =>{
  87. dispatch(handleLogoutFunction());
  88. HttpUtils.post({
  89. url: UrlUtils.POST_FORGOT_PASSWORD_NEW_PASSWORD,
  90. params:{
  91. username: username,
  92. newPassword: values.password,
  93. emailVerifyHash: decodeURIComponent(params.verifyCode)
  94. },
  95. onSuccess: () => {
  96. useJwt
  97. .login({ username: username, password: values.password })
  98. .then((
  99. // response
  100. ) => {
  101. // console.log(response)
  102. navigate('/forgot/password/success');
  103. location.reload()
  104. // setSumitting(false)
  105. })
  106. .catch((error) => {
  107. console.error(error)
  108. });
  109. },
  110. onFail: (response)=>{
  111. console.log("Fail");
  112. console.log(response);
  113. window.location.assign("/iamsmart/loginFail");
  114. },
  115. onError:(error)=>{
  116. console.log(error);
  117. window.location.assign("/iamsmart/loginFail");
  118. }
  119. });
  120. }
  121. const BackgroundHead = {
  122. backgroundImage: `url(${titleBackgroundImg})`,
  123. width: 'auto',
  124. height: 'auto',
  125. backgroundSize: 'contain',
  126. backgroundRepeat: 'no-repeat',
  127. backgroundColor: '#0C489E',
  128. backgroundPosition: 'right'
  129. }
  130. const handleClickShowPassword = () => {
  131. setShowPassword(!showPassword);
  132. };
  133. const handleClickShowConfirmPassword = () => {
  134. setshowConfirmPassword(!showConfirmPassword);
  135. };
  136. const handleMouseDownPassword = (event) => {
  137. event.preventDefault();
  138. };
  139. const changePassword = (
  140. // value
  141. ) => {
  142. // const temp = strengthIndicator(value);
  143. // setLevel(strengthColorChi(temp));
  144. };
  145. function getMaxErrStr(num, fieldname){
  146. return intl.formatMessage({ id: 'noMoreThenNWords' },{num:num, fieldname:fieldname?intl.formatMessage({ id: fieldname})+": ":""});
  147. }
  148. const formik = useFormik({
  149. enableReinitialize: true,
  150. initialValues: {
  151. // username: '',
  152. password: '',
  153. confirmPassword: '',
  154. // emailVerifyHash: '',
  155. },
  156. validationSchema: yup.object().shape({
  157. // emailVerifyHash: yup.string().required(intl.formatMessage({id: 'requireSecurityCode'})),
  158. // username: yup.string().required(intl.formatMessage({id: 'requireUsername'})),
  159. password: yup.string().min(8, intl.formatMessage({id: 'atLeast8CharPassword'}))
  160. .max(60, getMaxErrStr(60))
  161. .required(intl.formatMessage({id: 'requirePassword'}))
  162. .matches(/^\S*$/, { message: (intl.formatMessage({id: 'noSpacePassword'}))})
  163. .matches(/^(?=.*[a-z])/, { message: intl.formatMessage({id: 'atLeastOneSmallLetter'})})
  164. .matches(/^(?=.*[A-Z])/, { message: intl.formatMessage({id: 'atLeastOneCapLetter'})})
  165. .matches(/^(?=.*[0-9])/, { message: intl.formatMessage({id: 'atLeast1Number'})})
  166. .matches(/^(?=.*\W)/, { message: intl.formatMessage({id: 'atLeast1SpecialChar'})}),
  167. confirmPassword: yup.string().min(8, intl.formatMessage({id: 'atLeast8CharPassword'}))
  168. .max(60, getMaxErrStr(60))
  169. .required(intl.formatMessage({id: 'pleaseConfirmPassword'}))
  170. .oneOf([yup.ref('password'), null], intl.formatMessage({id: 'samePassword'})),
  171. }),
  172. onSubmit: values => {
  173. // console.log(values)
  174. goLogin(values)
  175. }
  176. });
  177. return (
  178. isLoading || verifyState == null ?
  179. <Grid container sx={{ minHeight: '87vh', mb: 3 }} direction="column" justifyContent="center" alignItems="center">
  180. <Grid item>
  181. <LoadingComponent />
  182. </Grid>
  183. </Grid>
  184. :
  185. <Grid container sx={{ minHeight: '87vh', mb: 3 }} direction="column" alignItems="center">
  186. <Grid item xs={12} md={12} width="100%" >
  187. <div style={BackgroundHead}>
  188. <Stack direction="row" height='70px' justifyContent="flex-start" alignItems="center">
  189. <Typography component="h1" ml={15} color='#FFF' variant="h4" sx={{display: { xs: 'none', sm: 'none', md: 'block' }}}>
  190. <FormattedMessage id="forgotUserPassword"/>
  191. </Typography>
  192. </Stack>
  193. </div>
  194. </Grid>
  195. {/* <Grid item xs={12} width={{xs:"90%", sm:"90%", md:"60%", lg:"60%"}}>
  196. <Button
  197. aria-label={intl.formatMessage({id: 'back'})}
  198. title={intl.formatMessage({id: 'back'})}
  199. sx={{ ml: 0, mt: 2.5 }} style={{ border: '2px solid' }} variant="outlined" onClick={() => { navigate(-1) }}
  200. >
  201. <ForwardIcon style={{ height: 30, width: 50, transform: "rotate(180deg)" }} />
  202. </Button>
  203. </Grid> */}
  204. {/* <Grid item xs={12}>
  205. <Typography variant="pnspsFormParagraphBold">申請公共啟事</Typography>
  206. </Grid> */}
  207. <Grid item xs={12} md={12} width={{ sx:"90%", sm:"90%",md: "60%", xs: "90%" }}>
  208. <MainCard
  209. sx={{
  210. maxWidth: { xs: 400, sm:730, md:800, lg: 1000 },
  211. margin: { sm: 0, md: 3 },
  212. '& > *': {
  213. flexGrow: 1,
  214. flexBasis: '50%'
  215. }
  216. }}
  217. content={false}
  218. border={false}
  219. boxShadow
  220. >
  221. <form onSubmit={formik.handleSubmit}>
  222. {verifyState ?
  223. // SUCCESS page
  224. <Grid container spacing={4} sx={{ minHeight: {xs:"80vh", sm:"50vh", md: "50vh", lg:"70vh", xl:"50vh"} }} direction="column" justifyContent="flex-start" alignItems="center">
  225. <Grid container direction="column" alignItems="center">
  226. <Grid item xs={12} md={12} lg={12} sx={{ mb: 1, mt:5, }}>
  227. <Typography display="inline" variant="h4">
  228. <FormattedMessage id="verifySuccess"/>
  229. </Typography>
  230. </Grid>
  231. <Grid item xs={12} md={12} lg={12} sx={{ mb: 1,}}>
  232. <InputLabel htmlFor="email-login-title3">
  233. <Typography variant="h5" >
  234. <FormattedMessage id="setNewPassword"/>
  235. </Typography>
  236. </InputLabel>
  237. </Grid>
  238. </Grid>
  239. {/* <Grid item xs={12} md={12} lg={12} width={{xs:"70%", sm:"60%",md:"50%", lg:"50%"}}>
  240. <Grid container direction="row" justifyContent="flex-start">
  241. <Grid item xs={12} md={12} lg={12}>
  242. <TextField
  243. fullWidth
  244. onChange={formik.handleChange}
  245. id="emailVerifyHash"
  246. name="emailVerifyHash"
  247. label={intl.formatMessage({id: 'securityCode'}) + ":"}
  248. placeholder={intl.formatMessage({id: 'securityCode'})}
  249. defaultValue={formik.values.emailVerifyHash}
  250. value={formik.values.emailVerifyHash}
  251. error={Boolean(formik.touched.emailVerifyHash && formik.errors.emailVerifyHash)}
  252. onBlur={formik.handleBlur}
  253. inputProps={{
  254. maxLength: 50,
  255. onKeyDown: (e) => {
  256. if (e.key === 'Enter') {
  257. e.preventDefault();
  258. }
  259. },
  260. }}
  261. InputLabelProps={{
  262. shrink: true
  263. }}
  264. />
  265. </Grid>
  266. {formik.touched.emailVerifyHash && formik.errors.emailVerifyHash && (
  267. <FormHelperText error id="standard-weight-helper-text-username-login">
  268. {formik.errors.emailVerifyHash}
  269. </FormHelperText>
  270. )}
  271. </Grid>
  272. </Grid> */}
  273. <Grid item xs={12} md={12} lg={12} width={{xs:"70%", sm:"60%",md:"50%", lg:"50%"}}>
  274. <Grid container direction="row" justifyContent="flex-start">
  275. <Grid item xs={12} md={12} lg={12}>
  276. <TextField
  277. fullWidth
  278. id="username"
  279. name="username"
  280. label={intl.formatMessage({id: 'userLoginName'}) + ":"}
  281. placeholder={intl.formatMessage({id: 'userLoginName'})}
  282. // defaultValue={username}
  283. value={username}
  284. disabled={true} />
  285. </Grid>
  286. </Grid>
  287. </Grid>
  288. <Grid item xs={12} md={12} lg={12} width={{xs:"70%", sm:"60%",md:"50%", lg:"50%"}}>
  289. <Grid container direction="row" justifyContent="flex-start">
  290. <Grid item xs={12} md={12} lg={12}>
  291. <TextField
  292. fullWidth
  293. autoFocus
  294. onChange={(e) => {
  295. formik.handleChange(e);
  296. changePassword(e.target.value);
  297. }}
  298. id="password"
  299. type={showPassword ? 'text' : 'password'}
  300. name="password"
  301. label={intl.formatMessage({id: 'newPassword'}) + ":"}
  302. placeholder={intl.formatMessage({id: 'newPassword'})}
  303. // defaultValue={formik.values.password.trim()}
  304. value={formik.values.password.trim()}
  305. error={Boolean(formik.touched.password && formik.errors.password)}
  306. onBlur={formik.handleBlur}
  307. inputProps={{
  308. onKeyDown: (e) => {
  309. if (e.key === 'Enter') {
  310. e.preventDefault();
  311. }
  312. },
  313. }}
  314. InputLabelProps={{
  315. shrink: true
  316. }}
  317. InputProps={{
  318. endAdornment:(
  319. <InputAdornment position="end">
  320. <IconButton
  321. aria-label={intl.formatMessage({
  322. id: showPassword ? "ariaHidePassword" : "ariaShowPassword"
  323. })}
  324. onClick={handleClickShowPassword}
  325. onMouseDown={handleMouseDownPassword}
  326. edge="end"
  327. size="large"
  328. >
  329. {showPassword ? <EyeOutlined /> : <EyeInvisibleOutlined />}
  330. </IconButton>
  331. </InputAdornment>
  332. )
  333. }}
  334. />
  335. </Grid>
  336. {/* <FormControl fullWidth sx={{ mt: 2 }}>
  337. <Grid container spacing={2} alignItems="center">
  338. <Grid item>
  339. <Box sx={{ bgcolor: level?.color, width: 85, height: 8, borderRadius: '7px' }} />
  340. </Grid>
  341. <Grid item>
  342. <Typography variant="subtitle1">
  343. <FormattedMessage id={level ? level?.label : "pwWeak" }/>
  344. </Typography>
  345. </Grid>
  346. </Grid>
  347. </FormControl> */}
  348. {formik.touched.password && formik.errors.password && (
  349. <FormHelperText error id="helper-text-password-signup">
  350. {formik.errors.password}
  351. </FormHelperText>
  352. )}
  353. </Grid>
  354. </Grid>
  355. <Grid item xs={12} md={12} lg={12} width={{xs:"70%", sm:"60%",md:"50%", lg:"50%"}}>
  356. <Grid container direction="row" justifyContent="flex-start">
  357. <Grid item xs={12} md={12} lg={12}>
  358. <TextField
  359. fullWidth
  360. onChange={(e) => {
  361. formik.handleChange(e);
  362. // changePassword(e.target.value);
  363. }}
  364. id="confirmPassword"
  365. type={showConfirmPassword ? 'text' : 'password'}
  366. name="confirmPassword"
  367. label={intl.formatMessage({id: 'confirmPassword'}) + ":"}
  368. placeholder={intl.formatMessage({id: 'confirmPassword'})}
  369. // defaultValue={formik.values.confirmPassword.trim()}
  370. value={formik.values.confirmPassword.trim()}
  371. error={Boolean(formik.touched.confirmPassword && formik.errors.confirmPassword)}
  372. onBlur={formik.handleBlur}
  373. inputProps={{
  374. maxLength: 50,
  375. onKeyDown: (e) => {
  376. if (e.key === 'Enter') {
  377. e.preventDefault();
  378. }
  379. },
  380. }}
  381. InputLabelProps={{
  382. shrink: true
  383. }}
  384. InputProps={{
  385. endAdornment:(
  386. <InputAdornment position="end">
  387. <IconButton
  388. aria-label={intl.formatMessage({
  389. id: showConfirmPassword ? "ariaHidePassword" : "ariaShowPassword"
  390. })}
  391. aria-describedby="helper-text-confirmPassword-signup"
  392. onClick={handleClickShowConfirmPassword}
  393. onMouseDown={handleMouseDownPassword}
  394. edge="end"
  395. size="large"
  396. >
  397. {showConfirmPassword ? <EyeOutlined /> : <EyeInvisibleOutlined />}
  398. </IconButton>
  399. </InputAdornment>
  400. )
  401. }}
  402. />
  403. </Grid>
  404. {formik.touched.confirmPassword && formik.errors.confirmPassword && (
  405. <FormHelperText error id="helper-text-confirmPassword-signup">
  406. {formik.errors.confirmPassword}
  407. </FormHelperText>
  408. )}
  409. </Grid>
  410. </Grid>
  411. <Grid item xs={12} md={12} lg={12} mt={1} sx={{mb:3}}>
  412. <ThemeProvider theme={PNSPS_LONG_BUTTON_THEME}>
  413. <Button
  414. aria-label={intl.formatMessage({id: 'confirm'})}
  415. variant="contained"
  416. type="submit"
  417. // onClick={()=>goLogin()}
  418. >
  419. <FormattedMessage id="confirm"/>
  420. </Button>
  421. </ThemeProvider>
  422. </Grid>
  423. </Grid>
  424. :
  425. // ERROR page
  426. <Grid container spacing={4} sx={{ minHeight: {xs:"80vh", sm:"70vh", md: "70vh", lg:"70vh", xl:"50vh"} }} direction="column" justifyContent="flex-start" alignItems="center">
  427. <Grid item xs={12} md={12} lg={12} sx={{ mb: 1, mt:5, display: { xs: 'none', sm: 'none', md: 'block' } }}>
  428. {/* <Button disabled={true} hidden={true} variant="contained" type="submit" sx={{ fontSize: 12,height:'25px'}}>Submit</Button> */}
  429. <CancelOutlinedIcon color="error" sx={{ width: "200px", height: "200px" }} />
  430. </Grid>
  431. <Grid item xs={12} md={12} lg={12} sx={{ mb: 1, mt:5, ml:2, display: { xs: 'none', sm: 'none', md: 'block' } }}>
  432. <Typography display="inline" variant="h4">
  433. <FormattedMessage id="verifyFail"/>
  434. </Typography>
  435. </Grid>
  436. <Grid item xs={12} md={12} lg={12} sx={{ mb: 1, mt:5, display: { xs: 'none', sm: 'none', md: 'block' } }}>
  437. <Button color="error" variant="outlined" component={Link} to="/login">
  438. <Typography variant="h5">
  439. <FormattedMessage id="backToLogin"/>
  440. </Typography>
  441. </Button>
  442. </Grid>
  443. </Grid>
  444. }
  445. <Grid container spacing={4} sx={{ minHeight: {xs:"80vh", sm:"70vh", md: "70vh", lg:"70vh", xl:"50vh"} }} direction="column" justifyContent="flex-start" alignItems="center">
  446. </Grid>
  447. </form>
  448. </MainCard>
  449. </Grid>
  450. </Grid>
  451. );
  452. };
  453. export default Index;