mirror of
https://github.com/snowykami/web-tools.git
synced 2025-09-03 19:56:27 +00:00
feat: 移除 JSON 格式化页面,更新 MTR 表单和工具列表
All checks were successful
Build and Push Container Image, Deploy to Host / build-and-push-and-deploy (push) Successful in 2m52s
All checks were successful
Build and Push Container Image, Deploy to Host / build-and-push-and-deploy (push) Successful in 2m52s
This commit is contained in:
@ -1,76 +0,0 @@
|
||||
"use client";
|
||||
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Textarea } from "@/components/ui/textarea";
|
||||
import { useState } from "react";
|
||||
import Link from "next/link";
|
||||
|
||||
export default function JsonFormatterPage() {
|
||||
const [input, setInput] = useState("");
|
||||
const [output, setOutput] = useState("");
|
||||
const [error, setError] = useState("");
|
||||
|
||||
const formatJson = () => {
|
||||
try {
|
||||
const formatted = JSON.stringify(JSON.parse(input), null, 2);
|
||||
setOutput(formatted);
|
||||
setError("");
|
||||
} catch (e: any) {
|
||||
setError("Invalid JSON: " + e.message);
|
||||
setOutput("");
|
||||
}
|
||||
};
|
||||
|
||||
const copyToClipboard = () => {
|
||||
navigator.clipboard.writeText(output);
|
||||
};
|
||||
|
||||
const clearText = () => {
|
||||
setInput("");
|
||||
setOutput("");
|
||||
setError("");
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="container mx-auto p-4">
|
||||
<header className="mb-8">
|
||||
<Link href="/" className="text-blue-500 hover:underline">
|
||||
← Back to Home
|
||||
</Link>
|
||||
<h1 className="text-4xl font-bold mt-4">JSON Formatter</h1>
|
||||
</header>
|
||||
<main className="grid md:grid-cols-2 gap-4">
|
||||
<div className="flex flex-col gap-2">
|
||||
<label htmlFor="json-input">Input</label>
|
||||
<Textarea
|
||||
id="json-input"
|
||||
value={input}
|
||||
onChange={(e) => setInput(e.target.value)}
|
||||
placeholder="Paste your JSON here"
|
||||
className="h-96"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-col gap-2">
|
||||
<label htmlFor="json-output">Output</label>
|
||||
<Textarea
|
||||
id="json-output"
|
||||
value={output}
|
||||
readOnly
|
||||
placeholder="Formatted JSON will appear here"
|
||||
className="h-96"
|
||||
/>
|
||||
</div>
|
||||
</main>
|
||||
<footer className="mt-4 flex gap-2">
|
||||
<Button onClick={formatJson}>Format JSON</Button>
|
||||
<Button onClick={copyToClipboard} disabled={!output}>
|
||||
Copy to Clipboard
|
||||
</Button>
|
||||
<Button onClick={clearText} variant="destructive">
|
||||
Clear
|
||||
</Button>
|
||||
</footer>
|
||||
{error && <p className="text-red-500 mt-4">{error}</p>}
|
||||
</div>
|
||||
);
|
||||
}
|
@ -18,7 +18,7 @@ import {
|
||||
import { Separator } from "@/components/ui/separator";
|
||||
import { Switch } from "@/components/ui/switch";
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
||||
import { BoardData, TrainType } from "./types";
|
||||
import { BoardData, ThemeInfo, TrainType } from "./types";
|
||||
|
||||
interface BoardFormProps {
|
||||
data: BoardData;
|
||||
@ -30,22 +30,38 @@ export function BoardForm({ data, setData }: BoardFormProps) {
|
||||
setData({ ...data, statusBar: { ...data.statusBar, [field]: value } });
|
||||
};
|
||||
|
||||
const handleTrainChange = (index: number, field: string, value: any) => {
|
||||
type TrainField =
|
||||
| "platform"
|
||||
| "arrival"
|
||||
| "type"
|
||||
| "destination.en"
|
||||
| "destination.cn";
|
||||
|
||||
const handleTrainChange = (
|
||||
index: number,
|
||||
field: TrainField,
|
||||
value: string | TrainType
|
||||
) => {
|
||||
const newTrains = [...data.trains];
|
||||
const trainToUpdate = { ...newTrains[index] };
|
||||
|
||||
if (field === "destination.en" || field === "destination.cn") {
|
||||
const [, subkey] = field.split(".");
|
||||
(trainToUpdate.destination as any)[subkey] = value;
|
||||
const [, subkey] = field.split(".") as ["destination", "en" | "cn"];
|
||||
trainToUpdate.destination[subkey] = value as string;
|
||||
} else if (field === "type") {
|
||||
trainToUpdate[field] = value as TrainType;
|
||||
} else {
|
||||
(trainToUpdate as any)[field] = value;
|
||||
trainToUpdate[field as "platform" | "arrival"] = value;
|
||||
}
|
||||
|
||||
newTrains[index] = trainToUpdate;
|
||||
setData({ ...data, trains: newTrains });
|
||||
};
|
||||
|
||||
const handleThemeChange = (field: string, value: string) => {
|
||||
const handleThemeChange = (
|
||||
field: keyof Omit<ThemeInfo, "trainTypeColors"> | "trainTypeColors",
|
||||
value: string | Record<TrainType, string>
|
||||
) => {
|
||||
setData({ ...data, theme: { ...data.theme, [field]: value } });
|
||||
};
|
||||
|
||||
@ -265,11 +281,11 @@ export function BoardForm({ data, setData }: BoardFormProps) {
|
||||
type="color"
|
||||
value={data.theme.trainTypeColors[type]}
|
||||
onChange={(e) => {
|
||||
const newColors = {
|
||||
const newColors: Record<TrainType, string> = {
|
||||
...data.theme.trainTypeColors,
|
||||
[type]: e.target.value,
|
||||
};
|
||||
handleThemeChange("trainTypeColors", newColors as any);
|
||||
handleThemeChange("trainTypeColors", newColors);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
@ -19,7 +19,7 @@ import { ColorPicker } from "@/components/ui/color-picker";
|
||||
import { Separator } from "@/components/ui/separator";
|
||||
import { Switch } from "@/components/ui/switch";
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
||||
import { BoardData, TrainType } from "@/app/rt-guide/types";
|
||||
import { BoardData, ThemeInfo, TrainType } from "@/app/rt-guide/types";
|
||||
|
||||
interface MtrBoardFormProps {
|
||||
data: BoardData;
|
||||
@ -31,22 +31,38 @@ export function MtrBoardForm({ data, setData }: MtrBoardFormProps) {
|
||||
setData({ ...data, statusBar: { ...data.statusBar, [field]: value } });
|
||||
};
|
||||
|
||||
const handleTrainChange = (index: number, field: string, value: any) => {
|
||||
type TrainField =
|
||||
| "platform"
|
||||
| "arrival"
|
||||
| "type"
|
||||
| "destination.en"
|
||||
| "destination.cn";
|
||||
|
||||
const handleTrainChange = (
|
||||
index: number,
|
||||
field: TrainField,
|
||||
value: string | TrainType
|
||||
) => {
|
||||
const newTrains = [...data.trains];
|
||||
const trainToUpdate = { ...newTrains[index] };
|
||||
|
||||
if (field === "destination.en" || field === "destination.cn") {
|
||||
const [, subkey] = field.split(".");
|
||||
(trainToUpdate.destination as any)[subkey] = value;
|
||||
const [, subkey] = field.split(".") as ["destination", "en" | "cn"];
|
||||
trainToUpdate.destination[subkey] = value as string;
|
||||
} else if (field === "type") {
|
||||
trainToUpdate[field] = value as TrainType;
|
||||
} else {
|
||||
(trainToUpdate as any)[field] = value;
|
||||
trainToUpdate[field as "platform" | "arrival"] = value;
|
||||
}
|
||||
|
||||
newTrains[index] = trainToUpdate;
|
||||
setData({ ...data, trains: newTrains });
|
||||
};
|
||||
|
||||
const handleThemeChange = (field: string, value: any) => {
|
||||
const handleThemeChange = (
|
||||
field: keyof Omit<ThemeInfo, "trainTypeColors"> | "trainTypeColors",
|
||||
value: string | Record<TrainType, string>
|
||||
) => {
|
||||
setData({ ...data, theme: { ...data.theme, [field]: value } });
|
||||
};
|
||||
|
||||
@ -250,10 +266,10 @@ export function MtrBoardForm({ data, setData }: MtrBoardFormProps) {
|
||||
(type) => (
|
||||
<ColorPicker
|
||||
key={type}
|
||||
label={type === "local" ? "普通" :
|
||||
type === "express" ? "特快" :
|
||||
type === "rapid" ? "快速" :
|
||||
type === "through" ? "直通" : type}
|
||||
label={type === "local" ? "普通" :
|
||||
type === "express" ? "直快" :
|
||||
type === "rapid" ? "快速" :
|
||||
type === "through" ? "贯通" : type}
|
||||
value={data.theme.trainTypeColors[type]}
|
||||
onChange={(value) => {
|
||||
const newColors = {
|
||||
|
@ -9,15 +9,5 @@ export const tools: Tool[] = [
|
||||
title: "Rail Transit Guide",
|
||||
description: "轨道交通导视生成器",
|
||||
href: "/rt-guide",
|
||||
},
|
||||
{
|
||||
title: "URL Encoder/Decoder",
|
||||
description: "Encode or decode URLs and strings.",
|
||||
href: "/url-encoder",
|
||||
},
|
||||
{
|
||||
title: "Base64 Encoder/Decoder",
|
||||
description: "Encode or decode strings to and from Base64.",
|
||||
href: "/base64-encoder",
|
||||
},
|
||||
}
|
||||
];
|
||||
|
Reference in New Issue
Block a user