Files

379 lines
10 KiB
Vue
Raw Permalink Normal View History

2025-08-26 16:17:24 +08:00
<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>