import { computeDateRange, toDateOnly } from './dateRange.uts' import { rpcOrEmptyArray, rpcOrNull } from './rpc.uts' export type TrendData = { x: Array; gmv: Array; orders: Array } export type SegmentItem = { name: string; value: number } export type TrafficItem = { name: string; value: number } export type TopProductItem = { id: string; rank: number; name: string; sales: number } export type TopMerchantItem = { id: string; rank: number; name: string; sales: number; growth: number } function safeNumber(v: any): number { const n = Number(v) return isFinite(n) ? n : 0 } export async function fetchDashboardTrend(period: string): Promise { const { startIso, endIso } = computeDateRange(period) const p_start_date = toDateOnly(startIso) const p_end_date = toDateOnly(endIso) const rows = await rpcOrEmptyArray('rpc_analytics_trend_data', { p_start_date, p_end_date, p_merchant_id: null } as any) const x: Array = [] const gmv: Array = [] const orders: Array = [] for (let i = 0; i < rows.length; i++) { const row: any = rows[i] const d = `${row.getString?.('date') ?? row.getString?.('day') ?? row.getString?.('date_key') ?? ''}` if (d && d.length >= 10) x.push(d.slice(5)) else x.push(`${i + 1}`) gmv.push(safeNumber(row.getAny?.('gmv') ?? row.getAny?.('total_amount') ?? 0)) orders.push(safeNumber(row.getAny?.('orders') ?? row.getAny?.('order_count') ?? 0)) } return { x, gmv, orders } } export async function fetchDashboardRealtime(): Promise { const now = new Date() const today0 = new Date(now.getFullYear(), now.getMonth(), now.getDate()) const todayISO = today0.toISOString() const ySame = new Date(now.getTime() - 24 * 60 * 60 * 1000) const y0 = new Date(ySame.getFullYear(), ySame.getMonth(), ySame.getDate()) const row = await rpcOrNull('rpc_analytics_realtime_kpis', { p_start: todayISO, p_end: now.toISOString(), p_compare_start: y0.toISOString(), p_compare_end: ySame.toISOString(), p_merchant_id: null } as any) const safe = (v: any): number => { const n = Number(v) return isFinite(n) ? n : 0 } const obj: any = row != null ? row : ({} as any) return { gmv: Math.round(safe(obj.getAny?.('gmv') ?? obj.getAny?.('total_gmv') ?? obj.getAny?.('revenue') ?? 0)), gmv_growth: safe(obj.getAny?.('gmv_growth') ?? obj.getAny?.('gmv_growth_rate') ?? obj.getAny?.('revenue_growth') ?? 0), orders: Math.round(safe(obj.getAny?.('orders') ?? obj.getAny?.('order_count') ?? obj.getAny?.('total_orders') ?? 0)), order_growth: safe(obj.getAny?.('order_growth') ?? obj.getAny?.('order_growth_rate') ?? 0), online_users: Math.round(safe(obj.getAny?.('online_users') ?? obj.getAny?.('active_users') ?? obj.getAny?.('current_users') ?? 0)), conversion_rate: safe(obj.getAny?.('conversion_rate') ?? obj.getAny?.('conversion') ?? 0), conversion_growth: safe(obj.getAny?.('conversion_growth') ?? obj.getAny?.('conversion_growth_rate') ?? 0) } } export async function fetchDashboardTopProducts(period: string, limit: number = 50): Promise> { const { startIso, endIso } = computeDateRange(period) const rows = await rpcOrEmptyArray('rpc_analytics_top_products', { p_start_date: toDateOnly(startIso), p_end_date: toDateOnly(endIso), p_limit: limit, p_merchant_id: null } as any) const list: Array = [] for (let i = 0; i < rows.length; i++) { const row: any = rows[i] list.push({ id: `${row.getAny?.('id') ?? i}`, rank: i + 1, name: `${row.getAny?.('name') ?? '未知商品'}`, sales: safeNumber(row.getAny?.('sales') ?? row.getAny?.('total_amount') ?? 0) }) } return list } export async function fetchDashboardTopMerchants(period: string, limit: number = 50): Promise> { const { startIso, endIso } = computeDateRange(period) const rows = await rpcOrEmptyArray('rpc_analytics_top_merchants', { p_start_date: toDateOnly(startIso), p_end_date: toDateOnly(endIso), p_limit: limit } as any) const list: Array = [] for (let i = 0; i < rows.length; i++) { const row: any = rows[i] list.push({ id: `${row.getAny?.('id') ?? i}`, rank: i + 1, name: `${row.getAny?.('name') ?? row.getAny?.('shop_name') ?? '未知商家'}`, sales: safeNumber(row.getAny?.('sales') ?? row.getAny?.('total_amount') ?? 0), growth: safeNumber(row.getAny?.('growth') ?? row.getAny?.('growth_rate') ?? 0) }) } return list } export async function fetchDashboardUserSegments(period: string): Promise> { const { startIso, endIso } = computeDateRange(period) const rows = await rpcOrEmptyArray('rpc_analytics_user_segments', { p_start_date: toDateOnly(startIso), p_end_date: toDateOnly(endIso) } as any) const list: Array = [] for (let i = 0; i < rows.length; i++) { const row: any = rows[i] list.push({ name: `${row.getAny?.('name') ?? row.getAny?.('segment_name') ?? row.getAny?.('label') ?? '未知'}`, value: safeNumber(row.getAny?.('value') ?? row.getAny?.('count') ?? row.getAny?.('amount') ?? 0) }) } return list } export async function fetchDashboardTrafficSources(period: string): Promise> { const { startIso, endIso } = computeDateRange(period) const rows = await rpcOrEmptyArray('rpc_analytics_traffic_sources', { p_start_date: toDateOnly(startIso), p_end_date: toDateOnly(endIso) } as any) const list: Array = [] for (let i = 0; i < rows.length; i++) { const row: any = rows[i] list.push({ name: `${row.getAny?.('name') ?? row.getAny?.('source_name') ?? row.getAny?.('label') ?? '未知'}`, value: safeNumber(row.getAny?.('value') ?? row.getAny?.('count') ?? row.getAny?.('amount') ?? 0) }) } return list }