{"version":3,"file":"batch2.mjs","sources":["../../../../../../packages/components/batch/src/batch.vue"],"sourcesContent":["<template>\n  <div\n    :class=\"[ns.b(), ns.is('disabled', disabled), ns.m(_size)]\"\n    :style=\"{ 'max-width': width + 'px' }\"\n  >\n    <el-input\n      ref=\"inputRef\"\n      v-model=\"searchValue\"\n      clearable\n      v-bind=\"userAttrsCopy\"\n      :disabled=\"disabled\"\n      :class=\"ns.e('input')\"\n      :style=\"{ width: width + 'px' }\"\n      @click=\"handleFocus\"\n    >\n      <template #prepend>\n        <template v-if=\"$slots.prepend\">\n          <div :class=\"ns.e('prepend')\">\n            <slot name=\"prepend\" />\n          </div>\n        </template>\n        <el-select\n          ref=\"selectRef\"\n          v-model=\"optionValue\"\n          style=\"height: 100%\"\n          :class=\"[ns.e('select'), ns.is('disabled', disabled)]\"\n          :disabled=\"disabled\"\n          @change=\"changeOption\"\n        >\n          <template #prefix>\n            <span :class=\"ns.is('empty', options.length <= 0)\">\n              {{\n                options.find((s) => s.value === optionValue)?.label ?? emptyText\n              }}\n            </span>\n          </template>\n          <el-option\n            v-for=\"item in options\"\n            :key=\"item.value\"\n            :label=\"item[labelValue.label]\"\n            :value=\"item[labelValue.value]\"\n          />\n        </el-select>\n      </template>\n      <template #suffix>\n        <el-icon :class=\"ns.e('batch-icon')\" @click.stop=\"handleSearch\"\n          ><Search\n        /></el-icon>\n        <el-popover\n          effect=\"light\"\n          placement=\"bottom-end\"\n          :popper-class=\"ns.e('batch-popper')\"\n          :class=\"ns.e('batch-tooltip')\"\n          :visible=\"tooltipVisible\"\n          :offset=\"20\"\n          :width=\"Number(width) - selectWidth\"\n        >\n          <el-input\n            ref=\"textareaRef\"\n            v-model=\"inputValue\"\n            resize=\"none\"\n            :autosize=\"{ minRows: minRows, maxRows: 12 }\"\n            :class=\"ns.e('textarea')\"\n            :placeholder=\"'精确搜索，一行一项，最多支持' + rows + '行'\"\n            type=\"textarea\"\n            @keydown.enter=\"handleEnterKey\"\n            @input=\"handleTextareaInput\"\n          />\n          <div :class=\"ns.e('controls')\">\n            <el-button size=\"small\" plain @click.stop=\"handleClear\"\n              >清空</el-button\n            >\n            <div>\n              <el-button size=\"small\" plain @click.stop=\"handleClose\"\n                >关闭</el-button\n              >\n              <el-button\n                size=\"small\"\n                :class=\"ns.e('search-button')\"\n                plain\n                @click.stop=\"handleMultipleSearch\"\n                >搜索</el-button\n              >\n            </div>\n          </div>\n          <template #reference>\n            <el-icon :class=\"ns.e('tooltip-icon')\" @click.stop=\"showTooltip\"\n              ><Operation\n            /></el-icon>\n          </template>\n        </el-popover>\n      </template>\n    </el-input>\n    <div v-show=\"tagShow\" :class=\"ns.e('tag')\">\n      <el-popover\n        :width=\"Number(width) - selectWidth\"\n        :popper-class=\"ns.e('batch-popper')\"\n        effect=\"light\"\n        placement=\"bottom-start\"\n      >\n        <div\n          :class=\"ns.e('tag-content')\"\n          :style=\"{ 'min-width': Number(width) - selectWidth + 'px' }\"\n        >\n          <el-scrollbar>\n            <p v-for=\"item in multipleSearchValue\" :key=\"item\">{{ item }}</p>\n          </el-scrollbar>\n        </div>\n        <template #reference>\n          <el-tag closable @close=\"handleCloseTag\"\n            >{{ selectedLabel }}：{{\n              multipleSearchValue.slice(0, 3).join(', ')\n            }}\n            等{{ multipleSearchValue.length }}项\n          </el-tag>\n        </template>\n      </el-popover>\n    </div>\n  </div>\n</template>\n\n<script lang=\"ts\" setup>\nimport { nextTick, onMounted, reactive, ref, toRef, useAttrs } from 'vue'\nimport { Operation, Search } from '@element-plus/icons-vue'\nimport { ElMessage } from '@code-monkey-ui/components/message'\nimport ElInput from '@code-monkey-ui/components/input'\nimport { ElScrollbar } from '@code-monkey-ui/components/scrollbar'\nimport { ElOption, ElSelect } from '@code-monkey-ui/components/select'\nimport ElIcon from '@code-monkey-ui/components/icon'\nimport ElPopover from '@code-monkey-ui/components/popover'\nimport { ElButton } from '@code-monkey-ui/components/button'\nimport { ElTag } from '@code-monkey-ui/components/tag'\nimport { useNamespace } from '@code-monkey-ui/hooks'\nimport { batchEmits, batchProps } from './batch'\nimport { useBatch } from './use-batch'\nconst props = defineProps(batchProps)\n\nconst useSize = reactive({\n  size: toRef(props, 'size'),\n})\nconst ns = useNamespace('batch')\nconst emit = defineEmits(batchEmits)\nconst { disabled, _size } = useBatch(props, useSize.size)\nconst userAttrs = useAttrs()\nconst textareaRef = ref<any>()\nconst userAttrsCopy = reactive<any>({ ...userAttrs })\n// 不被需要的props\ndelete userAttrsCopy.size\ndelete userAttrsCopy.prefixIcon\ndelete userAttrsCopy.suffixIcon\ndelete userAttrsCopy.rows\ndelete userAttrsCopy.readonly\ndelete userAttrsCopy.tabindex\ndelete userAttrsCopy.modelValue\ndelete userAttrsCopy.resize\ndelete userAttrsCopy.autosize\ndelete userAttrsCopy.type\n\ndefineOptions({\n  name: 'ElBatch',\n})\n\nconst inputRef = ref<any>(null)\nconst selectRef = ref<any>(null)\nconst tooltipVisible = ref<boolean>(false)\nconst optionValue = ref(props.options[0]?.value)\nconst selectWidth = ref<number>(0)\nconst searchValue = ref<string>('')\nconst inputValue = ref('')\nconst selectedLabel = ref<string>('')\nconst multipleSearchValue = ref<any[]>([])\nconst tagShow = ref<boolean>(false)\n\n/**\n * 处理批量搜索框回车键事件\n * @param event 事件\n */\nconst handleEnterKey = (event: Event) => {\n  const lines = inputValue.value.split('\\n')\n  const lastLine = lines[lines.length - 1]\n  nextTick(() => {\n    const textarea = textareaRef.value?.textarea\n    textarea.selectionStart = textarea.selectionEnd = textarea.value.length\n  })\n  if (!lastLine.trim() || lines.length >= props.rows) {\n    event.preventDefault()\n  }\n}\n\n/**\n * 处理批量搜索框输入事件\n * @param value 输入的值\n */\nconst handleTextareaInput = (value: string) => {\n  const inputElement = textareaRef.value.$el.querySelector('textarea')\n  inputElement.addEventListener('paste', preventPaste)\n  const lines = value.split('\\n')\n  const nonEmptyLines = lines.filter((line) => line.trim() !== '')\n  if (nonEmptyLines.length >= props.rows) {\n    inputValue.value = lines.slice(0, props.rows).join('\\n')\n  } else {\n    inputElement.removeEventListener('paste', preventPaste)\n  }\n}\n\n/**\n * 阻止粘贴事件\n * @param event 事件\n */\nconst preventPaste = (event: ClipboardEvent) => {\n  event.preventDefault()\n}\n\n/**\n * 处理输入框聚焦事件\n */\nconst handleFocus = () => {\n  handleClose()\n  nextTick(() => {\n    inputRef.value.blur()\n    inputRef.value.focus()\n  })\n}\n\n/**\n * 处理选择框改变事件\n * @param value 选择的值\n */\nconst changeOption = (value: any) => {\n  handleClose()\n  emit('optionsChange', value)\n}\n\n/**\n * 处理搜索事件\n */\nconst handleSearch = () => {\n  if (disabled.value) return\n  emit('search', {\n    searchValue: searchValue.value,\n    optionValue: optionValue.value,\n  })\n}\n\n/**\n * 处理清空事件\n */\nconst handleClear = () => {\n  handleBlur()\n  inputValue.value = ''\n  emit('clearMultipleValue')\n}\n\n/**\n * 处理关闭事件\n */\nconst handleClose = () => {\n  tooltipVisible.value = false\n}\n\n/**\n * 处理输入框失去焦点事件\n */\nconst handleBlur = () => {\n  const focusElement = inputRef.value.$el.querySelector('.is-focus')\n  const activeElement = document.activeElement as HTMLInputElement\n  activeElement?.blur()\n  if (focusElement) {\n    focusElement.classList.remove('is-focus')\n  }\n}\n\n/**\n * 处理多选搜索事件\n */\nconst handleMultipleSearch = () => {\n  handleBlur()\n  handleClose()\n  handleMultipleSearchData()\n  nextTick(() => {\n    selectedLabel.value = selectRef.value.selectedLabel\n  })\n  emit('multipleSearch', {\n    multipleSearchValue: multipleSearchValue.value,\n    optionsValue: optionValue.value,\n  })\n}\n\n// 处理多选搜索数据\nconst handleMultipleSearchData = () => {\n  const data = inputValue.value\n    .split('\\n')\n    .map((item) => item.trim())\n    .filter(Boolean)\n  multipleSearchValue.value = [...new Set(data)]\n  if (data.length > multipleSearchValue.value.length) {\n    ElMessage.warning('有重复数据,已自动去重')\n  }\n  inputValue.value = multipleSearchValue.value.join('\\n')\n  if (props.needTag) {\n    tagShow.value = true\n  }\n  return multipleSearchValue.value\n}\n\n/**\n * 处理显示提示框事件\n */\nconst showTooltip = () => {\n  if (disabled.value) return\n  handleBlur()\n  selectWidth.value = selectRef.value?.$el.offsetWidth\n  tooltipVisible.value = !tooltipVisible.value\n}\n\n/**\n * 处理关闭标签事件\n */\nconst handleCloseTag = () => {\n  tagShow.value = false\n}\n\nconst clear = () => {\n  multipleSearchValue.value = []\n  optionValue.value = props.options[0]?.value\n  searchValue.value = ''\n}\n\nonMounted(() => {\n  changeOption(optionValue.value)\n  if (disabled.value) return\n  selectWidth.value = selectRef.value?.$el.offsetWidth\n})\n\ndefineExpose({\n  size: props.size,\n  getFullData: () => {\n    return {\n      multipleSearchValue: handleMultipleSearchData(),\n      optionsValue: optionValue.value,\n      searchValue: searchValue.value,\n    }\n  },\n  clear,\n})\n</script>\n"],"names":[],"mappings":"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"}