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 ADD_DATA_INFLUX_STORAGE_TYPE = 'INFLUXDB' 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() 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 ( method: AddDataRequestMethod, path: string, params?: object ): Promise> => { 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(requestPath) } return await http.post(requestPath, params) } catch (error) { lastError = error if (index === requestPaths.length - 1 || !isFallbackableAddDataError(error)) { throw error } } } throw lastError } const resolveTaskPathPrefix = (storageType?: AddData.StorageType) => { // MySQL 与 InfluxDB 任务接口相互独立,创建和状态轮询必须使用同一入库类型前缀。 return storageType === ADD_DATA_INFLUX_STORAGE_TYPE ? '/influx/task' : '/task' } export const getAddDataStorageTypeList = () => { return requestAddData('get', '/storage-type/list') } export const getAddDataPreview = (params: AddData.TaskRequestParams) => { return requestAddData('post', '/task/preview', params) } export const createAddDataTask = (params: AddData.TaskRequestParams, storageType?: AddData.StorageType) => { return requestAddData('post', `${resolveTaskPathPrefix(storageType)}/create`, params) } export const getAddDataTaskStatus = (taskId: string | number, storageType?: AddData.StorageType) => { return requestAddData('get', `${resolveTaskPathPrefix(storageType)}/status/${taskId}`) } export const getAddDataTemplateList = () => { return requestAddData('get', '/template/list') }