Skip to content

Commit

Permalink
支持导出歌单
Browse files Browse the repository at this point in the history
  • Loading branch information
sunzongzheng committed Dec 22, 2018
1 parent 3bfdf28 commit c81ec92
Show file tree
Hide file tree
Showing 3 changed files with 215 additions and 63 deletions.
19 changes: 10 additions & 9 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "player",
"version": "1.2.0",
"version": "1.2.0",
"author": "sunzongzheng <sunzongzhengwy@163.com>",
"description": "A player",
"license": "CC0-1.0",
Expand Down Expand Up @@ -56,12 +56,12 @@
"target": "nsis",
"icon": "build/icons/icon.ico"
},
"nsis": {
"allowToChangeInstallationDirectory": true,
"oneClick": false,
"menuCategory": true,
"allowElevation": false
},
"nsis": {
"allowToChangeInstallationDirectory": true,
"oneClick": false,
"menuCategory": true,
"allowElevation": false
},
"linux": {
"icon": "build/icons",
"executableName": "MusicLake",
Expand All @@ -85,7 +85,7 @@
"element-ui": "^2.4.1",
"flyio": "^0.6.2",
"moment": "^2.18.1",
"music-metadata": "^3.1.4",
"music-metadata": "^3.1.4",
"sass-resources-loader": "^1.3.1",
"social-share.js": "^1.0.16",
"socket.io-client": "^2.1.1",
Expand All @@ -94,7 +94,8 @@
"velocity-animate": "^1.5.0",
"vue": "^2.5.16",
"vue-router": "^3.0.1",
"vuex": "^3.0.1"
"vuex": "^3.0.1",
"xlsx": "^0.14.1"
},
"devDependencies": {
"@babel/core": "^7.0.0-beta.46",
Expand Down
26 changes: 5 additions & 21 deletions src/index.ejs
Original file line number Diff line number Diff line change
Expand Up @@ -50,19 +50,6 @@
height: 48px;
}
}
.alert {
position: fixed;
width: 100%;
height: 100%;
left: 0;
top: 0;
z-index: 99999;
background: white;
display: flex;
align-items: center;
justify-content: center;
}
</style>
<% if (htmlWebpackPlugin.options.nodeModules) { %>
<!-- Add `node_modules/` to global paths so `require` works properly in development -->
Expand All @@ -73,14 +60,11 @@
</head>
<body>
<div id="app"></div>
<!--<div id="page-loading">-->
<!--<div class="line1"></div>-->
<!--<div class="line2"></div>-->
<!--<div class="line3"></div>-->
<!--<div class="line4"></div>-->
<!--</div>-->
<div class="alert">
<p>由于受到QQ音乐、网易云音乐的警告函,现已关闭服务</p>
<div id="page-loading">
<div class="line1"></div>
<div class="line2"></div>
<div class="line3"></div>
<div class="line4"></div>
</div>
<!-- Set `__static` path to static files in production -->
<script>
Expand Down
233 changes: 200 additions & 33 deletions src/renderer/App.vue
Original file line number Diff line number Diff line change
@@ -1,18 +1,56 @@
<template>
<div :class="s.app">
<left-menu></left-menu>
<div :class="s.right">
<search-bar></search-bar>
<div :class="s.main" ref="main">
<keep-alive :include="cacheList">
<router-view v-if="!refresh"></router-view>
</keep-alive>
</div>
<!--<left-menu></left-menu>-->
<!--<div :class="s.right">-->
<!--<search-bar></search-bar>-->
<!--<div :class="s.main" ref="main">-->
<!--<keep-alive :include="cacheList">-->
<!--<router-view v-if="!refresh"></router-view>-->
<!--</keep-alive>-->
<!--</div>-->
<!--</div>-->
<!--<player></player>-->
<!--<lyrics></lyrics>-->
<!--<play-list></play-list>-->
<!--<download-progress></download-progress>-->
<div :class="s.alert">
<p>由于受到QQ音乐、网易云音乐的警告函,现已关闭服务</p>
<p>如果您需要导出云歌单,请点击<a v-popover:popover>此链接</a></p>
</div>
<player></player>
<lyrics></lyrics>
<play-list></play-list>
<download-progress></download-progress>
<el-popover :popper-class="s.avatarPopover"
placement="bottom"
ref="popover"
trigger="click"
>
<div :class="s.loginMethod">
<div @click="showLoginDialog('qq')">
<Icon type="QQ"></Icon>
<span>QQ登录</span>
</div>
<div @click="showLoginDialog('weibo')">
<Icon type="weibo"></Icon>
<span>微博登录</span>
</div>
</div>
</el-popover>
<el-dialog
title="请选择要导出的歌单"
:visible.sync="modal.exportPlaylist"
width="30%"
>
<el-select v-model="chosenPlaylist" placeholder="请选择" style="width: 100%">
<el-option
v-for="item in playlist"
:key="item.id"
:label="item.name"
:value="item.id">
</el-option>
</el-select>
<div slot="footer" class="dialog-footer">
<el-button @click="modal.exportPlaylist = false">取 消</el-button>
<el-button type="primary" @click="exportPlaylist" :loading="loading.exportPlaylist">确 定</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
Expand All @@ -25,6 +63,8 @@
import eventBus from './eventBus/searchResult'
import updateAlert from './view/components/updateAlert.vue'
import { mapState, mapActions, mapMutations } from 'vuex'
import weiboLogin from './view/components/leftMenu/avatar/weibo-login'
import xlsx from 'xlsx'
export default {
components: {
Expand All @@ -41,11 +81,19 @@
cacheList: [
'rank',
],
modal: {
exportPlaylist: false,
},
playlist: [],
chosenPlaylist: null,
loading: {
exportPlaylist: false,
},
}
},
computed: {
...mapState('hot-key', ['hotKey', 'enableGlobal']),
...mapState('user', ['setting']),
...mapState('user', ['setting', 'info']),
...mapState('c_playlist', ['cycle']),
...mapState('play', ['volume']),
},
Expand Down Expand Up @@ -82,38 +130,113 @@
duration: 0,
})
},
showLoginDialog(type) {
if (type === 'qq') {
this.$ipc.send('login')
} else {
weiboLogin.init()
}
},
async getPlaylist() {
const loading = this.$loading({
lock: true,
text: '正在获取歌单',
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)',
})
try {
this.playlist = await Vue.$http.get('/playlist')
} catch (e) {
}
loading.close()
},
async exportPlaylist() {
if (this.chosenPlaylist === null) {
this.$message.warning('请选择歌单')
return
}
this.loading.exportPlaylist = true
try {
const list = await this.$http.get(`playlist/${this.chosenPlaylist}`)
const workbook = xlsx.utils.book_new()
const worksheet = xlsx.utils.json_to_sheet(
list.map(item => {
return {
'歌曲名称': item.name,
'专辑名': item.album.name,
'歌手': item.artists[0].name,
'来源平台': {
qq: 'QQ音乐',
netease: '网易云音乐',
xiami: '虾米音乐',
}[item.vendor],
}
}),
)
const playlistName = this.playlist.find(item => item.id === this.chosenPlaylist).name
xlsx.utils.book_append_sheet(workbook, worksheet, playlistName)
const s2ab = function(s) { // 字符串转字符流
const buf = new ArrayBuffer(s.length)
const view = new Uint8Array(buf)
for (let i = 0; i !== s.length; ++i) {
view[i] = s.charCodeAt(i) & 0xFF
}
return buf
}
// 创建二进制对象写入转换好的字节流
let tmpDown = new Blob([s2ab(xlsx.write(workbook, {
bookType: 'xlsx',
bookSST: false,
type: 'binary',
}))], { type: '' })
let a = document.createElement('a')
// 利用URL.createObjectURL()方法为a元素生成blob URL
a.href = URL.createObjectURL(tmpDown) // 创建对象超链接
a.download = `${playlistName}.xls`
a.click()
} catch (e) {
console.warn(e)
}
this.loading.exportPlaylist = false
},
},
watch: {
'$route'() {
this.$refs.main.scrollTop = 0
},
info(val) {
if (val) {
this.modal.exportPlaylist = true
this.getPlaylist()
}
},
},
created() {
Vue.$store.dispatch('offline-playlist/init') // 初始化离线歌单
this.$ipc.on('loginSuccessed', this.loginSuccessed) // 监听登录成功
this.$ipc.on('update-alert', this.updateAlert) // 监听版本更新
this.$ipc.send('toggle-tray', this.setting.macStatusBar)
this.$ipc.send('tray-control-volume', this.volume)
if (localStorage.token) {
this.$store.dispatch('user/init')
}
if (!['add-to-playlist', 'share'].includes(this.$route.name)) {
Vue.$socket.connect() // 连接 socket
}
eventBus.$on('refresh', () => {
this.refresh = true
this.$nextTick(() => {
this.refresh = false
})
})
this.initMenu()
this.initGlobalShortcut()
this.initDownload()
this.checkNeteaseBindAvalible()
this.checkQQBindAvalible()
setTimeout(() => {
this.$updater.__judgeUpdater(this.setting.linuxAutoUpdate)
}, 5000)
// if (localStorage.token) {
// this.$store.dispatch('user/init')
// }
// if (!['add-to-playlist', 'share'].includes(this.$route.name)) {
// Vue.$socket.connect() // 连接 socket
// }
// eventBus.$on('refresh', () => {
// this.refresh = true
// this.$nextTick(() => {
// this.refresh = false
// })
// })
// this.initMenu()
// this.initGlobalShortcut()
// this.initDownload()
// this.checkNeteaseBindAvalible()
// this.checkQQBindAvalible()
// setTimeout(() => {
// this.$updater.__judgeUpdater(this.setting.linuxAutoUpdate)
// }, 5000)
},
mounted() {
document.body.querySelector('#page-loading').style.display = 'none'
Expand Down Expand Up @@ -192,5 +315,49 @@
height: calc(100% - #{$searchBar-height});
overflow: auto;
}
.alert {
position: fixed;
width: 100%;
height: 100%;
left: 0;
top: 0;
z-index: 100;
background: white;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
}
.avatarPopover {
-webkit-app-region: no-drag;
span {
font-size: 12px;
cursor: pointer;
&:hover {
color: #26B36C;
}
}
.loginMethod {
display: flex;
justify-content: space-around;
& > div {
display: flex;
flex-direction: column;
align-items: center;
padding: 0 12px;
svg {
font-size: 32px;
cursor: pointer;
}
span {
margin-top: 8px;
}
&:hover {
opacity: .8;
}
}
}
}
</style>

0 comments on commit c81ec92

Please sign in to comment.