Showing
14 changed files
with
369 additions
and
19 deletions
| 1 | 1 | import type { VueFlowStore, Getters, Elements } from '@vue-flow/core'; | 
| 2 | -import { ComputedRef, ref, unref } from 'vue'; | |
| 2 | +import { ComputedRef, computed, ref, unref } from 'vue'; | |
| 3 | 3 | import { BasicNodeBindData, EdgeData, NodeData } from '../types/node'; | 
| 4 | 4 | import { EntryCategoryComponentEnum } from '../enum/category'; | 
| 5 | 5 | import { useBasicDataTransform } from './useBasicDataTransform'; | 
| ... | ... | @@ -7,6 +7,7 @@ import { getRuleChainData, saveRuleChainData } from '/@/api/ruleDesigner'; | 
| 7 | 7 | import { ConnectionItemType, RuleChainType } from '../types/ruleNode'; | 
| 8 | 8 | import { useInputNode } from './useInputNode'; | 
| 9 | 9 | import { buildUUID } from '/@/utils/uuid'; | 
| 10 | +import { useRoute } from 'vue-router'; | |
| 10 | 11 | |
| 11 | 12 | const ignoreNodeKeys: string[] = [EntryCategoryComponentEnum.INPUT]; | 
| 12 | 13 | |
| ... | ... | @@ -17,6 +18,10 @@ export function useSaveAndRedo() { | 
| 17 | 18 | |
| 18 | 19 | const redoDataRef = ref<Elements>([]); | 
| 19 | 20 | |
| 21 | + const route = useRoute(); | |
| 22 | + | |
| 23 | + const getRuleChainId = computed(() => (route.params as Record<'id', string>).id); | |
| 24 | + | |
| 20 | 25 | const { mergeData, deconstructionData } = useBasicDataTransform(); | 
| 21 | 26 | |
| 22 | 27 | const triggerChange = () => { | 
| ... | ... | @@ -124,7 +129,7 @@ export function useSaveAndRedo() { | 
| 124 | 129 | firstNodeIndex, | 
| 125 | 130 | ruleChainId: { | 
| 126 | 131 | entityType: 'RULE_CHAIN', | 
| 127 | - id: '992ddda0-3d97-11ee-8b46-0dfb0900ab17', | |
| 132 | + id: unref(getRuleChainId), | |
| 128 | 133 | }, | 
| 129 | 134 | }); | 
| 130 | 135 | |
| ... | ... | @@ -140,9 +145,7 @@ export function useSaveAndRedo() { | 
| 140 | 145 | try { | 
| 141 | 146 | loading.value = true; | 
| 142 | 147 | |
| 143 | - const id = '992ddda0-3d97-11ee-8b46-0dfb0900ab17'; | |
| 144 | - | |
| 145 | - const data = await getRuleChainData(id); | |
| 148 | + const data = await getRuleChainData(unref(getRuleChainId)); | |
| 146 | 149 | |
| 147 | 150 | const elements = parseRuleChain(data); | 
| 148 | 151 | ... | ... | 
| ... | ... | @@ -5,7 +5,12 @@ | 
| 5 | 5 | import { Panel, PanelPosition, VueFlow } from '@vue-flow/core'; | 
| 6 | 6 | import { computed, onMounted, Ref, ref, unref } from 'vue'; | 
| 7 | 7 | import './style'; | 
| 8 | - import { BasicConnectionArrow, BasicConnectionLine, BasicEdge, Sidebar } from './src/components'; | |
| 8 | + import { | |
| 9 | + BasicConnectionArrow, | |
| 10 | + BasicConnectionLine, | |
| 11 | + BasicEdge, | |
| 12 | + MenuSidebar, | |
| 13 | + } from './src/components'; | |
| 9 | 14 | import type { FlowElRef } from './types/flow'; | 
| 10 | 15 | import { useDragCreate } from './hook/useDragCreate'; | 
| 11 | 16 | import { createFlowContext } from './hook/useFlowContext'; | 
| ... | ... | @@ -88,7 +93,8 @@ | 
| 88 | 93 | |
| 89 | 94 | <template> | 
| 90 | 95 | <main ref="rootElRef" class="w-full h-full flex relative" @drop="handleOnDrop"> | 
| 91 | - <Sidebar /> | |
| 96 | + <!-- <Sidebar /> --> | |
| 97 | + <MenuSidebar /> | |
| 92 | 98 | |
| 93 | 99 | <Spin :spinning="loading" wrapperClassName="w-full h-ful rule-chain-designer-loading-container"> | 
| 94 | 100 | <VueFlow | ... | ... | 
| 1 | 1 | import { BasicConnectionModalEnum } from '../enum'; | 
| 2 | 2 | import { FetchNodeComFlagTypeENum } from '../enum/node'; | 
| 3 | -import type { CategoryConfigType, NodeItemConfigType } from '../types/node'; | |
| 3 | +import type { NodeItemConfigType } from '../types/node'; | |
| 4 | 4 | import { ActionCategoryConfig, ActionComponents } from './Action'; | 
| 5 | 5 | import { EnrichmentCategoryConfig, EnrichmentComponents } from './Enrichment'; | 
| 6 | 6 | import { ExternalCategoryConfig, ExternalComponents } from './External'; | 
| 7 | 7 | import { FilterCategoryConfig, FilterComponents } from './Filter'; | 
| 8 | 8 | import { FlowCategoryConfig, FlowComponents } from './Flow'; | 
| 9 | 9 | import { TransformationCategoryConfig, TransformationComponents } from './Transformation'; | 
| 10 | -import { RuleNodeTypeEnum } from './index.type'; | |
| 10 | +import { CategoryItemType, RuleNodeTypeEnum } from './index.type'; | |
| 11 | 11 | |
| 12 | 12 | const createModules = import.meta.glob('../packages/**/create.vue'); | 
| 13 | 13 | const connectionModules = import.meta.glob('../packages/**/connection.vue'); | 
| ... | ... | @@ -63,7 +63,7 @@ export const fetchNodeExtraContent = async (config: NodeItemConfigType) => { | 
| 63 | 63 | |
| 64 | 64 | export const allComponents: Record< | 
| 65 | 65 | Exclude<RuleNodeTypeEnum, RuleNodeTypeEnum.ENTRY>, | 
| 66 | - { category: CategoryConfigType; components: NodeItemConfigType[] } | |
| 66 | + CategoryItemType | |
| 67 | 67 | > = { | 
| 68 | 68 | [RuleNodeTypeEnum.FILTER]: { | 
| 69 | 69 | category: FilterCategoryConfig, | ... | ... | 
| 1 | +import { CategoryConfigType, NodeItemConfigType } from '../types/node'; | |
| 2 | + | |
| 1 | 3 | export enum RuleNodeTypeEnum { | 
| 2 | 4 | ENTRY = 'ENTRY', | 
| 3 | 5 | FLOW = 'FLOW', | 
| ... | ... | @@ -7,3 +9,8 @@ export enum RuleNodeTypeEnum { | 
| 7 | 9 | FILTER = 'FILTER', | 
| 8 | 10 | TRANSFORMATION = 'TRANSFORMATION', | 
| 9 | 11 | } | 
| 12 | + | |
| 13 | +export interface CategoryItemType { | |
| 14 | + category: CategoryConfigType; | |
| 15 | + components: NodeItemConfigType[]; | |
| 16 | +} | ... | ... | 
| 1 | +<script lang="ts" setup> | |
| 2 | + import { CategoryItemType, RuleNodeTypeEnum } from '../../../packages/index.type'; | |
| 3 | + import Icon from '/@/components/Icon'; | |
| 4 | + import { Tooltip } from 'ant-design-vue'; | |
| 5 | + | |
| 6 | + const emit = defineEmits<{ | |
| 7 | + (eventName: 'update:activeKey', activeKey?: RuleNodeTypeEnum); | |
| 8 | + }>(); | |
| 9 | + | |
| 10 | + defineProps<{ | |
| 11 | + activeKey?: RuleNodeTypeEnum; | |
| 12 | + category?: CategoryItemType; | |
| 13 | + }>(); | |
| 14 | + | |
| 15 | + const handleClick = (category?: RuleNodeTypeEnum) => { | |
| 16 | + emit('update:activeKey', category); | |
| 17 | + }; | |
| 18 | +</script> | |
| 19 | + | |
| 20 | +<template> | |
| 21 | + <Tooltip color="#fff" placement="right"> | |
| 22 | + <template #title> | |
| 23 | + <p class="text-dark-900 font-bold text-xs m-0 py-1"> | |
| 24 | + {{ category?.category.title }} | |
| 25 | + </p> | |
| 26 | + <p class="text-gray-500 text-xs m-0 py-1"> | |
| 27 | + {{ category?.category.description }} | |
| 28 | + </p> | |
| 29 | + </template> | |
| 30 | + <div | |
| 31 | + class="h-16 mt-2 flex justify-center items-center flex-col cursor-pointer rounded" | |
| 32 | + :class="activeKey === category?.category.category ? 'bg-blue-100 text-blue-400' : ''" | |
| 33 | + @click="handleClick(category?.category.category)" | |
| 34 | + > | |
| 35 | + <Icon :icon="category?.category.icon" class="svg:text-3xl" /> | |
| 36 | + <div class="select-none">{{ category?.category.title }}</div> | |
| 37 | + </div> | |
| 38 | + </Tooltip> | |
| 39 | +</template> | ... | ... | 
| 1 | +<script lang="ts" setup> | |
| 2 | + import { cloneDeep } from 'lodash'; | |
| 3 | + import { computed, ref, unref } from 'vue'; | |
| 4 | + import { allComponents } from '../../../packages'; | |
| 5 | + import { CategoryItemType, RuleNodeTypeEnum } from '../../../packages/index.type'; | |
| 6 | + import CategoryItem from './CategoryItem.vue'; | |
| 7 | + import NodeItem from './NodeItem.vue'; | |
| 8 | + | |
| 9 | + const props = defineProps<{ | |
| 10 | + searchText?: string; | |
| 11 | + }>(); | |
| 12 | + | |
| 13 | + const activeKey = ref<RuleNodeTypeEnum | undefined>(RuleNodeTypeEnum.FILTER); | |
| 14 | + | |
| 15 | + const getCurrentCategoryNode = computed<CategoryItemType>(() => { | |
| 16 | + const category = cloneDeep(allComponents[unref(activeKey)!]) as CategoryItemType; | |
| 17 | + const { searchText } = props; | |
| 18 | + if (searchText) { | |
| 19 | + category.components = category.components.filter((item) => | |
| 20 | + item.name.toUpperCase().includes(searchText.toUpperCase()) | |
| 21 | + ); | |
| 22 | + } | |
| 23 | + return category; | |
| 24 | + }); | |
| 25 | +</script> | |
| 26 | + | |
| 27 | +<template> | |
| 28 | + <section class="absolute top-11 w-full flex flex-auto h-[calc(100%-2.75rem)] bg-neutral-100"> | |
| 29 | + <nav class="w-20 min-w-20 p-2 border-t border-light-50"> | |
| 30 | + <CategoryItem | |
| 31 | + v-for="category in allComponents" | |
| 32 | + :key="category.category.category" | |
| 33 | + v-model:activeKey="activeKey" | |
| 34 | + :category="category" | |
| 35 | + /> | |
| 36 | + </nav> | |
| 37 | + <body class="p-4 w-full flex flex-col gap-2 items-center overflow-x-hidden overflow-y-auto"> | |
| 38 | + <NodeItem | |
| 39 | + v-for="config in getCurrentCategoryNode.components" | |
| 40 | + :key="config.clazz" | |
| 41 | + :config="config" | |
| 42 | + :category="getCurrentCategoryNode.category" | |
| 43 | + /> | |
| 44 | + </body> | |
| 45 | + </section> | |
| 46 | +</template> | ... | ... | 
| 1 | +<script setup lang="ts"> | |
| 2 | + import { Input, Tooltip } from 'ant-design-vue'; | |
| 3 | + import { Icon } from '/@/components/Icon'; | |
| 4 | + | |
| 5 | + const emit = defineEmits(['fold', 'search']); | |
| 6 | + | |
| 7 | + const handleOnFold = () => emit('fold'); | |
| 8 | + | |
| 9 | + const handleInputChange = (event: Event) => { | |
| 10 | + const value = (event.target as HTMLInputElement).value; | |
| 11 | + emit('search', value); | |
| 12 | + }; | |
| 13 | +</script> | |
| 14 | + | |
| 15 | +<template> | |
| 16 | + <head class="h-11 w-full flex justify-between items-center bg-neutral-100"> | |
| 17 | + <Input | |
| 18 | + placeholder="搜索节点" | |
| 19 | + class="!mx-2 flex-auto" | |
| 20 | + @change="handleInputChange" | |
| 21 | + :allowClear="true" | |
| 22 | + > | |
| 23 | + <template #suffix> | |
| 24 | + <Icon icon="material-symbols:search" /> | |
| 25 | + </template> | |
| 26 | + </Input> | |
| 27 | + <div class="w-14 min-w-14 flex justify-center"> | |
| 28 | + <Tooltip title="折叠"> | |
| 29 | + <Icon | |
| 30 | + icon="ant-design:menu-fold-outlined" | |
| 31 | + class="cursor-pointer svg:text-xl" | |
| 32 | + @click="handleOnFold" | |
| 33 | + /> | |
| 34 | + </Tooltip> | |
| 35 | + </div> | |
| 36 | + </head> | |
| 37 | +</template> | ... | ... | 
| 1 | +<script lang="ts" setup> | |
| 2 | + import { Tooltip } from 'ant-design-vue'; | |
| 3 | + import { computed, ref, toRaw, unref } from 'vue'; | |
| 4 | + import { EFFECT_SYMBOL, TRANSFER_DATA_KEY } from '../../../hook/useDragCreate'; | |
| 5 | + import { CategoryConfigType, NodeItemConfigType } from '../../../types/node'; | |
| 6 | + | |
| 7 | + const props = defineProps<{ | |
| 8 | + category?: CategoryConfigType; | |
| 9 | + config?: NodeItemConfigType; | |
| 10 | + }>(); | |
| 11 | + | |
| 12 | + const visible = ref(false); | |
| 13 | + | |
| 14 | + const getNodeDefinition = computed(() => { | |
| 15 | + const { config } = props; | |
| 16 | + const { configurationDescriptor } = config || {}; | |
| 17 | + const { nodeDefinition } = configurationDescriptor || {}; | |
| 18 | + return nodeDefinition || {}; | |
| 19 | + }); | |
| 20 | + | |
| 21 | + const getIcon = computed(() => { | |
| 22 | + const { icon } = unref(getNodeDefinition); | |
| 23 | + const { icon: categoryIcon } = props.category || {}; | |
| 24 | + return icon || categoryIcon || 'tabler:circuit-ground'; | |
| 25 | + }); | |
| 26 | + | |
| 27 | + const getIconUrl = computed(() => { | |
| 28 | + const { iconUrl } = unref(getNodeDefinition); | |
| 29 | + return iconUrl; | |
| 30 | + }); | |
| 31 | + | |
| 32 | + const getBackgroundColor = computed(() => { | |
| 33 | + const { config, category } = props; | |
| 34 | + const { backgroundColor } = config || {}; | |
| 35 | + const { backgroundColor: categoryBackgroundColor } = category || {}; | |
| 36 | + return backgroundColor || categoryBackgroundColor; | |
| 37 | + }); | |
| 38 | + | |
| 39 | + const handleOnDragStart = (event: DragEvent, options: object) => { | |
| 40 | + if (event.dataTransfer) { | |
| 41 | + event.dataTransfer.setData( | |
| 42 | + TRANSFER_DATA_KEY, | |
| 43 | + JSON.stringify({ offsetX: event.offsetX, offsetY: event.offsetY, options }) | |
| 44 | + ); | |
| 45 | + event.dataTransfer.effectAllowed = EFFECT_SYMBOL; | |
| 46 | + } | |
| 47 | + }; | |
| 48 | + | |
| 49 | + const handleDragStart = (event: DragEvent) => { | |
| 50 | + visible.value = false; | |
| 51 | + handleOnDragStart(event, toRaw(unref(props))); | |
| 52 | + }; | |
| 53 | +</script> | |
| 54 | + | |
| 55 | +<template> | |
| 56 | + <Tooltip | |
| 57 | + v-model:visible="visible" | |
| 58 | + placement="right" | |
| 59 | + color="#fff" | |
| 60 | + trigger="hover" | |
| 61 | + :mouse-enter-delay="0.5" | |
| 62 | + overlay-class-name="!max-w-90" | |
| 63 | + > | |
| 64 | + <template #title> | |
| 65 | + <section class="text-dark-900"> | |
| 66 | + <h1 class="font-bold dark:text-dark-50"> | |
| 67 | + {{ config?.name }} | |
| 68 | + </h1> | |
| 69 | + <p class="italic text-gray-600"> | |
| 70 | + {{ getNodeDefinition.description }} | |
| 71 | + </p> | |
| 72 | + <p v-html="getNodeDefinition.details"></p> | |
| 73 | + </section> | |
| 74 | + </template> | |
| 75 | + <main | |
| 76 | + class="node flex items-center cursor-pointer w-44 h-12 min-h-12 rounded border relative px-4 py-2 border-gray-700 z-10" | |
| 77 | + :style="{ backgroundColor: getBackgroundColor }" | |
| 78 | + :draggable="true" | |
| 79 | + @dragstart="handleDragStart" | |
| 80 | + > | |
| 81 | + <div> | |
| 82 | + <img v-if="getIconUrl" class="w-4 h-4" :src="getIconUrl" alt="" /> | |
| 83 | + <Icon v-if="!getIconUrl" class="text-2xl dark:text-light-50" :icon="getIcon" /> | |
| 84 | + </div> | |
| 85 | + <div class="flex flex-1 text-xs flex-col ml-2 text-left truncate"> | |
| 86 | + <span class="text-gray-700 w-full truncate text-xs dark:text-light-50"> | |
| 87 | + {{ config?.name }} | |
| 88 | + </span> | |
| 89 | + </div> | |
| 90 | + <div class="w-4 h-4 bg-dark-50 rounded-1 border absolute -left-2 border-light-50"></div> | |
| 91 | + <div class="w-4 h-4 bg-dark-50 rounded-1 border absolute -right-2 border-light-50"></div> | |
| 92 | + </main> | |
| 93 | + </Tooltip> | |
| 94 | +</template> | |
| 95 | + | |
| 96 | +<style lang="css" scoped> | |
| 97 | + .node::before { | |
| 98 | + content: ''; | |
| 99 | + position: absolute; | |
| 100 | + width: 100%; | |
| 101 | + height: 100%; | |
| 102 | + left: 0; | |
| 103 | + display: none; | |
| 104 | + background-color: #00000027; | |
| 105 | + } | |
| 106 | + | |
| 107 | + .node:hover::before { | |
| 108 | + display: block; | |
| 109 | + } | |
| 110 | +</style> | ... | ... | 
| 1 | +export { default as MenuSidebar } from './index.vue'; | ... | ... | 
| 1 | +<script setup lang="ts"> | |
| 2 | + import NodeFilter from './NodeFilter.vue'; | |
| 3 | + import CategoryPanel from './CategoryPanel.vue'; | |
| 4 | + import { computed, CSSProperties, ref, unref } from 'vue'; | |
| 5 | + import { Icon } from '/@/components/Icon'; | |
| 6 | + import { Tooltip } from 'ant-design-vue'; | |
| 7 | + | |
| 8 | + const expand = ref(true); | |
| 9 | + | |
| 10 | + const searchText = ref(); | |
| 11 | + | |
| 12 | + const handleOnFold = () => { | |
| 13 | + expand.value = false; | |
| 14 | + }; | |
| 15 | + | |
| 16 | + const getSidebarStyle = computed<CSSProperties>(() => { | |
| 17 | + return { | |
| 18 | + flex: `0 0 ${unref(expand) ? '320px' : 0}`, | |
| 19 | + width: unref(expand) ? '320px' : 0, | |
| 20 | + minWidth: unref(expand) ? '320px' : 0, | |
| 21 | + }; | |
| 22 | + }); | |
| 23 | + | |
| 24 | + const handleSearch = (value: string) => { | |
| 25 | + searchText.value = value; | |
| 26 | + }; | |
| 27 | +</script> | |
| 28 | + | |
| 29 | +<template> | |
| 30 | + <section | |
| 31 | + :style="getSidebarStyle" | |
| 32 | + class="h-full shadow shadow-lg relative z-50 shadow-dark-600 overflow-hidden transition-all" | |
| 33 | + > | |
| 34 | + <NodeFilter @fold="handleOnFold" @search="handleSearch" /> | |
| 35 | + <CategoryPanel :searchText="searchText" /> | |
| 36 | + </section> | |
| 37 | + <Tooltip title="展开"> | |
| 38 | + <Icon | |
| 39 | + icon="ant-design:menu-unfold-outlined" | |
| 40 | + class="cursor-pointer svg:text-2xl absolute top-5 left-5 z-40 !flex justify-center items-center w-10 h-10 rounded-1 bg-blue-200 svg:text-light-50 shadow-lg" | |
| 41 | + @click="expand = true" | |
| 42 | + /> | |
| 43 | + </Tooltip> | |
| 44 | +</template> | ... | ... | 
| 1 | +import { h } from 'vue'; | |
| 1 | 2 | import { BasicColumn } from '/@/components/Table'; | 
| 3 | +import { dateUtil } from '/@/utils/dateUtil'; | |
| 4 | +import Icon from '/@/components/Icon'; | |
| 5 | +import { Modal } from 'ant-design-vue'; | |
| 6 | +import { JsonPreview } from '/@/components/CodeEditor'; | |
| 7 | + | |
| 8 | +const handleOpenJsonPreviewModal = (title: string, content: string) => { | |
| 9 | + Modal.info({ | |
| 10 | + title, | |
| 11 | + width: 600, | |
| 12 | + content: h(JsonPreview, { data: JSON.parse(content) }), | |
| 13 | + }); | |
| 14 | +}; | |
| 2 | 15 | |
| 3 | 16 | export const columns: BasicColumn[] = [ | 
| 4 | 17 | { | 
| 5 | 18 | title: '事件时间', | 
| 6 | 19 | dataIndex: 'createdTime', | 
| 20 | + width: 200, | |
| 21 | + format(text) { | |
| 22 | + return dateUtil(text).format('YYYY-MM-DD HH:mm:ss'); | |
| 23 | + }, | |
| 7 | 24 | }, | 
| 8 | 25 | { | 
| 9 | 26 | title: '服务器', | 
| 10 | 27 | dataIndex: 'body.server', | 
| 28 | + ellipsis: true, | |
| 11 | 29 | }, | 
| 12 | 30 | { | 
| 13 | 31 | title: '类型', | 
| 14 | - dataIndex: 'type', | |
| 32 | + dataIndex: 'body.type', | |
| 33 | + ellipsis: true, | |
| 15 | 34 | }, | 
| 16 | 35 | { | 
| 17 | 36 | title: '实体类型', | 
| 18 | - dataIndex: 'entityId.entityType', | |
| 37 | + dataIndex: 'body.entityName', | |
| 38 | + ellipsis: true, | |
| 19 | 39 | }, | 
| 20 | 40 | { | 
| 21 | 41 | title: '消息ID', | 
| 22 | - dataIndex: 'id.id', | |
| 42 | + dataIndex: 'body.entityId', | |
| 43 | + ellipsis: true, | |
| 23 | 44 | }, | 
| 24 | 45 | { | 
| 25 | 46 | title: '消息类型', | 
| 26 | - dataIndex: 'msgtype', | |
| 47 | + dataIndex: 'body.msgType', | |
| 48 | + ellipsis: true, | |
| 27 | 49 | }, | 
| 28 | 50 | { | 
| 29 | 51 | title: '关联类型', | 
| 30 | - dataIndex: 'relatedType', | |
| 52 | + dataIndex: 'body.relationType', | |
| 53 | + ellipsis: true, | |
| 31 | 54 | }, | 
| 32 | 55 | { | 
| 33 | 56 | title: '数据', | 
| 34 | - dataIndex: 'data', | |
| 57 | + dataIndex: 'body.data', | |
| 58 | + ellipsis: true, | |
| 59 | + width: 80, | |
| 60 | + customRender({ text }) { | |
| 61 | + return ( | |
| 62 | + text && | |
| 63 | + h(Icon, { | |
| 64 | + icon: 'material-symbols:more-horiz', | |
| 65 | + class: 'cursor-pointer svg:text-2xl', | |
| 66 | + onClick: () => handleOpenJsonPreviewModal('数据', text), | |
| 67 | + }) | |
| 68 | + ); | |
| 69 | + }, | |
| 35 | 70 | }, | 
| 36 | 71 | { | 
| 37 | 72 | title: '元数据', | 
| 38 | - dataIndex: 'metadaeta', | |
| 73 | + dataIndex: 'body.metadata', | |
| 74 | + ellipsis: true, | |
| 75 | + width: 80, | |
| 76 | + customRender({ text }) { | |
| 77 | + return ( | |
| 78 | + text && | |
| 79 | + h(Icon, { | |
| 80 | + icon: 'material-symbols:more-horiz', | |
| 81 | + class: 'cursor-pointer svg:text-2xl', | |
| 82 | + onClick: () => handleOpenJsonPreviewModal('元数据', text), | |
| 83 | + }) | |
| 84 | + ); | |
| 85 | + }, | |
| 39 | 86 | }, | 
| 40 | 87 | { | 
| 41 | 88 | title: '错误', | 
| 42 | 89 | dataIndex: 'error', | 
| 90 | + width: 80, | |
| 91 | + slots: { | |
| 92 | + customRender: 'error', | |
| 93 | + }, | |
| 43 | 94 | }, | 
| 44 | 95 | ]; | ... | ... | 
| ... | ... | @@ -46,6 +46,8 @@ | 
| 46 | 46 | const result = await getRuleNodeEventList( | 
| 47 | 47 | unref(getNodeId)!, | 
| 48 | 48 | { | 
| 49 | + sortProperty: 'createdTime', | |
| 50 | + sortOrder: 'DESC', | |
| 49 | 51 | page: params.page - 1, | 
| 50 | 52 | pageSize: params.pageSize, | 
| 51 | 53 | tenantId: unref(getTenantId), | 
| ... | ... | @@ -130,6 +132,7 @@ | 
| 130 | 132 | </template> | 
| 131 | 133 | <template #error="{ text }"> | 
| 132 | 134 | <Icon | 
| 135 | + v-if="text" | |
| 133 | 136 | icon="material-symbols:more-horiz" | 
| 134 | 137 | class="cursor-pointer svg:text-2xl" | 
| 135 | 138 | @click="handleOpenDetailModal(text)" | ... | ... | 
| ... | ... | @@ -18,12 +18,14 @@ export const columns: BasicColumn[] = [ | 
| 18 | 18 | }, | 
| 19 | 19 | { | 
| 20 | 20 | title: '消息处理', | 
| 21 | - dataIndex: 'body.event', | |
| 21 | + dataIndex: 'body.messagesProcessed', | |
| 22 | 22 | ellipsis: true, | 
| 23 | + width: 100, | |
| 23 | 24 | }, | 
| 24 | 25 | { | 
| 25 | 26 | title: '错误发生', | 
| 26 | - dataIndex: 'body.event', | |
| 27 | + dataIndex: 'body.errorsOccurred', | |
| 27 | 28 | ellipsis: true, | 
| 29 | + width: 100, | |
| 28 | 30 | }, | 
| 29 | 31 | ]; | ... | ... |