| | |
| | | <template> |
| | | <div class="left-panel"> |
| | | <!-- 参与统计 --> |
| | | <!-- 已参与自主购房安置统计 --> |
| | | <div class="statistics-box"> |
| | | <div class="box-title">各街道/乡参与排名</div> |
| | | </div> |
| | | |
| | | <!-- 各街道参与排名 --> |
| | | <div class="ranking-box"> |
| | | <div class="box-title">各街道/乡参与排名</div> |
| | | <!-- <<div class="ranking-list"> |
| | | <div v-for="(item, index) in rankingList" :key="index" class="ranking-item"> |
| | | <span class="rank">{{ index + 1 }}</span> |
| | | <span class="name">{{ item.name }}</span> |
| | | <div class="progress-bar"> |
| | | <div class="progress" :style="{ width: item.percentage + '%' }"></div> |
| | | </div> |
| | | <span class="value">{{ item.value }}</span> |
| | | <div class="box-title">已参与自主购房安置统计</div> |
| | | <div class="box-content"> |
| | | <div class="box-content-item"> |
| | | <div class="box-content-item-title">总参与户数(户)</div> |
| | | <div class="box-content-item-value">{{ data.selfBuyResponse.householdNum || 0 }}</div> |
| | | </div> |
| | | </div> --> |
| | | <div class="box-content-item" style="margin-left: 35px;"> |
| | | <div class="box-content-item-title">总参与人数(人)</div> |
| | | <div class="box-content-item-value">{{ data.selfBuyResponse.personNum || 0 }}</div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- 安置房完成比 --> |
| | | <!-- 各镇/街参与户数排名 --> |
| | | <div class="ranking-box"> |
| | | <div class="box-title">各镇/街参与户数排名</div> |
| | | <div class="ranking-list"> |
| | | <div v-for="(item, index) in rankingList" :key="index" class="ranking-item"> |
| | | <div class="ranking-item-content"> |
| | | <span class="rank" :class="'rank-' + (index + 1)">{{ index + 1 }}</span> |
| | | <span class="name">{{ item.street }}</span> |
| | | <div class="value"> |
| | | <div class="value-text"> |
| | | 环比 |
| | | <span class="value-text-value" |
| | | :class="{ 'positive': item.latestBatchHouseholdCount < item.secondLatestBatchHouseholdCount, 'negative': item.latestBatchHouseholdCount > item.secondLatestBatchHouseholdCount }"> |
| | | {{ item.growth > 0 ? '+' : '' }}{{ item.householdNumRate }} |
| | | </span> |
| | | </div> |
| | | {{ item.householdNum }}人 |
| | | </div> |
| | | </div> |
| | | <div class="progress-bar"> |
| | | <div class="progress" :style="{ width: item.percentage + '%' }" :class="'rank-' + (index + 1)"> |
| | | <div class="progress-icon" :class="'rank-' + (index + 1)"></div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- 户主信息导入异常统计 --> |
| | | <div class="line-chart"> |
| | | <div class="box-title">安置房完成比</div> |
| | | <div class="pie-chart"> |
| | | <v-chart class="chart" :option="pieOption" autoresize /> |
| | | <div class="box-title">户主信息导入异常统计</div> |
| | | <div class="chart-container"> |
| | | <v-chart class="chart" :option="lineOption" autoresize /> |
| | | </div> |
| | | </div> |
| | | </div> |
| | |
| | | <script> |
| | | export default { |
| | | name: 'LeftPanel', |
| | | props: { |
| | | data: { |
| | | type: Object, |
| | | default: () => ({}) |
| | | }, |
| | | }, |
| | | data() { |
| | | return { |
| | | totalHouseholds: 87695, |
| | | totalPeople: 876995, |
| | | rankingList: [ |
| | | { name: '崇州街道', percentage: 90, value: '999户' }, |
| | | { name: '羊马乡', percentage: 85, value: '999户' }, |
| | | { name: '万家镇', percentage: 80, value: '999户' }, |
| | | { name: '崇阳街道', percentage: 75, value: '999户' }, |
| | | { name: '白头镇', percentage: 70, value: '999户' }, |
| | | { name: '金鸡乡', percentage: 65, value: '999户' }, |
| | | { name: '西江镇', percentage: 60, value: '999户' }, |
| | | { name: '观胜镇', percentage: 55, value: '999户' } |
| | | ], |
| | | pieOption: { |
| | | totalHouseholds: 0, |
| | | totalPeople: 0, |
| | | rankingList: [], |
| | | lineOption: { |
| | | tooltip: { |
| | | trigger: 'item' |
| | | trigger: 'axis', |
| | | axisPointer: { |
| | | type: 'none' |
| | | } |
| | | }, |
| | | series: [{ |
| | | type: 'pie', |
| | | radius: ['65%', '80%'], |
| | | label: { |
| | | legend: { |
| | | data: ['安置面积异常', '补偿金额异常'], |
| | | textStyle: { |
| | | color: 'rgba(255, 255, 255, 0.6)', |
| | | fontSize: 12 |
| | | }, |
| | | color: ['#FEDB65', '#00F2F0'], |
| | | icon: 'circle', |
| | | itemWidth: 6, |
| | | itemHeight: 6, |
| | | top: 5, |
| | | right: 0 |
| | | }, |
| | | grid: { |
| | | top: '20%', |
| | | left: '3%', |
| | | right: '6%', |
| | | bottom: '3%', |
| | | containLabel: true |
| | | }, |
| | | xAxis: { |
| | | type: 'category', |
| | | boundaryGap: false, |
| | | data: [], |
| | | axisLine: { |
| | | show: true, |
| | | lineStyle: { |
| | | color: '#1F2C5C' |
| | | } |
| | | }, |
| | | axisTick: { |
| | | show: false |
| | | }, |
| | | data: [ |
| | | { value: 34.5, name: '商业用房' }, |
| | | { value: 30, name: '住宅' }, |
| | | { value: 35.5, name: '其他' } |
| | | ], |
| | | itemStyle: { |
| | | color: function(params) { |
| | | const colorList = ['#00ffff', '#7cb9e8', 'rgba(0,255,255,0.5)']; |
| | | return colorList[params.dataIndex]; |
| | | } |
| | | axisLabel: { |
| | | color: '#fff', |
| | | fontSize: 12, |
| | | // rotate: 30, // 标签倾斜角度 |
| | | } |
| | | }] |
| | | }, |
| | | yAxis: { |
| | | type: 'value', |
| | | name: '单位:次', |
| | | nameTextStyle: { |
| | | color: '#fff', |
| | | fontSize: 12, |
| | | }, |
| | | splitLine: { |
| | | lineStyle: { |
| | | color: '#1F2C5C', |
| | | type: 'solid' |
| | | } |
| | | }, |
| | | axisLine: { |
| | | show: false |
| | | }, |
| | | axisTick: { |
| | | show: false |
| | | }, |
| | | axisLabel: { |
| | | color: '#fff', |
| | | fontSize: 12 |
| | | } |
| | | }, |
| | | series: [ |
| | | { |
| | | name: '安置面积异常', |
| | | type: 'line', |
| | | smooth: true, |
| | | symbol: 'circle', |
| | | itemStyle: { |
| | | color: '#FEDB65' |
| | | }, |
| | | areaStyle: { |
| | | opacity: 0.8, |
| | | color: { |
| | | type: 'linear', |
| | | x: 0, |
| | | y: 0, |
| | | x2: 0, |
| | | y2: 1, |
| | | colorStops: [{ |
| | | offset: 0, |
| | | color: '#6C1F0D' |
| | | }, { |
| | | offset: 0.7, |
| | | color: 'rgba(255,102,0,0)' |
| | | }] |
| | | } |
| | | }, |
| | | lineStyle: { |
| | | width: 4, |
| | | color: { |
| | | type: 'linear', |
| | | x: 0, |
| | | y: 0, |
| | | x2: 1, |
| | | y2: 0, |
| | | colorStops: [{ |
| | | offset: 0, |
| | | color: '#AE5112' // 0% 处的颜色 |
| | | }, { |
| | | offset: 0.3, |
| | | color: '#FEDB65' // 50% 处的颜色 |
| | | }, { |
| | | offset: 0.7, |
| | | color: '#FEDB65' // 50% 处的颜色 |
| | | }, { |
| | | offset: 1, |
| | | color: '#AE5112' // 100% 处的颜色 |
| | | }] |
| | | } |
| | | }, |
| | | data: [] |
| | | }, |
| | | { |
| | | name: '补偿金额异常', |
| | | type: 'line', |
| | | smooth: true, |
| | | symbol: 'circle', |
| | | itemStyle: { |
| | | color: '#00F2EF' |
| | | }, |
| | | areaStyle: { |
| | | opacity: 0.8, |
| | | color: { |
| | | type: 'linear', |
| | | x: 0, |
| | | y: 0, |
| | | x2: 0, |
| | | y2: 1, |
| | | colorStops: [{ |
| | | offset: 0, |
| | | color: 'rgba(28,0,255,0.8)' |
| | | }, { |
| | | offset: 0.7, |
| | | color: 'rgba(28,0,255,0)' |
| | | }] |
| | | } |
| | | }, |
| | | lineStyle: { |
| | | width: 4, |
| | | color: { |
| | | type: 'linear', |
| | | x: 0, |
| | | y: 0, |
| | | x2: 1, |
| | | y2: 0, |
| | | colorStops: [{ |
| | | offset: 0, |
| | | color: '#0E5FFF' // 0% 处的颜色 |
| | | }, { |
| | | offset: 0.3, |
| | | color: '#00F2EF' // 50% 处的颜色 |
| | | }, { |
| | | offset: 0.7, |
| | | color: '#00F2EF' // 50% 处的颜色 |
| | | }, { |
| | | offset: 1, |
| | | color: '#0E5FFF' // 100% 处的颜色 |
| | | }] |
| | | } |
| | | }, |
| | | data: [] |
| | | } |
| | | ] |
| | | } |
| | | }; |
| | | }, |
| | | watch: { |
| | | data: { |
| | | handler(newVal, oldVal) { |
| | | if (newVal) { |
| | | this.rankingList = newVal.streetResponses |
| | | this.$nextTick(() => { |
| | | this.animateProgressBars(); |
| | | this.updateChartData(this.data.importErrorResponses); |
| | | }); |
| | | } |
| | | }, |
| | | deep: true, |
| | | immediate: true |
| | | } |
| | | }, |
| | | methods: { |
| | | animateProgressBars() { |
| | | let count = 0 |
| | | this.rankingList.map(item => { |
| | | count += item.householdNum; |
| | | }); |
| | | |
| | | this.rankingList = this.rankingList.map((item, index) => { |
| | | item.percentage = (item.householdNum / count) * 100; |
| | | return item |
| | | }); |
| | | }, |
| | | updateChartData(apiData) { |
| | | this.lineOption.xAxis.data = apiData.map(item => item.month); |
| | | this.lineOption.series[0].data = apiData.map(item => item.areaErrorCount); |
| | | this.lineOption.series[1].data = apiData.map(item => item.moneyErrorCount); |
| | | } |
| | | } |
| | | }; |
| | | </script> |
| | |
| | | left: 20px; |
| | | width: 440px; |
| | | bottom: 20px; |
| | | |
| | | .statistics-box { |
| | | height: 196px; |
| | | background: url('@/assets/left-top-bg.png') no-repeat center center; |
| | | background-size: 100% 100%; |
| | | |
| | | .box-content { |
| | | display: flex; |
| | | justify-content: center; |
| | | margin-top: 30px; |
| | | height: 100%; |
| | | |
| | | .box-content-item-title { |
| | | width: 178px; |
| | | height: 38px; |
| | | text-align: center; |
| | | line-height: 38px; |
| | | font-size: 15px; |
| | | background: url('@/assets/left/top-number-header.png') no-repeat center center; |
| | | background-size: 100% 100%; |
| | | } |
| | | |
| | | .box-content-item-value { |
| | | width: 178px; |
| | | height: 64px; |
| | | text-align: center; |
| | | line-height: 64px; |
| | | font-weight: bold; |
| | | font-size: 31px; |
| | | margin-top: 8px; |
| | | color: #66FFFF; |
| | | background: url('@/assets/left/top-number-box.png') no-repeat center center; |
| | | background-size: 100% 100%; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .ranking-box { |
| | | height: 466px; |
| | | margin-top: 21px; |
| | | background: url('@/assets/left-middle-bg.png') no-repeat center center; |
| | | background-size: 100% 100%; |
| | | } |
| | | |
| | | .line-chart { |
| | | height: 244px; |
| | | margin-top: 21px; |
| | | background: url('@/assets/left-bottom-bg.png') no-repeat center center; |
| | | background-size: 100% 100%; |
| | | } |
| | | |
| | | |
| | | .box-title { |
| | | font-size: 14px; |
| | |
| | | line-height: 21px; |
| | | } |
| | | |
| | | .ranking-list { |
| | | height: 400px; |
| | | margin-top: 30px; |
| | | overflow: auto; |
| | | /* 隐藏滚动条 */ |
| | | scrollbar-width: none; |
| | | /* Firefox */ |
| | | -ms-overflow-style: none; |
| | | |
| | | /* IE 和 Edge */ |
| | | &::-webkit-scrollbar { |
| | | display: none; |
| | | /* Chrome, Safari 和 Opera */ |
| | | } |
| | | } |
| | | |
| | | .ranking-item { |
| | | display: flex; |
| | | align-items: center; |
| | | padding: 7px 20px; |
| | | |
| | | .rank { |
| | | width: 20px; |
| | | color: #00ffff; |
| | | } |
| | | .ranking-item-content { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | margin-bottom: 6.5px; |
| | | |
| | | .name { |
| | | width: 80px; |
| | | } |
| | | .rank { |
| | | font-weight: bold; |
| | | font-size: 18px; |
| | | width: 22px; |
| | | height: 22px; |
| | | line-height: 22px; |
| | | padding-left: 2px; |
| | | |
| | | .progress-bar { |
| | | flex: 1; |
| | | height: 6px; |
| | | background: rgba(0,255,255,0.1); |
| | | border-radius: 3px; |
| | | &.rank-1 { |
| | | color: #E9B701; |
| | | background: url('@/assets/left/one.png') no-repeat center center; |
| | | background-size: 100% 100%; |
| | | } |
| | | |
| | | .progress { |
| | | height: 100%; |
| | | background: linear-gradient(to right, #00ffff, #7cb9e8); |
| | | border-radius: 3px; |
| | | &.rank-2 { |
| | | color: #0ED1A3; |
| | | background: url('@/assets/left/two.png') no-repeat center center; |
| | | background-size: 100% 100%; |
| | | } |
| | | |
| | | &.rank-3 { |
| | | color: #0EBFDA; |
| | | background: url('@/assets/left/three.png') no-repeat center center; |
| | | background-size: 100% 100%; |
| | | } |
| | | |
| | | &:not(.rank-1):not(.rank-2):not(.rank-3) { |
| | | color: #0089FF; |
| | | background: linear-gradient(270deg, rgba(0, 137, 255, 0) 0%, rgba(0, 137, 255, 0.4) 100%); |
| | | } |
| | | } |
| | | |
| | | .name { |
| | | flex: 1; |
| | | color: #C0CFDC; |
| | | margin: 0 4px; |
| | | font-size: 15px; |
| | | } |
| | | |
| | | .value { |
| | | color: #fff; |
| | | font-size: 15px; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | text-align: end; |
| | | width: 175px; |
| | | |
| | | .value-text { |
| | | color: #C0CFDC; |
| | | font-size: 12px; |
| | | |
| | | .value-text-value { |
| | | margin-left: 12px; |
| | | |
| | | &.positive { |
| | | color: #FEDB65; |
| | | } |
| | | |
| | | &.negative { |
| | | color: #66FFFF; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .value { |
| | | width: 60px; |
| | | text-align: right; |
| | | color: #00ffff; |
| | | .progress-bar { |
| | | height: 6px; |
| | | background: rgba(0, 255, 255, 0.1); |
| | | border-radius: 3px; |
| | | overflow: visible; |
| | | |
| | | .progress { |
| | | height: 100%; |
| | | border-radius: 3px; |
| | | width: 0; |
| | | transition: width 1.5s cubic-bezier(0.4, 0, 0.2, 1); |
| | | position: relative; |
| | | |
| | | .progress-icon { |
| | | position: absolute; |
| | | right: -8px; |
| | | top: 50%; |
| | | transform: translateY(-50%); |
| | | width: 22px; |
| | | height: 22px; |
| | | background-size: contain; |
| | | background-repeat: no-repeat; |
| | | background-position: center; |
| | | } |
| | | |
| | | &.rank-1 { |
| | | background: linear-gradient(90deg, #2A1802 0%, #C86A01 49%, #E5D704 100%); |
| | | |
| | | .progress-icon { |
| | | background-image: url('@/assets/left/progress-one.png'); |
| | | } |
| | | } |
| | | |
| | | &.rank-2 { |
| | | background: linear-gradient(270deg, #0ED1A3 0%, #03493E 100%); |
| | | |
| | | .progress-icon { |
| | | background-image: url('@/assets/left/progress-two.png'); |
| | | } |
| | | } |
| | | |
| | | &.rank-3 { |
| | | background: linear-gradient(90deg, #104461 0%, #0EB2DA 100%); |
| | | |
| | | .progress-icon { |
| | | background-image: url('@/assets/left/progress-three.png'); |
| | | } |
| | | } |
| | | |
| | | &:not(.rank-1):not(.rank-2):not(.rank-3) { |
| | | background: linear-gradient(90deg, #03142C 0%, #057BFF 49%, #05DBFF 100%); |
| | | |
| | | .progress-icon { |
| | | background-image: url('@/assets/left/progress-four.png'); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .chart-container { |
| | | height: calc(100% - 35px); |
| | | padding: 10px; |
| | | } |
| | | |
| | | .chart { |
| | | width: 100%; |
| | | height: calc(100% - 35px); |
| | | height: 100%; |
| | | } |
| | | } |
| | | </style> |
| | | </style> |