gaoluyang
2026-04-07 62e9986b6d2d20e61a3b65745af33165c9f1534b
军泰
1.产品维护上传修改
已修改2个文件
187 ■■■■ 文件已修改
src/components/filePreview/index.vue 56 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/basicData/product/index.vue 131 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/filePreview/index.vue
@@ -6,9 +6,9 @@
        <img :src="imgUrl" alt="Image Preview" />
      </div>
      
      <!-- PDF预览提示 -->
      <div v-if="isPdf" style="height: 100vh; display: flex; align-items: center; justify-content: center;">
        <p>正在准备PDF预览...</p>
      <!-- PDF预览 -->
      <div v-if="isPdf" class="pdf-preview-wrapper">
        <iframe :src="fileUrl" class="pdf-preview-frame" frameborder="0"></iframe>
      </div>
      
      <!-- Word文档预览 -->
@@ -53,7 +53,7 @@
</template>
<script setup>
import { ref, computed, getCurrentInstance, watch } from 'vue';
import { ref, computed, getCurrentInstance } from 'vue';
import VueOfficeDocx from '@vue-office/docx';
import '@vue-office/docx/lib/index.css';
import VueOfficeExcel from '@vue-office/excel';
@@ -112,45 +112,6 @@
  return isImage.value || isPdf.value || isDoc.value || isXls.value || isZipOrRar.value;
});
// 动态创建a标签并跳转预览PDF
const previewPdf = (url) => {
  // 创建a标签
  const link = document.createElement('a');
  // 设置PDF文件URL
  link.href = url;
  // 在新标签页打开
  link.target = '_blank';
  // 安全属性,防止新页面访问原页面
  link.rel = 'noopener noreferrer';
  // 可选:设置链接文本
  link.textContent = '预览PDF';
  // 将a标签添加到页面(部分浏览器要求必须在DOM中)
  document.body.appendChild(link);
  // 触发点击事件
  link.click();
  // 移除a标签,清理DOM
  document.body.removeChild(link);
};
// 监听PDF状态变化,自动触发跳转
watch(
  () => isPdf.value,
  (newVal) => {
    // 当确认是PDF且文件URL有效时
    if (newVal && fileUrl.value) {
      // 关闭对话框
      dialogVisible.value = false;
      // 加个小延迟确保状态更新完成
      setTimeout(() => {
        previewPdf(fileUrl.value);
        fileUrl.value = '';
      }, 100);
    }
  }
);
// 方法定义
const renderedHandler = () => {
  console.log("渲染完成");
@@ -194,6 +155,15 @@
  margin: 0 auto;
}
.pdf-preview-wrapper {
  height: 100vh;
}
.pdf-preview-frame {
  width: 100%;
  height: 100%;
}
.oneLine {
  overflow: hidden;
  white-space: nowrap;
src/views/basicData/product/index.vue
@@ -144,10 +144,11 @@
            :data="upload.data"
            :on-success="handleDrawingUploadSuccess"
            :on-remove="handleDrawingRemove"
            :on-preview="handleDrawingPreview"
            :before-upload="handleDrawingBeforeUpload"
            :limit="5"
            accept=".pdf,.jpg,.jpeg,.png,.dwg"
            list-type="picture-card"
            list-type="text"
          >
            <el-icon class="avatar-uploader-icon"><Plus /></el-icon>
            <template #tip>
@@ -156,6 +157,29 @@
              </div>
            </template>
          </el-upload>
          <div v-if="drawingFileList.length" class="drawing-preview-list">
            <div
              v-for="file in drawingFileList"
              :key="file.uid || file.id || file.name"
              class="drawing-preview-card"
              @click="handleDrawingPreview(file)"
            >
              <img
                v-if="isImageFile(file)"
                :src="getDrawingFileUrl(file)"
                :alt="file.name"
                class="drawing-preview-image"
              />
              <div
                v-else
                class="drawing-preview-placeholder"
                :class="`is-${getDrawingFileExtension(file)}`"
              >
                {{ getDrawingFileExtension(file).toUpperCase() }}
              </div>
              <div class="drawing-preview-name">{{ file.name }}</div>
            </div>
          </div>
        </el-form-item>
      </el-form>
    </FormDialog>
@@ -194,6 +218,7 @@
        </template>
      </el-upload>
    </FormDialog>
    <filePreview ref="filePreviewRef" />
  </div>
</template>
@@ -204,6 +229,7 @@
import { Plus } from "@element-plus/icons-vue";
import { getToken } from "@/utils/auth.js";
import FormDialog from "@/components/Dialog/FormDialog.vue";
import filePreview from "@/components/filePreview/index.vue";
import {
  addOrEditProductModel,
  delProduct,
@@ -215,6 +241,7 @@
const { proxy } = getCurrentInstance();
const importUploadRef = ref(null);
const filePreviewRef = ref(null);
const modelDia = ref(false);
const importDia = ref(false);
@@ -617,6 +644,9 @@
  console.log('上传成功响应', response);
  console.log('response.data', response.data);
  if (response.code === 200) {
    file.url = response.data?.tempPath || file.url;
    file.name = response.data?.originalName || file.name;
    file.tempId = response.data?.tempId;
    // 支持多文件,追加到数组
    modelForm.value.tempFileIds.push(response.data?.tempId);
    modelForm.value.salesLedgerFiles.push({
@@ -629,6 +659,32 @@
  } else {
    proxy.$modal.msgError(response.msg || "上传失败");
  }
};
const getDrawingFileUrl = (file) => {
  return file.url || file.response?.data?.tempPath || file.tempPath || "";
};
const getDrawingFileName = (file) => {
  return file.name || file.originalName || getDrawingFileUrl(file).split("/").pop() || "";
};
const getDrawingFileExtension = (file) => {
  const name = getDrawingFileName(file).split("?")[0];
  const nameParts = name.split(".");
  return nameParts.length > 1 ? nameParts.pop().toLowerCase() : "file";
};
const isImageFile = (file) => {
  return ["jpg", "jpeg", "png", "gif", "bmp", "webp"].includes(getDrawingFileExtension(file));
};
const handleDrawingPreview = (file) => {
  const fileUrl = getDrawingFileUrl(file);
  if (!fileUrl) {
    return;
  }
  filePreviewRef.value?.open(fileUrl);
};
const handleDrawingRemove = (file) => {
@@ -698,15 +754,76 @@
.avatar-uploader-icon {
  font-size: 28px;
  color: #8c939d;
  width: 148px;
  height: 148px;
  width: 88px;
  height: 88px;
  text-align: center;
  line-height: 148px;
  line-height: 88px;
}
:deep(.el-upload--picture-card) {
  width: 148px;
  height: 148px;
:deep(.el-upload--text) {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 88px;
  height: 88px;
  border: 1px dashed #dcdfe6;
  border-radius: 8px;
}
:deep(.el-upload-list--text) {
  margin-top: 8px;
}
.drawing-preview-list {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: 12px;
}
.drawing-preview-card {
  width: 120px;
  cursor: pointer;
}
.drawing-preview-image,
.drawing-preview-placeholder {
  width: 120px;
  height: 120px;
  border: 1px solid #dcdfe6;
  border-radius: 8px;
  background: #f5f7fa;
}
.drawing-preview-image {
  object-fit: cover;
}
.drawing-preview-placeholder {
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 24px;
  font-weight: 600;
  color: #606266;
}
.drawing-preview-placeholder.is-pdf {
  color: #f56c6c;
  background: #fef0f0;
}
.drawing-preview-placeholder.is-dwg {
  color: #409eff;
  background: #ecf5ff;
}
.drawing-preview-name {
  margin-top: 6px;
  font-size: 12px;
  line-height: 1.4;
  color: #606266;
  word-break: break-all;
}
:deep(.el-upload__tip) {