From ceeb5fdbe689d68c4f795690ea56a27ed515757c Mon Sep 17 00:00:00 2001
From: shuishen <1109946754@qq.com>
Date: Fri, 16 Jan 2026 10:55:57 +0800
Subject: [PATCH] Merge branch 'master' of http://139.196.74.78:10010/r/jagzwxm/ja_web

---
 uniapps/work-app/src/hooks/useGlobalWS.js             |  102 +++--------
 uniapps/work-app/src/utils/websocket.js               |    6 
 uniapps/work-app/src/pages/login/index.vue            |   53 -----
 uniapps/work-app/src/subPackages/workDetail/index.vue |  366 ++++++++++++++++++++++++++++------------
 4 files changed, 287 insertions(+), 240 deletions(-)

diff --git a/uniapps/work-app/src/hooks/useGlobalWS.js b/uniapps/work-app/src/hooks/useGlobalWS.js
index 9f18e0c..64d3d58 100644
--- a/uniapps/work-app/src/hooks/useGlobalWS.js
+++ b/uniapps/work-app/src/hooks/useGlobalWS.js
@@ -1,5 +1,4 @@
 import { useUserStore } from "@/store/index.js";
-import { ref, computed, watch } from "vue";
 import useAppStore from "../store/modules/app/index.js";
 import websocketService from "@/utils/websocket.js";
 
@@ -34,81 +33,24 @@
       // 转义参数以便在URL中传递
       const encodedParams = encodeURIComponent(JSON.stringify(callParams));
 
-      // 跳转到mobile-web-view应用中的语音通话页面
-      const voiceCallUrl = `http://localhost:9527/work-app/#/subPackages/voiceCallDetail/index?voiceparams=${encodedParams}`;
-
-      console.log('🔗 准备导航到:', voiceCallUrl)
-
       try {
-        // 优先使用uni-app的导航API(适用于uni-app环境)
+        // 优先使用uni-app的导航API(适用于同应用内跳转)
         if (typeof uni !== 'undefined' && uni.navigateTo) {
           console.log('使用uni-app导航API跳转到语音通话页面');
-
-          // 检查是否是跳转到应用内页面
-          if (voiceCallUrl.includes('/subPackages/voiceCallDetail/')) {
-            // 应用内页面跳转
-            uni.navigateTo({
-              url: voiceCallUrl.replace('http://localhost:9527/work-app/#', ''),
-              success: () => {
-                console.log('✅ 应用内导航成功!');
-              },
-              fail: (err) => {
-                console.error('❌ 应用内导航失败:', err);
-                // 如果应用内导航失败,尝试使用外部跳转
-                fallbackToExternalNavigation();
-              }
-            });
-          } else {
-            // 外部页面跳转
-            fallbackToExternalNavigation();
-          }
-        }
-        // 否则尝试使用window.location跳转(适用于Web环境)
-        else if (typeof window !== 'undefined' && window.location) {
-          console.log('使用window.location跳转到语音通话页面');
-          window.location.href = voiceCallUrl;
+          uni.navigateTo({
+            url: `/subPackages/voiceCallDetail/index?voiceparams=${encodedParams}`,
+            success: () => {
+              console.log('✅ 应用内导航成功!');
+            },
+            fail: (err) => {
+              console.error('❌ 应用内导航失败:', err);
+            }
+          });
         } else {
           console.error('无法跳转到语音通话页面:当前环境不支持导航');
         }
       } catch (error) {
         console.error('跳转到语音通话页面失败:', error);
-        // 尝试使用外部跳转作为最后的补救措施
-        fallbackToExternalNavigation();
-      }
-
-      // 外部页面跳转的回调函数
-      function fallbackToExternalNavigation() {
-        console.log('尝试使用外部导航跳转到语音通话页面');
-        try {
-          // 使用uni-app的外部链接跳转API
-          if (typeof uni !== 'undefined' && uni.navigateToWebview) {
-            // 这是一个示例,具体API可能需要根据uni-app版本和配置调整
-            uni.navigateToWebview({
-              url: voiceCallUrl,
-              success: () => {
-                console.log('✅ 外部Webview导航成功!');
-              },
-              fail: (err) => {
-                console.error('❌ 外部Webview导航失败:', err);
-                // 如果还是失败,尝试使用浏览器打开
-                if (typeof plus !== 'undefined' && plus.runtime) {
-                  plus.runtime.openURL(voiceCallUrl);
-                } else {
-                  console.error('❌ 所有导航方式都失败了');
-                }
-              }
-            });
-          }
-          // 或者使用plus.runtime.openURL(适用于App环境)
-          else if (typeof plus !== 'undefined' && plus.runtime) {
-            plus.runtime.openURL(voiceCallUrl);
-            console.log('尝试使用plus.runtime.openURL打开外部链接');
-          } else {
-            console.error('无法跳转到外部页面:当前环境不支持外部导航');
-          }
-        } catch (fallbackError) {
-          console.error('外部导航尝试失败:', fallbackError);
-        }
       }
       return
     }
@@ -142,14 +84,24 @@
   // 初始化WebSocket连接
   function initWS() {
     try {
-      // 使用默认用户ID初始化WebSocket连接
-      websocketService.init(defaultUserId, WS_BASE);
-      console.log('🌐 全局WebSocket初始化成功,默认用户ID:', defaultUserId);
+      // 检查是否已经有活跃的WebSocket连接
+      if (!websocketService.getConnected()) {
+        // 使用默认用户ID初始化WebSocket连接
+        websocketService.init(defaultUserId, WS_BASE);
+        console.log('🌐 全局WebSocket初始化成功,默认用户ID:', defaultUserId);
+      } else {
+        console.log('🌐 WebSocket已存在活跃连接,无需重新初始化');
+      }
 
-      // 设置全局消息处理回调
-      websocketService.setOnMessageCallback(messageHandler);
-
-      console.log('✅ 全局WebSocket消息处理器已设置');
+      // 只设置一次全局消息处理回调
+      // 检查是否已经设置了回调
+      if (typeof websocketService.getOnMessageCallback() !== 'function') {
+        // 设置全局消息处理回调
+        websocketService.setOnMessageCallback(messageHandler);
+        console.log('✅ 全局WebSocket消息处理器已设置');
+      } else {
+        console.log('✅ WebSocket消息处理器已存在,无需重新设置');
+      }
     } catch (error) {
       console.error('❌ 全局WebSocket初始化失败:', error);
     }
diff --git a/uniapps/work-app/src/pages/login/index.vue b/uniapps/work-app/src/pages/login/index.vue
index 4dc8802..7158d87 100644
--- a/uniapps/work-app/src/pages/login/index.vue
+++ b/uniapps/work-app/src/pages/login/index.vue
@@ -135,59 +135,8 @@
       userInfo.key,
       userInfo.code
     );
-    console.log('登录成功,用户信息:', res.data.data);
     userStore.setUserInfo(res.data.data);
-
-
-    // 初始化WebSocket连接
-    try {
-      const wsUrl = 'wss://wrj.shuixiongit.com/ws/chat?userId=';
-      // 设置默认用户ID为3
-      const defaultUserId = '3';
-      // 使用默认用户ID初始化WebSocket连接
-      websocketService.init(defaultUserId, wsUrl);
-      console.log('登录成功,WebSocket已初始化,默认用户ID:', defaultUserId);
-      
-      // 设置来电消息回调
-      websocketService.setOnMessageCallback((message) => {
-        if (message.type === 'call') {
-          console.log('收到来电,准备跳转到语音通话页面');
-          // 构建来电参数
-          const callParams = {
-            peerUid: message.from,
-            from: message.from,
-            type: 'incoming'
-          };
-          
-          // 转义参数以便在URL中传递
-          const encodedParams = encodeURIComponent(JSON.stringify(callParams));
-          
-          try {
-            // 优先使用uni-app的导航API(适用于同应用内跳转)
-            if (typeof uni !== 'undefined' && uni.navigateTo) {
-              console.log('使用uni-app导航API跳转到语音通话页面');
-              uni.navigateTo({
-                url: `/subPackages/voiceCallDetail/index?params=${encodedParams}`
-              });
-            } 
-            // 否则使用window.location跳转(适用于Web环境)
-            else if (typeof window !== 'undefined' && window.location) {
-              console.log('使用window.location跳转到语音通话页面');
-              // 注意:实际部署时需要使用正确的URL
-              const voiceCallUrl = `http://localhost:8080/appPages/voiceCallDetail/index.html?params=${encodedParams}`;
-              window.location.href = voiceCallUrl;
-            } else {
-              console.error('无法跳转到语音通话页面:当前环境不支持导航');
-            }
-          } catch (error) {
-            console.error('跳转到语音通话页面失败:', error);
-          }
-        }
-      });
-    } catch (error) {
-      console.error('WebSocket初始化失败:', error);
-    }
-
+    console.log('登录成功,WebSocket连接将由全局钩子统一管理');
     uni.reLaunch({
       url: "/pages/work/index",
     });
diff --git a/uniapps/work-app/src/subPackages/workDetail/index.vue b/uniapps/work-app/src/subPackages/workDetail/index.vue
index b61a8ca..231874c 100644
--- a/uniapps/work-app/src/subPackages/workDetail/index.vue
+++ b/uniapps/work-app/src/subPackages/workDetail/index.vue
@@ -1,40 +1,58 @@
 <!-- 工单详情 -->
 <template>
-  <div class="workDetailContainer">
-    <!-- 自定义导航栏 -->
-    <u-navbar
-      title="工单详情"
-      :is-back="true"
-      back-text=""
-      :back-icon-size="40"
-      @left-click="onBackClick"
-    >
-      <template #right>
-        <div class="share-btn" @click="onShareClick">分享</div>
-      </template>
-    </u-navbar>
-    <div class="detailTop">
-      <div class="image-container">
-        <u-swiper
-          class="detailImage"
-          :list="getImageList"
-          mode="round"
-          indicator
-          indicatorMode="dot"
-          indicatorActiveColor="#4C85FF"
-          indicatorInactiveColor="#fff"
-          indicatorPosition="center"
-          height="410rpx"
-          @click="previewImage"
-        ></u-swiper>
-        <!--				<div class="detailTitle">-->
-        <!--					<div class="titleText">-->
-        <!--						<div class="itemName">{{workDetailData.event_name}}</div>-->
-        <!--						<div class="itemTime">{{formatDate(workDetailData.create_time)}}</div>-->
-        <!--					</div>-->
-        <!--				</div>-->
-      </div>
-    </div>
+	<div class="workDetailContainer">
+		<!-- 自定义导航栏 -->
+		<u-navbar title="工单详情" :is-back="true" back-text="" :back-icon-size="40" @left-click="onBackClick">
+			<template #right>
+				<div class="share-btn" @click="onShareClick">分享</div>
+			</template>
+		</u-navbar>
+
+		<!-- 分享弹出层 -->
+		<div v-if="showShareModal" class="share-modal-overlay" @click="onShareModalClose">
+			<div class="share-modal-content" @click.stop>
+				<div class="share-modal-header">
+					<div class="share-modal-title">分享到</div>
+					<div class="share-modal-close" @click="onShareModalClose">×</div>
+				</div>
+				<div class="share-modal-body">
+					<div class="share-item" @click="shareToWechat">
+						<div class="share-icon wechat"></div>
+						<div class="share-name">微信好友</div>
+					</div>
+					<div class="share-item" @click="shareToMoments">
+						<div class="share-icon moments"></div>
+						<div class="share-name">朋友圈</div>
+					</div>
+					<div class="share-item" @click="copyLink">
+						<div class="share-icon link"></div>
+						<div class="share-name">复制链接</div>
+					</div>
+				</div>
+			</div>
+		</div>
+		<div class="detailTop">
+			<div class="image-container">
+				<u-swiper
+					class="detailImage"
+					:list="getImageList"
+					mode="round"
+					indicator
+					indicatorMode="dot"
+					indicatorActiveColor="#4C85FF"
+					indicatorInactiveColor="#fff"
+					indicatorPosition="center"
+					height="410rpx"
+					@click="previewImage"
+				></u-swiper>
+				<!--				<div class="detailTitle">-->
+				<!--					<div class="titleText">-->
+				<!--						<div class="itemName">{{workDetailData.event_name}}</div>-->
+				<!--						<div class="itemTime">{{formatDate(workDetailData.create_time)}}</div>-->
+				<!--					</div>-->
+				<!--				</div>-->
+			</div>
+		</div>
 
     <!-- 工单内容 -->
     <div class="worderContainer">
@@ -178,88 +196,111 @@
   })
 }
 
-// 分享按钮点击事件
+// 分享模态框状态
+const showShareModal = ref(false)
+
+// 分享按钮点击事件 - 显示分享模态框
 const onShareClick = () => {
-  // 检查当前平台是否支持分享功能
-  const platform = uni.getSystemInfoSync().platform
+	showShareModal.value = true
+}
 
-  // H5平台不支持uni.share API
-  if (platform === 'web') {
-    uni.showToast({
-      title: 'H5平台暂不支持分享功能',
-      icon: 'none'
-    })
-    return
-  }
+// 关闭分享模态框
+const onShareModalClose = () => {
+	showShareModal.value = false
+}
 
-  uni.showActionSheet({
-    itemList: ['分享给微信好友', '分享到朋友圈'],
-    success: res => {
-      // 检查uni.share是否存在
-      if (typeof uni.share !== 'function') {
-        uni.showToast({
-          title: '当前环境不支持分享功能',
-          icon: 'none'
-        })
-        return
-      }
+// 微信好友分享
+const shareToWechat = () => {
+	shareToPlatform('weixin', 'WXSceneSession')
+}
 
-      try {
-        switch (res.tapIndex) {
-          case 0:
-            // 分享给微信好友
-            uni.share({
-              provider: 'weixin',
-              scene: 'WXSceneSession',
-              type: 0,
-              title: '工单详情',
-              summary: workDetailData.value.event_name,
-              href: 'https://example.com/workDetail?eventNum=' + workDetailData.value.event_num,
-              imageUrl: workDetailData.value.photo_url,
-              success: () => {
-                uni.showToast({ title: '分享成功', icon: 'success' })
-              },
-              fail: (err) => {
-                console.log('分享失败', err.errMsg)
-                uni.showToast({
-                  title: err.errMsg,
-                  icon: 'none'
-                })
-              }
-            })
-            break
-          case 1:
-            // 分享到朋友圈
-            uni.share({
-              provider: 'weixin',
-              scene: 'WXSceneTimeline',
-              type: 0,
-              title: workDetailData.value.event_name,
-              summary: '查看工单详情',
-              href: 'https://example.com/workDetail?eventNum=' + workDetailData.value.event_num,
-              imageUrl: workDetailData.value.photo_url,
-              success: () => {
-                uni.showToast({ title: '分享成功', icon: 'success' })
-              },
-              fail: (err) => {
-                console.log('分享失败', err)
-                uni.showToast({
-                  title: '分享失败,请检查配置',
-                  icon: 'none'
-                })
-              }
-            })
-            break
-        }
-      } catch (error) {
-        console.error('分享出错:', error)
-        uni.showToast({
-          title: '分享功能异常',
-          icon: 'none'
-        })
-      }
-    }
-  })
+// 朋友圈分享
+const shareToMoments = () => {
+	shareToPlatform('weixin', 'WXSceneTimeline')
+}
+
+// 复制链接
+const copyLink = async () => {
+	const shareUrl = 'https://example.com/workDetail?eventNum=' + workDetailData.value.event_num
+	try {
+		await uni.setClipboardData({
+			data: shareUrl,
+		})
+		uni.showToast({
+			title: '链接已复制',
+			icon: 'success',
+		})
+	} catch (error) {
+		console.error('复制失败:', error)
+		uni.showToast({
+			title: '复制失败,请重试',
+			icon: 'none',
+		})
+	}
+	onShareModalClose()
+}
+
+// 通用分享平台函数
+const shareToPlatform = (provider, scene = '') => {
+	// 检查当前平台是否支持分享功能
+	const platform = uni.getSystemInfoSync().platform
+
+	// H5平台不支持uni.share API
+	if (platform === 'web') {
+		uni.showToast({
+			title: 'H5平台暂不支持分享功能',
+			icon: 'none',
+		})
+		onShareModalClose()
+		return
+	}
+
+	// 检查uni.share是否存在
+	if (typeof uni.share !== 'function') {
+		uni.showToast({
+			title: '当前环境不支持分享功能',
+			icon: 'none',
+		})
+		onShareModalClose()
+		return
+	}
+
+	try {
+		const shareConfig = {
+			provider,
+			type: 0,
+			title: workDetailData.value.event_name || '工单详情',
+			summary: '查看工单详情',
+			href: 'https://example.com/workDetail?eventNum=' + workDetailData.value.event_num,
+			imageUrl: workDetailData.value.photo_url,
+			success: () => {
+				uni.showToast({ title: '分享成功', icon: 'success' })
+				onShareModalClose()
+			},
+			fail: err => {
+				console.log('分享失败', err)
+				uni.showToast({
+					title: '分享失败,请重试',
+					icon: 'none',
+				})
+				onShareModalClose()
+			},
+		}
+
+		// 添加场景参数(如果有)
+		if (scene) {
+			shareConfig.scene = scene
+		}
+
+		uni.share(shareConfig)
+	} catch (error) {
+		console.error('分享出错:', error)
+		uni.showToast({
+			title: '分享功能异常',
+			icon: 'none',
+		})
+		onShareModalClose()
+	}
 }
 
 // 返回按钮点击事件
@@ -422,4 +463,103 @@
     }
   }
 }
+
+/* 分享弹出层样式 */
+.share-modal-overlay {
+	position: fixed;
+	top: 0;
+	left: 0;
+	right: 0;
+	bottom: 0;
+	background-color: rgba(0, 0, 0, 0.6);
+	display: flex;
+	justify-content: flex-end;
+	align-items: flex-end;
+	z-index: 9999;
+}
+
+.share-modal-content {
+	background-color: #fff;
+	border-radius: 20rpx 20rpx 0 0;
+	padding: 30rpx;
+	width: 100%;
+	max-height: 80vh;
+	overflow-y: auto;
+}
+
+.share-modal-header {
+	display: flex;
+	justify-content: space-between;
+	align-items: center;
+	margin-bottom: 30rpx;
+}
+
+.share-modal-title {
+	font-size: 36rpx;
+	font-weight: bold;
+	color: #222324;
+	text-align: center;
+	flex: 1;
+}
+
+.share-modal-close {
+	font-size: 60rpx;
+	color: #999;
+	line-height: 40rpx;
+}
+
+.share-modal-body {
+	display: flex;
+	flex-wrap: wrap;
+	justify-content: space-around;
+	padding-bottom: 30rpx;
+}
+
+.share-modal-footer {
+	display: flex;
+	justify-content: space-around;
+	padding-top: 30rpx;
+	border-top: 1px solid #f0f0f0;
+}
+
+.share-item {
+	display: flex;
+	flex-direction: column;
+	align-items: center;
+	margin: 20rpx;
+	width: 120rpx;
+}
+
+.share-icon {
+	width: 90rpx;
+	height: 90rpx;
+	border-radius: 50%;
+	margin-bottom: 15rpx;
+	background-size: contain;
+	background-repeat: no-repeat;
+	background-position: center;
+}
+
+.share-icon.wechat {
+	background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="%2307C160" d="M18.66 6.86l-1.41-1.42a1 1 0 00-1.42 0l-12 12a1 1 0 000 1.42l1.42 1.42a1 1 0 001.42 0l12-12a1 1 0 000-1.42z"/><path fill="%2307C160" d="M8.5 14.5c-2.21 0-4-1.79-4-4s1.79-4 4-4 4 1.79 4 4-1.79 4-4 4zm0-6a2 2 0 100 4 2 2 0 000-4zm7 6c-2.21 0-4-1.79-4-4s1.79-4 4-4 4 1.79 4 4-1.79 4-4 4zm0-6a2 2 0 100 4 2 2 0 000-4z"/></svg>');
+}
+
+.share-icon.moments {
+	background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="%2307C160" d="M18 2H6c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm0 18H6V4h12v16z"/><path fill="%2307C160" d="M12 6c-3.31 0-6 2.69-6 6s2.69 6 6 6 6-2.69 6-6-2.69-6-6-6zm0 10c-2.21 0-4-1.79-4-4s1.79-4 4-4 4 1.79 4 4-1.79 4-4 4z"/><path fill="%2307C160" d="M10 13.5h4v3h-4z"/></svg>');
+}
+
+
+.share-icon.link {
+	background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="%23666" d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"/></svg>');
+}
+
+.share-icon.poster {
+	background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="%23FFA500" d="M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H5V5h14v14z"/><path fill="%23FFA500" d="M12 8c-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4-1.79-4-4-4zm0 6c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2z"/></svg>');
+}
+
+.share-name {
+	font-size: 24rpx;
+	color: #666;
+	margin-top: 10rpx;
+}
 </style>
diff --git a/uniapps/work-app/src/utils/websocket.js b/uniapps/work-app/src/utils/websocket.js
index 9706abd..32379d1 100644
--- a/uniapps/work-app/src/utils/websocket.js
+++ b/uniapps/work-app/src/utils/websocket.js
@@ -160,8 +160,14 @@
 
   // 设置消息回调
   setOnMessageCallback(callback) {
+    console.log('🔔 WebSocket消息回调已设置')
     this.onMessageCallback = callback
   }
+  
+  // 获取当前消息回调(用于检查是否已设置)
+  getOnMessageCallback() {
+    return this.onMessageCallback
+  }
 
   // 设置连接打开回调
   setOnOpenCallback(callback) {

--
Gitblit v1.9.3