diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..ab14a6b --- /dev/null +++ b/.env.example @@ -0,0 +1 @@ +VUE_APP_NETEASE_API_URL=http://localhost:3000 \ No newline at end of file diff --git a/.gitignore b/.gitignore index 3557e17..3736680 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ node_modules # local env files +.env .env.local .env.*.local diff --git a/README.md b/README.md index b81b731..a8fa474 100644 --- a/README.md +++ b/README.md @@ -44,16 +44,16 @@ git clone https://github.com/qier222/YesPlayMusic.git npm install ``` -4. 替换 `/src/config/request.js` 里面 `baseURL` 的值为网易云 API 地址 +4. 复制 `/.env.example` 文件为 `/.env`,修改里面 `VUE_APP_NETEASE_API_URL` 的值为网易云 API 地址。本地开发的话可以填写 API 地址为 `http://localhost:3000`,YesPlayMusic 地址为 `http://localhost:8080` -```JS -baseURL: "http://example.com", +``` +VUE_APP_NETEASE_API_URL=http://localhost:3000 ``` 5. 编译打包 ```sh -npm build +npm run build ``` 6. 将 `/dist` 目录下的文件上传到你的 Web 服务器 @@ -62,6 +62,7 @@ npm build - 中文支持 - Dark Mode +- 歌词 - 私人 FM - 播放记录 - 无限播放模式(播放完列表后自动播放相似歌曲) diff --git a/src/components/CoverRow.vue b/src/components/CoverRow.vue index 9de24a6..48a482c 100644 --- a/src/components/CoverRow.vue +++ b/src/components/CoverRow.vue @@ -33,6 +33,12 @@ v-if="type === 'album' && item.mark === 1056768" > + + {{ item.name }} @@ -164,6 +170,16 @@ export default { } } +.lock-icon { + color: rgba(0, 0, 0, 0.28); + margin-right: 4px; + // float: right; + .svg-icon { + height: 12px; + width: 12px; + } +} + .play-count { font-weight: 600; color: rgba(0, 0, 0, 0.58); diff --git a/src/components/Player.vue b/src/components/Player.vue index 12a9bc5..ff59bdb 100644 --- a/src/components/Player.vue +++ b/src/components/Player.vue @@ -37,7 +37,10 @@
- + diff --git a/src/config/request.js b/src/config/request.js deleted file mode 100644 index bac58ec..0000000 --- a/src/config/request.js +++ /dev/null @@ -1,6 +0,0 @@ -/** - * The base url of your API. - * - * The API can be found at https://github.com/Binaryify/NeteaseCloudMusicApi - */ -export const baseURL = ""; \ No newline at end of file diff --git a/src/locale/index.js b/src/locale/index.js index 5005c24..0a62566 100644 --- a/src/locale/index.js +++ b/src/locale/index.js @@ -1,12 +1,17 @@ -import Vue from 'vue'; -import VueI18n from 'vue-i18n' -import messages from './messages'; +import Vue from "vue"; +import VueI18n from "vue-i18n"; -Vue.use(VueI18n) +import en from "./lang/en.js"; +import zhCN from "./lang/zh-CN.js"; + +Vue.use(VueI18n); const i18n = new VueI18n({ - locale: 'zh-CN', - messages + locale: "en", + messages: { + en, + "zh-CN": zhCN + } }); -export default i18n; \ No newline at end of file +export default i18n; diff --git a/src/locale/lang/en.js b/src/locale/lang/en.js new file mode 100644 index 0000000..c0b9460 --- /dev/null +++ b/src/locale/lang/en.js @@ -0,0 +1,83 @@ +export default { + play: "PLAY", + nav: { + home: "Home", + explore: "Explore", + library: "Library", + search: "Search" + }, + footer: { + settings: "Settings" + }, + home: { + recommendPlaylist: "Recommended Playlists", + recommendArtist: "Recommended Artists", + newAlbum: "Latest Albums", + seeMore: "SEE MORE", + charts: "Charts" + }, + library: { + sLibrary: "'s Library", + likedSongs: "Liked Songs", + sLikedSongs: "'s LikedSongs" + }, + explore: { + explore: "Explore", + loadMore: "Load More" + }, + artist: { + latestRelease: "Latest Releases", + popularSongs: "Popular Songs", + showMore: "SHOW MORE", + showLess: "SHOW LESS", + EPSingle: "EPs & Singles", + albums: "Albums" + }, + album: { + released: "Released" + }, + playlist: { + playlist: "Playlists", + updatedAt: "Updated at" + }, + login: { + accessToAll: "Access to all data", + loginText: "Login in Netease", + search: "Search account", + readonly: "Only access to public data", + usernameLogin: "Username Login", + searchHolder: "Your account username", + enterTip: "Press 'enter' to search", + choose: "Choose your account", + confirm: "Confirm", + countryCode: "Country code", + phone: "Phone", + email: "Email address", + password: "Password", + login: "Login", + loginWithEmail: "Login with Email", + loginWithPhone: "Login with Phone", + // TODO + agreement: `YesPlayMusic promises not to save any of your account information to the cloud. + Your password will be MD5 encrypted locally and then transmitted to NetEase Cloud API. + YesPlayMusic is not the official website of NetEase Cloud Music, please consider carefully before entering account information. You can also go to YesPlayMusic's GitHub repository to build and use the self-hosted NetEase Cloud Music API.` + }, + mv: { + moreVideo: "More Videos" + }, + next: { + nowPlaying: "Now Playing", + nextUp: "Next Up" + }, + player: { + like: "Like", + previous: "Previous Song", + next: "Next Song", + repeat: "Repeat", + shuffle: "Shuffle", + play: "Play", + pause: "Pause", + mute: "Mute", + nextUp: "Next Up" + } +}; diff --git a/src/locale/lang/zh-CN.js b/src/locale/lang/zh-CN.js new file mode 100644 index 0000000..10797a5 --- /dev/null +++ b/src/locale/lang/zh-CN.js @@ -0,0 +1,87 @@ +export default { + play: "播放", + nav: { + home: "首页", + explore: "发现", + library: "资料库", + search: "搜索" + }, + footer: { + settings: "设置" + }, + home: { + recommendPlaylist: "推荐歌单", + recommendArtist: "推荐歌手", + newAlbum: "新专速递", + seeMore: "更多", + charts: "排行榜" + }, + library: { + sLibrary: "的资料库", + likedSongs: "我喜欢的歌", + sLikedSongs: "喜欢的歌" + }, + explore: { + explore: "发现", + loadMore: "加载更多" + }, + artist: { + latestRelease: "最新发布", + popularSongs: "热门歌曲", + showMore: "显示更多", + showLess: "收起", + EPSingle: "EP和单曲", + albums: "专辑" + }, + album: { + released: "发行于" + }, + playlist: { + playlist: "歌单", + updatedAt: "最后更新于" + }, + login: { + accessToAll: "可访问全部数据", + loginText: "登录网易云账号", + search: "搜索网易云账号", + readonly: "只能读取账号公开数据", + usernameLogin: "用户名登录", + searchHolder: "请输入你的网易云用户名", + enterTip: "按 Enter 搜索", + choose: "在列表中选中你的账号", + confirm: "确认", + countryCode: "国际区号", + phone: "手机号", + email: "邮箱", + password: "密码", + login: "登录", + usingEmail: "使用邮箱登录", + usingPhone: "使用手机号登录", + // TODO + agreement: `YesPlayMusic 承诺不会保存你的任何账号信息到云端。
+ 你的密码会在本地进行 MD5 加密后再传输到网易云 API。
+ YesPlayMusic 并非网易云官方网站,输入账号信息前请慎重考虑。 你也可以前往 + YesPlayMusic 的 GitHub 源代码仓库 + 自行构建并使用自托管的网易云 API。` + }, + mv: { + moreVideo: "更多视频" + }, + next: { + nowPlaying: "正在播放", + nextUp: "即将播放" + }, + player: { + like: "喜欢", + previous: "上一首", + next: "下一首", + repeat: "单曲循环", + shuffle: "随机播放", + play: "播放", + pause: "暂停", + mute: "静音", + nextUp: "播放列表" + } +}; diff --git a/src/locale/messages.js b/src/locale/messages.js deleted file mode 100644 index 228328b..0000000 --- a/src/locale/messages.js +++ /dev/null @@ -1,166 +0,0 @@ -export default { - en: { - nav: { - home: "Home", - explore: "Explore", - library: "Library", - search: "Search" - }, - footer: { - settings: 'Settings', - }, - home: { - recommendPlaylist: "Recommended Playlist", - recommendArtist: "Recommended Artist", - newAlbum: "Lastest Album", - leaderboard: "Leaderboard", - seeMore: "SEE MORE", - }, - library: "Library", - explore: { - explore: "Explore", - loadMore: "Load More", - }, - artist: { - latestRelease: "Latest Release", - popularSongs: "Popular Songs", - showMore: "SHOW MORE", - showLess: "SHOW LESS", - EPSingle: "EPs & Singles", - albums: "Albums" - }, - album: { - released: "Released", - }, - login: { - accessToAll: "Access to all data", - loginText: "Login in Netease", - search: "Search account", - readonly: "Only access to public data", - usernameLogin: "Username Login", - searchHolder: "Your account username", - enterTip: "Press 'enter' to search", - choose: "Choose your account", - confirm: "confirm", - countrycode: 'countrycode', - phone: 'phone', - email: 'email', - password: 'password', - login: 'Login', - usingEmail: 'Using email', - usingPhone: 'Using phone', - // TODO - agreement: `YesPlayMusic promises not to save any of your account information to the cloud. - Your password will be MD5 encrypted locally and then transmitted to NetEase Cloud API. - YesPlayMusic is not the official website of NetEase Cloud, please consider carefully before entering account information. You can also go to YesPlayMusic's GitHub repository to build and use the self-hosted NetEase Cloud API.` - }, - mv: { - moreVideo: 'More Videos' - }, - next: { - nowPlaying: 'Now Playing', - nextUp: 'Next Up' - }, - player: { - like: 'Like', - previous: 'Previous Song', - next: 'Next Song', - repeat: 'Repeat', - shuffle: 'Shuffle', - play: 'Play', - pause: 'Pause', - mute: 'Mute', - nextUp: 'Next Up' - }, - playlist: "Playlists", - play: "PLAY", - likedSong: "Liked Songs", - shortIs: "'s", - is: "'s", - updatedAt: "Updated at", - }, - "zh-CN": { - nav: { - home: "首页", - explore: "发现", - library: "歌单", - search: "搜索" - }, - footer: { - settings: '设置', - }, - home: { - recommendPlaylist: "推荐歌单", - recommendArtist: "推荐歌手", - newAlbum: "新专速递", - leaderboard: "排行榜", - seeMore: "更多", - }, - library: "歌单", - explore: { - explore: "发现", - loadMore: "加载更多", - }, - artist: { - latestRelease: "最新发布", - popularSongs: "热门歌曲", - showMore: "显示更多", - showLess: "收起", - EPSingle: "专辑及单曲", - albums: "专辑" - }, - album: { - released: "发布于", - }, - login: { - accessToAll: "可访问全部数据", - loginText: "登录网易云账号", - search: "搜索网易云账号", - readonly: "只能读取账号公开数据", - usernameLogin: '用户名登录', - searchHolder: "请输入你的网易云用户名", - enterTip: "按 Enter 搜索", - choose: "在列表中选中你的账号", - confirm: "确认", - countrycode: '国际区号', - phone: '手机号', - email: '邮箱', - password: '密码', - login: '登录', - usingEmail: '使用邮箱登录', - usingPhone: '使用手机号登录', - // TODO - agreement: `YesPlayMusic 承诺不会保存你的任何账号信息到云端。
- 你的密码会在本地进行 MD5 加密后再传输到网易云 API。
- YesPlayMusic 并非网易云官方网站,输入账号信息前请慎重考虑。 你也可以前往 - YesPlayMusic 的 GitHub 源代码仓库 - 自行构建并使用自托管的网易云 API。` - }, - mv: { - moreVideo: '更多视频' - }, - next: { - nowPlaying: '正在播放', - nextUp: '即将播放' - }, - player: { - like: '喜欢', - previous: '上一首', - next: '下一首', - repeat: '单曲循环', - shuffle: '随机播放', - play: '播放', - pause: '暂停', - mute: '静音', - nextUp: '播放列表' - }, - playlist: "播放列表", - play: "播放", - likedSong: "我喜欢的音乐", - shortIs: "", - is: "的", - updatedAt: "更新于" - } -}; \ No newline at end of file diff --git a/src/utils/filters.js b/src/utils/filters.js index 109ff35..8760dc9 100644 --- a/src/utils/filters.js +++ b/src/utils/filters.js @@ -2,6 +2,7 @@ import Vue from "vue"; import dayjs from "dayjs"; import duration from "dayjs/plugin/duration"; import relativeTime from "dayjs/plugin/relativeTime"; +import locale from "@/locale"; Vue.filter("formatTime", (Milliseconds, format = "HH:MM:SS") => { if (!Milliseconds) return ""; @@ -27,6 +28,7 @@ Vue.filter("formatTime", (Milliseconds, format = "HH:MM:SS") => { Vue.filter("formatDate", (timestamp, format = "MMM D, YYYY") => { if (!timestamp) return ""; + if (locale.locale === "zh-CN") format = "YYYY年MM月DD日"; return dayjs(timestamp).format(format); }); @@ -52,26 +54,34 @@ Vue.filter("resizeImage", (imgUrl, size = 512) => { return `${httpsImgUrl}?param=${size}y${size}`; }); -Vue.filter("formatPlayCount", (count) => { +Vue.filter("formatPlayCount", count => { if (!count) return ""; - if (count > 100000000) { - return `${~~(count / 100000000)}亿`; - } - if (count > 10000) { - return `${~~(count / 10000)}万`; + if (locale.locale === "zh-CN") { + if (count > 100000000) { + return `${Math.floor((count / 100000000) * 100) / 100}亿`; // 2.32 亿 + } + if (count > 100000) { + return `${Math.floor((count / 10000) * 10) / 10}万`; // 232.1 万 + } + if (count > 10000) { + return `${Math.floor((count / 10000) * 100) / 100}万`; // 2.3 万 + } + return count; + } else { + if (count > 10000000) { + return `${Math.floor((count / 1000000) * 10) / 10}M`; // 233.2M + } + if (count > 1000000) { + return `${Math.floor((count / 1000000) * 100) / 100}M`; // 2.3M + } + if (count > 1000) { + return `${Math.floor((count / 1000) * 100) / 100}K`; // 233.23K + } + return count; } - return count; - - // if (count > 1000000) { - // return `${Math.floor((count / 1000000) * 100) / 100}M`; - // } - // if (count > 1000) { - // return `${~~(count / 1000)}K`; - // } - // return count; }); -Vue.filter("toHttps", (url) => { +Vue.filter("toHttps", url => { if (!url) return ""; return url.replace(/^http:/, "https:"); }); diff --git a/src/utils/request.js b/src/utils/request.js index 7c9c333..bfecc67 100644 --- a/src/utils/request.js +++ b/src/utils/request.js @@ -1,37 +1,36 @@ import axios from "axios"; -import { baseURL } from "@/config/request"; const service = axios.create({ - baseURL: baseURL, + baseURL: process.env.VUE_APP_NETEASE_API_URL, withCredentials: true, - timeout: 15000, + timeout: 15000 }); const errors = new Map([ - [401, 'The token you are using has expired.'], + [401, "The token you are using has expired."], [502, null], - [301, 'You must login to use this feature.'], - [-1, 'An unexpected error has occurred: '], + [301, "You must login to use this feature."], + [-1, "An unexpected error has occurred: "] ]); service.interceptors.response.use( - (response) => { + response => { const res = response.data; if (res.code !== 200) { alert( errors.has(res.code) - ? errors.get(res.code) - // null = `The server returned ${res.msg}` - || `The server returned ${res.msg}` - // -1 = default expection message - : errors.get(-1) + res.code + ? errors.get(res.code) || + // null = `The server returned ${res.msg}` + `The server returned ${res.msg}` + : // -1 = default expection message + errors.get(-1) + res.code ); } else { return res; } }, - (error) => { + error => { const errMsg = `error: ${error}`; console.log(errMsg); diff --git a/src/views/album.vue b/src/views/album.vue index a0d21dd..21a1d06 100644 --- a/src/views/album.vue +++ b/src/views/album.vue @@ -38,7 +38,7 @@ @click.native="playAlbumByID(album.id)" :iconClass="`play`" > - {{ $t('play') }} + {{ $t("play") }}
@@ -47,7 +47,8 @@
- {{ $t("album.released") }} {{ album.publishTime | formatDate("MMMM D, YYYY") }} + {{ $t("album.released") }} + {{ album.publishTime | formatDate("MMMM D, YYYY") }}