2019-06-11 17:00:02 +08:00
|
|
|
|
import React from 'react';
|
2022-06-01 15:06:00 +08:00
|
|
|
|
import {toast, render, makeTranslator} from 'amis';
|
2022-06-01 21:35:49 +08:00
|
|
|
|
import {normalizeLink} from 'amis-core';
|
|
|
|
|
import {isMobile} from 'amis-core';
|
|
|
|
|
import {attachmentAdpator} from 'amis-core';
|
|
|
|
|
import {alert, confirm} from 'amis-ui';
|
2019-06-11 17:00:02 +08:00
|
|
|
|
import axios from 'axios';
|
2021-08-27 14:44:50 +08:00
|
|
|
|
import JSON5 from 'json5';
|
2022-06-01 21:35:49 +08:00
|
|
|
|
import {Editor as CodeEditor} from 'amis-ui';
|
2020-08-05 14:59:27 +08:00
|
|
|
|
import copy from 'copy-to-clipboard';
|
2022-02-11 19:45:33 +08:00
|
|
|
|
import {matchPath} from 'react-router-dom';
|
2022-06-01 21:35:49 +08:00
|
|
|
|
import {Drawer} from 'amis-ui';
|
2019-04-30 11:11:25 +08:00
|
|
|
|
|
|
|
|
|
const DEFAULT_CONTENT = `{
|
2020-09-03 11:45:31 +08:00
|
|
|
|
"$schema": "/schemas/page.json#",
|
2019-04-30 11:11:25 +08:00
|
|
|
|
"type": "page",
|
|
|
|
|
"title": "Title",
|
|
|
|
|
"body": "Body",
|
|
|
|
|
"aside": "Aside",
|
|
|
|
|
"toolbar": "Toolbar"
|
|
|
|
|
}`;
|
|
|
|
|
|
|
|
|
|
const scopes = {
|
2019-12-06 09:58:08 +08:00
|
|
|
|
'none': ``,
|
2019-04-30 11:11:25 +08:00
|
|
|
|
|
2019-12-06 09:58:08 +08:00
|
|
|
|
'body': `{
|
2019-04-30 11:11:25 +08:00
|
|
|
|
"type": "page",
|
|
|
|
|
"body": SCHEMA_PLACEHOLDER
|
|
|
|
|
}`,
|
|
|
|
|
|
2019-12-06 09:58:08 +08:00
|
|
|
|
'form': `{
|
2019-04-30 11:11:25 +08:00
|
|
|
|
"type": "page",
|
|
|
|
|
"body": {
|
|
|
|
|
"title": "",
|
|
|
|
|
"type": "form",
|
|
|
|
|
"autoFocus": false,
|
|
|
|
|
"api": "/api/mock/saveForm?waitSeconds=1",
|
|
|
|
|
"mode": "horizontal",
|
2022-02-10 20:08:17 +08:00
|
|
|
|
"body": SCHEMA_PLACEHOLDER,
|
2019-04-30 11:11:25 +08:00
|
|
|
|
"submitText": null,
|
|
|
|
|
"actions": []
|
|
|
|
|
}
|
|
|
|
|
}`,
|
|
|
|
|
|
2021-06-03 22:09:30 +08:00
|
|
|
|
'form2': `{
|
|
|
|
|
"type": "page",
|
|
|
|
|
"body": {
|
|
|
|
|
"title": "",
|
|
|
|
|
"type": "form",
|
|
|
|
|
"autoFocus": false,
|
|
|
|
|
"api": "/api/mock/saveForm?waitSeconds=1",
|
|
|
|
|
"mode": "horizontal",
|
|
|
|
|
"body": SCHEMA_PLACEHOLDER,
|
|
|
|
|
"submitText": null,
|
|
|
|
|
"actions": []
|
|
|
|
|
}
|
|
|
|
|
}`,
|
|
|
|
|
|
2019-11-07 10:41:14 +08:00
|
|
|
|
'form-item': `{
|
2019-04-30 11:11:25 +08:00
|
|
|
|
"type": "page",
|
|
|
|
|
"body": {
|
|
|
|
|
"title": "",
|
|
|
|
|
"type": "form",
|
|
|
|
|
"mode": "horizontal",
|
|
|
|
|
"autoFocus": false,
|
2022-02-10 20:08:17 +08:00
|
|
|
|
"body": [
|
2019-04-30 11:11:25 +08:00
|
|
|
|
SCHEMA_PLACEHOLDER
|
|
|
|
|
],
|
|
|
|
|
"submitText": null,
|
|
|
|
|
"actions": []
|
|
|
|
|
}
|
2021-06-03 22:25:26 +08:00
|
|
|
|
}`,
|
|
|
|
|
|
|
|
|
|
'form-item2': `{
|
|
|
|
|
"type": "page",
|
|
|
|
|
"body": {
|
|
|
|
|
"title": "",
|
|
|
|
|
"type": "form",
|
|
|
|
|
"mode": "horizontal",
|
|
|
|
|
"autoFocus": false,
|
|
|
|
|
"body": [
|
|
|
|
|
SCHEMA_PLACEHOLDER
|
|
|
|
|
],
|
|
|
|
|
"submitText": null,
|
|
|
|
|
"actions": []
|
|
|
|
|
}
|
|
|
|
|
}`
|
2019-04-30 11:11:25 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export default class PlayGround extends React.Component {
|
2019-11-07 10:41:14 +08:00
|
|
|
|
state = null;
|
|
|
|
|
startX = 0;
|
|
|
|
|
oldContents = '';
|
|
|
|
|
frameTemplate;
|
2020-11-19 13:47:56 +08:00
|
|
|
|
iframeRef;
|
2019-11-07 10:41:14 +08:00
|
|
|
|
|
|
|
|
|
static defaultProps = {
|
|
|
|
|
vertical: false
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
constructor(props) {
|
|
|
|
|
super(props);
|
2020-11-19 13:47:56 +08:00
|
|
|
|
this.iframeRef = React.createRef();
|
2022-02-10 19:55:17 +08:00
|
|
|
|
const {history} = props;
|
2020-08-05 14:59:27 +08:00
|
|
|
|
|
2019-11-07 10:41:14 +08:00
|
|
|
|
const schema = this.buildSchema(props.code || DEFAULT_CONTENT, props);
|
|
|
|
|
this.state = {
|
|
|
|
|
asideWidth: props.asideWidth || Math.max(300, window.innerWidth * 0.3),
|
|
|
|
|
schema: schema,
|
2022-04-28 10:53:06 +08:00
|
|
|
|
schemaCode: JSON.stringify(schema, null, 2),
|
|
|
|
|
isOpened: false
|
2019-04-30 11:11:25 +08:00
|
|
|
|
};
|
|
|
|
|
|
2019-11-07 10:41:14 +08:00
|
|
|
|
this.handleMouseDown = this.handleMouseDown.bind(this);
|
|
|
|
|
this.handleMouseMove = this.handleMouseMove.bind(this);
|
|
|
|
|
this.handleMouseUp = this.handleMouseUp.bind(this);
|
|
|
|
|
this.removeWindowEvents = this.removeWindowEvents.bind(this);
|
|
|
|
|
this.handleChange = this.handleChange.bind(this);
|
2022-04-28 10:53:06 +08:00
|
|
|
|
this.toggleDrawer = this.toggleDrawer.bind(this);
|
|
|
|
|
this.close = this.close.bind(this);
|
2020-12-21 10:08:40 +08:00
|
|
|
|
this.schemaProps = {};
|
2021-08-26 17:52:15 +08:00
|
|
|
|
|
|
|
|
|
const __ = makeTranslator(props.locale);
|
|
|
|
|
|
2019-11-07 10:41:14 +08:00
|
|
|
|
this.env = {
|
2020-08-01 00:26:55 +08:00
|
|
|
|
session: 'doc',
|
2020-08-05 14:59:27 +08:00
|
|
|
|
updateLocation: (location, replace) => {
|
2022-02-10 19:55:17 +08:00
|
|
|
|
history[replace ? 'replace' : 'push'](normalizeLink(location));
|
2020-08-05 14:59:27 +08:00
|
|
|
|
},
|
|
|
|
|
isCurrentUrl: to => {
|
2022-02-10 19:55:17 +08:00
|
|
|
|
if (!to) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2020-08-05 14:59:27 +08:00
|
|
|
|
const link = normalizeLink(to);
|
2022-02-10 19:55:17 +08:00
|
|
|
|
return !!matchPath(history.location.pathname, {
|
|
|
|
|
path: link,
|
|
|
|
|
exact: true
|
|
|
|
|
});
|
2020-08-05 14:59:27 +08:00
|
|
|
|
},
|
2020-08-20 16:01:19 +08:00
|
|
|
|
jumpTo: (to, action) => {
|
2020-08-05 14:59:27 +08:00
|
|
|
|
to = normalizeLink(to);
|
|
|
|
|
|
2020-08-20 16:01:19 +08:00
|
|
|
|
if (action && action.actionType === 'url') {
|
2020-11-03 11:02:04 +08:00
|
|
|
|
action.blank === true ? window.open(to) : (window.location.href = to);
|
2020-08-20 16:01:19 +08:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2021-07-01 00:45:13 +08:00
|
|
|
|
if (action && to && action.target) {
|
|
|
|
|
window.open(to, action.target);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-05 14:59:27 +08:00
|
|
|
|
if (/^https?:\/\//.test(to)) {
|
|
|
|
|
window.location.replace(to);
|
|
|
|
|
} else {
|
2022-02-10 19:55:17 +08:00
|
|
|
|
history.push(to);
|
2020-08-05 14:59:27 +08:00
|
|
|
|
}
|
|
|
|
|
},
|
2021-10-28 19:38:16 +08:00
|
|
|
|
fetcher: async api => {
|
|
|
|
|
let {url, method, data, responseType, config, headers} = api;
|
|
|
|
|
config = config || {};
|
2023-03-21 19:27:34 +08:00
|
|
|
|
// 如果在 gh-pages 里面
|
|
|
|
|
if (
|
|
|
|
|
/^\/amis/.test(window.location.pathname) &&
|
|
|
|
|
typeof url === 'string' &&
|
|
|
|
|
url.startsWith('/examples/static/')
|
|
|
|
|
) {
|
|
|
|
|
url = url.replace('/examples/static/', '/amis/static/');
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-28 19:38:16 +08:00
|
|
|
|
config.url = url;
|
|
|
|
|
responseType && (config.responseType = responseType);
|
|
|
|
|
|
|
|
|
|
if (config.cancelExecutor) {
|
|
|
|
|
config.cancelToken = new axios.CancelToken(config.cancelExecutor);
|
|
|
|
|
}
|
2019-04-30 11:11:25 +08:00
|
|
|
|
|
2021-10-28 19:38:16 +08:00
|
|
|
|
config.headers = headers || {};
|
|
|
|
|
config.method = method;
|
|
|
|
|
config.data = data;
|
|
|
|
|
|
|
|
|
|
if (method === 'get' && data) {
|
|
|
|
|
config.params = data;
|
|
|
|
|
} else if (data && data instanceof FormData) {
|
|
|
|
|
// config.headers['Content-Type'] = 'multipart/form-data';
|
|
|
|
|
} else if (
|
|
|
|
|
data &&
|
|
|
|
|
typeof data !== 'string' &&
|
|
|
|
|
!(data instanceof Blob) &&
|
|
|
|
|
!(data instanceof ArrayBuffer)
|
|
|
|
|
) {
|
|
|
|
|
data = JSON.stringify(data);
|
2019-11-07 10:41:14 +08:00
|
|
|
|
config.headers['Content-Type'] = 'application/json';
|
2019-04-30 11:11:25 +08:00
|
|
|
|
}
|
|
|
|
|
|
2021-04-09 12:40:36 +08:00
|
|
|
|
// 支持返回各种报错信息
|
2021-10-28 19:38:16 +08:00
|
|
|
|
config.validateStatus = function () {
|
2021-04-09 12:40:36 +08:00
|
|
|
|
return true;
|
|
|
|
|
};
|
|
|
|
|
|
2021-10-28 19:38:16 +08:00
|
|
|
|
let response = await axios(config);
|
2023-10-24 14:13:31 +08:00
|
|
|
|
response = await attachmentAdpator(response, __, api);
|
2021-04-09 12:40:36 +08:00
|
|
|
|
|
|
|
|
|
if (response.status >= 400) {
|
|
|
|
|
if (response.data) {
|
2021-10-28 19:38:16 +08:00
|
|
|
|
// 主要用于 raw: 模式下,后端自己校验登录,
|
|
|
|
|
if (
|
|
|
|
|
response.status === 401 &&
|
|
|
|
|
response.data.location &&
|
|
|
|
|
response.data.location.startsWith('http')
|
|
|
|
|
) {
|
|
|
|
|
location.href = response.data.location.replace(
|
|
|
|
|
'{{redirect}}',
|
|
|
|
|
encodeURIComponent(location.href)
|
|
|
|
|
);
|
|
|
|
|
return new Promise(() => {});
|
|
|
|
|
} else if (response.data.msg) {
|
2021-04-09 12:40:36 +08:00
|
|
|
|
throw new Error(response.data.msg);
|
|
|
|
|
} else {
|
|
|
|
|
throw new Error(
|
2021-08-26 17:52:15 +08:00
|
|
|
|
__('System.requestError') +
|
|
|
|
|
JSON.stringify(response.data, null, 2)
|
2021-04-09 12:40:36 +08:00
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
2021-08-26 17:52:15 +08:00
|
|
|
|
throw new Error(
|
|
|
|
|
`${__('System.requestErrorStatus')} ${response.status}`
|
|
|
|
|
);
|
2021-04-09 12:40:36 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
2021-10-28 19:38:16 +08:00
|
|
|
|
|
2021-04-09 12:40:36 +08:00
|
|
|
|
return response;
|
2019-11-07 10:41:14 +08:00
|
|
|
|
},
|
2020-08-05 14:59:27 +08:00
|
|
|
|
isCancel: value => axios.isCancel(value),
|
2021-11-24 21:49:08 +08:00
|
|
|
|
notify: (type, msg, conf) =>
|
|
|
|
|
toast[type]
|
|
|
|
|
? toast[type](msg, conf)
|
|
|
|
|
: console.warn('[Notify]', type, msg),
|
2020-08-05 14:59:27 +08:00
|
|
|
|
alert,
|
|
|
|
|
confirm,
|
2021-10-13 11:41:43 +08:00
|
|
|
|
copy: (content, options) => {
|
|
|
|
|
copy(content, options);
|
2021-08-26 17:52:15 +08:00
|
|
|
|
toast.success(__('System.copy'));
|
2021-11-12 12:36:44 +08:00
|
|
|
|
},
|
|
|
|
|
tracker(eventTrack) {
|
|
|
|
|
console.debug('eventTrack', eventTrack);
|
2021-11-22 12:41:26 +08:00
|
|
|
|
},
|
|
|
|
|
replaceText: {
|
|
|
|
|
AMIS_HOST: 'https://baidu.gitee.io/amis'
|
2023-08-15 10:09:01 +08:00
|
|
|
|
},
|
|
|
|
|
loadTinymcePlugin: async tinymce => {
|
|
|
|
|
// 参考:https://www.tiny.cloud/docs/advanced/creating-a-plugin/
|
|
|
|
|
/*
|
|
|
|
|
Note: We have included the plugin in the same JavaScript file as the TinyMCE
|
|
|
|
|
instance for display purposes only. Tiny recommends not maintaining the plugin
|
|
|
|
|
with the TinyMCE instance and using the `external_plugins` option.
|
|
|
|
|
*/
|
|
|
|
|
tinymce.PluginManager.add('example', function (editor, url) {
|
|
|
|
|
var openDialog = function () {
|
|
|
|
|
return editor.windowManager.open({
|
|
|
|
|
title: 'Example plugin',
|
|
|
|
|
body: {
|
|
|
|
|
type: 'panel',
|
|
|
|
|
items: [
|
|
|
|
|
{
|
|
|
|
|
type: 'input',
|
|
|
|
|
name: 'title',
|
|
|
|
|
label: 'Title'
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
buttons: [
|
|
|
|
|
{
|
|
|
|
|
type: 'cancel',
|
|
|
|
|
text: 'Close'
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
type: 'submit',
|
|
|
|
|
text: 'Save',
|
|
|
|
|
primary: true
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
onSubmit: function (api) {
|
|
|
|
|
var data = api.getData();
|
|
|
|
|
/* Insert content when the window form is submitted */
|
|
|
|
|
editor.insertContent('Title: ' + data.title);
|
|
|
|
|
api.close();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
/* Add a button that opens a window */
|
|
|
|
|
editor.ui.registry.addButton('example', {
|
|
|
|
|
text: 'My button',
|
|
|
|
|
onAction: function () {
|
|
|
|
|
/* Open window */
|
|
|
|
|
openDialog();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
/* Adds a menu item, which can then be included in any menu via the menu/menubar configuration */
|
|
|
|
|
editor.ui.registry.addMenuItem('example', {
|
|
|
|
|
text: 'Example plugin',
|
|
|
|
|
onAction: function () {
|
|
|
|
|
/* Open window */
|
|
|
|
|
openDialog();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
/* Return the metadata for the help plugin */
|
|
|
|
|
return {
|
|
|
|
|
getMetadata: function () {
|
|
|
|
|
return {
|
|
|
|
|
name: 'Example plugin',
|
|
|
|
|
url: 'http://exampleplugindocsurl.com'
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
});
|
2020-08-05 14:59:27 +08:00
|
|
|
|
}
|
2019-11-07 10:41:14 +08:00
|
|
|
|
};
|
2019-04-30 11:11:25 +08:00
|
|
|
|
|
2020-11-19 13:47:56 +08:00
|
|
|
|
this.watchIframeReady = this.watchIframeReady.bind(this);
|
|
|
|
|
window.addEventListener('message', this.watchIframeReady, false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
watchIframeReady(event) {
|
|
|
|
|
// iframe 里面的 amis 初始化了就可以发数据
|
|
|
|
|
if (event.data && event.data === 'amisReady') {
|
|
|
|
|
this.updateIframe();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
updateIframe() {
|
|
|
|
|
if (this.iframeRef && this.iframeRef.current) {
|
|
|
|
|
this.iframeRef.current.contentWindow.postMessage(
|
|
|
|
|
{
|
|
|
|
|
schema: this.state.schema,
|
|
|
|
|
props: {theme: this.props.theme, locale: this.props.locale}
|
|
|
|
|
},
|
|
|
|
|
'*'
|
|
|
|
|
);
|
|
|
|
|
}
|
2019-11-07 10:41:14 +08:00
|
|
|
|
}
|
|
|
|
|
|
2022-02-09 19:28:57 +08:00
|
|
|
|
componentDidUpdate(preProps) {
|
2019-11-07 10:41:14 +08:00
|
|
|
|
const props = this.props;
|
|
|
|
|
|
2022-02-09 19:28:57 +08:00
|
|
|
|
if (preProps.code !== props.code) {
|
|
|
|
|
const schema = this.buildSchema(props.code || DEFAULT_CONTENT, props);
|
2019-11-07 10:41:14 +08:00
|
|
|
|
this.setState({
|
|
|
|
|
schema: schema,
|
|
|
|
|
schemaCode: JSON.stringify(schema, null, 2)
|
|
|
|
|
});
|
2019-04-30 11:11:25 +08:00
|
|
|
|
}
|
2019-11-07 10:41:14 +08:00
|
|
|
|
}
|
2019-04-30 11:11:25 +08:00
|
|
|
|
|
2019-11-07 10:41:14 +08:00
|
|
|
|
componentDidMount() {
|
|
|
|
|
this.props.setAsideFolded && this.props.setAsideFolded(true);
|
|
|
|
|
}
|
2019-04-30 11:11:25 +08:00
|
|
|
|
|
2019-11-07 10:41:14 +08:00
|
|
|
|
componentWillUnmount() {
|
|
|
|
|
this.props.setAsideFolded && this.props.setAsideFolded(false);
|
2020-11-19 13:47:56 +08:00
|
|
|
|
window.removeEventListener('message', this.watchIframeReady, false);
|
2019-11-07 10:41:14 +08:00
|
|
|
|
}
|
2019-04-30 11:11:25 +08:00
|
|
|
|
|
2019-11-07 10:41:14 +08:00
|
|
|
|
buildSchema(schemaContent, props = this.props) {
|
|
|
|
|
const query = props.location.query;
|
2019-04-30 11:11:25 +08:00
|
|
|
|
|
2019-11-07 10:41:14 +08:00
|
|
|
|
try {
|
2022-02-10 13:50:12 +08:00
|
|
|
|
const scope = props.scope;
|
2019-04-30 11:11:25 +08:00
|
|
|
|
|
2019-11-07 10:41:14 +08:00
|
|
|
|
if (scope && scopes[scope]) {
|
|
|
|
|
schemaContent = scopes[scope].replace(
|
|
|
|
|
'SCHEMA_PLACEHOLDER',
|
|
|
|
|
schemaContent
|
2019-04-30 11:11:25 +08:00
|
|
|
|
);
|
2019-11-07 10:41:14 +08:00
|
|
|
|
}
|
2019-04-30 11:11:25 +08:00
|
|
|
|
|
2021-08-27 14:44:50 +08:00
|
|
|
|
schemaContent = schemaContent.replace(/('|")raw:/g, '$1'); // 去掉 raw
|
2019-04-30 11:11:25 +08:00
|
|
|
|
|
2021-08-27 14:44:50 +08:00
|
|
|
|
const json = JSON5.parse(schemaContent);
|
2020-09-03 11:45:31 +08:00
|
|
|
|
|
|
|
|
|
return json;
|
2019-11-07 10:41:14 +08:00
|
|
|
|
} catch (e) {
|
|
|
|
|
console.error(this.formatMessage(e.message, schemaContent));
|
2019-04-30 11:11:25 +08:00
|
|
|
|
}
|
|
|
|
|
|
2019-11-07 10:41:14 +08:00
|
|
|
|
return {};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
formatMessage(message, input) {
|
|
|
|
|
if (/position\s?(\d+)$/.test(message)) {
|
|
|
|
|
const lines = input
|
|
|
|
|
.substring(0, parseInt(RegExp.$1, 10))
|
|
|
|
|
.split(/\n|\r\n|\r/);
|
|
|
|
|
message = `Json 语法错误,请检测。出错位置:${lines.length},列:${
|
|
|
|
|
lines[lines.length - 1].length
|
|
|
|
|
}。`;
|
2019-04-30 11:11:25 +08:00
|
|
|
|
}
|
|
|
|
|
|
2019-11-07 10:41:14 +08:00
|
|
|
|
return message;
|
|
|
|
|
}
|
2019-04-30 11:11:25 +08:00
|
|
|
|
|
2019-11-07 10:41:14 +08:00
|
|
|
|
renderPreview() {
|
|
|
|
|
const schema = this.state.schema;
|
2019-04-30 11:11:25 +08:00
|
|
|
|
|
2020-07-28 10:03:53 +08:00
|
|
|
|
const props = {
|
|
|
|
|
...this.schemaProps,
|
|
|
|
|
theme: this.props.theme,
|
2020-08-01 00:26:55 +08:00
|
|
|
|
locale: this.props.locale,
|
|
|
|
|
affixHeader: false,
|
2021-12-29 18:31:37 +08:00
|
|
|
|
affixFooter: false
|
2020-07-28 10:03:53 +08:00
|
|
|
|
};
|
|
|
|
|
|
2021-12-29 18:31:37 +08:00
|
|
|
|
if (this.props.viewMode === 'mobile' && !isMobile()) {
|
2020-11-19 13:47:56 +08:00
|
|
|
|
return (
|
|
|
|
|
<iframe
|
|
|
|
|
width="375"
|
|
|
|
|
height="100%"
|
|
|
|
|
frameBorder={0}
|
|
|
|
|
className="mobile-frame"
|
|
|
|
|
ref={this.iframeRef}
|
|
|
|
|
// @ts-ignore
|
2020-11-19 19:22:56 +08:00
|
|
|
|
src={__uri('../mobile.html')}
|
2020-11-19 13:47:56 +08:00
|
|
|
|
></iframe>
|
|
|
|
|
);
|
2019-04-30 11:11:25 +08:00
|
|
|
|
}
|
|
|
|
|
|
2020-11-19 13:47:56 +08:00
|
|
|
|
return render(schema, props, this.env);
|
2019-11-07 10:41:14 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
handleChange(value) {
|
|
|
|
|
this.setState({
|
|
|
|
|
schemaCode: value
|
|
|
|
|
});
|
|
|
|
|
try {
|
2021-08-27 14:44:50 +08:00
|
|
|
|
const schema = JSON5.parse(value);
|
2020-11-19 13:47:56 +08:00
|
|
|
|
this.setState(
|
|
|
|
|
{
|
|
|
|
|
schema
|
|
|
|
|
},
|
|
|
|
|
() => {
|
|
|
|
|
this.updateIframe();
|
|
|
|
|
}
|
|
|
|
|
);
|
2019-11-07 10:41:14 +08:00
|
|
|
|
} catch (e) {
|
|
|
|
|
//ignore
|
2019-04-30 11:11:25 +08:00
|
|
|
|
}
|
2019-11-07 10:41:14 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
handleMouseDown(e) {
|
|
|
|
|
this.startX = e.clientX;
|
|
|
|
|
this.startWidth = this.state.asideWidth;
|
|
|
|
|
|
|
|
|
|
// this.startPosition.y = e.clientY;
|
|
|
|
|
|
|
|
|
|
window.addEventListener('mouseup', this.handleMouseUp);
|
|
|
|
|
window.addEventListener('mousemove', this.handleMouseMove);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
handleMouseMove(e) {
|
|
|
|
|
const diff = this.startX - e.clientX;
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
|
|
|
|
|
this.setState({
|
|
|
|
|
asideWidth: Math.min(800, Math.max(200, this.startWidth + diff))
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
handleMouseUp() {
|
|
|
|
|
this.removeWindowEvents();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
removeWindowEvents() {
|
|
|
|
|
window.removeEventListener('mouseup', this.handleMouseUp);
|
|
|
|
|
window.removeEventListener('mousemove', this.handleMouseMove);
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-28 10:53:06 +08:00
|
|
|
|
toggleDrawer() {
|
|
|
|
|
this.setState({
|
|
|
|
|
isOpened: !this.state.isOpened
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
close() {
|
|
|
|
|
this.setState({
|
|
|
|
|
isOpened: false
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-16 23:41:51 +08:00
|
|
|
|
editorDidMount = (editor, monaco) => {
|
|
|
|
|
this.editor = editor;
|
|
|
|
|
this.monaco = monaco;
|
|
|
|
|
|
|
|
|
|
let host = `${window.location.protocol}//${window.location.host}`;
|
|
|
|
|
|
|
|
|
|
// 如果在 gh-pages 里面
|
|
|
|
|
if (/^\/amis/.test(window.location.pathname)) {
|
|
|
|
|
host += '/amis';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const schemaUrl = `${host}/schema.json`;
|
|
|
|
|
|
|
|
|
|
monaco.languages.json.jsonDefaults.setDiagnosticsOptions({
|
|
|
|
|
schemas: [
|
|
|
|
|
{
|
|
|
|
|
uri: schemaUrl,
|
|
|
|
|
fileMatch: ['*']
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
validate: true,
|
|
|
|
|
enableSchemaRequest: true,
|
|
|
|
|
allowComments: true
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// editorFactory = (containerElement, monaco, options) => {
|
|
|
|
|
// this.model = monaco.editor.createModel(
|
|
|
|
|
// this.state.schemaCode,
|
|
|
|
|
// 'json',
|
|
|
|
|
// monaco.Uri.parse(`isuda://schemas/page.json`)
|
|
|
|
|
// );
|
|
|
|
|
|
|
|
|
|
// return monaco.editor.create(containerElement, {
|
|
|
|
|
// autoIndent: true,
|
|
|
|
|
// formatOnType: true,
|
|
|
|
|
// formatOnPaste: true,
|
|
|
|
|
// selectOnLineNumbers: true,
|
|
|
|
|
// scrollBeyondLastLine: false,
|
|
|
|
|
// folding: true,
|
|
|
|
|
// minimap: {
|
|
|
|
|
// enabled: false
|
|
|
|
|
// },
|
|
|
|
|
// ...options,
|
|
|
|
|
// model: this.model
|
|
|
|
|
// });
|
|
|
|
|
// };
|
|
|
|
|
|
2019-11-07 10:41:14 +08:00
|
|
|
|
renderEditor() {
|
2020-12-01 11:43:30 +08:00
|
|
|
|
const {theme} = this.props;
|
2019-11-07 10:41:14 +08:00
|
|
|
|
return (
|
|
|
|
|
<CodeEditor
|
|
|
|
|
value={this.state.schemaCode}
|
|
|
|
|
onChange={this.handleChange}
|
2021-11-12 14:07:58 +08:00
|
|
|
|
options={{
|
|
|
|
|
lineNumbers: 'off'
|
|
|
|
|
}}
|
2020-09-16 23:41:51 +08:00
|
|
|
|
// editorFactory={this.editorFactory}
|
|
|
|
|
editorDidMount={this.editorDidMount}
|
2019-11-07 10:41:14 +08:00
|
|
|
|
language="json"
|
2020-12-01 11:43:30 +08:00
|
|
|
|
editorTheme={theme === 'dark' ? 'vs-dark' : 'vs'}
|
2019-11-07 10:41:14 +08:00
|
|
|
|
/>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
render() {
|
2022-04-28 10:53:06 +08:00
|
|
|
|
const {vertical, mini, height, theme, classPrefix} = this.props;
|
|
|
|
|
if (mini) {
|
|
|
|
|
return (
|
|
|
|
|
<div className="Playgroud Playgroud--mini">
|
2022-05-19 13:31:08 +08:00
|
|
|
|
<a onClick={this.toggleDrawer} className="Playgroud-edit-btn">
|
2022-04-28 10:53:06 +08:00
|
|
|
|
编辑代码 <i className="fa fa-code p-l-xs"></i>
|
|
|
|
|
</a>
|
|
|
|
|
<Drawer
|
|
|
|
|
showCloseButton
|
2022-05-19 13:31:08 +08:00
|
|
|
|
closeOnOutside
|
2022-04-28 10:53:06 +08:00
|
|
|
|
resizable
|
|
|
|
|
theme={theme}
|
|
|
|
|
overlay={false}
|
|
|
|
|
position="right"
|
|
|
|
|
show={this.state.isOpened}
|
|
|
|
|
onHide={this.close}
|
|
|
|
|
>
|
|
|
|
|
<div className={`${classPrefix}Drawer-header`}>
|
|
|
|
|
编辑代码(支持编辑实时预览)
|
|
|
|
|
</div>
|
|
|
|
|
<div className={`${classPrefix}Drawer-body no-padder`}>
|
|
|
|
|
{this.renderEditor()}
|
|
|
|
|
</div>
|
|
|
|
|
</Drawer>
|
|
|
|
|
<div style={{minHeight: height}} className="Playgroud-preview">
|
|
|
|
|
{this.renderPreview()}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
} else if (vertical) {
|
2019-11-07 10:41:14 +08:00
|
|
|
|
return (
|
2020-12-09 00:35:24 +08:00
|
|
|
|
<div className="Playgroud">
|
|
|
|
|
<div style={{minHeight: height}} className="Playgroud-preview">
|
|
|
|
|
{this.renderPreview()}
|
2019-11-07 10:41:14 +08:00
|
|
|
|
</div>
|
2020-12-09 00:35:24 +08:00
|
|
|
|
<div className="Playgroud-code">{this.renderEditor()}</div>
|
2019-11-07 10:41:14 +08:00
|
|
|
|
</div>
|
|
|
|
|
);
|
2019-04-30 11:11:25 +08:00
|
|
|
|
}
|
|
|
|
|
|
2019-11-07 10:41:14 +08:00
|
|
|
|
return (
|
|
|
|
|
<div
|
|
|
|
|
style={{
|
|
|
|
|
position: 'absolute',
|
|
|
|
|
top: 50,
|
|
|
|
|
bottom: 0
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
<div className="hbox">
|
|
|
|
|
<div className="col pos-rlt">
|
2020-10-12 11:19:25 +08:00
|
|
|
|
<div className="scroll-y h-full pos-abt w-full b-b">
|
2019-11-07 10:41:14 +08:00
|
|
|
|
{this.renderPreview()}
|
2019-04-30 11:11:25 +08:00
|
|
|
|
</div>
|
2019-11-07 10:41:14 +08:00
|
|
|
|
</div>
|
|
|
|
|
<div
|
|
|
|
|
className="col bg-light lter b-l bg-auto pos-rlt"
|
|
|
|
|
style={{width: this.state.asideWidth}}
|
|
|
|
|
>
|
|
|
|
|
<div className="resizer" onMouseDown={this.handleMouseDown} />
|
|
|
|
|
{this.renderEditor()}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
2019-04-30 11:11:25 +08:00
|
|
|
|
}
|