基于 @uiw/react-codemirror 封装的 json 编辑器,支持格式化和 json 语法校验

 
import React, { useEffect, useState } from 'react';
import { intl } from '@sc/intl';
import CodeMirror from '@uiw/react-codemirror';
import { Button } from 'antd';
import { ErrorFilled } from '@antd/icons';
import { javascript } from '@codemirror/lang-javascript';
import styles from './index.less';

interface IProps {
  value: string;
  /** onChange 回调, 输出 json */
  onChange?: (json: string) => void;
  /**占位符 */
  placeholder?: string;
  /**编辑器高度 */
  height?: string;
  /**只读模式 */
  readonly?: boolean;
}

export default function JsonInput({
  value = '',
  placeholder,
  height,
  readonly,
  onChange,
}: IProps) {
  const [jsonString, setJsonString] = useState(value);
  const [errorTips, setErrorTips] = useState('');
  const verifyJson = () => {
    if (jsonString === '') return;
    try {
      const result = JSON.stringify(JSON.parse(jsonString), null, '\t');
      setErrorTips('');
      return result;
    } catch (error) {
      setErrorTips(intl('json语法有错误,请修改'));
    }
  };
  return (
    <div className={styles['json-container']}>
      <div className={styles['json-input']}>
        <CodeMirror
          className={styles.json}
          value={jsonString}
          height={height}
          theme={'light'}
          placeholder={placeholder}
          readOnly={readonly}
          extensions={[javascript({ jsx: true })]}
          onChange={(value) => {
            setJsonString(value);
            onChange?.(value);
          }}
          onBlur={() => {
            verifyJson();
          }}
        />
        {errorTips && (
          <div className={styles['error-tips']}>
            <ErrorFilled style={{ marginRight: '4px' }} />
            {errorTips}
          </div>
        )}
      </div>
      <Button
        className={styles.format}
        onClick={() => {
          if (typeof verifyJson() === 'string') {
            setJsonString(verifyJson() as 'string');
          }
        }}
      >
        {intl('格式化')}
      </Button>
    </div>
  );
}

.json-container {
  display: flex;
  width: calc(~'100% - 75px');
  .json-input {
    display: flex;
    width: 100%;
    flex-direction: column;
    .json {
      border: 1px solid rgba(0, 21, 64, 0.12);
      border-radius: 4px;
    }
    .error-tips {
      margin-top: 8px;
      font-size: 12px;
      color: #e54545;
    }
  }
  .format {
    display: inline-flex;
    margin-left: 12px;
  }
}

 

posted @ 2022-07-22 11:11  雾夜飞雨  阅读(2555)  评论(0编辑  收藏  举报