Files
Thing/src/modules/quickpanel/HistoryPicker.vue
T
2026-08-14 17:47:06 +08:00

160 lines
3.2 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<script setup lang="ts">
import { Pin } from '@lucide/vue'
defineProps<{
items: string[]
favs?: string[]
open?: boolean
}>()
const emit = defineEmits<{
pick: [value: string]
fav: [value: string]
}>()
function pick(value: string) {
emit('pick', value)
}
</script>
<template>
<!-- mousedown.prevent 阻止点击下拉项时输入框失焦使 focus 触发的历史面板保持展开 -->
<div
v-if="open && ((favs && favs.length) || items.length)"
class="qp-fa-dropdown"
@mousedown.prevent
>
<!-- 钉住/常用独立保存显示在历史之上 -->
<template v-if="favs && favs.length">
<p class="qp-fa-dropdown-label">常用</p>
<div
v-for="f in favs"
:key="'fav-' + f"
class="qp-fa-dropdown-item"
>
<button
type="button"
class="flex-1 min-w-0 text-left text-xs truncate"
:title="f"
@click="pick(f)"
>
{{ f || '(空)' }}
</button>
<button
type="button"
class="qp-fa-pin pinned"
title="取消钉住"
@click="emit('fav', f)"
>
<Pin class="size-3.5" />
</button>
</div>
</template>
<!-- 历史最多 10 排除已钉住的 -->
<p
v-if="items.filter(x => !(favs ?? []).includes(x)).length"
class="qp-fa-dropdown-label"
>
历史
</p>
<div
v-for="it in items.filter(x => !(favs ?? []).includes(x))"
:key="'his-' + it"
class="qp-fa-dropdown-item"
>
<button
type="button"
class="flex-1 min-w-0 text-left text-xs truncate"
:title="it"
@click="pick(it)"
>
{{ it || '(空)' }}
</button>
<button
v-if="favs"
type="button"
class="qp-fa-pin"
title="钉住为常用"
@click="emit('fav', it)"
>
<Pin class="size-3.5" />
</button>
</div>
</div>
</template>
<style scoped>
.qp-fa-dropdown {
position: absolute;
top: calc(100% + 2px);
left: 0;
right: 0;
z-index: 50;
max-height: 220px;
overflow-y: auto;
background: var(--popover, var(--card));
border: 1px solid var(--border);
border-radius: 6px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
padding: 4px;
}
.qp-fa-dropdown-label {
padding: 3px 8px 1px;
font-size: 10px;
color: var(--muted-foreground);
text-transform: uppercase;
letter-spacing: 0.5px;
}
.qp-fa-dropdown-item {
display: flex;
align-items: center;
gap: 4px;
padding: 3px 6px;
border-radius: 5px;
}
.qp-fa-dropdown-item:hover {
background: var(--accent);
}
.qp-fa-pin {
display: inline-flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
border: none;
background: none;
padding: 2px;
color: var(--muted-foreground);
cursor: pointer;
opacity: 0.5;
transition: opacity 0.1s, color 0.1s;
}
.qp-fa-pin:hover {
opacity: 1;
color: var(--foreground);
}
.qp-fa-pin.pinned {
color: var(--primary);
opacity: 1;
}
.qp-fa-dropdown::-webkit-scrollbar {
width: 6px;
}
.qp-fa-dropdown::-webkit-scrollbar-thumb {
background: var(--muted-foreground);
opacity: 0.3;
border-radius: 3px;
}
.qp-fa-dropdown::-webkit-scrollbar-track {
background: transparent;
}
</style>