544 lines
16 KiB
Vue
544 lines
16 KiB
Vue
<script setup lang="ts">
|
|
import { ref, reactive, onMounted } from "vue";
|
|
import { useQuasar } from "quasar";
|
|
|
|
import http from "@/plugins/http";
|
|
import config from "@/app.config";
|
|
import { useCounterMixin } from "@/stores/mixin";
|
|
|
|
import type { QTableProps } from "quasar";
|
|
import type { FormQuery } from "@/modules/01_metadata/interface/index/positionEmployee";
|
|
import type { DataOption } from "@/modules/01_metadata/interface/request/position/index";
|
|
import type {
|
|
ResGroup,
|
|
ResLevel,
|
|
ResPossition,
|
|
} from "@/modules/01_metadata/interface/response/positionEmployee/Main";
|
|
|
|
import DialogHeader from "@/components/DialogHeader.vue";
|
|
|
|
/**use*/
|
|
const $q = useQuasar();
|
|
const mixin = useCounterMixin();
|
|
const {
|
|
dialogConfirm,
|
|
showLoader,
|
|
hideLoader,
|
|
messageError,
|
|
success,
|
|
dialogRemove,
|
|
} = mixin;
|
|
|
|
//table
|
|
const rows = ref<ResPossition[]>([]);
|
|
const columns = ref<QTableProps["columns"]>([
|
|
{
|
|
name: "no",
|
|
align: "left",
|
|
label: "ลำดับ",
|
|
sortable: false,
|
|
field: "no",
|
|
headerStyle: "font-size: 14px",
|
|
style: "font-size: 14px",
|
|
},
|
|
{
|
|
name: "posDictName",
|
|
align: "left",
|
|
label: "ชื่อตำแหน่ง",
|
|
sortable: true,
|
|
field: "posDictName",
|
|
headerStyle: "font-size: 14px",
|
|
style: "font-size: 14px",
|
|
},
|
|
{
|
|
name: "posTypeName",
|
|
align: "left",
|
|
label: "กลุ่มงาน",
|
|
sortable: true,
|
|
field: "posTypeName",
|
|
headerStyle: "font-size: 14px",
|
|
style: "font-size: 14px",
|
|
},
|
|
{
|
|
name: "posLevelName",
|
|
align: "left",
|
|
label: "ระดับชั้นงาน",
|
|
sortable: true,
|
|
field: "posLevelName",
|
|
headerStyle: "font-size: 14px",
|
|
style: "font-size: 14px",
|
|
},
|
|
{
|
|
name: "createdAt",
|
|
align: "left",
|
|
label: "วันที่สร้าง",
|
|
sortable: true,
|
|
field: "createdAt",
|
|
headerStyle: "font-size: 14px",
|
|
style: "font-size: 14px",
|
|
},
|
|
{
|
|
name: "lastUpdatedAt",
|
|
align: "left",
|
|
label: "วันที่แก้ไข",
|
|
sortable: true,
|
|
field: "lastUpdatedAt",
|
|
headerStyle: "font-size: 14px",
|
|
style: "font-size: 14px",
|
|
},
|
|
{
|
|
name: "lastUpdateFullName",
|
|
align: "left",
|
|
label: "ผู้ดำเนินการ",
|
|
sortable: true,
|
|
field: "lastUpdateFullName",
|
|
headerStyle: "font-size: 14px",
|
|
style: "font-size: 14px",
|
|
},
|
|
]);
|
|
const visibleColumns = ref<string[]>([
|
|
"no",
|
|
"posDictName",
|
|
"posTypeName",
|
|
"posLevelName",
|
|
"createdAt",
|
|
"lastUpdatedAt",
|
|
"lastUpdateFullName",
|
|
]);
|
|
// ตัวเลือกค้นหา
|
|
const optionFilter = ref<DataOption[]>([
|
|
{ id: "positionName", name: "ชื่อตำแหน่ง" },
|
|
{ id: "positionType", name: "กลุ่มงาน" },
|
|
{ id: "positionLevel", name: "ระดับชั้นงาน" },
|
|
]);
|
|
|
|
const formQuery = reactive<FormQuery>({
|
|
type: "positionName",
|
|
keyword: "",
|
|
});
|
|
|
|
const modalDialog = ref<boolean>(false);
|
|
const isStatusEdit = ref<boolean>(false);
|
|
const posId = ref<string>("");
|
|
|
|
const formDataPos = reactive({
|
|
posName: "",
|
|
posTypeName: "",
|
|
posLevelName: "",
|
|
});
|
|
|
|
const posTypeMain = ref<ResGroup[]>([]);
|
|
const posTypeOp = ref<DataOption[]>([]);
|
|
const posLevelOp = ref<DataOption[]>([]);
|
|
|
|
/**
|
|
* ฟังก์ชันดึงข้อมูลรายการตำแหน่งจาก API
|
|
* @param statusType สถานะการส่งประเภทค้นหา (true = ไม่ส่งประเภทค้นหา)
|
|
*
|
|
* เก็บข้อมูลรายการตำแหน่งจากไว้ใน rows.value
|
|
*/
|
|
async function fetchData(statusType: boolean = false) {
|
|
showLoader();
|
|
await http
|
|
.get(
|
|
config.API.orgEmployeePos +
|
|
`?keyword=${formQuery.keyword}&type=${statusType ? "" : formQuery.type}`
|
|
)
|
|
.then(async (res) => {
|
|
rows.value = await res.data.result;
|
|
})
|
|
.catch((err) => {
|
|
messageError($q, err);
|
|
})
|
|
.finally(() => {
|
|
hideLoader();
|
|
});
|
|
}
|
|
|
|
/**
|
|
* ฟังก์ชันยืนยันการบันทึกข้อมูลตำแหน่ง
|
|
*
|
|
* เมื่อ isStatusEdit เป็น false จะทำการเพิ่มข้อมูลรายการข้อมุลตำแหน่ง ถ้าไม่จะทำการแก้ไขข้อมูล
|
|
* และเมื่อเพิ่มข้อมูลเสร็จจำทำการดึงข้อมูลรายการตำแหน่งใหม่
|
|
*/
|
|
function onSubmit() {
|
|
dialogConfirm($q, async () => {
|
|
const body = {
|
|
posDictName: formDataPos.posName,
|
|
posTypeId: formDataPos.posTypeName,
|
|
posLevelId: formDataPos.posLevelName,
|
|
};
|
|
showLoader();
|
|
//กำหนด Phat API
|
|
const url = !isStatusEdit.value
|
|
? config.API.orgEmployeePos
|
|
: config.API.orgEmployeePosById(posId.value);
|
|
|
|
await http[!isStatusEdit.value ? "post" : "put"](url, body)
|
|
.then(async () => {
|
|
await fetchData();
|
|
success($q, "บันทีกข้อมูลสำเร็จ");
|
|
closeDialog();
|
|
})
|
|
.catch((err) => {
|
|
messageError($q, err);
|
|
})
|
|
.finally(() => {
|
|
hideLoader();
|
|
});
|
|
});
|
|
}
|
|
|
|
/**
|
|
* ฟังก์ชันยืนยันการลบรายการข้อมูลตำแหน่ง
|
|
*
|
|
* @param id รายการข้อมูลตำแหน่งที่จะลบ
|
|
* เมื่อลบข้อมูลเสร็จจำทำการดึงข้อมูลรายการตำแหน่งใหม่
|
|
*/
|
|
function deletePos(id: string) {
|
|
dialogRemove($q, async () => {
|
|
showLoader();
|
|
await http
|
|
.delete(config.API.orgEmployeePosById(id))
|
|
.then(async () => {
|
|
await fetchData();
|
|
success($q, "ลบข้อมูลสำเร็จ");
|
|
})
|
|
.catch((err) => {
|
|
messageError($q, err);
|
|
})
|
|
.finally(() => {
|
|
hideLoader();
|
|
});
|
|
});
|
|
}
|
|
|
|
/**
|
|
* ฟังก์ชันเปิด popup เพื่อแก้ไขหรือคัดลอกข้อมูลตำแหน่ง
|
|
* @param typeEdit สถานะการแก้ไข (true = แก้ไข, false = เพิ่มใหม่หรือคัดลอก)
|
|
* @param data ข้อมูลตำแหน่งที่ต้องการแก้ไขหรือคัดลอก
|
|
*/
|
|
async function onClickOpenDialog(
|
|
typeEdit: boolean = false,
|
|
data: ResPossition = {} as ResPossition
|
|
) {
|
|
isStatusEdit.value = typeEdit;
|
|
modalDialog.value = true;
|
|
|
|
// ดึงข้อมูลกลุ่มงาน
|
|
await fetchType();
|
|
|
|
isStatusEdit.value = typeEdit;
|
|
modalDialog.value = true;
|
|
// อัพเดตข้อมูลประเภทตำแหน่งตาม id กลุ่มงาน
|
|
await updatePosTypeName(data.posTypeId);
|
|
|
|
if (data) {
|
|
posId.value = data.id;
|
|
formDataPos.posName = data.posDictName;
|
|
formDataPos.posTypeName = data.posTypeId;
|
|
formDataPos.posLevelName = data.posLevelId;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* ฟังก์ชันดึงข้อมูลกลุ่มงาน
|
|
*/
|
|
async function fetchType() {
|
|
if (posTypeMain.value.length === 0) {
|
|
showLoader();
|
|
await http
|
|
.get(config.API.orgEmployeeType)
|
|
.then((res) => {
|
|
const data = res.data.result;
|
|
posTypeMain.value = data;
|
|
posTypeOp.value = data.map((e: ResGroup) => ({
|
|
id: e.id,
|
|
name: e.posTypeName,
|
|
}));
|
|
})
|
|
.catch((err) => {
|
|
messageError($q, err);
|
|
})
|
|
.finally(() => {
|
|
hideLoader();
|
|
});
|
|
}
|
|
}
|
|
|
|
/**
|
|
* ฟังก์ชันหาตัวเลือกระดับชั้นงานตาม ID กลุ่มงาน
|
|
* @param id กลุ่มงาน
|
|
*/
|
|
async function updatePosTypeName(id: string) {
|
|
const posLevel = posTypeMain.value.find((e: ResGroup) => e.id === id);
|
|
posLevelOp.value =
|
|
posLevel?.posLevels.map((e: ResLevel) => ({
|
|
id: e.id,
|
|
name: e.posLevelName.toString(),
|
|
})) ?? [];
|
|
formDataPos.posLevelName = "";
|
|
}
|
|
|
|
/**
|
|
* ฟังก์ชันปิด Popup แก้ไขหรือคัดลอกข้อมูลตำแหน่ง
|
|
* และกำหนด formDataPos ไปเป็นค่าว่าง
|
|
*/
|
|
function closeDialog() {
|
|
modalDialog.value = false;
|
|
formDataPos.posName = "";
|
|
formDataPos.posTypeName = "";
|
|
formDataPos.posLevelName = "";
|
|
}
|
|
|
|
/**
|
|
* hook ทำงานเมื่อ Components ถูกเรียกใช้งาน
|
|
*/
|
|
onMounted(async () => {
|
|
await fetchData(true);
|
|
});
|
|
</script>
|
|
<template>
|
|
<div class="row col-12 q-mb-sm q-col-gutter-sm">
|
|
<div class="row col-12">
|
|
<div class="row col-md-12 q-col-gutter-sm">
|
|
<div class="col-md-2">
|
|
<q-select
|
|
label="ค้นหาจาก"
|
|
v-model="formQuery.type"
|
|
:options="optionFilter"
|
|
emit-value
|
|
dense
|
|
map-options
|
|
outlined
|
|
option-label="name"
|
|
option-value="id"
|
|
/>
|
|
</div>
|
|
|
|
<div class="col-md-4">
|
|
<q-input
|
|
ref="searchRef"
|
|
v-model="formQuery.keyword"
|
|
outlined
|
|
dense
|
|
lazy-rules
|
|
label="คำค้น"
|
|
hide-bottom-space
|
|
@keydown.enter="fetchData()"
|
|
>
|
|
<template v-slot:append>
|
|
<q-icon
|
|
v-if="formQuery.keyword"
|
|
name="cancel"
|
|
@click="(formQuery.keyword = ''), fetchData()"
|
|
class="cursor-pointer"
|
|
></q-icon>
|
|
</template>
|
|
</q-input>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<q-btn
|
|
color="primary"
|
|
icon="search"
|
|
label="ค้นหา"
|
|
class="full-width"
|
|
@click="fetchData()"
|
|
/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="row col-12">
|
|
<q-btn
|
|
id="addComplaints"
|
|
for="addComplaints"
|
|
size="12px"
|
|
flat
|
|
round
|
|
color="primary"
|
|
icon="mdi-plus"
|
|
@click="onClickOpenDialog()"
|
|
><q-tooltip>เพิ่มตำเเหน่ง </q-tooltip></q-btn
|
|
>
|
|
<q-space />
|
|
|
|
<q-select
|
|
v-model="visibleColumns"
|
|
multiple
|
|
outlined
|
|
dense
|
|
options-dense
|
|
:display-value="$q.lang.table.columns"
|
|
emit-value
|
|
map-options
|
|
:options="columns"
|
|
option-value="name"
|
|
style="min-width: 140px"
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="full-width q-mt-sm">
|
|
<d-table
|
|
ref="table"
|
|
:columns="columns"
|
|
:rows="rows"
|
|
row-key="id"
|
|
flat
|
|
bordered
|
|
:paging="true"
|
|
dense
|
|
class="custom-header-table"
|
|
:visible-columns="visibleColumns"
|
|
>
|
|
<template v-slot:header="props">
|
|
<q-tr :props="props">
|
|
<q-th auto-width></q-th>
|
|
<q-th
|
|
v-for="col in props.cols"
|
|
:key="col.name"
|
|
:props="props"
|
|
style="color: #000000; font-weight: 500"
|
|
>
|
|
<span class="text-weight-medium">{{ col.label }}</span>
|
|
</q-th>
|
|
</q-tr>
|
|
</template>
|
|
<template v-slot:body="props">
|
|
<q-tr :props="props">
|
|
<q-td auto-width>
|
|
<q-btn
|
|
color="blue-6"
|
|
flat
|
|
dense
|
|
round
|
|
class="q-mr-xs"
|
|
icon="mdi-content-copy"
|
|
clickable
|
|
@click.stop="
|
|
() => {
|
|
onClickOpenDialog(false, props.row);
|
|
}
|
|
"
|
|
>
|
|
<q-tooltip>คัดลอกข้อมูล</q-tooltip>
|
|
</q-btn>
|
|
<q-btn
|
|
color="edit"
|
|
flat
|
|
dense
|
|
round
|
|
icon="mdi-pencil"
|
|
clickable
|
|
@click.stop="onClickOpenDialog(true, props.row)"
|
|
v-close-popup
|
|
>
|
|
<q-tooltip>แก้ไขข้อมูล</q-tooltip>
|
|
</q-btn>
|
|
<q-btn
|
|
color="red"
|
|
flat
|
|
dense
|
|
round
|
|
icon="mdi-delete"
|
|
clickable
|
|
@click.stop="deletePos(props.row.id)"
|
|
v-close-popup
|
|
>
|
|
<q-tooltip>ลบข้อมูล</q-tooltip>
|
|
</q-btn>
|
|
</q-td>
|
|
<q-td v-for="col in props.cols" :key="col.name" :props="props">
|
|
<div v-if="col.name == 'no'">
|
|
{{ props.rowIndex + 1 }}
|
|
</div>
|
|
|
|
<div v-else>
|
|
{{ col.value ? col.value : "-" }}
|
|
</div>
|
|
</q-td>
|
|
</q-tr>
|
|
</template>
|
|
</d-table>
|
|
</div>
|
|
|
|
<q-dialog v-model="modalDialog" class="dialog" persistent>
|
|
<q-card style="width: 350px">
|
|
<q-form greedy @submit.prevent @validation-success="onSubmit">
|
|
<DialogHeader
|
|
:tittle="`${
|
|
isStatusEdit
|
|
? 'แก้ไขข้อมูลตำแหน่งลูกจ้างประจำ'
|
|
: 'เพิ่มข้อมูลตำแหน่งลูกจ้างประจำ'
|
|
}`"
|
|
:close="closeDialog"
|
|
/>
|
|
<q-separator />
|
|
|
|
<q-card-section>
|
|
<div class="row q-col-gutter-sm col-12">
|
|
<div class="col-12">
|
|
<q-input
|
|
ref="posNameRef"
|
|
v-model="formDataPos.posName"
|
|
dense
|
|
outlined
|
|
for="#positionName"
|
|
label="ชื่อตำแหน่ง"
|
|
lazy-rules
|
|
hide-bottom-space
|
|
:rules="[(val:string) => !!val || `${'กรุณากรอกชื่อตำแหน่ง'}`]"
|
|
class="inputgreen"
|
|
/>
|
|
</div>
|
|
|
|
<div class="col-6">
|
|
<q-select
|
|
ref="posTypeNameRef"
|
|
label="กลุ่มงาน"
|
|
v-model="formDataPos.posTypeName"
|
|
:options="posTypeOp"
|
|
emit-value
|
|
dense
|
|
map-options
|
|
outlined
|
|
option-label="name"
|
|
option-value="id"
|
|
lazy-rules
|
|
hide-bottom-space
|
|
:rules="[(val:string) => !!val || `${'กรุณาเลือกกลุ่มงาน'}`]"
|
|
@update:model-value="updatePosTypeName"
|
|
class="inputgreen"
|
|
/>
|
|
</div>
|
|
|
|
<div class="col-6">
|
|
<q-select
|
|
ref="posLevelNameRef"
|
|
label="ระดับชั้นงาน"
|
|
v-model="formDataPos.posLevelName"
|
|
:disable="formDataPos.posTypeName === ''"
|
|
:options="posLevelOp"
|
|
emit-value
|
|
dense
|
|
map-options
|
|
outlined
|
|
option-label="name"
|
|
option-value="id"
|
|
lazy-rules
|
|
hide-bottom-space
|
|
:rules="[(val:string) => !!val || `${'กรุณาเลือกระดับชั้นงาน'}`]"
|
|
class="inputgreen"
|
|
/>
|
|
</div>
|
|
</div>
|
|
</q-card-section>
|
|
<q-separator />
|
|
<q-card-actions align="right">
|
|
<q-btn type="submit" :label="`บันทึก`" color="public" />
|
|
</q-card-actions>
|
|
</q-form>
|
|
</q-card>
|
|
</q-dialog>
|
|
</template>
|