CrawlerPanel.vue
4.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
<script setup lang="ts">
import { computed } from 'vue'
import SectionHeading from '@/components/common/SectionHeading.vue'
import CrawlerControlForm from '@/components/crawler/CrawlerControlForm.vue'
import CrawlerPlatformStrip from '@/components/crawler/CrawlerPlatformStrip.vue'
import CrawlerStatusDeck from '@/components/crawler/CrawlerStatusDeck.vue'
import type {
CrawlerFlowStep,
CrawlerFormState,
CrawlerLogEntry,
CrawlerOptionsResponse,
CrawlerPlatformState,
CrawlerPrimaryAction,
CrawlerStateResponse,
CrawlerSummaryItem,
} from '@/types'
import { statusTone } from '@/utils/format'
const props = defineProps<{
options: CrawlerOptionsResponse
form: CrawlerFormState
snapshot: CrawlerStateResponse
selectedPlatformState: CrawlerPlatformState | null
availableLoginTypes: CrawlerOptionsResponse['login_types']
availableCrawlerTypes: CrawlerOptionsResponse['crawler_types']
capabilityHint: string
validationIssues: string[]
workflowSteps: CrawlerFlowStep[]
primaryAction: CrawlerPrimaryAction
missionSummary: CrawlerSummaryItem[]
selectedQrCode: string
lastLoginConfig: Record<string, unknown> | null
lastCrawlConfig: Record<string, unknown> | null
canStartLogin: boolean
canStartCrawler: boolean
loading: boolean
acting: boolean
collapsed: boolean
}>()
const emit = defineEmits<{
'update:form': [value: CrawlerFormState]
'update:collapsed': [value: boolean]
checkLogin: []
startLogin: []
cancelLogin: []
startCrawler: []
stopCrawler: []
restoreLastLogin: []
restoreLastCrawl: []
}>()
const visibleLogs = computed<CrawlerLogEntry[]>(() => {
if (props.snapshot.crawler.logs.length > 0) {
return props.snapshot.crawler.logs
}
return props.selectedPlatformState?.logs ?? []
})
</script>
<template>
<section class="panel crawler-shell">
<SectionHeading
kicker="Collection Center"
title="采集中心"
description="把平台登录、采集参数、执行反馈和最近配置串成一条清晰的操作流,让首次使用和重复执行都更顺手。"
>
<template #actions>
<span class="status-chip" :data-tone="statusTone(snapshot.crawler.status)">
{{ snapshot.crawler.message || '空闲' }}
</span>
<el-button plain @click="$emit('update:collapsed', !collapsed)">
{{ collapsed ? '展开采集面板' : '收起采集面板' }}
</el-button>
</template>
</SectionHeading>
<CrawlerPlatformStrip
:platforms="snapshot.login.platforms"
:selected-platform="form.platform"
@select="$emit('update:form', { ...form, platform: $event })"
/>
<div v-show="!collapsed" class="crawler-body">
<CrawlerControlForm
:options="options"
:form="form"
:selected-platform-state="selectedPlatformState"
:available-login-types="availableLoginTypes"
:available-crawler-types="availableCrawlerTypes"
:capability-hint="capabilityHint"
:validation-issues="validationIssues"
:workflow-steps="workflowSteps"
:primary-action="primaryAction"
:last-login-config="lastLoginConfig"
:last-crawl-config="lastCrawlConfig"
:can-start-login="canStartLogin"
:can-start-crawler="canStartCrawler"
:acting="acting"
@update:form="$emit('update:form', $event)"
@check-login="$emit('checkLogin')"
@start-login="$emit('startLogin')"
@cancel-login="$emit('cancelLogin')"
@start-crawler="$emit('startCrawler')"
@stop-crawler="$emit('stopCrawler')"
@restore-last-login="$emit('restoreLastLogin')"
@restore-last-crawl="$emit('restoreLastCrawl')"
/>
<CrawlerStatusDeck
:selected-platform-state="selectedPlatformState"
:capability-hint="capabilityHint"
:snapshot="snapshot"
:validation-issues="validationIssues"
:workflow-steps="workflowSteps"
:primary-action="primaryAction"
:mission-summary="missionSummary"
:selected-qr-code="selectedQrCode"
:loading="loading"
:visible-logs="visibleLogs"
/>
</div>
</section>
</template>
<style scoped>
.crawler-shell {
display: grid;
gap: 22px;
}
.crawler-body {
display: grid;
gap: 18px;
}
</style>