Ver Fonte

feat: 更新上传组件,支持多种文件类型及扩展名,优化发票展示逻辑

laiqi há 11 meses atrás
pai
commit
e833d4416b

+ 16 - 1
src/components/UploadComponent.vue

@@ -3,6 +3,8 @@
     <wd-upload
       v-model:file-list="fileList"
       image-mode="aspectFill"
+      :accept="accept"
+      :extension="extension"
       :upload-method="
         createCustomUpload({
           attmodel,
@@ -84,6 +86,19 @@ const props = defineProps({
     type: String,
     default: '',
   },
+  // 新增:接受的文件类型,默认为image保持向后兼容
+  accept: {
+    type: String as () => 'image' | 'video' | 'media' | 'file' | 'all',
+    default: 'image', // 默认只支持图片,保持向后兼容
+    validator: (value: string) => {
+      return ['image', 'video', 'media', 'file', 'all'].includes(value)
+    },
+  },
+  // 新增:文件扩展名限制,默认为空数组
+  extension: {
+    type: Array as () => string[],
+    default: () => [],
+  },
 })
 
 const emit = defineEmits(['update:modelValue', 'update:fileIds'])
@@ -150,7 +165,7 @@ function createCustomUpload({ attmodel, attpath, modelStats }) {
 
     if (!error.value) {
       options.onSuccess('', file, formData)
-      // {"Status":0,"Data":"2025041016044040627399","Message":"执行成功","OtherData":"https://dzapi.kdboss.cn/upfile/orders_invoice/20250410/2025041016044040731543.png"}
+      // {"Status":0,"Data":"2025041016044040627399","Message":"执行成功","OtherData":"https://dzapi.kdboss.cn/upfile/coupon_invoice/20250410/2025041016044040731543.png"}
       const dataObject = JSON.parse(data.value)
       const newFileIds = [...props.fileIds]
       newFileIds.push({

+ 7 - 5
src/pages/form/formStep4.vue

@@ -101,7 +101,7 @@
 
         <view class="mb-4">
           <view class="text-gray-700 mb-2 text-base flex items-center">
-            <text>发票照片</text>
+            <text>发票照片或PDF文件</text>
             <text class="text-red-500 ml-1">*</text>
           </view>
           <UploadComponent
@@ -109,11 +109,13 @@
             v-model:fileIds="formData.invoiceFileIds"
             :limit="1"
             :required="true"
-            attmodel="orders_invoice"
-            attpath="/orders_invoice/"
+            accept="all"
+            :extension="['.jpg', '.jpeg', '.png', '.pdf']"
+            attmodel="coupon_invoice"
+            attpath="/coupon_invoice/"
             modelStats="invoiceFileIds"
-            message="请上传发票照片"
-            tips="请上传清晰的发票照片"
+            message="请上传发票照片或PDF文件"
+            tips="支持图片格式(JPG、PNG)和PDF文件,文件大小不超过10MB"
           />
         </view>
       </view>

+ 110 - 5
src/pages/order/detail.vue

@@ -27,8 +27,25 @@
       <wd-cell title="发票信息">
         <!-- 发票信息展示 -->
         <view class="flex flex-wrap" v-if="invoiceImg.length">
-          <view class="flex-1" v-for="item in invoiceImg" :key="item.id">
-            <wd-img :width="100" :height="100" :src="item.url" :enable-preview="true" />
+          <view class="flex-1 flex justify-end" v-for="item in invoiceImg" :key="item.attid">
+            <!-- 如果是PDF文件,显示文件名并可点击打开 -->
+            <view v-if="item.atttype === 'pdf'" class="file-item" @click="openPdfFile(item)">
+              <view class="file-icon">📄</view>
+              <view class="file-name">{{ item.attorginname }}</view>
+            </view>
+            <!-- 如果是图片文件,使用wd-img展示 -->
+            <wd-img
+              v-else-if="isImageType(item.atttype)"
+              :width="100"
+              :height="100"
+              :src="item.url"
+              :enable-preview="true"
+            />
+            <!-- 其他类型文件的默认展示 -->
+            <view v-else class="file-item" @click="openPdfFile(item)">
+              <view class="file-icon">📎</view>
+              <view class="file-name">{{ item.attorginname }}</view>
+            </view>
           </view>
         </view>
         <!-- 无发票信息时的提示 -->
@@ -62,12 +79,12 @@
 <script lang="ts" setup>
 import { useOrderStore } from '@/store/order'
 import { useFileStore } from '@/store/file'
-import { useMessage } from 'wot-design-uni'
+import { useToast } from 'wot-design-uni'
 import type { OrderType } from '@/types/order'
 
 const orderStore = useOrderStore()
 const fileStore = useFileStore()
-const message = useMessage()
+const toast = useToast()
 const currentOrdersId = ref('')
 const coupon2sid = ref('')
 const orderDetail = ref<OrderType>({} as OrderType)
@@ -108,6 +125,53 @@ function handleBack() {
   })
 }
 
+// 判断文件是否为图片类型
+function isImageType(atttype: string) {
+  const imageTypes = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp']
+  return imageTypes.includes(atttype.toLowerCase())
+}
+
+// 打开PDF文件
+function openPdfFile(item: any) {
+  // 拼接PDF文件完整URL
+  const pdfUrl = `${fileStore.fileHeadUrl}${item.attpath}${item.attname}.${item.atttype}`
+
+  // 使用浏览器打开PDF文件
+  // #ifdef H5
+  window.open(pdfUrl, '_blank')
+  // #endif
+
+  // #ifdef MP-WEIXIN
+  // 微信小程序中下载后打开文档
+  uni.downloadFile({
+    url: pdfUrl,
+    success: (res) => {
+      if (res.statusCode === 200) {
+        uni.openDocument({
+          filePath: res.tempFilePath,
+          success: () => {
+            console.log('PDF打开成功')
+          },
+          fail: (err) => {
+            console.error('PDF打开失败:', err)
+            toast.error('PDF文件打开失败')
+          },
+        })
+      }
+    },
+    fail: (err) => {
+      console.error('PDF下载失败:', err)
+      toast.error('PDF文件下载失败')
+    },
+  })
+  // #endif
+
+  // #ifdef APP-PLUS
+  // App中使用系统默认方式打开
+  plus.runtime.openURL(pdfUrl)
+  // #endif
+}
+
 const invoiceImg = ref([]) // 发票图片
 const identityImg = ref([]) // 购机者证件照片
 const buyerImg = ref([]) // 购机者照片
@@ -116,7 +180,7 @@ const buyerImg = ref([]) // 购机者照片
 const getInvoiceImg = async () => {
   const res = await fileStore.getAttachmentList({
     attlsh: currentOrdersId.value, // 关联id为订单id
-    attmodel: 'orders_invoice',
+    attmodel: 'coupon_invoice',
   })
   invoiceImg.value = res
 }
@@ -162,4 +226,45 @@ onLoad(async (query) => {
 :deep(.wd-upload) {
   width: 100%;
 }
+
+.file-item {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: center;
+  width: 100px;
+  height: 100px;
+  cursor: pointer;
+  background-color: #f9fafb;
+  border: 1px solid #e5e7eb;
+  border-radius: 8px;
+  transition: all 0.2s ease;
+
+  &:hover {
+    background-color: #f3f4f6;
+    border-color: #d1d5db;
+  }
+
+  &:active {
+    background-color: #e5e7eb;
+  }
+}
+
+.file-icon {
+  margin-bottom: 4px;
+  font-size: 24px;
+}
+
+.file-name {
+  display: -webkit-box;
+  max-width: 90px;
+  overflow: hidden;
+  font-size: 12px;
+  line-height: 1.2;
+  color: #374151;
+  text-align: center;
+  word-break: break-all;
+  -webkit-line-clamp: 2;
+  -webkit-box-orient: vertical;
+}
 </style>

+ 1 - 1
src/store/file.ts

@@ -24,7 +24,7 @@ export const useFileStore = defineStore(
       )
 
       await until(loading).toBe(false)
-      // https://dzapi.kdboss.cn/upfile/orders_invoice/20250410/2025041018283477178626.png
+      // https://dzapi.kdboss.cn/upfile/coupon_invoice/20250410/2025041018283477178626.png
 
       const fileList = configList.value.Data.map((item) => {
         return {