diff --git a/components.d.ts b/components.d.ts
index 99a9dd0..0e23dab 100644
--- a/components.d.ts
+++ b/components.d.ts
@@ -16,6 +16,7 @@ declare module 'vue' {
NAvatar: typeof import('naive-ui')['NAvatar']
NButton: typeof import('naive-ui')['NButton']
NButtonGroup: typeof import('naive-ui')['NButtonGroup']
+ NCheckbox: typeof import('naive-ui')['NCheckbox']
NConfigProvider: typeof import('naive-ui')['NConfigProvider']
NDialogProvider: typeof import('naive-ui')['NDialogProvider']
NDrawer: typeof import('naive-ui')['NDrawer']
@@ -37,6 +38,7 @@ declare module 'vue' {
PlayListsItem: typeof import('./src/components/common/PlayListsItem.vue')['default']
PlaylistType: typeof import('./src/components/PlaylistType.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']
RecommendSinger: typeof import('./src/components/RecommendSinger.vue')['default']
RecommendSonglist: typeof import('./src/components/RecommendSonglist.vue')['default']
diff --git a/electron/set.json b/electron/set.json
index 2eb3dd9..b43145a 100644
--- a/electron/set.json
+++ b/electron/set.json
@@ -1,5 +1,7 @@
{
- "version": "1.5.1",
"isProxy": false,
- "author": "alger"
+ "noAnimate": false,
+ "animationSpeed": 1,
+ "author": "Alger",
+ "authorUrl": "https://github.com/algerkong"
}
diff --git a/package.json b/package.json
index b58be56..d29d4ec 100644
--- a/package.json
+++ b/package.json
@@ -47,7 +47,7 @@
"postcss": "^8.4.49",
"prettier": "^3.3.3",
"remixicon": "^4.2.0",
- "sass": "^1.78.0",
+ "sass": "^1.82.0",
"tailwindcss": "^3.4.15",
"typescript": "^5.5.4",
"unplugin-auto-import": "^0.18.2",
diff --git a/src/App.vue b/src/App.vue
index daab34d..3773c51 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -11,20 +11,17 @@
diff --git a/src/components/common/InstallAppModal.vue b/src/components/common/InstallAppModal.vue
index 2b9deb0..48d8eeb 100644
--- a/src/components/common/InstallAppModal.vue
+++ b/src/components/common/InstallAppModal.vue
@@ -7,7 +7,8 @@
@@ -23,10 +24,13 @@ import { onMounted, ref } from 'vue';
const showModal = ref(false);
const isElectron = ref((window as any).electron !== undefined);
+const noPrompt = ref(false);
const closeModal = () => {
showModal.value = false;
- localStorage.setItem('installPromptDismissed', 'true');
+ if (noPrompt.value) {
+ localStorage.setItem('installPromptDismissed', 'true');
+ }
};
const handleInstall = async () => {
diff --git a/src/store/index.ts b/src/store/index.ts
index 8ca215e..077269d 100644
--- a/src/store/index.ts
+++ b/src/store/index.ts
@@ -4,6 +4,15 @@ import { useMusicListHook } from '@/hooks/MusicListHook';
import homeRouter from '@/router/home';
import type { SongResult } from '@/type/music';
+// 默认设置
+const defaultSettings = {
+ isProxy: false,
+ noAnimate: false,
+ animationSpeed: 1,
+ author: 'Alger',
+ authorUrl: 'https://github.com/algerkong',
+};
+
interface State {
menus: any[];
play: boolean;
@@ -29,7 +38,7 @@ const state: State = {
user: localStorage.getItem('user') ? JSON.parse(localStorage.getItem('user') as string) : null,
playList: [],
playListIndex: 0,
- setData: null,
+ setData: defaultSettings,
lyric: {},
isMobile: false,
searchValue: '',
@@ -61,10 +70,34 @@ const mutations = {
async prevPlay(state: State) {
await prevPlay(state);
},
- async setSetData(state: State, setData: any) {
+ setSetData(state: State, setData: any) {
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)));
+ } 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({
state,
mutations,
+ actions,
});
export default store;
diff --git a/src/utils/index.ts b/src/utils/index.ts
index 568c975..dc7848a 100644
--- a/src/utils/index.ts
+++ b/src/utils/index.ts
@@ -11,11 +11,20 @@ export const setAnimationClass = (type: String) => {
if (store.state.setData && store.state.setData.noAnimate) {
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) => {
- return `animation-delay:${index * time}ms`;
+ const speed = store.state.setData?.animationSpeed || 1;
+ return `animation-delay:${(index * time) / (speed * 2)}ms`;
};
// 将秒转换为分钟和秒
diff --git a/src/views/list/index.vue b/src/views/list/index.vue
index 9f74066..d5c7b27 100644
--- a/src/views/list/index.vue
+++ b/src/views/list/index.vue
@@ -5,19 +5,13 @@ import { getListByCat, getListDetail, getRecommendList } from '@/api/list';
import MusicList from '@/components/MusicList.vue';
import type { IRecommendItem } from '@/type/list';
import type { IListDetail } from '@/type/listDetail';
-import { formatNumber, getImgUrl, isMobile, setAnimationClass, setAnimationDelay } from '@/utils';
+import { formatNumber, getImgUrl, setAnimationClass, setAnimationDelay } from '@/utils';
defineOptions({
name: 'List',
});
-const ITEMS_PER_ROW = ref(6); // 每行显示的数量
-const TOTAL_ITEMS = 30; // 每页数量
-
-// 计算实际需要加载的数量,确保能被每行数量整除
-const getAdjustedLimit = (perRow: number) => {
- return Math.ceil(TOTAL_ITEMS / perRow) * perRow;
-};
+const TOTAL_ITEMS = 40; // 每页数量
const recommendList = ref
([]);
const showMusic = ref(false);
@@ -25,11 +19,9 @@ const page = ref(0);
const hasMore = ref(true);
const isLoadingMore = ref(false);
-// 计算每个项目在当前页面中的索引
+// 计算每个项目的动画延迟
const getItemAnimationDelay = (index: number) => {
- const adjustedLimit = getAdjustedLimit(ITEMS_PER_ROW.value);
- const currentPageIndex = index % adjustedLimit;
- return setAnimationDelay(currentPageIndex, 30);
+ return setAnimationDelay(index, 30);
};
const recommendItem = ref();
@@ -62,11 +54,10 @@ const loadList = async (type: string, isLoadMore = false) => {
}
try {
- const adjustedLimit = getAdjustedLimit(ITEMS_PER_ROW.value);
const params = {
cat: type || '',
- limit: adjustedLimit,
- offset: page.value * adjustedLimit,
+ limit: TOTAL_ITEMS,
+ offset: page.value * TOTAL_ITEMS,
};
const { data } = await getListByCat(params);
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(() => {
- updateItemsPerRow();
- window.addEventListener('resize', updateItemsPerRow);
if (route.query.type) {
loadList(route.query.type as string);
} 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;
});
}
});
-onUnmounted(() => {
- window.removeEventListener('resize', updateItemsPerRow);
-});
-
watch(
() => route.query,
async (newParams) => {
@@ -195,12 +167,12 @@ watch(
&-list {
@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 {
@apply flex flex-col;
&-img {
- @apply rounded-xl overflow-hidden relative w-full;
+ @apply rounded-xl overflow-hidden relative w-full aspect-square;
&-img {
@apply block w-full h-full;
}
@@ -248,6 +220,8 @@ watch(
.mobile {
.recommend-list {
@apply px-4;
+ grid-template-columns: repeat(2, 1fr);
+ gap: 1rem;
}
}
diff --git a/src/views/mv/index.vue b/src/views/mv/index.vue
index b68f0ae..8d11243 100644
--- a/src/views/mv/index.vue
+++ b/src/views/mv/index.vue
@@ -13,14 +13,7 @@
:style="getItemAnimationDelay(index)"
>
-
+
{{ formatNumber(item.playCount) }}
@@ -169,8 +162,8 @@ const isPrevDisabled = computed(() => currentIndex.value === 0);
}
&-content {
- @apply grid gap-6 pb-28 mt-2 pr-4;
- grid-template-columns: repeat(auto-fill, minmax(14%, 1fr));
+ @apply grid gap-4 pb-28 mt-2 pr-4;
+ grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
}
.mv-item {
@@ -178,6 +171,7 @@ const isPrevDisabled = computed(() => currentIndex.value === 0);
background-color: #1f1f1f;
&-img {
@apply rounded-lg overflow-hidden relative;
+ aspect-ratio: 16/9;
line-height: 0;
&:hover img {
@@ -185,7 +179,7 @@ const isPrevDisabled = computed(() => currentIndex.value === 0);
}
&-img {
- @apply w-full rounded-lg overflow-hidden;
+ @apply w-full h-full object-cover rounded-lg overflow-hidden;
}
.top {
@@ -224,7 +218,9 @@ const isPrevDisabled = computed(() => currentIndex.value === 0);
.mobile {
.mv-list-content {
- grid-template-columns: repeat(auto-fill, minmax(30%, 1fr));
+ @apply px-4;
+ grid-template-columns: repeat(2, 1fr);
+ gap: 1rem;
}
}
diff --git a/src/views/set/index.vue b/src/views/set/index.vue
index ce12e2e..e1d020b 100644
--- a/src/views/set/index.vue
+++ b/src/views/set/index.vue
@@ -1,6 +1,6 @@
-
+
代理
无法听音乐时打开
@@ -9,10 +9,34 @@
+
+
+
+
{{ setData.animationSpeed }}x
+
+
+
+
+
-
+
- 取消
- 保存并重启
+ 取消
+ {{ isElectron ? '保存并重启' : '保存' }}
+
+
+
+
支持作者
+
+
+
+ 支付宝
+
+
+
+ 微信支付
+
+
@@ -67,7 +118,7 @@ const handleSave = () => {
@apply flex flex-col justify-center items-center pt-8;
}
.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 {
@apply text-gray-200 text-base;
}
@@ -75,4 +126,7 @@ const handleSave = () => {
@apply text-gray-400 text-sm;
}
}
+.set-action {
+ @apply flex gap-3 mt-4;
+}