Files
2025-08-26 16:17:24 +08:00

379 lines
10 KiB
Vue
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="container">
<scroll-view scroll-y="true" class="scroll">
<view class="tourist-box">
<image class="bgImg" src="../../static/img/rectangle.png" mode=""></image>
<image class="img" src="../../static/img/yksl.png" mode=""></image>
<view style="position: relative;">
<view class="title">累计游客数量</view>
<view class="num">{{accumulatedTouristsVo.totalNum}}</view>
<view class="bar-box">
<view class="row">
<view class="label">
<view class="icon">
<view>
<u-icon name="man" color="#2B75E9" size="32rpx" bold></u-icon>
</view>
<text>男生人数</text>
</view>
<view class="num">{{accumulatedTouristsVo.manNum}}</view>
</view>
<view class="manProgress">
<u-line-progress :percentage="(accumulatedTouristsVo.manNum / accumulatedTouristsVo.totalNum) * 100" activeColor="#2B75E9" :showText="false" height="15rpx"></u-line-progress>
</view>
</view>
<view class="row">
<view class="label">
<view class="icon">
<view class="woman">
<u-icon name="woman" color="#FF5EA4" size="32rpx" bold></u-icon>
</view>
<text>女生人数</text>
</view>
<view class="num">{{accumulatedTouristsVo.womenNum}}</view>
</view>
<u-line-progress :percentage="(accumulatedTouristsVo.womenNum / accumulatedTouristsVo.totalNum) * 100" activeColor="#03AE80" :showText="false" height="15rpx"></u-line-progress>
</view>
</view>
</view>
</view>
<view class="card age-box">
<view class="title-box">
<image class="headline" src="../../static/img/nltj.png" mode=""></image>
<view class="label">年龄统计</view>
</view>
<view class="chart1-box">
<view class="left">
<qiun-data-charts type="ring" canvas2d :opts="ringOpts" :chartData="ringChartData" />
</view>
<view class="right">
<view class="row" v-for="(item, index) in ageStatisticsVo">
<view class="col1">
<view class="dot"></view>
<view class="label">{{item.name}}</view>
</view>
<view class="col2">{{item.value}}</view>
</view>
</view>
</view>
</view>
<view class="card source-box">
<view class="title-box">
<image class="headline" src="../../static/img/yklyd.png" mode=""></image>
<view class="label">游客来源地</view>
</view>
<view class="chart2-box">
<view class="unit">单位</view>
<view class="plan-list">
<view class="plan-item" v-for="(item, index) in touristSourcesStatisticsVO" :key="index">
<view class="icon1">
<image v-if="index == 0" class="ranking" src="../../static/img/No1.png" mode=""></image>
<image v-else-if="index == 1" class="ranking" src="../../static/img/No2.png" mode=""></image>
<image v-else-if="index == 2" class="ranking" src="../../static/img/No3.png" mode=""></image>
<view v-else class="sort">{{index + 1}}</view>
</view>
<view class="row">
<view class="label">
<view class="text">{{item.name}}</view>
<view class="num">{{item.value}}</view>
</view>
<u-line-progress :percentage="(item.value / yklydTotal) * 100" activeColor="#03AE80" :showText="false" height="15rpx"></u-line-progress>
</view>
</view>
</view>
</view>
</view>
<view class="card classify-box">
<view class="title-box">
<image class="headline" src="../../static/img/ykfxtj.png" mode=""></image>
<view class="label">游客分类统计</view>
</view>
<view class="chart3-box">
<view class="unit">单位</view>
<qiun-data-charts type="funnel" canvas2d :opts="funnelOpts" :chartData="funnelChartData" />
</view>
</view>
</scroll-view>
</view>
</template>
<script>
export default {
data() {
return {
accumulatedTouristsVo: {},
ageStatisticsVo: [],
touristSourcesStatisticsVO: [],
yklydTotal: 0,
touristCategorizeVo: [],
ringOpts: {
rotate: false,
rotateLock: false,
color: ["#03AE80","#347BEA","#FE7D51","#6E34EA"],
padding: [0,0,0,0],
dataLabel: true,
enableScroll: false,
legend: {
show: false,
position: "right",
lineHeight: 30
},
title: {
name: "",
fontSize: 0,
color: "#666666"
},
subtitle: {
name: "",
fontSize: 0,
color: "#7cb5ec"
},
extra: {
ring: {
ringWidth: 20,
activeOpacity: 0.5,
activeRadius: 10,
offsetAngle: -90,
labelWidth: 15,
border: true,
borderWidth: 3,
borderColor: "#FFFFFF",
customRadius: 70
}
}
},
funnelOpts: {
color: ["#03AE80", "#347BEA", "#FE7D51", ],
legend: {
show: true,
},
padding: [10, 0, 10, 0],
enableScroll: false,
extra: {
funnel: {
activeOpacity: 0.3,
activeWidth: 10,
border: false,
borderWidth: 2,
borderColor: "#FFFFFF",
fillOpacity: 1,
labelAlign: "right",
type: "pyramid"
}
}
},
ringChartData: {},
funnelChartData: {}
};
},
mounted() {
this.getTouristPortrait();
},
methods: {
async getTouristPortrait() {
let info = await this.$http.getTouristPortrait();
this.accumulatedTouristsVo = info.data.accumulatedTouristsVo;
this.ageStatisticsVo = info.data.ageStatisticsVo;
this.touristSourcesStatisticsVO = info.data.touristSourcesStatisticsVO;
this.touristSourcesStatisticsVO.forEach(m => {
this.yklydTotal += m.value;
})
this.touristCategorizeVo = info.data.touristCategorizeVo;
this.ageStatisticsVo.forEach(m => {
m.labelShow = false;
})
let res1 = {
series: [
{
data: this.ageStatisticsVo
}
]
};
this.ringChartData = JSON.parse(JSON.stringify(res1));
this.touristCategorizeVo.forEach(e => {
e.centerText = e.value;
e.labelText = e.name + ' ' + e.value;
e.centerText = '';
})
let res2 = {
series: [
{
data: this.touristCategorizeVo
}
]
};
this.funnelChartData = JSON.parse(JSON.stringify(res2));
}
}
}
</script>
<style lang="scss" scoped>
.container {
height: 100%;
.scroll {
height: 100%;
}
.tourist-box {
width: 686rpx;
height: 396rpx;
border-radius: 10rpx;
box-sizing: border-box;
padding: 32rpx;
position: relative;
.bgImg {
position: absolute;
left: 0;
top: 0;
width: 686rpx;
height: 396rpx;
}
.img {
position: absolute;
width: 240rpx;
height: 232rpx;
right: 45rpx;
top: -24rpx;
}
.title {
font-size: 28rpx;
color: #333333;
line-height: 33rpx;
}
.num {
margin-top: 8rpx;
font-weight: bold;
font-size: 56rpx;
color: #333333;
line-height: 66rpx;
}
.bar-box {
padding-top: 20rpx;
.row {
.label {
display: flex; align-items: center; justify-content: space-between; margin: 28rpx 0 12rpx;
.icon {
display: flex; align-items: center; font-size: 28rpx; color: #333333; line-height: 33rpx;
.woman {
transform: rotate(45deg);
}
text { margin-left: 10rpx; }
}
.num { font-weight: bold; font-size: 32rpx; color: #333333; line-height: 38rpx; }
}
}
}
}
.title-box {
width: 686rpx;
height: 90rpx;
box-sizing: border-box;
border-radius: 10rpx 10rpx 0 0;
padding: 23rpx 28rpx;
display: flex;
align-items: center;
.headline {
width: 44rpx;
height: 44rpx;
margin-right: 16rpx;
}
.label {
font-weight: 500;
font-size: 32rpx;
color: #333333;
}
}
.card {
width: 100%;
box-sizing: border-box;
background: #FFFFFF;
border-radius: 10rpx;
margin-top: 20rpx;
}
.age-box {
.title-box { background: linear-gradient( 90deg, rgba(3,174,128,0.2) 0%, rgba(255,255,255,0.05) 100%); }
.chart1-box {
display: flex; align-items: center; padding: 0 32rpx;
.left {
width: 358rpx; height: 358rpx; position: relative; margin-right: 24rpx;
}
.right {
flex: 1;
.row {
margin-top: 37rpx; display: flex; align-items: center; justify-content: space-between;
&:nth-child(1) {
margin-top: 0;
.dot { background: #03AE80; }
}
&:nth-child(2) {
.dot { background: #347BEA; }
}
&:nth-child(3) {
.dot { background: #FE7D51; }
}
&:nth-child(4) {
.dot { background: #6E34EA; }
}
.col1 {
display: flex; align-items: center;
.dot {
width: 14rpx; height: 14rpx; border-radius: 50%; margin-right: 12rpx;
}
.label { font-size: 28rpx; color: #666666; }
}
.col2 { font-weight: 500; font-size: 28rpx; color: #333333; }
}
}
}
}
.source-box {
.title-box { background: linear-gradient( 90deg, rgba(43,117,233,0.2) 0%, rgba(255,255,255,0.05) 100%); }
.chart2-box {
padding: 20rpx 28rpx 40rpx;
.unit {
font-weight: 500;
font-size: 22rpx;
color: #999999;
text-align: right;
}
.plan-list {
margin-top: 21rpx;
.plan-item {
margin-top: 36rpx;
display: flex;
align-items: center;
&:first-child {
margin-top: 0;
}
.icon1 {
width: 48rpx; margin-right: 20rpx;
.ranking { width: 48rpx; height: 48rpx; }
.sort {
width: 36rpx; height: 36rpx; line-height: 36rpx; text-align: center; background: #F6F6F6; border-radius: 4rpx; font-weight: 500; font-size: 20rpx; color: #333333; margin-left: 12rpx;
}
}
.row {
flex: 1;
.label {
display: flex; align-items: center; justify-content: space-between; font-weight: 500; font-size: 28rpx; color: #333333; line-height: 33rpx; margin-bottom: 4rpx;
}
}
}
}
}
}
.classify-box {
.title-box { background: linear-gradient( 90deg, rgba(254,125,81,0.2) 0%, rgba(255,255,255,0.05) 100%); }
.chart3-box {
height: 370rpx; box-sizing: border-box; padding: 20rpx 28rpx 40rpx;
.unit {
font-weight: 500;
font-size: 22rpx;
color: #999999;
text-align: right;
}
}
}
}
</style>