🦄 refactor: 重构整个项目 优化打包 修改后台服务为本地运行 添加更新版本检测功能

This commit is contained in:
alger
2025-01-01 02:25:18 +08:00
parent f8d421c9b1
commit 17d20fa299
260 changed files with 78557 additions and 1693 deletions

View File

@@ -1,13 +0,0 @@
snapshot*
dist
lib
es
esm
node_modules
static
cypress
script/test/cypress
_site
temp*
static/
!.prettierrc.js

140
.eslintrc
View File

@@ -1,140 +0,0 @@
{
"extends": [
"plugin:@typescript-eslint/recommended",
"eslint-config-airbnb-base",
"@vue/typescript/recommended",
"plugin:vue/vue3-recommended",
"plugin:vue-scoped-css/base",
"plugin:prettier/recommended"
],
"env": {
"browser": true,
"node": true,
"jest": true,
"es6": true
},
"globals": {
"defineProps": "readonly",
"defineEmits": "readonly"
},
"plugins": [
"vue",
"@typescript-eslint",
"simple-import-sort"
],
"parserOptions": {
"parser": "@typescript-eslint/parser",
"sourceType": "module",
"allowImportExportEverywhere": true,
"ecmaFeatures": {
"jsx": true
}
},
"settings": {
"import/extensions": [
".js",
".jsx",
".ts",
".tsx"
]
},
"rules": {
"no-nested-ternary": "off",
"no-console": "off",
"no-continue": "off",
"no-restricted-syntax": "off",
"no-return-assign": "off",
"no-unused-expressions": "off",
"no-return-await": "off",
"no-plusplus": "off",
"no-param-reassign": "off",
"no-shadow": "off",
"guard-for-in": "off",
"import/extensions": "off",
"import/no-unresolved": "off",
"import/no-extraneous-dependencies": "off",
"import/prefer-default-export": "off",
"import/first": "off", // https://github.com/vuejs/vue-eslint-parser/issues/58
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/explicit-module-boundary-types": "off",
"vue/first-attribute-linebreak": 0,
"@typescript-eslint/no-unused-vars": [
"error",
{
"argsIgnorePattern": "^_",
"varsIgnorePattern": "^_"
}
],
"no-unused-vars": [
"error",
{
"argsIgnorePattern": "^_",
"varsIgnorePattern": "^_"
}
],
"no-use-before-define": "off",
"@typescript-eslint/no-use-before-define": "off",
"@typescript-eslint/ban-ts-comment": "off",
"@typescript-eslint/ban-types": "off",
"class-methods-use-this": "off", // 因为AxiosCancel必须实例化而能静态化所以加的规则如果有办法解决可以取消
"simple-import-sort/imports": "error",
"simple-import-sort/exports": "error"
},
"overrides": [
{
"files": [
"*.vue"
],
"rules": {
"vue/component-name-in-template-casing": [
2,
"kebab-case"
],
"vue/require-default-prop": 0,
"vue/multi-word-component-names": 0,
"vue/no-reserved-props": 0,
"vue/no-v-html": 0,
"vue-scoped-css/enforce-style-type": [
"error",
{
"allows": [
"scoped"
]
}
]
}
},
{
"files": [
"*.ts",
"*.tsx"
], // https://github.com/typescript-eslint eslint-recommended
"rules": {
"constructor-super": "off", // ts(2335) & ts(2377)
"getter-return": "off", // ts(2378)
"no-const-assign": "off", // ts(2588)
"no-dupe-args": "off", // ts(2300)
"no-dupe-class-members": "off", // ts(2393) & ts(2300)
"no-dupe-keys": "off", // ts(1117)
"no-func-assign": "off", // ts(2539)
"no-import-assign": "off", // ts(2539) & ts(2540)
"no-new-symbol": "off", // ts(2588)
"no-obj-calls": "off", // ts(2349)
"no-redeclare": "off", // ts(2451)
"no-setter-return": "off", // ts(2408)
"no-this-before-super": "off", // ts(2376)
"no-undef": "off", // ts(2304)
"no-unreachable": "off", // ts(7027)
"no-unsafe-negation": "off", // ts(2365) & ts(2360) & ts(2358)
"no-var": "error", // ts transpiles let/const to var, so no need for vars any more
"prefer-const": "error", // ts provides better types with const
"prefer-rest-params": "error", // ts provides better types with rest args over arguments
"prefer-spread": "error", // ts transpiles spread to apply, so no need for manual apply
"valid-typeof": "off", // ts(2367)
"consistent-return": "off",
"no-promise-executor-return": "off",
"prefer-promise-reject-errors": "off"
}
}
]
}

2
.npmrc
View File

@@ -1,2 +0,0 @@
electron_mirror=https://npmmirror.com/mirrors/electron/
electron_builder_binaries_mirror=https://npmmirror.com/mirrors/electron-builder-binaries/

View File

@@ -1,39 +0,0 @@
module.exports = {
// 一行最多 120 字符..
printWidth: 120,
// 使用 2 个空格缩进
tabWidth: 2,
// 不使用缩进符,而使用空格
useTabs: false,
// 行尾需要有分号
semi: true,
// 使用单引号
singleQuote: true,
// 对象的 key 仅在必要时用引号
quoteProps: 'as-needed',
// jsx 不使用单引号,而使用双引号
jsxSingleQuote: false,
// 末尾需要有逗号
trailingComma: 'all',
// 大括号内的首尾需要空格
bracketSpacing: true,
// jsx 标签的反尖括号需要换行
jsxBracketSameLine: false,
// 箭头函数,只有一个参数的时候,也需要括号
arrowParens: 'always',
// 每个文件格式化的范围是文件的全部内容
rangeStart: 0,
rangeEnd: Infinity,
// 不需要写文件开头的 @prettier
requirePragma: false,
// 不需要自动在文件开头插入 @prettier
insertPragma: false,
// 使用默认的折行标准
proseWrap: 'preserve',
// 根据显示样式决定 html 要不要折行
htmlWhitespaceSensitivity: 'css',
// vue 文件中的 script 和 style 内不用缩进
vueIndentScriptAndStyle: false,
// 换行符使用 lf
endOfLine: 'lf',
};

201
LICENSE
View File

@@ -1,201 +0,0 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

108
README.md
View File

@@ -1,102 +1,34 @@
# Alger Music Player
主要功能如下
# electron-lan-file
- 音乐推荐
- 音乐播放
- 网易云登录
- 播放历史
- 桌面歌词
- 歌单 mv 搜索 专辑等功能
- 识别无法播放歌曲 并代理播放
- 可听周杰伦(搜索专辑)
An Electron application with Vue and TypeScript
## 项目简介
一个基于 electron typescript vue3 的桌面音乐播放器 适配 web端 桌面端 web移动端
## Recommended IDE Setup
## 预览地址
[http://mc.alger.fun/](http://mc.alger.fun/)
- [VSCode](https://code.visualstudio.com/) + [ESLint](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint) + [Prettier](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin)
QQ群:789288579
## Project Setup
## 软件截图
![首页](./docs/img/image-7.png)
![歌词](./docs/img/image-6.png)
![搜索](./docs/img/image-8.png)
## 技术栈
### 主要框架
- Vue 3 - 渐进式 JavaScript 框架
- TypeScript - JavaScript 的超集,添加了类型系统
- Electron - 跨平台桌面应用开发框架
- Vite - 下一代前端构建工具
### UI 框架
- Naive UI - 基于 Vue 3 的组件库
### 项目特点
- 完整的类型支持TypeScript
- 模块化设计
- 自动化组件和 API 导入
- 多平台支持Web、Desktop、Mobile Web
- 构建优化(代码分割、压缩)
## 咖啡☕️
| 微信 | 支付宝 |
| :--------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------: |
| <img src="https://github.com/algerkong/algerkong/blob/main/wechat.jpg?raw=true" alt="WeChat QRcode" width=200> | <img src="https://github.com/algerkong/algerkong/blob/main/alipay.jpg?raw=true" alt="Wechat QRcode" width=200> |
## 项目运行
```bash
# 安装依赖
npm install
# 运行项目 web
npm run dev
# 运行项目 electron
npm run start
# 打包项目 web
npm run build
# 打包项目 electron
npm run win ...
# 具体看 package.json
```
#### 注意
- 本地运行需要配置 .env.development 文件
- 打包需要配置 .env.production 文件
### Install
```bash
# .env.development
VITE_API_LOCAL = /api
VITE_API_MUSIC_PROXY = /music
VITE_API_PROXY_MUSIC = /music_proxy
# 你的接口地址 (必填)
VITE_API = ***
# 音乐po接口地址
VITE_API_MUSIC = ***
VITE_API_PROXY = ***
# .env.production
# 你的接口地址 (必填)
VITE_API = ***
# 音乐po接口地址
VITE_API_MUSIC = ***
# 代理地址
VITE_API_PROXY = ***
$ npm install
```
## Stargazers over time
[![Stargazers over time](https://starchart.cc/algerkong/AlgerMusicPlayer.svg?variant=adaptive)](https://starchart.cc/algerkong/AlgerMusicPlayer)
### Development
```bash
$ npm run dev
```
### Build
```bash
# For windows
$ npm run build:win
## 欢迎提Issues
# For macOS
$ npm run build:mac
## 免责声明
本软件仅用于学习交流,禁止用于商业用途,否则后果自负。
# For Linux
$ npm run build:linux
```

148
app.js
View File

@@ -1,148 +0,0 @@
const { app, BrowserWindow, ipcMain, Tray, Menu, globalShortcut, nativeImage } = require('electron');
const path = require('path');
const Store = require('electron-store');
const setJson = require('./electron/set.json');
const { loadLyricWindow } = require('./electron/lyric');
const config = require('./electron/config');
let mainWin = null;
function createWindow() {
mainWin = new BrowserWindow({
width: 1200,
height: 780,
frame: false,
webPreferences: {
nodeIntegration: false,
contextIsolation: true,
preload: path.join(__dirname, '/electron/preload.js'),
},
});
const win = mainWin;
win.setMinimumSize(1200, 780);
if (process.env.NODE_ENV === 'development') {
win.webContents.openDevTools({ mode: 'detach' });
win.loadURL(`http://localhost:${config.development.mainPort}/`);
} else {
win.loadURL(`file://${__dirname}/dist/index.html`);
}
const image = nativeImage
.createFromPath(path.join(__dirname, 'public/icon_16x16.png'))
.resize({ width: 16, height: 16 });
const tray = new Tray(image);
// 创建一个上下文菜单
const contextMenu = Menu.buildFromTemplate([
{
label: '显示',
click: () => {
win.show();
},
},
{
label: '退出',
click: () => {
win.destroy();
app.quit();
},
},
]);
// 设置系统托盘图标的上下文菜单
tray.setContextMenu(contextMenu);
// 当系统托盘图标被点击时,切换窗口的显示/隐藏
tray.on('click', () => {
if (win.isVisible()) {
win.hide();
} else {
win.show();
}
});
const set = store.get('set');
// store.set('set', setJson)
if (!set) {
store.set('set', setJson);
}
loadLyricWindow(ipcMain, mainWin);
}
// 限制只能启动一个应用
const gotTheLock = app.requestSingleInstanceLock();
if (!gotTheLock) {
app.quit();
}
app.whenReady().then(createWindow);
app.on('ready', () => {
globalShortcut.register('CommandOrControl+Alt+Shift+M', () => {
if (mainWin.isVisible()) {
mainWin.hide();
} else {
mainWin.show();
}
});
});
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit();
}
});
app.on('will-quit', () => {
globalShortcut.unregisterAll();
});
ipcMain.on('minimize-window', (event) => {
const win = BrowserWindow.fromWebContents(event.sender);
win.minimize();
});
ipcMain.on('maximize-window', (event) => {
const win = BrowserWindow.fromWebContents(event.sender);
if (win.isMaximized()) {
win.unmaximize();
} else {
win.maximize();
}
});
ipcMain.on('close-window', (event) => {
const win = BrowserWindow.fromWebContents(event.sender);
win.destroy();
app.quit();
});
ipcMain.on('drag-start', (event) => {
const win = BrowserWindow.fromWebContents(event.sender);
win.webContents.beginFrameSubscription((frameBuffer) => {
event.reply('frame-buffer', frameBuffer);
});
});
ipcMain.on('mini-tray', (event) => {
const win = BrowserWindow.fromWebContents(event.sender);
win.hide();
});
// 重启
ipcMain.on('restart', () => {
app.relaunch();
app.exit(0);
});
const store = new Store();
// 定义ipcRenderer监听事件
ipcMain.on('setStore', (_, key, value) => {
store.set(key, value);
});
ipcMain.on('getStore', (_, key) => {
const value = store.get(key);
_.returnValue = value || '';
});

139
auto-imports.d.ts vendored
View File

@@ -6,70 +6,85 @@
// biome-ignore lint: disable
export {}
declare global {
const EffectScope: typeof import('vue')['EffectScope']
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 onWatcherCleanup: typeof import('vue')['onWatcherCleanup']
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 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 toValue: typeof import('vue')['toValue']
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 useDialog: typeof import('naive-ui')['useDialog']
const useId: typeof import('vue')['useId']
const useLoadingBar: typeof import('naive-ui')['useLoadingBar']
const useMessage: typeof import('naive-ui')['useMessage']
const useModel: typeof import('vue')['useModel']
const useNotification: typeof import('naive-ui')['useNotification']
const useSlots: typeof import('vue')['useSlots']
const useTemplateRef: typeof import('vue')['useTemplateRef']
const watch: typeof import('vue')['watch']
const watchEffect: typeof import('vue')['watchEffect']
const watchPostEffect: typeof import('vue')['watchPostEffect']
const watchSyncEffect: typeof import('vue')['watchSyncEffect']
const EffectScope: (typeof import('vue'))['EffectScope'];
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 onWatcherCleanup: (typeof import('vue'))['onWatcherCleanup'];
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 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 toValue: (typeof import('vue'))['toValue'];
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 useDialog: (typeof import('naive-ui'))['useDialog'];
const useId: (typeof import('vue'))['useId'];
const useLoadingBar: (typeof import('naive-ui'))['useLoadingBar'];
const useMessage: (typeof import('naive-ui'))['useMessage'];
const useModel: (typeof import('vue'))['useModel'];
const useNotification: (typeof import('naive-ui'))['useNotification'];
const useSlots: (typeof import('vue'))['useSlots'];
const useTemplateRef: (typeof import('vue'))['useTemplateRef'];
const watch: (typeof import('vue'))['watch'];
const watchEffect: (typeof import('vue'))['watchEffect'];
const watchPostEffect: (typeof import('vue'))['watchPostEffect'];
const watchSyncEffect: (typeof import('vue'))['watchSyncEffect'];
}
// for type re-export
declare global {
// @ts-ignore
export type { Component, ComponentPublicInstance, ComputedRef, DirectiveBinding, ExtractDefaultPropTypes, ExtractPropTypes, ExtractPublicPropTypes, InjectionKey, PropType, Ref, MaybeRef, MaybeRefOrGetter, VNode, WritableComputedRef } from 'vue'
import('vue')
export type {
Component,
ComponentPublicInstance,
ComputedRef,
DirectiveBinding,
ExtractDefaultPropTypes,
ExtractPropTypes,
ExtractPublicPropTypes,
InjectionKey,
PropType,
Ref,
MaybeRef,
MaybeRefOrGetter,
VNode,
WritableComputedRef
} from 'vue';
import('vue');
}

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.cs.allow-jit</key>
<true/>
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
<true/>
<key>com.apple.security.cs.allow-dyld-environment-variables</key>
<true/>
</dict>
</plist>

BIN
build/icon.icns Normal file

Binary file not shown.

BIN
build/icon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 121 KiB

BIN
build/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

View File

@@ -1,49 +0,0 @@
{
"appId": "com.alger.music",
"productName": "AlgerMusic",
"artifactName": "${productName}_${version}_${arch}.${ext}",
"directories": {
"output": "dist_electron/mac"
},
"files": [
"dist/**/*",
"package.json",
"app.js",
"electron/**/*",
"**/*",
"public/**/*",
"node_modules/**/*"
],
"mac": {
"icon": "public/icon.icns",
"target": [
{
"target": "dmg",
"arch": ["x64", "arm64"]
}
],
"category": "public.app-category.music",
"darkModeSupport": true
},
"dmg": {
"title": "${productName} ${version}",
"icon": "public/icon.icns",
"contents": [
{
"x": 410,
"y": 150,
"type": "link",
"path": "/Applications"
},
{
"x": 130,
"y": 150,
"type": "file"
}
],
"window": {
"width": 540,
"height": 380
}
}
}

View File

@@ -1,31 +0,0 @@
{
"appId": "com.alger.music",
"productName": "AlgerMusic",
"artifactName": "${productName}_${version}_Setup_x86.${ext}",
"directories": {
"output": "dist_electron/win-x86"
},
"files": ["dist/**/*", "package.json", "app.js", "electron/**/*"],
"win": {
"icon": "public/icon.png",
"target": [
{
"target": "nsis",
"arch": ["ia32"]
}
],
"extraFiles": [
{
"from": "installer/installer.nsh",
"to": "$INSTDIR"
}
]
},
"nsis": {
"oneClick": false,
"language": "2052",
"allowToChangeInstallationDirectory": true,
"differentialPackage": true,
"shortcutName": "Alger Music"
}
}

View File

@@ -1,31 +0,0 @@
{
"appId": "com.alger.music",
"productName": "AlgerMusic",
"artifactName": "${productName}_${version}_Setup_x64.${ext}",
"directories": {
"output": "dist_electron/win-x64"
},
"files": ["dist/**/*", "package.json", "app.js", "electron/**/*"],
"win": {
"icon": "public/icon.png",
"target": [
{
"target": "nsis",
"arch": ["x64"]
}
],
"extraFiles": [
{
"from": "installer/installer.nsh",
"to": "$INSTDIR"
}
]
},
"nsis": {
"oneClick": false,
"language": "2052",
"allowToChangeInstallationDirectory": true,
"differentialPackage": true,
"shortcutName": "Alger Music"
}
}

View File

@@ -1,31 +0,0 @@
{
"appId": "com.alger.music",
"productName": "AlgerMusic",
"artifactName": "${productName}_${version}_Setup_arm64.${ext}",
"directories": {
"output": "dist_electron/win-arm64"
},
"files": ["dist/**/*", "package.json", "app.js", "electron/**/*", "!node_modules/**/*"],
"win": {
"icon": "public/icon.png",
"target": [
{
"target": "nsis",
"arch": ["arm64"]
}
],
"extraFiles": [
{
"from": "installer/installer.nsh",
"to": "$INSTDIR"
}
]
},
"nsis": {
"oneClick": false,
"language": "2052",
"allowToChangeInstallationDirectory": true,
"differentialPackage": true,
"shortcutName": "Alger Music"
}
}

19
components.d.ts vendored
View File

@@ -2,19 +2,13 @@
// @ts-nocheck
// Generated by unplugin-vue-components
// Read more: https://github.com/vuejs/core/pull/3399
export {}
export {};
/* prettier-ignore */
declare module 'vue' {
export interface GlobalComponents {
Coffee: typeof import('./src/components/Coffee.vue')['default']
InstallAppModal: typeof import('./src/components/common/InstallAppModal.vue')['default']
MPop: typeof import('./src/components/common/MPop.vue')['default']
MusicList: typeof import('./src/components/MusicList.vue')['default']
MvPlayer: typeof import('./src/components/MvPlayer.vue')['default']
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']
@@ -24,6 +18,7 @@ declare module 'vue' {
NEmpty: typeof import('naive-ui')['NEmpty']
NImage: typeof import('naive-ui')['NImage']
NInput: typeof import('naive-ui')['NInput']
NInputNumber: typeof import('naive-ui')['NInputNumber']
NLayout: typeof import('naive-ui')['NLayout']
NMessageProvider: typeof import('naive-ui')['NMessageProvider']
NModal: typeof import('naive-ui')['NModal']
@@ -32,17 +27,7 @@ declare module 'vue' {
NSlider: typeof import('naive-ui')['NSlider']
NSpin: typeof import('naive-ui')['NSpin']
NSwitch: typeof import('naive-ui')['NSwitch']
NTooltip: typeof import('naive-ui')['NTooltip']
NVirtualList: typeof import('naive-ui')['NVirtualList']
PlayBottom: typeof import('./src/components/common/PlayBottom.vue')['default']
PlayListsItem: typeof import('./src/components/common/PlayListsItem.vue')['default']
PlaylistType: typeof import('./src/components/PlaylistType.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']
RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView']
SearchItem: typeof import('./src/components/common/SearchItem.vue')['default']
SongItem: typeof import('./src/components/common/SongItem.vue')['default']
}
}

3
dev-app-update.yml Normal file
View File

@@ -0,0 +1,3 @@
provider: generic
url: https://example.com/auto-updates
updaterCacheDirName: electron-lan-file-updater

Binary file not shown.

Before

Width:  |  Height:  |  Size: 902 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 283 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 237 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 478 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 502 KiB

45
electron-builder.yml Normal file
View File

@@ -0,0 +1,45 @@
appId: com.electron.app
productName: electron-lan-file
directories:
buildResources: build
files:
- '!**/.vscode/*'
- '!src/*'
- '!electron.vite.config.{js,ts,mjs,cjs}'
- '!{.eslintignore,.eslintrc.cjs,.prettierignore,.prettierrc.yaml,dev-app-update.yml,CHANGELOG.md,README.md}'
- '!{.env,.env.*,.npmrc,pnpm-lock.yaml}'
- '!{tsconfig.json,tsconfig.node.json,tsconfig.web.json}'
asarUnpack:
- resources/**
win:
executableName: electron-lan-file
nsis:
artifactName: ${name}-${version}-setup.${ext}
shortcutName: ${productName}
uninstallDisplayName: ${productName}
createDesktopShortcut: always
mac:
entitlementsInherit: build/entitlements.mac.plist
extendInfo:
- NSCameraUsageDescription: Application requests access to the device's camera.
- NSMicrophoneUsageDescription: Application requests access to the device's microphone.
- NSDocumentsFolderUsageDescription: Application requests access to the user's Documents folder.
- NSDownloadsFolderUsageDescription: Application requests access to the user's Downloads folder.
notarize: false
dmg:
artifactName: ${name}-${version}.${ext}
linux:
target:
- AppImage
- snap
- deb
maintainer: electronjs.org
category: Utility
appImage:
artifactName: ${name}-${version}.${ext}
npmRebuild: false
publish:
provider: generic
url: https://example.com/auto-updates
electronDownload:
mirror: https://npmmirror.com/mirrors/electron/

60
electron.vite.config.ts Normal file
View File

@@ -0,0 +1,60 @@
import vue from '@vitejs/plugin-vue';
import { defineConfig, externalizeDepsPlugin } from 'electron-vite';
import { resolve } from 'path';
import AutoImport from 'unplugin-auto-import/vite';
import { NaiveUiResolver } from 'unplugin-vue-components/resolvers';
import Components from 'unplugin-vue-components/vite';
import viteCompression from 'vite-plugin-compression';
export default defineConfig({
main: {
plugins: [externalizeDepsPlugin()]
},
preload: {
plugins: [externalizeDepsPlugin()]
},
renderer: {
resolve: {
alias: {
'@': resolve('src/renderer'),
'@renderer': resolve('src/renderer')
}
},
plugins: [
vue(),
viteCompression(),
// VueDevTools(),
AutoImport({
imports: [
'vue',
{
'naive-ui': ['useDialog', 'useMessage', 'useNotification', 'useLoadingBar']
}
]
}),
Components({
resolvers: [NaiveUiResolver()]
})
],
server: {
proxy: {
// with options
[process.env.VITE_API_LOCAL as string]: {
target: process.env.VITE_API,
changeOrigin: true,
rewrite: (path) => path.replace(new RegExp(`^${process.env.VITE_API_LOCAL}`), '')
},
[process.env.VITE_API_MUSIC_PROXY as string]: {
target: process.env.VITE_API_MUSIC,
changeOrigin: true,
rewrite: (path) => path.replace(new RegExp(`^${process.env.VITE_API_MUSIC_PROXY}`), '')
},
[process.env.VITE_API_PROXY_MUSIC as string]: {
target: process.env.VITE_API_PROXY,
changeOrigin: true,
rewrite: (path) => path.replace(new RegExp(`^${process.env.VITE_API_PROXY_MUSIC}`), '')
}
}
}
}
});

View File

@@ -1,11 +0,0 @@
module.exports = {
// 开发环境配置
development: {
mainPort: 4488,
lyricPort: 4488,
},
// 生产环境配置
production: {
distPath: '../dist',
},
};

View File

@@ -1,30 +0,0 @@
const { contextBridge, ipcRenderer } = require('electron');
// 主进程通信
contextBridge.exposeInMainWorld('electronAPI', {
minimize: () => ipcRenderer.send('minimize-window'),
maximize: () => ipcRenderer.send('maximize-window'),
close: () => ipcRenderer.send('close-window'),
dragStart: (data) => ipcRenderer.send('drag-start', data),
miniTray: () => ipcRenderer.send('mini-tray'),
restart: () => ipcRenderer.send('restart'),
openLyric: () => ipcRenderer.send('open-lyric'),
sendLyric: (data) => ipcRenderer.send('send-lyric', data),
});
// 存储相关
contextBridge.exposeInMainWorld('electron', {
ipcRenderer: {
setStoreValue: (key, value) => ipcRenderer.send('setStore', key, value),
getStoreValue: (key) => ipcRenderer.sendSync('getStore', key),
on: (channel, func) => {
ipcRenderer.on(channel, (event, ...args) => func(...args));
},
once: (channel, func) => {
ipcRenderer.once(channel, (event, ...args) => func(...args));
},
send: (channel, data) => {
ipcRenderer.send(channel, data);
},
},
});

View File

@@ -1,69 +0,0 @@
const { app, BrowserWindow } = require('electron');
const axios = require('axios');
const fs = require('fs');
const path = require('path');
const AdmZip = require('adm-zip');
class Updater {
constructor(mainWindow) {
this.mainWindow = mainWindow;
this.updateUrl = 'http://your-server.com/update'; // 更新服务器地址
this.version = app.getVersion();
}
// 检查更新
async checkForUpdates() {
try {
const response = await axios.get(`${this.updateUrl}/check`, {
params: {
version: this.version,
},
});
if (response.data.hasUpdate) {
await this.downloadUpdate(response.data.downloadUrl);
}
} catch (error) {
console.error('检查更新失败:', error);
}
}
// 下载更新
async downloadUpdate(downloadUrl) {
try {
const response = await axios({
url: downloadUrl,
method: 'GET',
responseType: 'arraybuffer',
});
const tempPath = path.join(app.getPath('temp'), 'update.zip');
fs.writeFileSync(tempPath, response.data);
await this.extractUpdate(tempPath);
} catch (error) {
console.error('下载更新失败:', error);
}
}
// 解压更新
async extractUpdate(zipPath) {
try {
const zip = new AdmZip(zipPath);
const targetPath = path.join(__dirname, '../dist'); // 前端文件目录
// 解压文件
zip.extractAllTo(targetPath, true);
// 删除临时文件
fs.unlinkSync(zipPath);
// 刷新页面
this.mainWindow.webContents.reload();
} catch (error) {
console.error('解压更新失败:', error);
}
}
}
module.exports = Updater;

View File

@@ -1,57 +0,0 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<!-- SEO 元数据 -->
<title>网抑云音乐 | AlgerKong AlgerMusicPlayer</title>
<meta name="description"
content="AlgerMusicPlayer 网抑云音乐 基于 网易云音乐API 的一款免费的在线音乐播放器,支持在线播放、歌词显示、音乐下载等功能。提供海量音乐资源,让您随时随地享受音乐。" />
<meta name="keywords" content="AlgerMusic, AlgerMusicPlayer, 网抑云, 音乐播放器, 在线音乐, 免费音乐, 歌词显示, 音乐下载, AlgerKong, 网易云音乐" />
<!-- 作者信息 -->
<meta name="author" content="AlgerKong" />
<meta name="author-url" content="https://github.com/algerkong" />
<!-- PWA 相关 -->
<link rel="manifest" href="/manifest.json" />
<meta name="theme-color" content="#000000" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
<meta name="apple-mobile-web-app-title" content="网抑云音乐" />
<link rel="apple-touch-icon" href="/apple-touch-icon.png" />
<!-- 资源预加载 -->
<link rel="preload" href="/icon/iconfont.css" as="style" />
<link rel="preload" href="/css/animate.css" as="style" />
<link rel="preload" href="/css/base.css" as="style" />
<!-- 样式表 -->
<link rel="stylesheet" href="/icon/iconfont.css" />
<link rel="stylesheet" href="/css/animate.css" />
<link rel="stylesheet" href="/css/base.css" />
<script defer src="https://cn.vercount.one/js"></script>
<!-- 动画配置 -->
<style>
:root {
--animate-delay: 0.5s;
}
</style>
</head>
<body>
<div id="app"></div>
<div style="display: none;">
Total Page View <span id="vercount_value_page_pv">Loading</span>
Total Visits <span id="vercount_value_site_pv">Loading</span>
Site Total Visitors <span id="vercount_value_site_uv">Loading</span>
</div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>

323
out/main/index.js Normal file
View File

@@ -0,0 +1,323 @@
"use strict";
const utils = require("@electron-toolkit/utils");
const electron = require("electron");
const Store = require("electron-store");
const path = require("path");
const fs = require("fs");
const os = require("os");
const match = require("@unblockneteasemusic/server");
const server = require("netease-cloud-music-api-alger/server");
const isProxy = false;
const noAnimate = false;
const animationSpeed = 1;
const author = "Alger";
const authorUrl = "https://github.com/algerkong";
const musicApiPort = 30488;
const set = {
isProxy,
noAnimate,
animationSpeed,
author,
authorUrl,
musicApiPort
};
const store$2 = new Store();
let lyricWindow = null;
const createWin = () => {
console.log("Creating lyric window");
const windowBounds = store$2.get("lyricWindowBounds") || {};
const { x, y, width, height } = windowBounds;
const { width: screenWidth, height: screenHeight } = electron.screen.getPrimaryDisplay().workAreaSize;
const validPosition = x !== void 0 && y !== void 0 && x >= 0 && y >= 0 && x < screenWidth && y < screenHeight;
lyricWindow = new electron.BrowserWindow({
width: width || 800,
height: height || 200,
x: validPosition ? x : void 0,
y: validPosition ? y : void 0,
frame: false,
show: false,
transparent: true,
hasShadow: false,
alwaysOnTop: true,
webPreferences: {
preload: path.join(__dirname, "../preload/index.js"),
sandbox: false,
contextIsolation: true
}
});
lyricWindow.on("closed", () => {
if (lyricWindow) {
lyricWindow.destroy();
lyricWindow = null;
}
});
return lyricWindow;
};
const loadLyricWindow = (ipcMain, mainWin) => {
const showLyricWindow = () => {
if (lyricWindow && !lyricWindow.isDestroyed()) {
if (lyricWindow.isMinimized()) {
lyricWindow.restore();
}
lyricWindow.focus();
lyricWindow.show();
return true;
}
return false;
};
ipcMain.on("open-lyric", () => {
console.log("Received open-lyric request");
if (showLyricWindow()) {
return;
}
console.log("Creating new lyric window");
const win = createWin();
if (!win) {
console.error("Failed to create lyric window");
return;
}
if (process.env.NODE_ENV === "development") {
win.webContents.openDevTools({ mode: "detach" });
win.loadURL(`${process.env.ELECTRON_RENDERER_URL}/#/lyric`);
} else {
const distPath = path.resolve(__dirname, "../renderer");
win.loadURL(`file://${distPath}/index.html#/lyric`);
}
win.setMinimumSize(600, 200);
win.setSkipTaskbar(true);
win.once("ready-to-show", () => {
console.log("Lyric window ready to show");
win.show();
});
});
ipcMain.on("send-lyric", (_, data) => {
if (lyricWindow && !lyricWindow.isDestroyed()) {
try {
lyricWindow.webContents.send("receive-lyric", data);
} catch (error) {
console.error("Error processing lyric data:", error);
}
}
});
ipcMain.on("top-lyric", (_, data) => {
if (lyricWindow && !lyricWindow.isDestroyed()) {
lyricWindow.setAlwaysOnTop(data);
}
});
ipcMain.on("close-lyric", () => {
if (lyricWindow && !lyricWindow.isDestroyed()) {
lyricWindow.webContents.send("lyric-window-close");
mainWin.webContents.send("lyric-control-back", "close");
lyricWindow.destroy();
lyricWindow = null;
}
});
ipcMain.on("mouseenter-lyric", () => {
if (lyricWindow && !lyricWindow.isDestroyed()) {
lyricWindow.setIgnoreMouseEvents(true);
}
});
ipcMain.on("mouseleave-lyric", () => {
if (lyricWindow && !lyricWindow.isDestroyed()) {
lyricWindow.setIgnoreMouseEvents(false);
}
});
ipcMain.on("lyric-drag-move", (_, { deltaX, deltaY }) => {
if (!lyricWindow || lyricWindow.isDestroyed()) return;
const [currentX, currentY] = lyricWindow.getPosition();
const { width: screenWidth, height: screenHeight } = electron.screen.getPrimaryDisplay().workAreaSize;
const [windowWidth, windowHeight] = lyricWindow.getSize();
const newX = Math.max(0, Math.min(currentX + deltaX, screenWidth - windowWidth));
const newY = Math.max(0, Math.min(currentY + deltaY, screenHeight - windowHeight));
lyricWindow.setPosition(newX, newY);
store$2.set("lyricWindowBounds", {
...lyricWindow.getBounds(),
x: newX,
y: newY
});
});
ipcMain.on("set-ignore-mouse", (_, shouldIgnore) => {
if (!lyricWindow || lyricWindow.isDestroyed()) return;
lyricWindow.setIgnoreMouseEvents(shouldIgnore, { forward: true });
});
ipcMain.on("control-back", (_, command) => {
console.log("command", command);
if (mainWin && !mainWin.isDestroyed()) {
console.log("Sending control-back command:", command);
mainWin.webContents.send("lyric-control-back", command);
}
});
};
const unblockMusic = async (id) => {
return new Promise((resolve, reject) => {
match(parseInt(id, 10), ["qq", "migu", "kugou", "joox"]).then((data) => {
resolve({
data: {
data,
params: {
id,
type: "song"
}
}
});
}).catch((err) => {
reject(err);
});
});
};
const store$1 = new Store();
if (!fs.existsSync(path.resolve(os.tmpdir(), "anonymous_token"))) {
fs.writeFileSync(path.resolve(os.tmpdir(), "anonymous_token"), "", "utf-8");
}
electron.ipcMain.handle("unblock-music", async (_, id) => {
return unblockMusic(id);
});
async function startMusicApi() {
console.log("MUSIC API STARTED");
const port = store$1.get("set").musicApiPort || 30488;
await server.serveNcmApi({
port
});
}
const iconPath = path.join(__dirname, "../../resources");
const icon = electron.nativeImage.createFromPath(
process.platform === "darwin" ? path.join(iconPath, "icon.icns") : process.platform === "win32" ? path.join(iconPath, "favicon.ico") : path.join(iconPath, "icon.png")
);
let mainWindow;
function createWindow() {
startMusicApi();
mainWindow = new electron.BrowserWindow({
width: 1200,
height: 780,
show: false,
frame: false,
autoHideMenuBar: true,
icon,
webPreferences: {
preload: path.join(__dirname, "../preload/index.js"),
sandbox: false,
contextIsolation: true
}
});
mainWindow.setMinimumSize(1200, 780);
mainWindow.on("ready-to-show", () => {
mainWindow.show();
});
mainWindow.webContents.setWindowOpenHandler((details) => {
electron.shell.openExternal(details.url);
return { action: "deny" };
});
if (utils.is.dev && process.env.ELECTRON_RENDERER_URL) {
mainWindow.webContents.openDevTools({ mode: "detach" });
mainWindow.loadURL(process.env.ELECTRON_RENDERER_URL);
} else {
mainWindow.webContents.openDevTools({ mode: "detach" });
mainWindow.loadFile(path.join(__dirname, "../renderer/index.html"));
}
const trayIcon = electron.nativeImage.createFromPath(path.join(iconPath, "icon_16x16.png")).resize({ width: 16, height: 16 });
const tray = new electron.Tray(trayIcon);
const contextMenu = electron.Menu.buildFromTemplate([
{
label: "显示",
click: () => {
mainWindow.show();
}
},
{
label: "退出",
click: () => {
mainWindow.destroy();
electron.app.quit();
}
}
]);
tray.setContextMenu(contextMenu);
tray.on("click", () => {
if (mainWindow.isVisible()) {
mainWindow.hide();
} else {
mainWindow.show();
}
});
loadLyricWindow(electron.ipcMain, mainWindow);
}
electron.app.whenReady().then(() => {
utils.electronApp.setAppUserModelId("com.alger.music");
electron.app.on("browser-window-created", (_, window) => {
utils.optimizer.watchWindowShortcuts(window);
});
electron.ipcMain.on("ping", () => console.log("pong"));
createWindow();
electron.app.on("activate", function() {
if (electron.BrowserWindow.getAllWindows().length === 0) createWindow();
});
});
electron.app.on("ready", () => {
electron.globalShortcut.register("CommandOrControl+Alt+Shift+M", () => {
if (mainWindow.isVisible()) {
mainWindow.hide();
} else {
mainWindow.show();
}
});
});
electron.app.on("window-all-closed", () => {
if (process.platform !== "darwin") {
electron.app.quit();
}
});
electron.ipcMain.on("minimize-window", (event) => {
const win = electron.BrowserWindow.fromWebContents(event.sender);
if (win) {
win.minimize();
}
});
electron.ipcMain.on("maximize-window", (event) => {
const win = electron.BrowserWindow.fromWebContents(event.sender);
if (win) {
if (win.isMaximized()) {
win.unmaximize();
} else {
win.maximize();
}
}
});
electron.ipcMain.on("close-window", (event) => {
const win = electron.BrowserWindow.fromWebContents(event.sender);
if (win) {
win.destroy();
electron.app.quit();
}
});
electron.ipcMain.on("drag-start", (event) => {
const win = electron.BrowserWindow.fromWebContents(event.sender);
if (win) {
win.webContents.beginFrameSubscription((frameBuffer) => {
event.reply("frame-buffer", frameBuffer);
});
}
});
electron.ipcMain.on("mini-tray", (event) => {
const win = electron.BrowserWindow.fromWebContents(event.sender);
if (win) {
win.hide();
}
});
electron.ipcMain.on("restart", () => {
electron.app.relaunch();
electron.app.exit(0);
});
const store = new Store({
name: "config",
// 配置文件名
defaults: {
set
}
});
electron.ipcMain.on("set-store-value", (_, key, value) => {
store.set(key, value);
});
electron.ipcMain.on("get-store-value", (_, key) => {
const value = store.get(key);
_.returnValue = value || "";
});

25
out/preload/index.js Normal file
View File

@@ -0,0 +1,25 @@
"use strict";
const preload = require("@electron-toolkit/preload");
const electron = require("electron");
const api = {
minimize: () => electron.ipcRenderer.send("minimize-window"),
maximize: () => electron.ipcRenderer.send("maximize-window"),
close: () => electron.ipcRenderer.send("close-window"),
dragStart: (data) => electron.ipcRenderer.send("drag-start", data),
miniTray: () => electron.ipcRenderer.send("mini-tray"),
restart: () => electron.ipcRenderer.send("restart"),
openLyric: () => electron.ipcRenderer.send("open-lyric"),
sendLyric: (data) => electron.ipcRenderer.send("send-lyric", data),
unblockMusic: (id) => electron.ipcRenderer.invoke("unblock-music", id)
};
if (process.contextIsolated) {
try {
electron.contextBridge.exposeInMainWorld("electron", preload.electronAPI);
electron.contextBridge.exposeInMainWorld("api", api);
} catch (error) {
console.error(error);
}
} else {
window.electron = preload.electronAPI;
window.api = api;
}

View File

@@ -0,0 +1,98 @@
import { d as defineComponent, af as useRoute, r as ref, E as watch, ar as resolveComponent, j as openBlock, c as createElementBlock, b as createBaseVNode, u as unref, a3 as Fragment, a4 as renderList, e as createVNode, f as withCtx, n as normalizeClass, a2 as normalizeStyle, t as toDisplayString, T as createCommentVNode, _ as _export_sfc } from "./index-DKaFsuse.js";
const icon = "" + new URL("icon-mGmYaNg4.png", import.meta.url).href;
const _hoisted_1 = { class: "app-menu-header" };
const _hoisted_2 = ["src"];
const _hoisted_3 = { class: "app-menu-list" };
const _sfc_main = /* @__PURE__ */ defineComponent({
__name: "AppMenu",
props: {
size: {
type: String,
default: "26px"
},
color: {
type: String,
default: "#aaa"
},
selectColor: {
type: String,
default: "#10B981"
},
menus: {
type: Array,
default: () => []
}
},
setup(__props) {
const props = __props;
const route = useRoute();
const path = ref(route.path);
watch(
() => route.path,
async (newParams) => {
path.value = newParams;
}
);
const isChecked = (index) => {
return path.value === props.menus[index].path;
};
const iconStyle = (index) => {
const style = {
fontSize: props.size,
color: isChecked(index) ? props.selectColor : props.color
};
return style;
};
const isText = ref(false);
return (_ctx, _cache) => {
const _component_router_link = resolveComponent("router-link");
return openBlock(), createElementBlock("div", null, [
createBaseVNode("div", {
class: normalizeClass(["app-menu", { "app-menu-expanded": unref(isText) }])
}, [
createBaseVNode("div", _hoisted_1, [
createBaseVNode("div", {
class: "app-menu-logo",
onClick: _cache[0] || (_cache[0] = ($event) => isText.value = !unref(isText))
}, [
createBaseVNode("img", {
src: unref(icon),
class: "w-9 h-9",
alt: "logo"
}, null, 8, _hoisted_2)
])
]),
createBaseVNode("div", _hoisted_3, [
(openBlock(true), createElementBlock(Fragment, null, renderList(__props.menus, (item, index) => {
return openBlock(), createElementBlock("div", {
key: item.path,
class: "app-menu-item"
}, [
createVNode(_component_router_link, {
class: "app-menu-item-link",
to: item.path
}, {
default: withCtx(() => [
createBaseVNode("i", {
class: normalizeClass(["iconfont app-menu-item-icon", item.meta.icon]),
style: normalizeStyle(iconStyle(index))
}, null, 6),
unref(isText) ? (openBlock(), createElementBlock("span", {
key: 0,
class: normalizeClass(["app-menu-item-text ml-3", isChecked(index) ? "text-green-500" : ""])
}, toDisplayString(item.meta.title), 3)) : createCommentVNode("", true)
]),
_: 2
}, 1032, ["to"])
]);
}), 128))
])
], 2)
]);
};
}
});
const AppMenu = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-f209e92f"]]);
export {
AppMenu as default
};

Binary file not shown.

View File

@@ -0,0 +1,90 @@
.app-menu[data-v-f209e92f] {
width: 100px;
flex-direction: column;
align-items: center;
justify-content: center;
padding-left: 0.25rem;
padding-right: 0.25rem;
transition-property: all;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-duration: 300ms;
}
.app-menu-expanded[data-v-f209e92f] {
width: 160px;
}
.app-menu-expanded .app-menu-item[data-v-f209e92f] {
margin-right: 1rem;
border-radius: 0.25rem;
}
.app-menu-expanded .app-menu-item[data-v-f209e92f]:hover {
--tw-bg-opacity: 1;
background-color: rgb(243 244 246 / var(--tw-bg-opacity, 1));
}
.app-menu-expanded .app-menu-item[data-v-f209e92f]:hover:is(.dark *) {
--tw-bg-opacity: 1;
background-color: rgb(31 41 55 / var(--tw-bg-opacity, 1));
}
.app-menu-item-link[data-v-f209e92f],
.app-menu-header[data-v-f209e92f] {
margin-left: 0.5rem;
display: flex;
width: 200px;
align-items: center;
overflow: hidden;
padding-left: 1.25rem;
padding-right: 1.25rem;
}
.app-menu-header[data-v-f209e92f] {
margin-left: 0.25rem;
}
.app-menu-item-link[data-v-f209e92f] {
margin-bottom: 1.5rem;
margin-top: 1.5rem;
}
.app-menu-item-icon[data-v-f209e92f] {
--tw-text-opacity: 1;
color: rgb(107 114 128 / var(--tw-text-opacity, 1));
transition-property: all;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-duration: 200ms;
}
.app-menu-item-icon[data-v-f209e92f]:is(.dark *) {
--tw-text-opacity: 1;
color: rgb(156 163 175 / var(--tw-text-opacity, 1));
}
.app-menu-item-icon[data-v-f209e92f]:hover {
--tw-scale-x: 1.05 !important;
--tw-scale-y: 1.05 !important;
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)) !important;
--tw-text-opacity: 1 !important;
color: rgb(34 197 94 / var(--tw-text-opacity, 1)) !important;
}
.mobile .app-menu[data-v-f209e92f] {
max-width: 100%;
width: 100vw;
position: relative;
z-index: 999999;
border-top-width: 1px;
--tw-border-opacity: 1;
border-color: rgb(229 231 235 / var(--tw-border-opacity, 1));
--tw-bg-opacity: 1;
background-color: rgb(255 255 255 / var(--tw-bg-opacity, 1));
}
.mobile .app-menu[data-v-f209e92f]:is(.dark *) {
--tw-border-opacity: 1;
border-color: rgb(55 65 81 / var(--tw-border-opacity, 1));
--tw-bg-opacity: 1;
background-color: rgb(0 0 0 / var(--tw-bg-opacity, 1));
}
.mobile .app-menu-header[data-v-f209e92f] {
display: none;
}
.mobile .app-menu-list[data-v-f209e92f] {
display: flex;
justify-content: space-between;
}
.mobile .app-menu-item-link[data-v-f209e92f] {
margin-top: 1rem;
margin-bottom: 1rem;
width: auto;
}

Binary file not shown.

View File

@@ -0,0 +1,319 @@
import { i as isImageSupportNativeLazy, o as observeIntersection } from "./Image-DXClIklC.js";
import { t as tagInjectionKey } from "./Tag-C0oC92WF.js";
import { aL as createInjectionKey, p as cB, aN as insideModal, m as c, aO as insidePopover, Y as cE, d as defineComponent, x as useConfig, r as ref, G as computed, q as useTheme, ap as useThemeClass, o as onMounted, a8 as watchEffect, a as onBeforeUnmount, E as watch, K as resolveSlot, I as resolveWrappedSlot, l as h, as as inject, bw as avatarLight, ao as createKey, bx as color2Class, ay as VResizeObserver } from "./index-DKaFsuse.js";
const avatarGroupInjectionKey = createInjectionKey("n-avatar-group");
const style = cB("avatar", `
width: var(--n-merged-size);
height: var(--n-merged-size);
color: #FFF;
font-size: var(--n-font-size);
display: inline-flex;
position: relative;
overflow: hidden;
text-align: center;
border: var(--n-border);
border-radius: var(--n-border-radius);
--n-merged-color: var(--n-color);
background-color: var(--n-merged-color);
transition:
border-color .3s var(--n-bezier),
background-color .3s var(--n-bezier),
color .3s var(--n-bezier);
`, [insideModal(c("&", "--n-merged-color: var(--n-color-modal);")), insidePopover(c("&", "--n-merged-color: var(--n-color-popover);")), c("img", `
width: 100%;
height: 100%;
`), cE("text", `
white-space: nowrap;
display: inline-block;
position: absolute;
left: 50%;
top: 50%;
`), cB("icon", `
vertical-align: bottom;
font-size: calc(var(--n-merged-size) - 6px);
`), cE("text", "line-height: 1.25")]);
const avatarProps = Object.assign(Object.assign({}, useTheme.props), {
size: [String, Number],
src: String,
circle: {
type: Boolean,
default: void 0
},
objectFit: String,
round: {
type: Boolean,
default: void 0
},
bordered: {
type: Boolean,
default: void 0
},
onError: Function,
fallbackSrc: String,
intersectionObserverOptions: Object,
lazy: Boolean,
onLoad: Function,
renderPlaceholder: Function,
renderFallback: Function,
imgProps: Object,
/** @deprecated */
color: String
});
const __unplugin_components_2 = defineComponent({
name: "Avatar",
props: avatarProps,
setup(props) {
const {
mergedClsPrefixRef,
inlineThemeDisabled
} = useConfig(props);
const hasLoadErrorRef = ref(false);
let memoedTextHtml = null;
const textRef = ref(null);
const selfRef = ref(null);
const fitTextTransform = () => {
const {
value: textEl
} = textRef;
if (textEl) {
if (memoedTextHtml === null || memoedTextHtml !== textEl.innerHTML) {
memoedTextHtml = textEl.innerHTML;
const {
value: selfEl
} = selfRef;
if (selfEl) {
const {
offsetWidth: elWidth,
offsetHeight: elHeight
} = selfEl;
const {
offsetWidth: textWidth,
offsetHeight: textHeight
} = textEl;
const radix = 0.9;
const ratio = Math.min(elWidth / textWidth * radix, elHeight / textHeight * radix, 1);
textEl.style.transform = `translateX(-50%) translateY(-50%) scale(${ratio})`;
}
}
}
};
const NAvatarGroup = inject(avatarGroupInjectionKey, null);
const mergedSizeRef = computed(() => {
const {
size
} = props;
if (size) return size;
const {
size: avatarGroupSize
} = NAvatarGroup || {};
if (avatarGroupSize) return avatarGroupSize;
return "medium";
});
const themeRef = useTheme("Avatar", "-avatar", style, avatarLight, props, mergedClsPrefixRef);
const TagInjection = inject(tagInjectionKey, null);
const mergedRoundRef = computed(() => {
if (NAvatarGroup) return true;
const {
round,
circle
} = props;
if (round !== void 0 || circle !== void 0) return round || circle;
if (TagInjection) {
return TagInjection.roundRef.value;
}
return false;
});
const mergedBorderedRef = computed(() => {
if (NAvatarGroup) return true;
return props.bordered || false;
});
const cssVarsRef = computed(() => {
const size = mergedSizeRef.value;
const round = mergedRoundRef.value;
const bordered = mergedBorderedRef.value;
const {
color: propColor
} = props;
const {
self: {
borderRadius,
fontSize,
color,
border,
colorModal,
colorPopover
},
common: {
cubicBezierEaseInOut
}
} = themeRef.value;
let height;
if (typeof size === "number") {
height = `${size}px`;
} else {
height = themeRef.value.self[createKey("height", size)];
}
return {
"--n-font-size": fontSize,
"--n-border": bordered ? border : "none",
"--n-border-radius": round ? "50%" : borderRadius,
"--n-color": propColor || color,
"--n-color-modal": propColor || colorModal,
"--n-color-popover": propColor || colorPopover,
"--n-bezier": cubicBezierEaseInOut,
"--n-merged-size": `var(--n-avatar-size-override, ${height})`
};
});
const themeClassHandle = inlineThemeDisabled ? useThemeClass("avatar", computed(() => {
const size = mergedSizeRef.value;
const round = mergedRoundRef.value;
const bordered = mergedBorderedRef.value;
const {
color
} = props;
let hash = "";
if (size) {
if (typeof size === "number") {
hash += `a${size}`;
} else {
hash += size[0];
}
}
if (round) {
hash += "b";
}
if (bordered) {
hash += "c";
}
if (color) {
hash += color2Class(color);
}
return hash;
}), cssVarsRef, props) : void 0;
const shouldStartLoadingRef = ref(!props.lazy);
onMounted(() => {
if (props.lazy && props.intersectionObserverOptions) {
let unobserve;
const stopWatchHandle = watchEffect(() => {
unobserve === null || unobserve === void 0 ? void 0 : unobserve();
unobserve = void 0;
if (props.lazy) {
unobserve = observeIntersection(selfRef.value, props.intersectionObserverOptions, shouldStartLoadingRef);
}
});
onBeforeUnmount(() => {
stopWatchHandle();
unobserve === null || unobserve === void 0 ? void 0 : unobserve();
});
}
});
watch(() => {
var _a;
return props.src || ((_a = props.imgProps) === null || _a === void 0 ? void 0 : _a.src);
}, () => {
hasLoadErrorRef.value = false;
});
const loadedRef = ref(!props.lazy);
return {
textRef,
selfRef,
mergedRoundRef,
mergedClsPrefix: mergedClsPrefixRef,
fitTextTransform,
cssVars: inlineThemeDisabled ? void 0 : cssVarsRef,
themeClass: themeClassHandle === null || themeClassHandle === void 0 ? void 0 : themeClassHandle.themeClass,
onRender: themeClassHandle === null || themeClassHandle === void 0 ? void 0 : themeClassHandle.onRender,
hasLoadError: hasLoadErrorRef,
shouldStartLoading: shouldStartLoadingRef,
loaded: loadedRef,
mergedOnError: (e) => {
if (!shouldStartLoadingRef.value) return;
hasLoadErrorRef.value = true;
const {
onError,
imgProps: {
onError: imgPropsOnError
} = {}
} = props;
onError === null || onError === void 0 ? void 0 : onError(e);
imgPropsOnError === null || imgPropsOnError === void 0 ? void 0 : imgPropsOnError(e);
},
mergedOnLoad: (e) => {
const {
onLoad,
imgProps: {
onLoad: imgPropsOnLoad
} = {}
} = props;
onLoad === null || onLoad === void 0 ? void 0 : onLoad(e);
imgPropsOnLoad === null || imgPropsOnLoad === void 0 ? void 0 : imgPropsOnLoad(e);
loadedRef.value = true;
}
};
},
render() {
var _a, _b;
const {
$slots,
src,
mergedClsPrefix,
lazy,
onRender,
loaded,
hasLoadError,
imgProps = {}
} = this;
onRender === null || onRender === void 0 ? void 0 : onRender();
let img;
const placeholderNode = !loaded && !hasLoadError && (this.renderPlaceholder ? this.renderPlaceholder() : (_b = (_a = this.$slots).placeholder) === null || _b === void 0 ? void 0 : _b.call(_a));
if (this.hasLoadError) {
img = this.renderFallback ? this.renderFallback() : resolveSlot($slots.fallback, () => [h("img", {
src: this.fallbackSrc,
style: {
objectFit: this.objectFit
}
})]);
} else {
img = resolveWrappedSlot($slots.default, (children) => {
if (children) {
return h(VResizeObserver, {
onResize: this.fitTextTransform
}, {
default: () => h("span", {
ref: "textRef",
class: `${mergedClsPrefix}-avatar__text`
}, children)
});
} else if (src || imgProps.src) {
const loadSrc = this.src || imgProps.src;
return h("img", Object.assign(Object.assign({}, imgProps), {
loading: (
// If interseciton observer options is set, do not use native lazy
isImageSupportNativeLazy && !this.intersectionObserverOptions && lazy ? "lazy" : "eager"
),
src: lazy && this.intersectionObserverOptions ? this.shouldStartLoading ? loadSrc : void 0 : loadSrc,
"data-image-src": loadSrc,
onLoad: this.mergedOnLoad,
onError: this.mergedOnError,
style: [imgProps.style || "", {
objectFit: this.objectFit
}, placeholderNode ? {
height: "0",
width: "0",
visibility: "hidden",
position: "absolute"
} : ""]
}));
}
});
}
return h("span", {
ref: "selfRef",
class: [`${mergedClsPrefix}-avatar`, this.themeClass],
style: this.cssVars
}, img, lazy && placeholderNode);
}
});
export {
__unplugin_components_2 as _
};

Binary file not shown.

View File

@@ -0,0 +1,803 @@
import { d as defineComponent, r as ref, as as inject, G as computed, x as useConfig, F as useRtl, a8 as watchEffect, E as watch, a as onBeforeUnmount, aT as clickoutside, aU as useLockHtmlScroll, $ as provide, w as withDirectives, a6 as vShow, l as h, aV as FocusTrap, ak as Transition, ax as mergeProps, aK as Scrollbar, aW as drawerInjectionKey, aX as drawerBodyInjectionKey, aY as popoverBodyInjectionKey, aZ as modalBodyInjectionKey, m as c, a_ as commonVariables, p as cB, W as cM, Y as cE, a$ as fadeInTransition, aR as isMounted, q as useTheme, C as useMergedState, A as toRef, b0 as useIsComposing, ap as useThemeClass, b1 as LazyTeleport, b2 as drawerLight, b3 as eventEffectNotPerformed, L as call, b4 as zindexable } from "./index-DKaFsuse.js";
import { f as formatLength } from "./Image-DXClIklC.js";
const NDrawerBodyWrapper = defineComponent({
name: "NDrawerContent",
inheritAttrs: false,
props: {
blockScroll: Boolean,
show: {
type: Boolean,
default: void 0
},
displayDirective: {
type: String,
required: true
},
placement: {
type: String,
required: true
},
contentClass: String,
contentStyle: [Object, String],
nativeScrollbar: {
type: Boolean,
required: true
},
scrollbarProps: Object,
trapFocus: {
type: Boolean,
default: true
},
autoFocus: {
type: Boolean,
default: true
},
showMask: {
type: [Boolean, String],
required: true
},
maxWidth: Number,
maxHeight: Number,
minWidth: Number,
minHeight: Number,
resizable: Boolean,
onClickoutside: Function,
onAfterLeave: Function,
onAfterEnter: Function,
onEsc: Function
},
setup(props) {
const displayedRef = ref(!!props.show);
const bodyRef = ref(null);
const NDrawer = inject(drawerInjectionKey);
let startPosition = 0;
let memoizedBodyStyleCursor = "";
let hoverTimerId = null;
const isHoverOnResizeTriggerRef = ref(false);
const isDraggingRef = ref(false);
const isVertical = computed(() => {
return props.placement === "top" || props.placement === "bottom";
});
const {
mergedClsPrefixRef,
mergedRtlRef
} = useConfig(props);
const rtlEnabledRef = useRtl("Drawer", mergedRtlRef, mergedClsPrefixRef);
const handleBodyMouseleave = handleBodyMouseup;
const handleMousedownResizeTrigger = (e) => {
isDraggingRef.value = true;
startPosition = isVertical.value ? e.clientY : e.clientX;
memoizedBodyStyleCursor = document.body.style.cursor;
document.body.style.cursor = isVertical.value ? "ns-resize" : "ew-resize";
document.body.addEventListener("mousemove", handleBodyMousemove);
document.body.addEventListener("mouseleave", handleBodyMouseleave);
document.body.addEventListener("mouseup", handleBodyMouseup);
};
const handleMouseenterResizeTrigger = () => {
if (hoverTimerId !== null) {
window.clearTimeout(hoverTimerId);
hoverTimerId = null;
}
if (isDraggingRef.value) {
isHoverOnResizeTriggerRef.value = true;
} else {
hoverTimerId = window.setTimeout(() => {
isHoverOnResizeTriggerRef.value = true;
}, 300);
}
};
const handleMouseleaveResizeTrigger = () => {
if (hoverTimerId !== null) {
window.clearTimeout(hoverTimerId);
hoverTimerId = null;
}
isHoverOnResizeTriggerRef.value = false;
};
const {
doUpdateHeight,
doUpdateWidth
} = NDrawer;
const regulateWidth = (size) => {
const {
maxWidth
} = props;
if (maxWidth && size > maxWidth) return maxWidth;
const {
minWidth
} = props;
if (minWidth && size < minWidth) return minWidth;
return size;
};
const regulateHeight = (size) => {
const {
maxHeight
} = props;
if (maxHeight && size > maxHeight) return maxHeight;
const {
minHeight
} = props;
if (minHeight && size < minHeight) return minHeight;
return size;
};
function handleBodyMousemove(e) {
var _a, _b;
if (isDraggingRef.value) {
if (isVertical.value) {
let height = ((_a = bodyRef.value) === null || _a === void 0 ? void 0 : _a.offsetHeight) || 0;
const increment = startPosition - e.clientY;
height += props.placement === "bottom" ? increment : -increment;
height = regulateHeight(height);
doUpdateHeight(height);
startPosition = e.clientY;
} else {
let width = ((_b = bodyRef.value) === null || _b === void 0 ? void 0 : _b.offsetWidth) || 0;
const increment = startPosition - e.clientX;
width += props.placement === "right" ? increment : -increment;
width = regulateWidth(width);
doUpdateWidth(width);
startPosition = e.clientX;
}
}
}
function handleBodyMouseup() {
if (isDraggingRef.value) {
startPosition = 0;
isDraggingRef.value = false;
document.body.style.cursor = memoizedBodyStyleCursor;
document.body.removeEventListener("mousemove", handleBodyMousemove);
document.body.removeEventListener("mouseup", handleBodyMouseup);
document.body.removeEventListener("mouseleave", handleBodyMouseleave);
}
}
watchEffect(() => {
if (props.show) displayedRef.value = true;
});
watch(() => props.show, (value) => {
if (!value) {
handleBodyMouseup();
}
});
onBeforeUnmount(() => {
handleBodyMouseup();
});
const bodyDirectivesRef = computed(() => {
const {
show
} = props;
const directives = [[vShow, show]];
if (!props.showMask) {
directives.push([clickoutside, props.onClickoutside, void 0, {
capture: true
}]);
}
return directives;
});
function handleAfterLeave() {
var _a;
displayedRef.value = false;
(_a = props.onAfterLeave) === null || _a === void 0 ? void 0 : _a.call(props);
}
useLockHtmlScroll(computed(() => props.blockScroll && displayedRef.value));
provide(drawerBodyInjectionKey, bodyRef);
provide(popoverBodyInjectionKey, null);
provide(modalBodyInjectionKey, null);
return {
bodyRef,
rtlEnabled: rtlEnabledRef,
mergedClsPrefix: NDrawer.mergedClsPrefixRef,
isMounted: NDrawer.isMountedRef,
mergedTheme: NDrawer.mergedThemeRef,
displayed: displayedRef,
transitionName: computed(() => {
return {
right: "slide-in-from-right-transition",
left: "slide-in-from-left-transition",
top: "slide-in-from-top-transition",
bottom: "slide-in-from-bottom-transition"
}[props.placement];
}),
handleAfterLeave,
bodyDirectives: bodyDirectivesRef,
handleMousedownResizeTrigger,
handleMouseenterResizeTrigger,
handleMouseleaveResizeTrigger,
isDragging: isDraggingRef,
isHoverOnResizeTrigger: isHoverOnResizeTriggerRef
};
},
render() {
const {
$slots,
mergedClsPrefix
} = this;
return this.displayDirective === "show" || this.displayed || this.show ? withDirectives(
/* Keep the wrapper dom. Make sure the drawer has a host.
Nor the detached content will disappear without transition */
h("div", {
role: "none"
}, h(FocusTrap, {
disabled: !this.showMask || !this.trapFocus,
active: this.show,
autoFocus: this.autoFocus,
onEsc: this.onEsc
}, {
default: () => h(Transition, {
name: this.transitionName,
appear: this.isMounted,
onAfterEnter: this.onAfterEnter,
onAfterLeave: this.handleAfterLeave
}, {
default: () => withDirectives(h("div", mergeProps(this.$attrs, {
role: "dialog",
ref: "bodyRef",
"aria-modal": "true",
class: [
`${mergedClsPrefix}-drawer`,
this.rtlEnabled && `${mergedClsPrefix}-drawer--rtl`,
`${mergedClsPrefix}-drawer--${this.placement}-placement`,
/**
* When the mouse is pressed to resize the drawer,
* disable text selection
*/
this.isDragging && `${mergedClsPrefix}-drawer--unselectable`,
this.nativeScrollbar && `${mergedClsPrefix}-drawer--native-scrollbar`
]
}), [this.resizable ? h("div", {
class: [`${mergedClsPrefix}-drawer__resize-trigger`, (this.isDragging || this.isHoverOnResizeTrigger) && `${mergedClsPrefix}-drawer__resize-trigger--hover`],
onMouseenter: this.handleMouseenterResizeTrigger,
onMouseleave: this.handleMouseleaveResizeTrigger,
onMousedown: this.handleMousedownResizeTrigger
}) : null, this.nativeScrollbar ? h("div", {
class: [`${mergedClsPrefix}-drawer-content-wrapper`, this.contentClass],
style: this.contentStyle,
role: "none"
}, $slots) : h(Scrollbar, Object.assign({}, this.scrollbarProps, {
contentStyle: this.contentStyle,
contentClass: [`${mergedClsPrefix}-drawer-content-wrapper`, this.contentClass],
theme: this.mergedTheme.peers.Scrollbar,
themeOverrides: this.mergedTheme.peerOverrides.Scrollbar
}), $slots)]), this.bodyDirectives)
})
})),
[[vShow, this.displayDirective === "if" || this.displayed || this.show]]
) : null;
}
});
const {
cubicBezierEaseIn: cubicBezierEaseIn$3,
cubicBezierEaseOut: cubicBezierEaseOut$3
} = commonVariables;
function slideInFromBottomTransition({
duration = "0.3s",
leaveDuration = "0.2s",
name = "slide-in-from-bottom"
} = {}) {
return [c(`&.${name}-transition-leave-active`, {
transition: `transform ${leaveDuration} ${cubicBezierEaseIn$3}`
}), c(`&.${name}-transition-enter-active`, {
transition: `transform ${duration} ${cubicBezierEaseOut$3}`
}), c(`&.${name}-transition-enter-to`, {
transform: "translateY(0)"
}), c(`&.${name}-transition-enter-from`, {
transform: "translateY(100%)"
}), c(`&.${name}-transition-leave-from`, {
transform: "translateY(0)"
}), c(`&.${name}-transition-leave-to`, {
transform: "translateY(100%)"
})];
}
const {
cubicBezierEaseIn: cubicBezierEaseIn$2,
cubicBezierEaseOut: cubicBezierEaseOut$2
} = commonVariables;
function slideInFromLeftTransition({
duration = "0.3s",
leaveDuration = "0.2s",
name = "slide-in-from-left"
} = {}) {
return [c(`&.${name}-transition-leave-active`, {
transition: `transform ${leaveDuration} ${cubicBezierEaseIn$2}`
}), c(`&.${name}-transition-enter-active`, {
transition: `transform ${duration} ${cubicBezierEaseOut$2}`
}), c(`&.${name}-transition-enter-to`, {
transform: "translateX(0)"
}), c(`&.${name}-transition-enter-from`, {
transform: "translateX(-100%)"
}), c(`&.${name}-transition-leave-from`, {
transform: "translateX(0)"
}), c(`&.${name}-transition-leave-to`, {
transform: "translateX(-100%)"
})];
}
const {
cubicBezierEaseIn: cubicBezierEaseIn$1,
cubicBezierEaseOut: cubicBezierEaseOut$1
} = commonVariables;
function slideInFromRightTransition({
duration = "0.3s",
leaveDuration = "0.2s",
name = "slide-in-from-right"
} = {}) {
return [c(`&.${name}-transition-leave-active`, {
transition: `transform ${leaveDuration} ${cubicBezierEaseIn$1}`
}), c(`&.${name}-transition-enter-active`, {
transition: `transform ${duration} ${cubicBezierEaseOut$1}`
}), c(`&.${name}-transition-enter-to`, {
transform: "translateX(0)"
}), c(`&.${name}-transition-enter-from`, {
transform: "translateX(100%)"
}), c(`&.${name}-transition-leave-from`, {
transform: "translateX(0)"
}), c(`&.${name}-transition-leave-to`, {
transform: "translateX(100%)"
})];
}
const {
cubicBezierEaseIn,
cubicBezierEaseOut
} = commonVariables;
function slideInFromTopTransition({
duration = "0.3s",
leaveDuration = "0.2s",
name = "slide-in-from-top"
} = {}) {
return [c(`&.${name}-transition-leave-active`, {
transition: `transform ${leaveDuration} ${cubicBezierEaseIn}`
}), c(`&.${name}-transition-enter-active`, {
transition: `transform ${duration} ${cubicBezierEaseOut}`
}), c(`&.${name}-transition-enter-to`, {
transform: "translateY(0)"
}), c(`&.${name}-transition-enter-from`, {
transform: "translateY(-100%)"
}), c(`&.${name}-transition-leave-from`, {
transform: "translateY(0)"
}), c(`&.${name}-transition-leave-to`, {
transform: "translateY(-100%)"
})];
}
const style = c([cB("drawer", `
word-break: break-word;
line-height: var(--n-line-height);
position: absolute;
pointer-events: all;
box-shadow: var(--n-box-shadow);
transition:
background-color .3s var(--n-bezier),
color .3s var(--n-bezier);
background-color: var(--n-color);
color: var(--n-text-color);
box-sizing: border-box;
`, [slideInFromRightTransition(), slideInFromLeftTransition(), slideInFromTopTransition(), slideInFromBottomTransition(), cM("unselectable", `
user-select: none;
-webkit-user-select: none;
`), cM("native-scrollbar", [cB("drawer-content-wrapper", `
overflow: auto;
height: 100%;
`)]), cE("resize-trigger", `
position: absolute;
background-color: #0000;
transition: background-color .3s var(--n-bezier);
`, [cM("hover", `
background-color: var(--n-resize-trigger-color-hover);
`)]), cB("drawer-content-wrapper", `
box-sizing: border-box;
`), cB("drawer-content", `
height: 100%;
display: flex;
flex-direction: column;
`, [cM("native-scrollbar", [cB("drawer-body-content-wrapper", `
height: 100%;
overflow: auto;
`)]), cB("drawer-body", `
flex: 1 0 0;
overflow: hidden;
`), cB("drawer-body-content-wrapper", `
box-sizing: border-box;
padding: var(--n-body-padding);
`), cB("drawer-header", `
font-weight: var(--n-title-font-weight);
line-height: 1;
font-size: var(--n-title-font-size);
color: var(--n-title-text-color);
padding: var(--n-header-padding);
transition: border .3s var(--n-bezier);
border-bottom: 1px solid var(--n-divider-color);
border-bottom: var(--n-header-border-bottom);
display: flex;
justify-content: space-between;
align-items: center;
`, [cE("main", `
flex: 1;
`), cE("close", `
margin-left: 6px;
transition:
background-color .3s var(--n-bezier),
color .3s var(--n-bezier);
`)]), cB("drawer-footer", `
display: flex;
justify-content: flex-end;
border-top: var(--n-footer-border-top);
transition: border .3s var(--n-bezier);
padding: var(--n-footer-padding);
`)]), cM("right-placement", `
top: 0;
bottom: 0;
right: 0;
border-top-left-radius: var(--n-border-radius);
border-bottom-left-radius: var(--n-border-radius);
`, [cE("resize-trigger", `
width: 3px;
height: 100%;
top: 0;
left: 0;
transform: translateX(-1.5px);
cursor: ew-resize;
`)]), cM("left-placement", `
top: 0;
bottom: 0;
left: 0;
border-top-right-radius: var(--n-border-radius);
border-bottom-right-radius: var(--n-border-radius);
`, [cE("resize-trigger", `
width: 3px;
height: 100%;
top: 0;
right: 0;
transform: translateX(1.5px);
cursor: ew-resize;
`)]), cM("top-placement", `
top: 0;
left: 0;
right: 0;
border-bottom-left-radius: var(--n-border-radius);
border-bottom-right-radius: var(--n-border-radius);
`, [cE("resize-trigger", `
width: 100%;
height: 3px;
bottom: 0;
left: 0;
transform: translateY(1.5px);
cursor: ns-resize;
`)]), cM("bottom-placement", `
left: 0;
bottom: 0;
right: 0;
border-top-left-radius: var(--n-border-radius);
border-top-right-radius: var(--n-border-radius);
`, [cE("resize-trigger", `
width: 100%;
height: 3px;
top: 0;
left: 0;
transform: translateY(-1.5px);
cursor: ns-resize;
`)])]), c("body", [c(">", [cB("drawer-container", `
position: fixed;
`)])]), cB("drawer-container", `
position: relative;
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
pointer-events: none;
`, [c("> *", `
pointer-events: all;
`)]), cB("drawer-mask", `
background-color: rgba(0, 0, 0, .3);
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
`, [cM("invisible", `
background-color: rgba(0, 0, 0, 0)
`), fadeInTransition({
enterDuration: "0.2s",
leaveDuration: "0.2s",
enterCubicBezier: "var(--n-bezier-in)",
leaveCubicBezier: "var(--n-bezier-out)"
})])]);
const drawerProps = Object.assign(Object.assign({}, useTheme.props), {
show: Boolean,
width: [Number, String],
height: [Number, String],
placement: {
type: String,
default: "right"
},
maskClosable: {
type: Boolean,
default: true
},
showMask: {
type: [Boolean, String],
default: true
},
to: [String, Object],
displayDirective: {
type: String,
default: "if"
},
nativeScrollbar: {
type: Boolean,
default: true
},
zIndex: Number,
onMaskClick: Function,
scrollbarProps: Object,
contentClass: String,
contentStyle: [Object, String],
trapFocus: {
type: Boolean,
default: true
},
onEsc: Function,
autoFocus: {
type: Boolean,
default: true
},
closeOnEsc: {
type: Boolean,
default: true
},
blockScroll: {
type: Boolean,
default: true
},
maxWidth: Number,
maxHeight: Number,
minWidth: Number,
minHeight: Number,
resizable: Boolean,
defaultWidth: {
type: [Number, String],
default: 251
},
defaultHeight: {
type: [Number, String],
default: 251
},
onUpdateWidth: [Function, Array],
onUpdateHeight: [Function, Array],
"onUpdate:width": [Function, Array],
"onUpdate:height": [Function, Array],
"onUpdate:show": [Function, Array],
onUpdateShow: [Function, Array],
onAfterEnter: Function,
onAfterLeave: Function,
/** @deprecated */
drawerStyle: [String, Object],
drawerClass: String,
target: null,
onShow: Function,
onHide: Function
});
const __unplugin_components_2 = defineComponent({
name: "Drawer",
inheritAttrs: false,
props: drawerProps,
setup(props) {
const {
mergedClsPrefixRef,
namespaceRef,
inlineThemeDisabled
} = useConfig(props);
const isMountedRef = isMounted();
const themeRef = useTheme("Drawer", "-drawer", style, drawerLight, props, mergedClsPrefixRef);
const uncontrolledWidthRef = ref(props.defaultWidth);
const uncontrolledHeightRef = ref(props.defaultHeight);
const mergedWidthRef = useMergedState(toRef(props, "width"), uncontrolledWidthRef);
const mergedHeightRef = useMergedState(toRef(props, "height"), uncontrolledHeightRef);
const styleWidthRef = computed(() => {
const {
placement
} = props;
if (placement === "top" || placement === "bottom") return "";
return formatLength(mergedWidthRef.value);
});
const styleHeightRef = computed(() => {
const {
placement
} = props;
if (placement === "left" || placement === "right") return "";
return formatLength(mergedHeightRef.value);
});
const doUpdateWidth = (value) => {
const {
onUpdateWidth,
"onUpdate:width": _onUpdateWidth
} = props;
if (onUpdateWidth) call(onUpdateWidth, value);
if (_onUpdateWidth) call(_onUpdateWidth, value);
uncontrolledWidthRef.value = value;
};
const doUpdateHeight = (value) => {
const {
onUpdateHeight,
"onUpdate:width": _onUpdateHeight
} = props;
if (onUpdateHeight) call(onUpdateHeight, value);
if (_onUpdateHeight) call(_onUpdateHeight, value);
uncontrolledHeightRef.value = value;
};
const mergedBodyStyleRef = computed(() => {
return [{
width: styleWidthRef.value,
height: styleHeightRef.value
}, props.drawerStyle || ""];
});
function handleMaskClick(e) {
const {
onMaskClick,
maskClosable
} = props;
if (maskClosable) {
doUpdateShow(false);
}
if (onMaskClick) onMaskClick(e);
}
function handleOutsideClick(e) {
handleMaskClick(e);
}
const isComposingRef = useIsComposing();
function handleEsc(e) {
var _a;
(_a = props.onEsc) === null || _a === void 0 ? void 0 : _a.call(props);
if (props.show && props.closeOnEsc && eventEffectNotPerformed(e)) {
if (!isComposingRef.value) {
doUpdateShow(false);
}
}
}
function doUpdateShow(show) {
const {
onHide,
onUpdateShow,
"onUpdate:show": _onUpdateShow
} = props;
if (onUpdateShow) call(onUpdateShow, show);
if (_onUpdateShow) call(_onUpdateShow, show);
if (onHide && !show) call(onHide, show);
}
provide(drawerInjectionKey, {
isMountedRef,
mergedThemeRef: themeRef,
mergedClsPrefixRef,
doUpdateShow,
doUpdateHeight,
doUpdateWidth
});
const cssVarsRef = computed(() => {
const {
common: {
cubicBezierEaseInOut,
cubicBezierEaseIn: cubicBezierEaseIn2,
cubicBezierEaseOut: cubicBezierEaseOut2
},
self: {
color,
textColor,
boxShadow,
lineHeight,
headerPadding,
footerPadding,
borderRadius,
bodyPadding,
titleFontSize,
titleTextColor,
titleFontWeight,
headerBorderBottom,
footerBorderTop,
closeIconColor,
closeIconColorHover,
closeIconColorPressed,
closeColorHover,
closeColorPressed,
closeIconSize,
closeSize,
closeBorderRadius,
resizableTriggerColorHover
}
} = themeRef.value;
return {
"--n-line-height": lineHeight,
"--n-color": color,
"--n-border-radius": borderRadius,
"--n-text-color": textColor,
"--n-box-shadow": boxShadow,
"--n-bezier": cubicBezierEaseInOut,
"--n-bezier-out": cubicBezierEaseOut2,
"--n-bezier-in": cubicBezierEaseIn2,
"--n-header-padding": headerPadding,
"--n-body-padding": bodyPadding,
"--n-footer-padding": footerPadding,
"--n-title-text-color": titleTextColor,
"--n-title-font-size": titleFontSize,
"--n-title-font-weight": titleFontWeight,
"--n-header-border-bottom": headerBorderBottom,
"--n-footer-border-top": footerBorderTop,
"--n-close-icon-color": closeIconColor,
"--n-close-icon-color-hover": closeIconColorHover,
"--n-close-icon-color-pressed": closeIconColorPressed,
"--n-close-size": closeSize,
"--n-close-color-hover": closeColorHover,
"--n-close-color-pressed": closeColorPressed,
"--n-close-icon-size": closeIconSize,
"--n-close-border-radius": closeBorderRadius,
"--n-resize-trigger-color-hover": resizableTriggerColorHover
};
});
const themeClassHandle = inlineThemeDisabled ? useThemeClass("drawer", void 0, cssVarsRef, props) : void 0;
return {
mergedClsPrefix: mergedClsPrefixRef,
namespace: namespaceRef,
mergedBodyStyle: mergedBodyStyleRef,
handleOutsideClick,
handleMaskClick,
handleEsc,
mergedTheme: themeRef,
cssVars: inlineThemeDisabled ? void 0 : cssVarsRef,
themeClass: themeClassHandle === null || themeClassHandle === void 0 ? void 0 : themeClassHandle.themeClass,
onRender: themeClassHandle === null || themeClassHandle === void 0 ? void 0 : themeClassHandle.onRender,
isMounted: isMountedRef
};
},
render() {
const {
mergedClsPrefix
} = this;
return h(LazyTeleport, {
to: this.to,
show: this.show
}, {
default: () => {
var _a;
(_a = this.onRender) === null || _a === void 0 ? void 0 : _a.call(this);
return withDirectives(h("div", {
class: [`${mergedClsPrefix}-drawer-container`, this.namespace, this.themeClass],
style: this.cssVars,
role: "none"
}, this.showMask ? h(Transition, {
name: "fade-in-transition",
appear: this.isMounted
}, {
default: () => this.show ? h("div", {
"aria-hidden": true,
class: [`${mergedClsPrefix}-drawer-mask`, this.showMask === "transparent" && `${mergedClsPrefix}-drawer-mask--invisible`],
onClick: this.handleMaskClick
}) : null
}) : null, h(NDrawerBodyWrapper, Object.assign({}, this.$attrs, {
class: [this.drawerClass, this.$attrs.class],
style: [this.mergedBodyStyle, this.$attrs.style],
blockScroll: this.blockScroll,
contentStyle: this.contentStyle,
contentClass: this.contentClass,
placement: this.placement,
scrollbarProps: this.scrollbarProps,
show: this.show,
displayDirective: this.displayDirective,
nativeScrollbar: this.nativeScrollbar,
onAfterEnter: this.onAfterEnter,
onAfterLeave: this.onAfterLeave,
trapFocus: this.trapFocus,
autoFocus: this.autoFocus,
resizable: this.resizable,
maxHeight: this.maxHeight,
minHeight: this.minHeight,
maxWidth: this.maxWidth,
minWidth: this.minWidth,
showMask: this.showMask,
onEsc: this.handleEsc,
onClickoutside: this.handleOutsideClick
}), this.$slots)), [[zindexable, {
zIndex: this.zIndex,
enabled: this.show
}]]);
}
});
}
});
export {
__unplugin_components_2 as _
};

Binary file not shown.

View File

@@ -0,0 +1,195 @@
import { p as cB, V as cNotM, W as cM, q as useTheme, d as defineComponent, b6 as useMergedClsPrefix, b7 as ellipsisLight, r as ref, G as computed, au as onDeactivated, l as h, ax as mergeProps } from "./index-DKaFsuse.js";
import { _ as __unplugin_components_3 } from "./Image-DXClIklC.js";
const style = cB("ellipsis", {
overflow: "hidden"
}, [cNotM("line-clamp", `
white-space: nowrap;
display: inline-block;
vertical-align: bottom;
max-width: 100%;
`), cM("line-clamp", `
display: -webkit-inline-box;
-webkit-box-orient: vertical;
`), cM("cursor-pointer", `
cursor: pointer;
`)]);
function createLineClampClass(clsPrefix) {
return `${clsPrefix}-ellipsis--line-clamp`;
}
function createCursorClass(clsPrefix, cursor) {
return `${clsPrefix}-ellipsis--cursor-${cursor}`;
}
const ellipsisProps = Object.assign(Object.assign({}, useTheme.props), {
expandTrigger: String,
lineClamp: [Number, String],
tooltip: {
type: [Boolean, Object],
default: true
}
});
const __unplugin_components_2 = defineComponent({
name: "Ellipsis",
inheritAttrs: false,
props: ellipsisProps,
setup(props, {
slots,
attrs
}) {
const mergedClsPrefixRef = useMergedClsPrefix();
const mergedTheme = useTheme("Ellipsis", "-ellipsis", style, ellipsisLight, props, mergedClsPrefixRef);
const triggerRef = ref(null);
const triggerInnerRef = ref(null);
const tooltipRef = ref(null);
const expandedRef = ref(false);
const ellipsisStyleRef = computed(() => {
const {
lineClamp
} = props;
const {
value: expanded
} = expandedRef;
if (lineClamp !== void 0) {
return {
textOverflow: "",
"-webkit-line-clamp": expanded ? "" : lineClamp
};
} else {
return {
textOverflow: expanded ? "" : "ellipsis",
"-webkit-line-clamp": ""
};
}
});
function getTooltipDisabled() {
let tooltipDisabled = false;
const {
value: expanded
} = expandedRef;
if (expanded) return true;
const {
value: trigger
} = triggerRef;
if (trigger) {
const {
lineClamp
} = props;
syncEllipsisStyle(trigger);
if (lineClamp !== void 0) {
tooltipDisabled = trigger.scrollHeight <= trigger.offsetHeight;
} else {
const {
value: triggerInner
} = triggerInnerRef;
if (triggerInner) {
tooltipDisabled = triggerInner.getBoundingClientRect().width <= trigger.getBoundingClientRect().width;
}
}
syncCursorStyle(trigger, tooltipDisabled);
}
return tooltipDisabled;
}
const handleClickRef = computed(() => {
return props.expandTrigger === "click" ? () => {
var _a;
const {
value: expanded
} = expandedRef;
if (expanded) {
(_a = tooltipRef.value) === null || _a === void 0 ? void 0 : _a.setShow(false);
}
expandedRef.value = !expanded;
} : void 0;
});
onDeactivated(() => {
var _a;
if (props.tooltip) {
(_a = tooltipRef.value) === null || _a === void 0 ? void 0 : _a.setShow(false);
}
});
const renderTrigger = () => h("span", Object.assign({}, mergeProps(attrs, {
class: [`${mergedClsPrefixRef.value}-ellipsis`, props.lineClamp !== void 0 ? createLineClampClass(mergedClsPrefixRef.value) : void 0, props.expandTrigger === "click" ? createCursorClass(mergedClsPrefixRef.value, "pointer") : void 0],
style: ellipsisStyleRef.value
}), {
ref: "triggerRef",
onClick: handleClickRef.value,
onMouseenter: (
// get tooltip disabled will derive cursor style
props.expandTrigger === "click" ? getTooltipDisabled : void 0
)
}), props.lineClamp ? slots : h("span", {
ref: "triggerInnerRef"
}, slots));
function syncEllipsisStyle(trigger) {
if (!trigger) return;
const latestStyle = ellipsisStyleRef.value;
const lineClampClass = createLineClampClass(mergedClsPrefixRef.value);
if (props.lineClamp !== void 0) {
syncTriggerClass(trigger, lineClampClass, "add");
} else {
syncTriggerClass(trigger, lineClampClass, "remove");
}
for (const key in latestStyle) {
if (trigger.style[key] !== latestStyle[key]) {
trigger.style[key] = latestStyle[key];
}
}
}
function syncCursorStyle(trigger, tooltipDisabled) {
const cursorClass = createCursorClass(mergedClsPrefixRef.value, "pointer");
if (props.expandTrigger === "click" && !tooltipDisabled) {
syncTriggerClass(trigger, cursorClass, "add");
} else {
syncTriggerClass(trigger, cursorClass, "remove");
}
}
function syncTriggerClass(trigger, styleClass, action) {
if (action === "add") {
if (!trigger.classList.contains(styleClass)) {
trigger.classList.add(styleClass);
}
} else {
if (trigger.classList.contains(styleClass)) {
trigger.classList.remove(styleClass);
}
}
}
return {
mergedTheme,
triggerRef,
triggerInnerRef,
tooltipRef,
handleClick: handleClickRef,
renderTrigger,
getTooltipDisabled
};
},
render() {
var _a;
const {
tooltip,
renderTrigger,
$slots
} = this;
if (tooltip) {
const {
mergedTheme
} = this;
return h(__unplugin_components_3, Object.assign({
ref: "tooltipRef",
placement: "top"
}, tooltip, {
getDisabled: this.getTooltipDisabled,
theme: mergedTheme.peers.Tooltip,
themeOverrides: mergedTheme.peerOverrides.Tooltip
}), {
trigger: renderTrigger,
default: (_a = $slots.tooltip) !== null && _a !== void 0 ? _a : $slots.default
});
} else {
return renderTrigger();
}
}
});
export {
__unplugin_components_2 as _
};

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,111 @@
import { p as cB, W as cM, m as c, q as useTheme, d as defineComponent, x as useConfig, bv as iconLight, G as computed, ap as useThemeClass, bd as warn, l as h, ax as mergeProps } from "./index-DKaFsuse.js";
import { f as formatLength } from "./Image-DXClIklC.js";
const style = cB("icon", `
height: 1em;
width: 1em;
line-height: 1em;
text-align: center;
display: inline-block;
position: relative;
fill: currentColor;
transform: translateZ(0);
`, [cM("color-transition", {
transition: "color .3s var(--n-bezier)"
}), cM("depth", {
color: "var(--n-color)"
}, [c("svg", {
opacity: "var(--n-opacity)",
transition: "opacity .3s var(--n-bezier)"
})]), c("svg", {
height: "1em",
width: "1em"
})]);
const iconProps = Object.assign(Object.assign({}, useTheme.props), {
depth: [String, Number],
size: [Number, String],
color: String,
component: [Object, Function]
});
const NIcon = defineComponent({
_n_icon__: true,
name: "Icon",
inheritAttrs: false,
props: iconProps,
setup(props) {
const {
mergedClsPrefixRef,
inlineThemeDisabled
} = useConfig(props);
const themeRef = useTheme("Icon", "-icon", style, iconLight, props, mergedClsPrefixRef);
const cssVarsRef = computed(() => {
const {
depth
} = props;
const {
common: {
cubicBezierEaseInOut
},
self
} = themeRef.value;
if (depth !== void 0) {
const {
color,
[`opacity${depth}Depth`]: opacity
} = self;
return {
"--n-bezier": cubicBezierEaseInOut,
"--n-color": color,
"--n-opacity": opacity
};
}
return {
"--n-bezier": cubicBezierEaseInOut,
"--n-color": "",
"--n-opacity": ""
};
});
const themeClassHandle = inlineThemeDisabled ? useThemeClass("icon", computed(() => `${props.depth || "d"}`), cssVarsRef, props) : void 0;
return {
mergedClsPrefix: mergedClsPrefixRef,
mergedStyle: computed(() => {
const {
size,
color
} = props;
return {
fontSize: formatLength(size),
color
};
}),
cssVars: inlineThemeDisabled ? void 0 : cssVarsRef,
themeClass: themeClassHandle === null || themeClassHandle === void 0 ? void 0 : themeClassHandle.themeClass,
onRender: themeClassHandle === null || themeClassHandle === void 0 ? void 0 : themeClassHandle.onRender
};
},
render() {
var _a;
const {
$parent,
depth,
mergedClsPrefix,
component,
onRender,
themeClass
} = this;
if ((_a = $parent === null || $parent === void 0 ? void 0 : $parent.$options) === null || _a === void 0 ? void 0 : _a._n_icon__) {
warn("icon", "don't wrap `n-icon` inside `n-icon`");
}
onRender === null || onRender === void 0 ? void 0 : onRender();
return h("i", mergeProps(this.$attrs, {
role: "img",
class: [`${mergedClsPrefix}-icon`, themeClass, {
[`${mergedClsPrefix}-icon--depth`]: depth,
[`${mergedClsPrefix}-icon--color-transition`]: depth !== void 0
}],
style: [this.cssVars, this.mergedStyle]
}), component ? h(component) : this.$slots);
}
});
export {
NIcon as N
};

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,170 @@
import { p as cB, W as cM, d as defineComponent, q as useTheme, r as ref, x as useConfig, aI as layoutLight, $ as provide, aJ as useReactivated, G as computed, ap as useThemeClass, l as h, aK as Scrollbar, aL as createInjectionKey } from "./index-DKaFsuse.js";
const positionProp = {
type: String,
default: "static"
};
const style = cB("layout", `
color: var(--n-text-color);
background-color: var(--n-color);
box-sizing: border-box;
position: relative;
z-index: auto;
flex: auto;
overflow: hidden;
transition:
box-shadow .3s var(--n-bezier),
background-color .3s var(--n-bezier),
color .3s var(--n-bezier);
`, [cB("layout-scroll-container", `
overflow-x: hidden;
box-sizing: border-box;
height: 100%;
`), cM("absolute-positioned", `
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
`)]);
const layoutProps = {
embedded: Boolean,
position: positionProp,
nativeScrollbar: {
type: Boolean,
default: true
},
scrollbarProps: Object,
onScroll: Function,
contentClass: String,
contentStyle: {
type: [String, Object],
default: ""
},
hasSider: Boolean,
siderPlacement: {
type: String,
default: "left"
}
};
const layoutInjectionKey = createInjectionKey("n-layout");
function createLayoutComponent(isContent) {
return defineComponent({
name: "Layout",
props: Object.assign(Object.assign({}, useTheme.props), layoutProps),
setup(props) {
const scrollableElRef = ref(null);
const scrollbarInstRef = ref(null);
const {
mergedClsPrefixRef,
inlineThemeDisabled
} = useConfig(props);
const themeRef = useTheme("Layout", "-layout", style, layoutLight, props, mergedClsPrefixRef);
function scrollTo(options, y) {
if (props.nativeScrollbar) {
const {
value: scrollableEl
} = scrollableElRef;
if (scrollableEl) {
if (y === void 0) {
scrollableEl.scrollTo(options);
} else {
scrollableEl.scrollTo(options, y);
}
}
} else {
const {
value: scrollbarInst
} = scrollbarInstRef;
if (scrollbarInst) {
scrollbarInst.scrollTo(options, y);
}
}
}
provide(layoutInjectionKey, props);
let scrollX = 0;
let scrollY = 0;
const handleNativeElScroll = (e) => {
var _a;
const target = e.target;
scrollX = target.scrollLeft;
scrollY = target.scrollTop;
(_a = props.onScroll) === null || _a === void 0 ? void 0 : _a.call(props, e);
};
useReactivated(() => {
if (props.nativeScrollbar) {
const el = scrollableElRef.value;
if (el) {
el.scrollTop = scrollY;
el.scrollLeft = scrollX;
}
}
});
const hasSiderStyle = {
display: "flex",
flexWrap: "nowrap",
width: "100%",
flexDirection: "row"
};
const exposedMethods = {
scrollTo
};
const cssVarsRef = computed(() => {
const {
common: {
cubicBezierEaseInOut
},
self
} = themeRef.value;
return {
"--n-bezier": cubicBezierEaseInOut,
"--n-color": props.embedded ? self.colorEmbedded : self.color,
"--n-text-color": self.textColor
};
});
const themeClassHandle = inlineThemeDisabled ? useThemeClass("layout", computed(() => {
return props.embedded ? "e" : "";
}), cssVarsRef, props) : void 0;
return Object.assign({
mergedClsPrefix: mergedClsPrefixRef,
scrollableElRef,
scrollbarInstRef,
hasSiderStyle,
mergedTheme: themeRef,
handleNativeElScroll,
cssVars: inlineThemeDisabled ? void 0 : cssVarsRef,
themeClass: themeClassHandle === null || themeClassHandle === void 0 ? void 0 : themeClassHandle.themeClass,
onRender: themeClassHandle === null || themeClassHandle === void 0 ? void 0 : themeClassHandle.onRender
}, exposedMethods);
},
render() {
var _a;
const {
mergedClsPrefix,
hasSider
} = this;
(_a = this.onRender) === null || _a === void 0 ? void 0 : _a.call(this);
const hasSiderStyle = hasSider ? this.hasSiderStyle : void 0;
const layoutClass = [this.themeClass, isContent, `${mergedClsPrefix}-layout`, `${mergedClsPrefix}-layout--${this.position}-positioned`];
return h("div", {
class: layoutClass,
style: this.cssVars
}, this.nativeScrollbar ? h("div", {
ref: "scrollableElRef",
class: [`${mergedClsPrefix}-layout-scroll-container`, this.contentClass],
style: [this.contentStyle, hasSiderStyle],
onScroll: this.handleNativeElScroll
}, this.$slots) : h(Scrollbar, Object.assign({}, this.scrollbarProps, {
onScroll: this.onScroll,
ref: "scrollbarInstRef",
theme: this.mergedTheme.peers.Scrollbar,
themeOverrides: this.mergedTheme.peerOverrides.Scrollbar,
contentClass: this.contentClass,
contentStyle: [this.contentStyle, hasSiderStyle]
}), this.$slots));
}
});
}
const __unplugin_components_1 = createLayoutComponent(false);
export {
__unplugin_components_1 as _
};

Binary file not shown.

View File

@@ -0,0 +1,162 @@
.music-title[data-v-1b137c3d] {
font-size: 1.25rem;
line-height: 1.75rem;
font-weight: 700;
--tw-text-opacity: 1;
color: rgb(17 24 39 / var(--tw-text-opacity, 1));
}
.music-title[data-v-1b137c3d]:is(.dark *) {
--tw-text-opacity: 1;
color: rgb(255 255 255 / var(--tw-text-opacity, 1));
}
.music-page[data-v-1b137c3d] {
height: 100%;
width: 100%;
border-top-left-radius: 1rem;
border-top-right-radius: 1rem;
background-color: rgb(255 255 255 / var(--tw-bg-opacity, 1));
--tw-bg-opacity: 0.75;
padding-left: 2rem;
padding-right: 2rem;
}
.music-page[data-v-1b137c3d]:is(.dark *) {
background-color: rgb(0 0 0 / var(--tw-bg-opacity, 1));
--tw-bg-opacity: 0.75;
}
.music-page[data-v-1b137c3d] {
-webkit-backdrop-filter: blur(20px);
backdrop-filter: blur(20px);
}
.music-close[data-v-1b137c3d] {
display: flex;
cursor: pointer;
align-items: center;
gap: 0.5rem;
--tw-text-opacity: 1;
color: rgb(17 24 39 / var(--tw-text-opacity, 1));
}
.music-close[data-v-1b137c3d]:is(.dark *) {
--tw-text-opacity: 1;
color: rgb(255 255 255 / var(--tw-text-opacity, 1));
}
.music-close .icon[data-v-1b137c3d] {
font-size: 1.875rem;
line-height: 2.25rem;
}
.music-content[data-v-1b137c3d] {
display: flex;
height: calc(100% - 60px);
}
.music-info[data-v-1b137c3d] {
display: flex;
width: 25%;
flex-shrink: 0;
flex-direction: column;
padding-right: 2rem;
}
.music-info .music-cover[data-v-1b137c3d] {
margin-bottom: 1rem;
aspect-ratio: 1 / 1;
min-height: 250px;
width: 100%;
overflow: hidden;
border-radius: 1rem;
}
.music-info .music-cover .cover-img[data-v-1b137c3d] {
height: 100%;
width: 100%;
-o-object-fit: cover;
object-fit: cover;
}
.music-info .creator-info[data-v-1b137c3d] {
margin-bottom: 1rem;
display: flex;
align-items: center;
}
.music-info .creator-info .creator-name[data-v-1b137c3d] {
margin-left: 0.5rem;
--tw-text-opacity: 1;
color: rgb(55 65 81 / var(--tw-text-opacity, 1));
}
.music-info .creator-info .creator-name[data-v-1b137c3d]:is(.dark *) {
--tw-text-opacity: 1;
color: rgb(209 213 219 / var(--tw-text-opacity, 1));
}
.music-info .music-desc[data-v-1b137c3d] {
padding-right: 1rem;
font-size: 0.875rem;
line-height: 1.25rem;
line-height: 1.625;
--tw-text-opacity: 1;
color: rgb(75 85 99 / var(--tw-text-opacity, 1));
}
.music-info .music-desc[data-v-1b137c3d]:is(.dark *) {
--tw-text-opacity: 1;
color: rgb(156 163 175 / var(--tw-text-opacity, 1));
}
.music-list[data-v-1b137c3d] {
min-height: 0px;
flex-grow: 1;
}
.music-list-container[data-v-1b137c3d] {
position: relative;
display: flex;
min-height: 0px;
flex-grow: 1;
flex-direction: column;
}
.music-list-content[data-v-1b137c3d] {
min-height: calc(80vh - 60px);
}
.music-list[data-v-1b137c3d] .n-virtual-list__scroll {
scrollbar-width: none;
}
.music-list[data-v-1b137c3d] .n-virtual-list__scroll::-webkit-scrollbar {
display: none;
}
.mobile .music-page[data-v-1b137c3d] {
padding-left: 1rem;
padding-right: 1rem;
}
.mobile .music-content[data-v-1b137c3d] {
flex-direction: column;
}
.mobile .music-info[data-v-1b137c3d] {
margin-bottom: 0.5rem;
display: flex;
width: 100%;
flex-direction: row;
padding-right: 0px;
}
.mobile .music-info .music-cover[data-v-1b137c3d] {
margin-bottom: 1rem;
height: 100px;
width: 100px;
overflow: hidden;
border-radius: 0.5rem;
}
.mobile .music-info .music-detail[data-v-1b137c3d] {
margin-left: 1rem;
flex: 1 1 0%;
}
.loading-more[data-v-1b137c3d] {
padding-top: 1rem;
padding-bottom: 1rem;
text-align: center;
--tw-text-opacity: 1;
color: rgb(107 114 128 / var(--tw-text-opacity, 1));
}
.loading-more[data-v-1b137c3d]:is(.dark *) {
--tw-text-opacity: 1;
color: rgb(156 163 175 / var(--tw-text-opacity, 1));
}
.double-item[data-v-1b137c3d] {
margin-bottom: 0.5rem;
border-radius: 1.5rem;
background-color: rgb(248 249 250 / var(--tw-bg-opacity, 1));
--tw-bg-opacity: 0.2;
}
.double-item[data-v-1b137c3d]:is(.dark *) {
background-color: rgb(22 22 22 / var(--tw-bg-opacity, 1));
--tw-bg-opacity: 0.2;
}

Binary file not shown.

View File

@@ -0,0 +1,258 @@
import { ad as request, d as defineComponent, r as ref, G as computed, E as watch, O as createBlock, f as withCtx, u as unref, g as useStore, j as openBlock, b as createBaseVNode, e as createVNode, t as toDisplayString, a7 as getImgUrl, n as normalizeClass, s as setAnimationClass, c as createElementBlock, T as createCommentVNode, U as PlayBottom, a4 as renderList, a2 as normalizeStyle, a3 as Fragment, ac as isMobile, a5 as setAnimationDelay, S as Scrollbar, aj as __unplugin_components_0, am as getMusicDetail, _ as _export_sfc } from "./index-DKaFsuse.js";
import { S as SongItem } from "./SongItem-CoswpGn6.js";
import { _ as __unplugin_components_2 } from "./Drawer-BEJ8Ydua.js";
import { _ as __unplugin_components_2$2 } from "./Avatar-rQ2og-6c.js";
import { _ as __unplugin_components_2$1 } from "./Ellipsis-D4R5dIX2.js";
import { N as NImage } from "./Image-DXClIklC.js";
function getListByCat(params) {
return request.get("/top/playlist", {
params
});
}
function getListDetail(id) {
return request.get("/playlist/detail", { params: { id } });
}
function getAlbum(id) {
return request.get("/album", { params: { id } });
}
const _hoisted_1 = { class: "music-page" };
const _hoisted_2 = { class: "music-header h-12 flex items-center justify-between" };
const _hoisted_3 = { class: "music-title" };
const _hoisted_4 = { class: "music-content" };
const _hoisted_5 = { class: "music-info" };
const _hoisted_6 = { class: "music-cover" };
const _hoisted_7 = {
key: 0,
class: "creator-info"
};
const _hoisted_8 = { class: "creator-name" };
const _hoisted_9 = {
key: 0,
class: "music-desc"
};
const _hoisted_10 = { class: "music-list-container" };
const _hoisted_11 = { class: "music-list" };
const _hoisted_12 = { class: "music-list-content" };
const _hoisted_13 = {
key: 0,
class: "loading-more"
};
const pageSize = 20;
const _sfc_main = /* @__PURE__ */ defineComponent({
__name: "MusicList",
props: {
show: { type: Boolean },
name: {},
songList: {},
loading: { type: Boolean, default: false },
listInfo: {},
cover: { type: Boolean, default: true }
},
emits: ["update:show", "update:loading"],
setup(__props, { emit: __emit }) {
const store = useStore();
const props = __props;
const emit = __emit;
const page = ref(0);
const isLoadingMore = ref(false);
const displayedSongs = ref([]);
const loadingList = ref(false);
const total = computed(() => {
if (props.listInfo?.trackIds) {
return props.listInfo.trackIds.length;
}
return props.songList.length;
});
const formatDetail = computed(() => (detail) => {
const song = {
artists: detail.ar,
name: detail.al.name,
id: detail.al.id
};
detail.song = song;
detail.picUrl = detail.al.picUrl;
return detail;
});
const handlePlay = () => {
const tracks = props.songList || [];
store.commit(
"setPlayList",
tracks.map((item) => ({
...item,
picUrl: item.al.picUrl,
song: {
artists: item.ar
}
}))
);
};
const close = () => {
emit("update:show", false);
};
const loadMoreSongs = async () => {
if (isLoadingMore.value || displayedSongs.value.length >= total.value) return;
isLoadingMore.value = true;
try {
if (props.listInfo?.trackIds) {
const start = page.value * pageSize;
const end = Math.min((page.value + 1) * pageSize, total.value);
const trackIds = props.listInfo.trackIds.slice(start, end).map((item) => item.id);
if (trackIds.length > 0) {
const { data } = await getMusicDetail(trackIds);
displayedSongs.value = [...displayedSongs.value, ...data.songs];
page.value++;
}
} else {
const start = page.value * pageSize;
const end = Math.min((page.value + 1) * pageSize, props.songList.length);
const newSongs = props.songList.slice(start, end);
displayedSongs.value = [...displayedSongs.value, ...newSongs];
page.value++;
}
} catch (error) {
console.error("加载歌曲失败:", error);
} finally {
isLoadingMore.value = false;
loadingList.value = false;
}
};
const getItemAnimationDelay = (index) => {
const currentPageIndex = index % pageSize;
return setAnimationDelay(currentPageIndex, 20);
};
const handleScroll = (e) => {
const target = e.target;
if (!target) return;
const { scrollTop, scrollHeight, clientHeight } = target;
if (scrollHeight - scrollTop - clientHeight < 100 && !isLoadingMore.value) {
loadMoreSongs();
}
};
watch(
() => props.show,
(newVal) => {
loadingList.value = newVal;
if (!props.cover) {
loadingList.value = false;
}
}
);
watch(
() => props.songList,
(newSongs) => {
page.value = 0;
displayedSongs.value = newSongs.slice(0, pageSize);
if (newSongs.length > pageSize) {
page.value = 1;
}
loadingList.value = false;
},
{ immediate: true }
);
return (_ctx, _cache) => {
const _component_n_ellipsis = __unplugin_components_2$1;
const _component_n_image = NImage;
const _component_n_avatar = __unplugin_components_2$2;
const _component_n_scrollbar = Scrollbar;
const _component_n_spin = __unplugin_components_0;
const _component_n_drawer = __unplugin_components_2;
return openBlock(), createBlock(_component_n_drawer, {
show: _ctx.show,
height: unref(isMobile) ? "100%" : "80%",
placement: "bottom",
"block-scroll": "",
"mask-closable": "",
style: { backgroundColor: "transparent" },
to: `#layout-main`,
onMaskClick: close
}, {
default: withCtx(() => [
createBaseVNode("div", _hoisted_1, [
createBaseVNode("div", _hoisted_2, [
createVNode(_component_n_ellipsis, { "line-clamp": 1 }, {
default: withCtx(() => [
createBaseVNode("div", _hoisted_3, toDisplayString(_ctx.name), 1)
]),
_: 1
}),
createBaseVNode("div", { class: "music-close" }, [
createBaseVNode("i", {
class: "icon iconfont icon-icon_error",
onClick: close
})
])
]),
createBaseVNode("div", _hoisted_4, [
createBaseVNode("div", _hoisted_5, [
createBaseVNode("div", _hoisted_6, [
createVNode(_component_n_image, {
src: unref(getImgUrl)(_ctx.cover ? _ctx.listInfo?.coverImgUrl : unref(displayedSongs)[0]?.picUrl, "500y500"),
class: normalizeClass(["cover-img", unref(setAnimationClass)("animate__fadeIn")]),
"preview-disabled": "",
"object-fit": "cover"
}, null, 8, ["src", "class"])
]),
_ctx.listInfo?.creator ? (openBlock(), createElementBlock("div", _hoisted_7, [
createVNode(_component_n_avatar, {
round: "",
size: 24,
src: unref(getImgUrl)(_ctx.listInfo.creator.avatarUrl, "50y50")
}, null, 8, ["src"]),
createBaseVNode("span", _hoisted_8, toDisplayString(_ctx.listInfo.creator.nickname), 1)
])) : createCommentVNode("", true),
createVNode(_component_n_scrollbar, { style: { "max-height": "200" } }, {
default: withCtx(() => [
_ctx.listInfo?.description ? (openBlock(), createElementBlock("div", _hoisted_9, toDisplayString(_ctx.listInfo.description), 1)) : createCommentVNode("", true),
createVNode(PlayBottom)
]),
_: 1
})
]),
createBaseVNode("div", _hoisted_10, [
createBaseVNode("div", _hoisted_11, [
createVNode(_component_n_scrollbar, { onScroll: handleScroll }, {
default: withCtx(() => [
createVNode(_component_n_spin, {
show: unref(loadingList) || _ctx.loading
}, {
default: withCtx(() => [
createBaseVNode("div", _hoisted_12, [
(openBlock(true), createElementBlock(Fragment, null, renderList(unref(displayedSongs), (item, index) => {
return openBlock(), createElementBlock("div", {
key: item.id,
class: normalizeClass(["double-item", unref(setAnimationClass)("animate__bounceInUp")]),
style: normalizeStyle(getItemAnimationDelay(index))
}, [
createVNode(SongItem, {
item: unref(formatDetail)(item),
onPlay: handlePlay
}, null, 8, ["item"])
], 6);
}), 128)),
unref(isLoadingMore) ? (openBlock(), createElementBlock("div", _hoisted_13, "加载更多...")) : createCommentVNode("", true),
createVNode(PlayBottom)
])
]),
_: 1
}, 8, ["show"])
]),
_: 1
})
]),
createVNode(PlayBottom)
])
])
])
]),
_: 1
}, 8, ["show", "height"]);
};
}
});
const MusicList = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-1b137c3d"]]);
export {
MusicList as M,
getListDetail as a,
getListByCat as b,
getAlbum as g
};

Binary file not shown.

View File

@@ -0,0 +1,177 @@
.mv-detail[data-v-f4c63e83] {
height: 100%;
--tw-bg-opacity: 1;
background-color: rgb(255 255 255 / var(--tw-bg-opacity, 1));
}
.mv-detail[data-v-f4c63e83]:is(.dark *) {
--tw-bg-opacity: 1;
background-color: rgb(0 0 0 / var(--tw-bg-opacity, 1));
}
.mv-detail-title[data-v-f4c63e83] {
position: fixed;
top: 0px;
left: 0px;
right: 0px;
z-index: 10;
padding: 1rem;
transition-property: opacity;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-duration: 300ms;
background: linear-gradient(to bottom, rgba(0, 0, 0, 0.7), transparent);
}
.mv-detail-title .title[data-v-f4c63e83] {
font-size: 1.125rem;
line-height: 1.75rem;
font-weight: 700;
--tw-text-opacity: 1;
color: rgb(255 255 255 / var(--tw-text-opacity, 1));
}
.video-container[data-v-f4c63e83] {
position: relative;
height: 100%;
width: 100%;
}
.video-container .video-player[data-v-f4c63e83] {
height: 100%;
width: 100%;
--tw-bg-opacity: 1;
background-color: rgb(0 0 0 / var(--tw-bg-opacity, 1));
-o-object-fit: contain;
object-fit: contain;
}
.video-container .play-hint[data-v-f4c63e83] {
position: absolute;
inset: 0px;
display: flex;
align-items: center;
justify-content: center;
background-color: rgb(0 0 0 / var(--tw-bg-opacity, 1));
--tw-bg-opacity: 0.5;
}
.video-container .play-hint .n-button[data-v-f4c63e83] {
--tw-text-opacity: 1;
color: rgb(255 255 255 / var(--tw-text-opacity, 1));
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-duration: 150ms;
}
.video-container .play-hint .n-button[data-v-f4c63e83]:hover {
--tw-text-opacity: 1;
color: rgb(34 197 94 / var(--tw-text-opacity, 1));
}
.video-container .custom-controls[data-v-f4c63e83] {
position: absolute;
bottom: 0px;
left: 0px;
right: 0px;
padding: 1rem;
transition-property: opacity;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-duration: 300ms;
background: linear-gradient(to top, rgba(0, 0, 0, 0.7), transparent);
}
.video-container .custom-controls .controls-main[data-v-f4c63e83] {
display: flex;
align-items: center;
justify-content: space-between;
}
.video-container .custom-controls .controls-main .left-controls[data-v-f4c63e83],
.video-container .custom-controls .controls-main .right-controls[data-v-f4c63e83] {
display: flex;
align-items: center;
gap: 0.5rem;
}
.video-container .custom-controls .controls-main .left-controls .n-button[data-v-f4c63e83],
.video-container .custom-controls .controls-main .right-controls .n-button[data-v-f4c63e83] {
--tw-text-opacity: 1;
color: rgb(255 255 255 / var(--tw-text-opacity, 1));
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-duration: 150ms;
}
.video-container .custom-controls .controls-main .left-controls .n-button[data-v-f4c63e83]:hover,
.video-container .custom-controls .controls-main .right-controls .n-button[data-v-f4c63e83]:hover {
--tw-text-opacity: 1;
color: rgb(34 197 94 / var(--tw-text-opacity, 1));
}
.video-container .custom-controls .controls-main .left-controls .time-display[data-v-f4c63e83],
.video-container .custom-controls .controls-main .right-controls .time-display[data-v-f4c63e83] {
margin-left: 1rem;
font-size: 0.875rem;
line-height: 1.25rem;
--tw-text-opacity: 1;
color: rgb(255 255 255 / var(--tw-text-opacity, 1));
}
.mode-hint[data-v-f4c63e83] {
position: absolute;
top: 50%;
left: 50%;
display: flex;
--tw-translate-x: -50%;
--tw-translate-y: -50%;
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
flex-direction: column;
align-items: center;
}
.mode-hint .mode-icon[data-v-f4c63e83] {
margin-bottom: 0.5rem;
--tw-text-opacity: 1;
color: rgb(255 255 255 / var(--tw-text-opacity, 1));
}
.mode-hint .mode-text[data-v-f4c63e83] {
font-size: 0.875rem;
line-height: 1.25rem;
--tw-text-opacity: 1;
color: rgb(255 255 255 / var(--tw-text-opacity, 1));
}
.custom-slider[data-v-f4c63e83] .n-slider {
--n-rail-height: 4px;
--n-rail-color: rgba(255, 255, 255, 0.2);
--n-fill-color: #10b981;
--n-handle-size: 12px;
--n-handle-color: #10b981;
}
.progress-bar[data-v-f4c63e83] {
margin-bottom: 1rem;
}
.progress-bar .progress-rail[data-v-f4c63e83] {
position: relative;
height: 0.25rem;
width: 100%;
--tw-bg-opacity: 1;
background-color: rgb(75 85 99 / var(--tw-bg-opacity, 1));
}
.progress-bar .progress-rail .progress-buffer[data-v-f4c63e83] {
position: absolute;
top: 0px;
left: 0px;
height: 100%;
--tw-bg-opacity: 1;
background-color: rgb(156 163 175 / var(--tw-bg-opacity, 1));
}
.volume-control[data-v-f4c63e83] {
display: flex;
align-items: center;
gap: 0.5rem;
}
.volume-control .volume-slider[data-v-f4c63e83] {
width: 100px;
}
.controls-hidden[data-v-f4c63e83] {
opacity: 0;
pointer-events: none;
}
.cursor-hidden[data-v-f4c63e83] {
cursor: none;
}
.title-hidden[data-v-f4c63e83] {
opacity: 0;
}
.fade-enter-active[data-v-f4c63e83],
.fade-leave-active[data-v-f4c63e83] {
transition: opacity 0.3s ease;
}
.fade-enter-from[data-v-f4c63e83],
.fade-leave-to[data-v-f4c63e83] {
opacity: 0;
}

Binary file not shown.

View File

@@ -0,0 +1,670 @@
import { ad as request, d as defineComponent, r as ref, E as watch, o as onMounted, a1 as onUnmounted, G as computed, O as createBlock, f as withCtx, g as useStore, j as openBlock, b as createBaseVNode, n as normalizeClass, c as createElementBlock, e as createVNode, u as unref, B as Button, T as createCommentVNode, a2 as normalizeStyle, k as createTextVNode, t as toDisplayString, ak as Transition, M as nextTick, aj as __unplugin_components_0$1, _ as _export_sfc } from "./index-DKaFsuse.js";
import { N as NIcon } from "./Icon-DucaliTK.js";
import { _ as __unplugin_components_0 } from "./Slider-BA6NituQ.js";
import { _ as __unplugin_components_3 } from "./Image-DXClIklC.js";
import { _ as __unplugin_components_2 } from "./Drawer-BEJ8Ydua.js";
import { _ as __unplugin_components_2$1 } from "./Ellipsis-D4R5dIX2.js";
const getTopMv = (params) => {
return request({
url: "/mv/all",
method: "get",
params
});
};
const getAllMv = (params) => {
return request({
url: "/mv/all",
method: "get",
params
});
};
const getMvUrl = (id) => {
return request.get("/mv/url", {
params: {
id
}
});
};
const _hoisted_1 = { class: "mv-detail" };
const _hoisted_2 = ["src"];
const _hoisted_3 = { class: "progress-bar custom-slider" };
const _hoisted_4 = { class: "progress-rail" };
const _hoisted_5 = { class: "controls-main" };
const _hoisted_6 = { class: "left-controls" };
const _hoisted_7 = {
key: 1,
class: "ri-skip-back-line"
};
const _hoisted_8 = {
key: 1,
class: "ri-skip-forward-line"
};
const _hoisted_9 = { class: "time-display" };
const _hoisted_10 = { class: "right-controls" };
const _hoisted_11 = {
key: 0,
class: "volume-control custom-slider"
};
const _hoisted_12 = {
key: 0,
class: "mode-hint"
};
const _hoisted_13 = { class: "mode-text" };
const _hoisted_14 = { class: "title" };
const _sfc_main = /* @__PURE__ */ defineComponent({
__name: "MvPlayer",
props: {
show: { type: Boolean, default: false },
currentMv: { default: void 0 },
noList: { type: Boolean, default: false }
},
emits: ["update:show", "next", "prev"],
setup(__props, { emit: __emit }) {
const PLAY_MODE = {
Single: "single",
Auto: "auto"
};
const props = __props;
const emit = __emit;
const store = useStore();
const mvUrl = ref();
const playMode = ref(PLAY_MODE.Auto);
const videoRef = ref();
const isPlaying = ref(false);
const currentTime = ref(0);
const duration = ref(0);
const progress = ref(0);
const bufferedProgress = ref(0);
const volume = ref(100);
const showControls = ref(true);
let controlsTimer = null;
const formatTime = (seconds) => {
const minutes = Math.floor(seconds / 60);
const remainingSeconds = Math.floor(seconds % 60);
return `${minutes.toString().padStart(2, "0")}:${remainingSeconds.toString().padStart(2, "0")}`;
};
const togglePlay = () => {
if (!videoRef.value) return;
if (isPlaying.value) {
videoRef.value.pause();
} else {
videoRef.value.play();
}
resetCursorTimer();
};
const toggleMute = () => {
if (!videoRef.value) return;
if (volume.value === 0) {
volume.value = 100;
} else {
volume.value = 0;
}
};
watch(volume, (newVolume) => {
if (videoRef.value) {
videoRef.value.volume = newVolume / 100;
}
});
const handleProgressChange = (value) => {
if (!videoRef.value || !duration.value) return;
const newTime = value / 100 * duration.value;
videoRef.value.currentTime = newTime;
};
const handleTimeUpdate = () => {
if (!videoRef.value) return;
currentTime.value = videoRef.value.currentTime;
if (!isDragging.value) {
progress.value = currentTime.value / duration.value * 100;
}
if (videoRef.value.buffered.length > 0) {
bufferedProgress.value = videoRef.value.buffered.end(0) / duration.value * 100;
}
};
const handleLoadedMetadata = () => {
if (!videoRef.value) return;
duration.value = videoRef.value.duration;
};
const resetControlsTimer = () => {
if (controlsTimer) {
clearTimeout(controlsTimer);
}
showControls.value = true;
controlsTimer = setTimeout(() => {
if (isPlaying.value) {
showControls.value = false;
}
}, 3e3);
};
const handleMouseMove = () => {
resetControlsTimer();
resetCursorTimer();
};
onMounted(() => {
document.addEventListener("mousemove", handleMouseMove);
});
onUnmounted(() => {
document.removeEventListener("mousemove", handleMouseMove);
if (controlsTimer) {
clearTimeout(controlsTimer);
}
if (cursorTimer) {
clearTimeout(cursorTimer);
}
unlockScreenOrientation();
});
watch(
() => props.currentMv,
async (newMv) => {
if (newMv) {
await loadMvUrl(newMv);
}
}
);
const autoPlayBlocked = ref(false);
const playLoading = ref(false);
const loadMvUrl = async (mv) => {
playLoading.value = true;
autoPlayBlocked.value = false;
try {
const res = await getMvUrl(mv.id);
mvUrl.value = res.data.data.url;
await nextTick();
if (videoRef.value) {
try {
await videoRef.value.play();
} catch (error) {
console.warn("自动播放失败,可能需要用户交互:", error);
autoPlayBlocked.value = true;
}
}
} catch (error) {
console.error("加载MV地址失败:", error);
} finally {
playLoading.value = false;
}
};
const handleClose = () => {
emit("update:show", false);
if (store.state.playMusicUrl) {
store.commit("setIsPlay", true);
}
};
const handleEnded = () => {
if (playMode.value === PLAY_MODE.Single) {
if (props.currentMv) {
loadMvUrl(props.currentMv);
}
} else {
emit("next", (value) => {
nextLoading.value = value;
});
}
};
const togglePlayMode = () => {
playMode.value = playMode.value === PLAY_MODE.Auto ? PLAY_MODE.Single : PLAY_MODE.Auto;
showModeHint.value = true;
setTimeout(() => {
showModeHint.value = false;
}, 1500);
};
const isDragging = ref(false);
const videoContainerRef = ref();
const isFullscreen = ref(false);
const checkFullscreenAPI = () => {
const doc = document;
return {
requestFullscreen: videoContainerRef.value?.requestFullscreen || videoContainerRef.value?.webkitRequestFullscreen || videoContainerRef.value?.mozRequestFullScreen || videoContainerRef.value?.msRequestFullscreen,
exitFullscreen: doc.exitFullscreen || doc.webkitExitFullscreen || doc.mozCancelFullScreen || doc.msExitFullscreen,
fullscreenElement: doc.fullscreenElement || doc.webkitFullscreenElement || doc.mozFullScreenElement || doc.msFullscreenElement,
fullscreenEnabled: doc.fullscreenEnabled || doc.webkitFullscreenEnabled || doc.mozFullScreenEnabled || doc.msFullscreenEnabled
};
};
const lockScreenOrientation = async () => {
try {
if ("orientation" in screen) {
await screen.orientation.lock("landscape");
}
} catch (error) {
console.warn("无法锁定屏幕方向:", error);
}
};
const unlockScreenOrientation = () => {
try {
if ("orientation" in screen) {
screen.orientation.unlock();
}
} catch (error) {
console.warn("无法解锁屏幕方向:", error);
}
};
const toggleFullscreen = async () => {
const api = checkFullscreenAPI();
if (!api.fullscreenEnabled) {
console.warn("全屏API不可用");
return;
}
try {
if (!api.fullscreenElement) {
await videoContainerRef.value?.requestFullscreen();
isFullscreen.value = true;
if (window.innerWidth <= 768) {
await lockScreenOrientation();
}
} else {
await document.exitFullscreen();
isFullscreen.value = false;
if (window.innerWidth <= 768) {
unlockScreenOrientation();
}
}
} catch (error) {
console.error("切换全屏失败:", error);
}
};
const handleFullscreenChange = () => {
const api = checkFullscreenAPI();
isFullscreen.value = !!api.fullscreenElement;
};
onMounted(() => {
document.addEventListener("fullscreenchange", handleFullscreenChange);
document.addEventListener("webkitfullscreenchange", handleFullscreenChange);
document.addEventListener("mozfullscreenchange", handleFullscreenChange);
document.addEventListener("MSFullscreenChange", handleFullscreenChange);
});
onUnmounted(() => {
document.removeEventListener("fullscreenchange", handleFullscreenChange);
document.removeEventListener("webkitfullscreenchange", handleFullscreenChange);
document.removeEventListener("mozfullscreenchange", handleFullscreenChange);
document.removeEventListener("MSFullscreenChange", handleFullscreenChange);
});
const handleKeyPress = (e) => {
if (e.key === "f" || e.key === "F") {
toggleFullscreen();
}
};
onMounted(() => {
document.addEventListener("keydown", handleKeyPress);
});
onUnmounted(() => {
document.removeEventListener("keydown", handleKeyPress);
});
const showModeHint = ref(false);
const prevLoading = ref(false);
const nextLoading = ref(false);
const handlePrev = () => {
prevLoading.value = true;
emit("prev", (value) => {
prevLoading.value = value;
});
};
const handleNext = () => {
nextLoading.value = true;
emit("next", (value) => {
nextLoading.value = value;
});
};
const showCursor = ref(true);
let cursorTimer = null;
const resetCursorTimer = () => {
if (cursorTimer) {
clearTimeout(cursorTimer);
}
showCursor.value = true;
if (isPlaying.value && !showControls.value) {
cursorTimer = setTimeout(() => {
showCursor.value = false;
}, 3e3);
}
};
watch(isPlaying, (newValue) => {
if (!newValue) {
showCursor.value = true;
if (cursorTimer) {
clearTimeout(cursorTimer);
}
} else {
resetCursorTimer();
}
});
watch(showControls, (newValue) => {
if (newValue) {
showCursor.value = true;
if (cursorTimer) {
clearTimeout(cursorTimer);
}
} else {
resetCursorTimer();
}
});
const isMobile = computed(() => store.state.isMobile);
return (_ctx, _cache) => {
const _component_n_spin = __unplugin_components_0$1;
const _component_n_ellipsis = __unplugin_components_2$1;
const _component_n_drawer = __unplugin_components_2;
return openBlock(), createBlock(_component_n_drawer, {
show: _ctx.show,
height: "100%",
placement: "bottom",
"z-index": 999999999,
to: `#layout-main`
}, {
default: withCtx(() => [
createBaseVNode("div", _hoisted_1, [
createBaseVNode("div", {
ref_key: "videoContainerRef",
ref: videoContainerRef,
class: normalizeClass(["video-container", { "cursor-hidden": !showCursor.value }])
}, [
createBaseVNode("video", {
ref_key: "videoRef",
ref: videoRef,
src: mvUrl.value,
class: "video-player",
onEnded: handleEnded,
onTimeupdate: handleTimeUpdate,
onLoadedmetadata: handleLoadedMetadata,
onPlay: _cache[0] || (_cache[0] = ($event) => isPlaying.value = true),
onPause: _cache[1] || (_cache[1] = ($event) => isPlaying.value = false),
onClick: togglePlay
}, null, 40, _hoisted_2),
autoPlayBlocked.value ? (openBlock(), createElementBlock("div", {
key: 0,
class: "play-hint",
onClick: togglePlay
}, [
createVNode(unref(Button), {
quaternary: "",
circle: "",
size: "large"
}, {
icon: withCtx(() => [
createVNode(unref(NIcon), { size: "48" }, {
default: withCtx(() => _cache[4] || (_cache[4] = [
createBaseVNode("i", { class: "ri-play-circle-line" }, null, -1)
])),
_: 1
})
]),
_: 1
})
])) : createCommentVNode("", true),
createBaseVNode("div", {
class: normalizeClass(["custom-controls", { "controls-hidden": !showControls.value }])
}, [
createBaseVNode("div", _hoisted_3, [
createVNode(unref(__unplugin_components_0), {
value: progress.value,
"onUpdate:value": [
_cache[2] || (_cache[2] = ($event) => progress.value = $event),
handleProgressChange
],
min: 0,
max: 100,
tooltip: false,
step: 0.1
}, {
rail: withCtx(() => [
createBaseVNode("div", _hoisted_4, [
createBaseVNode("div", {
class: "progress-buffer",
style: normalizeStyle({ width: `${bufferedProgress.value}%` })
}, null, 4)
])
]),
_: 1
}, 8, ["value"])
]),
createBaseVNode("div", _hoisted_5, [
createBaseVNode("div", _hoisted_6, [
!props.noList ? (openBlock(), createBlock(unref(__unplugin_components_3), {
key: 0,
placement: "top"
}, {
trigger: withCtx(() => [
createVNode(unref(Button), {
quaternary: "",
circle: "",
onClick: handlePrev
}, {
icon: withCtx(() => [
createVNode(unref(NIcon), { size: "24" }, {
default: withCtx(() => [
prevLoading.value ? (openBlock(), createBlock(_component_n_spin, {
key: 0,
size: "small"
})) : (openBlock(), createElementBlock("i", _hoisted_7))
]),
_: 1
})
]),
_: 1
})
]),
default: withCtx(() => [
_cache[5] || (_cache[5] = createTextVNode(" 上一个 "))
]),
_: 1
})) : createCommentVNode("", true),
createVNode(unref(__unplugin_components_3), { placement: "top" }, {
trigger: withCtx(() => [
createVNode(unref(Button), {
quaternary: "",
circle: "",
onClick: togglePlay
}, {
icon: withCtx(() => [
createVNode(unref(NIcon), { size: "24" }, {
default: withCtx(() => [
playLoading.value ? (openBlock(), createBlock(_component_n_spin, {
key: 0,
size: "small"
})) : (openBlock(), createElementBlock("i", {
key: 1,
class: normalizeClass(isPlaying.value ? "ri-pause-line" : "ri-play-line")
}, null, 2))
]),
_: 1
})
]),
_: 1
})
]),
default: withCtx(() => [
createTextVNode(" " + toDisplayString(isPlaying.value ? "暂停" : "播放"), 1)
]),
_: 1
}),
!props.noList ? (openBlock(), createBlock(unref(__unplugin_components_3), {
key: 1,
placement: "top"
}, {
trigger: withCtx(() => [
createVNode(unref(Button), {
quaternary: "",
circle: "",
onClick: handleNext
}, {
icon: withCtx(() => [
createVNode(unref(NIcon), { size: "24" }, {
default: withCtx(() => [
nextLoading.value ? (openBlock(), createBlock(_component_n_spin, {
key: 0,
size: "small"
})) : (openBlock(), createElementBlock("i", _hoisted_8))
]),
_: 1
})
]),
_: 1
})
]),
default: withCtx(() => [
_cache[6] || (_cache[6] = createTextVNode(" 下一个 "))
]),
_: 1
})) : createCommentVNode("", true),
createBaseVNode("div", _hoisted_9, toDisplayString(formatTime(currentTime.value)) + " / " + toDisplayString(formatTime(duration.value)), 1)
]),
createBaseVNode("div", _hoisted_10, [
!isMobile.value ? (openBlock(), createElementBlock("div", _hoisted_11, [
createVNode(unref(__unplugin_components_3), { placement: "top" }, {
trigger: withCtx(() => [
createVNode(unref(Button), {
quaternary: "",
circle: "",
onClick: toggleMute
}, {
icon: withCtx(() => [
createVNode(unref(NIcon), { size: "24" }, {
default: withCtx(() => [
createBaseVNode("i", {
class: normalizeClass(volume.value === 0 ? "ri-volume-mute-line" : "ri-volume-up-line")
}, null, 2)
]),
_: 1
})
]),
_: 1
})
]),
default: withCtx(() => [
createTextVNode(" " + toDisplayString(volume.value === 0 ? "取消静音" : "静音"), 1)
]),
_: 1
}),
createVNode(unref(__unplugin_components_0), {
value: volume.value,
"onUpdate:value": _cache[3] || (_cache[3] = ($event) => volume.value = $event),
min: 0,
max: 100,
tooltip: false,
class: "volume-slider"
}, null, 8, ["value"])
])) : createCommentVNode("", true),
!props.noList ? (openBlock(), createBlock(unref(__unplugin_components_3), {
key: 1,
placement: "top"
}, {
trigger: withCtx(() => [
createVNode(unref(Button), {
quaternary: "",
circle: "",
class: "play-mode-btn",
onClick: togglePlayMode
}, {
icon: withCtx(() => [
createVNode(unref(NIcon), { size: "24" }, {
default: withCtx(() => [
createBaseVNode("i", {
class: normalizeClass(
playMode.value === "single" ? "ri-repeat-one-line" : "ri-play-list-line"
)
}, null, 2)
]),
_: 1
})
]),
_: 1
})
]),
default: withCtx(() => [
createTextVNode(" " + toDisplayString(playMode.value === "single" ? "单曲循环" : "列表循环"), 1)
]),
_: 1
})) : createCommentVNode("", true),
createVNode(unref(__unplugin_components_3), { placement: "top" }, {
trigger: withCtx(() => [
createVNode(unref(Button), {
quaternary: "",
circle: "",
onClick: toggleFullscreen
}, {
icon: withCtx(() => [
createVNode(unref(NIcon), { size: "24" }, {
default: withCtx(() => [
createBaseVNode("i", {
class: normalizeClass(isFullscreen.value ? "ri-fullscreen-exit-line" : "ri-fullscreen-line")
}, null, 2)
]),
_: 1
})
]),
_: 1
})
]),
default: withCtx(() => [
createTextVNode(" " + toDisplayString(isFullscreen.value ? "退出全屏" : "全屏"), 1)
]),
_: 1
}),
createVNode(unref(__unplugin_components_3), { placement: "top" }, {
trigger: withCtx(() => [
createVNode(unref(Button), {
quaternary: "",
circle: "",
onClick: handleClose
}, {
icon: withCtx(() => [
createVNode(unref(NIcon), { size: "24" }, {
default: withCtx(() => _cache[7] || (_cache[7] = [
createBaseVNode("i", { class: "ri-close-line" }, null, -1)
])),
_: 1
})
]),
_: 1
})
]),
default: withCtx(() => [
_cache[8] || (_cache[8] = createTextVNode(" 关闭 "))
]),
_: 1
})
])
])
], 2),
createVNode(Transition, { name: "fade" }, {
default: withCtx(() => [
showModeHint.value ? (openBlock(), createElementBlock("div", _hoisted_12, [
createVNode(unref(NIcon), {
size: "48",
class: "mode-icon"
}, {
default: withCtx(() => [
createBaseVNode("i", {
class: normalizeClass(playMode.value === "single" ? "ri-repeat-one-line" : "ri-play-list-line")
}, null, 2)
]),
_: 1
}),
createBaseVNode("div", _hoisted_13, toDisplayString(playMode.value === "single" ? "单曲循环" : "自动播放下一个"), 1)
])) : createCommentVNode("", true)
]),
_: 1
})
], 2),
createBaseVNode("div", {
class: normalizeClass(["mv-detail-title", { "title-hidden": !showControls.value }])
}, [
createBaseVNode("div", _hoisted_14, [
createVNode(_component_n_ellipsis, null, {
default: withCtx(() => [
createTextVNode(toDisplayString(_ctx.currentMv?.name), 1)
]),
_: 1
})
])
], 2)
])
]),
_: 1
}, 8, ["show"]);
};
}
});
const MvPlayer = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-f4c63e83"]]);
export {
MvPlayer as M,
getAllMv as a,
getTopMv as g
};

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@@ -0,0 +1,502 @@
@keyframes round-03432cea {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
.drawer-back[data-v-03432cea] {
position: absolute;
background-size: cover;
background-position: center;
z-index: -1;
width: 200%;
height: 200%;
top: -50%;
left: -50%;
}
.drawer-back.paused[data-v-03432cea] {
animation-play-state: paused;
}
#drawer-target[data-v-03432cea] {
position: absolute;
top: 0px;
left: 0px;
display: flex;
height: 100%;
width: 100%;
align-items: center;
justify-content: center;
overflow: hidden;
border-radius: 0.25rem;
padding-left: 6rem;
padding-right: 6rem;
padding-bottom: 2rem;
animation-duration: 300ms;
}
#drawer-target .music-img[data-v-03432cea] {
margin-right: 4rem;
display: flex;
flex: 1 1 0%;
flex-direction: column;
justify-content: center;
max-width: 360px;
max-height: 360px;
}
#drawer-target .music-img .img[data-v-03432cea] {
height: 100%;
width: 100%;
border-radius: 0.75rem;
--tw-shadow: 0 25px 50px -12px rgb(0 0 0 / 0.25);
--tw-shadow-colored: 0 25px 50px -12px var(--tw-shadow-color);
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
}
#drawer-target .music-content[data-v-03432cea] {
position: relative;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
#drawer-target .music-content-name[data-v-03432cea] {
padding-bottom: 0.25rem;
padding-top: 1rem;
font-size: 1.25rem;
line-height: 1.75rem;
font-weight: 700;
}
#drawer-target .music-content-singer[data-v-03432cea] {
font-size: 1rem;
line-height: 1.5rem;
}
#drawer-target .music-content-time[data-v-03432cea] {
display: none;
display: flex;
align-items: center;
justify-content: center;
}
#drawer-target .music-lrc[data-v-03432cea] {
background-color: inherit;
width: 500px;
height: 550px;
-webkit-mask-image: linear-gradient(to bottom, transparent 0%, black 10%, black 90%, transparent 100%);
mask-image: linear-gradient(to bottom, transparent 0%, black 10%, black 90%, transparent 100%);
}
#drawer-target .music-lrc-text[data-v-03432cea] {
cursor: pointer;
padding-left: 0.5rem;
padding-right: 0.5rem;
padding-top: 1rem;
padding-bottom: 1rem;
font-size: 1.5rem;
line-height: 2rem;
font-weight: 700;
transition: all 0.3s ease;
background-color: transparent;
}
#drawer-target .music-lrc-text span[data-v-03432cea] {
background-clip: text !important;
-webkit-background-clip: text !important;
padding-right: 30px;
}
#drawer-target .music-lrc-text-tr[data-v-03432cea] {
font-weight: 400;
opacity: 0.7;
color: var(--text-color-primary);
}
#drawer-target .music-lrc .hover-text[data-v-03432cea]:hover {
border-radius: 0.75rem;
font-weight: 700;
opacity: 1;
background-color: var(--hover-bg-color);
}
#drawer-target .music-lrc .hover-text:hover span[data-v-03432cea] {
color: var(--text-color-active) !important;
}
.mobile #drawer-target[data-v-03432cea] {
flex-direction: column;
justify-content: flex-start;
padding: 1rem;
padding-top: 2rem;
}
.mobile #drawer-target .music-img[data-v-03432cea] {
display: none;
}
.mobile #drawer-target .music-lrc[data-v-03432cea] {
height: calc(100vh - 260px) !important;
width: 100vw;
}
.mobile #drawer-target .music-lrc span[data-v-03432cea] {
padding-right: 0px !important;
}
.mobile #drawer-target .music-lrc-text[data-v-03432cea] {
text-align: center;
font-size: 1.25rem;
line-height: 1.75rem;
}
.music-drawer[data-v-03432cea] {
transition: none;
}.text-ellipsis[data-v-5d6cadda] {
width: 100%;
}
.music-play-bar[data-v-5d6cadda] {
position: absolute;
bottom: 0px;
left: 0px;
box-sizing: border-box;
display: flex;
height: 5rem;
width: 100%;
align-items: center;
padding-left: 1.5rem;
padding-right: 1.5rem;
padding-bottom: 0.5rem;
padding-top: 0.75rem;
--tw-bg-opacity: 1;
background-color: rgb(255 255 255 / var(--tw-bg-opacity, 1));
--tw-shadow: 0 25px 50px -12px rgb(0 0 0 / 0.25);
--tw-shadow-colored: 0 25px 50px -12px var(--tw-shadow-color);
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
--tw-shadow-color: #d1d5db;
--tw-shadow: var(--tw-shadow-colored);
}
.music-play-bar[data-v-5d6cadda]:is(.dark *) {
--tw-bg-opacity: 1;
background-color: rgb(0 0 0 / var(--tw-bg-opacity, 1));
}
.music-play-bar[data-v-5d6cadda] {
z-index: 9999;
animation-duration: 0.5s !important;
}
.music-play-bar .music-content[data-v-5d6cadda] {
width: 160px;
margin-left: 1rem;
}
.music-play-bar .music-content-title[data-v-5d6cadda] {
font-size: 1rem;
line-height: 1.5rem;
}
.music-play-bar .music-content-name[data-v-5d6cadda] {
margin-top: 0.25rem;
font-size: 0.75rem;
line-height: 1rem;
opacity: 0.8;
}
.play-bar-opcity[data-v-5d6cadda] {
background-color: transparent !important;
box-shadow: 0 0 20px 5px rgba(0, 0, 0, 0.1137254902);
}
.play-bar-img[data-v-5d6cadda] {
height: 3.5rem;
width: 3.5rem;
border-radius: 1rem;
}
.music-buttons[data-v-5d6cadda] {
margin-left: 1.5rem;
margin-right: 1.5rem;
flex: 1 1 0%;
justify-content: center;
display: flex;
align-items: center;
}
.music-buttons .iconfont[data-v-5d6cadda] {
font-size: 1.5rem;
line-height: 2rem;
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, -webkit-backdrop-filter;
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter;
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter, -webkit-backdrop-filter;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-duration: 150ms;
}
.music-buttons .iconfont[data-v-5d6cadda]:hover {
--tw-text-opacity: 1;
color: rgb(34 197 94 / var(--tw-text-opacity, 1));
}
.music-buttons .icon[data-v-5d6cadda] {
font-size: 1.875rem;
line-height: 2.25rem;
}
.music-buttons .icon[data-v-5d6cadda]:hover {
--tw-text-opacity: 1;
color: rgb(34 197 94 / var(--tw-text-opacity, 1));
}
.music-buttons > div[data-v-5d6cadda] {
cursor: pointer;
}
.music-buttons-play[data-v-5d6cadda] {
margin-left: 1rem;
margin-right: 1rem;
display: flex;
height: 3rem;
width: 5rem;
align-items: center;
justify-content: center;
border-radius: 9999px;
--tw-text-opacity: 1;
color: rgb(107 114 128 / var(--tw-text-opacity, 1));
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, -webkit-backdrop-filter;
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter;
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter, -webkit-backdrop-filter;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-duration: 150ms;
background-color: rgb(243 244 246 / var(--tw-bg-opacity, 1));
--tw-bg-opacity: 0.6;
}
.music-buttons-play[data-v-5d6cadda]:hover {
--tw-bg-opacity: 1;
background-color: rgb(229 231 235 / var(--tw-bg-opacity, 1));
}
.audio-volume[data-v-5d6cadda] {
position: relative;
display: flex;
align-items: center;
}
.audio-volume:hover .volume-slider[data-v-5d6cadda] {
visibility: visible;
opacity: 1;
}
.audio-volume .volume-icon[data-v-5d6cadda] {
cursor: pointer;
}
.audio-volume .iconfont[data-v-5d6cadda] {
font-size: 1.5rem;
line-height: 2rem;
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, -webkit-backdrop-filter;
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter;
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter, -webkit-backdrop-filter;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-duration: 150ms;
}
.audio-volume .iconfont[data-v-5d6cadda]:hover {
--tw-text-opacity: 1;
color: rgb(34 197 94 / var(--tw-text-opacity, 1));
}
.audio-volume .volume-slider[data-v-5d6cadda] {
visibility: hidden;
position: absolute;
bottom: 30px;
left: 50%;
height: 180px;
--tw-translate-x: -50%;
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
border-radius: 0.75rem;
padding-left: 0.5rem;
padding-right: 0.5rem;
padding-top: 1rem;
padding-bottom: 1rem;
opacity: 0;
transition-property: all;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-duration: 300ms;
--tw-bg-opacity: 1;
background-color: rgb(255 255 255 / var(--tw-bg-opacity, 1));
}
.audio-volume .volume-slider[data-v-5d6cadda]:is(.dark *) {
--tw-bg-opacity: 1;
background-color: rgb(31 41 55 / var(--tw-bg-opacity, 1));
}
.audio-volume .volume-slider[data-v-5d6cadda] {
border-width: 1px;
--tw-border-opacity: 1;
border-color: rgb(229 231 235 / var(--tw-border-opacity, 1));
}
.audio-volume .volume-slider[data-v-5d6cadda]:is(.dark *) {
--tw-border-opacity: 1;
border-color: rgb(55 65 81 / var(--tw-border-opacity, 1));
}
.audio-button[data-v-5d6cadda] {
margin-left: 1rem;
margin-right: 1rem;
display: flex;
align-items: center;
}
.audio-button .iconfont[data-v-5d6cadda] {
margin: 1rem;
cursor: pointer;
font-size: 1.5rem;
line-height: 2rem;
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, -webkit-backdrop-filter;
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter;
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter, -webkit-backdrop-filter;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-duration: 150ms;
}
.audio-button .iconfont[data-v-5d6cadda]:hover {
--tw-text-opacity: 1;
color: rgb(34 197 94 / var(--tw-text-opacity, 1));
}
.music-play-list[data-v-5d6cadda] {
height: 50vh;
width: 300px;
position: relative;
overflow: hidden;
border-radius: 1.5rem;
padding-top: 0.5rem;
padding-bottom: 0.5rem;
}
.music-play-list-back[data-v-5d6cadda] {
-webkit-backdrop-filter: blur(20px);
backdrop-filter: blur(20px);
position: absolute;
top: 0px;
left: 0px;
height: 100%;
width: 100%;
background-color: rgb(255 255 255 / var(--tw-bg-opacity, 1));
--tw-bg-opacity: 0.75;
}
.music-play-list-back[data-v-5d6cadda]:is(.dark *) {
--tw-bg-opacity: 1;
background-color: rgb(0 0 0 / var(--tw-bg-opacity, 1));
}
.music-play-list-content[data-v-5d6cadda] {
margin-left: 0.5rem;
margin-right: 0.5rem;
}
.mobile .music-play-bar[data-v-5d6cadda] {
padding-left: 1rem;
padding-right: 1rem;
bottom: 70px;
}
.mobile .music-time[data-v-5d6cadda] {
display: none;
}
.mobile .ri-netease-cloud-music-line[data-v-5d6cadda] {
display: none;
}
.mobile .audio-volume[data-v-5d6cadda] {
display: none;
}
.mobile .audio-button[data-v-5d6cadda] {
margin-left: 0px;
margin-right: 0px;
}
.mobile .music-buttons[data-v-5d6cadda] {
margin: 0px;
}
.mobile .music-buttons-prev[data-v-5d6cadda], .mobile .music-buttons-next[data-v-5d6cadda] {
display: none;
}
.mobile .music-buttons-play[data-v-5d6cadda] {
margin: 0px;
}
.mobile .music-content[data-v-5d6cadda] {
flex: 1;
}
.custom-slider[data-v-5d6cadda] .n-slider {
--n-rail-height: 4px;
--n-rail-color: #e5e7eb;
--n-rail-color-dark: #374151;
--n-fill-color: #22c55e;
--n-handle-size: 12px;
--n-handle-color: #22c55e;
}
.custom-slider[data-v-5d6cadda] .n-slider.n-slider--vertical {
height: 100%;
}
.custom-slider[data-v-5d6cadda] .n-slider.n-slider--vertical .n-slider-rail {
width: 4px;
}
.custom-slider[data-v-5d6cadda] .n-slider.n-slider--vertical:hover .n-slider-rail {
width: 6px;
}
.custom-slider[data-v-5d6cadda] .n-slider.n-slider--vertical:hover .n-slider-handle {
width: 14px;
height: 14px;
}
.custom-slider[data-v-5d6cadda] .n-slider .n-slider-rail {
overflow: hidden;
transition-property: all;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-duration: 200ms;
background-color: rgb(107 114 128 / var(--tw-bg-opacity, 1)) !important;
--tw-bg-opacity: 0.1 !important;
}
.custom-slider[data-v-5d6cadda] .n-slider .n-slider-rail:is(.dark *) {
--tw-bg-opacity: 1 !important;
background-color: rgb(61 61 61 / var(--tw-bg-opacity, 1)) !important;
}
.custom-slider[data-v-5d6cadda] .n-slider .n-slider-handle {
transition-property: all;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-duration: 200ms;
opacity: 0;
}
.custom-slider[data-v-5d6cadda] .n-slider:hover .n-slider-handle {
opacity: 1;
}
.play-bar-img-wrapper[data-v-5d6cadda] {
position: relative;
height: 3.5rem;
width: 3.5rem;
cursor: pointer;
}
.play-bar-img-wrapper .hover-arrow[data-v-5d6cadda] {
position: absolute;
inset: 0px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 1rem;
opacity: 0;
transition-property: opacity;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-duration: 300ms;
background: rgba(0, 0, 0, 0.5);
}
.play-bar-img-wrapper .hover-arrow .hover-content[data-v-5d6cadda] {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.play-bar-img-wrapper .hover-arrow .hover-content i[data-v-5d6cadda] {
margin-bottom: 0.125rem;
--tw-text-opacity: 1;
color: rgb(255 255 255 / var(--tw-text-opacity, 1));
}
.play-bar-img-wrapper .hover-arrow .hover-content .hover-text[data-v-5d6cadda] {
--tw-scale-x: .9;
--tw-scale-y: .9;
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
font-size: 0.75rem;
line-height: 1rem;
--tw-text-opacity: 1;
color: rgb(255 255 255 / var(--tw-text-opacity, 1));
}
.play-bar-img-wrapper:hover .hover-arrow[data-v-5d6cadda] {
opacity: 1;
}
.tooltip-content[data-v-5d6cadda] {
padding-top: 0.25rem;
padding-bottom: 0.25rem;
padding-left: 0.5rem;
padding-right: 0.5rem;
font-size: 0.875rem;
line-height: 1.25rem;
}
.play-bar-img[data-v-5d6cadda] {
height: 3.5rem;
width: 3.5rem;
border-radius: 1rem;
}
.like-active[data-v-5d6cadda] {
--tw-text-opacity: 1 !important;
color: rgb(239 68 68 / var(--tw-text-opacity, 1)) !important;
}
.like-active[data-v-5d6cadda]:hover {
--tw-text-opacity: 1 !important;
color: rgb(220 38 38 / var(--tw-text-opacity, 1)) !important;
}
.icon-loop[data-v-5d6cadda],
.icon-single-loop[data-v-5d6cadda] {
font-size: 1.5rem;
}
.music-time .n-slider[data-v-5d6cadda] {
position: absolute;
top: 0;
left: 0;
padding: 0;
border-radius: 0;
}

Binary file not shown.

View File

@@ -0,0 +1,219 @@
.user-box[data-v-064c45e9] {
margin-left: 1rem;
display: flex;
align-items: center;
justify-content: center;
border-radius: 9999px;
font-size: 1.125rem;
line-height: 1.75rem;
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-duration: 200ms;
border-width: 1px;
--tw-border-opacity: 1;
border-color: rgb(229 231 235 / var(--tw-border-opacity, 1));
}.user-box[data-v-064c45e9]:hover {
--tw-border-opacity: 1;
border-color: rgb(156 163 175 / var(--tw-border-opacity, 1));
}.user-box[data-v-064c45e9]:is(.dark *) {
--tw-border-opacity: 1;
border-color: rgb(75 85 99 / var(--tw-border-opacity, 1));
}.user-box[data-v-064c45e9]:hover:is(.dark *) {
--tw-border-opacity: 1;
border-color: rgb(156 163 175 / var(--tw-border-opacity, 1));
}.user-box[data-v-064c45e9] {
--tw-bg-opacity: 1;
background-color: rgb(255 255 255 / var(--tw-bg-opacity, 1));
}.user-box[data-v-064c45e9]:is(.dark *) {
--tw-bg-opacity: 1;
background-color: rgb(31 41 55 / var(--tw-bg-opacity, 1));
}
.search-box[data-v-064c45e9] {
padding-bottom: 1rem;
padding-right: 1rem;
}
.search-box-input[data-v-064c45e9] {
position: relative;
}
.search-box-input[data-v-064c45e9] .n-input {
--tw-bg-opacity: 1;
background-color: rgb(249 250 251 / var(--tw-bg-opacity, 1));
}
.search-box-input[data-v-064c45e9] .n-input:is(.dark *) {
--tw-bg-opacity: 1;
background-color: rgb(0 0 0 / var(--tw-bg-opacity, 1));
}
.search-box-input[data-v-064c45e9] .n-input .n-input__input-el {
--tw-text-opacity: 1;
color: rgb(17 24 39 / var(--tw-text-opacity, 1));
}
.search-box-input[data-v-064c45e9] .n-input .n-input__input-el:is(.dark *) {
--tw-text-opacity: 1;
color: rgb(255 255 255 / var(--tw-text-opacity, 1));
}
.search-box-input[data-v-064c45e9] .n-input .n-input__prefix {
--tw-text-opacity: 1;
color: rgb(107 114 128 / var(--tw-text-opacity, 1));
}
.search-box-input[data-v-064c45e9] .n-input .n-input__prefix:is(.dark *) {
--tw-text-opacity: 1;
color: rgb(156 163 175 / var(--tw-text-opacity, 1));
}
.mobile .search-box[data-v-064c45e9] {
padding-left: 1rem;
}
.github[data-v-064c45e9] {
margin-left: 1rem;
display: flex;
height: 100%;
cursor: pointer;
align-items: center;
justify-content: center;
border-radius: 9999px;
padding-left: 0.5rem;
padding-right: 0.5rem;
font-size: 1.25rem;
line-height: 1.75rem;
--tw-text-opacity: 1;
color: rgb(17 24 39 / var(--tw-text-opacity, 1));
}
.github[data-v-064c45e9]:hover {
--tw-text-opacity: 1;
color: rgb(75 85 99 / var(--tw-text-opacity, 1));
}
.github[data-v-064c45e9]:is(.dark *) {
--tw-text-opacity: 1;
color: rgb(243 244 246 / var(--tw-text-opacity, 1));
}
.github[data-v-064c45e9]:hover:is(.dark *) {
--tw-text-opacity: 1;
color: rgb(156 163 175 / var(--tw-text-opacity, 1));
}
.github[data-v-064c45e9] {
border-width: 1px;
--tw-border-opacity: 1;
border-color: rgb(229 231 235 / var(--tw-border-opacity, 1));
--tw-bg-opacity: 1;
background-color: rgb(255 255 255 / var(--tw-bg-opacity, 1));
}
.github[data-v-064c45e9]:is(.dark *) {
--tw-border-opacity: 1;
border-color: rgb(75 85 99 / var(--tw-border-opacity, 1));
--tw-bg-opacity: 1;
background-color: rgb(0 0 0 / var(--tw-bg-opacity, 1));
}
.user-popover[data-v-064c45e9] {
min-width: 280px;
overflow: hidden;
border-radius: 0.75rem;
padding: 0px;
--tw-bg-opacity: 1;
background-color: rgb(255 255 255 / var(--tw-bg-opacity, 1));
}
.user-popover[data-v-064c45e9]:is(.dark *) {
--tw-bg-opacity: 1;
background-color: rgb(0 0 0 / var(--tw-bg-opacity, 1));
}
.user-popover[data-v-064c45e9] {
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
.user-popover .user-header[data-v-064c45e9] {
display: flex;
cursor: pointer;
align-items: center;
gap: 0.5rem;
padding: 0.75rem;
border-bottom-width: 1px;
--tw-border-opacity: 1;
border-color: rgb(243 244 246 / var(--tw-border-opacity, 1));
}
.user-popover .user-header[data-v-064c45e9]:hover {
--tw-bg-opacity: 1;
background-color: rgb(243 244 246 / var(--tw-bg-opacity, 1));
}
.user-popover .user-header[data-v-064c45e9]:is(.dark *) {
--tw-border-opacity: 1;
border-color: rgb(55 65 81 / var(--tw-border-opacity, 1));
}
.user-popover .user-header[data-v-064c45e9]:hover:is(.dark *) {
--tw-bg-opacity: 1;
background-color: rgb(55 65 81 / var(--tw-bg-opacity, 1));
}
.user-popover .user-header .username[data-v-064c45e9] {
font-size: 0.875rem;
line-height: 1.25rem;
font-weight: 500;
--tw-text-opacity: 1;
color: rgb(17 24 39 / var(--tw-text-opacity, 1));
}
.user-popover .user-header .username[data-v-064c45e9]:is(.dark *) {
--tw-text-opacity: 1;
color: rgb(229 231 235 / var(--tw-text-opacity, 1));
}
.user-popover .menu-items[data-v-064c45e9] {
padding-top: 0.25rem;
padding-bottom: 0.25rem;
}
.user-popover .menu-items .menu-item[data-v-064c45e9] {
display: flex;
cursor: pointer;
align-items: center;
padding-left: 0.75rem;
padding-right: 0.75rem;
padding-top: 0.5rem;
padding-bottom: 0.5rem;
font-size: 0.875rem;
line-height: 1.25rem;
--tw-text-opacity: 1;
color: rgb(55 65 81 / var(--tw-text-opacity, 1));
}
.user-popover .menu-items .menu-item[data-v-064c45e9]:is(.dark *) {
--tw-text-opacity: 1;
color: rgb(209 213 219 / var(--tw-text-opacity, 1));
}
.user-popover .menu-items .menu-item[data-v-064c45e9] {
transition: background-color 0.2s;
}
.user-popover .menu-items .menu-item[data-v-064c45e9]:hover {
--tw-bg-opacity: 1;
background-color: rgb(243 244 246 / var(--tw-bg-opacity, 1));
}
.user-popover .menu-items .menu-item[data-v-064c45e9]:hover:is(.dark *) {
--tw-bg-opacity: 1;
background-color: rgb(55 65 81 / var(--tw-bg-opacity, 1));
}
.user-popover .menu-items .menu-item i[data-v-064c45e9] {
margin-right: 0.25rem;
font-size: 1.125rem;
line-height: 1.75rem;
--tw-text-opacity: 1;
color: rgb(107 114 128 / var(--tw-text-opacity, 1));
}
.user-popover .menu-items .menu-item i[data-v-064c45e9]:is(.dark *) {
--tw-text-opacity: 1;
color: rgb(156 163 175 / var(--tw-text-opacity, 1));
}
.user-popover .menu-items .menu-item .version-info[data-v-064c45e9] {
margin-left: auto;
display: flex;
align-items: center;
}
.user-popover .menu-items .menu-item .version-info .version-number[data-v-064c45e9] {
border-radius: 0.25rem;
padding-left: 0.5rem;
padding-right: 0.5rem;
padding-top: 0.125rem;
padding-bottom: 0.125rem;
font-size: 0.75rem;
line-height: 1rem;
--tw-bg-opacity: 1;
background-color: rgb(243 244 246 / var(--tw-bg-opacity, 1));
--tw-text-opacity: 1;
color: rgb(75 85 99 / var(--tw-text-opacity, 1));
}
.user-popover .menu-items .menu-item .version-info .version-number[data-v-064c45e9]:is(.dark *) {
--tw-bg-opacity: 1;
background-color: rgb(55 65 81 / var(--tw-bg-opacity, 1));
--tw-text-opacity: 1;
color: rgb(209 213 219 / var(--tw-text-opacity, 1));
}

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@@ -0,0 +1,864 @@
import { m as c, p as cB, W as cM, Y as cE, aM as fadeInScaleUpTransition, aN as insideModal, aO as insidePopover, aP as onBeforeUpdate, q as useTheme, d as defineComponent, x as useConfig, aQ as sliderLight, r as ref, z as useFormItem, G as computed, A as toRef, C as useMergedState, E as watch, a as onBeforeUnmount, ap as useThemeClass, aR as isMounted, l as h, K as resolveSlot, ak as Transition, L as call, J as on, aS as off, M as nextTick } from "./index-DKaFsuse.js";
import { d as useAdjustedTo, B as Binder, V as VTarget, e as VFollower } from "./use-locale-DLWAOXez.js";
const style = c([cB("slider", `
display: block;
padding: calc((var(--n-handle-size) - var(--n-rail-height)) / 2) 0;
position: relative;
z-index: 0;
width: 100%;
cursor: pointer;
user-select: none;
-webkit-user-select: none;
`, [cM("reverse", [cB("slider-handles", [cB("slider-handle-wrapper", `
transform: translate(50%, -50%);
`)]), cB("slider-dots", [cB("slider-dot", `
transform: translateX(50%, -50%);
`)]), cM("vertical", [cB("slider-handles", [cB("slider-handle-wrapper", `
transform: translate(-50%, -50%);
`)]), cB("slider-marks", [cB("slider-mark", `
transform: translateY(calc(-50% + var(--n-dot-height) / 2));
`)]), cB("slider-dots", [cB("slider-dot", `
transform: translateX(-50%) translateY(0);
`)])])]), cM("vertical", `
box-sizing: content-box;
padding: 0 calc((var(--n-handle-size) - var(--n-rail-height)) / 2);
width: var(--n-rail-width-vertical);
height: 100%;
`, [cB("slider-handles", `
top: calc(var(--n-handle-size) / 2);
right: 0;
bottom: calc(var(--n-handle-size) / 2);
left: 0;
`, [cB("slider-handle-wrapper", `
top: unset;
left: 50%;
transform: translate(-50%, 50%);
`)]), cB("slider-rail", `
height: 100%;
`, [cE("fill", `
top: unset;
right: 0;
bottom: unset;
left: 0;
`)]), cM("with-mark", `
width: var(--n-rail-width-vertical);
margin: 0 32px 0 8px;
`), cB("slider-marks", `
top: calc(var(--n-handle-size) / 2);
right: unset;
bottom: calc(var(--n-handle-size) / 2);
left: 22px;
font-size: var(--n-mark-font-size);
`, [cB("slider-mark", `
transform: translateY(50%);
white-space: nowrap;
`)]), cB("slider-dots", `
top: calc(var(--n-handle-size) / 2);
right: unset;
bottom: calc(var(--n-handle-size) / 2);
left: 50%;
`, [cB("slider-dot", `
transform: translateX(-50%) translateY(50%);
`)])]), cM("disabled", `
cursor: not-allowed;
opacity: var(--n-opacity-disabled);
`, [cB("slider-handle", `
cursor: not-allowed;
`)]), cM("with-mark", `
width: 100%;
margin: 8px 0 32px 0;
`), c("&:hover", [cB("slider-rail", {
backgroundColor: "var(--n-rail-color-hover)"
}, [cE("fill", {
backgroundColor: "var(--n-fill-color-hover)"
})]), cB("slider-handle", {
boxShadow: "var(--n-handle-box-shadow-hover)"
})]), cM("active", [cB("slider-rail", {
backgroundColor: "var(--n-rail-color-hover)"
}, [cE("fill", {
backgroundColor: "var(--n-fill-color-hover)"
})]), cB("slider-handle", {
boxShadow: "var(--n-handle-box-shadow-hover)"
})]), cB("slider-marks", `
position: absolute;
top: 18px;
left: calc(var(--n-handle-size) / 2);
right: calc(var(--n-handle-size) / 2);
`, [cB("slider-mark", `
position: absolute;
transform: translateX(-50%);
white-space: nowrap;
`)]), cB("slider-rail", `
width: 100%;
position: relative;
height: var(--n-rail-height);
background-color: var(--n-rail-color);
transition: background-color .3s var(--n-bezier);
border-radius: calc(var(--n-rail-height) / 2);
`, [cE("fill", `
position: absolute;
top: 0;
bottom: 0;
border-radius: calc(var(--n-rail-height) / 2);
transition: background-color .3s var(--n-bezier);
background-color: var(--n-fill-color);
`)]), cB("slider-handles", `
position: absolute;
top: 0;
right: calc(var(--n-handle-size) / 2);
bottom: 0;
left: calc(var(--n-handle-size) / 2);
`, [cB("slider-handle-wrapper", `
outline: none;
position: absolute;
top: 50%;
transform: translate(-50%, -50%);
cursor: pointer;
display: flex;
`, [cB("slider-handle", `
height: var(--n-handle-size);
width: var(--n-handle-size);
border-radius: 50%;
overflow: hidden;
transition: box-shadow .2s var(--n-bezier), background-color .3s var(--n-bezier);
background-color: var(--n-handle-color);
box-shadow: var(--n-handle-box-shadow);
`, [c("&:hover", `
box-shadow: var(--n-handle-box-shadow-hover);
`)]), c("&:focus", [cB("slider-handle", `
box-shadow: var(--n-handle-box-shadow-focus);
`, [c("&:hover", `
box-shadow: var(--n-handle-box-shadow-active);
`)])])])]), cB("slider-dots", `
position: absolute;
top: 50%;
left: calc(var(--n-handle-size) / 2);
right: calc(var(--n-handle-size) / 2);
`, [cM("transition-disabled", [cB("slider-dot", "transition: none;")]), cB("slider-dot", `
transition:
border-color .3s var(--n-bezier),
box-shadow .3s var(--n-bezier),
background-color .3s var(--n-bezier);
position: absolute;
transform: translate(-50%, -50%);
height: var(--n-dot-height);
width: var(--n-dot-width);
border-radius: var(--n-dot-border-radius);
overflow: hidden;
box-sizing: border-box;
border: var(--n-dot-border);
background-color: var(--n-dot-color);
`, [cM("active", "border: var(--n-dot-border-active);")])])]), cB("slider-handle-indicator", `
font-size: var(--n-font-size);
padding: 6px 10px;
border-radius: var(--n-indicator-border-radius);
color: var(--n-indicator-text-color);
background-color: var(--n-indicator-color);
box-shadow: var(--n-indicator-box-shadow);
`, [fadeInScaleUpTransition()]), cB("slider-handle-indicator", `
font-size: var(--n-font-size);
padding: 6px 10px;
border-radius: var(--n-indicator-border-radius);
color: var(--n-indicator-text-color);
background-color: var(--n-indicator-color);
box-shadow: var(--n-indicator-box-shadow);
`, [cM("top", `
margin-bottom: 12px;
`), cM("right", `
margin-left: 12px;
`), cM("bottom", `
margin-top: 12px;
`), cM("left", `
margin-right: 12px;
`), fadeInScaleUpTransition()]), insideModal(cB("slider", [cB("slider-dot", "background-color: var(--n-dot-color-modal);")])), insidePopover(cB("slider", [cB("slider-dot", "background-color: var(--n-dot-color-popover);")]))]);
function isTouchEvent(e) {
return window.TouchEvent && e instanceof window.TouchEvent;
}
function useRefs() {
const refs = /* @__PURE__ */ new Map();
const setRefs = (index) => (el) => {
refs.set(index, el);
};
onBeforeUpdate(() => {
refs.clear();
});
return [refs, setRefs];
}
const eventButtonLeft = 0;
const sliderProps = Object.assign(Object.assign({}, useTheme.props), {
to: useAdjustedTo.propTo,
defaultValue: {
type: [Number, Array],
default: 0
},
marks: Object,
disabled: {
type: Boolean,
default: void 0
},
formatTooltip: Function,
keyboard: {
type: Boolean,
default: true
},
min: {
type: Number,
default: 0
},
max: {
type: Number,
default: 100
},
step: {
type: [Number, String],
default: 1
},
range: Boolean,
value: [Number, Array],
placement: String,
showTooltip: {
type: Boolean,
default: void 0
},
tooltip: {
type: Boolean,
default: true
},
vertical: Boolean,
reverse: Boolean,
"onUpdate:value": [Function, Array],
onUpdateValue: [Function, Array],
onDragstart: [Function],
onDragend: [Function]
});
const __unplugin_components_0 = defineComponent({
name: "Slider",
props: sliderProps,
setup(props) {
const {
mergedClsPrefixRef,
namespaceRef,
inlineThemeDisabled
} = useConfig(props);
const themeRef = useTheme("Slider", "-slider", style, sliderLight, props, mergedClsPrefixRef);
const handleRailRef = ref(null);
const [handleRefs, setHandleRefs] = useRefs();
const [followerRefs, setFollowerRefs] = useRefs();
const followerEnabledIndexSetRef = ref(/* @__PURE__ */ new Set());
const formItem = useFormItem(props);
const {
mergedDisabledRef
} = formItem;
const precisionRef = computed(() => {
const {
step
} = props;
if (Number(step) <= 0 || step === "mark") return 0;
const stepString = step.toString();
let precision = 0;
if (stepString.includes(".")) {
precision = stepString.length - stepString.indexOf(".") - 1;
}
return precision;
});
const uncontrolledValueRef = ref(props.defaultValue);
const controlledValueRef = toRef(props, "value");
const mergedValueRef = useMergedState(controlledValueRef, uncontrolledValueRef);
const arrifiedValueRef = computed(() => {
const {
value: mergedValue
} = mergedValueRef;
return (props.range ? mergedValue : [mergedValue]).map(clampValue);
});
const handleCountExceeds2Ref = computed(() => arrifiedValueRef.value.length > 2);
const mergedPlacementRef = computed(() => {
return props.placement === void 0 ? props.vertical ? "right" : "top" : props.placement;
});
const markValuesRef = computed(() => {
const {
marks
} = props;
return marks ? Object.keys(marks).map(Number.parseFloat) : null;
});
const activeIndexRef = ref(-1);
const previousIndexRef = ref(-1);
const hoverIndexRef = ref(-1);
const draggingRef = ref(false);
const dotTransitionDisabledRef = ref(false);
const styleDirectionRef = computed(() => {
const {
vertical,
reverse
} = props;
const left = reverse ? "right" : "left";
const bottom = reverse ? "top" : "bottom";
return vertical ? bottom : left;
});
const fillStyleRef = computed(() => {
if (handleCountExceeds2Ref.value) return;
const values = arrifiedValueRef.value;
const start = valueToPercentage(props.range ? Math.min(...values) : props.min);
const end = valueToPercentage(props.range ? Math.max(...values) : values[0]);
const {
value: styleDirection
} = styleDirectionRef;
return props.vertical ? {
[styleDirection]: `${start}%`,
height: `${end - start}%`
} : {
[styleDirection]: `${start}%`,
width: `${end - start}%`
};
});
const markInfosRef = computed(() => {
const mergedMarks = [];
const {
marks
} = props;
if (marks) {
const orderValues = arrifiedValueRef.value.slice();
orderValues.sort((a, b) => a - b);
const {
value: styleDirection
} = styleDirectionRef;
const {
value: handleCountExceeds2
} = handleCountExceeds2Ref;
const {
range
} = props;
const isActive = handleCountExceeds2 ? () => false : (num) => range ? num >= orderValues[0] && num <= orderValues[orderValues.length - 1] : num <= orderValues[0];
for (const key of Object.keys(marks)) {
const num = Number(key);
mergedMarks.push({
active: isActive(num),
key: num,
label: marks[key],
style: {
[styleDirection]: `${valueToPercentage(num)}%`
}
});
}
}
return mergedMarks;
});
function getHandleStyle(value, index) {
const percentage = valueToPercentage(value);
const {
value: styleDirection
} = styleDirectionRef;
return {
[styleDirection]: `${percentage}%`,
zIndex: index === activeIndexRef.value ? 1 : 0
};
}
function isShowTooltip(index) {
return props.showTooltip || hoverIndexRef.value === index || activeIndexRef.value === index && draggingRef.value;
}
function shouldKeepTooltipTransition(index) {
if (!draggingRef.value) return true;
return !(activeIndexRef.value === index && previousIndexRef.value === index);
}
function focusActiveHandle(index) {
var _a;
if (~index) {
activeIndexRef.value = index;
(_a = handleRefs.get(index)) === null || _a === void 0 ? void 0 : _a.focus();
}
}
function syncPosition() {
followerRefs.forEach((inst, index) => {
if (isShowTooltip(index)) inst.syncPosition();
});
}
function doUpdateValue(value) {
const {
"onUpdate:value": _onUpdateValue,
onUpdateValue
} = props;
const {
nTriggerFormInput,
nTriggerFormChange
} = formItem;
if (onUpdateValue) call(onUpdateValue, value);
if (_onUpdateValue) call(_onUpdateValue, value);
uncontrolledValueRef.value = value;
nTriggerFormInput();
nTriggerFormChange();
}
function dispatchValueUpdate(value) {
const {
range
} = props;
if (range) {
if (Array.isArray(value)) {
const {
value: oldValues
} = arrifiedValueRef;
if (value.join() !== oldValues.join()) {
doUpdateValue(value);
}
}
} else if (!Array.isArray(value)) {
const oldValue = arrifiedValueRef.value[0];
if (oldValue !== value) {
doUpdateValue(value);
}
}
}
function doDispatchValue(value, index) {
if (props.range) {
const values = arrifiedValueRef.value.slice();
values.splice(index, 1, value);
dispatchValueUpdate(values);
} else {
dispatchValueUpdate(value);
}
}
function sanitizeValue(value, currentValue, stepBuffer) {
const stepping = stepBuffer !== void 0;
if (!stepBuffer) {
stepBuffer = value - currentValue > 0 ? 1 : -1;
}
const markValues = markValuesRef.value || [];
const {
step
} = props;
if (step === "mark") {
const closestMark2 = getClosestMark(value, markValues.concat(currentValue), stepping ? stepBuffer : void 0);
return closestMark2 ? closestMark2.value : currentValue;
}
if (step <= 0) return currentValue;
const {
value: precision
} = precisionRef;
let closestMark;
if (stepping) {
const currentStep = Number((currentValue / step).toFixed(precision));
const actualStep = Math.floor(currentStep);
const leftStep = currentStep > actualStep ? actualStep : actualStep - 1;
const rightStep = currentStep < actualStep ? actualStep : actualStep + 1;
closestMark = getClosestMark(currentValue, [Number((leftStep * step).toFixed(precision)), Number((rightStep * step).toFixed(precision)), ...markValues], stepBuffer);
} else {
const roundValue = getRoundValue(value);
closestMark = getClosestMark(value, [...markValues, roundValue]);
}
return closestMark ? clampValue(closestMark.value) : currentValue;
}
function clampValue(value) {
return Math.min(props.max, Math.max(props.min, value));
}
function valueToPercentage(value) {
const {
max,
min
} = props;
return (value - min) / (max - min) * 100;
}
function percentageToValue(percentage) {
const {
max,
min
} = props;
return min + (max - min) * percentage;
}
function getRoundValue(value) {
const {
step,
min
} = props;
if (Number(step) <= 0 || step === "mark") return value;
const newValue = Math.round((value - min) / step) * step + min;
return Number(newValue.toFixed(precisionRef.value));
}
function getClosestMark(currentValue, markValues = markValuesRef.value, buffer) {
if (!(markValues === null || markValues === void 0 ? void 0 : markValues.length)) return null;
let closestMark = null;
let index = -1;
while (++index < markValues.length) {
const diff = markValues[index] - currentValue;
const distance = Math.abs(diff);
if (
// find marks in the same direction
(buffer === void 0 || diff * buffer > 0) && (closestMark === null || distance < closestMark.distance)
) {
closestMark = {
index,
distance,
value: markValues[index]
};
}
}
return closestMark;
}
function getPointValue(event) {
const railEl = handleRailRef.value;
if (!railEl) return;
const touchEvent = isTouchEvent(event) ? event.touches[0] : event;
const railRect = railEl.getBoundingClientRect();
let percentage;
if (props.vertical) {
percentage = (railRect.bottom - touchEvent.clientY) / railRect.height;
} else {
percentage = (touchEvent.clientX - railRect.left) / railRect.width;
}
if (props.reverse) {
percentage = 1 - percentage;
}
return percentageToValue(percentage);
}
function handleRailKeyDown(e) {
if (mergedDisabledRef.value || !props.keyboard) return;
const {
vertical,
reverse
} = props;
switch (e.key) {
case "ArrowUp":
e.preventDefault();
handleStepValue(vertical && reverse ? -1 : 1);
break;
case "ArrowRight":
e.preventDefault();
handleStepValue(!vertical && reverse ? -1 : 1);
break;
case "ArrowDown":
e.preventDefault();
handleStepValue(vertical && reverse ? 1 : -1);
break;
case "ArrowLeft":
e.preventDefault();
handleStepValue(!vertical && reverse ? 1 : -1);
break;
}
}
function handleStepValue(ratio) {
const activeIndex = activeIndexRef.value;
if (activeIndex === -1) return;
const {
step
} = props;
const currentValue = arrifiedValueRef.value[activeIndex];
const nextValue = Number(step) <= 0 || step === "mark" ? currentValue : currentValue + step * ratio;
doDispatchValue(
// Avoid the number of value does not change when `step` is null
sanitizeValue(nextValue, currentValue, ratio > 0 ? 1 : -1),
activeIndex
);
}
function handleRailMouseDown(event) {
var _a, _b;
if (mergedDisabledRef.value) return;
if (!isTouchEvent(event) && event.button !== eventButtonLeft) {
return;
}
const pointValue = getPointValue(event);
if (pointValue === void 0) return;
const values = arrifiedValueRef.value.slice();
const activeIndex = props.range ? (_b = (_a = getClosestMark(pointValue, values)) === null || _a === void 0 ? void 0 : _a.index) !== null && _b !== void 0 ? _b : -1 : 0;
if (activeIndex !== -1) {
event.preventDefault();
focusActiveHandle(activeIndex);
startDragging();
doDispatchValue(sanitizeValue(pointValue, arrifiedValueRef.value[activeIndex]), activeIndex);
}
}
function startDragging() {
if (!draggingRef.value) {
draggingRef.value = true;
if (props.onDragstart) call(props.onDragstart);
on("touchend", document, handleMouseUp);
on("mouseup", document, handleMouseUp);
on("touchmove", document, handleMouseMove);
on("mousemove", document, handleMouseMove);
}
}
function stopDragging() {
if (draggingRef.value) {
draggingRef.value = false;
if (props.onDragend) call(props.onDragend);
off("touchend", document, handleMouseUp);
off("mouseup", document, handleMouseUp);
off("touchmove", document, handleMouseMove);
off("mousemove", document, handleMouseMove);
}
}
function handleMouseMove(event) {
const {
value: activeIndex
} = activeIndexRef;
if (!draggingRef.value || activeIndex === -1) {
stopDragging();
return;
}
const pointValue = getPointValue(event);
if (pointValue === void 0) return;
doDispatchValue(sanitizeValue(pointValue, arrifiedValueRef.value[activeIndex]), activeIndex);
}
function handleMouseUp() {
stopDragging();
}
function handleHandleFocus(index) {
activeIndexRef.value = index;
if (!mergedDisabledRef.value) {
hoverIndexRef.value = index;
}
}
function handleHandleBlur(index) {
if (activeIndexRef.value === index) {
activeIndexRef.value = -1;
stopDragging();
}
if (hoverIndexRef.value === index) {
hoverIndexRef.value = -1;
}
}
function handleHandleMouseEnter(index) {
hoverIndexRef.value = index;
}
function handleHandleMouseLeave(index) {
if (hoverIndexRef.value === index) {
hoverIndexRef.value = -1;
}
}
watch(activeIndexRef, (_, previous) => void nextTick(() => previousIndexRef.value = previous));
watch(mergedValueRef, () => {
if (props.marks) {
if (dotTransitionDisabledRef.value) return;
dotTransitionDisabledRef.value = true;
void nextTick(() => {
dotTransitionDisabledRef.value = false;
});
}
void nextTick(syncPosition);
});
onBeforeUnmount(() => {
stopDragging();
});
const cssVarsRef = computed(() => {
const {
self: {
markFontSize,
railColor,
railColorHover,
fillColor,
fillColorHover,
handleColor,
opacityDisabled,
dotColor,
dotColorModal,
handleBoxShadow,
handleBoxShadowHover,
handleBoxShadowActive,
handleBoxShadowFocus,
dotBorder,
dotBoxShadow,
railHeight,
railWidthVertical,
handleSize,
dotHeight,
dotWidth,
dotBorderRadius,
fontSize,
dotBorderActive,
dotColorPopover
},
common: {
cubicBezierEaseInOut
}
} = themeRef.value;
return {
"--n-bezier": cubicBezierEaseInOut,
"--n-dot-border": dotBorder,
"--n-dot-border-active": dotBorderActive,
"--n-dot-border-radius": dotBorderRadius,
"--n-dot-box-shadow": dotBoxShadow,
"--n-dot-color": dotColor,
"--n-dot-color-modal": dotColorModal,
"--n-dot-color-popover": dotColorPopover,
"--n-dot-height": dotHeight,
"--n-dot-width": dotWidth,
"--n-fill-color": fillColor,
"--n-fill-color-hover": fillColorHover,
"--n-font-size": fontSize,
"--n-handle-box-shadow": handleBoxShadow,
"--n-handle-box-shadow-active": handleBoxShadowActive,
"--n-handle-box-shadow-focus": handleBoxShadowFocus,
"--n-handle-box-shadow-hover": handleBoxShadowHover,
"--n-handle-color": handleColor,
"--n-handle-size": handleSize,
"--n-opacity-disabled": opacityDisabled,
"--n-rail-color": railColor,
"--n-rail-color-hover": railColorHover,
"--n-rail-height": railHeight,
"--n-rail-width-vertical": railWidthVertical,
"--n-mark-font-size": markFontSize
};
});
const themeClassHandle = inlineThemeDisabled ? useThemeClass("slider", void 0, cssVarsRef, props) : void 0;
const indicatorCssVarsRef = computed(() => {
const {
self: {
fontSize,
indicatorColor,
indicatorBoxShadow,
indicatorTextColor,
indicatorBorderRadius
}
} = themeRef.value;
return {
"--n-font-size": fontSize,
"--n-indicator-border-radius": indicatorBorderRadius,
"--n-indicator-box-shadow": indicatorBoxShadow,
"--n-indicator-color": indicatorColor,
"--n-indicator-text-color": indicatorTextColor
};
});
const indicatorThemeClassHandle = inlineThemeDisabled ? useThemeClass("slider-indicator", void 0, indicatorCssVarsRef, props) : void 0;
return {
mergedClsPrefix: mergedClsPrefixRef,
namespace: namespaceRef,
uncontrolledValue: uncontrolledValueRef,
mergedValue: mergedValueRef,
mergedDisabled: mergedDisabledRef,
mergedPlacement: mergedPlacementRef,
isMounted: isMounted(),
adjustedTo: useAdjustedTo(props),
dotTransitionDisabled: dotTransitionDisabledRef,
markInfos: markInfosRef,
isShowTooltip,
shouldKeepTooltipTransition,
handleRailRef,
setHandleRefs,
setFollowerRefs,
fillStyle: fillStyleRef,
getHandleStyle,
activeIndex: activeIndexRef,
arrifiedValues: arrifiedValueRef,
followerEnabledIndexSet: followerEnabledIndexSetRef,
handleRailMouseDown,
handleHandleFocus,
handleHandleBlur,
handleHandleMouseEnter,
handleHandleMouseLeave,
handleRailKeyDown,
indicatorCssVars: inlineThemeDisabled ? void 0 : indicatorCssVarsRef,
indicatorThemeClass: indicatorThemeClassHandle === null || indicatorThemeClassHandle === void 0 ? void 0 : indicatorThemeClassHandle.themeClass,
indicatorOnRender: indicatorThemeClassHandle === null || indicatorThemeClassHandle === void 0 ? void 0 : indicatorThemeClassHandle.onRender,
cssVars: inlineThemeDisabled ? void 0 : cssVarsRef,
themeClass: themeClassHandle === null || themeClassHandle === void 0 ? void 0 : themeClassHandle.themeClass,
onRender: themeClassHandle === null || themeClassHandle === void 0 ? void 0 : themeClassHandle.onRender
};
},
render() {
var _a;
const {
mergedClsPrefix,
themeClass,
formatTooltip
} = this;
(_a = this.onRender) === null || _a === void 0 ? void 0 : _a.call(this);
return h("div", {
class: [`${mergedClsPrefix}-slider`, themeClass, {
[`${mergedClsPrefix}-slider--disabled`]: this.mergedDisabled,
[`${mergedClsPrefix}-slider--active`]: this.activeIndex !== -1,
[`${mergedClsPrefix}-slider--with-mark`]: this.marks,
[`${mergedClsPrefix}-slider--vertical`]: this.vertical,
[`${mergedClsPrefix}-slider--reverse`]: this.reverse
}],
style: this.cssVars,
onKeydown: this.handleRailKeyDown,
onMousedown: this.handleRailMouseDown,
onTouchstart: this.handleRailMouseDown
}, h("div", {
class: `${mergedClsPrefix}-slider-rail`
}, h("div", {
class: `${mergedClsPrefix}-slider-rail__fill`,
style: this.fillStyle
}), this.marks ? h("div", {
class: [`${mergedClsPrefix}-slider-dots`, this.dotTransitionDisabled && `${mergedClsPrefix}-slider-dots--transition-disabled`]
}, this.markInfos.map((mark) => h("div", {
key: mark.key,
class: [`${mergedClsPrefix}-slider-dot`, {
[`${mergedClsPrefix}-slider-dot--active`]: mark.active
}],
style: mark.style
}))) : null, h("div", {
ref: "handleRailRef",
class: `${mergedClsPrefix}-slider-handles`
}, this.arrifiedValues.map((value, index) => {
const showTooltip = this.isShowTooltip(index);
return h(Binder, null, {
default: () => [h(VTarget, null, {
default: () => h("div", {
ref: this.setHandleRefs(index),
class: `${mergedClsPrefix}-slider-handle-wrapper`,
tabindex: this.mergedDisabled ? -1 : 0,
role: "slider",
"aria-valuenow": value,
"aria-valuemin": this.min,
"aria-valuemax": this.max,
"aria-orientation": this.vertical ? "vertical" : "horizontal",
"aria-disabled": this.disabled,
style: this.getHandleStyle(value, index),
onFocus: () => {
this.handleHandleFocus(index);
},
onBlur: () => {
this.handleHandleBlur(index);
},
onMouseenter: () => {
this.handleHandleMouseEnter(index);
},
onMouseleave: () => {
this.handleHandleMouseLeave(index);
}
}, resolveSlot(this.$slots.thumb, () => [h("div", {
class: `${mergedClsPrefix}-slider-handle`
})]))
}), this.tooltip && h(VFollower, {
ref: this.setFollowerRefs(index),
show: showTooltip,
to: this.adjustedTo,
enabled: this.showTooltip && !this.range || this.followerEnabledIndexSet.has(index),
teleportDisabled: this.adjustedTo === useAdjustedTo.tdkey,
placement: this.mergedPlacement,
containerClass: this.namespace
}, {
default: () => h(Transition, {
name: "fade-in-scale-up-transition",
appear: this.isMounted,
css: this.shouldKeepTooltipTransition(index),
onEnter: () => {
this.followerEnabledIndexSet.add(index);
},
onAfterLeave: () => {
this.followerEnabledIndexSet.delete(index);
}
}, {
default: () => {
var _a2;
if (showTooltip) {
(_a2 = this.indicatorOnRender) === null || _a2 === void 0 ? void 0 : _a2.call(this);
return h("div", {
class: [`${mergedClsPrefix}-slider-handle-indicator`, this.indicatorThemeClass, `${mergedClsPrefix}-slider-handle-indicator--${this.mergedPlacement}`],
style: this.indicatorCssVars
}, typeof formatTooltip === "function" ? formatTooltip(value) : value);
}
return null;
}
})
})]
});
})), this.marks ? h("div", {
class: `${mergedClsPrefix}-slider-marks`
}, this.markInfos.map((mark) => h("div", {
key: mark.key,
class: `${mergedClsPrefix}-slider-mark`,
style: mark.style
}, typeof mark.label === "function" ? mark.label() : mark.label))) : null));
}
});
export {
__unplugin_components_0 as _
};

Binary file not shown.

View File

@@ -0,0 +1,296 @@
.text-ellipsis[data-v-aae6c67f] {
width: 100%;
}
.song-item[data-v-aae6c67f] {
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
display: flex;
align-items: center;
border-radius: 1.5rem;
background-color: transparent;
padding: 0.75rem;
--tw-text-opacity: 1;
color: rgb(17 24 39 / var(--tw-text-opacity, 1));
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, -webkit-backdrop-filter;
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter;
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter, -webkit-backdrop-filter;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-duration: 150ms;
}
.song-item[data-v-aae6c67f]:is(.dark *) {
--tw-text-opacity: 1;
color: rgb(255 255 255 / var(--tw-text-opacity, 1));
}
.song-item[data-v-aae6c67f]:hover {
--tw-bg-opacity: 1;
background-color: rgb(243 244 246 / var(--tw-bg-opacity, 1));
}
.song-item[data-v-aae6c67f]:hover:is(.dark *) {
--tw-bg-opacity: 1;
background-color: rgb(31 41 55 / var(--tw-bg-opacity, 1));
}
.song-item-img[data-v-aae6c67f] {
margin-right: 1rem;
height: 3rem;
width: 3rem;
border-radius: 1rem;
}
.song-item-content[data-v-aae6c67f] {
flex: 1 1 0%;
}
.song-item-content-title[data-v-aae6c67f] {
font-size: 1rem;
line-height: 1.5rem;
--tw-text-opacity: 1;
color: rgb(17 24 39 / var(--tw-text-opacity, 1));
}
.song-item-content-title[data-v-aae6c67f]:is(.dark *) {
--tw-text-opacity: 1;
color: rgb(255 255 255 / var(--tw-text-opacity, 1));
}
.song-item-content-name[data-v-aae6c67f] {
font-size: 0.75rem;
line-height: 1rem;
--tw-text-opacity: 1;
color: rgb(107 114 128 / var(--tw-text-opacity, 1));
}
.song-item-content-name[data-v-aae6c67f]:is(.dark *) {
--tw-text-opacity: 1;
color: rgb(156 163 175 / var(--tw-text-opacity, 1));
}
.song-item-operating[data-v-aae6c67f] {
margin-left: 1rem;
display: flex;
align-items: center;
border-radius: 9999px;
border-width: 1px;
--tw-border-opacity: 1;
border-color: rgb(229 231 235 / var(--tw-border-opacity, 1));
--tw-bg-opacity: 1;
background-color: rgb(255 255 255 / var(--tw-bg-opacity, 1));
}
.song-item-operating[data-v-aae6c67f]:is(.dark *) {
--tw-border-opacity: 1;
border-color: rgb(55 65 81 / var(--tw-border-opacity, 1));
--tw-bg-opacity: 1;
background-color: rgb(0 0 0 / var(--tw-bg-opacity, 1));
}
.song-item-operating .iconfont[data-v-aae6c67f] {
font-size: 1.25rem;
line-height: 1.75rem;
}
.song-item-operating .icon-likefill[data-v-aae6c67f] {
font-size: 1.25rem;
line-height: 1.75rem;
--tw-text-opacity: 1;
color: rgb(107 114 128 / var(--tw-text-opacity, 1));
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, -webkit-backdrop-filter;
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter;
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter, -webkit-backdrop-filter;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-duration: 150ms;
}
.song-item-operating .icon-likefill[data-v-aae6c67f]:hover {
--tw-text-opacity: 1;
color: rgb(239 68 68 / var(--tw-text-opacity, 1));
}
.song-item-operating .icon-likefill[data-v-aae6c67f]:is(.dark *) {
--tw-text-opacity: 1;
color: rgb(156 163 175 / var(--tw-text-opacity, 1));
}
.song-item-operating-like[data-v-aae6c67f] {
margin-right: 0.5rem;
margin-left: 1rem;
cursor: pointer;
}
.song-item-operating .like-active[data-v-aae6c67f] {
--tw-text-opacity: 1;
color: rgb(239 68 68 / var(--tw-text-opacity, 1));
}
.song-item-operating-play[data-v-aae6c67f] {
display: flex;
height: 2.5rem;
width: 2.5rem;
cursor: pointer;
align-items: center;
justify-content: center;
border-radius: 9999px;
border-width: 1px;
--tw-border-opacity: 1;
border-color: rgb(229 231 235 / var(--tw-border-opacity, 1));
--tw-text-opacity: 1;
color: rgb(17 24 39 / var(--tw-text-opacity, 1));
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, -webkit-backdrop-filter;
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter;
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter, -webkit-backdrop-filter;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-duration: 150ms;
}
.song-item-operating-play[data-v-aae6c67f]:is(.dark *) {
--tw-border-opacity: 1;
border-color: rgb(55 65 81 / var(--tw-border-opacity, 1));
--tw-text-opacity: 1;
color: rgb(255 255 255 / var(--tw-text-opacity, 1));
}
.song-item-operating-play[data-v-aae6c67f]:hover, .song-item-operating-play.bg-green-600[data-v-aae6c67f] {
--tw-border-opacity: 1;
border-color: rgb(34 197 94 / var(--tw-border-opacity, 1));
--tw-bg-opacity: 1;
background-color: rgb(34 197 94 / var(--tw-bg-opacity, 1));
--tw-text-opacity: 1;
color: rgb(255 255 255 / var(--tw-text-opacity, 1));
}
.song-mini[data-v-aae6c67f] {
border-radius: 1rem;
padding: 0.5rem;
}
.song-mini .song-item[data-v-aae6c67f] {
padding: 0px;
}
.song-mini .song-item-img[data-v-aae6c67f] {
margin-right: 0.5rem;
height: 2.5rem;
width: 2.5rem;
}
.song-mini .song-item-content[data-v-aae6c67f] {
flex: 1 1 0%;
}
.song-mini .song-item-content-title[data-v-aae6c67f] {
font-size: 0.875rem;
line-height: 1.25rem;
}
.song-mini .song-item-content-name[data-v-aae6c67f] {
font-size: 0.75rem;
line-height: 1rem;
}
.song-mini .song-item-operating[data-v-aae6c67f] {
padding-left: 0.5rem;
}
.song-mini .song-item-operating .iconfont[data-v-aae6c67f] {
font-size: 1rem;
line-height: 1.5rem;
}
.song-mini .song-item-operating-like[data-v-aae6c67f] {
margin-right: 0.25rem;
margin-left: 0.25rem;
}
.song-mini .song-item-operating-play[data-v-aae6c67f] {
height: 2rem;
width: 2rem;
}
.song-list[data-v-aae6c67f] {
margin-bottom: 0.5rem;
border-radius: 0.5rem;
border-width: 1px;
--tw-border-opacity: 1;
border-color: rgb(229 231 235 / var(--tw-border-opacity, 1));
padding: 0.5rem;
}
.song-list[data-v-aae6c67f]:is(.dark *) {
--tw-border-opacity: 1;
border-color: rgb(31 41 55 / var(--tw-border-opacity, 1));
}
.song-list[data-v-aae6c67f]:hover {
--tw-bg-opacity: 1;
background-color: rgb(249 250 251 / var(--tw-bg-opacity, 1));
}
.song-list[data-v-aae6c67f]:hover:is(.dark *) {
--tw-bg-opacity: 1;
background-color: rgb(31 41 55 / var(--tw-bg-opacity, 1));
}
.song-list .song-item-img[data-v-aae6c67f] {
margin-right: 0.75rem;
height: 2.5rem;
width: 2.5rem;
border-radius: 0.5rem;
}
.song-list .song-item-content[data-v-aae6c67f] {
display: flex;
flex: 1 1 0%;
align-items: center;
}
.song-list .song-item-content-wrapper[data-v-aae6c67f] {
display: flex;
flex: 1 1 0%;
align-items: center;
font-size: 0.875rem;
line-height: 1.25rem;
}
.song-list .song-item-content-title[data-v-aae6c67f] {
max-width: 45%;
flex-shrink: 0;
--tw-text-opacity: 1;
color: rgb(17 24 39 / var(--tw-text-opacity, 1));
}
.song-list .song-item-content-title[data-v-aae6c67f]:is(.dark *) {
--tw-text-opacity: 1;
color: rgb(255 255 255 / var(--tw-text-opacity, 1));
}
.song-list .song-item-content-divider[data-v-aae6c67f] {
margin-left: 0.5rem;
margin-right: 0.5rem;
--tw-text-opacity: 1;
color: rgb(107 114 128 / var(--tw-text-opacity, 1));
}
.song-list .song-item-content-divider[data-v-aae6c67f]:is(.dark *) {
--tw-text-opacity: 1;
color: rgb(156 163 175 / var(--tw-text-opacity, 1));
}
.song-list .song-item-content-name[data-v-aae6c67f] {
min-width: 0px;
flex: 1 1 0%;
--tw-text-opacity: 1;
color: rgb(107 114 128 / var(--tw-text-opacity, 1));
}
.song-list .song-item-content-name[data-v-aae6c67f]:is(.dark *) {
--tw-text-opacity: 1;
color: rgb(156 163 175 / var(--tw-text-opacity, 1));
}
.song-list .song-item-operating[data-v-aae6c67f] {
display: flex;
align-items: center;
gap: 0.5rem;
}
.song-list .song-item-operating-like[data-v-aae6c67f] {
cursor: pointer;
transition-property: transform;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-duration: 150ms;
}
.song-list .song-item-operating-like[data-v-aae6c67f]:hover {
--tw-scale-x: 1.1;
--tw-scale-y: 1.1;
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}
.song-list .song-item-operating-like .iconfont[data-v-aae6c67f] {
font-size: 1rem;
line-height: 1.5rem;
--tw-text-opacity: 1;
color: rgb(107 114 128 / var(--tw-text-opacity, 1));
}
.song-list .song-item-operating-like .iconfont[data-v-aae6c67f]:hover {
--tw-text-opacity: 1;
color: rgb(239 68 68 / var(--tw-text-opacity, 1));
}
.song-list .song-item-operating-like .iconfont[data-v-aae6c67f]:is(.dark *) {
--tw-text-opacity: 1;
color: rgb(156 163 175 / var(--tw-text-opacity, 1));
}
.song-list .song-item-operating-play[data-v-aae6c67f] {
height: 1.75rem;
width: 1.75rem;
cursor: pointer;
transition-property: transform;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-duration: 150ms;
}
.song-list .song-item-operating-play[data-v-aae6c67f]:hover {
--tw-scale-x: 1.1;
--tw-scale-y: 1.1;
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}
.song-list .song-item-operating-play .iconfont[data-v-aae6c67f] {
font-size: 1rem;
line-height: 1.5rem;
}

Binary file not shown.

View File

@@ -0,0 +1,170 @@
import { d as defineComponent, g as useStore, G as computed, aG as useTemplateRef, j as openBlock, c as createElementBlock, O as createBlock, u as unref, a7 as getImgUrl, T as createCommentVNode, b as createBaseVNode, e as createVNode, f as withCtx, k as createTextVNode, t as toDisplayString, a3 as Fragment, a4 as renderList, n as normalizeClass, ah as withModifiers, b5 as getImageBackground, ae as audioService, _ as _export_sfc } from "./index-DKaFsuse.js";
import { N as NImage } from "./Image-DXClIklC.js";
import { _ as __unplugin_components_2 } from "./Ellipsis-D4R5dIX2.js";
const _hoisted_1 = { class: "song-item-content" };
const _hoisted_2 = {
key: 0,
class: "song-item-content-wrapper"
};
const _hoisted_3 = { class: "song-item-content-title" };
const _hoisted_4 = { class: "song-item-content-name" };
const _hoisted_5 = {
key: 0,
class: "song-item-operating-like"
};
const _hoisted_6 = {
key: 0,
class: "iconfont icon-stop"
};
const _hoisted_7 = {
key: 1,
class: "iconfont icon-playfill"
};
const _sfc_main = /* @__PURE__ */ defineComponent({
__name: "SongItem",
props: {
item: {},
mini: { type: Boolean, default: false },
list: { type: Boolean, default: false },
favorite: { type: Boolean, default: true }
},
emits: ["play"],
setup(__props, { emit: __emit }) {
const props = __props;
const store = useStore();
const play = computed(() => store.state.play);
const playMusic = computed(() => store.state.playMusic);
const playLoading = computed(
() => playMusic.value.id === props.item.id && playMusic.value.playLoading
);
const isPlaying = computed(() => {
return playMusic.value.id === props.item.id;
});
const emits = __emit;
const songImageRef = useTemplateRef("songImg");
const imageLoad = async () => {
if (!songImageRef.value) {
return;
}
const { backgroundColor } = await getImageBackground(
songImageRef.value.imageRef
);
props.item.backgroundColor = backgroundColor;
};
const playMusicEvent = async (item) => {
if (playMusic.value.id === item.id) {
if (play.value) {
store.commit("setPlayMusic", false);
audioService.getCurrentSound()?.pause();
} else {
store.commit("setPlayMusic", true);
audioService.getCurrentSound()?.play();
}
return;
}
await store.commit("setPlay", item);
store.commit("setIsPlay", true);
emits("play", item);
};
const isFavorite = computed(() => {
return store.state.favoriteList.includes(props.item.id);
});
const toggleFavorite = async (e) => {
e.stopPropagation();
if (isFavorite.value) {
store.commit("removeFromFavorite", props.item.id);
} else {
store.commit("addToFavorite", props.item.id);
}
};
return (_ctx, _cache) => {
const _component_n_image = NImage;
const _component_n_ellipsis = __unplugin_components_2;
return openBlock(), createElementBlock("div", {
class: normalizeClass(["song-item", { "song-mini": _ctx.mini, "song-list": _ctx.list }])
}, [
_ctx.item.picUrl ? (openBlock(), createBlock(_component_n_image, {
key: 0,
ref: "songImg",
src: unref(getImgUrl)(_ctx.item.picUrl, "100y100"),
class: "song-item-img",
"preview-disabled": "",
"img-props": {
crossorigin: "anonymous"
},
onLoad: imageLoad
}, null, 8, ["src"])) : createCommentVNode("", true),
createBaseVNode("div", _hoisted_1, [
_ctx.list ? (openBlock(), createElementBlock("div", _hoisted_2, [
createVNode(_component_n_ellipsis, {
class: "song-item-content-title text-ellipsis",
"line-clamp": "1"
}, {
default: withCtx(() => [
createTextVNode(toDisplayString(_ctx.item.name), 1)
]),
_: 1
}),
_cache[1] || (_cache[1] = createBaseVNode("div", { class: "song-item-content-divider" }, "-", -1)),
createVNode(_component_n_ellipsis, {
class: "song-item-content-name text-ellipsis",
"line-clamp": "1"
}, {
default: withCtx(() => [
(openBlock(true), createElementBlock(Fragment, null, renderList(_ctx.item.ar || _ctx.item.song.artists, (artists, artistsindex) => {
return openBlock(), createElementBlock("span", { key: artistsindex }, toDisplayString(artists.name) + toDisplayString(artistsindex < (_ctx.item.ar || _ctx.item.song.artists).length - 1 ? " / " : ""), 1);
}), 128))
]),
_: 1
})
])) : (openBlock(), createElementBlock(Fragment, { key: 1 }, [
createBaseVNode("div", _hoisted_3, [
createVNode(_component_n_ellipsis, {
class: "text-ellipsis",
"line-clamp": "1"
}, {
default: withCtx(() => [
createTextVNode(toDisplayString(_ctx.item.name), 1)
]),
_: 1
})
]),
createBaseVNode("div", _hoisted_4, [
createVNode(_component_n_ellipsis, {
class: "text-ellipsis",
"line-clamp": "1"
}, {
default: withCtx(() => [
(openBlock(true), createElementBlock(Fragment, null, renderList(_ctx.item.ar || _ctx.item.song.artists, (artists, artistsindex) => {
return openBlock(), createElementBlock("span", { key: artistsindex }, toDisplayString(artists.name) + toDisplayString(artistsindex < (_ctx.item.ar || _ctx.item.song.artists).length - 1 ? " / " : ""), 1);
}), 128))
]),
_: 1
})
])
], 64))
]),
createBaseVNode("div", {
class: normalizeClass(["song-item-operating", { "song-item-operating-list": _ctx.list }])
}, [
_ctx.favorite ? (openBlock(), createElementBlock("div", _hoisted_5, [
createBaseVNode("i", {
class: normalizeClass(["iconfont icon-likefill", { "like-active": isFavorite.value }]),
onClick: withModifiers(toggleFavorite, ["stop"])
}, null, 2)
])) : createCommentVNode("", true),
createBaseVNode("div", {
class: normalizeClass(["song-item-operating-play bg-gray-300 dark:bg-gray-800 animate__animated", { "bg-green-600": isPlaying.value, animate__flipInY: playLoading.value }]),
onClick: _cache[0] || (_cache[0] = ($event) => playMusicEvent(_ctx.item))
}, [
isPlaying.value && play.value ? (openBlock(), createElementBlock("i", _hoisted_6)) : (openBlock(), createElementBlock("i", _hoisted_7))
], 2)
], 2)
], 2);
};
}
});
const SongItem = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-aae6c67f"]]);
export {
SongItem as S
};

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@@ -0,0 +1,344 @@
import { p as cB, W as cM, Y as cE, V as cNotM, m as c, q as useTheme, d as defineComponent, r as ref, x as useConfig, by as tagLight, $ as provide, A as toRef, F as useRtl, G as computed, ao as createKey, bs as getMargin, ap as useThemeClass, bx as color2Class, I as resolveWrappedSlot, l as h, bz as NBaseClose, aL as createInjectionKey, L as call } from "./index-DKaFsuse.js";
const commonProps = {
color: Object,
type: {
type: String,
default: "default"
},
round: Boolean,
size: {
type: String,
default: "medium"
},
closable: Boolean,
disabled: {
type: Boolean,
default: void 0
}
};
const style = cB("tag", `
--n-close-margin: var(--n-close-margin-top) var(--n-close-margin-right) var(--n-close-margin-bottom) var(--n-close-margin-left);
white-space: nowrap;
position: relative;
box-sizing: border-box;
cursor: default;
display: inline-flex;
align-items: center;
flex-wrap: nowrap;
padding: var(--n-padding);
border-radius: var(--n-border-radius);
color: var(--n-text-color);
background-color: var(--n-color);
transition:
border-color .3s var(--n-bezier),
background-color .3s var(--n-bezier),
color .3s var(--n-bezier),
box-shadow .3s var(--n-bezier),
opacity .3s var(--n-bezier);
line-height: 1;
height: var(--n-height);
font-size: var(--n-font-size);
`, [cM("strong", `
font-weight: var(--n-font-weight-strong);
`), cE("border", `
pointer-events: none;
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
border-radius: inherit;
border: var(--n-border);
transition: border-color .3s var(--n-bezier);
`), cE("icon", `
display: flex;
margin: 0 4px 0 0;
color: var(--n-text-color);
transition: color .3s var(--n-bezier);
font-size: var(--n-avatar-size-override);
`), cE("avatar", `
display: flex;
margin: 0 6px 0 0;
`), cE("close", `
margin: var(--n-close-margin);
transition:
background-color .3s var(--n-bezier),
color .3s var(--n-bezier);
`), cM("round", `
padding: 0 calc(var(--n-height) / 3);
border-radius: calc(var(--n-height) / 2);
`, [cE("icon", `
margin: 0 4px 0 calc((var(--n-height) - 8px) / -2);
`), cE("avatar", `
margin: 0 6px 0 calc((var(--n-height) - 8px) / -2);
`), cM("closable", `
padding: 0 calc(var(--n-height) / 4) 0 calc(var(--n-height) / 3);
`)]), cM("icon, avatar", [cM("round", `
padding: 0 calc(var(--n-height) / 3) 0 calc(var(--n-height) / 2);
`)]), cM("disabled", `
cursor: not-allowed !important;
opacity: var(--n-opacity-disabled);
`), cM("checkable", `
cursor: pointer;
box-shadow: none;
color: var(--n-text-color-checkable);
background-color: var(--n-color-checkable);
`, [cNotM("disabled", [c("&:hover", "background-color: var(--n-color-hover-checkable);", [cNotM("checked", "color: var(--n-text-color-hover-checkable);")]), c("&:active", "background-color: var(--n-color-pressed-checkable);", [cNotM("checked", "color: var(--n-text-color-pressed-checkable);")])]), cM("checked", `
color: var(--n-text-color-checked);
background-color: var(--n-color-checked);
`, [cNotM("disabled", [c("&:hover", "background-color: var(--n-color-checked-hover);"), c("&:active", "background-color: var(--n-color-checked-pressed);")])])])]);
const tagProps = Object.assign(Object.assign(Object.assign({}, useTheme.props), commonProps), {
bordered: {
type: Boolean,
default: void 0
},
checked: Boolean,
checkable: Boolean,
strong: Boolean,
triggerClickOnClose: Boolean,
onClose: [Array, Function],
onMouseenter: Function,
onMouseleave: Function,
"onUpdate:checked": Function,
onUpdateChecked: Function,
// private
internalCloseFocusable: {
type: Boolean,
default: true
},
internalCloseIsButtonTag: {
type: Boolean,
default: true
},
// deprecated
onCheckedChange: Function
});
const tagInjectionKey = createInjectionKey("n-tag");
const __unplugin_components_4 = defineComponent({
name: "Tag",
props: tagProps,
setup(props) {
const contentRef = ref(null);
const {
mergedBorderedRef,
mergedClsPrefixRef,
inlineThemeDisabled,
mergedRtlRef
} = useConfig(props);
const themeRef = useTheme("Tag", "-tag", style, tagLight, props, mergedClsPrefixRef);
provide(tagInjectionKey, {
roundRef: toRef(props, "round")
});
function handleClick() {
if (!props.disabled) {
if (props.checkable) {
const {
checked,
onCheckedChange,
onUpdateChecked,
"onUpdate:checked": _onUpdateChecked
} = props;
if (onUpdateChecked) onUpdateChecked(!checked);
if (_onUpdateChecked) _onUpdateChecked(!checked);
if (onCheckedChange) onCheckedChange(!checked);
}
}
}
function handleCloseClick(e) {
if (!props.triggerClickOnClose) {
e.stopPropagation();
}
if (!props.disabled) {
const {
onClose
} = props;
if (onClose) call(onClose, e);
}
}
const tagPublicMethods = {
setTextContent(textContent) {
const {
value
} = contentRef;
if (value) value.textContent = textContent;
}
};
const rtlEnabledRef = useRtl("Tag", mergedRtlRef, mergedClsPrefixRef);
const cssVarsRef = computed(() => {
const {
type,
size,
color: {
color,
textColor
} = {}
} = props;
const {
common: {
cubicBezierEaseInOut
},
self: {
padding,
closeMargin,
borderRadius,
opacityDisabled,
textColorCheckable,
textColorHoverCheckable,
textColorPressedCheckable,
textColorChecked,
colorCheckable,
colorHoverCheckable,
colorPressedCheckable,
colorChecked,
colorCheckedHover,
colorCheckedPressed,
closeBorderRadius,
fontWeightStrong,
[createKey("colorBordered", type)]: colorBordered,
[createKey("closeSize", size)]: closeSize,
[createKey("closeIconSize", size)]: closeIconSize,
[createKey("fontSize", size)]: fontSize,
[createKey("height", size)]: height,
[createKey("color", type)]: typedColor,
[createKey("textColor", type)]: typeTextColor,
[createKey("border", type)]: border,
[createKey("closeIconColor", type)]: closeIconColor,
[createKey("closeIconColorHover", type)]: closeIconColorHover,
[createKey("closeIconColorPressed", type)]: closeIconColorPressed,
[createKey("closeColorHover", type)]: closeColorHover,
[createKey("closeColorPressed", type)]: closeColorPressed
}
} = themeRef.value;
const closeMarginDiscrete = getMargin(closeMargin);
return {
"--n-font-weight-strong": fontWeightStrong,
"--n-avatar-size-override": `calc(${height} - 8px)`,
"--n-bezier": cubicBezierEaseInOut,
"--n-border-radius": borderRadius,
"--n-border": border,
"--n-close-icon-size": closeIconSize,
"--n-close-color-pressed": closeColorPressed,
"--n-close-color-hover": closeColorHover,
"--n-close-border-radius": closeBorderRadius,
"--n-close-icon-color": closeIconColor,
"--n-close-icon-color-hover": closeIconColorHover,
"--n-close-icon-color-pressed": closeIconColorPressed,
"--n-close-icon-color-disabled": closeIconColor,
"--n-close-margin-top": closeMarginDiscrete.top,
"--n-close-margin-right": closeMarginDiscrete.right,
"--n-close-margin-bottom": closeMarginDiscrete.bottom,
"--n-close-margin-left": closeMarginDiscrete.left,
"--n-close-size": closeSize,
"--n-color": color || (mergedBorderedRef.value ? colorBordered : typedColor),
"--n-color-checkable": colorCheckable,
"--n-color-checked": colorChecked,
"--n-color-checked-hover": colorCheckedHover,
"--n-color-checked-pressed": colorCheckedPressed,
"--n-color-hover-checkable": colorHoverCheckable,
"--n-color-pressed-checkable": colorPressedCheckable,
"--n-font-size": fontSize,
"--n-height": height,
"--n-opacity-disabled": opacityDisabled,
"--n-padding": padding,
"--n-text-color": textColor || typeTextColor,
"--n-text-color-checkable": textColorCheckable,
"--n-text-color-checked": textColorChecked,
"--n-text-color-hover-checkable": textColorHoverCheckable,
"--n-text-color-pressed-checkable": textColorPressedCheckable
};
});
const themeClassHandle = inlineThemeDisabled ? useThemeClass("tag", computed(() => {
let hash = "";
const {
type,
size,
color: {
color,
textColor
} = {}
} = props;
hash += type[0];
hash += size[0];
if (color) {
hash += `a${color2Class(color)}`;
}
if (textColor) {
hash += `b${color2Class(textColor)}`;
}
if (mergedBorderedRef.value) {
hash += "c";
}
return hash;
}), cssVarsRef, props) : void 0;
return Object.assign(Object.assign({}, tagPublicMethods), {
rtlEnabled: rtlEnabledRef,
mergedClsPrefix: mergedClsPrefixRef,
contentRef,
mergedBordered: mergedBorderedRef,
handleClick,
handleCloseClick,
cssVars: inlineThemeDisabled ? void 0 : cssVarsRef,
themeClass: themeClassHandle === null || themeClassHandle === void 0 ? void 0 : themeClassHandle.themeClass,
onRender: themeClassHandle === null || themeClassHandle === void 0 ? void 0 : themeClassHandle.onRender
});
},
render() {
var _a, _b;
const {
mergedClsPrefix,
rtlEnabled,
closable,
color: {
borderColor
} = {},
round,
onRender,
$slots
} = this;
onRender === null || onRender === void 0 ? void 0 : onRender();
const avatarNode = resolveWrappedSlot($slots.avatar, (children) => children && h("div", {
class: `${mergedClsPrefix}-tag__avatar`
}, children));
const iconNode = resolveWrappedSlot($slots.icon, (children) => children && h("div", {
class: `${mergedClsPrefix}-tag__icon`
}, children));
return h("div", {
class: [`${mergedClsPrefix}-tag`, this.themeClass, {
[`${mergedClsPrefix}-tag--rtl`]: rtlEnabled,
[`${mergedClsPrefix}-tag--strong`]: this.strong,
[`${mergedClsPrefix}-tag--disabled`]: this.disabled,
[`${mergedClsPrefix}-tag--checkable`]: this.checkable,
[`${mergedClsPrefix}-tag--checked`]: this.checkable && this.checked,
[`${mergedClsPrefix}-tag--round`]: round,
[`${mergedClsPrefix}-tag--avatar`]: avatarNode,
[`${mergedClsPrefix}-tag--icon`]: iconNode,
[`${mergedClsPrefix}-tag--closable`]: closable
}],
style: this.cssVars,
onClick: this.handleClick,
onMouseenter: this.onMouseenter,
onMouseleave: this.onMouseleave
}, iconNode || avatarNode, h("span", {
class: `${mergedClsPrefix}-tag__content`,
ref: "contentRef"
}, (_b = (_a = this.$slots).default) === null || _b === void 0 ? void 0 : _b.call(_a)), !this.checkable && closable ? h(NBaseClose, {
clsPrefix: mergedClsPrefix,
class: `${mergedClsPrefix}-tag__close`,
disabled: this.disabled,
onClick: this.handleCloseClick,
focusable: this.internalCloseFocusable,
round,
isButtonTag: this.internalCloseIsButtonTag,
absolute: true
}) : null, !this.checkable && this.mergedBordered ? h("div", {
class: `${mergedClsPrefix}-tag__border`,
style: {
borderColor
}
}) : null);
}
});
export {
__unplugin_components_4 as _,
tagInjectionKey as t
};

Binary file not shown.

View File

@@ -0,0 +1,63 @@
import { as as inject, ce as dialogApiInjectionKey, bi as throwError, d as defineComponent, j as openBlock, c as createElementBlock, b as createBaseVNode, R as isElectron, _ as _export_sfc } from "./index-DKaFsuse.js";
function useDialog() {
const dialog = inject(dialogApiInjectionKey, null);
if (dialog === null) {
throwError("use-dialog", "No outer <n-dialog-provider /> founded.");
}
return dialog;
}
const _sfc_main = /* @__PURE__ */ defineComponent({
__name: "TitleBar",
setup(__props) {
const dialog = useDialog();
const minimize = () => {
if (!isElectron) {
return;
}
window.api.minimize();
};
const close = () => {
if (!isElectron) {
return;
}
dialog.warning({
title: "提示",
content: "确定要退出吗?",
positiveText: "最小化",
negativeText: "关闭",
onPositiveClick: () => {
window.api.minimize();
},
onNegativeClick: () => {
window.api.close();
}
});
};
const drag = (event) => {
if (!isElectron) {
return;
}
window.api.dragStart(event);
};
return (_ctx, _cache) => {
return openBlock(), createElementBlock("div", {
id: "title-bar",
onMousedown: drag
}, [
_cache[2] || (_cache[2] = createBaseVNode("div", { id: "title" }, "Alger Music", -1)),
createBaseVNode("div", { id: "buttons" }, [
createBaseVNode("button", { onClick: minimize }, _cache[0] || (_cache[0] = [
createBaseVNode("i", { class: "iconfont icon-minisize" }, null, -1)
])),
createBaseVNode("button", { onClick: close }, _cache[1] || (_cache[1] = [
createBaseVNode("i", { class: "iconfont icon-close" }, null, -1)
]))
])
], 32);
};
}
});
const TitleBar = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-6ad4ce60"]]);
export {
TitleBar as default
};

Binary file not shown.

View File

@@ -0,0 +1,37 @@
#title-bar[data-v-6ad4ce60] {
-webkit-app-region: drag;
position: relative;
display: flex;
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
justify-content: space-between;
padding-left: 1.5rem;
padding-right: 1.5rem;
padding-top: 0.5rem;
padding-bottom: 0.5rem;
--tw-text-opacity: 1;
color: rgb(0 0 0 / var(--tw-text-opacity, 1));
}#title-bar[data-v-6ad4ce60]:is(.dark *) {
--tw-text-opacity: 1;
color: rgb(255 255 255 / var(--tw-text-opacity, 1));
}#title-bar[data-v-6ad4ce60] {
z-index: 9999999;
}
#buttons[data-v-6ad4ce60] {
display: flex;
gap: 1rem;
-webkit-app-region: no-drag;
}
button[data-v-6ad4ce60] {
--tw-text-opacity: 1;
color: rgb(75 85 99 / var(--tw-text-opacity, 1));
}
button[data-v-6ad4ce60]:hover {
--tw-text-opacity: 1;
color: rgb(34 197 94 / var(--tw-text-opacity, 1));
}
button[data-v-6ad4ce60]:is(.dark *) {
--tw-text-opacity: 1;
color: rgb(156 163 175 / var(--tw-text-opacity, 1));
}

View File

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

@@ -0,0 +1,31 @@
import { ad as request } from "./index-DKaFsuse.js";
const getHotSinger = (params) => {
return request.get("/top/artists", { params });
};
const getSearchKeyword = () => {
return request.get("/search/default");
};
const getHotSearch = () => {
return request.get("/search/hot/detail");
};
const getPlaylistCategory = () => {
return request.get("/playlist/catlist");
};
const getRecommendMusic = (params) => {
return request.get("/personalized/newsong", { params });
};
const getDayRecommend = () => {
return request.get("/recommend/songs");
};
const getNewAlbum = () => {
return request.get("/album/newest");
};
export {
getNewAlbum as a,
getHotSinger as b,
getDayRecommend as c,
getRecommendMusic as d,
getHotSearch as e,
getSearchKeyword as f,
getPlaylistCategory as g
};

View File

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

View File

@@ -0,0 +1,43 @@
.favorite-page[data-v-2d1a7423] {display: flex;height: 100%;flex-direction: column;padding-top: 0.5rem;--tw-bg-opacity: 1;background-color: rgb(255 255 255 / var(--tw-bg-opacity, 1))
}.favorite-page[data-v-2d1a7423]:is(.dark *) {--tw-bg-opacity: 1;background-color: rgb(0 0 0 / var(--tw-bg-opacity, 1))
}
.favorite-page .favorite-header[data-v-2d1a7423] {display: flex;flex-shrink: 0;align-items: center;justify-content: space-between;padding-left: 1rem;padding-right: 1rem
}
.favorite-page .favorite-header h2[data-v-2d1a7423] {padding-bottom: 0.5rem;font-size: 1.25rem;line-height: 1.75rem;font-weight: 700;--tw-text-opacity: 1;color: rgb(17 24 39 / var(--tw-text-opacity, 1))
}
.favorite-page .favorite-header h2[data-v-2d1a7423]:is(.dark *) {--tw-text-opacity: 1;color: rgb(255 255 255 / var(--tw-text-opacity, 1))
}
.favorite-page .favorite-header .favorite-count[data-v-2d1a7423] {font-size: 0.875rem;line-height: 1.25rem;--tw-text-opacity: 1;color: rgb(107 114 128 / var(--tw-text-opacity, 1))
}
.favorite-page .favorite-header .favorite-count[data-v-2d1a7423]:is(.dark *) {--tw-text-opacity: 1;color: rgb(156 163 175 / var(--tw-text-opacity, 1))
}
.favorite-page .favorite-main[data-v-2d1a7423] {display: flex;min-height: 0px;flex-grow: 1;flex-direction: column
}
.favorite-page .favorite-main .favorite-content[data-v-2d1a7423] {min-height: 0px;flex-grow: 1
}
.favorite-page .favorite-main .favorite-content .empty-tip[data-v-2d1a7423] {display: flex;height: 100%;align-items: center;justify-content: center;--tw-text-opacity: 1;color: rgb(107 114 128 / var(--tw-text-opacity, 1))
}
.favorite-page .favorite-main .favorite-content .empty-tip[data-v-2d1a7423]:is(.dark *) {--tw-text-opacity: 1;color: rgb(156 163 175 / var(--tw-text-opacity, 1))
}
.favorite-page .favorite-main .favorite-content .favorite-list[data-v-2d1a7423] > :not([hidden]) ~ :not([hidden]) {--tw-space-y-reverse: 0;margin-top: calc(0.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom: calc(0.5rem * var(--tw-space-y-reverse))
}
.favorite-page .favorite-main .favorite-content .favorite-list[data-v-2d1a7423] {padding-left: 1rem;padding-right: 1rem;padding-bottom: 1rem
}
.favorite-page .favorite-main .favorite-content .favorite-list-more[data-v-2d1a7423] {margin-top: 1rem
}
.favorite-page .favorite-main .favorite-content .favorite-list-more .n-button[data-v-2d1a7423] {--tw-text-opacity: 1;color: rgb(34 197 94 / var(--tw-text-opacity, 1))
}
.favorite-page .favorite-main .favorite-content .favorite-list-more .n-button[data-v-2d1a7423]:hover {--tw-text-opacity: 1;color: rgb(22 163 74 / var(--tw-text-opacity, 1))
}
.loading-wrapper[data-v-2d1a7423] {display: flex;align-items: center;justify-content: center;padding-top: 5rem;padding-bottom: 5rem
}
.no-more-tip[data-v-2d1a7423] {padding-top: 1rem;padding-bottom: 1rem;text-align: center;font-size: 0.875rem;line-height: 1.25rem;--tw-text-opacity: 1;color: rgb(107 114 128 / var(--tw-text-opacity, 1))
}
.no-more-tip[data-v-2d1a7423]:is(.dark *) {--tw-text-opacity: 1;color: rgb(156 163 175 / var(--tw-text-opacity, 1))
}
.mobile .favorite-page[data-v-2d1a7423] {padding: 1rem
}
.mobile .favorite-page .favorite-header[data-v-2d1a7423] {margin-bottom: 1rem
}
.mobile .favorite-page .favorite-header h2[data-v-2d1a7423] {font-size: 1.25rem;line-height: 1.75rem
}

Binary file not shown.

View File

@@ -0,0 +1,540 @@
import { p as cB, V as cNotM, m as c, W as cM, Y as cE, d as defineComponent, x as useConfig, Z as useStyle, $ as provide, F as useRtl, l as h, a0 as buttonGroupInjectionKey, r as ref, G as computed, E as watch, o as onMounted, a1 as onUnmounted, c as createElementBlock, b as createBaseVNode, e as createVNode, f as withCtx, t as toDisplayString, n as normalizeClass, a2 as normalizeStyle, a3 as Fragment, a4 as renderList, j as openBlock, T as createCommentVNode, B as Button, _ as _export_sfc } from "./index-DKaFsuse.js";
const zero = "0!important";
const n1 = "-1px!important";
function createLeftBorderStyle(type) {
return cM(`${type}-type`, [c("& +", [cB("button", {}, [cM(`${type}-type`, [cE("border", {
borderLeftWidth: zero
}), cE("state-border", {
left: n1
})])])])]);
}
function createTopBorderStyle(type) {
return cM(`${type}-type`, [c("& +", [cB("button", [cM(`${type}-type`, [cE("border", {
borderTopWidth: zero
}), cE("state-border", {
top: n1
})])])])]);
}
const style = cB("button-group", `
flex-wrap: nowrap;
display: inline-flex;
position: relative;
`, [cNotM("vertical", {
flexDirection: "row"
}, [cNotM("rtl", [cB("button", [c("&:first-child:not(:last-child)", `
margin-right: ${zero};
border-top-right-radius: ${zero};
border-bottom-right-radius: ${zero};
`), c("&:last-child:not(:first-child)", `
margin-left: ${zero};
border-top-left-radius: ${zero};
border-bottom-left-radius: ${zero};
`), c("&:not(:first-child):not(:last-child)", `
margin-left: ${zero};
margin-right: ${zero};
border-radius: ${zero};
`), createLeftBorderStyle("default"), cM("ghost", [createLeftBorderStyle("primary"), createLeftBorderStyle("info"), createLeftBorderStyle("success"), createLeftBorderStyle("warning"), createLeftBorderStyle("error")])])])]), cM("vertical", {
flexDirection: "column"
}, [cB("button", [c("&:first-child:not(:last-child)", `
margin-bottom: ${zero};
margin-left: ${zero};
margin-right: ${zero};
border-bottom-left-radius: ${zero};
border-bottom-right-radius: ${zero};
`), c("&:last-child:not(:first-child)", `
margin-top: ${zero};
margin-left: ${zero};
margin-right: ${zero};
border-top-left-radius: ${zero};
border-top-right-radius: ${zero};
`), c("&:not(:first-child):not(:last-child)", `
margin: ${zero};
border-radius: ${zero};
`), createTopBorderStyle("default"), cM("ghost", [createTopBorderStyle("primary"), createTopBorderStyle("info"), createTopBorderStyle("success"), createTopBorderStyle("warning"), createTopBorderStyle("error")])])])]);
const buttonGroupProps = {
size: {
type: String,
default: void 0
},
vertical: Boolean
};
const __unplugin_components_1 = defineComponent({
name: "ButtonGroup",
props: buttonGroupProps,
setup(props) {
const {
mergedClsPrefixRef,
mergedRtlRef
} = useConfig(props);
useStyle("-button-group", style, mergedClsPrefixRef);
provide(buttonGroupInjectionKey, props);
const rtlEnabledRef = useRtl("ButtonGroup", mergedRtlRef, mergedClsPrefixRef);
return {
rtlEnabled: rtlEnabledRef,
mergedClsPrefix: mergedClsPrefixRef
};
},
render() {
const {
mergedClsPrefix
} = this;
return h("div", {
class: [`${mergedClsPrefix}-button-group`, this.rtlEnabled && `${mergedClsPrefix}-button-group--rtl`, this.vertical && `${mergedClsPrefix}-button-group--vertical`],
role: "group"
}, this.$slots);
}
});
const _hoisted_1 = { class: "font-size-controls" };
const _hoisted_2 = { class: "play-controls" };
const _hoisted_3 = { class: "control-buttons" };
const _hoisted_4 = {
key: 0,
class: "ri-sun-line"
};
const _hoisted_5 = {
key: 1,
class: "ri-moon-line"
};
const _hoisted_6 = {
key: 0,
class: "ri-lock-line"
};
const _hoisted_7 = {
key: 1,
class: "ri-lock-unlock-line"
};
const _hoisted_8 = { class: "lyric-scroll" };
const _hoisted_9 = {
key: 1,
class: "lyric-empty"
};
const fontSizeStep = 2;
const TIME_OFFSET = 400;
const _sfc_main = /* @__PURE__ */ defineComponent({
...{
name: "Lyric"
},
__name: "index",
setup(__props) {
const windowData = window;
const containerRef = ref(null);
const containerHeight = ref(0);
const lineHeight = ref(60);
const currentIndex = ref(0);
const fontSize = ref(24);
const animationFrameId = ref(null);
const lastUpdateTime = ref(performance.now());
const staticData = ref({
lrcArray: [],
lrcTimeArray: [],
allTime: 0,
playMusic: {}
});
const dynamicData = ref({
nowTime: 0,
startCurrentTime: 0,
nextTime: 0,
isPlay: true
});
const lyricSetting = ref({
...localStorage.getItem("lyricData") ? JSON.parse(localStorage.getItem("lyricData") || "") : {
isTop: false,
theme: "dark",
isLock: false
}
});
const isHovering = ref(false);
const showControls = computed(() => {
if (lyricSetting.value.isLock) {
return isHovering.value;
}
return true;
});
const handleMouseEnter = () => {
if (lyricSetting.value.isLock) {
isHovering.value = true;
windowData.electron.ipcRenderer.send("set-ignore-mouse", true);
} else {
windowData.electron.ipcRenderer.send("set-ignore-mouse", false);
}
};
const handleMouseLeave = () => {
if (!lyricSetting.value.isLock) return;
isHovering.value = false;
windowData.electron.ipcRenderer.send("set-ignore-mouse", false);
};
watch(
() => lyricSetting.value.isLock,
(newLock) => {
if (newLock) {
isHovering.value = false;
}
}
);
onMounted(() => {
if (lyricSetting.value.isLock) {
isHovering.value = false;
}
});
onUnmounted(() => {
});
const wrapperStyle = computed(() => {
if (!containerHeight.value) {
return {
transform: "translateY(0)",
transition: "none"
};
}
const containerCenter = containerHeight.value / 2;
const currentLineTop = currentIndex.value * lineHeight.value + containerHeight.value * 0.2 + lineHeight.value;
const targetOffset = containerCenter - currentLineTop;
const contentHeight = staticData.value.lrcArray.length * lineHeight.value + containerHeight.value * 0.4;
const minOffset = -(contentHeight - containerHeight.value);
const maxOffset = 0;
const finalOffset = Math.min(maxOffset, Math.max(minOffset, targetOffset));
return {
transform: `translateY(${finalOffset}px)`,
transition: "transform 0.3s cubic-bezier(0.4, 0, 0.2, 1)"
};
});
const lyricLineStyle = computed(() => ({
height: `${lineHeight.value}px`
}));
const updateContainerHeight = () => {
if (!containerRef.value) return;
containerHeight.value = containerRef.value.clientHeight;
const baseLineHeight = fontSize.value * 2.5;
const maxAllowedHeight = containerHeight.value / 3;
lineHeight.value = Math.min(maxAllowedHeight, Math.max(40, baseLineHeight));
};
const handleFontSizeChange = async () => {
saveFontSize();
updateContainerHeight();
};
const increaseFontSize = async () => {
if (fontSize.value < 48) {
fontSize.value += fontSizeStep;
await handleFontSizeChange();
}
};
const decreaseFontSize = async () => {
if (fontSize.value > 12) {
fontSize.value -= fontSizeStep;
await handleFontSizeChange();
}
};
const saveFontSize = () => {
localStorage.setItem("lyricFontSize", fontSize.value.toString());
};
onMounted(() => {
const resizeObserver = new ResizeObserver(() => {
updateContainerHeight();
});
if (containerRef.value) {
resizeObserver.observe(containerRef.value);
}
onUnmounted(() => {
resizeObserver.disconnect();
});
});
const actualTime = ref(0);
const currentProgress = computed(() => {
const { startCurrentTime, nextTime } = dynamicData.value;
if (!startCurrentTime || !nextTime) return 0;
const duration = nextTime - startCurrentTime;
const elapsed = actualTime.value - startCurrentTime;
return Math.min(Math.max(elapsed / duration, 0), 1);
});
const getLyricStyle = (index2) => {
if (index2 !== currentIndex.value) return {};
const progress = currentProgress.value * 100;
return {
background: `linear-gradient(to right, var(--highlight-color) ${progress}%, var(--text-color) ${progress}%)`,
WebkitBackgroundClip: "text",
WebkitTextFillColor: "transparent",
transition: "all 0.1s linear"
};
};
const updateProgress = () => {
if (!dynamicData.value.isPlay) {
if (animationFrameId.value) {
cancelAnimationFrame(animationFrameId.value);
animationFrameId.value = null;
}
return;
}
const timeDiff = (performance.now() - lastUpdateTime.value) / 1e3;
actualTime.value = dynamicData.value.nowTime + timeDiff + TIME_OFFSET / 1e3;
animationFrameId.value = requestAnimationFrame(updateProgress);
};
watch(
() => dynamicData.value,
(newData) => {
lastUpdateTime.value = performance.now();
actualTime.value = newData.nowTime + TIME_OFFSET / 1e3;
if (newData.isPlay && !animationFrameId.value) {
updateProgress();
}
},
{ deep: true }
);
watch(
() => dynamicData.value.isPlay,
(isPlaying) => {
if (isPlaying) {
lastUpdateTime.value = performance.now();
updateProgress();
} else if (animationFrameId.value) {
cancelAnimationFrame(animationFrameId.value);
animationFrameId.value = null;
}
}
);
const handleDataUpdate = (parsedData) => {
if (!parsedData) {
console.error("Invalid update data received:", parsedData);
return;
}
staticData.value = {
lrcArray: parsedData.lrcArray || [],
lrcTimeArray: parsedData.lrcTimeArray || [],
allTime: parsedData.allTime || 0,
playMusic: parsedData.playMusic || {}
};
dynamicData.value = {
nowTime: parsedData.nowTime || 0,
startCurrentTime: parsedData.startCurrentTime || 0,
nextTime: parsedData.nextTime || 0,
isPlay: parsedData.isPlay
};
if (typeof parsedData.nowIndex === "number") {
currentIndex.value = parsedData.nowIndex;
}
};
onMounted(() => {
const savedFontSize = localStorage.getItem("lyricFontSize");
if (savedFontSize) {
fontSize.value = Number(savedFontSize);
lineHeight.value = fontSize.value * 2.5;
}
updateContainerHeight();
window.addEventListener("resize", updateContainerHeight);
windowData.electron.ipcRenderer.on("receive-lyric", (_, data) => {
try {
const parsedData = JSON.parse(data);
handleDataUpdate(parsedData);
} catch (error) {
console.error("Error parsing lyric data:", error);
}
});
});
onUnmounted(() => {
window.removeEventListener("resize", updateContainerHeight);
});
const checkTheme = () => {
if (lyricSetting.value.theme === "light") {
lyricSetting.value.theme = "dark";
} else {
lyricSetting.value.theme = "light";
}
};
const handleLock = () => {
lyricSetting.value.isLock = !lyricSetting.value.isLock;
windowData.electron.ipcRenderer.send("set-ignore-mouse", lyricSetting.value.isLock);
};
const handleClose = () => {
windowData.electron.ipcRenderer.send("close-lyric");
};
watch(
() => lyricSetting.value,
(newValue) => {
localStorage.setItem("lyricData", JSON.stringify(newValue));
},
{ deep: true }
);
const isDragging = ref(false);
const startPosition = ref({ x: 0, y: 0 });
const handleMouseDown = (e) => {
if (lyricSetting.value.isLock || e.target.closest(".control-buttons") || e.target.closest(".font-size-controls")) {
return;
}
if (e.button !== 0) return;
isDragging.value = true;
startPosition.value = { x: e.screenX, y: e.screenY };
const handleMouseMove = (e2) => {
if (!isDragging.value) return;
const deltaX = e2.screenX - startPosition.value.x;
const deltaY = e2.screenY - startPosition.value.y;
windowData.electron.ipcRenderer.send("lyric-drag-move", { deltaX, deltaY });
startPosition.value = { x: e2.screenX, y: e2.screenY };
};
const handleMouseUp = () => {
if (!isDragging.value) return;
isDragging.value = false;
document.removeEventListener("mousemove", handleMouseMove);
document.removeEventListener("mouseup", handleMouseUp);
};
document.addEventListener("mousemove", handleMouseMove);
document.addEventListener("mouseup", handleMouseUp);
};
onUnmounted(() => {
isDragging.value = false;
});
onMounted(() => {
const lyricLock = document.getElementById("lyric-lock");
if (lyricLock) {
lyricLock.onmouseenter = () => {
if (lyricSetting.value.isLock) {
windowData.electron.ipcRenderer.send("set-ignore-mouse", false);
}
};
lyricLock.onmouseleave = () => {
if (lyricSetting.value.isLock) {
windowData.electron.ipcRenderer.send("set-ignore-mouse", true);
}
};
}
});
const handlePlayPause = () => {
windowData.electron.ipcRenderer.send("control-back", "playpause");
};
const handlePrev = () => {
windowData.electron.ipcRenderer.send("control-back", "prev");
};
const handleNext = () => {
windowData.electron.ipcRenderer.send("control-back", "next");
};
return (_ctx, _cache) => {
const _component_n_button = Button;
const _component_n_button_group = __unplugin_components_1;
return openBlock(), createElementBlock("div", {
class: normalizeClass(["lyric-window", [lyricSetting.value.theme, { lyric_lock: lyricSetting.value.isLock }]]),
onMousedown: handleMouseDown,
onMouseenter: handleMouseEnter,
onMouseleave: handleMouseLeave
}, [
_cache[5] || (_cache[5] = createBaseVNode("div", { class: "drag-overlay" }, null, -1)),
createBaseVNode("div", {
class: normalizeClass(["control-bar", { "control-bar-show": showControls.value }])
}, [
createBaseVNode("div", _hoisted_1, [
createVNode(_component_n_button_group, null, {
default: withCtx(() => [
createVNode(_component_n_button, {
quaternary: "",
size: "small",
disabled: fontSize.value <= 12,
onClick: decreaseFontSize
}, {
default: withCtx(() => _cache[0] || (_cache[0] = [
createBaseVNode("i", { class: "ri-subtract-line" }, null, -1)
])),
_: 1
}, 8, ["disabled"]),
createVNode(_component_n_button, {
quaternary: "",
size: "small",
disabled: fontSize.value >= 48,
onClick: increaseFontSize
}, {
default: withCtx(() => _cache[1] || (_cache[1] = [
createBaseVNode("i", { class: "ri-add-line" }, null, -1)
])),
_: 1
}, 8, ["disabled"])
]),
_: 1
}),
createBaseVNode("div", null, toDisplayString(staticData.value.playMusic.name), 1)
]),
createBaseVNode("div", _hoisted_2, [
createBaseVNode("div", {
class: "control-button",
onClick: handlePrev
}, _cache[2] || (_cache[2] = [
createBaseVNode("i", { class: "ri-skip-back-fill" }, null, -1)
])),
createBaseVNode("div", {
class: "control-button play-button",
onClick: handlePlayPause
}, [
createBaseVNode("i", {
class: normalizeClass(dynamicData.value.isPlay ? "ri-pause-fill" : "ri-play-fill")
}, null, 2)
]),
createBaseVNode("div", {
class: "control-button",
onClick: handleNext
}, _cache[3] || (_cache[3] = [
createBaseVNode("i", { class: "ri-skip-forward-fill" }, null, -1)
]))
]),
createBaseVNode("div", _hoisted_3, [
createBaseVNode("div", {
class: "control-button",
onClick: checkTheme
}, [
lyricSetting.value.theme === "light" ? (openBlock(), createElementBlock("i", _hoisted_4)) : (openBlock(), createElementBlock("i", _hoisted_5))
]),
createBaseVNode("div", {
id: "lyric-lock",
class: "control-button",
onClick: handleLock
}, [
lyricSetting.value.isLock ? (openBlock(), createElementBlock("i", _hoisted_6)) : (openBlock(), createElementBlock("i", _hoisted_7))
]),
createBaseVNode("div", {
class: "control-button",
onClick: handleClose
}, _cache[4] || (_cache[4] = [
createBaseVNode("i", { class: "ri-close-line" }, null, -1)
]))
])
], 2),
createBaseVNode("div", {
ref_key: "containerRef",
ref: containerRef,
class: "lyric-container"
}, [
createBaseVNode("div", _hoisted_8, [
createBaseVNode("div", {
class: "lyric-wrapper",
style: normalizeStyle(wrapperStyle.value)
}, [
staticData.value.lrcArray?.length > 0 ? (openBlock(true), createElementBlock(Fragment, { key: 0 }, renderList(staticData.value.lrcArray, (line, index2) => {
return openBlock(), createElementBlock("div", {
key: index2,
class: normalizeClass(["lyric-line", {
"lyric-line-current": index2 === currentIndex.value,
"lyric-line-passed": index2 < currentIndex.value,
"lyric-line-next": index2 === currentIndex.value + 1
}]),
style: normalizeStyle(lyricLineStyle.value)
}, [
createBaseVNode("div", {
class: "lyric-text",
style: normalizeStyle({ fontSize: `${fontSize.value}px` })
}, [
createBaseVNode("span", {
class: "lyric-text-inner",
style: normalizeStyle(getLyricStyle(index2))
}, toDisplayString(line.text || ""), 5)
], 4),
line.trText ? (openBlock(), createElementBlock("div", {
key: 0,
class: "lyric-translation",
style: normalizeStyle({ fontSize: `${fontSize.value * 0.6}px` })
}, toDisplayString(line.trText), 5)) : createCommentVNode("", true)
], 6);
}), 128)) : (openBlock(), createElementBlock("div", _hoisted_9, "无歌词"))
], 4)
])
], 512)
], 34);
};
}
});
const index = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-4abaac34"]]);
export {
index as default
};

Binary file not shown.

View File

@@ -0,0 +1,203 @@
body {
background-color: transparent !important;
}
.lyric-window[data-v-4abaac34] {
width: 100vw;
height: 100vh;
position: relative;
overflow: hidden;
background: transparent;
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
transition: background-color 0.2s ease;
cursor: default;
}
.lyric-window[data-v-4abaac34]:hover {
background: rgba(0, 0, 0, 0.5);
}
.lyric-window:hover .control-bar-show[data-v-4abaac34] {
opacity: 1;
visibility: visible;
}
.lyric-window[data-v-4abaac34]:active {
cursor: grabbing;
}
.lyric-window.dark[data-v-4abaac34] {
--text-color: #ffffff;
--text-secondary: rgba(255, 255, 255, 0.6);
--highlight-color: #1db954;
--control-bg: rgba(124, 124, 124, 0.3);
}
.lyric-window.light[data-v-4abaac34] {
--text-color: #333333;
--text-secondary: rgba(51, 51, 51, 0.6);
--highlight-color: #1db954;
--control-bg: rgba(255, 255, 255, 0.3);
}
.control-bar[data-v-4abaac34] {
position: absolute;
top: 10px;
left: 0;
right: 0;
height: 80px;
display: flex;
justify-content: space-between;
align-items: start;
padding: 0 20px;
opacity: 0;
visibility: hidden;
transition: opacity 0.2s ease, visibility 0.2s ease;
z-index: 100;
}
.control-bar .font-size-controls[data-v-4abaac34] {
-webkit-app-region: no-drag;
color: var(--text-color);
display: flex;
align-items: center;
gap: 16px;
}
.control-bar .play-controls[data-v-4abaac34] {
position: absolute;
top: 0px;
left: 50%;
transform: translateX(-50%);
display: flex;
align-items: center;
gap: 16px;
-webkit-app-region: no-drag;
}
.control-bar .play-controls .play-button[data-v-4abaac34] {
width: 36px;
height: 36px;
}
.control-bar .play-controls .play-button i[data-v-4abaac34] {
font-size: 24px;
}
.control-bar .control-buttons[data-v-4abaac34] {
-webkit-app-region: no-drag;
}
.control-buttons[data-v-4abaac34] {
display: flex;
gap: 16px;
-webkit-app-region: no-drag;
}
.control-button[data-v-4abaac34] {
width: 36px;
height: 36px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
border-radius: 8px;
color: var(--text-color);
transition: all 0.2s ease;
}
.control-button[data-v-4abaac34]:hover {
background: var(--control-bg);
}
.control-button i[data-v-4abaac34] {
font-size: 20px;
text-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
}
.control-button i.active[data-v-4abaac34] {
color: var(--highlight-color);
}
.lyric-container[data-v-4abaac34] {
position: absolute;
top: 80px;
left: 0;
right: 0;
bottom: 0;
overflow: hidden;
z-index: 100;
}
.lyric-scroll[data-v-4abaac34] {
height: 100%;
overflow: hidden;
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: center;
-webkit-mask-image: linear-gradient(to bottom, transparent 0%, black 20%, black 80%, transparent 100%);
mask-image: linear-gradient(to bottom, transparent 0%, black 20%, black 80%, transparent 100%);
}
.lyric-wrapper[data-v-4abaac34] {
will-change: transform;
padding: 20vh 0;
transform-origin: center center;
transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}
.lyric-line[data-v-4abaac34] {
padding: 4px 20px;
text-align: center;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.lyric-line.lyric-line-current[data-v-4abaac34] {
transform: scale(1.05);
opacity: 1;
}
.lyric-line.lyric-line-passed[data-v-4abaac34] {
opacity: 0.6;
}
.lyric-text[data-v-4abaac34] {
font-weight: 600;
margin-bottom: 2px;
color: var(--text-color);
white-space: pre-wrap;
word-break: break-all;
text-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
transition: all 0.2s ease;
line-height: 1.4;
}
.lyric-translation[data-v-4abaac34] {
color: var(--text-secondary);
white-space: pre-wrap;
word-break: break-all;
text-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
transition: font-size 0.2s ease;
line-height: 1.4;
}
.lyric-empty[data-v-4abaac34] {
text-align: center;
color: var(--text-secondary);
font-size: 16px;
padding: 20px;
}
body[data-v-4abaac34] {
background-color: transparent !important;
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif;
}
.lyric-content[data-v-4abaac34] {
transition: font-size 0.2s ease;
}
.lyric-line-current[data-v-4abaac34] {
opacity: 1;
}
.lyric_lock .control-bar .control-buttons .control-button[data-v-4abaac34]:not(:has(.ri-lock-line)):not(:has(.ri-lock-unlock-line)) {
display: none;
}
.lyric_lock .control-bar .font-size-controls[data-v-4abaac34] {
display: none;
}
.lyric_lock .control-bar .play-controls[data-v-4abaac34] {
display: none;
}
.lyric_lock[data-v-4abaac34] {
background: transparent;
}
.lyric_lock[data-v-4abaac34]:hover {
background: transparent;
}
.lyric_lock #lyric-lock[data-v-4abaac34] {
position: absolute;
top: 0;
right: 72px;
background: var(--control-bg);
}

Binary file not shown.

View File

@@ -0,0 +1,203 @@
import { ad as request, d as defineComponent, r as ref, G as computed, aq as onActivated, c as createElementBlock, n as normalizeClass, u as unref, a2 as normalizeStyle, b as createBaseVNode, t as toDisplayString, e as createVNode, f as withCtx, T as createCommentVNode, w as withDirectives, S as Scrollbar, ab as resolveDirective, g as useStore, h as useRouter, j as openBlock, s as setAnimationClass, a7 as getImgUrl, a3 as Fragment, a4 as renderList, U as PlayBottom, ac as isMobile, a5 as setAnimationDelay, _ as _export_sfc } from "./index-DKaFsuse.js";
import { M as MusicList, a as getListDetail } from "./MusicList-s-QHu-iA.js";
import { S as SongItem } from "./SongItem-CoswpGn6.js";
import { _ as __unplugin_components_2 } from "./Avatar-rQ2og-6c.js";
import { N as NImage } from "./Image-DXClIklC.js";
import "./Drawer-BEJ8Ydua.js";
import "./Ellipsis-D4R5dIX2.js";
import "./Tag-C0oC92WF.js";
import "./use-locale-DLWAOXez.js";
function getUserDetail(uid) {
return request.get("/user/detail", { params: { uid } });
}
function getUserPlaylist(uid) {
return request.get("/user/playlist", { params: { uid } });
}
function getUserRecord(uid, type = 0) {
return request.get("/user/record", { params: { uid, type } });
}
const _hoisted_1 = { class: "user-page" };
const _hoisted_2 = { class: "page" };
const _hoisted_3 = { class: "user-name" };
const _hoisted_4 = { class: "user-info" };
const _hoisted_5 = { class: "user-info-list" };
const _hoisted_6 = { class: "user-info-item" };
const _hoisted_7 = { class: "label" };
const _hoisted_8 = { class: "user-info-item" };
const _hoisted_9 = { class: "label" };
const _hoisted_10 = { class: "user-info-item" };
const _hoisted_11 = { class: "label" };
const _hoisted_12 = { class: "uesr-signature" };
const _hoisted_13 = ["onClick"];
const _hoisted_14 = { class: "play-list-item-info" };
const _hoisted_15 = { class: "play-list-item-name" };
const _hoisted_16 = { class: "play-list-item-count" };
const _hoisted_17 = { class: "record-list" };
const _hoisted_18 = { class: "play-count" };
const _sfc_main = /* @__PURE__ */ defineComponent({
...{
name: "User"
},
__name: "index",
setup(__props) {
const store = useStore();
const router = useRouter();
const userDetail = ref();
const playList = ref([]);
const recordList = ref();
const infoLoading = ref(false);
const user = computed(() => store.state.user);
const loadPage = async () => {
if (!user.value) {
router.push("/login");
return;
}
infoLoading.value = true;
const { data: userData } = await getUserDetail(user.value.userId);
userDetail.value = userData;
const { data: playlistData } = await getUserPlaylist(user.value.userId);
playList.value = playlistData.playlist;
const { data: recordData } = await getUserRecord(user.value.userId);
recordList.value = recordData.allData.map((item) => ({
...item,
...item.song,
picUrl: item.song.al.picUrl
}));
infoLoading.value = false;
};
onActivated(() => {
if (!user.value) {
router.push("/login");
} else {
loadPage();
}
});
const isShowList = ref(false);
const list = ref();
const listLoading = ref(false);
const showPlaylist = async (id, name) => {
isShowList.value = true;
listLoading.value = true;
list.value = {
name
};
const { data } = await getListDetail(id);
list.value = data.playlist;
listLoading.value = false;
};
const handlePlay = () => {
const tracks = recordList.value || [];
store.commit("setPlayList", tracks);
};
return (_ctx, _cache) => {
const _component_n_avatar = __unplugin_components_2;
const _component_n_image = NImage;
const _component_n_scrollbar = Scrollbar;
const _directive_loading = resolveDirective("loading");
return openBlock(), createElementBlock("div", _hoisted_1, [
userDetail.value ? (openBlock(), createElementBlock("div", {
key: 0,
class: normalizeClass(["left", unref(setAnimationClass)("animate__fadeInLeft")]),
style: normalizeStyle({ backgroundImage: `url(${unref(getImgUrl)(user.value.backgroundUrl)})` })
}, [
createBaseVNode("div", _hoisted_2, [
createBaseVNode("div", _hoisted_3, toDisplayString(user.value.nickname), 1),
createBaseVNode("div", _hoisted_4, [
createVNode(_component_n_avatar, {
round: "",
size: 50,
src: unref(getImgUrl)(user.value.avatarUrl, "50y50")
}, null, 8, ["src"]),
createBaseVNode("div", _hoisted_5, [
createBaseVNode("div", _hoisted_6, [
createBaseVNode("div", _hoisted_7, toDisplayString(userDetail.value.profile.followeds), 1),
_cache[1] || (_cache[1] = createBaseVNode("div", null, "粉丝", -1))
]),
createBaseVNode("div", _hoisted_8, [
createBaseVNode("div", _hoisted_9, toDisplayString(userDetail.value.profile.follows), 1),
_cache[2] || (_cache[2] = createBaseVNode("div", null, "关注", -1))
]),
createBaseVNode("div", _hoisted_10, [
createBaseVNode("div", _hoisted_11, toDisplayString(userDetail.value.level), 1),
_cache[3] || (_cache[3] = createBaseVNode("div", null, "等级", -1))
])
])
]),
createBaseVNode("div", _hoisted_12, toDisplayString(userDetail.value.profile.signature), 1),
createBaseVNode("div", {
class: normalizeClass(["play-list", unref(setAnimationClass)("animate__fadeInLeft")])
}, [
_cache[4] || (_cache[4] = createBaseVNode("div", { class: "title" }, "创建的歌单", -1)),
createVNode(_component_n_scrollbar, null, {
default: withCtx(() => [
(openBlock(true), createElementBlock(Fragment, null, renderList(playList.value, (item, index2) => {
return openBlock(), createElementBlock("div", {
key: index2,
class: "play-list-item",
onClick: ($event) => showPlaylist(item.id, item.name)
}, [
createVNode(_component_n_image, {
src: unref(getImgUrl)(item.coverImgUrl, "50y50"),
class: "play-list-item-img",
lazy: "",
"preview-disabled": ""
}, null, 8, ["src"]),
createBaseVNode("div", _hoisted_14, [
createBaseVNode("div", _hoisted_15, toDisplayString(item.name), 1),
createBaseVNode("div", _hoisted_16, toDisplayString(item.trackCount) + "首,播放" + toDisplayString(item.playCount) + "次 ", 1)
])
], 8, _hoisted_13);
}), 128)),
createVNode(PlayBottom)
]),
_: 1
})
], 2)
])
], 6)) : createCommentVNode("", true),
!unref(isMobile) ? withDirectives((openBlock(), createElementBlock("div", {
key: 1,
class: normalizeClass(["right", unref(setAnimationClass)("animate__fadeInRight")])
}, [
_cache[5] || (_cache[5] = createBaseVNode("div", { class: "title" }, "听歌排行", -1)),
createBaseVNode("div", _hoisted_17, [
createVNode(_component_n_scrollbar, null, {
default: withCtx(() => [
(openBlock(true), createElementBlock(Fragment, null, renderList(recordList.value, (item, index2) => {
return openBlock(), createElementBlock("div", {
key: item.id,
class: normalizeClass(["record-item", unref(setAnimationClass)("animate__bounceInUp")]),
style: normalizeStyle(unref(setAnimationDelay)(index2, 25))
}, [
createVNode(SongItem, {
class: "song-item",
item,
onPlay: handlePlay
}, null, 8, ["item"]),
createBaseVNode("div", _hoisted_18, toDisplayString(item.playCount) + "次", 1)
], 6);
}), 128)),
createVNode(PlayBottom)
]),
_: 1
})
])
], 2)), [
[_directive_loading, infoLoading.value]
]) : createCommentVNode("", true),
createVNode(MusicList, {
show: isShowList.value,
"onUpdate:show": _cache[0] || (_cache[0] = ($event) => isShowList.value = $event),
name: list.value?.name || "",
"song-list": list.value?.tracks || [],
"list-info": list.value,
loading: listLoading.value
}, null, 8, ["show", "name", "song-list", "list-info", "loading"])
]);
};
}
});
const index = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-be63ae6f"]]);
export {
index as default
};

Binary file not shown.

View File

@@ -0,0 +1,233 @@
import { d as defineComponent, r as ref, G as computed, o as onMounted, E as watch, c as createElementBlock, b as createBaseVNode, e as createVNode, f as withCtx, u as unref, i as isRef, af as useRoute, S as Scrollbar, a5 as setAnimationDelay, ab as resolveDirective, j as openBlock, ah as withModifiers, a3 as Fragment, a4 as renderList, n as normalizeClass, s as setAnimationClass, a2 as normalizeStyle, t as toDisplayString, w as withDirectives, a7 as getImgUrl, ai as formatNumber, T as createCommentVNode, aj as __unplugin_components_0, _ as _export_sfc } from "./index-DKaFsuse.js";
import { g as getPlaylistCategory } from "./home-BXGE9AqN.js";
import { M as MusicList, b as getListByCat, a as getListDetail } from "./MusicList-s-QHu-iA.js";
import { N as NImage } from "./Image-DXClIklC.js";
import "./SongItem-CoswpGn6.js";
import "./Ellipsis-D4R5dIX2.js";
import "./Drawer-BEJ8Ydua.js";
import "./Avatar-rQ2og-6c.js";
import "./Tag-C0oC92WF.js";
import "./use-locale-DLWAOXez.js";
const _hoisted_1 = { class: "list-page" };
const _hoisted_2 = { class: "play-list-type" };
const _hoisted_3 = ["onClick"];
const _hoisted_4 = { class: "recommend-list" };
const _hoisted_5 = ["onClick"];
const _hoisted_6 = { class: "recommend-item-img" };
const _hoisted_7 = { class: "top" };
const _hoisted_8 = { class: "play-count" };
const _hoisted_9 = { class: "recommend-item-title" };
const _hoisted_10 = {
key: 0,
class: "loading-more"
};
const _hoisted_11 = {
key: 1,
class: "no-more"
};
const TOTAL_ITEMS = 42;
const _sfc_main = /* @__PURE__ */ defineComponent({
...{
name: "List"
},
__name: "index",
setup(__props) {
const recommendList = ref([]);
const showMusic = ref(false);
const page = ref(0);
const hasMore = ref(true);
const isLoadingMore = ref(false);
const getItemAnimationDelay = (index2) => {
const currentPageIndex = index2 % TOTAL_ITEMS;
return setAnimationDelay(currentPageIndex, 30);
};
const recommendItem = ref();
const listDetail = ref();
const listLoading = ref(true);
const selectRecommendItem = async (item) => {
listLoading.value = true;
recommendItem.value = null;
listDetail.value = null;
showMusic.value = true;
recommendItem.value = item;
const { data } = await getListDetail(item.id);
listDetail.value = data;
listLoading.value = false;
};
const route = useRoute();
const listTitle = ref(route.query.type || "歌单列表");
const loading = ref(false);
const loadList = async (type, isLoadMore = false) => {
if (!hasMore.value && isLoadMore) return;
if (isLoadMore) {
isLoadingMore.value = true;
} else {
loading.value = true;
page.value = 0;
recommendList.value = [];
}
try {
const params = {
cat: type === "每日推荐" ? "" : type,
limit: TOTAL_ITEMS,
offset: page.value * TOTAL_ITEMS
};
const { data } = await getListByCat(params);
if (isLoadMore) {
recommendList.value.push(...data.playlists);
} else {
recommendList.value = data.playlists;
}
hasMore.value = data.more;
page.value++;
} catch (error) {
console.error("加载歌单列表失败:", error);
} finally {
loading.value = false;
isLoadingMore.value = false;
}
};
const handleScroll = (e) => {
const { scrollTop, scrollHeight, clientHeight } = e.target;
if (scrollTop + clientHeight >= scrollHeight - 100 && !isLoadingMore.value && hasMore.value) {
loadList(route.query.type, true);
}
};
const playlistCategory = ref();
const currentType = ref(route.query.type || "每日推荐");
const getAnimationDelay = computed(() => {
return (index2) => setAnimationDelay(index2, 30);
});
const loadPlaylistCategory = async () => {
const { data } = await getPlaylistCategory();
playlistCategory.value = {
...data,
sub: [
{
name: "每日推荐",
category: 0
},
...data.sub
]
};
};
const handleClickPlaylistType = (type) => {
currentType.value = type;
listTitle.value = type;
loading.value = true;
loadList(type);
};
const scrollbarRef = ref();
const handleWheel = (e) => {
const scrollbar = scrollbarRef.value;
if (scrollbar) {
const delta = e.deltaY || e.detail;
scrollbar.scrollBy({ left: delta });
}
};
onMounted(() => {
loadPlaylistCategory();
currentType.value = route.query.type || currentType.value;
loadList(currentType.value);
});
watch(
() => route.query,
async (newParams) => {
if (newParams.type) {
recommendList.value = [];
listTitle.value = newParams.type || "歌单列表";
currentType.value = newParams.type;
loading.value = true;
loadList(newParams.type);
}
}
);
return (_ctx, _cache) => {
const _component_n_scrollbar = Scrollbar;
const _component_n_image = NImage;
const _component_n_spin = __unplugin_components_0;
const _directive_loading = resolveDirective("loading");
return openBlock(), createElementBlock("div", _hoisted_1, [
createBaseVNode("div", _hoisted_2, [
createVNode(_component_n_scrollbar, {
ref_key: "scrollbarRef",
ref: scrollbarRef,
"x-scrollable": ""
}, {
default: withCtx(() => [
createBaseVNode("div", {
class: "categories-wrapper",
onWheel: withModifiers(handleWheel, ["prevent"])
}, [
(openBlock(true), createElementBlock(Fragment, null, renderList(unref(playlistCategory)?.sub, (item, index2) => {
return openBlock(), createElementBlock("span", {
key: item.name,
class: normalizeClass(["play-list-type-item", [unref(setAnimationClass)("animate__bounceIn"), { active: unref(currentType) === item.name }]]),
style: normalizeStyle(unref(getAnimationDelay)(index2)),
onClick: ($event) => handleClickPlaylistType(item.name)
}, toDisplayString(item.name), 15, _hoisted_3);
}), 128))
], 32)
]),
_: 1
}, 512)
]),
createVNode(_component_n_scrollbar, {
class: "recommend",
size: 100,
onScroll: handleScroll
}, {
default: withCtx(() => [
withDirectives((openBlock(), createElementBlock("div", _hoisted_4, [
(openBlock(true), createElementBlock(Fragment, null, renderList(unref(recommendList), (item, index2) => {
return openBlock(), createElementBlock("div", {
key: item.id,
class: normalizeClass(["recommend-item", unref(setAnimationClass)("animate__bounceIn")]),
style: normalizeStyle(getItemAnimationDelay(index2)),
onClick: withModifiers(($event) => selectRecommendItem(item), ["stop"])
}, [
createBaseVNode("div", _hoisted_6, [
createVNode(_component_n_image, {
class: "recommend-item-img-img",
src: unref(getImgUrl)(item.picUrl || item.coverImgUrl, "200y200"),
width: "200",
height: "200",
lazy: "",
"preview-disabled": ""
}, null, 8, ["src"]),
createBaseVNode("div", _hoisted_7, [
createBaseVNode("div", _hoisted_8, toDisplayString(unref(formatNumber)(item.playCount)), 1),
_cache[2] || (_cache[2] = createBaseVNode("i", { class: "iconfont icon-videofill" }, null, -1))
])
]),
createBaseVNode("div", _hoisted_9, toDisplayString(item.name), 1)
], 14, _hoisted_5);
}), 128))
])), [
[_directive_loading, unref(loading)]
]),
unref(isLoadingMore) ? (openBlock(), createElementBlock("div", _hoisted_10, [
createVNode(_component_n_spin, { size: "small" }),
_cache[3] || (_cache[3] = createBaseVNode("span", { class: "ml-2" }, "加载中...", -1))
])) : createCommentVNode("", true),
!unref(hasMore) && unref(recommendList).length > 0 ? (openBlock(), createElementBlock("div", _hoisted_11, "没有更多了")) : createCommentVNode("", true)
]),
_: 1
}),
createVNode(MusicList, {
show: unref(showMusic),
"onUpdate:show": _cache[0] || (_cache[0] = ($event) => isRef(showMusic) ? showMusic.value = $event : null),
loading: unref(listLoading),
"onUpdate:loading": _cache[1] || (_cache[1] = ($event) => isRef(listLoading) ? listLoading.value = $event : null),
name: unref(recommendItem)?.name || "",
"song-list": unref(listDetail)?.playlist.tracks || [],
"list-info": unref(listDetail)?.playlist
}, null, 8, ["show", "loading", "name", "song-list", "list-info"])
]);
};
}
});
const index = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-f9f1189c"]]);
export {
index as default
};

Binary file not shown.

View File

@@ -0,0 +1,336 @@
.title[data-v-686a7f41] {
margin-bottom: 1rem;
font-size: 1.125rem;
line-height: 1.75rem;
font-weight: 700;
--tw-text-opacity: 1;
color: rgb(17 24 39 / var(--tw-text-opacity, 1));
}
.title[data-v-686a7f41]:is(.dark *) {
--tw-text-opacity: 1;
color: rgb(255 255 255 / var(--tw-text-opacity, 1));
}
.play-list-type[data-v-686a7f41] {
width: 250px;
margin-right: 1rem;
}
.play-list-type-item[data-v-686a7f41], .play-list-type-showall[data-v-686a7f41] {
--tw-bg-opacity: 1;
background-color: rgb(255 255 255 / var(--tw-bg-opacity, 1));
--tw-text-opacity: 1;
color: rgb(17 24 39 / var(--tw-text-opacity, 1));
}
.play-list-type-item[data-v-686a7f41]:is(.dark *), .play-list-type-showall[data-v-686a7f41]:is(.dark *) {
--tw-bg-opacity: 1;
background-color: rgb(0 0 0 / var(--tw-bg-opacity, 1));
--tw-text-opacity: 1;
color: rgb(255 255 255 / var(--tw-text-opacity, 1));
}
.play-list-type-item[data-v-686a7f41], .play-list-type-showall[data-v-686a7f41] {
margin-right: 0.75rem;
margin-bottom: 0.75rem;
display: inline-block;
cursor: pointer;
border-radius: 0.75rem;
border-width: 1px;
--tw-border-opacity: 1;
border-color: rgb(229 231 235 / var(--tw-border-opacity, 1));
padding-top: 0.5rem;
padding-bottom: 0.5rem;
padding-left: 0.75rem;
padding-right: 0.75rem;
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, -webkit-backdrop-filter;
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter;
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter, -webkit-backdrop-filter;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-duration: 150ms;
}
.play-list-type-item[data-v-686a7f41]:hover, .play-list-type-showall[data-v-686a7f41]:hover {
--tw-bg-opacity: 1;
background-color: rgb(22 163 74 / var(--tw-bg-opacity, 1));
--tw-text-opacity: 1;
color: rgb(255 255 255 / var(--tw-text-opacity, 1));
}
.play-list-type-item[data-v-686a7f41]:is(.dark *), .play-list-type-showall[data-v-686a7f41]:is(.dark *) {
--tw-border-opacity: 1;
border-color: rgb(55 65 81 / var(--tw-border-opacity, 1));
}
.play-list-type-showall[data-v-686a7f41] {
display: block;
text-align: center;
}
.mobile .play-list-type[data-v-686a7f41] {
margin-left: 0px;
margin-right: 0px;
width: 100%;
}.recommend-album[data-v-1df7dbee] {
margin-left: 1.25rem;
margin-right: 1.25rem;
flex: 1 1 0%;
}
.recommend-album .title[data-v-1df7dbee] {
margin-bottom: 1rem;
font-size: 1.125rem;
line-height: 1.75rem;
font-weight: 700;
--tw-text-opacity: 1;
color: rgb(17 24 39 / var(--tw-text-opacity, 1));
}
.recommend-album .title[data-v-1df7dbee]:is(.dark *) {
--tw-text-opacity: 1;
color: rgb(255 255 255 / var(--tw-text-opacity, 1));
}
.recommend-album .recommend-album-list[data-v-1df7dbee] {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
grid-template-rows: repeat(3, minmax(0, 1fr));
gap: 0.5rem;
}
.recommend-album .recommend-album-list-item[data-v-1df7dbee] {
position: relative;
overflow: hidden;
border-radius: 0.75rem;
}
.recommend-album .recommend-album-list-item-img[data-v-1df7dbee] {
height: 100%;
width: 100%;
border-radius: 0.75rem;
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, -webkit-backdrop-filter;
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter;
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter, -webkit-backdrop-filter;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-duration: 150ms;
}
.recommend-album .recommend-album-list-item:hover img[data-v-1df7dbee] {
filter: brightness(50%);
}
.recommend-album .recommend-album-list-item-content[data-v-1df7dbee] {
position: absolute;
top: 0px;
left: 0px;
z-index: 10;
height: 100%;
width: 100%;
background-color: rgb(0 0 0 / var(--tw-bg-opacity, 1));
--tw-bg-opacity: 0.6;
padding: 1rem;
font-size: 1.25rem;
line-height: 1.75rem;
--tw-text-opacity: 1;
color: rgb(255 255 255 / var(--tw-text-opacity, 1));
opacity: 0;
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, -webkit-backdrop-filter;
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter;
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter, -webkit-backdrop-filter;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-duration: 150ms;
}
.recommend-album .recommend-album-list-item-content[data-v-1df7dbee]:is(.dark *) {
background-color: rgb(0 0 0 / var(--tw-bg-opacity, 1));
--tw-bg-opacity: 0.6;
}
.recommend-album .recommend-album-list-item-content[data-v-1df7dbee]:hover {
opacity: 1;
}.recommend-singer-list[data-v-f8da161d] {
display: flex;
height: 280px;
}
.recommend-singer-item[data-v-f8da161d] {
margin-right: 1.25rem;
display: flex;
height: 100%;
flex: 1 1 0%;
flex-direction: column;
justify-content: space-between;
overflow: hidden;
border-radius: 1.5rem;
padding: 1.25rem;
}
.recommend-singer-item-bg[data-v-f8da161d] {
position: absolute;
top: 0px;
left: 0px;
z-index: 0;
height: 100%;
width: 100%;
border-radius: 1.5rem;
--tw-bg-opacity: 1;
background-color: rgb(17 24 39 / var(--tw-bg-opacity, 1));
background-size: cover;
background-position: center;
background-repeat: no-repeat;
}
.recommend-singer-item-bg[data-v-f8da161d]:is(.dark *) {
--tw-bg-opacity: 1;
background-color: rgb(31 41 55 / var(--tw-bg-opacity, 1));
}
.recommend-singer-item-bg[data-v-f8da161d] {
filter: brightness(60%);
}
.recommend-singer-item-info[data-v-f8da161d] {
display: flex;
align-items: center;
padding: 0.5rem;
}
.recommend-singer-item-info-play[data-v-f8da161d] {
display: flex;
height: 3rem;
width: 3rem;
cursor: pointer;
align-items: center;
justify-content: center;
border-radius: 9999px;
--tw-bg-opacity: 1;
background-color: rgb(34 197 94 / var(--tw-bg-opacity, 1));
--tw-text-opacity: 1;
color: rgb(255 255 255 / var(--tw-text-opacity, 1));
}
.recommend-singer-item-info-play[data-v-f8da161d]:hover {
--tw-bg-opacity: 1;
background-color: rgb(22 163 74 / var(--tw-bg-opacity, 1));
}
.recommend-singer-item-info-name[data-v-f8da161d] {
--tw-text-opacity: 1;
color: rgb(243 244 246 / var(--tw-text-opacity, 1));
}
.recommend-singer-item-info-name[data-v-f8da161d]:is(.dark *) {
--tw-text-opacity: 1;
color: rgb(243 244 246 / var(--tw-text-opacity, 1));
}
.recommend-singer-item-count[data-v-f8da161d] {
--tw-text-opacity: 1;
color: rgb(243 244 246 / var(--tw-text-opacity, 1));
}
.recommend-singer-item-count[data-v-f8da161d]:is(.dark *) {
--tw-text-opacity: 1;
color: rgb(243 244 246 / var(--tw-text-opacity, 1));
}
.mobile .recommend-singer-list[data-v-f8da161d] {
height: 180px;
margin-left: 1rem;
}
.mobile .recommend-singer-item[data-v-f8da161d] {
border-radius: 0.75rem;
padding: 1rem;
}
.mobile .recommend-singer-item-bg[data-v-f8da161d] {
border-radius: 0.75rem;
}.title[data-v-ae2da107] {
margin-bottom: 1rem;
font-size: 1.125rem;
line-height: 1.75rem;
font-weight: 700;
--tw-text-opacity: 1;
color: rgb(17 24 39 / var(--tw-text-opacity, 1));
}
.title[data-v-ae2da107]:is(.dark *) {
--tw-text-opacity: 1;
color: rgb(255 255 255 / var(--tw-text-opacity, 1));
}
.recommend-music[data-v-ae2da107] {
flex: 1 1 auto;
}
.recommend-music .text-ellipsis[data-v-ae2da107] {
width: 100%;
}
.recommend-music-list[data-v-ae2da107] {
width: 100%;
border-radius: 1.5rem;
border-width: 1px;
--tw-border-opacity: 1;
border-color: rgb(229 231 235 / var(--tw-border-opacity, 1));
--tw-bg-opacity: 1;
background-color: rgb(255 255 255 / var(--tw-bg-opacity, 1));
padding: 0.5rem;
}
.recommend-music-list[data-v-ae2da107]:is(.dark *) {
--tw-border-opacity: 1;
border-color: rgb(55 65 81 / var(--tw-border-opacity, 1));
--tw-bg-opacity: 1;
background-color: rgb(0 0 0 / var(--tw-bg-opacity, 1));
}.main-page[data-v-b0ca1b97] {
height: 100%;
width: 100%;
overflow: hidden;
--tw-bg-opacity: 1;
background-color: rgb(255 255 255 / var(--tw-bg-opacity, 1))
}
.main-page[data-v-b0ca1b97]:is(.dark *) {
--tw-bg-opacity: 1;
background-color: rgb(0 0 0 / var(--tw-bg-opacity, 1))
}
.main-content[data-v-b0ca1b97] {
margin-top: 1.5rem;
margin-bottom: 7rem;
display: flex
}
.mobile .main-content[data-v-b0ca1b97] {
margin-left: 1rem;
margin-right: 1rem;
flex-direction: column
}
.mobile[data-v-b0ca1b97] .favorite-page {
margin-left: 1rem;
margin-right: 1rem;
height: 100%;
padding: 0px
}
[data-v-b0ca1b97] .favorite-page {
margin-left: 1rem;
margin-right: 1rem;
height: 300px;
padding: 0px
}
[data-v-b0ca1b97] .favorite-page .favorite-header {
margin-bottom: 0px !important;
padding-left: 0px !important;
padding-right: 0px !important
}
[data-v-b0ca1b97] .favorite-page .favorite-header h2 {
font-size: 1.125rem;
line-height: 1.75rem;
font-weight: 700;
--tw-text-opacity: 1;
color: rgb(17 24 39 / var(--tw-text-opacity, 1))
}
[data-v-b0ca1b97] .favorite-page .favorite-header h2:is(.dark *) {
--tw-text-opacity: 1;
color: rgb(255 255 255 / var(--tw-text-opacity, 1))
}
[data-v-b0ca1b97] .favorite-page .favorite-list {
padding-left: 0px !important;
padding-right: 0px !important
}

Some files were not shown because too many files have changed in this diff Show More