hrms-user/src/modules/06_evaluate/components/viewstep/viewStep1.vue
DESKTOP-1R2VSQH\Lenovo ThinkPad E490 7d95116c25 fix fetch profilePosition
2025-07-25 15:08:35 +07:00

837 lines
26 KiB
Vue

div
<script setup lang="ts">
import { reactive, onMounted, ref } from "vue";
import { useRoute } from "vue-router";
import { useQuasar } from "quasar";
import http from "@/plugins/http";
import config from "@/app.config";
import { useCounterMixin } from "@/stores/mixin";
import { useEvaluateDetailStore } from "@/modules/06_evaluate/stores/evaluteDetail";
import { useEvaluateStore } from "@/modules/06_evaluate/store";
import { useDataStore } from "@/stores/data";
/** importType*/
import type { DataProfile } from "@/interface/Main";
import type {
EducationForm,
CertificatesForm,
} from "@/modules/06_evaluate/interface/evalute";
/** importComponents*/
import TableData from "@/modules/06_evaluate/components/viewstep/tableStep1.vue";
import HeaderDialog from "@/components/DialogHeader.vue";
/** use*/
const mixin = useCounterMixin();
const store = useEvaluateDetailStore();
const storeEva = useEvaluateStore();
const storeData = useDataStore();
const $q = useQuasar();
const route = useRoute();
const { showLoader, hideLoader, messageError, date2Thai, findOrgNameHtml } =
mixin;
const {
columnsCertificates,
columnSalaries,
columnTraining,
columnExperience,
columnAssessments,
} = store;
const props = defineProps({
data: {
type: Object,
},
});
const emit = defineEmits(["update:formDeital"]);
const formDetail = reactive<any>({
userId: "",
citizenId: "",
prefix: "",
fullName: "",
position: "",
oc: "",
org: "",
salary: "",
positionLevel: "",
posNo: "",
birthDate: "",
govAge: "",
govAgeMap: {
year: 0,
month: 0,
day: 0,
},
posExecutive: "",
positionArea: "",
educations: [] as EducationForm[],
certificates: [],
salaries: [],
trainings: [],
assessments: [],
experience: [],
honor: [],
});
/** function เรียกข้อมูลตรวจสอบคุณสมบัติ*/
async function fetchDetail() {
try {
if (!storeData.dataprofilePosition) {
const res = await http.get(config.API.profilePosition());
await updateFormDetail(res.data.result);
} else {
await updateFormDetail(storeData.dataprofilePosition);
}
} catch (error) {
messageError($q, error);
}
}
async function updateFormDetail(data: DataProfile) {
formDetail.root = data.root;
formDetail.rootId = data.rootId;
formDetail.userId = data.profileId;
formDetail.citizenId = data.citizenId;
formDetail.prefix = data.prefix;
formDetail.fullName = `${data.firstName} ${data.lastName}`;
formDetail.firstName = data.firstName;
formDetail.lastName = data.lastName;
formDetail.position = data.position;
formDetail.oc = data.rootShortName;
formDetail.positionLevel = data.posLevelName;
formDetail.posNo = data.posNo ?? "";
formDetail.birthDate = data.birthDate;
// formDetail.govAge = data.govAge; // ยังไม่มี
formDetail.salary = data.salary;
formDetail.posExecutive = data.posExecutiveName;
formDetail.positionArea = data.positionArea;
await fetchDataAllDetail();
emit("update:formDeital", formDetail);
}
async function fetchDataAllDetail() {
// ดึงข้อมูลประวัติการศึกษา
http.get(config.API.dataUserEducations).then((res) => {
formDetail.educations = res.data.result;
});
// ดึงข้อมูลใบอนุญาตประกอบวิชาชีพ
http.get(config.API.dataUserCertificate("certificate")).then((res) => {
formDetail.certificates = res.data.result.map((e: CertificatesForm) => ({
certificateNo: e.certificateNo,
certificateType: e.certificateType,
expireDate: e.expireDate,
issueDate: e.issueDate,
issuer: e.issuer,
}));
});
// ดึงข้อมูลประวัติการรับราชการ
http.get(config.API.dataUserSalaryPosition).then((res) => {
formDetail.salaries = res.data.result;
});
// ดึงข้อมูลประวัติการฝึกอบรมดูงาน
http.get(config.API.dataUserCertificate("training")).then((res) => {
formDetail.trainings = res.data.result.map((e: any) => ({
dateOrder: e.dateOrder,
department: e.department,
duration: e.duration,
endDate: e.endDate,
name: e.name,
numberOrder: e.numberOrder,
place: e.place,
startDate: e.startDate,
topic: e.topic,
yearly: e.yearly,
}));
});
http.get(config.API.dataUserPerformance).then((res) => {
formDetail.assessments = res.data.result.map((e: any) => ({
...e,
isAdd: false,
}));
});
http.get(config.API.dataUserPortfolio).then((res) => {
formDetail.experience = res.data.result;
});
}
/**
* function fetchData ตรวจสอบคุณสมบัติ
* @param id ประเมิน
*/
async function fetchCheckSpec(data: any) {
formDetail.userId = data.id;
formDetail.citizenId = data.citizenId;
formDetail.prefix = data.prefix;
formDetail.fullName = data.fullName;
formDetail.position = data.position;
formDetail.oc = data.oc;
formDetail.salary = data.salary ? formattedNumber(data.salary) : "";
formDetail.positionLevel = data.positionLevel;
formDetail.posNo = data.posNo;
formDetail.birthDate = data.birthDate;
formDetail.educations = data.educations;
formDetail.certificates = data.certificates.map((e: CertificatesForm) => ({
certificateNo: e.certificateNo,
certificateType: e.certificateType,
expireDate: date2Thai(e.expireDate),
issueDate: date2Thai(e.issueDate),
issuer: e.issuer,
}));
formDetail.salaries = data.salaries;
formDetail.trainings = data.trainings.map((e: any) => ({
dateOrder: date2Thai(e.dateOrder),
department: e.department,
duration: e.duration,
endDate: date2Thai(e.endDate),
name: e.name,
numberOrder: e.numberOrder,
place: e.place,
startDate: date2Thai(e.startDate),
topic: e.topic,
yearly: e.yearly,
}));
formDetail.assessments = data.performances;
formDetail.experience = data.portfolios;
}
/**
* function convertตัวเลข
* @param x
*/
function formattedNumber(x: number) {
if (x) {
return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
} else {
return "";
}
}
/** get data */
function getData() {
http
.get(config.API.dataUserGovernment)
.then(async (res) => {
const data = await res.data.result;
formDetail.org = data.org;
formDetail.govAge = data.govAge
? `${data.govAge.year} ปี ${data.govAge.month} เดือน ${data.govAge.day} วัน`
: "";
})
.catch((e) => {
messageError($q, e);
});
}
/** ผลงานที่เคยเสนอขอ*/
const modalPerformance = ref<boolean>(false);
const isEdit = ref<boolean>(false);
const isIndex = ref<number>();
const formPerformance = reactive<any>({
year: null,
type: "",
subject: "",
evaluationResult: "",
});
const typeOptions = ref<string[]>([
"ประเมินชำนาญการ",
"ประเมินชำนาญการพิเศษ",
"ประเมินเชี่ยวชาญ",
]);
const resultOptions = ref<any[]>([
{ label: "ผ่าน", value: "ผ่าน" },
{ label: "ไม่ผ่าน", value: "ไม่ผ่าน" },
]);
function onOpenDialogPerformance(
stetusEdit: boolean = false,
index: number | null = null
) {
if (stetusEdit && index !== null) {
isIndex.value = index;
const data = formDetail.assessments[index];
formPerformance.year = data.year ? Number(data.year) - 543 : null;
formPerformance.type = data.type;
formPerformance.subject = data.subject;
formPerformance.evaluationResult = data.evaluationResult;
}
isEdit.value = stetusEdit;
modalPerformance.value = true;
}
function onCloseDialogPerformance() {
modalPerformance.value = false;
formPerformance.year = null;
formPerformance.type = "";
formPerformance.subject = "";
formPerformance.evaluationResult = "";
}
function onSubmitPerformance() {
const body = {
...formPerformance,
year: formPerformance.year ? Number(formPerformance.year) + 543 : null,
isAdd: true,
};
if (isEdit.value && isIndex.value !== null && isIndex.value !== undefined) {
formDetail.assessments[isIndex.value] = body;
} else {
formDetail.assessments.push(body);
}
onCloseDialogPerformance();
}
function onDeletePerformance(index: number) {
formDetail.assessments.splice(index, 1);
}
onMounted(async () => {
try {
showLoader();
const promises = [];
if (route.name === "evaluate-add") {
promises.push(fetchDetail());
}
if (props.data) {
promises.push(fetchCheckSpec(props.data));
}
promises.push(getData());
await Promise.all(promises);
} catch (error) {
console.log(error);
} finally {
hideLoader();
}
});
</script>
<template>
<q-card
bordered
class="col-12 row shadow-0 q-pa-sm"
:style="$q.screen.lt.sm ? '' : 'height: 60vh; overflow: scroll;'"
>
<div class="row col-12">
<q-card class="col-12 cardSp1" bordered>
<div class="text-weight-bold row items-center bg-grey-2 col-12">
<span class="q-ml-lg q-my-sm">อมลสวนต</span>
</div>
<div class="col-12"><q-separator /></div>
<div class="row col-12 q-pa-sm">
<div class="row q-col-gutter-sm">
<div class="col-xs-6 col-sm-4 col-md-3">
<q-input
borderless
readonly
:model-value="formDetail.prefix"
label="คำนำหน้าชื่อ"
></q-input>
</div>
<div class="col-xs-6 col-sm-4 col-md-3">
<q-input
borderless
readonly
:model-value="formDetail.fullName"
label="ชื่อ - นามสกุล"
/>
</div>
<div class="col-xs-6 col-sm-4 col-md-3">
<q-input
borderless
:model-value="
formDetail.birthDate ? date2Thai(formDetail.birthDate) : '-'
"
readonly
label="วันเดือนปีเกิด"
>
</q-input>
</div>
<div class="col-xs-6 col-sm-4 col-md-3">
<q-input
borderless
readonly
:model-value="formDetail.position"
label="ตำแหน่ง"
/>
</div>
<div class="col-xs-6 col-sm-4 col-md-3">
<q-input
borderless
readonly
:model-value="`${formDetail.posNo ? formDetail.posNo : '-'}`"
label="เลขที่ตำแหน่ง"
/>
</div>
<div class="col-xs-6 col-sm-4 col-md-3">
<q-input
borderless
readonly
:model-value="
formDetail.salary
? formDetail.salary.toLocaleString('th-TH')
: ''
"
label="เงินเดือน"
/>
</div>
<div class="col-xs-6 col-sm-4 col-md-3">
<q-input
borderless
readonly
:model-value="formDetail.positionLevel"
label="ระดับปัจจุบัน"
/>
</div>
<div class="col-xs-6 col-sm-4 col-md-3">
<q-input
borderless
readonly
:model-value="formDetail.positionLevel"
label="ระดับที่ประเมิน"
/>
</div>
<div class="col-xs-6 col-sm-4 col-md-3">
<q-input
borderless
readonly
:model-value="formDetail.govAge ? formDetail.govAge : '-'"
label="อายุราชการ"
/>
</div>
<div class="col-xs-12 col-sm-9 text-html">
<q-input
borderless
readonly
:model-value="formDetail.org"
label="สังกัด"
autogrow
/>
</div>
</div>
</div>
</q-card>
<q-card class="col-12 cardSp1" bordered>
<div class="text-weight-bold row items-center bg-grey-2 col-12">
<span class="q-ml-lg q-my-sm">ประวการศกษา </span>
</div>
<div class="col-12"><q-separator /></div>
<div
class="row col-12 q-pa-sm"
v-if="formDetail.educations && formDetail.educations.length > 0"
>
<div
class="row q-col-gutter-sm"
v-for="(education, index) in formDetail.educations"
:key="index"
>
<div class="col-xs-6 col-sm-4 col-md-3">
<q-input
borderless
readonly
:model-value="
education.educationLevel ? education.educationLevel : '-'
"
label="ระดับศึกษา"
/>
</div>
<div class="col-xs-6 col-sm-4 col-md-3">
<q-input
borderless
readonly
:model-value="education.institute ? education.institute : '-'"
label="สถานศึกษา"
/>
</div>
<div class="col-xs-6 col-sm-4 col-md-3">
<q-input
borderless
:model-value="
education.startDate ? date2Thai(education.startDate) : '-'
"
readonly
label="ตั้งแต่"
>
</q-input>
</div>
<div class="col-xs-6 col-sm-4 col-md-3">
<q-input
borderless
:model-value="
education.endDate ? date2Thai(education.endDate) : '-'
"
readonly
label="ถึง"
>
</q-input>
</div>
<div class="col-xs-6 col-sm-4 col-md-3">
<q-input
borderless
:model-value="
education.finishDate ? date2Thai(education.finishDate) : '-'
"
readonly
label="วันที่สำเร็จการศึกษา"
>
</q-input>
</div>
<div class="col-xs-6 col-sm-4 col-md-3">
<q-input
borderless
readonly
:model-value="education.isEducation ? 'ใช่' : 'ไม่ใช่'"
label="วุฒิการศึกษาในตําแหน่ง"
/>
</div>
<div class="col-xs-6 col-sm-4 col-md-3">
<q-input
borderless
readonly
:model-value="education.degree ? education.degree : '-'"
label="วุฒิการศึกษา"
/>
</div>
<div class="col-xs-6 col-sm-4 col-md-3">
<q-input
borderless
readonly
:model-value="education.field ? education.field : '-'"
label="สาขาวิชา/ทาง"
/>
</div>
<div class="col-xs-6 col-sm-4 col-md-3">
<q-input
borderless
readonly
:model-value="education.fundName ? education.fundName : '-'"
label="ทุน"
/>
</div>
<div class="col-xs-6 col-sm-4 col-md-3">
<q-input
borderless
readonly
:model-value="education.gpa ? education.gpa : '-'"
label="เกรดเฉลี่ย"
/>
</div>
<div class="col-xs-6 col-sm-4 col-md-6">
<q-input
borderless
readonly
:model-value="education.country ? education.country : '-'"
label="ประเทศ"
/>
</div>
<div
v-if="index + 1 !== formDetail.educations.length"
class="col-12"
>
<q-separator size="2px" />
</div>
</div>
</div>
<div v-else class="row col-12 q-pa-md">ไม่มีประวัติการศึกษา</div>
</q-card>
<q-card class="col-12 cardSp1" bordered>
<div class="text-weight-bold row items-center bg-grey-2 col-12">
<span class="q-ml-lg q-my-sm">ใบอนุญาตประกอบวิชาชีพ</span>
</div>
<div class="col-12"><q-separator /></div>
<TableData
class="col-12"
:columns="columnsCertificates"
:row="formDetail.certificates"
/>
</q-card>
<q-card class="col-12 cardSp1" bordered>
<div class="text-weight-bold row items-center bg-grey-2 col-12">
<span class="q-ml-lg q-my-sm">ประวัติการรับราชการ</span>
</div>
<div class="col-12"><q-separator /></div>
<div class="col-10">
<d-table
ref="table"
row-key="id"
flat
bordered
dense
:columns="columnSalaries"
:rows="formDetail.salaries"
:paging="true"
:rows-per-page-options="[20, 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.id"
class="vertical-top"
>
<div v-if="col.name == 'organization'" class="text-html">
{{
props.row
? findOrgNameHtml({
root: props.row.orgRoot,
child1: props.row.orgChild1,
child2: props.row.orgChild2,
child3: props.row.orgChild3,
child4: props.row.orgChild4,
})
: "-"
}}
</div>
<div v-else class="table_ellipsis">
{{ col.value ? col.value : "-" }}
</div>
</q-td>
</q-tr>
</template>
</d-table>
</div>
</q-card>
<q-card class="col-12 cardSp1" bordered>
<div class="text-weight-bold row items-center bg-grey-2 col-12">
<span class="q-ml-lg q-my-sm">ประวัติการฝึกอบรมดูงาน</span>
</div>
<div class="col-12"><q-separator /></div>
<TableData
class="col-12"
:columns="columnTraining"
:row="formDetail.trainings"
/>
</q-card>
<q-card class="col-12 cardSp1" bordered>
<div class="text-weight-bold row items-center bg-grey-2 col-12">
<span class="q-ml-lg q-my-sm">ประสบการณ์ในการปฏิบัติงาน </span>
</div>
<div class="col-12"><q-separator /></div>
<TableData
class="col-12"
:columns="columnExperience"
:row="formDetail.experience"
/>
</q-card>
<q-card class="col-12 cardSp1" bordered>
<div class="text-weight-bold row items-center bg-grey-2 col-12">
<span class="q-ml-lg q-my-sm">ผลงานที่เคยเสนอขอประเมิน (ถ้ามี) </span>
<q-btn
v-if="storeEva.currentStep === 1"
class="q-ml-sm"
flat
round
dense
color="primary"
icon="add"
@click.stop="onOpenDialogPerformance(false)"
>
<q-tooltip>เพิ่มข้อมูล </q-tooltip>
</q-btn>
</div>
<div class="col-12"><q-separator /></div>
<div class="col-10">
<div class="q-pa-sm row col-12">
<d-table
flat
bordered
:columns="columnAssessments"
:rows="formDetail.assessments"
dense
:rows-per-page-options="[10, 25, 50, 100]"
virtual-scroll
class="row col-12"
:style="$q.screen.lt.sm ? 'width: 80vw' : 'width: 50vw;'"
>
<template v-slot:header="props">
<q-tr :props="props" class="bg-grey-2">
<q-th auto-widt v-if="storeEva.currentStep === 1" />
<q-th
v-for="col in props.cols"
:key="col.name"
:props="props"
>
<span class="text-body2 text-black">{{ col.label }}</span>
</q-th>
</q-tr>
</template>
<template v-slot:body="props">
<q-tr :props="props">
<q-td auto-widt v-if="storeEva.currentStep === 1">
<q-btn
v-if="props.row.isAdd"
flat
dense
round
color="edit"
icon="edit"
@Click.stop.prevent="
onOpenDialogPerformance(true, props.rowIndex)
"
>
<q-tooltip>แกไข</q-tooltip>
</q-btn>
<q-btn
v-if="props.row.isAdd"
flat
dense
round
color="red"
icon="delete"
@click.stop.pervent="onDeletePerformance(props.rowIndex)"
>
<q-tooltip>ลบ</q-tooltip>
</q-btn>
</q-td>
<q-td
v-for="col in props.cols"
:key="col.name"
:props="props"
>
<div>
{{ !col.value ? "-" : col.value }}
</div>
</q-td>
</q-tr>
</template>
</d-table>
</div>
</div>
</q-card>
</div>
</q-card>
<q-dialog v-model="modalPerformance" persistent>
<q-card style="min-width: 35%">
<q-form greedy @submit.prevent @validation-success="onSubmitPerformance">
<HeaderDialog
:tittle="'ผลงานที่เคยเสนอขอประเมิน (ถ้ามี)'"
:close="onCloseDialogPerformance"
/>
<q-separator />
<q-card-section>
<div class="row q-col-gutter-sm">
<div class="col-12">
<datepicker
menu-class-name="modalfix"
v-model="formPerformance.year"
:locale="'th'"
autoApply
year-picker
:enableTimePicker="false"
>
<template #year="{ year }">{{ year + 543 }}</template>
<template #year-overlay-value="{ value }">{{
parseInt(value + 543)
}}</template>
<template #trigger>
<q-input
dense
outlined
:model-value="
!formPerformance.year
? null
: Number(formPerformance.year) + 543
"
:label="`${'ปี พ.ศ.'}`"
:rules="[(val:string) => !!val || 'กรุณาเลือกปี พ.ศ.']"
hide-bottom-space
>
<template v-slot:prepend>
<q-icon
name="event"
class="cursor-pointer"
style="color: var(--q-primary)"
>
</q-icon>
</template>
</q-input>
</template>
</datepicker>
</div>
<div class="col-12">
<q-select
dense
outlined
label="ระดับตอนที่ยืนขอ"
hide-bottom-space
v-model="formPerformance.type"
:options="typeOptions"
/>
</div>
<div class="col-12">
<q-input
v-model="formPerformance.subject"
label="เรื่อง/ชื่อเรื่อง"
outlined
dense
hide-bottom-space
/>
</div>
<div class="col-12">
<q-option-group
:options="resultOptions"
type="radio"
v-model="formPerformance.evaluationResult"
inline
/>
</div>
</div>
</q-card-section>
<q-separator />
<q-card-actions align="right">
<q-btn label="บันทึก" color="public" type="submit" />
</q-card-actions>
</q-form>
</q-card>
</q-dialog>
</template>
<style>
.cardSp1 {
border: 1px solid #d6dee1;
margin-bottom: 10px;
box-shadow: none !important;
}
</style>