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