将literature改名为paper

This commit is contained in:
2025-01-16 02:40:32 +00:00
parent 3cfaf8bcba
commit 42e7e4e885
5 changed files with 488 additions and 254 deletions
+1 -1
View File
@@ -743,7 +743,7 @@
<div class="navbar-menu-item" onclick="window.location.href='lab.html'">Project</div>
<div class="navbar-menu-item active">Device</div>
<div class="navbar-menu-item" onclick="window.location.href='reports.html'">Reports</div>
<div class="navbar-menu-item" onclick="window.location.href='literature.html'">Literature</div>
<div class="navbar-menu-item" onclick="window.location.href='paper.html'">Paper</div>
</div>
<div class="navbar-right">
<a href="https://beta.obscura.work/lab/device-register.html" target="_blank" class="btn btn-primary">
+15 -15
View File
@@ -747,7 +747,7 @@
<div class="navbar-menu-item active">Project</div>
<div class="navbar-menu-item" onclick="window.open('device.html', '_blank')">Device</div>
<div class="navbar-menu-item" onclick="window.open('reports.html', '_blank')">Reports</div>
<div class="navbar-menu-item" onclick="window.open('literature.html', '_blank')">Literature</div>
<div class="navbar-menu-item" onclick="window.open('Paper.html', '_blank')">Paper</div>
</div>
<div class="navbar-right">
<a href="https://beta.obscura.work/lab/device-register.html" target="_blank" class="btn btn-primary">
@@ -908,9 +908,9 @@
<i class="bi bi-journal-text"></i>
<span>Memo</span>
</div>
<div class="sidebar-item" onclick="event.preventDefault(); window.open('https://beta.obscura.work/lab/literature.html?projectId=' + currentProjectId, '_blank')">
<div class="sidebar-item" onclick="event.preventDefault(); window.open('https://beta.obscura.work/lab/Paper.html?projectId=' + currentProjectId, '_blank')">
<i class="bi bi-book"></i>
<span>Literature</span>
<span>Paper</span>
</div>
<div class="sidebar-item" onclick="downloadProjectReport(currentProjectId)">
<i class="bi bi-file-earmark-text"></i>
@@ -2827,7 +2827,7 @@
`;
document.body.appendChild(loadingToast);
let projectResult, literatureResult;
let projectResult, paperResult;
// 3. Generate new project report
@@ -2843,24 +2843,24 @@
projectResult = await analyzeResponse.json();
// 2. Get literature analysis report
const literatureReportResponse = await fetch(`${API_BASE_URL}/references/${projectId}/summary_report`, {
// 2. Get paper analysis report
const paperReportResponse = await fetch(`${API_BASE_URL}/references/${projectId}/summary_report`, {
headers: {
'Authorization': `Bearer ${token}`
}
});
if (literatureReportResponse.status === 404 || !literatureReportResponse.ok) {
console.log('No saved literature analysis report found, generating new report...');
const literatureAnalyzeResponse = await fetch(`${API_BASE_URL}/references/${projectId}/analyze_report`, {
if (paperReportResponse.status === 404 || !paperReportResponse.ok) {
console.log('No saved paper analysis report found, generating new report...');
const paperAnalyzeResponse = await fetch(`${API_BASE_URL}/references/${projectId}/analyze_report`, {
headers: {
'Authorization': `Bearer ${token}`
}
});
if (!literatureAnalyzeResponse.ok) {
console.log('Failed to generate literature analysis report, will only include project report');
literatureResult = null;
if (!paperAnalyzeResponse.ok) {
console.log('Failed to generate paper analysis report, will only include project report');
paperResult = null;
} else {
// Re-fetch generated report
const newReportResponse = await fetch(`${API_BASE_URL}/references/${projectId}/summary_report`, {
@@ -2870,17 +2870,17 @@
});
if (newReportResponse.ok) {
literatureResult = await newReportResponse.json();
paperResult = await newReportResponse.json();
}
}
} else {
literatureResult = await literatureReportResponse.json();
paperResult = await paperReportResponse.json();
}
// 3. Merge reports
const combinedReport = {
project_report: projectResult,
literature_analysis: literatureResult || "No literature analysis report found"
paper_analysis: paperResult || "No analysis report found"
};
// 4. Remove loading prompt
+385 -151
View File
@@ -1335,132 +1335,6 @@ async def complete_experiment(
print(f"Error completing experiment: {str(e)}")
raise HTTPException(status_code=500, detail=f"Failed to complete experiment: {str(e)}")
@app.get("/lab/experiments/{experiment_id}/analyze")
async def analyze_data(
experiment_id: str,
current_user: UserModel = Depends(get_current_user)
):
"""分析实验数据"""
db = await get_database()
redis = await get_redis()
try:
sessions = []
total_points = 0
total_duration = 0
devices_set = set()
sensors_count = 0
async for session in db.experiment_sessions.find({
"experiment_id": ObjectId(experiment_id)
}):
# 计算会话持续时间
end_time = session.get("end_time") or datetime.now(timezone.utc)
duration = (end_time - session["start_time"]).total_seconds()
total_duration += duration
# 转换时间戳为毫秒
start_ms = int(session["start_time"].timestamp() * 1000)
end_ms = int(end_time.timestamp() * 1000)
# 统计设备和传感器数量
session_devices = session.get("devices", [])
for device in session_devices:
devices_set.add(device["serial_number"])
sensors_count += len(device.get("sensors", []))
# 获取会话数据点数
session_points = 0
for device in session_devices:
stream_key = f"experiment:{experiment_id}:{device['serial_number']}"
await redis.select(200)
# 使用 xrange 获取指定时间范围内的数据
data_points = await redis.xrange(
stream_key,
min=str(start_ms),
max=str(end_ms)
)
# 计算数据点数量
points = len(data_points)
session_points += points
# 累加到总数据点
total_points += session_points
sessions.append({
"session_id": str(session["_id"]),
"duration": duration,
"data_points": session_points
})
if not sessions:
raise HTTPException(status_code=404, detail="没有找到实验会话数据")
# 准备分析数据
experiment_info = {
"total_sessions": len(sessions),
"total_duration": total_duration,
"total_points": total_points,
"device_stats": {
"total_devices": len(devices_set),
"total_sensors": sensors_count
},
"sessions": sessions
}
# 发送统计数据进行分析
analysis_result = await analyze_experiment_data(experiment_info)
if not analysis_result:
raise HTTPException(status_code=500, detail="生成分析报告失败")
# 保存分析结果到db201
await redis.select(201)
report_key = f"experiment_report:{experiment_id}"
await redis.set(report_key, json.dumps(analysis_result))
return analysis_result
except Exception as e:
print(f"Error analyzing experiment data: {str(e)}")
raise HTTPException(status_code=500, detail=str(e))
finally:
try:
await redis.aclose()
except Exception as e:
print(f"Error closing Redis connection: {e}")
@app.get("/lab/experiments/{experiment_id}/report")
async def get_saved_report(
experiment_id: str,
current_user: UserModel = Depends(get_current_user)
):
"""从 Redis db201 读取已保存的实验报告"""
redis = await get_redis()
try:
# 选择 db201
await redis.select(201)
report_key = f"experiment_report:{experiment_id}"
# 获取已保存的报告
existing_report = await redis.get(report_key)
if not existing_report:
raise HTTPException(status_code=404, detail="No saved experiment report found")
# 返回报告
return json.loads(existing_report)
except Exception as e:
print(f"Error getting experiment report: {e}")
raise HTTPException(status_code=500, detail=str(e))
finally:
try:
await redis.aclose()
except Exception as e:
print(f"Error closing Redis connection: {e}")
# 修改进入实验的路由,添加状态检查
@app.get("/lab/experiments/{experiment_id}")
@@ -1650,14 +1524,322 @@ async def analyze_project_data(project_data):
return None
# 创建线程池
exppro_analysis_thread_pool = ThreadPoolExecutor(max_workers=3)
@app.get("/lab/experiments/{experiment_id}/analyze")
async def analyze_data(
experiment_id: str,
current_user: UserModel = Depends(get_current_user)
):
"""启动实验数据分析"""
db = await get_database()
redis = await get_redis()
try:
# 检查是否已经有正在进行的分析任务
await redis.select(201)
status_key = f"experiment_analysis_status:{experiment_id}"
current_status = await redis.get(status_key)
if current_status:
status_data = json.loads(current_status)
if status_data.get("status") == "processing":
return {
"message": "实验分析任务正在进行中",
"status": "processing",
"experiment_id": experiment_id,
"start_time": status_data.get("start_time")
}
# 记录分析开始状态
status_data = {
"status": "processing",
"start_time": datetime.now(timezone.utc).isoformat()
}
await redis.set(status_key, json.dumps(status_data))
# 在新线程中运行分析任务
exppro_analysis_thread_pool.submit(
run_experiment_analysis_in_thread,
experiment_id
)
return {
"message": "实验分析任务已启动",
"status": "processing",
"experiment_id": experiment_id,
"start_time": status_data["start_time"]
}
except Exception as e:
print(f"Error starting experiment analysis: {str(e)}")
raise HTTPException(status_code=500, detail=str(e))
finally:
try:
await redis.aclose()
except Exception as e:
print(f"Error closing Redis connection: {e}")
def run_experiment_analysis_in_thread(experiment_id: str):
"""在独立线程中运行实验分析任务"""
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
try:
loop.run_until_complete(
process_experiment_analysis(experiment_id)
)
except Exception as e:
print(f"Error in analysis thread: {str(e)}")
finally:
loop.close()
async def process_experiment_analysis(experiment_id: str):
"""后台处理实验分析任务"""
db = await get_database()
redis = await get_redis()
try:
sessions = []
total_points = 0
total_duration = 0
devices_set = set()
sensors_count = 0
async for session in db.experiment_sessions.find({
"experiment_id": ObjectId(experiment_id)
}):
# 计算会话持续时间
end_time = session.get("end_time") or datetime.now(timezone.utc)
duration = (end_time - session["start_time"]).total_seconds()
total_duration += duration
# 转换时间戳为毫秒
start_ms = int(session["start_time"].timestamp() * 1000)
end_ms = int(end_time.timestamp() * 1000)
# 统计设备和传感器数量
session_devices = session.get("devices", [])
for device in session_devices:
devices_set.add(device["serial_number"])
sensors_count += len(device.get("sensors", []))
# 获取会话数据点数
session_points = 0
for device in session_devices:
stream_key = f"experiment:{experiment_id}:{device['serial_number']}"
await redis.select(200)
# 使用 xrange 获取指定时间范围内的数据
data_points = await redis.xrange(
stream_key,
min=str(start_ms),
max=str(end_ms)
)
# 计算数据点数量
points = len(data_points)
session_points += points
# 累加到总数据点
total_points += session_points
sessions.append({
"session_id": str(session["_id"]),
"duration": duration,
"data_points": session_points
})
if not sessions:
raise HTTPException(status_code=404, detail="没有找到实验会话数据")
experiment_info = {
"total_sessions": len(sessions),
"total_duration": total_duration,
"total_points": total_points,
"device_stats": {
"total_devices": len(devices_set),
"total_sensors": sensors_count
},
"sessions": sessions
}
# 执行分析
analysis_result = await analyze_experiment_data(experiment_info)
if analysis_result:
# 保存分析结果
await redis.select(201)
report_key = f"experiment_report:{experiment_id}"
await redis.set(report_key, json.dumps(analysis_result))
# 更新状态为完成
status_key = f"experiment_analysis_status:{experiment_id}"
status_data = {
"status": "completed",
"completion_time": datetime.now(timezone.utc).isoformat()
}
await redis.set(status_key, json.dumps(status_data))
else:
# 更新失败状态
status_data = {
"status": "failed",
"error": "Failed to generate analysis result",
"completion_time": datetime.now(timezone.utc).isoformat()
}
await redis.set(status_key, json.dumps(status_data))
except Exception as e:
print(f"Error in background experiment analysis: {str(e)}")
try:
await redis.select(201)
status_key = f"experiment_analysis_status:{experiment_id}"
status_data = {
"status": "failed",
"error": str(e),
"completion_time": datetime.now(timezone.utc).isoformat()
}
await redis.set(status_key, json.dumps(status_data))
except Exception as redis_error:
print(f"Error updating Redis status: {redis_error}")
finally:
try:
await redis.aclose()
except Exception as e:
print(f"Error closing Redis connection: {e}")
@app.get("/lab/experiments/{experiment_id}/analysis_status")
async def get_experiment_analysis_status(
experiment_id: str,
current_user: UserModel = Depends(get_current_user)
):
"""获取实验分析任务的状态"""
redis = await get_redis()
try:
await redis.select(201)
status_key = f"experiment_analysis_status:{experiment_id}"
status_data = await redis.get(status_key)
if not status_data:
return {
"status": "not_started",
"experiment_id": experiment_id
}
return json.loads(status_data)
except Exception as e:
print(f"Error getting analysis status: {str(e)}")
raise HTTPException(status_code=500, detail=str(e))
finally:
try:
await redis.aclose()
except Exception as e:
print(f"Error closing Redis connection: {e}")
@app.get("/lab/experiments/{experiment_id}/report")
async def get_saved_report(
experiment_id: str,
current_user: UserModel = Depends(get_current_user)
):
"""从 Redis db201 读取已保存的实验报告"""
redis = await get_redis()
try:
# 选择 db201
await redis.select(201)
report_key = f"experiment_report:{experiment_id}"
# 获取已保存的报告
existing_report = await redis.get(report_key)
if not existing_report:
raise HTTPException(status_code=404, detail="No saved experiment report found")
# 返回报告
return json.loads(existing_report)
except Exception as e:
print(f"Error getting experiment report: {e}")
raise HTTPException(status_code=500, detail=str(e))
finally:
try:
await redis.aclose()
except Exception as e:
print(f"Error closing Redis connection: {e}")
# 项目分析的异步实现类似:
@app.get("/lab/projects/{project_id}/analyze")
async def analyze_project_data_endpoint(
project_id: str,
current_user: UserModel = Depends(get_current_user)
):
"""分析项目数据"""
"""启动项目数据分析"""
db = await get_database()
redis = await get_redis()
try:
# 检查是否已经有正在进行的分析任务
await redis.select(202)
status_key = f"project_analysis_status:{project_id}"
current_status = await redis.get(status_key)
if current_status:
status_data = json.loads(current_status)
if status_data.get("status") == "processing":
return {
"message": "项目分析任务正在进行中",
"status": "processing",
"project_id": project_id,
"start_time": status_data.get("start_time")
}
# 记录分析开始状态
status_data = {
"status": "processing",
"start_time": datetime.now(timezone.utc).isoformat()
}
await redis.set(status_key, json.dumps(status_data))
# 在新线程中运行分析任务
exppro_analysis_thread_pool.submit(
run_project_analysis_in_thread,
project_id
)
return {
"message": "项目分析任务已启动",
"status": "processing",
"project_id": project_id,
"start_time": status_data["start_time"]
}
except Exception as e:
print(f"Error starting project analysis: {str(e)}")
raise HTTPException(status_code=500, detail=str(e))
finally:
try:
await redis.aclose()
except Exception as e:
print(f"Error closing Redis connection: {e}")
def run_project_analysis_in_thread(project_id: str):
"""在独立线程中运行项目分析任务"""
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
try:
loop.run_until_complete(
process_project_analysis(project_id)
)
except Exception as e:
print(f"Error in analysis thread: {str(e)}")
finally:
loop.close()
async def process_project_analysis(project_id: str):
"""后台处理项目分析任务"""
db = await get_database()
redis = await get_redis()
@@ -1740,21 +1922,73 @@ async def analyze_project_data_endpoint(
"experiment_reports": all_experiment_reports
}
# 发送数据进行项目级分析
# 执行分析
analysis_result = await analyze_project_data(project_data)
if not analysis_result:
raise HTTPException(status_code=500, detail="Failed to generate project analysis report")
# 将分析结果保存到Redis db202
if analysis_result:
# 保存分析结果
await redis.select(202)
report_key = f"project_report:{project_id}"
await redis.set(report_key, json.dumps(analysis_result))
# 更新状态为完成
status_key = f"project_analysis_status:{project_id}"
status_data = {
"status": "completed",
"completion_time": datetime.now(timezone.utc).isoformat()
}
await redis.set(status_key, json.dumps(status_data))
else:
# 更新失败状态
status_data = {
"status": "failed",
"error": "Failed to generate analysis result",
"completion_time": datetime.now(timezone.utc).isoformat()
}
await redis.set(status_key, json.dumps(status_data))
except Exception as e:
print(f"Error in background project analysis: {str(e)}")
try:
await redis.select(202)
status_key = f"project_analysis_status:{project_id}"
status_data = {
"status": "failed",
"error": str(e),
"completion_time": datetime.now(timezone.utc).isoformat()
}
await redis.set(status_key, json.dumps(status_data))
except Exception as redis_error:
print(f"Error updating Redis status: {redis_error}")
finally:
try:
await redis.aclose()
except Exception as e:
print(f"Error closing Redis connection: {e}")
@app.get("/lab/projects/{project_id}/analysis_status")
async def get_project_analysis_status(
project_id: str,
current_user: UserModel = Depends(get_current_user)
):
"""获取项目分析任务的状态"""
redis = await get_redis()
try:
await redis.select(202)
report_key = f"project_report:{project_id}"
await redis.set(report_key, json.dumps(analysis_result))
status_key = f"project_analysis_status:{project_id}"
status_data = await redis.get(status_key)
return analysis_result
if not status_data:
return {
"status": "not_started",
"project_id": project_id
}
return json.loads(status_data)
except Exception as e:
print(f"Error analyzing project data: {e}")
print(f"Error getting analysis status: {str(e)}")
raise HTTPException(status_code=500, detail=str(e))
finally:
try:
@@ -2060,18 +2294,18 @@ async def get_reference_report(
# 修改函数定义为异步函数
async def analyze_reference_summary(reference_data):
system_prompt = """
You are an AI assistant responsible for analyzing literature reports.
You will summarize and analyze all literature reports and generate a comprehensive analysis report in JSON format.
You are an AI assistant responsible for analyzing paper reports.
You will summarize and analyze all paper reports and generate a comprehensive analysis report in JSON format.
The JSON structure must strictly follow the provided template.
"""
user_prompt = f"""Analyze the following literature reports:
Literature reports: {json.dumps(reference_data, ensure_ascii=False)}
user_prompt = f"""Analyze the following paper reports:
Paper reports: {json.dumps(reference_data, ensure_ascii=False)}
Generate a JSON response with the following structure:
{{
"Literature Summary Report": {{
"Paper Summary Report": {{
"overview": {{
"total_papers": "[Number of papers]",
"time_range": {{"start_year": "[Start year]", "end_year": "[End year]"}},
@@ -2094,11 +2328,11 @@ async def analyze_reference_summary(reference_data):
}},
"future_directions": {{
"potential_applications": "[Potential future applications]",
"methodological_suggestions": "[Methodological suggestions based on literature summary]"
"methodological_suggestions": "[Methodological suggestions based on paper summary]"
}},
"impact_assessment": {{
"academic_influence": "[Summarize the academic influence of the literature]",
"practical_value": "[Summarize the practical value of the literature]"
"academic_influence": "[Summarize the academic influence of the paper]",
"practical_value": "[Summarize the practical value of the paper]"
}}
}}
}}
@@ -3073,13 +3307,13 @@ async def analyze_long_document_async(content: str) -> List[dict]:
print(f"\n开始分析第 {i+1}/{len(segments)} 个段落...")
system_prompt = f"""
You are an AI assistant tasked with analyzing part {i+1} of {len(segments)} of an academic literature.
You are an AI assistant tasked with analyzing part {i+1} of {len(segments)} of an academic paper.
Generate a comprehensive analysis in JSON format covering both basic information and content analysis.
Note that this is part {i+1} of a longer document, so focus on the content provided.
The JSON structure must strictly follow the provided template.
"""
user_prompt = f"""Analyze the following literature segment and extract all relevant information:
user_prompt = f"""Analyze the following paper segment and extract all relevant information:
Content: {segment}
Generate a JSON response with the following structure:
@@ -3130,7 +3364,7 @@ async def merge_analysis_results(results: List[dict]) -> dict:
print(f"开始合并 {len(results)} 个分析结果...")
system_prompt = """
You are an AI assistant tasked with merging multiple analysis results of different parts of the same academic literature.
You are an AI assistant tasked with merging multiple analysis results of different parts of the same academic paper.
Generate a comprehensive merged analysis in JSON format.
The JSON structure must strictly follow the provided template.
Ensure the merged result is coherent and eliminates redundancy.
@@ -3174,12 +3408,12 @@ async def merge_analysis_results(results: List[dict]) -> dict:
async def analyze_reference_document_async(content: str):
"""分析文献的基本信息和内容"""
system_prompt = """
You are an AI assistant tasked with analyzing academic literature.
You are an AI assistant tasked with analyzing academic paper.
Generate a comprehensive analysis in JSON format covering both basic information and content analysis.
The JSON structure must strictly follow the provided template.
"""
user_prompt = f"""Analyze the following literature and extract all relevant information:
user_prompt = f"""Analyze the following paper and extract all relevant information:
Content: {content}
Generate a JSON response with the following structure:
@@ -3211,12 +3445,12 @@ async def analyze_reference_document_async(content: str):
async def analyze_reference_value_async(content_analysis: dict):
"""基于内容分析结果评估文献的价值"""
system_prompt = """
You are an AI assistant tasked with evaluating the value of academic literature based on its content analysis.
You are an AI assistant tasked with evaluating the value of academic paper based on its content analysis.
Generate a comprehensive value evaluation in JSON format.
The JSON structure must strictly follow the provided template.
"""
user_prompt = f"""Based on the following content analysis, evaluate the literature's value:
user_prompt = f"""Based on the following content analysis, evaluate the paper's value:
Content Analysis: {json.dumps(content_analysis, ensure_ascii=False)}
Generate a JSON response with the following structure:
+63 -63
View File
@@ -3,7 +3,7 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Literature Analysis</title>
<title>Paper Analysis</title>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/font/bootstrap-icons.min.css">
<style>
@@ -356,7 +356,7 @@
<div class="navbar-menu-item" onclick="window.location.href='lab.html'">Project</div>
<div class="navbar-menu-item" onclick="window.location.href='device.html'">Device</div>
<div class="navbar-menu-item" onclick="window.location.href='reports.html'">Reports</div>
<div class="navbar-menu-item active" onclick="window.location.href='literature.html'">Literature</div>
<div class="navbar-menu-item active" onclick="window.location.href='Paper.html'">Paper</div>
</div>
<div class="navbar-right">
<a href="https://beta.obscura.work/lab/device.html" target="_blank" class="btn btn-primary">
@@ -389,9 +389,9 @@
<!-- 项目文献页面的侧边栏 -->
<div class="sidebar-menu hidden" id="projectDetailSidebar">
<div class="sidebar-item" onclick="showLiteratureList()">
<div class="sidebar-item" onclick="showPaperList()">
<i class="bi bi-list-ul"></i>
<span>Literature List</span>
<span>Paper List</span>
</div>
<div class="sidebar-item" onclick="downloadReferenceReport()">
<i class="bi bi-file-earmark-text"></i>
@@ -421,8 +421,8 @@
<!-- 项目文献详情页面 -->
<div id="projectDetailPage" class="content-body hidden">
<div class="content-header d-flex justify-content-between align-items-center">
<h3 class="content-title" id="referenceAnalysisTitle">Literature Analysis</h3>
<button class="btn btn-info" onclick="uploadLiterature()">
<h3 class="content-title" id="referenceAnalysisTitle">Paper Analysis</h3>
<button class="btn btn-info" onclick="uploadPaper()">
<i class="bi bi-upload me-2"></i>
Upload
</button>
@@ -433,9 +433,9 @@
</div>
<!-- 文献分析报告页面 -->
<div id="literatureReportPage" class="content-body hidden">
<div id="paperReportPage" class="content-body hidden">
<div class="content-header d-flex justify-content-between align-items-center">
<h3 class="content-title" id="literatureReportTitle">Literature Summary Report</h3>
<h3 class="content-title" id="paperReportTitle">Paper Summary Report</h3>
<div class="d-flex gap-2">
<button class="btn btn-infoy" onclick="regenerateReport()">
<i class="bi bi-arrow-clockwise me-2"></i>
@@ -447,7 +447,7 @@
</button>
</div>
</div>
<div id="literatureReportContent" class="mt-4">
<div id="paperReportContent" class="mt-4">
<!-- 报告内容将在这里动态加载 -->
</div>
</div>
@@ -564,7 +564,7 @@
// 隐藏其他页面和侧边栏
document.getElementById('projectDetailPage').classList.add('hidden');
document.getElementById('projectDetailSidebar').classList.add('hidden');
document.getElementById('literatureReportPage').classList.add('hidden');
document.getElementById('paperReportPage').classList.add('hidden');
currentProjectId = null;
// 重新加载项目列表数据
@@ -584,14 +584,14 @@
document.getElementById('projectDetailSidebar').classList.remove('hidden');
// 隐藏报告页面
document.getElementById('literatureReportPage').classList.add('hidden');
document.getElementById('paperReportPage').classList.add('hidden');
document.getElementById('referenceAnalysisTitle').textContent = `Literature Analysis - ${projectName}`;
document.getElementById('referenceAnalysisTitle').textContent = `Paper Analysis - ${projectName}`;
await loadReferences(projectId);
}
// Add show literature analysis page function
// Add show paper analysis page function
async function showReferenceAnalysis() {
try {
// Hide other pages
@@ -599,22 +599,22 @@
page.classList.remove('active');
});
// Show literature analysis page
// Show paper analysis page
document.getElementById('referenceAnalysisPage').classList.add('active');
// Set title
document.getElementById('referenceAnalysisTitle').textContent =
`Literature Analysis - ${document.getElementById('projectDetailTitle').textContent}`;
`Paper Analysis - ${document.getElementById('projectDetailTitle').textContent}`;
// Load literature list
// Load paper list
await loadReferences(currentProjectId);
} catch (error) {
console.error('Failed to show literature analysis page:', error);
alert('Failed to show literature analysis page, please try again');
console.error('Failed to show Paper analysis page:', error);
alert('Failed to show Paper analysis page, please try again');
}
}
// Literature card rendering function
// paper card rendering function
function renderReferenceCard(reference, projectId) {
const uploadTime = reference.upload_time;
const cardId = `reference-${reference._id}`;
@@ -629,7 +629,7 @@
<div class="spinner-border spinner-border-sm text-primary me-2" role="status">
<span class="visually-hidden">Loading...</span>
</div>
<span>Analyzing literature content...</span>
<span>Analyzing Paper content...</span>
</div>
</div>
<div class="btn-group">
@@ -659,12 +659,12 @@
`;
}
// Load literature list function
// Load paper list function
async function loadReferences(projectId) {
const referencesList = document.getElementById('referenceAnalysis');
try {
// Get literature list
// Get paper list
const response = await fetch(`${API_BASE_URL}/projects/${projectId}/references`, {
headers: {
'Authorization': `Bearer ${token}`
@@ -688,15 +688,15 @@
}
if (references.length === 0) {
referencesList.innerHTML = '<div class="alert alert-info">No literature data, please upload literature</div>';
referencesList.innerHTML = '<div class="alert alert-info">No paper data, please upload paper</div>';
return;
}
// Render literature cards
// Render paper cards
const referenceCards = references.map(ref => renderReferenceCard(ref, projectId)).join('');
referencesList.innerHTML = referenceCards;
// Get analysis status and results for each literature
// Get analysis status and results for each paper
references.forEach(async (ref) => {
try {
const checkAnalysisStatus = async () => {
@@ -721,7 +721,7 @@
<div class="spinner-border spinner-border-sm text-primary me-2" role="status">
<span class="visually-hidden">Loading...</span>
</div>
<span>Analyzing literature content...</span>
<span>Analyzing Paper content...</span>
</div>
`;
statusElement.innerHTML = '<span class="text-primary">Analysis in progress...</span>';
@@ -787,10 +787,10 @@
});
} catch (error) {
console.error('Failed to load literature list:', error);
console.error('Failed to load Paper list:', error);
referencesList.innerHTML = `
<div class="alert alert-danger">
Failed to load literature list: ${error.message}
Failed to load Paper list: ${error.message}
<br>
<button class="btn btn-primary mt-2" onclick="loadReferences('${projectId}')">
Retry
@@ -799,7 +799,7 @@
}
}
async function uploadLiterature() {
async function uploadPaper() {
if (!currentProjectId) {
alert('Please select a project first');
return;
@@ -912,7 +912,7 @@
input.click();
}
// View literature details function
// View paper details function
async function viewReferenceDetail(referenceId) {
try {
const response = await fetch(`${API_BASE_URL}/references/${referenceId}/report`, {
@@ -934,7 +934,7 @@
<div class="spinner-border text-primary me-3" role="status">
<span class="visually-hidden">Loading...</span>
</div>
<h5 class="mb-0">Analyzing literature content, please wait...</h5>
<h5 class="mb-0">Analyzing Paper content, please wait...</h5>
</div>
`;
} else if (analysisResult.status === 'completed') {
@@ -943,7 +943,7 @@
.replace(/},/g, '')
.replace(/{ },/g, '')
.replace(/^\s*,/gm, '')
.replace(/Literature Analysis Report:/, '<div style="text-align: center"><strong>Literature Analysis Report</strong></div>')
.replace(/Paper Analysis Report:/, '<div style="text-align: center"><strong>Paper Analysis</strong></div>')
.replace(/^(\s*\d+\.[^:\n]+:)/gm, '<strong>$1</strong>')
.split('\n')
.map(line => line.trimEnd())
@@ -972,7 +972,7 @@
<div class="modal-dialog modal-lg" style="max-width: 80%; margin: 1.75rem auto;">
<div class="modal-content" style="min-height: 80vh;">
<div class="modal-header">
<h5 class="modal-title" id="referenceDetailModalTitle">Literature Analysis Report</h5>
<h5 class="modal-title" id="referenceDetailModalTitle">Paper Analysis</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body" style="max-height: calc(80vh - 60px); overflow-y: auto;">
@@ -1003,17 +1003,17 @@
} catch (error) {
console.error('Failed to view details:', error);
alert('Failed to get literature analysis report, please try again later');
alert('Failed to get analysis report, please try again later');
}
}
// View literature details from card
// View paper details from card
function viewReferenceDetailFromCard(card) {
const referenceId = card.id.replace('reference-', '');
viewReferenceDetail(referenceId);
}
// Download literature analysis report function
// Download paper analysis report function
async function downloadReferenceReport() {
if (!currentProjectId) {
alert('Please select a project first');
@@ -1023,20 +1023,20 @@
try {
// 1. 检查是否有文献
const referencesList = document.getElementById('referenceAnalysis');
if (referencesList && referencesList.innerHTML.includes('No literature data')) {
alert('Please upload literature first!');
if (referencesList && referencesList.innerHTML.includes('No Paper data')) {
alert('Please upload Paper first!');
return;
}
// 显示报告页面
document.getElementById('projectsListPage').classList.add('hidden');
document.getElementById('projectDetailPage').classList.add('hidden');
const reportPage = document.getElementById('literatureReportPage');
const reportPage = document.getElementById('paperReportPage');
reportPage.classList.remove('hidden');
// Show loading status
const showLoading = (message) => {
document.getElementById('literatureReportContent').innerHTML = `
document.getElementById('paperReportContent').innerHTML = `
<div class="d-flex align-items-center justify-content-center" style="min-height: 200px;">
<div class="text-center">
<div class="spinner-border text-primary mb-3" role="status">
@@ -1049,7 +1049,7 @@
`;
};
showLoading('Getting literature analysis report...');
showLoading('Getting paper analysis report...');
// 2. Check if report already exists
const existingReport = await fetch(`${API_BASE_URL}/references/${currentProjectId}/summary_report`, {
@@ -1059,7 +1059,7 @@
if (existingReport.ok) {
const report = await existingReport.json();
currentReportData = report;
document.getElementById('literatureReportContent').innerHTML = formatReportContent(report);
document.getElementById('paperReportContent').innerHTML = formatReportContent(report);
return;
}
@@ -1095,7 +1095,7 @@
});
const report = await finalReport.json();
currentReportData = report;
document.getElementById('literatureReportContent').innerHTML = formatReportContent(report);
document.getElementById('paperReportContent').innerHTML = formatReportContent(report);
}
else if (status.status === 'failed') {
clearInterval(statusCheck);
@@ -1103,7 +1103,7 @@
}
else if (attempts >= maxAttempts) {
clearInterval(statusCheck);
document.getElementById('literatureReportContent').innerHTML = `
document.getElementById('paperReportContent').innerHTML = `
<div class="alert alert-warning">
Report generation is taking longer than expected. Please refresh and try again later.
<button class="btn btn-primary mt-2" onclick="downloadReferenceReport()">
@@ -1117,7 +1117,7 @@
}
} catch (error) {
clearInterval(statusCheck);
document.getElementById('literatureReportContent').innerHTML = `
document.getElementById('paperReportContent').innerHTML = `
<div class="alert alert-danger">
Failed to generate report: ${error.message}
<button class="btn btn-primary mt-2" onclick="downloadReferenceReport()">
@@ -1129,7 +1129,7 @@
}, 5000);
} catch (error) {
document.getElementById('literatureReportContent').innerHTML = `
document.getElementById('paperReportContent').innerHTML = `
<div class="alert alert-danger">
Operation failed: ${error.message}
<button class="btn btn-primary mt-2" onclick="downloadReferenceReport()">
@@ -1152,7 +1152,7 @@
.replace(/},/g, '')
.replace(/{ },/g, '')
.replace(/^\s*,/gm, '')
.replace(/Literature Summary Report:/, '<div style="text-align: center"><strong style="font-size: 24px;">Literature Summary Report</strong></div>')
.replace(/Paper Summary Report:/, '<div style="text-align: center"><strong style="font-size: 24px;">Paper Summary Report</strong></div>')
.replace(/^(\s*\d+\.[^:\n]+:)/gm, '<strong>$1</strong>')
.split('\n')
.map(line => line.trimEnd())
@@ -1162,9 +1162,9 @@
</div>`;
}
// Delete literature function
// Delete paper function
async function deleteReference(projectId, referenceId) {
if (!confirm('Are you sure you want to delete this literature? This action cannot be undone.')) {
if (!confirm('Are you sure you want to delete this Paper? This action cannot be undone.')) {
return;
}
@@ -1184,17 +1184,17 @@
const referencesList = document.getElementById('referenceAnalysis');
if (!referencesList.children.length) {
referencesList.innerHTML = '<div class="alert alert-info">No literature data, please upload literature</div>';
referencesList.innerHTML = '<div class="alert alert-info">No Paper data, please upload</div>';
}
alert('Literature deleted successfully');
alert('Deleted successfully');
} else {
const error = await response.json();
alert(`Failed to delete literature: ${error.detail}`);
alert(`Failed to delete Paper: ${error.detail}`);
}
} catch (error) {
console.error('Failed to delete literature:', error);
alert('Failed to delete literature, please try again');
console.error('Failed to delete Paper:', error);
alert('Failed to delete Paper, please try again');
}
}
@@ -1216,7 +1216,7 @@
<div class="modal-dialog modal-lg modal-dialog-centered" style="max-width: 800px;">
<div class="modal-content" style="min-height: 60vh;">
<div class="modal-header">
<h5 class="modal-title" id="chatModalTitle">Chat with Literature: ${title}</h5>
<h5 class="modal-title" id="chatModalTitle">${title}</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body d-flex flex-column" style="height: calc(60vh - 76px);">
@@ -1485,9 +1485,9 @@
}
// 添加显示文献列表的函数
function showLiteratureList() {
function showPaperList() {
// 隐藏报告页面
document.getElementById('literatureReportPage').classList.add('hidden');
document.getElementById('paperReportPage').classList.add('hidden');
// 显示文献列表页面
document.getElementById('projectDetailPage').classList.remove('hidden');
@@ -1515,7 +1515,7 @@
// 创建临时下载链接
const a = document.createElement('a');
a.href = url;
a.download = `literature_analysis_report_${new Date().toISOString().split('T')[0]}.json`;
a.download = `paper_analysis_report_${new Date().toISOString().split('T')[0]}.json`;
// 触发下载
document.body.appendChild(a);
@@ -1544,7 +1544,7 @@
try {
// 显示加载状态
const showLoading = (message) => {
document.getElementById('literatureReportContent').innerHTML = `
document.getElementById('paperReportContent').innerHTML = `
<div class="d-flex align-items-center justify-content-center" style="min-height: 200px;">
<div class="text-center">
<div class="spinner-border text-primary mb-3" role="status">
@@ -1589,7 +1589,7 @@
});
const report = await finalReport.json();
currentReportData = report;
document.getElementById('literatureReportContent').innerHTML = formatReportContent(report);
document.getElementById('paperReportContent').innerHTML = formatReportContent(report);
}
else if (status.status === 'failed') {
clearInterval(statusCheck);
@@ -1597,7 +1597,7 @@
}
else if (attempts >= maxAttempts) {
clearInterval(statusCheck);
document.getElementById('literatureReportContent').innerHTML = `
document.getElementById('paperReportContent').innerHTML = `
<div class="alert alert-warning">
Report regeneration is taking longer than expected. Please refresh and try again later.
<button class="btn btn-primary mt-2" onclick="regenerateReport()">
@@ -1611,7 +1611,7 @@
}
} catch (error) {
clearInterval(statusCheck);
document.getElementById('literatureReportContent').innerHTML = `
document.getElementById('paperReportContent').innerHTML = `
<div class="alert alert-danger">
Failed to regenerate report: ${error.message}
<button class="btn btn-primary mt-2" onclick="regenerateReport()">
@@ -1623,7 +1623,7 @@
}, 5000);
} catch (error) {
document.getElementById('literatureReportContent').innerHTML = `
document.getElementById('paperReportContent').innerHTML = `
<div class="alert alert-danger">
Operation failed: ${error.message}
<button class="btn btn-primary mt-2" onclick="regenerateReport()">
+24 -24
View File
@@ -635,7 +635,7 @@
<div class="navbar-menu-item" onclick="window.location.href='lab.html'">Project</div>
<div class="navbar-menu-item" onclick="window.location.href='device.html'">Device</div>
<div class="navbar-menu-item active">Reports</div>
<div class="navbar-menu-item" onclick="window.location.href='literature.html'">Literature</div>
<div class="navbar-menu-item" onclick="window.location.href='Paper.html'">Paper</div>
</div>
<div class="navbar-right">
<a href="https://beta.obscura.work/lab/device.html" target="_blank" class="btn btn-primary">
@@ -721,7 +721,7 @@
<option value="">All</option>
<option value="project">Project</option>
<option value="experiment">experiment</option>
<option value="literature">Literature</option>
<option value="paper">Paper</option>
</select>
</div>
</form>
@@ -745,9 +745,9 @@
<i class="bi bi-file-text"></i>
<span>Project</span>
</div>
<div class="sidebar-item" onclick="switchReportSection('literatureReport')">
<div class="sidebar-item" onclick="switchReportSection('paperReport')">
<i class="bi bi-book"></i>
<span>Literature</span>
<span>Paper</span>
</div>
<div class="sidebar-item" onclick="downloadCurrentReport()">
<i class="bi bi-download"></i>
@@ -772,8 +772,8 @@
<div id="projectReportSection" class="report-section active">
<pre id="projectReportDetail" class="report-content bg-light p-3 rounded"></pre>
</div>
<div id="literatureReportSection" class="report-section">
<pre id="literatureReportDetail" class="report-content bg-light p-3 rounded"></pre>
<div id="paperReportSection" class="report-section">
<pre id="paperReportDetail" class="report-content bg-light p-3 rounded"></pre>
</div>
</div>
</div>
@@ -860,7 +860,7 @@
.replace(/{ },/g, '')
.replace(/^\s*,/gm, '') // 处理行首的逗号
.replace(/Project Analysis Report:/, '<div style="text-align: center"><strong style="font-size: 24px;">Project Analysis Report</strong></div>')
.replace(/Literature Summary Report:/, '<div style="text-align: center"><strong style="font-size: 24px;">Literature Summary Report</strong></div>')
.replace(/paper Summary Report:/, '<div style="text-align: center"><strong style="font-size: 24px;">Paper Summary Report</strong></div>')
// 加粗标题 (以数字开头的行)
.replace(/^(\s*\d+\.[^:\n]+:)/gm, '<strong>$1</strong>')
// 保持缩进
@@ -912,7 +912,7 @@
// 修改后的 viewProjectReport 函数
async function viewProjectReport(projectId, projectName) {
try {
let projectData = null, literatureData = null;
let projectData = null, paperData = null;
// 隐藏项目列表页面
document.querySelector('.main-content > .row').style.display = 'none';
@@ -932,33 +932,33 @@
// 2. 如果没有项目报告,尝试获取文献分析报告
if (!projectData) {
const literatureResponse = await fetch(`${API_BASE_URL}/references/${projectId}/summary_report`, {
const paperResponse = await fetch(`${API_BASE_URL}/references/${projectId}/summary_report`, {
headers: {
'Authorization': `Bearer ${token}`
}
});
if (literatureResponse.ok) {
literatureData = await literatureResponse.json();
if (paperResponse.ok) {
paperData = await paperResponse.json();
} else {
console.log('No literature report found');
console.log('No paper report found');
}
}
// 3. 如果两种报告都没有,显示提示信息
if (!projectData && !literatureData) {
if (!projectData && !paperData) {
document.getElementById('reportDetailTitle').textContent = `Project Report - ${projectName}`;
document.getElementById('projectReportDetail').innerHTML =
'<div class="alert alert-info">No reports available for this project yet.</div>';
document.getElementById('literatureReportDetail').innerHTML =
'<div class="alert alert-info">No literature analysis report available.</div>';
document.getElementById('paperReportDetail').innerHTML =
'<div class="alert alert-info">No paper analysis report available.</div>';
} else {
// 4. 保存当前报告数据
currentReportData = {
projectId,
projectName,
projectReport: projectData,
literatureReport: literatureData
paperReport: paperData
};
// 5. 更新报告显示
@@ -966,9 +966,9 @@
document.getElementById('projectReportDetail').innerHTML = projectData ?
formatReportContent(projectData) :
'<div class="alert alert-info">No project report available.</div>';
document.getElementById('literatureReportDetail').innerHTML = literatureData ?
formatReportContent(literatureData) :
'<div class="alert alert-info">No literature analysis report available.</div>';
document.getElementById('paperReportDetail').innerHTML = paperData ?
formatReportContent(paperData) :
'<div class="alert alert-info">No paper analysis report available.</div>';
}
// 6. 显示报告详情页面
@@ -990,7 +990,7 @@
// Build complete report object
const combinedReport = {
project_report: currentReportData.projectReport,
literature_analysis: currentReportData.literatureReport || "No literature analysis report found"
paper_analysis: currentReportData.paperReport || "No paper analysis report found"
};
const reportText = JSON.stringify(combinedReport, null, 2);
@@ -1093,7 +1093,7 @@
project_name: project.project_name,
description: project.description,
project_reports: project.project_reports,
literature_analysis: project.literature_analysis
paper_analysis: project.paper_analysis
}));
const reportText = JSON.stringify(reports, null, 2);
@@ -1128,7 +1128,7 @@
project_name: project.project_name,
description: project.description,
project_reports: project.project_reports,
literature_analysis: project.literature_analysis
paper_analysis: project.paper_analysis
}));
const summaryText = JSON.stringify(summary, null, 2);
@@ -1148,7 +1148,7 @@
}
}
// Switch between project report and literature analysis
// Switch between project report and paper analysis
function switchReportSection(section) {
// Remove active class from all sections
document.querySelectorAll('.report-section').forEach(section => {
@@ -1173,7 +1173,7 @@
}
// 更新标题
const title = sectionId === 'projectReport' ? 'Project Report' : 'Literature Analysis';
const title = sectionId === 'projectReport' ? 'Project Report' : 'paper Analysis';
document.getElementById('reportDetailTitle').textContent = `${title} - ${currentReportData.projectName}`;
// 更新侧边栏选中状态