Compare commits

..

No commits in common. "6e49fadbabc1440047c26d6b69c5b2a687b5f550" and "73f419f1aab112a13e44dd04bfa1d3f5b8e42e6e" have entirely different histories.

4 changed files with 108 additions and 170 deletions

273
app.py
View File

@ -1,166 +1,109 @@
from fastapi import FastAPI, Request, HTTPException from fastapi import FastAPI, Request, HTTPException
from fastapi.responses import HTMLResponse, FileResponse, Response from fastapi.responses import HTMLResponse
import markdown import markdown
from fastapi.staticfiles import StaticFiles from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates from fastapi.templating import Jinja2Templates
import json, yaml import json, yaml
import os import os
import uvicorn import uvicorn
from datetime import datetime
from xml.etree import ElementTree as ET app = FastAPI()
templates = Jinja2Templates(directory="templates")
app = FastAPI() app.mount("/static", StaticFiles(directory="static"), name="static")
templates = Jinja2Templates(directory="templates")
app.mount("/static", StaticFiles(directory="static"), name="static") # 加载所有问卷数据
def load_all_scales():
# 加载所有问卷数据 scales = {}
def load_all_scales(): tags = []
scales = {} for root, dirs, files in os.walk(os.path.realpath('scales')):
tags = [] for filename in files:
for root, dirs, files in os.walk(os.path.realpath('scales')): if filename.endswith(('.yaml', '.yml')):
for filename in files: try:
if filename.endswith(('.yaml', '.yml')): with open(os.path.join(root, filename), 'r', encoding='utf-8') as f:
try: scale = yaml.safe_load(f)
with open(os.path.join(root, filename), 'r', encoding='utf-8') as f: scale['instructions']=markdown.markdown(scale['instructions'], extensions=['fenced_code','tables','mdx_math'])
scale = yaml.safe_load(f) scale['descriptions']=markdown.markdown(scale['descriptions'], extensions=['fenced_code','tables','mdx_math'])
scale['instructions']=markdown.markdown(scale['instructions'], extensions=['fenced_code','tables','mdx_math']) scale['abstract']=markdown.markdown(scale['abstract'], extensions=['fenced_code','tables','mdx_math'])
scale['descriptions']=markdown.markdown(scale['descriptions'], extensions=['fenced_code','tables','mdx_math']) if 'tag' not in scale:
scale['abstract']=markdown.markdown(scale['abstract'], extensions=['fenced_code','tables','mdx_math']) scale['tag']='其他'
if 'tag' not in scale: if scale['tag'] not in tags:
scale['tag']='其他' tags.append(scale['tag'])
if scale['tag'] not in tags: scale_id = os.path.splitext(filename)[0] # 使用文件名作为标识
tags.append(scale['tag']) scales[scale_id] = scale
scale_id = os.path.splitext(filename)[0] # 使用文件名作为标识 except Exception as e:
scales[scale_id] = scale print(f"Error loading scale {filename}: {e}")
except Exception as e: return tags, scales
print(f"Error loading scale {filename}: {e}")
return tags, scales @app.get("/", response_class=HTMLResponse)
async def index(request: Request):
@app.get("/", response_class=HTMLResponse) tags, _ = load_all_scales()
async def index(request: Request): # 新增读取README.md的逻辑
tags, _ = load_all_scales() readme_content = ""
# 新增读取README.md的逻辑 try:
readme_content = "" with open("README.md", "r", encoding="utf-8") as f:
try: readme_content = markdown.markdown(f.read())
with open("README.md", "r", encoding="utf-8") as f: except FileNotFoundError:
readme_content = markdown.markdown(f.read()) pass # 如果README不存在则静默失败
except FileNotFoundError: return templates.TemplateResponse("index.html", {
pass # 如果README不存在则静默失败 "request": request,
return templates.TemplateResponse("index.html", { "tags": tags,
"request": request, "readme_content": readme_content # 新增模板变量
"tags": tags, })
"readme_content": readme_content # 新增模板变量
}) @app.get("/tag/{tag}", response_class=HTMLResponse)
async def list(request: Request, tag: str):
@app.get("/tag/{tag}", response_class=HTMLResponse) tags, scales = load_all_scales()
async def list(request: Request, tag: str): return templates.TemplateResponse("list.html", {
tags, scales = load_all_scales() "request": request,
return templates.TemplateResponse("list.html", { "tags": tags,
"request": request, "scales": scales,
"tags": tags, "tag": tag
"scales": scales, })
"tag": tag
}) @app.get("/scales/{scale_id}", response_class=HTMLResponse)
async def scale(request: Request, scale_id: str):
@app.get("/scales/{scale_id}", response_class=HTMLResponse) tags, scales = load_all_scales()
async def scale(request: Request, scale_id: str): scale = scales.get(scale_id)
tags, scales = load_all_scales() if scale:
scale = scales.get(scale_id) return templates.TemplateResponse("scale.html", {
if scale: "request": request,
return templates.TemplateResponse("scale.html", { "scale_id": scale_id,
"request": request, "scale": scale,
"scale_id": scale_id, "tags":tags
"scale": scale, })
"tags":tags raise HTTPException(status_code=404, detail="问卷未找到")
})
raise HTTPException(status_code=404, detail="问卷未找到") @app.post("/scales/{scale_id}", response_class=HTMLResponse)
async def result(request: Request, scale_id: str):
@app.post("/scales/{scale_id}", response_class=HTMLResponse) form_data = await request.form()
async def result(request: Request, scale_id: str): tags, scales = load_all_scales()
form_data = await request.form() scale = scales.get(scale_id)
tags, scales = load_all_scales() if scale:
scale = scales.get(scale_id) # 这里可以添加保存数据到数据库等逻辑
if scale: responses = {}
# 这里可以添加保存数据到数据库等逻辑 average = {}
responses = {} options = {}
average = {} for subscale, qids in scale['subscales'].items():
options = {} responses[subscale] = 0
for subscale, qids in scale['subscales'].items(): min_val = min(scale['options'].keys())
responses[subscale] = 0 max_val = max(scale['options'].keys())
min_val = min(scale['options'].keys()) options[subscale] = [min_val*len(qids),max_val*len(qids)]
max_val = max(scale['options'].keys()) for qid in qids:
options[subscale] = [min_val*len(qids),max_val*len(qids)] if qid<0:
for qid in qids: responses[subscale] += min_val + max_val - int(form_data[str(-qid)])
if qid<0: else:
responses[subscale] += min_val + max_val - int(form_data[str(-qid)]) responses[subscale] += int(form_data[str(qid)])
else: average[subscale] = round(responses[subscale]/len(qids),2)
responses[subscale] += int(form_data[str(qid)]) return templates.TemplateResponse("result.html", {
average[subscale] = round(responses[subscale]/len(qids),2) "request": request,
return templates.TemplateResponse("result.html", { "responses": responses,
"request": request, "average": average,
"responses": responses, "options": options,
"average": average, "scale": scale,
"options": options, "tags":tags
"scale": scale, })
"tags":tags raise HTTPException(status_code=404, detail="问卷未找到")
})
raise HTTPException(status_code=404, detail="问卷未找到")
if __name__ == '__main__':
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) uvicorn.run(app,host='0.0.0.0',port=8000)

View File

@ -1,4 +0,0 @@
User-agent: *
Allow: /
# Sitemap: /sitemap.xml

Binary file not shown.

Before

Width:  |  Height:  |  Size: 200 KiB

View File

@ -8,7 +8,6 @@
<meta name="keywords" content="心尺, PsychoScales, 心理学量表,专业心理测评,抑郁症测试,焦虑症自评,在线心理测评系统,心理咨询师工具, 心理测验, 报告解读, 测试题"> <meta name="keywords" content="心尺, PsychoScales, 心理学量表,专业心理测评,抑郁症测试,焦虑症自评,在线心理测评系统,心理咨询师工具, 心理测验, 报告解读, 测试题">
<meta name="baidu-site-verification" content="codeva-mPOBUr0rLS" /> <meta name="baidu-site-verification" content="codeva-mPOBUr0rLS" />
<link rel="stylesheet" href="/static/styles.css"> <link rel="stylesheet" href="/static/styles.css">
<link rel="icon" type="image/x-icon" href="/static/favicon.ico">
{% block head_extra %}{% endblock %} {% block head_extra %}{% endblock %}
</head> </head>