<template>
  <el-select v-model="selectPersonnelValue" filterable @visible-change="toggleSelectPrefix" remote
    :remote-method="userListRemotemethod" :multiple="multiple" @focus="userFocus" :size="size" collapse-tags
    @change="updateValue" clearable :ref="`select${timeRef}`" :style="`width: ${width}`" class="custom-select">
    <template #prefix>
      <div style="height: 100%;display: flex;align-items: center;">
        <!-- 单选 -->
        <template v-if="!multiple">
          <div v-if="selectPrefixFlg" class="selectSingleChoice" :style="sizeStyle[size]">
            <template v-if="getSelectedLabel == '请选择'">
              <span class="pleaseChoose">请选择</span>
            </template>
            <template v-else>
              <!-- {{ getSelectedLabel }} -->
              <TranslationOpenDataText type='userName' :openid="getSelectedLabel"></TranslationOpenDataText>
            </template>
          </div>
        </template>
        <!-- 多选 -->
        <template v-if="multiple">
          <div class="selectMultiple" :style="sizeStyle[size]">
            <template v-if="value.length == 0">
              <span class="textSpan pleaseChoose">请选择</span>
            </template>
            <template v-else>
              <el-tag closable type="info" :size="size" class="narrow" style="margin: 0;" @close="userTagClose">
                {{
                getSelectedLabel
              }}
              <TranslationOpenDataText type='userName' :openid="getSelectedLabel"></TranslationOpenDataText>
            </el-tag>
              <el-tag type="info" :size="size" v-if="value.length > 1" class="narrow" style="margin: 0;">+ {{
                value.length - 1 }}</el-tag>
            </template>
          </div>
        </template>
        <!-- 占位符 -->
        <span></span>
      </div>
    </template>

    <!-- 主体显示内容 -->
    <div :ref="`mySelectUser${timeRef}`" class="select-user-class">
      <el-option v-for="item in options" :key="item.id" :label="item.name" :value="item.id">
        <span class="floatLeft">
          <TranslationOpenDataText type='userName' :openid='item.name'></TranslationOpenDataText>
        </span>
        <span class="jonumberUser">{{ item.jobNumber }}</span>
      </el-option>
      <!-- 下滚加载提示 -->
      <div class="itemsLoading" v-if="loadingInProgress">
        加载中...
      </div>
    </div>
  </el-select>
</template>

<script>
export default {
  name: 'HelloWorld',
  props: {
    value: { // 双向数据绑定
      type: [String, Number, Array],
      required: true
    },
    size: { // 尺寸
      type: String,
      default: 'small'
    },
    multiple: { // 是否多选
      type: Boolean,
      default: () => false
    },
    width: { // 宽度
      type: String,
      default: '200px'
    }
  },
  data() {
    return {
      options: [],
      selectPersonnelValue: this.value,
      selectPrefixFlg: true,
      timeRef: new Date().getTime(),
      updateTrigger: 0, // 用来强制触发计算属性
      sizeStyle: {
        mini: `height: 24px;`,
        small: `height: 28px`,
        medium: `height: 32px`,
      },
      keyword: '',
      loadingInProgress: false,
      userListloading: false,
      userPageIndex: 1,
      userPageSize: 50,
      userTotal: 0,
      cursor: 1,
    }
  },
  watch: {
    selectPersonnelValue: {
      handler() {
        this.$nextTick(() => {
          if (this.multiple) {
            this.getSelectedLabel
          }
        });
      },
      deep: true,
      immediate: true
    }
  },
  computed: {
    getSelectedLabel() {
      this.updateTrigger;

      if (!this.multiple) {
        const selectedOption = this.options.find(item => item.id === this.selectPersonnelValue)
        return selectedOption ? selectedOption.name : '请选择'
      } else if (this.multiple) {
        if (this.selectPersonnelValue.length === 0) {
          return '请选择'
        }
        const selectVal = this.selectPersonnelValue[0]
        const selectedOption = this.options.find(item => item.id === selectVal)
        return selectedOption ? selectedOption.name : '请选择'
      }

      return '请选择'
    }
  },
  methods: {
    userListRemotemethod: _.debounce(function (val) {
      this.newProjectListPage = 1
      this.getUserList(val)
    }, 500),
    // 随机取名字4-6个字
    getRandomName() {
      const firstNames = ['张', '李', '王', '刘', '陈', '杨', '黄', '赵'];
      const lastNames = ['伟', '芳', '娜', '敏', '军', '洋', '静', '磊'];

      const nameLength = Math.floor(Math.random() * 3) + 4; // 生成4到6之间的随机数
      let name = '';

      for (let i = 0; i < nameLength; i++) {
        if (i % 2 === 0) {
          name += firstNames[Math.floor(Math.random() * firstNames.length)];
        } else {
          name += lastNames[Math.floor(Math.random() * lastNames.length)];
        }
      }

      return name;
    },
    uniqueById(arr) {
      return arr.reduce((accumulator, current) => {
        if (!accumulator.some(item => item.id === current.id)) {
          accumulator.push(current);
        }
        return accumulator;
      }, []);
    },
    userTagClose() {
      this.selectPersonnelValue = this.selectPersonnelValue.splice(0, 1)
    },
    userFocus() {
      console.log('失去焦点了', this.selectPrefixFlg)
      if (this.selectPrefixFlg) {
        this.userPageIndex = 1
        this.getUserList('', false)
      }
    },
    addUserList() {
      this.loadingInProgress = true
      this.postData(`/user/getSimpleActiveUserListPage`, {
        pageIndex: this.userPageIndex,
        pageSize: this.userPageSize,
        departmentId: '',
        keyword: this.keyword,
        cursor: '',
        userIds: this.multiple ? this.selectPersonnelValue.join(',') : this.selectPersonnelValue
      }).then(res => {
        const { data = [], total = 0 } = res.data
        this.userTotal = total
        // this.options = [...new Set([...this.options, ...data].map(JSON.stringify))].map(JSON.parse);
        // this.options = this.uniqueById([...this.options, ...newData]) 
        const newData = data.map((item) => {
          return {
            ...item,
            // name: this.getRandomName()
          }
        })
        this.options = this.uniqueById([...this.options, ...newData]) 
        console.log(this.options.length, '<==== this.options')
      }).finally(() => {
        setTimeout(() => {
          this.loadingInProgress = false
        }, 500)
      })
    },
    getUserList(keyword = '', flag = true) {
      this.keyword = keyword
      this.userListloading = flag
      this.postData(`/user/getSimpleActiveUserListPage`, {
        pageIndex: this.userPageIndex,
        pageSize: this.userPageSize,
        departmentId: '',
        keyword,
        cursor: '',
        userIds: this.multiple ? this.selectPersonnelValue.join(',') : this.selectPersonnelValue
      }).then(res => {
        const { data = [], total = 0 } = res.data
        this.userTotal = total
        // this.options = [...new Set(data.map(JSON.stringify))].map(JSON.parse);
        // this.options = this.uniqueById(data);
        const dataVal = data.map((item) => {
          return {
            ...item,
            // name: this.getRandomName()
          }
        })
        this.options = this.uniqueById(dataVal);
      }).finally(() => {
        this.userListloading = false
      })
    },
    async postData(urls, param) { // 单独封装 post 请求 方法
      return new Promise((resolve, reject) => {
        this.http.post(urls, { ...param },
          res => {
            if (res.code == 'ok') {
              resolve(res)
            } else {
              this.$message({
                message: res.msg,
                type: 'error'
              })
              reject(res)
            }
            resolve(res)
          },
          error => {
            this.$message({
              message: error,
              type: "error"
            });
            reject(error)
          }
        )
      });
    },
    handleScroll(event) {
      const container = event.target;
      const { scrollTop, scrollHeight, clientHeight } = container;

      const totalPage = Math.ceil(this.userTotal / this.userPageSize);
      if (scrollTop + clientHeight >= scrollHeight - 20 && this.userPageIndex < totalPage && !this.loadingInProgress) {
        this.loadMoreData()
      }
    },
    loadMoreData() {
      this.userPageIndex += 1;
      this.addUserList();
    },
    toggleSelectPrefix(value) {
      this.selectPrefixFlg = !value
      console.log(this.selectPrefixFlg, '<===== selectPrefixFlg')
      if (value) {
        this.$nextTick(() => {
          this.addScrollListener();
        });
      } else {
        this.removeScrollListener();
      }
    },
    addScrollListener() {
      const container = this.$refs[`mySelectUser${this.timeRef}`];
      const scrollbar = container.closest('.el-scrollbar__wrap');
      if (scrollbar) {
        this.loadingInProgressHight = scrollbar.clientHeight - 40
        this.removeScrollListener();
        const debouncedHandleScroll = _.debounce(this.handleScroll, 200);
        scrollbar.addEventListener('scroll', debouncedHandleScroll);
        this.scrollListener = debouncedHandleScroll;
      }
    },

    removeScrollListener() {
      const container = this.$refs[`mySelectUser${this.timeRef}`];
      const scrollbar = container.closest('.el-scrollbar__wrap');
      if (scrollbar && this.scrollListener) {
        scrollbar.removeEventListener('scroll', this.scrollListener);
        this.scrollListener = null;
      }
    },
    updateValue(value) { // 更新数据
      if (this.multiple) {
        this.updateTrigger += 1 // 强行触发计算属性
      }

      this.$emit('input', value);
      this.$emit('change', value, this.getSelectedLabel);
    },
  },
  mounted() {
    this.$nextTick(() => {
      this.getUserList()
    });
  },
  beforeDestroy() {
    this.removeScrollListener();
  }
}
</script>

<style>
.custom-select input::placeholder {
  color: transparent !important;
}
</style>

<style scoped lang="scss">
.select-base {
  position: absolute;
  width: auto;
  display: flex;
  align-items: center;
  background: #fff;
  box-sizing: border-box;
  color: #606266;
  white-space: nowrap;
}

.selectSingleChoice {
  @extend .select-base;
  left: 26px;
  transform-origin: left;
}

.selectMultiple {
  @extend .select-base;
  left: 0;
  z-index: 10;
  min-width: 40px;
}

.select-user-class {
  position: relative;

  .itemsLoading {
    position: absolute;
    left: 0;
    bottom: -2px;
    width: 100%;
    text-align: center;
    padding: 10px;
    background: #fff;
    box-shadow: 0px -4px 20px 0px #999;
    font-size: 12px;
    color: #999;
    z-index: 99;
    box-sizing: border-box;
  }
}

.narrow {
  transform: scale(0.9);
  transform-origin: left;
}

.selectMultiple .textSpan {
  position: relative;
  left: 26px;
}

.pleaseChoose {
  color: #C0C4CC;
}

.floatLeft {
  float: left;
}

.jonumberUser {
  float: right;
  color: #8492a6;
}
</style>