| | |
| | | .DS_Store |
| | | node_modules |
| | | /dist |
| | | package-lock.json |
| | | |
| | | |
| | | # local env files |
| | |
| | | # chongzhou-screen |
| | | # 崇州市自主安置购房信息化大数据平台 |
| | | |
| | | ## Project setup |
| | | ``` |
| | |
| | | <meta charset="utf-8"> |
| | | <meta http-equiv="X-UA-Compatible" content="IE=edge"> |
| | | <meta name="viewport" content="width=device-width,initial-scale=1.0"> |
| | | <!-- <link rel="icon" href="<%= BASE_URL %>favicon.ico"> --> |
| | | <link rel="icon" href="<%= BASE_URL %>favicon.ico"> |
| | | <title><%= htmlWebpackPlugin.options.title %></title> |
| | | </head> |
| | | <body> |
| | |
| | | <div class="header"> |
| | | <!-- 左侧天气 --> |
| | | <div class="weather"> |
| | | <!-- <img :src="require(`@/assets/weather/${weatherInfo.icon}.png`)" alt="weather" class="weather-icon"> --> |
| | | <span class="weather-text">{{ weatherInfo.text }}</span> |
| | | <div class="mask"></div> |
| | | <div class="box"></div> |
| | | <iframe allowtransparency="true" frameborder="0" width="180" height="36" scrolling="no" |
| | | src="//tianqi.2345.com/plugin/widget/index.htm?s=3&z=3&t=1&v=0&d=3&bd=0&k=000000&f=ffffff<f=ffffff&htf=ffffff&q=1&e=1&a=1&c=60910&w=103&h=36&align=left" /> |
| | | </div> |
| | | |
| | | <!-- 中间标题 --> |
| | |
| | | display: flex; |
| | | margin-top: 61px; |
| | | |
| | | .weather-icon { |
| | | width: 30px; |
| | | height: 30px; |
| | | margin-right: 10px; |
| | | |
| | | .mask { |
| | | position: absolute; |
| | | width: 180px; |
| | | height: 36px; |
| | | z-index: 1; |
| | | filter: alpha(opacity=0); |
| | | opacity: 0; |
| | | background: #040A56 |
| | | } |
| | | |
| | | .weather-text { |
| | | color: #fff; |
| | | font-size: 16px; |
| | | .box { |
| | | position: absolute; |
| | | width: 20px; |
| | | height: 36px; |
| | | left: 140px; |
| | | z-index: 1; |
| | | background: #040A56 |
| | | } |
| | | } |
| | | |
| | |
| | | .datetime { |
| | | display: flex; |
| | | margin-top: 61px; |
| | | |
| | | .calendar-icon { |
| | | width: 22px; |
| | | height: 21px; |
| | |
| | | |
| | | <!-- 右侧第三块 --> |
| | | <div class="panel-item bottom-panel-item"> |
| | | <div class="box-title">安置房类型分布</div> |
| | | <div class="box-title">各季度应补偿总额</div> |
| | | <div class="pie-chart"> |
| | | <!-- <v-chart class="chart" :option="typeDistOption" autoresize /> --> |
| | | <v-chart class="chart" :option="barOption" autoresize /> |
| | | </div> |
| | | </div> |
| | | </div> |
| | |
| | | <script> |
| | | export default { |
| | | name: 'RightPanel', |
| | | props: { |
| | | data: { |
| | | type: Object, |
| | | default: () => { } |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | circleOption: { |
| | |
| | | ] |
| | | }] |
| | | }, |
| | | barOption: { |
| | | tooltip: { |
| | | trigger: 'axis' |
| | | }, |
| | | xAxis: { |
| | | type: 'category', |
| | | data: ['2023年4月', '2023年5月', '2023年7月', '2023年10月'], |
| | | axisLine: { |
| | | lineStyle: { |
| | | color: '#7cb9e8' |
| | | } |
| | | }, |
| | | axisLabel: { |
| | | color: '#7cb9e8' |
| | | } |
| | | }, |
| | | yAxis: { |
| | | type: 'value', |
| | | axisLine: { |
| | | lineStyle: { |
| | | color: '#7cb9e8' |
| | | } |
| | | }, |
| | | axisLabel: { |
| | | color: '#7cb9e8' |
| | | }, |
| | | splitLine: { |
| | | lineStyle: { |
| | | color: 'rgba(124,185,232,0.1)' |
| | | } |
| | | } |
| | | }, |
| | | series: [{ |
| | | data: [120, 200, 150, 80], |
| | | type: 'bar', |
| | | itemStyle: { |
| | | color: '#00ffff' |
| | | } |
| | | }] |
| | | }, |
| | | barOption: {}, |
| | | typeDistOption: { |
| | | tooltip: { |
| | | trigger: 'item' |
| | |
| | | }] |
| | | } |
| | | }; |
| | | }, |
| | | |
| | | mounted() { |
| | | // 组件挂载后初始化地图 |
| | | this.$nextTick(() => { |
| | | this.initBarChart(); |
| | | }); |
| | | }, |
| | | methods: { |
| | | initBarChart() { |
| | | if (!this.data.quarterPayResponses || !this.data.quarterPayResponses[0]) return; |
| | | |
| | | const sortedData = Object.entries(this.data.quarterPayResponses[0]) |
| | | .sort((a, b) => { |
| | | const dateA = new Date(a[0].replace('-', '/')); |
| | | const dateB = new Date(b[0].replace('-', '/')); |
| | | return dateA - dateB; |
| | | }); |
| | | |
| | | const maxValue = Math.max(...sortedData.map(item => item[1])); |
| | | const yAxisMax = Math.ceil(maxValue / 100) * 100; |
| | | |
| | | this.barOption = { |
| | | tooltip: { |
| | | trigger: 'axis', |
| | | formatter: function (params) { |
| | | const dataParams = params[1]; |
| | | return `${dataParams.name}<br/>数值:${dataParams.value}`; |
| | | }, |
| | | backgroundColor: 'rgba(0,0,0,0.7)', |
| | | borderColor: '#00ffff', |
| | | borderWidth: 1, |
| | | textStyle: { |
| | | color: '#fff', |
| | | fontSize: 14 |
| | | } |
| | | }, |
| | | grid: { |
| | | top: '10%', |
| | | left: '3%', |
| | | right: '4%', |
| | | bottom: '3%', |
| | | containLabel: true |
| | | }, |
| | | xAxis: { |
| | | type: 'category', |
| | | data: sortedData.map(item => item[0]), |
| | | axisTick: { |
| | | show: false // 隐藏刻度线 |
| | | }, |
| | | axisLine: { |
| | | lineStyle: { |
| | | color: 'rgba(30, 44, 88, 1)' |
| | | } |
| | | }, |
| | | axisLabel: { |
| | | color: '#ffffff', |
| | | fontSize: 12 |
| | | } |
| | | }, |
| | | yAxis: { |
| | | type: 'value', |
| | | max: yAxisMax, |
| | | splitNumber: 4, |
| | | axisLabel: { |
| | | color: 'rgba(88, 115, 150, 1)', |
| | | fontSize: 12 |
| | | }, |
| | | splitLine: { |
| | | lineStyle: { |
| | | color: 'rgba(30, 44, 88, 1)' |
| | | } |
| | | } |
| | | }, |
| | | series: [ |
| | | { |
| | | type: 'bar', |
| | | barWidth: '30%', |
| | | z: 1, |
| | | data: Array(sortedData.length).fill(yAxisMax), |
| | | itemStyle: { |
| | | color: 'rgba(0, 255, 255, 0.1)' |
| | | } |
| | | }, |
| | | { |
| | | type: 'pictorialBar', |
| | | symbol: 'roundRect', |
| | | symbolSize: [20, 6], |
| | | symbolRepeat: 'fixed', |
| | | symbolMargin: 1, |
| | | symbolClip: true, |
| | | symbolPosition: 'start', |
| | | symbolOffset: [0, 0], |
| | | symbolBoundingData: yAxisMax, |
| | | z: 2, |
| | | data: sortedData.map(item => item[1]), |
| | | itemStyle: { |
| | | color: function (params) { |
| | | return params.dataIndex === 0 ? '#ffd700' : '#00ffff'; |
| | | } |
| | | } |
| | | } |
| | | ] |
| | | }; |
| | | } |
| | | }, |
| | | watch: { |
| | | data: { |
| | | handler() { |
| | | this.initBarChart(); |
| | | }, |
| | | deep: true |
| | | } |
| | | } |
| | | }; |
| | | </script> |
| | |
| | | |
| | | .chart { |
| | | width: 100%; |
| | | height: calc(100% - 35px); |
| | | height: 100%; |
| | | } |
| | | } |
| | | |
| | | .pie-chart { |
| | | height: calc(100% - 35px); |
| | | } |
| | | </style> |
| | |
| | | // 生成标记点系列的配置 |
| | | getMarkerSeries(type) { |
| | | return { |
| | | name: type === "blue" ? "蓝色标记" : "橙色标记", // 系列名称 |
| | | type: "scatter", // 散点图类型 |
| | | coordinateSystem: "geo", // 使用地理坐标系 |
| | | geoIndex: 0, // 关联第一个geo组件 |
| | | data: this.mapPoints.filter(point => point.type === type), // 筛选对应类型的数据 |
| | | symbol: `image://${type === "blue" ? tooltipBlue : tooltipOrange}`, // 标记图标 |
| | | symbolSize: [20, 30], // 标记大小 |
| | | symbolOffset: [0, -15], // 标记偏移量 |
| | | z: 20, // 层级 |
| | | name: type === "blue" ? "蓝色标记" : "橙色标记", |
| | | type: "scatter", |
| | | coordinateSystem: "geo", |
| | | geoIndex: 0, |
| | | data: this.mapPoints.filter(point => point.type === type), |
| | | symbol: `image://${type === "blue" ? tooltipBlue : tooltipOrange}`, |
| | | symbolSize: MAP_CONSTANTS.MARKER.SIZE, |
| | | symbolOffset: MAP_CONSTANTS.MARKER.OFFSET, |
| | | z: MAP_CONSTANTS.MARKER.Z_INDEX, |
| | | |
| | | // 提示框配置 |
| | | label: { |
| | | show: false // 禁用标签显示 |
| | | }, |
| | | |
| | | // 修复tooltip配置 |
| | | tooltip: { |
| | | show: true, // 显示提示框 |
| | | trigger: 'item', // 触发类型:数据项 |
| | | backgroundColor: 'transparent', // 背景透明 |
| | | borderWidth: 0, // 无边框 |
| | | padding: [0, 0, 0, 0], // 内边距 |
| | | // 提示框位置 |
| | | show: true, |
| | | trigger: 'item', |
| | | backgroundColor: 'transparent', |
| | | borderWidth: 0, |
| | | padding: 0, |
| | | className: 'map-tooltip', |
| | | position: function (point) { |
| | | // 固定偏移量 |
| | | return [point[0] - 100, point[1] - 160]; |
| | | }, |
| | | // 提示框内容格式化 |
| | | formatter: function (params) { |
| | | // 返回自定义HTML结构的提示框内容 |
| | | return `<div style=" |
| | | const { name, data } = params; |
| | | return ` |
| | | <div style=" |
| | | background: url(${tooltipBg}) no-repeat center center; |
| | | background-size: 100% 100%; |
| | | width: 211px; |
| | | padding-bottom: 24px; |
| | | padding: 20px 0; |
| | | display: flex; |
| | | flex-direction: column; |
| | | justify-content: center; |
| | | align-items: center; |
| | | "> |
| | | <div style="color: #fff; font-size: 16px; margin: 21px 0;font-weight: bold;">${params.name}</div> |
| | | <div style="display: flex; justify-content: space-around; width: 100%;"> |
| | | <div style="color: #fff; font-size: 16px; margin-bottom: 16px; font-weight: bold;">${name}</div> |
| | | <div style="display: flex; justify-content: space-around; width: 100%; padding: 0 20px;"> |
| | | <div style="text-align: center;"> |
| | | <div style="color: rgba(102, 255, 255, 1); font-size: 20px;margin-bottom: 8px;font-family: 'pangmenzhengdao';">${params.data.householdCount}</div> |
| | | <div style="color: #66ffff; font-size: 20px; font-family: 'pangmenzhengdao'; margin-bottom: 8px;">${data.householdCount}</div> |
| | | <div style="color: #fff; font-size: 12px;">安置户数(户)</div> |
| | | </div> |
| | | <div style="text-align: center;"> |
| | | <div style="color: rgba(102, 255, 255, 1); font-size: 20px;margin-bottom: 8px;font-family: 'pangmenzhengdao';">${params.data.personCount}</div> |
| | | <div style="color: #66ffff; font-size: 20px; font-family: 'pangmenzhengdao'; margin-bottom: 8px;">${data.personCount}</div> |
| | | <div style="color: #fff; font-size: 12px;">安置人数(人)</div> |
| | | </div> |
| | | </div> |
| | | </div>`; |
| | | </div> |
| | | `; |
| | | } |
| | | }, |
| | | |
| | | // 标签配置 |
| | | label: { |
| | | show: false // 不显示标签 |
| | | }, |
| | | |
| | | // 高亮效果配置 |
| | | emphasis: { |
| | | scale: true, // 启用缩放效果 |
| | | scaleSize: 1.2, // 放大比例 |
| | | scale: true, |
| | | scaleSize: 1.2, |
| | | itemStyle: { |
| | | shadowBlur: 10, // 阴影模糊大小 |
| | | shadowColor: type === "blue" ? '#00eaff' : '#ff8e3a' // 根据类型设置阴影颜色 |
| | | shadowBlur: 10, |
| | | shadowColor: type === "blue" ? MAP_CONSTANTS.SHADOW.COLOR : '#ff8e3a' |
| | | } |
| | | } |
| | | }; |
| | |
| | | disabled: false, // 启用高亮效果 |
| | | label: { |
| | | show: true, // 显示标签 |
| | | textStyle: { // 标签文字样式 |
| | | color: "#fff", |
| | | fontSize: 10, |
| | | fontWeight: "normal", |
| | | opacity: 1 |
| | | } |
| | | color: "#fff", // 文字颜色 |
| | | fontSize: 10, // 文字大小 |
| | | fontWeight: "normal", // 文字粗细 |
| | | opacity: 1 // 不透明度 |
| | | }, |
| | | itemStyle: { // 高亮时的样式 |
| | | itemStyle: { |
| | | areaColor: { // 区域填充,保持与正常状态相同的背景 |
| | | type: 'pattern', |
| | | image: mapBg, |
| | |
| | | // 标签配置 |
| | | label: { |
| | | show: true, // 显示标签 |
| | | textStyle: { // 标签文字样式 |
| | | color: "#fff", |
| | | fontSize: 10, |
| | | fontWeight: "normal", |
| | | opacity: 1 |
| | | } |
| | | color: "#fff", // 文字颜色 |
| | | fontSize: 10, // 文字大小 |
| | | fontWeight: "normal", // 文字粗细 |
| | | opacity: 1 // 不透明度 |
| | | }, |
| | | |
| | | tooltip: { |
| | |
| | | <header-panel /> |
| | | <left-panel /> |
| | | <center-panel v-if="!loading" :data="data" /> |
| | | <right-panel /> |
| | | <right-panel v-if="!loading" :data="data" /> |
| | | </div> |
| | | </template> |
| | | |
| | |
| | | }; |
| | | }, |
| | | created() { |
| | | this.handleResize(); |
| | | getData().then(res => { |
| | | this.data = res.data; |
| | | this.loading = false; |
| | |
| | | }, |
| | | methods: { |
| | | handleResize() { |
| | | this.screenStyle.transform = `scale(${window.innerWidth / 1920})`; |
| | | const widthScale = window.innerWidth / 1920; |
| | | const heightScale = window.innerHeight / 1080; |
| | | const scale = Math.min(widthScale, heightScale); |
| | | this.screenStyle.transform = `scale(${scale})`; |
| | | } |
| | | } |
| | | }; |