const component_search_folders = { emits: ['play_audio', 'set_token'], data() { return { search_foldernames: "", folders: [], folder: {}, offset: 0, limit: 10, folder_offset: 0, folder_limit: 10, files_in_folder: [], playing_audio_file: {}, } }, template: `
{{ offset }}~{{ offset + folders.length }}
Folder Name Action
{{ folder.foldername }}
{{ folder_offset }}~{{ folder_offset + files_in_folder.length }}
Filename Folder Name Size Action
`, mounted() { if (this.$route.query.folder_id) { this.folder.id = parseInt(this.$route.query.folder_id) this.folder.foldername = this.$route.query.foldername this.get_files_in_folder() } }, methods: { folder_last_page() { this.folder_offset = this.folder_offset - this.folder_limit if (this.folder_offset < 0) { this.folder_offset = 0 return } this.get_files_in_folder() }, folder_next_page() { this.folder_offset = this.folder_offset + this.folder_limit this.get_files_in_folder() }, view_folder(folder) { this.folder = folder this.get_files_in_folder() }, get_files_in_folder() { axios.post('/api/v1/get_files_in_folder', { folder_id: this.folder.id, limit: this.folder_limit, offset: this.folder_offset, }).then((response) => { var files = response.data.files for (var key in files) { files[key].foldername = this.folder.foldername } this.files_in_folder = files }) }, last_page() { this.offset = this.offset - this.limit if (this.offset < 0) { this.offset = 0 return } this.search_folders() }, next_page() { this.offset = this.offset + this.limit this.search_folders() }, first_search_folders() { this.offset = 0 this.search_folders() }, search_folders() { axios.post('/api/v1/search_folders', { foldername: this.search_foldernames, limit: this.limit, offset: this.offset, }).then((response) => { this.folders = response.data.folders }) }, }, } const component_token = { progs: ['token'], emits: ['set_token'], data() { return { token_tmp: "", } }, template: `
Token
`, methods: { emit_set_token() { this.$emit('set_token', this.token_tmp) }, }, } const component_manage= { props: ['token'], emits: ['set_token'], data() { return { } }, template: `

关于本站

本站是 MSW Project 的一个应用,希望以个人之力分享被隐藏在历史中的音乐。

自己是V家厨,喜欢的p主包括 wonder-k, buzzG, *luna 等,但却因为种种原因淹没在主流音乐APP的曲库中。本站的初衷是为了让那些知名度低的 VOCALOID / ACG / 东方曲,能够被更多有缘人听到,同时有一个跨平台的工具,能够在低网速的条件下享受硬盘中的无损音乐。

`, } const component_manage_database = { props: ['token'], data() { return { root: "", pattern: [".flac", ".mp3"], pattern_tmp: "", s: "", } }, template: `
Root
Pattern List
{{ p }}
Status {{ s }}
`, methods: { add_pattern() { this.pattern.push(this.pattern_tmp) this.pattern_tmp = "" }, reset_database() { axios.post('/api/v1/reset', { token: this.token, }).then((response) => { this.s = response.data.status }).catch((err) => { this.s = err.response.data.status }) }, update_database() { this.s = "Updating..." axios.post('/api/v1/walk', { token: this.token, root: this.root, pattern: this.pattern, }).then((response) => { this.s = response.data.status }).catch((err) => { this.s = err.response.data.status }) } }, } const component_file_dialog = { props: ['file', 'show_dialog'], emits: ['play_audio', 'close_dialog'], template: `

{{ file.filename }}

Download 使用 Axios 异步下载
Play 调用网页播放器播放源文件
Stream 将串流播放稍低码率的文件

`, data() { return { download_loaded: 0, disabled: false, } }, methods: { emit_close_dialog() { this.$emit('close_dialog') }, emit_stream_audio() { this.file.play_back_type = 'stream', this.$emit("play_audio", this.file) this.emit_close_dialog() }, emit_play_audio() { console.log("pressed button") this.file.play_back_type = 'raw' this.$emit("play_audio", this.file) this.emit_close_dialog() }, download_file(file) { this.disabled = true axios({ url: '/api/v1/get_file', method: 'POST', responseType: 'blob', // important data: { id: file.id, }, onDownloadProgress: ProgressEvent => { this.download_loaded = ProgressEvent.loaded } }).then((response) => { const url = window.URL.createObjectURL(new Blob([response.data])); const link = document.createElement('a'); link.href = url; link.setAttribute('download', file.filename); document.body.appendChild(link); link.click(); this.download_loaded = 0 this.disabled = false this.emit_close_dialog() }) }, }, computed: { computed_download_status() { if (this.download_loaded === 0) { return 'Download' } else { return Math.round(this.download_loaded / this.file.filesize * 100) + '%' } }, }, } const component_file = { props: ['file'], emits: ['play_audio'], template: ` {{ file.filename }} {{ file.foldername }} {{ computed_readable_size }} `, data() { return { download_loaded: 0, disabled: false, show_dialog: false, } }, methods: { show_folder() { this.$router.push({ path: '/search_folders', query: { folder_id: this.file.folder_id, foldername: this.file.foldername, } }) }, close_dialog() { this.show_dialog = false }, dialog() { this.show_dialog = this.show_dialog ? false : true }, }, computed: { computed_readable_size() { let filesize = this.file.filesize if (filesize < 1024) { return filesize } if (filesize < 1024 * 1024) { return Math.round(filesize / 1024) + 'K' } if (filesize < 1024 * 1024 * 1024) { return Math.round(filesize / 1024 / 1024) + 'M' } if (filesize < 1024 * 1024 * 1024 * 1024) { return Math.round(filesize / 1024 / 1024 / 1024) + 'G' } }, }, } const component_audio_player = { data() { return { loop: true, ffmpeg_config: {}, } }, props: ["file"], template: `
{{ file.filename }} / {{ file.foldername }}

`, methods: { set_ffmpeg_config(ffmpeg_config) { this.ffmpeg_config = ffmpeg_config }, }, computed: { computed_playing_audio_file_url() { if (this.file.play_back_type === 'raw') { return '/api/v1/get_file_direct?id=' + this.file.id } else if (this.file.play_back_type === 'stream') { return '/api/v1/get_file_stream?id=' + this.file.id + '&config=' + this.ffmpeg_config.name } }, computed_show() { return this.file.id ? true : false }, }, } const component_search_files = { emits: ['play_audio'], template: `
{{ offset }}~{{ offset + files.length }}
Filename Folder Name Size Action
`, data() { return { search_filenames: '', files: [], offset: 0, limit: 10, playing_audio_file: {}, } }, methods: { first_search_files() { this.offset = 0 this.search_files() }, search_files() { axios.post('/api/v1/search_files', { filename: this.search_filenames, limit: this.limit, offset: this.offset, }).then((response) => { this.files = response.data.files }) }, last_page() { this.offset = this.offset - this.limit if (this.offset < 0) { this.offset = 0 return } this.search_files() }, next_page() { this.offset = this.offset + this.limit this.search_files() }, }, } const component_get_random_files = { emits: ['play_audio', 'set_token'], data() { return { files: [], } }, template: `
Filename Folder Name Size Action
`, mounted() { this.get_random_files() }, methods: { get_random_files() { axios.get('/api/v1/get_random_files' ).then(response => { this.files = response.data.files; }) } }, } const component_stream_config = { emits: ['set_ffmpeg_config'], data() { return { ffmpeg_config_list: [], selected_ffmpeg_config: {}, } }, template: `
`, mounted() { axios.get('/api/v1/get_ffmpeg_config_list', ).then(response => { var ffmpeg_configs = response.data.ffmpeg_configs var tmp_list = [] for (var key in ffmpeg_configs) { tmp_list.push(ffmpeg_configs[key]) } tmp_list.sort() this.ffmpeg_config_list = tmp_list this.selected_ffmpeg_config = this.ffmpeg_config_list[0] }).catch(err => { this.ffmpeg_config_list = [{name: 'No avaliable config'}] this.selected_ffmpeg_config = this.ffmpeg_config_list[0] }) }, watch: { selected_ffmpeg_config(n, o) { this.$emit('set_ffmpeg_config', this.selected_ffmpeg_config) }, }, } const routes = [ { path: '/', component: component_get_random_files}, { path: '/search_files', component: component_search_files}, { path: '/search_folders', component: component_search_folders}, { path: '/manage', component: component_manage}, ] const router = VueRouter.createRouter({ history: VueRouter.createWebHashHistory(), routes, }) const app = Vue.createApp({ data() { return { playing_audio_file: {}, token: "default token", } }, methods: { set_token(token) { this.token = token }, play_audio(file) { console.log(file) this.playing_audio_file = file }, }, }) app.component('component-search-folders', component_search_folders) app.component('component-manage', component_manage) app.component('component-file', component_file) app.component('component-audio-player', component_audio_player) app.component('component-search-files', component_search_files) app.component('component-get-random-files', component_get_random_files) app.component('component-file-dialog', component_file_dialog) app.component('component-token', component_token) app.component('component-stream-config', component_stream_config) app.component('component-manage-database', component_manage_database) app.use(router) app.mount('#app')