Full Code of algerkong/AlgerMusicPlayer for AI

main cd1c09889f4c cached
322 files
1.6 MB
509.8k tokens
519 symbols
1 requests
Download .txt
Showing preview only (1,786K chars total). Download the full file or copy to clipboard to get everything.
Repository: algerkong/AlgerMusicPlayer
Branch: main
Commit: cd1c09889f4c
Files: 322
Total size: 1.6 MB

Directory structure:
gitextract_wrew8kq0/

├── .github/
│   ├── CODEOWNERS
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug-report.zh-CN.yml
│   │   ├── config.yml
│   │   └── feature-report.zh-CN.yml
│   ├── PULL_REQUEST_TEMPLATE.md
│   ├── dependabot.yml
│   ├── issue-shoot.md
│   └── workflows/
│       ├── build.yml
│       └── deploy.yml
├── .gitignore
├── .husky/
│   ├── pre-commit
│   └── pre-push
├── .prettierignore
├── CHANGELOG.md
├── DEV.md
├── LICENSE
├── README.md
├── android/
│   └── .gitignore
├── build/
│   ├── entitlements.mac.plist
│   ├── icon.icns
│   └── installer.nsh
├── dev-app-update.yml
├── docs/
│   └── custom-api-readme.md
├── electron.vite.config.ts
├── eslint.config.mjs
├── package.json
├── postcss.config.js
├── prettier.config.js
├── resources/
│   ├── html/
│   │   └── remote-control.html
│   ├── icon.icns
│   └── manifest.json
├── src/
│   ├── i18n/
│   │   ├── lang/
│   │   │   ├── en-US/
│   │   │   │   ├── artist.ts
│   │   │   │   ├── bilibili.ts
│   │   │   │   ├── common.ts
│   │   │   │   ├── comp.ts
│   │   │   │   ├── donation.ts
│   │   │   │   ├── download.ts
│   │   │   │   ├── favorite.ts
│   │   │   │   ├── history.ts
│   │   │   │   ├── login.ts
│   │   │   │   ├── player.ts
│   │   │   │   ├── search.ts
│   │   │   │   ├── settings.ts
│   │   │   │   ├── songItem.ts
│   │   │   │   └── user.ts
│   │   │   ├── ja-JP/
│   │   │   │   ├── artist.ts
│   │   │   │   ├── bilibili.ts
│   │   │   │   ├── common.ts
│   │   │   │   ├── comp.ts
│   │   │   │   ├── donation.ts
│   │   │   │   ├── download.ts
│   │   │   │   ├── favorite.ts
│   │   │   │   ├── history.ts
│   │   │   │   ├── login.ts
│   │   │   │   ├── player.ts
│   │   │   │   ├── search.ts
│   │   │   │   ├── settings.ts
│   │   │   │   ├── songItem.ts
│   │   │   │   └── user.ts
│   │   │   ├── ko-KR/
│   │   │   │   ├── artist.ts
│   │   │   │   ├── bilibili.ts
│   │   │   │   ├── common.ts
│   │   │   │   ├── comp.ts
│   │   │   │   ├── donation.ts
│   │   │   │   ├── download.ts
│   │   │   │   ├── favorite.ts
│   │   │   │   ├── history.ts
│   │   │   │   ├── login.ts
│   │   │   │   ├── player.ts
│   │   │   │   ├── search.ts
│   │   │   │   ├── settings.ts
│   │   │   │   ├── songItem.ts
│   │   │   │   └── user.ts
│   │   │   ├── zh-CN/
│   │   │   │   ├── artist.ts
│   │   │   │   ├── bilibili.ts
│   │   │   │   ├── common.ts
│   │   │   │   ├── comp.ts
│   │   │   │   ├── donation.ts
│   │   │   │   ├── download.ts
│   │   │   │   ├── favorite.ts
│   │   │   │   ├── history.ts
│   │   │   │   ├── login.ts
│   │   │   │   ├── player.ts
│   │   │   │   ├── search.ts
│   │   │   │   ├── settings.ts
│   │   │   │   ├── songItem.ts
│   │   │   │   └── user.ts
│   │   │   └── zh-Hant/
│   │   │       ├── artist.ts
│   │   │       ├── bilibili.ts
│   │   │       ├── common.ts
│   │   │       ├── comp.ts
│   │   │       ├── donation.ts
│   │   │       ├── download.ts
│   │   │       ├── favorite.ts
│   │   │       ├── history.ts
│   │   │       ├── login.ts
│   │   │       ├── player.ts
│   │   │       ├── search.ts
│   │   │       ├── settings.ts
│   │   │       ├── songItem.ts
│   │   │       └── user.ts
│   │   ├── languages.ts
│   │   ├── main.ts
│   │   ├── renderer.ts
│   │   └── utils.ts
│   ├── main/
│   │   ├── index.ts
│   │   ├── lyric.ts
│   │   ├── modules/
│   │   │   ├── cache.ts
│   │   │   ├── config.ts
│   │   │   ├── deviceInfo.ts
│   │   │   ├── fileManager.ts
│   │   │   ├── fonts.ts
│   │   │   ├── loginWindow.ts
│   │   │   ├── lxMusicHttp.ts
│   │   │   ├── otherApi.ts
│   │   │   ├── remoteControl.ts
│   │   │   ├── shortcuts.ts
│   │   │   ├── tray.ts
│   │   │   ├── update.ts
│   │   │   ├── window-size.ts
│   │   │   └── window.ts
│   │   ├── server.ts
│   │   ├── set.json
│   │   └── unblockMusic.ts
│   ├── preload/
│   │   ├── index.d.ts
│   │   └── index.ts
│   └── renderer/
│       ├── App.vue
│       ├── api/
│       │   ├── artist.ts
│       │   ├── bilibili.ts
│       │   ├── donation.ts
│       │   ├── gdmusic.ts
│       │   ├── home.ts
│       │   ├── list.ts
│       │   ├── login.ts
│       │   ├── lxMusicStrategy.ts
│       │   ├── music.ts
│       │   ├── musicParser.ts
│       │   ├── mv.ts
│       │   ├── parseFromCustomApi.ts
│       │   ├── playlist.ts
│       │   ├── search.ts
│       │   └── user.ts
│       ├── assets/
│       │   ├── css/
│       │   │   └── base.css
│       │   └── icon/
│       │       ├── iconfont.css
│       │       ├── iconfont.js
│       │       └── iconfont.json
│       ├── components/
│       │   ├── Coffee.vue
│       │   ├── EQControl.vue
│       │   ├── LanguageSwitcher.vue
│       │   ├── MusicList.vue
│       │   ├── MvPlayer.vue
│       │   ├── ShortcutToast.vue
│       │   ├── TrafficWarningDrawer.vue
│       │   ├── common/
│       │   │   ├── AlbumItem.vue
│       │   │   ├── ArtistDrawer.vue
│       │   │   ├── BilibiliItem.vue
│       │   │   ├── DisclaimerModal.vue
│       │   │   ├── DonationList.vue
│       │   │   ├── DownloadDrawer.vue
│       │   │   ├── InstallAppModal.vue
│       │   │   ├── MobileUpdateModal.vue
│       │   │   ├── MusicListNavigator.ts
│       │   │   ├── PlayBottom.vue
│       │   │   ├── PlayListsItem.vue
│       │   │   ├── PlaylistDrawer.vue
│       │   │   ├── PlaylistItem.vue
│       │   │   ├── ResponsiveModal.vue
│       │   │   ├── SearchItem.vue
│       │   │   ├── SongItem.vue
│       │   │   ├── UpdateModal.vue
│       │   │   └── songItemCom/
│       │   │       ├── BaseSongItem.vue
│       │   │       ├── CompactSongItem.vue
│       │   │       ├── ListSongItem.vue
│       │   │       ├── MiniSongItem.vue
│       │   │       ├── SongItemDropdown.vue
│       │   │       └── StandardSongItem.vue
│       │   ├── cover/
│       │   │   └── Cover3D.vue
│       │   ├── home/
│       │   │   ├── PlaylistType.vue
│       │   │   ├── RecommendAlbum.vue
│       │   │   ├── RecommendSonglist.vue
│       │   │   └── TopBanner.vue
│       │   ├── login/
│       │   │   ├── CookieLogin.vue
│       │   │   ├── QrLogin.vue
│       │   │   └── UidLogin.vue
│       │   ├── lyric/
│       │   │   ├── LyricCorrectionControl.vue
│       │   │   ├── LyricSettings.vue
│       │   │   ├── MusicFull.vue
│       │   │   ├── MusicFullMobile.vue
│       │   │   ├── MusicFullWrapper.vue
│       │   │   └── ThemeColorPanel.vue
│       │   ├── player/
│       │   │   ├── AdvancedControlsPopover.vue
│       │   │   ├── MiniPlayBar.vue
│       │   │   ├── MobilePlayBar.vue
│       │   │   ├── MobilePlayerSettings.vue
│       │   │   ├── PlayBar.vue
│       │   │   ├── PlayingListDrawer.vue
│       │   │   ├── ReparsePopover.vue
│       │   │   ├── SimplePlayBar.vue
│       │   │   ├── SleepTimer.vue
│       │   │   └── SleepTimerTop.vue
│       │   └── settings/
│       │       ├── ClearCacheSettings.vue
│       │       ├── CookieSettingsModal.vue
│       │       ├── MusicSourceSettings.vue
│       │       ├── ProxySettings.vue
│       │       ├── ServerSetting.vue
│       │       └── ShortcutSettings.vue
│       ├── const/
│       │   └── bar-const.ts
│       ├── directive/
│       │   ├── index.ts
│       │   └── loading/
│       │       ├── index.ts
│       │       └── index.vue
│       ├── hooks/
│       │   ├── AlbumHistoryHook.ts
│       │   ├── IndexDBHook.ts
│       │   ├── MusicHistoryHook.ts
│       │   ├── MusicHook.ts
│       │   ├── PlaylistHistoryHook.ts
│       │   ├── useArtist.ts
│       │   ├── useDownload.ts
│       │   ├── usePlayMode.ts
│       │   ├── usePlayerHooks.ts
│       │   ├── useSongItem.ts
│       │   └── useZoom.ts
│       ├── index.css
│       ├── index.html
│       ├── layout/
│       │   ├── AppLayout.vue
│       │   ├── MiniLayout.vue
│       │   ├── MobileLayout.vue
│       │   └── components/
│       │       ├── AppMenu.vue
│       │       ├── MobileHeader.vue
│       │       ├── SearchBar.vue
│       │       ├── TitleBar.vue
│       │       └── index.ts
│       ├── main.ts
│       ├── router/
│       │   ├── home.ts
│       │   ├── index.ts
│       │   └── other.ts
│       ├── services/
│       │   ├── LxMusicSourceRunner.ts
│       │   ├── SongSourceConfigManager.ts
│       │   ├── audioService.ts
│       │   ├── eqService.ts
│       │   ├── lyricTranslation.ts
│       │   ├── playbackRequestManager.ts
│       │   ├── preloadService.ts
│       │   └── translation-engines/
│       │       ├── index.ts
│       │       └── opencc.ts
│       ├── shims-vue.d.ts
│       ├── store/
│       │   ├── index.ts
│       │   └── modules/
│       │       ├── favorite.ts
│       │       ├── intelligenceMode.ts
│       │       ├── lyric.ts
│       │       ├── menu.ts
│       │       ├── music.ts
│       │       ├── player.ts
│       │       ├── playerCore.ts
│       │       ├── playlist.ts
│       │       ├── recommend.ts
│       │       ├── search.ts
│       │       ├── settings.ts
│       │       ├── sleepTimer.ts
│       │       └── user.ts
│       ├── types/
│       │   ├── album.ts
│       │   ├── artist.ts
│       │   ├── bilibili.ts
│       │   ├── day_recommend.ts
│       │   ├── electron.d.ts
│       │   ├── index.ts
│       │   ├── list.ts
│       │   ├── listDetail.ts
│       │   ├── lxMusic.ts
│       │   ├── lyric.ts
│       │   ├── music.ts
│       │   ├── mv.ts
│       │   ├── opencc-rust.d.ts
│       │   ├── playlist.ts
│       │   ├── search.ts
│       │   ├── singer.ts
│       │   └── user.ts
│       ├── utils/
│       │   ├── appShortcuts.ts
│       │   ├── auth.ts
│       │   ├── fileOperation.ts
│       │   ├── index.ts
│       │   ├── linearColor.ts
│       │   ├── lxCrypto.ts
│       │   ├── playerUtils.ts
│       │   ├── request.ts
│       │   ├── request_music.ts
│       │   ├── shortcutToast.ts
│       │   ├── theme.ts
│       │   ├── update.ts
│       │   └── yrcParser.ts
│       ├── views/
│       │   ├── artist/
│       │   │   └── detail.vue
│       │   ├── bilibili/
│       │   │   └── BilibiliPlayer.vue
│       │   ├── download/
│       │   │   └── DownloadPage.vue
│       │   ├── favorite/
│       │   │   └── index.vue
│       │   ├── heatmap/
│       │   │   └── index.vue
│       │   ├── history/
│       │   │   └── index.vue
│       │   ├── historyAndFavorite/
│       │   │   └── index.vue
│       │   ├── home/
│       │   │   └── index.vue
│       │   ├── list/
│       │   │   └── index.vue
│       │   ├── login/
│       │   │   └── index.vue
│       │   ├── lyric/
│       │   │   └── index.vue
│       │   ├── mobile-search/
│       │   │   └── index.vue
│       │   ├── mobile-search-result/
│       │   │   └── index.vue
│       │   ├── music/
│       │   │   ├── HistoryRecommend.vue
│       │   │   └── MusicListPage.vue
│       │   ├── mv/
│       │   │   └── index.vue
│       │   ├── playlist/
│       │   │   └── ImportPlaylist.vue
│       │   ├── search/
│       │   │   └── index.vue
│       │   ├── set/
│       │   │   ├── SettingItem.vue
│       │   │   ├── SettingNav.vue
│       │   │   ├── SettingSection.vue
│       │   │   └── index.vue
│       │   ├── toplist/
│       │   │   └── index.vue
│       │   └── user/
│       │       ├── detail.vue
│       │       ├── followers.vue
│       │       ├── follows.vue
│       │       └── index.vue
│       └── vite-env.d.ts
├── tailwind.config.js
├── tsconfig.json
├── tsconfig.node.json
├── tsconfig.web.json
└── vite.config.ts

================================================
FILE CONTENTS
================================================

================================================
FILE: .github/CODEOWNERS
================================================
* @algerkong


================================================
FILE: .github/ISSUE_TEMPLATE/bug-report.zh-CN.yml
================================================
name: 反馈 Bug
description: 通过 github 模板进行 Bug 反馈。
title: '描述问题的标题'
body:
  - type: markdown
    attributes:
      value: |
        # 欢迎你的参与
        Issue 列表接受 bug 报告或是新功能请求。

        在发布一个 Issue 前,请确保:
        - 在Issue中搜索过你的问题。(你的问题可能已有人提出,也可能已在最新版本中被修正)
        - 如果你发现一个已经关闭的旧 Issue 在最新版本中仍然存在,不要在旧 Issue 下面留言,请建一个新的 issue。

  - type: input
    id: reproduce
    attributes:
      label: 重现链接
      description: 请提供尽可能精简的 CodePen、CodeSandbox 或 GitHub 仓库的链接。请不要填无关链接,否则你的 Issue 将被关闭。
      placeholder: 请填写

  - type: textarea
    id: reproduceSteps
    attributes:
      label: 重现步骤
      description: 请清晰的描述重现该 Issue 的步骤,这能帮助我们快速定位问题。没有清晰重现步骤将不会被修复,标有 'need reproduction' 的 Issue 在 7 天内不提供相关步骤,将被关闭。
      placeholder: 请填写

  - type: textarea
    id: expect
    attributes:
      label: 期望结果
      placeholder: 请填写

  - type: textarea
    id: actual
    attributes:
      label: 实际结果
      placeholder: 请填写

  - type: input
    id: frameworkVersion
    attributes:
      label: 框架版本
      placeholder: Vue(3.3.0)

  - type: input
    id: browsersVersion
    attributes:
      label: 浏览器版本
      placeholder: Chrome(8.213.231.123)

  - type: input
    id: systemVersion
    attributes:
      label: 系统版本
      placeholder: MacOS(11.2.3)

  - type: input
    id: nodeVersion
    attributes:
      label: Node版本
      placeholder: 请填写

  - type: textarea
    id: remarks
    attributes:
      label: 补充说明
      description: 可以是遇到这个 bug 的业务场景、上下文等信息。
      placeholder: 请填写


================================================
FILE: .github/ISSUE_TEMPLATE/config.yml
================================================
blank_issues_enabled: true
contact_links:
  - name:
    url:
    about:


================================================
FILE: .github/ISSUE_TEMPLATE/feature-report.zh-CN.yml
================================================
name: 反馈新功能
description: 通过 github 模板进行新功能反馈。
title: '描述问题的标题'
body:
  - type: markdown
    attributes:
      value: |
        # 欢迎你的参与

        在发布一个 Issue 前,请确保:
        - 在 Issue 中搜索过你的问题。(你的问题可能已有人提出,也可能已在最新版本中被修正)
        - 如果你发现一个已经关闭的旧 Issue 在最新版本中仍然存在,不要在旧 Issue 下面留言,请建一个新的 issue。

  - type: textarea
    id: functionContent
    attributes:
      label: 这个功能解决了什么问题
      description: 请详尽说明这个需求的用例和场景。最重要的是:解释清楚是怎样的用户体验需求催生了这个功能上的需求。我们将考虑添加在现有 API 无法轻松实现的功能。新功能的用例也应当足够常见。
      placeholder: 请填写
    validations:
      required: true

  - type: textarea
    id: functionalExpectations
    attributes:
      label: 你建议的方案是什么
      placeholder: 请填写
    validations:
      required: true


================================================
FILE: .github/PULL_REQUEST_TEMPLATE.md
================================================
<!--
首先,感谢你的贡献!😄
PR 在维护者审核通过后会合并,谢谢!
-->

### 🤔 这个 PR 的性质是?

- [ ] 日常 bug 修复
- [ ] 新特性提交
- [ ] 文档改进
- [ ] 演示代码改进
- [ ] 组件样式/交互改进
- [ ] CI/CD 改进
- [ ] 重构
- [ ] 代码风格优化
- [ ] 测试用例
- [ ] 分支合并
- [ ] 其他

### 🔗 相关 Issue

<!--
1. 描述相关需求的来源,如相关的 issue 讨论链接。
-->

### 💡 需求背景和解决方案

<!--
1. 要解决的具体问题。
2. 列出最终的 API 实现和用法。
3. 涉及UI/交互变动需要有截图或 GIF。
-->

### 📝 更新日志

<!--
从用户角度描述具体变化,以及可能的 breaking change 和其他风险。
-->

- fix(组件名称): 处理问题或特性描述 ...

- [ ] 本条 PR 不需要纳入 Changelog

### ☑️ 请求合并前的自查清单

⚠️ 请自检并全部**勾选全部选项**。⚠️

- [ ] 文档已补充或无须补充
- [ ] 代码演示已提供或无须提供
- [ ] TypeScript 定义已补充或无须补充
- [ ] Changelog 已提供或无须提供


================================================
FILE: .github/dependabot.yml
================================================
# Basic dependabot.yml file with
# minimum configuration for two package managers

version: 2
updates:
  # Enable version updates for npm
  - package-ecosystem: 'npm'
    # Look for `package.json` and `lock` files in the `root` directory
    directory: '/'
    # Check the npm registry for updates every day (weekdays)
    schedule:
      interval: 'monthly'

  # Enable version updates for Docker
  - package-ecosystem: 'docker'
    # Look for a `Dockerfile` in the `root` directory
    directory: '/'
    # Check for updates once a week
    schedule:
      interval: 'monthly'


================================================
FILE: .github/issue-shoot.md
================================================
## IssueShoot

- 预估时长: {{ .duration }}
- 期望完成时间: {{ .deadline }}
- 开发难度: {{ .level }}
- 参与人数: 1
- 需求对接人: ivringpeng
- 验收标准: 实现期望改造效果,提 PR 并通过验收无误
- 备注: 最终激励以实际提交 `pull request` 并合并为准


================================================
FILE: .github/workflows/build.yml
================================================
name: Build and Release

on:
  push:
    tags:
      - 'v*'

jobs:
  release:
    runs-on: ${{ matrix.os }}

    strategy:
      matrix:
        os: [macos-latest, windows-latest, ubuntu-latest]

    steps:
      - name: Check out Git repository
        uses: actions/checkout@v4

      - name: Install Node.js
        uses: actions/setup-node@v4
        with:
          node-version: 18

      - name: Install Dependencies
        run: npm install

      # MacOS Build
      - name: Build MacOS
        if: matrix.os == 'macos-latest'
        run: |
          export ELECTRON_BUILDER_EXTRA_ARGS="--universal"
          npm run build:mac
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          CSC_IDENTITY_AUTO_DISCOVERY: false
          DEBUG: electron-builder

      # Windows Build
      - name: Build Windows
        if: matrix.os == 'windows-latest'
        run: npm run build:win
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

      # Linux Build
      - name: Build Linux
        if: matrix.os == 'ubuntu-latest'
        run: |
          sudo apt-get update
          sudo apt-get install -y libgtk-3-dev webkit2gtk-4.0 libappindicator3-dev librsvg2-dev patchelf
          npm run build:linux
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

      # Get version from tag
      - name: Get version from tag
        id: get_version
        run: echo "VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_ENV
        shell: bash

      # Read release notes
      - name: Read release notes
        id: release_notes
        run: |
          NOTES=$(awk "/## \[v${{ env.VERSION }}\]/{p=1;print;next} /## \[v/{p=0}p" CHANGELOG.md)
          echo "NOTES<<EOF" >> $GITHUB_ENV
          echo "$NOTES" >> $GITHUB_ENV
          echo "EOF" >> $GITHUB_ENV
        shell: bash

      # Upload artifacts
      - name: Upload artifacts
        uses: softprops/action-gh-release@v1
        with:
          files: |
            dist/*.dmg
            dist/*.exe
            dist/*.deb
            dist/*.rpm
            dist/*.AppImage
            dist/latest*.yml
            dist/*.blockmap
          body: ${{ env.NOTES }}
          draft: false
          prerelease: false
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}


================================================
FILE: .github/workflows/deploy.yml
================================================
name: Deploy Web

on:
  push:
    branches:
      - main # 或者您的主分支名称
  workflow_dispatch: # 允许手动触发

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3

      - name: Setup Node.js
        uses: actions/setup-node@v3
        with:
          node-version: '18'

      - name: 创建环境变量文件
        run: |
          echo "VITE_API=${{ secrets.VITE_API }}" > .env.production.local
          echo "VITE_API_MUSIC=${{ secrets.VITE_API_MUSIC }}" >> .env.production.local
          # 添加其他需要的环境变量
          cat .env.production.local # 查看创建的文件内容,调试用

      - name: Install Dependencies
        run: npm install

      - name: Build
        run: npm run build

      - name: Deploy to Server
        uses: appleboy/scp-action@master
        with:
          host: ${{ secrets.SERVER_HOST }}
          username: ${{ secrets.SERVER_USERNAME }}
          key: ${{ secrets.DEPLOY_KEY }}
          source: 'out/renderer/*'
          target: ${{ secrets.DEPLOY_PATH }}
          strip_components: 2

      - name: Execute Remote Commands
        uses: appleboy/ssh-action@master
        with:
          host: ${{ secrets.SERVER_HOST }}
          username: ${{ secrets.SERVER_USERNAME }}
          key: ${{ secrets.DEPLOY_KEY }}
          script: |
            cd ${{ secrets.DEPLOY_PATH }}
            echo "部署完成于 $(date)"


================================================
FILE: .gitignore
================================================
node_modules
.DS_Store

dist
dist-ssr
*.local
dist_electron
.idea

# lock
yarn.lock
pnpm-lock.yaml
package-lock.json
dist.zip

.vscode

bun.lockb
bun.lock

.env.*.local

out

.cursorrules

.github/deploy_keys

resources/android/**/*
android/app/release

.cursor
.windsurf
.agent


.auto-imports.d.ts
.components.d.ts

src/renderer/auto-imports.d.ts
src/renderer/components.d.ts

================================================
FILE: .husky/pre-commit
================================================
echo "对已暂存文件运行 lint-staged..."
npx lint-staged

echo "运行类型检查..."
npm run typecheck

echo "所有检查通过,准备提交..."

================================================
FILE: .husky/pre-push
================================================
echo "对已暂存文件运行 lint-staged..."
npx lint-staged

echo "运行类型检查..."
npm run typecheck

echo "所有检查通过,准备提交..."

================================================
FILE: .prettierignore
================================================
out
dist
pnpm-lock.yaml
LICENSE.md
tsconfig.json
tsconfig.*.json


================================================
FILE: CHANGELOG.md
================================================
# 更新日志

## v5.0.0

### ✨ 新功能

- LX Music 音源脚本导入
- 逐字歌词,支持全屏歌词和桌面歌词同步显示
- 心动模式播放
- 移动设备整体页面风格和效果优化
- 移动端添加平板模式设置
- 歌词页面样式控制优化 支持背景、宽度、字体粗细等个性化设置
- 历史日推查看
- 播放记录热力图
- 历史记录支持本地和云端记录
- 用户页面收藏专辑展示
- 添加 GPU 硬件加速设置
- 菜单展开状态保存 - 感谢 [harenchi](https://github.com/souvenp) 的贡献
- 搜索建议 - 感谢 [harenchi](https://github.com/souvenp) 的贡献
- 歌词繁体中文翻译模块,集成 OpenCC 引擎 - 感谢 [Leko](https://github.com/lekoOwO) 的贡献
- 自定义 API源 支持 [自定义源文档](https://github.com/algerkong/AlgerMusicPlayer/blob/main/docs/custom-api-readme.md) - 感谢 [harenchi](https://github.com/souvenp) 的贡献

### 🐛 Bug 修复

- 修复随机播放顺序异常
- 修复音源解析错误处理
- 修复 Mini 播放栏主题颜色问题
- 修复桌面歌词透明模式标题栏显示
- 修复逐字歌词字间距
- 修复远程控制设置无法保存
- 修复下载无损格式返回 HiRes 音质 - 感谢 [harenchi](https://github.com/souvenp) 的贡献
- 兼容 pnpm 包管理器 - 感谢 [Leko](https://github.com/lekoOwO) 的贡献

### 🎨 优化

- 音源解析缓存
- 完善多语言国际化
- 优化播放检测和错误处理
- FLAC 元数据和封面图片处理 - 感谢 [harenchi](https://github.com/souvenp) 的贡献
- 日推不感兴趣调用官方接口 - 感谢 [harenchi](https://github.com/souvenp) 的贡献
- 代码提交流程优化,添加 lint-staged

## 赞赏支持☕️

[赞赏列表](https://donate.alger.fun/donate)

<table>
  <tr>
    <th style="text-align:center">微信赞赏</th>
    <th style="width:100px"></th>
    <th style="text-align:center">支付宝赞赏</th>
  </tr>
  <tr>
    <td align="center">
      <img src="https://github.com/algerkong/algerkong/blob/main/wechat.jpg?raw=true" alt="WeChat QRcode" width="200"><br>
      <h6>☕️喝点咖啡继续干</h6>
    </td>
    <td></td>
    <td align="center">
      <img src="https://github.com/algerkong/algerkong/blob/main/alipay.jpg?raw=true" alt="Alipay QRcode" width="200"><br>
      <h6>🍔来个汉堡</h6>
    </td>
  </tr>
</table>


================================================
FILE: DEV.md
================================================
# Alger Music Player 开发文档

## 项目结构

### 技术栈

- **前端框架**:Vue 3 + TypeScript
- **UI 组件库**:naive-ui
- **样式框架**:Tailwind CSS
- **图标库**:remixicon
- **状态管理**:Pinia
- **工具库**:VueUse
- **构建工具**:Vite, electron-vite
- **打包工具**:electron-builder
- **国际化**:vue-i18n
- **HTTP 客户端**:axios
- **本地存储**:electron-store localstorage
- **网易云音乐 API**:netease-cloud-music-api
- **音乐解锁**:@unblockneteasemusic/server

### 项目结构

```
AlgerMusicPlayer/
├── build/                  # 构建相关文件
├── docs/                   # 项目文档
├── node_modules/           # 依赖包
├── out/                    # 构建输出目录
├── resources/              # 资源文件
├── src/                    # 源代码
│   ├── i18n/               # 国际化配置
│   │   ├── lang/           # 语言包
│   │   ├── main.ts         # 主进程国际化入口
│   │   └── renderer.ts     # 渲染进程国际化入口
│   ├── main/               # Electron 主进程
│   │   ├── modules/        # 主进程模块
│   │   ├── index.ts        # 主进程入口
│   │   ├── lyric.ts        # 歌词处理
│   │   ├── server.ts       # 服务器
│   │   ├── set.json        # 设置
│   │   └── unblockMusic.ts # 音乐解锁
│   ├── preload/            # 预加载脚本
│   │   ├── index.ts        # 预加载脚本入口
│   │   └── index.d.ts      # 预加载脚本类型声明
│   └── renderer/           # Vue 渲染进程
│       ├── api/            # API 请求
│       ├── assets/         # 静态资源
│       ├── components/     # 组件
│       │   ├── common/     # 通用组件
│       │   ├── home/       # 首页组件
│       │   ├── lyric/      # 歌词组件
│       │   ├── settings/   # 设置组件
│       │   └── ...         # 其他组件
│       ├── const/          # 常量定义
│       ├── directive/      # 自定义指令
│       ├── hooks/          # 自定义 Hooks
│       ├── layout/         # 布局组件
│       ├── router/         # 路由配置
│       ├── services/       # 服务
│       ├── store/          # Pinia 状态管理
│       │   ├── modules/    # Pinia 模块
│       │   └── index.ts    # Pinia 入口
│       ├── type/           # 类型定义
│       ├── types/          # 更多类型定义
│       ├── utils/          # 工具函数
│       ├── views/          # 页面视图
│       ├── App.vue         # 根组件
│       ├── index.css       # 全局样式
│       ├── index.html      # HTML 模板
│       ├── main.ts         # 渲染进程入口
│       └── ...             # 其他文件
├── .env.development        # 开发环境变量
├── .env.development.local  # 本地开发环境变量
├── .env.production.local   # 本地生产环境变量
├── .eslintrc.cjs           # ESLint 配置
├── .gitignore              # Git 忽略文件
├── .prettierrc.yaml        # Prettier 配置
├── electron-builder.yml    # electron-builder 配置
├── electron.vite.config.ts # electron-vite 配置
├── package.json            # 项目配置
├── postcss.config.js       # PostCSS 配置
├── tailwind.config.js      # Tailwind 配置
├── tsconfig.json           # TypeScript 配置
├── tsconfig.node.json      # 节点 TypeScript 配置
└── tsconfig.web.json       # Web TypeScript 配置
```

### 主要组件说明

#### 主进程 (src/main)

主进程负责创建窗口、处理系统层面的交互以及与渲染进程的通信。

- **index.ts**: 应用主入口,负责创建窗口和应用生命周期管理
- **lyric.ts**: 歌词解析和处理
- **unblockMusic.ts**: 网易云音乐解锁功能
- **server.ts**: 本地服务器

#### 预加载脚本 (src/preload)

预加载脚本在渲染进程加载前执行,提供了渲染进程和主进程之间的桥接功能。

#### 渲染进程 (src/renderer)

渲染进程是基于 Vue 3 的前端应用,负责 UI 渲染和用户交互。

- **components/**: 包含各种 UI 组件
    - **common/**: 通用组件
    - **home/**: 首页相关组件
    - **lyric/**: 歌词显示组件
    - **settings/**: 设置界面组件
    - **MusicList.vue**: 音乐列表组件
    - **MvPlayer.vue**: MV 播放器
    - **EQControl.vue**: 均衡器控制
    - **...**: 其他组件

- **store/**: Pinia 状态管理
    - **modules/**: 各功能模块的状态管理
    - **index.ts**: 状态管理入口

- **views/**: 页面视图组件

- **router/**: 路由配置

- **api/**: API 请求封装

- **utils/**: 工具函数

### 开发指南

#### 命名约定

- 目录使用 kebab-case (如: components/auth-wizard)
- 组件文件名使用 PascalCase (如: AuthWizard.vue)
- 可组合式函数使用 camelCase (如: useAuthState.ts)

#### 代码风格

- 使用 Composition API 和 `<script setup>` 语法
- 使用 TypeScript 类型系统
- 优先使用类型而非接口
- 避免使用枚举,使用 const 对象代替
- 使用 tailwind 实现响应式设计

### 如何启动?

安装依赖(最好使用node18+):

```
npm install
```

#### 桌面端开发

启动桌面端开发:

```
npm run dev
```

#### 网页端开发

如果只启动网页端开发,需要自己部署服务 netease-cloud-music-api

需要复制一份 `.env.development.local` 到 `src/renderer` 下

```
# .env.development.local

# 你的接口地址 (必填)
VITE_API = ***
# 音乐破解接口地址
VITE_API_MUSIC = ***
```

启动web端开发:

```
npm run dev:web
```

### 打包

打包桌面端:

```
npm run build:win
```

打包后的文件在 /dist 下

打包网页端:

```
npm run build
```

打包后的文件在 /out/renderer 下


================================================
FILE: LICENSE
================================================
MIT License

Copyright (c) 2026 Alger

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: README.md
================================================
<h2 align="center">🎵 Alger Music Player</h2>
<div align="center">
<div align="center">
  <a href="https://github.com/algerkong/AlgerMusicPlayer/stargazers">
    <img src="https://img.shields.io/github/stars/algerkong/AlgerMusicPlayer?style=for-the-badge&logo=github&label=Stars&logoColor=white&color=22c55e" alt="GitHub stars">
  </a>
  <a href="https://github.com/algerkong/AlgerMusicPlayer/releases">
    <img src="https://img.shields.io/github/v/release/algerkong/AlgerMusicPlayer?style=for-the-badge&logo=github&label=Release&logoColor=white&color=1a67af" alt="GitHub release">
  </a>
  <a href="https://pd.qq.com/s/cs056n33q?b=5">
    <img src="https://img.shields.io/badge/QQ频道-algermusic-blue?style=for-the-badge&color=yellow" alt="加入频道">
  </a>
  <a href="https://t.me/+9efsKRuvKBk2NWVl">
    <img src="https://img.shields.io/badge/AlgerMusic-blue?style=for-the-badge&logo=telegram&logoColor=white&label=Telegram" alt="Telegram">
  </a>
   <a href="https://donate.alger.fun/">
    <img src="https://img.shields.io/badge/%E9%A1%B9%E7%9B%AE%E6%8D%90%E8%B5%A0-blue?style=for-the-badge&logo=telegram&logoColor=pink&color=pink&label=%E8%B5%9E%E5%8A%A9" alt="赞助">
  </a>
</div>
</div>
<div align="center">
  <a href="https://hellogithub.com/repository/607b849c598d48e08fe38789d156ebdc" target="_blank"><img src="https://api.hellogithub.com/v1/widgets/recommend.svg?rid=607b849c598d48e08fe38789d156ebdc&claim_uid=ObuMXUfeHBmk9TI&theme=neutral" alt="Featured|HelloGitHub" width="160" height="32" /></a>
</div>

[项目下安装以及常用问题文档](https://www.yuque.com/alger-pfg5q/ip4f1a/bmgmfmghnhgwghkm?singleDoc#)

主要功能如下

- 🎵 音乐推荐
- 🔐 网易云账号登录与同步
- 📝 功能
  - 播放历史记录
  - 歌曲收藏管理
  - 歌单 MV 排行榜 每日推荐
  - 自定义快捷键配置(全局或应用内)
- 🎨 界面与交互
  - 沉浸式歌词显示(点击左下角封面进入)
  - 独立桌面歌词窗口
  - 明暗主题切换
  - 迷你模式
  - 状态栏控制
  - 多语言支持
- 🎼 音乐功能
  - 支持歌单、MV、专辑等完整音乐服务
  - 音乐资源解析(基于 @unblockneteasemusic/server)
  - EQ均衡器
  - 定时播放 远程控制播放 倍速播放
  - 高品质音乐
  - 音乐文件下载
  - 搜索 MV 音乐 专辑 歌单 bilibili
  - 音乐单独选择音源解析
- 🚀 技术特性
  - 本地化服务,无需依赖在线API (基于 netease-cloud-music-api)
  - 全平台适配(Desktop & Web & Mobile Web & Android<测试> & ios<后续>)

## 项目简介

一个第三方音乐播放器、本地服务、桌面歌词、音乐下载、最高音质

## 预览地址

[http://music.alger.fun/](http://music.alger.fun/)

## 软件截图

![首页白](./docs/image.png)
![首页黑](./docs/image3.png)
![歌词](./docs/image6.png)
![桌面歌词](./docs/image2.png)
![设置页面](./docs/image4.png)
![音乐远程控制](./docs/image5.png)

## 项目启动

```bash
npm install
npm run dev
```

## 开发文档

点击这里[开发文档](./DEV.md)

## 赞赏☕️

[赞赏列表](http://donate.alger.fun/)
| 微信赞赏 | 支付宝赞赏 |
| :--------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------: |
| <img src="https://github.com/algerkong/algerkong/blob/main/wechat.jpg?raw=true" alt="WeChat QRcode" width=200> <br><small>喝点咖啡继续干</small> | <img src="https://github.com/algerkong/algerkong/blob/main/alipay.jpg?raw=true" alt="Wechat QRcode" width=200> <br><small>来包辣条吧~</small> |

## 项目统计

[![Stargazers over time](https://starchart.cc/algerkong/AlgerMusicPlayer.svg?variant=adaptive)](https://starchart.cc/algerkong/AlgerMusicPlayer)
![Alt](https://repobeats.axiom.co/api/embed/c4d01b3632e241c90cdec9508dfde86a7f54c9f5.svg 'Repobeats analytics image')

## 欢迎提Issues

## 声明

本软件仅用于学习交流,禁止用于商业用途,否则后果自负。
希望大家还是要多多支持官方正版,此软件仅用作开发教学。


================================================
FILE: android/.gitignore
================================================
# Using Android gitignore template: https://github.com/github/gitignore/blob/HEAD/Android.gitignore

# Built application files
*.apk
*.aar
*.ap_
*.aab

# Files for the ART/Dalvik VM
*.dex

# Java class files
*.class

# Generated files
bin/
gen/
out/
#  Uncomment the following line in case you need and you don't have the release build type files in your app
# release/

# Gradle files
.gradle/
build/

# Local configuration file (sdk path, etc)
local.properties

# Proguard folder generated by Eclipse
proguard/

# Log Files
*.log

# Android Studio Navigation editor temp files
.navigation/

# Android Studio captures folder
captures/

# IntelliJ
*.iml
.idea/workspace.xml
.idea/tasks.xml
.idea/gradle.xml
.idea/assetWizardSettings.xml
.idea/dictionaries
.idea/libraries
# Android Studio 3 in .gitignore file.
.idea/caches
.idea/modules.xml
# Comment next line if keeping position of elements in Navigation Editor is relevant for you
.idea/navEditor.xml

# Keystore files
# Uncomment the following lines if you do not want to check your keystore files in.
#*.jks
#*.keystore

# External native build folder generated in Android Studio 2.2 and later
.externalNativeBuild
.cxx/

# Google Services (e.g. APIs or Firebase)
# google-services.json

# Freeline
freeline.py
freeline/
freeline_project_description.json

# fastlane
fastlane/report.xml
fastlane/Preview.html
fastlane/screenshots
fastlane/test_output
fastlane/readme.md

# Version control
vcs.xml

# lint
lint/intermediates/
lint/generated/
lint/outputs/
lint/tmp/
# lint/reports/

# Android Profiling
*.hprof

# Cordova plugins for Capacitor
capacitor-cordova-android-plugins

# Copied web assets
app/src/main/assets/public

# Generated Config files
app/src/main/assets/capacitor.config.json
app/src/main/assets/capacitor.plugins.json
app/src/main/res/xml/config.xml


================================================
FILE: build/entitlements.mac.plist
================================================
<?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/>
    <key>com.apple.security.network.client</key>
    <true/>
    <key>com.apple.security.network.server</key>
    <true/>
    <key>com.apple.security.files.user-selected.read-write</key>
    <true/>
    <key>com.apple.security.files.downloads.read-write</key>
    <true/>
    <key>com.apple.security.device.microphone</key>
    <true/>
  </dict>
</plist>


================================================
FILE: build/installer.nsh
================================================
# 设置 Windows 7 兼容性
ManifestDPIAware true
ManifestSupportedOS all

!macro customInit
  # 检查系统版本
  ${If} ${AtLeastWin7}
    # Windows 7 或更高版本
  ${Else}
    MessageBox MB_OK|MB_ICONSTOP "此应用程序需要 Windows 7 或更高版本。"
    Abort
  ${EndIf}
!macroend 

================================================
FILE: dev-app-update.yml
================================================
provider: generic
url: https://example.com/auto-updates
updaterCacheDirName: electron-lan-file-updater


================================================
FILE: docs/custom-api-readme.md
================================================
## 🎵 自定义音源API配置

现在支持通过导入一个简单的 JSON 配置文件来对接第三方的音乐解析 API。这将提供极大的灵活性,可以接入任意第三方音源。

### 如何使用

1.  前往 **设置 -> 播放设置 -> 音源设置**。
2.  在 **自定义 API 设置** 区域,点击 **“导入 JSON 配置”** 按钮。
3.  选择你已经编写好的 `xxx.json` 配置文件。
4.  导入成功后,程序将优先使用你的自定义 API 进行解析。

### JSON 配置文件格式说明

导入的配置文件必须是一个合法的 JSON 文件,并包含以下字段:

| 字段名            | 类型     | 是否必须 | 描述                                                                                                                        |
| ----------------- | -------- | -------- | --------------------------------------------------------------------------------------------------------------------------- |
| `name`            | `string` | 是       | API 名称,将显示在应用的 UI 界面上。                                                                                        |
| `apiUrl`          | `string` | 是       | API 的基础请求地址。                                                                                                        |
| `method`          | `string` | 否       | HTTP 请求方法。可以是 `"GET"` 或 `"POST"`。**如果省略,默认为 "GET"**。                                                     |
| `params`          | `object` | 是       | 请求时需要发送的参数。对于 `GET` 请求,它们会作为查询字符串;对于 `POST` 请求,它们会作为请求体。                           |
| `qualityMapping`  | `object` | 否       | **音质映射表**。用于将应用内部的音质值(如 `"lossless"`)翻译成你的 API 需要的特定值。如果省略,则直接使用应用内部值。      |
| `responseUrlPath` | `string` | 是       | **URL提取路径**。用于从 API 返回的 JSON 响应中找到最终可播放的音乐链接。支持点 `.` 和方括号 `[]` 语法来访问嵌套对象和数组。 |

#### 占位符

在 `params` 对象的值中,你可以使用以下占位符,程序在请求时会自动替换它们:

- `{songId}`: 将被替换为当前歌曲的 ID。
- `{quality}`: 将被替换为当前用户设置的音质字符串 (例如, `"higher"`, `"lossless"`)。

#### 音质值列表

应用内部使用的音质值如下,你可以在 `qualityMapping` 中使用它们作为**键**:
`standard`, `higher`, `exhigh`, `lossless`, `hires`, `jyeffect`, `sky`, `dolby`, `jymaster`

### 示例

假设有一个 API 如下:
`https://api.example.com/music?song_id=12345&bitrate=320000`
它返回的 JSON 是:
`{ "code": 200, "data": { "play_url": "http://..." } }`

那么对应的 JSON 配置文件应该是:

```json
{
  "name": "Example API",
  "apiUrl": "https://api.example.com/music",
  "method": "GET",
  "params": {
    "song_id": "{songId}",
    "bitrate": "{quality}"
  },
  "qualityMapping": {
    "higher": "128000",
    "exhigh": "320000",
    "lossless": "999000"
  },
  "responseUrlPath": "data.play_url"
}
```


================================================
FILE: electron.vite.config.ts
================================================
import vue from '@vitejs/plugin-vue';
import { defineConfig } 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';
import VueDevTools from 'vite-plugin-vue-devtools';

export default defineConfig({
  main: {},
  preload: {},
  renderer: {
    resolve: {
      alias: {
        '@': resolve('src/renderer'),
        '@renderer': resolve('src/renderer'),
        '@i18n': resolve('src/i18n')
      }
    },
    plugins: [
      vue(),
      viteCompression(),
      VueDevTools(),
      AutoImport({
        imports: [
          'vue',
          {
            'naive-ui': ['useDialog', 'useMessage', 'useNotification', 'useLoadingBar']
          }
        ]
      }),
      Components({
        resolvers: [NaiveUiResolver()]
      })
    ],
    publicDir: resolve('resources'),
    server: {
      host: '0.0.0.0',
      port: 2389
    }
  }
});


================================================
FILE: eslint.config.mjs
================================================
import js from '@eslint/js';
import typescript from '@typescript-eslint/eslint-plugin';
import typescriptParser from '@typescript-eslint/parser';
import vue from 'eslint-plugin-vue';
import vueParser from 'vue-eslint-parser';
import prettier from 'eslint-plugin-prettier';
import simpleImportSort from 'eslint-plugin-simple-import-sort';
import vueScopedCss from 'eslint-plugin-vue-scoped-css';
import globals from 'globals';

export default [
  // 忽略文件配置
  {
    ignores: ['node_modules/**', 'dist/**', 'out/**', '.gitignore']
  },

  // 基础 JavaScript 配置
  js.configs.recommended,

  // JavaScript 文件配置
  {
    files: ['**/*.js', '**/*.cjs', '**/*.mjs'],
    languageOptions: {
      ecmaVersion: 'latest',
      sourceType: 'module',
      globals: {
        ...globals.node,
        ...globals.browser
      }
    },
    rules: {
      'no-console': 'off',
      'no-undef': 'error'
    }
  },

  // TypeScript 文件配置
  {
    files: ['**/*.ts', '**/*.tsx'],
    languageOptions: {
      parser: typescriptParser,
      parserOptions: {
        ecmaVersion: 'latest',
        sourceType: 'module',
        allowImportExportEverywhere: true,
        ecmaFeatures: {
          jsx: true
        }
      },
      globals: {
        ...globals.node,
        ...globals.browser,
        // Vue 3 特定全局变量
        defineProps: 'readonly',
        defineEmits: 'readonly',
        // TypeScript 全局类型
        NodeJS: 'readonly',
        ScrollBehavior: 'readonly'
      }
    },
    plugins: {
      '@typescript-eslint': typescript,
      'simple-import-sort': simpleImportSort
    },
    rules: {
      '@typescript-eslint/no-explicit-any': 'off',
      '@typescript-eslint/explicit-module-boundary-types': 'off',
      '@typescript-eslint/no-unused-vars': [
        'error',
        // we are only using this rule to check for unused arguments since TS
        // catches unused variables but not args.
        { varsIgnorePattern: '.*', args: 'none' }
      ],
      '@typescript-eslint/no-use-before-define': 'off',
      '@typescript-eslint/ban-ts-comment': 'off',
      '@typescript-eslint/ban-types': 'off',
      '@typescript-eslint/explicit-function-return-type': 'off',
      'simple-import-sort/imports': 'error',
      'simple-import-sort/exports': 'error',
      'no-console': 'off',
      'no-unused-vars': [
        'error',
        // we are only using this rule to check for unused arguments since TS
        // catches unused variables but not args.
        { varsIgnorePattern: '.*', args: 'none' }
      ],
      'no-use-before-define': 'off',
      'max-classes-per-file': 'off',
      'no-await-in-loop': 'off',
      'dot-notation': 'off',
      'constructor-super': 'off',
      'getter-return': 'off',
      'no-const-assign': 'off',
      'no-dupe-args': 'off',
      'no-dupe-class-members': 'off',
      'no-dupe-keys': 'off',
      'no-func-assign': 'off',
      'no-import-assign': 'off',
      'no-new-symbol': 'off',
      'no-obj-calls': 'off',
      'no-redeclare': 'off',
      'no-setter-return': 'off',
      'no-this-before-super': 'off',
      'no-undef': 'off',
      'no-unreachable': 'off',
      'no-unsafe-negation': 'off',
      'no-var': 'error',
      'prefer-const': 'error',
      'prefer-rest-params': 'error',
      'prefer-spread': 'error',
      'valid-typeof': 'off',
      'consistent-return': 'off',
      'no-promise-executor-return': 'off',
      'prefer-promise-reject-errors': 'off'
    }
  },

  // Vue 文件配置
  {
    files: ['**/*.vue'],
    languageOptions: {
      parser: vueParser,
      parserOptions: {
        parser: typescriptParser,
        ecmaVersion: 'latest',
        sourceType: 'module',
        allowImportExportEverywhere: true
      },
      globals: {
        ...globals.browser,
        // Vue 3 特定全局变量
        defineProps: 'readonly',
        defineEmits: 'readonly',
        // Vue 3 Composition API (如果使用了 unplugin-auto-import)
        ref: 'readonly',
        reactive: 'readonly',
        computed: 'readonly',
        watch: 'readonly',
        watchEffect: 'readonly',
        onMounted: 'readonly',
        onUnmounted: 'readonly',
        onBeforeUnmount: 'readonly',
        nextTick: 'readonly',
        inject: 'readonly',
        provide: 'readonly',
        // Naive UI (如果使用了 unplugin-auto-import)
        useDialog: 'readonly',
        useMessage: 'readonly',
        // TypeScript 全局类型
        NodeJS: 'readonly',
        ScrollBehavior: 'readonly'
      }
    },
    plugins: {
      vue,
      '@typescript-eslint': typescript,
      prettier,
      'simple-import-sort': simpleImportSort,
      'vue-scoped-css': vueScopedCss
    },
    rules: {
      // Vue 3 推荐规则
      'vue/no-unused-vars': 'error',
      'vue/no-unused-components': 'error',
      'vue/no-multiple-template-root': 'off',
      'vue/no-v-model-argument': 'off',
      'vue/require-default-prop': 'off',
      'vue/multi-word-component-names': 'off',
      'vue/component-name-in-template-casing': ['error', 'kebab-case'],
      'vue/no-reserved-props': 'off',
      'vue/no-v-html': 'off',
      'vue/first-attribute-linebreak': 'off',
      'vue-scoped-css/enforce-style-type': [
        'error',
        {
          allows: ['scoped']
        }
      ],
      '@typescript-eslint/explicit-function-return-type': 'off',
      '@typescript-eslint/no-explicit-any': 'off',
      '@typescript-eslint/explicit-module-boundary-types': 'off',
      'prettier/prettier': 'error',
      'simple-import-sort/imports': 'error',
      'simple-import-sort/exports': 'error'
    }
  },

  // TypeScript 类型定义文件配置
  {
    files: ['**/*.d.ts'],
    rules: {
      'no-unused-vars': 'off',
      '@typescript-eslint/no-unused-vars': 'off',
      '@typescript-eslint/no-explicit-any': 'off',
      '@typescript-eslint/no-empty-interface': 'off'
    }
  },

  // JavaScript 第三方库文件配置
  {
    files: ['**/assets/**/*.js', '**/vendor/**/*.js', '**/lib/**/*.js'],
    rules: {
      'no-unused-vars': 'off',
      'no-redeclare': 'off',
      'no-self-assign': 'off',
      'no-undef': 'off'
    }
  },

  // 通用规则
  {
    files: ['**/*.js', '**/*.ts', '**/*.vue'],
    rules: {
      'no-console': 'off',
      'no-underscore-dangle': 'off',
      'no-nested-ternary': 'off',
      'no-await-in-loop': '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',
      'class-methods-use-this': 'off',
      'no-case-declarations': 'off',
      'no-unused-vars': [
        'error',
        // we are only using this rule to check for unused arguments since TS
        // catches unused variables but not args.
        { varsIgnorePattern: '.*', args: 'none' }
      ]
    }
  }
];


================================================
FILE: package.json
================================================
{
  "name": "AlgerMusicPlayer",
  "version": "5.0.0",
  "description": "Alger Music Player",
  "author": "Alger <algerkc@qq.com>",
  "main": "./out/main/index.js",
  "homepage": "https://github.com/algerkong/AlgerMusicPlayer",
  "scripts": {
    "prepare": "husky",
    "format": "prettier --write ./src",
    "lint": "eslint ./src --fix",
    "typecheck:node": "tsc --noEmit -p tsconfig.node.json --composite false",
    "typecheck:web": "vue-tsc --noEmit -p tsconfig.web.json --composite false",
    "typecheck": "npm run typecheck:node && npm run typecheck:web",
    "start": "electron-vite preview",
    "dev": "electron-vite dev",
    "dev:web": "vite dev",
    "build": "electron-vite build",
    "postinstall": "electron-builder install-app-deps",
    "build:unpack": "npm run build && electron-builder --dir",
    "build:win": "npm run build && electron-builder --win",
    "build:mac": "npm run build && electron-builder --mac",
    "build:linux": "npm run build && electron-builder --linux"
  },
  "lint-staged": {
    "*.{ts,tsx,vue,js}": [
      "eslint --fix"
    ],
    "*.{ts,tsx,vue,js,css,scss,md,json}": [
      "prettier --write"
    ]
  },
  "dependencies": {
    "@electron-toolkit/preload": "^3.0.2",
    "@electron-toolkit/utils": "^4.0.0",
    "@unblockneteasemusic/server": "^0.27.10",
    "cors": "^2.8.5",
    "crypto-js": "^4.2.0",
    "electron-store": "^8.2.0",
    "electron-updater": "^6.6.2",
    "electron-window-state": "^5.0.3",
    "express": "^4.22.1",
    "file-type": "^21.1.1",
    "flac-tagger": "^1.0.7",
    "font-list": "^1.6.0",
    "form-data": "^4.0.5",
    "husky": "^9.1.7",
    "jsencrypt": "^3.5.4",
    "music-metadata": "^11.10.3",
    "netease-cloud-music-api-alger": "^4.26.1",
    "node-fetch": "^2.7.0",
    "node-id3": "^0.2.9",
    "node-machine-id": "^1.1.12",
    "pinia-plugin-persistedstate": "^4.7.1",
    "sharp": "^0.34.5",
    "vue-i18n": "^11.2.2"
  },
  "devDependencies": {
    "@electron-toolkit/eslint-config": "^2.1.0",
    "@electron-toolkit/eslint-config-ts": "^3.1.0",
    "@electron-toolkit/tsconfig": "^1.0.1",
    "@eslint/js": "^9.39.2",
    "@rushstack/eslint-patch": "^1.15.0",
    "@types/howler": "^2.2.12",
    "@types/node": "^20.19.26",
    "@types/node-fetch": "^2.6.13",
    "@types/tinycolor2": "^1.4.6",
    "@typescript-eslint/eslint-plugin": "^8.49.0",
    "@typescript-eslint/parser": "^8.49.0",
    "@vitejs/plugin-vue": "^5.2.4",
    "@vue/compiler-sfc": "^3.5.25",
    "@vue/eslint-config-prettier": "^10.2.0",
    "@vue/eslint-config-typescript": "^14.6.0",
    "@vue/runtime-core": "^3.5.25",
    "@vueuse/core": "^11.3.0",
    "@vueuse/electron": "^13.9.0",
    "animate.css": "^4.1.1",
    "autoprefixer": "^10.4.22",
    "axios": "^1.13.2",
    "cross-env": "^7.0.3",
    "electron": "^39.2.7",
    "electron-builder": "^26.0.12",
    "electron-vite": "^5.0.0",
    "eslint": "^9.39.2",
    "eslint-config-prettier": "^10.1.8",
    "eslint-plugin-import": "^2.32.0",
    "eslint-plugin-prettier": "^5.5.4",
    "eslint-plugin-simple-import-sort": "^12.1.1",
    "eslint-plugin-vue": "^10.6.2",
    "eslint-plugin-vue-scoped-css": "^2.12.0",
    "globals": "^16.5.0",
    "howler": "^2.2.4",
    "lint-staged": "^15.5.2",
    "lodash": "^4.17.21",
    "marked": "^15.0.12",
    "naive-ui": "^2.43.2",
    "pinia": "^3.0.4",
    "pinyin-match": "^1.2.10",
    "postcss": "^8.5.6",
    "prettier": "^3.7.4",
    "remixicon": "^4.7.0",
    "sass": "^1.96.0",
    "tailwindcss": "^3.4.19",
    "tinycolor2": "^1.6.0",
    "tunajs": "^1.0.15",
    "typescript": "^5.9.3",
    "unplugin-auto-import": "^19.3.0",
    "unplugin-vue-components": "^28.8.0",
    "vite": "^6.4.1",
    "vite-plugin-compression": "^0.5.1",
    "vite-plugin-vue-devtools": "7.7.2",
    "vue": "^3.5.25",
    "vue-eslint-parser": "^10.2.0",
    "vue-router": "^4.6.4",
    "vue-tsc": "^2.2.12"
  },
  "build": {
    "appId": "com.alger.music",
    "productName": "AlgerMusicPlayer",
    "publish": [
      {
        "provider": "github",
        "owner": "algerkong",
        "repo": "AlgerMusicPlayer"
      }
    ],
    "extraResources": [
      {
        "from": "resources/html",
        "to": "html",
        "filter": [
          "**/*"
        ]
      }
    ],
    "mac": {
      "icon": "resources/icon.icns",
      "target": [
        {
          "target": "dmg",
          "arch": [
            "universal"
          ]
        }
      ],
      "artifactName": "${productName}-${version}-mac-${arch}.${ext}",
      "darkModeSupport": true,
      "hardenedRuntime": false,
      "gatekeeperAssess": false,
      "entitlements": "build/entitlements.mac.plist",
      "entitlementsInherit": "build/entitlements.mac.plist",
      "extendInfo": {
        "NSMicrophoneUsageDescription": "AlgerMusicPlayer needs access to the microphone for audio visualization.",
        "NSCameraUsageDescription": "Application requests access to the device's camera.",
        "NSDocumentsFolderUsageDescription": "Application requests access to the user's Documents folder.",
        "NSDownloadsFolderUsageDescription": "Application requests access to the user's Downloads folder."
      },
      "notarize": false,
      "identity": null,
      "type": "distribution",
      "binaries": [
        "Contents/MacOS/AlgerMusicPlayer"
      ]
    },
    "win": {
      "icon": "resources/icon.ico",
      "target": [
        {
          "target": "nsis",
          "arch": [
            "x64",
            "ia32",
            "arm64"
          ]
        }
      ],
      "artifactName": "${productName}-${version}-win-${arch}.${ext}",
      "requestedExecutionLevel": "asInvoker"
    },
    "linux": {
      "icon": "resources/icon.png",
      "target": [
        {
          "target": "AppImage",
          "arch": [
            "x64",
            "arm64"
          ]
        },
        {
          "target": "deb",
          "arch": [
            "x64",
            "arm64"
          ]
        },
        {
          "target": "rpm",
          "arch": [
            "x64",
            "arm64"
          ]
        }
      ],
      "artifactName": "${productName}-${version}-linux-${arch}.${ext}",
      "category": "Audio",
      "maintainer": "Alger <algerkc@qq.com>"
    },
    "nsis": {
      "oneClick": false,
      "allowToChangeInstallationDirectory": true,
      "installerIcon": "resources/icon.ico",
      "uninstallerIcon": "resources/icon.ico",
      "createDesktopShortcut": true,
      "createStartMenuShortcut": true,
      "shortcutName": "AlgerMusicPlayer",
      "include": "build/installer.nsh",
      "deleteAppDataOnUninstall": true,
      "uninstallDisplayName": "AlgerMusicPlayer"
    }
  },
  "pnpm": {
    "onlyBuiltDependencies": [
      "electron",
      "esbuild"
    ]
  }
}


================================================
FILE: postcss.config.js
================================================
module.exports = {
  plugins: {
    tailwindcss: {},
    autoprefixer: {}
  }
};


================================================
FILE: prettier.config.js
================================================
/**
 * @type {import('prettier').Config}
 */
module.exports = {
  singleQuote: true,
  semi: true,
  printWidth: 100,
  trailingComma: 'none',
  endOfLine: 'auto'
};


================================================
FILE: resources/html/remote-control.html
================================================
<!doctype html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <meta
      name="viewport"
      content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"
    />
    <title>AlgerMusicPlayer 远程控制</title>
    <style>
      :root {
        --primary-color: #007aff;
        --secondary-color: #5ac8fa;
        --success-color: #4cd964;
        --danger-color: #ff3b30;
        --warning-color: #ff9500;
        --light-gray: #f2f2f7;
        --medium-gray: #e5e5ea;
        --dark-gray: #8e8e93;
        --text-color: #000000;
        --text-secondary: #6c6c6c;
        --background-color: #ffffff;
      }

      @media (prefers-color-scheme: dark) {
        :root {
          --primary-color: #0a84ff;
          --secondary-color: #64d2ff;
          --success-color: #30d158;
          --danger-color: #ff453a;
          --warning-color: #ff9f0a;
          --light-gray: #1c1c1e;
          --medium-gray: #2c2c2e;
          --dark-gray: #8e8e93;
          --text-color: #ffffff;
          --text-secondary: #aeaeb2;
          --background-color: #000000;
        }
      }

      * {
        margin: 0;
        padding: 0;
        box-sizing: border-box;
        -webkit-tap-highlight-color: transparent;
      }

      body {
        font-family:
          -apple-system, BlinkMacSystemFont, 'SF Pro Text', 'Helvetica Neue', Arial, sans-serif;
        line-height: 1.6;
        color: var(--text-color);
        background-color: var(--light-gray);
        display: flex;
        flex-direction: column;
        min-height: 100vh;
        padding: 0;
        margin: 0;
      }

      .header {
        position: sticky;
        top: 0;
        z-index: 100;
        background-color: var(--background-color);
        padding: 12px 16px;
        text-align: center;
        border-bottom: 1px solid var(--medium-gray);
        backdrop-filter: blur(10px);
        -webkit-backdrop-filter: blur(10px);
      }

      .header h1 {
        font-size: 18px;
        font-weight: 600;
        margin: 0;
      }

      .container {
        max-width: 540px;
        margin: 0 auto;
        padding: 16px;
        width: 100%;
        flex: 1;
      }

      .card {
        background-color: var(--background-color);
        border-radius: 12px;
        padding: 16px;
        margin-bottom: 16px;
        box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
      }

      .song-info {
        display: flex;
        align-items: center;
        padding-bottom: 16px;
      }

      .song-cover {
        width: 72px;
        height: 72px;
        border-radius: 8px;
        object-fit: cover;
        box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
        background-color: var(--medium-gray);
      }

      .song-details {
        margin-left: 16px;
        flex: 1;
      }

      .song-details h2 {
        margin: 0;
        font-size: 18px;
        font-weight: 600;
        color: var(--text-color);
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
      }

      .song-details p {
        margin: 4px 0 0;
        font-size: 15px;
        color: var(--text-secondary);
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
      }

      .play-state {
        font-size: 14px;
        color: var(--primary-color);
        margin-top: 4px;
        display: flex;
        align-items: center;
      }

      .play-state::before {
        content: '';
        display: inline-block;
        width: 8px;
        height: 8px;
        border-radius: 50%;
        margin-right: 6px;
      }

      .playing .play-state::before {
        background-color: var(--success-color);
      }

      .paused .play-state::before {
        background-color: var(--warning-color);
      }

      .controls {
        display: grid;
        grid-template-columns: repeat(3, 1fr);
        gap: 12px;
        margin-bottom: 16px;
      }

      .extra-controls {
        display: grid;
        grid-template-columns: repeat(2, 1fr);
        gap: 12px;
      }

      .btn {
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        background-color: var(--background-color);
        color: var(--primary-color);
        border: 1px solid var(--medium-gray);
        padding: 16px 0;
        border-radius: 12px;
        cursor: pointer;
        font-size: 14px;
        font-weight: 500;
        transition: all 0.2s ease;
        user-select: none;
        position: relative;
        overflow: hidden;
      }

      .btn:active {
        transform: scale(0.97);
        opacity: 0.7;
      }

      .btn::before {
        content: '';
        position: absolute;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        background-color: var(--primary-color);
        opacity: 0;
        transition: opacity 0.2s ease;
        z-index: -1;
      }

      .btn:active::before {
        opacity: 0.1;
      }

      .btn svg {
        margin-bottom: 8px;
        width: 24px;
        height: 24px;
        fill: var(--primary-color);
      }

      .btn-play svg {
        width: 28px;
        height: 28px;
        margin-bottom: 6px;
      }

      .status-bar {
        text-align: center;
        padding: 8px 16px;
        font-size: 14px;
        color: var(--text-secondary);
        background-color: var(--background-color);
        border-top: 1px solid var(--medium-gray);
        position: sticky;
        bottom: 0;
      }

      .status-message {
        display: inline-block;
        transition: opacity 0.3s ease;
      }

      .status-message.fade {
        opacity: 0;
      }

      .refresh-button {
        color: var(--primary-color);
        background: none;
        border: none;
        font-size: 14px;
        cursor: pointer;
        padding: 0;
        margin-left: 8px;
      }

      @media (max-width: 350px) {
        .controls,
        .extra-controls {
          gap: 8px;
        }

        .btn {
          padding: 12px 0;
          font-size: 12px;
        }

        .btn svg {
          width: 20px;
          height: 20px;
          margin-bottom: 6px;
        }
      }
    </style>
  </head>
  <body>
    <div class="header">
      <h1>AlgerMusicPlayer 远程控制</h1>
    </div>

    <div class="container">
      <div class="card" id="songInfoCard">
        <div class="song-info">
          <img
            id="songCover"
            class="song-cover"
            src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%238E8E93'%3E%3Cpath d='M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 14.5c-2.49 0-4.5-2.01-4.5-4.5S9.51 7.5 12 7.5s4.5 2.01 4.5 4.5-2.01 4.5-4.5 4.5zm0-5.5c-.55 0-1 .45-1 1s.45 1 1 1 1-.45 1-1-.45-1-1-1z'/%3E%3C/svg%3E"
            alt="封面"
          />
          <div class="song-details">
            <h2 id="songTitle">未在播放</h2>
            <p id="songArtist">--</p>
            <div class="play-state" id="playState">未播放</div>
          </div>
        </div>
      </div>

      <div class="card">
        <div class="controls">
          <button id="prevBtn" class="btn">
            <svg viewBox="0 0 24 24" fill="currentColor">
              <path d="M6 6h2v12H6zm3.5 6l8.5 6V6z" />
            </svg>
            上一首
          </button>
          <button id="playBtn" class="btn btn-play">
            <svg id="playIcon" viewBox="0 0 24 24" fill="currentColor">
              <path d="M8 5v14l11-7z" />
            </svg>
            播放/暂停
          </button>
          <button id="nextBtn" class="btn">
            <svg viewBox="0 0 24 24" fill="currentColor">
              <path d="M6 18l8.5-6L6 6v12zM16 6v12h2V6h-2z" />
            </svg>
            下一首
          </button>
        </div>

        <div class="extra-controls">
          <button id="volumeDownBtn" class="btn">
            <svg viewBox="0 0 24 24" fill="currentColor">
              <path
                d="M18.5 12c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02zM5 9v6h4l5 5V4L9 9H5z"
              />
            </svg>
            音量-
          </button>
          <button id="volumeUpBtn" class="btn">
            <svg viewBox="0 0 24 24" fill="currentColor">
              <path
                d="M3 9v6h4l5 5V4L7 9H3zm13.5 3c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02zM14 3.23v2.06c2.89.86 5 3.54 5 6.71s-2.11 5.85-5 6.71v2.06c4.01-.91 7-4.49 7-8.77s-2.99-7.86-7-8.77z"
              />
            </svg>
            音量+
          </button>
        </div>
      </div>

      <div class="card">
        <div class="extra-controls">
          <button id="favoriteBtn" class="btn">
            <svg viewBox="0 0 24 24" fill="currentColor">
              <path
                d="M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z"
              />
            </svg>
            收藏
          </button>
          <button id="refreshBtn" class="btn">
            <svg viewBox="0 0 24 24" fill="currentColor">
              <path
                d="M17.65 6.35C16.2 4.9 14.21 4 12 4c-4.42 0-7.99 3.58-7.99 8s3.57 8 7.99 8c3.73 0 6.84-2.55 7.73-6h-2.08c-.82 2.33-3.04 4-5.65 4-3.31 0-6-2.69-6-6s2.69-6 6-6c1.66 0 3.14.69 4.22 1.78L13 11h7V4l-2.35 2.35z"
              />
            </svg>
            刷新
          </button>
        </div>
      </div>
    </div>

    <div class="status-bar">
      <span id="status" class="status-message">准备就绪</span>
    </div>

    <script>
      // 页面加载完成后执行
      document.addEventListener('DOMContentLoaded', () => {
        // 获取DOM元素
        const songInfoCard = document.getElementById('songInfoCard');
        const songTitle = document.getElementById('songTitle');
        const songArtist = document.getElementById('songArtist');
        const songCover = document.getElementById('songCover');
        const playState = document.getElementById('playState');
        const playBtn = document.getElementById('playBtn');
        const playIcon = document.getElementById('playIcon');
        const prevBtn = document.getElementById('prevBtn');
        const nextBtn = document.getElementById('nextBtn');
        const favoriteBtn = document.getElementById('favoriteBtn');
        const volumeUpBtn = document.getElementById('volumeUpBtn');
        const volumeDownBtn = document.getElementById('volumeDownBtn');
        const refreshBtn = document.getElementById('refreshBtn');
        const status = document.getElementById('status');

        let isPlaying = false;

        // 显示状态消息并淡出
        function showStatus(message, autoClear = true) {
          status.textContent = message;
          status.classList.remove('fade');

          if (autoClear) {
            setTimeout(() => {
              status.classList.add('fade');
            }, 2000);
          }
        }

        // 更新播放/暂停图标
        function updatePlayIcon() {
          if (isPlaying) {
            playIcon.innerHTML = '<path d="M6 19h4V5H6v14zm8-14v14h4V5h-4z"/>';
          } else {
            playIcon.innerHTML = '<path d="M8 5v14l11-7z"/>';
          }
        }

        // 更新状态的函数
        async function updateStatus() {
          try {
            showStatus('获取播放状态...', false);

            const response = await fetch('/api/status');
            const data = await response.json();

            // 更新播放状态
            isPlaying = data.isPlaying;
            updatePlayIcon();

            // 更新UI
            if (data.currentSong) {
              songTitle.textContent = data.currentSong.name || '未知歌曲';

              if (data.currentSong.ar && data.currentSong.ar.length) {
                songArtist.textContent = data.currentSong.ar.map((a) => a.name).join(', ');
              } else if (data.currentSong.artists && data.currentSong.artists.length) {
                songArtist.textContent = data.currentSong.artists.map((a) => a.name).join(', ');
              } else {
                songArtist.textContent = '未知艺术家';
              }

              if (data.currentSong.picUrl) {
                songCover.src = data.currentSong.picUrl;
              }
            } else {
              songTitle.textContent = '未在播放';
              songArtist.textContent = '--';
              songCover.src =
                "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%238E8E93'%3E%3Cpath d='M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 14.5c-2.49 0-4.5-2.01-4.5-4.5S9.51 7.5 12 7.5s4.5 2.01 4.5 4.5-2.01 4.5-4.5 4.5zm0-5.5c-.55 0-1 .45-1 1s.45 1 1 1 1-.45 1-1-.45-1-1-1z'/%3E%3C/svg%3E";
            }

            // 更新播放状态
            playState.textContent = isPlaying ? '正在播放' : '已暂停';
            songInfoCard.className = isPlaying ? 'card playing' : 'card paused';

            showStatus('已更新', true);
          } catch (error) {
            console.error('获取状态失败:', error);
            showStatus('获取状态失败');
          }
        }

        // 发送命令的函数
        async function sendCommand(endpoint) {
          try {
            showStatus('发送命令中...', false);
            const response = await fetch('/api/' + endpoint, { method: 'POST' });
            const data = await response.json();

            showStatus(data.message || '命令已发送');

            // 稍等后更新状态
            setTimeout(updateStatus, 500);
          } catch (error) {
            console.error('发送命令失败:', error);
            showStatus('发送命令失败');
          }
        }

        // 绑定按钮事件
        playBtn.addEventListener('click', () => sendCommand('toggle-play'));
        prevBtn.addEventListener('click', () => sendCommand('prev'));
        nextBtn.addEventListener('click', () => sendCommand('next'));
        favoriteBtn.addEventListener('click', () => sendCommand('toggle-favorite'));
        volumeUpBtn.addEventListener('click', () => sendCommand('volume-up'));
        volumeDownBtn.addEventListener('click', () => sendCommand('volume-down'));
        refreshBtn.addEventListener('click', updateStatus);

        // 初始加载状态
        updateStatus();

        // 每1秒更新一次状态
        setInterval(updateStatus, 1000);

        // 添加触摸反馈
        const buttons = document.querySelectorAll('.btn');
        buttons.forEach((btn) => {
          btn.addEventListener('touchstart', function () {
            this.style.transform = 'scale(0.97)';
            this.style.opacity = '0.7';
          });

          btn.addEventListener('touchend', function () {
            this.style.transform = 'scale(1)';
            this.style.opacity = '1';
          });
        });

        // 检测深色模式变化
        window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', () => {
          updateStatus();
        });
      });
    </script>
  </body>
</html>


================================================
FILE: resources/manifest.json
================================================
{
  "name": "Alger Music PWA",
  "icons": [
    {
      "src": "./icon.png",
      "type": "image/png",
      "sizes": "256x256"
    }
  ]
}


================================================
FILE: src/i18n/lang/en-US/artist.ts
================================================
export default {
  hotSongs: 'Hot Songs',
  albums: 'Albums',
  description: 'Artist Introduction'
};


================================================
FILE: src/i18n/lang/en-US/bilibili.ts
================================================
export default {
  player: {
    loading: 'Loading audio...',
    retry: 'Retry',
    playNow: 'Play Now',
    loadingTitle: 'Loading...',
    totalDuration: 'Total Duration: {duration}',
    partsList: 'Parts List ({count} episodes)',
    playStarted: 'Playback started',
    switchingPart: 'Switching to part: {part}',
    preloadingNext: 'Preloading next part: {part}',
    playingCurrent: 'Playing current selected part: {name}',
    num: 'M',
    errors: {
      invalidVideoId: 'Invalid video ID',
      loadVideoDetailFailed: 'Failed to load video details',
      loadPartInfoFailed: 'Unable to load video part information',
      loadAudioUrlFailed: 'Failed to get audio playback URL',
      videoDetailNotLoaded: 'Video details not loaded',
      missingParams: 'Missing required parameters',
      noAvailableAudioUrl: 'No available audio URL found',
      loadPartAudioFailed: 'Failed to load part audio URL',
      audioListEmpty: 'Audio list is empty, please retry',
      currentPartNotFound: 'Current part audio not found',
      audioUrlFailed: 'Failed to get audio URL',
      playFailed: 'Playback failed, please retry',
      getAudioUrlFailed: 'Failed to get audio URL, please retry',
      audioNotFound: 'Corresponding audio not found, please retry',
      preloadFailed: 'Failed to preload next part',
      switchPartFailed: 'Failed to load audio URL when switching parts'
    },
    console: {
      loadingDetail: 'Loading Bilibili video details',
      detailData: 'Bilibili video detail data',
      multipleParts: 'Video has multiple parts, total {count}',
      noPartsData: 'Video has no parts or part data is empty',
      loadingAudioSource: 'Loading audio source',
      generatedAudioList: 'Generated audio list, total {count}',
      getDashAudioUrl: 'Got dash audio URL',
      getDurlAudioUrl: 'Got durl audio URL',
      loadingPartAudio: 'Loading part audio URL: {part}, cid: {cid}',
      loadPartAudioFailed: 'Failed to load part audio URL: {part}',
      switchToPart: 'Switching to part: {part}',
      audioNotFoundInList: 'Corresponding audio item not found',
      preparingToPlay: 'Preparing to play current selected part: {name}',
      preloadingNextPart: 'Preloading next part: {part}',
      playingSelectedPart: 'Playing current selected part: {name}, audio URL: {url}',
      preloadNextFailed: 'Failed to preload next part'
    }
  }
};


================================================
FILE: src/i18n/lang/en-US/common.ts
================================================
export default {
  play: 'Play',
  next: 'Next',
  previous: 'Previous',
  volume: 'Volume',
  settings: 'Settings',
  search: 'Search',
  loading: 'Loading...',
  loadingMore: 'Loading more...',
  alipay: 'Alipay',
  wechat: 'WeChat Pay',
  on: 'On',
  off: 'Off',
  show: 'Show',
  hide: 'Hide',
  confirm: 'Confirm',
  cancel: 'Cancel',
  configure: 'Configure',
  open: 'Open',
  modify: 'Modify',
  success: 'Operation Successful',
  error: 'Operation Failed',
  warning: 'Warning',
  info: 'Info',
  save: 'Save',
  delete: 'Delete',
  refresh: 'Refresh',
  retry: 'Retry',
  reset: 'Reset',
  back: 'Back',
  copySuccess: 'Copied to clipboard',
  copyFailed: 'Copy failed',
  validation: {
    required: 'This field is required',
    invalidInput: 'Invalid input',
    selectRequired: 'Please select an option',
    numberRange: 'Please enter a number between {min} and {max}',
    ipAddress: 'Please enter a valid IP address',
    portNumber: 'Please enter a valid port number (1-65535)'
  },
  viewMore: 'View More',
  noMore: 'No more',
  selectAll: 'Select All',
  expand: 'Expand',
  collapse: 'Collapse',
  songCount: '{count} songs',
  language: 'Language',
  today: 'Today',
  yesterday: 'Yesterday',
  tray: {
    show: 'Show',
    quit: 'Quit',
    playPause: 'Play/Pause',
    prev: 'Previous',
    next: 'Next',
    pause: 'Pause',
    play: 'Play',
    favorite: 'Favorite'
  }
};


================================================
FILE: src/i18n/lang/en-US/comp.ts
================================================
export default {
  installApp: {
    description: 'Install the application for a better experience',
    noPrompt: 'Do not prompt again',
    install: 'Install now',
    cancel: 'Cancel',
    download: 'Download',
    downloadFailed: 'Download failed',
    downloadComplete: 'Download complete',
    downloadProblem: 'Download problem? Go to',
    downloadProblemLinkText: 'Download the latest version'
  },
  playlistDrawer: {
    title: 'Add to playlist',
    createPlaylist: 'Create new playlist',
    cancelCreate: 'Cancel create',
    create: 'Create',
    playlistName: 'Playlist name',
    privatePlaylist: 'Private playlist',
    publicPlaylist: 'Public playlist',
    createSuccess: 'Playlist created successfully',
    createFailed: 'Playlist creation failed',
    addSuccess: 'Song added successfully',
    addFailed: 'Song addition failed',
    private: 'Private',
    public: 'Public',
    count: 'songs',
    loginFirst: 'Please login first',
    getPlaylistFailed: 'Get playlist failed',
    inputPlaylistName: 'Please enter the playlist name'
  },
  update: {
    title: 'New version found',
    currentVersion: 'Current version',
    cancel: 'Do not update',
    prepareDownload: 'Preparing to download...',
    downloading: 'Downloading...',
    nowUpdate: 'Update now',
    downloadFailed: 'Download failed, please try again or download manually',
    startFailed: 'Start download failed, please try again or download manually',
    noDownloadUrl:
      'No suitable installation package found for the current system, please download manually',
    installConfirmTitle: 'Install Update',
    installConfirmContent: 'Do you want to close the application and install the update?',
    manualInstallTip:
      'If the installer does not open automatically after closing the application, please find the file in your download folder and open it manually.',
    yesInstall: 'Install Now',
    noThanks: 'Later',
    fileLocation: 'File Location',
    copy: 'Copy Path',
    copySuccess: 'Path copied to clipboard',
    copyFailed: 'Copy failed',
    backgroundDownload: 'Background Download'
  },
  disclaimer: {
    title: 'Terms of Use',
    warning:
      'This application is a development test version. Functions are not yet perfect, and there may be many problems and bugs. It is for learning and exchange only.',
    item1:
      'This application is for personal learning, research and technical exchange only. Please do not use it for any commercial purposes.',
    item2:
      'Please delete it within 24 hours after downloading. If you need to use it for a long time, please support the genuine music service.',
    item3:
      'By using this application, you understand and assume the relevant risks. The developer is not responsible for any loss.',
    agree: 'I have read and agree',
    disagree: 'Disagree and Exit'
  },
  donate: {
    title: 'Support Developer',
    subtitle: 'Your support is my motivation',
    tip: 'Donation is completely voluntary. All functions can be used normally without donation. Thank you for your understanding and support!',
    wechat: 'WeChat',
    alipay: 'Alipay',
    wechatQR: 'WeChat QR Code',
    alipayQR: 'Alipay QR Code',
    scanTip: 'Please use your phone to scan the QR code above to donate',
    enterApp: 'Enter App',
    noForce: 'No forced donation, click to enter'
  },
  coffee: {
    title: 'Buy me a coffee',
    alipay: 'Alipay',
    wechat: 'Wechat',
    alipayQR: 'Alipay QR code',
    wechatQR: 'Wechat QR code',
    coffeeDesc: 'A cup of coffee, a support',
    coffeeDescLinkText: 'View more',
    groupText: 'Wechat Public Account: AlgerMusic',
    messages: {
      copySuccess: 'Copied to clipboard'
    },
    donateList: 'Buy me a coffee'
  },
  playlistType: {
    title: 'Playlist Category',
    showAll: 'Show all',
    hide: 'Hide some'
  },
  recommendAlbum: {
    title: 'Latest Album'
  },
  recommendSinger: {
    title: 'Daily Recommendation',
    songlist: 'Daily Recommendation List'
  },
  recommendSonglist: {
    title: 'Weekly Hot Music'
  },
  searchBar: {
    login: 'Login',
    toLogin: 'To Login',
    logout: 'Logout',
    set: 'Settings',
    theme: 'Theme',
    restart: 'Restart',
    refresh: 'Refresh',
    currentVersion: 'Current Version',
    searchPlaceholder: 'Search for something...',
    zoom: 'Zoom',
    zoom100: 'Zoom 100%',
    resetZoom: 'Reset Zoom',
    zoomDefault: 'Default Zoom'
  },
  titleBar: {
    closeTitle: 'Choose how to close',
    minimizeToTray: 'Minimize to Tray',
    exitApp: 'Exit App',
    rememberChoice: 'Remember my choice',
    closeApp: 'Close App'
  },
  userPlayList: {
    title: "{name}'s Playlist"
  },
  musicList: {
    searchSongs: 'Search Songs',
    noSearchResults: 'No search results',
    switchToNormal: 'Switch to normal layout',
    switchToCompact: 'Switch to compact layout',
    playAll: 'Play All',
    collect: 'Collect',
    collectSuccess: 'Collect Success',
    cancelCollectSuccess: 'Cancel Collect Success',
    cancelCollect: 'Cancel Collect',
    addToPlaylist: 'Add to Playlist',
    addToPlaylistSuccess: 'Add to Playlist Success',
    operationFailed: 'Operation Failed',
    songsAlreadyInPlaylist: 'Songs already in playlist',
    historyRecommend: 'Daily History',
    fetchDatesFailed: 'Failed to fetch dates',
    fetchSongsFailed: 'Failed to fetch songs',
    noSongs: 'No songs'
  },
  playlist: {
    import: {
      button: 'Import Playlist',
      title: 'Import Playlist',
      description: 'Import playlists via metadata, text, or links',
      linkTab: 'Import by Link',
      textTab: 'Import by Text',
      localTab: 'Import by Metadata',
      linkPlaceholder: 'Enter playlist links, one per line',
      textPlaceholder: 'Enter song information in format: Song Name Artist Name',
      localPlaceholder: 'Enter song metadata in JSON format',
      linkTips: 'Supported link sources:',
      linkTip1: 'Copy links after sharing playlists to WeChat/Weibo/QQ',
      linkTip2: 'Directly copy playlist/profile links',
      linkTip3: 'Directly copy article links',
      textTips: 'Enter song information, one song per line',
      textFormat: 'Format: Song Name Artist Name',
      localTips: 'Add song metadata',
      localFormat: 'Format example:',
      songNamePlaceholder: 'Song Name',
      artistNamePlaceholder: 'Artist Name',
      albumNamePlaceholder: 'Album Name',
      addSongButton: 'Add Song',
      addLinkButton: 'Add Link',
      importToStarPlaylist: 'Import to My Favorite Music',
      playlistNamePlaceholder: 'Enter playlist name',
      importButton: 'Start Import',
      emptyLinkWarning: 'Please enter playlist links',
      emptyTextWarning: 'Please enter song information',
      emptyLocalWarning: 'Please enter song metadata',
      invalidJsonFormat: 'Invalid JSON format',
      importSuccess: 'Import task created successfully',
      importFailed: 'Import failed',
      importStatus: 'Import Status',
      refresh: 'Refresh',
      taskId: 'Task ID',
      status: 'Status',
      successCount: 'Success Count',
      failReason: 'Failure Reason',
      unknownError: 'Unknown error',
      statusPending: 'Pending',
      statusProcessing: 'Processing',
      statusSuccess: 'Success',
      statusFailed: 'Failed',
      statusUnknown: 'Unknown',
      taskList: 'Task List',
      taskListTitle: 'Import Task List',
      action: 'Action',
      select: 'Select',
      fetchTaskListFailed: 'Failed to fetch task list',
      noTasks: 'No import tasks',
      clearTasks: 'Clear Tasks',
      clearTasksConfirmTitle: 'Confirm Clear',
      clearTasksConfirmContent:
        'Are you sure you want to clear all import task records? This action cannot be undone.',
      confirm: 'Confirm',
      cancel: 'Cancel',
      clearTasksSuccess: 'Task list cleared',
      clearTasksFailed: 'Failed to clear task list'
    }
  },
  settings: 'Settings',
  user: 'User',
  toplist: 'Toplist',
  history: 'History',
  list: 'Playlist',
  mv: 'MV',
  home: 'Home',
  search: 'Search'
};


================================================
FILE: src/i18n/lang/en-US/donation.ts
================================================
export default {
  description:
    'Your donation will be used to support development and maintenance work, including but not limited to server maintenance, domain name renewal, etc.',
  message: 'You can leave your email or github name when leaving a message.',
  refresh: 'Refresh List',
  toDonateList: 'Buy me a coffee',
  title: 'Donation List',
  noMessage: 'No Message'
};


================================================
FILE: src/i18n/lang/en-US/download.ts
================================================
export default {
  title: 'Download Manager',
  localMusic: 'Local Music',
  count: '{count} songs in total',
  clearAll: 'Clear All',
  settings: 'Settings',
  tabs: {
    downloading: 'Downloading',
    downloaded: 'Downloaded'
  },
  empty: {
    noTasks: 'No download tasks',
    noDownloaded: 'No downloaded songs',
    noDownloadedHint: 'Download your favorite songs to listen offline'
  },
  progress: {
    total: 'Total Progress: {progress}%'
  },
  items: 'items',
  status: {
    downloading: 'Downloading',
    completed: 'Completed',
    failed: 'Failed',
    unknown: 'Unknown'
  },
  artist: {
    unknown: 'Unknown Artist'
  },
  delete: {
    title: 'Delete Confirmation',
    message: 'Are you sure you want to delete "{filename}"? This action cannot be undone.',
    confirm: 'Delete',
    cancel: 'Cancel',
    success: 'Successfully deleted',
    failed: 'Failed to delete',
    fileNotFound: 'File not found or moved, removed from records',
    recordRemoved: 'Failed to delete file, but removed from records'
  },
  clear: {
    title: 'Clear Download Records',
    message:
      'Are you sure you want to clear all download records? This will not delete the actual music files, but will clear all records.',
    confirm: 'Clear',
    cancel: 'Cancel',
    success: 'Download records cleared'
  },
  message: {
    downloadComplete: '{filename} download completed',
    downloadFailed: '{filename} download failed: {error}',
    alreadyDownloading: '{filename} is already downloading'
  },
  loading: 'Loading...',
  playStarted: 'Play started: {name}',
  playFailed: 'Play failed: {name}',
  path: {
    copied: 'Path copied to clipboard',
    copyFailed: 'Failed to copy path'
  },
  settingsPanel: {
    title: 'Download Settings',
    path: 'Download Location',
    pathDesc: 'Set where your music files will be saved',
    pathPlaceholder: 'Please select download path',
    noPathSelected: 'Please select download path first',
    select: 'Select Folder',
    open: 'Open Folder',
    fileFormat: 'Filename Format',
    fileFormatDesc: 'Set how downloaded music files will be named',
    customFormat: 'Custom Format',
    separator: 'Separator',
    separators: {
      dash: 'Space-dash-space',
      underscore: 'Underscore',
      space: 'Space'
    },
    dragToArrange: 'Sort or use arrow buttons to arrange:',
    formatVariables: 'Available variables',
    preview: 'Preview:',
    saveSuccess: 'Download settings saved',
    presets: {
      songArtist: 'Song - Artist',
      artistSong: 'Artist - Song',
      songOnly: 'Song only'
    },
    components: {
      songName: 'Song name',
      artistName: 'Artist name',
      albumName: 'Album name'
    }
  }
};


================================================
FILE: src/i18n/lang/en-US/favorite.ts
================================================
export default {
  title: 'Favorites',
  count: 'Total {count}',
  batchDownload: 'Batch Download',
  selectAll: 'All',
  download: 'Download ({count})',
  cancel: 'Cancel',
  emptyTip: 'No favorite songs yet',
  viewMore: 'View More',
  noMore: 'No more',
  downloadSuccess: 'Download completed',
  downloadFailed: 'Download failed',
  downloading: 'Downloading, please wait...',
  selectSongsFirst: 'Please select songs to download first',
  descending: 'Descending',
  ascending: 'Ascending'
};


================================================
FILE: src/i18n/lang/en-US/history.ts
================================================
export default {
  title: 'Play History',
  heatmapTitle: 'Heatmap',
  playCount: '{count}',
  getHistoryFailed: 'Failed to get play history',
  categoryTabs: {
    songs: 'Songs',
    playlists: 'Playlists',
    albums: 'Albums'
  },
  tabs: {
    all: 'All Records',
    local: 'Local Records',
    cloud: 'Cloud Records'
  },
  getCloudRecordFailed: 'Failed to get cloud records',
  needLogin: 'Please login with cookie to view cloud records',
  merging: 'Merging records...',
  noDescription: 'No description',
  noData: 'No records',
  newKey: 'New translation',
  heatmap: {
    title: 'Play Heatmap',
    loading: 'Loading data...',
    unit: 'plays',
    footerText: 'Hover to view details',
    playCount: 'Played {count} times',
    topSongs: 'Top songs of the day',
    times: 'times',
    totalPlays: 'Total Plays',
    activeDays: 'Active Days',
    noData: 'No play records',
    colorTheme: 'Color Theme',
    colors: {
      green: 'Green',
      blue: 'Blue',
      orange: 'Orange',
      purple: 'Purple',
      red: 'Red'
    },
    mostPlayedSong: 'Most Played Song',
    mostActiveDay: 'Most Active Day',
    latestNightSong: 'Latest Night Song'
  }
};


================================================
FILE: src/i18n/lang/en-US/login.ts
================================================
export default {
  title: {
    qr: 'QR Code Login',
    phone: 'Phone Login',
    cookie: 'Cookie Login',
    uid: 'UID Login'
  },
  qrTip: 'Scan with NetEase Cloud Music APP',
  phoneTip: 'Login with NetEase Cloud account',
  tokenTip: 'Enter a valid NetEase Cloud Music Cookie to login',
  uidTip: 'Enter User ID for quick login',
  placeholder: {
    phone: 'Phone Number',
    password: 'Password',
    cookie: 'Please enter NetEase Cloud Music Cookie (token)',
    uid: 'Please enter User ID (UID)'
  },
  button: {
    login: 'Login',
    switchToQr: 'QR Code Login',
    switchToPhone: 'Phone Login',
    switchToToken: 'Use Cookie Login',
    switchToUid: 'UID Login',
    backToQr: 'Back to QR Code Login',
    cookieLogin: 'Cookie Login',
    autoGetCookie: 'Auto Get Cookie',
    refresh: 'Click to Refresh',
    refreshing: 'Refreshing...',
    refreshQr: 'Refresh QR Code'
  },
  message: {
    loginSuccess: 'Login successful',
    loginFailed: 'Login failed',
    tokenLoginSuccess: 'Cookie login successful',
    uidLoginSuccess: 'UID login successful',
    loadError: 'Error loading login information',
    qrCheckError: 'Error checking QR code status',
    tokenRequired: 'Please enter Cookie',
    tokenInvalid: 'Invalid Cookie, please check and try again',
    uidRequired: 'Please enter User ID',
    uidInvalid: 'Invalid User ID or user does not exist',
    uidLoginFailed: 'UID login failed, please check if User ID is correct',
    phoneRequired: 'Please enter phone number',
    passwordRequired: 'Please enter password',
    phoneLoginFailed: 'Phone login failed, please check if phone number and password are correct',
    autoGetCookieSuccess: 'Auto get Cookie successful',
    autoGetCookieFailed: 'Auto get Cookie failed',
    autoGetCookieTip:
      'Will open NetEase Cloud Music login page, please complete login and close the window',
    qrCheckFailed: 'Failed to check QR code status, please refresh and try again',
    qrLoading: 'Loading QR code...',
    qrExpired: 'QR code has expired, please click to refresh',
    qrExpiredShort: 'QR code expired',
    qrExpiredWarning: 'QR code has expired, please click to refresh for a new one',
    qrScanned: 'QR code scanned, please confirm login on your phone',
    qrScannedShort: 'Scanned',
    qrScannedInfo: 'QR code scanned, please confirm login on your phone',
    qrConfirmed: 'Login successful, redirecting...',
    qrGenerating: 'Generating QR code...'
  },
  qrTitle: 'NetEase Cloud Music QR Code Login',
  uidWarning:
    'Note: UID login is only for viewing user public information and cannot access features that require login permissions.'
};


================================================
FILE: src/i18n/lang/en-US/player.ts
================================================
export default {
  nowPlaying: 'Now Playing',
  playlist: 'Playlist',
  lyrics: 'Lyrics',
  previous: 'Previous',
  play: 'Play',
  pause: 'Pause',
  next: 'Next',
  volumeUp: 'Volume Up',
  volumeDown: 'Volume Down',
  mute: 'Mute',
  unmute: 'Unmute',
  songNum: 'Song Number: {num}',
  addCorrection: 'Add {num} seconds',
  subtractCorrection: 'Subtract {num} seconds',
  playFailed: 'Play Failed, Play Next Song',
  parseFailedPlayNext: 'Song parsing failed, playing next',
  consecutiveFailsError:
    'Playback error, possibly due to network issues or invalid source. Please switch playlist or try again later',
  playMode: {
    sequence: 'Sequence',
    loop: 'Loop',
    random: 'Random'
  },
  fullscreen: {
    enter: 'Enter Fullscreen',
    exit: 'Exit Fullscreen'
  },
  close: 'Close',
  modeHint: {
    single: 'Single',
    list: 'Next'
  },
  lrc: {
    noLrc: 'No lyrics, please enjoy',
    noAutoScroll: 'This lyrics does not support auto-scroll'
  },
  reparse: {
    title: 'Select Music Source',
    desc: 'Click a source to directly reparse the current song. This source will be used next time this song plays.',
    success: 'Reparse successful',
    failed: 'Reparse failed',
    warning: 'Please select a music source',
    bilibiliNotSupported: 'Bilibili videos do not support reparsing',
    processing: 'Processing...',
    clear: 'Clear Custom Source',
    customApiFailed: 'Custom API parsing failed, trying built-in sources...',
    customApiError: 'Custom API request error, trying built-in sources...'
  },
  playBar: {
    expand: 'Expand Lyrics',
    collapse: 'Collapse Lyrics',
    like: 'Like',
    lyric: 'Lyric',
    noSongPlaying: 'No song playing',
    eq: 'Equalizer',
    playList: 'Play List',
    reparse: 'Reparse',
    miniPlayBar: 'Mini Play Bar',
    playMode: {
      sequence: 'Sequence',
      loop: 'Loop',
      random: 'Random'
    },
    play: 'Play',
    pause: 'Pause',
    prev: 'Previous',
    next: 'Next',
    volume: 'Volume',
    favorite: 'Favorite {name}',
    unFavorite: 'Unfavorite {name}',
    playbackSpeed: 'Playback Speed',
    advancedControls: 'Advanced Controls',
    intelligenceMode: {
      title: 'Intelligence Mode',
      needCookieLogin: 'Please login with Cookie method to use Intelligence Mode',
      noFavoritePlaylist: 'Favorite playlist not found',
      noLikedSongs: 'You have no liked songs yet',
      loading: 'Loading Intelligence Mode',
      success: 'Loaded {count} songs',
      failed: 'Failed to get Intelligence Mode list',
      error: 'Intelligence Mode error'
    }
  },
  eq: {
    title: 'Equalizer',
    reset: 'Reset',
    on: 'On',
    off: 'Off',
    bass: 'Bass',
    midrange: 'Midrange',
    treble: 'Treble',
    presets: {
      flat: 'Flat',
      pop: 'Pop',
      rock: 'Rock',
      classical: 'Classical',
      jazz: 'Jazz',
      electronic: 'Electronic',
      hiphop: 'Hip-Hop',
      rb: 'R&B',
      metal: 'Metal',
      vocal: 'Vocal',
      dance: 'Dance',
      acoustic: 'Acoustic',
      custom: 'Custom'
    }
  },
  // Playback settings
  settings: {
    title: 'Playback Settings',
    playbackSpeed: 'Playback Speed'
  },
  // Sleep timer related
  sleepTimer: {
    title: 'Sleep Timer',
    cancel: 'Cancel Timer',
    timeMode: 'By Time',
    songsMode: 'By Songs',
    playlistEnd: 'After Playlist',
    afterPlaylist: 'After Playlist Ends',
    activeUntilEnd: 'Active until end of playlist',
    minutes: 'min',
    hours: 'hr',
    songs: 'songs',
    set: 'Set',
    timerSetSuccess: 'Timer set for {minutes} minutes',
    songsSetSuccess: 'Timer set for {songs} songs',
    playlistEndSetSuccess: 'Timer set to end after playlist',
    timerCancelled: 'Sleep timer cancelled',
    timerEnded: 'Sleep timer ended',
    playbackStopped: 'Music playback stopped',
    minutesRemaining: '{minutes} min remaining',
    songsRemaining: '{count} songs remaining',
    activeTime: 'Timer Active',
    activeSongs: 'Counting Songs',
    activeEnd: 'End After List'
  },
  playList: {
    clearAll: 'Clear Playlist',
    alreadyEmpty: 'Playlist is already empty',
    cleared: 'Playlist cleared',
    empty: 'Playlist is empty',
    clearConfirmTitle: 'Clear Playlist',
    clearConfirmContent:
      'This will clear all songs in the playlist and stop the current playback. Continue?'
  }
};


================================================
FILE: src/i18n/lang/en-US/search.ts
================================================
export default {
  title: {
    hotSearch: 'Hot Search',
    searchList: 'Search Results',
    searchHistory: 'Search History'
  },
  button: {
    clear: 'Clear',
    back: 'Back',
    playAll: 'Play All'
  },
  loading: {
    more: 'Loading...',
    failed: 'Search failed',
    searching: 'Searching...'
  },
  noMore: 'No more results',
  error: {
    searchFailed: 'Search failed'
  },
  search: {
    single: 'Single',
    album: 'Album',
    playlist: 'Playlist',
    mv: 'MV',
    bilibili: 'Bilibili'
  },
  history: 'Search History',
  hot: 'Hot Searches',
  suggestions: 'Search Suggestions'
};


================================================
FILE: src/i18n/lang/en-US/settings.ts
================================================
export default {
  theme: 'Theme',
  language: 'Language',
  regard: 'About',
  logout: 'Logout',
  sections: {
    basic: 'Basic Settings',
    playback: 'Playback Settings',
    application: 'Application Settings',
    network: 'Network Settings',
    system: 'System Management',
    donation: 'Donation',
    about: 'About'
  },
  basic: {
    themeMode: 'Theme Mode',
    themeModeDesc: 'Switch between light/dark theme',
    autoTheme: 'Follow System',
    manualTheme: 'Manual Switch',
    language: 'Language Settings',
    languageDesc: 'Change display language',
    tokenManagement: 'Cookie Management',
    tokenManagementDesc: 'Manage NetEase Cloud Music login Cookie',
    tokenStatus: 'Current Cookie Status',
    tokenSet: 'Set',
    tokenNotSet: 'Not Set',
    setToken: 'Set Cookie',
    modifyToken: 'Modify Cookie',
    clearToken: 'Clear Cookie',
    font: 'Font Settings',
    fontDesc: 'Select fonts, prioritize fonts in order',
    fontScope: {
      global: 'Global',
      lyric: 'Lyrics Only'
    },
    animation: 'Animation Speed',
    animationDesc: 'Enable/disable animations',
    animationSpeed: {
      slow: 'Very Slow',
      normal: 'Normal',
      fast: 'Very Fast'
    },
    fontPreview: {
      title: 'Font Preview',
      chinese: 'Chinese',
      english: 'English',
      japanese: 'Japanese',
      korean: 'Korean',
      chineseText: '静夜思 床前明月光 疑是地上霜',
      englishText: 'The quick brown fox jumps over the lazy dog',
      japaneseText: 'あいうえお かきくけこ さしすせそ',
      koreanText: '가나다라마 바사아자차 카타파하'
    },
    gpuAcceleration: 'GPU Acceleration',
    gpuAccelerationDesc:
      'Enable or disable hardware acceleration, can improve rendering performance but may increase GPU load',
    gpuAccelerationRestart:
      'Changing GPU acceleration settings requires application restart to take effect',
    gpuAccelerationChangeSuccess:
      'GPU acceleration settings updated, restart application to take effect',
    gpuAccelerationChangeError: 'Failed to update GPU acceleration settings',
    tabletMode: 'Tablet Mode',
    tabletModeDesc: 'Enabling tablet mode allows using PC-style interface on mobile devices'
  },
  playback: {
    quality: 'Audio Quality',
    qualityDesc: 'Select music playback quality (VIP)',
    qualityOptions: {
      standard: 'Standard',
      higher: 'Higher',
      exhigh: 'Extreme',
      lossless: 'Lossless',
      hires: 'Hi-Res',
      jyeffect: 'HD Surround',
      sky: 'Immersive',
      dolby: 'Dolby Atmos',
      jymaster: 'Master'
    },
    musicSources: 'Music Sources',
    musicSourcesDesc: 'Select music sources for song resolution',
    musicSourcesWarning: 'At least one music source must be selected',
    musicUnblockEnable: 'Enable Music Unblocking',
    musicUnblockEnableDesc: 'When enabled, attempts to resolve unplayable songs',
    configureMusicSources: 'Configure Sources',
    selectedMusicSources: 'Selected sources:',
    noMusicSources: 'No sources selected',
    gdmusicInfo:
      'GD Music Station intelligently resolves music from multiple platforms automatically',
    autoPlay: 'Auto Play',
    autoPlayDesc: 'Auto resume playback when reopening the app',
    showStatusBar: 'Show Status Bar',
    showStatusBarContent:
      'You can display the music control function in your mac status bar (effective after a restart)',
    fallbackParser: 'Fallback Parser (GD Music)',
    fallbackParserDesc:
      'When "GD Music" is checked and regular sources fail, this service will be used.',
    parserGD: 'GD Music (Built-in)',
    parserCustom: 'Custom API',

    // Source labels
    sourceLabels: {
      migu: 'Migu',
      kugou: 'Kugou',
      pyncmd: 'NetEase (Built-in)',
      bilibili: 'Bilibili',
      gdmusic: 'GD Music',
      custom: 'Custom API'
    },

    customApi: {
      sectionTitle: 'Custom API Settings',
      importConfig: 'Import JSON Config',
      currentSource: 'Current Source',
      notImported: 'No custom source imported yet.',
      importSuccess: 'Successfully imported source: {name}',
      importFailed: 'Import failed: {message}',
      enableHint: 'Import a JSON config file to enable',
      status: {
        imported: 'Custom Source Imported',
        notImported: 'Not Imported'
      }
    },
    lxMusic: {
      tabs: {
        sources: 'Source Selection',
        lxMusic: 'LX Music',
        customApi: 'Custom API'
      },
      scripts: {
        title: 'Imported Scripts',
        importLocal: 'Import Local',
        importOnline: 'Import Online',
        urlPlaceholder: 'Enter LX Music Script URL',
        importBtn: 'Import',
        empty: 'No imported LX Music scripts',
        notConfigured: 'Not configured (Configure in LX Music Tab)',
        importHint: 'Import compatible custom API plugins to extend sources',
        noScriptWarning: 'Please import LX Music script first',
        noSelectionWarning: 'Please select an LX Music source first',
        notFound: 'Source not found',
        switched: 'Switched to source: {name}',
        deleted: 'Deleted source: {name}',
        enterUrl: 'Please enter script URL',
        invalidUrl: 'Invalid URL format',
        invalidScript: 'Invalid LX Music script, globalThis.lx code not found',
        nameRequired: 'Name cannot be empty',
        renameSuccess: 'Rename successful'
      }
    }
  },
  application: {
    closeAction: 'Close Action',
    closeActionDesc: 'Choose action when closing window',
    closeOptions: {
      ask: 'Ask Every Time',
      minimize: 'Minimize to Tray',
      close: 'Exit Directly'
    },
    shortcut: 'Shortcut Settings',
    shortcutDesc: 'Customize global shortcuts',
    download: 'Download Management',
    downloadDesc: 'Always show download list button',
    unlimitedDownload: 'Unlimited Download',
    unlimitedDownloadDesc: 'Enable unlimited download mode for music , default limit 300 songs',
    downloadPath: 'Download Directory',
    downloadPathDesc: 'Choose download location for music files',
    remoteControl: 'Remote Control',
    remoteControlDesc: 'Set remote control function'
  },
  network: {
    apiPort: 'Music API Port',
    apiPortDesc: 'Restart required after modification',
    proxy: 'Proxy Settings',
    proxyDesc: 'Enable proxy when unable to access music',
    proxyHost: 'Proxy Host',
    proxyHostPlaceholder: 'Enter proxy host',
    proxyPort: 'Proxy Port',
    proxyPortPlaceholder: 'Enter proxy port',
    realIP: 'RealIP Settings',
    realIPDesc: 'Use realIP parameter with mainland China IP to resolve access restrictions abroad',
    messages: {
      proxySuccess: 'Proxy settings saved, restart required to take effect',
      proxyError: 'Please check your input',
      realIPSuccess: 'RealIP settings saved',
      realIPError: 'Please enter a valid IP address'
    }
  },
  system: {
    cache: 'Cache Management',
    cacheDesc: 'Clear cache',
    cacheClearTitle: 'Select cache types to clear:',
    cacheTypes: {
      history: {
        label: 'Play History',
        description: 'Clear played song records'
      },
      favorite: {
        label: 'Favorites',
        description: 'Clear local favorite songs (cloud favorites not affected)'
      },
      user: {
        label: 'User Data',
        description: 'Clear login info and user-related data'
      },
      settings: {
        label: 'App Settings',
        description: 'Clear all custom app settings'
      },
      downloads: {
        label: 'Download History',
        description: 'Clear download history (downloaded files not affected)'
      },
      resources: {
        label: 'Music Resources',
        description: 'Clear cached music files, lyrics and other resources'
      },
      lyrics: {
        label: 'Lyrics Resources',
        description: 'Clear cached lyrics resources'
      }
    },
    restart: 'Restart',
    restartDesc: 'Restart application',
    messages: {
      clearSuccess: 'Cache cleared successfully, some settings will take effect after restart'
    }
  },
  about: {
    version: 'Version',
    checkUpdate: 'Check for Updates',
    checking: 'Checking...',
    latest: 'Already latest version',
    hasUpdate: 'New version available',
    gotoUpdate: 'Go to Update',
    gotoGithub: 'Go to Github',
    author: 'Author',
    authorDesc: 'algerkong Give a star🌟',
    messages: {
      checkError: 'Failed to check for updates, please try again later'
    }
  },
  validation: {
    selectProxyProtocol: 'Please select proxy protocol',
    proxyHost: 'Please enter proxy host',
    portNumber: 'Please enter a valid port number (1-65535)'
  },
  lyricSettings: {
    title: 'Lyric Settings',
    tabs: {
      display: 'Display',
      interface: 'Interface',
      typography: 'Typography',
      background: 'Background',
      mobile: 'Mobile'
    },
    pureMode: 'Pure Mode',
    hideCover: 'Hide Cover',
    centerDisplay: 'Center Display',
    showTranslation: 'Show Translation',
    hideLyrics: 'Hide Lyrics',
    hidePlayBar: 'Hide Play Bar',
    hideMiniPlayBar: 'Hide Mini Play Bar',
    showMiniPlayBar: 'Show Mini Play Bar',
    backgroundTheme: 'Background Theme',
    themeOptions: {
      default: 'Default',
      light: 'Light',
      dark: 'Dark'
    },
    fontSize: 'Font Size',
    fontSizeMarks: {
      small: 'Small',
      medium: 'Medium',
      large: 'Large'
    },
    fontWeight: 'Font Weight',
    fontWeightMarks: {
      thin: 'Thin',
      normal: 'Normal',
      bold: 'Bold'
    },
    letterSpacing: 'Letter Spacing',
    letterSpacingMarks: {
      compact: 'Compact',
      default: 'Default',
      loose: 'Loose'
    },
    lineHeight: 'Line Height',
    lineHeightMarks: {
      compact: 'Compact',
      default: 'Default',
      loose: 'Loose'
    },
    contentWidth: 'Content Width',
    mobileLayout: 'Mobile Layout',
    layoutOptions: {
      default: 'Default',
      ios: 'iOS Style',
      android: 'Android Style'
    },
    mobileCoverStyle: 'Cover Style',
    coverOptions: {
      record: 'Record',
      square: 'Square',
      full: 'Full Screen'
    },
    lyricLines: 'Lyric Lines',
    mobileUnavailable: 'This setting is only available on mobile devices',
    // Background settings
    background: {
      useCustomBackground: 'Use Custom Background',
      backgroundMode: 'Background Mode',
      modeOptions: {
        solid: 'Solid',
        gradient: 'Gradient',
        image: 'Image',
        css: 'CSS'
      },
      solidColor: 'Select Color',
      presetColors: 'Preset Colors',
      customColor: 'Custom Color',
      gradientEditor: 'Gradient Editor',
      gradientColors: 'Gradient Colors',
      gradientDirection: 'Gradient Direction',
      directionOptions: {
        toBottom: 'Top to Bottom',
        toRight: 'Left to Right',
        toBottomRight: 'Top Left to Bottom Right',
        angle45: '45 Degrees',
        toTop: 'Bottom to Top',
        toLeft: 'Right to Left'
      },
      addColor: 'Add Color',
      removeColor: 'Remove Color',
      imageUpload: 'Upload Image',
      imagePreview: 'Image Preview',
      clearImage: 'Clear Image',
      imageBlur: 'Blur',
      imageBrightness: 'Brightness',
      customCss: 'Custom CSS Style',
      customCssPlaceholder: 'Enter CSS style, e.g.: background: linear-gradient(...)',
      customCssHelp: 'Supports any CSS background property',
      reset: 'Reset to Default',
      fileSizeLimit: 'Image size limit: 20MB',
      invalidImageFormat: 'Invalid image format',
      imageTooLarge: 'Image too large, please select an image smaller than 20MB'
    }
  },
  translationEngine: 'Lyric Translation Engine',
  translationEngineOptions: {
    none: 'Off',
    opencc: 'OpenCC Traditionalize'
  },
  themeColor: {
    title: 'Lyric Theme Color',
    presetColors: 'Preset Colors',
    customColor: 'Custom Color',
    preview: 'Preview',
    previewText: 'Lyric Effect',
    colorNames: {
      'spotify-green': 'Spotify Green',
      'apple-blue': 'Apple Blue',
      'youtube-red': 'YouTube Red',
      orange: 'Vibrant Orange',
      purple: 'Mystic Purple',
      pink: 'Cherry Pink'
    },
    tooltips: {
      openColorPicker: 'Open Color Picker',
      closeColorPicker: 'Close Color Picker'
    },
    placeholder: '#1db954'
  },
  shortcutSettings: {
    title: 'Shortcut Settings',
    shortcut: 'Shortcut',
    shortcutDesc: 'Customize global shortcuts',
    shortcutConflict: 'Shortcut Conflict',
    inputPlaceholder: 'Click to input shortcut',
    resetShortcuts: 'Reset',
    disableAll: 'Disable All',
    enableAll: 'Enable All',
    togglePlay: 'Play/Pause',
    prevPlay: 'Previous',
    nextPlay: 'Next',
    volumeUp: 'Volume Up',
    volumeDown: 'Volume Down',
    toggleFavorite: 'Favorite/Unfavorite',
    toggleWindow: 'Show/Hide Window',
    scopeGlobal: 'Global',
    scopeApp: 'App Only',
    enabled: 'Enabled',
    disabled: 'Disabled',
    messages: {
      resetSuccess: 'Shortcuts reset successfully, please save',
      conflict: 'Shortcut conflict, please reset',
      saveSuccess: 'Shortcuts saved successfully',
      saveError: 'Failed to save shortcuts',
      cancelEdit: 'Edit cancelled',
      disableAll: 'All shortcuts disabled, please save to apply',
      enableAll: 'All shortcuts enabled, please save to apply'
    }
  },
  remoteControl: {
    title: 'Remote Control',
    enable: 'Enable Remote Control',
    port: 'Port',
    allowedIps: 'Allowed IPs',
    addIp: 'Add IP',
    emptyListHint: 'Empty list means allow all IPs',
    saveSuccess: 'Remote control settings saved',
    accessInfo: 'Remote control access address:'
  },
  cookie: {
    title: 'Cookie Settings',
    description: 'Please enter NetEase Cloud Music Cookie:',
    placeholder: 'Please paste the complete Cookie...',
    help: {
      format: 'Cookie usually starts with "MUSIC_U="',
      source: 'Can be obtained from browser developer tools network requests',
      storage: 'Cookie will be automatically saved to local storage after setting'
    },
    action: {
      save: 'Save Cookie',
      paste: 'Paste',
      clear: 'Clear'
    },
    validation: {
      required: 'Please enter Cookie',
      format: 'Cookie format may be incorrect, please check if it contains MUSIC_U'
    },
    message: {
      saveSuccess: 'Cookie saved successfully',
      saveError: 'Failed to save Cookie',
      pasteSuccess: 'Pasted successfully',
      pasteError: 'Paste failed, please copy manually'
    },
    info: {
      length: 'Current length: {length} characters'
    }
  }
};


================================================
FILE: src/i18n/lang/en-US/songItem.ts
================================================
export default {
  menu: {
    play: 'Play',
    playNext: 'Play Next',
    download: 'Download',
    addToPlaylist: 'Add to Playlist',
    favorite: 'Like',
    unfavorite: 'Unlike',
    removeFromPlaylist: 'Remove from Playlist',
    dislike: 'Dislike',
    undislike: 'Undislike'
  },
  message: {
    downloading: 'Downloading, please wait...',
    downloadFailed: 'Download failed',
    downloadQueued: 'Added to download queue',
    addedToNextPlay: 'Added to play next',
    getUrlFailed: 'Failed to get music download URL, please check if logged in'
  },
  dialog: {
    dislike: {
      title: 'Dislike',
      content: 'Are you sure you want to dislike this song?',
      positiveText: 'Dislike',
      negativeText: 'Cancel'
    }
  }
};


================================================
FILE: src/i18n/lang/en-US/user.ts
================================================
export default {
  profile: {
    followers: 'Followers',
    following: 'Following',
    level: 'Level'
  },
  playlist: {
    created: 'Created Playlists',
    mine: 'Mine',
    trackCount: '{count} tracks',
    playCount: 'Played {count} times'
  },
  tabs: {
    created: 'Created',
    favorite: 'Favorite',
    album: 'Album'
  },
  ranking: {
    title: 'Listening History',
    playCount: '{count} times'
  },
  follow: {
    title: 'Follow List',
    viewPlaylist: 'View Playlist',
    noFollowings: 'No Followings',
    loadMore: 'Load More',
    noSignature: 'This guy is lazy, nothing left',
    userFollowsTitle: "'s Followings",
    myFollowsTitle: 'My Followings'
  },
  follower: {
    title: 'Follower List',
    noFollowers: 'No Followers',
    loadMore: 'Load More',
    userFollowersTitle: "'s Followers",
    myFollowersTitle: 'My Followers'
  },
  detail: {
    playlists: 'Playlists',
    records: 'Listening History',
    noPlaylists: 'No Playlists',
    noRecords: 'No Listening History',
    artist: 'Artist',
    noSignature: 'This guy is lazy, nothing left',
    invalidUserId: 'Invalid User ID',
    noRecordPermission: "{name} doesn't let you see your listening history"
  },
  message: {
    loadFailed: 'Failed to load user page',
    deleteSuccess: 'Successfully deleted',
    deleteFailed: 'Failed to delete'
  }
};


================================================
FILE: src/i18n/lang/ja-JP/artist.ts
================================================
export default {
  hotSongs: '人気楽曲',
  albums: 'アルバム',
  description: 'アーティスト紹介'
};


================================================
FILE: src/i18n/lang/ja-JP/bilibili.ts
================================================
export default {
  player: {
    loading: 'オーディオ読み込み中...',
    retry: '再試行',
    playNow: '今すぐ再生',
    loadingTitle: '読み込み中...',
    totalDuration: '総再生時間: {duration}',
    partsList: 'パートリスト ({count}話)',
    playStarted: '再生を開始しました',
    switchingPart: 'パートを切り替え中: {part}',
    preloadingNext: '次のパートをプリロード中: {part}',
    playingCurrent: '現在選択されたパートを再生中: {name}',
    num: '万',
    errors: {
      invalidVideoId: '無効な動画ID',
      loadVideoDetailFailed: '動画詳細の取得に失敗しました',
      loadPartInfoFailed: '動画パート情報の読み込みができません',
      loadAudioUrlFailed: 'オーディオ再生URLの取得に失敗しました',
      videoDetailNotLoaded: '動画詳細が読み込まれていません',
      missingParams: '必要なパラメータが不足しています',
      noAvailableAudioUrl: '利用可能なオーディオURLが見つかりません',
      loadPartAudioFailed: 'パートオーディオURLの読み込みに失敗しました',
      audioListEmpty: 'オーディオリストが空です。再試行してください',
      currentPartNotFound: '現在のパートのオーディオが見つかりません',
      audioUrlFailed: 'オーディオURLの取得に失敗しました',
      playFailed: '再生に失敗しました。再試行してください',
      getAudioUrlFailed: 'オーディオURLの取得に失敗しました。再試行してください',
      audioNotFound: '対応するオーディオが見つかりません。再試行してください',
      preloadFailed: '次のパートのプリロードに失敗しました',
      switchPartFailed: 'パート切り替え時のオーディオURL読み込みに失敗しました'
    },
    console: {
      loadingDetail: 'Bilibiliビデオ詳細を読み込み中',
      detailData: 'Bilibiliビデオ詳細データ',
      multipleParts: 'ビデオに複数のパートがあります。合計{count}個',
      noPartsData: 'ビデオにパートがないか、パートデータが空です',
      loadingAudioSource: 'オーディオソースを読み込み中',
      generatedAudioList: 'オーディオリストを生成しました。合計{count}個',
      getDashAudioUrl: 'dashオーディオURLを取得しました',
      getDurlAudioUrl: 'durlオーディオURLを取得しました',
      loadingPartAudio: 'パートオーディオURLを読み込み中: {part}, cid: {cid}',
      loadPartAudioFailed: 'パートオーディオURLの読み込みに失敗: {part}',
      switchToPart: 'パートに切り替え中: {part}',
      audioNotFoundInList: '対応するオーディオアイテムが見つかりません',
      preparingToPlay: '現在選択されたパートの再生準備中: {name}',
      preloadingNextPart: '次のパートをプリロード中: {part}',
      playingSelectedPart: '現在選択されたパートを再生中: {name}、オーディオURL: {url}',
      preloadNextFailed: '次のパートのプリロードに失敗しました'
    }
  }
};


================================================
FILE: src/i18n/lang/ja-JP/common.ts
================================================
export default {
  play: '再生',
  next: '次の曲',
  previous: '前の曲',
  volume: '音量',
  settings: '設定',
  search: '検索',
  loading: '読み込み中...',
  loadingMore: 'さらに読み込み中...',
  alipay: 'Alipay',
  wechat: 'WeChat Pay',
  on: 'オン',
  off: 'オフ',
  show: '表示',
  hide: '非表示',
  confirm: '確認',
  cancel: 'キャンセル',
  configure: '設定',
  open: '開く',
  modify: '変更',
  success: '操作成功',
  error: '操作失敗',
  warning: '警告',
  info: 'お知らせ',
  save: '保存',
  delete: '削除',
  refresh: '更新',
  retry: '再試行',
  reset: 'リセット',
  back: '戻る',
  copySuccess: 'クリップボードにコピーしました',
  copyFailed: 'コピーに失敗しました',
  validation: {
    required: 'この項目は必須です',
    invalidInput: '無効な入力です',
    selectRequired: 'オプションを選択してください',
    numberRange: '{min}から{max}の間の数値を入力してください'
  },
  viewMore: 'もっと見る',
  noMore: 'これ以上ありません',
  selectAll: '全選択',
  expand: '展開',
  collapse: '折りたたみ',
  songCount: '{count}曲',
  language: '言語',
  today: '今日',
  yesterday: '昨日',
  tray: {
    show: '表示',
    quit: '終了',
    playPause: '再生/一時停止',
    prev: '前の曲',
    next: '次の曲',
    pause: '一時停止',
    play: '再生',
    favorite: 'お気に入り'
  }
};


================================================
FILE: src/i18n/lang/ja-JP/comp.ts
================================================
export default {
  installApp: {
    description: 'アプリをインストールして、より良い体験を',
    noPrompt: '今後表示しない',
    install: '今すぐインストール',
    cancel: '後でインストール',
    download: 'ダウンロード',
    downloadFailed: 'ダウンロード失敗',
    downloadComplete: 'ダウンロード完了',
    downloadProblem: 'ダウンロードに問題がありますか?',
    downloadProblemLinkText: '最新版をダウンロード'
  },
  playlistDrawer: {
    title: 'プレイリストに追加',
    createPlaylist: '新しいプレイリストを作成',
    cancelCreate: '作成をキャンセル',
    create: '作成',
    playlistName: 'プレイリスト名',
    privatePlaylist: 'プライベートプレイリスト',
    publicPlaylist: 'パブリックプレイリスト',
    createSuccess: 'プレイリストの作成に成功しました',
    createFailed: 'プレイリストの作成に失敗しました',
    addSuccess: '楽曲の追加に成功しました',
    addFailed: '楽曲の追加に失敗しました',
    private: 'プライベート',
    public: 'パブリック',
    count: '曲',
    loginFirst: 'まずログインしてください',
    getPlaylistFailed: 'プレイリストの取得に失敗しました',
    inputPlaylistName: 'プレイリスト名を入力してください'
  },
  update: {
    title: '新しいバージョンが見つかりました',
    currentVersion: '現在のバージョン',
    cancel: '後で更新',
    prepareDownload: 'ダウンロード準備中...',
    downloading: 'ダウンロード中...',
    nowUpdate: '今すぐ更新',
    downloadFailed: 'ダウンロードに失敗しました。再試行するか手動でダウンロードしてください',
    startFailed: 'ダウンロードの開始に失敗しました。再試行するか手動でダウンロードしてください',
    noDownloadUrl:
      '現在のシステムに適したインストールパッケージが見つかりません。手動でダウンロードしてください',
    installConfirmTitle: '更新をインストール',
    installConfirmContent: 'アプリを閉じて更新をインストールしますか?',
    manualInstallTip:
      'アプリを閉じた後にインストーラーが正常に起動しない場合は、ダウンロードフォルダでファイルを見つけて手動で開いてください。',
    yesInstall: '今すぐインストール',
    noThanks: '後でインストール',
    fileLocation: 'ファイルの場所',
    copy: 'パスをコピー',
    copySuccess: 'パスをクリップボードにコピーしました',
    copyFailed: 'コピーに失敗しました',
    backgroundDownload: 'バックグラウンドダウンロード'
  },
  disclaimer: {
    title: '使用上の注意',
    warning:
      'このアプリは開発テスト版であり、機能が不完全で、多くの問題やバグが存在する可能性があります。学習と交流のみを目的としています。',
    item1:
      'このアプリは個人の学習、研究、技術交流のみを目的としています。商業目的で使用しないでください。',
    item2:
      'ダウンロード後24時間以内に削除してください。長期使用を希望される場合は、正規の音楽サービスをサポートしてください。',
    item3:
      'このアプリを使用することで、関連するリスクを理解し、負担するものとします。開発者は一切の損失に対して責任を負いません。',
    agree: '以上の内容を読み、同意します',
    disagree: '同意せずに終了'
  },
  donate: {
    title: '開発者を支援',
    subtitle: '皆様のサポートが私の原動力です',
    tip: '寄付は完全に任意です。寄付しなくてもすべての機能を通常通り使用できます。ご理解とご支援に感謝します!',
    wechat: 'WeChat',
    alipay: 'Alipay',
    wechatQR: 'WeChat 受取コード',
    alipayQR: 'Alipay 受取コード',
    scanTip: 'スマートフォンのアプリで上記のQRコードをスキャンして寄付してください',
    enterApp: 'アプリに入る',
    noForce: '寄付は強制ではありません。クリックして入れます'
  },
  coffee: {
    title: 'コーヒーをおごる',
    alipay: 'Alipay',
    wechat: 'WeChat Pay',
    alipayQR: 'Alipay QRコード',
    wechatQR: 'WeChat QRコード',
    coffeeDesc: '一杯のコーヒー、一つのサポート',
    coffeeDescLinkText: 'もっと見る',
    groupText: '微信公众号:AlgerMusic',
    messages: {
      copySuccess: 'クリップボードにコピーしました'
    },
    donateList: 'コーヒーをおごる'
  },
  playlistType: {
    title: 'プレイリストカテゴリ',
    showAll: 'すべて表示',
    hide: '一部を非表示'
  },
  recommendAlbum: {
    title: '最新アルバム'
  },
  recommendSinger: {
    title: '毎日のおすすめ',
    songlist: '毎日のおすすめリスト'
  },
  recommendSonglist: {
    title: '今週の人気音楽'
  },
  searchBar: {
    login: 'ログイン',
    toLogin: 'ログインへ',
    logout: 'ログアウト',
    set: '設定',
    theme: 'テーマ',
    restart: '再起動',
    refresh: '更新',
    currentVersion: '現在のバージョン',
    searchPlaceholder: '何かを検索してみましょう...',
    zoom: 'ページズーム',
    zoom100: '標準ズーム100%',
    resetZoom: 'クリックしてズームをリセット',
    zoomDefault: '標準ズーム'
  },
  titleBar: {
    closeTitle: '閉じる方法を選択してください',
    minimizeToTray: 'トレイに最小化',
    exitApp: 'アプリを終了',
    rememberChoice: '選択を記憶する',
    closeApp: 'アプリを閉じる'
  },
  userPlayList: {
    title: '{name}のよく聞く音楽'
  },
  musicList: {
    searchSongs: '楽曲を検索',
    noSearchResults: '関連する楽曲が見つかりませんでした',
    switchToNormal: 'デフォルトレイアウトに切り替え',
    switchToCompact: 'コンパクトレイアウトに切り替え',
    playAll: 'すべて再生',
    collect: 'お気に入り',
    collectSuccess: 'お気に入りに追加しました',
    cancelCollectSuccess: 'お気に入りから削除しました',
    operationFailed: '操作に失敗しました',
    cancelCollect: 'お気に入りから削除',
    addToPlaylist: 'プレイリストに追加',
    addToPlaylistSuccess: 'プレイリストに追加しました',
    songsAlreadyInPlaylist: '楽曲は既にプレイリストに存在します',
    historyRecommend: '履歴の日次推薦',
    fetchDatesFailed: '日付リストの取得に失敗しました',
    fetchSongsFailed: '楽曲リストの取得に失敗しました',
    noSongs: '楽曲がありません'
  },
  playlist: {
    import: {
      button: 'プレイリストインポート',
      title: 'プレイリストインポート',
      description: 'メタデータ/テキスト/リンクの3つの方法でプレイリストをインポートできます',
      linkTab: 'リンクインポート',
      textTab: 'テキストインポート',
      localTab: 'メタデータインポート',
      linkPlaceholder: 'プレイリストのリンクを入力してください(1行に1つ)',
      textPlaceholder: '楽曲情報を入力してください。形式:楽曲名 アーティスト名',
      localPlaceholder: 'JSON形式の楽曲メタデータを入力してください',
      linkTips: 'サポートされているリンクソース:',
      linkTip1: 'プレイリストをWeChat/Weibo/QQでシェアした後、リンクをコピー',
      linkTip2: 'プレイリスト/個人ページのリンクを直接コピー',
      linkTip3: '記事のリンクを直接コピー',
      textTips: '楽曲情報を入力してください(1行に1曲)',
      textFormat: '形式:楽曲名 アーティスト名',
      localTips: '楽曲メタデータを追加してください',
      localFormat: '形式例:',
      songNamePlaceholder: '楽曲名',
      artistNamePlaceholder: 'アーティスト名',
      albumNamePlaceholder: 'アルバム名',
      addSongButton: '楽曲を追加',
      addLinkButton: 'リンクを追加',
      importToStarPlaylist: 'お気に入りの音楽にインポート',
      playlistNamePlaceholder: 'プレイリスト名を入力してください',
      importButton: 'インポート開始',
      emptyLinkWarning: 'プレイリストのリンクを入力してください',
      emptyTextWarning: '楽曲情報を入力してください',
      emptyLocalWarning: '楽曲メタデータを入力してください',
      invalidJsonFormat: 'JSON形式が正しくありません',
      importSuccess: 'インポートタスクの作成に成功しました',
      importFailed: 'インポートに失敗しました',
      importStatus: 'インポート状況',
      refresh: '更新',
      taskId: 'タスクID',
      status: 'ステータス',
      successCount: '成功数',
      failReason: '失敗理由',
      unknownError: '不明なエラー',
      statusPending: '処理待ち',
      statusProcessing: '処理中',
      statusSuccess: 'インポート成功',
      statusFailed: 'インポート失敗',
      statusUnknown: '不明なステータス',
      taskList: 'タスクリスト',
      taskListTitle: 'インポートタスクリスト',
      action: '操作',
      select: '選択',
      fetchTaskListFailed: 'タスクリストの取得に失敗しました',
      noTasks: 'インポートタスクがありません',
      clearTasks: 'タスクをクリア',
      clearTasksConfirmTitle: 'クリア確認',
      clearTasksConfirmContent:
        'すべてのインポートタスク記録をクリアしますか?この操作は元に戻せません。',
      confirm: '確認',
      cancel: 'キャンセル',
      clearTasksSuccess: 'タスクリストをクリアしました',
      clearTasksFailed: 'タスクリストのクリアに失敗しました'
    }
  },
  settings: '設定',
  user: 'ユーザー',
  toplist: 'ランキング',
  history: 'お気に入り履歴',
  list: 'プレイリスト',
  mv: 'MV',
  home: 'ホーム',
  search: '検索'
};


================================================
FILE: src/i18n/lang/ja-JP/donation.ts
================================================
export default {
  description:
    'あなたの寄付は開発・保守作業をサポートするために使用され、サーバー保守、ドメイン更新などが含まれます。',
  message: 'メッセージを残す際は、メールアドレスやGitHubユーザー名を記載してください。',
  refresh: 'リストを更新',
  toDonateList: 'コーヒーをおごる',
  noMessage: 'メッセージがありません',
  title: '寄付リスト'
};


================================================
FILE: src/i18n/lang/ja-JP/download.ts
================================================
export default {
  title: 'ダウンロード管理',
  localMusic: 'ローカル音楽',
  count: '合計{count}曲',
  clearAll: '記録をクリア',
  settings: '設定',
  tabs: {
    downloading: 'ダウンロード中',
    downloaded: 'ダウンロード済み'
  },
  empty: {
    noTasks: 'ダウンロードタスクがありません',
    noDownloaded: 'ダウンロード済みの楽曲がありません'
  },
  progress: {
    total: '全体の進行状況: {progress}%'
  },
  status: {
    downloading: 'ダウンロード中',
    completed: '完了',
    failed: '失敗',
    unknown: '不明'
  },
  artist: {
    unknown: '不明なアーティスト'
  },
  delete: {
    title: '削除確認',
    message: '楽曲「{filename}」を削除しますか?この操作は元に戻せません。',
    confirm: '削除確認',
    cancel: 'キャンセル',
    success: '削除成功',
    failed: '削除失敗',
    fileNotFound: 'ファイルが存在しないか移動されました。記録から削除しました',
    recordRemoved: 'ファイルの削除に失敗しましたが、記録から削除しました'
  },
  clear: {
    title: 'ダウンロード記録をクリア',
    message:
      'すべてのダウンロード記録をクリアしますか?この操作はダウンロード済みの音楽ファイルを削除しませんが、すべての記録をクリアします。',
    confirm: 'クリア確認',
    cancel: 'キャンセル',
    success: 'ダウンロード記録をクリアしました'
  },
  message: {
    downloadComplete: '{filename}のダウンロードが完了しました',
    downloadFailed: '{filename}のダウンロードに失敗しました: {error}'
  },
  loading: '読み込み中...',
  playStarted: '再生開始: {name}',
  playFailed: '再生失敗: {name}',
  path: {
    copied: 'パスをクリップボードにコピーしました',
    copyFailed: 'パスのコピーに失敗しました'
  },
  settingsPanel: {
    title: 'ダウンロード設定',
    path: 'ダウンロード場所',
    pathDesc: '音楽ファイルのダウンロード保存場所を設定',
    pathPlaceholder: 'ダウンロードパスを選択してください',
    noPathSelected: 'まずダウンロードパスを選択してください',
    select: 'フォルダを選択',
    open: 'フォルダを開く',
    fileFormat: 'ファイル名形式',
    fileFormatDesc: '音楽ダウンロード時のファイル命名形式を設定',
    customFormat: 'カスタム形式',
    separator: '区切り文字',
    separators: {
      dash: 'スペース-スペース',
      underscore: 'アンダースコア',
      space: 'スペース'
    },
    dragToArrange: 'ドラッグで並び替えまたは矢印ボタンで順序を調整:',
    formatVariables: '使用可能な変数',
    preview: 'プレビュー効果:',
    saveSuccess: 'ダウンロード設定を保存しました',
    presets: {
      songArtist: '楽曲名 - アーティスト名',
      artistSong: 'アーティスト名 - 楽曲名',
      songOnly: '楽曲名のみ'
    },
    components: {
      songName: '楽曲名',
      artistName: 'アーティスト名',
      albumName: 'アルバム名'
    }
  }
};


================================================
FILE: src/i18n/lang/ja-JP/favorite.ts
================================================
export default {
  title: 'お気に入り',
  count: '合計{count}曲',
  batchDownload: '一括ダウンロード',
  download: 'ダウンロード ({count})',
  emptyTip: 'まだお気に入りの楽曲がありません',
  downloadSuccess: 'ダウンロード完了',
  downloadFailed: 'ダウンロード失敗',
  downloading: 'ダウンロード中です。しばらくお待ちください...',
  selectSongsFirst: 'まずダウンロードする楽曲を選択してください',
  descending: '降順',
  ascending: '昇順'
};


================================================
FILE: src/i18n/lang/ja-JP/history.ts
================================================
export default {
  title: '再生履歴',
  heatmapTitle: 'ヒートマップ',
  playCount: '{count}',
  getHistoryFailed: '履歴の取得に失敗しました',
  tabs: {
    all: 'すべての記録',
    local: 'ローカル記録',
    cloud: 'クラウド記録'
  },
  categoryTabs: {
    songs: '楽曲',
    playlists: 'プレイリスト',
    albums: 'アルバム'
  },
  noDescription: '説明なし',
  noData: '記録なし',
  getCloudRecordFailed: 'クラウド記録の取得に失敗しました',
  needLogin: 'cookieを使用してログインしてクラウド記録を表示できます',
  merging: '記録を統合中...',
  heatmap: {
    title: '再生ヒートマップ',
    loading: 'データを読み込み中...',
    unit: '回再生',
    footerText: 'ホバーして詳細を表示',
    playCount: '{count} 回再生',
    topSongs: 'その日の人気曲',
    times: '回',
    totalPlays: '総再生回数',
    activeDays: 'アクティブ日数',
    noData: '再生記録がありません',
    colorTheme: 'カラーテーマ',
    colors: {
      green: 'グリーン',
      blue: 'ブルー',
      orange: 'オレンジ',
      purple: 'パープル',
      red: 'レッド'
    },
    mostPlayedSong: '最も再生された曲',
    mostActiveDay: '最もアクティブな日',
    latestNightSong: '深夜に再生した曲'
  }
};


================================================
FILE: src/i18n/lang/ja-JP/login.ts
================================================
export default {
  title: {
    qr: 'QRコードログイン',
    phone: '電話番号ログイン',
    cookie: 'Cookieログイン',
    uid: 'UIDログイン'
  },
  qrTip: 'NetEase Cloudアプリでログイン',
  phoneTip: 'NetEase Cloudアカウントでログイン',
  tokenTip: '有効なNetEase Cloud MusicのCookieを入力してログイン',
  uidTip: 'ユーザーIDを入力してクイックログイン',
  placeholder: {
    phone: '電話番号',
    password: 'パスワード',
    cookie: 'NetEase Cloud MusicのCookie(token)を入力してください',
    uid: 'ユーザーID(UID)を入力してください'
  },
  button: {
    login: 'ログイン',
    switchToQr: 'QRコードログイン',
    switchToPhone: '電話番号ログイン',
    switchToToken: 'Cookieログインを使用',
    switchToUid: 'UIDログイン',
    backToQr: 'QRコードログインに戻る',
    cookieLogin: 'Cookieログイン',
    autoGetCookie: 'Cookie自動取得',
    refresh: 'クリックしてリフレッシュ',
    refreshing: 'リフレッシュ中...',
    refreshQr: 'QRコードをリフレッシュ'
  },
  message: {
    loginSuccess: 'ログイン成功',
    tokenLoginSuccess: 'Cookieログイン成功',
    uidLoginSuccess: 'UIDログイン成功',
    loadError: 'ログイン情報の読み込み中にエラーが発生しました',
    qrCheckError: 'QRコードの状態確認中にエラーが発生しました',
    tokenRequired: 'Cookieを入力してください',
    tokenInvalid: 'Cookieが無効です。確認して再試行してください',
    uidRequired: 'ユーザーIDを入力してください',
    uidInvalid: 'ユーザーIDが無効またはユーザーが存在しません',
    uidLoginFailed: 'UIDログインに失敗しました。ユーザーIDが正しいか確認してください',
    autoGetCookieSuccess: 'Cookie自動取得成功',
    autoGetCookieFailed: 'Cookie自動取得失敗',
    autoGetCookieTip:
      'NetEase Cloud Musicのログインページを開きます。ログイン完了後、ウィンドウを閉じてください',
    loginFailed: 'ログイン失敗',
    phoneRequired: '電話番号を入力してください',
    passwordRequired: 'パスワードを入力してください',
    phoneLoginFailed:
      '電話番号でのログインに失敗しました。電話番号とパスワードが正しいか確認してください',
    qrCheckFailed: 'QRコードの状態確認に失敗しました。リフレッシュして再試行してください',
    qrLoading: 'QRコードを読み込み中...',
    qrExpired: 'QRコードの期限が切れました。クリックしてリフレッシュしてください',
    qrExpiredShort: 'QRコード期限切れ',
    qrExpiredWarning: 'QRコードの期限が切れました。クリックして新しいQRコードを取得してください',
    qrScanned: 'QRコードがスキャンされました。スマートフォンでログインを確認してください',
    qrScannedShort: 'スキャン済み',
    qrScannedInfo: 'QRコードがスキャンされました。スマートフォンでログインを確認してください',
    qrConfirmed: 'ログイン成功、リダイレクト中...',
    qrGenerating: 'QRコードを生成中...'
  },
  qrTitle: 'NetEase Cloud Music QRコードログイン',
  uidWarning:
    '注意:UIDログインはユーザーの公開情報を表示するためのみ使用でき、ログイン権限が必要な機能にはアクセスできません。'
};


================================================
FILE: src/i18n/lang/ja-JP/player.ts
================================================
export default {
  nowPlaying: '再生中',
  playlist: 'プレイリスト',
  lyrics: '歌詞',
  previous: '前へ',
  play: '再生',
  pause: '一時停止',
  next: '次へ',
  volumeUp: '音量を上げる',
  volumeDown: '音量を下げる',
  mute: 'ミュート',
  unmute: 'ミュート解除',
  songNum: '楽曲総数:{num}',
  addCorrection: '{num}秒早める',
  subtractCorrection: '{num}秒遅らせる',
  playFailed: '現在の楽曲の再生に失敗しました。次の曲を再生します',
  parseFailedPlayNext: '楽曲の解析に失敗しました。次の曲を再生します',
  consecutiveFailsError:
    '再生エラーが発生しました。ネットワークの問題または無効な音源の可能性があります。プレイリストを切り替えるか、後でもう一度お試しください',
  playMode: {
    sequence: '順次再生',
    loop: 'リピート再生',
    random: 'ランダム再生'
  },
  fullscreen: {
    enter: 'フルスクリーン',
    exit: 'フルスクリーン終了'
  },
  close: '閉じる',
  modeHint: {
    single: 'リピート再生',
    list: '自動で次の曲を再生'
  },
  lrc: {
    noLrc: '歌詞がありません。お楽しみください',
    noAutoScroll: '本歌詞は自動スクロールをサポートしていません'
  },
  reparse: {
    title: '解析音源を選択',
    desc: '音源をクリックして直接解析します。次回この楽曲を再生する際は選択した音源を使用します',
    success: '再解析成功',
    failed: '再解析失敗',
    warning: '音源を選択してください',
    bilibiliNotSupported: 'Bilibili動画は再解析をサポートしていません',
    processing: '解析中...',
    clear: 'カスタム音源をクリア',
    customApiFailed: 'カスタムAPIの解析に失敗しました。内蔵音源を試しています...',
    customApiError: 'カスタムAPIのリクエストでエラーが発生しました。内蔵音源を試しています...'
  },
  playBar: {
    expand: '歌詞を展開',
    collapse: '歌詞を折りたたみ',
    like: 'いいね',
    lyric: '歌詞',
    noSongPlaying: '再生中の楽曲がありません',
    eq: 'イコライザー',
    playList: 'プレイリスト',
    reparse: '再解析',
    playMode: {
      sequence: '順次再生',
      loop: 'ループ再生',
      random: 'ランダム再生'
    },
    play: '再生開始',
    pause: '再生一時停止',
    prev: '前の曲',
    next: '次の曲',
    volume: '音量',
    favorite: '{name}をお気に入りに追加しました',
    unFavorite: '{name}をお気に入りから削除しました',
    miniPlayBar: 'ミニ再生バー',
    playbackSpeed: '再生速度',
    advancedControls: 'その他の設定',
    intelligenceMode: {
      title: 'インテリジェンスモード',
      needCookieLogin: 'Cookie方式でログインしてからインテリジェンスモードを使用してください',
      noFavoritePlaylist: '「お気に入りの音楽」プレイリストが見つかりません',
      noLikedSongs: 'まだ「いいね」した楽曲がありません',
      loading: 'インテリジェンスモードを読み込み中',
      success: '{count} 曲を読み込みました',
      failed: 'インテリジェンスモードのリスト取得に失敗しました',
      error: 'インテリジェンスモードの再生でエラーが発生しました'
    }
  },
  eq: {
    title: 'イコライザー',
    reset: 'リセット',
    on: 'オン',
    off: 'オフ',
    bass: '低音',
    midrange: '中音',
    treble: '高音',
    presets: {
      flat: 'フラット',
      pop: 'ポップ',
      rock: 'ロック',
      classical: 'クラシック',
      jazz: 'ジャズ',
      electronic: 'エレクトロニック',
      hiphop: 'ヒップホップ',
      rb: 'R&B',
      metal: 'メタル',
      vocal: 'ボーカル',
      dance: 'ダンス',
      acoustic: 'アコースティック',
      custom: 'カスタム'
    }
  },
  // プレイヤー設定
  settings: {
    title: '再生設定',
    playbackSpeed: '再生速度'
  },
  // タイマー機能関連
  sleepTimer: {
    title: 'スリープタイマー',
    cancel: 'タイマーをキャンセル',
    timeMode: '時間で停止',
    songsMode: '楽曲数で停止',
    playlistEnd: 'プレイリスト終了後に停止',
    afterPlaylist: 'プレイリスト終了後に停止',
    activeUntilEnd: 'リスト終了まで再生',
    minutes: '分',
    hours: '時間',
    songs: '曲',
    set: '設定',
    timerSetSuccess: '{minutes}分後に停止するよう設定しました',
    songsSetSuccess: '{songs}曲再生後に停止するよう設定しました',
    playlistEndSetSuccess: 'プレイリスト終了後に停止するよう設定しました',
    timerCancelled: 'スリープタイマーをキャンセルしました',
    timerEnded: 'スリープタイマーが作動しました',
    playbackStopped: '音楽再生を停止しました',
    minutesRemaining: '残り{minutes}分',
    songsRemaining: '残り{count}曲'
  },
  playList: {
    clearAll: 'プレイリストをクリア',
    alreadyEmpty: 'プレイリストは既に空です',
    cleared: 'プレイリストをクリアしました',
    empty: 'プレイリストが空です',
    clearConfirmTitle: 'プレイリストをクリア',
    clearConfirmContent:
      'これによりプレイリスト内のすべての楽曲がクリアされ、現在の再生が停止されます。続行しますか?'
  }
};


================================================
FILE: src/i18n/lang/ja-JP/search.ts
================================================
export default {
  title: {
    hotSearch: '人気検索リスト',
    searchList: '検索リスト',
    searchHistory: '検索履歴'
  },
  button: {
    clear: 'クリア',
    back: '戻る',
    playAll: 'リストを再生'
  },
  loading: {
    more: '読み込み中...',
    failed: '検索に失敗しました',
    searching: '検索中...'
  },
  noMore: 'これ以上ありません',
  error: {
    searchFailed: '検索に失敗しました'
  },
  search: {
    single: '楽曲',
    album: 'アルバム',
    playlist: 'プレイリスト',
    mv: 'MV',
    bilibili: 'Bilibili'
  },
  history: '検索履歴',
  hot: '人気検索',
  suggestions: '検索候補'
};


================================================
FILE: src/i18n/lang/ja-JP/settings.ts
================================================
export default {
  theme: 'テーマ',
  language: '言語',
  regard: 'について',
  logout: 'ログアウト',
  sections: {
    basic: '基本設定',
    playback: '再生設定',
    application: 'アプリケーション設定',
    network: 'ネットワーク設定',
    system: 'システム管理',
    donation: '寄付サポート',
    about: 'について'
  },
  basic: {
    themeMode: 'テーマモード',
    themeModeDesc: 'ライト/ダークテーマの切り替え',
    autoTheme: 'システムに従う',
    manualTheme: '手動切り替え',
    language: '言語設定',
    languageDesc: '表示言語を切り替え',
    tokenManagement: 'Cookie管理',
    tokenManagementDesc: 'NetEase Cloud MusicログインCookieを管理',
    tokenStatus: '現在のCookieステータス',
    tokenSet: '設定済み',
    tokenNotSet: '未設定',
    setToken: 'Cookieを設定',
    modifyToken: 'Cookieを変更',
    clearToken: 'Cookieをクリア',
    font: 'フォント設定',
    fontDesc: 'フォントを選択します。前に配置されたフォントが優先されます',
    fontScope: {
      global: 'グローバル',
      lyric: '歌詞のみ'
    },
    animation: 'アニメーション速度',
    animationDesc: 'アニメーションを有効にするかどうか',
    animationSpeed: {
      slow: '非常に遅い',
      normal: '通常',
      fast: '非常に速い'
    },
    fontPreview: {
      title: 'フォントプレビュー',
      chinese: '中国語',
      english: 'English',
      japanese: '日本語',
      korean: '韓国語',
      chineseText: '静夜思 床前明月光 疑是地上霜',
      englishText: 'The quick brown fox jumps over the lazy dog',
      japaneseText: 'あいうえお かきくけこ さしすせそ',
      koreanText: '가나다라마 바사아자차 카타파하'
    },
    gpuAcceleration: 'GPUアクセラレーション',
    gpuAccelerationDesc:
      'ハードウェアアクセラレーションを有効または無効にします。レンダリングパフォーマンスを向上させますが、GPU負荷が増える可能性があります',
    gpuAccelerationRestart: 'GPUアクセラレーション設定の変更はアプリの再起動後に有効になります',
    gpuAccelerationChangeSuccess:
      'GPUアクセラレーション設定を更新しました。アプリの再起動後に有効になります',
    gpuAccelerationChangeError: 'GPUアクセラレーション設定の更新に失敗しました',
    tabletMode: 'タブレットモード',
    tabletModeDesc:
      'タブレットモードを有効にすると、モバイルデバイスでPCスタイルのインターフェースを使用できます'
  },
  playback: {
    quality: '音質設定',
    qualityDesc: '音楽再生の音質を選択(NetEase Cloud VIP)',
    qualityOptions: {
      standard: '標準',
      higher: '高音質',
      exhigh: '超高音質',
      lossless: 'ロスレス',
      hires: 'Hi-Res',
      jyeffect: 'HD サラウンド',
      sky: 'イマーシブサラウンド',
      dolby: 'Dolby Atmos',
      jymaster: '超高解像度マスター'
    },
    musicSources: '音源設定',
    musicSourcesDesc: '音楽解析に使用する音源プラットフォームを選択',
    musicSourcesWarning: '少なくとも1つの音源プラットフォームを選択する必要があります',
    musicUnblockEnable: '音楽解析を有効にする',
    musicUnblockEnableDesc: '有効にすると、再生できない音楽の解析を試みます',
    configureMusicSources: '音源を設定',
    selectedMusicSources: '選択された音源:',
    noMusicSources: '音源が選択されていません',
    gdmusicInfo: 'GD音楽台は複数のプラットフォーム音源を自動解析し、最適な結果を自動選択できます',
    autoPlay: '自動再生',
    autoPlayDesc: 'アプリを再起動した際に自動的に再生を継続するかどうか',
    showStatusBar: 'ステータスバーコントロール機能を表示するかどうか',
    showStatusBarContent:
      'Macのステータスバーに音楽コントロール機能を表示できます(再起動後に有効)',
    fallbackParser: '代替解析サービス (GD音楽台)',
    fallbackParserDesc:
      '「GD音楽台」にチェックが入っていて、通常の音源で再生できない場合、このサービスが使用されます。',
    parserGD: 'GD 音楽台 (内蔵)',
    parserCustom: 'カスタム API',
    sourceLabels: {
      migu: 'Migu',
      kugou: 'Kugou',
      pyncmd: 'NetEase (内蔵)',
      bilibili: 'Bilibili',
      gdmusic: 'GD 音楽台',
      custom: 'カスタム API'
    },
    customApi: {
      sectionTitle: 'カスタム API 設定',
      enableHint:
        'カスタム API を有効にするには、まずカスタム API をインポートする必要があります。',
      importConfig: 'JSON設定をインポート',
      currentSource: '現在の音源',
      notImported: 'カスタム音源はまだインポートされていません。',
      importSuccess: '音源のインポートに成功しました: {name}',
      importFailed: 'インポートに失敗しました: {message}',
      status: {
        imported: 'カスタム音源インポート済み',
        notImported: '未インポート'
      }
    },
    lxMusic: {
      tabs: {
        sources: '音源選択',
        lxMusic: '落雪音源',
        customApi: 'カスタムAPI'
      },
      scripts: {
        title: 'インポート済みのスクリプト',
        importLocal: 'ローカルインポート',
        importOnline: 'オンラインインポート',
        urlPlaceholder: '落雪音源スクリプトのURLを入力',
        importBtn: 'インポート',
        empty: 'インポート済みの落雪音源はありません',
        notConfigured: '未設定(落雪音源タブで設定してください)',
        importHint: '互換性のあるカスタムAPIプラグインをインポートして音源を拡張します',
        noScriptWarning: '先に落雪音源スクリプトをインポートしてください',
        noSelectionWarning: '先に落雪音源を選択してください',
        notFound: '音源が存在しません',
        switched: '音源を切り替えました: {name}',
        deleted: '音源を削除しました: {name}',
        enterUrl: 'スクリプトURLを入力してください',
        invalidUrl: '無効なURL形式',
        invalidScript: '無効な落雪音源スクリプトです(globalThis.lxが見つかりません)',
        nameRequired: '名前を空にすることはできません',
        renameSuccess: '名前を変更しました'
      }
    }
  },
  application: {
    closeAction: '閉じる動作',
    closeActionDesc: 'ウィンドウを閉じる際の動作を選択',
    closeOptions: {
      ask: '毎回確認',
      minimize: 'トレイに最小化',
      close: '直接終了'
    },
    shortcut: 'ショートカット設定',
    shortcutDesc: 'グローバルショートカットをカスタマイズ',
    download: 'ダウンロード管理',
    downloadDesc: 'ダウンロードリストボタンを常に表示するかどうか',
    unlimitedDownload: '無制限ダウンロード',
    unlimitedDownloadDesc:
      '有効にすると音楽を無制限でダウンロードします(ダウンロード失敗の可能性があります)。デフォルトは300曲制限',
    downloadPath: 'ダウンロードディレクトリ',
    downloadPathDesc: '音楽ファイルのダウンロード場所を選択',
    remoteControl: 'リモートコントロール',
    remoteControlDesc: 'リモートコントロール機能を設定'
  },
  network: {
    apiPort: '音楽APIポート',
    apiPortDesc: '変更後はアプリの再起動が必要です',
    proxy: 'プロキシ設定',
    proxyDesc: '音楽にアクセスできない場合はプロキシを有効にできます',
    proxyHost: 'プロキシアドレス',
    proxyHostPlaceholder: 'プロキシアドレスを入力してください',
    proxyPort: 'プロキシポート',
    proxyPortPlaceholder: 'プロキシポートを入力してください',
    realIP: 'realIP設定',
    realIPDesc:
      '制限により、このプロジェクトは海外での使用が制限されます。realIPパラメータを使用して国内IPを渡すことで解決できます',
    messages: {
      proxySuccess: 'プロキシ設定を保存しました。アプリ再起動後に有効になります',
      proxyError: '入力が正しいかどうか確認してください',
      realIPSuccess: '実IPアドレス設定を保存しました',
      realIPError: '有効なIPアドレスを入力してください'
    }
  },
  system: {
    cache: 'キャッシュ管理',
    cacheDesc: 'キャッシュをクリア',
    cacheClearTitle: 'クリアするキャッシュタイプを選択してください:',
    cacheTypes: {
      history: {
        label: '再生履歴',
        description: '再生した楽曲の記録をクリア'
      },
      favorite: {
        label: 'お気に入り記録',
        description: 'ローカルのお気に入り楽曲記録をクリア(クラウドのお気に入りには影響しません)'
      },
      user: {
        label: 'ユーザーデータ',
        description: 'ログイン情報とユーザー関連データをクリア'
      },
      settings: {
        label: 'アプリ設定',
        description: 'アプリのすべてのカスタム設定をクリア'
      },
      downloads: {
        label: 'ダウンロード記録',
        description: 'ダウンロード履歴をクリア(ダウンロード済みファイルは削除されません)'
      },
      resources: {
        label: '音楽リソース',
        description: '読み込み済みの音楽ファイル、歌詞などのリソースキャッシュをクリア'
      },
      lyrics: {
        label: '歌詞リソース',
        description: '読み込み済みの歌詞リソースキャッシュをクリア'
      }
    },
    restart: '再起動',
    restartDesc: 'アプリを再起動',
    messages: {
      clearSuccess: 'クリア成功。一部の設定は再起動後に有効になります'
    }
  },
  about: {
    version: 'バージョン',
    checkUpdate: '更新を確認',
    checking: '確認中...',
    latest: '現在最新バージョンです',
    hasUpdate: '新しいバージョンが見つかりました',
    gotoUpdate: '更新へ',
    gotoGithub: 'Githubへ',
    author: '作者',
    authorDesc: 'algerkong スターを付けてください🌟',
    messages: {
      checkError: '更新確認に失敗しました。後でもう一度お試しください'
    }
  },
  validation: {
    selectProxyProtocol: 'プロキシプロトコルを選択してください',
    proxyHost: 'プロキシアドレスを入力してください',
    portNumber: '有効なポート番号を入力してください(1-65535)'
  },
  lyricSettings: {
    title: '歌詞設定',
    tabs: {
      display: '表示',
      interface: 'インターフェース',
      typography: 'テキスト',
      background: '背景',
      mobile: 'モバイル'
    },
    pureMode: 'ピュアモード',
    hideCover: 'カバーを非表示',
    centerDisplay: '中央表示',
    showTranslation: '翻訳を表示',
    hideLyrics: '歌詞を非表示',
    hidePlayBar: '再生バーを非表示',
    hideMiniPlayBar: 'ミニ再生バーを非表示',
    showMiniPlayBar: 'ミニ再生バーを表示',
    backgroundTheme: '背景テーマ',
    themeOptions: {
      default: 'デフォルト',
      light: 'ライト',
      dark: 'ダーク'
    },
    fontSize: 'フォントサイズ',
    fontSizeMarks: {
      small: '小',
      medium: '中',
      large: '大'
    },
    fontWeight: 'フォントの太さ',
    fontWeightMarks: {
      thin: '細い',
      normal: '通常',
      bold: '太い'
    },
    letterSpacing: '文字間隔',
    letterSpacingMarks: {
      compact: 'コンパクト',
      default: 'デフォルト',
      loose: 'ゆったり'
    },
    lineHeight: '行の高さ',
    lineHeightMarks: {
      compact: 'コンパクト',
      default: 'デフォルト',
      loose: 'ゆったり'
    },
    contentWidth: 'コンテンツ幅',
    mobileLayout: 'モバイルレイアウト',
    layoutOptions: {
      default: 'デフォルト',
      ios: 'iOSスタイル',
      android: 'Androidスタイル'
    },
    mobileCoverStyle: 'カバースタイル',
    coverOptions: {
      record: 'レコード',
      square: '正方形',
      full: 'フルスクリーン'
    },
    lyricLines: '歌詞行数',
    mobileUnavailable: 'この設定はモバイルでのみ利用可能です',
    // 背景設定
    background: {
      useCustomBackground: 'カスタム背景を使用',
      backgroundMode: '背景モード',
      modeOptions: {
        solid: '単色',
        gradient: 'グラデーション',
        image: '画像',
        css: 'CSS'
      },
      solidColor: '色を選択',
      presetColors: 'プリセットカラー',
      customColor: 'カスタムカラー',
      gradientEditor: 'グラデーションエディター',
      gradientColors: 'グラデーションカラー',
      gradientDirection: 'グラデーション方向',
      directionOptions: {
        toBottom: '上から下',
        toRight: '左から右',
        toBottomRight: '左上から右下',
        angle45: '45度',
        toTop: '下から上',
        toLeft: '右から左'
      },
      addColor: '色を追加',
      removeColor: '色を削除',
      imageUpload: '画像をアップロード',
      imagePreview: '画像プレビュー',
      clearImage: '画像をクリア',
      imageBlur: 'ぼかし',
      imageBrightness: '明るさ',
      customCss: 'カスタム CSS スタイル',
      customCssPlaceholder: 'CSSスタイルを入力、例: background: linear-gradient(...)',
      customCssHelp: '任意のCSS background プロパティをサポート',
      reset: 'デフォルトにリセット',
      fileSizeLimit: '画像サイズ制限: 20MB',
      invalidImageFormat: '無効な画像形式',
      imageTooLarge: '画像が大きすぎます。20MB未満の画像を選択してください'
    }
  },
  translationEngine: '歌詞翻訳エンジン',
  translationEngineOptions: {
    none: 'オフ',
    opencc: 'OpenCC 繁体字化'
  },
  themeColor: {
    title: '歌詞テーマカラー',
    presetColors: 'プリセットカラー',
    customColor: 'カスタムカラー',
    preview: 'プレビュー効果',
    previewText: '歌詞効果',
    colorNames: {
      'spotify-green': 'Spotify グリーン',
      'apple-blue': 'Apple ブルー',
      'youtube-red': 'YouTube レッド',
      orange: 'バイタルオレンジ',
      purple: 'ミステリアスパープル',
      pink: 'サクラピンク'
    },
    tooltips: {
      openColorPicker: 'カラーパレットを開く',
      closeColorPicker: 'カラーパレットを閉じる'
    },
    placeholder: '#1db954'
  },
  shortcutSettings: {
    title: 'ショートカット設定',
    shortcut: 'ショートカット',
    shortcutDesc: 'ショートカットをカスタマイズ',
    shortcutConflict: 'ショートカットの競合',
    inputPlaceholder: 'クリックしてショートカットを入力',
    resetShortcuts: 'デフォルトに戻す',
    disableAll: 'すべて無効',
    enableAll: 'すべて有効',
    togglePlay: '再生/一時停止',
    prevPlay: '前の曲',
    nextPlay: '次の曲',
    volumeUp: '音量を上げる',
    volumeDown: '音量を下げる',
    toggleFavorite: 'お気に入り/お気に入り解除',
    toggleWindow: 'ウィンドウ表示/非表示',
    scopeGlobal: 'グローバル',
    scopeApp: 'アプリ内',
    enabled: '有効',
    disabled: '無効',
    messages: {
      resetSuccess: 'デフォルトのショートカットに戻しました。保存を忘れずに',
      conflict: '競合するショートカットがあります。再設定してください',
      saveSuccess: 'ショートカット設定を保存しました',
      saveError: 'ショートカットの保存に失敗しました。再試行してください',
      cancelEdit: '変更をキャンセルしました',
      disableAll: 'すべてのショートカットを無効にしました。保存を忘れずに',
      enableAll: 'すべてのショートカットを有効にしました。保存を忘れずに'
    }
  },
  remoteControl: {
    title: 'リモートコントロール',
    enable: 'リモートコントロールを有効にする',
    port: 'サービスポート',
    allowedIps: '許可されたIPアドレス',
    addIp: 'IPを追加',
    emptyListHint: '空のリストはすべてのIPアクセスを許可することを意味します',
    saveSuccess: 'リモートコントロール設定を保存しました',
    accessInfo: 'リモートコントロールアクセスアドレス:'
  },
  cookie: {
    title: 'Cookie設定',
    description: 'NetEase Cloud MusicのCookieを入力してください:',
    placeholder: '完全なCookieを貼り付けてください...',
    help: {
      format: 'Cookieは通常「MUSIC_U=」で始まります',
      source: 'ブラウザの開発者ツールのネットワークリクエストから取得できます',
      storage: 'Cookie設定後、自動的にローカルストレージに保存されます'
    },
    action: {
      save: 'Cookieを保存',
      paste: '貼り付け',
      clear: 'クリア'
    },
    validation: {
      required: 'Cookieを入力してください',
      format: 'Cookie形式が正しくない可能性があります。MUSIC_Uが含まれているか確認してください'
    },
    message: {
      saveSuccess: 'Cookieの保存に成功しました',
      saveError: 'Cookieの保存に失敗しました',
      pasteSuccess: '貼り付けに成功しました',
      pasteError: '貼り付けに失敗しました。手動でコピーしてください'
    },
    info: {
      length: '現在の長さ:{length} 文字'
    }
  }
};


================================================
FILE: src/i18n/lang/ja-JP/songItem.ts
================================================
export default {
  menu: {
    play: '再生',
    playNext: '次に再生',
    download: '楽曲をダウンロード',
    addToPlaylist: 'プレイリストに追加',
    favorite: 'いいね',
    unfavorite: 'いいね解除',
    removeFromPlaylist: 'プレイリストから削除',
    dislike: '嫌い',
    undislike: '嫌い解除'
  },
  message: {
    downloading: 'ダウンロード中です。しばらくお待ちください...',
    downloadFailed: 'ダウンロードに失敗しました',
    downloadQueued: 'ダウンロードキューに追加しました',
    addedToNextPlay: '次の再生に追加しました',
    getUrlFailed: '音楽ダウンロードアドレスの取得に失敗しました。ログインしているか確認してください'
  },
  dialog: {
    dislike: {
      title: 'お知らせ!',
      content: 'この楽曲を嫌いにしますか?再度アクセスすると毎日のおすすめから除外されます。',
      positiveText: '嫌い',
      negativeText: 'キャンセル'
    }
  }
};


================================================
FILE: src/i18n/lang/ja-JP/user.ts
================================================
export default {
  profile: {
    followers: 'フォロワー',
    following: 'フォロー中',
    level: 'レベル'
  },
  playlist: {
    created: '作成したプレイリスト',
    mine: '私が作成した',
    trackCount: '{count}曲',
    playCount: '{count}回再生'
  },
  tabs: {
    created: '作成',
    favorite: 'お気に入り',
    album: 'アルバム'
  },
  ranking: {
    title: '聴取ランキング',
    playCount: '{count}回'
  },
  follow: {
    title: 'フォローリスト',
    viewPlaylist: 'プレイリストを見る',
    noFollowings: 'フォローがありません',
    loadMore: 'さらに読み込み',
    noSignature: 'この人は怠け者で、何も残していません',
    userFollowsTitle: 'のフォロー',
    myFollowsTitle: '私のフォロー'
  },
  follower: {
    title: 'フォロワーリスト',
    noFollowers: 'フォロワーがいません',
    loadMore: 'さらに読み込み',
    userFollowersTitle: 'のフォロワー',
    myFollowersTitle: '私のフォロワー'
  },
  detail: {
    playlists: 'プレイリスト',
    records: '聴取ランキング',
    noPlaylists: 'プレイリストがありません',
    noRecords: '聴取記録がありません',
    artist: 'アーティスト',
    noSignature: 'この人は怠け者で、何も残していません',
    invalidUserId: '無効なユーザーID',
    noRecordPermission: '{name}は聴取ランキングを見せてくれません'
  },
  message: {
    loadFailed: 'ユーザーページの読み込みに失敗しました',
    deleteSuccess: '削除成功',
    deleteFailed: '削除失敗'
  }
};


================================================
FILE: src/i18n/lang/ko-KR/artist.ts
================================================
export default {
  hotSongs: '인기 곡',
  albums: '앨범',
  description: '아티스트 소개'
};


================================================
FILE: src/i18n/lang/ko-KR/bilibili.ts
================================================
export default {
  player: {
    loading: '오디오 로딩 중...',
    retry: '다시 시도',
    playNow: '지금 재생',
    loadingTitle: '로딩 중...',
    totalDuration: '총 재생시간: {duration}',
    partsList: '파트 목록 ({count}화)',
    playStarted: '재생이 시작되었습니다',
    switchingPart: '파트 전환 중: {part}',
    preloadingNext: '다음 파트 미리 로딩 중: {part}',
    playingCurrent: '현재 선택된 파트 재생 중: {name}',
    num: '만',
    errors: {
      invalidVideoId: '유효하지 않은 비디오 ID',
      loadVideoDetailFailed: '비디오 세부정보 로드 실패',
      loadPartInfoFailed: '비디오 파트 정보를 로드할 수 없습니다',
      loadAudioUrlFailed: '오디오 재생 URL 가져오기 실패',
      videoDetailNotLoaded: '비디오 세부정보가 로드되지 않았습니다',
      missingParams: '필수 매개변수가 누락되었습니다',
      noAvailableAudioUrl: '사용 가능한 오디오 URL을 찾을 수 없습니다',
      loadPartAudioFailed: '파트 오디오 URL 로드 실패',
      audioListEmpty: '오디오 목록이 비어있습니다. 다시 시도해주세요',
      currentPartNotFound: '현재 파트의 오디오를 찾을 수 없습니다',
      audioUrlFailed: '오디오 URL 가져오기 실패',
      playFailed: '재생 실패. 다시 시도해주세요',
      getAudioUrlFailed: '오디오 URL 가져오기 실패. 다시 시도해주세요',
      audioNotFound: '해당 오디오를 찾을 수 없습니다. 다시 시도해주세요',
      preloadFailed: '다음 파트 미리 로딩 실패',
      switchPartFailed: '파트 전환 시 오디오 URL 로드 실패'
    },
    console: {
      loadingDetail: 'Bilibili 비디오 세부정보 로딩 중',
      detailData: 'Bilibili 비디오 세부정보 데이터',
      multipleParts: '비디오에 여러 파트가 있습니다. 총 {count}개',
      noPartsData: '비디오에 파트가 없거나 파트 데이터가 비어있습니다',
      loadingAudioSource: '오디오 소스 로딩 중',
      generatedAudioList: '오디오 목록을 생성했습니다. 총 {count}개',
      getDashAudioUrl: 'dash 오디오 URL을 가져왔습니다',
      getDurlAudioUrl: 'durl 오디오 URL을 가져왔습니다',
      loadingPartAudio: '파트 오디오 URL 로딩 중: {part}, cid: {cid}',
      loadPartAudioFailed: '파트 오디오 URL 로드 실패: {part}',
      switchToPart: '파트로 전환 중: {part}',
      audioNotFoundInList: '해당 오디오 항목을 찾을 수 없습니다',
      preparingToPlay: '현재 선택된 파트 재생 준비 중: {name}',
      preloadingNextPart: '다음 파트 미리 로딩 중: {part}',
      playingSelectedPart: '현재 선택된 파트 재생 중: {name}, 오디오 URL: {url}',
      preloadNextFailed: '다음 파트 미리 로딩 실패'
    }
  }
};


================================================
FILE: src/i18n/lang/ko-KR/common.ts
================================================
export default {
  play: '재생',
  next: '다음 곡',
  previous: '이전 곡',
  volume: '볼륨',
  settings: '설정',
  search: '검색',
  loading: '로딩 중...',
  loadingMore: '더 불러오기...',
  alipay: '알리페이',
  wechat: '위챗 페이',
  on: '켜기',
  off: '끄기',
  show: '표시',
  hide: '숨기기',
  confirm: '확인',
  cancel: '취소',
  configure: '구성',
  open: '열기',
  modify: '수정',
  success: '작업 성공',
  error: '작업 실패',
  warning: '경고',
  info: '알림',
  save: '저장',
  delete: '삭제',
  refresh: '새로고침',
  retry: '다시 시도',
  reset: '재설정',
  back: '뒤로',
  copySuccess: '클립보드에 복사됨',
  copyFailed: '복사 실패',
  validation: {
    required: '이 항목은 필수입니다',
    invalidInput: '잘못된 입력',
    selectRequired: '옵션을 선택해주세요',
    numberRange: '{min}에서 {max} 사이의 숫자를 입력해주세요'
  },
  viewMore: '더 보기',
  noMore: '더 이상 없음',
  selectAll: '전체 선택',
  expand: '펼치기',
  collapse: '접기',
  songCount: '{count}곡',
  language: '언어',
  today: '오늘',
  yesterday: '어제',
  tray: {
    show: '표시',
    quit: '종료',
    playPause: '재생/일시정지',
    prev: '이전 곡',
    next: '다음 곡',
    pause: '일시정지',
    play: '재생',
    favorite: '즐겨찾기'
  }
};


================================================
FILE: src/i18n/lang/ko-KR/comp.ts
================================================
export default {
  installApp: {
    description: '앱을 설치하여 더 나은 경험을 얻으세요',
    noPrompt: '다시 묻지 않기',
    install: '지금 설치',
    cancel: '나중에 설치',
    download: '다운로드',
    downloadFailed: '다운로드 실패',
    downloadComplete: '다운로드 완료',
    downloadProblem: '다운로드에 문제가 있나요?',
    downloadProblemLinkText: '최신 버전 다운로드'
  },
  playlistDrawer: {
    title: '플레이리스트에 추가',
    createPlaylist: '새 플레이리스트 만들기',
    cancelCreate: '만들기 취소',
    create: '만들기',
    playlistName: '플레이리스트 이름',
    privatePlaylist: '비공개 플레이리스트',
    publicPlaylist: '공개 플레이리스트',
    createSuccess: '플레이리스트 생성 성공',
    createFailed: '플레이리스트 생성 실패',
    addSuccess: '곡 추가 성공',
    addFailed: '곡 추가 실패',
    private: '비공개',
    public: '공개',
    count: '곡',
    loginFirst: '먼저 로그인해주세요',
    getPlaylistFailed: '플레이리스트 가져오기 실패',
    inputPlaylistName: '플레이리스트 이름을 입력해주세요'
  },
  update: {
    title: '새 버전 발견',
    currentVersion: '현재 버전',
    cancel: '나중에 업데이트',
    prepareDownload: '다운로드 준비 중...',
    downloading: '다운로드 중...',
    nowUpdate: '지금 업데이트',
    downloadFailed: '다운로드 실패, 다시 시도하거나 수동으로 다운로드해주세요',
    startFailed: '다운로드 시작 실패, 다시 시도하거나 수동으로 다운로드해주세요',
    noDownloadUrl: '현재 시스템에 적합한 설치 패키지를 찾을 수 없습니다. 수동으로 다운로드해주세요',
    installConfirmTitle: '업데이트 설치',
    installConfirmContent: '앱을 닫고 업데이트를 설치하시겠습니까?',
    manualInstallTip:
      '앱을 닫은 후 설치 프로그램이 정상적으로 나타나지 않으면 다운로드 폴더에서 파일을 찾아 수동으로 열어주세요.',
    yesInstall: '지금 설치',
    noThanks: '나중에 설치',
    fileLocation: '파일 위치',
    copy: '경로 복사',
    copySuccess: '경로가 클립보드에 복사됨',
    copyFailed: '복사 실패',
    backgroundDownload: '백그라운드 다운로드'
  },
  disclaimer: {
    title: '이용 안내',
    warning:
      '본 앱은 개발 테스트 버전으로 기능이 아직 미흡하며, 다수의 문제와 버그가 존재할 수 있습니다. 학습 및 교류 목적으로만 사용하십시오.',
    item1:
      '본 앱은 개인의 학습, 연구 및 기술 교류 목적으로만 사용되며, 상업적 용도로 사용하지 마십시오.',
    item2:
      '다운로드 후 24시간 이내에 삭제해 주십시오. 장기 사용을 원하시면 정품 음악 서비스를 이용해 주십시오.',
    item3:
      '본 앱을 사용함으로써 관련 위험을 이해하고 감수하는 것으로 간주합니다. 개발자는 어떠한 손실에 대해서도 책임을 지지 않습니다.',
    agree: '숙지하였으며 이에 동의합니다',
    disagree: '동의하지 않음 및 정지'
  },
  donate: {
    title: '개발자 지원',
    subtitle: '여러분의 지원이 저의 원동력입니다',
    tip: '후원은 완전히 자율적입니다. 후원하지 않더라도 모든 기능을 정상적으로 사용할 수 있습니다. 이해와 지원에 감사드립니다!',
    wechat: 'WeChat',
    alipay: 'Alipay',
    wechatQR: 'WeChat 결제 코드',
    alipayQR: 'Alipay 결제 코드',
    scanTip: '휴대전화로 위 QR 코드를 스캔하여 후원해 주세요',
    enterApp: '앱 시작하기',
    noForce: '후원은 강제가 아닙니다. 클릭하여 시작할 수 있습니다'
  },
  coffee: {
    title: '커피 한 잔 사주세요',
    alipay: '알리페이',
    wechat: '위챗 페이',
    alipayQR: '알리페이 결제 QR코드',
    wechatQR: '위챗 결제 QR코드',
    coffeeDesc: '커피 한 잔, 하나의 지원',
    coffeeDescLinkText: '더 보기',
    groupText: '微信公众号:AlgerMusic',
    messages: {
      copySuccess: '클립보드에 복사됨'
    },
    donateList: '커피 한 잔 사주세요'
  },
  playlistType: {
    title: '플레이리스트 분류',
    showAll: '모두 표시',
    hide: '일부 숨기기'
  },
  recommendAlbum: {
    title: '최신 앨범'
  },
  recommendSinger: {
    title: '일일 추천',
    songlist: '일일 추천 목록'
  },
  recommendSonglist: {
    title: '이번 주 인기 음악'
  },
  searchBar: {
    login: '로그인',
    toLogin: '로그인하기',
    logout: '로그아웃',
    set: '설정',
    theme: '테마',
    restart: '재시작',
    refresh: '새로고침',
    currentVersion: '현재 버전',
    searchPlaceholder: '검색해보세요...',
    zoom: '페이지 확대/축소',
    zoom100: '표준 확대/축소 100%',
    resetZoom: '클릭하여 확대/축소 재설정',
    zoomDefault: '표준 확대/축소'
  },
  titleBar: {
    closeTitle: '닫기 방법을 선택해주세요',
    minimizeToTray: '트레이로 최소화',
    exitApp: '앱 종료',
    rememberChoice: '선택 기억하기',
    closeApp: '앱 닫기'
  },
  userPlayList: {
    title: '{name}의 자주 듣는 음악'
  },
  musicList: {
    searchSongs: '곡 검색',
    noSearchResults: '관련 곡을 찾을 수 없습니다',
    switchToNormal: '기본 레이아웃으로 전환',
    switchToCompact: '컴팩트 레이아웃으로 전환',
    playAll: '모두 재생',
    collect: '수집',
    collectSuccess: '수집 성공',
    cancelCollectSuccess: '수집 취소 성공',
    operationFailed: '작업 실패',
    cancelCollect: '수집 취소',
    addToPlaylist: '재생 목록에 추가',
    addToPlaylistSuccess: '재생 목록에 추가 성공',
    songsAlreadyInPlaylist: '곡이 이미 재생 목록에 있습니다',
    historyRecommend: '일일 기록 권장',
    fetchDatesFailed: '날짜를 가져오지 못했습니다',
    fetchSongsFailed: '곡을 가져오지 못했습니다',
    noSongs: '노래 없음'
  },
  playlist: {
    import: {
      button: '플레이리스트 가져오기',
      title: '플레이리스트 가져오기',
      description: '메타데이터/텍스트/링크 세 가지 방법으로 플레이리스트 가져오기 지원',
      linkTab: '링크 가져오기',
      textTab: '텍스트 가져오기',
      localTab: '메타데이터 가져오기',
      linkPlaceholder: '플레이리스트 링크를 입력하세요. 한 줄에 하나씩',
      textPlaceholder: '곡 정보를 입력하세요. 형식: 곡명 가수명',
      localPlaceholder: 'JSON 형식의 곡 메타데이터를 입력하세요',
      linkTips: '지원되는 링크 소스:',
      linkTip1: '플레이리스트를 위챗/웨이보/QQ로 공유한 후 링크 복사',
      linkTip2: '플레이리스트/개인 홈페이지 링크 직접 복사',
      linkTip3: '기사 링크 직접 복사',
      textTips: '곡 정보를 입력하세요. 한 줄에 한 곡씩',
      textFormat: '형식: 곡명 가수명',
      localTips: '곡 메타데이터를 추가해주세요',
      localFormat: '형식 예시:',
      songNamePlaceholder: '곡명',
      artistNamePlaceholder: '아티스트명',
      albumNamePlaceholder: '앨범명',
      addSongButton: '곡 추가',
      addLinkButton: '링크 추가',
      importToStarPlaylist: '내가 좋아하는 음악으로 가져오기',
      playlistNamePlaceholder: '플레이리스트 이름을 입력하세요',
      importButton: '가져오기 시작',
      emptyLinkWarning: '플레이리스트 링크를 입력해주세요',
      emptyTextWarning: '곡 정보를 입력해주세요',
      emptyLocalWarning: '곡 메타데이터를 입력해주세요',
      invalidJsonFormat: 'JSON 형식이 올바르지 않습니다',
      importSuccess: '가져오기 작업 생성 성공',
      importFailed: '가져오기 실패',
      importStatus: '가져오기 상태',
      refresh: '새로고침',
      taskId: '작업 ID',
      status: '상태',
      successCount: '성공 수',
      failReason: '실패 이유',
      unknownError: '알 수 없는 오류',
      statusPending: '처리 대기 중',
      statusProcessing: '처리 중',
      statusSuccess: '가져오기 성공',
      statusFailed: '가져오기 실패',
      statusUnknown: '알 수 없는 상태',
      taskList: '작업 목록',
      taskListTitle: '가져오기 작업 목록',
      action: '작업',
      select: '선택',
      fetchTaskListFailed: '작업 목록 가져오기 실패',
      noTasks: '가져오기 작업이 없습니다',
      clearTasks: '작업 지우기',
      clearTasksConfirmTitle: '지우기 확인',
      clearTasksConfirmContent:
        '모든 가져오기 작업 기록을 지우시겠습니까? 이 작업은 되돌릴 수 없습니다.',
      confirm: '확인',
      cancel: '취소',
      clearTasksSuccess: '작업 목록이 지워졌습니다',
      clearTasksFailed: '작업 목록 지우기 실패'
    }
  },
  settings: '설정',
  user: '사용자',
  toplist: '순위',
  history: '수집 기록',
  list: '플레이리스트',
  mv: 'MV',
  home: '홈',
  search: '검색'
};


================================================
FILE: src/i18n/lang/ko-KR/donation.ts
================================================
export default {
  description:
    '귀하의 기부는 서버 유지보수, 도메인 갱신 등을 포함한 개발 및 유지보수 작업을 지원하는 데 사용됩니다.',
  message: '메시지를 남길 때 이메일이나 GitHub 이름을 남겨주세요.',
  refresh: '목록 새로고침',
  toDonateList: '커피 한 잔 사주세요',
  noMessage: '메시지가 없습니다',
  title: '기부 목록'
};


================================================
FILE: src/i18n/lang/ko-KR/download.ts
================================================
export default {
  title: '다운로드 관리',
  localMusic: '로컬 음악',
  count: '총 {count}곡',
  clearAll: '기록 지우기',
  settings: '설정',
  tabs: {
    downloading: '다운로드 중',
    downloaded: '다운로드 완료'
  },
  empty: {
    noTasks: '다운로드 작업이 없습니다',
    noDownloaded: '다운로드된 곡이 없습니다'
  },
  progress: {
    total: '전체 진행률: {progress}%'
  },
  status: {
    downloading: '다운로드 중',
    completed: '완료',
    failed: '실패',
    unknown: '알 수 없음'
  },
  artist: {
    unknown: '알 수 없는 가수'
  },
  delete: {
    title: '삭제 확인',
    message: '곡 "{filename}"을(를) 삭제하시겠습니까? 이 작업은 되돌릴 수 없습니다.',
    confirm: '삭제 확인',
    cancel: '취소',
    success: '삭제 성공',
    failed: '삭제 실패',
    fileNotFound: '파일이 존재하지 않거나 이동되었습니다. 기록에서 제거되었습니다',
    recordRemoved: '파일 삭제 실패, 하지만 기록에서 제거되었습니다'
  },
  clear: {
    title: '다운로드 기록 지우기',
    message:
      '모든 다운로드 기록을 지우시겠습니까? 이 작업은 다운로드된 음악 파일을 삭제하지 않지만 모든 기록을 지웁니다.',
    confirm: '지우기 확인',
    cancel: '취소',
    success: '다운로드 기록이 지워졌습니다'
  },
  message: {
    downloadComplete: '{filename} 다운로드 완료',
    downloadFailed: '{filename} 다운로드 실패: {error}'
  },
  loading: '로딩 중...',
  playStarted: '재생 시작: {name}',
  playFailed: '재생 실패: {name}',
  path: {
    copied: '경로가 클립보드에 복사됨',
    copyFailed: '경로 복사 실패'
  },
  settingsPanel: {
    title: '다운로드 설정',
    path: '다운로드 위치',
    pathDesc: '음악 파일 다운로드 저장 위치 설정',
    pathPlaceholder: '다운로드 경로를 선택해주세요',
    noPathSelected: '먼저 다운로드 경로를 선택해주세요',
    select: '폴더 선택',
    open: '폴더 열기',
    fileFormat: '파일명 형식',
    fileFormatDesc: '음악 다운로드 시 파일 이름 형식 설정',
    customFormat: '사용자 정의 형식',
    separator: '구분자',
    separators: {
      dash: '공백-공백',
      underscore: '밑줄',
      space: '공백'
    },
    dragToArrange: '드래그하여 정렬하거나 화살표 버튼을 사용하여 순서 조정:',
    formatVariables: '사용 가능한 변수',
    preview: '미리보기 효과:',
    saveSuccess: '다운로드 설정이 저장됨',
    presets: {
      songArtist: '곡명 - 가수명',
      artistSong: '가수명 - 곡명',
      songOnly: '곡명만'
    },
    components: {
      songName: '곡명',
      artistName: '가수명',
      albumName: '앨범명'
    }
  }
};


================================================
FILE: src/i18n/lang/ko-KR/favorite.ts
================================================
export default {
  title: '내 수집',
  count: '총 {count}곡',
  batchDownload: '일괄 다운로드',
  download: '다운로드 ({count})',
  emptyTip: '아직 수집한 곡이 없습니다',
  downloadSuccess: '다운로드 완료',
  downloadFailed: '다운로드 실패',
  downloading: '다운로드 중입니다. 잠시만 기다려주세요...',
  selectSongsFirst: '먼저 다운로드할 곡을 선택해주세요',
  descending: '내림차순',
  ascending: '오름차순'
};


================================================
FILE: src/i18n/lang/ko-KR/history.ts
================================================
export default {
  title: '재생 기록',
  heatmapTitle: '히트맵',
  playCount: '{count}',
  getHistoryFailed: '기록 가져오기 실패',
  tabs: {
    all: '전체 기록',
    local: '로컬 기록',
    cloud: '클라우드 기록'
  },
  categoryTabs: {
    songs: '곡',
    playlists: '플레이리스트',
    albums: '앨범'
  },
  noDescription: '설명 없음',
  noData: '기록 없음',
  getCloudRecordFailed: '클라우드 기록 가져오기 실패',
  needLogin: 'cookie를 사용하여 로그인하여 클라우드 기록을 볼 수 있습니다',
  merging: '기록 병합 중...',
  heatmap: {
    title: '재생 히트맵',
    loading: '데이터 로딩 중...',
    unit: '회 재생',
    footerText: '마우스를 올려서 자세히 보기',
    playCount: '{count}회 재생',
    topSongs: '오늘의 인기곡',
    times: '회',
    totalPlays: '총 재생 횟수',
    activeDays: '활동 일수',
    noData: '재생 기록이 없습니다',
    colorTheme: '색상 테마',
    colors: {
      green: '그린',
      blue: '블루',
      orange: '오렌지',
      purple: '퍼플',
      red: '레드'
    },
    mostPlayedSong: '가장 많이 재생한 노래',
    mostActiveDay: '가장 활발한 날',
    latestNightSong: '가장 늘게 재생한 노래'
  }
};


================================================
FILE: src/i18n/lang/ko-KR/login.ts
================================================
export default {
  title: {
    qr: 'QR코드 로그인',
    phone: '휴대폰 번호 로그인',
    cookie: 'Cookie 로그인',
    uid: 'UID 로그인'
  },
  qrTip: '넷이즈 클라우드 뮤직 앱으로 QR코드를 스캔하여 로그인',
  phoneTip: '넷이즈 클라우드 계정으로 로그인',
  tokenTip: '유효한 넷이즈 클라우드 뮤직 Cookie을 입력하여 로그인',
  uidTip: '사용자 ID를 입력하여 빠른 로그인',
  placeholder: {
    phone: '휴대폰 번호',
    password: '비밀번호',
    cookie: '넷이즈 클라우드 뮤직 Cookie(token)을 입력하세요',
    uid: '사용자 ID(UID)를 입력하세요'
  },
  button: {
    login: '로그인',
    switchToQr: 'QR코드 로그인',
    switchToPhone: '휴대폰 번호 로그인',
    switchToToken: 'Cookie 로그인 사용',
    switchToUid: 'UID 로그인',
    backToQr: 'QR코드 로그인으로 돌아가기',
    cookieLogin: 'Cookie 로그인',
    autoGetCookie: 'Cookie 자동 가져오기',
    refresh: '새로고침',
    refreshing: '새로고침 중...',
    refreshQr: 'QR코드 새로고침'
  },
  message: {
    loginSuccess: '로그인 성공',
    tokenLoginSuccess: 'Cookie 로그인 성공',
    uidLoginSuccess: 'UID 로그인 성공',
    loadError: '로그인 정보 로드 중 오류 발생',
    qrCheckError: 'QR코드 상태 확인 중 오류 발생',
    tokenRequired: 'Cookie을 입력하세요',
    tokenInvalid: 'Cookie이 유효하지 않습니다. 확인 후 다시 시도하세요',
    uidRequired: '사용자 ID를 입력하세요',
    uidInvalid: '사용자 ID가 유효하지 않거나 사용자가 존재하지 않습니다',
    uidLoginFailed: 'UID 로그인에 실패했습니다. 사용자 ID가 올바른지 확인하세요',
    autoGetCookieSuccess: 'Cookie 자동 가져오기 성공',
    autoGetCookieFailed: 'Cookie 자동 가져오기 실패',
    autoGetCookieTip:
      '넷이즈 클라우드 뮤직 로그인 페이지를 열겠습니다. 로그인 완료 후 창을 닫아주세요',
    loginFailed: '로그인 실패',
    phoneRequired: '휴대폰 번호를 입력하세요',
    passwordRequired: '비밀번호를 입력하세요',
    phoneLoginFailed: '휴대폰 번호 로그인 실패, 휴대폰 번호와 비밀번호가 올바른지 확인하세요',
    qrCheckFailed: 'QR코드 상태 확인 실패, 새로고침하여 다시 시도하세요',
    qrLoading: 'QR코드 로딩 중...',
    qrExpired: 'QR코드가 만료되었습니다. 클릭하여 새로고침하세요',
    qrExpiredShort: 'QR코드 만료됨',
    qrExpiredWarning: 'QR코드가 만료되었습니다. 클릭하여 새로운 QR코드를 받으세요',
    qrScanned: 'QR코드가 스캔되었습니다. 휴대폰에서 로그인을 확인하세요',
    qrScannedShort: '스캔됨',
    qrScannedInfo: 'QR코드가 스캔되었습니다. 휴대폰에서 로그인을 확인하세요',
    qrConfirmed: '로그인 성공, 리다이렉트 중...',
    qrGenerating: 'QR코드를 생성 중...'
  },
  qrTitle: '넷이즈 클라우드 뮤직 QR코드 로그인',
  uidWarning:
    '주의: UID 로그인은 사용자 공개 정보를 확인하는 데만 사용할 수 있으며, 로그인 권한이 필요한 기능에 액세스할 수 없습니다.'
};


================================================
FILE: src/i18n/lang/ko-KR/player.ts
================================================
export default {
  nowPlaying: '현재 재생 중',
  playlist: '재생 목록',
  lyrics: '가사',
  previous: '이전',
  play: '재생',
  pause: '일시정지',
  next: '다음',
  volumeUp: '볼륨 증가',
  volumeDown: '볼륨 감소',
  mute: '음소거',
  unmute: '음소거 해제',
  songNum: '총 곡 수: {num}',
  addCorrection: '{num}초 앞당기기',
  subtractCorrection: '{num}초 지연',
  playFailed: '현재 곡 재생 실패, 다음 곡 재생',
  parseFailedPlayNext: '곡 분석 실패, 다음 곡 재생',
  consecutiveFailsError:
    '재생 오류가 발생했습니다. 네트워크 문제 또는 유효하지 않은 음원일 수 있습니다. 재생 목록을 변경하거나 나중에 다시 시도하세요',
  playMode: {
    sequence: '순차 재생',
    loop: '한 곡 반복',
    random: '랜덤 재생'
  },
  fullscreen: {
    enter: '전체화면',
    exit: '전체화면 종료'
  },
  close: '닫기',
  modeHint: {
    single: '한 곡 반복',
    list: '자동으로 다음 곡 재생'
  },
  lrc: {
    noLrc: '가사가 없습니다. 음악을 감상해주세요',
    noAutoScroll: '본 가사는 자동 스크롤을 지원하지 않습니다'
  },
  reparse: {
    title: '음원 선택',
    desc: '음원을 클릭하여 직접 분석하세요. 다음에 이 곡을 재생할 때 선택한 음원을 사용합니다',
    success: '재분석 성공',
    failed: '재분석 실패',
    warning: '음원을 선택해주세요',
    bilibiliNotSupported: 'B站 비디오는 재분석을 지원하지 않습니다',
    processing: '분석 중...',
    clear: '사용자 정의 음원 지우기',
    customApiFailed: '사용자 정의 API 분석 실패, 기본 음원을 시도합니다...',
    customApiError: '사용자 정의 API 요청 오류, 기본 음원을 시도합니다...'
  },
  playBar: {
    expand: '가사 펼치기',
    collapse: '가사 접기',
    like: '좋아요',
    lyric: '가사',
    noSongPlaying: '재생 중인 곡이 없습니다',
    eq: '이퀄라이저',
    playList: '재생 목록',
    reparse: '재분석',
    playMode: {
      sequence: '순차 재생',
      loop: '반복 재생',
      random: '랜덤 재생'
    },
    play: '재생 시작',
    pause: '재생 일시정지',
    prev: '이전 곡',
    next: '다음 곡',
    volume: '볼륨',
    favorite: '{name} 즐겨찾기 추가됨',
    unFavorite: '{name} 즐겨찾기 해제됨',
    miniPlayBar: '미니 재생바',
    playbackSpeed: '재생 속도',
    advancedControls: '고급 설정',
    intelligenceMode: {
      title: '인텔리전스 모드',
      needCookieLogin: '쿠키 방식으로 로그인한 후 인텔리전스 모드를 사용할 수 있습니다',
      noFavoritePlaylist: '내가 좋아하는 음악 재생목록을 찾을 수 없습니다',
      noLikedSongs: '아직 좋아한 노래가 없습니다',
      loading: '인텔리전스 모드를 불러오는 중',
      success: '총 {count}곡을 불러왔습니다',
      failed: '인텔리전스 모드 목록을 가져오는 데 실패했습니다',
      error: '인텔리전스 모드 재생 오류'
    }
  },
  eq: {
    title: '이퀄라이저',
    reset: '재설정',
    on: '켜기',
    off: '끄기',
    bass: '저음',
    midrange: '중음',
    treble: '고음',
    presets: {
      flat: '플랫',
      pop: '팝',
      rock: '록',
      classical: '클래식',
      jazz: '재즈',
      electronic: '일렉트로닉',
      hiphop: '힙합',
      rb: 'R&B',
      metal: '메탈',
      vocal: '보컬',
      dance: '댄스',
      acoustic: '어쿠스틱',
      custom: '사용자 정의'
    }
  },
  // 플레이어 설정
  settings: {
    title: '재생 설정',
    playbackSpeed: '재생 속도'
  },
  sleepTimer: {
    title: '타이머 종료',
    cancel: '타이머 취소',
    timeMode: '시간으로 종료',
    songsMode: '곡 수로 종료',
    playlistEnd: '재생 목록 완료 후 종료',
    afterPlaylist: '재생 목록 완료 후 종료',
    activeUntilEnd: '목록 끝까지 재생',
    minutes: '분',
    hours: '시간',
    songs: '곡',
    set: '설정',
    timerSetSuccess: '{minutes}분 후 종료로 설정됨',
    songsSetSuccess: '{songs}곡 재생 후 종료로 설정됨',
    playlistEndSetSuccess: '재생 목록 완료 후 종료로 설정됨',
    timerCancelled: '타이머 종료 취소됨',
    timerEnded: '타이머 종료 실행됨',
    playbackStopped: '음악 재생이 중지됨',
    minutesRemaining: '남은 시간 {minutes}분',
    songsRemaining: '남은 곡 수 {count}곡'
  },
  playList: {
    clearAll: '재생 목록 비우기',
    alreadyEmpty: '재생 목록이 이미 비어있습니다',
    cleared: '재생 목록이 비워졌습니다',
    empty: '재생 목록이 비어있습니다',
    clearConfirmTitle: '재생 목록 비우기',
    clearConfirmContent: '재생 목록의 모든 곡을 삭제하고 현재 재생을 중지합니다. 계속하시겠습니까?'
  }
};


================================================
FILE: src/i18n/lang/ko-KR/search.ts
================================================
export default {
  title: {
    hotSearch: '인기 검색',
    searchList: '검색 목록',
    searchHistory: '검색 기록'
  },
  button: {
    clear: '지우기',
    back: '뒤로',
    playAll: '재생 목록'
  },
  loading: {
    more: '로딩 중...',
    failed: '검색 실패',
    searching: '검색 중...'
  },
  noMore: '더 이상 없음',
  error: {
    searchFailed: '검색 실패'
  },
  search: {
    single: '단일곡',
    album: '앨범',
    playlist: '플레이리스트',
    mv: 'MV',
    bilibili: 'B站'
  },
  history: '검색 기록',
  hot: '인기 검색',
  suggestions: '검색 제안'
};


================================================
FILE: src/i18n/lang/ko-KR/settings.ts
================================================
export default {
  theme: '테마',
  language: '언어',
  regard: '정보',
  logout: '로그아웃',
  sections: {
    basic: '기본 설정',
    playback: '재생 설정',
    application: '애플리케이션 설정',
    network: '네트워크 설정',
    system: '시스템 관리',
    donation: '후원 지원',
    about: '정보'
  },
  basic: {
    themeMode: '테마 모드',
    themeModeDesc: '낮/밤 테마 전환',
    autoTheme: '시스템 따라가기',
    manualTheme: '수동 전환',
    language: '언어 설정',
    languageDesc: '표시 언어 전환',
    tokenManagement: 'Cookie 관리',
    tokenManagementDesc: '넷이즈 클라우드 뮤직 로그인 Cookie 관리',
    tokenStatus: '현재 Cookie 상태',
    tokenSet: '설정됨',
    tokenNotSet: '설정되지 않음',
    setToken: 'Cookie 설정',
    modifyToken: 'Cookie 수정',
    clearToken: 'Cookie 지우기',
    font: '폰트 설정',
    fontDesc: '폰트 선택, 앞에 있는 폰트를 우선 사용',
    fontScope: {
      global: '전역',
      lyric: '가사만'
    },
    animation: '애니메이션 속도',
    animationDesc: '애니메이션 활성화 여부',
    animationSpeed: {
      slow: '매우 느림',
      normal: '보통',
      fast: '매우 빠름'
    },
    fontPreview: {
      title: '폰트 미리보기',
      chinese: '中文',
      english: 'English',
      japanese: '日本語',
      korean: '한국어',
      chineseText: '静夜思 床前明月光 疑是地上霜',
      englishText: 'The quick brown fox jumps over the lazy dog',
      japaneseText: 'あいうえお かきくけこ さしすせそ',
      koreanText: '가나다라마 바사아자차 카타파하'
    },
    gpuAcceleration: 'GPU 가속',
    gpuAccelerationDesc:
      'GPU 가속을 사용하면 애니메이션이 빠르게 재생되고 애니메이션이 느리게 재생되는 것보다 느릴 수 있습니다.',
    gpuAccelerationRestart: 'GPU 가속 설정을 변경하면 애플리케이션을 다시 시작해야 합니다',
    gpuAccelerationChangeSuccess:
      'GPU 가속 설정이 업데이트되었습니다. 애플리케이션을 다시 시작하여 적용하십시오',
    gpuAccelerationChangeError: 'GPU 가속 설정 업데이트에 실패했습니다',
    tabletMode: '태블릿 모드',
    tabletModeDesc:
      '태블릿 모드를 사용하면 모바일 기기에서 PC 스타일의 인터페이스를 사용할 수 있습니다'
  },
  playback: {
    quality: '음질 설정',
    qualityDesc: '음악 재생 음질 선택 (넷이즈 클라우드 VIP)',
    qualityOptions: {
      standard: '표준',
      higher: '높음',
      exhigh: '매우 높음',
      lossless: '무손실',
      hires: 'Hi-Res',
      jyeffect: 'HD 서라운드',
      sky: '몰입형 서라운드',
      dolby: '돌비 애트모스',
      jymaster: '초고화질 마스터'
    },
    musicSources: '음원 설정',
    musicSourcesDesc: '음악 해석에 사용할 음원 플랫폼 선택',
    musicSourcesWarning: '최소 하나의 음원 플랫폼을 선택해야 합니다',
    musicUnblockEnable: '음악 해석 활성화',
    musicUnblockEnableDesc: '활성화하면 재생할 수 없는 음악을 해석하려고 시도합니다',
    configureMusicSources: '음원 구성',
    selectedMusicSources: '선택된 음원:',
    noMusicSources: '음원이 선택되지 않음',
    gdmusicInfo: 'GD 뮤직은 여러 플랫폼 음원을 자동으로 해석하고 최적의 결과를 자동 선택합니다',
    autoPlay: '자동 재생',
    autoPlayDesc: '앱을 다시 열 때 자동으로 재생을 계속할지 여부',
    showStatusBar: '상태바 제어 기능 표시 여부',
    showStatusBarContent: 'Mac 상태바에 음악 제어 기능을 표시할 수 있습니다 (재시작 후 적용)',
    fallbackParser: '대체 분석 서비스 (GD Music)',
    fallbackParserDesc:
      '"GD Music"을 선택하고 일반 음원을 사용할 수 없을 때 이 서비스를 사용합니다.',
    parserGD: 'GD Music (내장)',
    parserCustom: '사용자 지정 API',

    // 음원 라벨
    sourceLabels: {
      migu: 'Migu',
      kugou: 'Kugou',
      pyncmd: 'NetEase (내장)',
      bilibili: 'Bilibili',
      gdmusic: 'GD Music',
      custom: '사용자 지정 API'
    },

    customApi: {
      sectionTitle: '사용자 지정 API 설정',
      importConfig: 'JSON 설정 가져오기',
      currentSource: '현재 음원',
      notImported: '아직 사용자 지정 음원을 가져오지 않았습니다.',
      importSuccess: '음원 가져오기 성공: {name}',
      importFailed: '가져오기 실패: {message}',
      enableHint: '사용하려면 먼저 JSON 구성 파일을 가져오세요',
      status: {
        imported: '사용자 지정 음원 가져옴',
        notImported: '가져오지 않음'
      }
    },
    lxMusic: {
      tabs: {
        sources: '음원 선택',
        lxMusic: '낙설 음원',
        customApi: '사용자 정의 API'
      },
      scripts: {
        title: '가져온 스크립트',
        importLocal: '로컬 가져오기',
        importOnline: '온라인 가져오기',
        urlPlaceholder: '낙설 음원 스크립트 URL 입력',
        importBtn: '가져오기',
        empty: '가져온 낙설 음원이 없습니다',
        notConfigured: '설정되지 않음 (낙설 음원 탭에서 설정하세요)',
        importHint: '소스 확장을 위해 호환되는 사용자 정의 API 플러그인을 가져옵니다',
        noScriptWarning: '먼저 낙설 음원 스크립트를 가져오세요',
        noSelectionWarning: '먼저 낙설 음원 소스를 선택하세요',
        notFound: '음원이 존재하지 않습니다',
        switched: '음원으로 전환되었습니다: {name}',
        deleted: '음원이 삭제되었습니다: {name}',
        enterUrl: '스크립트 URL을 입력하세요',
        invalidUrl: '유효하지 않은 URL 형식',
        invalidScript: '유효하지 않은 낙설 음원 스크립트입니다 (globalThis.lx 코드를 찾을 수 없음)',
        nameRequired: '이름은 비워둘 수 없습니다',
        renameSuccess: '이름이 변경되었습니다'
      }
    }
  },
  application: {
    closeAction: '닫기 동작',
    closeActionDesc: '창을 닫을 때의 동작 선택',
    closeOptions: {
      ask: '매번 묻기',
      minimize: '트레이로 최소화',
      close: '직접 종료'
    },
    shortcut: '단축키 설정',
    shortcutDesc: '전역 단축키 사용자 정의',
    download: '다운로드 관리',
    downloadDesc: '다운로드 목록 버튼을 항상 표시할지 여부',
    unlimitedDownload: '무제한 다운로드',
    unlimitedDownloadDesc:
      '활성화하면 음악을 무제한으로 다운로드합니다 (다운로드 실패가 발생할 수 있음), 기본 제한 300곡',
    downloadPath: '다운로드 디렉토리',
    downloadPathDesc: '음악 파일의 다운로드 위치 선택',
    remoteControl: '원격 제어',
    remoteControlDesc: '원격 제어 기능 설정'
  },
  network: {
    apiPort: '음악 API 포트',
    apiPortDesc: '수정 후 앱을 재시작해야 합니다',
    proxy: '프록시 설정',
    proxyDesc: '음악에 액세스할 수 없을 때 프록시를 활성화할 수 있습니다',
    proxyHost: '프록시 주소',
    proxyHostPlaceholder: '프록시 주소를 입력하세요',
    proxyPort: '프록시 포트',
    proxyPortPlaceholder: '프록시 포트를 입력하세요',
    realIP: 'realIP 설정',
    realIPDesc:
      '제한으로 인해 이 프로젝트는 해외에서 사용할 때 제한을 받을 수 있으며, realIP 매개변수를 사용하여 국내 IP를 전달하여 해결할 수 있습니다',
    messages: {
      proxySuccess: '프록시 설정이 저장되었습니다. 앱을 재시작한 후 적용됩니다',
      proxyError: '입력이 올바른지 확인하세요',
      realIPSuccess: '실제 IP 설정이 저장되었습니다',
      realIPError: '유효한 IP 주소를 입력하세요'
    }
  },
  system: {
    cache: '캐시 관리',
    cacheDesc: '캐시 지우기',
    cacheClearTitle: '지울 캐시 유형을 선택하세요:',
    cacheTypes: {
      history: {
        label: '재생 기록',
        description: '재생한 곡 기록 지우기'
      },
      favorite: {
        label: '즐겨찾기 기록',
        description: '로컬 즐겨찾기 곡 기록 지우기 (클라우드 즐겨찾기에는 영향 없음)'
      },
      user: {
        label: '사용자 데이터',
        description: '로그인 정보 및 사용자 관련 데이터 지우기'
      },
      settings: {
        label: '앱 설정',
        description: '앱의 모든 사용자 정의 설정 지우기'
      },
      downloads: {
        label: '다운로드 기록',
        description: '다운로드 기록 지우기 (다운로드된 파일은 삭제되지 않음)'
      },
      resources: {
        label: '음악 리소스',
        description: '로드된 음악 파일, 가사 등 리소스 캐시 지우기'
      },
      lyrics: {
        label: '가사 리소스',
        description: '로드된 가사 리소스 캐시 지우기'
      }
    },
    restart: '재시작',
    restartDesc: '앱 재시작',
    messages: {
      clearSuccess: '지우기 성공, 일부 설정은 재시작 후 적용됩니다'
    }
  },
  about: {
    version: '버전',
    checkUpdate: '업데이트 확인',
    checking: '확인 중...',
    latest: '현재 최신 버전입니다',
    hasUpdate: '새 버전 발견',
    gotoUpdate: '업데이트하러 가기',
    gotoGithub: 'Github로 이동',
    author: '작성자',
    authorDesc: 'algerkong 별점🌟 부탁드려요',
    messages: {
      checkError: '업데이트 확인 실패, 나중에 다시 시도하세요'
    }
  },
  validation: {
    selectProxyProtocol: '프록시 프로토콜을 선택하세요',
    proxyHost: '프록시 주소를 입력하세요',
    portNumber: '유효한 포트 번호를 입력하세요 (1-65535)'
  },
  lyricSettings: {
    title: '가사 설정',
    tabs: {
      display: '표시',
      interface: '인터페이스',
      typography: '텍스트',
      background: '배경',
      mobile: '모바일'
    },
    pureMode: '순수 모드',
    hideCover: '커버 숨기기',
    centerDisplay: '중앙 표시',
    showTranslation: '번역 표시',
    hideLyrics: '가사 숨기기',
    hidePlayBar: '재생바 숨기기',
    hideMiniPlayBar: '미니 재생바 숨기기',
    showMiniPlayBar: '미니 재생바 표시',
    backgroundTheme: '배경 테마',
    themeOptions: {
      default: '기본',
      light: '밝음',
      dark: '어둠'
    },
    fontSize: '폰트 크기',
    fontSizeMarks: {
      small: '작음',
      medium: '중간',
      large: '큼'
    },
    fontWeight: '글꼴 두께',
    fontWeightMarks: {
      thin: '가늘게',
      normal: '보통',
      bold: '굵게'
    },
    letterSpacing: '글자 간격',
    letterSpacingMarks: {
      compact: '좁음',
      default: '기본',
      loose: '넓음'
    },
    lineHeight: '줄 높이',
    lineHeightMarks: {
      compact: '좁음',
      default: '기본',
      loose: '넓음'
    },
    contentWidth: '콘텐츠 너비',
    mobileLayout: '모바일 레이아웃',
    layoutOptions: {
      default: '기본',
      ios: 'iOS 스타일',
      android: '안드로이드 스타일'
    },
    mobileCoverStyle: '커버 스타일',
    coverOptions: {
      record: '레코드',
      square: '정사각형',
      full: '전체화면'
    },
    lyricLines: '가사 줄 수',
    mobileUnavailable: '이 설정은 모바일에서만 사용 가능합니다',
    // 배경 설정
    background: {
      useCustomBackground: '사용자 정의 배경 사용',
      backgroundMode: '배경 모드',
      modeOptions: {
        solid: '단색',
        gradient: '그라데이션',
        image: '이미지',
        css: 'CSS'
      },
      solidColor: '색상 선택',
      presetColors: '프리셋 색상',
      customColor: '사용자 정의 색상',
      gradientEditor: '그라데이션 편집기',
      gradientColors: '그라데이션 색상',
      gradientDirection: '그라데이션 방향',
      directionOptions: {
        toBottom: '위에서 아래로',
        toRight: '왼쪽에서 오른쪽으로',
        toBottomRight: '왼쪽 위에서 오른쪽 아래로',
        angle45: '45도',
        toTop: '아래에서 위로',
        toLeft: '오른쪽에서 왼쪽으로'
      },
      addColor: '색상 추가',
      removeColor: '색상 제거',
      imageUpload: '이미지 업로드',
      imagePreview: '이미지 미리보기',
      clearImage: '이미지 지우기',
      imageBlur: '흐림',
      imageBrightness: '밝기',
      customCss: '사용자 정의 CSS 스타일',
      customCssPlaceholder: 'CSS 스타일 입력, 예: background: linear-gradient(...)',
      customCssHelp: '모든 CSS background 속성 지원',
      reset: '기본값으로 재설정',
      fileSizeLimit: '이미지 크기 제한: 20MB',
      invalidImageFormat: '잘못된 이미지 형식',
      imageTooLarge: '이미지가 너무 큽니다. 20MB 미만의 이미지를 선택하세요'
    }
  },
  translationEngine: '가사 번역 엔진',
  translationEngineOptions: {
    none: '닫기',
    opencc: 'OpenCC 중국어 번체'
  },
  themeColor: {
    title: '가사 테마 색상',
    presetColors: '미리 설정된 색상',
    customColor: '사용자 정의 색상',
    preview: '미리보기 효과',
    previewText: '가사 효과',
    colorNames: {
      'spotify-green': 'Spotify 그린',
      'apple-blue': '애플 블루',
      'youtube-red': 'YouTube 레드',
      orange: '활력 오렌지',
      purple: '신비 퍼플',
      pink: '벚꽃 핑크'
    },
    tooltips: {
      openColorPicker: '색상 선택기 열기',
      closeColorPicker: '색상 선택기 닫기'
    },
    placeholder: '#1db954'
  },
  shortcutSettings: {
    title: '단축키 설정',
    shortcut: '단축키',
    shortcutDesc: '단축키 사용자 정의',
    shortcutConflict: '단축키 충돌',
    inputPlaceholder: '클릭하여 단축키 입력',
    resetShortcuts: '기본값 복원',
    disableAll: '모두 비활성화',
    enableAll: '모두 활성화',
    togglePlay: '재생/일시정지',
    prevPlay: '이전 곡',
    nextPlay: '다음 곡',
    volumeUp: '볼륨 증가',
    volumeDown: '볼륨 감소',
    toggleFavorite: '즐겨찾기/즐겨찾기 취소',
    toggleWindow: '창 표시/숨기기',
    scopeGlobal: '전역',
    scopeApp: '앱 내',
    enabled: '활성화',
    disabled: '비활성화',
    messages: {
      resetSuccess: '기본 단축키로 복원되었습니다. 저장을 잊지 마세요',
      conflict: '충돌하는 단축키가 있습니다. 다시 설정하세요',
      saveSuccess: '단축키 설정이 저장되었습니다',
      saveError: '단축키 저장 실패, 다시 시도하세요',
      cancelEdit: '수정이 취소되었습니다',
      disableAll: '모든 단축키가 비활성화되었습니다. 저장을 잊지 마세요',
      enableAll: '모든 단축키가 활성화되었습니다. 저장을 잊지 마세요'
    }
  },
  remoteControl: {
    title: '원격 제어',
    enable: '원격 제어 활성화',
    port: '서비스 포트',
    allowedIps: '허용된 IP 주소',
    addIp: 'IP 추가',
    emptyListHint: '빈 목록은 모든 IP 액세스를 허용함을 의미합니다',
    saveSuccess: '원격 제어 설정이 저장되었습니다',
    accessInfo: '원격 제어 액세스 주소:'
  },
  cookie: {
    title: 'Cookie 설정',
    description: '넷이즈 클라우드 뮤직의 Cookie를 입력하세요:',
    placeholder: '완전한 Cookie를 붙여넣으세요...',
    help: {
      format: 'Cookie는 일반적으로 "MUSIC_U="로 시작합니다',
      source: '브라우저 개발자 도구의 네트워크 요청에서 얻을 수 있습니다',
      storage: 'Cookie 설정 후 자동으로 로컬 저장소에 저장됩니다'
    },
    action: {
      save: 'Cookie 저장',
      paste: '붙여넣기',
      clear: '지우기'
    },
    validation: {
      required: 'Cookie를 입력하세요',
      format: 'Cookie 형식이 올바르지 않을 수 있습니다. MUSIC_U가 포함되어 있는지 확인하세요'
    },
    message: {
      saveSuccess: 'Cookie 저장 성공',
      saveError: 'Cookie 저장 실패',
      pasteSuccess: '붙여넣기 성공',
      pasteError: '붙여넣기 실패, 수동으로 복사하세요'
    },
    info: {
      length: '현재 길이: {length} 문자'
    }
  }
};


================================================
FILE: src/i18n/lang/ko-KR/songItem.ts
================================================
export default {
  menu: {
    play: '재생',
    playNext: '다음에 재생',
    download: '곡 다운로드',
    addToPlaylist: '플레이리스트에 추가',
    favorite: '좋아요',
    unfavorite: '좋아요 취소',
    removeFromPlaylist: '플레이리스트에서 삭제',
    dislike: '싫어요',
    undislike: '싫어요 취소'
  },
  message: {
    downloading: '다운로드 중입니다. 잠시 기다려주세요...',
    downloadFailed: '다운로드 실패',
    downloadQueued: '다운로드 대기열에 추가됨',
    addedToNextPlay: '다음 재생에 추가됨',
    getUrlFailed: '음악 다운로드 주소 가져오기 실패, 로그인 상태를 확인하세요'
  },
  dialog: {
    dislike: {
      title: '알림!',
      content: '이 곡을 싫어한다고 확인하시겠습니까? 다시 들어가면 일일 추천에서 제외됩니다.',
      positiveText: '싫어요',
      negativeText: '취소'
    }
  }
};


================================================
FILE: src/i18n/lang/ko-KR/user.ts
================================================
export default {
  profile: {
    followers: '팔로워',
    following: '팔로잉',
    level: '레벨'
  },
  playlist: {
    created: '생성한 플레이리스트',
    mine: '내가 만든',
    trackCount: '{count}곡',
    playCount: '{count}회 재생'
  },
  tabs: {
    created: '생성',
    favorite: '즐겨찾기',
    album: '앨범'
  },
  ranking: {
    title: '음악 청취 순위',
    playCount: '{count}회'
  },
  follow: {
    title: '팔로잉 목록',
    viewPlaylist: '플레이리스트 보기',
    noFollowings: '팔로잉이 없습니다',
    loadMore: '더 보기',
    noSignature: '이 사람은 게을러서 아무것도 남기지 않았습니다',
    userFollowsTitle: '의 팔로잉',
    myFollowsTitle: '내 팔로잉'
  },
  follower: {
    title: '팔로워 목록',
    noFollowers: '팔로워가 없습니다',
    loadMore: '더 보기',
    userFollowersTitle: '의 팔로워',
    myFollowersTitle: '내 팔로워'
  },
  detail: {
    playlists: '플레이리스트',
    records: '음악 청취 순위',
    noPlaylists: '플레이리스트가 없습니다',
    noRecords: '음악 청취 기록이 없습니다',
    artist: '아티스트',
    noSignature: '이 사람은 게을러서 아무것도 남기지 않았습니다',
    invalidUserId: '사용자 ID가 유효하지 않습니다',
    noRecordPermission: '{name}님이 음악 청취 순위를 보지 못하게 했습니다'
  },
  message: {
    loadFailed: '사용자 페이지 로드 실패',
    deleteSuccess: '삭제 성공',
    deleteFailed: '삭제 실패'
  }
};


================================================
FILE: src/i18n/lang/zh-CN/artist.ts
================================================
export default {
  hotSongs: '热门歌曲',
  albums: '专辑',
  description: '艺人介绍'
};


================================================
FILE: src/i18n/lang/zh-CN/bilibili.ts
================================================
export default {
  player: {
    loading: '听书加载中...',
    retry: '重试',
    playNow: '立即播放',
    loadingTitle: '加载中...',
    totalDuration: '总时长: {duration}',
    partsList: '分P列表 (共{count}集)',
    playStarted: '已开始播放',
    switchingPart: '切换到分P: {part}',
    preloadingNext: '预加载下一个分P: {part}',
    playingCurrent: '播放当前选中的分P: {name}',
    num: '万',
    errors: {
      invalidVideoId: '视频ID无效',
      loadVideoDetailFailed: '获取视频详情失败',
      loadPartInfoFailed: '无法加载视频分P信息',
      loadAudioUrlFailed: '获取音频播放地址失败',
      videoDetailNotLoaded: '视频详情未加载',
      missingParams: '缺少必要参数',
      noAvailableAudioUrl: '未找到可用的音频地址',
      loadPartAudioFailed: '加载分P音频URL失败',
      audioListEmpty: '音频列表为空,请重试',
      currentPartNotFound: '未找到当前分P的音频',
      audioUrlFailed: '获取音频URL失败',
      playFailed: '播放失败,请重试',
      getAudioUrlFailed: '获取音频地址失败,请重试',
      audioNotFound: '未找到对应的音频,请重试',
      preloadFailed: '预加载下一个分P失败',
      switchPartFailed: '切换分P时加载音频URL失败'
    },
    console: {
      loadingDetail: '加载B站视频详情',
      detailData: 'B站视频详情数据',
      multipleParts: '视频有多个分P,共{count}个',
      noPartsData: '视频无分P或分P数据为空',
      loadingAudioSource: '加载音频源',
      generatedAudioList: '已生成音频列表,共{count}首',
      getDashAudioUrl: '获取到dash音频URL',
      getDurlAudioUrl: '获取到durl音频URL',
      loadingPartAudio: '加载分P音频URL: {part}, cid: {cid}',
      loadPartAudioFailed: '加载分P音频URL失败: {part}',
      switchToPart: '切换到分P: {part}',
      audioNotFoundInList: '未找到对应的音频项',
      preparingToPlay: '准备播放当前选中的分P: {name}',
      preloadingNextPart: '预加载下一个分P: {part}',
      playingSelectedPart: '播放当前选中的分P: {name},音频URL: {url}',
      preloadNextFailed: '预加载下一个分P失败'
    }
  }
};


================================================
FILE: src/i18n/lang/zh-CN/common.ts
================================================
export default {
  play: '播放',
  next: '下一首',
  previous: '上一首',
  volume: '音量',
  settings: '设置',
  search: '搜索',
  loading: '加载中...',
  loadingMore: '加载更多...',
  alipay: '支付宝',
  wechat: '微信支付',
  on: '开启',
  off: '关闭',
  show: '显示',
  hide: '隐藏',
  confirm: '确认',
  cancel: '取消',
  configure: '配置',
  open: '打开',
  modify: '修改',
  success: '操作成功',
  error: '操作失败',
  warning: '警告',
  info: '提示',
  save: '保存',
  delete: '删除',
  refresh: '刷新',
  retry: '重试',
  reset: '重置',
  back: '返回',
  copySuccess: '已复制到剪贴板',
  copyFailed: '复制失败',
  validation: {
    required: '此项是必填的',
    invalidInput: '输入无效',
    selectRequired: '请选择一个选项',
    numberRange: '请输入 {min} 到 {max} 之间的数字'
  },
  viewMore: '查看更多',
  noMore: '没有更多了',
  selectAll: '全选',
  expand: '展开',
  collapse: '收起',
  songCount: '{count}首',
  language: '语言',
  today: '今天',
  yesterday: '昨天',
  tray: {
    show: '显示',
    quit: '退出',
    playPause: '播放/暂停',
    prev: '上一首',
    next: '下一首',
    pause: '暂停',
    play: '播放',
    favorite: '收藏'
  }
};


================================================
FILE: src/i18n/lang/zh-CN/comp.ts
================================================
export default {
  installApp: {
    description: '安装应用程序,获得更好的体验',
    noPrompt: '不再提示',
    install: '立即安装',
    cancel: '暂不安装',
    download: '下载',
    downloadFailed: '下载失败',
    downloadComplete: '下载完成',
    downloadProblem: '下载遇到问题?去',
    downloadProblemLinkText: '下载最新版本'
  },
  playlistDrawer: {
    title: '添加到歌单',
    createPlaylist: '创建新歌单',
    cancelCreate: '取消创建',
    create: '创建',
    playlistName: '歌单名称',
    privatePlaylist: '私密歌单',
    publicPlaylist: '公开歌单',
    createSuccess: '歌单创建成功',
    createFailed: '歌单创建失败',
    addSuccess: '歌曲添加成功',
    addFailed: '歌曲添加失败',
    private: '私密',
    public: '公开',
    count: '首歌曲',
    loginFirst: '请先登录',
    getPlaylistFailed: '获取歌单失败',
    inputPlaylistName: '请输入歌单名称'
  },
  update: {
    title: '发现新版本',
    currentVersion: '当前版本',
    cancel: '暂不更新',
    prepareDownload: '准备下载...',
    downloading: '下载中...',
    nowUpdate: '立即更新',
    downloadFailed: '下载失败,请重试或手动下载',
    startFailed: '启动下载失败,请重试或手动下载',
    noDownloadUrl: '未找到适合当前系统的安装包,请手动下载',
    installConfirmTitle: '安装更新',
    installConfirmContent: '是否关闭应用并安装更新?',
    manualInstallTip: '如果关闭应用后没有正常弹出安装程序,请至下载文件夹查找文件并手动打开。',
    yesInstall: '立即安装',
    noThanks: '稍后安装',
    fileLocation: '文件位置',
    copy: '复制路径',
    copySuccess: '路径已复制到剪贴板',
    copyFailed: '复制失败',
    backgroundDownload: '后台下载'
  },
  disclaimer: {
    title: '使用须知',
    warning: '本应用为开发测试版本,功能尚不完善,可能存在较多问题和 Bug,仅供学习交流使用。',
    item1: '本应用仅供个人学习、研究和技术交流使用,请勿用于任何商业用途。',
    item2: '请在下载后 24 小时内删除,如需长期使用请支持正版音乐服务。',
    item3: '使用本应用即表示您理解并承担相关风险,开发者不对任何损失负责。',
    agree: '我已阅读并同意',
    disagree: '不同意并退出'
  },
  donate: {
    title: '支持开发者',
    subtitle: '您的支持是我前进的动力',
    tip: '捐赠完全自愿,不捐赠也可以正常使用所有功能,感谢您的理解与支持!',
    wechat: '微信',
    alipay: '支付宝',
    wechatQR: '微信收款码',
    alipayQR: '支付宝收款码',
    scanTip: '请使用手机扫描上方二维码进行捐赠',
    enterApp: '进入应用',
    noForce: '不强制捐赠,点击即可进入'
  },
  coffee: {
    title: '请我喝咖啡',
    alipay: '支付宝',
    wechat: '微信支付',
    alipayQR: '支付宝收款码',
    wechatQR: '微信收款码',
    coffeeDesc: '一杯咖啡,一份支持',
    coffeeDescLinkText: '查看更多',
    groupText: '微信公众号:AlgerMusic',
    messages: {
      copySuccess: '已复制到剪贴板'
    },
    donateList: '请我喝咖啡'
  },
  playlistType: {
    title: '歌单分类',
    showAll: '显示全部',
    hide: '隐藏一些'
  },
  recommendAlbum: {
    title: '最新专辑'
  },
  recommendSinger: {
    title: '每日推荐',
    songlist: '每日推荐列表'
  },
  recommendSonglist: {
    title: '本周最热音乐'
  },
  searchBar: {
    login: '登录',
    toLogin: '去登录',
    logout: '退出登录',
    set: '设置',
    theme: '主题',
    restart: '重启',
    refresh: '刷新',
    currentVersion: '当前版本',
    searchPlaceholder: '搜索点什么吧...',
    zoom: '页面缩放',
    zoom100: '标准缩放100%',
    resetZoom: '点击重置缩放',
    zoomDefault: '标准缩放'
  },
  titleBar: {
    closeTitle: '请选择关闭方式',
    minimizeToTray: '最小化到托盘',
    exitApp: '退出应用',
    rememberChoice: '记住我的选择',
    closeApp: '关闭应用'
  },
  userPlayList: {
    title: '{name}的常听'
  },
  musicList: {
    searchSongs: '搜索歌曲',
    noSearchResults: '没有找到相关歌曲',
    switchToNormal: '切换到默认布局',
    switchToCompact: '切换到紧凑布局',
    playAll: '播放全部',
    collect: '收藏',
    collectSuccess: '收藏成功',
    cancelCollectSuccess: '取消收藏成功',
    operationFailed: '操作失败',
    cancelCollect: '取消收藏',
    addToPlaylist: '添加到播放列表',
    addToPlaylistSuccess: '添加到播放列表成功',
    songsAlreadyInPlaylist: '歌曲已存在于播放列表中',
    historyRecommend: '历史日推',
    fetchDatesFailed: '获取日期列表失败',
    fetchSongsFailed: '获取歌曲列表失败',
    noSongs: '暂无歌曲'
  },
  playlist: {
    import: {
      button: '歌单导入',
      title: '歌单导入',
      description: '支持通过元数据/文字/链接三种方式导入歌单',
      linkTab: '链接导入',
      textTab: '文字导入',
      localTab: '元数据导入',
      linkPlaceholder: '请输入歌单链接,每行一个',
      textPlaceholder: '请输入歌曲信息,格式为:歌曲名 歌手名',
      localPlaceholder: '请输入JSON格式的歌曲元数据',
      linkTips: '支持的链接来源:',
      linkTip1: '将歌单分享到微信/微博/QQ后复制链接',
      linkTip2: '直接复制歌单/个人主页链接',
      linkTip3: '直接复制文章链接',
      textTips: '请输入歌曲信息,每行一首歌',
      textFormat: '格式:歌曲名 歌手名',
      localTips: '请添加歌曲元数据',
      localFormat: '格式示例:',
      songNamePlaceholder: '歌曲名称',
      artistNamePlaceholder: '艺术家名称',
      albumNamePlaceholder: '专辑名称',
      addSongButton: '添加歌曲',
      addLinkButton: '添加链接',
      importToStarPlaylist: '导入到我喜欢的音乐',
      playlistNamePlaceholder: '请输入歌单名称',
      importButton: '开始导入',
      emptyLinkWarning: '请输入歌单链接',
      emptyTextWarning: '请输入歌曲信息',
      emptyLocalWarning: '请输入歌曲元数据',
      invalidJsonFormat: 'JSON格式不正确',
      importSuccess: '导入任务创建成功',
      importFailed: '导入失败',
      importStatus: '导入状态',
      refresh: '刷新',
      taskId: '任务ID',
      status: '状态',
      successCount: '成功数量',
      failReason: '失败原因',
      unknownError: '未知错误',
      statusPending: '等待处理',
      statusProcessing: '处理中',
      statusSuccess: '导入成功',
      statusFailed: '导入失败',
      statusUnknown: '未知状态',
      taskList: '任务列表',
      taskListTitle: '导入任务列表',
      action: '操作',
      select: '选择',
      fetchTaskListFailed: '获取任务列表失败',
      noTasks: '暂无导入任务',
      clearTasks: '清除任务',
      clearTasksConfirmTitle: '确认清除',
      clearTasksConfirmContent: '确定要清除所有导入任务记录吗?此操作不可恢复。',
      confirm: '确认',
      cancel: '取消',
      clearTasksSuccess: '任务列表已清除',
      clearTasksFailed: '清除任务列表失败'
    }
  },
  settings: '设置',
  user: '用户',
  toplist: '排行榜',
  history: '收藏历史',
  list: '歌单',
  mv: 'MV',
  home: '首页',
  search: '搜索'
};


================================================
FILE: src/i18n/lang/zh-CN/donation.ts
================================================
export default {
  description: '您的捐赠将用于支持开发和维护工作,包括但不限于服务器维护、域名续费等。',
  message: '留言时可留下您的邮箱或 github名称。',
  refresh: '刷新列表',
  toDonateList: '请我喝咖啡',
  noMessage: '暂无留言',
  title: '捐赠列表'
};


================================================
FILE: src/i18n/lang/zh-CN/download.ts
================================================
export default {
  title: '下载管理',
  localMusic: '本地音乐',
  count: '共 {count} 首歌曲',
  clearAll: '清空记录',
  settings: '设置',
  tabs: {
    downloading: '下载中',
    downloaded: '已下载'
  },
  empty: {
    noTasks: '暂无下载任务',
    noDownloaded: '暂无已下载歌曲'
  },
  progress: {
    total: '总进度: {progress}%'
  },
  status: {
    downloading: '下载中',
    completed: '已完成',
    failed: '失败',
    unknown: '未知'
  },
  artist: {
    unknown: '未知歌手'
  },
  delete: {
    title: '删除确认',
    message: '确定要删除歌曲 "{filename}" 吗?此操作不可恢复。',
    confirm: '确定删除',
    cancel: '取消',
    success: '删除成功',
    failed: '删除失败',
    fileNotFound: '文件不存在或已被移动,已从记录中移除',
    recordRemoved: '文件删除失败,但已从记录中移除'
  },
  clear: {
    title: '清空下载记录',
    message: '确定要清空所有下载记录吗?此操作不会删除已下载的音乐文件,但将清空所有记录。',
    confirm: '确定清空',
    cancel: '取消',
    success: '下载记录已清空'
  },
  message: {
    downloadComplete: '{filename} 下载完成',
    downloadFailed: '{filename} 下载失败: {error}'
  },
  loading: '加载中...',
  playStarted: '开始播放: {name}',
  playFailed: '播放失败: {name}',
  path: {
    copied: '路径已复制到剪贴板',
    copyFailed: '复制路径失败'
  },
  settingsPanel: {
    title: '下载设置',
    path: '下载位置',
    pathDesc: '设置音乐文件下载保存的位置',
    pathPlaceholder: '请选择下载路径',
    noPathSelected: '请先选择下载路径',
    select: '选择文件夹',
    open: '打开文件夹',
    fileFormat: '文件名格式',
    fileFormatDesc: '设置下载音乐时的文件命名格式',
    customFormat: '自定义格式',
    separator: '分隔符',
    separators: {
      dash: '空格-空格',
      underscore: '下划线',
      space: '空格'
    },
    dragToArrange: '拖动排序或使用箭头按钮调整顺序:',
    formatVariables: '可用变量',
    preview: '预览效果:',
    saveSuccess: '下载设置已保存',
    presets: {
      songArtist: '歌曲名 - 歌手名',
      artistSong: '歌手名 - 歌曲名',
      songOnly: '仅歌曲名'
    },
    components: {
      songName: '歌曲名',
      artistName: '歌手名',
      albumName: '专辑名'
    }
  }
};


================================================
FILE: src/i18n/lang/zh-CN/favorite.ts
================================================
export default {
  title: '我的收藏',
  count: '共 {count} 首',
  batchDownload: '批量下载',
  download: '下载 ({count})',
  emptyTip: '还没有收藏歌曲',
  downloadSuccess: '下载完成',
  downloadFailed: '下载失败',
  downloading: '正在下载中,请稍候...',
  selectSongsFirst: '请先选择要下载的歌曲',
  descending: '降',
  ascending: '升'
};


================================================
FILE: src/i18n/lang/zh-CN/history.ts
================================================
export default {
  title: '播放历史',
  heatmapTitle: '热力图',
  playCount: '{count}',
  getHistoryFailed: '获取历史记录失败',
  categoryTabs: {
    songs: '歌曲',
    playlists: '歌单',
    albums: '专辑'
  },
  tabs: {
    all: '全部记录',
    local: '本地记录',
    cloud: '云端记录'
  },
  getCloudRecordFailed: '获取云端记录失败',
  needLogin: '请使用cookie登录以查看云端记录',
  merging: '正在合并记录...',
  noDescription: '暂无描述',
  noData: '暂无记录',
  heatmap: {
    title: '播放热力图',
    loading: '正在加载数据...',
    unit: '次播放',
    footerText: '鼠标悬停查看详细信息',
    playCount: '播放 {count} 次',
    topSongs: '当天热门歌曲',
    times: '次',
    totalPlays: '总播放次数',
    activeDays: '活跃天数',
    noData: '暂无播放记录',
    colorTheme: '配色方案',
    colors: {
      green: '绿色',
      blue: '蓝色',
      orange: '橙色',
      purple: '紫色',
      red: '红色'
    },
    mostPlayedSong: '播放最多的歌曲',
    mostActiveDay: '最活跃的一天',
    latestNightSong: '最晚播放的歌曲'
  }
};


================================================
FILE: src/i18n/lang/zh-CN/login.ts
================================================
export default {
  title: {
    qr: '扫码登录',
    phone: '手机号登录',
    cookie: 'Cookie登录',
    uid: 'UID登录'
  },
  qrTip: '使用网易云APP扫码登录',
  phoneTip: '使用网易云账号登录',
  tokenTip: '输入有效的网易云音乐Cookie即可登录',
  uidTip: '输入用户ID快速登录',
  placeholder: {
    phone: '手机号',
    password: '密码',
    cookie: '请输入网易云音乐Cookie(token)',
    uid: '请输入用户ID(UID)'
  },
  button: {
    login: '登录',
    switchToQr: '扫码登录',
    switchToPhone: '手机号登录',
    switchToToken: '使用Cookie登录',
    switchToUid: 'UID登录',
    backToQr: '返回二维码登录',
    cookieLogin: 'Cookie登录',
    autoGetCookie: '自动获取Cookie',
    refresh: '点击刷新',
    refreshing: '刷新中...',
    refreshQr: '刷新二维码'
  },
  message: {
    loginSuccess: '登录成功',
    loginFailed: '登录失败',
    tokenLoginSuccess: 'Cookie登录成功',
    uidLoginSuccess: 'UID登录成功',
    loadError: '加载登录信息时出错',
    qrCheckError: '检查二维码状态时出错',
    tokenRequired: '请输入Cookie',
    tokenInvalid: 'Cookie无效,请检查后重试',
    uidRequired: '请输入用户ID',
    uidInvalid: '用户ID无效或用户不存在',
    uidLoginFailed: 'UID登录失败,请检查用户ID是否正确',
    phoneRequired: '请输入手机号',
    passwordRequired: '请输入密码',
    phoneLoginFailed: '手机号登录失败,请检查手机号和密码是否正确',
    autoGetCookieSuccess: '自动获取Cookie成功',
    autoGetCookieFailed: '自动获取Cookie失败',
    autoGetCookieTip: '将打开网易云音乐登录页面,请完成登录后关闭窗口',
    qrCheckFailed: '检查二维码状态失败,请刷新重试',
    qrLoading: '正在加载二维码...',
    qrExpired: '二维码已过期,请点击刷新',
    qrExpiredShort: '二维码已过期',
    qrExpiredWarning: '二维码已过期,请点击刷新获取新的二维码',
    qrScanned: '已扫码,请在手机上确认登录',
    qrScannedShort: '已扫码',
    qrScannedInfo: '已扫码,请在手机上确认登录',
    qrConfirmed: '登录成功,正在跳转...',
    qrGenerating: '正在生成二维码...'
  },
  qrTitle: '扫码登录网易云音乐',
  uidWarning: '注意:UID登录仅用于查看用户公开信息,无法访问需要登录权限的功能'
};


================================================
FILE: src/i18n/lang/zh-CN/player.ts
================================================
export default {
  nowPlaying: '正在播放',
  playlist: '播放列表',
  lyrics: '歌词',
  previous: '上一个',
  play: '播放',
  pause: '暂停',
  next: '下一个',
  volumeUp: '音量增加',
  volumeDown: '音量减少',
  mute: '静音',
  unmute: '取消静音',
  songNum: '歌曲总数:{num}',
  addCorrection: '提前 {num} 秒',
  subtractCorrection: '延迟 {num} 秒',
  playFailed: '当前歌曲播放失败,播放下一首',
  parseFailedPlayNext: '歌曲解析失败,播放下一首',
  consecutiveFailsError: '播放遇到错误,可能是网络波动或解析源失效,请切换播放列表或稍后重试',
  playMode: {
    sequence: '顺序播放',
    loop: '单曲循环',
    random: '随机播放'
  },
  fullscreen: {
    enter: '全屏',
    exit: '退出全屏'
  },
  close: '关闭',
  modeHint: {
    single: '单曲循环',
    list: '自动播放下一个'
  },
  lrc: {
    noLrc: '暂无歌词, 请欣赏',
    noAutoScroll: '本歌词不支持自动滚动'
  },
  reparse: {
    title: '选择解析音源',
    desc: '点击音源直接进行解析,下次播放此歌曲时将使用所选音源',
    success: '重新解析成功',
    failed: '重新解析失败',
    warning: '请选择一个音源',
    bilibiliNotSupported: 'B站视频不支持重新解析',
    processing: '解析中...',
    clear: '清除自定义音源',
    customApiFailed: '自定义API解析失败,正在尝试使用内置音源...',
    customApiError: '自定义API请求出错,正在尝试使用内置音源...'
  },
  playBar: {
    expand: '展开歌词',
    collapse: '收起歌词',
    like: '喜欢',
    lyric: '歌词',
    noSongPlaying: '没有正在播放的歌曲',
    eq: '均衡器',
    playList: '播放列表',
    reparse: '重新解析',
    playMode: {
      sequence: '顺序播放',
      loop: '循环播放',
      random: '随机播放'
    },
    play: '开始播放',
    pause: '暂停播放',
    prev: '上一首',
    next: '下一首',
    volume: '音量',
    favorite: '已收藏{name}',
    unFavorite: '已取消收藏{name}',
    miniPlayBar: '迷你播放栏',
    playbackSpeed: '播放速度',
    advancedControls: '更多设置',
    intelligenceMode: {
      title: '心动模式',
      needCookieLogin: '请使用 Cookie 方式登录后使用心动模式',
      noFavoritePlaylist: '未找到我喜欢的音乐歌单',
      noLikedSongs: '您还没有喜欢的歌曲',
      loading: '正在加载心动模式',
      success: '已加载 {count} 首歌曲',
      failed: '获取心动模式列表失败',
      error: '心动模式播放出错'
    }
  },
  eq: {
    title: '均衡器',
    reset: '重置',
    on: '开启',
    off: '关闭',
    bass: '低音',
    midrange: '中音',
    treble: '高音',
    presets: {
      flat: '平坦',
      pop: '流行',
      rock: '摇滚',
      classical: '古典',
      jazz: '爵士',
      electronic: '电子',
      hiphop: '嘻哈',
      rb: 'R&B',
      metal: '金属',
      vocal: '人声',
      dance: '舞曲',
      acoustic: '原声',
      custom: '自定义'
    }
  },
  // 播放器设置
  settings: {
    title: '播放设置',
    playbackSpeed: '播放速度'
  },
  // 定时关闭功能相关
  sleepTimer: {
    title: '定时关闭',
    cancel: '取消定时',
    timeMode: '按时间关闭',
    songsMode: '按歌曲数关闭',
    playlistEnd: '播放完列表后关闭',
    afterPlaylist: '播放完列表后关闭',
    activeUntilEnd: '播放至列表结束',
    minutes: '分钟',
    hours: '小时',
    songs: '首歌',
    set: '设置',
    timerSetSuccess: '已设置{minutes}分钟后关闭',
    songsSetSuccess: '已设置播放{songs}首歌后关闭',
    playlistEndSetSuccess: '已设置播放完列表后关闭',
    timerCancelled: '已取消定时关闭',
    timerEnded: '定时关闭已触发',
    playbackStopped: '音乐播放已停止',
    minutesRemaining: '剩余{minutes}分钟',
    songsRemaining: '剩余{count}首歌'
  },
  playList: {
    clearAll: '清空播放列表',
    alreadyEmpty: '播放列表已经为空',
    cleared: '已清空播放列表',
    empty: '播放列表为空',
    clearConfirmTitle: '清空播放列表',
    clearConfirmContent: '这将清空所有播放列表中的歌曲并停止当前播放。是否继续?'
  }
};


================================================
FILE: src/i18n/lang/zh-CN/search.ts
================================================
export default {
  title: {
    hotSearch: '热搜列表',
    searchList: '搜索列表',
    searchHistory: '搜索历史'
  },
  button: {
    clear: '清空',
    back: '返回',
    playAll: '播放列表'
  },
  loading: {
    more: '加载中...',
    failed: '搜索失败',
    searching: '搜索中...'
  },
  noMore: '没有更多了',
  error: {
    searchFailed: '搜索失败'
  },
  search: {
    single: '单曲',
    album: '专辑',
    playlist: '歌单',
    mv: 'MV',
    bilibili: 'B站'
  },
  history: '搜索历史',
  hot: '热门搜索',
  suggestions: '搜索建议'
};


================================================
FILE: src/i18n/lang/zh-CN/settings.ts
================================================
export default {
  theme: '主题',
  language: '语言',
  regard: '关于',
  logout: '退出登录',
  sections: {
    basic: '基础设置',
    playback: '播放设置',
    application: '应用设置',
    network: '网络设置',
    system: '系统管理',
    donation: '捐赠支持',
    about: '关于'
  },
  basic: {
    themeMode: '主题模式',
    themeModeDesc: '切换日间/夜间主题',
    autoTheme: '跟随系统',
    manualTheme: '手动切换',
    language: '语言设置',
    languageDesc: '切换显示语言',
    tokenManagement: 'Cookie管理',
    tokenManagementDesc: '管理网易云音乐登录Cookie',
    tokenStatus: '当前Cookie状态',
    tokenSet: '已设置',
    tokenNotSet: '未设置',
    setToken: '设置Cookie',
    modifyToken: '修改Cookie',
    clearToken: '清除Cookie',
    font: '字体设置',
    fontDesc: '选择字体,优先使用排在前面的字体',
    fontScope: {
      global: '全局',
      lyric: '仅歌词'
    },
    animation: '动画速度',
    animationDesc: '是否开启动画',
    animationSpeed: {
      slow: '极慢',
      normal: '正常',
      fast: '极快'
    },
    fontPreview: {
      title: '字体预览',
      chinese: '中文',
      english: 'English',
      japanese: '日本語',
      korean: '한국어',
      chineseText: '静夜思 床前明月光 疑是地上霜',
      englishText: 'The quick brown fox jumps over the lazy dog',
      japaneseText: 'あいうえお かきくけこ さしすせそ',
      koreanText: '가나다라마 바사아자차 카타파하'
    },
    gpuAcceleration: 'GPU加速',
    gpuAccelerationDesc: '启用或禁用硬件加速,可以提高渲染性能但可能会增加GPU负载',
    gpuAccelerationRestart: '更改GPU加速设置需要重启应用后生效',
    gpuAccelerationChangeSuccess: 'GPU加速设置已更新,重启应用后生效',
    gpuAccelerationChangeError: 'GPU加速设置更新失败',
    tabletMode: '平板模式',
    tabletModeDesc: '启用后将在移动设备上使用PC样式界面,适合平板等大屏设备'
  },
  playback: {
    quality: '音质设置',
    qualityDesc: '选择音乐播放音质(网易云VIP)',
    qualityOptions: {
      standard: '标准',
      higher: '较高',
      exhigh: '极高',
      lossless: '无损',
      hires: 'Hi-Res',
      jyeffect: '高清环绕声',
      sky: '沉浸环绕声',
      dolby: '杜比全景声',
      jymaster: '超清母带'
    },
    musicSources: '音源设置',
    musicSourcesDesc: '选择音乐解析使用的音源平台',
    musicSourcesWarning: '至少需要选择一个音源平台',
    musicUnblockEnable: '启用音乐解析',
    musicUnblockEnableDesc: '开启后将尝试解析无法播放的音乐',
    configureMusicSources: '配置音源',
    selectedMusicSources: '已选音源:',
    noMusicSources: '未选择音源',
    gdmusicInfo: 'GD音乐台可自动解析多个平台音源,自动选择最佳结果',
    autoPlay: '自动播放',
    autoPlayDesc: '重新打开应用时是否自动继续播放',
    showStatusBar: '是否显示状态栏控制功能',
    showStatusBarContent: '可以在您的mac状态栏显示音乐控制功能(重启后生效)',

    fallbackParser: 'GD音乐台(music.gdstudio.xyz)设置',
    fallbackParserDesc:
      'GD音乐台将自动尝试多个音乐平台进行解析,无需额外配置。优先级高于其他解析方式,但是请求可能较慢。感谢(music.gdstudio.xyz)\n',
    parserGD: 'GD 音乐台 (内置)',
    parserCustom: '自定义 API',

    // 音源标签
    sourceLabels: {
      migu: '咪咕音乐',
      kugou: '酷狗音乐',
      pyncmd: '网易云(内置)',
      bilibili: 'Bilibili',
      gdmusic: 'GD音乐台',
      custom: '自定义 API'
    },

    // 自定义API相关的提示
    customApi: {
      sectionTitle: '自定义 API 设置',
      importConfig: '导入 JSON 配置',
      currentSource: '当前音源',
      notImported: '尚未导入自定义音源。',
      importSuccess: '成功导入音源: {name}',
      importFailed: '导入失败: {message}',
      enableHint: '请先导入 JSON 配置文件才能启用',
      status: {
        imported: '已导入自定义音源',
        notImported: '未导入'
      }
    },
    lxMusic: {
      tabs: {
        sources: '音源选择',
        lxMusic: '落雪音源',
        customApi: '自定义API'
      },
      scripts: {
        title: '已导入的音源脚本',
        importLocal: '本地导入',
        importOnline: '在线导入',
        urlPlaceholder: '输入落雪音源脚本 URL',
        importBtn: '导入',
        empty: '暂无已导入的落雪音源',
        notConfigured: '未配置 (请去落雪音源Tab配置)',
        importHint: '导入兼容的自定义 API 插件以扩展音源',
        noScriptWarning: '请先导入落雪音源脚本',
        noSelectionWarning: '请先选择一个落雪音源',
        notFound: '音源不存在',
        switched: '已切换到音源: {name}',
        deleted: '已删除音源: {name}',
        enterUrl: '请输入脚本 URL',
        invalidUrl: '无效的 URL 格式',
        invalidScript: '无效的落雪音源脚本,未找到 globalThis.lx 相关代码',
        nameRequired: '名称不能为空',
        renameSuccess: '重命名成功'
      }
    }
  },
  application: {
    closeAction: '关闭行为',
    closeActionDesc: '选择关闭窗口时的行为',
    closeOptions: {
      ask: '每次询问',
      minimize: '最小化到托盘',
      close: '直接退出'
    },
    shortcut: '快捷键设置',
    shortcutDesc: '自定义全局快捷键',
    download: '下载管理',
    downloadDesc: '是否始终显示下载列表按钮',
    unlimitedDownload: '无限制下载',
    unlimitedDownloadDesc: '开启后将无限制下载音乐(可能出现下载失败的情况), 默认限制 300 首',
    downloadPath: '下载目录',
    downloadPathDesc: '选择音乐文件的下载位置',
    remoteControl: '远程控制',
    remoteControlDesc: '设置远程控制功能'
  },
  network: {
    apiPort: '音乐API端口',
    apiPortDesc: '修改后需要重启应用',
    proxy: '代理设置',
    proxyDesc: '无法访问音乐时可以开启代理',
    proxyHost: '代理地址',
    proxyHostPlaceholder: '请输入代理地址',
    proxyPort: '代理端口',
    proxyPortPlaceholder: '请输入代理端口',
    realIP: 'realIP设置',
    realIPDesc: '由于限制,此项目在国外使用会受到限制可使用realIP参数,传进国内IP解决',
    messages: {
      proxySuccess: '代理设置已保存,重启应用后生效',
      proxyError: '请检查输入是否正确',
      realIPSuccess: '真实IP设置已保存',
      realIPError: '请输入有效的IP地址'
    }
  },
  system: {
    cache: '缓存管理',
    cacheDesc: '清除缓存',
    cacheClearTitle: '请选择要清除的缓存类型:',
    cacheTypes: {
      history: {
        label: '播放历史',
        description: '清除播放过的歌曲记录'
      },
      favorite: {
        label: '收藏记录',
        description: '清除本地收藏的歌曲记录(不会影响云端收藏)'
      },
      user: {
        label: '用户数据',
        description: '清除登录信息和用户相关数据'
      },
      settings: {
        label: '应用设置',
        description: '清除应用的所有自定义设置'
      },
      downloads: {
        label: '下载记录',
        description: '清除下载历史记录(不会删除已下载的文件)'
      },
      resources: {
        label: '音乐资源',
        description: '清除已加载的音乐文件、歌词等资源缓存'
      },
      lyrics: {
        label: '歌词资源',
        description: '清除已加载的歌词资源缓存'
      }
    },
    restart: '重启',
    restartDesc: '重启应用',
    messages: {
      clearSuccess: '清除成功,部分设置在重启后生效'
    }
  },
  about: {
    version: '版本',
    checkUpdate: '检查更新',
    checking: '检查中...',
    latest: '当前已是最新版本',
    hasUpdate: '发现新版本',
    gotoUpdate: '前往更新',
    gotoGithub: '前往 Github',
    author: '作者',
    authorDesc: 'algerkong 点个star🌟呗',
    messages: {
      checkError: '检查更新失败,请稍后重试'
    }
  },
  validation: {
    selectProxyProtocol: '请选择代理协议',
    proxyHost: '请输入代理地址',
    portNumber: '请输入有效的端口号(1-65535)'
  },
  lyricSettings: {
    title: '歌词设置',
    tabs: {
      display: '显示',
      interface: '界面',
      typography: '文字',
      background: '背景',
      mobile: '移动端'
    },
    pureMode: '纯净模式',
    hideCover: '隐藏封面',
    centerDisplay: '居中显示',
    showTranslation: '显示翻译',
    hideLyrics: '隐藏歌词',
    hidePlayBar: '隐藏播放栏',
    hideMiniPlayBar: '隐藏迷你播放栏',
    showMiniPlayBar: '显示迷你播放栏',
    backgroundTheme: '背景主题',
    themeOptions: {
      default: '默认',
      light: '亮色',
      dark: '暗色'
    },
    fontSize: '字体大小',
    fontSizeMarks: {
      small: '小',
      medium: '中',
      large: '大'
    },
    fontWeight: '字体粗细',
    fontWeightMarks: {
      thin: '细',
      normal: '常规',
      bold: '粗'
    },
    letterSpacing: '字间距',
    letterSpacingMarks: {
      compact: '紧凑',
      default: '默认',
      loose: '宽松'
    },
    lineHeight: '行高',
    lineHeightMarks: {
      compact: '紧凑',
      default: '默认',
      loose: '宽松'
    },
    contentWidth: '内容区宽度',
    mobileLayout: '移动端布局',
    layoutOptions: {
      default: '默认',
      ios: 'iOS风格',
      android: '安卓风格'
    },
    mobileCoverStyle: '封面样式',
    coverOptions: {
      record: '唱片',
      square: '方形',
      full: '全屏'
    },
    lyricLines: '歌词行数',
    mobileUnavailable: '此设置仅在移动端可用',
    // 背景设置
    background: {
      useCustomBackground: '使用自定义背景',
      backgroundMode: '背景模式',
      modeOptions: {
        solid: '纯色',
        gradient: '渐变',
        image: '图片',
        css: 'CSS'
      },
      solidColor: '选择颜色',
      presetColors: '预设颜色',
      customColor: '自定义颜色',
      gradientEditor: '渐变编辑器',
      gradientColors: '渐变颜色',
      gradientDirection: '渐变方向',
      directionOptions: {
        toBottom: '上到下',
        toRight: '左到右',
        toBottomRight: '左上到右下',
        angle45: '45度',
        toTop: '下到上',
        toLeft: '右到左'
      },
      addColor: '添加颜色',
      removeColor: '移除颜色',
      imageUpload: '上传图片',
      imagePreview: '图片预览',
      clearImage: '清除图片',
      imageBlur: '模糊度',
      imageBrightness: '明暗度',
      customCss: '自定义 CSS 样式',
      customCssPlaceholder: '输入 CSS 样式,如: background: linear-gradient(...)',
      customCssHelp: '支持任意 CSS background 属性',
      reset: '重置为默认',
      fileSizeLimit: '图片大小限制: 20MB',
      invalidImageFormat: '无效的图片格式',
      imageTooLarge: '图片过大,请选择小于 20MB 的图片'
    }
  },
  translationEngine: '歌詞翻譯引擎',
  translationEngineOptions: {
    none: '关闭',
    opencc: 'OpenCC 繁化'
  },
  themeColor: {
    title: '歌词主题色',
    presetColors: '预设颜色',
    customColor: '自定义颜色',
    preview: '预览效果',
    previewText: '歌词效果',
    colorNames: {
      'spotify-green': 'Spotify 绿',
      'apple-blue': '苹果蓝',
      'youtube-red': 'YouTube 红',
      orange: '活力橙',
      purple: '神秘紫',
      pink: '樱花粉'
    },
    tooltips: {
      openColorPicker: '打开色板',
      closeColorPicker: '关闭色板'
    },
    placeholder: '#1db954'
  },
  shortcutSettings: {
    title: '快捷键设置',
    shortcut: '快捷键',
    shortcutDesc: '自定义快捷键',
    shortcutConflict: '快捷键冲突',
    inputPlaceholder: '点击输入快捷键',
    resetShortcuts: '恢复默认',
    disableAll: '全部禁用',
    enableAll: '全部启用',
    togglePlay: '播放/暂停',
    prevPlay: '上一首',
    nextPlay: '下一首',
    volumeUp: '音量增加',
    volumeDown: '音量减少',
    toggleFavorite: '收藏/取消收藏',
    toggleWindow: '显示/隐藏窗口',
    scopeGlobal: '全局',
    scopeApp: '应用内',
    enabled: '启用',
    disabled: '禁用',
    messages: {
      resetSuccess: '已恢复默认快捷键,请记得保存',
      conflict: '存在冲突的快捷键,请重新设置',
      saveSuccess: '快捷键设置已保存',
      saveError: '保存快捷键失败,请重试',
      cancelEdit: '已取消修改',
      disableAll: '已禁用所有快捷键,请记得保存',
      enableAll: '已启用所有快捷键,请记得保存'
    }
  },
  remoteControl: {
    title: '远程控制',
    enable: '启用远程控制',
    port: '服务端口',
    allowedIps: '允许的IP地址',
    addIp: '添加IP',
    emptyListHint: '空列表表示允许所有IP访问',
    saveSuccess: '远程控制设置已保存',
    accessInfo: '远程控制访问地址:'
  },
  cookie: {
    title: 'Cookie设置',
    description: '请输入网易云音乐的Cookie:',
    placeholder: '请粘贴完整的Cookie...',
    help: {
      format: 'Cookie通常以 "MUSIC_U=" 开头',
      source: '可以从浏览器开发者工具的网络请求中获取',
      storage: 'Cookie设置后将自动保存到本地存储'
    },
    action: {
      save: '保存Cookie',
      paste: '粘贴',
      clear: '清空'
    },
    validation: {
      required: '请输入Cookie',
      format: 'Cookie格式可能不正确,请检查是否包含MUSIC_U'
    },
    message: {
      saveSuccess: 'Cookie保存成功',
      saveError: 'Cookie保存失败',
      pasteSuccess: '粘贴成功',
      pasteError: '粘贴失败,请手动复制'
    },
    info: {
      length: '当前长度:{length} 字符'
    }
  }
};


================================================
FILE: src/i18n/lang/zh-CN/songItem.ts
================================================
export default {
  menu: {
    play: '播放',
    playNext: '下一首播放',
    download: '下载歌曲',
    addToPlaylist: '添加到歌单',
    favorite: '喜欢',
    unfavorite: '取消喜欢',
    removeFromPlaylist: '从歌单中删除',
    dislike: '不喜欢',
    undislike: '取消不喜欢'
  },
  message: {
    downloading: '正在下载中,请稍候...',
    downloadFailed: '下载失败',
    downloadQueued: '已加入下载队列',
    addedToNextPlay: '已添加到下一首播放',
    getUrlFailed: '获取音乐下载地址失败,请检查是否登录'
  },
  dialog: {
    dislike: {
      title: '提示!',
      content: '确认不喜欢这首歌吗?再次进入将从每日推荐中排除。',
      positiveText: '不喜欢',
      negativeText: '取消'
    }
  }
};


================================================
FILE: src/i18n/lang/zh-CN/user.ts
================================================
export default {
  profile: {
    followers: '粉丝',
    following: '关注',
    level: '等级'
  },
  playlist: {
    created: '创
Download .txt
gitextract_wrew8kq0/

├── .github/
│   ├── CODEOWNERS
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug-report.zh-CN.yml
│   │   ├── config.yml
│   │   └── feature-report.zh-CN.yml
│   ├── PULL_REQUEST_TEMPLATE.md
│   ├── dependabot.yml
│   ├── issue-shoot.md
│   └── workflows/
│       ├── build.yml
│       └── deploy.yml
├── .gitignore
├── .husky/
│   ├── pre-commit
│   └── pre-push
├── .prettierignore
├── CHANGELOG.md
├── DEV.md
├── LICENSE
├── README.md
├── android/
│   └── .gitignore
├── build/
│   ├── entitlements.mac.plist
│   ├── icon.icns
│   └── installer.nsh
├── dev-app-update.yml
├── docs/
│   └── custom-api-readme.md
├── electron.vite.config.ts
├── eslint.config.mjs
├── package.json
├── postcss.config.js
├── prettier.config.js
├── resources/
│   ├── html/
│   │   └── remote-control.html
│   ├── icon.icns
│   └── manifest.json
├── src/
│   ├── i18n/
│   │   ├── lang/
│   │   │   ├── en-US/
│   │   │   │   ├── artist.ts
│   │   │   │   ├── bilibili.ts
│   │   │   │   ├── common.ts
│   │   │   │   ├── comp.ts
│   │   │   │   ├── donation.ts
│   │   │   │   ├── download.ts
│   │   │   │   ├── favorite.ts
│   │   │   │   ├── history.ts
│   │   │   │   ├── login.ts
│   │   │   │   ├── player.ts
│   │   │   │   ├── search.ts
│   │   │   │   ├── settings.ts
│   │   │   │   ├── songItem.ts
│   │   │   │   └── user.ts
│   │   │   ├── ja-JP/
│   │   │   │   ├── artist.ts
│   │   │   │   ├── bilibili.ts
│   │   │   │   ├── common.ts
│   │   │   │   ├── comp.ts
│   │   │   │   ├── donation.ts
│   │   │   │   ├── download.ts
│   │   │   │   ├── favorite.ts
│   │   │   │   ├── history.ts
│   │   │   │   ├── login.ts
│   │   │   │   ├── player.ts
│   │   │   │   ├── search.ts
│   │   │   │   ├── settings.ts
│   │   │   │   ├── songItem.ts
│   │   │   │   └── user.ts
│   │   │   ├── ko-KR/
│   │   │   │   ├── artist.ts
│   │   │   │   ├── bilibili.ts
│   │   │   │   ├── common.ts
│   │   │   │   ├── comp.ts
│   │   │   │   ├── donation.ts
│   │   │   │   ├── download.ts
│   │   │   │   ├── favorite.ts
│   │   │   │   ├── history.ts
│   │   │   │   ├── login.ts
│   │   │   │   ├── player.ts
│   │   │   │   ├── search.ts
│   │   │   │   ├── settings.ts
│   │   │   │   ├── songItem.ts
│   │   │   │   └── user.ts
│   │   │   ├── zh-CN/
│   │   │   │   ├── artist.ts
│   │   │   │   ├── bilibili.ts
│   │   │   │   ├── common.ts
│   │   │   │   ├── comp.ts
│   │   │   │   ├── donation.ts
│   │   │   │   ├── download.ts
│   │   │   │   ├── favorite.ts
│   │   │   │   ├── history.ts
│   │   │   │   ├── login.ts
│   │   │   │   ├── player.ts
│   │   │   │   ├── search.ts
│   │   │   │   ├── settings.ts
│   │   │   │   ├── songItem.ts
│   │   │   │   └── user.ts
│   │   │   └── zh-Hant/
│   │   │       ├── artist.ts
│   │   │       ├── bilibili.ts
│   │   │       ├── common.ts
│   │   │       ├── comp.ts
│   │   │       ├── donation.ts
│   │   │       ├── download.ts
│   │   │       ├── favorite.ts
│   │   │       ├── history.ts
│   │   │       ├── login.ts
│   │   │       ├── player.ts
│   │   │       ├── search.ts
│   │   │       ├── settings.ts
│   │   │       ├── songItem.ts
│   │   │       └── user.ts
│   │   ├── languages.ts
│   │   ├── main.ts
│   │   ├── renderer.ts
│   │   └── utils.ts
│   ├── main/
│   │   ├── index.ts
│   │   ├── lyric.ts
│   │   ├── modules/
│   │   │   ├── cache.ts
│   │   │   ├── config.ts
│   │   │   ├── deviceInfo.ts
│   │   │   ├── fileManager.ts
│   │   │   ├── fonts.ts
│   │   │   ├── loginWindow.ts
│   │   │   ├── lxMusicHttp.ts
│   │   │   ├── otherApi.ts
│   │   │   ├── remoteControl.ts
│   │   │   ├── shortcuts.ts
│   │   │   ├── tray.ts
│   │   │   ├── update.ts
│   │   │   ├── window-size.ts
│   │   │   └── window.ts
│   │   ├── server.ts
│   │   ├── set.json
│   │   └── unblockMusic.ts
│   ├── preload/
│   │   ├── index.d.ts
│   │   └── index.ts
│   └── renderer/
│       ├── App.vue
│       ├── api/
│       │   ├── artist.ts
│       │   ├── bilibili.ts
│       │   ├── donation.ts
│       │   ├── gdmusic.ts
│       │   ├── home.ts
│       │   ├── list.ts
│       │   ├── login.ts
│       │   ├── lxMusicStrategy.ts
│       │   ├── music.ts
│       │   ├── musicParser.ts
│       │   ├── mv.ts
│       │   ├── parseFromCustomApi.ts
│       │   ├── playlist.ts
│       │   ├── search.ts
│       │   └── user.ts
│       ├── assets/
│       │   ├── css/
│       │   │   └── base.css
│       │   └── icon/
│       │       ├── iconfont.css
│       │       ├── iconfont.js
│       │       └── iconfont.json
│       ├── components/
│       │   ├── Coffee.vue
│       │   ├── EQControl.vue
│       │   ├── LanguageSwitcher.vue
│       │   ├── MusicList.vue
│       │   ├── MvPlayer.vue
│       │   ├── ShortcutToast.vue
│       │   ├── TrafficWarningDrawer.vue
│       │   ├── common/
│       │   │   ├── AlbumItem.vue
│       │   │   ├── ArtistDrawer.vue
│       │   │   ├── BilibiliItem.vue
│       │   │   ├── DisclaimerModal.vue
│       │   │   ├── DonationList.vue
│       │   │   ├── DownloadDrawer.vue
│       │   │   ├── InstallAppModal.vue
│       │   │   ├── MobileUpdateModal.vue
│       │   │   ├── MusicListNavigator.ts
│       │   │   ├── PlayBottom.vue
│       │   │   ├── PlayListsItem.vue
│       │   │   ├── PlaylistDrawer.vue
│       │   │   ├── PlaylistItem.vue
│       │   │   ├── ResponsiveModal.vue
│       │   │   ├── SearchItem.vue
│       │   │   ├── SongItem.vue
│       │   │   ├── UpdateModal.vue
│       │   │   └── songItemCom/
│       │   │       ├── BaseSongItem.vue
│       │   │       ├── CompactSongItem.vue
│       │   │       ├── ListSongItem.vue
│       │   │       ├── MiniSongItem.vue
│       │   │       ├── SongItemDropdown.vue
│       │   │       └── StandardSongItem.vue
│       │   ├── cover/
│       │   │   └── Cover3D.vue
│       │   ├── home/
│       │   │   ├── PlaylistType.vue
│       │   │   ├── RecommendAlbum.vue
│       │   │   ├── RecommendSonglist.vue
│       │   │   └── TopBanner.vue
│       │   ├── login/
│       │   │   ├── CookieLogin.vue
│       │   │   ├── QrLogin.vue
│       │   │   └── UidLogin.vue
│       │   ├── lyric/
│       │   │   ├── LyricCorrectionControl.vue
│       │   │   ├── LyricSettings.vue
│       │   │   ├── MusicFull.vue
│       │   │   ├── MusicFullMobile.vue
│       │   │   ├── MusicFullWrapper.vue
│       │   │   └── ThemeColorPanel.vue
│       │   ├── player/
│       │   │   ├── AdvancedControlsPopover.vue
│       │   │   ├── MiniPlayBar.vue
│       │   │   ├── MobilePlayBar.vue
│       │   │   ├── MobilePlayerSettings.vue
│       │   │   ├── PlayBar.vue
│       │   │   ├── PlayingListDrawer.vue
│       │   │   ├── ReparsePopover.vue
│       │   │   ├── SimplePlayBar.vue
│       │   │   ├── SleepTimer.vue
│       │   │   └── SleepTimerTop.vue
│       │   └── settings/
│       │       ├── ClearCacheSettings.vue
│       │       ├── CookieSettingsModal.vue
│       │       ├── MusicSourceSettings.vue
│       │       ├── ProxySettings.vue
│       │       ├── ServerSetting.vue
│       │       └── ShortcutSettings.vue
│       ├── const/
│       │   └── bar-const.ts
│       ├── directive/
│       │   ├── index.ts
│       │   └── loading/
│       │       ├── index.ts
│       │       └── index.vue
│       ├── hooks/
│       │   ├── AlbumHistoryHook.ts
│       │   ├── IndexDBHook.ts
│       │   ├── MusicHistoryHook.ts
│       │   ├── MusicHook.ts
│       │   ├── PlaylistHistoryHook.ts
│       │   ├── useArtist.ts
│       │   ├── useDownload.ts
│       │   ├── usePlayMode.ts
│       │   ├── usePlayerHooks.ts
│       │   ├── useSongItem.ts
│       │   └── useZoom.ts
│       ├── index.css
│       ├── index.html
│       ├── layout/
│       │   ├── AppLayout.vue
│       │   ├── MiniLayout.vue
│       │   ├── MobileLayout.vue
│       │   └── components/
│       │       ├── AppMenu.vue
│       │       ├── MobileHeader.vue
│       │       ├── SearchBar.vue
│       │       ├── TitleBar.vue
│       │       └── index.ts
│       ├── main.ts
│       ├── router/
│       │   ├── home.ts
│       │   ├── index.ts
│       │   └── other.ts
│       ├── services/
│       │   ├── LxMusicSourceRunner.ts
│       │   ├── SongSourceConfigManager.ts
│       │   ├── audioService.ts
│       │   ├── eqService.ts
│       │   ├── lyricTranslation.ts
│       │   ├── playbackRequestManager.ts
│       │   ├── preloadService.ts
│       │   └── translation-engines/
│       │       ├── index.ts
│       │       └── opencc.ts
│       ├── shims-vue.d.ts
│       ├── store/
│       │   ├── index.ts
│       │   └── modules/
│       │       ├── favorite.ts
│       │       ├── intelligenceMode.ts
│       │       ├── lyric.ts
│       │       ├── menu.ts
│       │       ├── music.ts
│       │       ├── player.ts
│       │       ├── playerCore.ts
│       │       ├── playlist.ts
│       │       ├── recommend.ts
│       │       ├── search.ts
│       │       ├── settings.ts
│       │       ├── sleepTimer.ts
│       │       └── user.ts
│       ├── types/
│       │   ├── album.ts
│       │   ├── artist.ts
│       │   ├── bilibili.ts
│       │   ├── day_recommend.ts
│       │   ├── electron.d.ts
│       │   ├── index.ts
│       │   ├── list.ts
│       │   ├── listDetail.ts
│       │   ├── lxMusic.ts
│       │   ├── lyric.ts
│       │   ├── music.ts
│       │   ├── mv.ts
│       │   ├── opencc-rust.d.ts
│       │   ├── playlist.ts
│       │   ├── search.ts
│       │   ├── singer.ts
│       │   └── user.ts
│       ├── utils/
│       │   ├── appShortcuts.ts
│       │   ├── auth.ts
│       │   ├── fileOperation.ts
│       │   ├── index.ts
│       │   ├── linearColor.ts
│       │   ├── lxCrypto.ts
│       │   ├── playerUtils.ts
│       │   ├── request.ts
│       │   ├── request_music.ts
│       │   ├── shortcutToast.ts
│       │   ├── theme.ts
│       │   ├── update.ts
│       │   └── yrcParser.ts
│       ├── views/
│       │   ├── artist/
│       │   │   └── detail.vue
│       │   ├── bilibili/
│       │   │   └── BilibiliPlayer.vue
│       │   ├── download/
│       │   │   └── DownloadPage.vue
│       │   ├── favorite/
│       │   │   └── index.vue
│       │   ├── heatmap/
│       │   │   └── index.vue
│       │   ├── history/
│       │   │   └── index.vue
│       │   ├── historyAndFavorite/
│       │   │   └── index.vue
│       │   ├── home/
│       │   │   └── index.vue
│       │   ├── list/
│       │   │   └── index.vue
│       │   ├── login/
│       │   │   └── index.vue
│       │   ├── lyric/
│       │   │   └── index.vue
│       │   ├── mobile-search/
│       │   │   └── index.vue
│       │   ├── mobile-search-result/
│       │   │   └── index.vue
│       │   ├── music/
│       │   │   ├── HistoryRecommend.vue
│       │   │   └── MusicListPage.vue
│       │   ├── mv/
│       │   │   └── index.vue
│       │   ├── playlist/
│       │   │   └── ImportPlaylist.vue
│       │   ├── search/
│       │   │   └── index.vue
│       │   ├── set/
│       │   │   ├── SettingItem.vue
│       │   │   ├── SettingNav.vue
│       │   │   ├── SettingSection.vue
│       │   │   └── index.vue
│       │   ├── toplist/
│       │   │   └── index.vue
│       │   └── user/
│       │       ├── detail.vue
│       │       ├── followers.vue
│       │       ├── follows.vue
│       │       └── index.vue
│       └── vite-env.d.ts
├── tailwind.config.js
├── tsconfig.json
├── tsconfig.node.json
├── tsconfig.web.json
└── vite.config.ts
Download .txt
SYMBOL INDEX (519 symbols across 82 files)

FILE: src/i18n/languages.ts
  constant LANGUAGE_DISPLAY_NAMES (line 4) | const LANGUAGE_DISPLAY_NAMES: Record<string, string> = {
  constant DEFAULT_LANGUAGE (line 13) | const DEFAULT_LANGUAGE = 'zh-CN';
  constant FALLBACK_LANGUAGE (line 16) | const FALLBACK_LANGUAGE = 'en-US';
  constant LANGUAGE_PRIORITY (line 19) | const LANGUAGE_PRIORITY: Record<string, number> = {

FILE: src/i18n/main.ts
  type Language (line 7) | type Language = keyof typeof messages;
  method locale (line 13) | get locale() {
  method locale (line 16) | set locale(value: Language) {
  method t (line 19) | t(key: string) {

FILE: src/main/index.ts
  function initialize (line 31) | function initialize(configStore: any) {

FILE: src/main/modules/cache.ts
  type LyricData (line 4) | interface LyricData {
  type StoreSchema (line 10) | interface StoreSchema {
  class CacheManager (line 14) | class CacheManager {
    method constructor (line 17) | constructor() {
    method cacheLyric (line 26) | async cacheLyric(id: number, data: any) {
    method getCachedLyric (line 42) | async getCachedLyric(id: number) {
    method clearLyricCache (line 63) | async clearLyricCache() {
  function initializeCacheManager (line 76) | function initializeCacheManager() {

FILE: src/main/modules/config.ts
  type SetConfig (line 7) | type SetConfig = {
  type StoreType (line 30) | interface StoreType {
  function initializeConfig (line 40) | function initializeConfig() {
  function getStore (line 81) | function getStore() {

FILE: src/main/modules/deviceInfo.ts
  function getDeviceId (line 12) | function getDeviceId(): string {
  function getSystemInfo (line 55) | function getSystemInfo() {

FILE: src/main/modules/fileManager.ts
  constant MAX_CONCURRENT_DOWNLOADS (line 17) | const MAX_CONCURRENT_DOWNLOADS = 3;
  function initializeFileManager (line 43) | function initializeFileManager() {
  function handleDownloadRequest (line 359) | function handleDownloadRequest(
  function processDownloadQueue (line 407) | async function processDownloadQueue(event: Electron.IpcMainEvent) {
  function sanitizeFilename (line 426) | function sanitizeFilename(filename: string): string {
  function downloadMusic (line 437) | async function downloadMusic(
  function parseLyrics (line 887) | function parseLyrics(lyricsText: string): Map<string, string> {
  function mergeLyrics (line 910) | function mergeLyrics(

FILE: src/main/modules/fonts.ts
  function cleanFontName (line 9) | function cleanFontName(fontName: string): string {
  function getSystemFonts (line 19) | async function getSystemFonts(): Promise<string[]> {
  function initializeFonts (line 37) | function initializeFonts() {

FILE: src/main/modules/loginWindow.ts
  function initializeLoginWindow (line 95) | function initializeLoginWindow() {

FILE: src/main/modules/lxMusicHttp.ts
  type LxHttpRequest (line 9) | interface LxHttpRequest {
  type LxHttpResponse (line 22) | interface LxHttpResponse {

FILE: src/main/modules/otherApi.ts
  function initializeOtherApi (line 7) | function initializeOtherApi() {

FILE: src/main/modules/remoteControl.ts
  type RemoteControlConfig (line 11) | interface RemoteControlConfig {
  function getLocalIpAddresses (line 31) | function getLocalIpAddresses(): string[] {
  function initializeRemoteControl (line 50) | function initializeRemoteControl(mainWindow: Electron.BrowserWindow) {
  function startServer (line 102) | function startServer(config: RemoteControlConfig) {
  function stopServer (line 140) | function stopServer() {
  function setupRoutes (line 150) | function setupRoutes(app: express.Application) {

FILE: src/main/modules/shortcuts.ts
  type ShortcutConfig (line 11) | interface ShortcutConfig {
  type ShortcutsConfig (line 17) | interface ShortcutsConfig {
  function registerShortcuts (line 35) | function registerShortcuts(
  function initializeShortcuts (line 100) | function initializeShortcuts(mainWindow: Electron.BrowserWindow) {

FILE: src/main/modules/tray.ts
  type SongInfo (line 17) | interface SongInfo {
  constant LANGUAGES (line 37) | const LANGUAGES = getLanguageOptions();
  function updatePlayState (line 40) | function updatePlayState(playing: boolean) {
  function getArtistString (line 50) | function getArtistString(song: SongInfo | null): string {
  function getSongTitle (line 56) | function getSongTitle(song: SongInfo | null): string {
  function getTruncatedSongTitle (line 63) | function getTruncatedSongTitle(song: SongInfo | null, maxLength: number ...
  function updateCurrentSong (line 70) | function updateCurrentSong(song: SongInfo | null) {
  function getProperIconSize (line 80) | function getProperIconSize() {
  function updateStatusBarTray (line 88) | function updateStatusBarTray() {
  function updateTrayMenu (line 141) | function updateTrayMenu(mainWindow: BrowserWindow) {
  function initializeStatusBarTray (line 335) | function initializeStatusBarTray(mainWindow: BrowserWindow) {
  function initializeTray (line 406) | function initializeTray(iconPath: string, mainWindow: BrowserWindow) {

FILE: src/main/modules/update.ts
  function setupUpdateHandlers (line 7) | function setupUpdateHandlers(_mainWindow: BrowserWindow) {

FILE: src/main/modules/window-size.ts
  constant DEFAULT_MAIN_WIDTH (line 7) | const DEFAULT_MAIN_WIDTH = 1200;
  constant DEFAULT_MAIN_HEIGHT (line 8) | const DEFAULT_MAIN_HEIGHT = 780;
  constant DEFAULT_MINI_WIDTH (line 9) | const DEFAULT_MINI_WIDTH = 340;
  constant DEFAULT_MINI_HEIGHT (line 10) | const DEFAULT_MINI_HEIGHT = 64;
  constant DEFAULT_MINI_EXPANDED_HEIGHT (line 11) | const DEFAULT_MINI_EXPANDED_HEIGHT = 400;
  constant WINDOW_STATE_KEY (line 14) | const WINDOW_STATE_KEY = 'windowState';
  constant MIN_WIDTH (line 17) | let MIN_WIDTH = Math.round(DEFAULT_MAIN_WIDTH * 0.5);
  constant MIN_HEIGHT (line 18) | let MIN_HEIGHT = Math.round(DEFAULT_MAIN_HEIGHT * 0.5);
  type WindowState (line 26) | interface WindowState {
  class WindowSizeManager (line 38) | class WindowSizeManager {
    method constructor (line 44) | constructor() {
    method initialize (line 53) | initialize(): void {
    method setMainWindow (line 72) | setMainWindow(win: BrowserWindow): void {
    method initMinimumWindowSize (line 92) | private initMinimumWindowSize(): void {
    method setupEventListeners (line 120) | private setupEventListeners(win: BrowserWindow): void {
    method enforceCorrectSize (line 170) | private enforceCorrectSize(win: BrowserWindow): void {
    method getWindowOptions (line 275) | getWindowOptions(): Electron.BrowserWindowConstructorOptions {
    method applyInitialState (line 317) | applyInitialState(win: BrowserWindow): void {
    method saveWindowState (line 345) | saveWindowState(win: BrowserWindow): WindowState {
    method getWindowState (line 428) | getWindowState(): WindowState | null {
    method isPositionVisible (line 453) | isPositionVisible(x: number, y: number): boolean {
    method calculateContentZoomFactor (line 478) | calculateContentZoomFactor(): number {
    method applyContentZoom (line 528) | applyContentZoom(win: BrowserWindow): void {
    method setupIPCHandlers (line 548) | setupIPCHandlers(): void {

FILE: src/main/modules/window.ts
  function setAppQuitting (line 47) | function setAppQuitting(quitting: boolean) {
  function initializeProxy (line 54) | function initializeProxy() {
  function setThumbarButtons (line 77) | function setThumbarButtons(window: BrowserWindow) {
  function initializeWindowManager (line 110) | function initializeWindowManager() {
  function createMainWindow (line 291) | function createMainWindow(icon: Electron.NativeImage): BrowserWindow {

FILE: src/main/server.ts
  function checkPortAvailable (line 29) | function checkPortAvailable(port: number): Promise<boolean> {
  function startMusicApi (line 44) | async function startMusicApi(): Promise<void> {

FILE: src/main/unblockMusic.ts
  type Platform (line 3) | type Platform = 'qq' | 'migu' | 'kugou' | 'kuwo' | 'pyncmd' | 'joox' | '...
  type SongData (line 5) | interface SongData {
  type ResponseData (line 13) | interface ResponseData {
  type UnblockResult (line 22) | interface UnblockResult {
  constant ALL_PLATFORMS (line 33) | const ALL_PLATFORMS: Platform[] = ['migu', 'kugou', 'kuwo', 'pyncmd', 'b...
  function ensureDataStructure (line 39) | function ensureDataStructure(data: any): any {

FILE: src/preload/index.d.ts
  type API (line 3) | interface API {
  type IpcRenderer (line 34) | interface IpcRenderer {
  type Window (line 42) | interface Window {

FILE: src/renderer/api/bilibili.ts
  type ISearchParams (line 6) | interface ISearchParams {
  type IBilibiliResponse (line 60) | interface IBilibiliResponse<T> {

FILE: src/renderer/api/donation.ts
  type Donor (line 3) | interface Donor {

FILE: src/renderer/api/gdmusic.ts
  type GDMusicResponse (line 8) | interface GDMusicResponse {
  type ParsedMusicResult (line 17) | interface ParsedMusicResult {
  type GDMusicUrlResult (line 128) | interface GDMusicUrlResult {
  function searchAndGetUrl (line 144) | async function searchAndGetUrl(

FILE: src/renderer/api/home.ts
  type IHotSingerParams (line 10) | interface IHotSingerParams {
  type IRecommendMusicParams (line 15) | interface IRecommendMusicParams {

FILE: src/renderer/api/list.ts
  type IListByTagParams (line 5) | interface IListByTagParams {
  type IListByCatParams (line 11) | interface IListByCatParams {
  function getListByTag (line 18) | function getListByTag(params: IListByTagParams) {
  function getListByCat (line 23) | function getListByCat(params: IListByCatParams) {
  function getRecommendList (line 30) | function getRecommendList(limit: number = 30) {
  function getListDetail (line 35) | function getListDetail(id: number | string) {
  function getAlbum (line 40) | function getAlbum(id: number | string) {
  function getToplist (line 45) | function getToplist() {

FILE: src/renderer/api/login.ts
  function getQrKey (line 5) | function getQrKey() {
  function createQr (line 11) | function createQr(key: any) {
  function checkQr (line 17) | function checkQr(key: any) {
  function getLoginStatus (line 23) | function getLoginStatus() {
  function getUserDetail (line 29) | function getUserDetail() {
  function logout (line 35) | function logout() {
  function loginByCellphone (line 41) | function loginByCellphone(phone: string, password: string) {
  function loginByUid (line 50) | function loginByUid(uid: string | number) {

FILE: src/renderer/api/lxMusicStrategy.ts
  class LxMusicStrategy (line 140) | class LxMusicStrategy {
    method canHandle (line 147) | canHandle(sources: string[], settingsStore?: any): boolean {
    method parse (line 169) | async parse(

FILE: src/renderer/api/music.ts
  function getMusicListByType (line 135) | function getMusicListByType(type: string, id: string) {
  function getAlbumDetail (line 148) | function getAlbumDetail(id: string) {
  function getPlaylistDetail (line 162) | function getPlaylistDetail(id: string) {
  function subscribePlaylist (line 172) | function subscribePlaylist(params: { t: number; id: number }) {
  function subscribeAlbum (line 184) | function subscribeAlbum(params: { t: number; id: number }) {
  function getHistoryRecommendDates (line 195) | function getHistoryRecommendDates() {
  function getHistoryRecommendSongs (line 206) | function getHistoryRecommendSongs(date: string) {
  function getIntelligenceList (line 218) | function getIntelligenceList(params: { id: number; pid: number; sid?: nu...

FILE: src/renderer/api/musicParser.ts
  type MusicParseResult (line 21) | interface MusicParseResult {
  constant CACHE_CONFIG (line 35) | const CACHE_CONFIG = {
  class CacheManager (line 53) | class CacheManager {
    method getCachedMusicUrl (line 57) | static async getCachedMusicUrl(
    method setCachedMusicUrl (line 94) | static async setCachedMusicUrl(
    method isInFailedCache (line 116) | static isInFailedCache(id: number, strategyName: string): boolean {
    method addFailedCache (line 133) | static addFailedCache(id: number, strategyName: string): void {
    method clearFailedCache (line 144) | static clearFailedCache(id: number): void {
    method clearMusicCache (line 160) | static async clearMusicCache(id: number): Promise<void> {
  class RetryHelper (line 186) | class RetryHelper {
    method withRetry (line 190) | static async withRetry<T>(
  type MusicSourceStrategy (line 314) | interface MusicSourceStrategy {
  class CustomApiStrategy (line 329) | class CustomApiStrategy implements MusicSourceStrategy {
    method canHandle (line 333) | canHandle(sources: string[], settingsStore?: any): boolean {
    method parse (line 337) | async parse(id: number, data: SongResult, quality = 'higher'): Promise...
  class BilibiliStrategy (line 369) | class BilibiliStrategy implements MusicSourceStrategy {
    method canHandle (line 373) | canHandle(sources: string[]): boolean {
    method parse (line 377) | async parse(id: number, data: SongResult): Promise<MusicParseResult | ...
  class GDMusicStrategy (line 409) | class GDMusicStrategy implements MusicSourceStrategy {
    method canHandle (line 413) | canHandle(sources: string[]): boolean {
    method parse (line 417) | async parse(id: number, data: SongResult): Promise<MusicParseResult | ...
  class UnblockMusicStrategy (line 449) | class UnblockMusicStrategy implements MusicSourceStrategy {
    method canHandle (line 453) | canHandle(sources: string[]): boolean {
    method parse (line 460) | async parse(
  class MusicSourceStrategyFactory (line 501) | class MusicSourceStrategyFactory {
    method getAvailableStrategies (line 516) | static getAvailableStrategies(sources: string[], settingsStore?: any):...
  class MusicParser (line 560) | class MusicParser {
    method parseMusic (line 567) | static async parseMusic(id: number, data: SongResult): Promise<MusicPa...

FILE: src/renderer/api/mv.ts
  type MvParams (line 5) | interface MvParams {

FILE: src/renderer/api/parseFromCustomApi.ts
  type CustomApiPlugin (line 11) | interface CustomApiPlugin {

FILE: src/renderer/api/playlist.ts
  function importPlaylist (line 7) | function importPlaylist(params: {
  function getImportTaskStatus (line 21) | function getImportTaskStatus(id: string | number) {

FILE: src/renderer/api/search.ts
  type IParams (line 4) | interface IParams {
  type Suggestion (line 20) | interface Suggestion {
  type KugouSuggestionResponse (line 24) | interface KugouSuggestionResponse {
  type NeteaseSuggestResult (line 29) | interface NeteaseSuggestResult {

FILE: src/renderer/api/user.ts
  function getUserDetail (line 5) | function getUserDetail(uid: number) {
  function getUserPlaylist (line 10) | function getUserPlaylist(uid: number, limit: number = 30, offset: number...
  function getUserRecord (line 16) | function getUserRecord(uid: number, type: number = 0) {
  function getRecentSongs (line 25) | function getRecentSongs(limit: number = 100) {
  function getRecentPlaylists (line 34) | function getRecentPlaylists(limit: number = 100) {
  function getRecentAlbums (line 43) | function getRecentAlbums(limit: number = 100) {
  function getUserFollows (line 52) | function getUserFollows(uid: number, limit: number = 30, offset: number ...
  function getUserFollowers (line 57) | function getUserFollowers(uid: number, limit: number = 30, offset: numbe...

FILE: src/renderer/assets/icon/iconfont.js
  function p (line 55) | function p() {
  function e (line 58) | function e() {

FILE: src/renderer/components/common/MusicListNavigator.ts
  function navigateToMusicList (line 10) | function navigateToMusicList(

FILE: src/renderer/const/bar-const.ts
  constant USER_SET_OPTIONS (line 1) | const USER_SET_OPTIONS = [
  constant SEARCH_TYPES (line 24) | const SEARCH_TYPES = [
  constant SEARCH_TYPE (line 47) | const SEARCH_TYPE = {

FILE: src/renderer/directive/loading/index.ts
  function formatterClass (line 28) | function formatterClass(el: HTMLElement, binding: any) {

FILE: src/renderer/hooks/AlbumHistoryHook.ts
  type AlbumHistoryItem (line 5) | interface AlbumHistoryItem {

FILE: src/renderer/hooks/IndexDBHook.ts
  type StoreConfig (line 4) | interface StoreConfig<T extends string> {

FILE: src/renderer/hooks/MusicHook.ts
  constant CORRECTION_KEY (line 607) | const CORRECTION_KEY = 'lyric-correction-map';

FILE: src/renderer/hooks/PlaylistHistoryHook.ts
  type PlaylistHistoryItem (line 5) | interface PlaylistHistoryItem {

FILE: src/renderer/hooks/usePlayMode.ts
  function usePlayMode (line 10) | function usePlayMode() {

FILE: src/renderer/hooks/useSongItem.ts
  function useSongItem (line 14) | function useSongItem(props: { item: SongResult; canRemove?: boolean }) {

FILE: src/renderer/hooks/useZoom.ts
  function useZoom (line 7) | function useZoom() {

FILE: src/renderer/router/index.ts
  function getUserId (line 11) | function getUserId(): string | null {

FILE: src/renderer/services/LxMusicSourceRunner.ts
  class LxMusicSourceRunner (line 79) | class LxMusicSourceRunner {
    method constructor (line 89) | constructor(script: string) {
    method getScriptInfo (line 97) | getScriptInfo(): LxScriptInfo {
    method getSources (line 104) | getSources(): Partial<Record<LxSourceKey, LxSourceConfig>> {
    method initialize (line 111) | async initialize(): Promise<LxInitedData> {
    method executeSandboxed (line 146) | private executeSandboxed(
    method createSandbox (line 177) | private createSandbox(
    method handleHttpRequest (line 352) | private handleHttpRequest(
    method getMusicUrl (line 484) | async getMusicUrl(
    method getLyric (line 565) | async getLyric(source: LxSourceKey, musicInfo: LxMusicInfo): Promise<L...
    method getPic (line 599) | async getPic(source: LxSourceKey, musicInfo: LxMusicInfo): Promise<str...
    method isInitialized (line 633) | isInitialized(): boolean {

FILE: src/renderer/services/SongSourceConfigManager.ts
  type SongSourceConfig (line 14) | type SongSourceConfig = {
  constant STORAGE_KEY_PREFIX (line 25) | const STORAGE_KEY_PREFIX = 'song_source_';
  constant STORAGE_TYPE_KEY_PREFIX (line 26) | const STORAGE_TYPE_KEY_PREFIX = 'song_source_type_';
  class SongSourceConfigManager (line 31) | class SongSourceConfigManager {
    method getConfig (line 35) | static getConfig(songId: number | string): SongSourceConfig | null {
    method setConfig (line 64) | static setConfig(
    method clearConfig (line 88) | static clearConfig(songId: number | string): void {
    method hasConfig (line 100) | static hasConfig(songId: number | string): boolean {
    method isManualConfig (line 107) | static isManualConfig(songId: number | string): boolean {
    method getTriedSources (line 117) | static getTriedSources(songId: number | string): Set<string> {
    method addTriedSource (line 128) | static addTriedSource(songId: number | string, source: string): void {
    method clearTriedSources (line 138) | static clearTriedSources(songId: number | string): void {
    method getTriedSourceDiffs (line 148) | static getTriedSourceDiffs(songId: number | string): Map<string, numbe...
    method setTriedSourceDiff (line 159) | static setTriedSourceDiff(songId: number | string, source: string, dif...
    method findBestMatchingSource (line 168) | static findBestMatchingSource(songId: number | string): { source: stri...
    method clearAllMemoryCache (line 190) | static clearAllMemoryCache(): void {

FILE: src/renderer/services/audioService.ts
  class AudioService (line 6) | class AudioService {
    method constructor (line 54) | constructor() {
    method initMediaSession (line 71) | private initMediaSession() {
    method updateMediaSessionMetadata (line 116) | private updateMediaSessionMetadata(track: SongResult) {
    method updateMediaSessionState (line 142) | private updateMediaSessionState(isPlaying: boolean) {
    method updateMediaSessionPositionState (line 149) | private updateMediaSessionPositionState() {
    method emit (line 167) | private emit(event: string, ...args: any[]) {
    method on (line 174) | on(event: string, callback: Function) {
    method off (line 181) | off(event: string, callback: Function) {
    method isEQEnabled (line 189) | public isEQEnabled(): boolean {
    method setEQEnabled (line 193) | public setEQEnabled(enabled: boolean) {
    method setEQFrequencyGain (line 202) | public setEQFrequencyGain(frequency: string, gain: number) {
    method resetEQ (line 210) | public resetEQ() {
    method getAllEQSettings (line 217) | public getAllEQSettings(): { [key: string]: number } {
    method saveEQSettings (line 221) | private saveEQSettings(frequency: string, gain: number) {
    method loadEQSettings (line 227) | private loadEQSettings(): { [key: string]: number } {
    method disposeEQ (line 232) | private async disposeEQ(keepContext = false) {
    method setupEQ (line 270) | private async setupEQ(sound: Howl) {
    method applyBypassState (line 359) | private applyBypassState() {
    method setOperationLock (line 389) | private setOperationLock(): boolean {
    method releaseOperationLock (line 440) | public releaseOperationLock(): void {
    method forceResetOperationLock (line 458) | public forceResetOperationLock(): void {
    method play (line 474) | public play(
    method getCurrentSound (line 829) | getCurrentSound() {
    method getCurrentTrack (line 833) | getCurrentTrack() {
    method stop (line 837) | stop() {
    method setVolume (line 867) | setVolume(volume: number) {
    method seek (line 871) | seek(time: number) {
    method pause (line 888) | pause() {
    method clearAllListeners (line 905) | clearAllListeners() {
    method getCurrentPreset (line 909) | public getCurrentPreset(): string | null {
    method setCurrentPreset (line 913) | public setCurrentPreset(preset: string): void {
    method setPlaybackRate (line 917) | public setPlaybackRate(rate: number) {
    method getPlaybackRate (line 942) | public getPlaybackRate(): number {
    method applyVolume (line 947) | private applyVolume(volume: number) {
    method isLoading (line 970) | isLoading(): boolean {
    method isActuallyPlaying (line 981) | isActuallyPlaying(): boolean {

FILE: src/renderer/services/eqService.ts
  type HowlSound (line 5) | interface HowlSound {
  type EQSettings (line 13) | interface EQSettings {
  class EQService (line 17) | class EQService {
    method constructor (line 38) | constructor() {
    method initializeUserGestureHandler (line 45) | private initializeUserGestureHandler() {
    method setupAudioContext (line 56) | public async setupAudioContext(howl: Howl) {
    method setEnabled (line 112) | public setEnabled(enabled: boolean) {
    method isEnabled (line 118) | public isEnabled(): boolean {
    method setFrequencyGain (line 123) | public setFrequencyGain(frequency: string, gain: number) {
    method resetEQ (line 132) | public resetEQ() {
    method getAllSettings (line 140) | public getAllSettings(): EQSettings {
    method saveSettings (line 145) | private saveSettings(frequency: string, gain: number) {
    method loadSavedSettings (line 151) | private loadSavedSettings(): EQSettings {
    method getSavedGain (line 156) | private getSavedGain(frequency: string): number {
    method dispose (line 161) | public async dispose() {

FILE: src/renderer/services/lyricTranslation.ts
  function translateLyrics (line 8) | async function translateLyrics(lines: ILyricText[] | undefined) {

FILE: src/renderer/services/playbackRequestManager.ts
  type RequestStatus (line 11) | enum RequestStatus {
  type PlaybackRequest (line 22) | interface PlaybackRequest {
  class PlaybackRequestManager (line 33) | class PlaybackRequestManager {
    method generateRequestId (line 41) | private generateRequestId(): string {
    method createRequest (line 50) | createRequest(song: SongResult): string {
    method activateRequest (line 77) | activateRequest(requestId: string): boolean {
    method completeRequest (line 98) | completeRequest(requestId: string): void {
    method failRequest (line 115) | failRequest(requestId: string): void {
    method cancelRequest (line 129) | cancelRequest(requestId: string): void {
    method cancelAllRequests (line 156) | cancelAllRequests(): void {
    method isRequestValid (line 174) | isRequestValid(requestId: string): boolean {
    method getAbortSignal (line 203) | getAbortSignal(requestId: string): AbortSignal | undefined {
    method getCurrentRequestId (line 211) | getCurrentRequestId(): string | null {
    method getRequest (line 219) | getRequest(requestId: string): PlaybackRequest | undefined {
    method cleanupOldRequests (line 226) | private cleanupOldRequests(): void {
    method reset (line 257) | reset(): void {
    method getDebugInfo (line 268) | getDebugInfo(): {

FILE: src/renderer/services/preloadService.ts
  class PreloadService (line 5) | class PreloadService {
    method load (line 14) | public async load(song: SongResult): Promise<Howl> {
    method _performLoad (line 53) | private async _performLoad(song: SongResult): Promise<Howl> {
    method _createSound (line 82) | private _createSound(url: string): Promise<Howl> {
    method cancel (line 99) | public cancel(songId: string | number) {
    method getPreloadedSound (line 112) | public getPreloadedSound(songId: string | number): Howl | undefined {
    method consume (line 121) | public consume(songId: string | number): Howl | undefined {
    method clearAll (line 134) | public clearAll() {

FILE: src/renderer/services/translation-engines/opencc.ts
  function init (line 6) | async function init(): Promise<void> {
  function convert (line 17) | async function convert(text: string): Promise<string> {
  function convertLines (line 23) | async function convertLines(lines: string[]) {
  function translateLines (line 44) | async function translateLines(lines: ILyricText[]) {
  function ensureOpenccConverter (line 78) | async function ensureOpenccConverter() {

FILE: src/renderer/store/modules/music.ts
  type MusicState (line 3) | interface MusicState {
  method setCurrentMusicList (line 20) | setCurrentMusicList(list: any[], name: string, listInfo: any = null, can...
  method clearCurrentMusicList (line 28) | clearCurrentMusicList() {
  method removeSongFromList (line 36) | removeSongFromList(id: number) {

FILE: src/renderer/store/modules/sleepTimer.ts
  type SleepTimerType (line 8) | enum SleepTimerType {
  type SleepTimerInfo (line 16) | interface SleepTimerInfo {

FILE: src/renderer/store/modules/user.ts
  type UserData (line 9) | interface UserData {
  function getLocalStorageItem (line 14) | function getLocalStorageItem<T>(key: string, defaultValue: T): T {

FILE: src/renderer/types/album.ts
  type IAlbumNew (line 1) | interface IAlbumNew {
  type Album (line 6) | interface Album {
  type Artist2 (line 33) | interface Artist2 {
  type Artist (line 49) | interface Artist {

FILE: src/renderer/types/artist.ts
  type IArtistDetail (line 1) | interface IArtistDetail {
  type User (line 14) | interface User {
  type AvatarDetail (line 53) | interface AvatarDetail {
  type SecondaryExpertIdentiy (line 59) | interface SecondaryExpertIdentiy {
  type IArtist (line 65) | interface IArtist {
  type Rank (line 81) | interface Rank {
  type Identify (line 86) | interface Identify {
  type VipRights (line 92) | interface VipRights {
  type RightsInfoDetailDtoList (line 100) | interface RightsInfoDetailDtoList {

FILE: src/renderer/types/bilibili.ts
  type IBilibiliSearchResult (line 1) | interface IBilibiliSearchResult {
  type IBilibiliVideoDetail (line 28) | interface IBilibiliVideoDetail {
  type IBilibiliPage (line 54) | interface IBilibiliPage {
  type IBilibiliPlayUrl (line 66) | interface IBilibiliPlayUrl {
  type IBilibiliDashItem (line 97) | interface IBilibiliDashItem {

FILE: src/renderer/types/day_recommend.ts
  type IDayRecommend (line 1) | interface IDayRecommend {
  type RecommendReason (line 8) | interface RecommendReason {
  type DailySong (line 15) | interface DailySong {
  type Privilege (line 70) | interface Privilege {
  type ChargeInfoList (line 103) | interface ChargeInfoList {
  type FreeTrialPrivilege (line 110) | interface FreeTrialPrivilege {
  type VideoInfo (line 118) | interface VideoInfo {
  type Video (line 123) | interface Video {
  type OriginSongSimpleDatum (line 134) | interface OriginSongSimpleDatum {
  type Artist (line 141) | interface Artist {
  type H (line 146) | interface H {
  type Al (line 154) | interface Al {
  type Ar (line 163) | interface Ar {

FILE: src/renderer/types/electron.d.ts
  type IElectronAPI (line 1) | interface IElectronAPI {
  type Window (line 22) | interface Window {

FILE: src/renderer/types/index.ts
  type IData (line 1) | interface IData<T> {

FILE: src/renderer/types/list.ts
  type IList (line 1) | interface IList {
  type Playlist (line 9) | interface Playlist {
  type Subscriber (line 48) | interface Subscriber {
  type Creator (line 82) | interface Creator {
  type AvatarDetail (line 116) | interface AvatarDetail {
  type Expert (line 122) | interface Expert {
  type IRecommendList (line 128) | interface IRecommendList {
  type IRecommendItem (line 135) | interface IRecommendItem {

FILE: src/renderer/types/listDetail.ts
  type IListDetail (line 1) | interface IListDetail {
  type Privilege (line 11) | interface Privilege {
  type ChargeInfoList (line 37) | interface ChargeInfoList {
  type FreeTrialPrivilege (line 44) | interface FreeTrialPrivilege {
  type Playlist (line 49) | interface Playlist {
  type TrackId (line 96) | interface TrackId {
  type Track (line 106) | interface Track {
  type H (line 148) | interface H {
  type Al (line 155) | interface Al {
  type Ar (line 164) | interface Ar {
  type Subscriber (line 171) | interface Subscriber {

FILE: src/renderer/types/lxMusic.ts
  type LxScriptInfo (line 10) | type LxScriptInfo = {
  type LxQuality (line 22) | type LxQuality = '128k' | '320k' | 'flac' | 'flac24bit';
  type LxSourceKey (line 33) | type LxSourceKey = 'kw' | 'kg' | 'tx' | 'wy' | 'mg' | 'local';
  type LxSourceConfig (line 38) | type LxSourceConfig = {
  type LxInitedData (line 48) | type LxInitedData = {
  type LxRequestData (line 56) | type LxRequestData = {
  type LxMusicInfo (line 69) | type LxMusicInfo = {
  type LxLyricResult (line 84) | type LxLyricResult = {
  type LxMusicScriptConfig (line 94) | type LxMusicScriptConfig = {
  type LxMusicApiList (line 107) | type LxMusicApiList = {
  constant LX_EVENT_NAMES (line 115) | const LX_EVENT_NAMES = {
  constant LX_SOURCE_NAMES (line 124) | const LX_SOURCE_NAMES: Record<LxSourceKey, string> = {
  constant QUALITY_TO_LX (line 136) | const QUALITY_TO_LX: Record<string, LxQuality> = {

FILE: src/renderer/types/lyric.ts
  type LyricConfig (line 1) | interface LyricConfig {
  constant DEFAULT_LYRIC_CONFIG (line 34) | const DEFAULT_LYRIC_CONFIG: LyricConfig = {
  type ILyric (line 68) | interface ILyric {
  type Lrc (line 78) | interface Lrc {

FILE: src/renderer/types/music.ts
  type Platform (line 2) | type Platform =
  constant DEFAULT_PLATFORMS (line 14) | const DEFAULT_PLATFORMS: Platform[] = [
  type IRecommendMusic (line 23) | interface IRecommendMusic {
  type IWordData (line 29) | interface IWordData {
  type ILyricText (line 36) | interface ILyricText {
  type ILyric (line 45) | interface ILyric {
  type SongResult (line 52) | interface SongResult {
  type Song (line 88) | interface Song {
  type Privilege (line 140) | interface Privilege {
  type ChargeInfoList (line 163) | interface ChargeInfoList {
  type FreeTrialPrivilege (line 170) | interface FreeTrialPrivilege {
  type BMusic (line 175) | interface BMusic {
  type Album (line 187) | interface Album {
  type Artist (line 216) | interface Artist {
  type IPlayMusicUrl (line 231) | interface IPlayMusicUrl {
  type Datum (line 236) | interface Datum {
  type FreeTimeTrialPrivilege (line 259) | interface FreeTimeTrialPrivilege {
  type FreeTrialPrivilege (line 266) | interface FreeTrialPrivilege {
  type IArtists (line 271) | interface IArtists {
  type MusicSourceType (line 285) | type MusicSourceType =

FILE: src/renderer/types/mv.ts
  type IMvItem (line 1) | interface IMvItem {
  type IMvData (line 21) | interface IMvData {
  type Video (line 58) | interface Video {
  type TagSign (line 71) | interface TagSign {
  type Artist (line 79) | interface Artist {
  type IMvUrlData (line 99) | interface IMvUrlData {

FILE: src/renderer/types/playlist.ts
  type IPlayListSort (line 1) | interface IPlayListSort {
  type SortCategories (line 8) | interface SortCategories {
  type SortAll (line 16) | interface SortAll {

FILE: src/renderer/types/search.ts
  type ISearchKeyword (line 1) | interface ISearchKeyword {
  type SearchKeywordData (line 7) | interface SearchKeywordData {
  type IHotSearch (line 18) | interface IHotSearch {
  type Datum (line 24) | interface Datum {
  type ISearchDetail (line 35) | interface ISearchDetail {
  type Result (line 40) | interface Result {
  type User2 (line 57) | interface User2 {
  type User (line 64) | interface User {
  type Talk2 (line 99) | interface Talk2 {
  type Talk (line 105) | interface Talk {
  type ShareCover (line 123) | interface ShareCover {
  type DjRadio2 (line 131) | interface DjRadio2 {
  type DjRadio (line 138) | interface DjRadio {
  type Dj (line 176) | interface Dj {
  type Simquery2 (line 210) | interface Simquery2 {
  type Simquery (line 215) | interface Simquery {
  type Video2 (line 220) | interface Video2 {
  type Video (line 227) | interface Video {
  type Creator2 (line 241) | interface Creator2 {
  type Album3 (line 246) | interface Album3 {
  type Album2 (line 253) | interface Album2 {
  type Artist5 (line 281) | interface Artist5 {
  type Artist4 (line 297) | interface Artist4 {
  type Artist3 (line 315) | interface Artist3 {
  type Artist2 (line 322) | interface Artist2 {
  type PlayList2 (line 339) | interface PlayList2 {
  type PlayList (line 346) | interface PlayList {
  type Track (line 364) | interface Track {
  type HMusic (line 404) | interface HMusic {
  type Album (line 416) | interface Album {
  type Artist (line 441) | interface Artist {
  type Creator (line 455) | interface Creator {
  type Mlog2 (line 465) | interface Mlog2 {
  type Mlog (line 472) | interface Mlog {
  type Resource (line 485) | interface Resource {
  type UserProfile (line 493) | interface UserProfile {
  type MlogExtVO (line 502) | interface MlogExtVO {
  type MlogBaseData (line 517) | interface MlogBaseData {
  type Song2 (line 534) | interface Song2 {
  type KsongInfos (line 542) | interface KsongInfos {
  type _347230 (line 546) | interface _347230 {
  type Song (line 552) | interface Song {
  type Privilege (line 602) | interface Privilege {
  type ChargeInfoList (line 625) | interface ChargeInfoList {
  type FreeTrialPrivilege (line 632) | interface FreeTrialPrivilege {
  type H (line 637) | interface H {
  type Al (line 644) | interface Al {
  type Ar (line 653) | interface Ar {

FILE: src/renderer/types/singer.ts
  type IHotSinger (line 1) | interface IHotSinger {
  type Artist (line 7) | interface Artist {

FILE: src/renderer/types/user.ts
  type IUserDetail (line 1) | interface IUserDetail {
  type IUserFollow (line 17) | interface IUserFollow {
  type ProfileVillageInfo (line 31) | interface ProfileVillageInfo {
  type Binding (line 37) | interface Binding {
  type Profile (line 49) | interface Profile {
  type UserPoint (line 96) | interface UserPoint {

FILE: src/renderer/utils/appShortcuts.ts
  constant ACTION_DELAY (line 12) | const ACTION_DELAY = 300;
  type ShortcutConfig (line 20) | interface ShortcutConfig {
  type ShortcutsConfig (line 26) | interface ShortcutsConfig {
  function handleShortcutAction (line 39) | async function handleShortcutAction(action: string) {
  function matchShortcut (line 157) | function matchShortcut(e: KeyboardEvent, shortcutKey: string): boolean {
  function handleKeyDown (line 189) | function handleKeyDown(e: KeyboardEvent) {
  function updateAppShortcuts (line 207) | function updateAppShortcuts(shortcuts: ShortcutsConfig) {
  function initAppShortcuts (line 214) | function initAppShortcuts() {
  function cleanupAppShortcuts (line 240) | function cleanupAppShortcuts() {
  function useAppShortcuts (line 254) | function useAppShortcuts() {

FILE: src/renderer/utils/auth.ts
  type LoginInfo (line 8) | interface LoginInfo {
  function checkLoginStatus (line 20) | function checkLoginStatus(): LoginInfo {
  function hasPermission (line 63) | function hasPermission(requireAuth: boolean = false): boolean {
  function clearLoginStatus (line 81) | function clearLoginStatus(): void {
  function setLoginStatus (line 93) | function setLoginStatus(loginType: LoginInfo['loginType'], token?: strin...
  function getLoginErrorMessage (line 110) | function getLoginErrorMessage(requireAuth: boolean = false): string {

FILE: src/renderer/utils/linearColor.ts
  type IColor (line 4) | interface IColor {
  type ITextColors (line 9) | interface ITextColors {
  type LyricThemeColor (line 15) | interface LyricThemeColor {
  type LyricSettings (line 22) | interface LyricSettings {
  constant PRESET_LYRIC_COLORS (line 320) | const PRESET_LYRIC_COLORS: LyricThemeColor[] = [

FILE: src/renderer/utils/playerUtils.ts
  function getLocalStorageItem (line 6) | function getLocalStorageItem<T>(key: string, defaultValue: T): T {
  function setLocalStorageItem (line 18) | function setLocalStorageItem<T>(key: string, value: T): void {

FILE: src/renderer/utils/request.ts
  type CustomAxiosRequestConfig (line 10) | interface CustomAxiosRequestConfig extends InternalAxiosRequestConfig {
  constant MAX_RETRIES (line 26) | const MAX_RETRIES = 1;
  constant RETRY_DELAY (line 28) | const RETRY_DELAY = 500;
  constant NO_RETRY_URLS (line 76) | const NO_RETRY_URLS = ['暂时没有'];

FILE: src/renderer/utils/shortcutToast.ts
  type ToastOptions (line 8) | interface ToastOptions {
  function showShortcutToast (line 13) | function showShortcutToast(message: string, iconName = '', options: Toas...
  function showBottomToast (line 50) | function showBottomToast(message: string) {

FILE: src/renderer/utils/theme.ts
  type ThemeType (line 1) | type ThemeType = 'dark' | 'light';

FILE: src/renderer/utils/update.ts
  type GithubReleaseInfo (line 6) | interface GithubReleaseInfo {
  type ProxyNode (line 18) | interface ProxyNode {
  type ProxyResponse (line 27) | interface ProxyResponse {
  type UpdateResult (line 35) | interface UpdateResult {
  constant CACHE_KEY (line 51) | const CACHE_KEY = 'github_proxy_nodes';
  constant CACHE_EXPIRE_TIME (line 52) | const CACHE_EXPIRE_TIME = 1000 * 60 * 10;
  constant REQUEST_TIMEOUT (line 55) | const REQUEST_TIMEOUT = 2000;

FILE: src/renderer/utils/yrcParser.ts
  type WordData (line 4) | interface WordData {
  type LyricLine (line 18) | interface LyricLine {
  type MetaData (line 32) | interface MetaData {
  type ParsedLyrics (line 42) | interface ParsedLyrics {
  class LyricParseError (line 52) | class LyricParseError extends Error {
    method constructor (line 53) | constructor(
  type ParseResult (line 65) | type ParseResult<T> =
  constant METADATA_PATTERN (line 70) | const METADATA_PATTERN = /^\{("t":|"c":)/;
  constant LINE_TIME_PATTERN (line 71) | const LINE_TIME_PATTERN = /^\[(\d+),(\d+)\](.+)$/;
  constant LRC_TIME_PATTERN (line 72) | const LRC_TIME_PATTERN = /^\[(\d{2}):(\d{2})\.(\d{2,3})\](.*)$/;
  constant WORD_PATTERN (line 73) | const WORD_PATTERN = /\((\d+),(\d+),\d+\)([^(]*?)(?=\(|$)/g;
Condensed preview — 322 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,828K chars).
[
  {
    "path": ".github/CODEOWNERS",
    "chars": 13,
    "preview": "* @algerkong\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug-report.zh-CN.yml",
    "chars": 1472,
    "preview": "name: 反馈 Bug\ndescription: 通过 github 模板进行 Bug 反馈。\ntitle: '描述问题的标题'\nbody:\n  - type: markdown\n    attributes:\n      value: "
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "chars": 72,
    "preview": "blank_issues_enabled: true\ncontact_links:\n  - name:\n    url:\n    about:\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature-report.zh-CN.yml",
    "chars": 694,
    "preview": "name: 反馈新功能\ndescription: 通过 github 模板进行新功能反馈。\ntitle: '描述问题的标题'\nbody:\n  - type: markdown\n    attributes:\n      value: |\n "
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "chars": 590,
    "preview": "<!--\n首先,感谢你的贡献!😄\nPR 在维护者审核通过后会合并,谢谢!\n-->\n\n### 🤔 这个 PR 的性质是?\n\n- [ ] 日常 bug 修复\n- [ ] 新特性提交\n- [ ] 文档改进\n- [ ] 演示代码改进\n- [ ] 组"
  },
  {
    "path": ".github/dependabot.yml",
    "chars": 579,
    "preview": "# Basic dependabot.yml file with\n# minimum configuration for two package managers\n\nversion: 2\nupdates:\n  # Enable versio"
  },
  {
    "path": ".github/issue-shoot.md",
    "chars": 183,
    "preview": "## IssueShoot\n\n- 预估时长: {{ .duration }}\n- 期望完成时间: {{ .deadline }}\n- 开发难度: {{ .level }}\n- 参与人数: 1\n- 需求对接人: ivringpeng\n- 验收"
  },
  {
    "path": ".github/workflows/build.yml",
    "chars": 2269,
    "preview": "name: Build and Release\n\non:\n  push:\n    tags:\n      - 'v*'\n\njobs:\n  release:\n    runs-on: ${{ matrix.os }}\n\n    strateg"
  },
  {
    "path": ".github/workflows/deploy.yml",
    "chars": 1347,
    "preview": "name: Deploy Web\n\non:\n  push:\n    branches:\n      - main # 或者您的主分支名称\n  workflow_dispatch: # 允许手动触发\n\njobs:\n  build-and-de"
  },
  {
    "path": ".gitignore",
    "chars": 377,
    "preview": "node_modules\n.DS_Store\n\ndist\ndist-ssr\n*.local\ndist_electron\n.idea\n\n# lock\nyarn.lock\npnpm-lock.yaml\npackage-lock.json\ndis"
  },
  {
    "path": ".husky/pre-commit",
    "chars": 105,
    "preview": "echo \"对已暂存文件运行 lint-staged...\"\nnpx lint-staged\n\necho \"运行类型检查...\"\nnpm run typecheck\n\necho \"所有检查通过,准备提交...\""
  },
  {
    "path": ".husky/pre-push",
    "chars": 105,
    "preview": "echo \"对已暂存文件运行 lint-staged...\"\nnpx lint-staged\n\necho \"运行类型检查...\"\nnpm run typecheck\n\necho \"所有检查通过,准备提交...\""
  },
  {
    "path": ".prettierignore",
    "chars": 65,
    "preview": "out\ndist\npnpm-lock.yaml\nLICENSE.md\ntsconfig.json\ntsconfig.*.json\n"
  },
  {
    "path": "CHANGELOG.md",
    "chars": 1578,
    "preview": "# 更新日志\n\n## v5.0.0\n\n### ✨ 新功能\n\n- LX Music 音源脚本导入\n- 逐字歌词,支持全屏歌词和桌面歌词同步显示\n- 心动模式播放\n- 移动设备整体页面风格和效果优化\n- 移动端添加平板模式设置\n- 歌词页面样式"
  },
  {
    "path": "DEV.md",
    "chars": 4180,
    "preview": "# Alger Music Player 开发文档\n\n## 项目结构\n\n### 技术栈\n\n- **前端框架**:Vue 3 + TypeScript\n- **UI 组件库**:naive-ui\n- **样式框架**:Tailwind CSS"
  },
  {
    "path": "LICENSE",
    "chars": 1062,
    "preview": "MIT License\n\nCopyright (c) 2026 Alger\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof t"
  },
  {
    "path": "README.md",
    "chars": 3286,
    "preview": "<h2 align=\"center\">🎵 Alger Music Player</h2>\n<div align=\"center\">\n<div align=\"center\">\n  <a href=\"https://github.com/alg"
  },
  {
    "path": "android/.gitignore",
    "chars": 1824,
    "preview": "# Using Android gitignore template: https://github.com/github/gitignore/blob/HEAD/Android.gitignore\n\n# Built application"
  },
  {
    "path": "build/entitlements.mac.plist",
    "chars": 751,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "build/installer.nsh",
    "chars": 241,
    "preview": "# 设置 Windows 7 兼容性\nManifestDPIAware true\nManifestSupportedOS all\n\n!macro customInit\n  # 检查系统版本\n  ${If} ${AtLeastWin7}\n  "
  },
  {
    "path": "dev-app-update.yml",
    "chars": 103,
    "preview": "provider: generic\nurl: https://example.com/auto-updates\nupdaterCacheDirName: electron-lan-file-updater\n"
  },
  {
    "path": "docs/custom-api-readme.md",
    "chars": 2247,
    "preview": "## 🎵 自定义音源API配置\n\n现在支持通过导入一个简单的 JSON 配置文件来对接第三方的音乐解析 API。这将提供极大的灵活性,可以接入任意第三方音源。\n\n### 如何使用\n\n1.  前往 **设置 -> 播放设置 -> 音源设置**"
  },
  {
    "path": "electron.vite.config.ts",
    "chars": 1077,
    "preview": "import vue from '@vitejs/plugin-vue';\nimport { defineConfig } from 'electron-vite';\nimport { resolve } from 'path';\nimpo"
  },
  {
    "path": "eslint.config.mjs",
    "chars": 6852,
    "preview": "import js from '@eslint/js';\nimport typescript from '@typescript-eslint/eslint-plugin';\nimport typescriptParser from '@t"
  },
  {
    "path": "package.json",
    "chars": 6764,
    "preview": "{\n  \"name\": \"AlgerMusicPlayer\",\n  \"version\": \"5.0.0\",\n  \"description\": \"Alger Music Player\",\n  \"author\": \"Alger <algerkc"
  },
  {
    "path": "postcss.config.js",
    "chars": 81,
    "preview": "module.exports = {\n  plugins: {\n    tailwindcss: {},\n    autoprefixer: {}\n  }\n};\n"
  },
  {
    "path": "prettier.config.js",
    "chars": 166,
    "preview": "/**\n * @type {import('prettier').Config}\n */\nmodule.exports = {\n  singleQuote: true,\n  semi: true,\n  printWidth: 100,\n  "
  },
  {
    "path": "resources/html/remote-control.html",
    "chars": 14854,
    "preview": "<!doctype html>\n<html lang=\"zh-CN\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <meta\n      name=\"viewport\"\n      content="
  },
  {
    "path": "resources/manifest.json",
    "chars": 141,
    "preview": "{\n  \"name\": \"Alger Music PWA\",\n  \"icons\": [\n    {\n      \"src\": \"./icon.png\",\n      \"type\": \"image/png\",\n      \"sizes\": \""
  },
  {
    "path": "src/i18n/lang/en-US/artist.ts",
    "chars": 102,
    "preview": "export default {\n  hotSongs: 'Hot Songs',\n  albums: 'Albums',\n  description: 'Artist Introduction'\n};\n"
  },
  {
    "path": "src/i18n/lang/en-US/bilibili.ts",
    "chars": 2392,
    "preview": "export default {\n  player: {\n    loading: 'Loading audio...',\n    retry: 'Retry',\n    playNow: 'Play Now',\n    loadingTi"
  },
  {
    "path": "src/i18n/lang/en-US/common.ts",
    "chars": 1401,
    "preview": "export default {\n  play: 'Play',\n  next: 'Next',\n  previous: 'Previous',\n  volume: 'Volume',\n  settings: 'Settings',\n  s"
  },
  {
    "path": "src/i18n/lang/en-US/comp.ts",
    "chars": 8027,
    "preview": "export default {\n  installApp: {\n    description: 'Install the application for a better experience',\n    noPrompt: 'Do n"
  },
  {
    "path": "src/i18n/lang/en-US/donation.ts",
    "chars": 381,
    "preview": "export default {\n  description:\n    'Your donation will be used to support development and maintenance work, including b"
  },
  {
    "path": "src/i18n/lang/en-US/download.ts",
    "chars": 2703,
    "preview": "export default {\n  title: 'Download Manager',\n  localMusic: 'Local Music',\n  count: '{count} songs in total',\n  clearAll"
  },
  {
    "path": "src/i18n/lang/en-US/favorite.ts",
    "chars": 498,
    "preview": "export default {\n  title: 'Favorites',\n  count: 'Total {count}',\n  batchDownload: 'Batch Download',\n  selectAll: 'All',\n"
  },
  {
    "path": "src/i18n/lang/en-US/history.ts",
    "chars": 1175,
    "preview": "export default {\n  title: 'Play History',\n  heatmapTitle: 'Heatmap',\n  playCount: '{count}',\n  getHistoryFailed: 'Failed"
  },
  {
    "path": "src/i18n/lang/en-US/login.ts",
    "chars": 2642,
    "preview": "export default {\n  title: {\n    qr: 'QR Code Login',\n    phone: 'Phone Login',\n    cookie: 'Cookie Login',\n    uid: 'UID"
  },
  {
    "path": "src/i18n/lang/en-US/player.ts",
    "chars": 4331,
    "preview": "export default {\n  nowPlaying: 'Now Playing',\n  playlist: 'Playlist',\n  lyrics: 'Lyrics',\n  previous: 'Previous',\n  play"
  },
  {
    "path": "src/i18n/lang/en-US/search.ts",
    "chars": 606,
    "preview": "export default {\n  title: {\n    hotSearch: 'Hot Search',\n    searchList: 'Search Results',\n    searchHistory: 'Search Hi"
  },
  {
    "path": "src/i18n/lang/en-US/settings.ts",
    "chars": 14486,
    "preview": "export default {\n  theme: 'Theme',\n  language: 'Language',\n  regard: 'About',\n  logout: 'Logout',\n  sections: {\n    basi"
  },
  {
    "path": "src/i18n/lang/en-US/songItem.ts",
    "chars": 749,
    "preview": "export default {\n  menu: {\n    play: 'Play',\n    playNext: 'Play Next',\n    download: 'Download',\n    addToPlaylist: 'Ad"
  },
  {
    "path": "src/i18n/lang/en-US/user.ts",
    "chars": 1350,
    "preview": "export default {\n  profile: {\n    followers: 'Followers',\n    following: 'Following',\n    level: 'Level'\n  },\n  playlist"
  },
  {
    "path": "src/i18n/lang/ja-JP/artist.ts",
    "chars": 89,
    "preview": "export default {\r\n  hotSongs: '人気楽曲',\r\n  albums: 'アルバム',\r\n  description: 'アーティスト紹介'\r\n};\r\n"
  },
  {
    "path": "src/i18n/lang/ja-JP/bilibili.ts",
    "chars": 1993,
    "preview": "export default {\n  player: {\n    loading: 'オーディオ読み込み中...',\n    retry: '再試行',\n    playNow: '今すぐ再生',\n    loadingTitle: '読み"
  },
  {
    "path": "src/i18n/lang/ja-JP/common.ts",
    "chars": 1139,
    "preview": "export default {\r\n  play: '再生',\r\n  next: '次の曲',\r\n  previous: '前の曲',\r\n  volume: '音量',\r\n  settings: '設定',\r\n  search: '検索',"
  },
  {
    "path": "src/i18n/lang/ja-JP/comp.ts",
    "chars": 6601,
    "preview": "export default {\r\n  installApp: {\r\n    description: 'アプリをインストールして、より良い体験を',\r\n    noPrompt: '今後表示しない',\r\n    install: '今すぐ"
  },
  {
    "path": "src/i18n/lang/ja-JP/donation.ts",
    "chars": 252,
    "preview": "export default {\r\n  description:\r\n    'あなたの寄付は開発・保守作業をサポートするために使用され、サーバー保守、ドメイン更新などが含まれます。',\r\n  message: 'メッセージを残す際は、メール"
  },
  {
    "path": "src/i18n/lang/ja-JP/download.ts",
    "chars": 2148,
    "preview": "export default {\r\n  title: 'ダウンロード管理',\r\n  localMusic: 'ローカル音楽',\r\n  count: '合計{count}曲',\r\n  clearAll: '記録をクリア',\r\n  settin"
  },
  {
    "path": "src/i18n/lang/ja-JP/favorite.ts",
    "chars": 354,
    "preview": "export default {\r\n  title: 'お気に入り',\r\n  count: '合計{count}曲',\r\n  batchDownload: '一括ダウンロード',\r\n  download: 'ダウンロード ({count})"
  },
  {
    "path": "src/i18n/lang/ja-JP/history.ts",
    "chars": 993,
    "preview": "export default {\r\n  title: '再生履歴',\r\n  heatmapTitle: 'ヒートマップ',\r\n  playCount: '{count}',\r\n  getHistoryFailed: '履歴の取得に失敗しまし"
  },
  {
    "path": "src/i18n/lang/ja-JP/login.ts",
    "chars": 2199,
    "preview": "export default {\r\n  title: {\r\n    qr: 'QRコードログイン',\r\n    phone: '電話番号ログイン',\r\n    cookie: 'Cookieログイン',\r\n    uid: 'UIDログイン"
  },
  {
    "path": "src/i18n/lang/ja-JP/player.ts",
    "chars": 3531,
    "preview": "export default {\n  nowPlaying: '再生中',\n  playlist: 'プレイリスト',\n  lyrics: '歌詞',\n  previous: '前へ',\n  play: '再生',\n  pause: '一時"
  },
  {
    "path": "src/i18n/lang/ja-JP/search.ts",
    "chars": 548,
    "preview": "export default {\r\n  title: {\r\n    hotSearch: '人気検索リスト',\r\n    searchList: '検索リスト',\r\n    searchHistory: '検索履歴'\r\n  },\r\n  bu"
  },
  {
    "path": "src/i18n/lang/ja-JP/settings.ts",
    "chars": 12008,
    "preview": "export default {\n  theme: 'テーマ',\n  language: '言語',\n  regard: 'について',\n  logout: 'ログアウト',\n  sections: {\n    basic: '基本設定',"
  },
  {
    "path": "src/i18n/lang/ja-JP/songItem.ts",
    "chars": 692,
    "preview": "export default {\r\n  menu: {\r\n    play: '再生',\r\n    playNext: '次に再生',\r\n    download: '楽曲をダウンロード',\r\n    addToPlaylist: 'プレイ"
  },
  {
    "path": "src/i18n/lang/ja-JP/user.ts",
    "chars": 1188,
    "preview": "export default {\r\n  profile: {\r\n    followers: 'フォロワー',\r\n    following: 'フォロー中',\r\n    level: 'レベル'\r\n  },\r\n  playlist: {\r"
  },
  {
    "path": "src/i18n/lang/ko-KR/artist.ts",
    "chars": 86,
    "preview": "export default {\r\n  hotSongs: '인기 곡',\r\n  albums: '앨범',\r\n  description: '아티스트 소개'\r\n};\r\n"
  },
  {
    "path": "src/i18n/lang/ko-KR/bilibili.ts",
    "chars": 1994,
    "preview": "export default {\n  player: {\n    loading: '오디오 로딩 중...',\n    retry: '다시 시도',\n    playNow: '지금 재생',\n    loadingTitle: '로딩"
  },
  {
    "path": "src/i18n/lang/ko-KR/common.ts",
    "chars": 1117,
    "preview": "export default {\r\n  play: '재생',\r\n  next: '다음 곡',\r\n  previous: '이전 곡',\r\n  volume: '볼륨',\r\n  settings: '설정',\r\n  search: '검색"
  },
  {
    "path": "src/i18n/lang/ko-KR/comp.ts",
    "chars": 6468,
    "preview": "export default {\r\n  installApp: {\r\n    description: '앱을 설치하여 더 나은 경험을 얻으세요',\r\n    noPrompt: '다시 묻지 않기',\r\n    install: '지"
  },
  {
    "path": "src/i18n/lang/ko-KR/donation.ts",
    "chars": 254,
    "preview": "export default {\r\n  description:\r\n    '귀하의 기부는 서버 유지보수, 도메인 갱신 등을 포함한 개발 및 유지보수 작업을 지원하는 데 사용됩니다.',\r\n  message: '메시지를 남길"
  },
  {
    "path": "src/i18n/lang/ko-KR/download.ts",
    "chars": 2095,
    "preview": "export default {\r\n  title: '다운로드 관리',\r\n  localMusic: '로컬 음악',\r\n  count: '총 {count}곡',\r\n  clearAll: '기록 지우기',\r\n  settings"
  },
  {
    "path": "src/i18n/lang/ko-KR/favorite.ts",
    "chars": 347,
    "preview": "export default {\r\n  title: '내 수집',\r\n  count: '총 {count}곡',\r\n  batchDownload: '일괄 다운로드',\r\n  download: '다운로드 ({count})',\r\n"
  },
  {
    "path": "src/i18n/lang/ko-KR/history.ts",
    "chars": 996,
    "preview": "export default {\r\n  title: '재생 기록',\r\n  heatmapTitle: '히트맵',\r\n  playCount: '{count}',\r\n  getHistoryFailed: '기록 가져오기 실패',\r"
  },
  {
    "path": "src/i18n/lang/ko-KR/login.ts",
    "chars": 2147,
    "preview": "export default {\r\n  title: {\r\n    qr: 'QR코드 로그인',\r\n    phone: '휴대폰 번호 로그인',\r\n    cookie: 'Cookie 로그인',\r\n    uid: 'UID 로그"
  },
  {
    "path": "src/i18n/lang/ko-KR/player.ts",
    "chars": 3445,
    "preview": "export default {\n  nowPlaying: '현재 재생 중',\n  playlist: '재생 목록',\n  lyrics: '가사',\n  previous: '이전',\n  play: '재생',\n  pause: "
  },
  {
    "path": "src/i18n/lang/ko-KR/search.ts",
    "chars": 532,
    "preview": "export default {\r\n  title: {\r\n    hotSearch: '인기 검색',\r\n    searchList: '검색 목록',\r\n    searchHistory: '검색 기록'\r\n  },\r\n  but"
  },
  {
    "path": "src/i18n/lang/ko-KR/settings.ts",
    "chars": 11825,
    "preview": "export default {\n  theme: '테마',\n  language: '언어',\n  regard: '정보',\n  logout: '로그아웃',\n  sections: {\n    basic: '기본 설정',\n  "
  },
  {
    "path": "src/i18n/lang/ko-KR/songItem.ts",
    "chars": 680,
    "preview": "export default {\r\n  menu: {\r\n    play: '재생',\r\n    playNext: '다음에 재생',\r\n    download: '곡 다운로드',\r\n    addToPlaylist: '플레이리"
  },
  {
    "path": "src/i18n/lang/ko-KR/user.ts",
    "chars": 1194,
    "preview": "export default {\r\n  profile: {\r\n    followers: '팔로워',\r\n    following: '팔로잉',\r\n    level: '레벨'\r\n  },\r\n  playlist: {\r\n    "
  },
  {
    "path": "src/i18n/lang/zh-CN/artist.ts",
    "chars": 78,
    "preview": "export default {\n  hotSongs: '热门歌曲',\n  albums: '专辑',\n  description: '艺人介绍'\n};\n"
  },
  {
    "path": "src/i18n/lang/zh-CN/bilibili.ts",
    "chars": 1676,
    "preview": "export default {\n  player: {\n    loading: '听书加载中...',\n    retry: '重试',\n    playNow: '立即播放',\n    loadingTitle: '加载中...',\n"
  },
  {
    "path": "src/i18n/lang/zh-CN/common.ts",
    "chars": 1011,
    "preview": "export default {\n  play: '播放',\n  next: '下一首',\n  previous: '上一首',\n  volume: '音量',\n  settings: '设置',\n  search: '搜索',\n  loa"
  },
  {
    "path": "src/i18n/lang/zh-CN/comp.ts",
    "chars": 5353,
    "preview": "export default {\n  installApp: {\n    description: '安装应用程序,获得更好的体验',\n    noPrompt: '不再提示',\n    install: '立即安装',\n    cance"
  },
  {
    "path": "src/i18n/lang/zh-CN/donation.ts",
    "chars": 191,
    "preview": "export default {\n  description: '您的捐赠将用于支持开发和维护工作,包括但不限于服务器维护、域名续费等。',\n  message: '留言时可留下您的邮箱或 github名称。',\n  refresh: '刷"
  },
  {
    "path": "src/i18n/lang/zh-CN/download.ts",
    "chars": 1800,
    "preview": "export default {\n  title: '下载管理',\n  localMusic: '本地音乐',\n  count: '共 {count} 首歌曲',\n  clearAll: '清空记录',\n  settings: '设置',\n"
  },
  {
    "path": "src/i18n/lang/zh-CN/favorite.ts",
    "chars": 291,
    "preview": "export default {\n  title: '我的收藏',\n  count: '共 {count} 首',\n  batchDownload: '批量下载',\n  download: '下载 ({count})',\n  emptyTi"
  },
  {
    "path": "src/i18n/lang/zh-CN/history.ts",
    "chars": 882,
    "preview": "export default {\n  title: '播放历史',\n  heatmapTitle: '热力图',\n  playCount: '{count}',\n  getHistoryFailed: '获取历史记录失败',\n  categ"
  },
  {
    "path": "src/i18n/lang/zh-CN/login.ts",
    "chars": 1661,
    "preview": "export default {\n  title: {\n    qr: '扫码登录',\n    phone: '手机号登录',\n    cookie: 'Cookie登录',\n    uid: 'UID登录'\n  },\n  qrTip: '"
  },
  {
    "path": "src/i18n/lang/zh-CN/player.ts",
    "chars": 3093,
    "preview": "export default {\n  nowPlaying: '正在播放',\n  playlist: '播放列表',\n  lyrics: '歌词',\n  previous: '上一个',\n  play: '播放',\n  pause: '暂停"
  },
  {
    "path": "src/i18n/lang/zh-CN/search.ts",
    "chars": 482,
    "preview": "export default {\n  title: {\n    hotSearch: '热搜列表',\n    searchList: '搜索列表',\n    searchHistory: '搜索历史'\n  },\n  button: {\n  "
  },
  {
    "path": "src/i18n/lang/zh-CN/settings.ts",
    "chars": 10580,
    "preview": "export default {\n  theme: '主题',\n  language: '语言',\n  regard: '关于',\n  logout: '退出登录',\n  sections: {\n    basic: '基础设置',\n   "
  },
  {
    "path": "src/i18n/lang/zh-CN/songItem.ts",
    "chars": 580,
    "preview": "export default {\n  menu: {\n    play: '播放',\n    playNext: '下一首播放',\n    download: '下载歌曲',\n    addToPlaylist: '添加到歌单',\n    "
  },
  {
    "path": "src/i18n/lang/zh-CN/user.ts",
    "chars": 1016,
    "preview": "export default {\n  profile: {\n    followers: '粉丝',\n    following: '关注',\n    level: '等级'\n  },\n  playlist: {\n    created: "
  },
  {
    "path": "src/i18n/lang/zh-Hant/artist.ts",
    "chars": 78,
    "preview": "export default {\n  hotSongs: '熱門歌曲',\n  albums: '專輯',\n  description: '藝人介紹'\n};\n"
  },
  {
    "path": "src/i18n/lang/zh-Hant/bilibili.ts",
    "chars": 1678,
    "preview": "export default {\n  player: {\n    loading: '聽書載入中...',\n    retry: '重試',\n    playNow: '立即播放',\n    loadingTitle: '載入中...',\n"
  },
  {
    "path": "src/i18n/lang/zh-Hant/common.ts",
    "chars": 1012,
    "preview": "export default {\n  play: '播放',\n  next: '下一首',\n  previous: '上一首',\n  volume: '音量',\n  settings: '設定',\n  search: '搜尋',\n  loa"
  },
  {
    "path": "src/i18n/lang/zh-Hant/comp.ts",
    "chars": 5434,
    "preview": "export default {\n  installApp: {\n    description: '安裝應用程式,獲得更好的體驗',\n    noPrompt: '不再提示',\n    install: '立即安裝',\n    cance"
  },
  {
    "path": "src/i18n/lang/zh-Hant/donation.ts",
    "chars": 197,
    "preview": "export default {\n  description: '您的捐贈將用於支持開發和維護工作,包括但不限於伺服器維護、域名續費等。',\n  message: '留言時可留下您的電子郵件或 github 名稱。',\n  refresh:"
  },
  {
    "path": "src/i18n/lang/zh-Hant/download.ts",
    "chars": 1798,
    "preview": "export default {\n  title: '下載管理',\n  localMusic: '本機音樂',\n  count: '共 {count} 首歌曲',\n  clearAll: '清空記錄',\n  settings: '設定',\n"
  },
  {
    "path": "src/i18n/lang/zh-Hant/favorite.ts",
    "chars": 291,
    "preview": "export default {\n  title: '我的收藏',\n  count: '共 {count} 首',\n  batchDownload: '批次下載',\n  download: '下載 ({count})',\n  emptyTi"
  },
  {
    "path": "src/i18n/lang/zh-Hant/history.ts",
    "chars": 882,
    "preview": "export default {\n  title: '播放歷史',\n  heatmapTitle: '熱力圖',\n  playCount: '{count}',\n  getHistoryFailed: '取得歷史記錄失敗',\n  categ"
  },
  {
    "path": "src/i18n/lang/zh-Hant/login.ts",
    "chars": 1668,
    "preview": "export default {\n  title: {\n    qr: '掃碼登入',\n    phone: '手機號登入',\n    cookie: 'Cookie登入',\n    uid: 'UID登入'\n  },\n  qrTip: '"
  },
  {
    "path": "src/i18n/lang/zh-Hant/player.ts",
    "chars": 3093,
    "preview": "export default {\n  nowPlaying: '正在播放',\n  playlist: '播放清單',\n  lyrics: '歌詞',\n  previous: '上一個',\n  play: '播放',\n  pause: '暫停"
  },
  {
    "path": "src/i18n/lang/zh-Hant/search.ts",
    "chars": 482,
    "preview": "export default {\n  title: {\n    hotSearch: '熱搜列表',\n    searchList: '搜尋列表',\n    searchHistory: '搜尋歷史'\n  },\n  button: {\n  "
  },
  {
    "path": "src/i18n/lang/zh-Hant/settings.ts",
    "chars": 10553,
    "preview": "export default {\n  theme: '主題',\n  language: '語言',\n  regard: '關於',\n  logout: '登出',\n  sections: {\n    basic: '基礎設定',\n    p"
  },
  {
    "path": "src/i18n/lang/zh-Hant/songItem.ts",
    "chars": 584,
    "preview": "export default {\n  menu: {\n    play: '播放',\n    playNext: '下一首播放',\n    download: '下載歌曲',\n    addToPlaylist: '新增至播放清單',\n  "
  },
  {
    "path": "src/i18n/lang/zh-Hant/user.ts",
    "chars": 1017,
    "preview": "export default {\n  profile: {\n    followers: '粉絲',\n    following: '關注',\n    level: '等級'\n  },\n  playlist: {\n    created: "
  },
  {
    "path": "src/i18n/languages.ts",
    "chars": 485,
    "preview": "// 语言配置文件 - 集中管理语言相关的配置\r\n\r\n// 语言显示名称映射\r\nexport const LANGUAGE_DISPLAY_NAMES: Record<string, string> = {\r\n  'zh-CN': '简体中"
  },
  {
    "path": "src/i18n/main.ts",
    "chars": 814,
    "preview": "import { DEFAULT_LANGUAGE } from './languages';\nimport { buildLanguageMessages } from './utils';\n\n// 使用工具函数构建语言消息对象\ncons"
  },
  {
    "path": "src/i18n/renderer.ts",
    "chars": 447,
    "preview": "import { createI18n } from 'vue-i18n';\n\nimport { DEFAULT_LANGUAGE, FALLBACK_LANGUAGE } from './languages';\nimport { buil"
  },
  {
    "path": "src/i18n/utils.ts",
    "chars": 1747,
    "preview": "// 自动导入所有语言的所有翻译文件\r\nconst allLangModules = import.meta.glob('./lang/**/*.ts', { eager: true });\r\n\r\n// 构建语言消息对象\r\nexport c"
  },
  {
    "path": "src/main/index.ts",
    "chars": 4515,
    "preview": "import { electronApp, optimizer } from '@electron-toolkit/utils';\nimport { app, ipcMain, nativeImage } from 'electron';\n"
  },
  {
    "path": "src/main/lyric.ts",
    "chars": 7680,
    "preview": "import { BrowserWindow, IpcMain, screen } from 'electron';\nimport Store from 'electron-store';\nimport path, { join } fro"
  },
  {
    "path": "src/main/modules/cache.ts",
    "chars": 1951,
    "preview": "import { ipcMain } from 'electron';\nimport Store from 'electron-store';\n\ninterface LyricData {\n  id: number;\n  data: any"
  },
  {
    "path": "src/main/modules/config.ts",
    "chars": 1962,
    "preview": "import { app, ipcMain } from 'electron';\nimport Store from 'electron-store';\n\nimport set from '../set.json';\nimport { de"
  },
  {
    "path": "src/main/modules/deviceInfo.ts",
    "chars": 1473,
    "preview": "import { app } from 'electron';\nimport Store from 'electron-store';\nimport { machineIdSync } from 'node-machine-id';\nimp"
  },
  {
    "path": "src/main/modules/fileManager.ts",
    "chars": 26140,
    "preview": "import axios from 'axios';\nimport { app, dialog, ipcMain, Notification, protocol, shell } from 'electron';\nimport Store "
  },
  {
    "path": "src/main/modules/fonts.ts",
    "chars": 896,
    "preview": "import { ipcMain } from 'electron';\nimport { getFonts } from 'font-list';\n\n/**\n * 清理字体名称\n * @param fontName 原始字体名称\n * @r"
  },
  {
    "path": "src/main/modules/loginWindow.ts",
    "chars": 2359,
    "preview": "import { BrowserWindow, ipcMain, session } from 'electron';\nimport { join } from 'path';\n\nimport i18n from '../../i18n/m"
  },
  {
    "path": "src/main/modules/lxMusicHttp.ts",
    "chars": 4149,
    "preview": "/**\n * 落雪音乐 HTTP 请求处理(主进程)\n * 绕过渲染进程的 CORS 限制\n */\n\nimport { ipcMain } from 'electron';\nimport fetch, { type RequestInit "
  },
  {
    "path": "src/main/modules/otherApi.ts",
    "chars": 770,
    "preview": "import axios from 'axios';\nimport { ipcMain } from 'electron';\n\n/**\n * 初始化其他杂项 API(如搜索建议等)\n */\nexport function initializ"
  },
  {
    "path": "src/main/modules/remoteControl.ts",
    "chars": 5693,
    "preview": "import cors from 'cors';\nimport { ipcMain } from 'electron';\nimport express from 'express';\nimport fs from 'fs';\nimport "
  },
  {
    "path": "src/main/modules/shortcuts.ts",
    "chars": 3376,
    "preview": "import { globalShortcut, ipcMain } from 'electron';\n\nimport { getStore } from './config';\n\n// 添加获取平台信息的 IPC 处理程序\nipcMain"
  },
  {
    "path": "src/main/modules/tray.ts",
    "chars": 11487,
    "preview": "import {\n  app,\n  BrowserWindow,\n  Menu,\n  MenuItem,\n  MenuItemConstructorOptions,\n  nativeImage,\n  Tray\n} from 'electro"
  },
  {
    "path": "src/main/modules/update.ts",
    "chars": 3016,
    "preview": "import axios from 'axios';\nimport { spawn } from 'child_process';\nimport { app, BrowserWindow, ipcMain } from 'electron'"
  },
  {
    "path": "src/main/modules/window-size.ts",
    "chars": 18580,
    "preview": "import { app, BrowserWindow, ipcMain, screen } from 'electron';\nimport Store from 'electron-store';\n\nconst store = new S"
  },
  {
    "path": "src/main/modules/window.ts",
    "chars": 10161,
    "preview": "import { is } from '@electron-toolkit/utils';\nimport {\n  app,\n  BrowserWindow,\n  globalShortcut,\n  ipcMain,\n  nativeImag"
  },
  {
    "path": "src/main/server.ts",
    "chars": 2042,
    "preview": "import { ipcMain } from 'electron';\nimport Store from 'electron-store';\nimport fs from 'fs';\nimport server from 'netease"
  },
  {
    "path": "src/main/set.json",
    "chars": 940,
    "preview": "{\n  \"isProxy\": false,\n  \"proxyConfig\": {\n    \"enable\": false,\n    \"protocol\": \"http\",\n    \"host\": \"127.0.0.1\",\n    \"port"
  },
  {
    "path": "src/main/unblockMusic.ts",
    "chars": 3017,
    "preview": "import match from '@unblockneteasemusic/server';\n\ntype Platform = 'qq' | 'migu' | 'kugou' | 'kuwo' | 'pyncmd' | 'joox' |"
  },
  {
    "path": "src/preload/index.d.ts",
    "chars": 1815,
    "preview": "import { ElectronAPI } from '@electron-toolkit/preload';\n\ninterface API {\n  minimize: () => void;\n  maximize: () => void"
  },
  {
    "path": "src/preload/index.ts",
    "chars": 4169,
    "preview": "import { electronAPI } from '@electron-toolkit/preload';\nimport { contextBridge, ipcRenderer } from 'electron';\n\n// Cust"
  },
  {
    "path": "src/renderer/App.vue",
    "chars": 4768,
    "preview": "<template>\n  <div class=\"app-container\" :class=\"{ mobile: isMobile, noElectron: !isElectron }\">\n    <n-config-provider :"
  },
  {
    "path": "src/renderer/api/artist.ts",
    "chars": 429,
    "preview": "import request from '@/utils/request';\n\n// 获取歌手详情\nexport const getArtistDetail = (id) => {\n  return request.get('/artist"
  },
  {
    "path": "src/renderer/api/bilibili.ts",
    "chars": 10890,
    "preview": "import type { IBilibiliPage, IBilibiliPlayUrl, IBilibiliVideoDetail } from '@/types/bilibili';\nimport type { SongResult "
  },
  {
    "path": "src/renderer/api/donation.ts",
    "chars": 374,
    "preview": "import axios from 'axios';\n\nexport interface Donor {\n  id: number;\n  name: string;\n  amount: number;\n  date: string;\n  m"
  },
  {
    "path": "src/renderer/api/gdmusic.ts",
    "chars": 4930,
    "preview": "import axios from 'axios';\n\nimport type { MusicSourceType } from '@/types/music';\n\n/**\n * GD音乐台解析服务\n */\nexport interface"
  },
  {
    "path": "src/renderer/api/home.ts",
    "chars": 1350,
    "preview": "import { IData } from '@/types';\nimport { IAlbumNew } from '@/types/album';\nimport { IDayRecommend } from '@/types/day_r"
  },
  {
    "path": "src/renderer/api/list.ts",
    "chars": 1038,
    "preview": "import { IList } from '@/types/list';\nimport type { IListDetail } from '@/types/listDetail';\nimport request from '@/util"
  },
  {
    "path": "src/renderer/api/login.ts",
    "chars": 1055,
    "preview": "import request from '@/utils/request';\n\n// 创建二维码key\n//  /login/qr/key\nexport function getQrKey() {\n  return request.get("
  },
  {
    "path": "src/renderer/api/lxMusicStrategy.ts",
    "chars": 7707,
    "preview": "/**\n * 落雪音乐 (LX Music) 音源解析策略\n *\n * 实现 MusicSourceStrategy 接口,作为落雪音源的解析入口\n */\n\nimport { getLxMusicRunner, initLxMusicRun"
  },
  {
    "path": "src/renderer/api/music.ts",
    "chars": 5212,
    "preview": "import { musicDB } from '@/hooks/MusicHook';\nimport { useSettingsStore, useUserStore } from '@/store';\nimport type { ILy"
  },
  {
    "path": "src/renderer/api/musicParser.ts",
    "chars": 16999,
    "preview": "import { cloneDeep } from 'lodash';\n\nimport { musicDB } from '@/hooks/MusicHook';\nimport { SongSourceConfigManager } fro"
  },
  {
    "path": "src/renderer/api/mv.ts",
    "chars": 750,
    "preview": "import { IData } from '@/types';\nimport { IMvUrlData } from '@/types/mv';\nimport request from '@/utils/request';\n\ninterf"
  },
  {
    "path": "src/renderer/api/parseFromCustomApi.ts",
    "chars": 2902,
    "preview": "import axios from 'axios';\nimport { get } from 'lodash';\n\nimport { useSettingsStore } from '@/store';\n\nimport type { Par"
  },
  {
    "path": "src/renderer/api/playlist.ts",
    "chars": 524,
    "preview": "import request from '@/utils/request';\n\n/**\n * 歌单导入 - 元数据/文字/链接导入\n * @param params 导入参数\n */\nexport function importPlayli"
  },
  {
    "path": "src/renderer/api/search.ts",
    "chars": 2294,
    "preview": "import { isElectron } from '@/utils';\nimport request from '@/utils/request';\n\ninterface IParams {\n  keywords: string;\n  "
  },
  {
    "path": "src/renderer/api/user.ts",
    "chars": 2581,
    "preview": "import type { IUserDetail, IUserFollow } from '@/types/user';\nimport request from '@/utils/request';\n\n// /user/detail\nex"
  },
  {
    "path": "src/renderer/assets/css/base.css",
    "chars": 389,
    "preview": "body {\n  /* background-color: #000; */\n  overflow: hidden;\n}\n\n.n-popover:has(.music-play) {\n  border-radius: 1.5rem !imp"
  },
  {
    "path": "src/renderer/assets/icon/iconfont.css",
    "chars": 3599,
    "preview": "@font-face {\n  font-family: 'iconfont'; /* Project id 2685283 */\n  src:\n    url('iconfont.woff2?t=1703643214551') format"
  },
  {
    "path": "src/renderer/assets/icon/iconfont.js",
    "chars": 63181,
    "preview": "((window._iconfont_svg_string_2685283 =\n  '<svg><symbol id=\"icon-list\" viewBox=\"0 0 1024 1024\"><path d=\"M897.427256 249."
  },
  {
    "path": "src/renderer/assets/icon/iconfont.json",
    "chars": 10576,
    "preview": "{\n  \"id\": \"2685283\",\n  \"name\": \"music\",\n  \"font_family\": \"iconfont\",\n  \"css_prefix_text\": \"icon-\",\n  \"description\": \"\",\n"
  },
  {
    "path": "src/renderer/components/Coffee.vue",
    "chars": 2604,
    "preview": "<template>\n  <div class=\"relative inline-block\">\n    <n-popover trigger=\"hover\" placement=\"top\" :show-arrow=\"true\" :raw="
  },
  {
    "path": "src/renderer/components/EQControl.vue",
    "chars": 7783,
    "preview": "<template>\n  <div class=\"eq-control\">\n    <div class=\"eq-header\">\n      <h3>\n        {{ t('player.eq.title') }}\n        "
  },
  {
    "path": "src/renderer/components/LanguageSwitcher.vue",
    "chars": 626,
    "preview": "<script setup lang=\"ts\">\nimport { getLanguageOptions } from '@i18n/utils';\nimport { computed } from 'vue';\nimport { useI"
  },
  {
    "path": "src/renderer/components/MusicList.vue",
    "chars": 18571,
    "preview": "<template>\n  <n-drawer\n    :show=\"show\"\n    :height=\"isMobile ? '100%' : '80%'\"\n    placement=\"bottom\"\n    block-scroll\n"
  },
  {
    "path": "src/renderer/components/MvPlayer.vue",
    "chars": 17992,
    "preview": "<template>\n  <n-drawer :show=\"show\" height=\"100%\" placement=\"bottom\" :z-index=\"999999999\" :to=\"`#layout-main`\">\n    <div"
  },
  {
    "path": "src/renderer/components/ShortcutToast.vue",
    "chars": 2278,
    "preview": "<template>\n  <transition name=\"shortcut-toast\">\n    <div v-if=\"visible\" class=\"shortcut-toast\" :class=\"`shortcut-toast-$"
  },
  {
    "path": "src/renderer/components/TrafficWarningDrawer.vue",
    "chars": 7861,
    "preview": "<template>\n  <n-drawer\n    v-model:show=\"showDrawer\"\n    :width=\"isMobile ? '100%' : '800px'\"\n    :height=\"isMobile ? '1"
  },
  {
    "path": "src/renderer/components/common/AlbumItem.vue",
    "chars": 2629,
    "preview": "<template>\n  <div class=\"album-item\" @click=\"handleClick\">\n    <n-image\n      :src=\"getImgUrl(item.picUrl || '', '100y10"
  },
  {
    "path": "src/renderer/components/common/ArtistDrawer.vue",
    "chars": 8645,
    "preview": "<template>\n  <n-drawer\n    v-model:show=\"modelValue\"\n    :width=\"800\"\n    placement=\"right\"\n    :mask-closable=\"true\"\n  "
  },
  {
    "path": "src/renderer/components/common/BilibiliItem.vue",
    "chars": 3243,
    "preview": "<template>\n  <div class=\"bilibili-item\" @click=\"handleClick\">\n    <div class=\"bilibili-item-img\">\n      <n-image class=\""
  },
  {
    "path": "src/renderer/components/common/DisclaimerModal.vue",
    "chars": 11871,
    "preview": "<template>\n  <Teleport to=\"body\">\n    <Transition name=\"disclaimer-modal\">\n      <!-- 免责声明页面 -->\n      <div\n        v-if"
  },
  {
    "path": "src/renderer/components/common/DonationList.vue",
    "chars": 8195,
    "preview": "<template>\n  <div class=\"donation-container\">\n    <div class=\"qrcode-container\">\n      <div class=\"description\">\n       "
  },
  {
    "path": "src/renderer/components/common/DownloadDrawer.vue",
    "chars": 2975,
    "preview": "<template>\n  <div class=\"download-drawer-trigger\">\n    <n-badge :value=\"downloadingCount\" :max=\"99\" :show=\"downloadingCo"
  },
  {
    "path": "src/renderer/components/common/InstallAppModal.vue",
    "chars": 3127,
    "preview": "<template>\n  <n-modal\n    v-model:show=\"showModal\"\n    preset=\"dialog\"\n    :show-icon=\"false\"\n    :mask-closable=\"true\"\n"
  },
  {
    "path": "src/renderer/components/common/MobileUpdateModal.vue",
    "chars": 7404,
    "preview": "<template>\n  <Teleport to=\"body\">\n    <Transition name=\"update-modal\">\n      <div\n        v-if=\"showModal\"\n        class"
  },
  {
    "path": "src/renderer/components/common/MusicListNavigator.ts",
    "chars": 1009,
    "preview": "import { Router } from 'vue-router';\n\nimport { useMusicStore } from '@/store/modules/music';\n\n/**\n * 导航到音乐列表页面的通用方法\n * @"
  },
  {
    "path": "src/renderer/components/common/PlayBottom.vue",
    "chars": 497,
    "preview": "<template>\n  <div v-if=\"isPlay && !isMobile\" class=\"bottom\" :style=\"{ height }\"></div>\n</template>\n\n<script setup lang=\""
  },
  {
    "path": "src/renderer/components/common/PlayListsItem.vue",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "src/renderer/components/common/PlaylistDrawer.vue",
    "chars": 10176,
    "preview": "<template>\n  <n-drawer\n    :show=\"modelValue\"\n    :width=\"400\"\n    placement=\"right\"\n    @update:show=\"$emit('update:mod"
  },
  {
    "path": "src/renderer/components/common/PlaylistItem.vue",
    "chars": 2714,
    "preview": "<template>\n  <div class=\"playlist-item\" @click=\"handleClick\">\n    <n-image\n      :src=\"getImgUrl(item.coverImgUrl || ite"
  },
  {
    "path": "src/renderer/components/common/ResponsiveModal.vue",
    "chars": 3572,
    "preview": "<template>\n  <Teleport to=\"body\">\n    <Transition name=\"fade\">\n      <div\n        v-if=\"show\"\n        class=\"fixed inset"
  },
  {
    "path": "src/renderer/components/common/SearchItem.vue",
    "chars": 4981,
    "preview": "<template>\n  <div class=\"search-item\" :class=\"[shape, item.type]\" @click=\"handleClick\">\n    <div class=\"search-item-img\""
  },
  {
    "path": "src/renderer/components/common/SongItem.vue",
    "chars": 1494,
    "preview": "<template>\n  <component\n    :is=\"renderComponent\"\n    :item=\"item\"\n    :favorite=\"favorite\"\n    :selectable=\"selectable\""
  },
  {
    "path": "src/renderer/components/common/UpdateModal.vue",
    "chars": 14875,
    "preview": "<template>\n  <n-modal\n    v-model:show=\"showModal\"\n    preset=\"dialog\"\n    :show-icon=\"false\"\n    :mask-closable=\"!downl"
  },
  {
    "path": "src/renderer/components/common/songItemCom/BaseSongItem.vue",
    "chars": 2533,
    "preview": "<template>\n  <div\n    class=\"song-item\"\n    @contextmenu.prevent=\"handleContextMenu\"\n    @mouseenter=\"handleMouseEnter\"\n"
  },
  {
    "path": "src/renderer/components/common/songItemCom/CompactSongItem.vue",
    "chars": 7548,
    "preview": "<template>\n  <base-song-item\n    :item=\"item\"\n    :selectable=\"selectable\"\n    :selected=\"selected\"\n    :can-remove=\"can"
  },
  {
    "path": "src/renderer/components/common/songItemCom/ListSongItem.vue",
    "chars": 5310,
    "preview": "<template>\n  <base-song-item\n    :item=\"item\"\n    :selectable=\"selectable\"\n    :selected=\"selected\"\n    :can-remove=\"can"
  },
  {
    "path": "src/renderer/components/common/songItemCom/MiniSongItem.vue",
    "chars": 5308,
    "preview": "<template>\n  <base-song-item\n    :item=\"item\"\n    :selectable=\"selectable\"\n    :selected=\"selected\"\n    :can-remove=\"can"
  },
  {
    "path": "src/renderer/components/common/songItemCom/SongItemDropdown.vue",
    "chars": 5850,
    "preview": "<template>\n  <n-dropdown\n    v-if=\"isElectron\"\n    :show=\"show\"\n    :x=\"x\"\n    :y=\"y\"\n    :options=\"dropdownOptions\"\n   "
  },
  {
    "path": "src/renderer/components/common/songItemCom/StandardSongItem.vue",
    "chars": 6007,
    "preview": "<template>\n  <base-song-item\n    :item=\"item\"\n    :selectable=\"selectable\"\n    :selected=\"selected\"\n    :can-remove=\"can"
  },
  {
    "path": "src/renderer/components/cover/Cover3D.vue",
    "chars": 4810,
    "preview": "<template>\n  <div\n    ref=\"coverContainer\"\n    class=\"cover-3d-container relative cursor-pointer\"\n    @mousemove=\"handle"
  },
  {
    "path": "src/renderer/components/home/PlaylistType.vue",
    "chars": 4475,
    "preview": "<template>\n  <!-- 歌单分类列表 -->\n  <div class=\"play-list-type\">\n    <div class=\"title\" :class=\"setAnimationClass('animate__f"
  },
  {
    "path": "src/renderer/components/home/RecommendAlbum.vue",
    "chars": 3091,
    "preview": "<template>\n  <div class=\"recommend-album\">\n    <div class=\"title\" :class=\"setAnimationClass('animate__fadeInRight')\">\n  "
  },
  {
    "path": "src/renderer/components/home/RecommendSonglist.vue",
    "chars": 1889,
    "preview": "<template>\n  <div class=\"recommend-music\">\n    <div class=\"title\" :class=\"setAnimationClass('animate__fadeInLeft')\">\n   "
  },
  {
    "path": "src/renderer/components/home/TopBanner.vue",
    "chars": 16065,
    "preview": "<template>\n  <div class=\"recommend-singer\">\n    <div class=\"recommend-singer-list\">\n      <n-carousel\n        v-if=\"hotS"
  },
  {
    "path": "src/renderer/components/login/CookieLogin.vue",
    "chars": 5141,
    "preview": "<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui';\nimport { onBeforeUnmount, onMounted } from 'vue';\nimport"
  },
  {
    "path": "src/renderer/components/login/QrLogin.vue",
    "chars": 6474,
    "preview": "<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui';\nimport { onMounted } from 'vue';\nimport { useI18n } from"
  },
  {
    "path": "src/renderer/components/login/UidLogin.vue",
    "chars": 3241,
    "preview": "<template>\n  <div class=\"uid-login\">\n    <div class=\"login-title\">{{ t('login.title.uid') }}</div>\n    <div class=\"uid-p"
  },
  {
    "path": "src/renderer/components/lyric/LyricCorrectionControl.vue",
    "chars": 2159,
    "preview": "<script setup lang=\"ts\">\nimport { defineEmits, defineProps } from 'vue';\nimport { useI18n } from 'vue-i18n';\n\nconst prop"
  },
  {
    "path": "src/renderer/components/lyric/LyricSettings.vue",
    "chars": 23842,
    "preview": "<template>\n  <div\n    class=\"w-80 rounded-2xl bg-black/30 backdrop-blur-3xl border border-white/10 shadow-2xl overflow-h"
  },
  {
    "path": "src/renderer/components/lyric/MusicFull.vue",
    "chars": 26448,
    "preview": "<template>\n  <n-drawer\n    v-model:show=\"isVisible\"\n    height=\"100%\"\n    placement=\"bottom\"\n    :style=\"drawerBaseStyle"
  },
  {
    "path": "src/renderer/components/lyric/MusicFullMobile.vue",
    "chars": 52754,
    "preview": "<template>\n  <n-drawer\n    v-model:show=\"isVisible\"\n    height=\"100%\"\n    placement=\"bottom\"\n    :style=\"{ background: p"
  },
  {
    "path": "src/renderer/components/lyric/MusicFullWrapper.vue",
    "chars": 545,
    "preview": "<template>\n  <component :is=\"componentToUse\" v-bind=\"$attrs\" ref=\"musicFullRef\" />\n</template>\n\n<script setup lang=\"ts\">"
  },
  {
    "path": "src/renderer/components/lyric/ThemeColorPanel.vue",
    "chars": 11654,
    "preview": "<template>\r\n  <div\r\n    v-show=\"visible\"\r\n    class=\"theme-color-panel\"\r\n    :class=\"{ visible: visible, hidden: !visibl"
  },
  {
    "path": "src/renderer/components/player/AdvancedControlsPopover.vue",
    "chars": 7558,
    "preview": "<template>\n  <n-dropdown\n    :show=\"showDropdown\"\n    :options=\"dropdownOptions\"\n    trigger=\"hover\"\n    :z-index=\"99999"
  },
  {
    "path": "src/renderer/components/player/MiniPlayBar.vue",
    "chars": 15480,
    "preview": "<template>\n  <div\n    class=\"mini-play-bar\"\n    :class=\"{ 'pure-mode': pureModeEnabled, 'mini-mode': settingsStore.isMin"
  },
  {
    "path": "src/renderer/components/player/MobilePlayBar.vue",
    "chars": 8144,
    "preview": "<template>\n  <div\n    ref=\"playBarRef\"\n    class=\"mobile-play-bar\"\n    :class=\"[\n      setAnimationClass('animate__fadeI"
  },
  {
    "path": "src/renderer/components/player/MobilePlayerSettings.vue",
    "chars": 11960,
    "preview": "<template>\n  <Teleport to=\"body\">\n    <Transition name=\"settings-drawer\">\n      <div\n        v-if=\"visible\"\n        clas"
  },
  {
    "path": "src/renderer/components/player/PlayBar.vue",
    "chars": 17607,
    "preview": "<template>\n  <div\n    class=\"music-play-bar\"\n    :class=\"[\n      setAnimationClass('animate__bounceInUp'),\n      musicFu"
  },
  {
    "path": "src/renderer/components/player/PlayingListDrawer.vue",
    "chars": 7332,
    "preview": "<template>\n  <!-- 透明遮罩层,点击任意位置关闭 -->\n  <div v-if=\"internalVisible\" class=\"fixed-overlay\" @click=\"closePanel\"></div>\n\n  <"
  },
  {
    "path": "src/renderer/components/player/ReparsePopover.vue",
    "chars": 6369,
    "preview": "<template>\n  <n-popover\n    trigger=\"click\"\n    :z-index=\"99999999\"\n    placement=\"top\"\n    content-class=\"music-source-"
  },
  {
    "path": "src/renderer/components/player/SimplePlayBar.vue",
    "chars": 15617,
    "preview": "<template>\n  <div class=\"play-bar\" :class=\"{ 'dark-theme': isDarkMode }\" ref=\"playBarRef\">\n    <div class=\"container\">\n "
  },
  {
    "path": "src/renderer/components/player/SleepTimer.vue",
    "chars": 9153,
    "preview": "<template>\n  <div class=\"sleep-timer-content\">\n    <h3 class=\"timer-title\">{{ t('player.sleepTimer.title') }}</h3>\n\n    "
  },
  {
    "path": "src/renderer/components/player/SleepTimerTop.vue",
    "chars": 3498,
    "preview": "<template>\n  <div>\n    <!-- 定时关闭倒计时显示区域 -->\n    <div v-if=\"hasActiveSleepTimer\" class=\"sleep-timer-countdown\" @click=\"ha"
  },
  {
    "path": "src/renderer/components/settings/ClearCacheSettings.vue",
    "chars": 2945,
    "preview": "<template>\n  <n-modal\n    v-model:show=\"visible\"\n    preset=\"dialog\"\n    :title=\"t('settings.system.cache')\"\n    :positi"
  },
  {
    "path": "src/renderer/components/settings/CookieSettingsModal.vue",
    "chars": 4603,
    "preview": "<script lang=\"ts\" setup>\nimport { useMessage } from 'naive-ui';\nimport { ref, watch } from 'vue';\nimport { useI18n } fro"
  }
]

// ... and 122 more files (download for full content)

About this extraction

This page contains the full source code of the algerkong/AlgerMusicPlayer GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 322 files (1.6 MB), approximately 509.8k tokens, and a symbol index with 519 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!