This commit is contained in:
STW_TTTY\stwtt 2024-04-09 15:22:23 +07:00
parent cf66659b9a
commit 59aa022bab
15 changed files with 1629 additions and 6 deletions

View file

@ -0,0 +1,85 @@
<script setup lang="ts">
import { useQuasar, type QTableProps } from "quasar";
import { ref, onMounted } from "vue";
import Work from "@/modules/08_KPI/components/Tab/Topic/01_Template.vue";
import Capacity from "@/modules/08_KPI/components/Tab/Topic/02_Template.vue";
const rows_01 = ref<any[]>();
const rows_02 = ref<any[]>();
const rows_03 = ref<any[]>();
const rows_04 = ref<any[]>();
const rows_05 = ref<any[]>();
const total = ref<number>(0);
const resultWork = ref<number>(0);
const resultEvaluation = ref<number>(0);
function getList() {
const data = [
{
indicators: "ตัวชี้วัด 1",
target: null,
scoreLevel: "4",
weight: "50",
workResult: "ระดับ 5",
evaluationResults: "50",
},
];
rows_01.value = data;
}
onMounted(() => {
getList();
});
</script>
<template>
<q-scroll-area style="height: 400px" class="bg-white row col-12">
<div class="text-weight-bold text-body1">
<span class="txt-under text-blue-5">องคประกอบท 1</span>
<span> ผลสมฤทธของงาน</span>
</div>
<div class="q-gutter-md q-mt-sm">
<!-- องคประกอบท 1 -->
<Work v-model:data="rows_01" :title="`1. งานตามแผนปฏิบัติราชการประจำปี`" :page="1" />
<Work v-model:data="rows_02" :title="`2. งานตามหน้าที่ความรับผิดชอบหลัก`" :page="2" />
<Work v-model:data="rows_03" :title="`3. งานที่ได้รับมอบหมาย`" :page="3" />
<div class="row text-body1 text-weight-bold">
<div class="col-5 text-center">
<span>รวมผลการประเม (อยละ) 100</span>
</div>
<div class="col-1 text-primary">{{ total }}</div>
<div class="col-5 text-center">
<span>สรปผลการประเมนผลสมฤทธของงาน (คะแนนเต 70 คะแนน)</span>
</div>
<div class="col-1 text-primary">{{ resultWork }}</div>
</div>
<q-separator class="q-py-xs" />
<!-- องคประกอบท 2 -->
<div class="text-weight-bold text-body1 q-mb-sm">
<span class="txt-under text-blue-5">องคประกอบท 2</span>
<span> พฤตกรรมการปฎราชการ (สมรรถนะ)</span>
</div>
<Capacity v-model:data="rows_04" :title="`1. สมรรถนะหลัก`" :page="1" />
<Capacity v-model:data="rows_05" :title="`2. สมรรถนะประจำกลุ่ม`" :page="2" />
<div class="row justify-evenly text-body1 text-weight-bold">
<div class="col-5 text-right">
<span>ผลการประเมนสมรรถนะ (20 คะแนน)</span>
</div>
<div class="col-5 text-primary">{{ resultEvaluation }}</div>
</div>
</div>
</q-scroll-area>
</template>
<style scoped>
.txt-under {
text-decoration: underline;
}
</style>

View file

@ -0,0 +1,3 @@
<template>
<div>2</div>
</template>

View file

@ -0,0 +1,3 @@
<template>
<div>3</div>
</template>

View file

@ -0,0 +1,3 @@
<template>
<div>4</div>
</template>

View file

@ -0,0 +1,281 @@
<script setup lang="ts">
import { ref, reactive } from "vue";
import DialogHeader from "@/components/DialogHeader.vue";
const modal = defineModel<boolean>("modal", { required: true });
const numpage = defineModel<number>("numpage", { required: true });
const splitterModel = ref<number>(30);
const search = ref<string>("");
const define = ref<string>("");
const formula = ref<string>("");
const listCheck = ref<number | null>();
const listTarget = ref<any>([
{
id: "ID1",
metricCode: "1กก",
indicatorName: "ตัวชี้วัด 1",
},
{
id: "ID2",
metricCode: "2กก",
indicatorName: "ตัวชี้วัด 2",
},
]);
const formDetail = reactive<any>({
oc: `สำนักงานคณะกรรมการข้าราชการกรุงเทพมหานคร/กองบริหารทั่วไป/กลุ่มงานช่วยนักบริหาร`,
indicators: "1",
code: "1กก",
name: "ตัวชี้วัด 1",
target: "",
unit: "",
weight: "100",
});
const formScore = reactive<any>({
score5: "5",
score4: "4",
score3: "3",
score2: "2",
score1: "1",
});
const fieldDetailLabels = {
oc: "หน่วยงาน/ส่วนราชการ",
indicators: "ลำดับตัวชี้วัด",
code: "รหัสตัวชี้วัด",
name: "ชื่อตัวชี้วัด",
target: "ค่าเป้าหมาย",
unit: "หน่วยนับ",
weight: "น้ำหนัก (ร้อยละ)",
};
const fieldLabels = {
score5: "5",
score4: "4",
score3: "3",
score2: "2",
score1: "1",
};
function clickList(index: number, data: any) {
listCheck.value = index;
// dataList.value = data.map((i: any) => ({
// commandNo: i.commandNo,
// duty: i.duty,
// prefix: i.prefix,
// firstName: i.firstName,
// lastName: i.lastName,
// fullName:`${i.prefix}${i.firstName} ${i.lastName}`
// }));
}
/** ปิด dialog */
function closeDialog() {
modal.value = false;
search.value = ''
define.value = ''
formula.value = ''
}
/** เรียกใช้ class */
function getclass() {
return "inputgreen";
}
function onSubmit() {}
</script>
<template>
<q-dialog v-model="modal" persistent>
<q-card class="col-12" style="width: 80%">
<q-form greedy @submit.prevent @validation-success="onSubmit">
<DialogHeader
:tittle="
numpage == 1
? 'เพิ่มตัวชี้วัดตามแผนปฏิบัติราชการประจําปี'
: 'เพิ่มตัวชี้วัดตามหน้าที่ความรับผิดชอบ'
"
:close="closeDialog"
/>
<q-separator />
<q-card-section class="q-pa-none scroll" style="max-height: 80vh">
<q-splitter v-model="splitterModel" disable>
<template v-slot:before>
<div class="bg-grey-1 q-pa-md">
<q-input
v-model="search"
outlined
dense
label="ค้นหา"
bg-color="white"
:class="getclass()"
>
<template v-slot:append>
<q-icon v-if="search == ''" name="search" />
<q-icon
v-if="search !== ''"
name="clear"
class="cursor-pointer"
@click="search = ''"
/>
</template>
</q-input>
<q-card flat bordered class="q-mt-sm">
<div class="row q-px-md q-py-sm items-center bg-grey-1">
<div class="col-4">
<span>รหสตวช</span>
</div>
<div class="col-4">
<span>อตวช</span>
</div>
</div>
<q-separator />
<q-card-section class="q-pa-none">
<q-scroll-area
style="height: 71vh"
class="bg-white row col-12"
>
<q-list
v-for="(item, index) in listTarget"
:key="index"
bordered
separator
>
<q-item
clickable
v-ripple
:active="listCheck === index"
active-class="my-menu-link"
@click="clickList(index, item.id)"
>
<q-item-section class="q-pa-none">
<div class="row items-center" style="height: 20px">
<div class="col-4">
<span>{{ item.metricCode }}</span>
</div>
<div class="col-4">
<span>{{ item.indicatorName }}</span>
</div>
</div>
</q-item-section>
</q-item>
</q-list>
</q-scroll-area>
</q-card-section>
</q-card>
</div>
</template>
<template v-slot:after>
<div class="row q-pa-md q-col-gutter-md">
<div class="col-12">
<span class="text-body1 text-weight-bold"
>รายละเอยดตวช</span
>
</div>
<div class="col-8">
<q-card bordered class="full-height">
<div
v-for="(field, index) in Object.keys(fieldDetailLabels)"
:key="index + 1"
>
<div class="row q-pa-md">
<div class="col-3 text-grey-6 text-weight-medium">
{{
fieldDetailLabels[
field as keyof typeof fieldDetailLabels
]
}}
</div>
<div class="col-7">
<span>{{
formDetail[field] ? formDetail[field] : "-"
}}</span>
</div>
</div>
</div>
</q-card>
</div>
<div class="col-4">
<q-card bordered>
<div class="bg-grey-2 row q-py-sm text-weight-bold">
<div class="col-6 text-center">ระดบคะแนน</div>
<div class="col-6 text-center">ผลสำเรจของงาน</div>
</div>
<div
v-for="(field, index) in Object.keys(fieldLabels)"
:key="index + 1"
>
<div class="row q-py-lg">
<div
class="col-6 text-center text-body1 text-weight-bold"
>
{{ fieldLabels[field as keyof typeof fieldLabels] }}
</div>
<div class="col-6 text-center">
<span>{{
formScore[field] ? formScore[field] : "-"
}}</span>
</div>
</div>
<div
class="col-12"
v-if="index !== Object.keys(fieldLabels).length - 1"
>
<q-separator />
</div>
</div>
</q-card>
</div>
<div class="col-12">
<q-input
v-model="define"
label="นิยามหรือความหมายของตัวชี้วัด"
type="textarea"
outlined
dense
:rules="[(val:string) => !!val || `${'กรุณากรอกตัวชี้วัด'}`,]"
hide-bottom-space
:class="getclass()"
/>
</div>
<div class="col-12">
<q-input
v-model="formula"
label="สูตรคำนวณ"
type="textarea"
outlined
dense
:rules="[(val:string) => !!val || `${'กรุณากรอกตัวชี้วัด'}`,]"
hide-bottom-space
:class="getclass()"
/>
</div>
</div>
</template>
</q-splitter>
</q-card-section>
<q-separator />
<q-card-actions align="right" class="bg-white text-teal">
<q-btn
label="บันทึก"
color="secondary"
type="submit"
><q-tooltip>นทกขอม</q-tooltip></q-btn
>
</q-card-actions>
</q-form>
</q-card>
</q-dialog>
</template>
<style scoped>
.my-menu-link {
background: #ebf9f7 !important;
color: #1bb19ab8 !important;
}
</style>

View file

@ -0,0 +1,122 @@
<script setup lang="ts">
import { ref, reactive } from "vue";
import DialogHeader from "@/components/DialogHeader.vue";
import type { FormDataAssigned } from '@/modules/08_KPI/interface/request/index'
const modal = defineModel<boolean>("modal", { required: true });
const formData = reactive<FormDataAssigned>({
indicator:'',//
target:'',//
unit:'',//
weigth:'',// ()
definition:'',//
})
/** ปิด dialog */
function closeDialog() {
modal.value = false;
formData.indicator = ''
formData.target = ''
formData.unit = ''
formData.weigth = ''
formData.definition = ''
}
/** เรียกใช้ class */
function getclass() {
return "inputgreen";
}
function onSubmit() {}
</script>
<template>
<q-dialog v-model="modal" persistent>
<q-card class="col-12" style="width: 50%">
<q-form greedy @submit.prevent @validation-success="onSubmit">
<DialogHeader
:tittle="`เพิ่มตัวชี้วัดที่ได้รับมอบหมาย`"
:close="closeDialog"
/>
<q-separator />
<q-card-section >
<div class="row q-col-gutter-sm">
<div class="col-12">
<q-input
v-model="formData.indicator"
label="ชื่อตัวชี้วัด"
outlined
dense
:rules="[(val:string) => !!val || `${'กรุณากรอกชื่อตัวชี้วัด'}`,]"
hide-bottom-space
:class="getclass()"
/>
</div>
<div class="col-4">
<q-input
v-model="formData.target"
label="ค่าเป้าหมาย"
outlined
dense
:rules="[(val:string) => !!val || `${'กรุณากรอกค่าเป้าหมาย'}`,]"
hide-bottom-space
:class="getclass()"
/>
</div>
<div class="col-4">
<q-input
v-model="formData.unit"
label="หน่วยนับ"
outlined
dense
:rules="[(val:string) => !!val || `${'กรุณากรอกหน่วยนับ'}`,]"
hide-bottom-space
:class="getclass()"
/>
</div>
<div class="col-4">
<q-input
v-model="formData.weigth"
label="น้ำหนัก (ร้อยละ)"
outlined
dense
:rules="[(val:string) => !!val || `${'กรุณากรอกน้ำหนัก (ร้อยละ)'}`,]"
hide-bottom-space
:class="getclass()"
/>
</div>
<div class="col-12">
<q-input
v-model="formData.definition"
label="นิยามหรือความหมายของตัวชี้วัด"
outlined
dense
type="textarea"
:rules="[(val:string) => !!val || `${'กรุณากรอกนิยามหรือความหมายของตัวชี้วัด'}`,]"
hide-bottom-space
:class="getclass()"
/>
</div>
</div>
</q-card-section>
<q-separator />
<q-card-actions align="right" class="bg-white text-teal">
<q-btn
label="บันทึก"
color="secondary"
type="submit"
><q-tooltip>นทกขอม</q-tooltip></q-btn
>
</q-card-actions>
</q-form>
</q-card>
</q-dialog>
</template>
<style scoped>
.my-menu-link {
background: #ebf9f7 !important;
color: #1bb19ab8 !important;
}
</style>

View file

@ -0,0 +1,282 @@
<script setup lang="ts">
import { ref, reactive } from "vue";
import DialogHeader from "@/components/DialogHeader.vue";
import type { DataOptions } from "@/modules/08_KPI/interface/index/Main";
const modal = defineModel<boolean>("modal", { required: true });
const numpage = defineModel<number>("numpage", { required: true });
const splitterModel = ref<number>(30);
const search = ref<string>("");
const define = ref<string>("");
const formula = ref<string>("");
const type = ref<string>("");
const listCheck = ref<number | null>();
const listTarget = ref<any>([
{
id: "ID1",
metricCode: "1กก",
indicatorName: "ตัวชี้วัด 1",
},
{
id: "ID2",
metricCode: "2กก",
indicatorName: "ตัวชี้วัด 2",
},
]);
const formDetail = reactive<any>({
type: "สมรรถนะหลัก",
name: "สมรรถนะ 1",
definition: "",
criteria: "",
});
const formScore = reactive<any>({
score1: "1",
score2: "2",
score3: "3",
score4: "",
score5: "5",
});
const fieldDetailLabels = {
type: "ประเภทสมรรถนะ",
name: "ชื่อสมรรถนะ",
definition: "คำจำกัดความ",
criteria: "กำหนดเกณฑ์การประเมิน",
};
const fieldLabels = {
score1: "1",
score2: "2",
score3: "3",
score4: "4",
score5: "5",
};
const competencyTypeOp = ref<DataOptions[]>([
{
id: "ID1",
name: "สมรรถนะหลัก",
},
{
id: "ID2",
name: "สมรรถนะประจำกลุ่มงาน",
},
{
id: "ID3",
name: "สมรรถนะประจำกลุ่มงาน",
},
{
id: "ID4",
name: "สมรรถนะประจำผู้บริหารกรุงเทพมหานคร",
},
{
id: "ID5",
name: "สมรรถนะเฉพาะสำหรับตำแหน่ง ผอ.เขต ผช.ผอ.เขต และหัวหน้าฝ่ายในสังกัด สนง.เขต",
},
{
id: "ID6",
name: "สมรรถนะเฉพาะสำหรับตำแหน่งผู้ตรวจราชการ กทม. และผู้ตรวจราชการ",
},
]);
function clickList(index: number, data: any) {
listCheck.value = index;
// dataList.value = data.map((i: any) => ({
// commandNo: i.commandNo,
// duty: i.duty,
// prefix: i.prefix,
// firstName: i.firstName,
// lastName: i.lastName,
// fullName:`${i.prefix}${i.firstName} ${i.lastName}`
// }));
}
/** ปิด dialog */
function closeDialog() {
modal.value = false;
type.value = ''
search.value = ''
}
/** เรียกใช้ class */
function getclass() {
return "inputgreen";
}
function onSubmit() {}
</script>
<template>
<q-dialog v-model="modal" persistent>
<q-card class="col-12" style="width: 80%">
<q-form greedy @submit.prevent @validation-success="onSubmit">
<DialogHeader :tittle="`เพิ่มสมรรถนะ`" :close="closeDialog" />
<q-separator />
<q-card-section class="q-pa-none scroll" style="max-height: 80vh">
<q-splitter v-model="splitterModel" disable>
<template v-slot:before>
<div class="bg-grey-1 q-pa-md q-gutter-sm">
<q-select
v-model="type"
outlined
label="ประเภทสมรรถนะ"
dense
bg-color="white"
option-label="name"
option-value="id"
:options="competencyTypeOp"
emit-value
:class="getclass()"
map-options
/>
<q-input
v-model="search"
outlined
dense
label="ค้นหา"
bg-color="white"
:class="getclass()"
>
<template v-slot:append>
<q-icon v-if="search == ''" name="search" />
<q-icon
v-if="search !== ''"
name="clear"
class="cursor-pointer"
@click="search = ''"
/>
</template>
</q-input>
<q-card flat bordered>
<div class="row q-px-md q-py-sm items-center bg-grey-1">
<div class="col-4">
<span>รหสตวช</span>
</div>
<div class="col-4">
<span>อตวช</span>
</div>
</div>
<q-separator />
<q-card-section class="q-pa-none">
<q-scroll-area
style="height: 33vh"
class="bg-white row col-12"
>
<q-list
v-for="(item, index) in listTarget"
:key="index"
bordered
separator
>
<q-item
clickable
v-ripple
:active="listCheck === index"
active-class="my-menu-link"
@click="clickList(index, item.id)"
>
<q-item-section class="q-pa-none">
<div class="row items-center" style="height: 20px">
<div class="col-4">
<span>{{ item.metricCode }}</span>
</div>
<div class="col-4">
<span>{{ item.indicatorName }}</span>
</div>
</div>
</q-item-section>
</q-item>
</q-list>
</q-scroll-area>
</q-card-section>
</q-card>
</div>
</template>
<template v-slot:after>
<div class="row q-pa-md q-col-gutter-md">
<div class="col-12">
<span class="text-body1 text-weight-bold"
>รายละเอยดตวช</span
>
</div>
<div class="col-8">
<q-card bordered class="full-height">
<div
v-for="(field, index) in Object.keys(fieldDetailLabels)"
:key="index + 1"
>
<div class="row q-pa-md">
<div class="col-3 text-grey-6 text-weight-medium">
{{
fieldDetailLabels[
field as keyof typeof fieldDetailLabels
]
}}
</div>
<div class="col-7">
<span>{{
formDetail[field] ? formDetail[field] : "-"
}}</span>
</div>
</div>
</div>
</q-card>
</div>
<div class="col-4">
<q-card bordered>
<div class="bg-grey-2 row q-py-sm text-weight-bold">
<div class="col-6 text-center">ระดบคะแนน</div>
<div class="col-6 text-center">ผลสำเรจของงาน</div>
</div>
<div
v-for="(field, index) in Object.keys(fieldLabels)"
:key="index + 1"
>
<div class="row q-py-lg">
<div
class="col-6 text-center text-body1 text-weight-bold"
>
{{ fieldLabels[field as keyof typeof fieldLabels] }}
</div>
<div class="col-6 text-center">
<span>{{
formScore[field] ? formScore[field] : "-"
}}</span>
</div>
</div>
<div
class="col-12"
v-if="index !== Object.keys(fieldLabels).length - 1"
>
<q-separator />
</div>
</div>
</q-card>
</div>
</div>
</template>
</q-splitter>
</q-card-section>
<q-separator />
<q-card-actions align="right" class="bg-white text-teal">
<q-btn label="บันทึก" color="secondary" type="submit"
><q-tooltip>นทกขอม</q-tooltip></q-btn
>
</q-card-actions>
</q-form>
</q-card>
</q-dialog>
</template>
<style scoped>
.my-menu-link {
background: #ebf9f7 !important;
color: #1bb19ab8 !important;
}
</style>

View file

@ -0,0 +1,204 @@
<script setup lang="ts">
import { ref } from "vue";
import Dialog from "@/modules/08_KPI/components/Tab/Dialog/01_Dialog.vue";
import Dialog03 from "@/modules/08_KPI/components/Tab/Dialog/03_Dialog.vue";
import type { QTableProps } from "quasar";
import { useCounterMixin } from "@/stores/mixin";
const title = defineModel<string>('title',{required:true})
const rows = defineModel<any>('data',{required:true})
const numpage = defineModel<number>('page',{required:true})
const mixin = useCounterMixin();
const { date2Thai } = mixin;
const filterKeyword = ref<string>("");
const modal = ref<boolean>(false);
const modalAssigned = ref<boolean>(false);
const visibleColumns = ref<string[]>([
"indicators",
"target",
"scoreLevel",
"weight",
"workResult",
"evaluationResults",
]);
const columns = ref<QTableProps["columns"]>([
{
name: "indicators",
align: "left",
label: "ตัวชี้วัด",
sortable: true,
field: "indicators",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "target",
align: "left",
label: "ค่าเป้าหมาย",
sortable: true,
field: "target",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "scoreLevel",
align: "left",
label: "ระดับคะแนนตามเกณฑ์การประเมิน",
sortable: true,
field: "scoreLevel",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "weight",
align: "left",
label: "น้ำหนัก (ร้อยละ)",
sortable: true,
field: "weight",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "workResult",
align: "left",
label: "ผลสำเร็จของงาน",
sortable: true,
field: "workResult",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "evaluationResults",
align: "left",
label: "ผลการประเมิน",
sortable: true,
field: "evaluationResults",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
]);
function onAdd() {
if(numpage.value !== 3){
modal.value = true;
}else if(numpage.value == 3){
modalAssigned.value = true
}
}
</script>
<template>
<q-card bordered style="border-radius: 5px">
<q-card-section class="bg-grey-3 q-py-sm">
<span class="text-weight-bold">{{ title }}</span>
<q-btn
class="q-ml-xs"
flat
round
icon="mdi-plus"
color="primary"
size="md"
@click="onAdd"
>
<q-tooltip>เพมขอม</q-tooltip>
</q-btn>
</q-card-section>
<q-card-section>
<q-table
ref="table"
:columns="columns"
:rows="rows"
:filter="filterKeyword"
row-key="id"
flat
bordered
:paging="true"
dense
hide-pagination
class="custom-table2"
:visible-columns="visibleColumns"
no-data-label="ยังไม่มีข้อมูลแสดงในตารางนี้"
>
<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-th auto-width />
</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">
<div v-if="col.name == 'createDate'">
{{ col.value ? date2Thai(col.value) : "-" }}
</div>
<div v-else>
{{ col.value ? col.value : "-" }}
</div>
</q-td>
</q-tr>
</template>
</q-table>
</q-card-section>
</q-card>
<Dialog v-model:modal="modal" :numpage="numpage"/>
<Dialog03 v-model:modal="modalAssigned" :numpage="numpage"/>
</template>
<style scoped>
.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;
}
}
</style>

View file

@ -0,0 +1,187 @@
<script setup lang="ts">
import { ref } from "vue";
import Dialog from "@/modules/08_KPI/components/Tab/Dialog/04_Dialog.vue";
import type { QTableProps } from "quasar";
import { useCounterMixin } from "@/stores/mixin";
const title = defineModel<string>('title',{required:true})
const rows = defineModel<any>('data',{required:true})
const numpage = defineModel<number>('page',{required:true})
const mixin = useCounterMixin();
const { date2Thai } = mixin;
const filterKeyword = ref<string>("");
const modal = ref<boolean>(false);
const modalAssigned = ref<boolean>(false);
const visibleColumns = ref<string[]>([
"capacity",
"level",
"scoreLevel",
"weight",
"evaluationResults",
]);
const columns = ref<QTableProps["columns"]>([
{
name: "capacity",
align: "left",
label: "รายการสมรรถนะ",
sortable: true,
field: "capacity",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "level",
align: "left",
label: "ระดับที่คาดหวัง",
sortable: true,
field: "level",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "scoreLevel",
align: "left",
label: "ระดับคะแนนตามเกณฑ์การประเมิน",
sortable: true,
field: "scoreLevel",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "weight",
align: "left",
label: "น้ำหนัก (ร้อยละ)",
sortable: true,
field: "weight",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "evaluationResults",
align: "left",
label: "ผลการประเมิน",
sortable: true,
field: "evaluationResults",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
]);
function onAdd() {
modal.value = true;
}
</script>
<template>
<q-card bordered style="border-radius: 5px">
<q-card-section class="bg-grey-3 q-py-sm">
<span class="text-weight-bold">{{ title }}</span>
<q-btn
class="q-ml-xs"
flat
round
icon="mdi-plus"
color="primary"
size="md"
@click="onAdd"
>
<q-tooltip>เพมขอม</q-tooltip>
</q-btn>
</q-card-section>
<q-card-section>
<q-table
ref="table"
:columns="columns"
:rows="rows"
:filter="filterKeyword"
row-key="id"
flat
bordered
:paging="true"
dense
hide-pagination
class="custom-table2"
:visible-columns="visibleColumns"
no-data-label="ยังไม่มีข้อมูลแสดงในตารางนี้"
>
<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-th auto-width />
</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">
<div v-if="col.name == 'createDate'">
{{ col.value ? date2Thai(col.value) : "-" }}
</div>
<div v-else>
{{ col.value ? col.value : "-" }}
</div>
</q-td>
</q-tr>
</template>
</q-table>
</q-card-section>
</q-card>
<Dialog v-model:modal="modal" :numpage="numpage"/>
</template>
<style scoped>
.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;
}
}
</style>