<!--
 * @Description: 
 * @Author: 陈长吉
 * @Date: 2019-06-03 10:55:50
 * @LastEditTime: 2019-07-19 16:55:54
 * @LastEditors: 陈长吉
 -->
<template>
  <div>
    <el-cascader
      class="address-cascader"
      ref="cascader"
      v-bind="$attrs"
      v-model="myValue"
      @active-item-change="handleItemChange"
      :options="optionsTree"
      @change="handleChange"
    />
  </div>
</template>

<script>
import * as http from '@/utils/http/core'
import { map } from 'rxjs/operators'
import { dispatch } from '@/mixins'
export default {
  name: 'EAddressCascader',
  mixins: [dispatch],
  props: {
    grade: {
      // 1省 2市 3区 4县
      default: 4
    },
    options: {
      type: Array
    },
    action: {
      // 接口地址
      required: false,
      default: '/fmsloanadmin/admin/supplier/basic/info/address'
    },
    valueKey: {
      // 请求参数的key
      required: false,
      default: 'code'
    },
    codeKey: {
      // 接口返回的code的key
      required: false,
      default: 'code'
    },
    dataKey: {
      // 接口返回的data的key
      required: false,
      default: 'data'
    },
    value: {
      type: Array,
      default() {
        return []
      }
    },
    world: {
      // 国际地址
      type: Boolean,
      default: false
    }
  },
  watch: {
    value(val) {
      if (Array.isArray(val) && val.length > 0) {
        this.getValueOption(val)
      }
      this.myValue = val
    }
  },
  data() {
    return {
      optionsTree: [],
      myValue: this.value
    }
  },
  mounted() {
    let code = this.world ? -1 : 0
    this.getOptions(code).subscribe((res) => {
      if (res && Array.isArray(res.data)) {
        this.$set(this, 'optionsTree', res.data)
      }
    })
  },
  methods: {
    /**
     * @description: 初始化数据显示
     * @param {type}
     * @return:
     */
    getValueOption(arr, num = 0) {
      this.setOptionsChildren(arr[num]).then(() => {
        if (arr.length < ++num) {
          this.getValueOption(arr, num)
        }
      })
    },
    /**
     * @description: 获取接口信息
     * @param {type}
     * @return:
     */
    getOptions(code) {
      let data = {}
      data[this.valueKey] = code
      return http.httpAgent(http.GET(this.action, data, {}), this.filterResponse).pipe(
        map((res) => {
          let obj = [...res.data]
          res.data.map((item) => {
            item.label = item.name
            item.value = item.code + ''
            if (!this.isLastrade(item.value)) {
              item.children = []
            }
            delete item.name
            delete item.code
          })
          return res
        })
      )
    },
    /**
     * @description: 子类点击
     * @param {type}
     * @return:
     */
    handleItemChange(val) {
      const value = val[val.length - 1]
      this.setOptionsChildren(value)
    },
    setOptionsChildren(value) {
      if (value === undefined) return
      return new Promise((resolve) => {
        let findItem = this.findOptionItem(value)
        if (
          !findItem ||
          (findItem && findItem.children && findItem.children.length > 0) ||
          !findItem.children
        ) {
          resolve()
          return
        }
        this.getOptions(value).subscribe((res) => {
          this.$set(findItem, 'children', res.data)
          resolve()
        })
      })
    },
    /**
     * @description: 查找code对应的对象
     * @param {type}
     * @return:
     */
    findOptionItem(code) {
      function findeArray(arr) {
        arr.forEach((item) => {
          if (item.value === code) {
            throw item
          } else if (item.children) {
            findeArray(item.children)
          }
        })
      }
      try {
        findeArray(this.optionsTree)
      } catch (error) {
        if (error.value) {
          return error
        }
      }
    },

    /**
     * @method: change事件
     * @param value{Array} 值
     * @return:
     * @Author: 陈长吉（chencj@yunjiglobal.com）
     * @Date: 2019-06-05 10:25:56
     */
    handleChange(value) {
      setTimeout(() => {
        this.setParentValue(value)
      }, 0)
    },
    /**
     * @method: 向父组件传选中值
     * @param {type}
     * @return:
     * @Author: 陈长吉（chencj@yunjiglobal.com）
     * @Date: 2019-06-05 10:25:53
     */
    setParentValue(value) {
      this.$emit('input', value)
        .$emit('change', value)
        .$emit('update:presentText', this.$refs.cascader.currentLabels)
      if (this.validateEvent) {
        // 触发表单校验
        this.dispatch(this, 'ElFormItem', 'el.form.change', [value])
        this.dispatch(this, 'ElFormItem', 'el.form.blur', [value])
      }
    },
    /**
     * @description: 重写的http过滤器
     * @param {type}
     * @return:
     */
    filterResponse(res) {
      if (!res.data || res.data[this.codeKey] !== 0 || res.status !== 200) {
        throw {
          response: res,
          status: res.status,
          request: res.request,
          responseText: res.data && res.data.errorMessage ? res.data.errorMessage : '网络错误',
          errorCode: res.data && res.data[this.codeKey] ? res.data[this.codeKey] : 1
        }
      }
      return {
        data: res.data[this.dataKey],
        response: res
      }
    },
    /**
     * @description: 查找有没有子类
     * @param {type}
     * @return:
     */

    isLastrade(value) {
      let grade = this.world ? [4, 7, 10, 13] : [2, 5, 8, 11]
      return (value + '').length === grade[this.grade - 1]
    }
  }
}
</script>
<style lang="less" scoped>
.address-cascader {
  width: 300px;
}
</style>
