Skip to content

Commit a57a18b

Browse files
committed
✨ feat: 播放模式支持点击切换
1 parent 309c323 commit a57a18b

File tree

6 files changed

+121
-56
lines changed

6 files changed

+121
-56
lines changed

README.md

Lines changed: 27 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@
2121
- 本项目采用 [Vue 3](https://cn.vuejs.org/) 全家桶和 [Naïve UI](https://www.naiveui.com/) 组件库及 [Electron](https://www.electronjs.org/zh/docs/latest/) 开发
2222
- 支持网页端与客户端,由于设备有限,目前仅适配 `Win`,其他平台可自行解决兼容性后进行构建
2323
- 仅对移动端做了基础适配,**不保证功能全部可用**
24+
2425
> 请注意,本程序不打算开发移动端,也不会对移动端进行完美适配,仅保证基础可用性
26+
2527
- 欢迎各位大佬 `Star` 😍
2628

2729
## 👀 Demo
@@ -30,38 +32,31 @@
3032

3133
## 🎉 功能
3234

33-
- 支持扫码登录
34-
- 支持手机号登录
35-
- 自动进行每日签到及云贝签到
36-
- 封面主题色自适应
37-
- 本地歌曲管理及分类(建议先使用 [音乐标签](https://www.cnblogs.com/vinlxc/p/11347744.html) 进行匹配后再使用)
38-
- **支持播放部分无版权歌曲(可能会与原曲不匹配,客户端独占功能)**
39-
- 下载歌曲(最高支持 Hi-Res)
40-
- 新建歌单及歌单编辑
41-
- 收藏 / 取消收藏歌单或歌手
42-
- 每日推荐歌曲
43-
- 私人 FM
44-
- 云盘音乐上传
45-
- 云盘内歌曲播放
46-
- 云盘内歌曲纠正
47-
- 云盘歌曲删除
48-
- 支持逐字歌词
49-
- 歌词滚动以及歌词翻译
50-
- MV 与视频播放
51-
- 音乐频谱显示( 暂时去除,还待完善 )
52-
- 音乐渐入渐出
53-
- 支持 PWA
54-
- 支持评论区及评论点赞
55-
- 明暗模式自动 / 手动切换
56-
- ~~移动端基础适配~~
57-
- ~~`i18n` 支持~~
58-
59-
#### 待办
60-
61-
- [ ] 完善音乐频谱
62-
- [ ] 添加桌面歌词
63-
- [ ] 多种布局方式
64-
- [ ] 发表评论
35+
- ✨ 支持扫码登录
36+
- 📱 支持手机号登录
37+
- 📅 自动进行每日签到及云贝签到
38+
- 🎨 封面主题色自适应
39+
- 📁 本地歌曲管理及分类(建议先使用 [音乐标签](https://www.cnblogs.com/vinlxc/p/11347744.html) 进行匹配后再使用)
40+
- 🎵 **支持播放部分无版权歌曲(可能会与原曲不匹配,客户端独占功能)**
41+
- ⬇️ 下载歌曲(最高支持 Hi-Res)
42+
- ➕ 新建歌单及歌单编辑
43+
- ❤️ 收藏 / 取消收藏歌单或歌手
44+
- 🎶 每日推荐歌曲
45+
- 📻 私人 FM
46+
- ☁️ 云盘音乐上传
47+
- 📂 云盘内歌曲播放
48+
- 🔄 云盘内歌曲纠正
49+
- 🗑️ 云盘歌曲删除
50+
- 📝 支持逐字歌词
51+
- 🔄 歌词滚动以及歌词翻译
52+
- 📹 MV 与视频播放
53+
- 🎶 音乐频谱显示
54+
- ⏭️ 音乐渐入渐出
55+
- 🔄 支持 PWA
56+
- 💬 支持评论区及评论点赞
57+
- 🌓 明暗模式自动 / 手动切换
58+
- 📱 移动端基础适配
59+
- ~~🌐 `i18n` 支持~~
6560

6661
## 🖼️ Screenshots
6762

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
"home": "https://imsyy.top",
88
"github": "https://github.com/imsyy/SPlayer",
99
"repository": "github:imsyy/SPlayer",
10+
"license": "AGPL-3.0",
11+
"license-file": "LICENSE",
1012
"engines": {
1113
"node": ">=18.16.0",
1214
"npm": ">=9.6.7",

src/api/search.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,19 @@ export const getSearchSuggest = (keywords, mobile = false) => {
3333
});
3434
};
3535

36+
/**
37+
* 默认搜索关键词
38+
*/
39+
export const getSearchDefault = () => {
40+
return axios({
41+
method: "GET",
42+
url: "/search/default",
43+
params: {
44+
timestamp: new Date().getTime(),
45+
},
46+
});
47+
};
48+
3649
/**
3750
* 搜索结果
3851
* @param {string} keywords - 搜索关键词

src/components/Player/MainControl.vue

Lines changed: 34 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -221,22 +221,25 @@
221221
trigger="hover"
222222
@select="playModeChange"
223223
>
224-
<div class="mode hidden" @click.stop @dblclick.stop>
225-
<n-icon size="22">
226-
<SvgIcon
227-
:icon="
228-
playHeartbeatMode
229-
? 'heartbit'
230-
: playSongMode === 'normal'
231-
? 'repeat-list'
232-
: playSongMode === 'random'
233-
? 'shuffle'
234-
: 'repeat-song'
235-
"
236-
isSpecial
237-
/>
238-
</n-icon>
239-
</div>
224+
<n-icon
225+
class="mode hidden"
226+
size="22"
227+
@click.stop="playModeChange(false)"
228+
@dblclick.stop
229+
>
230+
<SvgIcon
231+
:icon="
232+
playHeartbeatMode
233+
? 'heartbit'
234+
: playSongMode === 'normal'
235+
? 'repeat-list'
236+
: playSongMode === 'random'
237+
? 'shuffle'
238+
: 'repeat-song'
239+
"
240+
isSpecial
241+
/>
242+
</n-icon>
240243
</n-dropdown>
241244
<!-- 倍速 -->
242245
<n-popover :show-arrow="false" trigger="hover" placement="top-end" raw>
@@ -390,16 +393,16 @@ const renderIcon = (icon, isSpecial = false) => {
390393
391394
// 播放模式数据
392395
const playModeOptions = ref([
393-
{
394-
label: "列表循环",
395-
key: "normal",
396-
icon: renderIcon("repeat-list", true),
397-
},
398396
{
399397
label: "单曲循环",
400398
key: "repeat",
401399
icon: renderIcon("repeat-song", true),
402400
},
401+
{
402+
label: "列表循环",
403+
key: "normal",
404+
icon: renderIcon("repeat-list", true),
405+
},
403406
{
404407
label: "随机播放",
405408
key: "random",
@@ -504,6 +507,11 @@ const changePlayIndexDebounce = debounce(async (type, id) => {
504507
505508
// 播放模式切换
506509
const playModeChange = (mode) => {
510+
const modeMap = {
511+
normal: "random",
512+
random: "shuffle",
513+
shuffle: "normal",
514+
};
507515
// 关闭心动模式
508516
if (playHeartbeatMode.value) {
509517
playHeartbeatMode.value = false;
@@ -513,7 +521,11 @@ const playModeChange = (mode) => {
513521
playListOld.value = [];
514522
}
515523
// 切换模式
516-
playSongMode.value = mode;
524+
if (mode) {
525+
playSongMode.value = mode;
526+
} else {
527+
playSongMode.value = modeMap[playSongMode.value] || "normal";
528+
}
517529
};
518530
519531
// 音量条鼠标滚动

src/components/Search/SearchInp.vue

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
v-model:value="searchInputValue"
77
:class="searchInputFocus ? 'input focus' : 'input'"
88
:input-props="{ autoComplete: false }"
9+
:placeholder="searchPlaceholder"
910
:allow-input="noSideSpace"
10-
placeholder="搜索音乐 / 视频"
1111
round
1212
clearable
1313
@focus="searchInputToFocus"
@@ -43,6 +43,7 @@
4343
import { storeToRefs } from "pinia";
4444
import { useRouter } from "vue-router";
4545
import { getSongDetail } from "@/api/song";
46+
import { getSearchDefault } from "@/api/search";
4647
import { siteData, siteStatus, musicData } from "@/stores";
4748
import { addSongToNext, initPlayer } from "@/utils/Player";
4849
import formatData from "@/utils/formatData";
@@ -55,8 +56,12 @@ const { searchHistory } = storeToRefs(data);
5556
const { playSongData } = storeToRefs(music);
5657
const { searchInputFocus } = storeToRefs(status);
5758
59+
// 搜索框数据
5860
const searchInpRef = ref(null);
5961
const searchInputValue = ref("");
62+
const searchInterval = ref(null);
63+
const searchRealkeyword = ref(null);
64+
const searchPlaceholder = ref("搜索音乐 / 视频");
6065
6166
// 搜索框输入限制
6267
const noSideSpace = (value) => !value.startsWith(" ");
@@ -80,6 +85,25 @@ const setSearchHistory = (name) => {
8085
}
8186
};
8287
88+
// 更换搜索框关键词
89+
const updatePlaceholder = async () => {
90+
try {
91+
const result = await getSearchDefault();
92+
searchPlaceholder.value = result.data.showKeyword;
93+
searchRealkeyword.value = result.data.realkeyword;
94+
} catch (error) {
95+
console.error("搜索关键词获取失败:", error);
96+
searchPlaceholder.value = "搜索音乐 / 视频";
97+
}
98+
};
99+
100+
// 更新搜索框关键词
101+
const changePlaceholder = () => {
102+
updatePlaceholder();
103+
// 5分钟
104+
searchInterval.value = setInterval(updatePlaceholder, 5 * 60 * 1000);
105+
};
106+
83107
// 关闭搜索
84108
const closeSearch = () => {
85109
// 取消聚焦状态
@@ -107,9 +131,15 @@ const toPlaySong = async (id) => {
107131
108132
// 前往搜索
109133
const toSearch = (val, type = "song") => {
110-
if (!val) return false;
134+
// 未输入内容且不存在推荐
135+
if (!val && searchPlaceholder.value === "搜索音乐 / 视频") return false;
136+
if (!val && searchPlaceholder.value !== "搜索音乐 / 视频" && searchRealkeyword.value) {
137+
val = searchRealkeyword.value?.trim();
138+
}
111139
// 取消聚焦状态
112140
closeSearch();
141+
// 更新推荐
142+
updatePlaceholder();
113143
// 触发测试
114144
if (Number(val) === 114514) return router.push("/test");
115145
// 判断类型
@@ -161,6 +191,14 @@ const toSearch = (val, type = "song") => {
161191
break;
162192
}
163193
};
194+
195+
onMounted(() => {
196+
changePlaceholder();
197+
});
198+
199+
onBeforeUnmount(() => {
200+
clearInterval(searchInterval.value);
201+
});
164202
</script>
165203
166204
<style lang="scss" scoped>

src/utils/Player.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -779,6 +779,11 @@ const getPlaySongName = () => {
779779
return songName + " - " + songArtist;
780780
};
781781

782+
/**
783+
* 播放所有歌曲
784+
* @param {Array} playlist - 包含歌曲信息的数组
785+
* @param {string} mode - 播放模式
786+
*/
782787
export const playAllSongs = async (playlist, mode = "normal") => {
783788
try {
784789
// pinia

0 commit comments

Comments
 (0)