mirror of
https://github.com/nonebot/nonebot2.git
synced 2025-07-27 16:21:28 +00:00
Some checks failed
Code Coverage / Test Coverage (pydantic-v1, ubuntu-latest, 3.10) (push) Failing after 6m39s
Code Coverage / Test Coverage (pydantic-v1, ubuntu-latest, 3.11) (push) Failing after 4m44s
Code Coverage / Test Coverage (pydantic-v1, ubuntu-latest, 3.12) (push) Failing after 5m2s
Code Coverage / Test Coverage (pydantic-v1, ubuntu-latest, 3.9) (push) Failing after 4m31s
Code Coverage / Test Coverage (pydantic-v2, ubuntu-latest, 3.10) (push) Failing after 5m1s
Code Coverage / Test Coverage (pydantic-v2, ubuntu-latest, 3.11) (push) Failing after 2m23s
Code Coverage / Test Coverage (pydantic-v2, ubuntu-latest, 3.12) (push) Failing after 4m30s
Code Coverage / Test Coverage (pydantic-v2, ubuntu-latest, 3.9) (push) Failing after 4m19s
Pyright Lint / Pyright Lint (pydantic-v1) (push) Failing after 4m33s
Ruff Lint / Ruff Lint (push) Successful in 25s
Pyright Lint / Pyright Lint (pydantic-v2) (push) Failing after 4m47s
Site Deploy / publish (push) Failing after 4m9s
Code Coverage / Test Coverage (pydantic-v1, macos-latest, 3.10) (push) Has been cancelled
Code Coverage / Test Coverage (pydantic-v1, macos-latest, 3.11) (push) Has been cancelled
Code Coverage / Test Coverage (pydantic-v1, macos-latest, 3.12) (push) Has been cancelled
Code Coverage / Test Coverage (pydantic-v1, macos-latest, 3.9) (push) Has been cancelled
Code Coverage / Test Coverage (pydantic-v1, windows-latest, 3.10) (push) Has been cancelled
Code Coverage / Test Coverage (pydantic-v1, windows-latest, 3.11) (push) Has been cancelled
Code Coverage / Test Coverage (pydantic-v1, windows-latest, 3.12) (push) Has been cancelled
Code Coverage / Test Coverage (pydantic-v1, windows-latest, 3.9) (push) Has been cancelled
Code Coverage / Test Coverage (pydantic-v2, macos-latest, 3.10) (push) Has been cancelled
Code Coverage / Test Coverage (pydantic-v2, macos-latest, 3.11) (push) Has been cancelled
Code Coverage / Test Coverage (pydantic-v2, macos-latest, 3.12) (push) Has been cancelled
Code Coverage / Test Coverage (pydantic-v2, macos-latest, 3.9) (push) Has been cancelled
Code Coverage / Test Coverage (pydantic-v2, windows-latest, 3.10) (push) Has been cancelled
Code Coverage / Test Coverage (pydantic-v2, windows-latest, 3.11) (push) Has been cancelled
Code Coverage / Test Coverage (pydantic-v2, windows-latest, 3.12) (push) Has been cancelled
Code Coverage / Test Coverage (pydantic-v2, windows-latest, 3.9) (push) Has been cancelled
163 lines
4.0 KiB
TypeScript
163 lines
4.0 KiB
TypeScript
import React, { useEffect, useState } from "react";
|
|
|
|
import clsx from "clsx";
|
|
|
|
import "./styles.css";
|
|
|
|
import type { Resource } from "@/libs/store";
|
|
import { fetchRegistryData } from "@/libs/store";
|
|
|
|
import TagFormItem from "./Items/Tag";
|
|
|
|
import type { Tag as TagType } from "@/types/tag";
|
|
|
|
export type FormItemData = {
|
|
type: string;
|
|
name: string;
|
|
labelText: string;
|
|
};
|
|
|
|
export type FormItemGroup = {
|
|
name: string;
|
|
items: FormItemData[];
|
|
};
|
|
|
|
export type Props = {
|
|
children?: React.ReactNode;
|
|
type: Resource["resourceType"];
|
|
formItems: FormItemGroup[];
|
|
handleSubmit: (result: Record<string, string>) => void;
|
|
};
|
|
|
|
export function Form({
|
|
type,
|
|
children,
|
|
formItems,
|
|
handleSubmit,
|
|
}: Props): React.ReactNode {
|
|
const [currentStep, setCurrentStep] = useState<number>(0);
|
|
const [result, setResult] = useState<Record<string, string>>({});
|
|
const [allowTags, setAllowTags] = useState<TagType[]>([]);
|
|
|
|
// load tags asynchronously
|
|
useEffect(() => {
|
|
fetchRegistryData(type)
|
|
.then((data) =>
|
|
setAllowTags(
|
|
data
|
|
.filter((item) => item.tags.length > 0)
|
|
.map((ele) => ele.tags)
|
|
.flat()
|
|
)
|
|
)
|
|
.catch((e) => {
|
|
console.error(e);
|
|
});
|
|
}, [type]);
|
|
|
|
const setFormValue = (key: string, value: string) => {
|
|
setResult({ ...result, [key]: value });
|
|
};
|
|
|
|
const handleNextStep = () => {
|
|
const currentStepNames = formItems[currentStep].items.map(
|
|
(item) => item.name
|
|
);
|
|
if (currentStepNames.every((name) => result[name])) {
|
|
setCurrentStep(currentStep + 1);
|
|
} else {
|
|
}
|
|
};
|
|
const onPrev = () => currentStep > 0 && setCurrentStep(currentStep - 1);
|
|
const onNext = () =>
|
|
currentStep < formItems.length - 1
|
|
? handleNextStep()
|
|
: handleSubmit(result);
|
|
|
|
return (
|
|
<>
|
|
<ul className="steps">
|
|
{formItems.map((item, index) => (
|
|
<li
|
|
key={index}
|
|
className={clsx("step", currentStep === index && "step-primary")}
|
|
>
|
|
{item.name}
|
|
</li>
|
|
))}
|
|
</ul>
|
|
<div className="form-control w-full min-h-[300px]">
|
|
{children ||
|
|
formItems[currentStep].items.map((item) => (
|
|
<FormItem
|
|
key={item.name}
|
|
type={item.type}
|
|
name={item.name}
|
|
labelText={item.labelText}
|
|
allowTags={allowTags}
|
|
result={result}
|
|
setResult={setFormValue}
|
|
/>
|
|
))}
|
|
</div>
|
|
<div className="flex justify-between">
|
|
<button
|
|
className={clsx("form-btn form-btn-prev", {
|
|
"form-btn-hidden": currentStep === 0,
|
|
})}
|
|
onClick={onPrev}
|
|
>
|
|
上一步
|
|
</button>
|
|
<button className="form-btn form-btn-next" onClick={onNext}>
|
|
{currentStep === formItems.length - 1 ? "提交" : "下一步"}
|
|
</button>
|
|
</div>
|
|
</>
|
|
);
|
|
}
|
|
|
|
export function FormItem({
|
|
type,
|
|
name,
|
|
labelText,
|
|
allowTags,
|
|
result,
|
|
setResult,
|
|
}: FormItemData & {
|
|
allowTags: TagType[];
|
|
result: Record<string, string>;
|
|
setResult: (key: string, value: string) => void;
|
|
}): React.ReactNode {
|
|
return (
|
|
<>
|
|
<label className="label">
|
|
<span className="label-text">{labelText}</span>
|
|
</label>
|
|
{type === "text" && (
|
|
<input
|
|
value={result[name] || ""}
|
|
type="text"
|
|
name={name}
|
|
onChange={(e) => setResult(name, e.target.value)}
|
|
placeholder="请输入"
|
|
className={clsx("form-input", {
|
|
"form-input-error": !result[name],
|
|
})}
|
|
/>
|
|
)}
|
|
{type === "text" && !result[name] && (
|
|
<label className="label">
|
|
<span className="form-label form-label-error">请输入{labelText}</span>
|
|
</label>
|
|
)}
|
|
{type === "tag" && (
|
|
<TagFormItem
|
|
allowTags={allowTags}
|
|
onTagUpdate={(tags) => setResult(name, JSON.stringify(tags))}
|
|
/>
|
|
)}
|
|
</>
|
|
);
|
|
}
|