1.实现手机号码校验提示 和登录返回错误提示

This commit is contained in:
amass 2023-06-21 16:19:29 +08:00
parent 16bc07d970
commit f30bf34432
6 changed files with 104 additions and 44 deletions

View File

@ -5,7 +5,7 @@ import styles from './LoginPage.module.css';
import { useSelector, useDispatch } from 'react-redux' import { useSelector, useDispatch } from 'react-redux'
import { setFlushToken, setAccessToken, setUserInfo, setAgreeAgreement } from "./business/userSlice.js" import { setFlushToken, setAccessToken, setUserInfo, setAgreeAgreement } from "./business/userSlice.js"
import logo from './assets/logo.png'; import logo from './assets/logo.png';
import { Container, Tab, Box, Snackbar, Button } from '@mui/material'; import { Container, Tab, Box, Snackbar, Alert, Button } from '@mui/material';
import TabPanel from '@mui/lab/TabPanel'; import TabPanel from '@mui/lab/TabPanel';
import { TabList } from '@mui/lab'; import { TabList } from '@mui/lab';
import TabContext from '@mui/lab/TabContext'; import TabContext from '@mui/lab/TabContext';
@ -35,6 +35,8 @@ export default function () {
const dispatch = useDispatch(); const dispatch = useDispatch();
const [cookies, setCookie] = useCookies(['accessToken']); const [cookies, setCookie] = useCookies(['accessToken']);
const [value, setValue] = useState("1"); const [value, setValue] = useState("1");
const [message, setMessage] = useState("");
const [openTooltip, setOpenTooltip] = useState(false);
const account = useSelector(state => state.user.account) const account = useSelector(state => state.user.account)
const password = useSelector(state => state.user.password) const password = useSelector(state => state.user.password)
const verificationCode = useSelector(state => state.user.verificationCode) const verificationCode = useSelector(state => state.user.verificationCode)
@ -44,6 +46,10 @@ export default function () {
setValue(newValue); setValue(newValue);
}; };
const handleTooltipClose = () => {
setOpenTooltip(false);
};
const onAgreeChange = (event) => { const onAgreeChange = (event) => {
dispatch(setAgreeAgreement(!agreeAgreement)); dispatch(setAgreeAgreement(!agreeAgreement));
} }
@ -78,6 +84,8 @@ export default function () {
}) })
}).catch(error => { }).catch(error => {
console.log(error) console.log(error)
setMessage(error);
setOpenTooltip(true);
}); });
}; };
@ -123,12 +131,13 @@ export default function () {
</ThemeProvider > </ThemeProvider >
{/* <Button variant="contained" onClick={debug_test}>测试</Button> */} {/* <Button variant="contained" onClick={debug_test}>测试</Button> */}
</div> </div>
{/* <Snackbar <Snackbar
anchorOrigin={{ vertical, horizontal }} anchorOrigin={{ vertical: 'bottom', horizontal: 'center' }}
open={open} open={openTooltip}
onClose={handleClose} autoHideDuration={3500}
message="I love snacks" onClose={handleTooltipClose}
key={vertical + horizontal} >
/> */} <Alert severity="error">{message}</Alert>
</Snackbar>
</div> </div>
} }

View File

@ -206,10 +206,11 @@ const yzs = {
"Access-Control-Allow-Origin": "*", "Access-Control-Allow-Origin": "*",
}, },
}).then(response => response.json()).then((json) => { }).then(response => response.json()).then((json) => {
console.log("flushToken: ", json.result.flushToken); if (json.returnCode != "uc_0000") {
throw json.message;
}
// console.log("flushToken: ", json.result.flushToken);
return json.result.flushToken; return json.result.flushToken;
}).catch(error => {
console.log(error);
}); });
}, },
send_phone_code: function (udid, userCell) { send_phone_code: function (udid, userCell) {

View File

@ -33,4 +33,18 @@ function audioWaveData(url, interval) {
}); });
} }
export { sampleInterval, audioWaveData }; function validatePhoneNumber(phoneNumber) {
if (phoneNumber.length !== 11) {
return false;
}
let reg = /^1\d{10}$/;
return reg.test(phoneNumber);
}
function textHintOfValidatePhoneNumber(phoneNumber) {
if (validatePhoneNumber(phoneNumber)) return "";
if (phoneNumber.length === 0) return "请输入手机号码"
return "请输入正确的手机号码";
}
export { sampleInterval, audioWaveData, validatePhoneNumber, textHintOfValidatePhoneNumber };

View File

@ -6,10 +6,12 @@ import { useSelector, useDispatch } from 'react-redux'
import { setAccount, setVerificationCode } from "../business/userSlice.js" import { setAccount, setVerificationCode } from "../business/userSlice.js"
import yzs from "../business/request.js"; import yzs from "../business/request.js";
import Agreement from "./Agreement.js"; import Agreement from "./Agreement.js";
import { validatePhoneNumber, textHintOfValidatePhoneNumber } from "../business/utilities.js"
export default function ({ udid, agreeAgreement, onAgreeChange }) { export default function ({ udid, agreeAgreement, onAgreeChange }) {
const dispatch = useDispatch(); const dispatch = useDispatch();
const code = useRef(null); const code = useRef(null);
const [firstEnter, setFirstEnter] = useState(true);
const [seconds, setSeconds] = useState(0); // 倒计时 const [seconds, setSeconds] = useState(0); // 倒计时
const account = useSelector(state => state.user.account) const account = useSelector(state => state.user.account)
@ -17,7 +19,10 @@ export default function ({ udid, agreeAgreement, onAgreeChange }) {
const handleInputChange = (event) => { const handleInputChange = (event) => {
const { name, value } = event.target; const { name, value } = event.target;
if (name === 'username') dispatch(setAccount(value)); if (name === 'username') {
dispatch(setAccount(value));
if (firstEnter) setFirstEnter(false);
}
if (name === 'password') dispatch(setVerificationCode(value)); if (name === 'password') dispatch(setVerificationCode(value));
}; };
@ -50,11 +55,15 @@ export default function ({ udid, agreeAgreement, onAgreeChange }) {
<TextField <TextField
name="username" name="username"
autoComplete="username" autoComplete="username"
label="请输入手机号码" hiddenLabel
placeholder="请输入手机号码"
variant="outlined" variant="outlined"
value={account} value={account}
color="primary" color="primary"
size="small"
fullWidth fullWidth
error={firstEnter ? false : !validatePhoneNumber(account)}
helperText={firstEnter ? "" : textHintOfValidatePhoneNumber(account)}
onChange={handleInputChange} onChange={handleInputChange}
InputProps={{ InputProps={{
startAdornment: ( startAdornment: (
@ -63,16 +72,22 @@ export default function ({ udid, agreeAgreement, onAgreeChange }) {
</InputAdornment> </InputAdornment>
), ),
}} }}
sx={{
minHeight: 64,
}}
/> />
<TextField <TextField
// sx={{ paddingTop: 4 }} sx={{
minHeight: 50,
}}
hiddenLabel
fullWidth fullWidth
margin="normal"
name="password" name="password"
label="请输入验证码" placeholder="请输入验证码"
type="password" type="text"
autoComplete="current-password" autoComplete="current-password"
variant="outlined" variant="outlined"
size="small"
value={verificationCode} value={verificationCode}
onChange={handleInputChange} onChange={handleInputChange}
InputProps={{ InputProps={{
@ -96,6 +111,7 @@ export default function ({ udid, agreeAgreement, onAgreeChange }) {
fullWidth fullWidth
disabled={!agreeAgreement} disabled={!agreeAgreement}
sx={{ sx={{
marginTop: 1.5,
backgroundColor: "#FF595A", backgroundColor: "#FF595A",
'&:hover': { '&:hover': {
backgroundColor: '#FF595A', backgroundColor: '#FF595A',

View File

@ -1,18 +1,23 @@
import React from 'react'; import React, { useState } from 'react';
import { Container, TextField, Button, InputAdornment } from "@mui/material"; import { Container, TextField, Button, InputAdornment } from "@mui/material";
import PhoneIphoneIcon from '@mui/icons-material/PhoneIphone'; import PhoneIphoneIcon from '@mui/icons-material/PhoneIphone';
import LockIcon from '@mui/icons-material/Lock'; import LockIcon from '@mui/icons-material/Lock';
import { useSelector, useDispatch } from 'react-redux' import { useSelector, useDispatch } from 'react-redux'
import { setAccount, setPassword } from "../business/userSlice.js" import { setAccount, setPassword } from "../business/userSlice.js"
import Agreement from './Agreement.js'; import Agreement from './Agreement.js';
import { validatePhoneNumber, textHintOfValidatePhoneNumber } from "../business/utilities.js"
export default function ({ agreeAgreement, onAgreeChange }) { export default function ({ agreeAgreement, onAgreeChange }) {
const dispatch = useDispatch(); const dispatch = useDispatch();
const account = useSelector(state => state.user.account) const account = useSelector(state => state.user.account)
const password = useSelector(state => state.user.password) const password = useSelector(state => state.user.password)
const [firstEnter, setFirstEnter] = useState(true);
const handleInputChange = (event) => { const handleInputChange = (event) => {
const { name, value } = event.target; const { name, value } = event.target;
if (name === 'username') dispatch(setAccount(value)); if (name === 'username') {
dispatch(setAccount(value));
if (firstEnter) setFirstEnter(false);
}
if (name === 'password') dispatch(setPassword(value)); if (name === 'password') dispatch(setPassword(value));
}; };
@ -25,8 +30,12 @@ export default function ({ agreeAgreement, onAgreeChange }) {
<TextField <TextField
name="username" name="username"
autoComplete="username" autoComplete="username"
label="请输入手机号码" hiddenLabel
placeholder="请输入手机号码"
variant="outlined" variant="outlined"
size="small"
error={firstEnter ? false : !validatePhoneNumber(account)}
helperText={firstEnter ? "" : textHintOfValidatePhoneNumber(account)}
value={account} value={account}
fullWidth fullWidth
onChange={handleInputChange} onChange={handleInputChange}
@ -37,16 +46,22 @@ export default function ({ agreeAgreement, onAgreeChange }) {
</InputAdornment> </InputAdornment>
), ),
}} }}
sx={{
minHeight: 64,
}}
/> />
<TextField <TextField
// sx={{ paddingTop: 4 }} sx={{
minHeight: 50,
}}
fullWidth fullWidth
margin="normal"
name="password" name="password"
label="请输入密码" hiddenLabel
placeholder="请输入密码"
type="password" type="password"
autoComplete="current-password" autoComplete="current-password"
variant="outlined" variant="outlined"
size="small"
value={password} value={password}
onChange={handleInputChange} onChange={handleInputChange}
InputProps={{ InputProps={{
@ -64,6 +79,7 @@ export default function ({ agreeAgreement, onAgreeChange }) {
fullWidth fullWidth
disabled={!agreeAgreement} disabled={!agreeAgreement}
sx={{ sx={{
marginTop: 1.5,
backgroundColor: "#FF595A", backgroundColor: "#FF595A",
'&:hover': { '&:hover': {
backgroundColor: '#FF595A', backgroundColor: '#FF595A',

View File

@ -58,28 +58,32 @@ const paintCanvas = ({
canvas, waveformData, duration, scrollLeft, leftPadding, canvasHeight, pointWidth, pointMargin, interval canvas, waveformData, duration, scrollLeft, leftPadding, canvasHeight, pointWidth, pointMargin, interval
}) => { }) => {
// console.log("paintCanvas", duration, canvasHeight, canvas.width, scrollLeft); // console.log("paintCanvas", duration, canvasHeight, canvas.width, scrollLeft);
const context = canvas.getContext('2d'); try {
context.save(); const context = canvas.getContext('2d');
context.clearRect(0, 0, canvas.width, canvas.height); context.save();
context.translate(leftPadding, 0);; context.clearRect(0, 0, canvas.width, canvas.height);
context.translate(leftPadding, 0);;
drawText(context, duration, interval); // 画刻度尺 drawText(context, duration, interval); // 画刻度尺
waveformData.forEach((p, i) => { waveformData.forEach((p, i) => {
context.beginPath() context.beginPath()
const coordinates = pointCoordinates({ const coordinates = pointCoordinates({
index: i, index: i,
pointWidth, pointWidth,
pointMargin, pointMargin,
canvasHeight, canvasHeight,
maxAmplitude: canvasHeight - 30, // 留出空间画时间轴 maxAmplitude: canvasHeight - 30, // 留出空间画时间轴
amplitude: p, amplitude: p,
}) })
context.rect(...coordinates) context.rect(...coordinates)
context.fillStyle = (coordinates[0] <= scrollLeft) ? '#FF595A' : '#ABB5BC' context.fillStyle = (coordinates[0] <= scrollLeft) ? '#FF595A' : '#ABB5BC'
context.fill() context.fill()
}); });
context.restore(); context.restore();
} catch (error) {
console.log(error);
}
} }
// duration ms // duration ms