106 lines
2.6 KiB
Vue
106 lines
2.6 KiB
Vue
|
|
<template>
|
||
|
|
<form @submit.prevent="handleUpload" class="upload-form">
|
||
|
|
<div class="form-group">
|
||
|
|
<label>MP3 файл (макс. 10MB)</label>
|
||
|
|
<input
|
||
|
|
type="file"
|
||
|
|
accept="audio/mpeg,audio/mp3"
|
||
|
|
@change="handleFileSelect"
|
||
|
|
required
|
||
|
|
ref="fileInput"
|
||
|
|
/>
|
||
|
|
<small class="hint">Название и исполнитель будут взяты из тегов файла</small>
|
||
|
|
</div>
|
||
|
|
<div class="form-group">
|
||
|
|
<label>Название <span class="optional">(необязательно)</span></label>
|
||
|
|
<input type="text" v-model="title" placeholder="Оставьте пустым для автоопределения" />
|
||
|
|
</div>
|
||
|
|
<div class="form-group">
|
||
|
|
<label>Исполнитель <span class="optional">(необязательно)</span></label>
|
||
|
|
<input type="text" v-model="artist" placeholder="Оставьте пустым для автоопределения" />
|
||
|
|
</div>
|
||
|
|
<p v-if="error" class="error-message">{{ error }}</p>
|
||
|
|
<button type="submit" class="btn-primary" :disabled="uploading">
|
||
|
|
{{ uploading ? 'Загрузка...' : 'Загрузить' }}
|
||
|
|
</button>
|
||
|
|
</form>
|
||
|
|
</template>
|
||
|
|
|
||
|
|
<script setup>
|
||
|
|
import { ref } from 'vue'
|
||
|
|
import { useTracksStore } from '../../stores/tracks'
|
||
|
|
|
||
|
|
const emit = defineEmits(['uploaded'])
|
||
|
|
|
||
|
|
const tracksStore = useTracksStore()
|
||
|
|
|
||
|
|
const title = ref('')
|
||
|
|
const artist = ref('')
|
||
|
|
const file = ref(null)
|
||
|
|
const fileInput = ref(null)
|
||
|
|
const error = ref('')
|
||
|
|
const uploading = ref(false)
|
||
|
|
|
||
|
|
function handleFileSelect(e) {
|
||
|
|
const selectedFile = e.target.files[0]
|
||
|
|
if (!selectedFile) return
|
||
|
|
|
||
|
|
// Check file size (10MB)
|
||
|
|
if (selectedFile.size > 10 * 1024 * 1024) {
|
||
|
|
error.value = 'Файл слишком большой (макс. 10MB)'
|
||
|
|
fileInput.value.value = ''
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
file.value = selectedFile
|
||
|
|
error.value = ''
|
||
|
|
}
|
||
|
|
|
||
|
|
async function handleUpload() {
|
||
|
|
if (!file.value) {
|
||
|
|
error.value = 'Выберите файл'
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
uploading.value = true
|
||
|
|
error.value = ''
|
||
|
|
|
||
|
|
try {
|
||
|
|
await tracksStore.uploadTrack(file.value, title.value, artist.value)
|
||
|
|
title.value = ''
|
||
|
|
artist.value = ''
|
||
|
|
file.value = null
|
||
|
|
fileInput.value.value = ''
|
||
|
|
emit('uploaded')
|
||
|
|
} catch (e) {
|
||
|
|
error.value = e.response?.data?.detail || 'Ошибка загрузки'
|
||
|
|
} finally {
|
||
|
|
uploading.value = false
|
||
|
|
}
|
||
|
|
}
|
||
|
|
</script>
|
||
|
|
|
||
|
|
<style scoped>
|
||
|
|
.upload-form {
|
||
|
|
display: flex;
|
||
|
|
flex-direction: column;
|
||
|
|
gap: 16px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.upload-form input[type="file"] {
|
||
|
|
padding: 10px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.hint {
|
||
|
|
color: #888;
|
||
|
|
font-size: 12px;
|
||
|
|
margin-top: 4px;
|
||
|
|
display: block;
|
||
|
|
}
|
||
|
|
|
||
|
|
.optional {
|
||
|
|
color: #666;
|
||
|
|
font-weight: normal;
|
||
|
|
}
|
||
|
|
</style>
|