Initial commit
This commit is contained in:
@@ -0,0 +1,118 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { Button, Space, Typography, message } from 'antd';
|
||||
import { FormatPainterOutlined, CompressOutlined, CheckCircleOutlined } from '@ant-design/icons';
|
||||
import type { Scale } from '../../../types';
|
||||
|
||||
const { Text } = Typography;
|
||||
|
||||
interface Props {
|
||||
scale: Scale;
|
||||
setScale: (scale: Scale) => void;
|
||||
}
|
||||
|
||||
const JsonTab: React.FC<Props> = ({ scale, setScale }) => {
|
||||
const [jsonText, setJsonText] = useState('');
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
// Sync from scale to text
|
||||
useEffect(() => {
|
||||
setJsonText(JSON.stringify(scale, null, 2));
|
||||
setError(null);
|
||||
}, [scale]);
|
||||
|
||||
const handleFormat = () => {
|
||||
try {
|
||||
const parsed = JSON.parse(jsonText);
|
||||
setJsonText(JSON.stringify(parsed, null, 2));
|
||||
setError(null);
|
||||
message.success('已格式化');
|
||||
} catch (e: any) {
|
||||
setError('JSON格式错误: ' + e.message);
|
||||
}
|
||||
};
|
||||
|
||||
const handleCompress = () => {
|
||||
try {
|
||||
const parsed = JSON.parse(jsonText);
|
||||
setJsonText(JSON.stringify(parsed));
|
||||
setError(null);
|
||||
message.success('已压缩');
|
||||
} catch (e: any) {
|
||||
setError('JSON格式错误: ' + e.message);
|
||||
}
|
||||
};
|
||||
|
||||
const handleApply = () => {
|
||||
try {
|
||||
const parsed = JSON.parse(jsonText);
|
||||
if (!parsed.meta?.id) { setError('缺少 meta.id 字段'); return; }
|
||||
setScale(parsed);
|
||||
setError(null);
|
||||
message.success('已应用到编辑器');
|
||||
} catch (e: any) {
|
||||
setError('JSON格式错误: ' + e.message);
|
||||
}
|
||||
};
|
||||
|
||||
const handleTextChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
|
||||
setJsonText(e.target.value);
|
||||
// Try to parse to show errors
|
||||
try {
|
||||
JSON.parse(e.target.value);
|
||||
setError(null);
|
||||
} catch (e: any) {
|
||||
setError('JSON格式错误');
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 12 }}>
|
||||
<Space>
|
||||
<Button icon={<FormatPainterOutlined />} onClick={handleFormat}>格式化</Button>
|
||||
<Button icon={<CompressOutlined />} onClick={handleCompress}>压缩</Button>
|
||||
<Button icon={<CheckCircleOutlined />} type="primary" onClick={handleApply}
|
||||
style={{ background: '#2563eb', border: 'none' }}>
|
||||
应用到编辑器
|
||||
</Button>
|
||||
</Space>
|
||||
{error ? (
|
||||
<Text type="danger" style={{ fontSize: 12 }}>{error}</Text>
|
||||
) : (
|
||||
<Text type="success" style={{ fontSize: 12 }}>✓ 有效JSON</Text>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<textarea
|
||||
value={jsonText}
|
||||
onChange={handleTextChange}
|
||||
style={{
|
||||
width: '100%',
|
||||
height: 600,
|
||||
fontFamily: 'Consolas, Monaco, "Courier New", monospace',
|
||||
fontSize: 13,
|
||||
lineHeight: 1.5,
|
||||
padding: 16,
|
||||
border: error ? '2px solid #ef4444' : '1px solid #e2e8f0',
|
||||
borderRadius: 8,
|
||||
background: '#fafbfc',
|
||||
color: '#0f172a',
|
||||
resize: 'vertical',
|
||||
outline: 'none',
|
||||
}}
|
||||
spellCheck={false}
|
||||
/>
|
||||
|
||||
<div style={{ marginTop: 8, display: 'flex', justifyContent: 'space-between' }}>
|
||||
<Text type="secondary" style={{ fontSize: 12 }}>
|
||||
修改JSON后点击"应用到编辑器"同步到可视化编辑
|
||||
</Text>
|
||||
<Text type="secondary" style={{ fontSize: 12 }}>
|
||||
{jsonText.length} 字符
|
||||
</Text>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default JsonTab;
|
||||
Reference in New Issue
Block a user