123 lines
2.9 KiB
Vue
123 lines
2.9 KiB
Vue
<template>
|
|
<div class="dropdown-menu">
|
|
<div class="dropdown-menu-list" v-if="items?.length">
|
|
<div
|
|
class="dropdown-item"
|
|
:class="{ 'is-selected': index === selectedIndex }"
|
|
v-for="(item, index) in varList"
|
|
:key="index"
|
|
@click="selectItem(index)"
|
|
>
|
|
<div class="label"> {{ item.text }}</div>
|
|
<span class="value">{{item.value}}</span>
|
|
</div>
|
|
</div>
|
|
<div class="not-exists" v-else>
|
|
<span>数据指标不存在</span>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import {getProductValue} from "@/service/use-result-vars.js";
|
|
import {watch, ref} from "vue";
|
|
|
|
const productList = getProductValue();
|
|
const varList = ref<ResultVarItem[] >([])
|
|
|
|
const props = defineProps({
|
|
items: {
|
|
type: Array,
|
|
},
|
|
query:{
|
|
type: String,
|
|
},
|
|
command: {
|
|
type: Function,
|
|
required: true,
|
|
},
|
|
});
|
|
const selectedIndex = ref(0)
|
|
|
|
watch(()=>props.query, () => {
|
|
selectedIndex.value = 0;
|
|
if(props.query){
|
|
const q = String(props.query)
|
|
varList.value = productList.value.filter(item => (
|
|
item.value.includes(q) || item.label.includes(q) || (item.text && item.text.includes(q))
|
|
));//.filter((_,index)=> index < 10)
|
|
}else{
|
|
varList.value = productList.value.filter((_,index)=> index < 10)
|
|
}
|
|
});
|
|
|
|
const upHandler = () => {
|
|
selectedIndex.value = ((selectedIndex.value + varList.value.length) - 1) % varList.value.length
|
|
}
|
|
const downHandler = () => {
|
|
selectedIndex.value = (selectedIndex.value + 1) % varList.value.length
|
|
}
|
|
const enterHandler = () => {
|
|
selectItem(selectedIndex.value)
|
|
}
|
|
const selectItem = (index:number) => {
|
|
const item = varList.value[index]
|
|
if (item) {
|
|
props.command({id: item.value, label: item.text || item.label})
|
|
}
|
|
// selectedIndex.value = index
|
|
}
|
|
const onKeyDown = ({event}: { event: { key: string } }) => {
|
|
if (event.key === 'ArrowUp') {
|
|
upHandler()
|
|
return true
|
|
}
|
|
|
|
if (event.key === 'ArrowDown') {
|
|
downHandler()
|
|
return true
|
|
}
|
|
|
|
if (event.key === 'Enter') {
|
|
enterHandler()
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
defineExpose({onKeyDown})
|
|
|
|
</script>
|
|
|
|
<style lang="scss">
|
|
/* Dropdown menu */
|
|
.dropdown-menu-list{
|
|
}
|
|
.dropdown-menu {
|
|
@apply bg-white relative overflow-auto flex flex-col shadow rounded border border-gray-200;
|
|
max-height: calc(100vh - 300px);
|
|
}
|
|
|
|
.dropdown-item {
|
|
@apply w-full p-2 gap-2 bg-transparent flex items-center cursor-pointer justify-between;
|
|
text-align: left;
|
|
|
|
&:hover,
|
|
&:hover.is-selected {
|
|
@apply bg-gray-200;
|
|
}
|
|
|
|
&.is-selected {
|
|
@apply bg-gray-100;
|
|
}
|
|
.label{
|
|
@apply text-gray-800;
|
|
}
|
|
.value{
|
|
@apply text-gray-300 text-sm;
|
|
}
|
|
}
|
|
|
|
.not-exists {
|
|
@apply p-2;
|
|
}
|
|
</style> |