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
85fdc758
Commit
85fdc758
authored
Nov 13, 2025
by
liucan
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
pref:调整任务信息页面、系统管理页面显示
parent
cff37174
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
482 additions
and
415 deletions
+482
-415
package-lock.json
package-lock.json
+0
-0
index.vue
src/views/os-system/index.vue
+182
-120
taskCard.vue
src/views/os-taskInformation/components/taskCard.vue
+299
-294
vite.config.ts
vite.config.ts
+1
-1
No files found.
package-lock.json
0 → 100644
View file @
85fdc758
This source diff could not be displayed because it is too large. You can
view the blob
instead.
src/views/os-system/index.vue
View file @
85fdc758
<
template
>
<div>
<div
class=
"text-left p-8"
>
<el-form
inline
>
<el-form-item>
<el-button
test-element=
"userSystem-AddUser"
type=
"primary"
plain
@
click=
"openAddUserDialog"
>
创建用户
</el-button>
</el-form-item>
<el-form-item>
<el-button
type=
"danger"
plain
@
click=
"handleBatchDelete"
>
批量删除
</el-button>
</el-form-item>
</el-form>
</div>
<el-table
:data=
"tableData"
style=
"width: 100%"
border
:header-cell-style=
"
{ textAlign: 'center' }"
:cell-style="{ textAlign: 'center' }" :row-style="{ height: '58px' }"
@selection-change="handleSelectionChange">
<el-table-column
type=
"selection"
width=
"40"
/>
<el-table-column
property=
"number"
label=
"序号"
width=
"55"
type=
"index"
/>
<el-table-column
property=
"username"
label=
"用户账号"
show-overflow-tooltip
/>
<el-table-column
property=
"nickname"
label=
"用户名称"
show-overflow-tooltip
/>
<el-table-column
property=
"create_time"
label=
"创建时间"
width=
"280"
show-overflow-tooltip
/>
<el-table-column
label=
"操作"
width=
"220"
>
<template
#
default=
"scope"
>
<el-button
type=
"primary"
plain
@
click=
"handleEdit(scope.row)"
id=
"editUser"
>
编辑
</el-button>
<el-button
type=
"danger"
plain
@
click=
"handleDelete(scope.row)"
>
删除
</el-button>
</
template
>
</el-table-column>
</el-table>
<div
class=
"pagination w-full flex flex-row-reverse pr-4 m-t-4"
>
<Pagination
:total=
"pageObj.total"
v-model:page=
"pageObj.pageNo"
v-model:limit=
"pageObj.pageSize"
@
pagination=
"getUserListData"
/>
</div>
<!-- 删除弹窗组件 -->
<deleteDialog
v-model:dialogVisible=
"showDeleteDialog"
@
get-user-list=
"getUserListData"
:ids=
"userIds"
:deleteMode=
"deleteMode"
:id=
"userId"
/>
<!-- 创建用户弹窗组件 -->
<addUserDialog
v-model:dialogVisible=
"dialogVisible"
:mode=
"mode"
:nickName=
"nickName"
:userName=
"userName"
:id=
"userId"
:userRole=
"userRole"
:userStatus=
"userStatus"
:userPassword=
"userPassword"
@
get-user-list=
"getUserListData"
/>
</div>
<div
class=
"sys-content"
>
<el-card>
<div
class=
"title"
>
系统管理
</div>
<div
class=
"low-titme"
>
System Admin
</div>
<el-divider
class=
"divider"
/>
<div
class=
"btns"
>
<el-button
test-element=
"userSystem-AddUser"
type=
"primary"
plain
@
click=
"openAddUserDialog"
>
创建用户
</el-button
>
<el-button
type=
"danger"
plain
@
click=
"handleBatchDelete"
>
批量删除
</el-button>
</div>
</el-card>
<el-table
:data=
"tableData"
style=
"width: 100%"
border
:header-cell-style=
"
{ textAlign: 'center' }"
:cell-style="{ textAlign: 'center' }"
:row-style="{ height: '58px' }"
@selection-change="handleSelectionChange"
>
<el-table-column
type=
"selection"
width=
"40"
/>
<el-table-column
property=
"number"
label=
"序号"
width=
"55"
type=
"index"
/>
<el-table-column
property=
"username"
label=
"用户账号"
show-overflow-tooltip
/>
<el-table-column
property=
"nickname"
label=
"用户名称"
show-overflow-tooltip
/>
<el-table-column
property=
"role"
label=
"用户角色"
show-overflow-tooltip
>
<template
#
default=
"scope"
>
{{
scope
.
row
.
role
==
1
?
"管理员"
:
"普通用户"
}}
</
template
>
</el-table-column>
<el-table-column
property=
"status"
label=
"用户状态"
show-overflow-tooltip
>
<
template
#
default=
"scope"
>
{{
scope
.
row
.
status
?
"启用"
:
"停用"
}}
</
template
>
</el-table-column>
<el-table-column
property=
"create_time"
label=
"创建时间"
width=
"280"
show-overflow-tooltip
/>
<el-table-column
label=
"操作"
width=
"220"
>
<
template
#
default=
"scope"
>
<el-button
type=
"primary"
plain
@
click=
"handleEdit(scope.row)"
id=
"editUser"
>
编辑
</el-button>
<el-button
type=
"danger"
plain
@
click=
"handleDelete(scope.row)"
>
删除
</el-button>
</
template
>
</el-table-column>
</el-table>
<div
class=
"pagination w-full flex flex-row-reverse pr-4 m-t-4"
>
<Pagination
:total=
"pageObj.total"
v-model:page=
"pageObj.pageNo"
v-model:limit=
"pageObj.pageSize"
@
pagination=
"getUserListData"
/>
</div>
<!-- 删除弹窗组件 -->
<deleteDialog
v-model:dialogVisible=
"showDeleteDialog"
@
get-user-list=
"getUserListData"
:ids=
"userIds"
:deleteMode=
"deleteMode"
:id=
"userId"
/>
<!-- 创建用户弹窗组件 -->
<addUserDialog
v-model:dialogVisible=
"dialogVisible"
:mode=
"mode"
:nickName=
"nickName"
:userName=
"userName"
:id=
"userId"
:userRole=
"userRole"
:userStatus=
"userStatus"
:userPassword=
"userPassword"
@
get-user-list=
"getUserListData"
/>
</div>
</template>
<
script
setup
lang=
"ts"
>
import
{
ref
,
onMounted
}
from
'vue'
import
Pagination
from
'@/components/pagination/index.vue'
import
deleteDialog
from
'@/components/Delete/index.vue'
import
addUserDialog
from
'./components/addUserDialog.vue'
import
{
getUserList
}
from
'@/api/user.ts'
import
{
DeleteMode
}
from
'@/components/Delete/enum.ts'
import
{
AddMode
}
from
'./components/enum.ts'
;
import
{
ElMessage
}
from
'element-plus'
const
userId
=
ref
<
any
>
([])
const
userIds
=
ref
<
any
>
()
const
nickName
=
ref
<
string
>
(
''
)
const
userName
=
ref
<
string
>
(
''
)
const
userRole
=
ref
<
number
>
(
0
)
const
userStatus
=
ref
<
boolean
>
(
true
)
const
userPassword
=
ref
<
string
>
(
''
)
const
showDeleteDialog
=
ref
(
false
)
const
deleteMode
=
ref
<
DeleteMode
>
(
DeleteMode
.
SINGLE_DELETE
)
const
dialogVisible
=
ref
<
boolean
>
(
false
)
const
mode
=
ref
<
AddMode
>
(
AddMode
.
ADD_MODE
)
const
tableData
=
ref
()
import
{
ref
,
onMounted
}
from
"vue"
;
import
Pagination
from
"@/components/pagination/index.vue"
;
import
deleteDialog
from
"@/components/Delete/index.vue"
;
import
addUserDialog
from
"./components/addUserDialog.vue"
;
import
{
getUserList
}
from
"@/api/user.ts"
;
import
{
DeleteMode
}
from
"@/components/Delete/enum.ts"
;
import
{
AddMode
}
from
"./components/enum.ts"
;
import
{
ElMessage
}
from
"element-plus"
;
const
userId
=
ref
<
any
>
([])
;
const
userIds
=
ref
<
any
>
()
;
const
nickName
=
ref
<
string
>
(
""
);
const
userName
=
ref
<
string
>
(
""
);
const
userRole
=
ref
<
number
>
(
0
)
;
const
userStatus
=
ref
<
boolean
>
(
true
)
;
const
userPassword
=
ref
<
string
>
(
""
);
const
showDeleteDialog
=
ref
(
false
)
;
const
deleteMode
=
ref
<
DeleteMode
>
(
DeleteMode
.
SINGLE_DELETE
)
;
const
dialogVisible
=
ref
<
boolean
>
(
false
)
;
const
mode
=
ref
<
AddMode
>
(
AddMode
.
ADD_MODE
)
;
const
tableData
=
ref
()
;
const
pageObj
=
ref
({
total
:
0
,
pageSize
:
10
,
pageNo
:
1
})
total
:
0
,
pageSize
:
10
,
pageNo
:
1
,
})
;
// 编辑用户信息的方法
const
handleEdit
=
async
(
row
:
any
)
=>
{
mode
.
value
=
AddMode
.
UPDATE_MODE
nickName
.
value
=
row
.
nickname
userName
.
value
=
row
.
username
userRole
.
value
=
row
.
role
userStatus
.
value
=
row
.
status
userPassword
.
value
=
row
.
password
dialogVisible
.
value
=
true
userId
.
value
=
row
.
id
}
mode
.
value
=
AddMode
.
UPDATE_MODE
;
nickName
.
value
=
row
.
nickname
;
userName
.
value
=
row
.
username
;
userRole
.
value
=
row
.
role
;
userStatus
.
value
=
row
.
status
;
userPassword
.
value
=
row
.
password
;
dialogVisible
.
value
=
true
;
userId
.
value
=
row
.
id
;
}
;
// 弹窗关闭的方法
const
handleDelete
=
async
(
row
:
any
)
=>
{
showDeleteDialog
.
value
=
true
deleteMode
.
value
=
DeleteMode
.
SINGLE_DELETE
userId
.
value
=
row
.
id
console
.
log
(
userId
.
value
);
}
showDeleteDialog
.
value
=
true
;
deleteMode
.
value
=
DeleteMode
.
SINGLE_DELETE
;
userId
.
value
=
row
.
id
;
console
.
log
(
userId
.
value
);
}
;
// 批量删除用户的方法
const
handleBatchDelete
=
async
()
=>
{
if
(
userIds
.
value
==
undefined
)
{
ElMessage
({
message
:
'请先选择要删除的用户'
,
type
:
'warning'
})
return
}
else
{
deleteMode
.
value
=
DeleteMode
.
BATCH_DELETE
showDeleteDialog
.
value
=
true
}
}
if
(
userIds
.
value
==
undefined
)
{
ElMessage
({
message
:
"请先选择要删除的用户"
,
type
:
"warning"
,
});
return
;
}
else
{
deleteMode
.
value
=
DeleteMode
.
BATCH_DELETE
;
showDeleteDialog
.
value
=
true
;
}
}
;
// 多选框改变后的方法
const
handleSelectionChange
=
(
data
:
any
)
=>
{
let
array
=
[]
for
(
let
i
=
0
;
i
<
data
.
length
;
i
++
)
{
array
.
push
(
data
[
i
].
id
)
}
userIds
.
value
=
array
}
let
array
=
[];
for
(
let
i
=
0
;
i
<
data
.
length
;
i
++
)
{
array
.
push
(
data
[
i
].
id
);
}
userIds
.
value
=
array
;
}
;
const
openAddUserDialog
=
()
=>
{
mode
.
value
=
AddMode
.
ADD_MODE
dialogVisible
.
value
=
true
}
mode
.
value
=
AddMode
.
ADD_MODE
;
dialogVisible
.
value
=
true
;
}
;
// 获取用户列表数据的方法
const
getUserListData
=
async
()
=>
{
const
userList
=
await
getUserList
({
page
:
pageObj
.
value
.
pageNo
,
size
:
pageObj
.
value
.
pageSize
})
tableData
.
value
=
userList
.
data
.
list
pageObj
.
value
.
total
=
userList
.
data
.
total
console
.
log
(
userList
);
}
const
userList
=
await
getUserList
({
page
:
pageObj
.
value
.
pageNo
,
size
:
pageObj
.
value
.
pageSize
,
});
tableData
.
value
=
userList
.
data
.
list
;
pageObj
.
value
.
total
=
userList
.
data
.
total
;
console
.
log
(
userList
);
};
onMounted
(
async
()
=>
{
getUserListData
()
})
getUserListData
();
})
;
</
script
>
<
style
scoped
>
/* 去除按钮边框 */
.el-button
:focus
{
outline
:
none
;
outline
:
none
;
}
.sys-content
{
padding
:
10px
;
}
.title
{
text-align
:
left
;
font-size
:
18px
;
font-weight
:
500
;
color
:
white
;
}
.low-titme
{
color
:
#ccc
;
text-align
:
left
;
margin-left
:
20px
;
}
.divider
{
margin-top
:
15px
;
}
.btns
{
display
:
flex
;
justify-content
:
end
;
}
</
style
>
<
style
>
/* 修改弹窗样式 */
.el-dialog
{
background-image
:
url("@/assets/picture/dialog1.png")
;
background-size
:
100%
100%
;
background-repeat
:
no-repeat
;
background-image
:
url("@/assets/picture/dialog1.png")
;
background-size
:
100%
100%
;
background-repeat
:
no-repeat
;
.el-dialog__title
{
color
:
#ffffff
;
}
.el-dialog__title
{
color
:
#ffffff
;
}
}
/* 修改el输入框的样式 */
.el-input__wrapper
{
background-color
:
#1d5484
;
box-shadow
:
none
;
background-color
:
#1d5484
;
box-shadow
:
none
;
}
/* 卡片外层容器透明 */
.el-card
{
background-color
:
transparent
!important
;
border
:
none
;
/* 可选:去除边框 */
}
/* 卡片内容区域透明 */
.el-card__body
{
background-color
:
transparent
!important
;
padding
:
16px
;
/* 保持默认内边距,可按需调整 */
}
</
style
>
src/views/os-taskInformation/components/taskCard.vue
View file @
85fdc758
<!-- 任务执行统计卡片组件 -->
<
template
>
<div>
<div
class=
"m-t-2"
/>
<div
class=
"text-left p-4 toolbarStyle "
>
<div
class=
"formStyle"
>
<el-form
inline
>
<el-form-item>
<el-text
class=
"mx-1"
style=
"color: #fff;"
>
所属爬虫:
</el-text>
</el-form-item>
<el-form-item>
<div>
<el-select
v-model=
"searchCondition.spiders"
placeholder=
"请选择"
style=
"width: 220px"
>
<el-option
v-for=
"item in taskSelectOptions"
:key=
"item.spider"
:label=
"item.spider"
:value=
"item.spider"
/>
</el-select>
</div>
</el-form-item>
<!--
<el-form-item>
<div>
<div
class=
"m-t-2"
/>
<div
class=
"text-left p-4 toolbarStyle"
>
<div
class=
"formStyle"
>
<el-form
inline
>
<el-form-item>
<el-text
class=
"mx-1"
style=
"color: #fff"
>
所属爬虫:
</el-text>
</el-form-item>
<el-form-item>
<div>
<el-select
v-model=
"searchCondition.spiders"
placeholder=
"请选择"
style=
"width: 220px"
>
<el-option
v-for=
"item in taskSelectOptions"
:key=
"item.spider"
:label=
"item.spider"
:value=
"item.spider"
/>
</el-select>
</div>
</el-form-item>
<!--
<el-form-item>
<el-text
class=
"mx-1"
style=
"color: #fff;"
>
任务名称:
</el-text>
</el-form-item>
<el-form-item>
<el-input
v-model=
"taskName"
placeholder=
"请输入"
style=
"width: 220px"
/>
</el-form-item>
-->
<el-form-item>
<el-space>
<el-button
type=
"primary"
@
Click=
"search"
>
查询
</el-button>
<el-button
type=
"primary"
@
Click=
"resetData"
>
重置列表
</el-button>
<el-button
type=
"primary"
@
click=
"openTaskDialog"
>
新建任务
</el-button>
</el-space>
</el-form-item>
</el-form>
</div>
</div>
<div
class=
"cardStyle"
>
<div
class=
"taskCard p-6"
v-for=
"task in taskList"
:key=
"task.taskId"
>
<div
class=
"taskContent"
>
<div>
<el-form-item
class=
"form-item"
>
<span
class=
"titleStyle"
>
{{
task
.
kwargs
.
options
===
''
?
'无名称'
:
JSON
.
parse
(
task
.
kwargs
.
options
).
jobName
}}
</span>
</el-form-item>
</div>
<div>
<el-form-item
class=
"form-item"
>
<el-button
type=
"primary"
@
click=
"editTask(task)"
class=
"editButton"
>
编辑
</el-button>
<!--
<el-button
type=
"success"
@
click=
"goToTaskRecord"
class=
"recordButton"
>
执行记录
</el-button>
-->
<el-button
type=
"danger"
@
click=
"deleteTask(task)"
class=
"deleteButton"
>
删除
</el-button>
</el-form-item>
</div>
<div
class=
"wordStyle"
>
<el-form-item
class=
"form-item"
>
<el-space>
<span
class=
"wordStyle"
>
启用/停止:
</span>
<el-switch
v-model=
"task.status"
:active-value=
"'running'"
:inactive-value=
"'paused'"
@
change=
"(newStatus: any) => changeStatus(task, newStatus)"
/>
</el-space>
</el-form-item>
</div>
<div
class=
"wordStyle"
>
<el-form-item
class=
"form-item"
>
<el-space>
<span
class=
"wordStyle"
>
执行频率:
{{
parseCronExpression
(
task
.
kwargs
.
cron
)
}}
</span>
</el-space>
</el-form-item>
</div>
<div
class=
"wordStyle"
>
<el-form-item
class=
"form-item"
>
<el-space>
<span
class=
"wordStyle"
>
执行次数:
{{
task
.
count
}}
</span>
</el-space>
</el-form-item>
</div>
<div
class=
"wordStyle"
>
<el-form-item
class=
"form-item"
>
<el-space>
<span
class=
"wordStyle"
>
所属爬虫:
{{
task
.
kwargs
.
spider
}}
</span>
</el-space>
</el-form-item>
</div>
<!--
<div
class=
"wordStyle"
>
<el-form-item>
<el-space>
<el-button
type=
"primary"
@
Click=
"search"
>
查询
</el-button>
<el-button
type=
"primary"
@
Click=
"resetData"
>
重置列表
</el-button>
<el-button
type=
"primary"
@
click=
"openTaskDialog"
>
新建任务
</el-button>
</el-space>
</el-form-item>
</el-form>
</div>
</div>
<div
class=
"cardStyle"
>
<el-row>
<div
class=
"taskCard p-6"
v-for=
"task in taskList"
:key=
"task.taskId"
>
<div
class=
"taskContent"
>
<div>
<el-form-item
class=
"form-item"
>
<span
class=
"titleStyle"
>
{{
task
.
kwargs
.
options
===
""
?
"无名称"
:
JSON
.
parse
(
task
.
kwargs
.
options
).
jobName
}}
</span>
</el-form-item>
</div>
<div>
<el-form-item
class=
"form-item"
>
<el-button
type=
"primary"
@
click=
"editTask(task)"
class=
"editButton"
>
编辑
</el-button>
<!--
<el-button
type=
"success"
@
click=
"goToTaskRecord"
class=
"recordButton"
>
执行记录
</el-button>
-->
<el-button
type=
"danger"
@
click=
"deleteTask(task)"
class=
"deleteButton"
>
删除
</el-button>
</el-form-item>
</div>
<div
class=
"wordStyle"
>
<el-form-item
class=
"form-item"
>
<el-space>
<span
class=
"wordStyle"
>
启用/停止:
</span>
<el-switch
v-model=
"task.status"
:active-value=
"'running'"
:inactive-value=
"'paused'"
@
change=
"(newStatus: any) => changeStatus(task, newStatus)"
/>
</el-space>
</el-form-item>
</div>
<div
class=
"wordStyle"
>
<el-form-item
class=
"form-item"
>
<el-space>
<span
class=
"wordStyle"
>
执行频率:
{{
parseCronExpression
(
task
.
kwargs
.
cron
)
}}
</span>
</el-space>
</el-form-item>
</div>
<div
class=
"wordStyle"
>
<el-form-item
class=
"form-item"
>
<el-space>
<span
class=
"wordStyle"
>
执行次数:
{{
task
.
count
}}
</span>
</el-space>
</el-form-item>
</div>
<div
class=
"wordStyle"
>
<el-form-item
class=
"form-item"
>
<el-space>
<span
class=
"wordStyle"
>
所属爬虫:
{{
task
.
kwargs
.
spider
}}
</span>
</el-space>
</el-form-item>
</div>
<!--
<div
class=
"wordStyle"
>
<el-form-item
class=
"form-item"
>
<el-space>
<span
class=
"wordStyle"
>
失败次数:
</span>
...
...
@@ -87,202 +96,206 @@
</el-space>
</el-form-item>
</div>
-->
</div>
</div>
</div>
<addTaskDialog
v-model:dialogVisible=
"showTaskDialog"
@
confirm=
"handleEdit"
:mode=
"editMode"
@
getTaskList=
"getData"
:jobId=
"jobId"
:cron=
"frequency"
:spiderType=
"belongSpiderType"
:options=
"taskOptions"
/>
<deleteDialog
v-model:dialogVisible=
"showDeleteDialog"
@
get-user-list=
"getData"
:jobId=
"jobId"
/>
</div>
</div>
</div>
</el-row>
</div>
<addTaskDialog
v-model:dialogVisible=
"showTaskDialog"
@
confirm=
"handleEdit"
:mode=
"editMode"
@
getTaskList=
"getData"
:jobId=
"jobId"
:cron=
"frequency"
:spiderType=
"belongSpiderType"
:options=
"taskOptions"
/>
<deleteDialog
v-model:dialogVisible=
"showDeleteDialog"
@
get-user-list=
"getData"
:jobId=
"jobId"
/>
</div>
</
template
>
<
script
lang=
"ts"
setup
>
import
{
ref
,
onMounted
,
watch
}
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
{
CronExpressionParser
}
from
'cron-parser'
;
import
{
ElMessage
}
from
'element-plus'
import
{
getSpiderList
}
from
'@/api/system.ts'
import
{
ref
,
onMounted
,
watch
}
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
{
CronExpressionParser
}
from
"cron-parser"
;
import
{
ElMessage
}
from
"element-plus"
;
import
{
getSpiderList
}
from
"@/api/system.ts"
;
const
props
=
defineProps
({
spiderType
:
{
type
:
String
,
default
:
''
},
failTask
:
{
type
:
String
,
default
:
''
},
unusualTask
:
{
type
:
String
,
default
:
''
}
})
const
taskSelectOptions
=
ref
()
spiderType
:
{
type
:
String
,
default
:
""
,
},
failTask
:
{
type
:
String
,
default
:
""
,
},
unusualTask
:
{
type
:
String
,
default
:
""
,
},
})
;
const
taskSelectOptions
=
ref
()
;
const
searchCondition
=
ref
({
spiders
:
''
,
options
:
''
})
const
belongSpider
=
ref
(
''
)
const
taskName
=
ref
(
''
)
const
taskValue
=
ref
(
''
)
const
belongSpiderType
=
ref
(
''
)
const
router
=
useRouter
()
const
frequency
=
ref
()
const
editMode
=
ref
(
AddMode
.
UPDATE_TASK
)
const
deleteMode
=
ref
(
DeleteMode
.
SINGLE_DELETE
)
const
showDeleteDialog
=
ref
(
false
)
const
showTaskDialog
=
ref
(
false
)
const
taskSwitch
=
ref
(
false
)
const
taskOptions
=
ref
(
''
)
const
jobId
=
ref
(
''
)
const
taskList
=
ref
<
any
[]
>
([])
spiders
:
""
,
options
:
""
,
})
;
const
belongSpider
=
ref
(
""
);
const
taskName
=
ref
(
""
);
const
taskValue
=
ref
(
""
);
const
belongSpiderType
=
ref
(
""
);
const
router
=
useRouter
()
;
const
frequency
=
ref
()
;
const
editMode
=
ref
(
AddMode
.
UPDATE_TASK
)
;
const
deleteMode
=
ref
(
DeleteMode
.
SINGLE_DELETE
)
;
const
showDeleteDialog
=
ref
(
false
)
;
const
showTaskDialog
=
ref
(
false
)
;
const
taskSwitch
=
ref
(
false
)
;
const
taskOptions
=
ref
(
""
);
const
jobId
=
ref
(
""
);
const
taskList
=
ref
<
any
[]
>
([])
;
// 删除任务的方法
const
deleteTask
=
(
task
:
any
)
=>
{
jobId
.
value
=
task
.
id
deleteMode
.
value
=
DeleteMode
.
SINGLE_DELETE
showDeleteDialog
.
value
=
true
}
jobId
.
value
=
task
.
id
;
deleteMode
.
value
=
DeleteMode
.
SINGLE_DELETE
;
showDeleteDialog
.
value
=
true
;
}
;
// 编辑任务的方法
const
editTask
=
(
task
:
any
)
=>
{
jobId
.
value
=
task
.
id
taskOptions
.
value
=
JSON
.
stringify
(
JSON
.
parse
(
task
.
kwargs
.
options
))
belongSpiderType
.
value
=
task
.
kwargs
.
spider
frequency
.
value
=
task
.
kwargs
.
cron
editMode
.
value
=
AddMode
.
UPDATE_TASK
showTaskDialog
.
value
=
true
// console.log(JSON.stringify(JSON.parse(task.kwargs.options)));
}
jobId
.
value
=
task
.
id
;
taskOptions
.
value
=
JSON
.
stringify
(
JSON
.
parse
(
task
.
kwargs
.
options
));
belongSpiderType
.
value
=
task
.
kwargs
.
spider
;
frequency
.
value
=
task
.
kwargs
.
cron
;
editMode
.
value
=
AddMode
.
UPDATE_TASK
;
showTaskDialog
.
value
=
true
;
// console.log(JSON.stringify(JSON.parse(task.kwargs.options)));
};
const
goToTaskRecord
=
()
=>
{
router
.
push
({
path
:
'/osTaskRecord/list'
,
query
:
{
jump
:
'yes'
,
mode
:
'任务信息'
}
})
}
router
.
push
({
path
:
"/osTaskRecord/list"
,
query
:
{
jump
:
"yes"
,
mode
:
"任务信息"
,
},
});
}
;
// 启动与停止任务的方法
const
changeStatus
=
async
(
task
:
any
,
newStatus
:
string
)
=>
{
if
(
newStatus
===
"running"
)
{
await
resumeSpiderTask
({
job_id
:
task
.
id
});
}
else
if
(
newStatus
===
"paused"
)
{
await
pauseSpiderTask
({
job_id
:
task
.
id
});
}
// await getData();
if
(
newStatus
===
"running"
)
{
await
resumeSpiderTask
({
job_id
:
task
.
id
});
}
else
if
(
newStatus
===
"paused"
)
{
await
pauseSpiderTask
({
job_id
:
task
.
id
});
}
// await getData();
};
const
handleEdit
=
()
=>
{
}
const
handleEdit
=
()
=>
{};
// 打开新建任务弹窗
const
openTaskDialog
=
()
=>
{
editMode
.
value
=
AddMode
.
ADD_TASK
frequency
.
value
=
'* * * * * *'
showTaskDialog
.
value
=
true
}
editMode
.
value
=
AddMode
.
ADD_TASK
;
frequency
.
value
=
"* * * * * *"
;
showTaskDialog
.
value
=
true
;
}
;
// 获取任务列表的方法
const
getData
=
async
()
=>
{
const
res
=
await
getSpiderTaskList
({
spiders
:
searchCondition
.
value
.
spiders
?
[
searchCondition
.
value
.
spiders
]
:
[]
})
const
resId
=
await
getTaskCount
({})
for
(
let
i
=
0
;
i
<
res
.
data
.
length
;
i
++
)
{
res
.
data
[
i
].
count
=
resId
.
data
[
res
.
data
[
i
].
id
]
===
undefined
?
0
:
resId
.
data
[
res
.
data
[
i
].
id
]
}
taskList
.
value
=
res
.
data
}
const
res
=
await
getSpiderTaskList
({
spiders
:
searchCondition
.
value
.
spiders
?
[
searchCondition
.
value
.
spiders
]
:
[],
});
const
resId
=
await
getTaskCount
({});
for
(
let
i
=
0
;
i
<
res
.
data
.
length
;
i
++
)
{
res
.
data
[
i
].
count
=
resId
.
data
[
res
.
data
[
i
].
id
]
===
undefined
?
0
:
resId
.
data
[
res
.
data
[
i
].
id
];
}
taskList
.
value
=
res
.
data
;
};
// 重置任务列表的方法
const
resetData
=
async
()
=>
{
searchCondition
.
value
.
spiders
=
''
const
res
=
await
getSpiderTaskList
({
spiders
:
[],
options
:
JSON
.
stringify
({
jobName
:
taskName
.
value
})
})
const
resId
=
await
getTaskCount
({})
for
(
let
i
=
0
;
i
<
res
.
data
.
length
;
i
++
)
{
res
.
data
[
i
].
count
=
resId
.
data
[
res
.
data
[
i
].
id
]
===
undefined
?
0
:
resId
.
data
[
res
.
data
[
i
].
id
]
}
taskList
.
value
=
res
.
data
}
searchCondition
.
value
.
spiders
=
""
;
const
res
=
await
getSpiderTaskList
({
spiders
:
[],
options
:
JSON
.
stringify
({
jobName
:
taskName
.
value
})
});
const
resId
=
await
getTaskCount
({});
for
(
let
i
=
0
;
i
<
res
.
data
.
length
;
i
++
)
{
res
.
data
[
i
].
count
=
resId
.
data
[
res
.
data
[
i
].
id
]
===
undefined
?
0
:
resId
.
data
[
res
.
data
[
i
].
id
];
}
taskList
.
value
=
res
.
data
;
}
;
// 搜索任务的方法
const
search
=
async
()
=>
{
if
(
searchCondition
.
value
.
spiders
===
''
)
{
ElMessage
.
warning
(
'请先选择爬虫'
)
return
}
const
res
=
await
getSpiderTaskList
({
spiders
:
searchCondition
.
value
.
spiders
?
[
searchCondition
.
value
.
spiders
]
:
[],
options
:
JSON
.
stringify
({
jobName
:
taskName
.
value
})
})
const
resId
=
await
getTaskCount
({})
for
(
let
i
=
0
;
i
<
res
.
data
.
length
;
i
++
)
{
res
.
data
[
i
].
count
=
resId
.
data
[
res
.
data
[
i
].
id
]
===
undefined
?
0
:
resId
.
data
[
res
.
data
[
i
].
id
]
}
taskList
.
value
=
res
.
data
}
if
(
searchCondition
.
value
.
spiders
===
""
)
{
ElMessage
.
warning
(
"请先选择爬虫"
);
return
;
}
const
res
=
await
getSpiderTaskList
({
spiders
:
searchCondition
.
value
.
spiders
?
[
searchCondition
.
value
.
spiders
]
:
[],
options
:
JSON
.
stringify
({
jobName
:
taskName
.
value
}),
});
const
resId
=
await
getTaskCount
({});
for
(
let
i
=
0
;
i
<
res
.
data
.
length
;
i
++
)
{
res
.
data
[
i
].
count
=
resId
.
data
[
res
.
data
[
i
].
id
]
===
undefined
?
0
:
resId
.
data
[
res
.
data
[
i
].
id
];
}
taskList
.
value
=
res
.
data
;
};
// 解析cron表达式的方法
const
parseCronExpression
=
(
cronExpression
:
string
)
=>
{
const
res
=
cronExpression
.
split
(
'*'
).
length
-
1
if
(
res
>=
5
)
{
const
aaa
=
cronExpression
.
split
(
' '
)
for
(
let
i
=
0
;
i
<
aaa
.
length
;
i
++
)
{
if
(
aaa
[
i
]
!=
'*'
)
{
if
(
i
==
0
)
{
if
(
aaa
[
i
].
length
===
3
)
{
return
`每
${
aaa
[
i
][
2
]}
秒执行一次`
}
else
{
return
`每
${
aaa
[
i
][
2
]
+
aaa
[
i
][
3
]}
秒执行一次`
}
}
else
if
(
i
==
1
)
{
if
(
aaa
[
i
].
length
===
3
)
{
return
`每
${
aaa
[
i
][
2
]}
分钟执行一次`
}
else
{
return
`每
${
aaa
[
i
][
2
]
+
aaa
[
i
][
3
]}
分钟执行一次`
}
}
else
if
(
i
==
2
)
{
if
(
aaa
[
i
].
length
===
3
)
{
return
`每
${
aaa
[
i
][
2
]}
小时执行一次`
}
else
{
return
`每
${
aaa
[
i
][
2
]
+
aaa
[
i
][
3
]}
小时执行一次`
}
}
else
if
(
i
==
3
)
{
if
(
aaa
[
i
].
length
===
3
)
{
return
`每
${
aaa
[
i
][
2
]}
天执行一次`
}
else
{
return
`每
${
aaa
[
i
][
2
]
+
aaa
[
i
][
3
]}
天执行一次`
}
}
else
if
(
i
==
4
)
{
if
(
aaa
[
i
].
length
===
3
)
{
return
`每
${
aaa
[
i
][
2
]}
月执行一次`
}
else
{
return
`每
${
aaa
[
i
][
2
]
+
aaa
[
i
][
3
]}
月执行一次`
}
}
}
}
}
}
const
res
=
cronExpression
.
split
(
"*"
).
length
-
1
;
if
(
res
>=
5
)
{
const
aaa
=
cronExpression
.
split
(
" "
);
for
(
let
i
=
0
;
i
<
aaa
.
length
;
i
++
)
{
if
(
aaa
[
i
]
!=
"*"
)
{
if
(
i
==
0
)
{
if
(
aaa
[
i
].
length
===
3
)
{
return
`每
${
aaa
[
i
][
2
]}
秒执行一次`
;
}
else
{
return
`每
${
aaa
[
i
][
2
]
+
aaa
[
i
][
3
]}
秒执行一次`
;
}
}
else
if
(
i
==
1
)
{
if
(
aaa
[
i
].
length
===
3
)
{
return
`每
${
aaa
[
i
][
2
]}
分钟执行一次`
;
}
else
{
return
`每
${
aaa
[
i
][
2
]
+
aaa
[
i
][
3
]}
分钟执行一次`
;
}
}
else
if
(
i
==
2
)
{
if
(
aaa
[
i
].
length
===
3
)
{
return
`每
${
aaa
[
i
][
2
]}
小时执行一次`
;
}
else
{
return
`每
${
aaa
[
i
][
2
]
+
aaa
[
i
][
3
]}
小时执行一次`
;
}
}
else
if
(
i
==
3
)
{
if
(
aaa
[
i
].
length
===
3
)
{
return
`每
${
aaa
[
i
][
2
]}
天执行一次`
;
}
else
{
return
`每
${
aaa
[
i
][
2
]
+
aaa
[
i
][
3
]}
天执行一次`
;
}
}
else
if
(
i
==
4
)
{
if
(
aaa
[
i
].
length
===
3
)
{
return
`每
${
aaa
[
i
][
2
]}
月执行一次`
;
}
else
{
return
`每
${
aaa
[
i
][
2
]
+
aaa
[
i
][
3
]}
月执行一次`
;
}
}
}
}
}
}
;
const
getSpiderTypeList
=
async
()
=>
{
const
res
=
await
getSpiderList
({
scrapydServerId
:
'1'
,
project
:
'spiders'
})
console
.
log
(
res
,
8888888888888
);
taskSelectOptions
.
value
=
res
.
data
// taskSelectOptions.value = res.data
}
const
res
=
await
getSpiderList
({
scrapydServerId
:
"1"
,
project
:
"spiders"
});
console
.
log
(
res
,
8888888888888
);
taskSelectOptions
.
value
=
res
.
data
;
// taskSelectOptions.value = res.data
}
;
onMounted
(()
=>
{
if
(
props
.
spiderType
!==
''
)
{
searchCondition
.
value
.
spiders
=
props
.
spiderType
}
getData
()
getSpiderTypeList
()
})
if
(
props
.
spiderType
!==
""
)
{
searchCondition
.
value
.
spiders
=
props
.
spiderType
;
}
getData
();
getSpiderTypeList
();
});
// const parseCronExpression=(cronExpression: string)=> {
// try {
...
...
@@ -305,87 +318,80 @@ onMounted(() => {
<
style
lang=
"scss"
scoped
>
.cardStyle
{
display
:
flex
;
flex-wrap
:
wrap
;
margin-top
:
1.5%
;
padding
:
18px
;
gap
:
15px
;
width
:
auto
!important
;
justify-content
:
space-between
;
margin-top
:
1.5%
;
padding
:
18px
;
gap
:
15px
;
width
:
auto
!important
;
}
.taskContent
{
display
:
flex
;
flex-direction
:
column
;
align-items
:
center
;
justify-content
:
center
;
height
:
100%
;
gap
:
6px
;
/* 进一步减小项目之间的间距 */
padding
:
5px
0
;
display
:
flex
;
flex-direction
:
column
;
align-items
:
center
;
justify-content
:
center
;
height
:
100%
;
gap
:
6px
;
/* 进一步减小项目之间的间距 */
padding
:
5px
0
;
}
/* 任务卡片样式 */
.taskCard
{
margin-left
:
1%
;
background-image
:
url("@/assets/picture/box2.png")
;
background-size
:
100%
100%
;
background-repeat
:
no-repeat
;
margin-bottom
:
10px
;
width
:
380px
;
font-size
:
20px
;
min-height
:
240px
;
border-radius
:
7px
;
display
:
flex
;
flex-direction
:
column
;
margin-left
:
1%
;
background-image
:
url("@/assets/picture/box2.png")
;
background-size
:
100%
100%
;
background-repeat
:
no-repeat
;
margin-bottom
:
10px
;
width
:
380px
;
font-size
:
20px
;
min-height
:
240px
;
border-radius
:
7px
;
display
:
flex
;
flex-direction
:
column
;
}
/* 减小表单的间距 */
.form-item
{
margin-bottom
:
3px
!important
;
margin-bottom
:
3px
!important
;
}
.taskCard
.titleStyle
{
font-size
:
22px
;
color
:
#FFFFFF
;
font-size
:
22px
;
color
:
#ffffff
;
}
.taskCard
.wordStyle
{
font-size
:
16px
;
color
:
#FFFFFF
;
font-size
:
16px
;
color
:
#ffffff
;
}
/* 按钮样式微调 */
.editButton
,
.recordButton
,
.deleteButton
{
margin
:
0
3px
!important
;
margin
:
0
3px
!important
;
}
/* 工具栏样式 */
.toolbarStyle
{
background-image
:
url("@/assets/picture/box3.png")
;
background-size
:
100%
100%
;
background-repeat
:
no-repeat
;
background-image
:
url("@/assets/picture/box3.png")
;
background-size
:
100%
100%
;
background-repeat
:
no-repeat
;
}
/* 表单样式 */
.formStyle
{
display
:
flex
;
justify-content
:
space-around
;
margin-top
:
0.5%
;
padding
:
2px
;
display
:
flex
;
justify-content
:
space-around
;
margin-top
:
0.5%
;
padding
:
2px
;
}
//
去除按钮边框
.el-button
:focus
{
outline
:
none
;
color
:
#ffffff
;
border
:
none
;
outline
:
none
;
color
:
#ffffff
;
border
:
none
;
}
</
style
>
...
...
@@ -396,10 +402,10 @@ onMounted(() => {
} */
.el-input
{
color
:
#FFFFFF
;
color
:
#ffffff
;
}
.el-select__placeholder
{
color
:
#FFFFFF
;
color
:
#ffffff
;
}
</
style
>
\ No newline at end of file
</
style
>
vite.config.ts
View file @
85fdc758
...
...
@@ -31,7 +31,7 @@ export default defineConfig({
proxy
:
{
// 代理API请求,使用更精确的路径匹配
'/api'
:
{
target
:
'http://192.168.
0.176
:5001/'
,
target
:
'http://192.168.
3.10
:5001/'
,
changeOrigin
:
true
,
},
}
...
...
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