feat: enhance HTML report with modals for summary JSON and log content, and improve download functionality

This commit is contained in:
lilong.129
2025-06-25 15:30:32 +08:00
parent bfa6a0e4cd
commit 9b9875dc2c
3 changed files with 150 additions and 20 deletions
+1 -1
View File
@@ -1 +1 @@
v5.0.0-beta-2506251440 v5.0.0-beta-2506251530
+146 -19
View File
@@ -2337,25 +2337,25 @@ const htmlTemplate = `<!DOCTYPE html>
<div class="subtitle">Start Time: {{.Time.StartAt.Format "2006-01-02 15:04:05"}}</div> <div class="subtitle">Start Time: {{.Time.StartAt.Format "2006-01-02 15:04:05"}}</div>
</div> </div>
<div class="header-right"> <div class="header-right">
<div class="download-section"> <div class="download-section">
<div class="download-title">📥 Download & View</div> <div class="download-title">📥 View & Download</div>
<div class="download-buttons"> <div class="download-buttons">
<button class="download-btn" onclick="downloadSummary()"> {{if getCaseContentBase64}}
<span>📄</span> <button class="download-btn" onclick="showCaseJson()">
<span>summary.json</span> <span>📋</span>
</button> <span>case.json</span>
<button class="download-btn" onclick="downloadLog()"> </button>
<span>📋</span> {{end}}
<span>hrp.log</span> <button class="download-btn" onclick="showSummaryJson()">
</button> <span>📄</span>
{{if getCaseContentBase64}} <span>summary.json</span>
<button class="download-btn" onclick="showCaseJson()"> </button>
<span>📋</span> <button class="download-btn" onclick="showLogContent()">
<span>case.json</span> <span>📋</span>
</button> <span>hrp.log</span>
{{end}} </button>
</div>
</div> </div>
</div>
</div> </div>
</div> </div>
</div> </div>
@@ -2891,6 +2891,46 @@ const htmlTemplate = `<!DOCTYPE html>
</div> </div>
</div> </div>
<!-- Summary JSON Modal -->
<div id="summaryModal" class="json-modal">
<div class="json-modal-content">
<div class="json-modal-header">
<h2 class="json-modal-title">📄 Summary JSON</h2>
<button class="json-close" onclick="closeSummaryModal()">&times;</button>
</div>
<div class="json-modal-body">
<div class="json-toolbar">
<div>
<button onclick="copySummaryContent()">📋 Copy to Clipboard</button>
<button onclick="downloadSummary()">📥 Download summary.json</button>
</div>
<span class="copy-status" id="summaryStatus">✅ Copied!</span>
</div>
<pre class="json-content" id="summaryContent"></pre>
</div>
</div>
</div>
<!-- Log Content Modal -->
<div id="logModal" class="json-modal">
<div class="json-modal-content">
<div class="json-modal-header">
<h2 class="json-modal-title">📋 Log Content</h2>
<button class="json-close" onclick="closeLogModal()">&times;</button>
</div>
<div class="json-modal-body">
<div class="json-toolbar">
<div>
<button onclick="copyLogContent()">📋 Copy to Clipboard</button>
<button onclick="downloadLog()">📥 Download hrp.log</button>
</div>
<span class="copy-status" id="logStatus">✅ Copied!</span>
</div>
<pre class="json-content" id="logContentDisplay"></pre>
</div>
</div>
</div>
<script> <script>
// Embedded file contents for download (Base64 encoded) // Embedded file contents for download (Base64 encoded)
const summaryContentBase64 = "{{getSummaryContentBase64}}"; const summaryContentBase64 = "{{getSummaryContentBase64}}";
@@ -3000,6 +3040,85 @@ const htmlTemplate = `<!DOCTYPE html>
downloadFile(caseContent, 'case.json', 'application/json'); downloadFile(caseContent, 'case.json', 'application/json');
} }
// Summary JSON Modal functions
function showSummaryJson() {
if (!summaryContent) {
alert('Summary JSON content not available');
return;
}
try {
// Parse and format JSON for beautiful display
const jsonObj = JSON.parse(summaryContent);
const formattedJson = JSON.stringify(jsonObj, null, 2);
document.getElementById('summaryContent').textContent = formattedJson;
document.getElementById('summaryModal').style.display = 'block';
} catch (e) {
console.error('Failed to parse JSON:', e);
// Fallback to raw content if parsing fails
document.getElementById('summaryContent').textContent = summaryContent;
document.getElementById('summaryModal').style.display = 'block';
}
}
function closeSummaryModal() {
document.getElementById('summaryModal').style.display = 'none';
}
function copySummaryContent() {
const content = document.getElementById('summaryContent').textContent;
if (!content) {
alert('No content to copy');
return;
}
navigator.clipboard.writeText(content).then(function() {
const copyStatus = document.getElementById('summaryStatus');
copyStatus.classList.add('show');
setTimeout(function() {
copyStatus.classList.remove('show');
}, 2000);
}).catch(function(err) {
console.error('Failed to copy to clipboard:', err);
alert('Failed to copy to clipboard. Please select and copy manually.');
});
}
// Log Content Modal functions
function showLogContent() {
if (!logContent) {
alert('Log content not available');
return;
}
document.getElementById('logContentDisplay').textContent = logContent;
document.getElementById('logModal').style.display = 'block';
}
function closeLogModal() {
document.getElementById('logModal').style.display = 'none';
}
function copyLogContent() {
const content = document.getElementById('logContentDisplay').textContent;
if (!content) {
alert('No content to copy');
return;
}
navigator.clipboard.writeText(content).then(function() {
const copyStatus = document.getElementById('logStatus');
copyStatus.classList.add('show');
setTimeout(function() {
copyStatus.classList.remove('show');
}, 2000);
}).catch(function(err) {
console.error('Failed to copy to clipboard:', err);
alert('Failed to copy to clipboard. Please select and copy manually.');
});
}
function toggleStep(stepIndex) { function toggleStep(stepIndex) {
const content = document.getElementById('step-' + stepIndex); const content = document.getElementById('step-' + stepIndex);
const icon = document.getElementById('toggle-' + stepIndex); const icon = document.getElementById('toggle-' + stepIndex);
@@ -3068,10 +3187,12 @@ const htmlTemplate = `<!DOCTYPE html>
document.getElementById('imageModal').style.display = 'none'; document.getElementById('imageModal').style.display = 'none';
} }
// Close modal when clicking outside the image or JSON modal // Close modal when clicking outside the image or JSON modals
window.onclick = function(event) { window.onclick = function(event) {
const imageModal = document.getElementById('imageModal'); const imageModal = document.getElementById('imageModal');
const jsonModal = document.getElementById('jsonModal'); const jsonModal = document.getElementById('jsonModal');
const summaryModal = document.getElementById('summaryModal');
const logModal = document.getElementById('logModal');
if (event.target == imageModal) { if (event.target == imageModal) {
imageModal.style.display = 'none'; imageModal.style.display = 'none';
@@ -3079,6 +3200,12 @@ const htmlTemplate = `<!DOCTYPE html>
if (event.target == jsonModal) { if (event.target == jsonModal) {
jsonModal.style.display = 'none'; jsonModal.style.display = 'none';
} }
if (event.target == summaryModal) {
summaryModal.style.display = 'none';
}
if (event.target == logModal) {
logModal.style.display = 'none';
}
} }
// Auto-expand all steps on load to show actions // Auto-expand all steps on load to show actions
+3
View File
@@ -424,6 +424,9 @@ func resizeImage(src image.Image, width, height int) image.Image {
// CompressImageFile compresses an image file and returns the compressed data // CompressImageFile compresses an image file and returns the compressed data
func CompressImageFile(imagePath string, enableResize bool, maxWidth int) ([]byte, error) { func CompressImageFile(imagePath string, enableResize bool, maxWidth int) ([]byte, error) {
log.Debug().Str("imagePath", imagePath).Bool("enableResize", enableResize).
Int("maxWidth", maxWidth).Msg("compress image file")
// Read the original image file // Read the original image file
file, err := os.Open(imagePath) file, err := os.Open(imagePath)
if err != nil { if err != nil {