From 2e805e8c4c35c53e3ce1fb73528ab5e8d3f535d5 Mon Sep 17 00:00:00 2001
From: 罗广辉 <guanghui.luo@foxmail.com>
Date: Fri, 30 Jan 2026 15:26:54 +0800
Subject: [PATCH] feat: 共享

---
 applications/drone-command/src/views/permissionManage/permissionDept/index.vue              |   39 ++++++++-
 applications/drone-command/src/views/permissionManage/permissionDept/ShareDiaLog.vue        |  143 +++++++++++++++++++++++++++++++++++
 applications/drone-command/src/views/permissionManage/permissionDept/FormDiaLog.vue         |    3 
 applications/task-work-order/src/views/orderView/orderManage/orderManage/FormDiaLog.vue     |    3 
 applications/drone-command/src/views/permissionManage/permissionDept/fwDevicePerShareApi.js |   28 +++++++
 5 files changed, 205 insertions(+), 11 deletions(-)

diff --git a/applications/drone-command/src/views/permissionManage/permissionDept/FormDiaLog.vue b/applications/drone-command/src/views/permissionManage/permissionDept/FormDiaLog.vue
index d983ceb..d9adc8c 100644
--- a/applications/drone-command/src/views/permissionManage/permissionDept/FormDiaLog.vue
+++ b/applications/drone-command/src/views/permissionManage/permissionDept/FormDiaLog.vue
@@ -175,7 +175,7 @@
 const emit = defineEmits(['success'])
 const formRef = ref(null)
 const formData = ref(initForm())
-const visible = ref(false)
+const visible = defineModel()
 const dialogMode = ref('add')
 const submitting = ref(false)
 const isAddChild = ref(false)
@@ -283,7 +283,6 @@
 
 async function open({ mode, row, parent } = {}) {
 	dialogMode.value = mode || 'add'
-	visible.value = true
 	isAddChild.value = mode === 'add' && !!parent?.id
 	await getDeptTree().then(res => {
 		if (deptTree) {
diff --git a/applications/drone-command/src/views/permissionManage/permissionDept/ShareDiaLog.vue b/applications/drone-command/src/views/permissionManage/permissionDept/ShareDiaLog.vue
new file mode 100644
index 0000000..bbbf716
--- /dev/null
+++ b/applications/drone-command/src/views/permissionManage/permissionDept/ShareDiaLog.vue
@@ -0,0 +1,143 @@
+<template>
+	<el-dialog class="command-page-map-view-dialog" v-model="visible" :show-close="false" :close-on-click-modal="false">
+		<div class="dialog-container">
+			<div class="right-container" style="width: 100%">
+				<div class="header">
+					<span>设备共享</span>
+					<el-icon class="close-btn" @click.stop="visible = false"><Close /></el-icon>
+				</div>
+
+				<div class="content">
+					<div class="command-table-container" v-loading="loading" element-loading-background="rgba(5, 5, 15, 0.6)">
+						<div class="command-table-content">
+							<el-table
+								ref="tableRef"
+								class="command-table"
+								:data="deviceList"
+								row-key="id"
+								@selection-change="handleSelectionChange"
+							>
+								<el-table-column type="selection" width="55" :reserve-selection="true" />
+								<el-table-column type="index" show-overflow-tooltip width="64" label="序号" />
+								<el-table-column prop="deviceName" show-overflow-tooltip label="设备名称" />
+								<el-table-column prop="deviceSn" show-overflow-tooltip label="设备SN" />
+								<el-table-column prop="deviceType" show-overflow-tooltip label="设备类型" />
+								<el-table-column prop="belongDeptName" show-overflow-tooltip label="所属部门" />
+							</el-table>
+						</div>
+					</div>
+				</div>
+
+				<div class="footer">
+					<el-button color="#2B2B4C" @click="handleCancel">取消</el-button>
+					<el-button color="#284FE3" type="primary" :loading="submitting" :disabled="submitting" @click="handleSubmit">
+						确定
+					</el-button>
+				</div>
+			</div>
+		</div>
+	</el-dialog>
+</template>
+
+<script setup>
+import { Close } from '@element-plus/icons-vue'
+import { ref, nextTick } from 'vue'
+import { ElMessage } from 'element-plus'
+import { nonDeptAreaDevicesApi, fwDevicePerShareSaveApi, fwDevicePerShareRemoveApi } from './fwDevicePerShareApi'
+
+const emit = defineEmits(['success'])
+const visible = defineModel() // 弹框显隐
+const loading = ref(false) // 加载中
+const submitting = ref(false) // 提交中
+const deviceList = ref([]) // 设备列表
+const tableRef = ref(null) // 表格实例
+const selectedRows = ref([]) // 当前选中的行
+const originalSharedIds = ref([]) // 原始已共享的设备ID集合
+const currentDeptId = ref(null) // 当前操作的部门ID
+
+// 选中变化
+function handleSelectionChange(rows) {
+	selectedRows.value = rows
+}
+
+// 关闭弹框
+function handleCancel() {
+	visible.value = false
+}
+
+// 获取设备列表
+async function getDeviceList() {
+	loading.value = true
+	try {
+		const res = await nonDeptAreaDevicesApi({ loanToDeptId: currentDeptId.value })
+		deviceList.value = res?.data?.data ?? []
+		// 记录原始已共享的设备ID
+		originalSharedIds.value = deviceList.value.filter(item => item.isShared).map(item => item.id)
+		// 回显已共享的设备勾选状态
+		nextTick(() => {
+			deviceList.value.forEach(item => {
+				if (item.isShared) {
+					tableRef.value?.toggleRowSelection(item, true)
+				}
+			})
+		})
+	} finally {
+		loading.value = false
+	}
+}
+
+// 提交
+async function handleSubmit() {
+	submitting.value = true
+	try {
+		const currentSelectedIds = selectedRows.value.map(item => item.id)
+
+		// 计算需要新增的设备(当前选中但原来未共享)
+		const toAddDevices = selectedRows.value.filter(item => !originalSharedIds.value.includes(item.id))
+
+		// 计算需要删除的设备(原来共享但当前未选中)
+		const toRemoveIds = originalSharedIds.value.filter(id => !currentSelectedIds.includes(id))
+
+		const promises = []
+
+		// 调用新增接口
+		if (toAddDevices.length > 0) {
+			const addData = toAddDevices.map(item => ({
+				deviceId: item.id,
+				deviceSn: item.deviceSn,
+				loanFromDeptId: item.belongDept,
+				loanToDeptId: currentDeptId.value,
+			}))
+			promises.push(fwDevicePerShareSaveApi(addData))
+		}
+
+		// 调用删除接口
+		if (toRemoveIds.length > 0) {
+			promises.push(fwDevicePerShareRemoveApi({ ids: toRemoveIds.join(',') }))
+		}
+
+		if (promises.length > 0) {
+			await Promise.all(promises)
+			ElMessage.success('保存成功')
+		} else {
+			ElMessage.info('未做任何修改')
+		}
+
+		visible.value = false
+		emit('success')
+	} finally {
+		submitting.value = false
+	}
+}
+
+// 打开弹框
+async function open({ row } = {}) {
+	currentDeptId.value = row?.id
+	selectedRows.value = []
+	await getDeviceList()
+}
+
+defineExpose({ open })
+</script>
+
+<style scoped lang="scss"></style>
diff --git a/applications/drone-command/src/views/permissionManage/permissionDept/fwDevicePerShareApi.js b/applications/drone-command/src/views/permissionManage/permissionDept/fwDevicePerShareApi.js
new file mode 100644
index 0000000..2194414
--- /dev/null
+++ b/applications/drone-command/src/views/permissionManage/permissionDept/fwDevicePerShareApi.js
@@ -0,0 +1,28 @@
+import request from '@/axios'
+
+// 查询非本部门区域的设备
+export const nonDeptAreaDevicesApi = params => {
+	return request({
+		url: `/drone-fw/device/fwDevice/nonDeptAreaDevices`,
+		method: 'get',
+		params,
+	})
+}
+
+// 新增设备共享
+export const fwDevicePerShareSaveApi = data => {
+	return request({
+		url: `/drone-fw/device/fwDevicePerShare/save`,
+		method: 'post',
+		data,
+	})
+}
+
+// 删除设备共享
+export const fwDevicePerShareRemoveApi = params => {
+	return request({
+		url: `/drone-fw/device/fwDevicePerShare/remove`,
+		method: 'post',
+		params,
+	})
+}
diff --git a/applications/drone-command/src/views/permissionManage/permissionDept/index.vue b/applications/drone-command/src/views/permissionManage/permissionDept/index.vue
index 9930be6..160df0b 100644
--- a/applications/drone-command/src/views/permissionManage/permissionDept/index.vue
+++ b/applications/drone-command/src/views/permissionManage/permissionDept/index.vue
@@ -62,13 +62,14 @@
 					<el-table-column prop="sort" show-overflow-tooltip width="80" label="排序" />
 					<el-table-column prop="bingId" show-overflow-tooltip width="100" label="组织id" />
 					<el-table-column prop="areaName" show-overflow-tooltip width="180" label="行政区划" />
-					
+
 					<el-table-column label="操作" class-name="operation-btns" width="220">
 						<template v-slot="{ row }">
 							<el-link @click="handleView(row)">查看</el-link>
 							<el-link @click="handleEdit(row)">编辑</el-link>
 							<el-link @click="handleAddChild(row)">新增子项</el-link>
 							<el-link type="danger" @click="handleDelete(row)">删除</el-link>
+							<el-link type="danger" @click="handleShare(row)">共享</el-link>
 						</template>
 					</el-table-column>
 				</el-table>
@@ -86,18 +87,20 @@
 			</div>
 		</div>
 
-		<FormDiaLog ref="dialogRef" @success="getList" />
+		<FormDiaLog ref="dialogRef" @success="getList" v-model="visible" v-if="visible" />
+		<ShareDiaLog ref="shareDialogRef" @success="getList" v-model="shareVisible" v-if="shareVisible" />
 	</basic-container>
 </template>
 
 <script setup>
 import { Delete, Plus, RefreshRight, Search } from '@element-plus/icons-vue'
-import { onMounted, provide, ref } from 'vue'
+import { nextTick, onMounted, provide, ref } from 'vue'
 import { ElMessage, ElMessageBox } from 'element-plus'
 import { getDictionary } from '@/api/system/dict'
 import { getChildLazyTree, getDeptTree, getLazyList, remove } from '@/api/system/dept'
 import { getDictLabel } from '@ztzf/utils'
 import FormDiaLog from './FormDiaLog.vue'
+import ShareDiaLog from './ShareDiaLog.vue'
 import { saveOperationLog } from '@ztzf/apis'
 import { useRoute } from 'vue-router'
 
@@ -110,11 +113,14 @@
 
 const searchParams = ref(initSearchParams())
 const loading = ref(true)
+const visible = ref(false)
 const list = ref([])
 const total = ref(0)
 const selectedIds = ref([])
 const queryParamsRef = ref(null)
 const dialogRef = ref(null)
+const shareDialogRef = ref(null)
+const shareVisible = ref(false)
 const dictObj = ref({
 	org_category: [],
 	org_nature: [],
@@ -148,19 +154,38 @@
 }
 
 function handleAdd() {
-	dialogRef.value?.open({ mode: 'add' })
+	visible.value = true
+	nextTick(() => {
+		dialogRef.value?.open({ mode: 'add' })
+	})
 }
 
 function handleAddChild(row) {
-	dialogRef.value?.open({ mode: 'add', parent: row })
+	visible.value = true
+	nextTick(() => {
+		dialogRef.value?.open({ mode: 'add', parent: row })
+	})
 }
 
 function handleView(row) {
-	dialogRef.value?.open({ mode: 'view', row: { ...row } })
+	visible.value = true
+	nextTick(() => {
+		dialogRef.value?.open({ mode: 'view', row: { ...row } })
+	})
 }
 
 function handleEdit(row) {
-	dialogRef.value?.open({ mode: 'edit', row: { ...row } })
+	visible.value = true
+	nextTick(() => {
+		dialogRef.value?.open({ mode: 'edit', row: { ...row } })
+	})
+}
+
+function handleShare(row) {
+	shareVisible.value = true
+	nextTick(() => {
+		shareDialogRef.value?.open({ row })
+	})
 }
 
 async function handleDelete(row) {
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 41e1040..2e4ae11 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
@@ -264,7 +264,7 @@
 </template>
 
 <script setup>
-import { computed, ref, onMounted, nextTick } from 'vue'
+import { computed, ref, nextTick } from 'vue'
 import { ElMessage } from 'element-plus'
 import { dateRangeFormat, fieldRules, flyVisual, geomAnalysis, getDictLabel } from '@ztzf/utils'
 import {
@@ -321,7 +321,6 @@
 let viewer
 let drawPolygonExample
 let pointList = ref([])
-const requester = inject('requester')
 const suddenlyEdit = ref(false)
 const processList = ref([])
 let viewPlane

--
Gitblit v1.9.3