Merge branch 'NiceDev' into develop

# Conflicts:
#	src/api/KPI/api.kpis.ts
#	src/modules/08_KPI/components/Tab/01_Assessment.vue
This commit is contained in:
DESKTOP-1R2VSQH\Lenovo ThinkPad E490 2024-04-24 15:02:19 +07:00
commit 673ac3dd04
6 changed files with 245 additions and 77 deletions

View file

@ -20,12 +20,13 @@ export default {
file: KpiFile, file: KpiFile,
kpiAchievement: (type: string) => `${kpiAchievement}/${type}`, kpiAchievement: (type: string) => `${kpiAchievement}/${type}`,
kpiAchievementPoint: (type: string) => `${kpiAchievement}/${type}/point`,
/** ผลสัมฤทธิ์ของงาน*/ /** ผลสัมฤทธิ์ของงาน*/
fileByFile: (name: string, group: string, id: string, fileName: string) => fileByFile: (name: string, group: string, id: string, fileName: string) =>
`${url}/file/${name}/${group}/${id}/${fileName}`, `${url}/file/${name}/${group}/${id}/${fileName}`,
kpiUserCapacity:`${KpiUser}/capacity`, kpiUserCapacity: `${KpiUser}/capacity`,
KpiEvaluation KpiEvaluation,
}; };

View file

@ -1,5 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref, onMounted } from "vue"; import { ref, onMounted, computed } from "vue";
import { useQuasar } from "quasar"; import { useQuasar } from "quasar";
import { useRoute } from "vue-router"; import { useRoute } from "vue-router";
@ -26,8 +26,10 @@ const rows_01 = ref<any[]>();
const rows_02 = ref<any[]>(); const rows_02 = ref<any[]>();
const rows_03 = ref<any[]>(); const rows_03 = ref<any[]>();
const total = ref<number>(0); const totalResults1 = ref<number>(0);
const resultWork = ref<number>(0); const totalResults2 = ref<number>(0);
const totalResults3 = ref<number>(0);
// const resultWork = ref<number>(0);
const resultEvaluation = ref<number>(0); const resultEvaluation = ref<number>(0);
function fetchListPlanned() { function fetchListPlanned() {
@ -36,7 +38,16 @@ function fetchListPlanned() {
.get(config.API.kpiAchievement("planned") + `?id=${evaluationId.value}`) .get(config.API.kpiAchievement("planned") + `?id=${evaluationId.value}`)
.then((res) => { .then((res) => {
const data = res.data.result; const data = res.data.result;
rows_01.value = data; const newRow = data.map((e: any) => ({
...e,
evaluationResults: (e.point / 5) * e.weight,
}));
rows_01.value = newRow;
const result = newRow.reduce(
(sum: number, e: any) => sum + e.evaluationResults,
0
);
totalResults1.value = (result * 80) / 100;
}) })
.catch((err) => { .catch((err) => {
messageError($q, err); messageError($q, err);
@ -52,7 +63,16 @@ function fetchListRole() {
.get(config.API.kpiAchievement("role") + `?id=${evaluationId.value}`) .get(config.API.kpiAchievement("role") + `?id=${evaluationId.value}`)
.then((res) => { .then((res) => {
const data = res.data.result; const data = res.data.result;
rows_02.value = data; const newRow = data.map((e: any) => ({
...e,
evaluationResults: (e.point / 5) * e.weight,
}));
rows_02.value = newRow;
const result = newRow.reduce(
(sum: number, e: any) => sum + e.evaluationResults,
0
);
totalResults2.value = (result * 80) / 100;
}) })
.catch((err) => { .catch((err) => {
messageError($q, err); messageError($q, err);
@ -63,22 +83,38 @@ function fetchListRole() {
} }
function fetchAssigned() { function fetchAssigned() {
const data = [ showLoader();
{ http
includingName: "name", .get(config.API.kpiAchievement("special") + `?id=${evaluationId.value}`)
target: "เป่า", .then((res) => {
point: "12", const data = res.data.result;
weight: "12", const newRow = data.map((e: any) => ({
achievement: "12", ...e,
evaluationResults: "12", evaluationResults: (e.point / 5) * e.weight,
}, }));
];
rows_03.value = data; rows_03.value = newRow;
const result = newRow.reduce(
(sum: number, e: any) => sum + e.evaluationResults,
0
);
totalResults3.value = (result * 80) / 100;
})
.catch((err) => {
messageError($q, err);
})
.finally(() => {
hideLoader();
});
} }
function onInfo(){ function onInfo(){
modalCriteria.value = true modalCriteria.value = true
} }
const resultWork = computed(() => {
const total = totalResults1.value + totalResults2.value + totalResults3.value;
return (total * 80) / 100;
});
onMounted(() => { onMounted(() => {
fetchListPlanned(); fetchListPlanned();
@ -104,18 +140,21 @@ onMounted(() => {
:title="`1. งานตามแผนปฏิบัติราชการประจำปี`" :title="`1. งานตามแผนปฏิบัติราชการประจำปี`"
:page="1" :page="1"
:fetchList="fetchListPlanned" :fetchList="fetchListPlanned"
:total="totalResults1"
/> />
<Work <Work
v-model:data="rows_02" v-model:data="rows_02"
:title="`2. งานตามหน้าที่ความรับผิดชอบหลัก`" :title="`2. งานตามหน้าที่ความรับผิดชอบหลัก`"
:page="2" :page="2"
:fetchList="fetchListRole" :fetchList="fetchListRole"
:total="totalResults2"
/> />
<Work <Work
v-model:data="rows_03" v-model:data="rows_03"
:title="`3. งานที่ได้รับมอบหมายพิเศษ`" :title="`3. งานที่ได้รับมอบหมายพิเศษ`"
:page="3" :page="3"
:fetchList="fetchAssigned" :fetchList="fetchAssigned"
:total="totalResults3"
/> />
<div class="row text-body2 text-weight-bold"> <div class="row text-body2 text-weight-bold">
<!-- <div class="col-6 text-center row justify-center"> <!-- <div class="col-6 text-center row justify-center">
@ -124,7 +163,7 @@ onMounted(() => {
</div> --> </div> -->
<div class="col-12 text-center row justify-center"> <div class="col-12 text-center row justify-center">
<span>สรปผลการประเมนผลสมฤทธของงาน (คะแนนเต 70 คะแนน)</span> <span>สรปผลการประเมนผลสมฤทธของงาน (คะแนนเต 80 คะแนน)</span>
<div class="text-primary q-pl-md">{{ resultWork }}</div> <div class="text-primary q-pl-md">{{ resultWork }}</div>
</div> </div>
</div> </div>

View file

@ -1,5 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref, reactive } from "vue"; import { ref, reactive, watch } from "vue";
import { useQuasar } from "quasar"; import { useQuasar } from "quasar";
import config from "@/app.config"; import config from "@/app.config";
import http from "@/plugins/http"; import http from "@/plugins/http";
@ -8,8 +8,12 @@ import type { FormDataAssigned } from "@/modules/08_KPI/interface/request/index"
import DialogHeader from "@/components/DialogHeader.vue"; import DialogHeader from "@/components/DialogHeader.vue";
import { useKpiDataStore } from "@/modules/08_KPI/store";
import { useCounterMixin } from "@/stores/mixin"; import { useCounterMixin } from "@/stores/mixin";
const $q = useQuasar(); const $q = useQuasar();
const store = useKpiDataStore();
const { const {
showLoader, showLoader,
hideLoader, hideLoader,
@ -27,54 +31,98 @@ const kpiUserPlannedId = defineModel<string>("kpiUserPlannedId", {
const formData = reactive<FormDataAssigned>({ const formData = reactive<FormDataAssigned>({
including: "", // including: "", //
indicator: "", // includingName: "", //
target: "", // target: "", //
unit: "", // unit: null, //
weigth: "", // () weight: null, // ()
definition: "", // meaning: "", //
formula: "", // formula: "", //
achievement1: "", // 1 achievement1: "", // 1
achievement2: "", // 2 achievement2: "", // 2
achievement3: "", // 3 achievement3: "", // 3
achievement4: "", // 4 achievement4: "", // 4
achievement5: "", // 5 achievement5: "", // 5
kpiUserEvaluationId: "",
}); });
function fetchspecialByid(id: string) {
showLoader();
http
.get(config.API.kpiAchievement("special") + `/${id}`)
.then((res) => {
const data = res.data.result;
console.log(data);
formData.including = data.including;
formData.includingName = data.includingName;
formData.target = data.target;
formData.unit = data.unit;
formData.achievement1 = data.achievement1;
formData.achievement2 = data.achievement2;
formData.achievement3 = data.achievement3;
formData.achievement4 = data.achievement4;
formData.achievement5 = data.achievement5;
formData.weight = data.weight;
formData.formula = data.formula;
formData.meaning = data.meaning;
})
.catch((err) => {
messageError($q, err);
})
.finally(() => {
hideLoader();
});
}
/** ปิด dialog */ /** ปิด dialog */
function closeDialog() { function closeDialog() {
modal.value = false; modal.value = false;
formData.including = ""; formData.including = "";
formData.indicator = ""; formData.includingName = "";
formData.target = ""; formData.target = "";
formData.unit = ""; formData.unit = null;
formData.achievement1 = ""; formData.achievement1 = "";
formData.achievement2 = ""; formData.achievement2 = "";
formData.achievement3 = ""; formData.achievement3 = "";
formData.achievement4 = ""; formData.achievement4 = "";
formData.achievement5 = ""; formData.achievement5 = "";
formData.weigth = ""; formData.weight = null;
formData.definition = ""; formData.meaning = "";
formData.formula = "";
} }
function onSubmit() { function onSubmit() {
dialogConfirm($q, async () => { dialogConfirm($q, async () => {
console.log(formData); showLoader();
formData.weight = Number(formData.weight);
formData.unit = Number(formData.unit);
formData.kpiUserEvaluationId = store.dataEvaluation.id;
// try { try {
// const url = isStatusEdit.value const url = isStatusEdit.value
// ? config.API.kpiAchievement("planned") + `/${kpiUserPlannedId.value}` ? config.API.kpiAchievement("special") + `/${kpiUserPlannedId.value}`
// : config.API.kpiAchievement("planned"); : config.API.kpiAchievement("special");
// const method = isStatusEdit.value ? "put" : "post"; const method = isStatusEdit.value ? "put" : "post";
// await http[method](url, formData); await http[method](url, formData);
// success($q, ""); success($q, "บันทึกข้อมูลสำเร็จ");
// } catch (err) { } catch (err) {
// messageError($q, err); messageError($q, err);
// } finally { } finally {
// hideLoader(); hideLoader();
closeDialog(); closeDialog();
// } }
}); });
} }
watch(
() => modal.value,
() => {
if (modal.value) {
isStatusEdit.value && fetchspecialByid(kpiUserPlannedId.value);
}
}
);
</script> </script>
<template> <template>
<q-dialog v-model="modal" persistent> <q-dialog v-model="modal" persistent>
@ -98,17 +146,19 @@ function onSubmit() {
class="inputgreen" class="inputgreen"
:rules="[(val) => !!val || `${'กรุณากรอกรหัสตัวชี้วัด'}`]" :rules="[(val) => !!val || `${'กรุณากรอกรหัสตัวชี้วัด'}`]"
hide-bottom-space hide-bottom-space
lazy-rules
/> />
</div> </div>
<div class="col-10"> <div class="col-10">
<q-input <q-input
v-model="formData.indicator" v-model="formData.includingName"
label="ชื่อตัวชี้วัด" label="ชื่อตัวชี้วัด"
outlined outlined
dense dense
:rules="[(val:string) => !!val || `${'กรุณากรอกชื่อตัวชี้วัด'}`,]" :rules="[(val:string) => !!val || `${'กรุณากรอกชื่อตัวชี้วัด'}`,]"
hide-bottom-space hide-bottom-space
class="inputgreen" class="inputgreen"
lazy-rules
/> />
</div> </div>
<div class="col-4"> <div class="col-4">
@ -120,6 +170,7 @@ function onSubmit() {
:rules="[(val:string) => !!val || `${'กรุณากรอกค่าเป้าหมาย'}`,]" :rules="[(val:string) => !!val || `${'กรุณากรอกค่าเป้าหมาย'}`,]"
hide-bottom-space hide-bottom-space
class="inputgreen" class="inputgreen"
lazy-rules
/> />
</div> </div>
<div class="col-4"> <div class="col-4">
@ -133,11 +184,12 @@ function onSubmit() {
class="inputgreen" class="inputgreen"
mask="#" mask="#"
reverse-fill-mask reverse-fill-mask
lazy-rules
/> />
</div> </div>
<div class="col-4"> <div class="col-4">
<q-input <q-input
v-model="formData.weigth" v-model="formData.weight"
label="น้ำหนัก (ร้อยละ)" label="น้ำหนัก (ร้อยละ)"
outlined outlined
dense dense
@ -146,6 +198,7 @@ function onSubmit() {
class="inputgreen" class="inputgreen"
mask="#" mask="#"
reverse-fill-mask reverse-fill-mask
lazy-rules
/> />
</div> </div>
<div class="col-12"> <div class="col-12">
@ -174,6 +227,7 @@ function onSubmit() {
(val) => !!val || `${'กรุณากรอกผลสำเร็จของงาน'}`, (val) => !!val || `${'กรุณากรอกผลสำเร็จของงาน'}`,
]" ]"
hide-bottom-space hide-bottom-space
lazy-rules
/> />
</div> </div>
</div> </div>
@ -193,6 +247,7 @@ function onSubmit() {
(val) => !!val || `${'กรุณากรอกผลสำเร็จของงาน'}`, (val) => !!val || `${'กรุณากรอกผลสำเร็จของงาน'}`,
]" ]"
hide-bottom-space hide-bottom-space
lazy-rules
/> />
</div> </div>
</div> </div>
@ -212,6 +267,7 @@ function onSubmit() {
(val) => !!val || `${'กรุณากรอกผลสำเร็จของงาน'}`, (val) => !!val || `${'กรุณากรอกผลสำเร็จของงาน'}`,
]" ]"
hide-bottom-space hide-bottom-space
lazy-rules
/> />
</div> </div>
</div> </div>
@ -231,6 +287,7 @@ function onSubmit() {
(val) => !!val || `${'กรุณากรอกผลสำเร็จของงาน'}`, (val) => !!val || `${'กรุณากรอกผลสำเร็จของงาน'}`,
]" ]"
hide-bottom-space hide-bottom-space
lazy-rules
/> />
</div> </div>
</div> </div>
@ -250,6 +307,7 @@ function onSubmit() {
(val) => !!val || `${'กรุณากรอกผลสำเร็จของงาน'}`, (val) => !!val || `${'กรุณากรอกผลสำเร็จของงาน'}`,
]" ]"
hide-bottom-space hide-bottom-space
lazy-rules
/> />
</div> </div>
</div> </div>
@ -257,7 +315,7 @@ function onSubmit() {
</div> </div>
<div class="col-12"> <div class="col-12">
<q-input <q-input
v-model="formData.definition" v-model="formData.meaning"
label="นิยามหรือความหมายของตัวชี้วัด" label="นิยามหรือความหมายของตัวชี้วัด"
outlined outlined
dense dense
@ -265,6 +323,7 @@ function onSubmit() {
:rules="[(val:string) => !!val || `${'กรุณากรอกนิยามหรือความหมายของตัวชี้วัด'}`,]" :rules="[(val:string) => !!val || `${'กรุณากรอกนิยามหรือความหมายของตัวชี้วัด'}`,]"
hide-bottom-space hide-bottom-space
class="inputgreen" class="inputgreen"
lazy-rules
/> />
</div> </div>
<div class="col-12"> <div class="col-12">
@ -278,6 +337,7 @@ function onSubmit() {
class="inputgreen" class="inputgreen"
:rules="[(val) => !!val || `${'กรุณากรอกสูตรคำนวณ'}`]" :rules="[(val) => !!val || `${'กรุณากรอกสูตรคำนวณ'}`]"
hide-bottom-space hide-bottom-space
lazy-rules
/> />
</div> </div>
</div> </div>

View file

@ -1,6 +1,8 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref, watch } from "vue"; import { ref, watch } from "vue";
import { useQuasar } from "quasar"; import { useQuasar } from "quasar";
import config from "@/app.config";
import http from "@/plugins/http";
import DialogHeader from "@/components/DialogHeader.vue"; import DialogHeader from "@/components/DialogHeader.vue";
@ -127,8 +129,30 @@ function updateAchievement(index: number, data: any) {
} }
function onSubmit() { function onSubmit() {
dialogConfirm($q, () => { dialogConfirm($q, async () => {
closeDialog(); try {
showLoader();
const formData = rows.value.map((e: any) => ({
id: e.id,
point: e.point,
}));
const url =
numpage.value === 1
? config.API.kpiAchievementPoint("planned")
: numpage.value === 2
? config.API.kpiAchievementPoint("role")
: numpage.value === 3
? config.API.kpiAchievementPoint("special")
: "";
await http.post(url, formData);
success($q, "บันทึกข้อมูลสำเร็จ");
} catch (err) {
messageError($q, err);
} finally {
hideLoader();
closeDialog();
}
}); });
console.log(rows.value); console.log(rows.value);
} }
@ -198,7 +222,13 @@ function onSubmit() {
{{ props.row.achievement }} {{ props.row.achievement }}
</div> </div>
<div v-else-if="col.name === 'evaluationResults'"> <div v-else-if="col.name === 'evaluationResults'">
{{ (props.row.point / 5) * props.row.weight }} {{
parseFloat(
Number(
(props.row.point / 5) * props.row.weight
).toFixed(2)
)
}}
</div> </div>
<div v-else> <div v-else>
{{ col.value ? col.value : "-" }} {{ col.value ? col.value : "-" }}

View file

@ -12,8 +12,10 @@ import Dialog03 from "@/modules/08_KPI/components/Tab/Dialog/03_FormIndicatorSpe
import DialogEvaluate from "@/modules/08_KPI/components/Tab/DialogEvaluate/01_Indicator.vue"; import DialogEvaluate from "@/modules/08_KPI/components/Tab/DialogEvaluate/01_Indicator.vue";
import { useCounterMixin } from "@/stores/mixin"; import { useCounterMixin } from "@/stores/mixin";
import { useKpiDataStore } from "@/modules/08_KPI/store";
const $q = useQuasar(); const $q = useQuasar();
const store = useKpiDataStore();
const route = useRoute(); const route = useRoute();
const { const {
date2Thai, date2Thai,
@ -27,6 +29,7 @@ const {
const title = defineModel<string>("title", { required: true }); const title = defineModel<string>("title", { required: true });
const rows = defineModel<any>("data", { required: true }); const rows = defineModel<any>("data", { required: true });
const numpage = defineModel<number>("page", { required: true }); const numpage = defineModel<number>("page", { required: true });
const evaluationTotal = defineModel<number>("total", { required: true });
const props = defineProps({ const props = defineProps({
fetchList: { type: Function, required: true }, fetchList: { type: Function, required: true },
@ -115,18 +118,6 @@ const modal = ref<boolean>(false);
const modalAssigned = ref<boolean>(false); const modalAssigned = ref<boolean>(false);
const isStatusEdit = ref<boolean>(false); const isStatusEdit = ref<boolean>(false);
const modalEvaluate = ref<boolean>(false); const modalEvaluate = ref<boolean>(false);
const evaluationTotal = ref<number>(0);
// const evaluationTotal = computed(() => {
// if (rows.value) {
// const test = rows.value.reduce(
// (sumAge: number, e: any) => sumAge + e.point
// );
// console.log(test);
// return test;
// }
// });
function onAdd(edit: boolean = false, id: string = "") { function onAdd(edit: boolean = false, id: string = "") {
isStatusEdit.value = edit; isStatusEdit.value = edit;
@ -152,7 +143,7 @@ function onDelete(id: string) {
: numpage.value === 2 : numpage.value === 2
? config.API.kpiAchievement("role") + `/${id}` ? config.API.kpiAchievement("role") + `/${id}`
: numpage.value === 3 : numpage.value === 3
? config.API.kpiAchievement("role") + `/${id}` ? config.API.kpiAchievement("special") + `/${id}`
: ""; : "";
await http.delete(url); await http.delete(url);
props.fetchList?.(); props.fetchList?.();
@ -174,6 +165,15 @@ watch(
} }
); );
watch(
() => modalAssigned.value,
() => {
if (!modalAssigned.value) {
props.fetchList?.();
}
}
);
watch( watch(
() => modalEvaluate.value, () => modalEvaluate.value,
() => { () => {
@ -245,8 +245,39 @@ watch(
<template v-slot:body="props"> <template v-slot:body="props">
<q-tr :props="props" class="cursor-pointer"> <q-tr :props="props" class="cursor-pointer">
<q-td v-for="col in props.cols" :key="col.id"> <q-td v-for="col in props.cols" :key="col.id">
<div v-if="col.name == 'createDate'"> <div v-if="col.name === 'point'">
{{ col.value ? date2Thai(col.value) : "-" }} <q-rating
v-model="props.row.point"
max="5"
size="sm"
color="grey"
:color-selected="store.ratingColors"
label="ระดับการประเมินพฤติกรรม"
disable
>
<template v-slot:tip-1>
<q-tooltip>{{ props.row.achievement1 }}</q-tooltip>
</template>
<template v-slot:tip-2>
<q-tooltip>{{ props.row.achievement2 }}</q-tooltip>
</template>
<template v-slot:tip-3>
<q-tooltip>{{ props.row.achievement3 }}</q-tooltip>
</template>
<template v-slot:tip-4>
<q-tooltip>{{ props.row.achievement4 }}</q-tooltip>
</template>
<template v-slot:tip-5>
<q-tooltip>{{ props.row.achievement5 }}</q-tooltip>
</template>
</q-rating>
</div>
<div v-else-if="col.name === 'evaluationResults'">
{{
parseFloat(
Number((props.row.point / 5) * props.row.weight).toFixed(2)
)
}}
</div> </div>
<div v-else> <div v-else>
{{ col.value ? col.value : "-" }} {{ col.value ? col.value : "-" }}
@ -279,13 +310,19 @@ watch(
</td> </td>
</q-tr> </q-tr>
</template> </template>
<template v-slot:bottom>
<span class="text-body2 text-weight-bold"
>รวมผลการประเม (อยละ)</span
>
<div class="text-primary q-pl-md">{{ evaluationTotal }}</div>
</template>
</q-table> </q-table>
<div class="row text-body2 text-weight-bold q-pa-md"> <!-- <div class="row text-body2 text-weight-bold q-pa-md">
<div class="col-12 text-center row justify-center"> <div class="col-12 text-center row justify-center">
<span>รวมผลการประเม (อยละ)</span> <span>รวมผลการประเม (อยละ)</span>
<div class="text-primary q-pl-md">{{ evaluationTotal }}</div> <div class="text-primary q-pl-md">{{ evaluationTotal }}</div>
</div> </div>
</div> </div> -->
</q-card-section> </q-card-section>
</q-card> </q-card>

View file

@ -13,26 +13,27 @@ interface FormProfile {
interface FormDataAssigned { interface FormDataAssigned {
including: string; including: string;
indicator: string; includingName: string;
target: string; target: string;
unit: string; unit: number | null;
weigth: string; weight: number | null;
achievement1: string; achievement1: string;
achievement2: string; achievement2: string;
achievement3: string; achievement3: string;
achievement4: string; achievement4: string;
achievement5: string; achievement5: string;
definition: string; meaning: string;
formula: string; formula: string;
kpiUserEvaluationId: string;
} }
interface FormCapacityList{ interface FormCapacityList {
id:string|null id: string | null;
name:string name: string;
level:string level: string;
point:number point: number;
weight:number weight: number;
summary:number summary: number;
} }
export type { FormProfile, FormDataAssigned,FormCapacityList }; export type { FormProfile, FormDataAssigned, FormCapacityList };