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

@@ -116,11 +116,11 @@
</template>
<script lang="uts">
import supa from '@/components/supadb/aksupainstance.uts'
import { ensureSupabaseReady } from '@/components/supadb/aksupainstance.uts'
import AnalyticsSidebarMenu from '@/components/analytics/AnalyticsSidebarMenu.uvue'
import AnalyticsTopBar from '@/components/analytics/AnalyticsTopBar.uvue'
import EChartsView from '@/uni_modules/charts/EChartsView.vue'
import { fetchDeliveryAnalysis } from '@/services/analytics/deliveryAnalysisService.uts'
import { mapAnalyticsError } from '@/services/analytics/errorMapper.uts'
type DeliveryData = {
avg_delivery_time: number
@@ -186,126 +186,9 @@ export default {
methods: {
async loadDeliveryData() {
try {
// 根据时间维度计算起始时间
const now = new Date()
const start = new Date(now.getTime())
if (this.selectedPeriod === '7d') start.setDate(start.getDate() - 7)
else if (this.selectedPeriod === '30d') start.setDate(start.getDate() - 30)
else if (this.selectedPeriod === '90d') start.setDate(start.getDate() - 90)
else if (this.selectedPeriod === '1y') start.setFullYear(start.getFullYear() - 1)
const startIso = start.toISOString()
await ensureSupabaseReady()
// 1) 查询周期内已送达任务(按 assigned_at 统计周期,口径:接单 assigned_at -> 送达 delivered_at
// 表结构来源doc_mall/database/complete_mall_database.sql
// 1) 趋势RPC数据库侧聚合
const endIso = now.toISOString()
// 优先走 RPC需要在 Supabase 执行 DELIVERY_ANALYSIS_RPCS.sql 创建函数)
let trendList: Array<UTSJSONObject> = []
let topList: Array<UTSJSONObject> = []
const trendRes = await supa.rpc('rpc_delivery_efficiency_daily', {
p_start: startIso,
p_end: endIso
})
if (trendRes.status === 404) {
// RPC 不存在:降级到直查表聚合(测试阶段兜底)
const taskRes = 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 })
.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>()
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() !== '') {
const c = driverAgg.get(driverId) ?? 0
driverAgg.set(driverId, c + 1)
}
}
const keys = Array.from(dayAgg.keys()).sort()
for (let i = 0; i < keys.length; i++) {
const k = keys[i]
const agg = dayAgg.get(k) as UTSJSONObject
const cnt = agg.getNumber('completed_orders') ?? 0
const sumMin = agg.getNumber('sum_minutes') ?? 0
const tFee = agg.getNumber('total_fee') ?? 0
const row = new UTSJSONObject()
row.set('day', k)
row.set('completed_orders', cnt)
row.set('avg_delivery_minutes', cnt > 0 ? (sumMin / cnt) : 0)
row.set('total_fee', tFee)
row.set('avg_fee', cnt > 0 ? (tFee / cnt) : 0)
trendList.push(row)
}
// TOP仅用 driverAgg 计算(姓名/评分未知,先兜底)
const ids = Array.from(driverAgg.keys()).sort((a, b) => (driverAgg.get(b) ?? 0) - (driverAgg.get(a) ?? 0))
const topN = Math.min(10, ids.length)
for (let i = 0; i < topN; i++) {
const id = ids[i]
const row = new UTSJSONObject()
row.set('driver_id', id)
row.set('driver_name', '未知')
row.set('orders', driverAgg.get(id) ?? 0)
row.set('rating_avg', 0)
topList.push(row)
}
} else {
if (trendRes.error != null) throw trendRes.error
const trendAny = (trendRes.data != null ? trendRes.data : []) as any
trendList = Array.isArray(trendAny) ? trendAny as Array<UTSJSONObject> : []
const topRes = await supa.rpc('rpc_delivery_efficiency_top_drivers', {
p_start: startIso,
p_end: endIso,
p_limit: 10
})
if (topRes.error != null) throw topRes.error
const topAny = (topRes.data != null ? topRes.data : []) as any
topList = Array.isArray(topAny) ? topAny as Array<UTSJSONObject> : []
}
const data = await fetchDeliveryAnalysis(this.selectedPeriod)
const trendList = data.trendList
const topList = data.topList
// 3) 转成页面内部 trendRows 格式
const trendRows: Array<UTSJSONObject> = []
@@ -397,7 +280,7 @@ export default {
console.error('loadDeliveryData failed:', e)
this.updateTime()
this.buildChartOptions()
uni.showToast({ title: '配送分析数据加载失败', icon: 'none' })
uni.showToast({ title: mapAnalyticsError(e, { fallbackMessage: '配送分析数据加载失败' }), icon: 'none' })
}
},