Merge branch 'master' of ssh://gitea.bowongai.com:222/bowong/mxivideo
This commit is contained in:
commit
7e84d27c18
|
|
@ -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() {
|
|||
<Route path="/editor" element={<EditorPage />} />
|
||||
<Route path="/ai-video" element={<AIVideoPage />} />
|
||||
<Route path="/templates" element={<TemplateManagePage />} />
|
||||
<Route path="/kv-test" element={<KVTestPage />} />
|
||||
<Route path="/settings" element={<SettingsPage />} />
|
||||
</Routes>
|
||||
</Layout>
|
||||
|
|
|
|||
|
|
@ -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<string[]>([])
|
||||
|
||||
// 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<number>('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<DemoData>(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
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setLogs([])}
|
||||
className="bg-gray-500 hover:bg-gray-600 text-white px-4 py-2 rounded-lg transition-colors ml-3"
|
||||
>
|
||||
Clear Logs
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Debug Logs Section */}
|
||||
<div className="bg-white rounded-lg shadow-lg p-6 mt-6">
|
||||
<h2 className="text-xl font-semibold text-gray-900 mb-4">
|
||||
Debug Logs
|
||||
</h2>
|
||||
<div className="bg-gray-900 text-green-400 p-4 rounded-lg font-mono text-sm max-h-96 overflow-y-auto">
|
||||
{logs.length === 0 ? (
|
||||
<div className="text-gray-500">No logs yet...</div>
|
||||
) : (
|
||||
logs.map((log, index) => (
|
||||
<div key={index} className="mb-1">
|
||||
{log}
|
||||
</div>
|
||||
))
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 () => {
|
||||
|
|
|
|||
|
|
@ -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 (
|
||||
<div className="min-h-screen bg-secondary-50">
|
||||
{/* Header */}
|
||||
<div className="bg-white border-b border-secondary-200 px-6 py-4">
|
||||
<div className="flex items-center space-x-4">
|
||||
<Link
|
||||
to="/"
|
||||
className="flex items-center space-x-2 text-secondary-600 hover:text-secondary-900 transition-colors"
|
||||
>
|
||||
<ArrowLeft size={20} />
|
||||
<span>返回首页</span>
|
||||
</Link>
|
||||
<div className="h-6 w-px bg-secondary-300" />
|
||||
<h1 className="text-2xl font-bold text-secondary-900">
|
||||
Cloudflare KV 测试
|
||||
</h1>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Content */}
|
||||
<div className="p-6">
|
||||
<div className="max-w-6xl mx-auto">
|
||||
{/* Description */}
|
||||
<div className="bg-white rounded-lg shadow-sm border border-secondary-200 p-6 mb-6">
|
||||
<h2 className="text-lg font-semibold text-secondary-900 mb-3">
|
||||
关于 Cloudflare KV 测试
|
||||
</h2>
|
||||
<p className="text-secondary-600 mb-4">
|
||||
这个页面演示了如何在 MixVideo V2 中使用 Cloudflare KV 存储。
|
||||
您可以测试键值对的存储、读取、删除和批量操作功能。
|
||||
</p>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
|
||||
<div className="bg-blue-50 p-4 rounded-lg">
|
||||
<h3 className="font-medium text-blue-900 mb-2">存储数据</h3>
|
||||
<p className="text-sm text-blue-700">
|
||||
将键值对数据存储到 Cloudflare KV
|
||||
</p>
|
||||
</div>
|
||||
<div className="bg-green-50 p-4 rounded-lg">
|
||||
<h3 className="font-medium text-green-900 mb-2">读取数据</h3>
|
||||
<p className="text-sm text-green-700">
|
||||
根据键名获取存储的数据
|
||||
</p>
|
||||
</div>
|
||||
<div className="bg-purple-50 p-4 rounded-lg">
|
||||
<h3 className="font-medium text-purple-900 mb-2">列出键名</h3>
|
||||
<p className="text-sm text-purple-700">
|
||||
按前缀搜索和列出所有键名
|
||||
</p>
|
||||
</div>
|
||||
<div className="bg-orange-50 p-4 rounded-lg">
|
||||
<h3 className="font-medium text-orange-900 mb-2">批量操作</h3>
|
||||
<p className="text-sm text-orange-700">
|
||||
一次性处理多个键值对操作
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* KV Demo Component */}
|
||||
<CloudflareKVDemo />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default KVTestPage
|
||||
|
|
@ -59,7 +59,8 @@ export class CloudflareKVClient {
|
|||
async put(key: string, value: any, metadata?: Record<string, any>): Promise<CloudflareKVResponse> {
|
||||
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'}`)
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue