Files
CloudFlare-AI-Insight-Daily/src/htmlGenerators.js
justlovemaki 60668026a0 opensource
2025-06-11 17:05:32 +08:00

500 lines
33 KiB
JavaScript

// src/htmlGenerators.js
import { escapeHtml, formatDateToChinese, convertEnglishQuotesToChinese} from './helpers.js';
import { dataSources } from './dataFetchers.js'; // Import dataSources
function generateHtmlListForContentPage(items, dateStr) {
let listHtml = '';
if (!Array.isArray(items) || items.length === 0) {
listHtml += `<p>此日期无可用数据。抓取/筛选过程可能没有为此日期生成任何结果。</p>`;
return listHtml;
}
listHtml += '<ul class="item-list">';
items.forEach((item, index) => {
let displayContent = '';
let itemId = item.id;
// Use the generateHtml method from the corresponding data source
const dataSourceConfig = dataSources[item.type];
// console.log("item.type:", item.type);
// console.log("dataSourceConfig:", dataSourceConfig);
if (dataSourceConfig && dataSourceConfig.sources && dataSourceConfig.sources.length > 0 && dataSourceConfig.sources[0].generateHtml) {
displayContent = dataSourceConfig.sources[0].generateHtml(item);
} else {
// Fallback for unknown types or if generateHtml is not defined
displayContent = `<strong>未知项目类型: ${escapeHtml(item.type)}</strong><br>${escapeHtml(item.title || item.description || JSON.stringify(item))}`;
}
listHtml += `<li class="item-card">
<label>
<input type="checkbox" name="selectedItems" value="${item.type}:${itemId}" class="item-checkbox">
<div class="item-content">${displayContent}</div>
</label>
</li>`;
});
listHtml += '</ul>';
return listHtml;
}
export function generateContentSelectionPageHtml(env, dateStr, allData, dataCategories) {
// Ensure allData is an object and dataCategories is an array
const data = allData || {};
const categories = Array.isArray(dataCategories) ? dataCategories : [];
// Generate tab buttons and content dynamically
const tabButtonsHtml = categories.map((category, index) => `
<div class="tab-buttons-wrapper">
<button type="button" class="tab-button ${index === 0 ? 'active' : ''}" onclick="openTab(event, '${category.id}-tab')" ondblclick="confirmFetchCategoryData(this,'${category.id}')">${escapeHtml(category.name)}</button>
</div>
`).join('');
const tabContentsHtml = categories.map((category, index) => `
<div id="${category.id}-tab" class="tab-content ${index === 0 ? 'active' : ''}">
${generateHtmlListForContentPage(data[category.id], dateStr)}
</div>
`).join('');
return `
<!DOCTYPE html>
<html lang="zh-Hans">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>${formatDateToChinese(escapeHtml(dateStr))} ${env.FOLO_FILTER_DAYS}天内的数据</title>
<style>
:root { --primary-color: #007bff; --light-gray: #f8f9fa; --medium-gray: #e9ecef; --dark-gray: #343a40; --line-height-normal: 1.4; --font-size-small: 0.9rem;}
* { box-sizing: border-box; margin: 0; padding: 0; }
body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; line-height: 1.6; background-color: var(--light-gray); color: var(--dark-gray); padding: 1rem; }
.container { max-width: 1200px; margin: 0 auto; background-color: #fff; padding: 1rem; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); }
.header-bar { display: flex; justify-content: space-between; align-items: center; margin-bottom: 1.5rem; flex-wrap: wrap; gap: 1rem; }
h1 { font-size: 1.8rem; color: var(--dark-gray); margin-bottom: 0.5rem; }
.submit-button { background-color: var(--primary-color); color: white; border: none; padding: 0.6rem 1.2rem; font-size: 0.9rem; border-radius: 5px; cursor: pointer; transition: background-color 0.2s; white-space: nowrap; }
.submit-button:hover { background-color: #0056b3; }
.tab-navigation { display: flex; flex-wrap: wrap; margin-bottom: 1rem; border-bottom: 1px solid var(--medium-gray); }
.tab-buttons-wrapper { display: flex; align-items: center; margin-right: 1rem; margin-bottom: 0.5rem; }
.tab-button { background-color: transparent; border: none; border-bottom: 3px solid transparent; padding: 0.8rem 1rem; cursor: pointer; font-size: 1rem; color: #555; transition: color 0.2s, border-color 0.2s; }
.tab-button.active { color: var(--primary-color); border-bottom-color: var(--primary-color); font-weight: 600; }
.tab-button:hover { color: var(--primary-color); }
.tab-content { display: none; animation: fadeIn 0.5s; }
.tab-content.active { display: block; }
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
.item-list { list-style-type: none; counter-reset: item-counter; padding-left: 0; }
.item-card { margin-bottom: 1rem; padding: 1rem; padding-left: 3em; border: 1px solid var(--medium-gray); border-radius: 6px; background-color: #fff; position: relative; counter-increment: item-counter; }
.item-card::before { content: counter(item-counter) "."; position: absolute; left: 0.8em; top: 1rem; font-weight: 600; color: var(--dark-gray); min-width: 1.5em; text-align: right; }
.item-card label { display: flex; align-items: flex-start; cursor: pointer; }
.item-checkbox { margin-right: 0.8rem; margin-top: 0.2rem; transform: scale(1.2); flex-shrink: 0; }
.item-content { flex-grow: 1; min-width: 0; }
.item-content strong { font-size: 1.1rem; }
.item-content small { color: #6c757d; display: block; margin: 0.2rem 0; }
.content-html { border: 1px dashed #ccc; padding: 0.5rem; margin-top: 0.5rem; background: #fdfdfd; font-size: var(--font-size-small); line-height: var(--line-height-normal); max-width: 100%; overflow-wrap: break-word; word-break: break-word; overflow-y: hidden; transition: max-height 0.35s ease-in-out; position: relative; }
.content-html.is-collapsed { max-height: calc(var(--font-size-small) * var(--line-height-normal) * 6 + 1rem); }
.content-html.is-expanded { max-height: 3000px; overflow-y: auto; }
.read-more-btn { display: block; margin-top: 0.5rem; padding: 0.3rem 0.6rem; font-size: 0.85rem; color: var(--primary-color); background-color: transparent; border: 1px solid var(--primary-color); border-radius: 4px; cursor: pointer; text-align: center; width: fit-content; }
.read-more-btn:hover { background-color: #eef; }
.item-content a { color: var(--primary-color); text-decoration: none; }
.item-content a:hover { text-decoration: underline; }
.error { color: #dc3545; font-weight: bold; background-color: #f8d7da; padding: 0.5rem; border-radius: 4px; border: 1px solid #f5c6cb;}
hr { border: 0; border-top: 1px solid var(--medium-gray); margin: 0.5rem 0; }
@media (max-width: 768px) {
body { padding: 0.5rem; } .container { padding: 0.8rem; } h1 { font-size: 1.5rem; }
.header-bar { flex-direction: column; align-items: flex-start; }
.submit-button { margin-top: 0.5rem; width: 100%; }
.tab-button { padding: 0.7rem 0.5rem; font-size: 0.9rem; flex-grow: 1; text-align: center; }
.item-card { padding-left: 2.5em; } .item-card::before { left: 0.5em; top: 0.8rem; }
}
</style>
</head>
<body>
<div class="container">
<form action="/genAIContent" method="POST">
<input type="hidden" name="date" value="${escapeHtml(dateStr)}">
<div class="header-bar">
<button type="button" class="submit-button" onclick="confirmFetchAndWriteData(this)">抓取并写入今日数据</button>
<h1>${formatDateToChinese(escapeHtml(dateStr))} ${env.FOLO_FILTER_DAYS}天内的数据</h1>
<button type="submit" class="submit-button" onclick="return confirmGenerateAIContent(event)">从选中内容生成 AI 日报</button>
</div>
<div class="cookie-setting-area" style="margin-bottom: 1rem; padding: 0.8rem; border: 1px solid var(--medium-gray); border-radius: 6px; background-color: #fefefe;">
<label for="foloCookie" style="font-weight: bold; margin-right: 0.5rem;">Folo Cookie:</label>
<input type="text" id="foloCookie" placeholder="在此输入 Folo Cookie" style="flex-grow: 1; padding: 0.4rem; border: 1px solid #ccc; border-radius: 4px; width: 300px; max-width: 70%;">
<button type="button" class="submit-button" onclick="saveFoloCookie(this)" style="margin-left: 0.5rem; padding: 0.4rem 0.8rem; font-size: 0.85rem;">保存 Cookie</button>
<p style="font-size: 0.8rem; color: #666; margin-top: 0.5rem;">此 Cookie 将保存在您的浏览器本地存储中,以便下次使用。</p>
</div>
<div class="tab-navigation">
${tabButtonsHtml}
</div>
${tabContentsHtml}
</form>
</div>
<script>
function openTab(evt, tabName) {
var i, tabcontent, tablinks;
tabcontent = document.getElementsByClassName("tab-content");
for (i = 0; i < tabcontent.length; i++) { tabcontent[i].style.display = "none"; tabcontent[i].classList.remove("active"); }
tablinks = document.getElementsByClassName("tab-button");
for (i = 0; i < tablinks.length; i++) { tablinks[i].classList.remove("active"); }
document.getElementById(tabName).style.display = "block"; document.getElementById(tabName).classList.add("active");
if (evt && evt.currentTarget) { evt.currentTarget.classList.add("active"); }
}
document.addEventListener('DOMContentLoaded', function() {
if (document.querySelector('.tab-button') && !document.querySelector('.tab-button.active')) { document.querySelector('.tab-button').click(); }
else if (document.querySelector('.tab-content.active') === null && document.querySelector('.tab-content')) {
const firstTabButton = document.querySelector('.tab-button'); const firstTabContent = document.querySelector('.tab-content');
if (firstTabButton) firstTabButton.classList.add('active');
if (firstTabContent) { firstTabContent.style.display = 'block'; firstTabContent.classList.add('active');}
}
document.querySelectorAll('.content-html').forEach(contentDiv => {
contentDiv.classList.add('is-collapsed');
requestAnimationFrame(() => {
const readMoreBtn = document.createElement('button'); readMoreBtn.type = 'button';
readMoreBtn.textContent = '展开'; readMoreBtn.className = 'read-more-btn';
contentDiv.insertAdjacentElement('afterend', readMoreBtn);
readMoreBtn.addEventListener('click', function() {
contentDiv.classList.toggle('is-expanded'); contentDiv.classList.toggle('is-collapsed', !contentDiv.classList.contains('is-expanded'));
this.textContent = contentDiv.classList.contains('is-expanded') ? '折叠' : '展开';
});
});
});
});
async function saveFoloCookie(button) {
const cookieInput = document.getElementById('foloCookie');
const cookieValue = cookieInput.value;
if (!cookieValue.trim()) {
alert('Folo Cookie 不能为空。');
return;
}
const originalButtonText = button.textContent;
button.textContent = '保存中...';
button.disabled = true;
try {
localStorage.setItem('${env.FOLO_COOKIE_KV_KEY}', cookieValue); // 直接保存到 localStorage
alert('Folo Cookie 已成功保存在本地存储!');
} catch (error) {
console.error('Error saving Folo Cookie to localStorage:', error);
alert(\`保存 Folo Cookie 到本地存储时发生错误: \${error.message}\`);
} finally {
button.textContent = originalButtonText;
button.disabled = false;
}
}
document.addEventListener('DOMContentLoaded', function() {
const savedCookie = localStorage.getItem('${env.FOLO_COOKIE_KV_KEY}');
if (savedCookie) {
document.getElementById('foloCookie').value = savedCookie;
}
});
function confirmFetchAndWriteData(button) {
if (confirm('确定要抓取并写入今日数据吗?此操作将更新今日数据。')) {
fetchAndWriteData(button);
}
}
async function fetchAndWriteData(button, category = null) {
const originalText = button.textContent;
button.textContent = '正在抓取和写入...';
button.disabled = true;
const foloCookie = localStorage.getItem('${env.FOLO_COOKIE_KV_KEY}'); // 从 localStorage 获取 foloCookie
try {
const response = await fetch('/writeData', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ category: category, foloCookie: foloCookie }), // 将 foloCookie 添加到请求体
});
if (response.ok) {
const result = await response.text();
alert('数据抓取和写入成功!' + result);
window.location.reload();
} else {
const errorText = await response.text();
alert('数据抓取和写入失败: ' + errorText);
}
} catch (error) {
console.error('Error fetching and writing data:', error);
alert('请求失败,请检查网络或服务器。');
} finally {
button.textContent = originalText;
button.disabled = false;
}
}
function confirmFetchCategoryData(button, category) {
if (confirm(\`确定要抓取并写入 \${category} 分类的数据吗?此操作将更新 \${category} 数据。\`)) {
fetchAndWriteData(button, category);
}
}
function confirmGenerateAIContent(event) {
const selectedCheckboxes = document.querySelectorAll('input[name="selectedItems"]:checked');
if (selectedCheckboxes.length === 0) {
alert('请至少选择一个内容条目来生成 AI 日报。');
event.preventDefault(); // Prevent form submission
return false;
}
if (confirm('确定要从选中内容生成 AI 日报吗?此操作将调用 AI 模型生成内容。')) {
return true; // Allow form submission
} else {
event.preventDefault(); // Prevent form submission
return false;
}
}
</script>
</body>
</html>
`;
}
function generatePromptSectionHtmlForGenAI(systemPrompt, userPrompt, promptTitle, promptIdSuffix) {
if (!systemPrompt && !userPrompt) return '';
let fullPromptTextForCopy = "";
if (systemPrompt) fullPromptTextForCopy += `系统指令:\n${systemPrompt}\n\n`;
if (userPrompt) fullPromptTextForCopy += `用户输入:\n${userPrompt}`;
fullPromptTextForCopy = fullPromptTextForCopy.trim();
return `
<div style="margin-top: 1rem; border: 1px solid #ddd; padding: 0.8rem; border-radius: 4px; background-color: #f9f9f9;">
<h3 style="font-size: 1.1rem; margin-bottom: 0.5rem; color: #333;">${escapeHtml(promptTitle)}</h3>
<button type="button" class="button-link toggle-prompt-btn" onclick="togglePromptVisibility('promptDetails_${promptIdSuffix}', this)">显示提示详情</button>
<button type="button" class="button-link copy-prompt-btn" onclick="copyToClipboard(this.dataset.fullPrompt, this)" data-full-prompt="${escapeHtml(fullPromptTextForCopy)}">复制完整提示</button>
<div id="promptDetails_${promptIdSuffix}" class="content-box" style="display: none; margin-top: 0.5rem; background-color: #e9ecef; border-color: #ced4da; max-height: 400px; overflow-y: auto; text-align: left;">
${systemPrompt ? `<strong>系统指令:</strong><pre style="white-space: pre-wrap; word-wrap: break-word; font-size: 0.85rem; margin-top:0.2em; margin-bottom:0.8em; padding: 0.5em; background: #fff; border: 1px solid #ccc; border-radius: 3px;">${escapeHtml(systemPrompt)}</pre>` : '<p><em>本次调用无系统指令。</em></p>'}
${userPrompt ? `<strong>用户输入:</strong><pre style="white-space: pre-wrap; word-wrap: break-word; font-size: 0.85rem; margin-top:0.2em; padding: 0.5em; background: #fff; border: 1px solid #ccc; border-radius: 3px;">${escapeHtml(userPrompt)}</pre>` : '<p><em>本次调用无用户输入。</em></p>'}
</div>
</div>`;
}
export function generateGenAiPageHtml(title, bodyContent, pageDate, isErrorPage = false, selectedItemsForAction = null,
systemP1 = null, userP1 = null, systemP2 = null, userP2 = null,
promptsMd = null, dailyMd = null, podcastMd = null) {
let actionButtonHtml = '';
// Regenerate button for AI Content Summary page
if (title.includes('AI日报') && selectedItemsForAction && Array.isArray(selectedItemsForAction) && selectedItemsForAction.length > 0) {
actionButtonHtml = `
<form action="/genAIContent" method="POST" style="display: inline-block; margin-left: 0.5rem;">
<input type="hidden" name="date" value="${escapeHtml(pageDate)}">
${selectedItemsForAction.map(item => `<input type="hidden" name="selectedItems" value="${escapeHtml(item)}">`).join('')}
<button type="submit" class="button-link regenerate-button">${isErrorPage ? '重试生成' : '重新生成'}</button>
</form>`;
}
// Regenerate button for AI Podcast Script page
else if (title.includes('AI播客') && selectedItemsForAction && Array.isArray(selectedItemsForAction) && selectedItemsForAction.length > 0) {
actionButtonHtml = `
<form action="/genAIPodcastScript" method="POST" style="display: inline-block; margin-left: 0.5rem;">
<input type="hidden" name="date" value="${escapeHtml(pageDate)}">
${selectedItemsForAction.map(item => `<input type="hidden" name="selectedItems" value="${escapeHtml(item)}">`).join('')}
<input type="hidden" name="summarizedContent" value="${escapeHtml(convertEnglishQuotesToChinese(dailyMd))}">
<button type="submit" class="button-link regenerate-button">${isErrorPage ? '重试生成' : '重新生成'}</button>
</form>`;
}
let githubSaveFormHtml = '';
let generatePodcastButtonHtml = '';
let aiDailyAnalysisButtonHtml = '';
// Since commitToGitHub and genAIPodcastScript are now API calls,
// these forms should be handled by JavaScript on the client side.
// We will provide the data as hidden inputs for potential client-side use,
// but the submission will be via JS fetch, not direct form POST.
if (!isErrorPage) {
if (title === 'AI日报' && promptsMd && dailyMd) {
githubSaveFormHtml = `
<input type="hidden" id="promptsMdCall1" value="${escapeHtml(promptsMd)}">
<input type="hidden" id="dailyMd" value="${escapeHtml(dailyMd)}">
<button type="button" class="button-link github-save-button" onclick="commitToGitHub('${pageDate}', 'daily')">保存提示词和日报到 GitHub</button>`;
} else if (title === 'AI播客脚本' && promptsMd && podcastMd) {
githubSaveFormHtml = `
<input type="hidden" id="promptsMdCall2" value="${escapeHtml(promptsMd)}">
<input type="hidden" id="podcastMd" value="${escapeHtml(podcastMd)}">
<button type="button" class="button-link github-save-button" onclick="commitToGitHub('${pageDate}', 'podcast')">保存提示词和播客到 GitHub</button>`;
}
}
if (title === 'AI日报' && !isErrorPage && podcastMd === null) { // podcastMd === null indicates it's the Call 1 page
generatePodcastButtonHtml = `
<form action="/genAIPodcastScript" method="POST" style="display: inline-block; margin-left: 0.5rem;">
<input type="hidden" name="date" value="${escapeHtml(pageDate)}">
${selectedItemsForAction.map(item => `<input type="hidden" name="selectedItems" value="${escapeHtml(item)}">`).join('')}
<input type="hidden" name="summarizedContent" value="${escapeHtml(convertEnglishQuotesToChinese(bodyContent))}">
<button type="submit" class="button-link">生成播客脚本</button>
</form>`;
aiDailyAnalysisButtonHtml = `
<input type="hidden" id="summarizedContentInput" value="${escapeHtml(convertEnglishQuotesToChinese(bodyContent))}">
<button type="button" class="button-link" onclick="generateAIDailyAnalysis('${escapeHtml(pageDate)}')">AI 日报分析</button>
`;
}
let promptDisplayHtml = '';
if (title === 'AI日报') {
if (systemP1 || userP1) {
promptDisplayHtml = `
<div style="margin-top: 1.5rem;">
<h2 style="font-size:1.3rem; margin-bottom:0.5rem;">API 调用详情</h2>
${generatePromptSectionHtmlForGenAI(convertEnglishQuotesToChinese(systemP1), convertEnglishQuotesToChinese(userP1), '调用 1: 日报', 'call1')}
</div>`;
}
} else if (title === 'AI播客脚本') {
if (systemP2 || userP2) {
promptDisplayHtml = `
<div style="margin-top: 1.5rem;">
<h2 style="font-size:1.3rem; margin-bottom:0.5rem;">API 调用详情</h2>
${generatePromptSectionHtmlForGenAI(convertEnglishQuotesToChinese(systemP2), convertEnglishQuotesToChinese(userP2), '调用 2: 播客格式化', 'call2')}
</div>`;
}
}
return `
<!DOCTYPE html><html lang="zh-Hans"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>${escapeHtml(title)}</title>
<style>
:root { --primary-color: #007bff; --light-gray: #f8f9fa; --medium-gray: #e9ecef; --dark-gray: #343a40; --retry-color: #ffc107; --retry-text-color: #212529; --info-color: #17a2b8; --github-green: #28a745;}
body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; line-height: 1.6; background-color: var(--light-gray); color: var(--dark-gray); padding: 1rem; }
.container { max-width: 900px; margin: 0 auto; background-color: #fff; padding: 1.5rem; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); }
h1 { font-size: 1.8rem; color: ${isErrorPage ? '#dc3545' : 'var(--dark-gray)'}; margin-bottom: 0.5rem; }
p { margin-bottom: 1rem; }
.content-box { margin-top: 1.5rem; padding: 1rem; background-color: ${isErrorPage ? '#f8d7da' : '#f0f9ff'}; border: 1px solid ${isErrorPage ? '#f5c6cb' : '#cce7ff'}; color: ${isErrorPage ? '#721c24' : 'var(--dark-gray)'}; border-radius: 6px; white-space: pre-wrap; word-wrap: break-word; line-height: 1.5; font-family: ${isErrorPage ? 'inherit' : 'Menlo, Monaco, Consolas, "Courier New", monospace'}; font-size: ${isErrorPage ? '1rem' : '0.95rem'};}
.header-actions { display: flex; flex-wrap: wrap; gap: 0.5rem; justify-content: flex-end; align-items: center; margin-bottom: 1rem; }
.navigation-links { margin-top: 1.5rem; }
.button-link { display: inline-block; background-color: var(--primary-color); color: white; border: none; padding: 0.6rem 1.2rem; font-size: 0.9rem; border-radius: 5px; cursor: pointer; text-decoration: none; transition: background-color 0.2s; margin-right: 0.5rem; margin-bottom: 0.5rem;}
.button-link:hover { background-color: #0056b3; }
.regenerate-button { background-color: ${isErrorPage ? 'var(--retry-color)' : 'var(--info-color)'}; color: ${isErrorPage ? 'var(--retry-text-color)' : 'white'}; }
.regenerate-button:hover { background-color: ${isErrorPage ? '#e0a800' : '#138496'}; }
.github-save-button { background-color: var(--github-green); }
.github-save-button:hover { background-color: #218838; }
.toggle-prompt-btn { background-color: #6c757d; font-size: 0.85rem; padding: 0.4rem 0.8rem;}
.toggle-prompt-btn:hover { background-color: #5a6268; }
.copy-prompt-btn { background-color: #17a2b8; font-size: 0.85rem; padding: 0.4rem 0.8rem;}
.copy-prompt-btn:hover { background-color: #138496;}
</style>
</head><body><div class="container">
<div class="header-bar" style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 1.5rem; flex-wrap: wrap; gap: 1rem;">
<h1>${escapeHtml(title)}</h1>
<div class="header-actions">
${generatePodcastButtonHtml}
${aiDailyAnalysisButtonHtml}
</div>
</div>
<p>所选内容日期: <strong>${formatDateToChinese(escapeHtml(pageDate))}</strong></p>
<div class="content-box">${bodyContent}</div>
${promptDisplayHtml}
<div class="navigation-links">
<a href="/getContentHtml?date=${encodeURIComponent(pageDate)}" class="button-link">返回内容选择</a>
${actionButtonHtml}
${githubSaveFormHtml}
<div id="dailyAnalysisResult" style="margin-top: 1rem; padding: 1rem; border: 1px solid #ccc; border-radius: 5px; background-color: #f9f9f9; display: none;"></div>
</div>
</div>
<script>
function togglePromptVisibility(elementId, buttonElement) {
const promptDiv = document.getElementById(elementId);
if (promptDiv) {
promptDiv.style.display = (promptDiv.style.display === 'none') ? 'block' : 'none';
if (buttonElement) buttonElement.textContent = (promptDiv.style.display === 'none') ? '显示提示详情' : '隐藏提示详情';
}
}
function copyToClipboard(textToCopy, buttonElement) {
if (!textToCopy) { alert("Nothing to copy."); return; }
navigator.clipboard.writeText(textToCopy).then(() => {
const originalText = buttonElement.textContent;
buttonElement.textContent = '已复制!'; buttonElement.style.backgroundColor = '#28a745';
setTimeout(() => { buttonElement.textContent = originalText; buttonElement.style.backgroundColor = '#17a2b8'; }, 2000);
}, (err) => { console.error('Async: Could not copy text: ', err); alert('复制提示失败。'); });
}
async function commitToGitHub(date, type) {
const button = event.target;
const originalText = button.textContent;
button.textContent = '保存中...';
button.disabled = true;
const formData = new FormData();
formData.append('date', date);
if (type === 'daily') {
formData.append('prompts_markdown-1', document.getElementById('promptsMdCall1').value);
formData.append('daily_summary_markdown', document.getElementById('dailyMd').value);
} else if (type === 'podcast') {
formData.append('prompts_markdown-2', document.getElementById('promptsMdCall2').value);
formData.append('podcast_script_markdown', document.getElementById('podcastMd').value);
}
try {
const response = await fetch('/commitToGitHub', {
method: 'POST',
body: formData
});
const result = await response.json();
if (response.ok) {
alert('GitHub 提交成功!');
console.log('GitHub Commit Success:', result);
} else {
alert('GitHub 提交失败: ' + result.message);
console.error('GitHub Commit Failed:', result);
}
} catch (error) {
console.error('Error committing to GitHub:', error);
alert('请求失败,请检查网络或服务器。');
} finally {
button.textContent = originalText;
button.disabled = false;
}
}
async function generateAIDailyAnalysis(date) {
const button = event.target;
const originalText = button.textContent;
button.textContent = '正在分析...';
button.disabled = true;
const analysisResultDiv = document.getElementById('dailyAnalysisResult');
analysisResultDiv.style.display = 'none'; // Hide previous result
analysisResultDiv.innerHTML = ''; // Clear previous result
const summarizedContent = document.getElementById('summarizedContentInput').value; // Get summarized content from hidden input
try {
const response = await fetch('/genAIDailyAnalysis', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ date: date, summarizedContent: summarizedContent })
});
if (response.ok) {
const result = await response.text();
analysisResultDiv.innerHTML = \`<h2>AI 日报分析结果</h2><div class="content-box">\${result}</div>\`;
analysisResultDiv.style.display = 'block';
//alert('AI 日报分析成功!');
} else {
const errorText = await response.text();
analysisResultDiv.innerHTML = \`<h2>AI 日报分析失败</h2><div class="content-box error">\${errorText}</div>\`;
analysisResultDiv.style.display = 'block';
alert('AI 日报分析失败: ' + errorText);
}
} catch (error) {
console.error('Error generating AI daily analysis:', error);
analysisResultDiv.innerHTML = \`<h2>AI 日报分析失败</h2><div class="content-box error">请求失败,请检查网络或服务器。错误: \${escapeHtml(error.message)}</div>\`;
analysisResultDiv.style.display = 'block';
alert('请求失败,请检查网络或服务器。');
} finally {
button.textContent = originalText;
button.disabled = false;
}
}
</script>
</body></html>`;
}