@ovine/editor
Version:
Ovine json editor.
166 lines (165 loc) • 7.18 kB
JavaScript
import { toast, confirm } from 'amis';
import cls from 'classnames';
import copy from 'copy-to-clipboard';
import _ from 'lodash';
import { observer, inject } from 'mobx-react';
import React, { useEffect, useRef } from 'react';
import { app } from "../../../../core/lib/app";
import { saveToFile } from "../../../../core/lib/utils/file";
import { editorStore } from "../../stores/editor";
import { StyledHeader } from "./styled";
// TODO: 优化 getSchemaString
export default inject('store')(observer((props) => {
const { isPreview, option, isDirty, isMobile, togglePreview, toggleViewMode, setLastSavedSchema, editorInstance, } = props.store;
const { breadcrumb, onExit, onSave, saveApi, saveInterval } = option;
const timerRef = useRef(0);
const hasPrevStep = editorInstance.canUndo();
const hasNextStep = editorInstance.canRedo();
const getBreadcrumbItems = () => {
return typeof breadcrumb === 'string' ? [breadcrumb] : breadcrumb;
};
const getSchemaString = (errTip) => {
let value = '';
try {
value = JSON.stringify(editorStore.schema);
}
catch (__) {
toast.error(errTip, 'JSON解析错误');
return false;
}
return value;
};
const onExitEditor = () => {
if (isPreview) {
togglePreview();
return;
}
const exit = () => {
let exitRes = true;
if (onExit) {
exitRes = onExit();
}
if (exitRes !== false) {
if (app.routerHistory.length) {
app.routerHistory.goBack();
}
else {
app.routerHistory.replace('/');
}
}
};
if (isDirty) {
confirm('当前存在未保存的改动,退出将视为放弃更改!', '确定退出编辑器?').then((choose) => {
if (choose) {
exit();
}
});
return;
}
exit();
};
const onCopyClick = () => {
const value = getSchemaString('复制操作执行失败!');
if (value) {
copy(value);
toast.success('复制成功');
}
};
const onDownloadClick = () => {
const value = getSchemaString('下载操作执行失败!');
if (value) {
saveToFile(value, 'text/plain', `${_.last(getBreadcrumbItems())}.json`);
toast.success('文件下载成功');
}
};
const renderBreadcrumb = () => {
if (!breadcrumb) {
return React.createElement("span", null, "\u672A\u77E5\u9875\u9762");
}
return (React.createElement("nav", { "aria-label": "breadcrumb" },
React.createElement("ol", { className: "breadcrumb " }, getBreadcrumbItems().map((text, index) => {
return (React.createElement("li", { key: index, className: "breadcrumb-item text-ellipsis" }, text));
}))));
};
const saveSchemaApi = (mounted = false) => {
const value = editorStore.schema;
saveApi.data = Object.assign(Object.assign({}, saveApi.data), { schema: value });
return app
.request(saveApi)
.then((source) => {
const { status, msg } = source.data;
if (!mounted) {
if (status === 0) {
toast.success(msg || '保存成功', '系统提示');
}
else {
toast.error(msg || '保存失败', '系统提示');
}
}
if (onSave) {
onSave(value);
}
setLastSavedSchema(value);
return source;
})
.catch((source) => {
toast.error((source === null || source === void 0 ? void 0 : source.msg) || '保存失败', '系统提示');
});
};
const onSaveClick = () => {
const value = editorStore.schema;
if (saveApi) {
saveSchemaApi();
return;
}
if (onSave) {
onSave(value);
}
setLastSavedSchema(value);
toast.success('当前编辑数据已经保存', '系统提示');
};
useEffect(() => {
if (saveApi && saveInterval > 2 * 1000) {
if (timerRef.current) {
clearInterval(timerRef.current);
}
timerRef.current = setInterval(() => {
saveSchemaApi(true);
}, saveInterval);
}
return () => {
if (timerRef.current) {
clearInterval(timerRef.current);
}
};
}, []);
return (React.createElement(StyledHeader, null,
React.createElement("div", { className: "toolbar-left" },
React.createElement("i", { className: "fa fa-chevron-left back-icon", "data-tooltip": "\u9000\u51FA", "data-position": "bottom", onClick: onExitEditor }),
renderBreadcrumb()),
React.createElement("div", { className: "toolbar-main" },
React.createElement("div", { className: cls('toolbar-item', { active: isPreview }), onClick: togglePreview },
React.createElement("i", { className: `fa ${isPreview ? 'fa-eye-slash' : 'fa-eye'}` }),
React.createElement("span", null, "\u9884\u89C8")),
React.createElement("div", { className: cls('toolbar-item view-mode', {
active: !isPreview && isMobile,
}), onClick: toggleViewMode },
React.createElement("i", { className: `fa ${isMobile ? 'fa-mobile' : 'fa-desktop'}` }),
React.createElement("span", null, isMobile ? '移动端' : 'PC端')),
React.createElement("div", { className: cls('toolbar-item', { disabled: isPreview || !hasPrevStep }), onClick: () => editorInstance.undo() },
React.createElement("i", { className: "fa fa-reply" }),
React.createElement("span", null, "\u64A4\u9500")),
React.createElement("div", { className: cls('toolbar-item', { disabled: isPreview || !hasNextStep }), onClick: () => editorInstance.redo() },
React.createElement("i", { className: "fa fa-share" }),
React.createElement("span", null, "\u56DE\u9000")),
React.createElement("div", { className: cls('toolbar-item'), onClick: onCopyClick },
React.createElement("i", { className: "fa fa-copy" }),
React.createElement("span", null, "\u590D\u5236")),
React.createElement("div", { className: cls('toolbar-item'), onClick: onDownloadClick },
React.createElement("i", { className: "fa fa-save" }),
React.createElement("span", null, "\u5BFC\u51FA")),
React.createElement("div", { className: cls('toolbar-item'), onClick: onSaveClick },
React.createElement("i", { className: "fa fa-cloud-upload " }),
React.createElement("span", null, "\u4FDD\u5B58"))),
React.createElement("div", { className: "toolbar-right" })));
}));