Initial commit: Web2App static site to Tauri platform

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-05-27 21:56:23 +08:00
commit 8298278c10
64 changed files with 11509 additions and 0 deletions

78
web/src/pages/Upload.tsx Normal file
View File

@@ -0,0 +1,78 @@
import { FormEvent, useState } from "react";
import { useNavigate } from "react-router-dom";
import { createBuild } from "../api";
export default function Upload() {
const navigate = useNavigate();
const [appName, setAppName] = useState("");
const [identifier, setIdentifier] = useState("");
const [file, setFile] = useState<File | null>(null);
const [loading, setLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
async function onSubmit(event: FormEvent) {
event.preventDefault();
if (!file) {
setError("请选择 zip 文件");
return;
}
setLoading(true);
setError(null);
try {
const formData = new FormData();
formData.append("file", file);
formData.append("appName", appName);
if (identifier.trim()) {
formData.append("identifier", identifier.trim());
}
const result = await createBuild(formData);
navigate(`/jobs/${result.id}`);
} catch (err) {
setError(err instanceof Error ? err.message : "上传失败");
} finally {
setLoading(false);
}
}
return (
<section className="card">
<h2></h2>
<p className="hint"> index.html 50MB</p>
<form className="form" onSubmit={onSubmit}>
<label>
<input
value={appName}
onChange={(e) => setAppName(e.target.value)}
placeholder="My App"
required
/>
</label>
<label>
Bundle ID
<input
value={identifier}
onChange={(e) => setIdentifier(e.target.value)}
placeholder="com.example.myapp"
/>
</label>
<label>
zip
<input
type="file"
accept=".zip,application/zip"
onChange={(e) => setFile(e.target.files?.[0] ?? null)}
required
/>
</label>
{error ? <p className="error">{error}</p> : null}
<button type="submit" disabled={loading}>
{loading ? "上传并触发构建..." : "开始构建"}
</button>
</form>
</section>
);
}