feat: 适配器解析引擎,用 CSS 选择器从提交的 HTML 中自动提取数据进行校验
This commit is contained in:
@@ -113,6 +113,7 @@
|
||||
<el-tag v-if="r.isValid === true" size="small" type="success">有效</el-tag>
|
||||
<el-tag v-else-if="r.isValid === false" size="small" type="danger">无效</el-tag>
|
||||
<el-button size="small" @click="viewContent(r)">查看</el-button>
|
||||
<el-button size="small" type="primary" :disabled="!selectedConfig" @click="parseResult(r)">解析</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="!expandedUrls.has(page.url) && page.totalCount > 5" style="padding:2px 0;color:#909399;font-size:12px;text-align:center">
|
||||
@@ -145,6 +146,36 @@
|
||||
<el-button v-if="viewingResult.isValid == null" type="danger" size="small" @click="singleValidate(viewingResult.id, false)">无效</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 适配解析结果弹窗 -->
|
||||
<el-dialog v-model="parseVisible" title="适配解析结果" width="850px" :close-on-click-modal="false">
|
||||
<div v-if="parseLoading" style="text-align:center;padding:40px">解析中...</div>
|
||||
<div v-else-if="parseError" style="color:#f56c6c;padding:10px">{{ parseError }}</div>
|
||||
<template v-else>
|
||||
<el-descriptions :column="3" border size="small" style="margin-bottom:12px">
|
||||
<el-descriptions-item label="匹配页面">{{ parseData.pageName || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="提取行数">{{ parseData.rowCount ?? 0 }}</el-descriptions-item>
|
||||
<el-descriptions-item label="字段数">{{ parseData.fieldCount ?? 0 }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
<div v-if="!parseData.matched" style="color:#e6a23c;margin-bottom:8px">
|
||||
未匹配到页面规则。可用页面: {{ (parseData.availablePages || []).join(', ') || '无' }}
|
||||
</div>
|
||||
<el-table v-if="parseData.extracted?.length" :data="parseData.extracted" border stripe size="small" max-height="400">
|
||||
<el-table-column type="index" label="#" width="50" />
|
||||
<el-table-column v-for="col in parseColumns" :key="col" :prop="col" :label="col" min-width="120" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<span :style="scope.row[col] == null ? 'color:#909399' : ''">{{ scope.row[col] ?? 'null' }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div v-else-if="parseData.matched" style="text-align:center;padding:20px;color:#909399">
|
||||
无提取结果(HTML 内容可能不包含匹配元素)
|
||||
</div>
|
||||
</template>
|
||||
<template #footer>
|
||||
<el-button @click="parseVisible = false">关闭</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -175,6 +206,11 @@ const viewingResult = ref({})
|
||||
const viewingContentType = ref('html')
|
||||
const viewingContent = ref('')
|
||||
|
||||
const parseVisible = ref(false)
|
||||
const parseLoading = ref(false)
|
||||
const parseError = ref('')
|
||||
const parseData = ref({})
|
||||
|
||||
const expandedUrls = reactive(new Set())
|
||||
const MAX_VISIBLE = 5
|
||||
|
||||
@@ -322,6 +358,25 @@ const singleValidate = async (id, isValid) => {
|
||||
} catch { ElMessage.error('校验失败') }
|
||||
}
|
||||
|
||||
const parseColumns = computed(() => {
|
||||
if (!parseData.value.extracted?.length) return []
|
||||
return Object.keys(parseData.value.extracted[0])
|
||||
})
|
||||
|
||||
const parseResult = async (row) => {
|
||||
if (!selectedConfig.value) { ElMessage.warning('请先选择适配配置'); return }
|
||||
parseVisible.value = true
|
||||
parseLoading.value = true
|
||||
parseError.value = ''
|
||||
parseData.value = {}
|
||||
try {
|
||||
const r = await api.adapter.parse(selectedConfig.value.id, row.id)
|
||||
parseData.value = r.data || {}
|
||||
} catch (e) {
|
||||
parseError.value = e.response?.data?.message || '解析失败'
|
||||
} finally { parseLoading.value = false }
|
||||
}
|
||||
|
||||
const viewContent = async (row) => {
|
||||
viewingResult.value = { ...row }
|
||||
viewingContentType.value = row.contentType || 'html'
|
||||
|
||||
Reference in New Issue
Block a user