fix 聚合搜索

This commit is contained in:
jxxghp
2024-06-02 14:58:58 +08:00
parent a2d28ad360
commit b859d00cb9
7 changed files with 193 additions and 64 deletions

View File

@@ -445,6 +445,8 @@ export interface Plugin {
history?: { [key: string]: string }
// 添加时间
add_time?: number
// 页面打开状态
page_open?: boolean
}
// 渲染结构

View File

@@ -365,11 +365,19 @@ const dropdownItems = ref([
// 监听插件状态变化
watch(
() => props.plugin?.has_update,
(newHasUpdate, oldHasUpdate) => {
(newHasUpdate, _) => {
const updateItemIndex = dropdownItems.value.findIndex(item => item.value === 3)
if (updateItemIndex !== -1) dropdownItems.value[updateItemIndex].show = newHasUpdate
},
)
// 监听插件窗口状态变化
watch(
() => props.plugin?.page_open,
(newOpenState, _) => {
if (newOpenState) openPluginDetail()
},
)
</script>
<template>

View File

@@ -1,10 +1,16 @@
<script lang="ts" setup>
import * as Mousetrap from 'mousetrap'
import SearchBarView from '@/views/system/SearchBarView.vue'
const searchDialog = ref(false)
// 注册快捷键
Mousetrap.bind(['command+k', 'ctrl+k'], openSearchDialog)
// 打开搜索弹窗
function openSearchDialog() {
searchDialog.value = true
return false
}
</script>
@@ -20,7 +26,7 @@ function openSearchDialog() {
</span>
</div>
<!-- 搜索弹窗 -->
<SearchBarView v-model="searchDialog" @close="searchDialog = false" />
<SearchBarView v-model="searchDialog" v-if="searchDialog" @close="searchDialog = false" />
</template>
<style type="scss" scoped>
.meta-key {

View File

@@ -22,6 +22,9 @@ let deferApp = (_: number) => true
// 当前标签
const activeTab = ref(route.query.tab)
// 插件ID参数
const pluginId = ref(route.query.id)
// 标签页
const tabs = [
{
@@ -330,6 +333,13 @@ function jumpTab(tab: string) {
onBeforeMount(async () => {
await refreshData()
getPluginStatistics()
if (activeTab.value != 'market' && pluginId.value) {
// 找到这个插件
const plugin = dataList.value.find(item => item.id === pluginId.value)
if (plugin) {
plugin.page_open = true
}
}
})
</script>

View File

@@ -1,4 +1,7 @@
<script setup lang="ts">
import api from '@/api'
import type { Plugin } from '@/api/types'
// 路由
const router = useRouter()
@@ -14,8 +17,69 @@ const searchWordInput = ref<HTMLElement | null>(null)
// 搜索提示词列表
const searchHintList = ref<string[]>([])
// Search
function search(searchType: string) {
// 所有菜单功能
const menuItems = ref([])
// 常用菜单功能
const commonMenuItems = ref([
{
title: '搜索设置',
icon: 'mdi-magnify',
to: 'setting?tab=search',
},
{
title: '订阅设置',
icon: 'mdi-rss',
to: 'setting?tab=subscribe',
},
{
title: '服务',
icon: 'mdi-list-box',
to: 'setting?tab=service',
},
{
title: '词表',
icon: 'mdi-file-word-box',
to: 'setting?tab=words',
},
{
title: '历史记录',
icon: 'mdi-history',
to: 'history',
},
])
// 所有插件(已安装)
const pluginItems = ref<Plugin[]>([])
// 匹配的菜单列表
const matchedMenuItems = ref([])
// 获取插件列表数据
async function fetchInstalledPlugins() {
try {
pluginItems.value = await api.get('plugin/', {
params: {
state: 'installed',
},
})
} catch (error) {
console.error(error)
}
}
// 区配的插件列表
const matchedPluginItems = computed(() => {
if (!searchWord.value) return []
const lowerWord = searchWord.value?.toLowerCase()
return pluginItems.value.filter((item: Plugin) => {
if (!item.plugin_name && !item.plugin_desc) return false
return item.plugin_name?.toLowerCase().includes(lowerWord) || item.plugin_desc?.toLowerCase().includes(lowerWord)
})
})
// 跳转媒体搜索页面
function searchMedia(searchType: string) {
// 搜索类型 media/person
if (!searchWord.value) return
if (!searchHintList.value.includes(searchWord.value)) searchHintList.value.push(searchWord.value)
@@ -29,10 +93,29 @@ function search(searchType: string) {
emit('close')
}
// 跳转插件页面
function showPlugin(pluginId: string) {
router.push({
path: `/plugins/`,
query: {
tab: 'installed',
id: pluginId,
},
})
emit('close')
}
// 跳转菜单页面
function goPage(to: string) {
router.push(to)
emit('close')
}
onMounted(() => {
setTimeout(() => {
searchWordInput.value?.focus()
}, 500)
fetchInstalledPlugins()
})
</script>
<template>
@@ -47,6 +130,7 @@ onMounted(() => {
class="text-high-emphasis"
placeholder="搜索 ..."
:items="searchHintList"
@keydown.enter="searchMedia('media')"
>
<template #prepend>
<VIcon icon="ri-search-line" style="opacity: 1" />
@@ -66,7 +150,7 @@ onMounted(() => {
density="compact"
link
v-bind="hover.props"
@click="search('media')"
@click="searchMedia('media')"
>
<VListItemTitle>
搜索 <span class="font-bold">{{ searchWord }} </span> 相关的电影电视剧
@@ -80,11 +164,11 @@ onMounted(() => {
<VHover>
<template #default="hover">
<VListItem
prepend-icon="mdi-people"
prepend-icon="mdi-account-search"
density="compact"
link
v-bind="hover.props"
@click="search('person')"
@click="searchMedia('person')"
>
<VListItemTitle>
搜索 <span class="font-bold">{{ searchWord }}</span> 相关的人物
@@ -95,11 +179,78 @@ onMounted(() => {
</VListItem>
</template>
</VHover>
<VListSubheader v-if="searchWord"> 功能 </VListSubheader>
<VListSubheader v-if="searchWord"> 插件 </VListSubheader>
<VListSubheader v-if="matchedMenuItems.length > 0"> 功能 </VListSubheader>
<VListSubheader v-if="matchedPluginItems.length > 0"> 插件 </VListSubheader>
<VHover v-if="matchedPluginItems.length > 0" v-for="plugin in matchedPluginItems" :key="plugin.id">
<template #default="hover">
<VListItem
prepend-icon="mdi-puzzle"
density="compact"
link
v-bind="hover.props"
@click="showPlugin(plugin.id ?? '')"
>
<VListItemTitle> {{ plugin.plugin_name }} </VListItemTitle>
<VListItemSubtitle> {{ plugin.plugin_desc }} </VListItemSubtitle>
<template #append>
<VIcon v-if="hover.isHovering" icon="ri-corner-down-left-line" />
</template>
</VListItem>
</template>
</VHover>
</VList>
<div v-else>
<!-- 默认 -->
<VCardText>
<VRow>
<VCol cols="12" md="6">
<p class="custom-letter-spacing text-sm text-disabled text-uppercase py-2 px-4 mb-0">常用功能</p>
<VList lines="one">
<VHover v-for="(menu, index) in commonMenuItems" :key="index">
<template #default="hover">
<VListItem
:prepend-icon="menu.icon"
density="compact"
link
v-bind="hover.props"
@click="goPage(menu.to)"
>
<VListItemTitle>
{{ menu.title }}
</VListItemTitle>
<template #append>
<VIcon v-if="hover.isHovering" icon="ri-corner-down-left-line" />
</template>
</VListItem>
</template>
</VHover>
</VList>
</VCol>
<VCol cols="12" md="6">
<p class="custom-letter-spacing text-sm text-disabled text-uppercase py-2 px-4 mb-0">常用插件</p>
<VList lines="one">
<VHover v-for="plugin in pluginItems.slice(0, 5)" :key="plugin.id">
<template #default="hover">
<VListItem
prepend-icon="mdi-package-variant"
density="compact"
link
v-bind="hover.props"
@click="showPlugin(plugin.id ?? '')"
>
<VListItemTitle> {{ plugin.plugin_name }} </VListItemTitle>
<template #append>
<VIcon v-if="hover.isHovering" icon="ri-corner-down-left-line" />
</template>
</VListItem>
</template>
</VHover>
</VList>
</VCol>
<VCol cols="12" md="6"> </VCol>
<VCol cols="12" md="6"> </VCol>
</VRow>
</VCardText>
</div>
</div>
</VCard>