使用了html模板;增加了导航栏;将lang改为看起来更加通用的tag
This commit is contained in:
parent
4954abfca4
commit
441768dab0
37
app.py
37
app.py
@ -15,10 +15,10 @@ app.mount("/static", StaticFiles(directory="static"), name="static")
|
|||||||
def load_all_scales():
|
def load_all_scales():
|
||||||
scale_folder = 'scales'
|
scale_folder = 'scales'
|
||||||
scales = {}
|
scales = {}
|
||||||
lang = {}
|
tags = {}
|
||||||
try:
|
try:
|
||||||
with open(os.path.join('langmap.yml'), 'r', encoding='utf-8') as f:
|
with open(os.path.join('tagmap.yml'), 'r', encoding='utf-8') as f:
|
||||||
langmap = yaml.safe_load(f)
|
tagmap = yaml.safe_load(f)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Error loading scale langmap: {e}")
|
print(f"Error loading scale langmap: {e}")
|
||||||
for filename in os.listdir(scale_folder):
|
for filename in os.listdir(scale_folder):
|
||||||
@ -28,18 +28,18 @@ def load_all_scales():
|
|||||||
scale = yaml.safe_load(f)
|
scale = yaml.safe_load(f)
|
||||||
scale['instructions']=markdown.markdown(scale['instructions'], extensions=['fenced_code','tables','mdx_math'])
|
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['descriptions']=markdown.markdown(scale['descriptions'], extensions=['fenced_code','tables','mdx_math'])
|
||||||
if 'lang' not in scale or scale['lang'] not in langmap:
|
if 'tag' not in scale or scale['tag'] not in tagmap:
|
||||||
scale['lang']='other'
|
scale['tag']='other'
|
||||||
lang[scale['lang']]=langmap[scale['lang']]
|
tags[scale['tag']]=tagmap[scale['tag']]
|
||||||
scale_id = os.path.splitext(filename)[0] # 使用文件名作为标识
|
scale_id = os.path.splitext(filename)[0] # 使用文件名作为标识
|
||||||
scales[scale_id] = scale
|
scales[scale_id] = scale
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Error loading scale {filename}: {e}")
|
print(f"Error loading scale {filename}: {e}")
|
||||||
return lang, scales
|
return tags, scales
|
||||||
|
|
||||||
@app.get("/", response_class=HTMLResponse)
|
@app.get("/", response_class=HTMLResponse)
|
||||||
async def index(request: Request):
|
async def index(request: Request):
|
||||||
lang, _ = load_all_scales()
|
tags, _ = load_all_scales()
|
||||||
# 新增读取README.md的逻辑
|
# 新增读取README.md的逻辑
|
||||||
readme_content = ""
|
readme_content = ""
|
||||||
try:
|
try:
|
||||||
@ -49,35 +49,37 @@ async def index(request: Request):
|
|||||||
pass # 如果README不存在则静默失败
|
pass # 如果README不存在则静默失败
|
||||||
return templates.TemplateResponse("index.html", {
|
return templates.TemplateResponse("index.html", {
|
||||||
"request": request,
|
"request": request,
|
||||||
"lang": lang,
|
"tags": tags,
|
||||||
"readme_content": readme_content # 新增模板变量
|
"readme_content": readme_content # 新增模板变量
|
||||||
})
|
})
|
||||||
|
|
||||||
@app.get("/{lang}", response_class=HTMLResponse)
|
@app.get("/{tag}", response_class=HTMLResponse)
|
||||||
async def scale(request: Request, lang: str):
|
async def list(request: Request, tag: str):
|
||||||
_, scales = load_all_scales()
|
tags, scales = load_all_scales()
|
||||||
return templates.TemplateResponse("list.html", {
|
return templates.TemplateResponse("list.html", {
|
||||||
"request": request,
|
"request": request,
|
||||||
|
"tags": tags,
|
||||||
"scales": scales,
|
"scales": scales,
|
||||||
"lang": lang
|
"tag": tag
|
||||||
})
|
})
|
||||||
|
|
||||||
@app.get("/scales/{scale_id}", response_class=HTMLResponse)
|
@app.get("/scales/{scale_id}", response_class=HTMLResponse)
|
||||||
async def scale(request: Request, scale_id: str):
|
async def scale(request: Request, scale_id: str):
|
||||||
_, scales = load_all_scales()
|
tags, scales = load_all_scales()
|
||||||
scale = scales.get(scale_id)
|
scale = scales.get(scale_id)
|
||||||
if scale:
|
if scale:
|
||||||
return templates.TemplateResponse("scale.html", {
|
return templates.TemplateResponse("scale.html", {
|
||||||
"request": request,
|
"request": request,
|
||||||
"scale_id": scale_id,
|
"scale_id": scale_id,
|
||||||
"scale": scale
|
"scale": scale,
|
||||||
|
"tags":tags
|
||||||
})
|
})
|
||||||
raise HTTPException(status_code=404, detail="问卷未找到")
|
raise HTTPException(status_code=404, detail="问卷未找到")
|
||||||
|
|
||||||
@app.post("/scales/{scale_id}", response_class=HTMLResponse)
|
@app.post("/scales/{scale_id}", response_class=HTMLResponse)
|
||||||
async def result(request: Request, scale_id: str):
|
async def result(request: Request, scale_id: str):
|
||||||
form_data = await request.form()
|
form_data = await request.form()
|
||||||
lang, scales = load_all_scales()
|
tags, scales = load_all_scales()
|
||||||
scale = scales.get(scale_id)
|
scale = scales.get(scale_id)
|
||||||
if scale:
|
if scale:
|
||||||
# 这里可以添加保存数据到数据库等逻辑
|
# 这里可以添加保存数据到数据库等逻辑
|
||||||
@ -95,7 +97,8 @@ async def result(request: Request, scale_id: str):
|
|||||||
"request": request,
|
"request": request,
|
||||||
"responses": responses,
|
"responses": responses,
|
||||||
"ranges": ranges,
|
"ranges": ranges,
|
||||||
"scale": scale
|
"scale": scale,
|
||||||
|
"tags":tags
|
||||||
})
|
})
|
||||||
raise HTTPException(status_code=404, detail="问卷未找到")
|
raise HTTPException(status_code=404, detail="问卷未找到")
|
||||||
|
|
||||||
|
@ -1,3 +0,0 @@
|
|||||||
other: 未分类 Other
|
|
||||||
zh: 中文
|
|
||||||
en: English
|
|
@ -1,5 +1,5 @@
|
|||||||
title: 中国大五人格问卷(简式版)
|
title: 中国大五人格问卷(简式版)
|
||||||
lang: zh
|
tag: zh
|
||||||
instructions: 下面是一些描述人们性格特点的句子,请根据每个句子与您性格相符程度选择相应的数字。1-6分别代表完全不符合、大部分不符合、有点不符合、有点符合、大部分符合、完全符合。
|
instructions: 下面是一些描述人们性格特点的句子,请根据每个句子与您性格相符程度选择相应的数字。1-6分别代表完全不符合、大部分不符合、有点不符合、有点符合、大部分符合、完全符合。
|
||||||
descriptions: |
|
descriptions: |
|
||||||
中国大五人格问卷(CBF-PI)是由王孟成和戴晓阳等编制的,中国拥有其知识产权的人格问卷(相比NEO-PI)。此处是基于其简化的问卷,与完整版问卷的各项相关系数的$r$神经质最小的$0.886$、宜人性最大的$0.922$。
|
中国大五人格问卷(CBF-PI)是由王孟成和戴晓阳等编制的,中国拥有其知识产权的人格问卷(相比NEO-PI)。此处是基于其简化的问卷,与完整版问卷的各项相关系数的$r$神经质最小的$0.886$、宜人性最大的$0.922$。
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
title: Symptom Checklist-90 (SCL90)
|
title: Symptom Checklist-90 (SCL90)
|
||||||
lang: en
|
tag: en
|
||||||
instructions: |
|
instructions: |
|
||||||
Below is a list of problems and complaints that people sometimes have. Please read each one carefully. After you have done so, select one of the numbered descriptors that best describes HOW
|
Below is a list of problems and complaints that people sometimes have. Please read each one carefully. After you have done so, select one of the numbered descriptors that best describes HOW
|
||||||
MUCH THAT PROBLEM HAS BOTHERED OR DISTRESSED YOU DURING THE
|
MUCH THAT PROBLEM HAS BOTHERED OR DISTRESSED YOU DURING THE
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
title: 中庸实践思维量表
|
title: 中庸实践思维量表
|
||||||
lang: zh
|
tag: zh
|
||||||
instructions: |
|
instructions: |
|
||||||
以下题目是对个人思维方式的描述,不需要过多考虑,请根据你平时的真实想法,或者假设遇到所说的情形时,内心里自动出现的想法进行选择,根据符合度进行打分,答案并无对错之分。
|
以下题目是对个人思维方式的描述,不需要过多考虑,请根据你平时的真实想法,或者假设遇到所说的情形时,内心里自动出现的想法进行选择,根据符合度进行打分,答案并无对错之分。
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ body {
|
|||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
}
|
}
|
||||||
|
|
||||||
.content {
|
main {
|
||||||
/* 可选:添加一些内边距,让内容不紧贴容器边缘 */
|
/* 可选:添加一些内边距,让内容不紧贴容器边缘 */
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
||||||
@ -26,7 +26,7 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 768px) {
|
@media (max-width: 768px) {
|
||||||
.content {
|
main {
|
||||||
width: 95%;
|
width: 95%;
|
||||||
/* 全屏展示 */
|
/* 全屏展示 */
|
||||||
padding-top: 10px;
|
padding-top: 10px;
|
||||||
@ -62,3 +62,51 @@ body {
|
|||||||
background-color: #007BFF;
|
background-color: #007BFF;
|
||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 导航栏样式 */
|
||||||
|
nav {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
background-color: #f8f9fa;
|
||||||
|
padding: 1rem 2rem;
|
||||||
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-left .logo {
|
||||||
|
font-weight: 700;
|
||||||
|
font-size: 1.5rem;
|
||||||
|
color: #2c3e50;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-links {
|
||||||
|
display: flex;
|
||||||
|
gap: 2rem;
|
||||||
|
list-style: none;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-links a {
|
||||||
|
text-decoration: none;
|
||||||
|
color: #34495e;
|
||||||
|
font-weight: 500;
|
||||||
|
transition: color 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-links a:hover {
|
||||||
|
color: #3498db;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
padding-top: 80px;
|
||||||
|
/* 增加顶部内边距避免内容被导航栏遮挡 */
|
||||||
|
min-height: calc(100vh - 80px);
|
||||||
|
/* 补偿导航栏高度 */
|
||||||
|
}
|
3
tagmap.yml
Normal file
3
tagmap.yml
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
other: 未分类 Other
|
||||||
|
zh: 中文量表
|
||||||
|
en: English Scales
|
35
templates/base.html
Normal file
35
templates/base.html
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<!-- <html lang="zh"> -->
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<link rel="stylesheet" href="/static/styles.css">
|
||||||
|
<!-- 添加KaTeX支持 -->
|
||||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.css">
|
||||||
|
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.js"></script>
|
||||||
|
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/contrib/auto-render.min.js" onload="renderMathInElement(document.body, {delimiters: [
|
||||||
|
{left: '$$', right: '$$', display: true},
|
||||||
|
{left: '$', right: '$', display: false}]});">
|
||||||
|
</script>
|
||||||
|
{% block head_extra %}{% endblock %}
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<nav>
|
||||||
|
<div class="nav-left">
|
||||||
|
<a href="/" class="logo">PsychoScales</a>
|
||||||
|
</div>
|
||||||
|
<ul class="nav-links">
|
||||||
|
{% for key,value in tags.items() %}
|
||||||
|
<li><a href="/{{ key }}"">{{ value }}</a></li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
<br>
|
||||||
|
<main>
|
||||||
|
{% block main %}{% endblock %}
|
||||||
|
</main>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
@ -1,31 +1,13 @@
|
|||||||
<!DOCTYPE html>
|
{% extends 'base.html' %}
|
||||||
<html lang="zh">
|
|
||||||
|
|
||||||
<head>
|
{% block head_extra %}
|
||||||
<meta charset="UTF-8">
|
<title>心尺 PsychoScales</title>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
{% endblock %}
|
||||||
<title>心尺 PsychoScales</title>
|
|
||||||
<link rel="stylesheet" href="/static/styles.css">
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
{% block main %}
|
||||||
<div class="header">
|
{% if readme_content %}
|
||||||
|
<div class="readme-section">
|
||||||
</div>
|
|
||||||
<div class="content">
|
|
||||||
{% if readme_content %}
|
|
||||||
<div class="readme-section">
|
|
||||||
{{ readme_content|safe }}
|
{{ readme_content|safe }}
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<ul>
|
{% endblock %}
|
||||||
{% for key,value in lang.items() %}
|
|
||||||
<li><a href="/{{ key }}"">{{ value }}</a></li>
|
|
||||||
{% endfor %}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</html>
|
|
@ -1,27 +1,16 @@
|
|||||||
<!DOCTYPE html>
|
{% extends 'base.html' %}
|
||||||
<html lang="zh">
|
|
||||||
|
|
||||||
<head>
|
{% block head_extra %}
|
||||||
<meta charset="UTF-8">
|
<title>心尺 PsychoScales</title>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
{% endblock %}
|
||||||
<title>心尺 PsychoScales</title>
|
|
||||||
<link rel="stylesheet" href="/static/styles.css">
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
{% block main %}
|
||||||
<div class="header">
|
<ul>
|
||||||
|
|
||||||
</div>
|
|
||||||
<div class="content">
|
|
||||||
<ul>
|
|
||||||
{% for scale_id, scale in scales.items() %}
|
{% for scale_id, scale in scales.items() %}
|
||||||
{% if scale.lang == lang %}
|
{% if scale.tag == tag %}
|
||||||
<li><a href="/scales/{{ scale_id }}" , title=" {{ scale.abstract }}">{{ scale.get('title','未命名问卷') }}</a>
|
<li><a href="/scales/{{ scale_id }}" , title=" {{ scale.abstract }}">{{ scale.get('title','未命名问卷') }}</a>
|
||||||
</li>
|
</li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
{% endblock %}
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
@ -1,32 +1,17 @@
|
|||||||
<!DOCTYPE html>
|
{% extends 'base.html' %}
|
||||||
<html lang="zh">
|
|
||||||
|
|
||||||
<head>
|
{% block head_extra %}
|
||||||
<meta charset="UTF-8">
|
<title>{{scale_title}}</title>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
{% endblock %}
|
||||||
<title>{{scale_title}}</title>
|
|
||||||
<link rel="stylesheet" href="/static/styles.css">
|
|
||||||
<!-- 添加KaTeX支持 -->
|
|
||||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.css">
|
|
||||||
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.js"></script>
|
|
||||||
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/contrib/auto-render.min.js" onload="renderMathInElement(document.body, {delimiters: [
|
|
||||||
{left: '$$', right: '$$', display: true},
|
|
||||||
{left: '$', right: '$', display: false}]});">
|
|
||||||
</script>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
{% block main %}
|
||||||
<div class="content">
|
<h1>{{ scale.title }} </h1>
|
||||||
<h1>{{ scale.title }} </h1>
|
<ul>
|
||||||
<ul>
|
|
||||||
{% for key, value in responses.items() %}
|
{% for key, value in responses.items() %}
|
||||||
<li>{{ key }}: 在 {{ranges[key][0]}} 到 {{ranges[key][1]}} 的量表中得分 {{ value }}</li>
|
<li>{{ key }}: 在 {{ranges[key][0]}} 到 {{ranges[key][1]}} 的量表中得分 {{ value }}</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
<div>
|
<div>
|
||||||
{{scale.descriptions|safe}}
|
{{scale.descriptions|safe}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
{% endblock %}
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
@ -1,40 +1,25 @@
|
|||||||
<!DOCTYPE html>
|
{% extends 'base.html' %}
|
||||||
<html lang="zh">
|
|
||||||
|
|
||||||
<head>
|
{% block head_extra %}
|
||||||
<meta charset="UTF-8">
|
<title>{{ scale.title }}</title>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
{% endblock %}
|
||||||
<title>{{ scale.title }}</title>
|
|
||||||
<link rel="stylesheet" href="/static/styles.css">
|
|
||||||
<!-- 添加KaTeX支持 -->
|
|
||||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.css">
|
|
||||||
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.js"></script>
|
|
||||||
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/contrib/auto-render.min.js" onload="renderMathInElement(document.body, {delimiters: [
|
|
||||||
{left: '$$', right: '$$', display: true},
|
|
||||||
{left: '$', right: '$', display: false}]});">
|
|
||||||
</script>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
{% block main %}
|
||||||
<div class="content">
|
<h1>{{ scale.title }}</h1>
|
||||||
<h1>{{ scale.title }}</h1>
|
<div>
|
||||||
<div>
|
|
||||||
{{ scale.instructions|safe }}
|
{{ scale.instructions|safe }}
|
||||||
</div>
|
</div>
|
||||||
<form action="/scales/{{ scale_id }}" method="post">
|
<form action="/scales/{{ scale_id }}" method="post">
|
||||||
{% for id, question in scale.questions.items() %}
|
{% for id, question in scale.questions.items() %}
|
||||||
<label for="{{ id }}">{{ id }}. {{ question }}</label>
|
<label for="{{ id }}">{{ id }}. {{ question }}</label>
|
||||||
<div class="scale-button">
|
<div class="scale-button">
|
||||||
{% for option in range(scale.range[0], scale.range[1]+1) %}
|
{% for option in range(scale.range[0], scale.range[1]+1) %}
|
||||||
<input type="radio" id="{{ id }}_{{ option }}" name="{{ id }}" value="{{ option }}" {% if not
|
<input type="radio" id="{{ id }}_{{ option }}" name="{{ id }}" value="{{ option }}" {% if not ( 'optional' in
|
||||||
( 'optional' in question and question.optional) %}required{% endif %}>
|
question and question.optional) %}required{% endif %}>
|
||||||
<label for="{{ id }}_{{ option }}">{{ option }}</label>
|
<label for="{{ id }}_{{ option }}">{{ option }}</label>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
<input type="submit" value="提交">
|
<input type="submit" value="提交">
|
||||||
</form>
|
</form>
|
||||||
</div>
|
{% endblock %}
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
Loading…
x
Reference in New Issue
Block a user