BlockConCons.jsx 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. import React from 'react'
  2. import newEventActions from 'actions/newEvent'
  3. import treeStores from 'stores/tree'
  4. import {
  5. getEventBlockByBid,
  6. emptyCon,
  7. genConObj,
  8. consAstToArray
  9. } from 'stores/funcs/newEvent'
  10. import newEventStores from 'stores/newEvent'
  11. import { cpJson, shallowEqualImmutable } from 'utils/utils'
  12. import { BLOCK_OP_TYPE } from 'const/const'
  13. import BlockEventConItem from './BlockConConItem'
  14. export default class BlockConCons extends React.Component {
  15. constructor(props) {
  16. super(props)
  17. this.state = {
  18. cons: this.getCons()
  19. }
  20. this.onEventChange = this.onEventChange.bind(this)
  21. this.getCons = this.getCons.bind(this)
  22. this.changeConsAst = this.changeConsAst.bind(this)
  23. this.addBlockCon = this.addBlockCon.bind(this)
  24. this.delBlockCon = this.delBlockCon.bind(this)
  25. }
  26. shouldComponentUpdate(nextProps, nextState) {
  27. return (
  28. !shallowEqualImmutable(this.props, nextProps) ||
  29. !shallowEqualImmutable(this.state, nextState)
  30. )
  31. }
  32. componentDidMount() {
  33. this.unsubscribe = newEventStores.listen(this.onEventChange)
  34. }
  35. componentWillUnmount() {
  36. this.unsubscribe()
  37. }
  38. componentDidUpdate(preProps) {
  39. if (preProps.bid !== this.props.bid) {
  40. this.setState({
  41. cons: this.getCons()
  42. })
  43. }
  44. }
  45. onEventChange(status) {
  46. let obj = {}
  47. if (status && status.types) {
  48. if (
  49. status.types.includes('updateBlockProp') &&
  50. this.props.bid === status.data.affectBlockId &&
  51. status.data.prop === 'cons'
  52. ) {
  53. // 这里需要强制更新, 因为cons是个对象
  54. this.forceUpdate()
  55. }
  56. }
  57. if (Object.keys(obj).length > 0) {
  58. this.setState(obj)
  59. }
  60. }
  61. getCons() {
  62. let result = []
  63. let nodeId = this.props.eventNodeId || treeStores.curEventNodeId
  64. let block = getEventBlockByBid(this.props.bid, nodeId)
  65. if (
  66. block &&
  67. (block.op === BLOCK_OP_TYPE.IF || block.op === BLOCK_OP_TYPE.ELSE)
  68. ) {
  69. let conObj = block.args[0]
  70. result = consAstToArray(conObj)
  71. }
  72. return result
  73. }
  74. changeConsAst() {
  75. // 将cons数组转为ast格式
  76. let cons = cpJson(this.state.cons)
  77. let ors = []
  78. let ands = []
  79. cons.forEach((con, index) => {
  80. if (con.flag !== 'or') {
  81. ands.push(con)
  82. } else {
  83. ors.push(ands)
  84. ands = []
  85. ands.push(con)
  86. }
  87. if (index === cons.length - 1) {
  88. ors.push(ands)
  89. }
  90. })
  91. let consAst = {}
  92. if (ors.length > 1) {
  93. // 有or
  94. consAst.op = 'or'
  95. consAst.args = []
  96. ors.forEach(orItem => {
  97. if (orItem.length > 1) {
  98. // 多个条件
  99. let andObj = {
  100. op: 'and',
  101. args: []
  102. }
  103. orItem.forEach(conItem => {
  104. let conObj = genConObj(conItem)
  105. andObj.args.push(conObj)
  106. })
  107. consAst.args.push(andObj)
  108. } else {
  109. // 单个条件
  110. let conObj = genConObj(orItem[0])
  111. consAst.args.push(conObj)
  112. }
  113. })
  114. } else {
  115. // 没有or
  116. consAst.op = 'and'
  117. consAst.args = []
  118. let andArray = ors[0]
  119. if (andArray.length > 1) {
  120. // 多个条件
  121. andArray.forEach(conItem => {
  122. let conObj = genConObj(conItem)
  123. consAst.args.push(conObj)
  124. })
  125. } else {
  126. // 单个条件
  127. consAst = genConObj(andArray[0])
  128. }
  129. }
  130. let nodeId = this.props.eventNodeId || treeStores.curEventNodeId
  131. newEventActions.updateBlockProp({
  132. nodeId,
  133. blockId: this.props.bid,
  134. prop: 'cons',
  135. value: consAst,
  136. trigger: true,
  137. addRecord: true
  138. })
  139. }
  140. addBlockCon() {
  141. let cons = this.state.cons
  142. let newEmptyCon = emptyCon()
  143. cons.push(newEmptyCon)
  144. }
  145. delBlockCon({ index, resetLast }) {
  146. let cons = this.state.cons
  147. if (resetLast && cons.length === 1) {
  148. cons[0] = emptyCon()
  149. } else {
  150. cons.splice(index, 1)
  151. }
  152. if (cons.length === 1) {
  153. cons[0].flag = 'and'
  154. }
  155. }
  156. render() {
  157. let cons = (
  158. <div className="con-items-wrap">
  159. {this.state.cons.map((con, index) => {
  160. return (
  161. <BlockEventConItem
  162. index={index}
  163. con={con}
  164. key={index}
  165. layer={this.props.layer}
  166. groupLayer={this.props.groupLayer}
  167. nestGroupLayer={this.props.nestGroupLayer}
  168. extraGapGroupLayer={this.props.extraGapGroupLayer}
  169. bid={this.props.bid}
  170. eventNodeId={this.props.eventNodeId}
  171. onConsChange={this.changeConsAst}
  172. onAddBlockCon={this.addBlockCon}
  173. onDelBlockCon={this.delBlockCon}
  174. />
  175. )
  176. })}
  177. </div>
  178. )
  179. return (
  180. <div className="con-cons flex-1">
  181. {!this.state.cons || this.state.cons.length === 0 ? null : cons}
  182. </div>
  183. )
  184. }
  185. }