Merge branch 'master' of git.flexites.org:Students/ITRadio

This commit is contained in:
Mike0001-droid 2024-06-24 09:26:05 +05:00
commit 3568559bdb
20 changed files with 295 additions and 41 deletions

View File

@ -7,7 +7,7 @@ ROBOTS_USER_AGENT=*
ROBOTS_ALLOW=
ROBOTS_DISALLOW=["/"]
SERVICE_SELF_URL=//it-radio.flexidev.ru
SERVICE_URL=//82.97.242.49
SERVICE_URL=//it-radio.flexidev.ru
SERVICE_URL_AUDIO=//82.97.242.49:10084
SERVICE_PROTOCOL=http
SERVICE_PORT=8000

View File

@ -6,11 +6,12 @@ CACHE_STORAGE=tempStorage
ROBOTS_USER_AGENT=*
ROBOTS_ALLOW=
ROBOTS_DISALLOW=["/"]
SERVICE_SELF_URL=//tender.alidi.ru
SERVICE_URL=//backend.tender.alidi.ru
SERVICE_SELF_URL=//itradio.team
SERVICE_URL=//itradio.team
SERVICE_URL_AUDIO=//82.97.242.49:10084
SERVICE_PROTOCOL=https
SERVICE_PORT=8000
SERVICE_API=
SERVICE_API=/api
SERVICE_ON_LOCAL=false
SENTRY_DSN=https://e6dd82de128240cd8858fc6d47a0fff9@glitchtip.flexidev.ru/6
METRIKA_ID=

View File

@ -11,6 +11,7 @@
"serve": "npx cross-env NODE_ENV=development quasar dev",
"serve:ssr": "quasar dev -m ssr",
"build": "npx cross-env NODE_ENV=development quasar build",
"build:prod": "npx cross-env NODE_ENV=production quasar build",
"build:ssr": "quasar build -m ssr",
"build:dev": "quasar build",
"build:ssr:dev": "npx cross-env NODE_ENV=development quasar build -m ssr"

View File

@ -43,6 +43,9 @@
border: 1px solid var(--color-primary);
}
}
&.m--hidden{
display: none;
}
}
&__checkbox {
&-label{

View File

@ -1,6 +1,40 @@
.playlist {
position: relative;
z-index: 2;
&__header{
display: flex;
align-items: center;
gap: calc(var(--space-between-block) / 2);
margin-bottom: var(--space-between-block);
}
&__title{
font-size: 32px;
margin: 0;
padding: 0;
&.m--margin{
margin-bottom: 1rem;
}
}
&__back{
width: 30px;
height: 30px;
background: svg-load('./assets/img/icon/arrow-right.svg', stroke=$color-white) no-repeat 100%;
cursor: url("./assets/img/icon/cursor.svg"), auto;
transition: all .3s ease;
&:hover{
background: svg-load('./assets/img/icon/arrow-right.svg', stroke=$color-primary) no-repeat 100%;
}
}
&__edit{
width: 30px;
height: 30px;
background: svg-load('./assets/img/icon/ellipsis.svg', fill=$color-white) no-repeat 100%;
cursor: url("./assets/img/icon/cursor.svg"), auto;
transition: all .3s ease;
&:hover{
background: svg-load('./assets/img/icon/ellipsis.svg', fill=$color-primary) no-repeat 100%;
}
}
&-roster {
display: flex;
flex-wrap: wrap;
@ -31,6 +65,27 @@
background-image: var(--linear-gradient);
margin-bottom: 1rem;
}
&__upload{
cursor: url("./assets/img/icon/cursor.svg"), auto;
border: none;
padding: 0;
background-clip: text;
color: transparent;
background-image: var(--linear-gradient-highlight);
margin: 0 0 var(--space-between-block);
transition: all .3s ease;
display: flex;
gap: 10px;
&:before{
content: '';
width: 20px;
height: 20px;
background: svg-load('./assets/img/icon/paper-clip.svg', fill=$color-primary) no-repeat 100%;
}
&:hover{
color: var(--color-white);
}
}
}
&-item {

View File

@ -0,0 +1,4 @@
<svg width="30" height="30" viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M25.3125 15H4.6875" stroke="current" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M13.125 6.5625L4.6875 15L13.125 23.4375" stroke="current" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 352 B

View File

@ -0,0 +1,5 @@
<svg width="18" height="4" viewBox="0 0 18 4" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="2" cy="2" r="2" fill="current"/>
<circle cx="9" cy="2" r="2" fill="current"/>
<circle cx="16" cy="2" r="2" fill="current"/>
</svg>

After

Width:  |  Height:  |  Size: 237 B

View File

@ -0,0 +1,3 @@
<svg width="26" height="26" viewBox="0 0 26 26" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M2 6.33333H24M10.25 11.6667V19.6667M15.75 11.6667V19.6667M3.375 6.33333L4.75 22.3333C4.75 23.0406 5.03973 23.7189 5.55546 24.219C6.07118 24.719 6.77065 25 7.5 25H18.5C19.2293 25 19.9288 24.719 20.4445 24.219C20.9603 23.7189 21.25 23.0406 21.25 22.3333L22.625 6.33333M8.875 6.33333V2.33333C8.875 1.97971 9.01987 1.64057 9.27773 1.39052C9.53559 1.14048 9.88533 1 10.25 1H15.75C16.1147 1 16.4644 1.14048 16.7223 1.39052C16.9801 1.64057 17.125 1.97971 17.125 2.33333V6.33333" stroke="current" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 667 B

View File

@ -0,0 +1,14 @@
<svg width="20" height="21" viewBox="0 0 20 21" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_580_587)">
<path d="M3.264 9.07899C3.20042 9.14379 3.12456 9.19526 3.04085 9.23039C2.95715 9.26553 2.86728 9.28363 2.7765 9.28363C2.68572 9.28363 2.59585 9.26553 2.51215 9.23039C2.42844 9.19526 2.35258 9.14379 2.289 9.07899C2.15959 8.94733 2.08707 8.7701 2.08707 8.58549C2.08707 8.40088 2.15959 8.22365 2.289 8.09199L8.32 1.99999C9.68 0.943991 11.048 0.436991 12.41 0.505991C14.126 0.593991 15.462 1.24799 16.596 2.32099C17.752 3.41499 18.5 4.97599 18.5 6.86799C18.5 8.31999 18.078 9.59799 17.187 10.732L8.684 19.492C7.824 20.197 6.868 20.538 5.844 20.497C4.544 20.443 3.577 20.023 2.858 19.312C2.016 18.481 1.5 17.46 1.5 16.087C1.5 14.995 1.877 13.987 2.655 13.041L10.139 5.39999C10.739 4.75999 11.326 4.37999 11.926 4.28799C12.3265 4.22492 12.7363 4.26074 13.1197 4.39233C13.5032 4.52392 13.8487 4.7473 14.126 5.04299C14.658 5.60599 14.886 6.30799 14.806 7.10699C14.751 7.65199 14.528 8.15399 14.118 8.63499L7.238 15.683C7.17483 15.748 7.09935 15.7998 7.01596 15.8354C6.93256 15.871 6.84292 15.8896 6.75226 15.8901C6.6616 15.8907 6.57173 15.8732 6.4879 15.8387C6.40408 15.8041 6.32796 15.7532 6.264 15.689C6.13378 15.5581 6.06019 15.3813 6.05906 15.1967C6.05794 15.0121 6.12938 14.8344 6.258 14.702L13.105 7.68999C13.305 7.45499 13.41 7.21799 13.435 6.96599C13.475 6.56599 13.379 6.27099 13.13 6.00799C13.0042 5.8733 12.8471 5.77177 12.6727 5.71245C12.4982 5.65314 12.3118 5.63786 12.13 5.66799C11.887 5.70499 11.547 5.92599 11.128 6.37199L3.675 13.979C3.138 14.634 2.878 15.329 2.878 16.088C2.878 17.042 3.223 17.725 3.82 18.314C4.295 18.784 4.94 19.064 5.9 19.104C6.58 19.131 7.21 18.906 7.758 18.462L16.155 9.81199C16.8 8.98499 17.122 8.01199 17.122 6.86899C17.122 5.38699 16.545 4.18499 15.654 3.34099C14.744 2.47899 13.704 1.97099 12.341 1.90099C11.333 1.84899 10.276 2.24099 9.224 3.04699L3.264 9.07899Z" fill="url(#paint0_linear_580_587)"/>
</g>
<defs>
<linearGradient id="paint0_linear_580_587" x1="18.9474" y1="3.8332" x2="-0.25315" y2="6.91661" gradientUnits="userSpaceOnUse">
<stop stop-color="#5E5BFC"/>
<stop offset="1" stop-color="#871DF0"/>
</linearGradient>
<clipPath id="clip0_580_587">
<rect width="20" height="20" fill="white" transform="translate(0 0.5)"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@ -0,0 +1,4 @@
<svg width="63" height="63" viewBox="0 0 63 63" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="26.6543" width="8.48077" height="63" rx="4.24038" fill="current"/>
<rect x="63" y="26.6537" width="8.48077" height="63" rx="4.24038" transform="rotate(90 63 26.6537)" fill="current"/>
</svg>

After

Width:  |  Height:  |  Size: 296 B

View File

@ -0,0 +1,10 @@
<svg width="220" height="220" viewBox="0 0 220 220" fill="current" xmlns="http://www.w3.org/2000/svg">
<rect width="220" height="220" fill="url(#paint0_linear_365_2426)"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M130.768 49.5044C117.885 53.6039 101.991 58.6307 95.447 60.6741C88.9032 62.7175 82.5089 65.1543 81.2373 66.0897C76.4143 69.6352 76.4849 68.9812 76.4849 110.279V147.646L72.581 146.599C62.2894 143.84 51.2803 148.827 47.8366 157.808C46.0245 162.535 47.1897 167.867 51.0066 172.309C59.8333 182.579 79.4333 180.67 84.7442 169.024C86.0158 166.235 86.1206 163.497 86.1355 132.614L86.1519 99.218L87.825 98.4618C90.1041 97.4316 149.448 78.8325 150.846 78.7103C151.813 78.6259 151.987 81.7647 152.158 102.217L152.354 125.822L150.67 125.28C147.49 124.256 138.36 123.996 135.745 124.856C121.41 129.568 118.359 145.554 130.288 153.443C138.924 159.154 149.546 158.441 156.729 151.668C159.142 149.392 160.644 147.234 161.181 145.271C161.727 143.275 161.993 126.525 161.996 93.9476L162 45.5864L160.174 43.7689C159.063 42.6616 157.537 41.9706 156.271 42.001C155.128 42.0284 143.651 45.405 130.768 49.5044Z" fill="current"/>
<defs>
<linearGradient id="paint0_linear_365_2426" x1="225.789" y1="36.6667" x2="-20.311" y2="83.1634" gradientUnits="userSpaceOnUse">
<stop stop-color="#5E5BFC"/>
<stop offset="1" stop-color="#871DF0"/>
</linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -0,0 +1,9 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M17 17L21 21M3 11C3 13.1217 3.84285 15.1566 5.34315 16.6569C6.84344 18.1571 8.87827 19 11 19C13.1217 19 15.1566 18.1571 16.6569 16.6569C18.1571 15.1566 19 13.1217 19 11C19 8.87827 18.1571 6.84344 16.6569 5.34315C15.1566 3.84285 13.1217 3 11 3C8.87827 3 6.84344 3.84285 5.34315 5.34315C3.84285 6.84344 3 8.87827 3 11Z" stroke="url(#paint0_linear_557_1549)" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<defs>
<linearGradient id="paint0_linear_557_1549" x1="21.4737" y1="6" x2="1.33819" y2="9.80428" gradientUnits="userSpaceOnUse">
<stop stop-color="#5E5BFC"/>
<stop offset="1" stop-color="#871DF0"/>
</linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 760 B

View File

@ -25,9 +25,11 @@
</template>
</span>
</div>
<q-skeleton v-if="loaderPlay" class="player__favorites m--skeleton"/>
<div v-else class="player__favorites" :class="[isFavorites&&'m--active']" @click="handlerFavorites">
</div>
<template v-if="user?.id">
<q-skeleton v-if="loaderPlay" class="player__favorites m--skeleton"/>
<div v-else class="player__favorites" :class="[isFavorites&&'m--active']" @click="handlerFavorites">
</div>
</template>
<div class="player__tools">
<q-skeleton v-if="loaderPlay" class="player__tools m--skeleton"/>
<FormKit

View File

@ -1,7 +1,8 @@
<template>
<div class="playlist-item" @click="selectPlaylist">
<div class="playlist-item__cover"></div>
<div>{{playlist.title}}</div>
<div>{{playlist.name}}</div>
<div @click="editPlaylist">...</div>
</div>
</template>
@ -15,6 +16,9 @@ export default {
}
},
methods:{
editPlaylist(){
this.$emit('editPlaylist', this.playlist)
},
selectPlaylist(){
this.$emit('selectPlaylist', this.playlist)
}

View File

@ -5,6 +5,7 @@
:key="`playlist_${item.id}`"
:playlist="item"
@selectPlaylist="selectPlaylist"
@editPlaylist="editPlaylist"
/>
<div class="playlist-item m--create" @click="createPlaylist">
<div class="playlist-item__cover"></div>
@ -31,6 +32,9 @@ export default {
},
selectPlaylist(params) {
this.$router.push({name: 'playlist', params: {id: params.id}})
},
editPlaylist(params) {
this.$router.push({name: 'playlist-edit', params: {id: params.id}})
}
}
}

View File

@ -21,7 +21,7 @@
</div>
<div class="song-item__tools">
<button class="button song-item__btn m--small m--favorites" @click.stop="removeSong"></button>
<button class="button song-item__btn m--small m--add" :class="songAlreadyAddPlaylist&&'m--already'" @click.stop="songAlreadyAddPlaylist?removeToPlaylist:addPlaylist"></button>
<button class="button song-item__btn m--small m--add" :class="songAlreadyAddPlaylist&&'m--already'" @click.stop="songAlreadyAddPlaylist?removeToPlaylist():addPlaylist()"></button>
</div>
</div>
</template>

View File

@ -132,6 +132,21 @@ export default class extends REST {
throw new RESTError(error, 'Ошибка при получении плейлистов');
});
}
static removeSongToPlaylist(params) {
return this._post(`radio/playlists/delete_song_with_playlist`, {}, params).then((data) => {
return data;
}).catch((error) => {
throw new RESTError(error, 'Ошибка при удаления треков из плейлиста');
});
}
static updatePlaylist(params) {
return this._post(`radio/playlists/update_playlist`, {}, params).then((data) => {
return data;
}).catch((error) => {
throw new RESTError(error, 'Ошибка при удаления треков из плейлиста');
});
}
static createPlaylists() {
return this._post(`radio/playlists/create_playlist`, {}, {}).then((data) => {
return data;

View File

@ -8,7 +8,18 @@
{ name: 'Добавление плейлиста', route: { name: 'playlist-create' } }:
{ name: 'Редактирование плейлиста', route: { name: 'playlist-edit' } },
]"/>
<h1 class="h2">{{ $route.name==='playlist-create'?'Новый плейлист':playlist.name }}</h1>
<h1 class="h2 playlist__title m--margin">{{ $route.name === 'playlist-create' ? 'Новый плейлист' : playlist.name }}</h1>
<button class="playlist-edit__upload" @click="handlerUploadCover">Добавить обложку</button>
<div class="field__input m--hidden">
<input
id="cover"
ref="coverInput"
accept=".jpg,.png,.svg"
class="input"
type="file"
name="logo"
>
</div>
<FormKit
v-model="playlist.name"
type="text"
@ -25,7 +36,12 @@
Загрузка данных
</div>
</template>
<SongList v-else-if="songs.length>0" :songList="songs" class="m--column" @addPlaylist="addPlaylist"/>
<SongList
v-else-if="songsFiltered.length>0"
:songList="songsFiltered"
class="m--column"
@addPlaylist="addPlaylist"
/>
<div v-else>Каталог музыки пуст!</div>
</div>
<div class="playlist-edit__item">
@ -36,7 +52,13 @@
Загрузка данных
</div>
</template>
<SongList v-else-if="playlist.song?.length>0" :songList="playlist.song" class="m--column" :songAlreadyAdd="true" @removePlaylist="removePlaylist"/>
<SongList
v-else-if="playlist.song?.length>0"
:songList="playlist.song"
class="m--column"
:songAlreadyAdd="true"
@removePlaylist="removePlaylist"
/>
<div v-else>Добавьте музыку в плейлист!</div>
</div>
</div>
@ -64,44 +86,93 @@ export default {
this.getAllSong();
this.getPlaylist();
},
methods:{
getPlaylist(){
computed: {
songsFiltered() {
return this.songs.filter(song => {
const alreadyAdd = this.playlist.song.find(item => item.azura_id === song.azura_id)
return !alreadyAdd
})
}
},
methods: {
getPlaylist() {
this.showLoaderPlaylist = true;
app.getPlaylist(this.$route.params.id).then(res=>{
app.getPlaylist(this.$route.params.id).then(res => {
this.showLoaderPlaylist = false;
this.playlist = res;
}).catch(err=>{
}).catch(err => {
this.showLoaderPlaylist = false;
console.error(err)
})
},
getAllSong(){
getAllSong() {
this.showLoaderSongs = true;
app.getAllSong().then(res=>{
app.getAllSong().then(res => {
this.showLoaderSongs = false;
this.songs = res;
}).catch(err=>{
}).catch(err => {
this.showLoaderSongs = false;
console.error(err)
})
},
addPlaylist(song){
addPlaylist(song) {
console.log(song)
const params = {
playlist_id: this.$route.params.id,
...song
}
this.showLoaderSongs = true;
this.showLoaderPlaylist = true;
app.addSongToPlaylist(params).then(() => {
this.showLoaderPlaylist = false;
this.showLoaderSongs = false;
this.getPlaylist();
}).catch(err => {
this.showLoaderPlaylist = false;
this.showLoaderSongs = false;
console.error(err)
})
},
removePlaylist(song) {
const params = {
playlist_id: this.$route.params.id,
azura_id: song.azura_id
}
this.showLoaderSongs = true;
this.showLoaderPlaylist = true;
app.addSongToPlaylist(params).then(()=>{
app.removeSongToPlaylist(params).then(() => {
this.showLoaderPlaylist = false;
this.showLoaderSongs = false;
this.getPlaylist();
}).catch(err=>{
}).catch(err => {
this.showLoaderPlaylist = false;
this.showLoaderSongs = false;
console.error(err)
})
},
removePlaylist(){
handlerUploadCover(){
let logoInput = this.$refs.coverInput;
let click = new MouseEvent('click');
logoInput.onchange = this.uploadCover;
logoInput.dispatchEvent(click);
},
uploadCover(event){
let file = event.target.files ? event.target.files[0] : null
if (file) {
const data = new FormData();
data.append('playlist_art', file);
data.append('playlist_id', this.$route.params.id);
app.updatePlaylist(data).then((res) => {
this.showLoaderPlaylist = false;
this.showLoaderSongs = false;
this.playlist = res;
}).catch(err => {
this.showLoaderPlaylist = false;
this.showLoaderSongs = false;
console.error(err)
})
}
}
}
}

View File

@ -1,11 +1,55 @@
<template>
<div class="playlist">
<template v-if="showLoaderPlaylist">
<div class="loader">
<div class="spinner"/>
Загрузка данных
</div>
</template>
<template v-else>
<div class="playlist__header">
<div class="playlist__back" @click="handlerBack"></div>
<div class="h2 playlist__title">{{ playlist.name }}</div>
<div class="playlist__edit" @click="next({name: 'playlist-edit', params:{id:this.playlist.id}})"></div>
</div>
<SongList :songList="playlist.song" :songAlreadyAdd="true"/>
</template>
</div>
</template>
<script>
import {app} from "@/services";
import SongList from "@/components/song-list.vue";
export default {
name: 'playlist'
name: 'playlist',
components: {SongList},
data() {
return {
showLoaderPlaylist: false,
playlist: {}
}
},
created() {
this.getPlaylist();
},
methods: {
getPlaylist() {
this.showLoaderPlaylist = true;
app.getPlaylist(this.$route.params.id).then(res => {
this.showLoaderPlaylist = false;
this.playlist = res;
}).catch(err => {
this.showLoaderPlaylist = false;
console.error(err)
})
},
handlerBack() {
this.$router.go(-1);
},
next(params) {
this.$router.push(params);
}
}
}
</script>

View File

@ -1,6 +1,6 @@
<template>
<div class="app__content profile">
<template v-if="$route.name !== 'playlist-edit'">
<template v-if="$route.name !== 'playlist-edit' && $route.name !== 'playlist-create'">
<AppBreadcrumbs
:breadcrumbs="[
{ name: 'Главная', route: { name: 'home' } },
@ -89,21 +89,26 @@ export default {
}
},
watch: {
'$route.hash': {
'$route': {
immediate: true,
handler(to) {
if (to) {
this.currentTabsItem = to?.replace('#', '') || 'music';
} else {
this.currentTabsItem = 'music';
handler(to, from) {
if (!from && to?.hash && to?.name==='"profile"'){
console.log('1')
this.currentTabsItem = to?.hash.replace('#', '') || 'music';
}
},
},
'$route.name': {
immediate: false,
handler(to) {
if (to === 'playlist') {
this.currentTabsItem = 'playlists'
if (to?.hash !== from?.hash && to?.name === from?.name || !from?.name && !from?.hash){
console.log('2')
if (to.hash) {
this.currentTabsItem = to?.hash.replace('#', '') || 'music';
} else {
this.currentTabsItem = 'music';
}
}
else {
console.log('3')
if (to?.name === 'playlist') {
this.currentTabsItem = 'playlists'
}
}
},
},
@ -156,7 +161,7 @@ export default {
},
createPlayList() {
app.createPlaylists().then(res=>{
this.$router.push({name: 'playlist-edit'});
this.$router.push({name: 'playlist-create', params: {id: res.id}});
}).catch(err=>{
console.error(err)
})