Commit 2f084236 authored by wangjiankun's avatar wangjiankun

feat: 楼盘详情-产品分析-图表与表格数据渲染 项目整体颜色风格修改 板块产品分析--显示户型假分页

fix: 图片改为http地址 可视化图表配色、表格样式修改 实验高德地图与百度地图坐标转换
parent 2dadbb4f
......@@ -40,3 +40,26 @@ export function queryPropertySupplyData(projectId) {
projectId
})
}
// 根据楼盘id查询产品分析详情
export function queryAnalysisById(projectId) {
return xhr.get('/bnsproject/bns-project/withProjectAndProduct/getDetilProduct', {
projectId
})
}
// 根据土拍Id集合查询土拍信息
export function queryLandInfoById(landListId) {
return xhr.post('/bnsproject/bns-project/withProjectAndProduct/getAllLandByIds',{
landListId: JSON.stringify(landListId)
})
}
// 获取楼盘详情中 产品分析的导出Json数据
export function getJsonForProduction(projectId) {
return xhr.get('/bnsproject/bns-project/withProjectAndProduct/getDetilProductJson', {
projectId
})
}
// 导出楼盘详情 产品供求数据与产品分析数据
export function exportPropertyAnalysis(data) {
return xhr.downloadFile('/bnsregion/bns-region/downloadLP', data)
}
......@@ -40,3 +40,29 @@ export function averagePosition(array) {
latitude: Number((lat/array.length).toFixed(6))
}
}
// base64编码转BLOB对象
export function dataURLtoBlob(dataurl) {
var arr = dataurl.split(',');
var bstr = atob(arr[1]);
var n = bstr.length;
var mime = arr[0].match(/:(.*?);/)[1]
var u8arr = new Uint8Array(n)
while(n--){
u8arr[n] = bstr.charCodeAt(n);
}
return new Blob([u8arr], {type: mime });
}
// 高得地图坐标转为百度地图坐标
export function GDmapPositionTransform(lng, lat) {
var X_PI = Math.PI * 3000.0 / 180.0;
var x = lng, y = lat;
var z = Math.sqrt(x * x + y * y) + 0.00002 * Math.sin(y * X_PI);
var theta = Math.atan2(y, x) + 0.000003 * Math.cos(x * X_PI);
var bd_lng = z * Math.cos(theta) + 0.0065;
var bd_lat = z * Math.sin(theta) + 0.006;
return {
lng: bd_lat,
lat: bd_lng
};
}
......@@ -33,7 +33,7 @@ export default {
.hamburger-wrapper {
height: 100%;
padding: 0 15px;
line-height: 50px;
line-height: 60px;
float: left;
cursor: pointer;
&:hover {
......
......@@ -92,13 +92,29 @@ export default {
<style lang="stylus" scoped>
.menu-wrapper {
width: 100%;
display: inline-flex;
justify-content: center;
a {
display: inline-block;
width: 100%;
overflow: hidden;
width 90%;
margin 0 auto;
border-radius 10px
text-decoration none
.active {
background-color: rgb(46, 117, 182)!important
.el-menu-item{
background-color transparent
padding 0 20px!important
height 44px
span {
margin-left 10px
}
}
.is-active {
background-color: #EC7F5F!important
}
li:hover {
background-color: #EC7F5F!important
}
}
.svg-icon {
......@@ -112,4 +128,7 @@ export default {
}
}
}
.menu-wrapper:nth-child(2n) {
margin 20px 0
}
</style>
......@@ -2,16 +2,14 @@
<div class="app-wrapper">
<el-container>
<el-aside :width="isCollapse ? 'auto' : '200px'">
<div class="system-name">
<i class="el-icon-box" :title="systemName"></i>
<span v-if="!isCollapse">&nbsp;{{ systemName }}</span>
<div class="logon-container">
</div>
<transition name="fade">
<el-menu
:default-active="$route.path"
class="el-menu-vertical"
:collapse="isCollapse"
:background-color="menuStyle.menuBg"
:text-color="menuStyle.menuText"
:active-text-color="menuStyle.menuActiveText"
>
......@@ -25,7 +23,7 @@
</transition>
</el-aside>
<el-container>
<el-header height="50px">
<el-header height="60px">
<hamburger
:toggle-click="toggleSideBar"
:is-active="isCollapse"
......@@ -115,8 +113,8 @@ export default {
}
.el-header {
padding-left 0
background #fff
box-shadow: 0 1px 4px rgba(0,21,41,.08);
background-color: #e3ecf3;
display flex
flex-direction row
align-items center
......@@ -125,14 +123,21 @@ export default {
}
}
.el-aside {
.system-name {
padding-left 20px
font-size 22px
line-height 50px
color rgb(236, 240, 241)
display flex
flex-direction column
background:linear-gradient(180deg,rgba(40,102,144,1) 0%,rgba(16,34,68,1) 100%) !important;
.logon-container {
height 120px
width 100%
background url("../../assets/img/logo.png");
background-repeat no-repeat;
background-size 137px 21px;
background-position center;
}
.el-menu {
height 100%
border: none;
background-color transparent
&.el-menu--collapse {
.el-submenu__title{
>span, >.el-submenu__icon-arrow {
......@@ -160,7 +165,8 @@ export default {
}
.el-main {
height 100%
background #ffffff
background #f5f5f5
padding 15px 20px 20px 20px
}
.el-footer {
color #909399
......
......@@ -3,10 +3,11 @@
<el-autocomplete
prefix-icon="el-icon-search"
v-model="search"
clearable
value-key="text"
:trigger-on-focus="false"
:fetch-suggestions="querySearchAsync"
placeholder="请输入内容"
placeholder="请输入楼盘名称或板块名称"
@select="handleSelect">
<template slot-scope="{ item }">
<div style="float: left">{{ item.name }}</div>
......
export const colors = ['#3F6D98', '#ADC6E5', '#5B9BD5', '#C7D7EC', '#4A7FB0', '#8BB1DD', '#538EC3']
export const colors = [
'#8cc3ea', '#f08968',
'#efcc66', '#0fb9b1',
'#8c7ae6', '#fc7930',
'#1491a8', '#4b7bec',
'#ff793f','#ee4866',
'#33d9b2', '#ef3473',
'#428675', '#867018',
'#B53471']
......@@ -5,16 +5,23 @@
@mouseenter.native="active = true"
@mouseleave.native="active = false"
:class="{'flex': true}"
:style="backGroundType === 'waterDrop' ? { padding: '5px', minWidth: width + 'px', minHeight: height + 'px' } :
{ padding: '5px',width: width + 'px', height: height + 'px', color: textColor, backgroundColor: active ? activeColor : bgColor , borderRadius: circle }"
:style="type === 'icon' ? { padding: '5px', minWidth: width + 'px', minHeight: height + 'px' } :
{
width: type === 'square' ? 'auto' : width + 'px',
height: height + 'px',
color: textColor,
backgroundColor: active ? activeColor : bgColor ,
borderRadius: circle,
padding: type === 'square' ? '0 12px': '0'
}"
@draw="draw">
<div
:style="{fontSize: fontSize, fontFamily: 'Arial', textAlign: 'center', fontWeight: 'normal',whiteSpace: 'nowrap'}"
v-if="backGroundType === 'color'">
:style="{fontSize: fontSize + 'px', fontFamily: 'Arial', textAlign: 'center', fontWeight: 'normal',whiteSpace: 'nowrap'}"
v-if="type !== 'icon'">
{{text}}
<div v-if="num" style="font-weight: 600;height: 20px;line-height: 40px">{{num}}</div>
</div>
<div v-if="backGroundType === 'waterDrop'" class="flex-colum" :title="text">
<div v-if="type === 'icon'" class="flex-colum" :title="text">
<i class="el-icon-location"></i>
</div>
</bm-overlay>
......@@ -22,7 +29,7 @@
<script>
export default {
name: 'overlay',
props: ['text', 'position', 'backGroundType', 'textColor', 'bgColor', 'circle', 'width', 'height', 'num', 'fontSize', 'activeColor'],
props: ['text', 'position', 'type', 'textColor', 'bgColor', 'circle', 'width', 'height', 'num', 'fontSize', 'activeColor'],
data () {
return {
active: false
......@@ -44,6 +51,11 @@
el.style.left = pixel.x - this.width / 2 + 'px'
el.style.top = pixel.y - this.height / 2 + 'px'
}
},
computed: {
style () {
return
}
}
}
</script>
......
......@@ -26,9 +26,9 @@
</div>
<div class="table_body" v-if="tableData instanceof Array" :style="{ width: bodyWidth + '%'}">
<div class="productionName">
<el-col :span="8" v-for="(item,index) in tableData" :key="index" style="min-width: 200px">
<el-col :span="24 / tableData.length" v-for="(item,index) in tableData" :key="index" style="min-width: 200px">
<el-row :class="{'dataCell':true, 'prodName': index < 2}">{{item.productionName}}</el-row>
<el-col class="productionDetail" :span="12" v-for="(item2,index) in item.productionProperties" :key="index">
<el-col class="productionDetail" :span="24 / item.productionProperties.length" v-for="(item2,index) in item.productionProperties" :key="index">
<el-row v-for="(value, key) in dataMap" :key="key" :class="{ 'dataCell': true, 'imgHeigth': value === 'img'}">
<div v-if="value === 'string'">{{item2[key] || '--'}} <span v-if="key === 'area'">m<sup>2</sup></span> </div>
<viewer :images="[]" v-else-if="value === 'img'">
......@@ -47,7 +47,7 @@
<el-row v-for="(value, key) in dataMap" :key="key" :class="{ 'dataCell': true, 'imgHeigth': value === 'img' }">
<div v-if="value === 'string'">{{tableData[key] || '--'}}</div>
<viewer :images="[]" v-else-if="value === 'img'">
<img :src="tableData[key] ? tableData[key] : tableData['bannerSrc']" alt="" width="30%" height="80" style="cursor:pointer;">
<img :src="getImageUrl(tableData[key])" alt="" width="30%" height="80" style="cursor:pointer;">
</viewer>
<div v-else-if="value === 'boolean' && tableData[key] == 1" class="circle block"></div>
<div v-else-if="value === 'boolean' && tableData[key] == 0" class="circle hollow"></div>
......@@ -83,7 +83,7 @@
return {
dataMap :{
'unitArea': 'string',
'filePath': 'img',
'fileUrl': 'img',
'bayNumber': 'string',
'roomNumber': 'string',
'hallNumber': 'string',
......@@ -119,6 +119,15 @@
'hallway-designHallwayCFDX': 'boolean'
}
}
},
methods: {
getImageUrl(filePath) {
if(filePath) {
return process.env.VUE_APP_OSS_SRC + filePath
} else {
return null
}
}
}
}
</script>
......@@ -223,8 +232,8 @@
}
.circle {
box-sizing: border-box;
width: 20px;
height: 20px;
width: 15px;
height: 15px;
border: 1px solid #000000;
border-radius: 50%;
margin 0 auto
......
......@@ -5,7 +5,7 @@
<div class="blockShow"></div>
</div>
<div class="right buleText">
<div :style="{ display: 'inline', cursor: 'pointer' , color: saleingState ? 'rgb(25,124,230)' : '#000' }" @click="saleingState = !saleingState">在售楼盘</div>
<div :style="{ display: 'inline', cursor: 'pointer' , color: saleingState ? 'rgb(25,124,230)' : '#000' }" @click="saleingState = !saleingState">{{upText}}</div>
</div>
</div>
<div class="row">
......@@ -13,7 +13,7 @@
<div class="blockShow"></div>
</div>
<div class="right greenText">
<div :style="{ display: 'inline', cursor: 'pointer' , color: soldOutState ? 'rgb(169,209,142)' : '#000' }" @click="soldOutState = !soldOutState">售罄楼盘</div>
<div :style="{ display: 'inline', cursor: 'pointer' , color: soldOutState ? 'rgb(169,209,142)' : '#000' }" @click="soldOutState = !soldOutState">{{downText}}</div>
</div>
</div>
</div>
......@@ -22,6 +22,20 @@
<script>
export default {
name: "propertyControll",
props: {
upText: {
type: String,
default() {
return ''
}
},
downText: {
type: String,
default() {
return "";
}
}
},
data () {
return {
soldOutState: true,
......@@ -34,9 +48,9 @@
if(val && this.soldOutState) {
state = 'all'
} else if (val && !this.soldOutState) {
state = 0
} else if (!val && this.soldOutState) {
state = 1
} else if (!val && this.soldOutState) {
state = 0
} else {
state = ''
}
......@@ -47,9 +61,9 @@
if(val && this.saleingState) {
state = 'all'
} else if (val && !this.saleingState) {
state = 1
} else if (!val && this.saleingState) {
state = 0
} else if (!val && this.saleingState) {
state = 1
} else {
state = ''
}
......
<template>
<div class="unitCard">
<div class="imgContainer">
<viewer :images="[]">
<img src="@assets/img/zlhx.png" width="100%" height="100%">
<viewer :images="[]" style="width: 100%;height: 100%">
<img :src="imgUrl" width="100%" height="100%">
</viewer>
</div>
<div class="unitDetail">
<el-col :span="8">
xxxx家园
{{unitName}}
</el-col>
<el-col :span="8">
xxxxx平方米
<el-col :span="8" v-html="area">
</el-col>
<el-col :span="8">
x室x厅x卫
{{info}}
</el-col>
</div>
</div>
......@@ -23,13 +22,43 @@
export default {
name: 'unitCard',
props: {
imageUrl: {
type: String,
default: ''
},
unitName: {
type: String,
default: '楼盘名称'
},
unitArea: {
type: [String,Number],
default() {
return '----'
}
},
unitInfo: {
type: String,
default() {
return '0-1-2'
}
}
},
data () {
return {
}
},
computed: {
area() { return this.unitArea + 'm<sup>2</sup>' },
info() {
if(this.unitInfo) {
return this.unitInfo.split('-')[0] + '室' + this.unitInfo.split('-')[1] + '厅' + this.unitInfo.split('-')[this.unitInfo.split('-').length - 1] + '卫'
}
},
imgUrl() {
return this.imageUrl ? process.env.VUE_APP_OSS_SRC + this.imageUrl : require('@assets/img/zlhx.png')
}
},
methods: {
}
......
......@@ -10,34 +10,17 @@ import Layout from '@comp/Layout'
Vue.use(VueRouter);
let routes = [
{
path: '/',
component: Layout,
redirect: '/regionalPlate',
name: 'home',
meta: { title: '首页' },
hidden: true,
children: [
{
path: '/tableNew',
name: 'tableNew',
hidden: false,
meta: { title: 'Test' },
component: () => import('@comp/houseDetailForm/index.vue'),
}
]
},
{
path: '/regionalPlate',
hidden: false,
meta: { title: '户型查询', icon: 'el-icon-discover' },
meta: { title: '区域&板块', icon: 'el-icon-discover' },
component: Layout,
children: [
{
path: '/regionalPlate',
name: 'regionalPlate',
hidden: false,
meta: { title: '户型查询' },
meta: { title: '区域&板块' },
component: () => import('@/views/RegionalPlate/index.vue'),
}
]
......
......@@ -2,7 +2,7 @@
<!-- 板块产品分析-->
<section class="ProductAnalysis">
<div class="header">
<el-col :span="4">
<div class="headerFlex">
<el-select v-model="regionVal" @change="changePlateForRegion" placeholder="选择区域">
<el-option
v-for="item in regionOptions"
......@@ -11,9 +11,9 @@
:value="item.adminRegionId">
</el-option>
</el-select>
</el-col>
<el-col :span="4">
<el-select v-model="plateVal" @change="getPlateAnalysisData" placeholder="板块名">
</div>
<div class="headerFlex">
<el-select v-model="plateVal" @change="getAnalysisAndUnit" placeholder="板块名">
<el-option
v-for="item in plateOptions"
:key="item.regionId"
......@@ -21,9 +21,9 @@
:value="item.regionId">
</el-option>
</el-select>
</el-col>
<el-col :span="4">
<el-select v-model="timeVal" placeholder="年份" @change="getPlateAnalysisData">
</div>
<div class="headerFlex">
<el-select v-model="timeVal" placeholder="年份" @change="getAnalysisAndUnit">
<el-option
v-for="item in timeOptions"
:key="item.value"
......@@ -31,9 +31,9 @@
:value="item.value">
</el-option>
</el-select>
</el-col>
<el-col :span="4">
<el-select v-model="houseTypeVal" @change="getPlateAnalysisData" placeholder="类型">
</div>
<div class="headerFlex">
<el-select v-model="houseTypeVal" @change="getAnalysisAndUnit" placeholder="类型">
<el-option
v-for="item in houseTypeOptions"
:key="item.businessId"
......@@ -41,9 +41,9 @@
:value="item.businessId">
</el-option>
</el-select>
</el-col>
<el-col :span="4">
<el-select v-model="areaInterval" @change="getPlateAnalysisData" placeholder="面积区间">
</div>
<div class="headerFlex">
<el-select v-model="areaInterval" @change="getAnalysisAndUnit" placeholder="面积区间">
<el-option
v-for="item in areaIntervalData"
:key="item.value"
......@@ -51,21 +51,22 @@
:value="item.value">
</el-option>
</el-select>
</el-col>
<el-col :span="4" style="text-align: right">
<el-radio-group v-model="showMode">
</div>
<div class="headerFlex">
<el-radio-group v-model="showMode" size="small">
<el-radio-button :label="0">显示数据</el-radio-button>
<el-radio-button :label="1">显示户型</el-radio-button>
</el-radio-group>
</el-col>
</div>
<el-row style="text-align: right;margin: 20px 0">
<div style="width: 100%;text-align: right">
<el-button type="primary" size="small" :loading="exportLoading" :disabled="exportLoading" @click="exportPlateAnalysis">导出数据</el-button>
</el-row>
</div>
</div>
<el-card :body-style="{padding: '0'}">
<div class="supplyDealCharts" v-if="showMode === 0">
<div style="width: 50%">
<ve-pie :data="pieData" :legend="{ bottom: 20 }" :colors="colorsArr" :settings="pieSettings"></ve-pie>
<!-- 各产品 供应套数与详细信息表格-->
<!-- 各产品 供应套数与详细信息表格-->
<table cellspacing="0" cellpadding="0" class="table">
<tr>
<th>产品类型</th>
......@@ -87,7 +88,7 @@
</div>
<div style="width: 50%">
<ve-histogram :data="histogramData" :extend="extend" :legend="{ bottom: 20 }" :colors="colorsArr" :settings="chartSettings"></ve-histogram>
<!-- 各房屋 面宽表格详情-->
<!-- 各房屋 面宽表格详情-->
<table cellspacing="0" cellpadding="0" class="table">
<tr>
<th>产品类型</th>
......@@ -107,36 +108,26 @@
</div>
</div>
<div class="supplyAnalysisTable" v-if="showMode === 0">
<multi-header-table :header-width="42" :body-width="58" :header-data="headerTable" :table-data="demo"></multi-header-table>
<multi-header-table :header-width="42" :body-width="58" :header-data="headerTable" :table-data="productionProjectData"></multi-header-table>
</div>
<div v-if="showMode === 1" class="supplyDealUnitType">
<div class="mainUnit blueBorder">
<h2 class="header">主力户型</h2>
<div class="unitContainer">
<el-col :span="8" v-for="i in 3" :key="i" >
<unit-card ></unit-card>
</el-col>
</div>
<el-pagination
:page-size="3"
layout="total, prev, pager, next"
:total="1000">
</el-pagination>
</div>
<div class="nonMainUnit blueBorder">
<h2 class="header">非主力户型</h2>
<div class="mainUnit blueBorder" v-for="(item, index) in unitHouseTypeData" :key="index">
<h2 class="unitHeader" style="padding: 0 15px">{{item.productGroupName}}</h2>
<div class="unitContainer">
<el-col :span="8" v-for="i in 3" :key="i" >
<unit-card ></unit-card>
<el-col :span="8" v-for="(item2 ,index2) in pageListMap[item.productGroupName][pageList[index].page]" :key="index2" style="margin-bottom: 20px">
<unit-card :imageUrl="item2.imgUrl" :unit-name="item2.unitName" :unit-area="item2.unitArea" :unit-info="item2.unitHouse"></unit-card>
</el-col>
</div>
<el-pagination
:page-size="3"
:current-page="pageList[index].page"
@current-change="(page) => { productionPageChange(page, index)}"
:page-size="6"
layout="total, prev, pager, next"
:total="1000">
:total="item.children.length">
</el-pagination>
</div>
</div>
</el-card>
</section>
</template>
......@@ -145,11 +136,10 @@
import unitCard from '@comp/unitCard'
import tableHeader from "./tableHeader";
import multiHeaderTable from '@comp/multilHeaderTable'
import { demoData } from "./tableHeader";
import { getRegionPlate } from "../../assets/js/api/plateSupplyManage";
import { unitArea } from "./unitArea";
import {plateAnalysis, queryProductionType, exportExcelJson, exportAsExcel} from "../../assets/js/api/projectManage";
import {plateAnalysis, queryProductionType, exportExcelJson, exportAsExcel, plateAnalysisHouseImg} from "@assets/js/api/projectManage";
import { propertyMapFunction } from "../propertiesDetail/propertyFunctionMap";
export default {
name: "ProductAnalysis",
components:{
......@@ -174,10 +164,10 @@
]
},
map: {
'nxmkAvg': '南向面宽',
'qjsmkAvg': '起居室面宽',
'zwmkAvg': '主卧面宽',
'kwmkAvg': '客卧面宽'
'nxmk': '南向面宽',
'qjsmk': '起居室面宽',
'zwmk': '主卧面宽',
'kwmk': '客卧面宽'
}, // 房屋数据 map匹配
histogramTableData: [],
chartSettings : {
......@@ -187,7 +177,11 @@
extend: {
series: {
type: 'bar',
barWidth: 30
barWidth: 30,
label: {
show: true,
position: "top"
}
}
}, //柱状图设置柱的宽度
regionOptions: [], // 区域数据
......@@ -207,10 +201,21 @@
// 格式为 regionId: plateData 即区域Id所对应的下属板块数据
},
exportLoading: false, // 导出lodaing
exportExcelSave: null // 保存的excel表格数据
exportExcelSave: null, // 保存的excel表格数据
unitHouseTypeData: [],
pageList: [],
pageListMap: {
},
productionProjectData: []
}
},
methods: {
// 显示户型,分页查询
productionPageChange(currentPage, index) {
// this.$set(this.pageList[index], 'page', currentPage)
this.pageList[index].page = currentPage
},
// 导出板块产品分析-图表数据
exportPlateAnalysis () {
if(this.exportExcelSave) {
......@@ -254,6 +259,12 @@
this.plateOptions = []
}
},
getAnalysisAndUnit() {
this.pageList = []
this.unitHouseTypeData = []
this.getPlateAnalysisData()
this.getPlateProductionIng()
},
// 根据下拉框的值 筛选图表数据
getPlateAnalysisData() {
let temp = {
......@@ -266,7 +277,7 @@
areaMax: this.areaInterval.split('-')[1]
}
}
plateAnalysis(temp).then(res => {
plateAnalysis(temp).then((res) => {
this.pieData.rows = res.data.pieDetilProductDtoList || []
this.histogramTableData = res.data.barDetilDtoList || []
// 处理 面宽数据 格式: { roomInfo: '南向面宽', '产品1': num, '产品2': num2 }
......@@ -291,7 +302,48 @@
}
this.histogramData.columns = colum
this.histogramData.rows = histomData
console.log(this.histogramData)
// 处理多级表头数据
let resultArray = []
if(res.data.productQueryMap) {
Object.keys(res.data.productQueryMap).forEach(item => {
let singleProduct = {
productionName: item,
productionProperties: []
}
if(res.data.productQueryMap[item]) {
res.data.productQueryMap[item].forEach(propertySinle => {
const singleData = {}
singleData.unitArea = propertySinle.bnsProduct.unitArea
singleData.bayNumber = propertySinle.bnsProduct.bayNumber
singleData.roomNumber = propertySinle.bnsProduct.roomNumber
singleData.hallNumber = propertySinle.bnsProduct.hallNumber
singleData.toiletNumber = propertySinle.bnsProduct.toiletNumber
singleData.southWidth = propertySinle.bnsProduct.southWidth
singleData.liveRoomWidth = propertySinle.bnsProduct.liveRoomWidth
singleData.masterRoomWidth = propertySinle.bnsProduct.masterRoomWidth
singleData.guestRoomWidth = propertySinle.bnsProduct.guestRoomWidth
singleData.fileUrl = propertySinle.productImgList ? propertySinle.productImgList[0].fileUrl : ''
propertySinle.familyFunc.forEach(item => {
if(item.list) {
item.list.forEach(item2 => {
if(item2.checkboxGroup && item2.checkboxGroup.length > 0) {
const value = item2.checkboxGroup[0]
singleData[item.parentName + '-' + item2.functionName] = propertyMapFunction[value]
} else {
singleData[item.parentName + '-' + item2.functionName] = propertyMapFunction['null']
}
})
}
})
singleProduct.productionProperties.push(singleData)
console.info(singleProduct)
})
}
resultArray.push(singleProduct)
})
}
this.productionProjectData = resultArray
console.log(resultArray)
})
exportExcelJson(temp).then(res => {
try {
......@@ -301,11 +353,17 @@
}
})
},
// 获取区域---板块下拉框的值并赋搜索值或者第一个值
getRegionAndPlate(callback) {
getRegionPlate().then(res => {
this.regionOptions = res.data
const plateAnalysis = sessionStorage.getItem('plateAnalysisQuery')
const plateAnalysisQuery = JSON.parse(plateAnalysis)
let plateAnalysisQuery
try {
plateAnalysisQuery = JSON.parse(plateAnalysis)
} catch (e) {
plateAnalysisQuery = undefined
}
if(plateAnalysisQuery && plateAnalysisQuery.adminRegion && plateAnalysisQuery.regionId) {
res.data.forEach(item => {
if(!this.plateMap[item.adminRegionId]) {
......@@ -337,6 +395,7 @@
}
})
},
// 获取产品类型下拉框数据 并赋保存的搜索值或者第一个值
getProductType (callback) {
queryProductionType('product_Type').then(res => {
console.log(res)
......@@ -355,6 +414,63 @@
console.log(this.houseTypeVal)
callback()
})
},
// 获取户型信息----产品户型图与图片
getPlateProductionIng () {
let temp = {
adminRegion: this.regionVal,
regionId: this.plateVal,
year: this.timeVal,
productType: this.houseTypeVal,
unitArea: {
areaMin: this.areaInterval.split('-')[0],
areaMax: this.areaInterval.split('-')[1]
}
}
plateAnalysisHouseImg(temp).then(res => {
let productionList = []
let pageList = []
if(res.data && res.data.length > 0) {
res.data.forEach(item => {
let single = {}
single.productGroupName = item.productGroupName
let children = []
if(item.productQueryDtoList) {
item.productQueryDtoList.forEach((item2) => {
let unit = {}
unit.unitHouse = (item2.bnsProduct.roomNumber || 0) + '-' + (item2.bnsProduct.hallNumber || 0) + '-' + (item2.bnsProduct.toiletNumber || 0)
unit.unitName = item2.bnsProduct.name
unit.unitArea = item2.bnsProduct.unitArea
if(item2.productImgList && item2.productImgList.length > 0) {
unit.imgUrl = item2.productImgList[0].fileUrl
}
children.push(unit)
})
single.children = children
}
productionList.push(single)
pageList.push({
page: 1,
total: item.productQueryDtoList.length
})
})
}
this.pageList = pageList
this.unitHouseTypeData = productionList
// 假分页
const productionListCopy = JSON.parse(JSON.stringify(productionList))
productionListCopy.forEach(item => {
if(!this.pageListMap[item.productGroupName]) {
this.pageListMap[item.productGroupName] = {}
}
item.children.forEach((item2, index2) => {
if(index2 % 6 === 0) {
this.pageListMap[item.productGroupName][index2/ 6 + 1] = item.children.slice(index2,index2 + 6)
}
})
})
console.log(this.pageListMap)
})
}
},
created() {
......@@ -365,11 +481,6 @@
})
})
},
computed: {
demo () {
return demoData
}
},
beforeMount() {
for(let i = new Date().getFullYear(); i>= 2000; i--) {
this.timeOptions.push({
......@@ -380,6 +491,7 @@
this.getRegionAndPlate(() => {
this.getProductType(() => {
this.getPlateAnalysisData()
this.getPlateProductionIng()
})
})
},
......@@ -401,10 +513,24 @@
<style lang="stylus">
.ProductAnalysis{
width: 100%;
height: 100%;
background-color: #fff;
.header {
display flex
flex-direction row
align-items center
height 40px
width: 100%;
background-color: #f5f5f5;
padding-bottom 15px
.el-input__inner {
width 200px
}
.headerFlex:nth-child(2n) {
margin 0 15px
}
.el-radio-group{
white-space nowrap
}
}
.supplyDealCharts{
width: 90%;
......@@ -412,6 +538,7 @@
display: flex;
flex-direction: row;
table.table{
width 95%
font-family: verdana,arial,sans-serif;
font-size:11px;
color:#333333;
......@@ -421,19 +548,18 @@
margin 0 auto
}
table.table th {
border-width: 1px;
font-size:14px;
font-family:PingFangSC-Semibold,PingFang SC;
font-weight:600;
padding: 12px;
border-style: solid;
border-color: #d1ccc0;
background-color: #dedede;
color #909399
text-align center
white-space nowrap
}
table.table tr {
border-bottom 1px solid #EBEEF5
}
table.table td {
border-width: 1px;
padding: 12px;
border-style: solid;
border-color: #d1ccc0;
background-color: #ffffff;
text-align center
white-space nowrap
......@@ -445,7 +571,7 @@
}
.supplyDealUnitType{
width: 90%;
margin: 40px auto 0;
margin: 30px auto;
display flex
flex-direction column
}
......@@ -467,18 +593,17 @@
text-align center
}
}
.mainUnit:nth-child(2n) {
margin 20px 0
}
.nonMainUnit{
margin-top 15px
padding-bottom 20px
.header {
padding 0 15px
}
.unitContainer {
width 100%
overflow hidden
}
.el-pagination{
margin-top 10px
text-align center
font-size 15px
}
......
......@@ -4,7 +4,7 @@
:mapClick="false"
@ready="mapLoaded"
:center="map.center"
:min-zoom="11"
:min-zoom="9"
:zoom="map.setZoom"
@zoomend="zoomChanged"
:scroll-wheel-zoom="true"
......@@ -15,8 +15,8 @@
@click.native.stop="setShowToPlate(item)"
:key="index + 'region'"
v-for="(item,index) in dataType.region"
:position="{lng: item.longitude, lat: item.latitude}"
:back-ground-type="'color'"
:position="GDmapPositionTransform(item.longitude, item.latitude)"
:type="'circle'"
:text="item.name"
:num="item.projectSize"
:text-color="'#ffffff'"
......@@ -25,8 +25,8 @@
:active-color="'rgba(25,124,230,1)'"
:bg-img-url="null"
:circle="'50%'"
:width="90"
:height="90"
:width="80"
:height="80"
></my-overlay>
<!-- 板块-->
<my-overlay
......@@ -34,8 +34,8 @@
@click.native.stop="setShowToPlateRegion(item)"
:key="index + 'plate'"
v-for="(item,index) in dataType.plate"
:position="{lng: item.longitude, lat: item.latitude}"
:back-ground-type="'color'"
:position="GDmapPositionTransform(item.longitude, item.latitude)"
:type="'circle'"
:text="item.name"
:num="item.projectSize"
:fontSize="14"
......@@ -44,30 +44,48 @@
:active-color="'rgba(25,124,230,1)'"
:bg-img-url="null"
:circle="'50%'"
:width="90"
:height="90"
:width="80"
:height="80"
></my-overlay>
<!-- 板块下的楼盘以及板块详情-->
<!-- -->
<!-- 楼盘-->
<my-overlay
v-show="showType === 'plateRegion' && state !== '' ? ( state === 'all' ? true : ( state == item.saleStatus ? true : false ) ) : false"
v-show="showType === 'plateRegion' && infotType !== 1 && state !== '' ? ( state === 'all' ? true : ( state == item.saleStatus ? true : false ) ) : false"
@click.native.stop="toPropertyDetail(item.businessId)"
:key="index + 'plateRegion'"
:key="index + 'plateRegion' + 'property'"
v-for="(item,index) in dataType.plateRegion.resultBnsProjectDTOS"
:position="{lng: item.longitude, lat: item.latitude}"
:back-ground-type="'color'"
:position="GDmapPositionTransform(item.longitude, item.latitude)"
:type="'square'"
:text="item.name"
:fontSize="12"
:text-color="'#ffffff'"
:bg-color="item.saleStatus == 0 ? 'rgb(25,124,230,0.6)' : 'rgb(169,209,142,0.6)'"
:active-color="item.saleStatus == 0 ? 'rgb(25,124,230,1)' : 'rgb(169,209,142,1)'"
:bg-color="item.saleStatus == 1 ? 'rgb(25,124,230,0.6)' : 'rgb(169,209,142,0.6)'"
:active-color="item.saleStatus == 1 ? 'rgb(25,124,230,1)' : 'rgb(169,209,142,1)'"
:bg-img-url="null"
:circle="'10px'"
:height="30"></my-overlay>
<!-- 土拍-->
<my-overlay
v-show="showType === 'plateRegion' && infotType === 1 && solidState !== '' ? ( solidState === 'all' ? true : ( solidState == item.saleStatus ? true : false ) ) : false"
@click.native.stop="collapseItemShow(index)"
:key="index+ 'soild' + 'plateRegion'"
v-for="(item,index) in dataType.plateRegion.resultBnsLandDTOS"
:position="GDmapPositionTransform(item.longitude, item.latitude)"
:type="'square'"
:text="item.code"
:fontSize="12"
:text-color="'#ffffff'"
:bg-color="item.isHave == 0 ? 'rgb(25,124,230,0.6)' : 'rgb(169,209,142,0.6)'"
:active-color="item.isHave == 0 ? 'rgb(25,124,230,1)' : 'rgb(169,209,142,1)'"
:bg-img-url="null"
:circle="'10px'"
:width="80"
:height="30"></my-overlay>
<bm-control anchor="BMAP_ANCHOR_BOTTOM_LEFT" v-show="showType === 'plateRegion'">
<div class="customTools" style="position: relative">
<property-controll @stateChange="stateChange" />
<div class="customTools" style="position: relative" v-show="infotType !== 1">
<property-controll :up-text="'在售楼盘'" :down-text="'售罄楼盘'" @stateChange="stateChange" />
</div>
<div class="customTools" style="position: relative" v-show="infotType === 1">
<property-controll :up-text="'未拍土拍'" :down-text="'已拍土拍'" @stateChange="soildStateChange" />
</div>
</bm-control>
<!-- 搜索时的楼盘以及楼盘详情-->
......@@ -76,8 +94,8 @@
@click.native.stop="showTowerInfo(item)"
:key="index + 'property'"
v-for="(item,index) in dataType.property"
:position="{lng: item.longitude, lat: item.latitude}"
:back-ground-type="'waterDrop'"
:position="GDmapPositionTransform(item.longitude, item.latitude)"
:type="'icon'"
:text="item.name"
:text-color="'#ffffff'"
:circle="'none'"
......@@ -85,7 +103,7 @@
:height="20"
></my-overlay>
<!-- 标尺-->
<bm-scale anchor="BMAP_ANCHOR_TOP_LEFT"></bm-scale>
<bm-scale anchor="BMAP_ANCHOR_BOTTOM_RIGHT"></bm-scale>
<!-- 缩放比例-->
<bm-navigation :showZoomInfo="false" :enableGeolocation="false" anchor="BMAP_ANCHOR_TOP_RIGHT"></bm-navigation>
</baidu-map>
......@@ -109,9 +127,9 @@
</el-col>
</div>
<div v-if="infotType === 1" style="margin-top: 10px;" class="soildInfo">
<el-collapse v-model="soildInfoChange" class="sys-collapse">
<el-collapse accordion v-model="soildInfoChange" class="sys-collapse">
<el-card :body-style="{padding: '0'}" class="box-card" v-for="(item,index) in dataType.plateRegion.resultBnsLandDTOS" :key="index">
<el-collapse-item :title="item.name" :name="index">
<el-collapse-item :title="item.code" :name="index">
<p>行政分区:{{dataType.plateRegion.adminRegionName || '--'}}</p>
<p>所属板块: {{dataType.plateRegion.name || '--'}}</p>
<p>土地面积:{{item.landArea || '--'}}m<sup>2</sup></p>
......@@ -130,7 +148,7 @@
<div v-if="infotType === 2" style="margin-top: 10px;text-align: left">
<el-card v-for="(item, index) in dataType.plateRegion.resultBnsProjectDTOS" class="box-card distanceCard" :key="index" :body-style="{ padding: '0'}">
<div class="imgContainer" >
<img width="150" height="120" :src="item.fileSrc" alt="无法加载" @click.stop="toPropertyDetail(item.businessId)">
<img width="150" height="120" :src="imgUrlHeader + item.fileUrl" alt="无法加载" @click.stop="toPropertyDetail(item.businessId)">
</div>
<div class="infomationContainer">
<div class="propertyListName" style="color: #1482f0" @click="toPropertyDetail(item.businessId)">{{item.name}}</div>
......@@ -146,7 +164,7 @@
</div>
<div v-else-if="showType === 'property'" class="dealWidth">
<div class="searchDetailFlex">
<img style="cursor: pointer" @click="toPropertyDetail(propertyDetailData.businessId)" height="200" :src="require('@assets/img/loupan.png')" alt="">
<img style="cursor: pointer" @click="toPropertyDetail(propertyDetailData.businessId)" height="200" :src="imgUrlHeader + propertyDetailData.fileUrl" alt="">
<p @click="toPropertyDetail(propertyDetailData.businessId)" class="propertyName">{{propertyDetailData.name || '---'}}</p>
<p class="propertyDetail" v-html="'价格'+':' + propertyDetailData.price + '/m<sup>2</sup>'"></p>
<p class="propertyDetail">{{'产品类型'+ ':' + propertyDetailData.productType}}</p>
......@@ -183,13 +201,14 @@
},
data () {
return {
imgUrlHeader: process.env.VUE_APP_OSS_SRC,
map: {
center: {
lng: 117.200, // 经度
lat: 39.133 // 纬度 天津市中心坐标点
lng: 117.2300, // 经度
lat: 39.44000 // 纬度 天津市中心坐标点
},
saveCenter: { lng: 117.200, lat: 39.133 },
setZoom: 11.5 // 放大倍数
saveCenter: { lng: 117.2300, lat: 39.44000 },
setZoom: 10 // 放大倍数
}, // 地图初始化配置,经纬度坐标中点 放大倍数
dataType: {
region: [],
......@@ -202,12 +221,13 @@
allData: [],
showType: 'region', // 控制楼房显示的变量
zoomType: {
region: 11,
plate: 12,
region: 10,
plate: 11,
plateRegion: 13,
property: 13
}, // 根据行政区、板块、楼盘控制地图放大倍数
state: 'all', // 楼盘销售状态 在售 售完
solidState: 'all', //土拍的拍卖状态
saleingState: true, // 在售楼盘状态切换
soldOutState: true, // 售罄楼盘状态切换
infotType: 0, // 板块区域详情 详细信息切换
......@@ -240,7 +260,6 @@
methods: {
backToLeast() {
switch (this.showType) {
case "region": return;
case "plate":
this.showType = 'region'
this.map.setZoom = this.zoomType[this.showType]
......@@ -254,6 +273,13 @@
default: return
}
},
soildStateChange(val) {
if(val === 1 || val === 0) {
this.solidState = val === 1 ? 0 : 1
} else {
this.solidState = val
}
},
stateChange (val) {
this.state = val
},
......@@ -266,17 +292,20 @@
query: { propertyId: id }
})
},
collapseItemShow(index) {
if(index !== this.soildInfoChange) {
this.soildInfoChange = index
}
},
showTowerInfo(item) {
this.propertyDetailData = JSON.parse(JSON.stringify(item))
this.detailShow = true
},
setShowToPlate (item) {
queryPlateByRegionId(item.businessId).then(res => {
console.log(res)
this.showType = 'plate'
this.map.center.lng = res.data[0] ? res.data[0].longitude :item.longitude
this.map.center.lat = res.data[0] ? res.data[0].latitude :item.latitude
console.log(this.map.center)
this.map.setZoom = this.zoomType['plate']
this.dataType['plate'] = res.data
}).catch(e => {
......@@ -316,8 +345,7 @@
// } else if(zoom >= 13 && this.dataType.plateRegion.length > 0) {
// this.showType = 'plateRegion'
// }
console.log(target)
return type
return {target, type}
},
mapLoaded () {
if(this.$route.query && this.$route.query.type && this.$route.query.data) {
......@@ -390,6 +418,20 @@
computed: {
plateRegionColum () {
return plateRegionDetail
},
GDmapPositionTransform() {
return (lng,lat) => {
var X_PI = Math.PI * 3000.0 / 180.0;
var x = lng, y = lat;
var z = Math.sqrt(x * x + y * y) + 0.00002 * Math.sin(y * X_PI);
var theta = Math.atan2(y, x) + 0.000003 * Math.cos(x * X_PI);
var bd_lng = z * Math.cos(theta) + 0.0065;
var bd_lat = z * Math.sin(theta) + 0.006;
return {
lng: bd_lng,
lat: bd_lat
};
}
}
}
}
......@@ -480,7 +522,6 @@
font-size: 16px;
font-family: "Arial Black";
margin: 15px 0;
cursor: pointer;
}
.back {
position absolute
......@@ -492,6 +533,7 @@
.RegionalPlateMain{
.plateDetailShow {
height 100%
overflow-y auto
.sys-collapse{
border: none;
.el-collapse-item__header{
......@@ -542,6 +584,9 @@
margin-bottom 0
}
}
.plateDetailShow::-webkit-scrollbar{
width 3px
}
.anchorBL{
a,span {
display none!important
......
......@@ -2,7 +2,7 @@
<!-- 板块供求数据-->
<section class="supplyDealData">
<div class="header">
<el-col :span="4">
<div>
<el-select v-model="regionVal" @change="regionToPlate" placeholder="选择区域">
<el-option
v-for="item in regionOptions"
......@@ -11,8 +11,8 @@
:value="item.adminRegionName">
</el-option>
</el-select>
</el-col>
<el-col :span="4">
</div>
<div style="margin: 0 20px">
<el-select v-model="plateVal" placeholder="板块名" @change="getSupplyData">
<el-option
v-for="item in plateOptions"
......@@ -21,8 +21,8 @@
:value="item.regionName">
</el-option>
</el-select>
</el-col>
<el-col :span="4">
</div>
<div>
<el-select v-model="timeVal" placeholder="年份" @change="getSupplyData">
<el-option
v-for="item in timeOptions"
......@@ -31,11 +31,12 @@
:value="item.value">
</el-option>
</el-select>
</el-col>
<el-col style="text-align: right" :span="12">
<el-button type="primary" :loading="exportLoading" :disabled="exportLoading" @click="exportSupplyDataForeExcel">导出数据</el-button>
</el-col>
</div>
<div style="width: 100%; text-align: right" >
<el-button type="primary" :loading="exportLoading" :disabled="exportLoading" size="small" @click="exportSupplyDataForeExcel">导出数据</el-button>
</div>
</div>
<el-card :body-style="{ padding: '0' }">
<div class="analysisData">
<div style="width: 100%">
<ve-histogram :data="chartData" :legend="{ bottom: 20 }" :extend="extend" :colors="colorArr" :settings="chartSettings"></ve-histogram>
......@@ -49,7 +50,8 @@
<div style="width: 100%">
<ve-histogram :data="chartData2"
:legend="{ bottom: 20 }"
:extend="extend"
:yAxis="{ show: false }"
:extend="extend2"
:colors="colorArr"
:settings="chartSettings2"
:tooltip-visible="false"/>
......@@ -62,6 +64,7 @@
<div class="tips red">注:供求比=供应数量/销售数量,供应比越小,销售越好</div>
</div>
</div>
</el-card>
</section>
</template>
......@@ -137,7 +140,30 @@
extend: {
series: {
type: 'bar',
barWidth: 30
barWidth: 30,
label: {
show: true,
position: "top",
formatter:function(params){ //标签内容
if(params.data == 0) { return '0' }
return (params.data * 100 ).toFixed(2) + '%'
}
}
}
},
extend2: {
series: {
type: 'bar',
barWidth: 30,
label: {
show: true,
position: "top",
formatter:function(params){ //标签内容
console.log(params.data, 'sssssssssssssssssss')
if(params.data == 0) { return '0' }
return params.data.toFixed(2)
}
}
}
},
exportSaveStatus: [], // 请求数据后保存导出时用
......@@ -238,21 +264,25 @@
}
getRegionPlate().then(res => {
this.regionOptions = res.data
if(sessionStorage.getItem('supplyQuery')) {
const regionVal = JSON.parse(sessionStorage.getItem('supplyQuery')).regionVal
const plateVal = JSON.parse(sessionStorage.getItem('supplyQuery')).plateVal
const timeVal = JSON.parse(sessionStorage.getItem('supplyQuery')).timeVal
const plateSupplyQuery = sessionStorage.getItem('supplyQuery')
let plateSupplyObject
try {
plateSupplyObject = JSON.parse(plateSupplyQuery)
} catch (e) {
plateSupplyObject = undefined
}
if(plateSupplyObject && plateSupplyObject.regionVal && plateSupplyObject.plateVal) {
res.data.forEach(item => {
if(!this.plateMap[item.adminRegionName]) {
this.plateMap[item.adminRegionName] = item.resultRegionDTOS
}
if (item.adminRegionName === regionVal) {
if (item.adminRegionName === plateSupplyObject.regionVal) {
this.plateOptions = item.resultRegionDTOS
}
})
this.regionVal = regionVal ? regionVal : ''
this.plateVal = plateVal ? plateVal : ''
this.timeVal = timeVal ? timeVal: new Date().getFullYear()
this.regionVal = plateSupplyObject.regionVal
this.plateVal = plateSupplyObject.plateVal
this.timeVal = plateSupplyObject.timeVal ? plateSupplyObject.timeVal: new Date().getFullYear()
} else {
res.data.forEach(item => {
if(!this.plateMap[item.adminRegionName]) {
......@@ -278,6 +308,7 @@
})
},
beforeDestroy() {
if(this.regionVal && this.plateVal) {
sessionStorage.setItem('supplyQuery', JSON.stringify({
regionVal: this.regionVal,
plateVal: this.plateVal,
......@@ -285,24 +316,31 @@
}))
}
}
}
</script>
<style scoped lang="stylus">
.supplyDealData{
width 100%
height 100%
background #ffffff
.header {
display flex
flex-direction row
align-items center
height 40px
width: 100%;
background-color: #f5f5f5;
padding-bottom 15px
}
.analysisData{
margin: 40px auto 0;
margin: 20px auto 0;
width: 90%;
display: flex;
padding-bottom 20px;
flex-direction: column;
}
table.table{
width 100%
font-family: verdana,arial,sans-serif;
font-size:11px;
color:#333333;
......@@ -312,19 +350,18 @@
margin 0 auto
}
table.table th {
border-width: 1px;
font-size:14px;
font-family:PingFangSC-Semibold,PingFang SC;
font-weight:600;
padding: 12px;
border-style: solid;
border-color: #d1ccc0;
background-color: #dedede;
color #909399
text-align center
white-space nowrap
}
table.table tr {
border-bottom 1px solid #EBEEF5
}
table.table td {
border-width: 1px;
padding: 12px;
border-style: solid;
border-color: #d1ccc0;
background-color: #ffffff;
text-align center
white-space nowrap
......@@ -340,3 +377,12 @@
}
}
</style>
<style lang="stylus">
.supplyDealData {
.header {
.el-input__inner {
width 200px
}
}
}
</style>
<template>
<el-card :body-style="{ padding: '5px 0 10px 0' }">
<section class="propertiesMain" v-loading.body="propertyLoading">
<header class="header">
<div class="back">
......@@ -16,7 +17,7 @@
</div>
</header>
<main class="detailMain">
<!-- banner图划分-->
<!-- banner图划分-->
<div class="banner">
<div v-if="bannerType === 0">
<banner :banner-data="propertyData.propertyBanner.ztBanner"/>
......@@ -28,21 +29,20 @@
<banner :img-width="100" @bannerChange="saleingChange" :banner-data="propertyData.propertyBanner.hxBanner" />
</div>
</div>
<!-- 户型信息 只在banner类型为户型时才显示-->
<!-- 户型信息 只在banner类型为户型时才显示-->
<div class="planningInformation" v-if="bannerType === 2">
<div class="title">户型信息</div>
<div style="padding: 10px 20px 20px 20px;width: 80%;margin: 0 auto" align="center">
<multi-header-table :header-width="60" :body-width="40" :header-data="multiHeader" :table-data="hxObjectData"></multi-header-table>
</div>
</div>
<!-- 规划信息-->
<!-- 规划信息-->
<div class="planningInformation">
<div class="title">规划信息</div>
<div class="container">
<el-tag :key="key"
effect="dark"
v-for="(val,key) in planingTagsMap"
type="primary" class="tagsInfo"
type="info" class="tagsInfo"
v-html="val.name + ':' +
(typeof val.defaultSetting === 'function' ?
val.defaultSetting(propertyData.projectInformation[key]) :
......@@ -50,7 +50,7 @@
</el-tag>
</div>
</div>
<!-- 土拍信息-->
<!-- 土拍信息-->
<div class="soilPhotoInformation">
<div class="title">土拍信息</div>
<div class="container" v-for="(item,index) in propertyData.propertySoildInfo" :key="index">
......@@ -72,45 +72,45 @@
</div>
</div>
<!--销售信息-->
<!--销售信息-->
<div class="salesInfomation">
<div class="title" style="padding-left: 20px">销售信息</div>
<div style="text-align: right;padding-right: 20px">
<el-button type="primary" @click="imgExport">导出图表为图片</el-button>
<el-button type="primary" @click="properySaleInfoExport">导出数据</el-button>
</div>
<div ref="imgExport" class="container">
<el-row class="firstRow">
<el-col :span="24">
<!-- 供应成交套数比 图表展示-->
<ve-histogram :data="supplySaleData" :legend="{ bottom: 20 }" :colors="colorArr" :settings="supplySaleSettings"></ve-histogram>
<!-- 供应成交套数 详情数据-->
<!-- 供应成交套数比 图表展示-->
<ve-histogram :data="supplySaleCharts" :legend="{ bottom: 20 }" :extend="supplyExtend" :colors="colorArr" :settings="supplySaleSettings"></ve-histogram>
<!-- 供应成交套数 详情数据-->
<table cellspacing="0" cellpadding="0" class="table">
<tr v-for="(value, key) in supplySaleDataDetail" :key="key">
<tr v-for="(value, key) in supplySaleTable" :key="key">
<th>{{value.name}}</th>
<td v-for="(item,index) in value.data" :key="index">{{item}}</td>
</tr>
</table>
</el-col>
<el-col :span="24">
<!-- 供求比数据分析-->
<ve-histogram :data="supplyDemandRatioData" :legend="{ bottom: 20 }" :colors="colorArr" :settings="supplyDemandRatioSettings"></ve-histogram>
<!-- 供求比表格信息-->
<table cellspacing="0" cellpadding="0" class="table">
<tr v-for="(value, key) in supplyDemandRatioDataDetail" :key="key">
<!-- 供求比数据分析-->
<ve-histogram :data="supplyRateCharts" :yAxis="{ show: false }" :legend="{ bottom: 20 }" :extend="rateExtend" :colors="colorArr" :settings="supplyDemandRatioSettings"></ve-histogram>
<!-- 供求比表格信息-->
<table cellspacing="0" cellpadding="0" class="table" >
<tr v-for="(value, key) in supplyRateTable" :key="key">
<th>{{value.name}}</th>
<td v-for="(item,index) in value.data" :key="index">{{item}}</td>
<td v-for="(item,index) in value.data" :key="index">{{key === 'rate' ? item.toFixed(2) : item}}</td>
</tr>
</table>
<!-- 供求比提示信息-->
<!-- 供求比提示信息-->
<div class="tips" style="color: red">注:供求比=供应数量/销售数量,供应比越小,销售越好</div>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<!-- 各房 供应数量数据-->
<ve-pie :data="supplyData" :legend="{ bottom: 20 }" :colors="colorArr" :settings="supplySettings"></ve-pie>
<!-- 各房 供应数量表格数据-->
<table cellspacing="0" cellpadding="0" class="table">
<!-- 各房 庭室数量数据-->
<ve-pie :data="houseUnitCharts" :legend="{ bottom: 0 }" :colors="colorArr" :settings="supplySettings"></ve-pie>
<!-- 各房 庭室数量表格数据-->
<table cellspacing="0" cellpadding="0" class="table" style="width: 90%">
<tr>
<th>产品类型</th>
<th>开间数</th>
......@@ -118,7 +118,7 @@
<th>厅数</th>
<th>卫生间数</th>
</tr>
<tr v-for="item in supplyData.rows">
<tr v-for="item in houseUnitTable">
<td>{{item.production || '--'}}</td>
<td>{{item.kjNum || '--'}}</td>
<td>{{item.jsNum || '--'}}</td>
......@@ -128,10 +128,10 @@
</table>
</el-col>
<el-col :span="12">
<!-- 各房 供应图表数据-->
<ve-histogram :legend="{ bottom: 20 }" :data="supplyDataDetail" :colors="colorArr" :settings="supplySettingsDetail"></ve-histogram>
<!-- 各房 供应表格数据-->
<table cellspacing="0" cellpadding="0" class="table">
<!-- 各房 面宽图表数据-->
<ve-histogram :legend="{ bottom: 20 }" :data="houseWidthCharts" :extend="extend" :colors="colorArr"></ve-histogram>
<!-- 各房 面宽表格数据-->
<table cellspacing="0" cellpadding="0" class="table" style="width: 90%">
<tr>
<th>产品类型</th>
<th>南向面宽</th>
......@@ -139,7 +139,7 @@
<th>主卧面宽</th>
<th>客卧面宽</th>
</tr>
<tr v-for="item in supplyTableData">
<tr v-for="item in houseWidthTable">
<td>{{item.production || '--'}}</td>
<td>{{item.nxmk || '--'}}</td>
<td>{{item.qjsmk || '--'}}</td>
......@@ -153,18 +153,18 @@
</div>
</main>
</section>
</el-card>
</template>
<script>
import { columData } from "./tableColum";
import banner from '@comp/bannerDetail'
import { colors } from "../../components/color";
import html2canvas from "html2canvas"
import multiHeaderTable from '@comp/multilHeaderTable'
import tableHeader from "../ProductAnalysis/tableHeader"
import planningInfoMap from "./planningInfoMap";
import { propertyMapFunction } from "./propertyFunctionMap";
import { queryPropertyDetail, queryPropertySupplyData } from "../../assets/js/api/unitManage";
import {queryLandInfoById, queryPropertyDetail, queryPropertySupplyData, queryAnalysisById, getJsonForProduction, exportPropertyAnalysis} from "@assets/js/api/unitManage";
import { areaRangeMap } from "../plateSupplyData/areaRangeMap";
export default {
name: "propertiesDetail",
......@@ -173,7 +173,7 @@
return {
bannerType: 0,
propertyId: '',
supplySaleData: {
supplySaleCharts: {
columns: ['areaRange', 'supplyProportion', 'dealProportion'],
rows: []
}, // 供应比例、套数 图表数据
......@@ -186,7 +186,7 @@
dealProportion: '成交套数比例'
}
}, // 供应比例、套数 图表设置
supplySaleDataDetail: {
supplySaleTable: {
areaRange: {
name: '面积区间',
data: []
......@@ -208,12 +208,12 @@
}
},
// 供求比 图表数据
supplyDemandRatioData: {
supplyRateCharts: {
columns: ['areaRange', 'rate'],
rows: []
},
// 供求比 表格数据
supplyDemandRatioDataDetail:{
supplyRateTable:{
areaRange: {
name: '面积区间',
data: []
......@@ -229,46 +229,24 @@
supplication: '产品提供数'
}
},
supplyData: {
columns: ['production', 'supplication'],
// 各房面积区间 供应数量图饼
houseUnitCharts: {
columns: ['productionPie', 'supplication'],
rows: [
{ 'production': '产品1', 'supplication': 1393, kjNum: 4, jsNum: 1, tingNum: 1, wsjNum: 3 },
{ 'production': '产品2', 'supplication': 3530, kjNum: 4, jsNum: 1, tingNum: 1, wsjNum: 3 },
{ 'production': '产品3', 'supplication': 2923, kjNum: 4, jsNum: 1, tingNum: 1, wsjNum: 3 }
]
},
supplySettingsDetail: {
labelMap:{
roomInfo: '各房间数据',
'squareMetersFor85': '85平',
'squareMetersFor97': '97平',
'squareMetersFor95': '95平',
'squareMetersFor103': '103平',
'squareMetersFor123': '123平',
'squareMetersFor140': '143平'
}
},
// 各房面积区间 庭室数量表格
houseUnitTable: [],
// 房屋面宽信息图表
supplyDataDetail: {
columns: ['roomInfo', 'squareMetersFor85', 'squareMetersFor95', 'squareMetersFor97', 'squareMetersFor103', 'squareMetersFor123', 'squareMetersFor140'],
rows: [
{ 'roomInfo': '南向面宽', 'squareMetersFor85': 8.5, 'squareMetersFor97': 7.05, 'squareMetersFor95': 7.5, 'squareMetersFor103': 10.1, 'squareMetersFor123': 10.5, 'squareMetersFor140': 13.2 },
{ 'roomInfo': '起居室面宽', 'squareMetersFor85': 3.5, 'squareMetersFor97': 3.5, 'squareMetersFor95': 3.9, 'squareMetersFor103': 3.8, 'squareMetersFor123': 4, 'squareMetersFor140': 6.6 },
{ 'roomInfo': '主卧面宽', 'squareMetersFor85': 3.1, 'squareMetersFor97': 3.05, 'squareMetersFor95': 3.6, 'squareMetersFor103': 3.3, 'squareMetersFor123': 3.5, 'squareMetersFor140': 3.6 },
{ 'roomInfo': '客卧面宽', 'squareMetersFor85': 0, 'squareMetersFor97': 0, 'squareMetersFor95': 0, 'squareMetersFor103': 3, 'squareMetersFor123': 3, 'squareMetersFor140': 3 }
]
houseWidthCharts: {
columns: ['roomInfo'],
rows: []
},
// 房屋面宽表格信息
supplyTableData: [
{ production: '85平', nxmk: 10.1, qjsmk: 10.5, zwmk: 15, kwmk: 13 },
{ production: '97平', nxmk: 10.1, qjsmk: 10.5, zwmk: 15, kwmk: 13 },
{ production: '95平', nxmk: 10.1, qjsmk: 10.5, zwmk: 15, kwmk: 13 },
{ production: '103平', nxmk: 10.1, qjsmk: 10.5, zwmk: 15, kwmk: 13 },
{ production: '123平', nxmk: 10.1, qjsmk: 10.5, zwmk: 15, kwmk: 13 },
{ production: '143平', nxmk: 10.1, qjsmk: 10.5, zwmk: 15, kwmk: 13 },
],
houseWidthTable: [],
colorArr: colors,
hxObjectData: [],
hxObjectData: {}, // 户型信息多级表头数据
// 楼盘详情数据
propertyData: {
projectInformation: {
name: ''
......@@ -281,35 +259,81 @@
propertyPlaningInfo: [],
propertySoildInfo: []
},
// loading
propertyLoading: false,
planingTagsMap: planningInfoMap
// 规划信息map匹配
planingTagsMap: planningInfoMap,
// 柱状图宽度设置
extend: {
series: {
type: 'bar',
barWidth: 30,
label: { show: true, position: 'top' }
}
},
rateExtend: {
series: {
type: 'bar',
barWidth: 30,
label: {
show: true,
position: "top",
formatter:function(params){ //标签内容
if(params.data == 0) { return '0' }
return params.data.toFixed(2)
}
}
}
},
supplyExtend: {
series: {
type: 'bar',
barWidth: 30,
label: {
show: true,
position: "top",
formatter:function(params){ //标签内容
if(params.data == 0) { return '0' }
return (params.data * 100 ).toFixed(2) + '%'
}
}
}
},
// 面宽图表、表格map匹配
houseWidthMap : {
'nxmk': '南向面宽',
'qjsmk': '起居室面宽',
'zwmk': '主卧面宽',
'kwmk': '客卧面宽'
},
// 导出数据储存
exportSupplyDataSave: [],
exportHouseInfoSave: []
}
},
methods: {
imgExport () {
html2canvas(this.$refs.imgExport).then(canvas => {
let dataURL = canvas.toDataURL("image/png");
const bolb = this.dataURLtoBlob(dataURL)
const url = window.URL.createObjectURL(bolb)
properySaleInfoExport () {
// this.propertyData.projectInformation.businessId
if(this.propertyId) {
exportPropertyAnalysis({
title: `${this.propertyData.projectInformation.name}楼盘销售信息数据分析`,
dataJsonTwo: JSON.stringify(this.exportSupplyDataSave),
dataJson: JSON.stringify(this.exportHouseInfoSave)
}).then(res => {
const url = window.URL.createObjectURL(new Blob([res], { type: 'application/vnd.ms-excel;charset=utf-8' }))
const link = document.createElement('a')
link.style.display = 'none'
link.href = url
link.setAttribute('download', `销售信息`) // 自定义下载文件名(如exemple.txt)
link.setAttribute('download', `${this.propertyData.projectInformation.name}楼盘销售信息数据分析`) // 自定义下载文件名
document.body.appendChild(link)
link.click()
document.body.removeChild(link)
});
},
dataURLtoBlob(dataurl) {
var arr = dataurl.split(',');
var bstr = atob(arr[1]);
var n = bstr.length;
var mime = arr[0].match(/:(.*?);/)[1]
var u8arr = new Uint8Array(n)
while(n--){
u8arr[n] = bstr.charCodeAt(n);
}
return new Blob([u8arr], {type: mime });
this.$message({
type: 'success',
message: '导出完成'
})
})
}
},
saleingChange (item) {
this.hxObjectData = item
......@@ -318,23 +342,28 @@
queryPropertyDetail(this.propertyId).then(res => {
this.propertyLoading = true
if(res.data) {
// 总图
this.propertyData.projectInformation = res.data.bnsProject
try {
this.propertyData.propertyBanner.ztBanner = res.data.projectTotalImgList.map(item => {
return {
filePath: 'data:image/png;base64,'+ item.filePath
if(res.data.projectTotalImgList && res.data.projectTotalImgList.length > 0) {
this.propertyData.propertyBanner.ztBanner = res.data.projectTotalImgList
}
})
this.propertyData.propertyBanner.lmBanner = res.data.projectFacadeImgLis.map(item => {
return {
filePath: 'data:image/png;base64,'+ item.filePath
// 立面图
if(res.data.projectFacadeImgList && res.data.projectFacadeImgList.length > 0) {
this.propertyData.propertyBanner.lmBanner = res.data.projectFacadeImgList
}
// 土拍信息
const landIdlist = []
if(res.data.bnsBuildingProductList && res.data.bnsBuildingProductList.length > 0) {
res.data.bnsBuildingProductList.forEach(item => {
if(item.type == 0) {
landIdlist.push(item.businessId)
}
})
} catch (e) {
this.propertyData.propertyBanner.ztBanner = []
this.propertyData.propertyBanner.lmBanner = []
queryLandInfoById(landIdlist).then(res => {
console.log(res)
})
}
// 遍历户型信息 利用map出符合前台的数据结构
// 遍历户型信息 利用map遍历出符合前台的数据结构
let propertyProjectInfoArr = []
res.data.bnsProductList.forEach(propertySinle => {
const singleData = {}
......@@ -347,7 +376,7 @@
singleData.liveRoomWidth = propertySinle.bnsProduct.liveRoomWidth
singleData.masterRoomWidth = propertySinle.bnsProduct.masterRoomWidth
singleData.guestRoomWidth = propertySinle.bnsProduct.guestRoomWidth
singleData.filePath = propertySinle.productImgList[0].filePath
singleData.fileUrl = propertySinle.productImgList[0].fileUrl
propertySinle.familyFunc.forEach(item => {
if(item.list) {
item.list.forEach(item2 => {
......@@ -365,6 +394,7 @@
this.propertyData.propertyBanner.hxBanner = propertyProjectInfoArr
this.hxObjectData = this.propertyData.propertyBanner.hxBanner[0] || {}
this.propertyLoading = false
console.log(this.propertyData)
} else {
this.propertyLoading = false
}
......@@ -376,6 +406,7 @@
this.propertyLoading = false
})
},
// 供求数据 图表加表格数据
getPropertySupplyData () {
queryPropertySupplyData(this.propertyId).then(res => {
if(res.data) {
......@@ -385,6 +416,7 @@
let supplyNumber = [] // 供应套数
let dealNumber = [] // 成交套数
let areaRange = [] // 面积区间
let exportList = [] // 导出数据保存
Object.keys(areaRangeMap).forEach(key => {
supplyChartsData.push({
areaRange: areaRangeMap[key],
......@@ -397,16 +429,60 @@
})
areaRange.push(areaRangeMap[key])
rate.push(res.data[key] ? (res.data[key].rate || 0) : 0)
supplyNumber.push(res.data[key] ? (res.data[key].supplyNumber || 0) : 0)
supplyNumber.push(res.data[key] ? (res.data[key].suplyNumber || 0) : 0)
dealNumber.push(res.data[key] ? (res.data[key].dealNumber || 0) : 0)
exportList.push({
areaRange: areaRangeMap[key],
supplyNumber: res.data[key] ? (res.data[key].suplyNumber || 0) : 0,
dealNumber: res.data[key] ? (res.data[key].dealNumber || 0) : 0
})
})
this.supplySaleData.rows = supplyChartsData
this.supplyDemandRatioData.rows = supplyDealRate
this.supplySaleDataDetail.areaRange.data = areaRange
this.supplySaleDataDetail.dealNum.data = dealNumber
this.supplySaleDataDetail.supplyNum.data = supplyNumber
this.supplyRateData.areaRange.data = areaRange
this.supplyRateData.Rate.data = rate
this.supplySaleCharts.rows = supplyChartsData
this.supplyRateCharts.rows = supplyDealRate
this.supplySaleTable.areaRange.data = areaRange
this.supplySaleTable.dealNum.data = dealNumber
this.supplySaleTable.supplyNum.data = supplyNumber
this.supplyRateTable.areaRange.data = areaRange
this.supplyRateTable.rate.data = rate
this.exportSupplyDataSave = exportList
}
})
},
// 产品供应与户型信息 图表与表格
queryPropertyProductionAnalysis() {
queryAnalysisById(this.propertyId).then(res => {
console.log(JSON.stringify(res.data))
// 饼图图表数据
this.houseUnitCharts.rows = res.data.pieDetilDtoList
// 饼图表格数据
this.houseUnitTable = res.data.pieDetilTableList
this.houseWidthTable = res.data.barDetilDtoList
// 面宽信息柱状图
let histomData = []
let colum = ['roomInfo']
if(res.data.barDetilDtoList && res.data.barDetilDtoList.length > 0) {
Object.keys(this.houseWidthMap).forEach(key => {
// 单条数据预备对象
let singleData = {}
res.data.barDetilDtoList.forEach(item => {
// 将产品名称加入到图表条件
if(colum.length - 1 !== res.data.barDetilDtoList.length) {
colum.push(item.production)
}
if(!singleData.roomInfo) {
singleData.roomInfo = this.houseWidthMap[key]
}
singleData[item.production] = item[key]
})
histomData.push(singleData)
})
}
this.houseWidthCharts.columns = colum
this.houseWidthCharts.rows = histomData
})
getJsonForProduction(this.propertyId).then(res => {
if(res.data) {
this.exportHouseInfoSave = JSON.parse(res.data).detilProductJsonDtoList
}
})
}
......@@ -425,6 +501,7 @@
this.propertyId = this.$route.query.propertyId
this.getPropertyDetail()
this.getPropertySupplyData()
this.queryPropertyProductionAnalysis()
},
created() {
window.eventBus.$on('searchParamChange', (searchResult) => {
......@@ -473,12 +550,12 @@
.container {
margin-top 10px
.tagsInfo {
margin-right 15px
height 40px
line-height 40px
padding 0 15px
font-size 16px
margin-right 25px
padding 5px 15px
font-size 14px
font-family "sans-serif"
background-color: rgb(222,235,247);
height auto
}
}
}
......@@ -512,6 +589,7 @@
}
}
table.table{
width 100%
font-family: verdana,arial,sans-serif;
font-size:11px;
color:#333333;
......@@ -521,20 +599,21 @@
margin 0 auto
}
table.table th {
border-width: 1px;
font-size:14px;
font-family:PingFangSC-Semibold,PingFang SC;
font-weight:600;
padding: 12px;
border-style: solid;
border-color: #d1ccc0;
background-color: #dedede;
color #909399
text-align center
}
table.table tr {
border-bottom 1px solid #EBEEF5
}
table.table td {
border-width: 1px;
padding: 12px;
border-style: solid;
border-color: #d1ccc0;
background-color: #ffffff;
text-align center
white-space nowrap
}
.tips {
font-size 16px
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment