API รายการการประเมินผลการปฏิบัติราชการระดับบุคคล

This commit is contained in:
DESKTOP-1R2VSQH\Lenovo ThinkPad E490 2024-04-26 09:34:17 +07:00
parent 266ad5ef7c
commit bdbf4582ee
7 changed files with 254 additions and 107 deletions

View file

@ -25,6 +25,8 @@ interface ArrayFileList {
fileName: string;
}
const isReadonly = <boolean>(route.name === "KPIEditEvaluator" ? true : false);
const documentFile = ref<any>(null);
const fileList = ref<ArrayFileList[]>([]);
@ -156,7 +158,7 @@ onMounted(() => {
</div>
<div class="col-12"><q-separator /></div>
<div class="row col-12 q-col-gutter-y-sm q-pa-sm">
<div class="col-12 row">
<div class="col-12 row" v-if="!isReadonly">
<q-file
for="inputFiles"
class="col-12"

View file

@ -1,6 +1,7 @@
<script setup lang="ts">
import { ref, reactive, watch } from "vue";
import { useQuasar } from "quasar";
import { useRoute } from "vue-router";
import config from "@/app.config";
import http from "@/plugins/http";
@ -10,6 +11,7 @@ import { useCounterMixin } from "@/stores/mixin";
import { useKpiDataStore } from "@/modules/08_KPI/store";
const $q = useQuasar();
const route = useRoute();
const mixin = useCounterMixin();
const store = useKpiDataStore();

View file

@ -1,6 +1,7 @@
<script setup lang="ts">
import { ref } from "vue";
import { useKpiDataStore } from "@/modules/08_KPI/store";
import { useRoute } from "vue-router";
import Assessment from "@/modules/08_KPI/components/Tab/01_Assessment.vue";
import CommanderAbove from "@/modules/08_KPI/components/Tab/02_CommanderAbove.vue";
@ -8,6 +9,8 @@ import CommanderAboveOneStep from "@/modules/08_KPI/components/Tab/03_CommanderA
import File from "@/modules/08_KPI/components/Tab/04_File.vue";
const store = useKpiDataStore();
const route = useRoute();
const isReadonly = <boolean>(route.name === "KPIEditEvaluator" ? true : false);
const itemsTab = ref<any>([
{
@ -30,7 +33,6 @@ const itemsTab = ref<any>([
const splitterModel = ref<number>(12);
</script>
<template>
<q-splitter v-model="splitterModel" disable>
<template v-slot:before>

View file

@ -26,6 +26,7 @@ const {
success,
} = useCounterMixin();
const isReadonly = <boolean>(route.name === "KPIEditEvaluator" ? true : false);
const title = defineModel<string>("title", { required: true });
const rows = defineModel<any>("data", { required: true });
const numpage = defineModel<number>("page", { required: true });
@ -190,6 +191,7 @@ watch(
<div class="col">
<span class="text-weight-medium">{{ title }}</span>
<q-btn
v-if="!isReadonly"
class="q-ml-xs"
flat
round
@ -204,6 +206,7 @@ watch(
</div>
<div class="col-auto">
<q-btn
v-if="!isReadonly"
flat
round
icon="mdi-clipboard-check-outline"
@ -239,7 +242,7 @@ watch(
<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-th auto-width v-if="!isReadonly" />
</q-tr>
</template>
<template v-slot:body="props">
@ -286,7 +289,7 @@ watch(
{{ col.value ? col.value : "-" }}
</div>
</q-td>
<td>
<td v-if="!isReadonly">
<q-btn
flat
round

View file

@ -15,7 +15,9 @@ import type {
ListCriteria,
} from "@/modules/08_KPI/interface/request/index";
const dataListCriteria = defineModel<ListCriteria[]>("dataListCriteria", { required: true, });
const dataListCriteria = defineModel<ListCriteria[]>("dataListCriteria", {
required: true,
});
const sortedDataListCriteria = computed(() => {
return dataListCriteria.value.sort((a, b) => a.level - b.level);
@ -26,6 +28,8 @@ const store = useKpiDataStore();
const route = useRoute();
const id = ref<string>(route.params.id as string);
const isReadonly = <boolean>(route.name === "KPIEditEvaluator" ? true : false);
const idCapacity = ref<string | null>(null);
const $q = useQuasar();
@ -203,6 +207,7 @@ onMounted(() => {
<div class="col">
<span class="text-weight-medium">{{ item.name }}</span>
<q-btn
v-if="!isReadonly"
class="q-ml-xs"
flat
round
@ -218,6 +223,7 @@ onMounted(() => {
<q-space />
<q-btn
v-if="!isReadonly"
flat
round
icon="mdi-clipboard-check-outline"
@ -249,7 +255,7 @@ onMounted(() => {
<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-th auto-width v-if="!isReadonly" />
</q-tr>
</template>
<template v-slot:body="props">
@ -295,7 +301,7 @@ onMounted(() => {
{{ col.value }}
</div>
</q-td>
<q-td auto-width>
<q-td v-if="!isReadonly">
<q-btn
flat
round
@ -335,7 +341,6 @@ onMounted(() => {
v-model:type="typeCompetency"
v-model:dataListCriteria="dataListCriteria"
:get-data="getData"
/>
<div class="row text-body2 text-weight-bold justify-center">

View file

@ -13,6 +13,8 @@ import type { FormProfile } from "@/modules/08_KPI/interface/request/index";
const route = useRoute();
const id = ref<string>(route.params.id as string);
const isReadonly = <boolean>(route.name === "KPIEditEvaluator" ? true : false);
const store = useKpiDataStore();
const $q = useQuasar();
const mixin = useCounterMixin();
@ -111,10 +113,13 @@ onMounted(() => {
flat
color="primary"
class="q-mr-sm"
@click="router.push(`/KPI`)"
@click="
isReadonly ? router.push(`/KPI-evaluator`) : router.push(`/KPI`)
"
/>
{{ id ? `แก้ไขแบบประเมิน` : `เพิ่มแบบประเมิน` }}
<q-space />
<!-- <q-btn label="บันทึก" color="secondary" unelevated @click="onSave"
><q-tooltip>นท</q-tooltip></q-btn
> -->

View file

@ -1,30 +1,38 @@
<script setup lang="ts">
import { ref, onMounted } from "vue";
import { ref, onMounted, reactive, watch } from "vue";
import { useRouter } from "vue-router";
import { useQuasar } from "quasar";
import config from "@/app.config";
import http from "@/plugins/http";
import type { DataOptions } from "@/modules/08_KPI/interface/index/Main";
import type { QTableProps } from "quasar";
import { useCounterMixin } from "@/stores/mixin";
import { useKpiDataStore } from "@/modules/08_KPI/store";
const mixin = useCounterMixin()
const { date2Thai } = mixin
const $q = useQuasar();
const router = useRouter();
const store = useKpiDataStore();
const { showLoader, hideLoader, messageError, date2Thai, dialogConfirm } =
useCounterMixin();
const filterKeyword = ref<string>("");
const rows = ref<any>();
const round = ref<string>("ID1");
const roundOp = ref<DataOptions[]>([
{
id: "ID1",
name: "รอบเมษา",
},
const year = ref<number>(new Date().getFullYear());
const round = ref<string>("");
const roundOp = ref<DataOptions[]>([]);
const visibleColumns = ref<string[]>([
"name",
"createdAt",
"evaluationStatus",
"evaluationStatus",
]);
const visibleColumns = ref<string[]>(["name", "createDate", "status", "result"]);
const columns = ref<QTableProps["columns"]>([
{
name: "name",
@ -38,77 +46,132 @@ const columns = ref<QTableProps["columns"]>([
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "createDate",
name: "createdAt",
align: "left",
label: "วันที่สร้างแบบประเมิน",
sortable: true,
field: "createDate",
field: "createdAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
format: (v) => date2Thai(v),
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "status",
name: "evaluationStatus",
align: "left",
label: "สถานะการประเมิน",
sortable: true,
field: "status",
field: "evaluationStatus",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
format: (v) => store.convertResults(v),
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "result",
name: "evaluationStatus",
align: "left",
label: "ผลการประเมิน",
sortable: true,
field: "result",
field: "evaluationStatus",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
format: (v) => store.convertResults(v),
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
]);
/** ดึงข้อมูล */
function getData() {
const data = [
{
id: "ID1",
name: "สมศรี ใจดี",
createDate: '2024-02-16T06:01:00.000Z',
status: "รอดำเนินการ",
result: "ผ่านเกณฑ์การประเมิน",
},
{
id: "ID1",
name: "สมจิตร ใจดี",
createDate: '2024-02-16T06:01:00.000Z',
status: "รอดำเนินการ",
result: "ผ่านเกณฑ์การประเมิน",
},
];
rows.value = data;
// showLoader();
// await http
// .get(config.API.orgPrefix)
// .then(async (res) => {
// })
// .catch((err) => {
// messageError($q, err);
// })
// .finally(() => {
// hideLoader();
// });
const formQuery = reactive({
page: 1,
pageSize: 10,
});
const totalList = ref<number>(1);
function fetchRoundOption() {
showLoader();
http
.get(
config.API.kpiPeriod +
`?page=${1}&pageSize=${10}&keyword=${""}&year=${year.value}`
)
.then((res) => {
const data = res.data.result.data;
const list = data.map((e: any) => ({
id: e.id,
name:
e.durationKPI === "OCT"
? "รอบตุลาคม"
: e.durationKPI === "APR"
? "รอบเมษายน"
: "",
}));
roundOp.value = list;
fetchList();
})
.catch((err) => {
messageError($q, err);
})
.finally(() => {
hideLoader();
});
}
function onEdit(id:string){
router.push(`/KPI-evaluator/${id}`)
function fetchList() {
showLoader();
http
.get(
config.API.kpiEvaluation +
`/admin?page=${formQuery.page}&pageSize=${formQuery.pageSize}&kpiPeriodId=${round.value}`
)
.then((res) => {
const data = res.data.result;
totalList.value = Math.ceil(data.total / formQuery.pageSize);
rows.value = data.data;
})
.catch((err) => {
messageError($q, err);
})
.finally(() => {
hideLoader();
});
}
function changRound() {
formQuery.page = 1;
fetchList();
}
function redirectViewDetail(id: string) {
router.push(`/KPI-evaluator/${id}`);
}
/**
* function updatePagination
* @param newPagination อม Pagination ใหม
*/
function updatePagination(newPagination: any) {
formQuery.page = 1;
formQuery.pageSize = newPagination.rowsPerPage;
}
const pagination = ref({
sortBy: "desc",
descending: false,
page: 1,
rowsPerPage: 10,
});
watch(
() => formQuery.pageSize,
() => {
fetchList();
}
);
onMounted(async () => {
getData();
fetchRoundOption();
});
</script>
@ -131,18 +194,57 @@ onMounted(async () => {
<div class="col-12">
<q-card bordered class="q-pa-md">
<q-toolbar style="padding: 0">
<q-select
v-model="round"
outlined
label="รอบการประเมิน"
dense
option-label="name"
option-value="id"
:options="roundOp"
style="min-width: 200px"
emit-value
map-options
/>
<div class="row q-gutter-sm">
<datepicker
menu-class-name="modalfix"
v-model="year"
:locale="'th'"
autoApply
year-picker
:enableTimePicker="false"
@update:model-value="fetchRoundOption()"
>
<template #year="{ year }">{{ year + 543 }}</template>
<template #year-overlay-value="{ value }">{{
parseInt(value + 543)
}}</template>
<template #trigger>
<q-input
dense
lazy-rules
outlined
class="inputgreen"
hide-bottom-space
:model-value="!!year ? year + 543 : null"
:label="`${'ปีงบประมาณ'}`"
>
<template v-slot:prepend>
<q-icon
name="event"
class="cursor-pointer"
style="color: var(--q-primary)"
>
</q-icon>
</template>
</q-input>
</template>
</datepicker>
<q-select
v-model="round"
outlined
label="รอบการประเมิน"
dense
option-label="name"
option-value="id"
:options="roundOp"
style="min-width: 200px"
emit-value
map-options
@update:model-value="changRound"
/>
</div>
<q-space />
<div class="row q-gutter-sm">
<q-input
@ -167,41 +269,67 @@ onMounted(async () => {
/>
</div>
</q-toolbar>
<q-table
ref="table"
:columns="columns"
:rows="rows"
:filter="filterKeyword"
row-key="id"
flat
bordered
:paging="true"
dense
class="custom-table2"
: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" >
<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" @click="onEdit(props.row.id)">
<div v-if="col.name == 'createDate'">
{{ col.value ? date2Thai(col.value):'-' }}
</div>
<div v-else>
{{ col.value }}
</div>
</q-td>
</q-tr>
</template>
</q-table>
<div class="col-12">
<q-table
ref="table"
:columns="columns"
:rows="rows"
:filter="filterKeyword"
row-key="id"
flat
bordered
:paging="true"
dense
class="custom-table2"
:rows-per-page-options="[10, 25, 50, 100]"
:visible-columns="visibleColumns"
v-model:pagination="pagination"
@update:pagination="updatePagination"
>
<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"
@click="redirectViewDetail(props.row.id)"
>
<div v-if="col.name === 'name'">
{{
`${props.row.prefix}${props.row.firstname} ${props.row.lastname}`
}}
</div>
<div v-else>
{{ col.value ? col.value : "-" }}
</div>
</q-td>
</q-tr>
</template>
<template v-slot:pagination="scope">
<q-pagination
v-model="formQuery.page"
active-color="primary"
color="dark"
:max="Number(totalList)"
size="sm"
boundary-links
direction-links
:max-pages="5"
@update:model-value="fetchList"
></q-pagination>
</template>
</q-table>
</div>
</q-card>
</div>
</div>