generated from VLADIMIR/template_frontend
up
This commit is contained in:
@@ -1,23 +1,35 @@
|
||||
<script setup lang="ts">
|
||||
import { NAlert, NButton, NFlex, NTag } from 'naive-ui'
|
||||
import { NAlert, NButton, NFlex, NInput, NInputNumber, NSelect, NSwitch, NTag, NUpload, type UploadFileInfo } from 'naive-ui'
|
||||
import { ref } from 'vue'
|
||||
|
||||
import type { ScreenState } from '@/api/generated/crabs/evening_detective_server'
|
||||
import type { MusicState, Playlist, ScreenState } from '@/api/generated/crabs/evening_detective_server'
|
||||
import ScreenBindingModal from '@/components/ScreenBindingModal.vue'
|
||||
import UiBlock from '@/components/UiBlock.vue'
|
||||
|
||||
const props = defineProps<{
|
||||
screens: ScreenState[]
|
||||
screenBinding: boolean
|
||||
playlists: Playlist[]
|
||||
music?: MusicState
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
bind: [screenID: string, accessToken: string]
|
||||
setSound: [screen: ScreenState]
|
||||
unbind: [screen: ScreenState]
|
||||
setMusic: [change: { playlistID?: number; trackIndex?: number; positionMs?: number; playback?: MusicState['playback']; loop?: boolean; volume?: number }]
|
||||
createPlaylist: [name: string]
|
||||
deletePlaylist: [id: number]
|
||||
uploadTrack: [file: File]
|
||||
deleteTrack: [id: number]
|
||||
}>()
|
||||
|
||||
const showBindingModal = ref(false)
|
||||
const playlistName = ref('')
|
||||
|
||||
function uploadTrack(options: { file: UploadFileInfo }) {
|
||||
if (options.file.file) emit('uploadTrack', options.file.file)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -58,6 +70,79 @@ const showBindingModal = ref(false)
|
||||
:binding="props.screenBinding"
|
||||
@scanned="(screenID, accessToken) => emit('bind', screenID, accessToken)"
|
||||
/>
|
||||
<UiBlock class="music-block">
|
||||
<p class="screens-title">Музыка</p>
|
||||
<n-flex align="center" wrap class="playlist-actions">
|
||||
<n-input v-model:value="playlistName" placeholder="Новый плейлист" style="max-width: 220px" />
|
||||
<n-button
|
||||
size="small"
|
||||
:disabled="!playlistName.trim()"
|
||||
@click="emit('createPlaylist', playlistName.trim()); playlistName = ''"
|
||||
>
|
||||
Создать
|
||||
</n-button>
|
||||
<n-button
|
||||
v-if="props.music?.playlist?.ID"
|
||||
size="small"
|
||||
type="error"
|
||||
ghost
|
||||
@click="emit('deletePlaylist', props.music.playlist.ID)"
|
||||
>
|
||||
Удалить плейлист
|
||||
</n-button>
|
||||
<n-upload accept=".mp3,audio/mpeg" :default-upload="false" :show-file-list="false" @change="uploadTrack">
|
||||
<n-button size="small">Добавить MP3</n-button>
|
||||
</n-upload>
|
||||
</n-flex>
|
||||
<n-flex align="center" wrap>
|
||||
<n-select
|
||||
:value="props.music?.playlist?.ID"
|
||||
:options="props.playlists.map((playlist) => ({ label: playlist.name, value: playlist.ID }))"
|
||||
placeholder="Плейлист"
|
||||
clearable
|
||||
style="min-width: 220px"
|
||||
@update:value="(value) => emit('setMusic', { playlistID: value || 0, trackIndex: 0, playback: 'MUSIC_PLAYBACK_STOPPED' })"
|
||||
/>
|
||||
<n-button
|
||||
v-if="props.music?.playlist?.tracks?.[props.music.trackIndex || 0]?.ID"
|
||||
size="small"
|
||||
type="error"
|
||||
ghost
|
||||
@click="emit('deleteTrack', props.music.playlist.tracks[props.music.trackIndex || 0].ID!)"
|
||||
>
|
||||
Удалить трек
|
||||
</n-button>
|
||||
<n-select
|
||||
v-if="props.music?.playlist?.tracks?.length"
|
||||
:value="props.music.trackIndex"
|
||||
:options="props.music.playlist.tracks.map((track, index) => ({ label: track.name || track.filename || `Трек ${index + 1}`, value: index }))"
|
||||
style="min-width: 220px"
|
||||
@update:value="(value) => emit('setMusic', { trackIndex: value })"
|
||||
/>
|
||||
<n-button size="small" @click="emit('setMusic', { playback: 'MUSIC_PLAYBACK_PLAYING' })">Старт</n-button>
|
||||
<n-button size="small" @click="emit('setMusic', { playback: 'MUSIC_PLAYBACK_PAUSED' })">Пауза</n-button>
|
||||
<n-button size="small" @click="emit('setMusic', { playback: 'MUSIC_PLAYBACK_STOPPED', positionMs: 0 })">Стоп</n-button>
|
||||
<n-input-number
|
||||
:value="props.music?.volume"
|
||||
:min="0"
|
||||
:max="100"
|
||||
:step="5"
|
||||
size="small"
|
||||
style="width: 110px"
|
||||
@update:value="(value) => value != null && emit('setMusic', { volume: value })"
|
||||
>
|
||||
<template #prefix>Громкость</template>
|
||||
</n-input-number>
|
||||
<n-switch
|
||||
:value="props.music?.loop"
|
||||
:round="false"
|
||||
@update:value="(value) => emit('setMusic', { loop: value })"
|
||||
>
|
||||
<template #checked>Loop</template>
|
||||
<template #unchecked>Loop</template>
|
||||
</n-switch>
|
||||
</n-flex>
|
||||
</UiBlock>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
@@ -71,6 +156,14 @@ const showBindingModal = ref(false)
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.music-block {
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
.playlist-actions {
|
||||
margin: 8px 0;
|
||||
}
|
||||
|
||||
.screen-row {
|
||||
align-items: center;
|
||||
border-top: 1px solid rgb(255 255 255 / 10%);
|
||||
|
||||
Reference in New Issue
Block a user