Merge branch 'master' of ssh://gitea.bowongai.com:222/bowong/mxivideo

This commit is contained in:
root 2025-07-10 22:26:53 +08:00
commit 7e84d27c18
5 changed files with 172 additions and 12 deletions

View File

@ -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>

View File

@ -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>
)
}

View File

@ -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 () => {

74
src/pages/KVTestPage.tsx Normal file
View File

@ -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

View File

@ -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'}`)
}