Merge branch 'develop'

This commit is contained in:
Warunee Tamkoo 2025-08-05 10:58:46 +07:00
commit a8e52bdfa5
4 changed files with 156 additions and 140 deletions

View file

@ -99,7 +99,13 @@ const updateYear = async (e: number) => {
* งกนปมเพมวนหยดแบบเลอกวนได * งกนปมเพมวนหยดแบบเลอกวนได
*/ */
const addCalendar = () => { const addCalendar = () => {
dateAdd.value = [new Date(), new Date()]; const today = new Date();
const { year } = dateMonth.value;
dateAdd.value = [
new Date(year, today.getMonth(), today.getDate()),
new Date(year, today.getMonth(), today.getDate()),
];
name.value = ""; name.value = "";
category.value = "all"; category.value = "all";
isSpecial.value = true; isSpecial.value = true;

View file

@ -15,12 +15,10 @@ import type { Avatar } from "@/components/information/interface/response/avatar"
import { useCounterMixin } from "@/stores/mixin"; import { useCounterMixin } from "@/stores/mixin";
/** use*/ /** use*/
const route = useRoute();
const mixin = useCounterMixin(); const mixin = useCounterMixin();
const router = useRouter();
const $q = useQuasar(); const $q = useQuasar();
const retireDate = ref<Date>(); const { messageError, date2Thai } = mixin;
const { showLoader, hideLoader, messageError, date2Thai } = mixin;
const isEmployee = defineModel("isEmployee", { type: String }); const isEmployee = defineModel("isEmployee", { type: String });
const empType = ref<string>("officer"); const empType = ref<string>("officer");
@ -42,6 +40,9 @@ const emit = defineEmits(["update:modal"]);
/** ตัวแปร*/ /** ตัวแปร*/
const modal = ref<boolean>(false); const modal = ref<boolean>(false);
const isloadInformation = ref<boolean>(true);
const isloadGoverment = ref<boolean>(true);
const retireDate = ref<Date>();
const avatar = reactive<Avatar>({ const avatar = reactive<Avatar>({
avatar: "", avatar: "",
fullname: "", fullname: "",
@ -94,7 +95,7 @@ function calculateAge(birthDate: Date | null) {
* @param id profileID * @param id profileID
*/ */
async function fetchInformation(id: string) { async function fetchInformation(id: string) {
showLoader(); isloadInformation.value = true;
await http await http
.get( .get(
config.API.orgProfileAdminById( config.API.orgProfileAdminById(
@ -111,9 +112,7 @@ async function fetchInformation(id: string) {
imformation.birthDate = data.birthDate ? date2Thai(data.birthDate) : "-"; imformation.birthDate = data.birthDate ? date2Thai(data.birthDate) : "-";
imformation.age = data.birthDate ? calculateAge(data.birthDate) : "-"; imformation.age = data.birthDate ? calculateAge(data.birthDate) : "-";
imformation.gender = data.gender ?? "-"; imformation.gender = data.gender ?? "-";
avatar.fullname = `${data.prefix}${data.firstName} ${data.lastName}`; avatar.fullname = `${data.prefix}${data.firstName} ${data.lastName}`;
avatar.position = data.position ? data.position : "-"; avatar.position = data.position ? data.position : "-";
if (data.avatarName) { if (data.avatarName) {
await fetchProfile(data.id as string, data.avatarName); await fetchProfile(data.id as string, data.avatarName);
@ -125,7 +124,7 @@ async function fetchInformation(id: string) {
messageError($q, err); messageError($q, err);
}) })
.finally(() => { .finally(() => {
hideLoader(); isloadInformation.value = false;
}); });
} }
@ -134,7 +133,7 @@ async function fetchInformation(id: string) {
* @param id profileID * @param id profileID
*/ */
async function fetchProfileGov(id: string) { async function fetchProfileGov(id: string) {
showLoader(); isloadGoverment.value = true;
await http await http
.get( .get(
config.API.profileNewGovernmentCard( config.API.profileNewGovernmentCard(
@ -158,19 +157,21 @@ async function fetchProfileGov(id: string) {
goverment.positionExecutiveSide = goverment.positionExecutiveSide =
data.positionExecutiveField !== "" ? data.positionExecutiveField : "-"; data.positionExecutiveField !== "" ? data.positionExecutiveField : "-";
}) })
.catch((err) => { .catch((err) => {
messageError($q, err); messageError($q, err);
}) })
.finally(() => { .finally(() => {
hideLoader(); isloadGoverment.value = false;
}); });
} }
// function redirecToRegistry() { async function fetchProfile(id: string, avatarName: string) {
// router.push(`/registry-${empType.value}/${props.id}`); await http
// modal.value = false; .get(config.API.fileByFile("ทะเบียนประวัติ", "โปรไฟล์", id, avatarName))
// } .then(async (res) => {
avatar.avatar = await res.data.downloadUrl;
});
}
watch( watch(
() => props.modal, () => props.modal,
@ -178,12 +179,6 @@ watch(
modal.value = props.modal ? props.modal : false; modal.value = props.modal ? props.modal : false;
if (modal.value) { if (modal.value) {
if (props.id) { if (props.id) {
// empType.value =
// route.name === "appoint-employee-detail" ||
// isEmployee.value == "EMPLOYEE"
// ? "employee"
// : "officer";
await Promise.all([ await Promise.all([
fetchInformation(props.id), fetchInformation(props.id),
fetchProfileGov(props.id), fetchProfileGov(props.id),
@ -198,14 +193,6 @@ watch(modal, (newValue) => {
emit("update:modal", false); emit("update:modal", false);
} }
}); });
async function fetchProfile(id: string, avatarName: string) {
await http
.get(config.API.fileByFile("ทะเบียนประวัติ", "โปรไฟล์", id, avatarName))
.then(async (res) => {
avatar.avatar = await res.data.downloadUrl;
});
}
</script> </script>
<template> <template>
@ -227,7 +214,27 @@ async function fetchProfile(id: string, avatarName: string) {
<q-card-section class="col q-pt-none bg-grey-12"> <q-card-section class="col q-pt-none bg-grey-12">
<div class="q-gutter-md"> <div class="q-gutter-md">
<q-card bordered class="text-center bg-grey-12"> <div v-if="isloadInformation">
<q-skeleton
type="QAvatar"
size="120px"
style="background: #e3e3e3"
class="q-mx-auto q-mt-md"
/>
<q-skeleton
type="text"
width="150px"
style="background: #e3e3e3"
class="q-mx-auto q-mt-md"
/>
<q-skeleton
type="text"
width="100px"
style="background: #e3e3e3"
class="q-mx-auto q-mt-sm"
/>
</div>
<q-card v-else bordered class="text-center bg-grey-12">
<div> <div>
<q-avatar size="120px" color="grey-4"> <q-avatar size="120px" color="grey-4">
<img <img
@ -244,6 +251,7 @@ async function fetchProfile(id: string, avatarName: string) {
/> />
</q-avatar> </q-avatar>
</div> </div>
<div <div
class="q-mt-md text-subtitle2 text-bold" class="q-mt-md text-subtitle2 text-bold"
style="font-size: 18px" style="font-size: 18px"
@ -256,21 +264,6 @@ async function fetchProfile(id: string, avatarName: string) {
> >
{{ avatar.position }} {{ avatar.position }}
</div> </div>
<!-- <div class="q-mt-md">
<q-btn
v-if="
empType === 'employee'
? checkPermissionGet('SYS_REGISTRY_EMP')
: checkPermissionGet('SYS_REGISTRY_OFFICER')
"
class="bg-white"
outline
rounded
label="ดูรายละเอียดเพิ่มเติมทั้งหมด"
color="secondary"
@click.prevent="redirecToRegistry"
/>
</div> -->
</q-card> </q-card>
<q-scroll-area style="height: 65vh; max-width: 100%"> <q-scroll-area style="height: 65vh; max-width: 100%">
@ -281,7 +274,16 @@ async function fetchProfile(id: string, avatarName: string) {
<q-icon name="mdi-account" color="grey-7" /> <q-icon name="mdi-account" color="grey-7" />
<span class="q-ml-md">อมลสวนต </span> <span class="q-ml-md">อมลสวนต </span>
</div> </div>
<div class="row q-pa-sm"> <div v-if="isloadInformation" class="row q-pa-sm">
<div
v-for="n in 6"
:key="n"
class="col-xs-6 col-md-6 q-pa-sm"
>
<q-skeleton type="QInput" height="40px" />
</div>
</div>
<div v-else class="row q-pa-sm">
<div class="col-xs-6 col-md-6"> <div class="col-xs-6 col-md-6">
<q-input <q-input
borderless borderless
@ -360,7 +362,22 @@ async function fetchProfile(id: string, avatarName: string) {
<q-icon name="mdi-account-tie" color="grey-7" /> <q-icon name="mdi-account-tie" color="grey-7" />
<span class="q-ml-md">อมลราชการ </span> <span class="q-ml-md">อมลราชการ </span>
</div> </div>
<div class="row q-pa-sm">
<div v-if="isloadGoverment" class="row q-pa-sm">
<div
v-for="n in 9"
:key="n"
:class="
n !== 1
? 'col-xs-6 col-md-6 q-pa-sm'
: 'col-xs-12 col-md-12 q-pa-sm'
"
>
<q-skeleton type="QInput" height="40px" />
</div>
</div>
<div v-else class="row q-pa-sm">
<div class="col-xs-12 col-md-12"> <div class="col-xs-12 col-md-12">
<q-input <q-input
borderless borderless
@ -433,13 +450,11 @@ async function fetchProfile(id: string, avatarName: string) {
label="ระดับตำแหน่ง" label="ระดับตำแหน่ง"
/> />
</div> </div>
<div <div class="col-xs-6 col-md-6">
class="col-xs-6 col-md-6"
v-if="props.type !== 'employee'"
>
<q-input <q-input
borderless borderless
readonly readonly
autogrow
:model-value=" :model-value="
goverment.positionExecutive goverment.positionExecutive
? goverment.positionExecutive ? goverment.positionExecutive
@ -448,19 +463,17 @@ async function fetchProfile(id: string, avatarName: string) {
label="ตำแหน่งทางการบริหาร" label="ตำแหน่งทางการบริหาร"
/> />
</div> </div>
<div <div class="col-xs-6 col-md-6">
class="col-xs-6 col-md-6"
v-if="props.type !== 'employee'"
>
<q-input <q-input
borderless borderless
readonly readonly
autogrow
:model-value=" :model-value="
goverment.positionExecutiveSide goverment.positionExecutiveSide
? goverment.positionExecutiveSide ? goverment.positionExecutiveSide
: '-' : '-'
" "
label="ด้านตำแหน่งทางการบริหาร" label="ด้านทางการบริหาร"
/> />
</div> </div>
</div> </div>

View file

@ -17,12 +17,9 @@ const { dialogConfirm, success, showLoader, hideLoader, messageError } = mixin;
const commandId = defineModel<string>("commandId", { required: true }); // id const commandId = defineModel<string>("commandId", { required: true }); // id
const type = defineModel<string>("type", { required: true }); // tab const type = defineModel<string>("type", { required: true }); // tab
// //
const dataTemplateDetail = defineModel<DataTemplateDetail>( const dataTemplate = defineModel<DataTemplateDetail>("dataTemplateDetail", {
"dataTemplateDetail", required: true,
{ });
required: true,
}
);
const documentFile = ref<File | null>(null); // file const documentFile = ref<File | null>(null); // file
const isLoadPDF = ref<boolean>(false); // Loading display pdf const isLoadPDF = ref<boolean>(false); // Loading display pdf
@ -57,69 +54,71 @@ const { fetchDataTemplate } = defineProps({
* @param dataTemple รายละเอยดคำส * @param dataTemple รายละเอยดคำส
*/ */
async function fetchDocumentTemplate(dataTemple: DataTemplateDetail) { async function fetchDocumentTemplate(dataTemple: DataTemplateDetail) {
showLoader(); if (dataTemple) {
isLoadPDF.value = false; showLoader();
pdfSrc.value = undefined; isLoadPDF.value = false;
page.value = 1; pdfSrc.value = undefined;
const reportName = await `${dataTemplateDetail.value.code}_${type.value}`; page.value = 1;
const body = { const reportName = `${dataTemple.code}_${type.value}`;
template: reportName, const body = {
reportName: `${typeFile.value}-report`, template: reportName,
data: { reportName: `${typeFile.value}-report`,
issue: "............", // data: {
title: "......", // issue: "............", //
commandNo: "......", title: "......", //
commandYear: "......", commandNo: "......",
commandTitle: dataTemple.name, commandYear: "......",
detailHeader: dataTemple.detailHeader, commandTitle: dataTemple.name,
detailBody: dataTemple.detailBody, detailHeader: dataTemple.detailHeader,
detailFooter: dataTemple.detailFooter, detailBody: dataTemple.detailBody,
commandDate: "..................", detailFooter: dataTemple.detailFooter,
commandAffectDate: "..................", commandDate: "..................",
commandExcecuteDate: "..................", commandAffectDate: "..................",
name: "....................................", commandExcecuteDate: "..................",
name1: dataTemple.name1, name: "....................................",
name2: dataTemple.name2, name1: dataTemple.name1,
name3: dataTemple.name3, name2: dataTemple.name2,
name4: dataTemple.name4, name3: dataTemple.name3,
position: "ผู้อำนวยการสำนัก/เขต", name4: dataTemple.name4,
authorizedUserFullName: "............", position: "ผู้อำนวยการสำนัก/เขต",
authorizedPosition: "...................", authorizedUserFullName: "............",
...(dataTemple.persons ? { persons: dataTemple.persons } : {}), authorizedPosition: "...................",
}, ...(dataTemple.persons ? { persons: dataTemple.persons } : {}),
}; },
};
await axios await axios
.post( .post(
config.API.reportTemplate + `/${typeFile.value}?folder=command`, config.API.reportTemplate + `/${typeFile.value}?folder=command`,
body, body,
{ {
headers: { headers: {
accept: "application/pdf", accept: "application/pdf",
"content-Type": "application/json", "content-Type": "application/json",
}, },
responseType: "blob", responseType: "blob",
} }
) )
.then(async (res) => { .then(async (res) => {
const blob = new Blob([res.data]); const blob = new Blob([res.data]);
const objectUrl = URL.createObjectURL(blob); const objectUrl = URL.createObjectURL(blob);
const pdfData = await usePDF(`${objectUrl}`); const pdfData = await usePDF(`${objectUrl}`);
// PDF // PDF
setTimeout(() => { setTimeout(() => {
pdfSrc.value = pdfData.pdf.value; pdfSrc.value = pdfData.pdf.value;
numOfPages.value = pdfData.pages.value; numOfPages.value = pdfData.pages.value;
isLoadPDF.value = true; isLoadPDF.value = true;
hideLoader();
}, 1500);
})
.catch((e) => {
// Template
messageError($q, "", "ไม่พบข้อมูล Template");
isLoadPDF.value = false;
hideLoader(); hideLoader();
}, 1500); });
}) }
.catch((e) => {
// Template
messageError($q, "", "ไม่พบข้อมูล Template");
isLoadPDF.value = false;
hideLoader();
});
} }
/** /**
@ -130,7 +129,7 @@ async function uploadTemplate() {
$q, $q,
async () => { async () => {
showLoader(); showLoader();
const reportName = await `${dataTemplateDetail.value.code}_${type.value}`; const reportName = await `${dataTemplate.value.code}_${type.value}`;
await axios await axios
.post( .post(
config.API.reportTemplate + config.API.reportTemplate +
@ -150,7 +149,7 @@ async function uploadTemplate() {
hideLoader(); hideLoader();
// Template UI // Template UI
fetchDocumentTemplate(dataTemplateDetail.value); fetchDocumentTemplate(dataTemplate.value);
fetchDataTemplate(commandId.value); fetchDataTemplate(commandId.value);
}) })
.catch(async (e) => { .catch(async (e) => {
@ -170,8 +169,8 @@ async function uploadTemplate() {
*/ */
async function downloadTemplate() { async function downloadTemplate() {
const check = await (type.value == "cover" const check = await (type.value == "cover"
? dataTemplateDetail.value.fileCover ? dataTemplate.value.fileCover
: dataTemplateDetail.value.fileAttachment); : dataTemplate.value.fileAttachment);
await axios await axios
.post( .post(
config.API.reportTemplate + `/${typeFile.value}/download?folder=command`, config.API.reportTemplate + `/${typeFile.value}/download?folder=command`,
@ -189,7 +188,7 @@ async function downloadTemplate() {
.then(async (res) => { .then(async (res) => {
var a = document.createElement("a"); var a = document.createElement("a");
a.href = URL.createObjectURL(res.data); a.href = URL.createObjectURL(res.data);
a.download = `${dataTemplateDetail.value.code}_${type.value}.${typeFile.value}`; a.download = `${dataTemplate.value.code}_${type.value}.${typeFile.value}`;
a.click(); a.click();
hideLoader(); hideLoader();
}) })
@ -217,17 +216,16 @@ async function updateReportName(name: string) {
} }
// working on click command list // working on click command list
watch(dataTemplateDetail, () => { watch(
fetchDocumentTemplate(dataTemplateDetail.value); () => dataTemplate.value,
}); async (newValue, oldValue) => {
await fetchDocumentTemplate(newValue);
}
);
// working on change tab // working on change tab
onMounted(() => { onMounted(() => {
fetchDocumentTemplate(dataTemplateDetail.value); fetchDocumentTemplate(dataTemplate.value);
});
defineExpose({
fetchDocumentTemplate,
}); });
</script> </script>

View file

@ -303,13 +303,12 @@ onMounted(async () => {
</label> </label>
</div> </div>
</q-toolbar> </q-toolbar>
<q-separator /> <q-separator />
<q-card-section class="q-pa-sm"> <q-card-section class="q-pa-sm">
<q-list v-for="(item, index) in listOrder" bordered :key="item.id"> <q-list v-for="(item, index) in listOrder" bordered :key="item.id">
<q-item <q-item
clickable :clickable="item.code !== 'C-PM-47'"
v-ripple :v-ripple="item.code !== 'C-PM-47'"
:active="activeCommandId === item.id" :active="activeCommandId === item.id"
active-class="my-menu_link" active-class="my-menu_link"
@click="selectInbox(item)" @click="selectInbox(item)"
@ -325,7 +324,7 @@ onMounted(async () => {
<q-item-section side center @click.stop> <q-item-section side center @click.stop>
<q-icon <q-icon
name="edit" name="edit"
class="q-pa-none q-ml-xs" class="q-pa-none q-ml-xs cursor-pointer"
color="edit" color="edit"
flat flat
dense dense