后台管理页面开发进度
后端对应的接口已经写好,但是前端的页面总是没啥头绪,写的比较潦草
先看整体效果
这是目录
- 这是AdminIndex页面
<script lang="ts" setup>
import router from '../../router';
import {
Document,
Menu as IconMenu,
Location,
Setting,
} from '@element-plus/icons-vue'
const handleOpen = (key: string, keyPath: string[]) => {
console.log(key, keyPath)
}
const handleClose = (key: string, keyPath: string[]) => {
console.log(key, keyPath)
}
const goBack = () => {
router.push({path:'/'})
}
</script>
<template>
<div class="common-layout">
<el-container>
<el-header class="common-header" height="100px">
<el-page-header @back="goBack">
<template #content>
<span class="text-large font-600 mr-3"> 返回首页 </span>
</template>
</el-page-header>
<h1 class="title">后台管理系统</h1>
</el-header>
<el-container>
<el-aside class="common-aside" width="200px">
<el-menu
default-active="2"
class="el-menu-vertical-demo"
@open="handleOpen"
@close="handleClose"
router
>
<el-menu-item :index="'/music'">
<el-icon><icon-menu /></el-icon>
<span>音乐管理</span>
</el-menu-item>
<el-sub-menu index="2">
<template #title>
<el-icon><location /></el-icon>
<span>登录管理</span>
</template>
<el-menu-item-group title="用户">
<el-menu-item :index="'/user'">item one</el-menu-item>
</el-menu-item-group>
<el-menu-item-group title="权限">
<el-menu-item :index="'/role'">item three</el-menu-item>
</el-menu-item-group>
</el-sub-menu>
</el-menu>
</el-aside>
<el-main>
<router-view></router-view>
</el-main>
</el-container>
</el-container>
</div>
</template>
<style>
.el-container{
height: 100vh;
width: 100%;
overflow: hidden;
}
.common-header{
background-color: azure;
}
.common-aside{
background-color: azure;
}
.logo{
width: 50px;
}
.title{
text-align: center;
}
</style>
- MusicList.vue
<script lang="ts" setup>
import { onMounted, reactive,ref, toRefs,inject} from 'vue';
import api from '@/axios/axios.js';
import axios from 'axios';
import { ElMessageBox } from 'element-plus'
//获取音乐列表
let musicData = reactive({
tablelist:[]
})
onMounted(() => {
api({
url:'/Musics/GetMusicList',
method:'get',
}).then((res:any) =>{
musicData.tablelist = res.data
})
})
//搜索框
const formInline = reactive({
name: '',
})
//引入界面刷新
const reload:any = inject('reload');
//按歌曲名字进行查询
const onSubmit = () => {
let user= {
name:formInline.name
}
axios.post('Musics/GetMusicByName',user).then((res:any)=>{
musicData.tablelist = res.data
})
}
//编辑框
var dialogVisible = ref(false)
//新增
const onAdd = () => {
dialogVisible.value=true
}
//编辑
const onEdit = (row: any) =>{
console.log("操作的那条数据"+JSON.stringify(row.pid))
}
const handleClose = (done: () => void) => {
ElMessageBox.confirm('Are you sure to close this dialog?')
.then(() => {
done()
})
.catch(() => {
// catch error
})
}
</script>
<template>
<el-row class="tac">
<el-col :span="24">
<el-col :span="24">
<el-form :inline="true" :model="formInline" class="demo-form-inline">
<el-form-item label="">
<el-input v-model="formInline.name" placeholder="请输入歌曲名字" />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onSubmit">查询</el-button>
</el-form-item>
<el-form-item>
<el-button type="success" @click="onAdd">新增</el-button>
</el-form-item>
</el-form>
</el-col>
<el-dialog
v-model="dialogVisible"
title="Tips"
width="30%"
:before-close="handleClose"
>
<span>This is a message</span>
<template #footer>
<span class="dialog-footer">
<el-button @click="dialogVisible = false">Cancel</el-button>
<el-button type="primary" @click="dialogVisible = false">
Confirm
</el-button>
</span>
</template>
</el-dialog>
</el-col>
<el-col :span="24">
<el-table
:data="musicData.tablelist"
ref="singleTableRef"
height="550"
style="width:100%"
highlight-current-row
>
<el-table-column prop="mid" label="mid" width="50" />
<el-table-column prop="name" label="歌曲名称" />
<el-table-column prop="singer" label="演唱者" />
<el-table-column prop="album" label="专辑" />
<el-table-column label="操作">
<template #default="scope">
<el-button type="primary" @click="onEdit(scope.row)">编辑</el-button>
<el-button type="danger">删除</el-button>
</template>
</el-table-column>
</el-table>
</el-col>
</el-row>
</template>
<style scoped>
</style>
Aplayer的封装
为了实现动态点播音乐,我在网上找到了这段代码,目前已经看明白一点了
<template>
<div id="app">
<!-- 准备一个容器用来存放音乐播放器 -->
<div ref="playerRef"></div>
</div>
</template>
<script>
import http from '../axios/player.ts'
import APlayer from "APlayer"; // 引入音乐插件
import "APlayer/dist/APlayer.min.css"; // 引入音乐插件的样式
import "APlayer/dist/APlayer.min.css"; // 引入音乐插件的样式
import type {PropType} from '@vue/runtime-core';
import {nextTick, onBeforeUnmount, onMounted, ref} from 'vue'
const playerRef = ref()
let instance: APlayer;
// APlayer歌曲信息
class Audio {
// 音频艺术家
artist: String;
// 音频名称
name: String;
// 音频链接
url: String;
// 音频封面
cover: String;
// 歌词
lrc: String;
constructor(artist: String, name: String, url: String, cover: String, lrc: String) {
this.artist = artist;
this.name = name;
this.url = url;
this.cover = cover;
this.lrc = lrc;
}
}
const props = defineProps({
// 开启吸底模式
fixed: {
type: Boolean as PropType<boolean>,
default: true
},
// 开启迷你模式
mini: {
type: Boolean as PropType<boolean>,
default: true
},
// 音频自动播放
autoplay: {
type: Boolean as PropType<boolean>,
default: false
},
// 主题色
theme: {
type: String as PropType<string>,
default: 'rgba(255,255,255,0.2)'
},
// 音频循环播放
loop: {
type: String as PropType<'all' | 'one' | 'none'>,
default: 'all'
},
// 音频循环顺序
order: {
type: String as PropType<'list' | 'random'>,
default: 'random'
},
// 预加载
preload: {
type: String as PropType<'auto' | 'metadata' | 'none'>,
default: 'auto'
},
// 默认音量
volume: {
type: Number as PropType<number>,
default: 0.7,
validator: (value: Number) => {
return value >= 0 && value <= 1;
}
},
// 歌曲服务器(netease-网易云, tencent-qq音乐, kugou-酷狗, xiami-小米音乐, baidu-百度音乐)
songServer: {
type: String as PropType<'netease' | 'tencent' | 'kugou' | 'xiami' | 'baidu'>,
default: 'netease'
},
// 播放类型(song-歌曲, playlist-播放列表, album-专辑, search-搜索, artist-艺术家)
songType: {
type: String as PropType<string>,
default: 'playlist'
},
// 歌的id
songId: {
type: String as PropType<string>,
default: '19723756'
},
// 互斥,阻止多个播放器同时播放,当前播放器播放时暂停其他播放器
mutex: {
type: Boolean as PropType<boolean>,
default: true
},
// 传递歌词方式
lrcType: {
type: Number as PropType<number>,
default: 3
},
// 列表是否默认折叠
listFolded: {
type: Boolean as PropType<boolean>,
default: true
},
// 列表最大高度
listMaxHeight: {
type: String as PropType<string>,
default: '100px'
},
// 存储播放器设置的 localStorage key
storageName: {
type: String as PropType<string>,
default: 'aplayer-setting'
}
})
// 初始化
onMounted(() => {
nextTick(() => {
http.player.getSongSheet(props.songServer, props.songType, props.songId)
.then(res => {
let audioList = res.data.map(value => new Audio(value.author, value.title, value.url, value.pic, value.lrc));
instance = new APlayer({
container: playerRef.value,
fixed: props.fixed,
mini: props.mini,
autoplay: props.autoplay,
theme: props.theme,
loop: props.loop,
order: props.order,
preload: props.preload,
volume: props.volume,
mutex: props.mutex,
lrcType: props.lrcType,
listFolded: props.listFolded,
listMaxHeight: props.listMaxHeight,
storageName: props.storageName,
audio: audioList
})
})
})
})
// 销毁
onBeforeUnmount(() => {
instance.destroy()
})
</script>
<template>
</template>
<style scoped>
</style>