diff --git a/src/App.tsx b/src/App.tsx index b47bb73..6601840 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -6,6 +6,7 @@ import EditorPage from './pages/EditorPage' import AIVideoPage from './pages/AIVideoPage' import SettingsPage from './pages/SettingsPage' import TemplateManagePage from './pages/TemplateManagePage' +import KVTestPage from './pages/KVTestPage' function App() { return ( @@ -15,6 +16,7 @@ function App() { } /> } /> } /> + } /> } /> diff --git a/src/components/CloudflareKVDemo.tsx b/src/components/CloudflareKVDemo.tsx index dac4ebe..e80d79c 100644 --- a/src/components/CloudflareKVDemo.tsx +++ b/src/components/CloudflareKVDemo.tsx @@ -18,6 +18,15 @@ export const CloudflareKVDemo: React.FC = () => { const [inputKey, setInputKey] = useState('demo:test') const [inputValue, setInputValue] = useState('Hello, Cloudflare KV!') const [searchPrefix, setSearchPrefix] = useState('demo:') + const [logs, setLogs] = useState([]) + + // Add log function + const addLog = (message: string) => { + const timestamp = new Date().toLocaleTimeString() + const logMessage = `[${timestamp}] ${message}` + console.log(logMessage) + setLogs(prev => [logMessage, ...prev].slice(0, 20)) // Keep last 20 logs + } // Use the general KV hook const kv = useCloudflareKV() @@ -31,9 +40,25 @@ export const CloudflareKVDemo: React.FC = () => { refresh: refreshCounter } = useKVValue('demo:counter', true, true) + // Log initial state + React.useEffect(() => { + addLog('CloudflareKVDemo component initialized') + addLog(`KV loading state: ${kv.isLoading}`) + addLog(`KV has error: ${kv.hasError}`) + if (kv.hasError) { + addLog(`KV errors: ${JSON.stringify(kv.errors)}`) + } + }, [kv.isLoading, kv.hasError, kv.errors]) + // Handle putting a value const handlePutValue = async () => { - if (!inputKey || !inputValue) return + if (!inputKey || !inputValue) { + addLog('❌ Put operation failed: Key or value is empty') + alert('❌ Please enter both key and value') + return + } + + addLog(`🔄 Starting put operation for key: ${inputKey}`) try { const data: DemoData = { @@ -42,49 +67,77 @@ export const CloudflareKVDemo: React.FC = () => { counter: (typeof counterValue === 'number' ? counterValue : 0) + 1 } - await kv.put(inputKey, data) + addLog(`📤 Sending data: ${JSON.stringify(data)}`) + const result = await kv.put(inputKey, data) + addLog(`✅ Put operation successful: ${JSON.stringify(result)}`) alert('✅ Value stored successfully!') } catch (error) { - alert('❌ Failed to store value: ' + (error as Error).message) + const errorMessage = (error as Error).message + addLog(`❌ Put operation failed: ${errorMessage}`) + alert('❌ Failed to store value: ' + errorMessage) } } // Handle getting a value const handleGetValue = async () => { - if (!inputKey) return + if (!inputKey) { + addLog('❌ Get operation failed: Key is empty') + alert('❌ Please enter a key') + return + } + + addLog(`🔄 Starting get operation for key: ${inputKey}`) try { const result = await kv.get(inputKey) if (result) { + addLog(`✅ Get operation successful: ${JSON.stringify(result)}`) alert(`✅ Retrieved value: ${JSON.stringify(result, null, 2)}`) } else { + addLog(`ℹ️ Get operation completed: Key not found`) alert('ℹ️ Key not found') } } catch (error) { - alert('❌ Failed to get value: ' + (error as Error).message) + const errorMessage = (error as Error).message + addLog(`❌ Get operation failed: ${errorMessage}`) + alert('❌ Failed to get value: ' + errorMessage) } } // Handle deleting a value const handleDeleteValue = async () => { - if (!inputKey) return + if (!inputKey) { + addLog('❌ Delete operation failed: Key is empty') + alert('❌ Please enter a key') + return + } + + addLog(`🔄 Starting delete operation for key: ${inputKey}`) try { - await kv.delete(inputKey) + const result = await kv.delete(inputKey) + addLog(`✅ Delete operation successful: ${JSON.stringify(result)}`) alert('✅ Value deleted successfully!') } catch (error) { - alert('❌ Failed to delete value: ' + (error as Error).message) + const errorMessage = (error as Error).message + addLog(`❌ Delete operation failed: ${errorMessage}`) + alert('❌ Failed to delete value: ' + errorMessage) } } // Handle listing keys const handleListKeys = async () => { + addLog(`🔄 Starting list keys operation with prefix: ${searchPrefix}`) + try { const result = await kv.listKeys(searchPrefix, 50) + addLog(`✅ List keys operation successful: Found ${result.result.keys.length} keys`) const keyNames = result.result.keys.map(k => k.name).join('\n') alert(`✅ Found keys:\n${keyNames || 'No keys found'}`) } catch (error) { - alert('❌ Failed to list keys: ' + (error as Error).message) + const errorMessage = (error as Error).message + addLog(`❌ List keys operation failed: ${errorMessage}`) + alert('❌ Failed to list keys: ' + errorMessage) } } @@ -277,9 +330,33 @@ export const CloudflareKVDemo: React.FC = () => { > Clear All States + + + {/* Debug Logs Section */} +
+

+ Debug Logs +

+
+ {logs.length === 0 ? ( +
No logs yet...
+ ) : ( + logs.map((log, index) => ( +
+ {log} +
+ )) + )} +
+
) } diff --git a/src/pages/HomePage.tsx b/src/pages/HomePage.tsx index 796144a..64cb363 100644 --- a/src/pages/HomePage.tsx +++ b/src/pages/HomePage.tsx @@ -1,6 +1,6 @@ import React, { useState } from 'react' import { Link } from 'react-router-dom' -import { Plus, FolderOpen, Video, Music, Zap, TestTube, Sparkles } from 'lucide-react' +import { Plus, FolderOpen, Video, Music, Zap, TestTube, Sparkles, Database } from 'lucide-react' import { TauriService } from '../services/tauri' import { useProjectStore } from '../stores/useProjectStore' @@ -21,6 +21,7 @@ const HomePage: React.FC = () => { { icon: Music, label: '音频处理', description: '处理音频文件,添加效果', path: '/audio' }, { icon: Zap, label: 'AI 自动剪辑', description: '使用 AI 自动生成视频剪辑', path: '/editor' }, { icon: FolderOpen, label: '导入媒体', description: '导入视频、音频和图片文件', path: '/media' }, + { icon: Database, label: 'KV 存储测试', description: '测试 Cloudflare KV 键值存储功能', path: '/kv-test' }, ] const testTauriConnection = async () => { diff --git a/src/pages/KVTestPage.tsx b/src/pages/KVTestPage.tsx new file mode 100644 index 0000000..1f35825 --- /dev/null +++ b/src/pages/KVTestPage.tsx @@ -0,0 +1,74 @@ +import React from 'react' +import { ArrowLeft } from 'lucide-react' +import { Link } from 'react-router-dom' +import CloudflareKVDemo from '../components/CloudflareKVDemo' + +const KVTestPage: React.FC = () => { + return ( +
+ {/* Header */} +
+
+ + + 返回首页 + +
+

+ Cloudflare KV 测试 +

+
+
+ + {/* Content */} +
+
+ {/* Description */} +
+

+ 关于 Cloudflare KV 测试 +

+

+ 这个页面演示了如何在 MixVideo V2 中使用 Cloudflare KV 存储。 + 您可以测试键值对的存储、读取、删除和批量操作功能。 +

+
+
+

存储数据

+

+ 将键值对数据存储到 Cloudflare KV +

+
+
+

读取数据

+

+ 根据键名获取存储的数据 +

+
+
+

列出键名

+

+ 按前缀搜索和列出所有键名 +

+
+
+

批量操作

+

+ 一次性处理多个键值对操作 +

+
+
+
+ + {/* KV Demo Component */} + +
+
+
+ ) +} + +export default KVTestPage diff --git a/src/utils/cloudflareKV.ts b/src/utils/cloudflareKV.ts index a9668ba..9ae5df1 100644 --- a/src/utils/cloudflareKV.ts +++ b/src/utils/cloudflareKV.ts @@ -59,7 +59,8 @@ export class CloudflareKVClient { async put(key: string, value: any, metadata?: Record): Promise { try { const url = `${this.getKVBaseUrl()}/values/${encodeURIComponent(key)}` - + console.log(`[CloudflareKV] PUT request to: ${url}`) + const body: any = { value: typeof value === 'string' ? value : JSON.stringify(value) } @@ -68,6 +69,8 @@ export class CloudflareKVClient { body.metadata = JSON.stringify(metadata) } + console.log(`[CloudflareKV] PUT body:`, body) + const response = await fetch(url, { method: 'PUT', headers: { @@ -77,8 +80,11 @@ export class CloudflareKVClient { body: JSON.stringify(body) }) + console.log(`[CloudflareKV] PUT response status: ${response.status}`) + const result = await response.json() - + console.log(`[CloudflareKV] PUT response:`, result) + if (!response.ok) { throw new Error(`HTTP ${response.status}: ${result.errors?.[0]?.message || 'Unknown error'}`) }