数据分析ui补充完善,接入数据库
This commit is contained in:
@@ -76,19 +76,34 @@
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 时间维度:横排 -->
|
||||
<!-- 时间维度筛选(快捷 + 自定义) -->
|
||||
<view class="tabs">
|
||||
<view
|
||||
v-for="p in timePeriods"
|
||||
:key="p.value"
|
||||
class="tab"
|
||||
:class="{ active: selectedPeriod === p.value }"
|
||||
:class="{ active: selectedPeriod === p.value && !customRangeEnabled }"
|
||||
@click="selectPeriod(p.value)"
|
||||
>
|
||||
{{ p.label }}
|
||||
</view>
|
||||
<view
|
||||
class="tab"
|
||||
:class="{ active: customRangeEnabled }"
|
||||
@click="toggleCustomRange"
|
||||
>
|
||||
自定义
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<AnalyticsDateRangePicker
|
||||
v-if="customRangeEnabled"
|
||||
:initialStartDate="selectedStartDate"
|
||||
:initialEndDate="selectedEndDate"
|
||||
@apply="onDateRangeApply"
|
||||
@clear="onDateRangeClear"
|
||||
/>
|
||||
|
||||
<!-- 核心趋势:占满横向(柱+折 组合图) -->
|
||||
<view class="card card-full">
|
||||
<view class="card-head">
|
||||
@@ -252,10 +267,10 @@
|
||||
|
||||
<!-- 留白 -->
|
||||
<view style="height: 24px;"></view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="uts">
|
||||
@@ -264,6 +279,7 @@ import { computed, reactive, ref, watch } from 'vue'
|
||||
import AnalyticsComboChart from '@/components/analytics/AnalyticsComboChart.uvue'
|
||||
import AnalyticsSidebarMenu from '@/components/analytics/AnalyticsSidebarMenu.uvue'
|
||||
import AnalyticsTopBar from '@/components/analytics/AnalyticsTopBar.uvue'
|
||||
import AnalyticsDateRangePicker from '@/components/analytics/AnalyticsDateRangePicker.uvue'
|
||||
import EChartsView from '@/uni_modules/charts/EChartsView.vue'
|
||||
import { fetchDashboardRealtime, fetchDashboardTrend, fetchDashboardUserSegments, fetchDashboardTrafficSources, fetchDashboardTopProducts, fetchDashboardTopMerchants } from '@/services/analytics/dashboardService.uts'
|
||||
import { mapAnalyticsError } from '@/services/analytics/errorMapper.uts'
|
||||
@@ -271,6 +287,10 @@ import type { TrendData, SegmentItem, TrafficItem, TopProductItem, TopMerchantIt
|
||||
|
||||
const lastUpdateTime = ref('')
|
||||
const selectedPeriod = ref('7d')
|
||||
|
||||
const customRangeEnabled = ref(false)
|
||||
const selectedStartDate = ref('')
|
||||
const selectedEndDate = ref('')
|
||||
const showMoreMenu = ref(false)
|
||||
const showSidebarMenu = ref(false)
|
||||
const currentPath = ref('/pages/mall/analytics/index')
|
||||
@@ -333,7 +353,11 @@ function stopAutoRefresh() {
|
||||
|
||||
async function loadTrend() {
|
||||
try {
|
||||
const data = await fetchDashboardTrend(selectedPeriod.value)
|
||||
const range = selectedStartDate.value && selectedEndDate.value
|
||||
? { start: selectedStartDate.value, end: selectedEndDate.value }
|
||||
: null
|
||||
|
||||
const data = await fetchDashboardTrend(selectedPeriod.value, range)
|
||||
trend.x = data.x
|
||||
trend.gmv = data.gmv
|
||||
trend.orders = data.orders
|
||||
@@ -362,7 +386,10 @@ async function loadRealTime() {
|
||||
|
||||
async function loadTopProducts() {
|
||||
try {
|
||||
const list = await fetchDashboardTopProducts(selectedPeriod.value, 50)
|
||||
const range = selectedStartDate.value && selectedEndDate.value
|
||||
? { start: selectedStartDate.value, end: selectedEndDate.value }
|
||||
: null
|
||||
const list = await fetchDashboardTopProducts(selectedPeriod.value, 50, range)
|
||||
topProducts.splice(0, topProducts.length, ...list)
|
||||
} catch (e) {
|
||||
console.error('❌ loadTopProducts failed', e)
|
||||
@@ -372,7 +399,10 @@ async function loadTopProducts() {
|
||||
|
||||
async function loadTopMerchants() {
|
||||
try {
|
||||
const list = await fetchDashboardTopMerchants(selectedPeriod.value, 50)
|
||||
const range = selectedStartDate.value && selectedEndDate.value
|
||||
? { start: selectedStartDate.value, end: selectedEndDate.value }
|
||||
: null
|
||||
const list = await fetchDashboardTopMerchants(selectedPeriod.value, 50, range)
|
||||
topMerchants.splice(0, topMerchants.length, ...list)
|
||||
} catch (e) {
|
||||
console.error('❌ loadTopMerchants failed', e)
|
||||
@@ -382,7 +412,10 @@ async function loadTopMerchants() {
|
||||
|
||||
async function loadUserSegments() {
|
||||
try {
|
||||
const list = await fetchDashboardUserSegments(selectedPeriod.value)
|
||||
const range = selectedStartDate.value && selectedEndDate.value
|
||||
? { start: selectedStartDate.value, end: selectedEndDate.value }
|
||||
: null
|
||||
const list = await fetchDashboardUserSegments(selectedPeriod.value, range)
|
||||
userSegments.splice(0, userSegments.length, ...list)
|
||||
} catch (e) {
|
||||
console.error('❌ loadUserSegments failed', e)
|
||||
@@ -392,7 +425,10 @@ async function loadUserSegments() {
|
||||
|
||||
async function loadTrafficSources() {
|
||||
try {
|
||||
const list = await fetchDashboardTrafficSources(selectedPeriod.value)
|
||||
const range = selectedStartDate.value && selectedEndDate.value
|
||||
? { start: selectedStartDate.value, end: selectedEndDate.value }
|
||||
: null
|
||||
const list = await fetchDashboardTrafficSources(selectedPeriod.value, range)
|
||||
trafficSources.splice(0, trafficSources.length, ...list)
|
||||
} catch (e) {
|
||||
console.error('❌ loadTrafficSources failed', e)
|
||||
@@ -713,6 +749,24 @@ function handleSettings() {
|
||||
uni.showToast({ title: '设置', icon: 'none' })
|
||||
}
|
||||
|
||||
function toggleCustomRange() {
|
||||
customRangeEnabled.value = !customRangeEnabled.value
|
||||
}
|
||||
|
||||
function onDateRangeApply(range: { start: string; end: string }) {
|
||||
selectedStartDate.value = range.start
|
||||
selectedEndDate.value = range.end
|
||||
customRangeEnabled.value = true
|
||||
refreshAll()
|
||||
}
|
||||
|
||||
function onDateRangeClear() {
|
||||
selectedStartDate.value = ''
|
||||
selectedEndDate.value = ''
|
||||
customRangeEnabled.value = false
|
||||
refreshAll()
|
||||
}
|
||||
|
||||
function formatInt(n: number): string {
|
||||
const v = isFinite(n) ? Math.round(n) : 0
|
||||
if (v >= 10000) return (v / 10000).toFixed(1) + '万'
|
||||
|
||||
Reference in New Issue
Block a user