feat: 修改样式和启动命令

This commit is contained in:
alger
2023-12-19 14:42:53 +08:00
parent 9211dcd3bb
commit 6c8229a21d
13 changed files with 239 additions and 233 deletions
+1 -1
View File
@@ -14,8 +14,8 @@ function createWindow() {
win.setMinimumSize(1280, 900); win.setMinimumSize(1280, 900);
if (process.env.NODE_ENV === 'dev') { if (process.env.NODE_ENV === 'dev') {
win.loadURL('http://localhost:4678/')
win.webContents.openDevTools({ mode: 'detach' }) win.webContents.openDevTools({ mode: 'detach' })
win.loadURL('http://localhost:4678/')
} else { } else {
win.loadURL(`file://${__dirname}/dist/index.html`) win.loadURL(`file://${__dirname}/dist/index.html`)
} }
+1
View File
@@ -10,6 +10,7 @@
href="./public/icon/iconfont.css" href="./public/icon/iconfont.css"
/> />
<link rel="stylesheet" href="./public/css/animate.css" /> <link rel="stylesheet" href="./public/css/animate.css" />
<link rel="stylesheet" href="./public/css/base.css" />
<style> <style>
:root { :root {
--animate-delay: 0.5s; --animate-delay: 0.5s;
+3 -4
View File
@@ -7,9 +7,9 @@
"build": "vite build", "build": "vite build",
"serve": "vite preview", "serve": "vite preview",
"es": "vite && electron .", "es": "vite && electron .",
"eb": "vite build && electron-builder", "start": "set NODE_ENV=production && electron .",
"start": "electron .", "e:b": "electron-builder --config ./electron.config.json",
"e:b": "electron-builder --config ./electron.config.json" "eb": "vite build && e:b"
}, },
"dependencies": { "dependencies": {
"@tailwindcss/postcss7-compat": "^2.2.4", "@tailwindcss/postcss7-compat": "^2.2.4",
@@ -35,7 +35,6 @@
"typescript": "^4.3.2", "typescript": "^4.3.2",
"vfonts": "^0.1.0", "vfonts": "^0.1.0",
"vite": "^4.4.7", "vite": "^4.4.7",
"vite-plugin-electron-builder": "^0.1.0",
"vite-plugin-vue-devtools": "1.0.0-beta.5", "vite-plugin-vue-devtools": "1.0.0-beta.5",
"vue-tsc": "^0.0.24" "vue-tsc": "^0.0.24"
} }
+3
View File
@@ -0,0 +1,3 @@
body{
background-color: #000;
}
+2 -2
View File
@@ -2,7 +2,7 @@
<!-- 歌单分类列表 --> <!-- 歌单分类列表 -->
<div class="play-list-type"> <div class="play-list-type">
<div class="title" :class="setAnimationClass('animate__fadeInLeft')">歌单分类</div> <div class="title" :class="setAnimationClass('animate__fadeInLeft')">歌单分类</div>
<n-layout> <div>
<template v-for="(item, index) in playlistCategory?.sub" :key="item.name"> <template v-for="(item, index) in playlistCategory?.sub" :key="item.name">
<span <span
class="play-list-type-item" class="play-list-type-item"
@@ -24,7 +24,7 @@
" "
@click="isShowAllPlaylistCategory = !isShowAllPlaylistCategory" @click="isShowAllPlaylistCategory = !isShowAllPlaylistCategory"
>{{ !isShowAllPlaylistCategory ? "显示全部" : "隐藏一些" }}</div> >{{ !isShowAllPlaylistCategory ? "显示全部" : "隐藏一些" }}</div>
</n-layout> </div>
</div> </div>
</template> </template>
+1 -2
View File
@@ -137,8 +137,7 @@ defineExpose({
.music-lrc { .music-lrc {
background-color: inherit; background-color: inherit;
min-width: 400px; width: 500px;
max-width: 800px;
height: 550px; height: 550px;
&-text { &-text {
+2 -2
View File
@@ -82,7 +82,7 @@
<script lang="ts" setup> <script lang="ts" setup>
import type { SongResult } from '@/type/music' import type { SongResult } from '@/type/music'
import { secondToMinute, getImgUrl } from '@/utils' import { secondToMinute, getImgUrl, getIsMc } from '@/utils'
import { computed, onMounted, ref, watch } from 'vue' import { computed, onMounted, ref, watch } from 'vue'
import { useStore } from 'vuex' import { useStore } from 'vuex'
import { setAnimationClass } from '@/utils' import { setAnimationClass } from '@/utils'
@@ -107,7 +107,7 @@ const playMusicUrl = ref('')
watch( watch(
() => store.state.playMusicUrl, () => store.state.playMusicUrl,
async (value, oldValue) => { async (value, oldValue) => {
const isUrlHasMc = location.href.includes('mc.') const isUrlHasMc = getIsMc()
if (value && isUrlHasMc) { if (value && isUrlHasMc) {
let playMusicUrl1 = value as string let playMusicUrl1 = value as string
if (!ProxyUrl) { if (!ProxyUrl) {
+31 -31
View File
@@ -1,54 +1,54 @@
const layoutRouter = [ const layoutRouter = [
{ {
path: "/", path: '/',
name: "home", name: 'home',
mate: { mate: {
keepAlive: true, keepAlive: true,
title: "首页", title: '首页',
icon: "icon-Home", icon: 'icon-Home',
}, },
component: () => import("@/views/home/index.vue"), component: () => import('@/views/home/index.vue'),
}, },
{ {
path: "/search", path: '/search',
name: "search", name: 'search',
mate: { mate: {
title: "搜索", title: '搜索',
keepAlive: true, keepAlive: true,
icon: "icon-Search", icon: 'icon-Search',
}, },
component: () => import("@/views/search/index.vue"), component: () => import('@/views/search/index.vue'),
}, },
{ {
path: "/list", path: '/list',
name: "list", name: 'list',
mate: { mate: {
title: "歌单", title: '歌单',
keepAlive: true, keepAlive: true,
icon: "icon-Paper", icon: 'icon-Paper',
}, },
component: () => import("@/views/list/index.vue"), component: () => import('@/views/list/index.vue'),
}, },
{ {
path: "/user", path: '/user',
name: "user", name: 'user',
mate: { mate: {
title: "用户", title: '用户',
keepAlive: true, keepAlive: true,
icon: "icon-Profile", icon: 'icon-Profile',
}, },
component: () => import("@/views/user/index.vue"), component: () => import('@/views/user/index.vue'),
}, },
{ // {
path: "/test", // path: "/test",
name: "test", // name: "test",
mate: { // mate: {
title: "用户", // title: "用户",
keepAlive: true, // keepAlive: true,
icon: "icon-Profile", // icon: "icon-Profile",
}, // },
component: () => import("@/views/test/test.vue"), // component: () => import("@/views/test/test.vue"),
}, // },
]; ]
export default layoutRouter; export default layoutRouter;
+1 -1
View File
@@ -31,7 +31,7 @@ export const getIsMc = () => {
return true return true
} }
export const getImgUrl = computed(() => (url: string, size: string) => { export const getImgUrl = computed(() => (url: string, size: string = '') => {
const bdUrl = 'https://image.baidu.com/search/down?url=' const bdUrl = 'https://image.baidu.com/search/down?url='
const imgUrl = encodeURIComponent(`${url}?param=${size}`) const imgUrl = encodeURIComponent(`${url}?param=${size}`)
return `${bdUrl}${imgUrl}` return `${bdUrl}${imgUrl}`
+17 -16
View File
@@ -1,16 +1,18 @@
<template> <template>
<n-layout class="main-page" :native-scrollbar="false"> <div class="main-page">
<!-- 推荐歌手 --> <n-scrollbar>
<recommend-singer /> <!-- 推荐歌手 -->
<div class="main-content"> <recommend-singer />
<!-- 歌单分类列表 --> <div class="main-content">
<playlist-type /> <!-- 歌单分类列表 -->
<!-- 本周最热音乐 --> <playlist-type />
<recommend-songlist /> <!-- 本周最热音乐 -->
<!-- 推荐最新专辑 --> <recommend-songlist />
<recommend-album /> <!-- 推荐最新专辑 -->
</div> <recommend-album />
</n-layout> </div>
</n-scrollbar>
</div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
@@ -22,11 +24,10 @@ const RecommendAlbum = defineAsyncComponent(() => import("@/components/Recommend
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.main-page { .main-page{
@apply mt-4 h-full; @apply pt-4 h-full w-full;
} }
.main-content { .main-content {
@apply mt-6 flex; @apply mt-6 flex pb-28;
} }
</style> </style>
+6 -6
View File
@@ -105,7 +105,7 @@ const handlePlay = (item: any) => {
<template> <template>
<div class="list-page"> <div class="list-page">
<!-- 歌单列表 --> <!-- 歌单列表 -->
<n-layout class="recommend" :native-scrollbar="false" @click="showMusic = false"> <n-scrollbar class="recommend" @click="showMusic = false" :size="100">
<div <div
class="recommend-title" class="recommend-title"
:class="setAnimationClass('animate__bounceInLeft')" :class="setAnimationClass('animate__bounceInLeft')"
@@ -133,7 +133,7 @@ const handlePlay = (item: any) => {
<div class="recommend-item-title">{{ item.name }}</div> <div class="recommend-item-title">{{ item.name }}</div>
</div> </div>
</div> </div>
</n-layout> </n-scrollbar>
<transition name="musicPage"> <transition name="musicPage">
<div class="music-page" v-if="showMusic"> <div class="music-page" v-if="showMusic">
@@ -157,7 +157,7 @@ const handlePlay = (item: any) => {
<style lang="scss" scoped> <style lang="scss" scoped>
.list-page { .list-page {
@apply relative h-full; @apply relative h-full w-full pt-4;
} }
.musicPage-enter-active { .musicPage-enter-active {
@@ -169,13 +169,13 @@ const handlePlay = (item: any) => {
} }
.recommend { .recommend {
@apply w-full h-full; @apply w-full h-full bg-none;
&-title { &-title {
@apply text-lg font-bold text-white py-4; @apply text-lg font-bold text-white pb-4;
} }
&-list { &-list {
@apply grid gap-6 pb-28; @apply grid gap-6 pb-28 pr-3;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
} }
&-item { &-item {
+170 -167
View File
@@ -1,168 +1,171 @@
<script lang="ts" setup> <script lang="ts" setup>
import { getQrKey, createQr, checkQr, getLoginStatus } from '@/api/login' import { getQrKey, createQr, checkQr, getLoginStatus } from '@/api/login'
import { onMounted } from '@vue/runtime-core'; import { onMounted } from '@vue/runtime-core';
import { ref } from 'vue'; import { ref } from 'vue';
import { getUserDetail, loginByCellphone } from '@/api/login'; import { getUserDetail, loginByCellphone } from '@/api/login';
import { useStore } from 'vuex'; import { useStore } from 'vuex';
import { useMessage } from 'naive-ui' import { useMessage } from 'naive-ui'
import { setAnimationClass, setAnimationDelay } from "@/utils"; import { setAnimationClass, setAnimationDelay } from "@/utils";
import { useRouter } from 'vue-router'; import { useRouter } from 'vue-router';
const message = useMessage() const message = useMessage()
const store = useStore(); const store = useStore();
const router = useRouter() const router = useRouter()
const qrUrl = ref<string>() const qrUrl = ref<string>()
onMounted(() => { onMounted(() => {
loadLogin() loadLogin()
}) })
const loadLogin = async () => { const loadLogin = async () => {
const qrKey = await getQrKey() const qrKey = await getQrKey()
const key = qrKey.data.data.unikey const key = qrKey.data.data.unikey
const { data } = await createQr(key) const { data } = await createQr(key)
qrUrl.value = data.data.qrimg qrUrl.value = data.data.qrimg
timerIsQr(key) timerIsQr(key)
} }
const timerIsQr = (key: string) => { const timerIsQr = (key: string) => {
const timer = setInterval(async () => { const timer = setInterval(async () => {
const { data } = await checkQr(key) const { data } = await checkQr(key)
if (data.code === 800) { if (data.code === 800) {
clearInterval(timer) clearInterval(timer)
} }
if (data.code === 803) { if (data.code === 803) {
// 将token存入localStorage // 将token存入localStorage
localStorage.setItem('token', data.cookie) localStorage.setItem('token', data.cookie)
const user = await getUserDetail() const user = await getUserDetail()
store.state.user = user.data.profile store.state.user = user.data.profile
message.success('登录成功') message.success('登录成功')
await getLoginStatus().then(res => { await getLoginStatus().then(res => {
console.log(res); console.log(res);
}) })
clearInterval(timer) clearInterval(timer)
} setTimeout(() => {
}, 5000); router.push('/user')
} }, 1000);
}
}, 5000);
// 是否扫码登陆 }
const isQr = ref(true)
const chooseQr = () => {
isQr.value = !isQr.value // 是否扫码登陆
} const isQr = ref(true)
const chooseQr = () => {
// 手机号登录 isQr.value = !isQr.value
const phone = ref('') }
const password = ref('')
const loginPhone = async () => { // 手机号登录
const { data } = await loginByCellphone(phone.value, password.value) const phone = ref('')
if (data.code === 200) { const password = ref('')
message.success('登录成功') const loginPhone = async () => {
store.state.user = data.profile const { data } = await loginByCellphone(phone.value, password.value)
localStorage.setItem('token', data.cookie) if (data.code === 200) {
setTimeout(() => { message.success('登录成功')
router.push('/') store.state.user = data.profile
}, 1000); localStorage.setItem('token', data.cookie)
} setTimeout(() => {
} router.push('/user')
}, 1000);
</script> }
}
<template>
<div class="login-page"> </script>
<div class="phone-login">
<div class="bg"></div> <template>
<div class="content"> <div class="login-page">
<div class="phone" v-if="isQr" :class="setAnimationClass('animate__fadeInUp')"> <div class="phone-login">
<div class="login-title">扫码登陆</div> <div class="bg"></div>
<img class="qr-img" :src="qrUrl" /> <div class="content">
<div class="text">使用网易云APP扫码登录</div> <div class="phone" v-if="isQr" :class="setAnimationClass('animate__fadeInUp')">
</div> <div class="login-title">扫码登陆</div>
<div class="phone" v-else :class="setAnimationClass('animate__fadeInUp')"> <img class="qr-img" :src="qrUrl" />
<div class="login-title">手机号登录</div> <div class="text">使用网易云APP扫码登录</div>
<div class="phone-page"> </div>
<input v-model="phone" class="phone-input" type="text" placeholder="手机号" /> <div class="phone" v-else :class="setAnimationClass('animate__fadeInUp')">
<input v-model="password" class="phone-input" type="password" placeholder="密码" /> <div class="login-title">手机号登录</div>
</div> <div class="phone-page">
<n-button class="btn-login" @click="loginPhone()">登录</n-button> <input v-model="phone" class="phone-input" type="text" placeholder="手机号" />
</div> <input v-model="password" class="phone-input" type="password" placeholder="密码" />
</div> </div>
<div class="bottom"> <n-button class="btn-login" @click="loginPhone()">登录</n-button>
<div class="title" @click="chooseQr()">{{ isQr ? '手机号登录' : '扫码登录' }}</div> </div>
</div> </div>
</div> <div class="bottom">
</div> <div class="title" @click="chooseQr()">{{ isQr ? '手机号登录' : '扫码登录' }}</div>
</template> </div>
</div>
<style lang="scss" scoped> </div>
.login-page { </template>
@apply p-4 flex flex-col items-center justify-center p-20;
} <style lang="scss" scoped>
.login-page {
.login-title { @apply p-4 flex flex-col items-center justify-center p-20;
@apply text-2xl font-bold mb-6; }
}
.login-title {
.text { @apply text-2xl font-bold mb-6;
@apply mt-4 text-green-500 text-xs; }
}
.text {
.phone-login { @apply mt-4 text-green-500 text-xs;
width: 350px; }
height: 550px;
@apply rounded-2xl rounded-b-none bg-cover bg-no-repeat relative overflow-hidden; .phone-login {
background-image: url(http://tva4.sinaimg.cn/large/006opRgRgy1gw8nf6no7uj30rs15n0x7.jpg); width: 350px;
background-color: #383838; height: 550px;
box-shadow: inset 0px 0px 20px 5px #0000005e; @apply rounded-2xl rounded-b-none bg-cover bg-no-repeat relative overflow-hidden;
background-image: url(http://tva4.sinaimg.cn/large/006opRgRgy1gw8nf6no7uj30rs15n0x7.jpg);
.bg { background-color: #383838;
@apply absolute w-full h-full bg-black opacity-30; box-shadow: inset 0px 0px 20px 5px #0000005e;
}
.bg {
.bottom { @apply absolute w-full h-full bg-black opacity-30;
width: 200%; }
height: 250px;
bottom: -180px; .bottom {
border-radius: 50%; width: 200%;
left: 50%; height: 250px;
padding: 10px; bottom: -180px;
transform: translateX(-50%); border-radius: 50%;
color: #ffffff99; left: 50%;
@apply absolute bg-black flex justify-center text-lg font-bold cursor-pointer; padding: 10px;
box-shadow: 10px 0px 20px #000000a9; transform: translateX(-50%);
} color: #ffffff99;
@apply absolute bg-black flex justify-center text-lg font-bold cursor-pointer;
.content { box-shadow: 10px 0px 20px #000000a9;
@apply absolute w-full h-full p-4 flex flex-col items-center justify-center pb-20 text-center; }
.qr-img {
@apply opacity-80 rounded-2xl cursor-pointer; .content {
} @apply absolute w-full h-full p-4 flex flex-col items-center justify-center pb-20 text-center;
.qr-img {
.phone { @apply opacity-80 rounded-2xl cursor-pointer;
animation-duration: 0.5s; }
&-page {
background-color: #ffffffdd; .phone {
width: 250px; animation-duration: 0.5s;
@apply rounded-2xl overflow-hidden; &-page {
} background-color: #ffffffdd;
width: 250px;
&-input { @apply rounded-2xl overflow-hidden;
height: 40px; }
border-bottom: 1px solid #e5e5e5;
@apply w-full text-black px-4 outline-none; &-input {
} height: 40px;
} border-bottom: 1px solid #e5e5e5;
.btn-login { @apply w-full text-black px-4 outline-none;
width: 250px; }
height: 40px; }
@apply mt-10 text-white rounded-xl bg-black opacity-60; .btn-login {
} width: 250px;
} height: 40px;
} @apply mt-10 text-white rounded-xl bg-black opacity-60;
}
}
}
</style> </style>
+1 -1
View File
@@ -89,7 +89,7 @@ const handlePlay = (item: any) => {
<div class="page"> <div class="page">
<div class="user-name">{{ user.nickname }}</div> <div class="user-name">{{ user.nickname }}</div>
<div class="user-info"> <div class="user-info">
<n-avatar round :size="50" :src="user.avatarUrl" /> <n-avatar round :size="50" :src="getImgUrl(user.avatarUrl)" />
<div class="user-info-list"> <div class="user-info-list">
<div class="user-info-item"> <div class="user-info-item">
<div class="label">{{ userDetail.profile.followeds }}</div> <div class="label">{{ userDetail.profile.followeds }}</div>