Commit b904cf02 by 周田

Merge branch 'yzh' into 'main'

完成了爬虫管理页面,任务执行记录页面

See merge request !7
parents b323f506 b36709fb
...@@ -76,4 +76,16 @@ export const userApi = { ...@@ -76,4 +76,16 @@ export const userApi = {
addUser: '/user/insert', addUser: '/user/insert',
updateUser: '/user/update', updateUser: '/user/update',
deleteUser: '/user/delete', deleteUser: '/user/delete',
batchDelete: '/user/batchDelete',
} as const
export const spiderApi = {
// 系统用户相关接口
spiderList: '/scrapyd/listSpiders',
} as const
export const spiderTaskApi = {
// 爬虫任务相关接口
taskList: '/schedule/getJobs',
taskRecord: '/schedule/scheduleLogs',
} as const } as const
\ No newline at end of file
import { request, POST } from '@/utils/request'
import type { ApiResponse, QueryParams ,UserQueryParams } from '@/utils/request'
import { systemApi, scrapydServerApi, spiderApi,spiderTaskApi} from './apiPaths'
// 爬虫任务执行记录
export function getSpiderTaskRecord(data: UserQueryParams) {
return request({
url: spiderTaskApi.taskRecord,
method: POST,
data
}) as unknown as Promise<ApiResponse>
}
// 爬虫任务列表
export function getSpiderTaskList(data: UserQueryParams) {
return request({
url: spiderTaskApi.taskList,
method: POST,
data
}) as unknown as Promise<ApiResponse>
}
\ No newline at end of file
import { request, POST } from '@/utils/request' import { request, POST } from '@/utils/request'
import type { ApiResponse, QueryParams } from '@/utils/request' import type { ApiResponse, QueryParams ,UserQueryParams } from '@/utils/request'
import { systemApi, scrapydServerApi } from './apiPaths' import { systemApi, scrapydServerApi, spiderApi } from './apiPaths'
// 获取系统信息 // 获取系统信息
export function getSystemInfo(): Promise<ApiResponse> { export function getSystemInfo(): Promise<ApiResponse> {
...@@ -52,3 +52,11 @@ export const getScrapydServerList = (): Promise<ApiResponse> => { ...@@ -52,3 +52,11 @@ export const getScrapydServerList = (): Promise<ApiResponse> => {
}) as unknown as Promise<ApiResponse> }) as unknown as Promise<ApiResponse>
} }
// 爬虫列表
export function getSpiderList(data: UserQueryParams) {
return request({
url: spiderApi.spiderList,
method: POST,
data
}) as unknown as Promise<ApiResponse>
}
\ No newline at end of file
...@@ -67,4 +67,13 @@ export function deleteUser(data: UserQueryParams) { ...@@ -67,4 +67,13 @@ export function deleteUser(data: UserQueryParams) {
method: POST, method: POST,
data data
}) as unknown as Promise<ApiResponse> }) as unknown as Promise<ApiResponse>
}
// 批量删除用户
export function batchDeleteUser(data: UserQueryParams) {
return request({
url: userApi.batchDelete,
method: POST,
data
}) as unknown as Promise<ApiResponse>
} }
\ No newline at end of file
/// @ts-ignore
export enum DeleteMode {
BATCH_DELETE = 0,
SINGLE_DELETE = 1,
}
...@@ -17,24 +17,32 @@ ...@@ -17,24 +17,32 @@
<script lang="ts" setup> <script lang="ts" setup>
import { ref, watch } from 'vue' import { ref, watch } from 'vue'
import { defineProps } from 'vue'; import { defineProps } from 'vue';
import { getUserList, addUser, deleteUser, updateUser, batchDeleteUser } from '@/api/user.ts'
const props = defineProps({ import { DeleteMode } from '@/components/Delete/enum.ts'
dialogVisible: { interface deleteDialogPropType {
type: Boolean, dialogVisible: boolean,
default: false deleteMode: DeleteMode,
}, id: number,
mode: { ids: number[]
type: String, }
default: '1' const props = defineProps<deleteDialogPropType>()
} const emit = defineEmits(['update:dialogVisible', 'confirm', 'getUserList', 'update:deleteMode'])
})
const emit = defineEmits(['update:dialogVisible', 'confirm'])
const deleteDialogVisible = ref(props.dialogVisible) const deleteDialogVisible = ref(props.dialogVisible)
const deleteMode = ref(props.deleteMode)
// 删除方法 // 删除方法
const handleDelelte = () => { const handleDelelte = async () => {
emit('confirm') if (props.deleteMode == DeleteMode.SINGLE_DELETE) {
deleteDialogVisible.value = false await deleteUser({ id: props.id })
emit('getUserList')
deleteDialogVisible.value = false
}
else if (props.deleteMode == DeleteMode.BATCH_DELETE) {
console.log(props.ids);
await batchDeleteUser({ ids: props.ids })
emit('getUserList')
deleteDialogVisible.value = false
}
} }
// 关闭弹窗的方法 // 关闭弹窗的方法
const close = () => { const close = () => {
...@@ -52,4 +60,16 @@ watch(() => deleteDialogVisible.value, ...@@ -52,4 +60,16 @@ watch(() => deleteDialogVisible.value,
emit('update:dialogVisible', newVal) emit('update:dialogVisible', newVal)
} }
) )
// 监听父组件传过来的值
watch(() => props.deleteMode,
(newVal) => {
deleteMode.value = newVal
}
)
// 监听组件内的值并向父组件更新
watch(() => deleteMode.value,
(newVal) => {
emit('update:deleteMode', newVal)
}
)
</script> </script>
\ No newline at end of file
...@@ -106,5 +106,11 @@ export interface UserQueryParams { ...@@ -106,5 +106,11 @@ export interface UserQueryParams {
nickname?: string nickname?: string
password?: string password?: string
role?: number role?: number
status?: boolean status?: any
id?: number
ids?: any
scrapydServerId?: string
project?: string
spiders?:any
times?:any
} }
\ No newline at end of file
...@@ -18,7 +18,7 @@ const textarea = ref('') ...@@ -18,7 +18,7 @@ const textarea = ref('')
const bactToRecord = () => { const bactToRecord = () => {
router.push({ router.push({
path: '/os-taskRecord/list', path: '/osTaskRecord/list',
}) })
} }
</script> </script>
......
...@@ -4,9 +4,9 @@ ...@@ -4,9 +4,9 @@
<div> <div>
<el-table :data="tableData" style="width: 100%" border :header-cell-style="{ textAlign: 'center' }" <el-table :data="tableData" style="width: 100%" border :header-cell-style="{ textAlign: 'center' }"
:cell-style="{ textAlign: 'center' }" :row-style="{ height: '60px' }"> :cell-style="{ textAlign: 'center' }" :row-style="{ height: '60px' }">
<el-table-column type="selection" width="40" height="40" /> <!-- <el-table-column type="selection" width="40" height="40" /> -->
<el-table-column property="number" label="序号" /> <el-table-column property="number" label="序号" type="index" width="80" />
<el-table-column property="spiderName" label="爬虫名称" show-overflow-tooltip /> <el-table-column property="spider" label="爬虫名称" show-overflow-tooltip />
<el-table-column label="查看任务"> <el-table-column label="查看任务">
<template #default="scope"> <template #default="scope">
<el-button type="primary" plain @click="handleDetails(scope.row)"> <el-button type="primary" plain @click="handleDetails(scope.row)">
...@@ -27,51 +27,9 @@ ...@@ -27,51 +27,9 @@
import { ref, onMounted } from 'vue' import { ref, onMounted } from 'vue'
import Pagination from '@/components/pagination/index.vue' import Pagination from '@/components/pagination/index.vue'
import { useRouter } from 'vue-router' import { useRouter } from 'vue-router'
import { getSpiderList } from '@/api/system.ts'
const router = useRouter() const router = useRouter()
const tableData = ref([ const tableData = ref([])
{
number: '1',
spiderName: 'sk网爬虫',
},
{
name: '2',
address: 'sk网',
},
{
name: '3',
address: 'sk网',
},
{
name: '4',
address: 'sk网',
},
{
name: '5',
address: 'sk网',
},
{
name: '6',
address: 'sk网',
},
{
name: '7',
address: 'sk网',
},
{
name: '8',
address: 'sk网',
},
{
name: '9',
address: 'sk网',
},
{
name: '10',
address: 'sk网',
},
])
const pageObj = ref({ const pageObj = ref({
total: 10, total: 10,
pageSize: 10, pageSize: 10,
...@@ -86,11 +44,13 @@ const handleDetails = (row: any) => { ...@@ -86,11 +44,13 @@ const handleDetails = (row: any) => {
} }
}) })
} }
const getData = () => { const getData = async () => {
console.log('getData'); const res = await getSpiderList({scrapydServerId:'1',project:'spiders'})
tableData.value = res.data
} }
onMounted(() => { onMounted(() => {
getData()
}) })
</script> </script>
......
<template> <template>
<el-dialog v-model="currentVisible" :title="currentMode === '1' ? '新增用户' : '编辑用户'" width="610" center align-center <el-dialog v-model="currentVisible" :title="currentMode === AddMode.ADD_MODE ? '新增用户' : '编辑用户'" width="610" center align-center
@close="handleClose" draggable> @close="handleClose" draggable>
<div v-if="currentMode === '1'"> <div v-if="currentMode === AddMode.ADD_MODE">
<el-form :inline="true" > <el-form :rules="firstFormRules" ref="firstRuleFormRef" :model="firstForm">
<el-form-item label="用户账号:"> <el-form-item label="用户账号:" prop="userAccount">
<el-input v-model="addNickName" /> <el-input v-model="firstForm.userAccount" />
</el-form-item> </el-form-item>
<el-form-item label="用户名称:" > <el-form-item label="用户名称:" prop="userName">
<el-input v-model="addUserName" /> <el-input v-model="firstForm.userName" />
</el-form-item> </el-form-item>
</el-form> <el-form-item label="用户状态:">
<div class="m-t-4" /> <el-select v-model="userStatusValue" placeholder="请选择状态" style="width: 100%;">
<el-form :inline="true"> <el-option v-for="item in userStatusOptions" :key="item.value" :label="item.label" :value="item.value" />
<el-form-item label="用户状态:"> </el-select>
<el-select v-model="userStatusValue" placeholder=" " style="width: 180px;"> </el-form-item>
<el-option v-for="item in userStatusOptions" :key="item.value" :label="item.label" :value="item.value" /> <el-form-item label="用户密码:" prop="userPassword">
</el-select> <el-input v-model="firstForm.userPassword" />
</el-form-item> </el-form-item>
<el-form-item label="用户密码:"> <el-form-item label="用户角色:">
<el-input v-model="userPassword" /> <el-select v-model="userRoleValue" placeholder="请选择角色" style="width: 100%;">
</el-form-item> <el-option v-for="item in userRoleOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-form> </el-select>
<div class="m-t-4" /> </el-form-item>
<el-form :inline="true"> </el-form>
<el-form-item label="用户角色:">
<el-select v-model="userRoleValue" placeholder=" " style="width: 180px;">
<el-option v-for="item in userRoleOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
</el-form>
</div> </div>
<div class="m-t-4"> <div v-if="currentMode === AddMode.UPDATE_MODE">
<el-form :inline="true" :rules="secondFormRules" ref="secondRuleFormRef" :model="secondForm">
<el-form-item label="用户名称:" prop="userName">
<el-input v-model="secondForm.userName" />
</el-form-item>
<el-form-item label="用户角色:">
<el-select v-model="userRoleValue" placeholder="请选择角色" style="width: 180px;">
<el-option v-for="item in userRoleOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
</el-form>
<div class="m-t-4" />
<el-form :inline="true" :rules="editPasswordRules" ref="editPasswordFormRef" :model="editPasswordForm">
<el-form-item label="用户状态:">
<el-select v-model="userStatusValue" placeholder="请选择状态" style="width: 180px;">
<el-option v-for="item in userStatusOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
<el-form-item label="用户密码:" prop="userPassword">
<el-input v-model="editPasswordForm.userPassword" placeholder="不修改请留空" />
</el-form-item>
</el-form>
</div> </div>
<div v-if="currentMode === '2'">
<el-form :inline="true" v-if="currentMode === '2'">
<el-form-item label="用户名称:" >
<el-input v-model="addNickName" />
</el-form-item>
<el-form-item label="用户角色:">
<el-select v-model="userRoleValue" placeholder=" " style="width: 180px;">
<el-option v-for="item in userRoleOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
</el-form>
<div class="m-t-4" />
<el-form :inline="true" v-if="currentMode === '2'">
<el-form-item label="用户状态:">
<el-select v-model="userStatusValue" placeholder=" " style="width: 180px;">
<el-option v-for="item in userStatusOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
<el-form-item label="用户密码:">
<el-input v-model="userPassword" />
</el-form-item>
</el-form>
</div>
<div class="m-t-4" />
<template #footer> <template #footer>
<div class="dialog-footer"> <div class="dialog-footer">
<el-button @click="handleClose">取消</el-button> <el-button @click="handleClose">取消</el-button>
...@@ -68,143 +59,181 @@ ...@@ -68,143 +59,181 @@
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { onMounted, ref } from 'vue' import { ref, watch } from 'vue'
import { defineProps } from 'vue'; import { defineProps, defineEmits } from 'vue';
import { watch } from 'vue' import { addUser, updateUser } from '@/api/user.ts'
import { getUserList, addUser, deleteUser, updateUser } from '@/api/user.ts' import type { FormInstance, FormRules } from 'element-plus'
import { ElMessage } from 'element-plus';
import { AddMode } from './enum';
interface addDialogPropType {
dialogVisible: boolean,
mode: AddMode,
nickName: string,
userName: string,
id: number,
userPassword: string,
userRole: number,
userStatus: boolean
}
const props = defineProps<addDialogPropType>()
// 定义表单数据结构(与rules对应)
const firstForm = ref({
userAccount: '', // 用户账号
userName: '', // 用户名称
userPassword: '' // 用户密码
})
const secondForm = ref({
userName: '' // 编辑模式的用户名称
})
const editPasswordForm = ref({
userPassword: '' // 编辑模式的密码
})
// 表单引用
const firstRuleFormRef = ref<FormInstance>()
const secondRuleFormRef = ref<FormInstance>()
const editPasswordFormRef = ref<FormInstance>()
// 新增模式验证规则
const firstFormRules = ref<FormRules>({
userAccount: [
{ required: true, message: '请输入用户账号', trigger: 'blur' },
{ type: 'string', min: 1, max: 20, message: '用户账号长度1-20字符', trigger: 'blur' },
{ pattern: /^[A-Za-z0-9]+$/, message: '只能包含英文字母或数字', trigger: 'blur' }
],
userName: [
{ required: true, message: '请输入用户名称', trigger: 'blur' },
{ type: 'string', min: 1, max: 20, message: '用户名称长度1-20字符', trigger: 'blur' },
],
userPassword: [
{ required: true, message: '请输入用户密码', trigger: 'blur' },
{ type: 'string', min: 6, max: 20, message: '密码长度6-20字符', trigger: 'blur' },
],
})
// 编辑模式验证规则(密码可选)
const secondFormRules = ref<FormRules>({
userName: [
{ required: true, message: '请输入用户名称', trigger: 'blur' },
{ type: 'string', min: 1, max: 20, message: '用户名称长度1-20字符', trigger: 'blur' },
],
})
const editPasswordRules = ref<FormRules>({
userPassword: [
{ type: 'string', min: 6, max: 20, message: '密码长度6-20字符', trigger: 'blur' },
],
})
// 状态选项(统一值类型,避免类型错误)
const userStatusValue = ref(true) const userStatusValue = ref(true)
const userRoleValue = ref(1) const userRoleValue = ref(1)
const userStatusOptions = [ const userStatusOptions = [
{ { value: true, label: '启用' },
value: true, { value: false, label: '停用' } // 与userStatusValue类型一致(boolean)
label: '启用'
},
{
value: '0',
label: '停用'
}
] ]
const userRoleOptions = [ const userRoleOptions = [
{ { value: false, label: '管理员' },
value: false, { value: true, label: '普通用户' } // 统一值类型
label: '管理员'
},
{
value: '0',
label: '普通用户'
}
] ]
const props = defineProps({
dialogVisible: {
type: Boolean, const emit = defineEmits(['update:dialogVisible', 'getUserList'])
default: false
}, // 组件状态
mode: {
type: String,
default: 'add'
},
nickName: {
type: String,
default: ''
},
userName: {
type: String,
default: ''
},
id: {
type: Number,
default: false
},
userPassword: {
type: String,
default: ''
},
userStatus: {
type: Boolean,
default: ''
},
userRole: {
type: Number,
default: ''
}
})
// 向父组件传递dialog值
const emit = defineEmits(['update:dialogVisible', 'confirm','getUserList'])
// 组件的状态
const currentVisible = ref(props.dialogVisible) const currentVisible = ref(props.dialogVisible)
const currentMode = ref(props.mode) const currentMode = ref(props.mode)
const addNickName = ref('')
const addUserName = ref('')
const userRemark = ref('')
const userPassword = ref('')
// 关闭的方法 // 关闭对话框
const handleClose = () => { const handleClose = () => {
currentVisible.value = false currentVisible.value = false
} }
// 确定的方法
const handleConfirm = async () => {
if (currentMode.value === '1') {
await addUser({
nickname: addNickName.value,
username: addUserName.value,
password: userPassword.value,
role: userRoleValue.value,
status: userStatusValue.value
})
console.log(addUserName.value);
emit('getUserList')
} else if (currentMode.value === '2') {
// 确认操作
const handleConfirm = async () => {
try {
if (currentMode.value === AddMode.ADD_MODE) {
if (!firstRuleFormRef.value) {
return;
}
// 3. 使用Promise形式的validate(不传入回调),确保await生效
const valid = await firstRuleFormRef.value.validate();
if (valid) {
// 进入这里即197行附近逻辑
await addUser({
nickname: firstForm.value.userName, // 注意:根据实际接口字段调整
username: firstForm.value.userAccount,
password: firstForm.value.userPassword,
role: userRoleValue.value,
status: userStatusValue.value
});
ElMessage.success('新增成功');
emit('getUserList');
currentVisible.value = false;
}
} else if (currentMode.value === AddMode.UPDATE_MODE) {
// 编辑模式逻辑(略,可参考新增模式调整)
if (!secondRuleFormRef.value) return;
const valid = await secondRuleFormRef.value.validate();
if (valid) {
// 密码非空时验证密码
if (editPasswordForm.value.userPassword) {
if (!editPasswordFormRef.value) return;
const pwdValid = await editPasswordFormRef.value.validate();
if (!pwdValid) return;
}
await updateUser({
id: props.id,
nickname: secondForm.value.userName,
role: userRoleValue.value,
status: userStatusValue.value,
...(editPasswordForm.value.userPassword && { password: editPasswordForm.value.userPassword })
});
ElMessage.success('编辑成功');
emit('getUserList');
currentVisible.value = false;
}
}
} catch (error) {
console.error(error);
} }
currentVisible.value = false };
}
// 监听props变化,同步给组件内部 watch(() => props.dialogVisible, (newVal) => {
watch(() => props.dialogVisible, currentVisible.value = newVal
(newVal) => { })
currentVisible.value = newVal
}
)
// 监听组件内部状态变化,同步给父组件,这样才能做到控制对话框组件的显隐 watch(() => currentVisible.value, (newVal) => {
watch(() => currentVisible.value, emit('update:dialogVisible', newVal)
(newVal) => { })
emit('update:dialogVisible', newVal)
} watch(() => props.mode, (newVal) => {
) currentMode.value = newVal
watch(() => props.mode, })
(newVal) => {
currentMode.value = newVal
}
)
watch( watch(
// 监听需要同步的 props 集合 [() => props.dialogVisible, () => props.mode, () => props.nickName, () => props.userPassword, () => props.userStatus, () => props.userRole],
[() => props.dialogVisible, () => props.mode, () => props.nickName, () => props.userPassword, () => props.userStatus, () => props.userRole], ([newVisible, newMode, newNickName, newPwd, newStatus, newRole]) => {
// 任一值变化时执行 if (newVisible && newMode === AddMode.UPDATE_MODE) {
([newVisible, newMode, newNickName, newPwd, newStatus, newRole]) => { secondForm.value.userName = newNickName;
if (newVisible && newMode === '2') { editPasswordForm.value.userPassword = newPwd || '';
addNickName.value = newNickName; userStatusValue.value = newStatus;
userPassword.value = newPwd; userRoleValue.value = newRole;
userStatusValue.value = newStatus; }
userRoleValue.value = newRole; if (!newVisible) {
} // 清空表单
// 弹窗关闭时,清空表单 firstForm.value = { userAccount: '', userName: '', userPassword: '' };
if (!newVisible) { secondForm.value = { userName: '' };
addNickName.value = ''; editPasswordForm.value = { userPassword: '' };
addUserName.value = ''; }
userPassword.value = ''; },
} { immediate: true }
},
{ immediate: true }
); );
</script> </script>
<style> <style>
/* 修改弹窗样式 */ /* 保持原有样式 */
.el-dialog { .el-dialog {
background: transparent; background: transparent;
background-image: url("@/assets/picture/dialog1.png"); background-image: url("@/assets/picture/dialog1.png");
...@@ -215,27 +244,26 @@ watch( ...@@ -215,27 +244,26 @@ watch(
.el-dialog__title { .el-dialog__title {
color: #ffffff; color: #ffffff;
} }
.el-input__inner{
.el-input__inner {
color: #ffffff; color: #ffffff;
} }
.el-select__wrapper{
background-color:#1d5484 ; .el-select__wrapper {
box-shadow: 0,0,0,0; background-color: #1d5484;
box-shadow: 0, 0, 0, 0;
border: none; border: none;
.el-select__placeholder{
.el-select__placeholder {
color: #ffffff; color: #ffffff;
} }
} }
} }
/* 修改表单样式 */
.el-form { .el-form {
.el-form-item__label { .el-form-item__label {
color: #ffffff; color: #ffffff;
} }
} }
</style> </style>
<style> \ No newline at end of file
</style>
\ No newline at end of file
/// @ts-ignore
export enum AddMode {
ADD_MODE = 0,
UPDATE_MODE = 1,
}
...@@ -6,18 +6,17 @@ ...@@ -6,18 +6,17 @@
<el-button type="primary" plain @click="openAddUserDialog">创建用户</el-button> <el-button type="primary" plain @click="openAddUserDialog">创建用户</el-button>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="danger" plain @click="handleDelete">批量删除</el-button> <el-button type="danger" plain @click="handleBatchDelete">批量删除</el-button>
</el-form-item> </el-form-item>
</el-form> </el-form>
</div> </div>
<el-table :data="tableData" style="width: 100%" border :header-cell-style="{ textAlign: 'center' }" <el-table :data="tableData" style="width: 100%" border :header-cell-style="{ textAlign: 'center' }"
:cell-style="{ textAlign: 'center' }" :row-style="{ height: '58px' }"> :cell-style="{ textAlign: 'center' }" :row-style="{ height: '58px' }"
@selection-change="handleSelectionChange">
<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="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 />
<!-- <el-table-column property="userRemark" label="备注" show-overflow-tooltip /> -->
<!-- <el-table-column property="userPassword" label="用户密码" show-overflow-tooltip /> -->
<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">
...@@ -32,13 +31,16 @@ ...@@ -32,13 +31,16 @@
</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 :total="pageObj.total" v-model:page="pageObj.pageNo" v-model:limit="pageObj.pageSize" <Pagination :total="pageObj.total" v-model:page="pageObj.pageNo" v-model:limit="pageObj.pageSize"
@pagination="getData" /> @pagination="getUserListData" />
</div> </div>
<!-- 删除弹窗组件 --> <!-- 删除弹窗组件 -->
<deleteDialog v-model:dialogVisible="showDeleteDialog" @mode="deleteMode" /> <deleteDialog v-model:dialogVisible="showDeleteDialog" @get-user-list="getUserListData"
:ids="userIds" :deleteMode="deleteMode" :id="userId" />
<!-- 创建用户弹窗组件 --> <!-- 创建用户弹窗组件 -->
<addUserDialog v-model:dialogVisible="dialogVisible" :mode="mode" :nick-name="nickName" :user-name="userName" :id="userId" <!-- todo -->
:user-role="userRole" :user-status="userStatus" :user-password="userPassword" @get-user-list="getUserListData" /> <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>
</template> </template>
...@@ -47,18 +49,21 @@ import { ref, onMounted } from 'vue' ...@@ -47,18 +49,21 @@ import { ref, onMounted } from 'vue'
import Pagination from '@/components/pagination/index.vue' import Pagination from '@/components/pagination/index.vue'
import deleteDialog from '@/components/Delete/index.vue' import deleteDialog from '@/components/Delete/index.vue'
import addUserDialog from './components/addUserDialog.vue' import addUserDialog from './components/addUserDialog.vue'
import { getUserList, addUser, deleteUser, updateUser } from '@/api/user.ts' import { getUserList, addUser, deleteUser, updateUser, batchDeleteUser } from '@/api/user.ts'
import { DeleteMode } from '@/components/Delete/enum.ts'
import { AddMode } from './components/enum.ts';
const userId = ref(0) const userId = ref<any>([])
const nickName = ref('') const userIds = ref<any>()
const userName = ref('') const nickName = ref<string>('')
const userRole = ref(0) const userName = ref<string>('')
const userStatus = ref(true) const userRole = ref<number>(0)
const userPassword = ref('') const userStatus = ref<boolean>(true)
const userPassword = ref<string>('')
const showDeleteDialog = ref(false) const showDeleteDialog = ref(false)
const deleteMode = ref('2') const deleteMode = ref<DeleteMode>(DeleteMode.SINGLE_DELETE)
const dialogVisible = ref(false) const dialogVisible = ref<boolean>(false)
const mode = ref('1') const mode = ref<AddMode>(AddMode.ADD_MODE)
const tableData = ref() const tableData = ref()
const pageObj = ref({ const pageObj = ref({
total: 12, total: 12,
...@@ -66,40 +71,49 @@ const pageObj = ref({ ...@@ -66,40 +71,49 @@ const pageObj = ref({
pageNo: 1 pageNo: 1
}) })
const handleEdit = async (row: any) => { const handleEdit = async (row: any) => {
mode.value = '2' mode.value = AddMode.UPDATE_MODE
nickName.value = row.nickname nickName.value = row.nickname
userName.value = row.username userName.value = row.username
userRole.value = row.role userRole.value = row.role
userStatus.value = row.status userStatus.value = row.status
userPassword.value = row.password userPassword.value = row.password
dialogVisible.value = true dialogVisible.value = true
userId.value = row.id
// console.log(row); // console.log(row);
} }
const handleDelete = (row: any) => { const handleDelete = async (row: any) => {
showDeleteDialog.value = true showDeleteDialog.value = true
deleteMode.value = DeleteMode.SINGLE_DELETE
userId.value = row.id
console.log(userId.value);
} }
const handleBatchDelete = async () => {
const getData = (number: number) => { deleteMode.value = DeleteMode.BATCH_DELETE
// console.log('getData'); showDeleteDialog.value = true
console.log(number);
} }
const handleSelectionChange = (data: any) => {
const handleDeleteConfirm = () => { let array = []
for (let i = 0; i < data.length; i++) {
array.push(data[i].id)
}
userIds.value = array
console.log(userIds.value);
} }
const openAddUserDialog = () => { const openAddUserDialog = () => {
mode.value = '1' mode.value = AddMode.ADD_MODE
dialogVisible.value = true dialogVisible.value = true
} }
const getUserListData = async () => { const getUserListData = async () => {
const userList = await getUserList({ const userList = await getUserList({
page: 1, // page: 1,
size: 10 size: 10
}) })
tableData.value = userList.data tableData.value = userList.data
console.log(tableData.value); pageObj.value.total = tableData.value.length
console.log(tableData.value.length);
} }
onMounted(async () => { onMounted(async () => {
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
<div class="m-t-4" /> <div class="m-t-4" />
<el-form :inline="true"> <el-form :inline="true">
<el-form-item label="所属爬虫:"> <el-form-item label="所属爬虫:">
<el-select v-model="spiderTypeValue" placeholder="请选择爬虫类型" style="width: 183px"> <el-select v-model="spiderTypeValue" placeholder="请选择爬虫类型" style="width: 181px">
<el-option v-for="item in spiderTypeOptions" :key="item.value" :label="item.label" :value="item.value" /> <el-option v-for="item in spiderTypeOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select> </el-select>
</el-form-item> </el-form-item>
......
...@@ -46,10 +46,11 @@ ...@@ -46,10 +46,11 @@
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { ref } from 'vue' import { ref, onMounted } from 'vue'
import { useRouter } from 'vue-router' import { useRouter } from 'vue-router'
import deleteDialog from '@/components/Delete/index.vue' import deleteDialog from '@/components/Delete/index.vue'
import addTaskDialog from './addTaskDialog.vue' import addTaskDialog from './addTaskDialog.vue'
import { getSpiderTaskList } from '@/api/spiderTask'
defineProps({ defineProps({
successTask: { successTask: {
type: String, type: String,
...@@ -159,6 +160,17 @@ const handleEdit = () => { ...@@ -159,6 +160,17 @@ const handleEdit = () => {
const handleDeleteConfirm = () => { const handleDeleteConfirm = () => {
} }
const getData = async () => {
console.log('getData');
const res = await getSpiderTaskList({spiders:['api_spider']})
// taskList.value = res.data
console.log(res);
}
onMounted(() => {
getData()
})
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
......
<template> <template>
<div> <div>
<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-5" /> <div class="m-t-10" />
<div class="text-left p-4 toolbarStyle"> <div class="text-left p-4 toolbarStyle">
<div class="formStyle"> <div class="formStyle">
<el-form inline> <el-form inline>
...@@ -36,10 +36,10 @@ ...@@ -36,10 +36,10 @@
</div> </div>
<div class="cardStyle"> <div class="cardStyle">
<taskCard successTask="100" failTask="10" unusualTask="1" /> <taskCard successTask="100" failTask="10" unusualTask="1" />
<div class="pagination w-full flex flex-row-reverse pr-18 m-t-0"> <!-- <div class="pagination w-full flex flex-row-reverse pr-18 m-t-0">
<Pagination :total="pageObj.total" v-model:page="pageObj.pageNo" v-model:limit="pageObj.pageSize" <Pagination :total="pageObj.total" v-model:page="pageObj.pageNo" v-model:limit="pageObj.pageSize"
@pagination="getData" /> @pagination="getData" />
</div> </div> -->
</div> </div>
<!-- 添加任务对话框组件 --> <!-- 添加任务对话框组件 -->
<addTaskDialog v-model:dialogVisible="showDialog" @confirm="handleDeleteConfirm" :mode="editMode" /> <addTaskDialog v-model:dialogVisible="showDialog" @confirm="handleDeleteConfirm" :mode="editMode" />
...@@ -54,10 +54,13 @@ import taskCard from './components/taskCard.vue' ...@@ -54,10 +54,13 @@ import taskCard from './components/taskCard.vue'
import addTaskDialog from './components/addTaskDialog.vue' import addTaskDialog from './components/addTaskDialog.vue'
import { useRouter } from 'vue-router' import { useRouter } from 'vue-router'
import { useRoute } from 'vue-router' import { useRoute } from 'vue-router'
import { getSpiderTaskList } from '@/api/spiderTask'
const route = useRoute() const route = useRoute()
const router = useRouter() const router = useRouter()
const editMode = ref('1') const editMode = ref('1')
const taskValue = ref('') const taskValue = ref('')
const taskList = ref([])
const taskOptions = [ const taskOptions = [
{ {
value: 'task1', value: 'task1',
...@@ -77,9 +80,7 @@ const pageObj = ref({ ...@@ -77,9 +80,7 @@ const pageObj = ref({
pageSize: 10, pageSize: 10,
pageNo: 1 pageNo: 1
}) })
const getData = () => {
console.log('getData');
}
// 控制对话框显示/隐藏的状态变量 // 控制对话框显示/隐藏的状态变量
const showDialog = ref(false) const showDialog = ref(false)
...@@ -105,8 +106,8 @@ onMounted(() => { ...@@ -105,8 +106,8 @@ onMounted(() => {
background-image: url("@/assets/picture/back.png"); background-image: url("@/assets/picture/back.png");
background-size: 100% 100%; background-size: 100% 100%;
background-repeat: no-repeat; background-repeat: no-repeat;
height: 5vh; height: 7vh;
width: 5%; width: 7%;
display: flex; display: flex;
margin-left: 0.8%; margin-left: 0.8%;
} }
......
...@@ -6,38 +6,28 @@ ...@@ -6,38 +6,28 @@
<div class="formStyle"> <div class="formStyle">
<el-form inline> <el-form inline>
<el-form-item> <el-form-item>
<el-text class="mx-1">任务名称:</el-text>
</el-form-item>
<el-form-item>
<div>
<el-select v-model="taskValue" placeholder="请选择" style="width: 220px">
<el-option v-for="item in taskOptions" :key="item.value" :label="item.label"
:value="item.value" />
</el-select>
</div>
</el-form-item>
<el-form-item>
<el-text class="mx-1">时间:</el-text> <el-text class="mx-1">时间:</el-text>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-date-picker v-model="timeValue" type="datetimerange" start-placeholder="Start date" <el-date-picker v-model="timeValue" type="datetimerange" start-placeholder="Start date"
end-placeholder="End date" format="YYYY-MM-DD HH:mm:ss" date-format="YYYY/MM/DD ddd" end-placeholder="End date" format="YYYY-MM-DD HH:mm:ss" date-format="YYYY/MM/DD ddd"
time-format="A hh:mm:ss" /> time-format="A hh:mm:ss" value-format="YYYY-MM-DD HH:mm:ss"/>
</el-form-item> </el-form-item>
<el-form-item> <!-- <el-form-item>
<el-text class="mx-1">调度状态:</el-text> <el-text class="mx-1">调度状态:</el-text>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<div> <div>
<el-select v-model="taskValue" placeholder="请选择" style="width: 220px"> <el-select v-model="taskValue" placeholder="请选择" style="width: 220px">
<el-option v-for="item in taskOptions" :key="item.value" :label="item.label" <el-option v-for="item in taskOptions" :key="item.value" :label="item.label" :value="item.value" />
:value="item.value" />
</el-select> </el-select>
</div> </div>
</el-form-item> </el-form-item> -->
<el-form-item> <el-form-item>
<el-space> <el-space>
<el-button type="primary">查询</el-button> <el-button type="primary" @click="searchData">查询</el-button>
<el-button type="primary" @click="getData">重置表格</el-button>
</el-space> </el-space>
</el-form-item> </el-form-item>
</el-form> </el-form>
...@@ -47,27 +37,36 @@ ...@@ -47,27 +37,36 @@
<div> <div>
<el-table :data="tableData" style="width: 100%" border :header-cell-style="{ textAlign: 'center' }" <el-table :data="tableData" style="width: 100%" border :header-cell-style="{ textAlign: 'center' }"
:cell-style="{ textAlign: 'center' }"> :cell-style="{ textAlign: 'center' }">
<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" /> <el-table-column property="project" label="项目名称" show-overflow-tooltip />
<el-table-column property="taskName" label="任务名称" show-overflow-tooltip /> <el-table-column property="spider" label="所属爬虫" show-overflow-tooltip />
<el-table-column property="scheduleMode" label="调度模式" show-overflow-tooltip /> <el-table-column property="schedule_mode" label="调度模式" show-overflow-tooltip />
<el-table-column property="scheduleStatus" label="调度状态" show-overflow-tooltip /> <el-table-column property="run_status" label="调度状态" show-overflow-tooltip>
<el-table-column property="errorMessage" label="错误消息" show-overflow-tooltip /> <template #default="scope">
<el-table-column property="runningStatus" label="运行状态" show-overflow-tooltip /> {{ '已完成' }}
<el-table-column property="duration" label="持续时间" show-overflow-tooltip /> </template>
<el-table-column property="scheduleTime" label="调度时间" width="200" show-overflow-tooltip /> </el-table-column>
<el-table-column label="运行日志" width="120"> <el-table-column label="错误消息" show-overflow-tooltip>
<!-- 当错误消息为空时默认值为'-' -->
<template #default="scope">
{{ scope.row.message || '-' }}
</template>
</el-table-column>
<el-table-column property="run_status" label="运行状态" show-overflow-tooltip />
<!-- <el-table-column property="duration" label="持续时间" show-overflow-tooltip /> -->
<el-table-column property="create_time" label="调度时间" width="200" show-overflow-tooltip />
<!-- <el-table-column label="运行日志" width="120">
<template #default="scope"> <template #default="scope">
<el-button size="small" plain type="primary" @click="handleDetails(scope.row)"> <el-button size="small" plain type="primary" @click="handleDetails(scope.row)">
日志 日志
</el-button> </el-button>
</template> </template>
</el-table-column> </el-table-column> -->
</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 :total="pageObj.total" v-model:page="pageObj.pageNo" v-model:limit="pageObj.pageSize" <Pagination :total="pageObj.total" v-model:page="pageObj.pageNo" v-model:limit="pageObj.pageSize"
@pagination="getData" /> @pagination="getData" v-model:pagerCount="pageObj.pagerCount" />
</div> </div>
</div> </div>
</template> </template>
...@@ -77,6 +76,7 @@ import { ref, onMounted } from 'vue' ...@@ -77,6 +76,7 @@ import { ref, onMounted } from 'vue'
import Pagination from '@/components/pagination/index.vue' import Pagination from '@/components/pagination/index.vue'
import { useRoute } from 'vue-router' import { useRoute } from 'vue-router'
import { useRouter } from 'vue-router' import { useRouter } from 'vue-router'
import { getSpiderTaskRecord } from '@/api/spiderTask.ts'
const route = useRoute() const route = useRoute()
const router = useRouter() const router = useRouter()
...@@ -96,121 +96,12 @@ const taskOptions = [ ...@@ -96,121 +96,12 @@ const taskOptions = [
label: '网', label: '网',
}, },
] ]
const tableData = ref([ const tableData = ref([])
{
number: '1',
taskName: 'dsn爬虫任务',
scheduleMode: '自动',
scheduleStatus: '自动',
errorMessage: '无',
runningStatus: '完成',
duration: '10s',
scheduleTime: '2023-05-13 10:00:00',
},
{
name: '1',
address: 'sk网',
address1: '成功',
address2: '100',
address3: '0',
address4: '无',
address5: '10s',
address6: '2023-05-13 10:00:00',
status: 0
},
{
name: '1',
address: 'sk网',
address1: '成功',
address2: '100',
address3: '0',
address4: '无',
address5: '10s',
address6: '2023-05-13 10:00:00',
status: 0
},
{
name: '1',
address: 'sk网',
address1: '成功',
address2: '100',
address3: '0',
address4: '无',
address5: '10s',
address6: '2023-05-13 10:00:00',
status: 0
},
{
name: '1',
address: 'sk网',
address1: '成功',
address2: '100',
address3: '0',
address4: '无',
address5: '10s',
address6: '2023-05-13 10:00:00',
status: 0
},
{
name: '1',
address: 'sk网',
address1: '成功',
address2: '100',
address3: '0',
address4: '无',
address5: '10s',
address6: '2023-05-13 10:00:00',
status: 0
}, {
name: '1',
address: 'sk网',
address1: '成功',
address2: '100',
address3: '0',
address4: '无',
address5: '10s',
address6: '2023-05-13 10:00:00',
status: 0
}
, {
name: '1',
address: 'sk网',
address1: '成功',
address2: '100',
address3: '0',
address4: '无',
address5: '10s',
address6: '2023-05-13 10:00:00',
status: 0
},
{
name: '1',
address: 'sk网',
address1: '成功',
address2: '100',
address3: '0',
address4: '无',
address5: '10s',
address6: '2023-05-13 10:00:00',
status: 0
},
{
name: '1',
address: 'sk网',
address1: '成功',
address2: '100',
address3: '0',
address4: '无',
address5: '10s',
address6: '2023-05-13 10:00:00',
status: 0
}
])
const pageObj = ref({ const pageObj = ref({
total: 10, total: 10,
pageSize: 10, pageSize: 10,
pageNo: 1 pageNo: 1,
pagerCount: 5,
}) })
const handleDetails = (row: any) => { const handleDetails = (row: any) => {
console.log(row); console.log(row);
...@@ -235,12 +126,26 @@ const goToStatus = () => { ...@@ -235,12 +126,26 @@ const goToStatus = () => {
} }
const getData = () => { // 获取任务执行记录列表
console.log('getData'); const getData = async () => {
const res = await getSpiderTaskRecord({ page: pageObj.value.pageNo, size: pageObj.value.pageSize, status: 'total' })
pageObj.value.total = res.data.total
tableData.value = res.data.list
} }
onMounted(() => { const searchData = async () => {
let resTime = []
const startTime = timeValue.value[0]
const endTime = timeValue.value[1]
resTime.push(startTime)
resTime.push(endTime)
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
}
onMounted(() => {
getData()
}) })
</script> </script>
......
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
"strict": true, "strict": true,
"noUnusedLocals": true, "noUnusedLocals": true,
"noUnusedParameters": true, "noUnusedParameters": true,
"erasableSyntaxOnly": true, "erasableSyntaxOnly": false,
"noFallthroughCasesInSwitch": true, "noFallthroughCasesInSwitch": true,
"noUncheckedSideEffectImports": true "noUncheckedSideEffectImports": true
}, },
......
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