รายการเลื่อนเงินเดือนลูกจ้างประจำ

This commit is contained in:
DESKTOP-1R2VSQH\Lenovo ThinkPad E490 2024-03-14 09:53:01 +07:00
parent d0f721253c
commit 26c7a66906
13 changed files with 3008 additions and 3 deletions

View file

@ -0,0 +1,3 @@
<template>
<q-card class="q-pa-sm"> แสดง dashboard สำหร สกจ. </q-card>
</template>

View file

@ -0,0 +1,316 @@
<script setup lang="ts">
import { ref, reactive, watch } from "vue";
import { useQuasar } from "quasar";
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";
/** importComponents*/
import Header from "@/components/DialogHeader.vue";
/** importStore*/
import { useCounterMixin } from "@/stores/mixin";
import { useSalaryEmployeeListSDataStore } from "@/modules/13_salary/store/SalaryEmployeeListsStore";
/** use*/
const $q = useQuasar();
const store = useSalaryEmployeeListSDataStore();
const { messageError, showLoader, hideLoader, dialogConfirm, success } =
useCounterMixin();
/** props*/
const modal = defineModel<boolean>("modal", { required: true });
const props = defineProps({
fetchData: {
type: Function,
},
});
/** Table*/
const columns = ref<QTableProps["columns"]>([
{
name: "no",
align: "left",
label: "ลำดับ",
sortable: false,
field: "no",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "citizenId",
align: "left",
label: "เลขประจำตัวประชาชน",
sortable: true,
field: "citizenId",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "fullName",
align: "left",
label: "ชื่อ-นามสกุล",
field: "fullName",
sortable: true,
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "position",
align: "left",
label: "ตำแหน่งในสายงาน",
sortable: true,
field: "position",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "posType",
align: "left",
label: "ประเภทตำเเหน่ง",
sortable: true,
field: "posType",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "posLevel",
align: "left",
label: "ระดับตำเเหน่ง",
sortable: true,
field: "posLevel",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
]);
const rows = ref<DataPerson[]>([]);
/** ข้อมูุลค้นหา*/
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 = "";
}
/** function เรียกรายชื่อ คนเลื่อนเงินเดือน*/
function fetchListPerson() {
showLoader();
formFilter.rootId = store.rootId;
formFilter.period = store.roundMainCode;
formFilter.year = store.roundYear;
http
.post(config.API.salaryListPerson, formFilter)
.then((res) => {
const data = res.data.result.data;
maxPage.value = Math.ceil(res.data.result.total / formFilter.pageSize);
rows.value = data;
})
.catch((err) => {
messageError($q, err);
closeModal();
})
.finally(() => {
hideLoader();
});
}
/**
* function นยนการเพมคนเลอนเงนเดอน
* @param data อมลคนทเพ
*/
function onClickAddPerson(data: DataPerson) {
const body: DataPersonReq = {
id: store.groupId,
type: store.tabType,
...data,
};
dialogConfirm(
$q,
() => {
http
.post(config.API.salaryPeriodProfile, body)
.then(() => {
props.fetchData?.();
success($q, "เพื่มรายชื่อสำเร็จ");
closeModal();
})
.catch((err) => {
messageError($q, err);
})
.finally(() => {
hideLoader();
});
},
"ยืนยันการเพิ่มรายชื่อ",
"ต้องการยืนยันการเพิ่มรายชื่อนี้ใช่หรือไม่?"
);
}
/** function updatePage*/
async function updatePagePagination() {
fetchListPerson();
}
/** function updatePageSize*/
function updatePageSizePagination(newPagination: NewPagination) {
formFilter.page = 1;
formFilter.pageSize = newPagination.rowsPerPage;
}
/** function ค้นหาข้อมูลตาม keyword*/
function searchData() {
formFilter.page = 1;
fetchListPerson();
}
/** callblack function เรียกข้อมูลรายชื่อคนเลื่อนเงินเดือน เมื่อมีการเปิด Popup*/
watch(
() => modal.value,
() => {
if (modal.value) {
fetchListPerson();
}
}
);
/** callblack function เรียกข้อมูลรายชื่อคนเลื่อนเงินเดือน เมื่อมีการเปลี่ยน PageSize*/
watch(
() => formFilter.pageSize,
() => {
updatePagePagination();
}
);
</script>
<template>
<q-dialog v-model="modal" persistent>
<q-card style="max-width: 100vw">
<Header :tittle="'เพิ่มคนเลื่อนเงินเดือน'" :close="closeModal" />
<q-separator />
<q-card-section class="scroll" style="max-height: 70vh">
<div class="row q-col-gutter-sm">
<div class="col-12">
<q-input
borderless
dense
debounce="300"
outlined
placeholder="ค้นหา"
v-model="formFilter.keyword"
@keydown.enter.prevent="searchData"
>
<template v-slot:append>
<q-icon name="search" />
</template>
</q-input>
</div>
<div class="col-12">
<d-table
ref="table"
:columns="columns"
:rows="rows"
row-key="id"
flat
bordered
:paging="true"
dense
:rows-per-page-options="[10, 25, 50, 100]"
@update:pagination="updatePageSizePagination"
>
<template v-slot:header="props">
<q-tr :props="props">
<q-th
v-for="col in props.cols"
:key="col.name"
:props="props"
>
<span class="text-weight-medium">{{ col.label }}</span>
</q-th>
<q-th auto-width></q-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'">
{{
(formFilter.page - 1) * formFilter.pageSize +
props.rowIndex +
1
}}
</div>
<div v-else-if="col.name === 'fullName'">
{{
`${props.row.prefix}${props.row.firstName} ${props.row.lastName}`
}}
</div>
<div v-else>
{{ col.value ? col.value : "-" }}
</div>
</q-td>
<q-td>
<q-btn
outline
color="primary"
label="เพิ่ม"
@click="onClickAddPerson(props.row)"
/>
</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>
</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>
<style scoped></style>

View file

@ -0,0 +1,112 @@
<script setup lang="ts">
import { ref } from "vue";
import { useQuasar } from "quasar";
import http from "@/plugins/http";
import config from "@/app.config";
/** importComponents*/
import Header from "@/components/DialogHeader.vue";
/** importStore*/
import { useCounterMixin } from "@/stores/mixin";
/** use*/
const $q = useQuasar();
const mixin = useCounterMixin();
const { dialogConfirm, success, messageError } = mixin;
/** props*/
const modal = defineModel<boolean>("modal", { required: true });
const amount = defineModel<number | null>("amount", { required: true });
const profileId = defineModel<string>("profileId", { required: true });
const props = defineProps({
fetchData: {
type: Function,
},
});
const amountRef = ref<any>();
/** ฟังก์ชั่นสำหรับ validate ฟอร์ม */
function validateForm() {
if (amountRef.value.validate()) {
onSubmit();
}
}
/** function ปืด Popup */
function close() {
modal.value = false;
amount.value = null;
}
/** function ยืนยันการบันทึกข้อมูล*/
function onSubmit() {
dialogConfirm($q, () => {
if (amount.value !== null) {
const amountString: string = amount.value.toString();
const body = {
profileId: profileId.value,
amount:
typeof amount.value === "number"
? amount.value
: Number(amountString.replace(/,/g, "")),
};
http
.post(config.API.salaryPeriod() + `/change/amount`, body)
.then(() => {
success($q, "บันทึกข้อมูลสำเร็จ");
props.fetchData?.();
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
close();
});
}
});
}
</script>
<template>
<q-dialog v-model="modal" persistent>
<q-card class="col-12" style="width: 30%">
<Header :tittle="`แก้ไขเงินเดือน`" :close="close" />
<q-separator />
<q-card-section class="scroll" style="max-height: 70vh">
<div class="q-gutter-y-sm">
<q-input
ref="amountRef"
dense
outlined
v-model="amount"
label="เงินเดือนฐาน"
mask="###,###,###,###"
reverse-fill-mask
:rules="[(val) => !!val || `${'กรุณากรอกเงินเดือนฐาน'}`]"
lazy-rules
hide-bottom-space
/>
</div>
</q-card-section>
<q-separator />
<form @submit.prevent="validateForm">
<q-card-actions align="right" class="bg-white text-teal">
<q-btn
type="submit"
for="#submitForm"
unelevated
dense
class="q-px-md items-center"
color="light-blue-10"
label="บันทึก"
/>
</q-card-actions>
</form>
</q-card>
</q-dialog>
</template>
<style lang="scss" scoped></style>

View file

@ -0,0 +1,160 @@
<script setup lang="ts">
import { ref } from "vue";
import Header from "@/components/DialogHeader.vue";
const modal = defineModel<boolean>("modal", { required: true });
const separator = ref<any>("cell");
/** ปิด Dialog */
function closeDialog() {
modal.value = !modal.value;
}
</script>
<template>
<q-dialog v-model="modal" persistent>
<q-card class="col-12" full-width>
<Header
tittle="หลักเกณฑ์การพิจารณาเลื่อนขั้นเงินข้าราชการ"
:close="closeDialog"
/>
<q-separator />
<q-card-section>
<div class="q-pa-md">
<q-markup-table
:separator="separator"
flat
bordered
class="custom-header-table"
>
<thead>
<tr>
<th class="text-center">หลกเกณฑในการพจารณาเลอนขนฯ</th>
<th class="text-center">หนงข</th>
<th class="text-center">ครงข</th>
<th class="text-center">ไมไดบการเลอนข</th>
</tr>
</thead>
<tbody>
<!-- อ1 -->
<tr>
<td class="text-left">1. ผลการประเมนผลการปฎราชการ</td>
<td class="text-center">
ผลการประเมนผลในระดบดเด<br />(90-100%)
</td>
<td class="text-center">
ผลการประเมนเปนทยอมรบได<br />(60-89%)
</td>
<td class="text-center">
ผลการประเมนตองปรบปร<br />(ำกว 60%)
</td>
</tr>
<!-- อ2 -->
<tr>
<td class="text-left">
2. ระยะเวลาการปฎราชการในรอบครงป
</td>
<td class="text-center">ไมอยกว 4 เดอน</td>
<td class="text-center">ไมอยกว 4 เดอน</td>
<td class="text-center">
อยกว 4 เดอน<br />(บรรจใหม ลาศกษา กอบรมดงาน)
</td>
</tr>
<!-- อ3 -->
<tr>
<td class="text-left">3. การลงโทษทางว</td>
<td class="text-center">
กสงลงโทษไมหนกกว<br />ภาคทณฑ
</td>
<td class="text-center">
กสงลงโทษไมหนกกว<br />ภาคทณฑ
</td>
<td class="text-center">
กสงลงโทษไมหนกกว<br />ภาคทณฑ
</td>
</tr>
<!-- อ4 -->
<tr>
<td class="text-left">4. กราชการ</td>
<td class="text-center">ไมกสงพกราชการ</td>
<td class="text-center">
กสงพกราชการ<br />ไมเก 2 เดอน
</td>
<td class="text-center">
กสงพกราชการ<br />ไมเก 2 เดอน
</td>
</tr>
<!-- อ5 -->
<tr>
<td class="text-left">5. ขาดราชการ</td>
<td class="text-center">ไมขาดราชการ</td>
<td class="text-center">ไมขาดราชการ</td>
<td class="text-center">ไมขาดราชการ</td>
</tr>
<!-- อ6 -->
<tr class="vertical-top">
<td class="text-left">6. นลา</td>
<td class="text-left">
<p class="q-mb-none txt-under">
ไมเก 5 คร 23 <br />สายไมเก 5 คร
</p>
<p class="q-mb-none">(บเฉพาะการลาปวยลาก)</p>
<p class="text-bold q-mb-none">ยกเว</p>
<p class="q-mb-none">
- ลาอปสมบท
<br />
- ลาคลอดบตร (ไมเก 90 )
<br />
* กรณลาปวยซงจำเปนตองรกษาตวเปนเวลานาน<br />ไมาคราวเดยวหรอหลายคราว
รวมก<span class="txt-under">ไมเก</span> 60 นทำการ
</p>
</td>
<td class="text-left">
<p class="txt-under q-mb-none">
ไมเก 8 คร 23 <br />สายไมเก 23 คร
</p>
<p class="q-mb-none">(บเฉพาะการลาปวยลาก)</p>
<p class="text-bold q-mb-none">ยกเว</p>
<p class="q-mb-none">
- ลาอปสมบท
<br />
- ลาคลอดบตร (ไมเก 90 )
<br />
* กรณลาปวยซงจำเปนตองรกษาตวเปนเวลานาน<br />ไมาคราวเดยวหรอหลายคราว
รวมก<span class="txt-under">ไมเก</span> 60 นทำการ
</p>
</td>
<td class="text-left">
<p class="txt-under q-mb-none">
ไมเก 8 คร 23 <br />สายไมเก 23 คร
</p>
<p>(บเฉพาะการลาปวยลาก)</p>
<br />
<br />
<p class="q-mb-none">
* กรณลาปวยซงจำเปนตองรกษาตวเปนเวลานาน<br />ไมาคราวเดยวหรอหลายคราว
รวมก<span class="txt-under">ไมเก</span> 60 นทำการ
</p>
</td>
</tr>
</tbody>
</q-markup-table>
</div>
</q-card-section>
</q-card>
</q-dialog>
</template>
<style lang="scss" scoped>
.txt-under {
text-decoration: underline;
}
.q-table th {
font-size: 14px !important;
}
</style>

View file

@ -0,0 +1,135 @@
<script setup lang="ts">
import { ref, defineModel, watch } from "vue";
import { useQuasar } from "quasar";
import http from "@/plugins/http";
import config from "@/app.config";
/** importComponents*/
import Header from "@/components/DialogHeader.vue";
/** importStore*/
import { useCounterMixin } from "@/stores/mixin";
import { useSalaryEmployeeListSDataStore } from "@/modules/13_salary/store/SalaryEmployeeListsStore";
/** use*/
const $q = useQuasar();
const store = useSalaryEmployeeListSDataStore();
const { dialogConfirm, success, messageError, showLoader, hideLoader } =
useCounterMixin();
/** props*/
const modal = defineModel<boolean>("modal", { required: true });
const profileId = defineModel<string>("profileId", { required: true });
const props = defineProps({
group: { type: String },
fetchData: {
type: Function,
},
});
/** ตัวแปร*/
const group = ref<string>("");
const groupRef = ref<any>(null);
const isReadonly = ref<boolean>(false); //
/*** ฟังก์ชั่นสำหรับ validate ฟอร์ม */
function validateForm() {
if (groupRef.value.validate()) {
onSubmit();
}
}
/** function ปืด Popup */
function close() {
modal.value = false;
group.value = "";
}
/** function ยืนยันการบันทึกข้อมูล*/
function onSubmit() {
dialogConfirm($q, () => {
showLoader();
const body = {
profileId: profileId.value,
groupId: group.value,
};
http
.post(config.API.salaryPeriod() + `/change/group`, body)
.then(() => {
success($q, "บันทึกข้อมูลสำเร็จ");
props.fetchData?.();
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
hideLoader();
close();
});
});
}
watch(
() => modal.value,
() => {
if (modal.value) {
group.value =
props.group === "กลุ่ม1" ? store.groupOp[1].id : store.groupOp[0].id;
}
}
);
function inputEdit(val: boolean) {
return {
"full-width cursor-pointer inputgreen ": val,
"full-width cursor-pointer inputgreen": !val,
};
}
</script>
<template>
<q-dialog v-model="modal" persistent>
<q-card class="col-12" style="width: 30%">
<Header :tittle="`ย้ายกลุ่ม`" :close="close" />
<q-separator />
<q-card-section class="scroll" style="max-height: 70vh">
<div class="q-gutter-y-sm">
<q-select
ref="groupRef"
:class="inputEdit(isReadonly)"
v-model="group"
label="กลุ่ม"
dense
outlined
emit-value
map-options
option-label="name"
option-value="id"
:options="store.groupOp.filter((e) => e.name !== props.group)"
:rules="[(val) => !!val || `${'กรุณากลุ่ม'}`]"
lazy-rules
hide-bottom-space
/>
</div>
</q-card-section>
<q-separator />
<form @submit.prevent="validateForm">
<q-card-actions align="right" class="bg-white text-teal">
<!-- <q-btn flat label="OK" v-close-popup /> -->
<q-btn
type="submit"
for="#submitForm"
unelevated
dense
class="q-px-md items-center"
color="light-blue-10"
label="บันทึก"
/>
</q-card-actions>
</form>
</q-card>
</q-dialog>
</template>
<style lang="scss" scoped></style>

View file

@ -0,0 +1,178 @@
<script setup lang="ts">
import { ref, computed, watch } from "vue";
import { useQuasar } from "quasar";
import http from "@/plugins/http";
import config from "@/app.config";
/** importComponents*/
import Header from "@/components/DialogHeader.vue";
/** importStore*/
import { useCounterMixin } from "@/stores/mixin";
import { useSalaryEmployeeListSDataStore } from "@/modules/13_salary/store/SalaryEmployeeListsStore";
/** use*/
const $q = useQuasar();
const store = useSalaryEmployeeListSDataStore();
const {
dialogConfirm,
success,
messageError,
showLoader,
hideLoader,
dialogMessageNotify,
} = useCounterMixin();
/**porps*/
const modal = defineModel<boolean>("modal", { required: true });
const profileId = defineModel<string>("profileId", { required: true });
const props = defineProps({
typeLevel: { type: String, required: true },
isReserve: { type: Boolean, required: true },
fetchData: {
type: Function,
},
});
const type = ref<string>("");
const typeRef = ref<any>(null);
const isReadonly = ref<boolean>(false); //
const isChange = ref<boolean>(false); //
const isReserve = ref<boolean>(false); //
const typeRangeOps = computed(() => {
return store.roundMainCode == "OCT"
? [
{ id: "NONE", name: "ไม่ได้เลื่อน" },
{ id: "HAFT", name: "0.5 ขั้น" },
{ id: "FULL", name: "1 ขั้น" },
{ id: "FULLHAFT", name: "1.5 ขั้น" },
]
: [
{ id: "NONE", name: "ไม่ได้เลื่อน" },
{ id: "HAFT", name: "0.5 ขั้น" },
{ id: "FULL", name: "1 ขั้น" },
];
});
/*** ฟังก์ชั่นสำหรับ validate ฟอร์ม */
function validateForm() {
if (typeRef.value.validate()) {
// if (
// store.roundMainCode === "APR" &&
// store.remaining === 0 &&
// type.value === "FULL"
// ) {
// dialogMessageNotify($q, "");
// } else {
onSubmit();
// }
}
}
/** function ปืด Popup */
function close() {
modal.value = false;
type.value = "";
}
/** function ยืนยันการบันทึกข้อมูล*/
function onSubmit() {
dialogConfirm($q, () => {
showLoader();
const body = {
profileId: profileId.value,
type: type.value,
isReserve: isReserve.value,
};
http
.post(config.API.salaryPeriod() + `/change/type`, body)
.then(() => {
success($q, "บันทึกข้อมูลสำเร็จ");
props.fetchData?.();
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
close();
hideLoader();
});
});
}
watch(
() => modal.value,
() => {
type.value = props.typeLevel == 'PENDING' ? "" : props.typeLevel;
isReserve.value = props.isReserve;
isChange.value = false;
}
);
function inputEdit(val: boolean) {
return {
"full-width cursor-pointer inputgreen ": val,
"full-width cursor-pointer inputgreen": !val,
};
}
</script>
<template>
<q-dialog v-model="modal" persistent>
<q-card class="col-12" style="width: 30%">
<Header :tittle="`ย้ายขั้น`" :close="close" />
<q-separator />
<q-card-section class="scroll" style="max-height: 70vh">
<div class="q-gutter-y-sm">
<q-select
ref="typeRef"
:class="inputEdit(isReadonly)"
v-model="type"
label="เลื่อนขั้น"
dense
outlined
emit-value
map-options
option-label="name"
option-value="id"
:options="typeRangeOps"
:rules="[(val) => !!val || `${'กรุณาเลือก ขั้น'}`]"
lazy-rules
hide-bottom-space
@update:model-value="isChange = true"
/>
<!-- :options="typeRangeOps.filter((e) => e.id !== store.tabType)" -->
<q-checkbox
v-if="type === 'FULL'"
keep-color
label="สำรอง"
dense
v-model="isReserve"
@update:model-value="isChange = true"
/>
</div>
</q-card-section>
<q-separator />
<form @submit.prevent="validateForm">
<q-card-actions align="right" class="bg-white text-teal">
<!-- <q-btn flat label="OK" v-close-popup /> -->
<q-btn
:disabled="!isChange"
type="submit"
for="#submitForm"
unelevated
dense
class="q-px-md items-center"
color="light-blue-10"
label="บันทึก"
/>
</q-card-actions>
</form>
</q-card>
</q-dialog>
</template>
<style lang="scss" scoped></style>

View file

@ -0,0 +1,176 @@
<script setup lang="ts">
import { ref, computed, watch } from "vue";
import { useQuasar } from "quasar";
import http from "@/plugins/http";
import config from "@/app.config";
/** importComponents*/
import Header from "@/components/DialogHeader.vue";
/** importStore*/
import { useCounterMixin } from "@/stores/mixin";
import { useSalaryEmployeeListSDataStore } from "@/modules/13_salary/store/SalaryEmployeeListsStore";
/** use*/
const $q = useQuasar();
const store = useSalaryEmployeeListSDataStore();
const {
dialogConfirm,
success,
messageError,
showLoader,
hideLoader,
dialogMessageNotify,
} = useCounterMixin();
/**porps*/
const modal = defineModel<boolean>("modal", { required: true });
const profileId = defineModel<string>("id", { required: true });
const props = defineProps({
isPunish: { type: Boolean, required: true },
isSuspension: { type: Boolean, required: true },
isAbsent: { type: Boolean, required: true },
isLeave: { type: Boolean, required: true },
fetchData: {
type: Function,
},
});
const type = ref<string>("");
const typeRef = ref<any>(null);
const isReadonly = ref<boolean>(false); //
const isPunish = ref<boolean>(false); //
const isSuspension = ref<boolean>(false); //
const isAbsent = ref<boolean>(false); //
const isLeave = ref<boolean>(false); //
const typeRangeOps = computed(() => {
return store.roundMainCode == "OCT"
? [
{ id: "NONE", name: "ไม่ได้เลื่อน" },
{ id: "HAFT", name: "0.5 ขั้น" },
{ id: "FULL", name: "1 ขั้น" },
{ id: "FULLHAFT", name: "1.5 ขั้น" },
]
: [
{ id: "NONE", name: "ไม่ได้เลื่อน" },
{ id: "HAFT", name: "0.5 ขั้น" },
{ id: "FULL", name: "1 ขั้น" },
];
});
/*** ฟังก์ชั่นสำหรับ validate ฟอร์ม */
function validateForm() {
onSubmit();
}
/** function ปืด Popup */
function close() {
modal.value = false;
type.value = "";
}
/** function ยืนยันการบันทึกข้อมูล*/
function onSubmit() {
dialogConfirm($q, () => {
showLoader();
const body = {
isPunish: isPunish.value,
isSuspension: isSuspension.value,
isAbsent: isAbsent.value,
isLeave: isLeave.value,
};
http
.put(config.API.salaryProperty(profileId.value), body)
.then(() => {
success($q, "บันทึกข้อมูลสำเร็จ");
props.fetchData?.();
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
close();
hideLoader();
});
});
}
watch(
() => modal.value,
() => {
isPunish.value = props.isPunish;
isSuspension.value = props.isSuspension;
isAbsent.value = props.isAbsent;
isLeave.value = props.isLeave;
}
);
function inputEdit(val: boolean) {
return {
"full-width cursor-pointer inputgreen ": val,
"full-width cursor-pointer inputgreen": !val,
};
}
</script>
<template>
<q-dialog v-model="modal" persistent>
<q-card class="col-12" style="width: 20%">
<Header :tittle="`แก้ไขคุณสมบัติ`" :close="close" />
<q-separator />
<q-card-section class="scroll" style="max-height: 70vh">
<div class="q-gutter-y-sm column">
<q-checkbox
toggle-indeterminate
keep-color
label="ไม่ถูกลงโทษทางวินัย"
dense
v-model="isPunish"
/>
<q-checkbox
toggle-indeterminate
keep-color
label="ไม่ถูกพักราชการ"
dense
v-model="isSuspension"
/>
<q-checkbox
toggle-indeterminate
keep-color
label="ไม่ขาดราชการ"
dense
v-model="isAbsent"
/>
<q-checkbox
toggle-indeterminate
keep-color
label="วันลาไม่เกิน"
dense
v-model="isLeave"
/>
</div>
</q-card-section>
<q-separator />
<form @submit.prevent="validateForm">
<q-card-actions align="right" class="bg-white text-teal">
<!-- <q-btn flat label="OK" v-close-popup /> -->
<q-btn
type="submit"
for="#submitForm"
unelevated
dense
class="q-px-md items-center"
color="light-blue-10"
label="บันทึก"
/>
</q-card-actions>
</form>
</q-card>
</q-dialog>
</template>
<style lang="scss" scoped></style>

View file

@ -0,0 +1,189 @@
<script setup lang="ts">
import { ref } from "vue";
import { useQuasar } from "quasar";
import http from "@/plugins/http";
import config from "@/app.config";
import DialogPopupReason from "@/components/Dialogs/PopupReason.vue"; //
import { useCounterMixin } from "@/stores/mixin";
const $q = useQuasar(); // noti quasar
const mixin = useCounterMixin();
const { messageError, dialogConfirm, showLoader, hideLoader, success } = mixin;
const sendStep = ref<number>(1);
const fileUpload = ref<any>(null);
const document = ref<string>("");
/**
* function ปโหลดไฟลเจาหนาท
* @param event file
*/
async function uploadFile(event: any) {
dialogConfirm(
$q,
async () => {
const selectedFile = event;
const formdata = new FormData();
formdata.append("Document", selectedFile);
// await http
// .put(config.API.uploadfileOnlyInsignia(requestId.value), formdata)
// .then(async () => {
// await fecthInsigniaByOc(
// round.value,
// DataStore.agency,
// "officer",
// tab.value
// );
// success($q, "");
// fileUpload.value = null;
// })
// .catch((err) => {
// messageError($q, err);
// }),
},
"ยืนยันการอัปโหลดไฟล์",
"ต้องการยืนยันการอัปโหลดไฟล์นี้หรือไม่ ?"
);
}
function saveReccommend() {
dialogConfirm(
$q,
async () => {
sendStep.value = sendStep.value + 1;
modalRecommend.value = false;
},
"ยืนยันการ" + titleRecommend.value,
"ต้องการยืนยันการ" + titleRecommend.value + "หรือไม่?"
);
}
function sendToDirector(msg: string) {
dialogConfirm(
$q,
async () => {
sendStep.value = sendStep.value == 3 ? 6 : sendStep.value + 1;
},
"ยืนยันการ" + msg,
"ต้องการยืนยันการ" + msg + "หรือไม่?"
);
}
const modalRecommend = ref<boolean>(false);
const titleRecommend = ref<string>("");
function sendAndRecommend(title: string) {
modalRecommend.value = true;
titleRecommend.value = title;
}
</script>
<template>
<div class="row col-12 q-pa-md">
<q-toolbar>
<q-file
v-if="sendStep == 1"
bg-color="white"
clearable
outlined
dense
v-model="fileUpload"
accept=".pdf"
label="อัปโหลดไฟล์"
>
<template v-slot:prepend>
<q-icon color="light-blue" name="attach_file" />
<q-tooltip>ปโหลดไฟล</q-tooltip>
</template>
</q-file>
<q-btn
flat
color="light-blue"
icon="upload"
@click="uploadFile(fileUpload)"
v-if="fileUpload !== null"
/>
<div v-if="document">
<q-btn
dense
color="primary"
icon-right="mdi-download"
label="ดาวน์โหลดไฟล์"
outline
:href="document"
target="_blank"
>
<q-tooltip>ดาวนโหลด</q-tooltip></q-btn
>
</div>
<q-toolbar-title>
<!-- Toolbar -->
</q-toolbar-title>
<div>
<!-- การเจาหนาทของหนวยงานสงเอกสารให ผอ. หนวยงานตรวจสอบ -->
<q-btn
v-if="sendStep == 1"
unelevated
color="public"
label="ส่งเอกสารให้ ผอ. ตรวจสอบ"
@click="sendToDirector('ส่งเอกสารให้ ผอ. ตรวจสอบ')"
/>
<!-- ผอ. หนวยงานทำการยนยนและสงให สกจ. -->
<q-btn
v-if="sendStep == 2"
unelevated
color="public"
label="ยืนยันและส่งเอกสารให้ สกจ."
@click="sendToDirector('ยืนยันและส่งเอกสารให้ สกจ.')"
/>
<!-- สกจ. ตรวจสอบเอกสารและขอมลรายการเงนเดอนทแตละหนวยงานสงมา ไมปรบโควต -->
<q-btn
v-if="sendStep == 3"
unelevated
color="green"
label="ยืนยันการตรวจสอบ"
@click="sendToDirector('ยืนยันการตรวจสอบ')"
/>
<!-- สกจ. ตรวจสอบเอกสารและขอมลรายการเงนเดอนทแตละหนวยงานสงมา ปรบโควต -->
<q-btn
v-if="sendStep == 3"
class="q-ml-sm"
unelevated
color="warning"
label="ส่งคำแนะนำให้ ผอ. ตรวจสอบ"
@click="sendAndRecommend('ส่งคำแนะนำให้ ผอ. ตรวจสอบ')"
/>
<!-- ผอ.หนวยงานสงคำแนะนำใหการเจาหนาทหนวยงาน -->
<q-btn
v-if="sendStep == 4"
unelevated
color="public"
label="ส่งคำแนะนำให้การเจ้าหน้าที่หน่วยงาน"
@click="sendAndRecommend('ส่งคำแนะนำให้ ผอ. ตรวจสอบ')"
/>
<q-btn
v-if="sendStep > 4"
unelevated
color="public"
label="ส่งไปออกคำสั่ง"
/>
</div>
</q-toolbar>
<DialogPopupReason
v-model:modal="modalRecommend"
:title="titleRecommend"
label="คำแนะนำ"
:savaForm="saveReccommend"
textReport=""
/>
</div>
</template>
<style lang="scss" scoped></style>

View file

@ -0,0 +1,492 @@
<script setup lang="ts">
import { ref, onMounted, reactive, computed } from "vue";
import { useQuasar } from "quasar";
import http from "@/plugins/http";
import config from "@/app.config";
import genReportXLSX from "@/plugins/genreportxlsx";
import DialogInfoCriteria from "@/modules/13_salary/components/SalaryLists/DialogInfoCriteria.vue";
/** 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,
} from "@/modules/13_salary/interface/response/SalaryList";
/** importComponents*/
import TableTabType1 from "@/modules/13_salary/components/SalaryEmployeeLists/TableTypePending.vue";
import TableTabType2 from "@/modules/13_salary/components/SalaryEmployeeLists/TableTypeOther.vue";
/** importStore*/
import { useCounterMixin } from "@/stores/mixin";
import { useSalaryEmployeeListSDataStore } from "@/modules/13_salary/store/SalaryEmployeeListsStore";
/** use*/
const $q = useQuasar();
const store = useSalaryEmployeeListSDataStore();
const { messageError, showLoader, hideLoader } = useCounterMixin();
/** props*/
const props = defineProps({
periodLatest: { type: Object as () => DataPeriodLatest, require: true },
});
const total = ref<number>();
const splitterModel = ref<number>(13);
const rows = ref<DataPeriod[]>([]);
/** itemsTab กลุ่ม*/
const itemsTabGroup = ref([
{
lable: "กลุ่ม 1",
name: "group1",
},
{
lable: "กลุ่ม 2",
name: "group2",
},
]);
/** itemsTab ขั้น*/
const itemsTabType = computed(() => {
return store.roundMainCode === "OCT"
? [
{
lable: "รายชื่อคนครอง",
name: "tab1",
type: "PENDING",
},
{
lable: "รายชื่อผู้เกษียณอายุราชการ",
name: "tab5",
type: "RETIRE",
},
{
lable: "1 ขั้น",
name: "tab2",
type: "FULL",
},
{
lable: "0.5 ขั้น",
name: "tab3",
type: "HAFT",
},
{
lable: "1.5 ขั้น",
name: "tab4",
type: "FULLHAFT",
},
{
lable: "ไม่ได้เลื่อน",
name: "tab4",
type: "NONE",
},
]
: [
{
lable: "รายชื่อคนครอง",
name: "tab1",
type: "PENDING",
},
{
lable: "1 ขั้น",
name: "tab2",
type: "FULL",
},
{
lable: "0.5 ขั้น",
name: "tab3",
type: "HAFT",
},
{
lable: "ไม่ได้เลื่อน",
name: "tab4",
type: "NONE",
},
];
});
/** itemsCard*/
const itemsCard = ref([
{
lable: "จำนวนคนทั้งหมด",
name: "group1",
color: "secondary",
total: 0,
},
{
lable: "15% ของจำนวนคน",
name: "group2",
color: "light-blue-4",
total: 0,
},
{
lable: "เลือกไปแล้ว",
name: "group2",
color: "primary",
total: 0,
},
{
lable: "คงเหลือโควตา",
name: "group2",
color: "indigo-6",
total: 0,
},
{
lable: "สำรอง",
name: "group2",
color: "red-6",
total: 0,
},
{
lable: "จำนวนเงินคนครองปัจจุบัน",
name: "group1",
color: "secondary",
total: 0,
},
{
lable: "วงเงิน 6%",
name: "group2",
color: "light-blue-4",
total: 0,
},
{
lable: "ยอดเงินที่ใช้ไป",
name: "group2",
color: "primary",
total: 0,
},
{
lable: "วงเงิน 6%-ยอดเงินที่ใช้ไป",
name: "group2",
color: "indigo-6",
total: 0,
},
{
lable: "ใช้ไปเท่าไหร่",
name: "group2",
color: "blue-6",
total: 0,
},
{
lable: "เหลือเท่าไหร่",
name: "group2",
color: "green-6",
total: 0,
},
{
lable: "สำรอง",
name: "group2",
color: "red-6",
total: 0,
},
]);
/** ข้อมูลค้นหารายชื่อคยขึ้นเงินเดือน*/
const formFilter = reactive<DataFilter>({
page: 1,
pageSize: 10,
keyword: "",
type: store.tabType,
});
const maxPage = ref<number>(1);
/**
* function เรยกขอมลจำนวนโควต
* @param id กล
*/
function fetchDataQuota(id: string) {
// showLoader();
http
.get(config.API.salaryListPeriodQuota(id))
.then((res) => {
const data = res.data.result;
store.remaining = data.remaining;
itemsCard.value[0].total = data.total;
itemsCard.value[1].total = data.fifteenPercent;
itemsCard.value[2].total = data.chosen;
itemsCard.value[3].total = data.remaining;
itemsCard.value[4].total = data.totalBackup;
itemsCard.value[5].total = data.currentAmount;
itemsCard.value[6].total = data.sixPercentAmount;
itemsCard.value[7].total = data.spentAmount;
itemsCard.value[8].total = data.sixPercentSpentAmount;
itemsCard.value[9].total = data.useAmount;
itemsCard.value[10].total = data.remainingAmount;
itemsCard.value[11].total = data.totalBackup;
})
.catch((err) => {
messageError($q, err);
});
// .finally(() => {
// hideLoader();
// });
}
/**
* function เรยกขอมลรายช
* @param id กล
*/
function fetchDataPeriod(id: string) {
rows.value = [];
const formData = {
page: formFilter.page.toString(),
pageSize: formFilter.pageSize.toString(),
keyword: formFilter.keyword,
type: store.tabType === "RETIRE" ? "" : store.tabType,
isRetire: store.tabType === "RETIRE" ? true : null,
};
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);
})
.catch((err) => {
messageError($q, err);
});
}
/**function เปลี่ยนกลุ่ม*/
function changeTabGroup() {
formFilter.page = 1;
formFilter.pageSize = 10;
formFilter.keyword = "";
store.tabType = "PENDING";
props.periodLatest &&
store.fetchPeriodLatest(props?.periodLatest, store.tabGroup);
store.groupId && fetchDataQuota(store.groupId);
store.groupId && fetchDataPeriod(store.groupId);
splitterModel.value = store.roundMainCode === "APR" ? 13 : 16;
}
/**function เปลี่ยนขั้น*/
function changeTabType() {
formFilter.page = 1;
formFilter.pageSize = 10;
formFilter.keyword = "";
store.groupId && fetchDataPeriod(store.groupId);
}
/** function เรียกข้อมูลรายชื่ออีกครั้ง*/
function fetchDataPeriodNew() {
store.groupId && fetchDataPeriod(store.groupId);
store.groupId && fetchDataQuota(store.groupId);
}
function onClickDownload(data: DataOption) {
console.log(data);
// showLoader();
// http
// .get(config.API.salaryReportByid(salaryId.value))
// .then((res) => {
// const dataList = res.data.result;
// genReportXLSX(dataList, "");
// })
// .catch((e) => {
// messageError($q, e);
// })
// .finally(() => {
// hideLoader();
// });
}
const modalDialogInfoCriteria = ref<boolean>(false);
onMounted(async () => {
await fetchDataQuota(store.groupId);
await fetchDataPeriod(store.groupId);
splitterModel.value = store.roundMainCode === "APR" ? 13 : 16;
});
</script>
<template>
<!-- Tab กล -->
<!-- <q-tabs
v-model="store.tabGroup"
dense
class="text-grey"
active-color="primary"
active-class="bg-teal-1"
indicator-color="primary"
align="left"
>
<div
v-for="(item, index) in itemsTabGroup"
:key="index"
@click="changeTabGroup"
>
<q-tab :name="item.name" :label="item.lable" />
</div>
<q-space />
<q-btn
dense
flat
icon="info"
class="q-mr-sm"
label="หลักเกณฑ์การพิจารณาเลื่อนขั้นเงินข้าราชการ"
@click="() => (modalDialogInfoCriteria = true)"
/>
</q-tabs> -->
<!-- <q-separator /> -->
<q-tab-panels v-model="store.tabGroup" animated class="bg-grey-1">
<q-tab-panel
style="padding: 0px"
v-for="(item, index) in itemsTabGroup"
:key="index"
:name="item.name"
>
<!-- Card โควต -->
<div class="row col-12 q-pa-md">
<div
:class="`row col-12 ${
store.roundMainCode === 'APR' ? `q-col-gutter-md` : `q-gutter-md`
} items-start`"
>
<div
v-for="(item, index) in store.roundMainCode === 'APR'
? itemsCard.slice(0, 5)
: store.roundMainCode === 'OCT'
? itemsCard.slice(5, 12)
: itemsCard"
:key="index"
:class="
store.roundMainCode === 'APR'
? 'col-6 col-sm-4 col-md-3 col-lg-2'
: 'col-3'
"
>
<q-card>
<q-card-section>
<div class="row items-center no-wrap">
<div class="col">
<div class="">{{ item.lable }}</div>
</div>
<div :class="`text-${item.color} text-bold`">
{{ item.total ? item.total.toLocaleString() : 0 }}
</div>
</div>
</q-card-section>
</q-card>
</div>
<div class="row col justify-end self-center">
<q-btn-dropdown color="blue-5" label="ดาวน์โหลด">
<q-list>
<q-item
v-for="(item, index) in store.roundMainCode === 'APR'
? store.itemDownloadApr
: store.roundMainCode === 'OCT'
? store.itemDownloadOct
: []"
:key="index"
clickable
v-close-popup
@click="onClickDownload(item)"
>
<q-item-section>
<q-item-label>{{ item.name }}</q-item-label>
</q-item-section>
</q-item>
</q-list>
</q-btn-dropdown>
<!-- <q-btn color="blue-5" icon="download" label="ดาวน์โหลด" /> -->
</div>
</div>
</div>
<q-separator />
<!-- Tab -->
<q-card flat bordered>
<q-splitter v-model="splitterModel" disable>
<template v-slot:before>
<q-tabs
v-model="store.tabType"
vertical
dense
class="text-grey-black"
active-color="blue-5"
active-class="bg-blue-1"
indicator-color="blue-5"
align="left"
>
<div
v-for="(item, index) in itemsTabType"
:key="index"
class="row"
:style="
store.roundMainCode === 'OCT'
? index === 1
? 'border-bottom: 1px solid #c8d3db;'
: ''
: ''
"
>
<q-tab
class="col-12"
style="justify-content: left"
:name="item.type"
:label="item.lable"
@click="changeTabType()"
/>
</div>
</q-tabs>
</template>
<template v-slot:after>
<q-tab-panels
v-model="store.tabType"
animated
swipeable
vertical
transition-prev="jump-up"
transition-next="jump-up"
>
<q-tab-panel
class="q-pa-md"
v-for="(item, index) in itemsTabType"
:key="index"
:name="item.type"
>
<TableTabType1
v-if="index === 0"
:rows="rows"
v-model:maxPage="maxPage"
v-model:formFilter="formFilter"
:fetchDataTable="fetchDataPeriodNew"
:total="total"
/>
<TableTabType2
v-else
:rows="rows"
v-model:maxPage="maxPage"
v-model:formFilter="formFilter"
:fetchDataTable="fetchDataPeriodNew"
:total="total"
/>
</q-tab-panel>
</q-tab-panels>
</template>
</q-splitter>
</q-card>
</q-tab-panel>
</q-tab-panels>
<DialogInfoCriteria v-model:modal="modalDialogInfoCriteria" />
</template>
<style scoped>
.my-card {
width: 100%;
max-width: 200px;
}
.q-tabs--vertical .q-tab {
padding: 0 20px;
}
</style>

View file

@ -0,0 +1,493 @@
<script setup lang="ts">
import { ref, watch, computed } from "vue";
import { useQuasar } from "quasar";
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/SalaryEmployeeLists//DialogAddPerson.vue";
import DialogFormEdit from "@/modules/13_salary/components/SalaryEmployeeLists/DialogFormEdit.vue";
import DialogMoveGroup from "@/modules/13_salary/components/SalaryEmployeeLists/DialogMoveGroup.vue";
import DialogMoveLevel from "@/modules/13_salary/components/SalaryEmployeeLists/DialogMoveLevel.vue";
/** importStore*/
import { useCounterMixin } from "@/stores/mixin";
import { useSalaryEmployeeListSDataStore } from "@/modules/13_salary/store/SalaryEmployeeListsStore";
/** use*/
const $q = useQuasar();
const store = useSalaryEmployeeListSDataStore();
const { dialogRemove, messageError, showLoader, hideLoader, success } =
useCounterMixin();
/** props*/
const formFilter = defineModel<DataFilter>("formFilter", { required: true });
const maxPage = defineModel<Number>("maxPage", { required: true });
const props = defineProps({
rows: { type: Array },
fetchDataTable: {
type: Function,
},
total: {
type: Number,
},
});
/** ข้อมูล Table*/
const columns = ref<QTableProps["columns"]>([
{
name: "no",
align: "left",
label: "ลำดับ",
sortable: true,
field: "no",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "posNo",
align: "left",
label: "ตำแหน่งเลขที่",
sortable: true,
field: "posNo",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "fullName",
align: "left",
label: "ชื่อ-นามสกุล",
field: "fullName",
sortable: true,
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "position",
align: "left",
label: "ตำแหน่งในสายงาน",
sortable: true,
field: "position",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "posType",
align: "left",
label: "ตำแหน่งประเภท",
sortable: false,
field: "posType",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "posLevel",
align: "left",
label: "ระดับตำแหน่ง",
sortable: false,
field: "posLevel",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "posExecutive",
align: "left",
label: "ตำแหน่งทางการบริหาร",
sortable: false,
field: "posExecutive",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "amount",
align: "left",
label: "เงินเดือนฐาน",
sortable: false,
field: "amount",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "amountUse",
align: "left",
label: "จำนวนเงินที่ใช้เลื่อน",
sortable: false,
field: "amountUse",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "positionSalaryAmount",
align: "left",
label: "เงินเดือนหลังเลื่อน",
sortable: false,
field: "positionSalaryAmount",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "isRetired",
align: "center",
label: "เกษียณอายุ",
sortable: false,
field: "isRetired",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
]);
const visibleColumns = ref<string[]>([
"no",
"posNo",
"fullName",
"position",
"posType",
"posLevel",
"posExecutive",
"amount",
"amountUse",
"positionSalaryAmount",
"isRetired",
]);
/** modalDialog*/
const modalDialogAddPerson = ref<boolean>(false);
const modalDialogForm = ref<boolean>(false);
const modalDialogMoveGroup = ref<boolean>(false);
const modalDialogMoveLeve = ref<boolean>(false);
const profileId = ref<string>("");
const amount = ref<number>(0);
/** function openPopup เพิ่มคนเลื่อนเงินเดือน*/
function onClickAddPerson() {
modalDialogAddPerson.value = !modalDialogAddPerson.value;
}
/**
* function openPopup แกไขเงนเดอน
* @param id profileId
* @param amountSalary จำนวนเงนเดอน
*
*/
function onClickEdit(id: string, amountSalary: number) {
profileId.value = id;
amount.value = amountSalary;
modalDialogForm.value = !modalDialogForm.value;
}
/**
* function openPopup ายกล
* @param id profileId
*
*/
function onClickMovieGroup(id: string) {
profileId.value = id;
modalDialogMoveGroup.value = !modalDialogMoveGroup.value;
}
const typeLevel = ref<string>("");
const isReserve = ref<boolean>(false);
/**
* function openPopup ายกข
* @param id profileId
*
*/
function onClickMoveLevel(id: string, typeVal: string, isReserveVal: boolean) {
profileId.value = id;
modalDialogMoveLeve.value = !modalDialogMoveLeve.value;
typeLevel.value = typeVal;
isReserve.value = isReserveVal;
}
/**
* function นยนการลบรายช
* @param id profileId
*/
function onClickDelete(id: string) {
dialogRemove($q, async () => {
showLoader();
await http
.delete(config.API.salaryListPeriodProfileById(id))
.then(() => {
success($q, "ลบข้อมูลสำเร็จ");
props.fetchDataTable?.();
})
.catch((err) => {
messageError($q, err);
})
.finally(() => {
hideLoader();
});
});
}
/** 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;
props.fetchDataTable?.();
}
/** callblack function เรียกข้อมูลรายชื่อใหม่ เมื่อมีการเปลี่ยน PageSize*/
watch(
() => formFilter.value.pageSize,
() => {
updatePagePagination();
}
);
</script>
<template>
<q-toolbar class="text-primary" style="padding: 0px">
<q-btn
v-if="!store.isClosedRound"
flat
round
dense
icon="add"
@click="onClickAddPerson"
>
<q-tooltip>เพ</q-tooltip>
</q-btn>
<q-space />
<q-input
borderless
dense
debounce="300"
outlined
v-model="formFilter.keyword"
placeholder="ค้นหา"
@keydown.enter.prevent="searchData"
>
<template v-slot:append>
<q-icon name="search" />
</template>
</q-input>
<q-select
for="#select"
v-model="visibleColumns"
multiple
outlined
dense
options-dense
:display-value="$q.lang.table.columns"
emit-value
map-options
:options="store.roundMainCode === 'OCT' ? columns : columns.slice(0, 10)"
option-value="name"
options-cover
style="min-width: 150px"
class="col-xs-12 col-sm-3 col-md-2 q-ml-sm"
/>
</q-toolbar>
<d-table
ref="table"
:columns="store.roundMainCode === 'OCT' ? columns : columns.slice(0, 10)"
:rows="props.rows"
row-key="id"
flat
bordered
:paging="true"
dense
:rows-per-page-options="[10, 25, 50, 100]"
:visible-columns="visibleColumns"
@update:pagination="updatePageSizePagination"
>
<template v-slot:header="props">
<q-tr :props="props">
<q-th v-for="col in props.cols" :key="col.name" :props="props">
<span class="text-weight-medium">{{ col.label }}</span>
</q-th>
<q-th auto-width></q-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"
:class="
store.tabType !== 'RETIRE'
? props.row.isNext == true
? 'text-red'
: ''
: ''
"
>
<div v-if="col.name === 'no'">
{{
(formFilter.page - 1) * formFilter.pageSize +
props.rowIndex +
1 +
(store.tabType == "FULL" && props.row.isReserve == true
? " (สำรอง)"
: "")
}}
</div>
<div v-else-if="col.name === 'posNo'">
{{ `${props.row.orgShortName}${props.row.posMasterNo}` }}
</div>
<div v-else-if="col.name === 'fullName'">
{{
`${props.row.prefix}${props.row.firstName} ${props.row.lastName}`
}}
</div>
<div v-else-if="col.name === 'amount'">
{{
props.row.amount !== null ? props.row.amount.toLocaleString() : ""
}}
</div>
<div v-else-if="col.name === 'amountUse'">
{{
props.row.amountUse !== null
? props.row.amountUse.toLocaleString()
: ""
}}
{{
props.row.amountSpecial > 0
? `(${props.row.amountSpecial.toLocaleString()})`
: ""
}}
</div>
<div v-else-if="col.name === 'positionSalaryAmount'">
{{
props.row.positionSalaryAmount !== null
? props.row.positionSalaryAmount.toLocaleString()
: ""
}}
{{
props.row.amountSpecial > 0
? `(${props.row.amountSpecial.toLocaleString()})`
: ""
}}
</div>
<div
v-else-if="
col.name === 'isRetired' && store.roundMainCode === 'OCT'
"
>
<q-icon
name="check"
color="primary"
size="24px"
v-if="props.row.isRetired"
/>
</div>
<div v-else>
{{ col.value ? col.value : "-" }}
</div>
</q-td>
<q-td>
<q-btn
v-if="!store.isClosedRound"
flat
dense
icon="mdi-dots-vertical"
class="q-pa-none q-ml-xs"
color="grey-13"
size="12px"
>
<q-menu>
<q-list dense style="min-width: 150px">
<q-item
v-for="(item, index) in store.itemMenu.filter((x:any)=>x.type != 'properties')"
:key="index"
clickable
v-close-popup
@click="
item.type === 'edit'
? onClickEdit(props.row.id, props.row.amount)
: item.type === 'moveGroup'
? onClickMovieGroup(props.row.id)
: item.type === 'moveLevel'
? onClickMoveLevel(
props.row.id,
props.row.type,
props.row.isReserve
)
: item.type === 'delete'
? onClickDelete(props.row.id)
: null
"
>
<q-item-section>
<div class="row items-center">
<q-icon
:color="item.color"
size="17px"
:name="item.icon"
/>
<div class="q-pl-md">{{ item.label }}</div>
</div>
</q-item-section>
</q-item>
</q-list>
</q-menu>
</q-btn>
</q-td>
</q-tr>
</template>
<template v-slot:pagination="scope">
งหมด {{ props.total }} รายการ
<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>
<DialogAddPerson
v-model:modal="modalDialogAddPerson"
:fetchData="props.fetchDataTable"
/>
<DialogFormEdit
v-model:modal="modalDialogForm"
v-model:profileId="profileId"
v-model:amount="amount"
:fetchData="props.fetchDataTable"
/>
<DialogMoveGroup
v-model:modal="modalDialogMoveGroup"
v-model:profileId="profileId"
:group="store.tabGroup === 'group1' ? 'กลุ่ม1' : 'กลุ่ม2'"
:fetchData="props.fetchDataTable"
/>
<DialogMoveLevel
:typeLevel="typeLevel"
:isReserve="isReserve"
v-model:modal="modalDialogMoveLeve"
v-model:profileId="profileId"
:fetchData="props.fetchDataTable"
:type="store.tabType"
/>
</template>
<style scoped></style>

View file

@ -0,0 +1,589 @@
<script setup lang="ts">
import { ref, watch } from "vue";
import { useQuasar } from "quasar";
/** 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/SalaryEmployeeLists//DialogAddPerson.vue";
import DialogFormEdit from "@/modules/13_salary/components/SalaryEmployeeLists/DialogFormEdit.vue";
import DialogMoveGroup from "@/modules/13_salary/components/SalaryEmployeeLists/DialogMoveGroup.vue";
import DialogMoveLevel from "@/modules/13_salary/components/SalaryEmployeeLists/DialogMoveLevel.vue";
import DialogProperties from "@/modules/13_salary/components/SalaryEmployeeLists/DialogProperties.vue";
/** importStore*/
import { useCounterMixin } from "@/stores/mixin";
import { useSalaryEmployeeListSDataStore } from "@/modules/13_salary/store/SalaryEmployeeListsStore";
import http from "@/plugins/http";
import config from "@/app.config";
/** use*/
const $q = useQuasar();
const store = useSalaryEmployeeListSDataStore();
const { dialogRemove, messageError, showLoader, hideLoader, success } =
useCounterMixin();
/** Props*/
const formFilter = defineModel<DataFilter>("formFilter", { required: true });
const maxPage = defineModel<Number>("maxPage", { required: true });
const props = defineProps({
rows: { type: Array },
fetchDataTable: {
type: Function,
},
maxPage: {
type: Number,
},
total: {
type: Number,
},
});
/** ข้อมูล Table*/
const columns = ref<QTableProps["columns"]>([
{
name: "no",
align: "left",
label: "ลำดับ",
sortable: true,
field: "no",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "fullName",
align: "left",
label: "ชื่อ-นามสกุล",
sortable: true,
field: "fullName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "posType",
align: "left",
label: "ตำแหน่งประเภท",
sortable: true,
field: "posType",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "posExecutive",
align: "left",
label: "ตำแหน่งทางการบริหาร",
sortable: true,
field: "posExecutive",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "position",
align: "left",
label: "ตำแหน่งในสายงาน",
field: "position",
sortable: true,
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "posLevel",
align: "left",
label: "ระดับตำแหน่ง",
field: "posLevel",
sortable: true,
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "amount",
align: "left",
label: "เงินเดือน",
field: "amount",
sortable: true,
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "organization",
align: "left",
label: "สังกัด",
sortable: true,
field: "organization",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "result",
align: "center",
label: "ผลการประเมินฯ",
sortable: false,
field: "result",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "duration",
align: "center",
label: "ระยะเวลาการปฏิบัติราชการในรอบครึ่งปี",
sortable: false,
field: "duration",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "isPunish",
align: "center",
label: "ไม่ถูกลงโทษทางวินัย",
sortable: false,
field: "isPunish",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "isSuspension",
align: "center",
label: "ไม่ถูกพักราชการ",
sortable: false,
field: "isSuspension",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "isAbsent",
align: "center",
label: "ไม่ขาดราชการ",
sortable: false,
field: "isAbsent",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "isLeave",
align: "center",
label: "วันลาไม่เกิน",
sortable: false,
field: "isLeave",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
]);
const visibleColumns = ref<string[]>([
"no",
"fullName",
"posType",
"posExecutive",
"position",
"posLevel",
"amount",
"organization",
"result",
"duration",
"isPunish",
"isSuspension",
"isAbsent",
"isLeave",
]);
/** modalDialog*/
const modalDialogAddPerson = ref<boolean>(false);
const modalDialogForm = ref<boolean>(false);
const modalDialogMoveGroup = ref<boolean>(false);
const modalDialogMoveLeve = ref<boolean>(false);
const modalDialogProperties = ref<boolean>(false);
/** ตัวแปร*/
const profileId = ref<string>("");
const amount = ref<number>(0);
const isPunish = ref<boolean>(false)
const isSuspension = ref<boolean>(false)
const isAbsent = ref<boolean>(false)
const isLeave = ref<boolean>(false)
/**
* function นยนการลบรายช
* @param id profileId
*/
function onClickDelete(id: string) {
dialogRemove($q, async () => {
showLoader();
await http
.delete(config.API.salaryListPeriodProfileById(id))
.then(() => {
success($q, "ลบข้อมูลสำเร็จ");
props.fetchDataTable?.();
})
.catch((err) => {
messageError($q, err);
})
.finally(() => {
hideLoader();
});
});
}
/** function openPopup เพิ่มคนเลื่อนเงินเดือน*/
function onClickAddPerson() {
modalDialogAddPerson.value = !modalDialogAddPerson.value;
}
/**
* function openPopup แกไขเงนเดอน
* @param id profileId
* @param amountSalary จำนวนเงนเดอน
*
*/
function onClickEdit(id: string, amountSalary: number) {
profileId.value = id;
amount.value = amountSalary;
modalDialogForm.value = !modalDialogForm.value;
}
/**
* function openPopup ายกล
* @param id profileId
*
*/
function onClickMovieGroup(id: string) {
profileId.value = id;
modalDialogMoveGroup.value = !modalDialogMoveGroup.value;
}
const typeLevel = ref<string>("");
const isReserve = ref<boolean>(false);
/**
* function openPopup ายกข
* @param id profileId
*
*/
function onClickMoveLevel(id: string, typeVal: string, isReserveVal: boolean) {
profileId.value = id;
modalDialogMoveLeve.value = !modalDialogMoveLeve.value;
typeLevel.value = typeVal;
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;
props.fetchDataTable?.();
}
function onProperties(data:any){
console.log(data)
modalDialogProperties.value = true
profileId.value = data.id
isPunish.value = data.isPunish
isSuspension.value = data.isSuspension
isAbsent.value = data.isAbsent
isLeave.value = data.isLeave
}
/** callblack function เรียกข้อมูลรายชื่อใหม่ เมื่อมีการเปลี่ยน PageSize*/
watch(
() => formFilter.value.pageSize,
() => {
updatePagePagination();
}
);
</script>
<template>
<q-toolbar class="text-primary" style="padding: 0px">
<q-btn v-if="!store.isClosedRound" flat round dense icon="add" @click="onClickAddPerson">
<q-tooltip>เพ </q-tooltip>
</q-btn>
<q-space />
<q-input
borderless
dense
debounce="300"
outlined
v-model="formFilter.keyword"
placeholder="ค้นหา"
@keydown.enter.prevent="searchData"
>
<template v-slot:append>
<q-icon name="search" />
</template>
</q-input>
<q-select
for="#select"
v-model="visibleColumns"
multiple
outlined
dense
options-dense
:display-value="$q.lang.table.columns"
emit-value
map-options
:options="columns"
option-value="name"
options-cover
style="min-width: 150px"
class="col-xs-12 col-sm-3 col-md-2 q-ml-sm"
/>
</q-toolbar>
<d-table
ref="table"
:columns="columns"
:rows="props.rows"
row-key="id"
flat
bordered
:paging="true"
dense
:rows-per-page-options="[10, 25, 50, 100]"
:visible-columns="visibleColumns"
@update:pagination="updatePageSizePagination"
>
<template v-slot:header="props">
<q-tr :props="props">
<q-th v-for="col in props.cols" :key="col.name" :props="props">
<span class="text-weight-medium">{{ col.label }}</span>
</q-th>
<q-th auto-width />
</q-tr>
</template>
<template v-slot:body="props">
<q-tr :props="props" class="cursor-pointer">
<q-td v-for="col in props.cols" :key="col.name" :props="props">
<div v-if="col.name === 'no'">
{{
(formFilter.page - 1) * formFilter.pageSize + props.rowIndex + 1
}}
</div>
<div v-else-if="col.name === 'fullName'">
{{
`${props.row.prefix}${props.row.firstName} ${props.row.lastName}`
}}
</div>
<div v-else-if="col.name == 'organization'" class="table_ellipsis">
<div
v-if="
props.row.child4 === null &&
props.row.child3 === null &&
props.row.child2 === null &&
props.row.child1 === null &&
props.row.root === null
"
>
-
</div>
{{
`${props.row.child4 ? props.row.child4 + "/" : ""}${
props.row.child3 ? props.row.child3 + "/" : ""
}${props.row.child2 ? props.row.child2 + "-" : ""}${
props.row.child1 ? props.row.child1 + "/" : ""
}${props.row.root ? props.row.root : ""}`
}}
</div>
<!-- <div v-else-if="col.name === 'isResult'">
<q-checkbox
disable
keep-color
color="primary"
v-model="props.row.isResult"
/>
</div>
<div v-else-if="col.name === 'isDuration'">
<q-checkbox
disable
keep-color
color="primary"
v-model="props.row.isDuration"
/>
</div>
<div v-else-if="col.name === 'isPunish'">
<q-checkbox
disable
keep-color
color="primary"
v-model="props.row.isPunish"
/>
</div>
<div v-else-if="col.name === 'isRetired'">
<q-checkbox
disable
keep-color
color="primary"
v-model="props.row.isRetired"
/>
</div>
<div v-else-if="col.name === 'isRetired2'">
<q-checkbox
disable
keep-color
color="primary"
v-model="props.row.isRetired2"
false
/>
</div> -->
<div v-else-if="col.name == 'isPunish'">
<q-icon
v-if="props.row.isPunish !== null"
:name="props.row.isPunish ? 'done' : 'close'"
:color="props.row.isPunish ? 'primary' : 'red'"
size="24px"
/>
<div v-else-if="props.row.isPunish == null">
{{ props.row.isPunish == null ? '-':''}}
</div>
</div>
<div v-else-if="col.name == 'isSuspension'">
<q-icon
v-if="props.row.isSuspension !== null"
:name="props.row.isSuspension ? 'done' : 'close'"
:color="props.row.isSuspension ? 'primary' : 'red'"
size="24px"
/>
<div v-else-if="props.row.isSuspension == null">
{{ props.row.isSuspension == null ? '-':''}}
</div>
</div>
<div v-else-if="col.name == 'isAbsent'">
<q-icon
v-if="props.row.isAbsent !== null"
:name="props.row.isAbsent ? 'done' : 'close'"
:color="props.row.isAbsent ? 'primary' : 'red'"
size="24px"
/>
<div v-else-if="props.row.isAbsent == null">
{{ props.row.isAbsent == null ? '-':''}}
</div>
</div>
<div v-else-if="col.name == 'amount'">
{{Number(props.row.amount).toLocaleString()}}
</div>
<div v-else-if="col.name == 'isLeave'">
<q-icon
v-if="props.row.isLeave !== null"
:name="props.row.isLeave ? 'done' : 'close'"
:color="props.row.isLeave ? 'primary' : 'red'"
size="24px"
/>
<div v-else-if="props.row.isLeave == null">
{{ props.row.isLeave == null ? '-':''}}
</div>
</div>
<div v-else>
{{ col.value ? col.value : "-" }}
</div>
</q-td>
<q-td>
<q-btn
v-if="!store.isClosedRound"
flat
dense
icon="mdi-dots-vertical"
class="q-pa-none q-ml-xs"
color="grey-13"
size="12px"
>
<q-menu>
<q-list dense style="min-width: 150px">
<q-item
v-for="(item, index) in store.itemMenu"
:key="index"
clickable
v-close-popup
@click="
item.type === 'edit'
? onClickEdit(props.row.id, props.row.amount)
: item.type === 'moveGroup'
? onClickMovieGroup(props.row.id)
: item.type === 'moveLevel'
? onClickMoveLevel(
props.row.id,
props.row.type,
props.row.isReserve
)
: item.type === 'delete'
? onClickDelete(props.row.id)
: item.type === 'properties'
? onProperties(props.row)
: null
"
>
<q-item-section>
<div class="row items-center">
<q-icon
:color="item.color"
size="17px"
:name="item.icon"
/>
<div class="q-pl-md">{{ item.label }}</div>
</div>
</q-item-section>
</q-item>
</q-list>
</q-menu>
</q-btn>
</q-td>
</q-tr>
</template>
<template v-slot:pagination="scope">
งหมด {{ props.total }} รายการ
<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>
<DialogAddPerson
v-model:modal="modalDialogAddPerson"
:fetchData="props.fetchDataTable"
/>
<DialogFormEdit
v-model:modal="modalDialogForm"
v-model:profileId="profileId"
v-model:amount="amount"
:fetchData="props.fetchDataTable"
/>
<DialogMoveGroup
v-model:modal="modalDialogMoveGroup"
v-model:profileId="profileId"
:group="store.tabGroup === 'group1' ? 'กลุ่ม1' : 'กลุ่ม2'"
:fetchData="props.fetchDataTable"
/>
<DialogMoveLevel
:typeLevel="typeLevel"
:isReserve="isReserve"
v-model:modal="modalDialogMoveLeve"
v-model:profileId="profileId"
:fetchData="props.fetchDataTable"
/>
<DialogProperties
v-model:modal="modalDialogProperties"
v-model:id="profileId"
:is-punish="isPunish"
:is-suspension="isSuspension"
:is-absent="isAbsent"
:is-leave="isLeave"
:fetch-data="props.fetchDataTable"
/>
</template>
<style scoped></style>

View file

@ -0,0 +1,162 @@
import { defineStore } from "pinia";
import { ref } from "vue";
/** importType*/
import type {
ItemsMenu,
DataOption,
} from "@/modules/13_salary/interface/index/Main";
import type { DataPeriodLatest } from "@/modules/13_salary/interface/response/SalaryList";
export const useSalaryEmployeeListSDataStore = defineStore(
"salaryEmployeeListStore",
() => {
const tabGroup = ref<string>("group1");
const tabType = ref<string>("PENDING");
const groupOp = ref<DataOption[]>([
{ id: "", name: "กลุ่ม1" },
{ id: "", name: "กลุ่ม2" },
]);
const remaining = ref<number>(0);
const groupId = ref<string>("");
const rootId = ref<string>("");
const roundMainCode = ref<string>("");
const roundYear = ref<number>(0);
const roundCode = ref<string>("");
const isClosedRound = ref<boolean>(false); // การปิดรอบ
/** List Menu*/
const itemMenu = ref<ItemsMenu[]>([
{
label: "แก้ไขเงินเดือน",
icon: "edit",
color: "edit",
type: "edit",
},
{
label: "ย้ายกลุ่ม",
icon: "mdi-account-arrow-right-outline",
color: "indigo-6",
type: "moveGroup",
},
{
label: "ย้ายขั้น",
icon: "mdi-swap-vertical-bold",
color: "green-6",
type: "moveLevel",
},
{
label: "แก้ไขคุณสมบัติ",
icon: "mdi-format-list-checks",
color: "blue-6",
type: "properties",
},
{
label: "ลบ",
icon: "delete",
color: "red",
type: "delete",
},
]);
/** List Download รายงานของรอบเมษายน*/
const itemDownloadApr = ref<DataOption[]>([
{
id: "gov1-01",
name: "รายชื่อข้าราชการผู้ที่ครองตำแหน่ง ณ วันที่ 1 มีนาคม",
},
{
id: "gov1-02",
name: "บัญชีการคำนวณโควตาเลื่อนเงินเดือน รอบเมษายน",
},
{
id: "gov1-03",
name: "รายชื่อข้าราชการที่ได้รับการเสนอขอเลื่อนหนึ่งขั้น",
},
{
id: "gov1-04",
name: "แบบ 1 กท รอบเมษายน",
},
{
id: "gov1-05",
name: "แบบ 2 กท รอบเมษายน",
},
{
id: "gov1-06",
name: "แบบ 3 กท บัญชีแสดงวันลาครึ่งปี ขรก.",
},
{
id: "gov1-07",
name: "คำสั่งเลื่อนเงินเดือน รอบเมษายน",
},
{
id: "gov1-08",
name: "คำสั่งค่าตอบแทนพิเศษ และผู้ไม่ได้เลื่อน รอบเมษายน",
},
]);
/** List Download รายงานของรอบตุลาคม*/
const itemDownloadOct = ref<DataOption[]>([
{
id: "gov2-01",
name: "รายชื่อข้าราชการผู้ที่ครองตำแหน่ง ณ วันที่ 1 กันยายน",
},
{
id: "gov2-02",
name: "บัญชีการคำนวณวงเงินเลื่อนเงินเดือน รอบตุลาคม",
},
{
id: "gov2-03",
name: "รายชื่อข้าราชการผู้ที่ได้รับการเสนอขอเลื่อนเงินเดือนทั้งปีสองขั้น",
},
{
id: "gov2-04",
name: "แบบ 1 กท รอบตุลาคม",
},
{
id: "gov2-05",
name: "แบบ 2 กท รอบตุลาคม",
},
{
id: "gov2-06",
name: "แบบ 3 กท บัญชีแสดงวันลาครึ่งปี ขรก. ",
},
{
id: "gov2-07",
name: "คำสั่งเลื่อนเงินเดือนข้าราชการเกษียณ",
},
{
id: "gov2-08",
name: "คำสั่งเลื่อนเงินเดือน รอบตุลาคม",
},
{
id: "gov2-09",
name: "คำสั่งค่าตอบแทนพิเศษ และผู้ไม่ได้เลื่อนเงินเดือน รอบตุลาคม",
},
]);
function fetchPeriodLatest(data: DataPeriodLatest, type: string) {
groupId.value = type === "group1" ? data.group1id : data.group2id;
roundCode.value = data.period;
groupOp.value[0].id = data.group1id;
groupOp.value[1].id = data.group2id;
}
return {
tabGroup,
tabType,
itemMenu,
itemDownloadOct,
itemDownloadApr,
groupId,
fetchPeriodLatest,
rootId,
roundCode,
groupOp,
roundMainCode,
remaining,
isClosedRound,
roundYear,
};
}
);

View file

@ -17,14 +17,14 @@ import type {
} from "@/modules/13_salary/interface/response/SalaryList";
/** importComponents*/
import TabGroup from "@/modules/13_salary/components/SalaryLists/TabMain.vue";
import TabGroup from "@/modules/13_salary/components/SalaryEmployeeLists/TabMain.vue";
/** importStore*/
import { useSalaryListSDataStore } from "@/modules/13_salary/store/SalaryListsStore";
import { useSalaryEmployeeListSDataStore } from "@/modules/13_salary/store/SalaryEmployeeListsStore";
import { useCounterMixin } from "@/stores/mixin";
/** use*/
const store = useSalaryListSDataStore();
const store = useSalaryEmployeeListSDataStore();
const $q = useQuasar();
const { messageError, showLoader, hideLoader } = useCounterMixin();