From ff3c0d8feadf3a5b083ae9176b20880894925b2b Mon Sep 17 00:00:00 2001 From: caoqianming Date: Mon, 27 Apr 2026 10:19:51 +0800 Subject: [PATCH] =?UTF-8?q?feat(h5):=20runserver=20=E5=90=8C=E6=97=B6?= =?UTF-8?q?=E6=89=98=E7=AE=A1=20H5=20SPA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 /m/ 路由:直出 frontend-h5/dist 下静态资源;不存在的路径回退到 dist/index.html 以支持 vue-router history 模式刷新/直链 - PC 通配路由排除 m/,避免被 PC 的 index.html 拦截 Co-Authored-By: Claude Opus 4.7 --- backend/config/urls.py | 12 +++++++++--- backend/config/views.py | 18 ++++++++++++++++++ 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/backend/config/urls.py b/backend/config/urls.py index c665bd9..50ee39d 100644 --- a/backend/config/urls.py +++ b/backend/config/urls.py @@ -7,7 +7,7 @@ from django.conf import settings from django.conf.urls.static import static from django.views.generic import TemplateView -from .views import upload_image +from .views import upload_image, serve_h5 urlpatterns = [ path('admin/', admin.site.urls), @@ -25,9 +25,15 @@ if settings.DEBUG: urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) urlpatterns += static('/assets/', document_root=settings.BASE_DIR / 'dist' / 'assets') -# 前端单页应用入口 +# H5 子应用:必须放在 PC 通配路由之前 urlpatterns += [ - re_path(r'^(?!api/|admin/|media/).*$', + re_path(r'^m/?$', serve_h5, name='h5-index'), + re_path(r'^m/(?P.*)$', serve_h5, name='h5-assets'), +] + +# 前端单页应用入口(PC 端) +urlpatterns += [ + re_path(r'^(?!api/|admin/|media/|m/).*$', TemplateView.as_view(template_name='index.html'), name='frontend-index'), ] diff --git a/backend/config/views.py b/backend/config/views.py index bfdb61f..a8927c1 100644 --- a/backend/config/views.py +++ b/backend/config/views.py @@ -1,7 +1,9 @@ import os import uuid +from pathlib import Path from django.conf import settings +from django.views.static import serve as static_serve from rest_framework.decorators import api_view, permission_classes, parser_classes from rest_framework.permissions import IsAuthenticated from rest_framework.parsers import MultiPartParser @@ -9,6 +11,22 @@ from rest_framework.response import Response from rest_framework import status +H5_DIST_ROOT = Path(settings.BASE_DIR).parent / 'frontend-h5' / 'dist' + + +def serve_h5(request, path=''): + """ + H5 SPA 静态资源 + history 路由回退。 + - /m/ 或 /m/(无扩展名/不存在的路径)→ 返回 dist/index.html + - /m/assets/xxx.js, /m/img/xxx.jpg 等真实存在的文件 → 直出 + """ + if path: + candidate = H5_DIST_ROOT / path + if candidate.is_file(): + return static_serve(request, path, document_root=str(H5_DIST_ROOT)) + return static_serve(request, 'index.html', document_root=str(H5_DIST_ROOT)) + + ALLOWED_IMAGE_TYPES = { 'image/jpeg', 'image/png', 'image/gif', 'image/webp', 'image/bmp', }