salary-management-front/pc4mobx/hrmSalary/pages/salaryItem/formalFormModal.js

511 lines
17 KiB
JavaScript

import React from "react";
import { Button, Col, message, Modal, Row } from "antd";
import { WeaCheckbox, WeaDialog, WeaFormItem, WeaHelpfulTip, WeaInput, WeaSelect } from "ecCom";
import { inject, observer } from "mobx-react";
import { testFormual } from "../../apis/item";
import TestModal from "./testModal";
import ExcelEditor from "../../components/excelEditor";
import "./index.less";
@inject("salaryItemStore")
@observer
export default class FormalFormModal extends React.Component {
constructor(props) {
super(props);
this.state = {
validateType: "",
returnType: "",
value: "",
formula: "",
extendParam: {
isCustomFunction: "0",
sqlReturnKey: "",
openDecrypt: "0",
datasource: {
datasourceId: ""
}
},
returnValue: "",
formulaDatasourceList: [],
testVisible: false,
showTestVal: "",
groupParams: {}
};
this.group = {};
this.field = {};
this.parameters = [];
this.referenceType = "";
this.timer = null;
}
componentWillMount() {
const { salaryItemStore, formulaId, valueType } = this.props;
const { salaryAcctImportTemplateParam, setSearchFields, detailFormual } = salaryItemStore;
setSearchFields([]);
if (!!this.props.formulaId && this.props.formulaId != 0) {
detailFormual({
formulaId,
returnType: (valueType.toString() === "2" || valueType.toString() === "FORMULA") ? "formula" : "sql"
}).then(data => {
this.parameters = data.parameters;
this.referenceType = data.referenceType;
this.extendParam = data.extendParam;
if (this.extendParam && this.extendParam.length > 0) {
let extendParam = {};
try {
extendParam = JSON.parse(this.extendParam);
} catch (ex) {
}
this.setState({
extendParam: {
isCustomFunction: extendParam.isCustomFunction || "1",
sqlReturnKey: extendParam.sqlReturnKey,
openDecrypt: extendParam.openDecrypt,
datasource: {
datasourceId: extendParam.datasource ? extendParam.datasource.datasourceId : ""
}
}
});
}
this.setState({
value: data.formula,
formula: data.formula,
returnType: data.returnType,
validateType: data.validateType
});
// salaryAcctImportTemplateParam(groupParams);
});
let groupParams = {};
if (this.props.valueType == "3") {
groupParams = { "referenceType": "sql" };
} else {
groupParams = this.props.backCalcType === "issuedItems" ? { "referenceType": "backCalc" } : {};
}
this.setState({ groupParams });
} else {
let groupParams = {};
if (this.props.valueType == "3") {
groupParams = { "referenceType": "sql" };
} else if (this.props.valueType === "FORMULA") {
groupParams = this.props.backCalcType === "issuedItems" ? { "referenceType": "backCalc" } : {};
this.referenceType = "formula";
this.setState({
value: this.props.formulaContent
});
}
this.setState({ groupParams });
// salaryAcctImportTemplateParam(groupParams);
}
}
componentDidMount() {
this.formulaDatasourceList();
}
componentWillUnmount() {
clearTimeout(this.timer);
}
triggerKeyDown = (e) => {
let propsTextarea = this.contentProps.refs.textareaNormal.refs.input.refs.input; // 获取dom节点实例
const { value } = this.state;
if (e.key === "Backspace" && value) {
const { end } = this.getPositionForTextArea(propsTextarea);
const str = value.substring(end - 1, end);
if (str === "}") {
e.preventDefault();
const index = value.lastIndexOf("{", end - 1);
const currentValue = value.substring(index, end);
this.setState({
value: value.replace(currentValue, "")
}, () => {
if (propsTextarea.setSelectionRange) {
this.timer = setTimeout(() => {
propsTextarea.setSelectionRange(index, index);
}, 0);
}
});
}
}
};
formulaDatasourceList = () => {
const { salaryItemStore } = this.props;
const { formulaDatasourceList } = salaryItemStore;
formulaDatasourceList().then(({ status, data }) => {
if (status) {
this.setState({
formulaDatasourceList: [{
key: "",
showname: ""
}, ..._.map(data, it => ({ key: it, showname: it }))]
});
}
});
};
// 多行文本编辑
handleChange = (value) => {
if (value && value.trim() == "") {
this.parameters = [];
}
this.setState({
value
});
};
// 获取光标位置
getPositionForTextArea(ctrl) {
let CaretPos = {
start: 0,
end: 0
};
if (ctrl.selectionStart) {// Firefox support
CaretPos.start = ctrl.selectionStart;
}
if (ctrl.selectionEnd) {
CaretPos.end = ctrl.selectionEnd;
}
return (CaretPos);
}
// 分组项被点击
handleItemClick(item) {
const { salaryItemStore } = this.props;
const { formualSearchField } = salaryItemStore;
this.group = item;
let params = {};
if (this.props.valueType == "3" || this.referenceType == "sql") {
params = {
extendParam: {
"referenceType": "sql"
}
};
}
formualSearchField(item.key, params);
}
// 保存
handleSave = () => {
const { salaryItemStore } = this.props;
const { saveFormual } = salaryItemStore;
this.parameters = this.parameters.filter(item => this.state.value.indexOf(item.name) > -1);
// 去重
let result = [];
this.parameters.map(item => {
let flag = false;
result.map(i => {
if (item.fieldId == i.fieldId) {
flag = true;
}
});
if (!flag) {
result.push(item);
}
});
this.parameters = result;
let params = {
name: this.props.name || "公式1",
description: "备注",
module: "salary",
useFor: "salaryitem",
returnType: this.props.dataType || this.state.returnType,
validateType: this.props.dataType || this.state.returnType,
extendParam: JSON.stringify(this.state.extendParam),
formula: this.state.value.replace(/[\r\n]/g, ""),
parameters: this.parameters,
referenceType: this.referenceType == "" ? this.props.valueType == "2" ? "formula" : this.props.valueType == "3" ? "sql" : "" : this.referenceType
};
saveFormual(params).then(data => {
this.props.onSaveFormal(data);
this.props.onCancel();
});
};
/**
* name: 获取文本框光标位置
* param {*} obj
* param {*} str
* return {*}
*/
insertText = (obj, str) => {
if (document.selection) {
let sel = document.selection.createRange();
sel.text = str;
} else if (typeof obj.selectionStart === "number" && typeof obj.selectionEnd === "number") {
let startPos = obj.selectionStart,
endPos = obj.selectionEnd,
cursorPos = startPos,
tmpStr = obj.value;
obj.value = tmpStr.substring(0, startPos) + str + tmpStr.substring(endPos, tmpStr.length);
cursorPos += str.length;
obj.selectionStart = obj.selectionEnd = cursorPos;
obj.focus();
this.setState({ value: obj.value });
} else {
obj.value += str;
}
};
// 字段点击回调
handleFieldClick(item) {
this.field = item;
let fieldName = "{" + this.group.value + "." + this.field.name + "}";
let parameterItem = {
name: item.name,
fieldId: item.fieldId,
fieldName: fieldName,
fieldType: item.fieldType,
source: item.source,
orderIndex: this.parameters.length
};
this.parameters.push(parameterItem);
let propsTextarea = this.contentProps.refs.textareaNormal.refs.input.refs.input; // 获取dom节点实例
let position = this.insertText(propsTextarea, fieldName); // 光标的位置
this.forceUpdate();
}
handleChangeTestValue = (record, value) => {
if (!record && !value) {
this.parameters = _.map(this.parameters, item => ({ ...item, content: null }));
this.setState({
showTestVal: "显示结果"
});
} else {
this.parameters = _.map(this.parameters, item => {
if (item.id === record.id) {
return {
...item,
content: value
};
}
return { ...item };
});
}
this.forceUpdate();
};
handleImplement = () => {
this.parameters = this.parameters.filter(item => this.state.value.indexOf(item.name) > -1);
let result = [];
this.parameters.map(item => {
let flag = false;
result.map(i => {
if (item.fieldId == i.fieldId) {
flag = true;
}
});
if (!flag) {
result.push(item);
}
});
this.parameters = result;
let params = {
// name: "公式1",
// description: "备注",
// module: "salary",
// useFor: "salaryitem",
// returnType: this.props.dataType || this.state.returnType,
// validateType: this.props.dataType || this.state.returnType,
// extendParam: JSON.stringify(this.state.extendParam),
// formula: this.state.value,
parameters: _.map(this.parameters, o => ({ ...o, content: o.content || "" })),
id: this.props.formulaId
// referenceType: this.referenceType == "" ? this.props.valueType == "2" ? "formula" : this.props.valueType == "3" ? "sql" : "" : this.referenceType
};
testFormual(params).then(({ status, data, errormsg }) => {
if (status) {
message.success("测试结果已更新");
this.setState({
showTestVal: !_.isNil(data) ? data.toString() : data
});
} else {
message.error(errormsg || "");
}
});
};
handleChangeCustomFunction = (isCustomFunction) => {
const { extendParam } = this.state;
this.setState({
extendParam: {
...extendParam,
isCustomFunction
}
});
};
render() {
const { salaryItemStore } = this.props;
const { searchGroup, searchFields } = salaryItemStore;
const { value, formula, formulaDatasourceList, extendParam, testVisible, showTestVal, groupParams } = this.state;
const title = <div className="formulaTitleWrapper">
<div>{`${(this.props.valueType == 2 || this.props.valueType === "FORMULA") ? "函数" : "SQL"}公式`}</div>
{
!_.isEmpty(value) && <Button type="primary" onClick={() => {
const isSaveBool = _.every(this.parameters, it => !!it.id);
if (value === formula) {
this.setState({ testVisible: true });
} else {
message.info("请先保存公式后再进行测试");
}
}}>测试</Button>
}
{/*公式测试*/}
<TestModal visible={testVisible} testParams={value} parameters={this.parameters}
showTestVal={showTestVal}
onChangeTestValue={this.handleChangeTestValue}
onImplement={this.handleImplement}
onCancel={() => this.setState({ testVisible: false }, () => this.handleChangeTestValue())}/>
</div>;
return (
<WeaDialog
title={title} hasScroll scalable className="formula-wrapper" initLoadCss
visible={this.props.visible} style={{ width: 1000 }}
buttons={[
<Button type="primary" onClick={this.handleSave}>保存</Button>
]}
onCancel={() => {
this.props.onCancel();
}}>
{
(this.props.valueType == "3" || this.referenceType == "sql") &&
<Row gutter={20} style={{ marginBottom: 10 }}>
<Col span={12}>
<WeaFormItem
label="返回字段"
labelCol={{ span: 6 }}
wrapperCol={{ span: 18 }}
>
<WeaInput style={{ width: "100%" }} value={extendParam.sqlReturnKey} onChange={(sqlReturnKey) => {
this.setState({ extendParam: { ...extendParam, sqlReturnKey } });
}}/>
</WeaFormItem>
</Col>
<Col span={12} className="dataList-wrapper">
<WeaFormItem
label="外部数据源"
labelCol={{ span: 6 }}
wrapperCol={{ span: 18 }}
>
<WeaSelect
options={formulaDatasourceList}
value={extendParam.datasource.datasourceId}
onChange={(datasourceId) => {
if (datasourceId) {
Modal.confirm({
title: "信息确认",
content: "外部数据源指第三方数据库,连接第三方数据库会影响核算效率。",
onOk: () => {
this.setState({ extendParam: { ...extendParam, datasource: { datasourceId } } });
},
onCancel: () => {
this.setState({ extendParam: { ...extendParam, datasource: { datasourceId: "" } } });
}
});
} else {
this.setState({ extendParam: { ...extendParam, datasource: { datasourceId: "" } } });
}
}}
/>
<WeaHelpfulTip
width={196}
title="不设置,默认使用系统数据源。"
isCenter={true}
/>
</WeaFormItem>
</Col>
<Col span={12}>
<WeaFormItem
label="开启解密"
labelCol={{ span: 6 }}
wrapperCol={{ span: 18 }}
>
<WeaCheckbox
style={{ marginRight: 8 }}
display="switch"
value={extendParam.openDecrypt}
onChange={(openDecrypt) => {
this.setState({ extendParam: { ...extendParam, openDecrypt } });
}}
/>
<WeaHelpfulTip
width={196}
title="若需要获取薪酬加密数据,需开启解密。"
isCenter={true}
/>
</WeaFormItem>
</Col>
</Row>
}
<ExcelEditor value={value} groupParams={groupParams} isCustomFunction={extendParam.isCustomFunction}
onChange={(value) => this.handleChange(value)}
onChangeCustomFunction={this.handleChangeCustomFunction}/>
{/*<div>*/}
{/* <WeaTextarea*/}
{/* ref={(input) => this.contentProps = input}*/}
{/* minRows={8}*/}
{/* maxRows={8}*/}
{/* value={value}*/}
{/* onChange={(value) => this.handleChange(value)}*/}
{/* noResize={true}*/}
{/* style={{ fontSize: "14px", lineHeight: 1.2 }}*/}
{/* onKeyDown={this.triggerKeyDown}*/}
{/* />*/}
{/*</div>*/}
{/*<div style={{ display: "flex", height: "300px", marginTop: "10px" }}>*/}
{/* <div style={{*/}
{/* flex: 1,*/}
{/* height: "300px",*/}
{/* overflowY: "scroll",*/}
{/* padding: "10px",*/}
{/* border: "1px solid rgb(217, 217, 217)",*/}
{/* marginRight: "10px"*/}
{/* }}>*/}
{/* <div>*/}
{/* <div style={{ marginBottom: "10px", fontSize: "14px" }}>变量</div>*/}
{/* <div>*/}
{/* {*/}
{/* searchGroup && searchGroup.map(item => {*/}
{/* return <div style={{ height: "25px", lineHeight: "25px", cursor: "pointer", overflow: "hidden" }}*/}
{/* key={item.key} onClick={() => {*/}
{/* this.handleItemClick(item);*/}
{/* }}>*/}
{/* {item.value}*/}
{/* <Icon type="right" style={{ float: "right", marginLeft: "10px", color: "#eee", marginTop: "9px" }}/>*/}
{/* <span style={{ color: "#999", float: "right" }}>{item.value} 的字段</span>*/}
{/* </div>;*/}
{/* })*/}
{/* }*/}
{/* </div>*/}
{/* </div>*/}
{/* </div>*/}
{/* <div style={{*/}
{/* flex: 1,*/}
{/* height: "300px",*/}
{/* overflowY: "scroll",*/}
{/* border: "1px solid rgb(217, 217, 217)",*/}
{/* padding: "10px"*/}
{/* }}>*/}
{/* {*/}
{/* searchFields && searchFields.map(item => {*/}
{/* return (*/}
{/* <div style={{ height: "25px", lineHeight: "25px", cursor: "pointer" }} key={item.fieldId}*/}
{/* onClick={() => {*/}
{/* this.handleFieldClick(item);*/}
{/* }}>*/}
{/* {item.name}*/}
{/* </div>*/}
{/* );*/}
{/* })*/}
{/* }*/}
{/* </div>*/}
{/*</div>*/}
</WeaDialog>
);
}
}