Browse Source

feat: 支持组态项目复制

- 新增组态复制接口,提交 id、项目名称和备注
- 卡片操作区增加复制入口,复用项目配置弹窗
- 复制时带出原绑定设备但禁用编辑,仅允许修改名称和备注
Zimo 1 day ago
parent
commit
1ea04d0a02
2 changed files with 77 additions and 3 deletions
  1. 12 0
      src/api/pms/maotu/index.ts
  2. 65 3
      src/views/maotu/index.vue

+ 12 - 0
src/api/pms/maotu/index.ts

@@ -51,6 +51,12 @@ export type WebtopoProjectUpdateReqVO = WebtopoProjectCreateReqVO & {
   dataModel?: string
 }
 
+export type WebtopoProjectCopyReqVO = {
+  id: number
+  projectName: string
+  remark?: string
+}
+
 type ApiResult<T> = {
   code?: number
   data?: T
@@ -107,6 +113,12 @@ export const WebtopoProjectApi = {
       data
     })
   },
+  copyWebtopoProject: (data: WebtopoProjectCopyReqVO) => {
+    return request.post({
+      url: '/pms/iot-webtopo-project/copyProject',
+      data
+    })
+  },
   getWebtopoProjectPage: (params: WebtopoProjectPageReqVO) => {
     return request.get<WebtopoProjectVO[] | { list: WebtopoProjectVO[]; total: number }>({
       url: '/pms/iot-webtopo-project/page',

+ 65 - 3
src/views/maotu/index.vue

@@ -1,6 +1,7 @@
 <script lang="ts" setup>
 import {
   WebtopoProjectApi,
+  type WebtopoProjectCopyReqVO,
   type WebtopoProjectCreateReqVO,
   type WebtopoProjectPageReqVO,
   type WebtopoProjectUpdateReqVO,
@@ -32,7 +33,7 @@ const initQuery: WebtopoProjectPageReqVO = {
 
 const query = ref<WebtopoProjectPageReqVO>({ ...initQuery })
 
-type FormMode = 'create' | 'config'
+type FormMode = 'create' | 'config' | 'copy'
 type ProjectForm = Partial<WebtopoProjectUpdateReqVO>
 
 interface DeviceOption {
@@ -157,6 +158,21 @@ async function openConfig(row: WebtopoProjectVO) {
   formRef.value?.clearValidate()
 }
 
+async function openCopy(row: WebtopoProjectVO) {
+  formMode.value = 'copy'
+  createForm.value = {
+    id: row.id,
+    projectName: `${row.projectName || ''}副本`,
+    linkedDeviceIds: getLinkedDeviceIds(row),
+    remark: row.remark
+  }
+  deviceOptions.value = []
+  createVisible.value = true
+  await loadDeviceOptions(deptId)
+  await nextTick()
+  formRef.value?.clearValidate()
+}
+
 function handleCreateClose() {
   createVisible.value = false
 }
@@ -204,12 +220,37 @@ async function submitConfig() {
   }
 }
 
+async function submitCopy() {
+  if (!formRef.value || !createForm.value.id || deviceLoading.value) return
+
+  try {
+    createLoading.value = true
+    await formRef.value.validate()
+    const data: WebtopoProjectCopyReqVO = {
+      id: createForm.value.id,
+      projectName: createForm.value.projectName!,
+      remark: createForm.value.remark
+    }
+    await WebtopoProjectApi.copyWebtopoProject(data)
+    ElMessage.success('复制成功')
+    handleCreateClose()
+    loadList()
+  } finally {
+    createLoading.value = false
+  }
+}
+
 function submitForm() {
   if (formMode.value === 'config') {
     submitConfig()
     return
   }
 
+  if (formMode.value === 'copy') {
+    submitCopy()
+    return
+  }
+
   submitCreate()
 }
 
@@ -237,6 +278,24 @@ function handleConfig(row: WebtopoProjectVO) {
   openConfig(row)
 }
 
+function handleCopy(row: WebtopoProjectVO) {
+  openCopy(row)
+}
+
+function getDialogTitle() {
+  if (formMode.value === 'config') {
+    return '配置关联设备'
+  }
+
+  if (formMode.value === 'copy') {
+    return '复制组态项目'
+  }
+
+  return '新建组态项目'
+}
+
+const isDeviceSelectDisabled = computed(() => deviceLoading.value || formMode.value === 'copy')
+
 watch(
   [() => query.value.deptId, () => query.value.projectName],
   () => {
@@ -370,6 +429,9 @@ watch(
                     <el-button size="small" type="primary" link @click="handlePreview(item)">
                       <Icon icon="ep:view" class="mr-4px" /> 预览
                     </el-button>
+                    <el-button size="small" type="primary" link @click="handleCopy(item)">
+                      <Icon icon="ep:copy-document" class="mr-4px" /> 复制
+                    </el-button>
                     <el-button size="small" type="primary" link @click="handleConfig(item)">
                       <Icon icon="ep:setting" class="mr-4px" /> 配置
                     </el-button>
@@ -399,7 +461,7 @@ watch(
 
   <el-dialog
     v-model="createVisible"
-    :title="formMode === 'config' ? '配置关联设备' : '新建组态项目'"
+    :title="getDialogTitle()"
     width="560px"
     :close-on-click-modal="false"
     destroy-on-close>
@@ -426,7 +488,7 @@ watch(
           collapse-tags-tooltip
           :max-collapse-tags="3"
           :loading="deviceLoading"
-          :disabled="deviceLoading"
+          :disabled="isDeviceSelectDisabled"
           class="w-full"
           :placeholder="deviceLoading ? '设备选项加载中...' : '请选择绑定设备'">
           <el-option