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
components.d.ts vendored
View File

@@ -7,6 +7,7 @@ export {}
declare module 'vue' {
export interface GlobalComponents {
AlbumsItem: typeof import('./src/components/common/AlbumsItem.vue')['default']
MPop: typeof import('./src/components/common/MPop.vue')['default']
MusicList: typeof import('./src/components/MusicList.vue')['default']
NAvatar: typeof import('naive-ui')['NAvatar']
@@ -22,15 +23,18 @@ declare module 'vue' {
NMessageProvider: typeof import('naive-ui')['NMessageProvider']
NPopover: typeof import('naive-ui')['NPopover']
NScrollbar: typeof import('naive-ui')['NScrollbar']
NSelect: typeof import('naive-ui')['NSelect']
NSlider: typeof import('naive-ui')['NSlider']
NTooltip: typeof import('naive-ui')['NTooltip']
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']
RecommendAlbum: typeof import('./src/components/RecommendAlbum.vue')['default']
RecommendSinger: typeof import('./src/components/RecommendSinger.vue')['default']
RecommendSonglist: typeof import('./src/components/RecommendSonglist.vue')['default']
RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView']
SearchItem: typeof import('./src/components/common/SearchItem.vue')['default']
SongItem: typeof import('./src/components/common/SongItem.vue')['default']
}
}

View File

@@ -16,16 +16,17 @@
"dependencies": {
"@tailwindcss/postcss7-compat": "^2.2.4",
"@vue/runtime-core": "^3.3.4",
"@vueuse/core": "^10.7.1",
"autoprefixer": "^9.8.6",
"axios": "^0.21.1",
"lodash": "^4.17.21",
"naive-ui": "^2.34.4",
"postcss": "^7.0.36",
"sass": "^1.35.2",
"tailwindcss": "npm:@tailwindcss/postcss7-compat@^2.2.4",
"vue": "^3.3.4",
"vue-router": "^4.2.4",
"vuex": "^4.1.0",
"naive-ui": "^2.34.4"
"vuex": "^4.1.0"
},
"devDependencies": {
"@sicons/antd": "^0.10.0",
@@ -35,11 +36,11 @@
"electron": "^28.0.0",
"electron-builder": "^24.9.1",
"typescript": "^4.3.2",
"unplugin-auto-import": "^0.17.2",
"unplugin-vue-components": "^0.26.0",
"vfonts": "^0.1.0",
"vite": "^4.4.7",
"vite-plugin-vue-devtools": "1.0.0-beta.5",
"vue-tsc": "^0.0.24",
"unplugin-auto-import": "^0.17.2",
"unplugin-vue-components": "^0.26.0"
"vue-tsc": "^0.0.24"
}
}

View File

@@ -1,9 +1,13 @@
import request from "@/utils/request"
import { ISearchDetail } from "@/type/search"
interface IParams {
keywords: string
type: number
}
// 搜索内容
export const getSearch = (keywords: any) => {
return request.get<any>("/cloudsearch", {
params: { keywords: keywords, type: 1 },
export const getSearch = (params: IParams) => {
return request.get<any>('/cloudsearch', {
params,
})
}

View File

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>

View File

@@ -12,6 +12,14 @@
<template #prefix>
<i class="iconfont icon-search"></i>
</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>
</div>
<div class="user-box">
@@ -80,6 +88,7 @@ onMounted(() => {
// 搜索词
const searchValue = ref("")
const searchType = ref(1)
const search = () => {
let value = searchValue.value
@@ -89,12 +98,62 @@ const search = () => {
router.push({
path: "/search",
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 options = [
{

View File

@@ -3,31 +3,31 @@ export interface IAlbumNew {
albums: Album[];
}
interface Album {
name: string;
id: number;
type: string;
size: number;
picId: number;
blurPicUrl: string;
companyId: number;
pic: number;
picUrl: string;
publishTime: number;
description: string;
tags: string;
company: string;
briefDesc: string;
artist: Artist;
songs?: any;
alias: string[];
status: number;
copyrightId: number;
commentThreadId: string;
artists: Artist2[];
paid: boolean;
onSale: boolean;
picId_str: string;
export interface Album {
name: string
id: number
type: string
size: number
picId: number
blurPicUrl: string
companyId: number
pic: number
picUrl: string
publishTime: number
description: string
tags: string
company: string
briefDesc: string
artist: Artist
songs?: any
alias: string[]
status: number
copyrightId: number
commentThreadId: string
artists: Artist2[]
paid: boolean
onSale: boolean
picId_str: string
}
interface Artist2 {

View File

@@ -6,43 +6,43 @@ export interface IList {
total: number;
}
interface Playlist {
name: string;
id: number;
trackNumberUpdateTime: number;
status: number;
userId: number;
createTime: number;
updateTime: number;
subscribedCount: number;
trackCount: number;
cloudTrackCount: number;
coverImgUrl: string;
coverImgId: number;
description: string;
tags: string[];
playCount: number;
trackUpdateTime: number;
specialType: number;
totalDuration: number;
creator: Creator;
tracks?: any;
subscribers: Subscriber[];
subscribed: boolean;
commentThreadId: string;
newImported: boolean;
adType: number;
highQuality: boolean;
privacy: number;
ordered: boolean;
anonimous: boolean;
coverStatus: number;
recommendInfo?: any;
shareCount: number;
coverImgId_str?: string;
commentCount: number;
copywriter: string;
tag: string;
export interface Playlist {
name: string
id: number
trackNumberUpdateTime: number
status: number
userId: number
createTime: number
updateTime: number
subscribedCount: number
trackCount: number
cloudTrackCount: number
coverImgUrl: string
coverImgId: number
description: string
tags: string[]
playCount: number
trackUpdateTime: number
specialType: number
totalDuration: number
creator: Creator
tracks?: any
subscribers: Subscriber[]
subscribed: boolean
commentThreadId: string
newImported: boolean
adType: number
highQuality: boolean
privacy: number
ordered: boolean
anonimous: boolean
coverStatus: number
recommendInfo?: any
shareCount: number
coverImgId_str?: string
commentCount: number
copywriter: string
tag: string
}
interface Subscriber {

View File

@@ -33,13 +33,26 @@
<div class="search-list-box">
<template v-if="searchDetail">
<div
v-for="(item, index) in searchDetail?.result.songs"
v-for="(item, index) in searchDetail?.songs"
:key="item.id"
:class="setAnimationClass('animate__bounceInRight')"
:style="setAnimationDelay(index, 50)"
>
<SongItem :item="item" @play="handlePlay"/>
</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>
</div>
</n-layout>
@@ -55,10 +68,12 @@ import { setAnimationClass, setAnimationDelay } from "@/utils";
import { onMounted, ref, watch } from "vue";
import SongItem from "@/components/common/SongItem.vue";
import { useStore } from "vuex";
import { useDateFormat } from '@vueuse/core'
const route = useRoute();
const router = useRouter();
const searchDetail = ref<any>();
const searchType = ref(Number(route.query.type) || 1);
// 热搜列表
const hotSearchData = ref<IHotSearch>();
@@ -79,18 +94,21 @@ const clickHotKeyword = (keyword: string) => {
path: "/search",
query: {
keyword: keyword,
type: 1
},
});
// isHotSearchList.value = false;
};
const loadSearch = async (keyword: any) => {
hotKeyword.value = keyword;
const dateFormat = (time:any) => useDateFormat(time, 'YYYY.MM.DD').value
const loadSearch = async (keywords: any) => {
hotKeyword.value = keywords;
searchDetail.value = undefined;
if (!keyword) return;
const { data } = await getSearch(keyword);
if (!keywords) return;
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((item: any) => {
@@ -98,7 +116,14 @@ const loadSearch = async (keyword: any) => {
item.song = item;
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);
@@ -106,6 +131,7 @@ loadSearch(route.query.keyword);
watch(
() => route.query,
async newParams => {
searchType.value = Number(newParams.type || 1)
loadSearch(newParams.keyword);
}
)

View File

@@ -35,6 +35,8 @@ const loadPage = async () => {
recordList.value = recordData.allData
}
loadPage()
watch(() => router.currentRoute.value, (to) => {
if (to.path === "/user") {
loadPage()