<template>
  <div class="mark-param-objective-answer">
    <div class="part-box part-box-pad">
      <div>
        <p class="tips-info">
          1.如果已经扫描了答题卡，客观题标答提交后请到成绩检查菜单点击客观题统分按钮进行统分；
        </p>
      </div>
    </div>

    <div class="part-box part-box-pad">
      <div class="box-justify mb-1">
        <p style="font-weight: bold">
          <i class="el-icon-warning"></i> 客观题标答只能输入大写字母ABCDE...
          ，判断题正确请输入A，错误输入B
        </p>

        <div>
          <el-select
            v-if="paperTypes.length > 1"
            v-model="curPaperType"
            placeholder="选择卷型"
            :clearable="false"
            style="width: 100px; margin-right: 10px"
            @change="paperTypeChange"
          >
            <el-option
              v-for="item in paperTypes"
              :key="item"
              :value="item"
              :label="`${item}卷`"
            ></el-option>
          </el-select>
          <el-button type="primary" @click="toImport">导入标答</el-button>
        </div>
      </div>
      <el-table
        ref="TableList"
        :data="tableData"
        :row-class-name="getRowClassName"
        border
      >
        <el-table-column width="50" align="center">
          <template slot-scope="scope" v-if="scope.row.mainFirstSub">
            <div
              :class="[
                'expand-btn',
                { 'expand-btn-unexpand': !scope.row.expandSub },
              ]"
              @click="switchExpandSub(scope.row)"
            >
              <i
                :class="scope.row.expandSub ? 'el-icon-minus' : 'el-icon-plus'"
              ></i>
            </div>
          </template>
        </el-table-column>
        <el-table-column prop="mainTitle" label="大题名称">
          <span slot-scope="scope" v-if="scope.row.mainFirstSub">
            {{ scope.row.mainTitle }}
          </span>
        </el-table-column>
        <el-table-column prop="mainNumber" label="大题号" width="80">
          <template slot-scope="scope" v-if="scope.row.mainFirstSub">
            <span>{{ scope.row.mainNumber }}</span>
          </template>
        </el-table-column>
        <el-table-column
          prop="subNumber"
          label="小题号"
          width="80"
        ></el-table-column>
        <el-table-column prop="totalScore" label="小题满分" width="85">
        </el-table-column>
        <el-table-column label="答案" width="140px" class-name="answer-column">
          <div
            slot-scope="scope"
            :class="['el-form-item', { 'is-error': scope.row.answerError }]"
          >
            <div class="el-form-item__content">
              <el-input
                v-model.trim="scope.row.answer"
                :placeholder="
                  scope.row.type === 3 ? 'A:正确，B:错误' : '请输入答案'
                "
                :maxlength="scope.row.optionCount"
                clearable
                @change="answerChange(scope.row)"
              ></el-input>
              <div v-if="scope.row.answerError" class="el-form-item__error">
                {{ scope.row.answerError }}
              </div>
            </div>
          </div>
        </el-table-column>
        <el-table-column
          label="判分策略"
          width="270px"
          class-name="answer-column"
        >
          <template slot="header">
            <span>判分策略</span>
            <el-tooltip effect="dark" placement="top">
              <div slot="content" class="tooltip-area">
                <p>全对给分：答对得该小题满分</p>
                <p>任选给分：选任意答案都得该小题满分，一般用于题目出错了</p>
                <p>
                  漏选给半分：答对，但是漏选了，给该小题一半分，比如满分4分，得2分
                </p>
                <p>
                  漏选给任意分：答对，但是漏选了，设置每对一个选项得分，最大不能超过该小题满分除以该小题选项个数
                </p>
              </div>
              <i class="el-icon-info ml-1 tooltip-info-icon"></i>
            </el-tooltip>
          </template>
          <template slot-scope="scope">
            <template v-if="scope.row.questionType === 2">
              <el-select
                v-model="scope.row.objectivePolicy"
                style="width: 120px"
                @change="objectivePolicyChange(scope.row)"
              >
                <el-option
                  v-for="(val, key) in QUESTION_SCORE_TYPE"
                  :key="key"
                  :value="key"
                  :label="val"
                ></el-option>
              </el-select>
              <div
                v-if="scope.row.objectivePolicy === 'LEAK'"
                :class="[
                  'el-form-item',
                  { 'is-error': scope.row.objectivePolicyError },
                ]"
                style="display: inline-block"
              >
                <div class="el-form-item__content">
                  <el-input-number
                    v-model="scope.row.objectivePolicyScore"
                    :disabled="scope.row.answer.length <= 1"
                    style="width: 110px; margin-left: 5px"
                    size="small"
                    :min="0"
                    :max="100"
                    :step="0.5"
                    step-strictly
                    :controls="false"
                    placeholder="每个选项得分"
                    @change="objectivePolicyScoreChange(scope.row)"
                  ></el-input-number>
                  <div
                    v-if="scope.row.objectivePolicyError"
                    class="el-form-item__error"
                    style="padding-left: 5px"
                  >
                    {{ scope.row.objectivePolicyError }}
                  </div>
                </div>
              </div>
            </template>
            <template
              v-if="
                scope.row.questionType === 1 || scope.row.questionType === 3
              "
            >
              <el-select
                v-model="scope.row.objectivePolicy"
                style="width: 120px"
              >
                <el-option
                  v-for="(val, key) in QUESTION_SCORE_TYPE_SIMPLE"
                  :key="key"
                  :value="key"
                  :label="val"
                ></el-option>
              </el-select>
            </template>
          </template>
        </el-table-column>
      </el-table>
    </div>

    <div class="text-center">
      <el-button type="primary" :disabled="loading" @click="submit"
        >提交</el-button
      >
      <el-button @click="cancel">取消</el-button>
    </div>

    <!-- ImportFile -->
    <import-file
      ref="ImportFile"
      title="导入客观题标答"
      :upload-url="uploadUrl"
      :format="['xls', 'xlsx']"
      :upload-data="uploadData"
      :download-handle="downloadHandle"
      :download-filename="dfilename"
      :auto-upload="false"
      @upload-success="importAnswerSuccess"
    ></import-file>
  </div>
</template>

<script>
import { QUESTION_SCORE_TYPE } from "@/constants/enumerate";
import {
  markObjectiveQuestionList,
  markObjectiveQuestionSave,
  markObjectiveQuestionExport,
} from "../../api";
import ImportFile from "@/components/ImportFile.vue";
import { downloadByApi } from "@/plugins/download";

import { mapState } from "vuex";
import { omit } from "lodash";

export default {
  name: "mark-param-objective-answer",
  components: { ImportFile },
  data() {
    return {
      loading: false,
      tableDict: {},
      tableData: [],
      QUESTION_SCORE_TYPE,
      abc: "abcdefghijklmnopqrstuvwxyz".toUpperCase(),
      QUESTION_SCORE_TYPE_SIMPLE: {
        NONE: "全对给分",
        ALL: "任选给分",
      },
      paperTypes: [],
      curPaperType: "A",
      prevPaperType: "A",
      // import
      uploadUrl: "/api/admin/mark/question/objective/import",
      dfilename: "客观题标答导入模板.xlsx",
      downloading: false,
    };
  },
  computed: {
    ...mapState("markParam", ["basicInfo"]),
    uploadData() {
      return {
        examId: this.basicInfo.examId,
        paperNumber: this.basicInfo.paperNumber,
        paperType: this.curPaperType,
      };
    },
  },
  mounted() {
    this.initData();
  },
  methods: {
    async initData(defaultPaperType = null) {
      const params = {
        examId: this.basicInfo.examId,
        paperNumber: this.basicInfo.paperNumber,
      };
      this.paperTypes = this.basicInfo.paperType.split(",");

      const res = await markObjectiveQuestionList(params);
      const objectiveStructure = res || [];

      this.paperTypes.forEach((paperType) => {
        let curMainNumber = null;
        let curMainId = null;
        const tableData = objectiveStructure
          .filter((item) => item.paperType === paperType)
          .map((item) => {
            let nitem = {
              ...item,
              objectivePolicyScore: item.objectivePolicyScore || undefined,
              mainFirstSub: false,
              expandSub: true,
              answerError: "",
              objectivePolicyError: "",
            };
            if (item.questionType <= 3 && !item.objectivePolicy) {
              nitem.objectivePolicy = "NONE";
            }
            if (nitem.mainNumber !== curMainNumber) {
              curMainNumber = nitem.mainNumber;
              nitem.mainFirstSub = true;
              curMainId = this.$randomCode();
            }
            nitem.mainId = curMainId;
            return nitem;
          });

        this.tableDict[paperType] = tableData;
      });

      this.curPaperType =
        defaultPaperType && this.tableDict[defaultPaperType]
          ? defaultPaperType
          : this.paperTypes[0];
      this.prevPaperType = this.curPaperType;
      this.tableData = this.tableDict[this.curPaperType];
    },
    paperTypeChange() {
      if (!this.checkData()) {
        this.curPaperType = this.prevPaperType;
        return;
      }
      this.prevPaperType = this.curPaperType;
      this.tableData = this.tableDict[this.curPaperType];
    },
    getRowClassName({ row }) {
      let classNames = [];
      if (row.mainFirstSub) {
        classNames.push("row-main-first-sub");
      }
      if (!row.mainFirstSub && !row.expandSub) {
        classNames.push("row-unexpand-sub");
      }
      return classNames.join(" ");
    },
    switchExpandSub(row) {
      row.expandSub = !row.expandSub;
      this.tableData
        .filter((item) => item.mainId === row.mainId && !item.mainFirstSub)
        .forEach((item) => (item.expandSub = row.expandSub));
    },
    answerChange(row) {
      this.validateAnswer(row);
      this.objectivePolicyChange(row);
    },
    validateAnswer(row) {
      if (!row.answer) {
        row.answerError = "不能为空";
        return;
      }

      if (!/^[A-Z]{1,26}$/.test(row.answer)) {
        row.answerError = "只能输入英文大写字母";
        return;
      }

      const validAnswers = this.abc.substring(0, row.optionCount);
      // 单选题 判断题
      if (row.questionType === 1 || row.questionType === 3) {
        if (
          row.answer.length !== 1 ||
          row.answer.split("").some((item) => !validAnswers.includes(item))
        ) {
          row.answerError = `只能输入${validAnswers}中的一个`;
          return;
        }
      }

      // 多选题
      if (row.questionType === 2) {
        // if (row.answer.length <= 1) {
        //   row.answerError = `答案必须为多个`;
        //   return;
        // }
        if (row.answer.split("").some((item) => !validAnswers.includes(item))) {
          row.answerError = `只能输入${validAnswers}中的字符`;
          return;
        }

        const ansSet = new Set(row.answer.split(""));
        if (ansSet.size !== row.answer.length) {
          row.answerError = "答案不能重复";
          return;
        }
      }

      row.answerError = "";
    },
    validateObjectivePolicy(row) {
      if (row.questionType === 2 && row.objectivePolicy === "LEAK") {
        if (!row.objectivePolicyScore && row.objectivePolicyScore !== 0) {
          row.objectivePolicyError = "不能为空";
          return;
        }

        if (
          row.answer.length > 1 &&
          row.objectivePolicyScore * row.answer.length > row.totalScore
        ) {
          row.objectivePolicyError = "分值过大";
          return;
        }
      }

      row.objectivePolicyError = "";
    },
    checkData() {
      this.tableData.forEach((item) => {
        this.validateAnswer(item);
        this.validateObjectivePolicy(item);
      });

      return !this.tableData.some(
        (item) => item.answerError || item.objectivePolicyError
      );
    },
    objectivePolicyScoreChange(row) {
      this.$nextTick(() => {
        this.objectivePolicyChange(row);
      });
    },
    objectivePolicyChange(row) {
      const { totalScore, answer, objectivePolicy } = row;
      if (objectivePolicy === "LEAK") {
        if (answer.length > 1) {
          const pickScore = Math.floor((totalScore * 2) / answer.length) / 2;
          row.objectivePolicyScore = pickScore;
        } else {
          row.objectivePolicyScore = 0;
        }
      } else {
        row.objectivePolicyScore = null;
      }
      this.validateObjectivePolicy(row);
    },
    async submit() {
      if (!this.checkData()) return;

      if (this.loading) return;
      this.loading = true;
      const datas = {
        examId: this.basicInfo.examId,
        paperNumber: this.basicInfo.paperNumber,
        paperType: this.curPaperType,
        objectiveInfo: this.tableData.map((item) =>
          omit(item, ["mainFirstSub", "expandSub", "error", "errMsg", "mainId"])
        ),
      };
      const data = await markObjectiveQuestionSave(datas).catch(() => {});
      this.loading = false;
      if (!data) return;

      this.$message.success(
        "保存成功，请到成绩检查菜单点击客观题统分按钮进行统分！"
      );

      // this.$emit("confirm");
    },
    cancel() {
      this.$emit("cancel");
    },
    // toImport
    async downloadHandle() {
      if (this.downloading) return;
      this.downloading = true;

      const res = await downloadByApi(() => {
        return markObjectiveQuestionExport(this.uploadData);
      }).catch((e) => {
        this.$message.error(e || "下载失败，请重新尝试！");
      });
      this.downloading = false;

      if (!res) return;
      this.$message.success("下载成功！");
    },
    toImport() {
      this.$refs.ImportFile.open();
    },
    importAnswerSuccess() {
      this.$message.success("导入成功！");
      this.initData(this.curPaperType);
    },
  },
};
</script>
