feat(mcp): show inline duplicate ID error and block submit in add mode
- Display red hint next to title when ID exists - Disable Add/Save button and prevent submit on duplicate - Accept existing IDs via prop for real-time validation - Remove overwrite confirmation dialog on add - i18n: add duplicate-ID error strings and remove unused overwrite prompt - files: - src/components/mcp/McpFormModal.tsx - src/components/mcp/McpPanel.tsx - src/i18n/locales/en.json - src/i18n/locales/zh.json
This commit is contained in:
@@ -11,6 +11,7 @@ interface McpFormModalProps {
|
||||
initialData?: McpServer;
|
||||
onSave: (id: string, server: McpServer) => Promise<void>;
|
||||
onClose: () => void;
|
||||
existingIds?: string[];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -38,6 +39,7 @@ const McpFormModal: React.FC<McpFormModalProps> = ({
|
||||
initialData,
|
||||
onSave,
|
||||
onClose,
|
||||
existingIds = [],
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const [formId, setFormId] = useState(editingId || "");
|
||||
@@ -50,10 +52,19 @@ const McpFormModal: React.FC<McpFormModalProps> = ({
|
||||
const [jsonError, setJsonError] = useState("");
|
||||
const [saving, setSaving] = useState(false);
|
||||
const [isWizardOpen, setIsWizardOpen] = useState(false);
|
||||
const [idError, setIdError] = useState("");
|
||||
|
||||
// 编辑模式下禁止修改 ID
|
||||
const isEditing = !!editingId;
|
||||
|
||||
const handleIdChange = (value: string) => {
|
||||
setFormId(value);
|
||||
if (!isEditing) {
|
||||
const exists = existingIds.includes(value.trim());
|
||||
setIdError(exists ? t("mcp.error.idExists") : "");
|
||||
}
|
||||
};
|
||||
|
||||
const handleJsonChange = (value: string) => {
|
||||
setFormJson(value);
|
||||
|
||||
@@ -104,6 +115,12 @@ const McpFormModal: React.FC<McpFormModalProps> = ({
|
||||
return;
|
||||
}
|
||||
|
||||
// 新增模式:阻止提交重名 ID
|
||||
if (!isEditing && existingIds.includes(formId.trim())) {
|
||||
setIdError(t("mcp.error.idExists"));
|
||||
return;
|
||||
}
|
||||
|
||||
// 验证 JSON
|
||||
const currentJsonError = validateJson(formJson);
|
||||
setJsonError(currentJsonError);
|
||||
@@ -186,14 +203,21 @@ const McpFormModal: React.FC<McpFormModalProps> = ({
|
||||
<div className="p-6 space-y-4">
|
||||
{/* ID (标题) */}
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
|
||||
{t("mcp.form.title")} <span className="text-red-500">*</span>
|
||||
</label>
|
||||
<div className="flex items-center justify-between mb-2">
|
||||
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300">
|
||||
{t("mcp.form.title")} <span className="text-red-500">*</span>
|
||||
</label>
|
||||
{!isEditing && idError && (
|
||||
<span className="text-xs text-red-500 dark:text-red-400">
|
||||
{idError}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
<input
|
||||
className={inputStyles.text}
|
||||
placeholder={t("mcp.form.titlePlaceholder")}
|
||||
value={formId}
|
||||
onChange={(e) => setFormId(e.target.value)}
|
||||
onChange={(e) => handleIdChange(e.target.value)}
|
||||
disabled={isEditing}
|
||||
/>
|
||||
</div>
|
||||
@@ -247,7 +271,7 @@ const McpFormModal: React.FC<McpFormModalProps> = ({
|
||||
</button>
|
||||
<button
|
||||
onClick={handleSubmit}
|
||||
disabled={saving}
|
||||
disabled={saving || (!isEditing && !!idError)}
|
||||
className={buttonStyles.primary}
|
||||
>
|
||||
<Save size={16} />
|
||||
|
||||
Reference in New Issue
Block a user