React中如何避免重复添加会议及禁用过去日期?
React会议模块两个需求的实现方案
1. 阻止指定团队在已有会议时段添加新会议
要实现这个需求,需要先获取选中团队的所有现有会议,再在提交新会议前校验时间段是否重叠。结合你现有代码,修改如下:
步骤说明:
- 新增状态存储选中团队的会议列表
- 监听团队选择变化,实时获取对应团队的会议数据
- 提交时校验新会议时间段与现有会议是否冲突
修改后的完整代码:
function Insert(): JSX.Element { const navigate = useNavigate(); const [teams, setTeams] = useState<TeamModel[]>([]); // 新增:存储选中团队的现有会议 const [teamMeetings, setTeamMeetings] = useState<MeetingModel[]>([]); const { register, handleSubmit, watch } = useForm<MeetingModel>(); // 监听选中的团队ID const selectedTeamId = watch("teamId"); useEffect(() => { meetingsService.getAllTeams() .then(teams => setTeams(teams)) .catch(err => alert(err.message)); }, []); // 新增:当选中团队变化时,获取该团队的所有会议 useEffect(() => { if (selectedTeamId) { meetingsService.getMeetingsByTeamId(selectedTeamId) .then(meetings => setTeamMeetings(meetings)) .catch(err => alert(err.message)); } else { setTeamMeetings([]); } }, [selectedTeamId]); // 新增:时间段冲突校验函数 function isTimeConflict(newMeeting: MeetingModel): boolean { const newStart = new Date(newMeeting.meetingStart); const newEnd = new Date(newMeeting.meetingEnd); return teamMeetings.some(meeting => { const existingStart = new Date(meeting.meetingStart); const existingEnd = new Date(meeting.meetingEnd); // 冲突判断逻辑:新会议开始早于现有会议结束,且新会议结束晚于现有会议开始 return newStart < existingEnd && newEnd > existingStart; }); } async function send(meeting: MeetingModel) { // 新增:提交前先校验冲突 if (isTimeConflict(meeting)) { alert("该团队在所选时段已有会议,请重新选择时间"); return; } try { await meetingsService.addMeeting(meeting); alert("Meeting has been added"); navigate("/meetings"); } catch (err: any) { alert(err.message); } } return ( <div className="Insert"> <h2>Add Meeting</h2> <img src={teamImage} alt="Team work" /> <form onSubmit={handleSubmit(send)}> <label>Select Team: </label> <select defaultValue="" {...register("teamId")} required> <option disabled value="">Select Team</option> {teams.map(t => <option key={t.teamId} value={t.teamId}>{t.teamName}</option>)} </select> <label>Start of meeting:</label> <input type="datetime-local" {...register("meetingStart")} required /> <label>End of meeting: </label> <input type="datetime-local" {...register("meetingEnd")} required /> <label>Description: </label> <input type="text" {...register("description")} required minLength={1} maxLength={100} /> <label>Meeting room: </label> <input type="text" {...register("meetingRoom")} required minLength={1} maxLength={100} /> <button>Add</button> </form> </div> ); }
关键细节:
- 用
watch监听选中的团队ID,实时拉取对应会议数据 - 冲突校验函数覆盖了所有时间段重叠场景(包含、交叉等)
- 提交前先做前端校验,避免无效的后端请求
2. 禁用datetime-local输入框的过去日期
datetime-local输入框支持min属性,只需将其设置为当前时间的ISO格式(精确到分钟),即可禁用过去的时间。
修改后的输入框代码:
// 计算当前时间的最小可选值(截取到分钟,匹配datetime-local格式要求) const minDateTime = new Date().toISOString().slice(0, 16); // 应用到两个时间输入框 <label>Start of meeting:</label> <input type="datetime-local" {...register("meetingStart")} required min={minDateTime} /> <label>End of meeting: </label> <input type="datetime-local" {...register("meetingEnd")} required min={minDateTime} />
关键细节:
new Date().toISOString()生成的格式是YYYY-MM-DDTHH:mm:ss.sssZ,用slice(0,16)截取到分钟部分,符合datetime-local的格式要求- 给开始和结束时间输入框都加上
min属性,确保两个时间都不能早于当前时间
内容的提问来源于stack exchange,提问作者DennisR93
相关产品推荐
相关产品推荐

