搜索框

This commit is contained in:
jxxghp
2023-07-01 14:09:14 +08:00
parent b0e6388456
commit 2b257f386b
3 changed files with 89 additions and 27 deletions
@@ -8,7 +8,23 @@ import Footer from "@/layouts/components/Footer.vue";
import NavbarThemeSwitcher from "@/layouts/components/NavbarThemeSwitcher.vue"; import NavbarThemeSwitcher from "@/layouts/components/NavbarThemeSwitcher.vue";
import UserProfile from "@/layouts/components/UserProfile.vue"; import UserProfile from "@/layouts/components/UserProfile.vue";
// Banner const router = useRouter();
// 搜索词
const searchWord = ref<string>("");
// Search
const search = () => {
if (!searchWord.value) {
return;
}
router.push({
path: "/browse/media/search",
query: {
title: searchWord.value,
},
});
};
</script> </script>
<template> <template>
@@ -24,16 +40,28 @@ import UserProfile from "@/layouts/components/UserProfile.vue";
<!-- 👉 Search --> <!-- 👉 Search -->
<div class="d-flex align-center cursor-pointer" style="user-select: none"> <div class="d-flex align-center cursor-pointer" style="user-select: none">
<!-- 👉 Search Trigger button --> <!-- 👉 Search Trigger button -->
<IconBtn> <IconBtn class="d-lg-none">
<VIcon icon="mdi-magnify" /> <VIcon icon="mdi-magnify" />
</IconBtn> </IconBtn>
<span class="d-none d-md-flex align-center text-disabled">
<span class="me-3">搜索</span>
<span class="meta-key">&#8984;K</span>
</span>
</div> </div>
<span class="w-1/5">
<VTextField
v-model="searchWord"
class="d-none d-lg-block text-disabled"
density="compact"
variant="solo"
label="搜索电影、电视剧"
append-inner-icon="mdi-magnify"
single-line
hide-details
@click:append-inner="search"
@keydown.enter="search"
flat
rounded
/>
</span>
<VSpacer /> <VSpacer />
<IconBtn <IconBtn
+27 -17
View File
@@ -1,47 +1,57 @@
<script setup lang="ts"> <script setup lang="ts">
import MediaCardListView from '@/views/discover/MediaCardListView.vue'; import MediaCardListView from "@/views/discover/MediaCardListView.vue";
// 输入参数 // 输入参数
const props = defineProps({ const props = defineProps({
type: Array as PropType<string[]> | PropType<string>, type: Array as PropType<string[]> | PropType<string>,
}); });
// 路由参数
const route = useRoute();
// 面包屑标题定义
const titles: { [key: string]: any } = { const titles: { [key: string]: any } = {
tmdb: { tmdb: {
trending: '流行趋势', trending: "流行趋势",
movies: '热门电影', movies: "热门电影",
tvs: '热门电视剧', tvs: "热门电视剧",
}, },
douban: { douban: {
movies: '最新电影', movies: "最新电影",
tvs: '最新电视剧', tvs: "最新电视剧",
tv_weekly_chinese: '华语剧集榜', tv_weekly_chinese: "华语剧集榜",
tv_weekly_global: '全球剧集榜', tv_weekly_global: "全球剧集榜",
},
media: {
search: "搜索",
}, },
}; };
// 计算API路径
const getApiPath = (types: string[] | string) => { const getApiPath = (types: string[] | string) => {
if (Array.isArray(types)) { if (Array.isArray(types)) {
return types.join('/') return types.join("/");
} else { } else {
return types return types;
} }
}; };
const getTitle = (types: string[] | string) => { // 面包屑标题
const getTitle = (types: string[] | string, title: any = "") => {
if (Array.isArray(types)) { if (Array.isArray(types)) {
return ['推荐', titles[types[0]][types[1]]] if (title) {
return [titles[types[0]][types[1]], title];
}
return ["推荐", titles[types[0]][types[1]]];
} else { } else {
return ["推荐"] return ["发现"];
} }
}; };
</script> </script>
<template> <template>
<div> <div>
<VBreadcrumbs :items="getTitle(props.type||'')"></VBreadcrumbs> <VBreadcrumbs :items="getTitle(props.type || '', route.query?.title)"></VBreadcrumbs>
<MediaCardListView :apipath="getApiPath(props.type||'')"/> <MediaCardListView :apipath="getApiPath(props.type || '')" :params="route.query" />
</div> </div>
</template> </template>
+27 -3
View File
@@ -6,12 +6,15 @@ import MediaCard from "@/components/cards/MediaCard.vue";
// 输入参数 // 输入参数
const props = defineProps({ const props = defineProps({
apipath: String, apipath: String,
params: Object as PropType<{ [key: string]: any }>,
}); });
// 当前页码 // 当前页码
const page = ref(1); const page = ref(1);
// 是否加载中 // 是否加载中
const loading = ref(false); const loading = ref(false);
// 是否加载完成
const finished = ref(false);
// 数据列表 // 数据列表
const dataList = ref<MediaInfo[]>([]); const dataList = ref<MediaInfo[]>([]);
@@ -29,15 +32,23 @@ const fetchData = async ({ done }) => {
} }
// 设置加载中 // 设置加载中
loading.value = true; loading.value = true;
// 参数
let params = {
page: page.value,
};
if (props.params) {
params = { ...params, ...props.params };
}
currData.value = await api.get(props.apipath, { currData.value = await api.get(props.apipath, {
params: { params: params,
page: page.value,
},
}); });
// 合并数据 // 合并数据
dataList.value = [...dataList.value, ...currData.value]; dataList.value = [...dataList.value, ...currData.value];
// 页码+1 // 页码+1
page.value++; page.value++;
// 标计为完成
finished.value = true;
} catch (error) { } catch (error) {
console.error(error); console.error(error);
} finally { } finally {
@@ -49,6 +60,12 @@ const fetchData = async ({ done }) => {
</script> </script>
<template> <template>
<VProgressCircular
class="centered"
v-if="!finished"
indeterminate
color="primary"
></VProgressCircular>
<VInfiniteScroll <VInfiniteScroll
mode="intersect" mode="intersect"
side="end" side="end"
@@ -66,4 +83,11 @@ const fetchData = async ({ done }) => {
.grid-media-card { .grid-media-card {
grid-template-columns: repeat(auto-fill, minmax(9.375rem, 1fr)); grid-template-columns: repeat(auto-fill, minmax(9.375rem, 1fr));
} }
.centered {
position: absolute;
inset-block-start: 50%;
inset-inline-start: 50%;
transform: translate(-50%, -50%);
}
</style> </style>