Selaa lähdekoodia

添加图片预览

zengjun 6 kuukautta sitten
vanhempi
commit
ad38d47889

+ 39 - 1
src/api/processing/index.ts

@@ -1,5 +1,6 @@
 // @ts-ignore
 import request from '@/utils/request'
+
 /**
  * 加工-获取加工类型
  * @param params
@@ -10,11 +11,12 @@ export function getProcessingTypeList() {
     method: 'get',
   })
 }
+
 /**
  * 加工-创建加工单
  * @param params
  */
-export function createProcessing(data:any) {
+export function createProcessing(data: any) {
   return request({
     url: 'api/device/check/processing/reference',
     method: 'post',
@@ -22,3 +24,39 @@ export function createProcessing(data:any) {
   })
 }
 
+/**
+ * 加工单拍摄任务
+ * @param params
+ */
+export function getProcessingPhotoTask(params) {
+  return request({
+    url: 'api/device/check/processing/photo-task',
+    method: 'get',
+    params,
+  })
+}
+
+/**
+ * 对应的拍摄图片
+ * @param id {number} processing photo task id
+ */
+export function processingPhotoTaskItems(id) {
+  return request({
+    url: `api/device/check/processing/photo-task/${id}/photos`,
+    method: 'get',
+  })
+}
+
+/**
+ * 上传图片
+ * @param  id  processing photo task id
+ * @param params  params
+ */
+export function uploadPhoto(id, params) {
+  return request({
+    url: `api/device/check/processing/photo-task/upload-photo/${id}`,
+    method: 'put',
+    headers: { 'Content-Type': 'multipart/form-data' },
+    data: params,
+  })
+}

+ 5 - 1
src/hooks/basic/menu.js

@@ -124,7 +124,11 @@ export default function() {
               icon: 'newspaper-o',
               path: 'container-operation',
             },
-
+            {
+              title: '加工拍摄任务',
+              icon: 'newspaper-o',
+              path: 'processing-photo-task',
+            },
           ],
         },
       ],

+ 6 - 0
src/router/index.ts

@@ -145,6 +145,12 @@ const routes: RouteRecordRaw[] = [
     meta:{title:'移库'},
     component: () => import('@/views/inventory/transfer/index.vue')
   },
+  {
+    path: '/processing-photo-task',
+    name: 'ProcessingPhotoTask',
+    meta:{title:'加工拍摄任务'},
+    component: () => import('@/views/processing/photoTask/index.vue')
+  },
 ];
 
 // 创建路由实例

+ 317 - 0
src/views/processing/photoTask/index.vue

@@ -0,0 +1,317 @@
+<template>
+  <div class="container">
+    <div class="processing-photo-task">
+      <div class="top">
+        <div class="nav-bar">
+          <van-nav-bar
+            title="加工拍照任务"
+            left-arrow
+            @click-left="goBack"
+            @click-right="onRefresh"
+          >
+            <template #left>
+              <van-icon name="arrow-left" size="25" />
+              <div
+                style="
+                  color: #fff;
+                  height: 46px;
+                  padding-right: 20px;
+                  line-height: 46px;
+                "
+              >
+                返回
+              </div>
+            </template>
+            <template #right>
+              <div class="nav-right" style="color: #fff">刷新</div>
+            </template>
+          </van-nav-bar>
+        </div>
+
+        <div class="context">
+          <van-pull-refresh
+            v-model="loading"
+            @refresh="onRefresh"
+            :style="{
+              'max-height': computedMaxHeight,
+              'min-height': computedMaxHeight,
+              overflow: 'auto',
+            }"
+          >
+            <table
+              border="1"
+              style="
+                width: 100%;
+                border-collapse: collapse;
+                text-align: center;
+                table-layout: fixed;
+              "
+            >
+              <thead>
+                <tr>
+                  <th>货主</th>
+                  <th>加工单号</th>
+                  <th>状态</th>
+                  <th>查看</th>
+                  <th>操作</th>
+                </tr>
+              </thead>
+              <tbody>
+                <tr v-for="(row, rowIndex) in photoTasks" :key="rowIndex">
+                  <td>{{ row.ownerName }}</td>
+                  <td>{{ row.code }}</td>
+                  <td>{{ row.status }}</td>
+                  <td>
+                    <van-button type="info" size="mini" @click="showPhotos(row)"
+                      >查看
+                    </van-button>
+                  </td>
+                  <td>
+                    <van-button type="primary" size="mini" @click="toPhoto(row)"
+                      >拍摄
+                    </van-button>
+                  </td>
+                </tr>
+              </tbody>
+            </table>
+          </van-pull-refresh>
+        </div>
+      </div>
+
+      <!-- 图片上传弹窗 -->
+      <van-popup v-model:show="showUpload" position="bottom" :style="{ height: '80%' }">
+        <div class="upload-popup">
+          <van-nav-bar
+            title="图片上传"
+            left-arrow
+            @click-left="showUpload = false"
+          >
+            <template #left>
+              <van-icon name="arrow-left" size="25" />
+              <div style="color: #fff; height: 46px; padding-right: 20px; line-height: 46px;">
+                返回
+              </div>
+            </template>
+          </van-nav-bar>
+
+          <div class="upload-content">
+            <van-uploader
+              v-model="uploadImages"
+              :max-count="9"
+              :max-size="15 * 1024 * 1024"
+              :before-read="beforeReadImage"
+              :after-read="afterReadImage"
+              multiple
+              preview-full-image
+            />
+
+            <div class="upload-footer">
+              <van-button
+                type="primary"
+                block
+                :loading="uploading"
+                @click="submitUpload"
+              >
+                {{ uploading ? '上传中...' : '提交上传' }}
+              </van-button>
+            </div>
+          </div>
+        </div>
+      </van-popup>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, computed, onMounted } from 'vue'
+import { useRoute } from 'vue-router'
+import { showNotify, showImagePreview, showFailToast, showLoadingToast, closeToast } from 'vant'
+import {
+  getProcessingPhotoTask,
+  processingPhotoTaskItems,
+  uploadPhoto
+} from '@/api/processing/index'
+import { goBack } from '@/utils/android'
+
+
+const route = useRoute()
+const loading = ref(false)
+const photoTasks = ref([])
+const showUpload = ref(false)
+const uploadImages = ref([])
+const uploading = ref(false)
+const currentTaskId = ref(null)
+
+const sizes = ref([20, 50, 100])
+const paginate = ref({
+  page: 1,
+  size: 20,
+  total: 0,
+  pages: 0,
+})
+const reviewImages = ref([])
+
+// 计算最大高度适配手持设备
+const computedMaxHeight = computed(() => {
+  return window.innerHeight - 46 - 20 + 'px'
+})
+
+// 获取从其他页面传递的参数
+onMounted(() => {
+  // 可以从route.query或route.params中获取参数
+  if (route.query.id) {
+    // 如果有传入id参数,可以做特殊处理
+    console.log('接收到参数id:', route.query.id)
+  }
+})
+
+function onRefresh() {
+  listProcessingPhoto()
+}
+
+function listProcessingPhoto() {
+  loading.value = true
+  getProcessingPhotoTask(paginate.value).then((res) => {
+    photoTasks.value = res?.data?.records || []
+  }).finally(() => {
+    loading.value = false
+  })
+}
+
+function nextPage() {
+  const page = paginate.value.page
+  paginate.value.page += 1
+}
+
+function showPhotos(row) {
+  processingPhotoTaskItems(row.id).then((res) => {
+    const items = res.data
+    console.log(res)
+    if (!items || items.length === 0) {
+      showNotify({ type: 'warning', message: '没有对应的拍摄' })
+      return
+    }
+    console.log(import.meta.env.VITE_APP_BASE_API)
+    const baseUrl = import.meta.env.VITE_APP_BASE_API + 'statics/storage/'
+    const paths = baseUrl.split('.')
+    paths[1] = 'swms'
+    const base = paths.join('.')
+    // 解构图片url
+    reviewImages.value = items.map(item => {
+      const {path,module} = item
+      return `${base}${module}/${path}`
+    }).filter(url => url)
+
+    console.log(reviewImages.value)
+    // 预览图片
+    if (reviewImages.value.length > 0) {
+      showImagePreview({
+        images: reviewImages.value,
+        closeable: true,
+      })
+    } else {
+      showNotify({ type: 'warning', message: '没有可预览的图片' })
+    }
+  }).catch(err => {
+    showNotify({ type: 'danger', message: '获取图片失败' })
+  })
+}
+
+function toPhoto(row) {
+  currentTaskId.value = row.id
+  uploadImages.value = []
+  showUpload.value = true
+}
+
+// 检查图片格式和大小
+const beforeReadImage = (file) => {
+  const files = Array.isArray(file) ? file : [file]
+  for (const f of files) {
+    // 检查文件格式
+    if (f.name.toLowerCase().endsWith('.heic') || f.name.toLowerCase().endsWith('.heif')) {
+      showFailToast('不支持HEIC/HEIF格式的图片')
+      return false
+    }
+
+    // 检查文件类型
+    const isImage = /^image\//.test(f.type)
+    if (!isImage) {
+      showFailToast('请上传图片文件')
+      return false
+    }
+
+    // 检查文件大小 (15MB)
+    if (f.size > 15 * 1024 * 1024) {
+      showFailToast('图片大小不能超过15MB')
+      return false
+    }
+  }
+  return true
+}
+
+// 图片读取完成后处理
+const afterReadImage = (file) => {
+  // file 是上传的文件信息,可以在这里进行额外处理
+  console.log('文件读取完成:', file)
+}
+
+// 提交上传
+const submitUpload = async () => {
+  if (!uploadImages.value.length) {
+    showFailToast('请先选择图片')
+    return
+  }
+
+  if (!currentTaskId.value) {
+    showFailToast('任务ID无效')
+    return
+  }
+
+  uploading.value = true
+  const toast = showLoadingToast('上传中...')
+
+  try {
+    // 逐个上传图片
+    for (const image of uploadImages.value) {
+      const formData = new FormData()
+      formData.append('file', image.file)
+      // 调用上传API
+      await uploadPhoto(currentTaskId.value, formData)
+    }
+
+    closeToast()
+    showNotify({ type: 'success', message: '上传成功' })
+
+    // 关闭弹窗并刷新列表
+    showUpload.value = false
+    uploadImages.value = []
+    onRefresh()
+  } catch (err) {
+    closeToast()
+    showNotify({ type: 'danger', message: '上传失败: ' + (err.message || '未知错误') })
+  } finally {
+    uploading.value = false
+  }
+}
+
+// 初始化加载数据
+onRefresh()
+</script>
+
+<style scoped lang="scss">
+.upload-popup {
+  height: 100%;
+  display: flex;
+  flex-direction: column;
+
+  .upload-content {
+    flex: 1;
+    padding: 10px;
+    overflow-y: auto;
+
+    .upload-footer {
+      padding: 10px 0;
+    }
+  }
+}
+</style>