<template>
  <div class="grading-level-set">
    <div class="part-box-top">
      <Button type="success" icon="md-add" @click="toAdd">新增</Button>
    </div>
    <div class="part-box">
      <table class="table table-noborder">
        <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)"
              ></Input>
            </td>
            <td>
              <InputNumber
                v-model="level.minScore"
                :min="0"
                :max="200"
                @on-blur="checkLevelValidate(level)"
              ></InputNumber>
            </td>
            <td>
              <InputNumber
                v-model="level.maxScore"
                :min="1"
                :max="200"
                @on-blur="checkLevelValidate(level)"
              ></InputNumber>
            </td>
            <td style="min-width: 100px">
              <InputNumber
                v-model="level.intervalScore"
                :min="1"
                :max="100"
                :precision="0"
                @on-blur="checkLevelValidate(level)"
                v-if="level.levelType === 'ADMITED'"
              ></InputNumber>
            </td>
            <td>
              <InputNumber
                v-model="level.weight"
                :min="1"
                :max="100"
                @on-blur="checkLevelValidate(level)"
              ></InputNumber>
            </td>
            <td>
              <Select
                v-model="level.levelType"
                @on-change="levelTypeChange(level)"
                style="width: 120px"
              >
                <Option
                  v-for="(val, key) in LEVEL_TYPE"
                  :key="key"
                  :value="key"
                  >{{ val }}</Option
                >
              </Select>
            </td>
            <td style="min-width: 140px">
              <Input
                v-model="level.scoreList"
                @on-blur="checkLevelValidate(level)"
                v-if="level.levelType === 'UNADMIT'"
              ></Input>
            </td>
            <td>
              <InputNumber
                v-model="level.kdpt"
                :min="1"
                :max="100"
                @on-blur="checkLevelValidate(level)"
              ></InputNumber>
            </td>
            <td>
              <InputNumber
                v-model="level.pt"
                :min="1"
                :max="100"
                @on-blur="checkLevelValidate(level)"
              ></InputNumber>
            </td>
            <td>
              <Button size="small" type="error" @click="toDelete(index)"
                >删除</Button
              >
            </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" @click="toSubmit" :disabled="isSubmit"
          >确定</Button
        >
      </div>
    </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;
    },
    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);
    },
    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;
      const data = await updateWork(this.worKDetail).catch(() => {
        this.isSubmit = false;
      });

      if (!data) return;

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