click suffix icon to show options

This commit is contained in:
ailanyin
2023-06-12 15:21:30 +08:00
parent 6feec83997
commit 189ffd2255
2 changed files with 107 additions and 92 deletions

View File

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

View File

@ -224,7 +224,8 @@
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
<template v-if="tenantSettingForm.mode==='3'"> <template v-if="tenantSettingForm.mode==='3'">
<div class="data-source-item"> <div v-for="item in tenantSettingForm.datasourceList" :key="`${item.ip}-${item.port}-${item.name}`"
class="data-source-item">
<div class="left"> <div class="left">
<div class="database-type">{{ "MySQL" }}</div> <div class="database-type">{{ "MySQL" }}</div>
<div class="database-url">{{ "127.0.0.1" }} : {{ 3306 }}</div> <div class="database-url">{{ "127.0.0.1" }} : {{ 3306 }}</div>
@ -285,6 +286,7 @@ const total = ref(0);
const title = ref(""); const title = ref("");
const showTenantSetting = ref(false) /*是否显示租户设置对话框*/ const showTenantSetting = ref(false) /*是否显示租户设置对话框*/
const tenantSettingRef = ref() const tenantSettingRef = ref()
const editDatasourceIndex = ref(-1)
const data = reactive({ const data = reactive({
form: {}, form: {},
queryParams: { queryParams: {
@ -310,17 +312,17 @@ const data = reactive({
}, },
tenantSettingForm: { tenantSettingForm: {
// TODO: // TODO:
dataSource: [ // dataSource: [
{ // {
type: "MySQL", // type: "MySQL",
ip: "127.0.0.1", // ip: "127.0.0.1",
port: "", // port: "",
name: "", // name: "",
username: "", // username: "",
password: "" // password: ""
} // }
], // ],
mode: '3' // mode: '3'
} }
, ,
tenantSettingRules: { tenantSettingRules: {
@ -383,7 +385,14 @@ function reset() {
const resetSettingTenant = () => { const resetSettingTenant = () => {
form.value = { form.value = {
/*TODO:*/ /*TODO:*/
datasourceList: [] datasourceList: [{
type: null,
ip: null,
port: null,
name: null,
username: null,
password: null,
}]
} }
tenantSettingRef.value?.resetFields() tenantSettingRef.value?.resetFields()
} }
@ -430,6 +439,7 @@ function handleUpdate(row) {
* @param row * @param row
*/ */
const handleSetting = (row) => { const handleSetting = (row) => {
// editDatasourceIndex.value = 0
resetSettingTenant() resetSettingTenant()
getSetting(row.tenantId).then(resp => { getSetting(row.tenantId).then(resp => {
tenantSettingForm.value = resp.data tenantSettingForm.value = resp.data