Files
ttstd-infinite-canvas/web/src/components/skills/skill-runtime-picker.tsx

58 lines
2.0 KiB
TypeScript

import { useEffect, useMemo, useState } from "react";
import { Select } from "antd";
import { listAddedSkills, type Skill } from "@/services/api/skills";
import { SKILL_RUNTIME_PROFILES, type SkillRuntimeProfile } from "@/services/skill-runtime";
export function useSkillRuntimeCatalog() {
const [skills, setSkills] = useState<Skill[]>([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
let cancelled = false;
listAddedSkills()
.then((result) => {
if (!cancelled) setSkills(result.skills.filter((skill) => skill.isAdded));
})
.catch(() => {
if (!cancelled) setSkills([]);
})
.finally(() => {
if (!cancelled) setLoading(false);
});
return () => {
cancelled = true;
};
}, []);
return { skills, loading };
}
export function SkillRuntimePicker({ skills, loading, value, onChange, placeholder = "选择本次生成使用的技能", profile = "canvas" }: { skills: Skill[]; loading?: boolean; value: string[]; onChange: (skillIds: string[]) => void; placeholder?: string; profile?: SkillRuntimeProfile }) {
const options = useMemo(
() => skills.map((skill) => ({ value: skill.skillId, label: skill.skillName, title: skill.description })),
[skills],
);
const maxSkills = SKILL_RUNTIME_PROFILES[profile].maxSkills;
return (
<Select
className="w-full"
style={{ width: "100%" }}
mode="multiple"
allowClear
showSearch
maxCount={maxSkills || undefined}
maxTagCount="responsive"
loading={loading}
value={value}
placeholder={placeholder}
optionFilterProp="label"
options={options}
onChange={onChange}
notFoundContent={loading ? "正在读取技能库" : "暂无已加入的技能"}
aria-label="本次生成使用的技能"
/>
);
}