176 lines
6.6 KiB
JavaScript
176 lines
6.6 KiB
JavaScript
import React, { Component } from "react";
|
|
import { Button } from "antd";
|
|
import { WeaLocaleProvider } from "ecCom";
|
|
import { Controlled as CodeMirror } from "react-codemirror2";
|
|
import { keyboardBaseBtns } from "./constants";
|
|
import CodeAction from "./components/codeAction";
|
|
import cs from "classnames";
|
|
import "./index.less";
|
|
import "codemirror/lib/codemirror.css";
|
|
import "codemirror/lib/codemirror.js";
|
|
import "codemirror/mode/javascript/javascript.js";
|
|
|
|
require("./extendCodeMirror");
|
|
const getLabel = WeaLocaleProvider.getLabel;
|
|
|
|
class ExcelEditor extends Component {
|
|
constructor(props) {
|
|
super(props);
|
|
this.state = {
|
|
value: "",
|
|
isFormter: false,
|
|
isCustomFunctionClick: false
|
|
};
|
|
this.editorRef = null;
|
|
this.timer = null;
|
|
}
|
|
|
|
componentWillReceiveProps(nextProps, nextContext) {
|
|
if (nextProps.value !== this.props.value && nextProps.value) this.setState({ value: nextProps.value });
|
|
}
|
|
|
|
componentWillUnmount() {
|
|
if (this.timer) clearInterval(this.timer);
|
|
this.setState({ isCustomFunctionClick: false });
|
|
}
|
|
|
|
autoFormatSelection = () => {
|
|
const { isFormter } = this.state;
|
|
if (isFormter) {
|
|
const script_length = this.editorRef.getValue().length;
|
|
const startPos = { line: 0, ch: 0, sticky: null };
|
|
const endPos = this.editorRef.doc.posFromIndex(script_length);
|
|
this.editorRef.setSelection(startPos, endPos);
|
|
this.editorRef.autoFormatRange(startPos, endPos);
|
|
this.editorRef.commentRange(true, startPos, endPos);
|
|
} else {
|
|
this.editorRef.undo();
|
|
this.editorRef.undo();
|
|
}
|
|
};
|
|
insertText = text => {
|
|
const cursor = this.editorRef.getCursor();
|
|
this.editorRef.replaceRange(text, cursor);
|
|
this.editorRef.refresh();
|
|
this.editorRef.focus();
|
|
};
|
|
replaceToWidget = (editor) => {
|
|
editor.getAllMarks().forEach(m => m.clear());
|
|
};
|
|
handleVariSelect = str => this.insertText(`{${str}}`);
|
|
handleFuncSelect = str => {
|
|
const cursor = this.editorRef.getCursor();
|
|
this.editorRef.replaceRange(`${str}()`, cursor);
|
|
this.timer = setTimeout(() => {
|
|
const { line, ch } = this.editorRef.getCursor();
|
|
this.editorRef.setCursor({ line, ch: ch - 1 });
|
|
this.editorRef.refresh();
|
|
this.editorRef.focus();
|
|
}, 100);
|
|
};
|
|
handleEditorRedo = () => {
|
|
const { ch, line } = this.editorRef.getCursor();
|
|
const delStr = this.editorRef.getRange({ line, ch: ch - 1 }, { line, ch });
|
|
const codeValue = this.editorRef.getValue();
|
|
if (delStr === "}") {
|
|
if (codeValue.slice(0, ch).lastIndexOf("{") === -1) {
|
|
this.editorRef.replaceRange("", { line, ch: ch - 1 }, { line, ch });
|
|
} else {
|
|
this.editorRef.replaceRange("", { line, ch: codeValue.slice(0, ch).lastIndexOf("{") }, { line, ch });
|
|
}
|
|
} else {
|
|
this.editorRef.replaceRange("", { line, ch: ch - 1 }, { line, ch });
|
|
}
|
|
this.editorRef.refresh();
|
|
this.editorRef.focus();
|
|
};
|
|
handleBackSpaceRedo = () => {
|
|
const { ch, line } = this.editorRef.getCursor();
|
|
const delStr = this.editorRef.getRange({ line, ch: ch - 1 }, { line, ch });
|
|
const codeValue = this.editorRef.getValue();
|
|
if (delStr === "}") {
|
|
if (codeValue.slice(0, ch).lastIndexOf("{") === -1) {
|
|
this.editorRef.replaceRange("", { line, ch: ch - 1 }, { line, ch });
|
|
} else {
|
|
this.editorRef.replaceRange("", { line, ch: codeValue.slice(0, ch).lastIndexOf("{") + 1 }, { line, ch });
|
|
}
|
|
}
|
|
this.editorRef.refresh();
|
|
this.editorRef.focus();
|
|
};
|
|
|
|
render() {
|
|
const { isFormter, isCustomFunctionClick } = this.state;
|
|
const { groupParams = {}, isCustomFunction, value, onChangeCustomFunction } = this.props;
|
|
const { referenceType } = groupParams;
|
|
return (
|
|
<React.Fragment>
|
|
<div className="excel-codeWrap">
|
|
<div className="excel-codeBox">
|
|
<CodeMirror
|
|
editorDidMount={editor => this.editorRef = editor}
|
|
value={this.state.value}
|
|
onBeforeChange={(editor, data, value) => {
|
|
this.setState({ value }, () => this.props.onChange(this.state.value));
|
|
}}
|
|
onChange={(editor, data, value) => {
|
|
this.replaceToWidget(editor, data, value);
|
|
}}
|
|
options={{
|
|
lineNumbers: false,
|
|
mode: "javascript",
|
|
autofocus: false,
|
|
styleActiveLine: true,
|
|
lineWrapping: true,
|
|
matchBrackets: true,
|
|
lint: false,
|
|
indentUnit: 2,
|
|
cursorHeight: 0.85,
|
|
placeholder: "",
|
|
showCursorWhenSelecting: true
|
|
}}
|
|
onKeyDown={(_, { keyCode }) => keyCode === 8 && this.handleBackSpaceRedo()}
|
|
/>
|
|
</div>
|
|
{
|
|
referenceType !== "sql" &&
|
|
<div className="excel-codeBox-keyboard">
|
|
<div className="excel-codeBox-keyboard-operate">
|
|
<div className="excel-codeBox-keyboard-operate-content">
|
|
{
|
|
_.map(keyboardBaseBtns, item => {
|
|
const { key, label } = item;
|
|
return <Button
|
|
key={key} title={label} size="small"
|
|
className={cs(key === " " ? "excel-codeBox-keyboard-space" : "excel-codeBox-keyboard-base")}
|
|
onClick={() => this.insertText(key)}
|
|
>{label}</Button>;
|
|
})
|
|
}
|
|
</div>
|
|
<div className="excel-codeBox-keyboard-operate-clear">
|
|
<Button title="←" size="small" className="excel-codeBox-keyboard-del"
|
|
onClick={this.handleEditorRedo}>←</Button>
|
|
<Button title="C" size="small" className="excel-codeBox-keyboard-clear"
|
|
onClick={() => this.setState({ value: "", isCustomFunctionClick: true })}>C</Button>
|
|
</div>
|
|
</div>
|
|
<Button type="ghost"
|
|
onClick={() => this.setState({ isFormter: !isFormter }, () => this.autoFormatSelection())}>
|
|
{!isFormter ? getLabel(111, "格式美化") : getLabel(111, "格式还原")}
|
|
</Button>
|
|
</div>
|
|
}
|
|
</div>
|
|
{/*公式参数列表*/}
|
|
<CodeAction groupParams={groupParams} isCustomFunction={isCustomFunction} onVariSelect={this.handleVariSelect}
|
|
onFuncSelect={this.handleFuncSelect} codeVal={value} isCustomFunctionClick={isCustomFunctionClick}
|
|
onChangeCustomFunction={onChangeCustomFunction}
|
|
/>
|
|
</React.Fragment>
|
|
);
|
|
}
|
|
}
|
|
|
|
export default ExcelEditor;
|