front/src/api/oms/common.ts
zzh e5175e6cc1
All checks were successful
Build and Deploy Front / deploy (push) Successful in 6m4s
feat: H5 门户切换与充值审核,订单编辑支持仓库件重尺及 COS 资源代理修复
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-15 19:53:24 +08:00

139 lines
4.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* OMS admin 接口通用:与 /order 同源(开发环境走 Vite 代理路径前缀)
*/
import type { AxiosError } from 'axios'
import { axiosInstance } from '@/api/rbac'
import { resolveAdminApiPath, resolveAdminAssetOrigin } from '@/utils/adminApi'
/** 从 axios / 业务响应中提取可读错误信息 */
export function extractOmsRequestError(err: unknown): string {
const axiosErr = err as AxiosError<{ msg?: string; Msg?: string; message?: string; Message?: string }>
const data = axiosErr?.response?.data
if (data && typeof data === 'object') {
const msg = data.msg ?? data.Msg ?? data.message ?? data.Message
if (msg != null && String(msg).trim()) {
return String(msg).trim()
}
}
return err instanceof Error ? err.message : String(err)
}
export function omsUrl(path: string): string {
return resolveAdminApiPath(path)
}
export function assertBusinessOk(body: any) {
if (body == null) throw new Error('空响应')
const code = body.code ?? body.Code
const ok =
code === undefined ||
code === null ||
code === 0 ||
code === 200 ||
code === '0' ||
code === '200' ||
body.success === true ||
body.Success === true
if (!ok) {
throw new Error(body.msg ?? body.Msg ?? body.message ?? body.Message ?? '请求失败')
}
}
/** 分页列表载荷(兼容 camel/Pascal、items/list/records) */
export function parseListPayload(resBody: any): { items: any[]; total: number } {
assertBusinessOk(resBody)
const inner = resBody.data ?? resBody.Data ?? resBody
if (Array.isArray(inner)) {
return { items: inner, total: inner.length }
}
const payload =
inner && typeof inner === 'object' && !Array.isArray(inner) ? inner : resBody
const items =
payload.items ??
payload.Items ??
payload.list ??
payload.List ??
payload.records ??
payload.Records ??
payload.rows ??
payload.Rows ??
payload.result ??
payload.Result ??
(Array.isArray(payload.data) ? payload.data : undefined) ??
(Array.isArray(payload.Data) ? payload.Data : undefined) ??
[]
const totalRaw =
payload.total ??
payload.Total ??
payload.totalCount ??
payload.TotalCount ??
payload.count ??
payload.Count
const list = Array.isArray(items) ? items : []
const total =
typeof totalRaw === 'number'
? totalRaw
: totalRaw != null && totalRaw !== ''
? Number(totalRaw)
: list.length
return { items: list, total: Number.isFinite(total) ? total : list.length }
}
export function unwrapData<T = any>(resBody: any): T {
assertBusinessOk(resBody)
const nested = resBody.data ?? resBody.Data
if (nested !== undefined && nested !== null) {
return nested as T
}
// 部分 OMS 接口直接返回业务 DTO,无 data 包裹
return resBody as T
}
export async function omsGet<T = any>(path: string, params?: Record<string, any>): Promise<T> {
const res = await axiosInstance.get(omsUrl(path), { params })
return unwrapData<T>(res.data)
}
export async function omsPost<T = any>(path: string, body?: Record<string, any>): Promise<T> {
const res = await axiosInstance.post(omsUrl(path), body ?? {})
return unwrapData<T>(res.data)
}
/**
* COS 绝对地址 → 同源 `/__cos__/<host>/...`(开发 Vite / 生产 nginx 反代)。
* cos.ideship.com 等自定义域名 https 不可用,直链 http 又会在 https 页面触发混合内容。
*/
function toCosSameOriginProxyUrl(absoluteUrl: string): string | null {
try {
const u = new URL(absoluteUrl)
const host = u.hostname.toLowerCase()
if (!host.startsWith('cos.') && !host.includes('myqcloud.com')) return null
return `/__cos__/${u.host}${u.pathname}${u.search}`
} catch {
return null
}
}
/** 将 /uploads/... 相对路径转为可访问 URL(同源相对,或 VITE_API_ASSET_ORIGIN 绝对前缀) */
export function resolveOmsAssetUrl(path?: string | null): string {
if (!path) return ''
const value = path.trim()
if (!value) return ''
if (/^https?:\/\//i.test(value) || value.startsWith('data:') || value.startsWith('blob:')) {
const cosProxied = toCosSameOriginProxyUrl(value)
if (cosProxied) return cosProxied
// 纠正常见错链:api.nanafa.com/uploads → api.nanafa.com/admin/uploads
return value.replace(
/^(https?:\/\/api\.(?:nanafa|ideship)\.com)\/uploads\//i,
'$1/admin/uploads/',
)
}
const origin = resolveAdminAssetOrigin()
const rel = value.startsWith('/') ? value : `/${value}`
return origin ? `${origin}${rel}` : rel
}