搜索关键字爬虫
This commit is contained in:
@@ -1,20 +1,654 @@
|
||||
<template>
|
||||
<AdminLayout
|
||||
title="资源管理"
|
||||
<AdminLayout
|
||||
title="资源管理"
|
||||
subtitle="管理文章、资源、数据等内容"
|
||||
>
|
||||
<div class="resource-management">
|
||||
<el-empty description="请使用顶部标签页切换到对应的资源管理功能" />
|
||||
<div class="header">
|
||||
<h2>数据采集管理</h2>
|
||||
<div class="header-actions">
|
||||
<el-button type="primary" @click="handleRefresh">
|
||||
<el-icon><Refresh /></el-icon>
|
||||
刷新
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 搜索筛选区域 -->
|
||||
<div class="search-bar">
|
||||
<!-- 任务名称搜索 -->
|
||||
<div class="search-item">
|
||||
<span class="search-label">任务名称</span>
|
||||
<el-input
|
||||
v-model="searchForm.taskName"
|
||||
placeholder="请输入任务名称"
|
||||
clearable
|
||||
style="width: 200px"
|
||||
@keyup.enter="handleSearch"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- 日志批次ID搜索 -->
|
||||
<div class="search-item">
|
||||
<span class="search-label">批次ID</span>
|
||||
<el-input
|
||||
v-model="searchForm.logId"
|
||||
placeholder="请输入批次ID"
|
||||
clearable
|
||||
style="width: 150px"
|
||||
@keyup.enter="handleSearch"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- 标题搜索 -->
|
||||
<div class="search-item">
|
||||
<span class="search-label">标题</span>
|
||||
<el-input
|
||||
v-model="searchForm.title"
|
||||
placeholder="请输入标题"
|
||||
clearable
|
||||
style="width: 200px"
|
||||
@keyup.enter="handleSearch"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- 来源URL搜索 -->
|
||||
<div class="search-item">
|
||||
<span class="search-label">来源URL</span>
|
||||
<el-input
|
||||
v-model="searchForm.sourceUrl"
|
||||
placeholder="请输入URL"
|
||||
clearable
|
||||
style="width: 200px"
|
||||
@keyup.enter="handleSearch"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- 状态筛选 -->
|
||||
<div class="search-item">
|
||||
<span class="search-label">转换状态</span>
|
||||
<el-select
|
||||
v-model="searchForm.status"
|
||||
placeholder="请选择状态"
|
||||
clearable
|
||||
style="width: 120px"
|
||||
>
|
||||
<el-option label="未处理" :value="0" />
|
||||
<el-option label="已转换" :value="1" />
|
||||
<el-option label="已忽略" :value="2" />
|
||||
</el-select>
|
||||
</div>
|
||||
|
||||
<!-- 搜索/重置按钮 -->
|
||||
<div class="search-actions">
|
||||
<el-button type="primary" @click="handleSearch">
|
||||
<el-icon><Search /></el-icon>
|
||||
搜索
|
||||
</el-button>
|
||||
<el-button @click="handleReset">
|
||||
<el-icon><Refresh /></el-icon>
|
||||
重置
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 数据表格 -->
|
||||
<el-table
|
||||
:data="dataList"
|
||||
v-loading="loading"
|
||||
border
|
||||
stripe
|
||||
style="width: 100%"
|
||||
>
|
||||
<!-- 任务名称 -->
|
||||
<el-table-column
|
||||
prop="taskName"
|
||||
label="任务名称"
|
||||
width="150"
|
||||
fixed="left"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
|
||||
<!-- 日志批次ID -->
|
||||
<el-table-column
|
||||
prop="logId"
|
||||
label="批次ID"
|
||||
width="100"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
|
||||
<!-- 来源URL -->
|
||||
<el-table-column label="来源URL" width="200">
|
||||
<template #default="{ row }">
|
||||
<el-link
|
||||
v-if="row.sourceUrl"
|
||||
:href="row.sourceUrl"
|
||||
target="_blank"
|
||||
type="primary"
|
||||
:underline="false"
|
||||
>
|
||||
{{ truncateUrl(row.sourceUrl) }}
|
||||
</el-link>
|
||||
<span v-else>-</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<!-- 爬虫解析结果 -->
|
||||
<el-table-column label="解析结果" width="220">
|
||||
<template #default="{ row }">
|
||||
<div class="parse-result">
|
||||
<div v-if="row.category" class="result-item">
|
||||
<el-tag size="small" type="info">{{ row.category }}</el-tag>
|
||||
</div>
|
||||
<div v-if="row.source" class="result-item">
|
||||
来源: {{ row.source }}
|
||||
</div>
|
||||
<div v-if="row.tags" class="result-item">
|
||||
标签: {{ row.tags }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<!-- 标题 -->
|
||||
<el-table-column
|
||||
prop="title"
|
||||
label="标题"
|
||||
min-width="250"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
|
||||
<!-- 作者 -->
|
||||
<el-table-column
|
||||
prop="author"
|
||||
label="作者"
|
||||
width="100"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
|
||||
<!-- 发布时间 -->
|
||||
<el-table-column label="发布时间" width="160">
|
||||
<template #default="{ row }">
|
||||
{{ formatDateTime(row.publishTime) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<!-- 转换状态 -->
|
||||
<el-table-column label="转换状态" width="100">
|
||||
<template #default="{ row }">
|
||||
<el-tag
|
||||
:type="getStatusTagType(row.status)"
|
||||
size="small"
|
||||
>
|
||||
{{ getStatusText(row.status) }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<!-- 操作列 -->
|
||||
<el-table-column label="操作" width="260" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button
|
||||
type="primary"
|
||||
size="small"
|
||||
@click="handleViewDetail(row)"
|
||||
>
|
||||
查看详情
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="row.status === 0"
|
||||
type="success"
|
||||
size="small"
|
||||
@click="handleConvert(row)"
|
||||
>
|
||||
转换为资源
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<!-- 分页组件 -->
|
||||
<div class="pagination-container" v-if="total > 0">
|
||||
<el-pagination
|
||||
v-model:current-page="pageParam.pageNumber"
|
||||
v-model:page-size="pageParam.pageSize"
|
||||
:page-sizes="[10, 20, 50, 100]"
|
||||
:total="total"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
@size-change="handleSizeChange"
|
||||
@current-change="handlePageChange"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- 详情对话框 -->
|
||||
<el-dialog
|
||||
v-model="detailDialogVisible"
|
||||
title="数据采集详情"
|
||||
width="900px"
|
||||
:close-on-click-modal="false"
|
||||
>
|
||||
<div class="detail-content" v-if="currentItem">
|
||||
<!-- 基本信息区域 -->
|
||||
<el-descriptions title="基本信息" :column="2" border>
|
||||
<el-descriptions-item label="标题" :span="2">
|
||||
{{ currentItem.title }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="作者">
|
||||
{{ currentItem.author || '未知' }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="发布时间">
|
||||
{{ formatDateTime(currentItem.publishTime) }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="来源">
|
||||
{{ currentItem.source || '-' }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="分类">
|
||||
{{ currentItem.category || '-' }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="状态">
|
||||
<el-tag :type="getStatusTagType(currentItem.status)">
|
||||
{{ getStatusText(currentItem.status) }}
|
||||
</el-tag>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="任务名称">
|
||||
{{ currentItem.taskName || '-' }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="来源URL" :span="2">
|
||||
<el-link
|
||||
v-if="currentItem.sourceUrl"
|
||||
:href="currentItem.sourceUrl"
|
||||
target="_blank"
|
||||
type="primary"
|
||||
>
|
||||
{{ currentItem.sourceUrl }}
|
||||
</el-link>
|
||||
<span v-else>-</span>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="标签" :span="2">
|
||||
{{ currentItem.tags || '无' }}
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
|
||||
<!-- 封面图片 -->
|
||||
<div v-if="currentItem.coverImage" class="cover-section">
|
||||
<h4>封面图片</h4>
|
||||
<el-image
|
||||
:src="currentItem.coverImage"
|
||||
fit="cover"
|
||||
style="width: 200px; height: 150px; border-radius: 4px"
|
||||
:preview-src-list="[currentItem.coverImage]"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- 摘要 -->
|
||||
<div v-if="currentItem.summary" class="summary-section">
|
||||
<h4>摘要</h4>
|
||||
<p>{{ currentItem.summary }}</p>
|
||||
</div>
|
||||
|
||||
<!-- 正文内容 - 使用富文本显示 -->
|
||||
<div v-if="currentItem.content" class="content-section">
|
||||
<h4>正文内容</h4>
|
||||
<div class="content-display" v-html="currentItem.content"></div>
|
||||
</div>
|
||||
|
||||
<!-- 转换信息 -->
|
||||
<div v-if="currentItem.status === 1" class="convert-info">
|
||||
<h4>转换信息</h4>
|
||||
<el-descriptions :column="2" border>
|
||||
<el-descriptions-item label="资源ID">
|
||||
{{ currentItem.resourceId || '-' }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="转换时间">
|
||||
{{ formatDateTime(currentItem.processTime) }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="处理人" :span="2">
|
||||
{{ currentItem.processor || '系统' }}
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</div>
|
||||
|
||||
<!-- 错误信息 -->
|
||||
<div v-if="currentItem.status === 2 && currentItem.errorMessage" class="error-info">
|
||||
<h4>错误信息</h4>
|
||||
<el-alert type="error" :closable="false">
|
||||
{{ currentItem.errorMessage }}
|
||||
</el-alert>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<template #footer>
|
||||
<el-button @click="detailDialogVisible = false">关闭</el-button>
|
||||
<el-button
|
||||
v-if="currentItem && currentItem.status === 0"
|
||||
type="success"
|
||||
@click="handleConvertFromDetail"
|
||||
>
|
||||
转换为资源
|
||||
</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 转换对话框 - 使用 ArticleAdd 组件 -->
|
||||
<el-dialog
|
||||
v-model="convertDialogVisible"
|
||||
title="转换为资源"
|
||||
width="90%"
|
||||
:close-on-click-modal="false"
|
||||
:destroy-on-close="true"
|
||||
top="5vh"
|
||||
>
|
||||
<ArticleAdd
|
||||
v-if="convertDialogVisible"
|
||||
:initial-data="convertFormData"
|
||||
:show-back-button="false"
|
||||
@publish-success="handleConvertSuccess"
|
||||
@back="convertDialogVisible = false"
|
||||
/>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</AdminLayout>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, onMounted } from 'vue';
|
||||
import { ElMessage, ElMessageBox } from 'element-plus';
|
||||
import { Search, Refresh } from '@element-plus/icons-vue';
|
||||
import { crontabApi } from '@/apis/crontab';
|
||||
import { ArticleAdd } from '@/views/public/article/components';
|
||||
import type { DataCollectionItem, PageParam, ResourceVO } from '@/types';
|
||||
import { AdminLayout } from '@/views/admin';
|
||||
|
||||
defineOptions({
|
||||
name: 'ResourceManagementView'
|
||||
});
|
||||
|
||||
// ==================== 数据状态 ====================
|
||||
const loading = ref(false);
|
||||
const dataList = ref<DataCollectionItem[]>([]);
|
||||
const total = ref(0);
|
||||
const currentItem = ref<DataCollectionItem | null>(null);
|
||||
const convertItem = ref<DataCollectionItem | null>(null);
|
||||
|
||||
// 转换表单数据
|
||||
const convertFormData = ref<ResourceVO>({
|
||||
resource: {},
|
||||
tags: []
|
||||
});
|
||||
|
||||
// ==================== 搜索表单 ====================
|
||||
const searchForm = reactive({
|
||||
taskName: '',
|
||||
logId: '',
|
||||
title: '',
|
||||
sourceUrl: '',
|
||||
status: undefined as number | undefined
|
||||
});
|
||||
|
||||
// ==================== 分页参数 ====================
|
||||
const pageParam = reactive<PageParam>({
|
||||
pageNumber: 1,
|
||||
pageSize: 20
|
||||
});
|
||||
|
||||
// ==================== 对话框状态 ====================
|
||||
const detailDialogVisible = ref(false);
|
||||
const convertDialogVisible = ref(false);
|
||||
|
||||
// ==================== 数据加载 ====================
|
||||
|
||||
/**
|
||||
* 加载数据采集列表
|
||||
*/
|
||||
async function loadDataList() {
|
||||
loading.value = true;
|
||||
try {
|
||||
const filter: Partial<DataCollectionItem> = {};
|
||||
|
||||
if (searchForm.taskName) filter.taskName = searchForm.taskName;
|
||||
if (searchForm.logId) filter.logId = searchForm.logId;
|
||||
if (searchForm.title) filter.title = searchForm.title;
|
||||
if (searchForm.sourceUrl) filter.sourceUrl = searchForm.sourceUrl;
|
||||
if (searchForm.status !== undefined) filter.status = searchForm.status;
|
||||
|
||||
const result = await crontabApi.getCollectionItemPage(filter, pageParam);
|
||||
|
||||
if (result.success) {
|
||||
if (result.pageDomain) {
|
||||
dataList.value = result.pageDomain.dataList || [];
|
||||
total.value = result.pageDomain.pageParam?.totalElements || 0;
|
||||
} else if (result.dataList) {
|
||||
dataList.value = result.dataList;
|
||||
total.value = result.pageParam?.totalElements || 0;
|
||||
} else {
|
||||
dataList.value = [];
|
||||
total.value = 0;
|
||||
}
|
||||
} else {
|
||||
ElMessage.error(result.message || '加载数据失败');
|
||||
dataList.value = [];
|
||||
total.value = 0;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('加载数据采集列表失败:', error);
|
||||
ElMessage.error('加载数据失败');
|
||||
dataList.value = [];
|
||||
total.value = 0;
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== 搜索操作 ====================
|
||||
|
||||
/**
|
||||
* 搜索
|
||||
*/
|
||||
function handleSearch() {
|
||||
pageParam.pageNumber = 1;
|
||||
loadDataList();
|
||||
}
|
||||
|
||||
/**
|
||||
* 重置搜索
|
||||
*/
|
||||
function handleReset() {
|
||||
searchForm.taskName = '';
|
||||
searchForm.logId = '';
|
||||
searchForm.title = '';
|
||||
searchForm.sourceUrl = '';
|
||||
searchForm.status = undefined;
|
||||
pageParam.pageNumber = 1;
|
||||
loadDataList();
|
||||
}
|
||||
|
||||
/**
|
||||
* 刷新列表
|
||||
*/
|
||||
function handleRefresh() {
|
||||
loadDataList();
|
||||
}
|
||||
|
||||
// ==================== 分页操作 ====================
|
||||
|
||||
/**
|
||||
* 页码变化
|
||||
*/
|
||||
function handlePageChange(page: number) {
|
||||
pageParam.pageNumber = page;
|
||||
loadDataList();
|
||||
}
|
||||
|
||||
/**
|
||||
* 每页数量变化
|
||||
*/
|
||||
function handleSizeChange(size: number) {
|
||||
pageParam.pageSize = size;
|
||||
pageParam.pageNumber = 1;
|
||||
loadDataList();
|
||||
}
|
||||
|
||||
// ==================== 详情查看 ====================
|
||||
|
||||
/**
|
||||
* 查看详情
|
||||
*/
|
||||
function handleViewDetail(row: DataCollectionItem) {
|
||||
currentItem.value = row;
|
||||
detailDialogVisible.value = true;
|
||||
}
|
||||
|
||||
// ==================== 转换操作 ====================
|
||||
|
||||
/**
|
||||
* 处理富文本内容,清理不必要的样式
|
||||
*/
|
||||
function cleanHtmlContent(html: string): string {
|
||||
if (!html) return '';
|
||||
|
||||
// 创建临时DOM元素来处理HTML
|
||||
const tempDiv = document.createElement('div');
|
||||
tempDiv.innerHTML = html;
|
||||
|
||||
// 移除所有内联样式中的字体大小、字体族等可能导致显示问题的样式
|
||||
const elementsWithStyle = tempDiv.querySelectorAll('[style]');
|
||||
elementsWithStyle.forEach((el) => {
|
||||
const element = el as HTMLElement;
|
||||
const style = element.style;
|
||||
|
||||
// 保留一些重要的样式,移除可能冲突的样式
|
||||
const preservedStyles: string[] = [];
|
||||
|
||||
// 保留文本颜色
|
||||
if (style.color) preservedStyles.push(`color: ${style.color}`);
|
||||
// 保留背景色
|
||||
if (style.backgroundColor) preservedStyles.push(`background-color: ${style.backgroundColor}`);
|
||||
// 保留文本对齐
|
||||
if (style.textAlign) preservedStyles.push(`text-align: ${style.textAlign}`);
|
||||
// 保留边距
|
||||
if (style.marginTop) preservedStyles.push(`margin-top: ${style.marginTop}`);
|
||||
if (style.marginBottom) preservedStyles.push(`margin-bottom: ${style.marginBottom}`);
|
||||
|
||||
element.setAttribute('style', preservedStyles.join('; '));
|
||||
});
|
||||
|
||||
// 移除可能的外部类名,避免样式冲突
|
||||
const elementsWithClass = tempDiv.querySelectorAll('[class]');
|
||||
elementsWithClass.forEach((el) => {
|
||||
el.removeAttribute('class');
|
||||
});
|
||||
|
||||
return tempDiv.innerHTML;
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开转换对话框,预填充数据
|
||||
*/
|
||||
function handleConvert(row: DataCollectionItem) {
|
||||
convertItem.value = row;
|
||||
|
||||
// 处理富文本内容,清理样式
|
||||
const cleanedContent = cleanHtmlContent(row.content || '');
|
||||
|
||||
// 预填充文章数据
|
||||
convertFormData.value = {
|
||||
resource: {
|
||||
title: row.title || '',
|
||||
content: cleanedContent,
|
||||
summary: row.summary || '',
|
||||
coverImage: row.coverImage || '',
|
||||
author: row.author || '',
|
||||
source: row.source || '',
|
||||
sourceUrl: row.sourceUrl || '',
|
||||
publishTime: row.publishTime || new Date().toISOString(),
|
||||
status: 1, // 已发布
|
||||
allowComment: true,
|
||||
isTop: false,
|
||||
isRecommend: false
|
||||
},
|
||||
tags: []
|
||||
};
|
||||
|
||||
convertDialogVisible.value = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从详情页转换
|
||||
*/
|
||||
function handleConvertFromDetail() {
|
||||
detailDialogVisible.value = false;
|
||||
handleConvert(currentItem.value!);
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换成功后的回调
|
||||
*/
|
||||
function handleConvertSuccess(resourceId: string) {
|
||||
ElMessage.success('转换成功');
|
||||
convertDialogVisible.value = false;
|
||||
|
||||
// 更新采集项状态为已转换
|
||||
if (convertItem.value?.id) {
|
||||
// 这里可以调用API更新状态,或者直接刷新列表
|
||||
loadDataList();
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== 辅助函数 ====================
|
||||
|
||||
/**
|
||||
* 格式化日期时间
|
||||
*/
|
||||
function formatDateTime(dateTime: string | Date | undefined): string {
|
||||
if (!dateTime) return '-';
|
||||
const date = typeof dateTime === 'string' ? new Date(dateTime) : dateTime;
|
||||
if (isNaN(date.getTime())) return '-';
|
||||
return date.toLocaleString('zh-CN', {
|
||||
year: 'numeric',
|
||||
month: '2-digit',
|
||||
day: '2-digit',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit'
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 截断URL显示
|
||||
*/
|
||||
function truncateUrl(url: string | undefined): string {
|
||||
if (!url) return '-';
|
||||
return url.length > 30 ? url.substring(0, 30) + '...' : url;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取状态文本
|
||||
*/
|
||||
function getStatusText(status: number | undefined): string {
|
||||
switch (status) {
|
||||
case 0: return '未处理';
|
||||
case 1: return '已转换';
|
||||
case 2: return '已忽略';
|
||||
default: return '未知';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取状态标签类型
|
||||
*/
|
||||
function getStatusTagType(status: number | undefined): string {
|
||||
switch (status) {
|
||||
case 0: return 'warning';
|
||||
case 1: return 'success';
|
||||
case 2: return 'info';
|
||||
default: return '';
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== 生命周期 ====================
|
||||
|
||||
onMounted(() => {
|
||||
loadDataList();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@@ -23,8 +657,184 @@ defineOptions({
|
||||
padding: 24px;
|
||||
border-radius: 14px;
|
||||
min-height: 400px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 20px;
|
||||
|
||||
h2 {
|
||||
margin: 0;
|
||||
font-size: 24px;
|
||||
font-weight: 600;
|
||||
color: #141F38;
|
||||
}
|
||||
|
||||
.header-actions {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
.search-bar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16px;
|
||||
margin-bottom: 20px;
|
||||
padding: 20px;
|
||||
background-color: #f8f9fa;
|
||||
border-radius: 8px;
|
||||
flex-wrap: wrap;
|
||||
|
||||
.search-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
|
||||
.search-label {
|
||||
font-size: 14px;
|
||||
color: #606266;
|
||||
white-space: nowrap;
|
||||
min-width: 70px;
|
||||
}
|
||||
}
|
||||
|
||||
.search-actions {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
margin-left: auto;
|
||||
}
|
||||
}
|
||||
|
||||
// 表格内的解析结果
|
||||
.parse-result {
|
||||
.result-item {
|
||||
margin-bottom: 4px;
|
||||
font-size: 12px;
|
||||
color: #606266;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 分页容器
|
||||
.pagination-container {
|
||||
margin-top: 20px;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
// 详情对话框样式
|
||||
.detail-content {
|
||||
max-height: 70vh;
|
||||
// overflow-y: auto;
|
||||
|
||||
h4 {
|
||||
margin: 20px 0 10px 0;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
border-left: 4px solid #409eff;
|
||||
padding-left: 10px;
|
||||
|
||||
&:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.cover-section {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.summary-section {
|
||||
margin-top: 20px;
|
||||
|
||||
p {
|
||||
padding: 12px;
|
||||
background-color: #f5f7fa;
|
||||
border-radius: 4px;
|
||||
line-height: 1.8;
|
||||
color: #606266;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.content-section {
|
||||
margin-top: 20px;
|
||||
|
||||
.content-display {
|
||||
padding: 16px;
|
||||
background-color: #ffffff;
|
||||
border: 1px solid #e4e7ed;
|
||||
border-radius: 4px;
|
||||
line-height: 1.8;
|
||||
color: #303133;
|
||||
max-height: 200px;
|
||||
overflow-y: auto;
|
||||
|
||||
// 富文本内容样式
|
||||
:deep(img) {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
:deep(p) {
|
||||
margin: 8px 0;
|
||||
}
|
||||
|
||||
:deep(h1), :deep(h2), :deep(h3),
|
||||
:deep(h4), :deep(h5), :deep(h6) {
|
||||
margin: 16px 0 8px 0;
|
||||
}
|
||||
|
||||
:deep(a) {
|
||||
color: #409eff;
|
||||
text-decoration: none;
|
||||
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(ul), :deep(ol) {
|
||||
padding-left: 24px;
|
||||
}
|
||||
|
||||
:deep(blockquote) {
|
||||
border-left: 4px solid #dcdfe6;
|
||||
padding-left: 12px;
|
||||
color: #909399;
|
||||
margin: 12px 0;
|
||||
}
|
||||
|
||||
:deep(code) {
|
||||
background-color: #f5f7fa;
|
||||
padding: 2px 6px;
|
||||
border-radius: 3px;
|
||||
font-family: 'Courier New', monospace;
|
||||
}
|
||||
|
||||
:deep(pre) {
|
||||
background-color: #f5f7fa;
|
||||
padding: 12px;
|
||||
border-radius: 4px;
|
||||
overflow-x: auto;
|
||||
|
||||
code {
|
||||
background-color: transparent;
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.convert-info,
|
||||
.error-info {
|
||||
margin-top: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user