步骤十三页面修改
This commit is contained in:
@ -99,110 +99,186 @@ class Step13ReportPanel(QWidget):
|
||||
self.init_ui()
|
||||
|
||||
def init_ui(self):
|
||||
# 1. 确保全局主题类被导入
|
||||
from src.gui.styles import ModernStylesheet
|
||||
|
||||
layout = QVBoxLayout()
|
||||
layout.setContentsMargins(10, 10, 10, 10)
|
||||
layout.setSpacing(10)
|
||||
layout.setContentsMargins(24, 24, 24, 24)
|
||||
layout.setSpacing(20)
|
||||
|
||||
# 重新定义全局绝美样式
|
||||
common_lineedit_css = "QLineEdit { padding: 4px 8px; border: 1px solid #C0C0C0; border-radius: 4px; min-height: 24px; background-color: #FFFFFF; }"
|
||||
common_btn_css = """
|
||||
QPushButton { background-color: #F8F9FA; border: 1px solid #D1D5DB; border-radius: 4px; padding: 4px 12px; color: #374151; }
|
||||
QPushButton:hover { background-color: #F3F4F6; border-color: #9CA3AF; }
|
||||
"""
|
||||
|
||||
# 【核心黑科技】:定义标准行闭包,强制统一 120px 标签和 10px 间距
|
||||
def create_standard_row(label_text, widget, btn=None):
|
||||
row = QHBoxLayout()
|
||||
row.setContentsMargins(0, 0, 0, 0)
|
||||
row.setSpacing(10)
|
||||
label = QLabel(label_text)
|
||||
label.setMinimumWidth(120)
|
||||
label.setMaximumWidth(120)
|
||||
row.addWidget(label)
|
||||
row.addWidget(widget, 1)
|
||||
if btn:
|
||||
row.addWidget(btn)
|
||||
return row
|
||||
|
||||
intro = QLabel(
|
||||
"根据工作目录下的可视化结果(14_visualization 等)生成 Word 分析报告。"
|
||||
"💡 提示:根据工作目录下的可视化结果(14_visualization 等)自动生成 Word 分析报告。\n"
|
||||
"需已存在可视化图表;AI 分析通过 Ollama 或 Minimax 调用云端/本地服务。"
|
||||
)
|
||||
intro.setWordWrap(True)
|
||||
intro.setStyleSheet(
|
||||
f"color: {ModernStylesheet.COLORS.get('text_secondary', '#666')};"
|
||||
)
|
||||
intro.setStyleSheet(f"""
|
||||
QLabel {{
|
||||
color: {ModernStylesheet.COLORS.get('primary', '#0078D7')};
|
||||
background-color: {ModernStylesheet.COLORS.get('selected', '#E5F3FF')};
|
||||
border: 1px solid {ModernStylesheet.COLORS.get('border_light', '#D1D5DB')};
|
||||
border-radius: 6px;
|
||||
padding: 10px 14px;
|
||||
margin-bottom: 8px;
|
||||
}}
|
||||
""")
|
||||
layout.addWidget(intro)
|
||||
|
||||
# ── 路径 ──────────────────────────────────────────────────────────────
|
||||
path_group = QGroupBox("路径")
|
||||
path_form = QFormLayout()
|
||||
# ==========================================
|
||||
# 卡片 1:报告路径配置
|
||||
# ==========================================
|
||||
path_group = QGroupBox("📁 报告路径配置")
|
||||
path_layout = QVBoxLayout()
|
||||
path_layout.setSpacing(16)
|
||||
path_layout.setContentsMargins(20, 24, 20, 20)
|
||||
|
||||
wd_row = QHBoxLayout()
|
||||
# 工作目录 (只读)
|
||||
self.work_dir_edit = QLineEdit()
|
||||
self.work_dir_edit.setPlaceholderText("流程工作目录(含 14_visualization)…")
|
||||
self.work_dir_edit.setReadOnly(True)
|
||||
wd_browse = QPushButton("浏览…")
|
||||
wd_browse.clicked.connect(self.browse_work_dir)
|
||||
wd_browse.setVisible(False)
|
||||
sync_btn = QPushButton("同步主窗口工作目录")
|
||||
sync_btn.clicked.connect(self.sync_work_dir_from_main)
|
||||
sync_btn.setVisible(False)
|
||||
wd_row.addWidget(self.work_dir_edit, 1)
|
||||
wd_row.addWidget(wd_browse)
|
||||
wd_row.addWidget(sync_btn)
|
||||
path_form.addRow("工作目录:", wd_row)
|
||||
self.work_dir_edit.setStyleSheet(common_lineedit_css)
|
||||
path_layout.addLayout(create_standard_row("工作目录:", self.work_dir_edit))
|
||||
|
||||
out_row = QHBoxLayout()
|
||||
# 报告输出目录
|
||||
self.output_dir_edit = QLineEdit()
|
||||
self.output_dir_edit.setPlaceholderText("留空则保存到 工作目录/14_visualization")
|
||||
out_browse = QPushButton("浏览…")
|
||||
out_browse.clicked.connect(self.browse_output_dir)
|
||||
out_row.addWidget(self.output_dir_edit, 1)
|
||||
out_row.addWidget(out_browse)
|
||||
path_form.addRow("报告输出目录:", out_row)
|
||||
self.output_dir_edit.setStyleSheet(common_lineedit_css)
|
||||
|
||||
out_browse = QPushButton("浏览...")
|
||||
out_browse.setStyleSheet(common_btn_css)
|
||||
out_browse.setMaximumWidth(80)
|
||||
out_browse.clicked.connect(self.browse_output_dir)
|
||||
|
||||
path_layout.addLayout(create_standard_row("报告输出目录:", self.output_dir_edit, out_browse))
|
||||
|
||||
# 报告标题
|
||||
self.report_title_edit = QLineEdit()
|
||||
self.report_title_edit.setText("水质参数反演分析报告")
|
||||
path_form.addRow("报告标题:", self.report_title_edit)
|
||||
self.report_title_edit.setStyleSheet(common_lineedit_css)
|
||||
path_layout.addLayout(create_standard_row("报告标题:", self.report_title_edit))
|
||||
|
||||
path_group.setLayout(path_form)
|
||||
path_group.setLayout(path_layout)
|
||||
layout.addWidget(path_group)
|
||||
|
||||
# ── AI 分析 ───────────────────────────────────────────────────────────
|
||||
ai_group = QGroupBox("AI 分析")
|
||||
# ==========================================
|
||||
# 卡片 2:AI 分析配置
|
||||
# ==========================================
|
||||
ai_group = QGroupBox("🤖 AI 分析配置")
|
||||
ai_layout = QVBoxLayout()
|
||||
ai_layout.setSpacing(16)
|
||||
ai_layout.setContentsMargins(20, 24, 20, 20)
|
||||
|
||||
# 启用复选框,采用占位符顶齐 120px
|
||||
check_row = QHBoxLayout()
|
||||
check_row.setContentsMargins(0, 0, 0, 0)
|
||||
check_row.setSpacing(10)
|
||||
placeholder = QLabel("")
|
||||
placeholder.setMinimumWidth(120)
|
||||
placeholder.setMaximumWidth(120)
|
||||
check_row.addWidget(placeholder)
|
||||
|
||||
self.enable_ai_cb = QCheckBox("启用 AI 图表解读与综合总结")
|
||||
self.enable_ai_cb.setChecked(
|
||||
os.environ.get("ENABLE_AI_ANALYSIS", "1") not in {"0", "false", "False"}
|
||||
)
|
||||
ai_layout.addWidget(self.enable_ai_cb)
|
||||
self.enable_ai_cb.setChecked(os.environ.get("ENABLE_AI_ANALYSIS", "1") not in {"0", "false", "False"})
|
||||
check_row.addWidget(self.enable_ai_cb)
|
||||
check_row.addStretch()
|
||||
ai_layout.addLayout(check_row)
|
||||
|
||||
# 只读提示行:当前引擎 + 配置按钮
|
||||
# AI 引擎状态行
|
||||
ai_status_row = QHBoxLayout()
|
||||
ai_status_row.addWidget(QLabel("当前 AI 引擎:"))
|
||||
ai_status_row.setContentsMargins(0, 0, 0, 0)
|
||||
ai_status_row.setSpacing(10)
|
||||
engine_label = QLabel("当前 AI 引擎:")
|
||||
engine_label.setMinimumWidth(120)
|
||||
engine_label.setMaximumWidth(120)
|
||||
ai_status_row.addWidget(engine_label)
|
||||
|
||||
self._ai_label = QLabel()
|
||||
self._ai_label.setStyleSheet("color: #0078d4; font-weight: bold;")
|
||||
self._ai_label.setStyleSheet("color: #0078D7; font-weight: bold; font-size: 13px;")
|
||||
ai_status_row.addWidget(self._ai_label)
|
||||
ai_status_row.addStretch(1)
|
||||
|
||||
open_settings_btn = QPushButton("高级配置...")
|
||||
open_settings_btn.setStyleSheet(common_btn_css)
|
||||
open_settings_btn.clicked.connect(self._open_ai_settings)
|
||||
ai_status_row.addWidget(open_settings_btn)
|
||||
|
||||
ai_layout.addLayout(ai_status_row)
|
||||
|
||||
ai_group.setLayout(ai_layout)
|
||||
layout.addWidget(ai_group)
|
||||
|
||||
# ── 按钮 ──────────────────────────────────────────────────────────────
|
||||
btn_row = QHBoxLayout()
|
||||
self.generate_btn = QPushButton("生成 Word 报告")
|
||||
self.generate_btn.setStyleSheet(
|
||||
ModernStylesheet.get_button_stylesheet("success")
|
||||
)
|
||||
self.generate_btn.clicked.connect(self.on_generate_clicked)
|
||||
btn_row.addWidget(self.generate_btn)
|
||||
btn_row.addStretch()
|
||||
layout.addLayout(btn_row)
|
||||
# ==========================================
|
||||
# 卡片 3:输出与执行
|
||||
# ==========================================
|
||||
execute_group = QGroupBox("🚀 输出与执行")
|
||||
execute_layout = QVBoxLayout()
|
||||
execute_layout.setSpacing(12)
|
||||
execute_layout.setContentsMargins(20, 24, 20, 20)
|
||||
|
||||
# ── 进度条 + 状态文案 ────────────────────────────────────────────────
|
||||
progress_row = QHBoxLayout()
|
||||
self.progress_label = QLabel("就绪")
|
||||
self.progress_label.setMinimumWidth(220)
|
||||
progress_row.addWidget(self.progress_label)
|
||||
# 进度状态呈现(使用独一无二的 ID 选择器,彻底击碎并无视任何全局白块背景样式!)
|
||||
self.progress_label = QLabel("⏳ 准备就绪")
|
||||
self.progress_label.setObjectName("step13_progress_lbl")
|
||||
self.progress_label.setStyleSheet("""
|
||||
QLabel#step13_progress_lbl {
|
||||
background-color: transparent;
|
||||
background: transparent;
|
||||
border: none;
|
||||
color: #4A5568;
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
}
|
||||
""")
|
||||
execute_layout.addWidget(self.progress_label)
|
||||
|
||||
# 现代极简细线条进度条
|
||||
self.progress_bar = QProgressBar()
|
||||
self.progress_bar.setRange(0, 100)
|
||||
self.progress_bar.setValue(0)
|
||||
self.progress_bar.setTextVisible(True)
|
||||
progress_row.addWidget(self.progress_bar, 1)
|
||||
layout.addLayout(progress_row)
|
||||
self.progress_bar.setTextVisible(False) # 【核心】关闭原生文字,彻底干掉 Windows 丑陋白框!
|
||||
self.progress_bar.setFixedHeight(8) # 压低高度,高级感拉满
|
||||
self.progress_bar.setStyleSheet("""
|
||||
QProgressBar { border: none; border-radius: 4px; background-color: #E2E8F0; }
|
||||
QProgressBar::chunk { background-color: #0078D7; border-radius: 4px; }
|
||||
""")
|
||||
execute_layout.addWidget(self.progress_bar)
|
||||
|
||||
action_layout = QHBoxLayout()
|
||||
action_layout.addStretch()
|
||||
|
||||
self.generate_btn = QPushButton("独立运行步骤")
|
||||
self.generate_btn.setStyleSheet(ModernStylesheet.get_button_stylesheet("primary"))
|
||||
self.generate_btn.setMinimumWidth(140)
|
||||
self.generate_btn.clicked.connect(self.on_generate_clicked)
|
||||
action_layout.addWidget(self.generate_btn)
|
||||
|
||||
execute_layout.addLayout(action_layout)
|
||||
execute_group.setLayout(execute_layout)
|
||||
layout.addWidget(execute_group)
|
||||
|
||||
layout.addStretch()
|
||||
self.setLayout(layout)
|
||||
|
||||
# 刷新引擎提示文字
|
||||
self._refresh_ai_label()
|
||||
|
||||
# 初次构建时尝试同步主窗口工作目录
|
||||
self._auto_pull_work_dir()
|
||||
|
||||
def _refresh_ai_label(self):
|
||||
@ -215,6 +291,11 @@ class Step13ReportPanel(QWidget):
|
||||
def _open_ai_settings(self):
|
||||
"""弹出全局 AI 设置对话框,保存后刷新提示标签。"""
|
||||
dlg = AISettingsDialog(self)
|
||||
# 【强力注入】强制将配置弹窗内的标签与编组框背景抹为透明,全面恢复高级灰度质感!
|
||||
dlg.setStyleSheet("""
|
||||
QLabel { background-color: transparent; background: transparent; border: none; }
|
||||
QGroupBox { background-color: transparent; }
|
||||
""")
|
||||
if dlg.exec_() == dlg.Accepted:
|
||||
self._refresh_ai_label()
|
||||
|
||||
@ -333,21 +414,22 @@ class Step13ReportPanel(QWidget):
|
||||
print(f"[{level}] {msg}")
|
||||
|
||||
def _on_progress(self, pct: int, text: str):
|
||||
"""接收 ReportWorkerThread.progress(int, str) —— 主线程槽。"""
|
||||
"""接收后台进度的槽函数 —— 主线程。"""
|
||||
self.progress_bar.setValue(int(pct))
|
||||
self.progress_label.setText(text or f"{pct}%")
|
||||
# 将百分比和文案完美融合进透明标签
|
||||
self.progress_label.setText(f"⏳ {text} ({pct}%)" if text else f"⏳ 正在生成... ({pct}%)")
|
||||
|
||||
def _on_finished(self, path: str):
|
||||
"""报告生成成功 —— 主线程槽。"""
|
||||
self.progress_bar.setValue(100)
|
||||
self.progress_label.setText("完成")
|
||||
self.progress_label.setText("✅ 分析报告生成成功!")
|
||||
self.generate_btn.setEnabled(True)
|
||||
QMessageBox.information(self, "完成", f"报告已生成:\n{path}")
|
||||
self._forward_log(f"Word 报告已保存: {path}", "info")
|
||||
|
||||
def _on_error(self, err: str):
|
||||
"""报告生成异常 —— 主线程槽。"""
|
||||
self.progress_label.setText("失败")
|
||||
self.progress_label.setText("❌ 报告生成失败")
|
||||
self.generate_btn.setEnabled(True)
|
||||
QMessageBox.critical(self, "失败", f"报告生成失败:\n{err[:800]}")
|
||||
self._forward_log(err, "error")
|
||||
Reference in New Issue
Block a user