Przeglądaj źródła

批量管理的逻辑优化

zmj 1 miesiąc temu
rodzic
commit
4906ebe304
2 zmienionych plików z 253 dodań i 55 usunięć
  1. 9 0
      src/api/base/report.js
  2. 244 55
      src/views/base/batch/index.vue

+ 9 - 0
src/api/base/report.js

@@ -26,6 +26,15 @@ export function addReport(data) {
   })
 }
 
+// 批量新增检测报告
+export function batchAddReport(data) {
+  return request({
+    url: '/base/report/batchAdd',
+    method: 'post',
+    data: data
+  })
+}
+
 // 修改检测报告
 export function updateReport(data) {
   return request({

+ 244 - 55
src/views/base/batch/index.vue

@@ -238,7 +238,7 @@
         </template>
       </el-table-column>
     </el-table>
-    
+
     <pagination
       v-show="total>0"
       :total="total"
@@ -549,14 +549,14 @@
       </div>
     </el-dialog>
 
-  
+
   </div>
 </template>
 
 <script>
 import { listBatch, getBatch, delBatch, addBatch, updateBatch } from "@/api/base/batch"
 import QRCode from 'qrcode'
-import { listReport, getReport, addReport, updateReport } from "@/api/base/report"
+import { listReport, getReport, addReport, updateReport,batchAddReport,delReport } from "@/api/base/report"
 import { listCertificate, getCertificate, addCertificate, updateCertificate } from "@/api/base/certificate"
 
 
@@ -853,7 +853,7 @@ export default {
       try {
         // 动态导入 html2canvas
         const html2canvas = (await import('html2canvas')).default
-        
+
         // 将整个卡片转换为图片
         const canvas = await html2canvas(cardElement, {
           backgroundColor: '#ffffff',
@@ -861,14 +861,14 @@ export default {
           useCORS: true,
           logging: false
         })
-        
+
         // 转为图片并下载
         const imgUrl = canvas.toDataURL('image/png')
         const link = document.createElement('a')
         link.download = `溯源卡片_${this.qrData.batchNo}.png`
         link.href = imgUrl
         link.click()
-        
+
         this.$message.success('下载成功')
       } catch (error) {
         console.error('下载失败:', error)
@@ -901,7 +901,7 @@ export default {
             certStatus: cert.certStatus,
             certFiles: []
           }
-          
+
           // 解析 certFiles 字段(JSON 数组)
           if (cert.certFiles) {
             try {
@@ -927,7 +927,7 @@ export default {
               this.certForm.certFiles = []
             }
           }
-          
+
           this.certTitle = "编辑合格证"
         }
       })
@@ -952,7 +952,7 @@ export default {
       }
       this.resetForm("certForm")
     },
-    /** 提交合格证表单 */
+
     /** 提交合格证表单 */
     submitCertForm() {
       this.$refs["certForm"].validate(valid => {
@@ -1060,8 +1060,9 @@ export default {
       })
     },
 
+
     /** 打开上传检测报告弹窗 */
-    handleUploadReport(row) {
+     handleUploadReport(row) {
       this.resetReport()
       this.reportForm.batchId = row.id
       this.reportForm.batchNo = row.batchNo
@@ -1070,12 +1071,60 @@ export default {
       this.reportVisible = true
       this.reportTitle = "上传检测报告"
 
-      // TODO: 查询该批次是否已有检测报告数据
-      // listReport({ batchId: row.id }).then(response => {
-      //   if (response.rows && response.rows.length > 0) {
-      //     // 已有检测报告,设置为编辑模式
-      //   }
-      // })
+      // 查询该批次是否已有检测报告数据
+      listReport({ batchId: row.id }).then(response => {
+        if (response.rows && response.rows.length > 0) {
+          // 已有检测报告,设置为编辑模式
+          this.reportTitle = "编辑检测报告"
+
+          // 将已有数据填充到 reportItems 中
+          const reportItems = []
+          response.rows.forEach(report => {
+            // 解析 reportFiles 字段(注意:后端返回的是 reportFiles,不是 reportFile)
+            let reportFileValue = []
+
+            // 使用 reportFiles 字段(从响应数据看,字段名是 reportFiles)
+            const fileUrl = report.reportFiles
+
+            if (fileUrl) {
+              try {
+                // 尝试解析为 JSON 数组
+                const parsed = JSON.parse(fileUrl)
+                if (Array.isArray(parsed)) {
+                  // 如果是 JSON 数组
+                  reportFileValue = parsed.map(file => {
+                    return typeof file === 'string'
+                      ? { url: file, name: file.split('/').pop() || file }
+                      : file
+                  })
+                } else {
+                  // 单个对象
+                  const url = typeof parsed === 'string' ? parsed : parsed.url
+                  reportFileValue = [{
+                    url: url,
+                    name: url.split('/').pop() || url
+                  }]
+                }
+              } catch (e) {
+                // 不是 JSON,直接当作 URL 字符串处理
+                reportFileValue = [{
+                  url: fileUrl,
+                  name: fileUrl.split('/').pop() || fileUrl
+                }]
+              }
+            }
+
+            reportItems.push({
+              id: report.id,
+              reportNo: report.reportNo,
+              reportDate: report.reportDate,
+              reportFile: reportFileValue
+            })
+          })
+
+          this.reportForm.reportItems = reportItems
+        }
+      })
     },
 
     /** 取消检测报告 */
@@ -1111,25 +1160,68 @@ export default {
       })
     },
 
+
     /** 删除一条检测报告 */
     removeReportItem(index) {
-      if (this.reportForm.reportItems.length === 1) {
-        this.$message.warning("至少保留一条检测报告")
-        return
+      const item = this.reportForm.reportItems[index]
+
+      // 如果是已有数据(有 id),需要调用后端删除接口
+      if (item.id) {
+        this.$modal.confirm(`是否确认删除第 ${index + 1} 条检测报告?删除后不可恢复!`).then(() => {
+          const loading = this.$modal.loading("正在删除检测报告,请稍候...")
+
+          delReport(item.id)
+            .then(response => {
+              this.$modal.closeLoading()
+              this.$modal.msgSuccess("删除成功")
+              // 从数组中移除
+              this.reportForm.reportItems.splice(index, 1)
+
+              // 如果删除后数组为空,添加一个空项
+              if (this.reportForm.reportItems.length === 0) {
+                this.addReportItem()
+              }
+            })
+            .catch(error => {
+              this.$modal.closeLoading()
+              console.error('删除失败:', error)
+              this.$message.error("删除失败,请重试")
+            })
+        }).catch(() => {
+          // 用户取消删除
+        })
+      } else {
+        // 如果是新增数据(没有 id),直接从前端移除
+        this.$modal.confirm(`是否确认删除第 ${index + 1} 条检测报告?`).then(() => {
+          this.reportForm.reportItems.splice(index, 1)
+
+          // 如果删除后数组为空,添加一个空项
+          if (this.reportForm.reportItems.length === 0) {
+            this.addReportItem()
+          }
+
+          this.$modal.msgSuccess("删除成功")
+        }).catch(() => {
+          // 用户取消删除
+        })
       }
-      this.reportForm.reportItems.splice(index, 1)
     },
 
-    /** 提交检测报告表单 */
+       /** 提交检测报告表单 */
     submitReportForm() {
       // 校验整个报告表单
       this.$refs["reportFormRef"].validate(valid => {
         if (valid) {
-          // 校验每条报告项 - file-upload 组件返回逗号分隔的字符串
+          // 校验每条报告项
           const hasEmptyItem = this.reportForm.reportItems.some(item => {
-            // 报告编号和检测日期是字符串,直接判断非空
-            // reportFile 是上传组件返回的字符串,上传后会有值(如 "url1,url2")
-            const isReportFileEmpty = !item.reportFile || item.reportFile.trim() === ""
+            let isReportFileEmpty = true
+
+            if (Array.isArray(item.reportFile)) {
+              isReportFileEmpty = item.reportFile.length === 0
+            } else if (typeof item.reportFile === 'string') {
+              isReportFileEmpty = !item.reportFile || item.reportFile.trim() === ""
+            }
+
             return !item.reportNo || !item.reportDate || isReportFileEmpty
           })
 
@@ -1140,44 +1232,141 @@ export default {
 
           // 前端兜底校验:检查文件类型和大小
           const allowedTypes = ['jpg', 'jpeg', 'png', 'pdf']
-          const maxSize = 2 * 1024 * 1024 // 2MB
 
           for (let i = 0; i < this.reportForm.reportItems.length; i++) {
             const item = this.reportForm.reportItems[i]
-            const files = item.reportFile
-
-            // 如果有上传文件,进行兜底校验
-            if (files && files.trim()) {
-              const fileUrls = files.split(',')
-              for (const fileUrl of fileUrls) {
-                const trimmedUrl = fileUrl.trim()
-                if (!trimmedUrl) continue
-
-                // 获取文件扩展名(小写)
-                const ext = trimmedUrl.split('.').pop().toLowerCase()
-
-                // 检查文件类型
-                if (!allowedTypes.includes(ext)) {
-                  this.$message.warning(`第 ${i + 1} 条检测报告的文件格式不正确,仅支持 jpg/jpeg/png/pdf 格式`)
-                  return
-                }
+            let fileUrls = []
+
+            if (Array.isArray(item.reportFile)) {
+              fileUrls = item.reportFile.map(file => typeof file === 'string' ? file : file.url)
+            } else if (typeof item.reportFile === 'string') {
+              fileUrls = item.reportFile.split(',').map(url => url.trim())
+            }
 
-                // 注意:这里无法直接获取文件大小进行校验
-                // 文件大小由上传组件在上传前进行限制
-                // 此处只能通过文件扩展名进行类型兜底校验
+            for (const fileUrl of fileUrls) {
+              const trimmedUrl = fileUrl || ''
+              if (!trimmedUrl) continue
+
+              const ext = trimmedUrl.split('.').pop().toLowerCase()
+              if (!allowedTypes.includes(ext)) {
+                this.$message.warning(`第 ${i + 1} 条检测报告的文件格式不正确,仅支持 jpg/jpeg/png/pdf 格式`)
+                return
               }
             }
           }
 
-          // 前端校验通过,打印数据
-          console.log("检测报告表单数据:", this.reportForm)
-          this.$message.success("前端校验通过,待接接口")
+          // 前端校验通过,准备提交数据
+          // 将 reportItems 转换为后端需要的格式
+          const reportItemsData = this.reportForm.reportItems.map(item => {
+            // 处理 reportFile:转为单个 URL(取第一个)
+            let reportFileUrl = ""
+
+            if (Array.isArray(item.reportFile) && item.reportFile.length > 0) {
+              const firstFile = item.reportFile[0]
+              reportFileUrl = typeof firstFile === 'string' ? firstFile : (firstFile.url || "")
+            } else if (typeof item.reportFile === 'string' && item.reportFile.trim()) {
+              const urls = item.reportFile.split(',').map(url => url.trim())
+              reportFileUrl = urls[0] || ""
+            }
+
+            // 构建报告项数据(使用 reportFiles 作为 key)
+            const reportData = {
+              reportNo: item.reportNo,
+              reportDate: item.reportDate,
+              reportFiles: reportFileUrl
+            }
 
-          // TODO: 接接口时的提交逻辑
-          // const data = {
-          //   batchId: this.reportForm.batchId,
-          //   reportItems: this.reportForm.reportItems
-          // }
+            if (item.id) {
+              reportData.id = item.id
+            }
+
+            return reportData
+          })
+
+          // 打印调试信息(查看提交的数据是否正确)
+          console.log('=== 提交检测报告数据 ===')
+          console.log('reportItemsData:', reportItemsData)
+          console.log('当前 reportForm.reportItems:', this.reportForm.reportItems)
+
+          // 判断操作类型
+          const hasExistingItems = this.reportForm.reportItems.some(item => item.id)
+          const hasNewItems = this.reportForm.reportItems.some(item => !item.id)
+
+          const loading = this.$modal.loading("正在保存检测报告,请稍候...")
+
+          // 情况 1:如果所有项都是新增的(没有 id),使用批量新增接口
+          if (hasNewItems && !hasExistingItems) {
+            const batchData = {
+              batchId: this.reportForm.batchId,
+              batchNo: this.reportForm.batchNo,
+              productName: this.reportForm.productName,
+              farmName: this.reportForm.farmName,
+              reportItems: reportItemsData
+            }
+
+            console.log('批量新增数据:', batchData)
+
+            batchAddReport(batchData)
+              .then(response => {
+                this.$modal.closeLoading()
+                this.$modal.msgSuccess("上传成功")
+                this.reportVisible = false
+                this.resetReport()
+              })
+              .catch(error => {
+                this.$modal.closeLoading()
+                console.error('上传失败:', error)
+                this.$message.error("上传失败,请重试")
+              })
+
+          // 情况 2:如果有已有数据(有 id),需要逐条处理(新增或修改)
+          } else {
+            // 分离新增和修改的数据
+            const newItems = reportItemsData.filter(item => !item.id)
+            const updateItems = reportItemsData.filter(item => item.id)
+
+            const promises = []
+
+            // 处理新增数据
+            if (newItems.length > 0) {
+              const newBatchData = {
+                batchId: this.reportForm.batchId,
+                batchNo: this.reportForm.batchNo,
+                productName: this.reportForm.productName,
+                farmName: this.reportForm.farmName,
+                reportItems: newItems
+              }
+              console.log('批量新增数据:', newBatchData)
+              promises.push(batchAddReport(newBatchData))
+            }
+
+            // 处理修改数据(逐条调用更新接口)
+            updateItems.forEach(item => {
+              const updateData = {
+                id: item.id,
+                batchId: this.reportForm.batchId,
+                reportNo: item.reportNo,
+                reportDate: item.reportDate,
+                reportFiles: item.reportFiles
+              }
+              console.log('更新数据:', updateData)
+              promises.push(updateReport(updateData))
+            })
+
+            // 等待所有请求完成
+            Promise.all(promises)
+              .then(() => {
+                this.$modal.closeLoading()
+                this.$modal.msgSuccess("保存成功")
+                this.reportVisible = false
+                this.resetReport()
+              })
+              .catch(error => {
+                this.$modal.closeLoading()
+                console.error('保存失败:', error)
+                this.$message.error("保存失败,请重试")
+              })
+          }
         }
       })
     },
@@ -1485,4 +1674,4 @@ export default {
   width: 100%;
   border-style: dashed;
 }
-</style>
+</style>