ZHZ.YHY/streamlit_app.py
2026-01-08 21:48:24 +08:00

310 lines
9.8 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import streamlit as st
import time
from config import config
from agents import code_explainer, bug_fixer
from utils import detect_language
# 设置页面配置
st.set_page_config(
page_title="代码解释与修复助手",
page_icon="🤖",
layout="wide",
initial_sidebar_state="expanded"
)
# 自定义CSS样式
st.markdown("""
<style>
/* 全局样式 */
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background-color: #f5f7fa;
}
/* 标题样式 */
.stApp h1 {
color: #2c3e50;
font-size: 2.5rem;
margin-bottom: 1rem;
text-align: center;
}
.stApp h2 {
color: #34495e;
font-size: 1.5rem;
margin-top: 1.5rem;
margin-bottom: 1rem;
}
/* 容器样式 */
.container {
max-width: 1200px;
margin: 0 auto;
padding: 2rem;
}
/* 卡片样式 */
.card {
background-color: white;
border-radius: 12px;
padding: 1.5rem;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
margin-bottom: 1.5rem;
}
/* 按钮样式 */
.stButton > button {
background-color: #3498db;
color: white;
border: none;
border-radius: 8px;
padding: 0.75rem 1.5rem;
font-size: 1rem;
font-weight: 600;
transition: all 0.3s ease;
}
.stButton > button:hover {
background-color: #2980b9;
transform: translateY(-2px);
box-shadow: 0 6px 12px rgba(52, 152, 219, 0.3);
}
/* 输入区域样式 */
.stTextArea > div > div {
border-radius: 8px;
border: 2px solid #e0e0e0;
}
.stTextArea > div > div:focus-within {
border-color: #3498db;
}
/* 选择框样式 */
.stSelectbox > div > div {
border-radius: 8px;
border: 2px solid #e0e0e0;
}
/* 结果区域样式 */
.result-container {
background-color: #f8f9fa;
border-radius: 8px;
padding: 1.5rem;
margin-top: 1rem;
border-left: 4px solid #3498db;
}
/* 错误提示样式 */
.error-container {
background-color: #fff5f5;
border-radius: 8px;
padding: 1.5rem;
margin-top: 1rem;
border-left: 4px solid #e74c3c;
color: #c0392b;
}
/* 加载动画样式 */
.loading-container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 2rem;
}
/* 响应式布局 */
@media (max-width: 768px) {
.container {
padding: 1rem;
}
.stApp h1 {
font-size: 2rem;
}
}
</style>
""", unsafe_allow_html=True)
# 页面标题和描述
st.title("🤖 代码解释与修复助手")
st.markdown("""
<div style='text-align: center; color: #6c757d; font-size: 1.1rem; margin-bottom: 2rem;'>
输入您的代码选择功能AI将为您提供专业的代码解释或修复建议
</div>
""", unsafe_allow_html=True)
# 创建两列布局
col1, col2 = st.columns([1, 1], gap="large")
# 左侧:输入区域
with col1:
with st.container():
st.subheader("📝 代码输入")
# 代码输入框
code_input = st.text_area(
"请输入您需要分析的代码:",
height=300,
placeholder="在此输入您的代码...\n例如:\ndef hello():\n print('Hello World')",
label_visibility="collapsed"
)
# 语言选择
language = st.selectbox(
"编程语言:",
options=[(lang.capitalize(), lang) for lang in config.SUPPORTED_LANGUAGES],
format_func=lambda x: x[0],
key="language"
)
# 任务类型选择
task_type = st.selectbox(
"任务类型:",
options=[("代码解释", "explain"), ("代码修复", "fix")],
format_func=lambda x: x[0],
key="task_type"
)
# 解释详细程度(仅在代码解释时显示)
depth = None
if task_type[1] == "explain":
# 使用简单的字符串选项,完全避免元组带来的状态管理问题
depth_options = ["基础", "详细", "全面"]
depth_values = {"基础": "basic", "详细": "detailed", "全面": "comprehensive"}
# 设置默认值为"详细"
depth_str = st.select_slider(
"解释详细程度:",
options=depth_options,
value="详细",
key="depth_str"
)
# 构建需要的返回值格式
depth = (depth_str, depth_values[depth_str])
# 开始分析按钮
start_button = st.button(
"🚀 开始分析",
type="primary",
use_container_width=True
)
# 右侧:结果区域
with col2:
with st.container():
st.subheader("📊 分析结果")
# 结果显示区域
result_placeholder = st.empty()
# 初始状态
with result_placeholder.container():
st.markdown("""
<div style='text-align: center; color: #95a5a6; padding: 3rem 0;'>
<div style='font-size: 3rem; margin-bottom: 1rem;'>💡</div>
<p style='font-size: 1.1rem;'>输入代码并点击"开始分析"按钮获取AI分析结果</p>
</div>
""", unsafe_allow_html=True)
# 处理分析请求
if start_button:
# 验证输入
if not code_input.strip():
with result_placeholder.container():
st.error("请输入代码后再进行分析!")
else:
# 显示加载状态
with result_placeholder.container():
with st.spinner("🤖 AI正在分析代码...请稍候"):
# 添加视觉反馈
loading_bar = st.progress(0)
for i in range(100):
time.sleep(0.01) # 模拟进度
loading_bar.progress(i + 1)
try:
# 调用相应的处理函数
if task_type[1] == "explain":
# 代码解释
result = code_explainer.explain(
code=code_input,
language=language[1],
depth=depth[1]
)
# 显示解释结果
with result_placeholder.container():
st.success("✅ 代码解释完成!")
st.markdown("""
<div class='result-container'>
<h3 style='color: #27ae60; margin-bottom: 1rem;'>📚 代码解释</h3>
<div style='white-space: pre-wrap; line-height: 1.6;'>{}</div>
</div>
""".format(result), unsafe_allow_html=True)
else:
# 代码修复
result = bug_fixer.fix(
code=code_input,
language=language[1]
)
# 显示修复结果
with result_placeholder.container():
st.success("✅ 代码修复完成!")
# 显示问题分析
st.markdown("""
<div class='result-container'>
<h3 style='color: #e67e22; margin-bottom: 1rem;'>🔍 问题分析</h3>
<ul style='line-height: 1.8;'>
""", unsafe_allow_html=True)
# 解析并显示问题
if hasattr(result, 'problems_found'):
for problem in result.problems_found:
st.markdown(f"- {problem}")
st.markdown("""
</ul>
</div>
""", unsafe_allow_html=True)
# 显示修复方案
st.markdown("""
<div class='result-container'>
<h3 style='color: #27ae60; margin-bottom: 1rem;'>🔧 修复方案</h3>
""", unsafe_allow_html=True)
if hasattr(result, 'fixed_code'):
st.code(result.fixed_code, language=language[1])
# 显示修复说明
if hasattr(result, 'explanation'):
st.markdown("""
<h4 style='color: #3498db; margin-top: 1rem; margin-bottom: 0.5rem;'>📝 修复说明</h4>
<div style='line-height: 1.6;'>{}</div>
</div>
""".format(result.explanation), unsafe_allow_html=True)
except Exception as e:
# 显示错误信息
with result_placeholder.container():
st.error("❌ 分析失败!")
st.markdown("""
<div class='error-container'>
<h4>错误信息:</h4>
<p>{}</p>
</div>
""".format(str(e)), unsafe_allow_html=True)
# 页脚信息
st.markdown("""
<div style='text-align: center; color: #95a5a6; font-size: 0.9rem; margin-top: 3rem; padding-top: 1rem; border-top: 1px solid #ecf0f1;'>
<p>基于硅基流动AI服务 | 支持多种编程语言</p>
</div>
""", unsafe_allow_html=True)