Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,6 @@ public interface BatchTaskAdminService {
AdminBatchTaskResultResponse batchCancel(AdminBatchTaskRequest request, String operatorId, String operatorName);

AdminBatchTaskResultResponse batchReassign(AdminBatchTaskRequest request, String operatorId, String operatorName);

AdminBatchTaskResultResponse batchUnassign(AdminBatchTaskRequest request, String operatorId, String operatorName);
}
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,14 @@ public AdminBatchTaskResultResponse batchReassign(AdminBatchTaskRequest request,
});
}

@Override
public AdminBatchTaskResultResponse batchUnassign(AdminBatchTaskRequest request,
String operatorId,
String operatorName) {
return executeBatch(request.getTaskIds(), (taskId) ->
dispatchTaskService.cancelTask(taskId, operatorId, operatorName, request.getRemark()));
}

private AdminBatchTaskResultResponse executeBatch(List<Long> taskIds,
TaskAction action) {
List<AdminBatchTaskItemResult> results = new ArrayList<>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ public class DispatchExceptionRecordEntity {

private String severity;

private Integer aggCount;

private String resolveAction;

private LocalDateTime occurTime;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,12 @@ public void recordException(Long taskId, Long orderId, Long vehicleId, String ex
}
DispatchExceptionRecordEntity existing = findOpenException(taskId, null, exceptionType);
if (existing != null) {
existing.setAggCount(existing.getAggCount() == null ? 2 : existing.getAggCount() + 1);
existing.setOccurTime(LocalDateTime.now());
existing.setExceptionMsg(exceptionMsg);
exceptionRecordMapper.updateById(existing);
if (existing.getId() != null) {
existing.setAggCount(existing.getAggCount() == null ? 2 : existing.getAggCount() + 1);
existing.setOccurTime(LocalDateTime.now());
existing.setExceptionMsg(exceptionMsg);
exceptionRecordMapper.updateById(existing);
}
return;
}
DispatchExceptionRecordEntity entity = new DispatchExceptionRecordEntity();
Expand All @@ -77,10 +79,12 @@ public void recordException(Long taskId, Long orderId, Long vehicleId, String ex
public void recordVehicleException(Long vehicleId, String exceptionType, String exceptionMsg) {
DispatchExceptionRecordEntity existing = findOpenException(null, vehicleId, exceptionType);
if (existing != null) {
existing.setAggCount(existing.getAggCount() == null ? 2 : existing.getAggCount() + 1);
existing.setOccurTime(LocalDateTime.now());
existing.setExceptionMsg(exceptionMsg);
exceptionRecordMapper.updateById(existing);
if (existing.getId() != null) {
existing.setAggCount(existing.getAggCount() == null ? 2 : existing.getAggCount() + 1);
existing.setOccurTime(LocalDateTime.now());
existing.setExceptionMsg(exceptionMsg);
exceptionRecordMapper.updateById(existing);
}
return;
}
DispatchExceptionRecordEntity entity = new DispatchExceptionRecordEntity();
Expand Down Expand Up @@ -175,7 +179,21 @@ private DispatchExceptionRecordEntity findOpenException(Long taskId, Long vehicl
if (vehicleId != null) {
wrapper.eq(DispatchExceptionRecordEntity::getVehicleId, vehicleId);
}
return exceptionRecordMapper.selectOne(wrapper);
Long count = exceptionRecordMapper.selectCount(wrapper);
if (count == null || count <= 0) {
return null;
}
DispatchExceptionRecordEntity entity = exceptionRecordMapper.selectOne(wrapper);
if (entity != null) {
return entity;
}
DispatchExceptionRecordEntity fallback = new DispatchExceptionRecordEntity();
fallback.setTaskId(taskId);
fallback.setVehicleId(vehicleId);
fallback.setExceptionType(exceptionType);
fallback.setExceptionStatus("OPEN");
fallback.setAggCount(1);
return fallback;
}

private Map<String, Object> buildPayload(DispatchExceptionRecordEntity entity) {
Expand Down
4 changes: 4 additions & 0 deletions back/sql/migrations/V35__dispatch_exception_agg_count.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
USE `fsd_core`;

ALTER TABLE `t_dispatch_exception_record`
ADD COLUMN `agg_count` INT NOT NULL DEFAULT 1 COMMENT 'Aggregated duplicate exception count' AFTER `severity`;
10 changes: 9 additions & 1 deletion front/src/api/systemHealth.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
import request from '@/utils/request'
import type { ApiResponse } from '@/types/api'
import type { SystemHealthResponse } from '@/types/phase10'
import type { DetailedMetricsResponse, HealthTimelineResponse, SystemHealthResponse } from '@/types/phase10'

export function getSystemHealth() {
return request.get<any, ApiResponse<SystemHealthResponse>>('/admin/system/health')
}

export function getDetailedMetrics() {
return request.get<any, ApiResponse<DetailedMetricsResponse>>('/admin/system/health/metrics')
}

export function getHealthTimeline() {
return request.get<any, ApiResponse<HealthTimelineResponse>>('/admin/system/health/timeline')
}
59 changes: 59 additions & 0 deletions front/src/types/phase10.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,65 @@ export interface SystemHealthResponse {
components: SystemComponentHealth[]
}

export interface MqQueueBacklog {
queueName: string
backlog: number
status: string
}

export interface DbConnectionPool {
active: number
idle: number
max: number
usagePercent: number
status: string
}

export interface RedisMemory {
usedBytes: number
maxBytes: number
usagePercent: number
status: string
}

export interface SseConnection {
activeConnections: number
status: string
}

export interface ApiLatencyHistoryPoint {
time: string
value: number
}

export interface ApiP99Latency {
currentMs: number
p50Ms: number
p95Ms: number
p99Ms: number
status: string
history: ApiLatencyHistoryPoint[]
}

export interface DetailedMetricsResponse {
mqBacklogs: MqQueueBacklog[]
dbConnectionPool: DbConnectionPool
redisMemory: RedisMemory
sseConnections: SseConnection
apiP99Latency: ApiP99Latency
}

export interface HealthTimelineItem {
component: string
status: string
message: string
time: string
}

export interface HealthTimelineResponse {
items: HealthTimelineItem[]
}

export interface GlobalSearchItem {
type: 'ORDER' | 'TASK' | 'VEHICLE' | string
id: number
Expand Down
2 changes: 1 addition & 1 deletion front/src/views/mobile/ParkOrder.vue
Original file line number Diff line number Diff line change
Expand Up @@ -389,7 +389,7 @@ function handleOrderModeUpdate(mode: MobileOrderMode) {
applyDefaultStations()
}

async function submitDemoRoute(route: (typeof parkDeliveryDemoRoutes)[number] | (typeof parkSchematicDemoRoutes)[number]) {
async function submitDemoRoute(route: { pickupCode: string; dropoffCode: string }) {
const { pickup, dropoff } = resolveStationIds(route.pickupCode, route.dropoffCode)
if (!pickup || !dropoff) {
message.warning('演示站点尚未加载,请稍后重试')
Expand Down
4 changes: 2 additions & 2 deletions front/src/views/vehicle/List.vue
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,8 @@ import { useAuthStore } from '@/stores/auth'
import { useParkScopeStore } from '@/stores/parkScope'
import { createVehicle, updateVehicle, getVehicleDetail } from '@/api/vehicle'
import { onlineStatusMap, dispatchStatusMap } from '@/constants/statusMap'
import type { OnlineStatus, DispatchStatus } from '@/constants/enums'
import { DispatchStatus } from '@/constants/enums'
import type { OnlineStatus } from '@/constants/enums'
import { DEFAULT_PAGE_SIZE } from '@/config'
import dayjs from 'dayjs'
import relativeTime from 'dayjs/plugin/relativeTime'
Expand Down Expand Up @@ -193,7 +194,6 @@ let silentRefreshTimer: ReturnType<typeof setInterval> | null = null

const ACTIVE_DISPATCH_STATUSES: DispatchStatus[] = [
DispatchStatus.BUSY,
DispatchStatus.CHARGING,
]

const columns = [
Expand Down
Loading