mirror of
https://gitee.com/baidu/amis.git
synced 2024-11-30 02:58:05 +08:00
amis-saas-7517 editor
Change-Id: I3165b21aff1f0065ceddf6d025881a7e2b299d6c
This commit is contained in:
parent
e470882ee7
commit
0f2a7dffe0
@ -229,6 +229,12 @@
|
||||
}
|
||||
}
|
||||
|
||||
.editor-code-tabs,
|
||||
.editor-code-tabs-cont,
|
||||
.editor-code-tabs-cont .in {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
// 左侧面板悬浮模式时的占位,避免折叠状态遮挡内容区
|
||||
.editor-left-panel-fixed-placeholder {
|
||||
position: relative;
|
||||
|
@ -0,0 +1,70 @@
|
||||
import React, {useEffect, useState} from 'react';
|
||||
import {Editor} from 'amis-ui';
|
||||
|
||||
export interface AmisStyleCodeEditorProps {
|
||||
value: any;
|
||||
onChange: (value: any, diff: any) => void;
|
||||
onPaste?: () => void;
|
||||
disabled?: boolean;
|
||||
$schemaUrl?: string;
|
||||
$schema?: string;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
function json2Css(data: any) {
|
||||
let res = '';
|
||||
for (let className in data) {
|
||||
if (typeof data[className] === 'object') {
|
||||
let value = [];
|
||||
for (let key in data[className]) {
|
||||
if (typeof data[className][key] !== 'object') {
|
||||
if (data[className][key]) {
|
||||
value.push(`${key}: ${data[className][key]};`);
|
||||
}
|
||||
} else {
|
||||
for (let k in data[className][key]) {
|
||||
if (data[className][key][k]) {
|
||||
value.push(`${k}: ${data[className][key][k]};`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
res += `.${className} {
|
||||
${value.join('\n ')}
|
||||
}\n`;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
function AmisStyleCodeEditor(props: AmisStyleCodeEditorProps) {
|
||||
const [value, setValue] = useState(props.value);
|
||||
debugger;
|
||||
useEffect(() => {
|
||||
setValue(props.value);
|
||||
}, [props.value]);
|
||||
console.log(json2Css(value));
|
||||
return (
|
||||
<Editor
|
||||
value={json2Css(value)}
|
||||
language="css"
|
||||
options={{
|
||||
automaticLayout: true,
|
||||
lineNumbers: 'off',
|
||||
glyphMargin: false,
|
||||
tabSize: 2,
|
||||
wordWrap: 'on',
|
||||
lineDecorationsWidth: 0,
|
||||
lineNumbersMinChars: 0,
|
||||
selectOnLineNumbers: true,
|
||||
scrollBeyondLastLine: false,
|
||||
folding: true,
|
||||
minimap: {
|
||||
enabled: false
|
||||
}
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export default AmisStyleCodeEditor;
|
@ -2,8 +2,13 @@ import React from 'react';
|
||||
import {PanelProps} from '../../plugin';
|
||||
import {autobind} from '../../util';
|
||||
import AMisCodeEditor from './AMisCodeEditor';
|
||||
import AmisStyleCodeEditor from './AmisStyleCodeEditor';
|
||||
import {Tab, Tabs} from 'amis-ui';
|
||||
|
||||
export default class CodeEditorPanel extends React.Component<PanelProps> {
|
||||
state = {
|
||||
tabsKey: 'schema'
|
||||
};
|
||||
@autobind
|
||||
handleCodePaste() {
|
||||
setTimeout(() => {
|
||||
@ -11,6 +16,11 @@ export default class CodeEditorPanel extends React.Component<PanelProps> {
|
||||
}, 500);
|
||||
}
|
||||
|
||||
@autobind
|
||||
handleSelect(key: string) {
|
||||
this.setState({tabsKey: key});
|
||||
}
|
||||
|
||||
render() {
|
||||
const {onChange, manager, store} = this.props;
|
||||
|
||||
@ -18,13 +28,45 @@ export default class CodeEditorPanel extends React.Component<PanelProps> {
|
||||
<div className="ae-CodePanel">
|
||||
<div className="panel-header">代码</div>
|
||||
<div className="ae-CodePanel-content">
|
||||
<AMisCodeEditor
|
||||
value={store.valueWithoutHiddenProps}
|
||||
onChange={onChange}
|
||||
$schema={store.jsonSchemaUri}
|
||||
$schemaUrl={manager.config.$schemaUrl}
|
||||
onPaste={this.handleCodePaste}
|
||||
/>
|
||||
<Tabs
|
||||
tabsMode="line"
|
||||
activeKey={this.state.tabsKey}
|
||||
onSelect={this.handleSelect}
|
||||
className="editor-code-tabs"
|
||||
linksClassName="editor-code-tabs-links"
|
||||
contentClassName="editor-code-tabs-cont"
|
||||
>
|
||||
<Tab
|
||||
key={'schema'}
|
||||
eventKey={'schema'}
|
||||
title={'Schema'}
|
||||
mountOnEnter={true}
|
||||
unmountOnExit={false}
|
||||
>
|
||||
<AMisCodeEditor
|
||||
value={store.valueWithoutHiddenProps}
|
||||
onChange={onChange}
|
||||
$schema={store.jsonSchemaUri}
|
||||
$schemaUrl={manager.config.$schemaUrl}
|
||||
onPaste={this.handleCodePaste}
|
||||
/>
|
||||
</Tab>
|
||||
<Tab
|
||||
key={'style'}
|
||||
eventKey={'style'}
|
||||
title={'Style'}
|
||||
mountOnEnter={true}
|
||||
unmountOnExit={false}
|
||||
>
|
||||
<AmisStyleCodeEditor
|
||||
value={store.cssValue}
|
||||
onChange={onChange}
|
||||
$schema={store.jsonSchemaUri}
|
||||
$schemaUrl={manager.config.$schemaUrl}
|
||||
onPaste={this.handleCodePaste}
|
||||
/>
|
||||
</Tab>
|
||||
</Tabs>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
@ -40,6 +40,7 @@ import isPlainObject from 'lodash/isPlainObject';
|
||||
import {EditorManagerConfig} from '../manager';
|
||||
import {EditorNode, EditorNodeType} from './node';
|
||||
import findIndex from 'lodash/findIndex';
|
||||
import {cloneDeep} from 'lodash';
|
||||
|
||||
export interface SchemaHistory {
|
||||
versionId: number;
|
||||
@ -154,6 +155,7 @@ export const EditorStore = types
|
||||
showInsertRenderer: false, // 是否显示插入组件面板(抽屉弹出模式)
|
||||
|
||||
schema: types.frozen(),
|
||||
style: types.frozen(),
|
||||
versionId: 0,
|
||||
schemaHistory: types.optional(
|
||||
types.array(types.frozen<SchemaHistory>()),
|
||||
@ -497,8 +499,46 @@ export const EditorStore = types
|
||||
return this.getValueOf(self.activeId);
|
||||
},
|
||||
|
||||
get cssValue() {
|
||||
if (!self.activeId) {
|
||||
return undefined;
|
||||
}
|
||||
const schema = JSONGetById(self.schema, self.activeId);
|
||||
return this.getCssValueof(schema)?.res;
|
||||
},
|
||||
|
||||
getValueOf(id: string) {
|
||||
return JSONPipeOut(JSONGetById(self.schema, id), false);
|
||||
const schema = JSONGetById(self.schema, id);
|
||||
const res = JSONPipeOut(
|
||||
Object.assign({}, schema, this.getCssValueof(schema)?.css),
|
||||
false
|
||||
);
|
||||
return res;
|
||||
},
|
||||
|
||||
getCssValueof(schema: any) {
|
||||
if (!self.style) {
|
||||
return null;
|
||||
}
|
||||
const list = [];
|
||||
for (let key in schema) {
|
||||
if (/[c|C]lassName/.test(key)) {
|
||||
const className = schema[key];
|
||||
if (/(\S*[C|c]lassName-\S*)/.test(className)) {
|
||||
list.push({
|
||||
key,
|
||||
value: /(\S*[C|c]lassName-\S*)/.exec(className)![0]
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
const css: any = {};
|
||||
const res: any = {};
|
||||
list.forEach(item => {
|
||||
css[item.key] = self.style[item.value];
|
||||
res[item.value] = self.style[item.value];
|
||||
});
|
||||
return {css: {css}, res};
|
||||
},
|
||||
|
||||
get valueWithoutHiddenProps() {
|
||||
@ -1181,7 +1221,11 @@ export const EditorStore = types
|
||||
if (!self.activeId) {
|
||||
return;
|
||||
}
|
||||
this.changeValueById(self.activeId, value, diff);
|
||||
if (this.isStyleChange(diff)) {
|
||||
this.changeStyle(value, diff);
|
||||
} else {
|
||||
this.changeValueById(self.activeId, value, diff);
|
||||
}
|
||||
},
|
||||
|
||||
changeValueById(
|
||||
@ -1212,6 +1256,70 @@ export const EditorStore = types
|
||||
}
|
||||
},
|
||||
|
||||
isStyleChange(diff: any) {
|
||||
if (
|
||||
Array.isArray(diff) &&
|
||||
!!diff.find(
|
||||
(n: any) =>
|
||||
!!n.path.find(
|
||||
(path: any) =>
|
||||
typeof path === 'string' && !!~path.indexOf('css')
|
||||
)
|
||||
)
|
||||
) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
changeStyle(value: Schema, diff?: any) {
|
||||
const styleDiff = diff.find(
|
||||
(n: any) =>
|
||||
!!n.path.find(
|
||||
(path: any) => typeof path === 'string' && !!~path.indexOf('css')
|
||||
)
|
||||
);
|
||||
const obj = cloneDeep(value);
|
||||
const style = cloneDeep(self.style);
|
||||
let key = '';
|
||||
let styleValue = {};
|
||||
const cssIndex = styleDiff.path.findIndex((path: any) =>
|
||||
/css/.test(path)
|
||||
);
|
||||
key = styleDiff.path[cssIndex + 1];
|
||||
if (!key) {
|
||||
key = Object.keys(styleDiff.rhs)[0];
|
||||
styleValue = obj.css[key];
|
||||
} else {
|
||||
const styleKey = styleDiff.path[cssIndex + 2];
|
||||
if (styleKey) {
|
||||
styleValue = {
|
||||
[styleKey]: obj.css[key][styleKey]
|
||||
};
|
||||
} else {
|
||||
styleValue = obj.css[key];
|
||||
}
|
||||
}
|
||||
let classname = `${key}-${guid()}`;
|
||||
if (!value[key]) {
|
||||
obj[key] = classname;
|
||||
} else if (/(\S*[C|c]lassName-\S*)/.test(obj[key])) {
|
||||
classname = /(\S*[C|c]lassName-\S*)/.exec(obj[key])![0];
|
||||
} else {
|
||||
obj[key] += ' ' + classname;
|
||||
}
|
||||
|
||||
self.style = Object.assign(style || {}, {
|
||||
[classname]: Object.assign(
|
||||
style ? style[classname] || {} : {},
|
||||
styleValue
|
||||
)
|
||||
});
|
||||
delete obj.css;
|
||||
this.changeValueById(self.activeId, obj);
|
||||
},
|
||||
|
||||
moveUp(id: string) {
|
||||
if (!id) {
|
||||
return;
|
||||
|
Loading…
Reference in New Issue
Block a user