This commit is contained in:
Warunee Tamkoo 2024-09-11 18:06:04 +07:00
parent 9ab3001ff0
commit f68c4af30b
6 changed files with 261 additions and 34 deletions

View file

@ -0,0 +1,151 @@
<script setup lang="ts">
import { watch, ref } from "vue";
import { useQuasar } from "quasar";
import { useCounterMixin } from "@/stores/mixin";
import { useDataStore } from "@/modules/05_command/stores/main";
const $q = useQuasar();
const mixin = useCounterMixin();
const {
dialogConfirm,
success,
showLoader,
hideLoader,
dialogRemove,
messageError,
} = mixin;
const store = useDataStore();
const commandId = defineModel<string>("commandId", { required: true });
const type = defineModel<string>("type", { required: true });
const textHeader = ref<string>("");
const textBody = ref<string>("");
const textFooter = ref<string>("");
const fetchData = async () => {
textHeader.value = "";
textBody.value = "";
textFooter.value = "";
};
const onSave = () => {
console.log("textHeader===>", textHeader.value);
console.log("textBody===>", textBody.value);
console.log("textFooter===>", textFooter.value);
};
function clearFormat(type: string) {
switch (type) {
case "textHeader":
textHeader.value = textHeader.value.replace(/<\/?[^>]+(>|$)/g, "");
break;
case "textBody":
textBody.value = textBody.value.replace(/<\/?[^>]+(>|$)/g, "");
break;
case "textFooter":
textFooter.value = textFooter.value.replace(/<\/?[^>]+(>|$)/g, "");
break;
default:
break;
}
}
const handleInput = (event: any, type: string) => {
if (event.inputType === "insertFromPaste") {
clearFormat(type);
}
};
watch(
() => commandId.value,
(newValue, oldValue) => {
if (newValue && newValue !== oldValue) {
fetchData();
}
}
);
</script>
<template>
<q-card>
<q-card-section class="q-pt-none">
<div class="row items-center q-col-gutter-sm">
<div class="col-12">
<q-label>เนอหาคำสงสวนต</q-label>
<q-field
class="q_field_p_none"
ref="fieldRef"
v-model="textHeader"
borderless
hide-bottom-space
>
<template #control>
<q-editor
class="full-width"
v-model="textHeader"
min-height="5rem"
:toolbar="store.toolbarOptions"
@input="(e:any) => handleInput(e, 'textHeader')"
/>
</template>
</q-field>
</div>
<div class="col-12">
<q-label>เนอหาคำสงสวนกลาง</q-label>
<q-field
class="q_field_p_none"
ref="fieldRef"
v-model="textBody"
borderless
hide-bottom-space
>
<template #control>
<q-editor
class="full-width"
v-model="textBody"
min-height="5rem"
:toolbar="store.toolbarOptions"
@input="(e:any) => handleInput(e, 'textBody')"
/>
</template>
</q-field>
</div>
<div class="col-12">
<q-label>เนอหาคำสงสวนทาย</q-label>
<q-field
class="q_field_p_none"
ref="fieldRef"
v-model="textFooter"
borderless
hide-bottom-space
>
<template #control>
<q-editor
class="full-width"
v-model="textFooter"
min-height="5rem"
:toolbar="store.toolbarOptions"
@input="(e:any) => handleInput(e, 'textFooter')"
/>
</template>
</q-field>
</div>
</div>
</q-card-section>
<q-card-section align="right">
<q-btn
for="#submitForm"
unelevated
dense
class="q-px-md items-center"
color="light-blue-10"
label="บันทึก"
@click="onSave"
/>
</q-card-section>
</q-card>
</template>

View file

@ -4,8 +4,10 @@ import { VuePDF, usePDF } from "@tato30/vue-pdf";
import { useQuasar } from "quasar"; import { useQuasar } from "quasar";
import { useCounterMixin } from "@/stores/mixin"; import { useCounterMixin } from "@/stores/mixin";
import http from "@/plugins/http";
import config from "@/app.config"; import config from "@/app.config";
import axios from "axios";
// import genReport from "@/plugins/genreport";
const $q = useQuasar(); const $q = useQuasar();
const mixin = useCounterMixin(); const mixin = useCounterMixin();
@ -48,25 +50,77 @@ function backPage() {
} }
} }
const showDocument = (url: any) => { function replaceAllTag(html: string) {
const pdfData = usePDF(url); return html.replace("div", "p");
setTimeout(() => { }
pdfSrc.value = pdfData.pdf.value;
numOfPages.value = pdfData.pages.value; async function fetchDocumentTemplate() {
}, 1000); showLoader();
}; let textEditHeader = "";
let textEditBody = "";
let textEditFooter = "";
textEditHeader +=
"อาศัยอำนาจตามความในมาตรา ๔๔ และมาตรา ๕๒ (๔) แห่งพระราชบัญญัติระเบียบข้าราชการ-กรุงเทพมหานครและบุคลากรกรุงเทพมหานคร พ.ศ. ๒๕๕๔ ประกอบกับกฎ ก.ก. ว่าด้วยการทดลองปฏิบัติ-หน้าที่ราชการและการพัฒนาข้าราชการกรุงเทพมหานครสามัญที่อยู่ระหว่างทดลองปฏิบัติหน้าที่ราชการ พ.ศ. ๒๕๕๕ มติคณะกรรมการข้าราชการกรุงเทพมหานครและบุคลากรกรุงเทพมหานคร ครั้งที่ ๑/๒๕๕๔ เมื่อวันที่ ๒๒ ธันวาคม ๒๕๕๔ มติ อ.ก.ก. วิสามัญเกี่ยวกับระบบราชการ การจัดส่วนราชการ และค่าตอบแทน ครั้งที่ ๙/๒๕๕๖";
textEditBody +=
"เมื่อวันที่ ๑๘ กันยายน ๒๕๕๖ ประกาศผลการสอบแข่งขันสำนักงานคณะกรรมการ-ข้าราชการกรุงเทพมหานคร ครั้งที่ ๑/๒๕๖๔ ลงวันที่ ๒๙ เมษายน ๒๕๖๕ ตำแหน่งนักทรัพยากรบุคคลปฏิบัติการ จึงบรรจุและแต่งตั้งผู้สอบแข่งขันได้เข้ารับราชการเป็นข้าราชการกรุงเทพมหานครสามัญ และแต่งตั้งให้ดำรงตำแหน่งนักทรัพยากรบุคคลปฏิบัติการ จำนวน ๔ ราย";
textEditFooter += "ดังบัญชีรายละเอียดแนบท้ายคำสั่งนี้";
const data = await {
template: "command_test",
reportName: "docx-report",
data: {
commandNo: "๑๒",
commandYear: "๒๕๖๗",
commandTitle: "บรรจุและแต่งตั้งผู้สอบแข่งขันได้",
detailHeader: textEditHeader,
detailBody:
'<meta charset="UTF-8"><body><p style="font-family: \'TH Sarabun Psk\'; font-size: 16pt;">' +
replaceAllTag(textEditBody) +
"</p></body>",
detailFooter:
'<meta charset="UTF-8"><body><p style="font-family: \'TH Sarabun Psk\'; font-size: 16pt;">' +
replaceAllTag(textEditFooter) +
"</p></body>",
commandDate: "๑ สิงหาคม ๒๕๖๗",
name: "Admin Administrator",
position: "Admin Administrator",
},
};
// genReport(data, ``);
await axios
.post(config.API.reportTemplate + `/docx/html`, 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 = await usePDF(`${objectUrl}`);
showLoader();
setTimeout(() => {
pdfSrc.value = pdfData.pdf.value;
numOfPages.value = pdfData.pages.value;
hideLoader();
}, 1500);
})
.catch(async (e) => {
messageError($q, e);
hideLoader();
});
}
watch( watch(
() => idOrder.value, () => idOrder.value,
(newValue, oldValue) => { (newValue, oldValue) => {
if (newValue && newValue !== oldValue) { if (newValue && newValue !== oldValue) {
showLoader(); fetchDocumentTemplate();
setTimeout(() => {
const url =
"https://s3cluster.frappet.com/public/template-command.pdf?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=A3O4SZ1Q1L0A2SPWLMDY%2F20240909%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20240909T064638Z&X-Amz-Expires=604800&X-Amz-Security-Token=eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJhY2Nlc3NLZXkiOiJBM080U1oxUTFMMEEyU1BXTE1EWSIsImV4cCI6MTcyNTkwNzE4MiwicGFyZW50IjoiZnJhcHBldCJ9.4opHdRH9VegUbtcHsIucy-SpWyboCcuhg2jjtLT4Ypvg2Yg8WvvLoyL92-IabqEYlNvv_sMJMa7P8oQkMqpsSA&X-Amz-SignedHeaders=host&versionId=null&X-Amz-Signature=fce8a76e6d5d3e83eac102402b07ba2a8ac8c2a1e0a055f1d8a5ecc74434c0e0";
showDocument(url);
hideLoader();
}, 1000);
} }
}, },
{ immediate: true } { immediate: true }
@ -81,7 +135,7 @@ watch(
outlined outlined
dense dense
v-model="documentFile" v-model="documentFile"
label="ไฟล์เอกสารหลักฐาน" :label="`ไฟล์ต้นแบบ${type == 'order' ? 'คำสั่ง' : 'บัญชีแนบท้าย'}`"
hide-bottom-space hide-bottom-space
:accept="type == 'order' ? '.docx' : '.pdf'" :accept="type == 'order' ? '.docx' : '.pdf'"
clearable clearable

View file

@ -3,7 +3,7 @@ interface Pagination {
} }
interface ActiveOptions { interface ActiveOptions {
value: string; value: boolean;
label: string; label: string;
} }

View file

@ -3,7 +3,13 @@ import { ref } from "vue";
export const useDataStore = defineStore("commandStore", () => { export const useDataStore = defineStore("commandStore", () => {
const currentTab = ref<string>("order"); const currentTab = ref<string>("order");
const toolbarOptions = ref([
["left", "center", "right", "justify"],
["token", "bold", "italic", "underline", "subscript", "superscript"],
]);
return { return {
currentTab currentTab,
toolbarOptions,
}; };
}); });

View file

@ -15,6 +15,7 @@ import type {
import Header from "@/components/DialogHeader.vue"; import Header from "@/components/DialogHeader.vue";
import PageOrder from "@/modules/05_command/components/ViewPdf.vue"; import PageOrder from "@/modules/05_command/components/ViewPdf.vue";
import TemplateDetail from "@/modules/05_command/components/FormTemplate.vue";
const $q = useQuasar(); const $q = useQuasar();
const mixin = useCounterMixin(); const mixin = useCounterMixin();
@ -28,18 +29,20 @@ const {
messageError, messageError,
} = mixin; } = mixin;
const inActive = ref<string>(""); //Select Active/InActive const isActive = ref<string>(""); //
// options
const activeOptions = ref<ActiveOptions[]>([ const activeOptions = ref<ActiveOptions[]>([
{ {
value: "Active", value: true,
label: "Active", label: "Active",
}, },
{ {
value: "InActive", value: false,
label: "InActive", label: "InActive",
}, },
]); ]);
// Tabs
const tabs = ref<Tabs[]>([ const tabs = ref<Tabs[]>([
{ {
value: "order", value: "order",
@ -49,25 +52,32 @@ const tabs = ref<Tabs[]>([
value: "account", value: "account",
label: "บัญชีแนบท้าย", label: "บัญชีแนบท้าย",
}, },
{
value: "template",
label: "ข้อความต้นแบบ",
},
]); ]);
const idOrder = ref<string>(""); const idOrder = ref<string>(""); // Id
const activeOrderId = ref<string>(""); const activeOrderId = ref<string>(""); // Id
const name = ref<string>(""); // const name = ref<string>(""); //
const listOrder = ref<ListOrder[]>([]); // list const listOrder = ref<ListOrder[]>([]); // list
const status = ref<boolean>(false); // const status = ref<boolean>(false); //
const isEdit = ref<boolean>(false); // true/false const isEdit = ref<boolean>(false); // true/false
const modelDialogActive = ref<boolean>(false); // model const dialogFormCommand = ref<boolean>(false); // model
/** search Active / InActive */ /**
function searchActive(val: string) { * งกนคนหาคำส ตามสถานะ
* @param val สถานะ true/false
*/
function searchByStatus(val: string) {
console.log(val); console.log(val);
} }
/** เปิด dialog */ /** เปิด dialog */
function onDialogAdd() { function onDialogAdd() {
isEdit.value = false; isEdit.value = false;
modelDialogActive.value = true; dialogFormCommand.value = true;
} }
/** /**
* เป dialog Edit * เป dialog Edit
@ -79,7 +89,7 @@ function onDialogEdit(data: ListOrder) {
status.value = data.status; status.value = data.status;
isEdit.value = true; isEdit.value = true;
modelDialogActive.value = true; dialogFormCommand.value = true;
} }
/** /**
@ -102,7 +112,7 @@ function onDelete(id: string) {
function closeDialog() { function closeDialog() {
idOrder.value = ""; idOrder.value = "";
isEdit.value = false; isEdit.value = false;
modelDialogActive.value = false; dialogFormCommand.value = false;
name.value = ""; name.value = "";
status.value = false; status.value = false;
} }
@ -174,14 +184,14 @@ onMounted(() => {
<q-select <q-select
outlined outlined
dense dense
v-model="inActive" v-model="isActive"
class="inputgreen" class="inputgreen"
label="สถานะการใช้งาน" label="สถานะการใช้งาน"
:options="activeOptions" :options="activeOptions"
option-label="label" option-label="label"
option-value="value" option-value="value"
emit-value emit-value
@update:model-value="searchActive" @update:model-value="searchByStatus"
></q-select> ></q-select>
</div> </div>
</div> </div>
@ -294,6 +304,12 @@ onMounted(() => {
:id-order="activeOrderId" :id-order="activeOrderId"
/> />
</q-tab-panel> </q-tab-panel>
<q-tab-panel name="template">
<TemplateDetail
v-model:type="store.currentTab"
:command-id="activeOrderId"
/>
</q-tab-panel>
</q-tab-panels> </q-tab-panels>
</div> </div>
<div v-else style="height: auto; max-width: 100%; max-height: 90vh"> <div v-else style="height: auto; max-width: 100%; max-height: 90vh">
@ -315,11 +331,11 @@ onMounted(() => {
</div> </div>
</div> </div>
<q-dialog v-model="modelDialogActive" persistent> <q-dialog v-model="dialogFormCommand" persistent>
<q-card class="col-12" style="min-width: 30%"> <q-card class="col-12" style="min-width: 30%">
<q-form greedy @submit.prevent @validation-success="onSubmit"> <q-form greedy @submit.prevent @validation-success="onSubmit">
<Header <Header
:tittle="isEdit ? 'แก้ไขข้อมูลคำสั่ง' : 'เพิ่มข้อมูลคำสั่ง'" :tittle="isEdit ? 'แก้ไขคำสั่ง' : 'เพิ่มคำสั่ง'"
:close="closeDialog" :close="closeDialog"
/> />
<q-separator /> <q-separator />

View file

@ -12,7 +12,7 @@ const { showLoader, hideLoader, messageError } = mixin;
async function genReport(data: any, fileName: string, type: string = "docx") { async function genReport(data: any, fileName: string, type: string = "docx") {
showLoader(); showLoader();
await axios await axios
.post(`${config.API.reportTemplate}/docx`, data, { .post(`${config.API.reportTemplate}/docx/html`, data, {
headers: headers:
type == "docx" type == "docx"
? { ? {