feat: 优化发布单冲突提示
- src/services/http.ts: 保留后端 envelope 错误码、状态和 details - src/stores/platform.ts: 增加发布单列表轻量刷新入口 - src/views: 发布中心和运行记录接入 CONFLICT 刷新提示 - src/types/devops.ts: 同步 ReleaseRun version 字段
This commit is contained in:
@@ -98,6 +98,7 @@ interface BackendDeployRunStep {
|
||||
|
||||
interface BackendDeployRun {
|
||||
id?: string
|
||||
version?: number
|
||||
projectKey?: string
|
||||
environment?: EnvironmentName
|
||||
ref?: string
|
||||
@@ -993,6 +994,7 @@ function toReleaseRun(run: BackendDeployRun, projectList: ProjectConfig[]): Rele
|
||||
|
||||
return {
|
||||
id: run.id || `${projectKey}-${ref}-${run.createdAt ?? Date.now()}`,
|
||||
version: typeof run.version === 'number' && Number.isFinite(run.version) ? run.version : 0,
|
||||
projectKey,
|
||||
projectName: project?.name ?? projectKey,
|
||||
environment: toEnvironmentName(run.environment),
|
||||
|
||||
+85
-8
@@ -1,5 +1,29 @@
|
||||
import axios from 'axios'
|
||||
|
||||
type DevopsApiErrorOptions = {
|
||||
code?: string
|
||||
message?: string
|
||||
details?: unknown
|
||||
status?: number
|
||||
}
|
||||
|
||||
/**
|
||||
* 后端 envelope 错误在浏览器侧的统一形态,保留 code/details 供页面做精确交互。
|
||||
*/
|
||||
export class DevopsApiError extends Error {
|
||||
readonly code: string
|
||||
readonly details: unknown
|
||||
readonly status: number | undefined
|
||||
|
||||
constructor(options: DevopsApiErrorOptions) {
|
||||
super(options.message || '请求失败,请稍后重试')
|
||||
this.name = 'DevopsApiError'
|
||||
this.code = options.code || 'HTTP_ERROR'
|
||||
this.details = options.details
|
||||
this.status = options.status
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* DevOps 平台统一 HTTP 实例,只识别后端 envelope,不承接任何第三方密钥。
|
||||
*/
|
||||
@@ -27,13 +51,7 @@ http.interceptors.response.use(
|
||||
return response
|
||||
},
|
||||
(error) => {
|
||||
const message =
|
||||
error.response?.data?.error?.message ||
|
||||
error.response?.data?.message ||
|
||||
error.message ||
|
||||
'请求失败,请稍后重试'
|
||||
|
||||
return Promise.reject(new Error(message))
|
||||
return Promise.reject(toDevopsApiError(error))
|
||||
},
|
||||
)
|
||||
|
||||
@@ -59,7 +77,11 @@ function unwrapApiPayload(payload: unknown): unknown {
|
||||
return envelope.data
|
||||
}
|
||||
|
||||
throw new Error(envelope.error?.message || '请求失败,请稍后重试')
|
||||
throw new DevopsApiError({
|
||||
code: envelope.error?.code,
|
||||
message: envelope.error?.message,
|
||||
details: envelope.error?.details,
|
||||
})
|
||||
}
|
||||
|
||||
if (Object.keys(payload).length === 1 && 'data' in payload) {
|
||||
@@ -76,3 +98,58 @@ function isRecord(value: unknown): value is Record<string, unknown> {
|
||||
function isApiEnvelope(value: unknown): value is ApiEnvelope<unknown> {
|
||||
return isRecord(value) && typeof value.success === 'boolean'
|
||||
}
|
||||
|
||||
/**
|
||||
* 类型守卫供页面区分业务错误与普通网络错误,避免靠中文文案判断状态。
|
||||
*/
|
||||
export function isDevopsApiError(error: unknown): error is DevopsApiError {
|
||||
return error instanceof DevopsApiError
|
||||
}
|
||||
|
||||
function toDevopsApiError(error: unknown): DevopsApiError {
|
||||
if (isDevopsApiError(error)) {
|
||||
return error
|
||||
}
|
||||
|
||||
if (isRecord(error)) {
|
||||
const response = isRecord(error.response) ? error.response : undefined
|
||||
const status = typeof response?.status === 'number' ? response.status : undefined
|
||||
const payload = response?.data
|
||||
|
||||
if (isApiEnvelope(payload)) {
|
||||
return new DevopsApiError({
|
||||
code: payload.error?.code,
|
||||
message: payload.error?.message,
|
||||
details: payload.error?.details,
|
||||
status,
|
||||
})
|
||||
}
|
||||
|
||||
if (isRecord(payload)) {
|
||||
const backendError = isRecord(payload.error) ? payload.error : undefined
|
||||
const code = textValue(backendError?.code) || textValue(payload.code)
|
||||
const message =
|
||||
textValue(backendError?.message) ||
|
||||
textValue(payload.message) ||
|
||||
textValue(error.message)
|
||||
|
||||
return new DevopsApiError({
|
||||
code,
|
||||
message,
|
||||
details: backendError?.details ?? payload.details,
|
||||
status,
|
||||
})
|
||||
}
|
||||
|
||||
return new DevopsApiError({
|
||||
message: textValue(error.message),
|
||||
status,
|
||||
})
|
||||
}
|
||||
|
||||
return new DevopsApiError({})
|
||||
}
|
||||
|
||||
function textValue(value: unknown): string | undefined {
|
||||
return typeof value === 'string' && value.trim() ? value : undefined
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user