把歌曲的热门评论与最新评论拆分成两个列表显示

pull/930/merge
lyswhut 2022-02-11 19:38:51 +08:00
parent 777551cb43
commit 055ab98d4c
3 changed files with 217 additions and 68 deletions

View File

@ -1,8 +1,12 @@
### 新增
- 新增“双击列表里的歌曲时自动切换到当前列表播放”设置,此功能仅对歌单、排行榜有效,默认关闭
- 新增打开收藏的在线列表的对应平台详情页功能,可以在我的列表-列表右键菜单中使用
### 优化
- 过滤tx源某些不支持播放的歌曲解决播放此类内容会导致意外的问题
- 新增“双击列表里的歌曲时自动切换到当前列表播放”设置,此功能仅对歌单、排行榜有效,默认关闭
- 新增打开收藏的在线列表的对应平台详情页功能,可以在我的列表-列表右键菜单中使用
- 把歌曲的热门评论与最新评论拆分成两个列表显示
### 修复

View File

@ -10,26 +10,31 @@ div.comment(:class="$style.comment")
svg(version='1.1' xmlns='http://www.w3.org/2000/svg' xlink='http://www.w3.org/1999/xlink' viewBox='0 0 24 24' space='preserve')
use(xlink:href='#icon-close')
div.scroll(:class="$style.commentMain" ref="dom_comment")
div(v-if="page == 1")
h2(:class="$style.commentType") {{$t('comment__hot_title')}}
p(:class="$style.commentLabel" style="cursor: pointer;" v-if="isHotLoadError" @click="handleGetHotComment(currentMusicInfo)") {{$t('comment__hot_load_error')}}
p(:class="$style.commentLabel" v-else-if="isHotLoading && !hotComments.length") {{$t('comment__hot_loading')}}
comment-floor(v-if="!isHotLoadError && hotComments.length" :class="[$style.commentFloor, isHotLoading ? $style.loading : null]" :comments="hotComments")
p(:class="$style.commentLabel" v-else-if="!isHotLoadError && !isHotLoading") {{$t('comment__no_content')}}
div
h2(:class="$style.commentType") {{$t('comment__new_title')}} ({{total}})
p(:class="$style.commentLabel" style="cursor: pointer;" v-if="isNewLoadError" @click="handleGetNewComment(currentMusicInfo, nextPage, limit)") {{$t('comment__new_load_error')}}
p(:class="$style.commentLabel" v-else-if="isNewLoading && !newComments.length") {{$t('comment__new_loading')}}
comment-floor(v-if="!isNewLoadError && newComments.length" :class="[$style.commentFloor, isNewLoading ? $style.loading : null]" :comments="newComments")
p(:class="$style.commentLabel" v-else-if="!isNewLoadError && !isNewLoading") {{$t('comment__no_content')}}
div(:class="$style.commentMain")
header(:class="$style.tab_header")
button(type="button" @click="handleToggleTab('hot')" :class="[$style.commentType, { [$style.active]: tabActiveId == 'hot' }]") {{$t('comment__hot_title')}} ({{hotComment.total}})
button(type="button" @click="handleToggleTab('new')" :class="[$style.commentType, { [$style.active]: tabActiveId == 'new' }]") {{$t('comment__new_title')}} ({{newComment.total}})
main(:class="$style.tab_main" ref="dom_tabMain")
div(:class="$style.tab_container")
div.scroll(:class="$style.tab_content" ref="dom_commentHot")
p(:class="$style.commentLabel" style="cursor: pointer;" v-if="hotComment.isLoadError" @click="handleGetHotComment(currentMusicInfo, hotComment.nextPage, hotComment.limit)") {{$t('comment__hot_load_error')}}
p(:class="$style.commentLabel" v-else-if="hotComment.isLoading && !hotComment.list.length") {{$t('comment__hot_loading')}}
comment-floor(v-if="!hotComment.isLoadError && hotComment.list.length" :class="[$style.commentFloor, hotComment.isLoading ? $style.loading : null]" :comments="hotComment.list")
p(:class="$style.commentLabel" v-else-if="!hotComment.isLoadError && !hotComment.isLoading") {{$t('comment__no_content')}}
div(:class="$style.pagination")
material-pagination(:count="total" :btnLength="5" :limit="limit" :page="page" @btn-click="handleToggleCommentPage")
material-pagination(:count="hotComment.total" :btnLength="5" :limit="hotComment.limit" :page="hotComment.page" @btn-click="handleToggleHotCommentPage")
div.scroll(:class="$style.tab_content" ref="dom_commentNew")
p(:class="$style.commentLabel" style="cursor: pointer;" v-if="newComment.isLoadError" @click="handleGetNewComment(currentMusicInfo, newComment.nextPage, newComment.limit)") {{$t('comment__new_load_error')}}
p(:class="$style.commentLabel" v-else-if="newComment.isLoading && !newComment.list.length") {{$t('comment__new_loading')}}
comment-floor(v-if="!newComment.isLoadError && newComment.list.length" :class="[$style.commentFloor, newComment.isLoading ? $style.loading : null]" :comments="newComment.list")
p(:class="$style.commentLabel" v-else-if="!newComment.isLoadError && !newComment.isLoading") {{$t('comment__no_content')}}
div(:class="$style.pagination")
material-pagination(:count="newComment.total" :btnLength="5" :limit="newComment.limit" :page="newComment.page" @btn-click="handleToggleCommentPage")
</template>
<script>
import { mapGetters } from 'vuex'
import { scrollTo } from '@renderer/utils'
import { scrollTo, scrollXTo } from '@renderer/utils'
import music from '@renderer/utils/music'
import CommentFloor from './CommentFloor'
@ -52,16 +57,16 @@ export default {
name: '',
singer: '',
},
tabActiveId: 'hot',
newComment: {
isLoading: false,
isLoadError: false,
page: 1,
total: 0,
maxPage: 1,
limit: 20,
isHotLoading: true,
isNewLoading: false,
isHotLoadError: true,
isNewLoadError: false,
nextPage: 1,
newComments: [
limit: 20,
list: [
// {
// text: ['123123hhh'],
// userName: 'dsads',
@ -72,7 +77,16 @@ export default {
// reply: [],
// },
],
hotComments: [
},
hotComment: {
isLoading: true,
isLoadError: true,
page: 1,
total: 0,
maxPage: 1,
nextPage: 1,
limit: 20,
list: [
// {
// text: ['123123hhh'],
// userName: 'dsads',
@ -92,6 +106,7 @@ export default {
// ],
// },
],
},
}
},
computed: {
@ -118,65 +133,92 @@ export default {
}
return resp
},
async getHotComment(musicInfo, retryNum = 0) {
async getHotComment(musicInfo, page, limit, retryNum = 0) {
let resp
try {
resp = await music[musicInfo.source].comment.getHotComment(musicInfo)
resp = await music[musicInfo.source].comment.getHotComment(musicInfo, page, limit)
} catch (error) {
if (error.message == '取消请求' || ++retryNum > 2) throw error
resp = await this.getHotComment(musicInfo, retryNum)
resp = await this.getHotComment(musicInfo, page, limit, retryNum)
}
return resp
},
handleGetNewComment(musicInfo, page, limit) {
this.isNewLoadError = false
this.isNewLoading = true
this.newComment.isLoadError = false
this.newComment.isLoading = true
this.getComment(musicInfo, page, limit).then(comment => {
this.isNewLoading = false
this.total = comment.total
this.maxPage = comment.maxPage
this.page = page
this.newComments = comment.comments
this.newComment.isLoading = false
this.newComment.total = comment.total
this.newComment.maxPage = comment.maxPage
this.newComment.page = page
this.newComment.list = comment.comments
this.$nextTick(() => {
scrollTo(this.$refs.dom_comment, 0, 300)
scrollTo(this.$refs.dom_commentNew, 0, 300)
})
}).catch(err => {
console.log(err)
if (err.message == '取消请求') return
this.isNewLoadError = true
this.isNewLoading = false
this.newComment.isLoadError = true
this.newComment.isLoading = false
})
},
handleGetHotComment(musicInfo) {
this.isHotLoadError = false
this.isHotLoading = true
this.getHotComment(musicInfo).then(hotComment => {
this.isHotLoading = false
this.hotComments = hotComment.comments
handleGetHotComment(musicInfo, page, limit) {
this.hotComment.isLoadError = false
this.hotComment.isLoading = true
this.getHotComment(musicInfo, page, limit).then(hotComment => {
this.hotComment.isLoading = false
this.hotComment.total = hotComment.total
this.hotComment.maxPage = hotComment.maxPage
this.hotComment.page = page
this.hotComment.list = hotComment.comments
this.$nextTick(() => {
scrollTo(this.$refs.dom_commentHot, 0, 300)
})
}).catch(err => {
console.log(err)
if (err.message == '取消请求') return
this.isHotLoadError = true
this.isHotLoading = false
this.hotComment.isLoadError = true
this.hotComment.isLoading = false
})
},
handleShowComment() {
if (!this.musicInfo.songmid || !music[this.musicInfo.source].comment) return
// if (this.musicInfo.songmid != this.currentMusicInfo.songmid) {
this.page = 1
this.total = 0
this.maxPage = 1
this.nextPage = 1
this.hotComment.page = 1
this.hotComment.total = 0
this.hotComment.maxPage = 1
this.hotComment.nextPage = 1
this.newComment.page = 1
this.newComment.total = 0
this.newComment.maxPage = 1
this.newComment.nextPage = 1
// }
this.isShowComment = true
this.currentMusicInfo = this.musicInfo
if (this.page == 1) this.handleGetHotComment(this.currentMusicInfo)
this.handleGetNewComment(this.currentMusicInfo, this.page, this.limit)
this.handleGetHotComment(this.currentMusicInfo, this.hotComment.page, this.hotComment.limit)
this.handleGetNewComment(this.currentMusicInfo, this.newComment.page, this.newComment.limit)
},
handleToggleHotCommentPage(page) {
this.hotComment.nextPage = page
this.handleGetHotComment(this.currentMusicInfo, page, this.hotComment.limit)
},
handleToggleCommentPage(page) {
this.nextPage = page
this.handleGetNewComment(this.currentMusicInfo, page, this.limit)
this.newComment.nextPage = page
this.handleGetNewComment(this.currentMusicInfo, page, this.newComment.limit)
},
handleToggleTab(id) {
if (this.tabActiveId == id) return
switch (id) {
case 'hot':
scrollXTo(this.$refs.dom_tabMain, 0)
break
case 'new':
scrollXTo(this.$refs.dom_tabMain, this.$refs.dom_tabMain.clientWidth)
break
}
this.tabActiveId = id
},
},
}
@ -229,10 +271,38 @@ export default {
}
.commentMain {
flex: auto;
padding-left: 15px;
padding-right: 10px;
background-color: @color-reply-floor;
border-radius: 4px;
display: flex;
flex-direction: column;
}
.tab_header {
display: flex;
flex-flow: row nowrap;
gap: 15px;
padding-left: 15px;
padding-right: 10px;
}
.tab_main {
flex: auto;
// display: flex;
// flex-flow: row nowrap;
position: relative;
overflow: hidden;
}
.tab_container {
position: absolute;
left: 0;
top: 0;
width: 200%;
height: 100%;
display: flex;
flex-flow: row nowrap;
}
.tab_content {
width: 100%;
padding-left: 15px;
padding-right: 10px;
}
.commentLabel {
padding: 15px;
@ -240,10 +310,21 @@ export default {
font-size: 14px;
}
.commentType {
padding: 10px 0;
padding: 5px;
margin: 5px 0;
font-size: 13px;
background: none;
border: none;
cursor: pointer;
transition: @transition-theme;
transition-property: opacity, color;
&:hover {
opacity: .7;
}
&.active {
color: @color-theme;
}
}
.commentFloor {
opacity: 1;
transition: opacity @transition-theme;
@ -268,8 +349,10 @@ each(@themes, {
color: ~'@{color-@{value}-theme_2-font-label}';
}
.commentType {
&.active {
color: ~'@{color-@{value}-theme}';
}
}
}
})
</style>

View File

@ -93,7 +93,7 @@ const easeInOutQuad = (t, b, c, d) => {
t--
return (-c / 2) * (t * (t - 2) - 1) + b
}
const handleScroll = (element, to, duration = 300, fn = () => {}) => {
const handleScrollY = (element, to, duration = 300, fn = () => {}) => {
if (!element) return fn()
const start = element.scrollTop || element.scrollY || 0
let cancel = false
@ -148,10 +148,72 @@ export const scrollTo = (element, to, duration = 300, fn = () => {}, delay = 0)
}
timeout = setTimeout(() => {
timeout = null
scrollCancelFn = handleScroll(element, to, duration, fn, delay)
scrollCancelFn = handleScrollY(element, to, duration, fn, delay)
}, delay)
} else {
cancelFn = handleScroll(element, to, duration, fn, delay)
cancelFn = handleScrollY(element, to, duration, fn, delay)
}
return cancelFn
}
const handleScrollX = (element, to, duration = 300, fn = () => {}) => {
if (!element) return fn()
const start = element.scrollLeft || element.scrollX || 0
let cancel = false
if (to > start) {
let maxScrollLeft = element.scrollWidth - element.clientWidth
if (to > maxScrollLeft) to = maxScrollLeft
} else if (to < start) {
if (to < 0) to = 0
} else return fn()
const change = to - start
const increment = 10
if (!change) return fn()
let currentTime = 0
let val
const animateScroll = () => {
currentTime += increment
val = parseInt(easeInOutQuad(currentTime, start, change, duration))
if (element.scrollTo) {
element.scrollTo(val, 0)
} else {
element.scrollLeft = val
}
if (currentTime < duration) {
if (cancel) return fn()
setTimeout(animateScroll, increment)
} else {
fn()
}
}
animateScroll()
return () => {
cancel = true
}
}
/**
* 设置滚动条位置
* @param {*} element 要设置滚动的容器 dom
* @param {*} to 滚动的目标位置
* @param {*} duration 滚动完成时间 ms
* @param {*} fn 滚动完成后的回调
* @param {*} delay 延迟执行时间
*/
export const scrollXTo = (element, to, duration = 300, fn = () => {}, delay = 0) => {
let cancelFn
let timeout
if (delay) {
let scrollCancelFn
cancelFn = () => {
timeout == null ? scrollCancelFn && scrollCancelFn() : clearTimeout(timeout)
}
timeout = setTimeout(() => {
timeout = null
scrollCancelFn = handleScrollX(element, to, duration, fn, delay)
}, delay)
} else {
cancelFn = handleScrollX(element, to, duration, fn, delay)
}
return cancelFn
}