Update from Vibe Studio

This commit is contained in:
Vibe Studio
2026-02-04 09:39:59 +00:00
parent 4332632f15
commit b775c40437
4 changed files with 210 additions and 1 deletions

View File

@@ -0,0 +1,173 @@
import { useState } from 'react'
import { Form, Input, Button, Card, Typography, Space, Spin } from 'antd'
import { ArrowRightOutlined, ClearOutlined } from '@ant-design/icons'
import type { FetchStreamOptions } from '@copilotkit/react-core'
const { Title, Text } = Typography
interface DifyResponse {
message: string
}
export default function NumberToChinese() {
const [form] = Form.useForm()
const [loading, setLoading] = useState(false)
const [result, setResult] = useState('')
const [error, setError] = useState('')
const handleConvert = async (values: { number: string }) => {
setLoading(true)
setError('')
setResult('')
try {
const response = await fetch(`${import.meta.env.VITE_DIFY_API_BASE}/chat-messages`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${import.meta.env.VITE_DIFY_APP_KEY}`
},
body: JSON.stringify({
inputs: { number: values.number },
query: '1',
response_mode: 'streaming'
})
})
if (!response.ok) {
throw new Error('请求失败')
}
const reader = response.body?.getReader()
if (!reader) {
throw new Error('无法读取响应流')
}
const decoder = new TextDecoder()
let fullContent = ''
while (true) {
const { done, value } = await reader.read()
if (done) break
const chunk = decoder.decode(value)
const lines = chunk.split('\n')
for (const line of lines) {
if (line.startsWith('data: ')) {
try {
const data = JSON.parse(line.slice(6)) as DifyResponse
if (data.message) {
fullContent += data.message
setResult(fullContent)
}
} catch {
// 忽略解析错误
}
}
}
}
} catch (err) {
setError(err instanceof Error ? err.message : '转换失败,请稍后重试')
} finally {
setLoading(false)
}
}
const handleReset = () => {
form.resetFields()
setResult('')
setError('')
}
return (
<div className="min-h-screen bg-white p-6">
<div className="max-w-2xl mx-auto">
{/* 页面标题区 */}
<div className="text-center mb-8">
<Title level={2} style={{ color: '#1890ff', margin: 0 }}>
</Title>
</div>
{/* 参数输入区 */}
<Card className="mb-6 shadow-sm border-radius-lg">
<Form
form={form}
layout="vertical"
onFinish={handleConvert}
autoComplete="off"
>
<Form.Item
name="number"
rules={[
{ required: true, message: '请输入数字' },
{ pattern: /^-?\d+(\.\d+)?$/, message: '请输入有效数字' }
]}
>
<Input.TextArea
placeholder="请输入要转换的数字"
rows={3}
className="text-lg"
allowClear
/>
</Form.Item>
<Form.Item className="mb-0">
<Space className="w-full justify-center">
<Button
type="primary"
htmlType="submit"
icon={<ArrowRightOutlined />}
loading={loading}
size="large"
>
</Button>
<Button
icon={<ClearOutlined />}
onClick={handleReset}
size="large"
>
</Button>
</Space>
</Form.Item>
</Form>
</Card>
{/* 内容展示区 */}
<Card
className="shadow-sm"
style={{ minHeight: '150px', maxHeight: '60vh', overflow: 'auto' }}
>
{loading && (
<div className="text-center py-8">
<Spin size="large" />
<Text className="block mt-4 text-gray-400">...</Text>
</div>
)}
{!loading && error && (
<div className="text-center py-8">
<Text type="danger">{error}</Text>
</div>
)}
{!loading && !error && result && (
<div>
<Text strong className="block mb-4"></Text>
<div className="text-lg leading-relaxed whitespace-pre-wrap">{result}</div>
</div>
)}
{!loading && !error && !result && (
<div className="text-center py-8">
<Text type="secondary"></Text>
</div>
)}
</Card>
</div>
</div>
)
}