diff --git a/core/settings.py b/core/settings.py index e9c405b..350c052 100644 --- a/core/settings.py +++ b/core/settings.py @@ -68,10 +68,11 @@ DATABASES = { } # 静态文件设置 +STATIC_EXTRA_DIR = 'static' STATIC_URL = '/static/' STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles') STATICFILES_DIRS = [ - os.path.join(BASE_DIR, 'static'), + os.path.join(BASE_DIR, STATIC_EXTRA_DIR), ] # 默认自动字段类型 diff --git a/docker.sh b/docker.sh index 6ca6af8..31bbde6 100755 --- a/docker.sh +++ b/docker.sh @@ -32,7 +32,7 @@ case "$1" in docker-compose exec web bash ;; "static") - docker-compose exec web uv run manage.py makemigrations + docker-compose exec web uv run manage.py collectstatic ;; "migrate") docker-compose exec web uv run manage.py makemigrations diff --git a/links/api_urls.py b/links/api_urls.py index d41a928..4be69cf 100644 --- a/links/api_urls.py +++ b/links/api_urls.py @@ -2,11 +2,13 @@ from django.urls import path, include from rest_framework.routers import DefaultRouter from . import page_views from . import newsletter_views +from . import api_views # Create a router and register our viewsets with it router = DefaultRouter(trailing_slash=False) router.register('pages', page_views.PageViewSet, basename='api-pages') router.register('newsletters', newsletter_views.NewsletterViewSet, basename='api-newsletters') +router.register('music', api_views.MusicViewSet, basename='api-music') # The API URLs are determined automatically by the router urlpatterns = [ diff --git a/links/api_views.py b/links/api_views.py index 9a36f8c..96379e6 100644 --- a/links/api_views.py +++ b/links/api_views.py @@ -7,6 +7,9 @@ from .serializers import ImageCollectionSerializer, ImageSerializer from .storage import R2Storage import uuid import logging +from django.conf import settings +import os + logger = logging.getLogger(__name__) @@ -138,3 +141,13 @@ class ImageViewSet(viewsets.ModelViewSet): except Exception as e: logger.error(f"Failed to delete from storage: {e}") instance.delete() + +class MusicViewSet(viewsets.ViewSet): + def list(self, request): + + return Response([ + {'title': 'Purple Planet', 'src': '/static/music/Purple-Planet.mp3'}, + {'title': 'Just Kidding', 'src': '/static/music/mixkit-just-kidding.mp3'}, + {'title': 'Thomas', 'src': '/static/music/Thomas-the-Tank-Engine.mp3'} + ]) + \ No newline at end of file diff --git a/links/templates/links/collection_slideshow.html b/links/templates/links/collection_slideshow.html index a395bff..d63611f 100644 --- a/links/templates/links/collection_slideshow.html +++ b/links/templates/links/collection_slideshow.html @@ -76,12 +76,16 @@ } .progress-circle { position: fixed; - bottom: 1rem; + top: 1rem; right: 1rem; width: 24px; height: 24px; z-index: 50; opacity: 0.8; + transition: opacity 0.3s; + } + .slideshow-container:hover .progress-circle { + opacity: 1; } .progress-circle-bg { fill: none; @@ -127,6 +131,7 @@ min-height: 44px; display: flex; align-items: center; + gap: 0.5rem; } .playlist-item:hover { background-color: rgba(255, 255, 255, 0.1); @@ -135,6 +140,31 @@ background-color: rgba(59, 130, 246, 0.5); font-weight: 500; } + .playlist-item input[type="checkbox"] { + width: 18px; + height: 18px; + margin: 0; + } + .playlist-controls { + display: flex; + justify-content: center; + margin-top: 1rem; + padding-top: 1rem; + border-top: 1px solid rgba(255, 255, 255, 0.1); + } + .playlist-controls button { + background: rgba(59, 130, 246, 0.5); + color: white; + border: none; + padding: 0.5rem 1rem; + border-radius: 0.375rem; + cursor: pointer; + transition: background-color 0.2s; + font-size: 0.9rem; + } + .playlist-controls button:hover { + background: rgba(59, 130, 246, 0.7); + } .playlist-content h3 { color: #fff; margin: 0; @@ -244,7 +274,7 @@ -