Showing
31 changed files
with
1417 additions
and
189 deletions
| ... | ... | @@ -6,6 +6,7 @@ import { RuleChainType } from '/@/views/rule/designer/types/ruleNode'; |
| 6 | 6 | enum Api { |
| 7 | 7 | SAVE = '/ruleChain/metadata', |
| 8 | 8 | GET_RULE_CHAINES = '/ruleChains', |
| 9 | + GET_RULE_NODE_EVENTS = '/events/RULE_NODE', | |
| 9 | 10 | } |
| 10 | 11 | |
| 11 | 12 | export const getRuleChainData = (id: string) => { |
| ... | ... | @@ -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 | 10 | type: ElementsTypeEnum; |
| 11 | 11 | } |
| 12 | 12 | |
| 13 | +export interface ElementInfo { | |
| 14 | + id: string; | |
| 15 | + type: ElementsTypeEnum; | |
| 16 | +} | |
| 17 | + | |
| 13 | 18 | export function useAwaitPopupWindowBindData( |
| 14 | 19 | options: OptionsType = { mode: DataActionModeEnum.CREATE, type: ElementsTypeEnum.NODE } |
| 15 | 20 | ) { |
| ... | ... | @@ -29,6 +34,8 @@ export function useAwaitPopupWindowBindData( |
| 29 | 34 | |
| 30 | 35 | const shadowComponent = shallowRef<Nullable<Component>>(); |
| 31 | 36 | |
| 37 | + const elementInfo = ref<ElementInfo>(); | |
| 38 | + | |
| 32 | 39 | const getNodeSetValue = computed(() => { |
| 33 | 40 | return unref(mode) === DataActionModeEnum.CREATE |
| 34 | 41 | ? unref(nodeData)?.config?.configurationDescriptor.nodeDefinition.defaultConfiguration |
| ... | ... | @@ -68,8 +75,10 @@ export function useAwaitPopupWindowBindData( |
| 68 | 75 | |
| 69 | 76 | const open = async ( |
| 70 | 77 | nodeData: NodeData, |
| 71 | - edgeData?: EdgeData | |
| 78 | + edgeData?: EdgeData, | |
| 79 | + _elementInfo?: ElementInfo | |
| 72 | 80 | ): Promise<AwaitPopupWindowReturnDataType> => { |
| 81 | + elementInfo.value = _elementInfo; | |
| 73 | 82 | await handleFetchComponent(nodeData, edgeData); |
| 74 | 83 | return new Promise((_resolve) => { |
| 75 | 84 | visible.value = true; |
| ... | ... | @@ -113,6 +122,7 @@ export function useAwaitPopupWindowBindData( |
| 113 | 122 | visible, |
| 114 | 123 | nodeData, |
| 115 | 124 | spinning, |
| 125 | + elementInfo, | |
| 116 | 126 | shadowComponent, |
| 117 | 127 | createComponentEl, |
| 118 | 128 | getComponentKey, | ... | ... |
| ... | ... | @@ -10,7 +10,7 @@ import type { Ref } from 'vue'; |
| 10 | 10 | import { markRaw, toRaw, unref } from 'vue'; |
| 11 | 11 | import { isFunction } from 'lodash-es'; |
| 12 | 12 | import type { CreateNodeModal } from '../src/components/CreateNodeModal'; |
| 13 | -import { EdgeTypeEnum, NodeTypeEnum } from '../enum'; | |
| 13 | +import { EdgeTypeEnum, ElementsTypeEnum, NodeTypeEnum } from '../enum'; | |
| 14 | 14 | import { BasicEdge, BasicNode } from '../src/components'; |
| 15 | 15 | import type { EdgeData, NodeData } from '../types/node'; |
| 16 | 16 | import type { CreateEdgeModal } from '../src/components/CreateEdgeModal'; |
| ... | ... | @@ -126,10 +126,11 @@ export function useRuleFlow(options: UseRuleFlowOptionsType) { |
| 126 | 126 | |
| 127 | 127 | onNodeDoubleClick(async ({ node }) => { |
| 128 | 128 | if ((node.data as NodeData).config?.disableAction) return; |
| 129 | - | |
| 130 | 129 | const { flag, data } = |
| 131 | 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 | 136 | if (!flag) return; |
| ... | ... | @@ -146,7 +147,8 @@ export function useRuleFlow(options: UseRuleFlowOptionsType) { |
| 146 | 147 | const { flag, data } = |
| 147 | 148 | (await unref(updateEdgeDrawerActionType)?.open( |
| 148 | 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 | 154 | if (!flag) return; | ... | ... |
| 1 | 1 | <script setup lang="ts"> |
| 2 | + import { Spin } from 'ant-design-vue'; | |
| 2 | 3 | import { Background, BackgroundVariant } from '@vue-flow/background'; |
| 3 | 4 | import { Controls } from '@vue-flow/controls'; |
| 4 | 5 | import { Panel, PanelPosition, VueFlow } from '@vue-flow/core'; |
| ... | ... | @@ -34,6 +35,7 @@ |
| 34 | 35 | const elements = ref([]); |
| 35 | 36 | |
| 36 | 37 | const { |
| 38 | + loading, | |
| 37 | 39 | changeMarker, |
| 38 | 40 | getCurrentPageMetaData, |
| 39 | 41 | triggerChange, |
| ... | ... | @@ -88,66 +90,68 @@ |
| 88 | 90 | <main ref="rootElRef" class="w-full h-full flex relative" @drop="handleOnDrop"> |
| 89 | 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 | 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 | 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 | 156 | <CreateNodeModal ref="createNodeModalActionType" :get-container="handleGetContainer" /> |
| 153 | 157 | <CreateEdgeModal ref="createEdgeModalActionType" :get-container="handleGetContainer" /> |
| ... | ... | @@ -162,3 +166,11 @@ |
| 162 | 166 | box-shadow: 0 3px 5px -1px #0003, 0 6px 10px 0 #00000024, 0 1px 18px 0 #0000001f; |
| 163 | 167 | } |
| 164 | 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 | import { useConnectionFocus } from '../../../hook/useConnectionFocus'; |
| 7 | 7 | import { useFlowContext } from '../../../hook/useFlowContext'; |
| 8 | 8 | import { useTextWidth } from '../../../hook/useTextWidth'; |
| 9 | + import { ElementsTypeEnum } from '../../../enum'; | |
| 9 | 10 | |
| 10 | 11 | const props = defineProps<EdgeProps>(); |
| 11 | 12 | |
| ... | ... | @@ -31,7 +32,8 @@ |
| 31 | 32 | const { flag, data } = |
| 32 | 33 | (await unref(updateEdgeDrawerActionType)?.open( |
| 33 | 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 | 39 | if (!flag) return; | ... | ... |
| ... | ... | @@ -5,6 +5,7 @@ |
| 5 | 5 | import { computed, toRaw, unref } from 'vue'; |
| 6 | 6 | import { useFlowContext } from '../../../hook/useFlowContext'; |
| 7 | 7 | import type { NodeData } from '../../../types/node'; |
| 8 | + import { ElementsTypeEnum } from '../../../enum'; | |
| 8 | 9 | |
| 9 | 10 | const props = defineProps<NodeProps>(); |
| 10 | 11 | |
| ... | ... | @@ -14,7 +15,10 @@ |
| 14 | 15 | |
| 15 | 16 | const handleOpenEdit = async () => { |
| 16 | 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 | 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 | 9 | import { useForm, BasicForm } from '/@/components/Form'; |
| 10 | 10 | import { BottomFormSchemas, TopFormSchemas } from '../CreateNodeModal/config'; |
| 11 | 11 | import { toRaw, unref } from 'vue'; |
| 12 | - import { BasicEvents } from '../BasicEvents'; | |
| 12 | + import { BasicEvents } from './BasicEvents'; | |
| 13 | 13 | |
| 14 | 14 | const [topFormRegister, topFormActionType] = useForm({ |
| 15 | 15 | schemas: TopFormSchemas, |
| ... | ... | @@ -25,6 +25,7 @@ |
| 25 | 25 | visible, |
| 26 | 26 | spinning, |
| 27 | 27 | nodeData, |
| 28 | + elementInfo, | |
| 28 | 29 | getComponentKey, |
| 29 | 30 | shadowComponent, |
| 30 | 31 | createComponentEl, |
| ... | ... | @@ -113,7 +114,7 @@ |
| 113 | 114 | </Spin> |
| 114 | 115 | </Tabs.TabPane> |
| 115 | 116 | <Tabs.TabPane :tab="TabsPanelNameEnum[TabsPanelEnum.EVENT]" :key="TabsPanelEnum.EVENT"> |
| 116 | - <BasicEvents /> | |
| 117 | + <BasicEvents :elementInfo="elementInfo" /> | |
| 117 | 118 | </Tabs.TabPane> |
| 118 | 119 | <Tabs.TabPane :tab="TabsPanelNameEnum[TabsPanelEnum.HELP]" :key="TabsPanelEnum.HELP"> |
| 119 | 120 | <HelpMessage :nodeData="nodeData" /> | ... | ... |