feat: 2.6.0
1. 优化取消日志信息
This commit is contained in:
parent
e383abacad
commit
7b696254b8
@ -2,6 +2,7 @@ package com.aizuda.easy.retry.server.job.task.dto;
|
|||||||
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author xiaowoniu
|
* @author xiaowoniu
|
||||||
* @date 2023-12-24 23:00:24
|
* @date 2023-12-24 23:00:24
|
||||||
|
@ -178,6 +178,7 @@ public class JobExecutorActor extends AbstractActor {
|
|||||||
if (Objects.isNull(job)
|
if (Objects.isNull(job)
|
||||||
|| JobTaskExecutorSceneEnum.MANUAL_JOB.getType().equals(taskExecuteDTO.getTaskExecutorScene())
|
|| JobTaskExecutorSceneEnum.MANUAL_JOB.getType().equals(taskExecuteDTO.getTaskExecutorScene())
|
||||||
|| JobTaskExecutorSceneEnum.AUTO_WORKFLOW.getType().equals(taskExecuteDTO.getTaskExecutorScene())
|
|| JobTaskExecutorSceneEnum.AUTO_WORKFLOW.getType().equals(taskExecuteDTO.getTaskExecutorScene())
|
||||||
|
|| JobTaskExecutorSceneEnum.MANUAL_WORKFLOW.getType().equals(taskExecuteDTO.getTaskExecutorScene())
|
||||||
// 是否是常驻任务
|
// 是否是常驻任务
|
||||||
|| Objects.equals(StatusEnum.NO.getStatus(), job.getResident())
|
|| Objects.equals(StatusEnum.NO.getStatus(), job.getResident())
|
||||||
) {
|
) {
|
||||||
|
@ -84,7 +84,7 @@ public class ScanWorkflowTaskActor extends AbstractActor {
|
|||||||
for (final WorkflowTaskPrepareDTO waitExecTask : waitExecWorkflows) {
|
for (final WorkflowTaskPrepareDTO waitExecTask : waitExecWorkflows) {
|
||||||
// 执行预处理阶段
|
// 执行预处理阶段
|
||||||
ActorRef actorRef = ActorGenerator.workflowTaskPrepareActor();
|
ActorRef actorRef = ActorGenerator.workflowTaskPrepareActor();
|
||||||
waitExecTask.setTaskExecutorScene(JobTaskExecutorSceneEnum.AUTO_JOB.getType());
|
waitExecTask.setTaskExecutorScene(JobTaskExecutorSceneEnum.AUTO_WORKFLOW.getType());
|
||||||
actorRef.tell(waitExecTask, actorRef);
|
actorRef.tell(waitExecTask, actorRef);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,8 @@ import com.aizuda.easy.retry.server.common.dto.CallbackConfig;
|
|||||||
import com.aizuda.easy.retry.server.common.enums.ContentTypeEnum;
|
import com.aizuda.easy.retry.server.common.enums.ContentTypeEnum;
|
||||||
import com.aizuda.easy.retry.server.job.task.dto.LogMetaDTO;
|
import com.aizuda.easy.retry.server.job.task.dto.LogMetaDTO;
|
||||||
import com.aizuda.easy.retry.server.job.task.support.WorkflowTaskConverter;
|
import com.aizuda.easy.retry.server.job.task.support.WorkflowTaskConverter;
|
||||||
|
import com.aizuda.easy.retry.server.job.task.support.generator.batch.JobTaskBatchGenerator;
|
||||||
|
import com.aizuda.easy.retry.server.job.task.support.generator.batch.JobTaskBatchGeneratorContext;
|
||||||
import com.aizuda.easy.retry.server.model.dto.CallbackParamsDTO;
|
import com.aizuda.easy.retry.server.model.dto.CallbackParamsDTO;
|
||||||
import com.aizuda.easy.retry.template.datasource.persistence.mapper.JobTaskMapper;
|
import com.aizuda.easy.retry.template.datasource.persistence.mapper.JobTaskMapper;
|
||||||
import com.aizuda.easy.retry.template.datasource.persistence.po.JobTask;
|
import com.aizuda.easy.retry.template.datasource.persistence.po.JobTask;
|
||||||
@ -98,8 +100,8 @@ public class CallbackWorkflowExecutor extends AbstractWorkflowExecutor {
|
|||||||
requestHeaders.set(RequestInterceptor.TIMEOUT_TIME, CALLBACK_TIMEOUT);
|
requestHeaders.set(RequestInterceptor.TIMEOUT_TIME, CALLBACK_TIMEOUT);
|
||||||
|
|
||||||
List<JobTask> jobTasks = jobTaskMapper.selectList(new LambdaQueryWrapper<JobTask>()
|
List<JobTask> jobTasks = jobTaskMapper.selectList(new LambdaQueryWrapper<JobTask>()
|
||||||
.select(JobTask::getResultMessage, JobTask::getClientInfo)
|
.select(JobTask::getResultMessage, JobTask::getClientInfo)
|
||||||
.eq(JobTask::getTaskBatchId, context.getTaskBatchId()));
|
.eq(JobTask::getTaskBatchId, context.getTaskBatchId()));
|
||||||
List<CallbackParamsDTO> callbackParamsList = WorkflowTaskConverter.INSTANCE.toCallbackParamsDTO(jobTasks);
|
List<CallbackParamsDTO> callbackParamsList = WorkflowTaskConverter.INSTANCE.toCallbackParamsDTO(jobTasks);
|
||||||
|
|
||||||
context.setTaskResult(JsonUtil.toJsonString(callbackParamsList));
|
context.setTaskResult(JsonUtil.toJsonString(callbackParamsList));
|
||||||
@ -109,14 +111,14 @@ public class CallbackWorkflowExecutor extends AbstractWorkflowExecutor {
|
|||||||
uriVariables.put(SECRET, decisionConfig.getSecret());
|
uriVariables.put(SECRET, decisionConfig.getSecret());
|
||||||
|
|
||||||
ResponseEntity<String> response = buildRetryer(decisionConfig).call(
|
ResponseEntity<String> response = buildRetryer(decisionConfig).call(
|
||||||
() -> restTemplate.exchange(decisionConfig.getWebhook(), HttpMethod.POST,
|
() -> restTemplate.exchange(decisionConfig.getWebhook(), HttpMethod.POST,
|
||||||
new HttpEntity<>(callbackParamsList, requestHeaders), String.class, uriVariables));
|
new HttpEntity<>(callbackParamsList, requestHeaders), String.class, uriVariables));
|
||||||
|
|
||||||
result = response.getBody();
|
result = response.getBody();
|
||||||
EasyRetryLog.LOCAL.info("回调结果. webHook:[{}],结果: [{}]", decisionConfig.getWebhook(), result);
|
EasyRetryLog.LOCAL.info("回调结果. webHook:[{}],结果: [{}]", decisionConfig.getWebhook(), result);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
EasyRetryLog.LOCAL.error("回调异常. webHook:[{}],参数: [{}]", decisionConfig.getWebhook(),
|
EasyRetryLog.LOCAL.error("回调异常. webHook:[{}],参数: [{}]", decisionConfig.getWebhook(),
|
||||||
context.getTaskResult(), e);
|
context.getTaskResult(), e);
|
||||||
|
|
||||||
context.setTaskBatchStatus(JobTaskBatchStatusEnum.FAIL.getStatus());
|
context.setTaskBatchStatus(JobTaskBatchStatusEnum.FAIL.getStatus());
|
||||||
context.setOperationReason(JobOperationReasonEnum.WORKFLOW_CALLBACK_NODE_EXECUTION_ERROR.getReason());
|
context.setOperationReason(JobOperationReasonEnum.WORKFLOW_CALLBACK_NODE_EXECUTION_ERROR.getReason());
|
||||||
@ -171,15 +173,15 @@ public class CallbackWorkflowExecutor extends AbstractWorkflowExecutor {
|
|||||||
logMetaDTO.setJobId(SystemConstants.CALLBACK_JOB_ID);
|
logMetaDTO.setJobId(SystemConstants.CALLBACK_JOB_ID);
|
||||||
logMetaDTO.setTaskId(jobTask.getId());
|
logMetaDTO.setTaskId(jobTask.getId());
|
||||||
if (jobTaskBatch.getTaskBatchStatus() == JobTaskStatusEnum.SUCCESS.getStatus()) {
|
if (jobTaskBatch.getTaskBatchStatus() == JobTaskStatusEnum.SUCCESS.getStatus()) {
|
||||||
EasyRetryLog.REMOTE.info("回调成功. \n workflowNodeId:{} \n回调参数:{} \n回调结果:[{}] <|>{}<|>",
|
EasyRetryLog.REMOTE.info("节点[{}]回调成功.\n回调参数:{} \n回调结果:[{}] <|>{}<|>",
|
||||||
context.getWorkflowNodeId(), context.getTaskResult(), context.getEvaluationResult(), logMetaDTO);
|
context.getWorkflowNodeId(), context.getTaskResult(), context.getEvaluationResult(), logMetaDTO);
|
||||||
|
} else if (jobTaskBatch.getTaskBatchStatus() == JobTaskStatusEnum.CANCEL.getStatus()) {
|
||||||
|
EasyRetryLog.REMOTE.warn("节点[{}]取消回调. 取消原因: 任务状态已关闭 <|>{}<|>",
|
||||||
|
context.getWorkflowNodeId(), logMetaDTO);
|
||||||
} else {
|
} else {
|
||||||
EasyRetryLog.REMOTE.error(" 回调失败.\n workflowNodeId:{} \n失败原因:{} <|>{}<|>",
|
EasyRetryLog.REMOTE.error("节点[{}]回调失败.\n失败原因:{} <|>{}<|>",
|
||||||
context.getWorkflowNodeId(),
|
context.getWorkflowNodeId(),
|
||||||
context.getLogMessage(), logMetaDTO);
|
context.getLogMessage(), logMetaDTO);
|
||||||
|
|
||||||
// 尝试完成任务
|
|
||||||
workflowBatchHandler.complete(context.getWorkflowTaskBatchId());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -147,10 +147,10 @@ public class DecisionWorkflowExecutor extends AbstractWorkflowExecutor {
|
|||||||
logMetaDTO.setTaskId(jobTask.getId());
|
logMetaDTO.setTaskId(jobTask.getId());
|
||||||
if (jobTaskBatch.getTaskBatchStatus() == JobTaskStatusEnum.SUCCESS.getStatus()
|
if (jobTaskBatch.getTaskBatchStatus() == JobTaskStatusEnum.SUCCESS.getStatus()
|
||||||
|| JobOperationReasonEnum.WORKFLOW_NODE_NO_REQUIRED.getReason() == context.getOperationReason()) {
|
|| JobOperationReasonEnum.WORKFLOW_NODE_NO_REQUIRED.getReason() == context.getOperationReason()) {
|
||||||
EasyRetryLog.REMOTE.info("workflowNodeId:[{}]决策完成. 上下文:[{}] 决策结果:[{}] <|>{}<|>",
|
EasyRetryLog.REMOTE.info("节点Id:[{}] 决策完成. 上下文:[{}] 决策结果:[{}] <|>{}<|>",
|
||||||
context.getWorkflowNodeId(), context.getTaskResult(), context.getEvaluationResult(), logMetaDTO);
|
context.getWorkflowNodeId(), context.getTaskResult(), context.getEvaluationResult(), logMetaDTO);
|
||||||
} else {
|
} else {
|
||||||
EasyRetryLog.REMOTE.error("workflowNodeId:[{}] 决策失败. 上下文:[{}] 失败原因:[{}] <|>{}<|>",
|
EasyRetryLog.REMOTE.error("节点Id:[{}] 决策失败. 上下文:[{}] 失败原因:[{}] <|>{}<|>",
|
||||||
context.getWorkflowNodeId(), context.getTaskResult(), context.getLogMessage(), logMetaDTO);
|
context.getWorkflowNodeId(), context.getTaskResult(), context.getLogMessage(), logMetaDTO);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,19 +1,24 @@
|
|||||||
package com.aizuda.easy.retry.server.job.task.support.executor.workflow;
|
package com.aizuda.easy.retry.server.job.task.support.executor.workflow;
|
||||||
|
|
||||||
import akka.actor.ActorRef;
|
import akka.actor.ActorRef;
|
||||||
|
import com.aizuda.easy.retry.common.core.constant.SystemConstants;
|
||||||
import com.aizuda.easy.retry.common.core.enums.JobOperationReasonEnum;
|
import com.aizuda.easy.retry.common.core.enums.JobOperationReasonEnum;
|
||||||
import com.aizuda.easy.retry.common.core.enums.JobTaskBatchStatusEnum;
|
import com.aizuda.easy.retry.common.core.enums.JobTaskBatchStatusEnum;
|
||||||
import com.aizuda.easy.retry.common.core.enums.JobTaskStatusEnum;
|
import com.aizuda.easy.retry.common.core.enums.JobTaskStatusEnum;
|
||||||
import com.aizuda.easy.retry.common.core.enums.StatusEnum;
|
import com.aizuda.easy.retry.common.core.enums.StatusEnum;
|
||||||
import com.aizuda.easy.retry.common.core.enums.WorkflowNodeTypeEnum;
|
import com.aizuda.easy.retry.common.core.enums.WorkflowNodeTypeEnum;
|
||||||
|
import com.aizuda.easy.retry.common.log.EasyRetryLog;
|
||||||
import com.aizuda.easy.retry.server.common.akka.ActorGenerator;
|
import com.aizuda.easy.retry.server.common.akka.ActorGenerator;
|
||||||
import com.aizuda.easy.retry.server.common.enums.JobTaskExecutorSceneEnum;
|
import com.aizuda.easy.retry.server.common.enums.JobTaskExecutorSceneEnum;
|
||||||
import com.aizuda.easy.retry.server.common.util.DateUtils;
|
import com.aizuda.easy.retry.server.common.util.DateUtils;
|
||||||
import com.aizuda.easy.retry.server.job.task.dto.JobTaskPrepareDTO;
|
import com.aizuda.easy.retry.server.job.task.dto.JobTaskPrepareDTO;
|
||||||
|
import com.aizuda.easy.retry.server.job.task.dto.LogMetaDTO;
|
||||||
import com.aizuda.easy.retry.server.job.task.support.JobTaskConverter;
|
import com.aizuda.easy.retry.server.job.task.support.JobTaskConverter;
|
||||||
import com.aizuda.easy.retry.server.job.task.support.WorkflowTaskConverter;
|
import com.aizuda.easy.retry.server.job.task.support.WorkflowTaskConverter;
|
||||||
import com.aizuda.easy.retry.server.job.task.support.generator.batch.JobTaskBatchGenerator;
|
import com.aizuda.easy.retry.server.job.task.support.generator.batch.JobTaskBatchGenerator;
|
||||||
import com.aizuda.easy.retry.server.job.task.support.generator.batch.JobTaskBatchGeneratorContext;
|
import com.aizuda.easy.retry.server.job.task.support.generator.batch.JobTaskBatchGeneratorContext;
|
||||||
|
import com.aizuda.easy.retry.template.datasource.persistence.po.JobTask;
|
||||||
|
import com.aizuda.easy.retry.template.datasource.persistence.po.JobTaskBatch;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
@ -28,8 +33,6 @@ import java.util.Objects;
|
|||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class JobTaskWorkflowExecutor extends AbstractWorkflowExecutor {
|
public class JobTaskWorkflowExecutor extends AbstractWorkflowExecutor {
|
||||||
|
|
||||||
private final JobTaskBatchGenerator jobTaskBatchGenerator;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WorkflowNodeTypeEnum getWorkflowNodeType() {
|
public WorkflowNodeTypeEnum getWorkflowNodeType() {
|
||||||
return WorkflowNodeTypeEnum.JOB_TASK;
|
return WorkflowNodeTypeEnum.JOB_TASK;
|
||||||
@ -42,7 +45,22 @@ public class JobTaskWorkflowExecutor extends AbstractWorkflowExecutor {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void afterExecute(WorkflowExecutorContext context) {
|
protected void afterExecute(WorkflowExecutorContext context) {
|
||||||
|
if (Objects.equals(context.getWorkflowNodeStatus(), StatusEnum.YES.getStatus())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
JobTaskBatch jobTaskBatch = generateJobTaskBatch(context);
|
||||||
|
JobTask jobTask = generateJobTask(context, jobTaskBatch);
|
||||||
|
|
||||||
|
LogMetaDTO logMetaDTO = new LogMetaDTO();
|
||||||
|
logMetaDTO.setNamespaceId(context.getNamespaceId());
|
||||||
|
logMetaDTO.setGroupName(context.getGroupName());
|
||||||
|
logMetaDTO.setTaskBatchId(jobTaskBatch.getId());
|
||||||
|
logMetaDTO.setJobId(context.getJobId());
|
||||||
|
logMetaDTO.setTaskId(jobTask.getId());
|
||||||
|
|
||||||
|
EasyRetryLog.REMOTE.warn("节点[{}]已取消任务执行. 取消原因: 任务已关闭. <|>{}<|>",
|
||||||
|
context.getWorkflowNodeId(), logMetaDTO);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -54,13 +72,9 @@ public class JobTaskWorkflowExecutor extends AbstractWorkflowExecutor {
|
|||||||
protected void doExecute(WorkflowExecutorContext context) {
|
protected void doExecute(WorkflowExecutorContext context) {
|
||||||
|
|
||||||
if (Objects.equals(context.getWorkflowNodeStatus(), StatusEnum.NO.getStatus())) {
|
if (Objects.equals(context.getWorkflowNodeStatus(), StatusEnum.NO.getStatus())) {
|
||||||
JobTaskBatchGeneratorContext generatorContext = WorkflowTaskConverter.INSTANCE.toJobTaskBatchGeneratorContext(context);
|
context.setTaskBatchStatus(JobTaskBatchStatusEnum.CANCEL.getStatus());
|
||||||
generatorContext.setTaskBatchStatus(JobTaskBatchStatusEnum.CANCEL.getStatus());
|
context.setOperationReason(JobOperationReasonEnum.WORKFLOW_NODE_CLOSED_SKIP_EXECUTION.getReason());
|
||||||
generatorContext.setOperationReason(JobOperationReasonEnum.WORKFLOW_NODE_CLOSED_SKIP_EXECUTION.getReason());
|
context.setJobTaskStatus(JobTaskStatusEnum.CANCEL.getStatus());
|
||||||
generatorContext.setJobId(context.getJobId());
|
|
||||||
generatorContext.setTaskExecutorScene(context.getTaskExecutorScene());
|
|
||||||
jobTaskBatchGenerator.generateJobTaskBatch(generatorContext);
|
|
||||||
workflowBatchHandler.complete(context.getWorkflowTaskBatchId());
|
|
||||||
|
|
||||||
// 执行下一个节点
|
// 执行下一个节点
|
||||||
workflowTaskExecutor(context);
|
workflowTaskExecutor(context);
|
||||||
@ -73,11 +87,7 @@ public class JobTaskWorkflowExecutor extends AbstractWorkflowExecutor {
|
|||||||
private static void invokeJobTask(final WorkflowExecutorContext context) {
|
private static void invokeJobTask(final WorkflowExecutorContext context) {
|
||||||
// 生成任务批次
|
// 生成任务批次
|
||||||
JobTaskPrepareDTO jobTaskPrepare = JobTaskConverter.INSTANCE.toJobTaskPrepare(context.getJob(), context);
|
JobTaskPrepareDTO jobTaskPrepare = JobTaskConverter.INSTANCE.toJobTaskPrepare(context.getJob(), context);
|
||||||
// jobTaskPrepare.setTaskExecutorScene(context.getTaskExecutorScene());
|
|
||||||
jobTaskPrepare.setNextTriggerAt(DateUtils.toNowMilli() + DateUtils.toNowMilli() % 1000);
|
jobTaskPrepare.setNextTriggerAt(DateUtils.toNowMilli() + DateUtils.toNowMilli() % 1000);
|
||||||
// jobTaskPrepare.setWorkflowNodeId(context.getWorkflowNodeId());
|
|
||||||
// jobTaskPrepare.setWorkflowTaskBatchId(context.getWorkflowTaskBatchId());
|
|
||||||
// jobTaskPrepare.setParentWorkflowNodeId(context.getParentWorkflowNodeId());
|
|
||||||
// 执行预处理阶段
|
// 执行预处理阶段
|
||||||
ActorRef actorRef = ActorGenerator.jobTaskPrepareActor();
|
ActorRef actorRef = ActorGenerator.jobTaskPrepareActor();
|
||||||
actorRef.tell(jobTaskPrepare, actorRef);
|
actorRef.tell(jobTaskPrepare, actorRef);
|
||||||
|
@ -68,7 +68,7 @@ public class JobTaskBatchGenerator {
|
|||||||
try {
|
try {
|
||||||
WorkflowNodeTaskExecuteDTO taskExecuteDTO = new WorkflowNodeTaskExecuteDTO();
|
WorkflowNodeTaskExecuteDTO taskExecuteDTO = new WorkflowNodeTaskExecuteDTO();
|
||||||
taskExecuteDTO.setWorkflowTaskBatchId(context.getWorkflowTaskBatchId());
|
taskExecuteDTO.setWorkflowTaskBatchId(context.getWorkflowTaskBatchId());
|
||||||
taskExecuteDTO.setTaskExecutorScene(JobTaskExecutorSceneEnum.AUTO_JOB.getType());
|
taskExecuteDTO.setTaskExecutorScene(context.getTaskExecutorScene());
|
||||||
taskExecuteDTO.setParentId(context.getWorkflowNodeId());
|
taskExecuteDTO.setParentId(context.getWorkflowNodeId());
|
||||||
ActorRef actorRef = ActorGenerator.workflowTaskExecutorActor();
|
ActorRef actorRef = ActorGenerator.workflowTaskExecutorActor();
|
||||||
actorRef.tell(taskExecuteDTO, actorRef);
|
actorRef.tell(taskExecuteDTO, actorRef);
|
||||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
1
frontend/public/lib/assets/Z7fZzXo1.css
Normal file
1
frontend/public/lib/assets/Z7fZzXo1.css
Normal file
File diff suppressed because one or more lines are too long
@ -5,8 +5,8 @@
|
|||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>Easy Retry</title>
|
<title>Easy Retry</title>
|
||||||
<script type="module" crossorigin src="./assets/gfVhN6lL.js"></script>
|
<script type="module" crossorigin src="./assets/1RK3CeRh.js"></script>
|
||||||
<link rel="stylesheet" crossorigin href="./assets/-o3uFske.css">
|
<link rel="stylesheet" crossorigin href="./assets/Z7fZzXo1.css">
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
@ -169,6 +169,35 @@ export default {
|
|||||||
display: flex !important;
|
display: flex !important;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|
||||||
|
// 美化滚动条
|
||||||
|
::-webkit-scrollbar {
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-track {
|
||||||
|
width: 6px;
|
||||||
|
background: rgba(#101F1C, 0.1);
|
||||||
|
-webkit-border-radius: 2em;
|
||||||
|
-moz-border-radius: 2em;
|
||||||
|
border-radius: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-thumb {
|
||||||
|
background-color: rgba(144,147,153,.5);
|
||||||
|
background-clip: padding-box;
|
||||||
|
min-height: 28px;
|
||||||
|
-webkit-border-radius: 2em;
|
||||||
|
-moz-border-radius: 2em;
|
||||||
|
border-radius: 2em;
|
||||||
|
transition: background-color .3s;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-thumb:hover {
|
||||||
|
background-color: rgba(144,147,153,.3);
|
||||||
|
}
|
||||||
|
|
||||||
.scroller {
|
.scroller {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
|
Loading…
Reference in New Issue
Block a user