update selected and load data

This commit is contained in:
Warunee Tamkoo 2026-03-25 17:48:24 +07:00
parent 263e122b60
commit bebf684069
2 changed files with 157 additions and 53 deletions

View file

@ -125,7 +125,7 @@ export const useChangeRoundDataStore = defineStore(
async function fetchDataForCardId(dataDetail: any, type?: string) {
if (dataDetail) {
showLoader();
// showLoader();
const url =
type && type == "emp"
? config.API.leaveSearchEMP()
@ -170,7 +170,7 @@ export const useChangeRoundDataStore = defineStore(
console.log(e);
})
.finally(() => {
hideLoader();
// hideLoader();
});
}
}

View file

@ -1,5 +1,5 @@
<script setup lang="ts">
import { ref, watch, reactive, onMounted } from "vue";
import { ref, watch, reactive, onMounted, nextTick } from "vue";
import { useQuasar } from "quasar";
import http from "@/plugins/http";
@ -18,13 +18,7 @@ import Dialogform from "@/modules/09_leave/components/03_ChangeRound/DialogForm.
const route = useRoute();
const mixin = useCounterMixin();
const {
showLoader,
hideLoader,
success,
messageError,
dialogConfirm,
} = mixin;
const { showLoader, hideLoader, success, messageError, dialogConfirm } = mixin;
const dataStore = useChangeRoundDataStore();
const { fetchStructureTree } = useStructureTree();
@ -48,7 +42,7 @@ const formData = reactive<DataPost>({
const pagination = ref({
page: 1,
rowsPerPage: formData.pageSize,
rowsPerPage: 0,
});
/** โครงสร้างข้อมูลต้นไม้ขององค์กร **/
@ -59,6 +53,19 @@ const filter = ref<string>("");
const selected = ref<any[]>([]);
const isMultiple = ref<boolean>(false);
/** client-side data & batch loading **/
const allRows = ref<any[]>([]);
const isLoadingAll = ref<boolean>(false);
const loadAllProgress = ref<number>(0);
const totalToLoad = ref<number | null>(null);
const BATCH_SIZE = 250;
function waitForUi() {
return new Promise((resolve) => {
setTimeout(resolve, 0);
});
}
/** function fetch ข้อมูลของ Tree*/
async function fetchDataTree() {
nodeTree.value = await fetchStructureTree(route.meta.Key as string, true);
@ -135,27 +142,75 @@ function save() {
});
}
/**
* function updatePagination
* @param newPagination อม Pagination ใหม
*/
function updatePagination(newPagination: any) {
formData.pageSize =
newPagination.rowsPerPage === 0 ? 3000 : newPagination.rowsPerPage;
/** Function โหลดข้อมูลทั้งหมดแบบ batch แล้วให้ QTable ทำ pagination เอง */
async function fetchAllData() {
isLoadingAll.value = true;
allRows.value = [];
loadAllProgress.value = 0;
totalToLoad.value = null;
selected.value = [];
// UI API
await nextTick();
await waitForUi();
try {
await dataStore.fetchDataForCardId({
...formData,
page: 1,
pageSize: BATCH_SIZE,
});
allRows.value = dataStore.rows.slice();
const total = dataStore.totalListMain;
totalToLoad.value = total;
const totalPages = Math.ceil(total / BATCH_SIZE);
loadAllProgress.value =
totalPages <= 1 ? 100 : Math.round(100 / totalPages);
await nextTick();
for (let page = 2; page <= totalPages; page++) {
await dataStore.fetchDataForCardId({
...formData,
page,
pageSize: BATCH_SIZE,
});
allRows.value.push(...dataStore.rows);
loadAllProgress.value = Math.round((page / totalPages) * 100);
await nextTick();
await waitForUi();
}
} finally {
isLoadingAll.value = false;
totalToLoad.value = null;
}
}
/** Function ค้นหาข้อมูล */
async function searchData() {
await dataStore.fetchDataForCardId(formData);
await fetchAllData();
}
function submitSearchByEnter() {
if (isLoadingAll.value) return;
if (!checkPermission(route)?.attrIsGet) return;
formData.page = 1;
searchData();
}
/** Function เลือกทั้งหมด */
function selectAllRows() {
selected.value = [...allRows.value];
}
function onSelectedOrgTree(data: any) {
if (isLoadingAll.value) return;
selected.value = [];
allRows.value = [];
orgTreeId.value = data.orgTreeId;
formData.selectedNodeId = data.orgTreeDnaId;
formData.selectedNode = data.orgLevel;
formData.page = 1;
searchData();
}
function handleSelectMultiple() {
@ -171,14 +226,14 @@ function resetSelected() {
watch(
() => formData.pageSize,
() => {
formData.page = 1;
searchData();
// pageSize QTable (client-side) fetch API
}
);
onMounted(() => {
fetchDataTree();
dataStore.rows = [];
allRows.value = [];
});
</script>
<template>
@ -238,7 +293,6 @@ onMounted(() => {
<q-card-section
class="col-lg-9 col-md-8 col-xs-12 q-gutter-sm scroll"
style="height: 80vh"
v-if="orgTreeId"
>
<div class="row col-xs-12 col-sm-9">
<q-card flat bordered class="bg-grey-2 col-12 bg-white q-pa-lg">
@ -247,7 +301,7 @@ onMounted(() => {
</div>
<div class="row justify-between q-gutter-y-sm">
<q-input
:readonly="!checkPermission($route)?.attrIsGet"
:readonly="!checkPermission($route)?.attrIsGet || isLoadingAll"
v-model="formData.cardId"
outlined
label="เลขประจำตัวประชาชน"
@ -255,28 +309,32 @@ onMounted(() => {
dense
hide-bottom-space
maxlength="13"
@keyup.enter="submitSearchByEnter"
/>
<q-input
:readonly="!checkPermission($route)?.attrIsGet"
:readonly="!checkPermission($route)?.attrIsGet || isLoadingAll"
v-model="formData.firstName"
outlined
label="ชื่อ"
class="col-5 col-md-3 bg-white inputgreen"
dense
hide-bottom-space
@keyup.enter="submitSearchByEnter"
/>
<q-input
:readonly="!checkPermission($route)?.attrIsGet"
:readonly="!checkPermission($route)?.attrIsGet || isLoadingAll"
v-model="formData.lastName"
outlined
label="นามสกุล"
class="col-6 col-md-3 bg-white inputgreen"
dense
hide-bottom-space
@keyup.enter="submitSearchByEnter"
/>
<q-btn
v-if="checkPermission($route)?.attrIsGet"
@click="(formData.page = 1), searchData()"
:disable="isLoadingAll"
for="#search"
dense
unelevated
@ -289,7 +347,11 @@ onMounted(() => {
</q-card>
</div>
<div
v-if="dataStore.rows.length === 0 && dataStore.checkCilck === true"
v-if="
allRows.length === 0 &&
dataStore.checkCilck === true &&
!isLoadingAll
"
>
<q-card
flat
@ -298,30 +360,81 @@ onMounted(() => {
>ไมพบขอม</q-card
>
</div>
<div v-if="dataStore.rows.length !== 0" class="col-12">
<div v-if="allRows.length !== 0 || isLoadingAll" class="col-12">
<q-banner
v-if="isLoadingAll"
rounded
class="bg-blue-1 text-primary q-mb-sm"
>
<div class="row items-center q-gutter-sm">
<q-spinner color="primary" size="22px" />
<div v-if="totalToLoad === null || totalToLoad <= 500">
กำลงคนหาขอม กรณารอสกคร
</div>
<div v-else>
กำลงโหลดขอมลจำนวนมาก กรณารอสกคร
<div class="text-caption text-grey-7">
ระบบกำลงดงขอมลทงหมด
{{ totalToLoad.toLocaleString() }} รายการ
</div>
</div>
</div>
</q-banner>
<q-linear-progress
v-if="isLoadingAll && totalToLoad === null"
indeterminate
color="primary"
class="q-mb-xs"
/>
<q-linear-progress
v-if="isLoadingAll && totalToLoad !== null"
:value="loadAllProgress / 100"
color="primary"
class="q-mb-xs"
/>
<div
v-if="isLoadingAll && totalToLoad !== null"
class="text-caption text-grey-6 q-mb-xs"
>
กำลงโหลด... {{ allRows.length.toLocaleString() }} /
{{ totalToLoad.toLocaleString() }} รายการ
</div>
<div class="row justify-between items-center q-mb-sm">
<q-btn
:disable="selected.length === 0"
:color="selected.length === 0 ? 'grey' : 'info'"
dense
icon="mdi-shuffle-variant"
label="เปลี่ยนรอบการลงเวลา"
@click="handleSelectMultiple()"
/>
<div class="row q-gutter-sm">
<!-- <q-btn
color="secondary"
dense
icon="mdi-checkbox-multiple-marked-outline"
label="เลือกทั้งหมด"
:disable="isLoadingAll || allRows.length === 0"
@click="selectAllRows()"
/> -->
<q-btn
:disable="selected.length === 0 || isLoadingAll"
:color="selected.length === 0 ? 'grey' : 'info'"
dense
icon="mdi-shuffle-variant"
:label="`เปลี่ยนรอบการลงเวลา${
selected.length > 0 ? ` (${selected.length})` : ''
}`"
@click="handleSelectMultiple()"
/>
</div>
</div>
<d-table
ref="table"
:columns="dataStore.columns"
:rows="dataStore.rows"
:rows="allRows"
row-key="profileId"
flat
bordered
dense
virtual-scroll
table-style="max-height: 58vh"
class="custom-header-table"
:visible-columns="dataStore.visibleColumns"
:rows-per-page-options="[10, 25, 50, 100]"
@update:pagination="updatePagination"
hide-pagination
v-model:pagination="pagination"
selection="multiple"
v-model:selected="selected"
@ -333,6 +446,7 @@ onMounted(() => {
keep-color
color="primary"
dense
:disable="isLoadingAll"
v-model="props.selected"
/>
</q-th>
@ -354,6 +468,7 @@ onMounted(() => {
keep-color
color="primary"
dense
:disable="isLoadingAll"
v-model="props.selected"
/>
</q-td>
@ -429,21 +544,10 @@ onMounted(() => {
</q-td>
</q-tr>
</template>
<template v-slot:pagination="scope">
งหมด {{ dataStore.totalListMain }} รายการ
<q-pagination
v-model="formData.page"
active-color="primary"
color="dark"
:max="Number(dataStore.maxPageMain)"
size="sm"
boundary-links
direction-links
:max-pages="5"
@update:model-value="dataStore.fetchDataForCardId(formData)"
></q-pagination>
</template>
</d-table>
<div class="text-caption text-grey-7 q-mt-sm">
งหมด {{ allRows.length }} รายการ
</div>
</div>
</q-card-section>
</q-card-section>