<template>
  <el-form class="component-vin-input" label-position="top">
    <el-form-item label="VIN码" :required="true">
      <template #label>
        <span>VIN码</span>
        <el-tooltip class="item" effect="dark" content="不可提交属于其他责任人的VIN码" placement="top-start">
          <i class="el-icon-warning-outline" />
        </el-tooltip>
      </template>
      <div class="vin-input-wrapper">
        <div v-for="(vin, index) in vinGroup" :key="index" :class="vin.result ? '' : 'input-error'" class="vin-edit">
          <el-input v-model="vin.vin" maxlength="17" @input="value => handleVinItemChange(value, index)" @blur="validate([], index)" />
          <div class="error-tip">{{ vin.message }}</div>
        </div>
        <el-input v-model="vinInput" class="vin-input" placeholder="请输入或粘贴VIN码" @input="handleVinInput" @blur="handleVinInputBlur" />
      </div>
      <div class="vin-tip">*每个VIN码输入完成后，以分号(；)结束</div>
    </el-form-item>
  </el-form>
</template>

<script>
export default {
  name: 'CompVin',
  props: {
    value: {
      type: Array,
      default: () => ([])
    }
  },
  data() {
    return {
      vinGroup: [],
      vinInput: ''
    }
  },
  mounted() {
    this.value.forEach(vin => {
      this.vinGroup.push({
        result: true,
        vin,
        message: ''
      })
    })
  },
  methods: {
    /**
     * 更新vin的页面显示
     * @param vinList vin的列表
     */
    updateVinGroup(vinList) {
      // 先清空vin
      this.vinGroup = []
      // 遍历列表数据
      vinList.forEach(vin => {
        this.vinGroup.push({
          result: true,
          vin,
          message: ''
        })
      })
    },

    /**
     * vin改变的方法，将其格式化成数组
     */
    handleVinInput() {
      // 如果当前没有输入
      if (!this.vinInput) {
        return
      }
      // 替换中文的分号
      const replaceChinessSemicolon = this.vinInput.replace(/[；,，]/g, ';')
      // 按逗号分割
      const vinList = replaceChinessSemicolon.split(';')
      // 取出最后一个当成输入项目
      this.vinInput = vinList.pop()
      // 重新赋值vin的集合
      this.vinList = [
        ...(this.vinList || []),
        ...vinList.filter(vin => !!vin)
      ]
      // 先清空之前的数据
      this.vinGroup = [
        ...this.vinGroup,
        ...vinList.filter(vin => !!vin).map(vin => ({
          result: vin.length === 17,
          vin,
          message: vin.length === 17 ? '' : '请输入合法的vin号'
        }))
      ]
      // 双向绑定vinList
      this.$emit('input', this.vinList)
    },

    /**
     * vin输入框失去焦点的方法
     */
    handleVinInputBlur() {
      // 给vin加上；
      this.vinInput = this.vinInput + ';'
      // 将当前输入的vin初始化成需要校验的参数
      this.handleVinInput()
    },

    /**
     * vin输入的改变方法
     */
    handleVinItemChange(value, index) {
      // 如果当前没有输入值
      if (!value) {
        this.vinGroup.splice(index, 1)
      } else {
        // 替换中文的分号
        const replaceChinessSemicolon = value.replace(/[；,，]/g, ';')
        // 按逗号分割
        const vinList = replaceChinessSemicolon.split(';').filter(vin => !!vin)
        // 如果当前长度大于1个，说明输入了；
        if (vinList.length >= 1) {
          // 将当前输入的数据插到原来的对象中
          vinList.forEach((vin, vIndex) => {
            this.vinGroup.splice(index + vIndex, vIndex === 0 ? 1 : 0, {
              result: vin.length === 17,
              vin,
              message: vin.length === 17 ? '' : '请输入合法的vin号'
            })
          })
        }
      }
      // 重新赋值
      this.vinList = this.vinGroup.map(vin => vin.vin)
      // 双向绑定vinList
      this.$emit('input', this.vinList)
    },

    /**
     * 校验方法
     * @param results 需要回显的校验结果
     * @param index 当前需要校验的项目
     */
    validate(results = [], index = -1) {
      // 当前是否是错误
      let isError = true
      // 当前vin的集合
      const vinList = []
      // 如果没有输入
      if (this.vinGroup.length === 0) {
        this.$message.error('请输入VIN码')
        throw new Error('请输入VIN码')
      }
      // 写入错误信息
      this.vinGroup.forEach((group, gIndex) => {
        // 如果当前传入了需要校验的项目，则直接校验，如果没传，则全量校验
        if (index === -1 || gIndex === index) {
          // 如果当前vin输入的不合法
          if (group.vin.length !== 17) {
            isError = false
            group.result = false
            group.message = '请输入合法的vin号'
          } else {
            group.result = true
            group.message = ''
          }
          // 现在开始校验输入的结果
          results.forEach(result => {
            if (group.vin === result.vin) {
              group.result = result.checkResult
              group.message = result.errorMsg
              isError = isError && result.checkResult
            }
          })
          vinList.push(group.vin)
        }
      })
      // 如果校验有错误
      if (!isError) {
        throw new Error('请输入正确的VIN号')
      }
      return vinList
    }
  }
}
</script>

<style lang="scss">
.component-vin-input {
  .el-textarea {
    width: 896px;
    height: 390px;
    .el-textarea__inner {
      padding: 12px;
    }
  }
  .vin-input-wrapper {
    border: 1px solid #DCDFE6;
    border-radius: 4px;
    width: 896px;
    min-height: 390px;
    .vin-edit {
      display: inline-block;
      width: 168px;
      margin-left: 8px;
      margin-top: 8px;
      .el-input {
        width: 100%;
        height: 36px;

        .el-input__inner  {
          background-color: #F7F8FA;
          border-color: #ffffff;
          box-shadow: none;
          color: #212026;
          font-size: 14px;
          font-weight: 400;
          padding: 0 10px;
        }
      }
      .error-tip {
        display: none;
        color: #FF4D4F;
        font-weight: 400;
        font-size: 12px;
        line-height: 18px;
        height: 18px;
        margin-top: 2px;
        position: absolute;
      }
      &.input-error {
        margin-bottom: 20px;
        .el-input {
          .el-input__inner {
            border-color: #FF4D4F;
          }
        }
        .error-tip {
          display: block;
        }
      }
    }
    .vin-input {
      display: inline-block;
      width: 168px;
      margin-left: 8px;
      margin-top: 8px;
      .el-input__inner  {
        background-color: #FFFFFF;
        border-color: #ffffff;
        box-shadow: none;
        color: #212026;
        font-size: 14px;
        font-weight: 400;
        padding: 0 10px;
      }
    }
  }
  .vin-tip {
    color: rgba(132, 133, 138, 0.7);
    font-size: 12px;
    font-weight: 400;
    line-height: 18px;
    height: 18px;
    margin-top: 10px;
  }
}
</style>
