<template>
  <div
    v-if="permission != 'n'"
    :class="[
      'inputs',
      formInputsDisplay == 'block'
        ? 'ht-form-inputs__block'
        : 'ht-form-inputs__inline',
    ]"
  >
    <template v-if="inputWriteable">
      <input
        v-if="disabled && isValidate && !isSubCellReadOnly"
        v-model="inputVal"
        v-validate="inputValidate"
        type="hidden"
        :name="inputName"
        :data-vv-as="name"
      />
      <template v-if="!isMobile">
        <template v-if="isSubCellReadOnly">
          <input
            v-if="isSubCellReadOnly"
            v-model="inputVal"
            v-validate="inputValidate"
            type="hidden"
            :name="inputName"
            :data-vv-as="name"
          />
          <div class="sub-table-cell-readonly" @click="handleCellClick">
            <span>
              {{ labelValue.join() }}
            </span>
          </div>
        </template>
        <template v-else>
          <el-select
            v-if="ganged"
            ref="treeselect"
            v-model="inputVal"
            v-validate="inputValidate"
            style="width: 100%"
            :name="inputName"
            :data-vv-as="name"
            :size="inputSize"
            :clearable="clearable"
            :placeholder="placeholder"
            :filterable="filterable"
            :filter-method="filterMethod"
            :multiple="multiple"
            :multiple-limit="limitCount"
            :disabled="disabled"
            @visible-change="handleVisibleChange"
            @clear="() => $emit('clear')"
            @remove-tag="handleSelectTagRemove"
            @focus="selectBlur"
          >
            <el-option
              v-for="(item, index) in tempoptions"
              v-show="false"
              :key="`${item.key}_selectTree${index}`"
              :value="item.key"
              :label="item.value"
            ></el-option>
            <el-option value disabled>
              <el-tree
                ref="treeselectElTree"
                node-key="id"
                :data="options"
                :highlight-current="true"
                :default-expand-all="treeDataMode === 1 ? false : true"
                :default-checked-keys="valueChange"
                :expand-on-click-node="false"
                :props="defaultProps"
                :indent="indent"
                :lazy="treeDataMode === 1 ? true : false"
                :load="loadTree"
                :filter-node-method="filterNode"
                :show-checkbox="multiple"
                :check-strictly="!cascade"
                @check="handleNodeClick"
                @node-click="handleNodeClick"
                @check-change="handleCheckChange"
              ></el-tree>
            </el-option>
          </el-select>
          <ht-select
            v-if="!ganged"
            ref="selected"
            v-model="inputVal"
            :validate="inputValidate"
            :options="options"
            :name="name"
            :data-vv-as="name"
            :multiple-limit="limitCount"
            :size="inputSize"
            :clearable="clearable"
            :placeholder="placeholder"
            :filterable="filterable"
            reserve-keyword
            :multiple="multiple"
            :permission="permission_sub"
            :disabled="disabled"
            :loading="loadingOptions"
            @click.native="clickNative"
            @blur="selectBlur"
          />
        </template>
      </template>
      <template v-else>
        <div class="mobile-cell__wrap">
          <!-- 校验 -->
          <input
            v-model="inputVal"
            v-validate="validateRules"
            type="hidden"
            :name="inputName"
            :data-vv-as="name"
          />
          <van-cell
            v-validate="!inputVal && validateRules"
            class="mobile-cell cell"
            :class="{ 'mobile-disabled-cell': disabled }"
            :name="inputName"
            :data-vv-as="name"
            title=" "
            is-link
            :disabled="disabled"
            @click.stop="handleShowDialog"
          >
            <div class="flex">
              <span v-if="inputVal && inputVal.length > 0" class="cell-text">
                <template>
                  {{ showName(inputVal) }}&nbsp;
                  <span v-if="showName(inputVal, false).split(',').length > 3">
                    共{{ showName(inputVal, false).split(',').length }}项
                  </span>
                </template>
              </span>

              <span
                v-if="!inputVal || inputVal.length == 0"
                class="placeholder-class"
              >
                {{ mobilePlaceholder('请选择') }}
              </span>
              <van-icon
                v-if="inputVal && inputVal.length && !disabled"
                name="clear"
                color="#bfbfbf"
                @click.stop="clearSelect"
              />
            </div>
          </van-cell>
        </div>
      </template>
    </template>
    <van-cell
      v-if="inputWriteable === false && isMobile"
      class="mobile-cell"
      @click="
        inputVal &&
        inputVal.length > 0 &&
        showName(inputVal, false).split(',').length > 3
          ? showAllPeople(showName(inputVal, false))
          : ''
      "
    >
      <template #default>
        <span v-if="inputVal && inputVal.length > 0" class="cell-text">
          <span v-if="showName(inputVal, false).split(',').length < 4">
            {{ showName(inputVal) }}
          </span>
          <span v-else>
            {{ showName(inputVal).split(',').splice(0, 3).join(',') }}&nbsp;共{{
              showName(inputVal, false).split(',').length
            }}项
          </span>
        </span>
        <span
          v-if="!inputVal || inputVal.length == 0"
          class="placeholder-class"
        ></span>
      </template>
      <template
        v-if="
          inputVal &&
          inputVal.length > 0 &&
          showName(inputVal, false).split(',').length > 3
        "
        #right-icon
      >
        <span class="mobileCellRightIcon">
          <slot name="mobile-right-icon">
            <van-icon name="arrow" />
          </slot>
        </span>
      </template>
    </van-cell>
    <ht-field-tail
      v-if="permission != 'n'"
      :field-name="inputName"
      :readonly="!isMobile ? !inputWriteable : false"
      input-value
      :tag-format-value="!isMobile ? labelValue : []"
    />
    <select-tree-mobile-dialog
      v-if="isMobile"
      ref="selectTreeMobileDialog"
      :data="options"
      :ganged="ganged"
      :clone-list="cloneList"
      :multiple="multiple"
      :limit-count="limitCount"
      :displayfield="displayfield"
      :treeDataMode="treeDataMode"
      primaryField="key"
      @select-data="(data) => $emit('select-data', data)"
      @input="(data) => $emit('input', data)"
      @dataList="(data) => $emit('dataList', data)"
      @upDateList="upDateList"
    />
    <select-tree-mobile-Page
      v-if="isMobile && page"
      ref="selectTreeMobilePage"
      :data="options"
      :ganged="ganged"
      :clone-list="cloneList"
      :multiple="multiple"
      :limit-count="limitCount"
      :displayfield="displayfield"
      :treeDataMode="treeDataMode"
      primaryField="key"
      @select-data="(data) => $emit('select-data', data)"
      @input="(data) => $emit('input', data)"
      @dataList="(data) => $emit('dataList', data)"
      @upDateList="upDateList"
    />
    <LookAllPeople
      v-if="isMobile"
      ref="LookAllPeople"
      :title="'已选项'"
    ></LookAllPeople>
  </div>
</template>
<script>
  import LookAllPeople from '../../LookAllPeople/index'
  import utils from '@/utils.js'
  import permission from '@/mixins/permission.js'
  import inputName from '@/mixins/inputName.js'
  import linkage from '@/mixins/linkage.js'
  import ganged from '@/mixins/ganged.js'
  import form from '@/mixins/form.js'
  import mobileMode from '@/mixins/mobileMode.js'
  import SelectTreeMobileDialog from './SelectTreeMobileDialog.vue'
  import SelectTreeMobilePage from './SelectTreeMobilePage.vue'
  import CustomQuery from '@/services/CustomQuery'
  import tableFieldReadOnly from '@/mixins/tableFieldReadOnly.js'
  export default {
    name: 'HtSelectTree',
    components: { SelectTreeMobileDialog, SelectTreeMobilePage, LookAllPeople },
    mixins: [
      permission,
      inputName,
      linkage,
      ganged,
      form,
      mobileMode,
      tableFieldReadOnly,
    ],
    props: {
      value: String,
      selectlist: Array,
      multiple: {
        //多选
        type: Boolean,
        default: false,
      },
      page: {
        type: Boolean,
        default: false,
      },
      clearable: {
        type: Boolean,
        default: true,
      },
      indent: {
        type: Number,
        default: 8,
      },
      filterable: {
        type: Boolean,
        default: false,
      },
      customQuery: Object,
      cascade: {
        type: Boolean,
        default: false,
      },
      limitCount: {
        type: Number,
        default: 0,
      },

      title: {
        type: String,
        default: '请选择',
      },
      disabled: {
        type: Boolean,
        default: false,
      },
      isValidate: {
        type: Boolean,
        default: false,
      },
      pvalue: {
        type: String | Number,
        default: 0,
      },
      treeDataMode: {
        type: Number,
        default: 0,
      },
    },

    data() {
      return {
        options: [],
        cloneList: [],
        tempoptions: [],
        tagFormatValue: [],
        defaultProps: {
          children: 'children',
          label: 'value',
          disabled: this.limitDisabled,
        },
        loadingOptions: false,
        valueChange: [],
        oncePerform: true,
      }
    },
    watch: {
      value: {
        handler(val) {
          if (val && typeof val === 'string') {
            this.valueChange = val.split(',')
          }
          if (val && Array.isArray(val)) {
            this.valueChange = val
          }
        },
        immediate: true,
        deep: true,
      },
    },
    computed: {
      inputVal: {
        get() {
          if (this.multiple) {
            if (this.value) {
              return this.value.split(',')
            } else {
              return []
            }
          } else if (this.value || this.value === 0) {
            return this.value + ''
          } else {
            return this.value
          }
        },
        set(val) {
          if (this.multiple) {
            this.$emit('input', val.join(','))
          } else {
            this.$emit('input', val)
            if (!this.multiple && val) {
              //判断对话框是否绑定了关联查询
              if (
                this.customQuery &&
                this.customQuery.custQueryJson &&
                this.customQuery.custQueryJson.length > 0
              ) {
                let custQueryJson = this.customQuery.custQueryJson
                for (let i = 0; i < custQueryJson.length; i++) {
                  if (custQueryJson[i].conditionfield.length > 0) {
                    this.doSubCustomQuery(custQueryJson[i])
                  } else {
                    console.error(
                      '[' +
                        custQueryJson[i].comment +
                        ']关联查询取值参数未绑定表单字段'
                    )
                  }
                }
              }
            }
          }
        },
      },
      labelValue() {
        let labelAry = []
        let changeData = []
        this.tempoptions.forEach((opt) => {
          if (this.multiple) {
            if (this.inputVal.some((v) => v == opt.key)) {
              labelAry.push(opt.value)
              changeData.push(opt.key)
            }
          } else {
            if (opt.key == this.inputVal) {
              labelAry.push(opt.value)
              changeData.push(opt.key)
              return
            }
          }
        })
        if (!this.tempoptions || this.tempoptions.length < 1) {
          if (this.multiple) {
            this.inputVal &&
              this.inputVal.length > 0 &&
              this.inputVal.forEach((item) => {
                if (!changeData.includes(item)) {
                  labelAry.push(item)
                }
              })
          } else {
            labelAry.length === 0 && this.inputVal
              ? labelAry.push(this.inputVal)
              : []
          }
        }
        labelAry=[...new Set(labelAry)]
        return labelAry
      },
      validateRules() {
        return this.disabled && !this.isValidate ? '' : this.inputValidate
      },
      displayfield() {
        let list = {
          id: this.ganged.valueBind || 'key',
        }

        return JSON.stringify(list)
      },
    },
    created() {
      this.loadOption('init')
    },
    mounted() {},
    methods: {
      showAllPeople(value) {
        this.$refs.LookAllPeople.showDialog(value)
      },
      limitDisabled(data, node) {
        if (this.multiple) {
          let check = this.inputVal.includes(data.key)
          return (
            !check &&
            (this.inputVal || []).length >= this.limitCount &&
            this.limitCount > 0
          )
        } else {
          return false
        }
      },
      showName(val, type = true) {
        if (this.value) {
          let nameList = []
          let alreadCheck = []
          let list = this.multiple ? this.value.split(',') : [this.value]

          if (list.length > 2 && type) {
            list.length = 3
          }
          list.forEach((item) => {
            this.cloneList.map((val) => {
              if (this.ganged) {
                if (item == val[this.ganged.valueBind]) {
                  nameList.push(val[this.ganged.labelBind])
                  alreadCheck.push(item)
                }
              } else {
                if (item == val['key']) {
                  nameList.push(val['value'])
                  alreadCheck.push(item)
                }
              }
            })
          })
          list.forEach((item) => {
            if (!alreadCheck.includes(item)) {
              nameList.push(item)
            }
          })

          nameList = Array.from(new Set(nameList))
          return nameList.join()
        }
      },
      clearSelect() {
        this.selectResult = []
        this.selectStr = ''
        this.$emit('input', '')
        // this.$emit('change', '')
      },
      handleShowDialog() {
        if (this.readonly || this.disabled) return
        this.selectBlur()
        let data = []
        if (this.multiple) {
          data = this.inputVal
        } else {
          data = this.inputVal ? this.inputVal.split(',') : []
        }
        this.$refs.selectTreeMobileDialog.showDialog(data)
      },

      handleSelectTagRemove(value) {
        this.$refs.treeselectElTree.setChecked(value, false, this.cascade)
      },
      //判断对象里面的值是否为空
      objIsEmpty(obj) {
        for (let key in obj) {
          if (obj[key]) {
            return false
          }
        }
        return true
      },
      // 加载选项
      loadOption(isInit = '') {
        if (this.ganged && this.ganged.alias) {
          // 如果初始化时不需加载选项时
          if (isInit === 'init' && this.ganged.noInit === 'true') {
            return
          }
          this.dynamicLoadOption()
        } else {
          const selectList = this.selectlist ? this.selectlist : []
          this.options = selectList.map((item) => {
            return {
              ...item,
              id: item.key,
            }
          })
        }
      },
      //pc懒加载
      loadTree(node, resolve) {
        if (node && node.data && node.data instanceof Object && node.data.id) {
          this.dynamicLoadOption(node.data.id, 'add', (res) => {
            this.tempoptions = []
            let cloneListDaa = [...this.cloneList, ...res]
            this.addSelectList(cloneListDaa)
            this.cloneList = _.cloneDeep(cloneListDaa)
            resolve(res)
            this.$forceUpdate()
          })
        }
      },
      // mobile懒加载
      upDateList(node, resolve) {
        let displayfield = JSON.parse(this.displayfield)

        if (node && node instanceof Object && node[displayfield.id]) {
          this.dynamicLoadOption(node.id || node[displayfield.id], 'add', (res) => {
            this.tempoptions = []
            let cloneListDaa = [...this.cloneList, ...res]
            this.addSelectList(cloneListDaa)
            let map = new Map()
            for (let item of cloneListDaa) {
              map.set(item[displayfield.id], item)
            }

            this.cloneList = _.cloneDeep([...map.values()])

            resolve(res)
            this.$forceUpdate()
          })
        }
      },
      // 动态加载选项
      dynamicLoadOption(nodeId, type, cb) {
        this.loadingOptions = true
        let setOption = {
          treeDataMode: this.treeDataMode,
          PId: this.ganged.PId,
          pvalue: this.pvalue,
          type: type,
          nodeId: nodeId,
        }

        this.doCustomQuery(null, false, setOption)
          .then(({ data, query }) => {
            let params = {}

            if (params && this.ganged.valueBind) {
              params = {
                [this.ganged.valueBind]: this.value,
              }
            }
            if (data) {
              data.forEach((items) => {
                items.showArrow = true
              })
            }

            if (data && this.ganged.PId) {
              if (type != 'add') {
                this.tempoptions = []
              }
              this.addSelectList(data)
              var dataDep = _.cloneDeep(data)
              data = utils.tile2nest(
                data,
                this.ganged.valueBind || 'key',
                this.ganged.PId
              )
              if (type == 'add') {
                cb(data)
              } else {
                this.cloneList = _.cloneDeep(dataDep)
                this.options = data
                // 逐级执行查询值
                if (
                  this.oncePerform &&
                  query &&
                  this.value &&
                  this.treeDataMode === 1
                ) {
                  this.searchValue(query, params, '1', {}, dataDep)
                }
              }
            } else if (data) {
              if (type == 'add') {
                cb(data)
              } else {
                this.tempoptions = []
                this.addSelectList(data)

                this.cloneList = _.cloneDeep(data)
                data = utils.tile2nest(
                  data,
                  this.ganged.valueBind || 'key',
                  this.ganged.PId
                )
                this.options = data
                // 逐级执行查询值
                if (
                  this.oncePerform &&
                  query &&
                  this.value &&
                  this.treeDataMode === 1
                ) {
                  this.searchValue(query, params, '1', {}, cloneList)
                }
              }
            }
          })
          .finally(() => {
            this.loadingOptions = false
          })
      },
      //逐级回显name
      searchValue(query, params, type, setOption, dataDep) {
        this.oncePerform = false
        let queryChange = {
          ...query,
          conditionfield: JSON.stringify([
            {
              field: this.ganged.valueBind,
              defaultValue: this.value,
              condition: 'IN',
            },
          ]),
        }
        CustomQuery._doQuery(queryChange, params, type, setOption, (res) => {
          if (res) {
            this.tempoptions = []
            res.forEach((items) => {
              items.showArrow = true
            })

            let dataDepList = [...dataDep, ...res]

            dataDepList = _.uniqBy(dataDepList, this.ganged.valueBind)
            this.addSelectList(dataDepList)
            this.cloneList = _.cloneDeep(dataDepList)
            let data = utils.tile2nest(
              dataDepList,
              this.ganged.valueBind || 'key',
              this.ganged.PId
            )

            this.options = data
            this.cloneList = _.uniqBy(this.cloneList, this.ganged.valueBind)
            this.options = _.uniqBy(this.options, this.ganged.valueBind)
            this.$forceUpdate()
          }
        })
      },
      doSubCustomQuery() {
        //TODO 实现关联子查询
      },
      clickNative: function () {
        this.loadOption()
      },
      selectBlur: function () {
        this.loadOption()
      },
      handleCheckChange(data, currentChecked) {
        if (this.multiple) {
          let checkedNodes = this.$refs.treeselectElTree.getCheckedNodes()
          if (
            this.limitCount > 0 &&
            checkedNodes.length > this.limitCount &&
            currentChecked
          ) {
            this.$refs.treeselectElTree.setChecked(data, false, true)
            return
          }
          let modelValue = []
          // this.tempoptions = checkedNodes
          for (let data of checkedNodes) {
            modelValue.push(data.key)
          }
          this.$emit('input', modelValue.join(','))
        }
      },
      handleNodeClick(data) {
        if (!this.multiple) {
          this.$emit('input', data.key)

          if (data.key) {
            //判断对话框是否绑定了关联查询
            if (
              this.customQuery &&
              this.customQuery.custQueryJson &&
              this.customQuery.custQueryJson.length > 0
            ) {
              let custQueryJson = this.customQuery.custQueryJson
              for (let i = 0; i < custQueryJson.length; i++) {
                if (custQueryJson[i].conditionfield.length > 0) {
                  this.doSubCustomQuery(custQueryJson[i])
                } else {
                  console.error(
                    '[' +
                      custQueryJson[i].comment +
                      ']关联查询取值参数未绑定表单字段'
                  )
                }
              }
            }
          }
          this.$refs.treeselect.blur()
          setTimeout(() => {
            this.$validator.validate(this.inputName)
          })
        }
      },
      filterNode(value, data) {
        if (!value) return true
        return data.value.indexOf(value) !== -1
      },
      filterMethod(query) {
        this.$refs.treeselectElTree.filter(query)
      },
      handleVisibleChange() {
        this.$refs.treeselectElTree.filter('')
        //当没值时 下拉树自动定位会到最前面
        if (!this.inputVal || this.inputVal.length == 0) {
          this.$nextTick(() => {
            const treeElselect =
              this.$refs.treeselectElTree &&
              this.$refs.treeselectElTree.$parent &&
              this.$refs.treeselectElTree.$parent.$parent &&
              this.$refs.treeselectElTree.$parent.$parent.$el.querySelectorAll(
                '.el-select-dropdown__wrap'
              )
            setTimeout(() => {
              treeElselect &&
                treeElselect.length > 0 &&
                treeElselect.forEach((item) => {
                  item.scrollTo({
                    top: 0,
                  })
                })
            }, 0)
          })
        }
      },

      addSelectList(list) {
        let valueFiled =
          (this.ganged.valueBind || '') == 'key' ? '' : this.ganged.valueBind
        let labelFiled =
          (this.ganged.labelBind || '') == 'value' ? '' : this.ganged.labelBind
        if (list && list.length > 0) {
          list.forEach((l) => {
            if (valueFiled) {
              l['key'] = l[valueFiled]
            }
            if (labelFiled) {
              l['value'] = l[labelFiled]
            }
            l['id'] = l.id || l.ID || l.id_ || l.ID_ || l[valueFiled]
            this.tempoptions.push(l)
            if (l.children) {
              this.addSelectList(l.children)
            }
          })
        }
      },
    },
  }
</script>
<style lang="scss" scoped>
  div[aria-invalid='true'] {
    ::v-deep {
      .el-input__inner,
      .el-input__inner:focus {
        border-color: #f56c6c;
      }
    }
  }

  .el-select-dropdown__item.hover,
  .el-select-dropdown__item:hover {
    background-color: #fff;
  }

  .el-select-dropdown__item {
    font-size: 14px;
    padding: 0 8px;
    position: relative;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    color: #606266;
    height: 100%;
    line-height: 34px;
    -webkit-box-sizing: border-box;
    box-sizing: border-box;
    cursor: pointer;
  }

  li.el-select-dropdown__item.selected {
    font-weight: normal;
  }

  .mobile_field_input {
    border: none;
    width: 100%;
    height: 32px;
    position: absolute;
  }
  .van-cell[aria-invalid='true'] {
    border: none;
  }
  .cell {
    .flex {
      display: flex;
      align-items: center;
      justify-content: flex-end;
      i {
        margin-left: 5px;
      }
    }
    // position: absolute;
    // top: 0;
    // left: 0;
  }
  .van-cell {
    padding: 0;
    // min-height: 32px;
    // padding-top: 3px;
    // padding-bottom: 0;
    // padding-right: 0;
    &::after {
      display: none;
    }
    .van-cell__title {
      width: 1px;
      flex-grow: 0;
    }
  }
  .custom-van-pop {
    max-height: 80%;
    display: flex;
    flex-direction: column;
    .pop-header {
      display: flex;
      justify-content: space-between;
      align-items: center;
      padding: 12px 15px;
      .cancel {
        font-size: 14px;
        color: #8c8c8c;
      }
      .title {
        font-size: 17px;
        color: #1a1a1a;
        font-weight: bold;
      }
      .confirm {
        font-size: 14px;
        color: #3177ec;
      }
    }
    .pop-content {
      flex: 1;
      overflow: auto;
      -webkit-overflow-scrolling: touch;
      margin: 16px 0;
      .van-radio-group,
      .van-checkbox-group {
        ::v-deep .radio-item {
          padding: 14px 15px;
          border-bottom: 1px solid #e6e6e6;
          .van-radio__label,
          .van-checkbox__label {
            margin-left: 12px;
            color: #262626;
            font-size: 14px;
          }
        }
        .radio-item:last-child {
          border-bottom: none;
        }
      }
    }
  }
  .placeholder-class {
    color: #bfbfbf;
    font-size: 14px;
    text-align: right;
  }
  .cell-text {
    word-break: break-all;
    color: #262626;
    font-size: 14px;
    text-align: right;
  }
  .mobile-cell__wrap {
    min-height: 32px;
    position: relative;
    display: flex;
    align-items: center;
  }
  .mobile-cell {
    min-height: 32px;
    padding: 0;
    align-items: center;
    &::after {
      display: none;
    }
    .van-cell__value {
      display: flex;
      align-items: center;
      justify-content: flex-end;
      .cell-text {
        flex: 1;
        word-break: break-all;
        color: #262626;
        font-size: 14px;
        text-align: right;
        padding: 12px 0;
      }

      .placeholder-class {
        flex: 1;
        color: #bfbfbf;
        font-size: 14px;
        text-align: right;
      }
      .cell-close {
        margin-left: 8px;
      }
    }
  }
  [v-cloak] {
    display: none;
  }
</style>
