Skip to content
Snippets Groups Projects
Commit 78a869ab authored by CosineSky's avatar CosineSky
Browse files

- Converted setting page into song-uploading page.

parent 54336a36
No related branches found
No related tags found
No related merge requests found
......@@ -5,8 +5,8 @@ import {API_MODULE} from './_prefix'
// TODO - newly added
+ user_id: number
*/
export const uploadImage = (payload) => {
return axios.post(`${API_MODULE}/images`, payload, {
export const uploadFile = (payload) => {
return axios.post(`${API_MODULE}/upload`, payload, {
headers:{'Content-Type': "multipart/form-data;"}
}).then(res => {
return res
......
<script setup lang="ts">
import {ElMessage} from "element-plus";
import {uploadImage} from "../api/tool";
<script setup>
import {ref} from "vue";
import {uploadFile} from "../api/tool";
import {defineEmits} from 'vue';
const imageFileList = ref([])
const logoUrl = ref('')
const uploadingImages = ref(false);
const fileList = ref([])
const fileUrl = ref('')
const isUploadingFiles = ref(false);
const handleExceed = () => {
ElMessage.warning(`当前限制选择 1 个文件`);
alert("File count exceeded!")
}
const handleChange = (file: any, fileList: any) => {
uploadingImages.value = true;
imageFileList.value = fileList
const handleChange = (file, fileList) => {
isUploadingFiles.value = true;
fileList.value = fileList
let formData = new FormData()
formData.append('file', file.raw)
uploadImage(formData).then(res => {
logoUrl.value = res.data.result
uploadingImages.value = false;
})
uploadFile(formData)
.then(res => {
fileUrl.value = res.data.result
isUploadingFiles.value = false;
passFileUrl(fileUrl.value)
})
}
const uploadHttpRequest = () => {
return new XMLHttpRequest()
}
const emit = defineEmits();
const passFileUrl = (url) => {
emit('updateFileUrl', url);
};
</script>
<template>
<el-upload
v-model:file-list="imageFileList"
style="width: 300px"
v-model:file-list="fileList"
:limit="1"
:on-change="handleChange"
:on-exceed="handleExceed"
:on-remove="handleChange"
class="upload-demo"
list-type="picture"
:http-request="uploadHttpRequest"
drag
>
<div class="el-upload-text">
将文件拖到此处或单击此处上传。
</div>
</el-upload>
</template>
<style scoped>
el-upload {
width: 100px;
}
</style>
\ No newline at end of file
......@@ -9,11 +9,11 @@ const searchInput = ref('');
const showDropdown = ref(false);
function toggleDropdown() {
showDropdown.value =!showDropdown.value;
showDropdown.value =!showDropdown.value;
}
function exit() {
router.push('/login');
router.push('/login');
}
function callPersonalData() {
......@@ -36,32 +36,38 @@ function callSearch() {
</script>
<template>
<div class="header">
<router-link to="/home" class="home-btn">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-home">
<path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"></path>
<polyline points="9 22 9 12 15 12 15 22"></polyline>
</svg>
</router-link>
<div class="search-box">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-search">
<circle cx="11" cy="11" r="8"></circle>
<line x1="21" y1="21" x2="16.65" y2="16.65"></line>
</svg>
<input type="text" v-model="searchInput" placeholder="想播放什么?" @keyup.enter="callSearch" />
<div class="header">
<div style="display: flex; flex-direction: row">
<router-link to="/home" class="home-btn">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-home">
<path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"></path>
<polyline points="9 22 9 12 15 12 15 22"></polyline>
</svg>
</router-link>
<router-link to="/manage" class="manage-btn">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024"><path fill="currentColor" d="M480 480V128a32 32 0 0 1 64 0v352h352a32 32 0 1 1 0 64H544v352a32 32 0 1 1-64 0V544H128a32 32 0 0 1 0-64z"></path></svg>
</router-link>
</div>
<div class="search-box">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-search">
<circle cx="11" cy="11" r="8"></circle>
<line x1="21" y1="21" x2="16.65" y2="16.65"></line>
</svg>
<input type="text" v-model="searchInput" placeholder="想播放什么?" @keyup.enter="callSearch" />
</div>
<div class="role-btn" @click="toggleDropdown">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-user">
<path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"></path>
<circle cx="12" cy="7" r="4"></circle>
</svg>
</div>
<div class="dropdown" v-show="showDropdown" style="z-index: 2147483647">
<button @click="callPersonalData">个人资料</button>
<button @click="callSetting">设置</button>
<button @click="exit">退出</button>
</div>
</div>
<div class="role-btn" @click="toggleDropdown">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-user">
<path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"></path>
<circle cx="12" cy="7" r="4"></circle>
</svg>
</div>
<div class="dropdown" v-show="showDropdown" style="z-index: 2147483647">
<button @click="callPersonalData">个人资料</button>
<button @click="callSetting">设置</button>
<button @click="exit">退出</button>
</div>
</div>
</template>
<style scoped>
......@@ -93,6 +99,20 @@ function callSearch() {
margin-right: 10px;
}
.manage-btn {
display: flex;
align-items: center;
margin-right: 10px;
color: #fff;
text-decoration: none;
}
.manage-btn svg {
width: 32px;
height: 32px;
margin-right: 10px;
}
.search-box {
display: flex;
align-items: center;
......
......@@ -102,7 +102,6 @@ defineProps({
@mouseenter="()=>{hoverOnAlbum=true}"
@mouseleave="()=>{hoverOnAlbum=false}"
:style="{ scrollbarWidth : hoverOnAlbum? 'auto':'none'}">
<!-- <button @click="callParentFunction('子组件传参')">调用父组件函数</button>-->
<div v-if="musicAlbums !== undefined" v-for="album in musicAlbums"
:key="album.id"
......
......@@ -39,6 +39,12 @@ const router = createRouter({
component: () => import('../views/ProfilePage.vue'),
meta: {title: 'Profile'}
},
{
path: '/manage',
// @ts-ignore
component: () => import('../views/ManagePage.vue'),
meta: {title: 'Manage'}
},
]
})
......
This diff is collapsed.
<script setup>
import {onMounted, ref} from "vue";
import {addSong} from "../api/manager";
import ImageUploader from "../components/FileUploader.vue";
const song_title = ref("");
const song_artist = ref("");
const song_album = ref("");
const song_description = ref("");
// 定义父组件的响应式变量
const song_url = ref('');
const cover_url = ref('');
const lyrics_url = ref('');
// 处理子组件传递过来的值
const receiveSongUrl = (value) => {
song_url.value = value;
console.log(song_url.value)
};
const receiveCoverUrl = (value) => {
cover_url.value = value;
};
const receiveLyricsUrl = (value) => {
lyrics_url.value = value;
};
function handleSubmit() {
addSong({
song_name: song_title.value,
artist: song_artist.value,
album: song_album.value,
audio_path: "",
lyrics_path: "",
}).then(() => {
console.log("success")
}).catch(() => {
console.log("fail")
})
}
onMounted(() => {
})
</script>
<template>
<body>
<body>
<section class="user">
<div class="user_options-container">
<div class="user_options-text">
<div class="user_options-unregistered">
<h2 class="user_unregistered-title">Want something NEW?</h2>
<p class="user_unregistered-text">Tired of all those songs? Not a problem! As a music-player manager, you can always add new songs to our archives!</p>
</div>
<div class="user_options-registered">
<button class="user_registered-login" id="login-button">Login</button>
</div>
</div>
<div class="user_options-forms" id="user_options-forms">
<div class="user_forms-login">
<h2 class="forms_title">Upload A NEW SONG</h2>
<form class="forms_form">
<div class="text-area">
<h2>Song Information</h2>
<div class="setting">
<div class="setting-items">
<h3>Song Title</h3>
<input v-model="song_title" placeholder="..." type="text">
</div>
<div class="setting-items">
<h3>Artist</h3>
<input v-model="song_artist" placeholder="..." type="text">
</div>
<div class="setting-items">
<h3>Album</h3>
<input v-model="song_album" placeholder="..." type="text">
</div>
<div class="setting-items">
<h3>Description</h3>
<input v-model="song_description" placeholder="..." type="text">
</div>
</div>
<h2>Source Files</h2>
<div class="setting">
<div class="setting-items">
<h3>Song File(.mp3)</h3>
<image-uploader @updateFileUrl="receiveSongUrl"/>
</div>
<div class="setting-items">
<h3>Cover File(.png/.jpg)</h3>
<image-uploader @updateFileUrl="receiveCoverUrl"/>
</div>
<div class="setting-items">
<h3>Lyrics File(.lyc)</h3>
<image-uploader @updateFileUrl="receiveLyricsUrl"/>
</div>
</div>
</div>
<div>
<router-link to="/home" class="home-btn">
<input style="margin: 5px" type="submit" value="Back" class="forms_buttons-cancel">
</router-link>
<input style="margin: 5px" @click="handleSubmit" type="submit" value="Let's ROCK!" class="forms_buttons-action">
</div>
</form>
</div>
</body>
</div>
</div>
</section>
</body>
</template>
<style scoped>
/**
* * General configs
* */
*,
*::before,
*::after {
box-sizing: border-box;
padding: 0;
margin: 0;
}
body {
margin: 0;
padding: 0;
height: 100%;
font-family: "Nunito", sans-serif;
display: flex;
align-items: center;
justify-content: center;
background-image: url("../assets/pictures/bg4.jpg");
background-repeat: no-repeat;
background-size: cover;
}
button {
background-color: transparent;
padding: 0;
border: 0;
outline: 0;
cursor: pointer;
}
.text-area {
padding: 20px 20px 0 20px;
h2 {
text-transform: uppercase;
font-size: 1.2em;
margin-bottom: 20px;
letter-spacing: .2em;
font-weight: 480;
}
h3 {
text-transform: uppercase;
font-size: .9em;
letter-spacing: .2em;
font-weight: 320;
}
p {
font-size: .7em;
width: 75%;
line-height: 2em;
}
span {
font-size: .9em;
line-height: 2em;
}
}
.setting {
position: relative;
padding-bottom: 20px;
}
.setting-items {
display: flex;
margin-bottom: 20px;
flex-direction: row;
justify-content: space-between;
}
input[type=text] {
height: 40px;
}
input::-moz-placeholder {
font-size: 0.85rem;
font-family: "Montserrat", sans-serif;
font-weight: 300;
letter-spacing: 0.1rem;
color: #ccc;
}
input:-ms-input-placeholder {
font-size: 0.85rem;
font-family: "Montserrat", sans-serif;
font-weight: 300;
letter-spacing: 0.1rem;
color: #ccc;
}
input::placeholder {
font-size: 0.85rem;
font-family: "Montserrat", sans-serif;
font-weight: 300;
letter-spacing: 0.1rem;
color: #ccc;
}
/**
* * Page background
* */
.user {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 100vh;
background-size: cover;
}
.user_options-container {
position: relative;
width: 80%;
}
.user_options-text {
display: flex;
justify-content: space-between;
width: 100%;
background-color: rgba(34, 34, 34, 0.85);
border-radius: 3px;
}
/**
* * Registered and Unregistered user box and text
* */
.user_options-registered,
.user_options-unregistered {
width: 50%;
padding: 75px 45px;
color: #fff;
font-weight: 300;
}
.user_unregistered-title {
margin-bottom: 15px;
font-size: 1.66rem;
line-height: 1em;
}
.user_unregistered-text {
font-size: 0.83rem;
line-height: 1.4em;
}
.user_registered-login {
margin-top: 30px;
border: 1px solid #ccc;
border-radius: 3px;
padding: 10px 30px;
color: #fff;
text-transform: uppercase;
line-height: 1em;
letter-spacing: 0.2rem;
transition: background-color 0.2s ease-in-out, color 0.2s ease-in-out;
}
.user_registered-login:hover {
color: rgba(34, 34, 34, 0.85);
background-color: #ccc;
}
/**
* * Login and signup forms
* */
.user_options-forms {
position: absolute;
top: 50%;
left: 30px;
width: calc(50% - 30px);
min-height: 800px;
background-color: #fff;
border-radius: 3px;
box-shadow: 2px 0 15px rgba(0, 0, 0, 0.25);
overflow: auto;
transform: translate3d(100%, -50%, 0);
transition: transform 0.4s ease-in-out;
}
.user_options-forms .user_forms-login {
transition: opacity 0.4s ease-in-out, visibility 0.4s ease-in-out;
}
.user_options-forms .forms_title {
margin-bottom: 10px;
font-size: 1.5rem;
font-weight: 500;
line-height: 1em;
text-transform: uppercase;
color: #e8716d;
letter-spacing: 0.1rem;
}
.user_options-forms :focus {
border-color: gray;
}
.user_options-forms {
font-family: "Montserrat", sans-serif;
letter-spacing: 0.1rem;
color: #ccc;
text-decoration: underline;
transition: color 0.2s ease-in-out;
}
.user_options-forms {
color: #b3b3b3;
}
.user_options-forms .forms_buttons-action {
background-color: #e8716d;
border-radius: 3px;
padding: 10px 35px;
font-size: 1rem;
font-family: "Montserrat", sans-serif;
font-weight: 480;
color: #fff;
text-transform: uppercase;
letter-spacing: 0.1rem;
transition: background-color 0.2s ease-in-out;
}
.user_options-forms .forms_buttons-action:hover {
background-color: #e14641;
}
.user_options-forms .forms_buttons-cancel {
background-color: #469de3;
border-radius: 3px;
padding: 10px 35px;
font-size: 1rem;
font-family: "Montserrat", sans-serif;
font-weight: 480;
color: #ffffff;
text-transform: uppercase;
letter-spacing: 0.1rem;
transition: background-color 0.2s ease-in-out;
}
.user_options-forms .forms_buttons-cancel:hover {
background-color: #4c7ce3;
}
.user_options-forms .user_forms-signup,
.user_options-forms .user_forms-login {
position: absolute;
top: 70px;
left: 40px;
width: calc(100% - 80px);
opacity: 0;
visibility: hidden;
transition: opacity 0.4s ease-in-out, visibility 0.4s ease-in-out, transform 0.5s ease-in-out;
}
.user_options-forms .user_forms-login {
transform: translate3d(0, 0, 0);
opacity: 1;
visibility: visible;
}
.user_options-forms input[type=text] {
border-bottom: 1px solid #ccc;
padding: 6px 20px 6px 6px;
font-family: "Montserrat", sans-serif;
font-size: 1.1rem;
font-weight: 320;
color: gray;
letter-spacing: 0.1rem;
transition: border-color 0.2s ease-in-out;
}
/**
* * Responsive 990px
* */
@media screen and (max-width: 990px) {
.user_options-forms {
min-height: 350px;
}
.user_options-forms .user_forms-login .forms_buttons-action {
margin-top: 30px;
}
.user_options-forms,
.user_options-forms .user_forms-login {
top: 40px;
}
.user_options-registered,
.user_options-unregistered {
padding: 50px 45px;
}
}
</style>
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment