From 0022b5ae401809e1612c56221b8e93f321891fe0 Mon Sep 17 00:00:00 2001 From: Marvin Zhang Date: Wed, 21 May 2025 00:03:04 +0800 Subject: [PATCH] feat: add display configuration options and enhance element filtering in AutoProbeResultsPreview component - Introduced showLabel and focusMode options for better control over element display. - Updated page element filtering logic to accommodate new focus mode functionality. - Added translations for new display configuration options in English and Chinese. - Included csstype dependency for improved type management in styles. --- frontend/crawlab-ui/package.json | 1 + frontend/crawlab-ui/pnpm-lock.yaml | 3 + .../autoprobe/AutoProbeResultsPreview.vue | 166 +++++++++++++++--- .../src/i18n/lang/en/components/autoprobe.ts | 11 ++ .../src/i18n/lang/zh/components/autoprobe.ts | 11 ++ .../interfaces/i18n/components/autoprobe.d.ts | 11 ++ .../src/interfaces/models/autoprobe.d.ts | 4 +- .../views/autoprobe/list/useAutoProbeList.tsx | 12 +- 8 files changed, 189 insertions(+), 30 deletions(-) diff --git a/frontend/crawlab-ui/package.json b/frontend/crawlab-ui/package.json index d6f676bd..5ad4e790 100644 --- a/frontend/crawlab-ui/package.json +++ b/frontend/crawlab-ui/package.json @@ -169,6 +169,7 @@ }, "dependencies": { "@types/semver": "^7.5.8", + "csstype": "^3.1.3", "json-editor-vue": "^0.17.0", "semver": "^7.6.3", "uuid": "^10.0.0" diff --git a/frontend/crawlab-ui/pnpm-lock.yaml b/frontend/crawlab-ui/pnpm-lock.yaml index 2ab85446..3eb5de4f 100644 --- a/frontend/crawlab-ui/pnpm-lock.yaml +++ b/frontend/crawlab-ui/pnpm-lock.yaml @@ -101,6 +101,9 @@ importers: cronstrue: specifier: ^2.50.0 version: 2.59.0 + csstype: + specifier: ^3.1.3 + version: 3.1.3 dayjs: specifier: ^1.11.11 version: 1.11.13 diff --git a/frontend/crawlab-ui/src/components/core/autoprobe/AutoProbeResultsPreview.vue b/frontend/crawlab-ui/src/components/core/autoprobe/AutoProbeResultsPreview.vue index 2fa545fa..3f4fe43d 100644 --- a/frontend/crawlab-ui/src/components/core/autoprobe/AutoProbeResultsPreview.vue +++ b/frontend/crawlab-ui/src/components/core/autoprobe/AutoProbeResultsPreview.vue @@ -8,8 +8,9 @@ import { onBeforeUnmount, } from 'vue'; import useRequest from '@/services/request'; -import { getIconByPageElementType } from '@/utils'; +import { getIconByPageElementType, translate } from '@/utils'; import { debounce } from 'lodash'; +import type { Property } from 'csstype'; const props = defineProps<{ activeId: string; @@ -17,6 +18,8 @@ const props = defineProps<{ viewport?: PageViewPort; }>(); +const t = translate; + const { get } = useRequest(); const previewRef = ref(null); @@ -32,6 +35,11 @@ const updateOverlayScale = () => { screenshotScale.value = rect.width / (viewport?.width ?? 1280); }; +const displayConfig = ref({ + showLabel: true, + focusMode: true, +}); + let resizeObserver: ResizeObserver | null = null; onMounted(() => { @@ -105,33 +113,98 @@ const getElementMaskStyle = (el: PageElement): CSSProperties => { const pageElements = computed(() => { const { activeNavItem } = props; - if (!activeNavItem) { - return previewResult.value?.page_elements ?? []; - } + const { focusMode } = displayConfig.value; if (!previewResult.value?.page_elements) { return []; } - if (activeNavItem.type === 'page_pattern') { - return previewResult.value.page_elements; - } else if (activeNavItem.type === 'list') { - const listElement = previewResult.value.page_elements.find( - el => el.name === activeNavItem.name + const fieldElements = previewResult.value.page_elements.filter( + el => el.type === 'field' + ); + const listElements = previewResult.value.page_elements.filter( + el => el.type === 'list' + ); + + // If focus mode is not enabled, return all elements + if (!focusMode) { + const allListItemElements = listElements.flatMap(el => el.children || []); + const allListFieldElements = allListItemElements.flatMap( + el => el.children || [] ); - if (!listElement) { - return []; - } - const itemElements = listElement.children ?? []; - const fieldElements = itemElements.flatMap(el => el.children ?? []); - return [...itemElements, ...fieldElements]; - } else if (activeNavItem.type === 'field') { - return ( - previewResult.value.page_elements.filter( - el => el.name === activeNavItem.name - ) ?? [] - ); - } else { + return [ + ...fieldElements, + ...listElements, + ...allListItemElements, + ...allListFieldElements, + ]; + } + + // If focus mode is enabled, filter elements based on the active navigation item + if (!activeNavItem) { return []; } + switch (activeNavItem.type) { + case 'page_pattern': + return [...fieldElements, ...listElements]; + case 'list': + const listElement = listElements.find( + el => el.name === activeNavItem.name + ); + if (!listElement) { + return []; + } + const listItemElements = listElements.flatMap(el => el.children || []); + const listFieldElements = listItemElements.flatMap( + el => el.children || [] + ); + return [ + { ...listElement, active: true }, + ...listItemElements, + ...listFieldElements, + ]; + case 'field': + // Non-list field + if (activeNavItem.parent?.type === 'page_pattern') { + const fieldElement = fieldElements.find( + el => el.name === activeNavItem.name + ); + if (!fieldElement) { + return []; + } + return [{ ...fieldElement, active: true }]; + } + // List item field + if (activeNavItem.parent?.type === 'list') { + const listElement = listElements.find( + el => el.name === activeNavItem.parent!.name + ); + if (!listElement) { + return []; + } + const listItemElements = listElements.flatMap(el => el.children || []); + const listFieldElements = listItemElements + .flatMap(el => el.children || []) + .filter(el => el.name === activeNavItem.name) + .map(el => ({ ...el, active: true })); + return [...listItemElements, ...listFieldElements]; + } + return []; + case 'pagination': + const paginationElement = previewResult.value.page_elements.find( + el => el.type === 'pagination' && el.name === activeNavItem.name + ); + if (!paginationElement) { + return []; + } + return [{ ...paginationElement, active: true }]; + default: + return []; + } +}); + +const viewportDisplay = computed(() => { + const { viewport } = props; + if (!viewport) return ''; + return `${viewport.width}x${viewport.height}`; }); defineExpose({ @@ -143,16 +216,38 @@ defineOptions({ name: 'ClAutoProbeResultsPreview' });