mirror of
https://github.com/crawlab-team/crawlab.git
synced 2026-01-21 17:21:09 +01:00
feat: add viewport selection and run on create options in AutoProbeForm component
This commit is contained in:
@@ -1,7 +1,8 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, onBeforeMount, ref, watch } from 'vue';
|
||||
import { useStore } from 'vuex';
|
||||
import { useAutoProbe } from '@/components';
|
||||
import { translate } from '@/utils';
|
||||
import { getViewPortOptions, translate } from '@/utils';
|
||||
|
||||
// i18n
|
||||
const t = translate;
|
||||
@@ -10,6 +11,33 @@ const t = translate;
|
||||
const store = useStore();
|
||||
const { form, formRef, formRules, isSelectiveForm, isFormItemDisabled } =
|
||||
useAutoProbe(store);
|
||||
|
||||
const viewportOptions = computed<ViewPortSelectOption[]>(() => {
|
||||
return getViewPortOptions();
|
||||
});
|
||||
const viewportValue = ref<ViewPortValue>('pc-normal');
|
||||
const onViewportChange = (value: ViewPortValue) => {
|
||||
if (!form.value) return;
|
||||
const selectedOption = viewportOptions.value.find(
|
||||
option => option.value === value
|
||||
);
|
||||
if (selectedOption) {
|
||||
form.value.viewport = selectedOption.viewport;
|
||||
}
|
||||
};
|
||||
const updateViewPortValue = () => {
|
||||
const selectedOption = viewportOptions.value.find(
|
||||
op =>
|
||||
op.viewport.width === form.value?.viewport?.width &&
|
||||
op.viewport.height === form.value?.viewport?.height
|
||||
);
|
||||
if (selectedOption) {
|
||||
viewportValue.value = selectedOption.value!;
|
||||
}
|
||||
};
|
||||
watch(() => JSON.stringify(form.value?.viewport), updateViewPortValue);
|
||||
onBeforeMount(updateViewPortValue);
|
||||
|
||||
defineOptions({ name: 'ClAutoProbeForm' });
|
||||
</script>
|
||||
|
||||
@@ -45,8 +73,11 @@ defineOptions({ name: 'ClAutoProbeForm' });
|
||||
v-model="form.url"
|
||||
:disabled="isFormItemDisabled('url')"
|
||||
:placeholder="t('components.autoprobe.form.url')"
|
||||
type="textarea"
|
||||
/>
|
||||
>
|
||||
<template #prefix>
|
||||
<cl-icon :icon="['fa', 'at']" />
|
||||
</template>
|
||||
</el-input>
|
||||
</cl-form-item>
|
||||
<cl-form-item
|
||||
:span="4"
|
||||
@@ -56,9 +87,62 @@ defineOptions({ name: 'ClAutoProbeForm' });
|
||||
<el-input
|
||||
v-model="form.query"
|
||||
:disabled="isFormItemDisabled('query')"
|
||||
:placeholder="t('components.autoprobe.form.query')"
|
||||
:placeholder="t('components.autoprobe.form.queryPlaceholder')"
|
||||
type="textarea"
|
||||
/>
|
||||
</cl-form-item>
|
||||
<cl-form-item
|
||||
:span="2"
|
||||
:label="t('components.autoprobe.form.viewport')"
|
||||
prop="viewport"
|
||||
>
|
||||
<el-select
|
||||
v-model="viewportValue"
|
||||
:disabled="isFormItemDisabled('viewport')"
|
||||
:placeholder="t('components.autoprobe.form.viewport')"
|
||||
@change="onViewportChange"
|
||||
>
|
||||
<el-option
|
||||
v-for="op in viewportOptions"
|
||||
:key="op.value"
|
||||
:label="op.label"
|
||||
:value="op.value"
|
||||
/>
|
||||
</el-select>
|
||||
<cl-tag
|
||||
v-if="form.viewport"
|
||||
size="large"
|
||||
:icon="['fa', 'desktop']"
|
||||
:label="`${form.viewport?.width}x${form.viewport?.height}`"
|
||||
>
|
||||
<template #tooltip>
|
||||
<div>
|
||||
<label>{{ t('components.autoprobe.form.viewportWidth') }}: </label>
|
||||
<span
|
||||
>{{ form.viewport?.width }}
|
||||
{{ t('components.autoprobe.form.viewportPx') }}</span
|
||||
>
|
||||
</div>
|
||||
<div>
|
||||
<label>{{ t('components.autoprobe.form.viewportHeight') }}: </label>
|
||||
<span
|
||||
>{{ form.viewport?.height }}
|
||||
{{ t('components.autoprobe.form.viewportPx') }}</span
|
||||
>
|
||||
</div>
|
||||
</template>
|
||||
</cl-tag>
|
||||
</cl-form-item>
|
||||
<cl-form-item
|
||||
:span="2"
|
||||
:label="t('components.autoprobe.form.runOnCreate')"
|
||||
prop="query"
|
||||
>
|
||||
<cl-switch
|
||||
v-model="form.run_on_create"
|
||||
:disabled="isFormItemDisabled('run_on_create')"
|
||||
:placeholder="t('components.autoprobe.form.runOnCreate')"
|
||||
/>
|
||||
</cl-form-item>
|
||||
</cl-form>
|
||||
</template>
|
||||
|
||||
@@ -85,7 +85,7 @@ const tableColumns = computed<TableColumns<AutoProbeNavItem>>(() => {
|
||||
case 'list':
|
||||
const list = row.rule as ListRule;
|
||||
const selectorType = list.item_selector_type;
|
||||
const selector = [list.item_selector, list.list_selector]
|
||||
const selector = [list.list_selector, list.item_selector]
|
||||
.filter(item => item)
|
||||
.join(' > ');
|
||||
return (
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
<script setup lang="tsx">
|
||||
import { computed, CSSProperties, ref } from 'vue';
|
||||
import { computed, ref } from 'vue';
|
||||
import { CellStyle } from 'element-plus';
|
||||
import { ClTag } from '@/components';
|
||||
import { translate, getIconByItemType, getIconByPageElementType } from '@/utils';
|
||||
import { ClTag, ClAutoProbeResultsPreview } from '@/components';
|
||||
import { translate, getIconByItemType } from '@/utils';
|
||||
import { TAB_NAME_RESULTS, TAB_NAME_PREVIEW } from '@/constants';
|
||||
import useRequest from '@/services/request';
|
||||
|
||||
const t = translate;
|
||||
|
||||
@@ -14,6 +13,7 @@ const props = defineProps<{
|
||||
fields?: AutoProbeNavItem[];
|
||||
activeFieldName?: string;
|
||||
url?: string;
|
||||
viewport?: PageViewPort;
|
||||
activeId?: string;
|
||||
}>();
|
||||
|
||||
@@ -22,15 +22,9 @@ const emit = defineEmits<{
|
||||
(e: 'size-change', size: number): void;
|
||||
}>();
|
||||
|
||||
const { get } = useRequest();
|
||||
|
||||
// Refs
|
||||
const resultsContainerRef = ref<HTMLElement | null>(null);
|
||||
const iframeLoading = ref(true);
|
||||
const previewRef = ref<HTMLDivElement | null>(null);
|
||||
const previewLoading = ref(false);
|
||||
const previewResult = ref<PagePreviewResult>();
|
||||
const overlayRef = ref<HTMLDivElement | null>(null);
|
||||
const previewRef = ref<typeof ClAutoProbeResultsPreview | null>(null);
|
||||
|
||||
// States
|
||||
const activeTabName = ref<string | undefined>(TAB_NAME_RESULTS);
|
||||
@@ -97,12 +91,6 @@ const onTabSelect = async (id: string) => {
|
||||
if (!resultsVisible.value) {
|
||||
resultsVisible.value = true;
|
||||
}
|
||||
|
||||
// Reset iframe loading state when switching to preview tab
|
||||
if (id === TAB_NAME_PREVIEW) {
|
||||
iframeLoading.value = true;
|
||||
setTimeout(getPreview, 10);
|
||||
}
|
||||
};
|
||||
|
||||
const toggleResults = () => {
|
||||
@@ -112,45 +100,6 @@ const toggleResults = () => {
|
||||
}
|
||||
};
|
||||
|
||||
const getPreview = async () => {
|
||||
const { activeId } = props;
|
||||
const rect = previewRef.value?.getBoundingClientRect();
|
||||
const viewport: PageViewPort | undefined = rect
|
||||
? {
|
||||
width: rect.width,
|
||||
height: rect.height,
|
||||
}
|
||||
: undefined;
|
||||
previewLoading.value = true;
|
||||
try {
|
||||
const res = await get<any, ResponseWithData<PagePreviewResult>>(
|
||||
`/ai/autoprobes/${activeId}/preview`,
|
||||
{
|
||||
viewport,
|
||||
}
|
||||
);
|
||||
previewResult.value = res.data;
|
||||
} finally {
|
||||
previewLoading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
const overlayScale = computed(() => {
|
||||
const rect = overlayRef.value?.getBoundingClientRect();
|
||||
if (!rect) return 1;
|
||||
return rect.width / 1280; // TODO: Adjust based on the actual viewport size
|
||||
});
|
||||
|
||||
const getElementMaskStyle = (el: PageElement): CSSProperties => {
|
||||
return {
|
||||
position: 'absolute',
|
||||
left: el.coordinates.left * overlayScale.value + 'px',
|
||||
top: el.coordinates.top * overlayScale.value + 'px',
|
||||
width: el.coordinates.width * overlayScale.value + 'px',
|
||||
height: el.coordinates.height * overlayScale.value + 'px',
|
||||
};
|
||||
};
|
||||
|
||||
// Resize handler
|
||||
const heightKey = 'autoprobe.results.containerHeight';
|
||||
const onSizeChange = (size: number) => {
|
||||
@@ -194,44 +143,28 @@ defineOptions({ name: 'ClAutoProbeResultsContainer' });
|
||||
</div>
|
||||
</template>
|
||||
</cl-nav-tabs>
|
||||
<div class="results" v-if="activeTabName === TAB_NAME_RESULTS">
|
||||
<cl-table
|
||||
:key="JSON.stringify(tableColumns)"
|
||||
:columns="tableColumns"
|
||||
:data="tableData"
|
||||
:header-cell-style="tableCellStyle"
|
||||
:cell-style="tableCellStyle"
|
||||
embedded
|
||||
hide-footer
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
v-else-if="activeTabName === TAB_NAME_PREVIEW"
|
||||
ref="previewRef"
|
||||
class="preview"
|
||||
>
|
||||
<!-- <el-skeleton :rows="15" animated v-if="iframeLoading && url" />-->
|
||||
<div v-loading="previewLoading" class="preview-container">
|
||||
<div v-if="previewResult" ref="overlayRef" class="preview-overlay">
|
||||
<img class="screenshot" :src="previewResult.screenshot_base64" />
|
||||
<div
|
||||
v-for="(el, index) in previewResult.page_elements"
|
||||
:key="index"
|
||||
class="element-mask"
|
||||
:style="getElementMaskStyle(el)"
|
||||
>
|
||||
<el-badge type="primary" :badge-style="{ opacity: 0.8 }">
|
||||
<template #content>
|
||||
<span style="margin-right: 5px">
|
||||
<cl-icon :icon="getIconByPageElementType(el.type)" />
|
||||
</span>
|
||||
{{ el.name }}
|
||||
</template>
|
||||
</el-badge>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<template v-if="activeTabName === TAB_NAME_RESULTS">
|
||||
<div class="results">
|
||||
<cl-table
|
||||
:key="JSON.stringify(tableColumns)"
|
||||
:columns="tableColumns"
|
||||
:data="tableData"
|
||||
:header-cell-style="tableCellStyle"
|
||||
:cell-style="tableCellStyle"
|
||||
embedded
|
||||
hide-footer
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else-if="activeTabName === TAB_NAME_PREVIEW">
|
||||
<cl-auto-probe-results-preview
|
||||
v-if="activeId"
|
||||
ref="previewRef"
|
||||
:active-id="activeId"
|
||||
:viewport="viewport"
|
||||
/>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -289,41 +222,5 @@ defineOptions({ name: 'ClAutoProbeResultsContainer' });
|
||||
top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.preview {
|
||||
overflow: hidden;
|
||||
height: calc(100% - 41px);
|
||||
|
||||
.preview-container {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
scrollbar-width: none;
|
||||
|
||||
.preview-overlay {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
z-index: 1;
|
||||
|
||||
img.screenshot {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.element-mask {
|
||||
border: 1px solid var(--el-color-primary-light-5);
|
||||
border-radius: 4px;
|
||||
z-index: 1;
|
||||
|
||||
&:hover {
|
||||
background: rgba(64, 156, 255, 0.2);
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -0,0 +1,180 @@
|
||||
<script setup lang="ts">
|
||||
import {
|
||||
type CSSProperties,
|
||||
onMounted,
|
||||
ref,
|
||||
watch,
|
||||
onBeforeUnmount,
|
||||
} from 'vue';
|
||||
import useRequest from '@/services/request';
|
||||
import { getIconByPageElementType } from '@/utils';
|
||||
import { debounce } from 'lodash';
|
||||
|
||||
const props = defineProps<{
|
||||
activeId: string;
|
||||
viewport?: PageViewPort;
|
||||
}>();
|
||||
|
||||
const { get } = useRequest();
|
||||
|
||||
const previewRef = ref<HTMLDivElement | null>(null);
|
||||
const previewLoading = ref(false);
|
||||
const previewResult = ref<PagePreviewResult>();
|
||||
|
||||
const overlayRef = ref<HTMLDivElement | null>(null);
|
||||
const overlayScale = ref(1);
|
||||
const updateOverlayScale = () => {
|
||||
const { viewport } = props;
|
||||
const rect = overlayRef.value?.getBoundingClientRect();
|
||||
if (!rect) return 1;
|
||||
overlayScale.value = rect.width / (viewport?.width ?? 1280);
|
||||
};
|
||||
|
||||
let resizeObserver: ResizeObserver | null = null;
|
||||
|
||||
onMounted(() => {
|
||||
// Initial calculation if reference is already available
|
||||
if (overlayRef.value) {
|
||||
setupResizeObserver();
|
||||
}
|
||||
|
||||
// Watch for when the reference becomes available
|
||||
watch(overlayRef, newRef => {
|
||||
if (newRef) {
|
||||
setupResizeObserver();
|
||||
}
|
||||
});
|
||||
|
||||
const handle = setInterval(() => {
|
||||
if (!overlayRef.value) return;
|
||||
overlayRef.value.addEventListener('resize', updateOverlayScale);
|
||||
updateOverlayScale();
|
||||
clearInterval(handle);
|
||||
}, 10);
|
||||
return () => {
|
||||
overlayRef.value?.removeEventListener('resize', updateOverlayScale);
|
||||
};
|
||||
});
|
||||
|
||||
const setupResizeObserver = () => {
|
||||
// Clean up existing observer if there is one
|
||||
if (resizeObserver) {
|
||||
resizeObserver.disconnect();
|
||||
}
|
||||
|
||||
resizeObserver = new ResizeObserver(() => {
|
||||
updateOverlayScale();
|
||||
});
|
||||
|
||||
resizeObserver.observe(overlayRef.value!);
|
||||
updateOverlayScale();
|
||||
};
|
||||
|
||||
// Clean up function
|
||||
onBeforeUnmount(() => {
|
||||
if (resizeObserver) {
|
||||
resizeObserver.disconnect();
|
||||
}
|
||||
});
|
||||
|
||||
const getPreview = debounce(async () => {
|
||||
const { activeId } = props;
|
||||
const rect = previewRef.value?.getBoundingClientRect();
|
||||
const viewport: PageViewPort | undefined = rect
|
||||
? {
|
||||
width: rect.width,
|
||||
height: rect.height,
|
||||
}
|
||||
: undefined;
|
||||
previewLoading.value = true;
|
||||
try {
|
||||
const res = await get<any, ResponseWithData<PagePreviewResult>>(
|
||||
`/ai/autoprobes/${activeId}/preview`
|
||||
);
|
||||
previewResult.value = res.data;
|
||||
} finally {
|
||||
previewLoading.value = false;
|
||||
}
|
||||
});
|
||||
onMounted(getPreview);
|
||||
|
||||
const getElementMaskStyle = (el: PageElement): CSSProperties => {
|
||||
return {
|
||||
position: 'absolute',
|
||||
left: el.coordinates.left * overlayScale.value + 'px',
|
||||
top: el.coordinates.top * overlayScale.value + 'px',
|
||||
width: el.coordinates.width * overlayScale.value + 'px',
|
||||
height: el.coordinates.height * overlayScale.value + 'px',
|
||||
};
|
||||
};
|
||||
|
||||
defineExpose({
|
||||
updateOverlayScale,
|
||||
});
|
||||
|
||||
defineOptions({ name: 'ClAutoProbeResultsPreview' });
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div ref="previewRef" class="preview">
|
||||
<div v-loading="previewLoading" class="preview-container">
|
||||
<div v-if="previewResult" ref="overlayRef" class="preview-overlay">
|
||||
<img class="screenshot" :src="previewResult.screenshot_base64" />
|
||||
<div
|
||||
v-for="(el, index) in previewResult.page_elements"
|
||||
:key="index"
|
||||
class="element-mask"
|
||||
:style="getElementMaskStyle(el)"
|
||||
>
|
||||
<el-badge type="primary" :badge-style="{ opacity: 0.8 }">
|
||||
<template #content>
|
||||
<span style="margin-right: 5px">
|
||||
<cl-icon :icon="getIconByPageElementType(el.type)" />
|
||||
</span>
|
||||
{{ el.name }}
|
||||
</template>
|
||||
</el-badge>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.preview {
|
||||
overflow: hidden;
|
||||
height: calc(100% - 41px);
|
||||
|
||||
.preview-container {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
scrollbar-width: none;
|
||||
|
||||
.preview-overlay {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
z-index: 1;
|
||||
|
||||
img.screenshot {
|
||||
width: fit-content;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.element-mask {
|
||||
border: 1px solid var(--el-color-primary-light-5);
|
||||
border-radius: 4px;
|
||||
z-index: 1;
|
||||
|
||||
&:hover {
|
||||
background: rgba(64, 156, 255, 0.2);
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -13,7 +13,12 @@ const useAutoProbe = (store: Store<RootStoreState>) => {
|
||||
const state = store.state[ns];
|
||||
|
||||
// form rules
|
||||
const formRules: FormRules = {};
|
||||
const formRules: FormRules = {
|
||||
url: {
|
||||
pattern: /^https?:\/\/.+/,
|
||||
message: 'URL is not valid (must start with http:// or https://)',
|
||||
},
|
||||
};
|
||||
|
||||
// all autoprobe select options
|
||||
const allAutoProbeSelectOptions = computed<SelectOption[]>(() =>
|
||||
|
||||
@@ -24,6 +24,7 @@ import AutoProbeItemDetail from './core/autoprobe/AutoProbeItemDetail.vue';
|
||||
import AutoProbePagePatternsSidebar from './core/autoprobe/AutoProbePagePatternsSidebar.vue';
|
||||
import AutoProbePatternStats from './core/autoprobe/AutoProbePatternStats.vue';
|
||||
import AutoProbeResultsContainer from './core/autoprobe/AutoProbeResultsContainer.vue';
|
||||
import AutoProbeResultsPreview from './core/autoprobe/AutoProbeResultsPreview.vue';
|
||||
import AutoProbeSelector from './core/autoprobe/AutoProbeSelector.vue';
|
||||
import AutoProbeTaskStatus from './core/autoprobe/AutoProbeTaskStatus.vue';
|
||||
import BlockOptionsDropdownList from './ui/lexical/components/BlockOptionsDropdownList.vue';
|
||||
@@ -279,6 +280,7 @@ export {
|
||||
AutoProbePagePatternsSidebar as ClAutoProbePagePatternsSidebar,
|
||||
AutoProbePatternStats as ClAutoProbePatternStats,
|
||||
AutoProbeResultsContainer as ClAutoProbeResultsContainer,
|
||||
AutoProbeResultsPreview as ClAutoProbeResultsPreview,
|
||||
AutoProbeSelector as ClAutoProbeSelector,
|
||||
AutoProbeTaskStatus as ClAutoProbeTaskStatus,
|
||||
BlockOptionsDropdownList as ClBlockOptionsDropdownList,
|
||||
|
||||
@@ -3,6 +3,20 @@ const autoprobe: LComponentsAutoProbe = {
|
||||
name: 'Name',
|
||||
url: 'URL',
|
||||
query: 'Query',
|
||||
queryPlaceholder:
|
||||
'User instruction query to extract data (default to system prompt only)',
|
||||
runOnCreate: 'Run on Create',
|
||||
viewport: 'Viewport',
|
||||
viewports: {
|
||||
pc: {
|
||||
normal: 'PC (Normal)',
|
||||
wide: 'PC (Wide)',
|
||||
small: 'PC (Small)',
|
||||
},
|
||||
},
|
||||
viewportWidth: 'Viewport Width',
|
||||
viewportHeight: 'Viewport Height',
|
||||
viewportPx: 'px',
|
||||
},
|
||||
task: {
|
||||
status: {
|
||||
|
||||
@@ -3,6 +3,19 @@ const autoprobe: LComponentsAutoProbe = {
|
||||
name: '名称',
|
||||
url: 'URL',
|
||||
query: '查询',
|
||||
queryPlaceholder: '用户指令查询以提取数据 (默认为系统提示)',
|
||||
runOnCreate: '创建时运行',
|
||||
viewport: '视窗大小',
|
||||
viewports: {
|
||||
pc: {
|
||||
normal: 'PC (正常)',
|
||||
wide: 'PC (宽)',
|
||||
small: 'PC (小)',
|
||||
},
|
||||
},
|
||||
viewportWidth: '视窗宽度',
|
||||
viewportHeight: '视窗高度',
|
||||
viewportPx: '像素',
|
||||
},
|
||||
task: {
|
||||
status: {
|
||||
|
||||
@@ -3,6 +3,19 @@ interface LComponentsAutoProbe {
|
||||
name: string;
|
||||
url: string;
|
||||
query: string;
|
||||
queryPlaceholder: string;
|
||||
runOnCreate: string;
|
||||
viewport: string;
|
||||
viewports: {
|
||||
pc: {
|
||||
normal: string;
|
||||
wide: string;
|
||||
small: string;
|
||||
};
|
||||
};
|
||||
viewportWidth: string;
|
||||
viewportHeight: string;
|
||||
viewportPx: string;
|
||||
};
|
||||
task: {
|
||||
status: {
|
||||
|
||||
@@ -6,8 +6,10 @@ export declare global {
|
||||
last_task_id?: string;
|
||||
last_task?: AutoProbeTask;
|
||||
default_task_id?: string;
|
||||
run_on_create?: boolean;
|
||||
page_pattern?: PagePattern;
|
||||
page_data?: PageData;
|
||||
viewport?: PageViewPort;
|
||||
}
|
||||
|
||||
type AutoProbeTaskStatus =
|
||||
@@ -121,4 +123,10 @@ export declare global {
|
||||
screenshot_base64: string;
|
||||
page_elements: PageElement[];
|
||||
}
|
||||
|
||||
type ViewPortValue = 'pc-normal' | 'pc-wide' | 'pc-small';
|
||||
|
||||
interface ViewPortSelectOption extends SelectOption<ViewPortValue> {
|
||||
viewport: PageViewPort;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import {
|
||||
} from '@/constants/tab';
|
||||
import { translate } from '@/utils/i18n';
|
||||
import useRequest from '@/services/request';
|
||||
import { getViewPortOptions } from '@/utils';
|
||||
|
||||
// i18n
|
||||
const t = translate;
|
||||
@@ -19,6 +20,13 @@ const { post } = useRequest();
|
||||
|
||||
const state = {
|
||||
...getDefaultStoreState<AutoProbe>('autoprobe'),
|
||||
newFormFn: () => {
|
||||
return {
|
||||
run_on_create: true,
|
||||
viewport: getViewPortOptions().find(v => v.value === 'pc-normal')
|
||||
?.viewport,
|
||||
};
|
||||
},
|
||||
tabs: [
|
||||
{ id: TAB_NAME_OVERVIEW, title: t('common.tabs.overview') },
|
||||
{ id: TAB_NAME_TASKS, title: t('common.tabs.tasks') },
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
import { translate } from '@/utils';
|
||||
|
||||
const t = translate;
|
||||
|
||||
export const getIconBySelectorType = (selectorType: SelectorType): Icon => {
|
||||
switch (selectorType) {
|
||||
case 'css':
|
||||
@@ -50,4 +54,24 @@ export const getIconByPageElementType = (itemType?: PageElementType): Icon => {
|
||||
default:
|
||||
return ['fa', 'question'];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const getViewPortOptions = () => {
|
||||
return [
|
||||
{
|
||||
label: t('components.autoprobe.form.viewports.pc.normal'),
|
||||
value: 'pc-normal',
|
||||
viewport: { width: 1280, height: 800 },
|
||||
},
|
||||
{
|
||||
label: t('components.autoprobe.form.viewports.pc.wide'),
|
||||
value: 'pc-wide',
|
||||
viewport: { width: 1920, height: 1080 },
|
||||
},
|
||||
{
|
||||
label: t('components.autoprobe.form.viewports.pc.small'),
|
||||
value: 'pc-small',
|
||||
viewport: { width: 1024, height: 768 },
|
||||
},
|
||||
] as ViewPortSelectOption[];
|
||||
};
|
||||
|
||||
@@ -264,6 +264,7 @@ defineOptions({ name: 'ClAutoProbeDetailTabPatterns' });
|
||||
:fields="resultsFields"
|
||||
:active-field-name="resultsActiveField?.name"
|
||||
:url="form.url"
|
||||
:viewport="form.viewport"
|
||||
:active-id="activeId"
|
||||
@size-change="onSizeChange"
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user