feat: 现代化翻页组件 + 完整项目更新
- 新增 Pagination 通用组件:首页/上一页/页码/下一页/末页导航 - PickModal 和 SwapModal 集成分页功能,每页20项 - 搜索/筛选切换自动回到第1页 - 现代化CSS样式:hover浮起动效、主色高亮、移动端适配 - 新增 dashboard、admin 管理模板 - 菜系(cuisine)模型和迁移 - 构建脚本 build.py 支持 PyInstaller 打包 - 前端资源重新构建
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
import mimetypes
|
||||
import os
|
||||
|
||||
from django.http import FileResponse, HttpResponseNotFound
|
||||
from django.views.decorators.csrf import ensure_csrf_cookie
|
||||
|
||||
_FE_DIR_CACHE = None
|
||||
_INDEX_CACHE = None
|
||||
|
||||
|
||||
def _get_frontend_dir():
|
||||
global _FE_DIR_CACHE
|
||||
if _FE_DIR_CACHE is None:
|
||||
import sys
|
||||
if getattr(sys, 'frozen', False):
|
||||
_FE_DIR_CACHE = os.path.join(sys._MEIPASS, 'backend', 'static', 'frontend')
|
||||
else:
|
||||
env_dir = os.environ.get('FRONTEND_DIR')
|
||||
if env_dir and os.path.isdir(env_dir):
|
||||
_FE_DIR_CACHE = env_dir
|
||||
else:
|
||||
_FE_DIR_CACHE = os.path.join(
|
||||
os.path.dirname(os.path.dirname(os.path.abspath(__file__))),
|
||||
'static', 'frontend',
|
||||
)
|
||||
return _FE_DIR_CACHE
|
||||
|
||||
|
||||
def _get_index_path():
|
||||
global _INDEX_CACHE
|
||||
if _INDEX_CACHE is None:
|
||||
p = os.path.join(_get_frontend_dir(), 'index.html')
|
||||
_INDEX_CACHE = p if os.path.isfile(p) else ''
|
||||
return _INDEX_CACHE
|
||||
|
||||
|
||||
def _serve_file(filepath):
|
||||
ct, _ = mimetypes.guess_type(filepath)
|
||||
return FileResponse(open(filepath, 'rb'), content_type=ct or 'application/octet-stream')
|
||||
|
||||
|
||||
@ensure_csrf_cookie
|
||||
def spa_serve(request, path=None):
|
||||
"""Serve built React assets or fall back to index.html."""
|
||||
fdir = _get_frontend_dir()
|
||||
req_path = (path or '').lstrip('/')
|
||||
|
||||
if req_path:
|
||||
target = os.path.normpath(os.path.join(fdir, req_path))
|
||||
if target.startswith(os.path.normpath(fdir)) and os.path.isfile(target):
|
||||
return _serve_file(target)
|
||||
|
||||
index = _get_index_path()
|
||||
if index:
|
||||
return _serve_file(index)
|
||||
return HttpResponseNotFound('Frontend not built. Run build.py first.')
|
||||
Reference in New Issue
Block a user