mirror of
https://gitee.com/baidu/amis.git
synced 2024-12-02 03:48:13 +08:00
feat: 更换 json 查看组件,支持查看并修改功能 (#2360)
This commit is contained in:
parent
d9ef3ba9fe
commit
771c676424
@ -124,9 +124,12 @@ List 的内容、Card 卡片的内容配置同上
|
|||||||
},
|
},
|
||||||
"body": [
|
"body": [
|
||||||
{
|
{
|
||||||
"type": "static-json",
|
"type": "control",
|
||||||
"name": "json",
|
"name": "json",
|
||||||
"label": "颜色"
|
"label": "Json",
|
||||||
|
"body": {
|
||||||
|
"type": "json"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@ -186,6 +189,29 @@ List 的内容、Card 卡片的内容配置同上
|
|||||||
|
|
||||||
如上,`levelExpand`配置为`0`,则默认不展开。
|
如上,`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` | `''` | 通过数据映射获取数据链中的值 |
|
| source | `string` | `''` | 通过数据映射获取数据链中的值 |
|
||||||
| placeholder | `string` | `-` | 占位文本 |
|
| placeholder | `string` | `-` | 占位文本 |
|
||||||
| levelExpand | `number` | `1` | 默认展开的层级 |
|
| levelExpand | `number` | `1` | 默认展开的层级 |
|
||||||
| hideRoot | `boolean` | `false` | 是否隐藏根节点 |
|
|
||||||
| jsonTheme | `string` | `twilight` | 主题,可选`twilight`和`eighties` |
|
| jsonTheme | `string` | `twilight` | 主题,可选`twilight`和`eighties` |
|
||||||
|
| mutable | `boolean` | `false` | 是否可修改 |
|
||||||
|
@ -78,7 +78,7 @@
|
|||||||
"react-dom": "^16.8.6",
|
"react-dom": "^16.8.6",
|
||||||
"react-dropzone": "11.2.4",
|
"react-dropzone": "11.2.4",
|
||||||
"react-input-range": "1.3.0",
|
"react-input-range": "1.3.0",
|
||||||
"react-json-tree": "0.15.0",
|
"react-json-view": "1.21.3",
|
||||||
"react-overlays": "0.8.3",
|
"react-overlays": "0.8.3",
|
||||||
"react-textarea-autosize": "5.1.0",
|
"react-textarea-autosize": "5.1.0",
|
||||||
"react-transition-group": "2.9.0",
|
"react-transition-group": "2.9.0",
|
||||||
|
@ -3,6 +3,7 @@ import React from 'react';
|
|||||||
import {RendererProps, Renderer} from '../../factory';
|
import {RendererProps, Renderer} from '../../factory';
|
||||||
import {SchemaCollection} from '../../Schema';
|
import {SchemaCollection} from '../../Schema';
|
||||||
import {autobind} from '../../utils/helper';
|
import {autobind} from '../../utils/helper';
|
||||||
|
import {resolveVariable} from '../../utils/tpl-builtin';
|
||||||
import {FormBaseControl, FormItemWrap} from './Item';
|
import {FormBaseControl, FormItemWrap} from './Item';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -24,8 +25,10 @@ export interface FormControlSchema extends FormBaseControl {
|
|||||||
export class ControlRenderer extends React.Component<RendererProps> {
|
export class ControlRenderer extends React.Component<RendererProps> {
|
||||||
@autobind
|
@autobind
|
||||||
renderInput() {
|
renderInput() {
|
||||||
const {render, body} = this.props;
|
const {render, body, name, data} = this.props;
|
||||||
return render('inner', body);
|
return render('inner', body, {
|
||||||
|
value: typeof name === 'string' ? resolveVariable(name, data) : undefined
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import {Renderer, RendererProps} from '../factory';
|
import {Renderer, RendererProps} from '../factory';
|
||||||
|
|
||||||
import JSONTree from 'react-json-tree';
|
import JsonView, {InteractionProps} from 'react-json-view';
|
||||||
import {autobind, getPropValue} from '../utils/helper';
|
import {autobind, getPropValue, noop} from '../utils/helper';
|
||||||
import {BaseSchema} from '../Schema';
|
import {BaseSchema} from '../Schema';
|
||||||
import {resolveVariableAndFilter, isPureVariable} from '../utils/tpl-builtin';
|
import {resolveVariableAndFilter, isPureVariable} from '../utils/tpl-builtin';
|
||||||
/**
|
/**
|
||||||
@ -20,15 +20,15 @@ export interface JsonSchema extends BaseSchema {
|
|||||||
*/
|
*/
|
||||||
levelExpand?: number;
|
levelExpand?: number;
|
||||||
|
|
||||||
/**
|
|
||||||
* 是否隐藏根节点
|
|
||||||
*/
|
|
||||||
hideRoot?: boolean;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 支持从数据链取值
|
* 支持从数据链取值
|
||||||
*/
|
*/
|
||||||
source?: string;
|
source?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否可修改
|
||||||
|
*/
|
||||||
|
mutable?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface JSONProps extends RendererProps, JsonSchema {
|
export interface JSONProps extends RendererProps, JsonSchema {
|
||||||
@ -40,123 +40,46 @@ export interface JSONProps extends RendererProps, JsonSchema {
|
|||||||
source?: string;
|
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> {
|
export class JSONField extends React.Component<JSONProps, object> {
|
||||||
static defaultProps: Partial<JSONProps> = {
|
static defaultProps: Partial<JSONProps> = {
|
||||||
placeholder: '-',
|
placeholder: '-',
|
||||||
levelExpand: 1,
|
levelExpand: 1,
|
||||||
jsonTheme: 'twilight',
|
|
||||||
hideRoot: false,
|
|
||||||
source: ''
|
source: ''
|
||||||
};
|
};
|
||||||
|
|
||||||
@autobind
|
@autobind
|
||||||
valueRenderer(raw: any) {
|
emitChange(e: InteractionProps) {
|
||||||
const cx = this.props.classnames;
|
const {onChange, name} = this.props;
|
||||||
if (typeof raw === 'string' && /^\"?https?:\/\//.test(raw)) {
|
|
||||||
return (
|
if (!name || !onChange) {
|
||||||
<a
|
return false;
|
||||||
className={cx('JsonField-nodeValue')}
|
|
||||||
rel="noopener"
|
|
||||||
href={raw.replace(/^\"(.*)\"$/, '$1')}
|
|
||||||
target="_blank"
|
|
||||||
>
|
|
||||||
{raw}
|
|
||||||
</a>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
return <span className={cx('JsonField-nodeValue')}>{raw}</span>;
|
|
||||||
|
onChange(e.updated_src, name);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
shouldExpandNode = (keyName: any, data: any, level: any) => {
|
@autobind
|
||||||
|
shouldExpandNode({namespace}: {namespace: Array<string | null>}) {
|
||||||
const {levelExpand} = this.props;
|
const {levelExpand} = this.props;
|
||||||
return level < levelExpand;
|
|
||||||
};
|
if (typeof levelExpand !== 'number') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return namespace.length > levelExpand;
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
className,
|
className,
|
||||||
jsonTheme,
|
jsonTheme,
|
||||||
classnames: cx,
|
classnames: cx,
|
||||||
hideRoot,
|
|
||||||
placeholder,
|
placeholder,
|
||||||
source
|
source,
|
||||||
|
levelExpand,
|
||||||
|
mutable,
|
||||||
|
name
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
const value = getPropValue(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 (
|
return (
|
||||||
<div className={cx('JsonField', className)}>
|
<div className={cx('JsonField', className)}>
|
||||||
{typeof data === 'undefined' || data === null ? (
|
{typeof data === 'undefined' || data === null ? (
|
||||||
placeholder
|
placeholder
|
||||||
) : (
|
) : (
|
||||||
<JSONTree
|
<JsonView
|
||||||
data={data}
|
name={false}
|
||||||
theme={theme}
|
src={data}
|
||||||
shouldExpandNode={this.shouldExpandNode}
|
theme={(jsonTheme as any) ?? 'rjv-default'}
|
||||||
valueRenderer={this.valueRenderer}
|
shouldCollapse={this.shouldExpandNode}
|
||||||
hideRoot={hideRoot}
|
enableClipboard={false}
|
||||||
|
iconStyle="square"
|
||||||
|
onEdit={name && mutable ? this.emitChange : false}
|
||||||
|
onDelete={name && mutable ? this.emitChange : false}
|
||||||
|
onAdd={name && mutable ? this.emitChange : false}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
Loading…
Reference in New Issue
Block a user