mirror of
https://github.com/jxxghp/MoviePilot-Frontend.git
synced 2026-05-30 21:00:43 +08:00
fix 聚合搜索
This commit is contained in:
@@ -445,6 +445,8 @@ export interface Plugin {
|
||||
history?: { [key: string]: string }
|
||||
// 添加时间
|
||||
add_time?: number
|
||||
// 页面打开状态
|
||||
page_open?: boolean
|
||||
}
|
||||
|
||||
// 渲染结构
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user