71 lines
1.6 KiB
TypeScript
71 lines
1.6 KiB
TypeScript
import React from 'react'
|
||
import { ShellExecutePreview } from './ShellExecutePreview'
|
||
|
||
export interface UrlScriptPreviewProps {
|
||
url: string
|
||
title?: string
|
||
}
|
||
|
||
/**
|
||
* 基于 URL 加载脚本内容并用 ScriptPreview 渲染
|
||
* - 保持 nova-sdk 自包含,不依赖宿主应用的 Preview 组件
|
||
* - 由外部控制传入的 url(通常来自后端签名地址)
|
||
*/
|
||
export function UrlScriptPreview({ url, title }: UrlScriptPreviewProps) {
|
||
const [code, setCode] = React.useState('')
|
||
const [loading, setLoading] = React.useState(true)
|
||
const [error, setError] = React.useState(false)
|
||
|
||
React.useEffect(() => {
|
||
let cancelled = false
|
||
setLoading(true)
|
||
setError(false)
|
||
|
||
fetch(url)
|
||
.then(res => {
|
||
if (!res.ok) {
|
||
throw new Error(`Failed to fetch script file: ${res.status}`)
|
||
}
|
||
return res.text()
|
||
})
|
||
.then(text => {
|
||
if (!cancelled) {
|
||
setCode(text)
|
||
}
|
||
})
|
||
.catch(() => {
|
||
if (!cancelled) {
|
||
setError(true)
|
||
}
|
||
})
|
||
.finally(() => {
|
||
if (!cancelled) {
|
||
setLoading(false)
|
||
}
|
||
})
|
||
|
||
return () => {
|
||
cancelled = true
|
||
}
|
||
}, [url])
|
||
|
||
if (error) {
|
||
return (
|
||
<div className="flex-1 flex flex-col items-center justify-center p-8 text-muted-foreground">
|
||
<span className="text-sm">脚本内容加载失败</span>
|
||
</div>
|
||
)
|
||
}
|
||
|
||
return (
|
||
<ShellExecutePreview
|
||
output={code}
|
||
toolLabel={title || 'script_file'}
|
||
loading={loading}
|
||
/>
|
||
)
|
||
}
|
||
|
||
export default UrlScriptPreview
|
||
|