Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
F
fk-spider-web
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
周田
fk-spider-web
Commits
e3e5939c
Commit
e3e5939c
authored
Dec 10, 2025
by
周田
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'liucan' into 'main'
fix:修改监控状态页面错误日志弹窗标题为"错误详情",任务执行记录页面优先加载当日数据 See merge request
!15
parents
1d23619c
0859477c
Show whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
147 additions
and
102 deletions
+147
-102
.env.development
.env.development
+2
-0
apiPaths.ts
src/api/apiPaths.ts
+4
-2
system.ts
src/api/system.ts
+19
-1
AppMain.vue
src/layout/components/AppMain.vue
+33
-1
permission.ts
src/permission.ts
+5
-5
NoItem.vue
src/views/os-spiderManager/components/NoItem.vue
+3
-3
index.vue
src/views/os-spiderManager/index.vue
+48
-50
errorMessageChart.vue
src/views/os-status/components/errorMessageChart.vue
+11
-4
taskCard.vue
src/views/os-taskInformation/components/taskCard.vue
+2
-32
index.vue
src/views/os-taskRecord/index.vue
+20
-4
No files found.
.env.development
View file @
e3e5939c
# 开发环境配置
VITE_APP_BASE_API = '/api'
VITE_APP_TITLE = 'Spider Admin Pro'
VITE_WEBSOCKET_API = "http://192.168.3.10:5001/"
\ No newline at end of file
src/api/apiPaths.ts
View file @
e3e5939c
...
...
@@ -97,8 +97,10 @@ export const spiderTaskApi = {
resumeJob
:
"/schedule/resumeJob"
,
jobDetail
:
"/schedule/jobDetail"
,
taskCount
:
"/schedule/getAllJobCount"
,
addSateNo
:
"/schedule/resetNoradID"
,
getSateIdList
:
"/schedule/getNoradIDList"
,
addSateNo
:
"/noradId/add"
,
getSateIdList
:
"/noradId/list"
,
deleteSateNoList
:
"/noradId/delete"
,
addSateNoList
:
"/noradId/batchAdd"
,
}
as
const
;
// 爬虫数据相关接口
...
...
src/api/system.ts
View file @
e3e5939c
...
...
@@ -62,7 +62,7 @@ export function getSpiderList(data: UserQueryParams) {
}
//添加卫星编号
export
function
addSateNo
(
data
:
{
id
:
string
[]
})
{
export
function
addSateNo
(
data
:
{
norad_id
:
string
})
{
return
request
({
url
:
spiderTaskApi
.
addSateNo
,
method
:
POST
,
...
...
@@ -70,6 +70,24 @@ export function addSateNo(data: { id: string[] }) {
})
as
unknown
as
Promise
<
ApiResponse
>
;
}
//批量删除编号
export
function
deleteSateNoList
(
data
:
{
norad_id
:
string
[]
})
{
return
request
({
url
:
spiderTaskApi
.
deleteSateNoList
,
method
:
POST
,
data
,
})
as
unknown
as
Promise
<
ApiResponse
>
;
}
//批量添加编号
export
function
addSateNoList
(
data
:
{
norad_id
:
string
[]
})
{
return
request
({
url
:
spiderTaskApi
.
addSateNoList
,
method
:
POST
,
data
,
})
as
unknown
as
Promise
<
ApiResponse
>
;
}
//获取编号列表
export
function
getSateIdList
()
{
return
request
({
...
...
src/layout/components/AppMain.vue
View file @
e3e5939c
<
script
setup
lang=
"ts"
>
import
{
computed
}
from
"vue"
;
import
{
ElNotification
}
from
"element-plus"
;
import
{
Manager
,
Socket
}
from
"socket.io-client"
;
import
{
computed
,
onMounted
,
onUnmounted
,
ref
}
from
"vue"
;
import
{
useRoute
}
from
"vue-router"
;
const
route
=
useRoute
();
const
key
=
computed
(()
=>
route
.
path
);
const
socket
=
ref
<
Socket
|
null
>
(
null
);
//错误消息通知
const
handleErrorMsgNotify
=
()
=>
{
//websocket连接
const
manager
=
new
Manager
(
import
.
meta
.
env
.
VITE_WEBSOCKET_API
);
socket
.
value
=
manager
.
socket
(
"/"
);
//收到错误通知
socket
.
value
.
on
(
"error_message"
,
onErrorMsg
);
};
//错误消息处理
const
onErrorMsg
=
({
message
}:
{
message
:
any
})
=>
{
ElNotification
({
title
:
"爬虫错误提示"
,
message
,
type
:
"error"
,
});
};
onMounted
(()
=>
{
handleErrorMsgNotify
();
});
onUnmounted
(()
=>
{
if
(
socket
.
value
)
{
socket
.
value
.
disconnect
();
}
});
</
script
>
<
template
>
...
...
src/permission.ts
View file @
e3e5939c
import
router
from
'./router'
import
{
useUserStore
}
from
'./store/user'
import
{
getToken
}
from
'@/utils/auth'
import
{
useUserStore
}
from
'./store/user'
import
{
getToken
}
from
'@/utils/auth'
import
NProgress
from
'nprogress'
import
'nprogress/nprogress.css'
// NProgress 配置
NProgress
.
configure
({
showSpinner
:
false
})
NProgress
.
configure
({
showSpinner
:
false
})
// 白名单路由
const
whiteList
=
[
'/login'
,
'/404'
]
...
...
@@ -15,12 +15,12 @@ router.beforeEach(async (to, from, next) => {
NProgress
.
start
()
const
userStore
=
useUserStore
()
const
hasToken
=
getToken
()
const
hasToken
=
getToken
();
if
(
hasToken
)
{
if
(
to
.
path
===
'/login'
)
{
// 已登录,重定向到首页
next
({
path
:
'/'
})
next
({
path
:
'/'
})
NProgress
.
done
()
}
else
{
// 确定用户是否有用户信息
...
...
src/views/os-spiderManager/components/NoItem.vue
View file @
e3e5939c
...
...
@@ -10,14 +10,14 @@
import
{
ref
,
watch
}
from
"vue"
;
const
props
=
defineProps
<
{
No
:
string
|
number
;
No
:
string
;
resetSelected
?:
boolean
;
}
>
();
const
isSelected
=
ref
(
false
);
const
emit
=
defineEmits
<
{
(
e
:
"addNo"
,
sateNo
:
string
|
number
):
void
;
(
e
:
"delNo"
,
sateNo
:
string
|
number
):
void
;
(
e
:
"addNo"
,
sateNo
:
string
):
void
;
(
e
:
"delNo"
,
sateNo
:
string
):
void
;
}
>
();
const
selectNo
=
()
=>
{
...
...
src/views/os-spiderManager/index.vue
View file @
e3e5939c
...
...
@@ -47,7 +47,7 @@
v-for=
"(no, index) in sateNoList"
:key=
"index"
class=
"no-item-row"
:-no=
"no"
:-no=
"no
.norad_cat_id
"
@
add-no=
"handleSateAdd"
@
del-no=
"handleSateDel"
:reset-selected=
"resetSelected"
...
...
@@ -59,7 +59,7 @@
<span
style=
"color: white; font-weight: 500"
>
NORAD编号:
</span>
<el-input
@
input=
"handleNumInput"
maxlength=
"
5
"
maxlength=
"
6
"
placeholder=
"请输入编号"
v-model=
"curSateNo"
style=
"width: 100px"
...
...
@@ -77,8 +77,8 @@
type=
"danger"
size=
"small"
@
click=
"
() =>
{
confirm();
(
e:MouseEvent
) =>
{
confirm(
e
);
delNoList();
}
"
...
...
@@ -107,7 +107,7 @@
import
{
ref
,
onMounted
,
nextTick
,
watch
}
from
"vue"
;
import
Pagination
from
"@/components/pagination/index.vue"
;
import
{
useRouter
}
from
"vue-router"
;
import
{
getSpiderList
,
addSateNo
,
getSateIdList
}
from
"@/api/system.ts"
;
import
{
getSpiderList
,
addSateNo
,
getSateIdList
,
deleteSateNoList
,
addSateNoList
}
from
"@/api/system.ts"
;
import
NoItem
from
"./components/NoItem.vue"
;
import
{
ElMessage
,
type
UploadProps
,
type
UploadRawFile
}
from
"element-plus"
;
import
MenuTitle
from
"@/components/MenuTitle.vue"
;
...
...
@@ -137,57 +137,53 @@ const getData = async () => {
const
editDialogVisible
=
ref
(
false
);
const
sateNoList
=
ref
<
string
[]
>
([]);
//编号item类型定义
interface
noradItem
{
id
:
number
;
norad_cat_id
:
string
;
create_time
:
string
;
}
const
sateNoList
=
ref
<
noradItem
[]
>
([]);
const
curSateNo
=
ref
(
""
);
const
curSelSateNo
=
ref
<
(
string
|
number
)
[]
>
([]);
const
curSelSateNo
=
ref
<
string
[]
>
([]);
const
resetSelected
=
ref
(
false
);
//添加选中项到当前列表
const
handleSateAdd
=
(
no
:
string
|
number
)
=>
{
curSelSateNo
.
value
.
push
(
padZeroTo5Digits
(
no
));
const
handleSateAdd
=
(
no
:
string
)
=>
{
if
(
checkNoLeSix
(
no
))
{
curSelSateNo
.
value
.
push
(
no
);
}
};
//从当前列表删除选中项
const
handleSateDel
=
(
no
:
string
|
number
)
=>
{
curSelSateNo
.
value
=
curSelSateNo
.
value
.
filter
((
item
)
=>
item
!=
no
);
};
//添加编号到列表并整体发到后端
//添加编号发到后端
const
addNoToList
=
async
()
=>
{
try
{
if
(
curSateNo
.
value
&&
sateNoList
.
value
.
includes
(
padZeroTo5Digits
(
curSateNo
.
value
)))
{
ElMessage
.
error
(
"当前编号已存在,请重新输入"
);
curSateNo
.
value
=
""
;
return
;
}
sateNoList
.
value
.
push
(
padZeroTo5Digits
(
curSateNo
.
value
));
const
res
=
await
addSateNo
({
id
:
sateNoList
.
value
});
const
res
=
await
addSateNo
({
norad_id
:
curSateNo
.
value
});
if
(
res
.
code
===
0
)
{
ElMessage
.
success
(
"添加编号成功"
);
}
else
{
sateNoList
.
value
.
pop
();
ElMessage
.
error
(
res
.
message
);
getSateNoList
();
}
curSateNo
.
value
=
""
;
scrollToBottom
();
}
catch
(
error
:
any
)
{
ElMessage
.
error
(
error
.
message
);
}
};
//编号文件导入后发送到后端
const
fileImptAddNoList
=
async
()
=>
{
try
{
const
res
=
await
addSateNo
({
id
:
sateNoList
.
value
});
console
.
log
(
textFileNumbers
.
value
);
const
res
=
await
addSateNoList
({
norad_id
:
textFileNumbers
.
value
});
console
.
log
(
res
);
if
(
res
.
code
===
0
)
{
ElMessage
.
success
(
"编号导入成功"
);
}
else
{
sateNoList
.
value
.
pop
();
ElMessage
.
error
(
res
.
message
);
ElMessage
.
success
(
"导入编号成功"
);
}
scrollToBottom
();
getSateNoList
();
}
catch
(
error
:
any
)
{
ElMessage
.
error
(
error
.
message
);
}
...
...
@@ -196,8 +192,7 @@ const fileImptAddNoList = async () => {
//删除选中编号
const
delNoList
=
async
()
=>
{
try
{
sateNoList
.
value
=
sateNoList
.
value
.
filter
((
item
)
=>
!
curSelSateNo
.
value
.
includes
(
item
));
const
res
=
await
addSateNo
({
id
:
sateNoList
.
value
as
string
[]
});
const
res
=
await
deleteSateNoList
({
norad_id
:
curSelSateNo
.
value
});
if
(
res
.
code
===
0
)
{
ElMessage
.
success
(
"删除编号成功"
);
}
...
...
@@ -206,6 +201,7 @@ const delNoList = async () => {
nextTick
(()
=>
{
resetSelected
.
value
=
false
;
});
getSateNoList
();
}
catch
(
error
:
any
)
{
ElMessage
.
error
(
error
.
message
);
}
...
...
@@ -223,24 +219,31 @@ const scrollToBottom = () => {
});
};
const
handleNumInput
=
(
value
:
string
)
=>
{
const
filtered
=
value
.
replace
(
/
\D
/g
,
""
);
curSateNo
.
value
=
filtered
.
slice
(
0
,
5
);
//检查输入的编号个数不大于6
const
checkNoLeSix
=
(
no
:
number
|
string
):
boolean
=>
{
if
(
String
(
no
).
length
>
6
)
{
ElMessage
.
error
(
"编号位数错误,长度不能大于6位"
);
return
false
;
}
return
true
;
};
//编号格式化
const
padZeroTo5Digits
=
(
num
:
number
|
string
):
string
=>
{
const
numStr
=
String
(
num
);
const
pureNumStr
=
numStr
.
replace
(
/
\D
/g
,
""
);
return
pureNumStr
.
padStart
(
5
,
"0"
).
slice
(
-
5
);
const
handleNumInput
=
(
value
:
string
)
=>
{
const
filtered
=
value
.
replace
(
/
\D
/g
,
""
);
curSateNo
.
value
=
filtered
.
slice
(
0
,
6
);
};
const
handleEditSateId
=
async
()
=>
{
editDialogVisible
.
value
=
true
;
getSateNoList
();
};
//获取编号列表
const
getSateNoList
=
async
()
=>
{
try
{
const
res
=
await
getSateIdList
();
if
(
res
.
code
===
0
)
{
sateNoList
.
value
=
res
.
data
||
[];
sateNoList
.
value
=
res
.
data
.
list
||
[];
}
}
catch
(
error
:
any
)
{
ElMessage
.
error
(
error
.
message
);
...
...
@@ -248,16 +251,12 @@ const handleEditSateId = async () => {
};
//读取文本文件后存储读取的编号
const
textFileNumbers
=
ref
<
number
[]
>
([]);
const
textFileNumbers
=
ref
<
string
[]
>
([]);
//监听导入文件的数组变化
watch
(
textFileNumbers
,
(
newVal
)
=>
{
if
(
newVal
.
length
>
0
)
{
newVal
.
map
((
num
)
=>
{
if
(
!
sateNoList
.
value
.
includes
(
padZeroTo5Digits
(
num
)))
{
sateNoList
.
value
.
push
(
padZeroTo5Digits
(
num
));
}
});
newVal
.
forEach
((
num
)
=>
{});
fileImptAddNoList
();
}
});
...
...
@@ -306,13 +305,12 @@ const handleFileChange: UploadProps["onChange"] = (uploadFile) => {
if
(
!
textContent
)
{
throw
new
Error
(
"文件内容为空"
);
}
textFileNumbers
.
value
=
parseTextToNumbers
(
textContent
);
textFileNumbers
.
value
=
parseTextToNumbers
(
textContent
)
.
map
((
item
)
=>
String
(
item
))
;
};
//失败的回调
reader
.
onerror
=
()
=>
{
ElMessage
.
error
(
"文件导入失败,请检查文件是否损坏或重试"
);
};
//读取文件
reader
.
readAsText
(
file
,
"utf-8"
);
};
...
...
src/views/os-status/components/errorMessageChart.vue
View file @
e3e5939c
...
...
@@ -2,13 +2,17 @@
<div
class=
"dataCard"
>
<div
class=
"titleStyle"
>
错误日志统计
</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"
>
<el-table
:data=
"curTableData"
border
style=
"width: 100%"
>
<el-table-column
width=
"55"
label=
"序号"
type=
"index"
/>
<el-table-column
width=
"150"
property=
"spider"
label=
"爬虫名称"
/>
<el-table-column
property=
"error"
label=
"错误信息"
/>
<el-table-column
width=
"160"
property=
"timestamp"
label=
"发生时间"
/>
<el-table-column
property=
"error"
label=
"错误信息"
>
<template
#
default=
"scope"
>
{{
scope
.
row
.
error
.
error
}}
</
template
>
</el-table-column>
<el-table-column
width=
"160"
property=
"timestamp"
label=
"记录时间"
/>
</el-table>
<div
class=
"pagination w-full flex flex-row-reverse pr-4 m-t-4"
>
<Pagination
...
...
@@ -65,7 +69,7 @@ const logCountList = computed(() => {
return
logList
.
value
.
map
((
item
)
=>
item
.
count
);
});
//
x
轴日期列表
//
X
轴日期列表
const
dateList
=
ref
<
string
[]
>
([]);
//Y轴最大值
...
...
@@ -138,6 +142,7 @@ const setChartData = async () => {
data
:
dateList
.
value
,
name
:
"日期"
,
nameLocation
:
"middle"
,
nameGap
:
20
,
nameTextStyle
:
{
color
:
"#fff"
,
fontSize
:
12
,
...
...
@@ -155,6 +160,7 @@ const setChartData = async () => {
type
:
"value"
,
name
:
"数量"
,
nameLocation
:
"middle"
,
nameGap
:
20
,
max
:
maxVal
.
value
,
axisLabel
:
{
color
:
"#fff"
,
...
...
@@ -192,6 +198,7 @@ const handleClickChart = (params: any) => {
});
pageObj
.
value
.
total
=
tableData
.
value
.
length
;
curTableData
.
value
=
tableData
.
value
.
slice
(
0
,
5
);
console
.
log
(
curTableData
.
value
);
};
//生成图表
...
...
src/views/os-taskInformation/components/taskCard.vue
View file @
e3e5939c
...
...
@@ -90,18 +90,17 @@
<
/template
>
<
script
lang
=
"ts"
setup
>
import
{
ref
,
onMounted
,
onUnmounted
}
from
"vue"
;
import
{
ref
,
onMounted
}
from
"vue"
;
import
{
useRouter
}
from
"vue-router"
;
import
addTaskDialog
from
"./addTaskDialog.vue"
;
import
{
getSpiderTaskList
,
resumeSpiderTask
,
pauseSpiderTask
,
getTaskCount
}
from
"@/api/spiderTask"
;
import
{
DeleteMode
}
from
"@/components/Delete/enum.ts"
;
import
{
AddMode
}
from
"./enum"
;
import
deleteDialog
from
"./deleteDialog.vue"
;
import
{
ElMessage
,
ElNotification
}
from
"element-plus"
;
import
{
ElMessage
}
from
"element-plus"
;
import
{
getSpiderList
}
from
"@/api/system.ts"
;
import
formatExactLargeNum
from
"@/utils/formatExactLargeNum"
;
import
TableSearch
from
"@/components/TableSearch.vue"
;
import
{
Manager
,
Socket
}
from
"socket.io-client"
;
const
props
=
defineProps
({
spiderType
:
{
...
...
@@ -118,26 +117,6 @@ const props = defineProps({
}
,
}
);
const
socket
=
ref
<
Socket
|
null
>
(
null
);
//错误消息通知
const
handleErrorMsgNotify
=
()
=>
{
//websocket连接
const
manager
=
new
Manager
(
"/api:5001"
);
socket
.
value
=
manager
.
socket
(
"/"
);
//收到错误通知
socket
.
value
.
on
(
"error_message"
,
onErrorMsg
);
}
;
//错误消息处理
const
onErrorMsg
=
({
message
}
:
{
message
:
any
}
)
=>
{
ElNotification
({
title
:
"任务错误提示"
,
message
,
type
:
"error"
,
}
);
}
;
// 所有响应式变量初始化时避免 undefined
const
taskSelectOptions
=
ref
<
any
[]
>
([]);
// 初始化为空数组
const
searchCondition
=
ref
({
...
...
@@ -311,15 +290,6 @@ onMounted(() => {
}
getData
();
getSpiderTypeList
();
//开启socket连接
handleErrorMsgNotify
();
}
);
onUnmounted
(()
=>
{
//关闭socket连接
if
(
socket
.
value
)
{
socket
.
value
.
disconnect
();
}
}
);
<
/script
>
...
...
src/views/os-taskRecord/index.vue
View file @
e3e5939c
...
...
@@ -102,7 +102,7 @@ zhCn.el.pagination.pageClassifier = "页";
const
route
=
useRoute
();
const
router
=
useRouter
();
//初始数据为近七天
const
timeValue
=
ref
([
dayjs
().
subtract
(
7
,
"day"
).
format
(
"YYYY-MM-DD"
),
dayjs
().
format
(
"YYYY-MM-DD"
)
]);
const
timeValue
=
ref
<
string
[]
>
([
]);
const
tableData
=
ref
([]);
const
pageObj
=
ref
({
total
:
10
,
...
...
@@ -128,18 +128,34 @@ const tableLoading = ref(false);
//重置查询
const
resetQuery
=
()
=>
{
timeValue
.
value
=
[
dayjs
().
subtract
(
7
,
"day"
).
format
(
"YYYY-MM-DD"
),
dayjs
().
format
(
"YYYY-MM-DD"
)
];
timeValue
.
value
=
[];
getData
();
};
// 获取任务执行记录列表
const
getData
=
async
()
=>
{
searchData
();
let
resTime
:
any
[]
=
[];
resTime
.
push
(
dayjs
().
subtract
(
7
,
"day"
).
format
(
"YYYY-MM-DD HH:mm:ss"
));
resTime
.
push
(
dayjs
().
format
(
"YYYY-MM-DD HH:mm:ss"
));
console
.
log
(
resTime
);
tableLoading
.
value
=
true
;
const
res
=
await
getSpiderTaskRecord
({
page
:
pageObj
.
value
.
pageNo
,
size
:
pageObj
.
value
.
pageSize
,
status
:
"total"
,
times
:
resTime
,
});
pageObj
.
value
.
total
=
res
.
data
.
total
;
tableData
.
value
=
res
.
data
.
list
;
console
.
log
(
tableData
.
value
);
tableLoading
.
value
=
false
;
};
//查询数据的方法
const
searchData
=
async
()
=>
{
if
(
!
timeValue
.
value
)
{
if
(
timeValue
.
value
.
length
==
0
)
{
ElMessage
.
warning
(
"请先选择时间段"
);
return
;
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment