把歌曲的热门评论与最新评论拆分成两个列表显示
parent
777551cb43
commit
055ab98d4c
|
@ -1,8 +1,12 @@
|
||||||
|
### 新增
|
||||||
|
|
||||||
|
- 新增“双击列表里的歌曲时自动切换到当前列表播放”设置,此功能仅对歌单、排行榜有效,默认关闭
|
||||||
|
- 新增打开收藏的在线列表的对应平台详情页功能,可以在我的列表-列表右键菜单中使用
|
||||||
|
|
||||||
### 优化
|
### 优化
|
||||||
|
|
||||||
- 过滤tx源某些不支持播放的歌曲,解决播放此类内容会导致意外的问题
|
- 过滤tx源某些不支持播放的歌曲,解决播放此类内容会导致意外的问题
|
||||||
- 新增“双击列表里的歌曲时自动切换到当前列表播放”设置,此功能仅对歌单、排行榜有效,默认关闭
|
- 把歌曲的热门评论与最新评论拆分成两个列表显示
|
||||||
- 新增打开收藏的在线列表的对应平台详情页功能,可以在我的列表-列表右键菜单中使用
|
|
||||||
|
|
||||||
### 修复
|
### 修复
|
||||||
|
|
||||||
|
|
|
@ -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')
|
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')
|
use(xlink:href='#icon-close')
|
||||||
|
|
||||||
div.scroll(:class="$style.commentMain" ref="dom_comment")
|
div(:class="$style.commentMain")
|
||||||
div(v-if="page == 1")
|
header(:class="$style.tab_header")
|
||||||
h2(:class="$style.commentType") {{$t('comment__hot_title')}}
|
button(type="button" @click="handleToggleTab('hot')" :class="[$style.commentType, { [$style.active]: tabActiveId == 'hot' }]") {{$t('comment__hot_title')}} ({{hotComment.total}})
|
||||||
p(:class="$style.commentLabel" style="cursor: pointer;" v-if="isHotLoadError" @click="handleGetHotComment(currentMusicInfo)") {{$t('comment__hot_load_error')}}
|
button(type="button" @click="handleToggleTab('new')" :class="[$style.commentType, { [$style.active]: tabActiveId == 'new' }]") {{$t('comment__new_title')}} ({{newComment.total}})
|
||||||
p(:class="$style.commentLabel" v-else-if="isHotLoading && !hotComments.length") {{$t('comment__hot_loading')}}
|
main(:class="$style.tab_main" ref="dom_tabMain")
|
||||||
comment-floor(v-if="!isHotLoadError && hotComments.length" :class="[$style.commentFloor, isHotLoading ? $style.loading : null]" :comments="hotComments")
|
div(:class="$style.tab_container")
|
||||||
p(:class="$style.commentLabel" v-else-if="!isHotLoadError && !isHotLoading") {{$t('comment__no_content')}}
|
div.scroll(:class="$style.tab_content" ref="dom_commentHot")
|
||||||
div
|
p(:class="$style.commentLabel" style="cursor: pointer;" v-if="hotComment.isLoadError" @click="handleGetHotComment(currentMusicInfo, hotComment.nextPage, hotComment.limit)") {{$t('comment__hot_load_error')}}
|
||||||
h2(:class="$style.commentType") {{$t('comment__new_title')}} ({{total}})
|
p(:class="$style.commentLabel" v-else-if="hotComment.isLoading && !hotComment.list.length") {{$t('comment__hot_loading')}}
|
||||||
p(:class="$style.commentLabel" style="cursor: pointer;" v-if="isNewLoadError" @click="handleGetNewComment(currentMusicInfo, nextPage, limit)") {{$t('comment__new_load_error')}}
|
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="isNewLoading && !newComments.length") {{$t('comment__new_loading')}}
|
p(:class="$style.commentLabel" v-else-if="!hotComment.isLoadError && !hotComment.isLoading") {{$t('comment__no_content')}}
|
||||||
comment-floor(v-if="!isNewLoadError && newComments.length" :class="[$style.commentFloor, isNewLoading ? $style.loading : null]" :comments="newComments")
|
div(:class="$style.pagination")
|
||||||
p(:class="$style.commentLabel" v-else-if="!isNewLoadError && !isNewLoading") {{$t('comment__no_content')}}
|
material-pagination(:count="hotComment.total" :btnLength="5" :limit="hotComment.limit" :page="hotComment.page" @btn-click="handleToggleHotCommentPage")
|
||||||
div(:class="$style.pagination")
|
div.scroll(:class="$style.tab_content" ref="dom_commentNew")
|
||||||
material-pagination(:count="total" :btnLength="5" :limit="limit" :page="page" @btn-click="handleToggleCommentPage")
|
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>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { mapGetters } from 'vuex'
|
import { mapGetters } from 'vuex'
|
||||||
import { scrollTo } from '@renderer/utils'
|
import { scrollTo, scrollXTo } from '@renderer/utils'
|
||||||
import music from '@renderer/utils/music'
|
import music from '@renderer/utils/music'
|
||||||
import CommentFloor from './CommentFloor'
|
import CommentFloor from './CommentFloor'
|
||||||
|
|
||||||
|
@ -52,16 +57,16 @@ export default {
|
||||||
name: '',
|
name: '',
|
||||||
singer: '',
|
singer: '',
|
||||||
},
|
},
|
||||||
page: 1,
|
tabActiveId: 'hot',
|
||||||
total: 0,
|
newComment: {
|
||||||
maxPage: 1,
|
isLoading: false,
|
||||||
limit: 20,
|
isLoadError: false,
|
||||||
isHotLoading: true,
|
page: 1,
|
||||||
isNewLoading: false,
|
total: 0,
|
||||||
isHotLoadError: true,
|
maxPage: 1,
|
||||||
isNewLoadError: false,
|
nextPage: 1,
|
||||||
nextPage: 1,
|
limit: 20,
|
||||||
newComments: [
|
list: [
|
||||||
// {
|
// {
|
||||||
// text: ['123123hhh'],
|
// text: ['123123hhh'],
|
||||||
// userName: 'dsads',
|
// userName: 'dsads',
|
||||||
|
@ -71,8 +76,17 @@ export default {
|
||||||
// likedCount: 100,
|
// likedCount: 100,
|
||||||
// reply: [],
|
// reply: [],
|
||||||
// },
|
// },
|
||||||
],
|
],
|
||||||
hotComments: [
|
},
|
||||||
|
hotComment: {
|
||||||
|
isLoading: true,
|
||||||
|
isLoadError: true,
|
||||||
|
page: 1,
|
||||||
|
total: 0,
|
||||||
|
maxPage: 1,
|
||||||
|
nextPage: 1,
|
||||||
|
limit: 20,
|
||||||
|
list: [
|
||||||
// {
|
// {
|
||||||
// text: ['123123hhh'],
|
// text: ['123123hhh'],
|
||||||
// userName: 'dsads',
|
// userName: 'dsads',
|
||||||
|
@ -91,7 +105,8 @@ export default {
|
||||||
// },
|
// },
|
||||||
// ],
|
// ],
|
||||||
// },
|
// },
|
||||||
],
|
],
|
||||||
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
@ -118,65 +133,92 @@ export default {
|
||||||
}
|
}
|
||||||
return resp
|
return resp
|
||||||
},
|
},
|
||||||
async getHotComment(musicInfo, retryNum = 0) {
|
async getHotComment(musicInfo, page, limit, retryNum = 0) {
|
||||||
let resp
|
let resp
|
||||||
try {
|
try {
|
||||||
resp = await music[musicInfo.source].comment.getHotComment(musicInfo)
|
resp = await music[musicInfo.source].comment.getHotComment(musicInfo, page, limit)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error.message == '取消请求' || ++retryNum > 2) throw error
|
if (error.message == '取消请求' || ++retryNum > 2) throw error
|
||||||
resp = await this.getHotComment(musicInfo, retryNum)
|
resp = await this.getHotComment(musicInfo, page, limit, retryNum)
|
||||||
}
|
}
|
||||||
return resp
|
return resp
|
||||||
},
|
},
|
||||||
handleGetNewComment(musicInfo, page, limit) {
|
handleGetNewComment(musicInfo, page, limit) {
|
||||||
this.isNewLoadError = false
|
this.newComment.isLoadError = false
|
||||||
this.isNewLoading = true
|
this.newComment.isLoading = true
|
||||||
this.getComment(musicInfo, page, limit).then(comment => {
|
this.getComment(musicInfo, page, limit).then(comment => {
|
||||||
this.isNewLoading = false
|
this.newComment.isLoading = false
|
||||||
this.total = comment.total
|
this.newComment.total = comment.total
|
||||||
this.maxPage = comment.maxPage
|
this.newComment.maxPage = comment.maxPage
|
||||||
this.page = page
|
this.newComment.page = page
|
||||||
this.newComments = comment.comments
|
this.newComment.list = comment.comments
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
scrollTo(this.$refs.dom_comment, 0, 300)
|
scrollTo(this.$refs.dom_commentNew, 0, 300)
|
||||||
})
|
})
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
console.log(err)
|
console.log(err)
|
||||||
if (err.message == '取消请求') return
|
if (err.message == '取消请求') return
|
||||||
this.isNewLoadError = true
|
this.newComment.isLoadError = true
|
||||||
this.isNewLoading = false
|
this.newComment.isLoading = false
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
handleGetHotComment(musicInfo) {
|
handleGetHotComment(musicInfo, page, limit) {
|
||||||
this.isHotLoadError = false
|
this.hotComment.isLoadError = false
|
||||||
this.isHotLoading = true
|
this.hotComment.isLoading = true
|
||||||
this.getHotComment(musicInfo).then(hotComment => {
|
this.getHotComment(musicInfo, page, limit).then(hotComment => {
|
||||||
this.isHotLoading = false
|
this.hotComment.isLoading = false
|
||||||
this.hotComments = hotComment.comments
|
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 => {
|
}).catch(err => {
|
||||||
console.log(err)
|
console.log(err)
|
||||||
if (err.message == '取消请求') return
|
if (err.message == '取消请求') return
|
||||||
this.isHotLoadError = true
|
this.hotComment.isLoadError = true
|
||||||
this.isHotLoading = false
|
this.hotComment.isLoading = false
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
handleShowComment() {
|
handleShowComment() {
|
||||||
if (!this.musicInfo.songmid || !music[this.musicInfo.source].comment) return
|
if (!this.musicInfo.songmid || !music[this.musicInfo.source].comment) return
|
||||||
// if (this.musicInfo.songmid != this.currentMusicInfo.songmid) {
|
// if (this.musicInfo.songmid != this.currentMusicInfo.songmid) {
|
||||||
this.page = 1
|
this.hotComment.page = 1
|
||||||
this.total = 0
|
this.hotComment.total = 0
|
||||||
this.maxPage = 1
|
this.hotComment.maxPage = 1
|
||||||
this.nextPage = 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.isShowComment = true
|
||||||
this.currentMusicInfo = this.musicInfo
|
this.currentMusicInfo = this.musicInfo
|
||||||
|
|
||||||
if (this.page == 1) this.handleGetHotComment(this.currentMusicInfo)
|
this.handleGetHotComment(this.currentMusicInfo, this.hotComment.page, this.hotComment.limit)
|
||||||
this.handleGetNewComment(this.currentMusicInfo, this.page, this.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) {
|
handleToggleCommentPage(page) {
|
||||||
this.nextPage = page
|
this.newComment.nextPage = page
|
||||||
this.handleGetNewComment(this.currentMusicInfo, page, this.limit)
|
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 {
|
.commentMain {
|
||||||
flex: auto;
|
flex: auto;
|
||||||
padding-left: 15px;
|
|
||||||
padding-right: 10px;
|
|
||||||
background-color: @color-reply-floor;
|
background-color: @color-reply-floor;
|
||||||
border-radius: 4px;
|
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 {
|
.commentLabel {
|
||||||
padding: 15px;
|
padding: 15px;
|
||||||
|
@ -240,9 +310,20 @@ export default {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
.commentType {
|
.commentType {
|
||||||
padding: 10px 0;
|
padding: 5px;
|
||||||
|
margin: 5px 0;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
color: @color-theme;
|
background: none;
|
||||||
|
border: none;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: @transition-theme;
|
||||||
|
transition-property: opacity, color;
|
||||||
|
&:hover {
|
||||||
|
opacity: .7;
|
||||||
|
}
|
||||||
|
&.active {
|
||||||
|
color: @color-theme;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.commentFloor {
|
.commentFloor {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
|
@ -268,7 +349,9 @@ each(@themes, {
|
||||||
color: ~'@{color-@{value}-theme_2-font-label}';
|
color: ~'@{color-@{value}-theme_2-font-label}';
|
||||||
}
|
}
|
||||||
.commentType {
|
.commentType {
|
||||||
color: ~'@{color-@{value}-theme}';
|
&.active {
|
||||||
|
color: ~'@{color-@{value}-theme}';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -93,7 +93,7 @@ const easeInOutQuad = (t, b, c, d) => {
|
||||||
t--
|
t--
|
||||||
return (-c / 2) * (t * (t - 2) - 1) + b
|
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()
|
if (!element) return fn()
|
||||||
const start = element.scrollTop || element.scrollY || 0
|
const start = element.scrollTop || element.scrollY || 0
|
||||||
let cancel = false
|
let cancel = false
|
||||||
|
@ -148,10 +148,72 @@ export const scrollTo = (element, to, duration = 300, fn = () => {}, delay = 0)
|
||||||
}
|
}
|
||||||
timeout = setTimeout(() => {
|
timeout = setTimeout(() => {
|
||||||
timeout = null
|
timeout = null
|
||||||
scrollCancelFn = handleScroll(element, to, duration, fn, delay)
|
scrollCancelFn = handleScrollY(element, to, duration, fn, delay)
|
||||||
}, delay)
|
}, delay)
|
||||||
} else {
|
} 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
|
return cancelFn
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue