yanghao vor 1 Tag
Ursprung
Commit
a3a1f9da7c
3 geänderte Dateien mit 119 neuen und 21 gelöschten Zeilen
  1. 12 0
      src/api/pms/maotu/index.ts
  2. 65 3
      src/views/maotu/index.vue
  3. 42 18
      src/views/pms/stat/rykb/ryProductionBriefs.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

+ 42 - 18
src/views/pms/stat/rykb/ryProductionBriefs.vue

@@ -178,9 +178,9 @@ onMounted(() => {
 
 <template>
   <div
-    class="panel device-list-panel production-brief-panel w-full flex flex-col"
+    class="panel device-list-panel production-brief-panel w-full min-h-0 flex flex-col"
     :class="{ 'production-brief-panel--full': props.pageMode === 'full' }">
-    <div class="panel-title flex items-center justify-between">
+    <div class="panel-title device-list-panel__title flex items-center justify-between">
       <div class="kb-panel-title-text flex items-center">
         <div class="icon-decorator">
           <span></span>
@@ -188,25 +188,28 @@ onMounted(() => {
         </div>
         生产简报
       </div>
-      <div class="production-brief-panel__picker">
+      <div class="device-list-panel__picker">
         <el-date-picker
           v-model="selectedDate"
           value-format="YYYY-MM-DD"
           type="date"
           placeholder="选择日期"
           :clearable="false"
-          class="production-brief-panel__picker-input"
+          class="device-list-panel__picker-input"
           @change="handleDateChange" />
       </div>
     </div>
-    <div class="device-list-panel__body flex-1 min-h-0">
+    <div class="device-list-panel__body flex flex-col flex-1 min-h-0">
       <el-table
         v-loading="loading"
         :data="tableData"
         :height="tableHeight"
         :span-method="tableSpanMethod"
+        element-loading-text="加载中..."
+        element-loading-background="rgb(222 236 252 / 72%)"
+        border
         class="device-list-table production-brief-table"
-        :class="{ 'production-brief-table--full': props.pageMode === 'full' }">
+        :class="{ 'device-list-table--full': props.pageMode === 'full' }">
         <el-table-column prop="projectClassification" label="公司" min-width="72" align="center" />
         <el-table-column prop="projectName" label="项目" min-width="150" align="center" />
         <el-table-column prop="deptName" label="队伍" min-width="94" align="center" />
@@ -222,7 +225,11 @@ onMounted(() => {
           prop="constructionBrief"
           label="当日生产简况"
           min-width="160"
-          align="center" />
+          align="center">
+          <template #default="{ row }">
+            <div class="production-brief-table__summary">{{ row.constructionBrief || '--' }}</div>
+          </template>
+        </el-table-column>
 
         <el-table-column label="当日进尺(m)/当日井次" min-width="150" align="center">
           <template #default="{ row }">
@@ -260,17 +267,13 @@ onMounted(() => {
 
 .device-list-panel.production-brief-panel--full {
   height: 100%;
+  min-height: 0;
   margin-top: 0;
 }
 
-.production-brief-panel__picker {
-  display: flex;
-  width: calc(120px * var(--kb-scale, 1));
-  align-items: center;
-}
-
-.production-brief-panel__picker-input {
-  width: calc(120px * var(--kb-scale, 1)) !important;
+.device-list-panel__picker,
+.device-list-panel__picker-input {
+  width: calc(160px * var(--kb-scale, 1)) !important;
 
   :deep(.el-input__wrapper) {
     min-height: calc(28px * var(--kb-scale, 1));
@@ -293,26 +296,47 @@ onMounted(() => {
   :deep(.el-table__header-wrapper th.el-table__cell) {
     font-size: calc(16px * var(--kb-scale, 1));
     line-height: 1.2;
+    color: #10233c !important;
+    background: #b5cde7 !important;
+    border-color: #fff !important;
   }
 
   :deep(.el-table__body td.el-table__cell) {
+    height: calc(58px * var(--kb-scale, 1));
     padding: calc(7px * var(--kb-scale, 1)) 0;
     font-size: calc(14px * var(--kb-scale, 1));
+    color: #07192c !important;
+    background: #89b3de !important;
+    border-color: #fff !important;
+  }
+
+  :deep(.el-table__body tr:nth-child(2n) td.el-table__cell) {
+    background: #b8cee5 !important;
+  }
+
+  :deep(.el-table__row:hover > td.el-table__cell) {
+    background: #75a5d6 !important;
   }
 }
 
-.production-brief-table--full {
+.production-brief-table__summary {
+  line-height: 1.5;
+  white-space: pre-wrap;
+  overflow-wrap: anywhere;
+}
+
+.device-list-table--full {
   :deep(.el-scrollbar__view) {
     display: block;
     height: 100%;
   }
 
   :deep(.el-table__body) {
-    height: 100%;
+    height: auto;
   }
 
   :deep(.el-table__body tbody) {
-    height: 100%;
+    height: auto;
   }
 }
 </style>