初始化
This commit is contained in:
108
src/views/common/MainMenu.vue
Normal file
108
src/views/common/MainMenu.vue
Normal file
@@ -0,0 +1,108 @@
|
||||
<script setup>
|
||||
import {
|
||||
h,
|
||||
ref,
|
||||
onMounted,
|
||||
onUnmounted,
|
||||
nextTick,
|
||||
} from "vue";
|
||||
import { useStore } from "vuex";
|
||||
import {
|
||||
RouterLink,
|
||||
useRoute,
|
||||
useRouter,
|
||||
} from "vue-router";
|
||||
import { NMenu, NIcon } from "naive-ui";
|
||||
|
||||
const menuOptions = ref([
|
||||
{
|
||||
label: () =>
|
||||
h(
|
||||
RouterLink,
|
||||
{
|
||||
to: {
|
||||
path: "/discover/recommend",
|
||||
},
|
||||
},
|
||||
{ default: () => "发现" }
|
||||
),
|
||||
key: "/discover",
|
||||
},
|
||||
{
|
||||
label: () =>
|
||||
h(
|
||||
RouterLink,
|
||||
{
|
||||
to: {
|
||||
path: "/videos/v",
|
||||
},
|
||||
},
|
||||
{ default: () => "视频" }
|
||||
),
|
||||
key: "/videos",
|
||||
},
|
||||
{
|
||||
label: () =>
|
||||
h(
|
||||
RouterLink,
|
||||
{
|
||||
to: {
|
||||
path: "/played",
|
||||
},
|
||||
},
|
||||
{ default: () => "最近播放" }
|
||||
),
|
||||
key: "/played",
|
||||
},
|
||||
//#region 其他
|
||||
// {
|
||||
// label: () =>
|
||||
// h(
|
||||
// RouterLink,
|
||||
// {
|
||||
// to: {
|
||||
// path: '/fm'
|
||||
// }
|
||||
// },
|
||||
// { default: () => '私人FM' }
|
||||
// ),
|
||||
// key: '/fm',
|
||||
// },
|
||||
// {
|
||||
// label: () =>
|
||||
// h(
|
||||
// RouterLink,
|
||||
// {
|
||||
// to: {
|
||||
// path: '/friends'
|
||||
// }
|
||||
// },
|
||||
// { default: () => '朋友' }
|
||||
// ),
|
||||
// key: '/friends',
|
||||
// },
|
||||
//#endregion
|
||||
]);
|
||||
|
||||
const store = useStore();
|
||||
const {mainMenuSelected} = store.getters
|
||||
</script>
|
||||
<template>
|
||||
<n-menu
|
||||
:options="menuOptions"
|
||||
:value="
|
||||
mainMenuSelected(menuOptions)
|
||||
"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
// beforeRouteEnter(to, from, next) {
|
||||
// console.log("MainMenu beforeRouteEnter", to, from);
|
||||
// next();
|
||||
// },
|
||||
};
|
||||
</script>
|
||||
|
||||
<style></style>
|
||||
34
src/views/common/Nav.vue
Normal file
34
src/views/common/Nav.vue
Normal file
@@ -0,0 +1,34 @@
|
||||
<script setup>
|
||||
import { useRouter } from "vue-router";
|
||||
import { NButton, NIcon, NSpace } from "naive-ui";
|
||||
import ChevronForward from '@/assets/svgs/ChevronForward.svg'
|
||||
import ChevronBack from '@/assets/svgs/ChevronBack.svg'
|
||||
|
||||
const router = useRouter()
|
||||
|
||||
</script>
|
||||
<template>
|
||||
<NSpace id="nav" justify="end">
|
||||
<n-button circle size="small" @click="router.back()" >
|
||||
<template #icon>
|
||||
<n-icon>
|
||||
<ChevronBack />
|
||||
</n-icon>
|
||||
</template>
|
||||
</n-button>
|
||||
<n-button circle size="small" @click="router.forward()">
|
||||
<template #icon>
|
||||
<n-icon>
|
||||
<ChevronForward />
|
||||
</n-icon>
|
||||
</template>
|
||||
</n-button>
|
||||
</NSpace>
|
||||
</template>
|
||||
<style lang="less" scoped>
|
||||
#nav {
|
||||
width: 150px;
|
||||
// text-align: right;
|
||||
// padding-top: 10px;
|
||||
}
|
||||
</style>
|
||||
19
src/views/common/Search.vue
Normal file
19
src/views/common/Search.vue
Normal file
@@ -0,0 +1,19 @@
|
||||
<script setup>
|
||||
import {NInput} from 'naive-ui'
|
||||
|
||||
</script>
|
||||
<template>
|
||||
<div id="search">
|
||||
<n-input size="small" round placeholder="请搜索..." />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
||||
39
src/views/common/Settings.vue
Normal file
39
src/views/common/Settings.vue
Normal file
@@ -0,0 +1,39 @@
|
||||
<script setup>
|
||||
import { NButton, NIcon, NSpace } from "naive-ui";
|
||||
import SettingsOutline from "@/assets/svgs/SettingsOutline.svg";
|
||||
import MailOutline from "@/assets/svgs/MailOutline.svg";
|
||||
|
||||
</script>
|
||||
<template>
|
||||
<NSpace id="settings" >
|
||||
<n-button circle size="small" >
|
||||
<template #icon>
|
||||
<n-icon>
|
||||
<SettingsOutline />
|
||||
</n-icon>
|
||||
</template>
|
||||
</n-button>
|
||||
<n-button circle size="small" >
|
||||
<template #icon>
|
||||
<n-icon>
|
||||
<MailOutline />
|
||||
</n-icon>
|
||||
</template>
|
||||
</n-button>
|
||||
|
||||
</NSpace>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
#settings{
|
||||
// width: 100px;
|
||||
margin: 0 15px
|
||||
}
|
||||
</style>
|
||||
219
src/views/common/SongCtrl.vue
Normal file
219
src/views/common/SongCtrl.vue
Normal file
@@ -0,0 +1,219 @@
|
||||
<script setup>
|
||||
import { ref, onMounted, onUnmounted, watch } from "vue";
|
||||
import { useStore } from "vuex";
|
||||
import { NButton, NIcon, NSpace } from "naive-ui";
|
||||
import PlayCircle from "@/assets/svgs/PlayCircle.svg";
|
||||
import PlaySkipForward from "@/assets/svgs/PlaySkipForward.svg";
|
||||
import PlaySkipBack from "@/assets/svgs/PlaySkipBack.svg";
|
||||
import HeartOutline from "@/assets/svgs/HeartOutline.svg";
|
||||
import TrashOutline from "@/assets/svgs/TrashOutline.svg";
|
||||
import PauseCircle from "@/assets/svgs/PauseCircle.svg";
|
||||
import { getSongUrl } from "@/network/song";
|
||||
import pubsub from "pubsub-js";
|
||||
|
||||
const store = useStore();
|
||||
const { settings } = store.state;
|
||||
const audioEl = ref("");
|
||||
const playing = ref(false);
|
||||
let currentTime = 0;
|
||||
let lastPause = Date.now()
|
||||
|
||||
onMounted(() => {
|
||||
audioEl.value.addEventListener("play", onPlay);
|
||||
audioEl.value.addEventListener("pause", onPause);
|
||||
audioEl.value.addEventListener("ended", onEnd);
|
||||
|
||||
if (settings.songId) {
|
||||
pubsub.publish("zp.play", {
|
||||
id: settings.songId,
|
||||
im: false,
|
||||
});
|
||||
// play(settings.songId, false)
|
||||
}
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
console.log("另外一个Unmounted");
|
||||
// audioEl.value.removeEventListener("play", onPlay);
|
||||
// audioEl.value.removeEventListener("pause", onPause);
|
||||
// audioEl.value.removeEventListener("ended", onEnd);
|
||||
});
|
||||
|
||||
const onPlay = () => {
|
||||
console.log("onPlay");
|
||||
};
|
||||
const onPause = () => {
|
||||
console.log("onPause");
|
||||
};
|
||||
const onEnd = () => {
|
||||
playing.value = false;
|
||||
currentTime = 0;
|
||||
console.log("onEnd");
|
||||
};
|
||||
|
||||
const play = async (id, im = true) => {
|
||||
console.log(id);
|
||||
await getSongUrl(id)
|
||||
.then((res) => {
|
||||
audioEl.value.src = res.data.data[0].url;
|
||||
store.commit("saveSettings", {
|
||||
songId: id,
|
||||
});
|
||||
if (im) {
|
||||
audioEl.value.play();
|
||||
playing.value = true;
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log("getSongUrl err", err);
|
||||
});
|
||||
};
|
||||
|
||||
const pause = () => {
|
||||
audioEl.value.pause();
|
||||
playing.value = false;
|
||||
};
|
||||
|
||||
const resume = async () => {
|
||||
if (audioEl.value.readyState) {
|
||||
//如果暂停过了5分钟,需要再次载入歌曲
|
||||
// console.log(Date.now() - lastPause);
|
||||
if((Date.now() - lastPause) > 1000 * 60 * 5){
|
||||
console.log('暂停过了5分钟,再次载入歌曲');
|
||||
await play(settings.songId, false);
|
||||
audioEl.value.currentTime = currentTime;
|
||||
}
|
||||
audioEl.value.play();
|
||||
playing.value = true;
|
||||
}
|
||||
};
|
||||
|
||||
const setProgressScale = (scale) => {
|
||||
if (audioEl.value.readyState) {
|
||||
// console.log(progress);
|
||||
audioEl.value.currentTime = currentTime =
|
||||
scale * audioEl.value.duration;
|
||||
}
|
||||
};
|
||||
|
||||
const favorite = () => {
|
||||
// console.log(audioEl.value.currentTime);
|
||||
};
|
||||
|
||||
let interval;
|
||||
watch(playing, (val, old) => {
|
||||
if (val === true) {
|
||||
interval = setInterval(() => {
|
||||
// console.log(audioEl.value.currentTime);
|
||||
currentTime = audioEl.value.currentTime;
|
||||
pubsub.publish("zp.progress", {
|
||||
progress: audioEl.value.currentTime,
|
||||
total: audioEl.value.duration,
|
||||
});
|
||||
}, 200);
|
||||
} else {
|
||||
clearInterval(interval);
|
||||
lastPause = Date.now();
|
||||
}
|
||||
});
|
||||
|
||||
//#region 处理消息订阅
|
||||
const psToken = pubsub.subscribe("zp", (msg, data) => {
|
||||
switch (msg) {
|
||||
case "zp.play":
|
||||
play(data.id, data.im);
|
||||
break;
|
||||
case "zp.setProgressScale":
|
||||
setProgressScale(data.scale);
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
//卸载组件
|
||||
onUnmounted(() => {
|
||||
pubsub.unsubscribe(psToken);
|
||||
});
|
||||
//#endregion
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<!-- <div id="songsCtrl"> -->
|
||||
<audio src="" ref="audioEl"></audio>
|
||||
<n-space
|
||||
id="songCtrl"
|
||||
align="center"
|
||||
:size="[6]"
|
||||
style="padding-top: 2px"
|
||||
>
|
||||
<n-button circle @click="favorite">
|
||||
<template #icon>
|
||||
<n-icon>
|
||||
<HeartOutline />
|
||||
</n-icon>
|
||||
</template>
|
||||
</n-button>
|
||||
<n-button circle>
|
||||
<template #icon>
|
||||
<n-icon>
|
||||
<PlaySkipBack />
|
||||
</n-icon>
|
||||
</template>
|
||||
</n-button>
|
||||
<n-button
|
||||
v-if="!playing"
|
||||
text
|
||||
class="start-play"
|
||||
style="font-size: 56px"
|
||||
type="primary"
|
||||
@click="resume"
|
||||
>
|
||||
<!-- <template #icon> -->
|
||||
<n-icon>
|
||||
<PlayCircle />
|
||||
</n-icon>
|
||||
<!-- </template> -->
|
||||
</n-button>
|
||||
<n-button
|
||||
v-if="playing"
|
||||
text
|
||||
class="start-play"
|
||||
style="font-size: 56px"
|
||||
type="primary"
|
||||
@click="pause"
|
||||
>
|
||||
<!-- <template #icon> -->
|
||||
<n-icon size="56">
|
||||
<PauseCircle />
|
||||
</n-icon>
|
||||
<!-- </template> -->
|
||||
</n-button>
|
||||
<!-- <n-button circle color="#18a058"> -->
|
||||
<n-button circle>
|
||||
<template #icon>
|
||||
<n-icon>
|
||||
<PlaySkipForward />
|
||||
</n-icon>
|
||||
</template>
|
||||
</n-button>
|
||||
<n-button circle>
|
||||
<template #icon>
|
||||
<n-icon>
|
||||
<TrashOutline />
|
||||
</n-icon>
|
||||
</template>
|
||||
</n-button>
|
||||
</n-space>
|
||||
|
||||
<!-- </div> -->
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
#songCtrl {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
||||
115
src/views/common/SongInfo.vue
Normal file
115
src/views/common/SongInfo.vue
Normal file
@@ -0,0 +1,115 @@
|
||||
<script setup>
|
||||
import {
|
||||
ref,
|
||||
onUnmounted,
|
||||
reactive,
|
||||
toRef,
|
||||
toRefs,
|
||||
} from "vue";
|
||||
import { NAvatar } from "naive-ui";
|
||||
import pubsub from "pubsub-js";
|
||||
import { getSongDetial } from "@/network/song";
|
||||
import dayjs from 'dayjs'
|
||||
import 'dayjs/locale/zh-cn'
|
||||
import duration from 'dayjs/plugin/duration'
|
||||
|
||||
const showInfo = ref(true);
|
||||
const info = reactive({
|
||||
name: "",
|
||||
artists: "",
|
||||
albumPicUrl: "",
|
||||
});
|
||||
|
||||
//#region 取得歌曲信息
|
||||
const songInfo = (id) => {
|
||||
getSongDetial(id)
|
||||
.then((res) => {
|
||||
showInfo.value = true;
|
||||
info.name = res.data.songs[0].name;
|
||||
info.artists = res.data.songs[0].ar[0].name;
|
||||
info.albumPicUrl = res.data.songs[0].al.picUrl;
|
||||
})
|
||||
.catch((err) => {});
|
||||
};
|
||||
//#endregion
|
||||
|
||||
//#region 处理消息订阅
|
||||
let totalTime = ref("03:13");
|
||||
let currTime = ref("00:03");
|
||||
|
||||
dayjs.extend(duration)
|
||||
function zpTime(time) {
|
||||
return dayjs.duration(time).format('mm:ss')
|
||||
}
|
||||
// totalTime.value = zpTime(12345)
|
||||
const psToken = pubsub.subscribe("zp", (msg, data) => {
|
||||
switch (msg) {
|
||||
case "zp.play":
|
||||
songInfo(data.id);
|
||||
break;
|
||||
case "zp.progress":
|
||||
totalTime.value = zpTime(data.total * 1000)
|
||||
currTime.value = zpTime(data.progress * 1000)
|
||||
break;
|
||||
}
|
||||
});
|
||||
//卸载组件
|
||||
onUnmounted(() => {
|
||||
pubsub.unsubscribe(psToken);
|
||||
});
|
||||
//#endregion
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div id="songInfo">
|
||||
<NAvatar
|
||||
:size="40"
|
||||
v-show="showInfo"
|
||||
:src="info.albumPicUrl"
|
||||
></NAvatar>
|
||||
<div class="song" v-show="showInfo">
|
||||
<div class="w-song">
|
||||
<div class="song-name">{{ info.name }}</div>
|
||||
<div class="song-author">{{ info.artists }}</div>
|
||||
</div>
|
||||
|
||||
<div class="song-time">
|
||||
<span class="played-time">{{ currTime }}</span>/<span class="total-time">{{ totalTime }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
#songInfo {
|
||||
flex: 3;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-left: 12px;
|
||||
|
||||
.song {
|
||||
padding-left: 6px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
.w-song {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.song-author {
|
||||
margin-left: 4px;
|
||||
color: #aaa;
|
||||
font-size: 13px;
|
||||
|
||||
}
|
||||
}
|
||||
.song-time {
|
||||
color: #aaa;
|
||||
font-size: 13px;
|
||||
font-family: Courier, monospace;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
114
src/views/common/SongProgress.vue
Normal file
114
src/views/common/SongProgress.vue
Normal file
@@ -0,0 +1,114 @@
|
||||
<script setup>
|
||||
import {
|
||||
ref,
|
||||
onUnmounted,
|
||||
reactive,
|
||||
toRef,
|
||||
toRefs,
|
||||
} from "vue";
|
||||
import { useStore } from "vuex";
|
||||
import { NProgress } from "naive-ui";
|
||||
import pubsub from "pubsub-js";
|
||||
import { getSongDetial } from "@/network/song";
|
||||
import dayjs from "dayjs";
|
||||
import "dayjs/locale/zh-cn";
|
||||
import duration from "dayjs/plugin/duration";
|
||||
|
||||
const store = useStore();
|
||||
const progress = ref("");
|
||||
const wpProgress = ref("");
|
||||
const setTime = (e) => {
|
||||
//设定状态条长度
|
||||
rightDot.value = wpProgress.value.clientWidth - e.offsetX + 'px'
|
||||
percentage.value = e.offsetX / wpProgress.value.clientWidth * 100
|
||||
// console.log(rightDot.value);
|
||||
//发布 设置进度条消息
|
||||
pubsub.publish("zp.setProgressScale", {
|
||||
scale: e.offsetX / wpProgress.value.clientWidth,
|
||||
});
|
||||
};
|
||||
|
||||
// const primaryColor = store.state.theme.themeOverrides.common.primaryColor;
|
||||
const rightDot = ref("px");
|
||||
//#region 处理消息订阅
|
||||
|
||||
let percentage = ref(0.0);
|
||||
const psToken = pubsub.subscribe("zp", (msg, data) => {
|
||||
switch (msg) {
|
||||
case "zp.progress":
|
||||
percentage.value = (data.progress * 100) / data.total;
|
||||
rightDot.value =
|
||||
(1 - data.progress / (data.total - 0)) *
|
||||
wpProgress.value.clientWidth +
|
||||
"px";
|
||||
// console.log(rightDot.value);
|
||||
break;
|
||||
}
|
||||
});
|
||||
//卸载组件
|
||||
onUnmounted(() => {
|
||||
pubsub.unsubscribe(psToken);
|
||||
});
|
||||
//#endregion
|
||||
</script>
|
||||
<template>
|
||||
<div id="wpProgress" ref="wpProgress">
|
||||
<n-progress
|
||||
class="progress"
|
||||
type="line"
|
||||
:percentage="percentage"
|
||||
:show-indicator="false"
|
||||
:color="
|
||||
store.state.theme.themeOverrides.common.primaryColor
|
||||
"
|
||||
:height="3"
|
||||
:border-radius="0"
|
||||
ref="progress"
|
||||
@click="setTime"
|
||||
/>
|
||||
<div
|
||||
class="dot"
|
||||
:style="{
|
||||
backgroundColor:
|
||||
store.state.theme.themeOverrides.common
|
||||
.primaryColor,
|
||||
right: rightDot,
|
||||
}"
|
||||
></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {};
|
||||
</script>
|
||||
|
||||
<style lang="less" scope>
|
||||
#wpProgress {
|
||||
position: relative;
|
||||
// overflow: visible;
|
||||
::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.progress {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.dot {
|
||||
position: absolute;
|
||||
// background-color: red;
|
||||
height: 10px;
|
||||
width: 10px;
|
||||
border-radius: 6px;
|
||||
top: -4px;
|
||||
// left: -4px;
|
||||
display: none;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
.dot {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
83
src/views/common/SongStatus.vue
Normal file
83
src/views/common/SongStatus.vue
Normal file
@@ -0,0 +1,83 @@
|
||||
<script setup>
|
||||
import { ref } from "vue";
|
||||
import { NButton, NIcon, NSpace } from "naive-ui";
|
||||
import PlaylistMusic from "@/assets/svgs/PlaylistMusic.svg";
|
||||
import VolumeOffOutline from "@/assets/svgs/VolumeOffOutline.svg";
|
||||
import RepeatOutline from "@/assets/svgs/RepeatOutline.svg";
|
||||
import RepeatOne from "@/assets/svgs/RepeatOne.svg";
|
||||
import Playlist from "@/assets/svgs/Playlist.svg";
|
||||
import Random from "@/assets/svgs/Random.svg";
|
||||
|
||||
|
||||
//播放模式:0-3,顺序,循环,单曲,随机。
|
||||
const playMode = ref(0)
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<!-- <div id="songsCtrl"> -->
|
||||
<n-space
|
||||
id="songStatus"
|
||||
justify="end"
|
||||
align="center"
|
||||
:size="[6]"
|
||||
style="padding-top: 2px; padding-right: 8px"
|
||||
>
|
||||
<n-button circle v-if="playMode==1">
|
||||
<template #icon>
|
||||
<n-icon>
|
||||
<RepeatOutline />
|
||||
</n-icon>
|
||||
</template>
|
||||
</n-button>
|
||||
<n-button circle v-if="playMode==2">
|
||||
<template #icon>
|
||||
<n-icon>
|
||||
<RepeatOne />
|
||||
</n-icon>
|
||||
</template>
|
||||
</n-button>
|
||||
<n-button circle v-if="playMode==0">
|
||||
<template #icon>
|
||||
<n-icon>
|
||||
<Playlist />
|
||||
</n-icon>
|
||||
</template>
|
||||
</n-button>
|
||||
<n-button circle v-if="playMode==3">
|
||||
<template #icon>
|
||||
<n-icon>
|
||||
<Random />
|
||||
</n-icon>
|
||||
</template>
|
||||
</n-button>
|
||||
<n-button circle>
|
||||
<template #icon>
|
||||
<n-icon>
|
||||
<PlaylistMusic />
|
||||
</n-icon>
|
||||
</template>
|
||||
</n-button>
|
||||
<n-button circle>
|
||||
<template #icon>
|
||||
<n-icon>
|
||||
<VolumeOffOutline />
|
||||
</n-icon>
|
||||
</template>
|
||||
</n-button>
|
||||
</n-space>
|
||||
|
||||
<!-- </div> -->
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
#songStatus {
|
||||
flex: 2;
|
||||
}
|
||||
</style>
|
||||
18
src/views/common/TopMenu.vue
Normal file
18
src/views/common/TopMenu.vue
Normal file
@@ -0,0 +1,18 @@
|
||||
<template>
|
||||
<div id="topmenu">
|
||||
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
#topmenu{
|
||||
flex: 1;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user