Files

74 lines
2.5 KiB
Python

"""根路由。
所有 api/v1/* 端点都允许匿名访问(ping、JWT 登录),业务 API 在 ViewSet 层用 permission 拦截。
"""
from django.contrib import admin
from django.urls import path, include
from rest_framework_simplejwt.views import (
TokenRefreshView,
)
from apps.core.auth_views import RateLimitedTokenObtainPairView
from rest_framework.permissions import AllowAny
from rest_framework.decorators import (
authentication_classes,
permission_classes,
api_view,
)
from rest_framework.response import Response
from datetime import datetime, timezone
import django
import granian
import sys
from apps.core.urls import core_urlpatterns
from apps.finance.views import public_statement
from apps.core.demo import enter_demo
from apps.core.register import register
@api_view(["GET"])
@authentication_classes([])
@permission_classes([AllowAny])
def ping(request):
return Response({
"ok": True,
"service": "dealerhub",
"ts": datetime.now(timezone.utc).isoformat(),
"versions": {
"python": sys.version.split()[0],
"django": django.get_version(),
"granian": getattr(granian, "__version__", "unknown"),
},
})
def spa_index(request):
"""Vue3 SPA 入口(hash 路由,仅需托管根路径)。"""
from django.conf import settings
from django.http import FileResponse, JsonResponse
index_path = settings.FRONTEND_DIST / "index.html"
if index_path.exists():
return FileResponse(index_path.open("rb"), content_type="text/html")
return JsonResponse(
{"detail": "前端资源未构建:请先执行 npm run build 并重新打包镜像"},
status=404,
)
urlpatterns = [
path("admin/", admin.site.urls),
path("api/v1/ping/", ping, name="ping"),
path("api/v1/auth/token/", RateLimitedTokenObtainPairView.as_view(), name="token_obtain_pair"),
path("api/v1/auth/token/refresh/", TokenRefreshView.as_view(), name="token_refresh"),
path("api/v1/auth/register/", register, name="auth-register"),
path("api/v1/open/statements/<uuid:token>/", public_statement, name="public-statement"),
path("api/v1/demo/enter/", enter_demo, name="demo-enter"),
path("api/v1/", include(core_urlpatterns)),
# Vue3 SPA(静态资源走 /static/ 由 whitenoise 托管)
# 营销官网(批次 C3):/site/* 静态页,与 SPA 分离便于 SEO
path("site/", include("apps.website.urls")),
path("", spa_index, name="spa-index"),
]