This commit is contained in:
ylj20011123 2025-10-29 14:47:21 +08:00
parent 2900c384eb
commit 6e2bd12f8c
29 changed files with 1197 additions and 664 deletions

30
App.vue
View File

@ -10,21 +10,21 @@ export default {
...mapActions(["memberLogin", "getLoginCode"]), ...mapActions(["memberLogin", "getLoginCode"]),
...mapMutations(["setVisitChannels"]), ...mapMutations(["setVisitChannels"]),
handleGetUserInfo() { handleGetUserInfo() {
wx.request({ // wx.request({
url: "https://qifu-api.baidubce.com/ip/local/geo/v1/district", // url: "https://qifu-api.baidubce.com/ip/local/geo/v1/district",
success(response) { // success(response) {
const data = response.data; // const data = response.data;
// // //
let obj = { // let obj = {
...data.data, // ...data.data,
ip: data.ip, // ip: data.ip,
}; // };
uni.setStorageSync("userInfo", obj); // uni.setStorageSync("userInfo", obj);
}, // },
fail(error) { // fail(error) {
// // //
}, // },
}); // });
}, },
}, },
onLaunch: async function (options) { onLaunch: async function (options) {

View File

@ -3,7 +3,10 @@
<!-- 会员分析图表 --> <!-- 会员分析图表 -->
<view class="chart-card"> <view class="chart-card">
<view class="chart-container"> <view class="chart-container">
<QiunDataCharts type="column" :opts="chartOpts" :chartData="chartData" :canvas2d="true" <!-- 图表加载效果 -->
<ChartLoading v-if="!hasChartData" text="数据加载中..." />
<!-- 实际图表 -->
<QiunDataCharts v-else type="column" :opts="chartOpts" :chartData="chartData" :canvas2d="true"
:inScrollView="true" canvasId="analysisOfMemberChart" :animation="false" :ontap="true" :inScrollView="true" canvasId="analysisOfMemberChart" :animation="false" :ontap="true"
:ontouch="true" tooltipFormat="AnalysisOfMember" /> :ontouch="true" tooltipFormat="AnalysisOfMember" />
</view> </view>
@ -13,12 +16,14 @@
<script> <script>
import QiunDataCharts from './qiun-data-charts/components/qiun-data-charts/qiun-data-charts.vue' import QiunDataCharts from './qiun-data-charts/components/qiun-data-charts/qiun-data-charts.vue'
import ChartLoading from './ChartLoading.vue'
import request from "@/util/index.js"; import request from "@/util/index.js";
import moment from 'moment' import moment from 'moment'
export default { export default {
components: { components: {
QiunDataCharts QiunDataCharts,
ChartLoading
}, },
data() { data() {
@ -34,6 +39,13 @@ export default {
}, },
computed: { computed: {
//
hasChartData() {
return this.rawData.category.length > 0 &&
this.rawData.weeklyData.length > 0 &&
this.rawData.otherData.length > 0
},
// //
chartData() { chartData() {
return { return {
@ -56,7 +68,7 @@ export default {
// //
chartOpts() { chartOpts() {
return { return {
padding: [15, 15, 15, 15], padding: [15, 15, 0, 15],
dataLabel: false, dataLabel: false,
enableScroll: true, enableScroll: true,
dataPointShape: false, dataPointShape: false,
@ -65,14 +77,15 @@ export default {
itemCount: 4 // 4 itemCount: 4 // 4
}, },
yAxis: { yAxis: {
showTitle: true,
titleFontSize: 12,
titleOffsetY: 10,
titleOffsetX: 10,
min: 0,
data: [{ data: [{
min: 0, min: 0,
max: 100, max: 100,
title: '百分比(%)', title: '百分比(%)',
titleFontSize: 12,
titleOffsetY: 0,
unit: '%',
format: 'value' //
}] }]
}, },
legend: { legend: {

View File

@ -7,21 +7,26 @@
<!-- 品牌消费水平图表 --> <!-- 品牌消费水平图表 -->
<view class="chart-container"> <view class="chart-container">
<QiunDataCharts type="column" :opts="chartOpts" :chartData="chartData" :canvas2d="true" :inScrollView="true" <!-- 图表加载效果 -->
canvasId="brandConsumptionLevelChart" :animation="false" :ontap="true" :ontouch="true" <ChartLoading v-if="!hasChartData" text="数据加载中..." />
tooltipFormat="BrandConsumptionLevel" /> <!-- 实际图表 -->
<QiunDataCharts v-else type="column" :opts="chartOpts" :chartData="chartData" :canvas2d="true"
:inScrollView="true" canvasId="brandConsumptionLevelChart" :animation="false" :ontap="true"
:ontouch="true" tooltipFormat="BrandConsumptionLevel" />
</view> </view>
</view> </view>
</template> </template>
<script> <script>
import QiunDataCharts from './qiun-data-charts/components/qiun-data-charts/qiun-data-charts.vue' import QiunDataCharts from './qiun-data-charts/components/qiun-data-charts/qiun-data-charts.vue'
import ChartLoading from './ChartLoading.vue'
import request from "@/util/index.js"; import request from "@/util/index.js";
import moment from 'moment' import moment from 'moment'
export default { export default {
components: { components: {
QiunDataCharts QiunDataCharts,
ChartLoading
}, },
data() { data() {
@ -33,8 +38,19 @@ export default {
} }
} }
}, },
props: {
selectTime: {
type: String,
default: ""
},
},
computed: { computed: {
//
hasChartData() {
return this.rawData.category.length > 0 &&
this.rawData.seriesData.length > 0
},
// //
chartData() { chartData() {
return { return {
@ -46,7 +62,7 @@ export default {
// //
chartOpts() { chartOpts() {
return { return {
padding: [15, 15, 15, 15], padding: [15, 15, 0, 15],
dataLabel: false, dataLabel: false,
enableScroll: true, enableScroll: true,
xAxis: { xAxis: {
@ -54,9 +70,13 @@ export default {
itemCount: 4, itemCount: 4,
}, },
yAxis: { yAxis: {
showTitle: true,
data: [{ data: [{
min: 0, min: 0,
title: '%' title: '百分比(%)',
titleFontSize: 12,
titleOffsetY: -5,
titleOffsetX: 0,
}] }]
}, },
legend: { legend: {
@ -95,7 +115,7 @@ export default {
async handleGetBrandConsumptionLevelData() { async handleGetBrandConsumptionLevelData() {
const req = { const req = {
ProvinceCode: '530000', ProvinceCode: '530000',
StatisticsDate: moment().subtract(1, 'd').subtract(1, 'M').format('YYYY-MM-DD'), StatisticsDate: this.selectTime ? moment(this.selectTime).subtract(1, 'd').subtract(1, 'M').format('YYYY-MM-DD') : moment().subtract(1, 'd').subtract(1, 'M').format('YYYY-MM-DD'),
// ServerpartId: '' // ServerpartId: ''
} }

View File

@ -8,7 +8,10 @@
<!-- 图表容器 --> <!-- 图表容器 -->
<view class="chart-container"> <view class="chart-container">
<QiunDataCharts type="pie" :opts="chartOpts" :chartData="chartData" :canvas2d="true" <!-- 图表加载效果 -->
<ChartLoading v-if="!hasChartData" text="数据加载中..." />
<!-- 实际图表 -->
<QiunDataCharts v-else type="pie" :opts="chartOpts" :chartData="chartData" :canvas2d="true"
:inScrollView="true" canvasId="brandChart" :animation="false" :ontap="true" :ontouch="true" :inScrollView="true" canvasId="brandChart" :animation="false" :ontap="true" :ontouch="true"
tooltipFormat="BrandDetail" /> tooltipFormat="BrandDetail" />
</view> </view>
@ -30,22 +33,27 @@
<!-- 品牌列表容器 --> <!-- 品牌列表容器 -->
<view class="brand-list-box"> <view class="brand-list-box">
<view class="brand-item" v-for="(item, index) in brandListData" :key="index" <!-- 品牌列表加载效果 -->
:style="{ marginBottom: index + 1 === brandListData.length ? '0' : '20rpx' }"> <ChartLoading v-if="!hasBrandListData" text="数据加载中..." />
<view class=" brand-left"> <!-- 品牌列表内容 -->
<image class="brand-icon" :src="item.BRAND_INTRO || defaultImg" mode="aspectFill" /> <view v-else>
</view> <view class="brand-item" v-for="(item, index) in brandListData" :key="index"
:style="{ marginBottom: index + 1 === brandListData.length ? '0' : '20rpx' }">
<view class="brand-right"> <view class=" brand-left">
<view class="brand-right-top"> <image class="brand-icon" :src="item.BRAND_INTRO || defaultImg" mode="aspectFill" />
<view class="brand-right-top-left">{{ item.BRAND_NAME }}</view>
<view class="brand-right-top-right">
<!-- 原组件中的服务区数量显示已被注释 -->
</view>
</view> </view>
<view class="brand-right-bottom"> <view class="brand-right">
<view class="brand-right-bottom-item">{{ item.BRAND_TYPENAME }}</view> <view class="brand-right-top">
<view class="brand-right-top-left">{{ item.BRAND_NAME }}</view>
<view class="brand-right-top-right">
<!-- 原组件中的服务区数量显示已被注释 -->
</view>
</view>
<view class="brand-right-bottom">
<view class="brand-right-bottom-item">{{ item.BRAND_TYPENAME }}</view>
</view>
</view> </view>
</view> </view>
</view> </view>
@ -56,13 +64,15 @@
<script> <script>
import QiunDataCharts from './qiun-data-charts/components/qiun-data-charts/qiun-data-charts.vue' import QiunDataCharts from './qiun-data-charts/components/qiun-data-charts/qiun-data-charts.vue'
import ChartLoading from './ChartLoading.vue'
import request from "@/util/index.js"; import request from "@/util/index.js";
import moment from 'moment' import moment from 'moment'
import { wrapTreeNode } from "@/util/dateTime"; import { wrapTreeNode } from "@/util/dateTime";
export default { export default {
components: { components: {
QiunDataCharts QiunDataCharts,
ChartLoading
}, },
data() { data() {
@ -88,6 +98,16 @@ export default {
}, },
computed: { computed: {
//
hasChartData() {
return this.rawData.pieData.length > 0
},
//
hasBrandListData() {
return this.brandListData && this.brandListData.length > 0;
},
// //
chartData() { chartData() {
return { return {
@ -100,36 +120,23 @@ export default {
// //
chartOpts() { chartOpts() {
return { return {
padding: [15, 15, 15, 15], padding: [15, 15, 0, 15],
dataLabel: false, dataLabel: false,
legend: { legend: {
show: true, show: true,
position: 'right', position: 'right',
float: 'center', float: 'center',
backgroundColor: 'rgba(0,0,0,0)',
borderColor: 'rgba(0,0,0,0)',
fontSize: 12, fontSize: 12,
fontColor: '#333333', fontColor: '#333333',
margin: 0,
padding: 0,
itemGap: 10,
textAlign: 'left',
//
formatter: function (name) {
// QiunDataChartsformatter
return name
}
}, },
extra: { extra: {
pie: { pie: {
activeOpacity: 0.5,
activeRadius: 10, activeRadius: 10,
offsetAngle: 0, offsetAngle: 0,
labelWidth: 0, labelWidth: 0,
border: false, border: false,
borderWidth: 2, borderWidth: 2,
borderColor: '#FFFFFF', borderColor: '#FFFFFF',
linearType: 'custom'
} }
} }
} }
@ -358,6 +365,8 @@ export default {
border-radius: 16rpx; border-radius: 16rpx;
padding: 24rpx; padding: 24rpx;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08); box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
min-height: 300rpx;
/* 设置最小高度以显示加载效果 */
.brand-item { .brand-item {
display: flex; display: flex;

View File

@ -20,8 +20,10 @@
<view style="width:100%;height: 400rpx;"> <view style="width:100%;height: 400rpx;">
<!-- 图表 --> <!-- 图表加载效果 -->
<QiunDataCharts type="column" :opts="chartOpts" :chartData="chartData" :canvas2d="true" <ChartLoading v-if="!hasChartData" text="数据加载中..." />
<!-- 实际图表 -->
<QiunDataCharts v-else type="column" :opts="chartOpts" :chartData="chartData" :canvas2d="true"
:inScrollView="true" canvasId="businessCaseChart" :animation="false" :ontap="true" :ontouch="true" :inScrollView="true" canvasId="businessCaseChart" :animation="false" :ontap="true" :ontouch="true"
tooltipFormat="businessCaseChart" /> tooltipFormat="businessCaseChart" />
</view> </view>
@ -32,12 +34,14 @@
<script> <script>
import QiunDataCharts from './qiun-data-charts/components/qiun-data-charts/qiun-data-charts.vue' import QiunDataCharts from './qiun-data-charts/components/qiun-data-charts/qiun-data-charts.vue'
import ChartLoading from './ChartLoading.vue'
import request from "@/util/index.js"; import request from "@/util/index.js";
import moment from 'moment' import moment from 'moment'
export default { export default {
components: { components: {
QiunDataCharts QiunDataCharts,
ChartLoading
}, },
data() { data() {
@ -60,8 +64,19 @@ export default {
} }
} }
}, },
props: {
selectTime: {
type: String,
default: ""
},
},
computed: { computed: {
//
hasChartData() {
return this.rawData.category.length > 0 &&
this.rawData.seriesData.length > 0
},
// //
chartData() { chartData() {
return { return {
@ -73,7 +88,7 @@ export default {
// //
chartOpts() { chartOpts() {
return { return {
padding: [15, 15, 15, 15], // paddingpicker padding: [15, 15, 0, 15], // paddingpicker
dataLabel: false, dataLabel: false,
enableScroll: true, enableScroll: true,
xAxis: { xAxis: {
@ -81,9 +96,13 @@ export default {
itemCount: 4, itemCount: 4,
}, },
yAxis: { yAxis: {
showTitle: true,
data: [{ data: [{
min: 0, min: 0,
title: this.getYAxisTitle() title: this.getYAxisTitle(),
titleFontSize: 12,
titleOffsetY: -5,
titleOffsetX: 10,
}] }]
}, },
legend: { legend: {
@ -108,7 +127,8 @@ export default {
seriesGap: 0, seriesGap: 0,
barBorderRadius: [3, 3, 0, 0] barBorderRadius: [3, 3, 0, 0]
} }
} },
unitType: this.selectTab
} }
} }
}, },
@ -122,7 +142,7 @@ export default {
async handleGetBusinessCaseData() { async handleGetBusinessCaseData() {
const req = { const req = {
ProvinceCode: "530000", ProvinceCode: "530000",
StatisticsDate: moment().subtract(1, 'd').format('YYYY-MM-DD'), StatisticsDate: this.selectTime ? moment(this.selectTime).subtract(1, 'd').format('YYYY-MM-DD') : moment().subtract(1, 'd').format('YYYY-MM-DD'),
ServerpartId: "", // ID ServerpartId: "", // ID
} }

View File

@ -7,8 +7,11 @@
<!-- 业态结构占比图表 --> <!-- 业态结构占比图表 -->
<view class="chart-container"> <view class="chart-container">
<QiunDataCharts type="pie" :opts="chartOpts" :chartData="chartData" :canvas2d="true" :inScrollView="true" <!-- 图表加载效果 -->
canvasId="businessStructureChart" :animation="false" :ontap="true" :ontouch="true" <ChartLoading v-if="!hasChartData" text="数据加载中..." />
<!-- 实际图表 -->
<QiunDataCharts v-else type="pie" :opts="chartOpts" :chartData="chartData" :canvas2d="true"
:inScrollView="true" canvasId="businessStructureChart" :animation="false" :ontap="true" :ontouch="true"
tooltipFormat="businessStructureChart" /> tooltipFormat="businessStructureChart" />
</view> </view>
</view> </view>
@ -16,14 +19,21 @@
<script> <script>
import QiunDataCharts from './qiun-data-charts/components/qiun-data-charts/qiun-data-charts.vue' import QiunDataCharts from './qiun-data-charts/components/qiun-data-charts/qiun-data-charts.vue'
import ChartLoading from './ChartLoading.vue'
import request from "@/util/index.js"; import request from "@/util/index.js";
import moment from 'moment' import moment from 'moment'
export default { export default {
components: { components: {
QiunDataCharts QiunDataCharts,
ChartLoading
},
props: {
selectTime: {
type: String,
default: ""
},
}, },
data() { data() {
return { return {
// //
@ -35,6 +45,11 @@ export default {
}, },
computed: { computed: {
//
hasChartData() {
return this.rawData.seriesData.length > 0
},
// //
chartData() { chartData() {
return { return {
@ -47,34 +62,28 @@ export default {
// //
chartOpts() { chartOpts() {
return { return {
padding: [15, 15, 15, 15], padding: [15, 62, 0, 15],
dataLabel: false, dataLabel: false,
legend: { legend: {
show: true, show: true,
position: 'right', position: 'right',
float: 'center', float: 'center',
backgroundColor: 'rgba(0,0,0,0)',
borderColor: 'rgba(0,0,0,0)',
fontSize: 12, fontSize: 12,
fontColor: '#333333', fontColor: '#333333',
margin: 0,
padding: 0,
itemGap: 10,
textAlign: 'left' textAlign: 'left'
}, },
extra: { extra: {
pie: { pie: {
activeOpacity: 0.5,
activeRadius: 10, activeRadius: 10,
offsetAngle: 0, offsetAngle: 0,
labelWidth: 0, labelWidth: 0,
border: false, border: false,
borderWidth: 2, borderWidth: 2,
borderColor: '#FFFFFF', borderColor: '#FFFFFF',
linearType: 'custom'
} }
}, },
realData: this.rawData.seriesData realData: this.rawData.seriesData,
legendData: this.rawData.legendData
} }
} }
}, },
@ -88,7 +97,7 @@ export default {
async handleGetBusinessStructureData() { async handleGetBusinessStructureData() {
const req = { const req = {
ProvinceCode: '530000', ProvinceCode: '530000',
StatisticsDate: moment().subtract(1, 'd').format('YYYY-MM-DD'), StatisticsDate: this.selectTime ? moment(this.selectTime).subtract(1, 'd').format('YYYY-MM-DD') : moment().subtract(1, 'd').format('YYYY-MM-DD'),
BusinessTradeIds: -1, BusinessTradeIds: -1,
ServerpartId: "" // ID ServerpartId: "" // ID
} }

View File

@ -0,0 +1,118 @@
<template>
<view class="chart-loading">
<view class="loading-container">
<!-- 加载动画图标 -->
<view class="loading-icon">
<view class="loading-dot dot1"></view>
<view class="loading-dot dot2"></view>
<view class="loading-dot dot3"></view>
</view>
<!-- 加载文字 -->
<view class="loading-text">{{ text }}</view>
</view>
</view>
</template>
<script>
export default {
name: 'ChartLoading',
props: {
//
text: {
type: String,
default: '数据加载中...'
},
//
size: {
type: String,
default: 'medium' // small, medium, large
},
//
transparent: {
type: Boolean,
default: false
}
}
}
</script>
<style scoped lang="less">
.chart-loading {
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
background: #fff;
border-radius: 8rpx;
min-height: 300rpx;
&.transparent {
background: transparent;
}
}
.loading-container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 20rpx;
}
.loading-icon {
display: flex;
align-items: center;
justify-content: center;
gap: 8rpx;
&.small {
transform: scale(0.8);
}
&.large {
transform: scale(1.2);
}
}
.loading-dot {
width: 12rpx;
height: 12rpx;
border-radius: 50%;
background: linear-gradient(45deg, #46B8F3, #1A4AF6);
animation: loading-bounce 1.4s ease-in-out infinite both;
&.dot1 {
animation-delay: -0.32s;
}
&.dot2 {
animation-delay: -0.16s;
}
&.dot3 {
animation-delay: 0;
}
}
.loading-text {
font-size: 24rpx;
color: #666;
opacity: 0.8;
}
@keyframes loading-bounce {
0%,
80%,
100% {
transform: scale(0);
opacity: 0.5;
}
40% {
transform: scale(1);
opacity: 1;
}
}
</style>

View File

@ -7,21 +7,26 @@
<!-- 消费转化对比图图表 --> <!-- 消费转化对比图图表 -->
<view class="chart-container"> <view class="chart-container">
<QiunDataCharts type="line" :opts="chartOpts" :chartData="chartData" :canvas2d="true" :inScrollView="true" <!-- 图表加载效果 -->
canvasId="consumptionConversionChart" :animation="false" :ontap="true" :ontouch="true" <ChartLoading v-if="!hasChartData" text="数据加载中..." />
tooltipFormat="ConsumptionConversion" /> <!-- 实际图表 -->
<QiunDataCharts v-else type="line" :opts="chartOpts" :chartData="chartData" :canvas2d="true"
:inScrollView="true" canvasId="consumptionConversionChart" :animation="false" :ontap="true"
:ontouch="true" tooltipFormat="ConsumptionConversion" />
</view> </view>
</view> </view>
</template> </template>
<script> <script>
import QiunDataCharts from './qiun-data-charts/components/qiun-data-charts/qiun-data-charts.vue' import QiunDataCharts from './qiun-data-charts/components/qiun-data-charts/qiun-data-charts.vue'
import ChartLoading from './ChartLoading.vue'
import request from "@/util/index.js"; import request from "@/util/index.js";
import moment from 'moment' import moment from 'moment'
export default { export default {
components: { components: {
QiunDataCharts QiunDataCharts,
ChartLoading
}, },
data() { data() {
@ -38,6 +43,13 @@ export default {
}, },
computed: { computed: {
//
hasChartData() {
return this.rawData.category.length > 0 &&
this.rawData.carResList.length > 0 &&
this.rawData.orderResList.length > 0
},
// //
chartData() { chartData() {
return { return {
@ -58,27 +70,28 @@ export default {
// //
chartOpts() { chartOpts() {
return { return {
padding: [15, 15, 15, 15], padding: [15, 15, 0, 15],
dataLabel: false, dataLabel: false,
enableScroll: true, enableScroll: false, //
dataPointShape: true, dataPointShape: true,
xAxis: { xAxis: {
disableGrid: true, disableGrid: true,
itemCount: 8, // itemCount: this.rawData.category.length || 7, //
}, },
yAxis: { yAxis: {
showTitle: true,
data: [ data: [
{ {
title: '车流量(辆)', title: '车流量(辆)',
titleFontSize: 12, titleFontSize: 12,
titleOffsetY: 0, titleOffsetY: -5,
titleOffsetX: 0, titleOffsetX: 0,
position: 'left' position: 'left'
}, },
{ {
title: '客单量(笔)', title: '客单量(笔)',
titleFontSize: 12, titleFontSize: 12,
titleOffsetY: 0, titleOffsetY: -5,
titleOffsetX: 0, titleOffsetX: 0,
position: 'right' position: 'right'
} }
@ -124,7 +137,7 @@ export default {
async handleGetConsumptionConversionData() { async handleGetConsumptionConversionData() {
const req = { const req = {
Province_Code: '530000', Province_Code: '530000',
Statistics_Date: moment().subtract(1, 'd').subtract(1, 'M').format('YYYY-MM-DD'), Statistics_Date: this.selectTime ? moment(this.selectTime).subtract(1, 'd').subtract(1, 'M').format('YYYY-MM-DD') : moment().subtract(1, 'd').subtract(1, 'M').format('YYYY-MM-DD'),
Serverpart_ID: "" // ID Serverpart_ID: "" // ID
} }
@ -151,25 +164,66 @@ export default {
let orderResList = [] let orderResList = []
let orderRealResList = [] let orderRealResList = []
// //
let carDataMap = {}
let orderDataMap = {}
let availableHours = new Set()
//
if (data.BayonetList && data.BayonetList.data && data.BayonetList.data.length > 0) { if (data.BayonetList && data.BayonetList.data && data.BayonetList.data.length > 0) {
let carList = data.BayonetList.data let carList = data.BayonetList.data
carList.forEach((item) => { carList.forEach((item) => {
carResList.push(Number(item[1])) const hour = parseInt(item[0])
carRealResList.push(item[1]) carDataMap[hour] = Number(item[1])
availableHours.add(hour)
}) })
} }
// //
if (data.TransactionList && data.TransactionList.data && data.TransactionList.data.length > 0) { if (data.TransactionList && data.TransactionList.data && data.TransactionList.data.length > 0) {
let orderList = data.TransactionList.data let orderList = data.TransactionList.data
orderList.forEach((item) => { orderList.forEach((item) => {
category.push(`${item[0]}`) const hour = parseInt(item[0])
orderResList.push(Number(item[1])) orderDataMap[hour] = Number(item[1])
orderRealResList.push(item[1]) availableHours.add(hour)
}) })
} }
// Set
let sortedHours = Array.from(availableHours).sort((a, b) => a - b)
//
let selectedHours = []
// 1. 448121620
sortedHours.forEach(hour => {
if (hour % 4 === 0) {
selectedHours.push(hour)
}
})
// 2. 023
if (availableHours.has(0) && !selectedHours.includes(0)) {
selectedHours.unshift(0) // 0
}
if (availableHours.has(23) && !selectedHours.includes(23)) {
selectedHours.push(23) // 23
}
// 3. 使7
if (selectedHours.length === 0) {
selectedHours = [0, 4, 8, 12, 16, 20, 23]
}
//
selectedHours.forEach(hour => {
category.push(`${hour}`)
carResList.push(carDataMap[hour] || 0)
carRealResList.push(carDataMap[hour] || 0)
orderResList.push(orderDataMap[hour] || 0)
orderRealResList.push(orderDataMap[hour] || 0)
})
// //
this.rawData = { this.rawData = {
category: category, category: category,

View File

@ -8,8 +8,11 @@
<!-- 消费水平图表 --> <!-- 消费水平图表 -->
<view class="chart-container"> <view class="chart-container">
<QiunDataCharts type="column" :opts="chartOpts" :chartData="chartData" :canvas2d="true" :inScrollView="true" <!-- 图表加载效果 -->
canvasId="consumptionLevelChart" :animation="false" :ontap="true" :ontouch="true" <ChartLoading v-if="!hasChartData" text="数据加载中..." />
<!-- 实际图表 -->
<QiunDataCharts v-else type="column" :opts="chartOpts" :chartData="chartData" :canvas2d="true"
:inScrollView="true" canvasId="consumptionLevelChart" :animation="false" :ontap="true" :ontouch="true"
tooltipFormat="ConsumptionLevel" /> tooltipFormat="ConsumptionLevel" />
</view> </view>
</view> </view>
@ -17,12 +20,14 @@
<script> <script>
import QiunDataCharts from './qiun-data-charts/components/qiun-data-charts/qiun-data-charts.vue' import QiunDataCharts from './qiun-data-charts/components/qiun-data-charts/qiun-data-charts.vue'
import ChartLoading from './ChartLoading.vue'
import request from "@/util/index.js"; import request from "@/util/index.js";
import moment from 'moment' import moment from 'moment'
export default { export default {
components: { components: {
QiunDataCharts QiunDataCharts,
ChartLoading
}, },
data() { data() {
@ -34,8 +39,19 @@ export default {
} }
} }
}, },
props: {
selectTime: {
type: String,
default: ""
},
},
computed: { computed: {
//
hasChartData() {
return this.rawData.category.length > 0 &&
this.rawData.seriesData.length > 0
},
// //
chartData() { chartData() {
return { return {
@ -47,7 +63,7 @@ export default {
// //
chartOpts() { chartOpts() {
return { return {
padding: [15, 15, 15, 15], padding: [15, 15, 0, 15],
dataLabel: false, dataLabel: false,
enableScroll: true, enableScroll: true,
xAxis: { xAxis: {
@ -56,9 +72,13 @@ export default {
margin: 15 margin: 15
}, },
yAxis: { yAxis: {
showTitle: true,
data: [{ data: [{
min: 0, min: 0,
title: '%' title: '百分比(%)',
titleFontSize: 12,
titleOffsetY: -5,
titleOffsetX: 0,
}] }]
}, },
legend: { legend: {
@ -97,7 +117,7 @@ export default {
async handleGetConsumptionLevelData() { async handleGetConsumptionLevelData() {
const req = { const req = {
ProvinceCode: '530000', ProvinceCode: '530000',
StatisticsDate: moment().subtract(1, 'd').subtract(1, 'M').format('YYYY-MM-DD'), StatisticsDate: this.selectTime ? moment(this.selectTime).subtract(1, 'd').subtract(1, 'M').format('YYYY-MM-DD') : moment().subtract(1, 'd').subtract(1, 'M').format('YYYY-MM-DD'),
// ServerpartId: '' // ServerpartId: ''
} }

View File

@ -7,8 +7,11 @@
<!-- 消费时段分析图表 --> <!-- 消费时段分析图表 -->
<view class="chart-container"> <view class="chart-container">
<QiunDataCharts type="line" :opts="chartOpts" :chartData="chartData" :canvas2d="true" :inScrollView="true" <!-- 图表加载效果 -->
canvasId="consumptionPeriodChart" :animation="false" :ontap="true" :ontouch="true" <ChartLoading v-if="!hasChartData" text="数据加载中..." />
<!-- 实际图表 -->
<QiunDataCharts v-else type="line" :opts="chartOpts" :chartData="chartData" :canvas2d="true"
:inScrollView="true" canvasId="consumptionPeriodChart" :animation="false" :ontap="true" :ontouch="true"
tooltipFormat="ConsumptionPeriod" /> tooltipFormat="ConsumptionPeriod" />
</view> </view>
</view> </view>
@ -16,12 +19,14 @@
<script> <script>
import QiunDataCharts from './qiun-data-charts/components/qiun-data-charts/qiun-data-charts.vue' import QiunDataCharts from './qiun-data-charts/components/qiun-data-charts/qiun-data-charts.vue'
import ChartLoading from './ChartLoading.vue'
import request from "@/util/index.js"; import request from "@/util/index.js";
import moment from 'moment' import moment from 'moment'
export default { export default {
components: { components: {
QiunDataCharts QiunDataCharts,
ChartLoading
}, },
data() { data() {
@ -33,8 +38,19 @@ export default {
} }
} }
}, },
props: {
selectTime: {
type: String,
default: ""
},
},
computed: { computed: {
//
hasChartData() {
return this.rawData.category.length > 0 &&
this.rawData.seriesData.length > 0
},
// //
chartData() { chartData() {
return { return {
@ -51,20 +67,21 @@ export default {
// //
chartOpts() { chartOpts() {
return { return {
padding: [15, 15, 15, 15], padding: [15, 15, 0, 15],
dataLabel: false, dataLabel: false,
enableScroll: true, enableScroll: false, //
dataPointShape: true, dataPointShape: true,
xAxis: { xAxis: {
disableGrid: true, disableGrid: true,
itemCount: 6, itemCount: this.rawData.category.length || 6, //
}, },
yAxis: { yAxis: {
showTitle: true,
data: [{ data: [{
min: 0, min: 0,
title: '客单占比(%)', title: '客单占比(%)',
titleFontSize: 12, titleFontSize: 12,
titleOffsetY: 0, titleOffsetY: -5,
titleOffsetX: 0 titleOffsetX: 0
}] }]
}, },
@ -108,7 +125,7 @@ export default {
async handleGetConsumptionPeriodData() { async handleGetConsumptionPeriodData() {
const req = { const req = {
Province_Code: '530000', Province_Code: '530000',
Statistics_Date: moment().subtract(1, 'd').subtract(1, 'M').format('YYYY-MM-DD'), Statistics_Date: this.selectTime ? moment(this.selectTime).subtract(1, 'd').subtract(1, 'M').format('YYYY-MM-DD') : moment().subtract(1, 'd').subtract(1, 'M').format('YYYY-MM-DD'),
Serverpart_ID: '', Serverpart_ID: '',
TimeSpan: 1 TimeSpan: 1
} }
@ -132,6 +149,8 @@ export default {
processChartData(data) { processChartData(data) {
let category = [] let category = []
let seriesData = [] let seriesData = []
let dataMap = {}
let availableHours = new Set()
// //
if (data && data.length > 0) { if (data && data.length > 0) {
@ -141,15 +160,45 @@ export default {
orderSum += Number(item.data) orderSum += Number(item.data)
}) })
// data key //
data.forEach((item, index) => { data.forEach((item, index) => {
if (index < 10) { const hour = index
category.push(`0${index}:00`) const percentage = Number(((item.data / orderSum) * 100).toFixed(2))
} else {
category.push(`${index}:00`)
}
seriesData.push(Number(((item.data / orderSum) * 100).toFixed(2))) dataMap[hour] = percentage
availableHours.add(hour)
})
// Set
let sortedHours = Array.from(availableHours).sort((a, b) => a - b)
//
let selectedHours = []
// 1. 448121620
sortedHours.forEach(hour => {
if (hour % 4 === 0) {
selectedHours.push(hour)
}
})
// 2. 023
if (availableHours.has(0) && !selectedHours.includes(0)) {
selectedHours.unshift(0) // 0
}
if (availableHours.has(23) && !selectedHours.includes(23)) {
selectedHours.push(23) // 23
}
// 3. 使
if (selectedHours.length === 0) {
selectedHours = [0, 4, 8, 12, 16, 20, 23]
}
//
selectedHours.forEach(hour => {
category.push(`${hour}`)
seriesData.push(dataMap[hour] || 0)
}) })
} }

View File

@ -7,8 +7,11 @@
<!-- 年龄图表 --> <!-- 年龄图表 -->
<view class="chart-container"> <view class="chart-container">
<QiunDataCharts type="column" :opts="chartOpts" :chartData="chartData" :canvas2d="true" :inScrollView="true" <!-- 图表加载效果 -->
canvasId="customerAgeGroupChart" :animation="false" :ontap="true" :ontouch="true" <ChartLoading v-if="!hasChartData" text="数据加载中..." />
<!-- 实际图表 -->
<QiunDataCharts v-else type="column" :opts="chartOpts" :chartData="chartData" :canvas2d="true"
:inScrollView="true" canvasId="customerAgeGroupChart" :animation="false" :ontap="true" :ontouch="true"
tooltipFormat="CustomerAgeGroup" /> tooltipFormat="CustomerAgeGroup" />
</view> </view>
</view> </view>
@ -16,12 +19,14 @@
<script> <script>
import QiunDataCharts from './qiun-data-charts/components/qiun-data-charts/qiun-data-charts.vue' import QiunDataCharts from './qiun-data-charts/components/qiun-data-charts/qiun-data-charts.vue'
import ChartLoading from './ChartLoading.vue'
import request from "@/util/index.js"; import request from "@/util/index.js";
import moment from 'moment' import moment from 'moment'
export default { export default {
components: { components: {
QiunDataCharts QiunDataCharts,
ChartLoading
}, },
data() { data() {
@ -34,8 +39,20 @@ export default {
} }
} }
}, },
props: {
selectTime: {
type: String,
default: ""
},
},
computed: { computed: {
//
hasChartData() {
return this.rawData.category.length > 0 &&
this.rawData.seriesDataMan.length > 0 &&
this.rawData.seriesDataWoman.length > 0
},
// //
chartData() { chartData() {
return { return {
@ -62,16 +79,15 @@ export default {
xAxis: { xAxis: {
disableGrid: true, disableGrid: true,
itemCount: 6, // 6 itemCount: 6, // 6
scrollShow: true, //
scrollAlign: 'left', //
scrollColor: '#46B8F3', //
scrollWidth: 4, //
scrollHeight: 8 //
}, },
yAxis: { yAxis: {
showTitle: true,
data: [{ data: [{
min: 0, min: 0,
title: '%', title: '百分比(%)',
titleFontSize: 12,
titleOffsetY: -5,
titleOffsetX: 10,
}] }]
}, },
extra: { extra: {
@ -97,7 +113,7 @@ export default {
async handleGetCustomerAgeData() { async handleGetCustomerAgeData() {
const req = { const req = {
provinceCode: '530000', provinceCode: '530000',
statisticsMonth: moment(moment().subtract(1, 'M')).format('YYYYMM'), statisticsMonth: this.selectTime ? moment(moment(this.selectTime).subtract(1, 'M')).format('YYYYMM') : moment(moment().subtract(1, 'M')).format('YYYYMM'),
} }
const data = await this.getCustomerAgeRatio(req); const data = await this.getCustomerAgeRatio(req);

View File

@ -7,21 +7,26 @@
<!-- 客群消费偏好图表 --> <!-- 客群消费偏好图表 -->
<view class="chart-container"> <view class="chart-container">
<QiunDataCharts type="column" :opts="chartOpts" :chartData="chartData" :canvas2d="true" :inScrollView="true" <!-- 图表加载效果 -->
canvasId="customerConsumptionPreferencesChart" :animation="false" :ontap="true" :ontouch="true" <ChartLoading v-if="!hasChartData" text="数据加载中..." />
tooltipFormat="customerConsumptionPreferencesChart" /> <!-- 实际图表 -->
<QiunDataCharts v-else type="column" :opts="chartOpts" :chartData="chartData" :canvas2d="true"
:inScrollView="true" canvasId="customerConsumptionPreferencesChart" :animation="false" :ontap="true"
:ontouch="true" tooltipFormat="customerConsumptionPreferencesChart" />
</view> </view>
</view> </view>
</template> </template>
<script> <script>
import QiunDataCharts from './qiun-data-charts/components/qiun-data-charts/qiun-data-charts.vue' import QiunDataCharts from './qiun-data-charts/components/qiun-data-charts/qiun-data-charts.vue'
import ChartLoading from './ChartLoading.vue'
import request from "@/util/index.js"; import request from "@/util/index.js";
import moment from 'moment' import moment from 'moment'
export default { export default {
components: { components: {
QiunDataCharts QiunDataCharts,
ChartLoading
}, },
data() { data() {
@ -34,8 +39,19 @@ export default {
} }
} }
}, },
props: {
selectTime: {
type: String,
default: ""
},
},
computed: { computed: {
//
hasChartData() {
return this.rawData.category && this.rawData.category.length > 0;
},
// //
chartData() { chartData() {
return { return {
@ -52,7 +68,7 @@ export default {
// //
chartOpts() { chartOpts() {
return { return {
padding: [15, 15, 15, 15], // paddingX padding: [15, 15, 0, 15], // paddingX
dataLabel: false, dataLabel: false,
enableScroll: true, enableScroll: true,
xAxis: { xAxis: {
@ -60,9 +76,13 @@ export default {
itemCount: 4, // itemCount: 4, //
}, },
yAxis: { yAxis: {
showTitle: true,
data: [{ data: [{
min: 0, min: 0,
title: '%' title: '百分比(%)',
titleFontSize: 12,
titleOffsetY: -5,
titleOffsetX: 10,
}] }]
}, },
legend: { legend: {
@ -99,7 +119,7 @@ export default {
async handleGetCustomerConsumptionPreferencesData() { async handleGetCustomerConsumptionPreferencesData() {
const req = { const req = {
ProvinceCode: '530000', ProvinceCode: '530000',
StatisticsDate: moment().subtract(1, 'd').format('YYYY-MM-DD'), StatisticsDate: this.selectTime ? moment(this.selectTime).subtract(1, 'd').format('YYYY-MM-DD') : moment().subtract(1, 'd').format('YYYY-MM-DD'),
ServerpartId: "" // ID ServerpartId: "" // ID
} }

View File

@ -7,20 +7,25 @@
<!-- 客群特征分析图表 --> <!-- 客群特征分析图表 -->
<view class="chart-container"> <view class="chart-container">
<QiunDataCharts type="bubble" :opts="chartOpts" :chartData="chartData" :canvas2d="true" :inScrollView="true" <!-- 图表加载效果 -->
canvasId="customerGroupChart" :animation="false" :ontap="true" :ontouch="true" /> <ChartLoading v-if="!hasChartData" text="数据加载中..." />
<!-- 实际图表 -->
<QiunDataCharts v-else type="bubble" :opts="chartOpts" :chartData="chartData" :canvas2d="true"
:inScrollView="true" canvasId="customerGroupChart" :animation="false" :ontap="true" :ontouch="true" />
</view> </view>
</view> </view>
</template> </template>
<script> <script>
import QiunDataCharts from './qiun-data-charts/components/qiun-data-charts/qiun-data-charts.vue' import QiunDataCharts from './qiun-data-charts/components/qiun-data-charts/qiun-data-charts.vue'
import ChartLoading from './ChartLoading.vue'
import request from "@/util/index.js"; import request from "@/util/index.js";
import moment from 'moment' import moment from 'moment'
export default { export default {
components: { components: {
QiunDataCharts QiunDataCharts,
ChartLoading
}, },
data() { data() {
@ -35,8 +40,18 @@ export default {
} }
} }
}, },
props: {
selectTime: {
type: String,
default: ""
},
},
computed: { computed: {
//
hasChartData() {
return this.rawData.seriesData && this.rawData.seriesData.length > 0;
},
// //
chartData() { chartData() {
return { return {
@ -117,7 +132,7 @@ export default {
async handleGetCustomerGroupData() { async handleGetCustomerGroupData() {
const req = { const req = {
provinceCode: "530000", provinceCode: "530000",
statisticsMonth: moment().subtract(1, 'M').format('YYYYMM'), statisticsMonth: this.selectTime ? moment(this.selectTime).subtract(1, 'M').format('YYYYMM') : moment().subtract(1, 'M').format('YYYYMM'),
serverpartId: "", // ID serverpartId: "", // ID
} }

View File

@ -5,22 +5,27 @@
</view> </view>
<!-- 节假日营收汇总图表 --> <!-- 节假日营收汇总图表 -->
<view class="chart-container"> <view class="chart-container">
<QiunDataCharts type="pie" :opts="chartOpts" :chartData="chartData" :canvas2d="true" :inScrollView="true" <!-- 图表加载效果 -->
canvasId="festivalRevenueSumInfoChart" :animation="false" :ontap="true" :ontouch="true" <ChartLoading v-if="!hasChartData" text="数据加载中..." />
tooltipFormat="festivalRevenueSumInfoChart" /> <!-- 实际图表 -->
<QiunDataCharts v-else type="pie" :opts="chartOpts" :chartData="chartData" :canvas2d="true"
:inScrollView="true" canvasId="festivalRevenueSumInfoChart" :animation="false" :ontap="true"
:ontouch="true" tooltipFormat="festivalRevenueSumInfoChart" />
</view> </view>
</view> </view>
</template> </template>
<script> <script>
import QiunDataCharts from './qiun-data-charts/components/qiun-data-charts/qiun-data-charts.vue' import QiunDataCharts from './qiun-data-charts/components/qiun-data-charts/qiun-data-charts.vue'
import ChartLoading from './ChartLoading.vue'
import request from "@/util/index.js"; import request from "@/util/index.js";
import moment from 'moment' import moment from 'moment'
import { wrapTreeNode } from "@/util/dateTime"; import { wrapTreeNode } from "@/util/dateTime";
export default { export default {
components: { components: {
QiunDataCharts QiunDataCharts,
ChartLoading
}, },
data() { data() {
@ -33,6 +38,11 @@ export default {
}, },
computed: { computed: {
//
hasChartData() {
return this.rawData.seriesData && this.rawData.seriesData.length > 0
},
// //
chartData() { chartData() {
return { return {
@ -45,31 +55,22 @@ export default {
// //
chartOpts() { chartOpts() {
return { return {
padding: [15, 15, 15, 15], // padding padding: [15, 48, 15, 15], // padding
dataLabel: false, dataLabel: false,
legend: { legend: {
show: true, show: true,
position: 'right', position: 'right',
float: 'center', float: 'center',
backgroundColor: 'rgba(0,0,0,0)',
borderColor: 'rgba(0,0,0,0)',
fontSize: 11, fontSize: 11,
fontColor: '#333333', fontColor: '#333333',
margin: 0,
padding: 0,
itemGap: 6,
textAlign: 'left'
}, },
extra: { extra: {
pie: { pie: {
activeOpacity: 0.5,
activeRadius: 10, activeRadius: 10,
offsetAngle: 0, offsetAngle: 0,
labelWidth: 0, labelWidth: 0,
border: false, border: false,
borderWidth: 2, borderWidth: 2,
borderColor: '#FFFFFF',
linearType: 'custom'
} }
}, },
} }
@ -102,13 +103,11 @@ export default {
"CommercialApi/Revenue/GetHolidayRevenueRatio", "CommercialApi/Revenue/GetHolidayRevenueRatio",
params params
); );
console.log('节假日营收汇总数据', data);
return data || [] return data || []
}, },
// //
processChartData(data) { processChartData(data) {
console.log('dasdjask;d', data);
let seriesData = [] let seriesData = []
@ -132,7 +131,6 @@ export default {
seriesData: seriesData seriesData: seriesData
} }
console.log('处理后的图表数据(仅节假日细分)', this.rawData)
}, },
} }

View File

@ -7,21 +7,26 @@
<!-- 性别图表 --> <!-- 性别图表 -->
<view class="chart-container"> <view class="chart-container">
<QiunDataCharts type="ring" :opts="chartOpts" :chartData="chartData" :canvas2d="true" :inScrollView="true" <!-- 图表加载效果 -->
canvasId="genderCustomerGroupChart" :animation="false" :ontap="true" :ontouch="true" <ChartLoading v-if="!hasChartData" text="数据加载中..." />
tooltipFormat="GenderCustomerGroup" /> <!-- 实际图表 -->
<QiunDataCharts v-else type="ring" :opts="chartOpts" :chartData="chartData" :canvas2d="true"
:inScrollView="true" canvasId="genderCustomerGroupChart" :animation="false" :ontap="true"
:ontouch="true" tooltipFormat="GenderCustomerGroup" />
</view> </view>
</view> </view>
</template> </template>
<script> <script>
import QiunDataCharts from './qiun-data-charts/components/qiun-data-charts/qiun-data-charts.vue' import QiunDataCharts from './qiun-data-charts/components/qiun-data-charts/qiun-data-charts.vue'
import ChartLoading from './ChartLoading.vue'
import request from "@/util/index.js"; import request from "@/util/index.js";
import moment from 'moment' import moment from 'moment'
export default { export default {
components: { components: {
QiunDataCharts QiunDataCharts,
ChartLoading
}, },
data() { data() {
@ -33,8 +38,18 @@ export default {
} }
} }
}, },
props: {
selectTime: {
type: String,
default: ""
},
},
computed: { computed: {
//
hasChartData() {
return this.rawData.seriesData && this.rawData.seriesData.length > 0
},
// //
chartData() { chartData() {
return { return {
@ -97,7 +112,7 @@ export default {
const req = { const req = {
statisticsType: 1, statisticsType: 1,
provinceCode: '530000', provinceCode: '530000',
statisticsMonth: moment(moment().subtract(1, 'M')).format('YYYYMM'), statisticsMonth: this.selectTime ? moment(moment(this.selectTime).subtract(1, 'M')).format('YYYYMM') : moment(moment().subtract(1, 'M')).format('YYYYMM'),
} }
const data = await this.getCustomerRatio(req); const data = await this.getCustomerRatio(req);
@ -112,7 +127,6 @@ export default {
"CommercialApi/Customer/GetCustomerRatio", "CommercialApi/Customer/GetCustomerRatio",
params params
); );
console.log('性别数据', data);
return data || [] return data || []
}, },
@ -142,7 +156,6 @@ export default {
legendData: legendData legendData: legendData
} }
console.log('处理后的图表数据', this.rawData)
}, },
} }

View File

@ -7,7 +7,10 @@
<!-- 图表容器 --> <!-- 图表容器 -->
<view class="chart-container" :style="{ height: chartHeight }"> <view class="chart-container" :style="{ height: chartHeight }">
<QiunDataCharts type="column" :opts="chartOpts" :chartData="barChartData" :canvas2d="true" <!-- 图表加载效果 -->
<ChartLoading v-if="!hasChartData" text="数据加载中..." />
<!-- 实际图表 -->
<QiunDataCharts v-else type="column" :opts="chartOpts" :chartData="barChartData" :canvas2d="true"
:inScrollView="true" canvasId="hotProductListChart" :animation="false" :ontap="true" :ontouch="true" :inScrollView="true" canvasId="hotProductListChart" :animation="false" :ontap="true" :ontouch="true"
tooltipFormat="SalesRankingOfProducts" /> tooltipFormat="SalesRankingOfProducts" />
</view> </view>
@ -16,12 +19,14 @@
<script> <script>
import QiunDataCharts from './qiun-data-charts/components/qiun-data-charts/qiun-data-charts.vue' import QiunDataCharts from './qiun-data-charts/components/qiun-data-charts/qiun-data-charts.vue'
import ChartLoading from './ChartLoading.vue'
import request from "@/util/index.js"; import request from "@/util/index.js";
import moment from 'moment' import moment from 'moment'
export default { export default {
components: { components: {
QiunDataCharts QiunDataCharts,
ChartLoading
}, },
data() { data() {
return { return {
@ -32,6 +37,11 @@ export default {
}, },
computed: { computed: {
//
hasChartData() {
return this.salesRankingData && this.salesRankingData.length > 0
},
// //
barChartData() { barChartData() {
return { return {
@ -45,7 +55,7 @@ export default {
} }
}, },
// //
chartOpts() { chartOpts() {
// 6100 // 6100
const maxSales = Math.max(...this.salesRankingData.map(item => item.sales)); const maxSales = Math.max(...this.salesRankingData.map(item => item.sales));
@ -61,32 +71,29 @@ export default {
} }
return { return {
color: ['#576EFF'],
legend: { legend: {
show: true, show: true,
color: ['#576EFF']
}, },
padding: [15, 15, 15, 15], // paddingX padding: [15, 15, 0, 15], // paddingX
dataLabel: false, dataLabel: false,
enableScroll: false, enableScroll: false,
xAxis: { xAxis: {
itemCount: 5, // itemCount: 5, //
scrollAlign: 'right', fontSize: 10, //
scrollColor: '#576EFF',
scrollBackgroundColor: 'rgba(87, 110, 255, 0.1)',
scrollWidth: 4,
scrollHeight: 8,
rotate: 30, // 30
fontSize: 12, //
margin: 15, // 线
}, },
yAxis: { yAxis: {
showTitle: true,
titleFontSize: 12,
gridType: 'dash', gridType: 'dash',
dashLength: 2, dashLength: 2,
data: [{ data: [{
title: '商品件数(件)',
min: 0, min: 0,
max: finalMax, max: finalMax,
data: yAxisData data: yAxisData,
titleOffsetY: -5,
titleOffsetX: -10,
}] }]
}, },
categoriesReal: this.salesRankingData.map(item => categoriesReal: this.salesRankingData.map(item =>

View File

@ -8,7 +8,10 @@
<!-- 订单统计图表 --> <!-- 订单统计图表 -->
<view class="chart-card"> <view class="chart-card">
<view class="chart-container"> <view class="chart-container">
<QiunDataCharts type="mix" :opts="chartOpts" :chartData="chartData" :canvas2d="true" <!-- 图表加载效果 -->
<ChartLoading v-if="!hasChartData" text="数据加载中..." />
<!-- 实际图表 -->
<QiunDataCharts v-else type="mix" :opts="chartOpts" :chartData="chartData" :canvas2d="true"
:inScrollView="true" canvasId="mallOrderStatisticsChart" :animation="false" :ontap="true" :inScrollView="true" canvasId="mallOrderStatisticsChart" :animation="false" :ontap="true"
:ontouch="true" tooltipFormat="MallOrderStatistics" /> :ontouch="true" tooltipFormat="MallOrderStatistics" />
</view> </view>
@ -18,12 +21,14 @@
<script> <script>
import QiunDataCharts from './qiun-data-charts/components/qiun-data-charts/qiun-data-charts.vue' import QiunDataCharts from './qiun-data-charts/components/qiun-data-charts/qiun-data-charts.vue'
import ChartLoading from './ChartLoading.vue'
import request from "@/util/index.js"; import request from "@/util/index.js";
import moment from 'moment' import moment from 'moment'
export default { export default {
components: { components: {
QiunDataCharts QiunDataCharts,
ChartLoading
}, },
data() { data() {
@ -36,8 +41,18 @@ export default {
} }
} }
}, },
props: {
selectTime: {
type: String,
default: ""
},
},
computed: { computed: {
//
hasChartData() {
return this.rawData.category && this.rawData.category.length > 0
},
// //
chartData() { chartData() {
return { return {
@ -62,7 +77,7 @@ export default {
// //
chartOpts() { chartOpts() {
return { return {
padding: [15, 15, 15, 15], // padding: [25, 15, 0, 15], //
dataLabel: false, dataLabel: false,
enableScroll: true, enableScroll: true,
dataPointShape: true, dataPointShape: true,
@ -76,11 +91,15 @@ export default {
min: 0, min: 0,
title: '交易金额(元)', title: '交易金额(元)',
titleFontSize: 12, titleFontSize: 12,
titleOffsetY: -10,
titleOffsetX: -30,
position: 'left', position: 'left',
}, },
{ {
min: 0, min: 0,
title: '交易笔数(笔)', title: '交易笔数(笔)',
titleOffsetY: -10,
titleOffsetX: 0,
titleFontSize: 12, titleFontSize: 12,
position: 'right', position: 'right',
} }
@ -122,8 +141,8 @@ export default {
DataType: 2, // 1 2 DataType: 2, // 1 2
ProvinceCode: '530000', ProvinceCode: '530000',
type: 'encryption', type: 'encryption',
StartMonth: moment().startOf('y').format('YYYYMM'), StartMonth: this.selectTime ? moment(this.selectTime).startOf('y').format('YYYYMM') : moment().startOf('y').format('YYYYMM'),
EndMonth: moment().subtract(1, 'M').format('YYYYMM'), EndMonth: this.selectTime ? moment(this.selectTime).subtract(1, 'M').format('YYYYMM') : moment().subtract(1, 'M').format('YYYYMM'),
} }

View File

@ -6,8 +6,10 @@
<!-- 会员总数 --> <!-- 会员总数 -->
<view class="member-sum-box"> <view class="member-sum-box">
<view class="member-sum-box-left">会员总数</view> <view class="member-sum-box-left">会员总数</view>
<view class="member-sum-total">{{ memberData.totalMembers || 0 }}</view> <view class="member-sum-total">{{ memberData.totalMembers ? memberData.totalMembers.toLocaleString() : 0 }}
<view class="member-sum-box-right">本月新增 {{ memberData.monthNewMembers || 0 }} </view> </view>
<view class="member-sum-box-right">本月新增 {{ memberData.monthNewMembers ?
memberData.monthNewMembers.toLocaleString() : 0 }} </view>
</view> </view>
<!-- 近30天数据 --> <!-- 近30天数据 -->
@ -18,22 +20,29 @@
<view class="recent-data"> <view class="recent-data">
<view class="recent-data-top"> <view class="recent-data-top">
<view class="recent-data-top-item" style="left: 0;top: 0;"> <view class="recent-data-top-item" style="left: 0;top: 0;">
<view class="recent-data-top-value">{{ memberData.newMembersCount || 0 }}</view> <view class="recent-data-top-value">{{ memberData.newMembersCount ?
memberData.newMembersCount.toLocaleString() : 0
}}
</view>
<view class="recent-data-top-label">新增会员数</view> <view class="recent-data-top-label">新增会员数</view>
</view> </view>
<view class="recent-data-top-item" style="left: 30%;top: 0;"> <view class="recent-data-top-item" style="left: 30%;top: 0;">
<view class="recent-data-top-value">{{ memberData.openCount || 0 }}</view> <view class="recent-data-top-value">{{ memberData.openCount ? memberData.openCount.toLocaleString()
: 0 }}</view>
<view class="recent-data-top-label">打开次数</view> <view class="recent-data-top-label">打开次数</view>
</view> </view>
<view class="recent-data-top-item" style="right: 30%;top: 0;"> <view class="recent-data-top-item" style="right: 30%;top: 0;">
<view class="recent-data-top-value">{{ memberData.newPeopleCount || 0 }}</view> <view class="recent-data-top-value">{{ memberData.newPeopleCount ?
memberData.newPeopleCount.toLocaleString() : 0 }}
</view>
<view class="recent-data-top-label">新增人数</view> <view class="recent-data-top-label">新增人数</view>
</view> </view>
<view class="recent-data-top-item" style="right: 0;top: 0;"> <view class="recent-data-top-item" style="right: 0;top: 0;">
<view class="recent-data-top-value">{{ memberData.visitCount || 0 }}</view> <view class="recent-data-top-value">{{ memberData.visitCount ?
memberData.visitCount.toLocaleString() : 0 }}</view>
<view class="recent-data-top-label">访问人数</view> <view class="recent-data-top-label">访问人数</view>
</view> </view>
</view> </view>
@ -46,13 +55,14 @@
<view class="member-consumption"> <view class="member-consumption">
<view class="member-consumption-item"> <view class="member-consumption-item">
<view class="member-consumption-label">会员消费笔数</view> <view class="member-consumption-label">会员消费笔数/</view>
<view class="member-consumption-progress"></view> <view class="member-consumption-progress"></view>
<view class="member-consumption-value">{{ memberData.consumptionCount || 0 }}</view> <view class="member-consumption-value">{{ memberData.consumptionCount ? memberData.consumptionCount : 0
}}</view>
</view> </view>
<view class="member-consumption-item"> <view class="member-consumption-item">
<view class="member-consumption-label">会员总销售额</view> <view class="member-consumption-label">会员总销售额/</view>
<view class="member-consumption-progress2"></view> <view class="member-consumption-progress2"></view>
<view class="member-consumption-value">{{ formatMoney(memberData.totalSalesAmount || 0) }}</view> <view class="member-consumption-value">{{ formatMoney(memberData.totalSalesAmount || 0) }}</view>
</view> </view>
@ -138,7 +148,12 @@ export default {
} }
} }
}, },
props: {
selectTime: {
type: String,
default: ""
},
},
onReady() { onReady() {
this.handleGetMemberMallData() this.handleGetMemberMallData()
}, },
@ -148,7 +163,7 @@ export default {
async handleGetMemberMallData() { async handleGetMemberMallData() {
const req = { const req = {
ProvinceCode: '530000', ProvinceCode: '530000',
StatisticsDate: moment().subtract(1, 'd').format('YYYY-MM-DD') StatisticsDate: this.selectTime ? moment(this.selectTime).subtract(1, 'd').format('YYYY-MM-DD') : moment().subtract(1, 'd').format('YYYY-MM-DD')
} }
const data = await this.getMemberMallData(req); const data = await this.getMemberMallData(req);
@ -246,7 +261,6 @@ export default {
font-size: 28rpx; font-size: 28rpx;
font-weight: 600; font-weight: 600;
color: #1890FF; color: #1890FF;
letter-spacing: 4rpx;
} }
.member-sum-box-right { .member-sum-box-right {

View File

@ -47,7 +47,10 @@
<view class="chart-section"> <view class="chart-section">
<view class="chart-title">设备设施</view> <view class="chart-title">设备设施</view>
<view class="chart-container"> <view class="chart-container">
<QiunDataCharts type="column" :opts="facilityChartOpts" :chartData="facilityChartData" :canvas2d="true" <!-- 图表加载效果 -->
<ChartLoading v-if="!hasFacilityData" text="数据加载中..." />
<!-- 实际图表 -->
<QiunDataCharts v-else type="column" :opts="facilityChartOpts" :chartData="facilityChartData" :canvas2d="true"
:inScrollView="true" canvasId="facilityChart" tooltipFormat="facilityChartData" /> :inScrollView="true" canvasId="facilityChart" tooltipFormat="facilityChartData" />
</view> </view>
</view> </view>
@ -83,7 +86,10 @@
<view class="chart-section"> <view class="chart-section">
<view class="chart-title">服务区类型分布</view> <view class="chart-title">服务区类型分布</view>
<view class="chart-container"> <view class="chart-container">
<QiunDataCharts type="pie" :opts="areaTypePieOpts" :chartData="areaTypePieData" :canvas2d="true" <!-- 图表加载效果 -->
<ChartLoading v-if="!hasPieData" text="数据加载中..." />
<!-- 实际饼图 -->
<QiunDataCharts v-else type="pie" :opts="areaTypePieOpts" :chartData="areaTypePieData" :canvas2d="true"
:inScrollView="true" canvasId="areaTypePieChart" tooltipFormat="areaTypePieData" /> :inScrollView="true" canvasId="areaTypePieChart" tooltipFormat="areaTypePieData" />
</view> </view>
</view> </view>
@ -92,11 +98,13 @@
<script> <script>
import QiunDataCharts from './qiun-data-charts/components/qiun-data-charts/qiun-data-charts.vue' import QiunDataCharts from './qiun-data-charts/components/qiun-data-charts/qiun-data-charts.vue'
import ChartLoading from './ChartLoading.vue'
import request from "@/util/index.js"; import request from "@/util/index.js";
export default { export default {
components: { components: {
QiunDataCharts QiunDataCharts,
ChartLoading
}, },
data() { data() {
@ -124,6 +132,26 @@ export default {
}, },
computed: { computed: {
//
hasFacilityData() {
return this.serviceData.REFUELINGGUNTotal > 0 ||
this.serviceData.ChargingStationTotal > 0 ||
this.serviceData.HASPILOTLOUNGETotal > 0 ||
this.serviceData.NursingRoomTotal > 0 ||
this.serviceData.URECOUNTTotal > 0 ||
this.serviceData.WaterCount > 0;
},
//
hasPieData() {
return this.serviceData.serviceAllTotal > 0 ||
this.serviceData.ParkingServiceCount > 0 ||
this.serviceData.WaterStationCount > 0 ||
this.serviceData.ViewingDeckCount > 0 ||
this.serviceData.RestAreaCount > 0 ||
this.serviceData.ClosedCount > 0;
},
// //
facilityChartData() { facilityChartData() {
return { return {
@ -146,19 +174,29 @@ export default {
facilityChartOpts() { facilityChartOpts() {
return { return {
color: ['#1890FF', '#52C41A', '#FAAD14', '#F5222D', '#722ED1', '#13C2C2'], color: ['#1890FF', '#52C41A', '#FAAD14', '#F5222D', '#722ED1', '#13C2C2'],
padding: [15, 15, 15, 15], padding: [15, 15, 0, 15],
dataLabel: true, dataLabel: true,
legend: { legend: {
show: false show: true
}, },
xAxis: { xAxis: {
itemCount: 6, itemCount: 6,
scrollShow: false scrollShow: false,
fontSize: 12
}, },
yAxis: { yAxis: {
gridType: 'dash', gridType: 'dash',
dashLength: 2, dashLength: 2,
data: [{ min: 0 }] showTitle: true,
data: [
{
min: 0,
title: '设施数量(个)',
titleFontSize: 12,
titleOffsetY: -5,
titleOffsetX: 0,
}
]
}, },
extra: { extra: {
column: { column: {

View File

@ -7,8 +7,11 @@
<!-- 偏好类型图表 --> <!-- 偏好类型图表 -->
<view class="chart-container"> <view class="chart-container">
<QiunDataCharts type="radar" :opts="chartOpts" :chartData="chartData" :canvas2d="true" :inScrollView="true" <!-- 图表加载效果 -->
canvasId="preferenceTypeChart" :animation="false" :ontap="true" :ontouch="true" <ChartLoading v-if="!hasChartData" text="数据加载中..." />
<!-- 实际图表 -->
<QiunDataCharts v-else type="radar" :opts="chartOpts" :chartData="chartData" :canvas2d="true"
:inScrollView="true" canvasId="preferenceTypeChart" :animation="false" :ontap="true" :ontouch="true"
tooltipFormat="PreferenceType" /> tooltipFormat="PreferenceType" />
</view> </view>
</view> </view>
@ -16,12 +19,14 @@
<script> <script>
import QiunDataCharts from './qiun-data-charts/components/qiun-data-charts/qiun-data-charts.vue' import QiunDataCharts from './qiun-data-charts/components/qiun-data-charts/qiun-data-charts.vue'
import ChartLoading from './ChartLoading.vue'
import request from "@/util/index.js"; import request from "@/util/index.js";
import moment from 'moment' import moment from 'moment'
export default { export default {
components: { components: {
QiunDataCharts QiunDataCharts,
ChartLoading
}, },
data() { data() {
@ -35,8 +40,18 @@ export default {
} }
} }
}, },
props: {
selectTime: {
type: String,
default: ""
},
},
computed: { computed: {
//
hasChartData() {
return this.rawData.category && this.rawData.category.length > 0
},
// //
chartData() { chartData() {
return { return {
@ -103,8 +118,8 @@ export default {
async handleGetPreferenceTypeData() { async handleGetPreferenceTypeData() {
const req = { const req = {
statisticsType: 1, statisticsType: 1,
startMonth: moment().startOf('y').format('YYYYMM'), startMonth: this.selectTime ? moment(this.selectTime).startOf('y').format('YYYYMM') : moment().startOf('y').format('YYYYMM'),
endMonth: moment().format('YYYYMM'), endMonth: this.selectTime ? moment(this.selectTime).format('YYYYMM') : moment().format('YYYYMM'),
provinceCode: '530000', provinceCode: '530000',
showTradeLevel: 1, showTradeLevel: 1,
fromRedis: true fromRedis: true

View File

@ -7,8 +7,11 @@
<!-- 区域营收占比图表 --> <!-- 区域营收占比图表 -->
<view class="chart-container"> <view class="chart-container">
<QiunDataCharts type="pie" :opts="chartOpts" :chartData="chartData" :canvas2d="true" :inScrollView="true" <!-- 图表加载效果 -->
canvasId="regionalRevenueChart" :animation="false" :ontap="true" :ontouch="true" <ChartLoading v-if="!hasChartData" text="数据加载中..." />
<!-- 实际图表 -->
<QiunDataCharts v-else type="pie" :opts="chartOpts" :chartData="chartData" :canvas2d="true"
:inScrollView="true" canvasId="regionalRevenueChart" :animation="false" :ontap="true" :ontouch="true"
tooltipFormat="regionalRevenueChart" /> tooltipFormat="regionalRevenueChart" />
</view> </view>
</view> </view>
@ -16,15 +19,22 @@
<script> <script>
import QiunDataCharts from './qiun-data-charts/components/qiun-data-charts/qiun-data-charts.vue' import QiunDataCharts from './qiun-data-charts/components/qiun-data-charts/qiun-data-charts.vue'
import ChartLoading from './ChartLoading.vue'
import request from "@/util/index.js"; import request from "@/util/index.js";
import moment from 'moment' import moment from 'moment'
import { wrapTreeNode } from "@/util/dateTime"; import { wrapTreeNode } from "@/util/dateTime";
export default { export default {
components: { components: {
QiunDataCharts QiunDataCharts,
ChartLoading
},
props: {
selectTime: {
type: String,
default: ""
},
}, },
data() { data() {
return { return {
// ID // ID
@ -39,6 +49,11 @@ export default {
}, },
computed: { computed: {
//
hasChartData() {
return this.rawData.seriesData && this.rawData.seriesData.length > 0
},
// //
chartData() { chartData() {
return { return {
@ -57,27 +72,20 @@ export default {
show: true, show: true,
position: 'right', position: 'right',
float: 'center', float: 'center',
backgroundColor: 'rgba(0,0,0,0)',
borderColor: 'rgba(0,0,0,0)',
fontSize: 12, fontSize: 12,
fontColor: '#333333', fontColor: '#333333',
margin: 0,
padding: 0,
itemGap: 10,
textAlign: 'left'
}, },
extra: { extra: {
pie: { pie: {
activeOpacity: 0.5,
activeRadius: 10, activeRadius: 10,
offsetAngle: 0, offsetAngle: 0,
labelWidth: 0, labelWidth: 0,
border: false, border: false,
borderWidth: 2, borderWidth: 2,
borderColor: '#FFFFFF', borderColor: '#FFFFFF'
linearType: 'custom'
} }
}, },
percentageList: this.rawData.legendData
} }
} }
}, },
@ -113,8 +121,8 @@ export default {
}) })
const req = { const req = {
StartDate: moment().startOf('M').format('YYYY-MM-DD'), StartDate: this.selectTime ? moment(this.selectTime).startOf('M').format('YYYY-MM-DD') : moment().startOf('M').format('YYYY-MM-DD'),
EndDate: moment().endOf('M').format('YYYY-MM-DD'), EndDate: this.selectTime ? moment(this.selectTime).endOf('M').format('YYYY-MM-DD') : moment().endOf('M').format('YYYY-MM-DD'),
DataType: 1, // DataType: 1, //
ServerpartIds: allId, // 使ID ServerpartIds: allId, // 使ID
DataSourceType: 1, DataSourceType: 1,

View File

@ -38,16 +38,21 @@
<!-- 供应商列表 --> <!-- 供应商列表 -->
<view class="supplier-list-content"> <view class="supplier-list-content">
<view class="supplier-list-item" v-for="(item, index) in supplierList" :key="index"> <!-- 供应商列表加载效果 -->
<view class="supplier-list-right"> <ChartLoading v-if="!hasSupplierListData" text="数据加载中..." />
<view class="supplier-list-namebox"> <!-- 供应商列表内容 -->
<image class="supplier-list-icon" :src="supplierIcon" mode="aspectFit" /> <view v-else>
<view class="supplier-list-name">{{ item.SupplierName || '' }}</view> <view class="supplier-list-item" v-for="(item, index) in supplierList" :key="index">
</view> <view class="supplier-list-right">
<view class="supplier-list-namebox">
<image class="supplier-list-icon" :src="supplierIcon" mode="aspectFit" />
<view class="supplier-list-name">{{ item.SupplierName || '' }}</view>
</view>
<view class="supplier-list-content2"> <view class="supplier-list-content2">
<text class="shop-value">{{ item.VarietyCount }}</text> <text class="shop-value">{{ item.VarietyCount }}</text>
<text class="shop-unit"></text> <text class="shop-unit"></text>
</view>
</view> </view>
</view> </view>
</view> </view>
@ -56,10 +61,15 @@
</template> </template>
<script> <script>
import ChartLoading from './ChartLoading.vue'
import request from "@/util/index.js"; import request from "@/util/index.js";
import moment from 'moment' import moment from 'moment'
export default { export default {
components: {
ChartLoading
},
data() { data() {
return { return {
// //
@ -72,6 +82,18 @@ export default {
supplierIcon: 'https://eshangtech.com/cyy_DIB/supplierIcon.png' supplierIcon: 'https://eshangtech.com/cyy_DIB/supplierIcon.png'
} }
}, },
props: {
selectTime: {
type: String,
default: ""
},
},
computed: {
//
hasSupplierListData() {
return this.supplierList && this.supplierList.length > 0;
}
},
onReady() { onReady() {
this.handleGetData() this.handleGetData()
@ -92,7 +114,7 @@ export default {
const req = { const req = {
ProvinceCode: "530000", ProvinceCode: "530000",
type: 'encryption', type: 'encryption',
StatisticsMonth: "202505", StatisticsMonth: this.selectTime ? moment(this.selectTime).format('YYYYMM') : "202505",
} }
// 使API // 使API
@ -211,6 +233,8 @@ export default {
border-radius: 16rpx; border-radius: 16rpx;
padding: 24rpx; padding: 24rpx;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08); box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
min-height: 300rpx;
/* 设置最小高度以显示加载效果 */
.supplier-list-item { .supplier-list-item {
width: 100%; width: 100%;

View File

@ -16,13 +16,18 @@
<text class="benefits-title">本月福利金发放额度</text> <text class="benefits-title">本月福利金发放额度</text>
</view> </view>
<view class="benefits-right"> <view class="benefits-right">
<text class="benefits-value">{{ allRealData.distributeAmount || '0' }}</text> <text class="benefits-value">{{ allRealData.distributeAmount ?
allRealData.distributeAmount.toLocaleString() : '0'
}}</text>
<text class="benefits-unit"></text> <text class="benefits-unit"></text>
</view> </view>
</view> </view>
<view class="chart-container"> <view class="chart-container">
<QiunDataCharts type="pie" :opts="chartOpts" :chartData="chartData" :canvas2d="true" <!-- 图表加载效果 -->
<ChartLoading v-if="!hasChartData" text="数据加载中..." />
<!-- 实际图表 -->
<QiunDataCharts v-else type="pie" :opts="chartOpts" :chartData="chartData" :canvas2d="true"
:inScrollView="true" canvasId="coreCategoryChart" :animation="false" :ontap="true" :ontouch="true" :inScrollView="true" canvasId="coreCategoryChart" :animation="false" :ontap="true" :ontouch="true"
tooltipFormat="ThisMonthBenefits" /> tooltipFormat="ThisMonthBenefits" />
</view> </view>
@ -32,12 +37,14 @@
<script> <script>
import QiunDataCharts from './qiun-data-charts/components/qiun-data-charts/qiun-data-charts.vue' import QiunDataCharts from './qiun-data-charts/components/qiun-data-charts/qiun-data-charts.vue'
import ChartLoading from './ChartLoading.vue'
import request from "@/util/index.js"; import request from "@/util/index.js";
import moment from 'moment' import moment from 'moment'
export default { export default {
components: { components: {
QiunDataCharts QiunDataCharts,
ChartLoading
}, },
data() { data() {
@ -50,8 +57,18 @@ export default {
}, },
} }
}, },
props: {
selectTime: {
type: String,
default: ""
},
},
computed: { computed: {
//
hasChartData() {
return this.rawData.pieData && this.rawData.pieData.length > 0
},
// //
chartData() { chartData() {
return { return {
@ -70,24 +87,17 @@ export default {
show: true, show: true,
position: 'right', position: 'right',
float: 'center', float: 'center',
backgroundColor: 'rgba(0,0,0,0)',
borderColor: 'rgba(0,0,0,0)',
fontSize: 12, fontSize: 12,
margin: 0,
padding: 0,
itemGap: 10,
textAlign: 'left' textAlign: 'left'
}, },
extra: { extra: {
pie: { pie: {
activeOpacity: 0.5,
activeRadius: 10, activeRadius: 10,
offsetAngle: 0, offsetAngle: 0,
labelWidth: 0, labelWidth: 0,
border: false, border: false,
borderWidth: 2, borderWidth: 2,
borderColor: '#FFFFFF', borderColor: '#FFFFFF',
linearType: 'custom'
} }
}, },
} }
@ -108,7 +118,7 @@ export default {
async getWelFareSummaryData() { async getWelFareSummaryData() {
const req = { const req = {
ProvinceCode: '530000', ProvinceCode: '530000',
StatisticsMonth: moment().subtract(1, 'M').format('YYYYMM'), StatisticsMonth: this.selectTime ? moment(this.selectTime).subtract(1, 'M').format('YYYYMM') : moment().subtract(1, 'M').format('YYYYMM'),
type: 'encryption' type: 'encryption'
} }

View File

@ -7,8 +7,11 @@
</view> </view>
<view class="chart-content"> <view class="chart-content">
<view class="bar-chart-container"> <view class="bar-chart-container">
<QiunDataCharts type="column" :opts="chartOpts" :chartData="chartData" :animation="false" :canvas2d="true" <!-- 图表加载效果 -->
:inScrollView="true" :ontap="true" :ontouch="true" canvasId="trendTrafficFlowChart" <ChartLoading v-if="!hasChartData" text="数据加载中..." />
<!-- 实际图表 -->
<QiunDataCharts v-else type="column" :opts="chartOpts" :chartData="chartData" :animation="false"
:canvas2d="true" :inScrollView="true" :ontap="true" :ontouch="true" canvasId="trendTrafficFlowChart"
tooltipFormat="TrendTrafficFlow" /> tooltipFormat="TrendTrafficFlow" />
</view> </view>
</view> </view>
@ -18,12 +21,14 @@
<script> <script>
import QiunDataCharts from './qiun-data-charts/components/qiun-data-charts/qiun-data-charts.vue' import QiunDataCharts from './qiun-data-charts/components/qiun-data-charts/qiun-data-charts.vue'
import ChartLoading from './ChartLoading.vue'
import request from "@/util/index.js"; import request from "@/util/index.js";
import moment from 'moment' import moment from 'moment'
export default { export default {
components: { components: {
QiunDataCharts QiunDataCharts,
ChartLoading
}, },
data() { data() {
@ -45,7 +50,20 @@ export default {
} }
}, },
props: {
selectTime: {
type: String,
default: ""
},
},
computed: { computed: {
//
hasChartData() {
// 0
return this.monthlyData && this.monthlyData.length > 0 &&
this.monthlyData.some(item => item.currentYearValue > 0 || item.previousYearValue > 0);
},
// //
chartData() { chartData() {
return { return {
@ -71,16 +89,16 @@ export default {
enableScroll: true, // enableScroll: true, //
xAxis: { xAxis: {
disableGrid: true, disableGrid: true,
scrollShow: true, //
scrollAlign: 'left', //
itemCount: 6, // 6 itemCount: 6, // 6
scrollColor: '#46B8F3', //
scrollWidth: 4, //
scrollHeight: 8 //
}, },
yAxis: { yAxis: {
showTitle: true,
data: [{ data: [{
min: 0 min: 0,
title: '断面流量(万辆)',
titleFontSize: 12,
titleOffsetY: -5,
titleOffsetX: -5,
}] }]
}, },
legend: {}, legend: {},
@ -124,9 +142,9 @@ export default {
async getCurrentYearData() { async getCurrentYearData() {
const currentReq = { const currentReq = {
ProvinceCode: '530000', ProvinceCode: '530000',
StatisticsDate: moment().format('YYYY-MM-DD'), StatisticsDate: this.selectTime ? moment(this.selectTime).endOf('M').format('YYYY-MM-DD') : moment().format('YYYY-MM-DD'),
StartDate: moment().startOf('y').format('YYYY-MM-DD'), StartDate: this.selectTime ? moment(this.selectTime).startOf('y').format('YYYY-MM-DD') : moment().startOf('y').format('YYYY-MM-DD'),
EndDate: moment().endOf('M').format('YYYY-MM-DD'), EndDate: this.selectTime ? moment(this.selectTime).endOf('M').format('YYYY-MM-DD') : moment().endOf('M').format('YYYY-MM-DD'),
} }
return await request.$webGet( return await request.$webGet(
@ -139,9 +157,9 @@ export default {
async getPreviousYearData() { async getPreviousYearData() {
const previousReq = { const previousReq = {
ProvinceCode: '530000', ProvinceCode: '530000',
StatisticsDate: moment().subtract(1, 'y').endOf('M').format('YYYY-MM-DD'), StatisticsDate: this.selectTime ? moment(this.selectTime).subtract(1, 'y').endOf('M').format('YYYY-MM-DD') : moment().subtract(1, 'y').endOf('M').format('YYYY-MM-DD'),
StartDate: moment().subtract(1, 'y').startOf('y').format('YYYY-MM-DD'), StartDate: this.selectTime ? moment(this.selectTime).subtract(1, 'y').startOf('y').format('YYYY-MM-DD') : moment().subtract(1, 'y').startOf('y').format('YYYY-MM-DD'),
EndDate: moment().subtract(1, 'y').endOf('M').format('YYYY-MM-DD'), EndDate: this.selectTime ? moment(this.selectTime).subtract(1, 'y').endOf('M').format('YYYY-MM-DD') : moment().subtract(1, 'y').endOf('M').format('YYYY-MM-DD'),
} }
return await request.$webGet( return await request.$webGet(
@ -414,98 +432,37 @@ export default {
width: 100%; width: 100%;
height: 400rpx; height: 400rpx;
} }
}
}
.chart-legend { .chart-legend {
display: flex; display: flex;
justify-content: center; justify-content: center;
gap: 32rpx; gap: 32rpx;
margin-top: 16rpx; margin-top: 16rpx;
.legend-item { .legend-item {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 8rpx; gap: 8rpx;
.legend-dot { .legend-dot {
width: 12rpx; width: 12rpx;
height: 12rpx; height: 12rpx;
border-radius: 2rpx; border-radius: 2rpx;
&.current-year { &.current-year {
background: linear-gradient(135deg, #46B8F3, #1A4AF6); background: linear-gradient(135deg, #46B8F3, #1A4AF6);
} }
&.previous-year { &.previous-year {
background: #3CD495; background: #3CD495;
}
}
.legend-text {
font-size: 22rpx;
color: @text-secondary;
}
} }
} }
}
.monthly-data { .legend-text {
.data-table { font-size: 22rpx;
.table-header { color: @text-secondary;
display: flex;
background: #f5f5f5;
border-radius: 8rpx;
padding: 16rpx 0;
margin-bottom: 16rpx;
.header-cell {
flex: 1;
text-align: center;
font-size: 24rpx;
font-weight: 600;
color: @text-primary;
&:first-child {
flex: 0.8;
}
}
}
.table-row {
display: flex;
align-items: center;
padding: 12rpx 0;
border-bottom: 1rpx solid #f0f0f0;
&:last-child {
border-bottom: none;
}
.table-cell {
flex: 1;
text-align: center;
font-size: 24rpx;
color: @text-primary;
&.month-cell {
flex: 0.8;
font-weight: 500;
}
&.growth-positive {
color: @success-color;
font-weight: 600;
}
&.growth-negative {
color: @danger-color;
font-weight: 600;
}
&.growth-neutral {
color: @text-secondary;
}
}
}
} }
} }
} }

View File

@ -7,8 +7,11 @@
<!-- 经营效益图表 --> <!-- 经营效益图表 -->
<view class="chart-container"> <view class="chart-container">
<QiunDataCharts type="column" :opts="chartOpts" :chartData="chartData" :canvas2d="true" :inScrollView="true" <!-- 图表加载效果 -->
canvasId="vehicleModelStayChart" :animation="false" :ontap="true" :ontouch="true" <ChartLoading v-if="!hasChartData" text="数据加载中..." />
<!-- 实际图表 -->
<QiunDataCharts v-else type="column" :opts="chartOpts" :chartData="chartData" :canvas2d="true"
:inScrollView="true" canvasId="vehicleModelStayChart" :animation="false" :ontap="true" :ontouch="true"
tooltipFormat="vehicleModelStayChart" /> tooltipFormat="vehicleModelStayChart" />
</view> </view>
</view> </view>
@ -16,12 +19,14 @@
<script> <script>
import QiunDataCharts from './qiun-data-charts/components/qiun-data-charts/qiun-data-charts.vue' import QiunDataCharts from './qiun-data-charts/components/qiun-data-charts/qiun-data-charts.vue'
import ChartLoading from './ChartLoading.vue'
import request from "@/util/index.js"; import request from "@/util/index.js";
import moment from 'moment' import moment from 'moment'
export default { export default {
components: { components: {
QiunDataCharts QiunDataCharts,
ChartLoading
}, },
data() { data() {
@ -39,8 +44,18 @@ export default {
} }
} }
}, },
props: {
selectTime: {
type: String,
default: ""
},
},
computed: { computed: {
//
hasChartData() {
return this.rawData.category && this.rawData.category.length > 0
},
// //
chartData() { chartData() {
return { return {
@ -67,16 +82,15 @@ export default {
xAxis: { xAxis: {
disableGrid: true, disableGrid: true,
itemCount: 6, // 6 itemCount: 6, // 6
scrollShow: true, //
scrollAlign: 'left', //
scrollColor: '#46B8F3', //
scrollWidth: 4, //
scrollHeight: 8 //
}, },
yAxis: { yAxis: {
showTitle: true,
data: [{ data: [{
min: 0, min: 0,
title: '万元', title: '经济效益(万元)',
titleFontSize: 12,
titleOffsetY: -5,
titleOffsetX: 0,
}] }]
}, },
extra: { extra: {
@ -102,14 +116,14 @@ export default {
async handleGetVehicleModelStayData() { async handleGetVehicleModelStayData() {
// //
const currentReq = { const currentReq = {
StatisticsDate: moment().format('YYYY'), StatisticsDate: this.selectTime ? moment(this.selectTime).format('YYYY') : moment().format('YYYY'),
ProvinceCode: '530000', ProvinceCode: '530000',
StatisticsType: 4, StatisticsType: 4,
} }
// //
const lastYearReq = { const lastYearReq = {
StatisticsDate: moment().subtract(1, 'y').format('YYYY'), StatisticsDate: this.selectTime ? moment(this.selectTime).subtract(1, 'y').format('YYYY') : moment().subtract(1, 'y').format('YYYY'),
ProvinceCode: '530000', ProvinceCode: '530000',
StatisticsType: 4, StatisticsType: 4,
} }

View File

@ -7,7 +7,10 @@
<!-- 入区车流图表 --> <!-- 入区车流图表 -->
<view class="chart-container"> <view class="chart-container">
<QiunDataCharts type="column" :opts="vehicleChartOpts" :chartData="vehicleChartData" :canvas2d="true" <!-- 图表加载效果 -->
<ChartLoading v-if="!hasVehicleChartData" text="数据加载中..." />
<!-- 实际图表 -->
<QiunDataCharts v-else type="column" :opts="vehicleChartOpts" :chartData="vehicleChartData" :canvas2d="true"
:inScrollView="true" canvasId="vehicleChart" :animation="false" :ontap="true" :ontouch="true" :inScrollView="true" canvasId="vehicleChart" :animation="false" :ontap="true" :ontouch="true"
tooltipFormat="vehicleChartData" /> tooltipFormat="vehicleChartData" />
</view> </view>
@ -19,7 +22,10 @@
<!-- 对客营收图表 --> <!-- 对客营收图表 -->
<view class="chart-container"> <view class="chart-container">
<QiunDataCharts type="line" :opts="revenueChartOpts" :chartData="revenueChartData" :canvas2d="true" <!-- 图表加载效果 -->
<ChartLoading v-if="!hasRevenueChartData" text="数据加载中..." />
<!-- 实际图表 -->
<QiunDataCharts v-else type="line" :opts="revenueChartOpts" :chartData="revenueChartData" :canvas2d="true"
:inScrollView="true" canvasId="revenueChart" :animation="false" :ontap="true" :ontouch="true" :inScrollView="true" canvasId="revenueChart" :animation="false" :ontap="true" :ontouch="true"
tooltipFormat="revenueChartDataVehicles" /> tooltipFormat="revenueChartDataVehicles" />
</view> </view>
@ -28,12 +34,14 @@
<script> <script>
import QiunDataCharts from './qiun-data-charts/components/qiun-data-charts/qiun-data-charts.vue' import QiunDataCharts from './qiun-data-charts/components/qiun-data-charts/qiun-data-charts.vue'
import ChartLoading from './ChartLoading.vue'
import request from "@/util/index.js"; import request from "@/util/index.js";
import moment from 'moment' import moment from 'moment'
export default { export default {
components: { components: {
QiunDataCharts QiunDataCharts,
ChartLoading
}, },
data() { data() {
@ -57,7 +65,24 @@ export default {
} }
}, },
props: {
selectTime: {
type: String,
default: ""
},
},
computed: { computed: {
//
hasVehicleChartData() {
return this.chartData.category && this.chartData.category.length > 0
},
//
hasRevenueChartData() {
return this.chartData.category && this.chartData.category.length > 0
},
// //
vehicleChartData() { vehicleChartData() {
return { return {
@ -84,16 +109,15 @@ export default {
xAxis: { xAxis: {
disableGrid: true, disableGrid: true,
itemCount: 6, // 6 itemCount: 6, // 6
scrollShow: true, //
scrollAlign: 'left', //
scrollColor: '#46B8F3', //
scrollWidth: 4, //
scrollHeight: 8 //
}, },
yAxis: { yAxis: {
showTitle: true,
data: [{ data: [{
min: 0, min: 0,
title: '万辆', title: '入区车流(万辆)',
titleFontSize: 12,
titleOffsetY: -5,
titleOffsetX: 0,
}] }]
}, },
extra: { extra: {
@ -135,20 +159,17 @@ export default {
enableScroll: true, // enableScroll: true, //
xAxis: { xAxis: {
disableGrid: true, disableGrid: true,
scrollShow: true, //
scrollAlign: 'left', //
itemCount: 6, // 6 itemCount: 6, // 6
scrollWidth: 4, //
scrollHeight: 8 //
}, },
yAxis: { yAxis: {
gridType: 'dash', gridType: 'dash',
dashLength: 2, dashLength: 2,
showTitle: true,
data: [{ data: [{
min: 0, min: 0,
title: '万元', title: '对客营收(万元)',
titleFontSize: 12, titleFontSize: 12,
titleOffsetY: -4, titleOffsetY: -5,
titleOffsetX: 0 titleOffsetX: 0
}], }],
splitNumber: 5 splitNumber: 5
@ -180,15 +201,15 @@ export default {
async handleGetSectionFlowCount() { async handleGetSectionFlowCount() {
// //
const currentReq = { const currentReq = {
StartDate: moment().startOf('y').format('YYYY-MM-DD'), StartDate: this.selectTime ? moment(this.selectTime).startOf('y').format('YYYY-MM-DD') : moment().startOf('y').format('YYYY-MM-DD'),
EndDate: moment().subtract(1, 'd').format('YYYY-MM-DD'), EndDate: this.selectTime ? moment(this.selectTime).subtract(1, 'd').format('YYYY-MM-DD') : moment().subtract(1, 'd').format('YYYY-MM-DD'),
ProvinceCode: 530000 ProvinceCode: 530000
} }
// //
const lastYearReq = { const lastYearReq = {
StartDate: moment().subtract(1, 'y').startOf('y').format('YYYY-MM-DD'), StartDate: this.selectTime ? moment(this.selectTime).subtract(1, 'y').startOf('y').format('YYYY-MM-DD') : moment().subtract(1, 'y').startOf('y').format('YYYY-MM-DD'),
EndDate: moment().subtract(1, 'y').endOf('y').format('YYYY-MM-DD'), EndDate: this.selectTime ? moment(this.selectTime).subtract(1, 'y').endOf('y').format('YYYY-MM-DD') : moment().subtract(1, 'y').endOf('y').format('YYYY-MM-DD'),
ProvinceCode: 530000 ProvinceCode: 530000
} }
@ -208,7 +229,6 @@ export default {
"CommercialApi/BigData/GetMonthAnalysis", "CommercialApi/BigData/GetMonthAnalysis",
params params
); );
console.log('入区车流数据', data);
return data || [] return data || []
}, },
@ -287,7 +307,6 @@ export default {
revenueAdd: revenueAdd revenueAdd: revenueAdd
} }
console.log('处理后的图表数据', this.chartData)
}, },
} }

View File

@ -108,16 +108,22 @@ const cfu = {
return `${item.name}${item.data}` return `${item.name}${item.data}`
}, },
"festivalRevenueSumInfoChart": function (item, category, index, opts) { "festivalRevenueSumInfoChart": function (item, category, index, opts) {
// console.log('', item);
// console.log('', category);
// console.log('', index);
// console.log('', opts);
return `${item.name}` return `${item.name}`
}, },
"businessStructureChart": function (item, category, index, opts) { "businessStructureChart": function (item, category, index, opts) {
return `${opts.realData[index].data}`
return `${opts.legendData[index].name}占比:${opts.legendData[index].value}${opts.realData[index].data}`
}, },
"regionalRevenueChart": function (item, category, index, opts) { "regionalRevenueChart": function (item, category, index, opts) {
return `${item.name}${item.data}万元` return `${item.name}占比${opts.percentageList[index].value}${item.data}万元`
}, },
"businessCaseChart": function (item, category, index, opts) { "businessCaseChart": function (item, category, index, opts) {
return `${category}${item.name}${item.data}万元`
return `${category}${item.name}${item.data}${opts.unitType === 1 ? '万元' : opts.unitType === 2 ? '万笔' : opts.unitType === 3 ? '元' : ''}`
}, },
"BrandConsumptionLevel": function (item, category, index, opts) { "BrandConsumptionLevel": function (item, category, index, opts) {
return `${item.name}占比:${item.data}%` return `${item.name}占比:${item.data}%`
@ -159,7 +165,7 @@ const cfu = {
return `${item.name}${item.data}` return `${item.name}${item.data}`
}, },
"facilityChartData": function (item, category, index, opts) { "facilityChartData": function (item, category, index, opts) {
return `${category}${item.name}${item.data}` return `${category}${item.name}${item.data}`
}, },
"distributionChartData": function (item, category, index, opts) { "distributionChartData": function (item, category, index, opts) {
return `${item.name}${item.data}` return `${item.name}${item.data}`

View File

@ -3,7 +3,8 @@
<scroll-view scroll-y @scroll="handleScroll" class="digital-dashboard" :scroll-into-view="scrollIntoView" <scroll-view scroll-y @scroll="handleScroll" class="digital-dashboard" :scroll-into-view="scrollIntoView"
:scroll-with-animation="true"> :scroll-with-animation="true">
<!-- Tab切换区域 --> <!-- Tab切换区域 -->
<scroll-view scroll-x class="tab-container" :scroll-into-view="scrollIntoTabItem" :scroll-with-animation="true"> <scroll-view scroll-x class="tab-container" :scroll-with-animation="true" :scroll-left="tabScrollPosition"
show-scrollbar="false">
<view class="tab-list"> <view class="tab-list">
<view v-for="(tab, index) in tabList" :key="index" :id="`tab-${index}`" class="tab-item" <view v-for="(tab, index) in tabList" :key="index" :id="`tab-${index}`" class="tab-item"
:class="{ active: activeTab === index }" @click="switchTab(index)"> :class="{ active: activeTab === index }" @click="switchTab(index)">
@ -24,7 +25,7 @@
</view> </view>
</view> </view>
<view class="nav-list" v-show="!isNavCollapsed"> <view class="nav-list" v-show="!isNavCollapsed">
<view v-for="(item, index) in currentNavItems" :key="item.id" class="nav-item" <view v-for="item in currentNavItems" :key="item.id" class="nav-item"
:class="{ active: activeNavItem === item.id }" @click="scrollToComponent(item.id)"> :class="{ active: activeNavItem === item.id }" @click="scrollToComponent(item.id)">
<text class="nav-text">{{ item.name }}</text> <text class="nav-text">{{ item.name }}</text>
<view class="nav-dot" v-if="activeNavItem === item.id"></view> <view class="nav-dot" v-if="activeNavItem === item.id"></view>
@ -32,9 +33,19 @@
</view> </view>
</view> </view>
</view> </view>
<view id="top"> </view> <view id="top"> </view>
<!-- 内容展示区域 --> <!-- 内容展示区域 -->
<view class="content-container"> <view class="content-container">
<!-- 时间选择 -->
<view class="timeBox">
<picker mode="date" @change="bindDateChange" :value="selectTime" fields="month">
统计时间{{ selectTime }}
</picker>
</view>
<!-- 实时运营监控中心 --> <!-- 实时运营监控中心 -->
<view v-if="activeTab === 0" class="tab-content"> <view v-if="activeTab === 0" class="tab-content">
<!-- 服务区概况 --> <!-- 服务区概况 -->
@ -47,69 +58,69 @@
<!-- 断面流量 --> <!-- 断面流量 -->
<view id="trend-of-trafficFlow"></view> <view id="trend-of-trafficFlow"></view>
<TrendOfTrafficFlow /> <TrendOfTrafficFlow :selectTime="selectTime" />
<!-- 入区车流 --> <!-- 入区车流 -->
<view id="vehicles-entering"></view> <view id="vehicles-entering"></view>
<VehiclesEntering /> <VehiclesEntering :selectTime="selectTime" />
<!-- 经营效益 --> <!-- 经营效益 -->
<view id="vehicle-model-stay"></view> <view id="vehicle-model-stay"></view>
<VehicleModelStay /> <VehicleModelStay :selectTime="selectTime" />
</view> </view>
<!-- 客群画像与消费行为分析 --> <!-- 客群画像与消费行为分析 -->
<view v-if="activeTab === 1" class="tab-content"> <view v-if="activeTab === 1" class="tab-content">
<!-- 年龄画像 --> <!-- 年龄画像 -->
<view id="customer-age-group"></view> <view id="customer-age-group"></view>
<CustomerAgeGroup /> <CustomerAgeGroup :selectTime="selectTime" />
<!-- 性别画像 --> <!-- 性别画像 -->
<view id="gender-customer-group"></view> <view id="gender-customer-group"></view>
<GenderCustomerGroup /> <GenderCustomerGroup :selectTime="selectTime" />
<!-- 偏好类型 --> <!-- 偏好类型 -->
<view id="preference-type"></view> <view id="preference-type"></view>
<PreferenceType /> <PreferenceType :selectTime="selectTime" />
<!-- 客群特征分析 --> <!-- 客群特征分析 -->
<view id="customer-group"></view> <view id="customer-group"></view>
<CustomerGroup /> <CustomerGroup :selectTime="selectTime" />
<!-- 客群消费偏好 --> <!-- 客群消费偏好 -->
<view id="customer-consumption-preferences"></view> <view id="customer-consumption-preferences"></view>
<CustomerConsumptionPreferences /> <CustomerConsumptionPreferences :selectTime="selectTime" />
<!-- 消费转化率对比图 --> <!-- 消费转化率对比图 -->
<view id="consumption-conversion"></view> <view id="consumption-conversion"></view>
<ConsumptionConversion /> <ConsumptionConversion :selectTime="selectTime" />
<!-- 消费水平 --> <!-- 消费水平 -->
<view id="consumption-level"></view> <view id="consumption-level"></view>
<ConsumptionLevel /> <ConsumptionLevel :selectTime="selectTime" />
<!-- 消费时段分析 --> <!-- 消费时段分析 -->
<view id="consumption-period"></view> <view id="consumption-period"></view>
<ConsumptionPeriod /> <ConsumptionPeriod :selectTime="selectTime" />
<!-- 品牌消费水平 --> <!-- 品牌消费水平 -->
<view id="brand-consumption-level"></view> <view id="brand-consumption-level"></view>
<BrandConsumptionLevel /> <BrandConsumptionLevel :selectTime="selectTime" />
</view> </view>
<!-- 多维度经营数据分析 --> <!-- 多维度经营数据分析 -->
<view v-if="activeTab === 2" class="tab-content"> <view v-if="activeTab === 2" class="tab-content">
<!-- 营收特征 --> <!-- 营收特征 -->
<view id="business-case"></view> <view id="business-case"></view>
<BusinessCase /> <BusinessCase :selectTime="selectTime" />
<!-- 区域营收占比 --> <!-- 区域营收占比 -->
<view id="regional-revenue"></view> <view id="regional-revenue"></view>
<RegionalRevenue /> <RegionalRevenue :selectTime="selectTime" />
<!-- 业态结构占比 --> <!-- 业态结构占比 -->
<view id="business-structure"></view> <view id="business-structure"></view>
<BusinessStructure /> <BusinessStructure :selectTime="selectTime" />
<!-- 节假日营收 --> <!-- 节假日营收 -->
<view id="festival-revenue-sum-info"></view> <view id="festival-revenue-sum-info"></view>
@ -121,7 +132,7 @@
<view v-if="activeTab === 3" class="tab-content"> <view v-if="activeTab === 3" class="tab-content">
<!-- 会员商城 --> <!-- 会员商城 -->
<view id="member-mall"></view> <view id="member-mall"></view>
<MemberMall /> <MemberMall :selectTime="selectTime" />
<!-- 热门商品榜单 --> <!-- 热门商品榜单 -->
<view id="hot-product-list"></view> <view id="hot-product-list"></view>
@ -133,15 +144,15 @@
<!-- 供应商列表 --> <!-- 供应商列表 -->
<view id="supplier-list-box"></view> <view id="supplier-list-box"></view>
<SupplierListBox /> <SupplierListBox :selectTime="selectTime" />
<!-- 商城订单统计 --> <!-- 商城订单统计 -->
<view id="mall-order-statistics"></view> <view id="mall-order-statistics"></view>
<MallOrderStatistics /> <MallOrderStatistics :selectTime="selectTime" />
<!-- 本月福利金发送额度 --> <!-- 本月福利金发送额度 -->
<view id="this-month-benefits"></view> <view id="this-month-benefits"></view>
<ThisMonthBenefits /> <ThisMonthBenefits :selectTime="selectTime" />
<!-- 会员消费数据分析 --> <!-- 会员消费数据分析 -->
<view id="analysis-of-member"></view> <view id="analysis-of-member"></view>
@ -177,6 +188,7 @@ import SupplierListBox from './components/SupplierListBox.vue'
import MallOrderStatistics from './components/MallOrderStatistics.vue' import MallOrderStatistics from './components/MallOrderStatistics.vue'
import ThisMonthBenefits from './components/ThisMonthBenefits.vue' import ThisMonthBenefits from './components/ThisMonthBenefits.vue'
import AnalysisOfMember from './components/AnalysisOfMember.vue' import AnalysisOfMember from './components/AnalysisOfMember.vue'
import moment from 'moment'
export default { export default {
@ -260,7 +272,8 @@ export default {
sessionData: {}, sessionData: {},
pageScrollTop: 0, pageScrollTop: 0,
scrollIntoView: "", scrollIntoView: "",
scrollIntoTabItem: "" tabScrollPosition: 0,
selectTime: moment().subtract(1, 'M').format('YYYY-MM')
} }
}, },
computed: { computed: {
@ -289,14 +302,25 @@ export default {
} }
}, },
methods: { methods: {
bindDateChange(e) {
console.log('eeeee', e);
this.selectTime = e.detail.value
},
switchTab(index) { switchTab(index) {
this.scrollIntoView = 'top' this.scrollIntoView = 'top'
this.activeTab = index; this.activeTab = index;
this.scrollIntoTabItem = `tab-${index}`
// //
this.fetchTabData(index); this.fetchTabData(index);
console.log('this.scrollIntoTabItemthis.scrollIntoTabItem', this.scrollIntoTabItem); // 使
// Tab 200rpx (100px)
const avgTabWidth = 100;
const targetPosition = index * avgTabWidth;
console.log('Switching to tab:', index, 'scrolling to:', targetPosition);
//
this.tabScrollPosition = targetPosition;
}, },
// //
@ -315,6 +339,9 @@ export default {
this.pageScrollTop = e.detail.scrollTop this.pageScrollTop = e.detail.scrollTop
}, },
// tab // tab
async fetchTabData(tabIndex) { async fetchTabData(tabIndex) {
// Tab // Tab
@ -350,10 +377,10 @@ export default {
.tab-container { .tab-container {
background: @bg-white; background: @bg-white;
box-shadow: @shadow-light; box-shadow: @shadow-light;
// position: sticky;
position: fixed; position: fixed;
top: 0; top: 0;
z-index: 100; z-index: 100;
width: 100%;
.tab-list { .tab-list {
height: 80rpx; height: 80rpx;
@ -361,306 +388,308 @@ export default {
padding: 0 32rpx; padding: 0 32rpx;
box-sizing: border-box; box-sizing: border-box;
position: relative; position: relative;
width: 100%; width: max-content;
overflow-x: auto; white-space: nowrap;
scrollbar-width: none; }
/* 隐藏滚动条 Firefox */
-ms-overflow-style: none;
/* 隐藏滚动条 IE/Edge */
&::-webkit-scrollbar { /* 隐藏滚动条 */
display: none; ::-webkit-scrollbar {
/* 隐藏滚动条 Chrome/Safari */ display: none;
width: 0;
height: 0;
color: transparent;
}
.tab-item {
position: relative;
padding: 16rpx 24rpx;
margin-right: 16rpx;
flex-shrink: 0;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
cursor: pointer;
min-width: fit-content;
display: inline-block;
&.active {
.tab-text {
color: @primary-color;
font-weight: 600;
transform: translateY(-1px);
}
.tab-indicator {
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
width: 48rpx;
height: 6rpx;
background: linear-gradient(90deg, @primary-color, @secondary-color);
border-radius: 3rpx;
animation: slideIn 0.3s ease-out;
}
} }
.tab-item { .tab-text {
position: relative; font-size: 28rpx;
padding: 16rpx 24rpx; color: @text-secondary;
margin-right: 16rpx;
flex-shrink: 0;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
cursor: pointer; white-space: nowrap;
min-width: fit-content; position: relative;
&:last-child { &::after {
margin-right: 0; content: '';
position: absolute;
bottom: -4rpx;
left: 0;
width: 100%;
height: 2rpx;
background: @primary-color;
transform: scaleX(0);
transition: transform 0.3s ease;
} }
}
&.active { &:active {
.tab-text { transform: scale(0.95);
color: @primary-color;
font-weight: 600;
transform: translateY(-1px);
}
.tab-indicator {
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
width: 48rpx;
height: 6rpx;
background: linear-gradient(90deg, @primary-color, @secondary-color);
border-radius: 3rpx;
animation: slideIn 0.3s ease-out;
}
}
.tab-text {
font-size: 28rpx;
color: @text-secondary;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
white-space: nowrap;
position: relative;
&::after {
content: '';
position: absolute;
bottom: -4rpx;
left: 0;
width: 100%;
height: 2rpx;
background: @primary-color;
transform: scaleX(0);
transition: transform 0.3s ease;
}
}
&:active {
transform: scale(0.95);
}
} }
} }
} }
}
.content-container { .content-container {
padding: 32rpx; padding: 32rpx;
padding-top: 92rpx; padding-top: 92rpx;
.tab-content { .tab-content {
/* 移除切换动画 */ /* 移除切换动画 */
.chart-grid { .chart-grid {
.chart-row { .chart-row {
margin-bottom: 24rpx; margin-bottom: 24rpx;
.chart-card { .chart-card {
background: @bg-white; background: @bg-white;
border-radius: @border-radius; border-radius: @border-radius;
padding: 24rpx; padding: 24rpx;
box-shadow: @shadow; box-shadow: @shadow;
transition: all 0.3s ease; transition: all 0.3s ease;
position: relative;
overflow: hidden;
box-sizing: border-box;
&::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 2rpx;
background: linear-gradient(90deg, @primary-color, @secondary-color);
opacity: 0;
transition: opacity 0.3s ease;
}
&:active {
transform: translateY(-2rpx);
box-shadow: 0 8px 30px rgba(0, 0, 0, 0.12);
&::before {
opacity: 1;
}
}
&.full {
width: 100%;
min-height: 400rpx;
}
.chart-header {
margin-bottom: 20rpx;
.chart-title {
font-size: 28rpx;
font-weight: 600;
color: @text-primary;
margin-bottom: 4rpx;
}
.chart-subtitle {
font-size: 22rpx;
color: @text-light;
}
}
.chart-placeholder {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 300rpx;
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
border-radius: 12rpx;
position: relative; position: relative;
overflow: hidden; overflow: hidden;
box-sizing: border-box;
&.large {
height: 400rpx;
}
&::before { &::before {
content: ''; content: '';
position: absolute; position: absolute;
top: 0; top: -50%;
left: 0; left: -50%;
right: 0; width: 200%;
height: 2rpx; height: 200%;
background: linear-gradient(90deg, @primary-color, @secondary-color); background: radial-gradient(circle, rgba(103, 126, 234, 0.1) 0%, transparent 70%);
opacity: 0; animation: rotate 30s infinite linear;
transition: opacity 0.3s ease;
} }
&:active { .placeholder-text {
transform: translateY(-2rpx); font-size: 32rpx;
box-shadow: 0 8px 30px rgba(0, 0, 0, 0.12); color: @text-secondary;
margin-bottom: 8rpx;
&::before {
opacity: 1;
}
}
&.full {
width: 100%;
min-height: 400rpx;
}
.chart-header {
margin-bottom: 20rpx;
.chart-title {
font-size: 28rpx;
font-weight: 600;
color: @text-primary;
margin-bottom: 4rpx;
}
.chart-subtitle {
font-size: 22rpx;
color: @text-light;
}
}
.chart-placeholder {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 300rpx;
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
border-radius: 12rpx;
position: relative; position: relative;
overflow: hidden; z-index: 1;
}
&.large { .placeholder-desc {
height: 400rpx; font-size: 24rpx;
} color: @text-light;
position: relative;
&::before { z-index: 1;
content: '';
position: absolute;
top: -50%;
left: -50%;
width: 200%;
height: 200%;
background: radial-gradient(circle, rgba(103, 126, 234, 0.1) 0%, transparent 70%);
animation: rotate 30s infinite linear;
}
.placeholder-text {
font-size: 32rpx;
color: @text-secondary;
margin-bottom: 8rpx;
position: relative;
z-index: 1;
}
.placeholder-desc {
font-size: 24rpx;
color: @text-light;
position: relative;
z-index: 1;
}
} }
} }
} }
} }
} }
} }
}
.side-navigation { .timeBox {
position: fixed; width: 100%;
right: 24rpx; display: flex;
top: 50%; justify-content: flex-end;
transform: translateY(-50%); }
z-index: 1000;
background: rgba(255, 255, 255, 0.95);
backdrop-filter: blur(10px);
border-radius: 16rpx;
box-shadow: @shadow;
border: 1rpx solid rgba(255, 255, 255, 0.2);
max-height: 70vh;
overflow-y: auto;
transition: all 0.3s ease;
&::-webkit-scrollbar { .side-navigation {
width: 4rpx; position: fixed;
right: 24rpx;
top: 50%;
transform: translateY(-50%);
z-index: 1000;
background: rgba(255, 255, 255, 0.95);
backdrop-filter: blur(10px);
border-radius: 16rpx;
box-shadow: @shadow;
border: 1rpx solid rgba(255, 255, 255, 0.2);
max-height: 70vh;
overflow-y: auto;
transition: all 0.3s ease;
&::-webkit-scrollbar {
width: 4rpx;
}
&::-webkit-scrollbar-track {
background: rgba(0, 0, 0, 0.1);
border-radius: 2rpx;
}
&::-webkit-scrollbar-thumb {
background: @primary-color;
border-radius: 2rpx;
}
//
&.collapsed {
min-width: auto;
max-width: auto;
.nav-container {
padding: 0;
} }
}
&::-webkit-scrollbar-track { .nav-container {
background: rgba(0, 0, 0, 0.1); padding: 0 16rpx;
border-radius: 2rpx;
}
&::-webkit-scrollbar-thumb { .nav-header {
background: @primary-color; display: flex;
border-radius: 2rpx; align-items: center;
} justify-content: space-between;
padding: 16rpx;
border-bottom: 1rpx solid #f0f0f0;
margin-bottom: 8rpx;
cursor: pointer;
// .nav-title {
&.collapsed { font-size: 24rpx;
min-width: auto; font-weight: 600;
max-width: auto; color: @text-primary;
}
.nav-container { .nav-toggle {
padding: 0; .toggle-icon {
font-size: 20rpx;
color: @text-secondary;
transition: transform 0.3s ease;
&.rotated {
transform: rotate(180deg);
}
}
}
&:hover {
background: rgba(102, 126, 234, 0.05);
border-radius: 8rpx;
} }
} }
.nav-container { .nav-list {
padding: 0 16rpx; .nav-item {
position: relative;
.nav-header { padding: 16rpx 20rpx;
margin-bottom: 8rpx;
border-radius: 12rpx;
cursor: pointer;
transition: all 0.3s ease;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
padding: 16rpx;
border-bottom: 1rpx solid #f0f0f0;
margin-bottom: 8rpx;
cursor: pointer;
.nav-title {
font-size: 24rpx;
font-weight: 600;
color: @text-primary;
}
.nav-toggle {
.toggle-icon {
font-size: 20rpx;
color: @text-secondary;
transition: transform 0.3s ease;
&.rotated {
transform: rotate(180deg);
}
}
}
&:hover { &:hover {
background: rgba(102, 126, 234, 0.05); background: rgba(102, 126, 234, 0.1);
border-radius: 8rpx; transform: translateX(-4rpx);
} }
}
.nav-list { &.active {
.nav-item { background: linear-gradient(90deg, rgba(102, 126, 234, 0.15), rgba(118, 75, 162, 0.15));
position: relative; border-left: 4rpx solid @primary-color;
padding: 16rpx 20rpx; padding-left: 16rpx;
margin-bottom: 8rpx;
border-radius: 12rpx;
cursor: pointer;
transition: all 0.3s ease;
display: flex;
align-items: center;
justify-content: space-between;
&:hover {
background: rgba(102, 126, 234, 0.1);
transform: translateX(-4rpx);
}
&.active {
background: linear-gradient(90deg, rgba(102, 126, 234, 0.15), rgba(118, 75, 162, 0.15));
border-left: 4rpx solid @primary-color;
padding-left: 16rpx;
.nav-text {
color: @primary-color;
font-weight: 600;
}
}
.nav-text { .nav-text {
font-size: 22rpx; color: @primary-color;
color: @text-secondary; font-weight: 600;
line-height: 1.4;
flex: 1;
transition: all 0.3s ease;
} }
}
.nav-dot { .nav-text {
width: 8rpx; font-size: 22rpx;
height: 8rpx; color: @text-secondary;
background: @primary-color; line-height: 1.4;
border-radius: 50%; flex: 1;
animation: pulse 2s infinite; transition: all 0.3s ease;
} }
.nav-dot {
width: 8rpx;
height: 8rpx;
background: @primary-color;
border-radius: 50%;
animation: pulse 2s infinite;
} }
} }
} }

View File

@ -118,7 +118,6 @@ const actions = {
let res = await request.$get('WeChat_GetBusinessMemberInfo', { Membership_Id: _id }) let res = await request.$get('WeChat_GetBusinessMemberInfo', { Membership_Id: _id })
if (res.Result_Code == 100) { if (res.Result_Code == 100) {
let data = res.Result_Data let data = res.Result_Data
console.log('WeChat_GetBusinessMemberInfoWeChat_GetBusinessMemberInfo', data);
commit('setUser', data) commit('setUser', data)
data.WeChat_MiniProToken = _user.WeChat_MiniProToken data.WeChat_MiniProToken = _user.WeChat_MiniProToken