Browse Source

新增点位关联任务

Fly 9 months ago
parent
commit
c8713557a6

+ 4 - 0
api/map.js

@@ -12,3 +12,7 @@ export const getMapList_Api = (params) => http.get('/h5/biz/map/list' , {params:
 export const getMaptypeList_Api = (params) => http.get('/h5/biz/maptype/list' , {params:params})
 
 
+// 获取地图点位服务
+export const getMapMatterList_Api = (params) => http.get('/h5/biz/map/matterList' , {params:params})
+
+

+ 2 - 15
components/Touchbox/Touchbox.vue

@@ -2,19 +2,6 @@
 	<view class="site-box" ref="fixbox" :style="{ 'z-index':zIndex , 'height':popupHeight + 'px'}">
 		<view class="tap-touch-line" @touchmove="getstart" @touchend="getend" />
 		<slot />
-		<!-- 		<scroll-view :style="{'height':scrollHeight - 20 + 'px' }" scroll-y="true" :show-scrollbar="false">
-			<template v-for="item in siteListArr">
-				<siteListModel :info="item" @checkSiteDetails="checkSiteDetails" />
-			</template>
-		</scroll-view> -->
-		<!-- @touchmove="getstart" @tap="tap" @touchend="getend" -->
-		<!-- :style="{'height':windowHeight + 'px','width':windowWidth + 'px','top':fixboxtop +'px','border-top-left-radius':radius,'border-top-right-radius':radius,'z-index':zIndex}" -->
-		<!-- <view class="content" :style="{'height':windowHeight + 'px'}">
-			<view class="tapBoxTouchLine" v-if="showLine">
-				<view class="line" :style="{'transform': `scaleY(${lineScale})`,'width':`${lineWidth}rpx`}"></view>
-			</view>
-			<slot />
-		</view> -->
 	</view>
 </template>
 
@@ -100,7 +87,7 @@
 				e.preventDefault();
 				const { clientY, screenY } = e.touches[0];
 				const Y = clientY || screenY;
-				console.log(Y, this.maxTop)
+				// console.log(Y, this.maxTop)
 				// // 这里特殊处理 解决:在滑动框内如果存在滚动元素,则会出现滑动时滑动框和内部滚动同时滑的问题
 				if (Y < this.minTop || Y > (this.windowHeight - this.touchHeight)) {
 					return
@@ -112,7 +99,7 @@
 					// 上拉
 					this.popupHeight = this.windowHeight * this.maxHeight
 				} else if ((this.oldHeight - this.popupHeight) > 50) {
-					console.log("this.oldHeight = ", this.oldHeight, "this.popupHeight = ", this.popupHeight)
+					// console.log("this.oldHeight = ", this.oldHeight, "this.popupHeight = ", this.popupHeight)
 					const s_h = this.windowHeight * this.smallHeight;
 					// 下拉
 					if (this.popupHeight >= s_h) {

+ 0 - 224
components/bab-Touchbox/bab-Touchbox.vue

@@ -1,224 +0,0 @@
-<template>
-	<view>
-		<view :class="isend?'fixedbox2' :'fixedbox'"
-			:style="{'height':windowHeight + 'px','width':windowWidth + 'px','top':fixboxtop +'px','border-top-left-radius':radius,'border-top-right-radius':radius,'z-index':zIndex}"
-			@touchmove="getstart" @tap="tap" @touchend="getend" ref="fixbox">
-			<view class="content" :style="{'height':windowHeight + 'px'}">
-				<view class="tapBoxTouchLine" v-if="showLine">
-					<view class="line" :style="{'transform': `scaleY(${lineScale})`,'width':`${lineWidth}rpx`}"></view>
-				</view>
-				<slot />
-			</view>
-		</view>
-	</view>
-</template>
-
-<script>
-	/**
-	 * tapBox 触摸上拉组件
-	 * @description 触摸上拉组件,类似于高德美团上拉组件
-	 * @property {String} radius 左上右上圆角
-	 * @property {Number} minHeight 最低高度 占总屏幕高度占比
-	 * @property {Number} minHeight 最高高度 占总屏幕高度占比
-	 * @property {Number} touchHeight 允许滑动区域高度默认顶部横线高度 0为任意区域可滑动,单位rpx
-	 * @property {Boolean} showLine 上否显示顶部滑动线
-	 * @event {Function} tap 点击事件
-	 * @event {Function} getstart 开始滑动时触发事件
-	 * @event {Function} getend 滑动结束事件
-	 */
-	export default {
-		name: 'tapBox',
-		data() {
-			return {
-				windowHeight: 0, // 屏幕高度
-				windowWidth: 0, // 屏幕宽度
-				firsttop: 0, // 默认高度
-				fixboxtop: 0, // 实际高度
-				phonetop: 200, // 默认滑动分界线 - 后面计算为最低与最高的一半
-				phoneMinTop: 100, // 默认滑动分界线 - 后面计算为最低与最高的一半
-				isend: false, // 触摸结束
-				isfirst: true, // 手指第一次触摸
-				tapboxtop: 0, // 手指距离顶部距离
-				startTop: 0
-			};
-		},
-
-		props: {
-			// width: 120rpx;
-			// transform: scaleY(0.5);
-			lineScale: {
-				type: Number,
-				default: 1,
-			},
-			lineWidth: {
-				type: Number,
-				default: 220,
-			},
-			zIndex: {
-				type: Number,
-				default: 99,
-			},
-			radius: {
-				type: String,
-				default: '50rpx',
-			},
-			minHeight: {
-				type: Number,
-				default: 0.2,
-			},
-			smallHeight: {
-				type: Number,
-				default: 0.35,
-			},
-			maxHeight: {
-				type: Number,
-				default: 0.5,
-			},
-			touchHeight: {
-				type: Number,
-				default: 0,
-			},
-			showLine: {
-				type: Boolean,
-				default: true,
-			},
-		},
-		mounted() {
-			this.$nextTick(function() {
-				this.windowWidth = uni.getSystemInfoSync().windowWidth;
-				this.windowHeight = uni.getSystemInfoSync().windowHeight;
-				var defaultHeight = this.windowHeight * (1 - this.minHeight);
-				this.firsttop = defaultHeight;
-				this.phonetop =
-					(this.windowHeight * this.maxHeight - this.windowHeight * this.minHeight) / 2;
-				this.phoneMinTop =
-					(this.windowHeight * this.minHeight - this.windowHeight * this.smallHeight) / 2;
-				this.fixboxtop = defaultHeight;
-				this.$emit('currentHeight', this.windowHeight - this.fixboxtop);
-				this.$emit('maxtHeight', this.windowHeight * this.maxHeight);
-			});
-		},
-		onReady() {},
-		computed: {},
-		methods: {
-			// 隐藏
-			concealList() {
-				const H_ = uni.getSystemInfoSync().windowHeight;
-				this.fixboxtop = H_ - uni.upx2px(200)
-			},
-			tap(e) {
-				// console.log(e)
-			},
-			getstart(e) {
-				e.preventDefault();
-				const { clientY, screenY } = e.touches[0];
-				let Y = clientY || screenY;
-				// //#ifdef MP-WEIXIN
-				// Y = e.touches[0].clientY;
-				// //#endif
-				// //#ifndef MP-WEIXIN
-				// Y = e.touches[0].screenY;
-				// //#endif
-				// console.log(Y)
-				// 这里特殊处理 解决:在滑动框内如果存在滚动元素,则会出现滑动时滑动框和内部滚动同时滑的问题
-				if (this.touchHeight !== 0) {
-					if (Y - this.fixboxtop > this.touchHeight) {
-						return false;
-					}
-				}
-				this.isend = false;
-				if (this.isfirst) {
-					this.isfirst = false;
-					this.tapboxtop = Y - this.fixboxtop;
-				}
-				this.fixboxtop = Y - this.tapboxtop;
-				if (this.fixboxtop > this.firsttop) {
-					if (this.fixboxtop >= this.windowHeight * (1 - this.smallHeight)) {
-						this.fixboxtop = this.windowHeight * (1 - this.smallHeight);
-					}
-				} else {
-					// 往上滑
-					if (this.fixboxtop <= this.windowHeight * (1 - this.maxHeight)) {
-						this.fixboxtop = this.windowHeight * (1 - this.maxHeight);
-					}
-				}
-				this.$emit('currentHeight', this.windowHeight - this.fixboxtop);
-			},
-			getend() {
-				this.isend = true;
-				this.isfirst = true;
-				console.log("this.fixboxtop > this.firsttop = ", this.fixboxtop, this.startTop)
-				if (!this.startTop) {
-					// 中间高度以下
-					if (this.fixboxtop > this.firsttop) {
-						//当超过平衡值
-						if (this.fixboxtop - this.firsttop >= this.phoneMinTop) {
-							this.fixboxtop = this.windowHeight * (1 - this.smallHeight);
-						} else {
-							this.fixboxtop = this.windowHeight * (1 - this.minHeight);
-						}
-					}
-					//中间高度以上
-					else {
-						//滑动距离小于平衡值
-						if (this.firsttop - this.fixboxtop <= this.phonetop) {
-							this.fixboxtop = this.firsttop;
-						} else {
-							this.fixboxtop = this.windowHeight * (1 - this.maxHeight);
-						}
-					}
-				} else if (this.fixboxtop < this.startTop) {
-					this.fixboxtop = this.windowHeight * (1 - this.maxHeight);
-					console.log("向上滑动", this.fixboxtop)
-				} else {
-					this.fixboxtop = this.windowHeight * (1 - this.minHeight);
-					console.log("向下滑动", this.fixboxtop)
-				}
-
-				this.$emit('currentHeight', this.windowHeight - this.fixboxtop);
-
-
-				this.startTop = this.fixboxtop - 0;
-			},
-		},
-	};
-</script>
-
-<style lang="scss" scoped>
-	.tapBoxTouchLine {
-		display: flex;
-		align-items: center;
-		justify-content: center;
-		padding: 20rpx 0 30rpx;
-	}
-
-	.line {
-		margin: 0px;
-		vertical-align: middle;
-		// border-bottom: 8rpx solid rgb(214, 215, 217);
-		height: 8rpx;
-		background-color: rgb(214, 215, 217);
-		border-radius: 4rpx;
-
-		// border: 4rpx;
-		// border-top-color: rgb(214, 215, 217);
-		// border-right-color: rgb(214, 215, 217);
-		// border-left-color: rgb(214, 215, 217);
-	}
-
-	.fixedbox {
-		position: fixed;
-		left: 0;
-		background-color: #ffffff;
-		padding: 0 12px;
-	}
-
-	.fixedbox2 {
-		position: fixed;
-		left: 0;
-		background-color: #ffffff;
-		padding: 0 12px;
-		transition-property: top;
-		transition-duration: 0.4s;
-	}
-</style>

+ 2 - 42
components/city/city.vue

@@ -1,8 +1,6 @@
 <template>
-	<uni-popup ref="popupRef" type="bottom" border-radius="10px 10px 0 0">
-
-		<!-- :indicator-style="indicatorStyle"   -->
-		<div class="city-box">
+	<uni-popup class="picker-popup" ref="popupRef" type="bottom" border-radius="10px 10px 0 0">
+		<div class="picker-content">
 			<div class="city-picker-btn">
 				<text @click.stop="cancel()">取消</text>
 				<text @click.stop="confirm()">确定</text>
@@ -84,41 +82,3 @@
 		}
 	}
 </script>
-
-<style lang="scss" scoped>
-	.uni-popup {
-		z-index: 1002;
-
-		.city-box {
-			height: 55vh;
-			background-color: #fff;
-			border-radius: 30rpx 30rpx 0 0;
-
-			.city-picker-btn {
-				height: 100rpx;
-				display: flex;
-				justify-content: space-between;
-				align-items: center;
-				padding: 0 30rpx;
-			}
-
-			.picker-view {
-				height: calc(100% - 100rpx);
-				text-align: center;
-
-			}
-		}
-	}
-
-	/deep/ .indicator-class {
-		height: 100rpx;
-	}
-
-	/deep/ .uni-picker-view-content {
-		.item {
-			text-align: center;
-
-			line-height: 100rpx;
-		}
-	}
-</style>

+ 3 - 38
components/mapType/mapType.vue

@@ -1,6 +1,6 @@
 <template>
-	<uni-popup ref="mapTypePopupRef" type="bottom" border-radius="10px 10px 0 0">
-		<div class="city-box">
+	<uni-popup class="picker-popup" ref="mapTypePopupRef" type="bottom" border-radius="10px 10px 0 0">
+		<div class="picker-content">
 			<div class="city-picker-btn">
 				<text @click.stop="cancel()">取消</text>
 				<text @click.stop="confirm()">确定</text>
@@ -11,7 +11,6 @@
 				</picker-view-column>
 			</picker-view>
 		</div>
-
 	</uni-popup>
 
 </template>
@@ -74,39 +73,5 @@
 </script>
 
 <style lang="scss" scoped>
-	.uni-popup {
-		z-index: 1002;
-
-		.city-box {
-			height: 55vh;
-			background-color: #fff;
-			border-radius: 30rpx 30rpx 0 0;
-
-			.city-picker-btn {
-				height: 100rpx;
-				display: flex;
-				justify-content: space-between;
-				align-items: center;
-				padding: 0 30rpx;
-			}
-
-			.picker-view {
-				height: calc(100% - 100rpx);
-				text-align: center;
-
-			}
-		}
-	}
-
-	/deep/ .indicator-class {
-		height: 100rpx;
-	}
-
-	/deep/ .uni-picker-view-content {
-		.item {
-			text-align: center;
-
-			line-height: 100rpx;
-		}
-	}
+	
 </style>

+ 4 - 14
components/tiandituMap/tiandituMap.vue

@@ -109,6 +109,7 @@
 	import { EventBus } from "@/utils/vueBus.js"
 	import iconPath from '@/static/images/point.png'
 	var Tmap = null;
+	const left = -(uni.upx2px(150));
 	export default {
 		data() {
 			return {
@@ -162,7 +163,7 @@
 				try {
 					if (Tmap) {
 						Tmap.removeEventListener("moveend", this.MapMoveend);
-						Tmap.removeEventListener("zoomend", this.MapMoveend);
+						Tmap.removeEventListener("zoomend", this.handleZoomEvent);
 					}
 				} catch (error) {
 					//TODO handle the exception
@@ -180,15 +181,6 @@
 				}
 			},
 
-			// // 移动地图,获取中心点
-			// MapMoveend: throttle((e) => {
-			// 	console.log("防抖防抖防抖1111", e.target.getCenter(), this)
-			// 	const v = e.target.getCenter()
-			// 	const Lng = v.getLng();
-			// 	const Lat = v.getLat();
-			// 	this.$emit("moveMap", { Lng, Lat })
-			// }, 500),
-
 			// 点击地图标注的点位
 			clickMapSite({ type, target, lnglat, containerPoint }) {
 				const Lng = lnglat.getLng();
@@ -199,8 +191,6 @@
 			// 天地图缩放事件
 			handleZoomEvent(event) {
 				if (!this.labelLsit || this.labelLsit.length === 0) return;
-				// let currentZoom = event.target.getZoom();
-				// console.log("handleZoomEvent = 天地图缩放事件  " , currentZoom)
 				this.labelLsit.forEach(el => {
 					this.labelShowOrHide(el)
 				})
@@ -235,7 +225,7 @@
 						const script = document.createElement('script')
 						script.src = 'https://api.tianditu.gov.cn/api?v=4.0&tk=' + this.options.apikey
 						script.onload = this.initChartsRender.bind(this)
-						document.head.appendChild(script) 
+						document.head.appendChild(script)
 					} else {
 						const {
 							lng,
@@ -317,7 +307,7 @@
 							// text: this.setLable(info.locationName),
 							text: info.locationName,
 							position: marker.getLngLat(),
-							offset: new T.Point(-50, 30)
+							offset: new T.Point(left, 30)
 						});
 						Tmap.addOverLay(label);
 						label.setLngLat(marker.getLngLat());

+ 1 - 0
config/index.js

@@ -1,6 +1,7 @@
 export default {
 	baseURL: "https://ditu.qqzzhou.com/oa",
 	// baseURL: "http://192.168.0.152:8282", 
+	// baseURL: "http://192.168.0.78:8282", 
 	
 	
 	

+ 1 - 0
main.js

@@ -1,4 +1,5 @@
 import App from './App'
+import "@/static/css/index.scss";
  
 // #ifndef VUE3
 import Vue from 'vue'

+ 8 - 0
pages.json

@@ -10,6 +10,12 @@
 				"navigationBarTitleText": "武汉公安政务服务地图"
 			}
 		},
+		{
+			"path": "pages/map/matterDetails",
+			"style": {
+				"navigationBarTitleText": "事项详情"
+			}
+		},
 		{
 			"path": "pages/index/index",
 			"style": {
@@ -22,6 +28,8 @@
 				"navigationBarTitleText": "武汉公安政务服务"
 			}
 		}
+
+
 	],
 	"globalStyle": {
 		"navigationStyle": "custom",

+ 6 - 13
pages/map/index.vue

@@ -2,16 +2,12 @@
 	<view class="map-box">
 		<search ref="searchRef" @handleSearch="handleSearch" v-if="showMap" />
 
-		<tiandituMap ref="tiandituMapRefs" @handleSearch="$refs.searchRef.handleSearch()" @clickMap="handleClickMap"
+		<tiandituMap ref="tiandituMapRefs" @handleSearch="$refs.searchRef.onSearchFocus()" @clickMap="handleClickMap"
 			@moveMap="moveMapSearch" @onLoadTianDiTu="initMaps" @onSelect="selectPoint" :apiKey="apiKey"
 			@handleMapSite="handleMapSite">
 		</tiandituMap>
 
-		<!-- 		<Touchbox ref="TouchboxRef"  :zIndex="1001"
-			:minHeight="0.35" :maxHeight="0.8" :touchHeight="64" @currentHeight="setTouchHeight"
-			@maxtHeight="setScrollMaxHeight">
-			
-		</Touchbox> -->
+ 
 		<Touchbox ref="TouchboxRef" :maxHeight="0.8" v-if="showMap && siteListArr && siteListArr.length > 0" :zIndex="1001" @currentHeight="e => TouchHeight = e">
 			<scroll-view :style="{'height':TouchHeight - 15  +'px' }" scroll-y="true" :show-scrollbar="false">
 				<template v-for="item in siteListArr">
@@ -31,8 +27,7 @@
 	import siteDetails from "./model/siteDetails.vue"
 	import $config from "@/config/index.js"
 	import { EventBus } from "@/utils/vueBus.js"
-	import { getLocation, throttle } from "@/utils/tool.js"
-	let mapThat = this;
+	import { getLocation } from "@/utils/tool.js" 
 	export default {
 		name: 'tdtmap',
 		components: {
@@ -41,8 +36,7 @@
 			siteDetails
 		},
 		data() {
-			return {
-				mapThat: this,
+			return { 
 				showMap: false,
 				longitude: undefined,
 				latitude: undefined,
@@ -60,8 +54,7 @@
 				TouchHeight: 0,
 			}
 		},
-		created() {
-			mapThat = this;
+		created() { 
 			getLocation();
 
 			this.getMapCenterPoint()
@@ -157,7 +150,7 @@
 				const { Lng, Lat } = parms;
 				this.longitude = Lng;
 				this.latitude = Lat;
-				this.$refs.searchRef.handleSearch()
+				this.$refs.searchRef.onSearchFocus()
 				// console.log("moveMapSearch", Lng, Lat)
 			},
 			handleSearch(val = {}) {

+ 116 - 0
pages/map/matterDetails.vue

@@ -0,0 +1,116 @@
+<template>
+	<view class="matter-page">
+		<template v-if="info">
+			<view class="matter-item" v-if="info.handleMethod">
+				<view class="matter-label">办理方式</view>
+				<view class="matter-val">{{info.handleMethod}}</view>
+			</view>
+			<view class="matter-item" v-if="info.serviceObject">
+				<view class="matter-label">服务对象</view>
+				<view class="matter-val">{{info.serviceObject}}</view>
+			</view>
+			<view class="matter-item" v-if="info.processingConditions">
+				<view class="matter-label">办理条件</view>
+				<view class="matter-val" v-html="info.processingConditions"></view>
+			</view>
+			<view class="matter-item" v-if="info.processingMaterial">
+				<view class="matter-label">办理材料</view>
+				<view class="matter-val" v-html="info.processingMaterial"></view>
+			</view>
+			<view class="matter-item" v-if="info.processingDays">
+				<view class="matter-label">承诺办结</view>
+				<view class="matter-val">{{info.processingDays}}天(工作日)</view>
+			</view>
+		</template>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				info: {
+					// "deleteFlag": "NOT_DELETE",
+					// "createTime": "2024-12-17 17:38:09",
+					// "createUser": "1543837863788879871",
+					// "updateTime": null,
+					// "updateUser": null,
+					// "id": "1868953821385449474",
+					// "category": "交通",
+					// "name": "message",
+					// "code": "test---11",
+					// "businessType": "SECURITY",
+					// "appId": "1851541103046574082",
+					// "bizAppName": null,
+					// "sort": 1,
+					// "active": "ENABLE",
+					// "processingDays": 2,
+					// "matterType": "COMPREHENSIVE",
+					// "handleMethod": "ONLINE_PROCESSING,WINDOW_PROCESSING",
+					// "serviceObject": "PERSON,ENTERPRISE",
+					// "processingConditions": "<p><img src=\"http://192.168.0.78:8282/dev/file/download?id=1868953714309062658\" alt=\"\" width=\"152\" height=\"152\"></p>",
+					// "processingMaterial": "<p>大萨达撒<a href=\"https://www.baidu.com\">www.baidu.com</a></p>",
+					// "transMap": {}
+				}
+			}
+		},
+		onLoad() {
+			const eventChannel = this.getOpenerEventChannel();
+			eventChannel.on('acceptDataFromOpenerPage', data => {
+				this.info = data
+				uni.setNavigationBarTitle({
+					title: data.name
+				});
+			})
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.matter-page {
+		width: 100%;
+		min-height: 100vh;
+		background-color: #F2F2F2;
+		padding: 30rpx;
+
+		.matter-item {
+			width: 100%;
+			border: 1rpx solid #E0DDDD;
+			display: flex;
+			justify-content: space-between;
+			align-items: stretch;
+			margin-bottom: 30rpx;
+
+			>view {
+				flex-shrink: 0;
+				padding: 20rpx;
+			}
+
+			.matter-label {
+				width: 30%;
+				background-color: #fff;
+				display: flex;
+				justify-content: center;
+				align-items: center;
+			}
+
+			.matter-val {
+				// display: flex;
+				// justify-content: center;
+				// align-items: center;
+				// flex-wrap: wrap;
+				border-left: 1rpx solid #E0DDDD;
+				width: 70%;
+				background-color: #F4FAFF;
+				white-space: pre-wrap;
+				overflow-wrap: break-word;
+			}
+		}
+	}
+
+	/deep/ img,
+	/deep/ video,
+	/deep/ audio {
+		max-width: 100%;
+	}
+</style>

+ 63 - 42
pages/map/model/search.vue

@@ -38,7 +38,7 @@
 	export default {
 		data() {
 			return {
-				locationPower: true,
+				locationPower: false,
 				locationName: undefined,
 				selfLatitude: undefined,
 				selfLongitude: undefined,
@@ -51,11 +51,14 @@
 					mapTypeId: undefined,
 					typeName: undefined,
 				},
-				
-				
-				SearchTimeout: null, 
+
+				LocationTimeout: null,
+				SearchTimeout: null,
 			}
 		},
+		created() {
+			this.init()
+		},
 		mounted() {
 			EventBus.$on('TianDiTuSearch', (callBack) => {
 				this.handleSearch(callBack)
@@ -66,7 +69,24 @@
 		},
 		methods: {
 			init() {
-
+				clearTimeout(this.LocationTimeout);
+				this.LocationTimeout = null;
+				this.LocationTimeout = setTimeout(() => {
+					getLocation().then(res => {
+						const { longitude, latitude } = res || {}
+						if (longitude && latitude) {
+							this.selfLatitude = latitude;
+							this.selfLongitude = longitude;
+							clearTimeout(this.LocationTimeout);
+							this.LocationTimeout = null;
+							this.onSearchFocus()
+						} else {
+							this.init()
+						}
+					}).catch(err => {
+						this.init()
+					})
+				}, 1000)
 			},
 			/**
 			 * 获取定位
@@ -74,37 +94,27 @@
 			 * 没有callBack,则需要手动收索
 			 * 
 			 */
+
 			handleSearch(callBack) {
 				try {
-					clearTimeout(this.SearchTimeout)
-					this.SearchTimeout = null;
-					this.SearchTimeout = setTimeout(() => {
-						if (!callBack && !this.locationPower) {
-							this.onSearchFocus()
-							return
+					uni.showLoading({
+						mask: true
+					})
+					getLocation().then(res => {
+						const { longitude, latitude } = res || {}
+						if (longitude && latitude) {
+							this.selfLatitude = latitude;
+							this.selfLongitude = longitude;
 						}
-						uni.showLoading({
-							mask: true
-						})
-						this.locationPower = true;
-						getLocation().then(res => {
-							const { longitude, latitude } = res || {}
-							if (longitude && latitude) {
-								this.selfLatitude = latitude;
-								this.selfLongitude = longitude;
-							}
-							callBack && callBack({ longitude: res.longitude, latitude: res.latitude })
-						}).catch(err => {
-							this.locationPower = false
-							uni.showToast({
-								title: '获取定位失败',
-								icon: 'none'
-							})
-						}).finally(() => {
-							if (!callBack) this.onSearchFocus()
-							uni.hideLoading()
+						callBack && callBack({ longitude: res.longitude, latitude: res.latitude })
+					}).catch(err => {
+						uni.showToast({
+							title: '获取定位失败',
+							icon: 'none'
 						})
-					}, 150)
+					}).finally(() => {
+						uni.hideLoading()
+					})
 
 				} catch (error) {
 					console.log(999977999, error)
@@ -112,20 +122,31 @@
 				}
 			},
 			onSearchFocus() {
-				let pms = {};
 				try {
-					if (this.params.code) {
-						pms.areaCode = this.params.code || undefined
-					}
-					pms.mapTypeId = this.params.mapTypeId;
-					pms.selfLatitude = this.selfLatitude;
-					pms.selfLongitude = this.selfLongitude;
-					pms.locationName = this.locationName;
+					clearTimeout(this.SearchTimeout)
+					this.SearchTimeout = null;
+					this.SearchTimeout = setTimeout(() => {
+						let pms = {};
+						try {
+							if (this.params.code) {
+								pms.areaCode = this.params.code || undefined
+							}
+							pms.mapTypeId = this.params.mapTypeId;
+							pms.selfLatitude = this.selfLatitude;
+							pms.selfLongitude = this.selfLongitude;
+							pms.locationName = this.locationName;
+						} catch (error) {
+							console.log("定位收索11 error", error)
+							//TODO handle the exception
+						}
+						this.$emit("handleSearch", pms)
+					}, 150)
+
 				} catch (error) {
-					console.log("定位收索11 error", error)
+					console.log(999977999, error)
 					//TODO handle the exception
 				}
-				this.$emit("handleSearch", pms)
+
 			},
 			getVal() {
 				return {

+ 121 - 18
pages/map/model/siteDetails.vue

@@ -2,20 +2,28 @@
 	<view class="">
 		<uni-popup ref="siteDetailsPopupRef" type="bottom">
 			<view class="details-box">
-				<scroll-view :style="{'height':scrollH  +'px' }" scroll-y="true" :show-scrollbar="false">
+
+				<view class="details-content" :style="{'height':contentH  +'px' }">
 					<template v-if="info">
-						<view class="site-name">{{info.locationName}}</view>
-						<view class="site-location">
-							{{`${info.provinceName}${info.cityName}${info.areaName}${info.address}`}}
+						<view class="site-info">
+							<view class="site-name">{{info.locationName}}</view>
+							<view class="site-location">
+								{{`${info.provinceName}${info.cityName}${info.areaName}${info.address}`}}
+							</view>
+							<view class="site-distance">距离{{getDistance(info.distance)}}</view>
+							<view class="site-time">
+								<text class="time-lable">办公时间</text>
+								<text class="site-time-val">{{info.workTimeRemark}}</text>
+							</view>
 						</view>
-						<view class="site-distance">距离{{getDistance(info.distance)}}</view>
-						<view class="site-time">
-							<text class="time-lable">办公时间</text>
-							<text class="site-time-val">{{info.workTimeRemark}}</text>
+						<view class="sever-box" :style="{'height':serveH  +'px' }">
+							<siteServe :height="serveH" :mapLocationId="info.mapLocationId" />
 						</view>
 					</template>
-
-				</scroll-view>
+				</view>
+				<!-- 		<scroll-view :style="{'height':scrollH  +'px' }" scroll-y="true" :show-scrollbar="false">
+					
+				</scroll-view> -->
 				<view class="details-btn">
 					<view class="site-btn" @click.stop="getPhoneCall(info.mapContactList)">
 						<svg t="1733972888261" class="icon" viewBox="0 0 1024 1024" version="1.1"
@@ -50,28 +58,91 @@
 	import { openMap } from "@/utils/openApp.js"
 	import { distanceCalculate } from "@/utils/tool.js";
 	import telList from "./telList.vue"
+	import siteServe from "./siteServe.vue"
 	export default {
 		data() {
 			return {
-				scrollH: 0,
+				contentH: 0,
+				serveH: 0,
 				info: null,
 			}
 		},
-		components: { telList },
+		components: { telList, siteServe },
 		created() {
-			const windowHeight = uni.getSystemInfoSync().windowHeight;
-			this.scrollH = windowHeight * 0.7 - uni.upx2px(150)
+
 		},
 		mounted() {
+
+
+
 			// EventBus.$on('TianDiTuSite', (res) => {
 			// 	const { longitude, latitude } = res;
 			// 	this.openDetails(res);
 			// });
+			// const aaa = {
+			// 	"deleteFlag": "NOT_DELETE",
+			// 	"createTime": "2024-12-11 16:56:18",
+			// 	"createUser": "1543837863788879871",
+			// 	"updateTime": "2024-12-18 09:08:07",
+			// 	"updateUser": "1543837863788879871",
+			// 	"mapLocationId": "1866768964909047810",
+			// 	"locationName": "武汉市民之家 出入境办证大厅",
+			// 	"mapTypeId": "1867023355423547393",
+			// 	"mapTypeName": "市公安政务服务中心",
+			// 	"mapTypeIcon": "https://sly-ga-zwserver.obs.cn-north-4.myhuaweicloud.com/2024/12/16/1868630815665283073.png",
+			// 	"provinceCode": "420000",
+			// 	"provinceName": "湖北省",
+			// 	"cityCode": "420100",
+			// 	"cityName": "武汉市",
+			// 	"areaCode": "420102",
+			// 	"areaName": "江岸区",
+			// 	"address": "江岸区金桥大道117号",
+			// 	"workTimeRemark": "周一至周五:上午9:00-12:00;下午13:30-17:00 周六:上午9:00-12:00;下午13:00-16:00",
+			// 	"outerPhone": "12367",
+			// 	"mapStatus": "ENABLE",
+			// 	"orderIndex": 1,
+			// 	"longitude": "114.28986",
+			// 	"latitude": "30.66223",
+			// 	"centerPoint": false,
+			// 	"distance": 0,
+			// 	"centerDistance": 50.825090552695464,
+			// 	"mapContactList": [{
+			// 		"deleteFlag": "NOT_DELETE",
+			// 		"createTime": "2024-12-18 09:08:07",
+			// 		"createUser": "1543837863788879871",
+			// 		"updateTime": null,
+			// 		"updateUser": null,
+			// 		"mapContactsId": "1869187854787371009",
+			// 		"phone": "12367",
+			// 		"remark": null,
+			// 		"mapLocationId": "1866768964909047810"
+			// 	}]
+			// }
+			// this.openDetails(aaa)
 		},
 		beforeDestroy() {
 			// EventBus.$off('someEvent'); // 确保在组件销毁前移除事件监听
 		},
+		watch: {
+			contentH: {
+				handler(newH) {
+					if (newH) {
+						const query = uni.createSelectorQuery().in(this);
+						query
+							.select(".site-info")
+							.boundingClientRect((data) => {
+								const { height } = data || {};
+								const h = this.contentH - height;
+								this.serveH = h;
+							})
+							.exec();
+					}
+				},
+
+			}
+		},
 		methods: {
+
 			getDistance(num) {
 				return distanceCalculate(num)
 			},
@@ -82,12 +153,37 @@
 				const { areaCode, cityCode, provinceCode, provinceName, cityName, areaName, address } = info
 				const name = `${provinceName}${cityName}${areaName}${address}`;
 				const code = areaCode || cityCode || provinceCode
-
 				openMap({ name, code: code, type: "baidu" })
 			},
 			openDetails(res) {
 				this.info = res;
 				this.$refs.siteDetailsPopupRef.open()
+				this.calculateHeight()
+			},
+			calculateHeight() {
+				this.$nextTick(() => {
+					try {
+						const query = uni.createSelectorQuery().in(this);
+						query
+							.select(".details-box")
+							.boundingClientRect((data) => {
+								if(data){
+									this.contentH = data.height - uni.upx2px(150);
+								}
+							})
+							.exec();
+					} catch (error) {
+						//TODO handle the exception
+						const windowHeight = uni.getSystemInfoSync().windowHeight;
+						this.contentH = windowHeight * 0.8 - uni.upx2px(150);
+					}
+
+					if (!this.contentH) {
+						setTimeout(() => {
+							this.calculateHeight()
+						}, 100)
+					}
+				})
 			}
 		}
 	}
@@ -98,7 +194,7 @@
 		z-index: 1002;
 
 		.details-box {
-			height: 70vh;
+			height: 80vh;
 			padding: 0 30rpx;
 			background-color: #fff;
 			border-radius: 20rpx 20rpx 0 0;
@@ -148,8 +244,8 @@
 
 			.details-btn {
 				width: 100%;
-				height: 150rpx;
-				padding-top: 30rpx;
+				height: 120rpx;
+				padding-top: 20rpx;
 				display: flex;
 				justify-content: center;
 				align-items: center;
@@ -185,5 +281,12 @@
 			}
 		}
 
+
+
+		.sever-box {
+
+			width: 100%;
+			// background-color: hotpink;
+		}
 	}
 </style>

+ 309 - 0
pages/map/model/siteServe.vue

@@ -0,0 +1,309 @@
+<template>
+	<view class="serve-content" :style="{'height':height  +'px' }">
+		<view class="serve-title">可以办事项</view>
+		<view class="serve-search">
+			<input confirm-type="search" ref="searchInputRef" class="search-input" :auto-blur="true" type="text"
+				placeholder="搜索服务事项" v-model="matterName" @confirm="getMatterList" />
+			<view class="search-btn" @click.stop="getMatterList"> 搜 索 </view>
+		</view>
+		<view class="matter-loading" v-if="MatterListLoading">
+			<u-loading-icon />
+		</view>
+		<view class="serve" :style="{'height':scrollH  +'px' }" v-else-if="MatterList">
+			<scroll-view class="scroll-lable" :style="{'height':scrollH  +'px' }" scroll-y="true"
+				:show-scrollbar="false">
+				<template v-for="(value, key , index) in MatterList">
+					<view :class="['lable one-row' , index === activeIndex ? 'active-lable' : '' ]"
+						@click.stop="openTyle(index)">{{ key }}</view>
+				</template>
+			</scroll-view>
+			<scroll-view class="scroll-val" :scroll-into-view="scrollIntoView" @scroll="scrollService"
+				:style="{'height':scrollH  +'px' }" scroll-y="true" :show-scrollbar="false">
+				<template v-for="(value, key , index) in MatterList">
+					<view class="val-content" :id="`service_${index}`">
+						<view class="val-name">{{key}}</view>
+						<template v-for="item in (value || [])">
+							<view class="val" @click.stop="LookMatterDetails(item)">
+								<text class="val-text one-row">{{ item.name }}</text>
+								<svg t="1734508422065" class="val-icon" viewBox="0 0 1024 1024" version="1.1"
+									xmlns="http://www.w3.org/2000/svg" p-id="4279"
+									xmlns:xlink="http://www.w3.org/1999/xlink">
+									<path
+										d="M492.675886 904.817574L885.696074 511.797385 492.675886 118.777197c-12.258185-12.258185-12.432147-32.892131 0.187265-45.51052 12.707416-12.707416 32.995485-12.703323 45.511543-0.187265l411.660734 411.660734c7.120165 7.120165 10.163477 17.065677 8.990768 26.624381 1.500167 9.755178-1.5104 20.010753-8.990768 27.491121L538.374694 950.515359c-12.258185 12.258185-32.892131 12.432147-45.511543-0.187265-12.707416-12.707416-12.703323-32.995485-0.187265-45.51052z"
+										p-id="4280"></path>
+								</svg>
+							</view>
+						</template>
+					</view>
+				</template>
+			</scroll-view>
+		</view>
+		<view v-else class="matter-loading">
+			<u-empty mode="data" :iconSize="emptySize" text="暂无可办事项" />
+		</view>
+	</view>
+</template>
+
+<script>
+	import { getMapMatterList_Api } from "@/api/map.js"
+	export default {
+		props: {
+			height: {
+				type: Number,
+				default: 0
+			},
+			mapLocationId: {
+				type: Number | String,
+				default: null
+			}
+		},
+		data() {
+			return {
+				scrollH: 0,
+				matterName: '',
+				MatterList: null,
+				MatterListLoading: false,
+				activeIndex: undefined,
+				scrollIntoView: undefined,
+				scrollStatus: true,
+				oldScrollNum: 0,
+				RightTopArr: [],
+
+				emptySize: uni.upx2px(130)
+			}
+		},
+		watch: {
+			height: {
+				handler(newH) {
+					// 区域高度 - 标题高度 - 搜索区域高度
+					this.scrollH = newH - uni.upx2px(60) - uni.upx2px(100);
+				},
+				immediate: true
+			},
+			mapLocationId: {
+				handler(newId) {
+					this.getMatterList(newId)
+				},
+				immediate: true
+			},
+		},
+		created() {
+
+		},
+		methods: {
+			getLabel(item) {
+				console.log("getLabel = ", item)
+				const label = Object.keys(item)[0];
+				return label;
+			},
+			getMatterList() {
+				this.MatterListLoading = true;
+				const parmas = {
+					mapLocationId: this.mapLocationId,
+					matterName: this.matterName
+				};
+				getMapMatterList_Api(parmas).then(res => {
+					const keys = Object.keys(res || {});
+					if (keys && keys.length > 0) {
+						this.MatterList = res;
+						this.activeIndex = 0;
+						this.getNodesInfo()
+					} else {
+						this.MatterList = null;
+						this.activeIndex = undefined;
+					}
+				}).catch(err => {
+					this.MatterList = null;
+					this.activeIndex = undefined;
+				}).finally(() => {
+					setTimeout(() => {
+						this.MatterListLoading = false;
+					}, 300)
+				})
+			},
+
+			openTyle(index) {
+				this.scrollStatus = false; 
+				this.activeIndex = index
+				this.scrollIntoView = `service_${index}`
+				setTimeout(() => {
+					this.scrollStatus = true;
+				}, 200)
+			},
+			scrollService(event) {
+				if (!this.scrollStatus) return
+				const { scrollTop } = event.detail;
+				let scrollNums = scrollTop;
+				if (this.oldScrollNum > scrollTop) {
+					scrollNums = scrollTop + 80;
+				};
+				try {
+					this.RightTopArr.forEach((el, index) => {
+						let data = this.RightTopArr[index];
+						if (scrollNums >= data.height && index == this.RightTopArr.length - 1 ? true :
+							scrollNums < this.RightTopArr[parseInt(index) + 1].height) {
+							this.activeIndex = index;
+							throw new Error()
+						}
+					})
+				} catch (e) {
+					//TODO handle the exception
+				}
+
+				this.oldScrollNum = scrollTop;
+
+
+			},
+			// 查看事项详情
+			LookMatterDetails(item) {
+				// pages/map/matterDetails
+				// 在起始页面跳转到test.vue页面,并监听test.vue发送过来的事件数据
+				uni.navigateTo({
+					url: '/pages/map/matterDetails',
+					success: function(res) {
+						// 通过eventChannel向被打开页面传送数据
+						res.eventChannel.emit('acceptDataFromOpenerPage', item)
+					}
+				})
+			},
+
+			getNodesInfo() {
+				new Promise(resolve => {
+					let selectorQuery = uni.createSelectorQuery();
+					// 获取节点的位置信息
+					selectorQuery.selectAll('.val-content').boundingClientRect((rects) => {
+						// 如果节点尚未生成,rects值为[](因为用selectAll,所以返回的是数组),循环调用执行
+						if (!rects.length) {
+							setTimeout(() => {
+								this.$nextTick(() => {
+									this.getNodesInfo();
+								})
+							}, 10);
+							return;
+						}
+						this.RightTopArr = [];
+						// 生成之后开始添加进去数组
+						rects.forEach((rect) => {
+							// 这里减去rects[0].top,是因为第一项顶部不是贴到导航栏=>每一个商品距离顶部的高度,如果此页面顶部没有其他的view那就不用减去rects[0].top,自己视情况而定。
+							let tops = rect.top - rects[0].top;
+							this.RightTopArr.push({
+								height: tops,
+								id: rect.id
+							});
+						})
+						resolve();
+					}).exec()
+				});
+			},
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.serve-content {
+		border-top: 1rpx solid #F0F0F0;
+
+		.serve-title {
+			color: #7D7D7D;
+			font-size: 32rpx;
+			height: 60rpx;
+			line-height: 60rpx;
+		}
+
+		.serve-search {
+			width: 100%;
+			padding: 20rpx 0;
+			display: flex;
+			justify-content: space-between;
+			align-items: stretch;
+
+			.search-input {
+				flex: 1;
+				height: 60rpx;
+				border: 1rpx solid #F0F0F0;
+				border-radius: 10rpx;
+				padding: 0 15rpx;
+				font-size: 28rpx;
+			}
+
+			.search-btn {
+				width: 120rpx;
+				background-color: #3291F8;
+				margin-left: 20rpx;
+				line-height: 60rpx;
+				text-align: center;
+				color: #fff;
+				font-size: 28rpx;
+				border-radius: 10rpx;
+			}
+		}
+
+		.serve {
+			width: 100%;
+			display: flex;
+			align-items: stretch;
+
+			.scroll-lable {
+				width: 200rpx;
+
+				.lable {
+					width: 100%;
+					height: 60rpx;
+					font-size: 30rpx;
+					line-height: 60rpx;
+					text-align: center;
+					border-left: 6rpx solid transparent;
+					padding: 0 10rpx;
+				}
+
+				.active-lable {
+					color: #3291F8;
+					font-weight: 600;
+					border-left-color: #3291F8;
+				}
+			}
+
+			.scroll-val {
+				width: calc(100% - 200rpx);
+				padding: 0 0 0 20rpx;
+
+				.val-content {
+					// height: 300px;
+				}
+
+				.val-name {
+					font-size: 30rpx;
+					padding: 15rpx 0;
+				}
+
+				.val {
+					width: 100%;
+					height: 100rpx;
+					padding: 0 20rpx;
+					border: 1rpx solid #F0F0F0;
+					display: flex;
+					justify-content: space-between;
+					align-items: center;
+					margin-bottom: 20rpx;
+
+					.val-text {
+						flex: 1;
+						width: 1px;
+						font-size: 30rpx;
+					}
+
+					.val-icon {
+						width: 34rpx;
+						height: 34rpx;
+					}
+				}
+			}
+		}
+
+		.matter-loading {
+			padding-top: 50rpx;
+			text-align: center;
+		}
+
+	}
+</style>

+ 1 - 0
static/css/index.scss

@@ -0,0 +1 @@
+@import "./picker-popup.scss";

+ 34 - 0
static/css/picker-popup.scss

@@ -0,0 +1,34 @@
+.picker-popup {
+	z-index: 1002 !important;
+
+	.picker-content{
+		height: 55vh;
+		background-color: #fff;
+		border-radius: 30rpx 30rpx 0 0;
+
+		.city-picker-btn {
+			height: 100rpx;
+			display: flex;
+			justify-content: space-between;
+			align-items: center;
+			padding: 0 30rpx;
+		}
+
+		.picker-view {
+			height: calc(100% - 100rpx);
+			text-align: center;
+			.indicator-class {
+				height: 100rpx;
+			}
+	
+			.uni-picker-view-content {
+				.item {
+					text-align: center;
+					line-height: 100rpx ;
+				}
+			}
+		}
+	}
+}
+
+	

File diff suppressed because it is too large
+ 1 - 0
static/images/more.svg


+ 6 - 1
utils/request.js

@@ -120,6 +120,7 @@ http.interceptors.response.use((res) => {
 	// 获取错误信息
 	const msg = errorCode[code] || res.data.msg || errorCode['default']
 	const { data } = res.data
+	console.log("msg =============== ", res)
 	// console.log("data res= ", res)
 	if (code === 401) {
 		onLogin("登录状态已过期")
@@ -144,8 +145,12 @@ http.interceptors.response.use((res) => {
 
 	// }
 }, (response) => {
+	console.log("msg ======111111111111========= ", response.data)
+	const res = response.data || {};
 	let { message } = response;
-	if (message == "Network Error") {
+	if (res?.msg) {
+		message = res.msg;
+	} else if (message == "Network Error") {
 		message = "后端接口连接异常";
 	} else if (message.includes("timeout")) {
 		message = "系统接口请求超时";

+ 1 - 34
utils/tool.js

@@ -68,37 +68,4 @@ export const getLocation = () => {
 		}
 	})
 }
-
-// 防抖:
-export const debounce = (func, delay) => {
-	console.log("防抖防抖防抖")
-	let timer;
-	return function() {
-		if (timer) {
-			clearTimeout(timer);
-		}
-		timer = setTimeout(() => {
-			func.apply(this, arguments);
-		}, delay);
-	};
-}
-
-
-// 节流:
-export const throttle = (func, delay) => {
-	let timer = null;
-	return () => {
-		if (!timer) {
-			func.apply(this, arguments);
-			timer = setTimeout(() => {
-				timer = null;
-			}, delay);
-		}
-	};
-}
-
-// // 使用
-// let myFunc = throttle(function() {
-//     console.log('节流函数被触发');
-// }, 1000);
-// window.addEventListener('scroll', myFunc);
+