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

ReactJS基于MUI时间选择器实现均分时间槽功能

MUI时间选择器均分时间槽实现

核心计算逻辑

  • 校验输入合法性:确认起止时间已选择、槽位数为大于0的正整数、结束时间晚于开始时间
  • 计算起止时间的总毫秒差值,除以槽位数得到单个时间槽的时长
  • 从开始时间逐次累加单槽时长,循环生成对应数量的连续时间区间
  • 用moment格式化每段时间为HH:mm格式,拼接成开始-结束的字符串

关键修改点

  • 修正startTime、endTime初始值为null,匹配TimePicker组件的value类型要求
  • 新增槽位数量、计算结果两个响应式状态,绑定到输入框和结果展示区域
  • 给按钮绑定计算点击事件,实现时间分割逻辑
  • 新增结果列表区域,渲染生成后的时间槽

完整可运行代码

import * as React from "react";
import TextField from "@mui/material/TextField";
import { AdapterDateFns } from "@mui/x-date-pickers/AdapterDateFns";
import { LocalizationProvider } from "@mui/x-date-pickers/LocalizationProvider";
import { TimePicker } from "@mui/x-date-pickers/TimePicker";
import { Box } from "@mui/system";
import moment from "moment";
import { Button, Grid, List, ListItem, ListItemText } from "@mui/material";
import Paper from "@mui/material/Paper";
export default function BasicDatePicker() {
  const [startTime, setStartTime] = React.useState(null);
  const [endTime, setEndTime] = React.useState(null);
  const [slotCount, setSlotCount] = React.useState(1);
  const [timeSlots, setTimeSlots] = React.useState([]);

  const calculateSlots = () => {
    if (!startTime || !endTime || slotCount < 1) {
      alert("请完善开始时间、结束时间和槽位数量");
      return;
    }
    const startMoment = moment(startTime);
    const endMoment = moment(endTime);
    if (!endMoment.isAfter(startMoment)) {
      alert("结束时间必须晚于开始时间");
      return;
    }
    const totalDuration = endMoment.diff(startMoment);
    const singleSlotDuration = totalDuration / slotCount;
    const slots = [];
    let current = startMoment;
    for (let i = 0; i < slotCount; i++) {
      const slotStart = current.clone();
      const slotEnd = current.add(singleSlotDuration, "ms");
      slots.push(`${slotStart.format("HH:mm")}-${slotEnd.format("HH:mm")}`);
    }
    setTimeSlots(slots);
  };

  return (
    <Box
      component="main"
      sx={{ flexGrow: 1, p: 3 }}
      style={{ marginTop: "100px" }}
    >
      <LocalizationProvider
        dateAdapter={AdapterDateFns}
        sx={{ flexGrow: 1, p: 3 }}
      >
        <Box
          sx={{
            display: "flex",
            flexWrap: "wrap",
            "& > :not(style)": {
              m: "0 auto",
              width: 300,
              minHeight: 350,
            },
          }}
        >
          <Paper elevation={3} sx={{p:2}}>
            <Grid container spacing={2}>
              <Grid item xs={12}>
                <TimePicker
                  label="Start Time"
                  value={startTime}
                  onChange={(newValue) => setStartTime(newValue)}
                  renderInput={(params) => <TextField {...params} fullWidth />}
                />
              </Grid>
              <Grid item xs={12}>
                <TimePicker 
                  label="End Time"
                  value={endTime}
                  onChange={(newValue) => setEndTime(newValue)}
                  renderInput={(params) => <TextField {...params} fullWidth />}
                />
              </Grid>
              <Grid item xs={12}>
                <TextField 
                  label="Slot" 
                  variant="outlined"
                  type="number"
                  value={slotCount}
                  onChange={(e) => setSlotCount(Number(e.target.value))}
                  fullWidth
                />
              </Grid>
              <Grid item xs={12} style={{ textAlign: "center" }}>
                <Button variant="contained" onClick={calculateSlots}>生成时间槽</Button> 
              </Grid>
              {timeSlots.length > 0 && (
                <Grid item xs={12}>
                  <List dense>
                    {timeSlots.map((slot, idx) => (
                      <ListItem key={idx}>
                        <ListItemText primary={slot} />
                      </ListItem>
                    ))}
                  </List>
                </Grid>
              )}
            </Grid>
          </Paper>
        </Box>
      </LocalizationProvider>
    </Box>
  );
}

效果参考

时间选择器运行效果

注意事项

  • moment的add方法会修改原时间对象,生成每段开始时间时需要用clone()复制实例,避免时间计算偏移
  • 槽位输入框要绑定number类型,防止传入字符串导致计算异常
  • 如果需要支持跨天时间分割,只需要在计算总时长时判断:如果结束时间早于开始时间,给结束时间加1天即可

内容的提问来源于stack exchange,提问作者Lokesh Bhardwaj

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 10:09:17