Compare commits
14 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
7854c9f459 | ||
|
392dbf84e3 | ||
|
709198e1a2 | ||
|
8ca5343c5a | ||
|
220ce2e319 | ||
|
a812b15e2a | ||
|
8bbf410a25 | ||
|
e5947ebfa9 | ||
|
8ac3b1c27f | ||
|
e3af10fb68 | ||
|
acafac9d1a | ||
|
1c1e74297f | ||
|
1086591adc | ||
|
d41a0b050b |
@ -1,15 +0,0 @@
|
|||||||
node_modules
|
|
||||||
npm-debug.log
|
|
||||||
Dockerfile*
|
|
||||||
docker-compose*
|
|
||||||
.dockerignore
|
|
||||||
.git
|
|
||||||
.github
|
|
||||||
.gitignore
|
|
||||||
README.md
|
|
||||||
LICENSE
|
|
||||||
.vscode
|
|
||||||
dist
|
|
||||||
build
|
|
||||||
images
|
|
||||||
script
|
|
@ -26,7 +26,7 @@ VITE_DESC_TEXT_OTHER = "哎呀,这都被你发现了( 再点击一次可关
|
|||||||
## 请注意不是 Web端 (JS API),免费申请,每日上限 5000 次
|
## 请注意不是 Web端 (JS API),免费申请,每日上限 5000 次
|
||||||
## 此处提供的服务可能会超量从而无法访问,请自行申请!请自行申请!请自行申请!
|
## 此处提供的服务可能会超量从而无法访问,请自行申请!请自行申请!请自行申请!
|
||||||
## 若此处设为空则调用 教书先生 API https://api.oioweb.cn/doc/weather/GetWeather
|
## 若此处设为空则调用 教书先生 API https://api.oioweb.cn/doc/weather/GetWeather
|
||||||
VITE_WEATHER_KEY = ""
|
VITE_WEATHER_KEY = "6c13af6fc30868bee488faf2cc652ab4"
|
||||||
|
|
||||||
# 建站日期
|
# 建站日期
|
||||||
## 若不需要,请设为空即可
|
## 若不需要,请设为空即可
|
||||||
@ -48,4 +48,4 @@ VITE_SONG_SERVER = "netease"
|
|||||||
# 播放类型 ( song-歌曲, playlist-播放列表, album-专辑, search-搜索, artist-艺术家 )
|
# 播放类型 ( song-歌曲, playlist-播放列表, album-专辑, search-搜索, artist-艺术家 )
|
||||||
VITE_SONG_TYPE = "playlist"
|
VITE_SONG_TYPE = "playlist"
|
||||||
# 播放 ID ( 若无需播放器,请设为空即可 )
|
# 播放 ID ( 若无需播放器,请设为空即可 )
|
||||||
VITE_SONG_ID = "9379831714"
|
VITE_SONG_ID = "7452421335"
|
@ -1,3 +0,0 @@
|
|||||||
node_modules
|
|
||||||
dist
|
|
||||||
.gitignore
|
|
46
.github/workflows/build.yml
vendored
46
.github/workflows/build.yml
vendored
@ -1,46 +0,0 @@
|
|||||||
# Dev 分支推送部署预览
|
|
||||||
## 仅部署 Win 端
|
|
||||||
name: Build Dev
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- dev
|
|
||||||
- master
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
release:
|
|
||||||
name: Build Website
|
|
||||||
runs-on: windows-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
# 检出 Git 仓库
|
|
||||||
- name: Check out git repository
|
|
||||||
uses: actions/checkout@v4.1.1
|
|
||||||
# 安装 Node.js
|
|
||||||
- name: Install Node.js
|
|
||||||
uses: actions/setup-node@v4.0.0
|
|
||||||
with:
|
|
||||||
node-version: "18.x"
|
|
||||||
# 复制环境变量文件
|
|
||||||
- name: Copy .env.example
|
|
||||||
run: |
|
|
||||||
if (-not (Test-Path .env)) {
|
|
||||||
Copy-Item .env.example .env
|
|
||||||
} else {
|
|
||||||
Write-Host ".env file already exists. Skipping the copy step."
|
|
||||||
}
|
|
||||||
# 安装项目依赖
|
|
||||||
- name: Install Dependencies
|
|
||||||
run: npm install
|
|
||||||
# 构建程序
|
|
||||||
- name: Build Website
|
|
||||||
run: npm run build
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.ACCESS_TOKEN }}
|
|
||||||
# 上传构建产物
|
|
||||||
- name: Upload artifacts
|
|
||||||
uses: actions/upload-artifact@v3.1.3
|
|
||||||
with:
|
|
||||||
name: Home
|
|
||||||
path: dist
|
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -11,7 +11,6 @@ node_modules
|
|||||||
dist
|
dist
|
||||||
dist-ssr
|
dist-ssr
|
||||||
*.local
|
*.local
|
||||||
.env
|
|
||||||
|
|
||||||
# Editor directories and files
|
# Editor directories and files
|
||||||
.vscode/*
|
.vscode/*
|
||||||
|
17
Dockerfile
17
Dockerfile
@ -1,17 +0,0 @@
|
|||||||
# 构建应用
|
|
||||||
FROM node:18 AS builder
|
|
||||||
WORKDIR /app
|
|
||||||
COPY package*.json ./
|
|
||||||
RUN npm install
|
|
||||||
COPY . .
|
|
||||||
RUN [ ! -e ".env" ] && cp .env.example .env || true
|
|
||||||
RUN npm run build
|
|
||||||
|
|
||||||
# 最小化镜像
|
|
||||||
FROM node:18-alpine
|
|
||||||
WORKDIR /app
|
|
||||||
COPY --from=builder /app/dist ./dist
|
|
||||||
RUN npm install -g http-server
|
|
||||||
|
|
||||||
EXPOSE 12445
|
|
||||||
CMD ["http-server", "dist", "-p", "12445"]
|
|
77
README.md
77
README.md
@ -5,11 +5,11 @@
|
|||||||
简单的小主页,原来的看够了,重新弄了一个
|
简单的小主页,原来的看够了,重新弄了一个
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
![無名の主页](/screenshots/main.jpg)
|
![無名の主页](https://s2.loli.net/2022/07/14/K5JigfvDoNewtuS.webp)
|
||||||
|
|
||||||
>主页的 Logo 字体已经过压缩,若用本站 Logo 以外的字母会变回默认字体,这里是 [完整字体](https://file.imsyy.top/font/Other/Pacifico-Regular.ttf),若无法下载,可将字体目录下的 `Pacifico-Regular-all.ttf` 进行替换
|
>主页的 Logo 字体已经过压缩,若用本站 Logo 以外的字母会变回默认字体,这里是 [完整字体](https://file.imsyy.top/font/Other/Pacifico-Regular.ttf),若无法下载,可将字体目录下的 `Pacifico-Regular-all.ttf` 进行替换
|
||||||
|
|
||||||
### 👀 Demo
|
### Demo
|
||||||
|
|
||||||
>由于 CDN 缓存原因,查看最新效果可能需要 `Ctrl` + `F5` 强制刷新浏览器缓存
|
>由于 CDN 缓存原因,查看最新效果可能需要 `Ctrl` + `F5` 强制刷新浏览器缓存
|
||||||
|
|
||||||
@ -17,7 +17,7 @@
|
|||||||
- [無名の主页 - Dev](https://home-imsyy.vercel.app)
|
- [無名の主页 - Dev](https://home-imsyy.vercel.app)
|
||||||
- [無名の主页 - 备用线路](https://home-5iw.pages.dev)
|
- [無名の主页 - 备用线路](https://home-5iw.pages.dev)
|
||||||
|
|
||||||
### 🎉 功能
|
### 功能
|
||||||
|
|
||||||
- [x] 载入动画
|
- [x] 载入动画
|
||||||
- [x] 站点简介
|
- [x] 站点简介
|
||||||
@ -28,27 +28,15 @@
|
|||||||
- [x] 音乐播放器
|
- [x] 音乐播放器
|
||||||
- [x] 移动端适配
|
- [x] 移动端适配
|
||||||
|
|
||||||
### ⚙️ 自动部署
|
### 部署
|
||||||
|
|
||||||
如果遇到构建环境或者打包过程出现错误,则可以采用 `Github Actions` 来进行自动构建
|
* **安装** [node.js](https://nodejs.org/zh-cn/) **环境**
|
||||||
|
|
||||||
- 在成功 `fork` 仓库后,前往 `Actions` 页面,若您是首次开启,则会出现下面的提示,点击开启
|
|
||||||
|
|
||||||
![步骤1](/screenshots/step1.jpg)
|
|
||||||
|
|
||||||
- 然后在仓库中进行任意修改后均会触发工作流的运行,在工作流完成后,会在下方生成一个可供下载的压缩包,这就是构建出的静态文件,可自行上传至服务器
|
|
||||||
|
|
||||||
![步骤2](/screenshots/step2.jpg)
|
|
||||||
|
|
||||||
### ⚙️ 手动部署
|
|
||||||
|
|
||||||
- **安装** [node.js](https://nodejs.org/zh-cn/) **环境**
|
|
||||||
|
|
||||||
> node > 16.16.0
|
> node > 16.16.0
|
||||||
> npm > 8.15.0
|
> npm > 8.15.0
|
||||||
|
|
||||||
- 然后以 **管理员权限** 运行 `cmd` 终端,并 `cd` 到 项目根目录
|
* 然后以 **管理员权限** 运行 `cmd` 终端,并 `cd` 到 项目根目录
|
||||||
- 在 `终端` 中输入:
|
* 在 `终端` 中输入:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# 安装 pnpm
|
# 安装 pnpm
|
||||||
@ -63,29 +51,8 @@ pnpm dev
|
|||||||
# 构建
|
# 构建
|
||||||
pnpm build
|
pnpm build
|
||||||
```
|
```
|
||||||
|
|
||||||
> 构建完成后,静态资源会在 **`dist` 目录** 中生成,可将 **`dist` 文件夹下的文件**上传至服务器,也可使用 `Vercel` 等托管平台一键导入并自动部署
|
> 构建完成后,静态资源会在 **`dist` 目录** 中生成,可将 **`dist` 文件夹下的文件**上传至服务器,也可使用 `Vercel` 等托管平台一键导入并自动部署
|
||||||
|
|
||||||
### ⚙️ Docker 部署
|
|
||||||
|
|
||||||
> 安装及配置 Docker 将不在此处说明,请自行解决
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 构建
|
|
||||||
docker build -t home .
|
|
||||||
# 运行
|
|
||||||
docker run -p 12445:12445 -d home
|
|
||||||
```
|
|
||||||
|
|
||||||
### ⚙️ Vercel 部署
|
|
||||||
|
|
||||||
> 其他部署平台大致相同,在此不做说明
|
|
||||||
|
|
||||||
1. 点击本仓库右上角的 `Fork`,复制本仓库到你的 `GitHub` 账号
|
|
||||||
2. 复制 `/.env.example` 文件并重命名为 `/.env`( 重要 )
|
|
||||||
3. 按需修改 `/.env` 文件中的配置
|
|
||||||
4. 点击 `Deploy`,即可成功部署
|
|
||||||
|
|
||||||
### 网站链接
|
### 网站链接
|
||||||
|
|
||||||
在 `src/assets/siteLinks.json` 中可以自定义网站链接(以指向自己的网站):
|
在 `src/assets/siteLinks.json` 中可以自定义网站链接(以指向自己的网站):
|
||||||
@ -140,10 +107,11 @@ const siteIcon = {
|
|||||||
|
|
||||||
也可自行更换其他方式
|
也可自行更换其他方式
|
||||||
|
|
||||||
|
|
||||||
### 音乐
|
### 音乐
|
||||||
|
|
||||||
>本项目采用了基于 `MetingJS` 的 `Aplayer` 音乐播放器,可实现快速自定义歌单
|
>本项目采用了基于 `MetingJS` 的 `Aplayer` 音乐播放器,可实现快速自定义歌单
|
||||||
> \*仅支持 **中国大陆地区**
|
>*仅支持 **中国大陆地区**
|
||||||
|
|
||||||
请在 `.env` 文件中更改歌曲相关参数即可实现自定义歌单列表
|
请在 `.env` 文件中更改歌曲相关参数即可实现自定义歌单列表
|
||||||
|
|
||||||
@ -210,9 +178,12 @@ make clean all
|
|||||||
如果想要添加更多的本地图片作为网站背景,可以将图片重命名 `background+数字` 的形式,并在 `src/components/Background/index.vue` 中进行修改:
|
如果想要添加更多的本地图片作为网站背景,可以将图片重命名 `background+数字` 的形式,并在 `src/components/Background/index.vue` 中进行修改:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
|
|
||||||
if (type == 0) {
|
if (type == 0) {
|
||||||
// 修改此处 Math.random() 后面的第一个数字为图片的数量
|
// 修改此处 Math.random() 后面的第一个数字为图片的数量
|
||||||
bgUrl.value = `/images/background${Math.floor(Math.random() * 10 + 1)}.webp`;
|
bgUrl.value = `/images/background${Math.floor(
|
||||||
|
Math.random() * 10 + 1
|
||||||
|
)}.webp`;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -222,20 +193,20 @@ if (type == 0) {
|
|||||||
|
|
||||||
### 技术栈
|
### 技术栈
|
||||||
|
|
||||||
- [Vue](https://cn.vuejs.org/)
|
* [Vue](https://cn.vuejs.org/)
|
||||||
- [Vite](https://vitejs.cn/vite3-cn/)
|
* [Vite](https://vitejs.cn/vite3-cn/)
|
||||||
- [Pinia](https://pinia.vuejs.org/zh/)
|
* [Pinia](https://pinia.vuejs.org/zh/)
|
||||||
- [IconPark](https://iconpark.oceanengine.com/official)
|
* [IconPark](https://iconpark.oceanengine.com/official)
|
||||||
- [xicons](https://xicons.org/)
|
* [xicons](https://xicons.org/)
|
||||||
- [Aplayer](https://aplayer.js.org/)
|
* [Aplayer](https://aplayer.js.org/)
|
||||||
|
|
||||||
### API
|
### API
|
||||||
|
|
||||||
- [韩小韩 WebAPI 接口](https://api.vvhan.com/)
|
* [小歪 API](https://api.aixiaowai.cn)
|
||||||
- [搏天 API](https://api.btstu.cn/doc/sjbz.php)
|
* [搏天 API](https://api.btstu.cn/doc/sjbz.php)
|
||||||
- [教书先生 API](https://api.oioweb.cn/doc/weather/GetWeather)
|
* [高德开放平台](https://lbs.amap.com/)
|
||||||
- [高德开放平台](https://lbs.amap.com/)
|
* [Hitokoto 一言](https://hitokoto.cn/)
|
||||||
- [Hitokoto 一言](https://hitokoto.cn/)
|
* [MetingAPI By 武恩赐](https://api.wuenci.com/meting/api/)
|
||||||
|
|
||||||
## Star History
|
## Star History
|
||||||
|
|
||||||
|
@ -136,7 +136,7 @@ make clean all
|
|||||||
|
|
||||||
### API
|
### API
|
||||||
|
|
||||||
* [韩小韩 WebAPI 接口](https://api.vvhan.com/)
|
* [MetingAPI By 武恩赐](https://api.wuenci.com/meting/api/)
|
||||||
* [搏天 API](https://api.btstu.cn/doc/sjbz.php)
|
* [搏天 API](https://api.btstu.cn/doc/sjbz.php)
|
||||||
* [高德开放平台](https://lbs.amap.com/)
|
* [高德开放平台](https://lbs.amap.com/)
|
||||||
* [Hitokoto 一言](https://hitokoto.cn/)
|
* [Hitokoto 一言](https://hitokoto.cn/)
|
||||||
|
57
auto-imports.d.ts
vendored
57
auto-imports.d.ts
vendored
@ -1,57 +0,0 @@
|
|||||||
// Generated by 'unplugin-auto-import'
|
|
||||||
export {}
|
|
||||||
declare global {
|
|
||||||
const EffectScope: typeof import('vue')['EffectScope']
|
|
||||||
const ElMessage: typeof import('element-plus/es')['ElMessage']
|
|
||||||
const computed: typeof import('vue')['computed']
|
|
||||||
const createApp: typeof import('vue')['createApp']
|
|
||||||
const customRef: typeof import('vue')['customRef']
|
|
||||||
const defineAsyncComponent: typeof import('vue')['defineAsyncComponent']
|
|
||||||
const defineComponent: typeof import('vue')['defineComponent']
|
|
||||||
const effectScope: typeof import('vue')['effectScope']
|
|
||||||
const getCurrentInstance: typeof import('vue')['getCurrentInstance']
|
|
||||||
const getCurrentScope: typeof import('vue')['getCurrentScope']
|
|
||||||
const h: typeof import('vue')['h']
|
|
||||||
const inject: typeof import('vue')['inject']
|
|
||||||
const isProxy: typeof import('vue')['isProxy']
|
|
||||||
const isReactive: typeof import('vue')['isReactive']
|
|
||||||
const isReadonly: typeof import('vue')['isReadonly']
|
|
||||||
const isRef: typeof import('vue')['isRef']
|
|
||||||
const markRaw: typeof import('vue')['markRaw']
|
|
||||||
const nextTick: typeof import('vue')['nextTick']
|
|
||||||
const onActivated: typeof import('vue')['onActivated']
|
|
||||||
const onBeforeMount: typeof import('vue')['onBeforeMount']
|
|
||||||
const onBeforeUnmount: typeof import('vue')['onBeforeUnmount']
|
|
||||||
const onBeforeUpdate: typeof import('vue')['onBeforeUpdate']
|
|
||||||
const onDeactivated: typeof import('vue')['onDeactivated']
|
|
||||||
const onErrorCaptured: typeof import('vue')['onErrorCaptured']
|
|
||||||
const onMounted: typeof import('vue')['onMounted']
|
|
||||||
const onRenderTracked: typeof import('vue')['onRenderTracked']
|
|
||||||
const onRenderTriggered: typeof import('vue')['onRenderTriggered']
|
|
||||||
const onScopeDispose: typeof import('vue')['onScopeDispose']
|
|
||||||
const onServerPrefetch: typeof import('vue')['onServerPrefetch']
|
|
||||||
const onUnmounted: typeof import('vue')['onUnmounted']
|
|
||||||
const onUpdated: typeof import('vue')['onUpdated']
|
|
||||||
const provide: typeof import('vue')['provide']
|
|
||||||
const reactive: typeof import('vue')['reactive']
|
|
||||||
const readonly: typeof import('vue')['readonly']
|
|
||||||
const ref: typeof import('vue')['ref']
|
|
||||||
const resolveComponent: typeof import('vue')['resolveComponent']
|
|
||||||
const resolveDirective: typeof import('vue')['resolveDirective']
|
|
||||||
const shallowReactive: typeof import('vue')['shallowReactive']
|
|
||||||
const shallowReadonly: typeof import('vue')['shallowReadonly']
|
|
||||||
const shallowRef: typeof import('vue')['shallowRef']
|
|
||||||
const toRaw: typeof import('vue')['toRaw']
|
|
||||||
const toRef: typeof import('vue')['toRef']
|
|
||||||
const toRefs: typeof import('vue')['toRefs']
|
|
||||||
const triggerRef: typeof import('vue')['triggerRef']
|
|
||||||
const unref: typeof import('vue')['unref']
|
|
||||||
const useAttrs: typeof import('vue')['useAttrs']
|
|
||||||
const useCssModule: typeof import('vue')['useCssModule']
|
|
||||||
const useCssVars: typeof import('vue')['useCssVars']
|
|
||||||
const useSlots: typeof import('vue')['useSlots']
|
|
||||||
const watch: typeof import('vue')['watch']
|
|
||||||
const watchEffect: typeof import('vue')['watchEffect']
|
|
||||||
const watchPostEffect: typeof import('vue')['watchPostEffect']
|
|
||||||
const watchSyncEffect: typeof import('vue')['watchSyncEffect']
|
|
||||||
}
|
|
35
components.d.ts
vendored
35
components.d.ts
vendored
@ -1,35 +0,0 @@
|
|||||||
// generated by unplugin-vue-components
|
|
||||||
// We suggest you to commit this file into source control
|
|
||||||
// Read more: https://github.com/vuejs/core/pull/3399
|
|
||||||
import '@vue/runtime-core'
|
|
||||||
|
|
||||||
export {}
|
|
||||||
|
|
||||||
declare module '@vue/runtime-core' {
|
|
||||||
export interface GlobalComponents {
|
|
||||||
Background: typeof import('./src/components/Background.vue')['default']
|
|
||||||
ElCard: typeof import('element-plus/es')['ElCard']
|
|
||||||
ElCol: typeof import('element-plus/es')['ElCol']
|
|
||||||
ElCollapse: typeof import('element-plus/es')['ElCollapse']
|
|
||||||
ElCollapseItem: typeof import('element-plus/es')['ElCollapseItem']
|
|
||||||
ElProgress: typeof import('element-plus/es')['ElProgress']
|
|
||||||
ElRadio: typeof import('element-plus/es')['ElRadio']
|
|
||||||
ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup']
|
|
||||||
ElRow: typeof import('element-plus/es')['ElRow']
|
|
||||||
ElSlider: typeof import('element-plus/es')['ElSlider']
|
|
||||||
ElSwitch: typeof import('element-plus/es')['ElSwitch']
|
|
||||||
ElTooltip: typeof import('element-plus/es')['ElTooltip']
|
|
||||||
Footer: typeof import('./src/components/Footer.vue')['default']
|
|
||||||
Hitokoto: typeof import('./src/components/Hitokoto.vue')['default']
|
|
||||||
Links: typeof import('./src/components/Links.vue')['default']
|
|
||||||
Loading: typeof import('./src/components/Loading.vue')['default']
|
|
||||||
Message: typeof import('./src/components/Message.vue')['default']
|
|
||||||
MoreContent: typeof import('./src/components/MoreContent.vue')['default']
|
|
||||||
Music: typeof import('./src/components/Music.vue')['default']
|
|
||||||
Player: typeof import('./src/components/Player.vue')['default']
|
|
||||||
Set: typeof import('./src/components/Set.vue')['default']
|
|
||||||
SocialLinks: typeof import('./src/components/SocialLinks.vue')['default']
|
|
||||||
TimeCapsule: typeof import('./src/components/TimeCapsule.vue')['default']
|
|
||||||
Weather: typeof import('./src/components/Weather.vue')['default']
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,9 +0,0 @@
|
|||||||
version: '3'
|
|
||||||
|
|
||||||
services:
|
|
||||||
app:
|
|
||||||
build:
|
|
||||||
context: .
|
|
||||||
dockerfile: Dockerfile
|
|
||||||
ports:
|
|
||||||
- "12445:12445"
|
|
42
package.json
42
package.json
@ -4,41 +4,39 @@
|
|||||||
"github": "https://github.com/imsyy/home",
|
"github": "https://github.com/imsyy/home",
|
||||||
"home": "https://imsyy.top",
|
"home": "https://imsyy.top",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "4.1.4",
|
"version": "4.1.3",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite --host",
|
"dev": "vite --host",
|
||||||
"build": "vite build",
|
"build": "vite build",
|
||||||
"preview": "vite preview",
|
"preview": "vite preview",
|
||||||
"format": "prettier --write src/",
|
"format": "prettier --write src/"
|
||||||
"lint": "eslint . --ext .js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts,.vue --fix"
|
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@worstone/vue-aplayer": "^1.0.6",
|
|
||||||
"aplayer": "^1.10.1",
|
"aplayer": "^1.10.1",
|
||||||
"axios": "^1.6.8",
|
"axios": "^1.1.3",
|
||||||
"dayjs": "^1.11.10",
|
"element-plus": "^2.2.18",
|
||||||
"element-plus": "^2.7.1",
|
"fetch-jsonp": "^1.2.3",
|
||||||
"fetch-jsonp": "^1.3.0",
|
"pinia": "^2.0.23",
|
||||||
"pinia": "^2.1.7",
|
"pinia-plugin-persistedstate": "^3.0.0",
|
||||||
"pinia-plugin-persistedstate": "^3.2.1",
|
"swiper": "^9.3.2",
|
||||||
"swiper": "^11.1.1",
|
"vue": "^3.3.4",
|
||||||
"vue": "^3.4.24"
|
"vue3-aplayer": "^1.7.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@icon-park/vue-next": "^1.4.2",
|
"@icon-park/vue-next": "^1.4.2",
|
||||||
"@vicons/fa": "^0.12.0",
|
"@vicons/fa": "^0.12.0",
|
||||||
"@vicons/utils": "^0.1.4",
|
"@vicons/utils": "^0.1.4",
|
||||||
"@vitejs/plugin-vue": "^4.6.2",
|
"@vitejs/plugin-vue": "^4.2.3",
|
||||||
"eslint": "^8.57.0",
|
"eslint": "^8.48.0",
|
||||||
"eslint-plugin-vue": "^9.25.0",
|
"eslint-plugin-vue": "^9.17.0",
|
||||||
"prettier": "^3.2.5",
|
"prettier": "^3.0.2",
|
||||||
"sass": "^1.75.0",
|
"sass": "^1.55.0",
|
||||||
"terser": "^5.30.4",
|
"terser": "^5.16.1",
|
||||||
"unplugin-auto-import": "^0.11.5",
|
"unplugin-auto-import": "^0.11.2",
|
||||||
"unplugin-vue-components": "^0.22.12",
|
"unplugin-vue-components": "^0.22.8",
|
||||||
"vite": "^4.5.3",
|
"vite": "^4.4.5",
|
||||||
"vite-plugin-compression": "^0.5.1",
|
"vite-plugin-compression": "^0.5.1",
|
||||||
"vite-plugin-pwa": "^0.14.7"
|
"vite-plugin-pwa": "^0.14.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
6663
pnpm-lock.yaml
6663
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Before Width: | Height: | Size: 245 KiB |
Binary file not shown.
Before Width: | Height: | Size: 56 KiB |
Binary file not shown.
Before Width: | Height: | Size: 67 KiB |
@ -13,7 +13,6 @@ export const getPlayerList = async (server, type, id) => {
|
|||||||
const data = await res.json();
|
const data = await res.json();
|
||||||
|
|
||||||
if (data[0].url.startsWith("@")) {
|
if (data[0].url.startsWith("@")) {
|
||||||
// eslint-disable-next-line no-unused-vars
|
|
||||||
const [handle, jsonpCallback, jsonpCallbackFunction, url] = data[0].url.split("@").slice(1);
|
const [handle, jsonpCallback, jsonpCallbackFunction, url] = data[0].url.split("@").slice(1);
|
||||||
const jsonpData = await fetchJsonp(url).then((res) => res.json());
|
const jsonpData = await fetchJsonp(url).then((res) => res.json());
|
||||||
const domain = (
|
const domain = (
|
||||||
@ -22,18 +21,18 @@ export const getPlayerList = async (server, type, id) => {
|
|||||||
).replace("http://", "https://");
|
).replace("http://", "https://");
|
||||||
|
|
||||||
return data.map((v, i) => ({
|
return data.map((v, i) => ({
|
||||||
name: v.name || v.title,
|
title: v.name || v.title,
|
||||||
artist: v.artist || v.author,
|
artist: v.artist || v.author,
|
||||||
url: domain + jsonpData.req_0.data.midurlinfo[i].purl,
|
src: domain + jsonpData.req_0.data.midurlinfo[i].purl,
|
||||||
cover: v.cover || v.pic,
|
pic: v.pic,
|
||||||
lrc: v.lrc,
|
lrc: v.lrc,
|
||||||
}));
|
}));
|
||||||
} else {
|
} else {
|
||||||
return data.map((v) => ({
|
return data.map((v) => ({
|
||||||
name: v.name || v.title,
|
title: v.name || v.title,
|
||||||
artist: v.artist || v.author,
|
artist: v.artist || v.author,
|
||||||
url: v.url,
|
src: v.url,
|
||||||
cover: v.cover || v.pic,
|
pic: v.pic,
|
||||||
lrc: v.lrc,
|
lrc: v.lrc,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
@ -2,9 +2,9 @@
|
|||||||
<div :class="store.backgroundShow ? 'cover show' : 'cover'">
|
<div :class="store.backgroundShow ? 'cover show' : 'cover'">
|
||||||
<img
|
<img
|
||||||
v-show="store.imgLoadStatus"
|
v-show="store.imgLoadStatus"
|
||||||
:src="bgUrl"
|
|
||||||
class="bg"
|
class="bg"
|
||||||
alt="cover"
|
alt="cover"
|
||||||
|
:src="bgUrl"
|
||||||
@load="imgLoadComplete"
|
@load="imgLoadComplete"
|
||||||
@error.once="imgLoadError"
|
@error.once="imgLoadError"
|
||||||
@animationend="imgAnimationEnd"
|
@animationend="imgAnimationEnd"
|
||||||
@ -43,9 +43,9 @@ const changeBg = (type) => {
|
|||||||
} else if (type == 1) {
|
} else if (type == 1) {
|
||||||
bgUrl.value = "https://api.dujin.org/bing/1920.php";
|
bgUrl.value = "https://api.dujin.org/bing/1920.php";
|
||||||
} else if (type == 2) {
|
} else if (type == 2) {
|
||||||
bgUrl.value = "https://api.vvhan.com/api/wallpaper/views";
|
bgUrl.value = "https://api.aixiaowai.cn/gqapi/gqapi.php";
|
||||||
} else if (type == 3) {
|
} else if (type == 3) {
|
||||||
bgUrl.value = "https://api.vvhan.com/api/wallpaper/acg";
|
bgUrl.value = "https://api.aixiaowai.cn/api/api.php";
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -79,14 +79,6 @@ const imgLoadError = () => {
|
|||||||
bgUrl.value = `/images/background${bgRandom}.jpg`;
|
bgUrl.value = `/images/background${bgRandom}.jpg`;
|
||||||
};
|
};
|
||||||
|
|
||||||
// 监听壁纸切换
|
|
||||||
watch(
|
|
||||||
() => store.coverType,
|
|
||||||
(value) => {
|
|
||||||
changeBg(value);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
// 加载壁纸
|
// 加载壁纸
|
||||||
changeBg(store.coverType);
|
changeBg(store.coverType);
|
||||||
@ -123,7 +115,7 @@ onBeforeUnmount(() => {
|
|||||||
transition:
|
transition:
|
||||||
filter 0.3s,
|
filter 0.3s,
|
||||||
transform 0.3s;
|
transform 0.3s;
|
||||||
animation: fade-blur-in 0.8s cubic-bezier(0.25, 0.46, 0.45, 0.94) forwards;
|
animation: fade-blur-in 1s cubic-bezier(0.25, 0.46, 0.45, 0.94) forwards;
|
||||||
animation-delay: 0.45s;
|
animation-delay: 0.45s;
|
||||||
}
|
}
|
||||||
.gray {
|
.gray {
|
||||||
|
@ -45,12 +45,13 @@ const hitokotoData = reactive({
|
|||||||
});
|
});
|
||||||
|
|
||||||
// 获取一言数据
|
// 获取一言数据
|
||||||
const getHitokotoData = async () => {
|
const getHitokotoData = () => {
|
||||||
try {
|
getHitokoto()
|
||||||
const result = await getHitokoto();
|
.then((res) => {
|
||||||
hitokotoData.text = result.hitokoto;
|
hitokotoData.text = res.hitokoto;
|
||||||
hitokotoData.from = result.from;
|
hitokotoData.from = res.from;
|
||||||
} catch (error) {
|
})
|
||||||
|
.catch(() => {
|
||||||
ElMessage({
|
ElMessage({
|
||||||
message: "一言获取失败",
|
message: "一言获取失败",
|
||||||
icon: h(Error, {
|
icon: h(Error, {
|
||||||
@ -60,7 +61,7 @@ const getHitokotoData = async () => {
|
|||||||
});
|
});
|
||||||
hitokotoData.text = "这里应该显示一句话";
|
hitokotoData.text = "这里应该显示一句话";
|
||||||
hitokotoData.from = "無名";
|
hitokotoData.from = "無名";
|
||||||
}
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// 更新一言数据
|
// 更新一言数据
|
||||||
|
@ -46,8 +46,10 @@ import { Icon } from "@vicons/utils";
|
|||||||
import { Link, Blog, CompactDisc, Cloud, Compass, Book, Fire, LaptopCode } from "@vicons/fa"; // 注意使用正确的类别
|
import { Link, Blog, CompactDisc, Cloud, Compass, Book, Fire, LaptopCode } from "@vicons/fa"; // 注意使用正确的类别
|
||||||
import { mainStore } from "@/store";
|
import { mainStore } from "@/store";
|
||||||
import { Swiper, SwiperSlide } from "swiper/vue";
|
import { Swiper, SwiperSlide } from "swiper/vue";
|
||||||
import { Pagination, Mousewheel } from "swiper/modules";
|
import { Pagination, Mousewheel } from "swiper";
|
||||||
import siteLinks from "@/assets/siteLinks.json";
|
import siteLinks from "@/assets/siteLinks.json";
|
||||||
|
import "swiper/scss";
|
||||||
|
import "swiper/scss/pagination";
|
||||||
|
|
||||||
const store = mainStore();
|
const store = mainStore();
|
||||||
|
|
||||||
@ -109,22 +111,14 @@ onMounted(() => {
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
.swiper-pagination {
|
.swiper-pagination {
|
||||||
margin-top: 12px;
|
position: static;
|
||||||
display: flex;
|
margin-top: 4px;
|
||||||
flex-direction: row;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
:deep(.swiper-pagination-bullet) {
|
:deep(.swiper-pagination-bullet) {
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
width: 20px;
|
width: 18px;
|
||||||
height: 4px;
|
height: 4px;
|
||||||
margin: 0 4px;
|
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
opacity: 0.2;
|
|
||||||
transition: opacity 0.3s;
|
transition: opacity 0.3s;
|
||||||
&.swiper-pagination-bullet-active {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
&:hover {
|
&:hover {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
@ -15,12 +15,10 @@
|
|||||||
<Icon size="16">
|
<Icon size="16">
|
||||||
<QuoteLeft />
|
<QuoteLeft />
|
||||||
</Icon>
|
</Icon>
|
||||||
<Transition name="fade" mode="out-in">
|
<div class="text">
|
||||||
<div :key="descriptionText.hello + descriptionText.text" class="text">
|
|
||||||
<p>{{ descriptionText.hello }}</p>
|
<p>{{ descriptionText.hello }}</p>
|
||||||
<p>{{ descriptionText.text }}</p>
|
<p>{{ descriptionText.text }}</p>
|
||||||
</div>
|
</div>
|
||||||
</Transition>
|
|
||||||
<Icon size="16">
|
<Icon size="16">
|
||||||
<QuoteRight />
|
<QuoteRight />
|
||||||
</Icon>
|
</Icon>
|
||||||
@ -148,7 +146,6 @@ watch(
|
|||||||
margin: 0.75rem 1rem;
|
margin: 0.75rem 1rem;
|
||||||
line-height: 2rem;
|
line-height: 2rem;
|
||||||
margin-right: auto;
|
margin-right: auto;
|
||||||
transition: opacity 0.2s;
|
|
||||||
|
|
||||||
p {
|
p {
|
||||||
&:nth-of-type(1) {
|
&:nth-of-type(1) {
|
||||||
|
@ -1,14 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="more-content">您可在此编写任意内容</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.more-content {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
margin-top: 20px;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
</style>
|
|
@ -12,12 +12,10 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="control">
|
<div class="control">
|
||||||
<go-start theme="filled" size="30" fill="#efefef" @click="changeMusicIndex(0)" />
|
<go-start theme="filled" size="30" fill="#efefef" @click="changeMusicIndex(0)" />
|
||||||
<Transition name="fade" mode="out-in">
|
<div class="state" @click="changePlayState">
|
||||||
<div :key="store.playerState" class="state" @click="changePlayState">
|
|
||||||
<play-one theme="filled" size="50" fill="#efefef" v-show="!store.playerState" />
|
<play-one theme="filled" size="50" fill="#efefef" v-show="!store.playerState" />
|
||||||
<pause theme="filled" size="50" fill="#efefef" v-show="store.playerState" />
|
<pause theme="filled" size="50" fill="#efefef" v-show="store.playerState" />
|
||||||
</div>
|
</div>
|
||||||
</Transition>
|
|
||||||
<go-end theme="filled" size="30" fill="#efefef" @click="changeMusicIndex(1)" />
|
<go-end theme="filled" size="30" fill="#efefef" @click="changeMusicIndex(1)" />
|
||||||
</div>
|
</div>
|
||||||
<div class="menu">
|
<div class="menu">
|
||||||
@ -45,7 +43,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<!-- 音乐列表弹窗 -->
|
<!-- 音乐列表弹窗 -->
|
||||||
<Transition name="fade" mode="out-in">
|
<Transition name="fade" mode="out-in">
|
||||||
<div class="music-list" v-show="musicListShow" @click="closeMusicList()">
|
<div class="music-list" v-show="musicListShow" @click="musicListShow = false">
|
||||||
<Transition name="zoom">
|
<Transition name="zoom">
|
||||||
<div class="list" v-show="musicListShow" @click.stop>
|
<div class="list" v-show="musicListShow" @click.stop>
|
||||||
<close-one
|
<close-one
|
||||||
@ -53,14 +51,15 @@
|
|||||||
theme="filled"
|
theme="filled"
|
||||||
size="28"
|
size="28"
|
||||||
fill="#ffffff60"
|
fill="#ffffff60"
|
||||||
@click="closeMusicList()"
|
@click="musicListShow = false"
|
||||||
/>
|
/>
|
||||||
<Player
|
<Player
|
||||||
ref="playerRef"
|
|
||||||
:songServer="playerData.server"
|
:songServer="playerData.server"
|
||||||
:songType="playerData.type"
|
:songType="playerData.type"
|
||||||
:songId="playerData.id"
|
:songId="playerData.id"
|
||||||
:volume="volumeNum"
|
:volume="volumeNum"
|
||||||
|
:shuffle="false"
|
||||||
|
ref="playerRef"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</Transition>
|
</Transition>
|
||||||
@ -99,13 +98,6 @@ const playerData = reactive({
|
|||||||
// 开启播放列表
|
// 开启播放列表
|
||||||
const openMusicList = () => {
|
const openMusicList = () => {
|
||||||
musicListShow.value = true;
|
musicListShow.value = true;
|
||||||
playerRef.value.toggleList();
|
|
||||||
};
|
|
||||||
|
|
||||||
// 关闭播放列表
|
|
||||||
const closeMusicList = () => {
|
|
||||||
musicListShow.value = false;
|
|
||||||
playerRef.value.toggleList();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// 音乐播放暂停
|
// 音乐播放暂停
|
||||||
@ -121,9 +113,6 @@ const changeMusicIndex = (type) => {
|
|||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
// 空格键事件
|
// 空格键事件
|
||||||
window.addEventListener("keydown", (e) => {
|
window.addEventListener("keydown", (e) => {
|
||||||
if (!store.musicIsOk) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (e.code == "Space") {
|
if (e.code == "Space") {
|
||||||
changePlayState();
|
changePlayState();
|
||||||
}
|
}
|
||||||
@ -179,7 +168,6 @@ watch(
|
|||||||
justify-content: space-evenly;
|
justify-content: space-evenly;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
.state {
|
.state {
|
||||||
transition: opacity 0.1s;
|
|
||||||
.i-icon {
|
.i-icon {
|
||||||
width: 50px;
|
width: 50px;
|
||||||
height: 50px;
|
height: 50px;
|
||||||
|
@ -1,21 +1,21 @@
|
|||||||
<template>
|
<template>
|
||||||
<APlayer
|
<aplayer
|
||||||
v-if="playList[0]"
|
showLrc
|
||||||
ref="player"
|
ref="player"
|
||||||
:audio="playList"
|
v-if="playList[0]"
|
||||||
:autoplay="store.playerAutoplay"
|
:music="playList[playIndex]"
|
||||||
|
:list="playList"
|
||||||
|
:autoplay="autoplay"
|
||||||
:theme="theme"
|
:theme="theme"
|
||||||
:autoSwitch="false"
|
:repeat="repeat"
|
||||||
:loop="store.playerLoop"
|
:shuffle="shuffle"
|
||||||
:order="store.playerOrder"
|
|
||||||
:volume="volume"
|
|
||||||
:showLrc="true"
|
|
||||||
:listFolded="listFolded"
|
|
||||||
:listMaxHeight="listMaxHeight"
|
:listMaxHeight="listMaxHeight"
|
||||||
:noticeSwitch="false"
|
:listFolded="listFolded"
|
||||||
|
:volume="volume"
|
||||||
@play="onPlay"
|
@play="onPlay"
|
||||||
@pause="onPause"
|
@pause="onPause"
|
||||||
@timeupdate="onTimeUp"
|
@timeupdate="onTimeUp"
|
||||||
|
@onSelectSong="onSelectSong"
|
||||||
@error="loadMusicError"
|
@error="loadMusicError"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
@ -24,7 +24,7 @@
|
|||||||
import { MusicOne, PlayWrong } from "@icon-park/vue-next";
|
import { MusicOne, PlayWrong } from "@icon-park/vue-next";
|
||||||
import { getPlayerList } from "@/api";
|
import { getPlayerList } from "@/api";
|
||||||
import { mainStore } from "@/store";
|
import { mainStore } from "@/store";
|
||||||
import APlayer from "@worstone/vue-aplayer";
|
import aplayer from "vue3-aplayer";
|
||||||
|
|
||||||
const store = mainStore();
|
const store = mainStore();
|
||||||
|
|
||||||
@ -36,14 +36,32 @@ const playList = ref([]);
|
|||||||
|
|
||||||
// 歌曲播放项
|
// 歌曲播放项
|
||||||
const playIndex = ref(0);
|
const playIndex = ref(0);
|
||||||
|
const playListCount = ref(0);
|
||||||
|
|
||||||
|
const skipTimeout = ref(null);
|
||||||
|
|
||||||
// 配置项
|
// 配置项
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
|
// 音频自动播放
|
||||||
|
autoplay: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
// 主题色
|
// 主题色
|
||||||
theme: {
|
theme: {
|
||||||
type: String,
|
type: String,
|
||||||
default: "#efefef",
|
default: "#efefef",
|
||||||
},
|
},
|
||||||
|
// 音频循环播放
|
||||||
|
repeat: {
|
||||||
|
type: String,
|
||||||
|
default: "list", //'list' | 'music' | 'none'
|
||||||
|
},
|
||||||
|
// 随机播放
|
||||||
|
shuffle: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
// 默认音量
|
// 默认音量
|
||||||
volume: {
|
volume: {
|
||||||
type: Number,
|
type: Number,
|
||||||
@ -74,28 +92,39 @@ const props = defineProps({
|
|||||||
},
|
},
|
||||||
// 列表最大高度
|
// 列表最大高度
|
||||||
listMaxHeight: {
|
listMaxHeight: {
|
||||||
type: Number,
|
type: String,
|
||||||
default: 420,
|
default: "420px",
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const listHeight = computed(() => {
|
|
||||||
return props.listMaxHeight + "px";
|
|
||||||
});
|
|
||||||
|
|
||||||
// 初始化播放器
|
// 初始化播放器
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
try {
|
try {
|
||||||
getPlayerList(props.songServer, props.songType, props.songId).then((res) => {
|
getPlayerList(props.songServer, props.songType, props.songId).then((res) => {
|
||||||
console.log(res);
|
console.log(res);
|
||||||
|
// 生成歌单信息
|
||||||
|
playIndex.value = Math.floor(Math.random() * res.length);
|
||||||
|
playListCount.value = res.length;
|
||||||
// 更改播放器加载状态
|
// 更改播放器加载状态
|
||||||
store.musicIsOk = true;
|
store.musicIsOk = true;
|
||||||
// 生成歌单
|
// 生成歌单
|
||||||
playList.value = res;
|
res.forEach((v) => {
|
||||||
console.log("音乐加载完成");
|
playList.value.push({
|
||||||
console.log(playList.value);
|
title: v.name || v.title,
|
||||||
console.log(playIndex.value, playList.value.length, props.volume);
|
artist: v.artist || v.author,
|
||||||
|
src: v.url || v.src,
|
||||||
|
pic: v.pic,
|
||||||
|
lrc: v.lrc,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
console.log(
|
||||||
|
"音乐加载完成",
|
||||||
|
playList.value,
|
||||||
|
playIndex.value,
|
||||||
|
playListCount.value,
|
||||||
|
props.volume,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
@ -115,11 +144,10 @@ onMounted(() => {
|
|||||||
// 播放
|
// 播放
|
||||||
const onPlay = () => {
|
const onPlay = () => {
|
||||||
console.log("播放");
|
console.log("播放");
|
||||||
playIndex.value = player.value.aplayer.index;
|
|
||||||
// 播放状态
|
// 播放状态
|
||||||
store.setPlayerState(player.value.audioRef.paused);
|
store.setPlayerState(player.value.audio.paused);
|
||||||
// 储存播放器信息
|
// 储存播放器信息
|
||||||
store.setPlayerData(playList.value[playIndex.value].name, playList.value[playIndex.value].artist);
|
store.setPlayerData(player.value.currentMusic.title, player.value.currentMusic.artist);
|
||||||
ElMessage({
|
ElMessage({
|
||||||
message: store.getPlayerData.name + " - " + store.getPlayerData.artist,
|
message: store.getPlayerData.name + " - " + store.getPlayerData.artist,
|
||||||
grouping: true,
|
grouping: true,
|
||||||
@ -132,23 +160,19 @@ const onPlay = () => {
|
|||||||
|
|
||||||
// 暂停
|
// 暂停
|
||||||
const onPause = () => {
|
const onPause = () => {
|
||||||
store.setPlayerState(player.value.audioRef.paused);
|
store.setPlayerState(player.value.audio.paused);
|
||||||
};
|
};
|
||||||
|
|
||||||
// 音频时间更新事件
|
// 音频时间更新事件
|
||||||
const onTimeUp = () => {
|
const onTimeUp = () => {
|
||||||
let lyrics = player.value.aplayer.lyrics[playIndex.value];
|
let playerRef = player.value.$.vnode.el;
|
||||||
let lyricIndex = player.value.aplayer.lyricIndex;
|
if (playerRef) {
|
||||||
if (!lyrics || !lyrics[lyricIndex]) {
|
const currentLrcElement = playerRef.querySelector(".aplayer-lrc-current");
|
||||||
return;
|
const previousLrcElement = currentLrcElement?.previousElementSibling;
|
||||||
|
const lrcContent =
|
||||||
|
currentLrcElement?.innerHTML || previousLrcElement?.innerHTML || "这句没有歌词";
|
||||||
|
store.setPlayerLrc(lrcContent);
|
||||||
}
|
}
|
||||||
let lrc = lyrics[lyricIndex][1];
|
|
||||||
if (lrc === "Loading") {
|
|
||||||
lrc = "歌词加载中";
|
|
||||||
} else if (lrc === "Not available") {
|
|
||||||
lrc = "歌词加载失败";
|
|
||||||
}
|
|
||||||
store.setPlayerLrc(lrc);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// 切换播放暂停事件
|
// 切换播放暂停事件
|
||||||
@ -158,27 +182,41 @@ const playToggle = () => {
|
|||||||
|
|
||||||
// 切换音量事件
|
// 切换音量事件
|
||||||
const changeVolume = (value) => {
|
const changeVolume = (value) => {
|
||||||
player.value.setVolume(value, false);
|
player.value.audio.volume = value;
|
||||||
|
};
|
||||||
|
|
||||||
|
const onSelectSong = (val) => {
|
||||||
|
console.log(val);
|
||||||
};
|
};
|
||||||
|
|
||||||
// 切换上下曲
|
// 切换上下曲
|
||||||
const changeSong = (type) => {
|
const changeSong = (type) => {
|
||||||
type === 0 ? player.value.skipBack() : player.value.skipForward();
|
playIndex.value = player.value.playIndex;
|
||||||
|
playIndex.value += type ? 1 : -1;
|
||||||
|
// 判断是否处于最后/第一首
|
||||||
|
if (playIndex.value < 0) {
|
||||||
|
playIndex.value = playListCount.value - 1;
|
||||||
|
} else if (playIndex.value >= playListCount.value) {
|
||||||
|
playIndex.value = 0;
|
||||||
|
}
|
||||||
|
// console.log(playIndex.value, playList.value[playIndex.value]);
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
player.value.play();
|
player.value.play();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// 切换歌曲列表状态
|
|
||||||
const toggleList = () => {
|
|
||||||
player.value.toggleList();
|
|
||||||
};
|
|
||||||
|
|
||||||
// 加载音频错误
|
// 加载音频错误
|
||||||
const loadMusicError = () => {
|
const loadMusicError = () => {
|
||||||
let notice = "";
|
let notice = "";
|
||||||
if (playList.value.length > 1) {
|
if (playList.value.length > 1) {
|
||||||
notice = "播放歌曲出现错误,播放器将在 2s 后进行下一首";
|
notice = "播放歌曲出现错误,播放器将在 2s 后进行下一首";
|
||||||
|
// 播放下一首
|
||||||
|
skipTimeout.value = setTimeout(() => {
|
||||||
|
changeSong(1);
|
||||||
|
if (!player.value.audio.paused) {
|
||||||
|
onPlay();
|
||||||
|
}
|
||||||
|
}, 2000);
|
||||||
} else {
|
} else {
|
||||||
notice = "播放歌曲出现错误";
|
notice = "播放歌曲出现错误";
|
||||||
}
|
}
|
||||||
@ -191,22 +229,24 @@ const loadMusicError = () => {
|
|||||||
duration: 2000,
|
duration: 2000,
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
console.error(
|
console.error("播放歌曲: " + player.value.currentMusic.title + " 出现错误");
|
||||||
"播放歌曲: " + player.value.aplayer.audio[player.value.aplayer.index].name + " 出现错误",
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// 暴露子组件方法
|
// 暴露子组件方法
|
||||||
defineExpose({ playToggle, changeVolume, changeSong, toggleList });
|
defineExpose({ playToggle, changeVolume, changeSong });
|
||||||
|
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
clearTimeout(skipTimeout.value);
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.aplayer {
|
.aplayer {
|
||||||
width: 80%;
|
width: 80%;
|
||||||
|
background: transparent;
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
font-family: "HarmonyOS_Regular", sans-serif !important;
|
font-family: "HarmonyOS_Regular", sans-serif !important;
|
||||||
:deep(.aplayer-body) {
|
:deep(.aplayer-body) {
|
||||||
background-color: transparent;
|
|
||||||
.aplayer-pic {
|
.aplayer-pic {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
@ -228,8 +268,8 @@ defineExpose({ playToggle, changeVolume, changeSong, toggleList });
|
|||||||
}
|
}
|
||||||
.aplayer-lrc {
|
.aplayer-lrc {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
margin: 7px 0 6px 6px;
|
margin: 4px 0 6px 6px;
|
||||||
height: 44px;
|
height: 100%;
|
||||||
mask: linear-gradient(
|
mask: linear-gradient(
|
||||||
#fff 15%,
|
#fff 15%,
|
||||||
#fff 85%,
|
#fff 85%,
|
||||||
@ -261,8 +301,6 @@ defineExpose({ playToggle, changeVolume, changeSong, toggleList });
|
|||||||
}
|
}
|
||||||
:deep(.aplayer-list) {
|
:deep(.aplayer-list) {
|
||||||
margin-top: 6px;
|
margin-top: 6px;
|
||||||
height: v-bind(listHeight);
|
|
||||||
background-color: transparent;
|
|
||||||
ol {
|
ol {
|
||||||
&::-webkit-scrollbar-track {
|
&::-webkit-scrollbar-track {
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
|
@ -4,10 +4,10 @@
|
|||||||
<el-collapse-item title="个性壁纸" name="1">
|
<el-collapse-item title="个性壁纸" name="1">
|
||||||
<div class="bg-set">
|
<div class="bg-set">
|
||||||
<el-radio-group v-model="coverType" text-color="#ffffff" @change="radioChange">
|
<el-radio-group v-model="coverType" text-color="#ffffff" @change="radioChange">
|
||||||
<el-radio value="0" size="large" border>默认壁纸</el-radio>
|
<el-radio label="0" size="large" border>默认壁纸</el-radio>
|
||||||
<el-radio value="1" size="large" border>每日一图</el-radio>
|
<el-radio label="1" size="large" border>每日一图</el-radio>
|
||||||
<el-radio value="2" size="large" border>随机风景</el-radio>
|
<el-radio label="2" size="large" border>随机风景</el-radio>
|
||||||
<el-radio value="3" size="large" border>随机动漫</el-radio>
|
<el-radio label="3" size="large" border>随机动漫</el-radio>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</div>
|
</div>
|
||||||
</el-collapse-item>
|
</el-collapse-item>
|
||||||
@ -50,34 +50,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</el-collapse-item>
|
</el-collapse-item>
|
||||||
<el-collapse-item title="播放器配置" name="3">
|
<el-collapse-item title="播放器配置" name="3">
|
||||||
<div class="item">
|
<div>设置内容待增加</div>
|
||||||
<span class="text">自动播放</span>
|
|
||||||
<el-switch
|
|
||||||
v-model="playerAutoplay"
|
|
||||||
inline-prompt
|
|
||||||
:active-icon="CheckSmall"
|
|
||||||
:inactive-icon="CloseSmall"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div class="item">
|
|
||||||
<span class="text">随机播放</span>
|
|
||||||
<el-switch
|
|
||||||
v-model="playerOrder"
|
|
||||||
inline-prompt
|
|
||||||
:active-icon="CheckSmall"
|
|
||||||
:inactive-icon="CloseSmall"
|
|
||||||
active-value="random"
|
|
||||||
inactive-value="list"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div class="item">
|
|
||||||
<span class="text">循环模式</span>
|
|
||||||
<el-radio-group v-model="playerLoop" size="small" text-color="#FFFFFF">
|
|
||||||
<el-radio value="all" border>列表</el-radio>
|
|
||||||
<el-radio value="one" border>单曲</el-radio>
|
|
||||||
<el-radio value="none" border>不循环</el-radio>
|
|
||||||
</el-radio-group>
|
|
||||||
</div>
|
|
||||||
</el-collapse-item>
|
</el-collapse-item>
|
||||||
<el-collapse-item title="其他设置" name="4">
|
<el-collapse-item title="其他设置" name="4">
|
||||||
<div>设置内容待增加</div>
|
<div>设置内容待增加</div>
|
||||||
@ -92,16 +65,7 @@ import { mainStore } from "@/store";
|
|||||||
import { storeToRefs } from "pinia";
|
import { storeToRefs } from "pinia";
|
||||||
|
|
||||||
const store = mainStore();
|
const store = mainStore();
|
||||||
const {
|
const { coverType, siteStartShow, musicClick, playerLrcShow, footerBlur } = storeToRefs(store);
|
||||||
coverType,
|
|
||||||
siteStartShow,
|
|
||||||
musicClick,
|
|
||||||
playerLrcShow,
|
|
||||||
footerBlur,
|
|
||||||
playerAutoplay,
|
|
||||||
playerOrder,
|
|
||||||
playerLoop,
|
|
||||||
} = storeToRefs(store);
|
|
||||||
|
|
||||||
// 默认选中项
|
// 默认选中项
|
||||||
const activeName = ref("1");
|
const activeName = ref("1");
|
||||||
@ -109,7 +73,7 @@ const activeName = ref("1");
|
|||||||
// 壁纸切换
|
// 壁纸切换
|
||||||
const radioChange = () => {
|
const radioChange = () => {
|
||||||
ElMessage({
|
ElMessage({
|
||||||
message: "壁纸更换成功",
|
message: "壁纸设置成功,刷新后生效",
|
||||||
icon: h(SuccessPicture, {
|
icon: h(SuccessPicture, {
|
||||||
theme: "filled",
|
theme: "filled",
|
||||||
fill: "#efefef",
|
fill: "#efefef",
|
||||||
@ -143,23 +107,13 @@ const radioChange = () => {
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
flex-wrap: wrap;
|
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
.el-switch__core {
|
.el-switch__core {
|
||||||
border-color: transparent;
|
border-color: transparent;
|
||||||
background-color: #ffffff30;
|
background-color: #ffffff30;
|
||||||
}
|
}
|
||||||
.el-radio-group {
|
|
||||||
.el-radio {
|
|
||||||
margin: 2px 10px 2px 0;
|
|
||||||
border-radius: 5px;
|
|
||||||
|
|
||||||
&:last-child {
|
|
||||||
margin-right: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
.bg-set {
|
||||||
.el-radio-group {
|
.el-radio-group {
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
|
||||||
@ -199,4 +153,5 @@ const radioChange = () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -4,24 +4,23 @@
|
|||||||
<hourglass-full theme="two-tone" size="24" :fill="['#efefef', '#00000020']" />
|
<hourglass-full theme="two-tone" size="24" :fill="['#efefef', '#00000020']" />
|
||||||
<span>时光胶囊</span>
|
<span>时光胶囊</span>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="timeData" class="all-capsule">
|
<span class="text">今日已经度过了 {{ timeData.day.elapsed }} 小时</span>
|
||||||
<div v-for="(item, tag, index) in timeData" :key="index" class="capsule-item">
|
<el-progress :text-inside="true" :stroke-width="20" :percentage="timeData.day.pass" />
|
||||||
<div class="item-title">
|
<span class="text">本周已经度过了 {{ timeData.week.elapsed }} 天</span>
|
||||||
<span class="percentage">
|
<el-progress :text-inside="true" :stroke-width="20" :percentage="timeData.week.pass" />
|
||||||
{{ item.name }}已度过
|
<span class="text">本月已经度过了 {{ timeData.month.elapsed }} 天</span>
|
||||||
<strong>{{ item.passed }}</strong>
|
<el-progress :text-inside="true" :stroke-width="20" :percentage="timeData.month.pass" />
|
||||||
{{ tag === "day" ? "小时" : "天" }}
|
<span class="text">今年已经度过了 {{ timeData.year.elapsed }} 个月</span>
|
||||||
</span>
|
<el-progress :text-inside="true" :stroke-width="20" :percentage="timeData.year.pass" />
|
||||||
<span class="remaining">
|
<div v-if="startDate?.length >= 4 && store.siteStartShow">
|
||||||
剩余 {{ item.remaining }} {{ tag === "day" ? "小时" : "天" }}
|
<span class="text" v-html="startDateText" />
|
||||||
</span>
|
<!-- <el-progress
|
||||||
</div>
|
:show-text="false"
|
||||||
<el-progress :text-inside="true" :stroke-width="20" :percentage="item.percentage" />
|
:indeterminate="true"
|
||||||
</div>
|
:stroke-width="6"
|
||||||
<!-- 建站日期 -->
|
:percentage="80"
|
||||||
<div v-if="store.siteStartShow" class="capsule-item start">
|
:duration="2"
|
||||||
<div class="item-title">{{ startDateText }}</div>
|
/> -->
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -66,33 +65,10 @@ onBeforeUnmount(() => {
|
|||||||
margin-right: 6px;
|
margin-right: 6px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.all-capsule {
|
.text {
|
||||||
.capsule-item {
|
display: block;
|
||||||
margin-bottom: 1rem;
|
|
||||||
.item-title {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
margin: 1rem 0rem 0.5rem 0rem;
|
margin: 1rem 0rem 0.5rem 0rem;
|
||||||
font-size: 0.95rem;
|
font-size: 0.95rem;
|
||||||
.remaining {
|
|
||||||
opacity: 0.6;
|
|
||||||
font-size: 0.85rem;
|
|
||||||
font-style: oblique;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
&:last-child {
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
&.start {
|
|
||||||
.item-title {
|
|
||||||
justify-content: center;
|
|
||||||
opacity: 0.8;
|
|
||||||
font-size: 0.85rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -38,60 +38,55 @@ const weatherData = reactive({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
// 取出天气平均值
|
|
||||||
const getTemperature = (min, max) => {
|
|
||||||
try {
|
|
||||||
// 计算平均值并四舍五入
|
|
||||||
const average = (Number(min) + Number(max)) / 2;
|
|
||||||
return Math.round(average);
|
|
||||||
} catch (error) {
|
|
||||||
console.error("计算温度出现错误:", error);
|
|
||||||
return "NaN";
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 获取天气数据
|
// 获取天气数据
|
||||||
const getWeatherData = async () => {
|
const getWeatherData = () => {
|
||||||
try {
|
|
||||||
// 获取地理位置信息
|
// 获取地理位置信息
|
||||||
if (!mainKey) {
|
if (!mainKey) {
|
||||||
console.log("未配置,使用备用天气接口");
|
getOtherWeather()
|
||||||
const result = await getOtherWeather();
|
.then((res) => {
|
||||||
console.log(result);
|
console.log(res);
|
||||||
const data = result.result;
|
const data = res.result;
|
||||||
weatherData.adCode = {
|
weatherData.adCode = {
|
||||||
city: data.city.City || "未知地区",
|
city: data.city.name,
|
||||||
// adcode: data.city.cityId,
|
adcode: data.city.cityId,
|
||||||
};
|
};
|
||||||
weatherData.weather = {
|
weatherData.weather = {
|
||||||
weather: data.condition.day_weather,
|
weather: data.condition.condition,
|
||||||
temperature: getTemperature(data.condition.min_degree, data.condition.max_degree),
|
temperature: data.condition.temp,
|
||||||
winddirection: data.condition.day_wind_direction,
|
winddirection: data.condition.windDir,
|
||||||
windpower: data.condition.day_wind_power,
|
windpower: data.condition.windLevel,
|
||||||
};
|
};
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.error("天气信息获取失败:" + err);
|
||||||
|
onError("天气信息获取失败");
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
// 获取 Adcode
|
getAdcode(mainKey)
|
||||||
const adCode = await getAdcode(mainKey);
|
.then((res) => {
|
||||||
console.log(adCode);
|
|
||||||
if (adCode.infocode !== "10000") {
|
|
||||||
throw "地区查询失败";
|
|
||||||
}
|
|
||||||
weatherData.adCode = {
|
weatherData.adCode = {
|
||||||
city: adCode.city,
|
city: res.city,
|
||||||
adcode: adCode.adcode,
|
adcode: res.adcode,
|
||||||
};
|
};
|
||||||
// 获取天气信息
|
// 获取天气信息
|
||||||
const result = await getWeather(mainKey, weatherData.adCode.adcode);
|
getWeather(mainKey, weatherData.adCode.adcode)
|
||||||
|
.then((res) => {
|
||||||
weatherData.weather = {
|
weatherData.weather = {
|
||||||
weather: result.lives[0].weather,
|
weather: res.lives[0].weather,
|
||||||
temperature: result.lives[0].temperature,
|
temperature: res.lives[0].temperature,
|
||||||
winddirection: result.lives[0].winddirection,
|
winddirection: res.lives[0].winddirection,
|
||||||
windpower: result.lives[0].windpower,
|
windpower: res.lives[0].windpower,
|
||||||
};
|
};
|
||||||
}
|
})
|
||||||
} catch (error) {
|
.catch((err) => {
|
||||||
console.error("天气信息获取失败:" + error);
|
console.error("天气信息获取失败:" + err);
|
||||||
onError("天气信息获取失败");
|
onError("天气信息获取失败");
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.error("地理位置获取失败:" + err);
|
||||||
|
onError("地理位置获取失败");
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -4,8 +4,6 @@ import App from "@/App.vue";
|
|||||||
// 引入 pinia
|
// 引入 pinia
|
||||||
import { createPinia } from "pinia";
|
import { createPinia } from "pinia";
|
||||||
import piniaPluginPersistedstate from "pinia-plugin-persistedstate";
|
import piniaPluginPersistedstate from "pinia-plugin-persistedstate";
|
||||||
// swiper
|
|
||||||
import "swiper/css";
|
|
||||||
|
|
||||||
const app = createApp(App);
|
const app = createApp(App);
|
||||||
const pinia = createPinia();
|
const pinia = createPinia();
|
||||||
|
@ -22,9 +22,6 @@ export const mainStore = defineStore("main", {
|
|||||||
playerLrc: "歌词加载中", // 当前播放歌词
|
playerLrc: "歌词加载中", // 当前播放歌词
|
||||||
playerLrcShow: true, // 是否显示底栏歌词
|
playerLrcShow: true, // 是否显示底栏歌词
|
||||||
footerBlur: true, // 底栏模糊
|
footerBlur: true, // 底栏模糊
|
||||||
playerAutoplay: false, // 是否自动播放
|
|
||||||
playerLoop: "all", // 循环播放 "all", "one", "none"
|
|
||||||
playerOrder: "list", // 循环顺序 "list", "random"
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
getters: {
|
getters: {
|
||||||
@ -85,9 +82,6 @@ export const mainStore = defineStore("main", {
|
|||||||
"musicClick",
|
"musicClick",
|
||||||
"playerLrcShow",
|
"playerLrcShow",
|
||||||
"footerBlur",
|
"footerBlur",
|
||||||
"playerAutoplay",
|
|
||||||
"playerLoop",
|
|
||||||
"playerOrder",
|
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -13,8 +13,6 @@ html,
|
|||||||
body {
|
body {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
// width: 100dvh;
|
|
||||||
// height: 100dvh;
|
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
background-color: #333;
|
background-color: #333;
|
||||||
@ -55,8 +53,8 @@ p {
|
|||||||
position: fixed;
|
position: fixed;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
width: 100%;
|
width: 100vw;
|
||||||
height: 100%;
|
height: 100vh;
|
||||||
z-index: 0;
|
z-index: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -170,7 +168,7 @@ p {
|
|||||||
}
|
}
|
||||||
to {
|
to {
|
||||||
filter: blur(0) brightness(1);
|
filter: blur(0) brightness(1);
|
||||||
transform: scale(1);
|
transform: scale(1.2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import { h } from "vue";
|
import { h } from "vue";
|
||||||
import { SpaCandle } from "@icon-park/vue-next";
|
import { SpaCandle } from "@icon-park/vue-next";
|
||||||
import dayjs from "dayjs";
|
|
||||||
|
|
||||||
// 时钟
|
// 时钟
|
||||||
export const getCurrentTime = () => {
|
export const getCurrentTime = () => {
|
||||||
@ -26,48 +25,47 @@ export const getCurrentTime = () => {
|
|||||||
|
|
||||||
// 时光胶囊
|
// 时光胶囊
|
||||||
export const getTimeCapsule = () => {
|
export const getTimeCapsule = () => {
|
||||||
const now = dayjs();
|
// 日进度
|
||||||
const dayText = {
|
const todayStartDate = new Date(new Date().toLocaleDateString()).getTime();
|
||||||
day: "今日",
|
const todayPassHours = (new Date() - todayStartDate) / 1000 / 60 / 60;
|
||||||
week: "本周",
|
const todayPassHoursPercent = (todayPassHours / 24) * 100;
|
||||||
month: "本月",
|
|
||||||
year: "本年",
|
// 周进度
|
||||||
};
|
const weeks = [7, 1, 2, 3, 4, 5, 6];
|
||||||
/**
|
const weekDay = weeks[new Date().getDay()];
|
||||||
* 计算时间差的函数
|
const weekDayPassPercent = (weekDay / 7) * 100;
|
||||||
* @param {String} unit 时间单位,可以是 'day', 'week', 'month', 'year'
|
|
||||||
*/
|
// 月进度
|
||||||
const getDifference = (unit) => {
|
const year = new Date().getFullYear();
|
||||||
// 获取当前时间单位的开始时间
|
const date = new Date().getDate();
|
||||||
const start = now.startOf(unit);
|
const month = new Date().getMonth() + 1;
|
||||||
// 获取当前时间单位的结束时间
|
const monthAll = new Date(year, month, 0).getDate();
|
||||||
const end = now.endOf(unit);
|
const monthPassPercent = (date / monthAll) * 100;
|
||||||
// 计算总的天数或小时数
|
|
||||||
const total = end.diff(start, unit === "day" ? "hour" : "day") + 1;
|
// 年进度
|
||||||
// 计算已经过去的天数或小时数
|
const yearStartDate = new Date(year, 0, 1).getTime();
|
||||||
let passed;
|
const yearEndDate = new Date(year + 1, 0, 1).getTime();
|
||||||
if (unit === "week" && now.day() === 0) {
|
const yearPassHours = (new Date() - yearStartDate) / 1000 / 60 / 60;
|
||||||
// 如果是星期日
|
const yearTotalHours = (yearEndDate - yearStartDate) / 1000 / 60 / 60;
|
||||||
passed = total - 1;
|
const yearPassPercent = (yearPassHours / yearTotalHours) * 100;
|
||||||
} else {
|
|
||||||
passed = now.diff(start, unit === "day" ? "hour" : "day");
|
|
||||||
}
|
|
||||||
const remaining = total - passed;
|
|
||||||
const percentage = (passed / total) * 100;
|
|
||||||
// 返回数据
|
|
||||||
return {
|
return {
|
||||||
name: dayText[unit],
|
day: {
|
||||||
total: total,
|
elapsed: Math.floor(todayPassHours),
|
||||||
passed: passed,
|
pass: Math.floor(todayPassHoursPercent),
|
||||||
remaining: remaining,
|
},
|
||||||
percentage: percentage.toFixed(2),
|
week: {
|
||||||
};
|
elapsed: weekDay,
|
||||||
};
|
pass: Math.floor(weekDayPassPercent),
|
||||||
return {
|
},
|
||||||
day: getDifference("day"),
|
month: {
|
||||||
week: getDifference("week"),
|
elapsed: date,
|
||||||
month: getDifference("month"),
|
pass: Math.floor(monthPassPercent),
|
||||||
year: getDifference("year"),
|
},
|
||||||
|
year: {
|
||||||
|
elapsed: month - 1,
|
||||||
|
pass: Math.floor(yearPassPercent),
|
||||||
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -21,9 +21,7 @@
|
|||||||
/>
|
/>
|
||||||
</transition>
|
</transition>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<!-- 可在此处自定义任意内容 -->
|
|
||||||
<TimeCapsule />
|
<TimeCapsule />
|
||||||
<MoreContent />
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -32,7 +30,6 @@
|
|||||||
import { CloseOne, SettingTwo } from "@icon-park/vue-next";
|
import { CloseOne, SettingTwo } from "@icon-park/vue-next";
|
||||||
import { mainStore } from "@/store";
|
import { mainStore } from "@/store";
|
||||||
import TimeCapsule from "@/components/TimeCapsule.vue";
|
import TimeCapsule from "@/components/TimeCapsule.vue";
|
||||||
import MoreContent from "@/components/MoreContent.vue";
|
|
||||||
|
|
||||||
const store = mainStore();
|
const store = mainStore();
|
||||||
const closeShow = ref(false);
|
const closeShow = ref(false);
|
||||||
@ -43,7 +40,6 @@ const closeShow = ref(false);
|
|||||||
flex: 1 0 0%;
|
flex: 1 0 0%;
|
||||||
margin-left: 0.75rem;
|
margin-left: 0.75rem;
|
||||||
height: 80%;
|
height: 80%;
|
||||||
max-width: 50%;
|
|
||||||
position: relative;
|
position: relative;
|
||||||
animation: fade 0.5s;
|
animation: fade 0.5s;
|
||||||
|
|
||||||
@ -76,8 +72,6 @@ const closeShow = ref(false);
|
|||||||
}
|
}
|
||||||
|
|
||||||
.content {
|
.content {
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
padding: 30px;
|
padding: 30px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
@ -136,7 +136,7 @@ const jumpTo = (url) => {
|
|||||||
padding-left: 22px;
|
padding-left: 22px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 260px;
|
height: 260px;
|
||||||
min-height: 140px;
|
|
||||||
.bg {
|
.bg {
|
||||||
font-size: 5rem;
|
font-size: 5rem;
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
/* eslint-disable no-undef */
|
|
||||||
import { defineConfig, loadEnv } from "vite";
|
import { defineConfig, loadEnv } from "vite";
|
||||||
import { ElementPlusResolver } from "unplugin-vue-components/resolvers";
|
import { ElementPlusResolver } from "unplugin-vue-components/resolvers";
|
||||||
import { resolve } from "path";
|
import { resolve } from "path";
|
||||||
|
Loading…
Reference in New Issue
Block a user