You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 02:41:27