feat: 移除 JSON 格式化页面,更新 MTR 表单和工具列表
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:
2025-08-14 01:39:58 +08:00
parent 330cd84beb
commit c133d1bbfe
5 changed files with 51 additions and 105 deletions

View File

@ -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">
&larr; 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>
);
}

View File

@ -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>

View File

@ -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 = {

View File

@ -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",
},
}
];