Showing
31 changed files
with
1417 additions
and
189 deletions
| @@ -6,6 +6,7 @@ import { RuleChainType } from '/@/views/rule/designer/types/ruleNode'; | @@ -6,6 +6,7 @@ import { RuleChainType } from '/@/views/rule/designer/types/ruleNode'; | ||
| 6 | enum Api { | 6 | enum Api { | 
| 7 | SAVE = '/ruleChain/metadata', | 7 | SAVE = '/ruleChain/metadata', | 
| 8 | GET_RULE_CHAINES = '/ruleChains', | 8 | GET_RULE_CHAINES = '/ruleChains', | 
| 9 | + GET_RULE_NODE_EVENTS = '/events/RULE_NODE', | ||
| 9 | } | 10 | } | 
| 10 | 11 | ||
| 11 | export const getRuleChainData = (id: string) => { | 12 | export const getRuleChainData = (id: string) => { | 
| @@ -38,3 +39,18 @@ export const getRuleChains = (params: Recordable) => { | @@ -38,3 +39,18 @@ export const getRuleChains = (params: Recordable) => { | ||
| 38 | } | 39 | } | 
| 39 | ); | 40 | ); | 
| 40 | }; | 41 | }; | 
| 42 | + | ||
| 43 | +export const getRuleNodeEventList = ( | ||
| 44 | + ruleNodeId: string, | ||
| 45 | + params: Recordable, | ||
| 46 | + data: Recordable & Record<'eventType', string> | ||
| 47 | +) => { | ||
| 48 | + return defHttp.post<TBPaginationResult>( | ||
| 49 | + { | ||
| 50 | + url: `${Api.GET_RULE_NODE_EVENTS}/${ruleNodeId}`, | ||
| 51 | + params, | ||
| 52 | + data, | ||
| 53 | + }, | ||
| 54 | + { joinPrefix: false } | ||
| 55 | + ); | ||
| 56 | +}; | 
| @@ -10,6 +10,11 @@ interface OptionsType { | @@ -10,6 +10,11 @@ interface OptionsType { | ||
| 10 | type: ElementsTypeEnum; | 10 | type: ElementsTypeEnum; | 
| 11 | } | 11 | } | 
| 12 | 12 | ||
| 13 | +export interface ElementInfo { | ||
| 14 | + id: string; | ||
| 15 | + type: ElementsTypeEnum; | ||
| 16 | +} | ||
| 17 | + | ||
| 13 | export function useAwaitPopupWindowBindData( | 18 | export function useAwaitPopupWindowBindData( | 
| 14 | options: OptionsType = { mode: DataActionModeEnum.CREATE, type: ElementsTypeEnum.NODE } | 19 | options: OptionsType = { mode: DataActionModeEnum.CREATE, type: ElementsTypeEnum.NODE } | 
| 15 | ) { | 20 | ) { | 
| @@ -29,6 +34,8 @@ export function useAwaitPopupWindowBindData( | @@ -29,6 +34,8 @@ export function useAwaitPopupWindowBindData( | ||
| 29 | 34 | ||
| 30 | const shadowComponent = shallowRef<Nullable<Component>>(); | 35 | const shadowComponent = shallowRef<Nullable<Component>>(); | 
| 31 | 36 | ||
| 37 | + const elementInfo = ref<ElementInfo>(); | ||
| 38 | + | ||
| 32 | const getNodeSetValue = computed(() => { | 39 | const getNodeSetValue = computed(() => { | 
| 33 | return unref(mode) === DataActionModeEnum.CREATE | 40 | return unref(mode) === DataActionModeEnum.CREATE | 
| 34 | ? unref(nodeData)?.config?.configurationDescriptor.nodeDefinition.defaultConfiguration | 41 | ? unref(nodeData)?.config?.configurationDescriptor.nodeDefinition.defaultConfiguration | 
| @@ -68,8 +75,10 @@ export function useAwaitPopupWindowBindData( | @@ -68,8 +75,10 @@ export function useAwaitPopupWindowBindData( | ||
| 68 | 75 | ||
| 69 | const open = async ( | 76 | const open = async ( | 
| 70 | nodeData: NodeData, | 77 | nodeData: NodeData, | 
| 71 | - edgeData?: EdgeData | 78 | + edgeData?: EdgeData, | 
| 79 | + _elementInfo?: ElementInfo | ||
| 72 | ): Promise<AwaitPopupWindowReturnDataType> => { | 80 | ): Promise<AwaitPopupWindowReturnDataType> => { | 
| 81 | + elementInfo.value = _elementInfo; | ||
| 73 | await handleFetchComponent(nodeData, edgeData); | 82 | await handleFetchComponent(nodeData, edgeData); | 
| 74 | return new Promise((_resolve) => { | 83 | return new Promise((_resolve) => { | 
| 75 | visible.value = true; | 84 | visible.value = true; | 
| @@ -113,6 +122,7 @@ export function useAwaitPopupWindowBindData( | @@ -113,6 +122,7 @@ export function useAwaitPopupWindowBindData( | ||
| 113 | visible, | 122 | visible, | 
| 114 | nodeData, | 123 | nodeData, | 
| 115 | spinning, | 124 | spinning, | 
| 125 | + elementInfo, | ||
| 116 | shadowComponent, | 126 | shadowComponent, | 
| 117 | createComponentEl, | 127 | createComponentEl, | 
| 118 | getComponentKey, | 128 | getComponentKey, | 
| @@ -10,7 +10,7 @@ import type { Ref } from 'vue'; | @@ -10,7 +10,7 @@ import type { Ref } from 'vue'; | ||
| 10 | import { markRaw, toRaw, unref } from 'vue'; | 10 | import { markRaw, toRaw, unref } from 'vue'; | 
| 11 | import { isFunction } from 'lodash-es'; | 11 | import { isFunction } from 'lodash-es'; | 
| 12 | import type { CreateNodeModal } from '../src/components/CreateNodeModal'; | 12 | import type { CreateNodeModal } from '../src/components/CreateNodeModal'; | 
| 13 | -import { EdgeTypeEnum, NodeTypeEnum } from '../enum'; | 13 | +import { EdgeTypeEnum, ElementsTypeEnum, NodeTypeEnum } from '../enum'; | 
| 14 | import { BasicEdge, BasicNode } from '../src/components'; | 14 | import { BasicEdge, BasicNode } from '../src/components'; | 
| 15 | import type { EdgeData, NodeData } from '../types/node'; | 15 | import type { EdgeData, NodeData } from '../types/node'; | 
| 16 | import type { CreateEdgeModal } from '../src/components/CreateEdgeModal'; | 16 | import type { CreateEdgeModal } from '../src/components/CreateEdgeModal'; | 
| @@ -126,10 +126,11 @@ export function useRuleFlow(options: UseRuleFlowOptionsType) { | @@ -126,10 +126,11 @@ export function useRuleFlow(options: UseRuleFlowOptionsType) { | ||
| 126 | 126 | ||
| 127 | onNodeDoubleClick(async ({ node }) => { | 127 | onNodeDoubleClick(async ({ node }) => { | 
| 128 | if ((node.data as NodeData).config?.disableAction) return; | 128 | if ((node.data as NodeData).config?.disableAction) return; | 
| 129 | - | ||
| 130 | const { flag, data } = | 129 | const { flag, data } = | 
| 131 | (await unref(updateNodeDrawerActionType)?.open( | 130 | (await unref(updateNodeDrawerActionType)?.open( | 
| 132 | - toRaw((node as NodeData)?.data as unknown as NodeData) | 131 | + toRaw((node as NodeData)?.data as unknown as NodeData), | 
| 132 | + void 0, | ||
| 133 | + { id: node.id, type: ElementsTypeEnum.NODE } | ||
| 133 | )) || {}; | 134 | )) || {}; | 
| 134 | 135 | ||
| 135 | if (!flag) return; | 136 | if (!flag) return; | 
| @@ -146,7 +147,8 @@ export function useRuleFlow(options: UseRuleFlowOptionsType) { | @@ -146,7 +147,8 @@ export function useRuleFlow(options: UseRuleFlowOptionsType) { | ||
| 146 | const { flag, data } = | 147 | const { flag, data } = | 
| 147 | (await unref(updateEdgeDrawerActionType)?.open( | 148 | (await unref(updateEdgeDrawerActionType)?.open( | 
| 148 | toRaw(unref(edge.sourceNode?.data as unknown as NodeData)), | 149 | toRaw(unref(edge.sourceNode?.data as unknown as NodeData)), | 
| 149 | - toRaw(unref(edge.data as EdgeData)) | 150 | + toRaw(unref(edge.data as EdgeData)), | 
| 151 | + { id: edge.id, type: ElementsTypeEnum.EDGE } | ||
| 150 | )) || {}; | 152 | )) || {}; | 
| 151 | 153 | ||
| 152 | if (!flag) return; | 154 | if (!flag) return; | 
| 1 | <script setup lang="ts"> | 1 | <script setup lang="ts"> | 
| 2 | + import { Spin } from 'ant-design-vue'; | ||
| 2 | import { Background, BackgroundVariant } from '@vue-flow/background'; | 3 | import { Background, BackgroundVariant } from '@vue-flow/background'; | 
| 3 | import { Controls } from '@vue-flow/controls'; | 4 | import { Controls } from '@vue-flow/controls'; | 
| 4 | import { Panel, PanelPosition, VueFlow } from '@vue-flow/core'; | 5 | import { Panel, PanelPosition, VueFlow } from '@vue-flow/core'; | 
| @@ -34,6 +35,7 @@ | @@ -34,6 +35,7 @@ | ||
| 34 | const elements = ref([]); | 35 | const elements = ref([]); | 
| 35 | 36 | ||
| 36 | const { | 37 | const { | 
| 38 | + loading, | ||
| 37 | changeMarker, | 39 | changeMarker, | 
| 38 | getCurrentPageMetaData, | 40 | getCurrentPageMetaData, | 
| 39 | triggerChange, | 41 | triggerChange, | 
| @@ -88,66 +90,68 @@ | @@ -88,66 +90,68 @@ | ||
| 88 | <main ref="rootElRef" class="w-full h-full flex relative" @drop="handleOnDrop"> | 90 | <main ref="rootElRef" class="w-full h-full flex relative" @drop="handleOnDrop"> | 
| 89 | <Sidebar /> | 91 | <Sidebar /> | 
| 90 | 92 | ||
| 91 | - <VueFlow | ||
| 92 | - :id="getId" | ||
| 93 | - ref="flowElRef" | ||
| 94 | - v-model="elements" | ||
| 95 | - class="w-full h-full" | ||
| 96 | - @dragover="handleOnDragOver" | ||
| 97 | - > | ||
| 98 | - <template #connection-line="props"> | ||
| 99 | - <BasicConnectionLine v-bind="props" /> | ||
| 100 | - </template> | ||
| 101 | - <template #edge-custom="props"> | ||
| 102 | - <BasicEdge v-bind="props" /> | ||
| 103 | - </template> | ||
| 104 | - | ||
| 105 | - <BasicConnectionArrow /> | ||
| 106 | - | ||
| 107 | - <Background :variant="BackgroundVariant.Lines" :gap="25" pattern-color="#cfcfcf" /> | ||
| 108 | - | ||
| 109 | - <Controls :position="PanelPosition.BottomLeft" /> | ||
| 110 | - | ||
| 111 | - <Panel position="bottom-right" class="controls"> | ||
| 112 | - <section class="flex gap-4"> | ||
| 113 | - <button | ||
| 114 | - :style="{ transform: `translateY(${getDeleteDisplayState ? 0 : '72px'})` }" | ||
| 115 | - class="button-box-shadow w-14 h-14 flex justify-center items-center bg-orange-600 rounded-full transition-transform transform" | ||
| 116 | - @click="handleDeleteSelectionElements" | ||
| 117 | - > | ||
| 118 | - <Icon class="!text-3xl !text-light-50" icon="mdi:delete" /> | ||
| 119 | - </button> | ||
| 120 | - <button | ||
| 121 | - class="button-box-shadow w-14 h-14 flex justify-center items-center bg-gray-400 rounded-full opacity-50" | ||
| 122 | - > | ||
| 123 | - <Icon class="!text-3xl !text-light-50" icon="carbon:debug" /> | ||
| 124 | - </button> | ||
| 125 | - <button | ||
| 126 | - :class="changeMarker ? '!bg-orange-600 !opacity-100' : 'opacity-50'" | ||
| 127 | - class="button-box-shadow w-14 h-14 flex justify-center items-center bg-gray-400 rounded-full" | ||
| 128 | - @click="handleApplyChange(flowActionType)" | ||
| 129 | - > | ||
| 130 | - <Icon class="!text-3xl !text-light-50" icon="mdi:tick" /> | ||
| 131 | - </button> | 93 | + <Spin :spinning="loading" wrapperClassName="w-full h-ful rule-chain-designer-loading-container"> | 
| 94 | + <VueFlow | ||
| 95 | + :id="getId" | ||
| 96 | + ref="flowElRef" | ||
| 97 | + v-model="elements" | ||
| 98 | + class="w-full h-full" | ||
| 99 | + @dragover="handleOnDragOver" | ||
| 100 | + > | ||
| 101 | + <template #connection-line="props"> | ||
| 102 | + <BasicConnectionLine v-bind="props" /> | ||
| 103 | + </template> | ||
| 104 | + <template #edge-custom="props"> | ||
| 105 | + <BasicEdge v-bind="props" /> | ||
| 106 | + </template> | ||
| 107 | + | ||
| 108 | + <BasicConnectionArrow /> | ||
| 109 | + | ||
| 110 | + <Background :variant="BackgroundVariant.Lines" :gap="25" pattern-color="#cfcfcf" /> | ||
| 111 | + | ||
| 112 | + <Controls :position="PanelPosition.BottomLeft" /> | ||
| 113 | + | ||
| 114 | + <Panel position="bottom-right" class="controls"> | ||
| 115 | + <section class="flex gap-4"> | ||
| 116 | + <button | ||
| 117 | + :style="{ transform: `translateY(${getDeleteDisplayState ? 0 : '72px'})` }" | ||
| 118 | + class="button-box-shadow w-14 h-14 flex justify-center items-center bg-orange-600 rounded-full transition-transform transform" | ||
| 119 | + @click="handleDeleteSelectionElements" | ||
| 120 | + > | ||
| 121 | + <Icon class="!text-3xl !text-light-50" icon="mdi:delete" /> | ||
| 122 | + </button> | ||
| 123 | + <button | ||
| 124 | + class="button-box-shadow w-14 h-14 flex justify-center items-center bg-gray-400 rounded-full opacity-50" | ||
| 125 | + > | ||
| 126 | + <Icon class="!text-3xl !text-light-50" icon="carbon:debug" /> | ||
| 127 | + </button> | ||
| 128 | + <button | ||
| 129 | + :class="changeMarker ? '!bg-orange-600 !opacity-100' : 'opacity-50'" | ||
| 130 | + class="button-box-shadow w-14 h-14 flex justify-center items-center bg-gray-400 rounded-full" | ||
| 131 | + @click="handleApplyChange(flowActionType)" | ||
| 132 | + > | ||
| 133 | + <Icon class="!text-3xl !text-light-50" icon="mdi:tick" /> | ||
| 134 | + </button> | ||
| 135 | + <button | ||
| 136 | + :class="changeMarker ? '!bg-orange-600 !opacity-100' : 'opacity-50'" | ||
| 137 | + class="button-box-shadow w-14 h-14 flex justify-center items-center bg-gray-400 rounded-full" | ||
| 138 | + @click="handleRedoChange(flowActionType)" | ||
| 139 | + > | ||
| 140 | + <Icon class="!text-3xl !text-light-50" icon="ic:baseline-close" /> | ||
| 141 | + </button> | ||
| 142 | + </section> | ||
| 143 | + </Panel> | ||
| 144 | + | ||
| 145 | + <Panel position="top-right"> | ||
| 132 | <button | 146 | <button | 
| 133 | - :class="changeMarker ? '!bg-orange-600 !opacity-100' : 'opacity-50'" | ||
| 134 | - class="button-box-shadow w-14 h-14 flex justify-center items-center bg-gray-400 rounded-full" | ||
| 135 | - @click="handleRedoChange(flowActionType)" | 147 | + class="w-10 h-10 bg-gray-300 flex justify-center items-center rounded-full dark:bg-dark-50" | 
| 148 | + @click="handleFullScreen" | ||
| 136 | > | 149 | > | 
| 137 | - <Icon class="!text-3xl !text-light-50" icon="ic:baseline-close" /> | 150 | + <Icon class="!text-2xl dark:text-light-50" :icon="getFullScreenIcon" /> | 
| 138 | </button> | 151 | </button> | 
| 139 | - </section> | ||
| 140 | - </Panel> | ||
| 141 | - | ||
| 142 | - <Panel position="top-right"> | ||
| 143 | - <button | ||
| 144 | - class="w-10 h-10 bg-gray-300 flex justify-center items-center rounded-full dark:bg-dark-50" | ||
| 145 | - @click="handleFullScreen" | ||
| 146 | - > | ||
| 147 | - <Icon class="!text-2xl dark:text-light-50" :icon="getFullScreenIcon" /> | ||
| 148 | - </button> | ||
| 149 | - </Panel> | ||
| 150 | - </VueFlow> | 152 | + </Panel> | 
| 153 | + </VueFlow> | ||
| 154 | + </Spin> | ||
| 151 | 155 | ||
| 152 | <CreateNodeModal ref="createNodeModalActionType" :get-container="handleGetContainer" /> | 156 | <CreateNodeModal ref="createNodeModalActionType" :get-container="handleGetContainer" /> | 
| 153 | <CreateEdgeModal ref="createEdgeModalActionType" :get-container="handleGetContainer" /> | 157 | <CreateEdgeModal ref="createEdgeModalActionType" :get-container="handleGetContainer" /> | 
| @@ -162,3 +166,11 @@ | @@ -162,3 +166,11 @@ | ||
| 162 | box-shadow: 0 3px 5px -1px #0003, 0 6px 10px 0 #00000024, 0 1px 18px 0 #0000001f; | 166 | box-shadow: 0 3px 5px -1px #0003, 0 6px 10px 0 #00000024, 0 1px 18px 0 #0000001f; | 
| 163 | } | 167 | } | 
| 164 | </style> | 168 | </style> | 
| 169 | + | ||
| 170 | +<style lang="less"> | ||
| 171 | + .rule-chain-designer-loading-container { | ||
| 172 | + .ant-spin-container { | ||
| 173 | + @apply w-full h-full; | ||
| 174 | + } | ||
| 175 | + } | ||
| 176 | +</style> | 
| @@ -6,6 +6,7 @@ | @@ -6,6 +6,7 @@ | ||
| 6 | import { useConnectionFocus } from '../../../hook/useConnectionFocus'; | 6 | import { useConnectionFocus } from '../../../hook/useConnectionFocus'; | 
| 7 | import { useFlowContext } from '../../../hook/useFlowContext'; | 7 | import { useFlowContext } from '../../../hook/useFlowContext'; | 
| 8 | import { useTextWidth } from '../../../hook/useTextWidth'; | 8 | import { useTextWidth } from '../../../hook/useTextWidth'; | 
| 9 | + import { ElementsTypeEnum } from '../../../enum'; | ||
| 9 | 10 | ||
| 10 | const props = defineProps<EdgeProps>(); | 11 | const props = defineProps<EdgeProps>(); | 
| 11 | 12 | ||
| @@ -31,7 +32,8 @@ | @@ -31,7 +32,8 @@ | ||
| 31 | const { flag, data } = | 32 | const { flag, data } = | 
| 32 | (await unref(updateEdgeDrawerActionType)?.open( | 33 | (await unref(updateEdgeDrawerActionType)?.open( | 
| 33 | toRaw(unref(props.sourceNode?.data as unknown as NodeData)), | 34 | toRaw(unref(props.sourceNode?.data as unknown as NodeData)), | 
| 34 | - toRaw(unref(props.data as EdgeData)) | 35 | + toRaw(unref(props.data as EdgeData)), | 
| 36 | + { id: props.id, type: ElementsTypeEnum.EDGE } | ||
| 35 | )) || {}; | 37 | )) || {}; | 
| 36 | 38 | ||
| 37 | if (!flag) return; | 39 | if (!flag) return; | 
| @@ -5,6 +5,7 @@ | @@ -5,6 +5,7 @@ | ||
| 5 | import { computed, toRaw, unref } from 'vue'; | 5 | import { computed, toRaw, unref } from 'vue'; | 
| 6 | import { useFlowContext } from '../../../hook/useFlowContext'; | 6 | import { useFlowContext } from '../../../hook/useFlowContext'; | 
| 7 | import type { NodeData } from '../../../types/node'; | 7 | import type { NodeData } from '../../../types/node'; | 
| 8 | + import { ElementsTypeEnum } from '../../../enum'; | ||
| 8 | 9 | ||
| 9 | const props = defineProps<NodeProps>(); | 10 | const props = defineProps<NodeProps>(); | 
| 10 | 11 | ||
| @@ -14,7 +15,10 @@ | @@ -14,7 +15,10 @@ | ||
| 14 | 15 | ||
| 15 | const handleOpenEdit = async () => { | 16 | const handleOpenEdit = async () => { | 
| 16 | const { flag, data } = | 17 | const { flag, data } = | 
| 17 | - (await unref(updateNodeDrawerActionType)?.open(toRaw(unref(getData)))) || {}; | 18 | + (await unref(updateNodeDrawerActionType)?.open(toRaw(unref(getData)), void 0, { | 
| 19 | + id: props.id, | ||
| 20 | + type: ElementsTypeEnum.NODE, | ||
| 21 | + })) || {}; | ||
| 18 | 22 | ||
| 19 | if (!flag) return; | 23 | if (!flag) return; | 
| 20 | 24 | 
src/views/rule/designer/src/components/BasicEvents/DebugEvent.vue
deleted
100644 → 0
| 1 | -<script lang="ts" setup> | ||
| 2 | - import { useTable, BasicTable } from '/@/components/Table'; | ||
| 3 | - import { columns, formSchemas } from './debugEvent.config'; | ||
| 4 | - | ||
| 5 | - const [register] = useTable({ | ||
| 6 | - columns, | ||
| 7 | - showIndexColumn: false, | ||
| 8 | - useSearchForm: true, | ||
| 9 | - formConfig: { | ||
| 10 | - layout: 'inline', | ||
| 11 | - baseColProps: { | ||
| 12 | - span: 12, | ||
| 13 | - }, | ||
| 14 | - labelWidth: 80, | ||
| 15 | - schemas: formSchemas, | ||
| 16 | - }, | ||
| 17 | - }); | ||
| 18 | -</script> | ||
| 19 | - | ||
| 20 | -<template> | ||
| 21 | - <BasicTable @register="register" /> | ||
| 22 | -</template> | 
src/views/rule/designer/src/components/BasicEvents/debugEvent.config.ts
deleted
100644 → 0
| 1 | -import { BasicColumn, FormSchema } from '/@/components/Table'; | ||
| 2 | - | ||
| 3 | -export const columns: BasicColumn[] = [ | ||
| 4 | - { | ||
| 5 | - title: '事件时间', | ||
| 6 | - dataIndex: '', | ||
| 7 | - }, | ||
| 8 | - { | ||
| 9 | - title: '服务器', | ||
| 10 | - dataIndex: '', | ||
| 11 | - }, | ||
| 12 | - { | ||
| 13 | - title: '类型', | ||
| 14 | - dataIndex: '', | ||
| 15 | - }, | ||
| 16 | - { | ||
| 17 | - title: '实体类型', | ||
| 18 | - dataIndex: '', | ||
| 19 | - }, | ||
| 20 | - { | ||
| 21 | - title: '消息ID', | ||
| 22 | - dataIndex: '', | ||
| 23 | - }, | ||
| 24 | - { | ||
| 25 | - title: '消息类型', | ||
| 26 | - dataIndex: '', | ||
| 27 | - }, | ||
| 28 | - { | ||
| 29 | - title: '关联类型', | ||
| 30 | - dataIndex: '', | ||
| 31 | - }, | ||
| 32 | - { | ||
| 33 | - title: '数据', | ||
| 34 | - dataIndex: '', | ||
| 35 | - }, | ||
| 36 | - { | ||
| 37 | - title: '原数据', | ||
| 38 | - dataIndex: '', | ||
| 39 | - }, | ||
| 40 | - { | ||
| 41 | - title: '错误', | ||
| 42 | - dataIndex: '', | ||
| 43 | - }, | ||
| 44 | -]; | ||
| 45 | - | ||
| 46 | -export const formSchemas: FormSchema[] = [ | ||
| 47 | - { | ||
| 48 | - field: '', | ||
| 49 | - label: '服务器', | ||
| 50 | - component: 'Input', | ||
| 51 | - }, | ||
| 52 | - { | ||
| 53 | - field: '', | ||
| 54 | - label: '类型', | ||
| 55 | - component: 'Select', | ||
| 56 | - }, | ||
| 57 | - { | ||
| 58 | - field: '', | ||
| 59 | - label: '实体ID', | ||
| 60 | - component: 'Input', | ||
| 61 | - }, | ||
| 62 | - { | ||
| 63 | - field: '', | ||
| 64 | - label: '实体类型', | ||
| 65 | - component: 'Select', | ||
| 66 | - }, | ||
| 67 | - { | ||
| 68 | - field: '', | ||
| 69 | - label: '消息类型', | ||
| 70 | - component: 'Input', | ||
| 71 | - }, | ||
| 72 | - { | ||
| 73 | - field: '', | ||
| 74 | - label: '关联类型', | ||
| 75 | - component: 'Input', | ||
| 76 | - }, | ||
| 77 | - { | ||
| 78 | - field: '', | ||
| 79 | - label: '数据', | ||
| 80 | - component: 'Input', | ||
| 81 | - }, | ||
| 82 | - { | ||
| 83 | - field: '', | ||
| 84 | - label: '元数据', | ||
| 85 | - component: 'Input', | ||
| 86 | - }, | ||
| 87 | - { | ||
| 88 | - field: '', | ||
| 89 | - label: '有错误', | ||
| 90 | - component: 'Checkbox', | ||
| 91 | - }, | ||
| 92 | -]; | 
src/views/rule/designer/src/components/BasicEvents/index.vue
deleted
100644 → 0
| 1 | +<script setup lang="ts"> | ||
| 2 | + import AceEditor, { Ace } from 'ace-builds'; | ||
| 3 | + import githubTheme from 'ace-builds/src-noconflict/theme-github?url'; | ||
| 4 | + import 'ace-builds/src-noconflict/mode-java'; | ||
| 5 | + import { ref, unref } from 'vue'; | ||
| 6 | + import { BasicModal, useModalInner } from '/@/components/Modal'; | ||
| 7 | + | ||
| 8 | + withDefaults( | ||
| 9 | + defineProps<{ | ||
| 10 | + content?: string; | ||
| 11 | + }>(), | ||
| 12 | + {} | ||
| 13 | + ); | ||
| 14 | + | ||
| 15 | + defineEmits(['register']); | ||
| 16 | + | ||
| 17 | + const content = ref(); | ||
| 18 | + | ||
| 19 | + const [register] = useModalInner((params: ModalParamsType<string>) => { | ||
| 20 | + content.value = params.record; | ||
| 21 | + initEditor(); | ||
| 22 | + unref(aceEditorRef)?.setValue(params.record, -1); | ||
| 23 | + }); | ||
| 24 | + | ||
| 25 | + const javaEditorElRef = ref(); | ||
| 26 | + | ||
| 27 | + const aceEditorRef = ref<Ace.Editor>(); | ||
| 28 | + | ||
| 29 | + const initEditor = () => { | ||
| 30 | + AceEditor.config.setModuleUrl('ace/theme/github', githubTheme); | ||
| 31 | + const editor = AceEditor.edit(unref(javaEditorElRef)!, { | ||
| 32 | + mode: 'ace/mode/java', | ||
| 33 | + }); | ||
| 34 | + editor.setTheme('ace/theme/github'); | ||
| 35 | + editor.setOptions({ | ||
| 36 | + fontSize: 14, | ||
| 37 | + showLineNumbers: false, | ||
| 38 | + showGutter: false, | ||
| 39 | + }); | ||
| 40 | + editor.setReadOnly(true); | ||
| 41 | + aceEditorRef.value = editor; | ||
| 42 | + }; | ||
| 43 | +</script> | ||
| 44 | + | ||
| 45 | +<template> | ||
| 46 | + <BasicModal @register="register" title="错误" :showOkBtn="false" cancelText="关闭" width="80%"> | ||
| 47 | + <div ref="javaEditorElRef" class="w-full h-full min-h-96"></div> | ||
| 48 | + </BasicModal> | ||
| 49 | +</template> | 
| 1 | +import { EventTypeEnum } from '../EventSelect/config'; | ||
| 2 | +import { columns as debugColumns } from './debug.config'; | ||
| 3 | +import { columns as errorColumns } from './error.config'; | ||
| 4 | +import { columns as liveColumns } from './live.config'; | ||
| 5 | +import { columns as statsColumns } from './stats.config'; | ||
| 6 | + | ||
| 7 | +export function getColumns(type: EventTypeEnum) { | ||
| 8 | + const mapping = { | ||
| 9 | + [EventTypeEnum.ERROR]: errorColumns, | ||
| 10 | + [EventTypeEnum.LC_EVENT]: liveColumns, | ||
| 11 | + [EventTypeEnum.STATS]: statsColumns, | ||
| 12 | + [EventTypeEnum.DEBUG_RULE_NODE]: debugColumns, | ||
| 13 | + }; | ||
| 14 | + return mapping?.[type] || []; | ||
| 15 | +} | 
| 1 | +import { BasicColumn } from '/@/components/Table'; | ||
| 2 | + | ||
| 3 | +export const columns: BasicColumn[] = [ | ||
| 4 | + { | ||
| 5 | + title: '事件时间', | ||
| 6 | + dataIndex: 'createdTime', | ||
| 7 | + }, | ||
| 8 | + { | ||
| 9 | + title: '服务器', | ||
| 10 | + dataIndex: 'body.server', | ||
| 11 | + }, | ||
| 12 | + { | ||
| 13 | + title: '类型', | ||
| 14 | + dataIndex: 'type', | ||
| 15 | + }, | ||
| 16 | + { | ||
| 17 | + title: '实体类型', | ||
| 18 | + dataIndex: 'entityId.entityType', | ||
| 19 | + }, | ||
| 20 | + { | ||
| 21 | + title: '消息ID', | ||
| 22 | + dataIndex: 'id.id', | ||
| 23 | + }, | ||
| 24 | + { | ||
| 25 | + title: '消息类型', | ||
| 26 | + dataIndex: 'msgtype', | ||
| 27 | + }, | ||
| 28 | + { | ||
| 29 | + title: '关联类型', | ||
| 30 | + dataIndex: 'relatedType', | ||
| 31 | + }, | ||
| 32 | + { | ||
| 33 | + title: '数据', | ||
| 34 | + dataIndex: 'data', | ||
| 35 | + }, | ||
| 36 | + { | ||
| 37 | + title: '元数据', | ||
| 38 | + dataIndex: 'metadaeta', | ||
| 39 | + }, | ||
| 40 | + { | ||
| 41 | + title: '错误', | ||
| 42 | + dataIndex: 'error', | ||
| 43 | + }, | ||
| 44 | +]; | 
| 1 | +import { BasicColumn } from '/@/components/Table'; | ||
| 2 | +import { dateUtil } from '/@/utils/dateUtil'; | ||
| 3 | + | ||
| 4 | +export const columns: BasicColumn[] = [ | ||
| 5 | + { | ||
| 6 | + title: '事件时间', | ||
| 7 | + dataIndex: 'createdTime', | ||
| 8 | + ellipsis: true, | ||
| 9 | + width: 200, | ||
| 10 | + format(text) { | ||
| 11 | + return dateUtil(text).format('YYYY-MM-DD HH:mm:ss'); | ||
| 12 | + }, | ||
| 13 | + }, | ||
| 14 | + { | ||
| 15 | + title: '服务器', | ||
| 16 | + dataIndex: 'body.server', | ||
| 17 | + ellipsis: true, | ||
| 18 | + }, | ||
| 19 | + { | ||
| 20 | + title: '方法', | ||
| 21 | + dataIndex: 'body.method', | ||
| 22 | + ellipsis: true, | ||
| 23 | + }, | ||
| 24 | + { | ||
| 25 | + title: '错误', | ||
| 26 | + dataIndex: 'body.error', | ||
| 27 | + ellipsis: true, | ||
| 28 | + width: 100, | ||
| 29 | + slots: { | ||
| 30 | + customRender: 'error', | ||
| 31 | + }, | ||
| 32 | + }, | ||
| 33 | +]; | 
src/views/rule/designer/src/components/UpdateNodeDrawer/BasicEvents/index.ts
renamed from
src/views/rule/designer/src/components/BasicEvents/index.ts
| 1 | +<script lang="ts" setup> | ||
| 2 | + import { useTable, BasicTable } from '/@/components/Table'; | ||
| 3 | + import { getColumns } from './config'; | ||
| 4 | + import { getRuleNodeEventList } from '/@/api/ruleDesigner'; | ||
| 5 | + import { BasicNodeFormData, NodeData } from '../../../../types/node'; | ||
| 6 | + import { computed, reactive, ref, unref, watch } from 'vue'; | ||
| 7 | + import { useUserStore } from '/@/store/modules/user'; | ||
| 8 | + import { EventSelect } from '../EventSelect'; | ||
| 9 | + import { Icon } from '/@/components/Icon'; | ||
| 10 | + import { Tooltip } from 'ant-design-vue'; | ||
| 11 | + import { EventTypeEnum } from '../EventSelect/config'; | ||
| 12 | + import { FilterForm } from '../FilterForm'; | ||
| 13 | + import { useModal } from '/@/components/Modal'; | ||
| 14 | + import { DataActionModeEnum } from '/@/enums/toolEnum'; | ||
| 15 | + import { ElementInfo } from '../../../../hook/useAwaitPopupWindowBindData'; | ||
| 16 | + import ShowDetailModal from './ShowDetailModal.vue'; | ||
| 17 | + | ||
| 18 | + const props = defineProps<{ | ||
| 19 | + nodeData?: NodeData<BasicNodeFormData>; | ||
| 20 | + elementInfo?: ElementInfo; | ||
| 21 | + }>(); | ||
| 22 | + | ||
| 23 | + const userStore = useUserStore(); | ||
| 24 | + const getNodeId = computed(() => props.elementInfo?.id); | ||
| 25 | + const getTenantId = computed(() => unref(userStore.getUserInfo).tenantId); | ||
| 26 | + const eventType = ref(EventTypeEnum.DEBUG_RULE_NODE); | ||
| 27 | + const filterFormElRef = ref<Nullable<InstanceType<typeof FilterForm>>>(null); | ||
| 28 | + | ||
| 29 | + const searchParams = reactive({ | ||
| 30 | + params: {} as Recordable, | ||
| 31 | + data: {} as Recordable, | ||
| 32 | + }); | ||
| 33 | + | ||
| 34 | + const [register, { reload, setColumns, setPagination }] = useTable({ | ||
| 35 | + columns: getColumns(EventTypeEnum.DEBUG_RULE_NODE), | ||
| 36 | + showIndexColumn: false, | ||
| 37 | + useSearchForm: false, | ||
| 38 | + canResize: true, | ||
| 39 | + resizeHeightOffset: 76, | ||
| 40 | + fetchSetting: { | ||
| 41 | + totalField: 'totalElements', | ||
| 42 | + listField: 'data', | ||
| 43 | + }, | ||
| 44 | + showTableSetting: true, | ||
| 45 | + api: async (params: Record<'page' | 'pageSize', number>) => { | ||
| 46 | + const result = await getRuleNodeEventList( | ||
| 47 | + unref(getNodeId)!, | ||
| 48 | + { | ||
| 49 | + page: params.page - 1, | ||
| 50 | + pageSize: params.pageSize, | ||
| 51 | + tenantId: unref(getTenantId), | ||
| 52 | + ...searchParams.params, | ||
| 53 | + }, | ||
| 54 | + { ...searchParams.data, eventType: unref(eventType) } | ||
| 55 | + ); | ||
| 56 | + | ||
| 57 | + return result; | ||
| 58 | + }, | ||
| 59 | + }); | ||
| 60 | + | ||
| 61 | + const [registerModal, { openModal }] = useModal(); | ||
| 62 | + | ||
| 63 | + const handleOpenFilterForm = () => { | ||
| 64 | + openModal(true, { | ||
| 65 | + mode: DataActionModeEnum.READ, | ||
| 66 | + record: { type: unref(eventType) }, | ||
| 67 | + } as ModalParamsType<{ type: EventTypeEnum }>); | ||
| 68 | + }; | ||
| 69 | + | ||
| 70 | + const handleRemoveFilterQueue = () => { | ||
| 71 | + unref(filterFormElRef)?.resetFields(); | ||
| 72 | + handleReset(); | ||
| 73 | + }; | ||
| 74 | + | ||
| 75 | + const handleFilterChange = (searchValue: Record<'data' | 'params', Recordable>) => { | ||
| 76 | + const { data, params } = searchValue; | ||
| 77 | + handleReset(data, params); | ||
| 78 | + }; | ||
| 79 | + | ||
| 80 | + const handleReset = (data: Recordable = {}, params: Recordable = {}) => { | ||
| 81 | + searchParams.data = data; | ||
| 82 | + searchParams.params = params; | ||
| 83 | + setPagination({ current: 1 }); | ||
| 84 | + reload(); | ||
| 85 | + }; | ||
| 86 | + | ||
| 87 | + const handleEventTypeChange = () => { | ||
| 88 | + setColumns(getColumns(unref(eventType))); | ||
| 89 | + handleReset(); | ||
| 90 | + }; | ||
| 91 | + | ||
| 92 | + const [registerDetailModal, { openModal: openDetailModal }] = useModal(); | ||
| 93 | + | ||
| 94 | + const handleOpenDetailModal = (text: string) => { | ||
| 95 | + openDetailModal(true, { | ||
| 96 | + mode: DataActionModeEnum.READ, | ||
| 97 | + record: text, | ||
| 98 | + } as ModalParamsType<string>); | ||
| 99 | + }; | ||
| 100 | + | ||
| 101 | + watch( | ||
| 102 | + () => props.elementInfo?.id, | ||
| 103 | + () => { | ||
| 104 | + reload(); | ||
| 105 | + } | ||
| 106 | + ); | ||
| 107 | +</script> | ||
| 108 | + | ||
| 109 | +<template> | ||
| 110 | + <section class="bg-gray-100 dark:bg-dark-200 p-4 h-full"> | ||
| 111 | + <BasicTable @register="register" class="debug-table h-full"> | ||
| 112 | + <template #tableTitle> | ||
| 113 | + <EventSelect v-model:type="eventType" @change="handleEventTypeChange" /> | ||
| 114 | + </template> | ||
| 115 | + <template #toolbar> | ||
| 116 | + <Tooltip title="过滤器"> | ||
| 117 | + <Icon | ||
| 118 | + icon="material-symbols:filter-list" | ||
| 119 | + class="cursor-pointer svg:text-2xl" | ||
| 120 | + @click="handleOpenFilterForm" | ||
| 121 | + /> | ||
| 122 | + </Tooltip> | ||
| 123 | + <Tooltip title="重置"> | ||
| 124 | + <Icon | ||
| 125 | + icon="mdi:filter-variant-remove" | ||
| 126 | + class="cursor-pointer svg:text-2xl" | ||
| 127 | + @click="handleRemoveFilterQueue" | ||
| 128 | + /> | ||
| 129 | + </Tooltip> | ||
| 130 | + </template> | ||
| 131 | + <template #error="{ text }"> | ||
| 132 | + <Icon | ||
| 133 | + icon="material-symbols:more-horiz" | ||
| 134 | + class="cursor-pointer svg:text-2xl" | ||
| 135 | + @click="handleOpenDetailModal(text)" | ||
| 136 | + /> | ||
| 137 | + </template> | ||
| 138 | + </BasicTable> | ||
| 139 | + | ||
| 140 | + <FilterForm | ||
| 141 | + ref="filterFormElRef" | ||
| 142 | + @register="registerModal" | ||
| 143 | + @filterChange="handleFilterChange" | ||
| 144 | + /> | ||
| 145 | + | ||
| 146 | + <ShowDetailModal @register="registerDetailModal" /> | ||
| 147 | + </section> | ||
| 148 | +</template> | ||
| 149 | + | ||
| 150 | +<style lang="less" scoped></style> | 
| 1 | +import { BasicColumn } from '/@/components/Table'; | ||
| 2 | +import { dateUtil } from '/@/utils/dateUtil'; | ||
| 3 | + | ||
| 4 | +export const columns: BasicColumn[] = [ | ||
| 5 | + { | ||
| 6 | + title: '事件时间', | ||
| 7 | + dataIndex: 'createdTime', | ||
| 8 | + ellipsis: true, | ||
| 9 | + width: 200, | ||
| 10 | + format(text) { | ||
| 11 | + return dateUtil(text).format('YYYY-MM-DD HH:mm:ss'); | ||
| 12 | + }, | ||
| 13 | + }, | ||
| 14 | + { | ||
| 15 | + title: '服务器', | ||
| 16 | + dataIndex: 'body.server', | ||
| 17 | + ellipsis: true, | ||
| 18 | + }, | ||
| 19 | + { | ||
| 20 | + title: '事件', | ||
| 21 | + dataIndex: 'body.event', | ||
| 22 | + ellipsis: true, | ||
| 23 | + }, | ||
| 24 | + { | ||
| 25 | + title: '状态', | ||
| 26 | + dataIndex: 'body.success', | ||
| 27 | + ellipsis: true, | ||
| 28 | + format(text) { | ||
| 29 | + return text ? '成功' : '失败'; | ||
| 30 | + }, | ||
| 31 | + }, | ||
| 32 | + { | ||
| 33 | + title: '错误', | ||
| 34 | + dataIndex: 'body.error', | ||
| 35 | + ellipsis: true, | ||
| 36 | + width: 100, | ||
| 37 | + slots: { | ||
| 38 | + customRender: 'error', | ||
| 39 | + }, | ||
| 40 | + }, | ||
| 41 | +]; | 
| 1 | +import { BasicColumn } from '/@/components/Table'; | ||
| 2 | +import { dateUtil } from '/@/utils/dateUtil'; | ||
| 3 | + | ||
| 4 | +export const columns: BasicColumn[] = [ | ||
| 5 | + { | ||
| 6 | + title: '事件时间', | ||
| 7 | + dataIndex: 'createdTime', | ||
| 8 | + ellipsis: true, | ||
| 9 | + width: 200, | ||
| 10 | + format(text) { | ||
| 11 | + return dateUtil(text).format('YYYY-MM-DD HH:mm:ss'); | ||
| 12 | + }, | ||
| 13 | + }, | ||
| 14 | + { | ||
| 15 | + title: '服务器', | ||
| 16 | + dataIndex: 'body.server', | ||
| 17 | + ellipsis: true, | ||
| 18 | + }, | ||
| 19 | + { | ||
| 20 | + title: '消息处理', | ||
| 21 | + dataIndex: 'body.event', | ||
| 22 | + ellipsis: true, | ||
| 23 | + }, | ||
| 24 | + { | ||
| 25 | + title: '错误发生', | ||
| 26 | + dataIndex: 'body.event', | ||
| 27 | + ellipsis: true, | ||
| 28 | + }, | ||
| 29 | +]; | 
| 1 | +export enum EventTypeEnum { | ||
| 2 | + ERROR = 'ERROR', | ||
| 3 | + LC_EVENT = 'LC_EVENT', | ||
| 4 | + STATS = 'STATS', | ||
| 5 | + DEBUG_RULE_NODE = 'DEBUG_RULE_NODE', | ||
| 6 | +} | ||
| 7 | + | ||
| 8 | +export enum EventTypeNameEnum { | ||
| 9 | + ERROR = '错误', | ||
| 10 | + LC_EVENT = '生命周期事件', | ||
| 11 | + STATS = '类型统计', | ||
| 12 | + DEBUG_RULE_NODE = '调试', | ||
| 13 | +} | ||
| 14 | + | ||
| 15 | +export const eventTypeOptions = Object.keys(EventTypeEnum).map((value) => ({ | ||
| 16 | + label: EventTypeNameEnum[value], | ||
| 17 | + value, | ||
| 18 | +})); | 
| 1 | +export { default as EventSelect } from './index.vue'; | 
| 1 | +<script setup lang="ts"> | ||
| 2 | + import { Select } from 'ant-design-vue'; | ||
| 3 | + import { eventTypeOptions, EventTypeEnum } from './config'; | ||
| 4 | + import { unref } from 'vue'; | ||
| 5 | + | ||
| 6 | + withDefaults( | ||
| 7 | + defineProps<{ | ||
| 8 | + type?: EventTypeEnum; | ||
| 9 | + }>(), | ||
| 10 | + { | ||
| 11 | + type: EventTypeEnum.DEBUG_RULE_NODE, | ||
| 12 | + } | ||
| 13 | + ); | ||
| 14 | + | ||
| 15 | + const emit = defineEmits<{ | ||
| 16 | + (eventName: 'update:type', value: EventTypeEnum): void; | ||
| 17 | + (eventName: 'change', value: EventTypeEnum): void; | ||
| 18 | + }>(); | ||
| 19 | + | ||
| 20 | + const handleChange = (value: EventTypeEnum) => { | ||
| 21 | + emit('update:type', unref(value)); | ||
| 22 | + emit('change', unref(value)); | ||
| 23 | + }; | ||
| 24 | +</script> | ||
| 25 | + | ||
| 26 | +<template> | ||
| 27 | + <Select | ||
| 28 | + :value="type" | ||
| 29 | + :options="eventTypeOptions" | ||
| 30 | + :bordered="false" | ||
| 31 | + class="border-b w-40" | ||
| 32 | + @change="handleChange" | ||
| 33 | + /> | ||
| 34 | +</template> | 
| 1 | +import { EventTypeEnum } from '../EventSelect/config'; | ||
| 2 | +import { | ||
| 3 | + formSchemas as debugFormSchemas, | ||
| 4 | + generateSearchParams as transformDebugSearchParams, | ||
| 5 | +} from './debug.config'; | ||
| 6 | +import { | ||
| 7 | + formSchemas as errorFormSchemas, | ||
| 8 | + generateSearchParams as transformErrorSearchParams, | ||
| 9 | +} from './error.config'; | ||
| 10 | +import { | ||
| 11 | + formSchemas as liveFormSchemas, | ||
| 12 | + generateSearchParams as transformLiveSearchParams, | ||
| 13 | +} from './live.config'; | ||
| 14 | +import { | ||
| 15 | + formSchemas as statsFormSchemas, | ||
| 16 | + generateSearchParams as transformStatsSearchParams, | ||
| 17 | +} from './stats.config'; | ||
| 18 | +import { FormSchema } from '/@/components/Form'; | ||
| 19 | + | ||
| 20 | +export function getFormSchemas(type: EventTypeEnum): FormSchema[] { | ||
| 21 | + const mapping = { | ||
| 22 | + [EventTypeEnum.ERROR]: errorFormSchemas, | ||
| 23 | + [EventTypeEnum.LC_EVENT]: liveFormSchemas, | ||
| 24 | + [EventTypeEnum.STATS]: statsFormSchemas, | ||
| 25 | + [EventTypeEnum.DEBUG_RULE_NODE]: debugFormSchemas, | ||
| 26 | + }; | ||
| 27 | + | ||
| 28 | + return mapping?.[type] || []; | ||
| 29 | +} | ||
| 30 | + | ||
| 31 | +export function transformFilterValue( | ||
| 32 | + type: EventTypeEnum, | ||
| 33 | + value: Recordable | ||
| 34 | +): Record<'data' | 'params', Recordable> { | ||
| 35 | + const mapping = { | ||
| 36 | + [EventTypeEnum.ERROR]: transformErrorSearchParams, | ||
| 37 | + [EventTypeEnum.LC_EVENT]: transformLiveSearchParams, | ||
| 38 | + [EventTypeEnum.STATS]: transformStatsSearchParams, | ||
| 39 | + [EventTypeEnum.DEBUG_RULE_NODE]: transformDebugSearchParams, | ||
| 40 | + }; | ||
| 41 | + return mapping?.[type]?.(value as any) || { data: {}, params: {} }; | ||
| 42 | +} | 
| 1 | +import { h } from 'vue'; | ||
| 2 | +import { RangePickerExtra } from '../RangePickerExtra'; | ||
| 3 | +import { FormSchema } from '/@/components/Form'; | ||
| 4 | + | ||
| 5 | +export enum FormFieldsEnum { | ||
| 6 | + SERVER = 'server', | ||
| 7 | + MSG_DIRECTION_TYPE = 'msgDirectionType', | ||
| 8 | + ENTITY_ID = 'entityId', | ||
| 9 | + ENTITY_NAME = 'entityName', | ||
| 10 | + MSG_TYPE = 'msgType', | ||
| 11 | + RELATION_TYPE = 'relationType', | ||
| 12 | + DATA_SEARCH = 'dataSearch', | ||
| 13 | + METADATA_SEARCH = 'metadataSearch', | ||
| 14 | + IS_ERROR = 'isError', | ||
| 15 | + ERROR_STR = 'errorStr', | ||
| 16 | + EVENT_TYPE = 'eventType', | ||
| 17 | + START_TIME = 'startTime', | ||
| 18 | + END_TIME = 'endTime', | ||
| 19 | + | ||
| 20 | + TIME_INTERVAL = 'timeInterval', | ||
| 21 | +} | ||
| 22 | + | ||
| 23 | +export enum MessageDirectionTypeEnum { | ||
| 24 | + IN = 'IN', | ||
| 25 | + OUT = 'OUT', | ||
| 26 | +} | ||
| 27 | + | ||
| 28 | +export enum EntityNameEnum { | ||
| 29 | + TENANT = 'TENANT', | ||
| 30 | + TENANT_PROFILE = 'TENANT_PROFILE', | ||
| 31 | + CUSTOMER = 'CUSTOMER', | ||
| 32 | + USER = 'USER', | ||
| 33 | + DASHBOARD = 'DASHBOARD', | ||
| 34 | + ASSET = 'ASSET', | ||
| 35 | + DEVICE = 'DEVICE', | ||
| 36 | + DEVICE_PROFILE = 'DEVICE_PROFILE', | ||
| 37 | + ALARM = 'ALARM', | ||
| 38 | + RULE_CHAIN = 'RULE_CHAIN', | ||
| 39 | + RULE_NODE = 'RULE_NODE', | ||
| 40 | + EDGE = 'EDGE', | ||
| 41 | + ENTITY_VIEW = 'ENTITY_VIEW', | ||
| 42 | + WIDGETS_BUNDLE = 'WIDGETS_BUNDLE', | ||
| 43 | + WIDGET_TYPE = 'WIDGET_TYPE', | ||
| 44 | + API_USAGE_STATE = 'API_USAGE_STATE', | ||
| 45 | + TB_RESOURCE = 'TB_RESOURCE', | ||
| 46 | + OTA_PACKAGE = 'OTA_PACKAGE', | ||
| 47 | + RPC = 'RPC', | ||
| 48 | +} | ||
| 49 | + | ||
| 50 | +export const formSchemas: FormSchema[] = [ | ||
| 51 | + { | ||
| 52 | + field: FormFieldsEnum.TIME_INTERVAL, | ||
| 53 | + label: '时间段', | ||
| 54 | + component: 'RangePicker', | ||
| 55 | + colProps: { span: 24 }, | ||
| 56 | + componentProps: { | ||
| 57 | + showTime: true, | ||
| 58 | + }, | ||
| 59 | + renderComponentContent: ({ model }) => { | ||
| 60 | + return { | ||
| 61 | + renderExtraFooter: () => | ||
| 62 | + h(RangePickerExtra, { | ||
| 63 | + onChange: (date: moment.Moment[]) => { | ||
| 64 | + model[FormFieldsEnum.TIME_INTERVAL] = date; | ||
| 65 | + }, | ||
| 66 | + }), | ||
| 67 | + }; | ||
| 68 | + }, | ||
| 69 | + }, | ||
| 70 | + { | ||
| 71 | + field: FormFieldsEnum.SERVER, | ||
| 72 | + label: '服务器', | ||
| 73 | + component: 'Input', | ||
| 74 | + componentProps: { | ||
| 75 | + placeholder: `请输入服务器`, | ||
| 76 | + }, | ||
| 77 | + }, | ||
| 78 | + { | ||
| 79 | + field: FormFieldsEnum.MSG_DIRECTION_TYPE, | ||
| 80 | + label: '类型', | ||
| 81 | + component: 'Select', | ||
| 82 | + componentProps: { | ||
| 83 | + options: Object.keys(MessageDirectionTypeEnum).map((value) => ({ label: value, value })), | ||
| 84 | + allowClear: true, | ||
| 85 | + placeholder: `请选择类型`, | ||
| 86 | + getPopupContainer: () => document.body, | ||
| 87 | + }, | ||
| 88 | + }, | ||
| 89 | + { | ||
| 90 | + field: FormFieldsEnum.ENTITY_ID, | ||
| 91 | + label: '实体ID', | ||
| 92 | + component: 'Input', | ||
| 93 | + componentProps: { | ||
| 94 | + placeholder: `请输入实体ID`, | ||
| 95 | + }, | ||
| 96 | + }, | ||
| 97 | + { | ||
| 98 | + field: FormFieldsEnum.ENTITY_NAME, | ||
| 99 | + label: '实体类型', | ||
| 100 | + component: 'Select', | ||
| 101 | + componentProps: { | ||
| 102 | + options: Object.keys(EntityNameEnum).map((value) => ({ label: value, value })), | ||
| 103 | + allowClear: true, | ||
| 104 | + placeholder: `请选择实体类型`, | ||
| 105 | + getPopupContainer: () => document.body, | ||
| 106 | + }, | ||
| 107 | + }, | ||
| 108 | + { | ||
| 109 | + field: FormFieldsEnum.MSG_TYPE, | ||
| 110 | + label: '消息类型', | ||
| 111 | + component: 'Input', | ||
| 112 | + componentProps: { | ||
| 113 | + placeholder: `请输入消息类型`, | ||
| 114 | + }, | ||
| 115 | + }, | ||
| 116 | + { | ||
| 117 | + field: FormFieldsEnum.RELATION_TYPE, | ||
| 118 | + label: '关联类型', | ||
| 119 | + component: 'Input', | ||
| 120 | + componentProps: { | ||
| 121 | + placeholder: `请输入关联类型`, | ||
| 122 | + }, | ||
| 123 | + }, | ||
| 124 | + { | ||
| 125 | + field: FormFieldsEnum.DATA_SEARCH, | ||
| 126 | + label: '数据', | ||
| 127 | + component: 'Input', | ||
| 128 | + componentProps: { | ||
| 129 | + placeholder: `请输入数据`, | ||
| 130 | + }, | ||
| 131 | + }, | ||
| 132 | + { | ||
| 133 | + field: FormFieldsEnum.METADATA_SEARCH, | ||
| 134 | + label: '元数据', | ||
| 135 | + component: 'Input', | ||
| 136 | + componentProps: { | ||
| 137 | + placeholder: `请输入元数据`, | ||
| 138 | + }, | ||
| 139 | + }, | ||
| 140 | + { | ||
| 141 | + field: FormFieldsEnum.IS_ERROR, | ||
| 142 | + label: '有错误', | ||
| 143 | + component: 'Checkbox', | ||
| 144 | + }, | ||
| 145 | + { | ||
| 146 | + field: FormFieldsEnum.ERROR_STR, | ||
| 147 | + label: '错误', | ||
| 148 | + component: 'Input', | ||
| 149 | + show: ({ model }) => model[FormFieldsEnum.IS_ERROR], | ||
| 150 | + componentProps: { | ||
| 151 | + placeholder: `请输入错误`, | ||
| 152 | + }, | ||
| 153 | + }, | ||
| 154 | +]; | ||
| 155 | + | ||
| 156 | +export function generateSearchParams( | ||
| 157 | + value: Record<FormFieldsEnum, any> | ||
| 158 | +): Record<'data' | 'params', Recordable> { | ||
| 159 | + const { | ||
| 160 | + startTime, | ||
| 161 | + endTime, | ||
| 162 | + dataSearch, | ||
| 163 | + entityId, | ||
| 164 | + entityName, | ||
| 165 | + errorStr, | ||
| 166 | + eventType, | ||
| 167 | + isError, | ||
| 168 | + metadataSearch, | ||
| 169 | + msgDirectionType, | ||
| 170 | + msgType, | ||
| 171 | + relationType, | ||
| 172 | + server, | ||
| 173 | + } = value; | ||
| 174 | + | ||
| 175 | + return { | ||
| 176 | + params: { startTime, endTime }, | ||
| 177 | + data: { | ||
| 178 | + dataSearch, | ||
| 179 | + entityId, | ||
| 180 | + entityName, | ||
| 181 | + errorStr, | ||
| 182 | + eventType, | ||
| 183 | + isError, | ||
| 184 | + metadataSearch, | ||
| 185 | + msgDirectionType, | ||
| 186 | + msgType, | ||
| 187 | + relationType, | ||
| 188 | + server, | ||
| 189 | + }, | ||
| 190 | + }; | ||
| 191 | +} | 
| 1 | +import { h } from 'vue'; | ||
| 2 | +import { RangePickerExtra } from '../RangePickerExtra'; | ||
| 3 | +import { FormSchema } from '/@/components/Form'; | ||
| 4 | + | ||
| 5 | +export enum FormFieldsEnum { | ||
| 6 | + ERROR_STR = 'errorStr', | ||
| 7 | + METHOD = 'method', | ||
| 8 | + SERVER = 'server', | ||
| 9 | + | ||
| 10 | + START_TIME = 'startTime', | ||
| 11 | + END_TIME = 'endTime', | ||
| 12 | + TIME_INTERVAL = 'timeInterval', | ||
| 13 | +} | ||
| 14 | + | ||
| 15 | +export const formSchemas: FormSchema[] = [ | ||
| 16 | + { | ||
| 17 | + field: FormFieldsEnum.TIME_INTERVAL, | ||
| 18 | + label: '时间段', | ||
| 19 | + component: 'RangePicker', | ||
| 20 | + colProps: { span: 24 }, | ||
| 21 | + componentProps: { | ||
| 22 | + showTime: true, | ||
| 23 | + }, | ||
| 24 | + renderComponentContent: ({ model }) => { | ||
| 25 | + return { | ||
| 26 | + renderExtraFooter: () => | ||
| 27 | + h(RangePickerExtra, { | ||
| 28 | + onChange: (date: moment.Moment[]) => { | ||
| 29 | + model[FormFieldsEnum.TIME_INTERVAL] = date; | ||
| 30 | + }, | ||
| 31 | + }), | ||
| 32 | + }; | ||
| 33 | + }, | ||
| 34 | + }, | ||
| 35 | + { | ||
| 36 | + field: FormFieldsEnum.SERVER, | ||
| 37 | + label: '服务器', | ||
| 38 | + component: 'Input', | ||
| 39 | + componentProps: { | ||
| 40 | + placeholder: `请输入服务器`, | ||
| 41 | + }, | ||
| 42 | + }, | ||
| 43 | + { | ||
| 44 | + field: FormFieldsEnum.METHOD, | ||
| 45 | + label: '方法', | ||
| 46 | + component: 'Input', | ||
| 47 | + componentProps: { | ||
| 48 | + placeholder: `请输入方法`, | ||
| 49 | + }, | ||
| 50 | + }, | ||
| 51 | + { | ||
| 52 | + field: FormFieldsEnum.ERROR_STR, | ||
| 53 | + label: '错误', | ||
| 54 | + component: 'Input', | ||
| 55 | + componentProps: { | ||
| 56 | + placeholder: `请输入错误`, | ||
| 57 | + }, | ||
| 58 | + }, | ||
| 59 | +]; | ||
| 60 | + | ||
| 61 | +export function generateSearchParams( | ||
| 62 | + value: Record<FormFieldsEnum, any> | ||
| 63 | +): Record<'data' | 'params', Recordable> { | ||
| 64 | + const { startTime, endTime, errorStr, method, server } = value; | ||
| 65 | + return { | ||
| 66 | + data: { errorStr, method, server }, | ||
| 67 | + params: { startTime, endTime }, | ||
| 68 | + }; | ||
| 69 | +} | 
| 1 | +export { default as FilterForm } from './index.vue'; | 
| 1 | +<script setup lang="ts"> | ||
| 2 | + import { ref, unref } from 'vue'; | ||
| 3 | + import { EventTypeEnum } from '../EventSelect/config'; | ||
| 4 | + import { getFormSchemas, transformFilterValue } from './config'; | ||
| 5 | + import { FormFieldsEnum } from './debug.config'; | ||
| 6 | + import { BasicForm, useForm } from '/@/components/Form'; | ||
| 7 | + import { BasicModal, useModalInner } from '/@/components/Modal'; | ||
| 8 | + | ||
| 9 | + interface FilterChangeValueType { | ||
| 10 | + data: Recordable; | ||
| 11 | + params: Recordable; | ||
| 12 | + } | ||
| 13 | + | ||
| 14 | + const emit = defineEmits<{ | ||
| 15 | + (eventName: 'register', value: any): any; | ||
| 16 | + (eventName: 'filterChange', value: FilterChangeValueType): void; | ||
| 17 | + }>(); | ||
| 18 | + | ||
| 19 | + const [registerForm, { resetSchema, getFieldsValue, resetFields }] = useForm({ | ||
| 20 | + layout: 'inline', | ||
| 21 | + showActionButtonGroup: false, | ||
| 22 | + labelWidth: 80, | ||
| 23 | + fieldMapToTime: [ | ||
| 24 | + [FormFieldsEnum.TIME_INTERVAL, [FormFieldsEnum.START_TIME, FormFieldsEnum.END_TIME], 'x'], | ||
| 25 | + ], | ||
| 26 | + }); | ||
| 27 | + | ||
| 28 | + const eventType = ref(); | ||
| 29 | + | ||
| 30 | + const [register, { closeModal }] = useModalInner( | ||
| 31 | + (params: ModalParamsType<{ type: EventTypeEnum }>) => { | ||
| 32 | + const { record } = params; | ||
| 33 | + const { type } = record; | ||
| 34 | + if (unref(eventType) !== type) { | ||
| 35 | + resetFields(); | ||
| 36 | + } | ||
| 37 | + eventType.value = type; | ||
| 38 | + resetSchema(getFormSchemas(unref(eventType))); | ||
| 39 | + } | ||
| 40 | + ); | ||
| 41 | + | ||
| 42 | + const handleOk = () => { | ||
| 43 | + emit('filterChange', transformFilterValue(unref(eventType), getFieldsValue())); | ||
| 44 | + closeModal(); | ||
| 45 | + }; | ||
| 46 | + | ||
| 47 | + defineExpose({ | ||
| 48 | + resetFields, | ||
| 49 | + }); | ||
| 50 | +</script> | ||
| 51 | + | ||
| 52 | +<template> | ||
| 53 | + <BasicModal | ||
| 54 | + @register="register" | ||
| 55 | + title="过滤器" | ||
| 56 | + wrapClassName="rule-node-filter-form" | ||
| 57 | + @cancel="closeModal()" | ||
| 58 | + @ok="handleOk" | ||
| 59 | + > | ||
| 60 | + <BasicForm @register="registerForm" /> | ||
| 61 | + </BasicModal> | ||
| 62 | +</template> | ||
| 63 | + | ||
| 64 | +<style lang="less"> | ||
| 65 | + .rule-node-filter-form { | ||
| 66 | + .ant-form-item-label { | ||
| 67 | + label { | ||
| 68 | + @apply w-full truncate block leading-8; | ||
| 69 | + } | ||
| 70 | + } | ||
| 71 | + | ||
| 72 | + .ant-calendar-picker.ant-calendar-picker-default { | ||
| 73 | + @apply !w-full; | ||
| 74 | + } | ||
| 75 | + | ||
| 76 | + .ant-input-number { | ||
| 77 | + @apply w-full; | ||
| 78 | + } | ||
| 79 | + } | ||
| 80 | +</style> | 
| 1 | +import { h } from 'vue'; | ||
| 2 | +import { RangePickerExtra } from '../RangePickerExtra'; | ||
| 3 | +import { FormSchema } from '/@/components/Form'; | ||
| 4 | + | ||
| 5 | +export enum FormFieldsEnum { | ||
| 6 | + ERROR_STR = 'errorStr', | ||
| 7 | + EVENT = 'event', | ||
| 8 | + SERVER = 'server', | ||
| 9 | + STATUS = 'status', | ||
| 10 | + | ||
| 11 | + START_TIME = 'startTime', | ||
| 12 | + END_TIME = 'endTime', | ||
| 13 | + TIME_INTERVAL = 'timeInterval', | ||
| 14 | +} | ||
| 15 | + | ||
| 16 | +enum StatusEnum { | ||
| 17 | + SUCCESS = 'SUCCESS', | ||
| 18 | + FAILURE = 'FAILURE', | ||
| 19 | +} | ||
| 20 | + | ||
| 21 | +enum StatusNameEnum { | ||
| 22 | + SUCCESS = 'Success', | ||
| 23 | + FAILURE = 'Failure', | ||
| 24 | +} | ||
| 25 | + | ||
| 26 | +export const formSchemas: FormSchema[] = [ | ||
| 27 | + { | ||
| 28 | + field: FormFieldsEnum.TIME_INTERVAL, | ||
| 29 | + label: '时间段', | ||
| 30 | + component: 'RangePicker', | ||
| 31 | + colProps: { span: 24 }, | ||
| 32 | + componentProps: { | ||
| 33 | + showTime: true, | ||
| 34 | + }, | ||
| 35 | + renderComponentContent: ({ model }) => { | ||
| 36 | + return { | ||
| 37 | + renderExtraFooter: () => | ||
| 38 | + h(RangePickerExtra, { | ||
| 39 | + onChange: (date: moment.Moment[]) => { | ||
| 40 | + model[FormFieldsEnum.TIME_INTERVAL] = date; | ||
| 41 | + }, | ||
| 42 | + }), | ||
| 43 | + }; | ||
| 44 | + }, | ||
| 45 | + }, | ||
| 46 | + { | ||
| 47 | + field: FormFieldsEnum.SERVER, | ||
| 48 | + label: '服务器', | ||
| 49 | + component: 'Input', | ||
| 50 | + componentProps: { | ||
| 51 | + placeholder: `请输入服务器`, | ||
| 52 | + }, | ||
| 53 | + }, | ||
| 54 | + { | ||
| 55 | + field: FormFieldsEnum.EVENT, | ||
| 56 | + label: '事件', | ||
| 57 | + component: 'Input', | ||
| 58 | + componentProps: { | ||
| 59 | + placeholder: `请输入事件`, | ||
| 60 | + }, | ||
| 61 | + }, | ||
| 62 | + { | ||
| 63 | + field: FormFieldsEnum.STATUS, | ||
| 64 | + label: '状态', | ||
| 65 | + component: 'Input', | ||
| 66 | + componentProps: { | ||
| 67 | + options: Object.keys(StatusEnum).map((value) => ({ label: StatusNameEnum[value], value })), | ||
| 68 | + allowClear: true, | ||
| 69 | + placeholder: `请选择状态`, | ||
| 70 | + getPopupContainer: () => document.body, | ||
| 71 | + }, | ||
| 72 | + }, | ||
| 73 | + { | ||
| 74 | + field: FormFieldsEnum.ERROR_STR, | ||
| 75 | + label: '错误', | ||
| 76 | + component: 'Input', | ||
| 77 | + componentProps: { | ||
| 78 | + placeholder: `请输入错误`, | ||
| 79 | + }, | ||
| 80 | + }, | ||
| 81 | +]; | ||
| 82 | + | ||
| 83 | +export function generateSearchParams( | ||
| 84 | + value: Record<FormFieldsEnum, any> | ||
| 85 | +): Record<'data' | 'params', Recordable> { | ||
| 86 | + const { startTime, endTime, errorStr, event, status, server } = value; | ||
| 87 | + return { | ||
| 88 | + data: { errorStr, event, status, server }, | ||
| 89 | + params: { startTime, endTime }, | ||
| 90 | + }; | ||
| 91 | +} | 
| 1 | +import { h } from 'vue'; | ||
| 2 | +import { RangePickerExtra } from '../RangePickerExtra'; | ||
| 3 | +import { FormSchema } from '/@/components/Form'; | ||
| 4 | + | ||
| 5 | +export enum FormFieldsEnum { | ||
| 6 | + SERVER = 'server', | ||
| 7 | + MESSAGE_PROCESSED = 'messageProcessed', | ||
| 8 | + ERRORS_OCCURRED = 'errorsOccured', | ||
| 9 | + | ||
| 10 | + START_TIME = 'startTime', | ||
| 11 | + END_TIME = 'endTime', | ||
| 12 | + TIME_INTERVAL = 'timeInterval', | ||
| 13 | +} | ||
| 14 | + | ||
| 15 | +export const formSchemas: FormSchema[] = [ | ||
| 16 | + { | ||
| 17 | + field: FormFieldsEnum.TIME_INTERVAL, | ||
| 18 | + label: '时间段', | ||
| 19 | + component: 'RangePicker', | ||
| 20 | + colProps: { span: 24 }, | ||
| 21 | + componentProps: { | ||
| 22 | + showTime: true, | ||
| 23 | + }, | ||
| 24 | + renderComponentContent: ({ model }) => { | ||
| 25 | + return { | ||
| 26 | + renderExtraFooter: () => | ||
| 27 | + h(RangePickerExtra, { | ||
| 28 | + onChange: (date: moment.Moment[]) => { | ||
| 29 | + model[FormFieldsEnum.TIME_INTERVAL] = date; | ||
| 30 | + }, | ||
| 31 | + }), | ||
| 32 | + }; | ||
| 33 | + }, | ||
| 34 | + }, | ||
| 35 | + { | ||
| 36 | + field: FormFieldsEnum.SERVER, | ||
| 37 | + label: '服务器', | ||
| 38 | + component: 'Input', | ||
| 39 | + componentProps: { | ||
| 40 | + placeholder: `请输入服务器`, | ||
| 41 | + }, | ||
| 42 | + }, | ||
| 43 | + { | ||
| 44 | + field: FormFieldsEnum.MESSAGE_PROCESSED, | ||
| 45 | + label: 'Minimum messages processed', | ||
| 46 | + component: 'InputNumber', | ||
| 47 | + componentProps: { | ||
| 48 | + min: 0, | ||
| 49 | + placeholder: `请输入Minimum messages processed`, | ||
| 50 | + }, | ||
| 51 | + }, | ||
| 52 | + { | ||
| 53 | + field: FormFieldsEnum.ERRORS_OCCURRED, | ||
| 54 | + label: 'Minimum errors occurred', | ||
| 55 | + component: 'InputNumber', | ||
| 56 | + componentProps: { | ||
| 57 | + min: 0, | ||
| 58 | + placeholder: `请输入Minimum errors occurred`, | ||
| 59 | + }, | ||
| 60 | + }, | ||
| 61 | +]; | ||
| 62 | + | ||
| 63 | +export function generateSearchParams( | ||
| 64 | + value: Record<FormFieldsEnum, any> | ||
| 65 | +): Record<'data' | 'params', Recordable> { | ||
| 66 | + const { startTime, endTime, messageProcessed, errorsOccured, server } = value; | ||
| 67 | + return { | ||
| 68 | + data: { messageProcessed, errorsOccured, server }, | ||
| 69 | + params: { startTime, endTime }, | ||
| 70 | + }; | ||
| 71 | +} | 
| 1 | +import { dateUtil } from '/@/utils/dateUtil'; | ||
| 2 | + | ||
| 3 | +export enum TimeUnitEnum { | ||
| 4 | + day = 'day', | ||
| 5 | + hour = 'hour', | ||
| 6 | + minute = 'minute', | ||
| 7 | + second = 'second', | ||
| 8 | +} | ||
| 9 | +export enum TimeUnitNameEnum { | ||
| 10 | + day = '天', | ||
| 11 | + hour = '小时', | ||
| 12 | + minute = '分', | ||
| 13 | + second = '秒', | ||
| 14 | +} | ||
| 15 | + | ||
| 16 | +export enum DateShortcutOptionEnum { | ||
| 17 | + YESTERDAY = 'YESTERDAY', | ||
| 18 | + DAY_BEFORE_YESTERDAY = 'DAY_BEFORE_YESTERDAY', | ||
| 19 | + THIS_DAY_LAST_WEEK = 'THIS_DAY_LAST_WEEK', | ||
| 20 | + PREVIOUS_WEEK_SUN_SAT = 'PREVIOUS_WEEK_SUN_SAT', | ||
| 21 | + PREVIOUS_WEEK_MON_SUN = 'PREVIOUS_WEEK_MON_SUN', | ||
| 22 | + PREVIOUS_MONTH = 'PREVIOUS_MONTH', | ||
| 23 | + PREVIOUS_YEAR = 'PREVIOUS_YEAR', | ||
| 24 | + CURRENT_HOUR = 'CURRENT_HOUR', | ||
| 25 | + CURRENT_DAY = 'CURRENT_DAY', | ||
| 26 | + CURRENT_DAY_SO_FAR = 'CURRENT_DAY_SO_FAR', | ||
| 27 | + CURRENT_WEEK_SUN_SAT = 'CURRENT_WEEK_SUN_SAT', | ||
| 28 | + CURRENT_WEEK_MON_SUN = 'CURRENT_WEEK_MON_SUN', | ||
| 29 | + CURRENT_WEEK_SO_FAR_SUN_SAT = 'CURRENT_WEEK_SO_FAR_SUN_SAT', | ||
| 30 | + CURRENT_WEEK_SO_FAR_MON_SUN = 'CURRENT_WEEK_SO_FAR_MON_SUN', | ||
| 31 | + CURRENT_MONTH = 'CURRENT_MONTH', | ||
| 32 | + CURRENT_MONTH_SO_FAR = 'CURRENT_MONTH_SO_FAR', | ||
| 33 | + CURRENT_YEAR = 'CURRENT_YEAR', | ||
| 34 | + CURRENT_YEAR_SO_FAR = 'CURRENT_YEAR_SO_FAR', | ||
| 35 | +} | ||
| 36 | +export enum DateShortcutOptionNameEnum { | ||
| 37 | + YESTERDAY = '昨天', | ||
| 38 | + DAY_BEFORE_YESTERDAY = '前天', | ||
| 39 | + THIS_DAY_LAST_WEEK = '前一周的这一天', | ||
| 40 | + PREVIOUS_WEEK_SUN_SAT = '前一周 (周日至周六)', | ||
| 41 | + PREVIOUS_WEEK_MON_SUN = '前一周 (周一至周日)', | ||
| 42 | + PREVIOUS_MONTH = '前一个月', | ||
| 43 | + PREVIOUS_YEAR = '前一年', | ||
| 44 | + CURRENT_HOUR = '当前小时', | ||
| 45 | + CURRENT_DAY = '当前天', | ||
| 46 | + CURRENT_DAY_SO_FAR = '当天到目前为止', | ||
| 47 | + CURRENT_WEEK_SUN_SAT = '本周 (周日至周六)', | ||
| 48 | + CURRENT_WEEK_MON_SUN = '本周 (周一至周日)', | ||
| 49 | + CURRENT_WEEK_SO_FAR_SUN_SAT = '本周到目前为止 (周日至周六)', | ||
| 50 | + CURRENT_WEEK_SO_FAR_MON_SUN = '本周到目前为止 (周一至周日)', | ||
| 51 | + CURRENT_MONTH = '本月', | ||
| 52 | + CURRENT_MONTH_SO_FAR = '本月到目前为止', | ||
| 53 | + CURRENT_YEAR = '本年', | ||
| 54 | + CURRENT_YEAR_SO_FAR = '本年到目前为止', | ||
| 55 | +} | ||
| 56 | + | ||
| 57 | +const options = [ | ||
| 58 | + { value: 1, unit: TimeUnitEnum.second }, | ||
| 59 | + { value: 5, unit: TimeUnitEnum.second }, | ||
| 60 | + { value: 10, unit: TimeUnitEnum.second }, | ||
| 61 | + { value: 15, unit: TimeUnitEnum.second }, | ||
| 62 | + { value: 30, unit: TimeUnitEnum.second }, | ||
| 63 | + | ||
| 64 | + { value: 1, unit: TimeUnitEnum.minute }, | ||
| 65 | + { value: 5, unit: TimeUnitEnum.minute }, | ||
| 66 | + { value: 10, unit: TimeUnitEnum.minute }, | ||
| 67 | + { value: 15, unit: TimeUnitEnum.minute }, | ||
| 68 | + { value: 30, unit: TimeUnitEnum.minute }, | ||
| 69 | + | ||
| 70 | + { value: 1, unit: TimeUnitEnum.hour }, | ||
| 71 | + { value: 2, unit: TimeUnitEnum.hour }, | ||
| 72 | + { value: 5, unit: TimeUnitEnum.hour }, | ||
| 73 | + { value: 10, unit: TimeUnitEnum.hour }, | ||
| 74 | + { value: 12, unit: TimeUnitEnum.hour }, | ||
| 75 | + | ||
| 76 | + { value: 1, unit: TimeUnitEnum.day }, | ||
| 77 | + { value: 7, unit: TimeUnitEnum.day }, | ||
| 78 | + { value: 30, unit: TimeUnitEnum.day }, | ||
| 79 | +]; | ||
| 80 | + | ||
| 81 | +export const latestOptions = options.map((item) => ({ | ||
| 82 | + ...item, | ||
| 83 | + value: `${item.value}${item.unit}`, | ||
| 84 | + label: `${item.value} ${TimeUnitNameEnum[item.unit]}`, | ||
| 85 | + unitValue: item.value, | ||
| 86 | +})); | ||
| 87 | + | ||
| 88 | +export const shortcutOptions = Object.keys(DateShortcutOptionEnum).map((value) => ({ | ||
| 89 | + label: DateShortcutOptionNameEnum[value], | ||
| 90 | + value, | ||
| 91 | +})); | ||
| 92 | + | ||
| 93 | +export const getShortcutOptionValue = (value: DateShortcutOptionEnum) => { | ||
| 94 | + const mapping = { | ||
| 95 | + YESTERDAY: () => { | ||
| 96 | + const startDate = dateUtil().subtract(1, 'day').startOf('day'); | ||
| 97 | + const endDate = dateUtil().subtract(1, 'day').endOf('day'); | ||
| 98 | + return [startDate, endDate]; | ||
| 99 | + }, | ||
| 100 | + DAY_BEFORE_YESTERDAY: () => { | ||
| 101 | + const startDate = dateUtil().subtract(2, 'day').startOf('day'); | ||
| 102 | + const endDate = dateUtil().subtract(2, 'day').endOf('day'); | ||
| 103 | + return [startDate, endDate]; | ||
| 104 | + }, | ||
| 105 | + THIS_DAY_LAST_WEEK: () => { | ||
| 106 | + const startDate = dateUtil().subtract(7, 'day').startOf('day'); | ||
| 107 | + const endDate = dateUtil().subtract(7, 'day').endOf('day'); | ||
| 108 | + return [startDate, endDate]; | ||
| 109 | + }, | ||
| 110 | + PREVIOUS_WEEK_SUN_SAT: () => { | ||
| 111 | + const startDate = dateUtil() | ||
| 112 | + .subtract(1, 'week') | ||
| 113 | + .startOf('week') | ||
| 114 | + .subtract(1, 'day') | ||
| 115 | + .startOf('day'); | ||
| 116 | + const endDate = dateUtil().subtract(1, 'week').endOf('week').subtract(1, 'day').endOf('day'); | ||
| 117 | + return [startDate, endDate]; | ||
| 118 | + }, | ||
| 119 | + PREVIOUS_WEEK_MON_SUN: () => { | ||
| 120 | + const startDate = dateUtil().subtract(1, 'week').startOf('week'); | ||
| 121 | + const endDate = dateUtil().subtract(1, 'week').endOf('week'); | ||
| 122 | + return [startDate, endDate]; | ||
| 123 | + }, | ||
| 124 | + PREVIOUS_MONTH: () => { | ||
| 125 | + const startDate = dateUtil().subtract(1, 'month').startOf('month'); | ||
| 126 | + const endDate = dateUtil().subtract(1, 'month').endOf('month'); | ||
| 127 | + return [startDate, endDate]; | ||
| 128 | + }, | ||
| 129 | + PREVIOUS_YEAR: () => { | ||
| 130 | + const startDate = dateUtil().subtract(1, 'year').startOf('year'); | ||
| 131 | + const endDate = dateUtil().subtract(1, 'year').endOf('year'); | ||
| 132 | + return [startDate, endDate]; | ||
| 133 | + }, | ||
| 134 | + CURRENT_HOUR: () => { | ||
| 135 | + const startDate = dateUtil().startOf('hour'); | ||
| 136 | + const endDate = dateUtil().endOf('hour'); | ||
| 137 | + return [startDate, endDate]; | ||
| 138 | + }, | ||
| 139 | + CURRENT_DAY: () => { | ||
| 140 | + const startDate = dateUtil().startOf('day'); | ||
| 141 | + const endDate = dateUtil().endOf('day'); | ||
| 142 | + return [startDate, endDate]; | ||
| 143 | + }, | ||
| 144 | + CURRENT_DAY_SO_FAR: () => { | ||
| 145 | + const startDate = dateUtil().startOf('day'); | ||
| 146 | + const endDate = dateUtil(); | ||
| 147 | + return [startDate, endDate]; | ||
| 148 | + }, | ||
| 149 | + CURRENT_WEEK_SUN_SAT: () => { | ||
| 150 | + const startDate = dateUtil().startOf('week').subtract(1, 'day').startOf('day'); | ||
| 151 | + const endDate = dateUtil().endOf('week').subtract(1, 'day').endOf('day'); | ||
| 152 | + return [startDate, endDate]; | ||
| 153 | + }, | ||
| 154 | + CURRENT_WEEK_MON_SUN: () => { | ||
| 155 | + const startDate = dateUtil().startOf('week'); | ||
| 156 | + const endDate = dateUtil().endOf('week'); | ||
| 157 | + return [startDate, endDate]; | ||
| 158 | + }, | ||
| 159 | + CURRENT_WEEK_SO_FAR_SUN_SAT: () => { | ||
| 160 | + const startDate = dateUtil().startOf('week').subtract(1, 'day').startOf('day'); | ||
| 161 | + const endDate = dateUtil(); | ||
| 162 | + return [startDate, endDate]; | ||
| 163 | + }, | ||
| 164 | + CURRENT_WEEK_SO_FAR_MON_SUN: () => { | ||
| 165 | + const startDate = dateUtil().startOf('week'); | ||
| 166 | + const endDate = dateUtil(); | ||
| 167 | + return [startDate, endDate]; | ||
| 168 | + }, | ||
| 169 | + CURRENT_MONTH: () => { | ||
| 170 | + const startDate = dateUtil().startOf('month'); | ||
| 171 | + const endDate = dateUtil().endOf('month'); | ||
| 172 | + return [startDate, endDate]; | ||
| 173 | + }, | ||
| 174 | + CURRENT_MONTH_SO_FAR: () => { | ||
| 175 | + const startDate = dateUtil().startOf('month'); | ||
| 176 | + const endDate = dateUtil(); | ||
| 177 | + return [startDate, endDate]; | ||
| 178 | + }, | ||
| 179 | + CURRENT_YEAR: () => { | ||
| 180 | + const startDate = dateUtil().startOf('year'); | ||
| 181 | + const endDate = dateUtil().endOf('year'); | ||
| 182 | + return [startDate, endDate]; | ||
| 183 | + }, | ||
| 184 | + CURRENT_YEAR_SO_FAR: () => { | ||
| 185 | + const startDate = dateUtil().startOf('year'); | ||
| 186 | + const endDate = dateUtil(); | ||
| 187 | + return [startDate, endDate]; | ||
| 188 | + }, | ||
| 189 | + }; | ||
| 190 | + return mapping?.[value]?.() || []; | ||
| 191 | +}; | 
| 1 | +export { default as RangePickerExtra } from './index.vue'; | 
| 1 | +<script setup lang="ts"> | ||
| 2 | + import { Button, Popover, Select, Switch, InputNumber } from 'ant-design-vue'; | ||
| 3 | + import { reactive, ref, unref } from 'vue'; | ||
| 4 | + import { | ||
| 5 | + DateShortcutOptionEnum, | ||
| 6 | + getShortcutOptionValue, | ||
| 7 | + latestOptions, | ||
| 8 | + shortcutOptions, | ||
| 9 | + } from './config'; | ||
| 10 | + import { getPopupContainer } from '/@/utils'; | ||
| 11 | + import { dateUtil } from '/@/utils/dateUtil'; | ||
| 12 | + | ||
| 13 | + const emit = defineEmits<{ | ||
| 14 | + (eventName: 'change', date: moment.Moment[]): void; | ||
| 15 | + }>(); | ||
| 16 | + | ||
| 17 | + const mode = ref(false); | ||
| 18 | + | ||
| 19 | + const latestPopoverVisible = ref(false); | ||
| 20 | + | ||
| 21 | + const latestSelect = ref(); | ||
| 22 | + | ||
| 23 | + const advancedLatest = reactive({ | ||
| 24 | + days: 0, | ||
| 25 | + hours: 0, | ||
| 26 | + minutes: 0, | ||
| 27 | + seconds: 0, | ||
| 28 | + }); | ||
| 29 | + | ||
| 30 | + const getAdvancedLatest = () => { | ||
| 31 | + const startDate = Object.keys(advancedLatest).reduce((prev, next) => { | ||
| 32 | + return prev.subtract(advancedLatest[next], next); | ||
| 33 | + }, dateUtil()); | ||
| 34 | + return [startDate, dateUtil()]; | ||
| 35 | + }; | ||
| 36 | + | ||
| 37 | + const getLatestSelect = () => { | ||
| 38 | + const selected = latestOptions.find((item) => item.value === unref(latestSelect))!; | ||
| 39 | + if (!selected) return []; | ||
| 40 | + const startDate = dateUtil().subtract(selected.unitValue, selected.unit); | ||
| 41 | + return [startDate, dateUtil()]; | ||
| 42 | + }; | ||
| 43 | + | ||
| 44 | + const handleUpdateDate = () => { | ||
| 45 | + emit('change', unref(mode) ? getAdvancedLatest() : getLatestSelect()); | ||
| 46 | + latestPopoverVisible.value = false; | ||
| 47 | + }; | ||
| 48 | + | ||
| 49 | + const shortcutOptionPopoverVisible = ref(false); | ||
| 50 | + | ||
| 51 | + const shortcutOptionSelect = ref<DateShortcutOptionEnum>(); | ||
| 52 | + | ||
| 53 | + const handleShortcutOptionUpdate = () => { | ||
| 54 | + unref(shortcutOptionSelect) && | ||
| 55 | + emit('change', getShortcutOptionValue(unref(shortcutOptionSelect)!)); | ||
| 56 | + shortcutOptionPopoverVisible.value = false; | ||
| 57 | + }; | ||
| 58 | +</script> | ||
| 59 | + | ||
| 60 | +<template> | ||
| 61 | + <section class="h-full items-center flex gap-2 h-9"> | ||
| 62 | + <Popover | ||
| 63 | + v-model:visible="latestPopoverVisible" | ||
| 64 | + trigger="click" | ||
| 65 | + :overlayStyle="{ zIndex: 9999 }" | ||
| 66 | + overlayClassName="range-picker-extra-latest-popover" | ||
| 67 | + > | ||
| 68 | + <template #content> | ||
| 69 | + <main class="w-90 p-4"> | ||
| 70 | + <div class="flex gap-3 items-end"> | ||
| 71 | + <div v-if="!mode" class="w-full"> | ||
| 72 | + <Select | ||
| 73 | + v-model:value="latestSelect" | ||
| 74 | + class="w-full border-b" | ||
| 75 | + :getPopupContainer="getPopupContainer" | ||
| 76 | + placeholder="请选择区间" | ||
| 77 | + :bordered="false" | ||
| 78 | + :options="latestOptions" | ||
| 79 | + /> | ||
| 80 | + </div> | ||
| 81 | + | ||
| 82 | + <div v-if="mode" class="w-full flex gap-1"> | ||
| 83 | + <div class="w-1/4"> | ||
| 84 | + <div>天</div> | ||
| 85 | + <InputNumber v-model:value="advancedLatest.days" :min="0" :precision="0" /> | ||
| 86 | + </div> | ||
| 87 | + <div class="w-1/4"> | ||
| 88 | + <div>小时</div> | ||
| 89 | + <InputNumber v-model:value="advancedLatest.hours" :min="0" :precision="0" /> | ||
| 90 | + </div> | ||
| 91 | + <div class="w-1/4"> | ||
| 92 | + <div>分钟</div> | ||
| 93 | + <InputNumber v-model:value="advancedLatest.minutes" :min="0" :precision="0" /> | ||
| 94 | + </div> | ||
| 95 | + <div class="w-1/4"> | ||
| 96 | + <div>秒</div> | ||
| 97 | + <InputNumber v-model:value="advancedLatest.seconds" :min="0" :precision="0" /> | ||
| 98 | + </div> | ||
| 99 | + </div> | ||
| 100 | + | ||
| 101 | + <div> | ||
| 102 | + <div class="h-6 text-center">高级</div> | ||
| 103 | + <Switch v-model:checked="mode" /> | ||
| 104 | + </div> | ||
| 105 | + </div> | ||
| 106 | + <div class="w-full flex mt-4 gap-4 justify-end"> | ||
| 107 | + <Button size="small" @click="latestPopoverVisible = false"> 取消</Button> | ||
| 108 | + <Button size="small" type="primary" @click="handleUpdateDate"> 更新</Button> | ||
| 109 | + </div> | ||
| 110 | + </main> | ||
| 111 | + </template> | ||
| 112 | + <Button type="primary" size="small" @click="latestPopoverVisible = true">最后</Button> | ||
| 113 | + </Popover> | ||
| 114 | + | ||
| 115 | + <Popover | ||
| 116 | + v-model:visible="shortcutOptionPopoverVisible" | ||
| 117 | + trigger="click" | ||
| 118 | + :overlayStyle="{ zIndex: 9999 }" | ||
| 119 | + overlayClassName="range-picker-extra-shortcut-popover" | ||
| 120 | + > | ||
| 121 | + <template #content> | ||
| 122 | + <main class="w-90 p-4"> | ||
| 123 | + <div> | ||
| 124 | + <Select | ||
| 125 | + v-model:value="shortcutOptionSelect" | ||
| 126 | + class="w-full border-b" | ||
| 127 | + :getPopupContainer="getPopupContainer" | ||
| 128 | + placeholder="请选择区间" | ||
| 129 | + :bordered="false" | ||
| 130 | + :options="shortcutOptions" | ||
| 131 | + /> | ||
| 132 | + </div> | ||
| 133 | + <div class="w-full flex mt-4 gap-4 justify-end"> | ||
| 134 | + <Button size="small" @click="shortcutOptionPopoverVisible = false"> 取消</Button> | ||
| 135 | + <Button size="small" type="primary" @click="handleShortcutOptionUpdate"> 更新</Button> | ||
| 136 | + </div> | ||
| 137 | + </main> | ||
| 138 | + </template> | ||
| 139 | + <Button type="primary" size="small" @click="shortcutOptionPopoverVisible = true"> | ||
| 140 | + 快捷选择 | ||
| 141 | + </Button> | ||
| 142 | + </Popover> | ||
| 143 | + </section> | ||
| 144 | +</template> | ||
| 145 | + | ||
| 146 | +<style lang="less"> | ||
| 147 | + .range-picker-extra-latest-popover { | ||
| 148 | + .ant-input-number { | ||
| 149 | + min-width: fit-content; | ||
| 150 | + width: 100%; | ||
| 151 | + } | ||
| 152 | + } | ||
| 153 | +</style> | 
| @@ -9,7 +9,7 @@ | @@ -9,7 +9,7 @@ | ||
| 9 | import { useForm, BasicForm } from '/@/components/Form'; | 9 | import { useForm, BasicForm } from '/@/components/Form'; | 
| 10 | import { BottomFormSchemas, TopFormSchemas } from '../CreateNodeModal/config'; | 10 | import { BottomFormSchemas, TopFormSchemas } from '../CreateNodeModal/config'; | 
| 11 | import { toRaw, unref } from 'vue'; | 11 | import { toRaw, unref } from 'vue'; | 
| 12 | - import { BasicEvents } from '../BasicEvents'; | 12 | + import { BasicEvents } from './BasicEvents'; | 
| 13 | 13 | ||
| 14 | const [topFormRegister, topFormActionType] = useForm({ | 14 | const [topFormRegister, topFormActionType] = useForm({ | 
| 15 | schemas: TopFormSchemas, | 15 | schemas: TopFormSchemas, | 
| @@ -25,6 +25,7 @@ | @@ -25,6 +25,7 @@ | ||
| 25 | visible, | 25 | visible, | 
| 26 | spinning, | 26 | spinning, | 
| 27 | nodeData, | 27 | nodeData, | 
| 28 | + elementInfo, | ||
| 28 | getComponentKey, | 29 | getComponentKey, | 
| 29 | shadowComponent, | 30 | shadowComponent, | 
| 30 | createComponentEl, | 31 | createComponentEl, | 
| @@ -113,7 +114,7 @@ | @@ -113,7 +114,7 @@ | ||
| 113 | </Spin> | 114 | </Spin> | 
| 114 | </Tabs.TabPane> | 115 | </Tabs.TabPane> | 
| 115 | <Tabs.TabPane :tab="TabsPanelNameEnum[TabsPanelEnum.EVENT]" :key="TabsPanelEnum.EVENT"> | 116 | <Tabs.TabPane :tab="TabsPanelNameEnum[TabsPanelEnum.EVENT]" :key="TabsPanelEnum.EVENT"> | 
| 116 | - <BasicEvents /> | 117 | + <BasicEvents :elementInfo="elementInfo" /> | 
| 117 | </Tabs.TabPane> | 118 | </Tabs.TabPane> | 
| 118 | <Tabs.TabPane :tab="TabsPanelNameEnum[TabsPanelEnum.HELP]" :key="TabsPanelEnum.HELP"> | 119 | <Tabs.TabPane :tab="TabsPanelNameEnum[TabsPanelEnum.HELP]" :key="TabsPanelEnum.HELP"> | 
| 119 | <HelpMessage :nodeData="nodeData" /> | 120 | <HelpMessage :nodeData="nodeData" /> |