feat(tools): 新增数据补数功能模块
- 实现补数任务面板组件,支持监测点ID输入、时间范围选择和时间步长设置 - 添加任务状态卡片组件,实时展示任务执行进度和结果统计 - 集成参数规则表格组件,显示后端配置的模板规则信息 - 实现补数API接口服务,包括预估写入量、创建任务和查询状态功能 - 添加磁盘监控策略对话框组件,支持全局监控配置管理 - 完成补数功能页面布局设计,集成左右双栏界面结构 - 实现任务轮询机制,自动更新任务执行状态直到完成 - 添加表单验证逻辑,确保输入参数符合业务规则要求
This commit is contained in:
98
frontend/src/api/tools/addData/index.ts
Normal file
98
frontend/src/api/tools/addData/index.ts
Normal file
@@ -0,0 +1,98 @@
|
||||
import http from '@/api'
|
||||
import type { ResultData } from '@/api/interface'
|
||||
import type { AddData } from './interface'
|
||||
|
||||
type AddDataRequestMethod = 'get' | 'post'
|
||||
|
||||
const ADD_DATA_ROUTE_PATHS = ['/addData', '/api/addData'] as const
|
||||
const ADD_DATA_BASE_URL = String(import.meta.env.VITE_API_URL || '').trim()
|
||||
|
||||
const resolveDevProxyTarget = () => {
|
||||
const proxyConfig = import.meta.env.VITE_PROXY
|
||||
if (!Array.isArray(proxyConfig)) return ''
|
||||
|
||||
const matchedProxy = proxyConfig.find(item => Array.isArray(item) && item[0] === '/api')
|
||||
if (!matchedProxy?.[1]) return ''
|
||||
|
||||
return String(matchedProxy[1]).replace(/\/+$/, '')
|
||||
}
|
||||
|
||||
const buildAddDataRequestPaths = (path: string) => {
|
||||
const requestPaths = new Set<string>()
|
||||
const devProxyTarget = resolveDevProxyTarget()
|
||||
|
||||
for (const routePath of ADD_DATA_ROUTE_PATHS) {
|
||||
if (ADD_DATA_BASE_URL === '/api' && routePath.startsWith('/api/')) {
|
||||
if (devProxyTarget) {
|
||||
requestPaths.add(`${devProxyTarget}${routePath}${path}`)
|
||||
}
|
||||
|
||||
requestPaths.add(`${window.location.origin}${routePath}${path}`)
|
||||
continue
|
||||
}
|
||||
|
||||
requestPaths.add(`${routePath}${path}`)
|
||||
}
|
||||
|
||||
return Array.from(requestPaths)
|
||||
}
|
||||
|
||||
const isFallbackableAddDataError = (error: unknown) => {
|
||||
const responseCode = typeof error === 'object' && error !== null && 'code' in error ? String(error.code) : ''
|
||||
const responseMessage = typeof error === 'object' && error !== null && 'message' in error ? String(error.message) : ''
|
||||
const normalizedMessage = responseMessage.toLowerCase()
|
||||
|
||||
// 部分部署环境会把未命中的 addData 路由转到旧的操作分发入口,
|
||||
// 前端在识别到“unknown operate”或典型路由错误时回退到备用前缀重试一次。
|
||||
return (
|
||||
responseCode === '404' ||
|
||||
normalizedMessage.includes('unknown operate') ||
|
||||
normalizedMessage.includes('not found') ||
|
||||
normalizedMessage.includes('no handler found')
|
||||
)
|
||||
}
|
||||
|
||||
const requestAddData = async <T>(
|
||||
method: AddDataRequestMethod,
|
||||
path: string,
|
||||
params?: object
|
||||
): Promise<ResultData<T>> => {
|
||||
let lastError: unknown
|
||||
const requestPaths = buildAddDataRequestPaths(path)
|
||||
|
||||
for (let index = 0; index < requestPaths.length; index += 1) {
|
||||
const requestPath = requestPaths[index]
|
||||
|
||||
try {
|
||||
if (method === 'get') {
|
||||
return await http.get<T>(requestPath)
|
||||
}
|
||||
|
||||
return await http.post<T>(requestPath, params)
|
||||
} catch (error) {
|
||||
lastError = error
|
||||
|
||||
if (index === requestPaths.length - 1 || !isFallbackableAddDataError(error)) {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw lastError
|
||||
}
|
||||
|
||||
export const getAddDataPreview = (params: AddData.TaskRequestParams) => {
|
||||
return requestAddData<AddData.PreviewResponse>('post', '/task/preview', params)
|
||||
}
|
||||
|
||||
export const createAddDataTask = (params: AddData.TaskRequestParams) => {
|
||||
return requestAddData<AddData.CreateTaskResponse>('post', '/task/create', params)
|
||||
}
|
||||
|
||||
export const getAddDataTaskStatus = (taskId: string | number) => {
|
||||
return requestAddData<AddData.TaskStatusResponse>('get', `/task/status/${taskId}`)
|
||||
}
|
||||
|
||||
export const getAddDataTemplateList = () => {
|
||||
return requestAddData<AddData.TemplateItem[]>('get', '/template/list')
|
||||
}
|
||||
109
frontend/src/api/tools/addData/interface/index.ts
Normal file
109
frontend/src/api/tools/addData/interface/index.ts
Normal file
@@ -0,0 +1,109 @@
|
||||
export namespace AddData {
|
||||
export type LineMode = 'single' | 'multiple'
|
||||
export type IntervalMinutes = 1 | 3 | 5 | 10
|
||||
export type TaskStatus = 'WAITING' | 'RUNNING' | 'SUCCESS' | 'FAILED' | (string & {})
|
||||
|
||||
export interface TaskRequestParams {
|
||||
lineIds: string[]
|
||||
startTime: string
|
||||
endTime: string
|
||||
intervalMinutes: IntervalMinutes
|
||||
}
|
||||
|
||||
export interface TaskFormModel {
|
||||
lineMode: LineMode
|
||||
lineIds: string[]
|
||||
startTime: string
|
||||
endTime: string
|
||||
intervalMinutes: IntervalMinutes
|
||||
}
|
||||
|
||||
export interface PreviewTableStat {
|
||||
tableName?: string
|
||||
timePointCount?: number | string
|
||||
phaseCount?: number | string
|
||||
rowCount?: number | string
|
||||
}
|
||||
|
||||
export interface PreviewResponse {
|
||||
lineCount?: number | string
|
||||
intervalMinutes?: number | string
|
||||
totalRowCount?: number | string
|
||||
tableStats?: PreviewTableStat[]
|
||||
}
|
||||
|
||||
export interface CreateTaskResponse {
|
||||
taskId?: string | number
|
||||
status?: TaskStatus
|
||||
}
|
||||
|
||||
export interface TaskStatusResponse {
|
||||
taskId?: string
|
||||
status?: TaskStatus
|
||||
currentTableName?: string
|
||||
currentBatchInfo?: string
|
||||
insertedCount?: number | string
|
||||
skippedCount?: number | string
|
||||
failedCount?: number | string
|
||||
failureReason?: string
|
||||
startTime?: string
|
||||
endTime?: string
|
||||
hourlyTimeResults?: string[]
|
||||
}
|
||||
|
||||
export interface TemplateItem {
|
||||
parameterName?: string
|
||||
tableName?: string
|
||||
phaseDisplay?: string
|
||||
phaseCodes?: string[]
|
||||
display?: boolean
|
||||
showQualified?: boolean
|
||||
maxValueRule?: string
|
||||
minValueRule?: string
|
||||
averageValueRule?: string
|
||||
cp95ValueRule?: string
|
||||
decimalScale?: number | string
|
||||
}
|
||||
|
||||
export interface PreviewTableSummary {
|
||||
tableName: string
|
||||
timePointCount: number
|
||||
phaseCount: number
|
||||
rowCount: number
|
||||
}
|
||||
|
||||
export interface NormalizedPreview {
|
||||
lineCount: number
|
||||
intervalMinutes: number
|
||||
totalRowCount: number
|
||||
tableStats: PreviewTableSummary[]
|
||||
}
|
||||
|
||||
export interface NormalizedTaskStatus {
|
||||
taskId: string
|
||||
status: TaskStatus
|
||||
currentTableName: string
|
||||
currentBatchInfo: string
|
||||
insertedCount: number
|
||||
skippedCount: number
|
||||
failedCount: number
|
||||
failureReason: string
|
||||
hourlyTimeResults: string[]
|
||||
startTime: string
|
||||
endTime: string
|
||||
}
|
||||
|
||||
export interface NormalizedTemplateItem {
|
||||
parameterName: string
|
||||
tableName: string
|
||||
phaseDisplay: string
|
||||
phaseCodesText: string
|
||||
displayText: string
|
||||
showQualifiedText: string
|
||||
maxValueRule: string
|
||||
minValueRule: string
|
||||
averageValueRule: string
|
||||
cp95ValueRule: string
|
||||
decimalScaleText: string
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user