Commit 63a9fe11783fc7d6a31e45b276d2368dfea392be
Merge branch 'master' of http://39.98.150.180/webapp/GreenwayWeb
Showing
4 changed files
with
168 additions
and
130 deletions
admin-web-master/src/api/cereBusinessInfo.js
| @@ -52,3 +52,12 @@ export function getInvestmentStatistics(data) { | @@ -52,3 +52,12 @@ export function getInvestmentStatistics(data) { | ||
| 52 | }) | 52 | }) |
| 53 | } | 53 | } |
| 54 | 54 | ||
| 55 | +// 招商方案统计 | ||
| 56 | +export function getInvestmentPlanStatistics(data) { | ||
| 57 | + return request({ | ||
| 58 | + url: '/attractInvestmentStatisticsController/getInvestmentPlanStatistics', | ||
| 59 | + method: 'post', | ||
| 60 | + data | ||
| 61 | + }) | ||
| 62 | +} | ||
| 63 | + |
admin-web-master/src/views/rent/InvestmentAnalysis/index.vue
admin-web-master/src/views/scheme/statistics.vue
| @@ -7,14 +7,14 @@ | @@ -7,14 +7,14 @@ | ||
| 7 | </div> | 7 | </div> |
| 8 | <div class="toolbar"> | 8 | <div class="toolbar"> |
| 9 | <el-form :inline="true" :model="pageindex"> | 9 | <el-form :inline="true" :model="pageindex"> |
| 10 | - <el-form-item label="资源类型"> | 10 | + <!-- <el-form-item label="资源类型"> |
| 11 | <el-select placeholder="全部" v-model="pageindex.leaseType" | 11 | <el-select placeholder="全部" v-model="pageindex.leaseType" |
| 12 | style="width: 120px;margin-right: 15px"> | 12 | style="width: 120px;margin-right: 15px"> |
| 13 | <el-option label="商铺" value="商铺" /> | 13 | <el-option label="商铺" value="商铺" /> |
| 14 | <el-option label="场地" value="场地" /> | 14 | <el-option label="场地" value="场地" /> |
| 15 | <el-option label="广告位" value="广告位" /> | 15 | <el-option label="广告位" value="广告位" /> |
| 16 | </el-select> | 16 | </el-select> |
| 17 | - </el-form-item> | 17 | + </el-form-item> --> |
| 18 | <el-form-item label="日期"> | 18 | <el-form-item label="日期"> |
| 19 | <el-date-picker | 19 | <el-date-picker |
| 20 | v-model="pageindex.list" | 20 | v-model="pageindex.list" |
| @@ -75,7 +75,7 @@ | @@ -75,7 +75,7 @@ | ||
| 75 | 75 | ||
| 76 | <script> | 76 | <script> |
| 77 | import { | 77 | import { |
| 78 | - getInvestmentStatistics | 78 | + getInvestmentPlanStatistics |
| 79 | } from '@/api/cereBusinessInfo' | 79 | } from '@/api/cereBusinessInfo' |
| 80 | import * as echarts from 'echarts' | 80 | import * as echarts from 'echarts' |
| 81 | export default { | 81 | export default { |
| @@ -129,56 +129,42 @@ | @@ -129,56 +129,42 @@ | ||
| 129 | const chartDom = this.$refs.shop2TJ | 129 | const chartDom = this.$refs.shop2TJ |
| 130 | // 初始化 ECharts 实例 | 130 | // 初始化 ECharts 实例 |
| 131 | const myChart = echarts.init(chartDom); | 131 | const myChart = echarts.init(chartDom); |
| 132 | - // 模拟数据 | ||
| 133 | - const shopCount = 50; | ||
| 134 | - const adCount = 30; | ||
| 135 | - const venueCount = 20; | ||
| 136 | - const totalCount = shopCount + adCount + venueCount; | 132 | + |
| 137 | 133 | ||
| 138 | const option = { | 134 | const option = { |
| 139 | tooltip: { | 135 | tooltip: { |
| 140 | trigger: 'item', | 136 | trigger: 'item', |
| 141 | - formatter: '{a} <br/>{b}: {c} ({d}%)' | 137 | + formatter: function (params) { |
| 138 | + const dataItem = val.find(item => item.businessPurpose === params.name); | ||
| 139 | + return `${params.name}<br/>数量: ${dataItem.num}<br/>占比: ${dataItem.proportion}%`; | ||
| 140 | + } | ||
| 142 | }, | 141 | }, |
| 143 | legend: { | 142 | legend: { |
| 144 | orient: 'horizontal', // 横向展示 | 143 | orient: 'horizontal', // 横向展示 |
| 145 | left: 'center', // 居中显示 | 144 | left: 'center', // 居中显示 |
| 146 | - data: ['商铺', '广告位', '场地'] | 145 | + data: val.map(item => item.businessPurpose) |
| 147 | }, | 146 | }, |
| 148 | series: [ | 147 | series: [ |
| 149 | { | 148 | { |
| 149 | + color: ['#4A90E2', '#37c954','#ff94e8', '#7a69d8','#aaffe7', '#8cd89b','#feff89', '#d8d6d5'], | ||
| 150 | name: '资源分布', | 150 | name: '资源分布', |
| 151 | type: 'pie', | 151 | type: 'pie', |
| 152 | - radius: ['50%', '70%'], | 152 | + radius: ['0%', '60%'], |
| 153 | avoidLabelOverlap: false, | 153 | avoidLabelOverlap: false, |
| 154 | label: { | 154 | label: { |
| 155 | show: true, | 155 | show: true, |
| 156 | position: 'outside', | 156 | position: 'outside', |
| 157 | - formatter: '{b}: {c}' | 157 | + formatter: '{b}: {c}%' |
| 158 | }, | 158 | }, |
| 159 | labelLine: { | 159 | labelLine: { |
| 160 | show: true | 160 | show: true |
| 161 | }, | 161 | }, |
| 162 | - data: [ | ||
| 163 | - { value: shopCount, name: '商铺' }, | ||
| 164 | - { value: adCount, name: '广告位' }, | ||
| 165 | - { value: venueCount, name: '场地' } | ||
| 166 | - ] | 162 | + data: val.map(item => ({ |
| 163 | + value: item.proportion, | ||
| 164 | + name: item.businessPurpose | ||
| 165 | + })) | ||
| 167 | }, | 166 | }, |
| 168 | - { | ||
| 169 | - name: '总量', | ||
| 170 | - type: 'pie', | ||
| 171 | - radius: ['0%', '0%'], // 不显示圆形 | ||
| 172 | - label: { | ||
| 173 | - show: true, | ||
| 174 | - position: 'center', | ||
| 175 | - formatter: `总量: ${totalCount}`, | ||
| 176 | - fontSize: 20 | ||
| 177 | - }, | ||
| 178 | - data: [ | ||
| 179 | - { value: totalCount, name: '总量' } | ||
| 180 | - ] | ||
| 181 | - } | 167 | + |
| 182 | ] | 168 | ] |
| 183 | }; | 169 | }; |
| 184 | // 使用刚指定的配置项和数据显示图表 | 170 | // 使用刚指定的配置项和数据显示图表 |
| @@ -191,25 +177,38 @@ | @@ -191,25 +177,38 @@ | ||
| 191 | 177 | ||
| 192 | const chartDom = this.$refs.shop1ZX; | 178 | const chartDom = this.$refs.shop1ZX; |
| 193 | const myChart = echarts.init(chartDom) | 179 | const myChart = echarts.init(chartDom) |
| 194 | - | ||
| 195 | - // 模拟数据 | ||
| 196 | - const shopCount = 50; | ||
| 197 | - const adCount = 30; | ||
| 198 | - const venueCount = 20; | ||
| 199 | - const totalCount = shopCount + adCount + venueCount; | 180 | + let shopCount = 0; |
| 181 | + let adCount = 0; | ||
| 182 | + let venueCount = 0; | ||
| 183 | + let totalCount = 0; | ||
| 184 | + val.forEach(item => { | ||
| 185 | + totalCount += item.num; | ||
| 186 | + if (item.businessPurpose === '商铺合同') { | ||
| 187 | + shopCount = item.proportion; | ||
| 188 | + } else if (item.businessPurpose === '场地合同') { | ||
| 189 | + venueCount = item.proportion; | ||
| 190 | + } else if (item.businessPurpose === '广告位合同') { | ||
| 191 | + adCount = item.proportion; | ||
| 192 | + } | ||
| 193 | + }); | ||
| 200 | 194 | ||
| 201 | const option = { | 195 | const option = { |
| 202 | tooltip: { | 196 | tooltip: { |
| 203 | trigger: 'item', | 197 | trigger: 'item', |
| 204 | - formatter: '{a} <br/>{b}: {c} ({d}%)' | 198 | + formatter: function (params) { |
| 199 | + const dataItem = val.find(item => item.businessPurpose === params.name); | ||
| 200 | + return `${params.name}<br/>数量: ${dataItem.num}<br/>占比: ${dataItem.proportion}%`; | ||
| 201 | + } | ||
| 205 | }, | 202 | }, |
| 206 | legend: { | 203 | legend: { |
| 207 | - orient: 'horizontal', // 横向展示 | ||
| 208 | - left: 'center', // 居中显示 | ||
| 209 | - data: ['商铺', '广告位', '场地'] | 204 | + orient: 'horizontal', |
| 205 | + left: 'center', | ||
| 206 | + data: val.map(item => item.businessPurpose) | ||
| 210 | }, | 207 | }, |
| 211 | series: [ | 208 | series: [ |
| 209 | + | ||
| 212 | { | 210 | { |
| 211 | + color: ['#4A90E2', '#37c954','#ff94e8', '#7a69d8','#aaffe7', '#8cd89b','#feff89', '#d8d6d5'], | ||
| 213 | name: '资源分布', | 212 | name: '资源分布', |
| 214 | type: 'pie', | 213 | type: 'pie', |
| 215 | radius: ['50%', '70%'], | 214 | radius: ['50%', '70%'], |
| @@ -217,30 +216,27 @@ | @@ -217,30 +216,27 @@ | ||
| 217 | label: { | 216 | label: { |
| 218 | show: true, | 217 | show: true, |
| 219 | position: 'outside', | 218 | position: 'outside', |
| 220 | - formatter: '{b}: {c}' | 219 | + formatter: '{b}: {c}%' |
| 221 | }, | 220 | }, |
| 222 | labelLine: { | 221 | labelLine: { |
| 223 | show: true | 222 | show: true |
| 224 | }, | 223 | }, |
| 225 | - data: [ | ||
| 226 | - { value: shopCount, name: '商铺' }, | ||
| 227 | - { value: adCount, name: '广告位' }, | ||
| 228 | - { value: venueCount, name: '场地' } | ||
| 229 | - ] | 224 | + data: val.map(item => ({ |
| 225 | + value: item.proportion, | ||
| 226 | + name: item.businessPurpose | ||
| 227 | + })) | ||
| 230 | }, | 228 | }, |
| 231 | { | 229 | { |
| 232 | - name: '总量', | ||
| 233 | - type: 'pie', | ||
| 234 | - radius: ['0%', '0%'], // 不显示圆形 | ||
| 235 | - label: { | ||
| 236 | - show: true, | ||
| 237 | - position: 'center', | ||
| 238 | - formatter: `总量: ${totalCount}`, | ||
| 239 | - fontSize: 20 | ||
| 240 | - }, | ||
| 241 | - data: [ | ||
| 242 | - { value: totalCount, name: '总量' } | ||
| 243 | - ] | 230 | + name: '总数', |
| 231 | + type: 'pie', | ||
| 232 | + radius: ['0%', '0%'], | ||
| 233 | + label: { | ||
| 234 | + show: true, | ||
| 235 | + position: 'center', | ||
| 236 | + formatter: `总数: ${totalCount}`, | ||
| 237 | + fontSize: 20 | ||
| 238 | + }, | ||
| 239 | + data: [{ value: totalCount, name: '总数' }] | ||
| 244 | } | 240 | } |
| 245 | ] | 241 | ] |
| 246 | }; | 242 | }; |
| @@ -251,15 +247,21 @@ | @@ -251,15 +247,21 @@ | ||
| 251 | charDam3(val) { | 247 | charDam3(val) { |
| 252 | let Dom = this.$refs.shop1TJ | 248 | let Dom = this.$refs.shop1TJ |
| 253 | let myChart = echarts.init(Dom) | 249 | let myChart = echarts.init(Dom) |
| 254 | - // val.sort((a, b) => { | ||
| 255 | - // return new Date(a.mouth) - new Date(b.mouth); | ||
| 256 | - // }); | ||
| 257 | - // const months = val.map(item => item.mouth); | ||
| 258 | - // const intentMerchants = val.map(item => item.intention); | ||
| 259 | - // const signedMerchants = val.map(item => item.signContract); | ||
| 260 | - // 模拟月度签约数据 | ||
| 261 | - const months = ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月']; | ||
| 262 | - const contractCounts = [12, 15, 20, 18, 22, 25, 28, 30, 26, 24, 21, 23]; | 250 | + // 处理数据 |
| 251 | + const months = Object.keys(val).reverse(); // 反转月份顺序,最新月份在前 | ||
| 252 | + const shopData = []; | ||
| 253 | + const venueData = []; | ||
| 254 | + const adData = []; | ||
| 255 | + | ||
| 256 | + months.forEach(month => { | ||
| 257 | + const monthData = val[month]; | ||
| 258 | + const shop = monthData.find(item => item.contractType === '商铺合同')?.contractCount || 0; | ||
| 259 | + const venue = monthData.find(item => item.contractType === '场地合同')?.contractCount || 0; | ||
| 260 | + const ad = monthData.find(item => item.contractType === '广告位合同')?.contractCount || 0; | ||
| 261 | + shopData.push(shop); | ||
| 262 | + venueData.push(venue); | ||
| 263 | + adData.push(ad); | ||
| 264 | + }); | ||
| 263 | 265 | ||
| 264 | const option = { | 266 | const option = { |
| 265 | tooltip: { | 267 | tooltip: { |
| @@ -272,33 +274,37 @@ | @@ -272,33 +274,37 @@ | ||
| 272 | }, | 274 | }, |
| 273 | yAxis: { | 275 | yAxis: { |
| 274 | type: 'value', | 276 | type: 'value', |
| 275 | - name: '签约数' | 277 | + name: '合同数量' |
| 276 | }, | 278 | }, |
| 277 | series: [ | 279 | series: [ |
| 278 | { | 280 | { |
| 279 | - name: '签约数', | 281 | + name: '商铺合同', |
| 280 | type: 'line', | 282 | type: 'line', |
| 281 | - data: contractCounts, | 283 | + data: shopData, |
| 282 | symbol: 'circle', | 284 | symbol: 'circle', |
| 283 | - lineStyle: { | ||
| 284 | - color: '#4A90E2' | ||
| 285 | - }, | ||
| 286 | - itemStyle: { | ||
| 287 | - color: '#4A90E2' | ||
| 288 | - }, | ||
| 289 | - areaStyle: { | ||
| 290 | - color: new echarts.graphic.LinearGradient( | ||
| 291 | - 0, 0, 0, 1, | ||
| 292 | - [ | ||
| 293 | - { offset: 0, color: 'rgba(74, 144, 226, 0.3)' }, | ||
| 294 | - { offset: 1, color: 'rgba(74, 144, 226, 0.1)' } | ||
| 295 | - ] | ||
| 296 | - ) | ||
| 297 | - } | 285 | + lineStyle: { color: '#4A90E2' }, |
| 286 | + itemStyle: { color: '#4A90E2' } | ||
| 287 | + }, | ||
| 288 | + { | ||
| 289 | + name: '场地合同', | ||
| 290 | + type: 'line', | ||
| 291 | + data: venueData, | ||
| 292 | + symbol: 'square', | ||
| 293 | + lineStyle: { color: '#52C41A' }, | ||
| 294 | + itemStyle: { color: '#52C41A' } | ||
| 295 | + }, | ||
| 296 | + { | ||
| 297 | + name: '广告位合同', | ||
| 298 | + type: 'line', | ||
| 299 | + data: adData, | ||
| 300 | + symbol: 'triangle', | ||
| 301 | + lineStyle: { color: '#FF7800' }, | ||
| 302 | + itemStyle: { color: '#FF7800' } | ||
| 298 | } | 303 | } |
| 299 | ] | 304 | ] |
| 300 | }; | 305 | }; |
| 301 | 306 | ||
| 307 | + | ||
| 302 | option && myChart.setOption(option); | 308 | option && myChart.setOption(option); |
| 303 | window.addEventListener('resize', function() { | 309 | window.addEventListener('resize', function() { |
| 304 | myChart.resize(); | 310 | myChart.resize(); |
| @@ -313,48 +319,72 @@ | @@ -313,48 +319,72 @@ | ||
| 313 | const myChart = echarts.init(chartDom); | 319 | const myChart = echarts.init(chartDom); |
| 314 | 320 | ||
| 315 | 321 | ||
| 316 | - // 模拟租金价格数据,这里假设是按月份统计 | ||
| 317 | - const months = ['1月', '2月', '3月', '4月', '5月', '6月']; | ||
| 318 | - const rentPrices = [50, 52, 55, 53, 56, 58]; | ||
| 319 | - | ||
| 320 | - const option = { | ||
| 321 | - tooltip: { | ||
| 322 | - trigger: 'axis' | ||
| 323 | - }, | ||
| 324 | - xAxis: { | ||
| 325 | - type: 'category', | ||
| 326 | - data: months, | ||
| 327 | - boundaryGap: false | ||
| 328 | - }, | ||
| 329 | - yAxis: { | ||
| 330 | - type: 'value', | ||
| 331 | - name: '租金价格(元/m²)' | ||
| 332 | - }, | ||
| 333 | - series: [ | ||
| 334 | - { | 322 | + const allDates = []; |
| 323 | + const leaseTerms = ['季', '年', '日', '月']; | ||
| 324 | + const seriesData = { | ||
| 325 | + '季': [], | ||
| 326 | + '年': [], | ||
| 327 | + '日': [], | ||
| 328 | + '月': [] | ||
| 329 | + }; | ||
| 330 | + | ||
| 331 | + // 收集所有日期 | ||
| 332 | + leaseTerms.forEach(term => { | ||
| 333 | + val[term].forEach(item => { | ||
| 334 | + if (!allDates.includes(item.createDay)) { | ||
| 335 | + allDates.push(item.createDay); | ||
| 336 | + } | ||
| 337 | + }); | ||
| 338 | + }); | ||
| 339 | + | ||
| 340 | + // 按日期排序 | ||
| 341 | + allDates.sort(); | ||
| 342 | + | ||
| 343 | + // 填充各租赁期限的数据 | ||
| 344 | + leaseTerms.forEach(term => { | ||
| 345 | + allDates.forEach(date => { | ||
| 346 | + const found = val[term].find(item => item.createDay === date); | ||
| 347 | + seriesData[term].push(found ? found.rentalPrice : null); | ||
| 348 | + }); | ||
| 349 | + }); | ||
| 350 | + | ||
| 351 | + const option = { | ||
| 352 | + tooltip: { | ||
| 353 | + trigger: 'axis', | ||
| 354 | + axisPointer: { | ||
| 355 | + type: 'cross', | ||
| 356 | + crossStyle: { | ||
| 357 | + color: '#999' | ||
| 358 | + } | ||
| 359 | + } | ||
| 360 | + }, | ||
| 361 | + legend: { | ||
| 362 | + data: leaseTerms | ||
| 363 | + }, | ||
| 364 | + xAxis: { | ||
| 365 | + type: 'category', | ||
| 366 | + data: allDates | ||
| 367 | + }, | ||
| 368 | + yAxis: { | ||
| 369 | + type: 'value', | ||
| 335 | name: '租金价格', | 370 | name: '租金价格', |
| 371 | + axisLabel: { | ||
| 372 | + formatter: '{value}' | ||
| 373 | + } | ||
| 374 | + }, | ||
| 375 | + series: leaseTerms.map(term => ({ | ||
| 376 | + name: term, | ||
| 336 | type: 'line', | 377 | type: 'line', |
| 337 | - data: rentPrices, | 378 | + data: seriesData[term], |
| 338 | symbol: 'circle', | 379 | symbol: 'circle', |
| 339 | - lineStyle: { | ||
| 340 | - color: '#4A90E2' | 380 | + label: { |
| 381 | + show: false | ||
| 341 | }, | 382 | }, |
| 342 | - itemStyle: { | ||
| 343 | - color: '#4A90E2' | ||
| 344 | - }, | ||
| 345 | - areaStyle: { | ||
| 346 | - color: new echarts.graphic.LinearGradient( | ||
| 347 | - 0, 0, 0, 1, | ||
| 348 | - [ | ||
| 349 | - { offset: 0, color: 'rgba(74, 144, 226, 0.3)' }, | ||
| 350 | - { offset: 1, color: 'rgba(74, 144, 226, 0.1)' } | ||
| 351 | - ] | ||
| 352 | - ) | 383 | + lineStyle: { |
| 384 | + width: 2 | ||
| 353 | } | 385 | } |
| 354 | - } | ||
| 355 | - ] | ||
| 356 | - }; | ||
| 357 | - | 386 | + })) |
| 387 | + }; | ||
| 358 | // 使用刚指定的配置项和数据显示图表 | 388 | // 使用刚指定的配置项和数据显示图表 |
| 359 | option && myChart.setOption(option) | 389 | option && myChart.setOption(option) |
| 360 | window.addEventListener('resize', function() { | 390 | window.addEventListener('resize', function() { |
| @@ -364,11 +394,11 @@ | @@ -364,11 +394,11 @@ | ||
| 364 | }, | 394 | }, |
| 365 | 395 | ||
| 366 | async getAll() { | 396 | async getAll() { |
| 367 | - const res = await getInvestmentStatistics(this.pageindex) | ||
| 368 | - this.charDam3() | ||
| 369 | - this.charDam1() | ||
| 370 | - this.charDam() | ||
| 371 | - this.charDam5() | 397 | + const res = await getInvestmentPlanStatistics(this.pageindex) |
| 398 | + this.charDam3(res.data.monthlyContractVOList) | ||
| 399 | + this.charDam1(res.data.resourceUsageRatioVOList) | ||
| 400 | + this.charDam(res.data.businessTypeProportionList) | ||
| 401 | + this.charDam5(res.data.rentTrendMap) | ||
| 372 | 402 | ||
| 373 | }, | 403 | }, |
| 374 | 404 |
lvdao-miniapp/pagesA/rentPay/rentPayDetails.vue
| @@ -138,7 +138,6 @@ | @@ -138,7 +138,6 @@ | ||
| 138 | }, | 138 | }, |
| 139 | confirm(e) { | 139 | confirm(e) { |
| 140 | this.pageIndex.time = e.year | 140 | this.pageIndex.time = e.year |
| 141 | - | ||
| 142 | const { | 141 | const { |
| 143 | firstDay, | 142 | firstDay, |
| 144 | lastDay | 143 | lastDay |
| @@ -150,7 +149,6 @@ | @@ -150,7 +149,6 @@ | ||
| 150 | }, 1).then(res => { | 149 | }, 1).then(res => { |
| 151 | console.log(res) | 150 | console.log(res) |
| 152 | if (res.data.data.length > 0) { | 151 | if (res.data.data.length > 0) { |
| 153 | - | ||
| 154 | this.getAll(res.data.data[0].cerePropertyOrderList) | 152 | this.getAll(res.data.data[0].cerePropertyOrderList) |
| 155 | } else { | 153 | } else { |
| 156 | this.dataList = [] | 154 | this.dataList = [] |