From 039679bf092a8a6cb1f8c921c8a2cfa5306dcf73 Mon Sep 17 00:00:00 2001
From: shuishen <1109946754@qq.com>
Date: Thu, 26 Feb 2026 14:25:02 +0800
Subject: [PATCH] Merge branch 'master' of http://139.196.74.78:10010/r/jagzwxm/ja_web

---
 applications/task-work-order/src/views/orderView/deviceInvocation/equipmentResource/equipmentResourceApi.js |    0 
 applications/drone-command/src/views/areaManage/partition/FormDiaLog copy.vue                               |    4 
 uniapps/work-app/src/pages/map/index.vue                                                                    |   37 ----
 applications/task-work-order/src/views/orderView/organizational/roleMange/RolePermissionDialog.vue          |   22 +-
 uniapps/work-app/src/hooks/useGlobalWS.js                                                                   |  122 ++++++++++---
 applications/task-work-order/src/api/system/user.js                                                         |    3 
 uniapps/work-app/src/subPackages/voiceCallDetail/index.vue                                                  |    8 
 applications/task-work-order/src/views/orderView/organizational/roleMange/FormDiaLog.vue                    |    0 
 applications/mobile-web-view/src/appPages/work/workDetail/index.vue                                         |    4 
 applications/task-work-order/src/views/orderView/deviceInvocation/equipmentResource/index.vue               |    0 
 applications/drone-command/src/views/areaManage/defenseZone/FormDiaLog.vue                                  |    4 
 applications/task-work-order/src/views/orderView/organizational/userMange/FormDiaLog.vue                    |    2 
 applications/drone-command/src/api/system/user.js                                                           |    3 
 applications/mobile-web-view/src/appPages/voiceCallDetail/index.vue                                         |   14 +
 applications/task-work-order/src/views/orderView/deviceInvocation/deviceCallRecord/index.vue                |   19 +-
 applications/drone-command/src/views/permissionManage/permissionUser/index.vue                              |    4 
 applications/task-work-order/src/views/orderView/deviceInvocation/equipmentResource/FormDiaLog.vue          |    0 
 applications/task-work-order/src/views/orderView/organizational/userMange/index.vue                         |    4 
 applications/drone-command/src/views/permissionManage/permissionUser/FormDiaLog.vue                         |    2 
 applications/task-work-order/src/views/orderView/organizational/roleMange/index.vue                         |    0 
 applications/task-work-order/src/views/orderView/orderManage/orderManage/FormDiaLog.vue                     |   42 ++++
 applications/task-work-order/src/views/orderView/deviceInvocation/deviceCallRecord/FormDiaLog.vue           |  142 +++++++++++++++
 packages/utils/map/DrawPolygon.js                                                                           |   40 ++++
 uniapps/work-app/src/App.vue                                                                                |    3 
 uniapps/work-app/src/utils/common/index.js                                                                  |    8 
 applications/drone-command/src/views/permissionManage/permissionRole/RolePermissionDialog.vue               |   44 ++--
 uniapps/work-app/src/static/audio/ringtone.mp3                                                              |    0 
 uniapps/work-app/src/pages/voiceCall/index.vue                                                              |    4 
 28 files changed, 398 insertions(+), 137 deletions(-)

diff --git a/applications/drone-command/src/api/system/user.js b/applications/drone-command/src/api/system/user.js
index 01b6ef4..c987df1 100644
--- a/applications/drone-command/src/api/system/user.js
+++ b/applications/drone-command/src/api/system/user.js
@@ -1,6 +1,6 @@
 import request from '@/axios';
 
-export const getList = (current, size,sysType, params, deptId) => {
+export const getList = (current, size,params, deptId) => {
   return request({
     url: '/blade-system/user/page',
     method: 'get',
@@ -8,7 +8,6 @@
       ...params,
       current,
       size,
-      sysType,
       deptId,
     },
   });
diff --git a/applications/drone-command/src/views/areaManage/defenseZone/FormDiaLog.vue b/applications/drone-command/src/views/areaManage/defenseZone/FormDiaLog.vue
index 9e5bc91..58551ba 100644
--- a/applications/drone-command/src/views/areaManage/defenseZone/FormDiaLog.vue
+++ b/applications/drone-command/src/views/areaManage/defenseZone/FormDiaLog.vue
@@ -251,7 +251,7 @@
 
 // 新增模式绘制
 function addPolygon () {
-	drawPolygonExample = new DrawPolygon(viewer)
+	drawPolygonExample = new DrawPolygon()
 	drawPolygonExample.initHandler(viewer)
 	drawPolygonExample.subscribe('getPolygonPositions', drawFinished)
 }
@@ -261,7 +261,7 @@
 	if (!formData.value?.geom) return
 	pointList = geomAnalysis(formData.value.geom)
 	drawPolygonExample?.destroy()
-	drawPolygonExample = new DrawPolygon(viewer)
+	drawPolygonExample = new DrawPolygon()
 	let noClosedList = _.cloneDeep(pointList)
 	noClosedList.pop()
 	drawPolygonExample.initPolygon(
diff --git a/applications/drone-command/src/views/areaManage/partition/FormDiaLog copy.vue b/applications/drone-command/src/views/areaManage/partition/FormDiaLog copy.vue
index 92a98c9..d90bd8f 100644
--- a/applications/drone-command/src/views/areaManage/partition/FormDiaLog copy.vue
+++ b/applications/drone-command/src/views/areaManage/partition/FormDiaLog copy.vue
@@ -352,7 +352,7 @@
 
 // 新增模式绘制
 function addPolygon () {
-	drawPolygonExample = new DrawPolygon(viewer)
+	drawPolygonExample = new DrawPolygon()
 	drawPolygonExample.initHandler(viewer)
 	drawPolygonExample.subscribe('getPolygonPositions', drawFinished)
 }
@@ -362,7 +362,7 @@
 	if (!formData.value?.geom) return
 	pointList = geomAnalysis(formData.value.geom)
 	drawPolygonExample?.destroy()
-	drawPolygonExample = new DrawPolygon(viewer)
+	drawPolygonExample = new DrawPolygon()
 	let pointList1 = _.cloneDeep(pointList)
 	pointList1.pop()
 	drawPolygonExample.initPolygon(
diff --git a/applications/drone-command/src/views/permissionManage/permissionRole/RolePermissionDialog.vue b/applications/drone-command/src/views/permissionManage/permissionRole/RolePermissionDialog.vue
index 37c6736..b76bfe3 100644
--- a/applications/drone-command/src/views/permissionManage/permissionRole/RolePermissionDialog.vue
+++ b/applications/drone-command/src/views/permissionManage/permissionRole/RolePermissionDialog.vue
@@ -20,28 +20,28 @@
 					:props="treeProps"
 				/>
 			</el-tab-pane>
-			<el-tab-pane label="任务工单">
-				<el-tree
-					class="command-tree"
-					ref="workRef"
-					:data="menuGrantListWord"
-					show-checkbox
-					node-key="id"
-					:default-checked-keys="menuTreeObjWork"
-					:props="treeProps"
-				/>
-			</el-tab-pane>
-			<el-tab-pane label="移动app">
-				<el-tree
-					class="command-tree"
-					ref="treeMenuApp"
-					:data="menuGrantListApp"
-					show-checkbox
-					node-key="id"
-					:default-checked-keys="menuTreeObjApp"
-					:props="treeProps"
-				/>
-			</el-tab-pane>
+<!--			<el-tab-pane label="任务工单">-->
+<!--				<el-tree-->
+<!--					class="command-tree"-->
+<!--					ref="workRef"-->
+<!--					:data="menuGrantListWord"-->
+<!--					show-checkbox-->
+<!--					node-key="id"-->
+<!--					:default-checked-keys="menuTreeObjWork"-->
+<!--					:props="treeProps"-->
+<!--				/>-->
+<!--			</el-tab-pane>-->
+<!--			<el-tab-pane label="移动app">-->
+<!--				<el-tree-->
+<!--					class="command-tree"-->
+<!--					ref="treeMenuApp"-->
+<!--					:data="menuGrantListApp"-->
+<!--					show-checkbox-->
+<!--					node-key="id"-->
+<!--					:default-checked-keys="menuTreeObjApp"-->
+<!--					:props="treeProps"-->
+<!--				/>-->
+<!--			</el-tab-pane>-->
 		</el-tabs>
 		<template #footer>
 			<el-button color="#2B2B4C" @click="visible = false">取消</el-button>
diff --git a/applications/drone-command/src/views/permissionManage/permissionUser/FormDiaLog.vue b/applications/drone-command/src/views/permissionManage/permissionUser/FormDiaLog.vue
index a473507..304ac4c 100644
--- a/applications/drone-command/src/views/permissionManage/permissionUser/FormDiaLog.vue
+++ b/applications/drone-command/src/views/permissionManage/permissionUser/FormDiaLog.vue
@@ -195,7 +195,7 @@
 	code: '',
 	roleId: '',
 	deptId: '',
-	sysType: 5
+	// sysType: 5
 })
 
 const treeProps = {
diff --git a/applications/drone-command/src/views/permissionManage/permissionUser/index.vue b/applications/drone-command/src/views/permissionManage/permissionUser/index.vue
index 72e8758..05e59b2 100644
--- a/applications/drone-command/src/views/permissionManage/permissionUser/index.vue
+++ b/applications/drone-command/src/views/permissionManage/permissionUser/index.vue
@@ -110,7 +110,7 @@
 	deptId: '',
 	current: 1,
 	size: 10,
-	sysType: 5,
+	// sysType: 5,
 })
 
 const searchParams = ref(initSearchParams())
@@ -135,7 +135,7 @@
 		const res = await getUserList(
 			searchParams.value.current,
 			searchParams.value.size,
-			searchParams.value.sysType,
+			// searchParams.value.sysType,
 			{
 				account: searchParams.value.account,
 				realName: searchParams.value.realName,
diff --git a/applications/mobile-web-view/src/appPages/voiceCallDetail/index.vue b/applications/mobile-web-view/src/appPages/voiceCallDetail/index.vue
index 52e2e4e..9359c56 100644
--- a/applications/mobile-web-view/src/appPages/voiceCallDetail/index.vue
+++ b/applications/mobile-web-view/src/appPages/voiceCallDetail/index.vue
@@ -22,7 +22,7 @@
 				<strong v-if="callEnded" class="status-text ended-status">{{ endMessage }}</strong>
 			</div>
 			<div class="button-group">
-				<button v-if="state === 'idle' && !receiveParameters" @click="requestCall" :disabled="!connected" class="btn btn-call">呼叫</button>
+				<!-- <button v-if="state === 'idle' && !receiveParameters && !callEnded" @click="requestCall" :disabled="!connected" class="btn btn-call">呼叫</button> -->
 
 				<button v-if="state==='ringing'" @click="acceptCall" class="btn btn-accept incoming-accept">接听</button>
 				<button v-if="state==='ringing'" @click="rejectCall" class="btn btn-reject incoming-reject">拒绝</button>
@@ -448,6 +448,9 @@
 	send('accept', incomingFrom, null)
 	log('✅ 已点击接听,发送 accept 给', incomingFrom)
 
+	// 停止铃声
+// 	const transmitData = { data: { type: 'stopVoice' } }
+// uni.postMessage(transmitData)
 	state.value = 'calling'
 
 	// 如果 offer 已经提前到达(我们暂存了),立刻 answer
@@ -463,6 +466,10 @@
 	// 你后端没有 reject,用 busy 表示拒绝/不可接听
 	send('busy', incomingFrom, null)
 	log('❌ 已拒绝来电,发送 busy 给', incomingFrom)
+
+	// 停止铃声
+// 	const transmitData = { data: { type: 'stopVoice' } }
+// uni.postMessage(transmitData)
 
 	incomingFrom = null
 	acceptedByMe = false
@@ -514,6 +521,9 @@
 }
 
 function hangup() {
+	// 停止铃声
+// 	const transmitData = { data: { type: 'stopVoice' } }
+// uni.postMessage(transmitData)
 	cleanup(true)
 }
 
@@ -577,7 +587,7 @@
 			}
 			// 重置通话结束状态
 			callEnded.value = false
-		}, 5000)
+		}, 3000)
 	}
 }
 
diff --git a/applications/mobile-web-view/src/appPages/work/workDetail/index.vue b/applications/mobile-web-view/src/appPages/work/workDetail/index.vue
index 12f8732..4e19622 100644
--- a/applications/mobile-web-view/src/appPages/work/workDetail/index.vue
+++ b/applications/mobile-web-view/src/appPages/work/workDetail/index.vue
@@ -69,14 +69,14 @@
 	const imageArr = []
 	const detail = workDetailData.value
 	if (detail.eventImageUrl) {
-		const smallUrl = getSmallImg(detail.eventImageUrl)
+		const smallUrl = detail.eventImageUrl
 		imageArr.push(smallUrl)
 	}
 	return imageArr
 })
 const openPreview = index => {
 	const detail = workDetailData.value
-	const showUrl = getShowImg(detail.eventImageUrl)
+	const showUrl = detail.eventImageUrl
 	showImagePreview({
 		images: [showUrl],
 		startPosition: 0,
diff --git a/applications/task-work-order/src/api/system/user.js b/applications/task-work-order/src/api/system/user.js
index 8d7f684..63ecdf7 100644
--- a/applications/task-work-order/src/api/system/user.js
+++ b/applications/task-work-order/src/api/system/user.js
@@ -1,6 +1,6 @@
 import request from '@/axios';
 
-export const getList = (current, size, sysType, params, deptId) => {
+export const getList = (current, size, params, deptId) => {
   return request({
     url: '/blade-system/user/page',
     method: 'get',
@@ -8,7 +8,6 @@
       ...params,
       current,
       size,
-      sysType,
       deptId,
     },
   });
diff --git a/applications/task-work-order/src/views/orderView/deviceInvocation/deviceCallRecord/FormDiaLog.vue b/applications/task-work-order/src/views/orderView/deviceInvocation/deviceCallRecord/FormDiaLog.vue
new file mode 100644
index 0000000..ddb6a4f
--- /dev/null
+++ b/applications/task-work-order/src/views/orderView/deviceInvocation/deviceCallRecord/FormDiaLog.vue
@@ -0,0 +1,142 @@
+<template>
+	<el-dialog class="gd-dialog" v-model="visible" :title="dialogTitle" @closed="handleClosed" destroy-on-close
+						 :close-on-click-modal="false">
+		<!--		<div class="detail-row-view" v-if="dialogReadonly">-->
+		<el-table :data="list" class="gd-dialog-table">
+			<el-table-column prop="resultCode" show-overflow-tooltip label="序号" />
+			<el-table-column prop="resultCode" show-overflow-tooltip label="设备状态" />
+			<el-table-column prop="shootTime" show-overflow-tooltip label="发生时间" />
+		</el-table>
+	</el-dialog>
+</template>
+
+<script setup>
+import { computed, onMounted, ref } from 'vue'
+import { ElMessage } from 'element-plus'
+import { add, getUser, update } from '@/api/system/user'
+import { getDeptTree } from '@/api/system/dept'
+import { getRoleTree } from '@/api/system/role'
+import func from '@/utils/func'
+import { saveOperationLog } from '@ztzf/apis'
+import { useRoute } from 'vue-router'
+
+const list = ref([])
+
+const initForm = () => ({
+	account: '',
+	password: '',
+	password2: '',
+	realName: '',
+	phone: '',
+	email: '',
+	sex: null,
+	birthday: '',
+	code: '',
+	roleId: '',
+	deptId: '',
+	// sysType: 6
+})
+
+const treeProps = {
+	label: 'title',
+	children: 'children',
+}
+const deptTreeSelectProps = {
+	label: 'name',
+	value: 'id',
+	children: 'children',
+}
+
+const emit = defineEmits(['success'])
+const formRef = ref(null)
+const formData = ref(initForm())
+const visible = ref(false)
+const dialogMode = ref('add')
+const submitting = ref(false)
+const dialogReadonly = computed(() => dialogMode.value === 'view')
+const dialogTitle = computed(() => {
+	if (dialogMode.value === 'edit') return '编辑'
+	if (dialogMode.value === 'view') return '查看'
+	return '新增'
+})
+const roleTree = ref([])
+const deptTree = ref([])
+const route = useRoute()
+
+const validatePass = (rule, value, callback) => {
+	if (value === '') {
+		callback(new Error('请输入密码'))
+	} else {
+		callback()
+	}
+}
+const validatePass2 = (rule, value, callback) => {
+	if (value === '') {
+		callback(new Error('请再次输入密码'))
+	} else if (value !== formData.value.password) {
+		callback(new Error('两次输入密码不一致'))
+	} else {
+		callback()
+	}
+}
+
+async function getRoleTreeData() {
+	const res = await getRoleTree('000000')
+	roleTree.value = res.data.data
+}
+
+async function getDeptTreeData() {
+	const res = await getDeptTree('000000')
+	deptTree.value = res.data.data
+}
+
+function handleCancel() {
+	visible.value = false
+}
+
+async function loadDetail() {
+	if (!formData.value.id) return
+	const res = await getUser(formData.value.id)
+	const data = res?.data?.data ?? {}
+	if (data.roleId) {
+		data.roleId = func.split(data.roleId)[0] || data.roleId
+	}
+	formData.value = data
+}
+
+function handleClosed() {
+	formData.value = initForm()
+}
+
+async function open({ mode, row } = {}) {
+	dialogMode.value = mode || 'add'
+	visible.value = true
+	if (dialogMode.value === 'add') {
+		formData.value = initForm()
+		return
+	}
+	formData.value = { id: row.id }
+	await loadDetail()
+}
+
+onMounted(() => {
+	getRoleTreeData()
+	getDeptTreeData()
+})
+
+defineExpose({ open })
+</script>
+
+<style scoped lang="scss">
+:deep(.el-select) {
+	width: 100%;
+}
+
+:deep(.el-date-editor) {
+	width: 100%;
+}
+
+:deep(.el-tree-select) {
+	width: 100%;
+}
+</style>
diff --git a/applications/task-work-order/src/views/orderView/systemMange/userMange/index.vue b/applications/task-work-order/src/views/orderView/deviceInvocation/deviceCallRecord/index.vue
similarity index 91%
copy from applications/task-work-order/src/views/orderView/systemMange/userMange/index.vue
copy to applications/task-work-order/src/views/orderView/deviceInvocation/deviceCallRecord/index.vue
index d18d70e..862a156 100644
--- a/applications/task-work-order/src/views/orderView/systemMange/userMange/index.vue
+++ b/applications/task-work-order/src/views/orderView/deviceInvocation/deviceCallRecord/index.vue
@@ -60,16 +60,17 @@
 				<el-table class="gd-table" :data="list" @selection-change="handleSelectionChange">
 					<el-table-column type="selection" width="46" />
 					<el-table-column type="index" show-overflow-tooltip width="64" label="序号" />
-					<el-table-column prop="account" show-overflow-tooltip label="登录账号" />
-					<el-table-column prop="realName" show-overflow-tooltip label="用户姓名" />
-					<el-table-column prop="roleName" show-overflow-tooltip label="所属角色" />
-					<el-table-column prop="deptName" show-overflow-tooltip label="所属部门" />
-					<el-table-column prop="phone" show-overflow-tooltip width="120" label="手机号" />
+					<el-table-column prop="account" show-overflow-tooltip label="任务名称" />
+					<el-table-column prop="realName" show-overflow-tooltip label="发起任务部门" />
+					<el-table-column prop="roleName" show-overflow-tooltip label="任务发起人" />
+					<el-table-column prop="deptName" show-overflow-tooltip label="飞行时长" />
+					<el-table-column prop="phone" show-overflow-tooltip label="飞行里程(m)" />
+					<el-table-column prop="phone" show-overflow-tooltip label="执行设备" />
+					<el-table-column prop="phone" show-overflow-tooltip label="计划执行时间" />
+					<el-table-column prop="phone" show-overflow-tooltip label="实际执行时间" />
 					<el-table-column label="操作" class-name="operation-btns" width="180">
 						<template v-slot="{ row }">
 							<el-link  @click="handleView(row)">查看</el-link>
-							<el-link v-if="permission.orderUser_edit" @click="handleEdit(row)">编辑</el-link>
-							<el-link v-if="permission.orderUser_remove" type="danger" @click="handleDelete(row)">删除</el-link>
 						</template>
 					</el-table-column>
 				</el-table>
@@ -108,7 +109,7 @@
 	deptId: '',
 	current: 1,
 	size: 10,
-	sysType: 6
+	// sysType: 6
 })
 
 const searchParams = ref(initSearchParams())
@@ -133,7 +134,7 @@
 		const res = await getUserList(
 			searchParams.value.current,
 			searchParams.value.size,
-			searchParams.value.sysType,
+			// searchParams.value.sysType,
 			{
 				account: searchParams.value.account,
 				realName: searchParams.value.realName,
diff --git a/applications/task-work-order/src/views/orderView/equipmentResource/FormDiaLog.vue b/applications/task-work-order/src/views/orderView/deviceInvocation/equipmentResource/FormDiaLog.vue
similarity index 100%
rename from applications/task-work-order/src/views/orderView/equipmentResource/FormDiaLog.vue
rename to applications/task-work-order/src/views/orderView/deviceInvocation/equipmentResource/FormDiaLog.vue
diff --git a/applications/task-work-order/src/views/orderView/equipmentResource/equipmentResourceApi.js b/applications/task-work-order/src/views/orderView/deviceInvocation/equipmentResource/equipmentResourceApi.js
similarity index 100%
rename from applications/task-work-order/src/views/orderView/equipmentResource/equipmentResourceApi.js
rename to applications/task-work-order/src/views/orderView/deviceInvocation/equipmentResource/equipmentResourceApi.js
diff --git a/applications/task-work-order/src/views/orderView/equipmentResource/index.vue b/applications/task-work-order/src/views/orderView/deviceInvocation/equipmentResource/index.vue
similarity index 100%
rename from applications/task-work-order/src/views/orderView/equipmentResource/index.vue
rename to applications/task-work-order/src/views/orderView/deviceInvocation/equipmentResource/index.vue
diff --git a/applications/task-work-order/src/views/orderView/orderManage/orderManage/FormDiaLog.vue b/applications/task-work-order/src/views/orderView/orderManage/orderManage/FormDiaLog.vue
index 7ab4e00..b5c8899 100644
--- a/applications/task-work-order/src/views/orderView/orderManage/orderManage/FormDiaLog.vue
+++ b/applications/task-work-order/src/views/orderView/orderManage/orderManage/FormDiaLog.vue
@@ -317,6 +317,7 @@
 const suddenlyEdit = ref(false)
 const processList = ref([])
 let viewPlane
+let allDeviceList = []
 const hasPatrolTaskList = computed(() => ['30', '40', '50', '60'].includes(String(formData.value.workOrderStatus)))
 
 const gdStatusObj = {
@@ -472,7 +473,7 @@
 
 // 新增模式绘制
 function addPolygon() {
-	drawPolygonExample = new DrawPolygon(viewer)
+	drawPolygonExample = new DrawPolygon({ deviceList: allDeviceList })
 	drawPolygonExample.initHandler(viewer)
 	drawPolygonExample.subscribe('getPolygonPositions', drawFinished)
 }
@@ -494,7 +495,7 @@
 	if (!formData.value?.geom) return
 	pointList.value = geomAnalysis(formData.value.geom)
 	drawPolygonExample?.destroy()
-	drawPolygonExample = new DrawPolygon(viewer)
+	drawPolygonExample = new DrawPolygon({ deviceList: allDeviceList })
 	let noClosedList = _.cloneDeep(pointList.value)
 	noClosedList.pop()
 	drawPolygonExample.initPolygon(
@@ -550,6 +551,19 @@
 	})
 }
 
+//  生成圆形坐标点
+function buildCirclePositions(center, radius, segments = 120) {
+	const cartographic = Cesium.Cartographic.fromCartesian(center)
+	const positions = []
+	for (let i = 0; i < segments; i++) {
+		const angle = (i / segments) * 2 * Math.PI
+		const lat = cartographic.latitude + (radius / 6378137) * Math.cos(angle)
+		const lon = cartographic.longitude + (radius / (6378137 * Math.cos(cartographic.latitude))) * Math.sin(angle)
+		positions.push(Cesium.Cartesian3.fromRadians(lon, lat))
+	}
+	return positions
+}
+
 //  渲染
 function renderingAllDevice(list) {
 	list.forEach(item => {
@@ -576,6 +590,27 @@
 				pixelOffset: new Cesium.Cartesian2(0, -20),
 			},
 		})
+		// 覆盖范围 - 5km圆形区域
+		viewer.entities.add({
+			position: position,
+			ellipse: {
+				semiMajorAxis: 5000,
+				semiMinorAxis: 5000,
+				material: Cesium.Color.fromBytes(45, 140, 240, 80),
+				outline: false,
+				heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
+			},
+		})
+		// 覆盖范围描边线 - 贴地
+		const circlePositions = buildCirclePositions(position, 5000)
+		viewer.entities.add({
+			polyline: {
+				positions: [...circlePositions, circlePositions[0]],
+				clampToGround: true,
+				width: 2,
+				material: Cesium.Color.fromBytes(45, 140, 240, 255),
+			},
+		})
 	})
 }
 
@@ -593,7 +628,8 @@
 	initMap()
 	const allDeviceRes = await gdManageDeviceListApi()
 	formData.value = dialogMode.value === 'add' ? initForm() : row
-	renderingAllDevice(allDeviceRes?.data?.data || [])
+	allDeviceList = allDeviceRes?.data?.data || []
+	renderingAllDevice(allDeviceList)
 	if (dialogMode.value === 'add') {
 		addPolygon()
 	} else {
diff --git a/applications/task-work-order/src/views/orderView/systemMange/roleMange/FormDiaLog.vue b/applications/task-work-order/src/views/orderView/organizational/roleMange/FormDiaLog.vue
similarity index 100%
rename from applications/task-work-order/src/views/orderView/systemMange/roleMange/FormDiaLog.vue
rename to applications/task-work-order/src/views/orderView/organizational/roleMange/FormDiaLog.vue
diff --git a/applications/task-work-order/src/views/orderView/systemMange/roleMange/RolePermissionDialog.vue b/applications/task-work-order/src/views/orderView/organizational/roleMange/RolePermissionDialog.vue
similarity index 90%
rename from applications/task-work-order/src/views/orderView/systemMange/roleMange/RolePermissionDialog.vue
rename to applications/task-work-order/src/views/orderView/organizational/roleMange/RolePermissionDialog.vue
index 3b14f65..e4312df 100644
--- a/applications/task-work-order/src/views/orderView/systemMange/roleMange/RolePermissionDialog.vue
+++ b/applications/task-work-order/src/views/orderView/organizational/roleMange/RolePermissionDialog.vue
@@ -31,17 +31,17 @@
 					:props="treeProps"
 				/>
 			</el-tab-pane>
-<!--			<el-tab-pane label="移动app">-->
-<!--				<el-tree-->
-<!--					class="command-tree"-->
-<!--					ref="treeMenuApp"-->
-<!--					:data="menuGrantListApp"-->
-<!--					show-checkbox-->
-<!--					node-key="id"-->
-<!--					:default-checked-keys="menuTreeObjApp"-->
-<!--					:props="treeProps"-->
-<!--				/>-->
-<!--			</el-tab-pane>-->
+			<el-tab-pane label="移动app">
+				<el-tree
+					class="command-tree"
+					ref="treeMenuApp"
+					:data="menuGrantListApp"
+					show-checkbox
+					node-key="id"
+					:default-checked-keys="menuTreeObjApp"
+					:props="treeProps"
+				/>
+			</el-tab-pane>
 		</el-tabs>
 		<template #footer>
 			<el-button color="#F2F3F5" @click="visible = false">取消</el-button>
diff --git a/applications/task-work-order/src/views/orderView/systemMange/roleMange/index.vue b/applications/task-work-order/src/views/orderView/organizational/roleMange/index.vue
similarity index 100%
rename from applications/task-work-order/src/views/orderView/systemMange/roleMange/index.vue
rename to applications/task-work-order/src/views/orderView/organizational/roleMange/index.vue
diff --git a/applications/task-work-order/src/views/orderView/systemMange/userMange/FormDiaLog.vue b/applications/task-work-order/src/views/orderView/organizational/userMange/FormDiaLog.vue
similarity index 99%
rename from applications/task-work-order/src/views/orderView/systemMange/userMange/FormDiaLog.vue
rename to applications/task-work-order/src/views/orderView/organizational/userMange/FormDiaLog.vue
index a8b3d1b..329edb5 100644
--- a/applications/task-work-order/src/views/orderView/systemMange/userMange/FormDiaLog.vue
+++ b/applications/task-work-order/src/views/orderView/organizational/userMange/FormDiaLog.vue
@@ -195,7 +195,7 @@
 	code: '',
 	roleId: '',
 	deptId: '',
-	sysType: 6
+	// sysType: 6
 })
 
 const treeProps = {
diff --git a/applications/task-work-order/src/views/orderView/systemMange/userMange/index.vue b/applications/task-work-order/src/views/orderView/organizational/userMange/index.vue
similarity index 98%
rename from applications/task-work-order/src/views/orderView/systemMange/userMange/index.vue
rename to applications/task-work-order/src/views/orderView/organizational/userMange/index.vue
index d18d70e..e53f208 100644
--- a/applications/task-work-order/src/views/orderView/systemMange/userMange/index.vue
+++ b/applications/task-work-order/src/views/orderView/organizational/userMange/index.vue
@@ -108,7 +108,7 @@
 	deptId: '',
 	current: 1,
 	size: 10,
-	sysType: 6
+	// sysType: 6
 })
 
 const searchParams = ref(initSearchParams())
@@ -133,7 +133,7 @@
 		const res = await getUserList(
 			searchParams.value.current,
 			searchParams.value.size,
-			searchParams.value.sysType,
+			// searchParams.value.sysType,
 			{
 				account: searchParams.value.account,
 				realName: searchParams.value.realName,
diff --git a/packages/utils/map/DrawPolygon.js b/packages/utils/map/DrawPolygon.js
index 77ec1e6..2bdeeff 100644
--- a/packages/utils/map/DrawPolygon.js
+++ b/packages/utils/map/DrawPolygon.js
@@ -14,7 +14,10 @@
  *  - 外部订阅/通知机制
  */
 export class DrawPolygon {
-	constructor() {
+	constructor(options = {}) {
+		// 设备覆盖范围列表(经纬度 + 5000m半径)
+		this.deviceList = options.deviceList || []
+		this.coverageRadius = 5000
 		// 图斑预览模式标记
 		this.isPureSpotPreview = false
 		// 是否删除测区
@@ -398,6 +401,19 @@
 	handleLeftUp() {
 		if (!(this.editingMode && this.curPolygon?.positions && this.draggedEntity)) return
 
+		// 检查松手位置是否在设备覆盖范围内
+		if (this.isDragging && !this.isWithinDeviceCoverage(this.curPolygon.positions[this.draggedEntity?.customData.ind])) {
+			ElMessage.warning('该位置不在设备覆盖范围内,请在设备5公里范围内绘制')
+			// 回弹到拖拽前的位置
+			this.draggedEntity.position = this.currentDragPointPosition
+			this.curPolygon.positions[this.draggedEntity?.customData.ind] = this.currentDragPointPosition
+			this.isDragging = false
+			this.draggedEntity = null
+			this.enableMapControl()
+			this.rebuildMidPoints()
+			return
+		}
+
 		if (this.currentDragPointIsValid && this.isDragging) {
 			// 更新点位置
 			this.draggedEntity.position = this.currentDragPointPosition
@@ -514,6 +530,12 @@
 		// 添加新的点
 		const cartesian = this.viewer.scene.pickPosition(click.position)
 		if (!cartesian) return
+
+		// 检查点击位置是否在设备覆盖范围内
+		if (!this.isWithinDeviceCoverage(cartesian)) {
+			ElMessage.warning('该位置不在设备覆盖范围内,请在设备5公里范围内绘制')
+			return
+		}
 
 		let arr = [...this.curPolygon.positions]
 		arr.pop()
@@ -662,7 +684,7 @@
 
 		const menuItems =
 			type === 'polygon'
-				? [{ title: '删除测区', class: 'del-planar-polygon' }]
+				? [{ title: '删除范围', class: 'del-planar-polygon' }]
 				: [{ title: '删除端点', class: 'del-planar-point' }]
 
 		menuItems.forEach(item => {
@@ -726,6 +748,20 @@
 
 		return intersections.features.length === 0
 	}
+
+	// 检查位置是否在任意设备的覆盖范围内(5km)
+	isWithinDeviceCoverage(cartesian) {
+		if (!this.deviceList || this.deviceList.length === 0) return true
+		const cartographic = Cesium.Cartographic.fromCartesian(cartesian)
+		const clickPoint = turf.point([Cesium.Math.toDegrees(cartographic.longitude), Cesium.Math.toDegrees(cartographic.latitude)])
+		return this.deviceList
+			.filter(item => item.latitude)
+			.some(item => {
+				const rangePoint = turf.point([item.longitude, item.latitude])
+				const distance = turf.distance(rangePoint, clickPoint, { units: 'kilometers' })
+				return distance <= 5
+			})
+	}
 	// 初始化已有多边形
 	async initPolygon(viewer, positions, isPurePreview = false) {
 		this.initHandler(viewer)
diff --git a/uniapps/work-app/src/App.vue b/uniapps/work-app/src/App.vue
index 2cfcd46..2397296 100644
--- a/uniapps/work-app/src/App.vue
+++ b/uniapps/work-app/src/App.vue
@@ -33,7 +33,6 @@
 allowFloat()
 // #endif
 
-
 useGlobalWS()
 
 onShow(async () => {
@@ -60,7 +59,7 @@
 	// #ifdef APP-PLUS
 	keepAliveStart()
 	// 请求用户允许忽略电池优化(重要:用于保活)
-	setTimeout(requestIgnoreBatteryOptimization, 120000)
+	setTimeout(requestIgnoreBatteryOptimization, 10000)
 	// #endif
 }
 
diff --git a/uniapps/work-app/src/hooks/useGlobalWS.js b/uniapps/work-app/src/hooks/useGlobalWS.js
index a4302d4..36086d1 100644
--- a/uniapps/work-app/src/hooks/useGlobalWS.js
+++ b/uniapps/work-app/src/hooks/useGlobalWS.js
@@ -1,13 +1,17 @@
 import { useUserStore } from "@/store/index.js";
 import useAppStore from "../store/modules/app/index.js";
 import websocketService from "@/utils/websocket.js";
-
+// #ifdef APP-PLUS
+import { openDialog, allowFloat, getBatteryCapacity } from '@/uni_modules/lgh-dialog'
+// #endif
 export function useGlobalWS() {
 	const userStore = useUserStore();
   const appStore = useAppStore();
   const callStatus = ref(null)
   // token 存储
   const accessToken = ref('')
+  // 存储铃声实例
+  let ringtoneInstance = null
 
   // 设置默认用户ID为3
   const defaultUserId = '2021474815063486465';
@@ -23,13 +27,19 @@
     // 处理语音通话请求
     if (t === 'call') {
       console.log('📞 全局收到来电 call,来自', payload.from)
+      // 播放铃声
+      // playRingtone();
+      // 触发震动
+      triggerVibration();
       // 构建来电参数
       const callParams = {
         peerUid: payload.from,
         from: payload.from,
         type: 'incoming'
       };
-
+// #ifdef APP-PLUS
+			openDialog()
+      // #endif
       // 转义参数以便在URL中传递
       const encodedParams = encodeURIComponent(JSON.stringify(callParams));
 
@@ -47,33 +57,91 @@
       }
       return
     }
-
-    // 然后处理biz_code格式的消息
-    // switch (bizCode) {
-    //   case 'JOB_ISREFRESH':
-    //     appStore.setJobUpdateKeyAdd()
-    //     break
-    //   case 'DEVICE_ISREFRESH':
-    //     appStore.setDeviceUpdateKeyAdd()
-    //     break
-    //   case 'DOWNLOAD_PROGRESS':
-    //     break
-    //   case 'LOGOUT_USER':
-    //     userStore.setUserInfo(null)
-    //     uni.reLaunch({
-    //       url: '/pages/login/index'
-    //     })
-    //     break
-    //   case 'VoiceCall':
-    //     // enterRoom(payload, userId.value)
-    //     break
-    //   default:
-    //     // 记录未处理的消息
-    //     console.log('未处理的WebSocket消息:', payload)
-    //     break;
-    // }
   }
 
+  // 播放来电铃声 - 定义在 messageHandler 外部
+  // function playRingtone() {
+  //   try {
+  //     if (typeof uni !== 'undefined' && uni.createInnerAudioContext) {
+  //       const ringtone = uni.createInnerAudioContext();
+  //       // 使用默认铃声,注意路径写法
+  //       ringtone.src = '/static/audio/ringtone.mp3';
+  //       ringtone.loop = true;
+  //       ringtone.volume = 0.8;
+  //       ringtone.play();
+  //       // 存储铃声实例
+  //       ringtoneInstance = ringtone; // 使用局部变量而不是window
+  //     }
+  //   } catch (error) {
+  //   }
+  // }
+
+  // 触发震动
+  function triggerVibration() {
+    try {
+      if (typeof uni !== 'undefined') {
+        // 方法1:使用uni.vibrate(现代API)
+        if (uni.vibrate) {
+          // 震动400ms
+          uni.vibrate({
+            duration: 400,
+            success: () => {
+              console.log('📳 震动已触发');
+            },
+            fail: (error) => {
+              // 方法2:使用uni.vibrateLong(兼容旧设备)
+              if (uni.vibrateLong) {
+                uni.vibrateLong({
+                  success: () => {
+                    console.log('📳 兼容模式震动已触发');
+                  },
+                  fail: (err) => {
+                    console.error('兼容模式震动失败:', err);
+                  }
+                });
+              }
+            }
+          });
+        }
+        // 方法3:使用plus API(H5+)
+        if (typeof plus !== 'undefined' && plus.device && plus.device.vibrate) {
+          plus.device.vibrate(400);
+          console.log('📳 H5+ 震动已触发');
+        }
+      }
+    } catch (error) {
+      console.error('触发震动失败:', error);
+    }
+  }
+
+  // 停止铃声
+  // function stopRingtone() {
+  //   try {
+  //     if (ringtoneInstance) {
+  //       ringtoneInstance.stop();
+  //       ringtoneInstance.destroy();
+  //       ringtoneInstance = null;
+  //     }
+  //   } catch (error) {
+  //     // 即使出错也重置实例
+  //     ringtoneInstance = null;
+  //   }
+  // }
+  //
+  // // 监听停止铃声事件
+  // if (typeof uni !== 'undefined' && uni.$on) {
+  //   uni.$on('stopRingtone', stopRingtone);
+  //   // 监听WebView消息事件
+  //   uni.$on('webViewMessage', (data) => {
+  //     // 检查是否是停止铃声消息
+  //     if (data?.type === 'stopVoice') {
+  //       stopRingtone();
+  //       console.log('📳 收到WebView停止铃声消息,已停止铃声');
+  //
+  //     }
+  //   });
+  // }
+
   // 初始化WebSocket连接
   function initWS() {
     const userStore = useUserStore()
diff --git a/uniapps/work-app/src/pages/map/index.vue b/uniapps/work-app/src/pages/map/index.vue
index 2ee54c8..45d5fb8 100644
--- a/uniapps/work-app/src/pages/map/index.vue
+++ b/uniapps/work-app/src/pages/map/index.vue
@@ -23,9 +23,6 @@
 const userParams = userStore?.userInfo ? JSON.stringify(userStore.userInfo) : '{}';
 
 const updateKey = ref(0);
-// const viewUrl = computed(() => {
-//   return `https://192.168.1.157:5176/mobile-web-view/#/webViewWrapper/defaultMap?params=${encodeURIComponent(userParams)}&isWeb=${envParam}&updateKey=${updateKey.value}`;
-// });
 const viewUrl = computed(() => {
   return getWebViewUrl("/defaultMap", {
     isWeb: envParam,
@@ -34,40 +31,6 @@
 });
 
 const onPostMessage = (data) => {
-  // #ifdef MP-WEIXIN
-  if (data.type === "scanCode") {
-  } else if (data.type === "jumpAddWork") {
-  } else if (data.type === "jumpMapNav") {
-    //事件导航
-  } else if (data.type === "workid") {
-    //事件详情
-  }
-  // #endif
-
-  // #ifndef MP-WEIXIN
-  if (data.type === "scanCode") {
-    uni.navigateTo({
-      url: "/subPackages/qrCode/index",
-    });
-  } else if (data.type === "jumpAddWork") {
-    //新建任务
-    const encodedData = encodeURIComponent(JSON.stringify(data.rowItem));
-    uni.setStorageSync("webview_params", encodedData);
-    uni.navigateTo({
-      url: `/subPackages/taskDetail/addTask/index`,
-    });
-  } else if (data.type === "jumpMapNav") {
-    //事件导航
-    uni.navigateTo({
-      url: `/subPackages/workDetail/mapWork/index?currentItem=${data.eventNum}`,
-    });
-  } else if (data.type === "workid") {
-    //事件详情
-    uni.navigateTo({
-      url: `/subPackages/workDetail/index?eventNum=${data.eventNum}`,
-    });
-  }
-  // #endif
 };
 
 onShow(() => {
diff --git a/uniapps/work-app/src/pages/voiceCall/index.vue b/uniapps/work-app/src/pages/voiceCall/index.vue
index 6bab0fa..fd9fc06 100644
--- a/uniapps/work-app/src/pages/voiceCall/index.vue
+++ b/uniapps/work-app/src/pages/voiceCall/index.vue
@@ -48,8 +48,8 @@
 import { getPhoneBookListApi } from '@/api/voiceCall/index.js'
 import { onShow } from '@dcloudio/uni-app'
 import defaultAvatar from '/static/images/defaultAvatar.svg'
-  const userStore = useUserStore()
-  const userId = userStore.userInfo.new_userInfo.userId
+const userStore = useUserStore()
+const userId = userStore.userInfo.new_userInfo.userId
 // 联系人数据
 const contacts = ref([])
 const defaultParam = ref({
diff --git a/uniapps/work-app/src/static/audio/ringtone.mp3 b/uniapps/work-app/src/static/audio/ringtone.mp3
new file mode 100644
index 0000000..956c7e3
--- /dev/null
+++ b/uniapps/work-app/src/static/audio/ringtone.mp3
Binary files differ
diff --git a/uniapps/work-app/src/subPackages/voiceCallDetail/index.vue b/uniapps/work-app/src/subPackages/voiceCallDetail/index.vue
index 6798ebd..710e6b2 100644
--- a/uniapps/work-app/src/subPackages/voiceCallDetail/index.vue
+++ b/uniapps/work-app/src/subPackages/voiceCallDetail/index.vue
@@ -74,11 +74,15 @@
   const contact = options.contact ? JSON.parse(decodeURIComponent(options.contact)) : null;
   // 构建viewUrl,将contact参数拼接到URL中
   const contactParam = contact ? encodeURIComponent(JSON.stringify(contact)) : '';
-  // viewUrl.value = `https://192.168.1.157:5176/mobile-web-view/#/webViewWrapper/voiceCallDetail?params=${encodeURIComponent(userParams)}&contact=${contactParam}`;
   viewUrl.value = getWebViewUrl("/voiceCallDetail", { contact: options.contact ,voiceparams: options.voiceparams});
 });
 
-function onPostMessage(data) {}
+function onPostMessage(data) {
+	// 将WebView消息传递给全局WebSocket处理
+	// if (typeof uni !== 'undefined' && uni.$emit) {
+	// 	uni.$emit('webViewMessage', data);
+	// }
+}
 
 </script>
 
diff --git a/uniapps/work-app/src/utils/common/index.js b/uniapps/work-app/src/utils/common/index.js
index 605ed86..a7b4e6c 100644
--- a/uniapps/work-app/src/utils/common/index.js
+++ b/uniapps/work-app/src/utils/common/index.js
@@ -72,8 +72,12 @@
   // 1. 处理用户参数
   const userParams = userStore?.userInfo ? JSON.stringify(userStore.userInfo) : '{}'
   // 2. 构建查询参数字符串
-  let queryString = `params=${encodeURIComponent(userParams)}&topMargin=${statusBarHeight}&uniPlatform=${uniPlatform}`
-
+  let queryString = null
+  if(targetUrl === '/workDetail') {
+    queryString = `topMargin=${statusBarHeight}&uniPlatform=${uniPlatform}`
+  }else{
+    queryString = `params=${encodeURIComponent(userParams)}&topMargin=${statusBarHeight}&uniPlatform=${uniPlatform}`
+  }
   // 3. 处理 otherParams 对象
   if (otherParams && typeof otherParams === 'object') {
     Object.keys(otherParams).forEach(key => {

--
Gitblit v1.9.3