From 5dbbe8f48499f6fade2dcc26c7760dd23e01a9fa Mon Sep 17 00:00:00 2001 From: justlovemaki <274166795@qq.com> Date: Thu, 12 Jun 2025 17:41:06 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E5=9B=BE=E7=89=87?= =?UTF-8?q?=E4=BB=A3=E7=90=86=E5=8A=9F=E8=83=BD=E5=B9=B6=E5=AE=8C=E5=96=84?= =?UTF-8?q?=E4=BC=9A=E8=AF=9D=E7=AE=A1=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在wrangler.toml中添加IMG_PROXY配置项用于图片代理 - 新增replaceImageProxy函数处理图片链接替换 - 实现KV存储的会话管理功能 - 在生成AI内容页面添加图片代理和新窗口预览功能 - 完善Markdown转HTML功能,支持更多语法元素 --- src/auth.js | 16 +- src/handlers/genAIContent.js | 20 +-- src/helpers.js | 5 + src/htmlGenerators.js | 306 ++++++++++++++++++++++++++++++++++- wrangler.toml | 1 + 5 files changed, 330 insertions(+), 18 deletions(-) diff --git a/src/auth.js b/src/auth.js index 87748d2..3bc2ae5 100644 --- a/src/auth.js +++ b/src/auth.js @@ -1,4 +1,6 @@ // src/auth.js +import { storeInKV, getFromKV} from './kv.js'; + const SESSION_COOKIE_NAME = 'session_id_89757'; const SESSION_EXPIRATION_SECONDS = 60 * 60; // 1 hour @@ -95,7 +97,7 @@ async function handleLogin(request, env) { const sessionId = crypto.randomUUID(); // Generate a simple session ID // Store sessionId in KV store for persistent sessions - // await env.DATA_KV.put(`session:${sessionId}`, 'valid', { expirationTtl: SESSION_EXPIRATION_SECONDS }); + await storeInKV(env.DATA_KV, `session:${sessionId}`, 'valid', SESSION_EXPIRATION_SECONDS); const cookie = setSessionCookie(sessionId); @@ -130,11 +132,13 @@ async function isAuthenticated(request, env) { const sessionId = sessionCookie.split('=')[1]; // Validate sessionId against KV store - // const storedSession = await env.DATA_KV.get(`session:${sessionId}`); - // if (storedSession !== 'valid') { - // return { authenticated: false, cookie: null }; - // } + const storedSession = await getFromKV(env.DATA_KV, `session:${sessionId}`); + if (storedSession !== 'valid') { + return { authenticated: false, cookie: null }; + } + // Store sessionId in KV store for persistent sessions + await storeInKV(env.DATA_KV, `session:${sessionId}`, 'valid', SESSION_EXPIRATION_SECONDS); // Renew the session cookie const newCookie = setSessionCookie(sessionId); return { authenticated: true, cookie: newCookie }; @@ -149,7 +153,7 @@ async function handleLogout(request, env) { if (sessionCookie) { const sessionId = sessionCookie.split('=')[1]; // Delete session from KV store - // await env.DATA_KV.delete(`session:${sessionId}`); + await env.DATA_KV.delete(`session:${sessionId}`); } } diff --git a/src/handlers/genAIContent.js b/src/handlers/genAIContent.js index 61fee48..a6a7e5a 100644 --- a/src/handlers/genAIContent.js +++ b/src/handlers/genAIContent.js @@ -27,7 +27,7 @@ export async function handleGenAIPodcastScript(request, env) { outputOfCall1 = formData.get('summarizedContent'); // Get summarized content from form data if (!outputOfCall1) { - const errorHtml = generateGenAiPageHtml('生成AI播客脚本出错', '
Summarized content is missing. Please go back and generate AI content first.
', dateStr, true, null); + const errorHtml = generateGenAiPageHtml(env, '生成AI播客脚本出错', 'Summarized content is missing. Please go back and generate AI content first.
', dateStr, true, null); return new Response(errorHtml, { status: 400, headers: { 'Content-Type': 'text/html; charset=utf-8' } }); } @@ -47,7 +47,7 @@ export async function handleGenAIPodcastScript(request, env) { console.log("Call 2 (Podcast Formatting) successful. Final output length:", finalAiResponse.length); } catch (error) { console.error("Error in Chat API Call 2 (Podcast Formatting):", error); - const errorHtml = generateGenAiPageHtml('生成AI播客脚本出错(播客文案)', `Failed during podcast formatting: ${escapeHtml(error.message)}
${error.stack ? `${escapeHtml(error.stack)}` : ''}`, dateStr, true, selectedItemsParams, null, null, fullPromptForCall2_System, fullPromptForCall2_User);
+ const errorHtml = generateGenAiPageHtml(env, '生成AI播客脚本出错(播客文案)', `Failed during podcast formatting: ${escapeHtml(error.message)}
${error.stack ? `${escapeHtml(error.stack)}` : ''}`, dateStr, true, selectedItemsParams, null, null, fullPromptForCall2_System, fullPromptForCall2_User);
return new Response(errorHtml, { status: 500, headers: { 'Content-Type': 'text/html; charset=utf-8' } });
}
@@ -59,6 +59,7 @@ export async function handleGenAIPodcastScript(request, env) {
let podcastScriptMarkdownContent = `# ${env.PODCAST_TITLE} ${formatDateToChinese(dateStr)}\n\n${removeMarkdownCodeBlock(finalAiResponse)}`;
const successHtml = generateGenAiPageHtml(
+ env,
'AI播客脚本',
escapeHtml(finalAiResponse),
dateStr, false, selectedItemsParams,
@@ -74,7 +75,7 @@ export async function handleGenAIPodcastScript(request, env) {
console.error("Error in /genAIPodcastScript (outer try-catch):", error);
const pageDateForError = dateStr || getISODate();
const itemsForActionOnError = Array.isArray(selectedItemsParams) ? selectedItemsParams : [];
- const errorHtml = generateGenAiPageHtml('生成AI播客脚本出错', `Unexpected error: ${escapeHtml(error.message)}
${error.stack ? `${escapeHtml(error.stack)}` : ''}`, pageDateForError, true, itemsForActionOnError, null, null, fullPromptForCall2_System, fullPromptForCall2_User);
+ const errorHtml = generateGenAiPageHtml(env, '生成AI播客脚本出错', `Unexpected error: ${escapeHtml(error.message)}
${error.stack ? `${escapeHtml(error.stack)}` : ''}`, pageDateForError, true, itemsForActionOnError, null, null, fullPromptForCall2_System, fullPromptForCall2_User);
return new Response(errorHtml, { status: 500, headers: { 'Content-Type': 'text/html; charset=utf-8' } });
}
}
@@ -96,7 +97,7 @@ export async function handleGenAIContent(request, env) {
selectedItemsParams = formData.getAll('selectedItems');
if (selectedItemsParams.length === 0) {
- const errorHtml = generateGenAiPageHtml('生成AI日报出错,未选生成条目', 'No items were selected. Please go back and select at least one item.
', dateStr, true, null); + const errorHtml = generateGenAiPageHtml(env, '生成AI日报出错,未选生成条目', 'No items were selected. Please go back and select at least one item.
', dateStr, true, null); return new Response(errorHtml, { status: 400, headers: { 'Content-Type': 'text/html; charset=utf-8' } }); } @@ -159,13 +160,13 @@ export async function handleGenAIContent(request, env) { } if (validItemsProcessedCount === 0) { - const errorHtml = generateGenAiPageHtml('生成AI日报出错,可生成条目为空', 'Selected items could not be retrieved or resulted in no content. Please check the data or try different selections.
', dateStr, true, selectedItemsParams); + const errorHtml = generateGenAiPageHtml(env, '生成AI日报出错,可生成条目为空', 'Selected items could not be retrieved or resulted in no content. Please check the data or try different selections.
', dateStr, true, selectedItemsParams); return new Response(errorHtml, { status: 404, headers: { 'Content-Type': 'text/html; charset=utf-8' } }); } //提示词内不能有英文引号,否则会存储数据缺失。 fullPromptForCall1_System = getSystemPromptSummarizationStepOne(); - fullPromptForCall1_User = selectedContentItems.join('\n\n---\n\n'); // Keep this for logging/error reporting if needed + fullPromptForCall1_User = '\n\n------\n\n'+selectedContentItems.join('\n\n------\n\n')+'\n\n------\n\n'; // Keep this for logging/error reporting if needed console.log("Call 1 to Chat (Summarization): User prompt length:", fullPromptForCall1_User.length); try { @@ -193,7 +194,7 @@ export async function handleGenAIContent(request, env) { console.log("Call 1 (Summarization) successful. Output length:", outputOfCall1.length); } catch (error) { console.error("Error in Chat API Call 1 (Summarization):", error); - const errorHtml = generateGenAiPageHtml('生成AI日报出错(分段处理)', `Failed during summarization: ${escapeHtml(error.message)}
${error.stack ? `${escapeHtml(error.stack)}` : ''}`, dateStr, true, selectedItemsParams, fullPromptForCall1_System, fullPromptForCall1_User);
+ const errorHtml = generateGenAiPageHtml(env, '生成AI日报出错(分段处理)', `Failed during summarization: ${escapeHtml(error.message)}
${error.stack ? `${escapeHtml(error.stack)}` : ''}`, dateStr, true, selectedItemsParams, fullPromptForCall1_System, fullPromptForCall1_User);
return new Response(errorHtml, { status: 500, headers: { 'Content-Type': 'text/html; charset=utf-8' } });
}
@@ -214,7 +215,7 @@ export async function handleGenAIContent(request, env) {
console.log("Call 2 (Processing Call 1 Output) successful. Output length:", outputOfCall2.length);
} catch (error) {
console.error("Error in Chat API Call 2 (Processing Call 1 Output):", error);
- const errorHtml = generateGenAiPageHtml('生成AI日报出错(格式化)', `Failed during processing of summarized content: ${escapeHtml(error.message)}
${error.stack ? `${escapeHtml(error.stack)}` : ''}`, dateStr, true, selectedItemsParams, fullPromptForCall1_System, fullPromptForCall1_User, fullPromptForCall2_System, fullPromptForCall2_User);
+ const errorHtml = generateGenAiPageHtml(env, '生成AI日报出错(格式化)', `Failed during processing of summarized content: ${escapeHtml(error.message)}
${error.stack ? `${escapeHtml(error.stack)}` : ''}`, dateStr, true, selectedItemsParams, fullPromptForCall1_System, fullPromptForCall1_User, fullPromptForCall2_System, fullPromptForCall2_User);
return new Response(errorHtml, { status: 500, headers: { 'Content-Type': 'text/html; charset=utf-8' } });
}
@@ -229,6 +230,7 @@ export async function handleGenAIContent(request, env) {
let dailySummaryMarkdownContent = `# ${env.DAILY_TITLE} ${formatDateToChinese(dateStr)}\n\n${removeMarkdownCodeBlock(outputOfCall2)}`;
const successHtml = generateGenAiPageHtml(
+ env,
'AI日报', // Title for Call 1 page
escapeHtml(outputOfCall2),
dateStr, false, selectedItemsParams,
@@ -245,7 +247,7 @@ export async function handleGenAIContent(request, env) {
console.error("Error in /genAIContent (outer try-catch):", error);
const pageDateForError = dateStr || getISODate();
const itemsForActionOnError = Array.isArray(selectedItemsParams) ? selectedItemsParams : [];
- const errorHtml = generateGenAiPageHtml('生成AI日报出错', `Unexpected error: ${escapeHtml(error.message)}
${error.stack ? `${escapeHtml(error.stack)}` : ''}`, pageDateForError, true, itemsForActionOnError, fullPromptForCall1_System, fullPromptForCall1_User, fullPromptForCall2_System, fullPromptForCall2_User);
+ const errorHtml = generateGenAiPageHtml(env, '生成AI日报出错', `Unexpected error: ${escapeHtml(error.message)}
${error.stack ? `${escapeHtml(error.stack)}` : ''}`, pageDateForError, true, itemsForActionOnError, fullPromptForCall1_System, fullPromptForCall1_User, fullPromptForCall2_System, fullPromptForCall2_User);
return new Response(errorHtml, { status: 500, headers: { 'Content-Type': 'text/html; charset=utf-8' } });
}
}
diff --git a/src/helpers.js b/src/helpers.js
index 0215d6c..bfd431e 100644
--- a/src/helpers.js
+++ b/src/helpers.js
@@ -244,3 +244,8 @@ export function getRandomUserAgent() {
export function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
+
+export function replaceImageProxy(proxy, content) {
+ const str = String(content);
+ return str.replace(/upload.chinaz.com/g, 'pic.chinaz.com').replace(/https:\/\/pic.chinaz.com/g, proxy+'https:\/\/pic.chinaz.com');
+}
\ No newline at end of file
diff --git a/src/htmlGenerators.js b/src/htmlGenerators.js
index 090c52e..f9ee440 100644
--- a/src/htmlGenerators.js
+++ b/src/htmlGenerators.js
@@ -1,5 +1,5 @@
// src/htmlGenerators.js
-import { escapeHtml, formatDateToChinese, convertEnglishQuotesToChinese} from './helpers.js';
+import { escapeHtml, formatDateToChinese, convertEnglishQuotesToChinese, replaceImageProxy} from './helpers.js';
import { dataSources } from './dataFetchers.js'; // Import dataSources
function generateHtmlListForContentPage(items, dateStr) {
@@ -275,7 +275,8 @@ function generatePromptSectionHtmlForGenAI(systemPrompt, userPrompt, promptTitle
`;
}
-export function generateGenAiPageHtml(title, bodyContent, pageDate, isErrorPage = false, selectedItemsForAction = null,
+
+export function generateGenAiPageHtml(env, title, bodyContent, pageDate, isErrorPage = false, selectedItemsForAction = null,
systemP1 = null, userP1 = null, systemP2 = null, userP2 = null,
promptsMd = null, dailyMd = null, podcastMd = null) {
@@ -303,6 +304,7 @@ export function generateGenAiPageHtml(title, bodyContent, pageDate, isErrorPage
let githubSaveFormHtml = '';
let generatePodcastButtonHtml = '';
let aiDailyAnalysisButtonHtml = '';
+ let outDisplayButtonHtml = '';
// Since commitToGitHub and genAIPodcastScript are now API calls,
// these forms should be handled by JavaScript on the client side.
@@ -334,6 +336,9 @@ export function generateGenAiPageHtml(title, bodyContent, pageDate, isErrorPage
`;
+ outDisplayButtonHtml = `
+
+ `;
}
let promptDisplayHtml = '';
@@ -377,6 +382,7 @@ export function generateGenAiPageHtml(title, bodyContent, pageDate, isErrorPage
.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;}
+ #outContentBox { display: none;}
所选内容日期: ${formatDateToChinese(escapeHtml(pageDate))}
-