Merge branch 'develop' into dev
All checks were successful
Build & Deploy on Dev / build (push) Successful in 2m32s

* develop:
  แก้ชื่อรายงานลงเวลาและการลาให้ถูกต้อง (แก้ id รายงานเป็น number) และลบไฟล์ที่ไม่ได้ใช้แล้วทิ้ง
  style(registry-temp):display columns isPosition
  style(placement):layout
  style(transfer):responsive
  fix(retire-old):resetFilter
  fix(leave) : max-date บันทึกวันลาย้อนหลัง
  style(registry): gov => position add q-ml-md
  fix(development): path API profile/development
  fix(retire-old): resetfilter year-1
  fix(development):sort
  feat(retirement): add Page retire-old
  fix(KPI):sort
  fix bug registry retire
  fix(rerirement): ปีงบ
  fix(salary):sort
  fix(registry-retire-employee): load list
  fix(leavea): delete readonly
  fix:TestTimes
  fix:add function calculateFiscalYear
This commit is contained in:
Warunee Tamkoo 2025-10-08 11:47:41 +07:00
commit 9d71f85a9e
86 changed files with 2357 additions and 3613 deletions

View file

@ -108,4 +108,6 @@ export default {
// แก้ไขข้อมูลการลาออก
updateResign: (path: string, id: string) =>
`${retirement}/${path}/admin-update/resign-info/${id}`,
exRetirement: `${env.API_URI}/org/ex/retirement`,
};

View file

@ -57,6 +57,8 @@ export default {
`${developmentOrg}/profile/development/registry/OFFICER/${id}`,
developmentIDP: (id: string) => `${development}/main/registry/OFFICER/${id}`,
devStrategySort:`${devStrategy}/sort`,
developmentScholarshipReport
devStrategySort: `${devStrategy}/sort`,
developmentScholarshipReport,
developmentProfile: `${developmentOrg}/profile/development`,
};

View file

@ -394,6 +394,7 @@
</template>
</HistoryTable>
</template>
<script setup lang="ts">
import { onMounted, ref, watch } from "vue";
import { useRoute } from "vue-router";
@ -412,6 +413,7 @@ import HistoryTable from "@/components/TableHistory.vue";
import http from "@/plugins/http";
import config from "@/app.config";
import type { QTableProps } from "quasar";
import { calculateFiscalYear } from "@/utils/function";
const props = defineProps({
statusEdit: {
@ -430,7 +432,7 @@ const route = useRoute();
const id = ref<string>("");
const name = ref<string>();
const topic = ref<string>();
const yearly = ref<number>(new Date().getFullYear());
const yearly = ref<number>(calculateFiscalYear(new Date()));
const place = ref<string>();
const duration = ref<string>();
const department = ref<string>();
@ -1017,7 +1019,7 @@ const addData = () => {
edit.value = true;
name.value = "";
topic.value = "";
yearly.value = new Date().getFullYear();
yearly.value = calculateFiscalYear(new Date());
place.value = "";
duration.value = "";
department.value = "";

View file

@ -7,7 +7,7 @@ export function usePagination(
) {
const pagination = ref<PropsTable.Pagination>({
sortBy: defaultSort,
descending: true,
descending: false,
page: 1,
rowsPerPage: 10,
rowsNumber: 0,

View file

@ -7,6 +7,7 @@ import config from "@/app.config";
import { useCounterMixin } from "@/stores/mixin";
import { useStructureTree } from "@/stores/structureTree";
import { calculateFiscalYear } from "@/utils/function";
import type { DataStructureTree } from "@/interface/main";
import type { FormDataRole } from "@/modules/01_masterdata/interface/request/Main";
@ -47,7 +48,7 @@ const isView = ref<boolean>(route.name === "KPIIndicatorByRoleView");
const modalDialogSelect = ref<boolean>(false);
const form = reactive<FormDataRole>({
position: "", //
year: new Date().getFullYear(), //
year: calculateFiscalYear(new Date()), //
round: "", //
org: "", ///
including: "", //

View file

@ -8,6 +8,7 @@ import { useRouter } from "vue-router";
import { useCounterMixin } from "@/stores/mixin";
import { checkPermission } from "@/utils/permissions";
import { usePagination } from "@/composables/usePagination";
import { calculateFiscalYear } from "@/utils/function";
/** importType*/
import type {
@ -63,7 +64,7 @@ const rows = ref<DataAssignment[]>([]);
const formFilter = reactive<FormFilterAssignment>({
keyword: "",
period: "",
year: new Date().getFullYear(),
year: calculateFiscalYear(new Date()),
});
/** ฟังก์ชันดึงข้อมูลรายการงานอื่นๆ ที่ได้รับมอบหมาย*/

View file

@ -9,6 +9,7 @@ import { useCounterMixin } from "@/stores/mixin";
import { checkPermission } from "@/utils/permissions";
import { useStructureTree } from "@/stores/structureTree";
import { usePagination } from "@/composables/usePagination";
import { calculateFiscalYear } from "@/utils/function";
import type {
DataOption,
@ -70,7 +71,7 @@ const roundOp = ref<DataOption[]>([
{ id: "OCT", name: "รอบตุลาคม" },
]);
const year = ref<number | null>(new Date().getFullYear());
const year = ref<number | null>(calculateFiscalYear(new Date()));
const nodeData = reactive<FormDataNodeData>({
round: "",
nodeId: null,

View file

@ -8,6 +8,7 @@ import config from "@/app.config";
import { useCounterMixin } from "@/stores/mixin";
import { checkPermission } from "@/utils/permissions";
import { usePagination } from "@/composables/usePagination";
import { calculateFiscalYear } from "@/utils/function";
import type { FormListMainByRole } from "@/modules/01_masterdata/interface/request/Main";
import type {
@ -65,7 +66,7 @@ const formFilter = reactive<FormListMainByRole>({
position: "",
round: "",
keyword: "",
year: new Date().getFullYear(),
year: calculateFiscalYear(new Date()),
});
const indicatorTotal = ref<IndicatorTotal[]>([

View file

@ -1,6 +1,6 @@
import { ref } from "vue";
interface Pagination {
page: number;
page?: number;
rowsPerPage: number;
sortBy?: string;
}

View file

@ -8,6 +8,7 @@ import http from "@/plugins/http";
import config from "@/app.config";
import { checkPermission } from "@/utils/permissions";
import { useCounterMixin } from "@/stores/mixin";
import { calculateFiscalYear } from "@/utils/function";
import type { DataOption } from "@/modules/09_leave/interface/index/Main";
@ -21,7 +22,7 @@ const { showLoader, hideLoader, messageError } = mixin;
const isLoadPDF = ref<boolean>(false);
const year = ref<number>(new Date().getFullYear());
const year = ref<number>(calculateFiscalYear(new Date()));
const reportSelect = ref<DataOption>({
id: "",
@ -145,7 +146,7 @@ function clearFilter() {
name: "",
};
detailReport.value = undefined;
year.value = new Date().getFullYear();
year.value = calculateFiscalYear(new Date());
pdfSrc.value = undefined;
detailReport.value = undefined;
}

View file

@ -16,7 +16,7 @@ const $q = useQuasar(); // show dialog
const router = useRouter();
const file = ref<boolean>(true);
const filter = ref<string>(""); //search data table
const initialPagination = ref<Pagination>({
const initialPagination = ref<Pagination>({
rowsPerPage: 0,
sortBy: "year",
});

View file

@ -10,6 +10,7 @@ import http from "@/plugins/http";
import config from "@/app.config";
import { checkPermission } from "@/utils/permissions";
import { useCounterMixin } from "@/stores/mixin";
import { calculateFiscalYear } from "@/utils/function";
import type { Pagination } from "@/modules/03_recruiting/interface/index/Main";
import type {
@ -36,7 +37,7 @@ const {
const router = useRouter();
const name = ref<string>("");
const year = ref<number>(new Date().getFullYear() + 543);
const year = ref<number>(calculateFiscalYear(new Date()) + 543);
const order = ref<number>(1);
const files = ref<any>(null);

View file

@ -6,6 +6,7 @@ import { useRouter, useRoute } from "vue-router";
import http from "@/plugins/http";
import config from "@/app.config";
import { useCounterMixin } from "@/stores/mixin";
import { calculateFiscalYear } from "@/utils/function";
import type { RequestPeriodCompete } from "@/modules/03_recruiting/interface/request/Period";
import type {
@ -36,7 +37,7 @@ const isFeeNotZero = computed(() => {
return fee.value !== 0 && fee.value !== "0" && fee.value !== "";
});
const round = ref<number>(1);
const yearly = ref<number>(new Date().getFullYear());
const yearly = ref<number>(calculateFiscalYear(new Date()));
const dateRegister = ref<[Date, Date] | null>(null); //
const datePayment = ref<[Date, Date] | null>(null); //
const dateAnnouncement = ref<[Date, Date] | null>(null); //

View file

@ -10,6 +10,7 @@ import http from "@/plugins/http";
import config from "@/app.config";
import { useCounterMixin } from "@/stores/mixin";
import { checkPermission } from "@/utils/permissions";
import { calculateFiscalYear } from "@/utils/function";
import type {
ResponseRecruitPeriod,
@ -37,7 +38,7 @@ const {
} = mixin;
const name = ref<string>("");
const year = ref<number>(new Date().getFullYear() + 543);
const year = ref<number>(calculateFiscalYear(new Date()) + 543);
const round = ref<number>(1);
const files = ref<any>(null);
const files_score = ref<any>(null);

View file

@ -7,6 +7,7 @@ import { useRouter, useRoute } from "vue-router";
import http from "@/plugins/http";
import config from "@/app.config";
import { useCounterMixin } from "@/stores/mixin";
import { calculateFiscalYear } from "@/utils/function";
import type { RequestPeriodDisable } from "@/modules/03_recruiting/interface/request/Period";
import type {
@ -33,7 +34,7 @@ const editor = ref<string>("");
const announcementExam = ref<boolean>(true);
const fee = ref<number>(0);
const round = ref<number>(1);
const yearly = ref<number>(new Date().getFullYear());
const yearly = ref<number>(calculateFiscalYear(new Date()));
const dateRegister = ref<[Date, Date] | null>(null); //
const datePayment = ref<[Date, Date] | null>(null); //
const dateAnnouncement = ref<[Date, Date] | null>(null); //

View file

@ -8,6 +8,7 @@ import { useRouter, useRoute } from "vue-router";
import http from "@/plugins/http";
import config from "@/app.config";
import { useCounterMixin } from "@/stores/mixin";
import { calculateFiscalYear } from "@/utils/function";
import type {
RequestPosition,
@ -74,7 +75,7 @@ const checkDocument = ref<boolean>(false);
const checkDisability = ref<boolean>(false);
const announcementExam = ref<boolean>(true);
const round = ref<number>(1);
const yearly = ref<number>(new Date().getFullYear());
const yearly = ref<number>(calculateFiscalYear(new Date()));
const nameRaw = ref<number | null>(null);
const roundRaw = ref<number | null>(null);
const yearlyRaw = ref<number | null>(null);

View file

@ -5,6 +5,7 @@ import { checkPermission } from "@/utils/permissions";
import { useRoute, useRouter } from "vue-router";
import { useRegistryNewDataStore } from "@/modules/04_registryPerson/store";
import { useCounterMixin } from "@/stores/mixin";
import { calculateFiscalYear } from "@/utils/function";
/** importType*/
import { useQuasar, type QTableProps } from "quasar";
@ -44,7 +45,7 @@ const rangeAge = ref<RangeAge>({
const objMarkerLabel = computed(() => {
return { 39: `ช่วงอายุ ${rangeAge.value.min}-${rangeAge.value.max} ปี` };
});
const year = ref<number>(new Date().getFullYear());
const year = ref<number>(calculateFiscalYear(new Date()));
//
const modalHistory = ref<boolean>(false); //

View file

@ -7,6 +7,7 @@ import { checkPermission } from "@/utils/permissions";
import { useCounterMixin } from "@/stores/mixin";
import { useResultsPerformDataStore } from "@/modules/04_registryPerson/stores/ResultsPerformance";
import { usePagination } from "@/composables/usePagination";
import { calculateFiscalYear } from "@/utils/function";
import http from "@/plugins/http";
import config from "@/app.config";
@ -45,7 +46,7 @@ const profileId = ref<string>(
route.params.id ? route.params.id.toString() : ""
);
const empType = ref<string>(pathRegistryEmp(route.name?.toString() ?? ""));
const year = ref<number | null>(new Date().getFullYear()); //
const year = ref<number | null>(calculateFiscalYear(new Date())); //
const id = ref<string>(""); //id
const typeIDP = ref<string>("");
const isEdit = ref<boolean>(false); //
@ -494,7 +495,7 @@ function clearData() {
resPerformForm.pointSumTotal = 0;
resPerformForm.pointSum = 0;
resPerformForm.date = null;
year.value = new Date().getFullYear();
year.value = calculateFiscalYear(new Date());
}
/**

View file

@ -888,7 +888,7 @@ onMounted(async () => {
{{ item.label }}
</div>
<div class="col-12"><q-separator /></div>
<q-card-section class="q-pt-none" style="min-height: 200px">
<q-card-section class="q-pt-none q-ml-md" style="min-height: 200px">
<li v-for="data in item.data">{{ data.name }} {{ data.time }}</li>
</q-card-section>
</q-card>

View file

@ -113,12 +113,10 @@ async function fetchDataPerson() {
queryParams.isProbation = store.formFilter.isProbation;
}
if (store.formFilter.isShowRetire != null) {
queryParams.isRetire = store.formFilter.isShowRetire;
queryParams.retireType = queryParams.isRetire
? store.formFilter.retireType
: undefined;
}
queryParams.isRetire = true;
queryParams.retireType = queryParams.isRetire
? store.formFilter.retireType
: undefined;
if (empType.value !== "officer") {
queryParams.type = empType.value;
@ -220,7 +218,6 @@ function onclickSearch() {
* @param item ประเภทขาราชการ
*/
function selectType() {
store.formFilter.isShowRetire = true;
store.labelOption.retireType = "ทั้งหมด";
store.formFilter.retireType = null;
store.formFilter.keyword = "";
@ -246,11 +243,11 @@ function selectType() {
store.formFilter.searchType = "fullName";
} else {
// filter
if (
store.formFilter.keyword != "" ||
store.labelOption.posType != "ทั้งหมด" ||
store.labelOption.posLevel != "ทั้งหมด" ||
store.formFilter.isShowRetire ||
store.formFilter.isProbation ||
store.formFilter.nodeId != null ||
store.formFilter.dateAppoint != ""

View file

@ -260,217 +260,236 @@ watch(
<DialogHeader :tittle="'ส่งไปออกคำสั่ง'" :close="closeModal" />
<q-separator />
<q-card-section>
<div class="row q-mb-sm" style="padding: 0">
<q-select
v-model="commandType"
dense
outlined
label="ประเภทคำสั่ง"
:options="commandOp"
option-label="name"
option-value="code"
emit-value
map-options
use-input
hide-selected
fill-input
style="width: 350px; max-width: auto"
@update:model-value="filterSelectOrder"
@filter="(inputValue:any,
<div class="row q-col-gutter-sm">
<div class="col-12">
<div class="row q-col-gutter-sm items-end">
<div class="col-xs-12 col-sm-12 col-md-5 col-lg-4">
<div class="row q-col-gutter-sm">
<div class="col-12">
<q-select
v-model="commandType"
dense
outlined
label="ประเภทคำสั่ง"
:options="commandOp"
option-label="name"
option-value="code"
emit-value
map-options
use-input
hide-selected
fill-input
@update:model-value="filterSelectOrder"
@filter="(inputValue:any,
doneFn:Function) => filterSelector(inputValue, doneFn
) "
>
<template v-slot:no-option>
<q-item>
<q-item-section class="text-grey"> ไมอม </q-item-section>
</q-item>
</template></q-select
>
<q-space />
<q-input
borderless
outlined
dense
v-model="filter"
placeholder="ค้นหา"
style="width: 200px; max-width: auto"
@keydown.enter.prevent="onSearch"
>
<template v-slot:append>
<q-icon name="search" />
<!-- <q-icon
v-if="filter !== ''"
name="clear"
class="cursor-pointer"
@click="filter = ''"
/> -->
</template>
</q-input>
<q-select
v-model="visibleColumns"
multiple
outlined
dense
options-dense
:display-value="$q.lang.table.columns"
emit-value
map-options
:options="columns"
option-value="name"
style="min-width: 140px"
class="gt-xs q-ml-sm"
/>
</div>
>
<template v-slot:no-option>
<q-item>
<q-item-section class="text-grey">
ไมอม
</q-item-section>
</q-item>
</template>
</q-select>
</div>
</div>
</div>
<div class="col-xs-12 col-sm-12 col-md-2 col-lg-4"></div>
<d-table
:columns="columns"
:rows="rows"
row-key="id"
:visible-columns="visibleColumns"
selection="multiple"
v-model:selected="selected"
>
<template v-slot:header-selection="scope">
<q-checkbox
keep-color
color="primary"
dense
:disable="commandType"
v-model="scope.selected"
/>
</template>
<template v-slot:body="props">
<q-tr :props="props">
<q-td>
<div class="col-xs-12 col-sm-12 col-md-5 col-lg-4">
<div class="row q-col-gutter-sm">
<div class="col-xs-12 col-sm-8 col-md-7 col-lg-7">
<q-input
borderless
outlined
dense
v-model="filter"
placeholder="ค้นหา"
@keydown.enter.prevent="onSearch"
>
<template v-slot:append>
<q-icon name="search" />
</template>
</q-input>
</div>
<div class="col-xs-12 col-sm-4 col-md-5 col-lg-5">
<q-select
v-model="visibleColumns"
multiple
outlined
dense
options-dense
:display-value="$q.lang.table.columns"
emit-value
map-options
:options="columns"
option-value="name"
/>
</div>
</div>
</div>
</div>
</div>
<div class="col-12">
<d-table
:columns="columns"
:rows="rows"
row-key="id"
:visible-columns="visibleColumns"
selection="multiple"
v-model:selected="selected"
>
<template v-slot:header-selection="scope">
<q-checkbox
keep-color
color="primary"
dense
:disable="commandType"
v-model="props.selected"
v-model="scope.selected"
/>
</q-td>
<q-td
v-for="col in props.cols"
:key="col.name"
:props="props"
class="cursor-pointer"
>
<template v-if="col.name === 'no'">
{{ props.rowIndex + 1 }}
</template>
<template
v-else-if="col.name === 'fullName'"
class="table_ellipsis"
>
<q-item v-ripple style="padding: 0">
<q-item-section avatar>
<q-avatar size="30px" color="grey-4">
<q-img
:src="props.row.avatar"
class="photo-profile"
v-if="props.row.avatar"
/>
<q-img :src="avatar" class="photo-profile" v-else/>
</q-avatar>
</q-item-section>
<q-item-section>
<div class="text-weight-medium">{{ props.row.name }}</div>
<div class="text-weight-light">
{{ props.row.idCard }}
</div>
</q-item-section>
</q-item>
</template>
<template v-else-if="col.name === 'examNumber'">
<div class="text-weight-medium">
{{
props.row.examNumber !== null ? props.row.examNumber : "-"
}}
</div>
</template>
<template v-else-if="col.name === 'organizationName'">
<div
v-if="
props.row.orgName !== null ||
props.row.positionPath !== null
"
</template>
<template v-slot:body="props">
<q-tr :props="props">
<q-td>
<q-checkbox
keep-color
color="primary"
dense
:disable="commandType"
v-model="props.selected"
/>
</q-td>
<q-td
v-for="col in props.cols"
:key="col.name"
:props="props"
class="cursor-pointer"
>
<div class="col-4">
<template v-if="col.name === 'no'">
{{ props.rowIndex + 1 }}
</template>
<template
v-else-if="col.name === 'fullName'"
class="table_ellipsis"
>
<q-item v-ripple style="padding: 0">
<q-item-section avatar>
<q-avatar size="30px" color="grey-4">
<q-img
:src="props.row.avatar"
class="photo-profile"
v-if="props.row.avatar"
/>
<q-img :src="avatar" class="photo-profile" v-else />
</q-avatar>
</q-item-section>
<q-item-section>
<div class="text-weight-medium">
{{ props.row.name }}
</div>
<div class="text-weight-light">
{{ props.row.idCard }}
</div>
</q-item-section>
</q-item>
</template>
<template v-else-if="col.name === 'examNumber'">
<div class="text-weight-medium">
{{ props.row.root !== null ? props.row.root : "-" }}
{{
props.row.rootShortName !== null
? `(${props.row.rootShortName})`
: ""
props.row.examNumber !== null
? props.row.examNumber
: "-"
}}
</div>
<div class="text-weight-light">
</template>
<template v-else-if="col.name === 'organizationName'">
<div
v-if="
props.row.orgName !== null ||
props.row.positionPath !== null
"
>
<div class="col-4">
<div class="text-weight-medium">
{{ props.row.root !== null ? props.row.root : "-" }}
{{
props.row.rootShortName !== null
? `(${props.row.rootShortName})`
: ""
}}
</div>
<div class="text-weight-light">
{{
props.row.nodeName !== null
? props.row.nodeName
: ""
}}
{{
props.row.nodeShortName !== null
? `(${props.row.nodeShortName}${props.row.posMasterNo})`
: ""
}}
</div>
</div>
</div>
<div v-else>
<div class="col-4">
<div class="text-weight-medium">-</div>
</div>
</div>
</template>
<template v-else-if="col.name === 'positionCandidate'">
<div
class="text-weight-medium"
v-if="props.row.positionCandidate == null"
>
-
</div>
<div class="text-weight-medium" v-else>
{{ props.row.positionCandidate }}
</div>
</template>
<template v-else-if="col.name === 'reportingDate'">
<div class="text-weight-medium">
{{
props.row.nodeName !== null ? props.row.nodeName : ""
}}
{{
props.row.nodeShortName !== null
? `(${props.row.nodeShortName}${props.row.posMasterNo})`
: ""
props.row.reportingDate !== null
? dateText(props.row.reportingDate)
: "-"
}}
</div>
</div>
</div>
</template>
<div v-else>
<div class="col-4">
<div class="text-weight-medium">-</div>
</div>
</div>
</template>
<template v-else-if="col.name === 'bmaOfficer'">
<div class="text-weight-medium">
{{ props.row.bmaOfficer }}
</div>
</template>
<template v-else-if="col.name === 'positionCandidate'">
<div
class="text-weight-medium"
v-if="props.row.positionCandidate == null"
>
-
</div>
<div class="text-weight-medium" v-else>
{{ props.row.positionCandidate }}
</div>
</template>
<template v-else-if="col.name === 'draft'">
<div class="text-weight-medium">
{{ props.row.draft }}
</div>
</template>
<template v-else-if="col.name === 'reportingDate'">
<div class="text-weight-medium">
{{
props.row.reportingDate !== null
? dateText(props.row.reportingDate)
: "-"
}}
</div>
</template>
<template v-else-if="col.name === 'bmaOfficer'">
<div class="text-weight-medium">
{{ props.row.bmaOfficer }}
</div>
</template>
<template v-else-if="col.name === 'draft'">
<div class="text-weight-medium">
{{ props.row.draft }}
</div>
</template>
<template v-else-if="col.name === 'statusName'">
<div class="text-weight-medium">
{{ props.row.statusName }}
</div>
</template>
</q-td>
</q-tr>
</template>
</d-table>
<template v-else-if="col.name === 'statusName'">
<div class="text-weight-medium">
{{ props.row.statusName }}
</div>
</template>
</q-td>
</q-tr>
</template>
</d-table>
</div>
</div>
</q-card-section>
<q-separator />
<q-card-actions align="right">

View file

@ -153,7 +153,7 @@ onMounted(async () => {
</div>
</q-card>
</div>
<q-card flat bordered class="col-12 q-mt-sm q-pt-sm">
<q-card flat bordered class="col-12 q-mt-sm">
<div class="q-pa-none">
<AddTablePosition :statCard="getStat" />
</div>

View file

@ -1447,188 +1447,201 @@ onMounted(async () => {
:close="clickCloseSendModal"
/>
<q-separator />
<q-card-section class="q-pt-none">
<div class="row justify-end">
<div class="col-5">
<q-toolbar style="padding: 0">
<q-input
borderless
outlined
dense
debounce="200"
v-model="filterlistAdd"
placeholder="ค้นหา"
style="width: 850px; max-width: auto"
@keydown.enter.prevent="onSearchAdd"
>
<template v-slot:append>
<q-icon name="search" />
</template>
</q-input>
<q-select
v-model="visibleColumnslist"
multiple
outlined
dense
options-dense
:display-value="$q.lang.table.columns"
emit-value
map-options
:options="columns"
option-value="name"
style="min-width: 140px"
class="gt-xs q-ml-sm"
/>
</q-toolbar>
</div>
</div>
<q-card-section>
<div class="row q-col-gutter-sm">
<div class="col-12">
<div class="row q-col-gutter-sm items-end">
<div class="col-xs-0 col-sm-0 col-md-4 col-lg-5"></div>
<div class="col-xs-12 col-sm-12 col-md-8 col-lg-7">
<div class="row q-col-gutter-sm">
<div class="col-xs-12 col-md-8 col-lg-7">
<q-input
borderless
outlined
dense
v-model="filterlistAdd"
placeholder="ค้นหา"
@keydown.enter.prevent="onSearchAdd"
>
<template v-slot:append>
<q-icon name="search" />
</template>
</q-input>
</div>
<d-table
flat
bordered
dense
:rows="rowsFilter"
:columns="columns"
row-key="name"
class="custom-header-table"
selection="multiple"
v-model:selected="selected"
:pagination-label="paginationLabel"
:visible-columns="visibleColumnslist"
>
<template v-slot:header-selection="scope">
<q-checkbox
keep-color
color="primary"
<div class="col-xs-12 col-md-4 col-lg-5">
<q-select
v-model="visibleColumnslist"
multiple
outlined
dense
options-dense
:display-value="$q.lang.table.columns"
emit-value
map-options
:options="columns"
option-value="name"
/>
</div>
</div>
</div>
</div>
</div>
<div class="col-12">
<d-table
flat
bordered
dense
v-model="scope.selected"
/>
</template>
<template v-slot:body="props">
<q-tr :props="props">
<q-td>
:rows="rowsFilter"
:columns="columns"
row-key="name"
class="custom-header-table"
selection="multiple"
v-model:selected="selected"
:pagination-label="paginationLabel"
:visible-columns="visibleColumnslist"
>
<template v-slot:header-selection="scope">
<q-checkbox
keep-color
color="primary"
dense
v-model="props.selected"
v-model="scope.selected"
/>
</q-td>
<q-td
v-for="col in props.cols"
:key="col.name"
:props="props"
class="cursor-pointer"
>
<template v-if="col.name === 'no'">
{{ props.rowIndex + 1 }}
</template>
<template
v-else-if="col.name === 'fullName'"
class="table_ellipsis"
>
<q-item v-ripple style="padding: 0">
<q-item-section avatar>
<q-avatar size="30px" color="grey-4">
<q-img
:src="props.row.avatar"
class="photo-profile"
v-if="props.row.avatar"
/>
<q-img :src="avatar" class="photo-profile" v-else/>
</q-avatar>
</q-item-section>
<q-item-section>
<div class="text-weight-medium">{{ props.row.name }}</div>
<div class="text-weight-light">
{{ props.row.idCard }}
</div>
</q-item-section>
</q-item>
</template>
<template v-else-if="col.name === 'examNumber'">
<div class="text-weight-medium">
{{
props.row.examNumber !== null ? props.row.examNumber : "-"
}}
</div>
</template>
<template v-else-if="col.name === 'organizationName'">
<div
v-if="
props.row.orgName !== null ||
props.row.positionPath !== null
"
</template>
<template v-slot:body="props">
<q-tr :props="props">
<q-td>
<q-checkbox
keep-color
color="primary"
dense
v-model="props.selected"
/>
</q-td>
<q-td
v-for="col in props.cols"
:key="col.name"
:props="props"
class="cursor-pointer"
>
<div class="col-4">
<template v-if="col.name === 'no'">
{{ props.rowIndex + 1 }}
</template>
<template
v-else-if="col.name === 'fullName'"
class="table_ellipsis"
>
<q-item v-ripple style="padding: 0">
<q-item-section avatar>
<q-avatar size="30px" color="grey-4">
<q-img
:src="props.row.avatar"
class="photo-profile"
v-if="props.row.avatar"
/>
<q-img :src="avatar" class="photo-profile" v-else />
</q-avatar>
</q-item-section>
<q-item-section>
<div class="text-weight-medium">
{{ props.row.name }}
</div>
<div class="text-weight-light">
{{ props.row.idCard }}
</div>
</q-item-section>
</q-item>
</template>
<template v-else-if="col.name === 'examNumber'">
<div class="text-weight-medium">
{{ props.row.root !== null ? props.row.root : "-" }}
{{
props.row.rootShortName !== null
? `(${props.row.rootShortName})`
: ""
props.row.examNumber !== null
? props.row.examNumber
: "-"
}}
</div>
<div class="text-weight-light">
{{
props.row.nodeName !== null ? props.row.nodeName : ""
}}
{{
props.row.nodeShortName !== null
? `(${props.row.nodeShortName}${props.row.posMasterNo})`
: ""
}}
</div>
</div>
</div>
</template>
<div v-else>
<div class="col-4">
<div class="text-weight-medium">-</div>
</div>
</div>
</template>
<template v-else-if="col.name === 'positionCandidate'">
<div
class="text-weight-medium"
v-if="props.row.positionCandidate == null"
>
-
</div>
<div class="text-weight-medium" v-else>
{{ props.row.positionCandidate }}
</div>
</template>
<template v-else-if="col.name === 'reportingDate'">
<div class="text-weight-medium">
{{
props.row.reportingDate !== null
? dateText(props.row.reportingDate)
: "-"
}}
</div>
</template>
<template v-else-if="col.name === 'bmaOfficer'">
<div class="text-weight-medium">
{{ props.row.bmaOfficer }}
</div>
</template>
<template v-else-if="col.name === 'draft'">
<div class="text-weight-medium">
{{ props.row.draft }}
</div>
</template>
<template v-else-if="col.name === 'statusName'">
<div class="text-weight-medium">
{{ props.row.statusName }}
</div>
</template>
</q-td>
</q-tr>
</template>
</d-table>
<template v-else-if="col.name === 'organizationName'">
<div
v-if="
props.row.orgName !== null ||
props.row.positionPath !== null
"
>
<div class="col-4">
<div class="text-weight-medium">
{{ props.row.root !== null ? props.row.root : "-" }}
{{
props.row.rootShortName !== null
? `(${props.row.rootShortName})`
: ""
}}
</div>
<div class="text-weight-light">
{{
props.row.nodeName !== null
? props.row.nodeName
: ""
}}
{{
props.row.nodeShortName !== null
? `(${props.row.nodeShortName}${props.row.posMasterNo})`
: ""
}}
</div>
</div>
</div>
<div v-else>
<div class="col-4">
<div class="text-weight-medium">-</div>
</div>
</div>
</template>
<template v-else-if="col.name === 'positionCandidate'">
<div
class="text-weight-medium"
v-if="props.row.positionCandidate == null"
>
-
</div>
<div class="text-weight-medium" v-else>
{{ props.row.positionCandidate }}
</div>
</template>
<template v-else-if="col.name === 'reportingDate'">
<div class="text-weight-medium">
{{
props.row.reportingDate !== null
? dateText(props.row.reportingDate)
: "-"
}}
</div>
</template>
<template v-else-if="col.name === 'bmaOfficer'">
<div class="text-weight-medium">
{{ props.row.bmaOfficer }}
</div>
</template>
<template v-else-if="col.name === 'draft'">
<div class="text-weight-medium">
{{ props.row.draft }}
</div>
</template>
<template v-else-if="col.name === 'statusName'">
<div class="text-weight-medium">
{{ props.row.statusName }}
</div>
</template>
</q-td>
</q-tr>
</template>
</d-table>
</div>
</div>
</q-card-section>
<q-separator />
<q-card-actions

View file

@ -205,166 +205,187 @@ function filterSelector(val: string, update: Function) {
</script>
<template>
<div class="q-px-md q-pb-md">
<div class="col-12 row q-py-sm">
<div class="row q-col-gutter-sm">
<q-select
outlined
dense
v-model="bmaOfficer"
:options="bmaOfficerOption"
emit-value
map-options
option-value="id"
option-label="name"
label="สถานภาพ"
:clearable="bmaOfficer !== ''"
style="width: 200px"
@update:model-value="onUpdateNewRows"
@clear="bmaOfficer = ''"
>
</q-select>
<q-select
outlined
dense
v-model="positionCandidate"
:options="positionCandidateOptions"
emit-value
map-options
option-value="id"
option-label="name"
label="ตำแหน่งที่สอบ"
style="width: 250px"
hide-selected
fill-input
use-input
:clearable="positionCandidate !== ''"
@clear="
(positionCandidate = ''),
(positionCandidateOptions = positionCandidateData || []),
onUpdateNewRows()
"
@update:model-value="onUpdateNewRows"
@filter="(inputValue:string,
<div class="q-pa-md q-gutter-sm row">
<div class="col-12">
<div class="row q-col-gutter-sm items-end">
<div class="col-xs-12 col-sm-12 col-md-12 col-lg-5">
<div class="row q-col-gutter-sm">
<div class="col-xs-12 col-sm-3 col-md-4 col-lg-4">
<q-select
outlined
dense
v-model="bmaOfficer"
:options="bmaOfficerOption"
emit-value
map-options
option-value="id"
option-label="name"
label="สถานภาพ"
:clearable="bmaOfficer !== ''"
@update:model-value="onUpdateNewRows"
@clear="bmaOfficer = ''"
>
</q-select>
</div>
<div class="col-xs-12 col-sm-5 col-md-4 col-lg-6">
<q-select
outlined
dense
v-model="positionCandidate"
:options="positionCandidateOptions"
emit-value
map-options
option-value="id"
option-label="name"
label="ตำแหน่งที่สอบ"
hide-selected
fill-input
use-input
:clearable="positionCandidate !== ''"
@clear="
(positionCandidate = ''),
(positionCandidateOptions = positionCandidateData || []),
onUpdateNewRows()
"
@update:model-value="onUpdateNewRows"
@filter="(inputValue:string,
doneFn:Function) => filterSelector(inputValue, doneFn
) "
>
<template v-slot:no-option>
<q-item>
<q-item-section class="text-grey"> ไมอม </q-item-section>
</q-item>
</template>
</q-select>
</div>
<div>
<q-btn
flat
round
color="blue"
icon="mdi-account-arrow-right"
@click="updateModaladdlist"
v-if="displayAdd && checkPermission($route)?.attrIsUpdate"
>
<q-tooltip>งรายชอไปยงหนวยงาน</q-tooltip>
</q-btn>
</div>
>
<template v-slot:no-option>
<q-item>
<q-item-section class="text-grey">
ไมอม
</q-item-section>
</q-item>
</template>
</q-select>
</div>
<div class="col-xs-12 col-sm-3 col-md-4 col-lg-2">
<div class="row q-col-gutter-sm">
<div
class="col"
v-if="displayAdd && checkPermission($route)?.attrIsUpdate"
>
<q-btn
flat
round
color="blue"
icon="mdi-account-arrow-right"
@click="updateModaladdlist"
>
<q-tooltip>งรายชอไปยงหนวยงาน</q-tooltip>
</q-btn>
</div>
<div
class="col"
v-if="
checkPermission($route)?.attrIsUpdate &&
checkPermissionList(['COMMAND']) &&
checkPermissionCreate('COMMAND')
"
>
<q-btn
flat
round
color="primary"
icon="mdi-account-arrow-right"
@click="openModalOrder()"
>
<q-tooltip>งไปออกคำส</q-tooltip>
</q-btn>
</div>
</div>
</div>
</div>
</div>
<q-btn
v-if="
checkPermission($route)?.attrIsUpdate &&
checkPermissionList(['COMMAND']) &&
checkPermissionCreate('COMMAND')
"
flat
round
color="primary"
icon="mdi-account-arrow-right"
@click="openModalOrder()"
>
<q-tooltip>งไปออกคำส</q-tooltip>
</q-btn>
<div class="col-xs-0 col-sm-0 col-md-0 col-lg-2"></div>
<q-space />
<div class="items-center" style="display: flex">
<q-toggle
class="col-xs-12 col-sm-5 col-md-5 toggle-expired-account"
:model-value="containStatus"
color="blue"
label="แสดงสถานะบรรจุแล้ว"
@update:model-value="updateContain"
/>
<q-input
standout
dense
:model-value="inputfilter"
ref="filterRef"
@update:model-value="updateInput"
outlined
placeholder="ค้นหา"
style="max-width: 200px"
class="q-ml-sm"
@keydown.enter.prevent="onUpdateNewRows"
>
<template v-slot:append> </template>
</q-input>
<!-- แสดง table ใน คอลมน -->
<q-select
:model-value="inputvisible"
@update:model-value="updateVisible"
:display-value="$q.lang.table.columns"
multiple
outlined
dense
:options="attrs.columns"
options-dense
option-value="name"
map-options
emit-value
style="min-width: 140px"
class="gt-xs q-ml-sm"
/>
<div class="col-xs-12 col-sm-12 col-md-12 col-lg-5">
<div class="row q-col-gutter-sm">
<div class="col-xs-12 col-sm-4 col-md-4">
<q-toggle
class="toggle-expired-account"
:model-value="containStatus"
color="blue"
label="แสดงสถานะบรรจุแล้ว"
@update:model-value="updateContain"
/>
</div>
<div class="col-xs-12 col-sm-5 col-md-5">
<q-input
standout
dense
:model-value="inputfilter"
ref="filterRef"
@update:model-value="updateInput"
outlined
placeholder="ค้นหา"
@keydown.enter.prevent="onUpdateNewRows"
>
<template v-slot:append> </template>
</q-input>
</div>
<div class="col-xs-12 col-sm-3 col-md-3">
<q-select
:model-value="inputvisible"
@update:model-value="updateVisible"
:display-value="$q.lang.table.columns"
multiple
outlined
dense
:options="attrs.columns"
options-dense
option-value="name"
map-options
emit-value
/>
</div>
</div>
</div>
</div>
</div>
<q-table
ref="table"
flat
bordered
class="custom-header-table"
v-bind="attrs"
virtual-scroll
:virtual-scroll-sticky-size-start="48"
dense
:pagination-label="paginationLabel"
v-model:pagination="pagination"
>
<template v-slot:pagination="scope">
งหมด {{ attrs.rows.length.toLocaleString() }} รายการ
<q-pagination
v-model="pagination.page"
active-color="primary"
color="dark"
:max="scope.pagesNumber"
:max-pages="5"
size="sm"
boundary-links
direction-links
></q-pagination>
</template>
<template v-slot:header="props">
<q-tr :props="props">
<q-th auto-width v-if="history == true" />
<q-th v-for="col in props.cols" :key="col.name" :props="props">
<span class="text-weight-medium">{{ col.label }}</span>
</q-th>
</q-tr>
</template>
<template #body="props">
<slot v-bind="props" name="columns"></slot>
</template>
</q-table>
<div class="col-12">
<q-table
ref="table"
flat
bordered
class="custom-header-table"
v-bind="attrs"
virtual-scroll
:virtual-scroll-sticky-size-start="48"
dense
:pagination-label="paginationLabel"
v-model:pagination="pagination"
>
<template v-slot:pagination="scope">
งหมด {{ attrs.rows.length.toLocaleString() }} รายการ
<q-pagination
v-model="pagination.page"
active-color="primary"
color="dark"
:max="scope.pagesNumber"
:max-pages="5"
size="sm"
boundary-links
direction-links
></q-pagination>
</template>
<template v-slot:header="props">
<q-tr :props="props">
<q-th auto-width v-if="history == true" />
<q-th v-for="col in props.cols" :key="col.name" :props="props">
<span class="text-weight-medium">{{ col.label }}</span>
</q-th>
</q-tr>
</template>
<template #body="props">
<slot v-bind="props" name="columns"></slot>
</template>
</q-table>
</div>
</div>
</template>

View file

@ -189,40 +189,49 @@ watch(
<q-separator />
<q-card-section>
<div class="row col-12 q-col-gutter-sm">
<div class="row col-12">
<q-space />
<q-input
borderless
outlined
dense
v-model="filter"
placeholder="ค้นหา"
@keydown.enter.prevent="onSearch"
>
<template v-slot:append>
<q-icon name="search" />
<!-- <q-icon
<div class="col-12">
<div class="row q-col-gutter-xs items-end">
<div class="col-xs-0 col-sm-4 col-md-6 col-lg-8"></div>
<div class="col-xs-12 col-sm-8 col-md-6 col-lg-4">
<div class="row q-col-gutter-sm">
<div class="col-xs-12 col-sm-6 col-md-6 col-lg-7">
<q-input
borderless
outlined
dense
v-model="filter"
placeholder="ค้นหา"
@keydown.enter.prevent="onSearch"
>
<template v-slot:append>
<q-icon name="search" />
<!-- <q-icon
v-if="filter !== ''"
name="clear"
class="cursor-pointer"
@click="filter = ''"
/> -->
</template>
</q-input>
<q-select
v-model="visibleColumns2"
multiple
outlined
dense
options-dense
:display-value="$q.lang.table.columns"
emit-value
map-options
:options="columns2"
option-value="name"
style="min-width: 140px"
class="gt-xs q-ml-sm"
/>
</template>
</q-input>
</div>
<div class="col-xs-12 col-sm-6 col-md-6 col-lg-5">
<q-select
v-model="visibleColumns2"
multiple
outlined
dense
options-dense
:display-value="$q.lang.table.columns"
emit-value
map-options
:options="columns2"
option-value="name"
/>
</div>
</div>
</div>
</div>
</div>
<div class="col-12">

View file

@ -14,7 +14,7 @@ const mixin = useCounterMixin();
const { showLoader, hideLoader, messageError, date2Thai } = mixin;
const { pagination, params, onRequest } = usePagination("", getData);
const year = ref<number | null>(new Date().getFullYear()); //
const year = ref<number | null>(new Date().getFullYear());
const rows = ref<MainData[]>([]);
const filterKeyword = ref<string>("");

View file

@ -385,147 +385,163 @@ onMounted(() => {
<q-card flat bordered class="col-12 q-mt-sm q-pa-md">
<div class="row q-col-gutter-sm">
<div class="row col-12">
<q-select
class="col-xs-12 col-sm-3 col-md-2"
v-model="searchYear"
label="ปีงบประมาณ"
dense
emit-value
map-options
:options="yearOptionsFn"
option-value="id"
option-label="name"
lazy-rules
hide-bottom-space
:readonly="false"
:borderless="false"
:outlined="true"
:hide-dropdown-icon="false"
@update:model-value="filterYear"
use-input
hide-selected
fill-input
@filter="filterFnYear"
><template v-slot:no-option>
<q-item>
<q-item-section class="text-grey"> ไมอม </q-item-section>
</q-item>
</template>
</q-select>
<q-space />
<q-input
standout
dense
v-model="filterKeyword"
ref="filterRef"
outlined
placeholder="ค้นหา"
@keydown.enter.prevent="onSearch"
>
<template v-slot:append>
<q-icon name="search" />
</template>
</q-input>
<q-select
class="q-ml-sm"
v-model="visibleColumns"
multiple
outlined
dense
options-dense
:display-value="$q.lang.table.columns"
emit-value
map-options
:options="columns"
option-value="name"
style="min-width: 140px"
/>
<div class="col-12">
<div class="row q-col-gutter-xs items-end">
<div class="col-xs-12 col-sm-6 col-md-6 col-lg-3">
<div class="row q-col-gutter-sm">
<div class="col-xs-12 col-sm-8 col-md-6">
<q-select
v-model="searchYear"
label="ปีงบประมาณ"
dense
emit-value
map-options
:options="yearOptionsFn"
option-value="id"
option-label="name"
lazy-rules
hide-bottom-space
:readonly="false"
:borderless="false"
:outlined="true"
:hide-dropdown-icon="false"
@update:model-value="filterYear"
use-input
hide-selected
fill-input
@filter="filterFnYear"
><template v-slot:no-option>
<q-item>
<q-item-section class="text-grey">
ไมอม
</q-item-section>
</q-item>
</template>
</q-select>
</div>
</div>
</div>
<div class="col-xs-0 col-sm-1 col-md-3 col-lg-5"></div>
<div class="col-xs-12 col-sm-5 col-md-3 col-lg-4">
<div class="row q-col-gutter-xs">
<div class="col-xs-12 col-sm-6 col-md-6 col-lg-7">
<q-input
standout
dense
v-model="filterKeyword"
ref="filterRef"
outlined
placeholder="ค้นหา"
@keydown.enter.prevent="onSearch"
>
<template v-slot:append>
<q-icon name="search" />
</template>
</q-input>
</div>
<div class="col-xs-12 col-sm-6 col-md-6 col-lg-5">
<q-select
v-model="visibleColumns"
multiple
outlined
dense
options-dense
:display-value="$q.lang.table.columns"
emit-value
map-options
:options="columns"
option-value="name"
/>
</div>
</div>
</div>
</div>
</div>
<div class="col-12">
<q-card bordered class="col-12 filter-card q-pa-sm">
<div class="row col-12 q-col-gutter-sm">
<q-select
class="col-xs-12 col-sm-3 col-md-2"
v-model="examTime"
label="ครั้งที่"
dense
emit-value
map-options
:options="examTimeOP2"
option-value="id"
option-label="name"
lazy-rules
hide-selected
fill-input
hide-bottom-space
:readonly="false"
:borderless="false"
:outlined="true"
:hide-dropdown-icon="false"
@update:model-value="searchFilterTable"
@filter="filterFnexamTime"
:clearable="examTime !== 'all' && examTime !== 'ทั้งหมด'"
@clear="(examTime = 'ทั้งหมด'), searchFilterTable()"
use-input
input-debounce="0"
><template v-slot:no-option>
<q-item>
<q-item-section class="text-grey">
ไมอม
</q-item-section>
</q-item>
</template>
</q-select>
<div class="col-xs-12 col-sm-4 col-md-2">
<q-select
v-model="examTime"
label="ครั้งที่"
dense
emit-value
map-options
:options="examTimeOP2"
option-value="id"
option-label="name"
lazy-rules
hide-selected
fill-input
hide-bottom-space
:readonly="false"
:borderless="false"
:outlined="true"
:hide-dropdown-icon="false"
@update:model-value="searchFilterTable"
@filter="filterFnexamTime"
:clearable="examTime !== 'all' && examTime !== 'ทั้งหมด'"
@clear="(examTime = 'ทั้งหมด'), searchFilterTable()"
use-input
input-debounce="0"
><template v-slot:no-option>
<q-item>
<q-item-section class="text-grey">
ไมอม
</q-item-section>
</q-item>
</template>
</q-select>
</div>
<q-select
class="col-xs-12 col-sm-3 col-md-3"
v-model="examType"
label="ประเภทการสอบ"
dense
emit-value
map-options
option-label="name"
:options="examTypeOP2"
option-value="id"
lazy-rules
hide-bottom-space
:readonly="false"
:borderless="false"
:outlined="true"
:hide-dropdown-icon="false"
@update:model-value="searchFilterTable"
@filter="filterFnExamtype"
use-input
hide-selected
fill-input
:clearable="examType !== 'all' && examType !== 'ทั้งหมด'"
@clear="
(examTimeOP2 = examTimeOP),
(examType = 'ทั้งหมด'),
searchFilterTable()
"
>
<template v-slot:no-option>
<q-item>
<q-item-section class="text-grey">
ไมอม
</q-item-section>
</q-item>
</template>
</q-select>
<div class="col-xs-12 col-sm-4 col-md-3">
<q-select
v-model="examType"
label="ประเภทการสอบ"
dense
emit-value
map-options
option-label="name"
:options="examTypeOP2"
option-value="id"
lazy-rules
hide-bottom-space
:readonly="false"
:borderless="false"
:outlined="true"
:hide-dropdown-icon="false"
@update:model-value="searchFilterTable"
@filter="filterFnExamtype"
use-input
hide-selected
fill-input
:clearable="examType !== 'all' && examType !== 'ทั้งหมด'"
@clear="
(examTimeOP2 = examTimeOP),
(examType = 'ทั้งหมด'),
searchFilterTable()
"
>
<template v-slot:no-option>
<q-item>
<q-item-section class="text-grey">
ไมอม
</q-item-section>
</q-item>
</template>
</q-select>
</div>
<q-toggle
class="col-xs-12 col-sm-5 col-md-5 toggle-expired-account"
v-model="expiredAccount"
color="blue"
label="แสดงบัญชีหมดอายุ"
@update:model-value="searchFilterTable"
/>
<div class="col-xs-12 col-sm-4 col-md-5">
<q-toggle
class="toggle-expired-account"
v-model="expiredAccount"
color="blue"
label="แสดงบัญชีหมดอายุ"
@update:model-value="searchFilterTable"
/>
</div>
</div>
</q-card>
</div>

View file

@ -205,145 +205,160 @@ onMounted(async () => {
<template>
<div class="toptitle text-dark col-12 row items-center">รายการขอโอน</div>
<q-card flat bordered class="col-12 q-mt-sm">
<div class="row q-pa-md">
<div class="col-12 q-col-gutter-sm">
<div class="row">
<div class="col-2">
<q-select
:model-value="status ? status : 'ทั้งหมด'"
outlined
dense
label="สถานะ"
:options="store.statusOp.filter((item:any)=> item.id !== 'PENDING')"
emit-value
map-options
option-label="name"
option-value="id"
fill-input
use-input
hide-selected
bg-color="white"
@filter="(inputValue:any,doneFn:Function) => filterOption(inputValue, doneFn) "
@update:model-value="(value:string)=>{(status = value),fetchData()}"
>
<template v-slot:no-option>
<q-item>
<q-item-section class="text-grey">
ไมอม
</q-item-section>
</q-item>
</template>
<template v-if="status" v-slot:append>
<q-icon
name="cancel"
@click.stop.prevent="(status = ''), fetchData()"
class="cursor-pointer"
style="opacity: 0.6"
/>
</template>
</q-select>
<q-card flat bordered class="col-12">
<div class="row q-pa-md q-col-gutter-sm">
<div class="col-12">
<div class="row q-col-gutter-xs items-end">
<div class="col-xs-12 col-sm-6 col-md-6 col-lg-3">
<div class="row q-col-gutter-sm">
<div class="col-xs-11 col-sm-7 col-md-7 col-lg-7">
<q-select
:model-value="status ? status : 'ทั้งหมด'"
outlined
dense
label="สถานะ"
:options="store.statusOp.filter((item:any)=> item.id !== 'PENDING')"
emit-value
map-options
option-label="name"
option-value="id"
fill-input
use-input
hide-selected
bg-color="white"
@filter="(inputValue:any,doneFn:Function) => filterOption(inputValue, doneFn) "
@update:model-value="(value:string)=>{(status = value),fetchData()}"
>
<template v-slot:no-option>
<q-item>
<q-item-section class="text-grey">
ไมอม
</q-item-section>
</q-item>
</template>
<template v-if="status" v-slot:append>
<q-icon
name="cancel"
@click.stop.prevent="(status = ''), fetchData()"
class="cursor-pointer"
style="opacity: 0.6"
/>
</template>
</q-select>
</div>
<div class="col-xs-1 col-sm-5 col-md-5 col-lg-5">
<q-btn
v-if="
checkPermission($route)?.attrIsUpdate &&
checkPermissionList(['COMMAND']) &&
checkPermissionCreate('COMMAND')
"
@click="openModalOrder"
flat
round
color="primary"
icon="mdi-account-arrow-right"
>
<q-tooltip>งไปออกคำส</q-tooltip>
</q-btn>
</div>
</div>
</div>
<q-btn
v-if="
checkPermission($route)?.attrIsUpdate &&
checkPermissionList(['COMMAND']) &&
checkPermissionCreate('COMMAND')
"
@click="openModalOrder"
flat
round
color="primary"
icon="mdi-account-arrow-right"
>
<q-tooltip>งไปออกคำส</q-tooltip>
</q-btn>
<q-space />
<q-input
standout
dense
v-model="filter"
ref="filterRef"
outlined
placeholder="ค้นหา"
@keyup.enter="onSearch"
>
<template v-slot:append>
<q-icon name="search" />
</template>
</q-input>
<div class="col-xs-0 col-sm-1 col-md-3 col-lg-5"></div>
<q-select
class="q-ml-sm"
v-model="visibleColumns"
multiple
outlined
dense
options-dense
:display-value="$q.lang.table.columns"
emit-value
map-options
:options="columns"
option-value="name"
style="min-width: 140px"
/>
<div class="col-xs-12 col-sm-5 col-md-3 col-lg-4">
<div class="row q-col-gutter-sm">
<!-- Search Input -->
<div class="col-xs-12 col-sm-7 col-md-7 col-lg-7">
<q-input
standout
dense
v-model="filter"
ref="filterRef"
outlined
placeholder="ค้นหา"
@keyup.enter="onSearch"
>
<template v-slot:append>
<q-icon name="search" />
</template>
</q-input>
</div>
<div class="col-xs-12 col-sm-5 col-md-5 col-lg-5">
<q-select
v-model="visibleColumns"
multiple
outlined
dense
options-dense
:display-value="$q.lang.table.columns"
emit-value
map-options
:options="columns"
option-value="name"
/>
</div>
</div>
</div>
</div>
</div>
<div class="col-12">
<d-table
:columns="columns"
:rows="rows"
row-key="id"
:visible-columns="visibleColumns"
>
<template v-slot:header="props">
<q-tr :props="props">
<q-th auto-width />
<q-th v-for="col in props.cols" :key="col.name" :props="props">
<span class="text-weight-medium">{{ col.label }}</span>
</q-th>
</q-tr>
</template>
<template v-slot:body="props">
<q-tr :props="props">
<q-td auto-width>
<q-btn
v-if="checkPermission($route)?.attrIsGet"
flat
dense
round
color="info"
icon="mdi-eye"
@click.stop.prevent="
router.push(`/placement/transfer/${props.row.id}`)
"
>
<q-tooltip>รายละเอยด</q-tooltip>
</q-btn>
</q-td>
<q-td v-for="col in props.cols" :key="col.id">
<div v-if="col.name === 'no'">
{{ props.rowIndex + 1 }}
</div>
<div class="col-12">
<d-table
:columns="columns"
:rows="rows"
row-key="id"
:visible-columns="visibleColumns"
>
<template v-slot:header="props">
<q-tr :props="props">
<q-th auto-width />
<q-th v-for="col in props.cols" :key="col.name" :props="props">
<span class="text-weight-medium">{{ col.label }}</span>
</q-th>
</q-tr>
</template>
<template v-slot:body="props">
<q-tr :props="props">
<q-td auto-width>
<q-btn
v-if="checkPermission($route)?.attrIsGet"
flat
dense
round
color="info"
icon="mdi-eye"
@click.stop.prevent="
router.push(`/placement/transfer/${props.row.id}`)
"
>
<q-tooltip>รายละเอยด</q-tooltip>
</q-btn>
</q-td>
<q-td v-for="col in props.cols" :key="col.id">
<div v-if="col.name === 'no'">
{{ props.rowIndex + 1 }}
</div>
<div
v-else-if="col.name === 'organizationPositionOld'"
class="text-html"
>
{{ props.row.organizationPositionOld ?? "-" }}
</div>
<div
v-else-if="col.name === 'organizationPositionOld'"
class="text-html"
>
{{ props.row.organizationPositionOld ?? "-" }}
</div>
<div v-else>
{{
col.value == null ? "" : col.value == "" ? "-" : col.value
}}
</div>
</q-td>
</q-tr>
</template>
</d-table>
</div>
<div v-else>
{{
col.value == null ? "" : col.value == "" ? "-" : col.value
}}
</div>
</q-td>
</q-tr>
</template>
</d-table>
</div>
</div>
</q-card>

View file

@ -7,6 +7,7 @@ import axios from "axios";
import { useRoute } from "vue-router";
import { useCounterMixin } from "@/stores/mixin";
import { useStructureTree } from "@/stores/structureTree";
import { calculateFiscalYear } from "@/utils/function";
import http from "@/plugins/http";
import config from "@/app.config";
@ -56,7 +57,7 @@ const optionReport = ref<DataTypeReport[]>([
type: "probation",
},
]);
const year = ref<number>(new Date().getFullYear());
const year = ref<number>(calculateFiscalYear(new Date()));
const dateStart = ref<Date>(new Date(year.value - 1, 9, 1));
const dateEnd = ref<Date>(new Date(year.value + 1, 8, 30));
@ -188,7 +189,7 @@ function clearFilter() {
detailReport.value = undefined;
pdfSrc.value = undefined;
year.value = new Date().getFullYear();
year.value = calculateFiscalYear(new Date());
dateStart.value = new Date(year.value - 1, 9, 1);
dateEnd.value = new Date(year.value + 1, 8, 30);
}

View file

@ -20,4 +20,17 @@ interface QuestionDesc {
question10Desc: string;
}
export type { OptionQuestions, OptionQuestions2,QuestionDesc };
interface FilterRetirementOld {
type: string;
retireYear: number;
citizenID: string;
firstNameTH: string;
lastNameTH: string;
}
export type {
OptionQuestions,
OptionQuestions2,
QuestionDesc,
FilterRetirementOld,
};

View file

@ -68,7 +68,33 @@ interface SeqTypeRow {
keycloakId: string;
approveStatus: string;
comment: string;
rejectDate: Date|null;
rejectDate: Date | null;
}
interface RetirementOld {
dataRecords: DataRecords[];
rowPerPage: number;
startRecord: number;
totalRecords: number;
}
interface DataRecords {
citizenID: string;
firstNameTH: string;
lastNameTH: string;
organizeID: string;
organizeNameTH: string;
positionID: string;
positionLevelID: string;
positionLevelNameTH: string;
positionNameTH: string;
positionTypeID: string;
positionTypeNameTH: string;
recordRow: number;
retireDate: string;
retireTypeID: string;
retireTypeNameTH: string;
retireYear: string;
}
export type {
@ -79,5 +105,7 @@ export type {
FileList,
CheckBoxType,
RowsType,
SeqTypeRow
SeqTypeRow,
RetirementOld,
DataRecords,
};

View file

@ -66,9 +66,11 @@ const outDetailOnlyEmp = () =>
import("@/modules/06_retirement/components/06_dismissOrder/DetailEMP.vue");
/** รายงาน*/
const ReportView = () => import("@/modules/06_retirement/views/07_report.vue");
const RetirementOld = () =>
import("@/modules/06_retirement/views/09_retirementOld.vue");
export default [
{
path: "/retirement",
@ -356,4 +358,15 @@ export default [
Role: "STAFF",
},
},
{
path: "retire-old",
name: "retireOld",
component: RetirementOld,
meta: {
Auth: true,
Key: "SYS_RETIRE_OLD",
Role: "STAFF",
},
},
];

View file

@ -7,6 +7,7 @@ import { useRouter } from "vue-router";
import { useCounterMixin } from "@/stores/mixin";
import { useDataStoreRetirement } from "@/modules/06_retirement/store/storeRetirement";
import { checkPermission } from "@/utils/permissions";
import { calculateFiscalYear } from "@/utils/function";
import http from "@/plugins/http";
import config from "@/app.config";
@ -24,10 +25,7 @@ const { clickTab } = useStoreRetire;
const { messageError, date2Thai, showLoader, hideLoader, onSearchDataTable } =
mixin;
const fiscalyear = ref<number>(); //
const yearOptionsFilter = ref<any>({
yearOptions: [],
});
const fiscalyear = ref<number>(calculateFiscalYear(new Date())); //
const actionOption = ref<resMain[]>([]);
const pagination = ref({
@ -90,10 +88,9 @@ const columns = ref<QTableProps["columns"]>([
]);
// ()
const currentYear = new Date().getFullYear();
const currentYear = calculateFiscalYear(new Date());
const rows = ref<resMain[]>([]);
const rowsData = ref<resMain[]>([]);
const yearOptions = ref<any>([{ id: "", year: "ทั้งหมด" }]);
//
async function fetchRetirement(type: string, year: any) {
@ -103,52 +100,30 @@ async function fetchRetirement(type: string, year: any) {
.get(config.API.retirement(type, year))
.then((res) => {
let data = res.data.result;
const listData = data.map((items: any) => ({
id: items.id,
signDate: date2Thai(items.signDate) ?? "-",
Date: date2Thai(items.createdAt),
year: items.year + 543,
retireNumber: items.round,
total: items.total,
round: items.round,
typeReport: typeReportChangeName(items.typeReport), //
json: items.json,
document: items.document,
}));
rows.value = listData;
rowsData.value = listData;
let option: any[] = [];
data.map((items: any) => {
option.push({
id: items.year,
year: (items.year + 543).toString(),
if (data.length !== 0) {
const listData = data.map((items: any) => ({
id: items.id,
signDate: date2Thai(items.signDate) ?? "-",
Date: date2Thai(items.createdAt),
year: items.year + 543,
retireNumber: items.round,
total: items.total,
round: items.round,
typeReport: typeReportChangeName(items.typeReport), //
});
});
yearOptions.value = [{ id: 0, year: "ทั้งหมด" }];
// yearOptions.value.push(...option);
if (option.length !== 0) {
const double_name = [...new Set(option.map((item: any) => item.id))];
for (let i = 1; i <= double_name.length; i++) {
const type = double_name[i - 1];
const listtype = {
id: type,
year: (Number(type) + 543).toString(),
};
yearOptions.value.push(listtype);
}
}
yearOptionsFilter.value = yearOptions.value;
if (yearOptionsFilter.value.length == 1) {
fiscalyear.value = yearOptionsFilter.value[0].id;
json: items.json,
document: items.document,
}));
rows.value = listData;
rowsData.value = listData;
actionOption.value = rows.value;
rows.value.sort((a, b) => a.round - b.round); //
checkststus(rows.value);
} else {
fiscalyear.value = year;
rows.value = [];
rowsData.value = [];
actionOption.value = [];
checkjson.value = false;
}
actionOption.value = rows.value;
rows.value.sort((a, b) => a.round - b.round); //
checkststus(rows.value);
})
.catch((e) => {
messageError($q, e);
@ -171,25 +146,6 @@ function checkststus(data: any) {
const filterKeyword = ref<string>("");
const filterRef = ref<any>(null);
/** reset ฟิลเตอร์ */
function resetFilter() {
filterKeyword.value = "";
filterRef.value.focus();
}
/**
* งชนฟลเตอร input
* @param val input
* @param update Function quasar
*/
function filterSelector(val: any, update: Function) {
update(() => {
yearOptions.value = yearOptionsFilter.value.filter(
(v: any) => v.year.indexOf(val) > -1
);
});
}
/**
* ไปหนาแกไขรายละเอยด
* @param prop อม
@ -270,40 +226,41 @@ onMounted(async () => {
<div class="col-12 row q-pa-md q-col-gutter-sm">
<div class="row col-12">
<div class="row col-12 q-col-gutter-sm">
<q-select
<datepicker
v-model="fiscalyear"
label="ปีงบประมาณ"
dense
emit-value
map-options
:options="yearOptions"
option-value="id"
option-label="year"
lazy-rules
hide-selected
fill-input
use-input
hide-bottom-space
:readonly="false"
:borderless="false"
:outlined="true"
@filter="(inputValue:any,
doneFn:Function) => filterSelector(inputValue, doneFn
) "
:hide-dropdown-icon="false"
style="min-width: 150px"
style="width: 150px"
:locale="'th'"
autoApply
year-picker
:enableTimePicker="false"
:max-date="`${calculateFiscalYear(new Date())}, 12, 31`"
@update:model-value="fetchRetirement(type, fiscalyear)"
>
<template v-slot:no-option>
<q-item>
<q-item-section class="text-grey">
ไมอม
</q-item-section>
</q-item>
<template #year="{ year }">{{ year + 543 }}</template>
<template #year-overlay-value="{ value }">{{
parseInt(value + 543)
}}</template>
<template #trigger>
<q-input
dense
outlined
hide-bottom-space
:model-value="
fiscalyear === null ? 'ทั้งหมด' : Number(fiscalyear) + 543
"
:label="`${'ปีพ.ศ.'}`"
>
</q-input>
</template>
</q-select>
</datepicker>
<!-- use-input -->
<div v-if="checkPermission($route)?.attrIsCreate">
<div
v-if="
checkPermission($route)?.attrIsCreate &&
fiscalyear === currentYear
"
>
<popupAdd
:type="useStoreRetire.type"
:year="fiscalyear"
@ -387,7 +344,8 @@ onMounted(async () => {
<q-btn
v-if="
checkPermission($route)?.attrIsGet &&
checkPermission($route)?.attrIsUpdate
checkPermission($route)?.attrIsUpdate &&
fiscalyear === currentYear
"
flat
round

View file

@ -7,6 +7,7 @@ import axios from "axios";
import { useRoute } from "vue-router";
import { useStructureTree } from "@/stores/structureTree";
import { useCounterMixin } from "@/stores/mixin";
import { calculateFiscalYear } from "@/utils/function";
import http from "@/plugins/http";
import config from "@/app.config";
import genReportXLSX from "@/plugins/genreportxlsx";
@ -48,7 +49,7 @@ const filterTypeOption = ref<DataOption[]>([
{ id: "MONTH", name: "รายเดือน" },
{ id: "YEAR", name: "รายปี" },
]);
const year = ref<number>(new Date().getFullYear());
const year = ref<number>(calculateFiscalYear(new Date()));
const dateMonth = ref<DataDateMonthObject>({
month: new Date().getMonth(),
year: new Date().getFullYear(),
@ -203,7 +204,7 @@ function clearFilter() {
reportType.value = "";
filterType.value = "MONTH";
year.value = new Date().getFullYear();
year.value = calculateFiscalYear(new Date());
dateMonth.value = {
month: new Date().getMonth(),
year: new Date().getFullYear(),

View file

@ -0,0 +1,384 @@
<script setup lang="ts">
import { ref, onMounted, computed } from "vue";
import { useQuasar } from "quasar";
import http from "@/plugins/http";
import config from "@/app.config";
import { useCounterMixin } from "@/stores/mixin";
import { usePagination } from "@/composables/usePagination";
import type { QTableColumn } from "quasar";
import type { DataOption } from "@/modules/06_retirement/interface/index/Main";
import type { FilterRetirementOld } from "@/modules/06_retirement/interface/request/Main";
import type {
RetirementOld,
DataRecords,
} from "@/modules/06_retirement/interface/response/Main";
const $q = useQuasar();
const { showLoader, hideLoader, messageError } = useCounterMixin();
const { pagination, params, onRequest } = usePagination(
"",
fetchDataRetirement
);
/** Title Page */
const titlePage = computed(() => {
return `ข้อมูลผู้พ้นราชการก่อนปี ${new Date().getFullYear() + 543}`;
});
const optionStatusMain = ref<DataOption[]>([
{ name: "ข้าราชการ", id: "officer" },
{ name: "ลูกจ้างชั่วคราว", id: "employee" },
]);
const optionStatus = ref<DataOption[]>(optionStatusMain.value);
/** Filter */
const filter = ref<FilterRetirementOld>({
type: "officer",
retireYear: new Date().getFullYear() - 1,
citizenID: "",
firstNameTH: "",
lastNameTH: "",
});
const rows = ref<DataRecords[]>([]); //
const columns = ref<QTableColumn[]>([
{
name: "recordRow",
align: "left",
label: "ลำดับ",
sortable: false,
field: "recordRow",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "citizenID",
align: "left",
label: "เลขบัตรประชาชน",
sortable: false,
field: "citizenID",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "fullName",
align: "left",
label: "ชื่อ-นามสกุล",
sortable: false,
field: "fullName",
format(val, row) {
return `${row.firstNameTH} ${row.lastNameTH}`;
},
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "positionNameTH",
align: "left",
label: "ตำแหน่ง",
sortable: false,
field: "positionNameTH",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "positionTypeNameTH",
align: "left",
label: "ตำแหน่งประเภท",
sortable: false,
field: "positionTypeNameTH",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "positionLevelNameTH",
align: "left",
label: "ระดับ",
sortable: false,
field: "positionLevelNameTH",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "organizeNameTH",
align: "left",
label: "สังกัด",
sortable: false,
field: "organizeNameTH",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "retireYear",
align: "left",
label: "ปีที่พ้น",
sortable: false,
field: "retireYear",
format(val, row) {
return val ? (Number(val) + 543).toString() : "-";
},
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "retireTypeNameTH",
align: "left",
label: "เหตุผลของการพ้นจากตำแหน่ง",
sortable: false,
field: "retireTypeNameTH",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
]);
/** ฟังก์ชันสำหรับดึงข้อมูลผู้พ้นราชการ */
async function fetchDataRetirement() {
showLoader();
try {
const response = await http.post(config.API.exRetirement, {
page: params.value.page,
type: filter.value.type,
retireYear: filter.value.retireYear.toString(),
citizenID: filter.value.citizenID,
firstNameTH: filter.value.firstNameTH.trim(),
lastNameTH: filter.value.lastNameTH.trim(),
});
const data: RetirementOld = response.data.data;
pagination.value.rowsNumber = data.totalRecords;
rows.value = data.dataRecords;
} catch (error) {
messageError($q, error);
} finally {
hideLoader();
}
}
/**
* งกนสำหรบกรองตวเลอกสถานะ
* @param inputValue าทกรอกในชองคนหา
* @param doneFn งกนทเรยกเมอกรองเสร
*/
function filterOption(inputValue: string, doneFn: Function) {
const needle = inputValue.toLowerCase();
optionStatus.value = optionStatusMain.value.filter(
(v) => v.name.toLowerCase().indexOf(needle) > -1
);
doneFn();
}
/** ฟังก์ชันสำหรับค้นหาข้อมูลผู้พ้นราชการ */
function searchData() {
pagination.value.page = 1; // Reset to first page on new search
fetchDataRetirement();
}
/** ฟังก์ชันสำหรับรีเซ็ตตัวกรอง */
function resetFilter() {
filter.value = {
type: "officer",
retireYear: new Date().getFullYear() - 1,
citizenID: "",
firstNameTH: "",
lastNameTH: "",
};
pagination.value = {
page: 1,
rowsPerPage: 25,
rowsNumber: 0,
};
rows.value = [];
}
onMounted(() => {
pagination.value.rowsPerPage = 25;
});
</script>
<template>
<div class="toptitle text-dark col-12 row items-center">
{{ titlePage }}
</div>
<!-- Filter Section -->
<q-form greedy @submit.prevent @validation-success="searchData">
<q-card class="q-mb-sm" flat bordered>
<q-card-section>
<div class="row q-col-gutter-md">
<!-- Position Type -->
<div class="col-12 col-md-6 col-lg-3">
<div class="row q-col-gutter-sm">
<!-- Type of Position -->
<div class="col">
<q-select
v-model="filter.type"
label="ประเภทตำแหน่ง"
option-label="name"
:options="optionStatus"
option-value="id"
dense
emit-value
map-options
outlined
use-input
hide-selected
fill-input
readonly
@filter="(inputValue:string,doneFn:Function) => filterOption(inputValue, doneFn)"
class="full-width"
>
<template v-slot:no-option>
<q-item>
<q-item-section class="text-grey">
ไมอม
</q-item-section>
</q-item>
</template>
</q-select>
</div>
<!-- Retirement Year -->
<div class="col">
<datepicker
menu-class-name="modalfix"
v-model="filter.retireYear"
:locale="'th'"
autoApply
year-picker
:enableTimePicker="false"
:max-date="`${new Date().getFullYear() - 1}, 11, 31`"
>
<template #year="{ year }">{{ year + 543 }}</template>
<template #year-overlay-value="{ value }">{{
parseInt(value + 543)
}}</template>
<template #trigger>
<q-input
dense
outlined
:model-value="Number(filter.retireYear) + 543"
label="ปีที่ออกจากราชการ"
bg-color="white"
class="full-width"
>
<template v-slot:prepend>
<q-icon name="event" color="primary" />
</template>
</q-input>
</template>
</datepicker>
</div>
</div>
</div>
<!-- Citizen ID -->
<div class="col-12 col-md-6 col-lg-3">
<q-input
outlined
v-model="filter.citizenID"
dense
label="เลขบัตรประชาชน"
hide-bottom-space
maxlength="13"
mask="#############"
>
</q-input>
</div>
<!-- Name Filters -->
<div class="col-12 col-md-6 col-lg-3">
<q-input
outlined
v-model="filter.firstNameTH"
dense
label="ชื่อ"
hide-bottom-space
>
</q-input>
</div>
<div class="col-12 col-md-6 col-lg-3">
<q-input
outlined
v-model="filter.lastNameTH"
dense
label="นามสกุล"
hide-bottom-space
>
</q-input>
</div>
<!-- Search Actions -->
<div class="row col-12 justify-end">
<div class="row col-md-6 col-lg-3 q-gutter-sm full-height">
<q-space />
<q-btn
color="primary"
icon="search"
label="ค้นหา"
no-caps
type="submit"
/>
<q-btn
color="grey-6"
icon="refresh"
label="รีเซ็ต"
@click="resetFilter"
outline
no-caps
/>
</div>
</div>
</div>
</q-card-section>
</q-card>
</q-form>
<!-- Results Section -->
<q-card flat bordered>
<q-card-section>
<p-table
ref="table"
:columns="columns"
:rows="rows"
row-key="personId"
flat
bordered
:paging="true"
dense
class="custom-header-table"
:rows-per-page-options="[25]"
v-model:pagination="pagination"
@request="onRequest"
>
<template v-slot:header="props">
<q-tr :props="props">
<q-th
v-for="col in props.cols"
:key="col.name"
:props="props"
style="color: #000000; font-weight: 500"
>
<span class="text-weight-medium">{{ col.label }}</span>
</q-th>
</q-tr>
</template>
<template v-slot:body="props">
<q-tr :props="props" class="cursor-pointer">
<q-td v-for="col in props.cols" :key="col.name" :props="props">
<div v-if="col.name == 'no'">
{{ props.rowIndex + 1 }}
</div>
<div>
{{ col.value ?? "-" }}
</div>
</q-td>
</q-tr>
</template>
</p-table>
</q-card-section>
</q-card>
</template>
<style scoped></style>

View file

@ -58,15 +58,6 @@ const expanded = ref<string[]>([]);
const filters = ref<string>(""); //
const rowsPosition = ref<Position[]>([]); //
const columns = ref<QTableProps["columns"]>([
{
name: "isPosition",
align: "left",
label: "",
sortable: true,
field: "isPosition",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "no",
align: "left",
@ -203,7 +194,6 @@ const columnsPostition = ref<QTableProps["columns"]>([
// },
]);
const visibleColumns = ref<string[]>([
"isPosition",
"no",
"posMasterNo",
"positionName",
@ -661,6 +651,7 @@ onBeforeMount(async () => {
>
<template v-slot:header="props">
<q-tr :props="props">
<q-th auto-width />
<q-th
v-for="col in props.cols"
:key="col.name"
@ -674,6 +665,17 @@ onBeforeMount(async () => {
</template>
<template v-slot:body="props">
<q-tr :props="props" class="cursor-pointer">
<q-td auto-width>
<div v-if="props.row.isPosition">
<q-icon
name="done"
color="primary"
size="24px"
>
<q-tooltip>ตรงตามตำแหน </q-tooltip>
</q-icon>
</div>
</q-td>
<q-td
v-for="col in props.cols"
:key="col.name"
@ -700,17 +702,6 @@ onBeforeMount(async () => {
<q-tooltip>อำนวยการ/วหน</q-tooltip>
</q-icon>
</div>
<div v-else-if="col.name === 'isPosition'">
<div v-if="col.value">
<q-icon
name="done"
color="primary"
size="24px"
>
<q-tooltip>ตรงตามตำแหน </q-tooltip>
</q-icon>
</div>
</div>
<div v-else>
{{ col.value ? col.value : "-" }}

View file

@ -1,297 +0,0 @@
<script setup lang="ts">
import { ref, watch } from "vue";
import { useQuasar } from "quasar";
import axios from "axios";
import http from "@/plugins/http";
import config from "@/app.config";
import { useCounterMixin } from "@/stores/mixin";
/** importType*/
import type {
DataOption,
DataDateMonthObject,
} from "@/modules/09_leave/interface/index/Main";
/** importComponents*/
import Header from "@/components/DialogHeader.vue";
/** use*/
const mixin = useCounterMixin();
const $q = useQuasar();
const { date2Thai, monthYear2Thai, dateToISO, messageError } = mixin;
// const apiGenReport =
// "https://report-server.frappet.synology.me/api/v1/report-template/xlsx";
const props = defineProps({
modal: {
type: Boolean,
requier: true,
default: false,
},
close: {
type: Function,
requier: true,
},
});
const loadingBtn = ref<boolean>(true);
const filterType = ref<string>("DAY");
const filterTypeMain = ref<DataOption[]>([
{ id: "DAY", name: "รายวัน" },
{ id: "MONTH", name: "รายเดือน" },
]);
const filterTypeOption = ref<DataOption[]>(filterTypeMain.value);
const date = ref<Date>(new Date());
const dateMonth = ref<DataDateMonthObject>({
month: new Date().getMonth(),
year: new Date().getFullYear(),
});
const detailReport = ref<any>();
/** function อัปเดทรายงานสถิติการลา*/
async function updateFilterType() {
filterType.value === "DAY"
? updateDte()
: filterType.value === "MONTH"
? updateMonth()
: false;
}
/** function อัปเดทวัน*/
async function updateDte() {
const body = {
startDate: dateToISO(date.value),
endDate: dateToISO(date.value),
type: filterType.value,
};
fetchReportTimeRecords(body);
}
/** function อัปเดทเดือน*/
async function updateMonth() {
const mount = dateMonth.value.month + 1;
//
const firstDay = new Date(dateMonth.value.year, mount - 1, 1);
//
const lastDay = new Date(dateMonth.value.year, mount, 0);
const body = {
startDate: dateToISO(firstDay),
endDate: dateToISO(lastDay),
type: filterType.value,
};
fetchReportTimeRecords(body);
}
/**
* function เรยกขอมลรายงานสถการลา
* @param body นเรมตนและสนส
*/
async function fetchReportTimeRecords(body: any) {
loadingBtn.value = true;
await http
.post(config.API.leaveReportTimeRecords(), body)
.then((res) => {
const data = res.data.result;
detailReport.value = data;
})
.catch((err) => {
messageError($q, err);
})
.finally(() => {
setTimeout(() => {
loadingBtn.value = false;
}, 500);
});
}
/**
* function filterOption
* @param val คำคนหา
* @param update functoin
*/
function filterFnOptions(val: any, update: Function) {
update(() => {
filterTypeOption.value = filterTypeMain.value.filter(
(v: DataOption) => v.name.indexOf(val) > -1
);
});
}
/**
* function เรยกไฟล XLSX
* @param data อมลรายงานสถการลา
*/
async function genReportXLSX(data: any) {
await axios
.post(`${config.API.reportTemplate}/xlsx`, data, {
headers: {
accept:
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
"content-Type": "application/json",
},
responseType: "blob",
})
.then(async (res) => {
const blob = new Blob([res.data]);
await downloadReport(blob, "xlsx");
})
.catch(async (e) => {
messageError($q, JSON.parse(await e.response.data.text()));
});
}
/**
*
* @param data อมลรายงานสถการลา
* @param type นามสกลไฟล
*/
async function downloadReport(data: any, type: string) {
const link = document.createElement("a");
var fileName = "รายงานสรุปบันทึกการลงเวลาปฏิบัติงาน";
link.href = window.URL.createObjectURL(new Blob([data]));
link.setAttribute("download", `${fileName}.${type}`);
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
function monthYearThai(val: DataDateMonthObject) {
if (val == null) return "";
else return monthYear2Thai(val.month, val.year);
}
watch(
() => props.modal,
() => {
filterType.value = "DAY";
date.value = new Date();
props.modal && updateFilterType();
}
);
</script>
<template>
<q-dialog v-model="props.modal" persistent>
<q-card style="width: 700px; max-width: 100vw">
<Header :close="props.close" :tittle="'รายงานสถิติการลงเวลา'" />
<q-separator />
<q-card-section class="q-pt-none" style="padding: 0px">
<div class="q-pa-sm q-gutter-y-sm">
<q-toolbar class="q-pa-sm bg-grey-2" style="border-radius: 5px">
<div class="q-pr-xs col-4">
<q-select
class="bg-white"
outlined
dense
v-model="filterType"
:options="filterTypeOption"
emit-value
map-options
option-label="name"
option-value="id"
@update:model-value="updateFilterType"
@filter="(inputValue: any,
doneFn: Function) => filterFnOptions(inputValue, doneFn,)"
>
<template v-slot:no-option>
<q-item>
<q-item-section class="text-grey">
ไมอม
</q-item-section>
</q-item>
</template>
</q-select>
</div>
<div class="q-pr-xs col-4" v-if="filterType === 'DAY'">
<datepicker
menu-class-name="modalfix"
v-model="date"
:locale="'th'"
autoApply
:enableTimePicker="false"
week-start="0"
@update:model-value="updateDte"
>
<template #year="{ year }">{{ year + 543 }}</template>
<template #year-overlay-value="{ value }">{{
parseInt(value + 543)
}}</template>
<template #trigger>
<q-input
class="bg-white"
outlined
dense
borderless
:model-value="date ? date2Thai(date) : null"
:label="`${'วันที่'}`"
>
<template v-slot:prepend>
<q-icon
name="event"
class="cursor-pointer"
color="primary"
>
</q-icon>
</template>
</q-input>
</template>
</datepicker>
</div>
<div class="q-pr-xs col-4" v-if="filterType === 'MONTH'">
<datepicker
v-model="dateMonth"
:locale="'th'"
autoApply
month-picker
:enableTimePicker="false"
@update:model-value="updateMonth"
>
<template #year="{ year }">{{ year + 543 }}</template>
<template #year-overlay-value="{ value }">{{
parseInt(value + 543)
}}</template>
<template #trigger>
<q-input
class="bg-white"
outlined
dense
borderless
:label="`${'เดือน'}`"
:model-value="monthYearThai(dateMonth)"
>
<template v-slot:prepend>
<q-icon
name="event"
class="cursor-pointer"
color="primary"
></q-icon>
</template>
</q-input>
</template>
</datepicker>
</div>
<div class="q-pr-xs col-4">
<q-btn
:loading="loadingBtn"
:disable="loadingBtn"
color="primary"
icon="download"
label="ดาวน์โหลดรายงาน"
@click="genReportXLSX(detailReport)"
style="width: 100%"
>
<q-tooltip>ดาวนโหลดรายงาน</q-tooltip>
</q-btn>
</div>
</q-toolbar>
</div>
</q-card-section>
</q-card>
</q-dialog>
</template>
<style scoped></style>

View file

@ -7,6 +7,7 @@ import http from "@/plugins/http";
import config from "@/app.config";
import { useCounterMixin } from "@/stores/mixin";
import { useLeaveHistoryDataStore } from "@/modules/09_leave/stores/LeaveHistoryStore";
import { calculateFiscalYear } from "@/utils/function";
import type { QTableColumn } from "quasar";
import type {
@ -19,6 +20,7 @@ import type {
} from "@/modules/09_leave/interface/response/leaveHistory";
import DialogHeader from "@/components/DialogHeader.vue";
import { max } from "moment";
/** useStore*/
const $q = useQuasar();
@ -78,7 +80,7 @@ const profileId = ref<string>("");
const rowId = ref<string>("");
const formData = reactive({
leaveTypeId: "", //
leaveYear: findYear(new Date()), //
leaveYear: calculateFiscalYear(new Date()), //
leaveDays: "", //
leaveDaysUsed: "", //
});
@ -191,7 +193,7 @@ function onClose() {
formFilter.page = 1;
formFilter.pageSize = 10;
formData.leaveTypeId = "";
formData.leaveYear = new Date().getFullYear();
formData.leaveYear = calculateFiscalYear(new Date());
formData.leaveDays = "";
formData.leaveDaysUsed = "";
rows.value = [];
@ -399,8 +401,7 @@ watch(modal, async (val) => {
autoApply
year-picker
:enableTimePicker="false"
@update:model-value="onSearchData"
readonly
:max-date="`${calculateFiscalYear(new Date())}, 12, 31`"
>
<template #year="{ year }">{{ year + 543 }}</template>
<template #year-overlay-value="{ value }">{{
@ -408,7 +409,6 @@ watch(modal, async (val) => {
}}</template>
<template #trigger>
<q-input
readonly
dense
outlined
:model-value="Number(formData.leaveYear) + 543"

View file

@ -5,6 +5,7 @@ import type { QTableProps } from "quasar";
import http from "@/plugins/http";
import config from "@/app.config";
import { useCounterMixin } from "@/stores/mixin";
import { calculateFiscalYear } from "@/utils/function";
/** importType*/
import type { DataProfilePosition } from "@/interface/response/main";
@ -28,7 +29,7 @@ export const useLeavelistDataStore = defineStore("leave", () => {
const tabView = ref<string>("list");
/** filter*/
const filter = reactive<DateFilter>({
year: new Date().getFullYear(), //*ปีในการยื่นขอใบลา(ใช้เป็น คศ.)
year: calculateFiscalYear(new Date()), //*ปีในการยื่นขอใบลา(ใช้เป็น คศ.)
type: "00000000-0000-0000-0000-000000000000", //*Id ประเภทการลา
status: "ALL", //*สถานะการของลา
keyword: "", //keyword ค้นหา

View file

@ -1,676 +0,0 @@
<script setup lang="ts">
import { ref, onMounted } from "vue";
import { useQuasar } from "quasar";
import { VuePDF, usePDF } from "@tato30/vue-pdf";
import axios from "axios";
import { useRoute } from "vue-router";
import { useStructureTree } from "@/stores/structureTree";
import { useCounterMixin } from "@/stores/mixin";
import { checkPermission } from "@/utils/permissions";
import http from "@/plugins/http";
import config from "@/app.config";
import genReportXLSX from "@/plugins/genreportxlsx";
import genReportDocx from "@/plugins/genreport";
import type { DataStructureTree } from "@/interface/main";
import type {
DataOption,
DataDateMonthObject,
} from "@/modules/09_leave/interface/index/Main";
import LoadView from "@/components/LoadView.vue";
const $q = useQuasar();
const route = useRoute();
const {
date2Thai,
monthYear2Thai,
dateToISO,
messageError,
showLoader,
hideLoader,
} = useCounterMixin();
const { fetchStructureTree } = useStructureTree();
/** filter*/
const typeReport = ref<string>("");
const optionReport = ref<DataOption[]>([
{ id: "1", name: "รายงานการเข้างาน" },
{ id: "2", name: "รายงานการเข้างานสาย" },
]);
const employeeClass = ref<string>("officer");
const employeeClassOption = ref<DataOption[]>([
{ id: "officer", name: "ข้าราชการ กทม. สามัญ" },
{ id: "employee", name: "ลูกจ้างประจำ กทม." },
]);
const filterType = ref<string>("DAY");
const filterTypeMain = ref<DataOption[]>([
{ id: "DAY", name: "รายวัน" },
{ id: "WEEKLY", name: "รายสัปดาห์" },
{ id: "MONTH", name: "รายเดือน" },
]);
const filterTypeOption = ref<DataOption[]>(filterTypeMain.value);
const date = ref<Date>(new Date());
const dateWeek = ref<Date[]>(getCurrentWeek());
const dateMonth = ref<DataDateMonthObject>({
month: new Date().getMonth(),
year: new Date().getFullYear(),
});
const isLoadPDF = ref<boolean>(false);
/** tree*/
const filterTree = ref<string>("");
const nodeId = ref<string>("");
const nodeLevel = ref<number>(0);
const node = ref<DataStructureTree[]>([]);
const expanded = ref<string[]>([]);
/** report*/
const numOfPages = ref<number>(0);
const page = ref<number>(1);
const pdfSrc = ref<any>();
const detailReport = ref<any>();
const isReport = ref<boolean>(false);
/** กลับหน้าก่อนหน้าของรายงาน */
function backPage() {
if (page.value !== 1) {
page.value--;
}
}
/** ไปหน้าต่อไปของรายงาน */
function nextPage() {
if (page.value < numOfPages.value) {
page.value++;
}
}
async function fetchDataTree() {
node.value = await fetchStructureTree(route.meta.Key as string, true);
}
function onSelectedNode(id: string, level: number) {
nodeId.value = id;
nodeLevel.value = level;
updateFilterType(filterType.value);
}
/** function อัปเดทรายงานสถิติการลา*/
async function updateFilterType(type: string) {
if (!nodeId.value || !typeReport.value) {
return false;
}
let body = {};
isReport.value = false;
isLoadPDF.value = true;
pdfSrc.value = undefined;
page.value = 1;
switch (type) {
case "DAY":
body = {
startDate: dateToISO(date.value),
endDate: dateToISO(date.value),
type: filterType.value,
nodeId: nodeId.value,
node: nodeLevel.value,
};
break;
case "WEEKLY":
const startOfWeek = new Date(dateWeek.value[0]); // index 0
const endOfWeek = new Date(dateWeek.value[1]);
body = {
startDate: dateToISO(startOfWeek),
endDate: dateToISO(endOfWeek),
type: filterType.value,
nodeId: nodeId.value,
node: nodeLevel.value,
};
break;
case "MONTH":
const mount = dateMonth.value.month + 1;
//
const firstDay = new Date(dateMonth.value.year, mount - 1, 1);
//
const lastDay = new Date(dateMonth.value.year, mount, 0);
body = {
startDate: dateToISO(firstDay),
endDate: dateToISO(lastDay),
type: filterType.value,
nodeId: nodeId.value,
node: nodeLevel.value,
};
break;
default:
break;
}
typeReport.value === "1"
? fetchReportTimeRecords(body)
: fetchReportTimeLate(body);
}
/**
* function เรยกขอมลรายงานการเขางาน
* @param body นเรมตนและสนส
*/
async function fetchReportTimeRecords(body: any) {
await http
.post(config.API.leaveReportTimeRecords(employeeClass.value), body)
.then(async (res) => {
const data = res.data.result;
detailReport.value = data;
isReport.value = data ? true : false;
await fetchDocumentTemplate(data);
})
.catch((err) => {
messageError($q, err);
})
.finally(() => {
isLoadPDF.value = false;
});
}
/**
* function เรยกขอมลรายงานการเขางานสาย
* @param body นเรมตนและสนส
*/
async function fetchReportTimeLate(body: any) {
await http
.post(config.API.leaveReportTimeLate(employeeClass.value), body)
.then(async (res) => {
const data = res.data.result;
detailReport.value = data;
isReport.value = data ? true : false;
await fetchDocumentTemplate(data);
})
.catch((err) => {
messageError($q, err);
})
.finally(() => {
isLoadPDF.value = false;
});
}
/**
* function เรยกไฟล XLSX
* @param data อมลรายงานสถการลา
*/
async function fetchDocumentTemplate(data: any) {
await axios
.post(`${config.API.reportTemplate}/xlsx?`, data, {
headers: {
accept: "application/pdf",
"content-Type": "application/json",
},
responseType: "blob",
})
.then(async (res) => {
const blob = new Blob([res.data]);
const objectUrl = URL.createObjectURL(blob);
const pdfData = await usePDF(`${objectUrl}`);
// PDF
setTimeout(async () => {
pdfSrc.value = pdfData.pdf.value;
numOfPages.value = pdfData.pages.value;
}, 1500);
})
.catch(async (e) => {
messageError($q, JSON.parse(await e.response.data.text()));
});
}
/**
* function filterOption
* @param val คำคนหา
* @param update functoin
*/
function filterFnOptions(val: string, update: Function) {
update(() => {
filterTypeOption.value = filterTypeMain.value.filter(
(v: DataOption) => v.name.indexOf(val) > -1
);
});
}
function monthYearThai(val: DataDateMonthObject) {
if (val == null) return "";
else return monthYear2Thai(val.month, val.year);
}
function formatWeekDisplay(week: Date[]) {
if (week) {
if (!week[0] || !week[1]) return "";
return `${date2Thai(week[0])} - ${date2Thai(week[1])}`;
}
}
/** ฟังก์ชันคำนวณวันเริ่มต้นและวันสิ้นสุดของสัปดาห์นี้ */
function getCurrentWeek() {
const today = new Date();
const firstDayOfWeek = new Date(today);
firstDayOfWeek.setDate(today.getDate() - today.getDay() + 1); //
const lastDayOfWeek = new Date(today);
lastDayOfWeek.setDate(today.getDate() - today.getDay() + 7); //
return [firstDayOfWeek, lastDayOfWeek];
}
function downloadReport(type: string) {
const fileName =
typeReport.value === "1" ? "รายงานการเข้างาน" : "รายงานการเข้างานสาย";
// if (type === "pdf") {
// genReportDocx(detailReport.value, fileName, type);
// } else {
genReportXLSX(detailReport.value, fileName, type);
// }
}
onMounted(() => {
fetchDataTree();
});
</script>
<template>
<div class="toptitle text-dark col-12 row items-center">
รายงานสถการลงเวลา
</div>
<div class="q-pa-sm q-gutter-sm">
<q-card flat bordered class="col-12">
<div class="row q-col-gutter-sm q-pa-sm">
<div class="row col-12">
<div class="row q-col-gutter-sm">
<q-select
outlined
dense
v-model="employeeClass"
:options="employeeClassOption"
label="ประเภทตำแหน่ง"
emit-value
map-options
option-label="name"
option-value="id"
@update:model-value="updateFilterType(filterType)"
>
</q-select>
</div>
<q-space />
<!-- @click.stop.prevent="
genReportXLSX(
detailReport,
`${
typeReport === '1'
? 'รายงานการเข้างาน'
: 'รายงานการเข้างานสาย'
}`
)
" -->
<q-btn
v-if="checkPermission($route)?.attrIsGet"
flat
:disable="!isReport || !nodeId || !employeeClass"
:loading="isLoadPDF"
round
color="primary"
icon="download"
>
<q-menu>
<q-list style="min-width: 150px">
<q-item clickable v-close-popup @click="downloadReport('pdf')">
<q-item-section avatar
><q-icon color="red" name="mdi-file-pdf"
/></q-item-section>
<q-item-section>ไฟล .pdf</q-item-section>
</q-item>
<q-item clickable v-close-popup @click="downloadReport('xlsx')">
<q-item-section avatar
><q-icon color="green" name="mdi-file-excel"
/></q-item-section>
<q-item-section>ไฟล .xlsx</q-item-section>
</q-item>
</q-list>
</q-menu>
</q-btn>
</div>
<div class="col-12 row">
<q-card bordered class="col-12 filter-card q-pa-sm">
<div class="row col-12 q-col-gutter-sm">
<div class="col-lg-2 col-md-4 col-xs-12">
<q-select
class="bg-white"
hide-bottom-space
outlined
dense
lazy-rules
borderless
v-model="typeReport"
:label="`${'รายงาน'}`"
emit-value
map-options
:options="optionReport"
option-value="id"
option-label="name"
@update:model-value="updateFilterType(filterType)"
/>
</div>
<div class="col-lg-2 col-md-4 col-xs-12" v-if="typeReport">
<q-select
class="bg-white"
outlined
dense
v-model="filterType"
:options="filterTypeOption"
emit-value
map-options
option-label="name"
option-value="id"
@update:model-value="updateFilterType"
@filter="(inputValue: string,
doneFn: Function) => filterFnOptions(inputValue, doneFn,)"
>
<template v-slot:no-option>
<q-item>
<q-item-section class="text-grey">
ไมอม
</q-item-section>
</q-item>
</template>
</q-select>
</div>
<div
class="col-lg-2 col-md-4 col-xs-12"
v-if="filterType === 'DAY' && typeReport"
>
<datepicker
v-model="date"
:locale="'th'"
autoApply
:enableTimePicker="false"
week-start="0"
@update:model-value="updateFilterType('DAY')"
>
<template #year="{ year }">{{ year + 543 }}</template>
<template #year-overlay-value="{ value }">{{
parseInt(value + 543)
}}</template>
<template #trigger>
<q-input
class="bg-white"
outlined
dense
borderless
:model-value="date ? date2Thai(date) : null"
:label="`${'วันที่'}`"
>
<template v-slot:prepend>
<q-icon
name="event"
class="cursor-pointer"
color="primary"
>
</q-icon>
</template>
</q-input>
</template>
</datepicker>
</div>
<div
class="col-lg-2 col-md-4 col-xs-12"
v-if="filterType === 'WEEKLY' && typeReport"
>
<datepicker
v-model="dateWeek"
:locale="'th'"
autoApply
:enableTimePicker="false"
@update:model-value="updateFilterType('WEEKLY')"
week-picker
>
<template #year="{ year }">{{ year + 543 }}</template>
<template #year-overlay-value="{ value }">{{
parseInt(value + 543)
}}</template>
<template #trigger>
<q-input
class="bg-white"
outlined
dense
borderless
:label="`${'รายสัปดาห์'}`"
:model-value="formatWeekDisplay(dateWeek)"
>
<template v-slot:prepend>
<q-icon
name="event"
class="cursor-pointer"
color="primary"
></q-icon>
</template>
</q-input>
</template>
</datepicker>
</div>
<div
class="col-lg-2 col-md-4 col-xs-12"
v-if="filterType === 'MONTH' && typeReport"
>
<datepicker
v-model="dateMonth"
:locale="'th'"
autoApply
month-picker
:enableTimePicker="false"
@update:model-value="updateFilterType('MONTH')"
>
<template #year="{ year }">{{ year + 543 }}</template>
<template #year-overlay-value="{ value }">{{
parseInt(value + 543)
}}</template>
<template #trigger>
<q-input
class="bg-white"
outlined
dense
borderless
:label="`${'เดือน'}`"
:model-value="monthYearThai(dateMonth)"
>
<template v-slot:prepend>
<q-icon
name="event"
class="cursor-pointer"
color="primary"
></q-icon>
</template>
</q-input>
</template>
</datepicker>
</div>
</div>
</q-card>
</div>
</div>
</q-card>
<q-card flat bordered class="col-12">
<q-card-section :horizontal="$q.screen.gt.sm">
<q-card-section class="col-lg-3 col-md-4 col-xs-12 q-gutter-sm">
<div class="col">
<q-input dense outlined v-model="filterTree" label="ค้นหา">
<template v-slot:append>
<q-icon name="search" />
</template>
</q-input>
</div>
<div class="bg-white tree-container q-pa-xs">
<q-tree
dense
:nodes="node"
node-key="orgTreeId"
label-key="labelName"
v-model:expanded="expanded"
:filter="filterTree.trim()"
no-results-label="ไม่พบข้อมูลที่ค้นหา"
no-nodes-label="ไม่มีข้อมูล"
>
<template v-slot:default-header="prop">
<q-item
@click.stop="
onSelectedNode(prop.node.orgTreeId, prop.node.orgLevel)
"
:active="nodeId === prop.node.orgTreeId"
clickable
active-class="my-list-link text-primary text-weight-medium"
class="row col-12 items-center text-dark q-py-xs q-pl-sm rounded-borders my-list"
>
<div>
<div class="text-weight-medium">
{{ prop.node.orgTreeName }}
</div>
<div class="text-weight-light text-grey-8">
{{ prop.node.orgCode == null ? null : prop.node.orgCode }}
{{
prop.node.orgTreeShortName == null
? null
: prop.node.orgTreeShortName
}}
</div>
</div>
</q-item>
</template>
</q-tree>
</div>
</q-card-section>
<q-separator :vertical="$q.screen.gt.xs" />
<q-card-section class="col-lg-9 col-md-8 col-xs-12 scroll">
<q-splitter
horizontal
style="
height: 65vh;
border: 1px solid rgb(210, 210, 210);
border-radius: 5px;
"
before-class="overflow-hidden disable"
separator-class="bg-white disabled"
>
<template v-slot:before>
<div class="q-px-sm">
<div class="row items-start items-center">
<div class="col">
<q-btn
padding="xs"
icon="mdi-chevron-left"
color="grey-2"
text-color="grey-5"
size="md"
class="my-auto"
@click="backPage"
:disable="page == 1"
/>
</div>
<div class="col-12 col-md-auto">
<div class="q-pa-md flex">
หนาท {{ page }} จาก {{ numOfPages }}
</div>
</div>
<div class="col text-right">
<q-btn
padding="xs"
icon="mdi-chevron-right"
color="grey-2"
text-color="grey-5"
size="md"
@click="nextPage"
:disable="page === numOfPages"
/>
</div>
</div>
</div>
</template>
<template v-slot:after>
<div class="q-pa-md">
<LoadView v-if="isLoadPDF" />
<VuePDF
v-else
ref="vuePDFRef"
:pdf="pdfSrc"
:page="page"
fit-parent
/>
</div>
</template>
<template v-slot:default>
<div class="q-pa-md">
<div class="row items-start items-center">
<div class="col">
<q-btn
padding="xs"
icon="mdi-chevron-left"
color="grey-2"
text-color="grey-5"
size="md"
class="my-auto"
@click="backPage"
:disable="page == 1"
/>
</div>
<div class="col-12 col-md-auto">
<div class="q-pa-md flex">
หนาท {{ page }} จาก {{ numOfPages }}
</div>
</div>
<div class="col text-right">
<q-btn
padding="xs"
icon="mdi-chevron-right"
color="grey-2"
text-color="grey-5"
size="md"
@click="nextPage"
:disable="page === numOfPages"
/>
</div>
</div>
</div>
</template>
</q-splitter>
</q-card-section>
</q-card-section>
</q-card>
</div>
</template>
<style scoped>
.tree-container {
overflow: auto;
height: 60vh;
border: 1px solid #e6e6e7;
border-radius: 10px;
}
.my-list-link {
color: rgb(118, 168, 222);
border-radius: 5px;
background: #a3d3fb48 !important;
font-weight: 600;
border: 1px solid rgba(175, 185, 196, 0.217);
}
</style>

View file

@ -4,7 +4,6 @@ import { ref } from "vue";
/** import Components */
import Tab1 from "@/modules/09_leave/components/02_WorkList/Tab1.vue";
import Tab2 from "@/modules/09_leave/components/02_WorkList/Tab2.vue";
// import DialogReport from "@/modules/09_leave/components/02_WorkList/DialogReport.vue";
const tab = ref("1");

View file

@ -8,6 +8,7 @@ import { useRoute } from "vue-router";
import { checkPermission } from "@/utils/permissions";
import { useCounterMixin } from "@/stores/mixin";
import { useStructureTree } from "@/stores/structureTree";
import { calculateFiscalYear } from "@/utils/function";
import genReportXLSX from "@/plugins/genreportxlsx";
import http from "@/plugins/http";
@ -15,6 +16,7 @@ import config from "@/app.config";
import type { DataStructureTree } from "@/interface/main";
import type {
DataOption,
DataOption2,
DataDateMonthObject,
} from "@/modules/09_leave/interface/index/Main";
@ -39,7 +41,7 @@ const {
hideLoader,
} = useCounterMixin();
const year = ref<number>(new Date().getFullYear());
const year = ref<number>(calculateFiscalYear(new Date()));
const dateStart = ref<Date>(new Date(year.value - 1, 9, 1));
const dateEnd = ref<Date>(new Date(year.value + 1, 8, 30));
@ -53,43 +55,28 @@ const pageName = ref<string>(route.name as string);
const dateWeek = ref<Date[]>(getCurrentWeek());
const date = ref<Date>(new Date());
const typeReport = ref<string>("");
const optionReport = ref<DataOption[]>([]);
const optionReportMain = ref<DataOption[]>(
const typeReport = ref<number | null>(null);
const optionReport = ref<DataOption2[]>([
{
id: 3,
name: "รายงานการเข้างาน",
},
{
id: 4,
name: "รายงานการเข้างานสาย",
},
{ id: 1, name: "รายงานการลางานตามประเภทการลา" },
{
id: 2,
name: "รายงานการลางาน จำแนกตามเพศ ประเภทการลา หน่วยงาน/ส่วนราชการ",
},
]);
const optionReportMain = ref<DataOption2[]>(
route.name?.toString() === "reportLeave"
? [
{
id: "3",
name: "รายงานการเข้างาน",
},
{
id: "4",
name: "รายงานการเข้างานสาย",
},
{ id: "1", name: "รายงานการลางานตามประเภทการลา" },
{
id: "2",
name: "รายงานการลางาน จำแนกตามเพศ ประเภทการลา หน่วยงาน/ส่วนราชการ",
},
]
? optionReport.value
: route.name?.toString() === "leaveReport"
? [
{ id: "1", name: "รายงานการลางานตามประเภทการลา" },
{
id: "2",
name: "รายงานการลางาน จำแนกตามเพศ ประเภทการลา หน่วยงาน/ส่วนราชการ",
},
]
: [
{
id: "3",
name: "รายงานการเข้างาน",
},
{
id: "4",
name: "รายงานการเข้างานสาย",
},
]
? optionReport.value.filter((item) => item.id === 1 || item.id === 2)
: optionReport.value.filter((item) => item.id === 3 || item.id === 4)
);
const employeeClass = ref<string>("officer");
@ -157,7 +144,7 @@ function onSelectedNode(data: any) {
*/
async function updateLeaveday() {
const list =
typeReport.value == "3" || typeReport.value == "4"
typeReport.value == 3 || typeReport.value == 4
? leaveType.value
: yearType.value;
switch (list) {
@ -250,11 +237,11 @@ async function fetchLeaveday(
};
const pathAPI =
typeReport.value === "1"
typeReport.value === 1
? config.API.leaveReportLeaveday(type)
: typeReport.value === "2"
: typeReport.value === 2
? config.API.leaveReportLeave2(type)
: typeReport.value === "3"
: typeReport.value === 3
? config.API.leaveReportTimeRecords(type)
: config.API.leaveReportTimeLate(type);
@ -348,13 +335,13 @@ function clearData() {
nodeId.value = "";
nodeLevel.value = 0;
org.value = "";
typeReport.value = "";
typeReport.value = null;
yearType.value = "FULL";
leaveType.value = "DAY";
pdfSrc.value = undefined;
detailReport.value = undefined;
year.value = new Date().getFullYear();
year.value = calculateFiscalYear(new Date());
dateMonth.value = {
month: new Date().getMonth(),
year: new Date().getFullYear(),
@ -369,7 +356,7 @@ function onSearch() {
updateLeaveday();
fetchLeaveday(
employeeClass.value,
typeReport.value == "3" || typeReport.value == "4"
typeReport.value == 3 || typeReport.value == 4
? leaveType.value
: yearType.value,
dateStart.value,
@ -388,7 +375,7 @@ function getCurrentWeek() {
}
function updateValue(val: string) {
if (typeReport.value == "3" || typeReport.value == "4") {
if (typeReport.value == 3 || typeReport.value == 4) {
leaveType.value = val;
} else {
yearType.value = val;
@ -408,7 +395,7 @@ const isLoad = ref<boolean>(false);
* @param isName อไฟล
* @param fileType pdf/xlsx
*/
function getReport(isName: string) {
function getReport() {
showLoader();
const body = {
type:
@ -448,7 +435,7 @@ function getReport(isName: string) {
//
const link = document.createElement("a");
link.href = url;
link.download = `${isName}.xlsx`; //
link.download = `${reportName()}.xlsx`; //
document.body.appendChild(link);
link.click();
@ -463,6 +450,19 @@ function getReport(isName: string) {
hideLoader();
});
}
const reportName = () => {
const employeeClassName =
employeeClass.value === "officer"
? " (ข้าราชการ กทม. สามัญ)"
: " (ลูกจ้างประจำ กทม.)";
const reportNameVal =
optionReportMain.value.find((item) => item.id === typeReport.value)?.name ||
"";
return reportNameVal + employeeClassName;
};
onMounted(() => {
fetchDataTree();
});
@ -508,7 +508,7 @@ onMounted(() => {
round
color="primary"
icon="download"
v-if="checkPermission($route)?.attrIsGet && typeReport !== '3'"
v-if="checkPermission($route)?.attrIsGet && typeReport !== 3"
>
<q-menu>
<q-list style="min-width: 150px">
@ -516,23 +516,7 @@ onMounted(() => {
clickable
v-close-popup
@click="
genReportXLSX(
detailReport,
`${
typeReport === '1'
? `รายงานการลางานตามประเภทการลา (${
employeeClass === 'officer'
? 'ข้าราชการ กทม. สามัญ'
: 'ลูกจ้างประจำ กทม.'
})`
: `รายงานการลางาน จำแนกตามเพศ ประเภทการลา หน่วยงาน/ส่วนราชการ (${
employeeClass === 'officer'
? 'ข้าราชการ กทม. สามัญ'
: 'ลูกจ้างประจำ กทม.'
})`
}`,
'pdf'
)
genReportXLSX(detailReport, `${reportName()}`, 'pdf')
"
>
<q-item-section avatar
@ -543,24 +527,7 @@ onMounted(() => {
<q-item
clickable
v-close-popup
@click="
genReportXLSX(
detailReport,
`${
typeReport === '1'
? `รายงานการลางานตามประเภทการลา (${
employeeClass === 'officer'
? 'ข้าราชการ กทม. สามัญ'
: 'ลูกจ้างประจำ กทม.'
})`
: `รายงานการลางาน จำแนกตามเพศ ประเภทการลา หน่วยงาน/ส่วนราชการ (${
employeeClass === 'officer'
? 'ข้าราชการ กทม. สามัญ'
: 'ลูกจ้างประจำ กทม.'
})`
}`
)
"
@click="genReportXLSX(detailReport, `${reportName()}`)"
>
<q-item-section avatar
><q-icon color="green" name="mdi-file-excel"
@ -576,16 +543,8 @@ onMounted(() => {
round
color="primary"
icon="download"
v-if="checkPermission($route)?.attrIsGet && typeReport == '3'"
@click="
getReport(
`${`รายงานการลางาน จำแนกตามเพศ ประเภทการลา หน่วยงาน/ส่วนราชการ (${
employeeClass === 'officer'
? 'ข้าราชการ กทม. สามัญ'
: 'ลูกจ้างประจำ กทม.'
})`}`
)
"
v-if="checkPermission($route)?.attrIsGet && typeReport == 3"
@click="getReport()"
>
</q-btn>
</div>
@ -743,12 +702,12 @@ onMounted(() => {
class="bg-white"
dense
:model-value="
typeReport == '3' || typeReport == '4'
typeReport == 3 || typeReport == 4
? leaveType
: yearType
"
:options="
typeReport == '3' || typeReport == '4'
typeReport == 3 || typeReport == 4
? leaveTypeOptionOption
: yearTypeOptionOption
"
@ -764,8 +723,8 @@ onMounted(() => {
class="col-12"
v-if="
yearType !== 'MONTH' &&
typeReport !== '3' &&
typeReport !== '4'
typeReport !== 3 &&
typeReport !== 4
"
>
<datepicker
@ -804,8 +763,8 @@ onMounted(() => {
class="col-12"
v-if="
yearType !== 'MONTH' &&
typeReport !== '3' &&
typeReport !== '4'
typeReport !== 3 &&
typeReport !== 4
"
>
<datepicker
@ -847,8 +806,8 @@ onMounted(() => {
class="col-12"
v-if="
yearType !== 'MONTH' &&
typeReport !== '3' &&
typeReport !== '4'
typeReport !== 3 &&
typeReport !== 4
"
>
<datepicker
@ -884,15 +843,7 @@ onMounted(() => {
</template>
</datepicker>
</div>
<div
class="col-12"
v-if="
(typeReport == '1' && yearType == 'MONTH') ||
(typeReport == '2' && yearType == 'MONTH') ||
(typeReport == '3' && leaveType == 'MONTH') ||
(typeReport == '4' && leaveType == 'MONTH')
"
>
<div class="col-12" v-if="yearType == 'MONTH'">
<datepicker
v-model="dateMonth"
:locale="'th'"
@ -924,15 +875,7 @@ onMounted(() => {
</template>
</datepicker>
</div>
<div
class="col-12"
v-if="
(typeReport == '1' && yearType == 'WEEKLY') ||
(typeReport == '2' && yearType == 'WEEKLY') ||
(typeReport == '3' && leaveType == 'WEEKLY') ||
(typeReport == '4' && leaveType == 'WEEKLY')
"
>
<div class="col-12" v-if="leaveType == 'WEEKLY'">
<datepicker
v-model="dateWeek"
:locale="'th'"
@ -966,8 +909,8 @@ onMounted(() => {
<div
class="col-12"
v-if="
(leaveType == 'DAY' && typeReport == '3') ||
(leaveType == 'DAY' && typeReport == '4')
(leaveType == 'DAY' && typeReport == 3) ||
(leaveType == 'DAY' && typeReport == 4)
"
>
<datepicker
@ -1007,7 +950,7 @@ onMounted(() => {
<q-separator />
<q-card-actions align="right">
<q-btn
v-if="typeReport !== '3'"
v-if="typeReport !== 3"
dense
class="q-px-md"
label="ค้นหา"
@ -1016,9 +959,7 @@ onMounted(() => {
type="submit"
:disable="
typeReport &&
(typeReport == '2' ||
typeReport == '3' ||
typeReport == '4') &&
(typeReport == 2 || typeReport == 3 || typeReport == 4) &&
org
"
/>
@ -1027,7 +968,7 @@ onMounted(() => {
</div>
<div class="col-lg-9 col-md-9 col-sm-9 col-xs-12 col-xs-12 flex">
<q-splitter
v-if="typeReport !== '3'"
v-if="typeReport !== 3"
disable
v-model="splitterModel"
horizontal

View file

@ -9,6 +9,7 @@ import { checkPermission } from "@/utils/permissions";
import { updateCurrentPage } from "@/utils/function";
import { useCounterMixin } from "@/stores/mixin";
import { useLeaveHistoryDataStore } from "@/modules/09_leave/stores/LeaveHistoryStore";
import { calculateFiscalYear } from "@/utils/function";
import type { QTableColumn } from "quasar";
import type { DataPagination } from "@/modules/09_leave/interface/index/Main";
@ -26,7 +27,7 @@ const { showLoader, hideLoader, messageError, dialogRemove, success } =
useCounterMixin();
const formFilter = reactive({
year: findYear(new Date()),
year: calculateFiscalYear(new Date()),
type: "00000000-0000-0000-0000-000000000000",
page: 1,
pageSize: 10,

View file

@ -8,6 +8,7 @@ import config from "@/app.config";
import { useCounterMixin } from "@/stores/mixin";
import { useDisciplineResultStore } from "@/modules/11_discipline/store/ResultStore";
import { useDisciplineMainStore } from "@/modules/11_discipline/store/Main";
import { calculateFiscalYear } from "@/utils/function";
import type {
FormData,
@ -106,7 +107,7 @@ const formData = reactive<FormData>({
oc: "",
file: null,
disciplineDisciplinary_DocResults: [],
year: new Date().getFullYear(),
year: calculateFiscalYear(new Date()),
});
/** maping ref เข้าตัวแปรเพื่อเตรียมตรวจสอบ */
@ -826,10 +827,7 @@ watch(
@update:modal="updatemodalPersonal"
/>
<DialogHistory
v-model:modal="modalHistory"
v-model:person-id="personalId"
/>
<DialogHistory v-model:modal="modalHistory" v-model:person-id="personalId" />
</template>
<style scoped>

View file

@ -9,6 +9,7 @@ import config from "@/app.config";
import { useCounterMixin } from "@/stores/mixin";
import { useAppealComplainStore } from "@/modules/11_discipline/store/AppealComplainStore";
import { useDisciplineMainStore } from "@/modules/11_discipline/store/Main";
import { calculateFiscalYear } from "@/utils/function";
import type {
MyObjectAppealRef,
@ -75,7 +76,7 @@ const formData = reactive<any>({
file: null,
disciplineComplaint_Appeal_Docs: [],
historyStatus: historyStatusOb,
year: new Date().getFullYear().toString(),
year: calculateFiscalYear(new Date()).toString(),
});
/** ตัวแปร validate */

View file

@ -8,6 +8,7 @@ import { useQuasar } from "quasar";
import { useCounterMixin } from "@/stores/mixin";
import { useAppealComplainStore } from "@/modules/11_discipline/store/AppealComplainStore";
import { checkPermission } from "@/utils/permissions";
import { calculateFiscalYear } from "@/utils/function";
import type { QTableProps } from "quasar";
import type { RowList } from "@/modules/11_discipline/interface/response/appealComplain";
@ -36,7 +37,7 @@ const dataRow = ref<RowList[]>([]);
const formData = reactive<any>({
type: "ALL",
status: "NEW",
year: new Date().getFullYear().toString(),
year: calculateFiscalYear(new Date()).toString(),
});
const total = ref<number>(0);

View file

@ -8,6 +8,7 @@ import genReportXLSX from "@/plugins/genreportxlsx";
import http from "@/plugins/http";
import config from "@/app.config";
import { usePagination } from "@/composables/usePagination";
import { calculateFiscalYear } from "@/utils/function";
/** importType*/
import type {
@ -36,7 +37,7 @@ const organization = ref<string>("");
const organizationOpsMain = ref<DataOption[]>([]);
const organizationOps = ref<DataOption[]>([]);
const year = ref<number>(new Date().getFullYear());
const year = ref<number>(calculateFiscalYear(new Date()));
const modalReport = ref<boolean>(false); // popup report
const loadingBtn = ref<boolean>(false); // popup report
const filter = ref<string>(""); //

View file

@ -1,10 +1,11 @@
<script setup lang="ts">
import { ref, reactive, onMounted, watch } from "vue";
import { ref, onMounted } from "vue";
import { useQuasar } from "quasar";
import { checkPermission } from "@/utils/permissions";
import { updateCurrentPage } from "@/utils/function";
import { usePagination } from "@/composables/usePagination";
import http from "@/plugins/http";
import config from "@/app.config";
import { useQuasar } from "quasar";
/** importType*/
import type { QTableProps } from "quasar";
@ -12,10 +13,7 @@ import type {
ListData,
ResponseData,
} from "@/modules/13_salary/interface/index/EmployeeChart";
import type {
NewPagination,
DataOption,
} from "@/modules/13_salary/interface/index/Main";
import type { DataOption } from "@/modules/13_salary/interface/index/Main";
import type { PosType } from "@/modules/13_salary/interface/response/salaryEmployeeChart";
/** importCompopnents*/
@ -27,8 +25,12 @@ import { useCounterMixin } from "@/stores/mixin";
const $q = useQuasar();
const { dialogRemove, messageError, showLoader, hideLoader, success } =
useCounterMixin();
const { pagination, params, onRequest, checkAndUpdatePage } = usePagination(
"",
getData
);
/** ข้อมูล Table*/
const keyword = ref<string>("");
const rows = ref<ListData[]>([]);
const columns = ref<QTableProps["columns"]>([
{
@ -44,16 +46,16 @@ const columns = ref<QTableProps["columns"]>([
name: "posType",
align: "left",
label: "กลุ่มงาน",
sortable: false,
sortable: true,
field: "posType",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "posName",
name: "position",
align: "left",
label: "ตำแหน่ง",
sortable: false,
sortable: true,
field: "posName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
@ -62,16 +64,16 @@ const columns = ref<QTableProps["columns"]>([
name: "posLevel",
align: "left",
label: "ระดับชั้นงาน",
sortable: false,
sortable: true,
field: "posLevel",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "rateOldMin",
name: "salaryMin",
align: "left",
label: "อัตราค่าจ้าง ขั้นต่ำสุด",
sortable: false,
sortable: true,
field: "rateOldMin",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
@ -86,37 +88,37 @@ const columns = ref<QTableProps["columns"]>([
style: "font-size: 14px",
},
{
name: "rateMaxOld",
name: "salary",
align: "left",
label: "อัตราค่าจ้าง ขั้นสูงสุดเดิม",
sortable: false,
sortable: true,
field: "rateMaxOld",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "groupRateHigh",
name: "group",
align: "left",
label: "อัตราค่าจ้างสูงกว่า ฯ กลุ่มบัญชีค่าจ่าง",
sortable: false,
sortable: true,
field: "groupRateHigh",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "rateHighMax",
name: "salaryMax",
align: "left",
label: "อัตราค่าจ้างสูงกว่า ฯ ขั้นสูงใหม่",
sortable: false,
sortable: true,
field: "rateHighMax",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "reson",
name: "details",
align: "left",
label: "หมายเหตุ",
sortable: false,
sortable: true,
field: "reson",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
@ -125,22 +127,15 @@ const columns = ref<QTableProps["columns"]>([
const visibleColumns = ref<string[]>([
"no",
"posType",
"posName",
"position",
"posLevel",
"rateOldMin",
"salaryMin",
"groupOld",
"rateMaxOld",
"groupRateHigh",
"rateHighMax",
"reson",
"salary",
"group",
"salaryMax",
"details",
]);
const formFilter = reactive({
page: 1,
pageSize: 10,
keyword: "",
});
const maxPage = ref<number>(1); //
const totalList = ref<number>(0); //
const modalForm = ref<boolean>(false); //Popup
const isStatusEdit = ref<boolean>(false); //
@ -151,11 +146,6 @@ const posTypeOpMain = ref<DataOption[]>([]); //ข้อมูลกลุ่ม
const posTypeOp = ref<DataOption[]>([]); //
const posType = ref<string | null>(""); //
const pagination = ref({
page: formFilter.page,
rowsPerPage: formFilter.pageSize,
});
/** ดึงข้อมูลกลุ่มงาน*/
async function getPosType() {
await http
@ -184,18 +174,19 @@ async function getPosType() {
/** ดึงข้อมูลรายการหลักเกณฑ์ */
async function getData() {
showLoader();
await http
.get(
config.API.salaryFormula() +
`/?page=${formFilter.page}&pageSize=${
formFilter.pageSize
}&keyword=${formFilter.keyword.trim()}&posTypeId=${posType.value}`
)
.get(config.API.salaryFormula(), {
params: {
...params.value,
keyword: keyword.value.trim(),
posTypeId: posType.value,
},
})
.then((res) => {
const data = res.data.result.data;
totalList.value = res.data.result.total;
maxPage.value = Math.ceil(res.data.result.total / formFilter.pageSize);
rows.value = data.map((item: ResponseData) => ({
const result = res.data.result;
pagination.value.rowsNumber = result.total;
rows.value = result.data.map((item: ResponseData) => ({
id: item.id,
posType: item.posType,
posName: item.position,
@ -210,6 +201,9 @@ async function getData() {
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
hideLoader();
});
}
@ -224,28 +218,6 @@ function editPopup(params: ListData, type: string) {
dataRow.value = params;
}
/**
* function fetch อมลรายการตามหน
* @param val หน
*/
async function updatePage(val: number) {
try {
showLoader();
formFilter.page = val;
await getData();
} catch (error) {
messageError($q, error);
} finally {
hideLoader();
}
}
/** function อัปเดทแถวต่อหน้า*/
function updatePageSize(newPagination: NewPagination) {
formFilter.page = 1;
formFilter.pageSize = newPagination.rowsPerPage;
}
/**
* ลบรายการหลกเกณฑ
* @param id หลกเกณฑ
@ -256,11 +228,7 @@ function onClickDelete(id: string) {
await http
.delete(config.API.salaryFormula() + `/${id}`)
.then(async () => {
formFilter.page = await updateCurrentPage(
formFilter.page,
maxPage.value,
rows.value.length
);
await checkAndUpdatePage(rows.value.length);
await getData();
await success($q, "ลบข้อมูลสำเร็จ");
})
@ -288,25 +256,10 @@ function filterSelector(val: string, update: Function) {
/** function fetch ข้อมูลรายการหน้าแรก */
function filterFn() {
formFilter.page = 1;
pagination.value.page = 1;
getData();
}
/** callbackFunction ทำงานเมื่อมี่การอัปเดทแถว*/
watch(
() => formFilter.pageSize,
async () => {
try {
showLoader();
await getData();
} catch (error) {
messageError($q, error);
} finally {
hideLoader();
}
}
);
/** Hook */
onMounted(async () => {
try {
@ -372,9 +325,9 @@ onMounted(async () => {
borderless
dense
outlined
v-model="formFilter.keyword"
v-model="keyword"
placeholder="ค้นหา"
@keydown.enter.pervrnt="filterFn"
@keydown.enter.prevent="filterFn"
>
<template v-slot:append>
<q-icon name="search" />
@ -397,7 +350,7 @@ onMounted(async () => {
/>
</q-toolbar>
<d-table
<p-table
flat
bordered
dense
@ -408,7 +361,7 @@ onMounted(async () => {
v-model:pagination="pagination"
:rows-per-page-options="[10, 20, 50, 100]"
:visible-columns="visibleColumns"
@update:pagination="updatePageSize"
@request="onRequest"
>
<template v-slot:header="props">
<q-tr :props="props">
@ -462,17 +415,13 @@ onMounted(async () => {
</q-td>
<q-td v-for="col in props.cols" :key="col.name" :props="props">
<div v-if="col.name === 'no'">
{{
(formFilter.page - 1) * Number(pagination.rowsPerPage) +
props.rowIndex +
1
}}
{{ props.rowIndex + 1 }}
</div>
<div
v-else-if="
col.name == 'rateOldMin' ||
col.name == 'rateMaxOld' ||
col.name == 'rateHighMax'
col.name == 'salaryMin' ||
col.name == 'salary' ||
col.name == 'salaryMax'
"
>
{{ col.value ? col.value.toLocaleString() : "-" }}
@ -487,21 +436,7 @@ onMounted(async () => {
</q-td>
</q-tr>
</template>
<template v-slot:pagination="scope">
งหมด {{ totalList.toLocaleString() }} รายการ
<q-pagination
v-model="formFilter.page"
active-color="primary"
color="dark"
:max="maxPage"
:max-pages="5"
size="sm"
boundary-links
direction-links
@update:model-value="updatePage"
></q-pagination>
</template>
</d-table>
</p-table>
<DialogFormCriteria
v-model:modal="modalForm"

View file

@ -1,16 +1,15 @@
<script setup lang="ts">
import { ref, reactive, onMounted, watch } from "vue";
import { ref, onMounted } from "vue";
import { checkPermission } from "@/utils/permissions";
import { useQuasar } from "quasar";
import { useRouter } from "vue-router";
import http from "@/plugins/http";
import config from "@/app.config";
import { updateCurrentPage } from "@/utils/function";
import { usePagination } from "@/composables/usePagination";
/** importType*/
import type { QTableProps } from "quasar";
import type { NewPagination } from "@/modules/13_salary/interface/index/Main";
import type { FormFilter } from "@/modules/13_salary/interface/request/EmployeeChart";
import type { EmployeeSalary } from "@/modules/13_salary/interface/response/salaryEmployeeChart";
/** importComponents*/
@ -31,14 +30,10 @@ const {
hideLoader,
success,
} = useCounterMixin();
const formFilter = reactive<FormFilter>({
page: 1, //*
pageSize: 10, //*
keyword: "", //keyword
});
const maxPage = ref<number>(1); //
const totalList = ref<number>(0); //
const { pagination, params, onRequest, checkAndUpdatePage } = usePagination(
"",
fetchListChart
);
const modalDialogEmployeeChart = ref<boolean>(false); //popup
const isStatusEdit = ref<boolean>(false); //
@ -50,12 +45,13 @@ const isActive = ref<boolean>(false); //สถานะการใช้งา
/** ข้อมูล Table*/
const rows = ref<EmployeeSalary[]>([]); //
const keyword = ref<string>(""); //
const columns = ref<QTableProps["columns"]>([
{
name: "name",
align: "left",
label: "ชื่อผังบัญชีอัตราค่าจ้าง",
sortable: false,
sortable: true,
field: "name",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
@ -64,7 +60,7 @@ const columns = ref<QTableProps["columns"]>([
name: "group",
align: "left",
label: "กลุ่มของผังบัญชีอัตราค่าจ้าง",
sortable: false,
sortable: true,
field: "group",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
@ -73,7 +69,7 @@ const columns = ref<QTableProps["columns"]>([
name: "startDate",
align: "left",
label: "วันที่มีผลบังคับใช้",
sortable: false,
sortable: true,
field: "startDate",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
@ -82,7 +78,7 @@ const columns = ref<QTableProps["columns"]>([
name: "isActive",
align: "left",
label: "สถานะการใช้งาน",
sortable: false,
sortable: true,
field: "isActive",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
@ -101,16 +97,16 @@ const visibleColumns = ref<string[]>([
async function fetchListChart() {
showLoader();
await http
.get(
config.API.salaryEmployeeChart +
`?page=${formFilter.page}&pageSize=${
formFilter.pageSize
}&keyword=${formFilter.keyword.trim()}`
)
.get(config.API.salaryEmployeeChart, {
params: {
...params.value,
keyword: keyword.value.trim(),
},
})
.then((res) => {
rows.value = res.data.result.data;
totalList.value = res.data.result.total;
maxPage.value = Math.ceil(res.data.result.total / formFilter.pageSize);
const result = res.data.result;
pagination.value.rowsNumber = result.total;
rows.value = result.data;
})
.catch((err) => {
messageError($q, err);
@ -180,11 +176,7 @@ function onClickDelete(id: string) {
http
.delete(config.API.salaryEmployeeChartByid(id))
.then(async () => {
formFilter.page = await updateCurrentPage(
formFilter.page,
maxPage.value,
rows.value.length
);
await checkAndUpdatePage(rows.value.length);
await fetchListChart();
await success($q, "ลบข้อมูลสำเร็จ");
})
@ -205,37 +197,12 @@ function onClickAdd() {
modalDialogEmployeeChart.value = true;
}
/**
* functionn fetch อมลรายการหนาแรก*
*/
/** function fetch ข้อมูลรายการหน้าแรก*/
function filterFn() {
formFilter.page = 1;
pagination.value.page = 1;
fetchListChart();
}
/**
* function fetch อมลรายการตามหน
* @param val หน
*/
function updatePage(val: number) {
formFilter.page = val;
fetchListChart();
}
/** function อัปเดทแถวต่อหน้า*/
function updatePageSize(newPagination: NewPagination) {
formFilter.page = 1;
formFilter.pageSize = newPagination.rowsPerPage;
}
/** callbackFuntioon ทำงานเมื่อมี่การอัปเดทแถว */
watch(
() => formFilter.pageSize,
() => {
fetchListChart();
}
);
onMounted(() => {
fetchListChart();
});
@ -257,7 +224,7 @@ onMounted(() => {
borderless
dense
outlined
v-model="formFilter.keyword"
v-model="keyword"
placeholder="ค้นหา"
@keydown.enter.prevent="filterFn"
>
@ -281,7 +248,7 @@ onMounted(() => {
class="col-xs-12 col-sm-3 col-md-2 q-ml-sm"
/>
</q-toolbar>
<d-table
<p-table
flat
bordered
dense
@ -290,7 +257,8 @@ onMounted(() => {
row-key="name"
:rows-per-page-options="[10, 20, 50, 100]"
:visible-columns="visibleColumns"
@update:pagination="updatePageSize"
v-model:pagination="pagination"
@request="onRequest"
>
<template v-slot:header="props">
<q-tr :props="props">
@ -445,21 +413,7 @@ onMounted(() => {
</q-td>
</q-tr>
</template>
<template v-slot:pagination="scope">
งหมด {{ totalList.toLocaleString() }} รายการ
<q-pagination
v-model="formFilter.page"
active-color="primary"
color="dark"
:max="maxPage"
:max-pages="5"
size="sm"
boundary-links
direction-links
@update:model-value="updatePage"
></q-pagination>
</template>
</d-table>
</p-table>
<!-- ปโหลดเอกสารอางอ -->
<DialogEmployeeUpload

View file

@ -4,6 +4,7 @@ import { useQuasar } from "quasar";
import { useCounterMixin } from "@/stores/mixin";
import { useSalaryListSDataStore } from "@/modules/13_salary/store/SalaryListsStore";
import { usePagination } from "@/composables/usePagination";
import config from "@/app.config";
import http from "@/plugins/http";
@ -22,6 +23,7 @@ const $q = useQuasar();
const store = useSalaryListSDataStore();
const { messageError, showLoader, hideLoader, dialogConfirm, success } =
useCounterMixin();
const { pagination, params, onRequest } = usePagination("", fetchListPerson);
/** props*/
const modal = defineModel<boolean>("modal", { required: true });
@ -47,25 +49,25 @@ const columns = ref<QTableProps["columns"]>([
name: "citizenId",
align: "left",
label: "เลขประจำตัวประชาชน",
sortable: false,
sortable: true,
field: "citizenId",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "fullName",
name: "firstName",
align: "left",
label: "ชื่อ-นามสกุล",
field: "fullName",
sortable: false,
sortable: true,
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "posNo",
name: "orgShortName",
align: "left",
label: "เลขที่ตำแหน่ง",
sortable: false,
sortable: true,
field: "posNo",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
@ -79,7 +81,7 @@ const columns = ref<QTableProps["columns"]>([
name: "position",
align: "left",
label: "ตำแหน่งในสายงาน",
sortable: false,
sortable: true,
field: "position",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
@ -88,7 +90,7 @@ const columns = ref<QTableProps["columns"]>([
name: "posType",
align: "left",
label: "ประเภทตำเเหน่ง",
sortable: false,
sortable: true,
field: "posType",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
@ -97,7 +99,7 @@ const columns = ref<QTableProps["columns"]>([
name: "posLevel",
align: "left",
label: "ระดับตำเเหน่ง",
sortable: false,
sortable: true,
field: "posLevel",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
@ -105,38 +107,46 @@ const columns = ref<QTableProps["columns"]>([
]);
/** ข้อมูุลค้นหา*/
const formFilter = reactive<DataFilterPerson>({
page: 1,
pageSize: 10,
keyword: "",
rootId: "",
year: 0,
period: "",
});
const maxPage = ref<number>(1);
/**
* function close popup
*/
function closeModal() {
modal.value = false;
formFilter.page = 1;
formFilter.keyword = "";
rows.value = [];
pagination.value = {
page: 1,
rowsPerPage: 10,
sortBy: "",
descending: false,
};
}
/**
* function เรยกรายช คนเลอนเงนเดอน
*/
function fetchListPerson() {
async function fetchListPerson() {
showLoader();
formFilter.rootId = store.rootId;
formFilter.period = store.roundMainCode;
formFilter.year = store.roundYear;
http
.post(config.API.salaryListPerson, formFilter)
const body = {
...params.value,
...formFilter,
};
await http
.post(config.API.salaryListPerson, body)
.then((res) => {
const data = res.data.result.data;
maxPage.value = Math.ceil(res.data.result.total / formFilter.pageSize);
rows.value = data;
const result = res.data.result;
pagination.value.rowsNumber = result.total;
rows.value = result.data;
})
.catch((err) => {
messageError($q, err);
@ -180,32 +190,13 @@ function onClickAddPerson(data: DataPerson) {
);
}
/**
* function updatePage
*/
async function updatePagePagination() {
fetchListPerson();
}
/**
* function updatePageSize
*/
function updatePageSizePagination(newPagination: NewPagination) {
formFilter.page = 1;
formFilter.pageSize = newPagination.rowsPerPage;
}
/**
* function นหาขอมลตาม keyword
*/
/** function ค้นหาข้อมูล*/
function searchData() {
formFilter.page = 1;
pagination.value.page = 1;
fetchListPerson();
}
/**
* callblack function เรยกขอมลรายชอคนเลอนเงนเดอน เมอมการเป Popup
*/
/** callblack function เรียกข้อมูลรายชื่อคนเลื่อนเงินเดือน เมื่อมีการเปิด Popup*/
watch(
() => modal.value,
() => {
@ -214,17 +205,8 @@ watch(
}
}
);
/**
* callblack function เรยกขอมลรายชอคนเลอนเงนเดอน เมอมการเปลยน PageSize
*/
watch(
() => formFilter.pageSize,
() => {
updatePagePagination();
}
);
</script>
<template>
<q-dialog v-model="modal" persistent>
<q-card style="max-width: 100vw">
@ -248,7 +230,7 @@ watch(
</q-input>
</div>
<div class="col-12">
<d-table
<p-table
ref="table"
:columns="columns"
:rows="rows"
@ -258,7 +240,8 @@ watch(
:paging="true"
dense
:rows-per-page-options="[10, 25, 50, 100]"
@update:pagination="updatePageSizePagination"
v-model:pagination="pagination"
:onRequest="onRequest"
>
<template v-slot:header="props">
<q-tr :props="props">
@ -288,13 +271,9 @@ watch(
:props="props"
>
<div v-if="col.name === 'no'">
{{
(formFilter.page - 1) * formFilter.pageSize +
props.rowIndex +
1
}}
{{ props.rowIndex + 1 }}
</div>
<div v-else-if="col.name === 'fullName'">
<div v-else-if="col.name === 'firstName'">
{{
`${props.row.prefix}${props.row.firstName} ${props.row.lastName}`
}}
@ -305,35 +284,11 @@ watch(
</q-td>
</q-tr>
</template>
<template v-slot:pagination="scope">
<q-pagination
v-model="formFilter.page"
active-color="primary"
color="dark"
:max="Number(maxPage)"
:max-pages="5"
size="sm"
boundary-links
direction-links
@update:model-value="updatePagePagination()"
></q-pagination>
</template>
</d-table>
</p-table>
</div>
</div>
</q-card-section>
<q-separator />
<!-- <q-card-actions align="right" class="bg-white text-teal">
<q-btn
type="submit"
unelevated
dense
class="q-px-md items-center"
color="light-blue-10"
label="บันทึก"
/>
</q-card-actions> -->
</q-card>
</q-dialog>
</template>

View file

@ -5,10 +5,10 @@ import { useQuasar } from "quasar";
import http from "@/plugins/http";
import config from "@/app.config";
import genReportXLSX from "@/plugins/genreportxlsx";
import { usePagination } from "@/composables/usePagination";
/** importType*/
import type { DataOption } from "@/modules/13_salary/interface/index/Main";
import type { DataFilter } from "@/modules/13_salary/interface/index/SalaryList";
import type {
DataPeriodLatest,
DataPeriod,
@ -27,6 +27,10 @@ import { useSalaryListSDataStore } from "@/modules/13_salary/store/SalaryListsSt
const $q = useQuasar();
const store = useSalaryListSDataStore();
const { messageError, showLoader, hideLoader } = useCounterMixin();
const { pagination, params, onRequest, checkAndUpdatePage } = usePagination(
"",
() => fetchDataPeriod(store.groupId, true)
);
/** props*/
const props = defineProps({
@ -44,6 +48,8 @@ const rows = ref<DataPeriod[]>([]);
const modalDialogInfoCriteria = ref<boolean>(false); // Dialog
const isRetire = ref<boolean>(false); //
const keyword = ref<string>("");
/** itemsTab กลุ่ม*/
const itemsTabGroup = ref([
{
@ -210,15 +216,6 @@ const itemsCard = ref([
},
]);
/** ข้อมูลค้นหารายชื่อคนขึ้นเงินเดือน*/
const formFilter = reactive<DataFilter>({
page: 1,
pageSize: 10,
keyword: "",
type: store.tabType,
});
const maxPage = ref<number>(1); //
/**
* งกนเรยกขอมลโควต
* @param id กล
@ -255,11 +252,11 @@ async function fetchDataQuota(id: string) {
* งกนเรยกขอมลรายชอเลอนเงนเดอนขาราชการฯ
* @param id กล
*/
async function fetchDataPeriod(id: string) {
async function fetchDataPeriod(id: string, force: boolean = false) {
force && showLoader();
let formData = {
page: formFilter.page.toString(),
pageSize: formFilter.pageSize.toString(),
keyword: formFilter.keyword.trim(),
...params.value,
keyword: keyword.value.trim(),
type: store.tabType,
isRetire:
store.roundMainCode !== "OCT"
@ -268,17 +265,20 @@ async function fetchDataPeriod(id: string) {
? "1"
: "0",
};
rows.value = [];
await http
.put(config.API.salaryListPeriodORG(id), formData)
.then((res) => {
rows.value = res.data.result.data;
total.value = res.data.result.total;
maxPage.value = Math.ceil(res.data.result.total / formFilter.pageSize);
const result = res.data.result;
pagination.value.rowsNumber = result.total;
rows.value = result.data;
total.value = result.total;
})
.catch((err) => {
messageError($q, err);
rows.value = [];
})
.finally(() => {
force && hideLoader();
});
}
@ -287,9 +287,9 @@ async function changeTabGroup() {
showLoader();
try {
await Promise.all([
(formFilter.page = 1),
(formFilter.pageSize = 10),
(formFilter.keyword = ""),
(pagination.value.page = 1),
(pagination.value.rowsPerPage = 10),
(keyword.value = ""),
(store.tabType = "PENDING"),
props.periodLatest &&
store.fetchPeriodLatest(props?.periodLatest, store.tabGroup),
@ -309,9 +309,9 @@ async function changeTabType() {
if (!store.groupId) return;
showLoader();
try {
formFilter.page = 1;
formFilter.pageSize = 10;
formFilter.keyword = "";
pagination.value.page = 1;
pagination.value.rowsPerPage = 10;
keyword.value = "";
store.groupId && (await fetchDataPeriod(store.groupId));
} catch (error) {
messageError($q, error);
@ -671,24 +671,26 @@ onMounted(async () => {
<TableTabType1
v-if="index === 0"
:rows="rows"
v-model:maxPage="maxPage"
v-model:formFilter="formFilter"
:fetchDataTable="fetchDataPeriodNew"
:total="total"
:snap-shot="props?.snapShot"
:is-close="props.periodLatest?.group1IsClose ?? false"
:is-retire="isRetire"
v-model:pagination="pagination"
v-model:keyword="keyword"
:onRequest="onRequest"
:checkAndUpdatePage="checkAndUpdatePage"
/>
<TableTabType2
v-else
:rows="rows"
v-model:maxPage="maxPage"
v-model:formFilter="formFilter"
:fetchDataTable="fetchDataPeriodNew"
:total="total"
:type="item.type"
:snap-shot="props?.snapShot"
:is-close="props.periodLatest?.group1IsClose ?? false"
v-model:pagination="pagination"
v-model:keyword="keyword"
:onRequest="onRequest"
:checkAndUpdatePage="checkAndUpdatePage"
/>
</q-tab-panel>
</q-tab-panels>

View file

@ -1,15 +1,14 @@
<script setup lang="ts">
import { ref, watch, computed } from "vue";
import { ref, computed } from "vue";
import { useQuasar } from "quasar";
import { checkPermission } from "@/utils/permissions";
import { updateCurrentPage } from "@/utils/function";
import config from "@/app.config";
import http from "@/plugins/http";
/** importType*/
import type { QTableProps } from "quasar";
import type { NewPagination } from "@/modules/13_salary/interface/index/Main";
import type { DataFilter } from "@/modules/13_salary/interface/index/SalaryList";
/** importComponents*/
import DialogAddPerson from "@/modules/13_salary/components/04_salaryLists//DialogAddPerson.vue";
@ -28,10 +27,11 @@ const { dialogRemove, messageError, showLoader, hideLoader, success } =
useCounterMixin();
/** props*/
const formFilter = defineModel<DataFilter>("formFilter", { required: true });
const maxPage = defineModel<Number>("maxPage", { required: true });
const snapShot = defineModel<string>("snapShot");
const isClose = defineModel<boolean>("isClose", { required: true });
const pagination = defineModel<NewPagination>("pagination", {
required: true,
});
const keyword = defineModel<string>("keyword", { required: true });
const props = defineProps({
rows: { type: Array, required: true },
@ -47,6 +47,14 @@ const props = defineProps({
type: String,
required: true,
},
onRequest: {
type: Function,
required: true,
},
checkAndUpdatePage: {
type: Function,
required: true,
},
});
/** ข้อมูล Table*/
@ -62,20 +70,20 @@ const baseColumns = ref<QTableProps["columns"]>([
},
{
name: "fullName",
name: "firstName",
align: "left",
label: "ชื่อ-นามสกุล",
field: "fullName",
sortable: false,
field: "firstName",
sortable: true,
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "posNo",
name: "orgShortName",
align: "left",
label: "เลขที่ตำแหน่ง",
sortable: false,
field: "posNo",
sortable: true,
field: "orgShortName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
format(val, row) {
@ -88,7 +96,7 @@ const baseColumns = ref<QTableProps["columns"]>([
name: "position",
align: "left",
label: "ตำแหน่งในสายงาน",
sortable: false,
sortable: true,
field: "position",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
@ -97,7 +105,7 @@ const baseColumns = ref<QTableProps["columns"]>([
name: "posType",
align: "left",
label: "ตำแหน่งประเภท",
sortable: false,
sortable: true,
field: "posType",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
@ -106,7 +114,7 @@ const baseColumns = ref<QTableProps["columns"]>([
name: "posLevel",
align: "left",
label: "ระดับ",
sortable: false,
sortable: true,
field: "posLevel",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
@ -115,7 +123,7 @@ const baseColumns = ref<QTableProps["columns"]>([
name: "posExecutive",
align: "left",
label: "ตำแหน่งทางการบริหาร",
sortable: false,
sortable: true,
field: "posExecutive",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
@ -124,7 +132,7 @@ const baseColumns = ref<QTableProps["columns"]>([
name: "amount",
align: "left",
label: "เงินเดือนฐาน",
sortable: false,
sortable: true,
field: "amount",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
@ -133,7 +141,7 @@ const baseColumns = ref<QTableProps["columns"]>([
name: "amountUse",
align: "left",
label: "จำนวนเงินที่ใช้เลื่อน",
sortable: false,
sortable: true,
field: "amountUse",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
@ -143,7 +151,7 @@ const baseColumns = ref<QTableProps["columns"]>([
name: "positionSalaryAmount",
align: "left",
label: "เงินเดือนหลังเลื่อน",
sortable: false,
sortable: true,
field: "positionSalaryAmount",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
@ -152,7 +160,7 @@ const baseColumns = ref<QTableProps["columns"]>([
name: "isRetired",
align: "center",
label: "เกษียณอายุ",
sortable: false,
sortable: true,
field: "isRetired",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
@ -161,7 +169,7 @@ const baseColumns = ref<QTableProps["columns"]>([
name: "remark",
align: "left",
label: "หมายเหตุ",
sortable: false,
sortable: true,
field: "remark",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
@ -169,8 +177,8 @@ const baseColumns = ref<QTableProps["columns"]>([
]);
const visibleColumns = ref<string[]>([
"no",
"posNo",
"fullName",
"orgShortName",
"firstName",
"position",
"posType",
"posLevel",
@ -271,48 +279,17 @@ function onClickDelete(id: string) {
});
}
/**
* function updatePageTable
*/
function updatePagePagination() {
props.fetchDataTable?.();
}
/**
* function updatePageSizeTable
*/
function updatePageSizePagination(newPagination: NewPagination) {
formFilter.value.page = 1;
formFilter.value.pageSize = newPagination.rowsPerPage;
}
/**
* function นหาขอม Table
*/
/** ฟังก์ชันค้นหาข้อมูล Table*/
function searchData() {
formFilter.value.page = 1;
pagination.value.page = 1;
props.fetchDataTable?.();
}
/** ฟังก์ชันอัปเดตหน้าปัจจุบันและดึงข้อมูล */
async function updateCurrentPageAndfetchData() {
formFilter.value.page = await updateCurrentPage(
formFilter.value.page,
Number(maxPage.value),
props.rows.length
);
await props.checkAndUpdatePage(props.rows.length);
await props.fetchDataTable?.();
}
/**
* callblack function เรยกขอมลรายชอใหม เมอมการเปลยน PageSize
*/
watch(
() => formFilter.value.pageSize,
() => {
updatePagePagination();
}
);
</script>
<template>
<q-toolbar class="text-primary" style="padding: 0px">
@ -336,7 +313,7 @@ watch(
borderless
dense
outlined
v-model="formFilter.keyword"
v-model="keyword"
placeholder="ค้นหา"
@keydown.enter.prevent="searchData"
>
@ -367,7 +344,7 @@ watch(
/>
</q-toolbar>
<d-table
<p-table
ref="table"
:columns="
store.roundMainCode === 'OCT'
@ -384,7 +361,8 @@ watch(
dense
:rows-per-page-options="[10, 25, 50, 100]"
:visible-columns="visibleColumns"
@update:pagination="updatePageSizePagination"
v-model:pagination="pagination"
@request="props.onRequest"
>
<template v-slot:header="props">
<q-tr :props="props">
@ -469,7 +447,6 @@ watch(
>
<div v-if="col.name === 'no'">
{{
(formFilter.page - 1) * formFilter.pageSize +
props.rowIndex +
1 +
(store.tabType == "FULL" && props.row.isReserve == true
@ -477,10 +454,10 @@ watch(
: "")
}}
</div>
<div v-else-if="col.name === 'posNo'">
<div v-else-if="col.name === 'orgShortName'">
{{ `${props.row.orgShortName} ${props.row.posMasterNo}` }}
</div>
<div v-else-if="col.name === 'fullName'">
<div v-else-if="col.name === 'firstName'">
{{
`${props.row.prefix}${props.row.firstName} ${props.row.lastName}`
}}
@ -530,21 +507,7 @@ watch(
</q-td>
</q-tr>
</template>
<template v-slot:pagination="scope">
งหมด {{ props?.total?.toLocaleString() }} รายการ
<q-pagination
v-model="formFilter.page"
active-color="primary"
color="dark"
:max="Number(maxPage)"
:max-pages="5"
size="sm"
boundary-links
direction-links
@update:model-value="updatePagePagination()"
></q-pagination>
</template>
</d-table>
</p-table>
<DialogAddPerson
v-model:modal="modalDialogAddPerson"

View file

@ -1,13 +1,11 @@
<script setup lang="ts">
import { ref, watch } from "vue";
import { ref } from "vue";
import { useQuasar } from "quasar";
import { checkPermission } from "@/utils/permissions";
import { updateCurrentPage } from "@/utils/function";
/** importType*/
import type { QTableColumn } from "quasar";
import type { NewPagination } from "@/modules/13_salary/interface/index/Main";
import type { DataFilter } from "@/modules/13_salary/interface/index/SalaryList";
/** importComponents*/
import DialogAddPerson from "@/modules/13_salary/components/04_salaryLists//DialogAddPerson.vue"; //
@ -38,20 +36,17 @@ const {
} = useCounterMixin();
/** Props*/
const formFilter = defineModel<DataFilter>("formFilter", { required: true });
const maxPage = defineModel<Number>("maxPage", { required: true });
const snapShot = defineModel<string>("snapShot");
const isClose = defineModel<boolean>("isClose", { required: true });
const pagination = defineModel<NewPagination>("pagination", {
required: true,
});
const keyword = defineModel<string>("keyword", { required: true });
const props = defineProps({
rows: { type: Array, required: true },
fetchDataTable: {
type: Function,
required: true,
},
maxPage: {
type: Number,
required: true,
},
total: {
type: Number,
required: true,
@ -60,6 +55,14 @@ const props = defineProps({
type: Boolean,
required: true,
},
onRequest: {
type: Function,
required: true,
},
checkAndUpdatePage: {
type: Function,
required: true,
},
});
/** ข้อมูล Table*/
@ -75,11 +78,11 @@ const columns = ref<QTableColumn[]>([
},
{
name: "fullName",
name: "firstName",
align: "left",
label: "ชื่อ-นามสกุล",
sortable: false,
field: "fullName",
sortable: true,
field: "firstName",
format(val, row) {
return `${row.prefix}${row.firstName} ${row.lastName}`;
},
@ -87,11 +90,11 @@ const columns = ref<QTableColumn[]>([
style: "font-size: 14px",
},
{
name: "posNo",
name: "orgShortName",
align: "left",
label: "เลขที่ตำแหน่ง",
sortable: false,
field: "posNo",
sortable: true,
field: "orgShortName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
format(val, row) {
@ -104,7 +107,7 @@ const columns = ref<QTableColumn[]>([
name: "posType",
align: "left",
label: "ตำแหน่งประเภท",
sortable: false,
sortable: true,
field: "posType",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
@ -113,7 +116,7 @@ const columns = ref<QTableColumn[]>([
name: "posExecutive",
align: "left",
label: "ตำแหน่งทางการบริหาร",
sortable: false,
sortable: true,
field: "posExecutive",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
@ -123,7 +126,7 @@ const columns = ref<QTableColumn[]>([
align: "left",
label: "ตำแหน่งในสายงาน",
field: "position",
sortable: false,
sortable: true,
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
@ -132,7 +135,7 @@ const columns = ref<QTableColumn[]>([
align: "left",
label: "ระดับ",
field: "posLevel",
sortable: false,
sortable: true,
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
@ -141,7 +144,7 @@ const columns = ref<QTableColumn[]>([
align: "left",
label: "เงินเดือน",
field: "amount",
sortable: false,
sortable: true,
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
@ -205,8 +208,8 @@ const columns = ref<QTableColumn[]>([
]);
const visibleColumns = ref<string[]>([
"no",
"fullName",
"posNo",
"firstName",
"orgShortName",
"posType",
"posExecutive",
"position",
@ -305,15 +308,9 @@ function updatePagePagination() {
props.fetchDataTable?.();
}
/** function updatePageSizeTable*/
function updatePageSizePagination(newPagination: NewPagination) {
formFilter.value.page = 1;
formFilter.value.pageSize = newPagination.rowsPerPage;
}
/** function ค้นหาข้อมูล Table */
function searchData() {
formFilter.value.page = 1;
pagination.value.page = 1;
props.fetchDataTable?.();
}
@ -337,22 +334,10 @@ function onClickMoveLevelMulti() {
/** ฟังก์ชันอัปเดตหน้าปัจจุบันและดึงข้อมูล */
async function updateCurrentPageAndfetchData() {
formFilter.value.page = await updateCurrentPage(
formFilter.value.page,
props.maxPage,
props.rows.length
);
await props.checkAndUpdatePage(props.rows.length);
await props.fetchDataTable?.();
}
/** callblack function เรียกข้อมูลรายชื่อใหม่ เมื่อมีการเปลี่ยน PageSize*/
watch(
() => formFilter.value.pageSize,
() => {
updatePagePagination();
}
);
const infoType = ref<string>(""); //
/**
* function อมลสวนต
@ -402,7 +387,7 @@ function onClickViewInfo(type: string, id: string) {
borderless
dense
outlined
v-model="formFilter.keyword"
v-model="keyword"
placeholder="ค้นหา"
@keydown.enter.prevent="searchData"
>
@ -426,7 +411,7 @@ function onClickViewInfo(type: string, id: string) {
class="q-ml-sm"
/>
</q-toolbar>
<d-table
<p-table
ref="table"
:columns="!checkPermission($route)?.attrIsGet ? columns?.filter((col:any) => col.name !== 'posSalary' && col.name !== 'discipline' && col.name !== 'leave' ) : columns"
:rows="props.rows"
@ -437,7 +422,8 @@ function onClickViewInfo(type: string, id: string) {
dense
:rows-per-page-options="[10, 25, 50, 100]"
:visible-columns="visibleColumns"
@update:pagination="updatePageSizePagination"
v-model:pagination="pagination"
@request="props.onRequest"
>
<template v-slot:header="props">
<q-tr :props="props">
@ -511,9 +497,7 @@ function onClickViewInfo(type: string, id: string) {
</q-td>
<q-td v-for="col in props.cols" :key="col.name" :props="props">
<div v-if="col.name === 'no'">
{{
(formFilter.page - 1) * formFilter.pageSize + props.rowIndex + 1
}}
{{ props.rowIndex + 1 }}
</div>
<div v-else-if="col.name == 'organization'" class="text-html">
{{ findOrgNameHtml(props.row) }}
@ -563,7 +547,7 @@ function onClickViewInfo(type: string, id: string) {
</q-td>
</q-tr>
</template>
<template v-slot:pagination="scope">
<!-- <template v-slot:pagination="scope">
งหมด {{ props?.total?.toLocaleString() }} รายการ
<q-pagination
v-model="formFilter.page"
@ -576,8 +560,8 @@ function onClickViewInfo(type: string, id: string) {
direction-links
@update:model-value="updatePagePagination()"
></q-pagination>
</template>
</d-table>
</template> -->
</p-table>
<!-- เพมคนเลอนเงนเดอน -->
<DialogAddPerson

View file

@ -4,12 +4,12 @@ import { useQuasar } from "quasar";
import { useCounterMixin } from "@/stores/mixin";
import { useSalaryEmployeeListSDataStore } from "@/modules/13_salary/store/SalaryEmployeeListsStore";
import { usePagination } from "@/composables/usePagination";
import config from "@/app.config";
import http from "@/plugins/http";
/** importType*/
import type { QTableProps } from "quasar";
import type { NewPagination } from "@/modules/13_salary/interface/index/Main";
import type { DataFilterPerson } from "@/modules/13_salary/interface/index/SalaryList";
import type { DataPersonReq } from "@/modules/13_salary/interface/request/SalaryList";
import type { DataPerson } from "@/modules/13_salary/interface/response/SalaryList";
@ -22,6 +22,7 @@ const $q = useQuasar();
const store = useSalaryEmployeeListSDataStore();
const { messageError, showLoader, hideLoader, dialogConfirm, success } =
useCounterMixin();
const { pagination, params, onRequest } = usePagination("", fetchListPerson);
/** props*/
const modal = defineModel<boolean>("modal", { required: true });
@ -47,26 +48,26 @@ const columns = ref<QTableProps["columns"]>([
name: "citizenId",
align: "left",
label: "เลขประจำตัวประชาชน",
sortable: false,
sortable: true,
field: "citizenId",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "fullName",
name: "firstName",
align: "left",
label: "ชื่อ-นามสกุล",
field: "fullName",
sortable: false,
field: "firstName",
sortable: true,
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "posNo",
name: "orgShortName",
align: "left",
label: "ตำแหน่งเลขที่",
sortable: false,
field: "posNo",
sortable: true,
field: "orgShortName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
format(val, row) {
@ -79,7 +80,7 @@ const columns = ref<QTableProps["columns"]>([
name: "position",
align: "left",
label: "ตำแหน่ง",
sortable: false,
sortable: true,
field: "position",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
@ -88,17 +89,17 @@ const columns = ref<QTableProps["columns"]>([
name: "posType",
align: "left",
label: "กลุ่มงาน",
sortable: false,
sortable: true,
field: "posType",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "posLevelName",
name: "posLevel",
align: "left",
label: "ระดับชั้นงาน",
sortable: false,
field: "posLevelName",
sortable: true,
field: "posLevel",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
format(val, row) {
@ -110,19 +111,21 @@ const columns = ref<QTableProps["columns"]>([
]);
/** ข้อมูุลค้นหา*/
const formFilter = reactive<DataFilterPerson>({
page: 1,
pageSize: 10,
keyword: "",
rootId: "",
year: 0,
period: "",
});
const maxPage = ref<number>(1);
/** function close popup*/
function closeModal() {
modal.value = false;
formFilter.page = 1;
pagination.value = {
page: 1,
rowsPerPage: 10,
rowsNumber: 0,
};
formFilter.keyword = "";
}
@ -133,12 +136,17 @@ async function fetchListPerson() {
formFilter.period = store.roundMainCode;
formFilter.year = store.roundYear;
const body = {
...params.value,
...formFilter,
};
await http
.post(config.API.salaryListPersonEmp, formFilter)
.post(config.API.salaryListPersonEmp, body)
.then((res) => {
const data = res.data.result.data;
maxPage.value = Math.ceil(res.data.result.total / formFilter.pageSize);
rows.value = data;
const result = res.data.result;
pagination.value.rowsNumber = result.total;
rows.value = result.data;
})
.catch((err) => {
messageError($q, err);
@ -186,20 +194,9 @@ function onClickAddPerson(data: DataPerson) {
);
}
/** function update Pagination*/
async function updatePagePagination() {
fetchListPerson();
}
/** function updatePageSize*/
function updatePageSizePagination(newPagination: NewPagination) {
formFilter.page = 1;
formFilter.pageSize = newPagination.rowsPerPage;
}
/** function ค้นหาข้อมูลตาม keyword*/
function searchData() {
formFilter.page = 1;
pagination.value.page = 1;
fetchListPerson();
}
@ -212,14 +209,6 @@ watch(
}
}
);
/** callblack function เรียกข้อมูลรายชื่อคนเลื่อนเงินเดือน เมื่อมีการเปลี่ยน PageSize*/
watch(
() => formFilter.pageSize,
() => {
updatePagePagination();
}
);
</script>
<template>
<q-dialog v-model="modal" persistent>
@ -244,7 +233,7 @@ watch(
</q-input>
</div>
<div class="col-12">
<d-table
<p-table
ref="table"
:columns="columns"
:rows="rows"
@ -254,7 +243,8 @@ watch(
:paging="true"
dense
:rows-per-page-options="[10, 25, 50, 100]"
@update:pagination="updatePageSizePagination"
v-model:pagination="pagination"
@request="onRequest"
>
<template v-slot:header="props">
<q-tr :props="props">
@ -284,13 +274,9 @@ watch(
:props="props"
>
<div v-if="col.name === 'no'">
{{
(formFilter.page - 1) * formFilter.pageSize +
props.rowIndex +
1
}}
{{ props.rowIndex + 1 }}
</div>
<div v-else-if="col.name === 'fullName'">
<div v-else-if="col.name === 'firstName'">
{{
`${props.row.prefix}${props.row.firstName} ${props.row.lastName}`
}}
@ -301,20 +287,7 @@ watch(
</q-td>
</q-tr>
</template>
<template v-slot:pagination="scope">
<q-pagination
v-model="formFilter.page"
active-color="primary"
color="dark"
:max="Number(maxPage)"
:max-pages="5"
size="sm"
boundary-links
direction-links
@update:model-value="updatePagePagination()"
></q-pagination>
</template>
</d-table>
</p-table>
</div>
</div>
</q-card-section>

View file

@ -1,14 +1,15 @@
<script setup lang="ts">
import { ref, onMounted, reactive, computed } from "vue";
import { ref, onMounted, computed } from "vue";
import { useQuasar } from "quasar";
import { checkPermission } from "@/utils/permissions";
import http from "@/plugins/http";
import config from "@/app.config";
import genReportXLSX from "@/plugins/genreportxlsx";
import { usePagination } from "@/composables/usePagination";
/** importType*/
import type { DataOption } from "@/modules/13_salary/interface/index/Main";
import type { DataFilter } from "@/modules/13_salary/interface/index/SalaryList";
import type {
DataPeriodLatest,
DataPeriod,
@ -27,6 +28,10 @@ import { useSalaryEmployeeListSDataStore } from "@/modules/13_salary/store/Salar
const $q = useQuasar();
const store = useSalaryEmployeeListSDataStore();
const { messageError, showLoader, hideLoader } = useCounterMixin();
const { pagination, params, onRequest, checkAndUpdatePage } = usePagination(
"",
() => fetchDataPeriod(store.groupId, true)
);
/** props*/
const props = defineProps({
@ -42,8 +47,8 @@ const splitterModel = ref<number>(13);
const modalDialogInfoCriteria = ref<boolean>(false); //popup
const isRetire = ref<boolean>(false); //
const rows = ref<DataPeriod[]>([]); //
const keyword = ref<string>(""); //
const total = ref<number>(0); //
const maxPage = ref<number>(1); //
//itemsTab
const itemsTabGroup = ref([
@ -203,13 +208,6 @@ const itemsCard = ref([
total: 0,
},
]);
//
const formFilter = reactive<DataFilter>({
page: 1,
pageSize: 10,
keyword: "",
type: store.tabType,
});
/**
* งกนเรยกขอมลโควต
@ -246,11 +244,11 @@ async function fetchDataQuota(id: string) {
* งกนเรยกขอมลรายช
* @param id กล
*/
async function fetchDataPeriod(id: string) {
async function fetchDataPeriod(id: string, force: boolean = false) {
force && showLoader();
let formData = {
page: formFilter.page.toString(),
pageSize: formFilter.pageSize.toString(),
keyword: formFilter.keyword,
...params.value,
keyword: keyword.value.trim(),
type: store.tabType,
isRetire:
store.roundMainCode !== "OCT"
@ -259,29 +257,32 @@ async function fetchDataPeriod(id: string) {
? "1"
: "0",
};
rows.value = [];
await http
.put(config.API.salaryListPeriodORGEmp(id), formData)
.then((res) => {
rows.value = res.data.result.data;
total.value = res.data.result.total;
maxPage.value = Math.ceil(res.data.result.total / formFilter.pageSize);
const result = res.data.result;
pagination.value.rowsNumber = result.total;
rows.value = result.data;
total.value = result.total;
})
.catch((err) => {
messageError($q, err);
rows.value = [];
})
.finally(() => {
force && hideLoader();
});
}
/** ฟังก์ชันเปลี่ยนขั้น*/
async function changeTabType() {
if (!store.groupId) return;
showLoader();
try {
formFilter.page = 1;
formFilter.pageSize = 10;
formFilter.keyword = "";
pagination.value.page = 1;
pagination.value.rowsPerPage = 10;
keyword.value = "";
await fetchDataPeriod(store.groupId);
} catch (error) {
messageError($q, error);
@ -531,25 +532,29 @@ onMounted(async () => {
>
<TableTabType1
v-if="index === 0"
v-model:max-page="maxPage"
v-model:form-filter="formFilter"
:fetch-data-table="fetchDataPeriodNew"
:rows="rows"
:total="total"
:snap-shot="props?.snapShot"
:is-retire="isRetire"
:is-close="props.periodLatest?.group1IsClose ?? false"
v-model:pagination="pagination"
v-model:keyword="keyword"
:onRequest="onRequest"
:checkAndUpdatePage="checkAndUpdatePage"
/>
<TableTabType2
v-else
:rows="rows"
v-model:max-page="maxPage"
v-model:form-filter="formFilter"
:fetch-data-table="fetchDataPeriodNew"
:total="total"
:type="item.type"
:snap-shot="props?.snapShot"
:is-close="props.periodLatest?.group1IsClose ?? false"
v-model:pagination="pagination"
v-model:keyword="keyword"
:onRequest="onRequest"
:checkAndUpdatePage="checkAndUpdatePage"
/>
</q-tab-panel>
</q-tab-panels>

View file

@ -1,9 +1,8 @@
<script setup lang="ts">
import { ref, watch, computed } from "vue";
import { ref, computed } from "vue";
import { useQuasar } from "quasar";
import { checkPermission } from "@/utils/permissions";
import { updateCurrentPage } from "@/utils/function";
import { useCounterMixin } from "@/stores/mixin";
import { useSalaryEmployeeListSDataStore } from "@/modules/13_salary/store/SalaryEmployeeListsStore";
import config from "@/app.config";
@ -12,7 +11,6 @@ import http from "@/plugins/http";
/** importType*/
import type { QTableProps } from "quasar";
import type { NewPagination } from "@/modules/13_salary/interface/index/Main";
import type { DataFilter } from "@/modules/13_salary/interface/index/SalaryList";
/** importComponents*/
import DialogAddPerson from "@/modules/13_salary/components/05_salaryListsEmployee//DialogAddPerson.vue";
@ -27,10 +25,12 @@ const { dialogRemove, messageError, showLoader, hideLoader, success } =
useCounterMixin();
/** props*/
const formFilter = defineModel<DataFilter>("formFilter", { required: true });
const maxPage = defineModel<Number>("maxPage", { required: true });
const isClose = defineModel<boolean>("isClose", { required: true });
const snapShot = defineModel<string>("snapShot");
const pagination = defineModel<NewPagination>("pagination", {
required: true,
});
const keyword = defineModel<string>("keyword", { required: true });
const props = defineProps({
rows: { type: Array, required: true },
fetchDataTable: {
@ -45,6 +45,14 @@ const props = defineProps({
type: String,
required: true,
},
onRequest: {
type: Function,
required: true,
},
checkAndUpdatePage: {
type: Function,
required: true,
},
});
/** ข้อมูล Table*/
@ -60,20 +68,20 @@ const baseColumns = ref<QTableProps["columns"]>([
},
{
name: "fullName",
name: "firstName",
align: "left",
label: "ชื่อ-นามสกุล",
field: "fullName",
sortable: false,
field: "firstName",
sortable: true,
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "posNo",
name: "orgShortName",
align: "left",
label: "ตำแหน่งเลขที่",
sortable: false,
field: "posNo",
sortable: true,
field: "orgShortName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
@ -81,7 +89,7 @@ const baseColumns = ref<QTableProps["columns"]>([
name: "position",
align: "left",
label: "ตำแหน่ง",
sortable: false,
sortable: true,
field: "position",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
@ -90,7 +98,7 @@ const baseColumns = ref<QTableProps["columns"]>([
name: "posType",
align: "left",
label: "กลุ่มงาน",
sortable: false,
sortable: true,
field: "posType",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
@ -99,7 +107,7 @@ const baseColumns = ref<QTableProps["columns"]>([
name: "posLevel",
align: "left",
label: "ระดับชั้นงาน",
sortable: false,
sortable: true,
field: "posLevel",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
@ -108,7 +116,7 @@ const baseColumns = ref<QTableProps["columns"]>([
name: "group",
align: "left",
label: "ผังค่าจ้าง(เดิม)",
sortable: false,
sortable: true,
field: "group",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
@ -120,7 +128,7 @@ const baseColumns = ref<QTableProps["columns"]>([
name: "salaryLevel",
align: "left",
label: "ขั้น(เดิม)",
sortable: false,
sortable: true,
field: "salaryLevel",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
@ -129,7 +137,7 @@ const baseColumns = ref<QTableProps["columns"]>([
name: "amount",
align: "left",
label: "ค่าจ้างฐาน",
sortable: false,
sortable: true,
field: "amount",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
@ -138,7 +146,7 @@ const baseColumns = ref<QTableProps["columns"]>([
name: "amountUse",
align: "left",
label: "จำนวนเงินที่ใช้เลื่อน",
sortable: false,
sortable: true,
field: "amountUse",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
@ -148,7 +156,7 @@ const baseColumns = ref<QTableProps["columns"]>([
name: "positionSalaryAmount",
align: "left",
label: "ค่าจ้างหลังเลื่อน",
sortable: false,
sortable: true,
field: "positionSalaryAmount",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
@ -166,7 +174,7 @@ const baseColumns = ref<QTableProps["columns"]>([
name: "remark",
align: "left",
label: "หมายเหตุ",
sortable: false,
sortable: true,
field: "remark",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
@ -174,8 +182,8 @@ const baseColumns = ref<QTableProps["columns"]>([
]);
const visibleColumns = ref<string[]>([
"no",
"posNo",
"fullName",
"firstName",
"orgShortName",
"position",
"posType",
"posLevel",
@ -208,9 +216,7 @@ const typeLevel = ref<string>(""); //เลื่อนขั้น
const isReserve = ref<boolean>(false); //
const remark = ref<string>(""); //
/**
* function openPopup เพมคนเลอนคาจาง
*/
/** function openPopup เพิ่มคนเลื่อนค่าจ้าง*/
function onClickAddPerson() {
modalDialogAddPerson.value = !modalDialogAddPerson.value;
}
@ -277,48 +283,17 @@ function onClickDelete(id: string) {
});
}
/**
* function updatePageTable
*/
function updatePagePagination() {
props.fetchDataTable?.();
}
/**
* function updatePageSizeTable
*/
function updatePageSizePagination(newPagination: NewPagination) {
formFilter.value.page = 1;
formFilter.value.pageSize = newPagination.rowsPerPage;
}
/**
* function นหาขอม Table
*/
/**function ค้นหาข้อมูล Table*/
function searchData() {
formFilter.value.page = 1;
pagination.value.page = 1;
props.fetchDataTable?.();
}
/** ฟังก์ชันอัปเดตหน้าปัจจุบันและดึงข้อมูล */
async function updateCurrentPageAndfetchData() {
formFilter.value.page = await updateCurrentPage(
formFilter.value.page,
Number(maxPage.value),
props.rows.length
);
await props.checkAndUpdatePage(props.rows.length);
await props.fetchDataTable?.();
}
/**
* callblack function เรยกขอมลรายชอใหม เมอมการเปลยน PageSize
*/
watch(
() => formFilter.value.pageSize,
() => {
updatePagePagination();
}
);
</script>
<template>
<q-toolbar class="text-primary" style="padding: 0px">
@ -343,7 +318,7 @@ watch(
borderless
dense
outlined
v-model="formFilter.keyword"
v-model="keyword"
placeholder="ค้นหา"
@keydown.enter.prevent="searchData"
>
@ -374,7 +349,7 @@ watch(
/>
</q-toolbar>
<d-table
<p-table
ref="table"
:columns="
store.roundMainCode === 'OCT'
@ -391,7 +366,8 @@ watch(
dense
:rows-per-page-options="[10, 25, 50, 100]"
:visible-columns="visibleColumns"
@update:pagination="updatePageSizePagination"
v-model:pagination="pagination"
@request="props.onRequest"
>
<template v-slot:header="props">
<q-tr :props="props">
@ -476,7 +452,6 @@ watch(
>
<div v-if="col.name === 'no'">
{{
(formFilter.page - 1) * formFilter.pageSize +
props.rowIndex +
1 +
(store.tabType == "FULL" && props.row.isReserve == true
@ -484,10 +459,10 @@ watch(
: "")
}}
</div>
<div v-else-if="col.name === 'posNo'">
<div v-else-if="col.name === 'orgShortName'">
{{ `${props.row.orgShortName} ${props.row.posMasterNo}` }}
</div>
<div v-else-if="col.name === 'fullName'">
<div v-else-if="col.name === 'firstName'">
{{
`${props.row.prefix}${props.row.firstName} ${props.row.lastName}`
}}
@ -539,21 +514,7 @@ watch(
</q-td>
</q-tr>
</template>
<template v-slot:pagination="scope">
งหมด {{ props?.total?.toLocaleString() }} รายการ
<q-pagination
v-model="formFilter.page"
active-color="primary"
color="dark"
:max="Number(maxPage)"
:max-pages="5"
size="sm"
boundary-links
direction-links
@update:model-value="updatePagePagination()"
></q-pagination>
</template>
</d-table>
</p-table>
<DialogAddPerson
v-model:modal="modalDialogAddPerson"

View file

@ -1,9 +1,9 @@
<script setup lang="ts">
import { ref, watch } from "vue";
import { ref } from "vue";
import { useQuasar } from "quasar";
import { checkPermission } from "@/utils/permissions";
import { updateCurrentPage } from "@/utils/function";
import { useCounterMixin } from "@/stores/mixin";
import { useSalaryEmployeeListSDataStore } from "@/modules/13_salary/store/SalaryEmployeeListsStore";
import http from "@/plugins/http";
@ -12,7 +12,6 @@ import config from "@/app.config";
/** importType*/
import type { QTableColumn } from "quasar";
import type { NewPagination } from "@/modules/13_salary/interface/index/Main";
import type { DataFilter } from "@/modules/13_salary/interface/index/SalaryList";
/** importComponents*/
import DialogAddPerson from "@/modules/13_salary/components/05_salaryListsEmployee//DialogAddPerson.vue";
@ -37,21 +36,18 @@ const {
} = useCounterMixin();
/** Props*/
const formFilter = defineModel<DataFilter>("formFilter", { required: true });
const maxPage = defineModel<Number>("maxPage", { required: true });
const isClose = defineModel<boolean>("isClose", { required: true });
const snapShot = defineModel<string>("snapShot");
const pagination = defineModel<NewPagination>("pagination", {
required: true,
});
const keyword = defineModel<string>("keyword", { required: true });
const props = defineProps({
rows: { type: Array, required: true },
fetchDataTable: {
type: Function,
required: true,
},
maxPage: {
type: Number,
required: true,
},
total: {
type: Number,
required: true,
@ -60,6 +56,14 @@ const props = defineProps({
type: Boolean,
required: true,
},
onRequest: {
type: Function,
required: true,
},
checkAndUpdatePage: {
type: Function,
required: true,
},
});
/** ข้อมูล Table*/
@ -74,11 +78,11 @@ const columns = ref<QTableColumn[]>([
style: "font-size: 14px",
},
{
name: "fullName",
name: "firstName",
align: "left",
label: "ชื่อ-นามสกุล",
sortable: false,
field: "fullName",
sortable: true,
field: "firstName",
format(val, row) {
return `${row.prefix}${row.firstName} ${row.lastName}`;
},
@ -86,11 +90,11 @@ const columns = ref<QTableColumn[]>([
style: "font-size: 14px",
},
{
name: "posNo",
name: "orgShortName",
align: "left",
label: "ตำแหน่งเลขที่",
sortable: false,
field: "posNo",
sortable: true,
field: "orgShortName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
format(val, row) {
@ -105,7 +109,7 @@ const columns = ref<QTableColumn[]>([
align: "left",
label: "ตำแหน่ง",
field: "position",
sortable: false,
sortable: true,
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
@ -113,7 +117,7 @@ const columns = ref<QTableColumn[]>([
name: "posType",
align: "left",
label: "กลุ่มงาน",
sortable: false,
sortable: true,
field: "posType",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
@ -123,7 +127,7 @@ const columns = ref<QTableColumn[]>([
align: "left",
label: "ระดับชั้นงาน",
field: "posLevel",
sortable: false,
sortable: true,
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
@ -131,7 +135,7 @@ const columns = ref<QTableColumn[]>([
name: "group",
align: "left",
label: "ผังค่าจ้าง(เดิม)",
sortable: false,
sortable: true,
field: "group",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
@ -143,7 +147,7 @@ const columns = ref<QTableColumn[]>([
name: "salaryLevel",
align: "left",
label: "ขั้น(เดิม)",
sortable: false,
sortable: true,
field: "salaryLevel",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
@ -153,7 +157,7 @@ const columns = ref<QTableColumn[]>([
align: "left",
label: "ค่าจ้าง",
field: "amount",
sortable: false,
sortable: true,
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
@ -217,8 +221,8 @@ const columns = ref<QTableColumn[]>([
]);
const visibleColumns = ref<string[]>([
"no",
"fullName",
"posNo",
"firstName",
"orgShortName",
"posType",
"position",
"posLevel",
@ -313,22 +317,9 @@ function onClickMoveLevel(id: string, typeVal: string, isReserveVal: boolean) {
isReserve.value = isReserveVal;
}
/** function updatePageTable*/
function updatePagePagination() {
props.fetchDataTable?.();
}
/**
* function updatePageSizeTable
*/
function updatePageSizePagination(newPagination: NewPagination) {
formFilter.value.page = 1;
formFilter.value.pageSize = newPagination.rowsPerPage;
}
/** function ค้นหาข้อมูล Table*/
function searchData() {
formFilter.value.page = 1;
pagination.value.page = 1;
props.fetchDataTable?.();
}
@ -364,23 +355,9 @@ function onClickMoveLevelMulti() {
/** ฟังก์ชันอัปเดตหน้าปัจจุบันและดึงข้อมูล */
async function updateCurrentPageAndfetchData() {
formFilter.value.page = await updateCurrentPage(
formFilter.value.page,
props.maxPage,
props.rows.length
);
await props.checkAndUpdatePage(props.rows.length);
await props.fetchDataTable?.();
}
/**
* callblack function เรยกขอมลรายชอใหม เมอมการเปลยน PageSize
*/
watch(
() => formFilter.value.pageSize,
() => {
updatePagePagination();
}
);
</script>
<template>
@ -418,7 +395,7 @@ watch(
borderless
dense
outlined
v-model="formFilter.keyword"
v-model="keyword"
placeholder="ค้นหา"
@keydown.enter.prevent="searchData"
>
@ -444,7 +421,7 @@ watch(
class="q-ml-sm"
/>
</q-toolbar>
<d-table
<p-table
ref="table"
:columns="!checkPermission($route)?.attrIsGet
? columns?.filter((col:any) => col.name !== 'posSalary' && col.name !== 'discipline' && col.name !== 'leave' )
@ -455,9 +432,10 @@ watch(
bordered
:paging="true"
dense
:rows-per-page-options="[10, 25, 50, 100]"
:rows-per-page-options="[1,10, 25, 50, 100]"
:visible-columns="visibleColumns"
@update:pagination="updatePageSizePagination"
v-model:pagination="pagination"
@request="props.onRequest"
>
<template v-slot:header="props">
<q-tr :props="props">
@ -530,9 +508,7 @@ watch(
</q-td>
<q-td v-for="col in props.cols" :key="col.name" :props="props">
<div v-if="col.name === 'no'">
{{
(formFilter.page - 1) * formFilter.pageSize + props.rowIndex + 1
}}
{{ props.rowIndex + 1 }}
</div>
<div v-else-if="col.name == 'organization'" class="text-html">
{{ findOrgNameHtml(props.row) }}
@ -589,21 +565,7 @@ watch(
</q-td>
</q-tr>
</template>
<template v-slot:pagination="scope">
งหมด {{ props.total?.toLocaleString() }} รายการ
<q-pagination
v-model="formFilter.page"
active-color="primary"
color="dark"
:max="Number(maxPage)"
:max-pages="5"
size="sm"
boundary-links
direction-links
@update:model-value="updatePagePagination()"
></q-pagination>
</template>
</d-table>
</p-table>
<DialogAddPerson
v-model:modal="modalDialogAddPerson"

View file

@ -13,10 +13,10 @@ interface DataOptionShort {
}
interface NewPagination {
descending: boolean;
descending?: boolean;
page: number;
rowsPerPage: number;
sortBy: string;
sortBy?: string;
}
interface ItemsMenu {

View file

@ -6,8 +6,6 @@ interface DataFilter {
}
interface DataFilterPerson {
page: number;
pageSize: number;
keyword: string;
rootId: string;
year: number;

View file

@ -6,12 +6,12 @@ import { useRouter } from "vue-router";
import { checkPermission } from "@/utils/permissions";
import { updateCurrentPage } from "@/utils/function";
import { useCounterMixin } from "@/stores/mixin";
import { usePagination } from "@/composables/usePagination";
import http from "@/plugins/http";
import config from "@/app.config";
/** importType */
import type { QTableProps } from "quasar";
import type { NewPagination } from "@/modules/13_salary/interface/index/Main";
import type { Salary } from "@/modules/13_salary/interface/response/Main";
import type { FormQuerySalary } from "@/modules/13_salary/interface/request/Main";
@ -30,6 +30,10 @@ const {
hideLoader,
success,
} = useCounterMixin();
const { pagination, params, onRequest, checkAndUpdatePage } = usePagination(
"",
fetchListSalaly
);
/** modalDialog */
const modalDialogFormMain = ref<boolean>(false); //popup ,
@ -38,22 +42,23 @@ const rowId = ref<string>(""); // id รายการผังบัญชี
/** Table*/
const rows = ref<Salary[]>([]); //
const keyword = ref<string>(""); //keyword
const columns = ref<QTableProps["columns"]>([
{
name: "name",
align: "left",
label: "ชื่อผังบัญชีอัตราเงินเดือน",
sortable: false,
sortable: true,
field: "name",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "posList",
name: "posType",
align: "left",
label: "ประเภทผังบัญชีเงินเดือน",
sortable: false,
field: "posList",
sortable: true,
field: "posType",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
@ -61,7 +66,7 @@ const columns = ref<QTableProps["columns"]>([
name: "startDate",
align: "left",
label: "วันที่มีผลบังคับใช้",
sortable: false,
sortable: true,
field: "startDate",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
@ -70,7 +75,7 @@ const columns = ref<QTableProps["columns"]>([
name: "isActive",
align: "center",
label: "สถานะการใช้งาน",
sortable: false,
sortable: true,
field: "isActive",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
@ -78,19 +83,11 @@ const columns = ref<QTableProps["columns"]>([
]);
const visibleColumns = ref<string[]>([
"name",
"posList",
"posType",
"startDate",
"isActive",
]);
/** queryString */
const formQuery = reactive<FormQuerySalary>({
page: 1, //*
pageSize: 10, //*
keyword: "", //keyword
});
const maxPage = ref<number>(1); //
const total = ref<number>(); //
const isActive = ref<boolean>(false); //
const typeAction = ref<string>(""); //
const dataSalary = ref<Salary>(); //
@ -98,19 +95,17 @@ const dataSalary = ref<Salary>(); //ข้อมูลรายการผั
/** ฟังก์ชันดึงข้อมูลรายการผังบัญชีเงินเดือน */
async function fetchListSalaly() {
showLoader();
const page = formQuery.page.toString();
const pageSize = formQuery.pageSize.toString();
const keyword = formQuery.keyword.toString().trim();
await http
.get(
config.API.salaryChart +
`?page=${page}&pageSize=${pageSize}&keyword=${keyword}`
)
.get(config.API.salaryChart, {
params: {
...params.value,
keyword: keyword.value.trim(),
},
})
.then(async (res) => {
const data = await res.data.result;
rows.value = data.data;
total.value = data.total;
maxPage.value = Math.ceil(data.total / formQuery.pageSize);
const result = await res.data.result;
pagination.value.rowsNumber = result.total;
rows.value = result.data;
})
.catch((err) => {
messageError($q, err);
@ -145,7 +140,7 @@ function onClickSalaryRate(id: string) {
* งกนคดลอกขอมลรายการผงบญชเงนเดอน
* @param id ญชเงนเดอน
*/
function onClickCoppy(id: string) {
function onClickCopy(id: string) {
showLoader();
http
.post(config.API.salaryChartCopy, { id: id })
@ -171,12 +166,7 @@ function onClickDelete(id: string) {
await http
.delete(config.API.salaryChartByid(id))
.then(async () => {
formQuery.page = await updateCurrentPage(
formQuery.page,
maxPage.value,
rows.value.length
);
await checkAndUpdatePage(rows.value.length);
await fetchListSalaly();
success($q, "ลบข้อมูลสำเร็จ");
})
@ -202,28 +192,12 @@ function onClickUpload(type: string, id: string, active: boolean) {
isActive.value = active;
}
/**
* งก updatePagination
* @param newPagination อม Pagination ใหม
*/
function updatePagination(newPagination: NewPagination) {
formQuery.page = 1;
formQuery.pageSize = newPagination.rowsPerPage;
}
/** ฟังก์ชัน ค้นหาข้อมูลตาม keyword */
function filterFn(page: number) {
page !== 1 ? (formQuery.page = 1) : fetchListSalaly();
function filterFn() {
pagination.value.page = 1;
fetchListSalaly();
}
/** callbackFunction ทำงานเมื่อมีการ เปลี่ยนแถว */
watch(
() => formQuery.pageSize,
() => {
fetchListSalaly();
}
);
/** hooklifecycle*/
onMounted(() => {
fetchListSalaly();
@ -255,9 +229,9 @@ onMounted(() => {
borderless
dense
outlined
v-model="formQuery.keyword"
v-model="keyword"
placeholder="ค้นหา"
@keydown.enter.prevent="filterFn(formQuery.page)"
@keydown.enter.prevent="filterFn()"
>
<template v-slot:append>
<q-icon name="search" />
@ -281,7 +255,7 @@ onMounted(() => {
</div>
<div class="col-12 q-pt-sm">
<d-table
<p-table
ref="table"
:columns="columns"
:rows="rows"
@ -291,8 +265,9 @@ onMounted(() => {
:paging="true"
dense
:rows-per-page-options="[10, 25, 50, 100]"
@update:pagination="updatePagination"
:visible-columns="visibleColumns"
v-model:pagination="pagination"
@request="onRequest"
>
<template v-slot:header="props">
<q-tr :props="props">
@ -399,7 +374,7 @@ onMounted(() => {
v-if="checkPermission($route)?.attrIsCreate"
clickable
v-close-popup
@click.stop="onClickCoppy(props.row.id)"
@click.stop="onClickCopy(props.row.id)"
>
<q-item-section>
<div class="row items-center">
@ -442,7 +417,7 @@ onMounted(() => {
size="24px"
/>
</div>
<div v-else-if="col.name === 'posList'" class="row">
<div v-else-if="col.name === 'posType'" class="row">
<div class="column text-weight-light">
<span>ประเภทตำแหน</span>
<span>ระดบตำแหน</span>
@ -464,7 +439,7 @@ onMounted(() => {
}}
</div>
<div v-else-if="col.name === 'startDate'">
{{ col.value ? date2Thai(col.value) : "" }}
{{ col.value ? date2Thai(col.value) : "-" }}
</div>
<div v-else>
{{ col.value ? col.value : "-" }}
@ -472,21 +447,7 @@ onMounted(() => {
</q-td>
</q-tr>
</template>
<template v-slot:pagination="scope">
งหมด {{ total?.toLocaleString() }} รายการ
<q-pagination
v-model="formQuery.page"
active-color="primary"
color="dark"
:max="maxPage"
size="sm"
boundary-links
direction-links
:max-pages="5"
@update:model-value="fetchListSalaly()"
></q-pagination>
</template>
</d-table>
</p-table>
</div>
</q-card>

View file

@ -6,6 +6,8 @@ import { checkPermission } from "@/utils/permissions";
import { updateCurrentPage } from "@/utils/function";
import { useCounterMixin } from "@/stores/mixin";
import { useSalaryDataStore } from "@/modules/13_salary/store/SalaryStore";
import { calculateFiscalYear } from "@/utils/function";
import { usePagination } from "@/composables/usePagination";
import config from "@/app.config";
import http from "@/plugins/http";
@ -29,6 +31,10 @@ const {
dialogConfirm,
success,
} = useCounterMixin();
const { pagination, params, onRequest, checkAndUpdatePage } = usePagination(
"",
getData
);
const idRound = ref<string>(""); //id
@ -43,8 +49,6 @@ const yearData = ref<number | null>(0); //ปีงบประมาณ
/** Table*/
const year = ref<number>(0); //
const filterKeyword = ref<string>(""); //
const maxPage = ref<number>(1); //
const totalList = ref<number>(0); //
const page = ref<number>(1); //
const rowsPerPage = ref<number>(10); //
const columns = ref<QTableProps["columns"]>([
@ -61,7 +65,7 @@ const columns = ref<QTableProps["columns"]>([
name: "period",
align: "left",
label: "รอบการขึ้นเงินเดือน",
sortable: false,
sortable: true,
field: "period",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
@ -70,7 +74,7 @@ const columns = ref<QTableProps["columns"]>([
name: "year",
align: "left",
label: "ปีงบประมาณ",
sortable: false,
sortable: true,
field: "year",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
@ -79,7 +83,7 @@ const columns = ref<QTableProps["columns"]>([
name: "effectiveDate",
align: "left",
label: "วันที่มีผลบังคับใช้",
sortable: false,
sortable: true,
field: "effectiveDate",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
@ -111,11 +115,6 @@ const visibleColumns = ref<string[]>([
"isActive",
"isClose",
]);
const pagination = ref({
descending: false,
page: page.value,
rowsPerPage: rowsPerPage.value,
});
/**ฟังก์ชัน เปิด Dialog เพิ่มรอบการขึ้นเงินเดือน */
function clickAdd() {
@ -127,15 +126,17 @@ function clickAdd() {
async function getData() {
showLoader();
await http
.get(
config.API.salaryPeriod() +
`?page=${page.value}&pageSize=${rowsPerPage.value}&keyword=${filterKeyword.value}&year=${year.value}`
)
.get(config.API.salaryPeriod(), {
params: {
...params.value,
keyword: filterKeyword.value.trim(),
year: year.value,
},
})
.then(async (res) => {
const data = await res.data.result;
dataStore.fetchDataMap(data.data);
maxPage.value = Math.ceil(data.total / rowsPerPage.value);
totalList.value = data.total;
const result = await res.data.result;
pagination.value.rowsNumber = result.total;
dataStore.fetchDataMap(result.data);
})
.catch((e) => {
messageError($q, e);
@ -167,12 +168,7 @@ function deleteData(id: string) {
await http
.delete(config.API.salaryPeriod() + `/${id}`)
.then(async () => {
page.value = await updateCurrentPage(
page.value,
maxPage.value,
dataStore.rows.length
);
await checkAndUpdatePage(dataStore.rows.length);
await getData();
await success($q, "ลบข้อมูลสำเร็จ");
})
@ -230,26 +226,9 @@ function dialogClose(id: string) {
);
}
/**
* งกนอปเดท แถวตอหน
* @param newPagination
*/
function updatePageSize(newPagination: NewPagination) {
page.value = 1;
rowsPerPage.value = newPagination.rowsPerPage;
}
/** ฟังก์ชันทำเมื่อมีการอัปเดท แถวต่อหน้า แล้ว fetch รายการรอบการขึ้นเงินเดือน */
watch(
() => rowsPerPage.value,
() => {
getData();
}
);
/** Hooklifecycle */
onMounted(async () => {
year.value = new Date().getFullYear();
year.value = calculateFiscalYear(new Date());
dataStore.visibleColumns = visibleColumns.value;
dataStore.columns = columns.value;
getData();
@ -337,7 +316,7 @@ onMounted(async () => {
</div>
<div class="col-12">
<d-table
<p-table
ref="table"
:columns="dataStore.columns"
:rows="dataStore.rows"
@ -350,21 +329,8 @@ onMounted(async () => {
:visible-columns="dataStore.visibleColumns"
v-model:pagination="pagination"
:rows-per-page-options="[10, 25, 50, 100]"
@update:pagination="updatePageSize"
@request="onRequest"
>
<template v-slot:pagination="scope">
งหมด {{ totalList?.toLocaleString() }} รายการ
<q-pagination
v-model="page"
active-color="primary"
color="dark"
:max="Number(maxPage)"
size="sm"
boundary-links
direction-links
@update:model-value="getData"
></q-pagination>
</template>
<template v-slot:header="props">
<q-tr :props="props">
<q-th auto-width />
@ -477,11 +443,7 @@ onMounted(async () => {
</q-td>
<q-td v-for="col in props.cols" :key="col.name" :props="props">
<div v-if="col.name == 'no'">
{{
(page - 1) * Number(pagination.rowsPerPage) +
props.rowIndex +
1
}}
{{ props.rowIndex + 1 }}
</div>
<div v-else-if="col.name == 'effectiveDate'">
{{ date2Thai(props.row.effectiveDate) }}
@ -515,7 +477,7 @@ onMounted(async () => {
</q-td>
</q-tr>
</template>
</d-table>
</p-table>
</div>
</q-card>

View file

@ -11,6 +11,7 @@ import {
} from "@/utils/permissions";
import config from "@/app.config";
import http from "@/plugins/http";
import { calculateFiscalYear } from "@/utils/function";
/** importType*/
import type {
@ -36,7 +37,7 @@ const { messageError, showLoader, hideLoader, success, dialogConfirm } =
useCounterMixin();
/** ตัวแปร*/
const year = ref<number>(new Date().getFullYear()); //
const year = ref<number>(calculateFiscalYear(new Date())); //
const roundFilter = ref<any>(); //
const agencyFilter = ref<string>(""); //
const snapFilter = ref<string>(""); //

View file

@ -11,6 +11,7 @@ import {
} from "@/utils/permissions";
import config from "@/app.config";
import http from "@/plugins/http";
import { calculateFiscalYear } from "@/utils/function";
/** importType*/
import type {
@ -35,7 +36,7 @@ const $q = useQuasar();
const { messageError, showLoader, hideLoader } = useCounterMixin();
/** ตัวแปร*/
const year = ref<number>(new Date().getFullYear()); //
const year = ref<number>(calculateFiscalYear(new Date())); //
const roundFilter = ref<any>(); //
const agencyFilter = ref<string>(""); //
const snapFilter = ref<string>(""); //

View file

@ -8,6 +8,7 @@ import http from "@/plugins/http";
import { useRouter } from "vue-router";
import { useCounterMixin } from "@/stores/mixin";
import { useRoute } from "vue-router";
import { calculateFiscalYear } from "@/utils/function";
import type {
DataOption,
@ -47,7 +48,7 @@ const typeOps = ref<typeOp[]>([
]);
const modalDialog = defineModel<boolean>("modal", { required: true });
const yearDialog = ref<number | any>(new Date().getFullYear());
const yearDialog = ref<number | any>(calculateFiscalYear(new Date())); //
const roundDialgOp = ref<DataOption[]>([]);
const isRoundClose = ref<boolean>(false);
@ -144,7 +145,7 @@ const columnsRespondent = ref<QTableProps["columns"]>([
function onCloseDialog() {
modalDialog.value = false;
formRound.kpiPeriodId = { id: "", name: "", isClosed: false };
yearDialog.value = new Date().getFullYear();
yearDialog.value = calculateFiscalYear(new Date());
rows.value = [];
formRound.evaluatorId = "";
formRound.commanderId = "";

View file

@ -1,5 +1,5 @@
<script setup lang="ts">
import { onMounted, ref, watch } from "vue";
import { onMounted, ref } from "vue";
import { useQuasar } from "quasar";
import http from "@/plugins/http";
@ -7,6 +7,8 @@ import config from "@/app.config";
import { useCounterMixin } from "@/stores/mixin";
import { useKpiDataStore } from "@/modules/14_KPI/store";
import { checkPermission } from "@/utils/permissions";
import { calculateFiscalYear } from "@/utils/function";
import { usePagination } from "@/composables/usePagination";
/** importType*/
import type { QTableProps } from "quasar";
@ -23,18 +25,13 @@ import DialogIndividual from "@/modules/14_KPI/components/results/dialogIndividu
const $q = useQuasar();
const { showLoader, messageError, hideLoader } = useCounterMixin();
const store = useKpiDataStore();
const { pagination, params, onRequest } = usePagination("", fetcDataList);
/** props*/
const tab = defineModel<string>("tab", { required: true });
/**
* วแปร
*/
/** ตัวแปร*/
const rows = ref<ResDevelopment[]>([]); //
const page = ref<number>(1);
const pageSize = ref<number>(10);
const maxPage = ref<number>(1);
const total = ref<number>(1);
const keyword = ref<string>("");
const modalDetail = ref<boolean>(false);
const devId = ref<string>("");
@ -51,11 +48,11 @@ const columns = ref<QTableProps["columns"]>([
style: "font-size: 14px",
},
{
name: "fullName",
name: "firstname",
align: "left",
label: "ชื่อ-นามสกุล",
sortable: true,
field: "fullName",
field: "firstname",
format: (val, row) => {
return `${row.prefix ?? ""}${row.firstname ?? ""} ${row.lastname ?? ""}`;
},
@ -119,7 +116,7 @@ const columns = ref<QTableProps["columns"]>([
]);
const visibleColumns = ref<string[]>([
"no",
"fullName",
"firstname",
"name",
"organization",
"position",
@ -127,13 +124,9 @@ const visibleColumns = ref<string[]>([
"posLevelName",
"root",
]);
const pagination = ref({
page: page.value,
rowsPerPage: pageSize.value,
});
/** ตัวแปร*/
const year = ref<number | null>(new Date().getFullYear()); //
const year = ref<number | null>(calculateFiscalYear(new Date())); //
const roundOp = ref<DataOption[]>([]); //
/** function fetch รายการแผนพัฒนาการปฏิบัติราชการรายบุคคลย้อนหลัง*/
@ -141,19 +134,18 @@ async function fetcDataList() {
showLoader();
await http
.post(config.API.achievementDev, {
page: page.value,
pageSize: pageSize.value,
...params.value,
keyword: keyword.value.trim(),
kpiPeriodId: store.formQuery.round ? store.formQuery.round : "",
})
.then(async (res) => {
const data = await res.data.result;
rows.value = data.data;
total.value = data.total;
maxPage.value = Math.ceil(total.value / pageSize.value);
const result = await res.data.result;
pagination.value.rowsNumber = result.total;
rows.value = result.data;
})
.catch((err) => {
messageError($q, err);
rows.value = [];
})
.finally(() => {
hideLoader();
@ -200,13 +192,13 @@ async function fetchRoundOption() {
/** function เปลี่ยนรอบการประเมิน และ เรียกข้อมูลรายการแผนพัฒนาการปฏิบัติราชการรายบุคคลย้อนหลัง*/
function changRound() {
store.formQuery.page = 1;
pagination.value.page = 1;
fetcDataList();
}
/** ค้นหาข้อมูล*/
function onSearchData() {
page.value = 1;
pagination.value.page = 1;
fetcDataList();
}
@ -219,12 +211,6 @@ function onClickView(id: string) {
devId.value = id;
}
/** ทำงานเมื่อมีการเปลี่ยนแถวต่อหน้า*/
watch(pagination, () => {
page.value = 1;
pageSize.value = pagination.value.rowsPerPage;
});
/** HookLifecycle*/
onMounted(async () => {
store.formQuery.round = "";
@ -312,14 +298,15 @@ onMounted(async () => {
style="min-width: 140px"
/>
</div>
<d-table
<p-table
:columns="columns"
:rows="rows"
row-key="id"
:rows-per-page-options="[10, 25, 50, 100]"
v-model:pagination="pagination"
:paging="true"
:visible-columns="visibleColumns"
@request="onRequest"
v-model:pagination="pagination"
>
<template v-slot:header="props">
<q-tr :props="props">
@ -354,7 +341,7 @@ onMounted(async () => {
</q-td>
<q-td v-for="col in props.cols" :key="col.name" :props="props">
<div v-if="col.name == 'no'">
{{ (page - 1) * pageSize + props.rowIndex + 1 }}
{{ props.rowIndex + 1 }}
</div>
<div
v-else-if="col.name == 'organization'"
@ -369,21 +356,7 @@ onMounted(async () => {
</q-td>
</q-tr>
</template>
<template v-slot:pagination="scope">
งหมด {{ total }} รายการ
<q-pagination
v-model="page"
active-color="primary"
color="dark"
:max="Number(maxPage)"
size="sm"
boundary-links
direction-links
:max-pages="5"
@update:model-value="fetcDataList()"
></q-pagination>
</template>
</d-table>
</p-table>
</q-card-section>
<DialogIndividual v-model:devId="devId" v-model:modal="modalDetail" />

View file

@ -1,5 +1,5 @@
<script setup lang="ts">
import { onMounted, ref, watch } from "vue";
import { onMounted, ref } from "vue";
import { useQuasar } from "quasar";
import http from "@/plugins/http";
@ -7,6 +7,7 @@ import config from "@/app.config";
import { useCounterMixin } from "@/stores/mixin";
import { useKpiDataStore } from "@/modules/14_KPI/store";
import { checkPermission } from "@/utils/permissions";
import { calculateFiscalYear } from "@/utils/function";
/** importType*/
import type { QTableProps } from "quasar";
@ -26,21 +27,19 @@ const {
hideLoader,
date2Thai,
} = useCounterMixin();
const { convertResults, convertStatus } = useKpiDataStore();
const { convertResults } = useKpiDataStore();
const store = useKpiDataStore();
/** props*/
const tab = defineModel<string>("tab", { required: true });
const rows = defineModel<ResResults[]>("row", { required: true });
const page = defineModel<number>("page", { required: true });
const pageSize = defineModel<number>("pageSize", { required: true });
const maxPage = defineModel<number>("maxPage", { required: true });
const total = defineModel<number>("total", { required: true });
const keyword = defineModel<string>("keyword", { required: true });
const result = defineModel<string>("result", { required: true });
const pagination = defineModel<any>("pagination", { required: true });
const porps = defineProps({
const props = defineProps({
fetchData: { type: Function, required: true }, // function
onRequest: { type: Function, required: true },
});
/** Table*/
@ -56,11 +55,11 @@ const columns = ref<QTableProps["columns"]>([
style: "font-size: 14px",
},
{
name: "fullName",
name: "firstname",
align: "left",
label: "ผู้รับการประเมิน",
sortable: true,
field: "fullName",
field: "firstname",
format: (val, row) => {
return `${row.prefix ?? ""}${row.firstname ?? ""} ${row.lastname ?? ""}`;
},
@ -95,7 +94,7 @@ const columns = ref<QTableProps["columns"]>([
name: "evaluationResults",
align: "left",
label: "ผลการประเมิน",
sortable: true,
sortable: false,
field: "evaluationResults",
format(val, row) {
return convertResults(val);
@ -151,7 +150,7 @@ const columns = ref<QTableProps["columns"]>([
]);
const visibleColumns = ref<string[]>([
"no",
"fullName",
"firstname",
"createdAt",
// "evaluationStatus",
"evaluationResults",
@ -161,13 +160,9 @@ const visibleColumns = ref<string[]>([
"posLevelName",
"root",
]);
const pagination = ref({
page: page.value,
rowsPerPage: pageSize.value,
});
/** ตัวแปร*/
const year = ref<number | null>(new Date().getFullYear()); //
const year = ref<number | null>(calculateFiscalYear(new Date())); //
const roundOp = ref<DataOption[]>([]); //
const resultOp = ref<DataOption[]>(store.resultsOptions);
@ -183,7 +178,7 @@ function onAnnounce() {
id: ids,
})
.then(async () => {
await porps.fetchData();
await props.fetchData();
await success($q, "ประกาศผลสำเร็จ");
selected.value = [];
})
@ -222,7 +217,7 @@ async function fetchRoundOption() {
roundOp.value = list;
store.formQuery.round = list[0].id;
await porps.fetchData();
await props.fetchData();
} else {
roundOp.value = [];
store.formQuery.round = "";
@ -238,15 +233,15 @@ async function fetchRoundOption() {
}
/** function เปลี่ยนรอบการประเมิน และ เรียกข้อมูลรายการแผนพัฒนาการปฏิบัติราชการรายบุคคลย้อนหลัง*/
function changRound() {
store.formQuery.page = 1;
porps.fetchData();
function changeRound() {
pagination.value.page = 1;
props.fetchData();
}
/** ค้นหาข้อมูล*/
function onSearchData() {
page.value = 1;
porps.fetchData();
pagination.value.page = 1;
props.fetchData();
}
/**
@ -270,13 +265,6 @@ function filterSelector(val: string, update: Function, refData: string) {
}
}
/** ทำงานเมื่อมีการเปลี่ยนแถวต่อหน้า*/
watch(pagination, () => {
page.value = 1;
pageSize.value = pagination.value.rowsPerPage;
});
/** ทำงานเมื่อมีการเปลี่ยนแถวต่อหน้า*/
onMounted(async () => {
store.formQuery.round = "";
await fetchRoundOption();
@ -365,7 +353,7 @@ onMounted(async () => {
style="min-width: 150px"
emit-value
map-options
@update:model-value="changRound"
@update:model-value="changeRound"
/>
</div>
@ -408,16 +396,17 @@ onMounted(async () => {
</div>
<div class="col-12">
<d-table
<p-table
:columns="columns"
:rows="rows"
row-key="id"
:selection="tab === 'COMPLETE' ? 'multiple' : null"
v-model:selected="selected"
:rows-per-page-options="[10, 25, 50, 100]"
v-model:pagination="pagination"
:paging="true"
:visible-columns="visibleColumns"
v-model:pagination="pagination"
@request="props.onRequest"
>
<template v-slot:header-selection="scope" v-if="tab === 'COMPLETE'">
<q-checkbox
@ -443,7 +432,7 @@ onMounted(async () => {
</q-td>
<q-td v-for="col in props.cols" :key="col.name" :props="props">
<div v-if="col.name == 'no'">
{{ (page - 1) * pageSize + props.rowIndex + 1 }}
{{ props.rowIndex + 1 }}
</div>
<div
v-else-if="col.name == 'organization'"
@ -458,21 +447,7 @@ onMounted(async () => {
</q-td>
</q-tr>
</template>
<template v-slot:pagination="scope">
งหมด {{ total }} รายการ
<q-pagination
v-model="page"
active-color="primary"
color="dark"
:max="Number(maxPage)"
size="sm"
boundary-links
direction-links
:max-pages="5"
@update:model-value="porps.fetchData()"
></q-pagination>
</template>
</d-table>
</p-table>
</div>
</div>
</q-card-section>

View file

@ -6,16 +6,12 @@ import { useCounterMixin } from "@/stores/mixin";
import { checkPermission } from "@/utils/permissions";
import http from "@/plugins/http";
import config from "@/app.config";
import { calculateFiscalYear } from "@/utils/function";
import { usePagination } from "@/composables/usePagination";
/** importType*/
import type {
DataOption,
NewPagination,
} from "@/modules/14_KPI/interface/index/Main";
import type {
FormQueryRound,
FormRound,
} from "@/modules/14_KPI/interface/request/Main";
import type { DataOption } from "@/modules/14_KPI/interface/index/Main";
import type { FormRound } from "@/modules/14_KPI/interface/request/Main";
import type { ResRound } from "@/modules/14_KPI/interface/response/Main";
/** importComponents*/
@ -32,11 +28,13 @@ const {
dialogConfirm,
dialogRemove,
} = useCounterMixin();
const { pagination, params, onRequest, checkAndUpdatePage } = usePagination(
"",
fetchList
);
/** Table*/
const rows = ref<ResRound[]>([]); //
const totalList = ref<number>(1); //
const total = ref<number>(0); //
const columns = ref<QTableProps["columns"]>([
{
name: "year",
@ -98,16 +96,12 @@ const visibleColumns = ref<string[]>([
"isActive",
]);
//
const formQuery = reactive<FormQueryRound>({
page: 1, //
pageSize: 10, //
year: new Date().getFullYear(), //
keyword: "",
});
const modalDialog = ref<boolean>(false); //modal
const isStatusEdit = ref<boolean>(false); //status
const fiscalyear = ref<number>(calculateFiscalYear(new Date())); //
const keyword = ref<string>(""); //
//
const formData = reactive<FormRound>({
durationKPI: "", //
@ -128,15 +122,17 @@ const roundOp = ref<DataOption[]>([
async function fetchList() {
showLoader();
await http
.get(
config.API.kpiPeriod +
`/admin?page=${formQuery.page}&pageSize=${formQuery.pageSize}&keyword=${formQuery.keyword}&year=${formQuery.year}`
)
.get(config.API.kpiPeriod + "/admin", {
params: {
...params.value,
year: fiscalyear.value,
keyword: keyword.value.trim(),
},
})
.then(async (res) => {
const data = await res.data.result;
totalList.value = Math.ceil(data.total / formQuery.pageSize);
total.value = data.total;
rows.value = data.data;
const result = await res.data.result;
pagination.value.rowsNumber = result.total;
rows.value = result.data;
})
.catch((err) => {
messageError($q, err);
@ -288,6 +284,7 @@ function onDeleteRound(id: string) {
http
.delete(config.API.kpiPeriodById(id))
.then(async () => {
await checkAndUpdatePage(rows.value.length);
await fetchList();
await success($q, "ลบข้อมูลสำเร็จ");
})
@ -311,29 +308,12 @@ function connvertName(val: string) {
return findData?.name;
}
/**
* งก updatePagination
* @param newPagination อม Pagination ใหม
*/
function updatePagination(newPagination: NewPagination) {
formQuery.page = 1;
formQuery.pageSize = newPagination.rowsPerPage;
}
/** function อัพเดทปีงบประมาณ และ fetch รายการรอบการประเมินผลการปฏิบัติหน้าที่ราชการ*/
function handleUpdateYear() {
formQuery.page = 1;
pagination.value.page = 1;
fetchList();
}
/** callback function fetch รายการรอบการประเมินผลการปฏิบัติหน้าที่ราชการ เมือมีการเปลี่ยนแถวต่อหน้า*/
watch(
() => formQuery.pageSize,
() => {
fetchList();
}
);
/** callback function เช็ต วันเริ่มต้น และวันสิ้นสุด รอบการประเมินผลการปฏิบัติหน้าที่ราชการ*/
watch(
[() => formData.durationKPI, () => formData.year],
@ -364,7 +344,7 @@ onMounted(async () => {
<div class="row q-col-gutter-sm">
<div class="row col-12">
<datepicker
v-model="formQuery.year"
v-model="fiscalyear"
:locale="'th'"
autoApply
year-picker
@ -380,7 +360,7 @@ onMounted(async () => {
dense
outlined
:model-value="
formQuery.year === 0 ? 'ทั้งหมด' : Number(formQuery.year) + 543
fiscalyear === 0 ? 'ทั้งหมด' : Number(fiscalyear) + 543
"
:label="`${'ปีงบประมาณ'}`"
>
@ -392,11 +372,11 @@ onMounted(async () => {
>
</q-icon>
</template>
<template v-if="formQuery.year" v-slot:append>
<template v-if="fiscalyear" v-slot:append>
<q-icon
name="cancel"
@click.stop.prevent="
(formQuery.year = 0), (formQuery.page = 1), fetchList()
(fiscalyear = 0), (pagination.page = 1), fetchList()
"
class="cursor-pointer"
/>
@ -434,7 +414,7 @@ onMounted(async () => {
</div>
<div class="col-12">
<d-table
<p-table
for="table"
ref="table"
:columns="columns"
@ -446,7 +426,8 @@ onMounted(async () => {
class="custom-header-table"
:visible-columns="visibleColumns"
:rows-per-page-options="[10, 25, 50, 100]"
@update:pagination="updatePagination"
v-model:pagination="pagination"
@request="onRequest"
>
<template v-slot:header="props">
<q-tr :props="props">
@ -492,21 +473,7 @@ onMounted(async () => {
</q-td>
</q-tr>
</template>
<template v-slot:pagination="scope">
งหมด {{ total }} รายการ
<q-pagination
v-model="formQuery.page"
active-color="primary"
color="dark"
:max="Number(totalList)"
size="sm"
boundary-links
direction-links
:max-pages="5"
@update:model-value="fetchList"
></q-pagination>
</template>
</d-table>
</p-table>
</div>
</div>
</q-card>

View file

@ -6,6 +6,8 @@ import { useRouter } from "vue-router";
import { useCounterMixin } from "@/stores/mixin";
import { useKpiDataStore } from "@/modules/14_KPI/store";
import { checkPermission } from "@/utils/permissions";
import { calculateFiscalYear } from "@/utils/function";
import { usePagination } from "@/composables/usePagination";
import config from "@/app.config";
import http from "@/plugins/http";
@ -21,11 +23,10 @@ const $q = useQuasar();
const router = useRouter();
const store = useKpiDataStore();
const { showLoader, hideLoader, messageError, date2Thai } = useCounterMixin();
const { pagination, params, onRequest } = usePagination("", fetchList);
const year = ref<number | null>(new Date().getFullYear()); //
const year = ref<number | null>(calculateFiscalYear(new Date())); //
const formQuery = reactive({
page: 1, //
pageSize: 10, //
status: "",
results: "",
});
@ -41,25 +42,23 @@ const rows = ref<any[]>([]); //รายการการประเมิน
const maxPage = ref<number>(1); //
const totalList = ref<number>(0); //
const visibleColumns = ref<string[]>([
"name",
"firstName",
"createdAt",
"evaluationStatus",
"evaluationResults",
]);
const columns = ref<QTableProps["columns"]>([
{
name: "name",
name: "firstName",
align: "left",
label: "ผู้รับการประเมิน",
sortable: true,
field: "name",
field: "firstName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
format(val, row) {
return `${row.prefix}${row.firstname} ${row.lastname}`;
},
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "createdAt",
@ -70,32 +69,26 @@ const columns = ref<QTableProps["columns"]>([
headerStyle: "font-size: 14px",
style: "font-size: 14px",
format: (v) => date2Thai(v, false, true),
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "evaluationStatus",
align: "left",
label: "สถานะการประเมิน",
sortable: true,
sortable: false,
field: "evaluationStatus",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
format: (v) => store.convertStatus(v),
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "evaluationResults",
align: "left",
label: "ผลการประเมิน",
sortable: true,
sortable: false,
field: "evaluationResults",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
format: (v) => store.convertResults(v),
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
]);
@ -141,8 +134,7 @@ async function fetchRoundOption() {
async function fetchList() {
showLoader();
const body = {
page: formQuery.page,
pageSize: formQuery.pageSize,
...params.value,
kpiPeriodId: store.formQuery.round,
keyword: store.formQuery.keyword.trim(),
status: formQuery.status === "" ? undefined : formQuery.status,
@ -153,10 +145,9 @@ async function fetchList() {
await http
.post(config.API.kpiUserEvaluation + `/list`, body)
.then(async (res) => {
const data = await res.data.result;
maxPage.value = Math.ceil(data.total / formQuery.pageSize);
totalList.value = data.total;
rows.value = data.data;
const result = await res.data.result;
pagination.value.rowsNumber = result.total;
rows.value = result.data;
})
.catch((err) => {
messageError($q, err);
@ -172,7 +163,7 @@ async function fetchList() {
* แลวเรยกขอมลรายการการประเมนผลการปฏราชการระดบบคคลใหม
*/
async function changRound() {
formQuery.page = 1;
pagination.value.page = 1;
await fetchList();
}
@ -194,22 +185,6 @@ function redirectViewDetailOnly(id: string) {
router.push(`KPI-list-detail/${id}`);
}
/** ฟังก์ชันเคลียข้อมูลค้นหาเป็นค้นหาจ้อมูลทั้งหมด*/
// function clearYear() {
// year.value = null;
// store.formQuery.round = "";
// roundOp.value = [];
// changRound();
// }
/**
* function updatePagination
* @param newPagination อม Pagination ใหม
*/
function updatePagination(newPagination: any) {
formQuery.pageSize = newPagination.rowsPerPage;
}
/**
* งกนคนหาขอมลในรายการตวเลอก
* @param val คำคนหา
@ -238,19 +213,6 @@ function filterSelector(val: string, update: Function, refData: string) {
}
}
/**
* การเปลยนแปลงของ formQuery.pageSize เมอมการเปลยนของแถวทงหมด
* จะกำหนด formQuery.page เปนหนาแรก
* แลวเรยกขอมลรายการการประเมนผลการปฏราชการระดบบคคลใหม
*/
watch(
() => formQuery.pageSize,
() => {
formQuery.page = 1;
fetchList();
}
);
/** Hook */
onMounted(async () => {
await fetchRoundOption();
@ -373,7 +335,7 @@ onMounted(async () => {
lazy-rules
hide-bottom-space
outlined
@update:model-value="(formQuery.page = 1), fetchList()"
@update:model-value="(pagination.page = 1), fetchList()"
use-input
@clear="
(formQuery.status = ''), (statusOp = store.statusOptions)
@ -408,7 +370,7 @@ onMounted(async () => {
lazy-rules
hide-bottom-space
outlined
@update:model-value="(formQuery.page = 1), fetchList()"
@update:model-value="(pagination.page = 1), fetchList()"
use-input
@clear="
(formQuery.results = ''), (resultOp = store.resultsOptions)
@ -432,7 +394,7 @@ onMounted(async () => {
</div>
<div class="col-12">
<d-table
<p-table
ref="table"
:columns="columns"
:rows="rows"
@ -443,7 +405,8 @@ onMounted(async () => {
dense
:rows-per-page-options="[10, 25, 50, 100]"
:visible-columns="visibleColumns"
@update:pagination="updatePagination"
v-model:pagination="pagination"
@request="onRequest"
>
<template v-slot:header="props">
<q-tr :props="props">
@ -489,21 +452,7 @@ onMounted(async () => {
</q-td>
</q-tr>
</template>
<template v-slot:pagination="scope">
งหมด {{ totalList }} รายการ
<q-pagination
v-model="formQuery.page"
active-color="primary"
color="dark"
:max="Number(maxPage)"
size="sm"
boundary-links
direction-links
:max-pages="5"
@update:model-value="fetchList"
></q-pagination>
</template>
</d-table>
</p-table>
</div>
</div>
</q-card>

View file

@ -4,6 +4,7 @@ import { useQuasar } from "quasar";
import { useCounterMixin } from "@/stores/mixin";
import { useKpiDataStore } from "@/modules/14_KPI/store";
import { usePagination } from "@/composables/usePagination";
import http from "@/plugins/http";
import config from "@/app.config";
@ -19,6 +20,7 @@ import TableIndividual from "@/modules/14_KPI/components/results/tableIndividual
const store = useKpiDataStore();
const $q = useQuasar();
const { messageError, showLoader, hideLoader } = useCounterMixin();
const { pagination, params, onRequest } = usePagination("", fetcDataList);
const tab = ref<string>("COMPLETE");
const tabItems = ref<ItemsTab[]>([
@ -27,10 +29,6 @@ const tabItems = ref<ItemsTab[]>([
{ name: "IDP", label: "แผนพัฒนาการปฏิบัติราชการรายบุคคล" },
]);
const dataList = ref<ResResults[]>([]); //
const page = ref<number>(1);
const pageSize = ref<number>(10);
const maxPage = ref<number>(1);
const total = ref<number>(1);
const keyword = ref<string>("");
const result = ref<string>("");
@ -40,17 +38,15 @@ async function fetcDataList() {
await http
.post(config.API.evaluationUser, {
status: tab.value,
page: page.value,
pageSize: pageSize.value,
...params.value,
keyword: keyword.value.trim(),
kpiPeriodId: store.formQuery.round ? store.formQuery.round : "",
results: result.value === "" ? undefined : result.value,
})
.then(async (res) => {
const data = await res.data.result;
dataList.value = data.data;
total.value = data.total;
maxPage.value = Math.ceil(total.value / pageSize.value);
const result = await res.data.result;
pagination.value.rowsNumber = result.total;
dataList.value = result.data;
})
.catch((err) => {
messageError($q, err);
@ -62,16 +58,11 @@ async function fetcDataList() {
/** ทำงานเมื่อมีการเปลี่ยน Tab */
watch(tab, () => {
page.value = 1;
pagination.value.page = 1;
result.value = "";
keyword.value = "";
dataList.value = [];
});
/** ทำงานเมื่อมีการเปลี่ยนแถวต่อหน้า*/
watch(pageSize, () => {
fetcDataList();
});
</script>
<template>
@ -97,13 +88,11 @@ watch(pageSize, () => {
<TableResults
:tab="tab"
:row="dataList"
v-model:page="page"
v-model:pageSize="pageSize"
v-model:maxPage="maxPage"
v-model:total="total"
v-model:keyword="keyword"
v-model:result="result"
v-model:pagination="pagination"
:fetchData="fetcDataList"
:onRequest="onRequest"
/>
</q-tab-panel>
@ -111,13 +100,11 @@ watch(pageSize, () => {
<TableResults
:tab="tab"
:row="dataList"
v-model:page="page"
v-model:pageSize="pageSize"
v-model:maxPage="maxPage"
v-model:total="total"
v-model:keyword="keyword"
v-model:result="result"
v-model:pagination="pagination"
:fetchData="fetcDataList"
:onRequest="onRequest"
/>
</q-tab-panel>
<q-tab-panel name="IDP" style="padding: 0px">

View file

@ -7,6 +7,7 @@ import http from "@/plugins/http";
import axios from "axios";
import genReport from "@/plugins/genreport";
import LoadView from "@/components/LoadView.vue";
import { calculateFiscalYear } from "@/utils/function";
/**
* importType
*/
@ -45,7 +46,7 @@ const route = useRoute();
*/
const fullNameShow = ref<string>("");
const isLoadPDF = ref<boolean>(false);
const year = ref<number | null>(new Date().getFullYear());
const year = ref<number | null>(calculateFiscalYear(new Date())); //
const round = ref<string>("");
const organization = ref<string>("");
const roundOp = ref<DataOption[]>([]);
@ -487,7 +488,7 @@ watch(
function clearFilter() {
organization.value = "";
year.value = new Date().getFullYear();
year.value = calculateFiscalYear(new Date());
typeReport.value = "KPI1";
pdfSrc.value = undefined;
dataDownload.value = undefined;

View file

@ -7,6 +7,7 @@ import http from "@/plugins/http";
import config from "@/app.config";
import { useStructureTree } from "@/stores/structureTree";
import { useCounterMixin } from "@/stores/mixin";
import { calculateFiscalYear } from "@/utils/function";
/** importType*/
import type { FormBasicinfo } from "@/modules/15_development/interface/request/Main";
@ -34,7 +35,7 @@ const checkRoutePermission = ref<boolean>(
); // check route
const formData = reactive<FormBasicinfo>({
year: new Date().getFullYear(), //
year: calculateFiscalYear(new Date()), //
projectName: "", //
reason: "", //
objective: "", //
@ -47,7 +48,7 @@ const orgName = ref<string>(""); //ชื่อ หน่วยงาน/ส่
const node = ref<any[]>([]); // /
const filter = ref<string>(""); //input
const expanded = ref<string[]>([]);
const nodeDnaId = ref<string>('');
const nodeDnaId = ref<string>("");
/**
* function fetch อมลเบองต
@ -67,7 +68,7 @@ async function fetchData(id: string) {
formData.nodeId = data.nodeId;
formData.node = data.node;
formData.orgRevisionId = data.revisionId;
nodeDnaId.value = data.nodeDnaId
nodeDnaId.value = data.nodeDnaId;
const arrayExpanded = [
data.root,
@ -126,7 +127,7 @@ function updateSelected(data: DataTree) {
formData.node = data.orgLevel;
formData.nodeId = data.orgTreeId;
formData.orgRevisionId = data.orgRevisionId;
nodeDnaId.value = data.orgTreeDnaId
nodeDnaId.value = data.orgTreeDnaId;
props.onCheckChangeData();
}

View file

@ -6,45 +6,22 @@ import { useQuasar, type QTableProps } from "quasar";
import http from "@/plugins/http";
import config from "@/app.config";
import { useCounterMixin } from "@/stores/mixin";
import { usePagination } from "@/composables/usePagination";
import type {
DataOption,
FormFilter,
NewPagination,
} from "@/modules/15_development/interface/index/Main";
import type { DataOption } from "@/modules/15_development/interface/index/Main";
import Header from "@/components/DialogHeader.vue";
const $q = useQuasar();
const mixin = useCounterMixin();
const { messageError, dialogMessageNotify, showLoader, hideLoader } = mixin;
const { pagination, params, onRequest } = usePagination("", searchFilter);
const rows = ref<any[]>([]);
const props = defineProps({
upDate: { type: Function },
});
const maxPage = ref<number>(1); //
const formFilter = reactive<FormFilter>({
page: 1,
pageSize: 20,
keyword: "",
year: new Date().getFullYear(),
type: "",
posType: "",
posLevel: "",
retireYear: "",
rangeYear: { min: 0, max: 60 },
isShowRetire: null,
isProbation: null,
});
const pagination = ref({
page: 1,
rowsPerPage: 20,
});
const modal = defineModel<boolean>("modal", { required: true });
const selected = ref<any[]>([]); // checkbox
const search = ref<string>("citizenId"); //
@ -62,11 +39,11 @@ const govOp = ref<DataOption[]>([
const visibleColumns = ref<string[]>([
"citizenId",
"name",
"firstName",
"position",
"type",
"level",
"positionSide",
"posType",
"posLevel",
"posExecutive",
]);
const columns = ref<QTableProps["columns"]>([
@ -80,7 +57,7 @@ const columns = ref<QTableProps["columns"]>([
style: "font-size: 14px",
},
{
name: "name",
name: "firstName",
align: "left",
label: "ชื่อ-นามสกุล",
sortable: true,
@ -99,7 +76,7 @@ const columns = ref<QTableProps["columns"]>([
style: "font-size: 14px",
},
{
name: "type",
name: "posType",
align: "left",
label: "ตำแหน่งประเภท",
sortable: true,
@ -108,7 +85,7 @@ const columns = ref<QTableProps["columns"]>([
style: "font-size: 14px",
},
{
name: "level",
name: "posLevel",
align: "left",
label: "ระดับตำแหน่ง",
sortable: true,
@ -117,7 +94,7 @@ const columns = ref<QTableProps["columns"]>([
style: "font-size: 14px",
},
{
name: "positionSide",
name: "posExecutive",
align: "left",
label: "ตําแหน่งทางการบริหาร",
sortable: true,
@ -166,48 +143,57 @@ function closeDialog() {
rows.value = [];
selected.value = [];
inputSearch.value = "";
}
/** class */
function getClass() {
return "inputgreen";
pagination.value = {
page: 1,
rowsPerPage: 10,
rowsNumber: 0,
sortBy: "",
};
}
/** ดึงข้อมูลตาม keyword */
function searchFilter() {
async function searchFilter() {
showLoader();
http
.get(
config.API.registryNew("") +
`?page=${formFilter.page}&pageSize=${formFilter.pageSize}&searchField=${search.value}&searchKeyword=${inputSearch.value}`
)
await http
.get(config.API.developmentProfile, {
params: {
...params.value,
searchField: search.value,
searchKeyword: inputSearch.value.trim(),
},
})
.then((res) => {
const data = res.data.result.data;
maxPage.value = Math.ceil(res.data.result.total / formFilter.pageSize);
rows.value = data.map((item: any) => ({
id: item.id ? item.id : null,
name: item.firstName
? `${item.prefix}${item.firstName} ${item.lastName}`
: null,
prefix: item.prefix ? item.prefix : null,
rank: item.rank ? item.rank : null,
firstName: item.firstName ? item.firstName : null,
lastName: item.lastName ? item.lastName : null,
citizenId: item.citizenId ? item.citizenId : null,
level: item.posLevel ? item.posLevel : null,
type: item.posType ? item.posType : null,
posLevelId: item.posLevelId ? item.posLevelId : null,
posTypeId: item.posTypeId ? item.posTypeId : null,
position: item.position ? item.position : null,
positionSide: item.posExecutive ? item.posExecutive : null,
posNo: item.posNo ? item.posNo : null,
org: item.org ? item.org : null,
rootId: item.rootId ? item.rootId : null,
rootDnaId: item.rootId ? item.rootDnaId : null,
root: item.root ? item.root : null,
orgRootShortName: item.orgRootShortName ? item.orgRootShortName : null,
orgRevisionId: item.orgRevisionId ? item.orgRevisionId : null,
}));
const result = res.data.result;
pagination.value.rowsNumber = result.total;
if (result.data.length !== 0) {
rows.value = result.data.map((item: any) => ({
id: item.id ? item.id : null,
name: item.firstName
? `${item.prefix}${item.firstName} ${item.lastName}`
: null,
prefix: item.prefix ? item.prefix : null,
rank: item.rank ? item.rank : null,
firstName: item.firstName ? item.firstName : null,
lastName: item.lastName ? item.lastName : null,
citizenId: item.citizenId ? item.citizenId : null,
level: item.posLevel ? item.posLevel : null,
type: item.posType ? item.posType : null,
posLevelId: item.posLevelId ? item.posLevelId : null,
posTypeId: item.posTypeId ? item.posTypeId : null,
position: item.position ? item.position : null,
positionSide: item.posExecutive ? item.posExecutive : null,
posNo: item.posNo ? item.posNo : null,
org: item.org ? item.org : null,
rootId: item.rootId ? item.rootId : null,
rootDnaId: item.rootId ? item.rootDnaId : null,
root: item.root ? item.root : null,
orgRootShortName: item.orgRootShortName
? item.orgRootShortName
: null,
orgRevisionId: item.orgRevisionId ? item.orgRevisionId : null,
}));
}
})
.catch((e) => {
messageError($q, e);
@ -217,25 +203,10 @@ function searchFilter() {
});
}
/** update ค่า เเถวข้อมูล */
function updatePage(val: number) {
formFilter.page = val;
function onfetchNewData() {
pagination.value.page = 1;
searchFilter();
}
/** update ค่า เเถวข้อมูล */
function updatePageSize(newPagination: NewPagination) {
formFilter.page = 1;
formFilter.pageSize = newPagination.rowsPerPage;
}
/** เช็คเเถวข้อมูลว่ามีการเปลี่ยนแปลงไหม */
watch(
() => formFilter.pageSize,
() => {
searchFilter();
}
);
</script>
<template>
<q-dialog v-model="modal" persistent>
@ -266,6 +237,7 @@ watch(
label="ค้นหา"
v-model="inputSearch"
:mask="search === 'citizenId' ? '#############' : undefined"
@keyup.enter="onfetchNewData()"
/>
</div>
<div class="col-2">
@ -275,13 +247,13 @@ watch(
unelevated
outline
color="primary"
@click="(formFilter.page = 1), searchFilter()"
@click="onfetchNewData()"
>
</q-btn>
</div>
</div>
<div class="q-mt-sm">
<d-table
<p-table
style="max-height: 70vh"
virtual-scroll
selection="single"
@ -298,21 +270,8 @@ watch(
:visible-columns="visibleColumns"
v-model:pagination="pagination"
:rows-per-page-options="[20, 25, 50, 100]"
@update:pagination="updatePageSize"
@request="onRequest"
>
<template v-slot:pagination="scope">
<q-pagination
v-model="formFilter.page"
active-color="primary"
color="dark"
:max="Number(maxPage)"
:max-pages="5"
size="sm"
boundary-links
direction-links
@update:model-value="updatePage"
></q-pagination>
</template>
<template v-slot:header="props">
<q-tr :props="props">
<q-th class="text-center"> </q-th>
@ -338,7 +297,7 @@ watch(
</q-td>
</q-tr>
</template>
</d-table>
</p-table>
</div>
</q-card-section>
<q-separator />

View file

@ -13,8 +13,6 @@ interface DataOptionTechnique {
}
interface FormFilter {
page: number;
pageSize: number;
keyword: string;
type: string;
year: number;

View file

@ -1,7 +1,5 @@
interface FormQueryListProject {
year: number | null;
page: number;
pageSize: number;
org: string;
keyword: string;
status: string;

View file

@ -1,6 +1,8 @@
import { defineStore } from "pinia";
import { reactive, ref } from "vue";
import { calculateFiscalYear } from "@/utils/function";
import type { QTableProps } from "quasar";
import type { FormAddProject } from "@/modules/15_development/interface/request/Main";
@ -12,7 +14,7 @@ export const useDevelopmentDataStore = defineStore(
const projectStatus = ref<string>("ONGOING");
const statusEdit = ref<boolean>(false);
const formAddProject = reactive<FormAddProject>({
year: new Date().getFullYear(), //ปีงบประมาณ*
year: calculateFiscalYear(new Date()), //ปีงบประมาณ*
projectName: "", //ชื่อโครงการ/กิจกรรม/หลักสูตร*
reason: "", //หลักการและเหตุผล
objective: "", //วัตถุประสงค์
@ -65,7 +67,7 @@ export const useDevelopmentDataStore = defineStore(
function clearFormAddProject() {
/** ข้อมูลเบื้องต้น*/
formAddProject.year = new Date().getFullYear();
formAddProject.year = calculateFiscalYear(new Date());
formAddProject.projectName = "";
formAddProject.reason = " ";
formAddProject.objective = "";

View file

@ -9,9 +9,13 @@ import { useRoute, useRouter } from "vue-router";
import { useDevelopmentDataStore } from "@/modules/15_development/store/developmentStore";
import { useCounterMixin } from "@/stores/mixin";
import { checkPermission } from "@/utils/permissions";
import { calculateFiscalYear } from "@/utils/function";
import { usePagination } from "@/composables/usePagination";
import type {
NewPagination,
DataHistory,
DataOption,
ItemsMenu,
} from "@/modules/15_development/interface/index/Main";
@ -21,24 +25,16 @@ const router = useRouter();
const route = useRoute();
const store = useDevelopmentDataStore();
const { showLoader, hideLoader, messageError } = useCounterMixin();
const { pagination, params, onRequest } = usePagination("", getData);
const maxPage = ref<number>(1); //
const totalList = ref<number>(0); //
const formFilter = reactive({
root: null,
page: 1,
pageSize: 10,
keyword: "",
year: new Date().getFullYear(),
year: calculateFiscalYear(new Date()), //
});
const pagination = ref({
page: formFilter.page,
rowsPerPage: formFilter.pageSize,
});
const rows = ref<any[]>([]);
const agencyOp = ref<any[]>([]);
const rows = ref<DataHistory[]>([]);
const agencyOp = ref<DataOption[]>([]);
const itemMenu = ref<ItemsMenu[]>([
{
label: "ไฟล์ .xlsx",
@ -53,18 +49,15 @@ const itemMenu = ref<ItemsMenu[]>([
color: "red",
},
]);
const visibleColumns = ref<string[]>([
"year",
"citizenId",
"name",
"fullName",
"position",
"type",
"level",
"positionSide",
"posType",
"posLevel",
"projectName",
]);
const columns = ref<QTableProps["columns"]>([
{
name: "year",
@ -86,11 +79,11 @@ const columns = ref<QTableProps["columns"]>([
style: "font-size: 14px",
},
{
name: "name",
name: "fullName",
align: "left",
label: "ชื่อ-นามสกุล",
sortable: true,
field: "name",
field: "fullName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
@ -105,20 +98,20 @@ const columns = ref<QTableProps["columns"]>([
style: "font-size: 14px",
},
{
name: "type",
name: "posType",
align: "left",
label: "กลุ่มงาน",
sortable: true,
field: "type",
field: "posType",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "level",
name: "posLevel",
align: "left",
label: "ระดับชั้นงาน",
sortable: true,
field: "level",
field: "posLevel",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
@ -140,7 +133,7 @@ async function fetchListOrg() {
.get(config.API.developmentHistoryListOrg("employee", formFilter.year))
.then(async (res) => {
formFilter.root = null;
formFilter.page = 1;
pagination.value.page = 1;
rows.value = [];
const option = [{ name: "ทั้งหมด", id: null }];
const optionNew = await res.data.result.map((e: string) => ({
@ -149,7 +142,6 @@ async function fetchListOrg() {
}));
option.push(...optionNew);
agencyOp.value = option;
// agencyOp.value = res.data.result;
await getData();
})
.catch((err) => {
@ -170,9 +162,9 @@ function onDownload(type: string) {
year: formFilter.year,
root: formFilter.root,
})
.then((res) => {
.then(async (res) => {
const dataList = res.data.result;
genReportXLSX(dataList, "รายการประวัติฝึกอบรม/ดูงาน ลูกจ้าง", type);
await genReportXLSX(dataList, "รายการประวัติฝึกอบรม/ดูงาน ลูกจ้าง", type);
})
.catch((e) => {
messageError($q, e);
@ -182,7 +174,7 @@ function onDownload(type: string) {
});
}
/** edit page
/**
* @param id id ของ row
*/
function onEdit(id: string) {
@ -192,30 +184,20 @@ function onEdit(id: string) {
}
}
/** ดึงข้อมูล */
/** ฟังก์ชันดึงข้อมูลรายการประวัติฝึกอบรม/ดูงาน */
async function getData() {
showLoader();
formFilter.keyword = formFilter.keyword.trim()
formFilter.keyword = formFilter.keyword.trim();
await http
.post(config.API.developmentHistoryList("employee"), formFilter)
.post(config.API.developmentHistoryList("employee"), {
...params.value,
...formFilter,
keyword: formFilter.keyword.trim(),
})
.then((res) => {
const data = res.data.result.data;
maxPage.value = Math.ceil(res.data.result.total / formFilter.pageSize);
totalList.value = res.data.result.total;
rows.value = data.map((item: any) => ({
id: item.id ? item.id : null,
citizenId: item.citizenId ? item.citizenId : null,
name: item.fullName ? item.fullName : null,
prefix: item.prefix ? item.prefix : null,
firstName: item.firstName ? item.firstName : null,
lastName: item.lastName ? item.lastName : null,
position: item.position ? item.position : null,
type: item.posType ? item.posType : null,
level: item.posLevel ? item.posLevel : null,
positionSide: item.posExecutive ? item.posExecutive : null,
projectName: item.projectName ? item.projectName : null,
year: item.year ? item.year : null,
}));
const result = res.data.result;
pagination.value.rowsNumber = result.total;
rows.value = result.data;
})
.catch((e) => {
messageError($q, e);
@ -225,23 +207,12 @@ async function getData() {
});
}
/**
* function updatePagination
* @param newPagination อม Pagination ใหม
*/
function updatePagination(newPagination: NewPagination) {
formFilter.page = 1;
formFilter.pageSize = newPagination.rowsPerPage;
/** ฟังก์ชันดึงข้อมูลใหม่ */
function onfetchNewData() {
pagination.value.page = 1;
getData();
}
/** callbackFunction ทำเมื่อมีการอัปเดท pageSize*/
watch(
() => formFilter.pageSize,
() => {
getData();
}
);
/** ดึงข้อมูลเมื่อโหลดหน้าเสร็จสิ้น */
onMounted(async () => {
await fetchListOrg();
@ -252,6 +223,7 @@ onMounted(async () => {
<div class="toptitle text-dark col-12 row items-center">
รายการประวกอบรม/งาน กจาง
</div>
<q-card flat bordered class="q-pa-md">
<div class="row no-wrap shadow-1 justify-between">
<q-toolbar class="row col-8 q-pa-none q-gutter-x-sm">
@ -306,7 +278,7 @@ onMounted(async () => {
:options="agencyOp"
option-value="id"
option-label="name"
@update:model-value="(formFilter.page = 1), getData()"
@update:model-value="onfetchNewData()"
style="min-width: 150px"
map-options
emit-value
@ -358,7 +330,7 @@ onMounted(async () => {
ref="filterRef"
outlined
placeholder="ค้นหา"
@keydown.enter.prevent="(formFilter.page = 1), getData()"
@keydown.enter.prevent="onfetchNewData()"
>
<template v-slot:append>
<q-icon name="search" />
@ -384,7 +356,7 @@ onMounted(async () => {
</div>
<div class="col-12">
<d-table
<p-table
for="table"
ref="table"
:columns="columns"
@ -395,24 +367,10 @@ onMounted(async () => {
dense
class="custom-header-table"
:visible-columns="visibleColumns"
v-model:pagination="pagination"
:rows-per-page-options="[10, 25, 50, 100]"
@update:pagination="updatePagination"
v-model:pagination="pagination"
@request="onRequest"
>
<template v-slot:pagination="scope">
งหมด {{ totalList }} รายการ
<q-pagination
v-model="formFilter.page"
active-color="primary"
color="dark"
:max="Number(maxPage)"
:max-pages="5"
size="sm"
boundary-links
direction-links
@update:model-value="getData"
></q-pagination>
</template>
<template v-slot:header="props">
<q-tr :props="props">
<q-th auto-width></q-th>
@ -443,7 +401,7 @@ onMounted(async () => {
</q-td>
</q-tr>
</template>
</d-table>
</p-table>
</div>
</q-card>
</template>

View file

@ -1,5 +1,5 @@
<script setup lang="ts">
import { ref, onMounted, reactive, watch } from "vue";
import { ref, onMounted, reactive } from "vue";
import { useRouter } from "vue-router";
import { useQuasar, type QTableProps } from "quasar";
@ -9,39 +9,32 @@ import genReportXLSX from "@/plugins/genreportxlsx";
import { useDevelopmentDataStore } from "@/modules/15_development/store/developmentStore";
import { useCounterMixin } from "@/stores/mixin";
import { checkPermission } from "@/utils/permissions";
import { calculateFiscalYear } from "@/utils/function";
import { usePagination } from "@/composables/usePagination";
/**
* importType
*/
/** importType*/
import type {
DataOption,
DataHistory,
NewPagination,
ItemsMenu,
} from "@/modules/15_development/interface/index/Main";
import type { ResHistory } from "@/modules/15_development/interface/response/Main";
/** use*/
const $q = useQuasar();
const router = useRouter();
const store = useDevelopmentDataStore();
const { showLoader, hideLoader, messageError } = useCounterMixin();
const { pagination, params, onRequest } = usePagination("", getData);
const formFilter = reactive({
root: null,
page: 1,
pageSize: 10,
keyword: "",
year: new Date().getFullYear(),
year: calculateFiscalYear(new Date()), //
});
const agencyOp = ref<DataOption[]>([]); //
/**
* อม Table
*/
/** ข้อมูล Table*/
const rows = ref<DataHistory[]>([]);
const maxPage = ref<number>(1); //
const totalList = ref<number>(0); //
const columns = ref<QTableProps["columns"]>([
{
name: "year",
@ -63,11 +56,11 @@ const columns = ref<QTableProps["columns"]>([
style: "font-size: 14px",
},
{
name: "name",
name: "fullName",
align: "left",
label: "ชื่อ-นามสกุล",
sortable: true,
field: "name",
field: "fullName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
@ -82,29 +75,29 @@ const columns = ref<QTableProps["columns"]>([
style: "font-size: 14px",
},
{
name: "type",
name: "posType",
align: "left",
label: "ตำแหน่งประเภท",
sortable: true,
field: "type",
field: "posType",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "level",
name: "posLevel",
align: "left",
label: "ระดับตำแหน่ง",
sortable: true,
field: "level",
field: "posLevel",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "positionSide",
name: "posExecutive",
align: "left",
label: "ตําแหน่งทางการบริหาร",
sortable: true,
field: "positionSide",
field: "posExecutive",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
@ -118,18 +111,14 @@ const columns = ref<QTableProps["columns"]>([
style: "font-size: 14px",
},
]);
const pagination = ref({
page: formFilter.page,
rowsPerPage: formFilter.pageSize,
});
const visibleColumns = ref<string[]>([
"year",
"citizenId",
"name",
"fullName",
"position",
"type",
"level",
"positionSide",
"posType",
"posLevel",
"posExecutive",
"projectName",
]);
@ -149,16 +138,14 @@ const itemMenu = ref<ItemsMenu[]>([
},
]);
/**
* function เรยกขอมหนวยงาน
*/
/** function เรียกข้อมูหน่วยงาน*/
function fetchListOrg() {
showLoader();
http
.get(config.API.developmentHistoryListOrg("officer", formFilter.year))
.then(async (res) => {
formFilter.root = null;
formFilter.page = 1;
pagination.value.page = 1;
rows.value = [];
const option = [{ name: "ทั้งหมด", id: null }];
const optionNew = await res.data.result.map((e: string) => ({
@ -177,29 +164,20 @@ function fetchListOrg() {
});
}
/**
* function เรยกขอมลรายการประวการฝกอบรม/งาน าราชการกรงเทพมหานครสาม
*/
/** function เรียกข้อมูลรายการประวัติการฝึกอบรม/ดูงาน ข้าราชการกรุงเทพมหานครสามัญ*/
async function getData() {
showLoader();
formFilter.keyword = formFilter.keyword.trim();
await http
.post(config.API.developmentHistoryList("officer"), formFilter)
.post(config.API.developmentHistoryList("officer"), {
...params.value,
...formFilter,
keyword: formFilter.keyword.trim(),
})
.then((res) => {
const data = res.data.result.data;
maxPage.value = Math.ceil(res.data.result.total / formFilter.pageSize);
totalList.value = res.data.result.total;
rows.value = data.map((item: ResHistory) => ({
id: item.id ? item.id : null,
citizenId: item.citizenId ? item.citizenId : null,
name: item.fullName ? item.fullName : null,
position: item.position ? item.position : null,
type: item.posType ? item.posType : null,
level: item.posLevel ? item.posLevel : null,
projectName: item.projectName ? item.projectName : null,
positionSide: item.posExecutive ? item.posExecutive : null,
year: item.year ? item.year : null,
}));
const result = res.data.result;
pagination.value.rowsNumber = result.total;
rows.value = result.data;
})
.catch((e) => {
messageError($q, e);
@ -245,25 +223,12 @@ function onEdit(id: string) {
router.push(`/development/history/${id}`);
}
/**
* function updatePagination
* @param newPagination อม Pagination ใหม
*/
function updatePagination(newPagination: NewPagination) {
formFilter.page = 1;
formFilter.pageSize = newPagination.rowsPerPage;
/** ฟังก์ชันเรียกข้อมูลใหม่ */
function onfetchNewData() {
pagination.value.page = 1;
getData();
}
/**
* callbackFunction ทำเมอมการอปเดท pageSize
*/
watch(
() => formFilter.pageSize,
() => {
getData();
}
);
/** ดึงข้อมูลเมื่ออยู่ในหน้า */
onMounted(() => {
fetchListOrg();
@ -328,7 +293,7 @@ onMounted(() => {
:options="agencyOp"
option-value="id"
option-label="name"
@update:model-value="(formFilter.page = 1), getData()"
@update:model-value="onfetchNewData()"
style="min-width: 150px"
map-options
emit-value
@ -381,7 +346,7 @@ onMounted(() => {
ref="filterRef"
outlined
placeholder="ค้นหา"
@keydown.enter.prevent="(formFilter.page = 1), getData()"
@keydown.enter.prevent="onfetchNewData()"
>
<template v-slot:append>
<q-icon name="search" />
@ -405,7 +370,7 @@ onMounted(() => {
</q-toolbar>
</div>
<div class="col-12">
<d-table
<p-table
for="table"
ref="table"
:columns="columns"
@ -418,7 +383,7 @@ onMounted(() => {
:visible-columns="visibleColumns"
v-model:pagination="pagination"
:rows-per-page-options="[10, 25, 50, 100]"
@update:pagination="updatePagination"
@request="onRequest"
>
<template v-slot:header="props">
<q-tr :props="props">
@ -451,22 +416,7 @@ onMounted(() => {
</q-td>
</q-tr>
</template>
<template v-slot:pagination="scope">
งหมด {{ totalList }} รายการ
<q-pagination
v-model="formFilter.page"
active-color="primary"
color="dark"
:max="Number(maxPage)"
:max-pages="5"
size="sm"
boundary-links
direction-links
@update:model-value="getData"
></q-pagination>
</template>
</d-table>
</p-table>
</div>
</q-card>
</template>

View file

@ -1,5 +1,5 @@
<script setup lang="ts">
import { ref, onMounted, reactive, watch } from "vue";
import { ref, onMounted, reactive } from "vue";
import { useQuasar, type QTableProps } from "quasar";
import { useRoute, useRouter } from "vue-router";
@ -10,12 +10,12 @@ import { useStructureTree } from "@/stores/structureTree";
import genReportXLSX from "@/plugins/genreportxlsx";
import { useDevelopmentDataStore } from "@/modules/15_development/store/developmentStore";
import { useCounterMixin } from "@/stores/mixin";
import { updateCurrentPage } from "@/utils/function";
import { calculateFiscalYear } from "@/utils/function";
import { usePagination } from "@/composables/usePagination";
/**importType*/
import type {
DataOption,
NewPagination,
OrgTree,
} from "@/modules/15_development/interface/index/Main";
import type {
@ -44,6 +44,10 @@ const {
dialogRemove,
success,
} = useCounterMixin();
const { pagination, params, onRequest, checkAndUpdatePage } = usePagination(
"",
fetchListProject
);
const node = ref<OrgTree[]>([]); // /
const expanded = ref<string[]>([]);
@ -53,8 +57,6 @@ const filter = ref<string>(""); //ค้นหา เพิ่มโครงก
const filterMain = ref<string>(""); // /
const splitterModel = ref<number>(60); //
const modal = ref<boolean>(false); // dialog
const totalList = ref<number>(0); //
const totalPage = ref<number>(1); //
const statusOpt = ref<DataOption[]>([
{ id: "ONGOING", name: "กำลังดำเนินการ" },
@ -107,9 +109,7 @@ const formProject = reactive<FormProject>({
/** formQuery */
const formQuery = reactive<FormQueryListProject>({
year: new Date().getFullYear(),
page: 1,
pageSize: 10,
year: calculateFiscalYear(new Date()), //
org: "1",
keyword: "",
status: "ONGOING",
@ -121,19 +121,20 @@ const formQuery = reactive<FormQueryListProject>({
async function fetchListProject() {
showLoader();
await http
.get(
config.API.developmentMain +
`?page=${formQuery.page}&pageSize=${
formQuery.pageSize
}&keyword=${formQuery.keyword.trim()}&year=${formQuery.year}&status=${
formQuery.status
}&node=${formQuery.node}&nodeId=${formQuery.nodeId}`
)
.get(config.API.developmentMain, {
params: {
...params.value,
keyword: formQuery.keyword.trim(),
year: formQuery.year,
status: formQuery.status,
node: formQuery.node,
nodeId: formQuery.nodeId,
},
})
.then((res) => {
const data = res.data.result.data;
totalPage.value = Math.ceil(res.data.result.total / formQuery.pageSize);
totalList.value = res.data.result.total;
rows.value = data;
const result = res.data.result;
pagination.value.rowsNumber = result.total;
rows.value = result.data;
})
.catch((err) => {
messageError($q, err);
@ -161,7 +162,7 @@ function onAdd() {
* function fetchขอมลหนาแรกใหม
*/
function fetchListProjectNew() {
formQuery.page = 1;
pagination.value.page = 1;
fetchListProject();
}
@ -241,9 +242,7 @@ function updateSelected(data: DataTree) {
formProject.orgRevisionId = data.orgRevisionId;
}
/**
* function เลอกหนวยงานทจะคนหาโครงกา
*/
/** function เลือกหน่วยงานที่จะค้นหาโครงกา*/
function updateSelectedTreeMain(data: DataTree) {
if (
formQuery.node === data.orgLevel &&
@ -258,15 +257,6 @@ function updateSelectedTreeMain(data: DataTree) {
fetchListProjectNew(); // fetch
}
/**
* function updatePagination
* @param newPagination อม Pagination ใหม
*/
function updatePagination(newPagination: NewPagination) {
formQuery.page = 1;
formQuery.pageSize = newPagination.rowsPerPage;
}
/**
* function redirect หนาบนทกผล
* @param id โครงการ
@ -281,11 +271,7 @@ function onDelete(id: string) {
await http
.delete(config.API.developmentMain + `/${id}`)
.then(async () => {
formQuery.page = await updateCurrentPage(
formQuery.page,
totalList.value,
rows.value.length
);
await checkAndUpdatePage(rows.value.length);
await fetchListProject();
success($q, "ลบข้อมูลสำเร็จ");
})
@ -306,14 +292,6 @@ function onDetail(id: string) {
router.push(`/development-detail/${id}`);
}
/** callbackFunction ทำเมื่อมีการอัปเดท pageSize*/
watch(
() => formQuery.pageSize,
() => {
fetchListProject();
}
);
/** ดึงข้อมูลเมื่อโหลดหน้าเสร็จสิ้น */
onMounted(() => {
fetchActive();
@ -501,7 +479,7 @@ onMounted(() => {
</q-toolbar>
<div class="col-12">
<d-table
<p-table
for="table"
ref="table"
:columns="columns"
@ -511,9 +489,10 @@ onMounted(() => {
bordered
dense
class="custom-header-table"
:rows-per-page-options="[10, 25, 50, 100]"
:rows-per-page-options="[1, 10, 25, 50, 100]"
:visible-columns="visibleColumns"
@update:pagination="updatePagination"
v-model:pagination="pagination"
@request="onRequest"
>
<template v-slot:header="props">
<q-tr :props="props">
@ -589,21 +568,7 @@ onMounted(() => {
</q-td>
</q-tr>
</template>
<template v-slot:pagination="scope">
งหมด {{ totalList }} รายการ
<q-pagination
v-model="formQuery.page"
active-color="primary"
color="dark"
:max="Number(totalPage)"
size="sm"
boundary-links
direction-links
:max-pages="5"
@update:model-value="fetchListProject"
></q-pagination>
</template>
</d-table>
</p-table>
</div>
</div>
</div>

View file

@ -1,5 +1,5 @@
<script setup lang="ts">
import { ref, reactive, onMounted, watch } from "vue";
import { ref, reactive, onMounted } from "vue";
import { useQuasar, type QTableProps } from "quasar";
import { useRouter } from "vue-router";
@ -7,20 +7,17 @@ import http from "@/plugins/http";
import config from "@/app.config";
import { checkPermission } from "@/utils/permissions";
import { useCounterMixin } from "@/stores/mixin";
import genReportXLSX from "@/plugins/genreportxlsx";
import { calculateFiscalYear } from "@/utils/function";
import { usePagination } from "@/composables/usePagination";
import type {
DataOption,
NewPagination,
} from "@/modules/15_development/interface/index/Main";
import type { DataOption } from "@/modules/15_development/interface/index/Main";
import type { ListSholarship } from "@/modules/15_development/interface/response/Scholarship";
/** importStore*/
/** use*/
/** use */
const $q = useQuasar();
const router = useRouter();
const { showLoader, hideLoader, messageError } = useCounterMixin();
const { pagination, params, onRequest } = usePagination("", fetchList);
/** หัวตาราง */
const rows = ref<ListSholarship[]>([]);
const columns = ref<QTableProps["columns"]>([
@ -141,32 +138,27 @@ const scholarshipTypeOp = ref<DataOption[]>([
]);
const formQuery = reactive({
page: 1,
pageSize: 10,
year: new Date().getFullYear(),
year: calculateFiscalYear(new Date()), //
type: "DOMESTICE",
keyword: "",
});
const totalList = ref<number>(1); //
const maxPage = ref<number>(1);
/** ดึงข้อมูล */
function fetchList() {
async function fetchList() {
showLoader();
http
.get(
config.API.devScholarship +
`?page=${formQuery.page}&pageSize=${
formQuery.pageSize
}&keyword=${formQuery.keyword.trim()}&year=${
formQuery.year
}&scholarshipType=${formQuery.type}`
)
await http
.get(config.API.devScholarship, {
params: {
...params.value,
keyword: formQuery.keyword.trim(),
year: formQuery.year,
scholarshipType: formQuery.type,
},
})
.then((res) => {
const data = res.data.result.data;
maxPage.value = Math.ceil(res.data.result.total / formQuery.pageSize);
totalList.value = res.data.result.total;
rows.value = data;
const result = res.data.result;
pagination.value.rowsNumber = result.total;
rows.value = result.data;
})
.catch((err) => {
messageError($q, err);
@ -178,7 +170,7 @@ function fetchList() {
/** ฟังชั่นดึงข้อมูล รายการ ใหม่ */
function fetchNewList() {
formQuery.page = 1;
pagination.value.page = 1;
fetchList();
}
@ -189,15 +181,12 @@ function onClickAddOrView(status: boolean = false, id: string = "") {
: router.push("/development/scholarship/add");
}
/**
* function updatePagination
* @param newPagination อม Pagination ใหม
*/
function updatePagination(newPagination: NewPagination) {
formQuery.page = 1;
formQuery.pageSize = newPagination.rowsPerPage;
/** ฟังชั่นดูรายละเอียด */
function onDetail(id: string) {
router.push(`/development/scholarship-detail/${id}`);
}
/** ฟังก์ชั่นแปลงสถานะ */
function conventStatus(val: string) {
switch (val) {
case "PENDING":
@ -211,35 +200,6 @@ function conventStatus(val: string) {
}
}
// /** download file */
// function onDownload() {
// showLoader();
// http
// .get(config.API.developmentReportScholarship())
// .then((res) => {
// const dataList = res.data.result;
// genReportXLSX(dataList, " /");
// })
// .catch((e) => {
// messageError($q, e);
// })
// .finally(() => {
// hideLoader();
// });
// }
/** เช็ค เมื่อมีการเปลี่ยนค่าของ ข้อมูลในเเถว */
watch(
() => formQuery.pageSize,
() => {
fetchNewList();
}
);
function onDetail(id: string) {
router.push(`/development/scholarship-detail/${id}`);
}
/** ดึงข้อมูลเมื่ออยู่ในหน้า */
onMounted(() => {
fetchList();
@ -250,6 +210,7 @@ onMounted(() => {
<div class="toptitle text-dark col-12 row items-center">
รายการขาราชการฯ ไดบทนการศกษา/กอบรม
</div>
<q-card flat bordered class="q-pa-md">
<q-toolbar class="q-pa-none">
<div class="row q-gutter-sm">
@ -359,7 +320,7 @@ onMounted(() => {
</q-toolbar>
<div class="col-12">
<d-table
<p-table
for="table"
ref="table"
:columns="columns"
@ -371,7 +332,8 @@ onMounted(() => {
class="custom-header-table"
:visible-columns="visibleColumns"
:rows-per-page-options="[10, 25, 50, 100]"
@update:pagination="updatePagination"
v-model:pagination="pagination"
@request="onRequest"
>
<template v-slot:header="props">
<q-tr :props="props">
@ -418,21 +380,7 @@ onMounted(() => {
</q-td>
</q-tr>
</template>
<template v-slot:pagination="scope">
งหมด {{ totalList }} รายการ
<q-pagination
v-model="formQuery.page"
active-color="primary"
color="dark"
:max="Number(maxPage)"
size="sm"
boundary-links
direction-links
:max-pages="5"
@update:model-value="fetchList"
></q-pagination>
</template>
</d-table>
</p-table>
</div>
</q-card>
</template>

View file

@ -6,6 +6,7 @@ import { checkPermission } from "@/utils/permissions";
import { useCounterMixin } from "@/stores/mixin";
import { useCommandListStore } from "@/modules/18_command/store/ListStore";
import { usePagination } from "@/composables/usePagination";
import { calculateFiscalYear } from "@/utils/function";
import http from "@/plugins/http";
import config from "@/app.config";
@ -36,7 +37,7 @@ const tabsManu = ref<ItemTabs[]>([
]);
//
const queryParams = reactive<FormQuery>({
year: new Date().getFullYear(), //
year: calculateFiscalYear(new Date()), //
keyword: "", //
commandTypeId: "",
});

View file

@ -10,6 +10,7 @@ import http from "@/plugins/http";
import config from "@/app.config";
import { checkPermission } from "@/utils/permissions";
import { useCounterMixin } from "@/stores/mixin";
import { calculateFiscalYear } from "@/utils/function";
import type {
OptionData,
@ -23,7 +24,7 @@ const route = useRoute();
const { messageError, showLoader, hideLoader } = useCounterMixin();
const loadingBtn = ref<boolean>(false);
const year = ref<number>(new Date().getFullYear());
const year = ref<number>(calculateFiscalYear(new Date())); //
const organization = ref<string>("");
const organizationOpsMain = ref<OptionData[]>([]);
@ -194,7 +195,7 @@ async function getOrg(id: string) {
}
function clearFilter() {
year.value = new Date().getFullYear();
year.value = calculateFiscalYear(new Date());
organization.value = "";
typeReport.value = "";
pdfSrc.value = undefined;
@ -323,7 +324,8 @@ onMounted(async () => {
option-value="id"
option-label="name"
@update:model-value="
(organization = ''), (year = new Date().getFullYear())
(organization = ''),
(year = calculateFiscalYear(new Date()))
"
/>
</div>

View file

@ -9,6 +9,7 @@ import config from "@/app.config";
import genReportXLSX from "@/plugins/genreportxlsx";
import { useStructureTree } from "@/stores/structureTree";
import { checkPermission } from "@/utils/permissions";
import { calculateFiscalYear } from "@/utils/function";
import { useCounterMixin } from "@/stores/mixin";
@ -39,7 +40,7 @@ const organizationName = computed(() => {
);
});
const year = ref<number>(new Date().getFullYear());
const year = ref<number>(calculateFiscalYear(new Date())); //
const detailReport = ref<any>();
@ -157,7 +158,7 @@ function nextPage() {
function clearFilter() {
pdfSrc.value = undefined;
detailReport.value = undefined;
year.value = new Date().getFullYear();
year.value = calculateFiscalYear(new Date());
// org.value = "";
nodeId.value = "";
// nodeName.value = "";

View file

@ -9,6 +9,7 @@ import { useCounterMixin } from "@/stores/mixin";
import { useSalaryListSDataStore } from "@/modules/13_salary/store/SalaryListsStore";
import { useSalaryEmployeeListSDataStore } from "@/modules/13_salary/store/SalaryEmployeeListsStore";
import genReportXLSX from "@/plugins/genreportxlsx";
import { calculateFiscalYear } from "@/utils/function";
import config from "@/app.config";
import http from "@/plugins/http";
@ -27,7 +28,7 @@ const checkId = ref<string>("");
const isLoadStructureTree = ref<boolean>(true);
// const expandedModal = ref<boolean>(false);
// const org = ref<string>("");
const year = ref<number>(new Date().getFullYear());
const year = ref<number>(calculateFiscalYear(new Date())); //
const isLoadFilePdf = ref<boolean>(false);
const employeeClass = ref<string>("officer");
const employeeClassOption = ref<DataOption[]>([
@ -327,7 +328,7 @@ function nextPage() {
function clearFilter() {
checkId.value = "";
year.value = new Date().getFullYear();
year.value = calculateFiscalYear(new Date());
round.value = "";
group.value = "GROUP1";
report.value = null;
@ -538,7 +539,9 @@ onMounted(() => {
<q-tooltip>
<div v-if="group === 'GROUP1'">
<div>วไป: ปฏงาน, ชำนาญงาน, อาวโส</div>
<div>ชาการ: ปฏการ, ชำนาญการ, ชำนาญการพเศษ</div>
<div>
ชาการ: ปฏการ, ชำนาญการ, ชำนาญการพเศษ
</div>
<div>อำนวยการ: </div>
</div>
<div v-else>

View file

@ -105,6 +105,13 @@ const router = createRouter({
name: "auth",
component: () => import("@/views/auth.vue"),
},
{
path: "/test-times",
name: "test-times",
component: () => {
return import("@/views/TestTimes.vue");
},
},
],
scrollBehavior(to, from, savedPosition) {

View file

@ -17,3 +17,14 @@ export async function updateCurrentPage(
}
return page;
}
/**
*
*
* @param date
* @returns
*/
export function calculateFiscalYear(date: Date) {
const month = date.getMonth() + 1;
return month >= 10 ? date.getFullYear() + 1 : date.getFullYear();
}

3
src/views/TestTimes.vue Normal file
View file

@ -0,0 +1,3 @@
<template>
<h1 class="text-center">{{ new Date() }}</h1>
</template>