| | |
| | | "webpack-merge": "^5.7.3", |
| | | "webpack-virtual-modules": "^0.4.2", |
| | | "whatwg-fetch": "^3.6.2" |
| | | }, |
| | | "dependencies": { |
| | | "@vue/vue-loader-v15": { |
| | | "version": "npm:vue-loader@15.11.1", |
| | | "resolved": "https://registry.npmmirror.com/vue-loader/-/vue-loader-15.11.1.tgz", |
| | | "integrity": "sha512-0iw4VchYLePqJfJu9s62ACWUXeSqM30SQqlIftbYWM3C+jpPcEHKSPUZBLjSF9au4HTHQ/naF6OGnO3Q/qGR3Q==", |
| | | "dev": true, |
| | | "requires": { |
| | | "@vue/component-compiler-utils": "^3.1.0", |
| | | "hash-sum": "^1.0.2", |
| | | "loader-utils": "^1.1.0", |
| | | "vue-hot-reload-api": "^2.3.0", |
| | | "vue-style-loader": "^4.1.0" |
| | | }, |
| | | "dependencies": { |
| | | "hash-sum": { |
| | | "version": "1.0.2", |
| | | "resolved": "https://registry.npmmirror.com/hash-sum/-/hash-sum-1.0.2.tgz", |
| | | "integrity": "sha512-fUs4B4L+mlt8/XAtSOGMUO1TXmAelItBPtJG7CyHJfYTdDjwisntGO2JQz7oUsatOY9o68+57eziUVNw/mRHmA==", |
| | | "dev": true |
| | | } |
| | | } |
| | | }, |
| | | "json5": { |
| | | "version": "1.0.2", |
| | | "resolved": "https://registry.npmmirror.com/json5/-/json5-1.0.2.tgz", |
| | | "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", |
| | | "dev": true, |
| | | "requires": { |
| | | "minimist": "^1.2.0" |
| | | } |
| | | }, |
| | | "loader-utils": { |
| | | "version": "1.4.2", |
| | | "resolved": "https://registry.npmmirror.com/loader-utils/-/loader-utils-1.4.2.tgz", |
| | | "integrity": "sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==", |
| | | "dev": true, |
| | | "requires": { |
| | | "big.js": "^5.2.2", |
| | | "emojis-list": "^3.0.0", |
| | | "json5": "^1.0.1" |
| | | } |
| | | } |
| | | } |
| | | }, |
| | | "@vue/cli-shared-utils": { |
| | |
| | | "integrity": "sha512-/hnE/qP5ZoGpol0a5mDi45bOd7t3tjYJBjsgCsivow7D48cJeV5l05RD82lPqi7gRiphZM37rnhW1l6ZoCNNnQ==", |
| | | "dev": true |
| | | }, |
| | | "@vue/vue-loader-v15": { |
| | | "version": "npm:vue-loader@15.11.1", |
| | | "resolved": "https://registry.npmmirror.com/vue-loader/-/vue-loader-15.11.1.tgz", |
| | | "integrity": "sha512-0iw4VchYLePqJfJu9s62ACWUXeSqM30SQqlIftbYWM3C+jpPcEHKSPUZBLjSF9au4HTHQ/naF6OGnO3Q/qGR3Q==", |
| | | "dev": true, |
| | | "requires": { |
| | | "@vue/component-compiler-utils": "^3.1.0", |
| | | "hash-sum": "^1.0.2", |
| | | "loader-utils": "^1.1.0", |
| | | "vue-hot-reload-api": "^2.3.0", |
| | | "vue-style-loader": "^4.1.0" |
| | | }, |
| | | "dependencies": { |
| | | "hash-sum": { |
| | | "version": "1.0.2", |
| | | "resolved": "https://registry.npmmirror.com/hash-sum/-/hash-sum-1.0.2.tgz", |
| | | "integrity": "sha512-fUs4B4L+mlt8/XAtSOGMUO1TXmAelItBPtJG7CyHJfYTdDjwisntGO2JQz7oUsatOY9o68+57eziUVNw/mRHmA==", |
| | | "dev": true |
| | | }, |
| | | "json5": { |
| | | "version": "1.0.2", |
| | | "resolved": "https://registry.npmmirror.com/json5/-/json5-1.0.2.tgz", |
| | | "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", |
| | | "dev": true, |
| | | "requires": { |
| | | "minimist": "^1.2.0" |
| | | } |
| | | }, |
| | | "loader-utils": { |
| | | "version": "1.4.2", |
| | | "resolved": "https://registry.npmmirror.com/loader-utils/-/loader-utils-1.4.2.tgz", |
| | | "integrity": "sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==", |
| | | "dev": true, |
| | | "requires": { |
| | | "big.js": "^5.2.2", |
| | | "emojis-list": "^3.0.0", |
| | | "json5": "^1.0.1" |
| | | } |
| | | } |
| | | } |
| | | }, |
| | | "@vue/web-component-wrapper": { |
| | | "version": "1.3.0", |
| | | "resolved": "https://registry.npmmirror.com/@vue/web-component-wrapper/-/web-component-wrapper-1.3.0.tgz", |
| | |
| | | <div class="box-content"> |
| | | <div class="box-content-item"> |
| | | <div class="box-content-item-title">总参与户数(户)</div> |
| | | <div class="box-content-item-value">87695</div> |
| | | <div class="box-content-item-value">{{ data.selfBuyResponse.householdNum || 0 }}</div> |
| | | </div> |
| | | <div class="box-content-item" style="margin-left: 35px;"> |
| | | <div class="box-content-item-title">总参与人数(人)</div> |
| | | <div class="box-content-item-value">876995</div> |
| | | <div class="box-content-item-value">{{ data.selfBuyResponse.personNum || 0 }}</div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | |
| | | <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.name }}</span> |
| | | <span class="name">{{ item.street }}</span> |
| | | <div class="value"> |
| | | <div class="value-text"> |
| | | 环比 |
| | | <span class="value-text-value" :class="{ 'positive': item.growth > 0, 'negative': item.growth < 0 }"> |
| | | {{ item.growth > 0 ? '+' : '' }}{{ item.growth }}% |
| | | <span class="value-text-value" |
| | | :class="{ 'positive': item.latestBatchHouseholdCount < item.secondLatestBatchHouseholdCount, 'negative': item.latestBatchHouseholdCount > item.secondLatestBatchHouseholdCount }"> |
| | | {{ item.growth > 0 ? '+' : '' }}{{ item.householdNumRate }} |
| | | </span> |
| | | </div> |
| | | {{ item.value }} |
| | | {{ item.householdNum }}户 |
| | | </div> |
| | | </div> |
| | | <div class="progress-bar"> |
| | |
| | | <script> |
| | | export default { |
| | | name: 'LeftPanel', |
| | | components: { |
| | | props: { |
| | | data: { |
| | | type: Object, |
| | | default: () => ({}) |
| | | }, |
| | | }, |
| | | data() { |
| | | return { |
| | | totalHouseholds: 87695, |
| | | totalPeople: 876995, |
| | | rankingList: [ |
| | | { name: '崇州街道', percentage: 0, value: '999户', growth: 43.2 }, |
| | | { name: '羊马乡', percentage: 0, value: '999户', growth: -12.5 }, |
| | | { name: '万家镇', percentage: 0, value: '999户', growth: 8.3 }, |
| | | { name: '崇阳街道', percentage: 0, value: '999户', growth: -5.2 }, |
| | | { name: '白头镇', percentage: 0, value: '999户', growth: 15.7 }, |
| | | { name: '金鸡乡', percentage: 0, value: '999户', growth: -3.8 }, |
| | | { name: '西江镇', percentage: 0, value: '999户', growth: 22.1 }, |
| | | { name: '观胜镇', percentage: 0, value: '999户', growth: -7.4 } |
| | | ], |
| | | finalPercentages: [ |
| | | 50, 85, 80, 75, 70, 65, 60, 55 |
| | | ], |
| | | |
| | | totalHouseholds: 0, |
| | | totalPeople: 0, |
| | | rankingList: [], |
| | | lineOption: { |
| | | tooltip: { |
| | | trigger: 'axis', |
| | |
| | | } |
| | | ] |
| | | } |
| | | |
| | | }; |
| | | }, |
| | | mounted() { |
| | | // 使用 setTimeout 确保 DOM 已经渲染 |
| | | setTimeout(() => { |
| | | this.animateProgressBars(); |
| | | }, 100); |
| | | watch: { |
| | | data: { |
| | | handler(newVal, oldVal) { |
| | | if (newVal) { |
| | | this.rankingList = newVal.streetResponses |
| | | this.$nextTick(() => { |
| | | this.animateProgressBars(); |
| | | }); |
| | | } |
| | | }, |
| | | deep: true, |
| | | immediate: true |
| | | } |
| | | }, |
| | | methods: { |
| | | animateProgressBars() { |
| | | this.rankingList = this.rankingList.map((item, index) => ({ |
| | | ...item, |
| | | percentage: this.finalPercentages[index] |
| | | })); |
| | | 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 |
| | | }); |
| | | } |
| | | } |
| | | }; |
| | |
| | | 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; |
| | |
| | | background: url('@/assets/left/top-number-header.png') no-repeat center center; |
| | | background-size: 100% 100%; |
| | | } |
| | | |
| | | .box-content-item-value { |
| | | width: 178px; |
| | | height: 64px; |
| | |
| | | |
| | | .ranking-list { |
| | | margin-top: 30px; |
| | | overflow: auto; |
| | | /* 隐藏滚动条 */ |
| | | scrollbar-width: none; |
| | | /* Firefox */ |
| | | -ms-overflow-style: none; |
| | | |
| | | /* IE 和 Edge */ |
| | | &::-webkit-scrollbar { |
| | | display: none; |
| | | /* Chrome, Safari 和 Opera */ |
| | | } |
| | | } |
| | | |
| | | .ranking-item { |
| | |
| | | height: 22px; |
| | | line-height: 22px; |
| | | padding-left: 2px; |
| | | |
| | | |
| | | &.rank-1 { |
| | | color: #E9B701; |
| | | background: url('@/assets/left/one.png') no-repeat center center; |
| | | background-size: 100% 100%; |
| | | } |
| | | |
| | | |
| | | &.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%); |
| | | background: linear-gradient(270deg, rgba(0, 137, 255, 0) 0%, rgba(0, 137, 255, 0.4) 100%); |
| | | } |
| | | } |
| | | |
| | |
| | | font-size: 15px; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | text-align: end; |
| | | width: 175px; |
| | | |
| | | .value-text { |
| | | color: #C0CFDC; |
| | | font-size: 12px; |
| | | width: 130px; |
| | | |
| | | .value-text-value { |
| | | margin-left: 12px; |
| | | |
| | | &.positive { |
| | | color: #FEDB65; |
| | | } |
| | | |
| | | &.negative { |
| | | color: #66FFFF; |
| | | } |
| | |
| | | width: 0; |
| | | transition: width 1.5s cubic-bezier(0.4, 0, 0.2, 1); |
| | | position: relative; |
| | | |
| | | |
| | | .progress-icon { |
| | | position: absolute; |
| | | right: -8px; |
| | |
| | | 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'); |
| | | } |
| | |
| | | import 'echarts/lib/component/legend'; |
| | | import 'echarts/lib/component/grid'; |
| | | Vue.component('v-chart', ECharts); |
| | | import './assets/font/font.css' |
| | | |
| | | Vue.prototype.$echarts = echarts |
| | | Vue.config.productionTip = false |
| | | |
| | |
| | | // 请求拦截 |
| | | service.interceptors.request.use( |
| | | config => { |
| | | const token = localStorage.getItem('token') |
| | | const token = localStorage.getItem('token') || 'Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJhZG1pbiIsImxvZ2luX3VzZXJfa2V5IjoiZWFjMDUyNWMtZjk4Mi00OWY3LWI5MTYtOTZlMmM0NzNjYjg1In0.zUMiAEKOfuto9pX4r3sKK7rfRDm-YRfSERi-0bRoBnvZKB7mApG2SdYPKRIiB6IyX7Fwz7o8IC9D3Svl2v5gMw' |
| | | if (token) { |
| | | // 添加token到请求头 |
| | | config.headers['Authorization'] = token |
| | |
| | | <template> |
| | | <div class="data-screen" :style="screenStyle"> |
| | | <header-panel /> |
| | | <left-panel /> |
| | | <left-panel v-if="!loading" :data="data" /> |
| | | <center-panel v-if="!loading" :data="data" /> |
| | | <right-panel /> |
| | | </div> |