This commit is contained in:
Warunee Tamkoo 2024-03-14 14:04:13 +07:00
parent 92aac7e941
commit c052ef9148
10 changed files with 2353 additions and 0 deletions

View file

@ -0,0 +1,4 @@
<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 { useSalaryListSDataStore } from "@/modules/13_salary/store/SalaryListsStore";
/** use*/
const $q = useQuasar();
const store = useSalaryListSDataStore();
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 { useSalaryListSDataStore } from "@/modules/13_salary/store/SalaryListsStore";
/** use*/
const $q = useQuasar();
const store = useSalaryListSDataStore();
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 { useSalaryListSDataStore } from "@/modules/13_salary/store/SalaryListsStore";
/** use*/
const $q = useQuasar();
const store = useSalaryListSDataStore();
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 { useSalaryListSDataStore } from "@/modules/13_salary/store/SalaryListsStore";
/** use*/
const $q = useQuasar();
const store = useSalaryListSDataStore();
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,190 @@
<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,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/SalaryLists//DialogAddPerson.vue";
import DialogFormEdit from "@/modules/13_salary/components/SalaryLists/DialogFormEdit.vue";
import DialogMoveGroup from "@/modules/13_salary/components/SalaryLists/DialogMoveGroup.vue";
import DialogMoveLevel from "@/modules/13_salary/components/SalaryLists/DialogMoveLevel.vue";
/** importStore*/
import { useCounterMixin } from "@/stores/mixin";
import { useSalaryListSDataStore } from "@/modules/13_salary/store/SalaryListsStore";
/** use*/
const $q = useQuasar();
const store = useSalaryListSDataStore();
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/SalaryLists//DialogAddPerson.vue";
import DialogFormEdit from "@/modules/13_salary/components/SalaryLists/DialogFormEdit.vue";
import DialogMoveGroup from "@/modules/13_salary/components/SalaryLists/DialogMoveGroup.vue";
import DialogMoveLevel from "@/modules/13_salary/components/SalaryLists/DialogMoveLevel.vue";
import DialogProperties from "@/modules/13_salary/components/SalaryLists/DialogProperties.vue";
/** importStore*/
import { useCounterMixin } from "@/stores/mixin";
import { useSalaryListSDataStore } from "@/modules/13_salary/store/SalaryListsStore";
import http from "@/plugins/http";
import config from "@/app.config";
/** use*/
const $q = useQuasar();
const store = useSalaryListSDataStore();
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>