feat(history): enable 'Analysis Report' button in simulation history
- ProjectManager._to_dict now scans simulation state files to find last_simulation_id and last_report_id for each project - HistoryDatabase: report button enabled when last_report_id or last_simulation_id available; goToReport looks up report by simulation ID if no direct report_id; report status icon reflects availability - Add getReportBySimulation() to frontend report API Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
f0f8a797ef
commit
e7641e9831
|
|
@ -242,8 +242,43 @@ class ProjectManager:
|
|||
|
||||
@classmethod
|
||||
def _to_dict(cls, proj: "ProjectModel") -> Dict[str, Any]:
|
||||
import os, json as _json
|
||||
ontology = cls.get_ontology(proj.id)
|
||||
graph_external_id = cls.get_latest_graph_external_id(proj.id)
|
||||
|
||||
# Find the latest simulation for this project by scanning state.json files
|
||||
last_simulation_id = None
|
||||
last_report_id = None
|
||||
sim_base = Config.OASIS_SIMULATION_DATA_DIR
|
||||
if os.path.isdir(sim_base):
|
||||
candidates = []
|
||||
for entry in os.scandir(sim_base):
|
||||
if not entry.is_dir():
|
||||
continue
|
||||
state_path = os.path.join(entry.path, "state.json")
|
||||
if not os.path.exists(state_path):
|
||||
continue
|
||||
try:
|
||||
with open(state_path, encoding="utf-8") as f:
|
||||
state = _json.load(f)
|
||||
if state.get("project_id") == proj.id:
|
||||
candidates.append((state.get("updated_at", ""), state.get("simulation_id")))
|
||||
except Exception:
|
||||
pass
|
||||
if candidates:
|
||||
candidates.sort(reverse=True)
|
||||
last_simulation_id = candidates[0][1]
|
||||
|
||||
# Find latest report for that simulation
|
||||
if last_simulation_id:
|
||||
from ..services.report_agent import ReportManager
|
||||
try:
|
||||
report = ReportManager.get_report_by_simulation(last_simulation_id)
|
||||
if report:
|
||||
last_report_id = report.report_id
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
return {
|
||||
"id": proj.id,
|
||||
"project_id": proj.id,
|
||||
|
|
@ -262,4 +297,6 @@ class ProjectManager:
|
|||
"graph_id": graph_external_id,
|
||||
"graph_build_task_id": None,
|
||||
"error": None,
|
||||
"last_simulation_id": last_simulation_id,
|
||||
"last_report_id": last_report_id,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,3 +50,11 @@ export const chatWithReport = (data) => {
|
|||
return requestWithRetry(() => service.post('/api/report/chat', data), 3, 1000)
|
||||
}
|
||||
|
||||
/**
|
||||
* Get report by simulation ID
|
||||
* @param {string} simulationId
|
||||
*/
|
||||
export const getReportBySimulation = (simulationId) => {
|
||||
return service.get(`/api/report/by-simulation/${simulationId}`)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -44,7 +44,8 @@
|
|||
:title="$t('history.envSetup')"
|
||||
>◈</span>
|
||||
<span
|
||||
class="status-icon unavailable"
|
||||
class="status-icon"
|
||||
:class="{ available: project.last_report_id || project.last_simulation_id, unavailable: !project.last_report_id && !project.last_simulation_id }"
|
||||
:title="$t('history.analysisReport')"
|
||||
>◆</span>
|
||||
</div>
|
||||
|
|
@ -173,7 +174,7 @@
|
|||
<button
|
||||
class="modal-btn btn-report"
|
||||
@click="goToReport"
|
||||
:disabled="true"
|
||||
:disabled="!selectedProject.last_report_id && !selectedProject.last_simulation_id"
|
||||
>
|
||||
<span class="btn-step">Step4</span>
|
||||
<span class="btn-icon">◆</span>
|
||||
|
|
@ -196,6 +197,7 @@ import { ref, computed, onMounted, onUnmounted, onActivated, watch, nextTick } f
|
|||
import { useRouter, useRoute } from 'vue-router'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { listProjects } from '../api/graph'
|
||||
import { getReportBySimulation } from '../api/report'
|
||||
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
|
|
@ -427,8 +429,26 @@ const goToSimulation = () => {
|
|||
}
|
||||
|
||||
// 导航到分析报告页面(Report)
|
||||
const goToReport = () => {
|
||||
// Report not yet implemented in F1-1
|
||||
const goToReport = async () => {
|
||||
if (!selectedProject.value) return
|
||||
|
||||
// Use known report_id if available
|
||||
let reportId = selectedProject.value.last_report_id
|
||||
|
||||
// Otherwise look it up by simulation_id
|
||||
if (!reportId && selectedProject.value.last_simulation_id) {
|
||||
try {
|
||||
const res = await getReportBySimulation(selectedProject.value.last_simulation_id)
|
||||
reportId = res?.data?.report_id
|
||||
} catch {
|
||||
// no report found
|
||||
}
|
||||
}
|
||||
|
||||
if (reportId) {
|
||||
closeModal()
|
||||
router.push({ name: 'Interaction', params: { reportId } })
|
||||
}
|
||||
}
|
||||
|
||||
// 加载历史项目
|
||||
|
|
|
|||
Loading…
Reference in New Issue