update selected and load data
This commit is contained in:
parent
263e122b60
commit
bebf684069
2 changed files with 157 additions and 53 deletions
|
|
@ -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();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue