602 lines
17 KiB
Vue
602 lines
17 KiB
Vue
<script setup lang="ts">
|
|
import { ref, onMounted, computed, watch, reactive } from "vue";
|
|
import { useQuasar, type QTableProps } from "quasar";
|
|
import { useRoute } from "vue-router";
|
|
|
|
import DialogListCriteria from "@/modules/14_KPI/components/Tab/Dialog/DialogListCriteria.vue";
|
|
|
|
import config from "@/app.config";
|
|
import http from "@/plugins/http";
|
|
|
|
import Work from "@/modules/14_KPI/components/Tab/Topic/01_Indicator.vue";
|
|
import Competency from "@/modules/14_KPI/components/Tab/Topic/02_Competency.vue";
|
|
import Develop from "@/modules/14_KPI/components/Tab/Topic/03_Develop.vue";
|
|
|
|
import { useCounterMixin } from "@/stores/mixin";
|
|
import { useKpiDataStore } from "@/modules/14_KPI/store";
|
|
|
|
import type { ListCriteria } from "@/modules/14_KPI/interface/request/index";
|
|
const dataListCriteria = ref<ListCriteria[]>([]);
|
|
|
|
const modalCriteria = ref<boolean>(false);
|
|
const $q = useQuasar();
|
|
const route = useRoute();
|
|
const { hideLoader, messageError, success, showLoader, dialogRemove } =
|
|
useCounterMixin();
|
|
const store = useKpiDataStore();
|
|
|
|
const evaluationId = ref<string>(route.params.id.toString());
|
|
|
|
const rows_01 = ref<any[]>([]);
|
|
const rows_02 = ref<any[]>([]);
|
|
const rows_03 = ref<any[]>([]);
|
|
|
|
const totalResults1 = ref<number>(0);
|
|
const totalResults2 = ref<number>(0);
|
|
const totalResults3 = ref<number>(0);
|
|
// const resultWork = ref<number>(0);
|
|
|
|
const weightPlanned = ref<number>(0);
|
|
const weightRole = ref<number>(0);
|
|
const weightAssigned = ref<number>(0);
|
|
const resultPlanned = ref<number>(0);
|
|
const resultRole = ref<number>(0);
|
|
const resultAssigned = ref<number>(0);
|
|
|
|
function fetchListPlanned() {
|
|
http
|
|
.get(config.API.kpiAchievement("planned") + `?id=${evaluationId.value}`)
|
|
.then((res) => {
|
|
const data = res.data.result;
|
|
const newRow = data.map((e: any) => ({
|
|
...e,
|
|
evaluationResults: (e.point / 5) * e.weight,
|
|
}));
|
|
rows_01.value = newRow;
|
|
|
|
if (newRow.length > 0) {
|
|
resultPlanned.value = newRow.reduce(
|
|
(sum: number, e: any) => sum + e.evaluationResults,
|
|
0
|
|
);
|
|
store.excusiveIndicator1PercentVal = resultPlanned.value;
|
|
|
|
const weight = newRow.reduce(
|
|
(sum: number, e: any) => sum + e.weight,
|
|
0
|
|
);
|
|
|
|
weightPlanned.value = weight;
|
|
store.indicatorWeight1Total = Number(weight);
|
|
|
|
totalResults1.value =
|
|
(resultPlanned.value * store.excusiveIndicator1Weight) / weight;
|
|
store.excusiveIndicator1ScoreVal = totalResults1.value;
|
|
}
|
|
})
|
|
.catch((err) => {
|
|
messageError($q, err);
|
|
});
|
|
}
|
|
|
|
function fetchListRole() {
|
|
http
|
|
.get(config.API.kpiAchievement("role") + `?id=${evaluationId.value}`)
|
|
.then((res) => {
|
|
const data = res.data.result;
|
|
const newRow = data.map((e: any) => ({
|
|
...e,
|
|
evaluationResults: (e.point / 5) * e.weight,
|
|
}));
|
|
rows_02.value = newRow;
|
|
|
|
if (newRow.length > 0) {
|
|
resultRole.value = newRow.reduce(
|
|
(sum: number, e: any) => sum + e.evaluationResults,
|
|
0
|
|
);
|
|
|
|
const weight = newRow.reduce(
|
|
(sum: number, e: any) => sum + e.weight,
|
|
0
|
|
);
|
|
|
|
weightRole.value = weight;
|
|
}
|
|
})
|
|
.catch((err) => {
|
|
messageError($q, err);
|
|
});
|
|
}
|
|
|
|
function fetchAssigned() {
|
|
http
|
|
.get(config.API.kpiAchievement("special") + `?id=${evaluationId.value}`)
|
|
.then((res) => {
|
|
const data = res.data.result;
|
|
const newRow = data.map((e: any) => ({
|
|
...e,
|
|
evaluationResults: (e.point / 5) * e.weight,
|
|
}));
|
|
|
|
rows_03.value = newRow;
|
|
|
|
if (newRow.length > 0) {
|
|
resultAssigned.value = newRow.reduce(
|
|
(sum: number, e: any) => sum + e.evaluationResults,
|
|
0
|
|
);
|
|
|
|
store.excusiveIndicator2PercentVal = resultAssigned.value;
|
|
|
|
const weight = newRow.reduce(
|
|
(sum: number, e: any) => sum + e.weight,
|
|
0
|
|
);
|
|
|
|
weightAssigned.value = weight;
|
|
store.indicatorWeight2Total = Number(weight);
|
|
|
|
totalResults3.value =
|
|
(resultAssigned.value * store.excusiveIndicator2Weight) / weight;
|
|
store.excusiveIndicator2ScoreVal = totalResults3.value;
|
|
}
|
|
})
|
|
.catch((err) => {
|
|
messageError($q, err);
|
|
});
|
|
}
|
|
|
|
function getCriteria() {
|
|
http
|
|
.get(config.API.KpiEvaluationInfo)
|
|
.then((res) => {
|
|
const data = res.data.result.data;
|
|
dataListCriteria.value = data;
|
|
})
|
|
.catch((e) => {
|
|
messageError($q, e);
|
|
});
|
|
}
|
|
|
|
const isShowScore = computed(() => {
|
|
return store.tabMain === "3";
|
|
});
|
|
|
|
watch(
|
|
[weightPlanned, weightRole, weightAssigned],
|
|
([newA, newB, newC], [prevA, prevB, prevC]) => {
|
|
if (newA !== prevA || newB !== prevB || newC !== prevC) {
|
|
store.indicatorWeightTotal =
|
|
Number(weightPlanned.value) +
|
|
Number(weightAssigned.value) +
|
|
Number(weightRole.value);
|
|
}
|
|
}
|
|
);
|
|
|
|
watch(
|
|
[resultPlanned, resultRole, resultAssigned],
|
|
([newA, newB, newC], [prevA, prevB, prevC]) => {
|
|
if (newA !== prevA || newB !== prevB || newC !== prevC) {
|
|
store.indicatorPercentVal =
|
|
Number(resultPlanned.value) +
|
|
Number(resultRole.value) +
|
|
Number(resultAssigned.value);
|
|
|
|
store.indicatorScoreVal =
|
|
store.indicatorPercentVal * (store.indicatorScore / 100);
|
|
|
|
if (store.isUpdate && store.tabMain === "3") {
|
|
http
|
|
.put(config.API.updatePoint(evaluationId.value), {
|
|
totalPoint1: (
|
|
store.indicatorPercentVal *
|
|
(store.indicatorScore / 100)
|
|
).toFixed(2),
|
|
summaryPoint: (
|
|
store.indicatorScoreVal +
|
|
store.competencyScoreVal +
|
|
store.devScoreVal
|
|
).toFixed(2),
|
|
})
|
|
.then((res) => {});
|
|
}
|
|
}
|
|
}
|
|
);
|
|
|
|
onMounted(() => {
|
|
showLoader(),
|
|
Promise.all([
|
|
getCriteria(),
|
|
fetchListPlanned(),
|
|
fetchListRole(),
|
|
fetchAssigned(),
|
|
]).finally(() => {
|
|
setTimeout(() => {
|
|
hideLoader();
|
|
}, 2500);
|
|
});
|
|
});
|
|
</script>
|
|
|
|
<template>
|
|
<q-scroll-area
|
|
style="height: 100vh; width: auto"
|
|
class="bg-white row col-12 text-dark q-pa-md"
|
|
>
|
|
<div class="text-weight-bold text-body2">
|
|
<span class="txt-under text-blue-6">องค์ประกอบที่ 1 </span>
|
|
<span class="q-ml-sm"> ผลสัมฤทธิ์ของงาน</span>
|
|
</div>
|
|
<div class="q-gutter-md q-mt-sm">
|
|
<!-- องค์ประกอบที่ 1 -->
|
|
<div
|
|
v-if="
|
|
store.dataEvaluation.posTypeName == 'อำนวยการ' &&
|
|
store.dataEvaluation.posTypeName == 'บริหาร'
|
|
"
|
|
>
|
|
<Work
|
|
v-model:data="rows_01"
|
|
:title="`มิติที่ 1 ภารกิจตามนโยบายและยุทธศาสตร์ของกรุงเทพมหานคร`"
|
|
:page="1"
|
|
:fetchList="fetchListPlanned"
|
|
:total="totalResults1"
|
|
/>
|
|
|
|
<div v-if="isShowScore">
|
|
<q-table
|
|
flat
|
|
dense
|
|
bordered
|
|
:rows="[
|
|
{
|
|
name: 'รวมผลการประเมิน (ร้อยละ)',
|
|
value: store.excusiveIndicator1PercentVal.toFixed(2),
|
|
},
|
|
{
|
|
name: 'ผลการประเมินมิติที่ 1 (คะแนน)',
|
|
value: store.excusiveIndicator1ScoreVal.toFixed(2),
|
|
},
|
|
]"
|
|
:columns="[
|
|
{
|
|
name: 'name',
|
|
field: 'name',
|
|
label: 'name',
|
|
style: 'font-size: 14px',
|
|
},
|
|
{
|
|
name: 'value',
|
|
field: 'value',
|
|
label: 'value',
|
|
style: 'font-size: 14px; font-weight: bold',
|
|
},
|
|
]"
|
|
row-key="name"
|
|
hide-header
|
|
hide-bottom
|
|
class="q-mt-xs q-mb-md"
|
|
/>
|
|
</div>
|
|
|
|
<div v-else class="q-mt-md"></div>
|
|
|
|
<Work
|
|
v-model:data="rows_03"
|
|
:title="`มิติที่ 2 วาระเร่งด่วนที่ได้รับมอบหมายพิเศษ (ถ้ามี)`"
|
|
:page="3"
|
|
:fetchList="fetchAssigned"
|
|
:total="totalResults3"
|
|
/>
|
|
|
|
<div v-if="isShowScore">
|
|
<q-table
|
|
flat
|
|
dense
|
|
bordered
|
|
:rows="[
|
|
// {
|
|
// name: 'รวมผลการประเมิน (ร้อยละ)',
|
|
// value: store.excusiveIndicator2PercentVal.toFixed(2),
|
|
// },
|
|
{
|
|
name: 'ผลการประเมินมิติที่ 2 (คะแนน)',
|
|
value: store.excusiveIndicator2ScoreVal.toFixed(2),
|
|
},
|
|
]"
|
|
:columns="[
|
|
{
|
|
name: 'name',
|
|
field: 'name',
|
|
label: 'name',
|
|
style: 'font-size: 14px',
|
|
},
|
|
{
|
|
name: 'value',
|
|
field: 'value',
|
|
label: 'value',
|
|
style: 'font-size: 14px; font-weight: bold',
|
|
},
|
|
]"
|
|
row-key="name"
|
|
hide-header
|
|
hide-bottom
|
|
class="q-mt-xs q-mb-md"
|
|
/>
|
|
|
|
<div class="row text-body2 text-weight-bold">
|
|
<div class="col-12 text-center row justify-center">
|
|
<span
|
|
>สรุปผลการประเมินผลสัมฤทธิ์ของงาน (มิติที่ 1 + มิติที่ 2)
|
|
(คะแนนเต็ม
|
|
{{ store.excusiveIndicatorScore }}
|
|
คะแนน)</span
|
|
>
|
|
<div class="text-primary q-pl-md">
|
|
{{
|
|
(
|
|
store.excusiveIndicator1ScoreVal +
|
|
store.excusiveIndicator2ScoreVal
|
|
).toFixed(2)
|
|
}}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div v-else>
|
|
<Work
|
|
v-model:data="rows_01"
|
|
:title="`1. งานตามแผนปฏิบัติราชการประจำปี`"
|
|
:page="1"
|
|
:fetchList="fetchListPlanned"
|
|
:total="totalResults1"
|
|
/>
|
|
<Work
|
|
v-model:data="rows_02"
|
|
:title="`2. งานตามหน้าที่ความรับผิดชอบหลัก`"
|
|
:page="2"
|
|
:fetchList="fetchListRole"
|
|
:total="totalResults2"
|
|
/>
|
|
<Work
|
|
v-model:data="rows_03"
|
|
:title="`3. งานอื่น ๆ ที่ได้รับมอบหมาย`"
|
|
:page="3"
|
|
:fetchList="fetchAssigned"
|
|
:total="totalResults3"
|
|
/>
|
|
|
|
<div v-if="isShowScore">
|
|
<q-table
|
|
flat
|
|
dense
|
|
bordered
|
|
:rows="[
|
|
{
|
|
name: 'รวมผลการประเมิน (ร้อยละ)',
|
|
value: store.indicatorPercentVal.toFixed(2),
|
|
},
|
|
]"
|
|
:columns="[
|
|
{
|
|
name: 'name',
|
|
field: 'name',
|
|
label: 'name',
|
|
style: 'font-size: 14px',
|
|
},
|
|
{
|
|
name: 'value',
|
|
field: 'value',
|
|
label: 'value',
|
|
style: 'font-size: 14px; font-weight: bold',
|
|
},
|
|
]"
|
|
row-key="name"
|
|
hide-header
|
|
hide-bottom
|
|
class="q-mt-xs q-mb-md"
|
|
/>
|
|
|
|
<div class="row text-body2 text-weight-bold">
|
|
<div class="col-12 text-center row justify-center">
|
|
<span
|
|
>สรุปผลการประเมินผลสัมฤทธิ์ของงาน (คะแนนเต็ม
|
|
{{ store.indicatorScore }}
|
|
คะแนน)</span
|
|
>
|
|
<div class="text-primary q-pl-md">
|
|
{{ store.indicatorScoreVal.toFixed(2) }}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<q-separator size="3px" class="q-my-lg" />
|
|
|
|
<!-- องค์ประกอบที่ 2 -->
|
|
<div class="text-weight-bold text-body2 q-mb-sm">
|
|
<span class="txt-under text-blue-6">องค์ประกอบที่ 2</span>
|
|
<span class="q-ml-sm"> พฤติกรรมการปฎิบัติราชการ (สมรรถนะ)</span>
|
|
</div>
|
|
|
|
<Competency v-model:dataListCriteria="dataListCriteria" />
|
|
|
|
<q-table
|
|
v-if="isShowScore"
|
|
flat
|
|
dense
|
|
bordered
|
|
:rows="[
|
|
{
|
|
name: `สรุปผลการประเมินสมรรถนะ (คะแนนเต็ม ${
|
|
store.dataEvaluation.posTypeName != 'อำนวยการ' &&
|
|
store.dataEvaluation.posTypeName != 'บริหาร'
|
|
? store.competencyScore
|
|
: store.excusiveCompetencyScore
|
|
} คะแนน)`,
|
|
value: store.competencyScoreVal.toFixed(2),
|
|
},
|
|
]"
|
|
:columns="[
|
|
{
|
|
name: 'name',
|
|
field: 'name',
|
|
label: 'name',
|
|
style: 'font-size: 14px',
|
|
},
|
|
{
|
|
name: 'value',
|
|
field: 'value',
|
|
label: 'value',
|
|
style: 'font-size: 14px; font-weight: bold',
|
|
},
|
|
]"
|
|
row-key="name"
|
|
hide-header
|
|
hide-bottom
|
|
class="q-mt-xs q-mb-md"
|
|
/>
|
|
|
|
<div
|
|
v-if="
|
|
store.dataEvaluation.posTypeName != 'อำนวยการ' &&
|
|
store.dataEvaluation.posTypeName != 'บริหาร'
|
|
"
|
|
>
|
|
<Develop />
|
|
|
|
<div v-if="isShowScore">
|
|
<q-table
|
|
flat
|
|
dense
|
|
bordered
|
|
:rows="[
|
|
{
|
|
name: `ผลการประเมินการพัฒนาตนเอง (คะแนนเต็ม ${store.devScore} คะแนน)`,
|
|
value: store.devScoreVal.toFixed(2),
|
|
},
|
|
]"
|
|
:columns="[
|
|
{
|
|
name: 'name',
|
|
field: 'name',
|
|
label: 'name',
|
|
style: 'font-size: 14px',
|
|
},
|
|
{
|
|
name: 'value',
|
|
field: 'value',
|
|
label: 'value',
|
|
style: 'font-size: 14px; font-weight: bold',
|
|
},
|
|
]"
|
|
row-key="name"
|
|
hide-header
|
|
hide-bottom
|
|
class="q-mt-xs q-mb-md"
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
<div v-if="isShowScore">
|
|
<div
|
|
v-if="
|
|
store.dataEvaluation.posTypeName != 'อำนวยการ' &&
|
|
store.dataEvaluation.posTypeName != 'บริหาร'
|
|
"
|
|
class="row text-body2 text-weight-bold"
|
|
>
|
|
<div class="col-12 text-center row justify-center">
|
|
<span
|
|
>สรุปผลการประเมินพฤติกรรมการปฏิบัติราชการ (สมรรถนะ+การพัฒนาตนเอง)
|
|
(คะแนนเต็ม {{ store.competencyDevScore }} คะแนน)</span
|
|
>
|
|
<div class="text-primary q-pl-md">
|
|
{{ (store.competencyScoreVal + store.devScoreVal).toFixed(2) }}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div v-else class="row text-body2 text-weight-bold">
|
|
<div class="col-12 text-center row justify-center">
|
|
<span
|
|
>สรุปผลการประเมินพฤติกรรมการปฏิบัติราชการ (สมรรถนะ) (คะแนนเต็ม
|
|
{{ store.competencyScore }} คะแนน)</span
|
|
>
|
|
<div class="text-primary q-pl-md">
|
|
{{ store.competencyScoreVal.toFixed(2) }}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</q-scroll-area>
|
|
|
|
<DialogListCriteria
|
|
v-model:modal="modalCriteria"
|
|
v-model:dataListCriteria="dataListCriteria"
|
|
/>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.txt-under {
|
|
text-decoration: underline;
|
|
}
|
|
|
|
.custom-table2 {
|
|
max-height: 64vh;
|
|
|
|
.q-table tr:nth-child(odd) td {
|
|
background: white;
|
|
}
|
|
|
|
.q-table tr:nth-child(even) td {
|
|
background: #f8f8f8;
|
|
}
|
|
|
|
.q-table thead tr {
|
|
background: #ecebeb;
|
|
}
|
|
|
|
.q-table thead tr th {
|
|
position: sticky;
|
|
}
|
|
|
|
.q-table td:nth-of-type(2) {
|
|
z-index: 3 !important;
|
|
}
|
|
|
|
.q-table th:nth-of-type(2),
|
|
.q-table td:nth-of-type(2) {
|
|
position: sticky;
|
|
left: 0;
|
|
z-index: 1;
|
|
}
|
|
|
|
/* this will be the loading indicator */
|
|
.q-table thead tr:last-child th {
|
|
/* height of all previous header rows */
|
|
top: 48px;
|
|
}
|
|
|
|
.q-table thead tr:first-child th {
|
|
top: 0;
|
|
}
|
|
|
|
.q-btn-group--outline > .q-btn-item:not(:last-child):before {
|
|
border-right: 1px solid #c4c4c4;
|
|
}
|
|
.q-btn-group--outline > .q-btn-item.active {
|
|
color: #2196f3 !important;
|
|
background-color: #fff;
|
|
}
|
|
.q-btn-group--outline > .q-btn-item.active:not(:last-child):before {
|
|
border: 1px solid #2196f3;
|
|
}
|
|
}
|
|
</style>
|