/*
 * @Author: yuananting
 * @Date: 2021-02-25 14:34:29
 * @LastEditors: yuananting
 * @LastEditTime: 2021-03-25 19:52:09
 * @Description: 助学工具-题库-题目管理-新建题目Tab
 * @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
 */
import React, { Component } from "react";
import {
  Form,
  Radio,
  message,
  Checkbox,
  Tag,
  Modal,
  Input,
  Popover,
} from "antd";
import "./NewQuestionTab.less";
import QuestionEditor from "./QuestionEditor";
import { PlusOutlined, CloseOutlined } from "@ant-design/icons";
import {
  NUM_TO_WORD_MAP,
  MEDIA_FILE_ACCEPT,
} from "@/common/constants/punchClock/punchClock";
import { defineOptionInfo, defineJudgeOptionInfo } from "./model";
import XMAudio from "./XMAudio";
import XMRecord from "./XMRecord";
import ScanFileModal from "@/modules/resource-disk/modal/ScanFileModal";
import SelectPrepareFileModal from "@/modules/prepare-lesson/modal/SelectPrepareFileModal";
import _ from "lodash";

class NewQuestionTab extends Component {
  constructor(props) {
    super(props);
    const { questionInfo = {} } = props;
    const {
      questionStemList,
      gapFillingAnswerList,
      optionList,
      questionAnswerDescList,
      showBox,
    } = questionInfo;
    this.state = {
      stemContent: JSON.parse(JSON.stringify(questionStemList)), // 题干内容
      gapFillingAnswer: JSON.parse(JSON.stringify(gapFillingAnswerList)), // 填空题-选项列表
      chooseOptions: JSON.parse(JSON.stringify(optionList)), // 单选多选不定项判断-选项列表
      questionAnswerDesc: JSON.parse(JSON.stringify(questionAnswerDescList)), // 答案解析
      accept: MEDIA_FILE_ACCEPT["PICTURE"], // 上传媒体类型
      fileType: "PICTURE", // 媒体枚举
      showRecord: false, // 录音弹窗
      showBox: showBox,
      gapFillingOptions: [],
      blanksList: [], // 填空列表
      showSelectFileModal: false,
      mediaType: "",
      diskList: [], // 资料云盘文件列表
    };

    this.uploadInput = React.createRef();
    this.markKey = window.random_string(16);
  }

  componentDidMount() {
    const { chooseOptions } = this.state;
    if (
      ["INDEFINITE_CHOICE", "MULTI_CHOICE", "SINGLE_CHOICE"].includes(
        this.props.questionTypeKey
      )
    ) {
      if (chooseOptions.length === 0) {
        // 选择题（单选 多选 不定项）-插入4条默认选项
        for (var i = 0; i < 4; i++) {
          this.handleAddOption();
          this.setState({ [`optionsValidate_${i}`]: "success" });
          this.setState({ [`optionsText_${i}`]: "" });
        }
      }
    } else if (this.props.questionTypeKey === "JUDGE") {
      this.initJudgeOption("正确");
      this.initJudgeOption("错误");
    }
    this.props.onRef(this);
  }

  handleLogger = (en, cn) => {
    const { onLogger } = this.props;
    onLogger && onLogger(en, cn);
  };

  static getDerivedStateFromProps(nextProps, prevState) {
    // 控制录音组件展示
    if (nextProps.showBox && !prevState.showBox) {
      return {
        showRecord: false,
        showBox: nextProps.showBox,
      };
    }
    return {
      showBox: nextProps.showBox,
    };
  }

  shouldComponentUpdate(nextProps, nextState) {
    const { questionInfo } = nextProps;
    if (this.props.questionInfo !== questionInfo) {
      this.setState({
        gapFillingAnswer: JSON.parse(
          JSON.stringify(questionInfo.gapFillingAnswerList)
        ),
      });
      this.setState(
        {
          stemContent: JSON.parse(
            JSON.stringify(questionInfo.questionStemList)
          ),
        },
        () => {
          const con = questionInfo.questionStemList[0].content;
          const input = con.match(/<input([^<>]*)>/g);
          let _blanksList =
            input &&
            input.map((item) => {
              return this.transferStemDocument(item).firstChild;
            });
          this.setState({ blanksList: _blanksList || [] });
        }
      ); // 题干内容
      this.setState({
        chooseOptions: JSON.parse(JSON.stringify(questionInfo.optionList)),
      }); // 单选多选不定项-选项列表
      this.setState({
        questionAnswerDesc: JSON.parse(
          JSON.stringify(questionInfo.questionAnswerDescList)
        ),
      }); // 答案解析
      this._onSetState();
    }
    return true;
  }

  _onSetState = (params = {}) => {
    this.setState({ ...params, updateKey: window.random_string(16) }, () => {
      this.props.onSetState({
        questionStemList: JSON.parse(JSON.stringify(this.state.stemContent)),
        gapFillingAnswerList: JSON.parse(
          JSON.stringify(this.state.gapFillingAnswer)
        ),
        optionList: JSON.parse(JSON.stringify(this.state.chooseOptions)),
        questionAnswerDescList: JSON.parse(
          JSON.stringify(this.state.questionAnswerDesc)
        ),
      });
    });
  };

  transferStemDocument = (txt) => {
    const template = `<div class='stem'>${txt}</div>`;
    let doc = new DOMParser().parseFromString(template, "text/html");
    let div = doc.querySelector(".stem");
    return div;
  };

  // 保存校验
  checkInput = () => {
    let validateError = 0;
    // 题干校验
    let stemContent = _.find(
      this.state.stemContent,
      (contentItem) => contentItem.type === "RICH_TEXT"
    );
    let stem = stemContent.content.replace(/<[^>]+>/g, "");
    stem = stem.replace(/\&nbsp\;/gi, "");
    stem = stem.replace(/\s+/g, "");
    if (this.props.questionTypeKey === "GAP_FILLING") {
      if (this.state.blanksList.length === 0 || stem.length === 0) {
        this.setState({ stemValidate: "error" });
        this.setState({
          stemText: (
            <div style={{ marginTop: 8, minWidth: "523px" }}>
              请输入正确格式，示例：党章规定，凡事有
              <span style={{ padding: "0 10px", borderBottom: "1px solid" }}>
                填空1
              </span>
              人以上的
              <span style={{ padding: "0 10px", borderBottom: "1px solid" }}>
                填空2
              </span>
              ，都应该成立党的基层组织
            </div>
          ),
        });
        validateError++;
      } else {
        this.setState({ stemValidate: "success" });
        this.setState({ stemText: "" });
      }
    } else {
      if (stem.length === 0) {
        this.setState({ stemValidate: "error" });
        this.setState({ stemText: "请输入题干" });
        validateError++;
      } else {
        this.setState({ stemValidate: "success" });
        this.setState({ stemText: "" });
      }
    }
    // 选项校验
    let optionUnChecked = 0;
    const { chooseOptions } = this.state;
    if (this.props.questionTypeKey === "GAP_FILLING") {
      this.state.gapFillingAnswer.forEach((item, index) => {
        if (item.correctAnswerList.length === 0) {
          this.setState({ [`optionsValidate_${index}`]: "error" });
          this.setState({ [`optionsText_${index}`]: "请输入答案" });
          validateError++;
        } else {
          this.setState({ [`optionsValidate_${index}`]: "success" });
          this.setState({ [`optionsText_${index}`]: "" });
        }
      });
    } else {
      chooseOptions.forEach((item, index) => {
        const optionContent = item.questionOptionContentList;
        optionUnChecked = item.isCorrectAnswer
          ? optionUnChecked
          : optionUnChecked + 1;

        let optionInput = optionContent[0].content.replace(/<[^>]+>/g, "");
        optionInput = optionInput.replace(/\&nbsp\;/gi, "");
        optionInput = optionInput.replace(/\s+/g, "");
        if (
          optionContent.length === 1 &&
          optionContent[0].type === "RICH_TEXT" &&
          optionInput.length === 0
        ) {
          this.setState({ [`optionsValidate_${index}`]: "error" });
          this.setState({ [`optionsText_${index}`]: "请输入选项" });
          validateError++;
        } else {
          this.setState({ [`optionsValidate_${index}`]: "success" });
          this.setState({ [`optionsText_${index}`]: "" });
        }
      });
      var chooseIcon = [];
      if (["SINGLE_CHOICE", "JUDGE"].includes(this.props.questionTypeKey)) {
        chooseIcon = document.getElementsByClassName("ant-radio-inner");
      } else if (
        ["MULTI_CHOICE", "INDEFINITE_CHOICE"].includes(
          this.props.questionTypeKey
        )
      ) {
        chooseIcon = document.getElementsByClassName("ant-checkbox-inner");
      }
      if (optionUnChecked === chooseOptions.length) {
        this.setState({ radioValidate: "error" });
        chooseIcon.forEach((item) => {
          item.setAttribute("style", "border:1px solid #ff4d4f;");
        });
        this.setState({
          radioText: (
            <span>
              正确答案
              <br />
              不能为空
            </span>
          ),
        });
        validateError++;
      } else {
        this.setState({ radioValidate: "success" });
        this.setState({ radioText: "" });
        chooseIcon.forEach((item) => {
          item.removeAttribute("style");
        });
      }
      if (
        this.props.questionTypeKey === "MULTI_CHOICE" &&
        this.state.chooseOptions.length - optionUnChecked === 1
      ) {
        this.setState({ radioValidate: "error" });
        this.setState({ radioText: "最少选两个" });
        chooseIcon.forEach((item) => {
          item.setAttribute("style", "border:1px solid #ff4d4f;");
        });
        validateError++;
      }
    }
    return validateError;
  };

  /**
   * 预览
   *
   * @memberof QuestionInputItem
   */
  handleScanFile = (scanFileType, scanFileAddress) => {
    this.setState({
      showScanFile: true,
      scanFileAddress,
      scanFileType,
    });
  };

  /**
   * 添加选项
   *
   * @memberof QuestionInputItem
   */
  handleAddOption = (content) => {
    const { chooseOptions } = this.state;
    if (chooseOptions.length >= 20) {
      message.warning("最多添加20个选项");
    } else {
      chooseOptions.push(defineOptionInfo(content));
      this._onSetState();
    }
  };

  /**
   * 初始化判断选项
   *
   * @memberof QuestionInputItem
   */
  initJudgeOption = (content) => {
    const { chooseOptions } = this.state;
    chooseOptions.push(defineJudgeOptionInfo(content));
    this._onSetState();
  };

  /**
   * 删除选项
   *
   * @memberof QuestionInputItem
   */
  handleDelOption = (optionIndex) => {
    const { chooseOptions } = this.state;
    this.handleLogger("delete_option", "删除选项");
    if (chooseOptions.length < 3) {
      message.warning("至少保留2个选项");
    } else {
      chooseOptions.splice(optionIndex, 1);
      this._onSetState();
    }
  };

  /**
   * 移动选项
   *
   * @memberof QuestionInputItem
   */
  handleMoveOption = (optionIndex, moveLength) => {
    const { chooseOptions } = this.state;
    const optionItem = chooseOptions.splice(optionIndex + moveLength, 1);
    this.handleLogger("sort_option", "选项排序");
    chooseOptions.splice(optionIndex, 0, optionItem[0]);
    this._onSetState();
  };
  /**
   * 选择上传文件类型
   *
   * @memberof QuestionInputItem
   */
  handleChangeMedia = (key, uploadItemTarget, contentType) => {
    const pictureMediaArr = _.filter(uploadItemTarget, (mediaItem) => {
      return mediaItem.type === "PICTURE";
    });
    const voiceMediaArr = _.filter(uploadItemTarget, (mediaItem) => {
      return mediaItem.type === "VOICE";
    });
    const audioMediaArr = _.filter(uploadItemTarget, (mediaItem) => {
      return mediaItem.type === "AUDIO";
    });
    const videodMediaArr = _.filter(uploadItemTarget, (mediaItem) => {
      return mediaItem.type === "VIDEO";
    });
    switch (contentType) {
      case "QUESTION_STEM":
        var existType = [];
        if (pictureMediaArr.length > 0) {
          existType.push("PICTURE");
        }
        if (voiceMediaArr.length > 0) {
          existType.push("VOICE");
        }
        if (audioMediaArr.length > 0) {
          existType.push("AUDIO");
        }
        if (videodMediaArr.length > 0) {
          existType.push("VIDEO");
        }
        if (existType.length > 0 && !existType.includes(key)) {
          return message.warning("只能添加1种类型的多媒体文件");
        } else {
          if (key === "PICTURE" && pictureMediaArr.length > 8) {
            return message.warning("只能添加9张图片");
          }
          if (key === "VOICE" && voiceMediaArr.length > 2) {
            return message.warning("只能添加3个音频");
          }
          if (key === "AUDIO" && audioMediaArr.length > 2) {
            return message.warning("只能添加3个录音");
          }
          if (key === "VIDEO" && videodMediaArr.length > 2) {
            return message.warning("只能添加3个视频");
          }
        }
        break;
      case "QUESTION_OPTION":
        var existType = [];
        if (pictureMediaArr.length > 0) {
          existType.push("PICTURE");
        }
        if (voiceMediaArr.length > 0) {
          existType.push("VOICE");
        }
        if (audioMediaArr.length > 0) {
          existType.push("AUDIO");
        }
        if (videodMediaArr.length > 0) {
          existType.push("VIDEO");
        }
        if (existType.length > 0) {
          return message.warning("只能添加1个多媒体文件");
        }
        break;
      case "QUESTION_ANSWER_DESC":
        var existType = [];
        if (pictureMediaArr.length > 0) {
          existType.push("PICTURE");
        }
        if (voiceMediaArr.length > 0) {
          existType.push("VOICE");
        }
        if (audioMediaArr.length > 0) {
          existType.push("AUDIO");
        }
        if (videodMediaArr.length > 0) {
          existType.push("VIDEO");
        }
        if (existType.length > 2 && !existType.includes(key)) {
          return message.warning("只能添加3种类型的多媒体文件");
        } else {
          if (key === "PICTURE" && pictureMediaArr.length > 8) {
            return message.warning("只能添加9张图片");
          }
          if (key === "VOICE" && voiceMediaArr.length > 2) {
            return message.warning("只能添加3个音频");
          }
          if (key === "AUDIO" && audioMediaArr.length > 2) {
            return message.warning("只能添加3个录音");
          }
          if (key === "VIDEO" && videodMediaArr.length > 2) {
            return message.warning("只能添加3个视频");
          }
        }
        break;
    }
    var that = this;
    function change() {
      that.setState({ contentType });
      that.setState({ mediaType: key });

      that.setState(
        {
          uploadItemTarget,
        },
        () => {
          MEDIA_FILE_ACCEPT[key] &&
            that.setState(
              {
                accept: MEDIA_FILE_ACCEPT[key],
                fileType: key,
              },
              () => {
                that.uploadInput.current.value = "";
                that.setState({ showSelectFileModal: key !== "AUDIO" });
              }
            );
        }
      );
    }
    if (key == "AUDIO") {
      // 录音
      this.setState({
        showRecord: true,
      });
      this.setState({
        onAudioFinish: function () {
          change();
        },
      });
    } else {
      change();
    }
  };

  async uploadFile(mediaFile) {
    const { fileType, uploadItemTarget, contentType } = this.state;
    if (!mediaFile) return;
    if (fileType === "VOICE") {
      if (
        !MEDIA_FILE_ACCEPT.VOICE.split(",").includes(mediaFile.folderFormat)
      ) {
        message.warning("文件格式不正确");
        return;
      }
      if (mediaFile.size > 20 * 1024 * 1024) {
        Modal.warning({
          title: "音频过大",
          content: "音频大小超过20M，请压缩后上传",
        });
        return;
      }
    }

    if (fileType === "PICTURE") {
      if (
        !MEDIA_FILE_ACCEPT.PICTURE.split(",").includes(mediaFile.folderFormat)
      ) {
        message.warning("文件格式不正确");
        return;
      }
      if (mediaFile.folderSize > 5 * 1024 * 1024) {
        Modal.warning({
          title: "图片过大",
          content: "图片大小超过5M，请压缩后上传",
        });
        return;
      }
    }

    if (fileType === "VIDEO") {
      if (
        !MEDIA_FILE_ACCEPT.VIDEO.split(",").includes(mediaFile.folderFormat)
      ) {
        message.warning("文件格式不正确");
        return;
      }
      if (mediaFile.folderSize > 500 * 1024 * 1024) {
        Modal.warning({
          title: "视频过大",
          content: "视频大小超过500G，请压缩后上传",
        });
        return;
      }
    }
    const originArr = mediaFile.folderName.split(".");
    const originType = originArr[originArr.length - 1];

    const uploadObj = {
      contentType,
      type: fileType,
      contentName: `${window.random_string(16)}.${originType}`, // 文件名
      fileType: mediaFile.folderFormat, // 文件后缀
      content: mediaFile.ossUrl, // url
    };
    if (["VIDEO", "VOICE"].includes(fileType)) {
      try {
        await new Promise((resolve) => {
          const fileurl = URL.createObjectURL(mediaFile);
          const audioElement = new Audio(fileurl);
          audioElement.addEventListener("loadedmetadata", (_event) => {
            const duration = audioElement.duration;
            uploadObj.size = Math.ceil(duration) * 1000;
            resolve();
          });
        });
      } catch (error) {
        console.log(error);
      }
    } else if (fileType === "PICTURE") {
      uploadObj.size = mediaFile.folderSize;
    }
    uploadItemTarget.push(uploadObj);
    this.setState({}, () => {
      this._onSetState();
      this.uploadInput.current.value = "";
    });
  }

  changeBlankCount = (data, idx) => {
    let _gap = this.state.gapFillingAnswer;
    if (data.length <= idx) {
      _gap.splice(idx, 1);
    } else {
      data.forEach((item, index) => {
        if (index === idx) {
          if (_gap.length < data.length) {
            _gap.splice(idx, 0, { correctAnswerList: [] });
          } else if (_gap.length > data.length) {
            _gap.splice(idx, 1);
          } else {
            _gap.splice(idx, 1, { correctAnswerList: [] });
          }
        }
        if (!item.correctAnswerList) {
          item.correctAnswerList = [];
        }
        item.inputVisible = false;
        item.errorHold = false;
        item.editInput = false;
        return item;
      });
    }

    this.setState(
      {
        blanksList: data,
        gapFillingAnswer: _gap,
      },
      () => this._onSetState()
    );
  };

  addAnswerTag = (optionItem) => {
    const _blanksList = this.state.blanksList;
    _blanksList.forEach((item) => {
      if (item.id === optionItem.id) {
        item.inputVisible = true;
      }
    });
    this.setState({ blanksList: _blanksList });
  };

  // 填空选项
  handleInputConfirm = (optionItem, val) => {
    var tagContent = val.replace(/\&nbsp\;/gi, "");
    tagContent = val.replace(/\s+/g, "");
    const _blanksList = this.state.blanksList;
    const { gapFillingAnswer } = this.state;

    let _gapFillingAnswer = [...gapFillingAnswer];

    _blanksList.forEach((item, index) => {
      if (item.id === optionItem.id) {
        if (val && tagContent.length > 0) {
          _gapFillingAnswer[index].correctAnswerList.push(val);
          optionItem.inputVisible = false;
        } else {
          optionItem.errorHold = true;
        }
      }
    });

    this.setState({ gapFillingAnswer: _gapFillingAnswer }, () =>
      this._onSetState()
    );
    this.setState({ blanksList: _blanksList });
  };

  handleTagClose = (optionItem, removedTag, removedIndex) => {
    const _blanksList = this.state.blanksList;
    const { gapFillingAnswer } = this.state;
    let _gapFillingAnswer = [...gapFillingAnswer];
    _blanksList.forEach((item, index) => {
      if (item.id === optionItem.id) {
        _gapFillingAnswer[index].correctAnswerList = _gapFillingAnswer[
          index
        ].correctAnswerList.filter(
          (tag, index) => tag !== removedTag || index !== removedIndex
        );
      }
    });
    this.setState({ gapFillingAnswer: _gapFillingAnswer }, () =>
      this._onSetState()
    );
    this.setState({ blanksList: _blanksList });
  };

  // 输入框关闭
  handleInputClose = (optionItem) => {
    const _blanksList = this.state.blanksList;
    _blanksList.forEach((item) => {
      if (item.id === optionItem.id) {
        item.inputVisible = false;
        optionItem.errorHold = false;
      }
    });
    this.setState({ blanksList: _blanksList });
  };

  handleInputEdit = (optionItem, index) => {
    const _blanksList = this.state.blanksList;
    _blanksList.forEach((item) => {
      if (item.id === optionItem.id) {
        item.correctAnswerList.map();
      }
    });
    this.setState({ blanksList: _blanksList });
  };

  renderGapFillingAnswer = (optionItem, optionIndex) => {
    const { gapFillingAnswer } = this.state;
    const list =
      gapFillingAnswer[optionIndex] &&
      gapFillingAnswer[optionIndex].correctAnswerList;
    return (
      <div className="gap-answer-box" key={optionIndex}>
        <span className="gap-answer-label">
          填空
          {optionIndex + 1}.
        </span>
        <div className="gap-answer-content">
          {list &&
            list.map((tag, index) => {
              return (
                <Tag
                  key={index}
                  className="edit-tag"
                  visible
                  closable
                  onClose={() => this.handleTagClose(optionItem, tag, index)}
                >
                  {tag}
                </Tag>
              );
            })}
          {optionItem.inputVisible && (
            <Input
              placeholder={optionItem.errorHold && "请输入"}
              style={{
                border: optionItem.errorHold && "1px solid #FF4F4F",
              }}
              maxLength={60}
              size="small"
              suffix={
                <CloseOutlined
                  onClick={() => this.handleInputClose(optionItem)}
                  style={{ color: "#999999" }}
                />
              }
              onBlur={(e) =>
                this.handleInputConfirm(optionItem, e.target.value, "save")
              }
              onPressEnter={(e) =>
                this.handleInputConfirm(optionItem, e.target.value, "save")
              }
            />
          )}
          <Tag
            style={{ color: "#5289FA", fontSize: 14 }}
            onClick={() => {
              this.addAnswerTag(optionItem);
            }}
          >
            <PlusOutlined /> 新增答案
          </Tag>
        </div>
      </div>
    );
  };

  renderJudgeOption = (judgeOptions) => {
    return (
      <div dangerouslySetInnerHTML={{ __html: judgeOptions[0].content }} />
    );
  };
  /**
   * 渲染输入内容
   *
   * @memberof QuestionInputItem
   */
  renderContent = (
    contentList,
    placehold,
    mediaBtn,
    contentType,
    validateStatus
  ) => {
    const { blanksList } = this.state;
    const isGapFilling = this.props.questionTypeKey === "GAP_FILLING";
    if (contentList.length === 0) {
      contentList.push({
        content: "",
        contentType: "QUESTION_ANSWER_DESC",
        sort: 0,
        textLength: 0,
        type: "RICH_TEXT",
      });
    }
    const editorContent = _.find(
      contentList,
      (contentItem) => contentItem.type === "RICH_TEXT"
    );
    const pictureMediaList = _.filter(contentList, (mediaItem) => {
      return mediaItem.type === "PICTURE";
    });
    const voiceMediaList = _.filter(contentList, (mediaItem) => {
      return mediaItem.type === "VOICE";
    });
    const audioMediaList = _.filter(contentList, (mediaItem) => {
      return mediaItem.type === "AUDIO";
    });
    const videoMediaList = _.filter(contentList, (mediaItem) => {
      return mediaItem.type === "VIDEO";
    });

    return (
      <React.Fragment>
        <div>
          <QuestionEditor
            markKey={this.markKey}
            placehold={placehold}
            validateStatus={validateStatus}
            detailInfo={editorContent}
            isGapFilling={isGapFilling}
            contentType={contentType}
            mediaBtn={mediaBtn}
            blanksList={blanksList}
            changeBlankCount={this.changeBlankCount.bind(this)}
            bindChangeContent={(cb, textElemId) => {
              this.setState({ textElemId });
              editorContent.handleChangeContent = cb;
            }}
            onChange={(content, textLength) => {
              editorContent.content = content;
              editorContent.textLength = textLength;
              this._onSetState();
            }}
            onUploadMedia={(key) => {
              this.handleChangeMedia(key, contentList, contentType);
            }}
          />
        </div>
        {contentType === "QUESTION_ANSWER_DESC" ? (
          <div className="question-desc-box">
            {pictureMediaList.length > 0 && (
              <div className="desc-picture-box">
                {_.map(pictureMediaList, (pictureItem, pictureIndex) => {
                  let { content } = pictureItem;
                  return (
                    <div className="picture-box" key={pictureIndex}>
                      <img
                        className="img-box"
                        src={content}
                        onClick={() => this.handleScanFile("JPG", content)}
                      />
                      <span
                        className="icon_arrow iconfont"
                        onClick={() => {
                          contentList.map((item, index) => {
                            if (item.contentName === pictureItem.contentName) {
                              contentList.splice(index, 1);
                              return item;
                            }
                          });
                          this._onSetState();
                        }}
                      >
                        &#xe717;
                      </span>
                    </div>
                  );
                })}
              </div>
            )}
            {audioMediaList.length > 0 && (
              <div className="desc-audio-box">
                {_.map(audioMediaList, (audioItem, audioIndex) => {
                  let { content, size } = audioItem;
                  return (
                    <div className="audio-box" key={audioIndex}>
                      <XMAudio
                        forbidParse
                        url={content}
                        getDuration={(durationSize) => {
                          size = durationSize;
                          this.setState({});
                        }}
                        index={audioIndex}
                        size={size || 1000}
                      />
                      <span
                        className="icon_sider iconfont"
                        onClick={() => {
                          contentList.map((item, index) => {
                            if (item.contentName === audioItem.contentName) {
                              contentList.splice(index, 1);
                              return item;
                            }
                          });
                          this._onSetState();
                        }}
                      >
                        &#xe717;
                      </span>
                    </div>
                  );
                })}
              </div>
            )}
            {voiceMediaList.length > 0 && (
              <div className="desc-audio-box">
                {_.map(voiceMediaList, (voiceItem, voiceIndex) => {
                  let { content, size } = voiceItem;
                  return (
                    <div className="audio-box" key={voiceIndex}>
                      <XMAudio
                        forbidParse
                        url={content}
                        getDuration={(durationSize) => {
                          size = durationSize;
                          this.setState({});
                        }}
                        index={voiceIndex}
                        size={size || 1000}
                      />
                      <span
                        className="icon_sider iconfont"
                        onClick={() => {
                          contentList.map((item, index) => {
                            if (item.contentName === voiceItem.contentName) {
                              contentList.splice(index, 1);
                              return item;
                            }
                          });
                          this._onSetState();
                        }}
                      >
                        &#xe717;
                      </span>
                    </div>
                  );
                })}
              </div>
            )}
            {videoMediaList.length > 0 && (
              <div className="desc-video-box">
                {_.map(videoMediaList, (videoItem, videoIndex) => {
                  let { content } = videoItem;
                  return (
                    <div className="video-box" key={videoIndex}>
                      <img
                        className="video-box_content"
                        src={`${content}?x-oss-process=video/snapshot,t_0,m_fast`}
                      />
                      <img
                        className="video-box_btn"
                        src="https://image.xiaomaiketang.com/xm/r5H8cYm4ch.png"
                        onClick={() => this.handleScanFile("MP4", content)}
                      />
                      <span
                        className="icon_arrow iconfont"
                        onClick={() => {
                          contentList.map((item, index) => {
                            if (item.contentName === videoItem.contentName) {
                              contentList.splice(index, 1);
                              return item;
                            }
                          });
                          this._onSetState();
                        }}
                      >
                        &#xe717;
                      </span>
                    </div>
                  );
                })}
              </div>
            )}
          </div>
        ) : (
          _.map(contentList, (contentItem, index) => {
            const { type, content } = contentItem;
            let dom = "";
            switch (type) {
              case "PICTURE":
                dom = (
                  <div className="picture-box">
                    <img
                      className="img-box"
                      src={content}
                      onClick={() => this.handleScanFile("JPG", content)}
                    />
                  </div>
                );
                break;
              case "VOICE":
                dom = (
                  <div className="audio-box">
                    <XMAudio
                      forbidParse
                      url={contentItem.content}
                      getDuration={(size) => {
                        contentItem.size = size;
                        this.setState({});
                      }}
                      index={index}
                      size={contentItem.size || 1000}
                    />
                  </div>
                );
                break;
              case "AUDIO":
                dom = (
                  <div className="audio-box">
                    <XMAudio
                      forbidParse
                      url={contentItem.content}
                      getDuration={(size) => {
                        contentItem.size = size;
                        this.setState({});
                      }}
                      index={index}
                      size={contentItem.size || 1000}
                    />
                  </div>
                );
                break;
              case "VIDEO":
                dom = (
                  <div
                    className="video-box"
                    onClick={() => this.handleScanFile("MP4", content)}
                  >
                    <img
                      className="video-box_content"
                      src={`${content}?x-oss-process=video/snapshot,t_0,m_fast`}
                    />
                    <img
                      className="video-box_btn"
                      src="https://image.xiaomaiketang.com/xm/r5H8cYm4ch.png"
                    />
                  </div>
                );
                break;
            }
            return dom ? (
              <div
                className="question-item_question-content"
                style={{
                  display: ["PICTURE", "VIDEO"].includes(type)
                    ? "inline-grid"
                    : "flex",
                }}
                key={index}
              >
                {dom}
                <span
                  className={
                    ["PICTURE", "VIDEO"].includes(type)
                      ? "icon_arrow iconfont"
                      : "icon_sider iconfont"
                  }
                  onClick={() => {
                    contentList.splice(index, 1);
                    this._onSetState();
                  }}
                >
                  &#xe717;
                </span>
              </div>
            ) : null;
          })
        )}
      </React.Fragment>
    );
  };

  /**
   * 取消上传
   *
   * @memberof QuestionInputItem
   */
  handleAbort = (uploadItem, index) => {
    const { uploadItemTarget } = this.state;
    const { xhr } = uploadItem;
    xhr && xhr.abort && xhr.abort();
    uploadItemTarget.splice(index, 1);
    this._onSetState();
  };

  /**
   * 完成语音录制
   *
   * @memberof QuestionInputItem
   */
  handleFinishRecord = (mp3URL, duration) => {
    const originArr = mp3URL.split(".");
    const originType = originArr[originArr.length - 1];
    this.state.onAudioFinish();

    const { uploadItemTarget, contentType } = this.state;
    uploadItemTarget.push({
      contentType,
      type: "AUDIO",
      contentName: `${window.random_string(16)}.${originType}`, // 文件名
      fileType: originType, // 文件后缀
      content: mp3URL,
      size: duration,
    });
    this._onSetState({ showRecord: false });
  };

  /**
   * 取消录制
   *
   * @memberof QuestionInputItem
   */
  handleCancelRecord = () => {
    this.setState({ showRecord: false });
  };

  handleSelectMedia = (file) => {
    this.uploadFile(file);
    this.setState({
      showSelectFileModal: false,
    });
  };

  render() {
    const {
      stemContent,
      chooseOptions,
      questionAnswerDesc,
      accept,
      showRecord,
      showScanFile,
      scanFileType,
      scanFileAddress,
      blanksList,
      showSelectFileModal,
      mediaType,
      diskList,
    } = this.state;
    const { stemValidate, stemText, radioValidate, radioText } = this.state;
    const isJudge = this.props.questionTypeKey === "JUDGE";
    const isGapFilling = this.props.questionTypeKey === "GAP_FILLING";
    const placehold = isGapFilling ? (
      <span>
        示例：党章规定，凡事有
        <span className="fill-line">&nbsp;&nbsp;填空1&nbsp;&nbsp;</span>
        人以上的
        <span className="fill-line">&nbsp;&nbsp;填空2&nbsp;&nbsp;</span>
        ，都应该成立党的基层组织
      </span>
    ) : (
      "必填（1000字以内）"
    );
    let acceptType = "";
    let selectTypeList = [];
    switch (mediaType) {
      case "PICTURE":
        acceptType = MEDIA_FILE_ACCEPT.PICTURE;
        selectTypeList = ["jpg", "png", "jpeg"];
        break;
      case "VOICE":
        acceptType = MEDIA_FILE_ACCEPT.VOICE;
        selectTypeList = ["mp3", "mpeg"];
        break;
      case "VIDEO":
        acceptType = MEDIA_FILE_ACCEPT.VIDEO;
        selectTypeList = ["mp4"];
        break;
    }

    return (
      <div className="question-input-item_wrapper">
        {/* 题干 */}
        <Form>
          <Form.Item
            name="stemContent"
            label="题干"
            required
            validateStatus={stemValidate}
            help={stemText}
          >
            {this.renderContent(
              stemContent,
              placehold,
              ["VOICE", "AUDIO", "PICTURE"],
              "QUESTION_STEM",
              stemValidate
            )}
          </Form.Item>
          {isGapFilling ? (
            <Form.Item
              name="answer"
              label={
                <span>
                  答案{" "}
                  <Popover
                    content={
                      <div>
                        <div style={{ marginBottom: "16px" }}>
                          一空可设置多个答案，答对任意一个即视为正确
                        </div>
                        <img
                          width="400px"
                          src="https://image.xiaomaiketang.com/xm/gaptip.png"
                          alt=""
                        />
                      </div>
                    }
                  >
                    <span
                      className="icon iconfont"
                      style={{ color: "#BFBFBF", fontSize: 14 }}
                    >
                      &#xe7c4;
                    </span>
                  </Popover>
                </span>
              }
              required
              className="question-answer_control"
            >
              {blanksList.length === 0 ? (
                <span className="answer-tip">请在题干中插入答案占位符</span>
              ) : (
                _.map(blanksList, (item, index) => {
                  return (
                    <Form.Item
                      name="answer"
                      validateStatus={this.state[`optionsValidate_${index}`]}
                      help={this.state[`optionsText_${index}`]}
                    >
                      {this.renderGapFillingAnswer(item, index)}
                    </Form.Item>
                  );
                })
              )}
            </Form.Item>
          ) : (
            <Form.Item
              name="options"
              label="选项"
              required
              className="question-option_control"
            >
              <div
                className="question-item_options__list"
                data-label="正确答案"
              >
                {_.map(chooseOptions, (optionItem, optionIndex) => {
                  const {
                    questionOptionContentList,
                    isCorrectAnswer,
                  } = optionItem;
                  optionItem.optionSort = optionIndex;
                  const mediaBtn = ["VOICE", "AUDIO", "PICTURE"];
                  const placeHold =
                    "必填（1000字以内；可以不输入文字，只添加音频或图片）";
                  return (
                    <div
                      className="question-item_options__content"
                      key={optionIndex}
                    >
                      <div className="question-item_options__setting">
                        <Form.Item
                          validateStatus={radioValidate}
                          help={
                            optionIndex === chooseOptions.length - 1
                              ? radioText
                              : ""
                          }
                        >
                          {/* 单选 or 判断*/}
                          {["SINGLE_CHOICE", "JUDGE"].includes(
                            this.props.questionTypeKey
                          ) && (
                            <Radio
                              checked={isCorrectAnswer}
                              onClick={() => {
                                _.each(chooseOptions, (o) => {
                                  o.isCorrectAnswer = 0;
                                });
                                optionItem.isCorrectAnswer = 1;
                                this._onSetState();
                              }}
                            />
                          )}
                          {/* 多选 or 不定项 */}
                          {["INDEFINITE_CHOICE", "MULTI_CHOICE"].includes(
                            this.props.questionTypeKey
                          ) && (
                            <Checkbox
                              checked={isCorrectAnswer === 1}
                              onChange={(e) => {
                                const checked = e.target.checked ? 1 : 0;
                                optionItem.isCorrectAnswer = checked;
                                this._onSetState();
                              }}
                            />
                          )}
                        </Form.Item>
                      </div>
                      <div className="question-item_options__sort mr12">
                        {NUM_TO_WORD_MAP[optionIndex]}.
                      </div>
                      <div className="question-item_options__input">
                        {isJudge ? (
                          this.renderJudgeOption(questionOptionContentList)
                        ) : (
                          <Form.Item
                            validateStatus={
                              this.state[`optionsValidate_${optionIndex}`]
                            }
                            help={this.state[`optionsText_${optionIndex}`]}
                          >
                            {this.renderContent(
                              questionOptionContentList,
                              placeHold,
                              mediaBtn,
                              "QUESTION_OPTION",
                              this.state[`optionsValidate_${optionIndex}`]
                            )}
                          </Form.Item>
                        )}
                      </div>
                      {[
                        "INDEFINITE_CHOICE",
                        "MULTI_CHOICE",
                        "SINGLE_CHOICE",
                      ].includes(this.props.questionTypeKey) && (
                        <div className="question-item_options__extra">
                          <React.Fragment>
                            <span
                              className="option-operate_item__icon icon iconfont"
                              style={{ fontSize: "14px" }}
                              onClick={() => this.handleDelOption(optionIndex)}
                            >
                              &#xe81a;
                            </span>
                            {optionIndex > 0 && (
                              <span
                                className="option-operate_item__icon icon iconfont"
                                onClick={() =>
                                  this.handleMoveOption(optionIndex, -1)
                                }
                              >
                                &#xe74a;
                              </span>
                            )}
                            {optionIndex < chooseOptions.length - 1 && (
                              <span
                                className="option-operate_item__icon icon iconfont"
                                style={{
                                  transform: "rotate(180deg)",
                                  display: "inline-block",
                                }}
                                onClick={() =>
                                  this.handleMoveOption(optionIndex, 1)
                                }
                              >
                                &#xe74a;
                              </span>
                            )}
                          </React.Fragment>
                        </div>
                      )}
                    </div>
                  );
                })}
                {!isJudge && (
                  <div
                    className="question-item_options__add"
                    onClick={() => {
                      this.handleAddOption();
                    }}
                  >
                    + 增加选项
                  </div>
                )}
              </div>
            </Form.Item>
          )}
          <Form.Item name="analysis" label="答案解析">
            <div className="question-item_analysis__content">
              {this.renderContent(
                questionAnswerDesc,
                "1000字以内",
                ["VOICE", "AUDIO", "PICTURE", "VIDEO"],
                "QUESTION_ANSWER_DESC"
              )}
            </div>
          </Form.Item>
        </Form>
        <input
          type="file"
          accept={accept}
          ref={this.uploadInput}
          style={{ display: "none" }}
          onChange={(event) => {
            this.uploadFile(event);
          }}
        />
        <div style={{ zIndex: 9999, position: "relative" }}>
          <XMRecord
            maxTime={600}
            visible={showRecord}
            onFinish={this.handleFinishRecord}
            onCancel={this.handleCancelRecord}
          />
        </div>
        {showScanFile && (
          <ScanFileModal
            modalTitle={scanFileType === "MP4" ? "视频播放" : "查看大图"}
            fileType={scanFileType}
            item={{
              ossAddress: scanFileAddress,
            }}
            close={() => {
              this.setState({ showScanFile: false });
            }}
          />
        )}
        <SelectPrepareFileModal
          operateType="select"
          accept={acceptType}
          selectTypeList={selectTypeList}
          isOpen={showSelectFileModal}
          diskList={diskList}
          onClose={() => {
            this.setState({ showSelectFileModal: false });
          }}
          onSelect={this.handleSelectMedia}
        />
      </div>
    );
  }
}

export default NewQuestionTab;
