提交 11c33355 authored 作者: kxjia's avatar kxjia

优化代码

上级 36181925
...@@ -35,9 +35,9 @@ public class CrawlerConfig { ...@@ -35,9 +35,9 @@ public class CrawlerConfig {
private int maxRetries = 3; private int maxRetries = 3;
/** /**
* 超时时间(毫秒) * 超时时间(毫秒),0表示不限制
*/ */
private int timeout = 30000; private int timeout = 0;
/** /**
* 数据源列表 * 数据源列表
...@@ -51,5 +51,7 @@ public class CrawlerConfig { ...@@ -51,5 +51,7 @@ public class CrawlerConfig {
private String baseUrl; private String baseUrl;
private String listUrl; private String listUrl;
private boolean enabled = true; private boolean enabled = true;
private String detailUrl;
private String detailUrlPattern;
} }
} }
...@@ -48,6 +48,18 @@ public class CrawlController { ...@@ -48,6 +48,18 @@ public class CrawlController {
return ResponseEntity.ok(ApiResponse.success(response)); return ResponseEntity.ok(ApiResponse.success(response));
} }
/**
* 停止爬取任务
*/
@PostMapping("/stop")
public ResponseEntity<ApiResponse<Void>> stopCrawl() {
if (!crawlScheduler.isRunning()) {
return ResponseEntity.ok(ApiResponse.error(400, "没有正在执行的爬取任务"));
}
crawlScheduler.stopCrawl();
return ResponseEntity.ok(ApiResponse.success("爬取任务已停止", null));
}
/** /**
* 获取爬取状态 * 获取爬取状态
*/ */
......
...@@ -26,6 +26,7 @@ public class PenaltyRecordDTO { ...@@ -26,6 +26,7 @@ public class PenaltyRecordDTO {
private BigDecimal penaltyAmount; private BigDecimal penaltyAmount;
private LocalDate penaltyDate; private LocalDate penaltyDate;
private String regulator; private String regulator;
private String province;
private String illegalFacts; private String illegalFacts;
private String penaltyBasis; private String penaltyBasis;
private String sourceUrl; private String sourceUrl;
......
...@@ -20,6 +20,7 @@ import java.time.LocalDateTime; ...@@ -20,6 +20,7 @@ import java.time.LocalDateTime;
@Index(name = "idx_penalty_type", columnList = "penaltyType"), @Index(name = "idx_penalty_type", columnList = "penaltyType"),
@Index(name = "idx_penalty_date", columnList = "penaltyDate"), @Index(name = "idx_penalty_date", columnList = "penaltyDate"),
@Index(name = "idx_regulator", columnList = "regulator"), @Index(name = "idx_regulator", columnList = "regulator"),
@Index(name = "idx_province", columnList = "province"),
@Index(name = "idx_is_new", columnList = "isNew"), @Index(name = "idx_is_new", columnList = "isNew"),
@Index(name = "idx_created_at", columnList = "createdAt") @Index(name = "idx_created_at", columnList = "createdAt")
}) })
...@@ -75,6 +76,12 @@ public class PenaltyRecord { ...@@ -75,6 +76,12 @@ public class PenaltyRecord {
@Column(name = "regulator", length = 100) @Column(name = "regulator", length = 100)
private String regulator; private String regulator;
/**
* 省份
*/
@Column(name = "province", length = 50)
private String province;
/** /**
* 违法事实 * 违法事实
*/ */
......
...@@ -94,6 +94,7 @@ public class CrawlScheduler { ...@@ -94,6 +94,7 @@ public class CrawlScheduler {
config.setCode(source.getSourceType()); config.setCode(source.getSourceType());
config.setBaseUrl(source.getSourceUrl()); config.setBaseUrl(source.getSourceUrl());
config.setListUrl(source.getSourceUrl() + (source.getListUrlPattern() != null ? source.getListUrlPattern() : "")); config.setListUrl(source.getSourceUrl() + (source.getListUrlPattern() != null ? source.getListUrlPattern() : ""));
config.setDetailUrlPattern(source.getDetailUrlPattern());
config.setEnabled(source.getIsEnabled()); config.setEnabled(source.getIsEnabled());
return config; return config;
} }
...@@ -156,4 +157,16 @@ public class CrawlScheduler { ...@@ -156,4 +157,16 @@ public class CrawlScheduler {
public boolean isRunning() { public boolean isRunning() {
return isRunning; return isRunning;
} }
/**
* 停止爬取任务
*/
public void stopCrawl() {
if (!isRunning) {
log.warn("没有正在执行的爬取任务");
return;
}
isRunning = false;
log.info("爬取任务已请求停止");
}
} }
...@@ -107,9 +107,6 @@ public class CrawlTaskService { ...@@ -107,9 +107,6 @@ public class CrawlTaskService {
return crawlSourceRepository.findAllByOrderBySortOrder(); return crawlSourceRepository.findAllByOrderBySortOrder();
} }
public List<CrawlSource> getAllSources() {
return crawlSourceRepository.findAll();
}
/** /**
* 获取最新任务状态 * 获取最新任务状态
......
...@@ -243,6 +243,7 @@ public class PenaltyRecordService { ...@@ -243,6 +243,7 @@ public class PenaltyRecordService {
.penaltyAmount(entity.getPenaltyAmount()) .penaltyAmount(entity.getPenaltyAmount())
.penaltyDate(entity.getPenaltyDate()) .penaltyDate(entity.getPenaltyDate())
.regulator(entity.getRegulator()) .regulator(entity.getRegulator())
.province(entity.getProvince())
.illegalFacts(entity.getIllegalFacts()) .illegalFacts(entity.getIllegalFacts())
.penaltyBasis(entity.getPenaltyBasis()) .penaltyBasis(entity.getPenaltyBasis())
.sourceUrl(entity.getSourceUrl()) .sourceUrl(entity.getSourceUrl())
......
server: server:
port: 8080 port: 8082
servlet: servlet:
context-path: /api context-path: /api
...@@ -10,7 +10,7 @@ spring: ...@@ -10,7 +10,7 @@ spring:
datasource: datasource:
url: jdbc:mysql://localhost:3306/penalty_monitor?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false url: jdbc:mysql://localhost:3306/penalty_monitor?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false
username: root username: root
password: 123456 password: ZhongRunChangHong/123
driver-class-name: com.mysql.cj.jdbc.Driver driver-class-name: com.mysql.cj.jdbc.Driver
hikari: hikari:
minimum-idle: 5 minimum-idle: 5
...@@ -38,6 +38,7 @@ spring: ...@@ -38,6 +38,7 @@ spring:
write-dates-as-timestamps: false write-dates-as-timestamps: false
# 爬虫配置(数据源从数据库 crawl_sources 表读取) # 爬虫配置(数据源从数据库 crawl_sources 表读取)
crawler: crawler:
enabled: true enabled: true
cron: "0 0 2 * * ?" cron: "0 0 2 * * ?"
...@@ -47,6 +48,10 @@ crawler: ...@@ -47,6 +48,10 @@ crawler:
resume: resume:
enabled: true # 是否启用断点续传 enabled: true # 是否启用断点续传
force-restart: false # 是否强制重新开始(设为true会忽略之前的进度) force-restart: false # 是否强制重新开始(设为true会忽略之前的进度)
nfra:
page-size: 18
max-pages: 10000
request-interval-ms: 1000
deepseek: deepseek:
api: api:
......
...@@ -38,6 +38,7 @@ spring: ...@@ -38,6 +38,7 @@ spring:
write-dates-as-timestamps: false write-dates-as-timestamps: false
# 爬虫配置(数据源从数据库 crawl_sources 表读取) # 爬虫配置(数据源从数据库 crawl_sources 表读取)
crawler: crawler:
enabled: true enabled: true
cron: "0 0 2 * * ?" cron: "0 0 2 * * ?"
...@@ -47,6 +48,10 @@ crawler: ...@@ -47,6 +48,10 @@ crawler:
resume: resume:
enabled: true # 是否启用断点续传 enabled: true # 是否启用断点续传
force-restart: false # 是否强制重新开始(设为true会忽略之前的进度) force-restart: false # 是否强制重新开始(设为true会忽略之前的进度)
nfra:
page-size: 18
max-pages: 10000
request-interval-ms: 1000
deepseek: deepseek:
api: api:
......
...@@ -46,6 +46,7 @@ D:\new_workspace_06\aispace\financial-penalty-monitor\backend\src\main\java\com\ ...@@ -46,6 +46,7 @@ D:\new_workspace_06\aispace\financial-penalty-monitor\backend\src\main\java\com\
D:\new_workspace_06\aispace\financial-penalty-monitor\backend\src\main\java\com\fintech\penalty\service\ReportTemplateService.java D:\new_workspace_06\aispace\financial-penalty-monitor\backend\src\main\java\com\fintech\penalty\service\ReportTemplateService.java
D:\new_workspace_06\aispace\financial-penalty-monitor\backend\src\main\java\com\fintech\penalty\entity\AnalysisKeyword.java D:\new_workspace_06\aispace\financial-penalty-monitor\backend\src\main\java\com\fintech\penalty\entity\AnalysisKeyword.java
D:\new_workspace_06\aispace\financial-penalty-monitor\backend\src\main\java\com\fintech\penalty\dto\CreateUserRequest.java D:\new_workspace_06\aispace\financial-penalty-monitor\backend\src\main\java\com\fintech\penalty\dto\CreateUserRequest.java
D:\new_workspace_06\aispace\financial-penalty-monitor\backend\src\main\java\com\fintech\penalty\entity\CrawlProgress.java
D:\new_workspace_06\aispace\financial-penalty-monitor\backend\src\main\java\com\fintech\penalty\controller\ReportTemplateController.java D:\new_workspace_06\aispace\financial-penalty-monitor\backend\src\main\java\com\fintech\penalty\controller\ReportTemplateController.java
D:\new_workspace_06\aispace\financial-penalty-monitor\backend\src\main\java\com\fintech\penalty\service\PermissionService.java D:\new_workspace_06\aispace\financial-penalty-monitor\backend\src\main\java\com\fintech\penalty\service\PermissionService.java
D:\new_workspace_06\aispace\financial-penalty-monitor\backend\src\main\java\com\fintech\penalty\dto\CreatePermissionRequest.java D:\new_workspace_06\aispace\financial-penalty-monitor\backend\src\main\java\com\fintech\penalty\dto\CreatePermissionRequest.java
...@@ -72,6 +73,7 @@ D:\new_workspace_06\aispace\financial-penalty-monitor\backend\src\main\java\com\ ...@@ -72,6 +73,7 @@ D:\new_workspace_06\aispace\financial-penalty-monitor\backend\src\main\java\com\
D:\new_workspace_06\aispace\financial-penalty-monitor\backend\src\main\java\com\fintech\penalty\dto\PenaltyRecordDTO.java D:\new_workspace_06\aispace\financial-penalty-monitor\backend\src\main\java\com\fintech\penalty\dto\PenaltyRecordDTO.java
D:\new_workspace_06\aispace\financial-penalty-monitor\backend\src\main\java\com\fintech\penalty\controller\RoleController.java D:\new_workspace_06\aispace\financial-penalty-monitor\backend\src\main\java\com\fintech\penalty\controller\RoleController.java
D:\new_workspace_06\aispace\financial-penalty-monitor\backend\src\main\java\com\fintech\penalty\dto\StatisticsDTO.java D:\new_workspace_06\aispace\financial-penalty-monitor\backend\src\main\java\com\fintech\penalty\dto\StatisticsDTO.java
D:\new_workspace_06\aispace\financial-penalty-monitor\backend\src\main\java\com\fintech\penalty\repository\CrawlProgressRepository.java
D:\new_workspace_06\aispace\financial-penalty-monitor\backend\src\main\java\com\fintech\penalty\dto\UpdatePermissionRequest.java D:\new_workspace_06\aispace\financial-penalty-monitor\backend\src\main\java\com\fintech\penalty\dto\UpdatePermissionRequest.java
D:\new_workspace_06\aispace\financial-penalty-monitor\backend\src\main\java\com\fintech\penalty\scheduler\CrawlScheduler.java D:\new_workspace_06\aispace\financial-penalty-monitor\backend\src\main\java\com\fintech\penalty\scheduler\CrawlScheduler.java
D:\new_workspace_06\aispace\financial-penalty-monitor\backend\src\main\java\com\fintech\penalty\dto\CreateMenuRequest.java D:\new_workspace_06\aispace\financial-penalty-monitor\backend\src\main\java\com\fintech\penalty\dto\CreateMenuRequest.java
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
<link rel="icon" href="/favicon.ico"> <link rel="icon" href="/favicon.ico">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>金融监管处罚监控系统</title> <title>金融监管处罚监控系统</title>
<script type="module" crossorigin src="/assets/index-BM812JBU.js"></script> <script type="module" crossorigin src="/assets/index-D0VsMWb-.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-D_lRsYFa.css"> <link rel="stylesheet" crossorigin href="/assets/index-D_lRsYFa.css">
</head> </head>
<body> <body>
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
"private": true, "private": true,
"scripts": { "scripts": {
"dev": "vite", "dev": "vite",
"build": "vite build", "build": "vite build --mode prod",
"preview": "vite preview" "preview": "vite preview"
}, },
"dependencies": { "dependencies": {
......
...@@ -159,6 +159,7 @@ export default { ...@@ -159,6 +159,7 @@ export default {
// 爬取任务 // 爬取任务
triggerCrawl: () => request.post('/crawl/trigger'), triggerCrawl: () => request.post('/crawl/trigger'),
stopCrawl: () => request.post('/crawl/stop'),
getCrawlStatus: () => request.get('/crawl/status'), getCrawlStatus: () => request.get('/crawl/status'),
getCrawlHistory: (params) => request.get('/crawl/history', { params }), getCrawlHistory: (params) => request.get('/crawl/history', { params }),
clearCrawlHistory: () => request.delete('/crawl/history'), clearCrawlHistory: () => request.delete('/crawl/history'),
......
...@@ -10,6 +10,9 @@ ...@@ -10,6 +10,9 @@
<el-button type="primary" @click="handleTrigger" :loading="loading" :icon="Refresh"> <el-button type="primary" @click="handleTrigger" :loading="loading" :icon="Refresh">
立即爬取 立即爬取
</el-button> </el-button>
<el-button type="danger" @click="handleStop" :loading="stopLoading" :disabled="!isRunning">
停止爬取
</el-button>
</div> </div>
</div> </div>
</template> </template>
...@@ -222,6 +225,8 @@ import api from '../api' ...@@ -222,6 +225,8 @@ import api from '../api'
import dayjs from 'dayjs' import dayjs from 'dayjs'
const loading = ref(false) const loading = ref(false)
const stopLoading = ref(false)
const isRunning = ref(false)
const crawlingSource = ref(null) const crawlingSource = ref(null)
const sources = ref([]) const sources = ref([])
const historyData = ref([]) const historyData = ref([])
...@@ -305,6 +310,7 @@ const fetchSources = async () => { ...@@ -305,6 +310,7 @@ const fetchSources = async () => {
const fetchStatus = async () => { const fetchStatus = async () => {
try { try {
const res = await api.getCrawlStatus() const res = await api.getCrawlStatus()
isRunning.value = res.data.isRunning
const tasks = res.data.tasks || [] const tasks = res.data.tasks || []
taskStatuses.value = {} taskStatuses.value = {}
tasks.forEach(task => { tasks.forEach(task => {
...@@ -358,6 +364,23 @@ const handleTrigger = async () => { ...@@ -358,6 +364,23 @@ const handleTrigger = async () => {
} }
} finally { } finally {
loading.value = false loading.value = false
fetchStatus()
}
}
const handleStop = async () => {
try {
await ElMessageBox.confirm('确定要停止当前爬取任务吗?', '警告', { type: 'warning' })
stopLoading.value = true
await api.stopCrawl()
ElMessage.success('已发送停止请求')
fetchStatus()
} catch (error) {
if (error !== 'cancel') {
ElMessage.error('停止失败')
}
} finally {
stopLoading.value = false
} }
} }
...@@ -540,6 +563,9 @@ onMounted(() => { ...@@ -540,6 +563,9 @@ onMounted(() => {
fetchSources() fetchSources()
fetchStatus() fetchStatus()
fetchHistory() fetchHistory()
setInterval(() => {
fetchStatus()
}, 3000)
}) })
</script> </script>
......
...@@ -66,9 +66,9 @@ ...@@ -66,9 +66,9 @@
<el-table <el-table
:data="tableData" :data="tableData"
v-loading="loading" v-loading="loading"
stripe
@selection-change="handleSelectionChange" @selection-change="handleSelectionChange"
border border="true"
resizable resizable
> >
<el-table-column type="selection" width="55" /> <el-table-column type="selection" width="55" />
...@@ -79,7 +79,7 @@ ...@@ -79,7 +79,7 @@
</el-link> </el-link>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="institutionName" label="机构名称" min-width="200" show-overflow-tooltip resizable /> <el-table-column prop="institutionName" label="机构名称" min-width="100" show-overflow-tooltip resizable />
<el-table-column prop="institutionType" label="机构类型" width="100" resizable> <el-table-column prop="institutionType" label="机构类型" width="100" resizable>
<template #default="{ row }"> <template #default="{ row }">
<el-tag size="small" :type="getTypeColor(row.institutionType)">{{ row.institutionType }}</el-tag> <el-tag size="small" :type="getTypeColor(row.institutionType)">{{ row.institutionType }}</el-tag>
...@@ -93,14 +93,15 @@ ...@@ -93,14 +93,15 @@
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="penaltyDate" label="处罚日期" width="120" resizable /> <el-table-column prop="penaltyDate" label="处罚日期" width="120" resizable />
<el-table-column prop="regulator" label="监管机构" width="120" resizable /> <el-table-column prop="regulator" label="监管机构" width="250" show-overflow-tooltip resizable />
<el-table-column prop="province" label="省份" width="130" resizable />
<el-table-column prop="isNew" label="状态" width="80" resizable> <el-table-column prop="isNew" label="状态" width="80" resizable>
<template #default="{ row }"> <template #default="{ row }">
<el-tag v-if="row.isNew" type="danger" size="small"></el-tag> <el-tag v-if="row.isNew" type="danger" size="small"></el-tag>
<span v-else style="color: #909399">已读</span> <span v-else style="color: #909399">已读</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="分析状态" width="100" resizable> <el-table-column label="分析状态" width="120">
<template #default="{ row }"> <template #default="{ row }">
<el-tag v-if="row.analysisStatus == 'pending'" size="small">待分析</el-tag> <el-tag v-if="row.analysisStatus == 'pending'" size="small">待分析</el-tag>
<el-tag v-else-if="row.analysisStatus == 'analyzing'" type="warning" size="small">分析中</el-tag> <el-tag v-else-if="row.analysisStatus == 'analyzing'" type="warning" size="small">分析中</el-tag>
...@@ -109,7 +110,7 @@ ...@@ -109,7 +110,7 @@
<span v-else>-</span> <span v-else>-</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="操作" width="250" fixed="right"> <el-table-column label="操作" width="230" fixed="right" align="center">
<template #default="{ row }"> <template #default="{ row }">
<el-button type="primary" link @click="viewDetail(row)">详情</el-button> <el-button type="primary" link @click="viewDetail(row)">详情</el-button>
<el-button type="primary" link @click="openReportDrawer(row)">报告</el-button> <el-button type="primary" link @click="openReportDrawer(row)">报告</el-button>
...@@ -142,7 +143,7 @@ ...@@ -142,7 +143,7 @@
</el-card> </el-card>
<!-- 详情弹窗 --> <!-- 详情弹窗 -->
<el-dialog v-model="detailVisible" title="处罚详情" width="825px" :fullscreen="detailFullscreen" show-fullscreen> <el-dialog v-model="detailVisible" title="处罚详情" width="750px" :fullscreen="detailFullscreen" show-fullscreen>
<template #header> <template #header>
<div class="detail-header"> <div class="detail-header">
<span>处罚详情</span> <span>处罚详情</span>
...@@ -151,7 +152,7 @@ ...@@ -151,7 +152,7 @@
</el-button> </el-button>
</div> </div>
</template> </template>
<el-descriptions v-if="currentRecord" :column="2" border> <el-descriptions v-if="currentRecord" :column="2" border label-width="100px">
<el-descriptions-item label="处罚编号" :span="2">{{ currentRecord.penaltyNumber }}</el-descriptions-item> <el-descriptions-item label="处罚编号" :span="2">{{ currentRecord.penaltyNumber }}</el-descriptions-item>
<el-descriptions-item label="被处罚机构" :span="2">{{ currentRecord.institutionName }}</el-descriptions-item> <el-descriptions-item label="被处罚机构" :span="2">{{ currentRecord.institutionName }}</el-descriptions-item>
<el-descriptions-item label="机构类型">{{ currentRecord.institutionType }}</el-descriptions-item> <el-descriptions-item label="机构类型">{{ currentRecord.institutionType }}</el-descriptions-item>
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论