更新项目格式及部分ui细节

This commit is contained in:
2025-10-20 00:23:45 +08:00
parent 071e4da378
commit a22bb42bd4
9 changed files with 1654 additions and 2309 deletions
+231
View File
@@ -0,0 +1,231 @@
import gradio as gr
from assets.knowledge_cards_html import (
TIME_DOMAIN_KNOWLEDGE,
FREQUENCY_DOMAIN_KNOWLEDGE,
ROOT_LOCUS_KNOWLEDGE
)
def create_header():
"""创建页面顶部的标题、横幅和在线计数器"""
gr.HTML("<h1 class='main-title'> 自动控制理论AI+数智平台</h1>")
gr.HTML("<p class='subtitle'>✨ 交互式控制系统分析与设计工具 | 时域·频域·根轨迹·AI问答 ✨</p>")
online_counter = gr.HTML(elem_id="online-counter")
gr.HTML("""
<div class='project-info-banner'>
<div style='display: flex; flex-wrap: wrap; justify-content: center; align-items: center; gap: 25px;'>
<div style='display: flex; align-items: center; gap: 10px; background: rgba(255,255,255,0.1); padding: 12px 18px; border-radius: 12px; backdrop-filter: blur(10px);'>
<span style='font-size: 1.8em; filter: drop-shadow(0 2px 4px rgba(0,0,0,0.2));'>📚</span>
<div>
<div style='font-size: 0.8em; color: rgba(255,255,255,0.85); font-weight: 500; letter-spacing: 0.5px;'>课程 Course</div>
<div style='font-weight: 700; font-size: 1.15em; color: white; margin-top: 2px;'>自动控制理论</div>
</div>
</div>
<div style='display: flex; align-items: center; gap: 10px; background: rgba(255,255,255,0.1); padding: 12px 18px; border-radius: 12px; backdrop-filter: blur(10px);'>
<span style='font-size: 1.8em; filter: drop-shadow(0 2px 4px rgba(0,0,0,0.2));'>👨‍🏫</span>
<div>
<div style='font-size: 0.8em; color: rgba(255,255,255,0.85); font-weight: 500; letter-spacing: 0.5px;'>负责人 Supervisor</div>
<div style='font-weight: 700; font-size: 1.15em; color: white; margin-top: 2px;'>魏鹏飞</div>
</div>
</div>
<div style='display: flex; align-items: center; gap: 10px; background: rgba(255,255,255,0.1); padding: 12px 18px; border-radius: 12px; backdrop-filter: blur(10px);'>
<span style='font-size: 1.8em; filter: drop-shadow(0 2px 4px rgba(0,0,0,0.2));'>📧</span>
<div>
<div style='font-size: 0.8em; color: rgba(255,255,255,0.85); font-weight: 500; letter-spacing: 0.5px;'>联系方式 Contact</div>
<a href='mailto:pengfeiwei@nwpu.edu.cn'
style='font-weight: 700; font-size: 1.15em; color: white; text-decoration: none;
border-bottom: 2px solid rgba(255,255,255,0.5); padding-bottom: 2px; margin-top: 2px; display: inline-block;
transition: all 0.3s ease;'
onmouseover='this.style.borderColor="white"; this.style.transform="translateY(-1px)";'
onmouseout='this.style.borderColor="rgba(255,255,255,0.5)"; this.style.transform="translateY(0)";'>
pengfeiwei@nwpu.edu.cn
</a>
</div>
</div>
</div>
<div style='text-align: center; margin-top: 20px; padding-top: 18px; border-top: 2px solid rgba(255,255,255,0.2);'>
<div style='display: inline-flex; align-items: center; gap: 8px; background: rgba(255,255,255,0.08); padding: 10px 20px; border-radius: 25px; backdrop-filter: blur(5px);'>
<span style='font-size: 1.3em; filter: drop-shadow(0 2px 4px rgba(0,0,0,0.2));'>🎓</span>
<span style='font-weight: 600; font-size: 1.05em; color: white;'>西北工业大学</span>
<span style='color: white; opacity: 0.9; font-size: 1.05em;'>Northwestern Polytechnical University</span>
</div>
<div style='margin-top: 10px;'>
<span style='color: white; opacity: 0.9; font-size: 0.95em; font-weight: 500;'>2025年校级本科生建设项目资助</span>
</div>
</div>
</div>
""")
return online_counter
def create_time_domain_tab():
"""创建时域分析选项卡的UI组件"""
ui_dict = {}
with gr.Row():
with gr.Column(scale=1):
with gr.Group():
gr.HTML("<div class='card-title'>🔧 系统模型</div>")
ui_dict["tf_display"] = gr.Markdown(label="当前传递函数", elem_classes="output-display")
with gr.Row():
ui_dict["confirm_button"] = gr.Button("✓ 显示传递函数", variant="secondary", scale=1)
ui_dict["analyze_button"] = gr.Button("🚀 开始分析", variant="primary", scale=1, elem_classes="primary-btn")
with gr.Group():
gr.HTML("<div class='card-title'>📈 动态性能指标</div>")
ui_dict["output_metrics"] = gr.Textbox(
label="Performance Metrics", lines=8, interactive=False, elem_classes="output-metrics"
)
with gr.Column(scale=2):
ui_dict["output_plot"] = gr.Plot(label="时域响应曲线", elem_classes="plot-container")
# 知识卡片
gr.HTML(f"""
<div id="time-domain-knowledge" style="max-height: 600px; overflow-y: auto; padding-right: 8px;">
{TIME_DOMAIN_KNOWLEDGE}
</div>
<script>
(function() {{
// 等待DOM加载完成
if (document.readyState === 'loading') {{
document.addEventListener('DOMContentLoaded', renderMath);
}} else {{
renderMath();
}}
function renderMath() {{
// 延迟执行以确保MathJax已加载
setTimeout(function() {{
if (typeof MathJax !== 'undefined' && MathJax.typesetPromise) {{
MathJax.typesetPromise([document.getElementById('time-domain-knowledge')])
.catch((err) => console.log('MathJax渲染错误:', err));
}} else {{
console.log('MathJax未加载,将在500ms后重试');
setTimeout(renderMath, 500);
}}
}}, 300);
}}
}})();
</script>
""")
return ui_dict
def create_frequency_domain_tab():
"""创建频域分析选项卡的UI组件"""
ui_dict = {}
with gr.Row():
with gr.Column(scale=1):
with gr.Group():
gr.HTML("<div class='card-title'>🎚️ 调整系统增益</div>")
ui_dict["log_k_slider"] = gr.Slider(minimum=-4, maximum=4, value=1, step=0.01, label="对数增益 log₁₀(K)", info="💡 拖动滑块查看实时变化")
ui_dict["k_number_display"] = gr.Number(value=10.0, label="当前增益 K", interactive=False, elem_classes="gain-display")
with gr.Group():
gr.HTML("<div class='card-title'>🔧 当前系统模型</div>")
ui_dict["tf_display"] = gr.Markdown(label="含增益K的开环传递函数", elem_classes="output-display")
with gr.Group():
gr.HTML("<div class='card-title'>📊 稳定裕度分析</div>")
ui_dict["metrics_display"] = gr.Textbox(label="Stability Margins", lines=4, interactive=False, elem_classes="output-metrics")
ui_dict["stability_display"] = gr.Markdown(elem_classes="stability-result")
with gr.Column(scale=2):
ui_dict["plot_output"] = gr.Plot(label="频域响应图", elem_classes="plot-container")
# 知识卡片
gr.HTML(f"""
<div id="freq-domain-knowledge" style="max-height: 600px; overflow-y: auto; padding-right: 8px;">
{FREQUENCY_DOMAIN_KNOWLEDGE}
</div>
<script>
(function() {{
if (document.readyState === 'loading') {{
document.addEventListener('DOMContentLoaded', renderMath);
}} else {{
renderMath();
}}
function renderMath() {{
setTimeout(function() {{
if (typeof MathJax !== 'undefined' && MathJax.typesetPromise) {{
MathJax.typesetPromise([document.getElementById('freq-domain-knowledge')])
.catch((err) => console.log('MathJax渲染错误:', err));
}} else {{
console.log('MathJax未加载,将在500ms后重试');
setTimeout(renderMath, 500);
}}
}}, 300);
}}
}})();
</script>
""")
return ui_dict
def create_root_locus_tab():
"""创建根轨迹分析选项卡的UI组件"""
ui_dict = {}
with gr.Row():
with gr.Column(scale=1):
with gr.Group():
gr.HTML("<div class='card-title'>🎚️ 调整系统增益</div>")
ui_dict["log_k_slider"] = gr.Slider(minimum=-4, maximum=4, value=1, step=0.01, label="对数增益 log₁₀(K)", info="💡 拖动滑块观察极点移动")
ui_dict["k_number_display"] = gr.Number(value=10.0, label="当前增益 K", interactive=False, elem_classes="gain-display")
with gr.Group():
gr.HTML("<div class='card-title'>📍 闭环极点位置</div>")
ui_dict["poles_display"] = gr.Textbox(label="Closed-Loop Pole Locations", lines=6, interactive=False, elem_classes="output-metrics")
with gr.Column(scale=2):
ui_dict["plot_output"] = gr.Plot(label="根轨迹图")
gr.HTML(f"""
<div id="root-locus-knowledge" style="max-height: 600px; overflow-y: auto; padding-right: 8px;">
{ROOT_LOCUS_KNOWLEDGE}
</div>
<script>
(function() {{
if (document.readyState === 'loading') {{
document.addEventListener('DOMContentLoaded', renderMath);
}} else {{
renderMath();
}}
function renderMath() {{
setTimeout(function() {{
if (typeof MathJax !== 'undefined' && MathJax.typesetPromise) {{
MathJax.typesetPromise([document.getElementById('root-locus-knowledge')])
.catch((err) => console.log('MathJax渲染错误:', err));
}} else {{
console.log('MathJax未加载,将在500ms后重试');
setTimeout(renderMath, 500);
}}
}}, 300);
}}
}})();
</script>
""")
return ui_dict
def create_chatbot_tab():
"""创建AI问答选项卡的UI组件"""
ui_dict = {}
ui_dict["chatbot"] = gr.Chatbot(
label="🎓 自控原理AI助教",
type="messages",
avatar_images=("https://img.icons8.com/fluency/96/user-male-circle.png", "https://img.icons8.com/fluency/96/chatbot.png"),
height=650,
latex_delimiters=[
{"left": "$$", "right": "$$", "display": True},
{"left": "$", "right": "$", "display": False},
{"left": "\\[", "right": "\\]", "display": True},
{"left": "\\(", "right": "\\)", "display": False}
],
elem_classes="modern-chatbot",
show_copy_button=True
)
with gr.Row():
ui_dict["chat_input"] = gr.Textbox(label="", placeholder="💬 输入您的问题...", scale=4, lines=2, max_lines=4)
with gr.Column(scale=1, min_width=120):
ui_dict["send_button"] = gr.Button("📤 发送", variant="primary", size="lg")
ui_dict["clear_button"] = gr.Button("🗑️ 清空", variant="secondary", size="lg")
gr.Examples(
examples=["什么是传递函数?", "如何判断系统稳定性?", "解释Bode图的物理意义", "PID控制器各参数的作用"],
inputs=ui_dict["chat_input"],
label="💡 试试这些问题:"
)
return ui_dict