|
@@ -0,0 +1,292 @@
|
|
|
|
|
+import React from 'react'
|
|
|
|
|
+import i18n from 'i18next'
|
|
|
|
|
+import newEventActions from 'actions/newEvent'
|
|
|
|
|
+import newEventStores from 'stores/newEvent'
|
|
|
|
|
+import treeStores from 'stores/tree'
|
|
|
|
|
+import {
|
|
|
|
|
+ getEventBlockByBid,
|
|
|
|
|
+ emptyCon,
|
|
|
|
|
+ genConObj,
|
|
|
|
|
+ consAstToArray
|
|
|
|
|
+} from 'stores/funcs/newEvent'
|
|
|
|
|
+import { cpJson, shallowEqualImmutable } from 'utils/utils'
|
|
|
|
|
+import { consFormulaShow } from 'utils/commons/ctrlHide'
|
|
|
|
|
+import { BLOCK_OP_TYPE } from 'const/const'
|
|
|
|
|
+import BlockLoopConItem from './BlockLoopConItem'
|
|
|
|
|
+import FormulaEditor from 'src/components/common/formulaEditor/EventFormulaEditor'
|
|
|
|
|
+
|
|
|
|
|
+export default class BlockLoopCustom extends React.Component {
|
|
|
|
|
+ constructor(props) {
|
|
|
|
|
+ super(props)
|
|
|
|
|
+ this.state = {
|
|
|
|
|
+ option: this.getLoopOption(props.bid),
|
|
|
|
|
+ custom: this.getLoopCustom(this.getLoopOption(props.bid), props.bid)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ this.onEventChange = this.onEventChange.bind(this)
|
|
|
|
|
+ this.onChangeTimes = this.onChangeTimes.bind(this)
|
|
|
|
|
+ this.getLoopOption = this.getLoopOption.bind(this)
|
|
|
|
|
+ this.getLoopCustom = this.getLoopCustom.bind(this)
|
|
|
|
|
+ this.getCustomCom = this.getCustomCom.bind(this)
|
|
|
|
|
+ this.changeConsAst = this.changeConsAst.bind(this)
|
|
|
|
|
+ this.addBlockCon = this.addBlockCon.bind(this)
|
|
|
|
|
+ this.delBlockCon = this.delBlockCon.bind(this)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ shouldComponentUpdate(nextProps, nextState) {
|
|
|
|
|
+ return (
|
|
|
|
|
+ !shallowEqualImmutable(this.props, nextProps) ||
|
|
|
|
|
+ !shallowEqualImmutable(this.state, nextState)
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ componentDidMount() {
|
|
|
|
|
+ this.unsubscribe = newEventStores.listen(this.onEventChange)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ componentWillUnmount() {
|
|
|
|
|
+ this.unsubscribe()
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ componentDidUpdate(preProps) {
|
|
|
|
|
+ if (preProps.bid !== this.props.bid) {
|
|
|
|
|
+ this.setState({
|
|
|
|
|
+ option: this.getLoopOption(),
|
|
|
|
|
+ custom: this.getLoopCustom(this.getLoopOption())
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ onEventChange(status) {
|
|
|
|
|
+ let obj = {}
|
|
|
|
|
+ if (status && status.types) {
|
|
|
|
|
+ if (
|
|
|
|
|
+ status.types.includes('updateBlockProp') &&
|
|
|
|
|
+ this.props.bid === status.data.affectBlockId &&
|
|
|
|
|
+ status.data.prop === 'op'
|
|
|
|
|
+ ) {
|
|
|
|
|
+ let option = this.getLoopOption()
|
|
|
|
|
+ if (this.state.option !== option) {
|
|
|
|
|
+ obj.option = option
|
|
|
|
|
+ obj.custom = this.getLoopCustom(option)
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if (
|
|
|
|
|
+ status.types.includes('updateBlockProp') &&
|
|
|
|
|
+ this.props.bid === status.data.affectBlockId &&
|
|
|
|
|
+ status.data.prop === 'cons'
|
|
|
|
|
+ ) {
|
|
|
|
|
+ this.forceUpdate()
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if (Object.keys(obj).length > 0) {
|
|
|
|
|
+ this.setState(obj)
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ genForCons(blockId, value) {
|
|
|
|
|
+ return {
|
|
|
|
|
+ op: 'let',
|
|
|
|
|
+ val: [blockId, 'int'],
|
|
|
|
|
+ args: [{ op: 'step', args: [{ op: 'var', expVal: value, args: [] }] }]
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ onChangeTimes(value) {
|
|
|
|
|
+ this.setState(
|
|
|
|
|
+ {
|
|
|
|
|
+ custom: value
|
|
|
|
|
+ },
|
|
|
|
|
+ () => {
|
|
|
|
|
+ let forCons = this.genForCons(this.props.bid, value)
|
|
|
|
|
+ newEventActions.updateBlockProp({
|
|
|
|
|
+ blockId: this.props.bid,
|
|
|
|
|
+ prop: 'cons',
|
|
|
|
|
+ value: forCons
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ getLoopOption(bid) {
|
|
|
|
|
+ let _bid = bid || this.props.bid
|
|
|
|
|
+ let nodeId = this.props.eventNodeId || newEventStores.curEventNodeId
|
|
|
|
|
+ let block = getEventBlockByBid(_bid, nodeId)
|
|
|
|
|
+ if (block) {
|
|
|
|
|
+ return block.op || BLOCK_OP_TYPE.FOR
|
|
|
|
|
+ }
|
|
|
|
|
+ return BLOCK_OP_TYPE.FOR
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ getLoopCustom(option, bid) {
|
|
|
|
|
+ let _bid = bid || this.props.bid
|
|
|
|
|
+ let nodeId = this.props.eventNodeId || newEventStores.curEventNodeId
|
|
|
|
|
+ let block = getEventBlockByBid(_bid, nodeId)
|
|
|
|
|
+ if (block) {
|
|
|
|
|
+ switch (option) {
|
|
|
|
|
+ case BLOCK_OP_TYPE.FOR:
|
|
|
|
|
+ return (
|
|
|
|
|
+ block.args &&
|
|
|
|
|
+ block.args[0] &&
|
|
|
|
|
+ block.args[0].args &&
|
|
|
|
|
+ block.args[0].args[0] === 'step' &&
|
|
|
|
|
+ block.args[0].args[0].args &&
|
|
|
|
|
+ block.args[0].args[0].args[0].expVar
|
|
|
|
|
+ )
|
|
|
|
|
+ case BLOCK_OP_TYPE.WHILE:
|
|
|
|
|
+ return consAstToArray(block.args[0])
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return null
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ changeConsAst() {
|
|
|
|
|
+ // 将cons数组转为ast格式
|
|
|
|
|
+ let cons = cpJson(this.state.custom)
|
|
|
|
|
+ let ors = []
|
|
|
|
|
+ let ands = []
|
|
|
|
|
+ cons.forEach((con, index) => {
|
|
|
|
|
+ if (con.flag !== 'or') {
|
|
|
|
|
+ ands.push(con)
|
|
|
|
|
+ } else {
|
|
|
|
|
+ ors.push(ands)
|
|
|
|
|
+ ands = []
|
|
|
|
|
+ ands.push(con)
|
|
|
|
|
+ }
|
|
|
|
|
+ if (index === cons.length - 1) {
|
|
|
|
|
+ ors.push(ands)
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ let consAst = {}
|
|
|
|
|
+ if (ors.length > 1) {
|
|
|
|
|
+ // 有or
|
|
|
|
|
+ consAst.op = 'or'
|
|
|
|
|
+ consAst.args = []
|
|
|
|
|
+ ors.forEach(orItem => {
|
|
|
|
|
+ if (orItem.length > 1) {
|
|
|
|
|
+ // 多个条件
|
|
|
|
|
+ let andObj = {
|
|
|
|
|
+ op: 'and',
|
|
|
|
|
+ args: []
|
|
|
|
|
+ }
|
|
|
|
|
+ orItem.forEach(conItem => {
|
|
|
|
|
+ let conObj = genConObj(conItem)
|
|
|
|
|
+ andObj.args.push(conObj)
|
|
|
|
|
+ })
|
|
|
|
|
+ consAst.args.push(andObj)
|
|
|
|
|
+ } else {
|
|
|
|
|
+ // 单个条件
|
|
|
|
|
+ let conObj = genConObj(orItem[0])
|
|
|
|
|
+ consAst.args.push(conObj)
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+ } else {
|
|
|
|
|
+ // 没有or
|
|
|
|
|
+ consAst.op = 'and'
|
|
|
|
|
+ consAst.args = []
|
|
|
|
|
+ let andArray = ors[0]
|
|
|
|
|
+ if (andArray.length > 1) {
|
|
|
|
|
+ // 多个条件
|
|
|
|
|
+ andArray.forEach(conItem => {
|
|
|
|
|
+ let conObj = genConObj(conItem)
|
|
|
|
|
+ consAst.args.push(conObj)
|
|
|
|
|
+ })
|
|
|
|
|
+ } else {
|
|
|
|
|
+ // 单个条件
|
|
|
|
|
+ consAst = genConObj(andArray[0])
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ let nodeId = this.props.eventNodeId || treeStores.curEventNodeId
|
|
|
|
|
+ newEventActions.updateBlockProp({
|
|
|
|
|
+ nodeId,
|
|
|
|
|
+ blockId: this.props.bid,
|
|
|
|
|
+ prop: 'cons',
|
|
|
|
|
+ value: consAst,
|
|
|
|
|
+ trigger: true,
|
|
|
|
|
+ addRecord: true
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ addBlockCon() {
|
|
|
|
|
+ let cons = this.state.custom
|
|
|
|
|
+ let newEmptyCon = emptyCon()
|
|
|
|
|
+ cons.push(newEmptyCon)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ delBlockCon({ index, resetLast }) {
|
|
|
|
|
+ let cons = this.state.custom
|
|
|
|
|
+ if (resetLast && cons.length === 1) {
|
|
|
|
|
+ cons[0] = emptyCon()
|
|
|
|
|
+ } else {
|
|
|
|
|
+ cons.splice(index, 1)
|
|
|
|
|
+ }
|
|
|
|
|
+ if (cons.length === 1) {
|
|
|
|
|
+ cons[0].flag = 'and'
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ getCustomCom() {
|
|
|
|
|
+ let forCom = () => {
|
|
|
|
|
+ return (
|
|
|
|
|
+ <div className="loop-for-wrap f--hlc">
|
|
|
|
|
+ <div className="for-tag f--hcc">
|
|
|
|
|
+ {i18n.t('EventView.jenga_loop_block.forTag')}
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div className="for-times-wrap f--h">
|
|
|
|
|
+ <FormulaEditor
|
|
|
|
|
+ className="loop-formula-editor loop-for-formula-editor"
|
|
|
|
|
+ uid={this.props.bid + BLOCK_OP_TYPE.FOR}
|
|
|
|
|
+ bid={this.props.bid}
|
|
|
|
|
+ value={this.state.custom}
|
|
|
|
|
+ hasCons={consFormulaShow()}
|
|
|
|
|
+ onChangeCode={this.onChangeTimes}
|
|
|
|
|
+ />
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ let whileCom = () => {
|
|
|
|
|
+ let cons = (
|
|
|
|
|
+ <div className="con-items-wrap">
|
|
|
|
|
+ {this.state.custom.map((con, index) => {
|
|
|
|
|
+ return (
|
|
|
|
|
+ <BlockLoopConItem
|
|
|
|
|
+ index={index}
|
|
|
|
|
+ con={con}
|
|
|
|
|
+ key={index}
|
|
|
|
|
+ layer={this.props.layer}
|
|
|
|
|
+ groupLayer={this.props.groupLayer}
|
|
|
|
|
+ nestGroupLayer={this.props.nestGroupLayer}
|
|
|
|
|
+ extraGapGroupLayer={this.props.extraGapGroupLayer}
|
|
|
|
|
+ bid={this.props.bid}
|
|
|
|
|
+ eventNodeId={this.props.eventNodeId}
|
|
|
|
|
+ onConsChange={this.changeConsAst}
|
|
|
|
|
+ onAddBlockCon={this.addBlockCon}
|
|
|
|
|
+ onDelBlockCon={this.delBlockCon}
|
|
|
|
|
+ />
|
|
|
|
|
+ )
|
|
|
|
|
+ })}
|
|
|
|
|
+ </div>
|
|
|
|
|
+ )
|
|
|
|
|
+ return (
|
|
|
|
|
+ <div className="loop-while-wrap f--hlc">
|
|
|
|
|
+ {!this.state.custom || this.state.custom.length === 0 ? null : cons}
|
|
|
|
|
+ </div>
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ switch (this.state.option) {
|
|
|
|
|
+ case BLOCK_OP_TYPE.FOR:
|
|
|
|
|
+ return forCom()
|
|
|
|
|
+ case BLOCK_OP_TYPE.WHILE:
|
|
|
|
|
+ return whileCom()
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ render() {
|
|
|
|
|
+ return <div className="loop-custom flex-1">{this.getCustomCom()}</div>
|
|
|
|
|
+ }
|
|
|
|
|
+}
|