antd的组件更加适用于web端,特别是DatePicker组件,在移动端上面能用,但是使用起来十分不顺畅,需要点击才能够实现时间的选择,不太适用移动设备,因此可以嵌套使用antd mobile的组件,提高移动设备上的使用体验。
首先安装antd-mobile
yarn add antd-mobile
import { DatePicker} from 'antd-mobile';
具体代码如下
import React, {useState, useEffect} from 'react';
import './style.less';
import {useNavigate, useLocation} from 'react-router-dom';
import {newRegister} from '../../api';
import {storage} from '@/utils/storage';
import moment from 'moment';
import {Col, Row, Button, Form, Modal, Spin} from 'antd';
import ErrorIcon from '../../components/iconFontGroup/IconError';
import SuccessIcon from '../../components/iconFontGroup/IconFontSuccess';
import ClearIcon from '../../components/iconFontGroup/iconFrontClear';
import {DatePicker} from 'antd-mobile';
const NewRegistration = () => {
const {state} = useLocation();
const [form] = Form.useForm();
const now = new Date();
const ng = useNavigate();
const [loading, setLoading] = useState(false);
const [fileFuc, setFileFuc] = useState(null);
const [visibleEnd, setVisibleEnd] = useState(false);
const [startTime] = useState(moment(new Date().toLocaleString('en-US', {timeZone: 'Asia/Shanghai'})).format('YYYY-MM-DD HH:mm:00'));
const [endTime, setEndTime] = useState(null);
useEffect(() => {
if (startTime&&endTime) {
form.setFieldsValue({
'visitorTime': [startTime, endTime],
});
}
}, [startTime, endTime]);
const urlToFile = async (url, filename, mimeType) => {
const response = await fetch(url);
const data = await response.blob();
return new File([data], filename, {type: mimeType});
};
useEffect(() => {
urlToFile(state?.info?.selfieUrl, 'image.png', 'image/png')
.then((file) => {
setFileFuc(state?.info?.selfieUrl?file:null);
});
}, [state?.info?.selfieUrl]);
const onFinish = (values) => {
setLoading(true);
const formData = new FormData();
values.visitorStartTime=moment(values.visitorTime[0]).format('YYYY-MM-DD HH:mm:ss');
values.visitorEndTime=moment(values.visitorTime[1]).format('YYYY-MM-DD HH:mm:ss');
values.mobile=values?.mobile?values?.mobile:'';
delete values.visitorTime;
for (const key in values) {
if (key==='file') {
formData.append('selfie', fileFuc);
} else {
formData.append(key, values[key]);
}
}
newRegister(formData, 2).then((res) => {
if (res.code===200) {
successModal();
}
}).catch((error) => {
errorModal();
}).finally(() => {
setLoading(false);
});
};
const successModal = () => {
Modal.info({
title: <div className='modal-title' style={{display: 'flex', alignItems: 'center'}}><SuccessIcon style={{marginRight: '10px'}}/>Sign-in successfully</div>,
content: <div className='modal-text'>Welcome to TBCT.</div>,
icon: '',
centered: true,
onOk() {
ng('/register', {state: {type: 'signIn'}});
},
});
};
const errorModal = () => {
Modal.error({
title: <div className='modal-title' style={{display: 'flex', alignItems: 'center'}}><ErrorIcon style={{marginRight: '10px'}}/>Sign-in failed</div>,
content: <div className='modal-text'>Please try again later.</div>,
icon: '',
centered: true,
onOk() {},
});
};
return (
<>
<Spin spinning={loading} style={{marginTop: '280px'}}>
<div className='home-container'>
<div className='home-top'>
Visitor Registration
<div className='log-out' onClick={() => {
storage.clearData('local', 'userInfo');
ng('/login');
}} />
<div className='back-page' onClick={() => {
ng('/home');
}} />
</div>
<div className='home-bg-visit home-bg-form'>
<div className='home-menu home-menu-register-form'>
<div className='home-menu-top-container'>
<div className='new-visitor-menu-top'>
<Form
name="emailLog"
form={form}
onFinish={onFinish}
onFinishFailed={(value) => console.log(value, 'onFinishFailed')}
layout="vertical"
initialValues={{...state?.info, email: state?.email}}
>
<Row gutter={16}>
<Col span={24}>
<Form.Item
label={'Meeting Time'}
name="visitorTime"
rules={[
{
required: true,
message: 'Please select meeting time!',
},
{
validator: (_, value) => {
console.log(value, 'value');
if (value?.length && value[0]&& value[1] &&value[0]===value[1]) {
// eslint-disable-next-line
return Promise.reject('The end time must be greater than the start time');
}
return Promise.resolve();
},
},
]}
>
<>
<div className="date-picker-contain">
<Row className="date-picker-contain-outer">
<Col span={11} className="date-picker-item">
<div
className="date-picker-container-div"
>
{/* 此处使用antd-mobile的DatePicker */}
<DatePicker
precision='minute'
>
{() =>startTime}
</DatePicker>
</div>
</Col>
<Col span={1} className="date-picker-item-it">
<span className='select-Remind'>—</span>
</Col>
<Col span={10} className="date-picker-item">
<div
className="date-picker-container-div"
onClick={() => {
setVisibleEnd(true);
}}
>
{/* antd mobile组件 */}
<DatePicker
className="custom-cascade-picker"
visible={visibleEnd}
onClose={() => {
setVisibleEnd(false);
}}
confirmText={'OK'}
cancelText={'Cancel'}
extra="Please select end time"
precision='minute'
min={now}
onConfirm={(val) => {
setEndTime(moment(val.toString()).format('YYYY-MM-DD HH:mm:ss'));
setVisibleEnd(false);
}}
>
{(value) => endTime ? moment(value).format('YYYY-MM-DD HH:mm:ss') : <span className='select-Remind'>{'Please select end time'}</span>}
</DatePicker>
</div>
</Col>
<Col span={2} className="date-picker-item-svg"
>
{(endTime)&&<div className='clear-item'
onClick={() => {
setEndTime(null);
form.setFieldsValue({
'visitorTime': [],
});
}}
>
<ClearIcon/>
</div>}
</Col>
</Row>
</div>
</>
</Form.Item>
</Col>
</Row>
<Row gutter={16}>
<Col span={12}>
<Form.Item>
<Button className="register-btn register-btn-left register-btn-z-index" onClick={() => {
form.resetFields();
ng('/home');
}}>
Cancel
</Button>
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
>
<Button type="primary" htmlType="submit" className="register-btn register-btn-z-index">
Sign-in
</Button>
</Form.Item>
</Col>
</Row>
</Form>
</div>
<div className='transparent-box'></div>
</div>
</div>
</div>
</div>
</Spin>
</>
);
};
export default NewRegistration;
通过这种形式就可以实现antd mobile嵌套进web端项目了,此处我设置了开始时间和结束时间,
开始时间进去页面自动获取当前系统时间,
因此设置now=new Date(),
结束时间需要大于开始时间,
因此使用了DatePicker的min约束最小时间,
ipad效果:
web端效果: