Commit da0eda5d by 周田

Merge branch 'yzh' into 'main'

feat:所有代码添加注释

See merge request !38
parents 77efbf7d 2f3169b1
<!-- 表格搜索组件 -->
<template> <template>
<div class="box"> <div class="box">
<div class="left"></div> <div class="left"></div>
......
<!-- 综合数据页面组件 -->
<template> <template>
<div class="text-left p-4 toolbarStyle"> <div class="text-left p-4 toolbarStyle">
<div class="formStyle"> <div class="formStyle">
...@@ -61,6 +62,7 @@ ...@@ -61,6 +62,7 @@
</div> </div>
</div> </div>
<div class="m-t-5" /> <div class="m-t-5" />
<!-- 综合数据表格 -->
<div> <div>
<el-table <el-table
:data="tableData" :data="tableData"
......
...@@ -5,17 +5,11 @@ ...@@ -5,17 +5,11 @@
}}</el-button> }}</el-button>
</div> </div>
<div class="m-t-5" /> <div class="m-t-5" />
<!-- DSN数据表格 -->
<div class="table-content"> <div class="table-content">
<el-table <el-table v-loading="!tableData" element-loading-background="rgba(48, 65, 86, 0.7)" :data="tableData"
v-loading="!tableData" style="width: 100%" border :row-style="{ height: '46px' }" :header-cell-style="{ textAlign: 'center' }"
element-loading-background="rgba(48, 65, 86, 0.7)" :cell-style="{ textAlign: 'center' }">
:data="tableData"
style="width: 100%"
border
:row-style="{ height: '46px' }"
:header-cell-style="{ textAlign: 'center' }"
:cell-style="{ textAlign: 'center' }"
>
<!-- <el-table-column type="selection" width="40" /> --> <!-- <el-table-column type="selection" width="40" /> -->
<el-table-column property="number" label="序号" width="55" type="index" /> <el-table-column property="number" label="序号" width="55" type="index" />
<el-table-column property="name" label="天线名称" show-overflow-tooltip /> <el-table-column property="name" label="天线名称" show-overflow-tooltip />
...@@ -57,6 +51,7 @@ ...@@ -57,6 +51,7 @@
</el-table> </el-table>
</div> </div>
<!-- DSN数据详情对话框 -->
<div class="detailForm"> <div class="detailForm">
<el-dialog v-model="detailVisibleValue" center width="800px" align-center @close="handleClose" draggable> <el-dialog v-model="detailVisibleValue" center width="800px" align-center @close="handleClose" draggable>
<template #header> <template #header>
...@@ -196,7 +191,7 @@ const dataTime = ref(""); ...@@ -196,7 +191,7 @@ const dataTime = ref("");
const recordTime = ref(""); const recordTime = ref("");
// 是否暂停使用 // 是否暂停使用
const isSuspended = ref(""); const isSuspended = ref("");
// dsn数据
interface dsnInfo { interface dsnInfo {
targetName: string; targetName: string;
targetNam: string; targetNam: string;
...@@ -204,7 +199,9 @@ interface dsnInfo { ...@@ -204,7 +199,9 @@ interface dsnInfo {
const dsnInfoDialog = ref<dsnInfo>(); const dsnInfoDialog = ref<dsnInfo>();
// 存放定时器的id // 存放定时器的id
const timerId = ref<number | null>(); const timerId = ref<number | null>();
// 表格数据
const tableData = ref(); const tableData = ref();
// 分页数据
const pageObj = ref({ const pageObj = ref({
total: 10, total: 10,
pageSize: 1, pageSize: 1,
...@@ -212,6 +209,7 @@ const pageObj = ref({ ...@@ -212,6 +209,7 @@ const pageObj = ref({
}); });
// 查看数据详情的方法 // 查看数据详情的方法
const handleDetails = (row: any) => { const handleDetails = (row: any) => {
// 将表格中对应行的数据赋值给上面定义的变量
targetName.value = row.targets[0].name; targetName.value = row.targets[0].name;
windSpeed.value = row.windSpeed === "" ? "--" : row.windSpeed; windSpeed.value = row.windSpeed === "" ? "--" : row.windSpeed;
antennaName.value = row.name; antennaName.value = row.name;
...@@ -234,6 +232,7 @@ const handleDetails = (row: any) => { ...@@ -234,6 +232,7 @@ const handleDetails = (row: any) => {
const getData = async () => { const getData = async () => {
const res = await getDsnList({ page: pageObj.value.pageNo, size: pageObj.value.pageSize }); const res = await getDsnList({ page: pageObj.value.pageNo, size: pageObj.value.pageSize });
let dishesData = []; let dishesData = [];
// 构造表格数据,dsn数据的结构比较特殊,需要遍历两层才能得到每一行的数据
for (let i = 0; i < res.data.list[0].stations.length; i++) { for (let i = 0; i < res.data.list[0].stations.length; i++) {
for (let j = 0; j < res.data.list[0].stations[i].dishes.length; j++) { for (let j = 0; j < res.data.list[0].stations[i].dishes.length; j++) {
dishesData.push(res.data.list[0].stations[i].dishes[j]); dishesData.push(res.data.list[0].stations[i].dishes[j]);
...@@ -243,6 +242,7 @@ const getData = async () => { ...@@ -243,6 +242,7 @@ const getData = async () => {
tableData.value = dishesData; tableData.value = dishesData;
console.log(tableData.value); console.log(tableData.value);
}; };
// 关闭详情对话框的方法
const handleClose = () => { const handleClose = () => {
detailVisibleValue.value = false; detailVisibleValue.value = false;
}; };
...@@ -262,6 +262,7 @@ const handleRefresh = () => { ...@@ -262,6 +262,7 @@ const handleRefresh = () => {
timerId.value = setInterval(async () => { timerId.value = setInterval(async () => {
const res = await getDsnList({ page: pageObj.value.pageNo, size: pageObj.value.pageSize }); const res = await getDsnList({ page: pageObj.value.pageNo, size: pageObj.value.pageSize });
let dishesData = []; let dishesData = [];
// 构造表格数据,dsn数据的结构比较特殊,需要遍历两层才能得到每一行的数据
for (let i = 0; i < res.data.list[0].stations.length; i++) { for (let i = 0; i < res.data.list[0].stations.length; i++) {
for (let j = 0; j < res.data.list[0].stations[i].dishes.length; j++) { for (let j = 0; j < res.data.list[0].stations[i].dishes.length; j++) {
dishesData.push(res.data.list[0].stations[i].dishes[j]); dishesData.push(res.data.list[0].stations[i].dishes[j]);
......
...@@ -13,8 +13,9 @@ ...@@ -13,8 +13,9 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref } from 'vue' import { ref } from 'vue'
import dsnDataTab from './dsnDataTab.vue' import dsnDataTab from './dsnDataTab.vue'
import newsDataTab from './newsDataTab.vue' // import newsDataTab from './newsDataTab.vue'
// 定义模式和选项
const mode = ref('DSN数据') const mode = ref('DSN数据')
const sizeOptions = ['DSN数据', '新闻'] const sizeOptions = ['DSN数据', '新闻']
......
...@@ -129,6 +129,7 @@ const newsDate = ref('') ...@@ -129,6 +129,7 @@ const newsDate = ref('')
const newsGetTime = ref('') const newsGetTime = ref('')
// 新闻内容 // 新闻内容
const newsContent = ref('') const newsContent = ref('')
// 表格数据
const tableData = ref([ const tableData = ref([
{ {
number: '1', number: '1',
...@@ -165,11 +166,13 @@ const tableData = ref([ ...@@ -165,11 +166,13 @@ const tableData = ref([
name: '1', name: '1',
}, },
]) ])
// 分页数据
const pageObj = ref({ const pageObj = ref({
total: 10, total: 10,
pageSize: 10, pageSize: 10,
pageNo: 1 pageNo: 1
}) })
// 查看详情的方法
const handleDetails = (row: any) => { const handleDetails = (row: any) => {
console.log(row); console.log(row);
detailVisibleValue.value = true detailVisibleValue.value = true
......
<template> <template>
<div class="text-left"> <div class="text-left">
<!-- 搜索工具栏 -->
<table-search> <table-search>
<div class="form-content"> <div class="form-content">
<div class="left"> <div class="left">
...@@ -14,17 +15,9 @@ ...@@ -14,17 +15,9 @@
<div> <div>
<span style="color: white">采集时间:</span> <span style="color: white">采集时间:</span>
<el-config-provider :locale="zhCn"> <el-config-provider :locale="zhCn">
<el-date-picker <el-date-picker type="datetimerange" format="YYYY-MM-DD HH:mm:ss" v-model="searchTimeValue"
type="datetimerange" start-placeholder="开始时间" style="width: 400px" end-placeholder="结束时间" date-format="YYYY/MM/DD ddd"
format="YYYY-MM-DD HH:mm:ss" time-format="A hh:mm:ss" value-format="YYYY-MM-DD HH:mm:ss" />
v-model="searchTimeValue"
start-placeholder="开始时间"
style="width: 400px"
end-placeholder="结束时间"
date-format="YYYY/MM/DD ddd"
time-format="A hh:mm:ss"
value-format="YYYY-MM-DD HH:mm:ss"
/>
</el-config-provider> </el-config-provider>
</div> </div>
</div> </div>
...@@ -36,18 +29,12 @@ ...@@ -36,18 +29,12 @@
</table-search> </table-search>
</div> </div>
<!-- ESA数据表格 -->
<div class="m-t-5" /> <div class="m-t-5" />
<div class="table-content"> <div class="table-content">
<el-table <el-table :data="tableData" style="width: 100%" border :row-style="{ height: '45.5px' }"
:data="tableData" :header-cell-style="{ textAlign: 'center' }" :cell-style="{ textAlign: 'center' }" v-loading="tableLoading"
style="width: 100%" element-loading-background="rgba(48, 65, 86, 0.7)">
border
:row-style="{ height: '45.5px' }"
:header-cell-style="{ textAlign: 'center' }"
:cell-style="{ textAlign: 'center' }"
v-loading="tableLoading"
element-loading-background="rgba(48, 65, 86, 0.7)"
>
<el-table-column property="number" label="序号" width="55" type="index" /> <el-table-column property="number" label="序号" width="55" type="index" />
<el-table-column property="data.mission" label="目标名称" width="86" show-overflow-tooltip /> <el-table-column property="data.mission" label="目标名称" width="86" show-overflow-tooltip />
<el-table-column property="data.station" label="站点名称" width="88" show-overflow-tooltip /> <el-table-column property="data.station" label="站点名称" width="88" show-overflow-tooltip />
...@@ -93,23 +80,19 @@ ...@@ -93,23 +80,19 @@
<el-button link type="primary" size="small" @click="handleMissionDetails(scope.row.data.mission)"> <el-button link type="primary" size="small" @click="handleMissionDetails(scope.row.data.mission)">
目标信息 目标信息
</el-button> </el-button>
<el-button link type="primary" size="small" @click="handleStationDetails(scope.row.data.station)" <el-button link type="primary" size="small"
>站点信息</el-button @click="handleStationDetails(scope.row.data.station)">站点信息</el-button>
>
</div> </div>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
<div class="pagination w-full flex flex-row-reverse pr-4 m-t-4"> <div class="pagination w-full flex flex-row-reverse pr-4 m-t-4">
<Pagination <Pagination :total="pageObj.total" v-model:page="pageObj.pageNo" v-model:limit="pageObj.pageSize"
:total="pageObj.total" @pagination="getData" />
v-model:page="pageObj.pageNo"
v-model:limit="pageObj.pageSize"
@pagination="getData"
/>
</div> </div>
</div> </div>
<!-- ESA目标详情弹窗 -->
<div class="detailForm"> <div class="detailForm">
<el-dialog v-model="detailVisibleValue" center width="765px" align-center @close="handleClose" draggable> <el-dialog v-model="detailVisibleValue" center width="765px" align-center @close="handleClose" draggable>
<template #header> <template #header>
...@@ -117,6 +100,7 @@ ...@@ -117,6 +100,7 @@
</template> </template>
<el-row> <el-row>
<el-col> <el-col>
<!-- 目标详情的表单 -->
<el-card> <el-card>
<div class="title">目标信息:</div> <div class="title">目标信息:</div>
<el-divider style="margin: 0"></el-divider> <el-divider style="margin: 0"></el-divider>
...@@ -207,6 +191,7 @@ ...@@ -207,6 +191,7 @@
</el-dialog> </el-dialog>
</div> </div>
<!-- ESA站点详情弹窗 -->
<div class="detailForm"> <div class="detailForm">
<el-dialog v-model="stationVisibleValue" center width="880px" align-center @close="handleClose" draggable> <el-dialog v-model="stationVisibleValue" center width="880px" align-center @close="handleClose" draggable>
<template #header> <template #header>
...@@ -214,6 +199,7 @@ ...@@ -214,6 +199,7 @@
</template> </template>
<el-row> <el-row>
<el-col> <el-col>
<!-- 站点详情的表单 -->
<el-card> <el-card>
<div class="title">站点信息:</div> <div class="title">站点信息:</div>
<el-divider style="margin: 0"></el-divider> <el-divider style="margin: 0"></el-divider>
...@@ -343,6 +329,7 @@ ...@@ -343,6 +329,7 @@
</el-row> </el-row>
</el-dialog> </el-dialog>
</div> </div>
<!-- 导出组件 -->
<exportDialog v-model:dialogVisible="showDeleteDialog" /> <exportDialog v-model:dialogVisible="showDeleteDialog" />
</template> </template>
...@@ -367,6 +354,7 @@ zhCn.el.pagination.pageClassifier = '页' ...@@ -367,6 +354,7 @@ zhCn.el.pagination.pageClassifier = '页'
const searchTargetName = ref('') const searchTargetName = ref('')
const searchTimeValue = ref('') const searchTimeValue = ref('')
const searchStation = ref('') const searchStation = ref('')
// 删除的ref
const showDeleteDialog = ref(false) const showDeleteDialog = ref(false)
const detailVisibleValue = ref(false) const detailVisibleValue = ref(false)
const stationVisibleValue = ref(false) const stationVisibleValue = ref(false)
...@@ -566,16 +554,21 @@ const handleStationDetails = async (id: any) => { ...@@ -566,16 +554,21 @@ const handleStationDetails = async (id: any) => {
} }
} }
// 表格数据
const tableData = ref([]) const tableData = ref([])
// 分页对象
const pageObj = ref({ const pageObj = ref({
total: 0, total: 0,
pageSize: 10, pageSize: 10,
pageNo: 1 pageNo: 1
}) })
// 时间戳格式化函数
const formatTimestamp = (timestamp: any) => { const formatTimestamp = (timestamp: any) => {
// 判断时间戳是否有效
if (!timestamp || typeof timestamp !== 'number' || timestamp <= 0) { if (!timestamp || typeof timestamp !== 'number' || timestamp <= 0) {
return '--' return '--'
} }
// 处理10位和13位时间戳
const msTimestamp = String(timestamp).length === 10 ? timestamp * 1000 : timestamp const msTimestamp = String(timestamp).length === 10 ? timestamp * 1000 : timestamp
const date = new Date(msTimestamp) const date = new Date(msTimestamp)
if (isNaN(date.getTime())) { if (isNaN(date.getTime())) {
...@@ -613,6 +606,7 @@ const handleMissionDetails = async (id: any) => { ...@@ -613,6 +606,7 @@ const handleMissionDetails = async (id: any) => {
targetIsCoreMission.value = res.data.data[0].coreMission targetIsCoreMission.value = res.data.data[0].coreMission
targetSolarWindSpeed.value = res.data.data[0].solarWindSpeed targetSolarWindSpeed.value = res.data.data[0].solarWindSpeed
targetSolarFluxDensity.value = res.data.data[0].solarFluxDensity targetSolarFluxDensity.value = res.data.data[0].solarFluxDensity
// 遍历后将数据取出来
for (let i = 0; i < res.data.data[0].description.length; i++) { for (let i = 0; i < res.data.data[0].description.length; i++) {
targetDescription.value += res.data.data[0].description[i] targetDescription.value += res.data.data[0].description[i]
} }
...@@ -631,6 +625,7 @@ const resetForm = () => { ...@@ -631,6 +625,7 @@ const resetForm = () => {
// 获取esa数据列表的方法 // 获取esa数据列表的方法
const getData = async () => { const getData = async () => {
tableLoading.value = true tableLoading.value = true
// 请求数据
const res = await getESAList({ const res = await getESAList({
spacecraft: searchTargetName.value, spacecraft: searchTargetName.value,
station: searchStation.value, station: searchStation.value,
...@@ -642,10 +637,11 @@ const getData = async () => { ...@@ -642,10 +637,11 @@ const getData = async () => {
tableData.value = res.data.list tableData.value = res.data.list
tableLoading.value = false tableLoading.value = false
} }
// 关闭弹窗的方法
const handleClose = () => { const handleClose = () => {
detailVisibleValue.value = false detailVisibleValue.value = false
} }
// 组件挂载时获取数据
onMounted(() => { onMounted(() => {
getData() getData()
}) })
...@@ -655,6 +651,7 @@ onMounted(() => { ...@@ -655,6 +651,7 @@ onMounted(() => {
:deep(.el-form-item__label) { :deep(.el-form-item__label) {
color: white; color: white;
} }
// 调整表单项间距 // 调整表单项间距
.detailForm { .detailForm {
.el-dialog-title { .el-dialog-title {
...@@ -723,6 +720,7 @@ onMounted(() => { ...@@ -723,6 +720,7 @@ onMounted(() => {
padding: 0 30px; padding: 0 30px;
justify-content: space-between; justify-content: space-between;
} }
.left { .left {
display: flex; display: flex;
gap: 10px; gap: 10px;
......
<template> <template>
<div> <div>
<!-- 导出记录的弹窗 -->
<el-dialog title="导出记录" v-model="dialogVisible" width="65%"> <el-dialog title="导出记录" v-model="dialogVisible" width="65%">
<div class="table-content"> <div class="table-content">
<el-table <!-- 导出条件的表单 -->
v-loading="tableLoading" <el-table v-loading="tableLoading" element-loading-background="rgba(48, 65, 86, 0.7)"
element-loading-background="rgba(48, 65, 86, 0.7)" :row-style="{ height: '45px' }" :header-cell-style="{ textAlign: 'center' }"
:row-style="{ height: '45px' }" :cell-style="{ textAlign: 'center' }" :data="exportRecordList" border>
:header-cell-style="{ textAlign: 'center' }"
:cell-style="{ textAlign: 'center' }"
:data="exportRecordList"
border
>
<el-table-column type="index" label="序号" width="60"></el-table-column> <el-table-column type="index" label="序号" width="60"></el-table-column>
<el-table-column prop="begin_export_time" label="导出开始时间"></el-table-column> <el-table-column prop="begin_export_time" label="导出开始时间"></el-table-column>
<el-table-column prop="end_export_time" label="导出结束时间"></el-table-column> <el-table-column prop="end_export_time" label="导出结束时间"></el-table-column>
...@@ -25,12 +21,8 @@ ...@@ -25,12 +21,8 @@
<el-table-column prop="create_time" label="记录时间"></el-table-column> <el-table-column prop="create_time" label="记录时间"></el-table-column>
</el-table> </el-table>
<div class="flex justify-end mt-2"> <div class="flex justify-end mt-2">
<el-pagination <el-pagination @current-change="handleCurrentChange" background layout="total, prev, pager, next"
@current-change="handleCurrentChange" :total="pagination.total" />
background
layout="total, prev, pager, next"
:total="pagination.total"
/>
</div> </div>
</div> </div>
</el-dialog> </el-dialog>
...@@ -43,11 +35,13 @@ import { reactive, ref } from "vue"; ...@@ -43,11 +35,13 @@ import { reactive, ref } from "vue";
const dialogVisible = ref(false); const dialogVisible = ref(false);
// 打开弹窗的方法,并获取数据
const openDialog = () => { const openDialog = () => {
dialogVisible.value = true; dialogVisible.value = true;
getData(); getData();
}; };
// 组件暴露的方法
defineExpose({ defineExpose({
openDialog, openDialog,
}); });
...@@ -82,6 +76,7 @@ const getDataSourceName = (code: number) => { ...@@ -82,6 +76,7 @@ const getDataSourceName = (code: number) => {
//记录数据 //记录数据
const exportRecordList = ref<any[]>([]); const exportRecordList = ref<any[]>([]);
// 表格加载状态
const tableLoading = ref(false); const tableLoading = ref(false);
//获取数据 //获取数据
......
<template> <template>
<div class="text-left"> <div class="text-left">
<!-- 搜索工具栏 -->
<TableSearch> <TableSearch>
<div class="form-content"> <div class="form-content">
<div class="left"> <div class="left">
...@@ -14,17 +15,9 @@ ...@@ -14,17 +15,9 @@
<div> <div>
<span style="color: white">采集时间:</span> <span style="color: white">采集时间:</span>
<el-config-provider :locale="zhCn"> <el-config-provider :locale="zhCn">
<el-date-picker <el-date-picker type="datetimerange" format="YYYY-MM-DD HH:mm:ss" v-model="searchTimeValue"
type="datetimerange" start-placeholder="开始时间" style="width: 400px" end-placeholder="结束时间" date-format="YYYY/MM/DD ddd"
format="YYYY-MM-DD HH:mm:ss" time-format="A hh:mm:ss" value-format="YYYY-MM-DD HH:mm:ss" />
v-model="searchTimeValue"
start-placeholder="开始时间"
style="width: 400px"
end-placeholder="结束时间"
date-format="YYYY/MM/DD ddd"
time-format="A hh:mm:ss"
value-format="YYYY-MM-DD HH:mm:ss"
/>
</el-config-provider> </el-config-provider>
</div> </div>
</div> </div>
...@@ -36,18 +29,12 @@ ...@@ -36,18 +29,12 @@
</TableSearch> </TableSearch>
</div> </div>
<!-- ITU数据表格 -->
<div class="m-t-5" /> <div class="m-t-5" />
<div class="itu-table"> <div class="itu-table">
<el-table <el-table :data="tableData" style="width: 100%" border :row-style="{ height: '45px' }"
:data="tableData" :header-cell-style="{ textAlign: 'center' }" :cell-style="{ textAlign: 'center' }" v-loading="tableLoading"
style="width: 100%" element-loading-background="rgba(48, 65, 86, 0.7)">
border
:row-style="{ height: '45px' }"
:header-cell-style="{ textAlign: 'center' }"
:cell-style="{ textAlign: 'center' }"
v-loading="tableLoading"
element-loading-background="rgba(48, 65, 86, 0.7)"
>
<!-- <el-table-column type="selection" width="40" /> --> <!-- <el-table-column type="selection" width="40" /> -->
<el-table-column property="number" label="序号" width="55" type="index" /> <el-table-column property="number" label="序号" width="55" type="index" />
<el-table-column property="item.ntc_id" label="SNS Notice ID" show-overflow-tooltip /> <el-table-column property="item.ntc_id" label="SNS Notice ID" show-overflow-tooltip />
...@@ -81,18 +68,8 @@ ...@@ -81,18 +68,8 @@
{{ scope.row.regulatory_status.d_reg_limit === null ? '-' : scope.row.regulatory_status.d_reg_limit }} {{ scope.row.regulatory_status.d_reg_limit === null ? '-' : scope.row.regulatory_status.d_reg_limit }}
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column min-width="100" property="regulatory_status.f_biu_grps" label="是否确认使用" show-overflow-tooltip />
min-width="100" <el-table-column property="regulatory_status.resumption_list" width="140" label="是否暂停使用" show-overflow-tooltip />
property="regulatory_status.f_biu_grps"
label="是否确认使用"
show-overflow-tooltip
/>
<el-table-column
property="regulatory_status.resumption_list"
width="140"
label="是否暂停使用"
show-overflow-tooltip
/>
<el-table-column width="180" property="crawl_time" label="采集时间" show-overflow-tooltip /> <el-table-column width="180" property="crawl_time" label="采集时间" show-overflow-tooltip />
<el-table-column label="操作" width="60"> <el-table-column label="操作" width="60">
<template #default="scope"> <template #default="scope">
...@@ -101,15 +78,12 @@ ...@@ -101,15 +78,12 @@
</el-table-column> </el-table-column>
</el-table> </el-table>
<div class="pagination w-full flex flex-row-reverse pr-4 m-t-4"> <div class="pagination w-full flex flex-row-reverse pr-4 m-t-4">
<Pagination <Pagination :total="pageObj.total" v-model:page="pageObj.pageNo" v-model:limit="pageObj.pageSize"
:total="pageObj.total" @pagination="getData" />
v-model:page="pageObj.pageNo"
v-model:limit="pageObj.pageSize"
@pagination="getData"
/>
</div> </div>
</div> </div>
<!-- ITU数据详情的弹窗 -->
<div class="detailForm"> <div class="detailForm">
<el-dialog v-model="detailVisibleValue" center width="765px" align-center @close="handleClose" draggable> <el-dialog v-model="detailVisibleValue" center width="765px" align-center @close="handleClose" draggable>
<template #header> <template #header>
...@@ -117,6 +91,7 @@ ...@@ -117,6 +91,7 @@
</template> </template>
<el-row> <el-row>
<el-col :span="12"> <el-col :span="12">
<!-- 身份信息 -->
<el-card> <el-card>
<div class="title">身份信息:</div> <div class="title">身份信息:</div>
<el-divider style="margin: 0"></el-divider> <el-divider style="margin: 0"></el-divider>
...@@ -141,6 +116,7 @@ ...@@ -141,6 +116,7 @@
<span class="item">{{ ntwkType }}</span> <span class="item">{{ ntwkType }}</span>
</div> </div>
</el-card> </el-card>
<!-- 监管状态跟踪 -->
<el-card> <el-card>
<div class="title">监管状态跟踪:</div> <div class="title">监管状态跟踪:</div>
<el-divider style="margin: 0"></el-divider> <el-divider style="margin: 0"></el-divider>
...@@ -171,6 +147,7 @@ ...@@ -171,6 +147,7 @@
</el-card> </el-card>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<!-- 特征信息 -->
<el-card> <el-card>
<div class="title">特征信息:</div> <div class="title">特征信息:</div>
<el-divider style="margin: 0"></el-divider> <el-divider style="margin: 0"></el-divider>
...@@ -195,6 +172,7 @@ ...@@ -195,6 +172,7 @@
<span class="item">{{ lowestAltitude }}</span> <span class="item">{{ lowestAltitude }}</span>
</div> </div>
</el-card> </el-card>
<!-- 其他信息 -->
<el-card> <el-card>
<div class="title">其他信息:</div> <div class="title">其他信息:</div>
<el-divider style="margin: 0"></el-divider> <el-divider style="margin: 0"></el-divider>
...@@ -243,10 +221,13 @@ zhCn.el.pagination.total = '共 `{total} 条`' ...@@ -243,10 +221,13 @@ zhCn.el.pagination.total = '共 `{total} 条`'
zhCn.el.pagination.goto = '跳至' zhCn.el.pagination.goto = '跳至'
zhCn.el.pagination.pagesize = '条/页' zhCn.el.pagination.pagesize = '条/页'
zhCn.el.pagination.pageClassifier = '页' zhCn.el.pagination.pageClassifier = '页'
// 查询参数
const searchTargetName = ref('') const searchTargetName = ref('')
const searchTimeValue = ref('') const searchTimeValue = ref('')
const searchTargetId = ref('') const searchTargetId = ref('')
// 删除对话框的显示状态
const showDeleteDialog = ref(false) const showDeleteDialog = ref(false)
// 详情对话框的显示状态
const detailVisibleValue = ref(false) const detailVisibleValue = ref(false)
// SNS Notice ID // SNS Notice ID
const snsId = ref('') const snsId = ref('')
...@@ -302,7 +283,9 @@ const isRestoreUsed = ref('') ...@@ -302,7 +283,9 @@ const isRestoreUsed = ref('')
const validityPeriodSatelliteNetworkOldName = ref('') const validityPeriodSatelliteNetworkOldName = ref('')
// 最新相关 BR IFIC 发布日期 // 最新相关 BR IFIC 发布日期
const BFIFICdate = ref('') const BFIFICdate = ref('')
// 表格数据
const tableData = ref([]) const tableData = ref([])
// 分页参数
const pageObj = ref({ const pageObj = ref({
total: 0, total: 0,
pageSize: 10, pageSize: 10,
...@@ -310,6 +293,7 @@ const pageObj = ref({ ...@@ -310,6 +293,7 @@ const pageObj = ref({
}) })
// 查看数据详情的方法 // 查看数据详情的方法
const handleDetails = async (id: any) => { const handleDetails = async (id: any) => {
// 获取数据并赋值
const res = await getItuDetail({ id: id._id }) const res = await getItuDetail({ id: id._id })
snsId.value = res.data.item.ntc_id snsId.value = res.data.item.ntc_id
department.value = res.data.item.adm department.value = res.data.item.adm
...@@ -347,14 +331,18 @@ const tableLoading = ref(false) ...@@ -347,14 +331,18 @@ const tableLoading = ref(false)
// 获取itu数据列表的方法 // 获取itu数据列表的方法
//重置搜索条件 //重置搜索条件
const resetForm = () => { const resetForm = () => {
// 清空
searchTargetName.value = '' searchTargetName.value = ''
searchTargetId.value = '' searchTargetId.value = ''
searchTimeValue.value = '' searchTimeValue.value = ''
pageObj.value.pageNo = 1 pageObj.value.pageNo = 1
// 重新获取数据
getData() getData()
} }
// 获取itu数据列表的方法
const getData = async () => { const getData = async () => {
tableLoading.value = true tableLoading.value = true
// 发送请求获取数据并赋值
const res = await await getItuList({ const res = await await getItuList({
sat_name: searchTargetName.value, sat_name: searchTargetName.value,
ntc_id: searchTargetId.value, ntc_id: searchTargetId.value,
...@@ -366,10 +354,11 @@ const getData = async () => { ...@@ -366,10 +354,11 @@ const getData = async () => {
tableData.value = res.data.list tableData.value = res.data.list
tableLoading.value = false tableLoading.value = false
} }
// 关闭详情弹窗的方法
const handleClose = () => { const handleClose = () => {
detailVisibleValue.value = false detailVisibleValue.value = false
} }
// 组件挂载时获取数据
onMounted(() => { onMounted(() => {
getData() getData()
}) })
...@@ -379,6 +368,7 @@ onMounted(() => { ...@@ -379,6 +368,7 @@ onMounted(() => {
:deep(.el-form-item__label) { :deep(.el-form-item__label) {
color: white; color: white;
} }
// 调整表单项间距 // 调整表单项间距
.detailForm { .detailForm {
.el-dialog-title { .el-dialog-title {
...@@ -429,6 +419,7 @@ onMounted(() => { ...@@ -429,6 +419,7 @@ onMounted(() => {
display: flex; display: flex;
gap: 10px; gap: 10px;
} }
.info-item { .info-item {
display: flex; display: flex;
align-items: center; align-items: center;
...@@ -443,6 +434,7 @@ onMounted(() => { ...@@ -443,6 +434,7 @@ onMounted(() => {
.item { .item {
color: #eee; color: #eee;
} }
.form-content { .form-content {
display: flex; display: flex;
height: 80px; height: 80px;
......
<template> <template>
<div class="text-left"> <div class="text-left">
<!-- 搜索工具栏 -->
<table-search> <table-search>
<div class="form-content"> <div class="form-content">
<div class="left"> <div class="left">
...@@ -36,6 +37,7 @@ ...@@ -36,6 +37,7 @@
</table-search> </table-search>
</div> </div>
<!-- ST数据表格 -->
<div class="m-t-5" /> <div class="m-t-5" />
<div class="table-content"> <div class="table-content">
<el-table <el-table
...@@ -80,6 +82,7 @@ ...@@ -80,6 +82,7 @@
</div> </div>
</div> </div>
<!-- ITU目标详情弹窗 -->
<div class="detailForm"> <div class="detailForm">
<el-dialog v-model="detailVisibleValue" center width="765px" align-center @close="handleClose" draggable> <el-dialog v-model="detailVisibleValue" center width="765px" align-center @close="handleClose" draggable>
<template #header> <template #header>
...@@ -87,6 +90,7 @@ ...@@ -87,6 +90,7 @@
</template> </template>
<el-row> <el-row>
<el-col> <el-col>
<!-- 目标信息 -->
<el-card> <el-card>
<div class="title">目标信息:</div> <div class="title">目标信息:</div>
<el-divider style="margin: 0"></el-divider> <el-divider style="margin: 0"></el-divider>
...@@ -169,6 +173,7 @@ ...@@ -169,6 +173,7 @@
</div> </div>
</el-col> </el-col>
</el-row> </el-row>
<!-- TLE数据 -->
<div class="title">TLE数据:</div> <div class="title">TLE数据:</div>
<el-divider style="margin: 0"></el-divider> <el-divider style="margin: 0"></el-divider>
<el-row> <el-row>
...@@ -210,6 +215,7 @@ ...@@ -210,6 +215,7 @@
</el-row> </el-row>
</el-dialog> </el-dialog>
</div> </div>
<!-- 数据导出弹窗 -->
<exportDialog v-model:dialogVisible="showDeleteDialog" /> <exportDialog v-model:dialogVisible="showDeleteDialog" />
</template> </template>
...@@ -230,15 +236,21 @@ zhCn.el.pagination.total = '共 `{total} 条`' ...@@ -230,15 +236,21 @@ zhCn.el.pagination.total = '共 `{total} 条`'
zhCn.el.pagination.goto = '跳至' zhCn.el.pagination.goto = '跳至'
zhCn.el.pagination.pagesize = '条/页' zhCn.el.pagination.pagesize = '条/页'
zhCn.el.pagination.pageClassifier = '页' zhCn.el.pagination.pageClassifier = '页'
// 查询参数
const searchTargetName = ref('') const searchTargetName = ref('')
// 搜索条件
const noradCatId = ref('') const noradCatId = ref('')
// 删除弹窗显示状态
const showDeleteDialog = ref(false) const showDeleteDialog = ref(false)
// 时间参数
const timeValue = ref('') const timeValue = ref('')
// 详情弹窗显示状态
const detailVisibleValue = ref(false) const detailVisibleValue = ref(false)
// NoradCatID // NoradCatID
const NoradCatID = ref('') const NoradCatID = ref('')
// 目标名称 // 目标名称
const targetName = ref('') const targetName = ref('')
// 目标类型
const objectType = ref('') const objectType = ref('')
// INTLDES // INTLDES
const intleds = ref('') const intleds = ref('')
...@@ -278,11 +290,14 @@ const meanAnomaly = ref('') ...@@ -278,11 +290,14 @@ const meanAnomaly = ref('')
const rcsSize = ref('') const rcsSize = ref('')
//LAUNCH_DATE //LAUNCH_DATE
const launchDate = ref('') const launchDate = ref('')
// 国家代码
const countryCode = ref('') const countryCode = ref('')
// 轨道速度微调器
const meanMotionDot = ref('') const meanMotionDot = ref('')
// 轨道加速度变化率
const meanMotionDdot = ref('') const meanMotionDdot = ref('')
// 轨道圈数计数器
const revAtEpoch = ref('') const revAtEpoch = ref('')
//半长轴SEMIMAJOR_AXIS //半长轴SEMIMAJOR_AXIS
const semimajorAxis = ref('') const semimajorAxis = ref('')
//第一行数据 TLE_LINE0 //第一行数据 TLE_LINE0
...@@ -291,8 +306,9 @@ const tleLine0 = ref('') ...@@ -291,8 +306,9 @@ const tleLine0 = ref('')
const tleLine1 = ref('') const tleLine1 = ref('')
//第三行数据 TLE_LINE0 //第三行数据 TLE_LINE0
const tleLine2 = ref('') const tleLine2 = ref('')
// 表格数据
const tableData = ref([]) const tableData = ref([])
// 分页数据
const pageObj = ref({ const pageObj = ref({
total: 10, total: 10,
pageSize: 10, pageSize: 10,
...@@ -300,9 +316,9 @@ const pageObj = ref({ ...@@ -300,9 +316,9 @@ const pageObj = ref({
}) })
// 查看数据详情的方法 // 查看数据详情的方法
const handleDetails = async (row: any) => { const handleDetails = async (row: any) => {
// 发送请求获取数据
const res = await getStDetail({ id: row._id }) const res = await getStDetail({ id: row._id })
console.log(res) // 将数据赋值给对应的变量
NoradCatID.value = res.data.NORAD_CAT_ID NoradCatID.value = res.data.NORAD_CAT_ID
rcsSize.value = res.data.RCS_SIZE rcsSize.value = res.data.RCS_SIZE
launchDate.value = res.data.LAUNCH_DATE launchDate.value = res.data.LAUNCH_DATE
...@@ -327,6 +343,7 @@ const handleDetails = async (row: any) => { ...@@ -327,6 +343,7 @@ const handleDetails = async (row: any) => {
apogee.value = res.data.APOAPSIS apogee.value = res.data.APOAPSIS
rcs.value = res.data.RCS_SIZE rcs.value = res.data.RCS_SIZE
site.value = res.data.SITE site.value = res.data.SITE
// 将TLE数据拼接成一行显示
tle.value = `${res.data.TLE_LINE0} tle.value = `${res.data.TLE_LINE0}
${res.data.TLE_LINE1} ${res.data.TLE_LINE1}
${res.data.TLE_LINE2}` ${res.data.TLE_LINE2}`
...@@ -341,15 +358,18 @@ ${res.data.TLE_LINE2}` ...@@ -341,15 +358,18 @@ ${res.data.TLE_LINE2}`
const tableLoading = ref(false) const tableLoading = ref(false)
//重置搜索条件 //重置搜索条件
const resetForm = () => { const resetForm = () => {
// 清空
noradCatId.value = '' noradCatId.value = ''
searchTargetName.value = '' searchTargetName.value = ''
timeValue.value = '' timeValue.value = ''
pageObj.value.pageNo = 1 pageObj.value.pageNo = 1
// 重新获取数据
getData() getData()
} }
// 获取st数据列表的方法 // 获取st数据列表的方法
const getData = async () => { const getData = async () => {
tableLoading.value = true tableLoading.value = true
// 发送请求获取数据并赋值
const res = await getStList({ const res = await getStList({
norad_cat_id: noradCatId.value, norad_cat_id: noradCatId.value,
object_name: searchTargetName.value, object_name: searchTargetName.value,
...@@ -361,10 +381,11 @@ const getData = async () => { ...@@ -361,10 +381,11 @@ const getData = async () => {
tableData.value = res.data.list tableData.value = res.data.list
tableLoading.value = false tableLoading.value = false
} }
// 关闭详情弹窗的方法
const handleClose = () => { const handleClose = () => {
detailVisibleValue.value = false detailVisibleValue.value = false
} }
// 组件挂载时获取数据
onMounted(() => { onMounted(() => {
getData() getData()
}) })
......
<template> <template>
<div> <div>
<!-- 页面标题 -->
<MenuTitle title="数据展示" subtitle="Data Display" /> <MenuTitle title="数据展示" subtitle="Data Display" />
<div class="backStyle" v-if="route.query.jump === 'yes'" @click="goToStatus" /> <div class="backStyle" v-if="route.query.jump === 'yes'" @click="goToStatus" />
<!-- 导出按钮 -->
<div class="segment-content"> <div class="segment-content">
<div class="custom-style flex justify-between"> <div class="custom-style flex justify-between">
<div class="flex gap-4"> <div class="flex gap-4">
...@@ -22,7 +24,9 @@ ...@@ -22,7 +24,9 @@
<stDataTab v-if="mode === 'ST数据'"></stDataTab> <stDataTab v-if="mode === 'ST数据'"></stDataTab>
<!-- ESA数据页面组件 --> <!-- ESA数据页面组件 -->
<esDataTab v-if="mode === 'ESA数据'"></esDataTab> <esDataTab v-if="mode === 'ESA数据'"></esDataTab>
<!-- 导出弹窗组件 -->
<exportDialog v-model:dialogVisible="showDeleteDialog" @confirm="handleExportConfirm" /> <exportDialog v-model:dialogVisible="showDeleteDialog" @confirm="handleExportConfirm" />
<!-- 导出记录弹窗组件 -->
<exportRecord ref="expRec" /> <exportRecord ref="expRec" />
</div> </div>
</template> </template>
...@@ -40,33 +44,39 @@ import MenuTitle from '@/components/MenuTitle.vue' ...@@ -40,33 +44,39 @@ import MenuTitle from '@/components/MenuTitle.vue'
import exportRecord from './components/exportRecord.vue' import exportRecord from './components/exportRecord.vue'
import { ElNotification } from 'element-plus' import { ElNotification } from 'element-plus'
// 数据展示模式
const mode = ref(sessionStorage.getItem('dataDisplayMode') || 'DSN数据') const mode = ref(sessionStorage.getItem('dataDisplayMode') || 'DSN数据')
// 删除弹窗显示状态
const showDeleteDialog = ref(false) const showDeleteDialog = ref(false)
// 数据源选择器选项配置
const sizeOptions = ['DSN数据', 'ITU数据', 'ST数据', 'ESA数据'] const sizeOptions = ['DSN数据', 'ITU数据', 'ST数据', 'ESA数据']
// 路由对象
const route = useRoute() const route = useRoute()
const router = useRouter() const router = useRouter()
// 路由参数中的mode值,用于设置初始数据展示模式
const modeValue = ref<any>('数据展示') const modeValue = ref<any>('数据展示')
//导出记录组件引用 //导出记录组件引用
const expRec = ref<any>(null) const expRec = ref<any>(null)
// 跳转到状态页面
const goToStatus = () => { const goToStatus = () => {
router.push({ router.push({
path: '/osStatus/list' path: '/osStatus/list'
}) })
} }
// 打开导出弹窗的方法
const handleExport = () => { const handleExport = () => {
showDeleteDialog.value = true showDeleteDialog.value = true
} }
// 消息通知
const noticeImpl = ref() const noticeImpl = ref()
const handleExportConfirm = () => {} const handleExportConfirm = () => {}
// 组件挂载时显示消息通知
onMounted(() => { onMounted(() => {
if (route.query.mode) { if (route.query.mode) {
modeValue.value = route.query.mode modeValue.value = route.query.mode
mode.value = modeValue.value mode.value = modeValue.value
} }
// 显示消息通知
noticeImpl.value = ElNotification({ noticeImpl.value = ElNotification({
title: '温馨提示', title: '温馨提示',
message: h('i', { style: 'color: teal' }, '爬虫数据可导出至本地,请点击【导出】按钮执行数据导出'), message: h('i', { style: 'color: teal' }, '爬虫数据可导出至本地,请点击【导出】按钮执行数据导出'),
...@@ -79,6 +89,7 @@ const handleExportRecord = () => { ...@@ -79,6 +89,7 @@ const handleExportRecord = () => {
expRec.value.openDialog() expRec.value.openDialog()
} }
// 监听mode变化,更新sessionStorage中的数据展示模式
watch( watch(
mode, mode,
(newVal) => { (newVal) => {
...@@ -89,7 +100,7 @@ watch( ...@@ -89,7 +100,7 @@ watch(
immediate: true immediate: true
} }
) )
// 组件卸载时关闭消息通知
onUnmounted(() => { onUnmounted(() => {
if (noticeImpl.value) { if (noticeImpl.value) {
noticeImpl.value.close() noticeImpl.value.close()
......
<template> <template>
<div> <div>
<!-- 页面标题 -->
<MenuTitle title="爬虫管理" subtitle="Spider Manager" /> <MenuTitle title="爬虫管理" subtitle="Spider Manager" />
<!-- 爬虫管理数据表格 -->
<div class="table-content"> <div class="table-content">
<el-table <el-table :data="tableData" style="width: 100%" border :header-cell-style="{ textAlign: 'center' }"
:data="tableData" :cell-style="{ textAlign: 'center' }" :row-style="{ height: '60px' }" v-loading="tableData.length == 0"
style="width: 100%" element-loading-background="rgba(48, 65, 86, 0.7)">
border <!-- 表头配置 -->
:header-cell-style="{ textAlign: 'center' }"
:cell-style="{ textAlign: 'center' }"
:row-style="{ height: '60px' }"
v-loading="tableData.length == 0"
element-loading-background="rgba(48, 65, 86, 0.7)"
>
<el-table-column property="number" label="序号" type="index" width="80" /> <el-table-column property="number" label="序号" type="index" width="80" />
<el-table-column property="spider" label="爬虫代号" show-overflow-tooltip /> <el-table-column property="spider" label="爬虫代号" show-overflow-tooltip />
<el-table-column property="spider_name" label="爬虫名称" show-overflow-tooltip /> <el-table-column property="spider_name" label="爬虫名称" show-overflow-tooltip />
...@@ -26,39 +22,20 @@ ...@@ -26,39 +22,20 @@
</el-table-column> </el-table-column>
</el-table> </el-table>
<div class="pagination w-full flex flex-row-reverse pr-4 m-t-4"> <div class="pagination w-full flex flex-row-reverse pr-4 m-t-4">
<Pagination <Pagination :total="pageObj.total" v-model:page="pageObj.pageNo" v-model:limit="pageObj.pageSize"
:total="pageObj.total" @pagination="getData" />
v-model:page="pageObj.pageNo"
v-model:limit="pageObj.pageSize"
@pagination="getData"
/>
</div> </div>
</div> </div>
<el-dialog <!-- ST详情对话框 -->
style="z-index: 999999" <el-dialog style="z-index: 999999" draggable v-model="editDialogVisible" title="指定下载以下卫星" width="550"
draggable @close="handleDialogClose">
v-model="editDialogVisible"
title="指定下载以下卫星"
width="550"
@close="handleDialogClose"
>
<div class="No-Content" ref="noContentRef"> <div class="No-Content" ref="noContentRef">
<TransitionGroup <TransitionGroup enter-active-class="animate__animated animate__slideInRight"
enter-active-class="animate__animated animate__slideInRight" leave-active-class="animate__animated animate__slideOutRight" enter-from-class="animate__opacity-0"
leave-active-class="animate__animated animate__slideOutRight" leave-to-class="animate__opacity-0">
enter-from-class="animate__opacity-0" <NoItem v-for="(no, index) in sateNoList" :key="index" class="no-item-row" :-no="no.norad_cat_id"
leave-to-class="animate__opacity-0" @add-no="handleSateAdd" @del-no="handleSateDel" :reset-selected="resetSelected"></NoItem>
>
<NoItem
v-for="(no, index) in sateNoList"
:key="index"
class="no-item-row"
:-no="no.norad_cat_id"
@add-no="handleSateAdd"
@del-no="handleSateDel"
:reset-selected="resetSelected"
></NoItem>
</TransitionGroup> </TransitionGroup>
</div> </div>
<div class="footer"> <div class="footer">
...@@ -74,16 +51,12 @@ ...@@ -74,16 +51,12 @@
</template> </template>
<template #actions="{ confirm, cancel }"> <template #actions="{ confirm, cancel }">
<el-button size="small" @click="cancel">取消</el-button> <el-button size="small" @click="cancel">取消</el-button>
<el-button <el-button type="danger" size="small" @click="
type="danger" (e: MouseEvent) => {
size="small" confirm(e)
@click=" delNoList()
(e: MouseEvent) => { }
confirm(e) ">
delNoList()
}
"
>
确定 确定
</el-button> </el-button>
</template> </template>
...@@ -103,14 +76,19 @@ import NoItem from './components/NoItem.vue' ...@@ -103,14 +76,19 @@ import NoItem from './components/NoItem.vue'
import { ElMessage, type UploadProps, type UploadRawFile } from 'element-plus' import { ElMessage, type UploadProps, type UploadRawFile } from 'element-plus'
import MenuTitle from '@/components/MenuTitle.vue' import MenuTitle from '@/components/MenuTitle.vue'
// 路由对象
const router = useRouter() const router = useRouter()
// 表格数据
const tableData = ref([]) const tableData = ref([])
// 分页参数
const pageObj = ref({ const pageObj = ref({
total: 10, total: 10,
pageSize: 10, pageSize: 10,
pageNo: 1 pageNo: 1
}) })
// 跳转到任务详情页面
const handleDetails = (row: any) => { const handleDetails = (row: any) => {
// 路由跳转并传递参数进行筛选
router.push({ router.push({
path: '/osTaskInformation/list', path: '/osTaskInformation/list',
query: { query: {
...@@ -125,7 +103,7 @@ const getData = async () => { ...@@ -125,7 +103,7 @@ const getData = async () => {
const res = await getSpiderList({ scrapydServerId: '1', project: 'spiders' }) const res = await getSpiderList({ scrapydServerId: '1', project: 'spiders' })
tableData.value = res.data tableData.value = res.data
} }
// 详情对话框显示状态
const editDialogVisible = ref(false) const editDialogVisible = ref(false)
//编号item类型定义 //编号item类型定义
...@@ -134,15 +112,15 @@ interface noradItem { ...@@ -134,15 +112,15 @@ interface noradItem {
norad_cat_id: string norad_cat_id: string
create_time: string create_time: string
} }
// 当前输入的编号
const sateNoList = ref<noradItem[]>([]) const sateNoList = ref<noradItem[]>([])
// 当前选中的编号列表
const curSateNo = ref('') const curSateNo = ref('')
// 当前选中的编号列表
const curSelSateNo = ref<string[]>([]) const curSelSateNo = ref<string[]>([])
// 重置选中状态的标志
const resetSelected = ref(false) const resetSelected = ref(false)
// 关闭对话框时的处理函数
const handleDialogClose = () => { const handleDialogClose = () => {
// 清空已选中的编号 // 清空已选中的编号
curSelSateNo.value = [] curSelSateNo.value = []
...@@ -180,6 +158,7 @@ const addNoToList = async () => { ...@@ -180,6 +158,7 @@ const addNoToList = async () => {
//编号文件导入后发送到后端 //编号文件导入后发送到后端
const fileImptAddNoList = async () => { const fileImptAddNoList = async () => {
try { try {
// 调用添加接口,传递读取的编号列表
const res = await addSateNoList({ norad_id: textFileNumbers.value }) const res = await addSateNoList({ norad_id: textFileNumbers.value })
if (res.code === 0) { if (res.code === 0) {
ElMessage.success('导入编号成功') ElMessage.success('导入编号成功')
...@@ -193,6 +172,7 @@ const fileImptAddNoList = async () => { ...@@ -193,6 +172,7 @@ const fileImptAddNoList = async () => {
//删除选中编号 //删除选中编号
const delNoList = async () => { const delNoList = async () => {
try { try {
// 调用删除接口,传递选中的编号列表
const res = await deleteSateNoList({ norad_id: curSelSateNo.value }) const res = await deleteSateNoList({ norad_id: curSelSateNo.value })
if (res.code === 0) { if (res.code === 0) {
ElMessage.success('删除编号成功') ElMessage.success('删除编号成功')
...@@ -207,7 +187,6 @@ const delNoList = async () => { ...@@ -207,7 +187,6 @@ const delNoList = async () => {
ElMessage.error(error.message) ElMessage.error(error.message)
} }
} }
const noContentRef = ref<HTMLDivElement | null>(null) const noContentRef = ref<HTMLDivElement | null>(null)
//新添加滚动到底部 //新添加滚动到底部
...@@ -228,12 +207,12 @@ const checkNoLeSix = (no: number | string): boolean => { ...@@ -228,12 +207,12 @@ const checkNoLeSix = (no: number | string): boolean => {
} }
return true return true
} }
// 添加编号后滚动到底部
const handleNumInput = (value: string) => { const handleNumInput = (value: string) => {
const filtered = value.replace(/\D/g, '') const filtered = value.replace(/\D/g, '')
curSateNo.value = filtered.slice(0, 6) curSateNo.value = filtered.slice(0, 6)
} }
// 打开编辑对话框的方法
const handleEditSateId = async () => { const handleEditSateId = async () => {
editDialogVisible.value = true editDialogVisible.value = true
getSateNoList() getSateNoList()
...@@ -257,7 +236,7 @@ const textFileNumbers = ref<string[]>([]) ...@@ -257,7 +236,7 @@ const textFileNumbers = ref<string[]>([])
//监听导入文件的数组变化 //监听导入文件的数组变化
watch(textFileNumbers, (newVal) => { watch(textFileNumbers, (newVal) => {
if (newVal.length > 0) { if (newVal.length > 0) {
newVal.forEach((num) => {}) newVal.forEach((num) => { })
fileImptAddNoList() fileImptAddNoList()
} }
}) })
...@@ -337,7 +316,7 @@ const parseTextToNumbers = (text: string): number[] => { ...@@ -337,7 +316,7 @@ const parseTextToNumbers = (text: string): number[] => {
return numbers return numbers
} }
// 组件挂载时获取数据
onMounted(() => { onMounted(() => {
getData() getData()
}) })
...@@ -347,6 +326,7 @@ onMounted(() => { ...@@ -347,6 +326,7 @@ onMounted(() => {
:deep(.el-input__inner) { :deep(.el-input__inner) {
color: black; color: black;
} }
/* 去除按钮边框 */ /* 去除按钮边框 */
.el-button:focus { .el-button:focus {
outline: none; outline: none;
...@@ -379,6 +359,7 @@ onMounted(() => { ...@@ -379,6 +359,7 @@ onMounted(() => {
text-align: left; text-align: left;
margin-left: 20px; margin-left: 20px;
} }
.divider { .divider {
margin-top: 15px; margin-top: 15px;
} }
...@@ -443,6 +424,7 @@ onMounted(() => { ...@@ -443,6 +424,7 @@ onMounted(() => {
white-space: nowrap; white-space: nowrap;
justify-content: center; justify-content: center;
} }
.btn-group .el-button { .btn-group .el-button {
flex-shrink: 0; flex-shrink: 0;
} }
......
<!-- 数据卡片组件 -->
<template> <template>
<div class="flex"> <div class="flex">
<span class="textStyle" :class="{ toRight0: slideState }">数据统计</span> <span class="textStyle" :class="{ toRight0: slideState }">数据统计</span>
...@@ -9,6 +10,7 @@ ...@@ -9,6 +10,7 @@
<div class="wordStyle"> <div class="wordStyle">
<span>总数据量(条):</span> <span>总数据量(条):</span>
<span class="total-num" v-if="totalDataNumber !== null">{{ <span class="total-num" v-if="totalDataNumber !== null">{{
// 格式化大数字,保留两位小数,并添加单位
formatExactLargeNum(totalDataNumber) ?? '--' formatExactLargeNum(totalDataNumber) ?? '--'
}}</span> }}</span>
<span class="loading" v-else></span> <span class="loading" v-else></span>
...@@ -16,15 +18,15 @@ ...@@ -16,15 +18,15 @@
<div class="wordStyle"> <div class="wordStyle">
<span>采集的页面数量(个):</span> <span>采集的页面数量(个):</span>
<span class="total-num" v-if="totalPageNumber !== null"> <span class="total-num" v-if="totalPageNumber !== null">
{{ formatExactLargeNum(totalPageNumber) ?? '--' }}</span <!-- 格式化数据并兜底 -->
> {{ formatExactLargeNum(totalPageNumber) ?? '--' }}</span>
<span class="loading" v-else></span> <span class="loading" v-else></span>
</div> </div>
<div class="wordStyle"> <div class="wordStyle">
<span>采集的目标数量(个):</span> <span>采集的目标数量(个):</span>
<span class="total-num" v-if="totalTargetNumber !== null"> <span class="total-num" v-if="totalTargetNumber !== null">
{{ formatExactLargeNum(totalTargetNumber) ?? '--' }}</span <!-- 格式化数据并兜底 -->
> {{ formatExactLargeNum(totalTargetNumber) ?? '--' }}</span>
<span class="loading" v-else></span> <span class="loading" v-else></span>
</div> </div>
</div> </div>
...@@ -36,11 +38,13 @@ ...@@ -36,11 +38,13 @@
<div class="items"> <div class="items">
<div class="wordStyle"> <div class="wordStyle">
<span>任务执行成功统计(个):</span> <span>任务执行成功统计(个):</span>
<!-- 格式化数据并兜底 -->
<span class="total-num" v-if="successTask !== null">{{ formatExactLargeNum(successTask) ?? '--' }}</span> <span class="total-num" v-if="successTask !== null">{{ formatExactLargeNum(successTask) ?? '--' }}</span>
<span class="loading" v-else></span> <span class="loading" v-else></span>
</div> </div>
<div class="wordStyle"> <div class="wordStyle">
<span>任务执行失败统计(个):</span> <span>任务执行失败统计(个):</span>
<!-- 格式化数据并兜底 -->
<span class="total-num" v-if="failTask !== null">{{ formatExactLargeNum(failTask) ?? '--' }}</span> <span class="total-num" v-if="failTask !== null">{{ formatExactLargeNum(failTask) ?? '--' }}</span>
<span class="loading" v-else></span> <span class="loading" v-else></span>
</div> </div>
...@@ -54,12 +58,13 @@ ...@@ -54,12 +58,13 @@
<div class="wordStyle"> <div class="wordStyle">
<span>平均成功率:</span> <span>平均成功率:</span>
<span class="total-num" v-if="speed !== null"> <span class="total-num" v-if="speed !== null">
{{ `${Number(Math.floor(speed * 100) / 100).toFixed(2)}%` }}</span <!-- 格式化数据 -->
> {{ `${Number(Math.floor(speed * 100) / 100).toFixed(2)}%` }}</span>
<span class="loading" v-else></span> <span class="loading" v-else></span>
</div> </div>
<div class="wordStyle"> <div class="wordStyle">
<span>平均错误率: </span> <span>平均错误率: </span>
<!-- 格式化数据 -->
<span class="total-num" v-if="errorRate !== null">{{ <span class="total-num" v-if="errorRate !== null">{{
`${Number(Math.ceil(errorRate * 100) / 100).toFixed(2)}%` `${Number(Math.ceil(errorRate * 100) / 100).toFixed(2)}%`
}}</span> }}</span>
...@@ -78,20 +83,31 @@ import formatExactLargeNum from '@/utils/formatExactLargeNum' ...@@ -78,20 +83,31 @@ import formatExactLargeNum from '@/utils/formatExactLargeNum'
import { useSlideStateStore } from '@/store/slideState' import { useSlideStateStore } from '@/store/slideState'
import { storeToRefs } from 'pinia' import { storeToRefs } from 'pinia'
// 格式化大数字的工具函数
const slideStateStore = useSlideStateStore() const slideStateStore = useSlideStateStore()
// 从store中获取侧边栏状态
const { slideState } = storeToRefs(slideStateStore) const { slideState } = storeToRefs(slideStateStore)
// 路由对象
const router = useRouter() const router = useRouter()
// 数据统计相关的响应式变量
const totalDataNumber = ref(null) const totalDataNumber = ref(null)
// 采集的页面数量
const totalPageNumber = ref(null) const totalPageNumber = ref(null)
// 采集的目标数量
const totalTargetNumber = ref(null) const totalTargetNumber = ref(null)
// 任务执行成功统计
const successTask = ref(null) const successTask = ref(null)
// 任务执行失败统计
const failTask = ref(null) const failTask = ref(null)
// 性能统计相关的响应式变量
const unusualTask = ref(null) const unusualTask = ref(null)
// 平均成功率
const speed = ref(null) const speed = ref(null)
// 错误率
const errorRate = ref(null) const errorRate = ref(null)
// 异常率
const unusualRate = ref(null) const unusualRate = ref(null)
// 跳转到DSN数据页面的方法
const goToAllDataPage = () => { const goToAllDataPage = () => {
router.push({ router.push({
path: '/osDataDisplay/list', path: '/osDataDisplay/list',
...@@ -101,7 +117,7 @@ const goToAllDataPage = () => { ...@@ -101,7 +117,7 @@ const goToAllDataPage = () => {
} }
}) })
} }
// 跳转到任务记录页面的方法
const goToTaskRecordPage = () => { const goToTaskRecordPage = () => {
router.push({ router.push({
path: '/osTaskRecord/list', path: '/osTaskRecord/list',
...@@ -114,6 +130,7 @@ const goToTaskRecordPage = () => { ...@@ -114,6 +130,7 @@ const goToTaskRecordPage = () => {
// 获取数据统计数据的方法 // 获取数据统计数据的方法
const getData = async () => { const getData = async () => {
// 调用接口获取数据统计数据
const staticData = await getStatsDataList({}) const staticData = await getStatsDataList({})
const spiderTask = await getSpiderTaskList({}) const spiderTask = await getSpiderTaskList({})
const performance = await getPerformanceList({}) const performance = await getPerformanceList({})
...@@ -125,13 +142,12 @@ const getData = async () => { ...@@ -125,13 +142,12 @@ const getData = async () => {
unusualTask.value = spiderTask.data.exceptionCount unusualTask.value = spiderTask.data.exceptionCount
speed.value = performance.data.success speed.value = performance.data.success
errorRate.value = performance.data.error errorRate.value = performance.data.error
console.log(errorRate.value)
unusualRate.value = performance.data.exception unusualRate.value = performance.data.exception
} }
//sidebarStatus //sidebarStatus
// 组件挂载时获取数据
onMounted(() => { onMounted(() => {
getData() getData()
}) })
...@@ -193,9 +209,11 @@ onMounted(() => { ...@@ -193,9 +209,11 @@ onMounted(() => {
0% { 0% {
opacity: 0; opacity: 0;
} }
50% { 50% {
opacity: 0.5; opacity: 0.5;
} }
100% { 100% {
opacity: 1; opacity: 1;
} }
...@@ -224,6 +242,7 @@ onMounted(() => { ...@@ -224,6 +242,7 @@ onMounted(() => {
background-size: calc(100% / 3) 50%; background-size: calc(100% / 3) 50%;
animation: l3 1s infinite linear; animation: l3 1s infinite linear;
} }
@keyframes l3 { @keyframes l3 {
20% { 20% {
background-position: background-position:
...@@ -231,18 +250,21 @@ onMounted(() => { ...@@ -231,18 +250,21 @@ onMounted(() => {
50% 50%, 50% 50%,
100% 50%; 100% 50%;
} }
40% { 40% {
background-position: background-position:
0% 100%, 0% 100%,
50% 0%, 50% 0%,
100% 50%; 100% 50%;
} }
60% { 60% {
background-position: background-position:
0% 50%, 0% 50%,
50% 100%, 50% 100%,
100% 0%; 100% 0%;
} }
80% { 80% {
background-position: background-position:
0% 50%, 0% 50%,
......
<!-- 错误日志统计表格组件 -->
<template> <template>
<div class="dataCard"> <div class="dataCard">
<div class="titleStyle">错误日志统计</div> <div class="titleStyle">错误日志统计</div>
<div class="chart-container" ref="chartRef"></div> <div class="chart-container" ref="chartRef"></div>
<!-- 错误详情弹窗 -->
<el-dialog draggable v-model="DialogVisible" :title="`错误详情丨${curDate}`" @close="tableData = []"> <el-dialog draggable v-model="DialogVisible" :title="`错误详情丨${curDate}`" @close="tableData = []">
<div class="table-content"> <div class="table-content">
<!-- 错误详情表格 -->
<el-table :data="curTableData" border style="width: 100%"> <el-table :data="curTableData" border style="width: 100%">
<el-table-column width="55" label="序号" type="index" /> <el-table-column width="55" label="序号" type="index" />
<el-table-column width="150" property="spider" label="爬虫名称" /> <el-table-column width="150" property="spider" label="爬虫名称" />
...@@ -15,13 +18,8 @@ ...@@ -15,13 +18,8 @@
<el-table-column width="160" property="timestamp" label="记录时间" /> <el-table-column width="160" property="timestamp" label="记录时间" />
</el-table> </el-table>
<div class="pagination w-full flex flex-row-reverse pr-4 m-t-4"> <div class="pagination w-full flex flex-row-reverse pr-4 m-t-4">
<Pagination <Pagination :total="pageObj.total" v-model:page="pageObj.pageNo" v-model:limit="pageObj.pageSize"
:total="pageObj.total" @pagination="getData" v-model:pagerCount="pageObj.pagerCount" />
v-model:page="pageObj.pageNo"
v-model:limit="pageObj.pageSize"
@pagination="getData"
v-model:pagerCount="pageObj.pagerCount"
/>
</div> </div>
</div> </div>
</el-dialog> </el-dialog>
...@@ -39,7 +37,7 @@ const chartRef = useTemplateRef<HTMLElement | null>("chartRef"); ...@@ -39,7 +37,7 @@ const chartRef = useTemplateRef<HTMLElement | null>("chartRef");
//详情弹窗状态 //详情弹窗状态
const DialogVisible = ref(false); const DialogVisible = ref(false);
// 分页参数
const pageObj = ref({ const pageObj = ref({
total: 0, total: 0,
pageNo: 1, pageNo: 1,
...@@ -49,7 +47,7 @@ const pageObj = ref({ ...@@ -49,7 +47,7 @@ const pageObj = ref({
//弹窗表格数据 //弹窗表格数据
const tableData = ref<any[]>([]); const tableData = ref<any[]>([]);
// 当前页表格数据
const curTableData = ref<any[]>([]); const curTableData = ref<any[]>([]);
//数据项定义 //数据项定义
...@@ -130,12 +128,14 @@ const setChartData = async () => { ...@@ -130,12 +128,14 @@ const setChartData = async () => {
type: "shadow", type: "shadow",
}, },
}, },
// 调整图表边距,确保内容不被遮挡
grid: { grid: {
left: "3%", left: "3%",
right: "4%", right: "4%",
bottom: "3%", bottom: "3%",
containLabel: true, containLabel: true,
}, },
// x轴配置
xAxis: [ xAxis: [
{ {
type: "category", type: "category",
...@@ -155,6 +155,7 @@ const setChartData = async () => { ...@@ -155,6 +155,7 @@ const setChartData = async () => {
}, },
}, },
], ],
// y轴配置
yAxis: [ yAxis: [
{ {
type: "value", type: "value",
...@@ -171,6 +172,7 @@ const setChartData = async () => { ...@@ -171,6 +172,7 @@ const setChartData = async () => {
}, },
}, },
], ],
// 数据系列配置
series: [ series: [
{ {
name: "日志数量", name: "日志数量",
...@@ -191,6 +193,7 @@ const setChartData = async () => { ...@@ -191,6 +193,7 @@ const setChartData = async () => {
const handleClickChart = (params: any) => { const handleClickChart = (params: any) => {
DialogVisible.value = true; DialogVisible.value = true;
curDate.value = params.name; curDate.value = params.name;
// 根据点击的日期筛选出对应的日志数据,展示在弹窗表格中
rawLogList.value.forEach((item) => { rawLogList.value.forEach((item) => {
if (item.timestamp.split(" ")[0] === params.name) { if (item.timestamp.split(" ")[0] === params.name) {
tableData.value.push(item); tableData.value.push(item);
......
...@@ -32,11 +32,13 @@ ...@@ -32,11 +32,13 @@
import { useRouter } from "vue-router"; import { useRouter } from "vue-router";
import { storeToRefs } from "pinia"; import { storeToRefs } from "pinia";
import { useSlideStateStore } from "@/store/slideState"; import { useSlideStateStore } from "@/store/slideState";
// 引入数据格式化工具函数s
const slideStateStore = useSlideStateStore(); const slideStateStore = useSlideStateStore();
// 从store中获取侧边栏状态
const { slideState } = storeToRefs(slideStateStore); const { slideState } = storeToRefs(slideStateStore);
// 获取路由对象
const router = useRouter(); const router = useRouter();
// 跳转到综合数据页面
defineProps({ defineProps({
totalDataNumber: { totalDataNumber: {
type: String, type: String,
...@@ -71,7 +73,7 @@ defineProps({ ...@@ -71,7 +73,7 @@ defineProps({
default: "", default: "",
}, },
}); });
// 跳转到综合数据页面
const goToAllDataPage = () => { const goToAllDataPage = () => {
router.push({ router.push({
path: "/osDataDisplay/list", path: "/osDataDisplay/list",
...@@ -81,6 +83,7 @@ const goToAllDataPage = () => { ...@@ -81,6 +83,7 @@ const goToAllDataPage = () => {
}, },
}); });
}; };
// 跳转到DSN数据页面
const goToDSNDataPage = () => { const goToDSNDataPage = () => {
router.push({ router.push({
path: "/osDataDisplay/list", path: "/osDataDisplay/list",
...@@ -90,6 +93,7 @@ const goToDSNDataPage = () => { ...@@ -90,6 +93,7 @@ const goToDSNDataPage = () => {
}, },
}); });
}; };
// 跳转到ITU数据页面
const goToITUDataPage = () => { const goToITUDataPage = () => {
router.push({ router.push({
path: "/osDataDisplay/list", path: "/osDataDisplay/list",
...@@ -99,6 +103,7 @@ const goToITUDataPage = () => { ...@@ -99,6 +103,7 @@ const goToITUDataPage = () => {
}, },
}); });
}; };
// 跳转到ST数据页面
const goToSTDataPage = () => { const goToSTDataPage = () => {
router.push({ router.push({
path: "/osDataDisplay/list", path: "/osDataDisplay/list",
...@@ -108,6 +113,7 @@ const goToSTDataPage = () => { ...@@ -108,6 +113,7 @@ const goToSTDataPage = () => {
}, },
}); });
}; };
// 跳转到ESA数据页面
const goToESADataPage = () => { const goToESADataPage = () => {
router.push({ router.push({
path: "/osDataDisplay/list", path: "/osDataDisplay/list",
......
<template> <template>
<div class="monitor-container"> <div class="monitor-container">
<div class="card-container"> <div class="card-container">
...@@ -30,6 +31,7 @@ import qbCard from "@/views/os-status/components/qbDataMonitor.vue"; ...@@ -30,6 +31,7 @@ import qbCard from "@/views/os-status/components/qbDataMonitor.vue";
import errorMessageChart from "./errorMessageChart.vue"; import errorMessageChart from "./errorMessageChart.vue";
import { onMounted } from "vue"; import { onMounted } from "vue";
//prop组件
defineProps({ defineProps({
title: { title: {
type: String, type: String,
......
<!-- 任务统计卡片 -->
<template> <template>
<div class="flex"> <div class="flex">
<span class="textStyle" :class="{ toRight0: slideState }">任务统计</span> <span class="textStyle" :class="{ toRight0: slideState }">任务统计</span>
<!-- DSN任务数据统计 -->
<div class="dataCard" @click="goToDSNTaskRecordPage"> <div class="dataCard" @click="goToDSNTaskRecordPage">
<div class="titleStyle"> <div class="titleStyle">
<span>DSN爬取任务</span> <span>DSN爬取任务</span>
...@@ -36,6 +38,7 @@ ...@@ -36,6 +38,7 @@
</div> </div>
</div> </div>
</div> </div>
<!-- ITU任务数据统计 -->
<div class="dataCard" @click="goToITUTaskRecordPage"> <div class="dataCard" @click="goToITUTaskRecordPage">
<div class="titleStyle"> <div class="titleStyle">
<span>ITU爬取任务</span> <span>ITU爬取任务</span>
...@@ -71,6 +74,7 @@ ...@@ -71,6 +74,7 @@
</div> </div>
</div> </div>
</div> </div>
<!-- ST任务数据统计 -->
<div class="dataCard" @click="goToSTTaskRecordPage"> <div class="dataCard" @click="goToSTTaskRecordPage">
<div class="titleStyle"> <div class="titleStyle">
<span>ST爬取任务</span> <span>ST爬取任务</span>
...@@ -106,6 +110,7 @@ ...@@ -106,6 +110,7 @@
</div> </div>
</div> </div>
</div> </div>
<!-- ESA任务数据统计 -->
<div class="dataCard" @click="goToESATaskRecordPage"> <div class="dataCard" @click="goToESATaskRecordPage">
<div class="titleStyle"> <div class="titleStyle">
<span>ESA爬取任务</span> <span>ESA爬取任务</span>
...@@ -149,28 +154,46 @@ import { useSlideStateStore } from '@/store/slideState' ...@@ -149,28 +154,46 @@ import { useSlideStateStore } from '@/store/slideState'
import { storeToRefs } from 'pinia' import { storeToRefs } from 'pinia'
import formatExactLargeNum from '@/utils/formatExactLargeNum' import formatExactLargeNum from '@/utils/formatExactLargeNum'
// 获取侧边栏状态
const slideStateStore = useSlideStateStore() const slideStateStore = useSlideStateStore()
// 从store中获取侧边栏状态
const { slideState } = storeToRefs(slideStateStore) const { slideState } = storeToRefs(slideStateStore)
// 路由对象
const router = useRouter() const router = useRouter()
// dsn任务统计数据
const dsnTotalTaskNumber = ref(null) const dsnTotalTaskNumber = ref(null)
// dsn任务成功数
const dsnTaskSuccessNumber = ref(null) const dsnTaskSuccessNumber = ref(null)
// dsn任务失败数
const dsnTaskFailNumber = ref(null) const dsnTaskFailNumber = ref(null)
// dsn任务错误率
const dsnErrorRate = ref(null) const dsnErrorRate = ref(null)
// itu任务统计数据
const ituTotalTaskNumber = ref(null) const ituTotalTaskNumber = ref(null)
// itu任务成功数
const ituTaskSuccessNumber = ref(null) const ituTaskSuccessNumber = ref(null)
// itu任务失败数
const ituTaskFailNumber = ref(null) const ituTaskFailNumber = ref(null)
// itu任务错误率
const ituErrorRate = ref(null) const ituErrorRate = ref(null)
// st任务统计数据
const stTotalTaskNumber = ref(null) const stTotalTaskNumber = ref(null)
// st任务成功数
const stTaskSuccessNumber = ref(null) const stTaskSuccessNumber = ref(null)
// st任务失败数
const stTaskFailNumber = ref(null) const stTaskFailNumber = ref(null)
// st任务错误率
const stErrorRate = ref(null) const stErrorRate = ref(null)
// esa任务统计数据
const esaTotalCount = ref(null) const esaTotalCount = ref(null)
// esa任务成功数
const esaSuccessCount = ref(null) const esaSuccessCount = ref(null)
// esa任务失败数
const esaErrorRate = ref(null) const esaErrorRate = ref(null)
// esa任务错误率
const esaFailCount = ref(null) const esaFailCount = ref(null)
// 跳转到DSN任务记录页面
const goToDSNTaskRecordPage = () => { const goToDSNTaskRecordPage = () => {
router.push({ router.push({
path: '/osTaskInformation/list', path: '/osTaskInformation/list',
...@@ -181,6 +204,7 @@ const goToDSNTaskRecordPage = () => { ...@@ -181,6 +204,7 @@ const goToDSNTaskRecordPage = () => {
} }
}) })
} }
// 跳转到ITU任务记录页面
const goToITUTaskRecordPage = () => { const goToITUTaskRecordPage = () => {
router.push({ router.push({
path: '/osTaskInformation/list', path: '/osTaskInformation/list',
...@@ -191,6 +215,7 @@ const goToITUTaskRecordPage = () => { ...@@ -191,6 +215,7 @@ const goToITUTaskRecordPage = () => {
} }
}) })
} }
// 跳转到ST任务记录页面
const goToSTTaskRecordPage = () => { const goToSTTaskRecordPage = () => {
router.push({ router.push({
path: '/osTaskInformation/list', path: '/osTaskInformation/list',
...@@ -201,7 +226,7 @@ const goToSTTaskRecordPage = () => { ...@@ -201,7 +226,7 @@ const goToSTTaskRecordPage = () => {
} }
}) })
} }
// 跳转到ESA任务记录页面
const goToESATaskRecordPage = () => { const goToESATaskRecordPage = () => {
router.push({ router.push({
path: '/osTaskInformation/list', path: '/osTaskInformation/list',
...@@ -225,7 +250,7 @@ const getData = async () => { ...@@ -225,7 +250,7 @@ const getData = async () => {
const [ituTask, dsnTask, esaTask, stTask] = await Promise.all(tasks) const [ituTask, dsnTask, esaTask, stTask] = await Promise.all(tasks)
const allTask = await getAllTaskStatistics() const allTask = await getAllTaskStatistics()
// 解析接口返回的数据,更新响应式变量
dsnTotalTaskNumber.value = dsnTask.data.length dsnTotalTaskNumber.value = dsnTask.data.length
dsnTaskSuccessNumber.value = res.data.dsn_now.successCount dsnTaskSuccessNumber.value = res.data.dsn_now.successCount
dsnTaskFailNumber.value = res.data.dsn_now.failCount dsnTaskFailNumber.value = res.data.dsn_now.failCount
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
<script lang="ts" setup> <script lang="ts" setup>
import taskMonitoringCard from './taskCard.vue' import taskMonitoringCard from './taskCard.vue'
// 组件的props定义
defineProps({ defineProps({
title: { title: {
type: String, type: String,
......
<template> <template>
<div> <div>
<!-- 页面标题 -->
<MenuTitle title="状态监控" subtitle="Status Monitor" /> <MenuTitle title="状态监控" subtitle="Status Monitor" />
<div> <div>
<div class="text-left timeStyle" /> <div class="text-left timeStyle" />
<div class="border-100"> <div class="border-100">
<!-- 状态监控组件 -->
<statusMonitor /> <statusMonitor />
</div> </div>
</div> </div>
......
<template> <template>
<div class="sys-content"> <div class="sys-content">
<!-- 页面标题组件 -->
<MenuTitle title="系统管理" subtitle="System Manager" /> <MenuTitle title="系统管理" subtitle="System Manager" />
<!-- 工具栏 -->
<el-card> <el-card>
<div class="btns"> <div class="btns">
<el-button <el-button test-element="userSystem-AddUser" type="primary" v-if="uRole === UserRole.ADMIN" plain
test-element="userSystem-AddUser" @click="openAddUserDialog">创建用户</el-button>
type="primary" <el-button type="danger" plain @click="handleBatchDelete" class=""
v-if="uRole === UserRole.ADMIN" v-if="uRole === UserRole.ADMIN">批量删除</el-button>
plain
@click="openAddUserDialog"
>创建用户</el-button
>
<el-button type="danger" plain @click="handleBatchDelete" class="" v-if="uRole === UserRole.ADMIN"
>批量删除</el-button
>
</div> </div>
</el-card> </el-card>
<!-- 用户数据表格 -->
<div class="table-content"> <div class="table-content">
<el-table <el-table :data="tableData" border :header-cell-style="{ textAlign: 'center' }"
:data="tableData" :cell-style="{ textAlign: 'center' }" :row-style="{ height: '58px' }" @selection-change="handleSelectionChange"
border v-loading="tableLoading" element-loading-background="rgba(48, 65, 86, 0.7)">
:header-cell-style="{ textAlign: 'center' }" <el-table-column type="selection" width="40" :selectable="() => uRole === UserRole.ADMIN"
:cell-style="{ textAlign: 'center' }" v-if="uRole === UserRole.ADMIN" />
:row-style="{ height: '58px' }"
@selection-change="handleSelectionChange"
v-loading="tableLoading"
element-loading-background="rgba(48, 65, 86, 0.7)"
>
<el-table-column
type="selection"
width="40"
:selectable="() => uRole === UserRole.ADMIN"
v-if="uRole === UserRole.ADMIN"
/>
<el-table-column property="number" label="序号" width="55" type="index" /> <el-table-column property="number" label="序号" width="55" type="index" />
<el-table-column property="username" label="用户账号" show-overflow-tooltip /> <el-table-column property="username" label="用户账号" show-overflow-tooltip />
<el-table-column property="nickname" label="用户名称" show-overflow-tooltip /> <el-table-column property="nickname" label="用户名称" show-overflow-tooltip />
...@@ -49,14 +34,8 @@ ...@@ -49,14 +34,8 @@
<el-table-column property="create_time" label="创建时间" width="280" show-overflow-tooltip /> <el-table-column property="create_time" label="创建时间" width="280" show-overflow-tooltip />
<el-table-column label="操作" width="220"> <el-table-column label="操作" width="220">
<template #default="scope"> <template #default="scope">
<el-button <el-button link type="primary" plain @click="handleEdit(scope.row)" id="editUser"
link v-if="uRole === UserRole.ADMIN">
type="primary"
plain
@click="handleEdit(scope.row)"
id="editUser"
v-if="uRole === UserRole.ADMIN"
>
编辑 编辑
</el-button> </el-button>
<el-button link type="danger" plain @click="handleDelete(scope.row)" v-if="uRole === UserRole.ADMIN"> <el-button link type="danger" plain @click="handleDelete(scope.row)" v-if="uRole === UserRole.ADMIN">
...@@ -67,35 +46,18 @@ ...@@ -67,35 +46,18 @@
</el-table-column> </el-table-column>
</el-table> </el-table>
<div class="pagination w-full flex flex-row-reverse pr-4 m-t-4"> <div class="pagination w-full flex flex-row-reverse pr-4 m-t-4">
<Pagination <Pagination :total="pageObj.total" v-model:page="pageObj.pageNo" v-model:limit="pageObj.pageSize"
:total="pageObj.total" @pagination="getUserListData" />
v-model:page="pageObj.pageNo"
v-model:limit="pageObj.pageSize"
@pagination="getUserListData"
/>
</div> </div>
</div> </div>
<!-- 删除弹窗组件 --> <!-- 删除弹窗组件 -->
<deleteDialog <deleteDialog v-model:dialogVisible="showDeleteDialog" @get-user-list="getUserListData" :ids="userIds"
v-model:dialogVisible="showDeleteDialog" :deleteMode="deleteMode" :id="userId" />
@get-user-list="getUserListData"
:ids="userIds"
:deleteMode="deleteMode"
:id="userId"
/>
<!-- 创建用户弹窗组件 --> <!-- 创建用户弹窗组件 -->
<addUserDialog <addUserDialog v-model:dialogVisible="dialogVisible" :mode="mode" :nickName="nickName" :userName="userName"
v-model:dialogVisible="dialogVisible" :id="userId" :userRole="userRole" :userStatus="userStatus" :userPassword="userPassword"
:mode="mode" @get-user-list="getUserListData" />
:nickName="nickName"
:userName="userName"
:id="userId"
:userRole="userRole"
:userStatus="userStatus"
:userPassword="userPassword"
@get-user-list="getUserListData"
/>
</div> </div>
</template> </template>
...@@ -109,18 +71,31 @@ import { DeleteMode } from '@/components/Delete/enum.ts' ...@@ -109,18 +71,31 @@ import { DeleteMode } from '@/components/Delete/enum.ts'
import { AddMode } from './components/enum.ts' import { AddMode } from './components/enum.ts'
import { ElMessage } from 'element-plus' import { ElMessage } from 'element-plus'
import MenuTitle from '@/components/MenuTitle.vue' import MenuTitle from '@/components/MenuTitle.vue'
// 用户id
const userId = ref<number>(-1) const userId = ref<number>(-1)
// 用户id列表(批量删除时使用)
const userIds = ref<number[]>([]) const userIds = ref<number[]>([])
// 用户昵称
const nickName = ref<string>('') const nickName = ref<string>('')
// 用户名
const userName = ref<string>('') const userName = ref<string>('')
// 用户角色
const userRole = ref<number>(0) const userRole = ref<number>(0)
// 用户状态
const userStatus = ref<boolean>(true) const userStatus = ref<boolean>(true)
// 用户密码
const userPassword = ref<string>('') const userPassword = ref<string>('')
// 用户列表数据
const showDeleteDialog = ref(false) const showDeleteDialog = ref(false)
// 删除模式(单个删除或批量删除)
const deleteMode = ref<DeleteMode>(DeleteMode.SINGLE_DELETE) const deleteMode = ref<DeleteMode>(DeleteMode.SINGLE_DELETE)
// 数据展示模式(添加用户或编辑用户)
const dialogVisible = ref<boolean>(false) const dialogVisible = ref<boolean>(false)
// 用户角色枚举
const mode = ref<AddMode>(AddMode.ADD_MODE) const mode = ref<AddMode>(AddMode.ADD_MODE)
// 表格数据
const tableData = ref([]) const tableData = ref([])
// 分页参数
const pageObj = ref({ const pageObj = ref({
total: 0, total: 0,
pageSize: 10, pageSize: 10,
...@@ -164,17 +139,18 @@ const handleSelectionChange = (data: any) => { ...@@ -164,17 +139,18 @@ const handleSelectionChange = (data: any) => {
} }
userIds.value = array userIds.value = array
} }
// 打开添加用户弹窗的方法
const openAddUserDialog = () => { const openAddUserDialog = () => {
mode.value = AddMode.ADD_MODE mode.value = AddMode.ADD_MODE
dialogVisible.value = true dialogVisible.value = true
} }
// 用户列表数据加载状态
const tableLoading = ref(false) const tableLoading = ref(false)
// 获取用户列表数据的方法 // 获取用户列表数据的方法
const getUserListData = async () => { const getUserListData = async () => {
tableLoading.value = true tableLoading.value = true
// 调用接口获取用户列表数据并更新响应式变量
const userList = await getUserList({ const userList = await getUserList({
page: pageObj.value.pageNo, page: pageObj.value.pageNo,
size: pageObj.value.pageSize size: pageObj.value.pageSize
...@@ -183,14 +159,14 @@ const getUserListData = async () => { ...@@ -183,14 +159,14 @@ const getUserListData = async () => {
tableData.value = userList.data.list tableData.value = userList.data.list
pageObj.value.total = userList.data.total pageObj.value.total = userList.data.total
} }
// 用户角色枚举
const uRole = ref<UserRole>(UserRole.NORMAL_USER) const uRole = ref<UserRole>(UserRole.NORMAL_USER)
// 查询用户角色 // 查询用户角色
const getURole = async () => { const getURole = async () => {
const res = await getUserRole() const res = await getUserRole()
uRole.value = res.data uRole.value = res.data
} }
// 组件挂载时获取用户角色和用户列表数据
onMounted(async () => { onMounted(async () => {
await getURole() await getURole()
getUserListData() getUserListData()
...@@ -202,20 +178,24 @@ onMounted(async () => { ...@@ -202,20 +178,24 @@ onMounted(async () => {
.el-button:focus { .el-button:focus {
outline: none; outline: none;
} }
.title { .title {
text-align: left; text-align: left;
font-size: 18px; font-size: 18px;
font-weight: 500; font-weight: 500;
color: white; color: white;
} }
.low-titme { .low-titme {
color: #ccc; color: #ccc;
text-align: left; text-align: left;
margin-left: 20px; margin-left: 20px;
} }
.divider { .divider {
margin-top: 15px; margin-top: 15px;
} }
.btns { .btns {
display: flex; display: flex;
justify-content: end; justify-content: end;
......
<template> <template>
<el-dialog <!-- 新增/修改任务的弹框 -->
v-model="currentVisible" <el-dialog v-model="currentVisible" :title="currentMode === AddMode.ADD_TASK ? '新增' : '修改'" width="710" center
:title="currentMode === AddMode.ADD_TASK ? '新增' : '修改'" align-center @close="handleClose" draggable>
width="710" <!-- 爬虫任务的表单内容 -->
center
align-center
@close="handleClose"
draggable
>
<el-form :model="ruleForm" :rules="rules" ref="ruleFormRef" label-width="100px"> <el-form :model="ruleForm" :rules="rules" ref="ruleFormRef" label-width="100px">
<el-form-item label="任务名称:" v-if="currentMode === AddMode.ADD_TASK" prop="taskName"> <el-form-item label="任务名称:" v-if="currentMode === AddMode.ADD_TASK" prop="taskName">
<el-input v-model="ruleForm.taskName" placeholder="请输入任务名称" style="width: 90%" /> <el-input v-model="ruleForm.taskName" placeholder="请输入任务名称" style="width: 90%" />
</el-form-item> </el-form-item>
<el-form-item label="选择爬虫:" v-if="currentMode === AddMode.ADD_TASK" prop="spiderTypeValue"> <el-form-item label="选择爬虫:" v-if="currentMode === AddMode.ADD_TASK" prop="spiderTypeValue">
<el-select v-model="ruleForm.spiderTypeValue" placeholder="请选择爬虫" style="width: 90%"> <el-select v-model="ruleForm.spiderTypeValue" placeholder="请选择爬虫" style="width: 90%">
<el-option <el-option v-for="item in spiderTypeOptions" :key="item.spider" :label="item.spider" :value="item.spider"
v-for="item in spiderTypeOptions" :id="item.spider" />
:key="item.spider"
:label="item.spider"
:value="item.spider"
:id="item.spider"
/>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="执行频率:"> <el-form-item label="执行频率:">
<!-- <Crontab v-model="ruleForm.cronExpression" style="width: 90%"/> --> <!-- <Crontab v-model="ruleForm.cronExpression" style="width: 90%"/> -->
<div class="gap-units"> <div class="gap-units">
<div class="gap-unit"> <div class="gap-unit">
<el-input-number <el-input-number v-model="exGaps.day" class="gap-ipt" :min="0" :precision="0"
v-model="exGaps.day" size="small"></el-input-number>
class="gap-ipt"
:min="0"
:precision="0"
size="small"
></el-input-number>
<span class="unit-num"></span> <span class="unit-num"></span>
</div> </div>
<div class="gap-unit"> <div class="gap-unit">
<el-input-number <el-input-number v-model="exGaps.hour" class="gap-ipt" :min="0" :precision="0"
v-model="exGaps.hour" size="small"></el-input-number>
class="gap-ipt"
:min="0"
:precision="0"
size="small"
></el-input-number>
<span class="unit-num">小时</span> <span class="unit-num">小时</span>
</div> </div>
<div class="gap-unit"> <div class="gap-unit">
<el-input-number <el-input-number v-model="exGaps.minute" class="gap-ipt" :min="0" :precision="0"
v-model="exGaps.minute" size="small"></el-input-number>
class="gap-ipt"
:min="0"
:precision="0"
size="small"
></el-input-number>
<span class="unit-num">分钟</span> <span class="unit-num">分钟</span>
</div> </div>
<div class="gap-unit"> <div class="gap-unit">
<el-input-number <el-input-number v-model="exGaps.second" class="gap-ipt" :min="0" :precision="2"
v-model="exGaps.second" size="small"></el-input-number>
class="gap-ipt"
:min="0"
:precision="2"
size="small"
></el-input-number>
<span class="unit-num"></span> <span class="unit-num"></span>
</div> </div>
</div> </div>
...@@ -86,16 +56,19 @@ import { AddMode } from "./enum"; ...@@ -86,16 +56,19 @@ import { AddMode } from "./enum";
import type { FormInstance, FormRules } from "element-plus"; import type { FormInstance, FormRules } from "element-plus";
import { ElMessage } from "element-plus"; import { ElMessage } from "element-plus";
import { getSpiderList } from "@/api/system.ts"; import { getSpiderList } from "@/api/system.ts";
// 定义表单数据的类型
interface RuleForm { interface RuleForm {
taskName: string; taskName: string;
spiderTypeValue: string; spiderTypeValue: string;
} }
// 表单验证规则的定义
const ruleFormRef = ref<FormInstance>(); const ruleFormRef = ref<FormInstance>();
// 定义表单验证规则类型
const ruleForm = ref<RuleForm>({ const ruleForm = ref<RuleForm>({
taskName: "", taskName: "",
spiderTypeValue: "", spiderTypeValue: "",
}); });
// 定义组件的类型
interface addDialogPropType { interface addDialogPropType {
dialogVisible: boolean; dialogVisible: boolean;
mode: AddMode; mode: AddMode;
...@@ -104,7 +77,9 @@ interface addDialogPropType { ...@@ -104,7 +77,9 @@ interface addDialogPropType {
spiderType: string; spiderType: string;
options: string; options: string;
} }
// 定义组件的props类型
const props = defineProps<addDialogPropType>(); const props = defineProps<addDialogPropType>();
// 定义表单的验证规则
const rules = ref<FormRules<RuleForm>>({ const rules = ref<FormRules<RuleForm>>({
taskName: [ taskName: [
{ required: true, message: "请输入任务名称", trigger: "blur" }, { required: true, message: "请输入任务名称", trigger: "blur" },
...@@ -124,6 +99,7 @@ const emit = defineEmits(["update:dialogVisible", "confirm", "update:mode", "get ...@@ -124,6 +99,7 @@ const emit = defineEmits(["update:dialogVisible", "confirm", "update:mode", "get
const currentVisible = ref(props.dialogVisible); const currentVisible = ref(props.dialogVisible);
const currentMode = ref(props.mode); const currentMode = ref(props.mode);
const spiderTypeOptions = ref(); const spiderTypeOptions = ref();
// 任务参数
const taskParams = ref({ const taskParams = ref({
scrapyd_server_id: "1", scrapyd_server_id: "1",
schedule_type: "0", schedule_type: "0",
...@@ -132,6 +108,7 @@ const taskParams = ref({ ...@@ -132,6 +108,7 @@ const taskParams = ref({
// 关闭的方法 // 关闭的方法
const handleClose = () => { const handleClose = () => {
// 清空表单数据和验证状态
ruleForm.value.taskName = ""; ruleForm.value.taskName = "";
ruleForm.value.spiderTypeValue; ruleForm.value.spiderTypeValue;
ruleFormRef.value?.resetFields(); ruleFormRef.value?.resetFields();
...@@ -200,7 +177,7 @@ const checkExGap = (exGaps: any) => { ...@@ -200,7 +177,7 @@ const checkExGap = (exGaps: any) => {
return true; return true;
} }
}; };
// 获取爬虫任务列表的方法
const getData = async () => { const getData = async () => {
const res = await getSpiderList({ scrapydServerId: "1", project: "spiders" }); const res = await getSpiderList({ scrapydServerId: "1", project: "spiders" });
spiderTypeOptions.value = res.data; spiderTypeOptions.value = res.data;
...@@ -221,6 +198,7 @@ watch( ...@@ -221,6 +198,7 @@ watch(
} }
); );
// 监听props.mode变化,同步给组件内部currentMode
watch( watch(
() => props.mode, () => props.mode,
(newVal) => { (newVal) => {
...@@ -228,12 +206,15 @@ watch( ...@@ -228,12 +206,15 @@ watch(
} }
); );
// 监听currentMode变化,同步给父组件,这样父组件才能知道当前是新增还是修改模式,以便在打开对话框时进行相应的处理
watch( watch(
() => currentMode.value, () => currentMode.value,
(newVal) => { (newVal) => {
emit("update:mode", newVal); emit("update:mode", newVal);
} }
); );
// 监听props.exGap变化,同步给组件内部的exGaps
watch( watch(
() => props.exGap, () => props.exGap,
(newVal) => { (newVal) => {
...@@ -244,6 +225,7 @@ watch( ...@@ -244,6 +225,7 @@ watch(
}, },
{ immediate: true } { immediate: true }
); );
// 组件挂载时获取爬虫任务列表数据
onMounted(() => { onMounted(() => {
getData(); getData();
}); });
...@@ -281,6 +263,7 @@ onMounted(() => { ...@@ -281,6 +263,7 @@ onMounted(() => {
align-items: center; align-items: center;
margin-right: 10px; margin-right: 10px;
} }
.unit-num { .unit-num {
color: white; color: white;
} }
......
...@@ -19,12 +19,16 @@ import { ref, watch } from 'vue' ...@@ -19,12 +19,16 @@ import { ref, watch } from 'vue'
import { defineProps } from 'vue'; import { defineProps } from 'vue';
import { deleteSpiderTask } from '@/api/spiderTask.ts' import { deleteSpiderTask } from '@/api/spiderTask.ts'
import { ElMessage } from 'element-plus'; import { ElMessage } from 'element-plus';
// 定义删除对话框的数据类型
interface deleteDialogPropType { interface deleteDialogPropType {
dialogVisible: boolean, dialogVisible: boolean,
jobId: string jobId: string
} }
// 定义组件的props类型
const props = defineProps<deleteDialogPropType>() const props = defineProps<deleteDialogPropType>()
// 定义组件的事件
const emit = defineEmits(['update:dialogVisible', 'confirm', 'getUserList', 'update:deleteMode']) const emit = defineEmits(['update:dialogVisible', 'confirm', 'getUserList', 'update:deleteMode'])
// 删除对话框的显示状态
const deleteDialogVisible = ref(props.dialogVisible) const deleteDialogVisible = ref(props.dialogVisible)
// 删除方法 // 删除方法
const handleDelelte = async () => { const handleDelelte = async () => {
......
<!-- 任务执行统计卡片组件 --> <!-- 任务执行统计卡片组件 -->
<template> <template>
<div> <div>
<!-- 搜索区域 -->
<TableSearch> <TableSearch>
<div class="form-content"> <div class="form-content">
<div class="ipt"> <div class="ipt">
<span style="color: white">选择爬虫:</span> <span style="color: white">选择爬虫:</span>
<el-select <el-select v-model="searchCondition.spiders" placeholder="请选择" style="width: 220px"
v-model="searchCondition.spiders" :disabled="!taskSelectOptions.length">
placeholder="请选择" <el-option v-for="item in taskSelectOptions || []" :key="item?.spider" :label="item?.spider || '未知'"
style="width: 220px" :value="item?.spider" />
:disabled="!taskSelectOptions.length"
>
<el-option
v-for="item in taskSelectOptions || []"
:key="item?.spider"
:label="item?.spider || '未知'"
:value="item?.spider"
/>
</el-select> </el-select>
</div> </div>
<div class="btns"> <div class="btns">
...@@ -26,34 +19,27 @@ ...@@ -26,34 +19,27 @@
</div> </div>
</div> </div>
</TableSearch> </TableSearch>
<!-- 卡片信息 -->
<div class="cardStyle" v-loading="isLoading" element-loading-background="rgba(48, 65, 86, 0.7)"> <div class="cardStyle" v-loading="isLoading" element-loading-background="rgba(48, 65, 86, 0.7)">
<div v-if="taskList.length === 0 && !isLoading" class="empty-tip">暂无任务数据</div> <div v-if="taskList.length === 0 && !isLoading" class="empty-tip">暂无任务数据</div>
<div class="taskCard p-2" v-for="task in taskList || []" :key="task?.id || task?.taskId"> <div class="taskCard p-2" v-for="task in taskList || []" :key="task?.id || task?.taskId">
<div class="header"> <div class="header">
<span class="task-name" <span class="task-name">任务名称: {{ (task?.kwargs?.options && JSON.parse(task.kwargs.options).jobName) || "无名称"
>任务名称: {{ (task?.kwargs?.options && JSON.parse(task.kwargs.options).jobName) || "无名称" }}</span }}</span>
>
<el-divider style="margin-top: 5px"></el-divider> <el-divider style="margin-top: 5px"></el-divider>
</div> </div>
<div class="btns"> <div class="btns">
<el-button plain type="primary" @click="editTask(task)" class="editButton" :disabled="!task?.id" <el-button plain type="primary" @click="editTask(task)" class="editButton"
>编辑</el-button :disabled="!task?.id">编辑</el-button>
> <el-button plain type="danger" @click="deleteTask(task)" class="deleteButton"
<el-button plain type="danger" @click="deleteTask(task)" class="deleteButton" :disabled="!task?.id" :disabled="!task?.id">删除</el-button>
>删除</el-button
>
</div> </div>
<div class="info"> <div class="info">
<div class="item"> <div class="item">
<span class="wordStyle">启用/停止: </span> <span class="wordStyle">启用/停止: </span>
<el-switch <el-switch v-model="task.status" :active-value="'running'" :inactive-value="'paused'"
v-model="task.status" @change="(newStatus: any) => changeStatus(task, newStatus)" :disabled="!task?.id" />
:active-value="'running'"
:inactive-value="'paused'"
@change="(newStatus: any) => changeStatus(task, newStatus)"
:disabled="!task?.id"
/>
</div> </div>
<div class="item"> <div class="item">
<span class="wordStyle">爬虫名称: </span> <span class="wordStyle">爬虫名称: </span>
...@@ -61,9 +47,9 @@ ...@@ -61,9 +47,9 @@
</div> </div>
<div class="item"> <div class="item">
<span class="wordStyle">执行频率: </span> <span class="wordStyle">执行频率: </span>
<span class="wordStyle" <span class="wordStyle">{{
>{{ `${task.kwargs.interval[3]} 天 ${task.kwargs.interval[2]} 小时 ${task.kwargs.interval[1]} 分钟
`${task.kwargs.interval[3]} 天 ${task.kwargs.interval[2]} 小时 ${task.kwargs.interval[1]} 分钟 ${task.kwargs.interval[0]} 秒` ${task.kwargs.interval[0]} 秒`
}} }}
</span> </span>
</div> </div>
...@@ -74,17 +60,10 @@ ...@@ -74,17 +60,10 @@
</div> </div>
</div> </div>
</div> </div>
<addTaskDialog <addTaskDialog v-model:dialogVisible="showTaskDialog" @confirm="handleEdit" :mode="editMode" @getTaskList="getData"
v-model:dialogVisible="showTaskDialog" :jobId="jobId" :exGap="frequency || []" :spiderType="belongSpiderType || ''" :options="taskOptions || ''" />
@confirm="handleEdit"
:mode="editMode"
@getTaskList="getData"
:jobId="jobId"
:exGap="frequency || []"
:spiderType="belongSpiderType || ''"
:options="taskOptions || ''"
/>
<!-- 删除对话框 -->
<deleteDialog v-model:dialogVisible="showDeleteDialog" @get-user-list="getData" :jobId="jobId" :disabled="!jobId" /> <deleteDialog v-model:dialogVisible="showDeleteDialog" @get-user-list="getData" :jobId="jobId" :disabled="!jobId" />
</div> </div>
</template> </template>
...@@ -101,7 +80,7 @@ import { ElMessage } from "element-plus"; ...@@ -101,7 +80,7 @@ import { ElMessage } from "element-plus";
import { getSpiderList } from "@/api/system.ts"; import { getSpiderList } from "@/api/system.ts";
import formatExactLargeNum from "@/utils/formatExactLargeNum"; import formatExactLargeNum from "@/utils/formatExactLargeNum";
import TableSearch from "@/components/TableSearch.vue"; import TableSearch from "@/components/TableSearch.vue";
// 定义组件的props类型
const props = defineProps({ const props = defineProps({
spiderType: { spiderType: {
type: String, type: String,
...@@ -119,29 +98,41 @@ const props = defineProps({ ...@@ -119,29 +98,41 @@ const props = defineProps({
// 所有响应式变量初始化时避免 undefined // 所有响应式变量初始化时避免 undefined
const taskSelectOptions = ref<any[]>([]); // 初始化为空数组 const taskSelectOptions = ref<any[]>([]); // 初始化为空数组
// 搜索条件
const searchCondition = ref({ const searchCondition = ref({
spiders: "", spiders: "",
options: "", options: "",
}); });
// 任务名称
const taskName = ref(""); const taskName = ref("");
const taskValue = ref(""); // 所属爬虫类型
const belongSpiderType = ref(""); const belongSpiderType = ref("");
// 路由对象
const router = useRouter(); const router = useRouter();
const frequency = ref([]); // 初始化为空字符串,解决 cron 类型错误 // 初始化为空字符串,解决 cron 类型错误
const frequency = ref([]);
// 编辑模式和删除模式的响应式变量
const editMode = ref(AddMode.UPDATE_TASK); const editMode = ref(AddMode.UPDATE_TASK);
// 删除模式默认为单个删除
const deleteMode = ref(DeleteMode.SINGLE_DELETE); const deleteMode = ref(DeleteMode.SINGLE_DELETE);
// 删除对话框的显示状态
const showDeleteDialog = ref(false); const showDeleteDialog = ref(false);
// 任务对话框的显示状态
const showTaskDialog = ref(false); const showTaskDialog = ref(false);
const taskSwitch = ref(false); // 任务选项的响应式变量,初始化为字符串类型的空对象
const taskOptions = ref(""); const taskOptions = ref("");
// 任务id的响应式变量,初始化为字符串类型的空字符串
const jobId = ref(""); const jobId = ref("");
// 任务列表数据的响应式变量,初始化为数组类型的空数组
const taskList = ref<any[]>([]); const taskList = ref<any[]>([]);
const isLoading = ref(false); // 新增专门的加载状态变量 // 新增专门的加载状态变量
const isLoading = ref(false);
// 删除任务的方法 // 删除任务的方法
const deleteTask = (task: any) => { const deleteTask = (task: any) => {
if (!task?.id) return; // 避免 task 为 undefined // 避免 task 为 undefined
if (!task?.id) return;
jobId.value = task.id; jobId.value = task.id;
deleteMode.value = DeleteMode.SINGLE_DELETE; deleteMode.value = DeleteMode.SINGLE_DELETE;
showDeleteDialog.value = true; showDeleteDialog.value = true;
...@@ -149,7 +140,8 @@ const deleteTask = (task: any) => { ...@@ -149,7 +140,8 @@ const deleteTask = (task: any) => {
// 编辑任务的方法 // 编辑任务的方法
const editTask = (task: any) => { const editTask = (task: any) => {
if (!task?.id) return; // 避免 task 为 undefined // 避免 task 为 undefined
if (!task?.id) return;
jobId.value = task.id; jobId.value = task.id;
// 安全处理 JSON 字符串,避免解析失败 // 安全处理 JSON 字符串,避免解析失败
try { try {
...@@ -158,15 +150,18 @@ const editTask = (task: any) => { ...@@ -158,15 +150,18 @@ const editTask = (task: any) => {
taskOptions.value = "{}"; taskOptions.value = "{}";
} }
belongSpiderType.value = task?.kwargs?.spider || ""; belongSpiderType.value = task?.kwargs?.spider || "";
frequency.value = task?.kwargs?.interval || []; // 兜底空字符串 // 兜底空字符串
frequency.value = task?.kwargs?.interval || [];
editMode.value = AddMode.UPDATE_TASK; editMode.value = AddMode.UPDATE_TASK;
showTaskDialog.value = true; showTaskDialog.value = true;
}; };
// 启动与停止任务的方法 // 启动与停止任务的方法
const changeStatus = async (task: any, newStatus: string) => { const changeStatus = async (task: any, newStatus: string) => {
if (!task?.id) return; // 避免 task 为 undefined // 避免 task 为 undefined
if (!task?.id) return;
try { try {
// 根据新的状态调用不同的接口,并提供用户反馈
if (newStatus === "running") { if (newStatus === "running") {
await resumeSpiderTask({ job_id: task.id }); await resumeSpiderTask({ job_id: task.id });
ElMessage.success("任务已启动"); ElMessage.success("任务已启动");
...@@ -205,16 +200,21 @@ const getData = async () => { ...@@ -205,16 +200,21 @@ const getData = async () => {
// 遍历赋值时兜底 // 遍历赋值时兜底
taskList.value = taskData.map((item: any) => ({ taskList.value = taskData.map((item: any) => ({
...item, ...item,
count: countData[item?.id] ?? 0, // 执行次数兜底 0 // 执行次数兜底 0
status: item?.status || "paused", // 状态兜底 count: countData[item?.id] ?? 0,
kwargs: item?.kwargs || {}, // kwargs 兜底空对象 // 状态兜底
status: item?.status || "paused",
// kwargs 兜底空对象
kwargs: item?.kwargs || {},
})); }));
} catch (err) { } catch (err) {
ElMessage.error("获取任务列表失败"); ElMessage.error("获取任务列表失败");
console.error(err); console.error(err);
taskList.value = []; // 错误时置空数组 // 错误时置空数组
taskList.value = [];
} finally { } finally {
isLoading.value = false; // 结束加载 // 结束加载
isLoading.value = false;
} }
}; };
...@@ -223,6 +223,7 @@ const resetData = async () => { ...@@ -223,6 +223,7 @@ const resetData = async () => {
searchCondition.value.spiders = ""; searchCondition.value.spiders = "";
isLoading.value = true; isLoading.value = true;
try { try {
// 重置时获取所有任务列表数据,避免因搜索条件导致的空数据问题
const res = await getSpiderTaskList({ spiders: [], options: JSON.stringify({ jobName: taskName.value }) }); const res = await getSpiderTaskList({ spiders: [], options: JSON.stringify({ jobName: taskName.value }) });
const resId = await getTaskCount({}); const resId = await getTaskCount({});
const taskData = res?.data || []; const taskData = res?.data || [];
...@@ -250,6 +251,7 @@ const search = async () => { ...@@ -250,6 +251,7 @@ const search = async () => {
} }
isLoading.value = true; isLoading.value = true;
try { try {
// 搜索时根据选择的爬虫类型和任务名称获取任务列表数据,避免因搜索条件导致的空数据问题
const res = await getSpiderTaskList({ const res = await getSpiderTaskList({
spiders: [searchCondition.value.spiders], spiders: [searchCondition.value.spiders],
options: JSON.stringify({ jobName: taskName.value }), options: JSON.stringify({ jobName: taskName.value }),
...@@ -276,14 +278,15 @@ const search = async () => { ...@@ -276,14 +278,15 @@ const search = async () => {
const getSpiderTypeList = async () => { const getSpiderTypeList = async () => {
try { try {
const res = await getSpiderList({ scrapydServerId: "1", project: "spiders" }); const res = await getSpiderList({ scrapydServerId: "1", project: "spiders" });
taskSelectOptions.value = res?.data || []; // 兜底空数组 // 兜底空数组
taskSelectOptions.value = res?.data || [];
} catch (err) { } catch (err) {
ElMessage.error("获取爬虫列表失败"); ElMessage.error("获取爬虫列表失败");
console.error(err); console.error(err);
taskSelectOptions.value = []; taskSelectOptions.value = [];
} }
}; };
// 挂载时获取任务列表数据和爬虫类型列表数据
onMounted(() => { onMounted(() => {
if (props.spiderType !== "") { if (props.spiderType !== "") {
searchCondition.value.spiders = props.spiderType; searchCondition.value.spiders = props.spiderType;
...@@ -297,9 +300,11 @@ onMounted(() => { ...@@ -297,9 +300,11 @@ onMounted(() => {
:deep(.el-select__selected-item) { :deep(.el-select__selected-item) {
color: white !important; color: white !important;
} }
:deep(.el-form-item__label) { :deep(.el-form-item__label) {
color: white; color: white;
} }
.cardStyle { .cardStyle {
padding: 18px; padding: 18px;
gap: 15px; gap: 15px;
......
<!-- 任务信息页面 -->
<template> <template>
<div> <div>
<!-- 菜单标题 -->
<MenuTitle title="任务信息" subtitle="Task Information" /> <MenuTitle title="任务信息" subtitle="Task Information" />
<div class="backStyle" v-if="route.query.jump === 'yes'" @click="goToTaskInformation" /> <div class="backStyle" v-if="route.query.jump === 'yes'" @click="goToTaskInformation" />
<div class="m-t-8" /> <div class="m-t-8" />
<div> <div>
<!-- 任务卡片 -->
<taskCard :spiderType="spiderType" failTask="10" unusualTask="1" /> <taskCard :spiderType="spiderType" failTask="10" unusualTask="1" />
</div> </div>
</div> </div>
...@@ -16,10 +19,12 @@ import { useRouter } from "vue-router"; ...@@ -16,10 +19,12 @@ import { useRouter } from "vue-router";
import { useRoute } from "vue-router"; import { useRoute } from "vue-router";
import MenuTitle from "@/components/MenuTitle.vue"; import MenuTitle from "@/components/MenuTitle.vue";
// 从路由参数中获取爬虫类型
const route = useRoute(); const route = useRoute();
const router = useRouter(); const router = useRouter();
const spiderType = ref<any>(route.query.spiderType); const spiderType = ref<any>(route.query.spiderType);
// 跳转到任务信息页面的方法
const goToTaskInformation = () => { const goToTaskInformation = () => {
if (route.query.page === "spiderManager") { if (route.query.page === "spiderManager") {
router.push({ path: "/osSpiderManager/list" }); router.push({ path: "/osSpiderManager/list" });
......
<!-- 任务执行记录页面 -->
<template> <template>
<div> <div>
<!-- 页面标题 -->
<MenuTitle title="任务执行记录" subtitle="Task Record" /> <MenuTitle title="任务执行记录" subtitle="Task Record" />
<div class="backStyle" v-if="route.query.jump === 'yes'" @click="goToStatus" /> <div class="backStyle" v-if="route.query.jump === 'yes'" @click="goToStatus" />
<div class="m-t-8" /> <div class="m-t-8" />
<!-- 搜索工具栏 -->
<table-search> <table-search>
<div class="form-content"> <div class="form-content">
<div class="timer"> <div class="timer">
<span style="color: white">采集日期:</span> <span style="color: white">采集日期:</span>
<el-config-provider :locale="zhCn"> <el-config-provider :locale="zhCn">
<el-date-picker <el-date-picker v-model="timeValue" type="daterange" start-placeholder="开始日期" end-placeholder="结束日期"
v-model="timeValue" format="YYYY-MM-DD" date-format="YYYY/MM/DD ddd" time-format="A hh:mm:ss" value-format="YYYY-MM-DD"
type="daterange" style="width: 250px" />
start-placeholder="开始日期"
end-placeholder="结束日期"
format="YYYY-MM-DD"
date-format="YYYY/MM/DD ddd"
time-format="A hh:mm:ss"
value-format="YYYY-MM-DD"
style="width: 250px"
/>
</el-config-provider> </el-config-provider>
</div> </div>
<div class="spider w-[300px] flex items-center"> <div class="spider w-[300px] flex items-center">
<span style="color: white" class="w-[100px]">任务名称:</span> <span style="color: white" class="w-[100px]">任务名称:</span>
<el-select v-model="jobname" placeholder="请选择任务名称"> <el-select v-model="jobname" placeholder="请选择任务名称">
<el-option <el-option v-for="item in jobNameOptions" :key="item.value" :label="item.label"
v-for="item in jobNameOptions" :value="item.value"></el-option>
:key="item.value"
:label="item.label"
:value="item.value"
></el-option>
</el-select> </el-select>
</div> </div>
<div class="spider w-[300px] flex items-center"> <div class="spider w-[300px] flex items-center">
<span style="color: white" class="w-[100px]">所属爬虫:</span> <span style="color: white" class="w-[100px]">所属爬虫:</span>
<el-select v-model="spidername" placeholder="请选择爬虫"> <el-select v-model="spidername" placeholder="请选择爬虫">
<el-option <el-option v-for="item in spideOptions" :key="item.value" :label="item.label"
v-for="item in spideOptions" :value="item.value"></el-option>
:key="item.value"
:label="item.label"
:value="item.value"
></el-option>
</el-select> </el-select>
</div> </div>
<div class="btns"> <div class="btns">
...@@ -49,17 +36,11 @@ ...@@ -49,17 +36,11 @@
</div> </div>
</div> </div>
</table-search> </table-search>
<!-- 任务执行记录表格数据 -->
<div class="table-content"> <div class="table-content">
<div> <div>
<el-table <el-table v-loading="tableLoading" element-loading-background="rgba(48, 65, 86, 0.7)" :data="tableData"
v-loading="tableLoading" style="width: 100%" border :header-cell-style="{ textAlign: 'center' }" :cell-style="{ textAlign: 'center' }">
element-loading-background="rgba(48, 65, 86, 0.7)"
:data="tableData"
style="width: 100%"
border
:header-cell-style="{ textAlign: 'center' }"
:cell-style="{ textAlign: 'center' }"
>
<el-table-column property="number" label="序号" width="55" type="index" /> <el-table-column property="number" label="序号" width="55" type="index" />
<el-table-column label="任务名称" show-overflow-tooltip> <el-table-column label="任务名称" show-overflow-tooltip>
<template #default="scope"> <template #default="scope">
...@@ -93,13 +74,8 @@ ...@@ -93,13 +74,8 @@
</el-table> </el-table>
</div> </div>
<div class="pagination w-full flex flex-row-reverse pr-4 m-t-4"> <div class="pagination w-full flex flex-row-reverse pr-4 m-t-4">
<Pagination <Pagination :total="pageObj.total" v-model:page="pageObj.pageNo" v-model:limit="pageObj.pageSize"
:total="pageObj.total" @pagination="searchData" v-model:pagerCount="pageObj.pagerCount" />
v-model:page="pageObj.pageNo"
v-model:limit="pageObj.pageSize"
@pagination="searchData"
v-model:pagerCount="pageObj.pagerCount"
/>
</div> </div>
</div> </div>
</div> </div>
...@@ -129,14 +105,16 @@ const route = useRoute() ...@@ -129,14 +105,16 @@ const route = useRoute()
const router = useRouter() const router = useRouter()
//初始数据为近七天 //初始数据为近七天
const timeValue = ref<string[]>([]) const timeValue = ref<string[]>([])
// 表格数据
const tableData = ref([]) const tableData = ref([])
// 分页参数
const pageObj = ref({ const pageObj = ref({
total: 10, total: 10,
pageSize: 10, pageSize: 10,
pageNo: 1, pageNo: 1,
pagerCount: 5 pagerCount: 5
}) })
// 跳转至状态监控页面的方法
const goToStatus = () => { const goToStatus = () => {
if (route.query.mode === '状态监控') { if (route.query.mode === '状态监控') {
router.push({ router.push({
...@@ -148,7 +126,7 @@ const goToStatus = () => { ...@@ -148,7 +126,7 @@ const goToStatus = () => {
}) })
} }
} }
// 爬虫名称下拉框选项
const spideOptions = [ const spideOptions = [
{ {
label: 'dsn_now', label: 'dsn_now',
...@@ -176,6 +154,7 @@ const tableLoading = ref(false) ...@@ -176,6 +154,7 @@ const tableLoading = ref(false)
//重置查询 //重置查询
const resetQuery = () => { const resetQuery = () => {
// 重置查询条件
timeValue.value = [] timeValue.value = []
spidername.value = '' spidername.value = ''
jobname.value = '' jobname.value = ''
...@@ -190,6 +169,7 @@ const taskList = ref([]) ...@@ -190,6 +169,7 @@ const taskList = ref([])
const getTaskList = async () => { const getTaskList = async () => {
const res = await getSpiderTaskList({}) const res = await getSpiderTaskList({})
taskList.value = res.data taskList.value = res.data
// 根据任务列表数据构建任务名称下拉框选项
jobNameOptions.value = taskList.value jobNameOptions.value = taskList.value
.filter((task: any) => task.id) .filter((task: any) => task.id)
.map((task: any) => ({ .map((task: any) => ({
...@@ -201,9 +181,10 @@ const getTaskList = async () => { ...@@ -201,9 +181,10 @@ const getTaskList = async () => {
// 获取任务执行记录列表 // 获取任务执行记录列表
const getData = async () => { const getData = async () => {
let resTime: any[] = [] let resTime: any[] = []
// 如果时间范围不为空,则将时间范围转换为字符串格式并添加到请求参数中
resTime.push(dayjs().subtract(7, 'day').format('YYYY-MM-DD HH:mm:ss')) resTime.push(dayjs().subtract(7, 'day').format('YYYY-MM-DD HH:mm:ss'))
resTime.push(dayjs().format('YYYY-MM-DD HH:mm:ss')) resTime.push(dayjs().format('YYYY-MM-DD HH:mm:ss'))
// 根据选择的爬虫类型和任务名称获取任务执行记录列表数据,避免因查询条件导致的空数据问题
tableLoading.value = true tableLoading.value = true
const res = await getSpiderTaskRecord({ const res = await getSpiderTaskRecord({
page: pageObj.value.pageNo, page: pageObj.value.pageNo,
...@@ -211,11 +192,13 @@ const getData = async () => { ...@@ -211,11 +192,13 @@ const getData = async () => {
status: 'total', status: 'total',
times: resTime times: resTime
}) })
// 根据接口返回的数据更新表格数据和分页参数
pageObj.value.total = res.data.total pageObj.value.total = res.data.total
tableData.value = res.data.list tableData.value = res.data.list
tableLoading.value = false tableLoading.value = false
} }
// 爬虫名称和任务名称
const spidername = ref('') const spidername = ref('')
const jobname = ref('') const jobname = ref('')
...@@ -228,7 +211,9 @@ const searchData = async () => { ...@@ -228,7 +211,9 @@ const searchData = async () => {
resTime.push(dayjs(startTime).format('YYYY-MM-DD HH:mm:ss')) resTime.push(dayjs(startTime).format('YYYY-MM-DD HH:mm:ss'))
resTime.push(dayjs(endTime).format('YYYY-MM-DD HH:mm:ss')) resTime.push(dayjs(endTime).format('YYYY-MM-DD HH:mm:ss'))
} }
// 打开表格加载状态
tableLoading.value = true tableLoading.value = true
// 发送请求获取数据
const res = await getSpiderTaskRecord({ const res = await getSpiderTaskRecord({
page: pageObj.value.pageNo, page: pageObj.value.pageNo,
size: pageObj.value.pageSize, size: pageObj.value.pageSize,
...@@ -237,11 +222,13 @@ const searchData = async () => { ...@@ -237,11 +222,13 @@ const searchData = async () => {
schedule_job_id: jobname.value, schedule_job_id: jobname.value,
times: resTime times: resTime
}) })
// 根据接口返回的数据更新表格数据和分页参数
pageObj.value.total = res.data.total pageObj.value.total = res.data.total
tableData.value = res.data.list tableData.value = res.data.list
tableLoading.value = false tableLoading.value = false
} }
// 挂载时获取任务执行记录列表数据
onMounted(() => { onMounted(() => {
getData() getData()
getTaskList() getTaskList()
...@@ -252,6 +239,7 @@ onMounted(() => { ...@@ -252,6 +239,7 @@ onMounted(() => {
:deep(.el-form-item__label) { :deep(.el-form-item__label) {
color: white; color: white;
} }
/* 工具栏样式 */ /* 工具栏样式 */
.toolbarStyle { .toolbarStyle {
background-image: url('@/assets/picture/box3.png'); background-image: url('@/assets/picture/box3.png');
...@@ -301,6 +289,7 @@ onMounted(() => { ...@@ -301,6 +289,7 @@ onMounted(() => {
text-align: left; text-align: left;
margin-left: 20px; margin-left: 20px;
} }
.divider { .divider {
margin-top: 15px; margin-top: 15px;
} }
...@@ -313,6 +302,7 @@ onMounted(() => { ...@@ -313,6 +302,7 @@ onMounted(() => {
align-items: center; align-items: center;
padding: 0 30px; padding: 0 30px;
} }
.btns { .btns {
position: absolute; position: absolute;
right: 30px; right: 30px;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment