This commit is contained in:
ailanyin
2023-06-12 16:03:09 +08:00
parent 830e2e9054
commit 2f1a48b088
9 changed files with 803 additions and 715 deletions

View File

@ -1,9 +1,17 @@
<script setup>
import {nextTick, onMounted, onUnmounted, ref, toRefs, watch, watchEffect,} from "vue";
import {
nextTick,
onMounted,
onUnmounted,
ref,
toRefs,
watch,
watchEffect,
} from "vue";
import InfiniteLoading from "v3-infinite-loading";
import "v3-infinite-loading/lib/style.css";
import {debounce} from "lodash-es"; //required if you're not going to override default slots
import {ElInput, ElPopover, ElScrollbar} from "element-plus";
import { debounce } from "lodash-es"; //required if you're not going to override default slots
import { ElInput, ElPopover, ElScrollbar } from "element-plus";
const props = defineProps({
modelValue: {},
@ -17,7 +25,7 @@ const props = defineProps({
width: {
type: Number,
},
prefixIcon: {type: String},
prefixIcon: { type: String },
query: {
type: Object,
required: true,
@ -35,14 +43,14 @@ const props = defineProps({
},
});
const {modelValue} = toRefs(props);
const { modelValue } = toRefs(props);
const loadKey = ref(0);
const emit = defineEmits(["update:modelValue", "change", "confirm"]);
const showPopOver = ref(false);
const inputRefWhenShowPop = ref();
const inputRefWhenNotShowPop = ref()
const inputRefWhenNotShowPop = ref();
const placeholderWhenShowPop = ref("");
const placeholderWhenNotShowPop = ref("");
const optionLabelWhenShowPop = ref("");
@ -52,41 +60,41 @@ const options = ref([]);
const page = ref(0);
const initOptions = (keyword) => {
props
.remoteMethod({
[props.query.page]: page.value,
[props.query.size]: 10,
[props.query.searchKey]: keyword,
})
.then((rows) => {
options.value = rows;
});
.remoteMethod({
[props.query.page]: page.value,
[props.query.size]: 10,
[props.query.searchKey]: keyword,
})
.then((rows) => {
options.value = rows;
});
};
const loadMore = async ($state) => {
page.value++;
props
.remoteMethod({
[props.query.page]: page.value,
[props.query.size]: 10,
[props.query.searchKey]: showPopOver.value
? optionLabelWhenShowPop.value ?? null
: null,
})
.then((rows) => {
options.value.push(...rows);
if (rows.length < 10) {
$state.complete();
} else {
$state.loaded();
}
})
.catch(() => {
$state.error();
});
.remoteMethod({
[props.query.page]: page.value,
[props.query.size]: 10,
[props.query.searchKey]: showPopOver.value
? optionLabelWhenShowPop.value ?? null
: null,
})
.then((rows) => {
options.value.push(...rows);
if (rows.length < 10) {
$state.complete();
} else {
$state.loaded();
}
})
.catch(() => {
$state.error();
});
};
const handleInputClick = (event) => {
event.stopPropagation()
event.stopPropagation();
showPopOver.value = true;
placeholderWhenShowPop.value = optionLabelWhenNotShowPop.value;
nextTick(() => {
@ -136,12 +144,12 @@ watchEffect(() => {
if (showPopOver.value) return;
if (modelValue.value) {
optionLabelWhenNotShowPop.value =
options.value.find((el) => el[props.prop.value] === modelValue.value)?.[
props.prop.label
] ??
(echoLabel.value.length ? echoLabel.value : null) ??
props.defaultLabel ??
"...";
options.value.find((el) => el[props.prop.value] === modelValue.value)?.[
props.prop.label
] ??
(echoLabel.value.length ? echoLabel.value : null) ??
props.defaultLabel ??
"...";
} else {
optionLabelWhenNotShowPop.value = "";
placeholderWhenNotShowPop.value = props.placeholder;
@ -152,7 +160,6 @@ watch(modelValue, (value) => {
emit("change", value);
});
/**
* 点击空白关闭弹出选项列表
* @param event
@ -173,17 +180,25 @@ onMounted(() => {
page.value++;
initOptions();
document.body.addEventListener("click", handleBodyClick);
watch(showPopOver, (show) => {
if (show) {
inputRefWhenNotShowPop.value?.input?.parentNode?.removeEventListener('click', handleInputClick)
} else {
nextTick(() => {
inputRefWhenNotShowPop.value?.input?.parentNode?.addEventListener('click', handleInputClick)
})
}
}, {immediate: true})
watch(
showPopOver,
(show) => {
if (show) {
inputRefWhenNotShowPop.value?.input?.parentNode?.removeEventListener(
"click",
handleInputClick
);
} else {
nextTick(() => {
inputRefWhenNotShowPop.value?.input?.parentNode?.addEventListener(
"click",
handleInputClick
);
});
}
},
{ immediate: true }
);
});
onUnmounted(() => {
@ -193,48 +208,48 @@ onUnmounted(() => {
<template>
<el-popover
:popper-style="{
:popper-style="{
padding: 0,
}"
:visible="showPopOver"
:width="width ?? 240"
placement="bottom"
:visible="showPopOver"
:width="width ?? 240"
placement="bottom"
>
<template #reference>
<div :style="`width: ${width ?? 240}px`">
<!--选项显示时-->
<el-input
v-if="showPopOver"
ref="inputRefWhenShowPop"
v-model="optionLabelWhenShowPop"
:placeholder="placeholderWhenShowPop"
:prefix-icon="prefixIcon"
:size="size ?? 'default'"
class="select-inner"
suffix-icon="ArrowUp"
@input="handleInputChange"
@click.stop
v-if="showPopOver"
ref="inputRefWhenShowPop"
v-model="optionLabelWhenShowPop"
:placeholder="placeholderWhenShowPop"
:prefix-icon="prefixIcon"
:size="size ?? 'default'"
class="select-inner"
suffix-icon="ArrowUp"
@input="handleInputChange"
@click.stop
>
<template #prefix>
<slot name="prefix"/>
<slot name="prefix" />
</template>
</el-input>
<!--选项隐藏时-->
<el-input
v-else
ref="inputRefWhenNotShowPop"
v-model="optionLabelWhenNotShowPop"
:placeholder="placeholderWhenNotShowPop"
:prefix-icon="prefixIcon"
:size="size ?? 'default'"
class="select-inner"
clearable
suffix-icon="ArrowDown"
@clear="handleClearSeletion"
v-else
ref="inputRefWhenNotShowPop"
v-model="optionLabelWhenNotShowPop"
:placeholder="placeholderWhenNotShowPop"
:prefix-icon="prefixIcon"
:size="size ?? 'default'"
class="select-inner"
clearable
suffix-icon="ArrowDown"
@clear="handleClearSeletion"
>
<!-- @click.stop="handleFocus"-->
<template #prefix>
<slot name="prefix"/>
<slot name="prefix" />
</template>
</el-input>
</div>
@ -242,12 +257,12 @@ onUnmounted(() => {
<el-scrollbar class="options-wrap" height="260" @click.stop>
<ul class="options">
<li
v-for="option in options"
:key="option[prop.value]"
:class="`option-item ${
v-for="option in options"
:key="option[prop.value]"
:class="`option-item ${
option[prop.value] === modelValue ? 'selected' : null
}`"
@click.stop="selectOption(option)"
@click.stop="selectOption(option)"
>
{{ option[prop.label] }}
</li>
@ -258,7 +273,7 @@ onUnmounted(() => {
</template>
<template #complete>
<div
style="display: flex; justify-content: center; align-items: center"
style="display: flex; justify-content: center; align-items: center"
>
-
</div>