mall数据库文件

This commit is contained in:
comlibmb
2026-01-30 16:11:23 +08:00
parent b53d2376ff
commit cfec4a16c0
71 changed files with 11786 additions and 1009 deletions

View File

@@ -0,0 +1,132 @@
import supa, { ensureSupabaseReady } from '@/components/supadb/aksupainstance.uts'
import { computeDateRange } from './dateRange.uts'
export type DeliveryAnalysisData = {
trendList: Array<UTSJSONObject>
topList: Array<UTSJSONObject>
startIso: string
endIso: string
}
export async function fetchDeliveryAnalysis(period: string): Promise<DeliveryAnalysisData> {
const { startIso, endIso } = computeDateRange(period)
await ensureSupabaseReady()
// 优先走 RPC需要在 Supabase 执行 DELIVERY_ANALYSIS_RPCS.sql 创建函数)
let trendList: Array<UTSJSONObject> = []
let topList: Array<UTSJSONObject> = []
const trendRes: any = await supa.rpc('rpc_delivery_efficiency_daily', {
p_start: startIso,
p_end: endIso
} as UTSJSONObject)
if (trendRes.status === 404) {
// RPC 不存在:降级到直查表聚合(测试阶段兜底)
const taskRes: any = await supa
.from('ml_delivery_tasks')
.select('id,driver_id,assigned_at,delivered_at,delivery_fee', {})
.eq('status', 5)
.gte('assigned_at', startIso)
.order('assigned_at', { ascending: true } as any)
.execute()
if (taskRes?.error != null) throw taskRes.error
const rowsAny = (taskRes.data != null ? taskRes.data : []) as any
const tasks = Array.isArray(rowsAny) ? (rowsAny as Array<UTSJSONObject>) : []
const dayAgg = new Map<string, UTSJSONObject>()
const driverAgg = new Map<string, number>()
const driverFeeAgg = new Map<string, number>()
const driverTimeAgg = new Map<string, number>()
for (let i = 0; i < tasks.length; i++) {
const t = tasks[i]
const assignedAt = t.getString('assigned_at') ?? ''
const deliveredAt = t.getString('delivered_at') ?? ''
const driverId = t.getString('driver_id') ?? ''
if (assignedAt.trim() === '' || deliveredAt.trim() === '') continue
const day = assignedAt.length >= 10 ? assignedAt.substring(0, 10) : assignedAt
const a = new Date(assignedAt)
const d = new Date(deliveredAt)
const diffMin = Math.max(0, (d.getTime() - a.getTime()) / 60000)
const fee = t.getNumber('delivery_fee') ?? 0
const old = dayAgg.get(day)
if (old == null) {
const obj = new UTSJSONObject()
obj.set('day', day)
obj.set('completed_orders', 1)
obj.set('sum_minutes', diffMin)
obj.set('total_fee', fee)
dayAgg.set(day, obj)
} else {
old.set('completed_orders', (old.getNumber('completed_orders') ?? 0) + 1)
old.set('sum_minutes', (old.getNumber('sum_minutes') ?? 0) + diffMin)
old.set('total_fee', (old.getNumber('total_fee') ?? 0) + fee)
}
if (driverId.trim() !== '') {
driverAgg.set(driverId, (driverAgg.get(driverId) ?? 0) + 1)
driverFeeAgg.set(driverId, (driverFeeAgg.get(driverId) ?? 0) + fee)
driverTimeAgg.set(driverId, (driverTimeAgg.get(driverId) ?? 0) + diffMin)
}
}
// dayAgg -> trendList
const days = Array.from(dayAgg.keys()).sort()
for (let i = 0; i < days.length; i++) {
const day = days[i]
const obj = dayAgg.get(day)
if (obj != null) {
const completed = obj.getNumber('completed_orders') ?? 0
const sumMin = obj.getNumber('sum_minutes') ?? 0
const totalFee = obj.getNumber('total_fee') ?? 0
const out = new UTSJSONObject()
out.set('day', day)
out.set('avg_delivery_time', completed > 0 ? sumMin / completed : 0)
out.set('total_fee', totalFee)
out.set('completed_orders', completed)
trendList.push(out)
}
}
// driverAgg -> topList (Top10)
const drivers = Array.from(driverAgg.entries()).sort((a, b) => b[1] - a[1]).slice(0, 10)
for (let i = 0; i < drivers.length; i++) {
const [driverId, orders] = drivers[i]
const out = new UTSJSONObject()
out.set('driver_id', driverId)
out.set('orders', orders)
out.set('total_fee', driverFeeAgg.get(driverId) ?? 0)
out.set('total_minutes', driverTimeAgg.get(driverId) ?? 0)
topList.push(out)
}
} else if (trendRes.error != null) {
throw trendRes.error
} else {
const anyData = trendRes.data as any
trendList = Array.isArray(anyData) ? (anyData as Array<UTSJSONObject>) : []
// Top drivers
const topRes = await supa.rpc('rpc_delivery_efficiency_top_drivers', {
p_start: startIso,
p_end: endIso,
p_limit: 10
})
if (topRes.status === 404) {
console.warn('rpc_delivery_efficiency_top_drivers not found, top drivers will be empty')
} else if (topRes.error != null) {
throw topRes.error
} else {
const topAny = topRes.data as any
topList = Array.isArray(topAny) ? (topAny as Array<UTSJSONObject>) : []
}
}
return { trendList, topList, startIso, endIso }
}