From f0c7f4845fb40bb75b2c9eb61a790e9b8ea7401a Mon Sep 17 00:00:00 2001
From: zhangwei <1504152376@qq.com>
Date: 星期三, 27 八月 2025 11:25:43 +0800
Subject: [PATCH] 'feat上传附件及预览文件'

---
 src/views/system/dept/detail.vue          |  179 ++++++++++++++++++++++++++++++++---
 vite.config.ts                            |    1 
 src/views/system/dept/uploadform.vue      |   56 +++++++---
 src/views/system/dept/utils/hook.tsx      |    5 
 src/views/system/dept/utils/types.ts      |    1 
 build/plugins.ts                          |    2 
 package.json                              |    1 
 src/views/system/component/pdfPreview.vue |   38 ++++++-
 src/views/system/dept/utils/detail.tsx    |    4 
 src/api/item/index.ts                     |    5 -
 10 files changed, 242 insertions(+), 50 deletions(-)

diff --git a/build/plugins.ts b/build/plugins.ts
index 93f5981..060b568 100644
--- a/build/plugins.ts
+++ b/build/plugins.ts
@@ -12,6 +12,7 @@
 import removeConsole from "vite-plugin-remove-console";
 import { codeInspectorPlugin } from "code-inspector-plugin";
 import { vitePluginFakeServer } from "vite-plugin-fake-server";
+import basicSsl from "@vitejs/plugin-basic-ssl";
 
 export function getPluginsList(
   VITE_CDN: boolean,
@@ -19,6 +20,7 @@
 ): PluginOption[] {
   const lifecycle = process.env.npm_lifecycle_event;
   return [
+    basicSsl(),
     tailwindcss(),
     vue(),
     // jsx銆乼sx璇硶鏀寔
diff --git a/package.json b/package.json
index 484a473..1a7302e 100644
--- a/package.json
+++ b/package.json
@@ -88,6 +88,7 @@
     "@types/path-browserify": "^1.0.3",
     "@types/qs": "^6.9.18",
     "@types/sortablejs": "^1.15.8",
+    "@vitejs/plugin-basic-ssl": "^2.1.0",
     "@vitejs/plugin-vue": "^5.2.3",
     "@vitejs/plugin-vue-jsx": "^4.1.2",
     "boxen": "^8.0.1",
diff --git a/src/api/item/index.ts b/src/api/item/index.ts
index 143fe1a..b4c9771 100644
--- a/src/api/item/index.ts
+++ b/src/api/item/index.ts
@@ -111,11 +111,6 @@
 };
 
 // 鎷涙爣浠g悊鍒嗛〉鏌ヨ闈炴斂搴滆鍗曞鐞�
-export const findWechatOpenId = (data?: object) => {
-  return http.request<PageResult>("post", baseUrlApi(""), {
-    data
-  });
-};
 
 // 閲囪喘浠g悊浜哄鍔犻潪鏀垮簻璁㈠崟澶勭悊鑾峰彇鑱旂郴鏂瑰紡
 export const addgetcontact = () => {
diff --git a/src/views/system/component/pdfPreview.vue b/src/views/system/component/pdfPreview.vue
index 54cdfa1..8681f05 100644
--- a/src/views/system/component/pdfPreview.vue
+++ b/src/views/system/component/pdfPreview.vue
@@ -6,7 +6,6 @@
   >
     <iframe
       id="printIframe"
-      :src="pdfSrc"
       frameborder="0"
       style="width: 100%; height: 100%"
       @load="iframeLoaded"
@@ -16,10 +15,14 @@
 
 <script setup lang="ts">
 import { ref, defineProps } from "vue";
-defineProps({
-  pdfSrc: {
-    type: String,
-    default: ""
+const props = defineProps({
+  // fileInfo: {
+  //   type: String,
+  //   default: ""
+  // }
+  fileInfo: {
+    type: Object,
+    required: true
   }
 });
 let isLoading = ref(true);
@@ -28,6 +31,31 @@
 
   isLoading.value = false;
 };
+console.log(props.fileInfo, "props.fileInfo");
+
+const pdfUrl = props.fileInfo.filePath;
+// 鐢╢etch鑾峰彇鏂囦欢娴侊紝寮哄埗杞负棰勮鏍煎紡
+fetch(pdfUrl)
+  .then(response => {
+    // 妫�鏌ュ搷搴旀槸鍚︽垚鍔�
+    if (!response.ok) throw new Error("鏂囦欢鑾峰彇澶辫触");
+    // 寮哄埗鑾峰彇Blob瀵硅薄锛堟寚瀹歅DF绫诲瀷锛�
+    return response.blob();
+  })
+  .then(blob => {
+    // 鐢熸垚涓存椂棰勮URL锛堟祻瑙堝櫒鏈湴涓存椂閾炬帴锛屾棤涓嬭浇瑙﹀彂锛�
+    const blobUrl = URL.createObjectURL(
+      new Blob([blob], { type: "application/pdf" }) // 鏄庣‘鎸囧畾PDF绫诲瀷
+    );
+    // 璧嬪�肩粰iframe骞舵樉绀�
+    const iframe = document.getElementById("printIframe");
+    iframe.src = blobUrl;
+    iframe.style.display = "block";
+    document.getElementById("loading").style.display = "none";
+  })
+  .catch(error => {
+    // document.getElementById("loading").innerText = `鍔犺浇澶辫触锛�${error.message}`;
+  });
 </script>
 <style>
 .pdf-container {
diff --git a/src/views/system/dept/detail.vue b/src/views/system/dept/detail.vue
index 2cb6698..1e3f834 100644
--- a/src/views/system/dept/detail.vue
+++ b/src/views/system/dept/detail.vue
@@ -11,6 +11,11 @@
 interface Emits {
   (e: "backListPage"): void;
 }
+import MaterialIconThemePdf from "~icons/material-icon-theme/pdf";
+import MaterialIconThemeImage from "~icons/material-icon-theme/image";
+import MaterialIconThemeWord from "~icons/material-icon-theme/word";
+import MaterialIconThemeTable from "~icons/material-icon-theme/table";
+import MaterialIconThemeZip from "~icons/material-icon-theme/zip";
 const emit = defineEmits<Emits>();
 const props = defineProps({
   nowID: null
@@ -23,26 +28,79 @@
 defineOptions({
   name: "itemdetail"
 });
+const convertFujianToObjects = (fujianStr, fujianNameStr) => {
+  // 鍒嗗壊瀛楃涓蹭负鏁扮粍骞惰繃婊ょ┖鍊�
+  const srcArray = fujianStr.split(",").filter(Boolean);
+  const nameArray = fujianNameStr.split(",").filter(Boolean);
+
+  // 鎻愬彇鏂囦欢鍚庣紑浣滀负valu
+  const getFileExtension = fileName => {
+    const lastDotIndex = fileName.lastIndexOf(".");
+    // 濡傛灉娌℃湁鍚庣紑鎴栨枃浠跺悕浠ョ偣缁撳熬锛岃繑鍥炵┖瀛楃涓�
+    if (lastDotIndex === -1 || lastDotIndex === fileName.length - 1) {
+      return "";
+    }
+    return fileName.slice(lastDotIndex + 1).toLowerCase();
+  };
+
+  // 鏄犲皠涓虹洰鏍囧璞℃暟缁�
+  return srcArray.map((src, index) => {
+    // 纭繚鍚嶇О鏁扮粍鏈夊搴旂储寮曠殑鍏冪礌
+    const name = nameArray[index]?.trim() || `鏈煡鏂囦欢${index + 1}`;
+
+    return {
+      name: name,
+      filePath: src.trim(),
+      fileType: getFileExtension(name)
+    };
+  });
+};
 onMounted(async () => {
   let res = await getTenderOrderDetail({ id: props.nowID });
   state.nowInfo = res.result;
+  if (state.nowInfo.fujian) {
+    state.nowInfo.fujianList = convertFujianToObjects(
+      state.nowInfo.fujian,
+      state.nowInfo.fujianName
+    );
+  }
 });
 const backListPage = () => {
   emit("backListPage");
 };
 const previewPdf = pdfUrl => {
-  addDialog({
-    title: `棰勮pdf`,
-    props: {},
-    width: "60%",
-    draggable: true,
-    fullscreen: deviceDetection(),
-    fullscreenIcon: true,
-    sureBtnLoading: true,
-    closeOnClickModal: false,
-    contentRenderer: () => h(pdfPreview, { pdfSrc: pdfUrl })
-    // jsx 璇硶 锛堟敞鎰忓湪.vue鏂囦欢鍚敤jsx璇硶锛岄渶瑕佸湪script寮�鍚痩ang="tsx"锛�
-  });
+  console.log(pdfUrl, "pdfUrl");
+
+  switch (pdfUrl.fileType) {
+    case "png":
+      showImg(pdfUrl.filePath);
+      break;
+    case "jepg":
+      showImg(pdfUrl.filePath);
+      break;
+    case "pdf":
+      addDialog({
+        title: `棰勮pdf`,
+        props: {},
+        width: "60%",
+        draggable: true,
+        fullscreen: deviceDetection(),
+        fullscreenIcon: true,
+        sureBtnLoading: true,
+        closeOnClickModal: false,
+        contentRenderer: () => h(pdfPreview, { fileInfo: pdfUrl })
+        // jsx 璇硶 锛堟敞鎰忓湪.vue鏂囦欢鍚敤jsx璇硶锛岄渶瑕佸湪script寮�鍚痩ang="tsx"锛�
+      });
+      break;
+    default:
+      window.location.href = pdfUrl.filePath;
+      break;
+  }
+};
+const showPreview = ref(false);
+const showImg = (name: string | number) => {
+  showPreview.value = true;
+  state.srcList = [name];
 };
 </script>
 
@@ -135,6 +193,7 @@
                     </el-button>
                     <el-button
                       v-if="state.nowInfo.zhaobiaowenjian"
+                      :disabled="!!state.nowInfo.changeOrder"
                       type="primary"
                       plain
                       size="small"
@@ -142,20 +201,96 @@
                     >
                       涓婁紶鍙樻洿鍏憡
                     </el-button>
+                    <el-button
+                      type="primary"
+                      plain
+                      size="small"
+                      @click="changeDialog('涓婁紶鍙樻洿', state.nowInfo)"
+                    >
+                      淇敼鏍囬
+                    </el-button>
                   </el-form-item>
                   <el-form-item v-if="state.nowInfo.zhaobiaowenjian" label=" ">
                     <div class="border-1 w-[100%] rounded-md p-3">
                       <p>{{ state.nowInfo.projectName }}</p>
-                      <p>涓婁紶鏃堕棿锛�2025-8-12 13:41:00</p>
-                      <el-button
+                      <p>涓婁紶鏃堕棿锛歿{ state.nowInfo.fabuDate }}</p>
+                      <p
+                        class="flex items-center cursor-pointer"
+                        @click="
+                          previewPdf({
+                            name: state.nowInfo.zhaobiaowenjian,
+                            filePath: state.nowInfo.zhaobiaowenjianName,
+                            fileType: 'pdf'
+                          })
+                        "
+                      >
+                        鎷涙爣鏂囦欢锛�<MaterialIconThemePdf
+                          style="font-size: 1.5em"
+                        />{{ state.nowInfo.zhaobiaowenjianName }}
+                      </p>
+                      <p
+                        v-if="state.nowInfo?.changeOrder"
+                        class="flex items-center cursor-pointer"
+                        @click="
+                          previewPdf({
+                            name: state.nowInfo.changeOrder.biangengwenjianName,
+                            filePath: state.nowInfo.changeOrder.biangengwenjian,
+                            fileType: 'pdf'
+                          })
+                        "
+                      >
+                        鍙樻洿鍏憡锛�
+                        <MaterialIconThemePdf style="font-size: 1.5em" />
+                        {{ state.nowInfo.changeOrder.biangengwenjianName }}
+                      </p>
+                      <div v-if="state.nowInfo.fujian" class="flex">
+                        闄勪欢锛�
+                        <div>
+                          <p
+                            v-for="item in state.nowInfo.fujianList"
+                            :key="item.src"
+                            class="flex items-center cursor-pointer"
+                            @click="previewPdf(item)"
+                          >
+                            <MaterialIconThemeImage
+                              v-if="
+                                item.fileType == 'png' ||
+                                item.fileType == 'jepg'
+                              "
+                              style="font-size: 1.5em"
+                            />
+                            <MaterialIconThemePdf
+                              v-else-if="item.fileType == 'pdf'"
+                              style="font-size: 1.5em"
+                            />
+                            <MaterialIconThemeTable
+                              v-else-if="item.fileType == 'xlsx'"
+                              style="font-size: 1.5em"
+                            />
+                            <MaterialIconThemeWord
+                              v-else-if="
+                                item.fileType == 'doc' ||
+                                item.fileType == 'docx'
+                              "
+                              style="font-size: 1.5em"
+                            />
+                            <MaterialIconThemeZip
+                              v-else
+                              style="font-size: 1.5em"
+                            />
+                            {{ item.name }}
+                          </p>
+                        </div>
+                      </div>
+                      <!-- <el-button
                         type="primary"
                         plain
                         size="small"
                         @click="previewPdf(state.nowInfo.zhaobiaowenjian)"
                       >
                         鐐瑰嚮棰勮
-                      </el-button>
-                      <el-button
+                      </el-button> -->
+                      <!-- <el-button
                         v-if="state.nowInfo?.changeOrder"
                         type="primary"
                         plain
@@ -165,15 +300,15 @@
                         "
                       >
                         鐐瑰嚮棰勮鍙樻洿鍏憡
-                      </el-button>
-                      <el-button
+                      </el-button> -->
+                      <!-- <el-button
                         type="primary"
                         plain
                         size="small"
                         @click="changeDialog('涓婁紶鍙樻洿', state.nowInfo)"
                       >
                         淇敼鏍囬
-                      </el-button>
+                      </el-button> -->
                     </div>
                   </el-form-item>
                   <!-- <el-form-item label="纾嬪晢鏂囦欢锛�">
@@ -242,6 +377,12 @@
         </el-tabs>
       </el-card>
     </div>
+    <el-image-viewer
+      v-if="showPreview"
+      :url-list="state.srcList"
+      show-progress
+      @close="showPreview = false"
+    />
   </div>
 </template>
 
diff --git a/src/views/system/dept/uploadform.vue b/src/views/system/dept/uploadform.vue
index f21bd75..18d67cf 100644
--- a/src/views/system/dept/uploadform.vue
+++ b/src/views/system/dept/uploadform.vue
@@ -27,6 +27,7 @@
     zhaobiaowenjianName: "",
     biangengwenjian: "",
     fujian: "", // 闄勪欢锛堝彲閫夛紝鏈�澶ч暱搴�512瀛楃锛屽彲涓虹┖锛�
+    fujianName: "", // 闄勪欢锛堝彲閫夛紝鏈�澶ч暱搴�512瀛楃锛屽彲涓虹┖锛�
     kaibiaodidian: "" // 寮�鏍囧湴鐐癸紙蹇呭~锛岄暱搴�1-250瀛楃锛�
   }),
   isChange: null,
@@ -116,6 +117,7 @@
 const newFormInline = ref(props.formInline);
 const validateForm = reactive({
   fileList: [],
+  fileListFile: [],
   date: ""
 });
 const upload = ref<UploadInstance>();
@@ -159,22 +161,41 @@
   fetchCredentials(file);
   // upload.value!.submit();
 };
-const handleChangeFile = file => {
-  console.log(file);
-
+const handleChangeFile = async file => {
   if (file.status !== "ready") return;
-  // let suffName = file.name.substring(file.name.lastIndexOf(".") + 1);
-  // const extension = suffName === "pdf";
-  // // const isLt10M = file.size / 1024 / 1024 < 10;
-  // if (!extension) {
-  //   message(`浠呮敮鎸乸df鏍煎紡锛岃涓婁紶pdf`, {
-  //     type: "error"
-  //   });
-  //   validateForm.fileList = [];
-  //   return false;
-  // }
+  // const isLt10M = file.size / 1024 / 1024 < 10;
   // fetchCredentials(file);
-  // upload.value!.submit();
+  // 杩欓噷搴旇皟鐢ㄤ綘鑷繁鐨勫悗绔帴鍙h幏鍙栦复鏃跺嚟璇�
+  let res = await getUploadToken();
+  if (res.code == 200) {
+    let keyVal = generateTimestampWithRandom(res.result.DirPath, file.name);
+    let upUrl = res.result.url;
+    let upPath = res.result.DirPath;
+    let formData = new FormData();
+    formData.append("policy", res.result.policy);
+    formData.append(
+      "x-oss-signature-version",
+      res.result.x_oss_signature_version
+    );
+    formData.append("x-oss-credential", res.result.x_oss_credential);
+    formData.append("x-oss-date", res.result.x_oss_date);
+    // formData.append("Signature", res.result.signature);
+    formData.append("x-oss-signature", res.result.signature);
+    formData.append("x-oss-security-token", res.result.security_token);
+    // formData.append("x-oss-content-type", "application/pdf");
+    formData.append("success_action_status", "200");
+    formData.append("key", keyVal); // 鏂囦欢鍚�
+    formData.append("file", file.raw); // file 蹇呴』涓烘渶鍚庝竴涓〃鍗曞煙
+    uploadFileAli(formData, res.result.url).then(res => {
+      let path = `${upUrl}${keyVal}`;
+      newFormInline.value.fujian += newFormInline.value.fujian
+        ? `,${path}`
+        : path;
+      newFormInline.value.fujianName += newFormInline.value.fujianName
+        ? `,${file.name}`
+        : file.name;
+    });
+  }
 };
 // state.formDataNew = {
 //   policy: res.result.policy, //琛ㄥ崟鍩�
@@ -267,7 +288,7 @@
     </el-row>
     <el-row v-else :gutter="30">
       <div v-if="props.isChange" style="width: 100%">
-        <re-col :value="24" :xs="24" :sm="24">
+        <!-- <re-col :value="24" :xs="24" :sm="24">
           <el-form-item label="鏍囬" prop="projectName">
             <el-input
               v-model="newFormInline.projectName"
@@ -275,7 +296,7 @@
               placeholder="璇疯緭鍏ユ爣棰�"
             />
           </el-form-item>
-        </re-col>
+        </re-col> -->
         <re-col :value="24" :xs="24" :sm="24">
           <el-form-item label="鍙樻洿鏂囦欢" prop="biangengwenjian">
             <el-upload
@@ -362,7 +383,7 @@
         <el-form-item label="闄勪欢" prop="">
           <el-upload
             ref="upload"
-            v-model:file-list="validateForm.fileList"
+            v-model:file-list="validateForm.fileListFile"
             multiple
             :on-exceed="handleExceed"
             :auto-upload="false"
@@ -393,6 +414,7 @@
 .el-date-editor.el-input__wrapper {
   width: 100%;
 }
+
 .upload__tip {
   width: 100%;
 }
diff --git a/src/views/system/dept/utils/detail.tsx b/src/views/system/dept/utils/detail.tsx
index 68ef1a9..6eded09 100644
--- a/src/views/system/dept/utils/detail.tsx
+++ b/src/views/system/dept/utils/detail.tsx
@@ -29,6 +29,7 @@
           kaibiaoDate: row?.kaibiaoDate ?? "", //寮�鏍囨椂闂�
           biangengwenjian: "", //鎷涙爣鏂囦欢
           fujian: row?.fujian ?? "", //闄勪欢
+          fujianName: row?.fujianName ?? "", //闄勪欢
           kaibiaodidian: row?.kaibiaodidian ?? "" //寮�鏍囧湴鐐�
         }
       },
@@ -180,7 +181,8 @@
       Authorization: `Bearer ${getToken()?.accessToken}`
     },
     nowInfo: Object as PropType<FormItemProps>,
-    formDataNew: {}
+    formDataNew: {},
+    srcList: []
   });
   //鐢熸垚鏃堕棿鎴�+闅忔満鏁�
   // 鐢熸垚鏃堕棿鎴�+闅忔満鏁扮殑鍑芥暟
diff --git a/src/views/system/dept/utils/hook.tsx b/src/views/system/dept/utils/hook.tsx
index 1aaa5a9..f603353 100644
--- a/src/views/system/dept/utils/hook.tsx
+++ b/src/views/system/dept/utils/hook.tsx
@@ -2,7 +2,7 @@
 import editForm from "../form.vue";
 import { handleTree } from "@/utils/tree";
 import { message } from "@/utils/message";
-import { zhaobiaoPageOrder, findWechatOpenId } from "@/api/item/index";
+import { zhaobiaoPageOrder } from "@/api/item/index";
 
 import {
   getCaigoufangshiList,
@@ -25,7 +25,7 @@
 import type { PaginationProps } from "@pureadmin/table";
 import { useUserStoreHook } from "@/store/modules/user";
 
-import pdfPreview from "../../component/pdfPreview.vue";
+import pdfPreview from "../../component/pdfPreview2.vue";
 // const nowRole = computed(() => {
 //   return useUserStoreHook().nowRole;
 // });
@@ -315,7 +315,6 @@
     }
   };
   async function onSearch() {
-    findWechatOpenId();
     const obj = cloneDeep(form);
     obj.tousu = obj.tousu.join("");
     obj.zhiyi = obj.zhiyi.join("");
diff --git a/src/views/system/dept/utils/types.ts b/src/views/system/dept/utils/types.ts
index e0289a5..4654639 100644
--- a/src/views/system/dept/utils/types.ts
+++ b/src/views/system/dept/utils/types.ts
@@ -55,6 +55,7 @@
   biangengwenjianName?: string | null | undefined;
   // 闄勪欢锛屽彲涓虹┖锛屾渶澶ч暱搴�512瀛楃
   fujian?: string;
+  fujianName?: string;
   // 寮�鏍囧湴鐐癸紝闀垮害1-250瀛楃
   kaibiaodidian: string;
 }
diff --git a/vite.config.ts b/vite.config.ts
index 81216e4..fd9b5e0 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -20,6 +20,7 @@
     },
     // 鏈嶅姟绔覆鏌�
     server: {
+      https: true, // 鍚敤 HTTPS
       // 绔彛鍙�
       port: VITE_PORT,
       host: "0.0.0.0",

--
Gitblit v1.9.1