feat:2.4.0

1. job列表页新增jobName模糊搜索
2. jobBatch列表页支持下拉选择任务进行搜索
3. 修复jobBatchList通过状态查询失败问题
This commit is contained in:
byteblogs168 2023-10-22 23:46:51 +08:00
parent 60d52e8524
commit 820cd7a3f4
9 changed files with 117 additions and 25 deletions

View File

@ -25,13 +25,13 @@
and a.group_name = #{queryDO.groupName} and a.group_name = #{queryDO.groupName}
</if> </if>
<if test="queryDO.taskBatchStatus != null"> <if test="queryDO.taskBatchStatus != null">
and task_status = #{queryDO.taskBatchStatus} and task_batch_status = #{queryDO.taskBatchStatus}
</if> </if>
<if test="queryDO.jobName != null"> <if test="queryDO.jobName != null">
and job_name like #{queryDO.jobName} and job_name like #{queryDO.jobName}
</if> </if>
and a.deleted = 0 and a.deleted = 0
order by id desc order by a.id desc
</where> </where>
</select> </select>

View File

@ -2,9 +2,11 @@ package com.aizuda.easy.retry.server.web.controller;
import com.aizuda.easy.retry.server.web.annotation.LoginRequired; import com.aizuda.easy.retry.server.web.annotation.LoginRequired;
import com.aizuda.easy.retry.server.web.model.base.PageResult; import com.aizuda.easy.retry.server.web.model.base.PageResult;
import com.aizuda.easy.retry.server.web.model.request.JobBatchQueryVO;
import com.aizuda.easy.retry.server.web.model.request.JobQueryVO; import com.aizuda.easy.retry.server.web.model.request.JobQueryVO;
import com.aizuda.easy.retry.server.web.model.request.JobRequestVO; import com.aizuda.easy.retry.server.web.model.request.JobRequestVO;
import com.aizuda.easy.retry.server.web.model.request.JobUpdateJobStatusRequestVO; import com.aizuda.easy.retry.server.web.model.request.JobUpdateJobStatusRequestVO;
import com.aizuda.easy.retry.server.web.model.response.JobBatchResponseVO;
import com.aizuda.easy.retry.server.web.model.response.JobResponseVO; import com.aizuda.easy.retry.server.web.model.response.JobResponseVO;
import com.aizuda.easy.retry.server.web.service.JobService; import com.aizuda.easy.retry.server.web.service.JobService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -67,4 +69,12 @@ public class JobController {
return jobService.getTimeByCron(cron); return jobService.getTimeByCron(cron);
} }
@GetMapping("/job-name/list")
@LoginRequired
public List<JobResponseVO> getJobNameList(
@RequestParam(value = "keywords", required = false) String keywords,
@RequestParam(value = "jobId", required = false) Long jobId
) {
return jobService.getJobNameList(keywords, jobId);
}
} }

View File

@ -12,7 +12,7 @@ import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
@Data @Data
public class JobBatchQueryVO extends BaseQueryVO { public class JobBatchQueryVO extends BaseQueryVO {
private Long jobId ; private Long jobId;
private String jobName; private String jobName;
private Integer taskBatchStatus; private Integer taskBatchStatus;
private String groupName; private String groupName;

View File

@ -27,4 +27,6 @@ public interface JobService {
Boolean deleteJobById(Long id); Boolean deleteJobById(Long id);
List<String> getTimeByCron(String cron); List<String> getTimeByCron(String cron);
List<JobResponseVO> getJobNameList(String keywords, Long jobId);
} }

View File

@ -58,7 +58,7 @@ public class JobServiceImpl implements JobService {
} }
if (StrUtil.isNotBlank(queryVO.getJobName())) { if (StrUtil.isNotBlank(queryVO.getJobName())) {
queryWrapper.like(Job::getJobName, "%" + queryVO.getJobName() + "%"); queryWrapper.like(Job::getJobName, "%" + queryVO.getJobName().trim() + "%");
} }
if (Objects.nonNull(queryVO.getJobStatus())) { if (Objects.nonNull(queryVO.getJobStatus())) {
@ -90,7 +90,7 @@ public class JobServiceImpl implements JobService {
try { try {
ZonedDateTime zdt = now.atZone(ZoneOffset.ofHours(8)); ZonedDateTime zdt = now.atZone(ZoneOffset.ofHours(8));
nextValidTime = new CronExpression(cron).getNextValidTimeAfter(Date.from(zdt.toInstant())); nextValidTime = new CronExpression(cron).getNextValidTimeAfter(Date.from(zdt.toInstant()));
now = LocalDateTime.ofEpochSecond( nextValidTime.getTime() / 1000,0, ZoneOffset.ofHours(8)); now = LocalDateTime.ofEpochSecond(nextValidTime.getTime() / 1000, 0, ZoneOffset.ofHours(8));
list.add(dateTimeFormatter.format(now)); list.add(dateTimeFormatter.format(now));
} catch (ParseException ignored) { } catch (ParseException ignored) {
} }
@ -99,6 +99,23 @@ public class JobServiceImpl implements JobService {
return list; return list;
} }
@Override
public List<JobResponseVO> getJobNameList(String keywords, Long jobId) {
LambdaQueryWrapper<Job> queryWrapper = new LambdaQueryWrapper<Job>()
.select(Job::getId, Job::getJobName);
if (StrUtil.isNotBlank(keywords)) {
queryWrapper.like(Job::getJobName, "%" + keywords.trim() + "%");
}
if (Objects.nonNull(jobId)) {
queryWrapper.eq(Job::getId, jobId);
}
PageDTO<Job> pageDTO = new PageDTO<>(1, 20);
PageDTO<Job> selectPage = jobMapper.selectPage(pageDTO, queryWrapper);
return JobResponseVOConverter.INSTANCE.toJobResponseVOs(selectPage.getRecords());
}
@Override @Override
public boolean saveJob(JobRequestVO jobRequestVO) { public boolean saveJob(JobRequestVO jobRequestVO) {

View File

@ -8,6 +8,7 @@ const jobApi = {
updateJobStatus: '/job/status', updateJobStatus: '/job/status',
delJob: '/job/', delJob: '/job/',
timeByCron: '/job/cron', timeByCron: '/job/cron',
jobNameList: '/job/job-name/list',
// 任务批次 // 任务批次
jobBatchList: '/job/batch/list', jobBatchList: '/job/batch/list',
@ -22,6 +23,14 @@ const jobApi = {
export default jobApi export default jobApi
export function jobNameList (parameter) {
return request({
url: jobApi.jobNameList,
method: 'get',
params: parameter
})
}
export function timeByCron (parameter) { export function timeByCron (parameter) {
return request({ return request({
url: jobApi.timeByCron, url: jobApi.timeByCron,

View File

@ -16,13 +16,28 @@
</a-col> </a-col>
<a-col :md="8" :sm="24"> <a-col :md="8" :sm="24">
<a-form-item label="任务名称"> <a-form-item label="任务名称">
<a-input v-model="queryParam.jobName" placeholder="请输入任务名称" allowClear /> <a-select
show-search
v-model="queryParam.jobId"
placeholder="请输入任务名称"
:default-active-first-option="false"
:show-arrow="true"
:filter-option="false"
:not-found-content="null"
@search="handleSearch"
@change="handleChange"
>
<a-select-option v-for="(item, index) in jobNameList" :value="item.id" :key="index">
{{ item.jobName }}
</a-select-option>
</a-select>
</a-form-item> </a-form-item>
</a-col> </a-col>
<a-col :md="8" :sm="24"> <a-col :md="8" :sm="24">
<a-form-item label="状态"> <a-form-item label="状态">
<a-select v-model="queryParam.taskBatchStatus" placeholder="请选择状态" allowClear> <a-select v-model="queryParam.taskBatchStatus" placeholder="请选择状态" allowClear>
<a-select-option v-for="(item, index) in taskStatus" :value="index" :key="index"> <a-select-option v-for="(item, index) in taskBatchStatus" :value="index" :key="index">
{{ item.name }}</a-select-option {{ item.name }}</a-select-option
> >
</a-select> </a-select>
@ -79,8 +94,9 @@
:data="loadData" :data="loadData"
:alert="options.alert" :alert="options.alert"
:rowSelection="options.rowSelection" :rowSelection="options.rowSelection"
:scroll="{ x: 1800 }"
> >
<span slot="serial" slot-scope="text, record"> <span slot="serial" slot-scope="record">
{{ record.id }} {{ record.id }}
</span> </span>
<span slot="taskBatchStatus" slot-scope="text"> <span slot="taskBatchStatus" slot-scope="text">
@ -142,7 +158,7 @@
import ATextarea from 'ant-design-vue/es/input/TextArea' import ATextarea from 'ant-design-vue/es/input/TextArea'
import AInput from 'ant-design-vue/es/input/Input' import AInput from 'ant-design-vue/es/input/Input'
import { STable } from '@/components' import { STable } from '@/components'
import { jobBatchList } from '@/api/jobApi' import { jobBatchList, jobNameList } from '@/api/jobApi'
import { getAllGroupNameList } from '@/api/manage' import { getAllGroupNameList } from '@/api/manage'
const enums = require('@/utils/enum') const enums = require('@/utils/enum')
@ -162,38 +178,46 @@ export default {
// / // /
advanced: false, advanced: false,
// //
queryParam: {}, queryParam: {
jobId: null
},
taskBatchStatus: enums.taskBatchStatus, taskBatchStatus: enums.taskBatchStatus,
operationReason: enums.operationReason, operationReason: enums.operationReason,
// //
columns: [ columns: [
{ {
title: 'ID', title: 'ID',
scopedSlots: { customRender: 'serial' } scopedSlots: { customRender: 'serial' },
width: '5%'
}, },
{ {
title: '组名称', title: '组名称',
dataIndex: 'groupName', dataIndex: 'groupName',
ellipsis: true ellipsis: true,
width: '15%'
}, },
{ {
title: '任务名称', title: '任务名称',
dataIndex: 'jobName', dataIndex: 'jobName',
ellipsis: true ellipsis: true,
width: '15%'
},
{
title: '开始执行时间',
dataIndex: 'executionAt',
width: '10%'
}, },
{ {
title: '状态', title: '状态',
dataIndex: 'taskBatchStatus', dataIndex: 'taskBatchStatus',
scopedSlots: { customRender: 'taskBatchStatus' } scopedSlots: { customRender: 'taskBatchStatus' },
}, width: '5%'
{
title: '开始执行时间',
dataIndex: 'executionAt'
}, },
{ {
title: '操作原因', title: '操作原因',
dataIndex: 'operationReason', dataIndex: 'operationReason',
scopedSlots: { customRender: 'operationReason' } scopedSlots: { customRender: 'operationReason' },
width: '15%'
}, },
{ {
title: '创建时间', title: '创建时间',
@ -211,6 +235,7 @@ export default {
], ],
// Promise // Promise
loadData: (parameter) => { loadData: (parameter) => {
// this.queryParam['jobId'] = this.$route.query.jobId
return jobBatchList(Object.assign(parameter, this.queryParam)).then((res) => { return jobBatchList(Object.assign(parameter, this.queryParam)).then((res) => {
return res return res
}) })
@ -233,7 +258,7 @@ export default {
}, },
optionAlertShow: false, optionAlertShow: false,
groupNameList: [], groupNameList: [],
sceneList: [] jobNameList: []
} }
}, },
created () { created () {
@ -242,7 +267,16 @@ export default {
if (this.groupNameList !== null && this.groupNameList.length > 0) { if (this.groupNameList !== null && this.groupNameList.length > 0) {
this.queryParam['groupName'] = this.groupNameList[0] this.queryParam['groupName'] = this.groupNameList[0]
this.$refs.table.refresh(true) this.$refs.table.refresh(true)
this.handleChange(this.groupNameList[0]) }
})
const jobId = this.$route.query.jobId
jobNameList({ jobId: jobId }).then(res => {
this.jobNameList = res.data
console.log(jobId)
if (jobId) {
this.queryParam['jobId'] = this.jobNameList[0].id
this.$refs.table.refresh(true)
} }
}) })
}, },
@ -253,7 +287,16 @@ export default {
handleBatchNew () { handleBatchNew () {
this.$refs.batchSaveRetryTask.isShow(true, null) this.$refs.batchSaveRetryTask.isShow(true, null)
}, },
handleSearch (value) {
console.log(`selected ${value}`)
jobNameList({ keywords: value }).then(res => {
this.jobNameList = res.data
})
},
handleChange (value) { handleChange (value) {
console.log(`handleChange ${value}`)
// this.queryParam['jobId'] = value
// this.$refs.table.refresh(true)
}, },
toggleAdvanced () { toggleAdvanced () {
this.advanced = !this.advanced this.advanced = !this.advanced

View File

@ -78,6 +78,7 @@
:rowKey="(record) => record.id" :rowKey="(record) => record.id"
:columns="columns" :columns="columns"
:data="loadData" :data="loadData"
:scroll="{ x: 2000 }"
> >
<span slot="serial" slot-scope="text, record"> <span slot="serial" slot-scope="text, record">
{{ record.id }} {{ record.id }}
@ -112,6 +113,8 @@
<template> <template>
<a @click="handleInfo(record)">详情</a> <a @click="handleInfo(record)">详情</a>
<a-divider type="vertical" /> <a-divider type="vertical" />
<a @click="goJobBatchList(record)">批次</a>
<a-divider type="vertical" />
<a @click="handleEdit(record)">编辑</a> <a @click="handleEdit(record)">编辑</a>
<a-divider type="vertical" /> <a-divider type="vertical" />
<a-popconfirm <a-popconfirm
@ -182,16 +185,19 @@ export default {
columns: [ columns: [
{ {
title: 'ID', title: 'ID',
scopedSlots: { customRender: 'serial' } scopedSlots: { customRender: 'serial' },
width: '4%'
}, },
{ {
title: '组名称', title: '组名称',
dataIndex: 'groupName' dataIndex: 'groupName',
width: '10%'
}, },
{ {
title: '任务名称', title: '任务名称',
dataIndex: 'jobName', dataIndex: 'jobName',
ellipsis: true ellipsis: true,
width: '10%'
}, },
{ {
title: '触发时间', title: '触发时间',
@ -284,6 +290,9 @@ export default {
handleEdit (record) { handleEdit (record) {
this.$router.push({ path: '/job/config', query: { id: record.id } }) this.$router.push({ path: '/job/config', query: { id: record.id } })
}, },
goJobBatchList (record) {
this.$router.push({ path: '/job/batch/list', query: { jobId: record.id } })
},
handleNew () { handleNew () {
this.$router.push({ path: '/job/config' }) this.$router.push({ path: '/job/config' })
}, },

View File

@ -83,6 +83,7 @@
:data="loadData" :data="loadData"
:alert="options.alert" :alert="options.alert"
:rowSelection="options.rowSelection" :rowSelection="options.rowSelection"
:scroll="{ x: 2000 }"
> >
<span slot="serial" slot-scope="text, record"> <span slot="serial" slot-scope="text, record">
{{ record.id }} {{ record.id }}
@ -140,7 +141,8 @@ export default {
columns: [ columns: [
{ {
title: 'ID', title: 'ID',
scopedSlots: { customRender: 'serial' } scopedSlots: { customRender: 'serial' },
width: '8%'
}, },
{ {
title: '组名称', title: '组名称',