From 6e49fadbabc1440047c26d6b69c5b2a687b5f550 Mon Sep 17 00:00:00 2001 From: mxr612 Date: Mon, 16 Jun 2025 04:15:44 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E7=BD=91=E7=AB=99?= =?UTF-8?q?=E5=9C=B0=E5=9B=BE=E7=94=9F=E6=88=90=E5=8A=9F=E8=83=BD=E5=B9=B6?= =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=85=AC=E5=85=B1=E6=96=87=E4=BB=B6=E8=AE=BF?= =?UTF-8?q?=E9=97=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增生成sitemap.xml的功能,包含静态和动态路由 - 优化公共文件访问接口,支持直接返回sitemap.xml --- app.py | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 58 insertions(+), 9 deletions(-) diff --git a/app.py b/app.py index fe93ced..1b67ec2 100644 --- a/app.py +++ b/app.py @@ -1,24 +1,18 @@ from fastapi import FastAPI, Request, HTTPException -from fastapi.responses import HTMLResponse, FileResponse +from fastapi.responses import HTMLResponse, FileResponse, Response import markdown from fastapi.staticfiles import StaticFiles from fastapi.templating import Jinja2Templates import json, yaml import os import uvicorn +from datetime import datetime +from xml.etree import ElementTree as ET app = FastAPI() templates = Jinja2Templates(directory="templates") app.mount("/static", StaticFiles(directory="static"), name="static") -# Mount all files from public directory to root -@app.get("/{filename}") -async def get_public_file(filename: str): - public_path = os.path.join("public", filename) - if os.path.isfile(public_path): - return FileResponse(public_path) - raise HTTPException(status_code=404, detail="File not found") - # 加载所有问卷数据 def load_all_scales(): scales = {} @@ -112,6 +106,61 @@ async def result(request: Request, scale_id: str): }) raise HTTPException(status_code=404, detail="问卷未找到") +def generate_sitemap(): + # Create the root element + urlset = ET.Element("urlset", xmlns="http://www.sitemaps.org/schemas/sitemap/0.9") + + latest_mtime = max( + os.path.getmtime(os.path.join(root, f)) + for root, _, files in os.walk('scales') + for f in files if f.endswith(('.yaml', '.yml')) + ) + + # Add static routes + static_routes = ["/"] # Add your static routes here + for route in static_routes: + url = ET.SubElement(urlset, "url") + ET.SubElement(url, "loc").text = f"https://psychoscales.org{route}" + ET.SubElement(url, "lastmod").text = datetime.fromtimestamp(latest_mtime).strftime("%Y-%m-%d") + ET.SubElement(url, "changefreq").text = "monthly" + ET.SubElement(url, "priority").text = "0.8" + + # Add dynamic tag routes + tags, scales = load_all_scales() + for tag in tags: + url = ET.SubElement(urlset, "url") + ET.SubElement(url, "loc").text = f"https://psychoscales.org/tag/{tag}" + ET.SubElement(url, "lastmod").text = datetime.fromtimestamp(latest_mtime).strftime("%Y-%m-%d") + ET.SubElement(url, "changefreq").text = "weekly" + ET.SubElement(url, "priority").text = "0.6" + + # Add dynamic scale routes + for scale_id in scales.keys(): + url = ET.SubElement(urlset, "url") + ET.SubElement(url, "loc").text = f"https://psychoscales.org/scales/{scale_id}" + # For individual scale pages, use the actual file modification time + scale_file = os.path.join('scales', f"{scale_id}.yaml") + if os.path.exists(scale_file): + mtime = os.path.getmtime(scale_file) + ET.SubElement(url, "lastmod").text = datetime.fromtimestamp(mtime).strftime("%Y-%m-%d") + ET.SubElement(url, "changefreq").text = "monthly" + ET.SubElement(url, "priority").text = "0.6" + + # Convert to string + return ET.tostring(urlset, encoding='unicode', method='xml') + +# Mount all files from public directory to root +@app.get("/{filename}") +async def get_public_file(filename: str): + public_path = os.path.join("public", filename) + if filename == "sitemap.xml": + return Response( + content=generate_sitemap(), + media_type="application/xml" + ) + if os.path.isfile(public_path): + return FileResponse(public_path) + raise HTTPException(status_code=404, detail="File not found") if __name__ == '__main__': uvicorn.run(app,host='0.0.0.0',port=8000) \ No newline at end of file