147 lines
3.9 KiB
TypeScript
147 lines
3.9 KiB
TypeScript
import type { ApiResponse } from "@/lib/api"
|
|
import type {
|
|
CreateOrderResult,
|
|
GameCity,
|
|
GameItem,
|
|
GameOrderData,
|
|
HttpOrderInfo,
|
|
} from "@/lib/models/http"
|
|
|
|
export const PHP_API_BASE_URL =
|
|
import.meta.env.VITE_PHP_API_BASE_URL ?? "https://php-api.juip.com"
|
|
|
|
const DEFAULT_TIMEOUT = 30_000
|
|
|
|
type RawHttpResponse = Record<string, unknown>
|
|
|
|
async function postJson<T = RawHttpResponse>(
|
|
path: string,
|
|
body: unknown,
|
|
): Promise<ApiResponse<T>> {
|
|
const controller = new AbortController()
|
|
const timer = setTimeout(() => controller.abort(), DEFAULT_TIMEOUT)
|
|
try {
|
|
const response = await fetch(`${PHP_API_BASE_URL}${path}`, {
|
|
method: "POST",
|
|
headers: { "Content-Type": "application/json" },
|
|
credentials: "include",
|
|
body: JSON.stringify(body),
|
|
signal: controller.signal,
|
|
})
|
|
if (!response.ok) {
|
|
return {
|
|
success: false,
|
|
status: response.status,
|
|
message: "请求失败",
|
|
}
|
|
}
|
|
const data = (await response.json()) as T
|
|
return { success: true, data }
|
|
} catch (e) {
|
|
if (controller.signal.aborted) {
|
|
return {
|
|
success: false,
|
|
status: 408,
|
|
message: "请求超时,请稍后重试",
|
|
}
|
|
}
|
|
return {
|
|
success: false,
|
|
status: 500,
|
|
message: (e as Error).message || "网络错误",
|
|
}
|
|
} finally {
|
|
clearTimeout(timer)
|
|
}
|
|
}
|
|
|
|
function unwrapD(raw: RawHttpResponse | undefined): Record<string, unknown> {
|
|
const d = raw?.d
|
|
if (d && typeof d === "object" && !Array.isArray(d)) {
|
|
return d as Record<string, unknown>
|
|
}
|
|
return {}
|
|
}
|
|
|
|
export async function fetchGameCities(
|
|
game: GameOrderData,
|
|
): Promise<ApiResponse<GameCity[]>> {
|
|
const res = await postJson<RawHttpResponse>("/http/product/city", game)
|
|
if (!res.success) return res
|
|
const cities = unwrapD(res.data).cities
|
|
return {
|
|
success: true,
|
|
data: Array.isArray(cities) ? (cities as GameCity[]) : [],
|
|
}
|
|
}
|
|
|
|
export async function fetchGameList(
|
|
game: GameOrderData,
|
|
): Promise<ApiResponse<GameItem[]>> {
|
|
const res = await postJson<RawHttpResponse>("/http/product/game", game)
|
|
if (!res.success) return res
|
|
const games = unwrapD(res.data).games
|
|
return {
|
|
success: true,
|
|
data: Array.isArray(games) ? (games as GameItem[]) : [],
|
|
}
|
|
}
|
|
|
|
export async function fetchGameLineCount(
|
|
game: GameOrderData,
|
|
): Promise<ApiResponse<number>> {
|
|
const res = await postJson<RawHttpResponse>("/http/product/linecount", game)
|
|
if (!res.success) return res
|
|
const count = unwrapD(res.data).count
|
|
return { success: true, data: Number(count) || 0 }
|
|
}
|
|
|
|
export async function calcGamePrice(
|
|
orderInfo: HttpOrderInfo,
|
|
): Promise<ApiResponse<number>> {
|
|
const res = await postJson<RawHttpResponse>(
|
|
"/http/product/calc_price",
|
|
orderInfo,
|
|
)
|
|
if (!res.success) return res
|
|
const raw = res.data ?? {}
|
|
const priceValue =
|
|
typeof raw.price === "number" ? raw.price : unwrapD(raw).price
|
|
return {
|
|
success: true,
|
|
data: typeof priceValue === "number" ? priceValue : 0,
|
|
}
|
|
}
|
|
|
|
export async function createHttpOrder(
|
|
orderInfo: HttpOrderInfo,
|
|
): Promise<ApiResponse<CreateOrderResult>> {
|
|
const res = await postJson<RawHttpResponse>("/http/order/create_order", {
|
|
cookie: document.cookie,
|
|
order_info: orderInfo,
|
|
})
|
|
if (!res.success) return res
|
|
return {
|
|
success: true,
|
|
data: {
|
|
code: Number(res.data?.code) || 0,
|
|
msg: typeof res.data?.msg === "string" ? res.data.msg : undefined,
|
|
data: typeof res.data?.data === "string" ? res.data.data : undefined,
|
|
},
|
|
}
|
|
}
|
|
|
|
export async function fetchHttpBalance(): Promise<ApiResponse<number>> {
|
|
const res = await postJson<RawHttpResponse | number>(
|
|
"/http/user/get_balance",
|
|
{
|
|
cookie: document.cookie,
|
|
},
|
|
)
|
|
if (!res.success) return res
|
|
if (typeof res.data === "number") return { success: true, data: res.data }
|
|
const raw = res.data ?? {}
|
|
const balance = raw.d ?? raw.data ?? raw.balance
|
|
return { success: true, data: Number(balance) || 0 }
|
|
}
|