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

优化代码

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