import React, { useState, useEffect, useCallback } from 'react'; import { useTranslation } from 'react-i18next'; import { Space, Button, Form, Card, Typography, Banner, Row, Col, InputNumber, Switch, Select, Input, } from '@douyinfe/semi-ui'; import { IconCode, IconEdit, IconPlus, IconDelete, IconSetting, } from '@douyinfe/semi-icons'; const { Text } = Typography; const JSONEditor = ({ value = '', onChange, field, label, placeholder, extraText, showClear = true, template, templateLabel, editorType = 'keyValue', // keyValue, object, region autosize = true, rules = [], formApi = null, ...props }) => { const { t } = useTranslation(); // 初始化JSON数据 const [jsonData, setJsonData] = useState(() => { // 初始化时解析JSON数据 if (value && value.trim()) { try { const parsed = JSON.parse(value); return parsed; } catch (error) { return {}; } } return {}; }); // 根据键数量决定默认编辑模式 const [editMode, setEditMode] = useState(() => { // 如果初始JSON数据的键数量大于10个,则默认使用手动模式 if (value && value.trim()) { try { const parsed = JSON.parse(value); const keyCount = Object.keys(parsed).length; return keyCount > 10 ? 'manual' : 'visual'; } catch (error) { // JSON无效时默认显示手动编辑模式 return 'manual'; } } return 'visual'; }); const [jsonError, setJsonError] = useState(''); // 数据同步 - 当value变化时总是更新jsonData(如果JSON有效) useEffect(() => { try { const parsed = value && value.trim() ? JSON.parse(value) : {}; setJsonData(parsed); setJsonError(''); } catch (error) { console.log('JSON解析失败:', error.message); setJsonError(error.message); // JSON格式错误时不更新jsonData } }, [value]); // 处理可视化编辑的数据变化 const handleVisualChange = useCallback((newData) => { setJsonData(newData); setJsonError(''); const jsonString = Object.keys(newData).length === 0 ? '' : JSON.stringify(newData, null, 2); // 通过formApi设置值(如果提供的话) if (formApi && field) { formApi.setValue(field, jsonString); } onChange?.(jsonString); }, [onChange, formApi, field]); // 处理手动编辑的数据变化 const handleManualChange = useCallback((newValue) => { onChange?.(newValue); // 验证JSON格式 if (newValue && newValue.trim()) { try { const parsed = JSON.parse(newValue); setJsonError(''); // 预先准备可视化数据,但不立即应用 // 这样切换到可视化模式时数据已经准备好了 } catch (error) { setJsonError(error.message); } } else { setJsonError(''); } }, [onChange]); // 切换编辑模式 const toggleEditMode = useCallback(() => { if (editMode === 'visual') { // 从可视化模式切换到手动模式 setEditMode('manual'); } else { // 从手动模式切换到可视化模式,需要验证JSON try { const parsed = value && value.trim() ? JSON.parse(value) : {}; setJsonData(parsed); setJsonError(''); setEditMode('visual'); } catch (error) { setJsonError(error.message); // JSON格式错误时不切换模式 return; } } }, [editMode, value]); // 添加键值对 const addKeyValue = useCallback(() => { const newData = { ...jsonData }; const keys = Object.keys(newData); let newKey = 'key'; let counter = 1; while (newData.hasOwnProperty(newKey)) { newKey = `key${counter}`; counter++; } newData[newKey] = ''; handleVisualChange(newData); }, [jsonData, handleVisualChange]); // 删除键值对 const removeKeyValue = useCallback((keyToRemove) => { const newData = { ...jsonData }; delete newData[keyToRemove]; handleVisualChange(newData); }, [jsonData, handleVisualChange]); // 更新键名 const updateKey = useCallback((oldKey, newKey) => { if (oldKey === newKey) return; const newData = { ...jsonData }; const value = newData[oldKey]; delete newData[oldKey]; newData[newKey] = value; handleVisualChange(newData); }, [jsonData, handleVisualChange]); // 更新值 const updateValue = useCallback((key, newValue) => { const newData = { ...jsonData }; newData[key] = newValue; handleVisualChange(newData); }, [jsonData, handleVisualChange]); // 填入模板 const fillTemplate = useCallback(() => { if (template) { const templateString = JSON.stringify(template, null, 2); // 通过formApi设置值(如果提供的话) if (formApi && field) { formApi.setValue(field, templateString); } // 无论哪种模式都要更新值 onChange?.(templateString); // 如果是可视化模式,同时更新jsonData if (editMode === 'visual') { setJsonData(template); } // 清除错误状态 setJsonError(''); } }, [template, onChange, editMode, formApi, field]); // 渲染键值对编辑器 const renderKeyValueEditor = () => { if (typeof jsonData !== 'object' || jsonData === null) { return (