feat: 分类/变体体系 + 用户认证 + 管理后台

- 运行时分类体系:Shell/Python/JavaScript/Ruby/PHP 各含变体
- 用户注册/登录(JWT + bcrypt),首个注册用户为管理员
- 管理后台 /admin 动态管理分类和变体
- 脚本市场支持按分类筛选
- CodeMirror 语言模式根据分类名称自动切换
- 结果页展示该分类下所有变体的运行命令
- source 命令变体用于 Shell 类继承环境变量

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-05-29 15:02:20 +08:00
parent 58a80cb196
commit 5414c9c865
24 changed files with 1309 additions and 295 deletions

View File

@@ -1,5 +1,5 @@
import { CreateScriptResponse, isShellRuntime, getSourceCommand } from '../types'
import CommandCard from './CommandCard'
import { CreateScriptResponse } from '../types'
import { Link } from 'react-router-dom'
interface Props {
result: CreateScriptResponse
@@ -7,10 +7,6 @@ interface Props {
}
export default function ResultCard({ result, onReset }: Props) {
const detailUrl = `${window.location.origin}/s/${result.id}`
const showSource = isShellRuntime(result.runtime)
const sourceCommand = showSource ? getSourceCommand(result.url, result.runtime) : null
return (
<div className="space-y-6">
<div className="text-center">
@@ -20,21 +16,6 @@ export default function ResultCard({ result, onReset }: Props) {
</h2>
</div>
<CommandCard command={result.command} />
{showSource && sourceCommand && (
<div>
<p className="text-xs text-gray-500 mb-2">
使 shell
</p>
<CommandCard
command={sourceCommand}
label="继承环境变量"
variant="secondary"
/>
</div>
)}
<div className="bg-gray-800/50 border border-gray-700 rounded-lg p-4 space-y-3">
<div className="flex justify-between text-sm">
<span className="text-gray-400"></span>
@@ -45,8 +26,10 @@ export default function ResultCard({ result, onReset }: Props) {
<span className="font-mono text-blue-400">{result.id}</span>
</div>
<div className="flex justify-between text-sm">
<span className="text-gray-400"></span>
<span>{result.runtime}</span>
<span className="text-gray-400"></span>
<a href={result.url} target="_blank" rel="noreferrer" className="font-mono text-blue-400 hover:underline break-all text-right max-w-[70%]">
{result.url}
</a>
</div>
<div className="flex justify-between text-sm">
<span className="text-gray-400"></span>
@@ -73,24 +56,12 @@ export default function ResultCard({ result, onReset }: Props) {
>
</button>
<a
href={detailUrl}
target="_blank"
rel="noreferrer"
<Link
to={`/s/${result.id}`}
className="px-4 py-2 bg-blue-600 hover:bg-blue-700 rounded-lg text-sm transition-colors"
>
</a>
{result.status === 'published' && (
<a
href={`${window.location.origin}/market`}
target="_blank"
rel="noreferrer"
className="px-4 py-2 bg-green-600/80 hover:bg-green-600 rounded-lg text-sm transition-colors"
>
</a>
)}
</Link>
</div>
</div>
)