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

@@ -36,6 +36,7 @@
"express": "^4.18.2",
"express-http-proxy": "^2.0.0",
"lodash": "^4.17.21",
"mousetrap": "^1.6.5",
"nprogress": "^0.2.0",
"qrcode.vue": "^3.4.1",
"sass": "^1.59.3",
@@ -100,4 +101,4 @@
"resolutions": {
"postcss": "8"
}
}
}

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>

View File

@@ -1023,13 +1023,6 @@
dependencies:
regenerator-runtime "^0.14.0"
"@babel/runtime@^7.23.8":
version "7.24.6"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.24.6.tgz#5b76eb89ad45e2e4a0a8db54c456251469a3358e"
integrity sha512-Ja18XcETdEl5mzzACGd+DKgaGJzPTCow7EglgwTmHdwokzDFYh/MHua6lU6DV/hjF2IaOJ4oX2nqnjG7RElKOw==
dependencies:
regenerator-runtime "^0.14.0"
"@babel/template@^7.22.15", "@babel/template@^7.23.9", "@babel/template@^7.24.0":
version "7.24.0"
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.24.0.tgz#c6a524aa93a4a05d66aaf31654258fae69d87d50"
@@ -1064,15 +1057,6 @@
"@babel/helper-validator-identifier" "^7.22.20"
to-fast-properties "^2.0.0"
"@bytebase/vue-kbar@^0.1.8":
version "0.1.8"
resolved "https://registry.yarnpkg.com/@bytebase/vue-kbar/-/vue-kbar-0.1.8.tgz#79b0cab21e9c013cb8935aa5d94be76fa9e0be3e"
integrity sha512-XfF3JadEvWzFngpu1U6C3RvseBEoWXF51Y0D3gL2R7T8Lx+OHEoPCR8jxCMXzROCCJ+eheerKqEiFl5WXrWw4w==
dependencies:
"@vueuse/core" "^7.1.2"
match-sorter "^6.3.1"
tiny-invariant "^1.2.0"
"@csstools/css-parser-algorithms@^2.6.1":
version "2.6.1"
resolved "https://registry.yarnpkg.com/@csstools/css-parser-algorithms/-/css-parser-algorithms-2.6.1.tgz#c45440d1efa2954006748a01697072dae5881bcd"
@@ -2201,14 +2185,6 @@
"@vueuse/shared" "10.9.0"
vue-demi ">=0.14.7"
"@vueuse/core@^7.1.2":
version "7.7.1"
resolved "https://registry.yarnpkg.com/@vueuse/core/-/core-7.7.1.tgz#fc284f4103de73c7fb79bc06579d8066790db511"
integrity sha512-PRRgbATMpoeUmkCEBtUeJgOwtew8s+4UsEd+Pm7MhkjL2ihCNrSqxNVtM6NFE4uP2sWnkGcZpCjPuNSxowJ1Ow==
dependencies:
"@vueuse/shared" "7.7.1"
vue-demi "*"
"@vueuse/math@^10.1.2":
version "10.9.0"
resolved "https://registry.yarnpkg.com/@vueuse/math/-/math-10.9.0.tgz#0db3cb27c893fa22c50351397c283d5b6df0f5bc"
@@ -2229,13 +2205,6 @@
dependencies:
vue-demi ">=0.14.7"
"@vueuse/shared@7.7.1":
version "7.7.1"
resolved "https://registry.yarnpkg.com/@vueuse/shared/-/shared-7.7.1.tgz#77e312de7275380efce86b0079bd7938791a076b"
integrity sha512-rN2qd22AUl7VdBxihagWyhUNHCyVk9IpvBTTfHoLH9G7rGE552X1f+zeCfehuno0zXif13jPw+icW/wn2a0rnQ==
dependencies:
vue-demi "*"
accepts@~1.3.8:
version "1.3.8"
resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e"
@@ -5104,14 +5073,6 @@ magic-string@^0.30.2, magic-string@^0.30.3, magic-string@^0.30.5, magic-string@^
dependencies:
"@jridgewell/sourcemap-codec" "^1.4.15"
match-sorter@^6.3.1:
version "6.3.4"
resolved "https://registry.yarnpkg.com/match-sorter/-/match-sorter-6.3.4.tgz#afa779d8e922c81971fbcb4781c7003ace781be7"
integrity sha512-jfZW7cWS5y/1xswZo8VBOdudUiSd9nifYRWphc9M5D/ee4w4AoXLgBEdRbgVaxbMuagBPeUC5y2Hi8DO6o9aDg==
dependencies:
"@babel/runtime" "^7.23.8"
remove-accents "0.5.0"
mathml-tag-names@^2.1.3:
version "2.1.3"
resolved "https://registry.yarnpkg.com/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz#4ddadd67308e780cf16a47685878ee27b736a0a3"
@@ -5294,6 +5255,11 @@ mlly@^1.2.0, mlly@^1.4.2, mlly@^1.5.0:
pkg-types "^1.0.3"
ufo "^1.3.2"
mousetrap@^1.6.5:
version "1.6.5"
resolved "https://registry.yarnpkg.com/mousetrap/-/mousetrap-1.6.5.tgz#8a766d8c272b08393d5f56074e0b5ec183485bf9"
integrity sha512-QNo4kEepaIBwiT8CDhP98umTetp+JNfQYBWvC1pc6/OAibuXtRcxZ58Qz8skvEHYvURne/7R8T5VoOI7rDsEUA==
ms@2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
@@ -6008,11 +5974,6 @@ regjsparser@^0.9.1:
dependencies:
jsesc "~0.5.0"
remove-accents@0.5.0:
version "0.5.0"
resolved "https://registry.yarnpkg.com/remove-accents/-/remove-accents-0.5.0.tgz#77991f37ba212afba162e375b627631315bed687"
integrity sha512-8g3/Otx1eJaVD12e31UbJj1YzdtVvzH85HV7t+9MJYk/u3XmkOUJ5Ys9wQrf9PCPK8+xn4ymzqYCiZl6QWKn+A==
request@^2.44.0:
version "2.88.2"
resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3"
@@ -6857,11 +6818,6 @@ through@^2.3.4:
resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==
tiny-invariant@^1.2.0:
version "1.3.3"
resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.3.3.tgz#46680b7a873a0d5d10005995eb90a70d74d60127"
integrity sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==
to-fast-properties@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e"
@@ -7288,11 +7244,6 @@ vite@^5.2.8:
optionalDependencies:
fsevents "~2.3.3"
vue-demi@*:
version "0.14.8"
resolved "https://registry.yarnpkg.com/vue-demi/-/vue-demi-0.14.8.tgz#00335e9317b45e4a68d3528aaf58e0cec3d5640a"
integrity sha512-Uuqnk9YE9SsWeReYqK2alDI5YzciATE0r2SkA6iMAtuXvNTMNACJLJEXNXaEy94ECuBe4Sk6RzRU80kjdbIo1Q==
vue-demi@>=0.14.7:
version "0.14.7"
resolved "https://registry.yarnpkg.com/vue-demi/-/vue-demi-0.14.7.tgz#8317536b3ef74c5b09f268f7782e70194567d8f2"