个人开发4
-
支持演练过程跟踪管理(步骤状态、操作记录、日志文件)
-
强制阅读安全须知(弹窗+1分钟语音朗读)
-
记录操作人、时间轴、安全确认状态
-
实时展示演练进度
// 安全确认API(JPA实体)
@Entity
@Table(name = "drill_execution")
public class DrillExecution {
@Column(name = "safety_confirmed", columnDefinition = "TINYINT(1) DEFAULT 0")
private Boolean safetyConfirmed; // 确认状态@Column(name = "safety_confirm_time")
private LocalDateTime safetyConfirmTime; // 确认时间
}
// 安全校验拦截器
@Component
public class SafetyCheckInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest req, HttpServletResponse res, Object handler) {
Integer executionId = getExecutionIdFromRequest(req);
DrillExecution exec = executionRepo.findById(executionId)
.orElseThrow(() -> new BizException("演练不存在"));
if (!exec.getSafetyConfirmed()) {
throw new SafetyCheckException("请先完成安全须知确认"); // 自定义异常
}
return true;
}
}
前端实现
vue
@Aspect
@Component
public class StepLogAspect {
@Pointcut("@annotation(com.emdrill.anno.LogStepAction)")
public void logPointcut() {}
@Around("logPointcut()")
public Object logStepAction(ProceedingJoinPoint pjp) throws Throwable {
Method method = ((MethodSignature) pjp.getSignature()).getMethod();
LogStepAction annotation = method.getAnnotation(LogStepAction.class);
// 记录操作前状态
StepLog preLog = buildPreLog(pjp.getArgs());
logRepository.save(preLog);
Object result = pjp.proceed();
// 记录操作后状态
StepLog postLog = buildPostLog(result);
logRepository.save(postLog);
return result;
}
}
// 使用注解标记需要日志记录的方法
@LogStepAction(actionType = "START_STEP")
public void startStep(Integer executionId) { ... }
WebSocket配置
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/topic/progress");
config.setApplicationDestinationPrefixes("/app");
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/ws-drill")
.setAllowedOrigins("*")
.withSockJS();
}
}
// 进度更新推送服务
@Service
@RequiredArgsConstructor
public class ProgressPushService {
private final SimpMessagingTemplate messagingTemplate;
public void pushProgressUpdate(Integer executionId, ProgressVO vo) {
messagingTemplate.convertAndSend(
"/topic/progress/" + executionId,
vo
);
}
<template>
<GanttChart
:tasks="ganttTasks"
@task-updated="handleTaskUpdate"
/>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import SockJS from 'sockjs-client'
import { Client } from '@stomp/stompjs'
const executionId = props.executionId
const ganttTasks = ref([])
// WebSocket连接初始化
const initWebSocket = () => {
const client = new Client({
brokerURL: 'ws://your-domain/ws-drill',
reconnectDelay: 5000,
onConnect: () => {
client.subscribe(`/topic/progress/${executionId}`, (msg) => {
const data = JSON.parse(msg.body)
updateGantt(data)
})
}
})
client.activate()
}
const updateGantt = (progressData) => {
ganttTasks.value = progressData.steps.map(step => ({
id: step.stepId,
name: step.stepName,
start: new Date(step.startTime),
end: new Date(step.endTime),
progress: step.progressPercent
}))
}
</script>
语音播放兼容性问题
document.addEventListener('click', () => {
audioElement.play().catch(() => {
showManualPlayButton() // 显示手动播放按健
})
}, { once: true })
@Entity
public class DrillExecution {
@Version
private Integer version;
}
@Transactional
public void updateStep(Integer id, StepUpdateDTO dto) {
DrillExecution exec = repository.findByIdWithLock(id);
if (!exec.getVersion().equals(dto.getVersion())) {
throw new OptimisticLockException("数据已被修改,请刷新重试");
}
}
| 功能测试 | 未确认安全须知时发起步骤操作 | 拦截请求并返回错误码SAFETY_CHECK_FAIL(1001) |
yaml
# Prometheus配置示例
scrape_configs:
- job_name: 'drill-execution'
metrics_path: '/actuator/prometheus'
static_configs:
- targets: ['execution-service:8080']
# Grafana仪表盘指标
- 实时在线人数(WebSocket连接数)
- 步骤操作TPS(Transactions Per Second)
- 语音合成服务响应时长(P99延迟)
**容器化部署**
```dockerfile
# 前端容器
FROM nginx:alpine
COPY dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
# 后端容器
FROM openjdk:17-jdk-slim
COPY target/execution-service.jar /app.jar
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
浙公网安备 33010602011771号