mall数据库文件
This commit is contained in:
@@ -38,6 +38,7 @@
|
||||
</view>
|
||||
</view>
|
||||
<view class="header-actions">
|
||||
<button class="action-btn detail" @click="goToDataDetail">🔍 数据分析详情</button>
|
||||
<button class="action-btn export" @click="exportReport">📊 导出</button>
|
||||
<button class="action-btn refresh" @click="refreshReport">🔄 刷新</button>
|
||||
</view>
|
||||
@@ -202,7 +203,8 @@
|
||||
<script lang="uts">
|
||||
import AnalyticsSidebarMenu from '@/components/analytics/AnalyticsSidebarMenu.uvue'
|
||||
import AnalyticsTopBar from '@/components/analytics/AnalyticsTopBar.uvue'
|
||||
import supa from '@/components/supadb/aksupainstance.uts'
|
||||
import { fetchReport, fetchReportMetrics, fetchReportRows, fetchReportInsights, fetchRelatedReports } from '@/services/analytics/reportDetailService.uts'
|
||||
import { mapAnalyticsError } from '@/services/analytics/errorMapper.uts'
|
||||
|
||||
type ReportType = {
|
||||
id: string
|
||||
@@ -325,42 +327,15 @@ export default {
|
||||
uni.showLoading({ title: '加载中...' })
|
||||
|
||||
// 1. 加载报表主体
|
||||
const reportRes: any = await supa
|
||||
.from('analytics_reports')
|
||||
.select('id, title, type, period, generated_at, description')
|
||||
.eq('id', reportId)
|
||||
|
||||
const reportRows: Array<any> = Array.isArray(reportRes.data) ? (reportRes.data as Array<any>) : []
|
||||
if (reportRows.length === 0) {
|
||||
const report = await fetchReport(reportId)
|
||||
if (report == null) {
|
||||
uni.showToast({ title: '报表不存在', icon: 'none' })
|
||||
return
|
||||
}
|
||||
const r = reportRows[0]
|
||||
this.report = {
|
||||
id: `${r.id}`,
|
||||
title: `${r.title}`,
|
||||
type: `${r.type}`,
|
||||
period: `${r.period}`,
|
||||
generated_at: `${r.generated_at}`,
|
||||
description: `${r.description || ''}`
|
||||
}
|
||||
this.report = report
|
||||
|
||||
// 2. 加载核心指标
|
||||
const metricRes: any = await supa
|
||||
.from('analytics_report_metrics')
|
||||
.select('metric_key, metric_label, metric_value_num, format, icon, color, change_pct')
|
||||
.eq('report_id', reportId)
|
||||
|
||||
const metricRows: Array<any> = Array.isArray(metricRes.data) ? (metricRes.data as Array<any>) : []
|
||||
this.coreMetrics = metricRows.map((m: any) => ({
|
||||
key: `${m.metric_key}`,
|
||||
label: `${m.metric_label}`,
|
||||
value: this.safeNumber(m.metric_value_num),
|
||||
format: `${m.format || 'number'}`,
|
||||
icon: `${m.icon || '📊'}`,
|
||||
color: `${m.color || '#4caf50'}`,
|
||||
change: this.safeNumber(m.change_pct)
|
||||
}))
|
||||
this.coreMetrics = await fetchReportMetrics(reportId)
|
||||
|
||||
// 3. 配置表头与排序选项(固定结构)
|
||||
this.tableColumns = [
|
||||
@@ -374,55 +349,19 @@ export default {
|
||||
this.sortOptions = ['按日期降序', '按销售额降序', '按订单数降序', '按转化率降序']
|
||||
|
||||
// 4. 加载明细行(趋势/表格)
|
||||
const rowsRes: any = await supa
|
||||
.from('analytics_report_rows')
|
||||
.select('row_date, gmv, orders, users, conversion, avg_order_amount')
|
||||
.eq('report_id', reportId)
|
||||
.order('row_date', { ascending: true } as any)
|
||||
|
||||
const rows: Array<any> = Array.isArray(rowsRes.data) ? (rowsRes.data as Array<any>) : []
|
||||
this.allRows = rows
|
||||
this.allRows = await fetchReportRows(reportId)
|
||||
this.currentPage = 1
|
||||
this.updateTotalPages()
|
||||
this.generateTableData()
|
||||
|
||||
// 5. 加载洞察
|
||||
const insightRes: any = await supa
|
||||
.from('analytics_insights')
|
||||
.select('id, type, title, content, impact')
|
||||
.eq('report_id', reportId)
|
||||
.order('created_at', { ascending: false } as any)
|
||||
|
||||
const insRows: Array<any> = Array.isArray(insightRes.data) ? (insightRes.data as Array<any>) : []
|
||||
this.dataInsights = insRows.map((it: any) => ({
|
||||
id: `${it.id}`,
|
||||
type: `${it.type || 'info'}`,
|
||||
title: `${it.title}`,
|
||||
content: `${it.content}`,
|
||||
impact: `${it.impact || 'medium'}`
|
||||
}))
|
||||
this.dataInsights = await fetchReportInsights(reportId)
|
||||
|
||||
// 6. 相关报表(同类型最近报表)
|
||||
const relatedRes: any = await supa
|
||||
.from('analytics_reports')
|
||||
.select('id, title, type, period, generated_at, description')
|
||||
.eq('type', this.report.type)
|
||||
.neq('id', reportId)
|
||||
.order('generated_at', { ascending: false } as any)
|
||||
.limit(3 as any)
|
||||
|
||||
const relRows: Array<any> = Array.isArray(relatedRes.data) ? (relatedRes.data as Array<any>) : []
|
||||
this.relatedReports = relRows.map((it: any) => ({
|
||||
id: `${it.id}`,
|
||||
title: `${it.title}`,
|
||||
type: `${it.type}`,
|
||||
period: `${it.period}`,
|
||||
generated_at: `${it.generated_at}`,
|
||||
description: `${it.description || ''}`
|
||||
}))
|
||||
this.relatedReports = await fetchRelatedReports(this.report.type, reportId)
|
||||
} catch (e) {
|
||||
console.error('loadReportDetail failed', e)
|
||||
uni.showToast({ title: '报表加载失败', icon: 'none' })
|
||||
uni.showToast({ title: mapAnalyticsError(e, { fallbackMessage: '报表加载失败' }), icon: 'none' })
|
||||
} finally {
|
||||
uni.hideLoading()
|
||||
}
|
||||
@@ -584,6 +523,16 @@ export default {
|
||||
}, 1500)
|
||||
},
|
||||
|
||||
goToDataDetail() {
|
||||
if (!this.report.id || this.report.id.length === 0) {
|
||||
uni.showToast({ title: '报表未加载完成', icon: 'none' })
|
||||
return
|
||||
}
|
||||
uni.navigateTo({
|
||||
url: `/pages/mall/analytics/data-detail?reportId=${this.report.id}`
|
||||
})
|
||||
},
|
||||
|
||||
viewInsightDetail(insight: InsightType) {
|
||||
uni.navigateTo({
|
||||
url: `/pages/mall/analytics/insight-detail?insightId=${insight.id}`
|
||||
@@ -729,13 +678,20 @@ export default {
|
||||
gap: 15rpx;
|
||||
}
|
||||
|
||||
.action-btn.export, .action-btn.refresh {
|
||||
.action-btn.detail,
|
||||
.action-btn.export,
|
||||
.action-btn.refresh {
|
||||
padding: 15rpx 25rpx;
|
||||
border-radius: 8rpx;
|
||||
font-size: 24rpx;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.action-btn.detail {
|
||||
background-color: #111827;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.action-btn.export {
|
||||
background-color: #4caf50;
|
||||
color: #fff;
|
||||
|
||||
Reference in New Issue
Block a user