feat: 修改搜索列表

This commit is contained in:
algerkong
2023-12-27 23:25:26 +08:00
parent f5d097e975
commit c7c1143cb4
10 changed files with 224 additions and 78 deletions
+4
View File
@@ -7,6 +7,7 @@ export {}
declare module 'vue' { declare module 'vue' {
export interface GlobalComponents { export interface GlobalComponents {
AlbumsItem: typeof import('./src/components/common/AlbumsItem.vue')['default']
MPop: typeof import('./src/components/common/MPop.vue')['default'] MPop: typeof import('./src/components/common/MPop.vue')['default']
MusicList: typeof import('./src/components/MusicList.vue')['default'] MusicList: typeof import('./src/components/MusicList.vue')['default']
NAvatar: typeof import('naive-ui')['NAvatar'] NAvatar: typeof import('naive-ui')['NAvatar']
@@ -22,15 +23,18 @@ declare module 'vue' {
NMessageProvider: typeof import('naive-ui')['NMessageProvider'] NMessageProvider: typeof import('naive-ui')['NMessageProvider']
NPopover: typeof import('naive-ui')['NPopover'] NPopover: typeof import('naive-ui')['NPopover']
NScrollbar: typeof import('naive-ui')['NScrollbar'] NScrollbar: typeof import('naive-ui')['NScrollbar']
NSelect: typeof import('naive-ui')['NSelect']
NSlider: typeof import('naive-ui')['NSlider'] NSlider: typeof import('naive-ui')['NSlider']
NTooltip: typeof import('naive-ui')['NTooltip'] NTooltip: typeof import('naive-ui')['NTooltip']
PlayBottom: typeof import('./src/components/common/PlayBottom.vue')['default'] PlayBottom: typeof import('./src/components/common/PlayBottom.vue')['default']
PlayListsItem: typeof import('./src/components/common/PlayListsItem.vue')['default']
PlaylistType: typeof import('./src/components/PlaylistType.vue')['default'] PlaylistType: typeof import('./src/components/PlaylistType.vue')['default']
RecommendAlbum: typeof import('./src/components/RecommendAlbum.vue')['default'] RecommendAlbum: typeof import('./src/components/RecommendAlbum.vue')['default']
RecommendSinger: typeof import('./src/components/RecommendSinger.vue')['default'] RecommendSinger: typeof import('./src/components/RecommendSinger.vue')['default']
RecommendSonglist: typeof import('./src/components/RecommendSonglist.vue')['default'] RecommendSonglist: typeof import('./src/components/RecommendSonglist.vue')['default']
RouterLink: typeof import('vue-router')['RouterLink'] RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView'] RouterView: typeof import('vue-router')['RouterView']
SearchItem: typeof import('./src/components/common/SearchItem.vue')['default']
SongItem: typeof import('./src/components/common/SongItem.vue')['default'] SongItem: typeof import('./src/components/common/SongItem.vue')['default']
} }
} }
+6 -5
View File
@@ -16,16 +16,17 @@
"dependencies": { "dependencies": {
"@tailwindcss/postcss7-compat": "^2.2.4", "@tailwindcss/postcss7-compat": "^2.2.4",
"@vue/runtime-core": "^3.3.4", "@vue/runtime-core": "^3.3.4",
"@vueuse/core": "^10.7.1",
"autoprefixer": "^9.8.6", "autoprefixer": "^9.8.6",
"axios": "^0.21.1", "axios": "^0.21.1",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"naive-ui": "^2.34.4",
"postcss": "^7.0.36", "postcss": "^7.0.36",
"sass": "^1.35.2", "sass": "^1.35.2",
"tailwindcss": "npm:@tailwindcss/postcss7-compat@^2.2.4", "tailwindcss": "npm:@tailwindcss/postcss7-compat@^2.2.4",
"vue": "^3.3.4", "vue": "^3.3.4",
"vue-router": "^4.2.4", "vue-router": "^4.2.4",
"vuex": "^4.1.0", "vuex": "^4.1.0"
"naive-ui": "^2.34.4"
}, },
"devDependencies": { "devDependencies": {
"@sicons/antd": "^0.10.0", "@sicons/antd": "^0.10.0",
@@ -35,11 +36,11 @@
"electron": "^28.0.0", "electron": "^28.0.0",
"electron-builder": "^24.9.1", "electron-builder": "^24.9.1",
"typescript": "^4.3.2", "typescript": "^4.3.2",
"unplugin-auto-import": "^0.17.2",
"unplugin-vue-components": "^0.26.0",
"vfonts": "^0.1.0", "vfonts": "^0.1.0",
"vite": "^4.4.7", "vite": "^4.4.7",
"vite-plugin-vue-devtools": "1.0.0-beta.5", "vite-plugin-vue-devtools": "1.0.0-beta.5",
"vue-tsc": "^0.0.24", "vue-tsc": "^0.0.24"
"unplugin-auto-import": "^0.17.2",
"unplugin-vue-components": "^0.26.0"
} }
} }
+7 -3
View File
@@ -1,9 +1,13 @@
import request from "@/utils/request" import request from "@/utils/request"
import { ISearchDetail } from "@/type/search" import { ISearchDetail } from "@/type/search"
interface IParams {
keywords: string
type: number
}
// 搜索内容 // 搜索内容
export const getSearch = (keywords: any) => { export const getSearch = (params: IParams) => {
return request.get<any>("/cloudsearch", { return request.get<any>('/cloudsearch', {
params: { keywords: keywords, type: 1 }, params,
}) })
} }
+50
View File
@@ -0,0 +1,50 @@
<template>
<div class="search-item">
<div class="search-item-img">
<n-image
:src="getImgUrl(item.picUrl, 'album')"
lazy
preview-disabled
/>
</div>
<div class="search-item-info">
<div class="search-item-name">{{ item.name }}</div>
<div class="search-item-artist">{{ item.desc}}</div>
</div>
</div>
</template>
<script setup lang="ts">
import { getImgUrl } from '@/utils'
import type {Album} from '@/type/album'
const props = defineProps<{
item: {
picUrl: string
name: string
desc: string
}
}>()
</script>
<style scoped lang="scss">
.search-item{
@apply rounded-3xl p-3 flex items-center hover:bg-gray-800 transition;
margin: 0 10px;
.search-item-img{
@apply w-12 h-12 mr-4 rounded-2xl overflow-hidden;
}
.search-item-info{
&-name{
@apply text-white text-sm text-center;
}
&-artist{
@apply text-gray-400 text-xs text-center;
}
}
}
</style>
+60 -1
View File
@@ -12,6 +12,14 @@
<template #prefix> <template #prefix>
<i class="iconfont icon-search"></i> <i class="iconfont icon-search"></i>
</template> </template>
<template #suffix>
<div class="w-20 px-3 flex justify-between items-center">
<div>{{ searchTypeOptions.find(item => item.key === searchType)?.label }}</div>
<n-dropdown trigger="hover" @select="selectSearchType" :options="searchTypeOptions">
<i class="iconfont icon-xiasanjiaoxing"></i>
</n-dropdown>
</div>
</template>
</n-input> </n-input>
</div> </div>
<div class="user-box"> <div class="user-box">
@@ -80,6 +88,7 @@ onMounted(() => {
// 搜索词 // 搜索词
const searchValue = ref("") const searchValue = ref("")
const searchType = ref(1)
const search = () => { const search = () => {
let value = searchValue.value let value = searchValue.value
@@ -89,12 +98,62 @@ const search = () => {
router.push({ router.push({
path: "/search", path: "/search",
query: { query: {
keyword: value keyword: value,
type: searchType.value
} }
}) })
} }
} }
const selectSearchType = (key: any) => {
searchType.value = key
}
const SEARCH_TYPES = [
{
label: '单曲',
key: 1
},
{
label: '专辑',
key: 10
},
{
label: '歌手',
key: 100
},
{
label: '歌单',
key: 1000
},
{
label: '用户',
key: 1002
},
{
label: 'MV',
key: 1004
},
{
label: '歌词',
key: 1006
},
{
label: '电台',
key: 1009
},
{
label: '视频',
key: 1014
},
{
label: '综合',
key: 1018
}
]
const searchTypeOptions = ref(SEARCH_TYPES)
const value = 'Drive My Car' const value = 'Drive My Car'
const options = [ const options = [
{ {
+25 -25
View File
@@ -3,31 +3,31 @@ export interface IAlbumNew {
albums: Album[]; albums: Album[];
} }
interface Album { export interface Album {
name: string; name: string
id: number; id: number
type: string; type: string
size: number; size: number
picId: number; picId: number
blurPicUrl: string; blurPicUrl: string
companyId: number; companyId: number
pic: number; pic: number
picUrl: string; picUrl: string
publishTime: number; publishTime: number
description: string; description: string
tags: string; tags: string
company: string; company: string
briefDesc: string; briefDesc: string
artist: Artist; artist: Artist
songs?: any; songs?: any
alias: string[]; alias: string[]
status: number; status: number
copyrightId: number; copyrightId: number
commentThreadId: string; commentThreadId: string
artists: Artist2[]; artists: Artist2[]
paid: boolean; paid: boolean
onSale: boolean; onSale: boolean
picId_str: string; picId_str: string
} }
interface Artist2 { interface Artist2 {
+37 -37
View File
@@ -6,43 +6,43 @@ export interface IList {
total: number; total: number;
} }
interface Playlist { export interface Playlist {
name: string; name: string
id: number; id: number
trackNumberUpdateTime: number; trackNumberUpdateTime: number
status: number; status: number
userId: number; userId: number
createTime: number; createTime: number
updateTime: number; updateTime: number
subscribedCount: number; subscribedCount: number
trackCount: number; trackCount: number
cloudTrackCount: number; cloudTrackCount: number
coverImgUrl: string; coverImgUrl: string
coverImgId: number; coverImgId: number
description: string; description: string
tags: string[]; tags: string[]
playCount: number; playCount: number
trackUpdateTime: number; trackUpdateTime: number
specialType: number; specialType: number
totalDuration: number; totalDuration: number
creator: Creator; creator: Creator
tracks?: any; tracks?: any
subscribers: Subscriber[]; subscribers: Subscriber[]
subscribed: boolean; subscribed: boolean
commentThreadId: string; commentThreadId: string
newImported: boolean; newImported: boolean
adType: number; adType: number
highQuality: boolean; highQuality: boolean
privacy: number; privacy: number
ordered: boolean; ordered: boolean
anonimous: boolean; anonimous: boolean
coverStatus: number; coverStatus: number
recommendInfo?: any; recommendInfo?: any
shareCount: number; shareCount: number
coverImgId_str?: string; coverImgId_str?: string
commentCount: number; commentCount: number
copywriter: string; copywriter: string
tag: string; tag: string
} }
interface Subscriber { interface Subscriber {
+33 -7
View File
@@ -33,13 +33,26 @@
<div class="search-list-box"> <div class="search-list-box">
<template v-if="searchDetail"> <template v-if="searchDetail">
<div <div
v-for="(item, index) in searchDetail?.result.songs" v-for="(item, index) in searchDetail?.songs"
:key="item.id" :key="item.id"
:class="setAnimationClass('animate__bounceInRight')" :class="setAnimationClass('animate__bounceInRight')"
:style="setAnimationDelay(index, 50)" :style="setAnimationDelay(index, 50)"
> >
<SongItem :item="item" @play="handlePlay"/> <SongItem :item="item" @play="handlePlay"/>
</div> </div>
<template v-for="(list, key) in searchDetail">
<template v-if="key !== 'songs'">
<div
v-for="(item, index) in list"
:key="item.id"
:class="setAnimationClass('animate__bounceInRight')"
:style="setAnimationDelay(index, 50)"
>
<SearchItem :item="item"/>
</div>
</template>
</template>
</template> </template>
</div> </div>
</n-layout> </n-layout>
@@ -55,10 +68,12 @@ import { setAnimationClass, setAnimationDelay } from "@/utils";
import { onMounted, ref, watch } from "vue"; import { onMounted, ref, watch } from "vue";
import SongItem from "@/components/common/SongItem.vue"; import SongItem from "@/components/common/SongItem.vue";
import { useStore } from "vuex"; import { useStore } from "vuex";
import { useDateFormat } from '@vueuse/core'
const route = useRoute(); const route = useRoute();
const router = useRouter(); const router = useRouter();
const searchDetail = ref<any>(); const searchDetail = ref<any>();
const searchType = ref(Number(route.query.type) || 1);
// 热搜列表 // 热搜列表
const hotSearchData = ref<IHotSearch>(); const hotSearchData = ref<IHotSearch>();
@@ -79,18 +94,21 @@ const clickHotKeyword = (keyword: string) => {
path: "/search", path: "/search",
query: { query: {
keyword: keyword, keyword: keyword,
type: 1
}, },
}); });
// isHotSearchList.value = false; // isHotSearchList.value = false;
}; };
const loadSearch = async (keyword: any) => { const dateFormat = (time:any) => useDateFormat(time, 'YYYY.MM.DD').value
hotKeyword.value = keyword; const loadSearch = async (keywords: any) => {
hotKeyword.value = keywords;
searchDetail.value = undefined; searchDetail.value = undefined;
if (!keyword) return; if (!keywords) return;
const { data } = await getSearch(keyword); const { data } = await getSearch({keywords, type:searchType.value});
const songs = data.result.songs; const songs = data.result.songs || [];
const albums = data.result.albums || [];
// songs map 替换属性 // songs map 替换属性
songs.map((item: any) => { songs.map((item: any) => {
@@ -98,7 +116,14 @@ const loadSearch = async (keyword: any) => {
item.song = item; item.song = item;
item.artists = item.ar; item.artists = item.ar;
}); });
searchDetail.value = data; albums.map((item: any) => {
item.desc = `${item.artist.name } ${ item.company } ${dateFormat(item.publishTime)}`;
});
searchDetail.value = {
songs,
albums
}
console.log('searchDetail',searchDetail.value)
}; };
loadSearch(route.query.keyword); loadSearch(route.query.keyword);
@@ -106,6 +131,7 @@ loadSearch(route.query.keyword);
watch( watch(
() => route.query, () => route.query,
async newParams => { async newParams => {
searchType.value = Number(newParams.type || 1)
loadSearch(newParams.keyword); loadSearch(newParams.keyword);
} }
) )
+2
View File
@@ -35,6 +35,8 @@ const loadPage = async () => {
recordList.value = recordData.allData recordList.value = recordData.allData
} }
loadPage()
watch(() => router.currentRoute.value, (to) => { watch(() => router.currentRoute.value, (to) => {
if (to.path === "/user") { if (to.path === "/user") {
loadPage() loadPage()