hrms-user/src/modules/03_retire/views/addRetire.vue
DESKTOP-1R2VSQH\Lenovo ThinkPad E490 5211555eae fix การลาออก
2025-05-29 14:27:15 +07:00

790 lines
27 KiB
Vue

<script setup lang="ts">
import { ref, onMounted } from "vue";
import { useQuasar } from "quasar";
import type { QForm, QTableProps } from "quasar";
import { useRouter, useRoute } from "vue-router";
import http from "@/plugins/http";
import config from "@/app.config";
import { useRestDataStore } from "@/modules/03_retire/store";
import { useCounterMixin } from "@/stores/mixin";
import { useDataStore } from "@/stores/data";
import type {
DataOptions,
RowsType,
SeqTypeRow,
} from "@/modules/03_retire/interface/Main";
import Dialog from "@/modules/03_retire/views/DialogRetire.vue";
import Header from "@/components/DialogHeader.vue";
import Workflow from "@/components/Workflow/Main.vue";
const $q = useQuasar();
const route = useRoute();
const router = useRouter();
const store = useRestDataStore();
const { convertStatusText } = store;
const link = ref<string>("");
const dataStore = useDataStore();
const routeName = router.currentRoute.value.name;
const mixin = useCounterMixin();
const {
date2Thai,
dateToISO,
success,
messageError,
showLoader,
hideLoader,
dialogConfirm,
} = mixin;
const id = ref<string>(
router.currentRoute.value.name !== "AddRetire"
? route.params.id.toString()
: ""
); //เก็บ id path
const rowsApprover = ref<RowsType>();
const myform = ref<QForm | null>(null); //form
const tranferOrg = ref(""); //สถานที่ยื่นขอลาออกจากราชการ
const dateCommand = ref<Date>(new Date()); //วันที่ยื่นขอลาออกจากราชการ
const dateLeave = ref<Date | null>(null); //วันที่ขอลาออกจากราชการ
const noteReason = ref<string>(""); //เหตุผลที่ลาออกจากราชการ
const modal = ref<boolean>(false); //ตัวแปร dialog
const remark = ref<string>(""); //ระบุเหตุผล
const noteReasonOp = ref<DataOptions[]>([
{
id: "CAREER",
name: "ประกอบอาชีพอื่น",
},
{
id: "MOVE",
name: "รับราชการสังกัดอื่น",
},
{
id: "FAMILY",
name: "ดูแลบิดามารดา",
},
{
id: "EDUCATION",
name: "ศึกษาต่อ",
},
{
id: "OTHER",
name: "อื่น ๆ",
},
]);
/** ข้อมูล v-model ของฟอร์ม */
const dataDetail = ref<any>({});
const modalWorkflow = ref<boolean>(false);
const columnsCommanders = ref<QTableProps["columns"]>([
{
name: "no",
align: "left",
label: "ลำดับ",
sortable: true,
field: "no",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "fullName",
align: "left",
label: "ชื่อ-นามสกุล",
sortable: true,
field: "fullName",
format(val, row) {
return `${row.prefix}${row.firstName} ${row.lastName}`;
},
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "positionName",
align: "left",
label: "ตำแหน่ง",
sortable: true,
field: "positionName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "approveStatus",
align: "left",
label: "สถานะ",
sortable: true,
field: "approveStatus",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "comment",
align: "left",
label: "ความคิดเห็นและเหตุผล",
field: "comment",
sortable: true,
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "rejectDate",
align: "left",
label: "วันสุดท้ายที่ยับยั้ง",
field: "rejectDate",
sortable: true,
headerStyle: "font-size: 14px",
style: "font-size: 14px",
format(val, row) {
return `${row.rejectDate ? date2Thai(row.rejectDate) : "-"}`;
},
},
]);
/**
* ฟังก์ชั่นเปลี่ยนเป็น string ของ status
* @param val value ของ status true/false
*/
function statusOrder(val: boolean) {
switch (val) {
case true:
return "ยับยั้ง";
case false:
return "อนุญาต";
}
}
/**
* บันทึกข้อมูลการลาออก
*/
async function onSubmit() {
dialogConfirm(
$q,
() => {
showLoader();
const formData = new FormData();
formData.append("Location", tranferOrg.value);
// formData.append("SendDate", dateToISO(dateCommand.value));
formData.append(
"ActiveDate",
dateLeave.value !== null ? dateToISO(dateLeave.value) : ""
);
formData.append("Reason", noteReason.value);
formData.append("file", files.value);
if (noteReason.value == "OTHER") {
formData.append("remark", remark.value);
}
http
.post(config.API.listResignByType(link.value), formData)
.then((res) => {
let id = res.data.result.id;
if (dataStore.officerType == "OFFICER") {
router.push(`/retire/result/${id}`);
} else {
router.push(`/retire/${id}`);
}
success($q, "บันทึกข้อมูลสำเร็จ");
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
hideLoader();
});
},
"ยืนยันการยื่นข้อมูลลาออก",
"ต้องการยื่นข้อมูลลาออกนี้ใช่หรือไม่"
);
}
const files = ref<any>();
const checkCancleLeave = ref<boolean>(false);
//ยกเลิกการลาออก
function cancelResing() {
modal.value = true;
}
/**
* ฟังก์ชั่นเรียกข้อมูลจาก Api
* @param id ไอดีของข้อมูล
*/
async function fectDataresign(id: string) {
showLoader();
await http
.get(config.API.resingByidType(link.value, id))
.then((res) => {
let data = res.data.result;
tranferOrg.value = data.location;
dateCommand.value = data.sendDate;
dateLeave.value = data.activeDate;
const currentDate = new Date();
let dueDateMinusOne = new Date(data.activeDate);
dueDateMinusOne.setDate(dueDateMinusOne.getDate() - 1);
checkCancleLeave.value = currentDate < dueDateMinusOne;
noteReason.value = data.reason;
remark.value = data.remark;
rowsApprover.value = {
commanders: data.commanders,
approvers: data.approvers,
};
files.value = data.docs;
dataDetail.value = data;
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
hideLoader();
});
}
/**
* เปิด tab ใหม่
* @param data path file
*/
function downloadFile(data: string) {
window.open(data, "_blank");
}
/**
* เรียกฟังก์ชันทั้งหมดตอนเรียกใช้ไฟล์นี้
*/
onMounted(async () => {
link.value = await dataStore.getProFileType();
if (route.params.id !== undefined) {
fectDataresign(id.value);
}
});
</script>
<template>
<div class="col-12 row justify-center">
<div class="col-xs-12 col-sm-12 col-md-11">
<div class="toptitle text-white col-12 row items-center">
<q-btn
icon="mdi-arrow-left"
unelevated
round
dense
flat
color="primary"
class="q-mr-sm"
@click="router.push('/retire')"
/>
<div v-if="routeName == 'AddRetire'">เพิ่มเรื่องลาออก</div>
<div v-else>รายละเอียดเรื่องลาออก</div>
</div>
<q-form
ref="myform"
class="col-12"
greedy
@submit.prevent
@validation-success="onSubmit"
>
<q-card bordered>
<q-card-actions
v-if="routeName !== 'AddRetire'"
style="padding-bottom: 0px"
>
<div class="q-pl-sm text-grey-7" v-if="dataDetail.cancelReason">
เหตุผลการขอยกเลิก :
<spen class="text-red">{{ dataDetail.cancelReason }}</spen>
</div>
<q-space />
<q-btn
v-if="
dataDetail.statusMain !== 'CANCEL' &&
dataDetail.statusMain !== 'DONECANCEL' &&
dataDetail.statusMain !== 'CANCELING' &&
checkCancleLeave
"
unelevated
color="orange"
label="ยกเลิกการลาออก"
@click="cancelResing"
:disable="tranferOrg == '' && noteReason == ''"
/>
<!-- <q-btn
v-else-if="
(dataDetail.statusMain === 'CANCEL' ||
dataDetail.statusMain === 'DONECANCEL') &&
dataStore.officerType == 'OFFICER'
"
unelevated
color="red"
label="ติดตามสถานะยกเลิกการขอลาออก"
@click="modalWorkflow = true"
/> -->
</q-card-actions>
<div class="col-12 row q-col-gutter-sm q-pa-md">
<q-input
:class="
routeName !== 'AddRetire'
? 'col-md-9 col-xs-12'
: 'col-md-9 col-xs-12 inputgreen'
"
class=""
dense
outlined
v-model="tranferOrg"
hide-bottom-space
label="สถานที่ยื่นขอลาออกจากราชการ"
:readonly="routeName != 'AddRetire'"
:rules="[(val:string) => !!val || `${'กรุณากรอกสถานที่ยื่นขอลาออกจากราชการ'}`]"
/>
<!-- <datepicker
:class="
routeName !== 'AddRetire'
? 'col-md-2 col-xs-12'
: 'col-md-2 col-xs-12 inputgreen'
"
menu-class-name="modalfix"
v-model="dateCommand"
:locale="'th'"
autoApply
readonly
borderless
:enableTimePicker="false"
week-start="0"
>
<template #year="{ year }">
{{ year + 543 }}
</template>
<template #year-overlay-value="{ value }">
{{ parseInt(value + 543) }}
</template>
<template #trigger>
<q-input
outlined
readonly
dense
hide-bottom-space
class="full-width"
:model-value="
dateCommand != null ? date2Thai(dateCommand) : null
"
:label="`${'วันที่ยื่นขอลาออกจากราชการ'}`"
:rules="[
(val: string) =>
!!val || `${'กรุณาเลือกวันที่ยื่นขอลาออกจากราชการ'}`,
]"
>
<template v-slot:prepend>
<q-icon
name="event"
class="cursor-pointer"
style="color: var(--q-primary)"
>
</q-icon>
</template>
</q-input>
</template>
</datepicker> -->
<datepicker
:class="
routeName !== 'AddRetire'
? 'col-md-3 col-xs-12'
: 'col-md-3 col-xs-12 inputgreen'
"
menu-class-name="modalfix"
v-model="dateLeave"
:locale="'th'"
autoApply
borderless
:enableTimePicker="false"
week-start="0"
:readonly="routeName != 'AddRetire'"
>
<template #year="{ year }">
{{ year + 543 }}
</template>
<template #year-overlay-value="{ value }">
{{ parseInt(value + 543) }}
</template>
<template #trigger>
<q-input
outlined
dense
hide-bottom-space
:readonly="routeName != 'AddRetire'"
class="full-width"
:model-value="dateLeave != null ? date2Thai(dateLeave) : null"
:label="`${'วันที่ขอลาออกจากราชการ'}`"
:rules="[
(val: string) =>
!!val || `${'กรุณาเลือกวันที่ขอลาออกจากราชการ'}`,
]"
>
<template v-slot:prepend>
<q-icon
name="event"
class="cursor-pointer"
style="color: var(--q-primary)"
>
</q-icon>
</template>
</q-input>
</template>
</datepicker>
<q-select
v-model="noteReason"
:class="
routeName !== 'AddRetire' ? 'col-12' : 'col-12 inputgreen'
"
dense
outlined
emit-value
map-options
hide-bottom-space
option-label="name"
option-value="id"
:options="noteReasonOp"
label="เหตุผลที่ลาออกจากราชการ"
:readonly="routeName != 'AddRetire'"
:rules="[
(val: string) => !!val || `${'กรุณาเลือกเหตุผลที่ลาออกจากราชการ'}`,
]"
>
</q-select>
<q-input
:class="
routeName !== 'AddRetire' ? 'col-12' : 'col-12 inputgreen'
"
v-if="noteReason == 'OTHER'"
v-model="remark"
outlined
hide-bottom-space
dense
type="textarea"
label="ระบุเหตุผล"
:readonly="routeName != 'AddRetire'"
:rules="[
(val: string) => !!val || `${'กรุณาระบุเหตุผล'}`,
]"
></q-input>
<div class="col-12 row" v-if="routeName == 'AddRetire'">
<q-file
v-model="files"
class="col-xs-12 col-sm-12 inputgreen"
outlined
dense
lazy-rules
hide-bottom-space
accept=".pdf"
:rules="[(val: string) => !!val || 'กรุณาเลือกเอกสารเพิ่มเติม']"
label="เอกสารเพิ่มเติม"
>
<template v-slot:prepend>
<q-icon name="attach_file" /> </template
></q-file>
</div>
<div class="col-12 row" v-if="routeName != 'AddRetire'">
<q-card bordered flat class="row col-12 text-dark q-mt-sm">
<div
class="bg-grey-1 q-pa-sm col-12 row items-center text-primary"
>
<div class="q-pl-sm text-weight-bold text-dark">
เอกสารเพิ่มเติม
</div>
</div>
<q-list class="col-12">
<q-item v-for="file in files" :key="file.key" class="q-my-xs">
<q-item-section>
<q-item-label class="full-width ellipsis">
{{ file.fileName }}
</q-item-label>
<q-item-label caption> </q-item-label>
</q-item-section>
<q-space />
<q-btn
size="12px"
flat
round
dense
color="blue"
icon="mdi-download"
@click="downloadFile(file.pathName)"
><q-tooltip>ดาวน์โหลดไฟล์</q-tooltip></q-btn
>
</q-item>
</q-list>
</q-card>
</div>
<!-- <div class="col-12 row" v-if="routeName != 'AddRetire'">
<q-card bordered class="row col-12 text-dark q-mt-sm">
<div
class="bg-grey-1 q-pa-sm col-12 row items-center text-primary"
>
<div class="q-pl-sm text-weight-bold text-dark">
ผลการพิจารณาของการเจ้าหน้าที่ของหน่วยงาน
</div>
</div>
<q-separator />
<div class="row col-12 q-pa-md">
<div class="col-12 row bg-white q-col-gutter-md">
<div class="col-xs-6 row items-start">
<div class="col-12 text-top">สถานะ</div>
<div class="col-12 text-detail">
{{
dataDetail.officerReject !== null
? statusOrder(dataDetail.officerReject)
: "-"
}}
</div>
</div>
<div class="col-xs-6 row items-start">
<div class="col-12 text-top">วันสุดท้ายที่ยับยั้ง</div>
<div class="col-12 text-detail">
{{
dataDetail.officerRejectDate !== null
? date2Thai(dataDetail.officerRejectDate)
: "-"
}}
</div>
</div>
<div class="col-xs-12 row items-start">
<div class="col-12 text-top">ความคิดเห็นและเหตุผล</div>
<div
class="col-12 text-detail"
v-if="dataDetail.officerReject === false"
>
{{
dataDetail.officerApproveReason !== null
? dataDetail.officerApproveReason
: "-"
}}
</div>
<div
class="col-12 text-detail"
v-if="dataDetail.officerReject === true"
>
{{
dataDetail.officerRejectReason !== null
? dataDetail.officerRejectReason
: "-"
}}
</div>
</div>
</div>
</div>
</q-card>
</div> -->
<!-- ผลการพิจารณาของผู้บังคับบัญชา -->
<div class="col-12 row" v-if="routeName != 'AddRetire'">
<q-card bordered class="row col-12 text-dark q-mt-sm">
<div
class="bg-grey-1 q-pa-sm col-12 row items-center text-primary"
>
<div class="q-pl-sm text-weight-bold text-dark">
ผลการพิจารณาของผู้บังคับบัญชา
</div>
</div>
<q-separator />
<div class="col-12">
<d-table
ref="table"
:columns="columnsCommanders"
:rows="rowsApprover?.commanders ?? []"
row-key="key"
flat
bordered
:paging="true"
dense
:rows-per-page-options="[1, 25, 50, 100]"
>
<template v-slot:header="props">
<q-tr :props="props">
<q-th
v-for="col in props.cols"
:key="col.name"
:props="props"
>
<span class="text-weight-medium">{{
col.label
}}</span>
</q-th>
</q-tr>
</template>
<template v-slot:body="props">
<q-tr :props="props" class="cursor-pointer">
<q-td
v-for="col in props.cols"
:key="col.name"
:props="props"
>
<div v-if="col.name == 'no'">
{{ props.rowIndex + 1 }}
</div>
<div v-else-if="col.name == 'approveStatus'">
{{
props.row.approveStatus
? convertStatusText(props.row.approveStatus)
: "-"
}}
</div>
<div v-else>
{{ col.value ? col.value : "-" }}
</div>
</q-td>
</q-tr>
</template>
</d-table>
</div>
</q-card>
</div>
<!-- ผลการพจารณาของผอำนาจ -->
<div class="col-12 row" v-if="routeName != 'AddRetire'">
<q-card bordered class="row col-12 text-dark q-mt-sm">
<div
class="bg-grey-1 q-pa-sm col-12 row items-center text-primary"
>
<div class="q-pl-sm text-weight-bold text-dark">
ผลการพจารณาของผอำนาจ
</div>
</div>
<q-separator />
<div class="row col-12 q-pa-md">
<div class="col-12 row bg-white q-col-gutter-md">
<div class="col-xs-6 row items-start">
<div class="col-12 text-top"> - นามสก</div>
<div class="col-12 text-detail">
{{
rowsApprover &&
rowsApprover.approvers &&
rowsApprover.approvers[0]?.firstName
? `${rowsApprover?.approvers[0].prefix}${rowsApprover?.approvers[0].firstName} ${rowsApprover?.approvers[0].lastName}`
: "-"
}}
</div>
</div>
<div class="col-xs-6 row items-start">
<div class="col-12 text-top">สถานะ</div>
<div class="col-12 text-detail">
{{
rowsApprover &&
rowsApprover.approvers &&
rowsApprover.approvers[0]?.approveStatus
? convertStatusText(
rowsApprover?.approvers[0].approveStatus
)
: "-"
}}
</div>
</div>
<div class="col-xs-6 row items-start">
<div class="col-12 text-top">นสดทายทบย</div>
<div class="col-12 text-detail">
{{
rowsApprover &&
rowsApprover.approvers &&
rowsApprover.approvers[0]?.rejectDate
? date2Thai(rowsApprover?.approvers[0].rejectDate)
: "-"
}}
</div>
</div>
<div class="col-xs-12 row items-start">
<div class="col-12 text-top">ความคดเหนและเหตผล</div>
<div class="col-12 text-detail">
{{
rowsApprover &&
rowsApprover.approvers &&
rowsApprover.approvers[0]?.comment
? rowsApprover?.approvers[0].comment
: "-"
}}
</div>
</div>
</div>
</div>
</q-card>
</div>
</div>
<q-separator v-if="routeName == 'AddRetire'" />
<q-card-actions
align="right"
v-if="routeName == 'AddRetire'"
class="q-px-md"
>
<q-space />
<q-btn
unelevated
class="q-px-md items-center"
color="primary"
label="ยื่นเรื่องขอลาออก"
type="submit"
/>
</q-card-actions>
</q-card>
</q-form>
<div
class="col-12 row q-mt-sm"
v-if="
routeName != 'AddRetire' &&
dataDetail.status !== 'DELETE' &&
dataDetail.status !== 'CANCEL' &&
dataDetail.status !== 'DONECANCEL' &&
dataDetail.status !== 'DONEREJECT' &&
dataStore.officerType == 'OFFICER'
"
>
<!-- <Workflow :id="id" sys-name="SYS_RESIGN" /> -->
</div>
</div>
</div>
<Dialog
v-model:modal="modal"
:fectData="fectDataresign"
v-model:link="link"
/>
<q-dialog v-model="modalWorkflow" persistent>
<q-card style="width: 700px; max-width: 80vw">
<Header
:tittle="`ติดตามสถานะยกเลิกการขอลาออก`"
:close="
() => {
modalWorkflow = false;
}
"
/>
<q-separator />
<q-card-section>
<Workflow :id="id" sys-name="RETIREMENT_CANCEL" />
</q-card-section>
</q-card>
</q-dialog>
</template>
<style scoped>
.text-top {
color: gray;
font-weight: 400;
padding-bottom: 3px;
}
.text-detail {
font-weight: 500;
}
</style>