<template>
  <el-select
    popper-class="define-select"
    :style="cssVariables"
    :class="{ 'define-select-v1': attrs.multiple }"
    data-id="workerNo"
    v-model="selectedItem"
    max
    filterable
    :filter-method="remoteMethod"
    remote-show-suffix
    :remote-method="remoteMethod"
    @change="change"
    :value-key="fieldsObj.valueField"
    :loading="filteredOptions.loading"
    @vnode-mounted="() => cancalReadOnly(false, 'workerNo')"
    @visible-change="(onOff: boolean) => cancalReadOnly(onOff,'workerNo')"
  >
    <template v-if="isKeyObject">
      <el-option
        v-for="(item, index) in filteredOptions.options"
        :key="`${index}-${item[fieldsObj.valueField]}`"
        :label="item[fieldsObj.labelField]"
        :value="item"
      />
    </template>
    <template v-else>
      <el-option
        v-for="(item, index) in filteredOptions.options"
        :key="`${index}-${item[fieldsObj.valueField]}`"
        :label="item[fieldsObj.labelField]"
        :value="item[fieldsObj.valueField]"
      />
    </template>
  </el-select>
</template>

<script lang="ts" setup>
/**
 * 下拉列表搜索组件
 */
import {
  ref,
  reactive,
  unref,
  computed,
  watch,
  nextTick,
  onMounted,
  onUnmounted,
  onDeactivated,
  useAttrs,
} from "vue";
import { pinyin } from "pinyin-pro";
import { useDebounceFn } from "@vueuse/shared";
import { isArrayLength } from "@/utils/is";
import { ISelectProps } from "element-plus";
interface ListIitem {
  value: string | number | boolean;
  label: string;
  letter?: string;
}
// 兼容目前select的options类型
type ElSelectPropsType = Omit<Partial<ISelectProps>, "options">;
interface Props extends ElSelectPropsType {
  options: ListIitem[] | Recordable;
  /**
   * 是否启动加载提示
   */
  isLoading?: boolean;
  /**
   * 防抖时间
   */
  debounceTime?: number;
  /**
   * 是否启动用对象key值
   */
  isKeyObject?: boolean;
  /**
   * 默认字段
   */
  fieldsObj?: {
    valueField: string;
    labelField: string;
  };
  /**
   * 默认省略宽度
   */
  leaveOutWidth?: number;
}
// withDefaults ==> 用于辅助defineProps设置默认值
const props = withDefaults(defineProps<Props>(), {
  isLoading: false,
  debounceTime: 500,
  isKeyObject: false,
  fieldsObj: () => {
    return { valueField: "value", labelField: "label" };
  },
  leaveOutWidth: 24,
});
const emit = defineEmits(["update:modelValue", "clickItem", "change"]);
const options = computed(() => props.options);
// 属性穿透属性
const attrs = useAttrs();
// 组件内容数据
const selectedItem = ref();
const filteredOptions = reactive({
  oldOptions: [] as ListIitem[], //用于保存处理的数据源
  options: [] as ListIitem[], //搜索显示的列表数据
  loading: false, //加载
});
const defineSelectRef = ref();
const cssVariables = computed(() => {
  return {
    "--leaveout-width": props.leaveOutWidth + "px",
  };
});
// 初始化列表数据
watch(
  () => options.value,
  () => {
    if (isArrayLength(unref(options))) {
      filteredOptions.options = unref(options).map((item: ListIitem) => {
        // 中文转拼音字母
        if (!item.letter && item[props.fieldsObj.labelField]) {
          // 中文转拼音
          const letter = pinyin(item[props.fieldsObj.labelField], {
            toneType: "none",
          }).replace(/\s+/g, "");
          item.letter = letter;
        }
        return item;
      });
      filteredOptions.oldOptions = filteredOptions.options;
    } else {
      filteredOptions.options = [];
      filteredOptions.oldOptions = [];
    }
  },
  { immediate: true }
);

// 触发model事件
const change = (val) => {
  emit("update:modelValue", unref(selectedItem));
  emit("change", val);
};
let timer;
// 模糊搜索
const remoteMethod = useDebounceFn((query) => {
  //输入防抖
  clearTimeout(timer);
  if (query) {
    if (!isArrayLength(filteredOptions.oldOptions)) return;
    if (props.isLoading) filteredOptions.loading = true;
    // 匹配对应的列表数据
    const filtered = filteredOptions.oldOptions.filter(
      (item) =>
        item[props.fieldsObj.labelField].indexOf(query) !== -1 ||
        item[props.fieldsObj.valueField].toString().indexOf(query) !== -1 ||
        item.letter?.startsWith(query) ||
        item[props.fieldsObj.valueField]
          .toString()
          .indexOf(query.toUpperCase()) !== -1
    );
    // console.log(filtered,":<==过滤的数据");
    filteredOptions.options = filtered;
    props.isLoading && filtered.length > 30
      ? (timer = setTimeout(() => {
          filteredOptions.loading = false;
        }, 500))
      : (filteredOptions.loading = false);
  } else {
    filteredOptions.options = filteredOptions.oldOptions;
  }
}, props.debounceTime);

/** fix: iOS Element 当el-select 可输入时，ios端调不起键盘 */
const divDomList = ref(new Map());
watch(
  () => defineSelectRef.value,
  (val) => {
    if (/(iPhone|iPad|iPod|iOS)/i.test(navigator.userAgent) && val) {
      // 判断iPhone|iPad|iPod|iOS
      divDomList.value.set(val.$attrs["data-id"], val);
    }
  }
);
// 去除input框的readonly属性
function cancalReadOnly(onOff: boolean, keyName: string) {
  if (/(iPhone|iPad|iPod|iOS)/i.test(navigator.userAgent)) {
    // 判断iPhone|iPad|iPod|iOS
    nextTick(() => {
      const select = divDomList.value.get(keyName);
      // console.log('select', select);
      if (select) {
        const input = select.$el.querySelector(".el-input__inner");
        input.removeAttribute("readonly");
        // console.log(keyName, input);
      }
    });
  }
}
// 初始化
function initIosEvent() {
  const defineSelectDom = unref(defineSelectRef);
  if (defineSelectDom) defineSelectDom.focus();
}
onMounted(() => {
  if (/(iPhone|iPad|iPod|iOS)/i.test(navigator.userAgent)) {
    // 判断iPhone|iPad|iPod|iOS
    const defineSelectDom = unref(defineSelectRef);
    if (defineSelectDom)
      defineSelectDom.$el.addEventListener("touchstart", initIosEvent);
  }
});
onUnmounted(() => {
  divDomList.value.clear();
});
onDeactivated(() => {
  divDomList.value.clear();
});
</script>
<style lang="scss" scoped>
.define-select-v1 {
  :deep(.el-select__tags-text) {
    max-width: var(--leaveout-width) !important;
  }
  :deep(.el-select__input) {
    margin-left: 8px;
  }
}
</style>
