WorkCalendar.js 8.35 KB
/* eslint-disable */
import React, { useRef, useState, useMemo, useEffect } from "react";
import {
  Calendar,
  Tooltip,
  Row,
  Col,
  Carousel,
  Form,
  Badge,
  Avatar,
  Modal,
  Input,
  message,
  Select,
  DatePicker
} from "antd-v4";
import { LeftOutlined, RightOutlined } from "@ant-design/icons";
import moment from "moment";
import * as commonUtils from "@/utils/utils"; /* 通用方法 */
import styles from "./index.less";

const WorkCalendar = props => {
  const [year, setYear] = useState(new Date().getFullYear());
  const monthArr = [1, 2, 3, 4, 5, 6];
  const [checkedDate, setCheckedDate] = useState([]);
  const [detailModalOption, setDetailModalOption] = useState(null);
  const clickTimer = useRef(null);

  useEffect(() => {
    const sDefaultYear = props.masterData?.tYear || moment();
    setYear(moment(sDefaultYear).format('YYYY'));
  }, [props.masterData?.tYear])

  const handleSaveData = values => {
    const slaveData = commonUtils.isNotEmptyArr(props.slaveData)
      ? [
          ...props.slaveData.filter(
            i => i && Object.prototype.hasOwnProperty.call(i, "sTemplateName")
          )
        ]
      : [];

    const iIndex = slaveData.findIndex(
      slaveItem => slaveItem.sId === values.sId
    );
    if (iIndex === -1) {
      slaveData.push({
        sParentId: props.masterData.sId,
        sId: commonUtils.createSid(),
        handleType: "add",
        sCalDate: detailModalOption?.date,
        ...values
      });
    } else {
      slaveData[iIndex] = {
        ...slaveData[iIndex],
        sParentId: props.masterData.sId,
        handleType: slaveData[iIndex]?.handleType || "update",
        ...values
      };
    }

    props.onSaveState({ slaveData: slaveData });
    setDetailModalOption(null);
  };

  const handleCancel = () => {
    setDetailModalOption(null);
  };

  const dateFullCellRender = (value, item) => {
    const { slaveData = [] } = props;
    const panelDate = value.format("YYYY-MM-DD");
    let detailContent = "";
    const iIndex = slaveData?.findIndex(item => item?.sCalDate === panelDate);
    const hasDetail = iIndex !== -1;
    let status = 'default';
    if (hasDetail) {
      const { sTemplateName } = slaveData[iIndex] || {};
      detailContent = sTemplateName;
      status = {
        '节日': 'success',
        '加班': 'error',
      }[sTemplateName] || 'default'
    }

    // 自定义日期单元格内容
    const customCell = (
      <div
        className={`custom-cell `}
        onClick={() => {
          clearTimeout(clickTimer.current);
          clickTimer.current = setTimeout(() => {
            if (!detailModalOption) {
              if (checkedDate.includes(panelDate)) {
                setCheckedDate(pre => pre.filter(item => item !== panelDate));
              } else {
                setCheckedDate(pre => [...pre, panelDate]);
              }
            }
          }, 150);
        }}
        onDoubleClick={() => {
          clearTimeout(clickTimer.current);
          setDetailModalOption({ date: panelDate });
        }}
      >
        <div className={`${hasDetail ? "date-mark" : ""}`}>
          <Badge count={0} size="small">
            <Tooltip title={detailContent} placement="bottom" color={"#000"}>
              <Avatar
                shape="square"
                style={{
                  backgroundColor: checkedDate.includes(panelDate)
                    ? "#fde4e5"
                    : "#fff",
                  color: [6, 0].includes(moment(panelDate).day())
                    ? "#fd9498"
                    : "#000"
                }}
              >
                {Number(panelDate.slice(-2))}
              </Avatar>
              <p>
                {detailContent && (
                  <Badge status={status} text={detailContent} />
                )}
              </p>
            </Tooltip>
          </Badge>
        </div>
      </div>
    );

    return customCell;
  };

  const preClick = () => {
    refCarousel?.current?.prev();
  };

  const nextClick = () => {
    refCarousel?.current?.next();
  };

  const refCarousel = useRef();

  return (
    <div className={styles.content}>
      <Carousel
        ref={refCarousel}
        dots={false}
        arrows={true}
        prevArrow={<LeftOutlined onClick={preClick} />}
        nextArrow={<RightOutlined onClick={nextClick} />}
      >
        {[0, 6].map(i => (
          <>
            <div className="calendarMain calendar">
              {[...monthArr.map(j => j + i)].map(item => {
                const startDate = moment(
                  `${year}-${item}`
                ).startOf("month");
                const endDate = moment(`${year}-${item}`).endOf(
                  "month"
                );
                return (
                  <div style={{ width: "33.33%", padding: '0 10px 10px' }}>
                    <div style={{ background: "#fff", height: "100%" }}>
                      <Calendar
                        headerRender={() => (
                          <div className="custom-header">{`${
                            year
                          }  ${item} 月`}</div>
                        )}
                        dateFullCellRender={value =>
                          dateFullCellRender(value, item)
                        }
                        fullscreen={false}
                        value={moment(`${year}-${item}`)}
                        validRange={[startDate, endDate]}
                        disabledDate={() => false}
                      />
                    </div>
                  </div>
                );
              })}
            </div>
          </>
        ))}
      </Carousel>
      <DetailToolTipModal
        {...props}
        detailModalOption={detailModalOption}
        handleCancel={handleCancel}
        handleSaveData={handleSaveData}
      />
    </div>
  );
};

const DetailToolTipModal = props => {
  const [form] = Form.useForm();

  const slaveData = useMemo(
    () =>
      commonUtils.isNotEmptyArr(props.slaveData)
        ? [
            ...props.slaveData.filter(
              i => i && Object.prototype.hasOwnProperty.call(i, "sTemplateName")
            )
          ]
        : [],
    [props.slaveData]
  );

  const fieldResult = slaveData.find(
    slaveItem => slaveItem.sCalDate === props.detailModalOption?.date
  );

  useEffect(() => {
    if (props.detailModalOption?.date) {
      form.setFieldsValue({ ...fieldResult || {} });
    }
  }, [props.detailModalOption])

  const formItemLayout = {
    labelCol: {
      span: 6,
      style: { color: "rgba(0, 0, 0, 0.65)", backgroundColor: "#BFEFFF" }
    },
    wrapperCol: { span: 18 }
  };

  const queryFormItem = configItem => {
    if (!configItem) return <Input />;
    const firstDataIndex = configItem.sName?.substring(0, 1);
    let options = [];
    if (["s"].includes(firstDataIndex)) {
      try {
        const result = JSON.parse(configItem?.sChineseDropDown);
        options = Object.keys(result).map(i => ({
          label: i,
          value: result[i]
        }));
      } catch (error) {
        options = [];
      }
    }

    return (
      {
        i: <Input />,
        t: <DatePicker />,
        s: <Select options={options} />
      }[firstDataIndex] || <Input />
    );
  };

  const slaveItem = () =>
    props.slaveConfig?.gdsconfigformslave
      ?.filter(item => item.bVisible && item.sName !== "")
      ?.map(configItem => {
        const itemProperty = {
          label: configItem.showName /*   标签   */,
          name: configItem.sName,
          ...formItemLayout /*   主要是rowspan和colspan   */,
          rules: [{ required: configItem.bNotEmpty, message: "请输入内容" }],
        };
        return (
          <Col span={8}>
            <Form.Item {...itemProperty}>{queryFormItem(configItem)}</Form.Item>
          </Col>
        );
      });

  return <>
      <Modal title={props?.slaveConfig?.showName || '日历'} width={"70%"} open={props.detailModalOption?.date} onOk={async () => {
          try {
            const values = await form.validateFields();
            props.handleSaveData({ ...(fieldResult || {}), ...values });
          } catch (error) {
            return message.error("保存异常");
          }
        }} onCancel={props.handleCancel} destroyOnClose maskClosable={false}>
        <Form form={form} preserve={false} >
          <Row>{props.detailModalOption?.date && slaveItem()}</Row>
        </Form>
      </Modal>
    </>;
};

export default WorkCalendar;