From f07cf2548995aa2456e6da01047069c12f1f4b33 Mon Sep 17 00:00:00 2001 From: "DESKTOP-1R2VSQH\\Lenovo ThinkPad E490" Date: Fri, 8 May 2026 17:39:01 +0700 Subject: [PATCH 1/7] refactor(registry): downloadBlobFile --- .../01_Information/02_ChangeName.vue | 43 ++------------ .../10_registry/01_Information/06_Ability.vue | 17 ++---- .../02_Government/02_Discipline.vue | 18 ++---- .../10_registry/02_Government/04_Duty.vue | 18 ++---- .../02_Government/06_Assistance.vue | 17 ++---- .../10_registry/03_Salary/02_Nopaid.vue | 17 ++---- .../04_Achievement/01_Certificate.vue | 18 ++---- .../04_Achievement/03_Insignia.vue | 17 ++---- .../10_registry/04_Achievement/04_Honor.vue | 17 ++---- src/modules/10_registry/utils/downloadFile.ts | 59 +++++++++++++++++++ 10 files changed, 103 insertions(+), 138 deletions(-) create mode 100644 src/modules/10_registry/utils/downloadFile.ts diff --git a/src/modules/10_registry/01_Information/02_ChangeName.vue b/src/modules/10_registry/01_Information/02_ChangeName.vue index dc2b645..165f95a 100644 --- a/src/modules/10_registry/01_Information/02_ChangeName.vue +++ b/src/modules/10_registry/01_Information/02_ChangeName.vue @@ -3,6 +3,7 @@ import { ref, onMounted } from "vue"; import { useCounterMixin } from "@/stores/mixin"; import { useDataStore } from "@/stores/data"; +import { downloadBlobFile } from "@/modules/10_registry/utils/downloadFile"; import http from "@/plugins/http"; import config from "@/app.config"; @@ -137,46 +138,10 @@ async function onDownloadFile(id: string, profileId: string) { ) .then(async (res) => { const downloadUrl = res.data.downloadUrl; - const response = await fetch(downloadUrl); - const blob = await response.blob(); - - const contentType: string | null = response.headers.get("Content-Type"); - - // 2. สร้างตัวแปลง MIME Type เป็นนามสกุลไฟล์ - const extensionMap: Record = { - "application/pdf": "pdf", - "image/jpeg": "jpg", - "image/png": "png", - "image/gif": "gif", - "application/zip": "zip", - "application/vnd.openxmlformats-officedocument.wordprocessingml.document": - "docx", - "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": - "xlsx", - }; - - let extension = contentType ? extensionMap[contentType] : undefined; - - if (!extension) { - const urlWithoutQuery = downloadUrl.split("?")[0]; - extension = urlWithoutQuery.includes(".") - ? urlWithoutQuery.split(".").pop() - : "pdf"; - } - - const blobForDownload = new Blob([blob], { - type: "application/octet-stream", + await downloadBlobFile({ + downloadUrl: downloadUrl, + fileName: `ประวัติการเปลี่ยนชื่อ-นามสกุล`, }); - const url = URL.createObjectURL(blobForDownload); - const link = document.createElement("a"); - link.href = url; - link.download = `ประวัติการเปลี่ยนชื่อ-นามสกุล.${extension}`; - document.body.appendChild(link); - link.click(); - setTimeout(() => { - document.body.removeChild(link); - URL.revokeObjectURL(url); - }, 100); }) .catch((err) => { messageError($q, err); diff --git a/src/modules/10_registry/01_Information/06_Ability.vue b/src/modules/10_registry/01_Information/06_Ability.vue index 5254633..ffcb8e0 100644 --- a/src/modules/10_registry/01_Information/06_Ability.vue +++ b/src/modules/10_registry/01_Information/06_Ability.vue @@ -6,6 +6,7 @@ import http from "@/plugins/http"; import config from "@/app.config"; import { useCounterMixin } from "@/stores/mixin"; import { useDataStore } from "@/stores/data"; +import { downloadBlobFile } from "@/modules/10_registry/utils/downloadFile"; /** import type */ import type { AbilityRows } from "@/modules/10_registry/interface/index/Main"; @@ -263,18 +264,10 @@ async function onDownloadFile(id: string, profileId: string) { ) .then(async (res) => { const downloadUrl = res.data.downloadUrl; - const response = await fetch(downloadUrl); - const blob = await response.blob(); - const url = URL.createObjectURL(blob); - const link = document.createElement("a"); - link.href = url; - link.download = `เอกสารความสามารถพิเศษ_`; - document.body.appendChild(link); - link.click(); - setTimeout(() => { - document.body.removeChild(link); - URL.revokeObjectURL(url); - }, 100); + await downloadBlobFile({ + downloadUrl: downloadUrl, + fileName: `เอกสารความสามารถพิเศษ`, + }); }) .catch((err) => { messageError($q, err); diff --git a/src/modules/10_registry/02_Government/02_Discipline.vue b/src/modules/10_registry/02_Government/02_Discipline.vue index 21dc522..2d6b4d0 100644 --- a/src/modules/10_registry/02_Government/02_Discipline.vue +++ b/src/modules/10_registry/02_Government/02_Discipline.vue @@ -7,6 +7,7 @@ import config from "@/app.config"; import { useCounterMixin } from "@/stores/mixin"; import { useDataStore } from "@/stores/data"; import { useRegistryDataStore } from "@/modules/10_registry/store/Main"; +import { downloadBlobFile } from "@/modules/10_registry/utils/downloadFile"; import type { DisciplineDetail } from "@/modules/10_registry/interface/index/Main"; @@ -195,19 +196,10 @@ async function onDownloadFile(id: string, profileId: string) { showLoader(); try { const res = await getPathUploadFlie(fileGroup.value, profileId, id); - const downloadUrl = res.downloadUrl; - const response = await fetch(downloadUrl); - const blob = await response.blob(); - const url = URL.createObjectURL(blob); - const link = document.createElement("a"); - link.href = url; - link.download = `เอกสารวินัย`; - document.body.appendChild(link); - link.click(); - setTimeout(() => { - document.body.removeChild(link); - URL.revokeObjectURL(url); - }, 100); + await downloadBlobFile({ + downloadUrl: res.downloadUrl, + fileName: `เอกสารวินัย`, + }); } catch (e) { messageError($q, e); } finally { diff --git a/src/modules/10_registry/02_Government/04_Duty.vue b/src/modules/10_registry/02_Government/04_Duty.vue index 7b2c1e7..a64dc34 100644 --- a/src/modules/10_registry/02_Government/04_Duty.vue +++ b/src/modules/10_registry/02_Government/04_Duty.vue @@ -7,6 +7,7 @@ import config from "@/app.config"; import { useCounterMixin } from "@/stores/mixin"; import { useDataStore } from "@/stores/data"; import { useRegistryDataStore } from "@/modules/10_registry/store/Main"; +import { downloadBlobFile } from "@/modules/10_registry/utils/downloadFile"; import type { DutyFormType } from "@/modules/10_registry/interface/index/Main"; @@ -298,19 +299,10 @@ async function onDownloadFile(id: string, profileId: string) { showLoader(); try { const res = await getPathUploadFlie(fileGroup.value, profileId, id); - const downloadUrl = res.downloadUrl; - const response = await fetch(downloadUrl); - const blob = await response.blob(); - const url = URL.createObjectURL(blob); - const link = document.createElement("a"); - link.href = url; - link.download = `เอกสารปฏิบัติราชการพิเศษ`; - document.body.appendChild(link); - link.click(); - setTimeout(() => { - document.body.removeChild(link); - URL.revokeObjectURL(url); - }, 100); + await downloadBlobFile({ + downloadUrl: res.downloadUrl, + fileName: `เอกสารปฏิบัติราชการพิเศษ`, + }); } catch (e) { messageError($q, e); } finally { diff --git a/src/modules/10_registry/02_Government/06_Assistance.vue b/src/modules/10_registry/02_Government/06_Assistance.vue index 02ad925..69d5184 100644 --- a/src/modules/10_registry/02_Government/06_Assistance.vue +++ b/src/modules/10_registry/02_Government/06_Assistance.vue @@ -6,6 +6,7 @@ import http from "@/plugins/http"; import config from "@/app.config"; import { useCounterMixin } from "@/stores/mixin"; import { useDataStore } from "@/stores/data"; +import { downloadBlobFile } from "@/modules/10_registry/utils/downloadFile"; import type { DutyFormType } from "@/modules/10_registry/interface/index/Main"; @@ -307,18 +308,10 @@ async function onDownloadFile(id: string, profileId: string) { ) .then(async (res) => { const downloadUrl = res.data.downloadUrl; - const response = await fetch(downloadUrl); - const blob = await response.blob(); - const url = URL.createObjectURL(blob); - const link = document.createElement("a"); - link.href = url; - link.download = `เอกสารช่วยราชการ`; - document.body.appendChild(link); - link.click(); - setTimeout(() => { - document.body.removeChild(link); - URL.revokeObjectURL(url); - }, 100); + await downloadBlobFile({ + downloadUrl: downloadUrl, + fileName: `เอกสารช่วยราชการ`, + }); }) .catch((err) => { messageError($q, err); diff --git a/src/modules/10_registry/03_Salary/02_Nopaid.vue b/src/modules/10_registry/03_Salary/02_Nopaid.vue index 8d81c30..271d3d9 100644 --- a/src/modules/10_registry/03_Salary/02_Nopaid.vue +++ b/src/modules/10_registry/03_Salary/02_Nopaid.vue @@ -7,6 +7,7 @@ import config from "@/app.config"; import { useCounterMixin } from "@/stores/mixin"; import { useDataStore } from "@/stores/data"; import { useRegistryDataStore } from "@/modules/10_registry/store/Main"; +import { downloadBlobFile } from "@/modules/10_registry/utils/downloadFile"; import type { NopaidFormType } from "@/modules/10_registry/interface/index/Main"; @@ -280,18 +281,10 @@ async function onDownloadFile(id: string, profileId: string) { try { const res = await getPathUploadFlie(fileGroup.value, profileId, id); const downloadUrl = res.downloadUrl; - const response = await fetch(downloadUrl); - const blob = await response.blob(); - const url = URL.createObjectURL(blob); - const link = document.createElement("a"); - link.href = url; - link.download = `บันทึกวันที่ไม่ได้รับ${salaryText.value}ฯ`; - document.body.appendChild(link); - link.click(); - setTimeout(() => { - document.body.removeChild(link); - URL.revokeObjectURL(url); - }, 100); + await downloadBlobFile({ + downloadUrl: downloadUrl, + fileName: `บันทึกวันที่ไม่ได้รับ${salaryText.value}ฯ`, + }); } catch (e) { messageError($q, e); } finally { diff --git a/src/modules/10_registry/04_Achievement/01_Certificate.vue b/src/modules/10_registry/04_Achievement/01_Certificate.vue index 21a6eeb..5e0b4c7 100644 --- a/src/modules/10_registry/04_Achievement/01_Certificate.vue +++ b/src/modules/10_registry/04_Achievement/01_Certificate.vue @@ -7,6 +7,7 @@ import config from "@/app.config"; import { useCounterMixin } from "@/stores/mixin"; import { useDataStore } from "@/stores/data"; import { useRegistryDataStore } from "@/modules/10_registry/store/Main"; +import { downloadBlobFile } from "@/modules/10_registry/utils/downloadFile"; import type { CertificateDetail } from "@/modules/10_registry/interface/index/Main"; @@ -278,19 +279,10 @@ async function onDownloadFile(id: string, profileId: string) { showLoader(); try { const data = await getPathUploadFlie(fileGroup.value, profileId, id); - const downloadUrl = data.downloadUrl; - const response = await fetch(downloadUrl); - const blob = await response.blob(); - const url = URL.createObjectURL(blob); - const link = document.createElement("a"); - link.href = url; - link.download = `เอกสารใบอนุญาตประกอบวิชาชีพ`; - document.body.appendChild(link); - link.click(); - setTimeout(() => { - document.body.removeChild(link); - URL.revokeObjectURL(url); - }, 100); + await downloadBlobFile({ + downloadUrl: data.downloadUrl, + fileName: `เอกสารใบอนุญาตประกอบวิชาชีพ`, + }); } catch (error) { messageError($q, error); } finally { diff --git a/src/modules/10_registry/04_Achievement/03_Insignia.vue b/src/modules/10_registry/04_Achievement/03_Insignia.vue index 8db5851..2acb679 100644 --- a/src/modules/10_registry/04_Achievement/03_Insignia.vue +++ b/src/modules/10_registry/04_Achievement/03_Insignia.vue @@ -7,6 +7,7 @@ import config from "@/app.config"; import { useCounterMixin } from "@/stores/mixin"; import { useDataStore } from "@/stores/data"; import { useRegistryDataStore } from "@/modules/10_registry/store/Main"; +import { downloadBlobFile } from "@/modules/10_registry/utils/downloadFile"; import type { InsigniaFormType } from "@/modules/10_registry/interface/index/Main"; @@ -494,18 +495,10 @@ async function onDownloadFile(id: string, profileId: string) { showLoader(); try { const data = await getPathUploadFlie(fileGroup.value, profileId, id); - const response = await fetch(data.downloadUrl); - const blob = await response.blob(); - const url = URL.createObjectURL(blob); - const link = document.createElement("a"); - link.href = url; - link.download = `เอกสารเครื่องราชอิสริยาภรณ์`; - document.body.appendChild(link); - link.click(); - setTimeout(() => { - document.body.removeChild(link); - URL.revokeObjectURL(url); - }, 100); + await downloadBlobFile({ + downloadUrl: data.downloadUrl, + fileName: `เอกสารเครื่องราชอิสริยาภรณ์`, + }); } catch (error) { messageError($q, error); } finally { diff --git a/src/modules/10_registry/04_Achievement/04_Honor.vue b/src/modules/10_registry/04_Achievement/04_Honor.vue index dee78b9..a142ad7 100644 --- a/src/modules/10_registry/04_Achievement/04_Honor.vue +++ b/src/modules/10_registry/04_Achievement/04_Honor.vue @@ -7,6 +7,7 @@ import config from "@/app.config"; import { useCounterMixin } from "@/stores/mixin"; import { useDataStore } from "@/stores/data"; import { useRegistryDataStore } from "@/modules/10_registry/store/Main"; +import { downloadBlobFile } from "@/modules/10_registry/utils/downloadFile"; import type { HonorFormData } from "@/modules/10_registry/interface/index/Main"; @@ -278,18 +279,10 @@ async function onDownloadFile(id: string, profileId: string) { showLoader(); try { const data = await getPathUploadFlie(fileGroup.value, profileId, id); - const response = await fetch(data.downloadUrl); - const blob = await response.blob(); - const url = URL.createObjectURL(blob); - const link = document.createElement("a"); - link.href = url; - link.download = `เอกสารประกาศเกียรติคุณ`; - document.body.appendChild(link); - link.click(); - setTimeout(() => { - document.body.removeChild(link); - URL.revokeObjectURL(url); - }, 100); + await downloadBlobFile({ + downloadUrl: data.downloadUrl, + fileName: `เอกสารประกาศเกียรติคุณ`, + }); } catch (error) { messageError($q, error); } finally { diff --git a/src/modules/10_registry/utils/downloadFile.ts b/src/modules/10_registry/utils/downloadFile.ts new file mode 100644 index 0000000..341b7f9 --- /dev/null +++ b/src/modules/10_registry/utils/downloadFile.ts @@ -0,0 +1,59 @@ +export interface DownloadFileOptions { + downloadUrl: string; + fileName: string; +} + +const isMobile = + /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test( + navigator.userAgent, + ); + +export async function downloadBlobFile({ + downloadUrl, + fileName, +}: DownloadFileOptions): Promise { + // Use window.open for desktop, blob download for mobile + if (!isMobile) { + window.open(downloadUrl, "_blank"); + return; + } + + const response = await fetch(downloadUrl); + const blob = await response.blob(); + + const contentType: string | null = response.headers.get("Content-Type"); + + const extensionMap: Record = { + "application/pdf": "pdf", + "image/jpeg": "jpg", + "image/png": "png", + "image/gif": "gif", + "application/zip": "zip", + "application/vnd.openxmlformats-officedocument.wordprocessingml.document": + "docx", + "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": "xlsx", + }; + + let extension = contentType ? extensionMap[contentType] : undefined; + + if (!extension) { + const urlWithoutQuery = downloadUrl.split("?")[0]; + extension = urlWithoutQuery.includes(".") + ? urlWithoutQuery.split(".").pop() + : "pdf"; + } + + const blobForDownload = new Blob([blob], { + type: "application/octet-stream", + }); + const url = URL.createObjectURL(blobForDownload); + const link = document.createElement("a"); + link.href = url; + link.download = `${fileName}.${extension}`; + document.body.appendChild(link); + link.click(); + setTimeout(() => { + document.body.removeChild(link); + URL.revokeObjectURL(url); + }, 100); +} From ebd514a33aa4dc6841cf36ea17535c2477794927 Mon Sep 17 00:00:00 2001 From: "DESKTOP-1R2VSQH\\Lenovo ThinkPad E490" Date: Fri, 8 May 2026 17:56:45 +0700 Subject: [PATCH 2/7] fix:downloadFileName --- src/modules/10_registry/05_Other/02_File.vue | 17 +++++------------ .../10_registry/05_Other/03_FileOther.vue | 17 +++++------------ src/modules/10_registry/utils/downloadFile.ts | 3 ++- 3 files changed, 12 insertions(+), 25 deletions(-) diff --git a/src/modules/10_registry/05_Other/02_File.vue b/src/modules/10_registry/05_Other/02_File.vue index 1be029f..bb9f287 100644 --- a/src/modules/10_registry/05_Other/02_File.vue +++ b/src/modules/10_registry/05_Other/02_File.vue @@ -6,6 +6,7 @@ import { ref, onMounted, watch } from "vue"; import http from "@/plugins/http"; import config from "@/app.config"; import { useRegistryInFormationStore } from "@/modules/10_registry/store/registry"; +import { downloadBlobFile } from "@/modules/10_registry/utils/downloadFile"; import type { FileFormType } from "@/modules/10_registry/interface/index/Main"; @@ -57,18 +58,10 @@ async function downloadFile(fileName: string) { ) .then(async (res) => { const downloadUrl = res.data.downloadUrl; - const response = await fetch(downloadUrl); - const blob = await response.blob(); - const url = URL.createObjectURL(blob); - const link = document.createElement("a"); - link.href = url; - link.download = fileName; - document.body.appendChild(link); - link.click(); - setTimeout(() => { - document.body.removeChild(link); - URL.revokeObjectURL(url); - }, 100); + await downloadBlobFile({ + downloadUrl: downloadUrl, + fileName: fileName, + }); }) .catch((e) => { messageError($q, e); diff --git a/src/modules/10_registry/05_Other/03_FileOther.vue b/src/modules/10_registry/05_Other/03_FileOther.vue index 05e740b..585e68c 100644 --- a/src/modules/10_registry/05_Other/03_FileOther.vue +++ b/src/modules/10_registry/05_Other/03_FileOther.vue @@ -6,6 +6,7 @@ import { useQuasar } from "quasar"; import http from "@/plugins/http"; import config from "@/app.config"; import { useRegistryInFormationStore } from "@/modules/10_registry/store/registry"; +import { downloadBlobFile } from "@/modules/10_registry/utils/downloadFile"; import type { FileFormType } from "@/modules/10_registry/interface/index/Main"; @@ -57,18 +58,10 @@ async function downloadFile(fileName: string) { ) .then(async (res) => { const downloadUrl = res.data.downloadUrl; - const response = await fetch(downloadUrl); - const blob = await response.blob(); - const url = URL.createObjectURL(blob); - const link = document.createElement("a"); - link.href = url; - link.download = fileName; - document.body.appendChild(link); - link.click(); - setTimeout(() => { - document.body.removeChild(link); - URL.revokeObjectURL(url); - }, 100); + await downloadBlobFile({ + downloadUrl: downloadUrl, + fileName: fileName, + }); }) .catch((e) => { messageError($q, e); diff --git a/src/modules/10_registry/utils/downloadFile.ts b/src/modules/10_registry/utils/downloadFile.ts index 341b7f9..99c06c5 100644 --- a/src/modules/10_registry/utils/downloadFile.ts +++ b/src/modules/10_registry/utils/downloadFile.ts @@ -49,7 +49,8 @@ export async function downloadBlobFile({ const url = URL.createObjectURL(blobForDownload); const link = document.createElement("a"); link.href = url; - link.download = `${fileName}.${extension}`; + const downloadFileName = fileName.includes(".") ? fileName : `${fileName}.${extension}`; + link.download = downloadFileName; document.body.appendChild(link); link.click(); setTimeout(() => { From 9bee07eb7c7a7ec7a4f18f4a398e653f4d663704 Mon Sep 17 00:00:00 2001 From: "DESKTOP-1R2VSQH\\Lenovo ThinkPad E490" Date: Mon, 11 May 2026 09:24:23 +0700 Subject: [PATCH 3/7] refactor:(genreport) : import downloadBlobFile --- src/plugins/genreport.ts | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/src/plugins/genreport.ts b/src/plugins/genreport.ts index 520ec00..19e2856 100644 --- a/src/plugins/genreport.ts +++ b/src/plugins/genreport.ts @@ -2,6 +2,7 @@ import axios from "axios"; import config from "@/app.config"; import { useCounterMixin } from "@/stores/mixin"; +import { downloadBlobFile } from "@/modules/10_registry/utils/downloadFile"; const mixin = useCounterMixin(); const { showLoader, hideLoader } = mixin; @@ -19,7 +20,7 @@ async function genReport(data: any, fileName: string, type: string = "docx") { }, responseType: "arraybuffer", }) - .then((res) => { + .then(async (res) => { const responseData = res.data; if (responseData) { const mimeType = @@ -31,18 +32,11 @@ async function genReport(data: any, fileName: string, type: string = "docx") { const url = URL.createObjectURL(blob); const baseName = fileName.trim(); - const extension = type === "docx" ? "docx" : "pdf"; - - const link = document.createElement("a"); - link.href = url; - link.download = `${baseName}.${extension}`; - document.body.appendChild(link); - link.click(); - - setTimeout(() => { - document.body.removeChild(link); - URL.revokeObjectURL(url); - }, 100); + // const extension = type === "docx" ? "docx" : "pdf"; + await downloadBlobFile({ + downloadUrl: url, + fileName: baseName, + }); } }) .catch((err) => { From 0092133ba68ce6b823b325d177aa66d3d3e66be9 Mon Sep 17 00:00:00 2001 From: "DESKTOP-1R2VSQH\\Lenovo ThinkPad E490" Date: Mon, 25 May 2026 13:24:55 +0700 Subject: [PATCH 4/7] fix: await API fileByFile --- src/modules/08_KPI/views/form.vue | 41 +++++++++++-------- src/modules/11_probation/views/mainDetail.vue | 10 +++-- src/views/MainLayout.vue | 5 ++- 3 files changed, 34 insertions(+), 22 deletions(-) diff --git a/src/modules/08_KPI/views/form.vue b/src/modules/08_KPI/views/form.vue index 39b06d4..2d8e58b 100644 --- a/src/modules/08_KPI/views/form.vue +++ b/src/modules/08_KPI/views/form.vue @@ -9,6 +9,7 @@ import http from "@/plugins/http"; import config from "@/app.config"; import { useCounterMixin } from "@/stores/mixin"; import { useKpiDataStore } from "@/modules/08_KPI/store"; +import avatar from "@/assets/avatar_user.jpg"; import type { FormProfile } from "@/modules/08_KPI/interface/request/index"; import type { @@ -107,11 +108,13 @@ async function getAvatar(id: string) { .then(async (res) => { const data = await res.data.result; if (data.avatarName) { - await fetchProfile(id, data.avatarName); + fetchProfile(id, data.avatarName); } }) .catch((e) => { messageError($q, e); + imgProfile.value = avatar; + store.dataEvaluation.avartar = avatar; }) .finally(() => { isLoadAvatar.value = false; @@ -119,12 +122,16 @@ async function getAvatar(id: string) { } /** ดึงข้อมูล เพื่อเก็บรูปโปรไฟล์ */ -async function fetchProfile(id: string, avatarName: string) { - await http +function fetchProfile(id: string, avatarName: string) { + http .get(config.API.fileByFile("ทะเบียนประวัติ", "โปรไฟล์", id, avatarName)) - .then(async (res) => { + .then((res) => { store.dataEvaluation.avartar = res.data.downloadUrl; imgProfile.value = res.data.downloadUrl; + }) + .catch(() => { + imgProfile.value = avatar; + store.dataEvaluation.avartar = avatar; }); } @@ -208,7 +215,7 @@ async function getOrgOp() { name: `${i.prefix}${i.firstName} ${i.lastName}`, })) .find( - (i: EvaOptionType) => i.id == store.dataEvaluation.commanderHighId + (i: EvaOptionType) => i.id == store.dataEvaluation.commanderHighId, ); isLoadCommander.value = false; }) @@ -225,21 +232,21 @@ function filterOption(val: string, update: Function, refData: string) { case "evaluatorIdOp": update(() => { evaluatorIdOp.value = evaluatorIdMainOp.value.filter( - (v: DataOptions) => v.name.indexOf(val) > -1 + (v: DataOptions) => v.name.indexOf(val) > -1, ); }); break; case "commanderIdOp": update(() => { commanderIdOp.value = commanderIdMainOp.value.filter( - (v: DataOptions) => v.name.indexOf(val) > -1 + (v: DataOptions) => v.name.indexOf(val) > -1, ); }); break; case "commanderHighOp": update(() => { commanderHighOp.value = commanderHighMainOp.value.filter( - (v: DataOptions) => v.name.indexOf(val) > -1 + (v: DataOptions) => v.name.indexOf(val) > -1, ); }); break; @@ -278,7 +285,7 @@ function sendToEvaluatore() { } }, "ยืนยันการส่งข้อตกลงให้ผู้ประเมินอนุมัติ", - "ต้องการยืนยันส่งข้อตกลงนี้ให้ผู้ประเมินอนุมัติใช่หรือไม่?" + "ต้องการยืนยันส่งข้อตกลงนี้ให้ผู้ประเมินอนุมัติใช่หรือไม่?", ); } @@ -308,7 +315,7 @@ function sendToEvaluateEvaluatore() { } }, "ยืนยันการส่งให้ผู้ประเมินรายงานผลสำเร็จของงาน", - "ต้องการยืนยันส่งให้ผู้ประเมินรายงานผลสำเร็จของงานใช่หรือไม่?" + "ต้องการยืนยันส่งให้ผู้ประเมินรายงานผลสำเร็จของงานใช่หรือไม่?", ); } @@ -338,7 +345,7 @@ function requireEdit() { } }, "ยืนยันการขอแก้ไขข้อตกลง", - "ต้องการยืนยันการขอแก้ไขข้อตกลงนี้ใช่หรือไม่?" + "ต้องการยืนยันการขอแก้ไขข้อตกลงนี้ใช่หรือไม่?", ); } @@ -411,7 +418,7 @@ async function goToSummary() { store.excusiveIndicator2ScoreVal + store.competencyScoreVal ).toFixed(2), - } + }, ) .then((res) => {}); @@ -427,7 +434,7 @@ async function goToSummary() { }); }, "ยืนยันการส่งไปสรุปผลการประเมิน", - "ต้องการยืนยันส่งไปสรุปผลการประเมินใช่หรือไม่?" + "ต้องการยืนยันส่งไปสรุปผลการประเมินใช่หรือไม่?", ); } @@ -517,7 +524,7 @@ async function downloadReport() { store.dataEvaluation.prefix + store.dataEvaluation.firstName + " " + - store.dataEvaluation.lastName + store.dataEvaluation.lastName, ); }) .catch((e) => { @@ -556,7 +563,7 @@ async function clickUpload(file: any) { const foundKey: string | undefined = Object.keys(res.data).find( (key) => res.data[key]?.fileName !== undefined && - res.data[key]?.fileName !== "" + res.data[key]?.fileName !== "", ); foundKey && uploadFileDoc(res.data[foundKey]?.uploadUrl, fileUpload.value); @@ -566,7 +573,7 @@ async function clickUpload(file: any) { }); }, "ยืนยันการอัปโหลดไฟล์", - "ต้องการยืนยันการอัปโหลดไฟล์นี้หรือไม่ ?" + "ต้องการยืนยันการอัปโหลดไฟล์นี้หรือไม่ ?", ); } @@ -623,7 +630,7 @@ function deleteFile(fileName: string) { showLoader(); http .delete( - config.API.file("แบบกำหนดข้อตกลง", "KPI", id.value) + `/${fileName}` + config.API.file("แบบกำหนดข้อตกลง", "KPI", id.value) + `/${fileName}`, ) .catch((e) => { messageError($q, e); diff --git a/src/modules/11_probation/views/mainDetail.vue b/src/modules/11_probation/views/mainDetail.vue index cd6b60c..a4584c0 100644 --- a/src/modules/11_probation/views/mainDetail.vue +++ b/src/modules/11_probation/views/mainDetail.vue @@ -151,6 +151,7 @@ async function getAvatar(id: string) { }) .catch((e) => { messageError($q, e); + profileImg.value = avatar; }); } @@ -168,14 +169,15 @@ function getList(id: string) { }); } -async function getImg(id: string, pathName: string) { - await http +function getImg(id: string, pathName: string) { + http .get(config.API.fileByFile("ทะเบียนประวัติ", "โปรไฟล์", id, pathName)) .then((res) => { profileImg.value = res.data.downloadUrl; }) .catch((e) => { - messageError($q, e); + profileImg.value = avatar; + // messageError($q, e); hideLoader(); }); } @@ -188,7 +190,7 @@ function onSearch() { rows.value = onSearchDataTable( filter.value, rowsData.value, - columns.value ? columns.value : [] + columns.value ? columns.value : [], ); } diff --git a/src/views/MainLayout.vue b/src/views/MainLayout.vue index 165bf6e..331dbe8 100644 --- a/src/views/MainLayout.vue +++ b/src/views/MainLayout.vue @@ -74,7 +74,7 @@ async function checkUser() { await dataStore.getProFileType(); kpiDataStore.dataProfile = data; // Set dataProfile in kpiDataStore if (data.avatarName) { - await getImg(data.profileId, data.avatarName); + getImg(data.profileId, data.avatarName); } else { dataStore.profileImg = avatar; } @@ -106,6 +106,9 @@ function getImg(id: string, pathName: string) { .get(config.API.fileByFile("ทะเบียนประวัติ", "โปรไฟล์", id, pathName)) .then((res) => { dataStore.profileImg = res.data.downloadUrl; + }) + .catch(() => { + dataStore.profileImg = avatar; }); } From 54c7855b615a3ed0646de9289da6b4e82d66a3a6 Mon Sep 17 00:00:00 2001 From: "DESKTOP-1R2VSQH\\Lenovo ThinkPad E490" Date: Fri, 29 May 2026 10:55:41 +0700 Subject: [PATCH 5/7] feat(leave): display leaveCountApproveCount --- src/modules/05_leave/interface/index/main.ts | 1 + src/modules/05_leave/views/Main.vue | 26 +++++++++++--------- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/src/modules/05_leave/interface/index/main.ts b/src/modules/05_leave/interface/index/main.ts index 9551977..a63d65d 100644 --- a/src/modules/05_leave/interface/index/main.ts +++ b/src/modules/05_leave/interface/index/main.ts @@ -43,6 +43,7 @@ interface LeaveItem { all: number; use: number; remain: number; + leaveCountApproveCount: number; } interface MainList { diff --git a/src/modules/05_leave/views/Main.vue b/src/modules/05_leave/views/Main.vue index 4e36478..fcaca35 100644 --- a/src/modules/05_leave/views/Main.vue +++ b/src/modules/05_leave/views/Main.vue @@ -141,12 +141,14 @@ async function fetchStatsTable() { value: el.leaveLimit > 0 ? Math.round( - (Number(el.leaveCountApprove) / Number(el.leaveLimit)) * 100 + (Number(el.leaveCountApprove) / Number(el.leaveLimit)) * + 100, ) : 0, all: Number(el.leaveLimit), use: el.leaveCountApprove, remain: Number(el.leaveLimit) - Number(el.leaveCountApprove), + leaveCountApproveCount: el.leaveCountApproveCount, })); }); stat.forEach((item) => itemPie.value.push(...item)); @@ -254,7 +256,7 @@ onMounted(async () => {
- ลาพักผ่อน + {{ item.text }}
@@ -262,17 +264,19 @@ onMounted(async () => {
ได้รับ - {{ item.all }} + {{ item.all }} วัน
ใช้ไป - {{ item.use }} + {{ item.use }} วัน
คงเหลือ - {{ item.remain }} + {{ item.remain }} วัน
@@ -294,11 +298,11 @@ onMounted(async () => { flat class="shadow-0 col-12 fit row items-center q-px-lg" > -
ลาป่วย
+
{{ item.text }}
ใช้ไป - {{ item.use }} - + {{ item.use }} วัน + ({{ item.leaveCountApproveCount }} ครั้ง)
@@ -317,11 +321,11 @@ onMounted(async () => { flat class="shadow-0 col-12 fit row items-center q-px-lg" > -
ลากิจส่วนตัว
+
{{ item.text }}
ใช้ไป - {{ item.use }} - + {{ item.use }} วัน + ({{ item.leaveCountApproveCount }} ครั้ง)
From 650de029f361be2cd37d0954e1f7c1b5a97743bd Mon Sep 17 00:00:00 2001 From: "DESKTOP-1R2VSQH\\Lenovo ThinkPad E490" Date: Fri, 29 May 2026 11:35:50 +0700 Subject: [PATCH 6/7] feat(leave): DownloadFile form leave --- .../05_leave/components/DialogDetail.vue | 147 ++++++++++++++++-- 1 file changed, 135 insertions(+), 12 deletions(-) diff --git a/src/modules/05_leave/components/DialogDetail.vue b/src/modules/05_leave/components/DialogDetail.vue index 3333374..7874515 100644 --- a/src/modules/05_leave/components/DialogDetail.vue +++ b/src/modules/05_leave/components/DialogDetail.vue @@ -6,7 +6,7 @@ import http from "@/plugins/http"; import config from "@/app.config"; import { useCounterMixin } from "@/stores/mixin"; import { useLeaveStore } from "@/modules/05_leave/store"; -import { useDataStore } from "@/stores/data"; +import genReport from "@/plugins/genreport"; /** import type*/ import type { @@ -16,8 +16,6 @@ import type { FromCancelDetail, } from "@/modules/05_leave/interface/response/leave"; -import DialogHeader from "@/components/DialogHeader.vue"; -import Workflow from "@/components/Workflow/Main.vue"; import FormLeave from "@/modules/05_leave/components/formDetail/01_SickForm.vue"; import FormChildbirth from "@/modules/05_leave/components/formDetail/04_HelpWifeBirthForm.vue"; import FormHoliday from "@/modules/05_leave/components/formDetail/05_VacationForm.vue"; @@ -33,7 +31,6 @@ import FormCancel from "@/modules/05_leave/components/formDetail/formCancel.vue" const $q = useQuasar(); const dataStore = useLeaveStore(); -const mainStore = useDataStore(); const { convertStatud } = dataStore; const mixin = useCounterMixin(); const { @@ -411,6 +408,28 @@ async function onSubmit() { }); } +/** + * ฟังก์ชันดาวน์โหลดไฟล์ + * @param id รหัสการลา + * @param fileName ชื่อไฟล์ + * @param type ประเภทไฟล์ + */ +async function onClickDownloadFile(id: string, fileName: string, type: string) { + showLoader(); + await http + .get(config.API.leaveReport(id)) + .then(async (res) => { + const data = res.data.result; + await genReport(data, fileName, type); + }) + .catch((err) => { + messageError($q, err); + }) + .finally(() => { + hideLoader(); + }); +} + /**** ตรวจสอบว่ามีการส่งข้อมูลเข้ามาแล้วเปิด modal */ watch( () => props.modal, @@ -434,10 +453,62 @@ watch( v-if="props.leaveStatus != 'DELETE'" style="width: 900px; max-width: 80vw" > - + + + {{ ` ${titleMain} ${titleName}` }} + + ดาวน์โหลดไฟล์ + + + + + + + ไฟล์ .DOCX + + + + + + ไฟล์ .pdf + + + + + + + @@ -580,10 +651,62 @@ watch( - + + + {{ ` ${titleMainCancle} ${titleName}` }} + + ดาวน์โหลดไฟล์ + + + + + + + ไฟล์ .DOCX + + + + + + ไฟล์ .pdf + + + + + + + From a0f0443a55a0f5fb6d4d543d856285264cf7a682 Mon Sep 17 00:00:00 2001 From: "DESKTOP-1R2VSQH\\Lenovo ThinkPad E490" Date: Fri, 29 May 2026 13:55:05 +0700 Subject: [PATCH 7/7] refactor: downloadBlobFile with direct blob download logic --- src/plugins/genreport.ts | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/plugins/genreport.ts b/src/plugins/genreport.ts index 19e2856..500dca4 100644 --- a/src/plugins/genreport.ts +++ b/src/plugins/genreport.ts @@ -2,7 +2,6 @@ import axios from "axios"; import config from "@/app.config"; import { useCounterMixin } from "@/stores/mixin"; -import { downloadBlobFile } from "@/modules/10_registry/utils/downloadFile"; const mixin = useCounterMixin(); const { showLoader, hideLoader } = mixin; @@ -32,11 +31,16 @@ async function genReport(data: any, fileName: string, type: string = "docx") { const url = URL.createObjectURL(blob); const baseName = fileName.trim(); - // const extension = type === "docx" ? "docx" : "pdf"; - await downloadBlobFile({ - downloadUrl: url, - fileName: baseName, - }); + const extension = type === "docx" ? "docx" : "pdf"; + const link = document.createElement("a"); + link.href = url; + link.download = `${baseName}.${extension}`; + document.body.appendChild(link); + link.click(); + setTimeout(() => { + document.body.removeChild(link); + URL.revokeObjectURL(url); + }, 100); } }) .catch((err) => {