add:docs
@@ -1,8 +1,5 @@
|
||||
{
|
||||
"extends": [
|
||||
"@electron-toolkit/eslint-config-ts",
|
||||
"@electron-toolkit/eslint-config-prettier"
|
||||
],
|
||||
"extends": ["@electron-toolkit/eslint-config-ts", "@electron-toolkit/eslint-config-prettier"],
|
||||
"rules": {
|
||||
"vue/require-default-prop": "off",
|
||||
"vue/multi-word-component-names": "off",
|
||||
|
||||
@@ -19,7 +19,13 @@ export default defineConfig({
|
||||
{
|
||||
text: 'CeruMusic',
|
||||
items: [
|
||||
{ text: '使用教程', link: '/guide/' },
|
||||
{ text: '安装教程', link: '/guide/' },
|
||||
{
|
||||
text:'使用教程',
|
||||
items:[
|
||||
{ text: '音乐播放列表', link: '/guide/used/playList' },
|
||||
]
|
||||
},
|
||||
{ text: '软件设计文档', link: '/guide/design' }
|
||||
]
|
||||
},
|
||||
|
||||
@@ -1,142 +0,0 @@
|
||||
# Alist 下载配置说明
|
||||
|
||||
## 概述
|
||||
|
||||
项目已从 GitHub 下载方式切换到 Alist API 下载方式,包括:
|
||||
|
||||
- 桌面应用的自动更新功能 (`src/main/autoUpdate.ts`)
|
||||
- 官方网站的下载功能 (`website/script.js`)
|
||||
|
||||
## 配置步骤
|
||||
|
||||
### 1. 修改 Alist 域名
|
||||
|
||||
#### 桌面应用配置
|
||||
|
||||
在 `src/main/autoUpdate.ts` 文件中,Alist 域名已配置为:
|
||||
|
||||
```typescript
|
||||
const ALIST_BASE_URL = 'http://47.96.72.224:5244'
|
||||
```
|
||||
|
||||
#### 网站配置
|
||||
|
||||
在 `website/script.js` 文件中,Alist 域名已配置为:
|
||||
|
||||
```javascript
|
||||
const ALIST_BASE_URL = 'http://47.96.72.224:5244'
|
||||
```
|
||||
|
||||
如需修改域名,请同时更新这两个文件中的 `ALIST_BASE_URL` 配置。
|
||||
|
||||
### 2. 认证信息
|
||||
|
||||
已配置的认证信息:
|
||||
|
||||
- 用户名: `ceruupdata`
|
||||
- 密码: `123456`
|
||||
|
||||
### 3. 文件路径格式
|
||||
|
||||
文件在 Alist 中的路径格式为:`/{version}/{文件名}`
|
||||
|
||||
例如:
|
||||
|
||||
- 版本 `v1.0.0` 的安装包 `app-setup.exe` 路径为:`/v1.0.0/app-setup.exe`
|
||||
|
||||
## 工作原理
|
||||
|
||||
### 桌面应用自动更新
|
||||
|
||||
1. **认证**: 使用配置的用户名和密码向 Alist API 获取认证 token
|
||||
2. **获取文件信息**: 使用 token 调用 `/api/fs/get` 接口获取文件信息和签名
|
||||
3. **下载**: 使用带签名的直接下载链接下载文件
|
||||
4. **备用方案**: 如果 Alist 失败,自动回退到原始 URL 下载
|
||||
|
||||
### 网站下载功能
|
||||
|
||||
1. **获取版本列表**: 调用 `/api/fs/list` 获取根目录下的版本文件夹
|
||||
2. **获取文件列表**: 获取最新版本文件夹中的所有文件
|
||||
3. **平台匹配**: 根据用户平台自动匹配对应的安装包文件
|
||||
4. **生成下载链接**: 获取文件的直接下载链接
|
||||
5. **备用方案**: 如果 Alist 失败,自动回退到 GitHub API
|
||||
|
||||
## API 接口
|
||||
|
||||
### 认证接口
|
||||
|
||||
```
|
||||
POST /api/auth/login
|
||||
{
|
||||
"username": "ceruupdata",
|
||||
"password": "123456"
|
||||
}
|
||||
```
|
||||
|
||||
### 获取文件信息接口
|
||||
|
||||
```
|
||||
POST /api/fs/get
|
||||
Headers: Authorization: {token} # 注意:直接使用 token,不需要 "Bearer " 前缀
|
||||
{
|
||||
"path": "/{version}/{fileName}"
|
||||
}
|
||||
```
|
||||
|
||||
### 获取文件列表接口
|
||||
|
||||
```
|
||||
POST /api/fs/list
|
||||
Headers: Authorization: {token} # 注意:直接使用 token,不需要 "Bearer " 前缀
|
||||
{
|
||||
"path": "/",
|
||||
"password": "",
|
||||
"page": 1,
|
||||
"per_page": 100,
|
||||
"refresh": false
|
||||
}
|
||||
```
|
||||
|
||||
### 下载链接格式
|
||||
|
||||
```
|
||||
{ALIST_BASE_URL}/d/{filePath}?sign={sign}
|
||||
```
|
||||
|
||||
## 测试方法
|
||||
|
||||
项目包含了一个测试脚本来验证 Alist 连接:
|
||||
|
||||
```bash
|
||||
node scripts/test-alist.js
|
||||
```
|
||||
|
||||
该脚本会:
|
||||
|
||||
1. 测试服务器连通性
|
||||
2. 测试用户认证
|
||||
3. 测试文件列表获取
|
||||
4. 测试文件信息获取
|
||||
|
||||
## 备用机制
|
||||
|
||||
两个组件都实现了备用机制:
|
||||
|
||||
### 桌面应用
|
||||
|
||||
- 主要:使用 Alist API 下载
|
||||
- 备用:如果 Alist 失败,使用原始 URL 下载
|
||||
|
||||
### 网站
|
||||
|
||||
- 主要:使用 Alist API 获取版本和文件信息
|
||||
- 备用:如果 Alist 失败,回退到 GitHub API
|
||||
- 最终备用:跳转到 GitHub releases 页面
|
||||
|
||||
## 注意事项
|
||||
|
||||
1. 确保 Alist 服务器可以正常访问
|
||||
2. 确保配置的用户名和密码有权限访问相应的文件路径
|
||||
3. 文件必须按照指定的路径格式存放在 Alist 中
|
||||
4. 网站会自动检测用户操作系统并推荐对应的下载版本
|
||||
5. 所有下载都会显示文件大小信息
|
||||
@@ -1,99 +0,0 @@
|
||||
# Alist 迁移完成总结
|
||||
|
||||
## 修改概述
|
||||
|
||||
项目已成功从 GitHub 下载方式迁移到 Alist API 下载方式。
|
||||
|
||||
## 修改的文件
|
||||
|
||||
### 1. 桌面应用自动更新 (`src/main/autoUpdate.ts`)
|
||||
|
||||
- ✅ 添加了 Alist API 配置
|
||||
- ✅ 实现了 Alist 认证功能
|
||||
- ✅ 实现了 Alist 文件下载功能
|
||||
- ✅ 添加了备用机制(Alist 失败时回退到原始 URL)
|
||||
- ✅ 修复了 Authorization 头格式(使用直接 token 而非 Bearer 格式)
|
||||
|
||||
### 2. 官方网站下载功能 (`website/script.js`)
|
||||
|
||||
- ✅ 添加了 Alist API 配置
|
||||
- ✅ 实现了 Alist 认证功能
|
||||
- ✅ 实现了版本列表获取功能
|
||||
- ✅ 实现了文件列表获取功能
|
||||
- ✅ 实现了平台文件匹配功能
|
||||
- ✅ 添加了多层备用机制(Alist → GitHub API → GitHub 页面)
|
||||
- ✅ 修复了 Authorization 头格式
|
||||
|
||||
### 3. 配置文档
|
||||
|
||||
- ✅ 创建了详细的配置说明 (`docs/alist-config.md`)
|
||||
- ✅ 创建了迁移总结文档 (`docs/alist-migration-summary.md`)
|
||||
|
||||
### 4. 测试脚本
|
||||
|
||||
- ✅ 创建了 Alist 连接测试脚本 (`scripts/test-alist.js`)
|
||||
- ✅ 创建了认证格式测试脚本 (`scripts/auth-test.js`)
|
||||
|
||||
## 配置信息
|
||||
|
||||
### Alist 服务器配置
|
||||
|
||||
- **服务器地址**: `http://47.96.72.224:5244`
|
||||
- **用户名**: `ceruupdate`
|
||||
- **密码**: `123456`
|
||||
- **文件路径格式**: `/{version}/{文件名}`
|
||||
|
||||
### Authorization 头格式
|
||||
|
||||
经过测试确认,正确的格式是:
|
||||
|
||||
```
|
||||
Authorization: {token}
|
||||
```
|
||||
|
||||
**注意**: 不需要 "Bearer " 前缀
|
||||
|
||||
## 功能特性
|
||||
|
||||
### 桌面应用
|
||||
|
||||
1. **智能下载**: 优先使用 Alist API,失败时自动回退
|
||||
2. **进度显示**: 支持下载进度显示和节流
|
||||
3. **错误处理**: 完善的错误处理和日志记录
|
||||
|
||||
### 网站
|
||||
|
||||
1. **自动检测**: 自动检测用户操作系统并推荐对应版本
|
||||
2. **版本信息**: 自动获取最新版本信息和文件大小
|
||||
3. **多层备用**: Alist → GitHub API → GitHub 页面的三层备用机制
|
||||
4. **用户体验**: 加载状态、成功通知、错误提示
|
||||
|
||||
## 测试结果
|
||||
|
||||
✅ **Alist 连接测试**: 通过
|
||||
✅ **认证测试**: 通过
|
||||
✅ **文件列表获取**: 通过
|
||||
✅ **Authorization 头格式**: 已修复并验证
|
||||
|
||||
## 可用文件
|
||||
|
||||
测试显示 Alist 服务器当前包含以下文件:
|
||||
|
||||
- `v1.2.1/` (版本目录)
|
||||
- `1111`
|
||||
- `L3YxLjIuMS8tMS4yLjEtYXJtNjQtbWFjLnppcA==`
|
||||
- `file2.msi`
|
||||
- `file.msi`
|
||||
|
||||
## 后续维护
|
||||
|
||||
1. **添加新版本**: 在 Alist 中创建新的版本目录(如 `v1.2.2/`)
|
||||
2. **上传文件**: 将对应平台的安装包上传到版本目录中
|
||||
3. **文件命名**: 确保文件名包含平台标识(如 `windows`, `mac`, `linux` 等)
|
||||
|
||||
## 备注
|
||||
|
||||
- 所有修改都保持了向后兼容性
|
||||
- 实现了完善的错误处理和备用机制
|
||||
- 用户体验不会因为迁移而受到影响
|
||||
- 可以随时回退到 GitHub 下载方式
|
||||
BIN
docs/guide/used/assets/image-20250916132204465.png
Normal file
|
After Width: | Height: | Size: 9.5 KiB |
BIN
docs/guide/used/assets/image-20250916132248046.png
Normal file
|
After Width: | Height: | Size: 9.5 KiB |
BIN
docs/guide/used/assets/image-20250916133531421.png
Normal file
|
After Width: | Height: | Size: 88 KiB |
BIN
docs/guide/used/assets/image-20250916134406714.png
Normal file
|
After Width: | Height: | Size: 249 KiB |
BIN
docs/guide/used/assets/image-20250916134511291.png
Normal file
|
After Width: | Height: | Size: 255 KiB |
BIN
docs/guide/used/assets/image-20250916134615679.png
Normal file
|
After Width: | Height: | Size: 41 KiB |
BIN
docs/guide/used/assets/image-20250916134820742.png
Normal file
|
After Width: | Height: | Size: 449 KiB |
25
docs/guide/used/playList.md
Normal file
@@ -0,0 +1,25 @@
|
||||
# 音乐播放列表-机制分析
|
||||
|
||||
## 基础使用
|
||||
|
||||
1. 默认情况下,播放**「搜索」「歌单」**双击中的歌曲时,会自动将该歌曲添加到**「列表」**中的末尾后并不会播放,这与手动将歌曲添加到**「列表」**等价,亦或是通过点击歌曲前面小三角播放<img src="./assets/image-20250916132248046.png" alt="image-20250916132248046" style="float:right" />可以添加到歌曲开头也可进行该歌曲添加到**「列表」**中的开头并播放。歌曲会按照你选择的播放顺序进行播放。
|
||||
2. 对于**「列表」**歌曲的顺序可通过展开长按**1.5s**后可以进行拖拽排序,歌曲排序实时保存到本地**LocalStorage**<img src="./assets/image-20250916133531421.png" alt="image-20250916133531421" style="zoom: 20%;" />
|
||||
|
||||
## 歌曲列表的导出和分享
|
||||
|
||||
3. 可进入设置
|
||||
|
||||

|
||||
|
||||
点击**【播放列表】**=>
|
||||
|
||||

|
||||
|
||||
即可操作你想要的功能
|
||||
|
||||
4. 播放列表还可以导出为歌单
|
||||
|
||||

|
||||
|
||||
歌单将自动选取第一首 **\*有效封面** 为歌单
|
||||
|
||||
@@ -1,150 +0,0 @@
|
||||
# WebDAV 同步配置指南
|
||||
|
||||
本项目包含两个 GitHub Actions 工作流,用于自动将 GitHub Releases 同步到 alist(WebDAV 服务器)。
|
||||
|
||||
## 工作流说明
|
||||
|
||||
### 1. 手动同步工作流 (`sync-releases-to-webdav.yml`)
|
||||
|
||||
- **触发方式**: 手动触发 (workflow_dispatch)
|
||||
- **功能**: 同步现有的所有版本或指定版本到 WebDAV
|
||||
- **参数**:
|
||||
- `tag_name`: 可选,指定要同步的版本标签(如 v1.0.0),留空则同步所有版本
|
||||
|
||||
### 2. 自动同步工作流 (集成在 `main.yml` 中)
|
||||
|
||||
- **触发方式**: 在 AutoBuild 完成后自动触发
|
||||
- **功能**: 自动将新构建的版本同步到 WebDAV
|
||||
- **参数**: 无需手动设置,自动获取发布信息
|
||||
|
||||
### 3. 独立自动同步工作流 (`auto-sync-release.yml`)
|
||||
|
||||
- **触发方式**: 当新版本发布时自动触发 (on release published)
|
||||
- **功能**: 备用的自动同步机制
|
||||
- **参数**: 无需手动设置,自动获取发布信息
|
||||
|
||||
## 配置要求
|
||||
|
||||
在 GitHub 仓库的 Settings > Secrets and variables > Actions 中添加以下密钥:
|
||||
|
||||
### 必需的 Secrets
|
||||
|
||||
1. **WEBDAV_BASE_URL**
|
||||
- 描述: WebDAV 服务器的基础 URL
|
||||
- 示例: `https://your-alist-domain.com/dav`
|
||||
- 注意: 不要在末尾添加斜杠
|
||||
|
||||
2. **WEBDAV_USERNAME**
|
||||
- 描述: WebDAV 服务器的用户名
|
||||
- 示例: `admin`
|
||||
|
||||
3. **WEBDAV_PASSWORD**
|
||||
- 描述: WebDAV 服务器的密码
|
||||
- 示例: `your-password`
|
||||
|
||||
4. **GITHUB_TOKEN**
|
||||
- 描述: GitHub 访问令牌(通常自动提供)
|
||||
- 注意: 如果默认的 `GITHUB_TOKEN` 权限不足,可能需要创建个人访问令牌
|
||||
|
||||
## 使用方法
|
||||
|
||||
### 手动同步现有版本
|
||||
|
||||
1. 进入 GitHub 仓库的 Actions 页面
|
||||
2. 选择 "Sync Existing Releases to WebDAV" 工作流
|
||||
3. 点击 "Run workflow"
|
||||
4. 可选择指定版本标签或留空同步所有版本
|
||||
5. 点击 "Run workflow" 开始执行
|
||||
|
||||
### 自动同步新版本
|
||||
|
||||
现在有两种自动同步方式:
|
||||
|
||||
1. **集成同步** (推荐): 在主构建工作流 (`main.yml`) 中集成了 WebDAV 同步,当您推送 `v*` 标签时,会自动执行:
|
||||
- 构建应用 → 创建 Release → 同步到 WebDAV
|
||||
2. **独立同步**: 当您手动发布 Release 时,`auto-sync-release.yml` 工作流会自动触发
|
||||
|
||||
推荐使用集成同步方式,因为它确保了构建和同步的一致性。
|
||||
|
||||
## 文件结构
|
||||
|
||||
同步后的文件将按以下结构存储在 alist 中:
|
||||
|
||||
```
|
||||
/yd/ceru/
|
||||
├── v1.0.0/
|
||||
│ ├── app-setup.exe
|
||||
│ ├── app.dmg
|
||||
│ └── app.AppImage
|
||||
├── v1.1.0/
|
||||
│ ├── app-setup.exe
|
||||
│ ├── app.dmg
|
||||
│ └── app.AppImage
|
||||
└── ...
|
||||
```
|
||||
|
||||
## 故障排除
|
||||
|
||||
### 常见问题
|
||||
|
||||
1. **上传失败**
|
||||
- 检查 WebDAV 服务器是否正常运行
|
||||
- 验证用户名和密码是否正确
|
||||
- 确认 WebDAV URL 格式正确
|
||||
|
||||
2. **权限错误**
|
||||
- 确保 WebDAV 用户有写入权限
|
||||
- 检查目标目录是否存在且可写
|
||||
|
||||
3. **文件大小不匹配**
|
||||
- 网络问题导致下载不完整
|
||||
- GitHub API 限制或临时故障
|
||||
|
||||
4. **目录创建失败**
|
||||
- WebDAV 服务器不支持 MKCOL 方法
|
||||
- 权限不足或路径错误
|
||||
|
||||
### 调试步骤
|
||||
|
||||
1. 查看 Actions 运行日志
|
||||
2. 检查 WebDAV 服务器日志
|
||||
3. 验证所有 Secrets 配置正确
|
||||
4. 测试 WebDAV 连接是否正常
|
||||
|
||||
## 安全注意事项
|
||||
|
||||
1. **密钥管理**
|
||||
- 不要在代码中硬编码密码
|
||||
- 定期更换 WebDAV 密码
|
||||
- 使用强密码
|
||||
|
||||
2. **权限控制**
|
||||
- 为 WebDAV 用户设置最小必要权限
|
||||
- 考虑使用专用的同步账户
|
||||
|
||||
3. **网络安全**
|
||||
- 建议使用 HTTPS 连接
|
||||
- 考虑 IP 白名单限制
|
||||
|
||||
## 自定义配置
|
||||
|
||||
如需修改同步路径或其他配置,请编辑对应的工作流文件:
|
||||
|
||||
- 修改存储路径: 更改 `remote_path` 变量
|
||||
- 调整重试逻辑: 修改错误处理部分
|
||||
- 添加通知: 集成 Slack、邮件等通知服务
|
||||
|
||||
## 支持的文件类型
|
||||
|
||||
工作流支持同步所有类型的 Release 资源文件,包括但不限于:
|
||||
|
||||
- 可执行文件 (.exe, .dmg, .AppImage)
|
||||
- 压缩包 (.zip, .tar.gz, .7z)
|
||||
- 安装包 (.msi, .deb, .rpm)
|
||||
- 其他二进制文件
|
||||
|
||||
## 版本兼容性
|
||||
|
||||
- GitHub Actions: 支持最新版本
|
||||
- alist: 支持 WebDAV 协议的版本
|
||||
- 操作系统: Ubuntu Latest (工作流运行环境)
|
||||
@@ -7,7 +7,6 @@ import musicService from './services/music'
|
||||
import pluginService from './services/plugin'
|
||||
import aiEvents from './events/ai'
|
||||
import './services/musicSdk/index'
|
||||
|
||||
// 获取单实例锁
|
||||
const gotTheLock = app.requestSingleInstanceLock()
|
||||
|
||||
|
||||
@@ -61,8 +61,7 @@ export default function useWindow(
|
||||
|
||||
app.whenReady().then(() => {
|
||||
// Set app user model id for windows
|
||||
electronApp.setAppUserModelId('com.cerulean.music')
|
||||
|
||||
// electronApp.setAppUserModelId('com.cerulean.music')
|
||||
// Default open or close DevTools by F12 in development
|
||||
// and ignore CommandOrControl + R in production.
|
||||
// see https://github.com/alex8088/electron-toolkit/tree/master/packages/utils
|
||||
|
||||
4
src/renderer/auto-imports.d.ts
vendored
@@ -5,6 +5,4 @@
|
||||
// Generated by unplugin-auto-import
|
||||
// biome-ignore lint: disable
|
||||
export {}
|
||||
declare global {
|
||||
|
||||
}
|
||||
declare global {}
|
||||
|
||||
52
src/renderer/components.d.ts
vendored
@@ -0,0 +1,52 @@
|
||||
/* eslint-disable */
|
||||
// @ts-nocheck
|
||||
// Generated by unplugin-vue-components
|
||||
// Read more: https://github.com/vuejs/core/pull/3399
|
||||
// biome-ignore lint: disable
|
||||
export {}
|
||||
|
||||
/* prettier-ignore */
|
||||
declare module 'vue' {
|
||||
export interface GlobalComponents {
|
||||
AIFloatBallSettings: typeof import('./src/components/Settings/AIFloatBallSettings.vue')['default']
|
||||
AudioVisualizer: typeof import('./src/components/Play/AudioVisualizer.vue')['default']
|
||||
FloatBall: typeof import('./src/components/AI/FloatBall.vue')['default']
|
||||
FullPlay: typeof import('./src/components/Play/FullPlay.vue')['default']
|
||||
GlobalAudio: typeof import('./src/components/Play/GlobalAudio.vue')['default']
|
||||
MusicCache: typeof import('./src/components/Settings/MusicCache.vue')['default']
|
||||
PlaylistActions: typeof import('./src/components/Play/PlaylistActions.vue')['default']
|
||||
PlaylistDrawer: typeof import('./src/components/Play/PlaylistDrawer.vue')['default']
|
||||
PlaylistSettings: typeof import('./src/components/Settings/PlaylistSettings.vue')['default']
|
||||
PlayMusic: typeof import('./src/components/Play/PlayMusic.vue')['default']
|
||||
RouterLink: typeof import('vue-router')['RouterLink']
|
||||
RouterView: typeof import('vue-router')['RouterView']
|
||||
SearchComponent: typeof import('./src/components/Search/SearchComponent.vue')['default']
|
||||
ShaderBackground: typeof import('./src/components/Play/ShaderBackground.vue')['default']
|
||||
SongVirtualList: typeof import('./src/components/Music/SongVirtualList.vue')['default']
|
||||
TAlert: typeof import('tdesign-vue-next')['Alert']
|
||||
TAside: typeof import('tdesign-vue-next')['Aside']
|
||||
TBadge: typeof import('tdesign-vue-next')['Badge']
|
||||
TButton: typeof import('tdesign-vue-next')['Button']
|
||||
TCard: typeof import('tdesign-vue-next')['Card']
|
||||
TContent: typeof import('tdesign-vue-next')['Content']
|
||||
TDialog: typeof import('tdesign-vue-next')['Dialog']
|
||||
TDropdown: typeof import('tdesign-vue-next')['Dropdown']
|
||||
TForm: typeof import('tdesign-vue-next')['Form']
|
||||
TFormItem: typeof import('tdesign-vue-next')['FormItem']
|
||||
ThemeSelector: typeof import('./src/components/ThemeSelector.vue')['default']
|
||||
TIcon: typeof import('tdesign-vue-next')['Icon']
|
||||
TImage: typeof import('tdesign-vue-next')['Image']
|
||||
TInput: typeof import('tdesign-vue-next')['Input']
|
||||
TitleBarControls: typeof import('./src/components/TitleBarControls.vue')['default']
|
||||
TLayout: typeof import('tdesign-vue-next')['Layout']
|
||||
TLoading: typeof import('tdesign-vue-next')['Loading']
|
||||
TSlider: typeof import('tdesign-vue-next')['Slider']
|
||||
TSwitch: typeof import('tdesign-vue-next')['Switch']
|
||||
TTextarea: typeof import('tdesign-vue-next')['Textarea']
|
||||
TTooltip: typeof import('tdesign-vue-next')['Tooltip']
|
||||
UpdateExample: typeof import('./src/components/UpdateExample.vue')['default']
|
||||
UpdateProgress: typeof import('./src/components/UpdateProgress.vue')['default']
|
||||
UpdateSettings: typeof import('./src/components/Settings/UpdateSettings.vue')['default']
|
||||
Versions: typeof import('./src/components/Versions.vue')['default']
|
||||
}
|
||||
}
|
||||
|
||||
@@ -215,10 +215,7 @@ const playSong = async (song: SongList) => {
|
||||
|
||||
// 开始播放
|
||||
try {
|
||||
const startResult = start()
|
||||
if (startResult && typeof startResult.then === 'function') {
|
||||
await startResult
|
||||
}
|
||||
start()
|
||||
} catch (error) {
|
||||
console.error('启动播放失败:', error)
|
||||
// 如果是 AbortError,尝试重新播放
|
||||
@@ -835,13 +832,11 @@ watch(showFullPlay, (val) => {
|
||||
:disabled="isLoadingSong"
|
||||
@click.stop="() => !isLoadingSong && togglePlayPause()"
|
||||
>
|
||||
<Transition name="loadSong" mode="out-in">
|
||||
<transition name="fade" mode="out-in">
|
||||
<div v-if="isLoadingSong" key="loading" class="loading-spinner play-loading"></div>
|
||||
<transition v-else name="fade" mode="out-in">
|
||||
<span v-if="Audio.isPlay" key="play" class="iconfont icon-zanting"></span>
|
||||
<span v-else key="pause" class="iconfont icon-bofang"></span>
|
||||
</transition>
|
||||
</Transition>
|
||||
<span v-else-if="Audio.isPlay" key="play" class="iconfont icon-zanting"></span>
|
||||
<span v-else key="pause" class="iconfont icon-bofang"></span>
|
||||
</transition>
|
||||
</button>
|
||||
<t-button class="control-btn" shape="circle" variant="text" @click.stop="playNext">
|
||||
<span class="iconfont icon-xiayishou"></span>
|
||||
|
||||