<template>
  <div class="AiWechatSelecter" v-if="isReeset">
    <el-button
        v-if="!isHasSlot && !isShowUser"
        size="mini"
        type="primary"
        @click="showSelecter"
        :disabled="disabled">
      选择人员
    </el-button>
    <div v-if="isHasSlot" @click="isShow = true">
      <slot></slot>
    </div>
    <div class="AiWechatSelecter-userlist" v-if="!isHasSlot && isShowUser">
      <div class="user-item" v-for="(item, index) in value" :key="index">
        <img :src="item.avatar">
        <el-tooltip effect="dark" :content="item[props.label]">
          <span>{{ item[props.label] }}</span>
        </el-tooltip>
        <i class="iconfont iconwarning" @click="removeUser(index, item)" v-if="isAdd"></i>
      </div>
      <div class="user-add" @click="isShow = true" v-if="isAdd">
        <div class="userlist-add__icon">
          <i class="el-icon-plus"></i>
        </div>
        <span>选择</span>
      </div>
    </div>
    <ai-dialog
        title="选择人员"
        :visible.sync="isShow"
        width="1200px"
        append-to-body
        :modal-append-to-body="false"
        :close-on-click-modal="false"
        @onConfirm="onConfirm">
      <div class="AiWechatSelecter-container">
        <div class="AiWechatSelecter-container__left">
          <div class="AiWechatSelecter-header">
            <div class="AiWechatSelecter-header__left">
              <h2>部门</h2>
            </div>
            <el-input
                size="mini"
                clearable
                @clear="unitName = ''"
                :placeholder="`请输入部门`"
                v-model="unitName"
                suffix-icon="iconfont iconSearch">
            </el-input>
          </div>
          <el-scrollbar class="AiWechatSelecter-list">
            <el-tree
                :filter-node-method="filterNode"
                ref="tree"
                :props="defaultProps"
                node-key="id"
                :data="unitList"
                :expand-on-click-node="false"
                highlight-current
                :current-node-key="search.departmentId"
                :default-expanded-keys="defaultExpanded"
                :default-checked-keys="defaultChecked"
                @current-change="onTreeChange">
            </el-tree>
          </el-scrollbar>
        </div>
        <div class="AiWechatSelecter-container__middle">
          <div class="AiWechatSelecter-header AiWechatSelecter-header__right">
            <div class="AiWechatSelecter-header__left">
              <h2>人员</h2>
            </div>
            <el-input
                size="mini"
                clearable
                @clear="search.name = '', search.current = 1, getList()"
                :placeholder="`请输入姓名`"
                v-model="search.name"
                suffix-icon="iconfont iconSearch"
                v-throttle="() => {search.current = 1, getList()}">
            </el-input>
          </div>
          <el-scrollbar class="AiWechatSelecter-list">
            <div class="user-wrapper">
              <el-checkbox-group v-model="userIds" @change="onCheckboxChange">
                <el-checkbox v-for="item in list" :label="item[props.id]" :key="item[props.id]"
                             @change="e => onboxChange(item[props.id], e)">{{ item.name }}
                </el-checkbox>
              </el-checkbox-group>
            </div>
            <AiEmpty v-if="!list.length"></AiEmpty>
            <el-pagination
                background
                :current-page.sync="search.current"
                :total="search.total"
                small
                :page-size="search.size"
                :page-sizes="[10, 20, 50, 100]"
                layout="slot,->, prev, pager, next"
                :pager-count="search.pagerCount"
                @size-change="getList"
                @current-change="getList">
              <div class="paginationPre" v-if="isMultiple">
                <el-checkbox :disabled="!list.length" :indeterminate="isIndeterminate" @change="onAllChange"
                             v-model="isCheckAll">全选
                </el-checkbox>
              </div>
            </el-pagination>
          </el-scrollbar>
        </div>
        <div class="AiWechatSelecter-container__right">
          <div class="AiWechatSelecter-header AiWechatSelecter-header__right">
            <h2>已选择({{ chooseUser.length }})个</h2>
            <el-button size="mini" icon="el-icon-delete" @click="clearAll">清空</el-button>
          </div>
          <el-scrollbar class="AiWechatSelecter-list">
            <div class="tags-wrapper">
              <el-tag
                  v-for="(item, index) in chooseUser"
                  :key="index"
                  closable
                  @close="onClose(item, index)"
                  size="small"
                  type="info">
                {{ item.name }}
              </el-tag>
            </div>
          </el-scrollbar>
        </div>
      </div>
    </ai-dialog>
  </div>
</template>

<script>
export default {
  name: 'AiUserSelecter',
  model: {
    prop: 'value',
    event: 'change',
  },

  props: {
    instance: Function,
    isMultiple: {
      type: Boolean,
      default: true
    },
    disabled: {
      type: Boolean,
      default: false
    },
    isShowUser: {
      type: Boolean,
      default: false
    },
    disabledList: {
      type: Array,
      default: () => {
        return []
      }
    },
    isAdd: {
      type: Boolean,
      default: true
    },
    value: {
      type: Array
    },
    props: {
      type: Object,
      default: () => {
        return {
          label: 'name',
          id: 'id'
        }
      }
    },
    actions: {default: () => ({})}
  },

  data() {
    return {
      showUserList: [],
      chooseUser: [],
      isReeset: true,
      isCheckAll: false,
      search: {
        con: '',
        current: 1,
        size: 20,
        status: 1,
        name: '',
        total: 0,
        departmentId: ''
      },
      defaultExpanded: [],
      typeIndex: 0,
      defaultProps: {
        children: 'children',
        label: 'name'
      },
      unitName: '',
      unitList: [],
      isShow: false,
      list: [],
      userIds: []
    }
  },

  computed: {
    isHasOptionSlot() {
      return this.$slots.option
    },

    isHasSlot() {
      return this.$slots.default
    },

    isIndeterminate() {
      const arr = this.chooseUser.filter(v => {
        return this.list.map(v => v.id).includes(v.id)
      })
      this.isCheckAll = !!(arr.length === this.list.length && this.list.length);
      return arr.length !== 0 && arr.length < this.list.length
    },

    defaultChecked() {
      if (!this.value) {
        return []
      }
      this.chooseUser = JSON.parse(JSON.stringify(this.value.map(item => {
        return {
          ...item,
          id: item[this.props.id],
          name: item[this.props.label],
          [this.props.id]: item[this.props.id],
          [this.props.label]: item[this.props.label]
        }
      })))

      return this.value.map(v => v[this.props.id])
    },
    action: v => ({
      tree: "/app/wxcp/wxdepartment/listAll",
      users: `/app/wxcp/wxuser/list`,
      ...v.actions
    })
  },

  watch: {
    unitName(val) {
      this.$refs.tree.filter(val)
    },

    isShow(val) {
      if (val) {
        this.chooseUser = JSON.parse(JSON.stringify(this.value.map(item => {
          return {
            ...item,
            id: item[this.props.id],
            name: item[this.props.label],
            [this.props.id]: item[this.props.id],
            [this.props.label]: item[this.props.label]
          }
        })))
        this.userIds = this.chooseUser.map(v => v[this.props.id])
      }
    },

    disabledList: {
      handler() {
        this.getList()
      },
      deep: true
    }
  },

  mounted() {
    this.getTree()
    this.getList()

    if (this.value.length && this.isShowUser) {
      this.showUserList = JSON.parse(JSON.stringify(this.value.map(item => {
        return {
          ...item,
          id: item[this.props.id],
          name: item[this.props.label],
          [this.props.id]: item[this.props.id],
          [this.props.label]: item[this.props.label]
        }
      })))
      this.chooseUser = JSON.parse(JSON.stringify(this.value.map(item => {
        return {
          ...item,
          id: item[this.props.id],
          name: item[this.props.label],
          [this.props.id]: item[this.props.id],
          [this.props.label]: item[this.props.label]
        }
      })))

      this.userIds = this.chooseUser.map(v => v[this.props.id])
    }
  },

  methods: {
    clearAll() {
      this.userIds = []
      this.chooseUser = []
    },

    onAllChange(e) {
      if (e) {
        if (!this.chooseUser.length) {
          this.chooseUser = [
            ...this.list
          ]
        } else {
          this.list.forEach(v => {
            if (!this.chooseUser.map(e => e[this.props.id]).includes(v[this.props.id])) {
              this.chooseUser.push(v)
            }
          })
        }
      } else {
        this.chooseUser = this.chooseUser.filter(v => {
          return !this.list.map(v => v[this.props.id]).includes(v[this.props.id])
        })
      }

      this.userIds = this.chooseUser.map(v => v[this.props.id])
    },

    showSelecter() {
      if (this.disabled) return

      this.isShow = true
    },

    onTreeChange(e) {
      this.search.departmentId = e.id || ''
      this.search.current = 1

      this.$nextTick(() => {
        this.getList()
      })
    },

    reset() {
      this.isReeset = false

      this.$nextTick(() => {
        this.isReeset = true
      })
    },

    onboxChange(id, v) {
      if (!this.isMultiple) {
        const checked = this.list.filter(v => v[this.props.id] === id)
        if (v) {
          const v = checked[checked.length - 1]
          this.chooseUser = [v]
          this.userIds = [v.id]
        }

        if (!v) {
          if (this.chooseUser.findIndex(v => v[this.props.id] === id) > -1) {
            this.chooseUser = []
          }
        }
      }
    },

    onCheckboxChange(ids) {
      this.$nextTick(() => {
        const checked = this.list.filter(v => ids.includes(v[this.props.id]))
        const unChecked = this.list.filter(v => !ids.includes(v[this.props.id]))
        if (!this.isMultiple) {

          return false
        }

        this.chooseUser.forEach((v, index) => {
          if (unChecked.findIndex(e => e[this.props.id] === v[this.props.id]) > -1) {
            this.chooseUser.splice(index, 1)
          }
        })

        checked.forEach(v => {
          if (this.chooseUser.findIndex(e => e[this.props.id] === v[this.props.id]) < 0) {
            this.chooseUser.push(v)
          }
        })
      })
    },

    arrDeduplication(arr) {
      const hash = {};
      arr = arr.reduce(function (item, next) {
        hash[next.id] = hash[next.id] || item.push(next)
        return item
      }, [])

      return arr
    },
    removeUser(index, item) {
      this.chooseUser.splice(index, 1)
      this.userIds.splice(this.userIds.findIndex(v => v === item.id), 1)

      this.$nextTick(() => {
        this.$emit('change', this.chooseUser)
        this.showUserList = JSON.parse(JSON.stringify(this.chooseUser))
      })
    },

    addChild(parent, list) {
      for (let i = 0; i < list.length; i++) {
        if (list[i].parentid === parent.id) {
          list[i].i = parent.children.length
          parent.children.push(list[i])
        }
      }

      if (parent.children.length) {
        parent.children.forEach(v => {
          v.len = parent.children.length
        })
      }

      if (list.length > 0) {
        parent['children'].map(v => this.addChild(v, list))
      }
    },

    getList() {
      this.loading = true
      this.instance.post(this.action.users, null, {
        params: {
          ...this.search,
          departmentId: this.search.departmentId,
          listType: 0
        }
      }).then(res => {
        if (res.code == 0) {
          this.list = res.data.records.filter(v => {
            return this.disabledList.indexOf(v.id) === -1
          }).map(v => {
            return {
              ...v,
              isChecked: false
            }
          })
          this.search.total = res.data.total

          if (!this.list.length) {
            this.isCheckAll = false
          }

          this.$nextTick(() => {
            this.loading = false
          })
        } else {
          this.loading = false
        }
      }).catch(() => {
        this.loading = false
      })
    },

    getTree() {
      this.instance.post(this.action.tree, null, {
        params: {unitName: this.unitName}
      }).then(res => {
        if (res?.data) {
          const origin = res.data.itemList || res.data
          this.unitList = this.$arr2tree(origin, {parent: "parentid"})
          const defaultRoot = this.unitList.at(0)?.id
          this.defaultExpanded = [defaultRoot].filter(Boolean) || []
          this.search.departmentId = defaultRoot
        }
      })
    },

    onClose(item, index) {
      this.chooseUser.splice(index, 1)

      this.userIds.splice(this.userIds.findIndex(v => v === item.id), 1)
    },

    filterNode(value, data) {
      if (!value) return true
      if (this.typeIndex === 0) {
        return data.name.indexOf(value) !== -1
      }

      return data.name.indexOf(value) !== -1
    },

    onConfirm() {
      if (!this.isMultiple && this.chooseUser.length > 1) {
        return this.$message.error('不能多选')
      }

      this.$emit('change', JSON.parse(JSON.stringify(this.chooseUser.map(item => {
        return {
          ...item
        }
      }))))
      this.showUserList = JSON.parse(JSON.stringify(this.chooseUser.map(item => {
        return {
          ...item
        }
      })))
      this.isShow = false
    }
  }
}
</script>

<style lang="scss" scoped>
.AiWechatSelecter {
  box-sizing: border-box;

  .AiWechatSelecter-userlist {
    display: flex;
    align-items: center;
    flex-wrap: wrap;

    .user-add {
      margin-bottom: 6px;

      .userlist-add__icon {
        display: flex;
        align-items: center;
        justify-content: center;
        width: 40px;
        height: 40px;
        margin-bottom: 4px;
        border-radius: 2px;
        border: 1px solid #CCCCCC;
        cursor: pointer;

        &:hover {
          opacity: 0.6;
        }

        i {
          color: #CCCCCC;
          font-size: 20px;
        }
      }

      span {
        display: block;
        width: 100%;
        line-height: 22px;
        text-align: center;
        color: #888888;
        font-size: 14px;
      }
    }

    .user-item {
      position: relative;
      margin-bottom: 6px;
      margin-right: 16px;
      width: 40px;
      text-align: center;

      img {
        display: block;
        width: 40px;
        height: 40px;
        margin-bottom: 4px;
        border-radius: 2px;
        border: 1px solid #CCCCCC;
      }

      i {
        position: absolute;
        top: -7px;
        right: -5px;
        padding: 0 0 2px 2px;
        font-size: 16px;
        background: #fff;
        border-radius: 50%;
        cursor: pointer;

        &:hover {
          opacity: 0.6;
        }
      }

      span {
        display: block;
        width: 100%;
        line-height: 22px;
        text-align: center;
        color: #888888;
        font-size: 14px;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
        cursor: pointer;
      }
    }
  }
}

.AiWechatSelecter-container {
  display: flex;
  height: 480px;

  .tree-container {
    & > span {
      display: block;
      margin-bottom: 4px;
    }

    .tree-user__item {
      display: flex;
      align-items: center;
      margin-bottom: 10px;

      &:last-child {
        margin-bottom: 0;
      }
    }

    img {
      width: 27px;
      height: 27px;
      margin-right: 10px;
    }
  }

  :deep( .el-tree ) {
    width: fit-content;
    min-width: 100%;
    background: transparent;

    .el-tree-node__expand-icon.is-leaf {
      color: transparent !important;
    }

    .el-tree-node__content > .el-tree-node__expand-icon {
      padding: 4px;
    }

    .el-tree-node__content {
      height: 32px;
    }

    .el-tree__empty-text {
      color: #222;
      font-size: 14px;
    }

    .el-tree-node__children .el-tree-node__content {
      height: 32px;
    }

    .el-tree-node__content:hover {
      background: #E8EFFF;
      color: #222222;
      border-radius: 2px;
    }

    .is-current > .el-tree-node__content {
      &:hover {
        background: #2266FF;
        color: #fff;
      }

      background: #2266FF;

      span {
        color: #fff;
      }
    }
  }

  .mask-btn__wrapper {
    position: relative;
  }

  .mask-btn {
    position: absolute;
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
    z-index: 1;
  }

  .userlist-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 8px;
    padding: 0 17px;
    cursor: pointer;
    user-select: none;

    :deep( .el-checkbox__label ) {
      display: none;
    }

    .userlist-item__left {
      display: flex;
      align-items: center;

      span {
        color: #222222;
        font-size: 14px;
      }

      img {
        width: 40px;
        height: 40px;
        margin-right: 8px;
      }
    }
  }

  & > div {
    width: 280px;
    background: #FCFCFC;
    border: 1px solid #D0D4DC;
  }

  .AiWechatSelecter-list {
    height: calc(100% - 40px);
    padding: 8px 0;

    :deep( .el-scrollbar__wrap ) {
      margin-bottom: 0 !important;
      overflow-x: hidden;
    }
  }

  .AiWechatSelecter-container__left {
    flex: 1;

    :deep( .el-scrollbar__wrap ) {
      overflow-x: auto;
    }
  }

  .AiWechatSelecter-container__middle {
    flex-shrink: 1;
    width: 360px;
    margin-left: 20px;
    position: relative;

    .user-wrapper {
      position: relative;
      padding-bottom: 40px !important;
    }

    :deep( .el-pagination ) {
      position: absolute;
      bottom: 0px;
      left: 0;
      z-index: 11;
      width: 100%;
      display: flex;
      align-items: center;
      flex-direction: row-reverse;
      justify-content: flex-end;
      background: #fcfcfc;
      padding: 10px 10px;

      .paginationPre {
        display: flex;
        align-items: center;
      }

      .el-pagination__rightwrapper {
        display: flex;
        align-items: center;
        justify-content: flex-end;
        flex: 1;

        .el-pagination__sizes {
          margin: 0;

          input {
            height: 22px;
            line-height: 22px;
          }
        }
      }

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

        .el-checkbox__input, .el-checkbox__inner {
          width: 14px;
          height: 14px;
          min-width: 0 !important;
          line-height: 1 !important;
        }

        .el-checkbox__label {
          font-size: 12px;
          color: #222222;
          height: auto !important;
          line-height: 1 !important;
          padding-left: 3px !important;
        }
      }
    }

    .user-wrapper {
      padding: 0 10px;

      :deep( .el-checkbox ) {
        display: block;
        margin-right: 0;
      }
    }
  }

  .AiWechatSelecter-container__right {
    flex: 1;
    margin-left: 20px;

    .AiWechatSelecter-list {
      .tags-wrapper {
        padding: 0 8px;
      }

      .el-tag {
        margin: 0 8px 8px 0px;
        color: #222222;
        font-size: 14px;
      }
    }
  }

  .AiWechatSelecter-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    height: 40px;
    padding: 0 8px 0 0;
    border-bottom: 1px solid #D0D4DC;
    background: #F5F7FA;

    .AiWechatSelecter-header__left {
      display: flex;
      align-items: center;

      h2 {
        width: 60px;
        height: 100%;
        line-height: 40px;
        color: #222222;
        font-size: 14px;
        text-align: center;
        cursor: pointer;
        border-bottom: 2px solid transparent;

        &.active {
          color: $primaryColor;
          border-color: $primaryColor;
        }
      }
    }

    .el-button {
      height: 28px;
      padding: 7px 5px;
    }

    .el-input {
      width: 160px;
    }
  }

  .AiWechatSelecter-header__right {
    padding: 0 8px;

    h2 {
      color: #222222;
      font-size: 14px;
      text-align: center;
    }
  }
}
</style>
