<!--
  * @File: 标签 多选、单选 混合组件
  * @FileDescription:
      接收父组件传递过来的数组数据，遍历出单选或多选框，并保存值返回结果。
      * 组件案例 *
      <CategoriesList
        ref='categoriesList'                   // 定义组件名称
        :title="'标签'"                        // 定义对话框标题名称
        :pitchOn="checkarr"                  // 定义选中返回值
        :tagsList="tagsList"                  // 定义列表数据
        :search="'search'"                    // 定义是否显示搜索框
        @callbackCheckIds='callbackCheckIds'  // 接收子组件返回的数据
      />
  * @Author: 蒋新平
  * @Date: 2021.10.20
  * @Update: 2021.10.25
-->
<template>
  <a-modal
    :title="title"
    :width="800"
    :visible="tagVis"
    :destroyOnClose="true"
    :maskClosable="true"
    @ok="handleOk"
    @cancel="handleCancel"
    :bodyStyle="{ padding: search === 'search' ? '0 0 20px 0' : '20px 0' }"
  >
    <!--  搜索框  -->
    <a-row
      type="flex"
      justify="end"
      align="middle"
      v-if="search === 'search'"
      class="ScrollButton"
    >
      <a-col :span="8">
        <a-input
          size="large"
          v-model="value"
          placeholder="请输入"
          @keydown="addByEnterKey"
          @change="SearchChange"
          :suffix="tagsIndex.length > 0 ? position + '/' + tagsIndex.length : '0/0'"
        />
      </a-col>
      <a-col :span="2">
        <!--        <a-button type="primary" @click="getSearch">搜索</a-button>-->
        <div class="but flex-row space-around">
          <a-icon type="up" style="cursor: pointer;" @click.stop="setUp"/>
          <a-icon type="down" style="cursor: pointer;" @click.stop="setDown"/>
        </div>
      </a-col>
    </a-row>
    <!--  筛选内容  -->
    <div
      id="Scroll"
      class="Scroll"
      ref="scrollview"
      @mousewheel="scrollChange"
    >
      <div
        v-for="(item, index) in tagsLableList"
        :key="index"
        class="park-title-category"
      >
        <div class="park-title-left">
          <span>{{ item.name }}:</span>
        </div>
        <div class="park-title-right" v-if="item.multi_select">
          <div :style="{ borderBottom: '1px solid #E9E9E9', paddingBottom: '5px', marginBottom: '5px' }">
            <a-checkbox
              ref="checksboxAll"
              :indeterminate="item.indeterminate"
              :checked="item.checkAll"
              @change="onCheckAllChange($event, index)"
            >全选</a-checkbox>
          </div>
          <a-checkbox-group
            ref="checksbox"
            name="checkboxgroup"
            class="park-main-check"
            v-model="checked[index]"
            :defaultValue="getCheckBoxValue(item.category_tags)"
            @change="onCheckboxChange($event, index, item.category_tags)"
          >
            <a-checkbox
              v-for="(tags, i) in item.category_tags"
              :key="i"
              :value="tags.value"
              :id="'box' + index + i"
              :style="{ color: (tags.color ? '#40a9ff' : '') }"
            >
              <span style="color: black;" :style="{ background: (tags.color ? '#40a9ff' : '') }">{{ tags.label }}</span>
            </a-checkbox>
          </a-checkbox-group>
        </div>
        <div class="park-title-right" v-if="!item.multi_select">
          <a-radio-group
            ref="radios"
            name="radioGroup"
            :defaultValue="getRadioValue(item.category_tags)"
          >
            <a-radio
              v-for="(tags, i) in item.category_tags"
              :key="i"
              :value="tags.value"
              :id="'box' + index + i"
            >
              <span style="color: black;" :style="{ background: (tags.color ? '#40a9ff' : '') }">{{ tags.label }}</span>
            </a-radio>
          </a-radio-group>
        </div>
      </div>
    </div>
  </a-modal>
</template>

<script>
  export default {
    name: 'Categories',
    data () {
      return {
        // tagVis: false,
        checkarr: [],
        checked: [],
        tagsLableList: [],
        value: '',
        position: 0, // 默认获取第一个位置
        tagsIndex: [] // 获取搜索的的ID数组
      }
    },
    props: {
      // 接收父组件传递过来的 title 值 - 非必传
      title: {
        type: String,
        default: '操作'
      },
      // 接收父组件传递过来的 选中的值 - 必传
      pitchOn: {
        type: Array,
        required: true
      },
      // 接收父组件传递过来的 列表数据 - 必传
      tagsList: {
        type: Array,
        required: true
      },
      // 接收父组件传递过来的 Search 值，判断是否显示搜索框 - 非必传
      search: {
        type: String,
        default: ''
      },
      // 控制是否（打开、关门）对话框 - 非必传
      tagVis: {
        type: Boolean,
        default: false
      },
      // 组件对应的下标 - 非必传
      index: {
        type: Number,
        required: true,
        default: null
      }
    },
    watch: {
      pitchOn: function (value) {
        this.checkarr = value
        this.setCheckbox()
      },
      tagsList: function (value) {
        this.tagsLableList = value
      }
    },
    created () {},
    mounted () {
      // 获取指定元素
      const scrollview = this.$refs['scrollview']
      // 添加滚动监听，该滚动监听了拖拽滚动条
      // 尾部的 true 最好加上，我这边测试没加 true ，拖拽滚动条无法监听到滚动，加上则可以监听到拖拽滚动条滚动回调
      // scrollview.addEventListener('scroll', this.scrollChange, true)
    },
    // beforeDestroy 与 destroyed 里面移除都行
    beforeDestroy () {
      // 获取指定元素
      const scrollview = this.$refs['scrollview']
      // 移除监听
      // scrollview.removeEventListener('scroll', this.scrollChange, true)
    },
    computed: {
      // 通过自动计算属性， 过滤出每一个是否被选中
      // 获取CheckBox默认值
      getCheckBoxValue () {
        var checkarr = this.checkarr
        return item => item.filter(v => checkarr && checkarr.indexOf(v.value) !== -1).map(v => v.value)
      },
      // 获取Radio默认值
      getRadioValue () {
        var checkarr = this.checkarr
        return item => item.filter(v => checkarr && checkarr.indexOf(v.value) !== -1).map(v => v.value)[0]
      },
      setCheckBoxValue () {
        var checkarr = this.checked
        return item => item.filter(v => checkarr && checkarr.indexOf(v.value) !== -1).map(v => v.value)
      }
    },
    methods: {
      // 滚动监听
      scrollChange (e) {
        // console.log('父滚动条到页面顶部距离', e.target.offsetTop)
        // console.log('相对距离', this.$refs.scrollview.scrollTop)
        // console.log('绝对距离', e.target.offsetTop + this.$refs.scrollview.scrollTop)
      },
      // 键盘键触发事件
      addByEnterKey (e) {
        const _this = this
        // Enter键的代码就是13
        if (parseInt(e.keyCode) === 13) {
          _this.getSearch()
        }
      },
      // 当搜索框发生改变时触发事件
      SearchChange () {
        const _this = this
        // 搜索发生改变时归零
        _this.position = 0
        _this.tagsIndex = []
        if (_this.value) {
          _this.tagsLableList.forEach((tags, index) => {
            tags.category_tags.filter(v => {
              if (v.label.indexOf(_this.value) > -1) {
                v.color = true
              } else {
                v.color = false
              }
              return v.color
            })
            tags.category_tags.map((tiem, i) => {
              if (tiem.color) {
                _this.tagsIndex.push('box' + index + i)
              }
            })
          })
        } else {
          _this.tagsLableList.forEach((tags, index) => {
            tags.category_tags.filter(v => {
              v.color = false
              return v.color
            })
          })
        }
        setTimeout(() => {
          _this.setDown()
        }, 100)
        _this.$forceUpdate()
      },
      // 搜索框 向上筛查
      setUp () {
        const _this = this
        var boxc, top
        _this.position--
        if (_this.tagsIndex.length > 0) {
          // 判断当前上一个取消高亮
          if (_this.position === 0) {
            document.getElementById(_this.tagsIndex[_this.position]).parentNode.nextSibling.firstChild.style.background = '#40a9ff'
            boxc = document.getElementById(_this.tagsIndex[_this.tagsIndex.length - 1])
            _this.position = _this.tagsIndex.length
          } else if (_this.position > 0 && _this.position <= _this.tagsIndex.length) {
            document.getElementById(_this.tagsIndex[_this.position]).parentNode.nextSibling.firstChild.style.background = '#40a9ff'
            boxc = document.getElementById(_this.tagsIndex[_this.position - 1])
          }
          // 获取id 并 添加高亮 以及 定位位置
          boxc.parentNode.nextSibling.firstChild.style.background = '#FF9632'
          boxc.scrollIntoView() // 滑动到可视区域
        }
      },
      // 搜索框 向下筛查
      setDown () {
        const _this = this
        var boxc, top
        if (_this.tagsIndex.length > 0) {
          // 判断定位到最后一个时，返回第一个
          if (_this.position >= _this.tagsIndex.length) _this.position = 0
          // 判断当前下一个取消高亮
          if (_this.position === 0) {
            document.getElementById(_this.tagsIndex[_this.tagsIndex.length - 1]).parentNode.nextSibling.firstChild.style.background = '#40a9ff'
            boxc = document.getElementById(_this.tagsIndex[_this.position])
          } else if (_this.position > 0 && _this.position <= _this.tagsIndex.length) {
            document.getElementById(_this.tagsIndex[_this.position - 1]).parentNode.nextSibling.firstChild.style.background = '#40a9ff'
            boxc = document.getElementById(_this.tagsIndex[_this.position])
          }
          _this.position++
          // 获取id 并 添加高亮 以及 定位位置
          boxc.parentNode.nextSibling.firstChild.style.background = '#FF9632'
          boxc.scrollIntoView() // 滑动到可视区域
        }
      },
      // 根据返回值，设置全选框状态
      setCheckbox () {
        const _this = this
        _this.tagsLableList.forEach((v, i) => {
          if (v.multi_select) {
            _this.onCheckboxChange(_this.checkarr, i, v.category_tags)
          }
        })
      },
      // 触发多选框点击事件
      onCheckboxChange (e, i, item) {
        // console.log(e, i, item)
        const _this = this
        const repetition = []
        item.forEach(v => {
          e.forEach(e => {
            if (v.value === e) {
              repetition.push(v.value)
            }
          })
        })
        _this.tagsLableList[i].indeterminate = repetition.length > 0 && repetition.length < item.length
        _this.tagsLableList[i].checkAll = repetition.length === item.length
      },
      // 全选按钮
      onCheckAllChange (e, i) {
        const _this = this
        _this.checked[i] = _this.checked[i] ? _this.checked[i] : []
        if (e.target.checked) {
          _this.tagsLableList[i].category_tags.forEach(v => {
            if (_this.checked[i].indexOf(v.value) === -1) {
              _this.checked[i].push(v.value)
            }
          })
          _this.tagsLableList[i].checkAll = e.target.checked
          _this.tagsLableList[i].indeterminate = !e.target.checked
        } else {
          let indexTag = 0
          _this.tagsLableList[i].category_tags.forEach(v => {
            indexTag = _this.checked[i].indexOf(v.value)
            if (indexTag > -1) {
              _this.checked[i].splice(indexTag, 1)
            }
          })
          _this.tagsLableList[i].checkAll = false
          _this.tagsLableList[i].indeterminate = false
        }
        _this.$forceUpdate()
      },
      // 弹窗确定
      handleOk () {
        const _this = this
        const checks = _this.$refs.checksbox
        const radios = _this.$refs.radios
        const arr = []
        if (radios) radios.forEach(item => item.stateValue ? arr.push(item.stateValue) : '')
        if (checks) checks.forEach(item => item.sValue.forEach(v => arr.push(v)))
        arr.sort(function (a, b) { return a - b }) // js对数组中的数字排序
        _this.checkarr = arr
        this.$emit('callbackCheckIds', _this.checkarr, _this.index)
      },
      // 取消标签弹窗
      handleCancel () {
        this.$emit('handleCancel', this.index)
      }
    }
  }
</script>

<style lang='scss' scoped>
  ::v-deep .ant-checkbox-wrapper + .ant-checkbox-wrapper {
    margin-left: 0;
    margin-right: 8px;
    margin-bottom: 4px;
  }
  ::v-deep .ant-radio-wrapper {
    margin-bottom: 4px;
  }
  .Scroll {
    width: 100%;
    height: 400px;
    overflow-y: scroll;
  }
  .ScrollButton {
    width: 98%;
    margin: auto;
    height: 70px;
    background: white;
    margin-bottom: 20px;
    padding-right: 20px;
    box-shadow: 0px 4px 10px #F1F1F1;
    .but {
      height: 40px;
      border-top: 1px solid #d9d9d9;
      border-right: 1px solid #d9d9d9;
      border-bottom: 1px solid #d9d9d9;
    }
  }
  .park-title-category{
    overflow: hidden;
    margin-bottom: 15px;
    .park-title-left{
      width:25%;
      float:left;
      text-align:right;
      margin-right:10px;
    }
    .park-title-right{
      width:70%;
      float:left;
      .tags{
        padding:0 8px;
        background:#fafafa;
        border-radius:4px;
        border:1px solid #d9d9d9;
        margin-right:4px;
        .close{
          font-size:12px;
          cursor: pointer;
        }
      }
    }
  }
  .w-e-menu{
    z-index:1 !important;
  }
  ::v-deep .ant-modal-wrap {
    z-index: 10002;
  }
</style>
