|
@@ -0,0 +1,397 @@
|
|
|
|
|
+<template>
|
|
|
|
|
+ <view class="page">
|
|
|
|
|
+ <!-- 1. 顶部标题 -->
|
|
|
|
|
+ <view class="header">
|
|
|
|
|
+ <text class="title">{{ title }}</text>
|
|
|
|
|
+ </view>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 2. 轮播图 -->
|
|
|
|
|
+ <swiper
|
|
|
|
|
+ class="swiper"
|
|
|
|
|
+ circular
|
|
|
|
|
+ :indicator-dots="true"
|
|
|
|
|
+ :autoplay="true"
|
|
|
|
|
+ :interval="3000"
|
|
|
|
|
+ :duration="800"
|
|
|
|
|
+ >
|
|
|
|
|
+ <swiper-item v-for="(item, index) in picture" :key="index">
|
|
|
|
|
+ <image :src="item" class="swiper-item" mode="aspectFill" />
|
|
|
|
|
+ </swiper-item>
|
|
|
|
|
+ </swiper>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 3. 全屏地图 -->
|
|
|
|
|
+ <view class="map-box">
|
|
|
|
|
+ <view class="map-wrap">
|
|
|
|
|
+ <canvas canvas-id="ydChart" id="ydChart" class="map-canvas" />
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 4. 悬浮按钮 -->
|
|
|
|
|
+ <view class="fab" @tap="openDrawer">
|
|
|
|
|
+ <text class="fab-txt">园区</text>
|
|
|
|
|
+ </view>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 5. 侧边抽屉 -->
|
|
|
|
|
+ <view class="drawer-mask" :class="{show: drawerOpen}" @tap="closeDrawer" />
|
|
|
|
|
+ <view class="drawer" :class="{show: drawerOpen}">
|
|
|
|
|
+ <view class="drawer-header">
|
|
|
|
|
+ <input
|
|
|
|
|
+ v-model="keyword"
|
|
|
|
|
+ class="search-input"
|
|
|
|
|
+ placeholder="搜索园区"
|
|
|
|
|
+ @input="onSearch"
|
|
|
|
|
+ />
|
|
|
|
|
+ <view class="mode-toggle" @tap="toggleMode">
|
|
|
|
|
+ <text :class="{active: mode==='grid'}">宫格</text>
|
|
|
|
|
+ <text :class="{active: mode==='list'}">列表</text>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 宫格模式 -->
|
|
|
|
|
+ <scroll-view v-if="mode==='grid'" scroll-y class="drawer-body">
|
|
|
|
|
+ <view class="grid-box">
|
|
|
|
|
+ <view
|
|
|
|
|
+ v-for="(item,index) in filteredList"
|
|
|
|
|
+ :key="index"
|
|
|
|
|
+ class="grid-card"
|
|
|
|
|
+ @tap="onSelectPark(item)"
|
|
|
|
|
+ >
|
|
|
|
|
+ <text class="grid-label">{{ item.label }}</text>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </scroll-view>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 列表模式 -->
|
|
|
|
|
+ <scroll-view v-else scroll-y class="drawer-body">
|
|
|
|
|
+ <view
|
|
|
|
|
+ v-for="(item,index) in filteredList"
|
|
|
|
|
+ :key="index"
|
|
|
|
|
+ class="list-item"
|
|
|
|
|
+ @tap="onSelectPark(item)"
|
|
|
|
|
+ >
|
|
|
|
|
+ <text class="list-label">{{ item.label }}</text>
|
|
|
|
|
+ <text class="list-count">{{ item.count||0 }} 处</text>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </scroll-view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+</template>
|
|
|
|
|
+
|
|
|
|
|
+<script>
|
|
|
|
|
+import * as echarts from 'echarts'
|
|
|
|
|
+
|
|
|
|
|
+export default {
|
|
|
|
|
+ data() {
|
|
|
|
|
+ return {
|
|
|
|
|
+ title: '盐都区闲置厂房分布图',
|
|
|
|
|
+ picture: [
|
|
|
|
|
+ 'https://ydwqfw.com.cn/yd_qycpfbH5/bg1.jpg',
|
|
|
|
|
+ 'https://ydwqfw.com.cn/yd_qycpfbH5/bg2.jpg',
|
|
|
|
|
+ 'https://ydwqfw.com.cn/yd_qycpfbH5/bg3.jpg',
|
|
|
|
|
+ 'https://ydwqfw.com.cn/yd_qycpfbH5/bg4.jpg'
|
|
|
|
|
+ ],
|
|
|
|
|
+ chart: null,
|
|
|
|
|
+ drawerOpen: false,
|
|
|
|
|
+ mode: 'grid', // grid | list
|
|
|
|
|
+ keyword: '',
|
|
|
|
|
+ parkList2: [
|
|
|
|
|
+ { label: '全部', value: '', count: 99 },
|
|
|
|
|
+ { label: '台创园', value: '1', count: 12 },
|
|
|
|
|
+ { label: '大冈', value: '2', count: 8 },
|
|
|
|
|
+ { label: '大纵湖', value: '3', count: 15 },
|
|
|
|
|
+ { label: '学富', value: '4', count: 6 },
|
|
|
|
|
+ { label: '尚庄', value: '5', count: 9 },
|
|
|
|
|
+ { label: '张庄', value: '6', count: 11 },
|
|
|
|
|
+ { label: '楼王', value: '7', count: 7 },
|
|
|
|
|
+ { label: '潘黄', value: '8', count: 13 },
|
|
|
|
|
+ { label: '盐渎', value: '9', count: 18 },
|
|
|
|
|
+ { label: '秦南', value: '10', count: 5 },
|
|
|
|
|
+ { label: '郭猛', value: '11', count: 10 },
|
|
|
|
|
+ { label: '高新区', value: '12', count: 22 },
|
|
|
|
|
+ { label: '龙冈', value: '13', count: 14 }
|
|
|
|
|
+ ]
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ computed: {
|
|
|
|
|
+ filteredList() {
|
|
|
|
|
+ if (!this.keyword) return this.parkList2
|
|
|
|
|
+ const kw = this.keyword.toLowerCase()
|
|
|
|
|
+ return this.parkList2.filter(i => i.label.toLowerCase().includes(kw))
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ async onReady() {
|
|
|
|
|
+ const json = await this.loadGeoJSON()
|
|
|
|
|
+ echarts.registerMap('yanduqu', json)
|
|
|
|
|
+
|
|
|
|
|
+ let canvasNode
|
|
|
|
|
+ // #ifdef H5
|
|
|
|
|
+ canvasNode = document.getElementById('ydChart')
|
|
|
|
|
+ // #endif
|
|
|
|
|
+ // #ifndef H5
|
|
|
|
|
+ canvasNode = await new Promise(resolve => {
|
|
|
|
|
+ uni.createSelectorQuery()
|
|
|
|
|
+ .in(this)
|
|
|
|
|
+ .select('#ydChart')
|
|
|
|
|
+ .node(res => resolve(res.node))
|
|
|
|
|
+ .exec()
|
|
|
|
|
+ })
|
|
|
|
|
+ // #endif
|
|
|
|
|
+
|
|
|
|
|
+ this.chart = echarts.init(canvasNode, null, {
|
|
|
|
|
+ width: uni.getSystemInfoSync().windowWidth,
|
|
|
|
|
+ height: uni.getSystemInfoSync().windowHeight - uni.upx2px(300) // 扣掉轮播图高度
|
|
|
|
|
+ })
|
|
|
|
|
+ this.renderMap()
|
|
|
|
|
+ },
|
|
|
|
|
+ methods: {
|
|
|
|
|
+ loadGeoJSON() {
|
|
|
|
|
+ return new Promise((resolve, reject) => {
|
|
|
|
|
+ uni.request({
|
|
|
|
|
+ url: './static/yandu.json',
|
|
|
|
|
+ method: 'GET',
|
|
|
|
|
+ success: res => resolve(res.data),
|
|
|
|
|
+ fail: reject
|
|
|
|
|
+ })
|
|
|
|
|
+ })
|
|
|
|
|
+ },
|
|
|
|
|
+ renderMap() {
|
|
|
|
|
+ const option = {
|
|
|
|
|
+ geo: [{
|
|
|
|
|
+ map: 'yanduqu',
|
|
|
|
|
+ roam: true,
|
|
|
|
|
+ aspectScale: 1.2,
|
|
|
|
|
+ zoom: 1.3,
|
|
|
|
|
+ itemStyle: {
|
|
|
|
|
+ areaColor: {
|
|
|
|
|
+ type: 'linear-gradient',
|
|
|
|
|
+ x: 0, y: 400, x2: 0, y2: 0,
|
|
|
|
|
+ colorStops: [
|
|
|
|
|
+ { offset: 0, color: 'rgba(37,108,190,0.8)' },
|
|
|
|
|
+ { offset: 1, color: 'rgba(15,169,195,0.8)' }
|
|
|
|
|
+ ],
|
|
|
|
|
+ global: true
|
|
|
|
|
+ },
|
|
|
|
|
+ borderColor: '#4ecee6',
|
|
|
|
|
+ borderWidth: 1
|
|
|
|
|
+ },
|
|
|
|
|
+ emphasis: {
|
|
|
|
|
+ areaColor: 'rgba(255,202,40,.9)'
|
|
|
|
|
+ },
|
|
|
|
|
+ label: { show: true, color: '#fff', fontSize: 12, fontWeight: 'bold' }
|
|
|
|
|
+ }],
|
|
|
|
|
+ series: [{ type: 'map', geoIndex: 0, data: [] }]
|
|
|
|
|
+ }
|
|
|
|
|
+ this.chart.setOption(option)
|
|
|
|
|
+
|
|
|
|
|
+ this.chart.on('click', params => {
|
|
|
|
|
+ uni.navigateTo({
|
|
|
|
|
+ url: `/pages/factoryBuildings/factoryBuildingsList?parkid=${params.name}`
|
|
|
|
|
+ })
|
|
|
|
|
+ })
|
|
|
|
|
+ },
|
|
|
|
|
+ // 抽屉交互
|
|
|
|
|
+ openDrawer() {
|
|
|
|
|
+ this.drawerOpen = true
|
|
|
|
|
+ },
|
|
|
|
|
+ closeDrawer() {
|
|
|
|
|
+ this.drawerOpen = false
|
|
|
|
|
+ },
|
|
|
|
|
+ toggleMode() {
|
|
|
|
|
+ this.mode = this.mode === 'grid' ? 'list' : 'grid'
|
|
|
|
|
+ },
|
|
|
|
|
+ onSearch() {}, // 已用 computed 实时过滤
|
|
|
|
|
+ // 选中园区
|
|
|
|
|
+ onSelectPark(item) {
|
|
|
|
|
+ this.closeDrawer()
|
|
|
|
|
+ // 1. 地图高亮
|
|
|
|
|
+ if (this.chart && item.value) {
|
|
|
|
|
+ this.chart.dispatchAction({
|
|
|
|
|
+ type: 'highlight',
|
|
|
|
|
+ seriesIndex: 0,
|
|
|
|
|
+ name: item.label
|
|
|
|
|
+ })
|
|
|
|
|
+ setTimeout(() => {
|
|
|
|
|
+ this.chart.dispatchAction({
|
|
|
|
|
+ type: 'downplay',
|
|
|
|
|
+ seriesIndex: 0,
|
|
|
|
|
+ name: item.label
|
|
|
|
|
+ })
|
|
|
|
|
+ }, 1200)
|
|
|
|
|
+ }
|
|
|
|
|
+ // 2. 跳转列表
|
|
|
|
|
+ uni.navigateTo({
|
|
|
|
|
+ url: `/pages/factoryBuildings/factoryBuildingsList?parkid=${item.value}`
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+</script>
|
|
|
|
|
+
|
|
|
|
|
+<style scoped>
|
|
|
|
|
+/* CSS 变量,一键换色 */
|
|
|
|
|
+:root {
|
|
|
|
|
+ --theme: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
|
|
|
+ --card-bg: #f7f9fc;
|
|
|
|
|
+ --text: #333;
|
|
|
|
|
+ --shadow: 0 6rpx 24rpx rgba(0,0,0,.08);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.page {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ flex-direction: column;
|
|
|
|
|
+ height: 100vh;
|
|
|
|
|
+ background: #f5f5f5;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.header {
|
|
|
|
|
+ padding: 20rpx 0;
|
|
|
|
|
+ text-align: center;
|
|
|
|
|
+ background: #fff;
|
|
|
|
|
+}
|
|
|
|
|
+.title {
|
|
|
|
|
+ font-size: 36rpx;
|
|
|
|
|
+ font-weight: bold;
|
|
|
|
|
+ color: var(--text);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.swiper {
|
|
|
|
|
+ width: 100%;
|
|
|
|
|
+ height: 300rpx;
|
|
|
|
|
+}
|
|
|
|
|
+.swiper-item {
|
|
|
|
|
+ width: 100%;
|
|
|
|
|
+ height: 100%;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.map-box {
|
|
|
|
|
+ flex: 1;
|
|
|
|
|
+ width: 100%;
|
|
|
|
|
+ position: relative;
|
|
|
|
|
+}
|
|
|
|
|
+.map-canvas {
|
|
|
|
|
+ width: 100%;
|
|
|
|
|
+ height: 100%;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/* 悬浮按钮 */
|
|
|
|
|
+.fab {
|
|
|
|
|
+ position: fixed;
|
|
|
|
|
+ right: 40rpx;
|
|
|
|
|
+ bottom: 80rpx;
|
|
|
|
|
+ width: 100rpx;
|
|
|
|
|
+ height: 100rpx;
|
|
|
|
|
+ border-radius: 50%;
|
|
|
|
|
+ background: var(--theme);
|
|
|
|
|
+ box-shadow: var(--shadow);
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ justify-content: center;
|
|
|
|
|
+ z-index: 9;
|
|
|
|
|
+}
|
|
|
|
|
+.fab-txt {
|
|
|
|
|
+ font-size: 28rpx;
|
|
|
|
|
+ color: #fff;
|
|
|
|
|
+ font-weight: 600;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/* 抽屉 */
|
|
|
|
|
+.drawer-mask {
|
|
|
|
|
+ position: fixed;
|
|
|
|
|
+ left: 0;
|
|
|
|
|
+ top: 0;
|
|
|
|
|
+ right: 0;
|
|
|
|
|
+ bottom: 0;
|
|
|
|
|
+ background: rgba(0,0,0,.45);
|
|
|
|
|
+ opacity: 0;
|
|
|
|
|
+ visibility: hidden;
|
|
|
|
|
+ transition: all .3s;
|
|
|
|
|
+ z-index: 10;
|
|
|
|
|
+}
|
|
|
|
|
+.drawer-mask.show {
|
|
|
|
|
+ opacity: 1;
|
|
|
|
|
+ visibility: visible;
|
|
|
|
|
+}
|
|
|
|
|
+.drawer {
|
|
|
|
|
+ position: fixed;
|
|
|
|
|
+ right: 0;
|
|
|
|
|
+ top: 0;
|
|
|
|
|
+ bottom: 0;
|
|
|
|
|
+ width: 75vw;
|
|
|
|
|
+ background: #fff;
|
|
|
|
|
+ transform: translateX(100%);
|
|
|
|
|
+ transition: transform .3s;
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ flex-direction: column;
|
|
|
|
|
+ z-index: 11;
|
|
|
|
|
+}
|
|
|
|
|
+.drawer.show {
|
|
|
|
|
+ transform: translateX(0);
|
|
|
|
|
+}
|
|
|
|
|
+.drawer-header {
|
|
|
|
|
+ padding: 30rpx;
|
|
|
|
|
+ border-bottom: 1rpx solid #eee;
|
|
|
|
|
+}
|
|
|
|
|
+.search-input {
|
|
|
|
|
+ height: 64rpx;
|
|
|
|
|
+ padding: 0 20rpx;
|
|
|
|
|
+ border: 1rpx solid #ddd;
|
|
|
|
|
+ border-radius: 8rpx;
|
|
|
|
|
+ font-size: 28rpx;
|
|
|
|
|
+}
|
|
|
|
|
+.mode-toggle {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ margin-top: 20rpx;
|
|
|
|
|
+ justify-content: space-around;
|
|
|
|
|
+}
|
|
|
|
|
+.mode-toggle text {
|
|
|
|
|
+ padding: 8rpx 24rpx;
|
|
|
|
|
+ border-radius: 8rpx;
|
|
|
|
|
+ font-size: 26rpx;
|
|
|
|
|
+ color: #666;
|
|
|
|
|
+ background: var(--card-bg);
|
|
|
|
|
+}
|
|
|
|
|
+.mode-toggle text.active {
|
|
|
|
|
+ background: var(--theme);
|
|
|
|
|
+ color: #fff;
|
|
|
|
|
+}
|
|
|
|
|
+.drawer-body {
|
|
|
|
|
+ flex: 1;
|
|
|
|
|
+ padding: 20rpx 30rpx;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/* 宫格 */
|
|
|
|
|
+.grid-box {
|
|
|
|
|
+ display: grid;
|
|
|
|
|
+ grid-template-columns: repeat(3, 1fr);
|
|
|
|
|
+ gap: 20rpx;
|
|
|
|
|
+}
|
|
|
|
|
+.grid-card {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ justify-content: center;
|
|
|
|
|
+ height: 140rpx;
|
|
|
|
|
+ border-radius: 12rpx;
|
|
|
|
|
+ background: var(--card-bg);
|
|
|
|
|
+ box-shadow: var(--shadow);
|
|
|
|
|
+ font-size: 28rpx;
|
|
|
|
|
+ font-weight: 600;
|
|
|
|
|
+ color: var(--text);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/* 列表 */
|
|
|
|
|
+.list-item {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ justify-content: space-between;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ padding: 24rpx 0;
|
|
|
|
|
+ border-bottom: 1rpx solid #f0f0f0;
|
|
|
|
|
+}
|
|
|
|
|
+.list-label {
|
|
|
|
|
+ font-size: 30rpx;
|
|
|
|
|
+ color: var(--text);
|
|
|
|
|
+}
|
|
|
|
|
+.list-count {
|
|
|
|
|
+ font-size: 26rpx;
|
|
|
|
|
+ color: #999;
|
|
|
|
|
+}
|
|
|
|
|
+</style>
|