mirror of
https://gitee.com/baidu/amis.git
synced 2024-11-29 18:39:05 +08:00
feat: 更换 json 查看组件,支持查看并修改功能 (#2360)
This commit is contained in:
parent
d9ef3ba9fe
commit
771c676424
@ -124,9 +124,12 @@ List 的内容、Card 卡片的内容配置同上
|
||||
},
|
||||
"body": [
|
||||
{
|
||||
"type": "static-json",
|
||||
"type": "control",
|
||||
"name": "json",
|
||||
"label": "颜色"
|
||||
"label": "Json",
|
||||
"body": {
|
||||
"type": "json"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -186,6 +189,29 @@ List 的内容、Card 卡片的内容配置同上
|
||||
|
||||
如上,`levelExpand`配置为`0`,则默认不展开。
|
||||
|
||||
## 开启 json 修改
|
||||
|
||||
> since 1.2.3
|
||||
|
||||
可配置`mutable` 为 true,展示 json 的同时支持修改。记得配置 name 属性。
|
||||
|
||||
```schema: scope="body"
|
||||
[
|
||||
{
|
||||
"type": "json",
|
||||
"name": "json",
|
||||
"mutable": true,
|
||||
"value": {
|
||||
"a": "a",
|
||||
"b": "b",
|
||||
"c": {
|
||||
"d": "d"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
## 属性表
|
||||
|
||||
| 属性名 | 类型 | 默认值 | 说明 |
|
||||
@ -196,5 +222,5 @@ List 的内容、Card 卡片的内容配置同上
|
||||
| source | `string` | `''` | 通过数据映射获取数据链中的值 |
|
||||
| placeholder | `string` | `-` | 占位文本 |
|
||||
| levelExpand | `number` | `1` | 默认展开的层级 |
|
||||
| hideRoot | `boolean` | `false` | 是否隐藏根节点 |
|
||||
| jsonTheme | `string` | `twilight` | 主题,可选`twilight`和`eighties` |
|
||||
| mutable | `boolean` | `false` | 是否可修改 |
|
||||
|
@ -78,7 +78,7 @@
|
||||
"react-dom": "^16.8.6",
|
||||
"react-dropzone": "11.2.4",
|
||||
"react-input-range": "1.3.0",
|
||||
"react-json-tree": "0.15.0",
|
||||
"react-json-view": "1.21.3",
|
||||
"react-overlays": "0.8.3",
|
||||
"react-textarea-autosize": "5.1.0",
|
||||
"react-transition-group": "2.9.0",
|
||||
|
@ -3,6 +3,7 @@ import React from 'react';
|
||||
import {RendererProps, Renderer} from '../../factory';
|
||||
import {SchemaCollection} from '../../Schema';
|
||||
import {autobind} from '../../utils/helper';
|
||||
import {resolveVariable} from '../../utils/tpl-builtin';
|
||||
import {FormBaseControl, FormItemWrap} from './Item';
|
||||
|
||||
/**
|
||||
@ -24,8 +25,10 @@ export interface FormControlSchema extends FormBaseControl {
|
||||
export class ControlRenderer extends React.Component<RendererProps> {
|
||||
@autobind
|
||||
renderInput() {
|
||||
const {render, body} = this.props;
|
||||
return render('inner', body);
|
||||
const {render, body, name, data} = this.props;
|
||||
return render('inner', body, {
|
||||
value: typeof name === 'string' ? resolveVariable(name, data) : undefined
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
|
@ -1,8 +1,8 @@
|
||||
import React from 'react';
|
||||
import {Renderer, RendererProps} from '../factory';
|
||||
|
||||
import JSONTree from 'react-json-tree';
|
||||
import {autobind, getPropValue} from '../utils/helper';
|
||||
import JsonView, {InteractionProps} from 'react-json-view';
|
||||
import {autobind, getPropValue, noop} from '../utils/helper';
|
||||
import {BaseSchema} from '../Schema';
|
||||
import {resolveVariableAndFilter, isPureVariable} from '../utils/tpl-builtin';
|
||||
/**
|
||||
@ -20,15 +20,15 @@ export interface JsonSchema extends BaseSchema {
|
||||
*/
|
||||
levelExpand?: number;
|
||||
|
||||
/**
|
||||
* 是否隐藏根节点
|
||||
*/
|
||||
hideRoot?: boolean;
|
||||
|
||||
/**
|
||||
* 支持从数据链取值
|
||||
*/
|
||||
source?: string;
|
||||
|
||||
/**
|
||||
* 是否可修改
|
||||
*/
|
||||
mutable?: boolean;
|
||||
}
|
||||
|
||||
export interface JSONProps extends RendererProps, JsonSchema {
|
||||
@ -40,123 +40,46 @@ export interface JSONProps extends RendererProps, JsonSchema {
|
||||
source?: string;
|
||||
}
|
||||
|
||||
const twilight = {
|
||||
scheme: 'twilight',
|
||||
author: 'david hart (http://hart-dev.com)',
|
||||
base00: '#1e1e1e',
|
||||
base01: '#323537',
|
||||
base02: '#464b50',
|
||||
base03: '#5f5a60',
|
||||
base04: '#838184',
|
||||
base05: '#a7a7a7',
|
||||
base06: '#c3c3c3',
|
||||
base07: '#ffffff',
|
||||
base08: '#cf6a4c',
|
||||
base09: '#cda869',
|
||||
base0A: '#f9ee98',
|
||||
base0B: '#8f9d6a',
|
||||
base0C: '#afc4db',
|
||||
base0D: '#7587a6',
|
||||
base0E: '#9b859d',
|
||||
base0F: '#9b703f',
|
||||
tree: {
|
||||
border: 0,
|
||||
padding: '0 0.625em 0.425em',
|
||||
marginTop: '-0.25em',
|
||||
marginBottom: '0',
|
||||
marginLeft: '0',
|
||||
marginRight: 0,
|
||||
listStyle: 'none',
|
||||
MozUserSelect: 'none',
|
||||
WebkitUserSelect: 'none',
|
||||
backgroundColor: 'rgba(255, 255, 255, 0.4)',
|
||||
whiteSpace: 'nowrap',
|
||||
display: 'inline-block',
|
||||
width: '100%'
|
||||
}
|
||||
};
|
||||
|
||||
const eighties = {
|
||||
scheme: 'eighties',
|
||||
author: 'chris kempson (http://chriskempson.com)',
|
||||
base00: '#2d2d2d',
|
||||
base01: '#393939',
|
||||
base02: '#515151',
|
||||
base03: '#747369',
|
||||
base04: '#a09f93',
|
||||
base05: '#d3d0c8',
|
||||
base06: '#e8e6df',
|
||||
base07: '#f2f0ec',
|
||||
base08: '#f2777a',
|
||||
base09: '#f99157',
|
||||
base0A: '#ffcc66',
|
||||
base0B: '#99cc99',
|
||||
base0C: '#66cccc',
|
||||
base0D: '#6699cc',
|
||||
base0E: '#cc99cc',
|
||||
base0F: '#d27b53',
|
||||
tree: {
|
||||
border: 0,
|
||||
padding: '0 0.625em 0.425em',
|
||||
marginTop: '-0.25em',
|
||||
marginBottom: '0',
|
||||
marginLeft: '0',
|
||||
marginRight: 0,
|
||||
listStyle: 'none',
|
||||
MozUserSelect: 'none',
|
||||
WebkitUserSelect: 'none',
|
||||
backgroundColor: '#2D2D2D',
|
||||
whiteSpace: 'nowrap',
|
||||
display: 'inline-block',
|
||||
width: '100%'
|
||||
}
|
||||
};
|
||||
|
||||
const themes: any = {
|
||||
twilight,
|
||||
eighties
|
||||
};
|
||||
|
||||
export class JSONField extends React.Component<JSONProps, object> {
|
||||
static defaultProps: Partial<JSONProps> = {
|
||||
placeholder: '-',
|
||||
levelExpand: 1,
|
||||
jsonTheme: 'twilight',
|
||||
hideRoot: false,
|
||||
source: ''
|
||||
};
|
||||
|
||||
@autobind
|
||||
valueRenderer(raw: any) {
|
||||
const cx = this.props.classnames;
|
||||
if (typeof raw === 'string' && /^\"?https?:\/\//.test(raw)) {
|
||||
return (
|
||||
<a
|
||||
className={cx('JsonField-nodeValue')}
|
||||
rel="noopener"
|
||||
href={raw.replace(/^\"(.*)\"$/, '$1')}
|
||||
target="_blank"
|
||||
>
|
||||
{raw}
|
||||
</a>
|
||||
);
|
||||
}
|
||||
return <span className={cx('JsonField-nodeValue')}>{raw}</span>;
|
||||
emitChange(e: InteractionProps) {
|
||||
const {onChange, name} = this.props;
|
||||
|
||||
if (!name || !onChange) {
|
||||
return false;
|
||||
}
|
||||
|
||||
shouldExpandNode = (keyName: any, data: any, level: any) => {
|
||||
onChange(e.updated_src, name);
|
||||
return true;
|
||||
}
|
||||
|
||||
@autobind
|
||||
shouldExpandNode({namespace}: {namespace: Array<string | null>}) {
|
||||
const {levelExpand} = this.props;
|
||||
return level < levelExpand;
|
||||
};
|
||||
|
||||
if (typeof levelExpand !== 'number') {
|
||||
return false;
|
||||
}
|
||||
|
||||
return namespace.length > levelExpand;
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
className,
|
||||
jsonTheme,
|
||||
classnames: cx,
|
||||
hideRoot,
|
||||
placeholder,
|
||||
source
|
||||
source,
|
||||
levelExpand,
|
||||
mutable,
|
||||
name
|
||||
} = this.props;
|
||||
|
||||
const value = getPropValue(this.props);
|
||||
@ -174,19 +97,21 @@ export class JSONField extends React.Component<JSONProps, object> {
|
||||
}
|
||||
}
|
||||
|
||||
const theme = themes[jsonTheme] ? themes[jsonTheme] : themes['twilight'];
|
||||
|
||||
return (
|
||||
<div className={cx('JsonField', className)}>
|
||||
{typeof data === 'undefined' || data === null ? (
|
||||
placeholder
|
||||
) : (
|
||||
<JSONTree
|
||||
data={data}
|
||||
theme={theme}
|
||||
shouldExpandNode={this.shouldExpandNode}
|
||||
valueRenderer={this.valueRenderer}
|
||||
hideRoot={hideRoot}
|
||||
<JsonView
|
||||
name={false}
|
||||
src={data}
|
||||
theme={(jsonTheme as any) ?? 'rjv-default'}
|
||||
shouldCollapse={this.shouldExpandNode}
|
||||
enableClipboard={false}
|
||||
iconStyle="square"
|
||||
onEdit={name && mutable ? this.emitChange : false}
|
||||
onDelete={name && mutable ? this.emitChange : false}
|
||||
onAdd={name && mutable ? this.emitChange : false}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
Loading…
Reference in New Issue
Block a user