KPI + UI สรุปผล

This commit is contained in:
STW_TTTY\stwtt 2024-06-20 16:35:41 +07:00
parent defcfd56da
commit abd7cd8beb
13 changed files with 1011 additions and 75 deletions

View file

@ -407,16 +407,6 @@ onMounted(() => {
<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>
<q-btn
flat
icon="mdi-eye"
color="info"
round
class="q-ml-xs"
@click="onInfo"
>
<q-tooltip>เกณฑการประเม</q-tooltip>
</q-btn>
</div>
<Competency v-model:dataListCriteria="dataListCriteria" />

View file

@ -1,3 +1,390 @@
<script setup lang="ts">
import { computed, ref } from "vue";
const separator = ref<any>("cell");
const title = ref<string>("");
const developmentMethod = ref<string>("");
const developmentPeriod = ref<string>("");
const evaluatorComment = ref<string>("");
const superiorComment = ref<string>("");
const additionalSuperiorComment = ref<string>("");
const superiorCommentCheck = ref<string>("");
const additionalSuperiorCheck = ref<string>("");
const weight1 = ref<number>(10);
const result1 = ref<number>(20);
const weight2 = ref<number>(50);
const result2 = ref<number>(60);
const sumWeight = computed(() => {
return weight1.value + weight2.value;
});
const sumResult = computed(() => {
return result1.value + result2.value;
});
const group = computed(() => {
return convert(sumResult.value);
});
const options = ref<any[]>([
{
label: "ดีเด่น (คะแนนร้อยละ ๙๐. ขึ้นไป)",
value: "EXCELLENT",
},
{
label: "ดีมาก (คะแนนร้อยละ ๘๐. - ๘๙.๙๙)",
value: "VERYGOOD",
},
{
label: "ดี (คะแนนร้อยละ ๗๐. - ๗๙.๙๙)",
value: "GOOD",
},
{
label: "พอใช้ (คะแนนร้อยละ ๖๐. - ๖๙.๙๙)",
value: "FAIR",
},
{
label: "ต้องปรับปรุง (คะแนนต่ำกว่าร้อยละ ๖๐.)",
value: "IMPROVEMENT",
},
]);
function convert(score: any): string {
if (score >= 90) {
return "EXCELLENT";
} else if (score >= 80) {
return "VERYGOOD";
} else if (score >= 70) {
return "GOOD";
} else if (score >= 60) {
return "FAIR";
} else {
return "IMPROVEMENT";
}
}
function onSubmit(){
}
function onSubmitCommander(){
}
function onSubmitCommanderHigh(){
}
</script>
<template>
<div class="q-pa-md">สรปผลการประเม</div>
<div class="q-pa-sm ">
<!-- 1-4 สรปผลการประเม -->
<q-card bordered>
<q-form greedy @submit.prevent @validation-success="onSubmit">
<q-card-section>
<div class="row q-col-gutter-sm">
<div class="col-12">
<div class="text-weight-bold text-body2">
<span class="txt-under text-blue-6">สรปผลการประเม</span>
</div>
</div>
<div class="col-12">
<q-markup-table
:separator="separator"
flat
bordered
class="custom-table2"
>
<thead>
<tr>
<th class="text-left txt-customHead">
องคประกอบการประเม
</th>
<th class="text-left txt-customHead">ำหนกคะแนน</th>
<th class="text-left txt-customHead">ผลการประเม</th>
</tr>
</thead>
<tbody>
<tr>
<td class="text-left">องคประกอบท ผลสมฤทธของงาน</td>
<td class="text-left">{{ weight1 }}</td>
<td class="text-left">{{ result1 }}</td>
</tr>
<tr>
<td class="text-left">
องคประกอบท พฤตกรรมการปฎราชการ (สมรรถนะ)
</td>
<td class="text-left">{{ weight2 }}</td>
<td class="text-left">{{ result2 }}</td>
</tr>
<tr>
<td class="text-right text-bold" style="font-size: 16px">
รวม
</td>
<td class="text-left">{{ sumWeight }}</td>
<td class="text-left">{{ sumResult }}</td>
</tr>
</tbody>
</q-markup-table>
</div>
<div class="col-12">
<div class="text-weight-bold text-body2">
<span class="txt-under text-blue-6">ระดบผลการประเม</span>
</div>
</div>
<div class="col-12 no-pointer">
<div class="column">
<q-radio
v-model="group"
checked-icon="task_alt"
unchecked-icon="panorama_fish_eye"
val="EXCELLENT"
label="ดีเด่น (คะแนนร้อยละ ๙๐. ขึ้นไป)"
/>
<q-radio
v-model="group"
checked-icon="task_alt"
unchecked-icon="panorama_fish_eye"
val="VERYGOOD"
label="ดีมาก (คะแนนร้อยละ ๘๐. - ๘๙.๙๙)"
/>
<q-radio
v-model="group"
checked-icon="task_alt"
unchecked-icon="panorama_fish_eye"
val="GOOD"
label="ดี (คะแนนร้อยละ ๗๐. - ๗๙.๙๙)"
/>
<q-radio
v-model="group"
checked-icon="task_alt"
unchecked-icon="panorama_fish_eye"
val="FAIR"
label="พอใช้ (คะแนนร้อยละ ๖๐. - ๖๙.๙๙)"
/>
<q-radio
v-model="group"
checked-icon="task_alt"
unchecked-icon="panorama_fish_eye"
val="IMPROVEMENT"
label="ต้องปรับปรุง (คะแนนต่ำกว่าร้อยละ ๖๐.)"
/>
</div>
</div>
<div class="col-12">
<div class="text-weight-bold text-body2">
<span class="txt-under text-blue-6">ความร/กษะ/สมรรถนะ</span>
</div>
</div>
<div class="col-12">
<q-input
v-model="title"
outlined
type="textarea"
label="ชื่อเรื่อง/เนื้อหา/หัวข้อการพัฒนา"
/>
</div>
<div class="col-12">
<q-input
v-model="developmentMethod"
outlined
type="textarea"
label="วิธีการพัฒนา"
/>
</div>
<div class="col-12">
<q-input
v-model="developmentPeriod"
outlined
type="textarea"
label="ช่วงเวลาการพัฒนา"
/>
</div>
<div class="col-12">
<div class="text-weight-bold text-body2">
<span class="txt-under text-blue-6">ความเหนของผประเม</span>
</div>
</div>
<div class="col-12">
<q-input
v-model="evaluatorComment"
outlined
type="textarea"
label="ความเห็นของผู้ประเมิน"
/>
</div>
</div>
</q-card-section>
<q-separator />
<q-card-actions align="right">
<q-btn label="บันทึก" color="secondary" type="submit"
><q-tooltip>นทกขอม</q-tooltip></q-btn
>
</q-card-actions>
</q-form>
</q-card>
<q-card bordered class="q-mt-md">
<q-form greedy @submit.prevent @validation-success="onSubmitCommander">
<q-card-section>
<div class="row q-gutter-sm">
<div class="col-12">
<div class="text-weight-bold text-body2">
<span class="txt-under text-blue-6"
>ความเหนของผงคบบญชาเหนอขนไป</span
>
</div>
</div>
<div class="col-12">
<div class="column">
<q-radio
v-model="superiorCommentCheck"
checked-icon="task_alt"
unchecked-icon="panorama_fish_eye"
val="true"
label="เห็นด้วยกับผลการประเมิน"
/>
<q-radio
v-model="superiorCommentCheck"
checked-icon="task_alt"
unchecked-icon="panorama_fish_eye"
val="false"
label="มีความเห็นตามดังนี้"
/>
</div>
</div>
<div class="col-12">
<q-input
v-model="superiorComment"
outlined
type="textarea"
label="ความเห็นของผู้บังคับบัญชาเหนือขึ้นไป"
:readonly="superiorCommentCheck == 'true'"
/>
</div>
</div>
</q-card-section>
<q-separator />
<q-card-actions align="right">
<q-btn label="บันทึก" color="secondary" type="submit"
><q-tooltip>นทกขอม</q-tooltip></q-btn
>
</q-card-actions>
</q-form>
</q-card>
<q-card bordered class="q-mt-md">
<q-form greedy @submit.prevent @validation-success="onSubmitCommanderHigh">
<q-card-section>
<div class="row q-gutter-sm">
<div class="col-12">
<div class="text-weight-bold text-body2">
<span class="txt-under text-blue-6"
>ความเหนของผงคบบญชาเหนอขนไปอกชนหน</span
>
</div>
</div>
<div class="col-12">
<div class="column">
<q-radio
v-model="additionalSuperiorCheck"
checked-icon="task_alt"
unchecked-icon="panorama_fish_eye"
val="true"
label="เห็นด้วยกับผลการประเมิน"
/>
<q-radio
v-model="additionalSuperiorCheck"
checked-icon="task_alt"
unchecked-icon="panorama_fish_eye"
val="false"
label="มีความเห็นตามดังนี้"
/>
</div>
</div>
<div class="col-12">
<q-input
v-model="additionalSuperiorComment"
outlined
type="textarea"
label="ความเห็นของผู้บังคับบัญชาเหนือขึ้นไปอีกชั้นหนึ่ง"
:readonly="additionalSuperiorCheck == 'true'"
/>
</div>
</div>
</q-card-section>
<q-separator />
<q-card-actions align="right">
<q-btn label="บันทึก" color="secondary" type="submit"
><q-tooltip>นทกขอม</q-tooltip></q-btn
>
</q-card-actions>
</q-form>
</q-card>
</div>
</template>
<style scoped>
.no-pointer {
pointer-events: none;
}
.txt-customHead {
font-size: 14px;
font-weight: 500;
}
.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>

View file

@ -56,7 +56,8 @@ const formDataView = reactive<FormCommentByRole>({
id: "",
topic: "",
reason: "",
createdFullName: "",
score: "",
reasonEvaluator: "",
reasonCommander: "",
reasonCommanderHigh: "",

View file

@ -14,11 +14,13 @@ import { useRoute } from "vue-router";
import { useQuasar } from "quasar";
import { useKpiDataStore } from "@/modules/08_KPI/store";
const numLevel = ref<string>("");
const store = useKpiDataStore();
const $q = useQuasar();
const mixin = useCounterMixin();
const { dialogConfirm, showLoader, hideLoader, messageError, success } = mixin;
const rows = defineModel<any>("rows");
const modal = defineModel<boolean>("modal", { required: true });
const type = defineModel<string>("type", { required: true });
const idList = defineModel<string>("idList", { required: true });
@ -45,7 +47,8 @@ const formDataView = reactive<FormCommentByRole>({
id: "",
topic: "",
reason: "",
createdFullName: "",
score: "",
reasonEvaluator: "",
reasonCommander: "",
reasonCommanderHigh: "",
@ -58,6 +61,8 @@ function clickList(index: string, data: any) {
formDataView.id = data.id;
formDataView.topic = data.topic;
formDataView.reason = data.reason;
formDataView.createdFullName = data.createdFullName;
formDataView.score = data.score;
formDataView.reasonEvaluator = data.reasonEvaluator;
formDataView.reasonCommander = data.reasonCommander;
@ -93,6 +98,7 @@ function onSubmitAdd() {
{
reason: formDataAdd.reason,
topic: formDataAdd.topic,
score: type.value == "capacity" ? undefined : numLevel.value,
}
)
.then((res) => {
@ -197,6 +203,7 @@ function onSubmitComment(role: string) {
});
});
}
watch(
() => modal.value,
() => {
@ -210,7 +217,14 @@ watch(
<q-dialog v-model="modal" persistent>
<q-card style="min-width: 70vw">
<q-form greedy @submit.prevent @validation-success="onSubmit">
<DialogHeader tittle="รายงานความก้าวหน้า" :close="close" />
<DialogHeader
:tittle="
type == 'capacity' || type == 'development'
? 'บันทึกเหตุการณ์/พฤติกรรม'
: 'รายงานความก้าวหน้า'
"
:close="close"
/>
<q-separator />
<q-card-section class="q-pa-none">
<q-splitter
@ -233,13 +247,21 @@ watch(
}
"
>
<q-tooltip>เพมความกาวหน</q-tooltip>
<q-tooltip>{{
type == "capacity" || type == "development"
? "เพิ่มเหตุการณ์/พฤติกรรม"
: "เพิ่มความก้าวหน้า"
}}</q-tooltip>
</q-btn>
<q-card bordered flat class="no-shadow bg-white col-12">
<div class="row q-px-md q-py-sm items-center bg-grey-1">
<div class="col-12">
<span>ความกาวหน</span>
<span>{{
type == "capacity" || type == "development"
? "เหตุการณ์/พฤติกรรม"
: "ความก้าวหน้า"
}}</span>
</div>
</div>
@ -295,13 +317,36 @@ watch(
<div v-else>
<div class="row q-pa-md q-col-gutter-sm">
<div class="row col-12 text-weight-medium">
<div class="col-4 text-grey-6">วขอความกาวหน</div>
<div class="col-4 text-grey-6">
{{
type == "capacity" || type == "development"
? "เหตุการณ์/พฤติกรรม"
: "หัวข้อความก้าวหน้า"
}}
</div>
<div class="col-8">{{ formDataView.topic }}</div>
</div>
<div class="row col-12 text-weight-medium">
<div class="col-4 text-grey-6">รายละเอยดความกาวหน</div>
<div class="col-4 text-grey-6">
{{
type == "capacity" || type == "development"
? "รายละเอียด"
: "รายละเอียดความก้าวหน้า"
}}
</div>
<div class="col-8">{{ formDataView.reason }}</div>
</div>
<div
class="row col-12 text-weight-medium"
v-if="type !== 'capacity' && type !== 'development'"
>
<div class="col-4 text-grey-6">คะแนน</div>
<div class="col-8">{{ formDataView.score }}</div>
</div>
<div class="row col-12 text-weight-medium">
<div class="col-4 text-grey-6">สราง</div>
<div class="col-8">{{ formDataView.createdFullName }}</div>
</div>
<div class="col-12">
<q-separator />
</div>
@ -469,7 +514,14 @@ watch(
<q-dialog v-model="modalAdd" persistent>
<q-card style="min-width: 30vw">
<q-form greedy @submit.prevent @validation-success="onSubmitAdd">
<DialogHeader tittle="เพิ่มหัวข้อความก้าวหน้า" :close="closeAdd" />
<DialogHeader
:tittle="
type == 'capacity' || type == 'development'
? 'เพิ่มหัวข้อบันทึกเหตุการณ์/พฤติกรรม'
: 'เพิ่มหัวข้อความก้าวหน้า'
"
:close="closeAdd"
/>
<q-separator />
<q-card-section>
@ -479,11 +531,30 @@ watch(
v-model="formDataAdd.topic"
outlined
class="inputgreen"
label="หัวข้อความก้าวหน้า"
:label="
type == 'capacity' || type == 'development'
? 'เหตุการณ์/พฤติกรรม'
: 'หัวข้อความก้าวหน้า'
"
dense
lazy-rules
hide-bottom-space
:rules="[(val:string) => !!val || `${'กรุณากรอกหัวข้อความก้าวหน้า'}`,]"
:rules="[(val:string) => !!val || `${type == 'capacity'||type == 'development' ? 'กรุณากรอกเหตุการณ์/พฤติกรรม':'กรุณากรอกหัวข้อความก้าวหน้า' }`,]"
/>
</div>
<div
class="col-12"
v-if="type !== 'capacity' && type !== 'development'"
>
<q-input
v-model="numLevel"
outlined
class="inputgreen"
label="คะแนน"
dense
lazy-rules
hide-bottom-space
:rules="[(val:string) => !!val || `${'กรุณากรอกคะแนน'}`,]"
/>
</div>
<div class="col-12">
@ -491,11 +562,14 @@ watch(
v-model="formDataAdd.reason"
outlined
class="inputgreen"
label="รายละเอียดความก้าวหน้า"
:label="
type == 'capacity' || type == 'development'
? 'รายละเอียด'
: 'รายละเอียดความก้าวหน้า'
"
dense
lazy-rules
hide-bottom-space
:rules="[(val:string) => !!val || `${'กรุณากรอกรายละเอียดความก้าวหน้า'}`,]"
type="textarea"
/>
</div>
@ -520,4 +594,20 @@ watch(
background: #ebf9f7 !important;
color: #1bb19ab8 !important;
}
.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: #cde6fb !important;
}
.q-btn-group--outline > .q-btn-item + .q-btn-item.active:before {
border-left: 1px solid #2196f3 !important;
background-color: #cde6fb;
}
.q-btn-group--outline > .q-btn-item.active:not(:last-child):before {
border: 1px solid #2196f3;
background-color: #cde6fb;
}
</style>

View file

@ -0,0 +1,195 @@
<script setup lang="ts">
import { ref, reactive, onMounted, watch } from "vue";
import DialogHeader from "@/components/DialogHeader.vue";
import { useCounterMixin } from "@/stores/mixin";
import type { QTableProps } from "quasar";
const mixin = useCounterMixin();
const { showLoader, hideLoader } = mixin;
const modal = defineModel<boolean>("modal", { required: true });
const rows = defineModel<any>("rows", { required: true });
const dataRows = ref<any[]>([]);
const visibleColumns = ref<String[]>(["level", "description"]);
const columns = ref<QTableProps["columns"]>([
{
name: "level",
align: "center",
label: "ระดับสมรรถนะ",
sortable: true,
field: "level",
headerStyle: "font-size: 14px",
style: "font-size: 14px; width:5px;",
},
{
name: "description",
align: "left",
label: "พฤติกรรมที่คาดหวัง/พฤติกรรมย่อย",
sortable: true,
field: "description",
headerStyle: "font-size: 14px",
style: "font-size: 14px; width:15%;",
},
]);
/** ปิด dialog */
function closeDialog() {
modal.value = false;
rows.value = [];
dataRows.value = [];
}
watch(
() => rows.value,
() => {
if (rows.value) {
const data = rows.value;
dataRows.value = data.sort((a: any, b: any) => a.level - b.level);
}
}
);
</script>
<template>
<q-dialog v-model="modal" persistent>
<q-card class="col-12" style="width: 85%">
<DialogHeader :tittle="`พฤติกรรมที่คาดหวัง/พฤติกรรมย่อย`" :close="closeDialog" />
<q-separator />
<q-card-section class="q-pa-sm scroll" style="max-height: 80vh">
<div class="row">
<div class="col-12">
<d-table
flat
bordered
dense
:paging="true"
row-key="level"
virtual-scroll
:rows="dataRows"
hide-pagination
:columns="columns"
:visible-columns="visibleColumns"
>
<template v-slot:header="props">
<q-tr :props="props">
<q-th
v-for="col in props.cols"
:key="col.name"
:props="props"
class="bg-grey-2"
>
<span class="text-weight-bold">{{ 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 = 'description')">
<span v-html="col.value"></span>
</div>
<div v-else>
{{ col.value }}
</div>
</q-td>
</q-tr>
</template>
<template #item="props">
<div class="q-pa-xs col-xs-12 col-sm-6 col-md-4 col-lg-3">
<q-card bordered flat>
<q-list>
<q-item
v-for="col in props.cols.filter((col:any) => col.name !== 'desc')"
:key="col.name"
>
<q-item-section>
<q-item-label caption>{{ col.label }}</q-item-label>
<q-item-label v-if="(col.name = 'description')">
<span v-html="col.value"></span
></q-item-label>
<q-item-label v-else>{{
col.value ?? "-"
}}</q-item-label>
</q-item-section>
</q-item>
</q-list>
</q-card>
</div>
</template>
<template v-slot:no-data="{ icon, message }">
<div class="q-pa-md text-weight-bold full-width text-center">
<span style="font-size: 16px">ไมพบขอมลสมรรถนะ</span>
</div>
</template>
</d-table>
</div>
</div>
</q-card-section>
</q-card>
</q-dialog>
</template>
<style scoped>
.my-menu-link {
background: #ebf9f7 !important;
color: #1bb19ab8 !important;
}
.no-shadow {
box-shadow: none !important;
}
.lineRight {
border-right: 1px solid #ededed !important;
}
.lineTop {
border-top: 1px solid #ededed !important;
}
.card-box {
border: 1px solid #ededed !important;
border-radius: 8px;
}
.custom-table2 {
.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;
}
}
</style>

View file

@ -0,0 +1,178 @@
<script setup lang="ts">
import { ref, reactive, onMounted, watch } from "vue";
import DialogHeader from "@/components/DialogHeader.vue";
import { useCounterMixin } from "@/stores/mixin";
import type { QTableProps } from "quasar";
const mixin = useCounterMixin();
const { showLoader, hideLoader } = mixin;
const modal = defineModel<boolean>("modal", { required: true });
const rows = defineModel<any>("rows", { required: true });
const dataRows = ref<any[]>([]);
const visibleColumns = ref<String[]>([ "description"]);
const columns = ref<QTableProps["columns"]>([
{
name: "description",
align: "left",
label: "พฤติกรรมที่คาดหวัง/พฤติกรรมย่อย",
sortable: true,
field: "description",
headerStyle: "font-size: 14px",
style: "font-size: 14px; width:15%;",
},
]);
/** ปิด dialog */
function closeDialog() {
modal.value = false;
rows.value = [];
dataRows.value = [];
}
</script>
<template>
<q-dialog v-model="modal" persistent>
<q-card class="col-12" style="width: 85%">
<DialogHeader :tittle="`ข้อมูลพฤติกรรมที่คาดหวัง/พฤติกรรมย่อย`" :close="closeDialog" />
<q-separator />
<q-card-section class="q-pa-sm scroll" style="max-height: 80vh">
<div class="row">
<div class="col-12">
<d-table
flat
bordered
dense
:paging="true"
row-key="level"
virtual-scroll
:rows="rows"
hide-pagination
:columns="columns"
:visible-columns="visibleColumns"
>
<template v-slot:header="props">
<q-tr :props="props">
<q-th
v-for="col in props.cols"
:key="col.name"
:props="props"
class="bg-grey-2"
>
<span class="text-weight-bold">{{ 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 = 'description')">
<span v-html="col.value"></span>
</div>
<div v-else>
{{ col.value }}
</div>
</q-td>
</q-tr>
</template>
<template #item="props">
<div class="q-pa-xs col-xs-12 col-sm-6 col-md-4 col-lg-3">
<q-card bordered flat>
<q-list>
<q-item
v-for="col in props.cols.filter((col:any) => col.name !== 'desc')"
:key="col.name"
>
<q-item-section>
<q-item-label caption>{{ col.label }}</q-item-label>
<q-item-label v-if="(col.name = 'description')">
<span v-html="col.value"></span
></q-item-label>
<q-item-label v-else>{{
col.value ?? "-"
}}</q-item-label>
</q-item-section>
</q-item>
</q-list>
</q-card>
</div>
</template>
<template v-slot:no-data="{ icon, message }">
<div class="q-pa-md text-weight-bold full-width text-center">
<span style="font-size: 16px">ไมพบขอมลสมรรถนะ</span>
</div>
</template>
</d-table>
</div>
</div>
</q-card-section>
</q-card>
</q-dialog>
</template>
<style scoped>
.my-menu-link {
background: #ebf9f7 !important;
color: #1bb19ab8 !important;
}
.no-shadow {
box-shadow: none !important;
}
.lineRight {
border-right: 1px solid #ededed !important;
}
.lineTop {
border-top: 1px solid #ededed !important;
}
.card-box {
border: 1px solid #ededed !important;
border-radius: 8px;
}
.custom-table2 {
.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;
}
}
</style>

View file

@ -35,29 +35,29 @@ function close() {
modal.value = false;
}
// function getData() {
// showLoader();
// http
// .get(config.API.orgPosition+`/${store.dataProfile.profileId}`)
// .then((res) => {
// const data = res.data.result.isProbation;
// work.value = data;
// })
// .catch((e) => {
// messageError($q, e);
// })
// .finally(() => {
// hideLoader();
// });
// }
// watch(
// () => modal.value,
// (n) => {
// if (n == true) {
// getData();
// }
// }
// );
function getData() {
showLoader();
http
.get(config.API.orgPosition+`/${store.dataProfile.profileId}`)
.then((res) => {
const data = res.data.result.isProbation;
work.value = data;
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
hideLoader();
});
}
watch(
() => modal.value,
(n) => {
if (n == true) {
getData();
}
}
);
</script>
<template>

View file

@ -304,7 +304,7 @@ const isEditStep3 = computed(() => {
<q-btn
flat
round
icon="info"
icon="mdi-eye"
color="info"
size="12px"
dense
@ -529,6 +529,7 @@ const isEditStep3 = computed(() => {
<DialogProgress
v-model:modal="modalProgress"
v-model:type="type"
v-model:rows="rows"
:idList="idList"
/>
<DialogProblem

View file

@ -16,7 +16,15 @@ import type {
FormCapacityList,
ListCriteria,
} from "@/modules/08_KPI/interface/request/index";
import DialogListCriteria from "@/modules/08_KPI/components/Tab/Dialog/DialogListCriteria.vue";
import DialogCompetncyByRow from "@/modules/08_KPI/components/Tab/Dialog/DialogCompetncyByRow.vue";
import DialogLevel from "@/modules/08_KPI/components/Tab/Dialog/DialogLevel.vue";
const modalLevel = ref<boolean>(false)
const modalCompetncyByRow = ref<boolean>(false);
const dataCompetncyByRow = ref<any[]>([]);
const dataLevel = ref<any[]>([]);
const modalCriteria = ref<boolean>(false);
const dataListCriteria = defineModel<ListCriteria[]>("dataListCriteria", {
required: true,
});
@ -127,7 +135,6 @@ function getData(type: string) {
.then(async (res) => {
const data = res.data.result.data;
rows.value[type] = data;
console.log("🚀 ~ .then ~ rows.value[type]:", rows.value[type])
lists.value = await lists.value.filter((x: any) => x.type != type);
lists.value.push({ type: type, data });
})
@ -257,8 +264,18 @@ watch(
}
);
function onInfo(){
function onInfo() {
modalCriteria.value = true;
}
function onAchievement(data: any) {
modalCompetncyByRow.value = true;
dataCompetncyByRow.value = data;
}
function onLevel(num:number,list:any){
dataLevel.value = list.filter((i:any)=> i.level == num)
modalLevel.value = true
}
onMounted(() => {
@ -277,7 +294,7 @@ onMounted(() => {
<div class="col">
<span class="text-weight-medium">{{ item.name }}</span>
<q-btn
v-if="isEditStep1"
v-if="!isEditStep1"
class="q-ml-xs"
flat
round
@ -324,7 +341,19 @@ onMounted(() => {
<q-tr :props="props">
<q-th auto-width />
<q-th v-for="col in props.cols" :key="col.name" :props="props">
<span class="text-weight-medium">{{ col.label }}</span>
<span v-if="col.name == 'point'" class="text-weight-medium">
<q-btn
flat
icon="mdi-eye"
color="info"
round
class="q-ml-xs"
@click="onInfo"
>
<q-tooltip>เกณฑการประเม</q-tooltip> </q-btn
>{{ col.label }}</span
>
<span v-else class="text-weight-medium">{{ col.label }}</span>
</q-th>
<q-th auto-width />
</q-tr>
@ -338,7 +367,7 @@ onMounted(() => {
color="info"
round
class="q-ml-xs"
@click="onInfo"
@click="onAchievement(props.row.achievement)"
>
<q-tooltip>พฤตกรรมทคาดหว/พฤตกรรมยอย</q-tooltip>
</q-btn>
@ -374,6 +403,9 @@ onMounted(() => {
: "-"
}}
</div>
<div v-else-if="col.name == 'level'">
<div @click="onLevel(props.row.level,props.row.achievement)" class="text-teal">{{ props.row.level }}</div>
</div>
<div v-else>
{{ col.value }}
</div>
@ -388,25 +420,13 @@ onMounted(() => {
<q-btn
flat
round
icon="mdi-developer-board"
icon="mdi-account-details"
color="blue-6"
size="12px"
dense
@click="openPopupProgress(props.row.id)"
>
<q-tooltip>รายงานความกาวหน</q-tooltip>
</q-btn>
<q-btn
flat
round
icon="warning"
color="red-5"
size="12px"
dense
main="problem"
@click="openPopupProblem(props.row.id)"
>
<q-tooltip>รายงานปญหา</q-tooltip>
<q-tooltip>นทกเหตการณ/พฤตกรรม</q-tooltip>
</q-btn>
</div>
@ -561,6 +581,21 @@ onMounted(() => {
v-model:type="type"
:idList="idList"
/>
<DialogListCriteria
v-model:modal="modalCriteria"
v-model:dataListCriteria="dataListCriteria"
/>
<DialogCompetncyByRow
v-model:modal="modalCompetncyByRow"
v-model:rows="dataCompetncyByRow"
/>
<DialogLevel
v-model:modal="modalLevel"
v-model:rows="dataLevel"
/>
</template>
<style scoped>

View file

@ -316,15 +316,15 @@ onMounted(() => {
<q-btn
flat
round
icon="mdi-developer-board"
icon="mdi-account-details"
color="blue-6"
size="12px"
dense
@click="openPopupProgress(props.row.id)"
>
<q-tooltip>รายงานความกาวหน</q-tooltip>
<q-tooltip>นทกเหตการณ/พฤตกรรม</q-tooltip>
</q-btn>
<q-btn
<!-- <q-btn
flat
round
icon="warning"
@ -335,7 +335,7 @@ onMounted(() => {
@click="openPopupProblem(props.row.id)"
>
<q-tooltip>รายงานปญหา</q-tooltip>
</q-btn>
</q-btn> -->
</div>
<div v-if="isEditStep1">

View file

@ -57,7 +57,8 @@ interface FormCommentByRole {
id: string;
topic: string;
reason: string;
createdFullName: string;
score:string
reasonEvaluator: string;
reasonCommander: string;
reasonCommanderHigh: string;

View file

@ -1,9 +1,26 @@
import { defineStore } from "pinia";
import { ref, reactive } from "vue";
import { ref, reactive, watch } from "vue";
import type { DataOptions } from "./interface/index/Main";
import type { FormQuery } from "@/modules/08_KPI/interface/request/index";
import { useCounterMixin } from "@/stores/mixin";
import http from "@/plugins/http";
import config from "@/app.config";
import { useQuasar } from "quasar";
export const useKpiDataStore = defineStore("KPIDate", () => {
const $q = useQuasar();
const mixin = useCounterMixin();
const {
dialogConfirm,
success,
showLoader,
hideLoader,
messageError,
findPosMasterNoOld,
findOrgNameOld,
date2Thai,
} = mixin;
const tabMainevaluator = ref<string>("1");
const yearRound = ref<number>(new Date().getFullYear());
const formQuery = reactive<FormQuery>({
@ -13,7 +30,7 @@ export const useKpiDataStore = defineStore("KPIDate", () => {
keyword: "",
});
const selected = ref([]);
const work = ref<boolean>(false);
const tabMain = ref<string>("1");
const dataProfile = ref<any>({
profileId: null,
@ -313,6 +330,47 @@ export const useKpiDataStore = defineStore("KPIDate", () => {
const indicatorScoreVal = ref<number>(0); // สรุปผลการประเมินผลสัมฤทธิ์ของงานที่ได้
const competencyScoreVal = ref<number>(0); // ผลการประเมินสมรรถนะที่ได้กี่คะแนน
function getDataWork() {
showLoader();
http
.get(config.API.orgPosition + `/${dataProfile.value.profileId}`)
.then((res) => {
const data = res.data.result.isProbation;
work.value = data;
if (data) {
indicatorScore.value = 50;
competencyScore.value = 40;
excusiveCompetencyScore.value = 40;
competencyDevScore.value = 10
} else {
indicatorScore.value = 70;
competencyScore.value = 20;
excusiveCompetencyScore.value = 20;
competencyDevScore.value = 30
}
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
hideLoader();
});
}
watch(
() => tabMain.value,
() => {
if (tabMain.value == "3" && tabOpen.value == 3) {
getDataWork();
} else {
indicatorScore.value = 70;
competencyScore.value = 20;
excusiveCompetencyScore.value = 20;
competencyDevScore.value = 30
}
}
);
return {
tabMain,
dataProfile,
@ -356,5 +414,6 @@ export const useKpiDataStore = defineStore("KPIDate", () => {
formQuery,
yearRound,
selected,
work,
};
});

View file

@ -92,7 +92,7 @@ async function getProfile() {
.get(config.API.orgPosition + `/${store.dataEvaluation.profileId}`)
.then(async (res) => {
const data = await res.data.result;
store.dataProfile = data;
store.dataProfile = await data;
})
.catch((e) => {
messageError($q, e);
@ -425,7 +425,6 @@ onMounted(async () => {
>*ำหน(อยละ) ผลสมฤทธของงานไมกตอง</span
>
<br v-if="!$q.screen.gt.xs" />
<q-btn
v-if="
store.rolePerson == 'USER' &&