mall数据库文件
This commit is contained in:
@@ -149,11 +149,12 @@
|
||||
</template>
|
||||
|
||||
<script lang="uts">
|
||||
import supa from '@/components/supadb/aksupainstance.uts'
|
||||
import AnalyticsComboChart from '@/components/analytics/AnalyticsComboChart.uvue'
|
||||
import AnalyticsSidebarMenu from '@/components/analytics/AnalyticsSidebarMenu.uvue'
|
||||
import AnalyticsTopBar from '@/components/analytics/AnalyticsTopBar.uvue'
|
||||
import AnalyticsRegionMap from '@/components/analytics/AnalyticsRegionMap.uvue'
|
||||
import { fetchSalesKpis, fetchSalesTrend, fetchSalesTopProducts, fetchSalesTopMerchants } from '@/services/analytics/salesReportService.uts'
|
||||
import { mapAnalyticsError } from '@/services/analytics/errorMapper.uts'
|
||||
|
||||
type TrendData = { x: Array<string>; gmv: Array<number>; orders: Array<number> }
|
||||
type SalesData = {
|
||||
@@ -238,73 +239,16 @@ export default {
|
||||
this.loading = true
|
||||
try {
|
||||
this.updateTime()
|
||||
const now = new Date()
|
||||
const { startDate, endDate, days } = this.calcDateRange()
|
||||
const { startDate, endDate } = this.calcDateRange()
|
||||
|
||||
// 1) KPI:复用 realtime_kpis 的口径(GMV/订单/转化率),把窗口替换成“周期范围 vs 上一周期”
|
||||
const periodStart = new Date(startDate.getFullYear(), startDate.getMonth(), startDate.getDate())
|
||||
const periodEnd = new Date(endDate.getFullYear(), endDate.getMonth(), endDate.getDate() + 1) // 包含 endDate 当天
|
||||
const prevStart = new Date(periodStart.getTime() - days * 24 * 60 * 60 * 1000)
|
||||
const prevEnd = new Date(periodStart.getTime())
|
||||
// 1) KPI
|
||||
this.salesData = await fetchSalesKpis(this.selectedPeriod)
|
||||
|
||||
const pKpi = new UTSJSONObject()
|
||||
pKpi.set('p_start', periodStart.toISOString())
|
||||
pKpi.set('p_end', periodEnd.toISOString())
|
||||
pKpi.set('p_compare_start', prevStart.toISOString())
|
||||
pKpi.set('p_compare_end', prevEnd.toISOString())
|
||||
pKpi.set('p_merchant_id', null)
|
||||
|
||||
const kpiRes: any = await supa.rpc('rpc_analytics_realtime_kpis', pKpi)
|
||||
const row = Array.isArray(kpiRes.data) && kpiRes.data.length > 0 ? kpiRes.data[0] : (kpiRes.data || {})
|
||||
const safe = (v: any): number => {
|
||||
const n = Number(v)
|
||||
return isFinite(n) ? n : 0
|
||||
}
|
||||
const gmv = safe(row.gmv)
|
||||
const orders = safe(row.orders)
|
||||
const avgOrder = orders > 0 ? gmv / orders : 0
|
||||
this.salesData = {
|
||||
gmv: Math.round(gmv),
|
||||
gmv_growth: safe(row.gmv_growth),
|
||||
orders: Math.round(orders),
|
||||
order_growth: safe(row.order_growth),
|
||||
conversion_rate: safe(row.conversion_rate),
|
||||
conversion_growth: safe(row.conversion_growth),
|
||||
avg_order_amount: avgOrder,
|
||||
avg_order_growth: safe(row.gmv_growth) // 兜底:暂无独立口径,先跟随 GMV 增长
|
||||
}
|
||||
|
||||
// 2) 趋势(复用 trend_data)
|
||||
const pTrend = new UTSJSONObject()
|
||||
pTrend.set('p_start_date', startDate.toISOString().slice(0, 10))
|
||||
pTrend.set('p_end_date', endDate.toISOString().slice(0, 10))
|
||||
pTrend.set('p_merchant_id', null)
|
||||
const trendRes: any = await supa.rpc('rpc_analytics_trend_data', pTrend)
|
||||
const tRows: Array<any> = Array.isArray(trendRes.data) ? (trendRes.data as Array<any>) : []
|
||||
const x: Array<string> = []
|
||||
const gmvArr: Array<number> = []
|
||||
const orderArr: Array<number> = []
|
||||
for (let i = 0; i < tRows.length; i++) {
|
||||
const d = `${tRows[i].date}`
|
||||
x.push(d.slice(5))
|
||||
gmvArr.push(Number(tRows[i].gmv) || 0)
|
||||
orderArr.push(Number(tRows[i].orders) || 0)
|
||||
}
|
||||
this.trend = { x, gmv: gmvArr, orders: orderArr }
|
||||
// 2) 趋势
|
||||
this.trend = await fetchSalesTrend(this.selectedPeriod)
|
||||
|
||||
// 3) TOP 商品/商家
|
||||
const pTopP = new UTSJSONObject()
|
||||
pTopP.set('p_start_date', startDate.toISOString().slice(0, 10))
|
||||
pTopP.set('p_end_date', endDate.toISOString().slice(0, 10))
|
||||
pTopP.set('p_limit', 50)
|
||||
pTopP.set('p_merchant_id', null)
|
||||
const topPRes: any = await supa.rpc('rpc_analytics_top_products', pTopP)
|
||||
console.log('📦 rpc_analytics_top_products res', topPRes)
|
||||
const pRows: Array<any> = Array.isArray(topPRes.data) ? (topPRes.data as Array<any>) : []
|
||||
const pList: Array<ProductRank> = []
|
||||
for (let i = 0; i < pRows.length; i++) {
|
||||
pList.push({ id: `${pRows[i].id}`, rank: i + 1, name: `${pRows[i].name}`, sales: Number(pRows[i].sales) || 0 })
|
||||
}
|
||||
const pList = await fetchSalesTopProducts(this.selectedPeriod, 50)
|
||||
|
||||
// 不足 50 条时补齐虚拟数据(真实数据优先,虚拟数据追加)
|
||||
if (pList.length < 50) {
|
||||
@@ -329,22 +273,7 @@ export default {
|
||||
|
||||
this.topProducts = pList
|
||||
|
||||
const pTopM = new UTSJSONObject()
|
||||
pTopM.set('p_start_date', startDate.toISOString().slice(0, 10))
|
||||
pTopM.set('p_end_date', endDate.toISOString().slice(0, 10))
|
||||
pTopM.set('p_limit', 50)
|
||||
const topMRes: any = await supa.rpc('rpc_analytics_top_merchants', pTopM)
|
||||
const mRows: Array<any> = Array.isArray(topMRes.data) ? (topMRes.data as Array<any>) : []
|
||||
const mList: Array<MerchantRank> = []
|
||||
for (let i = 0; i < mRows.length; i++) {
|
||||
mList.push({
|
||||
id: `${mRows[i].id}`,
|
||||
rank: i + 1,
|
||||
name: `${mRows[i].name}`,
|
||||
sales: Number(mRows[i].sales) || 0,
|
||||
growth: Number(mRows[i].growth) || 0
|
||||
})
|
||||
}
|
||||
const mList: Array<MerchantRank> = await fetchSalesTopMerchants(this.selectedPeriod, 50)
|
||||
|
||||
// 不足 50 条时补齐虚拟数据(真实数据优先,虚拟数据追加)
|
||||
if (mList.length < 50) {
|
||||
@@ -372,7 +301,7 @@ export default {
|
||||
// 4) 地域分布:由 AnalyticsRegionMap 组件自动处理
|
||||
} catch (e) {
|
||||
console.error('❌ loadSalesData failed', e)
|
||||
uni.showToast({ title: '数据加载失败', icon: 'none', duration: 2000 })
|
||||
uni.showToast({ title: mapAnalyticsError(e, { fallbackMessage: '数据加载失败' }), icon: 'none', duration: 2000 })
|
||||
} finally {
|
||||
this.loading = false
|
||||
this.updateTime()
|
||||
|
||||
Reference in New Issue
Block a user