<!--面包屑导航-->
<template>
  <div class="super-search" ref="superSearch" :style="{height: isShow ? maxHeight : height}">
    <el-form :model="search" label-suffix="：" label-position="left" size="medium">
      <!--  基础搜索  -->
      <div ref="basic" class="basic-search">
        <div class="search-title">
          <div class="title-left">基础搜索</div>
          <div class="title-right">
            <el-button size="mini" type="primary" icon="el-icon-search" @click="searchClick">查询
            </el-button>
            <el-button size="mini" icon="el-icon-refresh-right" @click="resetClick">重置</el-button>
            <div class="arrow" @click="isShowAdvance" v-if="search.basicSearchArr.length">
              <i :class="['el-icon-arrow-down', isShow ? 'arrow-down': 'arrow-up' ]" />
              {{ isShow ? '收起' : '展开' }}
            </div>
          </div>
        </div>
        <div class="search-content" v-if="search.basicSearchArr.length">
          <el-form-item :label-width="item.labelWidth" :label="item.itemLabel"
                        v-for="(item,index) in search.basicSearchArr"
                        :key="index">
            <template v-if="item.itemType === 'radio' || item.itemType === 'newRadio'">
              <el-checkbox-group v-model="item.itemValue" @change="val => radioChange(val,item)">
                <el-checkbox
                  :label="_item.value"
                  v-for="(_item,_index) in item.option"
                  :key="_index"
                >
                  {{ _item.name }}
                </el-checkbox>
              </el-checkbox-group>
            </template>
            <template v-else-if="item.itemType === 'checkbox'">
              <div style="display: flex;column-gap: 5px">
                <el-checkbox v-if="item.itemType === 'checkbox'"
                             :indeterminate="item.isIndeterminate"
                             v-model="item.checkAll"
                             @change="val => handleCheckAllChange(val,item)">全选
                </el-checkbox>
                <el-checkbox-group v-model="item.itemValue">
                  <el-checkbox
                    :label="_item.value"
                    v-for="(_item,_index) in item.option"
                    :key="_index"
                    @change="val => handleCheckedCitiesChange(val,item)"
                  >
                    {{ _item.name }}
                  </el-checkbox>
                </el-checkbox-group>
              </div>
            </template>
            <template v-else-if="item.itemType === 'switch'">
              <el-switch
                v-model="item.itemValue"
                :inactive-text="item.option[0].name"
                :inactive-value="item.option[1].name"
                :active-text="item.option[1].name"
                :active-value="item.option[1].value"
              >
              </el-switch>
            </template>
          </el-form-item>
        </div>
        <div class="advance-search" v-else>
          <div class="search-content">
            <div class="row">
              <div class="col" v-for="(item,index) in search.advanceSearchArr" :key="index">
                <template v-if="item.itemType === 'input'">
                  <el-form-item :label-width="item.labelWidth" :label="item.itemLabel">
                    <el-input
                      v-model="item.itemValue"
                      :clearable="true"
                      :placeholder="`请输入${item.itemLabel}`"
                    ></el-input>
                  </el-form-item>
                </template>
                <template v-else-if="item.itemType === 'select'">
                  <el-form-item :label-width="item.labelWidth" :label="item.itemLabel">
                    <el-select v-model="item.itemValue" clearable :placeholder="`请选择${item.itemLabel}`">
                      <el-option
                        v-for="_item in item.option"
                        :key="_item.value"
                        :label="_item.name"
                        :value="_item.value">
                      </el-option>
                    </el-select>
                  </el-form-item>
                </template>
              </div>
            </div>
          </div>
        </div>
      </div>
      <div :style="{opacity: isShow ? 1 : 0 }" class="advance-search">
        <div class="search-title">
          <div class="title-left">高级搜索</div>
          <div class="title-right"></div>
        </div>
        <div class="search-content">
          <div class="row">
            <div class="col" v-for="(item,index) in search.advanceSearchArr" :key="index">
              <template v-if="item.itemType === 'input'">
                <el-form-item :label-width="item.labelWidth" :label="item.itemLabel">
                  <el-input
                    v-model="item.itemValue"
                    :clearable="true"
                    :placeholder="`请输入${item.itemLabel}`"
                  ></el-input>
                </el-form-item>
              </template>
              <template v-else-if="item.itemType === 'select'">
                <el-form-item :label-width="item.labelWidth" :label="item.itemLabel">
                  <el-select v-model="item.itemValue" clearable :placeholder="`请选择${item.itemLabel}`">
                    <el-option
                      v-for="_item in item.option"
                      :key="_item.value"
                      :label="_item.name"
                      :value="_item.value">
                    </el-option>
                  </el-select>
                </el-form-item>
              </template>
              <template v-else-if="item.itemType === 'picker'">
                <el-form-item :label-width="item.labelWidth" :label="item.itemLabel">
                  <el-date-picker style="width: 100%;" v-model="item.itemValue" :type="item.timeType"
                                  :value-format="item.valueFormat"
                                  :placeholder="`请选择${item.itemLabel}`"></el-date-picker>
                </el-form-item>
              </template>
            </div>
          </div>
        </div>
      </div>
    </el-form>
  </div>
</template>

<script>
import lodash from 'lodash'

export default {
  name: 'SuperSearch',
  props: {
    // 搜索表单
    searchForm: {
      default() {
        return {}
      },
      type: Object
    },
    // 搜索配置项
    basisOption: {
      default() {
        return []
      },
      type: Array
    }
  },
  data() {
    return {
      search: {
        basicSearchArr: [], // 基础搜索
        advanceSearchArr: [] // 高级搜索
      },
      isShow: false,
      height: '0',
      maxHeight: '0',
      cloneForm: {}
    }
  },
  watch: {
    search: {
      handler(searchArr) {
        Object.keys(searchArr).forEach(key => {
          searchArr[key].forEach(i => {
            if (i.itemType === 'newRadio') {
              this.$set(this.searchForm, i.itemProp, i.itemValue[0] || '')
            } else {
              this.$set(this.searchForm, i.itemProp, i.itemValue)
            }
          })
        })
      },
      deep: true
    }
  },
  created() {
    // 克隆原表单
    this.cloneForm = lodash.cloneDeep(this.searchForm)
    this.dataInitialization(this.cloneForm)
  },
  mounted() {
    this.getAllHeight()
    this.$root.$on('resize', _ => this.getAllHeight(200))
  },
  methods: {
    // 计算元素高度函数
    getHeightUnfold(dom) {
      let fakeNode = dom.cloneNode(true)
      fakeNode.style.maxHeight = '1000px'
      dom.parentNode.insertBefore(fakeNode, dom)
      fakeNode.style.height = 'auto'
      fakeNode.style.visibility = 'hidden'
      let height = fakeNode.getBoundingClientRect().height
      dom.parentNode.removeChild(fakeNode)
      return height
    },

    // 动态计算收起，展开高度
    getAllHeight(delay = 0, callback) {
      if (!(this.$refs.superSearch && this.$refs.basic)) return
      this.$refs.superSearch.style.transition = 'height 0s'
      this.$nextTick(_ => {
        this.height = this.getHeightUnfold(this.$refs.basic) + 'px'
        this.maxHeight = this.getHeightUnfold(this.$refs.superSearch) + 'px'
        setTimeout(_ => {
          this.$refs.superSearch.style.transition = 'height 0.3s'
          callback && callback(this.height, this.maxHeight)
        }, delay)
      })
    },

    // 初始化数据结构
    dataInitialization(form = {}) {
      const [basicSearchArr, advanceSearchArr] = ['basic', 'advance'].map(searchType => {
        return this.basisOption.flatMap(i => {
          if (i.searchType !== searchType) return []
          let itemValue,
            labelWidth,
            isIndeterminate = false,
            checkAll = false,
            timeType,
            valueFormat
          if (i.itemType === 'checkbox' || i.itemType === 'radio') {
            itemValue = typeof form[i.itemProp] === 'undefined' ? [] : form[i.itemProp]
            checkAll = i.option.length === itemValue.length
            isIndeterminate = itemValue.length > 0 && itemValue.length < i.option.length
          } else if (i.itemType === 'newRadio') {
            itemValue = typeof form[i.itemProp] === 'undefined' ? [] : [form[i.itemProp]]
          } else {
            itemValue = typeof form[i.itemProp] === 'undefined' ? '' : form[i.itemProp]
          }
          labelWidth = i.labelWidth || 'auto'
          timeType = i.timeType || ''
          valueFormat = i.valueFormat || ''

          return {
            ...i,
            isIndeterminate,
            checkAll,
            itemValue,
            labelWidth,
            timeType,
            valueFormat
          }
        })
      })
      this.search.basicSearchArr = basicSearchArr
      this.search.advanceSearchArr = advanceSearchArr
    },

    // 全选改变
    handleCheckAllChange(val, item) {
      item.itemValue = val ? item.option.map(i => i.value) : []
      item.isIndeterminate = false
    },

    //   多选勾选改变
    handleCheckedCitiesChange(val, item) {
      item.checkAll = item.option.length === item.itemValue.length
      item.isIndeterminate = item.itemValue.length > 0 && item.itemValue.length < item.option.length
    },

    // 单选框改变
    radioChange(val, item) {
      // 保证只能选中一个
      if (val.length <= 1) return
      item.itemValue = [val[val.length - 1]]
    },

    // 重置
    resetClick() {
      Object.keys(this.searchForm).forEach(key => {
        Object.keys(this.cloneForm).forEach(_key => {
          if (key === _key) this.searchForm[key] = this.cloneForm[key]
        })
      })
      this.$emit('reset', this.searchForm)
      this.dataInitialization(this.cloneForm)
    },

    // 搜索
    searchClick() {
      this.$emit('search', this.searchForm)
    },

    // 展开高级搜索
    isShowAdvance() {
      this.isShow = !this.isShow
      this.$emit('is-show-advance')
    }
  },
  beforeDestroy() {
    this.$root.$off('resize', _ => this.getAllHeight(200))
  }
}
</script>

<style lang="scss" scoped>
@import "~@/assets/css/element-variables";

.super-search {
  width: 100%;
  overflow: hidden;

  .basic-search {
    .search-title {
      .title-right {
        display: flex;
        align-items: center;

        .arrow {
          margin-left: 30px;
          display: flex;
          align-items: center;
          column-gap: 4px;
          user-select: none;
          cursor: pointer;
          transition: all 0.15s;
          font-size: 13px;

          i {
            font-size: 13px;
            transition: all 0.2s;

            &.arrow-down {
              transform: rotate(180deg);
            }

            &.arrow-up {
              transform: rotate(0);
            }
          }

          &:hover {
            color: $--system-hover-active-text;
          }
        }
      }
    }


    .el-form-item {
      &:not(:last-child) {
        padding: 3px 0;
        border-bottom: 1px dashed $--system-border-color3;
      }

      &:last-child {
        padding-top: 3px;
      }
    }
  }

  .advance-search {
    transition: opacity 0.2s;

    .search-content {
      .row {
        display: flex;
        flex-wrap: wrap;
        row-gap: 20px;
        column-gap: 40px;
        margin-top: 10px;

        .col {
          width: calc((100% - 120px) / 4);
        }
      }
    }
  }

  .basic-search,
  .advance-search {
    width: 100%;

    .search-title {
      display: flex;
      justify-content: space-between;
      border-bottom: 1px solid $--system-border-color2;
      padding-bottom: 8px;

      .title-left {
        font-size: 16px;
        font-weight: 500;
        font-family: Microsoft YaHei, serif;
        display: flex;
        align-items: center;
        padding-left: 12px;
        position: relative;

        &::before {
          content: '';
          width: 2px;
          border-radius: 2px;
          height: 15px;
          position: absolute;
          left: 0;
          top: 50%;
          transform: translateY(-50%);
          background: $--system-hover-active-text;
        }
      }

      .title-right {
      }
    }

    .search-content {
      width: 100%;
      box-sizing: border-box;
      padding: 5px 0 0 12px;
    }
  }

  ::v-deep .el-form {
    display: flex;
    flex-direction: column;
    row-gap: 10px;

    .el-form-item {
      margin-bottom: 0;
      display: flex;

      .el-form-item__label-wrap {
        margin-left: 0 !important;

        .el-form-item__label {
          padding-right: 10px;
        }
      }

      .el-form-item__content {
        margin-left: 0 !important;
        flex: 1;
        display: flex;
        align-items: center;
        flex-wrap: wrap;
      }

      .el-form-item__label {
        font-weight: 600;
        width: auto !important;
      }

      .el-checkbox-group {
        display: flex;
        align-items: center;
      }

      .el-checkbox {
        margin-right: 10px;

        &.is-checked {
          .el-checkbox__label {
            background-color: #4080FF;
            color: #fff;
            border-radius: 4px;
          }
        }

        .el-checkbox__input {
          display: none;

          &.is-indeterminate + .el-checkbox__label {
            color: #4080FF;
          }
        }

        .el-checkbox__label {
          padding: 3px 8px;
          transition: all 0.1s;
        }
      }
    }

    .search-content {
    }
  }

  ::v-deep .el-button {
    height: auto !important;
  }
}
</style>
