hrms-mgt/src/modules/18_command/components/Step/4_Attached.vue
2024-09-24 10:50:42 +07:00

369 lines
10 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<script setup lang="ts">
import { onMounted, ref, watch } from "vue";
import { VuePDF, usePDF } from "@tato30/vue-pdf";
import axios from "axios";
import { useQuasar } from "quasar";
import http from "@/plugins/http";
import config from "@/app.config";
import genReport from "@/plugins/genreport";
import type { PDFDocumentLoadingTask } from "pdfjs-dist/types/src/display/api";
import { useCounterMixin } from "@/stores/mixin";
const $q = useQuasar();
const mixin = useCounterMixin();
const {
date2Thai,
messageError,
showLoader,
hideLoader,
dialogConfirm,
success,
} = mixin;
const isChangeData = defineModel<boolean>("isChangeData", { required: true });
const { onCheckChangeData } = defineProps({
onCheckChangeData: { type: Function, required: true },
});
const tab = ref<string>("main"); //tab
const page = ref<number>(1);
const numOfPages = ref<number>(0); //จำนวนหน้า pdf
const pdfSrc = ref<PDFDocumentLoadingTask | undefined>(); // ตัวแปรเก็บ เเสดง pdf
const isAttachment = ref<boolean>(true);
const dialog = ref<boolean>(false); // เปิด dialog
/**
* เปลี่ยน tab
* @param val ชื่อ tab
*/
function setTab(val: string) {
tab.value = val;
page.value = 1;
}
/** ดึง class ตามที่ set ไว้ */
function getClass(val: boolean) {
return {
"card-header-active q-px-lg q-py-md cursor-pointer": val,
"card-header q-px-lg q-py-md cursor-pointer": !val,
};
}
function onSubmit() {}
/** ฟังชั่นจองลอง แสดง pdf */
async function genPDf(data: any, type: string = "docx") {
showLoader();
await axios
.post(config.API.reportTemplate + `/${type}`, data, {
headers: {
accept: "application/pdf",
"content-Type": "application/json",
},
responseType: "blob",
})
.then(async (res) => {
const blob = new Blob([res.data]);
const objectUrl = URL.createObjectURL(blob);
const pdfData = usePDF(`${objectUrl}`);
setTimeout(() => {
pdfSrc.value = pdfData.pdf.value;
numOfPages.value = pdfData.pages.value;
hideLoader();
}, 1500);
})
.catch(async (e) => {
messageError($q, e);
hideLoader();
});
}
/**
* ฟังชั่นดาวห์โหลดไฟล์
* @param type pdf/docx
*/
async function downloadCover(type: string) {
genReport(
tab.value == "main" ? data1 : data2,
`${
tab.value == "main"
? "คำสั่ง คำสั่งบรรจุและแต่งตั้ง: สำหรับผู้สอบแข่งขันได้"
: "เอกสารแนบท้าย คำสั่งบรรจุและแต่งตั้ง: สำหรับผู้สอบแข่งขันได้"
}`,
type
);
}
/** ข้อมูลจำลอง */
const data1 = {
template: "C-PM-01",
reportName: "docx-report",
data: {
commandNo: "",
commandYear: "๒๕๖๗",
issuerOrganizationName: "",
conclusionRegisterNo: "test",
conclusionRegisterDate: "๒ สิงหาคม ๒๕๖๗",
conclusionResultNo: "test",
conclusionResultDate: "๓ สิงหาคม ๒๕๖๗",
positionList: "",
count: "๑",
commandAffectDate: "๑ สิงหาคม ๒๕๖๗",
authorizedUserFullName: "นายวิษณุ สุวรรณรัตน์",
authorizedPosition: "ผู้อำนวยการ",
subject: "เรื่อง คำสั่งบรรจุและแต่งตั้ง: สำหรับผู้สอบแข่งขันได้",
},
};
const data2 = {
template: "C-PM-01-attachment",
reportName: "docx-report",
data: {
commandNo: "",
commandYear: "๒๕๖๗",
issuerOrganizationName: "",
commandExcecuteDate: "-",
data: [
{
citizenId: "๒๔๕๙๙๐๐๐๑๙๖๘๐",
fullName: "นางสาวบุปผารัตน์ สีลาเหลี่ยม",
oc: "สำนักงานคณะกรรมการข้าราชการกรุงเทพมหานคร",
positionName: "นักบริหาร",
positionLevel: "ต้น",
positionType: "บริหาร",
positionNumber: "สกก.๒",
salary: "๑๒,",
appointDate: "๒๓ ส.ค. ๖๗",
examNumber: "๑",
placementName: "สอบแข่งขันนักคอมพิวเตอร์ ครั้งที่ ๑/๒๕๖๗",
seq: "๑",
education: "การศึกษาบัณฑิต",
remarkHorizontal:
"โดยมีเงื่อนไขว่าต้องปฏิบัติงานให้กรุงเทพมหานครเป็นระยะเวลาไม่น้อยกว่า ๕ ปี นับแต่วันที่ได้รับการบรรจุและแต่งตั้ง โดยห้ามโอนไปหน่วยงานหรือส่วนราชการอื่น เว้นเเต่ลาออกจากราชการ",
remarkVertical: null,
},
],
},
};
/**
* ฟังก์ชันที่ต้องการนำฟังก์ชันออกไปใช้ใน Components แม่
*/
defineExpose({
onSubmit,
});
/** check tab เมื่อมีการเปลี่ยน tab */
watch(tab, () => {
if (tab.value === "main") {
genPDf(data1);
}
if (tab.value === "second") {
genPDf(data2);
}
});
/** hook */
onMounted(async () => {
await genPDf(data1);
});
</script>
<template>
<div class="space">
<div @click="setTab('main')" :class="getClass(tab == 'main')">
<div class="q-pr-sm">คำส</div>
</div>
<div @click="setTab('second')" :class="getClass(tab == 'second')">
<div class="q-pr-sm">เอกสารแนบทาย</div>
</div>
<q-space />
<q-btn
class="text-dark"
flat
dense
icon="mdi-fullscreen"
color="add"
@click="dialog = true"
/>
</div>
<q-separator style="margin-top: -1px; z-index: 1" />
<div class="q-pa-sm">
<div class="q-pa-sm row q-gutter-sm">
<q-btn
flat
dense
round
color="red"
icon="mdi-file-pdf"
@click="downloadCover('pdf')"
>
<q-tooltip>ไฟล .PDF</q-tooltip>
</q-btn>
<q-btn
flat
dense
round
color="blue"
icon="mdi-file-word"
@click="downloadCover('docx')"
>
<q-tooltip>ไฟล .docx</q-tooltip>
</q-btn>
</div>
<q-card bordered class="card-pdf q-mx-sm q-pa-md">
<div class="justify-between items-center align-center q-pb-sm row">
<q-btn
class="text-dark bg-grey-4"
flat
dense
@click="page = page > 1 ? page - 1 : page"
>
<q-icon name="mdi-chevron-left" />
</q-btn>
<span class="body-2 grey--text">
หนาท {{ page }} จาก {{ numOfPages }}
</span>
<q-btn
class="text-dark bg-grey-4"
flat
dense
@click="page = page < numOfPages ? page + 1 : page"
>
<q-icon name="mdi-chevron-right" />
</q-btn>
</div>
<div class="pdfWidth">
<VuePDF ref="vuePDFRef" :pdf="pdfSrc" :page="page" fit-parent />
</div>
</q-card>
</div>
<q-dialog
v-model="dialog"
persistent
:maximized="true"
transition-show="slide-up"
transition-hide="slide-down"
>
<q-card class="bg-white text-white">
<div class="flex justify-end items-center align-center q-mr-md q-mt-sm">
<q-btn
icon="close"
unelevated
round
dense
style="color: #ff8080; background-color: #ffdede"
size="12px"
v-close-popup
/>
</div>
<q-card-section bordered class="card-pdf q-ma-md q-pa-md">
<div class="justify-between items-center align-center q-pb-sm row">
<q-btn
class="text-dark bg-grey-4"
flat
dense
@click="page = page > 1 ? page - 1 : page"
>
<q-icon name="mdi-chevron-left" />
</q-btn>
<span class="body-2 grey--text text-black">
หนาท {{ page }} จาก {{ numOfPages }}
</span>
<q-btn
class="text-dark bg-grey-4"
flat
dense
@click="page = page < numOfPages ? page + 1 : page"
>
<q-icon name="mdi-chevron-right" />
</q-btn>
</div>
<div class="pdfWidth">
<VuePDF
ref="vuePDFRef"
:pdf="pdfSrc"
:page="page"
fit-parent
:scale="0.1"
/>
<!-- <VuePdf :key="page" :src="pdfSrc" :page="page" /> -->
</div>
<div class="justify-between items-center align-center q-pt-sm row">
<q-btn
class="text-dark bg-grey-4"
flat
dense
@click="page = page > 1 ? page - 1 : page"
>
<q-icon name="mdi-chevron-left" />
</q-btn>
<span class="body-2 grey--text text-black">
หนาท {{ page }} จาก {{ numOfPages }}
</span>
<q-btn
class="text-dark bg-grey-4"
flat
dense
@click="page = page < numOfPages ? page + 1 : page"
>
<q-icon name="mdi-chevron-right" />
</q-btn>
</div>
</q-card-section>
</q-card>
</q-dialog>
</template>
<style scoped lang="scss">
.space {
background-color: #e9eaec61;
display: flex;
z-index: 3;
min-height: 40px;
}
.card-header-active {
margin-top: 5px;
margin-left: -1px;
background-color: white;
padding: 2px !important;
border-radius: 10px 10px 0px 0px;
border: 1px solid #e9eaec;
width: 200px;
display: flex;
justify-content: center;
border-bottom-style: none;
font-weight: 600;
align-items: center;
}
.card-header {
margin-top: 5px;
background-color: transparent;
padding: 2px !important;
border-radius: 10px 10px 0px 0px;
width: 200px;
display: flex;
justify-content: center;
font-weight: normal;
align-items: center;
}
.card-pdf {
border-radius: 10px;
border: 1px solid #e9eaec;
background-color: #e9eaec61;
}
</style>