mirror of
https://github.com/algerkong/AlgerMusicPlayer.git
synced 2026-04-24 16:27:23 +08:00
✨ feat: 添加动画速度调整功能 优化页面自适应效果
This commit is contained in:
Vendored
+2
@@ -16,6 +16,7 @@ declare module 'vue' {
|
|||||||
NAvatar: typeof import('naive-ui')['NAvatar']
|
NAvatar: typeof import('naive-ui')['NAvatar']
|
||||||
NButton: typeof import('naive-ui')['NButton']
|
NButton: typeof import('naive-ui')['NButton']
|
||||||
NButtonGroup: typeof import('naive-ui')['NButtonGroup']
|
NButtonGroup: typeof import('naive-ui')['NButtonGroup']
|
||||||
|
NCheckbox: typeof import('naive-ui')['NCheckbox']
|
||||||
NConfigProvider: typeof import('naive-ui')['NConfigProvider']
|
NConfigProvider: typeof import('naive-ui')['NConfigProvider']
|
||||||
NDialogProvider: typeof import('naive-ui')['NDialogProvider']
|
NDialogProvider: typeof import('naive-ui')['NDialogProvider']
|
||||||
NDrawer: typeof import('naive-ui')['NDrawer']
|
NDrawer: typeof import('naive-ui')['NDrawer']
|
||||||
@@ -37,6 +38,7 @@ declare module 'vue' {
|
|||||||
PlayListsItem: typeof import('./src/components/common/PlayListsItem.vue')['default']
|
PlayListsItem: typeof import('./src/components/common/PlayListsItem.vue')['default']
|
||||||
PlaylistType: typeof import('./src/components/PlaylistType.vue')['default']
|
PlaylistType: typeof import('./src/components/PlaylistType.vue')['default']
|
||||||
PlayVideo: typeof import('./src/components/common/PlayVideo.vue')['default']
|
PlayVideo: typeof import('./src/components/common/PlayVideo.vue')['default']
|
||||||
|
PWAInstallPrompt: typeof import('./src/components/common/PWAInstallPrompt.vue')['default']
|
||||||
RecommendAlbum: typeof import('./src/components/RecommendAlbum.vue')['default']
|
RecommendAlbum: typeof import('./src/components/RecommendAlbum.vue')['default']
|
||||||
RecommendSinger: typeof import('./src/components/RecommendSinger.vue')['default']
|
RecommendSinger: typeof import('./src/components/RecommendSinger.vue')['default']
|
||||||
RecommendSonglist: typeof import('./src/components/RecommendSonglist.vue')['default']
|
RecommendSonglist: typeof import('./src/components/RecommendSonglist.vue')['default']
|
||||||
|
|||||||
+4
-2
@@ -1,5 +1,7 @@
|
|||||||
{
|
{
|
||||||
"version": "1.5.1",
|
|
||||||
"isProxy": false,
|
"isProxy": false,
|
||||||
"author": "alger"
|
"noAnimate": false,
|
||||||
|
"animationSpeed": 1,
|
||||||
|
"author": "Alger",
|
||||||
|
"authorUrl": "https://github.com/algerkong"
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -47,7 +47,7 @@
|
|||||||
"postcss": "^8.4.49",
|
"postcss": "^8.4.49",
|
||||||
"prettier": "^3.3.3",
|
"prettier": "^3.3.3",
|
||||||
"remixicon": "^4.2.0",
|
"remixicon": "^4.2.0",
|
||||||
"sass": "^1.78.0",
|
"sass": "^1.82.0",
|
||||||
"tailwindcss": "^3.4.15",
|
"tailwindcss": "^3.4.15",
|
||||||
"typescript": "^5.5.4",
|
"typescript": "^5.5.4",
|
||||||
"unplugin-auto-import": "^0.18.2",
|
"unplugin-auto-import": "^0.18.2",
|
||||||
|
|||||||
+3
-6
@@ -11,20 +11,17 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { darkTheme } from 'naive-ui';
|
import { darkTheme } from 'naive-ui';
|
||||||
|
import { computed, onMounted } from 'vue';
|
||||||
|
|
||||||
import store from '@/store';
|
import store from '@/store';
|
||||||
|
|
||||||
import { isMobile } from './utils';
|
import { isMobile } from './utils';
|
||||||
|
|
||||||
const playMusicUrl = computed(() => store.state.playMusicUrl as string);
|
const playMusicUrl = computed(() => store.state.playMusicUrl as string);
|
||||||
// 是否播放
|
|
||||||
const play = computed(() => store.state.play as boolean);
|
const play = computed(() => store.state.play as boolean);
|
||||||
const windowData = window as any;
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
if (windowData.electron) {
|
store.dispatch('initializeSettings');
|
||||||
const setData = windowData.electron.ipcRenderer.getStoreValue('set');
|
|
||||||
store.commit('setSetData', setData);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="app-info">
|
<div class="app-info">
|
||||||
<h2 class="app-name">Alger Music</h2>
|
<h2 class="app-name">Alger Music</h2>
|
||||||
<p class="app-desc">在桌面安装应用,获得更好的体验</p>
|
<p class="app-desc mb-2">在桌面安装应用,获得更好的体验</p>
|
||||||
|
<n-checkbox v-model:checked="noPrompt">不再提示</n-checkbox>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-actions">
|
<div class="modal-actions">
|
||||||
@@ -23,10 +24,13 @@ import { onMounted, ref } from 'vue';
|
|||||||
|
|
||||||
const showModal = ref(false);
|
const showModal = ref(false);
|
||||||
const isElectron = ref((window as any).electron !== undefined);
|
const isElectron = ref((window as any).electron !== undefined);
|
||||||
|
const noPrompt = ref(false);
|
||||||
|
|
||||||
const closeModal = () => {
|
const closeModal = () => {
|
||||||
showModal.value = false;
|
showModal.value = false;
|
||||||
localStorage.setItem('installPromptDismissed', 'true');
|
if (noPrompt.value) {
|
||||||
|
localStorage.setItem('installPromptDismissed', 'true');
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleInstall = async () => {
|
const handleInstall = async () => {
|
||||||
|
|||||||
+37
-3
@@ -4,6 +4,15 @@ import { useMusicListHook } from '@/hooks/MusicListHook';
|
|||||||
import homeRouter from '@/router/home';
|
import homeRouter from '@/router/home';
|
||||||
import type { SongResult } from '@/type/music';
|
import type { SongResult } from '@/type/music';
|
||||||
|
|
||||||
|
// 默认设置
|
||||||
|
const defaultSettings = {
|
||||||
|
isProxy: false,
|
||||||
|
noAnimate: false,
|
||||||
|
animationSpeed: 1,
|
||||||
|
author: 'Alger',
|
||||||
|
authorUrl: 'https://github.com/algerkong',
|
||||||
|
};
|
||||||
|
|
||||||
interface State {
|
interface State {
|
||||||
menus: any[];
|
menus: any[];
|
||||||
play: boolean;
|
play: boolean;
|
||||||
@@ -29,7 +38,7 @@ const state: State = {
|
|||||||
user: localStorage.getItem('user') ? JSON.parse(localStorage.getItem('user') as string) : null,
|
user: localStorage.getItem('user') ? JSON.parse(localStorage.getItem('user') as string) : null,
|
||||||
playList: [],
|
playList: [],
|
||||||
playListIndex: 0,
|
playListIndex: 0,
|
||||||
setData: null,
|
setData: defaultSettings,
|
||||||
lyric: {},
|
lyric: {},
|
||||||
isMobile: false,
|
isMobile: false,
|
||||||
searchValue: '',
|
searchValue: '',
|
||||||
@@ -61,10 +70,34 @@ const mutations = {
|
|||||||
async prevPlay(state: State) {
|
async prevPlay(state: State) {
|
||||||
await prevPlay(state);
|
await prevPlay(state);
|
||||||
},
|
},
|
||||||
async setSetData(state: State, setData: any) {
|
setSetData(state: State, setData: any) {
|
||||||
state.setData = setData;
|
state.setData = setData;
|
||||||
if ((window as any).electron) {
|
const isElectron = (window as any).electronAPI !== undefined;
|
||||||
|
if (isElectron) {
|
||||||
(window as any).electron.ipcRenderer.setStoreValue('set', JSON.parse(JSON.stringify(setData)));
|
(window as any).electron.ipcRenderer.setStoreValue('set', JSON.parse(JSON.stringify(setData)));
|
||||||
|
} else {
|
||||||
|
localStorage.setItem('appSettings', JSON.stringify(setData));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const actions = {
|
||||||
|
initializeSettings({ commit }: { commit: any }) {
|
||||||
|
const isElectron = (window as any).electronAPI !== undefined;
|
||||||
|
|
||||||
|
if (isElectron) {
|
||||||
|
const setData = (window as any).electron.ipcRenderer.getStoreValue('set');
|
||||||
|
commit('setSetData', setData || defaultSettings);
|
||||||
|
} else {
|
||||||
|
const savedSettings = localStorage.getItem('appSettings');
|
||||||
|
if (savedSettings) {
|
||||||
|
commit('setSetData', {
|
||||||
|
...defaultSettings,
|
||||||
|
...JSON.parse(savedSettings),
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
commit('setSetData', defaultSettings);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -72,6 +105,7 @@ const mutations = {
|
|||||||
const store = createStore({
|
const store = createStore({
|
||||||
state,
|
state,
|
||||||
mutations,
|
mutations,
|
||||||
|
actions,
|
||||||
});
|
});
|
||||||
|
|
||||||
export default store;
|
export default store;
|
||||||
|
|||||||
+11
-2
@@ -11,11 +11,20 @@ export const setAnimationClass = (type: String) => {
|
|||||||
if (store.state.setData && store.state.setData.noAnimate) {
|
if (store.state.setData && store.state.setData.noAnimate) {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
return `animate__animated ${type}`;
|
const speed = store.state.setData?.animationSpeed || 1;
|
||||||
|
|
||||||
|
let speedClass = '';
|
||||||
|
if (speed <= 0.3) speedClass = 'animate__slower';
|
||||||
|
else if (speed <= 0.8) speedClass = 'animate__slow';
|
||||||
|
else if (speed >= 2.5) speedClass = 'animate__faster';
|
||||||
|
else if (speed >= 1.5) speedClass = 'animate__fast';
|
||||||
|
|
||||||
|
return `animate__animated ${type}${speedClass ? ` ${speedClass}` : ''}`;
|
||||||
};
|
};
|
||||||
// 设置动画延时
|
// 设置动画延时
|
||||||
export const setAnimationDelay = (index: number = 6, time: number = 50) => {
|
export const setAnimationDelay = (index: number = 6, time: number = 50) => {
|
||||||
return `animation-delay:${index * time}ms`;
|
const speed = store.state.setData?.animationSpeed || 1;
|
||||||
|
return `animation-delay:${(index * time) / (speed * 2)}ms`;
|
||||||
};
|
};
|
||||||
|
|
||||||
// 将秒转换为分钟和秒
|
// 将秒转换为分钟和秒
|
||||||
|
|||||||
+11
-37
@@ -5,19 +5,13 @@ import { getListByCat, getListDetail, getRecommendList } from '@/api/list';
|
|||||||
import MusicList from '@/components/MusicList.vue';
|
import MusicList from '@/components/MusicList.vue';
|
||||||
import type { IRecommendItem } from '@/type/list';
|
import type { IRecommendItem } from '@/type/list';
|
||||||
import type { IListDetail } from '@/type/listDetail';
|
import type { IListDetail } from '@/type/listDetail';
|
||||||
import { formatNumber, getImgUrl, isMobile, setAnimationClass, setAnimationDelay } from '@/utils';
|
import { formatNumber, getImgUrl, setAnimationClass, setAnimationDelay } from '@/utils';
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: 'List',
|
name: 'List',
|
||||||
});
|
});
|
||||||
|
|
||||||
const ITEMS_PER_ROW = ref(6); // 每行显示的数量
|
const TOTAL_ITEMS = 40; // 每页数量
|
||||||
const TOTAL_ITEMS = 30; // 每页数量
|
|
||||||
|
|
||||||
// 计算实际需要加载的数量,确保能被每行数量整除
|
|
||||||
const getAdjustedLimit = (perRow: number) => {
|
|
||||||
return Math.ceil(TOTAL_ITEMS / perRow) * perRow;
|
|
||||||
};
|
|
||||||
|
|
||||||
const recommendList = ref<any[]>([]);
|
const recommendList = ref<any[]>([]);
|
||||||
const showMusic = ref(false);
|
const showMusic = ref(false);
|
||||||
@@ -25,11 +19,9 @@ const page = ref(0);
|
|||||||
const hasMore = ref(true);
|
const hasMore = ref(true);
|
||||||
const isLoadingMore = ref(false);
|
const isLoadingMore = ref(false);
|
||||||
|
|
||||||
// 计算每个项目在当前页面中的索引
|
// 计算每个项目的动画延迟
|
||||||
const getItemAnimationDelay = (index: number) => {
|
const getItemAnimationDelay = (index: number) => {
|
||||||
const adjustedLimit = getAdjustedLimit(ITEMS_PER_ROW.value);
|
return setAnimationDelay(index, 30);
|
||||||
const currentPageIndex = index % adjustedLimit;
|
|
||||||
return setAnimationDelay(currentPageIndex, 30);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const recommendItem = ref<IRecommendItem | null>();
|
const recommendItem = ref<IRecommendItem | null>();
|
||||||
@@ -62,11 +54,10 @@ const loadList = async (type: string, isLoadMore = false) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const adjustedLimit = getAdjustedLimit(ITEMS_PER_ROW.value);
|
|
||||||
const params = {
|
const params = {
|
||||||
cat: type || '',
|
cat: type || '',
|
||||||
limit: adjustedLimit,
|
limit: TOTAL_ITEMS,
|
||||||
offset: page.value * adjustedLimit,
|
offset: page.value * TOTAL_ITEMS,
|
||||||
};
|
};
|
||||||
const { data } = await getListByCat(params);
|
const { data } = await getListByCat(params);
|
||||||
if (isLoadMore) {
|
if (isLoadMore) {
|
||||||
@@ -93,35 +84,16 @@ const handleScroll = (e: any) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 监听窗口大小变化,调整每行显示数量
|
|
||||||
const updateItemsPerRow = () => {
|
|
||||||
const width = window.innerWidth;
|
|
||||||
if (isMobile.value) {
|
|
||||||
ITEMS_PER_ROW.value = 2;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (width > 1800) ITEMS_PER_ROW.value = 8;
|
|
||||||
else if (width > 1200) ITEMS_PER_ROW.value = 8;
|
|
||||||
else if (width > 768) ITEMS_PER_ROW.value = 6;
|
|
||||||
else ITEMS_PER_ROW.value = 5;
|
|
||||||
};
|
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
updateItemsPerRow();
|
|
||||||
window.addEventListener('resize', updateItemsPerRow);
|
|
||||||
if (route.query.type) {
|
if (route.query.type) {
|
||||||
loadList(route.query.type as string);
|
loadList(route.query.type as string);
|
||||||
} else {
|
} else {
|
||||||
getRecommendList(getAdjustedLimit(ITEMS_PER_ROW.value)).then((res: { data: { result: any } }) => {
|
getRecommendList(TOTAL_ITEMS).then((res: { data: { result: any } }) => {
|
||||||
recommendList.value = res.data.result;
|
recommendList.value = res.data.result;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
onUnmounted(() => {
|
|
||||||
window.removeEventListener('resize', updateItemsPerRow);
|
|
||||||
});
|
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => route.query,
|
() => route.query,
|
||||||
async (newParams) => {
|
async (newParams) => {
|
||||||
@@ -195,12 +167,12 @@ watch(
|
|||||||
|
|
||||||
&-list {
|
&-list {
|
||||||
@apply grid gap-x-8 gap-y-6 pb-28 pr-4;
|
@apply grid gap-x-8 gap-y-6 pb-28 pr-4;
|
||||||
grid-template-columns: repeat(v-bind(ITEMS_PER_ROW), minmax(0, 1fr));
|
grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
|
||||||
}
|
}
|
||||||
&-item {
|
&-item {
|
||||||
@apply flex flex-col;
|
@apply flex flex-col;
|
||||||
&-img {
|
&-img {
|
||||||
@apply rounded-xl overflow-hidden relative w-full;
|
@apply rounded-xl overflow-hidden relative w-full aspect-square;
|
||||||
&-img {
|
&-img {
|
||||||
@apply block w-full h-full;
|
@apply block w-full h-full;
|
||||||
}
|
}
|
||||||
@@ -248,6 +220,8 @@ watch(
|
|||||||
.mobile {
|
.mobile {
|
||||||
.recommend-list {
|
.recommend-list {
|
||||||
@apply px-4;
|
@apply px-4;
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
gap: 1rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
+8
-12
@@ -13,14 +13,7 @@
|
|||||||
:style="getItemAnimationDelay(index)"
|
:style="getItemAnimationDelay(index)"
|
||||||
>
|
>
|
||||||
<div class="mv-item-img" @click="handleShowMv(item, index)">
|
<div class="mv-item-img" @click="handleShowMv(item, index)">
|
||||||
<n-image
|
<n-image class="mv-item-img-img" :src="getImgUrl(item.cover, '320y180')" lazy preview-disabled />
|
||||||
class="mv-item-img-img"
|
|
||||||
:src="getImgUrl(item.cover, '200y112')"
|
|
||||||
lazy
|
|
||||||
preview-disabled
|
|
||||||
width="200"
|
|
||||||
height="112"
|
|
||||||
/>
|
|
||||||
<div class="top">
|
<div class="top">
|
||||||
<div class="play-count">{{ formatNumber(item.playCount) }}</div>
|
<div class="play-count">{{ formatNumber(item.playCount) }}</div>
|
||||||
<i class="iconfont icon-videofill"></i>
|
<i class="iconfont icon-videofill"></i>
|
||||||
@@ -169,8 +162,8 @@ const isPrevDisabled = computed(() => currentIndex.value === 0);
|
|||||||
}
|
}
|
||||||
|
|
||||||
&-content {
|
&-content {
|
||||||
@apply grid gap-6 pb-28 mt-2 pr-4;
|
@apply grid gap-4 pb-28 mt-2 pr-4;
|
||||||
grid-template-columns: repeat(auto-fill, minmax(14%, 1fr));
|
grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
|
||||||
}
|
}
|
||||||
|
|
||||||
.mv-item {
|
.mv-item {
|
||||||
@@ -178,6 +171,7 @@ const isPrevDisabled = computed(() => currentIndex.value === 0);
|
|||||||
background-color: #1f1f1f;
|
background-color: #1f1f1f;
|
||||||
&-img {
|
&-img {
|
||||||
@apply rounded-lg overflow-hidden relative;
|
@apply rounded-lg overflow-hidden relative;
|
||||||
|
aspect-ratio: 16/9;
|
||||||
line-height: 0;
|
line-height: 0;
|
||||||
|
|
||||||
&:hover img {
|
&:hover img {
|
||||||
@@ -185,7 +179,7 @@ const isPrevDisabled = computed(() => currentIndex.value === 0);
|
|||||||
}
|
}
|
||||||
|
|
||||||
&-img {
|
&-img {
|
||||||
@apply w-full rounded-lg overflow-hidden;
|
@apply w-full h-full object-cover rounded-lg overflow-hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.top {
|
.top {
|
||||||
@@ -224,7 +218,9 @@ const isPrevDisabled = computed(() => currentIndex.value === 0);
|
|||||||
|
|
||||||
.mobile {
|
.mobile {
|
||||||
.mv-list-content {
|
.mv-list-content {
|
||||||
grid-template-columns: repeat(auto-fill, minmax(30%, 1fr));
|
@apply px-4;
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
gap: 1rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+66
-12
@@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="set-page">
|
<div class="set-page">
|
||||||
<div class="set-item">
|
<div v-if="isElectron" class="set-item">
|
||||||
<div>
|
<div>
|
||||||
<div class="set-item-title">代理</div>
|
<div class="set-item-title">代理</div>
|
||||||
<div class="set-item-content">无法听音乐时打开</div>
|
<div class="set-item-content">无法听音乐时打开</div>
|
||||||
@@ -9,10 +9,34 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="set-item">
|
<div class="set-item">
|
||||||
<div>
|
<div>
|
||||||
<div class="set-item-title">减轻动画效果</div>
|
<div class="set-item-title">关闭动画效果</div>
|
||||||
</div>
|
</div>
|
||||||
<n-switch v-model:value="setData.noAnimate" />
|
<n-switch v-model:value="setData.noAnimate" />
|
||||||
</div>
|
</div>
|
||||||
|
<div class="set-item">
|
||||||
|
<div>
|
||||||
|
<div class="set-item-title">动画速度</div>
|
||||||
|
<div class="set-item-content">调节动画播放速度</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
<span class="text-sm text-gray-400">{{ setData.animationSpeed }}x</span>
|
||||||
|
<div class="w-40">
|
||||||
|
<n-slider
|
||||||
|
v-model:value="setData.animationSpeed"
|
||||||
|
:min="0.1"
|
||||||
|
:max="3"
|
||||||
|
:step="0.1"
|
||||||
|
:marks="{
|
||||||
|
0.1: '极慢',
|
||||||
|
1: '正常',
|
||||||
|
3: '极快',
|
||||||
|
}"
|
||||||
|
:disabled="setData.noAnimate"
|
||||||
|
class="w-40"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="set-item">
|
<div class="set-item">
|
||||||
<div>
|
<div>
|
||||||
<div class="set-item-title">版本</div>
|
<div class="set-item-title">版本</div>
|
||||||
@@ -20,22 +44,37 @@
|
|||||||
</div>
|
</div>
|
||||||
<div>{{ config.version }}</div>
|
<div>{{ config.version }}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="set-item">
|
<div class="set-item cursor-pointer hover:text-green-500 hover:bg-green-950 transition-all" @click="openAuthor">
|
||||||
<div>
|
<div>
|
||||||
<div class="set-item-title">作者</div>
|
<div class="set-item-title">作者</div>
|
||||||
<div class="set-item-content"></div>
|
<div class="set-item-content">algerkong github</div>
|
||||||
</div>
|
</div>
|
||||||
<div>{{ setData.author }}</div>
|
<div>{{ setData.author }}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="set-action">
|
<div class="set-action">
|
||||||
<n-button @click="handelCancel">取消</n-button>
|
<n-button class="w-40 h-10" @click="handelCancel">取消</n-button>
|
||||||
<n-button type="primary" @click="handleSave">保存并重启</n-button>
|
<n-button type="primary" class="w-40 h-10" @click="handleSave">{{ isElectron ? '保存并重启' : '保存' }}</n-button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="p-6 bg-black rounded-lg shadow-lg mt-20">
|
||||||
|
<div class="text-gray-100 text-base text-center">支持作者</div>
|
||||||
|
<div class="flex gap-60">
|
||||||
|
<div class="flex flex-col items-center gap-2 cursor-pointer hover:scale-[2] transition-all z-10 bg-black">
|
||||||
|
<n-image :src="alipayQR" alt="支付宝收款码" class="w-32 h-32 rounded-lg" preview-disabled />
|
||||||
|
<span class="text-sm text-gray-100">支付宝</span>
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-col items-center gap-2 cursor-pointer hover:scale-[2] transition-all z-10 bg-black">
|
||||||
|
<n-image :src="wechatQR" alt="微信收款码" class="w-32 h-32 rounded-lg" preview-disabled />
|
||||||
|
<span class="text-sm text-gray-100">微信支付</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import { computed, ref } from 'vue';
|
||||||
import { useRouter } from 'vue-router';
|
import { useRouter } from 'vue-router';
|
||||||
|
|
||||||
import config from '@/../package.json';
|
import config from '@/../package.json';
|
||||||
@@ -45,20 +84,32 @@ defineOptions({
|
|||||||
name: 'Setting',
|
name: 'Setting',
|
||||||
});
|
});
|
||||||
|
|
||||||
const setData = ref(store.state.setData);
|
const alipayQR = 'https://github.com/algerkong/algerkong/blob/main/alipay.jpg?raw=true';
|
||||||
|
const wechatQR = 'https://github.com/algerkong/algerkong/blob/main/wechat.jpg?raw=true';
|
||||||
|
|
||||||
|
const isElectron = ref((window as any).electronAPI !== undefined);
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
|
// 使用计算属性来获取和设置数据
|
||||||
|
const setData = computed({
|
||||||
|
get: () => store.state.setData,
|
||||||
|
set: (value) => store.commit('setSetData', value),
|
||||||
|
});
|
||||||
|
|
||||||
const handelCancel = () => {
|
const handelCancel = () => {
|
||||||
router.back();
|
router.back();
|
||||||
};
|
};
|
||||||
|
|
||||||
const windowData = window as any;
|
|
||||||
|
|
||||||
const handleSave = () => {
|
const handleSave = () => {
|
||||||
store.commit('setSetData', setData.value);
|
store.commit('setSetData', setData.value);
|
||||||
if (windowData.electronAPI) {
|
if (isElectron.value) {
|
||||||
windowData.electronAPI.restart();
|
(window as any).electronAPI.restart();
|
||||||
}
|
}
|
||||||
|
router.back();
|
||||||
|
};
|
||||||
|
|
||||||
|
const openAuthor = () => {
|
||||||
|
window.open(setData.value.authorUrl, '_blank');
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -67,7 +118,7 @@ const handleSave = () => {
|
|||||||
@apply flex flex-col justify-center items-center pt-8;
|
@apply flex flex-col justify-center items-center pt-8;
|
||||||
}
|
}
|
||||||
.set-item {
|
.set-item {
|
||||||
@apply w-3/5 flex justify-between items-center mb-4;
|
@apply w-3/5 flex justify-between items-center mb-2 px-4 py-2 rounded-lg;
|
||||||
.set-item-title {
|
.set-item-title {
|
||||||
@apply text-gray-200 text-base;
|
@apply text-gray-200 text-base;
|
||||||
}
|
}
|
||||||
@@ -75,4 +126,7 @@ const handleSave = () => {
|
|||||||
@apply text-gray-400 text-sm;
|
@apply text-gray-400 text-sm;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.set-action {
|
||||||
|
@apply flex gap-3 mt-4;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user