diff --git a/src/App.vue b/src/App.vue index 19d2c6fac3d69b2d66680b7145d6cb1c51a1e1a9..34e64f59c18f5c57f4ddb23e45d7193f29c18028 100644 --- a/src/App.vue +++ b/src/App.vue @@ -17,7 +17,7 @@ color: #2c3e50; margin: 0; padding: 0; - + height: 100%; } ::-webkit-scrollbar { @@ -26,11 +26,14 @@ #opacity-bg, #opacity-bg1 { z-index: -1; + height: 100%; } html, body { margin: 0; padding: 0; + height: 100%; + width: 100%; overflow: hidden; } diff --git a/src/components/LeftSideBar.vue b/src/components/LeftSideBar.vue index 8461d0fdc14976403b741c3611050d7f711c3157..642e1f1da18f1a805fd1b27983d78cc866a50d1a 100644 --- a/src/components/LeftSideBar.vue +++ b/src/components/LeftSideBar.vue @@ -28,35 +28,35 @@ const userToken = ref(JSON.parse(sessionStorage.getItem('user-token'))); const currentUserId = ref(userToken.value.id); function toggleSideBar() { - isSideBarOpen = !isSideBarOpen; - sideBarWidth.value = isSideBarOpen ? criticalWidth : minWidth; + isSideBarOpen = !isSideBarOpen; + sideBarWidth.value = isSideBarOpen ? criticalWidth : minWidth; } function startResizing(event) { - event.preventDefault(); - const initialWidth = sideBarWidth.value; - const initialMouseX = event.clientX; - - const onMouseMove = (moveEvent) => { - sideBarWidth.value = initialWidth + (moveEvent.clientX - initialMouseX); - // 纭繚瀹藉害涓嶅皬浜庢渶灏忓€� - if (sideBarWidth.value <= criticalWidth) { - isSideBarOpen = false; - sideBarWidth.value = minWidth; - } - // 纭繚瀹藉害涓嶅ぇ浜庢渶澶у€� - else if (sideBarWidth.value >= maximumWidth) { - sideBarWidth.value = maximumWidth; - } else - isSideBarOpen = true; - }; - - const onMouseUp = () => { - window.removeEventListener('mousemove', onMouseMove); - window.removeEventListener('mouseup', onMouseUp); - }; - window.addEventListener('mousemove', onMouseMove); - window.addEventListener('mouseup', onMouseUp); + event.preventDefault(); + const initialWidth = sideBarWidth.value; + const initialMouseX = event.clientX; + + const onMouseMove = (moveEvent) => { + sideBarWidth.value = initialWidth + (moveEvent.clientX - initialMouseX); + // 纭繚瀹藉害涓嶅皬浜庢渶灏忓€� + if (sideBarWidth.value <= criticalWidth) { + isSideBarOpen = false; + sideBarWidth.value = minWidth; + } + // 纭繚瀹藉害涓嶅ぇ浜庢渶澶у€� + else if (sideBarWidth.value >= maximumWidth) { + sideBarWidth.value = maximumWidth; + } else + isSideBarOpen = true; + }; + + const onMouseUp = () => { + window.removeEventListener('mousemove', onMouseMove); + window.removeEventListener('mouseup', onMouseUp); + }; + window.addEventListener('mousemove', onMouseMove); + window.addEventListener('mouseup', onMouseUp); } function addAlbum() { @@ -91,6 +91,12 @@ onMounted(() => { }) }) +const popover1 = ref(null) + +const closePopover = () => { + popover1.value.hide(); +} + defineProps({ callParentFunction: Function }) @@ -107,15 +113,17 @@ defineProps({ </div> <el-popover v-if="isSideBarOpen" class="dropdown-options" + ref="popover1" :width="200" trigger="click" - :hide-after=0> + :hide-after=0 + popper-class="left-popover"> <template #reference> <div class="add-album"> <plus-icon class="plus-icon"/> </div> </template> - <ul> + <ul @click="closePopover"> <li @click="addAlbum">娣诲姞姝屽崟</li> </ul> </el-popover> @@ -133,22 +141,24 @@ defineProps({ <div class="musicAlbums" @mouseenter="()=>{hoverOnAlbum=true}" @mouseleave="()=>{hoverOnAlbum=false}" - :style="{ scrollbarWidth : hoverOnAlbum? 'auto':'none'}"> - + :style="{ scrollbarWidth : hoverOnAlbum? 'auto':'none'}" + > + <div v-if="musicAlbums !== undefined" v-for="album in musicAlbums" :key="album.id" @mouseenter="()=>{albumHoveredIndex = album.id}" @mouseleave="()=>{albumHoveredIndex = null}" :style="{backgroundColor: albumHoveredIndex === album.id ? '#1F1F1F' : '#171717' }" - class="musicAlbum-item"> + @click="emit('setCurrentPlaylist', album);" + class="musicAlbum-item"> <img :src="album.picPath" alt="playlist" class="musicAlbum-image" :style="{opacity:albumHoveredIndex === album.id ? 0.4 :1}" /> - <play-button @click="emit('setCurrentPlaylist', album);" v-if="albumHoveredIndex === album.id" + <play-button @click="" v-if="albumHoveredIndex === album.id" class="play-button"/> <div class="musicAlbum-description"> @@ -178,12 +188,13 @@ ul { list-style-type: none; margin: 0; border-radius: 10px; - padding: 12px 8px; + padding: 5px; } li { color: white; padding: 10px 12px; + border-radius: 10px; } li:hover { diff --git a/src/icon/dynamicPauseButton.vue b/src/icon/dynamicPauseButton.vue new file mode 100644 index 0000000000000000000000000000000000000000..79f4d03415ce6bd716f7d3723b043eea1f165576 --- /dev/null +++ b/src/icon/dynamicPauseButton.vue @@ -0,0 +1,9 @@ +<template> + <svg xmlns="http://www.w3.org/2000/svg" width="30px" height="30px" viewBox="0 0 24 24"><g fill="none" stroke="currentColor" stroke-dasharray="32" stroke-dashoffset="32" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"><path d="M7 6h2v12h-2Z"><animate fill="freeze" attributeName="stroke-dashoffset" dur="0.4s" values="32;0"/></path><path d="M15 6h2v12h-2Z"><animate fill="freeze" attributeName="stroke-dashoffset" begin="0.4s" dur="0.4s" values="32;0"/></path></g></svg> +</template> + +<script> +export default { + name: 'LineMdPause' +} +</script> \ No newline at end of file diff --git a/src/icon/pauseButton.vue b/src/icon/pauseButton.vue index 79f4d03415ce6bd716f7d3723b043eea1f165576..af03d22ad667770e18e1483581886bf1b146c78e 100644 --- a/src/icon/pauseButton.vue +++ b/src/icon/pauseButton.vue @@ -1,9 +1,11 @@ + + <template> - <svg xmlns="http://www.w3.org/2000/svg" width="30px" height="30px" viewBox="0 0 24 24"><g fill="none" stroke="currentColor" stroke-dasharray="32" stroke-dashoffset="32" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"><path d="M7 6h2v12h-2Z"><animate fill="freeze" attributeName="stroke-dashoffset" dur="0.4s" values="32;0"/></path><path d="M15 6h2v12h-2Z"><animate fill="freeze" attributeName="stroke-dashoffset" begin="0.4s" dur="0.4s" values="32;0"/></path></g></svg> + <svg xmlns="http://www.w3.org/2000/svg" width="30px" height="30px" viewBox="0 0 24 24"><path fill="currentColor" d="M16 19q-.825 0-1.412-.587T14 17V7q0-.825.588-1.412T16 5t1.413.588T18 7v10q0 .825-.587 1.413T16 19m-8 0q-.825 0-1.412-.587T6 17V7q0-.825.588-1.412T8 5t1.413.588T10 7v10q0 .825-.587 1.413T8 19"/></svg> </template> <script> export default { - name: 'LineMdPause' + name: 'MaterialSymbolsPauseRounded' } </script> \ No newline at end of file diff --git a/src/main.js b/src/main.js index 927275f59e530fd9ec6d4885b386b44eb727015a..b9ab5940a3476263a9d74ca9ad203fdfb33fa5ce 100644 --- a/src/main.js +++ b/src/main.js @@ -4,7 +4,8 @@ import App from './App.vue' import axios from 'axios' import ElementPlus from 'element-plus' import pinia from './store/store' - +import 'element-plus/dist/index.css' +import '@/style/ElStyle.css' // const { app, BrowserWindow } = require('electron'); // // const path = require('path'); // diff --git a/src/style/ElStyle.css b/src/style/ElStyle.css new file mode 100644 index 0000000000000000000000000000000000000000..04f1cd2ef2957abbdd77556d09e8fb255517d6c5 --- /dev/null +++ b/src/style/ElStyle.css @@ -0,0 +1,30 @@ +.reco-message{ + background-color: #FFFFFF; + border-radius: 4px; + padding: 20px 15px; +} +.el-message__content{ + font-size: 18px; + color: #000000 !important; + font-weight: bold; +} +.el-message__icon{ + margin: 5px; + font-size: 25px; + color: #1ed660 !important; +} +.el-popover{ + border-radius: 12px !important; + padding: 0 !important ; + border: #1f1f1f solid 1px !important; + box-shadow: #1f1f1f 2px 1px !important; +} +.el-card{ + height: 100%; + background-color: transparent; + border: none; +} +.el-card__body{ + height: 100%; + padding: 0; +} \ No newline at end of file diff --git a/src/utils/getBackgroundColor.js b/src/utils/getBackgroundColor.js index 81eb657f6dee965d95790dc9a73424fa65d4e729..db1b39771a75d3ce7434224526111949182848ca 100644 --- a/src/utils/getBackgroundColor.js +++ b/src/utils/getBackgroundColor.js @@ -1,4 +1,4 @@ -import {computed, ref} from "vue"; +import {ref} from "vue"; import ColorThief from "colorthief"; @@ -31,9 +31,8 @@ function getDominantColor(imageSrc, callback, alpha = 0.2) { }; } -function updateBackground (event) { - const imageSrc = event.target.src; - getDominantColor(imageSrc, (color) => { +function updateBackground (path) { + getDominantColor(path, (color) => { backgroundColor.value = color; }); } diff --git a/src/views/a.vue b/src/views/a.vue new file mode 100644 index 0000000000000000000000000000000000000000..30e58841b7d27fb01695a93e2a19e06822610a4a --- /dev/null +++ b/src/views/a.vue @@ -0,0 +1,412 @@ +<script setup> +import {defineEmits, onMounted, ref} from "vue"; +import musicAlbumOpened from "../icon/musicAlbumOpened.vue"; +import musicAlbumClosed from "../icon/musicAlbumClosed.vue"; +import searchIcon from "../icon/searchIcon.vue"; +import plusIcon from "../icon/plusIcon.vue"; +import playButton from "../icon/playButton.vue"; +import {getPlaylistsByUser} from "../api/playlist"; +import {ElPopover} from "element-plus"; + +const emit = defineEmits(); + +const musicAlbums = ref([]); + +let albumHoveredIndex = ref(null); +let hoverOnAlbum = ref(false); +let isSideBarOpen = ref(true); +let sideBarWidth = ref(250); +let user = ref("HanG"); +const criticalWidth = 180; +const maximumWidth = 310; +const minWidth = 75; + +/* + USER + */ +const userToken = ref(JSON.parse(sessionStorage.getItem('user-token'))); +const currentUserId = ref(userToken.value.id); + +function toggleSideBar() { + isSideBarOpen = !isSideBarOpen; + sideBarWidth.value = isSideBarOpen ? criticalWidth : minWidth; +} + +function startResizing(event) { + event.preventDefault(); + const initialWidth = sideBarWidth.value; + const initialMouseX = event.clientX; + + const onMouseMove = (moveEvent) => { + sideBarWidth.value = initialWidth + (moveEvent.clientX - initialMouseX); + // 纭繚瀹藉害涓嶅皬浜庢渶灏忓€� + if (sideBarWidth.value <= criticalWidth) { + isSideBarOpen = false; + sideBarWidth.value = minWidth; + } + // 纭繚瀹藉害涓嶅ぇ浜庢渶澶у€� + else if (sideBarWidth.value >= maximumWidth) { + sideBarWidth.value = maximumWidth; + } else + isSideBarOpen = true; + }; + + const onMouseUp = () => { + window.removeEventListener('mousemove', onMouseMove); + window.removeEventListener('mouseup', onMouseUp); + }; + window.addEventListener('mousemove', onMouseMove); + window.addEventListener('mouseup', onMouseUp); +} + +function addAlbum() { + //TODO锛氭坊鍔犳柊鐨勭┖姝屽崟 +} + +function toggleSearchBar() { + const input = document.querySelector(".search-input"); + input.classList.toggle('active'); // 鍒囨崲杈撳叆妗嗙殑鏄剧ず鐘舵€� + input.focus(); // 鐐瑰嚮鎼滅储鍥炬爣鍚庤仛鐒﹁緭鍏ユ +} + +function blurSearchBar() { + const input = document.querySelector(".search-input"); + if (input.classList.contains('active')) + input.classList.remove('active'); + +} + +function searchAlbum() { + const input = document.querySelector(".search-input").value; + // TODO:鎻愪氦琛ㄥ崟 +} + +onMounted(() => { + getPlaylistsByUser({ + user_id: currentUserId.value + }).then(res => { + musicAlbums.value = res.data.result || [] + }).catch(e => { + + }) +}) + +defineProps({ + callParentFunction: Function +}) +</script> + +<template> + <nav class="main-menu resizable-box" :style="{ width: sideBarWidth + 'px'}"> + <div class="top-control"> + <div class="toggle-button" @click="toggleSideBar"> + <music-album-opened v-if="isSideBarOpen"/> + <music-album-closed v-if="!isSideBarOpen"/> + <p style="margin-left: 15px;font:normal small-caps bold 20px Arial, sans-serif ;" v-if="isSideBarOpen"> + 闊充箰搴�</p> + </div> + + <el-popover v-if="isSideBarOpen" class="dropdown-options" + :width="200" + trigger="click" + :hide-after=0> + <template #reference> + <div class="add-album"> + <plus-icon class="plus-icon"/> + </div> + </template> + <ul> + <li @click="addAlbum">娣诲姞姝屽崟</li> + </ul> + </el-popover> + + </div> + <div class="search-container"> + <div class="search-album" v-if="isSideBarOpen" @click="toggleSearchBar"> + <search-icon class="search-icon"/> + </div> + <input type="text" class="search-input" placeholder="杈撳叆鎼滅储姝屽崟" @keydown.enter="searchAlbum" + @blur="blurSearchBar"/> + </div> + + + <div class="musicAlbums" + @mouseenter="()=>{hoverOnAlbum=true}" + @mouseleave="()=>{hoverOnAlbum=false}" + :style="{ scrollbarWidth : hoverOnAlbum? 'auto':'none'}"> + + + <div v-if="musicAlbums !== undefined" v-for="album in musicAlbums" + :key="album.id" + @mouseenter="()=>{albumHoveredIndex = album.id}" + @mouseleave="()=>{albumHoveredIndex = null}" + :style="{backgroundColor: albumHoveredIndex === album.id ? '#1F1F1F' : '#171717' }" + class="musicAlbum-item"> + <img + :src="album.picPath" + alt="playlist" + class="musicAlbum-image" + :style="{opacity:albumHoveredIndex === album.id ? 0.4 :1}" + /> + <play-button @click="emit('setCurrentPlaylist', album);" v-if="albumHoveredIndex === album.id" + class="play-button"/> + + <div class="musicAlbum-description"> + <p style="padding-bottom: 5px;font-size: 18px">{{ album.title }}</p> + <p v-if="album.title !== '鎴戝枩娆㈢殑姝屾洸'" style="color: #b2b2b2;font-size: 13px">姝屽崟 鈥� {{ userToken.username }}</p> + <p v-else style="color: #b2b2b2;font-size: 13px">榛樿鏀惰棌澶�</p> + </div> + </div> + </div> + <div class="resizer" @mousedown="startResizing" :style="{left:(sideBarWidth+8) +'px'}"></div> + + </nav> +</template> + +<style scoped> + +*, +*::before, +*::after { + box-sizing: border-box; + padding: 0; + margin: 0; +} + +ul { + background-color: #282828; + list-style-type: none; + margin: 0; + border-radius: 10px; + padding: 12px 8px; +} + +li { + color: white; + padding: 10px 12px; +} + +li:hover { + cursor: pointer; + background-color: #404040; + text-decoration: underline; +} + +nav { + user-select: none; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + -o-user-select: none; +} + + +.main-menu.resizable-box { + /* position: relative; /*浣垮緱瀛愬厓绱犵殑absotute鏄浉瀵逛簬璇ュ厓绱� 杩欓噷涓嶈缃紝浣嶇疆閫氳繃js鎺у埗 涓嶇劧鐨勮瘽resizer浼氳gap閬斀*/ + display: flex; + flex-direction: column; + border: none; + border-radius: 12px; + padding: 12px 0 20px; + overflow: hidden; + font-family: inherit; + background-color: #171717; + +} + +.top-control { + margin-top: 10px; + display: flex; + align-items: center; + justify-content: space-between; +} + +.add-album { + color: #b2b2b2; + margin-top: 5px; + margin-right: 10px; + width: 30px; + cursor: pointer; +} + +.search-container { + margin: 12px 10px; + display: flex; + align-items: center; + cursor: pointer; +} + +.search-icon { + font-size: 24px; + transition: margin-right 0.3s ease; +} + +.search-input { + background-color: #404040; + font-size: 15px; + color: #ffffff; + height: 35px; + border: none; + width: 0; + opacity: 0; + transition: width 0.3s ease, opacity 0.3s ease; + padding: 5px; + border-radius: 4px; + outline: none; +} + +.search-input.active { + width: 70%; /* 璁剧疆杈撳叆妗嗘媺浼稿悗鐨勫搴� */ + opacity: 1; +} + +.search-album { + display: flex; + color: #b2b2b2; + width: 35px; + height: 35px; + cursor: pointer; + align-items: center; + justify-content: center; +} + +.plus-icon { + + border-radius: 50%; + transition: width, color, background-color ease-in-out 0.2s; +} + +.plus-icon:hover { + transform: scale(1.1); + color: #efeeee; + background-color: #404040; +} + +.search-icon { + padding: 3px; + border-radius: 50%; + transition: width, color, background-color ease-in-out 0.2s; +} + +.search-icon:hover { + transform: scale(1.05); + color: #efeeee; + background-color: #404040; +} + +.toggle-button:hover { + color: #efeeee; +} + +.toggle-button { + display: flex; + align-items: center; + width: 120px; + margin: 0 0 0 16px; + background-color: transparent; + cursor: pointer; + transition: color 0.2s ease; + color: #b2b2b2; +} + +.resizer { + + position: absolute; + width: 7px; + background-color: transparent; + height: 92%; + top: 85px; + cursor: ew-resize; /* 姘村钩璋冩暣鍏夋爣 */ + + &::before { + opacity: 0; + position: absolute; + content: ''; + left: 3px; + width: 1px; + height: 100%; + background-color: #9d9d9d; + transition: opacity 0.2s ease-in-out; + } + + &:hover::before { + opacity: 1; + } +} + + +.musicAlbums { + height: 100%; + padding: 0 10px 0 10px; + overflow: auto; + /*榛樿鎯呭喌 婊氬姩鏉℃秷澶�*/ + +} + +/*婊戝姩鏉�*/ +.musicAlbums::-webkit-scrollbar { + width: 12px; /* 婊氬姩鏉″搴� */ +} + +.musicAlbums::-webkit-scrollbar:window-inactive { + +} + +.musicAlbums::-webkit-scrollbar-track { + background: transparent; /* 婊氬姩鏉¤儗鏅� */ +} + +.musicAlbums::-webkit-scrollbar-thumb { + background: #888; /* 婊氬姩鏉¢鑹� */ + border-radius: 10px; /* 鍦嗚 */ + +} + +.musicAlbums::-webkit-scrollbar-thumb:hover { + background-color: #555; /* 鎮仠鏃剁殑棰滆壊 */ +} + +.musicAlbum-item { + display: flex; + position: relative; + align-items: center; + border-radius: 10px; + padding: 10px 0; + color: #f6f6f6; +} + +.musicAlbum-description { + text-align: left; + display: flex; + flex-direction: column; + +} + +.musicAlbum-image { + width: 55px; /* 璋冩暣鍥剧墖澶у皬 */ + height: 55px; /* 璋冩暣鍥剧墖澶у皬 */ + margin-right: 10px; + border-radius: 10px; +} + +.play-button { + position: absolute; + top: 20px; + left: 10px; + color: #f1f1f1; /* 鎾斁閿殑棰滆壊 */ + cursor: pointer; /* 榧犳爣绉诲姩鍒版挱鏀鹃敭涓婃椂鏄剧ず涓虹偣鍑绘墜鍨� */ + transition: transform 0.3s ease; +} + +.play-button:hover { + transform: scale(1.1); +} + +.musicAlbum-description { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; /* 鍗曡鏄剧ず鏂囨湰 */ +} + + +</style> \ No newline at end of file