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"]),
...mapMutations(["setVisitChannels"]),
handleGetUserInfo() {
wx.request({
url: "https://qifu-api.baidubce.com/ip/local/geo/v1/district",
success(response) {
const data = response.data;
//
let obj = {
...data.data,
ip: data.ip,
};
uni.setStorageSync("userInfo", obj);
},
fail(error) {
//
},
});
// wx.request({
// url: "https://qifu-api.baidubce.com/ip/local/geo/v1/district",
// success(response) {
// const data = response.data;
// //
// let obj = {
// ...data.data,
// ip: data.ip,
// };
// uni.setStorageSync("userInfo", obj);
// },
// fail(error) {
// //
// },
// });
},
},
onLaunch: async function (options) {

View File

@ -3,7 +3,10 @@
<!-- 会员分析图表 -->
<view class="chart-card">
<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"
:ontouch="true" tooltipFormat="AnalysisOfMember" />
</view>
@ -13,12 +16,14 @@
<script>
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 moment from 'moment'
export default {
components: {
QiunDataCharts
QiunDataCharts,
ChartLoading
},
data() {
@ -34,6 +39,13 @@ export default {
},
computed: {
//
hasChartData() {
return this.rawData.category.length > 0 &&
this.rawData.weeklyData.length > 0 &&
this.rawData.otherData.length > 0
},
//
chartData() {
return {
@ -56,7 +68,7 @@ export default {
//
chartOpts() {
return {
padding: [15, 15, 15, 15],
padding: [15, 15, 0, 15],
dataLabel: false,
enableScroll: true,
dataPointShape: false,
@ -65,14 +77,15 @@ export default {
itemCount: 4 // 4
},
yAxis: {
showTitle: true,
titleFontSize: 12,
titleOffsetY: 10,
titleOffsetX: 10,
min: 0,
data: [{
min: 0,
max: 100,
title: '百分比(%)',
titleFontSize: 12,
titleOffsetY: 0,
unit: '%',
format: 'value' //
}]
},
legend: {

View File

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

View File

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

View File

@ -20,8 +20,10 @@
<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"
tooltipFormat="businessCaseChart" />
</view>
@ -32,12 +34,14 @@
<script>
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 moment from 'moment'
export default {
components: {
QiunDataCharts
QiunDataCharts,
ChartLoading
},
data() {
@ -60,8 +64,19 @@ export default {
}
}
},
props: {
selectTime: {
type: String,
default: ""
},
},
computed: {
//
hasChartData() {
return this.rawData.category.length > 0 &&
this.rawData.seriesData.length > 0
},
//
chartData() {
return {
@ -73,7 +88,7 @@ export default {
//
chartOpts() {
return {
padding: [15, 15, 15, 15], // paddingpicker
padding: [15, 15, 0, 15], // paddingpicker
dataLabel: false,
enableScroll: true,
xAxis: {
@ -81,9 +96,13 @@ export default {
itemCount: 4,
},
yAxis: {
showTitle: true,
data: [{
min: 0,
title: this.getYAxisTitle()
title: this.getYAxisTitle(),
titleFontSize: 12,
titleOffsetY: -5,
titleOffsetX: 10,
}]
},
legend: {
@ -108,7 +127,8 @@ export default {
seriesGap: 0,
barBorderRadius: [3, 3, 0, 0]
}
}
},
unitType: this.selectTab
}
}
},
@ -122,7 +142,7 @@ export default {
async handleGetBusinessCaseData() {
const req = {
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
}

View File

@ -7,8 +7,11 @@
<!-- 业态结构占比图表 -->
<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" />
</view>
</view>
@ -16,14 +19,21 @@
<script>
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 moment from 'moment'
export default {
components: {
QiunDataCharts
QiunDataCharts,
ChartLoading
},
props: {
selectTime: {
type: String,
default: ""
},
},
data() {
return {
//
@ -35,6 +45,11 @@ export default {
},
computed: {
//
hasChartData() {
return this.rawData.seriesData.length > 0
},
//
chartData() {
return {
@ -47,34 +62,28 @@ export default {
//
chartOpts() {
return {
padding: [15, 15, 15, 15],
padding: [15, 62, 0, 15],
dataLabel: false,
legend: {
show: true,
position: 'right',
float: 'center',
backgroundColor: 'rgba(0,0,0,0)',
borderColor: 'rgba(0,0,0,0)',
fontSize: 12,
fontColor: '#333333',
margin: 0,
padding: 0,
itemGap: 10,
textAlign: 'left'
},
extra: {
pie: {
activeOpacity: 0.5,
activeRadius: 10,
offsetAngle: 0,
labelWidth: 0,
border: false,
borderWidth: 2,
borderColor: '#FFFFFF',
linearType: 'custom'
}
},
realData: this.rawData.seriesData
realData: this.rawData.seriesData,
legendData: this.rawData.legendData
}
}
},
@ -88,7 +97,7 @@ export default {
async handleGetBusinessStructureData() {
const req = {
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,
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">
<QiunDataCharts type="line" :opts="chartOpts" :chartData="chartData" :canvas2d="true" :inScrollView="true"
canvasId="consumptionConversionChart" :animation="false" :ontap="true" :ontouch="true"
tooltipFormat="ConsumptionConversion" />
<!-- 图表加载效果 -->
<ChartLoading v-if="!hasChartData" text="数据加载中..." />
<!-- 实际图表 -->
<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>
</template>
<script>
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 moment from 'moment'
export default {
components: {
QiunDataCharts
QiunDataCharts,
ChartLoading
},
data() {
@ -38,6 +43,13 @@ export default {
},
computed: {
//
hasChartData() {
return this.rawData.category.length > 0 &&
this.rawData.carResList.length > 0 &&
this.rawData.orderResList.length > 0
},
//
chartData() {
return {
@ -58,27 +70,28 @@ export default {
//
chartOpts() {
return {
padding: [15, 15, 15, 15],
padding: [15, 15, 0, 15],
dataLabel: false,
enableScroll: true,
enableScroll: false, //
dataPointShape: true,
xAxis: {
disableGrid: true,
itemCount: 8, //
itemCount: this.rawData.category.length || 7, //
},
yAxis: {
showTitle: true,
data: [
{
title: '车流量(辆)',
titleFontSize: 12,
titleOffsetY: 0,
titleOffsetY: -5,
titleOffsetX: 0,
position: 'left'
},
{
title: '客单量(笔)',
titleFontSize: 12,
titleOffsetY: 0,
titleOffsetY: -5,
titleOffsetX: 0,
position: 'right'
}
@ -124,7 +137,7 @@ export default {
async handleGetConsumptionConversionData() {
const req = {
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
}
@ -151,25 +164,66 @@ export default {
let orderResList = []
let orderRealResList = []
//
//
let carDataMap = {}
let orderDataMap = {}
let availableHours = new Set()
//
if (data.BayonetList && data.BayonetList.data && data.BayonetList.data.length > 0) {
let carList = data.BayonetList.data
carList.forEach((item) => {
carResList.push(Number(item[1]))
carRealResList.push(item[1])
const hour = parseInt(item[0])
carDataMap[hour] = Number(item[1])
availableHours.add(hour)
})
}
//
//
if (data.TransactionList && data.TransactionList.data && data.TransactionList.data.length > 0) {
let orderList = data.TransactionList.data
orderList.forEach((item) => {
category.push(`${item[0]}`)
orderResList.push(Number(item[1]))
orderRealResList.push(item[1])
const hour = parseInt(item[0])
orderDataMap[hour] = Number(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 = {
category: category,

View File

@ -8,8 +8,11 @@
<!-- 消费水平图表 -->
<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" />
</view>
</view>
@ -17,12 +20,14 @@
<script>
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 moment from 'moment'
export default {
components: {
QiunDataCharts
QiunDataCharts,
ChartLoading
},
data() {
@ -34,8 +39,19 @@ export default {
}
}
},
props: {
selectTime: {
type: String,
default: ""
},
},
computed: {
//
hasChartData() {
return this.rawData.category.length > 0 &&
this.rawData.seriesData.length > 0
},
//
chartData() {
return {
@ -47,7 +63,7 @@ export default {
//
chartOpts() {
return {
padding: [15, 15, 15, 15],
padding: [15, 15, 0, 15],
dataLabel: false,
enableScroll: true,
xAxis: {
@ -56,9 +72,13 @@ export default {
margin: 15
},
yAxis: {
showTitle: true,
data: [{
min: 0,
title: '%'
title: '百分比(%)',
titleFontSize: 12,
titleOffsetY: -5,
titleOffsetX: 0,
}]
},
legend: {
@ -97,7 +117,7 @@ export default {
async handleGetConsumptionLevelData() {
const req = {
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: ''
}

View File

@ -7,8 +7,11 @@
<!-- 消费时段分析图表 -->
<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" />
</view>
</view>
@ -16,12 +19,14 @@
<script>
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 moment from 'moment'
export default {
components: {
QiunDataCharts
QiunDataCharts,
ChartLoading
},
data() {
@ -33,8 +38,19 @@ export default {
}
}
},
props: {
selectTime: {
type: String,
default: ""
},
},
computed: {
//
hasChartData() {
return this.rawData.category.length > 0 &&
this.rawData.seriesData.length > 0
},
//
chartData() {
return {
@ -51,20 +67,21 @@ export default {
//
chartOpts() {
return {
padding: [15, 15, 15, 15],
padding: [15, 15, 0, 15],
dataLabel: false,
enableScroll: true,
enableScroll: false, //
dataPointShape: true,
xAxis: {
disableGrid: true,
itemCount: 6,
itemCount: this.rawData.category.length || 6, //
},
yAxis: {
showTitle: true,
data: [{
min: 0,
title: '客单占比(%)',
titleFontSize: 12,
titleOffsetY: 0,
titleOffsetY: -5,
titleOffsetX: 0
}]
},
@ -108,7 +125,7 @@ export default {
async handleGetConsumptionPeriodData() {
const req = {
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: '',
TimeSpan: 1
}
@ -132,6 +149,8 @@ export default {
processChartData(data) {
let category = []
let seriesData = []
let dataMap = {}
let availableHours = new Set()
//
if (data && data.length > 0) {
@ -141,15 +160,45 @@ export default {
orderSum += Number(item.data)
})
// data key
//
data.forEach((item, index) => {
if (index < 10) {
category.push(`0${index}:00`)
} else {
category.push(`${index}:00`)
}
const hour = index
const percentage = Number(((item.data / orderSum) * 100).toFixed(2))
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">
<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" />
</view>
</view>
@ -16,12 +19,14 @@
<script>
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 moment from 'moment'
export default {
components: {
QiunDataCharts
QiunDataCharts,
ChartLoading
},
data() {
@ -34,8 +39,20 @@ export default {
}
}
},
props: {
selectTime: {
type: String,
default: ""
},
},
computed: {
//
hasChartData() {
return this.rawData.category.length > 0 &&
this.rawData.seriesDataMan.length > 0 &&
this.rawData.seriesDataWoman.length > 0
},
//
chartData() {
return {
@ -62,16 +79,15 @@ export default {
xAxis: {
disableGrid: true,
itemCount: 6, // 6
scrollShow: true, //
scrollAlign: 'left', //
scrollColor: '#46B8F3', //
scrollWidth: 4, //
scrollHeight: 8 //
},
yAxis: {
showTitle: true,
data: [{
min: 0,
title: '%',
title: '百分比(%)',
titleFontSize: 12,
titleOffsetY: -5,
titleOffsetX: 10,
}]
},
extra: {
@ -97,7 +113,7 @@ export default {
async handleGetCustomerAgeData() {
const req = {
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);

View File

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

View File

@ -7,20 +7,25 @@
<!-- 客群特征分析图表 -->
<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>
</template>
<script>
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 moment from 'moment'
export default {
components: {
QiunDataCharts
QiunDataCharts,
ChartLoading
},
data() {
@ -35,8 +40,18 @@ export default {
}
}
},
props: {
selectTime: {
type: String,
default: ""
},
},
computed: {
//
hasChartData() {
return this.rawData.seriesData && this.rawData.seriesData.length > 0;
},
//
chartData() {
return {
@ -117,7 +132,7 @@ export default {
async handleGetCustomerGroupData() {
const req = {
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
}

View File

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

View File

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

View File

@ -7,7 +7,10 @@
<!-- 图表容器 -->
<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"
tooltipFormat="SalesRankingOfProducts" />
</view>
@ -16,12 +19,14 @@
<script>
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 moment from 'moment'
export default {
components: {
QiunDataCharts
QiunDataCharts,
ChartLoading
},
data() {
return {
@ -32,6 +37,11 @@ export default {
},
computed: {
//
hasChartData() {
return this.salesRankingData && this.salesRankingData.length > 0
},
//
barChartData() {
return {
@ -45,7 +55,7 @@ export default {
}
},
//
//
chartOpts() {
// 6100
const maxSales = Math.max(...this.salesRankingData.map(item => item.sales));
@ -61,32 +71,29 @@ export default {
}
return {
color: ['#576EFF'],
legend: {
show: true,
color: ['#576EFF']
},
padding: [15, 15, 15, 15], // paddingX
padding: [15, 15, 0, 15], // paddingX
dataLabel: false,
enableScroll: false,
xAxis: {
itemCount: 5, //
scrollAlign: 'right',
scrollColor: '#576EFF',
scrollBackgroundColor: 'rgba(87, 110, 255, 0.1)',
scrollWidth: 4,
scrollHeight: 8,
rotate: 30, // 30
fontSize: 12, //
margin: 15, // 线
fontSize: 10, //
},
yAxis: {
showTitle: true,
titleFontSize: 12,
gridType: 'dash',
dashLength: 2,
data: [{
title: '商品件数(件)',
min: 0,
max: finalMax,
data: yAxisData
data: yAxisData,
titleOffsetY: -5,
titleOffsetX: -10,
}]
},
categoriesReal: this.salesRankingData.map(item =>

View File

@ -8,7 +8,10 @@
<!-- 订单统计图表 -->
<view class="chart-card">
<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"
:ontouch="true" tooltipFormat="MallOrderStatistics" />
</view>
@ -18,12 +21,14 @@
<script>
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 moment from 'moment'
export default {
components: {
QiunDataCharts
QiunDataCharts,
ChartLoading
},
data() {
@ -36,8 +41,18 @@ export default {
}
}
},
props: {
selectTime: {
type: String,
default: ""
},
},
computed: {
//
hasChartData() {
return this.rawData.category && this.rawData.category.length > 0
},
//
chartData() {
return {
@ -62,7 +77,7 @@ export default {
//
chartOpts() {
return {
padding: [15, 15, 15, 15], //
padding: [25, 15, 0, 15], //
dataLabel: false,
enableScroll: true,
dataPointShape: true,
@ -76,11 +91,15 @@ export default {
min: 0,
title: '交易金额(元)',
titleFontSize: 12,
titleOffsetY: -10,
titleOffsetX: -30,
position: 'left',
},
{
min: 0,
title: '交易笔数(笔)',
titleOffsetY: -10,
titleOffsetX: 0,
titleFontSize: 12,
position: 'right',
}
@ -122,8 +141,8 @@ export default {
DataType: 2, // 1 2
ProvinceCode: '530000',
type: 'encryption',
StartMonth: moment().startOf('y').format('YYYYMM'),
EndMonth: moment().subtract(1, 'M').format('YYYYMM'),
StartMonth: this.selectTime ? moment(this.selectTime).startOf('y').format('YYYYMM') : moment().startOf('y').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-left">会员总数</view>
<view class="member-sum-total">{{ memberData.totalMembers || 0 }}</view>
<view class="member-sum-box-right">本月新增 {{ memberData.monthNewMembers || 0 }} </view>
<view class="member-sum-total">{{ memberData.totalMembers ? memberData.totalMembers.toLocaleString() : 0 }}
</view>
<view class="member-sum-box-right">本月新增 {{ memberData.monthNewMembers ?
memberData.monthNewMembers.toLocaleString() : 0 }} </view>
</view>
<!-- 近30天数据 -->
@ -18,22 +20,29 @@
<view class="recent-data">
<view class="recent-data-top">
<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>
<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>
<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>
<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>
</view>
@ -46,13 +55,14 @@
<view class="member-consumption">
<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-value">{{ memberData.consumptionCount || 0 }}</view>
<view class="member-consumption-value">{{ memberData.consumptionCount ? memberData.consumptionCount : 0
}}</view>
</view>
<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-value">{{ formatMoney(memberData.totalSalesAmount || 0) }}</view>
</view>
@ -138,7 +148,12 @@ export default {
}
}
},
props: {
selectTime: {
type: String,
default: ""
},
},
onReady() {
this.handleGetMemberMallData()
},
@ -148,7 +163,7 @@ export default {
async handleGetMemberMallData() {
const req = {
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);
@ -246,7 +261,6 @@ export default {
font-size: 28rpx;
font-weight: 600;
color: #1890FF;
letter-spacing: 4rpx;
}
.member-sum-box-right {

View File

@ -47,7 +47,10 @@
<view class="chart-section">
<view class="chart-title">设备设施</view>
<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" />
</view>
</view>
@ -83,7 +86,10 @@
<view class="chart-section">
<view class="chart-title">服务区类型分布</view>
<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" />
</view>
</view>
@ -92,11 +98,13 @@
<script>
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";
export default {
components: {
QiunDataCharts
QiunDataCharts,
ChartLoading
},
data() {
@ -124,6 +132,26 @@ export default {
},
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() {
return {
@ -146,19 +174,29 @@ export default {
facilityChartOpts() {
return {
color: ['#1890FF', '#52C41A', '#FAAD14', '#F5222D', '#722ED1', '#13C2C2'],
padding: [15, 15, 15, 15],
padding: [15, 15, 0, 15],
dataLabel: true,
legend: {
show: false
show: true
},
xAxis: {
itemCount: 6,
scrollShow: false
scrollShow: false,
fontSize: 12
},
yAxis: {
gridType: 'dash',
dashLength: 2,
data: [{ min: 0 }]
showTitle: true,
data: [
{
min: 0,
title: '设施数量(个)',
titleFontSize: 12,
titleOffsetY: -5,
titleOffsetX: 0,
}
]
},
extra: {
column: {

View File

@ -7,8 +7,11 @@
<!-- 偏好类型图表 -->
<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" />
</view>
</view>
@ -16,12 +19,14 @@
<script>
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 moment from 'moment'
export default {
components: {
QiunDataCharts
QiunDataCharts,
ChartLoading
},
data() {
@ -35,8 +40,18 @@ export default {
}
}
},
props: {
selectTime: {
type: String,
default: ""
},
},
computed: {
//
hasChartData() {
return this.rawData.category && this.rawData.category.length > 0
},
//
chartData() {
return {
@ -103,8 +118,8 @@ export default {
async handleGetPreferenceTypeData() {
const req = {
statisticsType: 1,
startMonth: moment().startOf('y').format('YYYYMM'),
endMonth: moment().format('YYYYMM'),
startMonth: this.selectTime ? moment(this.selectTime).startOf('y').format('YYYYMM') : moment().startOf('y').format('YYYYMM'),
endMonth: this.selectTime ? moment(this.selectTime).format('YYYYMM') : moment().format('YYYYMM'),
provinceCode: '530000',
showTradeLevel: 1,
fromRedis: true

View File

@ -7,8 +7,11 @@
<!-- 区域营收占比图表 -->
<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" />
</view>
</view>
@ -16,15 +19,22 @@
<script>
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 moment from 'moment'
import { wrapTreeNode } from "@/util/dateTime";
export default {
components: {
QiunDataCharts
QiunDataCharts,
ChartLoading
},
props: {
selectTime: {
type: String,
default: ""
},
},
data() {
return {
// ID
@ -39,6 +49,11 @@ export default {
},
computed: {
//
hasChartData() {
return this.rawData.seriesData && this.rawData.seriesData.length > 0
},
//
chartData() {
return {
@ -57,27 +72,20 @@ export default {
show: true,
position: 'right',
float: 'center',
backgroundColor: 'rgba(0,0,0,0)',
borderColor: 'rgba(0,0,0,0)',
fontSize: 12,
fontColor: '#333333',
margin: 0,
padding: 0,
itemGap: 10,
textAlign: 'left'
},
extra: {
pie: {
activeOpacity: 0.5,
activeRadius: 10,
offsetAngle: 0,
labelWidth: 0,
border: false,
borderWidth: 2,
borderColor: '#FFFFFF',
linearType: 'custom'
borderColor: '#FFFFFF'
}
},
percentageList: this.rawData.legendData
}
}
},
@ -113,8 +121,8 @@ export default {
})
const req = {
StartDate: moment().startOf('M').format('YYYY-MM-DD'),
EndDate: moment().endOf('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: this.selectTime ? moment(this.selectTime).endOf('M').format('YYYY-MM-DD') : moment().endOf('M').format('YYYY-MM-DD'),
DataType: 1, //
ServerpartIds: allId, // 使ID
DataSourceType: 1,

View File

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

View File

@ -16,13 +16,18 @@
<text class="benefits-title">本月福利金发放额度</text>
</view>
<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>
</view>
</view>
<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"
tooltipFormat="ThisMonthBenefits" />
</view>
@ -32,12 +37,14 @@
<script>
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 moment from 'moment'
export default {
components: {
QiunDataCharts
QiunDataCharts,
ChartLoading
},
data() {
@ -50,8 +57,18 @@ export default {
},
}
},
props: {
selectTime: {
type: String,
default: ""
},
},
computed: {
//
hasChartData() {
return this.rawData.pieData && this.rawData.pieData.length > 0
},
//
chartData() {
return {
@ -70,24 +87,17 @@ export default {
show: true,
position: 'right',
float: 'center',
backgroundColor: 'rgba(0,0,0,0)',
borderColor: 'rgba(0,0,0,0)',
fontSize: 12,
margin: 0,
padding: 0,
itemGap: 10,
textAlign: 'left'
},
extra: {
pie: {
activeOpacity: 0.5,
activeRadius: 10,
offsetAngle: 0,
labelWidth: 0,
border: false,
borderWidth: 2,
borderColor: '#FFFFFF',
linearType: 'custom'
}
},
}
@ -108,7 +118,7 @@ export default {
async getWelFareSummaryData() {
const req = {
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'
}

View File

@ -7,8 +7,11 @@
</view>
<view class="chart-content">
<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" />
</view>
</view>
@ -18,12 +21,14 @@
<script>
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 moment from 'moment'
export default {
components: {
QiunDataCharts
QiunDataCharts,
ChartLoading
},
data() {
@ -45,7 +50,20 @@ export default {
}
},
props: {
selectTime: {
type: String,
default: ""
},
},
computed: {
//
hasChartData() {
// 0
return this.monthlyData && this.monthlyData.length > 0 &&
this.monthlyData.some(item => item.currentYearValue > 0 || item.previousYearValue > 0);
},
//
chartData() {
return {
@ -71,16 +89,16 @@ export default {
enableScroll: true, //
xAxis: {
disableGrid: true,
scrollShow: true, //
scrollAlign: 'left', //
itemCount: 6, // 6
scrollColor: '#46B8F3', //
scrollWidth: 4, //
scrollHeight: 8 //
},
yAxis: {
showTitle: true,
data: [{
min: 0
min: 0,
title: '断面流量(万辆)',
titleFontSize: 12,
titleOffsetY: -5,
titleOffsetX: -5,
}]
},
legend: {},
@ -124,9 +142,9 @@ export default {
async getCurrentYearData() {
const currentReq = {
ProvinceCode: '530000',
StatisticsDate: moment().format('YYYY-MM-DD'),
StartDate: moment().startOf('y').format('YYYY-MM-DD'),
EndDate: moment().endOf('M').format('YYYY-MM-DD'),
StatisticsDate: this.selectTime ? moment(this.selectTime).endOf('M').format('YYYY-MM-DD') : moment().format('YYYY-MM-DD'),
StartDate: this.selectTime ? moment(this.selectTime).startOf('y').format('YYYY-MM-DD') : moment().startOf('y').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(
@ -139,9 +157,9 @@ export default {
async getPreviousYearData() {
const previousReq = {
ProvinceCode: '530000',
StatisticsDate: moment().subtract(1, 'y').endOf('M').format('YYYY-MM-DD'),
StartDate: moment().subtract(1, 'y').startOf('y').format('YYYY-MM-DD'),
EndDate: 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: 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: 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(
@ -414,98 +432,37 @@ export default {
width: 100%;
height: 400rpx;
}
}
}
.chart-legend {
display: flex;
justify-content: center;
gap: 32rpx;
margin-top: 16rpx;
.chart-legend {
display: flex;
justify-content: center;
gap: 32rpx;
margin-top: 16rpx;
.legend-item {
display: flex;
align-items: center;
gap: 8rpx;
.legend-item {
display: flex;
align-items: center;
gap: 8rpx;
.legend-dot {
width: 12rpx;
height: 12rpx;
border-radius: 2rpx;
.legend-dot {
width: 12rpx;
height: 12rpx;
border-radius: 2rpx;
&.current-year {
background: linear-gradient(135deg, #46B8F3, #1A4AF6);
}
&.current-year {
background: linear-gradient(135deg, #46B8F3, #1A4AF6);
}
&.previous-year {
background: #3CD495;
}
}
.legend-text {
font-size: 22rpx;
color: @text-secondary;
}
&.previous-year {
background: #3CD495;
}
}
}
.monthly-data {
.data-table {
.table-header {
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;
}
}
}
.legend-text {
font-size: 22rpx;
color: @text-secondary;
}
}
}

View File

@ -7,8 +7,11 @@
<!-- 经营效益图表 -->
<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" />
</view>
</view>
@ -16,12 +19,14 @@
<script>
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 moment from 'moment'
export default {
components: {
QiunDataCharts
QiunDataCharts,
ChartLoading
},
data() {
@ -39,8 +44,18 @@ export default {
}
}
},
props: {
selectTime: {
type: String,
default: ""
},
},
computed: {
//
hasChartData() {
return this.rawData.category && this.rawData.category.length > 0
},
//
chartData() {
return {
@ -67,16 +82,15 @@ export default {
xAxis: {
disableGrid: true,
itemCount: 6, // 6
scrollShow: true, //
scrollAlign: 'left', //
scrollColor: '#46B8F3', //
scrollWidth: 4, //
scrollHeight: 8 //
},
yAxis: {
showTitle: true,
data: [{
min: 0,
title: '万元',
title: '经济效益(万元)',
titleFontSize: 12,
titleOffsetY: -5,
titleOffsetX: 0,
}]
},
extra: {
@ -102,14 +116,14 @@ export default {
async handleGetVehicleModelStayData() {
//
const currentReq = {
StatisticsDate: moment().format('YYYY'),
StatisticsDate: this.selectTime ? moment(this.selectTime).format('YYYY') : moment().format('YYYY'),
ProvinceCode: '530000',
StatisticsType: 4,
}
//
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',
StatisticsType: 4,
}

View File

@ -7,7 +7,10 @@
<!-- 入区车流图表 -->
<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"
tooltipFormat="vehicleChartData" />
</view>
@ -19,7 +22,10 @@
<!-- 对客营收图表 -->
<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"
tooltipFormat="revenueChartDataVehicles" />
</view>
@ -28,12 +34,14 @@
<script>
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 moment from 'moment'
export default {
components: {
QiunDataCharts
QiunDataCharts,
ChartLoading
},
data() {
@ -57,7 +65,24 @@ export default {
}
},
props: {
selectTime: {
type: String,
default: ""
},
},
computed: {
//
hasVehicleChartData() {
return this.chartData.category && this.chartData.category.length > 0
},
//
hasRevenueChartData() {
return this.chartData.category && this.chartData.category.length > 0
},
//
vehicleChartData() {
return {
@ -84,16 +109,15 @@ export default {
xAxis: {
disableGrid: true,
itemCount: 6, // 6
scrollShow: true, //
scrollAlign: 'left', //
scrollColor: '#46B8F3', //
scrollWidth: 4, //
scrollHeight: 8 //
},
yAxis: {
showTitle: true,
data: [{
min: 0,
title: '万辆',
title: '入区车流(万辆)',
titleFontSize: 12,
titleOffsetY: -5,
titleOffsetX: 0,
}]
},
extra: {
@ -135,20 +159,17 @@ export default {
enableScroll: true, //
xAxis: {
disableGrid: true,
scrollShow: true, //
scrollAlign: 'left', //
itemCount: 6, // 6
scrollWidth: 4, //
scrollHeight: 8 //
},
yAxis: {
gridType: 'dash',
dashLength: 2,
showTitle: true,
data: [{
min: 0,
title: '万元',
title: '对客营收(万元)',
titleFontSize: 12,
titleOffsetY: -4,
titleOffsetY: -5,
titleOffsetX: 0
}],
splitNumber: 5
@ -180,15 +201,15 @@ export default {
async handleGetSectionFlowCount() {
//
const currentReq = {
StartDate: moment().startOf('y').format('YYYY-MM-DD'),
EndDate: moment().subtract(1, 'd').format('YYYY-MM-DD'),
StartDate: this.selectTime ? moment(this.selectTime).startOf('y').format('YYYY-MM-DD') : moment().startOf('y').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
}
//
const lastYearReq = {
StartDate: moment().subtract(1, 'y').startOf('y').format('YYYY-MM-DD'),
EndDate: moment().subtract(1, 'y').endOf('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: 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
}
@ -208,7 +229,6 @@ export default {
"CommercialApi/BigData/GetMonthAnalysis",
params
);
console.log('入区车流数据', data);
return data || []
},
@ -287,7 +307,6 @@ export default {
revenueAdd: revenueAdd
}
console.log('处理后的图表数据', this.chartData)
},
}

View File

@ -108,16 +108,22 @@ const cfu = {
return `${item.name}${item.data}`
},
"festivalRevenueSumInfoChart": function (item, category, index, opts) {
// console.log('', item);
// console.log('', category);
// console.log('', index);
// console.log('', opts);
return `${item.name}`
},
"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) {
return `${item.name}${item.data}万元`
return `${item.name}占比${opts.percentageList[index].value}${item.data}万元`
},
"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) {
return `${item.name}占比:${item.data}%`
@ -159,7 +165,7 @@ const cfu = {
return `${item.name}${item.data}`
},
"facilityChartData": function (item, category, index, opts) {
return `${category}${item.name}${item.data}`
return `${category}${item.name}${item.data}`
},
"distributionChartData": function (item, category, index, opts) {
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-with-animation="true">
<!-- 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 v-for="(tab, index) in tabList" :key="index" :id="`tab-${index}`" class="tab-item"
:class="{ active: activeTab === index }" @click="switchTab(index)">
@ -24,7 +25,7 @@
</view>
</view>
<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)">
<text class="nav-text">{{ item.name }}</text>
<view class="nav-dot" v-if="activeNavItem === item.id"></view>
@ -32,9 +33,19 @@
</view>
</view>
</view>
<view id="top"> </view>
<!-- 内容展示区域 -->
<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">
<!-- 服务区概况 -->
@ -47,69 +58,69 @@
<!-- 断面流量 -->
<view id="trend-of-trafficFlow"></view>
<TrendOfTrafficFlow />
<TrendOfTrafficFlow :selectTime="selectTime" />
<!-- 入区车流 -->
<view id="vehicles-entering"></view>
<VehiclesEntering />
<VehiclesEntering :selectTime="selectTime" />
<!-- 经营效益 -->
<view id="vehicle-model-stay"></view>
<VehicleModelStay />
<VehicleModelStay :selectTime="selectTime" />
</view>
<!-- 客群画像与消费行为分析 -->
<view v-if="activeTab === 1" class="tab-content">
<!-- 年龄画像 -->
<view id="customer-age-group"></view>
<CustomerAgeGroup />
<CustomerAgeGroup :selectTime="selectTime" />
<!-- 性别画像 -->
<view id="gender-customer-group"></view>
<GenderCustomerGroup />
<GenderCustomerGroup :selectTime="selectTime" />
<!-- 偏好类型 -->
<view id="preference-type"></view>
<PreferenceType />
<PreferenceType :selectTime="selectTime" />
<!-- 客群特征分析 -->
<view id="customer-group"></view>
<CustomerGroup />
<CustomerGroup :selectTime="selectTime" />
<!-- 客群消费偏好 -->
<view id="customer-consumption-preferences"></view>
<CustomerConsumptionPreferences />
<CustomerConsumptionPreferences :selectTime="selectTime" />
<!-- 消费转化率对比图 -->
<view id="consumption-conversion"></view>
<ConsumptionConversion />
<ConsumptionConversion :selectTime="selectTime" />
<!-- 消费水平 -->
<view id="consumption-level"></view>
<ConsumptionLevel />
<ConsumptionLevel :selectTime="selectTime" />
<!-- 消费时段分析 -->
<view id="consumption-period"></view>
<ConsumptionPeriod />
<ConsumptionPeriod :selectTime="selectTime" />
<!-- 品牌消费水平 -->
<view id="brand-consumption-level"></view>
<BrandConsumptionLevel />
<BrandConsumptionLevel :selectTime="selectTime" />
</view>
<!-- 多维度经营数据分析 -->
<view v-if="activeTab === 2" class="tab-content">
<!-- 营收特征 -->
<view id="business-case"></view>
<BusinessCase />
<BusinessCase :selectTime="selectTime" />
<!-- 区域营收占比 -->
<view id="regional-revenue"></view>
<RegionalRevenue />
<RegionalRevenue :selectTime="selectTime" />
<!-- 业态结构占比 -->
<view id="business-structure"></view>
<BusinessStructure />
<BusinessStructure :selectTime="selectTime" />
<!-- 节假日营收 -->
<view id="festival-revenue-sum-info"></view>
@ -121,7 +132,7 @@
<view v-if="activeTab === 3" class="tab-content">
<!-- 会员商城 -->
<view id="member-mall"></view>
<MemberMall />
<MemberMall :selectTime="selectTime" />
<!-- 热门商品榜单 -->
<view id="hot-product-list"></view>
@ -133,15 +144,15 @@
<!-- 供应商列表 -->
<view id="supplier-list-box"></view>
<SupplierListBox />
<SupplierListBox :selectTime="selectTime" />
<!-- 商城订单统计 -->
<view id="mall-order-statistics"></view>
<MallOrderStatistics />
<MallOrderStatistics :selectTime="selectTime" />
<!-- 本月福利金发送额度 -->
<view id="this-month-benefits"></view>
<ThisMonthBenefits />
<ThisMonthBenefits :selectTime="selectTime" />
<!-- 会员消费数据分析 -->
<view id="analysis-of-member"></view>
@ -177,6 +188,7 @@ import SupplierListBox from './components/SupplierListBox.vue'
import MallOrderStatistics from './components/MallOrderStatistics.vue'
import ThisMonthBenefits from './components/ThisMonthBenefits.vue'
import AnalysisOfMember from './components/AnalysisOfMember.vue'
import moment from 'moment'
export default {
@ -260,7 +272,8 @@ export default {
sessionData: {},
pageScrollTop: 0,
scrollIntoView: "",
scrollIntoTabItem: ""
tabScrollPosition: 0,
selectTime: moment().subtract(1, 'M').format('YYYY-MM')
}
},
computed: {
@ -289,14 +302,25 @@ export default {
}
},
methods: {
bindDateChange(e) {
console.log('eeeee', e);
this.selectTime = e.detail.value
},
switchTab(index) {
this.scrollIntoView = 'top'
this.activeTab = index;
this.scrollIntoTabItem = `tab-${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
},
// tab
async fetchTabData(tabIndex) {
// Tab
@ -350,10 +377,10 @@ export default {
.tab-container {
background: @bg-white;
box-shadow: @shadow-light;
// position: sticky;
position: fixed;
top: 0;
z-index: 100;
width: 100%;
.tab-list {
height: 80rpx;
@ -361,306 +388,308 @@ export default {
padding: 0 32rpx;
box-sizing: border-box;
position: relative;
width: 100%;
overflow-x: auto;
scrollbar-width: none;
/* 隐藏滚动条 Firefox */
-ms-overflow-style: none;
/* 隐藏滚动条 IE/Edge */
width: max-content;
white-space: nowrap;
}
&::-webkit-scrollbar {
display: none;
/* 隐藏滚动条 Chrome/Safari */
/* 隐藏滚动条 */
::-webkit-scrollbar {
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 {
position: relative;
padding: 16rpx 24rpx;
margin-right: 16rpx;
flex-shrink: 0;
.tab-text {
font-size: 28rpx;
color: @text-secondary;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
cursor: pointer;
min-width: fit-content;
white-space: nowrap;
position: relative;
&:last-child {
margin-right: 0;
&::after {
content: '';
position: absolute;
bottom: -4rpx;
left: 0;
width: 100%;
height: 2rpx;
background: @primary-color;
transform: scaleX(0);
transition: transform 0.3s ease;
}
}
&.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-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);
}
&:active {
transform: scale(0.95);
}
}
}
}
.content-container {
padding: 32rpx;
padding-top: 92rpx;
.content-container {
padding: 32rpx;
padding-top: 92rpx;
.tab-content {
/* 移除切换动画 */
.tab-content {
/* 移除切换动画 */
.chart-grid {
.chart-row {
margin-bottom: 24rpx;
.chart-grid {
.chart-row {
margin-bottom: 24rpx;
.chart-card {
background: @bg-white;
border-radius: @border-radius;
padding: 24rpx;
box-shadow: @shadow;
transition: all 0.3s ease;
.chart-card {
background: @bg-white;
border-radius: @border-radius;
padding: 24rpx;
box-shadow: @shadow;
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;
overflow: hidden;
box-sizing: border-box;
&.large {
height: 400rpx;
}
&::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;
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;
}
&: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;
.placeholder-text {
font-size: 32rpx;
color: @text-secondary;
margin-bottom: 8rpx;
position: relative;
overflow: hidden;
z-index: 1;
}
&.large {
height: 400rpx;
}
&::before {
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;
}
.placeholder-desc {
font-size: 24rpx;
color: @text-light;
position: relative;
z-index: 1;
}
}
}
}
}
}
}
.side-navigation {
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;
.timeBox {
width: 100%;
display: flex;
justify-content: flex-end;
}
&::-webkit-scrollbar {
width: 4rpx;
.side-navigation {
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 {
background: rgba(0, 0, 0, 0.1);
border-radius: 2rpx;
}
.nav-container {
padding: 0 16rpx;
&::-webkit-scrollbar-thumb {
background: @primary-color;
border-radius: 2rpx;
}
.nav-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 16rpx;
border-bottom: 1rpx solid #f0f0f0;
margin-bottom: 8rpx;
cursor: pointer;
//
&.collapsed {
min-width: auto;
max-width: auto;
.nav-title {
font-size: 24rpx;
font-weight: 600;
color: @text-primary;
}
.nav-container {
padding: 0;
.nav-toggle {
.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 {
padding: 0 16rpx;
.nav-header {
.nav-list {
.nav-item {
position: relative;
padding: 16rpx 20rpx;
margin-bottom: 8rpx;
border-radius: 12rpx;
cursor: pointer;
transition: all 0.3s ease;
display: flex;
align-items: center;
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 {
background: rgba(102, 126, 234, 0.05);
border-radius: 8rpx;
background: rgba(102, 126, 234, 0.1);
transform: translateX(-4rpx);
}
}
.nav-list {
.nav-item {
position: relative;
padding: 16rpx 20rpx;
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;
}
}
&.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 {
font-size: 22rpx;
color: @text-secondary;
line-height: 1.4;
flex: 1;
transition: all 0.3s ease;
color: @primary-color;
font-weight: 600;
}
}
.nav-dot {
width: 8rpx;
height: 8rpx;
background: @primary-color;
border-radius: 50%;
animation: pulse 2s infinite;
}
.nav-text {
font-size: 22rpx;
color: @text-secondary;
line-height: 1.4;
flex: 1;
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 })
if (res.Result_Code == 100) {
let data = res.Result_Data
console.log('WeChat_GetBusinessMemberInfoWeChat_GetBusinessMemberInfo', data);
commit('setUser', data)
data.WeChat_MiniProToken = _user.WeChat_MiniProToken