You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

127 lines
3.6 KiB
TypeScript

import { http } from "../utils/service";
const VIDEO_LIST_PATH = "/notice/videolist";
const TICKET_LIST_PATH = "/notice/ticketlist";
let cachedVideoUrls: string[] = [];
let videoListPromise: Promise<string[]> | null = null;
export interface NoticeCallingItem {
ticketId: string;
winName: string;
isTransfer?: boolean;
}
export interface NoticeTicketListData {
total: number;
waitingNum: number;
completedNum: number;
dealingNum: number;
callinglist: NoticeCallingItem[];
abandonedlist: string[];
waitinglist: string[];
}
function normalizeCallingItem(raw: unknown): NoticeCallingItem | null {
if (!raw || typeof raw !== "object") {
return null;
}
const item = raw as Record<string, unknown>;
const ticketId = item.ticketId ?? item.ticket_id;
const winName = item.winName ?? item.win_name;
if (ticketId == null || winName == null) {
return null;
}
const isTransfer = item.isTransfer ?? item.is_transfer;
return {
ticketId: String(ticketId),
winName: String(winName),
isTransfer: Boolean(isTransfer),
};
}
function normalizeTicketIdFromListItem(raw: unknown): string | null {
if (raw == null) {
return null;
}
if (typeof raw === "string" || typeof raw === "number") {
const value = String(raw).trim();
return value.length > 0 ? value : null;
}
if (typeof raw === "object") {
const item = raw as Record<string, unknown>;
const ticketId = item.ticketId ?? item.ticket_id;
if (ticketId == null) {
return null;
}
const value = String(ticketId).trim();
return value.length > 0 ? value : null;
}
return null;
}
function normalizeTicketIdList(raw: unknown): string[] {
if (!Array.isArray(raw)) {
return [];
}
return raw
.map(normalizeTicketIdFromListItem)
.filter((ticketId): ticketId is string => ticketId !== null);
}
function normalizeTicketListData(raw: unknown): NoticeTicketListData {
const data = (raw ?? {}) as Record<string, unknown>;
const callingRaw = Array.isArray(data.callinglist) ? data.callinglist : [];
const callinglist = callingRaw
.map(normalizeCallingItem)
.filter((item): item is NoticeCallingItem => item !== null);
return {
total: Number(data.total ?? 0),
waitingNum: Number(data.waitingNum ?? data.waiting_num ?? 0),
completedNum: Number(data.completedNum ?? data.completed_num ?? 0),
dealingNum: Number(data.dealingNum ?? data.dealing_num ?? 0),
callinglist,
abandonedlist: normalizeTicketIdList(data.abandonedlist),
waitinglist: normalizeTicketIdList(data.waitinglist),
};
}
export async function fetchNoticeVideoList(): Promise<string[]> {
const data = await http.get<unknown>(VIDEO_LIST_PATH);
if (!Array.isArray(data)) {
return [];
}
return data.map((url) => String(url)).filter((url) => url.trim().length > 0);
}
export async function fetchNoticeTicketList(): Promise<NoticeTicketListData> {
const data = await http.get<unknown>(TICKET_LIST_PATH);
return normalizeTicketListData(data);
}
export function getCachedNoticeVideoUrls(): string[] {
return [...cachedVideoUrls];
}
/** 客户端打开时拉取宣传视频列表(结果缓存,重复调用复用同一请求)。 */
export async function loadNoticeVideoListOnOpen(force = false): Promise<string[]> {
if (!force && cachedVideoUrls.length > 0) {
return [...cachedVideoUrls];
}
if (!force && videoListPromise) {
return videoListPromise;
}
videoListPromise = fetchNoticeVideoList()
.then((urls) => {
cachedVideoUrls = urls;
return [...urls];
})
.finally(() => {
videoListPromise = null;
});
return videoListPromise;
}