diff --git a/app.py b/app.py index c0242f2..fe93ced 100644 --- a/app.py +++ b/app.py @@ -1,109 +1,117 @@ -from fastapi import FastAPI, Request, HTTPException -from fastapi.responses import HTMLResponse -import markdown -from fastapi.staticfiles import StaticFiles -from fastapi.templating import Jinja2Templates -import json, yaml -import os -import uvicorn - -app = FastAPI() -templates = Jinja2Templates(directory="templates") -app.mount("/static", StaticFiles(directory="static"), name="static") - -# 加载所有问卷数据 -def load_all_scales(): - scales = {} - tags = [] - for root, dirs, files in os.walk(os.path.realpath('scales')): - for filename in files: - if filename.endswith(('.yaml', '.yml')): - try: - with open(os.path.join(root, filename), 'r', encoding='utf-8') as f: - scale = yaml.safe_load(f) - scale['instructions']=markdown.markdown(scale['instructions'], extensions=['fenced_code','tables','mdx_math']) - scale['descriptions']=markdown.markdown(scale['descriptions'], extensions=['fenced_code','tables','mdx_math']) - scale['abstract']=markdown.markdown(scale['abstract'], extensions=['fenced_code','tables','mdx_math']) - if 'tag' not in scale: - scale['tag']='其他' - if scale['tag'] not in tags: - tags.append(scale['tag']) - scale_id = os.path.splitext(filename)[0] # 使用文件名作为标识 - scales[scale_id] = scale - except Exception as e: - print(f"Error loading scale {filename}: {e}") - return tags, scales - -@app.get("/", response_class=HTMLResponse) -async def index(request: Request): - tags, _ = load_all_scales() - # 新增读取README.md的逻辑 - readme_content = "" - try: - with open("README.md", "r", encoding="utf-8") as f: - readme_content = markdown.markdown(f.read()) - except FileNotFoundError: - pass # 如果README不存在则静默失败 - return templates.TemplateResponse("index.html", { - "request": request, - "tags": tags, - "readme_content": readme_content # 新增模板变量 - }) - -@app.get("/tag/{tag}", response_class=HTMLResponse) -async def list(request: Request, tag: str): - tags, scales = load_all_scales() - return templates.TemplateResponse("list.html", { - "request": request, - "tags": tags, - "scales": scales, - "tag": tag - }) - -@app.get("/scales/{scale_id}", response_class=HTMLResponse) -async def scale(request: Request, scale_id: str): - tags, scales = load_all_scales() - scale = scales.get(scale_id) - if scale: - return templates.TemplateResponse("scale.html", { - "request": request, - "scale_id": scale_id, - "scale": scale, - "tags":tags - }) - raise HTTPException(status_code=404, detail="问卷未找到") - -@app.post("/scales/{scale_id}", response_class=HTMLResponse) -async def result(request: Request, scale_id: str): - form_data = await request.form() - tags, scales = load_all_scales() - scale = scales.get(scale_id) - if scale: - # 这里可以添加保存数据到数据库等逻辑 - responses = {} - average = {} - options = {} - for subscale, qids in scale['subscales'].items(): - responses[subscale] = 0 - min_val = min(scale['options'].keys()) - max_val = max(scale['options'].keys()) - options[subscale] = [min_val*len(qids),max_val*len(qids)] - for qid in qids: - if qid<0: - responses[subscale] += min_val + max_val - int(form_data[str(-qid)]) - else: - responses[subscale] += int(form_data[str(qid)]) - average[subscale] = round(responses[subscale]/len(qids),2) - return templates.TemplateResponse("result.html", { - "request": request, - "responses": responses, - "average": average, - "options": options, - "scale": scale, - "tags":tags - }) - raise HTTPException(status_code=404, detail="问卷未找到") - - -if __name__ == '__main__': +from fastapi import FastAPI, Request, HTTPException +from fastapi.responses import HTMLResponse, FileResponse +import markdown +from fastapi.staticfiles import StaticFiles +from fastapi.templating import Jinja2Templates +import json, yaml +import os +import uvicorn + +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 = {} + tags = [] + for root, dirs, files in os.walk(os.path.realpath('scales')): + for filename in files: + if filename.endswith(('.yaml', '.yml')): + try: + with open(os.path.join(root, filename), 'r', encoding='utf-8') as f: + scale = yaml.safe_load(f) + scale['instructions']=markdown.markdown(scale['instructions'], extensions=['fenced_code','tables','mdx_math']) + scale['descriptions']=markdown.markdown(scale['descriptions'], extensions=['fenced_code','tables','mdx_math']) + scale['abstract']=markdown.markdown(scale['abstract'], extensions=['fenced_code','tables','mdx_math']) + if 'tag' not in scale: + scale['tag']='其他' + if scale['tag'] not in tags: + tags.append(scale['tag']) + scale_id = os.path.splitext(filename)[0] # 使用文件名作为标识 + scales[scale_id] = scale + except Exception as e: + print(f"Error loading scale {filename}: {e}") + return tags, scales + +@app.get("/", response_class=HTMLResponse) +async def index(request: Request): + tags, _ = load_all_scales() + # 新增读取README.md的逻辑 + readme_content = "" + try: + with open("README.md", "r", encoding="utf-8") as f: + readme_content = markdown.markdown(f.read()) + except FileNotFoundError: + pass # 如果README不存在则静默失败 + return templates.TemplateResponse("index.html", { + "request": request, + "tags": tags, + "readme_content": readme_content # 新增模板变量 + }) + +@app.get("/tag/{tag}", response_class=HTMLResponse) +async def list(request: Request, tag: str): + tags, scales = load_all_scales() + return templates.TemplateResponse("list.html", { + "request": request, + "tags": tags, + "scales": scales, + "tag": tag + }) + +@app.get("/scales/{scale_id}", response_class=HTMLResponse) +async def scale(request: Request, scale_id: str): + tags, scales = load_all_scales() + scale = scales.get(scale_id) + if scale: + return templates.TemplateResponse("scale.html", { + "request": request, + "scale_id": scale_id, + "scale": scale, + "tags":tags + }) + raise HTTPException(status_code=404, detail="问卷未找到") + +@app.post("/scales/{scale_id}", response_class=HTMLResponse) +async def result(request: Request, scale_id: str): + form_data = await request.form() + tags, scales = load_all_scales() + scale = scales.get(scale_id) + if scale: + # 这里可以添加保存数据到数据库等逻辑 + responses = {} + average = {} + options = {} + for subscale, qids in scale['subscales'].items(): + responses[subscale] = 0 + min_val = min(scale['options'].keys()) + max_val = max(scale['options'].keys()) + options[subscale] = [min_val*len(qids),max_val*len(qids)] + for qid in qids: + if qid<0: + responses[subscale] += min_val + max_val - int(form_data[str(-qid)]) + else: + responses[subscale] += int(form_data[str(qid)]) + average[subscale] = round(responses[subscale]/len(qids),2) + return templates.TemplateResponse("result.html", { + "request": request, + "responses": responses, + "average": average, + "options": options, + "scale": scale, + "tags":tags + }) + raise HTTPException(status_code=404, detail="问卷未找到") + + +if __name__ == '__main__': uvicorn.run(app,host='0.0.0.0',port=8000) \ No newline at end of file diff --git a/public/robots.txt b/public/robots.txt new file mode 100644 index 0000000..9d3dce5 --- /dev/null +++ b/public/robots.txt @@ -0,0 +1,4 @@ +User-agent: * +Allow: / + +# Sitemap: /sitemap.xml diff --git a/static/favicon.ico b/static/favicon.ico new file mode 100644 index 0000000..32b2216 Binary files /dev/null and b/static/favicon.ico differ diff --git a/templates/base.html b/templates/base.html index 8f607f4..6e416af 100644 --- a/templates/base.html +++ b/templates/base.html @@ -8,6 +8,7 @@ + {% block head_extra %}{% endblock %}