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,8 +51,13 @@
el.style.left = pixel.x - this.width / 2 + 'px'
el.style.top = pixel.y - this.height / 2 + 'px'
}
},
computed: {
style () {
return
}
}
}
}
</script>
<style scoped lang="stylus">
......
......@@ -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'),
}
]
......
This diff is collapsed.
This diff is collapsed.
......@@ -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,11 +308,13 @@
})
},
beforeDestroy() {
sessionStorage.setItem('supplyQuery', JSON.stringify({
regionVal: this.regionVal,
plateVal: this.plateVal,
timeVal: this.timeVal
}))
if(this.regionVal && this.plateVal) {
sessionStorage.setItem('supplyQuery', JSON.stringify({
regionVal: this.regionVal,
plateVal: this.plateVal,
timeVal: this.timeVal
}))
}
}
}
</script>
......@@ -290,19 +322,25 @@
<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>
This diff is collapsed.
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