fix:load skeleton

This commit is contained in:
setthawutttty 2025-08-14 16:15:04 +07:00
parent 7cdff8d853
commit cacb84bb48
20 changed files with 894 additions and 309 deletions

View file

@ -8,8 +8,11 @@ import { useKpiDataStore } from "@/modules/08_KPI/store";
import type { ResEvaluatorAssessor } from "@/modules/08_KPI/interface/response/index"; import type { ResEvaluatorAssessor } from "@/modules/08_KPI/interface/response/index";
import type { FormQuery } from "@/modules/08_KPI/interface/request/index"; import type { FormQuery } from "@/modules/08_KPI/interface/request/index";
import SkeletonTable from "@/components/SkeletonTable.vue";
const store = useKpiDataStore(); const store = useKpiDataStore();
const router = useRouter(); const router = useRouter();
const isLoad = defineModel<boolean>('isLoad',{required:true})
const visibleColumns = defineModel<string[]>("visibleColumns", { const visibleColumns = defineModel<string[]>("visibleColumns", {
required: true, required: true,
}); });
@ -42,6 +45,7 @@ async function redirectViewDetail(id: string) {
<template> <template>
<div class="col-12"> <div class="col-12">
<d-table <d-table
v-if="!isLoad"
ref="table" ref="table"
:columns="columns" :columns="columns"
:rows="rows" :rows="rows"
@ -120,6 +124,7 @@ async function redirectViewDetail(id: string) {
></q-pagination> ></q-pagination>
</template> </template>
</d-table> </d-table>
<SkeletonTable v-else :columns="columns"/>
</div> </div>
</template> </template>

View file

@ -12,6 +12,8 @@ import { useKpiDataStore } from "@/modules/08_KPI/store";
import type { FormQuery } from "@/modules/08_KPI/interface/request/index"; import type { FormQuery } from "@/modules/08_KPI/interface/request/index";
import type { ResEvaluatorAssessor } from "@/modules/08_KPI/interface/response/index"; import type { ResEvaluatorAssessor } from "@/modules/08_KPI/interface/response/index";
import SkeletonTable from "@/components/SkeletonTable.vue";
const $q = useQuasar(); const $q = useQuasar();
const router = useRouter(); const router = useRouter();
const store = useKpiDataStore(); const store = useKpiDataStore();
@ -34,6 +36,7 @@ const rows = defineModel<ResEvaluatorAssessor[]>("rows", { required: true });
const formQuery = defineModel<FormQuery>("formQuery", { required: true }); const formQuery = defineModel<FormQuery>("formQuery", { required: true });
const total = defineModel<number>("total", { required: true }); const total = defineModel<number>("total", { required: true });
const maxPage = defineModel<number>("maxPage", { required: true }); const maxPage = defineModel<number>("maxPage", { required: true });
const isLoad = defineModel<boolean>("isLoad", { required: true });
const props = defineProps({ const props = defineProps({
updatePagination: { type: Function }, updatePagination: { type: Function },
@ -109,6 +112,7 @@ async function onClickApprove(type: string = "") {
<template> <template>
<div class="col-12"> <div class="col-12">
<d-table <d-table
v-if="!isLoad"
ref="table" ref="table"
:columns="columns" :columns="columns"
:rows="rows" :rows="rows"
@ -187,10 +191,7 @@ async function onClickApprove(type: string = "") {
</q-card-section> </q-card-section>
<q-separator /> <q-separator />
<q-list @click="redirectViewDetail(props.row.id)"> <q-list @click="redirectViewDetail(props.row.id)">
<q-item <q-item v-for="col in props.cols" :key="col.name">
v-for="col in props.cols"
:key="col.name"
>
<q-item-section> <q-item-section>
<q-item-label caption>{{ col.label }}</q-item-label> <q-item-label caption>{{ col.label }}</q-item-label>
@ -225,6 +226,7 @@ async function onClickApprove(type: string = "") {
></q-pagination> ></q-pagination>
</template> </template>
</d-table> </d-table>
<SkeletonTable v-else :columns="columns" />
</div> </div>
<div class="row justify-end q-mt-md q-gutter-sm" v-if="rows.length !== 0"> <div class="row justify-end q-mt-md q-gutter-sm" v-if="rows.length !== 0">

View file

@ -37,6 +37,10 @@ const store = useKpiDataStore();
const evaluationId = ref<string>(route.params.id.toString()); const evaluationId = ref<string>(route.params.id.toString());
const isLoad01 = ref<boolean>(false);
const isLoad02 = ref<boolean>(false);
const isLoad03 = ref<boolean>(false);
const rows_01 = ref<EvaluationIndicatorType[]>(); const rows_01 = ref<EvaluationIndicatorType[]>();
const rows_02 = ref<EvaluationIndicatorType[]>(); const rows_02 = ref<EvaluationIndicatorType[]>();
const rows_03 = ref<EvaluationIndicatorType[]>(); const rows_03 = ref<EvaluationIndicatorType[]>();
@ -53,6 +57,7 @@ const resultRole = ref<number>(0);
const resultAssigned = ref<number>(0); const resultAssigned = ref<number>(0);
function fetchListPlanned() { function fetchListPlanned() {
isLoad01.value = true;
http http
.get(config.API.kpiAchievement("planned") + `?id=${evaluationId.value}`) .get(config.API.kpiAchievement("planned") + `?id=${evaluationId.value}`)
.then((res) => { .then((res) => {
@ -62,6 +67,7 @@ function fetchListPlanned() {
evaluationResults: (e.point / 5) * e.weight, evaluationResults: (e.point / 5) * e.weight,
})); }));
rows_01.value = newRow; rows_01.value = newRow;
isLoad01.value = false;
if (newRow.length > 0) { if (newRow.length > 0) {
resultPlanned.value = newRow.reduce( resultPlanned.value = newRow.reduce(
@ -89,6 +95,7 @@ function fetchListPlanned() {
} }
function fetchListRole() { function fetchListRole() {
isLoad02.value = true;
http http
.get(config.API.kpiAchievement("role") + `?id=${evaluationId.value}`) .get(config.API.kpiAchievement("role") + `?id=${evaluationId.value}`)
.then((res) => { .then((res) => {
@ -98,7 +105,7 @@ function fetchListRole() {
evaluationResults: (e.point / 5) * e.weight, evaluationResults: (e.point / 5) * e.weight,
})); }));
rows_02.value = newRow; rows_02.value = newRow;
isLoad02.value = false;
if (newRow.length > 0) { if (newRow.length > 0) {
resultRole.value = newRow.reduce( resultRole.value = newRow.reduce(
(sum: number, e: any) => sum + e.evaluationResults, (sum: number, e: any) => sum + e.evaluationResults,
@ -119,6 +126,7 @@ function fetchListRole() {
} }
function fetchAssigned() { function fetchAssigned() {
isLoad03.value = true;
http http
.get(config.API.kpiAchievement("special") + `?id=${evaluationId.value}`) .get(config.API.kpiAchievement("special") + `?id=${evaluationId.value}`)
.then((res) => { .then((res) => {
@ -129,7 +137,7 @@ function fetchAssigned() {
})); }));
rows_03.value = newRow; rows_03.value = newRow;
isLoad03.value = false;
if (newRow.length > 0) { if (newRow.length > 0) {
resultAssigned.value = newRow.reduce( resultAssigned.value = newRow.reduce(
(sum: number, e: any) => sum + e.evaluationResults, (sum: number, e: any) => sum + e.evaluationResults,
@ -345,6 +353,7 @@ onMounted(() => {
<div v-if="groupNo == 1"> <div v-if="groupNo == 1">
<Work <Work
v-model:data="rows_01" v-model:data="rows_01"
v-model:isLoad="isLoad01"
:title="`มิติที่ 1 ภารกิจตามนโยบายและยุทธศาสตร์ของกรุงเทพมหานคร`" :title="`มิติที่ 1 ภารกิจตามนโยบายและยุทธศาสตร์ของกรุงเทพมหานคร`"
:page="1" :page="1"
:fetchList="fetchListPlanned" :fetchList="fetchListPlanned"
@ -391,6 +400,7 @@ onMounted(() => {
<Work <Work
v-model:data="rows_03" v-model:data="rows_03"
v-model:isLoad="isLoad03"
:title="`มิติที่ 2 วาระเร่งด่วนที่ได้รับมอบหมายพิเศษ (ถ้ามี)`" :title="`มิติที่ 2 วาระเร่งด่วนที่ได้รับมอบหมายพิเศษ (ถ้ามี)`"
:page="3" :page="3"
:fetchList="fetchAssigned" :fetchList="fetchAssigned"
@ -437,12 +447,16 @@ onMounted(() => {
คะแนน)</span คะแนน)</span
> >
<div class="text-primary q-pl-md"> <div class="text-primary q-pl-md">
{{ <div v-if="!isLoad01">
( {{
store.excusiveIndicator1ScoreVal + (
store.excusiveIndicator2ScoreVal store.excusiveIndicator1ScoreVal +
).toFixed(2) store.excusiveIndicator2ScoreVal
}} ).toFixed(2)
}}
</div>
<q-skeleton v-else type="text" />
</div> </div>
</div> </div>
</div> </div>
@ -452,6 +466,7 @@ onMounted(() => {
<div v-else> <div v-else>
<Work <Work
v-model:data="rows_01" v-model:data="rows_01"
v-model:isLoad="isLoad01"
:title="`1. งานตามแผนปฏิบัติราชการประจำปี`" :title="`1. งานตามแผนปฏิบัติราชการประจำปี`"
:page="1" :page="1"
:fetchList="fetchListPlanned" :fetchList="fetchListPlanned"
@ -459,6 +474,7 @@ onMounted(() => {
/> />
<Work <Work
v-model:data="rows_02" v-model:data="rows_02"
v-model:isLoad="isLoad02"
:title="`2. งานตามหน้าที่ความรับผิดชอบหลัก`" :title="`2. งานตามหน้าที่ความรับผิดชอบหลัก`"
:page="2" :page="2"
:fetchList="fetchListRole" :fetchList="fetchListRole"
@ -466,6 +482,7 @@ onMounted(() => {
/> />
<Work <Work
v-model:data="rows_03" v-model:data="rows_03"
v-model:isLoad="isLoad03"
:title="`3. งานอื่น ๆ ที่ได้รับมอบหมาย`" :title="`3. งานอื่น ๆ ที่ได้รับมอบหมาย`"
:page="3" :page="3"
:fetchList="fetchAssigned" :fetchList="fetchAssigned"
@ -517,7 +534,10 @@ onMounted(() => {
คะแนน)</span คะแนน)</span
> >
<div class="text-primary q-pl-md"> <div class="text-primary q-pl-md">
{{ store.indicatorScoreVal.toFixed(2) }} <div v-if="!isLoad01">
{{ store.indicatorScoreVal.toFixed(2) }}
</div>
<q-skeleton v-else type="text" />
</div> </div>
</div> </div>
</div> </div>

View file

@ -192,7 +192,9 @@ function userOpen() {
}); });
} }
const isLoad = ref<boolean>(false);
function getData() { function getData() {
isLoad.value = true;
http http
.get(config.API.kpiSendToGet(id.value)) .get(config.API.kpiSendToGet(id.value))
.then((res) => { .then((res) => {
@ -220,9 +222,11 @@ function getData() {
sumWeight.value = data.weightPoint1 + data.weightPoint2; sumWeight.value = data.weightPoint1 + data.weightPoint2;
sumResult.value = data.summaryPoint; sumResult.value = data.summaryPoint;
result.value = data.evaluationResults; result.value = data.evaluationResults;
isLoad.value = false;
}) })
.catch((e) => { .catch((e) => {
messageError($q, e); messageError($q, e);
isLoad.value = false;
}) })
.finally(() => {}); .finally(() => {});
} }
@ -306,22 +310,47 @@ onMounted(() => {
<tbody> <tbody>
<tr> <tr>
<td class="text-left">องคประกอบท 1 ผลสมฤทธของงาน</td> <td class="text-left">องคประกอบท 1 ผลสมฤทธของงาน</td>
<td class="text-left">{{ weight1 }}</td> <td class="text-left">
<td class="text-left">{{ result1 }}</td> <div v-if="!isLoad">
{{ weight1 }}
</div>
<q-skeleton v-else type="text" />
</td>
<td class="text-left">
<div v-if="!isLoad">{{ result1 }}</div>
<q-skeleton v-else type="text" />
</td>
</tr> </tr>
<tr> <tr>
<td class="text-left"> <td class="text-left">
องคประกอบท 2 พฤตกรรมการปฎราชการ (สมรรถนะ) องคประกอบท 2 พฤตกรรมการปฎราชการ (สมรรถนะ)
</td> </td>
<td class="text-left">{{ weight2 }}</td> <td class="text-left">
<td class="text-left">{{ result2 }}</td> <div v-if="!isLoad">{{ weight2 }}</div>
<q-skeleton v-else type="text" />
</td>
<td class="text-left">
<div v-if="!isLoad">{{ result2 }}</div>
<q-skeleton v-else type="text" />
</td>
</tr> </tr>
<tr> <tr>
<td class="text-right text-bold" style="font-size: 16px"> <td class="text-right text-bold" style="font-size: 16px">
รวม รวม
</td> </td>
<td class="text-left">{{ sumWeight }}</td> <td class="text-left">
<td class="text-left">{{ sumResult }}</td> <div v-if="!isLoad">{{ sumWeight }}</div>
<q-skeleton v-else type="text" />
</td>
<td class="text-left">
<div v-if="!isLoad">{{ sumResult }}</div>
<q-skeleton v-else type="text" />
</td>
</tr> </tr>
</tbody> </tbody>
</q-markup-table> </q-markup-table>
@ -332,7 +361,7 @@ onMounted(() => {
</div> </div>
</div> </div>
<div class="col-12 no-pointer"> <div class="col-12 no-pointer">
<div class="column"> <div class="column" v-if="!isLoad">
<q-radio <q-radio
v-model="result" v-model="result"
checked-icon="task_alt" checked-icon="task_alt"
@ -369,6 +398,12 @@ onMounted(() => {
label="ต้องปรับปรุง (คะแนนต่ำกว่าร้อยละ 60.00)" label="ต้องปรับปรุง (คะแนนต่ำกว่าร้อยละ 60.00)"
/> />
</div> </div>
<q-item v-else dense v-for="item in 5" style="max-width: 300px;">
<q-item-section class="q-pa-none">
<q-skeleton type="text" />
</q-item-section>
</q-item>
</div> </div>
<div class="col-12"> <div class="col-12">
<div class="text-weight-bold text-body2"> <div class="text-weight-bold text-body2">
@ -378,6 +413,7 @@ onMounted(() => {
<div class="col-12"> <div class="col-12">
<q-input <q-input
v-if="!isLoad"
v-model="title" v-model="title"
outlined outlined
lazy-rules lazy-rules
@ -390,9 +426,11 @@ onMounted(() => {
" "
:rules="[(val:string) => !!val || `${'กรุณากรอกชื่อเรื่อง/เนื้อหา/หัวข้อการพัฒนา'}`,]" :rules="[(val:string) => !!val || `${'กรุณากรอกชื่อเรื่อง/เนื้อหา/หัวข้อการพัฒนา'}`,]"
/> />
<q-skeleton v-else type="QInput" height="150px" />
</div> </div>
<div class="col-12"> <div class="col-12">
<q-input <q-input
v-if="!isLoad"
v-model="developmentMethod" v-model="developmentMethod"
outlined outlined
lazy-rules lazy-rules
@ -405,9 +443,11 @@ onMounted(() => {
" "
:rules="[(val:string) => !!val || `${'กรุณากรอกวิธีการพัฒนา'}`,]" :rules="[(val:string) => !!val || `${'กรุณากรอกวิธีการพัฒนา'}`,]"
/> />
<q-skeleton v-else type="QInput" height="150px" />
</div> </div>
<div class="col-12"> <div class="col-12">
<q-input <q-input
v-if="!isLoad"
v-model="developmentPeriod" v-model="developmentPeriod"
outlined outlined
hide-bottom-space hide-bottom-space
@ -420,6 +460,7 @@ onMounted(() => {
" "
:rules="[(val:string) => !!val || `${'กรุณากรอกช่วงเวลาการพัฒนา'}`,]" :rules="[(val:string) => !!val || `${'กรุณากรอกช่วงเวลาการพัฒนา'}`,]"
/> />
<q-skeleton v-else type="QInput" height="150px" />
</div> </div>
<div class="col-12"> <div class="col-12">
<div class="text-weight-bold text-body2"> <div class="text-weight-bold text-body2">
@ -428,6 +469,7 @@ onMounted(() => {
</div> </div>
<div class="col-12"> <div class="col-12">
<q-input <q-input
v-if="!isLoad"
v-model="evaluatorComment" v-model="evaluatorComment"
outlined outlined
lazy-rules lazy-rules
@ -440,6 +482,7 @@ onMounted(() => {
" "
:rules="[(val:string) => !!val || `${'กรุณากรอกความเห็นของ'}`,]" :rules="[(val:string) => !!val || `${'กรุณากรอกความเห็นของ'}`,]"
/> />
<q-skeleton v-else type="QInput" height="150px" />
</div> </div>
</div> </div>
</q-card-section> </q-card-section>
@ -519,6 +562,7 @@ onMounted(() => {
<div class="col-12"> <div class="col-12">
<q-input <q-input
v-if="!isLoad"
lazy-rules lazy-rules
v-model="superiorComment" v-model="superiorComment"
outlined outlined
@ -538,6 +582,7 @@ onMounted(() => {
ref="superiorCommentRef" ref="superiorCommentRef"
:rules="[(val:string) => superiorCommentCheck !== 'false'||!!val || `${'กรุณากรอกความเห็น'}`,]" :rules="[(val:string) => superiorCommentCheck !== 'false'||!!val || `${'กรุณากรอกความเห็น'}`,]"
/> />
<q-skeleton v-else type="QInput" height="150px" />
</div> </div>
</div> </div>
</q-card-section> </q-card-section>
@ -621,6 +666,7 @@ onMounted(() => {
</div> </div>
<div class="col-12"> <div class="col-12">
<q-input <q-input
v-if="!isLoad"
lazy-rules lazy-rules
ref="additionalSuperiorCommentRef" ref="additionalSuperiorCommentRef"
v-model="additionalSuperiorComment" v-model="additionalSuperiorComment"
@ -641,6 +687,7 @@ onMounted(() => {
" "
:rules="[(val:string) => additionalSuperiorCheck !== 'false'||!!val || `${'กรุณากรอกความเห็น'}`,]" :rules="[(val:string) => additionalSuperiorCheck !== 'false'||!!val || `${'กรุณากรอกความเห็น'}`,]"
/> />
<q-skeleton v-else type="QInput" height="150px" />
</div> </div>
</div> </div>
</q-card-section> </q-card-section>

View file

@ -32,18 +32,20 @@ const isReadonly = ref<boolean>(
const documentFile = ref<any>(null); const documentFile = ref<any>(null);
const fileList = ref<ArrayFileList[]>([]); const fileList = ref<ArrayFileList[]>([]);
const isLoad = ref<boolean>(false);
async function getData() { async function getData() {
showLoader(); isLoad.value = true;
await http await http
.get(config.API.file("ไฟล์เอกสาร", "KPI", id.value)) .get(config.API.file("ไฟล์เอกสาร", "KPI", id.value))
.then((res) => { .then((res) => {
fileList.value = res.data; fileList.value = res.data;
isLoad.value = false;
}) })
.catch((e) => { .catch((e) => {
messageError($q, e); messageError($q, e);
}) })
.finally(() => { .finally(() => {
hideLoader(); isLoad.value = false;
}); });
} }
@ -190,7 +192,11 @@ onMounted(() => {
<!-- <div class="col-1 self-center" v-if="formData.documentFile"></div> --> <!-- <div class="col-1 self-center" v-if="formData.documentFile"></div> -->
</div> </div>
<div v-if="fileList.length > 0" class="col-xs-12 row"> <div v-if="isLoad" class="col-12">
<q-skeleton />
</div>
<div v-else-if="fileList.length > 0" class="col-xs-12 row">
<q-list class="full-width rounded-borders" bordered separator> <q-list class="full-width rounded-borders" bordered separator>
<q-item <q-item
clickable clickable

View file

@ -36,6 +36,8 @@ const search = ref<string>("");
const listCheckID = ref<string | null>(null); const listCheckID = ref<string | null>(null);
const listTarget = ref<any>([]); const listTarget = ref<any>([]);
const isLoad = ref<boolean>(false);
const isLoadList = ref<boolean>(false);
const formFilter = reactive<any>({ const formFilter = reactive<any>({
isAll: false, isAll: false,
keyword: "", keyword: "",
@ -91,20 +93,20 @@ function fetchListPlan() {
: store.dataProfile.nodeDnaId; : store.dataProfile.nodeDnaId;
formFilter.node = formFilter.isAll ? 0 : store.dataProfile.node; formFilter.node = formFilter.isAll ? 0 : store.dataProfile.node;
formFilter.year = formFilter?.year ? formFilter.year.toString() : ""; formFilter.year = formFilter?.year ? formFilter.year.toString() : "";
isLoadList.value = true;
showLoader();
http http
.post(config.API.kpiPlan + `/search`, formFilter) .post(config.API.kpiPlan + `/search`, formFilter)
.then((res) => { .then((res) => {
listTarget.value = res.data.result.data; listTarget.value = res.data.result.data;
maxPage.value = Math.ceil(res.data.result.total / formFilter.pageSize); maxPage.value = Math.ceil(res.data.result.total / formFilter.pageSize);
totalList.value = res.data.result.total; totalList.value = res.data.result.total;
isLoadList.value = false;
}) })
.catch((err) => { .catch((err) => {
messageError($q, err); messageError($q, err);
}) })
.finally(() => { .finally(() => {
hideLoader(); isLoadList.value = false;
}); });
} }
@ -113,7 +115,7 @@ function fetchListPlan() {
* @param id id * @param id id
*/ */
function fetchListPlanByid(id: string) { function fetchListPlanByid(id: string) {
showLoader(); isLoad.value = true;
http http
.get(config.API.kpiAchievement("planned") + `/${id}`) .get(config.API.kpiAchievement("planned") + `/${id}`)
.then((res) => { .then((res) => {
@ -138,12 +140,13 @@ function fetchListPlanByid(id: string) {
formDetail.endDate = data.endDate; formDetail.endDate = data.endDate;
listCheckID.value = data.kpiPlanId; listCheckID.value = data.kpiPlanId;
isLoad.value = false;
}) })
.catch((err) => { .catch((err) => {
messageError($q, err); messageError($q, err);
}) })
.finally(() => { .finally(() => {
hideLoader(); isLoad.value = false;
}); });
} }
@ -154,24 +157,25 @@ function fetchListRole() {
formFilter.node = formFilter.isAll ? 0 : store.dataProfile.node; formFilter.node = formFilter.isAll ? 0 : store.dataProfile.node;
formFilter.year = formFilter?.year ? formFilter.year.toString() : ""; formFilter.year = formFilter?.year ? formFilter.year.toString() : "";
formFilter.position = store.dataProfile.position; formFilter.position = store.dataProfile.position;
isLoadList.value = true;
http http
.post(config.API.kpiRole + `/search`, formFilter) .post(config.API.kpiRole + `/search`, formFilter)
.then((res) => { .then((res) => {
listTarget.value = res.data.result.data; listTarget.value = res.data.result.data;
maxPage.value = Math.ceil(res.data.result.total / formFilter.pageSize); maxPage.value = Math.ceil(res.data.result.total / formFilter.pageSize);
totalList.value = res.data.result.total; totalList.value = res.data.result.total;
isLoadList.value = false;
}) })
.catch((err) => { .catch((err) => {
messageError($q, err); messageError($q, err);
}) })
.finally(() => { .finally(() => {
hideLoader(); isLoadList.value = false;
}); });
} }
function fetchRoleByid(id: string) { function fetchRoleByid(id: string) {
showLoader(); isLoad.value = true;
http http
.get(config.API.kpiAchievement("role") + `/${id}`) .get(config.API.kpiAchievement("role") + `/${id}`)
.then((res) => { .then((res) => {
@ -193,12 +197,13 @@ function fetchRoleByid(id: string) {
formDetail.includingName = data.includingName; formDetail.includingName = data.includingName;
formDetail.including = data.including; formDetail.including = data.including;
listCheckID.value = data.kpiRoleId; listCheckID.value = data.kpiRoleId;
isLoad.value = false;
}) })
.catch((err) => { .catch((err) => {
messageError($q, err); messageError($q, err);
}) })
.finally(() => { .finally(() => {
hideLoader(); isLoad.value = false;
}); });
} }
@ -212,25 +217,25 @@ function fetchListSpecial() {
pageSize: formFilter.pageSize, pageSize: formFilter.pageSize,
page: formFilter.page, page: formFilter.page,
}; };
isLoadList.value = true;
showLoader();
http http
.post(config.API.kpiSpecial + `/search`, body) .post(config.API.kpiSpecial + `/search`, body)
.then((res) => { .then((res) => {
listTarget.value = res.data.result.data; listTarget.value = res.data.result.data;
maxPage.value = Math.ceil(res.data.result.total / formFilter.pageSize); maxPage.value = Math.ceil(res.data.result.total / formFilter.pageSize);
totalList.value = res.data.result.total; totalList.value = res.data.result.total;
isLoadList.value = false;
}) })
.catch((err) => { .catch((err) => {
messageError($q, err); messageError($q, err);
}) })
.finally(() => { .finally(() => {
hideLoader(); isLoadList.value = false;
}); });
} }
function fetchspecialByid(id: string) { function fetchspecialByid(id: string) {
showLoader(); isLoad.value = true;
http http
.get(config.API.kpiAchievement("special") + `/${id}`) .get(config.API.kpiAchievement("special") + `/${id}`)
.then((res) => { .then((res) => {
@ -252,18 +257,19 @@ function fetchspecialByid(id: string) {
formDetail.endDate = data.endDate; formDetail.endDate = data.endDate;
listCheckID.value = data.kpiSpecialId; listCheckID.value = data.kpiSpecialId;
isLoad.value = false;
}) })
.catch((err) => { .catch((err) => {
messageError($q, err); messageError($q, err);
}) })
.finally(() => { .finally(() => {
hideLoader(); isLoad.value = false;
}); });
} }
function clickList(id: string, isData: boolean = false) { function clickList(id: string, isData: boolean = false) {
if (!checkDetail.value) { if (!checkDetail.value) {
showLoader(); isLoad.value=true
const url = const url =
numpage.value === 1 numpage.value === 1
? config.API.kpiPlan ? config.API.kpiPlan
@ -301,12 +307,13 @@ function clickList(id: string, isData: boolean = false) {
formDetail.strategyId = data.strategyId; formDetail.strategyId = data.strategyId;
formDetail.strategyName = data.strategyName; formDetail.strategyName = data.strategyName;
formDetail.documentInfoEvidence = data.documentInfoEvidence; formDetail.documentInfoEvidence = data.documentInfoEvidence;
isLoad.value=false
}) })
.catch((err) => { .catch((err) => {
messageError($q, err); messageError($q, err);
}) })
.finally(() => { .finally(() => {
hideLoader(); isLoad.value=false
}); });
} }
} }
@ -595,7 +602,7 @@ const title = computed(() => {
<q-separator /> <q-separator />
<q-card-section class="q-pa-none"> <q-card-section class="q-pa-none">
<q-list separator> <q-list separator v-if="!isLoadList">
<q-item <q-item
dense dense
v-for="(item, index) in listTarget" v-for="(item, index) in listTarget"
@ -622,6 +629,25 @@ const title = computed(() => {
</q-item-section> </q-item-section>
</q-item> </q-item>
</q-list> </q-list>
<q-list v-else separator>
<q-item dense v-for="item in 2">
<q-item-section class="q-pa-none">
<div
class="row items-center"
style="min-height: 50px"
>
<div class="col-5">
<q-skeleton type="text" width="50px" />
</div>
<div class="col-7">
<q-skeleton type="text" />
</div>
</div>
</q-item-section>
</q-item>
</q-list>
<q-separator /> <q-separator />
<div <div
class="q-pa-lg flex justify-end" class="q-pa-lg flex justify-end"
@ -662,18 +688,33 @@ const title = computed(() => {
<div class="q-pa-sm q-col-gutter-lg"> <div class="q-pa-sm q-col-gutter-lg">
<div class="col-12 row" v-if="numpage !== 3"> <div class="col-12 row" v-if="numpage !== 3">
<div class="col-4 text-grey-6">หนวยงาน/วนราชการ</div> <div class="col-4 text-grey-6">หนวยงาน/วนราชการ</div>
<div class="col-8">{{ formDetail.nodeName }}</div> <div v-if="!isLoad" class="col-8">
{{ formDetail.nodeName }}
</div>
<div class="col-8" v-else>
<q-skeleton type="text" />
</div>
</div> </div>
<div class="col-12 row" v-if="numpage === 1"> <div class="col-12 row" v-if="numpage === 1">
<div class="col-4 text-grey-6">ทธศาสตร / แผน</div> <div class="col-4 text-grey-6">ทธศาสตร / แผน</div>
<div class="col-8">{{ formDetail.strategyName }}</div> <div v-if="!isLoad" class="col-8">
{{ formDetail.strategyName }}
</div>
<div class="col-8" v-else>
<q-skeleton type="text" />
</div>
</div> </div>
<div class="col-12 row"> <div class="col-12 row">
<div class="col-4 text-grey-6">ลำด/รหสตวช</div> <div class="col-4 text-grey-6">ลำด/รหสตวช</div>
<div class="col-8"> <div class="col-8">
<q-skeleton
v-if="isLoad"
type="QInput"
height="40px"
/>
<q-input <q-input
v-if="numpage === 3" v-else-if="numpage === 3"
outlined outlined
:readonly="checkDetail" :readonly="checkDetail"
v-model="formDetail.including" v-model="formDetail.including"
@ -694,8 +735,13 @@ const title = computed(() => {
<div class="col-12 row"> <div class="col-12 row">
<div class="col-4 text-grey-6">อตวช</div> <div class="col-4 text-grey-6">อตวช</div>
<div class="col-8"> <div class="col-8">
<q-skeleton
v-if="isLoad"
type="QInput"
height="40px"
/>
<q-input <q-input
v-if="numpage === 3" v-else-if="numpage === 3"
outlined outlined
:readonly="checkDetail" :readonly="checkDetail"
v-model="formDetail.includingName" v-model="formDetail.includingName"
@ -715,6 +761,7 @@ const title = computed(() => {
<div class="col-4 text-grey-6">าเปาหมาย</div> <div class="col-4 text-grey-6">าเปาหมาย</div>
<div class="col-8"> <div class="col-8">
<q-input <q-input
v-if="!isLoad"
outlined outlined
v-model="formDetail.target" v-model="formDetail.target"
bg-color="white" bg-color="white"
@ -727,12 +774,14 @@ const title = computed(() => {
hide-bottom-space hide-bottom-space
lazy-rules lazy-rules
/> />
<q-skeleton v-else type="QInput" height="40px" />
</div> </div>
</div> </div>
<div class="col-12 row"> <div class="col-12 row">
<div class="col-4 text-grey-6">หนวยน</div> <div class="col-4 text-grey-6">หนวยน</div>
<div class="col-8"> <div class="col-8">
<q-input <q-input
v-if="!isLoad"
outlined outlined
v-model="formDetail.unit" v-model="formDetail.unit"
bg-color="white" bg-color="white"
@ -746,12 +795,14 @@ const title = computed(() => {
hide-bottom-space hide-bottom-space
reverse-fill-mask reverse-fill-mask
/> />
<q-skeleton v-else type="QInput" height="40px" />
</div> </div>
</div> </div>
<div class="col-12 row"> <div class="col-12 row">
<div class="col-4 text-grey-6">ำหน (อยละ)</div> <div class="col-4 text-grey-6">ำหน (อยละ)</div>
<div class="col-8"> <div class="col-8">
<q-input <q-input
v-if="!isLoad"
outlined outlined
v-model="formDetail.weight" v-model="formDetail.weight"
bg-color="white" bg-color="white"
@ -766,6 +817,7 @@ const title = computed(() => {
lazy-rules lazy-rules
mask="###" mask="###"
/> />
<q-skeleton v-else type="QInput" height="40px" />
</div> </div>
</div> </div>
</div> </div>
@ -784,6 +836,7 @@ const title = computed(() => {
<div class="col-6 text-center text-body2">5</div> <div class="col-6 text-center text-body2">5</div>
<div class="col-6"> <div class="col-6">
<q-input <q-input
v-if="!isLoad"
v-model="formDetail.achievement5" v-model="formDetail.achievement5"
outlined outlined
dense dense
@ -793,6 +846,7 @@ const title = computed(() => {
class="inputgreen" class="inputgreen"
lazy-rules lazy-rules
/> />
<q-skeleton v-else type="QInput" height="40px" />
</div> </div>
</div> </div>
<q-separator /> <q-separator />
@ -800,6 +854,7 @@ const title = computed(() => {
<div class="col-6 text-center text-body2">4</div> <div class="col-6 text-center text-body2">4</div>
<div class="col-6 text-center text-primary"> <div class="col-6 text-center text-primary">
<q-input <q-input
v-if="!isLoad"
v-model="formDetail.achievement4" v-model="formDetail.achievement4"
outlined outlined
:readonly="checkDetail" :readonly="checkDetail"
@ -809,6 +864,7 @@ const title = computed(() => {
class="inputgreen" class="inputgreen"
lazy-rules lazy-rules
/> />
<q-skeleton v-else type="QInput" height="40px" />
</div> </div>
</div> </div>
<q-separator /> <q-separator />
@ -816,6 +872,7 @@ const title = computed(() => {
<div class="col-6 text-center text-body2">3</div> <div class="col-6 text-center text-body2">3</div>
<div class="col-6 text-center text-primary"> <div class="col-6 text-center text-primary">
<q-input <q-input
v-if="!isLoad"
v-model="formDetail.achievement3" v-model="formDetail.achievement3"
outlined outlined
:readonly="checkDetail" :readonly="checkDetail"
@ -825,6 +882,7 @@ const title = computed(() => {
class="inputgreen" class="inputgreen"
lazy-rules lazy-rules
/> />
<q-skeleton v-else type="QInput" height="40px" />
</div> </div>
</div> </div>
<q-separator /> <q-separator />
@ -832,6 +890,7 @@ const title = computed(() => {
<div class="col-6 text-center text-body2">2</div> <div class="col-6 text-center text-body2">2</div>
<div class="col-6 text-center text-primary"> <div class="col-6 text-center text-primary">
<q-input <q-input
v-if="!isLoad"
v-model="formDetail.achievement2" v-model="formDetail.achievement2"
outlined outlined
:readonly="checkDetail" :readonly="checkDetail"
@ -841,6 +900,7 @@ const title = computed(() => {
class="inputgreen" class="inputgreen"
lazy-rules lazy-rules
/> />
<q-skeleton v-else type="QInput" height="40px" />
</div> </div>
</div> </div>
<q-separator /> <q-separator />
@ -848,6 +908,7 @@ const title = computed(() => {
<div class="col-6 text-center text-body2">1</div> <div class="col-6 text-center text-body2">1</div>
<div class="col-6 text-center text-primary"> <div class="col-6 text-center text-primary">
<q-input <q-input
v-if="!isLoad"
v-model="formDetail.achievement1" v-model="formDetail.achievement1"
outlined outlined
:readonly="checkDetail" :readonly="checkDetail"
@ -857,12 +918,14 @@ const title = computed(() => {
class="inputgreen" class="inputgreen"
lazy-rules lazy-rules
/> />
<q-skeleton v-else type="QInput" height="40px" />
</div> </div>
</div> </div>
</q-card> </q-card>
</div> </div>
<div class="col-12"> <div class="col-12">
<q-input <q-input
v-if="!isLoad"
v-model="formDetail.meaning" v-model="formDetail.meaning"
label="นิยามหรือความหมายของตัวชี้วัด" label="นิยามหรือความหมายของตัวชี้วัด"
type="textarea" type="textarea"
@ -874,10 +937,12 @@ const title = computed(() => {
class="inputgreen" class="inputgreen"
lazy-rules lazy-rules
/> />
<q-skeleton v-else type="QInput" height="150px" />
</div> </div>
<div class="col-12"> <div class="col-12">
<q-input <q-input
v-if="!isLoad"
v-model="formDetail.formula" v-model="formDetail.formula"
label="สูตรคำนวณ" label="สูตรคำนวณ"
:readonly="checkDetail" :readonly="checkDetail"
@ -889,10 +954,12 @@ const title = computed(() => {
class="inputgreen" class="inputgreen"
lazy-rules lazy-rules
/> />
<q-skeleton v-else type="QInput" height="150px" />
</div> </div>
<div class="col-12"> <div class="col-12">
<q-input <q-input
v-if="!isLoad"
v-model="formDetail.documentInfoEvidence" v-model="formDetail.documentInfoEvidence"
label="ข้อมูลเอกสารหลักฐาน" label="ข้อมูลเอกสารหลักฐาน"
type="textarea" type="textarea"
@ -904,9 +971,11 @@ const title = computed(() => {
class="inputgreen" class="inputgreen"
lazy-rules lazy-rules
/> />
<q-skeleton v-else type="QInput" height="150px" />
</div> </div>
<div class="col-3"> <div class="col-3">
<datepicker <datepicker
v-if="!isLoad"
v-model="formDetail.startDate" v-model="formDetail.startDate"
:locale="'th'" :locale="'th'"
:readonly="checkDetail" :readonly="checkDetail"
@ -952,9 +1021,11 @@ const title = computed(() => {
</q-input> </q-input>
</template> </template>
</datepicker> </datepicker>
<q-skeleton v-else type="QInput" height="40px" />
</div> </div>
<div class="col-3"> <div class="col-3">
<datepicker <datepicker
v-if="!isLoad"
v-model="formDetail.endDate" v-model="formDetail.endDate"
:locale="'th'" :locale="'th'"
:readonly="checkDetail" :readonly="checkDetail"
@ -1000,6 +1071,7 @@ const title = computed(() => {
</q-input> </q-input>
</template> </template>
</datepicker> </datepicker>
<q-skeleton v-else type="QInput" height="40px" />
</div> </div>
</div> </div>
</div> </div>

View file

@ -13,6 +13,8 @@ import type { ListCapacity } from "@/modules/08_KPI/interface/request/index";
import DialogHeader from "@/components/DialogHeader.vue"; import DialogHeader from "@/components/DialogHeader.vue";
import SkeletonTable from '@/components/SkeletonTable.vue'
const dataListCapacityDetails = ref<ListCapacity[]>([]); const dataListCapacityDetails = ref<ListCapacity[]>([]);
const route = useRoute(); const route = useRoute();
const idParam = ref<string>(route.params.id as string); const idParam = ref<string>(route.params.id as string);
@ -195,9 +197,10 @@ function onSubmit() {
} }
} }
const isLoadCapacity = ref<boolean>(false);
/** ดึงข้อมูล สมรรถนะ */ /** ดึงข้อมูล สมรรถนะ */
function getData() { function getData() {
showLoader(); isLoadCapacity.value = true;
http http
.get(config.API.KpiCapacity + `?type=${type.value}&pageSize=100`) .get(config.API.KpiCapacity + `?type=${type.value}&pageSize=100`)
.then((res) => { .then((res) => {
@ -213,7 +216,7 @@ function getData() {
} }
}) })
.finally(() => { .finally(() => {
hideLoader(); isLoadCapacity.value = false;
}); });
} }
@ -228,7 +231,9 @@ function filterTxt(val: any) {
} }
/** ดึงข้อมูลตามไอดี */ /** ดึงข้อมูลตามไอดี */
const isLoadById = ref<boolean>(false);
function getDataById() { function getDataById() {
isLoadById.value = true;
http http
.get(config.API.kpiUserCapacity + `/${idProps.value}`) .get(config.API.kpiUserCapacity + `/${idProps.value}`)
.then((res) => { .then((res) => {
@ -252,6 +257,7 @@ function getDataById() {
formDetail.definition = target.description; formDetail.definition = target.description;
dataListCapacityDetails.value = dataListCriteria; dataListCapacityDetails.value = dataListCriteria;
isLoadById.value = false;
}) })
.catch((e) => {}) .catch((e) => {})
.finally(() => {}); .finally(() => {});
@ -262,8 +268,10 @@ watch(
() => { () => {
if (modal.value) { if (modal.value) {
type.value = competencyType.value; type.value = competencyType.value;
getData(); getData();
if (idProps.value) { if (idProps.value) {
isLoadById.value = true;
setTimeout(() => { setTimeout(() => {
getDataById(); getDataById();
}, 500); }, 500);
@ -407,18 +415,32 @@ watch(
}} }}
</div> </div>
<div class="col-8"> <div class="col-8">
<span v-if="field == 'type'">{{ <span v-if="field == 'type'">
formDetail[field] <div v-if="!isLoadById">
? store.convertCompetencyType(formDetail[field]) {{
: "-" formDetail[field]
}}</span> ? store.convertCompetencyType(
<span formDetail[field]
v-else-if="field == 'definition'" )
v-html="formDetail[field]" : "-"
></span> }}
<span v-else>{{ </div>
formDetail[field] ? formDetail[field] : "-"
}}</span> <q-skeleton v-else type="text" />
</span>
<span v-else-if="field == 'definition'">
<div
v-if="!isLoadById"
v-html="formDetail[field]"
></div>
<q-skeleton v-else type="text" />
</span>
<span v-else>
<div v-if="!isLoadById">
{{ formDetail[field] ? formDetail[field] : "-" }}
</div>
<q-skeleton v-else type="text"
/></span>
</div> </div>
</div> </div>
</div> </div>
@ -426,6 +448,7 @@ watch(
<div class="col-4 text-grey-6">ำหน (อยละ)</div> <div class="col-4 text-grey-6">ำหน (อยละ)</div>
<div class="col-8"> <div class="col-8">
<q-input <q-input
v-if="!isLoadById"
readonly readonly
v-model="weight" v-model="weight"
dense dense
@ -436,10 +459,12 @@ watch(
class="inputgreen" class="inputgreen"
mask="###" mask="###"
/> />
<q-skeleton v-else type="QInput" height="40px" />
</div> </div>
<div class="col-4 text-grey-6">ระดบทคาดหว</div> <div class="col-4 text-grey-6">ระดบทคาดหว</div>
<div class="col-8"> <div class="col-8">
<q-select <q-select
v-if="!isLoadById"
:readonly="type == 'HEAD' || type == 'GROUP'" :readonly="type == 'HEAD' || type == 'GROUP'"
v-model="expectedLevel" v-model="expectedLevel"
:options="expectedLevelOp" :options="expectedLevelOp"
@ -451,12 +476,14 @@ watch(
hide-bottom-space hide-bottom-space
class="inputgreen" class="inputgreen"
/> />
<q-skeleton v-else type="QInput" height="40px" />
</div> </div>
</div> </div>
</q-card> </q-card>
</div> </div>
<div class="col-xs-12 col-md-7"> <div class="col-xs-12 col-md-7">
<d-table <d-table
v-if="!isLoadById"
flat flat
bordered bordered
dense dense
@ -531,6 +558,7 @@ watch(
</div> </div>
</template> </template>
</d-table> </d-table>
<SkeletonTable v-else :columns="columns"/>
</div> </div>
</div> </div>
</div> </div>

View file

@ -60,7 +60,9 @@ let count = ref<number>(0);
* @param index id วข * @param index id วข
* @param data อม * @param data อม
*/ */
const isLoadDetail = ref<boolean>(false);
function clickList(index: string, data: any) { function clickList(index: string, data: any) {
isLoadDetail.value = true;
listCheck.value = index as string; listCheck.value = index as string;
formDataView.id = data.id; formDataView.id = data.id;
@ -76,13 +78,13 @@ function clickList(index: string, data: any) {
reasonCommanderHigh.value = data.reasonCommanderHigh ?? ""; reasonCommanderHigh.value = data.reasonCommanderHigh ?? "";
if (count.value >= 1) { if (count.value >= 1) {
reasonEvaluatorRef.value.reset(); reasonEvaluatorRef.value && reasonEvaluatorRef.value.reset();
reasonCommanderRef.value.reset(); reasonCommanderRef.value && reasonCommanderRef.value.reset();
reasonCommanderHighRef.value.reset(); reasonCommanderHighRef.value && reasonCommanderHighRef.value.reset();
} }
showLoader(); count.value++;
setTimeout(() => { setTimeout(() => {
hideLoader(); isLoadDetail.value = false;
}, 100); }, 100);
} }
@ -157,8 +159,9 @@ function closeAdd() {
getList(); getList();
} }
const isLoad = ref<boolean>(false);
function getList() { function getList() {
showLoader(); isLoad.value = true;
http http
.get( .get(
config.API.kpiCommentP( config.API.kpiCommentP(
@ -171,13 +174,13 @@ function getList() {
.then((res) => { .then((res) => {
const data = res.data.result; const data = res.data.result;
listTarget.value = data; listTarget.value = data;
isLoad.value = false;
}) })
.catch((e) => { .catch((e) => {
messageError($q, e); messageError($q, e);
isLoad.value = false;
}) })
.finally(() => { .finally(() => {});
hideLoader();
});
} }
/** /**
@ -288,7 +291,19 @@ watch(
<q-separator /> <q-separator />
<q-card-section class="q-pa-none"> <q-card-section class="q-pa-none">
<div v-if="listTarget.length > 0"> <q-list v-if="isLoad" separator>
<q-item dense v-for="item in 2">
<q-item-section class="q-pa-none">
<div class="row items-center" style="min-height: 50px">
<div class="col-12">
<q-skeleton type="text" />
</div>
</div>
</q-item-section>
</q-item>
</q-list>
<div v-else-if="listTarget.length > 0">
<q-list separator dense> <q-list separator dense>
<q-item <q-item
v-for="(item, index) in listTarget" v-for="(item, index) in listTarget"
@ -348,11 +363,21 @@ watch(
<div class="row q-pa-md q-col-gutter-sm"> <div class="row q-pa-md q-col-gutter-sm">
<div class="row col-12 text-weight-medium"> <div class="row col-12 text-weight-medium">
<div class="col-4 text-grey-6">วขอปญหา</div> <div class="col-4 text-grey-6">วขอปญหา</div>
<div class="col-8">{{ formDataView.topic }}</div> <div class="col-8">
<div v-if="!isLoadDetail">
{{ formDataView.topic }}
</div>
<q-skeleton v-else type="text" />
</div>
</div> </div>
<div class="row col-12 text-weight-medium"> <div class="row col-12 text-weight-medium">
<div class="col-4 text-grey-6">รายละเอยดปญหา</div> <div class="col-4 text-grey-6">รายละเอยดปญหา</div>
<div class="col-8">{{ formDataView.reason }}</div> <div class="col-8">
<div v-if="!isLoadDetail">
{{ formDataView.reason }}
</div>
<q-skeleton v-else type="text" />
</div>
</div> </div>
<div class="col-12"> <div class="col-12">
<q-separator /> <q-separator />
@ -375,6 +400,7 @@ watch(
</div> </div>
<div class="col-12"> <div class="col-12">
<q-input <q-input
v-if="!isLoadDetail"
outlined outlined
dense dense
:readonly=" :readonly="
@ -390,6 +416,7 @@ watch(
hide-bottom-space hide-bottom-space
:rules="[(val:string) => !!val || `${'กรุณากรอกความคิดเห็นของผู้ประเมิน'}`,]" :rules="[(val:string) => !!val || `${'กรุณากรอกความคิดเห็นของผู้ประเมิน'}`,]"
></q-input> ></q-input>
<q-skeleton v-else type="QInput" height="150px" />
</div> </div>
<div <div
@ -429,6 +456,7 @@ watch(
</div> </div>
<div class="col-12"> <div class="col-12">
<q-input <q-input
v-if="!isLoadDetail"
outlined outlined
dense dense
label="ความคิดเห็นของผู้บังคับบัญชาเหนือขึ้นไป" label="ความคิดเห็นของผู้บังคับบัญชาเหนือขึ้นไป"
@ -444,6 +472,7 @@ watch(
hide-bottom-space hide-bottom-space
:rules="[(val:string) => !!val || `${'กรุณากรอกความคิดเห็นของผู้บังคับบัญชาเหนือขึ้นไป'}`,]" :rules="[(val:string) => !!val || `${'กรุณากรอกความคิดเห็นของผู้บังคับบัญชาเหนือขึ้นไป'}`,]"
></q-input> ></q-input>
<q-skeleton v-else type="QInput" height="150px" />
</div> </div>
<div <div
@ -482,6 +511,7 @@ watch(
</div> </div>
<div class="col-12"> <div class="col-12">
<q-input <q-input
v-if="!isLoadDetail"
outlined outlined
dense dense
label="ความคิดเห็นของผู้บังคับบัญชาเหนือขึ้นไปอีกขั้นหนึ่ง" label="ความคิดเห็นของผู้บังคับบัญชาเหนือขึ้นไปอีกขั้นหนึ่ง"
@ -497,6 +527,7 @@ watch(
hide-bottom-space hide-bottom-space
:rules="[(val:string) => !!val || `${'กรุณากรอกความคิดเห็นของผู้บังคับบัญชาเหนือขึ้นไปอีกขั้นหนึ่ง'}`,]" :rules="[(val:string) => !!val || `${'กรุณากรอกความคิดเห็นของผู้บังคับบัญชาเหนือขึ้นไปอีกขั้นหนึ่ง'}`,]"
></q-input> ></q-input>
<q-skeleton v-else type="QInput" height="150px" />
</div> </div>
<div <div

View file

@ -62,7 +62,10 @@ const formDataView = reactive<FormCommentByRole>({
}); });
let count = ref<number>(0); let count = ref<number>(0);
const isLoadDetail = ref<boolean>(false);
function clickList(index: string, data: any) { function clickList(index: string, data: any) {
isLoadDetail.value = true;
listCheck.value = index as string; listCheck.value = index as string;
formDataView.id = data.id; formDataView.id = data.id;
@ -80,14 +83,13 @@ function clickList(index: string, data: any) {
reasonCommanderHigh.value = data.reasonCommanderHigh ?? ""; reasonCommanderHigh.value = data.reasonCommanderHigh ?? "";
if (count.value >= 1) { if (count.value >= 1) {
reasonEvaluatorRef.value.reset(); reasonEvaluatorRef.value && reasonEvaluatorRef.value.reset();
reasonCommanderRef.value.reset(); reasonCommanderRef.value && reasonCommanderRef.value.reset();
reasonCommanderHighRef.value.reset(); reasonCommanderHighRef.value && reasonCommanderHighRef.value.reset();
} }
count.value++; count.value++;
showLoader();
setTimeout(() => { setTimeout(() => {
hideLoader(); isLoadDetail.value = false;
}, 100); }, 100);
} }
@ -147,8 +149,9 @@ function closeAdd() {
numLevel.value = ""; numLevel.value = "";
} }
const isLoad = ref<boolean>(false);
function getList() { function getList() {
showLoader(); isLoad.value = true;
http http
.get( .get(
config.API.kpiCommentP( config.API.kpiCommentP(
@ -161,13 +164,13 @@ function getList() {
.then((res) => { .then((res) => {
const data = res.data.result; const data = res.data.result;
listTarget.value = data; listTarget.value = data;
isLoad.value = false;
}) })
.catch((e) => { .catch((e) => {
messageError($q, e); messageError($q, e);
isLoad.value = false;
}) })
.finally(() => { .finally(() => {});
hideLoader();
});
} }
function onSubmitComment(role: string) { function onSubmitComment(role: string) {
@ -313,7 +316,21 @@ watch(
<q-separator /> <q-separator />
<q-card-section class="q-pa-none"> <q-card-section class="q-pa-none">
<div v-if="listTarget.length > 0"> <q-list v-if="isLoad" separator>
<q-item dense v-for="item in 2">
<q-item-section class="q-pa-none">
<div
class="row items-center"
style="min-height: 50px"
>
<div class="col-12">
<q-skeleton type="text" />
</div>
</div>
</q-item-section>
</q-item>
</q-list>
<div v-else-if="listTarget.length > 0">
<q-list separator dense> <q-list separator dense>
<q-item <q-item
v-for="(item, index) in listTarget" v-for="(item, index) in listTarget"
@ -373,7 +390,12 @@ watch(
: "หัวข้อความก้าวหน้า" : "หัวข้อความก้าวหน้า"
}} }}
</div> </div>
<div class="col-8">{{ formDataView.topic }}</div> <div class="col-8">
<div v-if="!isLoadDetail">
{{ formDataView.topic }}
</div>
<q-skeleton v-else type="text" />
</div>
</div> </div>
<div class="row col-12 text-weight-medium"> <div class="row col-12 text-weight-medium">
<div class="col-4 text-grey-6"> <div class="col-4 text-grey-6">
@ -383,18 +405,29 @@ watch(
: "รายละเอียดความก้าวหน้า" : "รายละเอียดความก้าวหน้า"
}} }}
</div> </div>
<div class="col-8">{{ formDataView.reason }}</div> <div class="col-8">
<div v-if="!isLoadDetail">{{ formDataView.reason }}</div>
<q-skeleton v-else type="text" />
</div>
</div> </div>
<div <div
class="row col-12 text-weight-medium" class="row col-12 text-weight-medium"
v-if="type !== 'capacity' && type !== 'development'" v-if="type !== 'capacity' && type !== 'development'"
> >
<div class="col-4 text-grey-6">คะแนน</div> <div class="col-4 text-grey-6">คะแนน</div>
<div class="col-8">{{ formDataView.score }}</div> <div class="col-8">
<div v-if="!isLoadDetail">{{ formDataView.score }}</div>
<q-skeleton v-else type="text" />
</div>
</div> </div>
<div class="row col-12 text-weight-medium"> <div class="row col-12 text-weight-medium">
<div class="col-4 text-grey-6">สราง</div> <div class="col-4 text-grey-6">สราง</div>
<div class="col-8">{{ formDataView.createdFullName }}</div> <div class="col-8">
<div v-if="!isLoadDetail">
{{ formDataView.createdFullName }}
</div>
<q-skeleton v-else type="text" />
</div>
</div> </div>
<div <div
@ -422,6 +455,7 @@ watch(
</div> </div>
<div class="col-12"> <div class="col-12">
<q-input <q-input
v-if="!isLoadDetail"
outlined outlined
dense dense
:readonly=" :readonly="
@ -437,6 +471,7 @@ watch(
hide-bottom-space hide-bottom-space
:rules="[(val:string) => !!val || `${'กรุณากรอกความคิดเห็นของผู้ประเมิน'}`,]" :rules="[(val:string) => !!val || `${'กรุณากรอกความคิดเห็นของผู้ประเมิน'}`,]"
></q-input> ></q-input>
<q-skeleton v-else type="QInput" height="150px" />
</div> </div>
<div <div
@ -475,6 +510,7 @@ watch(
</div> </div>
<div class="col-12"> <div class="col-12">
<q-input <q-input
v-if="!isLoadDetail"
outlined outlined
dense dense
label="ความคิดเห็นของผู้บังคับบัญชาเหนือขึ้นไป" label="ความคิดเห็นของผู้บังคับบัญชาเหนือขึ้นไป"
@ -490,6 +526,7 @@ watch(
hide-bottom-space hide-bottom-space
:rules="[(val:string) => !!val || `${'กรุณากรอกความคิดเห็นของผู้บังคับบัญชาเหนือขึ้นไป'}`,]" :rules="[(val:string) => !!val || `${'กรุณากรอกความคิดเห็นของผู้บังคับบัญชาเหนือขึ้นไป'}`,]"
></q-input> ></q-input>
<q-skeleton v-else type="QInput" height="150px" />
</div> </div>
<div <div
@ -527,6 +564,7 @@ watch(
</div> </div>
<div class="col-12"> <div class="col-12">
<q-input <q-input
v-if="!isLoadDetail"
outlined outlined
dense dense
label="ความคิดเห็นของผู้บังคับบัญชาเหนือขึ้นไปอีกขั้นหนึ่ง" label="ความคิดเห็นของผู้บังคับบัญชาเหนือขึ้นไปอีกขั้นหนึ่ง"
@ -542,6 +580,7 @@ watch(
hide-bottom-space hide-bottom-space
:rules="[(val:string) => !!val || `${'กรุณากรอกความคิดเห็นของผู้บังคับบัญชาเหนือขึ้นไปอีกขั้นหนึ่ง'}`,]" :rules="[(val:string) => !!val || `${'กรุณากรอกความคิดเห็นของผู้บังคับบัญชาเหนือขึ้นไปอีกขั้นหนึ่ง'}`,]"
></q-input> ></q-input>
<q-skeleton v-else type="QInput" height="150px" />
</div> </div>
<div <div

View file

@ -30,6 +30,8 @@ const props = defineProps({
const route = useRoute(); const route = useRoute();
const idKpi = ref<string>(route.params.id.toLocaleString()); const idKpi = ref<string>(route.params.id.toLocaleString());
const isLoadMain = defineModel<boolean>('isLoadMain',{required:true})
const isLoad = ref<boolean>(false);
const development = ref<string[]>([]); // const development = ref<string[]>([]); //
const reasonDevelopment70 = ref<string>(""); // () const reasonDevelopment70 = ref<string>(""); // ()
const reasonDevelopment20 = ref<string>(""); // (Coach/Mentor/Consulting) const reasonDevelopment20 = ref<string>(""); // (Coach/Mentor/Consulting)
@ -220,11 +222,11 @@ function onSubmit() {
selectTypeYear: formData.year ? formData.year.toString() : null, selectTypeYear: formData.year ? formData.year.toString() : null,
selectTypeId: projectName.value ? projectName.value.id : null, selectTypeId: projectName.value ? projectName.value.id : null,
}; };
showLoader(); isLoadMain.value = true
http[id.value ? "put" : "post"](url, body) http[id.value ? "put" : "post"](url, body)
.then((res) => { .then((res) => {
success($q, "บันทึกข้อมูลสำเร็จ");
close(); close();
success($q, "บันทึกข้อมูลสำเร็จ");
}) })
.catch((e) => { .catch((e) => {
messageError($q, e); messageError($q, e);
@ -305,7 +307,7 @@ watch(
() => id.value, () => id.value,
(i) => { (i) => {
if (i) { if (i) {
showLoader(); isLoad.value = true;
http http
.get(config.API.kpiAchievementDevelop + `/${id.value}`) .get(config.API.kpiAchievementDevelop + `/${id.value}`)
.then(async (res) => { .then(async (res) => {
@ -342,13 +344,14 @@ watch(
) )
? data.reasonDevelopment10 ? data.reasonDevelopment10
: ""; : "";
isLoad.value = false;
}, 500); }, 500);
}) })
.catch((e) => { .catch((e) => {
messageError($q, e); messageError($q, e);
}) })
.finally(() => { .finally(() => {
hideLoader(); isLoad.value = false;
}); });
} }
} }
@ -367,6 +370,7 @@ watch(
<div class="row q-col-gutter-sm"> <div class="row q-col-gutter-sm">
<div class="col-3"> <div class="col-3">
<q-select <q-select
v-if="!isLoad"
class="inputgreen" class="inputgreen"
outlined outlined
dense dense
@ -379,9 +383,11 @@ watch(
v-model="choice" v-model="choice"
> >
</q-select> </q-select>
<q-skeleton v-else type="QInput" height="40px" />
</div> </div>
<div class="col-3" v-if="choice == 'PROJECT'"> <div class="col-3" v-if="choice == 'PROJECT'">
<datepicker <datepicker
v-if="!isLoad"
menu-class-name="modalfix" menu-class-name="modalfix"
v-model="formData.year" v-model="formData.year"
:locale="'th'" :locale="'th'"
@ -419,9 +425,11 @@ watch(
</q-input> </q-input>
</template> </template>
</datepicker> </datepicker>
<q-skeleton v-else type="QInput" height="40px" />
</div> </div>
<div class="col-3" v-if="choice == 'PROJECT'"> <div class="col-3" v-if="choice == 'PROJECT'">
<q-select <q-select
v-if="!isLoad"
outlined outlined
dense dense
:rules="[(val:string) => !!val || `${'กรุณาเลือกโครงการ/หลักสูตรการฝึกอบรม'}`,]" :rules="[(val:string) => !!val || `${'กรุณาเลือกโครงการ/หลักสูตรการฝึกอบรม'}`,]"
@ -446,9 +454,11 @@ watch(
</q-item> </q-item>
</template> </template>
</q-select> </q-select>
<q-skeleton v-else type="QInput" height="40px" />
</div> </div>
<div class="col-12"> <div class="col-12">
<q-input <q-input
v-if="!isLoad"
v-model="formData.name" v-model="formData.name"
outlined outlined
dense dense
@ -459,6 +469,7 @@ watch(
label="ชื่อเรื่อง/เนื้อเรื่อง/หัวข้อการพัฒนา" label="ชื่อเรื่อง/เนื้อเรื่อง/หัวข้อการพัฒนา"
> >
</q-input> </q-input>
<q-skeleton v-else type="QInput" height="40px" />
</div> </div>
<div class="col-12"> <div class="col-12">
<span class="text-weight-medium">การพฒนา</span> <span class="text-weight-medium">การพฒนา</span>
@ -469,6 +480,7 @@ watch(
>70 การลงมอปฏ (โดยผงคบบญชามอบหมาย)</span >70 การลงมอปฏ (โดยผงคบบญชามอบหมาย)</span
> >
<q-option-group <q-option-group
v-if="!isLoad"
class="check_box q-mt-sm" class="check_box q-mt-sm"
keep-color keep-color
color="primary" color="primary"
@ -477,16 +489,30 @@ watch(
:options="projectTechniquesOp1" :options="projectTechniquesOp1"
type="checkbox" type="checkbox"
/> />
<q-item
v-else
class="q-pa-none"
style="max-width: 300px; height: 30px"
v-for="item in 11"
>
<q-item-section>
<q-skeleton type="text" />
</q-item-section>
</q-item>
<div class="row q-pb-md" v-if="checkOtherBox11"> <div class="row q-pb-md" v-if="checkOtherBox11">
<div class="offset-4 col-8 q-mt-sm relative-position"> <div class="offset-4 col-8 q-mt-sm relative-position">
<div class="other_custom_input"> <div class="other_custom_input">
<q-input <q-input
v-if="!isLoad"
v-model="reasonDevelopment70" v-model="reasonDevelopment70"
dense dense
outlined outlined
class="inputgreen" class="inputgreen"
label="กรุณาระบุ" label="กรุณาระบุ"
></q-input> ></q-input>
<q-skeleton v-else type="QInput" height="40px" />
</div> </div>
</div> </div>
</div> </div>
@ -496,6 +522,7 @@ watch(
>20 การเรยนรจากผ (Coach/Mentor/Consulting)</span >20 การเรยนรจากผ (Coach/Mentor/Consulting)</span
> >
<q-option-group <q-option-group
v-if="!isLoad"
class="check_box q-mt-sm" class="check_box q-mt-sm"
keep-color keep-color
color="primary" color="primary"
@ -504,16 +531,28 @@ watch(
:options="projectTechniquesOp2" :options="projectTechniquesOp2"
type="checkbox" type="checkbox"
/> />
<q-item
v-else
class="q-pa-none"
style="max-width: 300px; height: 30px"
v-for="item in 5"
>
<q-item-section>
<q-skeleton type="text" />
</q-item-section>
</q-item>
<div class="row q-pb-md" v-if="checkOtherBox12"> <div class="row q-pb-md" v-if="checkOtherBox12">
<div class="offset-4 col-8 q-mt-sm relative-position"> <div class="offset-4 col-8 q-mt-sm relative-position">
<div class="other_custom_input"> <div class="other_custom_input">
<q-input <q-input
v-if="!isLoad"
v-model="reasonDevelopment20" v-model="reasonDevelopment20"
dense dense
outlined outlined
class="inputgreen" class="inputgreen"
label="กรุณาระบุ" label="กรุณาระบุ"
></q-input> ></q-input>
<q-skeleton v-else type="QInput" height="40px" />
</div> </div>
</div> </div>
</div> </div>
@ -521,6 +560,7 @@ watch(
<div class="col-12 col-sm-6 col-md-6 col-lg-4"> <div class="col-12 col-sm-6 col-md-6 col-lg-4">
<span class="text-weight-medium">10 การฝกอบรมอนๆ</span> <span class="text-weight-medium">10 การฝกอบรมอนๆ</span>
<q-option-group <q-option-group
v-if="!isLoad"
class="check_box q-mt-sm" class="check_box q-mt-sm"
keep-color keep-color
color="primary" color="primary"
@ -529,16 +569,28 @@ watch(
:options="projectTechniquesOp3" :options="projectTechniquesOp3"
type="checkbox" type="checkbox"
/> />
<q-item
v-else
class="q-pa-none"
style="max-width: 300px; height: 30px"
v-for="item in 7"
>
<q-item-section>
<q-skeleton type="text" />
</q-item-section>
</q-item>
<div class="row q-pb-md" v-if="checkOtherBox13"> <div class="row q-pb-md" v-if="checkOtherBox13">
<div class="offset-4 col-8 q-mt-sm relative-position"> <div class="offset-4 col-8 q-mt-sm relative-position">
<div class="other_custom_input"> <div class="other_custom_input">
<q-input <q-input
v-if="!isLoad"
v-model="reasonDevelopment10" v-model="reasonDevelopment10"
dense dense
outlined outlined
class="inputgreen" class="inputgreen"
label="กรุณาระบุ" label="กรุณาระบุ"
></q-input> ></q-input>
<q-skeleton v-else type="QInput" height="40px" />
</div> </div>
</div> </div>
</div> </div>
@ -546,6 +598,7 @@ watch(
</div> </div>
<div class="col-12"> <div class="col-12">
<q-input <q-input
v-if="!isLoad"
label="เป้าหมายการนำไปพัฒนางาน" label="เป้าหมายการนำไปพัฒนางาน"
v-model="formData.target" v-model="formData.target"
outlined outlined
@ -556,6 +609,7 @@ watch(
lazy-rules lazy-rules
hide-bottom-space hide-bottom-space
></q-input> ></q-input>
<q-skeleton v-else type="QInput" height="150px" />
</div> </div>
<div class="col-12"> <div class="col-12">
<q-card bordered> <q-card bordered>
@ -573,6 +627,7 @@ watch(
</div> </div>
<div class="col-8"> <div class="col-8">
<q-input <q-input
v-if="!isLoad"
class="inputgreen" class="inputgreen"
v-model="formData.achievement10" v-model="formData.achievement10"
outlined outlined
@ -582,6 +637,7 @@ watch(
lazy-rules lazy-rules
hide-bottom-space hide-bottom-space
></q-input> ></q-input>
<q-skeleton v-else type="QInput" height="40px" />
</div> </div>
</div> </div>
<q-separator /> <q-separator />
@ -591,6 +647,7 @@ watch(
</div> </div>
<div class="col-8"> <div class="col-8">
<q-input <q-input
v-if="!isLoad"
class="inputgreen" class="inputgreen"
v-model="formData.achievement5" v-model="formData.achievement5"
outlined outlined
@ -600,6 +657,7 @@ watch(
lazy-rules lazy-rules
hide-bottom-space hide-bottom-space
></q-input> ></q-input>
<q-skeleton v-else type="QInput" height="40px" />
</div> </div>
</div> </div>
<q-separator /> <q-separator />
@ -609,6 +667,7 @@ watch(
</div> </div>
<div class="col-8"> <div class="col-8">
<q-input <q-input
v-if="!isLoad"
class="inputgreen" class="inputgreen"
v-model="formData.achievement0" v-model="formData.achievement0"
outlined outlined
@ -618,6 +677,7 @@ watch(
lazy-rules lazy-rules
hide-bottom-space hide-bottom-space
></q-input> ></q-input>
<q-skeleton v-else type="QInput" height="40px" />
</div> </div>
</div> </div>
</q-card> </q-card>

View file

@ -10,6 +10,8 @@ import { useCounterMixin } from "@/stores/mixin";
import DialogHeader from "@/components/DialogHeader.vue"; import DialogHeader from "@/components/DialogHeader.vue";
import SkeletonTable from "@/components/SkeletonTable.vue";
const $q = useQuasar(); const $q = useQuasar();
const store = useKpiDataStore(); const store = useKpiDataStore();
const mixin = useCounterMixin(); const mixin = useCounterMixin();
@ -27,6 +29,8 @@ const modal = defineModel<boolean>("modal", { required: true });
const filterKeyword = ref<string>(""); const filterKeyword = ref<string>("");
const rows = ref<any[]>([]); const rows = ref<any[]>([]);
const isLoad = ref<boolean>(false);
const visibleColumns = ref<string[]>([ const visibleColumns = ref<string[]>([
"commandName", "commandName",
"agency", "agency",
@ -164,18 +168,19 @@ function close() {
/** ดึงข้อมูล */ /** ดึงข้อมูล */
function getData() { function getData() {
showLoader(); isLoad.value = true;
http http
.get(config.API.orgAssistance(store.dataEvaluation.profileId)) .get(config.API.orgAssistance(store.dataEvaluation.profileId))
.then((res) => { .then((res) => {
const data = res.data.result; const data = res.data.result;
rows.value = data; rows.value = data;
isLoad.value = false;
}) })
.catch((e) => { .catch((e) => {
messageError($q, e); messageError($q, e);
}) })
.finally(() => { .finally(() => {
hideLoader(); isLoad.value = false;
}); });
} }
@ -197,6 +202,7 @@ watch(
<div class="row"> <div class="row">
<div class="col-12"> <div class="col-12">
<d-table <d-table
v-if="!isLoad"
ref="table" ref="table"
:columns="columns" :columns="columns"
:rows="rows" :rows="rows"
@ -239,6 +245,7 @@ watch(
</q-tr> </q-tr>
</template> </template>
</d-table> </d-table>
<SkeletonTable v-else :columns="columns" />
</div> </div>
</div> </div>
</q-card-section> </q-card-section>

View file

@ -15,6 +15,8 @@ import DialogViewInfo from "@/modules/08_KPI/components/Tab/Dialog/DialogViewInf
import DialogProgress from "@/modules/08_KPI/components/Tab/Dialog/DialogCommentProgress.vue"; import DialogProgress from "@/modules/08_KPI/components/Tab/Dialog/DialogCommentProgress.vue";
import DialogProblem from "@/modules/08_KPI/components/Tab/Dialog/DialogCommentProblem.vue"; import DialogProblem from "@/modules/08_KPI/components/Tab/Dialog/DialogCommentProblem.vue";
import SkeletonTable from "@/components/SkeletonTable.vue";
const $q = useQuasar(); const $q = useQuasar();
const store = useKpiDataStore(); const store = useKpiDataStore();
const { dialogRemove, showLoader, hideLoader, messageError, success } = const { dialogRemove, showLoader, hideLoader, messageError, success } =
@ -25,6 +27,7 @@ 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 isLoad = defineModel<boolean>('isLoad',{required:true})
const props = defineProps({ const props = defineProps({
fetchList: { type: Function, required: true }, fetchList: { type: Function, required: true },
}); });
@ -136,7 +139,7 @@ async function onEvaluate() {
function onDelete(id: string) { function onDelete(id: string) {
dialogRemove($q, async () => { dialogRemove($q, async () => {
try { try {
showLoader(); isLoad.value = true
const url = const url =
numpage.value === 1 numpage.value === 1
? config.API.kpiAchievement("planned") + `/${id}` ? config.API.kpiAchievement("planned") + `/${id}`
@ -151,7 +154,6 @@ function onDelete(id: string) {
} catch (err) { } catch (err) {
messageError($q, err); messageError($q, err);
} finally { } finally {
hideLoader();
} }
}); });
} }
@ -241,7 +243,9 @@ const isEditStep3 = computed(() => {
</q-card-section> </q-card-section>
<q-separator /> <q-separator />
<q-card-section class="q-pa-sm"> <q-card-section class="q-pa-sm">
<d-table <d-table
v-if="!isLoad"
ref="table" ref="table"
:columns="columns" :columns="columns"
:rows="rows" :rows="rows"
@ -460,6 +464,7 @@ const isEditStep3 = computed(() => {
</div> </div>
</template> </template>
</d-table> </d-table>
<SkeletonTable v-else :columns="columns"/>
</q-card-section> </q-card-section>
</q-card> </q-card>

View file

@ -22,6 +22,8 @@ import DialogEvaluate from "@/modules/08_KPI/components/Tab/DialogEvaluate/02_Co
import DialogListCriteria from "@/modules/08_KPI/components/Tab/Dialog/DialogListCriteria.vue"; import DialogListCriteria from "@/modules/08_KPI/components/Tab/Dialog/DialogListCriteria.vue";
import DialogCompetncyByRow from "@/modules/08_KPI/components/Tab/Dialog/DialogCompetncyByRow.vue"; import DialogCompetncyByRow from "@/modules/08_KPI/components/Tab/Dialog/DialogCompetncyByRow.vue";
import SkeletonTable from "@/components/SkeletonTable.vue";
const modalLevel = ref<boolean>(false); const modalLevel = ref<boolean>(false);
const modalCompetncyByRow = ref<boolean>(false); const modalCompetncyByRow = ref<boolean>(false);
const dataCompetncyByRow = ref<any[]>([]); const dataCompetncyByRow = ref<any[]>([]);
@ -123,6 +125,7 @@ const visibleColumns = ref<string[]>(
const typeCompetency = ref<string>(""); const typeCompetency = ref<string>("");
const rows = ref<any>([]); const rows = ref<any>([]);
const isLoad = ref<any>([]);
const lists = ref<any>([]); const lists = ref<any>([]);
const modalProgress = ref<boolean>(false); const modalProgress = ref<boolean>(false);
const modalProblem = ref<boolean>(false); const modalProblem = ref<boolean>(false);
@ -161,9 +164,11 @@ function getData(type: string) {
.get(config.API.kpiUserCapacity + `?id=${id.value}&type=${type}`) .get(config.API.kpiUserCapacity + `?id=${id.value}&type=${type}`)
.then(async (res) => { .then(async (res) => {
const data = res.data.result.data; const data = res.data.result.data;
isLoad.value[type] = data ? true : false;
rows.value[type] = data; rows.value[type] = data;
lists.value = await lists.value.filter((x: any) => x.type != type); lists.value = await lists.value.filter((x: any) => x.type != type);
lists.value.push({ type: type, data }); lists.value.push({ type: type, data });
isLoad.value[type] = false;
}) })
.catch((e) => { .catch((e) => {
messageError($q, e); messageError($q, e);
@ -232,7 +237,7 @@ function onEdit(data: FormCapacityList, type: string) {
*/ */
function onDelete(id: string, type: string) { function onDelete(id: string, type: string) {
dialogRemove($q, () => { dialogRemove($q, () => {
showLoader(); isLoad.value[type] = true;
http http
.delete(config.API.kpiUserCapacity + `/${id}`) .delete(config.API.kpiUserCapacity + `/${id}`)
.then((res) => { .then((res) => {
@ -293,7 +298,12 @@ function onLevel(num: number, list: any) {
} }
watch( watch(
() => [store.dataEvaluation.posTypeName, store.dataEvaluation.posExecutiveName, store.dataEvaluation.position, store.dataEvaluation.posLevelName], // posTypeName posExecutiveName () => [
store.dataEvaluation.posTypeName,
store.dataEvaluation.posExecutiveName,
store.dataEvaluation.position,
store.dataEvaluation.posLevelName,
], // posTypeName posExecutiveName
(newValue) => { (newValue) => {
if (!newValue) return; // if (!newValue) return; //
const posTypeName = newValue[0]; const posTypeName = newValue[0];
@ -326,26 +336,25 @@ watch(
competencyType.value = competencyType.value =
position === "ผู้ตรวจราชการกรุงเทพมหานคร" || position === "ผู้ตรวจราชการ" position === "ผู้ตรวจราชการกรุงเทพมหานคร" || position === "ผู้ตรวจราชการ"
? competencyTypeList.filter( ? competencyTypeList.filter(
(x: DataOptions) => x.id === "HEAD" || x.id === "INSPECTOR" (x: DataOptions) => x.id === "HEAD" || x.id === "INSPECTOR"
) )
: posExecutiveName === "ผู้อำนวยการเขต" : posExecutiveName === "ผู้อำนวยการเขต"
? competencyTypeList.filter( ? competencyTypeList.filter(
(x: DataOptions) => x.id === "HEAD" || x.id === "DIRECTOR" (x: DataOptions) => x.id === "HEAD" || x.id === "DIRECTOR"
) )
: posTypeName === "อำนวยการ" || : posTypeName === "อำนวยการ" ||
posTypeName === "บริหาร" || posTypeName === "บริหาร" ||
(posTypeName === "ทั่วไป" && (posTypeName === "ทั่วไป" &&
posLevelName === "อาวุโส" && posLevelName === "อาวุโส" &&
posExecutiveName != null) || posExecutiveName != null) ||
(posTypeName === "วิชาการ" && (posTypeName === "วิชาการ" && posExecutiveName != null)
posExecutiveName != null) ? competencyTypeList.filter(
? competencyTypeList.filter( (x: DataOptions) => x.id === "HEAD" || x.id === "EXECUTIVE"
(x: DataOptions) => x.id === "HEAD" || x.id === "EXECUTIVE" )
) : competencyTypeList.filter(
: competencyTypeList.filter( (x: DataOptions) => x.id === "HEAD" || x.id === "GROUP"
(x: DataOptions) => x.id === "HEAD" || x.id === "GROUP" );
);
for (let index = 0; index < competencyType.value.length; index++) { for (let index = 0; index < competencyType.value.length; index++) {
const element = competencyType.value[index]; const element = competencyType.value[index];
@ -393,6 +402,7 @@ watch(
</q-card-section> </q-card-section>
<q-card-section class="q-pa-sm"> <q-card-section class="q-pa-sm">
<d-table <d-table
v-if="!isLoad[item.id]"
ref="table" ref="table"
:columns="columns" :columns="columns"
:rows="rows[item.id]" :rows="rows[item.id]"
@ -624,6 +634,7 @@ watch(
</div> </div>
</template> </template>
</d-table> </d-table>
<SkeletonTable v-else :columns="columns" />
</q-card-section> </q-card-section>
</q-card> </q-card>
</div> </div>

View file

@ -13,6 +13,8 @@ import DialogEvalutionDevelop from "@/modules/08_KPI/components/Tab/DialogEvalua
import DialogProgress from "@/modules/08_KPI/components/Tab/Dialog/DialogCommentProgress.vue"; import DialogProgress from "@/modules/08_KPI/components/Tab/Dialog/DialogCommentProgress.vue";
import DialogProblem from "@/modules/08_KPI/components/Tab/Dialog/DialogCommentProblem.vue"; import DialogProblem from "@/modules/08_KPI/components/Tab/Dialog/DialogCommentProblem.vue";
import SkeletonTable from "@/components/SkeletonTable.vue";
const store = useKpiDataStore(); const store = useKpiDataStore();
const route = useRoute(); const route = useRoute();
const evaluationId = ref<string>(route.params.id.toString()); const evaluationId = ref<string>(route.params.id.toString());
@ -38,15 +40,16 @@ const isUpdate = defineModel("isUpdate", {
default: false, default: false,
}); });
const isLoad = ref<boolean>(false);
const modalProgress = ref<boolean>(false); const modalProgress = ref<boolean>(false);
const modalProblem = ref<boolean>(false); const modalProblem = ref<boolean>(false);
const type = ref<string>(""); const type = ref<string>("");
const idList = ref<string>(""); const idList = ref<string>("");
const isEditStep1 = computed(() => { const isEditStep1 = computed(() => {
return ( return (
(store.dataEvaluation.evaluationStatus === "NEW" && store.dataEvaluation.evaluationStatus === "NEW" &&
store.rolePerson === "USER" && store.rolePerson === "USER" &&
store.tabMain === "1") store.tabMain === "1"
); );
}); });
@ -148,6 +151,7 @@ function onEdit(id: string) {
/** ดึงข้อมูลพัฒนา */ /** ดึงข้อมูลพัฒนา */
function getDevelop() { function getDevelop() {
isLoad.value = true;
http http
.get(config.API.kpiAchievementDevelop + `?id=${evaluationId.value}`) .get(config.API.kpiAchievementDevelop + `?id=${evaluationId.value}`)
.then((res) => { .then((res) => {
@ -159,6 +163,7 @@ function getDevelop() {
0 0
); );
isLoad.value = false;
store.devScoreVal = store.devScoreVal =
data.length !== 0 ? totalSummary / rows.value.length : 0; data.length !== 0 ? totalSummary / rows.value.length : 0;
}); });
@ -173,7 +178,7 @@ function onEvaluate() {
*/ */
function onDelete(id: string) { function onDelete(id: string) {
dialogRemove($q, () => { dialogRemove($q, () => {
showLoader(); isLoad.value = true;
http http
.delete(config.API.kpiAchievementDevelop + `/${id}`) .delete(config.API.kpiAchievementDevelop + `/${id}`)
.then((res) => { .then((res) => {
@ -182,10 +187,9 @@ function onDelete(id: string) {
}) })
.catch((e) => { .catch((e) => {
messageError($q, e); messageError($q, e);
isLoad.value = false;
}) })
.finally(() => { .finally(() => {});
hideLoader();
});
}); });
} }
@ -244,6 +248,7 @@ onMounted(() => {
</q-card-section> </q-card-section>
<q-card-section class="q-pa-sm"> <q-card-section class="q-pa-sm">
<d-table <d-table
v-if="!isLoad"
ref="table" ref="table"
:columns="columns" :columns="columns"
:rows="rows" :rows="rows"
@ -341,7 +346,11 @@ onMounted(() => {
dense dense
@click="openPopupProgress(props.row.id)" @click="openPopupProgress(props.row.id)"
> >
<q-tooltip>{{store.tabMain == '3' ? `บันทึกเหตุการณ์/พฤติกรรม/เหตุผล` :'บันทึกเหตุการณ์/พฤติกรรม'}}</q-tooltip> <q-tooltip>{{
store.tabMain == "3"
? `บันทึกเหตุการณ์/พฤติกรรม/เหตุผล`
: "บันทึกเหตุการณ์/พฤติกรรม"
}}</q-tooltip>
</q-btn> </q-btn>
</div> </div>
@ -498,6 +507,8 @@ onMounted(() => {
</div> </div>
</template> </template>
</d-table> </d-table>
<SkeletonTable v-else :columns="columns" />
</q-card-section> </q-card-section>
</q-card> </q-card>
@ -505,6 +516,7 @@ onMounted(() => {
v-model:modal="modalDevelop" v-model:modal="modalDevelop"
v-model:id="idEditDevelop" v-model:id="idEditDevelop"
:get-all="getDevelop" :get-all="getDevelop"
v-model:isLoadMain="isLoad"
/> />
<DialogEvalutionDevelop <DialogEvalutionDevelop

View file

@ -66,6 +66,11 @@ const commanderHighId = ref<any>(null); // ตัวแปรเก็บ id ผ
const imgProfile = ref<string>(""); // const imgProfile = ref<string>(""); //
/** ตัวแปรโหลด */
const isLoad = ref<boolean>(false);
const isLoadCommander = ref<boolean>(false);
const isLoadAvatar = ref<boolean>(false); //
const formProfile = reactive<FormProfile>({ const formProfile = reactive<FormProfile>({
fullName: "", fullName: "",
position: "", position: "",
@ -95,7 +100,10 @@ async function fetchEvaluation() {
} }
async function getAvatar(id: string) { async function getAvatar(id: string) {
isLoadAvatar.value = true;
await http await http
.get(config.API.orgCheckAvatar(id)) .get(config.API.orgCheckAvatar(id))
.then(async (res) => { .then(async (res) => {
const data = await res.data.result; const data = await res.data.result;
@ -105,6 +113,7 @@ async function getAvatar(id: string) {
}) })
.catch((e) => { .catch((e) => {
messageError($q, e); messageError($q, e);
isLoadAvatar.value = false;
}); });
} }
@ -115,6 +124,7 @@ async function fetchProfile(id: string, avatarName: string) {
.then(async (res) => { .then(async (res) => {
store.dataEvaluation.avartar = res.data.downloadUrl; store.dataEvaluation.avartar = res.data.downloadUrl;
imgProfile.value = res.data.downloadUrl; imgProfile.value = res.data.downloadUrl;
isLoadAvatar.value = false;
}); });
} }
@ -162,6 +172,7 @@ function onSubmit() {
/** ดึงข้อมูล ผู้ประเมิน */ /** ดึงข้อมูล ผู้ประเมิน */
async function getOrgOp() { async function getOrgOp() {
isLoadCommander.value = true;
http http
.get(config.API.Kpiorg) .get(config.API.Kpiorg)
.then((res) => { .then((res) => {
@ -199,9 +210,11 @@ async function getOrgOp() {
.find( .find(
(i: EvaOptionType) => i.id == store.dataEvaluation.commanderHighId (i: EvaOptionType) => i.id == store.dataEvaluation.commanderHighId
); );
isLoadCommander.value = false;
}) })
.catch((e) => { .catch((e) => {
messageError($q, e); messageError($q, e);
isLoadCommander.value = false;
}) })
.finally(() => {}); .finally(() => {});
} }
@ -453,8 +466,9 @@ const evaluator = ref<EvaluatorType>({
* อมลของผประเม * อมลของผประเม
* @param id อมลของผประเม * @param id อมลของผประเม
*/ */
const isLoadModal = ref<boolean>(false);
async function fetchProfileEvaluator(id: string) { async function fetchProfileEvaluator(id: string) {
showLoader(); isLoadModal.value = true;
http http
.get(config.API.orgPosition + `/${id}`) .get(config.API.orgPosition + `/${id}`)
.then(async (res) => { .then(async (res) => {
@ -467,12 +481,13 @@ async function fetchProfileEvaluator(id: string) {
evaluator.value.isPosmasterAct = data.isPosmasterAct; evaluator.value.isPosmasterAct = data.isPosmasterAct;
evaluator.value.posmasterAct = data.posmasterAct; evaluator.value.posmasterAct = data.posmasterAct;
evaluator.value.org = await findOrgNameHtml(data); evaluator.value.org = await findOrgNameHtml(data);
isLoadModal.value = false;
}) })
.catch((e) => { .catch((e) => {
messageError($q, e); messageError($q, e);
}) })
.finally(() => { .finally(() => {
hideLoader(); isLoadModal.value = false;
}); });
} }
@ -654,7 +669,6 @@ function onResize(size: { width: any; height: any }) {
} }
onMounted(async () => { onMounted(async () => {
showLoader();
store.isUpdate = false; store.isUpdate = false;
await getAll(); await getAll();
}); });
@ -689,7 +703,8 @@ onMounted(async () => {
<q-card bordered flat class="relative-position"> <q-card bordered flat class="relative-position">
<div class="row justify-center q-pa-md" v-if="!$q.screen.gt.xs"> <div class="row justify-center q-pa-md" v-if="!$q.screen.gt.xs">
<q-avatar :size="sizeImg"> <q-avatar :size="sizeImg">
<q-img :src="imgProfile" v-if="imgProfile !== ''" /> <q-skeleton type="circle" size="100px" v-if="isLoadAvatar" />
<q-img :src="imgProfile" v-else-if="imgProfile !== ''" />
<q-img src="@/assets/avatar_user.jpg" v-else /> <q-img src="@/assets/avatar_user.jpg" v-else />
</q-avatar> </q-avatar>
</div> </div>
@ -699,7 +714,8 @@ onMounted(async () => {
style="left: 2%; top: 50%; transform: translateY(-50%)" style="left: 2%; top: 50%; transform: translateY(-50%)"
> >
<q-avatar :size="sizeImg"> <q-avatar :size="sizeImg">
<q-img :src="imgProfile" v-if="imgProfile !== ''" /> <q-skeleton type="circle" size="100px" v-if="isLoadAvatar" />
<q-img :src="imgProfile" v-else-if="imgProfile !== ''" />
<q-img src="@/assets/avatar_user.jpg" v-else /> <q-img src="@/assets/avatar_user.jpg" v-else />
</q-avatar> </q-avatar>
</div> </div>
@ -1028,7 +1044,7 @@ onMounted(async () => {
/> />
<q-separator /> <q-separator />
<q-card-section> <q-card-section>
<div class="column q-gutter-sm"> <div v-if="!isLoadCommander" class="column q-gutter-sm">
<div class="row"> <div class="row">
<div class="col-10"> <div class="col-10">
<q-select <q-select
@ -1179,6 +1195,18 @@ onMounted(async () => {
</div> </div>
</div> </div>
</div> </div>
<div
v-else
class="row q-col-gutter-xs items-center"
v-for="item in 3"
>
<div class="col-10">
<q-skeleton type="QInput" height="40px" />
</div>
<div class="col-2 q-pa-sm text-right">
<q-skeleton type="QRadio" />
</div>
</div>
</q-card-section> </q-card-section>
<q-separator /> <q-separator />
<q-card-actions <q-card-actions
@ -1219,23 +1247,42 @@ onMounted(async () => {
<div class="col-3">ตำแหนงทางการบรหาร</div> <div class="col-3">ตำแหนงทางการบรหาร</div>
<div class="col-3">งก</div> <div class="col-3">งก</div>
</div> </div>
<div class="row"> <div class="row q-col-gutter-x-sm">
<div class="col-3"> <div class="col-3">
{{ evaluator.position ? evaluator.position : "-" }} <div v-if="!isLoadModal">
{{ evaluator.position ? evaluator.position : "-" }}
</div>
<q-skeleton v-else type="text" />
</div> </div>
<div class="col-3"> <div class="col-3">
{{ evaluator.posTypeName ? evaluator.posTypeName : "-" }} <div v-if="!isLoadModal">
{{ {{ evaluator.posTypeName ? evaluator.posTypeName : "-" }}
evaluator.posLevelName ? ` (${evaluator.posLevelName})` : "-" {{
}} evaluator.posLevelName
? ` (${evaluator.posLevelName})`
: "-"
}}
</div>
<q-skeleton v-else type="text" />
</div> </div>
<div class="col-3"> <div class="col-3">
{{ <div v-if="!isLoadModal">
evaluator.posExecutiveName ? evaluator.posExecutiveName : "-" {{
}} evaluator.posExecutiveName
? evaluator.posExecutiveName
: "-"
}}
</div>
<q-skeleton v-else type="text" />
</div> </div>
<div class="col-3 text-html"> <div class="col-3 text-html">
{{ evaluator.org ? evaluator.org : "-" }} <div v-if="!isLoadModal">
{{ evaluator.org ? evaluator.org : "-" }}
</div>
<q-skeleton v-else type="text" />
</div> </div>
</div> </div>
@ -1243,9 +1290,12 @@ onMounted(async () => {
<div class="col-12">กษาการในตำแหน/การรกษาราชการแทน</div> <div class="col-12">กษาการในตำแหน/การรกษาราชการแทน</div>
</div> </div>
<div class="row"> <div class="row">
<div v-if="isLoadModal" class="col-12">
<q-skeleton type="text" />
</div>
<div <div
class="col-12" class="col-12"
v-if="evaluator.isPosmasterAct" v-else-if="evaluator.isPosmasterAct"
v-for="(data, index) in evaluator.posmasterAct" v-for="(data, index) in evaluator.posmasterAct"
:key="index" :key="index"
> >

View file

@ -21,6 +21,7 @@ import type {
} from "@/modules/08_KPI/interface/response/index"; } from "@/modules/08_KPI/interface/response/index";
import DialogHeader from "@/components/DialogHeader.vue"; import DialogHeader from "@/components/DialogHeader.vue";
import SkeletonTable from "@/components/SkeletonTable.vue";
const $q = useQuasar(); const $q = useQuasar();
const mixin = useCounterMixin(); const mixin = useCounterMixin();
@ -30,6 +31,8 @@ const { showLoader, hideLoader, messageError, date2Thai, dialogConfirm } =
mixin; mixin;
/** Table*/ /** Table*/
const isLoadOp = ref<boolean>(false);
const isLoad = ref<boolean>(false);
const rows = ref<MainListKpi[]>([]); const rows = ref<MainListKpi[]>([]);
const visibleColumns = ref<string[]>([ const visibleColumns = ref<string[]>([
"createdAt", "createdAt",
@ -161,7 +164,7 @@ const pagination = ref({
*/ */
async function fetchRoundOption(type: string) { async function fetchRoundOption(type: string) {
const y = type === "main" ? year.value : yearDialog.value; const y = type === "main" ? year.value : yearDialog.value;
showLoader(); isLoadOp.value = true;
await http await http
.get( .get(
config.API.kpiPeriod + `?page=${1}&pageSize=${10}&keyword=${""}&year=${y}` config.API.kpiPeriod + `?page=${1}&pageSize=${10}&keyword=${""}&year=${y}`
@ -196,7 +199,7 @@ async function fetchRoundOption(type: string) {
messageError($q, err); messageError($q, err);
}) })
.finally(() => { .finally(() => {
hideLoader(); isLoadOp.value = false;
}); });
} }
@ -204,7 +207,7 @@ async function fetchRoundOption(type: string) {
* fetch รายการขอรบประเมนผลการปฏราชการระดบบคคล * fetch รายการขอรบประเมนผลการปฏราชการระดบบคคล
*/ */
async function fetchList() { async function fetchList() {
showLoader(); isLoad.value = true
let queryParams = { let queryParams = {
page: formQuery.page, page: formQuery.page,
pageSize: formQuery.pageSize, pageSize: formQuery.pageSize,
@ -222,13 +225,13 @@ async function fetchList() {
total.value = data.total; total.value = data.total;
totalList.value = Math.ceil(data.total / formQuery.pageSize); totalList.value = Math.ceil(data.total / formQuery.pageSize);
rows.value = data.data; rows.value = data.data;
isLoad.value = false
}) })
.catch((err) => { .catch((err) => {
isLoad.value = false
messageError($q, err); messageError($q, err);
}) })
.finally(() => { .finally(() => {});
hideLoader();
});
} }
/** เลือกรอบการประเมิน */ /** เลือกรอบการประเมิน */
@ -520,6 +523,7 @@ onMounted(async () => {
<div class="items-center col-12 row q-col-gutter-sm"> <div class="items-center col-12 row q-col-gutter-sm">
<div class="col-xs-12 col-md-2"> <div class="col-xs-12 col-md-2">
<q-select <q-select
v-if="!isLoadOp"
v-model="round" v-model="round"
outlined outlined
label="รอบการประเมิน" label="รอบการประเมิน"
@ -531,6 +535,7 @@ onMounted(async () => {
map-options map-options
@update:model-value="changRound" @update:model-value="changRound"
/> />
<q-skeleton v-else type="QInput" height="40px" bordered />
</div> </div>
<div class="col-xs-12 col-md-3"> <div class="col-xs-12 col-md-3">
@ -607,6 +612,7 @@ onMounted(async () => {
<div class="col-12"> <div class="col-12">
<d-table <d-table
v-if="!isLoad"
ref="table" ref="table"
:columns="columns" :columns="columns"
:rows="rows" :rows="rows"
@ -677,6 +683,7 @@ onMounted(async () => {
></q-pagination> ></q-pagination>
</template> </template>
</d-table> </d-table>
<SkeletonTable v-else :columns="columns" />
</div> </div>
</div> </div>
</q-card> </q-card>

View file

@ -93,8 +93,9 @@ const maxPage = ref<number>(1);
* งขอมลรายการขอรบประเมนผลการปฏราชการระดบบคคล * งขอมลรายการขอรบประเมนผลการปฏราชการระดบบคคล
* @param type * @param type
*/ */
const isLoadOp = ref<boolean>(false);
async function fetchRoundOption() { async function fetchRoundOption() {
showLoader(); isLoadOp.value = true;
await http await http
.get( .get(
config.API.kpiPeriod + config.API.kpiPeriod +
@ -120,18 +121,19 @@ async function fetchRoundOption() {
store.formQuery.round = roundOp.value[0].id; store.formQuery.round = roundOp.value[0].id;
await fetchList(); await fetchList();
} }
isLoadOp.value = false;
}) })
.catch((err) => { .catch((err) => {
messageError($q, err); messageError($q, err);
isLoadOp.value = false;
}) })
.finally(() => { .finally(() => {});
hideLoader();
});
} }
/** ดึงข้อมูล list */ /** ดึงข้อมูล list */
const isLoad = ref<boolean>(false)
async function fetchList() { async function fetchList() {
showLoader(); isLoad.value = true
const body = { const body = {
page: store.formQuery.page, page: store.formQuery.page,
pageSize: store.formQuery.pageSize, pageSize: store.formQuery.pageSize,
@ -158,13 +160,13 @@ async function fetchList() {
maxPage.value = Math.ceil(data.total / store.formQuery.pageSize); maxPage.value = Math.ceil(data.total / store.formQuery.pageSize);
totalList.value = data.total; totalList.value = data.total;
dataListMain.value = data.data; dataListMain.value = data.data;
isLoad.value = false
}) })
.catch((err) => { .catch((err) => {
messageError($q, err); messageError($q, err);
isLoad.value = false
}) })
.finally(() => { .finally(() => {});
hideLoader();
});
} }
/** เลือกรอบการประเมิน */ /** เลือกรอบการประเมิน */
@ -221,7 +223,7 @@ onMounted(async () => {
<div class="col-12"> <div class="col-12">
<q-card bordered class="q-pa-md"> <q-card bordered class="q-pa-md">
<div class="items-center col-12 row q-col-gutter-sm q-mb-sm"> <div class="items-center col-12 row q-gutter-sm q-mb-sm">
<datepicker <datepicker
class="col-md-1 col-xs-12" class="col-md-1 col-xs-12"
v-model="store.yearRound" v-model="store.yearRound"
@ -260,6 +262,7 @@ onMounted(async () => {
</template> </template>
</datepicker> </datepicker>
<q-select <q-select
v-if="!isLoadOp"
class="col-md-2 col-xs-12" class="col-md-2 col-xs-12"
v-model="store.formQuery.round" v-model="store.formQuery.round"
outlined outlined
@ -272,7 +275,12 @@ onMounted(async () => {
map-options map-options
@update:model-value="changRound" @update:model-value="changRound"
/> />
<q-skeleton
v-else
class="col-md-2 col-xs-12"
type="QInput"
height="40px"
/>
<q-space /> <q-space />
<q-input <q-input
@ -342,6 +350,7 @@ onMounted(async () => {
:maxPage="maxPage" :maxPage="maxPage"
:updatePagination="updatePagination" :updatePagination="updatePagination"
:fetchList="fetchList" :fetchList="fetchList"
:is-load="isLoad"
/> />
</q-tab-panel> </q-tab-panel>
@ -355,6 +364,7 @@ onMounted(async () => {
:maxPage="maxPage" :maxPage="maxPage"
:updatePagination="updatePagination" :updatePagination="updatePagination"
:fetchList="fetchList" :fetchList="fetchList"
:is-load="isLoad"
/> />
</q-tab-panel> </q-tab-panel>
@ -368,6 +378,7 @@ onMounted(async () => {
:maxPage="maxPage" :maxPage="maxPage"
:updatePagination="updatePagination" :updatePagination="updatePagination"
:fetchList="fetchList" :fetchList="fetchList"
:is-load="isLoad"
/> />
</q-tab-panel> </q-tab-panel>
@ -381,6 +392,7 @@ onMounted(async () => {
:maxPage="maxPage" :maxPage="maxPage"
:updatePagination="updatePagination" :updatePagination="updatePagination"
:fetchList="fetchList" :fetchList="fetchList"
:is-load="isLoad"
/> />
</q-tab-panel> </q-tab-panel>
@ -394,6 +406,7 @@ onMounted(async () => {
:maxPage="maxPage" :maxPage="maxPage"
:updatePagination="updatePagination" :updatePagination="updatePagination"
:fetchList="fetchList" :fetchList="fetchList"
:is-load="isLoad"
/> />
</q-tab-panel> </q-tab-panel>
</q-tab-panels> </q-tab-panels>

File diff suppressed because it is too large Load diff

View file

@ -13,6 +13,8 @@ import type {
Scholarship, Scholarship,
} from "@/modules/09_scholarship/interface/index/Main"; } from "@/modules/09_scholarship/interface/index/Main";
import SkeletonTable from "@/components/SkeletonTable.vue";
const mixin = useCounterMixin(); const mixin = useCounterMixin();
const { showLoader, hideLoader, messageError } = mixin; const { showLoader, hideLoader, messageError } = mixin;
const router = useRouter(); const router = useRouter();
@ -24,6 +26,7 @@ const currentPage = ref<number>(1);
const page = ref<number>(1); const page = ref<number>(1);
const rowsPerPage = ref<number>(10); const rowsPerPage = ref<number>(10);
const isLoad = ref<boolean>(false);
const rows = ref<Scholarship[]>([]); const rows = ref<Scholarship[]>([]);
const year = ref<number>(0); const year = ref<number>(0);
const type = ref<string>("DOMESTICE"); const type = ref<string>("DOMESTICE");
@ -127,15 +130,16 @@ async function getProfileId() {
if (dataStore.profileId) { if (dataStore.profileId) {
profilId.value = dataStore.profileId; profilId.value = dataStore.profileId;
} else { } else {
showLoader(); isLoad.value = true;
try { try {
const res = await http.get(config.API.profilePosition()); const res = await http.get(config.API.profilePosition());
dataStore.profileId = res.data.result.profileId; dataStore.profileId = res.data.result.profileId;
profilId.value = dataStore.profileId; profilId.value = dataStore.profileId;
isLoad.value = false;
} catch (e) { } catch (e) {
messageError($q, e); messageError($q, e);
} finally { } finally {
hideLoader(); isLoad.value = false;
} }
} }
@ -255,6 +259,7 @@ onMounted(async () => {
<div> <div>
<d-table <d-table
v-if="!isLoad"
flat flat
bordered bordered
dense dense
@ -339,6 +344,7 @@ onMounted(async () => {
</div> </div>
</template> </template>
</d-table> </d-table>
<SkeletonTable v-else :columns="columns" />
</div> </div>
</q-card> </q-card>
</div> </div>

View file

@ -14,6 +14,8 @@ import type {
ProbationFormType, ProbationFormType,
} from "@/modules/11_probation/interface/index/main"; } from "@/modules/11_probation/interface/index/main";
import SkeletonTable from "@/components/SkeletonTable.vue";
const $q = useQuasar(); const $q = useQuasar();
const mixin = useCounterMixin(); const mixin = useCounterMixin();
const { const {
@ -29,6 +31,7 @@ const profileId = ref<string>("");
const rows = ref<ListMain[]>([]); const rows = ref<ListMain[]>([]);
const rowsData = ref<ListMain[]>([]); const rowsData = ref<ListMain[]>([]);
const isLoad = ref<boolean>(false);
const mode = ref<boolean>($q.screen.gt.xs); const mode = ref<boolean>($q.screen.gt.xs);
const profileImg = ref<string>(""); const profileImg = ref<string>("");
const router = useRouter(); const router = useRouter();
@ -112,7 +115,7 @@ function onResize(size: any) {
} }
function getMain() { function getMain() {
showLoader(); isLoad.value = true;
http http
.get(config.API.kpiEvaluation + `/${route.params.id.toString()}`) .get(config.API.kpiEvaluation + `/${route.params.id.toString()}`)
// .get(config.API.profilePosition()) // .get(config.API.profilePosition())
@ -134,11 +137,11 @@ function getMain() {
promises.push(getAvatar(data.profileId)); promises.push(getAvatar(data.profileId));
await Promise.all(promises); await Promise.all(promises);
hideLoader(); isLoad.value = false;
}) })
.catch((e) => { .catch((e) => {
messageError($q, e); messageError($q, e);
hideLoader(); isLoad.value = false;
}) })
.finally(() => {}); .finally(() => {});
} }
@ -221,22 +224,31 @@ onMounted(async () => {
<div v-if="$q.screen.gt.xs" class="col-12"> <div v-if="$q.screen.gt.xs" class="col-12">
<q-card> <q-card>
<div class="bg-grey-1 row q-pa-sm items-center"> <div class="bg-grey-1 row q-pa-sm items-center">
<span class="text-teal text-weight-bold text-body2">{{ <span class="text-teal text-weight-bold text-body2">
formData.firstName <div v-if="!isLoad">
? `${formData.prefix}${formData.firstName} ${formData.lastName}` {{
: "-" formData.firstName
}}</span> ? `${formData.prefix}${formData.firstName} ${formData.lastName}`
: "-"
}}
</div>
<q-skeleton v-else type="text" />
</span>
</div> </div>
<q-resize-observer @resize="onResize" /> <q-resize-observer @resize="onResize" />
<q-card-section class="q-pa-md"> <q-card-section class="q-pa-md">
<div class="row"> <div class="row">
<div class="col-2 text-center self-center"> <div
<q-avatar :size="sizeImg" rounded> class="col-2 text-center self-center"
style="display: flex; justify-content: center"
>
<q-avatar v-if="!isLoad" :size="sizeImg" rounded>
<q-img <q-img
:src="profileImg" :src="profileImg"
style="border-radius: 10px; object-fit: cover" style="border-radius: 10px; object-fit: cover"
/> />
</q-avatar> </q-avatar>
<q-skeleton v-else type="QRadio" size="70px" />
</div> </div>
<div class="col-10 column justify-center no-wrap"> <div class="col-10 column justify-center no-wrap">
<div class="row text-grey-6"> <div class="row text-grey-6">
@ -247,7 +259,10 @@ onMounted(async () => {
<div class="row"> <div class="row">
<div class="col-4 column"> <div class="col-4 column">
<span> <span>
{{ formData.position ? formData.position : "-" }} <div v-if="!isLoad">
{{ formData.position ? formData.position : "-" }}
</div>
<q-skeleton v-else type="text" width="90px" />
</span> </span>
<span> <span>
{{ {{
@ -258,16 +273,22 @@ onMounted(async () => {
</span> </span>
</div> </div>
<div class="col-4"> <div class="col-4">
{{ <div v-if="!isLoad">
formData.posTypeName {{
? formData.posLevelName formData.posTypeName
? `${formData.posTypeName}(${formData.posLevelName})` ? formData.posLevelName
: formData.posTypeName ? `${formData.posTypeName}(${formData.posLevelName})`
: "-" : formData.posTypeName
}} : "-"
}}
</div>
<q-skeleton v-else type="text" width="90px" />
</div> </div>
<div class="col-4"> <div class="col-4">
{{ formData.org ? formData.org : "-" }} <div v-if="!isLoad">
{{ formData.org ? formData.org : "-" }}
</div>
<q-skeleton v-else type="text" width="90px" />
</div> </div>
</div> </div>
</div> </div>
@ -278,21 +299,27 @@ onMounted(async () => {
<div v-else class="col-12"> <div v-else class="col-12">
<q-card bordered> <q-card bordered>
<div class="bg-grey-1 row q-pa-sm items-center"> <div class="bg-grey-1 row q-pa-sm items-center">
<span class="text-teal text-weight-bold text-body2">{{ <span class="text-teal text-weight-bold text-body2">
formData.firstName <div v-if="!isLoad">
? `${formData.prefix}${formData.firstName} ${formData.lastName}` {{
: "-" formData.firstName
}}</span> ? `${formData.prefix}${formData.firstName} ${formData.lastName}`
: "-"
}}
</div>
<q-skeleton v-else type="text" />
</span>
</div> </div>
<q-resize-observer @resize="onResize" /> <q-resize-observer @resize="onResize" />
<q-card-section> <q-card-section>
<div class="text-center q-mt-md"> <div class="text-center q-mt-md" style="display: flex;justify-content: center;">
<q-avatar :size="sizeImg" rounded> <q-avatar v-if="!isLoad" :size="sizeImg" rounded>
<img <img
:src="profileImg" :src="profileImg"
style="border-radius: 10px; object-fit: cover" style="border-radius: 10px; object-fit: cover"
/> />
</q-avatar> </q-avatar>
<q-skeleton v-else type="QRadio" size="70px" />
</div> </div>
</q-card-section> </q-card-section>
@ -302,25 +329,34 @@ onMounted(async () => {
<q-item-label class="text-grey-6" <q-item-label class="text-grey-6"
>ตำแหนงในสายงาน</q-item-label >ตำแหนงในสายงาน</q-item-label
> >
<q-item-label>{{ <q-item-label>
formData.position ? formData.position : "-" <div v-if="!isLoad">
}}</q-item-label> {{ formData.position ? formData.position : "-" }}
</div>
<q-skeleton v-else type="text" />
</q-item-label>
</q-item-section> </q-item-section>
</q-item> </q-item>
<q-item> <q-item>
<q-item-section> <q-item-section>
<q-item-label class="text-grey-6">ระด</q-item-label> <q-item-label class="text-grey-6">ระด</q-item-label>
<q-item-label>{{ <q-item-label>
formData.posLevelName ? formData.posLevelName : "-" <div v-if="!isLoad">
}}</q-item-label> {{ formData.posLevelName ? formData.posLevelName : "-" }}
</div>
<q-skeleton v-else type="text" />
</q-item-label>
</q-item-section> </q-item-section>
</q-item> </q-item>
<q-item> <q-item>
<q-item-section> <q-item-section>
<q-item-label class="text-grey-6">งก</q-item-label> <q-item-label class="text-grey-6">งก</q-item-label>
<q-item-label>{{ <q-item-label>
formData.org ? formData.org : "-" <div v-if="!isLoad">
}}</q-item-label> {{ formData.org ? formData.org : "-" }}
</div>
<q-skeleton v-else type="text" />
</q-item-label>
</q-item-section> </q-item-section>
</q-item> </q-item>
</q-list> </q-list>
@ -361,6 +397,7 @@ onMounted(async () => {
</div> </div>
<div class="q-mt-sm"> <div class="q-mt-sm">
<d-table <d-table
v-if="!isLoad"
flat flat
dense dense
bordered bordered
@ -442,6 +479,7 @@ onMounted(async () => {
</div> </div>
</template> </template>
</d-table> </d-table>
<SkeletonTable v-else :columns="columns" />
</div> </div>
</q-card> </q-card>
</div> </div>