From ca5b68132ce9221639b3e2cc8937248051669e4a Mon Sep 17 00:00:00 2001 From: Courier Date: Sat, 22 Nov 2025 22:01:41 +0400 Subject: [PATCH 01/10] readme update, minor style fixes --- README.md | 25 +++++++++++++++++++++++++ bun.lock | 24 +++++++++--------------- package.json | 2 +- src/routes/+layout.svelte | 2 +- src/style/app.sass | 6 +++++- 5 files changed, 41 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 6b4d0b8..01b5987 100644 --- a/README.md +++ b/README.md @@ -33,3 +33,28 @@ Practice Japanese Karaoke lyrics reading and typing at the same time with KaraDa * [ ] Correct lyrics timing inconsistencies (i.e. 网易云的歌词因为是业余用户上传的,时间戳不一定准确。但是 waveform 里面可以分析出每句歌词的具体开始结束时间,也许可以自动修正) +## Development server + +### Requirements +- Bun +- Docker + +### 1. Environment setup +1. Create your `.env` file by renaming `.env.example` to `.env` +2. Add the following variable: + OPENROUTER_API_KEY=your_key_here + (Request the key from the repository owner) + +### 2. Start the database +Run in the project root: +docker compose up + +### 3. Install dependencies +Install Bun: +https://bun.com/get + +Then install project dependencies: +bun install + +### 4. Start development server +bun run dev diff --git a/bun.lock b/bun.lock index 2cb9554..29f9ff3 100644 --- a/bun.lock +++ b/bun.lock @@ -8,7 +8,7 @@ "@fontsource/roboto": "^5.2.8", "@iconify-json/material-symbols": "^1.2.46", "@iconify-json/svg-spinners": "^1.2.4", - "@neteasecloudmusicapienhanced/api": "^4.29.17", + "@neteasecloudmusicapienhanced/api": "4.29.17", "@openrouter/sdk": "^0.1.17", "@unocss/core": "^66.5.6", "@unocss/extractor-svelte": "^66.5.6", @@ -278,7 +278,7 @@ "@sveltejs/vite-plugin-svelte-inspector": ["@sveltejs/vite-plugin-svelte-inspector@5.0.1", "", { "dependencies": { "debug": "^4.4.1" }, "peerDependencies": { "@sveltejs/vite-plugin-svelte": "^6.0.0-next.0", "svelte": "^5.0.0", "vite": "^6.3.0 || ^7.0.0" } }, "sha512-ubWshlMk4bc8mkwWbg6vNvCeT7lGQojE3ijDh3QTR6Zr/R+GXxsGbyH4PExEPpiFmqPhYiVSVmHBjUcVc1JIrA=="], - "@tokenizer/inflate": ["@tokenizer/inflate@0.3.1", "", { "dependencies": { "debug": "^4.4.1", "fflate": "^0.8.2", "token-types": "^6.0.0" } }, "sha512-4oeoZEBQdLdt5WmP/hx1KZ6D3/Oid/0cUb2nk4F0pTDAWy+KCH3/EnAkZF/bvckWo8I33EqBm01lIPgmgc8rCA=="], + "@tokenizer/inflate": ["@tokenizer/inflate@0.4.1", "", { "dependencies": { "debug": "^4.4.3", "token-types": "^6.1.1" } }, "sha512-2mAv+8pkG6GIZiF1kNg1jAjh27IDxEPKwdGul3snfztFerfPGI1LjDezZp3i7BElXompqEtPmoPx6c2wgtWsOA=="], "@tokenizer/token": ["@tokenizer/token@0.3.0", "", {}, "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A=="], @@ -464,7 +464,7 @@ "consola": ["consola@3.4.2", "", {}, "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA=="], - "content-disposition": ["content-disposition@1.0.0", "", { "dependencies": { "safe-buffer": "5.2.1" } }, "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg=="], + "content-disposition": ["content-disposition@1.0.1", "", {}, "sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q=="], "content-type": ["content-type@1.0.5", "", {}, "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA=="], @@ -594,11 +594,9 @@ "fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="], - "fflate": ["fflate@0.8.2", "", {}, "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A=="], - "file-entry-cache": ["file-entry-cache@8.0.0", "", { "dependencies": { "flat-cache": "^4.0.0" } }, "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ=="], - "file-type": ["file-type@21.1.0", "", { "dependencies": { "@tokenizer/inflate": "^0.3.1", "strtok3": "^10.3.1", "token-types": "^6.0.0", "uint8array-extras": "^1.4.0" } }, "sha512-boU4EHmP3JXkwDo4uhyBhTt5pPstxB6eEXKJBu2yu2l7aAMMm7QQYQEzssJmKReZYrFdFOJS8koVo6bXIBGDqA=="], + "file-type": ["file-type@21.1.1", "", { "dependencies": { "@tokenizer/inflate": "^0.4.1", "strtok3": "^10.3.4", "token-types": "^6.1.1", "uint8array-extras": "^1.4.0" } }, "sha512-ifJXo8zUqbQ/bLbl9sFoqHNTNWbnPY1COImFfM6CCy7z+E+jC1eY9YfOKkx0fckIg+VljAy2/87T61fp0+eEkg=="], "fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="], @@ -614,7 +612,7 @@ "follow-redirects": ["follow-redirects@1.15.11", "", {}, "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ=="], - "form-data": ["form-data@4.0.4", "", { "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", "hasown": "^2.0.2", "mime-types": "^2.1.12" } }, "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow=="], + "form-data": ["form-data@4.0.5", "", { "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", "hasown": "^2.0.2", "mime-types": "^2.1.12" } }, "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w=="], "forwarded": ["forwarded@0.2.0", "", {}, "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow=="], @@ -654,7 +652,7 @@ "hasown": ["hasown@2.0.2", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ=="], - "http-errors": ["http-errors@2.0.0", "", { "dependencies": { "depd": "2.0.0", "inherits": "2.0.4", "setprototypeof": "1.2.0", "statuses": "2.0.1", "toidentifier": "1.0.1" } }, "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ=="], + "http-errors": ["http-errors@2.0.1", "", { "dependencies": { "depd": "~2.0.0", "inherits": "~2.0.4", "setprototypeof": "~1.2.0", "statuses": "~2.0.2", "toidentifier": "~1.0.1" } }, "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ=="], "http-proxy-agent": ["http-proxy-agent@7.0.2", "", { "dependencies": { "agent-base": "^7.1.0", "debug": "^4.3.4" } }, "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig=="], @@ -756,7 +754,7 @@ "mime-db": ["mime-db@1.54.0", "", {}, "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ=="], - "mime-types": ["mime-types@3.0.1", "", { "dependencies": { "mime-db": "^1.54.0" } }, "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA=="], + "mime-types": ["mime-types@3.0.2", "", { "dependencies": { "mime-db": "^1.54.0" } }, "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A=="], "minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="], @@ -772,7 +770,7 @@ "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], - "music-metadata": ["music-metadata@11.10.0", "", { "dependencies": { "@borewit/text-codec": "^0.2.0", "@tokenizer/token": "^0.3.0", "content-type": "^1.0.5", "debug": "^4.4.3", "file-type": "^21.0.0", "media-typer": "^1.1.0", "strtok3": "^10.3.4", "token-types": "^6.1.1", "uint8array-extras": "^1.5.0" } }, "sha512-alZYPjpqAPFgVZaFQob0PMq/9tSqaR+3m159vavrptxj09P0GcyBkDQI/wuCyn4uz/TDCrS8gN+9SzURlahmdQ=="], + "music-metadata": ["music-metadata@11.10.2", "", { "dependencies": { "@borewit/text-codec": "^0.2.0", "@tokenizer/token": "^0.3.0", "content-type": "^1.0.5", "debug": "^4.4.3", "file-type": "^21.1.1", "media-typer": "^1.1.0", "strtok3": "^10.3.4", "token-types": "^6.1.1", "uint8array-extras": "^1.5.0" } }, "sha512-sGbF+Si+GqYJGO6qQDyfvesfxb1M49m0QjLLkGR5zoRlPaZtHRvo8DDI5R/vySJVtUzTQ6Lwfd7nspYpmmInsA=="], "n-gram": ["n-gram@2.0.2", "", {}, "sha512-S24aGsn+HLBxUGVAUFOwGpKs7LBcG4RudKU//eWzt/mQ97/NMKQxDWHyHx63UNWk/OOdihgmzoETn1tf5nQDzQ=="], @@ -884,7 +882,7 @@ "range-parser": ["range-parser@1.2.1", "", {}, "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="], - "raw-body": ["raw-body@3.0.1", "", { "dependencies": { "bytes": "3.1.2", "http-errors": "2.0.0", "iconv-lite": "0.7.0", "unpipe": "1.0.0" } }, "sha512-9G8cA+tuMS75+6G/TzW8OtLzmBDMo8p1JRxN5AZ+LAp8uxGA8V8GZm4GQ4/N5QNQEnLmg6SS7wyuSmbKepiKqA=="], + "raw-body": ["raw-body@3.0.2", "", { "dependencies": { "bytes": "~3.1.2", "http-errors": "~2.0.1", "iconv-lite": "~0.7.0", "unpipe": "~1.0.0" } }, "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA=="], "readable-stream": ["readable-stream@3.6.2", "", { "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA=="], @@ -1118,8 +1116,6 @@ "form-data/mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="], - "http-errors/statuses": ["statuses@2.0.1", "", {}, "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ=="], - "micromatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], "mlly/pkg-types": ["pkg-types@1.3.1", "", { "dependencies": { "confbox": "^0.1.8", "mlly": "^1.7.4", "pathe": "^2.0.1" } }, "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ=="], @@ -1198,8 +1194,6 @@ "qrcode/yargs/string-width/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], - "qrcode/yargs/yargs-parser/camelcase": ["camelcase@5.3.1", "", {}, "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg=="], - "args/chalk/ansi-styles/color-convert/color-name": ["color-name@1.1.3", "", {}, "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="], "node-windows/yargs/cliui/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], diff --git a/package.json b/package.json index 45c1fef..bf3196c 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,7 @@ "@fontsource/roboto": "^5.2.8", "@iconify-json/material-symbols": "^1.2.46", "@iconify-json/svg-spinners": "^1.2.4", - "@neteasecloudmusicapienhanced/api": "^4.29.17", + "@neteasecloudmusicapienhanced/api": "4.29.17", "@openrouter/sdk": "^0.1.17", "@unocss/core": "^66.5.6", "@unocss/extractor-svelte": "^66.5.6", diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index 76f5360..39f0512 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -31,7 +31,7 @@ -
+
{@render children()}
diff --git a/src/style/app.sass b/src/style/app.sass index 1404c06..3ae069f 100644 --- a/src/style/app.sass +++ b/src/style/app.sass @@ -37,4 +37,8 @@ body align-self: stretch overflow-y: auto min-height: 0 - flex: 1 \ No newline at end of file + flex: 1 + +.app-container + max-width: 1200px; + margin: 0 auto; \ No newline at end of file From 33e7db56426b14a714d94c24b509bef5c84ee698 Mon Sep 17 00:00:00 2001 From: Courier Date: Sat, 22 Nov 2025 22:35:21 +0400 Subject: [PATCH 02/10] lang var update, ui update --- src/lib/i18n/en.ts | 5 +++++ src/lib/i18n/ja.ts | 5 +++++ src/lib/i18n/zh.ts | 5 +++++ src/lib/server/songs.ts | 18 +++++++++--------- src/routes/+error.svelte | 20 ++++++++++++++++++++ src/style/app.sass | 5 ++++- 6 files changed, 48 insertions(+), 10 deletions(-) create mode 100644 src/routes/+error.svelte diff --git a/src/lib/i18n/en.ts b/src/lib/i18n/en.ts index d8176dd..39dbdbe 100644 --- a/src/lib/i18n/en.ts +++ b/src/lib/i18n/en.ts @@ -127,5 +127,10 @@ export default { loginWithCode: 'Login with Sync Code', login: 'Login' } + }, + errorPage: { + title: 'Oops!', + message: 'The page you’re looking for doesn’t exist. It might have been removed, renamed, or never existed.\n\n

Go back to the homepage to continue browsing', + return: 'Return home', } } \ No newline at end of file diff --git a/src/lib/i18n/ja.ts b/src/lib/i18n/ja.ts index 0cdff11..8f2757e 100644 --- a/src/lib/i18n/ja.ts +++ b/src/lib/i18n/ja.ts @@ -127,5 +127,10 @@ export default { loginWithCode: '引き継ぎコードでログイン', login: 'ログイン' } + }, + errorPage: { + title: 'Oops!', + message: 'The page you’re looking for doesn’t exist. It might have been removed, renamed, or never existed.\n\n

Go back to the homepage to continue browsing', + return: 'Return home', } } diff --git a/src/lib/i18n/zh.ts b/src/lib/i18n/zh.ts index 305c876..9163ad3 100644 --- a/src/lib/i18n/zh.ts +++ b/src/lib/i18n/zh.ts @@ -127,5 +127,10 @@ export default { loginWithCode: '用引继码登录', login: '登录' } + }, + errorPage: { + title: 'Oops!', + message: 'The page you’re looking for doesn’t exist. It might have been removed, renamed, or never existed.\n\n

Go back to the homepage to continue browsing', + return: 'Return home', } } \ No newline at end of file diff --git a/src/lib/server/songs.ts b/src/lib/server/songs.ts index fbc00de..d41124c 100644 --- a/src/lib/server/songs.ts +++ b/src/lib/server/songs.ts @@ -140,7 +140,7 @@ export const getSongUrl = async (id: number | string) => { // ///////////////////////////////////////////////////////////////////////////// // API for Song Preparation -export interface ProgressItem { id: string, task: string, progress: number } +export interface ProgressItem { task: string, progress: number } export interface SongProcessState { items: ProgressItem[], status: 'running' | 'done' | 'error' } const songProcessingStatus = new Map() @@ -152,20 +152,20 @@ export const prepareSong = async (songId: number) => { const state: SongProcessState = { items: [], status: 'running' } songProcessingStatus.set(songId, state) - const addTask = (id: string, task: string) => ({ id, task, progress: 0 }).also(it => state.items.push(it)) + const addTask = (task: string) => ({ task, progress: 0 }).also(it => state.items.push(it)) try { // 1. Get Lyrics - const taskLyrics = addTask('lyrics', '从网易云获取歌词') + const taskLyrics = addTask('从网易云获取歌词') const raw = await getLyricsRaw(songId) taskLyrics.progress = 1 if (raw.lang !== 'jpn') { - addTask('error', '错误: 不是日语歌曲').progress = -1 + addTask('错误: 不是日语歌曲').progress = -1 return state.status = 'error' } // 2. AI Process - const taskAI = addTask('ai', 'AI 标注歌词读音') + const taskAI = addTask('AI 标注歌词读音') // Check cache if (await checkLyricsProcessed(songId)) taskAI.progress = 1 @@ -176,12 +176,12 @@ export const prepareSong = async (songId: number) => { } // 3. Audio - const taskAudio = addTask('music', '从网易云获取音乐') + const taskAudio = addTask('从网易云获取音乐') await getSongUrl(songId) taskAudio.progress = 1 // 4. Source Separation - const taskSeparation = addTask('separation', 'AI 人声分离') + const taskSeparation = addTask('AI 人声分离') const inputPath = path.join(CACHE_DIR, `${songId}/exhigh.mp3`) const outputDir = path.join(CACHE_DIR, `${songId}`) @@ -189,14 +189,14 @@ export const prepareSong = async (songId: number) => { await separateSong(inputPath, outputDir) taskSeparation.progress = 1 } catch (e: any) { - addTask('error', `错误: ${e.message}`).progress = -1 + addTask(`错误: ${e.message}`).progress = -1 // Don't fail the whole process, just this step } state.status = 'done' } catch (e) { - addTask('error', `错误: ${eToString(e)}`).progress = -1 + addTask(`错误: ${eToString(e)}`).progress = -1 state.status = 'error' } } diff --git a/src/routes/+error.svelte b/src/routes/+error.svelte new file mode 100644 index 0000000..ed9c99a --- /dev/null +++ b/src/routes/+error.svelte @@ -0,0 +1,20 @@ + + + + 404 — Page Not Found + + +
+ + + +
+

{@html t.message}

+ {t.return} +
+
diff --git a/src/style/app.sass b/src/style/app.sass index 3ae069f..3719353 100644 --- a/src/style/app.sass +++ b/src/style/app.sass @@ -41,4 +41,7 @@ body .app-container max-width: 1200px; - margin: 0 auto; \ No newline at end of file + margin: 0 auto; + +.error-page__link + text-decoration: underline; \ No newline at end of file From 7445966a61b05946fbc73261e85a92bdff6acbce Mon Sep 17 00:00:00 2001 From: Courier Date: Sat, 22 Nov 2025 23:04:51 +0400 Subject: [PATCH 03/10] 404 page ui --- src/routes/+error.svelte | 9 ++++++--- src/style/app.sass | 18 +++++++++++++++++- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/src/routes/+error.svelte b/src/routes/+error.svelte index ed9c99a..eed604c 100644 --- a/src/routes/+error.svelte +++ b/src/routes/+error.svelte @@ -1,5 +1,6 @@ - - 404 — Page Not Found - -
- - - +

{@html t.message}

- + + +
diff --git a/src/style/app.sass b/src/style/app.sass index 61ee9ec..cc77d3f 100644 --- a/src/style/app.sass +++ b/src/style/app.sass @@ -59,5 +59,4 @@ body .error-page__button-container position: absolute; bottom: 16px; - width: calc(100% - 32px) - max-width: 450px; \ No newline at end of file + width: calc(100% - 32px) \ No newline at end of file From fd13846a5bb4bb40e3192e7416764ce7be3e83e1 Mon Sep 17 00:00:00 2001 From: Courier Date: Sat, 22 Nov 2025 23:13:25 +0400 Subject: [PATCH 05/10] 404 page init --- src/style/app.sass | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/style/app.sass b/src/style/app.sass index cc77d3f..6fb3a28 100644 --- a/src/style/app.sass +++ b/src/style/app.sass @@ -40,23 +40,23 @@ body flex: 1 .app-container - max-width: 1200px; - margin: 0 auto; + max-width: 1200px + margin: 0 auto .error-page__link - text-decoration: underline; + text-decoration: underline .error-page__button - display: flex; - align-items: center; - justify-content: center; - width: 100%; + display: flex + align-items: center + justify-content: center + width: 100% .error-page__text - margin-top: 12px; + margin-top: 12px .error-page__button-container - position: absolute; - bottom: 16px; + position: absolute + bottom: 16px width: calc(100% - 32px) \ No newline at end of file From a3fbcbffb2365c989d6e7bfa108e48014c459b14 Mon Sep 17 00:00:00 2001 From: Courier Date: Sat, 22 Nov 2025 23:17:00 +0400 Subject: [PATCH 06/10] 404 page init --- src/routes/+error.svelte | 1 - 1 file changed, 1 deletion(-) diff --git a/src/routes/+error.svelte b/src/routes/+error.svelte index 3a0c739..44dbbe5 100644 --- a/src/routes/+error.svelte +++ b/src/routes/+error.svelte @@ -2,7 +2,6 @@ import AppBar from "$lib/ui/appbar/AppBar.svelte"; import Button from "$lib/ui/Button.svelte"; import { getI18n } from "$lib/i18n"; - import { goto } from '$app/navigation'; const t = getI18n().errorPage; From 11d20c560c3e4e840106fc1dae86a1536ae1a9f5 Mon Sep 17 00:00:00 2001 From: Azalea <22280294+hykilpikonna@users.noreply.github.com> Date: Sun, 23 Nov 2025 09:00:44 +0800 Subject: [PATCH 07/10] [-] Revert unintended changes --- src/lib/server/songs.ts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/lib/server/songs.ts b/src/lib/server/songs.ts index d41124c..fbc00de 100644 --- a/src/lib/server/songs.ts +++ b/src/lib/server/songs.ts @@ -140,7 +140,7 @@ export const getSongUrl = async (id: number | string) => { // ///////////////////////////////////////////////////////////////////////////// // API for Song Preparation -export interface ProgressItem { task: string, progress: number } +export interface ProgressItem { id: string, task: string, progress: number } export interface SongProcessState { items: ProgressItem[], status: 'running' | 'done' | 'error' } const songProcessingStatus = new Map() @@ -152,20 +152,20 @@ export const prepareSong = async (songId: number) => { const state: SongProcessState = { items: [], status: 'running' } songProcessingStatus.set(songId, state) - const addTask = (task: string) => ({ task, progress: 0 }).also(it => state.items.push(it)) + const addTask = (id: string, task: string) => ({ id, task, progress: 0 }).also(it => state.items.push(it)) try { // 1. Get Lyrics - const taskLyrics = addTask('从网易云获取歌词') + const taskLyrics = addTask('lyrics', '从网易云获取歌词') const raw = await getLyricsRaw(songId) taskLyrics.progress = 1 if (raw.lang !== 'jpn') { - addTask('错误: 不是日语歌曲').progress = -1 + addTask('error', '错误: 不是日语歌曲').progress = -1 return state.status = 'error' } // 2. AI Process - const taskAI = addTask('AI 标注歌词读音') + const taskAI = addTask('ai', 'AI 标注歌词读音') // Check cache if (await checkLyricsProcessed(songId)) taskAI.progress = 1 @@ -176,12 +176,12 @@ export const prepareSong = async (songId: number) => { } // 3. Audio - const taskAudio = addTask('从网易云获取音乐') + const taskAudio = addTask('music', '从网易云获取音乐') await getSongUrl(songId) taskAudio.progress = 1 // 4. Source Separation - const taskSeparation = addTask('AI 人声分离') + const taskSeparation = addTask('separation', 'AI 人声分离') const inputPath = path.join(CACHE_DIR, `${songId}/exhigh.mp3`) const outputDir = path.join(CACHE_DIR, `${songId}`) @@ -189,14 +189,14 @@ export const prepareSong = async (songId: number) => { await separateSong(inputPath, outputDir) taskSeparation.progress = 1 } catch (e: any) { - addTask(`错误: ${e.message}`).progress = -1 + addTask('error', `错误: ${e.message}`).progress = -1 // Don't fail the whole process, just this step } state.status = 'done' } catch (e) { - addTask(`错误: ${eToString(e)}`).progress = -1 + addTask('error', `错误: ${eToString(e)}`).progress = -1 state.status = 'error' } } From 8ebad5d32b1452a15d479b0e9a116f9114b8529c Mon Sep 17 00:00:00 2001 From: Azalea <22280294+hykilpikonna@users.noreply.github.com> Date: Sun, 23 Nov 2025 09:18:21 +0800 Subject: [PATCH 08/10] [O] css > tailwind --- src/routes/+error.svelte | 20 +++++++++----------- src/routes/+layout.svelte | 2 +- src/style/app.sass | 22 ---------------------- 3 files changed, 10 insertions(+), 34 deletions(-) diff --git a/src/routes/+error.svelte b/src/routes/+error.svelte index 44dbbe5..6f64e37 100644 --- a/src/routes/+error.svelte +++ b/src/routes/+error.svelte @@ -5,15 +5,13 @@ const t = getI18n().errorPage; - -
- -
-

{@html t.message}

- + + +
+

{@html t.message}

+ -
+
diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index 4224746..bd40088 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -33,7 +33,7 @@ -
+
{@render children()}
diff --git a/src/style/app.sass b/src/style/app.sass index 6fb3a28..62f27fa 100644 --- a/src/style/app.sass +++ b/src/style/app.sass @@ -38,25 +38,3 @@ body overflow-y: auto min-height: 0 flex: 1 - -.app-container - max-width: 1200px - margin: 0 auto - -.error-page__link - text-decoration: underline - -.error-page__button - display: flex - align-items: center - justify-content: center - width: 100% - - -.error-page__text - margin-top: 12px - -.error-page__button-container - position: absolute - bottom: 16px - width: calc(100% - 32px) \ No newline at end of file From d2a1de93ee55e65a2308181ad05316b54ea2a28d Mon Sep 17 00:00:00 2001 From: Azalea <22280294+hykilpikonna@users.noreply.github.com> Date: Sun, 23 Nov 2025 09:27:29 +0800 Subject: [PATCH 09/10] [S] Use flexbox instead of position: absolute --- src/routes/+error.svelte | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/routes/+error.svelte b/src/routes/+error.svelte index 6f64e37..1d054e8 100644 --- a/src/routes/+error.svelte +++ b/src/routes/+error.svelte @@ -7,9 +7,9 @@ -
-

{@html t.message}

-
+
+

{@html t.message}

+
From 3d42b72c8b52fd4e23cd6dd0ed649869ff0c75b5 Mon Sep 17 00:00:00 2001 From: Azalea <22280294+hykilpikonna@users.noreply.github.com> Date: Sun, 23 Nov 2025 09:29:37 +0800 Subject: [PATCH 10/10] [+] i18n for error page --- src/lib/i18n/ja.ts | 6 +++--- src/lib/i18n/zh.ts | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/lib/i18n/ja.ts b/src/lib/i18n/ja.ts index 8f2757e..ca2e986 100644 --- a/src/lib/i18n/ja.ts +++ b/src/lib/i18n/ja.ts @@ -129,8 +129,8 @@ export default { } }, errorPage: { - title: 'Oops!', - message: 'The page you’re looking for doesn’t exist. It might have been removed, renamed, or never existed.\n\n

Go back to the homepage to continue browsing', - return: 'Return home', + title: 'おっと!', + message: 'お探しのページは見つかりませんでした。削除されたか、名前が変更されたか、あるいは最初から存在しなかった可能性があります。\n\n

トップページ に戻って閲覧を続けてください', + return: 'トップページに戻る', } } diff --git a/src/lib/i18n/zh.ts b/src/lib/i18n/zh.ts index 9163ad3..06d423f 100644 --- a/src/lib/i18n/zh.ts +++ b/src/lib/i18n/zh.ts @@ -129,8 +129,8 @@ export default { } }, errorPage: { - title: 'Oops!', - message: 'The page you’re looking for doesn’t exist. It might have been removed, renamed, or never existed.\n\n

Go back to the homepage to continue browsing', - return: 'Return home', + title: '哎呀!', + message: '您寻找的页面不存在。它可能已被删除、重命名或从未存在过。\n\n

返回 首页 继续浏览', + return: '返回首页', } } \ No newline at end of file