Jelajahi Sumber

任务查看文件上传

Zimo 17 jam lalu
induk
melakukan
b712df2716
1 mengubah file dengan 186 tambahan dan 39 penghapusan
  1. 186 39
      src/views/pms/iotprojecttask/IotProjectTaskForm.vue

+ 186 - 39
src/views/pms/iotprojecttask/IotProjectTaskForm.vue

@@ -465,6 +465,62 @@
     </el-form>
   </ContentWrap>
 
+  <div
+    v-if="companyName === 'ry'"
+    class="my-6 bg-white p-4 border-1 border-solid border-[var(--el-border-color-light)]"
+  >
+    <h3 style="margin-bottom: 20px">附件</h3>
+    <el-form-item size="default" label="工程设计">
+      <el-upload
+        v-model:file-list="constructionFiles"
+        :action="uploadUrl"
+        multiple
+        :headers="{ 'tenant-id': 1, 'device-id': 'undefined' }"
+        name="files"
+        class="w-50%"
+      >
+        <el-button type="primary">上传工程设计</el-button>
+        <template #tip>
+          <div class="el-upload__tip">文件大小不能超过50MB </div>
+        </template>
+      </el-upload>
+    </el-form-item>
+    <el-form-item size="default" label="地质设计">
+      <el-upload
+        v-model:file-list="geologicalFiles"
+        :action="uploadUrl"
+        multiple
+        :headers="{ 'tenant-id': 1, 'device-id': 'undefined' }"
+        name="files"
+        class="w-50%"
+      >
+        <el-button type="primary">上传地质设计</el-button>
+        <template #tip>
+          <div class="el-upload__tip">文件大小不能超过50MB </div>
+        </template>
+      </el-upload>
+    </el-form-item>
+    <el-form-item size="default" label="完井报告">
+      <el-upload
+        v-model:file-list="completionFiles"
+        :action="uploadUrl"
+        multiple
+        :headers="{ 'tenant-id': 1, 'device-id': 'undefined' }"
+        name="files"
+        class="w-50%"
+      >
+        <el-button
+          :disabled="!(tableData[0].rigStatus === 'wg' && tableData[0].repairStatus === 'wg')"
+          type="primary"
+          >上传完井报告</el-button
+        >
+        <template #tip>
+          <div class="el-upload__tip">文件大小不能超过50MB </div>
+        </template>
+      </el-upload>
+    </el-form-item>
+  </div>
+
   <ContentWrap v-if="currentTask.platformWell === '1'">
     <h3 style="margin-bottom: 20px">平台井</h3>
     <el-table :data="currentTask.platformWellDetails" style="width: 100%">
@@ -764,19 +820,25 @@ import { IotDeviceApi, IotDeviceVO } from '@/api/pms/device'
 import * as UserApi from '@/api/system/user'
 import { IotProjectTaskAttrsApi } from '@/api/pms/iotprojecttaskattrs'
 import { DICT_TYPE, getStrDictOptions, getDictLabel } from '@/utils/dict'
+import { IotOpeationFillApi } from '@/api/pms/iotopeationfill'
 // 在导入部分添加Plus图标
 // import { Plus } from '@element-plus/icons-vue'
 
 const { query, params, name } = useRoute() // 查询参数
 const id = params.id
 
+const uploadUrl = import.meta.env.VITE_BASE_URL + '/admin-api/rq/file/upload'
+const constructionFiles = ref<any>([])
+const geologicalFiles = ref<any>([])
+const completionFiles = ref<any>([])
+
 // 修改projectId获取逻辑:优先使用params.projectId,其次使用query.projectId
 const projectId = ref<string>('')
 // 获取projectId的逻辑
 if (params.projectId) {
   projectId.value = Array.isArray(params.projectId) ? params.projectId[0] : params.projectId
 } else if (query.projectId) {
-  projectId.value = Array.isArray(query.projectId)
+  projectId.value = Array.isArray(query.projectId as any)
     ? query.projectId[0]
     : (query.projectId as string)
 }
@@ -818,7 +880,7 @@ const submitterList = ref([]) // 所有填报人列表
 const selectedSubmitterIds = ref([]) // 选中的日报填报人ID
 
 // 动态属性相关变量
-const dynamicAttrs = ref([]) // 存储动态属性列表
+const dynamicAttrs = ref<any[]>([]) // 存储动态属性列表
 
 // 跟踪是否已从任务数据中获取动态属性
 const hasDynamicAttrsFromTask = ref(false)
@@ -1805,6 +1867,8 @@ const getAllDeviceNames = (deviceIds: number[]) => {
   return deviceNames.join(', ') || '无有效设备'
 }
 
+const companyName = ref('')
+
 /** 打开弹窗 */
 const open = async () => {
   resetForm()
@@ -1820,6 +1884,9 @@ const open = async () => {
       const data = await IotProjectTaskApi.getIotProjectTaskPage(queryParams)
       tableData.value = data.list
 
+      const company = await IotOpeationFillApi.getOrgName(tableData.value[0].deptId)
+      companyName.value = company
+
       // 收集所有设备ID
       const allDeviceIds = new Set<number>()
       // 收集所有责任人ID
@@ -1968,6 +2035,36 @@ const open = async () => {
             }
           })
         }
+
+        const attachments = tableData.value[0].attachments || []
+
+        constructionFiles.value = attachments
+          .filter((item) => item.type === 'CONSTRUCTION_DESIGN')
+          .map((item) => ({
+            name: item.filename,
+            percentage: 100,
+            response: { data: item },
+            status: 'success',
+            uid: item.createTime
+          }))
+        geologicalFiles.value = attachments
+          .filter((item) => item.type === 'GEOLIGICAL_DESIGN')
+          .map((item) => ({
+            name: item.filename,
+            percentage: 100,
+            response: { data: item },
+            status: 'success',
+            uid: item.createTime
+          }))
+        completionFiles.value = attachments
+          .filter((item) => item.type === 'COMPLETION_DESIGN')
+          .map((item) => ({
+            name: item.filename,
+            percentage: 100,
+            response: { data: item },
+            status: 'success',
+            uid: item.createTime
+          }))
       }
     } finally {
       formLoading.value = false
@@ -2324,6 +2421,46 @@ const submitForm = async () => {
     return
   }
 
+  const getFileType = (filename: string) => {
+    const ext = filename.split('.').pop()?.toLowerCase()
+    if (['jpg', 'jpeg', 'png', 'gif', 'bmp'].includes(ext || '')) {
+      return 'image'
+    } else if (['pdf'].includes(ext || '')) {
+      return 'pdf'
+    } else if (['doc', 'docx'].includes(ext || '')) {
+      return 'word'
+    } else if (['xls', 'xlsx'].includes(ext || '')) {
+      return 'excel'
+    } else {
+      return 'other'
+    }
+  }
+
+  const formatFileSize = (bytes: number) => {
+    if (bytes === 0) return '0 Bytes'
+    const k = 1024
+    const sizes = ['Bytes', 'KB', 'MB', 'GB']
+    const i = Math.floor(Math.log(bytes) / Math.log(k))
+    return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]
+  }
+
+  function formatterAttachments(attachments: any[], type: string, taskId: number) {
+    return attachments.flatMap((item) => {
+      if (item.response.data.files) {
+        return item.response.data.files.map((file) => ({
+          category: 'DAILY_REPORT',
+          bizId: taskId,
+          filename: file.name || '未知文件',
+          fileType: getFileType(file.name),
+          filePath: file.filePath,
+          fileSize: formatFileSize(file.size || 0),
+          remark: '',
+          type
+        }))
+      } else return item.response.data
+    })
+  }
+
   // 处理动态属性数据
   const processedTableData = tableData.value.map((task) => {
     // 获取当前任务的工作量数据并转换为dropdownList格式
@@ -2352,7 +2489,10 @@ const submitForm = async () => {
     return {
       ...task,
       dictType: task.dictType || currentDictLabel.value, // 确保每个任务都有dictType
-      extProperty: extProperties
+      extProperty: extProperties,
+      attachments: formatterAttachments(constructionFiles.value, 'CONSTRUCTION_DESIGN', task.id)
+        .concat(formatterAttachments(geologicalFiles.value, 'GEOLOGICAL_DESIGN', task.id))
+        .concat(formatterAttachments(completionFiles.value, 'COMPLETION_REPORT', task.id))
     }
   })
 
@@ -2366,6 +2506,7 @@ const submitForm = async () => {
     const data = {
       taskList: processedTableData
     }
+
     if (formType.value === 'create') {
       await IotProjectTaskApi.createIotProjectTask(data)
       message.success(t('common.createSuccess'))
@@ -2963,11 +3104,13 @@ onMounted(async () => {
 .edit-input {
   margin-right: 10px;
 }
+
 .error-message {
-  color: #f56c6c;
-  font-size: 12px;
   margin-top: 5px;
+  font-size: 12px;
+  color: #f56c6c;
 }
+
 .action-cell {
   display: flex;
   gap: 8px;
@@ -2975,8 +3118,8 @@ onMounted(async () => {
 
 /* 1. 穿梭框父容器:居中 + 内边距 */
 .transfer-container {
+  padding: 0; /* 上下内边距,避免紧贴对话框边缘 */
   text-align: center;
-  padding: 0px; /* 上下内边距,避免紧贴对话框边缘 */
 }
 
 /* 2. 穿梭框组件:控制宽度,避免过窄或过宽 */
@@ -2993,22 +3136,26 @@ onMounted(async () => {
 /* 3. 深度选择器:修改el-transfer选项样式(解决内容省略问题) */
 :deep(.el-transfer-panel__item) {
   /* white-space: nowrap;  文本不换行,保证一行显示 */
+
   /* overflow: hidden;  超出部分隐藏 */
+
   /* text-overflow: ellipsis;  超出显示省略号 */
+
   /* max-width: 100%;  确保文本不超出选项容器宽度 */
+
   /* padding: 6px 6px;  适当增加内边距,优化点击体验 */
 }
 
 :deep(.el-transfer-panel__item) {
   display: flex !important;
-  align-items: center !important;
   height: 32px !important;
-  line-height: 32px !important;
   padding: 0 8px !important;
   margin: 0 !important;
-  white-space: nowrap;
   overflow: hidden;
+  line-height: 32px !important;
   text-overflow: ellipsis;
+  white-space: nowrap;
+  align-items: center !important;
 }
 
 /* 4. 选项文本:确保继承父容器宽度,省略号正常生效 */
@@ -3019,10 +3166,10 @@ onMounted(async () => {
 
 /* 设备名称显示区域样式 */
 .device-names {
-  white-space: nowrap;
+  max-width: 200px; /* 根据实际列宽调整 */
   overflow: hidden;
   text-overflow: ellipsis;
-  max-width: 200px; /* 根据实际列宽调整 */
+  white-space: nowrap;
 }
 
 :deep(.el-transfer-panel__list) {
@@ -3031,35 +3178,35 @@ onMounted(async () => {
 
 /* 责任人名称显示区域样式 */
 .responsible-names {
-  white-space: nowrap;
+  max-width: 200px; /* 根据实际列宽调整 */
   overflow: hidden;
   text-overflow: ellipsis;
-  max-width: 200px; /* 根据实际列宽调整 */
+  white-space: nowrap;
 }
 
 /* 添加部门名称的样式 */
 .dept-names {
-  white-space: nowrap;
+  display: inline-block;
+  max-width: 200px; /* 根据实际列宽调整 */
   overflow: hidden;
   text-overflow: ellipsis;
-  max-width: 200px; /* 根据实际列宽调整 */
-  display: inline-block;
+  white-space: nowrap;
   vertical-align: bottom;
 }
 
 /* 部门选择器样式优化 */
 :deep(.department-tree-select .el-select__tags) {
-  white-space: nowrap;
   overflow: hidden;
   text-overflow: ellipsis;
+  white-space: nowrap;
   flex-wrap: nowrap;
 }
 
 :deep(.department-tree-select .el-select__tags .el-tag) {
+  display: inline-block;
   max-width: 120px;
   overflow: hidden;
   text-overflow: ellipsis;
-  display: inline-block;
 }
 
 :deep(.department-tree-select .el-select__tags .el-tag + .el-tag) {
@@ -3075,29 +3222,29 @@ onMounted(async () => {
 
 /* 当有多个标签被折叠时显示的 "+N" 标签样式 */
 :deep(.department-tree-select .el-select__collapse-tags) {
-  white-space: nowrap;
   display: inline-block;
+  white-space: nowrap;
 }
 
 .task-edit-form {
-  margin-bottom: 20px;
   padding: 20px;
+  margin-bottom: 20px;
+  background-color: #fafafa;
   border: 1px solid #ebeef5;
   border-radius: 4px;
-  background-color: #fafafa;
 }
 
 /* 按钮文字样式 - 红色字体 */
 :deep(.workload-add-btn .btn-text) {
-  color: #ff0000 !important;
-  font-weight: 900; /* 更粗的字体 */
   font-size: 18px; /* 更大的字号 */
+  font-weight: 900; /* 更粗的字体 */
   line-height: 1;
+  color: #f00 !important;
 }
 
 /* 设计工作量加号按钮 - 启用状态(深蓝色) */
 :deep(.workload-add-btn .el-icon) {
-  color: #ff0000 !important; /* Element Plus 主色调深蓝色,可替换为 #003366 等自定义深蓝色 */
+  color: #f00 !important; /* Element Plus 主色调深蓝色,可替换为 #003366 等自定义深蓝色 */
 }
 
 /* 按钮禁用状态 */
@@ -3108,53 +3255,53 @@ onMounted(async () => {
 /* 调整按钮整体样式,确保icon居中 */
 :deep(.workload-add-btn) {
   display: flex;
-  align-items: center;
-  justify-content: center;
-  padding: 0 8px;
-  min-width: auto;
   width: 100%;
   height: 100%;
+  min-width: auto;
+  padding: 0 8px;
+  align-items: center;
+  justify-content: center;
 }
 
 /* 调整输入框append部分的宽度 */
 :deep(.workload-input-with-button .el-input-group__append) {
-  padding: 0;
   width: 45px; /* 稍微增加宽度以容纳文字 */
+  padding: 0;
 }
 
 /* 确保按钮在禁用状态下有正确的样式 */
 :deep(.workload-add-btn:disabled) {
+  cursor: not-allowed;
   background-color: #f5f7fa;
   border-color: #e4e7ed;
-  cursor: not-allowed;
 }
 
 /* 设计工作量错误输入框样式 */
 :deep(.error-input .el-input__inner) {
-  border-color: #f56c6c !important;
   background-color: #fef0f0 !important;
-  box-shadow: 0 0 0 1px rgba(245, 108, 108, 0.4) !important;
+  border-color: #f56c6c !important;
+  box-shadow: 0 0 0 1px rgb(245 108 108 / 40%) !important;
 }
 
 :deep(.error-input .el-input__inner:hover) {
-  border-color: #f56c6c !important;
   background-color: #fef0f0 !important;
+  border-color: #f56c6c !important;
 }
 
 :deep(.error-input .el-input__inner:focus) {
-  border-color: #f56c6c !important;
   background-color: #fef0f0 !important;
-  box-shadow: 0 0 0 1px rgba(245, 108, 108, 0.2) !important;
+  border-color: #f56c6c !important;
+  box-shadow: 0 0 0 1px rgb(245 108 108 / 20%) !important;
 }
 
 /* 设计工作量tooltip样式 */
 :deep(.workload-design-tooltip) {
-  background: #fef0f0 !important;
-  border: 1px solid #fbc4c4 !important;
-  color: #f56c6c !important;
   max-width: 300px;
-  font-size: 12px;
   padding: 8px 12px;
+  font-size: 12px;
+  color: #f56c6c !important;
+  background: #fef0f0 !important;
+  border: 1px solid #fbc4c4 !important;
 }
 
 /* 隐藏 Tooltip 箭头 */