初始提交: ScriptForge 脚本快速转运行链接服务
Some checks failed
Release / build-and-release (push) Failing after 1m31s
Some checks failed
Release / build-and-release (push) Failing after 1m31s
- Go 后端 (Gin + GORM + SQLite) 提供 API 和纯文本脚本服务 - Vite + React + TypeScript + Tailwind 前端 - 单二进制部署 (Go embed 前端静态文件) - Gitea Actions CI/CD: 打标签自动构建多平台 Release - 支持 bash/zsh/sh/fish/python3/node/ruby/php 8种运行环境 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
76
frontend/src/components/ScriptForm.tsx
Normal file
76
frontend/src/components/ScriptForm.tsx
Normal file
@@ -0,0 +1,76 @@
|
||||
import { useState } from 'react'
|
||||
import { RUNTIME_OPTIONS, EXPIRES_OPTIONS, RuntimeOption, ExpiresIn } from '../types'
|
||||
|
||||
interface Props {
|
||||
onSubmit: (content: string, runtime: RuntimeOption, expiresIn: ExpiresIn) => void
|
||||
loading: boolean
|
||||
}
|
||||
|
||||
export default function ScriptForm({ onSubmit, loading }: Props) {
|
||||
const [content, setContent] = useState('')
|
||||
const [runtime, setRuntime] = useState<RuntimeOption>('bash')
|
||||
const [expiresIn, setExpiresIn] = useState<ExpiresIn>('24h')
|
||||
|
||||
const canSubmit = content.trim().length > 0 && content.length <= 16384 && !loading
|
||||
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
<div className="flex gap-4 flex-wrap">
|
||||
<div>
|
||||
<label className="block text-xs text-gray-500 mb-1">运行环境</label>
|
||||
<select
|
||||
value={runtime}
|
||||
onChange={(e) => setRuntime(e.target.value as RuntimeOption)}
|
||||
className="px-3 py-2 bg-gray-800 border border-gray-700 rounded-lg text-sm focus:outline-none focus:border-blue-500"
|
||||
>
|
||||
{RUNTIME_OPTIONS.map((opt) => (
|
||||
<option key={opt.value} value={opt.value}>
|
||||
{opt.label}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-xs text-gray-500 mb-1">过期时间</label>
|
||||
<select
|
||||
value={expiresIn}
|
||||
onChange={(e) => setExpiresIn(e.target.value as ExpiresIn)}
|
||||
className="px-3 py-2 bg-gray-800 border border-gray-700 rounded-lg text-sm focus:outline-none focus:border-blue-500"
|
||||
>
|
||||
{EXPIRES_OPTIONS.map((opt) => (
|
||||
<option key={opt.value} value={opt.value}>
|
||||
{opt.label}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<textarea
|
||||
value={content}
|
||||
onChange={(e) => setContent(e.target.value)}
|
||||
placeholder="在此粘贴你的脚本..."
|
||||
rows={12}
|
||||
className="w-full px-4 py-3 bg-gray-800 border border-gray-700 rounded-lg text-sm font-mono focus:outline-none focus:border-blue-500 resize-y"
|
||||
/>
|
||||
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-xs text-gray-500">
|
||||
{content.length.toLocaleString()} / 16,384 字符
|
||||
{content.length > 16384 && (
|
||||
<span className="text-red-400 ml-1">超出限制!</span>
|
||||
)}
|
||||
</span>
|
||||
|
||||
<button
|
||||
onClick={() => onSubmit(content, runtime, expiresIn)}
|
||||
disabled={!canSubmit}
|
||||
className="px-6 py-2.5 bg-blue-600 hover:bg-blue-700 disabled:bg-gray-700 disabled:text-gray-500 rounded-lg text-sm font-medium transition-colors"
|
||||
>
|
||||
{loading ? '生成中...' : '生成运行链接'}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user