-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
-
+
+
+
+ ...
@@ -456,10 +342,224 @@ import { ref, reactive, onMounted, computed } from 'vue'
import { useRouter } from 'vue-router'
import { deviceService } from '@/services/deviceService'
import { useUserStore } from '@/stores/user'
+import AMapLoader from '@amap/amap-jsapi-loader'
const router = useRouter()
const userStore = useUserStore()
+const mapInstance = ref(null)
+const mapLoaded = ref(false)
+const isMapLoading = ref(false)
+
+// 高德地图配置
+// 在 HomePage.vue 中
+const mapConfig = reactive({
+ center: [112.9375, 28.1655],
+ zoom: 16,
+ key: import.meta.env.VITE_AMAP_KEY || '', // 使用环境变量
+ viewMode: '3D'
+})
+
+// 添加:后端接口获取设备位置
+const fetchDeviceLocations = async () => {
+ try {
+ // 调用后端接口获取设备位置数据
+ // 这里假设你有对应的后端接口
+ const response = await deviceService.getTerminalLocations()
+
+ if (response.code === 200 && response.data) {
+ return response.data
+ }
+ return []
+ } catch (error) {
+ console.error('获取设备位置失败:', error)
+ return []
+ }
+}
+
+// 修改:初始化地图
+const initMap = async () => {
+ if (isMapLoading.value) return
+ isMapLoading.value = true
+
+ try {
+ // 加载高德地图
+ const AMap = await AMapLoader.load({
+ key: mapConfig.key,
+ version: '2.0',
+ plugins: [
+ 'AMap.Marker',
+ 'AMap.Geolocation',
+ 'AMap.ToolBar',
+ 'AMap.Scale',
+ 'AMap.ControlBar'
+ ]
+ })
+
+ // 创建地图实例
+ mapInstance.value = new AMap.Map('mapContainer', {
+ zoom: mapConfig.zoom,
+ center: mapConfig.center,
+ viewMode: mapConfig.viewMode
+ })
+
+ // 添加控件
+ mapInstance.value.addControl(new AMap.ToolBar())
+ mapInstance.value.addControl(new AMap.Scale())
+ mapInstance.value.addControl(new AMap.ControlBar())
+
+ // 获取当前位置
+ const geolocation = new AMap.Geolocation({
+ enableHighAccuracy: true,
+ timeout: 10000,
+ buttonOffset: new AMap.Pixel(10, 20),
+ zoomToAccuracy: true,
+ buttonPosition: 'RB'
+ })
+
+ mapInstance.value.addControl(geolocation)
+
+ // 监听定位成功
+ geolocation.getCurrentPosition((status, result) => {
+ if (status === 'complete') {
+ console.log('定位成功:', result)
+ } else {
+ console.log('定位失败:', result)
+ }
+ })
+
+ // 获取设备数据并在地图上标记
+ const devices = await fetchDeviceLocations()
+ addDeviceMarkers(devices)
+
+ mapLoaded.value = true
+ console.log('地图初始化成功')
+ } catch (error) {
+ console.error('地图初始化失败:', error)
+ // 如果高德地图初始化失败,使用原有的模拟地图
+ useMockMap()
+ } finally {
+ isMapLoading.value = false
+ }
+}
+
+// 添加:在地图上添加设备标记
+const addDeviceMarkers = (devices) => {
+ if (!mapInstance.value || !devices.length) return
+
+ devices.forEach(device => {
+ // 创建标记
+ const marker = new AMap.Marker({
+ position: [device.longitude, device.latitude],
+ title: device.terminalName,
+ content: createMarkerContent(device),
+ offset: new AMap.Pixel(-12, -32) // 调整标记位置
+ })
+
+ // 添加点击事件
+ marker.on('click', () => {
+ showMarkerInfo(device.terminalId)
+ })
+
+ marker.setMap(mapInstance.value)
+
+ // 保存标记引用
+ if (!markers[device.terminalId]) {
+ markers[device.terminalId] = {}
+ }
+ markers[device.terminalId].marker = marker
+ })
+}
+
+// 添加:创建标记内容
+const createMarkerContent = (device) => {
+ const isOnline = device.deviceStatus === 'active'
+ const color = isOnline ? '#04d919' : '#aaaaaa'
+
+ return `
+
+
+
+ ${device.terminalId}
+
+
+ `
+}
+
+// 添加:模拟地图作为备用
+const useMockMap = () => {
+ console.log('使用模拟地图')
+ // 保持原有的模拟地图逻辑不变
+}
+
+// 修改:onMounted 钩子
+onMounted(() => {
+ // 初始化设备信息
+ Object.keys(markers).forEach(terminalId => {
+ fetchDeviceInfo(terminalId)
+ })
+
+ // 延迟初始化地图
+ setTimeout(() => {
+ initMap()
+ }, 500)
+})
+
+// 修改:地图控制方法
+const centerMap = () => {
+ if (mapInstance.value) {
+ // 使用高德地图的定位
+ const geolocation = new AMap.Geolocation()
+ geolocation.getCurrentPosition((status, result) => {
+ if (status === 'complete') {
+ mapInstance.value.setCenter([result.position.lng, result.position.lat])
+ }
+ })
+ }
+}
+
+const zoomIn = () => {
+ if (mapInstance.value) {
+ mapInstance.value.setZoom(mapInstance.value.getZoom() + 1)
+ }
+}
+
+const zoomOut = () => {
+ if (mapInstance.value) {
+ mapInstance.value.setZoom(mapInstance.value.getZoom() - 1)
+ }
+}
+
+// 修改:显示标记信息方法
+const showMarkerInfo = async (markerId) => {
+ if (!mapInstance.value) {
+ // 如果没有地图实例,使用原有逻辑
+ await originalShowMarkerInfo(markerId)
+ return
+ }
+
+ currentMarker.value = markerId
+ selectedMarker.value = markerId
+
+ // 如果数据还在加载中,重新获取
+ if (markers[markerId].status === 'loading') {
+ await fetchDeviceInfo(markerId)
+ }
+
+ // 平滑滚动到标记位置
+ const device = markers[markerId]
+ if (device && device.marker) {
+ mapInstance.value.setCenter(device.marker.getPosition())
+ mapInstance.value.setZoom(18)
+ }
+
+ showDevicePopup.value = true
+}
// 修改标记点配置
const markerConfigs = {
TERM001: {
@@ -547,6 +647,7 @@ const currentMarker = ref('')
const selectedMarker = ref('')
const isLoading = ref(false)
+// 从后端获取设备信息
// 从后端获取设备信息
const fetchDeviceInfo = async (terminalId) => {
try {
@@ -558,9 +659,10 @@ const fetchDeviceInfo = async (terminalId) => {
const marker = markers[terminalId]
if (marker) {
- // 更新标记点信息
- marker.status = data.status === 'active' ? 'online' : 'offline'
- marker.statusText = data.status === 'active' ? '在线' : '离线'
+ // 修改状态判断逻辑,同时兼容 'active' 和 'online' 状态
+ const isActive = data.status === 'active' || data.status === 'online'
+ marker.status = isActive ? 'online' : 'offline'
+ marker.statusText = isActive ? '在线' : '离线'
marker.quality = data.waterQuality || '--'
// 更新水质数据
@@ -573,7 +675,7 @@ const fetchDeviceInfo = async (terminalId) => {
marker.recordTime = data.updateTime || '--'
// 更新标记点颜色
- updateMarkerColor(terminalId, data.status)
+ updateMarkerColor(terminalId, isActive ? 'active' : 'inactive')
}
} else {
console.error(`获取设备 ${terminalId} 信息失败:`, result.message)
@@ -587,6 +689,7 @@ const fetchDeviceInfo = async (terminalId) => {
}
}
+
// 获取水质信息
const fetchWaterQualityInfo = async (deviceId) => {
try {
@@ -609,18 +712,7 @@ const updateMarkerColor = (terminalId, status) => {
}
}
-// 显示标记点信息
-const showMarkerInfo = async (markerId) => {
- currentMarker.value = markerId
- selectedMarker.value = markerId
- // 如果数据还在加载中,重新获取
- if (markers[markerId].status === 'loading') {
- await fetchDeviceInfo(markerId)
- }
-
- showDevicePopup.value = true
-}
// 隐藏弹窗
const hidePopup = () => {
@@ -683,18 +775,7 @@ const openMap = (mapType) => {
// 例如:window.location.href = `amapuri://route/...`
}
-// 地图控制
-const centerMap = () => {
- alert('定位到当前位置')
-}
-const zoomIn = () => {
- alert('放大地图')
-}
-
-const zoomOut = () => {
- alert('缩小地图')
-}
// 页面跳转
const goToPage = (page) => {
@@ -1532,4 +1613,67 @@ onMounted(() => {
font-size: 14px;
color: #666;
}
+
+/* 地图容器调整 */
+.map-container {
+ flex: 1;
+ position: relative;
+ overflow: hidden;
+ background: #e8f4fc;
+}
+
+.real-map-container {
+ width: 100%;
+ height: 100%;
+}
+
+/* 模拟地图背景(只有在真实地图加载失败时才显示) */
+.map-background {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ background: linear-gradient(135deg, #a8d8ff 0%, #e3f2fd 100%);
+ overflow: hidden;
+ display: none; /* 默认隐藏 */
+}
+
+/* 当真实地图加载失败时显示模拟地图 */
+.map-container:not(.map-loaded) .map-background {
+ display: block;
+}
+
+/* 地图控制按钮保持原有样式 */
+.map-controls {
+ position: absolute;
+ bottom: 100px;
+ right: 16px;
+ display: flex;
+ flex-direction: column;
+ gap: 12px;
+ z-index: 1000; /* 确保在地图上层 */
+}
+
+/* 自定义标记样式 */
+.custom-marker {
+ position: relative;
+}
+
+.custom-marker:hover div {
+ display: block !important;
+}
+
+/* 响应式调整 */
+@media (max-width: 420px) {
+ .home-page {
+ width: 100%;
+ height: 100vh;
+ }
+
+ .map-controls {
+ bottom: 70px;
+ right: 12px;
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/zzz/src/router/index.js b/src/main/resources/zzz/src/router/index.js
index 5ab741e..f0c378d 100644
--- a/src/main/resources/zzz/src/router/index.js
+++ b/src/main/resources/zzz/src/router/index.js
@@ -81,6 +81,12 @@ const router = createRouter({
name: 'InspectionForm',
component: () => import('../views/InspectionForm.vue'),
meta: { requiresAuth: true }
+ },
+ {
+ path: '/notifications',
+ name: 'NotificationsPage',
+ component: () => import('../views/NotificationsPage.vue'),
+ meta: { requiresAuth: true }
}
]
})
diff --git a/src/main/resources/zzz/src/services/notificationService.js b/src/main/resources/zzz/src/services/notificationService.js
new file mode 100644
index 0000000..8db84cb
--- /dev/null
+++ b/src/main/resources/zzz/src/services/notificationService.js
@@ -0,0 +1,40 @@
+// src/services/notificationService.js
+import api from './api'
+
+export const notificationService = {
+ // 获取未读通知
+ async getUnreadNotifications(repairmanId) {
+ try {
+ const response = await api.get('/api/app/repairman/notification/unread', {
+ params: { repairmanId }
+ })
+ return response.data
+ } catch (error) {
+ throw error.response?.data || error.message
+ }
+ },
+
+ // 获取所有通知
+ async getAllNotifications(repairmanId) {
+ try {
+ const response = await api.get('/api/app/repairman/notification/all', {
+ params: { repairmanId }
+ })
+ return response.data
+ } catch (error) {
+ throw error.response?.data || error.message
+ }
+ },
+
+ // 标记通知为已读
+ async markNotificationAsRead(notificationId) {
+ try {
+ const response = await api.post('/api/app/repairman/notification/read', null, {
+ params: { notificationId }
+ })
+ return response.data
+ } catch (error) {
+ throw error.response?.data || error.message
+ }
+ }
+}
diff --git a/src/main/resources/zzz/src/views/HomePage.vue b/src/main/resources/zzz/src/views/HomePage.vue
index a6b810a..64048c2 100644
--- a/src/main/resources/zzz/src/views/HomePage.vue
+++ b/src/main/resources/zzz/src/views/HomePage.vue
@@ -9,7 +9,12 @@