优化提示词

This commit is contained in:
朱潮 2025-11-30 20:11:22 +08:00
parent cfe8d0955b
commit 2a2ef429b4
5 changed files with 1380 additions and 67 deletions

View File

@ -5,7 +5,7 @@ meta {
}
post {
url: http://120.26.23.172:5678/webhook-test/survey_report
url: https://n8n.aitravelmaster.com/webhook-test/survey_report
body: json
auth: inherit
}

View File

@ -286,15 +286,34 @@ class ReportGenerator:
print(f"成功提取JSON格式内容长度: {len(json_content)} 字符")
try:
return json.loads(json_content)
parsed_data = json.loads(json_content)
# 如果返回的是数组,提取第一个元素
if isinstance(parsed_data, list):
print(f"检测到数组响应,长度: {len(parsed_data)}提取下标为0的数据")
if len(parsed_data) > 0:
return parsed_data[0]
else:
print(f"数组为空,返回空字典")
return {}
# 如果已经是字典格式,直接返回
elif isinstance(parsed_data, dict):
return parsed_data
# 其他情况,将数据包装成字典
else:
print(f"响应不是字典或数组格式,将数据包装为字典")
return {"data": parsed_data}
except json.JSONDecodeError as e:
print(f"JSON解析失败: {e}")
# 如果都不是,返回原始内容
return json_content
# 如果解析失败,返回原始内容包装的字典
return {"raw_content": json_content}
except Exception as e:
print(f"解析JSON响应失败: {e}")
return json_content
return {"error": str(e), "raw_content": json_content}
def save_report_to_db(self, session_id, report_data, analysis_data):
"""保存报告到数据库"""

1170
main.py

File diff suppressed because it is too large Load Diff

View File

@ -394,16 +394,24 @@
font-size: 12px;
}
.delete-btn {
padding: 6px 12px;
background: linear-gradient(135deg, #e74c3c, #c0392b);
color: white;
border: none;
border-radius: 4px;
font-size: 12px;
cursor: pointer;
transition: all 0.3s ease;
margin-left: 5px;
.delete-btn, .action-cell .view-btn {
padding: 6px 8px;
font-size: 11px;
margin: 2px;
}
.action-cell {
min-width: auto;
flex-direction: column;
align-items: stretch;
}
.action-cell .view-btn:nth-child(1) {
background: linear-gradient(135deg, #ff7e5f, #feb47b);
}
.action-cell .view-btn:nth-child(2) {
background: linear-gradient(135deg, #4CAF50, #66BB6A);
}
.delete-btn:hover {
@ -583,9 +591,11 @@
.action-cell {
display: flex;
flex-wrap: wrap;
gap: 5px;
justify-content: center;
align-items: center;
min-width: 200px;
}
</style>
</head>
@ -869,6 +879,7 @@
<td class="school-cell">${report.school}</td>
<td class="action-cell">
<a href="/report.html?id=${report.id}" class="view-btn">查看报告</a>
<a href="/quiz-results/${report.session_id}" class="view-btn" style="background: linear-gradient(135deg, #4CAF50, #66BB6A); margin-left: 5px;">查看答题结果</a>
<button class="delete-btn" onclick="reportManager.deleteReport('${report.id}', '${report.name}')"
style="${deleteButtonStyle}" id="delete-${report.id}">删除</button>
</td>

View File

@ -4,6 +4,7 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>学科能力测评问卷</title>
<script src="https://cdn.jsdelivr.net/npm/qrcode@1.5.1/build/qrcode.min.js"></script>
<style>
* {
margin: 0;
@ -1562,7 +1563,7 @@
<span class="button-arrow"></span>
</button>
<button class="generate-link-button" id="generateLinkBtn">
<span class="button-text">🔗 生成测评链接</span>
<span class="button-text">📱 生成测评二维码</span>
</button>
</div>
</div>
@ -1746,6 +1747,173 @@
});
}
// 显示二维码对话框
showQRCodeDialog(options) {
const { title = '二维码生成', assessmentLink, studentName, studentSchool, studentGrade } = options;
// 创建二维码对话框HTML
const qrDialogHTML = `
<div id="qrCodeDialogOverlay" style="position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0, 0, 0, 0.5); display: flex; align-items: center; justify-content: center; z-index: 10000; opacity: 0; transition: opacity 0.3s ease; padding: 20px; box-sizing: border-box;">
<div style="background: white; border-radius: 12px; width: 90%; max-width: 500px; max-height: 95vh; overflow: hidden; box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3); transform: scale(0.8); transition: transform 0.3s ease; display: flex; flex-direction: column;">
<div style="padding: 20px; border-bottom: 1px solid #e0e0e0; display: flex; justify-content: space-between; align-items: center; background: linear-gradient(135deg, #ff7e5f 0%, #feb47b 50%, #ff7e5f 100%); color: white; flex-shrink: 0;">
<h3 style="font-size: 18px; font-weight: 600; margin: 0;">${title}</h3>
<button id="closeQrDialog" style="background: none; border: none; color: white; font-size: 24px; cursor: pointer; width: 30px; height: 30px; border-radius: 50%; display: flex; align-items: center; justify-content: center; transition: background 0.3s;">×</button>
</div>
<div style="padding: 20px; flex-grow: 1; overflow-y: auto;">
<div style="text-align: center; padding: 20px;">
<div style="font-size: 48px; margin-bottom: 20px;">🎉</div>
<div style="color: #4CAF50; font-size: 18px; font-weight: bold; margin-bottom: 15px;">
测评二维码已生成!
</div>
<div style="color: #666; margin-bottom: 20px;">
学生信息:${studentName} | ${studentSchool} | ${studentGrade}
</div>
<div id="qrcode" style="display: flex; justify-content: center; margin-bottom: 20px;"></div>
<div style="background: #f5f5f5; padding: 15px; border-radius: 8px; word-break: break-all; font-size: 12px; color: #333; text-align: left; margin-bottom: 20px;">
<strong>答题链接:</strong><br>
${assessmentLink}
</div>
<div style="display: flex; gap: 10px; justify-content: center; flex-wrap: wrap;">
<button id="downloadQRCode" style="background: linear-gradient(135deg, #4CAF50, #66BB6A); color: white; border: none; padding: 10px 20px; border-radius: 6px; font-size: 14px; font-weight: 500; cursor: pointer; transition: all 0.3s;">📱 下载二维码</button>
<button id="copyLink" style="background: linear-gradient(135deg, #2196F3, #42A5F5); color: white; border: none; padding: 10px 20px; border-radius: 6px; font-size: 14px; font-weight: 500; cursor: pointer; transition: all 0.3s;">🔗 复制链接</button>
</div>
<div style="color: #999; font-size: 12px; margin-top: 15px;">
请学生扫描二维码或点击链接开始答题
</div>
</div>
</div>
</div>
</div>
`;
// 移除之前的对话框(如果存在)
const existingDialog = document.getElementById('qrCodeDialogOverlay');
if (existingDialog) {
existingDialog.remove();
}
// 添加新对话框到页面
document.body.insertAdjacentHTML('beforeend', qrDialogHTML);
// 显示对话框
setTimeout(() => {
const overlay = document.getElementById('qrCodeDialogOverlay');
overlay.style.opacity = '1';
overlay.querySelector('div').style.transform = 'scale(1)';
}, 10);
// 生成二维码
const qrCodeContainer = document.getElementById('qrcode');
qrCodeContainer.innerHTML = ''; // 清空容器
QRCode.toCanvas(assessmentLink, {
width: 200,
margin: 2,
color: {
dark: '#000000',
light: '#FFFFFF'
}
}, function(error, canvas) {
if (error) {
console.error('生成二维码失败:', error);
qrCodeContainer.innerHTML = '<div style="color: red;">二维码生成失败</div>';
} else {
qrCodeContainer.appendChild(canvas);
}
});
// 绑定事件
document.getElementById('closeQrDialog').onclick = () => {
const overlay = document.getElementById('qrCodeDialogOverlay');
overlay.style.opacity = '0';
overlay.querySelector('div').style.transform = 'scale(0.8)';
setTimeout(() => {
overlay.remove();
}, 300);
};
document.getElementById('downloadQRCode').onclick = () => {
const canvas = document.querySelector('#qrcode canvas');
if (canvas) {
const link = document.createElement('a');
link.download = `测评二维码_${studentName}_${new Date().toISOString().slice(0, 10)}.png`;
link.href = canvas.toDataURL();
link.click();
} else {
this.showNotification('二维码还未生成完成,请稍后再试', 'error');
}
};
document.getElementById('copyLink').onclick = async () => {
try {
// 先尝试使用现代 Clipboard API
if (navigator.clipboard && window.isSecureContext) {
await navigator.clipboard.writeText(assessmentLink);
this.showNotification('链接已复制到剪贴板!');
} else {
// 降级到传统方法
const textArea = document.createElement('textarea');
textArea.value = assessmentLink;
textArea.style.position = 'fixed';
textArea.style.left = '-999999px';
textArea.style.top = '-999999px';
document.body.appendChild(textArea);
textArea.focus();
textArea.select();
try {
const successful = document.execCommand('copy');
document.body.removeChild(textArea);
if (successful) {
this.showNotification('链接已复制到剪贴板!');
} else {
throw new Error('复制命令执行失败');
}
} catch (execError) {
document.body.removeChild(textArea);
throw execError;
}
}
} catch (err) {
console.error('复制失败:', err);
// 提供手动复制方案
const tempInput = document.createElement('input');
tempInput.value = assessmentLink;
tempInput.style.position = 'fixed';
tempInput.style.left = '0';
tempInput.style.top = '0';
tempInput.style.width = '200px';
tempInput.style.fontSize = '12px';
tempInput.style.padding = '5px';
tempInput.style.border = '1px solid #ccc';
tempInput.style.borderRadius = '3px';
tempInput.style.zIndex = '10001';
tempInput.readOnly = true;
document.body.appendChild(tempInput);
tempInput.focus();
tempInput.select();
// 添加提示
this.showNotification('请手动复制选中的链接Ctrl+C 或 Command+C', 'error');
// 3秒后移除输入框
setTimeout(() => {
if (document.body.contains(tempInput)) {
document.body.removeChild(tempInput);
}
}, 3000);
}
};
// 点击遮罩层关闭
document.getElementById('qrCodeDialogOverlay').onclick = (e) => {
if (e.target.id === 'qrCodeDialogOverlay') {
document.getElementById('closeQrDialog').click();
}
};
}
async init() {
try {
await this.loadQuestions();
@ -2233,13 +2401,13 @@
generateLinkBtn.querySelector('.button-text').textContent = '请先配置测评';
} else {
startBtn.querySelector('.button-text').textContent = '题目不足,无法开始';
generateLinkBtn.querySelector('.button-text').textContent = '题目不足,无法生成链接';
generateLinkBtn.querySelector('.button-text').textContent = '题目不足,无法生成二维码';
}
startBtn.disabled = true;
generateLinkBtn.disabled = true;
} else {
startBtn.querySelector('.button-text').textContent = '开始答题';
generateLinkBtn.querySelector('.button-text').textContent = '🔗 生成测评链接';
generateLinkBtn.querySelector('.button-text').textContent = '📱 生成测评二维码';
startBtn.disabled = false;
generateLinkBtn.disabled = false;
}
@ -2327,7 +2495,7 @@
if (!studentName || !studentSchool || !studentGrade || !studentPhone) {
this.showErrorDialog('学员信息不完整',
`请填写完整的学员信息后才能生成测评链接<br><br>
`请填写完整的学员信息后才能生成测评二维码<br><br>
${!studentName ? '✗ 姓名<br>' : '✓ 姓名<br>'}
${!studentSchool ? '✗ 学校<br>' : '✓ 学校<br>'}
${!studentGrade ? '✗ 年级<br>' : '✓ 年级<br>'}
@ -2366,8 +2534,7 @@
// 禁用按钮并显示加载状态
const generateBtn = document.getElementById('generateLinkBtn');
const originalText = generateBtn.querySelector('.button-text').textContent;
generateBtn.querySelector('.button-text').textContent = '正在生成链接...';
generateBtn.querySelector('.button-text').textContent = '正在生成二维码...';
generateBtn.disabled = true;
// iOS兼容性使用setTimeout确保请求是用户直接触发的
@ -2413,29 +2580,13 @@
// 生成答题页面链接
const assessmentLink = `${window.location.origin}/quiz/${result.sessionId}`;
// 复制链接到剪贴板
await navigator.clipboard.writeText(assessmentLink);
// 显示成功对话框
this.showDialog({
title: '测评链接生成成功!',
content: `<div style="text-align: center; padding: 20px;">
<div style="font-size: 48px; margin-bottom: 20px;">🎉</div>
<div style="color: #4CAF50; font-size: 18px; font-weight: bold; margin-bottom: 15px;">
测评链接已生成并复制到剪贴板!
</div>
<div style="color: #666; margin-bottom: 20px;">
学生信息:${studentName} | ${studentSchool} | ${studentGrade}
</div>
<div style="background: #f5f5f5; padding: 15px; border-radius: 8px; word-break: break-all; font-size: 14px; color: #333; text-align: left;">
<strong>答题链接:</strong><br>
${assessmentLink}
</div>
<div style="color: #999; font-size: 12px; margin-top: 15px;">
请将此链接发送给学生,学生点击后即可开始答题
</div>
</div>`,
onConfirm: null,
showCancel: false
// 创建二维码对话框
this.showQRCodeDialog({
title: '测评二维码生成成功!',
assessmentLink: assessmentLink,
studentName: studentName,
studentSchool: studentSchool,
studentGrade: studentGrade
});
// 可选:在控制台输出链接,方便调试
@ -2445,7 +2596,7 @@
}
} catch (error) {
console.error('生成测评链接失败:', error);
console.error('生成测评二维码失败:', error);
const isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent);
const errorMessage = error.message.includes('not allowed') && isIOS
? `iOS设备权限限制请确保<br><br>
@ -2454,16 +2605,16 @@
• 检查是否启用了"限制网页跟踪"<br>
• 如仍失败请尝试使用其他浏览器如Chrome<br><br>
技术细节:${error.message}`
: `创建测评链接时发生错误:<br><br>
: `创建测评二维码时发生错误:<br><br>
错误信息:${error.message}<br><br>
请检查网络连接或联系技术支持。`;
this.showErrorDialog('生成测评链接失败', errorMessage);
this.showErrorDialog('生成测评二维码失败', errorMessage);
} finally {
// 恢复按钮状态
const generateBtn = document.getElementById('generateLinkBtn');
if (generateBtn) {
generateBtn.querySelector('.button-text').textContent = '🔗 生成测评链接';
generateBtn.querySelector('.button-text').textContent = '📱 生成测评二维码';
generateBtn.disabled = false;
}
}