Jelajahi Sumber

new event view

lianghuang 4 tahun lalu
induk
melakukan
22e20420f7

+ 2 - 2
coms/jenga/block/base/BlockEnable.jsx

@@ -38,10 +38,10 @@ export default class BlockEnable extends React.Component {
       hasDisabled = hasDisabled || !result
     }
     if (!hasDisabled) {
-      let block = getParentBlock(this.props.bid, eventNode)
+      let block = getParentBlock(this.props.bid, eventNode.id)
       while (!hasDisabled && block) {
         hasDisabled = hasDisabled || block.skip
-        block = getParentBlock(block.ln, eventNode)
+        block = getParentBlock(block.ln, eventNode.id)
       }
     }
     return hasDisabled

+ 536 - 0
coms/jenga/block/base/action/BlockActionObject.jsx

@@ -0,0 +1,536 @@
+import React from 'react'
+import cls from 'classnames'
+import i18n from 'i18next'
+import { Menu, Dropdown } from 'antd'
+import newEventActions from 'actions/newEvent'
+import treeActions from 'actions/tree'
+import newEventStores from 'stores/newEvent'
+import widgetStore from 'stores/widget'
+import treeStores from 'stores/tree'
+import { shallowEqualImmutable } from 'utils/utils'
+import getTypeIcon from 'utils/commons/getTypeIcon'
+import {
+  getEventBlockByBid,
+  getParentBlock,
+  getChildIndex,
+  getEventNodeById,
+  getActionBlockObjNode
+} from 'stores/funcs/newEvent'
+import {
+  nodeIsFunctionGroup,
+  nodeIsService,
+  nodeIsTransaction,
+  nodeIsIotMessage,
+  nodeIsDyTransaction,
+  nodeIsFunction
+} from 'stores/funcs/nodeType'
+import { getNodeIconByEnvs } from 'stores/funcs/tree'
+import {
+  isServerRootNode,
+  isChangedActionValid
+} from 'stores/funcs/event/methodUtils'
+import { getNodeTypeName, getFakeNodeIds } from 'stores/funcs/event/fakeNode'
+import { EVENT_BLOCK_TYPE, BLOCK_OP_TYPE } from 'const/const'
+import { specialActionObj, fakeNodeIds } from 'const/enum'
+import BlockEnable from '../BlockEnable'
+import ObjSelector from 'src/components/common/objSelector/ObjSelector'
+import TitleTip from 'src/components/common/titleTip/TitleTip'
+
+const MenuItem = Menu.Item
+
+export default class BlockActionObject extends React.Component {
+  constructor(props) {
+    super(props)
+    this.curEventNodeId = newEventStores.curEventNodeId
+    this.state = {
+      object: this.getObject()
+    }
+    this.objSelector = React.createRef()
+
+    this.onEventChange = this.onEventChange.bind(this)
+    this.genObjSelectConfig = this.genObjSelectConfig.bind(this)
+
+    this.onAddAction = this.onAddAction.bind(this)
+
+    this.shouldClearAction = this.shouldClearAction.bind(this)
+    this.dealChangeActionObject = this.dealChangeActionObject.bind(this)
+    this.onSelectObj = this.onSelectObj.bind(this)
+    this.onActionObjectSelect = this.onActionObjectSelect.bind(this)
+
+    this.getSpecialObjName = this.getSpecialObjName.bind(this)
+    this.getActionObjName = this.getActionObjName.bind(this)
+    this.getActionObjIcon = this.getActionObjIcon.bind(this)
+    this.getObject = this.getObject.bind(this)
+
+    this.jumpToNode = this.jumpToNode.bind(this)
+    this.objJumpBtn = this.objJumpBtn.bind(this)
+  }
+
+  shouldComponentUpdate(nextProps, nextState) {
+    return (
+      !shallowEqualImmutable(this.props, nextProps) ||
+      !shallowEqualImmutable(this.state, nextState)
+    )
+  }
+
+  componentDidUpdate(preProps) {
+    if (preProps.bid !== this.props.bid) {
+      this.setState({
+        object: this.getObject()
+      })
+    }
+  }
+
+  componentDidMount() {
+    this.unsubscribe = newEventStores.listen(this.onEventChange)
+  }
+
+  componentWillUnmount() {
+    this.unsubscribe()
+  }
+
+  onEventChange(status) {
+    let obj = {}
+    if (status) {
+      if (
+        status.types.includes('curEventNodeId') &&
+        this.curEventNodeId !== status.data.curEventNodeId
+      ) {
+        this.curEventNodeId = status.data.curEventNodeId
+      }
+      if (
+        status.types.includes('reloadBlock') &&
+        this.props.bid === status.data.affectBlockId
+      ) {
+        obj.object = this.getObject()
+      }
+    }
+    if (Object.keys(obj).length > 0) {
+      this.setState(obj)
+    }
+  }
+
+  genObjSelectConfig() {
+    return {
+      srcId: this.curEventNodeId,
+      srcInStage: {
+        stage: true,
+        server: {
+          allow: [
+            'service',
+            'db',
+            'data-live',
+            'data-excel',
+            'data-sharedService'
+          ],
+          forbidden: [
+            'data-mallProduct',
+            'data-mallOrder',
+            'data-mallCart',
+            'data-voteCandidate',
+            'data-voteRecord',
+            'data-dynamoDb',
+            'data-cacheDb',
+            'data-email',
+            'data-sms'
+          ]
+        }
+      },
+      srcInServer: {
+        stage: false,
+        server: true
+      },
+      srcFrom: 'actionObj'
+    }
+  }
+
+  onAddAction() {
+    let nodeId = this.props.eventNodeId || this.curEventNodeId
+    let parentBlock = getParentBlock(this.props.bid, nodeId)
+    if (parentBlock) {
+      let index = getChildIndex(parentBlock, this.props.bid)
+      if (index !== -1) {
+        newEventActions.addBlock({
+          type: EVENT_BLOCK_TYPE.ACTION,
+          parentBid: parentBlock.eventId ? parentBlock.eventId : parentBlock.ln,
+          index: index + 1
+        })
+      }
+    }
+  }
+
+  shouldClearAction(block, obj) {
+    let result = false
+    let nodeId = this.props.eventNodeId || this.curEventNodeId
+    let node = getEventNodeById(nodeId)
+    // 对象改变
+    let preObj = this.getBlockObj(block)
+    let preObject = getActionBlockObjNode({
+      obj: preObj,
+      nodeId
+    })
+    let curObject = getActionBlockObjNode({
+      obj: obj,
+      nodeId
+    })
+    if (
+      (!preObject && curObject) ||
+      (preObject && !curObject) ||
+      (!preObject && !curObject && block.op) ||
+      (preObject && curObject && preObject.type !== curObject.type)
+    ) {
+      result = true
+    }
+    // 处理服务为当前对象,且动作为设置返回结果的情况下,选择其他服务时,需要clear
+    let actionName
+    if (block.op === BLOCK_OP_TYPE.CALL) {
+      if (block.val && Array.isArray(block.val)) {
+        actionName = block.val[1]
+      }
+    }
+    if (
+      !result &&
+      !isChangedActionValid({
+        rootNode: node,
+        blockNode: curObject,
+        blockObj: obj,
+        actionName
+      })
+    ) {
+      result = true
+    }
+    return result
+  }
+
+  dealChangeActionObject(block, obj) {
+    if (
+      block &&
+      (block.op === BLOCK_OP_TYPE.SET ||
+        block.op === BLOCK_OP_TYPE.CALL ||
+        block.op === BLOCK_OP_TYPE.LET ||
+        block.op === undefined)
+    ) {
+      if (this.shouldClearAction(block, obj)) {
+        block.op = undefined
+        block.val = ''
+        block.args = []
+      }
+    }
+  }
+
+  onSelectObj(obj) {
+    let nodeId = this.props.eventNodeId || this.curEventNodeId
+    let curBlock = getEventBlockByBid(this.props.bid, nodeId)
+    if (curBlock) {
+      this.dealChangeActionObject(curBlock, obj)
+      this.setState(
+        {
+          object: obj
+        },
+        () => {
+          newEventActions.updateBlockProp({
+            nodeId,
+            blockId: this.props.bid,
+            prop: 'object',
+            value: obj,
+            trigger: true
+          })
+          // 更新部分obj的参数
+          let node = getActionBlockObjNode({ obj, nodeId })
+          newEventStores.reloadAction(node && node.id)
+        }
+      )
+    }
+  }
+
+  onActionObjectSelect(option) {
+    if (option) {
+      if (option.key === 'objSelector') {
+        this.objSelector && this.objSelector.current.componentNode.click()
+      } else {
+        this.onSelectObj(option.key)
+      }
+    }
+  }
+
+  getSpecialObjName(obj) {
+    let name = obj
+    switch (obj) {
+      case 'curObj':
+        let nodeId = this.props.eventNodeId || this.curEventNodeId
+        let node = getEventNodeById(nodeId)
+        if (node) {
+          if (nodeIsService(node.type)) {
+            if (nodeIsTransaction(node.type)) {
+              name = i18n.t('EventView.jenga_action_block.curTransaction')
+            } else if (nodeIsIotMessage(node.type)) {
+              name = i18n.t('EventView.jenga_action_block.curIot')
+            } else {
+              name = i18n.t('EventView.jenga_action_block.curService')
+            }
+          } else if (nodeIsFunctionGroup(node.type)) {
+            name = i18n.t('EventView.jenga_action_block.curAction')
+          } else {
+            name = i18n.t('EventView.jenga_action_block.curObject')
+          }
+        }
+        break
+      default:
+        name = i18n.t('EventView.jenga_action_block.' + obj)
+    }
+    return name
+  }
+
+  getActionObjName(obj) {
+    if (obj === 'objSelector') {
+      return i18n.t('EventView.jenga_action_block.objSelector')
+    } else {
+      // 特殊且合法的对象
+      if (specialActionObj.indexOf(obj) >= 0) {
+        return this.actionObjList.indexOf(obj) >= 0
+          ? this.getSpecialObjName(obj)
+          : ''
+      } else if (fakeNodeIds.indexOf(obj) >= 0) {
+        return getNodeTypeName(obj)
+      } else {
+        let _obj = getEventNodeById(obj)
+        return _obj ? _obj.uis.name || _obj.type : ''
+      }
+    }
+  }
+
+  getActionObjIcon(obj) {
+    let nodeId = this.props.eventNodeId || this.curEventNodeId
+    let node = getActionBlockObjNode({ obj, nodeId })
+    let icon = null
+    let type = 'map'
+    if (node) {
+      if (node && node.type && widgetStore.widget[node.type]) {
+        icon = getNodeIconByEnvs(
+          node.type,
+          widgetStore.widget[node.type].icon,
+          node.envs
+        )
+        type = 'icon'
+      }
+      if (!icon) {
+        icon = getTypeIcon(node, treeStores.curCaseType)
+        type = 'map'
+      }
+    }
+    return { icon, type }
+  }
+
+  getBlockObj(block) {
+    let obj
+    if (block) {
+      if (block.isCurObj) {
+        obj = 'curObj'
+      } else {
+        switch (block.op) {
+          case BLOCK_OP_TYPE.SET:
+            if (block.args && block.args[0] && block.args[0].val) {
+              let _val = block.args[0].val
+              if (Array.isArray(_val) && _val[0]) {
+                obj = _val[0]
+              }
+            }
+            break
+          case BLOCK_OP_TYPE.CALL:
+            if (block.val && Array.isArray(block.val)) {
+              obj = block.val[0]
+            }
+            break
+          case BLOCK_OP_TYPE.LET:
+            if (block.args && block.args[0]) {
+              let tempBlock = block.args[0]
+              if (
+                tempBlock.op === BLOCK_OP_TYPE.CALL &&
+                tempBlock.val &&
+                Array.isArray(tempBlock.val)
+              ) {
+                obj = tempBlock.val[0]
+              }
+            }
+            break
+          default:
+            obj = block.val
+        }
+      }
+    }
+    return obj
+  }
+
+  getObject() {
+    let _obj
+    let nodeId = this.props.eventNodeId || this.curEventNodeId
+    let curBlock = getEventBlockByBid(this.props.bid, nodeId)
+    if (curBlock) {
+      _obj = this.getBlockObj(curBlock)
+    }
+    return _obj
+  }
+
+  get actionObjList() {
+    let curNode = getEventNodeById(this.state.curEventNodeId)
+    if (nodeIsDyTransaction(curNode && curNode.type)) {
+      // dy事务无相关选项
+      return []
+    }
+    // 只有当前对象
+    return specialActionObj.slice(0, 1)
+  }
+
+  get fakeNodes() {
+    let fakeNodeIds = getFakeNodeIds() || []
+    if (isServerRootNode(getEventNodeById(this.state.curEventNodeId))) {
+      // 后台的伪对象
+      fakeNodeIds = fakeNodeIds.filter(nodeId => {
+        return nodeId === '$sobj_serverSys'
+      })
+    } else {
+      // 前台的伪对象
+      fakeNodeIds = fakeNodeIds.filter(nodeId => {
+        return nodeId !== '$sobj_serverSys'
+      })
+    }
+    return fakeNodeIds
+  }
+
+  jumpToNode(e) {
+    e && e.stopPropagation()
+    let nodeId = this.props.eventNodeId || this.curEventNodeId
+    let node = getActionBlockObjNode({
+      obj: this.state.object,
+      nodeId
+    })
+    if (node && this.state.object !== 'curObj') {
+      if (nodeIsFunctionGroup(node.type) || nodeIsService(node.type)) {
+        newEventActions.toggleEventView({
+          show: true,
+          nodeId: node.id,
+          mode: 'jenga'
+        })
+      } else {
+        if (newEventStores.showEventView) {
+          newEventActions.toggleEventView({ show: false })
+        }
+      }
+      treeActions.selectNode(node.id)
+      // if (nodeIsFunction(node.type)) {
+      //   newEventActions.addNavId(node)
+      // }
+    }
+  }
+
+  objJumpBtn() {
+    let obj = this.state.object
+    if (obj !== 'curObj' && fakeNodeIds.indexOf(obj) === -1) {
+      let node = getActionBlockObjNode({
+        obj
+      })
+      if (
+        node &&
+        (nodeIsFunctionGroup(node.type) ||
+          nodeIsService(node.type) ||
+          nodeIsFunction(node.type))
+      ) {
+        return (
+          <button className="btn-clear btn-jump" onClick={this.jumpToNode} />
+        )
+      }
+    }
+    return null
+  }
+
+  render() {
+    let actionObjIconInfo = this.getActionObjIcon(this.state.object)
+    let actionObjMenu = () => {
+      let fakeNodes = this.fakeNodes
+      return (
+        <Menu
+          className="object-select-menu"
+          onClick={this.onActionObjectSelect}
+        >
+          <MenuItem key={'objSelector'}>
+            {this.getActionObjName('objSelector')}
+          </MenuItem>
+          <Menu.Divider />
+          {this.actionObjList.map(obj => {
+            return <MenuItem key={obj}>{this.getActionObjName(obj)}</MenuItem>
+          })}
+          {fakeNodes && fakeNodes.length > 0 ? <Menu.Divider /> : null}
+          {!fakeNodes || fakeNodes.length === 0
+            ? null
+            : fakeNodes.map(node => {
+                return (
+                  <MenuItem key={node} className={'fake-node'}>
+                    {this.getActionObjName(node)}
+                  </MenuItem>
+                )
+              })}
+        </Menu>
+      )
+    }
+
+    return (
+      <div className="action-object f--h">
+        <BlockEnable bid={this.props.bid} isEnable={this.props.isEnable} />
+        <div className="object-wrap">
+          <div className="select-wrap f--hlc">
+            <Dropdown
+              trigger={['click']}
+              getPopupContainer={triggerNode => triggerNode.parentNode}
+              overlayClassName={'object-select-dropdown'}
+              overlay={actionObjMenu()}
+            >
+              <div className="object-select f--hlc">
+                <ObjSelector
+                  ref={this.objSelector}
+                  stopPropagation={true}
+                  config={this.genObjSelectConfig()}
+                  cb={this.onSelectObj}
+                />
+                {actionObjIconInfo.type === 'icon' ? (
+                  <div
+                    className="icon-svg f--hcc"
+                    dangerouslySetInnerHTML={{
+                      __html: actionObjIconInfo.icon
+                    }}
+                  />
+                ) : actionObjIconInfo.icon ? (
+                  <div className={cls('icon-type', actionObjIconInfo.icon)} />
+                ) : null}
+                <TitleTip nodeId={this.state.object} maxLength={4}>
+                  <input
+                    value={this.getActionObjName(this.state.object)}
+                    readOnly={true}
+                    className={cls('ant-dropdown-input', {
+                      'fake-node': fakeNodeIds.indexOf(this.state.object) >= 0
+                    })}
+                    placeholder={i18n.t(
+                      'EventView.jenga_action_block.selectObject'
+                    )}
+                  />
+                </TitleTip>
+                {this.objJumpBtn()}
+                <div className="ant-dropdown-icon" />
+              </div>
+            </Dropdown>
+          </div>
+          <div className="add-action-block-wrap f--hcc">
+            <button
+              className="btn-clear btn-add-action-block"
+              onClick={this.onAddAction}
+            >
+              <div className="icon">
+                <span className="horizon" />
+                <span className="vertical" />
+              </div>
+            </button>
+          </div>
+        </div>
+      </div>
+    )
+  }
+}