import React from 'react' import newEventActions from 'actions/newEvent' import treeStores from 'stores/tree' import { getEventBlockByBid, emptyCon } from 'stores/funcs/newEvent' import newEventStores from 'stores/newEvent' import { cpJson, shallowEqualImmutable } from 'utils/utils' import { BLOCK_OP_TYPE } from 'const/const' import BlockEventConItem from './BlockConConItem' export default class BlockConCons extends React.Component { constructor(props) { super(props) this.state = { cons: this.getCons() } this.onEventChange = this.onEventChange.bind(this) this.getCons = this.getCons.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({ cons: this.getCons() }) } } onEventChange(status) { let obj = {} if (status && status.types) { if ( status.types.includes('updateBlockProp') && this.props.bid === status.data.affectBlockId && status.data.prop === 'cons' ) { // 这里需要强制更新, 因为cons是个对象 this.forceUpdate() } } if (Object.keys(obj).length > 0) { this.setState(obj) } } genConItem({ obj, flag }) { let result = {} result['flag'] = flag result['operator'] = obj.op result['value1'] = obj.args[0].expVal result['value2'] = obj.args[1].expVal return result } getCons() { let result = [] let nodeId = this.props.eventNodeId || treeStores.curEventNodeId let block = getEventBlockByBid(this.props.bid, nodeId) if ( block && (block.op === BLOCK_OP_TYPE.IF || block.op === BLOCK_OP_TYPE.ELSE) ) { let conObj = block.args[0] if (conObj && conObj.op) { switch (conObj.op) { case 'or': let orArgs = conObj.args orArgs.forEach(orItem => { if (orItem.op === 'and') { let andArgs = orItem.args andArgs.forEach((andItem, index) => { let flag = index === 0 ? 'or' : 'and' let con = this.genConItem({ obj: andItem, flag }) result.push(con) }) } else { let con = this.genConItem({ obj: orItem, flag: 'or' }) result.push(con) } }) break case 'and': let andArgs = conObj.args andArgs.forEach(andItem => { let con = this.genConItem({ obj: andItem, flag: 'and' }) result.push(con) }) break default: let con = this.genConItem({ obj: conObj, flag: 'and' }) result.push(con) } } } return result } genConObj(conItem) { let obj = { op: conItem.operator, args: [ { op: 'var', expVal: conItem.value1, args: [] }, { op: 'var', expVal: conItem.value2, args: [] } ] } return obj } changeConsAst() { // 将cons数组转为ast格式 let cons = cpJson(this.state.cons) 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 = this.genConObj(conItem) andObj.args.push(conObj) }) consAst.args.push(andObj) } else { // 单个条件 let conObj = this.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 = this.genConObj(conItem) consAst.args.push(conObj) }) } else { // 单个条件 consAst = this.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.cons let newEmptyCon = emptyCon() cons.push(newEmptyCon) } delBlockCon({ index, resetLast }) { let cons = this.state.cons if (resetLast && cons.length === 1) { cons[0] = emptyCon() } else { cons.splice(index, 1) } if (cons.length === 1) { cons[0].flag = 'and' } } render() { let cons = (
{this.state.cons.map((con, index) => { return ( ) })}
) return (
{!this.state.cons || this.state.cons.length === 0 ? null : cons}
) } }