Feature(custom): add strict search for plugin search, avoid unrelated results

This commit is contained in:
Kuingsmile
2025-12-31 17:08:51 +08:00
parent 6f44cf17b8
commit 17355168f6
5 changed files with 88 additions and 1 deletions

View File

@@ -627,6 +627,8 @@
"setResult": "Set Result", "setResult": "Set Result",
"setSuccess": "Set Success", "setSuccess": "Set Success",
"settings": "Settings", "settings": "Settings",
"strictSearch": "Strict Search",
"strictSearchDescription": "Only show plugins that contain the search term in name",
"title": "Plugins", "title": "Plugins",
"tryDifferentSearch": "Try Different Search Keywords", "tryDifferentSearch": "Try Different Search Keywords",
"updateAll": "Update All Plugins", "updateAll": "Update All Plugins",

View File

@@ -627,6 +627,8 @@
"setResult": "设置结果", "setResult": "设置结果",
"setSuccess": "设置成功", "setSuccess": "设置成功",
"settings": "设置", "settings": "设置",
"strictSearch": "严格搜索",
"strictSearchDescription": "仅显示包名包含搜索词的插件",
"title": "插件", "title": "插件",
"tryDifferentSearch": "尝试不同的搜索关键词", "tryDifferentSearch": "尝试不同的搜索关键词",
"updateAll": "更新全部插件", "updateAll": "更新全部插件",

View File

@@ -627,6 +627,8 @@
"setResult": "設定結果", "setResult": "設定結果",
"setSuccess": "設定成功", "setSuccess": "設定成功",
"settings": "設定", "settings": "設定",
"strictSearch": "嚴格搜索",
"strictSearchDescription": "僅顯示包名包含搜索詞的外掛",
"title": "插件", "title": "插件",
"tryDifferentSearch": "嘗試不同的搜尋關鍵詞", "tryDifferentSearch": "嘗試不同的搜尋關鍵詞",
"updateAll": "更新全部插件", "updateAll": "更新全部插件",

View File

@@ -48,6 +48,13 @@
<XIcon :size="16" /> <XIcon :size="16" />
</button> </button>
</div> </div>
<div class="search-options">
<label class="strict-search-checkbox">
<input v-model="strictSearch" type="checkbox" class="checkbox-input" />
<span class="checkbox-label">{{ t('pages.plugin.strictSearch') }}</span>
<span class="checkbox-description">{{ t('pages.plugin.strictSearchDescription') }}</span>
</label>
</div>
</div> </div>
</div> </div>
@@ -199,6 +206,7 @@
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { useStorage } from '@vueuse/core'
import { debounce, DebouncedFunc } from 'lodash-es' import { debounce, DebouncedFunc } from 'lodash-es'
import { import {
AlertCircleIcon, AlertCircleIcon,
@@ -242,6 +250,7 @@ const loading = ref(true)
const needReload = ref(false) const needReload = ref(false)
const latestVersionMap = reactive<Record<string, string>>({}) const latestVersionMap = reactive<Record<string, string>>({})
const $configForm = ref<InstanceType<typeof ConfigForm> | null>(null) const $configForm = ref<InstanceType<typeof ConfigForm> | null>(null)
const strictSearch = useStorage('plugin-strict-search', true)
function setSrc(e: Event) { function setSrc(e: Event) {
const target = e.target as HTMLImageElement const target = e.target as HTMLImageElement
@@ -456,9 +465,12 @@ function _getSearchResult(val: string) {
fetch(`https://registry.npmjs.com/-/v1/search?text=${val}`) fetch(`https://registry.npmjs.com/-/v1/search?text=${val}`)
.then(async (res: Response) => { .then(async (res: Response) => {
const data = await res.json() const data = await res.json()
console.log(data)
pluginList.value = data.objects pluginList.value = data.objects
.filter((item: INPMSearchResultObject) => { .filter((item: INPMSearchResultObject) => {
return item.package.name.includes('picgo-plugin-') return strictSearch.value
? item.package.name.includes('picgo-plugin-') && item.package.name.includes(val)
: item.package.name.includes('picgo-plugin-')
}) })
.map((item: INPMSearchResultObject) => { .map((item: INPMSearchResultObject) => {
return handleSearchResult(item) return handleSearchResult(item)

View File

@@ -121,7 +121,10 @@ html, body {
} }
.search-container { .search-container {
display: flex;
padding: 1rem 1.5rem; padding: 1rem 1.5rem;
flex-direction: column;
gap: 1rem;
} }
.search-input-wrapper { .search-input-wrapper {
@@ -178,6 +181,72 @@ html, body {
background: var(--color-surface); background: var(--color-surface);
} }
/* Search Options */
.search-options {
display: flex;
align-items: flex-start;
border-top: 1px solid var(--color-border-secondary);
padding-top: 0.5rem;
}
.strict-search-checkbox {
display: flex;
flex-direction: column;
gap: 0.25rem;
cursor: pointer;
user-select: none;
}
.checkbox-input {
display: none;
}
.checkbox-label {
position: relative;
display: flex;
align-items: center;
font-size: 0.875rem;
font-weight: 500;
color: var(--color-text);
gap: 0.5rem;
}
.checkbox-label::before {
border: 2px solid var(--color-border);
border-radius: 3px;
width: 16px;
height: 16px;
background: var(--color-surface);
transition: all 0.2s ease;
content: '';
flex-shrink: 0;
}
.checkbox-input:checked + .checkbox-label::before {
border-color: var(--color-primary);
background: var(--color-primary);
}
.checkbox-input:checked + .checkbox-label::after {
position: absolute;
left: 3px;
font-size: 10px;
font-weight: bold;
color: white;
content: '✓';
}
.checkbox-label:hover::before {
border-color: var(--color-primary);
}
.checkbox-description {
margin-left: 24px;
font-size: 0.75rem;
color: var(--color-text-secondary);
line-height: 1.4;
}
/* Notice Card */ /* Notice Card */
.notice-card { .notice-card {
border-color: var(--color-warning); border-color: var(--color-warning);