<template>
  <div class="grading-level-set">
    <Button
      class="level-add-btn"
      type="success"
      icon="recode-white icon"
      shape="circle"
      @click="toAdd"
      >新增档位</Button
    >
    <table class="table table-noborder grading-table">
      <tr>
        <th>档位</th>
        <th>最低分</th>
        <th>最高分</th>
        <th>给分间隔</th>
        <th>典型值</th>
        <th>类型</th>
        <th>给分项</th>
        <th>考区阈值%</th>
        <th>占比阈值%</th>
        <th>操作</th>
      </tr>
      <template v-for="(level, index) in levels">
        <tr :key="index">
          <td>
            <Input
              v-model="level.code"
              style="width: 60px"
              @on-blur="codeChange(level)"
              v-if="level.canEdit && workDetail.modifyOtherVal"
            ></Input>
            <p v-else>{{ level.code }}</p>
          </td>
          <td>
            <InputNumber
              v-model="level.minScore"
              :min="0"
              :max="1000"
              @on-blur="checkLevelValidate(level)"
              v-if="level.canEdit && workDetail.modifyOtherVal"
            ></InputNumber>
            <p v-else>{{ level.minScore }}</p>
          </td>
          <td>
            <InputNumber
              v-model="level.maxScore"
              :min="1"
              :max="1000"
              @on-blur="checkLevelValidate(level)"
              v-if="level.canEdit && workDetail.modifyOtherVal"
            ></InputNumber>
            <p v-else>{{ level.maxScore }}</p>
          </td>
          <td style="min-width: 100px">
            <InputNumber
              v-model="level.intervalScore"
              :min="1"
              :max="100"
              :precision="0"
              :disabled="!level.canEdit"
              @on-blur="checkLevelValidate(level)"
              v-if="
                level.levelType === 'ADMITED' &&
                level.canEdit &&
                workDetail.modifyOtherVal
              "
            ></InputNumber>
            <p v-else>{{ level.intervalScore }}</p>
          </td>
          <td>
            <InputNumber
              v-model="level.weight"
              :min="1"
              :max="1000"
              @on-blur="checkLevelValidate(level)"
              v-if="level.canEdit && workDetail.modifyOtherVal"
            ></InputNumber>
            <p v-else>{{ level.weight }}</p>
          </td>
          <td>
            <Select
              v-model="level.levelType"
              @on-change="levelTypeChange(level)"
              style="width: 120px"
              v-if="level.canEdit && workDetail.modifyOtherVal"
            >
              <Option
                v-for="(val, key) in LEVEL_TYPE"
                :key="key"
                :value="key"
                >{{ val }}</Option
              >
            </Select>
            <p v-else>{{ LEVEL_TYPE[level.levelType] }}</p>
          </td>
          <td style="min-width: 140px">
            <Input
              v-model="level.scoreList"
              @on-blur="checkLevelValidate(level)"
              v-if="
                level.levelType === 'UNADMIT' &&
                level.canEdit &&
                workDetail.modifyOtherVal
              "
            ></Input>
            <p v-else>{{ level.scoreList }}</p>
          </td>
          <td>
            <InputNumber
              v-model="level.kdpt"
              :min="1"
              :max="100"
              @on-blur="checkLevelValidate(level)"
              v-if="level.canEdit"
            ></InputNumber>
            <p v-else>{{ level.kdpt }}</p>
          </td>
          <td>
            <InputNumber
              v-model="level.pt"
              :min="1"
              :max="100"
              @on-blur="checkLevelValidate(level)"
              v-if="level.canEdit"
            ></InputNumber>
            <p v-else>{{ level.pt }}</p>
          </td>
          <td class="table-action">
            <div style="width: 60px">
              <Icon type="md-create" title="编辑" @click="toEdit(index)" />
              <Icon
                class="icon-danger"
                type="md-trash"
                title="删除"
                @click="toDelete(index)"
                v-if="workDetail.modifyOtherVal"
              />
            </div>
          </td>
        </tr>
        <tr class="tr-tips-error" v-if="level.errors" :key="index + '1'">
          <td>
            {{ level.errors.code }}
          </td>
          <td>
            {{ level.errors.minScore }}
          </td>
          <td>
            {{ level.errors.maxScore }}
          </td>
          <td>
            {{ level.errors.intervalScore }}
          </td>
          <td>
            {{ level.errors.weight }}
          </td>
          <td></td>
          <td>
            {{ level.errors.scoreList }}
          </td>
          <td>
            {{ level.errors.kdpt }}
          </td>
          <td>
            {{ level.errors.pt }}
          </td>
          <td></td>
        </tr>
      </template>
    </table>

    <div class="text-center">
      <Button
        type="primary"
        shape="circle"
        @click="toSubmit"
        style="width: 80px"
        :disabled="isSubmit"
        >确定</Button
      >
    </div>
  </div>
</template>

<script>
import { workDetail, updateWork } from "@/api";
import { LEVEL_TYPE } from "@/constants/enumerate";
import schema from "async-validator";
schema.warning = function () {};

const initLevel = {
  id: null,
  workId: null,
  code: null,
  levelValue: 0,
  maxScore: null,
  minScore: null,
  intervalScore: null,
  weight: null,
  levelType: "ADMITED",
  scoreList: null,
  pt: null,
  kdpt: null,
};

export default {
  name: "grading-level-set",
  data() {
    return {
      LEVEL_TYPE,
      workId: this.$route.params.workId,
      letterRelateNumber: {},
      levels: [],
      workDetail: {},
      isSubmit: false,
    };
  },
  mounted() {
    this.initData();
  },
  methods: {
    initData() {
      const letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
      letters.split("").map((item, index) => {
        this.letterRelateNumber[item] = index + 1;
      });

      this.getData();
    },
    async getData() {
      const data = await workDetail(this.workId);
      this.workDetail = data;
      this.levels = data.levels.map((item) => {
        item.canEdit = false;
        return item;
      });
    },
    checkLevelCodeIsContinuous() {
      let levelIsContinuous = true;
      for (var i = 0, num = this.levels.length; i < num; i++) {
        if (i > 0) {
          const beforeCodeNum =
            this.letterRelateNumber[this.levels[i - 1].code];
          const curCodeNum = this.letterRelateNumber[this.levels[i].code];
          levelIsContinuous =
            levelIsContinuous && curCodeNum - beforeCodeNum === 1;

          if (!levelIsContinuous) {
            return false;
          }
        }
      }

      return true;
    },
    levelTypeChange(level) {
      if (level.levelType === "ADMITED") {
        level.scoreList = null;
      } else {
        level.intervalScore = null;
      }
    },
    codeChange(level) {
      level.code = level.code.toUpperCase();
      this.levels.sort((a, b) => {
        if (
          !a.code ||
          !b.code ||
          !this.letterRelateNumber[a.code] ||
          !this.letterRelateNumber[b.code]
        )
          return 0;

        return (
          this.letterRelateNumber[a.code] - this.letterRelateNumber[b.code]
        );
      });
      this.checkLevelValidate(level);
    },
    getNextLevelCode() {
      const codeNumbers = this.levels.map(
        (level) => this.letterRelateNumber[level.code] || 0
      );
      const maxCodeNumber = Math.max.apply(null, codeNumbers);
      const nextLevel = Object.entries(this.letterRelateNumber).find(
        ([key, val]) => {
          return maxCodeNumber < val;
        }
      );
      return nextLevel ? nextLevel[0] : "";
    },
    toAdd() {
      let level = { ...initLevel };
      level.workId = this.workId;
      level.code = this.getNextLevelCode();
      this.levels.push(level);
    },
    toEdit(index) {
      this.levels[index].canEdit = true;
      this.$forceUpdate();
    },
    toDelete(index) {
      this.levels.splice(index, 1);
    },
    checkLevelValidate(level) {
      const descriptor = {
        code: {
          type: "string",
          required: true,
          pattern: /^[A-Z]{1}$/,
          message: "请输入单个大写字母",
        },
        minScore: {
          type: "number",
          required: true,
          message: "请输入最低分",
        },
        maxScore: {
          type: "number",
          required: true,
          validator: (rule, value, callback) => {
            if (!value || value < level.minScore) {
              callback(new Error("最高分不得小于最低分"));
            } else {
              callback();
            }
          },
        },
        intervalScore: {
          type: "number",
          validator: (rule, value, callback) => {
            if (level.levelType === "ADMITED" && !value) {
              callback(new Error("请输入给分间隔"));
            } else {
              callback();
            }
          },
        },
        weight: {
          type: "number",
          required: true,
          message: "请输入典型值",
        },
        scoreList: {
          type: "string",
          validator: (rule, value, callback) => {
            if (level.levelType !== "UNADMIT") return callback();

            if (level.levelType === "UNADMIT" && !value) {
              return callback(new Error("请输入给分项"));
            }
            if (!value.match(/^[0-9,]+$/)) {
              return callback(new Error("给分项只能包含数字和英文逗号"));
            }
            const unvalid = value
              .split(",")
              .filter((item) => item)
              .some((item) => {
                const num = item * 1;
                return num < level.minScore || num > level.maxScore;
              });
            if (unvalid) {
              return callback(
                new Error("给分项包含的分值只能介于最低分和最高分之间")
              );
            }

            callback();
          },
        },
        pt: {
          type: "number",
          required: true,
          message: "请输入占比阀值",
        },
        kdpt: {
          type: "number",
          required: true,
          message: "请输入考区阀值",
        },
      };
      return new schema(descriptor)
        .validate(level)
        .then(() => {
          if (level.errors) level.errors = null;
        })
        .catch(({ errors, fields }) => {
          let errorMsgs = {};
          errors.map((error) => {
            errorMsgs[error.field] = error.message;
          });
          this.$set(level, "errors", errorMsgs);
          return { errors };
        });
    },
    async toSubmit() {
      const validatorAll = this.levels.map((level) =>
        this.checkLevelValidate(level)
      );
      const result = await Promise.all(validatorAll);
      const hasUnvalidate = result.some((item) => !!item);

      if (hasUnvalidate) return;

      if (!this.checkLevelCodeIsContinuous()) {
        this.$Message.error("请保持档位连续！");
        return;
      }

      if (this.isSubmit) return;
      this.isSubmit = true;
      this.workDetail.levels = this.levels;
      const data = await updateWork(this.workDetail).catch(() => {
        this.isSubmit = false;
      });

      if (!data) return;

      this.isSubmit = false;
      this.getData();
      this.$Message.success("保存成功！");
    },
  },
};
</script>
