gaoluyang
2025-12-31 00ae6e7c8ccb3e8abad027104529f18f68142a48
陕西昭德型煤:
1.现场巡检上传附件查看附件修改联调
已修改5个文件
180 ■■■■ 文件已修改
src/components/imageUpload/index.vue 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/imageUpload/viewQrCodeFiles.vue 151 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/manifest.json 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/inspectionUpload/components/formDia.vue 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/inspectionUpload/components/qrCodeFormDia.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/imageUpload/index.vue
@@ -104,7 +104,7 @@
// Props 定义
const props = defineProps({
  modelValue: [String, Object, Array],
  action: { type: String, default: "/common/minioUploads" },
  action: { type: String, default: "/common/commonUploads" },
  data: { type: Object },
  limit: { type: Number, default: 5 },
  fileSize: { type: Number, default: 10 }, // 默认10MB,适合视频
@@ -115,7 +115,7 @@
  isShowTip: { type: Boolean, default: true },
  disabled: { type: Boolean, default: false },
  drag: { type: Boolean, default: false }, // 拍照不需要拖拽
  statusType: { type: Number, default: "" }, // 用于区分不同状态的上传
  type: { type: Number, default: "" }, // 用于区分不同状态的上传
  maxVideoDuration: { type: Number, default: 30 }, // 最大视频时长(秒)
});
@@ -174,7 +174,7 @@
const testServerConnection = () => {
  return new Promise((resolve) => {
    uni.request({
      url: uploadFileUrl.value.replace('/common/minioUploads', '/common/test'),
      url: uploadFileUrl.value.replace('/common/commonUploads', '/common/commonUploads'),
      method: 'GET',
      timeout: 5000,
      success: (res) => {
@@ -364,7 +364,7 @@
    filePath: filePath,
    name: 'files',
    formData: {
      type: props.statusType || 0,
      type: props.type || 0,
      ...(props.data || {})
    },
    header: {
src/components/imageUpload/viewQrCodeFiles.vue
@@ -49,15 +49,48 @@
                  v-for="(videoUrl, index) in beforeProductionVideos"
                  :key="index"
                  class="video-item"
                  @click="previewVideo(videoUrl)"
                  @click="playVideo(videoUrl, index)"
                >
                  <view class="video-preview">
                  <video
                    :src="videoUrl"
                    class="video-thumbnail"
                    :poster="videoUrl"
                    :controls="false"
                    :show-center-play-btn="true"
                    @play="onVideoPlay"
                  ></video>
                  <view class="video-overlay">
                    <u-icon name="play-circle-fill" size="40" color="#fff"></u-icon>
                  </view>
                  <view class="video-tip">点击播放</view>
                </view>
              </view>
            </view>
            <!-- 视频播放弹窗 -->
            <u-popup
              :show="showVideoPlayer"
              mode="center"
              width="100%"
              height="100%"
              :closeable="true"
              @close="closeVideoPlayer"
              :safeAreaInsetBottom="false"
            >
              <view class="video-player-container">
                <video
                  v-if="currentVideoUrl"
                  :src="currentVideoUrl"
                  class="video-player"
                  :controls="true"
                  :show-center-play-btn="true"
                  :enable-play-gesture="true"
                  :show-fullscreen-btn="true"
                  :enable-progress-gesture="true"
                  :object-fit="'contain'"
                  @fullscreenchange="onFullscreenChange"
                ></video>
              </view>
            </u-popup>
            
            <!-- 空状态 -->
            <view v-if="beforeProductionImgs.length === 0 && beforeProductionVideos.length === 0" class="empty-state">
@@ -83,6 +116,9 @@
const beforeProductionImgs = ref([])
// 视频数组
const beforeProductionVideos = ref([])
// 视频播放器
const showVideoPlayer = ref(false)
const currentVideoUrl = ref('')
// 打开弹窗并加载数据
const openDialog = async (row) => {
@@ -111,20 +147,30 @@
  })
}
// 预览视频
const previewVideo = (url) => {
  uni.previewVideo({
    sources: [{
      src: url
    }],
    fail: (err) => {
      console.error('视频预览失败:', err)
      uni.showToast({
        title: '视频预览失败',
        icon: 'error'
      })
    }
  })
// 播放视频
const playVideo = (url, index) => {
  currentVideoUrl.value = url
  showVideoPlayer.value = true
}
// 关闭视频播放器
const closeVideoPlayer = () => {
  showVideoPlayer.value = false
  currentVideoUrl.value = ''
}
// 视频播放事件
const onVideoPlay = () => {
  // 可以在这里处理播放事件
}
// 全屏变化事件
const onFullscreenChange = (e) => {
  console.log('全屏状态变化:', e)
  // 如果退出全屏,可以选择关闭弹窗
  if (e.detail && e.detail.fullScreen === false) {
    // 可以选择保持弹窗打开或关闭
  }
}
// 表单关闭方法
@@ -133,6 +179,17 @@
  // 重置数据
  beforeProductionImgs.value = []
  beforeProductionVideos.value = []
}
// 处理URL,添加基础域名
function formatUrl(url) {
  if (!url) return ''
  // 如果已经是完整URL,直接返回
  if (url.startsWith('http://') || url.startsWith('https://')) {
    return url
  }
  // 否则添加基础域名
  return `https://nj477vg8876.vicp.fun${url.startsWith('/') ? '' : '/'}${url}`
}
// 处理每一类数据:分离图片和视频
@@ -145,10 +202,15 @@
  const videos = []
  
  items.forEach(item => {
    const fileUrl = item.url || item.downloadUrl || item.fileUrl
    if (!fileUrl) return
    const fullUrl = formatUrl(fileUrl)
    if (item.contentType?.startsWith('image/')) {
      images.push(item.url)
      images.push(fullUrl)
    } else if (item.contentType?.startsWith('video/')) {
      videos.push(item.url)
      videos.push(fullUrl)
    }
  })
  
@@ -263,28 +325,43 @@
  border-radius: 8px;
  overflow: hidden;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
.video-preview {
  width: 100%;
  height: 100%;
  background-color: #333;
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
}
.video-tip {
.video-thumbnail {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.video-overlay {
  position: absolute;
  bottom: 5px;
  left: 50%;
  transform: translateX(-50%);
  font-size: 12px;
  color: #fff;
  background-color: rgba(0, 0, 0, 0.6);
  padding: 2px 8px;
  border-radius: 4px;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: rgba(0, 0, 0, 0.3);
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
}
.video-player-container {
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: #000;
  position: relative;
}
.video-player {
  width: 100%;
  height: 100%;
  max-width: 100vw;
  max-height: 100vh;
}
.empty-state {
src/manifest.json
@@ -7,10 +7,10 @@
    "transformPx" : false,
    /* 5+App特有相关 */
    "app-plus" : {
      "compatible" : {
        "usingComponents" : true,
        "ignoreVersion" : true
      },
        "compatible" : {
            "usingComponents" : true,
            "ignoreVersion" : true
        },
        "usingComponents" : true,
        "nvueStyleCompiler" : "uni-app",
        "compilerVersion" : 3,
@@ -21,7 +21,10 @@
            "delay" : 0
        },
        /* 模块配置 */
        "modules" : {},
        "modules" : {
            "Camera" : {},
            "VideoPlayer" : {}
        },
        /* 应用发布信息 */
        "distribute" : {
            /* android打包配置 */
src/pages/inspectionUpload/components/formDia.vue
@@ -285,13 +285,13 @@
  try {
    let arr = []
    if (beforeModelValue.value.length > 0) {
      arr.push(...beforeModelValue.value.map(item => ({ ...item, statusType: 0 })))
      arr.push(...beforeModelValue.value.map(item => ({ ...item, type: 0 })))
    }
    if (afterModelValue.value.length > 0) {
      arr.push(...afterModelValue.value.map(item => ({ ...item, statusType: 1 })))
      arr.push(...afterModelValue.value.map(item => ({ ...item, type: 1 })))
    }
    if (issueModelValue.value.length > 0) {
      arr.push(...issueModelValue.value.map(item => ({ ...item, statusType: 2 })))
      arr.push(...issueModelValue.value.map(item => ({ ...item, type: 2 })))
    }
    
    // 提交数据
src/pages/inspectionUpload/components/qrCodeFormDia.vue
@@ -48,7 +48,7 @@
                :fileSize="50"
                :fileType="['jpg', 'jpeg', 'png', 'mp4', 'mov']"
                :maxVideoDuration="60"
                :statusType="0"
                :type="0"
                @update:modelValue="handleStorageBlobUpdate"
              />
            </view>