yanghao 5 dagen geleden
bovenliggende
commit
ca9fb383ae

+ 19 - 6
src/views/pms/qhse/certificate.vue

@@ -293,7 +293,18 @@
 
   <!-- 查看证书图片对话框 -->
   <el-dialog :title="imageDialogTitle" v-model="imageDialogVisible" width="800px" center>
-    <img :src="imagePreviewUrl" alt="证书图片" style="max-width: 100%; max-height: 80vh" />
+    <!-- <img :src="imagePreviewUrl" alt="证书图片" style="max-width: 100%; max-height: 80vh" /> -->
+    <div
+      style="display: flex; justify-content: center; align-items: center; flex-direction: column"
+    >
+      <img
+        v-for="url in imagePreviewUrl"
+        :src="url"
+        :key="url"
+        alt="证书图片"
+        style="max-width: 100%"
+      />
+    </div>
   </el-dialog>
 </template>
 
@@ -306,7 +317,7 @@ import { ElMessageBox, ElMessage } from 'element-plus'
 const deptList = ref<Tree[]>([]) // 树形结构
 const deptList2 = ref<Tree[]>([]) // 树形结构
 import { formatDate } from '@/utils/formatTime'
-import UploadImage from '@/components/UploadFile/src/UploadImg.vue'
+import UploadImage from '@/components/UploadFile/src/UploadImgs.vue'
 import { DICT_TYPE, getStrDictOptions, getBoolDictOptions } from '@/utils/dict'
 import { defaultProps } from '@/utils/tree'
 import { selectedDeptsEmployee } from '@/api/system/user'
@@ -474,15 +485,16 @@ const handleEdit = (row) => {
     ...row,
     // 确保日期字段正确处理
     issueDate: row.issueDate ? ensureMillisecondTimestamp(row.issueDate) : null,
-    validityPeriod: row.validityPeriod ? ensureMillisecondTimestamp(row.validityPeriod) : null
+    validityPeriod: row.validityPeriod ? ensureMillisecondTimestamp(row.validityPeriod) : null,
+    certPic: row.certPic.split(',')
   }
 
   dialogVisible.value = true
 }
 
 // 查看证书图片
-const handleViewImage = (imageUrl: string) => {
-  imagePreviewUrl.value = imageUrl
+const handleViewImage = (imageUrl: any) => {
+  imagePreviewUrl.value = imageUrl.split(',')
   imageDialogTitle.value = '证书图片'
   imageDialogVisible.value = true
 }
@@ -562,7 +574,8 @@ const submitForm = async () => {
       ...formData.value,
       // 确保日期字段以正确的格式提交
       certIssue: formData.value.certIssue,
-      certExpire: formData.value.certExpire
+      certExpire: formData.value.certExpire,
+      certPic: formData.value.certPic ? formData.value.certPic.join(',') : '' // 将图片数组转换为逗号分隔的字符串
     }
 
     if (isEdit.value) {

+ 19 - 19
src/views/pms/qhse/iotmeasuredetect/IotMeasureDetectForm.vue

@@ -76,22 +76,6 @@
             <el-input v-model="formData.detectAmount" placeholder="请输入校准金额" />
           </el-form-item>
         </el-col>
-
-        <!-- <el-col :span="12">
-          <el-form-item label="部门" prop="deptId">
-            <el-tree-select
-              style="width: 100%"
-              clearable
-              v-model="formData.deptId"
-              :data="deptList2"
-              :props="defaultProps"
-              check-strictly
-              node-key="id"
-              filterable
-              placeholder="请选择所在部门"
-            />
-          </el-form-item>
-        </el-col> -->
       </el-row>
 
       <el-row :gutter="20">
@@ -101,6 +85,20 @@
           </el-form-item>
         </el-col>
       </el-row>
+
+      <el-row :gutter="20">
+        <el-col :span="24">
+          <el-form-item label="附件" prop="file">
+            <UploadFile
+              v-model="formData.file"
+              :file-type="['doc', 'docx', 'pdf', 'jpg', 'png', 'jpeg', 'xls', 'xlsx']"
+              :limit="3"
+              :file-size="100"
+              class="min-w-80px"
+            />
+          </el-form-item>
+        </el-col>
+      </el-row>
     </el-form>
 
     <template #footer>
@@ -212,7 +210,6 @@ defineOptions({ name: 'IotMeasureDetectForm' })
 const { t } = useI18n() // 国际化
 const message = useMessage() // 消息弹窗
 const deptList2 = ref<Tree[]>([]) // 树形结构
-import { defaultProps } from '@/utils/tree'
 
 const dialogVisible = ref(false) // 弹窗的是否展示
 const dialogTitle = ref('') // 弹窗的标题
@@ -228,9 +225,11 @@ const formData = ref({
   deptId: undefined,
   measureName: '',
   measureId: '',
-  measureCertNo: ''
+  measureCertNo: '',
+  file: ''
 })
 const formRules = reactive({
+  measureId: [{ required: true, message: '计量器具不能为空', trigger: 'blur' }],
   detectDate: [{ required: true, message: '检测/校准日期不能为空', trigger: 'blur' }],
   detectOrg: [{ required: true, message: '检测/校准机构不能为空', trigger: 'blur' }],
   detectContent: [{ required: true, message: '检测/校准内容不能为空', trigger: 'blur' }],
@@ -323,7 +322,8 @@ const resetForm = () => {
     measureName: '',
     measureId: '',
     measureCertNo: '',
-    detectStandard: undefined
+    detectStandard: undefined,
+    file: ''
   }
   formRef.value?.resetFields()
 }

+ 90 - 0
src/views/pms/qhse/iotmeasuredetect/index.vue

@@ -103,6 +103,18 @@
           </el-table-column>
           <el-table-column label="校准金额" align="center" prop="detectAmount" width="120" />
           <el-table-column label="部门名称" align="center" prop="deptName" min-width="140" />
+          <el-table-column label="附件" align="center" prop="file" min-width="90">
+            <template #default="scope">
+              <el-button
+                v-if="scope.row.file"
+                link
+                type="primary"
+                @click="viewFile(scope.row.file)"
+              >
+                查看
+              </el-button>
+            </template>
+          </el-table-column>
           <el-table-column label="操作" align="center" width="140" fixed="right">
             <template #default="scope">
               <el-button link type="primary" @click="openForm('update', scope.row.id)">
@@ -124,6 +136,30 @@
     </el-col>
   </el-row>
 
+  <el-dialog v-model="dialogFileView" title="附件" width="500">
+    <div
+      v-for="(file, index) in fileList"
+      :key="index"
+      class="flex items-center justify-between mt-5"
+    >
+      <span class="file-name-text">{{ extractFileName(file) }}</span>
+      <div>
+        <el-button link type="primary" @click="viewFileInfo(file)">
+          <Icon icon="ep:view" class="mr-2px" />查看</el-button
+        >
+        <el-button link type="primary" @click="handleDownload(file)">
+          <Icon icon="ep:download" class="mr-2px" />下载</el-button
+        >
+      </div>
+    </div>
+
+    <template #footer>
+      <div class="dialog-footer mt-10">
+        <el-button type="primary" @click="dialogFileView = false"> 确认 </el-button>
+      </div>
+    </template>
+  </el-dialog>
+
   <!-- 表单弹窗:添加/修改 -->
   <IotMeasureDetectForm ref="formRef" @success="getList" />
 </template>
@@ -252,6 +288,51 @@ const handleExport = async () => {
   }
 }
 
+let dialogFileView = ref(false)
+let fileList = ref([])
+const viewFile = (file) => {
+  fileList.value = file.split(',')
+  dialogFileView.value = true
+  // window.open(file)
+}
+
+const viewFileInfo = (file) => {
+  window.open(
+    'http://doc.deepoil.cc:8012/onlinePreview?url=' + encodeURIComponent(Base64.encode(file))
+  )
+}
+
+const extractFileName = (url: string): string => {
+  try {
+    // 移除查询参数和哈希
+    const cleanUrl = url.split('?')[0].split('#')[0]
+    // 获取最后一个斜杠后的内容
+    const parts = cleanUrl.split('/')
+    const fileName = parts[parts.length - 1]
+    // URL 解码
+    return decodeURIComponent(fileName) || url
+  } catch {
+    // 如果解析失败,返回原始 URL
+    return url
+  }
+}
+
+const handleDownload = async (url) => {
+  try {
+    const response = await fetch(url)
+    const blob = await response.blob()
+    const downloadUrl = window.URL.createObjectURL(blob)
+
+    const link = document.createElement('a')
+    link.href = downloadUrl
+    link.download = url.split('/').pop() // 自动获取文件名‌:ml-citation{ref="3" data="citationList"}
+    link.click()
+
+    URL.revokeObjectURL(downloadUrl)
+  } catch (error) {
+    console.error('下载失败:', error)
+  }
+}
 /** 初始化 **/
 onMounted(() => {
   getList()
@@ -265,4 +346,13 @@ onMounted(() => {
 ::deep(.el-transfer-panel__body) {
   height: 700px !important;
 }
+
+.file-name-text {
+  flex: 1;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+  margin-right: 12px;
+  color: var(--el-text-color-primary);
+}
 </style>

+ 68 - 25
src/views/pms/qhse/safety/index.vue

@@ -71,7 +71,7 @@
                 :underline="false"
                 type="primary"
                 size="small"
-                @click="viewHazardFile(row.hazardFile)"
+                @click="viewFile(row.hazardFile)"
                 >查看</el-link
               >
               <span v-else>-</span>
@@ -87,7 +87,7 @@
                 :underline="false"
                 type="primary"
                 size="small"
-                @click="viewRectifyFile(row.rectifyFile)"
+                @click="viewFile(row.rectifyFile)"
                 >查看</el-link
               >
               <span v-else>-</span>
@@ -243,6 +243,30 @@
     </template>
   </el-dialog>
 
+  <el-dialog v-model="dialogFileView" title="附件" width="500">
+    <div
+      v-for="(file, index) in fileList"
+      :key="index"
+      class="flex items-center justify-between mt-5"
+    >
+      <span class="file-name-text">{{ extractFileName(file) }}</span>
+      <div>
+        <el-button link type="primary" @click="viewFileInfo(file)">
+          <Icon icon="ep:view" class="mr-2px" />查看</el-button
+        >
+        <el-button link type="primary" @click="handleDownload(file)">
+          <Icon icon="ep:download" class="mr-2px" />下载</el-button
+        >
+      </div>
+    </div>
+
+    <template #footer>
+      <div class="dialog-footer mt-10">
+        <el-button type="primary" @click="dialogFileView = false"> 确认 </el-button>
+      </div>
+    </template>
+  </el-dialog>
+
   <FilePreviewDialog
     v-model="filePreviewVisible"
     :title="filePreviewTitle"
@@ -535,31 +559,21 @@ const submitFix = async () => {
 }
 
 // 下载文件函数
-const downloadFile = (response: any) => {
-  const blob = new Blob([response], {
-    type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8'
-  })
-
-  let fileName = '隐患排查.xlsx'
-  const disposition = response.headers ? response.headers['content-disposition'] : ''
-  if (disposition) {
-    const filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/
-    const matches = filenameRegex.exec(disposition)
-    if (matches != null && matches[1]) {
-      fileName = matches[1].replace(/['"]/g, '')
-    }
-  }
-
-  const url = window.URL.createObjectURL(blob)
-  const link = document.createElement('a')
-  link.href = url
-  link.setAttribute('download', fileName)
+const handleDownload = async (url) => {
+  try {
+    const response = await fetch(url)
+    const blob = await response.blob()
+    const downloadUrl = window.URL.createObjectURL(blob)
 
-  document.body.appendChild(link)
-  link.click()
+    const link = document.createElement('a')
+    link.href = downloadUrl
+    link.download = url.split('/').pop() // 自动获取文件名‌:ml-citation{ref="3" data="citationList"}
+    link.click()
 
-  document.body.removeChild(link)
-  window.URL.revokeObjectURL(url)
+    URL.revokeObjectURL(downloadUrl)
+  } catch (error) {
+    console.error('下载失败:', error)
+  }
 }
 
 let userList = ref([])
@@ -572,6 +586,35 @@ const handleDeptChange = async (value) => {
   console.log('value>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>', userList.value)
 }
 
+let dialogFileView = ref(false)
+let fileList = ref([])
+const viewFile = (file) => {
+  fileList.value = file.split(',')
+  dialogFileView.value = true
+  // window.open(file)
+}
+
+const viewFileInfo = (file) => {
+  window.open(
+    'http://doc.deepoil.cc:8012/onlinePreview?url=' + encodeURIComponent(Base64.encode(file))
+  )
+}
+
+const extractFileName = (url: string): string => {
+  try {
+    // 移除查询参数和哈希
+    const cleanUrl = url.split('?')[0].split('#')[0]
+    // 获取最后一个斜杠后的内容
+    const parts = cleanUrl.split('/')
+    const fileName = parts[parts.length - 1]
+    // URL 解码
+    return decodeURIComponent(fileName) || url
+  } catch {
+    // 如果解析失败,返回原始 URL
+    return url
+  }
+}
+
 onMounted(async () => {
   getList()
   deptList2.value = handleTree(await DeptApi.getSimpleDeptList())