spring
5 小时以前 0264677110e0bf49897e1b7af0551af3f406e193
fix: 原料检上传附件按钮点击无响应
已修改2个文件
134 ■■■■ 文件已修改
src/pages/index.vue 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/qualityManagement/rawMaterial/files.vue 130 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/index.vue
@@ -1208,9 +1208,9 @@
    // 质量管理菜单:固定只展示 3 个入口
    const originalQuality = [
      { icon: "/static/images/icon/caigoutaizhang@2x.png", label: "检测项维护" },
      { icon: "/static/images/icon/shengchanhesuan@2x.png", label: "检测项维护" },
      { icon: "/static/images/icon/caigoutaizhang@2x.png", label: "原料检" },
      { icon: "/static/images/icon/caigoutaizhang@2x.png", label: "不合格品管理" },
      { icon: "/static/images/icon/shengchandingdan@2x.png", label: "不合格品管理" },
    ];
    qualityItems.splice(0, qualityItems.length, ...originalQuality);
src/pages/qualityManagement/rawMaterial/files.vue
@@ -18,7 +18,7 @@
    </view>
    <view class="upload-bar">
      <view class="btn-upload" @click="chooseFile">上传附件</view>
      <view class="btn-upload" @tap="chooseFile">上传附件</view>
    </view>
  </view>
</template>
@@ -48,15 +48,46 @@
    uni.showToast({ title: '缺少检验记录ID', icon: 'none' })
    return
  }
  uni.chooseFile({
    count: 1,
    success: (res) => {
      const path = res?.tempFiles?.[0]?.path
      const name = res?.tempFiles?.[0]?.name
      if (!path) return
      uploadOne(path, name)
  const pickByChooseFile = () => {
    if (typeof uni.chooseFile !== 'function') return false
    uni.chooseFile({
      count: 1,
      success: (res) => {
        const file = res?.tempFiles?.[0]
        const path = file?.path
        const name = file?.name
        if (!path) return
        uploadOne(path, name)
      },
      fail: () => {
        // chooseFile 在部分 App 机型/基座可能会失败,做降级
        pickByChooseImage()
      }
    })
    return true
  }
  const pickByChooseImage = () => {
    if (typeof uni.chooseImage !== 'function') {
      uni.showToast({ title: '当前版本不支持选择文件', icon: 'none' })
      return
    }
  })
    uni.chooseImage({
      count: 1,
      success: (res) => {
        const path = res?.tempFilePaths?.[0]
        if (!path) return
        uploadOne(path, '图片附件')
      },
      fail: () => {
        uni.showToast({ title: '选择失败', icon: 'none' })
      }
    })
  }
  // App/H5 统一走 chooseFile,失败时降级 chooseImage
  const ok = pickByChooseFile()
  if (!ok) pickByChooseImage()
}
const uploadOne = (filePath, originalName) => {
@@ -97,12 +128,69 @@
}
const previewFile = (f) => {
  const url = f?.url
  const rawUrl = f?.url
  if (!rawUrl) return
  const url = normalizeUrl(rawUrl)
  const name = f?.name || '附件'
  if (!url) return
  // H5/APP 统一用外部打开
  uni.navigateTo({
    url: `/pages/inspectionUpload/filePreview?url=${encodeURIComponent(url)}`
  // 图片优先用原生预览
  if (isImageUrl(url) || isImageName(name)) {
    uni.previewImage({ urls: [url] })
    return
  }
  // 非图片:下载后打开
  const token = getToken()
  uni.showLoading({ title: '打开中...', mask: true })
  uni.downloadFile({
    url,
    header: token ? { Authorization: 'Bearer ' + token } : undefined,
    success: (res) => {
      const filePath = res?.tempFilePath
      if (!filePath) {
        uni.hideLoading()
        uni.showToast({ title: '打开失败', icon: 'none' })
        return
      }
      uni.openDocument({
        filePath,
        showMenu: true,
        success: () => {
          uni.hideLoading()
        },
        fail: () => {
          uni.hideLoading()
          uni.showToast({ title: '打开失败', icon: 'none' })
        }
      })
    },
    fail: () => {
      uni.hideLoading()
      uni.showToast({ title: '下载失败', icon: 'none' })
    }
  })
}
const normalizeUrl = (u) => {
  const s = String(u || '').trim()
  if (!s) return ''
  if (s.startsWith('http://') || s.startsWith('https://')) return s
  if (s.startsWith('//')) return 'https:' + s
  // 系统里附件预览/下载一般走 fileUrl
  if (s.startsWith('/')) return `${config.fileUrl}${s}`
  return `${config.fileUrl}/${s.replace(/^\//, '')}`
}
const isImageName = (name) => {
  const n = String(name || '').toLowerCase()
  return /\.(png|jpe?g|gif|bmp|webp|heic)$/.test(n)
}
const isImageUrl = (url) => {
  const u = String(url || '').toLowerCase()
  return /\.(png|jpe?g|gif|bmp|webp|heic)(\?|#|$)/.test(u)
}
const confirmDelete = (f) => {
@@ -148,12 +236,22 @@
.file-list { margin: 24rpx; background: #fff; border-radius: 16rpx; padding: 12rpx 24rpx; }
.file-item { padding: 20rpx 0; border-bottom: 1rpx solid #eee; display: flex; justify-content: space-between; align-items: center; gap: 16rpx; }
.file-item:last-child { border-bottom: 0; }
.file-name { font-size: 28rpx; color: #333; }
.file-actions { display: flex; gap: 20rpx; }
.file-info { flex: 1; min-width: 0; }
.file-name {
  display: block;
  width: 420rpx;
  max-width: 100%;
  font-size: 28rpx;
  color: #333;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.file-actions { display: flex; gap: 20rpx; flex-shrink: 0; }
.btn-link { color: #2979ff; font-size: 26rpx; }
.btn-link.danger { color: #f56c6c; }
.empty { text-align: center; padding: 60rpx 0; color: #999; font-size: 28rpx; }
.upload-bar { position: fixed; left: 0; right: 0; bottom: 0; padding: 16rpx 24rpx calc(16rpx + env(safe-area-inset-bottom)); background: #fff; box-shadow: 0 -4rpx 16rpx rgba(0,0,0,0.04); }
.upload-bar { position: fixed; left: 0; right: 0; bottom: 0; padding: 16rpx 24rpx calc(16rpx + env(safe-area-inset-bottom)); background: #fff; box-shadow: 0 -4rpx 16rpx rgba(0,0,0,0.04); z-index: 20; }
.btn-upload { height: 88rpx; border-radius: 999rpx; background: #2979ff; color: #fff; font-size: 30rpx; display: flex; align-items: center; justify-content: center; }
</style>