feat(h5): runserver 同时托管 H5 SPA

- 新增 /m/ 路由:直出 frontend-h5/dist 下静态资源;不存在的路径回退到 dist/index.html
  以支持 vue-router history 模式刷新/直链
- PC 通配路由排除 m/,避免被 PC 的 index.html 拦截

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
caoqianming 2026-04-27 10:19:51 +08:00
parent 76b2c08801
commit ff3c0d8fea
2 changed files with 27 additions and 3 deletions

View File

@ -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<path>.*)$', serve_h5, name='h5-assets'),
]
# 前端单页应用入口PC 端)
urlpatterns += [
re_path(r'^(?!api/|admin/|media/|m/).*$',
TemplateView.as_view(template_name='index.html'),
name='frontend-index'),
]

View File

@ -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/<route>无扩展名/不存在的路径 返回 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',
}