| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397 |
- <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>
|