MengYX
5 years ago
5 changed files with 266 additions and 218 deletions
@ -0,0 +1,71 @@ |
|||
<template> |
|||
<el-table :data="tableData" style="width: 100%"> |
|||
|
|||
<el-table-column label="封面"> |
|||
<template slot-scope="scope"> |
|||
<el-image :src="scope.row.picture" style="width: 100px; height: 100px"> |
|||
<div class="image-slot el-image__error" slot="error"> |
|||
暂无封面 |
|||
</div> |
|||
</el-image> |
|||
</template> |
|||
</el-table-column> |
|||
<el-table-column label="歌曲" sortable> |
|||
<template slot-scope="scope"> |
|||
<span style="margin-left: 10px">{{ scope.row.title }}</span> |
|||
</template> |
|||
</el-table-column> |
|||
<el-table-column label="歌手" sortable> |
|||
<template slot-scope="scope"> |
|||
<p>{{ scope.row.artist }}</p> |
|||
</template> |
|||
</el-table-column> |
|||
<el-table-column label="专辑" sortable> |
|||
<template slot-scope="scope"> |
|||
<p>{{ scope.row.album }}</p> |
|||
</template> |
|||
</el-table-column> |
|||
<el-table-column label="操作"> |
|||
<template slot-scope="scope"> |
|||
<el-button @click="handlePlay(scope.$index, scope.row)" |
|||
circle icon="el-icon-video-play" type="success"> |
|||
</el-button> |
|||
<el-button @click="handleDownload(scope.row)" |
|||
circle icon="el-icon-download"> |
|||
</el-button> |
|||
<el-button @click="handleDelete(scope.$index, scope.row)" |
|||
circle icon="el-icon-delete" type="danger"> |
|||
</el-button> |
|||
</template> |
|||
</el-table-column> |
|||
</el-table> |
|||
</template> |
|||
|
|||
<script> |
|||
import {DownloadBlobMusic, RemoveBlobMusic} from './util' |
|||
|
|||
export default { |
|||
name: "preview", |
|||
props: { |
|||
tableData: {type: Array, required: true}, |
|||
download_format: {type: String, required: true} |
|||
}, |
|||
|
|||
methods: { |
|||
handlePlay(index, row) { |
|||
this.$emit("music_changed", row.file); |
|||
}, |
|||
handleDelete(index, row) { |
|||
RemoveBlobMusic(row); |
|||
this.tableData.splice(index, 1); |
|||
}, |
|||
handleDownload(row) { |
|||
DownloadBlobMusic(row, this.download_format) |
|||
}, |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style scoped> |
|||
|
|||
</style> |
@ -0,0 +1,82 @@ |
|||
<template> |
|||
<el-upload |
|||
:auto-upload="false" |
|||
:on-change="handleFile" |
|||
:show-file-list="false" |
|||
action="" |
|||
drag |
|||
multiple> |
|||
<i class="el-icon-upload"/> |
|||
<div class="el-upload__text">将文件拖到此处,或<em>点击选择</em></div> |
|||
<div class="el-upload__tip" slot="tip">本工具仅在浏览器内对文件进行解锁,无需消耗流量</div> |
|||
</el-upload> |
|||
</template> |
|||
|
|||
<script> |
|||
"use strict";// 严格模式 用于尾调用优化 |
|||
|
|||
export default { |
|||
name: "upload", |
|||
data() { |
|||
return { |
|||
cacheQueue: [], |
|||
workers: [], |
|||
idle_workers: [], |
|||
thread_num: 1 |
|||
} |
|||
}, |
|||
mounted() { |
|||
if (document.location.host !== "") { |
|||
//todo: Fail on Hot Reload |
|||
const worker = require("workerize-loader!../decrypt/common"); |
|||
this.thread_num = navigator.hardwareConcurrency || 1; |
|||
for (let i = 0; i < this.thread_num; i++) { |
|||
// noinspection JSValidateTypes,JSUnresolvedVariable |
|||
this.workers.push(worker().CommonDecrypt); |
|||
this.idle_workers.push(i); |
|||
} |
|||
} else { |
|||
const dec = require('../decrypt/common'); |
|||
this.workers.push(dec.CommonDecrypt); |
|||
this.idle_workers.push(0) |
|||
} |
|||
}, |
|||
methods: { |
|||
handleFile(file) { |
|||
// 有空闲worker 立刻处理文件 |
|||
if (this.idle_workers.length > 0) { |
|||
this.handleDoFile(file, this.idle_workers.shift()); |
|||
} |
|||
// 无空闲worker 则放入缓存队列 |
|||
else { |
|||
this.cacheQueue.push(file); |
|||
} |
|||
}, |
|||
handleCacheQueue(worker_id) { |
|||
// 调用方法消费缓存队列中的数据 |
|||
if (this.cacheQueue.length === 0) { |
|||
this.idle_workers.push(worker_id); |
|||
return |
|||
} |
|||
this.handleDoFile(this.cacheQueue.shift(), worker_id); |
|||
}, |
|||
handleDoFile(file, worker_id) { |
|||
this.workers[worker_id](file).then(data => { |
|||
this.$emit("handle_finish", data); |
|||
// 完成之后 执行新任务 todo: 可能导致call stack过长 |
|||
this.handleCacheQueue(worker_id); |
|||
}).catch(err => { |
|||
this.$emit("handle_error", err, file.name); |
|||
this.handleCacheQueue(worker_id); |
|||
}) |
|||
}, |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style scoped> |
|||
/*noinspection CssUnusedSymbol*/ |
|||
.el-upload-dragger { |
|||
width: 80vw !important; |
|||
} |
|||
</style> |
@ -0,0 +1,26 @@ |
|||
export function DownloadBlobMusic(data, format) { |
|||
const a = document.createElement('a'); |
|||
a.href = data.file; |
|||
switch (format) { |
|||
case "1": |
|||
a.download = data.title + "." + data.ext; |
|||
break; |
|||
case "2": |
|||
a.download = data.artist + " - " + data.title + "." + data.ext; |
|||
break; |
|||
case "3": |
|||
a.download = data.title + " - " + data.artist + "." + data.ext; |
|||
break; |
|||
default: |
|||
a.download = data.filename; |
|||
break; |
|||
} |
|||
document.body.append(a); |
|||
a.click(); |
|||
a.remove(); |
|||
} |
|||
|
|||
export function RemoveBlobMusic(data) { |
|||
URL.revokeObjectURL(data.file); |
|||
URL.revokeObjectURL(data.picture); |
|||
} |
Loading…
Reference in new issue