import type { DetailCreate, DetailPriceUnit, WanfaRouteCreate } from "@/types"; export function createEmptyWanfaRoute(): WanfaRouteCreate { return { title: "", subtitle: "", image: "", routeCount: 0, demandKeyword: "" }; } export function compactWanfaRoute(draft: WanfaRouteCreate): WanfaRouteCreate { return { title: draft.title.trim(), subtitle: draft.subtitle.trim(), image: draft.image.trim(), routeCount: Number.isFinite(Number(draft.routeCount)) ? Math.max(0, Number(draft.routeCount)) : 0, demandKeyword: draft.demandKeyword.trim(), }; } export function createEmptyDetail(): DetailCreate { return { key: "", eyebrow: "玩法路线", duration: "", title: "", subtitle: "", intro: "", highlights: [], included: [], excluded: [], notes: [], gallery: [], priceStartingValue: null, priceUnit: null, pricePeopleRange: "", priceDescription: "", conciergeAdvisorId: null, isActive: true, }; } export function compactDetail(draft: DetailCreate): DetailCreate { return { key: draft.key.trim(), eyebrow: draft.eyebrow.trim(), duration: draft.duration.trim(), title: draft.title.trim(), subtitle: draft.subtitle.trim(), intro: draft.intro.trim(), highlights: compactList(draft.highlights), included: compactList(draft.included), excluded: compactList(draft.excluded), notes: compactList(draft.notes), gallery: compactList(draft.gallery), priceStartingValue: normalizePriceStartingValue(draft.priceStartingValue), priceUnit: normalizePriceUnit(draft.priceUnit), pricePeopleRange: draft.pricePeopleRange?.trim() || null, priceDescription: draft.priceDescription?.trim() || null, conciergeAdvisorId: draft.conciergeAdvisorId?.trim() || null, isActive: draft.isActive ?? true, ...(draft.sortOrder === undefined ? {} : { sortOrder: draft.sortOrder }), }; } export function validateWanfaWrite(route: WanfaRouteCreate, detail: DetailCreate) { if (!route.title || !route.subtitle || !route.image || !route.demandKeyword) { return "请完整填写路线标题、副标题、封面和需求关键词。"; } if (!isHttpUrl(route.image)) return "路线封面必须是有效的 HTTP(S) URL。"; if (!Number.isInteger(route.routeCount) || route.routeCount < 0) { return "路线数量必须是大于等于 0 的整数。"; } if (!detail.eyebrow || !detail.duration || !detail.title || !detail.subtitle || !detail.intro) { return "请完整填写详情眉标、时长、标题、副标题和详情介绍。"; } if (detail.gallery.some((image) => !isHttpUrl(image))) return "详情图片必须是有效的 HTTP(S) URL。"; if (detail.priceStartingValue !== null && detail.priceStartingValue !== undefined && !detail.priceUnit) { return "配置价格起始值时请选择价格单位。"; } return null; } function normalizePriceStartingValue(value: number | null | undefined) { if (value === null || value === undefined || !Number.isFinite(Number(value))) return null; return Math.max(0, Number(Number(value).toFixed(2))); } function normalizePriceUnit(value: DetailPriceUnit | null | undefined): DetailPriceUnit | null { return value === "person" || value === "day" || value === "group" ? value : null; } function compactList(items: string[]) { return items.map((item) => item.trim()).filter(Boolean); } function isHttpUrl(value: string) { try { const url = new URL(value); return url.protocol === "http:" || url.protocol === "https:"; } catch { return false; } }