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 0b9fde76e6
commit eb93bdd5a7
9 changed files with 117 additions and 25 deletions

View File

@ -25,13 +25,13 @@
and a.group_name = #{queryDO.groupName}
</if>
<if test="queryDO.taskBatchStatus != null">
and task_status = #{queryDO.taskBatchStatus}
and task_batch_status = #{queryDO.taskBatchStatus}
</if>
<if test="queryDO.jobName != null">
and job_name like #{queryDO.jobName}
</if>
and a.deleted = 0
order by id desc
order by a.id desc
</where>
</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.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.JobRequestVO;
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.service.JobService;
import org.springframework.beans.factory.annotation.Autowired;
@ -67,4 +69,12 @@ public class JobController {
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)
@Data
public class JobBatchQueryVO extends BaseQueryVO {
private Long jobId ;
private Long jobId;
private String jobName;
private Integer taskBatchStatus;
private String groupName;

View File

@ -27,4 +27,6 @@ public interface JobService {
Boolean deleteJobById(Long id);
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())) {
queryWrapper.like(Job::getJobName, "%" + queryVO.getJobName() + "%");
queryWrapper.like(Job::getJobName, "%" + queryVO.getJobName().trim() + "%");
}
if (Objects.nonNull(queryVO.getJobStatus())) {
@ -90,7 +90,7 @@ public class JobServiceImpl implements JobService {
try {
ZonedDateTime zdt = now.atZone(ZoneOffset.ofHours(8));
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));
} catch (ParseException ignored) {
}
@ -99,6 +99,23 @@ public class JobServiceImpl implements JobService {
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
public boolean saveJob(JobRequestVO jobRequestVO) {

View File

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

View File

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

View File

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

View File

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