From a77534c72be468df9219d1ca1a3f21d313b063fc Mon Sep 17 00:00:00 2001 From: AnthonyDuan Date: Sat, 22 Nov 2025 23:25:10 +0800 Subject: [PATCH] =?UTF-8?q?feat(type):=20=E6=96=B0=E5=A2=9E=E6=AD=8C?= =?UTF-8?q?=E6=9B=B2=E7=B1=BB=E5=9E=8B=E6=A8=A1=E5=9E=8B=E4=B8=8E=E6=A0=A1?= =?UTF-8?q?=E9=AA=8C=EF=BC=9B/api/songs=20=E6=94=AF=E6=8C=81=E6=8C=89?= =?UTF-8?q?=E7=B1=BB=E5=9E=8B=E8=BF=87=E6=BB=A4=EF=BC=9B=E4=B8=8A=E4=BC=A0?= =?UTF-8?q?=E9=A1=B5=E5=A2=9E=E5=8A=A0=E7=B1=BB=E5=9E=8B=E9=80=89=E6=8B=A9?= =?UTF-8?q?=EF=BC=9B=E6=AD=8C=E6=9B=B2=E9=80=89=E6=8B=A9=E9=A1=B5=E6=94=AF?= =?UTF-8?q?=E6=8C=81=E5=B7=A6=E5=8F=B3=E5=88=87=E6=8D=A2=E7=B1=BB=E5=9E=8B?= =?UTF-8?q?=E5=B9=B6=E6=98=BE=E7=A4=BA=E6=A0=87=E7=AD=BE=EF=BC=9BREADME=20?= =?UTF-8?q?=E8=A1=A5=E5=85=85=E8=AF=B4=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 27 ++++++++++++++++++ app.py | 28 ++++++++++++++++++- public/src/js/songselect.js | 55 +++++++++++++++++++++++++++++++------ public/upload/index.html | 15 ++++++++++ 4 files changed, 116 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index f0c091b..77f3802 100644 --- a/README.md +++ b/README.md @@ -94,3 +94,30 @@ docker run --detach \ --- 如需将监听接口改为仅内网或增加并发工作数(例如 `--workers 4`),可在 `setup.sh` 或 `systemd` 服务中调整。 +## 歌曲类型(Type) + +- 可选枚举: + - 01 Pop + - 02 Anime + - 03 Vocaloid + - 04 Children and Folk + - 05 Variety + - 06 Classical + - 07 Game Music + - 08 Live Festival Mode + - 09 Namco Original + - 10 Taiko Towers + - 11 Dan Dojo + +### 上传要求 +- 上传表单新增必填字段 `song_type`,取值为上述枚举之一 +- 成功后将写入 MongoDB `songs.song_type` + +### API 扩展 +- `GET /api/songs?type=<歌曲类型>` 按类型过滤返回启用歌曲 +- 示例:`/api/songs?type=02%20Anime` +- 返回项包含 `song_type` 字段 + +### 前端切换 +- 在歌曲选择页顶部显示当前歌曲类型标签 +- 使用左右跳转(Shift+左右或肩键)自动切换类型并刷新列表 diff --git a/app.py b/app.py index 0b6203a..4b12cde 100644 --- a/app.py +++ b/app.py @@ -45,6 +45,19 @@ def take_config(name, required=False): return None app = Flask(__name__) +SONG_TYPES = [ + "01 Pop", + "02 Anime", + "03 Vocaloid", + "04 Children and Folk", + "05 Variety", + "06 Classical", + "07 Game Music", + "08 Live Festival Mode", + "09 Namco Original", + "10 Taiko Towers", + "11 Dan Dojo", +] def get_remote_address() -> str: return flask.request.headers.get("CF-Connecting-IP") or flask.request.headers.get("X-Forwarded-For") or flask.request.remote_addr or "127.0.0.1" @@ -90,6 +103,7 @@ sess.init_app(app) db = client[take_config('MONGO', required=True)['database']] db.users.create_index('username', unique=True) db.songs.create_index('id', unique=True) +db.songs.create_index('song_type') db.scores.create_index('username') @@ -480,7 +494,13 @@ def route_api_preview(): @app.route(basedir + 'api/songs') @app.cache.cached(timeout=15) def route_api_songs(): - songs = list(db.songs.find({'enabled': True}, {'_id': False, 'enabled': False})) + type_q = flask.request.args.get('type') + query = {'enabled': True} + if type_q: + if type_q not in SONG_TYPES: + return abort(400) + query['song_type'] = type_q + songs = list(db.songs.find(query, {'_id': False, 'enabled': False})) for song in songs: if song['maker_id']: if song['maker_id'] == 0: @@ -853,6 +873,12 @@ def upload_file(): db_entry['enabled'] = True pprint.pprint(db_entry) + # 必要な歌曲类型 + song_type = flask.request.form.get('song_type') + if not song_type or song_type not in SONG_TYPES: + return flask.jsonify({'error': 'invalid_song_type'}) + db_entry['song_type'] = song_type + # mongoDBにデータをぶち込む(重複IDは部分更新で上書きし、_id を不変に保つ) coll = client['taiko']["songs"] try: diff --git a/public/src/js/songselect.js b/public/src/js/songselect.js index 58ba125..343645b 100644 --- a/public/src/js/songselect.js +++ b/public/src/js/songselect.js @@ -386,6 +386,32 @@ class SongSelect{ } this.songSelect = document.getElementById("song-select") + this.songTypes = [ + "01 Pop", + "02 Anime", + "03 Vocaloid", + "04 Children and Folk", + "05 Variety", + "06 Classical", + "07 Game Music", + "08 Live Festival Mode", + "09 Namco Original", + "10 Taiko Towers", + "11 Dan Dojo", + ] + this.songTypeIndex = Math.max(0, Math.min(this.songTypes.length - 1, +(localStorage.getItem("songTypeIndex") || 0))) + this.typeLabel = document.createElement("div") + this.typeLabel.style.position = "absolute" + this.typeLabel.style.top = "8px" + this.typeLabel.style.left = "12px" + this.typeLabel.style.padding = "4px 8px" + this.typeLabel.style.background = "rgba(0,0,0,0.5)" + this.typeLabel.style.color = "#fff" + this.typeLabel.style.borderRadius = "6px" + this.typeLabel.style.fontSize = "14px" + this.typeLabel.style.zIndex = "10" + this.songSelect.appendChild(this.typeLabel) + this.updateTypeLabel() var cat = this.songs[this.selectedSong].originalCategory this.drawBackground(cat) @@ -536,24 +562,20 @@ class SongSelect{ this.toSession() }else if(name === "left"){ if(shift){ - if(!repeat){ - this.categoryJump(-1) - } + if(!repeat){ this.changeType(-1) } }else{ this.moveToSong(-1) } }else if(name === "right"){ if(shift){ - if(!repeat){ - this.categoryJump(1) - } + if(!repeat){ this.changeType(1) } }else{ this.moveToSong(1) } }else if(name === "jump_left" && !repeat){ - this.categoryJump(-1) + this.changeType(-1) }else if(name === "jump_right" && !repeat){ - this.categoryJump(1) + this.changeType(1) }else if(name === "mute" || name === "ctrlGamepad"){ this.endPreview(true) this.playBgm(false) @@ -597,6 +619,23 @@ class SongSelect{ } } } + + updateTypeLabel(){ + this.setAltText(this.typeLabel, this.songTypes[this.songTypeIndex]) + } + + changeType(delta){ + this.songTypeIndex = (this.songTypeIndex + delta + this.songTypes.length) % this.songTypes.length + localStorage.setItem("songTypeIndex", this.songTypeIndex) + this.updateTypeLabel() + var type = encodeURIComponent(this.songTypes[this.songTypeIndex]) + loader.ajax("api/songs?type=" + type).then(resp => { + var songs = JSON.parse(resp) + assets.songsDefault = songs + assets.songs = assets.songsDefault + new SongSelect(false, false, this.touchEnabled) + }).catch(() => {}) + } mouseDown(event){ if(event.target === this.selectable || event.target.parentNode === this.selectable){ diff --git a/public/upload/index.html b/public/upload/index.html index 6c43997..b940417 100644 --- a/public/upload/index.html +++ b/public/upload/index.html @@ -16,6 +16,21 @@ + + +