Просмотр исходного кода

检测录入初步完成插入图片功能

yangguanjin 4 дней назад
Родитель
Сommit
4f4760ab8d

+ 123 - 0
src/components/SpreadDesigner/spreadDesigner.vue

@@ -612,6 +612,7 @@ function getImages(designerInstance) {
           continue
         }
         images.push({
+          shapeName: shape.name(),
           sheetName: sheet.name(),
           imgX: shape.x(),
           imgY: shape.y(),
@@ -1152,6 +1153,127 @@ function openCamera() {
   emit('openCamera')
 }
 
+function getPictureSource(photoData) {
+  if (!photoData?.base64) return ''
+  if (photoData.base64.startsWith('data:')) return photoData.base64
+  return `data:${photoData.type || 'image/jpeg'};base64,${photoData.base64}`
+}
+
+function getCellRangeOffset(sheet, row, col) {
+  let x = 0
+  let y = 0
+  for (let c = 0; c < col; c++) {
+    x += sheet.getColumnWidth(c)
+  }
+  for (let r = 0; r < row; r++) {
+    y += sheet.getRowHeight(r)
+  }
+  return { x, y }
+}
+
+function getCellRangeSize(sheet, row, col, rowCount, colCount) {
+  let width = 0
+  let height = 0
+  for (let c = 0; c < colCount; c++) {
+    width += sheet.getColumnWidth(col + c)
+  }
+  for (let r = 0; r < rowCount; r++) {
+    height += sheet.getRowHeight(row + r)
+  }
+  return { width, height }
+}
+
+function getTargetPictureCell() {
+  if (!designer.value) return null
+  const spreadInstance = designer.value.getWorkbook()
+  const sheet = currentCell.value?.sheet || spreadInstance.getActiveSheet()
+  let row = currentCell.value?.row
+  let col = currentCell.value?.col
+
+  if ((row === null || row === undefined || col === null || col === undefined) && sheet) {
+    row = sheet.getActiveRowIndex?.()
+    col = sheet.getActiveColumnIndex?.()
+  }
+
+  if ((row === null || row === undefined || col === null || col === undefined) && sheet) {
+    const selection = sheet.getSelections?.()?.[0]
+    row = selection?.row
+    col = selection?.col
+  }
+
+  if (row === null || row === undefined || col === null || col === undefined || row < 0 || col < 0) {
+    return null
+  }
+
+  return { sheet, row, col }
+}
+
+function handleTakePhotoData(photoData) {
+  console.log("处理图片。。。。。")
+  const targetCell = getTargetPictureCell()
+  if (!targetCell) {
+    showDialog('请先选择需要插入图片的单元格')
+    return false
+  }
+
+  const pictureSource = getPictureSource(photoData)
+  if (!pictureSource) {
+    showDialog('图片数据为空')
+    return false
+  }
+
+  try {
+    const { sheet, row, col } = targetCell
+    const targetRange = getMergedCellRange(sheet, row, col) || {
+      row,
+      col,
+      rowCount: 1,
+      colCount: 1,
+    }
+    const { x, y } = getCellRangeOffset(sheet, targetRange.row, targetRange.col)
+    const { width, height } = getCellRangeSize(
+      sheet,
+      targetRange.row,
+      targetRange.col,
+      targetRange.rowCount,
+      targetRange.colCount,
+    )
+    const pictureName = `addPicture_${targetRange.row}_${targetRange.col}_${Date.now()}`
+    const maxPictureWidth = Math.max(width * 0.72, 1)
+    const maxPictureHeight = Math.max(height * 0.72, 1)
+    const sourceWidth = Number(photoData.width) || maxPictureWidth
+    const sourceHeight = Number(photoData.height) || maxPictureHeight
+    const scale = Math.min(maxPictureWidth / sourceWidth, maxPictureHeight / sourceHeight)
+    const pictureWidth = Math.max(sourceWidth * scale, 1)
+    const pictureHeight = Math.max(sourceHeight * scale, 1)
+    const pictureX = x + (width - pictureWidth) / 2
+    const pictureY = y + (height - pictureHeight) / 2
+    const picture = sheet.shapes.addPictureShape(
+      pictureName,
+      pictureSource,
+      pictureX,
+      pictureY,
+      pictureWidth,
+      pictureHeight,
+    )
+
+    picture.startRow?.(targetRange.row)
+    picture.startColumn?.(targetRange.col)
+    picture.endRow?.(targetRange.row + targetRange.rowCount - 1)
+    picture.endColumn?.(targetRange.col + targetRange.colCount - 1)
+    picture.allowMove?.(true)
+    picture.allowResize?.(true)
+
+    sheet.repaint?.()
+    showDialog('图片已插入')
+    return true
+  } catch (error) {
+    console.error('插入图片失败:', error)
+    showDialog('插入图片失败')
+    return false
+  }
+}
+
 async function renderFeeTemplateAndReturnData(blob, bindingPathSchema, equipTemplateList) {
   if (!designer.value) return
   const spreadInstance = designer.value.getWorkbook()
@@ -1282,6 +1404,7 @@ defineExpose({
   onWebViewResize,
   updateCheckItemData,
   handleCameraResult,
+  handleTakePhotoData,
   setKeyboardHeight,
   renderFeeTemplateAndReturnData,
   signleRenderFeeTemplateAndReturnData,

+ 80 - 1
src/pages/editor/equipCheckRecordEditor.vue

@@ -33,7 +33,7 @@ import { ref, onUnmounted } from 'vue'
 import SpreadDesigner from '@/components/SpreadDesigner/spreadDesigner.vue'
 import { onLoad } from '@dcloudio/uni-app'
 import { getCheckerEquipmentDetailById, getDynamicTbVal, saveDynamicTbVal } from '@/api/task'
-import { getStandardTemplate } from '@/api/index'
+import { getStandardTemplate, uploadFile } from '@/api/index'
 import { getEnvBaseUrl } from '@/utils/index'
 import { PressureCheckerMyTaskStatus } from '@/utils/dictMap'
 
@@ -200,8 +200,40 @@ const blobToBase64 = (blob: Blob): Promise<string> => {
   })
 }
 
+const uploadBase64Image = async (image: any): Promise<string | null> => {
+  const imgUrl = image.imgUrl || ''
+  const [header, rawBase64] = imgUrl.includes(',') ? imgUrl.split(',') : ['', imgUrl]
+  const mimeType = header.match(/data:(.*?);base64/)?.[1] || 'image/jpeg'
+  const fileName = `${image.shapeName || `image_${Date.now()}`}.${mimeType.split('/')[1] || 'jpg'}`
+
+  try {
+    const byteString = atob(rawBase64)
+    const ab = new ArrayBuffer(byteString.length)
+    const ia = new Uint8Array(ab)
+    for (let i = 0; i < byteString.length; i++) {
+      ia[i] = byteString.charCodeAt(i)
+    }
+    const blob = new Blob([ab], { type: mimeType })
+    const file = new File([blob], fileName, { type: mimeType })
+    const formData = new FormData()
+    formData.append('file', file)
+
+    const result = await uploadFile(formData)
+    if (result?.code === 0 && result.data) {
+      return result.data as string
+    }
+    uni.showToast({ title: result?.msg || '图片上传失败', icon: 'none' })
+    return null
+  } catch (error) {
+    console.error('图片上传异常:', error)
+    uni.showToast({ title: '图片上传失败', icon: 'none' })
+    return null
+  }
+}
+
 const handleSave = async (data: any) => {
   try {
+    console.log('savedata......', data)
     if (useOnline === '1') {
       const instId = data.instId
       const reqData = {}
@@ -211,6 +243,52 @@ const handleSave = async (data: any) => {
         }
         reqData[key] = data.prepareJson[key]
       }
+
+      if (data.images && data.images.length > 0) {
+        const shouldUplodImgList = data.images.filter((item: any) =>
+          item.shapeName?.startsWith('addPicture_'),
+        )
+
+        if (shouldUplodImgList.length > 0) {
+          uni.showLoading({ title: '图片上传中...', mask: true })
+          for (const image of shouldUplodImgList) {
+            const uploadedUrl = await uploadBase64Image(image)
+            if (!uploadedUrl) {
+              uni.hideLoading()
+              return
+            }
+            image.imgUrl = uploadedUrl
+          }
+          uni.hideLoading()
+        }
+
+        const illustractionList = []
+        for (const element of data.images) {
+          if (element.shapeName.startsWith('addPicture_')) {
+            illustractionList.push({
+              url: element.imgUrl,
+              path: 'Illustration',
+              x: element.imgX,
+              y: element.imgY,
+              width: element.imgWidth,
+              height: element.imgHeight,
+              sheet: element.sheetName,
+            })
+            continue
+          }
+          const originObj = JSON.parse(element.shapeName)
+          const updatedObj = Object.assign(originObj, {
+            x: element.imgX,
+            y: element.imgY,
+            width: element.imgWidth,
+            height: element.imgHeight,
+          })
+          illustractionList.push(updatedObj)
+        }
+        reqData['Illustration'] = JSON.stringify(illustractionList)
+      }
+
+      // console.log("reqD....", reqData)
       const result = await saveDynamicTbVal({ params: reqData, instId })
       if (result?.code === 0 && result?.data) {
         uni.showToast({ title: '保存成功', icon: 'success' })
@@ -333,6 +411,7 @@ const handleTakePhotoFromRN = async (photoData: any) => {
     return
   }
   console.log('RN拍照数据:', photoData)
+  spreadDesignerRef.value?.handleTakePhotoData?.(photoData)
 }
 
 // 调起RN相机

+ 12 - 8
src/pages/equipment/detail/components/BoilerInspectProject.vue

@@ -536,11 +536,12 @@
     <view v-if="showSelectTemplatePopup" class="popup-overlay" @click="closeSelectTemplatePopup">
       <view class="popup-content" @click.stop>
         <text class="popup-title">选择模板</text>
-        <picker :range="templateList" range-key="label" @change="onTemplateChange">
-          <view class="picker-value">
-            <text>{{ selectedTemplate?.label || '请选择' }}</text>
-          </view>
-        </picker>
+        <wd-picker
+          v-model="selectedTemplateValue"
+          :columns="[templateList]"
+          placeholder="请选择"
+          @confirm="onTemplateChange"
+        />
         <view class="popup-actions">
           <button class="action-btn cancel-btn" @click="closeSelectTemplatePopup">取消</button>
           <button class="action-btn confirm-btn" @click="handleConfirmTemplate">确定</button>
@@ -681,6 +682,7 @@ const currentReckUser = ref<any>(null)
 const showSelectTemplatePopup = ref(false)
 const templateList = ref<any[]>([])
 const selectedTemplate = ref<any>(null)
+const selectedTemplateValue = ref('')
 
 const userInfo = computed(() => useUserStore().userInfo)
 
@@ -1179,6 +1181,7 @@ const showAddWorkInstructionPopup = async () => {
 
     templateList.value = list
     selectedTemplate.value = null
+    selectedTemplateValue.value = ''
     showSelectTemplatePopup.value = true
   } catch (error) {
     console.error('获取操作指导书模板失败:', error)
@@ -1189,11 +1192,12 @@ const showAddWorkInstructionPopup = async () => {
 const closeSelectTemplatePopup = () => {
   showSelectTemplatePopup.value = false
   selectedTemplate.value = null
+  selectedTemplateValue.value = ''
 }
 
-const onTemplateChange = (e: any) => {
-  const index = e.detail.value
-  selectedTemplate.value = templateList.value[index]
+const onTemplateChange = ({ value, selectedItems }: any) => {
+  selectedTemplateValue.value = value
+  selectedTemplate.value = selectedItems
 }
 
 const handleConfirmTemplate = async () => {

+ 12 - 8
src/pages/equipment/detail/components/PipeInspectProject.vue

@@ -298,11 +298,12 @@
     <view v-if="showSelectTemplatePopup" class="popup-overlay" @click="closeSelectTemplatePopup">
       <view class="popup-content" @click.stop>
         <text class="popup-title">选择模板</text>
-        <picker :range="templateList" range-key="label" @change="onTemplateChange">
-          <view class="picker-value">
-            <text>{{ selectedTemplate?.label || '请选择' }}</text>
-          </view>
-        </picker>
+        <wd-picker
+          v-model="selectedTemplateValue"
+          :columns="[templateList]"
+          placeholder="请选择"
+          @confirm="onTemplateChange"
+        />
         <view class="popup-actions">
           <button class="action-btn cancel-btn" @click="closeSelectTemplatePopup">取消</button>
           <button class="action-btn confirm-btn" @click="handleConfirmTemplate">确定</button>
@@ -407,6 +408,7 @@ const currentReckUser = ref<any>(null)
 const showSelectTemplatePopup = ref(false)
 const templateList = ref<any[]>([])
 const selectedTemplate = ref<any>(null)
+const selectedTemplateValue = ref('')
 
 const userInfo = computed(() => useUserStore().userInfo)
 
@@ -894,6 +896,7 @@ const showAddWorkInstructionPopup = async () => {
 
     templateList.value = list
     selectedTemplate.value = null
+    selectedTemplateValue.value = ''
     showSelectTemplatePopup.value = true
   } catch (error) {
     console.error('获取操作指导书模板失败:', error)
@@ -904,11 +907,12 @@ const showAddWorkInstructionPopup = async () => {
 const closeSelectTemplatePopup = () => {
   showSelectTemplatePopup.value = false
   selectedTemplate.value = null
+  selectedTemplateValue.value = ''
 }
 
-const onTemplateChange = (e: any) => {
-  const index = e.detail.value
-  selectedTemplate.value = templateList.value[index]
+const onTemplateChange = ({ value, selectedItems }: any) => {
+  selectedTemplateValue.value = value
+  selectedTemplate.value = selectedItems
 }
 
 const handleConfirmTemplate = async () => {