mirror of
https://github.com/EstrellaXD/Auto_Bangumi.git
synced 2026-10-28 19:25:55 +08:00
feat: 番剧搜索框接口使用和交互完成
- 三种搜索触发来源 - 输入中 debounce 600ms 后触发搜索 - 按回车或点击搜索 icon 按钮后触发搜索 - 切换 provider 源站时触发搜索 - 渲染的番剧信息列表样式待调整 - 搜索框 placeholder / provider 展示样式/i18n 待调整
This commit is contained in:
3
.vscode/launch.json
vendored
3
.vscode/launch.json
vendored
@@ -10,6 +10,9 @@
|
|||||||
"request": "launch",
|
"request": "launch",
|
||||||
"cwd": "${workspaceFolder}/backend/src",
|
"cwd": "${workspaceFolder}/backend/src",
|
||||||
"program": "main.py",
|
"program": "main.py",
|
||||||
|
"env": {
|
||||||
|
"HOST": "127.0.0.1",
|
||||||
|
},
|
||||||
"console": "integratedTerminal",
|
"console": "integratedTerminal",
|
||||||
"justMyCode": true
|
"justMyCode": true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ if __name__ == "__main__":
|
|||||||
if os.getenv("IPV6"):
|
if os.getenv("IPV6"):
|
||||||
host = "::"
|
host = "::"
|
||||||
else:
|
else:
|
||||||
host = "0.0.0.0"
|
host = os.getenv("HOST", "0.0.0.0")
|
||||||
uvicorn.run(
|
uvicorn.run(
|
||||||
app,
|
app,
|
||||||
host=host,
|
host=host,
|
||||||
|
|||||||
@@ -2,35 +2,39 @@
|
|||||||
import {Down, Search} from '@icon-park/vue-next';
|
import {Down, Search} from '@icon-park/vue-next';
|
||||||
import {ref} from 'vue';
|
import {ref} from 'vue';
|
||||||
|
|
||||||
const props = withDefaults(
|
|
||||||
defineProps<{
|
|
||||||
value?: string;
|
|
||||||
placeholder?: string;
|
|
||||||
}>(),
|
|
||||||
{
|
|
||||||
value: '',
|
|
||||||
placeholder: '',
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
const emit = defineEmits(['update:value', 'click-search']);
|
const inputValue = ref<string>('');
|
||||||
const {site, providers, bangumiInfo$ } = storeToRefs(useSearchStore());
|
const selectingProvider = ref<boolean>(false);
|
||||||
const {getProviders, onInput} = useSearchStore();
|
|
||||||
|
|
||||||
|
const {input$, provider, providers, getProviders, bangumiList } = useSearchStore();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* - 输入中 debounce 600ms 后触发搜索
|
||||||
|
* - 按回车或点击搜索 icon 按钮后触发搜索
|
||||||
|
* - 切换 provider 源站时触发搜索
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
function onInput (e: Event) {
|
||||||
|
const value = (e.target as HTMLInputElement).value;
|
||||||
|
input$.next(value);
|
||||||
|
inputValue.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
function onSearch () {
|
||||||
|
input$.next(inputValue.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
function onSelect (site: string) {
|
||||||
|
provider.value = site;
|
||||||
|
selectingProvider.value = !selectingProvider.value
|
||||||
|
onSearch();
|
||||||
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
getProviders();
|
getProviders();
|
||||||
});
|
});
|
||||||
|
|
||||||
const selectedProvider = computed(() => {
|
|
||||||
return site.value || '';
|
|
||||||
});
|
|
||||||
|
|
||||||
const onSelect = ref(false);
|
|
||||||
|
|
||||||
function onSearch() {
|
|
||||||
emit('click-search', props.value);
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -58,9 +62,9 @@ function onSearch() {
|
|||||||
|
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
:value="value"
|
placeholder="Input to search"
|
||||||
:placeholder="placeholder"
|
|
||||||
input-reset
|
input-reset
|
||||||
|
:value="inputValue"
|
||||||
@keyup.enter="onSearch"
|
@keyup.enter="onSearch"
|
||||||
@input="onInput"
|
@input="onInput"
|
||||||
/>
|
/>
|
||||||
@@ -72,27 +76,23 @@ function onSearch() {
|
|||||||
w-100px
|
w-100px
|
||||||
is-btn
|
is-btn
|
||||||
class="provider-select"
|
class="provider-select"
|
||||||
@click="() => onSelect = !onSelect"
|
@click="() => selectingProvider = !selectingProvider"
|
||||||
>
|
>
|
||||||
<div text-h3 truncate>
|
<div text-h3 truncate>
|
||||||
{{ selectedProvider }}
|
{{ provider }}
|
||||||
</div>
|
</div>
|
||||||
<div class="provider-select">
|
<div class="provider-select">
|
||||||
<Down/>
|
<Down/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-show="onSelect" abs top-84px left-540px w-100px rounded-12px shadow bg-white z-99 overflow-hidden>
|
<div v-show="selectingProvider" abs top-84px left-540px w-100px rounded-12px shadow bg-white z-99 overflow-hidden>
|
||||||
<div
|
<div
|
||||||
v-for="i in providers"
|
v-for="site in providers"
|
||||||
:key="i"
|
:key="site"
|
||||||
hover:bg-theme-row
|
hover:bg-theme-row
|
||||||
is-btn
|
is-btn
|
||||||
@click="() => {
|
@click="() => onSelect(site)"
|
||||||
site = i;
|
|
||||||
onSelect = false;
|
|
||||||
}"
|
|
||||||
|
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
text-h3
|
text-h3
|
||||||
@@ -101,19 +101,20 @@ function onSearch() {
|
|||||||
p-12px
|
p-12px
|
||||||
truncate
|
truncate
|
||||||
>
|
>
|
||||||
{{ i }}
|
{{ site }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
v-if="bangumiInfo$"
|
abs top-84px left-200px z-98
|
||||||
abs top-84px left-200px z-98>
|
>
|
||||||
<ab-bangumi-card
|
<ab-bangumi-card
|
||||||
:key="bangumiInfo$.id"
|
v-for="(item, index) in bangumiList"
|
||||||
:poster="bangumiInfo$.poster_link ?? ''"
|
:key="index"
|
||||||
:name="bangumiInfo$.official_title"
|
:poster="item.poster_link ?? ''"
|
||||||
:season="bangumiInfo$.season"
|
:name="item.official_title"
|
||||||
:group="bangumiInfo$.group_name"
|
:season="item.season"
|
||||||
|
:group="item.group_name"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,19 +1,21 @@
|
|||||||
|
import {ref} from 'vue';
|
||||||
import {
|
import {
|
||||||
Subject,
|
Subject,
|
||||||
debounceTime,
|
debounceTime,
|
||||||
|
filter,
|
||||||
switchMap,
|
switchMap,
|
||||||
tap,
|
tap,
|
||||||
} from "rxjs";
|
} from "rxjs";
|
||||||
import type {BangumiRule} from "#/bangumi";
|
import type {BangumiRule} from "#/bangumi";
|
||||||
|
|
||||||
|
|
||||||
export const useSearchStore = defineStore('search', () => {
|
export function useSearchStore () {
|
||||||
const input$ = new Subject<string>();
|
const bangumiList = ref<BangumiRule[]>([]);
|
||||||
const onInput = (e: Event) => input$.next(e.target.value);
|
|
||||||
const providers = ref<string[]>(['mikan', 'dmhy', 'nyaa']);
|
|
||||||
const site = ref<string>('mikan');
|
|
||||||
|
|
||||||
const bangumiInfo$ = apiSearch.get('魔女之旅');
|
const providers = ref<string[]>(['mikan', 'dmhy', 'nyaa']);
|
||||||
|
const provider = ref<string>('mikan');
|
||||||
|
|
||||||
|
const input$ = new Subject<string>();
|
||||||
|
|
||||||
const {execute: getProviders, onResult: onGetProvidersResult} = useApi(
|
const {execute: getProviders, onResult: onGetProvidersResult} = useApi(
|
||||||
apiSearch.getProvider
|
apiSearch.getProvider
|
||||||
@@ -23,34 +25,25 @@ export const useSearchStore = defineStore('search', () => {
|
|||||||
providers.value = res;
|
providers.value = res;
|
||||||
});
|
});
|
||||||
|
|
||||||
input$.pipe(
|
const bangumiInfo$ = input$.pipe(
|
||||||
debounceTime(1000),
|
debounceTime(600),
|
||||||
tap((input: string) => {
|
tap(() => {
|
||||||
console.log('input', input)
|
bangumiList.value = [];
|
||||||
// clear Search Result List
|
|
||||||
|
|
||||||
}),
|
}),
|
||||||
switchMap((input: string) => apiSearch.get(input, site.value)),
|
filter(Boolean),
|
||||||
tap((bangumi: BangumiRule) => console.log(bangumi)),
|
switchMap((input: string) => apiSearch.get(input, provider.value)),
|
||||||
tap((bangumi: BangumiRule) => {
|
tap((bangumi: BangumiRule) => {
|
||||||
console.log('bangumi', bangumi)
|
bangumiList.value.push(bangumi);
|
||||||
// set bangumi info to Search Result List
|
|
||||||
}),
|
}),
|
||||||
).subscribe({
|
)
|
||||||
complete() {
|
.subscribe()
|
||||||
// end of stream, stop loading animation
|
|
||||||
}
|
|
||||||
}, (err) => {
|
|
||||||
console.error(err);
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
input$,
|
input$,
|
||||||
onInput,
|
|
||||||
bangumiInfo$,
|
bangumiInfo$,
|
||||||
site,
|
provider,
|
||||||
getProviders,
|
getProviders,
|
||||||
providers,
|
providers,
|
||||||
|
bangumiList,
|
||||||
};
|
};
|
||||||
});
|
}
|
||||||
Reference in New Issue
Block a user