import { isCorpGoodsType } from './detail' export type UploadedImage = { id: string url: string preview: string } export type OrderLike = { order_id?: string goods_type?: string goods_name?: string entity_name?: string entity_phone?: string entity_extra?: Record extra?: Record [key: string]: any } export type ResubmitValues = { entity_name?: string entity_address_name?: string entity_address?: string entity_phone?: string entity_phone2?: string } const OMIT_EXTRA_KEYS = new Set([ 'origin_price', 'qrCodeImgUrl', 'remoteIp', 'weixinAppId', 'entity_storefront_image', 'entity_business_license_image', 'entity_storefront_image_url', 'entity_business_license_image_url', 'goods_param', ]) function splitValues (value: unknown) { if (value === undefined || value === null) return [] return String(value) .split(',') .map((item) => item.trim()) .filter(Boolean) } function isEmptySlotToken (value?: string) { return !value || value === 'null' || value === '0' } function splitSlotValues (value: unknown) { if (value === undefined || value === null || value === '') return [] return String(value).split(',').map((item) => item.trim()) } export type StorefrontSlot = UploadedImage | null export function joinStorefrontSlots (slots: Array = []) { return [0, 1, 2].map((index) => { const id = slots[index]?.id?.trim() return id ? id : '0' }).join(',') } export function parseStorefrontSlots (order: OrderLike | null | undefined): StorefrontSlot[] { const extra = order?.extra || {} const ids = splitSlotValues(extra.entity_storefront_image) const urls = splitSlotValues(extra.entity_storefront_image_url) return [0, 1, 2].map((index) => { const id = ids[index] || '' const url = urls[index] || '' if (isEmptySlotToken(id) && isEmptySlotToken(url)) return null if (isEmptySlotToken(id) && !isEmptySlotToken(url)) { return { id: '', url, preview: url } } const resolvedUrl = !isEmptySlotToken(url) ? url : (/^https?:\/\//i.test(id) ? id : '') return { id: /^https?:\/\//i.test(id) ? '' : id, url: resolvedUrl, preview: resolvedUrl, } }) } export function isCoordinateAddress (address?: string) { if (!address) return false const parts = address.split(',').map((part) => part.trim()) if (parts.length !== 2) return false return parts.every((part) => Number.isFinite(Number(part))) } export function parseCoordinate (address?: string) { if (!isCoordinateAddress(address)) return null const [lng, lat] = String(address).split(',').map((part) => Number(part.trim())) return { lng, lat } } export function formatMapCoordinate (point: { lng: number, lat: number }) { return `${point.lng.toFixed(6)},${point.lat.toFixed(6)}` } export function formatMapCoordinateDisplay (point: { lng: number, lat: number }) { return `N${point.lat.toFixed(6)}°, E${point.lng.toFixed(6)}°` } export function getOrderAddressName (order: OrderLike) { const extra = order.extra || {} return extra.entity_address_name || (!isCoordinateAddress(extra.entity_address) ? extra.entity_address : '') || '' } export function getOrderMapAddress (order: OrderLike) { const extra = order.extra || {} return isCoordinateAddress(extra.entity_address) ? extra.entity_address : '' } export function getInitialPhone2 (order: OrderLike) { const extra = order.extra || {} return String(extra.entity_phone2 || extra.entity_phone_2 || extra.phone2 || '') } export function getGoodsIcons (order: OrderLike) { const icons = order.extra?.goods_param?.['client.goods.icon'] return Array.isArray(icons) ? icons.filter((item) => typeof item === 'string') : [] } export function normalizeOrders (orders: T[] = []) { return orders.map((item) => { const nextItem = { ...item, extra: { ...(item.extra || {}) } } const goodsParam = nextItem.extra.goods_param if (typeof goodsParam === 'string') { try { nextItem.extra.goods_param = JSON.parse(goodsParam) } catch { nextItem.extra.goods_param = null } } return nextItem }) } export const MAP_LABEL_DISPLAY_NAME = '商户资料服务' export function getOrderDisplayName (order?: OrderLike | null) { if (order?.goods_type === 'map_label') return MAP_LABEL_DISPLAY_NAME return String(order?.goods_name || '').trim() || '-' } export function filterOrdersForProduct (goodsType: string, orders: T[] = []) { const normalized = normalizeOrders(orders) if (isCorpGoodsType(goodsType)) return normalized const target = goodsType || 'map_label' return normalized.filter((item) => item.goods_type === target) } export function filterMapLabelOrders (orders: T[] = []) { return filterOrdersForProduct('map_label', orders) } export function getOrderExtraImages (order: OrderLike | null | undefined, keys: string[]): UploadedImage[] { const extra = order?.extra || {} for (const key of keys) { const values = splitValues(extra[key]) const explicitIds = splitValues(extra[`${key}_id`]) const explicitUrls = splitValues(extra[`${key}_url`]) const urls = explicitUrls.length > 0 ? explicitUrls : values.filter((value) => /^https?:\/\//i.test(value)) if (urls.length > 0) { return urls.map((url, index) => { const valueId = values[index] && values[index] !== url ? values[index] : '' return { id: valueId || explicitIds[index] || '', url, preview: url, } }) } } return [] } export function joinUploadedImageIds (images: UploadedImage[]) { return images .map((image) => image.id.trim()) .filter(Boolean) .join(',') } export function buildResubmitPayload (input: { order: OrderLike values: ResubmitValues storefrontSlots: StorefrontSlot[] licenseImages: UploadedImage[] }) { const existingExtra = Object.entries(input.order.extra || {}).reduce>((result, [key, value]) => { if (!OMIT_EXTRA_KEYS.has(key)) { result[key] = value } return result }, {}) return { id: String(input.order.order_id || ''), corp_id: 0, entity_name: input.values.entity_name || input.order.entity_name || '', entity_phone: input.values.entity_phone || '', entity_extra: input.order.entity_extra || {}, extra: { ...existingExtra, entity_address_name: input.values.entity_address_name || '', entity_address: input.values.entity_address || '', entity_phone2: input.values.entity_phone2 || '', entity_storefront_image: joinStorefrontSlots(input.storefrontSlots), entity_business_license_image: joinUploadedImageIds(input.licenseImages), }, } }