feat: 2.5.0 定时任务添加告警通知
This commit is contained in:
parent
4d2c1ebfe5
commit
0f8e928bb6
@ -0,0 +1,59 @@
|
||||
package com.aizuda.easy.retry.common.core.enums;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 通知场景枚举
|
||||
*
|
||||
* @author: zuoJunLin
|
||||
* @date : 2023-12-02 18:18
|
||||
*/
|
||||
@Getter
|
||||
public enum JobNotifySceneEnum {
|
||||
|
||||
|
||||
|
||||
JOB_TASK_ERROR(1, "JOB任务执行失败", NodeTypeEnum.SERVER);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 通知场景
|
||||
*/
|
||||
private final int notifyScene;
|
||||
|
||||
/**
|
||||
* 触发通知节点类型
|
||||
*/
|
||||
private final NodeTypeEnum nodeType;
|
||||
|
||||
/**
|
||||
* 描述
|
||||
*/
|
||||
private final String desc;
|
||||
|
||||
JobNotifySceneEnum(int notifyScene, String desc, NodeTypeEnum nodeType) {
|
||||
this.notifyScene = notifyScene;
|
||||
this.desc = desc;
|
||||
this.nodeType = nodeType;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取通知场景
|
||||
*
|
||||
* @param notifyScene 场景
|
||||
* @param nodeType 触发通知节点类型
|
||||
* @return this
|
||||
*/
|
||||
public static JobNotifySceneEnum getJobNotifyScene(int notifyScene, NodeTypeEnum nodeType) {
|
||||
for (JobNotifySceneEnum sceneEnum : JobNotifySceneEnum.values()) {
|
||||
if (sceneEnum.getNotifyScene() == notifyScene && sceneEnum.nodeType.getType().equals(nodeType.getType())) {
|
||||
return sceneEnum;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -14,6 +14,11 @@ public class JobBatchResponseDO {
|
||||
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 命名空间
|
||||
*/
|
||||
private String namespaceId;
|
||||
|
||||
/**
|
||||
* 组名称
|
||||
*/
|
||||
@ -57,12 +62,15 @@ public class JobBatchResponseDO {
|
||||
/**
|
||||
* 执行器名称
|
||||
*/
|
||||
private String executorName;
|
||||
private String executorInfo;
|
||||
|
||||
|
||||
private Integer taskType;
|
||||
private Integer blockStrategy;
|
||||
private Integer triggerType;
|
||||
|
||||
private String argsStr;
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,21 @@
|
||||
package com.aizuda.easy.retry.template.datasource.persistence.dataobject;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author zuoJunLin
|
||||
* @date 2023-12-02 23:03:01
|
||||
* @since 2.4.0
|
||||
*/
|
||||
@Data
|
||||
public class JobNotifyConfigQueryDO {
|
||||
|
||||
private String groupName;
|
||||
|
||||
private Long jobId;
|
||||
/**
|
||||
* 命名空间id
|
||||
*/
|
||||
private String namespaceId;
|
||||
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
package com.aizuda.easy.retry.template.datasource.persistence.dataobject;
|
||||
|
||||
import lombok.Data;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* @author zuoJunLin
|
||||
* @date 2023-12-02 23:03:01
|
||||
* @since 2.4.0
|
||||
*/
|
||||
@Data
|
||||
public class JobNotifyConfigResponseDO {
|
||||
|
||||
private Long id;
|
||||
|
||||
private String namespaceId;
|
||||
|
||||
private String groupName;
|
||||
|
||||
private Long jobId;
|
||||
|
||||
private String jobName;
|
||||
|
||||
private Integer notifyStatus;
|
||||
|
||||
private Integer notifyType;
|
||||
|
||||
private String notifyAttribute;
|
||||
|
||||
private Integer notifyThreshold;
|
||||
|
||||
private Integer notifyScene;
|
||||
|
||||
private Integer rateLimiterStatus;
|
||||
|
||||
private Integer rateLimiterThreshold;
|
||||
|
||||
private String description;
|
||||
|
||||
private LocalDateTime createDt;
|
||||
|
||||
private LocalDateTime updateDt;
|
||||
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
package com.aizuda.easy.retry.template.datasource.persistence.mapper;
|
||||
|
||||
import com.aizuda.easy.retry.template.datasource.persistence.dataobject.JobNotifyConfigQueryDO;
|
||||
import com.aizuda.easy.retry.template.datasource.persistence.dataobject.JobNotifyConfigResponseDO;
|
||||
import com.aizuda.easy.retry.template.datasource.persistence.po.JobNotifyConfig;
|
||||
import com.aizuda.easy.retry.template.datasource.persistence.po.NotifyConfig;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.PageDTO;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author zuoJunLin
|
||||
*/
|
||||
public interface JobNotifyConfigMapper extends BaseMapper<JobNotifyConfig> {
|
||||
List<JobNotifyConfigResponseDO> selectJobNotifyConfigList(IPage<JobNotifyConfig> iPage, @Param("queryDO") JobNotifyConfigQueryDO queryDO);
|
||||
}
|
@ -23,7 +23,9 @@ import java.util.List;
|
||||
@Mapper
|
||||
public interface JobTaskBatchMapper extends BaseMapper<JobTaskBatch> {
|
||||
|
||||
List<JobBatchResponseDO> selectJobBatchList(IPage<JobTaskBatch> iPage, @Param("queryDO") JobBatchQueryDO queryDO);
|
||||
List<JobBatchResponseDO> selectJobBatchPageList(IPage<JobTaskBatch> iPage, @Param("queryDO") JobBatchQueryDO queryDO);
|
||||
|
||||
List<JobBatchResponseDO> selectJobBatchListByIds( @Param("ids") List<Long> ids);
|
||||
|
||||
List<JobBatchSummaryResponseDO> summaryJobBatchList(@Param("from") LocalDateTime todayFrom, @Param("to") LocalDateTime to);
|
||||
}
|
||||
|
@ -0,0 +1,45 @@
|
||||
package com.aizuda.easy.retry.template.datasource.persistence.po;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
public class JobNotifyConfig implements Serializable {
|
||||
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
private String namespaceId;
|
||||
|
||||
private String groupName;
|
||||
|
||||
private Long jobId;
|
||||
|
||||
private Integer notifyStatus;
|
||||
|
||||
private Integer notifyType;
|
||||
|
||||
private String notifyAttribute;
|
||||
|
||||
private Integer notifyThreshold;
|
||||
|
||||
private Integer notifyScene;
|
||||
|
||||
private Integer rateLimiterStatus;
|
||||
|
||||
private Integer rateLimiterThreshold;
|
||||
|
||||
private String description;
|
||||
|
||||
private LocalDateTime createDt;
|
||||
|
||||
private LocalDateTime updateDt;
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.aizuda.easy.retry.template.datasource.persistence.mapper.JobNotifyConfigMapper">
|
||||
<resultMap id="BaseResultMap" type="com.aizuda.easy.retry.template.datasource.persistence.po.JobNotifyConfig">
|
||||
<id column="id" jdbcType="BIGINT" property="id" />
|
||||
<result column="namespace_id" jdbcType="VARCHAR" property="namespaceId" />
|
||||
<result column="group_name" jdbcType="VARCHAR" property="groupName" />
|
||||
<result column="job_id" jdbcType="BIGINT" property="jobId" />
|
||||
<result column="notify_status" jdbcType="TINYINT" property="notifyStatus" />
|
||||
<result column="notify_type" jdbcType="TINYINT" property="notifyType" />
|
||||
<result column="notify_attribute" jdbcType="VARCHAR" property="notifyAttribute" />
|
||||
<result column="notify_threshold" jdbcType="TINYINT" property="notifyThreshold" />
|
||||
<result column="notify_scene" jdbcType="TINYINT" property="notifyScene" />
|
||||
<result column="rate_limiter_status" jdbcType="TINYINT" property="rateLimiterStatus" />
|
||||
<result column="rate_limiter_threshold" jdbcType="TINYINT" property="rateLimiterThreshold" />
|
||||
<result column="description" jdbcType="VARCHAR" property="description" />
|
||||
<result column="create_dt" jdbcType="TIMESTAMP" property="createDt" />
|
||||
<result column="update_dt" jdbcType="TIMESTAMP" property="updateDt" />
|
||||
</resultMap>
|
||||
<sql id="Base_Column_List">
|
||||
id,namespace_id, group_name,job_id,notify_status,notify_type, notify_attribute, notify_threshold, notify_scene,rate_limiter_status,rate_limiter_threshold, description,
|
||||
create_dt, update_dt
|
||||
</sql>
|
||||
<select id="selectJobNotifyConfigList"
|
||||
resultType="com.aizuda.easy.retry.template.datasource.persistence.dataobject.JobNotifyConfigResponseDO">
|
||||
SELECT a.*, b.job_name
|
||||
FROM job_notify_config a join job b on a.job_id = b.id
|
||||
<where>
|
||||
a.namespace_id = #{queryDO.namespaceId}
|
||||
<if test="queryDO.jobId != null">
|
||||
and a.job_id = #{queryDO.jobId}
|
||||
</if>
|
||||
<if test="queryDO.groupName != null">
|
||||
and a.group_name = #{queryDO.groupName}
|
||||
</if>
|
||||
order by a.id desc
|
||||
</where>
|
||||
</select>
|
||||
</mapper>
|
@ -13,7 +13,7 @@
|
||||
<result column="update_dt" property="updateDt" />
|
||||
<result column="deleted" property="deleted" />
|
||||
</resultMap>
|
||||
<select id="selectJobBatchList"
|
||||
<select id="selectJobBatchPageList"
|
||||
parameterType="com.aizuda.easy.retry.template.datasource.persistence.dataobject.JobBatchQueryDO"
|
||||
resultType="com.aizuda.easy.retry.template.datasource.persistence.dataobject.JobBatchResponseDO">
|
||||
SELECT a.*, b.job_name, b.task_type, b.block_strategy, b.trigger_type
|
||||
@ -37,4 +37,33 @@
|
||||
</where>
|
||||
|
||||
</select>
|
||||
<select id="summaryJobBatchList"
|
||||
resultType="com.aizuda.easy.retry.template.datasource.persistence.dataobject.JobBatchSummaryResponseDO">
|
||||
SELECT namespace_id AS namespaceId,
|
||||
job_id AS jobId,
|
||||
group_name AS groupName,
|
||||
task_batch_status AS taskBatchStatus,
|
||||
operation_reason AS operationReason,
|
||||
COUNT(operation_reason) AS operationReasonTotal,
|
||||
SUM(CASE WHEN (task_batch_status = 3) THEN 1 ELSE 0 END) AS successNum,
|
||||
SUM(CASE WHEN (operation_reason IN (2, 3)) THEN 1 ELSE 0 END) AS cancelNum,
|
||||
SUM(CASE WHEN (operation_reason IN (1, 5, 8)) THEN 1 ELSE 0 END) AS stopNum,
|
||||
SUM(CASE WHEN (operation_reason IN (4, 6, 7)) THEN 1 ELSE 0 END) AS failNum
|
||||
FROM job_task_batch
|
||||
WHERE create_dt BETWEEN #{from} AND #{to}
|
||||
GROUP BY namespace_id, group_name, job_id, task_batch_status, operation_reason
|
||||
|
||||
</select>
|
||||
<select id="selectJobBatchListByIds"
|
||||
resultType="com.aizuda.easy.retry.template.datasource.persistence.dataobject.JobBatchResponseDO">
|
||||
SELECT a.*, b.job_name, b.task_type, b.block_strategy, b.trigger_type,b.executor_info,b.args_str
|
||||
FROM job_task_batch a join job b on a.job_id = b.id
|
||||
<where>
|
||||
a.id in
|
||||
<foreach collection="ids" item="id" separator="," open="(" close=")">
|
||||
#{id}
|
||||
</foreach>
|
||||
and a.deleted = 0
|
||||
</where>
|
||||
</select>
|
||||
</mapper>
|
||||
|
@ -0,0 +1,39 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.aizuda.easy.retry.template.datasource.persistence.mapper.JobNotifyConfigMapper">
|
||||
<resultMap id="BaseResultMap" type="com.aizuda.easy.retry.template.datasource.persistence.po.JobNotifyConfig">
|
||||
<id column="id" jdbcType="BIGINT" property="id" />
|
||||
<result column="namespace_id" jdbcType="VARCHAR" property="namespaceId" />
|
||||
<result column="group_name" jdbcType="VARCHAR" property="groupName" />
|
||||
<result column="job_id" jdbcType="BIGINT" property="jobId" />
|
||||
<result column="notify_status" jdbcType="TINYINT" property="notifyStatus" />
|
||||
<result column="notify_type" jdbcType="TINYINT" property="notifyType" />
|
||||
<result column="notify_attribute" jdbcType="VARCHAR" property="notifyAttribute" />
|
||||
<result column="notify_threshold" jdbcType="TINYINT" property="notifyThreshold" />
|
||||
<result column="notify_scene" jdbcType="TINYINT" property="notifyScene" />
|
||||
<result column="rate_limiter_status" jdbcType="TINYINT" property="rateLimiterStatus" />
|
||||
<result column="rate_limiter_threshold" jdbcType="TINYINT" property="rateLimiterThreshold" />
|
||||
<result column="description" jdbcType="VARCHAR" property="description" />
|
||||
<result column="create_dt" jdbcType="TIMESTAMP" property="createDt" />
|
||||
<result column="update_dt" jdbcType="TIMESTAMP" property="updateDt" />
|
||||
</resultMap>
|
||||
<sql id="Base_Column_List">
|
||||
id,namespace_id, group_name,job_id,notify_status,notify_type, notify_attribute, notify_threshold, notify_scene,rate_limiter_status,rate_limiter_threshold, description,
|
||||
create_dt, update_dt
|
||||
</sql>
|
||||
<select id="selectJobNotifyConfigList"
|
||||
resultType="com.aizuda.easy.retry.template.datasource.persistence.dataobject.JobNotifyConfigResponseDO">
|
||||
SELECT a.*, b.job_name
|
||||
FROM job_notify_config a join job b on a.job_id = b.id
|
||||
<where>
|
||||
a.namespace_id = #{queryDO.namespaceId}
|
||||
<if test="queryDO.jobId != null">
|
||||
and a.job_id = #{queryDO.jobId}
|
||||
</if>
|
||||
<if test="queryDO.groupName != null">
|
||||
and a.group_name = #{queryDO.groupName}
|
||||
</if>
|
||||
order by a.id desc
|
||||
</where>
|
||||
</select>
|
||||
</mapper>
|
@ -13,7 +13,7 @@
|
||||
<result column="update_dt" property="updateDt" />
|
||||
<result column="deleted" property="deleted" />
|
||||
</resultMap>
|
||||
<select id="selectJobBatchList"
|
||||
<select id="selectJobBatchPageList"
|
||||
parameterType="com.aizuda.easy.retry.template.datasource.persistence.dataobject.JobBatchQueryDO"
|
||||
resultType="com.aizuda.easy.retry.template.datasource.persistence.dataobject.JobBatchResponseDO">
|
||||
SELECT a.*, b.job_name, b.task_type, b.block_strategy, b.trigger_type
|
||||
@ -55,4 +55,17 @@
|
||||
GROUP BY namespace_id, group_name, job_id, task_batch_status, operation_reason
|
||||
|
||||
</select>
|
||||
|
||||
<select id="selectJobBatchListByIds"
|
||||
resultType="com.aizuda.easy.retry.template.datasource.persistence.dataobject.JobBatchResponseDO">
|
||||
SELECT a.*, b.job_name, b.task_type, b.block_strategy, b.trigger_type,b.executor_info,b.args_str
|
||||
FROM job_task_batch a join job b on a.job_id = b.id
|
||||
<where>
|
||||
a.id in
|
||||
<foreach collection="ids" item="id" separator="," open="(" close=")">
|
||||
#{id}
|
||||
</foreach>
|
||||
and a.deleted = 0
|
||||
</where>
|
||||
</select>
|
||||
</mapper>
|
||||
|
@ -0,0 +1,40 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.aizuda.easy.retry.template.datasource.persistence.mapper.JobNotifyConfigMapper">
|
||||
<resultMap id="BaseResultMap" type="com.aizuda.easy.retry.template.datasource.persistence.po.JobNotifyConfig">
|
||||
<id column="id" jdbcType="BIGINT" property="id" />
|
||||
<result column="namespace_id" jdbcType="VARCHAR" property="namespaceId" />
|
||||
<result column="group_name" jdbcType="VARCHAR" property="groupName" />
|
||||
<result column="job_id" jdbcType="BIGINT" property="jobId" />
|
||||
<result column="notify_status" jdbcType="TINYINT" property="notifyStatus" />
|
||||
<result column="notify_type" jdbcType="TINYINT" property="notifyType" />
|
||||
<result column="notify_attribute" jdbcType="VARCHAR" property="notifyAttribute" />
|
||||
<result column="notify_threshold" jdbcType="TINYINT" property="notifyThreshold" />
|
||||
<result column="notify_scene" jdbcType="TINYINT" property="notifyScene" />
|
||||
<result column="rate_limiter_status" jdbcType="TINYINT" property="rateLimiterStatus" />
|
||||
<result column="rate_limiter_threshold" jdbcType="TINYINT" property="rateLimiterThreshold" />
|
||||
<result column="description" jdbcType="VARCHAR" property="description" />
|
||||
<result column="create_dt" jdbcType="TIMESTAMP" property="createDt" />
|
||||
<result column="update_dt" jdbcType="TIMESTAMP" property="updateDt" />
|
||||
</resultMap>
|
||||
<sql id="Base_Column_List">
|
||||
id,namespace_id, group_name,job_id,notify_status,notify_type, notify_attribute, notify_threshold, notify_scene,rate_limiter_status,rate_limiter_threshold, description,
|
||||
create_dt, update_dt
|
||||
</sql>
|
||||
|
||||
<select id="selectJobNotifyConfigList"
|
||||
resultType="com.aizuda.easy.retry.template.datasource.persistence.dataobject.JobNotifyConfigResponseDO">
|
||||
SELECT a.*, b.job_name
|
||||
FROM job_notify_config a join job b on a.job_id = b.id
|
||||
<where>
|
||||
a.namespace_id = #{queryDO.namespaceId}
|
||||
<if test="queryDO.jobId != null">
|
||||
and a.job_id = #{queryDO.jobId}
|
||||
</if>
|
||||
<if test="queryDO.groupName != null">
|
||||
and a.group_name = #{queryDO.groupName}
|
||||
</if>
|
||||
order by a.id desc
|
||||
</where>
|
||||
</select>
|
||||
</mapper>
|
@ -13,7 +13,7 @@
|
||||
<result column="update_dt" property="updateDt" />
|
||||
<result column="deleted" property="deleted" />
|
||||
</resultMap>
|
||||
<select id="selectJobBatchList"
|
||||
<select id="selectJobBatchPageList"
|
||||
parameterType="com.aizuda.easy.retry.template.datasource.persistence.dataobject.JobBatchQueryDO"
|
||||
resultType="com.aizuda.easy.retry.template.datasource.persistence.dataobject.JobBatchResponseDO">
|
||||
SELECT a.*, b.job_name, b.task_type, b.block_strategy, b.trigger_type
|
||||
@ -35,6 +35,34 @@
|
||||
and a.deleted = 0
|
||||
order by a.id desc
|
||||
</where>
|
||||
</select>
|
||||
<select id="summaryJobBatchList"
|
||||
resultType="com.aizuda.easy.retry.template.datasource.persistence.dataobject.JobBatchSummaryResponseDO">
|
||||
SELECT namespace_id AS namespaceId,
|
||||
job_id AS jobId,
|
||||
group_name AS groupName,
|
||||
task_batch_status AS taskBatchStatus,
|
||||
operation_reason AS operationReason,
|
||||
COUNT(operation_reason) AS operationReasonTotal,
|
||||
SUM(CASE WHEN (task_batch_status = 3) THEN 1 ELSE 0 END) AS successNum,
|
||||
SUM(CASE WHEN (operation_reason IN (2, 3)) THEN 1 ELSE 0 END) AS cancelNum,
|
||||
SUM(CASE WHEN (operation_reason IN (1, 5, 8)) THEN 1 ELSE 0 END) AS stopNum,
|
||||
SUM(CASE WHEN (operation_reason IN (4, 6, 7)) THEN 1 ELSE 0 END) AS failNum
|
||||
FROM job_task_batch
|
||||
WHERE create_dt BETWEEN #{from} AND #{to}
|
||||
GROUP BY namespace_id, group_name, job_id, task_batch_status, operation_reason
|
||||
|
||||
</select>
|
||||
<select id="selectJobBatchListByIds"
|
||||
resultType="com.aizuda.easy.retry.template.datasource.persistence.dataobject.JobBatchResponseDO">
|
||||
SELECT a.*, b.job_name, b.task_type, b.block_strategy, b.trigger_type,b.executor_info,b.args_str
|
||||
FROM job_task_batch a join job b on a.job_id = b.id
|
||||
<where>
|
||||
a.id in
|
||||
<foreach collection="ids" item="id" separator="," open="(" close=")">
|
||||
#{id}
|
||||
</foreach>
|
||||
and a.deleted = 0
|
||||
</where>
|
||||
</select>
|
||||
</mapper>
|
||||
|
@ -18,10 +18,12 @@ import com.aizuda.easy.retry.server.job.task.dto.TaskExecuteDTO;
|
||||
import com.aizuda.easy.retry.server.job.task.support.JobExecutor;
|
||||
import com.aizuda.easy.retry.server.job.task.support.JobTaskConverter;
|
||||
import com.aizuda.easy.retry.server.job.task.support.cache.ResidentTaskCache;
|
||||
import com.aizuda.easy.retry.server.job.task.support.event.JobTaskFailAlarmEvent;
|
||||
import com.aizuda.easy.retry.server.job.task.support.executor.JobExecutorContext;
|
||||
import com.aizuda.easy.retry.server.job.task.support.executor.JobExecutorFactory;
|
||||
import com.aizuda.easy.retry.server.job.task.support.timer.JobTimerWheel;
|
||||
import com.aizuda.easy.retry.server.job.task.support.timer.ResidentJobTimerTask;
|
||||
import com.aizuda.easy.retry.server.retry.task.support.event.RetryTaskFailMoreThresholdAlarmEvent;
|
||||
import com.aizuda.easy.retry.template.datasource.persistence.mapper.JobMapper;
|
||||
import com.aizuda.easy.retry.template.datasource.persistence.mapper.JobTaskBatchMapper;
|
||||
import com.aizuda.easy.retry.template.datasource.persistence.po.Job;
|
||||
@ -30,6 +32,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.TransactionStatus;
|
||||
@ -58,6 +61,8 @@ public class JobExecutorActor extends AbstractActor {
|
||||
private JobTaskBatchMapper jobTaskBatchMapper;
|
||||
@Autowired
|
||||
private TransactionTemplate transactionTemplate;
|
||||
@Autowired
|
||||
private ApplicationContext context;
|
||||
|
||||
@Override
|
||||
public Receive createReceive() {
|
||||
@ -74,7 +79,7 @@ public class JobExecutorActor extends AbstractActor {
|
||||
} catch (Exception e) {
|
||||
LogUtils.error(log, "job executor exception. [{}]", taskExecute, e);
|
||||
handlerTaskBatch(taskExecute, JobTaskBatchStatusEnum.FAIL.getStatus(), JobOperationReasonEnum.TASK_EXECUTE_ERROR.getReason());
|
||||
// TODO 告警通知
|
||||
context.publishEvent(new JobTaskFailAlarmEvent(taskExecute.getTaskBatchId()));
|
||||
} finally {
|
||||
getContext().stop(getSelf());
|
||||
}
|
||||
|
@ -0,0 +1,22 @@
|
||||
package com.aizuda.easy.retry.server.job.task.support.event;
|
||||
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
|
||||
/**
|
||||
* job任务失败事件
|
||||
* @author: zuoJunLin
|
||||
* @date : 2023-12-02 21:40
|
||||
* @since 2.5.0
|
||||
*/
|
||||
public class JobTaskFailAlarmEvent extends ApplicationEvent {
|
||||
private Long jobTaskBatchId;
|
||||
|
||||
public JobTaskFailAlarmEvent(Long jobTaskBatchId) {
|
||||
super(jobTaskBatchId);
|
||||
this.jobTaskBatchId=jobTaskBatchId;
|
||||
}
|
||||
|
||||
public Long getJobTaskBatchId() {
|
||||
return jobTaskBatchId;
|
||||
}
|
||||
}
|
@ -0,0 +1,178 @@
|
||||
package com.aizuda.easy.retry.server.job.task.support.listener;
|
||||
|
||||
import com.aizuda.easy.retry.common.core.alarm.Alarm;
|
||||
import com.aizuda.easy.retry.common.core.alarm.AlarmContext;
|
||||
import com.aizuda.easy.retry.common.core.alarm.EasyRetryAlarmFactory;
|
||||
import com.aizuda.easy.retry.common.core.enums.JobNotifySceneEnum;
|
||||
import com.aizuda.easy.retry.common.core.enums.StatusEnum;
|
||||
import com.aizuda.easy.retry.common.core.log.LogUtils;
|
||||
import com.aizuda.easy.retry.common.core.util.EnvironmentUtils;
|
||||
import com.aizuda.easy.retry.common.core.util.HostUtils;
|
||||
import com.aizuda.easy.retry.server.common.Lifecycle;
|
||||
import com.aizuda.easy.retry.server.common.triple.ImmutableTriple;
|
||||
import com.aizuda.easy.retry.server.common.triple.Triple;
|
||||
import com.aizuda.easy.retry.server.common.util.DateUtils;
|
||||
import com.aizuda.easy.retry.server.job.task.support.event.JobTaskFailAlarmEvent;
|
||||
import com.aizuda.easy.retry.template.datasource.persistence.dataobject.JobBatchResponseDO;
|
||||
import com.aizuda.easy.retry.template.datasource.persistence.mapper.JobNotifyConfigMapper;
|
||||
import com.aizuda.easy.retry.template.datasource.persistence.mapper.JobTaskBatchMapper;
|
||||
import com.aizuda.easy.retry.template.datasource.persistence.po.*;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.google.common.collect.Lists;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
||||
/**
|
||||
* JOB任务执行失败告警
|
||||
*
|
||||
* @author: zuoJunLin
|
||||
* @date : 2023-12-02 21:40
|
||||
* @since 2.5.0
|
||||
*/
|
||||
@Component
|
||||
@Slf4j
|
||||
public class JobTaskFailAlarmListener implements ApplicationListener<JobTaskFailAlarmEvent>, Runnable, Lifecycle {
|
||||
|
||||
|
||||
@Autowired
|
||||
private JobNotifyConfigMapper jobNotifyConfigMapper;
|
||||
|
||||
@Autowired
|
||||
private JobTaskBatchMapper jobTaskBatchMapper;
|
||||
|
||||
@Autowired
|
||||
private EasyRetryAlarmFactory easyRetryAlarmFactory;
|
||||
|
||||
/**
|
||||
* job任务失败数据
|
||||
*/
|
||||
private LinkedBlockingQueue<Long> queue = new LinkedBlockingQueue<>(1000);
|
||||
|
||||
private static String jobTaskFailTextMessagesFormatter =
|
||||
"<font face=\"微软雅黑\" color=#ff0000 size=4>{}环境 Job任务执行失败</font> \n" +
|
||||
"> 组名称:{} \n" +
|
||||
"> 任务名称:{} \n" +
|
||||
"> 执行器名称:{} \n" +
|
||||
"> 方法参数:{} \n" +
|
||||
"> 时间:{} \n";
|
||||
|
||||
private Thread thread;
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
thread = new Thread(this);
|
||||
thread.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
if (Objects.nonNull(thread)) {
|
||||
thread.interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
LogUtils.info(log, "JobTaskFailAlarmListener time[{}] ip:[{}]", LocalDateTime.now(), HostUtils.getIp());
|
||||
while (!Thread.currentThread().isInterrupted()) {
|
||||
try {
|
||||
// 无数据时阻塞线程
|
||||
Long jobTaskBatchId = queue.take();
|
||||
// 拉取200条
|
||||
List<Long> jobTaskBatchIds = Lists.newArrayList(jobTaskBatchId);
|
||||
queue.drainTo(jobTaskBatchIds, 200);
|
||||
List<JobBatchResponseDO> jobTaskBatchList = jobTaskBatchMapper.selectJobBatchListByIds(jobTaskBatchIds);
|
||||
Set<String> namespaceIds = new HashSet<>();
|
||||
Set<String> groupNames = new HashSet<>();
|
||||
Set<Long> jobIds = new HashSet<>();
|
||||
Map<Triple<String, String, Long>, List<JobBatchResponseDO>> jobTaskBatchMap = getJobTaskBatchMap(
|
||||
jobTaskBatchList, namespaceIds, groupNames, jobIds);
|
||||
|
||||
Map<Triple<String, String, Long>, List<JobNotifyConfig>> jobNotifyConfigMap = getJobNotifyConfigMap(
|
||||
namespaceIds, groupNames, jobIds);
|
||||
if (jobNotifyConfigMap == null) {
|
||||
continue;
|
||||
}
|
||||
// 循环发送消息
|
||||
jobTaskBatchMap.forEach((key, list) -> {
|
||||
List<JobNotifyConfig> jobNotifyConfigsList = jobNotifyConfigMap.get(key);
|
||||
for (JobBatchResponseDO JobBatch : list) {
|
||||
for (final JobNotifyConfig jobNotifyConfig : jobNotifyConfigsList) {
|
||||
// 预警
|
||||
AlarmContext context = AlarmContext.build()
|
||||
.text(jobTaskFailTextMessagesFormatter,
|
||||
EnvironmentUtils.getActiveProfile(),
|
||||
JobBatch.getGroupName(),
|
||||
JobBatch.getJobName(),
|
||||
JobBatch.getExecutorInfo(),
|
||||
JobBatch.getArgsStr(),
|
||||
DateUtils.toNowFormat(DateUtils.NORM_DATETIME_PATTERN))
|
||||
.title("{}环境 JOB任务失败", EnvironmentUtils.getActiveProfile())
|
||||
.notifyAttribute(jobNotifyConfig.getNotifyAttribute());
|
||||
Alarm<AlarmContext> alarmType = easyRetryAlarmFactory.getAlarmType(jobNotifyConfig.getNotifyType());
|
||||
alarmType.asyncSendMessage(context);
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (InterruptedException e) {
|
||||
LogUtils.info(log, "job task fail more alarm stop");
|
||||
Thread.currentThread().interrupt();
|
||||
} catch (Exception e) {
|
||||
LogUtils.error(log, "JobTaskFailAlarmListener queue take Exception", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Map<Triple<String, String, Long>, List<JobNotifyConfig>> getJobNotifyConfigMap(Set<String> namespaceIds, Set<String> groupNames, Set<Long> jobIds) {
|
||||
// 批量获取所需的通知配置
|
||||
List<JobNotifyConfig> jobNotifyConfigs = jobNotifyConfigMapper.selectList(
|
||||
new LambdaQueryWrapper<JobNotifyConfig>()
|
||||
.eq(JobNotifyConfig::getNotifyStatus, StatusEnum.YES)
|
||||
.eq(JobNotifyConfig::getNotifyScene, JobNotifySceneEnum.JOB_TASK_ERROR.getNotifyScene())
|
||||
.in(JobNotifyConfig::getNamespaceId, namespaceIds)
|
||||
.in(JobNotifyConfig::getGroupName, groupNames)
|
||||
.in(JobNotifyConfig::getJobId, jobIds)
|
||||
);
|
||||
if (CollectionUtils.isEmpty(jobNotifyConfigs)) {
|
||||
return null;
|
||||
}
|
||||
return jobNotifyConfigs.stream()
|
||||
.collect(Collectors.groupingBy(i -> {
|
||||
|
||||
String namespaceId = i.getNamespaceId();
|
||||
String groupName = i.getGroupName();
|
||||
Long jobId = i.getJobId();
|
||||
|
||||
return ImmutableTriple.of(namespaceId, groupName, jobId);
|
||||
}));
|
||||
}
|
||||
|
||||
private Map<Triple<String, String, Long>, List<JobBatchResponseDO>> getJobTaskBatchMap(List<JobBatchResponseDO> jobTaskBatchList, Set<String> namespaceIds, Set<String> groupNames, Set<Long> jobIds) {
|
||||
return jobTaskBatchList.stream().collect(Collectors.groupingBy(i -> {
|
||||
String namespaceId = i.getNamespaceId();
|
||||
String groupName = i.getGroupName();
|
||||
Long jobId = i.getJobId();
|
||||
namespaceIds.add(namespaceId);
|
||||
groupNames.add(groupName);
|
||||
jobIds.add(jobId);
|
||||
return ImmutableTriple.of(namespaceId, groupName, jobId);
|
||||
}));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(JobTaskFailAlarmEvent event) {
|
||||
if (queue.offer(event.getJobTaskBatchId())) {
|
||||
LogUtils.warn(log, "JOB任务执行失败告警队列已满");
|
||||
}
|
||||
}
|
||||
}
|
@ -27,12 +27,18 @@ public class JobController {
|
||||
@Autowired
|
||||
private JobService jobService;
|
||||
|
||||
@GetMapping("/list")
|
||||
@GetMapping("/page/list")
|
||||
@LoginRequired
|
||||
public PageResult<List<JobResponseVO>> getJobPage(JobQueryVO jobQueryVO) {
|
||||
return jobService.getJobPage(jobQueryVO);
|
||||
}
|
||||
|
||||
@GetMapping("/list")
|
||||
@LoginRequired
|
||||
public List<JobResponseVO> getJobList(@RequestParam("groupName") String groupName) {
|
||||
return jobService.getJobList(groupName);
|
||||
}
|
||||
|
||||
@GetMapping("{id}")
|
||||
@LoginRequired
|
||||
public JobResponseVO getJobDetail(@PathVariable("id") Long id) {
|
||||
|
@ -0,0 +1,53 @@
|
||||
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.JobNotifyConfigQueryVO;
|
||||
import com.aizuda.easy.retry.server.web.model.request.JobNotifyConfigRequestVO;
|
||||
import com.aizuda.easy.retry.server.web.model.response.JobNotifyConfigResponseVO;
|
||||
import com.aizuda.easy.retry.server.web.service.JobNotifyConfigService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Job通知配置接口
|
||||
*
|
||||
* @author: zuoJunLin
|
||||
* @date : 2023-12-02 11:32
|
||||
* @since : 2.5.0
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/job/notify/config")
|
||||
public class JobNotifyConfigController {
|
||||
|
||||
@Autowired
|
||||
private JobNotifyConfigService jobNotifyConfigService;
|
||||
|
||||
@LoginRequired
|
||||
@GetMapping("/page/list")
|
||||
public PageResult<List<JobNotifyConfigResponseVO>> getNotifyConfigList(JobNotifyConfigQueryVO queryVO) {
|
||||
return jobNotifyConfigService.getJobNotifyConfigList(queryVO);
|
||||
}
|
||||
|
||||
@LoginRequired
|
||||
@GetMapping("{id}")
|
||||
public JobNotifyConfigResponseVO getJobNotifyConfigDetail(@PathVariable("id") Long id) {
|
||||
return jobNotifyConfigService.getJobNotifyConfigDetail(id);
|
||||
}
|
||||
|
||||
|
||||
@LoginRequired
|
||||
@PostMapping
|
||||
public Boolean saveNotify(@RequestBody @Validated JobNotifyConfigRequestVO requestVO) {
|
||||
return jobNotifyConfigService.saveJobNotify(requestVO);
|
||||
}
|
||||
|
||||
@LoginRequired
|
||||
@PutMapping
|
||||
public Boolean updateNotify(@RequestBody @Validated JobNotifyConfigRequestVO requestVO) {
|
||||
return jobNotifyConfigService.updateJobNotify(requestVO);
|
||||
}
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
package com.aizuda.easy.retry.server.web.model.request;
|
||||
|
||||
import com.aizuda.easy.retry.server.web.model.base.BaseQueryVO;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* @author zuoJunLin
|
||||
* @date 2023-12-02 11:16:14
|
||||
* @since 2.5.0
|
||||
*/
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
public class JobNotifyConfigQueryVO extends BaseQueryVO {
|
||||
private String groupName;
|
||||
private Long jobId;
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
package com.aizuda.easy.retry.server.web.model.request;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import javax.validation.constraints.Pattern;
|
||||
|
||||
/**
|
||||
* @author zuoJunLin
|
||||
* @date 2023-11-02 11:40:10
|
||||
* @since 2.5.0
|
||||
*/
|
||||
@Data
|
||||
public class JobNotifyConfigRequestVO {
|
||||
|
||||
private Long id;
|
||||
|
||||
@NotBlank(message = "组名称 不能为空")
|
||||
@Pattern(regexp = "^[A-Za-z0-9_]{1,64}$", message = "仅支持长度为1~64字符且类型为数字、字母和下划线")
|
||||
private String groupName;
|
||||
|
||||
@NotNull(message = "任务不能为空")
|
||||
private Long jobId;
|
||||
|
||||
@NotNull(message = "通知状态不能为空")
|
||||
private Integer notifyStatus;
|
||||
|
||||
@NotNull(message = "通知类型不能为空")
|
||||
private Integer notifyType;
|
||||
|
||||
@NotBlank(message = "通知属性不能为空")
|
||||
private String notifyAttribute;
|
||||
|
||||
private Integer notifyThreshold;
|
||||
|
||||
@NotNull(message = "通知场景不能为空")
|
||||
private Integer notifyScene;
|
||||
|
||||
@NotNull(message = "限流状态不能为空")
|
||||
private Integer rateLimiterStatus;
|
||||
|
||||
private Integer rateLimiterThreshold;
|
||||
/**
|
||||
* 描述
|
||||
*/
|
||||
private String description;
|
||||
|
||||
/**
|
||||
* 是否删除
|
||||
*/
|
||||
private Integer isDeleted;
|
||||
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
package com.aizuda.easy.retry.server.web.model.response;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* @author: zuoJunLin
|
||||
* @date : 2023-12-02 11:22
|
||||
* @since : 2.5.0
|
||||
*/
|
||||
@Data
|
||||
public class JobNotifyConfigResponseVO implements Serializable {
|
||||
|
||||
private Long id;
|
||||
|
||||
private String namespaceId;
|
||||
|
||||
private String groupName;
|
||||
|
||||
private Long jobId;
|
||||
|
||||
private String jobName;
|
||||
|
||||
private Integer notifyStatus;
|
||||
|
||||
private String notifyName;
|
||||
|
||||
private Integer notifyType;
|
||||
|
||||
private String notifyAttribute;
|
||||
|
||||
private Integer notifyThreshold;
|
||||
|
||||
private Integer notifyScene;
|
||||
|
||||
private Integer rateLimiterStatus;
|
||||
|
||||
private Integer rateLimiterThreshold;
|
||||
|
||||
private String description;
|
||||
|
||||
private LocalDateTime createDt;
|
||||
|
||||
private LocalDateTime updateDt;
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
package com.aizuda.easy.retry.server.web.service;
|
||||
|
||||
import com.aizuda.easy.retry.server.web.model.base.PageResult;
|
||||
import com.aizuda.easy.retry.server.web.model.request.JobNotifyConfigQueryVO;
|
||||
import com.aizuda.easy.retry.server.web.model.request.JobNotifyConfigRequestVO;
|
||||
import com.aizuda.easy.retry.server.web.model.request.NotifyConfigQueryVO;
|
||||
import com.aizuda.easy.retry.server.web.model.request.NotifyConfigRequestVO;
|
||||
import com.aizuda.easy.retry.server.web.model.response.JobNotifyConfigResponseVO;
|
||||
import com.aizuda.easy.retry.server.web.model.response.NotifyConfigResponseVO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author: zuoJunLin
|
||||
* @date : 2023-12-02 12:54
|
||||
* @since :2.5.0
|
||||
*/
|
||||
public interface JobNotifyConfigService {
|
||||
|
||||
PageResult<List<JobNotifyConfigResponseVO>> getJobNotifyConfigList(JobNotifyConfigQueryVO queryVO);
|
||||
|
||||
Boolean saveJobNotify(JobNotifyConfigRequestVO requestVO);
|
||||
|
||||
Boolean updateJobNotify(JobNotifyConfigRequestVO requestVO);
|
||||
|
||||
JobNotifyConfigResponseVO getJobNotifyConfigDetail(Long id);
|
||||
}
|
@ -35,4 +35,5 @@ public interface JobService {
|
||||
|
||||
boolean trigger(Long jobId);
|
||||
|
||||
List<JobResponseVO> getJobList(String groupName);
|
||||
}
|
||||
|
@ -0,0 +1,18 @@
|
||||
package com.aizuda.easy.retry.server.web.service.convert;
|
||||
|
||||
import com.aizuda.easy.retry.server.web.model.request.JobNotifyConfigRequestVO;
|
||||
import com.aizuda.easy.retry.template.datasource.persistence.po.JobNotifyConfig;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
/**
|
||||
* @author: zuoJunLin
|
||||
* @date : 2023-12-02 13:43
|
||||
*/
|
||||
@Mapper
|
||||
public interface JobNotifyConfigConverter {
|
||||
|
||||
JobNotifyConfigConverter INSTANCE = Mappers.getMapper(JobNotifyConfigConverter.class);
|
||||
|
||||
JobNotifyConfig toJobNotifyConfig(JobNotifyConfigRequestVO jobNotifyConfigVO);
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
package com.aizuda.easy.retry.server.web.service.convert;
|
||||
|
||||
import com.aizuda.easy.retry.server.web.model.response.JobNotifyConfigResponseVO;
|
||||
import com.aizuda.easy.retry.template.datasource.persistence.dataobject.JobNotifyConfigResponseDO;
|
||||
import com.aizuda.easy.retry.template.datasource.persistence.po.JobNotifyConfig;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author: www.byteblogs.com
|
||||
* @date : 2022-03-03 11:20
|
||||
*/
|
||||
@Mapper
|
||||
public interface JobNotifyConfigResponseVOConverter {
|
||||
|
||||
JobNotifyConfigResponseVOConverter INSTANCE = Mappers.getMapper(JobNotifyConfigResponseVOConverter.class);
|
||||
|
||||
JobNotifyConfigResponseVO convert(JobNotifyConfig jobNotifyConfig);
|
||||
|
||||
List<JobNotifyConfigResponseVO> batchConvert(List<JobNotifyConfigResponseDO> jobNotifyConfigs);
|
||||
}
|
@ -60,7 +60,7 @@ public class JobBatchServiceImpl implements JobBatchService {
|
||||
jobBatchQueryDO.setTaskBatchStatus(queryVO.getTaskBatchStatus());
|
||||
jobBatchQueryDO.setGroupName(queryVO.getGroupName());
|
||||
jobBatchQueryDO.setNamespaceId(UserSessionUtils.currentUserSession().getNamespaceId());
|
||||
List<JobBatchResponseDO> batchResponseDOList = jobTaskBatchMapper.selectJobBatchList(pageDTO, jobBatchQueryDO);
|
||||
List<JobBatchResponseDO> batchResponseDOList = jobTaskBatchMapper.selectJobBatchPageList(pageDTO, jobBatchQueryDO);
|
||||
|
||||
List<JobBatchResponseVO> batchResponseVOList = JobBatchResponseVOConverter.INSTANCE.toJobBatchResponseVOs(
|
||||
batchResponseDOList);
|
||||
|
@ -0,0 +1,83 @@
|
||||
package com.aizuda.easy.retry.server.web.service.impl;
|
||||
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.aizuda.easy.retry.common.core.util.JsonUtil;
|
||||
import com.aizuda.easy.retry.server.common.exception.EasyRetryServerException;
|
||||
import com.aizuda.easy.retry.server.web.model.base.PageResult;
|
||||
import com.aizuda.easy.retry.server.web.model.request.JobNotifyConfigQueryVO;
|
||||
import com.aizuda.easy.retry.server.web.model.request.JobNotifyConfigRequestVO;
|
||||
import com.aizuda.easy.retry.server.web.model.response.JobNotifyConfigResponseVO;
|
||||
import com.aizuda.easy.retry.server.web.service.JobNotifyConfigService;
|
||||
import com.aizuda.easy.retry.server.web.service.convert.JobNotifyConfigConverter;
|
||||
import com.aizuda.easy.retry.server.web.service.convert.JobNotifyConfigResponseVOConverter;
|
||||
import com.aizuda.easy.retry.server.web.util.UserSessionUtils;
|
||||
import com.aizuda.easy.retry.template.datasource.persistence.dataobject.JobBatchQueryDO;
|
||||
import com.aizuda.easy.retry.template.datasource.persistence.dataobject.JobBatchResponseDO;
|
||||
import com.aizuda.easy.retry.template.datasource.persistence.dataobject.JobNotifyConfigQueryDO;
|
||||
import com.aizuda.easy.retry.template.datasource.persistence.dataobject.JobNotifyConfigResponseDO;
|
||||
import com.aizuda.easy.retry.template.datasource.persistence.mapper.JobNotifyConfigMapper;
|
||||
import com.aizuda.easy.retry.template.datasource.persistence.po.JobNotifyConfig;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.PageDTO;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* @author: zuoJunLin
|
||||
* @date : 2023-12-02 12:54
|
||||
* @since :2.5.0
|
||||
*/
|
||||
@Service
|
||||
public class JobNotifyConfigServiceImpl implements JobNotifyConfigService {
|
||||
|
||||
@Autowired
|
||||
private JobNotifyConfigMapper jobNotifyConfigMapper;
|
||||
|
||||
@Override
|
||||
public PageResult<List<JobNotifyConfigResponseVO>> getJobNotifyConfigList(JobNotifyConfigQueryVO queryVO) {
|
||||
PageDTO<JobNotifyConfig> pageDTO = new PageDTO<>();
|
||||
JobNotifyConfigQueryDO jobNotifyConfigQueryDO = new JobNotifyConfigQueryDO();
|
||||
jobNotifyConfigQueryDO.setNamespaceId(UserSessionUtils.currentUserSession().getNamespaceId());
|
||||
if (StrUtil.isNotBlank(queryVO.getGroupName())) {
|
||||
jobNotifyConfigQueryDO.setGroupName(queryVO.getGroupName());
|
||||
}
|
||||
if (Objects.nonNull(queryVO.getJobId())) {
|
||||
jobNotifyConfigQueryDO.setJobId(queryVO.getJobId());
|
||||
}
|
||||
List<JobNotifyConfigResponseDO> batchResponseDOList = jobNotifyConfigMapper.selectJobNotifyConfigList(pageDTO, jobNotifyConfigQueryDO);
|
||||
return new PageResult<>(pageDTO, JobNotifyConfigResponseVOConverter.INSTANCE.batchConvert(batchResponseDOList));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean saveJobNotify(JobNotifyConfigRequestVO requestVO) {
|
||||
JobNotifyConfig jobNotifyConfig = JobNotifyConfigConverter.INSTANCE.toJobNotifyConfig(requestVO);
|
||||
jobNotifyConfig.setCreateDt(LocalDateTime.now());
|
||||
jobNotifyConfig.setNamespaceId(UserSessionUtils.currentUserSession().getNamespaceId());
|
||||
Assert.isTrue(1 == jobNotifyConfigMapper.insert(jobNotifyConfig),
|
||||
() -> new EasyRetryServerException("failed to insert jobNotifyConfig. sceneConfig:[{}]", JsonUtil.toJsonString(jobNotifyConfig)));
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean updateJobNotify(JobNotifyConfigRequestVO requestVO) {
|
||||
Assert.notNull(requestVO.getId(), () -> new EasyRetryServerException("参数异常"));
|
||||
JobNotifyConfig jobNotifyConfig = JobNotifyConfigConverter.INSTANCE.toJobNotifyConfig(requestVO);
|
||||
// 防止被覆盖
|
||||
jobNotifyConfig.setNamespaceId(null);
|
||||
Assert.isTrue(1 == jobNotifyConfigMapper.updateById(jobNotifyConfig),
|
||||
() -> new EasyRetryServerException("failed to update jobNotifyConfig. sceneConfig:[{}]", JsonUtil.toJsonString(jobNotifyConfig)));
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JobNotifyConfigResponseVO getJobNotifyConfigDetail(Long id) {
|
||||
JobNotifyConfig jobNotifyConfig = jobNotifyConfigMapper.selectOne(new LambdaQueryWrapper<JobNotifyConfig>()
|
||||
.eq(JobNotifyConfig::getId, id));
|
||||
return JobNotifyConfigResponseVOConverter.INSTANCE.convert(jobNotifyConfig);
|
||||
}
|
||||
}
|
@ -22,9 +22,11 @@ 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.convert.JobConverter;
|
||||
import com.aizuda.easy.retry.server.web.service.convert.JobResponseVOConverter;
|
||||
import com.aizuda.easy.retry.server.web.service.convert.SceneConfigResponseVOConverter;
|
||||
import com.aizuda.easy.retry.server.web.util.UserSessionUtils;
|
||||
import com.aizuda.easy.retry.template.datasource.persistence.mapper.JobMapper;
|
||||
import com.aizuda.easy.retry.template.datasource.persistence.po.Job;
|
||||
import com.aizuda.easy.retry.template.datasource.persistence.po.SceneConfig;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.PageDTO;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@ -216,4 +218,16 @@ public class JobServiceImpl implements JobService {
|
||||
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<JobResponseVO> getJobList(String groupName) {
|
||||
String namespaceId = UserSessionUtils.currentUserSession().getNamespaceId();
|
||||
List<Job> jobs = jobMapper.selectList(new LambdaQueryWrapper<Job>()
|
||||
.select(Job::getId, Job::getJobName)
|
||||
.eq(Job::getNamespaceId, namespaceId)
|
||||
.eq(Job::getGroupName, groupName)
|
||||
.orderByDesc(Job::getCreateDt));
|
||||
List<JobResponseVO> jobResponseList = JobResponseVOConverter.INSTANCE.toJobResponseVOs(jobs);
|
||||
return jobResponseList;
|
||||
}
|
||||
}
|
@ -1,6 +1,8 @@
|
||||
import request from '@/utils/request'
|
||||
import retryApi from "@/api/retryApi";
|
||||
const jobApi = {
|
||||
// 任务信息
|
||||
jobPageList: '/job/page/list',
|
||||
jobList: '/job/list',
|
||||
jobDetail: '/job/',
|
||||
saveJob: '/job/',
|
||||
@ -16,6 +18,13 @@ const jobApi = {
|
||||
jobBatchDetail: '/job/batch/',
|
||||
stop: '/job/batch/stop/',
|
||||
|
||||
//通知
|
||||
jobNotifyConfigPageList: '/job/notify/config/page/list',
|
||||
jobNotifyConfigDetail: '/job/notify/config/',
|
||||
saveJobNotify: '/job/notify/config/',
|
||||
updateJobNotify: '/job/notify/config/',
|
||||
|
||||
|
||||
// 任务
|
||||
jobTaskList: '/job/task/list',
|
||||
|
||||
@ -101,6 +110,14 @@ export function jobBatchDetail (id) {
|
||||
})
|
||||
}
|
||||
|
||||
export function getJobPageList (parameter) {
|
||||
return request({
|
||||
url: jobApi.jobPageList,
|
||||
method: 'get',
|
||||
params: parameter
|
||||
})
|
||||
}
|
||||
|
||||
export function getJobList (parameter) {
|
||||
return request({
|
||||
url: jobApi.jobList,
|
||||
@ -131,3 +148,33 @@ export function updateJob (data) {
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function jobNotifyConfigPageList (parameter) {
|
||||
return request({
|
||||
url: jobApi.jobNotifyConfigPageList,
|
||||
method: 'get',
|
||||
params: parameter
|
||||
})
|
||||
}
|
||||
export function getJobNotifyConfigDetail (id) {
|
||||
return request({
|
||||
url: jobApi.jobNotifyConfigDetail + id,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
export function saveJobNotify (data) {
|
||||
return request({
|
||||
url: jobApi.saveJobNotify,
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function updateJobNotify (data) {
|
||||
return request({
|
||||
url: jobApi.updateJobNotify,
|
||||
method: 'put',
|
||||
data
|
||||
})
|
||||
}
|
@ -130,9 +130,9 @@ export const asyncRouterMap = [
|
||||
},
|
||||
{
|
||||
path: '/retry/scene/config',
|
||||
name: 'SceneFrom',
|
||||
name: 'SceneForm',
|
||||
hidden: true,
|
||||
component: () => import('@/views/task/form/SceneFrom'),
|
||||
component: () => import('@/views/task/form/SceneForm.vue'),
|
||||
meta: { title: '场景配置', icon: 'profile', keepAlive: true, permission: ['retryTask'] }
|
||||
},
|
||||
{
|
||||
@ -143,9 +143,9 @@ export const asyncRouterMap = [
|
||||
},
|
||||
{
|
||||
path: '/retry/notify/config',
|
||||
name: 'NotifyFrom',
|
||||
name: 'NotifyForm',
|
||||
hidden: true,
|
||||
component: () => import('@/views/task/form/NotifyFrom'),
|
||||
component: () => import('@/views/task/form/NotifyForm.vue'),
|
||||
meta: { title: '通知配置', icon: 'profile', keepAlive: true, permission: ['retryTask'] }
|
||||
}
|
||||
]
|
||||
@ -172,9 +172,9 @@ export const asyncRouterMap = [
|
||||
},
|
||||
{
|
||||
path: '/job/config',
|
||||
name: 'JobFrom',
|
||||
name: 'JobForm',
|
||||
hidden: true,
|
||||
component: () => import('@/views/job/from/JobFrom'),
|
||||
component: () => import('@/views/job/form/JobForm.vue'),
|
||||
meta: { title: '任务配置', icon: 'profile', permission: ['job'] }
|
||||
},
|
||||
{
|
||||
@ -196,6 +196,19 @@ export const asyncRouterMap = [
|
||||
hidden: true,
|
||||
component: () => import('@/views/job/JobTaskList'),
|
||||
meta: { title: '任务项', icon: 'profile', permission: ['jobBatch'] }
|
||||
},
|
||||
{
|
||||
path: '/job/notify/list',
|
||||
name: 'JobNotifyList',
|
||||
component: () => import('@/views/job/JobNotifyList'),
|
||||
meta: { title: '通知列表', icon: 'profile', keepAlive: true, permission: ['jobNotify'] }
|
||||
},
|
||||
{
|
||||
path: '/job/notify/config',
|
||||
name: 'JobNotifyForm',
|
||||
hidden: true,
|
||||
component: () => import('@/views/job/form/JobNotifyForm.vue'),
|
||||
meta: { title: '通知配置', icon: 'profile', keepAlive: true, permission: ['jobNotify'] }
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -151,7 +151,45 @@ const enums = {
|
||||
'name': '停止',
|
||||
'color': '#ac2df5'
|
||||
}
|
||||
}
|
||||
},
|
||||
notifyScene: {
|
||||
'1': {
|
||||
'name': '任务执行失败',
|
||||
'color': '#d06892'
|
||||
}
|
||||
},
|
||||
notifyType: {
|
||||
'1': {
|
||||
'name': '钉钉通知',
|
||||
'color': '#64a6ea'
|
||||
},
|
||||
'2': {
|
||||
'name': '邮箱通知',
|
||||
'color': '#1b7ee5'
|
||||
},
|
||||
'4': {
|
||||
'name': '飞书',
|
||||
'color': '#087da1'
|
||||
}
|
||||
}, notifyStatus: {
|
||||
'0': {
|
||||
'name': '停用',
|
||||
'color': '#9c1f1f'
|
||||
},
|
||||
'1': {
|
||||
'name': '启用',
|
||||
'color': '#f5a22d'
|
||||
}
|
||||
}, rateLimiterStatus: {
|
||||
'0': {
|
||||
'name': '未启用',
|
||||
'color': '#9c1f1f'
|
||||
},
|
||||
'1': {
|
||||
'name': '启用',
|
||||
'color': '#f5a22d'
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
module.exports = enums
|
||||
|
@ -111,6 +111,10 @@ const jobAdmin = [
|
||||
roleId: 1,
|
||||
permissionId: 'jobBatch',
|
||||
permissionName: '任务批次'
|
||||
},{
|
||||
roleId: 1,
|
||||
permissionId: 'jobNotify',
|
||||
permissionName: '任务通知'
|
||||
}
|
||||
]
|
||||
|
||||
@ -171,6 +175,11 @@ const jobUser = [
|
||||
roleId: 1,
|
||||
permissionId: 'jobBatch',
|
||||
permissionName: '任务批次'
|
||||
},
|
||||
{
|
||||
roleId: 1,
|
||||
permissionId: 'jobNotify',
|
||||
permissionName: '任务通知'
|
||||
}
|
||||
]
|
||||
|
||||
|
@ -55,11 +55,11 @@ const enums = {
|
||||
'color': '#a127f3'
|
||||
},
|
||||
'5': {
|
||||
'name': '任务重试数量超过阈值',
|
||||
'name': '任务重试失败数量超过阈值',
|
||||
'color': '#f5a22d'
|
||||
},
|
||||
'6': {
|
||||
'name': '任务失败进入死信队列',
|
||||
'name': '任务重试失败进入死信队列',
|
||||
'color': '#f5a22d'
|
||||
}
|
||||
},
|
||||
|
@ -178,7 +178,7 @@
|
||||
import ATextarea from 'ant-design-vue/es/input/TextArea'
|
||||
import AInput from 'ant-design-vue/es/input/Input'
|
||||
import { STable, Drawer } from '@/components'
|
||||
import { delJob, getJobList, triggerJob, updateJobStatus } from '@/api/jobApi'
|
||||
import { delJob, getJobPageList, triggerJob, updateJobStatus } from '@/api/jobApi'
|
||||
import { getAllGroupNameList } from '@/api/manage'
|
||||
import enums from '@/utils/jobEnum'
|
||||
import JobInfo from '@/views/job/JobInfo'
|
||||
@ -278,7 +278,7 @@ export default {
|
||||
],
|
||||
// 加载数据方法 必须为 Promise 对象
|
||||
loadData: (parameter) => {
|
||||
return getJobList(Object.assign(parameter, this.queryParam)).then((res) => {
|
||||
return getJobPageList(Object.assign(parameter, this.queryParam)).then((res) => {
|
||||
return res
|
||||
})
|
||||
},
|
||||
|
247
frontend/src/views/job/JobNotifyList.vue
Normal file
247
frontend/src/views/job/JobNotifyList.vue
Normal file
@ -0,0 +1,247 @@
|
||||
<template>
|
||||
<div>
|
||||
<a-card :bordered="false">
|
||||
<div class="table-page-search-wrapper">
|
||||
<a-form layout="inline">
|
||||
<a-row :gutter="48">
|
||||
<a-col :md="8" :sm="24">
|
||||
<a-form-item label="组名称">
|
||||
<a-select
|
||||
v-model="queryParam.groupName"
|
||||
placeholder="请输入组名称"
|
||||
@change="(value) => handleChange(value)"
|
||||
>
|
||||
<a-select-option v-for="item in groupNameList" :value="item" :key="item">{{ item }}</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :md="8" :sm="24">
|
||||
<a-form-item label="任务名称">
|
||||
<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"
|
||||
>
|
||||
<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>
|
||||
<template>
|
||||
|
||||
</template>
|
||||
<a-col :md="(!advanced && 8) || 24" :sm="24">
|
||||
<span
|
||||
class="table-page-search-submitButtons"
|
||||
:style="(advanced && { float: 'right', overflow: 'hidden' }) || {}"
|
||||
>
|
||||
<a-button type="primary" @click="$refs.table.refresh(true)">查询</a-button>
|
||||
<a-button style="margin-left: 8px" @click="() => (queryParam = {})">重置</a-button>
|
||||
<a @click="toggleAdvanced" style="margin-left: 8px">
|
||||
{{ advanced ? '收起' : '展开' }}
|
||||
<a-icon :type="advanced ? 'up' : 'down'" />
|
||||
</a>
|
||||
</span>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-form>
|
||||
</div>
|
||||
<div class="table-operator">
|
||||
<a-button type="primary" icon="plus" @click="handleNew()">新增</a-button>
|
||||
</div>
|
||||
<s-table
|
||||
ref="table"
|
||||
size="default"
|
||||
:rowKey="(record) => record.id"
|
||||
:columns="notifyColumns"
|
||||
:data="loadData"
|
||||
:alert="options.alert"
|
||||
:rowSelection="options.rowSelection"
|
||||
>
|
||||
|
||||
<span slot="notifyType" slot-scope="text">
|
||||
<a-tag :color="notifyTypeList[text].color">
|
||||
{{ notifyTypeList[text].name }}
|
||||
</a-tag>
|
||||
</span>
|
||||
<span slot="notifyStatus" slot-scope="text">
|
||||
<a-tag :color="notifyStatusList[text].color">
|
||||
{{ notifyStatusList[text].name }}
|
||||
</a-tag>
|
||||
</span>
|
||||
<span slot="notifyScene" slot-scope="text">
|
||||
<a-tag :color="notifySceneList[text].color">
|
||||
{{ notifySceneList[text].name }}
|
||||
</a-tag>
|
||||
</span>
|
||||
<span slot="notifyAttribute" slot-scope="text, record">
|
||||
{{ parseJson(JSON.parse(text),record) }}
|
||||
</span>
|
||||
<span slot="notifyThreshold" slot-scope="text">
|
||||
{{ text === 0 ? '无' : text }}
|
||||
</span>
|
||||
<span slot="action" slot-scope="record">
|
||||
<template>
|
||||
<a @click="handleEdit(record)">编辑</a>
|
||||
</template>
|
||||
</span>
|
||||
</s-table>
|
||||
</a-card>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {getAllGroupNameList, getSceneList} from '@/api/manage'
|
||||
import { STable } from '@/components'
|
||||
import {getJobList, jobNameList, jobNotifyConfigPageList} from "@/api/jobApi";
|
||||
const enums = require('@/utils/retryEnum')
|
||||
|
||||
export default {
|
||||
name: 'JobNotifyList',
|
||||
components: { STable },
|
||||
data () {
|
||||
return {
|
||||
notifyColumns: [
|
||||
{
|
||||
title: '组名',
|
||||
dataIndex: 'groupName',
|
||||
key: 'groupName',
|
||||
width: '10%',
|
||||
scopedSlots: { customRender: 'groupName' }
|
||||
},
|
||||
{
|
||||
title: '任务',
|
||||
dataIndex: 'jobName',
|
||||
key: 'jobName',
|
||||
width: '10%',
|
||||
scopedSlots: { customRender: 'jobName' }
|
||||
},
|
||||
{
|
||||
title: '通知状态',
|
||||
dataIndex: 'notifyStatus',
|
||||
width: '10%',
|
||||
scopedSlots: { customRender: 'notifyStatus' }
|
||||
},
|
||||
{
|
||||
title: '通知类型',
|
||||
dataIndex: 'notifyType',
|
||||
key: 'notifyType',
|
||||
width: '10%',
|
||||
scopedSlots: { customRender: 'notifyType' }
|
||||
},
|
||||
{
|
||||
title: '通知场景',
|
||||
dataIndex: 'notifyScene',
|
||||
key: 'notifyScene',
|
||||
width: '10%',
|
||||
scopedSlots: { customRender: 'notifyScene' }
|
||||
},
|
||||
{
|
||||
title: '通知阈值',
|
||||
dataIndex: 'notifyThreshold',
|
||||
key: 'notifyThreshold',
|
||||
width: '10%',
|
||||
scopedSlots: { customRender: 'notifyThreshold' }
|
||||
},
|
||||
{
|
||||
title: '描述',
|
||||
dataIndex: 'description',
|
||||
key: 'description',
|
||||
width: '20%',
|
||||
scopedSlots: { customRender: 'description' }
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
key: 'action',
|
||||
fixed: 'right',
|
||||
width: '180px',
|
||||
scopedSlots: { customRender: 'action' }
|
||||
}
|
||||
],
|
||||
data: [],
|
||||
loading: false,
|
||||
form: this.$form.createForm(this),
|
||||
// 高级搜索 展开/关闭
|
||||
advanced: false,
|
||||
queryParam: {},
|
||||
loadData: (parameter) => {
|
||||
return jobNotifyConfigPageList(Object.assign(parameter, this.queryParam)).then((res) => {
|
||||
return res
|
||||
})
|
||||
},
|
||||
selectedRowKeys: [],
|
||||
selectedRows: [],
|
||||
|
||||
// custom table alert & rowSelection
|
||||
options: {
|
||||
alert: {
|
||||
show: true,
|
||||
clear: () => {
|
||||
this.selectedRowKeys = []
|
||||
}
|
||||
},
|
||||
rowSelection: {
|
||||
selectedRowKeys: this.selectedRowKeys,
|
||||
onChange: this.onSelectChange
|
||||
}
|
||||
},
|
||||
optionAlertShow: false,
|
||||
memberLoading: false,
|
||||
notifySceneList: enums.notifyScene,
|
||||
notifyTypeList: enums.notifyType,
|
||||
notifyStatusList: enums.notifyStatus,
|
||||
visible: false,
|
||||
key: '',
|
||||
notifyTypeValue: '1',
|
||||
groupNameList: [],
|
||||
jobNameList: [],
|
||||
}
|
||||
},
|
||||
created () {
|
||||
getAllGroupNameList().then((res) => {
|
||||
this.groupNameList = res.data
|
||||
})
|
||||
|
||||
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)
|
||||
}
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
handleSearch (value) {
|
||||
jobNameList({ keywords: value }).then(res => {
|
||||
this.jobNameList = res.data
|
||||
})
|
||||
},
|
||||
handleChange (value) {
|
||||
getJobList({ groupName: value }).then((res) => {
|
||||
this.jobNameList = res.data
|
||||
})
|
||||
},
|
||||
toggleAdvanced () {
|
||||
this.advanced = !this.advanced
|
||||
},
|
||||
handleNew () {
|
||||
this.$router.push({ path: '/job/notify/config' })
|
||||
},
|
||||
handleEdit (record) {
|
||||
this.$router.push({ path: '/job/notify/config', query: { id: record.id } })
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style scoped>
|
||||
</style>
|
@ -313,7 +313,7 @@
|
||||
import { getAllGroupNameList } from '@/api/manage'
|
||||
import { getJobDetail, saveJob, updateJob } from '@/api/jobApi'
|
||||
import pick from 'lodash.pick'
|
||||
import CronModal from '@/views/job/from/CronModal'
|
||||
import CronModal from '@/views/job/form/CronModal'
|
||||
|
||||
import AFormModel from 'ant-design-vue/es/form-model/Form'
|
||||
import AFormModelItem from 'ant-design-vue/es/form-model/FormItem'
|
488
frontend/src/views/job/form/JobNotifyForm.vue
Normal file
488
frontend/src/views/job/form/JobNotifyForm.vue
Normal file
@ -0,0 +1,488 @@
|
||||
<template>
|
||||
<div>
|
||||
<page-header-wrapper content="场景配置" @back="() => $router.go(-1)" style="margin: -24px -1px 0">
|
||||
<div></div>
|
||||
</page-header-wrapper>
|
||||
<a-card :body-style="{padding: '24px 32px'}" :bordered="false" :loading="loading">
|
||||
<a-form @submit="handleSubmit" :form="form" class="form-row" layout="vertical" style="width: 40%;margin: auto;">
|
||||
<a-row class="form-row" :gutter="16">
|
||||
<a-col :lg="18" :md="12" :sm="24">
|
||||
<a-form-item>
|
||||
<a-input
|
||||
hidden
|
||||
v-decorator="['id']" />
|
||||
</a-form-item>
|
||||
<a-form-item label="通知场景">
|
||||
<a-select
|
||||
placeholder="通知场景"
|
||||
style="width: 100%;"
|
||||
@change="changeNotifyScene"
|
||||
v-decorator="[
|
||||
'notifyScene',
|
||||
{
|
||||
initialValue: '1',
|
||||
rules: [{ required: true, message: '请选通知场景'}]
|
||||
}
|
||||
]"
|
||||
>
|
||||
<a-select-option :value="index" v-for="(item, index) in notifySceneList" :key="index">{{ item.name }}</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="6" :md="12" :sm="24">
|
||||
<a-form-item>
|
||||
<a-input
|
||||
hidden />
|
||||
</a-form-item>
|
||||
<a-form-item label="通知阈值">
|
||||
<a-input
|
||||
v-if="notifyThresholdDisabled.includes(this.notifySceneValue)"
|
||||
disabled />
|
||||
<a-input-number
|
||||
v-else
|
||||
id="inputNumber"
|
||||
:min="1"
|
||||
style="width: -webkit-fill-available"
|
||||
v-decorator="[
|
||||
'notifyThreshold',
|
||||
{
|
||||
initialValue: '16',
|
||||
rules: [{ required: !notifyThresholdDisabled.includes(this.notifySceneValue), message: '请输入通知阈值'}]
|
||||
}
|
||||
]" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
<a-row class="form-row" :gutter="16">
|
||||
<a-col :lg="18" :md="12" :sm="24">
|
||||
<a-form-item label="组">
|
||||
<a-select placeholder="请选择组" v-decorator="['groupName', { rules: [{ required: true, message: '请选择组' }] }]" @change="value => changeGroup(value)">
|
||||
<a-select-option v-for="item in groupNameList" :value="item" :key="item">{{ item }}</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="6" :md="12" :sm="24">
|
||||
<a-form-item label="任务">
|
||||
<a-select :disabled="sceneNameDisabled.includes(this.notifySceneValue)" placeholder="请选择任务" v-decorator="['jobId', { rules: [{ required: true, message: '请选择任务' }] }]" >
|
||||
<a-select-option v-for="item in jobList" :value="item.id" :key="item.id">{{item.jobName}}</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
<a-row class="form-row" :gutter="16">
|
||||
<a-col :lg="8" :md="12" :sm="12">
|
||||
<a-form-item label="通知类型">
|
||||
<a-select
|
||||
@change="handleChange"
|
||||
placeholder="通知类型"
|
||||
style="width: 100%;"
|
||||
v-decorator="[
|
||||
'notifyType',
|
||||
{
|
||||
initialValue: '1',
|
||||
rules: [{ required: true, message: '请选择通知类型'}]
|
||||
}
|
||||
]"
|
||||
>
|
||||
<a-select-option :value="index" v-for="(item, index) in notifyTypeList" :key="index">{{ item.name }}</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="16" :md="12" :sm="12">
|
||||
<a-form-item label="配置属性">
|
||||
<a-input
|
||||
placeholder="请输入配置属性"
|
||||
@click="handleBlur"
|
||||
v-decorator="[
|
||||
'notifyAttribute',
|
||||
{rules: [{ required: true, message: '请输入配置属性', whitespace: true}]}
|
||||
]" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
<a-row class="form-row" :gutter="16">
|
||||
<a-col :lg="8" :md="12" :sm="24">
|
||||
<a-form-item label="限流状态">
|
||||
<a-select :disabled="rateLimiterStatusDisabled.includes(this.notifySceneValue)" placeholder="请选择限流状态" @change="changeRateLimiterStatus" v-decorator="['rateLimiterStatus',{initialValue: '0', rules: [{ required: true, message: '请选择限流状态'}]}]" >
|
||||
<a-select-option :value="index" v-for="(item, index) in rateLimiterStatusList" :key="index">{{ item.name }}</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="8" :md="12" :sm="24">
|
||||
<a-form-item label="每秒限流阈值">
|
||||
<a-input-number :disabled="rateLimiterThresholdDisabled.includes(this.rateLimiterStatusValue)" id="inputNumber" :min="1" style="width: -webkit-fill-available" v-decorator= "['rateLimiterThreshold',{initialValue: '100',rules: [{ required: !rateLimiterThresholdDisabled.includes(this.rateLimiterStatusValue), message: '请输入通知阈值' }]}]" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="8" :md="12" :sm="24">
|
||||
<a-form-item label="状态">
|
||||
<a-select
|
||||
placeholder="请选择状态"
|
||||
v-decorator="[
|
||||
'notifyStatus',
|
||||
{
|
||||
initialValue: '1',
|
||||
rules: [{ required: true, message: '请选择状态'}]
|
||||
}
|
||||
]" >
|
||||
<a-select-option :value="index" v-for="(item, index) in notifyStatusList" :key="index">{{ item.name }}</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
<a-row class="form-row" :gutter="16">
|
||||
<a-col :lg="24" :md="24" :sm="24">
|
||||
<a-form-item label="描述">
|
||||
<a-input
|
||||
placeholder="请输入描述"
|
||||
type="textarea"
|
||||
v-decorator="[
|
||||
'description',
|
||||
{rules: [{required: false, max: 256, message: '最多支持256个字符!'}]}
|
||||
]" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
<a-form-item
|
||||
:wrapperCol="{ span: 24 }"
|
||||
style="text-align: center"
|
||||
>
|
||||
<a-button htmlType="submit" type="primary">提交</a-button>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-card>
|
||||
<a-modal :visible="visible" title="添加配置" @ok="handleOk" @cancel="handlerCancel" width="1000px">
|
||||
<a-form :form="notifyAttributeForm" @submit="handleSubmit" :body-style="{padding: '0px 0px'}" v-bind="formItemLayout" >
|
||||
<a-form-item
|
||||
v-if="this.notifyTypeValue === '1'"
|
||||
label="钉钉URL">
|
||||
<a-input
|
||||
placeholder="请输入钉钉URL"
|
||||
v-decorator="[
|
||||
'webhookUrl',
|
||||
{rules: [{ required: true, message: '请输入钉钉URL', whitespace: true}]}
|
||||
]" />
|
||||
</a-form-item>
|
||||
<a-form-item v-if="this.notifyTypeValue === '1'">
|
||||
<span slot="label">被@人手机号 <a :href="officialWebsite + '/pages/32e4a0/#被@人手机号是何物' +''" target="_blank"> <a-icon type="question-circle-o" /></a></span>
|
||||
<a-input
|
||||
placeholder="请输入被@负责人手机号"
|
||||
type="textarea"
|
||||
v-if="this.notifyTypeValue === '1'"
|
||||
v-decorator="[
|
||||
'ats',
|
||||
{rules: [{ required: true, message: '请输入被@人手机号', whitespace: true}]}
|
||||
]" />
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
v-if="this.notifyTypeValue === '4'"
|
||||
label="飞书URL">
|
||||
<a-input
|
||||
placeholder="请输入飞书URL"
|
||||
v-decorator="[
|
||||
'webhookUrl',
|
||||
{rules: [{ required: true, message: '请输入飞书URL', whitespace: true}]}
|
||||
]" />
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
v-if="this.notifyTypeValue === '4'">
|
||||
<span slot="label">被@负责人用户id <a :href="officialWebsite + '/pages/32e4a0/#被@人open_id是何物' +''" target="_blank"> <a-icon type="question-circle-o" /></a></span>
|
||||
<a-input
|
||||
placeholder="请输入被@人open_id"
|
||||
type="textarea"
|
||||
v-if="this.notifyTypeValue === '4'"
|
||||
v-decorator="[
|
||||
'ats',
|
||||
{rules: [{ required: true, message: '请输入被@人open_id', whitespace: true}]}
|
||||
]" />
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
v-if="this.notifyTypeValue === '2'"
|
||||
label="用户名">
|
||||
<a-input
|
||||
placeholder="请输入用户名"
|
||||
v-if="this.notifyTypeValue === '2'"
|
||||
v-decorator="[
|
||||
'user',
|
||||
{rules: [{ required: true, message: '请输入用户名', whitespace: true}]}
|
||||
]" />
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
v-if="this.notifyTypeValue === '2'"
|
||||
label="密码">
|
||||
<a-input
|
||||
placeholder="请输入密码"
|
||||
v-if="this.notifyTypeValue === '2'"
|
||||
v-decorator="[
|
||||
'pass',
|
||||
{rules: [{ required: true, message: '请输入密码', whitespace: true}]}
|
||||
]"/>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
v-if="this.notifyTypeValue === '2'"
|
||||
label="SMTP地址">
|
||||
<a-input
|
||||
placeholder="请输入邮件服务器的SMTP地址"
|
||||
v-if="this.notifyTypeValue === '2'"
|
||||
v-decorator="[
|
||||
'host',
|
||||
{rules: [{ required: true, message: '请输入邮件服务器的SMTP地址', whitespace: true}]}
|
||||
]"/>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
v-if="this.notifyTypeValue === '2'"
|
||||
label="SMTP端口">
|
||||
<a-input
|
||||
v-if="this.notifyTypeValue === '2'"
|
||||
placeholder="请输入邮件服务器的SMTP端口"
|
||||
v-decorator="[
|
||||
'port',
|
||||
{rules: [{ required: true, message: '请输入邮件服务器的SMTP端口', whitespace: true}]}
|
||||
]"/>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
v-if="this.notifyTypeValue === '2'"
|
||||
label="发件人">
|
||||
<a-input
|
||||
v-if="this.notifyTypeValue === '2'"
|
||||
placeholder="请输入发件人"
|
||||
v-decorator="[
|
||||
'from',
|
||||
{rules: [{ required: true, message: '请输入发件人', whitespace: true}]}
|
||||
]"/>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
v-if="this.notifyTypeValue === '2'"
|
||||
label="收件人">
|
||||
<a-input
|
||||
v-if="this.notifyTypeValue === '2'"
|
||||
placeholder="请输入收件人"
|
||||
v-decorator="[
|
||||
'tos',
|
||||
{rules: [{ required: true, message: '请输入收件人', whitespace: true}]}
|
||||
]"/>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
:wrapper-col="{
|
||||
xs: { span: 24, offset: 0 },
|
||||
sm: { span: 16, offset: 8 },
|
||||
lg: { span: 7 }
|
||||
}">
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getAllGroupNameList, getSceneList } from '@/api/manage'
|
||||
import { getNotifyConfigDetail, saveNotify, updateNotify } from '@/api/retryApi'
|
||||
import pick from 'lodash.pick'
|
||||
import CronModal from '@/views/job/form/CronModal'
|
||||
import { officialWebsite } from '@/utils/util'
|
||||
import {getJobList, getJobNotifyConfigDetail, saveJobNotify, updateJobNotify} from "@/api/jobApi";
|
||||
const enums = require('@/utils/jobEnum')
|
||||
export default {
|
||||
name: 'NotifyFrom',
|
||||
props: {},
|
||||
comments: {
|
||||
CronModal
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
form: this.$form.createForm(this),
|
||||
formItemLayout: {
|
||||
labelCol: { lg: { span: 7 }, sm: { span: 7 } },
|
||||
wrapperCol: { lg: { span: 10 }, sm: { span: 17 } }
|
||||
},
|
||||
officialWebsite: officialWebsite(),
|
||||
formItemLayoutWithOutLabel: {
|
||||
wrapperCol: {
|
||||
xs: { span: 24, offset: 0 },
|
||||
sm: { span: 20, offset: 4 }
|
||||
}
|
||||
},
|
||||
formType: 'create',
|
||||
groupNameList: [],
|
||||
jobList: [],
|
||||
notifySceneList: enums.notifyScene,
|
||||
notifyTypeList: enums.notifyType,
|
||||
notifyStatusList: enums.notifyStatus,
|
||||
rateLimiterStatusList: enums.rateLimiterStatus,
|
||||
loading: false,
|
||||
visible: false,
|
||||
count: 0,
|
||||
notifyTypeValue: '1',
|
||||
notifyAttribute: '',
|
||||
notifyThresholdDisabled: ['1'],
|
||||
sceneNameDisabled: ['3', '4'],
|
||||
rateLimiterStatusDisabled: ['1'],
|
||||
rateLimiterThresholdDisabled: ['0'],
|
||||
notifySceneValue: '1',
|
||||
rateLimiterStatusValue: '0',
|
||||
defaultRateLimiterStatusValue: '0',
|
||||
defaultRateLimiterThreshold: '100'
|
||||
}
|
||||
},
|
||||
beforeCreate () {
|
||||
this.notifyAttributeForm = this.$form.createForm(this, { name: 'notify_attribute_form_item' })
|
||||
},
|
||||
mounted () {
|
||||
getAllGroupNameList().then((res) => {
|
||||
this.groupNameList = res.data
|
||||
})
|
||||
|
||||
this.$nextTick(() => {
|
||||
const id = this.$route.query.id
|
||||
console.log(id)
|
||||
if (id) {
|
||||
this.loading = true
|
||||
getJobNotifyConfigDetail(id).then(res => {
|
||||
this.loadEditInfo(res.data)
|
||||
this.loading = false
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
resetFiled () {
|
||||
this.form.resetFields()
|
||||
},
|
||||
buildNotifyAttribute (formData) {
|
||||
formData.ats = formData.ats && formData.ats.replace(/\s+/g, '').split(',')
|
||||
return JSON.stringify(formData)
|
||||
},
|
||||
handleChange (notifyType) {
|
||||
this.notifyTypeValue = notifyType
|
||||
},
|
||||
changeGroup (value) {
|
||||
getJobList({ groupName: value }).then((res) => {
|
||||
this.jobList = res.data
|
||||
})
|
||||
},
|
||||
changeRateLimiterStatus (rateLimiterStatus) {
|
||||
this.rateLimiterStatusValue = rateLimiterStatus
|
||||
},
|
||||
changeNotifyScene (notifyScene) {
|
||||
this.notifySceneValue = notifyScene
|
||||
const { form } = this
|
||||
if (this.sceneNameDisabled.includes(notifyScene)) {
|
||||
form.setFieldsValue({
|
||||
sceneName: ''
|
||||
})
|
||||
}
|
||||
if (this.rateLimiterStatusDisabled.includes(notifyScene)) {
|
||||
form.setFieldsValue({
|
||||
rateLimiterStatus: this.defaultRateLimiterStatusValue,
|
||||
rateLimiterThreshold: this.defaultRateLimiterThreshold
|
||||
})
|
||||
this.changeRateLimiterStatus(this.defaultRateLimiterStatusValue)
|
||||
}
|
||||
},
|
||||
handleBlur () {
|
||||
new Promise((resolve) => {
|
||||
setTimeout(resolve, 100)
|
||||
}).then(() => {
|
||||
if (this.formType === 'edit') {
|
||||
const formData = pick(JSON.parse(this.notifyAttribute), ['webhookUrl', 'ats', 'user', 'pass', 'host', 'port', 'from', 'tos'])
|
||||
this.notifyAttributeForm.getFieldDecorator(`webhookUrl`, { initialValue: formData.webhookUrl, preserve: true })
|
||||
this.notifyAttributeForm.getFieldDecorator(`ats`, { initialValue: formData.ats.join(','), preserve: true })
|
||||
this.notifyAttributeForm.getFieldDecorator(`user`, { initialValue: formData.user, preserve: true })
|
||||
this.notifyAttributeForm.getFieldDecorator(`pass`, { initialValue: formData.pass, preserve: true })
|
||||
this.notifyAttributeForm.getFieldDecorator(`host`, { initialValue: formData.host, preserve: true })
|
||||
this.notifyAttributeForm.getFieldDecorator(`port`, { initialValue: formData.port, preserve: true })
|
||||
this.notifyAttributeForm.getFieldDecorator(`from`, { initialValue: formData.from, preserve: true })
|
||||
this.notifyAttributeForm.getFieldDecorator(`tos`, { initialValue: formData.tos, preserve: true })
|
||||
}
|
||||
this.visible = !this.visible
|
||||
})
|
||||
},
|
||||
handlerCancel () {
|
||||
this.visible = false
|
||||
},
|
||||
handleOk () {
|
||||
this.notifyAttributeForm.validateFields((err, values) => {
|
||||
if (!err) {
|
||||
const { form } = this
|
||||
const formData = pick(values, ['webhookUrl', 'ats', 'user', 'pass', 'host', 'port', 'from', 'tos'])
|
||||
this.notifyAttribute = this.buildNotifyAttribute(formData)
|
||||
form.setFieldsValue({
|
||||
notifyAttribute: this.parseJson(formData)
|
||||
})
|
||||
this.visible = false
|
||||
}
|
||||
})
|
||||
},
|
||||
handleSubmit (e) {
|
||||
e.preventDefault()
|
||||
this.form.validateFields((err, values) => {
|
||||
if (!err) {
|
||||
values['notifyAttribute'] = this.notifyAttribute
|
||||
if (this.formType === 'create') {
|
||||
saveJobNotify(values).then(res => {
|
||||
this.$message.success('任务新增完成')
|
||||
this.form.resetFields()
|
||||
this.$router.go(-1)
|
||||
})
|
||||
} else {
|
||||
updateJobNotify(values).then(res => {
|
||||
this.$message.success('任务更新完成')
|
||||
this.form.resetFields()
|
||||
this.$router.go(-1)
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
loadEditInfo (data) {
|
||||
this.formType = 'edit'
|
||||
const { form } = this
|
||||
// ajax
|
||||
new Promise((resolve) => {
|
||||
setTimeout(async () => {
|
||||
await this.changeGroup(data.groupName)
|
||||
resolve()
|
||||
}, 100)
|
||||
}).then(() => {
|
||||
const formData = pick(data, [
|
||||
'id', 'notifyAttribute', 'groupName', 'jobId', 'notifyStatus', 'notifyScene', 'notifyThreshold', 'notifyType', 'description', 'rateLimiterStatus', 'rateLimiterThreshold'])
|
||||
formData.notifyStatus = formData.notifyStatus.toString()
|
||||
formData.notifyScene = formData.notifyScene.toString()
|
||||
formData.notifyType = formData.notifyType.toString()
|
||||
formData.notifyThreshold = formData.notifyThreshold.toString()
|
||||
formData.rateLimiterStatus = formData.rateLimiterStatus.toString()
|
||||
formData.rateLimiterThreshold = formData.rateLimiterThreshold.toString()
|
||||
this.notifyTypeValue = formData.notifyType
|
||||
this.notifyAttribute = formData.notifyAttribute
|
||||
this.notifySceneValue = formData.notifyScene
|
||||
this.rateLimiterStatusValue = formData.rateLimiterStatus
|
||||
formData.notifyAttribute = this.parseJson(JSON.parse(formData.notifyAttribute))
|
||||
form.setFieldsValue(formData)
|
||||
})
|
||||
},
|
||||
parseJson (json) {
|
||||
if (!json) {
|
||||
return null
|
||||
}
|
||||
|
||||
let s =
|
||||
'用户名:' + json['user'] + ';' +
|
||||
'密码:' + json['pass'] + ';' +
|
||||
'SMTP地址:' + json['host'] + ';' +
|
||||
'SMTP端口:' + json['port'] + ';' +
|
||||
'发件人:' + json['from'] + ';' +
|
||||
'收件人:' + json['tos'] + ';'
|
||||
|
||||
if (this.notifyTypeValue === '1') {
|
||||
s =
|
||||
'钉钉Url:' + json['webhookUrl'] + ';' +
|
||||
'被@人手机号:' + json['ats'] + ';'
|
||||
} else if (this.notifyTypeValue === '4') {
|
||||
s =
|
||||
'飞书Url:' + json['webhookUrl'] + ';' +
|
||||
'被@人用户id:' + json['ats'] + ';'
|
||||
}
|
||||
return s
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
@ -165,7 +165,7 @@
|
||||
<a-form-item v-if="this.notifyTypeValue === '1'">
|
||||
<span slot="label">被@人手机号 <a :href="officialWebsite + '/pages/32e4a0/#被@人手机号是何物' +''" target="_blank"> <a-icon type="question-circle-o" /></a></span>
|
||||
<a-input
|
||||
placeholder="请输入被@负责人手机号"
|
||||
placeholder="请输入被@人手机号"
|
||||
type="textarea"
|
||||
v-if="this.notifyTypeValue === '1'"
|
||||
v-decorator="[
|
||||
@ -185,7 +185,7 @@
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
v-if="this.notifyTypeValue === '4'">
|
||||
<span slot="label">被@负责人用户id <a :href="officialWebsite + '/pages/32e4a0/#被@人open_id是何物' +''" target="_blank"> <a-icon type="question-circle-o" /></a></span>
|
||||
<span slot="label">被@人用户id <a :href="officialWebsite + '/pages/32e4a0/#被@人open_id是何物' +''" target="_blank"> <a-icon type="question-circle-o" /></a></span>
|
||||
<a-input
|
||||
placeholder="请输入被@人open_id"
|
||||
type="textarea"
|
||||
@ -277,7 +277,7 @@
|
||||
import { getAllGroupNameList, getSceneList } from '@/api/manage'
|
||||
import { getNotifyConfigDetail, saveNotify, updateNotify } from '@/api/retryApi'
|
||||
import pick from 'lodash.pick'
|
||||
import CronModal from '@/views/job/from/CronModal'
|
||||
import CronModal from '@/views/job/form/CronModal'
|
||||
import { officialWebsite } from '@/utils/util'
|
||||
const enums = require('@/utils/retryEnum')
|
||||
export default {
|
||||
@ -474,11 +474,11 @@ export default {
|
||||
if (this.notifyTypeValue === '1') {
|
||||
s =
|
||||
'钉钉Url:' + json['webhookUrl'] + ';' +
|
||||
'被@负责人手机号:' + json['ats'] + ';'
|
||||
'被@人手机号:' + json['ats'] + ';'
|
||||
} else if (this.notifyTypeValue === '4') {
|
||||
s =
|
||||
'飞书Url:' + json['webhookUrl'] + ';' +
|
||||
'被@负责人用户id:' + json['ats'] + ';'
|
||||
'被@人用户id:' + json['ats'] + ';'
|
||||
}
|
||||
return s
|
||||
}
|
@ -202,7 +202,7 @@
|
||||
import { getAllGroupNameList } from '@/api/manage'
|
||||
import { saveScene, updateScene, getSceneDetail } from '@/api/retryApi'
|
||||
import pick from 'lodash.pick'
|
||||
import CronModal from '@/views/job/from/CronModal'
|
||||
import CronModal from '@/views/job/form/CronModal'
|
||||
|
||||
const enums = require('@/utils/retryEnum')
|
||||
export default {
|
Loading…
Reference in New Issue
Block a user