返回 DeepSeek-Reasonix
ModelImageInputControl.tsx
根目录 / desktop / frontend / src / components / ModelImageInputControl.tsx
1 import { useId } from "react";
2 import { useT } from "../lib/i18n";
3 import { imageInputHardBlocked, imageInputState, type ImageInputMode } from "../lib/providerImageInput";
4 import type { ProviderModelCapabilityView } from "../lib/types";
5
6 export function ModelImageInputControl({ model, mode, capability, baseURL, fallback, disabled, onChange }: {
7 model: string; mode: ImageInputMode; capability?: ProviderModelCapabilityView;
8 baseURL?: string; fallback?: string; disabled: boolean; onChange?: (mode: ImageInputMode) => void;
9 }) {
10 const t = useT();
11 const groupName = useId();
12 const blocked = imageInputHardBlocked(baseURL, model, capability);
13 const state = blocked ? "unsupported" : imageInputState(mode, capability, fallback);
14 const status = blocked ? t("settings.imageInputProtocolBadge")
15 : mode === "on" ? t("settings.imageInputManualOn")
16 : mode === "off" ? t("settings.imageInputManualOff")
17 : capability?.automaticSource === "legacy" ? t("settings.imageInputLegacy")
18 : state === "supported" ? t("settings.imageInputSupported")
19 : state === "unsupported" ? t("settings.imageInputUnsupported") : t("settings.imageInputUnknown");
20 const statusTone = blocked ? "restricted" : mode === "on" || state === "supported" ? "supported"
21 : mode === "off" || state === "unsupported" ? "unsupported" : "unknown";
22 const options: Array<{ value: ImageInputMode; label: string }> = [
23 { value: "auto", label: t("settings.imageInputAuto") },
24 { value: "on", label: t("settings.imageInputOn") },
25 { value: "off", label: t("settings.imageInputOff") },
26 ];
27 return <div className="provider-image-input">
28 <div className="provider-image-input__head">
29 <span className="provider-image-input__label">{t("settings.imageInputLabel")}</span>
30 <div className="set-seg provider-image-input__modes" role="radiogroup" aria-label={t("settings.imageInputModeAria", { model })}>
31 {options.map((option) => {
32 const optionDisabled = disabled || !onChange || (blocked && option.value === "on");
33 return <label key={option.value} className={`set-seg__btn provider-image-input__mode${mode === option.value ? " set-seg__btn--on" : ""}${optionDisabled ? " provider-image-input__mode--disabled" : ""}`}>
34 <input className="sr-only" type="radio" name={groupName} value={option.value} checked={mode === option.value}
35 disabled={optionDisabled} onChange={() => onChange?.(option.value)} />
36 <span>{option.label}</span>
37 </label>;
38 })}
39 </div>
40 </div>
41 <div className="provider-image-input__meta">
42 <span className={`provider-image-input__status provider-image-input__status--${statusTone}`}>
43 <span className="provider-image-input__status-dot" aria-hidden="true" />{status}
44 </span>
45 {(blocked || (mode === "auto" && state === "unknown")) && (
46 <span className="provider-image-input__detail">{blocked ? t("settings.imageInputProtocolBlocked") : t("settings.imageInputUnknownHint")}</span>
47 )}
48 </div>
49 </div>;
50 }
51
51 lines Plain Text