<template>
  <div>
    <div class="flexbox form__box" :style="{ width: width || '100%' }">
      <div
        class="title form__title"
        v-if="title"
        :style="{ width: title_width || '' }"
        :title="title"
      >
        <span class="red2" v-if="emphasize">*</span>
        <slot name="title"></slot>
        {{ title }}
        <slot name="titleAfter"></slot>
      </div>

      <!-- 显示已选指标项 -->
      <div class="flex" style="line-height:1.2">
        <draggable v-model="choiceSelect" handle=".btn-draggable" @end="end" v-if="!isTree">
          <el-tag
            v-for="(tag,index) in choiceSelect"
            :key="index"
            closable
            size="small"
            class="btn-draggable"
            @close="removeItem($event, tag.code,'out')"
          >({{tag.code}}){{tag.name}}</el-tag>
        </draggable>
        <span class="iconfont icon-Group-13 add-icon vxe-button--icon font20" @click="showDialog"></span>
      </div>
    </div>
    <biTreeDraggable
      :tasks="targetTreeDatas"
      v-if="isTree"
      style="margin-left:15px"
      @dragEndTree="dragEndTree"
      @delTree="delTree"
    />
    <diaLog :source="layObj" ref="targetDialog" width="80%" height="85%" @close="closeDialog">
      <div class="filter-con">
        <ts-select
          title="指标归类"
          v-model="filterObj.targetCategory"
          placeholder="请选择指标归类"
          :source="targetCategorySource"
          width="240px"
          @change="refresh"
          titleWidth="auto"
        ></ts-select>
        <ts-select
          title="指标单位"
          v-model="filterObj.targetUnit"
          placeholder="指标单位"
          :source="targetUnitSource"
          width="180px"
          @change="refresh"
          titleWidth="auto"
        ></ts-select>
        <ts-input
          v-model="filterObj.condition"
          placeholder="请输入名称/编码/定义的关键字搜索"
          width="280px"
          class="mrgl5"
          @searchClick="refresh()"
          @keyup="keyup"
          type="search"
        ></ts-input>
      </div>
      <ts-row type="flex" class="main-con">
        <ts-col class="left-tree-con">
          <ts-tree
            :source="treeObj"
            width="100%"
            height="100%"
            row-id="itemCode"
            :is-border="false"
            :expandAll="true"
            ref="tree"
            @onSelectRow="onTreeSelectRow"
            :checkRows="filterObj.busType?[filterObj.busType]:['yp']"
          ></ts-tree>
        </ts-col>
        <ts-col style="width:calc(100% - 150px)">
          <div style="height:calc(100% - 120px)">
            <ts-table
              :source="sourceTable"
              width="100%"
              height="100%"
              ref="tsTable"
              rowId="code"
              :isHideFunc="true"
              @checkboxChange="checkboxChange"
              @checkboxAll="checkboxAll"
              @radioChange="radioChange"
            ></ts-table>
          </div>
          <div class="selected-con">
            <div class="selected-txt">
              <p class="font12 txt">已选指标({{choiceSelect_.length||0}}):</p>
            </div>
            <div class="flex selected-target-con">
              <el-tag
                v-for="(tag,index) in choiceSelect_"
                :key="index"
                closable
                size="small"
                @close="removeItem($event, tag.code)"
              >({{tag.code}}){{tag.name}}</el-tag>
            </div>
          </div>
        </ts-col>
      </ts-row>
    </diaLog>
  </div>
</template>

<script>
import Draggable from 'vuedraggable'
import biTreeDraggable from './biTreeDraggable'
export default {
  name: 'tsTargetSelect',
  components: { Draggable, biTreeDraggable },
  props: {
    value: {
      type: [String, Number],
      default: ''
    },
    isTree: Boolean,
    emphasize: Boolean,
    title: String,
    width: String,
    titleWidth: [String, Number],
    source: Object
  },
  data() {
    return {
      currentValue: this.value,
      setObj: JSON.parse(JSON.stringify(this.source || {})),
      sourceTable: {},
      filterObj: { status: '01', pageSize: 2000 },
      targetUnitSource: this.getDictSource('BI_TARGETUNIT'),
      targetCategorySource: this.getDictSource('BI_CATE'),
      treeObj: {
        childName: 'children',
        dataType: 'local',
        data: [{ itemCode: '', itemName: '指标分类', children: [] }],
        page: 'pageNo',
        code: 'itemCode',
        textName: 'itemName'
      },
      title_width: '',
      layObj: {
        title: '选择指标', // 标题
        closeBtn: false, // 关闭按钮区域，boolean 默认：false
        buttons: [
          {
            text: '确认',
            event: this.confirmTarget,
            icon: 'iconfont icon-baocun1'
          }
        ]
      },
      targetTreeDatas: [],
      choiceSelect: [],
      choiceSelect_: [] // 弹框中所选
    }
  },
  created() {
    // 标题宽度计算
    if (this.titleWidth) {
      this.title_width = this.titleWidth.toString()
      if (
        this.titleWidth !== 'auto' &&
        this.title_width.indexOf('px') == -1 &&
        this.title_width.indexOf('%') == -1
      ) {
        this.title_width = this.title_width + 'px'
      }
    }
  },
  mounted() {
    this.sourceTable = this.sourceFn()
    if (this.setObj.dataType != 'local') {
      // 非本地数据
      this.getTargetDatas()
    } else {
      this.sourceTable.data = this.setObj.data
        ? [...this.setObj.data]
        : this.$store.state.bi.targetSource || []
      this.rebackSelect()
    }
    this.targetTreeDatas = [...(this.setObj.targetTreeDatas || [])]
    this.getBusiTypeData()
    this.layObj.title = '选择指标(' + (this.setObj.choice ? '多选)' : '单选)')
  },
  methods: {
    // 得到字段源
    getDictSource(type, choice) {
      return {
        dataType: 'json',
        url: '/ts-system/api/dict/item/list/' + type,
        method: 'get',
        data: {},
        page: 'pageNo',
        code: 'itemCode',
        text: 'itemName',
        condition: 'condition',
        choice: choice || false
      }
    },
    // 获取业务分类数据
    getBusiTypeData() {
      if (
        this.treeObj.data[0].children &&
        this.treeObj.data[0].children.length > 0
      ) {
        return
      }
      const _this = this
      this.$api({
        url: '/ts-system/api/dict/item/list/BI_BUSTYPE',
        method: 'get',
        loading: false
      }).then(res => {
        if (res.success) {
          _this.treeObj.data[0].children = res.object
        }
      })
    },
    // 获取所有指标
    getTargetDatas() {
      const _this = this
      this.$api({
        url: '/ts-bi/api/OfBusiCode/distinctCodeList',
        data: this.filterObj,
        method: 'get'
      })
        .then(res => {
          _this.sourceTable.data = res.object
          _this.$nextTick(() => {
            if (!_this.setObj.choice) {
              _this.sourceTable.checkRowKey = _this.currentValue
            } else {
              _this.sourceTable.checkRowKeys = _this.currentValue
                ? _this.currentValue.split(',')
                : []
            }
          })
          // _this.rebackSelect()
        })
        .catch(error => {
          _this.$utils.msg(_this, error.message || '系统异常', 'error')
        })
    },
    // 拖动结束
    end() {
      let currentValueArr = []
      for (let cs of this.choiceSelect) {
        currentValueArr.push(cs.code)
      }
      this.currentValue = currentValueArr.join(',')
      this.$emit('input', this.currentValue)
      if (this.setObj.choice) {
        this.$emit('change', this.currentValue)
      } else {
        this.$emit('change', this.choiceSelect[0])
      }
    },
    showDialog() {
      this.choiceSelect_ = [...this.choiceSelect] // 赋值
      this.$refs.targetDialog.open()
      this.$nextTick(() => {
        if (!this.setObj.choice) {
          this.sourceTable.checkRowKey = this.currentValue
        } else {
          this.sourceTable.checkRowKeys = this.currentValue
            ? this.currentValue.split(',')
            : []
        }
      })
    },
    //关闭弹窗
    closeDialog() {
      if (
        this.filterObj.targetCategory ||
        this.filterObj.condition ||
        this.filterObj.busType
      ) {
        this.filterObj = { status: '01', pageSize: 2000 }
        this.getTargetDatas()
      }
    },
    // 拖拽结束树
    dragEndTree() {
      this.$emit('change', this.targetTreeDatas)
    },
    delTree(node) {
      let arr = this.currentValue.split(',')
      this.delChoiceCurrent(node.el, arr) 
      this.targetTreeDatas = [...node.tasks]
      
      this.$emit('input', this.currentValue)
      this.$emit('change', this.targetTreeDatas)
    },
    //递归删除多余的选择内容
    delChoiceCurrent(item, arr) {
      let index = arr.findIndex(res => res == item.code)
      index>-1?arr.splice(index, 1):''
      this.currentValue = arr.join(',')
      let choiceIndex = this.choiceSelect.findIndex(
        res => res.code == item.code
      )
      choiceIndex>-1?this.choiceSelect.splice(choiceIndex, 1):''
      
      if (item.children && item.children.length > 0) {
        for (let child of item.children) {
          this.delChoiceCurrent(child, arr) 
        }
      }
    },
    confirmTarget() {
      this.$emit('input', this.currentValue)
      if (this.setObj.choice) {
        // 多选
        if (this.isTree) {
          // 树结构
          this.confirmTreeTarget()
        } else {
          this.$emit('change', this.currentValue)
        }
      } else {
        this.$emit('change', this.choiceSelect_[0])
      }
      this.choiceSelect = [...this.choiceSelect_] // 赋值回来
      this.$refs.targetDialog.close()
    },
    confirmTreeTarget() {
      for (let item of this.choiceSelect_) {
        // 去除多余的
        let success =
          this.targetTreeDatas.length == 0
            ? false
            : this.setTreeData(this.targetTreeDatas, item)
        if (!success) {
          this.targetTreeDatas.push({
            name: '(' + item.code + ')' + item.name,
            id: item.id,
            code: item.code,
            children: [
              // 暂时先这样，以后整理
              {
                name: '',
                children: []
              }
            ]
          })
        }
      }
      // targetTreeDatas>choiceSelect_的情况,弹框删除choice的情况，同时在树里删除
      this.deleteTargetDatas(this.targetTreeDatas)
      this.$emit('change', this.targetTreeDatas)
    },
    // 删除targetTreeDatass>choiceSelect_的情况
    deleteTargetDatas(list) {
      for (let i = 0; i < list.length; i++) {
        let item = list[i]
        let index = this.choiceSelect_.findIndex(res => res.id == item.id)
        if (item.name&&index == -1) {
          list.splice(i, 1) // 删除多余
          i--
        } else {
          if (item.children && item.children.length > 0) {
            this.deleteTargetDatas(item.children)
          }
        }
      }
    },
    // 获取模拟数据
    setTreeData(list, chioce) {
      for (let item of list) {
        if (item.id == chioce.id) {
          return true
        }
        if (item.children && item.children.length > 0) {
          let success = this.setTreeData(item.children, chioce)
          if (success) {
            return success
          }
        }
      }
      return false
    },
    // 列表配置
    sourceFn() {
      let self = this
      let checkRowKeys = []
      if (this.currentValue) {
        // 回显
        checkRowKeys = this.currentValue.split(',')
      }
      return {
        dataType: 'local',
        trigger: 'row',
        data: [],
        colModel: this.colFn(),
        showOverflow: true,
        checkbox: this.setObj.choice,
        checkRowKeys: checkRowKeys,
        radio: !this.setObj.choice,
        checkRowKey: this.currentValue
      }
    },
    colFn() {
      let self = this
      return [
        {
          title: '编码',
          field: 'code',
          width: 70,
          align: 'center'
        },

        {
          title: '指标名称',
          field: 'name',
          width: 250
        },
        {
          title: '指标定义',
          field: 'definition',
          width: 200
        },
        {
          title: '业务分类',
          field: 'busTypeName',
          width: 80
        },
        {
          title: '计算公式',
          field: 'calculateMethod',
          width: 120
        },
        {
          title: '指标导向',
          field: 'goodDirection',
          width: 80
        },
        {
          title: '指标说明',
          field: 'zbkDesc',
          width: 100
        },
        {
          title: '指标单位',
          field: 'targetUnit',
          width: 100
        },
        {
          title: '指标属性',
          field: 'targetAttribute',
          width: 100
        },
        {
          title: '指标归类',
          field: 'targetCategory',
          width: 100
        }
      ]
    },
    refresh() {
      this.$nextTick(() => {
        this.getTargetDatas()
      })
    },
    onTreeSelectRow(row) {
      this.$nextTick(() => {
        this.filterObj.busType = row.itemCode
        this.getTargetDatas()
      })
    },
    // 键盘按下
    keyup(e) {
      if (e.$event.keyCode === 13) {
        // 回车
        this.refresh()
      }
    },
    checkboxChange(rowid, data, checked) {
      if (!this.setObj.choice) {
        return
      }
      if (checked) {
        // 选中
        this.currentValue = this.currentValue
          ? this.currentValue + ',' + data.code
          : data.code
        this.choiceSelect_.push(data)
      } else {
        // 取消选中
        this.removeItem(null, data.code)
      }
    },
    radioChange(row) {
      if (this.setObj.choice) {
        return
      }
      this.currentValue = row.code
      this.choiceSelect_ = [row]
    },
    // 全选
    checkboxAll(selection, checked) {
      if (checked) {
        for (let item of selection) {
          let arr = this.currentValue.split(',')
          let index = arr.findIndex(res => res == item.code)
          if (index == -1) {
            // 不存在
            this.currentValue = this.currentValue
              ? this.currentValue + ',' + item.code
              : item.code
            this.choiceSelect_.push(item)
          }
        }
      } else {
        for (let item of this.$refs.tsTable.$refs.tstable.data) {
          // 取消选中
          this.removeItem(null, item.code)
        }
      }
    },
    // 回显名称
    rebackSelect() {
      // 首次进入需回显
      if (this.currentValue && this.choiceSelect.length == 0) {
        let val = this.currentValue
        if (!val || typeof val == 'object') {
          return
        }
        let arr = val.split(',')
        // 递归回显数据
        for (let res of arr) {
          //按选择顺序排序
          for (let item of this.sourceTable.data) {
            if (res == item.code) {
              this.choiceSelect.push(item)
              if (!this.setObj.choice) {
                //单选
                break
              }
            }
          }
        }
      }
    },
    // 删除选中
    removeItem(event, id, type) {
      event ? event.stopPropagation() : ''
      if (this.value && !this.currentValue) {
        this.currentValue = this.value
      }
      if (this.currentValue) {
        if (this.setObj.choice) {
          if (this.choiceSelect.length != 0 && this.choiceSelect_.length == 0) {
            // 两值不对称
            this.choiceSelect_ = [...this.choiceSelect]
          }
          // 多选
          let arr = this.currentValue.split(',')
          let index = arr.findIndex(res => res == id)
          if (index > -1) {
            arr.splice(index, 1)
          }
          this.currentValue = arr.join(',')
          if (this.choiceSelect_) {
            let index = this.choiceSelect_.findIndex(res => res.code == id)
            this.choiceSelect_.splice(index, 1)
          }
          this.$refs.tsTable
            ? (this.$refs.tsTable.$refs.tstable.selection = [
                ...this.choiceSelect_
              ])
            : ''
          this.sourceTable.checkRowKeys = arr
        } else {
          // 单选
          this.currentValue = ''
          this.choiceSelect_ = []
          this.$refs.tsTable
            ? this.$refs.tsTable.$refs.tstable.clearRadioRow()
            : ''
        }
      }
      if (type == 'out') {
        this.choiceSelect = [...this.choiceSelect_]
        // 外部删除，直接传出
        this.$emit('input', this.currentValue)
        if (this.setObj.choice) {
          this.$emit('change', this.currentValue)
        } else {
          this.$emit('change', this.choiceSelect_[0])
        }
      }
    }
  },
  watch: {
    value(val) {
      this.currentValue = val
    },
    '$store.state.bi.targetSource': {
      handler(n) {
        this.sourceTable.data = [...n]
        this.rebackSelect()
      },
      deep: true
    }
    // currentValue(val) {
    //   this.$emit('input', val)
    //   this.$emit('change', val)
    // }
  }
}
</script>

<style lang="scss" scoped>
.main-con {
  height: calc(100% - 35px);
  .left-tree-con {
    width: 150px;
    border: 1px solid var(--border_color);
  }
  .selected-con {
    height: 120px;
    padding: 0 5px;
    .txt {
      padding: 5px;
    }
    .selected-target-con {
      height: calc(100% - 28px);
      overflow: hidden;
      overflow-y: auto;
    }
    .selected-txt {
      height: 28px;
    }
  }
}
.filter-con {
  display: flex;
  height: 34px;
  align-items: center;
  padding: 0 5px;
}

.el-tag {
  color: var(--button_color);
  // border-color: var(--button_color);
  margin: 0 5px 5px 0;
  white-space: break-spaces;
  display: inline-table;
  /deep/.el-tag__close {
    color: var(--button_color);
    &:hover {
      color: white;
    }
  }
}
.add-icon {
  // color: var(--button_color);
  cursor: pointer;
  &:hover {
    color: var(--button_color);
  }
}
</style>
