Merge branch 'develop' into devTee

This commit is contained in:
STW_TTTY\stwtt 2024-09-19 16:37:30 +07:00
commit d1144b2def
85 changed files with 3637 additions and 11395 deletions

View file

@ -1,7 +1,8 @@
<script setup lang="ts">
import { onMounted, ref } from "vue";
import { checkPermission } from "@/utils/permissions";
import { useQuasar } from "quasar";
import { checkPermission } from "@/utils/permissions";
import { useRoute, useRouter } from "vue-router";
import { useCounterMixin } from "@/stores/mixin";
import http from "@/plugins/http";
@ -11,7 +12,6 @@ import config from "@/app.config";
* importType
*/
import type { QForm } from "quasar";
import type { ResponseTitle } from "@/modules/05_placement/interface/response/Receive";
import type {
appointmentData,
ResponseData,
@ -37,8 +37,7 @@ const {
dialogConfirm,
} = mixin;
const modalPersonal = ref<boolean>(false);
const dataProfile = ref<DataProfile>();
const dataProfile = ref<DataProfile>(); //
const appointment = ref<appointmentData>({
citizenId: "",
@ -49,42 +48,33 @@ const appointment = ref<appointmentData>({
const myForm = ref<QForm | null>(null);
const edit = ref<boolean>(false);
const profileId = ref<string>("");
const organizationPositionOld = ref<string>("");
const positionTypeOld = ref<string>("");
const positionLevelOld = ref<string>("");
const posNo = ref<string>("");
const salary = ref<number>(0);
const educationOld = ref<string>("");
const reason = ref<string>("");
const date = ref<Date | null>(null);
const educationOld = ref<string>(""); //
const organizationPositionOld = ref<string>(""); ///
const positionTypeOld = ref<string>(""); //
const positionLevelOld = ref<string>(""); //
const posNo = ref<string>(""); //
const salary = ref<number>(0); //
const date = ref<Date | null>(null); //
const reason = ref<string>(""); //
const status = ref<string>("");
const avatar = ref<string>("");
const title = ref<ResponseTitle>({
fullname: "",
organizationPositionOld: "",
positionLevelOld: "",
positionTypeOld: "",
});
const fullName = ref<string>("");
/**
* fetch รายละเอยดการปรบระดบชนงานลกจาง
*/
function fecthappointmentByid() {
async function fecthappointmentByid() {
showLoader();
http
await http
.get(config.API.appointEmployeeByid(paramsId.toString()))
.then((res: ResponseData) => {
dataProfile.value = res.data.result as unknown as DataProfile;
const data = res.data.result;
appointment.value = data;
profileId.value = data.profileId;
title.value.fullname = `${data.prefix === null ? "" : data.prefix}${
fullName.value = `${data.prefix === null ? "" : data.prefix}${
data.firstName ?? "-"
} ${data.lastName ?? "-"}`;
title.value.organizationPositionOld = data.organizationPositionOld ?? "-";
title.value.positionLevelOld = data.positionLevelOld ?? "-";
title.value.positionTypeOld = data.positionTypeOld ?? "-";
(status.value = data.status),
(educationOld.value = data.educationOld ?? "-");
organizationPositionOld.value = data.organizationPositionOld;
@ -94,7 +84,6 @@ function fecthappointmentByid() {
salary.value = data.salary ?? 0;
reason.value = data.reason;
date.value = data.positionDate;
avatar.value = data.avatar ?? "";
})
.catch((e) => {
messageError($q, e);
@ -186,7 +175,7 @@ onMounted(() => {
class="q-mr-sm"
@click="router.push(`/placement/appoint-employee`)"
/>
รายละเอยดการปรบระดบชนงานลกจาง{{ title.fullname }}
รายละเอยดการปรบระดบชนงานลกจาง{{ fullName }}
</div>
<CardProfile :data="dataProfile as DataProfile" :type="'employee'" />

View file

@ -1,34 +0,0 @@
<script setup lang="ts">
const props = defineProps({
title: String,
close: {
type: Function,
default: () => console.log("not function"),
},
});
const close = async () => {
props.close();
};
</script>
<template>
<q-toolbar class="q-py-md">
<q-toolbar-title class="header-text">{{ title }}</q-toolbar-title>
<q-btn
icon="close"
unelevated
round
dense
@click="close"
style="color: #ff8080; background-color: #ffdede"
/>
</q-toolbar>
</template>
<style scoped lang="scss">
.header-text {
font-size: 18px;
font-weight: 600;
line-height: 26px;
color: #35373c;
}
</style>

View file

@ -1,19 +1,16 @@
<script setup lang="ts">
import { ref, computed, watchEffect } from "vue";
import { ref, watch } from "vue";
import { useQuasar } from "quasar";
import { useCounterMixin } from "@/stores/mixin";
import http from "@/plugins/http";
import config from "@/app.config";
import type { QTableProps } from "quasar";
import type { UserData } from "@/modules/05_placement/interface/response/AppointMent";
import DialogHeader from "@/components/DialogHeader.vue";
import http from "@/plugins/http";
import config from "@/app.config";
import { useTransferDataStore } from "@/modules/05_placement/store";
const storeFn = useTransferDataStore();
const { statusText } = storeFn;
const $q = useQuasar();
const mixin = useCounterMixin();
const {
showLoader,
@ -24,24 +21,23 @@ const {
date2Thai,
} = mixin;
const $q = useQuasar();
const selected = ref<[]>([]);
const checkSelected = computed(() => {
if (selected.value.length === 0) {
return true;
}
});
const props = defineProps({
Modal: Boolean,
clickClose: Function,
fecthlistappointment: Function,
fetchData: Function,
nextPage: Function,
optionsType: Array,
rows2: Array,
filterKeyword2: String,
type: String,
});
const emit = defineEmits([
"update:filterKeyword2",
"update:type",
"update:selected",
]);
const selected = ref<[]>([]); //
const visibleColumns2 = ref<string[]>([
"no",
"citizenId",
@ -49,6 +45,11 @@ const visibleColumns2 = ref<string[]>([
"organizationName",
"dateOfBirth",
]);
/**
* ปเดทคคนหา
* @param value ตำคนหา
*/
const columns2 = ref<QTableProps["columns"]>([
{
name: "no",
@ -98,62 +99,62 @@ const columns2 = ref<QTableProps["columns"]>([
style: "font-size: 14px",
},
]);
// const pageNext = (item: object) => {
// props.nextPage?.(item);
// };
const emit = defineEmits([
"update:filterKeyword2",
"update:type",
"update:selected",
]);
const updateInput = (value: any) => {
function updateInput(value: any) {
emit("update:filterKeyword2", value);
};
}
const updateInputType = (value: string) => {
emit("update:type", value);
};
//
const Reset = () => {
/**
* เซตคาในชองคนหา
*/
function Reset() {
emit("update:filterKeyword2", "");
};
// modal
const clickAddlist = () => {
dialogConfirm($q, () => createdAppoint());
};
}
//
const createdAppoint = async () => {
let pId: string[] = [];
let Type = props.type as string;
selected.value.forEach((e: UserData) => {
pId.push(e.id);
});
let data = {
id: pId,
};
showLoader();
await http
.post(config.API.appointEmployeeOrder(Type), data)
.then(async () => {
await props.fecthlistappointment?.();
await props.clickClose?.();
await success($q, "บันทึกสำเร็จ");
selected.value = [];
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
hideLoader();
/**
* งกนยนยนสงไปออกคำส
*/
function clickAddlist() {
dialogConfirm($q, async () => {
let pId: string[] = [];
let Type = props.type as string;
selected.value.forEach((e: UserData) => {
pId.push(e.id);
});
};
let data = {
id: pId,
};
showLoader();
await http
.post(config.API.appointEmployeeOrder(Type), data)
.then(async () => {
await props.fetchData?.();
await props.clickClose?.();
await success($q, "บันทึกสำเร็จ");
selected.value = [];
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
hideLoader();
});
});
}
watchEffect(() => {
if (props.Modal === true) {
selected.value = [];
/**
* เม props.modal เป true
*
* กำหนดให selected เปนคาวาง
*/
watch(
() => props.Modal,
() => {
if (props.Modal === true) {
selected.value = [];
}
}
});
);
</script>
<template>
<q-dialog v-model="props.Modal">
@ -297,7 +298,7 @@ watchEffect(() => {
label="ส่งไปออกคำสั่ง"
@click="clickAddlist"
color="public"
:disable="checkSelected"
:disable="selected.length === 0"
><q-tooltip>งไปออกคำส</q-tooltip></q-btn
>
</q-card-actions>

View file

@ -1,700 +0,0 @@
<script setup lang="ts">
import { useQuasar, QForm } from "quasar";
import { onMounted, reactive, ref, watch } from "vue";
import DialogHeader from "@/components/DialogHeader.vue";
import DialogFooter from "@/modules/05_placement/components/PersonalList/DialogFooter.vue";
import { useCounterMixin } from "@/stores/mixin";
import http from "@/plugins/http";
import config from "@/app.config";
const $q = useQuasar();
const mixin = useCounterMixin(); //
const {
date2Thai,
hideLoader,
messageError,
showLoader,
success,
dialogConfirm,
} = mixin; //
const notFound = ref<string>("ไม่พบข้อมูลที่ค้นหา");
const noData = ref<string>("ไม่พบข้อมูลผังโครงสร้าง");
const checkValidate = ref<boolean>(false);
const myFormPosition = ref<any>();
const selected = ref<string>("");
const selectedFile = ref<string>("");
const dataRespone = ref<any>();
const personal = ref<any>();
const expanded = ref<string[]>([]);
const treeData = ref<Array<any>>([]);
const placementPosition = ref<any>([]);
const search = ref<string>("");
const filterRef = ref<any>(null);
const id = ref<string>("");
const editDataStatus = ref<boolean>(false);
// Set form field
let dataForm = reactive({
personalId: "",
containDate: new Date(),
posNoId: "",
positionId: "",
positionLevelId: "",
positionLineId: "",
positionPathSideId: "",
positionTypeId: "",
});
onMounted(async () => {
// await fetchPublishFile();
// await loadTreeData();
await fetchplacementPosition();
});
// const fetchPublishFile = async () => {
// await http
// .get(config.API.getPublishFileHistory)
// .then((res) => {
// let data = res.data.result;
// selectedFile.value = data[0].fileName;
// })
// .catch((e) => {
// messageError($q, e);
// })
// .finally(async () => {
// hideLoader();
// });
// };
// json
// const loadTreeData = async () => {
// expanded.value = [];
// await http
// .get(`${config.s3ClusterUrl}${selectedFile.value}`)
// .then((res: any) => {
// treeData.value = res.data;
// dataRespone.value = res.data;
// // Filter objects with "name" null
// const filteredData = res.data.filter(filterByPersonIdNull);
// treeData.value = filteredData;
// })
// .catch((e: any) => {
// messageError($q, e);
// })
// .finally(() => {
// hideLoader();
// });
// };
function filterByPersonIdNull(obj: any) {
if (obj.name === null && obj.isCondition != true) {
return true;
}
if (obj.children && obj.children.length > 0) {
obj.children = obj.children.filter(filterByPersonIdNull);
return obj.children.length > 0;
}
return false;
}
// position
const fetchplacementPosition = async () => {
await http
.get(config.API.apppointmentPositionUse())
.then((res: any) => {
placementPosition.value = res.data.result;
})
.catch((e: any) => {
messageError($q, e);
});
};
const props = defineProps({
personalId: String,
modal: Boolean,
close: {
type: Function,
default: () => console.log("close modal"),
},
personal: Object,
});
const myFilterMethod = (node: any, filter: string) => {
const filt = filter;
return (
(node.name && node.name.indexOf(filt) > -1) ||
(node.organizationName && node.organizationName.indexOf(filt) > -1) ||
(node.positionNum && node.positionNum.indexOf(filt) > -1) ||
(node.positionName && node.positionName.indexOf(filt) > -1) ||
(node.governmentCode &&
node.governmentCode.toString().indexOf(filt) > -1) ||
(node.agency && node.agency.indexOf(filt) > -1) ||
(node.government && node.government.indexOf(filt) > -1) ||
(node.department && node.department.indexOf(filt) > -1) ||
(node.pile && node.pile.indexOf(filt) > -1) ||
(node.organizationShortName &&
node.organizationShortName.indexOf(filt) > -1) ||
(node.positionSideName && node.positionSideName.indexOf(filt) > -1) ||
(node.executivePosition && node.executivePosition.indexOf(filt) > -1) ||
(node.executivePositionSide &&
node.executivePositionSide.indexOf(filt) > -1) ||
(node.positionLevel && node.positionLevel.indexOf(filt) > -1)
);
};
const validateData = async () => {
checkValidate.value = true;
await myFormPosition.value.validate().then((result: boolean) => {
if (result == false) {
checkValidate.value = false;
}
});
};
const saveAppoint = async () => {
myFormPosition.value.validate().then(async (result: boolean) => {
if (props.personalId !== undefined) {
id.value = props.personalId.toString();
}
if (result) {
const dataAppoint = await {
recruitDate: dataForm.containDate,
posNoId: dataForm.posNoId,
positionId: dataForm.positionId,
positionLevelId: dataForm.positionLevelId,
positionLineId: dataForm.positionLineId,
positionPathSideId: dataForm.positionPathSideId,
positionTypeId: dataForm.positionTypeId,
};
showLoader();
await http
.put(config.API.appointEmployeePosition(id.value), dataAppoint)
.then(() => {
success($q, "บันทึกสำเร็จ");
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await closeAndClear();
// await fetchPublishFile();
// await loadTreeData();
await fetchplacementPosition();
hideLoader();
});
}
});
};
const closeModal = () => {
if (editDataStatus.value == true) {
dialogConfirm(
$q,
async () => {
editDataStatus.value = false;
await closeAndClear();
},
`ข้อมูลมีการแก้ไข`,
`ยืนยันที่จะปิดโดยไม่บันทึกใช่หรือไม่?`
);
} else {
closeAndClear();
}
};
const closeAndClear = async () => {
await props.close();
editDataStatus.value = false;
selected.value = "";
dataForm.personalId = "";
dataForm.containDate = new Date();
dataForm.posNoId = "";
dataForm.positionId = "";
dataForm.positionLevelId = "";
dataForm.positionLineId = "";
dataForm.positionPathSideId = "";
dataForm.positionTypeId = "";
};
//
const posNoOptions = ref<Object[]>([
{
label: "",
value: "",
},
]);
//
const positionOptions = ref<Object[]>([
{
label: "",
value: "",
},
]);
// /
const positionPathSideOptions = ref<Object[]>([
{
label: "",
value: "",
},
]);
//
const positionTypeOptions = ref<Object[]>([
{
label: "",
value: "",
},
]);
//
const positionLineOptions = ref<Object[]>([
{
label: "",
value: "",
},
]);
//
const positionLevelOptions = ref<Object[]>([
{
label: "",
value: "",
},
]);
const selectedPosition = async (data: any) => {
if (data.name == null && selected.value != data.keyId) {
editDataStatus.value = true;
selected.value = data.keyId;
// posNo Options
posNoOptions.value = [
{
label: data.positionNum,
value: data.positionNumId,
},
];
dataForm.posNoId = data.positionNumId;
// position Options
positionOptions.value = [
{
label: data.positionName,
value: data.positionNameId,
},
];
dataForm.positionId = data.positionNameId;
// positionPathSide Options
let positionPathSideArr: any = [];
if (data.positionSideNameObj && data.positionSideNameObj != null) {
data.positionSideNameObj.map((x: any) => {
positionPathSideArr.push({
label: x.Name,
value: x.Id,
});
});
positionPathSideOptions.value = positionPathSideArr;
dataForm.positionPathSideId =
positionPathSideArr.length > 1 || positionPathSideArr.length == 0
? ""
: positionPathSideArr[0].value;
}
// positionType Options
positionTypeOptions.value = [
{
label: data.positionType,
value: data.positionTypeId,
},
];
dataForm.positionTypeId = data.positionTypeId;
// positionLine Options
positionLineOptions.value = [
{
label: data.positionLine,
value: data.positionLineId,
},
];
dataForm.positionLineId = data.positionLineId;
// positionLevel Options
let positionLevelsArr: any = [];
if (data.positionLevelObj != null) {
data.positionLevelObj.map((x: any) => {
positionLevelsArr.push({
label: x.Name,
value: x.Id,
});
});
positionLevelOptions.value = positionLevelsArr;
dataForm.positionLevelId =
positionLevelsArr.length > 1 || positionLevelsArr.length == 0
? ""
: positionLevelsArr[0].value;
dataForm.positionLevelId = data.positionLevelObj[0].Id;
}
} else if (selected.value == data.keyId) {
selected.value = "";
dataForm.posNoId = "";
dataForm.positionId = "";
dataForm.positionLevelId = "";
dataForm.positionLineId = "";
dataForm.positionPathSideId = "";
dataForm.positionTypeId = "";
}
};
const checkPosition = (val: string) => {
const num = placementPosition.value.findIndex((e: string) => e === val);
return num;
};
watch(props, () => {
expanded.value = [];
const dataPersonal = props.personal;
if (dataPersonal) {
dataPersonal.map((data: any) => {
personal.value = data;
});
}
if (personal.value) {
let findData: any = null;
dataRespone.value.map((x: any) => {
findData = findByPerson(x);
if (findData != null) {
selectedPosition(findData);
for (let i = 3; i <= findData.keyId.length; i += 2) {
expanded.value.push(findData.keyId.slice(0, i));
}
}
});
}
});
function findByPerson(element: any): any {
if (
element.positionNumId &&
element.positionLineId === personal.value.positionLineId &&
element.positionTypeId === personal.value.positionTypeId &&
element.positionNumId === personal.value.posNoId &&
(element.positionLevelObj === null ||
element.positionLevelObj[0].Id === personal.value.positionLevelId)
) {
return element;
} else if (element.children) {
var i;
var result = null;
for (i = 0; result == null && i < element.children.length; i++) {
result = findByPerson(element.children[i]);
}
return result;
}
return null;
}
</script>
<template>
<q-dialog v-model="props.modal" persistent>
<q-card style="width: 900px; max-width: 80vw">
<q-form ref="myFormPosition">
<DialogHeader :tittle="'เลือกหน่วยงาน'" :close="closeModal" />
<q-separator />
<q-card-section class="q-pa-sm bg-grey-1">
<div class="row col-12 q-col-gutter-sm">
<div class="col-xs-12 col-sm-7 row">
<q-card flat bordered class="fit q-pa-sm">
<q-scroll-area visible style="height: 70vh">
<q-input
outlined
dense
ref="filterRef"
v-model="search"
placeholder="ค้นหา"
class="q-mb-sm"
>
<template v-slot:append>
<q-icon name="mdi-magnify" />
</template>
</q-input>
<div class="q-pa-sm q-gutter-sm">
<q-tree
no-transition
dense
:nodes="treeData"
node-key="keyId"
:filter="search"
:no-results-label="notFound"
:no-nodes-label="noData"
:filter-method="myFilterMethod"
v-model:expanded="expanded"
>
<template v-slot:header-organization="prop">
<div class="col">
<div
class="row items-center q-px-xs q-pt-xs q-gutter-sm"
>
<!--แสดงชอแผนก มพวหนา คลกแลวกาง/ Tree-->
<div class="text-weight-medium">
{{ prop.node.organizationName }}
</div>
<q-badge
v-if="prop.node.totalPositionVacant > 0"
rounded
color="red"
outline
:label="prop.node.totalPositionVacant"
/>
<q-space />
</div>
<div class="col items-center q-px-xs q-pt-xs">
<div class="text-weight-medium text-grey-7">
{{ prop.node.governmentCode }}
{{ prop.node.organizationShortName }}
</div>
</div>
</div>
</template>
<template v-slot:header-person="prop">
<q-item
clickable
:active="selected == prop.node.keyId"
@click="selectedPosition(prop.node)"
:disable="
prop.node.name != null ||
checkPosition(prop.node.positionNumId) != -1
"
active-class="my-list-link text-primary text-weight-medium"
class="row items-center text-dark q-py-xs q-pl-sm rounded-borders my-list"
>
<img
v-if="
prop.node.avatar == '' ||
prop.node.avatar ==
'https://cdn.quasar.dev/img/boy-avatar.png'
"
src="@/assets/avatar_user.jpg"
class="col-xs-1 col-sm-2"
style="
width: 28px;
height: 28px;
border-radius: 50%;
"
/>
<img
v-else
:src="prop.node.avatar"
class="col-xs-1 col-sm-2"
style="
width: 28px;
height: 28px;
border-radius: 50%;
"
/>
<!--=====ตำแหนงวาง แดง=====-->
<div
v-if="prop.node.name == null"
class="q-px-sm text-weight-medium text-red"
>
าง
</div>
<!--=====วหน เขยว=====-->
<div v-else-if="prop.node.positionLeaderFlag">
<div
class="q-px-sm text-weight-medium text-primary"
>
{{ prop.node.name }}
</div>
</div>
<!--=====กนอง ปกต=====-->
<div v-else>
<div class="q-px-sm text-weight-medium">
{{ prop.node.name }}
</div>
</div>
<!--อทายชอคน แสดงสปกต-->
<div class="q-pr-sm">
{{ prop.node.positionName }}
</div>
<div class="q-pr-sm">
{{ prop.node.positionNum }}
</div>
<div class="q-pr-sm">
{{ prop.node.positionLevel }}
</div>
<q-icon
v-if="prop.node.positionLeaderFlag"
class="q-mr-sm"
size="15px"
color="primary"
name="mdi-bookmark"
></q-icon>
<q-space />
</q-item>
</template>
</q-tree>
</div>
</q-scroll-area>
</q-card>
</div>
<div class="col-xs-12 col-sm-5">
<q-card flat bordered class="fit q-pa-sm">
<q-scroll-area visible style="height: 70vh">
<div class="row col-12 q-col-gutter-xs">
<div class="col-xs-12 col-sm-12 col-md-12"></div>
<div class="col-xs-12 col-sm-12 col-md-12">
<datepicker
menu-class-name="modalfix"
v-model="dataForm.containDate"
:locale="'th'"
autoApply
:enableTimePicker="false"
week-start="0"
>
<template #year="{ year }">{{ year + 543 }}</template>
<template #year-overlay-value="{ value }">{{
parseInt(value + 543)
}}</template>
<template #trigger>
<q-input
class="full-width inputgreen cursor-pointer"
outlined
dense
:model-value="
date2Thai(new Date(dataForm.containDate))
"
:rules="[(val: string) => !!val || `${'วันที่รายงานตัว'}`]"
:label="`${'วันที่รายงานตัว'}`"
hide-bottom-space
>
<template v-slot:prepend>
<q-icon
name="event"
class="cursor-pointer"
style="color: var(--q-primary)"
>
</q-icon>
</template>
</q-input>
</template>
</datepicker>
</div>
<q-space />
<div class="col-xs-12 col-sm-12 col-md-12">
<q-select
class="full-width inputgreen cursor-pointer custom-input"
outlined
standout
dense
hide-bottom-space
lazy-rules
:options="posNoOptions"
v-model="dataForm.posNoId"
:label="`${'ตำแหน่งเลขที่'}`"
map-options
/>
</div>
<div class="col-xs-12 col-sm-12 col-md-12">
<q-select
outlined
class="full-width inputgreen cursor-pointer custom-input"
standout
dense
hide-bottom-space
lazy-rules
:options="positionOptions"
v-model="dataForm.positionId"
:label="`${'ตำแหน่ง'}`"
map-options
/>
</div>
<div class="col-xs-12 col-sm-12 col-md-12">
<q-select
outlined
class="full-width inputgreen cursor-pointer custom-input"
standout
dense
hide-bottom-space
lazy-rules
emit-value
:options="positionPathSideOptions"
v-model="dataForm.positionPathSideId"
:label="`${'ด้าน/สาขา'}`"
map-options
/>
</div>
<div class="col-xs-12 col-sm-12 col-md-12">
<q-select
outlined
class="full-width inputgreen cursor-pointer custom-input"
standout
dense
hide-bottom-space
lazy-rules
:options="positionTypeOptions"
v-model="dataForm.positionTypeId"
:label="`${'ประเภทตำแหน่ง'}`"
map-options
/>
</div>
<div class="col-xs-12 col-sm-12 col-md-12">
<q-select
outlined
class="full-width inputgreen cursor-pointer custom-input"
standout
dense
hide-bottom-space
lazy-rules
:options="positionLineOptions"
v-model="dataForm.positionLineId"
:label="`${'สายงาน'}`"
map-options
/>
</div>
<div class="col-xs-12 col-sm-12 col-md-12">
<q-select
outlined
class="full-width inputgreen cursor-pointer custom-input"
standout
dense
lazy-rules
:options="positionLevelOptions"
v-model="dataForm.positionLevelId"
:label="`${'ระดับ'}`"
hide-bottom-space
:rules="[(val: string) => !!val || `${'กรุณาเลือกระดับ'}`]"
emit-value
map-options
/>
</div>
</div>
</q-scroll-area>
</q-card>
</div>
</div>
</q-card-section>
<q-separator />
<DialogFooter
:editvisible="true"
:validate="validateData"
:save="saveAppoint"
v-model:modalEdit="editDataStatus"
/>
</q-form>
</q-card>
</q-dialog>
</template>
<style scoped lang="scss">
.q-tree__node-header {
padding: 0px;
margin-top: 0px;
border-radius: 4px;
outline: 0;
}
.my-list-link {
color: rgb(118, 168, 222);
border-radius: 5px;
background: #a3d3fb48 !important;
font-weight: 600;
border: 1px solid rgba(175, 185, 196, 0.217);
}
</style>

View file

@ -1,8 +1,10 @@
<script setup lang="ts">
import { onMounted, ref } from "vue";
import { checkPermission } from "@/utils/permissions";
import { useQuasar } from "quasar";
import { useRoute, useRouter } from "vue-router";
import { useQuasar } from "quasar";
import { checkPermission } from "@/utils/permissions";
import { useCounterMixin } from "@/stores/mixin";
import http from "@/plugins/http";
import config from "@/app.config";
@ -10,7 +12,6 @@ import config from "@/app.config";
* importType
*/
import type { QForm } from "quasar";
import type { ResponseTitle } from "@/modules/05_placement/interface/response/Receive";
import type { DataProfile } from "@/modules/05_placement/interface/response/AppointMent";
/**
@ -18,11 +19,6 @@ import type { DataProfile } from "@/modules/05_placement/interface/response/Appo
*/
import CardProfile from "@/components/CardProfile.vue"; // card
/**
* importStore
*/
import { useCounterMixin } from "@/stores/mixin";
const $q = useQuasar();
const route = useRoute();
const router = useRouter();
@ -34,49 +30,39 @@ const {
success,
dialogConfirm,
} = useCounterMixin();
const paramsId = route.params.id;
const dataProfile = ref<DataProfile>();
const paramsId = route.params.id; //id
const dataProfile = ref<DataProfile>(); //
const edit = ref<boolean>(false); //
const myForm = ref<QForm | null>(null);
const edit = ref<boolean>(false);
const profileId = ref<string>("");
const organizationPositionOld = ref<string>("");
const positionTypeOld = ref<string>("");
const positionLevelOld = ref<string>("");
const posNo = ref<string>("");
const salary = ref<number>(0);
const educationOld = ref<string>("");
const reason = ref<string>("");
const date = ref<Date | null>(null);
const educationOld = ref<string>(""); //
const organizationPositionOld = ref<string>(""); //'/
const positionTypeOld = ref<string>(""); //
const positionLevelOld = ref<string>(""); //
const posNo = ref<string>(""); //
const salary = ref<number>(0); //
const date = ref<Date | null>(null); //
const reason = ref<string>(""); //
const status = ref<string>("");
const avatar = ref<string>("");
const title = ref<ResponseTitle>({
fullname: "",
organizationPositionOld: "",
positionLevelOld: "",
positionTypeOld: "",
});
const fullName = ref<string>("");
/**
* fetch รายละเอยดการแตงต-เลอน-าย
*/
function fecthappointmentByid() {
async function fecthappointmentByid() {
showLoader();
http
await http
.get(config.API.appointmentByid(paramsId.toString()))
.then((res) => {
dataProfile.value = res.data.result as unknown as DataProfile;
const data = res.data.result;
profileId.value = data.profileId;
title.value.fullname = `${data.prefix}${data.firstName ?? "-"} ${
fullName.value = `${data.prefix}${data.firstName ?? "-"} ${
data.lastName ?? "-"
}`;
title.value.organizationPositionOld = data.organizationPositionOld ?? "-";
title.value.positionLevelOld = data.positionLevelOld ?? "-";
title.value.positionTypeOld = data.positionTypeOld ?? "-";
(status.value = data.status),
(educationOld.value = data.educationOld ?? "-");
organizationPositionOld.value = data.organizationPositionOld;
@ -86,7 +72,6 @@ function fecthappointmentByid() {
salary.value = data.salary ?? 0;
reason.value = data.reason;
date.value = data.positionDate;
avatar.value = data.avatar ?? "";
})
.catch((e) => {
messageError($q, e);
@ -156,6 +141,7 @@ onMounted(() => {
fecthappointmentByid();
});
</script>
<template>
<div class="toptitle text-dark col-12 row items-center">
<q-btn
@ -168,7 +154,7 @@ onMounted(() => {
class="q-mr-sm"
@click="router.push(`/placement/appoint-promote`)"
/>
รายละเอยดการแตงต-เลอน-าย{{ title.fullname }}
รายละเอยดการแตงต-เลอน-าย{{ fullName }}
</div>
<CardProfile :data="dataProfile as DataProfile" />
@ -392,7 +378,7 @@ onMounted(() => {
:borderless="!edit"
v-model="reason"
hide-bottom-space
:label="`${'หมายเหตุ '}`"
:label="`${'หมายเหตุ'}`"
type="textarea"
/>
</div>

View file

@ -1,715 +0,0 @@
<script setup lang="ts">
import { useQuasar, QForm } from "quasar";
import { onMounted, reactive, ref, watch } from "vue";
import DialogHeader from "@/components/DialogHeader.vue";
import DialogFooter from "@/modules/05_placement/components/PersonalList/DialogFooter.vue";
import { useCounterMixin } from "@/stores/mixin";
import http from "@/plugins/http";
import config from "@/app.config";
const $q = useQuasar();
const mixin = useCounterMixin(); //
const {
date2Thai,
hideLoader,
messageError,
showLoader,
success,
dialogConfirm,
} = mixin; //
const notFound = ref<string>("ไม่พบข้อมูลที่ค้นหา");
const noData = ref<string>("ไม่พบข้อมูลผังโครงสร้าง");
const checkValidate = ref<boolean>(false);
const myFormPosition = ref<any>();
const selected = ref<string>("");
const selectedFile = ref<string>("");
const dataRespone = ref<any>();
const personal = ref<any>();
const expanded = ref<string[]>([]);
const treeData = ref<Array<any>>([]);
const placementPosition = ref<any>([]);
const search = ref<string>("");
const filterRef = ref<any>(null);
const id = ref<string>("");
const editDataStatus = ref<boolean>(false);
// Set form field
let dataForm = reactive({
personalId: "",
containDate: new Date(),
posNoId: "",
positionId: "",
positionLevelId: "",
positionLineId: "",
positionPathSideId: "",
positionTypeId: "",
});
// const fetchPublishFile = async () => {
// await http
// .get(config.API.getPublishFileHistory)
// .then((res) => {
// let data = res.data.result;
// selectedFile.value = data[0].fileName;
// })
// .catch((e) => {
// messageError($q, e);
// })
// .finally(async () => {
// hideLoader();
// });
// };
// json
// const loadTreeData = async () => {
// expanded.value = [];
// await http
// .get(`${config.s3ClusterUrl}${selectedFile.value}`)
// .then((res: any) => {
// treeData.value = res.data;
// dataRespone.value = res.data;
// // Filter objects with "name" null
// const filteredData = res.data.filter(filterByPersonIdNull);
// treeData.value = filteredData;
// })
// .catch((e: any) => {
// messageError($q, e);
// })
// .finally(() => {
// hideLoader();
// });
// };
function filterByPersonIdNull(obj: any) {
if (obj.name === null && obj.isCondition != true) {
return true;
}
if (obj.children && obj.children.length > 0) {
obj.children = obj.children.filter(filterByPersonIdNull);
return obj.children.length > 0;
}
return false;
}
// position
const fetchplacementPosition = async () => {
await http
.get(config.API.apppointmentPosition())
.then((res: any) => {
placementPosition.value = res.data.result;
})
.catch((e: any) => {
messageError($q, e);
});
};
const props = defineProps({
personalId: String,
modal: Boolean,
close: {
type: Function,
default: () => console.log("close modal"),
},
personal: Object,
});
const myFilterMethod = (node: any, filter: string) => {
const filt = filter;
return (
(node.name && node.name.indexOf(filt) > -1) ||
(node.organizationName && node.organizationName.indexOf(filt) > -1) ||
(node.positionNum && node.positionNum.indexOf(filt) > -1) ||
(node.positionName && node.positionName.indexOf(filt) > -1) ||
(node.governmentCode &&
node.governmentCode.toString().indexOf(filt) > -1) ||
(node.agency && node.agency.indexOf(filt) > -1) ||
(node.government && node.government.indexOf(filt) > -1) ||
(node.department && node.department.indexOf(filt) > -1) ||
(node.pile && node.pile.indexOf(filt) > -1) ||
(node.organizationShortName &&
node.organizationShortName.indexOf(filt) > -1) ||
(node.positionSideName && node.positionSideName.indexOf(filt) > -1) ||
(node.executivePosition && node.executivePosition.indexOf(filt) > -1) ||
(node.executivePositionSide &&
node.executivePositionSide.indexOf(filt) > -1) ||
(node.positionLevel && node.positionLevel.indexOf(filt) > -1)
);
};
const validateData = async () => {
checkValidate.value = true;
await myFormPosition.value.validate().then((result: boolean) => {
if (result == false) {
checkValidate.value = false;
}
});
};
const saveAppoint = async () => {
myFormPosition.value.validate().then(async (result: boolean) => {
if (props.personalId !== undefined) {
id.value = props.personalId.toString();
}
if (result) {
const dataAppoint = await {
recruitDate: dataForm.containDate,
posNoId: dataForm.posNoId,
positionId: dataForm.positionId,
positionLevelId: dataForm.positionLevelId,
positionLineId: dataForm.positionLineId,
positionPathSideId: dataForm.positionPathSideId,
positionTypeId: dataForm.positionTypeId,
};
showLoader();
await http
.put(config.API.appointmentPosition(id.value), dataAppoint)
.then((res) => {
success($q, "บันทึกสำเร็จ");
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await closeAndClear();
// await fetchPublishFile();
// await loadTreeData();
await fetchplacementPosition();
hideLoader();
});
}
});
};
const closeModal = () => {
if (editDataStatus.value == true) {
dialogConfirm(
$q,
async () => {
editDataStatus.value = false;
await closeAndClear();
},
`ข้อมูลมีการแก้ไข`,
`ยืนยันที่จะปิดโดยไม่บันทึกใช่หรือไม่?`
);
} else {
closeAndClear();
}
};
const closeAndClear = async () => {
await props.close();
editDataStatus.value = false;
selected.value = "";
dataForm.personalId = "";
dataForm.containDate = new Date();
dataForm.posNoId = "";
dataForm.positionId = "";
dataForm.positionLevelId = "";
dataForm.positionLineId = "";
dataForm.positionPathSideId = "";
dataForm.positionTypeId = "";
};
//
const posNoOptions = ref<Object[]>([
{
label: "",
value: "",
},
]);
//
const positionOptions = ref<Object[]>([
{
label: "",
value: "",
},
]);
// /
const positionPathSideOptions = ref<Object[]>([
{
label: "",
value: "",
},
]);
//
const positionTypeOptions = ref<Object[]>([
{
label: "",
value: "",
},
]);
//
const positionLineOptions = ref<Object[]>([
{
label: "",
value: "",
},
]);
//
const positionLevelOptions = ref<Object[]>([
{
label: "",
value: "",
},
]);
const selectedPosition = async (data: any) => {
if (data.name == null && selected.value != data.keyId) {
editDataStatus.value = true;
selected.value = data.keyId;
// posNo Options
posNoOptions.value = [
{
label: data.positionNum,
value: data.positionNumId,
},
];
dataForm.posNoId = data.positionNumId;
// position Options
positionOptions.value = [
{
label: data.positionName,
value: data.positionNameId,
},
];
dataForm.positionId = data.positionNameId;
// positionPathSide Options
let positionPathSideArr: any = [];
if (data.positionSideNameObj && data.positionSideNameObj != null) {
data.positionSideNameObj.map((x: any) => {
positionPathSideArr.push({
label: x.Name,
value: x.Id,
});
});
positionPathSideOptions.value = positionPathSideArr;
dataForm.positionPathSideId =
positionPathSideArr.length > 1 || positionPathSideArr.length == 0
? ""
: positionPathSideArr[0].value;
}
// positionType Options
positionTypeOptions.value = [
{
label: data.positionType,
value: data.positionTypeId,
},
];
dataForm.positionTypeId = data.positionTypeId;
// positionLine Options
positionLineOptions.value = [
{
label: data.positionLine,
value: data.positionLineId,
},
];
dataForm.positionLineId = data.positionLineId;
// positionLevel Options
let positionLevelsArr: any = [];
if (data.positionLevelObj != null) {
data.positionLevelObj.map((x: any) => {
positionLevelsArr.push({
label: x.Name,
value: x.Id,
});
});
positionLevelOptions.value = positionLevelsArr;
dataForm.positionLevelId =
positionLevelsArr.length > 1 || positionLevelsArr.length == 0
? ""
: positionLevelsArr[0].value;
dataForm.positionLevelId = data.positionLevelObj[0].Id;
}
} else if (selected.value == data.keyId) {
selected.value = "";
dataForm.posNoId = "";
dataForm.positionId = "";
dataForm.positionLevelId = "";
dataForm.positionLineId = "";
dataForm.positionPathSideId = "";
dataForm.positionTypeId = "";
}
};
const checkPosition = (val: string) => {
const num = placementPosition.value.findIndex((e: string) => e === val);
return num;
};
watch(props, () => {
expanded.value = [];
const dataPersonal = props.personal;
if (dataPersonal) {
dataPersonal.map((data: any) => {
personal.value = data;
});
}
if (personal.value) {
let findData: any = null;
dataRespone.value.map((x: any) => {
findData = findByPerson(x);
if (findData != null) {
selectedPosition(findData);
for (let i = 3; i <= findData.keyId.length; i += 2) {
expanded.value.push(findData.keyId.slice(0, i));
}
}
});
}
});
function findByPerson(element: any): any {
if (
element.positionNumId &&
element.positionLineId === personal.value.positionLineId &&
element.positionTypeId === personal.value.positionTypeId &&
element.positionNumId === personal.value.posNoId &&
(element.positionLevelObj === null ||
element.positionLevelObj[0].Id === personal.value.positionLevelId)
) {
return element;
} else if (element.children) {
var i;
var result = null;
for (i = 0; result == null && i < element.children.length; i++) {
result = findByPerson(element.children[i]);
}
return result;
}
return null;
}
onMounted(async () => {
// await fetchPublishFile();
// await loadTreeData();
// await fetchplacementPosition();
});
</script>
<template>
<q-dialog v-model="props.modal" persistent>
<q-card style="width: 900px; max-width: 80vw">
<q-form ref="myFormPosition">
<DialogHeader
:tittle="'เลือกหน่วยงานที่แต่งตั้ง - เลื่อน'"
:close="closeModal"
/>
<q-separator />
<q-card-section class="q-pa-sm bg-grey-1">
<div class="row col-12 q-col-gutter-sm">
<div class="col-xs-12 col-sm-7 row">
<q-card flat bordered class="fit q-pa-sm">
<q-scroll-area visible style="height: 70vh">
<q-input
outlined
dense
ref="filterRef"
v-model="search"
placeholder="ค้นหา"
class="q-mb-sm"
>
<template v-slot:append>
<q-icon name="mdi-magnify" />
</template>
</q-input>
<div class="q-pa-sm q-gutter-sm">
<q-tree
no-transition
dense
:nodes="treeData"
node-key="keyId"
:filter="search"
:no-results-label="notFound"
:no-nodes-label="noData"
:filter-method="myFilterMethod"
v-model:expanded="expanded"
>
<template v-slot:header-organization="prop">
<div class="col">
<div
class="row items-center q-px-xs q-pt-xs q-gutter-sm"
>
<!--แสดงชอแผนก มพวหนา คลกแลวกาง/ Tree-->
<div class="text-weight-medium">
{{ prop.node.organizationName }}
</div>
<q-badge
v-if="prop.node.totalPositionVacant > 0"
rounded
color="red"
outline
:label="prop.node.totalPositionVacant"
/>
<q-space />
</div>
<div class="col items-center q-px-xs q-pt-xs">
<div class="text-weight-medium text-grey-7">
{{ prop.node.governmentCode }}
{{ prop.node.organizationShortName }}
</div>
</div>
</div>
</template>
<template v-slot:header-person="prop">
<q-item
clickable
:active="selected == prop.node.keyId"
@click="selectedPosition(prop.node)"
:disable="
prop.node.name != null ||
checkPosition(prop.node.positionNumId) != -1
"
active-class="my-list-link text-primary text-weight-medium"
class="row items-center text-dark q-py-xs q-pl-sm rounded-borders my-list"
>
<img
v-if="
prop.node.avatar == '' ||
prop.node.avatar ==
'https://cdn.quasar.dev/img/boy-avatar.png'
"
src="@/assets/avatar_user.jpg"
class="col-xs-1 col-sm-2"
style="
width: 28px;
height: 28px;
border-radius: 50%;
"
/>
<img
v-else
:src="prop.node.avatar"
class="col-xs-1 col-sm-2"
style="
width: 28px;
height: 28px;
border-radius: 50%;
"
/>
<!--=====ตำแหนงวาง แดง=====-->
<div
v-if="prop.node.name == null"
class="q-px-sm text-weight-medium text-red"
>
าง
</div>
<!--=====วหน เขยว=====-->
<div v-else-if="prop.node.positionLeaderFlag">
<div
class="q-px-sm text-weight-medium text-primary"
>
{{ prop.node.name }}
</div>
</div>
<!--=====กนอง ปกต=====-->
<div v-else>
<div class="q-px-sm text-weight-medium">
{{ prop.node.name }}
</div>
</div>
<!--อทายชอคน แสดงสปกต-->
<div class="q-pr-sm">
{{ prop.node.positionName }}
</div>
<div class="q-pr-sm">
{{ prop.node.positionNum }}
</div>
<div class="q-pr-sm">
{{ prop.node.positionLevel }}
</div>
<q-icon
v-if="prop.node.positionLeaderFlag"
class="q-mr-sm"
size="15px"
color="primary"
name="mdi-bookmark"
></q-icon>
<q-space />
</q-item>
</template>
</q-tree>
</div>
</q-scroll-area>
</q-card>
</div>
<div class="col-xs-12 col-sm-5">
<q-card flat bordered class="fit q-pa-sm">
<q-scroll-area visible style="height: 70vh">
<div class="row col-12 q-col-gutter-xs">
<div class="col-xs-12 col-sm-12 col-md-12"></div>
<div class="col-xs-12 col-sm-12 col-md-12">
<datepicker
menu-class-name="modalfix"
v-model="dataForm.containDate"
:locale="'th'"
autoApply
:enableTimePicker="false"
week-start="0"
>
<template #year="{ year }">{{ year + 543 }}</template>
<template #year-overlay-value="{ value }">{{
parseInt(value + 543)
}}</template>
<template #trigger>
<q-input
class="full-width inputgreen cursor-pointer"
outlined
dense
:model-value="
date2Thai(new Date(dataForm.containDate))
"
:rules="[ (val: string) =>!!val ||`${'วันที่รายงานตัว'}`]"
:label="`${'วันที่รายงานตัว'}`"
hide-bottom-space
>
<template v-slot:prepend>
<q-icon
name="event"
class="cursor-pointer"
style="color: var(--q-primary)"
>
</q-icon>
</template>
</q-input>
</template>
</datepicker>
</div>
<q-space />
<div class="col-xs-12 col-sm-12 col-md-12">
<q-select
class="full-width inputgreen cursor-pointer custom-input"
outlined
standout
dense
hide-bottom-space
lazy-rules
:options="posNoOptions"
v-model="dataForm.posNoId"
:label="`${'ตำแหน่งเลขที่'}`"
map-options
/>
</div>
<div class="col-xs-12 col-sm-12 col-md-12">
<q-select
outlined
class="full-width inputgreen cursor-pointer custom-input"
standout
dense
hide-bottom-space
lazy-rules
:options="positionOptions"
v-model="dataForm.positionId"
:label="`${'ตำแหน่ง'}`"
map-options
/>
</div>
<div class="col-xs-12 col-sm-12 col-md-12">
<q-select
outlined
class="full-width inputgreen cursor-pointer custom-input"
standout
dense
hide-bottom-space
lazy-rules
emit-value
:options="positionPathSideOptions"
v-model="dataForm.positionPathSideId"
:label="`${'ด้าน/สาขา'}`"
map-options
/>
</div>
<div class="col-xs-12 col-sm-12 col-md-12">
<q-select
outlined
class="full-width inputgreen cursor-pointer custom-input"
standout
dense
hide-bottom-space
lazy-rules
:options="positionTypeOptions"
v-model="dataForm.positionTypeId"
:label="`${'ประเภทตำแหน่ง'}`"
map-options
/>
</div>
<div class="col-xs-12 col-sm-12 col-md-12">
<q-select
outlined
class="full-width inputgreen cursor-pointer custom-input"
standout
dense
hide-bottom-space
lazy-rules
:options="positionLineOptions"
v-model="dataForm.positionLineId"
:label="`${'สายงาน'}`"
map-options
/>
</div>
<div class="col-xs-12 col-sm-12 col-md-12">
<q-select
outlined
class="full-width inputgreen cursor-pointer custom-input"
standout
dense
lazy-rules
:options="positionLevelOptions"
v-model="dataForm.positionLevelId"
:label="`${'ระดับตำแหน่ง'}`"
hide-bottom-space
:rules="[(val: string) => !!val || `${'กรุณาเลือกระดับตำแหน่ง'}`]"
emit-value
map-options
/>
</div>
</div>
</q-scroll-area>
</q-card>
</div>
</div>
</q-card-section>
<q-separator />
<DialogFooter
:editvisible="true"
:validate="validateData"
:save="saveAppoint"
v-model:modalEdit="editDataStatus"
/>
</q-form>
</q-card>
</q-dialog>
</template>
<style scoped lang="scss">
.q-tree__node-header {
padding: 0px;
margin-top: 0px;
border-radius: 4px;
outline: 0;
}
.my-list-link {
color: rgb(118, 168, 222);
border-radius: 5px;
background: #a3d3fb48 !important;
font-weight: 600;
border: 1px solid rgba(175, 185, 196, 0.217);
}
</style>

View file

@ -1,34 +0,0 @@
<script setup lang="ts">
const props = defineProps({
title: String,
close: {
type: Function,
default: () => console.log("not function"),
},
});
const close = async () => {
props.close();
};
</script>
<template>
<q-toolbar class="q-py-md">
<q-toolbar-title class="header-text">{{ title }}</q-toolbar-title>
<q-btn
icon="close"
unelevated
round
dense
@click="close"
style="color: #ff8080; background-color: #ffdede"
/>
</q-toolbar>
</template>
<style scoped lang="scss">
.header-text {
font-size: 18px;
font-weight: 600;
line-height: 26px;
color: #35373c;
}
</style>

View file

@ -1,6 +1,9 @@
<script setup lang="ts">
import { ref, computed, watch } from "vue";
import { ref, watch } from "vue";
import { useQuasar } from "quasar";
import { useCounterMixin } from "@/stores/mixin";
import { useTransferDataStore } from "@/modules/05_placement/store";
import http from "@/plugins/http";
import config from "@/app.config";
@ -14,13 +17,6 @@ import type { UserDataNew } from "@/modules/05_placement/interface/response/Appo
* importcomponents
*/
import DialogHeader from "@/components/DialogHeader.vue";
/**
* importStore
*/
import { useCounterMixin } from "@/stores/mixin";
import { useTransferDataStore } from "@/modules/05_placement/store";
const $q = useQuasar();
const storeFn = useTransferDataStore();
const { statusText } = storeFn;
@ -39,7 +35,7 @@ const {
const props = defineProps({
Modal: Boolean,
clickClose: Function,
fecthlistappointment: Function,
fetchData: Function,
nextPage: Function,
optionsType: Array,
rows2: Array,
@ -130,14 +126,12 @@ const columns2 = ref<QTableProps["columns"]>([
style: "font-size: 14px",
},
]);
const selected = ref<[]>([]);
const checkSelected = computed(() => {
if (selected.value.length === 0) {
return true;
}
});
/**
* ไปหนารายละเอยดทเลอก
* @param item
*/
function pageNext(item: any) {
props.nextPage?.(item?.id);
}
@ -173,7 +167,7 @@ function sendToCommand() {
await http
.put(config.API.apppointmentReport(Type), data)
.then(async () => {
await props.fecthlistappointment?.();
await props.fetchData?.();
await props.clickClose?.();
await success($q, "บันทึกสำเร็จ");
selected.value = [];
@ -187,6 +181,11 @@ function sendToCommand() {
});
}
/**
* เม props.modal เป true
*
* กำหนดให selected เปนคาวาง
*/
watch(
() => props.Modal,
() => {
@ -343,7 +342,7 @@ watch(
label="ส่งไปออกคำสั่ง"
@click="sendToCommand"
color="public"
:disable="checkSelected"
:disable="selected.length === 0"
>
<q-tooltip>งไปออกคำส</q-tooltip>
</q-btn>

View file

@ -1,409 +0,0 @@
<script setup lang="ts">
import { useCounterMixin } from "@/stores/mixin";
import { useQuasar } from "quasar";
import type { QTableProps } from "quasar";
import config from "@/app.config";
import http from "@/plugins/http";
import { reactive, ref, onMounted, watch } from "vue";
import DialogHeader from "@/components/DialogHeader.vue";
import type {
optionData,
tableType,
} from "@/modules/05_placement/interface/index/Main";
import { useRouter, useRoute } from "vue-router";
const total = ref<number>(0);
const totalList = ref<number>(1);
const pagination = ref({
sortBy: "createdAt",
descending: true,
page: 1,
rowsPerPage: 10,
});
const props = defineProps({
getData: Function,
});
const route = useRoute();
const router = useRouter();
const id = ref<string>(route.params.id ? route.params.id.toString() : "");
const searchRules = ref<boolean>(false);
const selected = ref<any[]>([]);
const searchRef = ref<any>(null);
const rows = ref<tableType[]>([]);
const type = ref<string>("citizenId");
const search = ref<string>("");
const typeOps = ref<optionData[]>([
{ id: "citizenId", name: "เลขประจำตัวประชาชน" },
{ id: "firstname", name: "ชื่อ" },
{ id: "lastname", name: "นามสกุล" },
]);
const $q = useQuasar();
const mixin = useCounterMixin();
const {
showLoader,
hideLoader,
messageError,
date2Thai,
dialogConfirm,
dialogMessageNotify,
findOrgName,
} = mixin;
const modalDialog = defineModel<boolean>("modal", { required: true });
function onCloseDialog() {
modalDialog.value = false;
rows.value = [];
selected.value = [];
search.value = "";
type.value = "idcard";
}
/** หัวข้อที่เเสดงในตารางผู้ถูกร้องเรียน */
const visibleColumnsRespondent = ref<string[]>([
"no",
"name",
"position",
"positionType",
"organization",
]);
const columnsRespondent = ref<QTableProps["columns"]>([
{
name: "no",
align: "left",
label: "ลำดับ",
sortable: false,
field: "no",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "name",
align: "left",
label: "ชื่อ - นามสกุล",
sortable: true,
field: "name",
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: "positionType",
align: "left",
label: "ประเภทตำแหน่ง",
sortable: true,
field: "positionType",
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",
},
]);
async function searchInput(check: boolean) {
if (check) {
searchRules.value = check;
searchRef.value.validate();
if (!searchRef.value.hasError) {
await getSearch();
}
setTimeout(() => {
searchRules.value = false;
}, 100);
}
}
async function getSearch() {
showLoader();
const body = {
fieldName: type.value,
keyword: search.value,
};
await http
.post(
config.API.orgSearchPersonal() +
`?page=${pagination.value.page}&pageSize=${pagination.value.rowsPerPage}&searchKeyword=${search.value}`,
body
)
.then((res) => {
const data = res.data.result;
totalList.value = Math.ceil(data.total / pagination.value.rowsPerPage);
total.value = data.total;
rows.value = data.data;
})
.catch((err) => {})
.finally(() => {
hideLoader();
});
}
/** update เมื่อเปลี่ยน option */
function updateSelect() {
search.value = "";
}
function onSubmit() {
if (selected.value.length == 0) {
dialogMessageNotify($q, "กรุณาเลือกรายชื่อผู้ที่ย้ายสับเปลี่ยนตำแหน่ง");
} else {
const dataProfile = selected.value;
dialogConfirm($q, () => {
showLoader();
http
.post(config.API.changePositionByIdProfile + `/${id.value}`, {
changePositionId: id.value,
profiles: dataProfile.map((i: any) => ({
profileId: i.id,
prefix: i.prefix,
firstName: i.firstName,
lastName: i.lastName,
citizenId: i.citizenId ? i.citizenId : null,
birthDate: i.birthDate ? i.birthDate : null,
positionOld: i.position ? i.position : null,
positionTypeOld: i.positionType ? i.positionType : null,
positionLevelOld: i.positionLevel ? i.positionLevel : null,
positionNumberOld: i.posNo ? i.posNo : null,
organizationOld: i.organization ? i.organization : null,
amountOld: i.salary ? i.salary : null,
educationOld: i.educationDegree ? i.educationDegree : null,
rootOld: i.root ? i.root : null,
rootOldId: i.rootId ? i.rootId : null,
rootShortNameOld: i.rootShortName ? i.rootShortName : null,
child1Old: i.child1 ? i.child1 : null,
child1OldId: i.child1Id ? i.child1Id : null,
child1ShortNameOld: i.child1ShortName ? i.child1ShortName : null,
child2Old: i.child2 ? i.child2 : null,
child2OldId: i.child2Id ? i.child2Id : null,
child2ShortNameOld: i.child2ShortName ? i.child2ShortName : null,
child3Old: i.child3 ? i.child3 : null,
child3OldId: i.child3Id ? i.child3Id : null,
child3ShortNameOld: i.child3ShortName ? i.child3ShortName : null,
child4Old: i.child4 ? i.child4 : null,
child4OldId: i.child4Id ? i.child4Id : null,
child4ShortNameOld: i.child4ShortName ? i.child4ShortName : null,
posMasterNoOld: i.posMasterNo ? i.posMasterNo : null,
posTypeOldId: i.posTypeId ? i.posTypeId : null,
posTypeNameOld: i.posTypeName ? i.posTypeName : null,
posLevelOldId: i.posLevelId ? i.posLevelId : null,
posLevelNameOld: i.posLevelName ? i.posLevelName : null,
})),
})
.then((res) => {
onCloseDialog();
props.getData?.();
})
.catch((err) => {
messageError($q, err);
})
.finally(() => {
hideLoader();
});
});
}
}
function updatePagination(newPagination: any) {
pagination.value.page = 1;
pagination.value.rowsPerPage = newPagination.rowsPerPage;
}
watch(
() => pagination.value.rowsPerPage,
async () => {
await getSearch();
}
);
</script>
<template>
<q-dialog v-model="modalDialog" persistent>
<q-card :style="$q.screen.gt.xs ? 'min-width: 90vw' : 'width: 100vw'">
<q-form greedy @submit.prevent @validation-success="onSubmit">
<DialogHeader
:tittle="'เพิ่มรายชื่อผู้ที่ย้ายสับเปลี่ยนตำแหน่ง'"
:close="onCloseDialog"
/>
<q-separator />
<q-card-section class="q-pa-none scroll" style="max-height: 80vh">
<div class="row">
<div class="col-12">
<div class="row q-pa-md q-col-gutter-sm">
<div class="col-12 col-sm-6 col-md-3">
<q-select
label="ค้นหาจาก"
v-model="type"
:options="typeOps"
emit-value
dense
@update:model-value="updateSelect"
map-options
outlined
option-label="name"
option-value="id"
/>
</div>
<div class="col-12 col-sm-6 col-md-9">
<q-input
ref="searchRef"
v-model="search"
outlined
clearable
hide-bottom-space
dense
label="คำค้น"
:rules="[
(val) => !!val || !searchRules || `กรุณากรอกคำค้น`,
]"
>
<template v-slot:after>
<q-btn
color="primary"
icon="search"
label="ค้นหา"
class="full-width q-py-sm q-px-md"
@click="searchInput(true)"
>
</q-btn>
</template>
</q-input>
</div>
<div class="col-12 q-pt-sm">
<d-table
ref="table"
:columns="columnsRespondent"
:rows="rows"
row-key="id"
flat
bordered
selection="multiple"
v-model:selected="selected"
:paging="true"
dense
class="custom-header-table"
:visible-columns="visibleColumnsRespondent"
:rows-per-page-options="[1, 25, 50, 100]"
@update:pagination="updatePagination"
>
<template v-slot:pagination="scope">
งหมด {{ total }} รายการ
<q-pagination
v-model="pagination.page"
active-color="primary"
color="dark"
:max="Number(totalList)"
size="sm"
boundary-links
direction-links
:max-pages="5"
@update:model-value="getSearch"
></q-pagination>
</template>
<template v-slot:header="props">
<q-tr :props="props">
<q-th auto-width>
<q-checkbox
keep-color
color="primary"
dense
v-model="props.selected"
/>
</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" class="cursor-pointer">
<q-td>
<q-checkbox
keep-color
color="primary"
dense
v-model="props.selected"
/>
</q-td>
<q-td
v-for="col in props.cols"
:key="col.name"
:props="props"
>
<div v-if="col.name == 'no'">
{{
(pagination.page - 1) * pagination.rowsPerPage +
props.rowIndex +
1
}}
</div>
<div v-else-if="col.name == 'name'">
{{
`${props.row.prefix ? props.row.prefix : ""}${
props.row.firstName ? props.row.firstName : ""
} ${props.row.lastName ? props.row.lastName : ""}`
}}
</div>
<div v-else-if="col.name == 'positionType'">
{{
props.row.positionTypeName
? props.row.positionTypeName
: ""
}}{{
props.row.positionLevelName
? ` (${props.row.positionLevelName})`
: ""
}}
</div>
<div
v-else-if="col.name == 'organization'"
class="table_ellipsis"
>
{{ findOrgName(props.row) }}
</div>
<div v-else>
{{ col.value }}
</div>
</q-td>
</q-tr>
</template>
</d-table>
</div>
</div>
</div>
</div>
</q-card-section>
<q-separator />
<q-card-actions align="right" class="bg-white text-teal">
<q-btn label="บันทึก" color="secondary" type="submit"
><q-tooltip>นทกขอม</q-tooltip></q-btn
>
</q-card-actions>
</q-form>
</q-card>
</q-dialog>
</template>

View file

@ -1,34 +0,0 @@
<script setup lang="ts">
const props = defineProps({
title: String,
close: {
type: Function,
default: () => console.log("not function"),
},
});
const close = async () => {
props.close();
};
</script>
<template>
<q-toolbar class="q-py-md">
<q-toolbar-title class="header-text">{{ title }}</q-toolbar-title>
<q-btn
icon="close"
unelevated
round
dense
@click="close"
style="color: #ff8080; background-color: #ffdede"
/>
</q-toolbar>
</template>
<style scoped lang="scss">
.header-text {
font-size: 18px;
font-weight: 600;
line-height: 26px;
color: #35373c;
}
</style>

View file

@ -1,80 +0,0 @@
<script setup lang="ts">
import { ref, watch } from "vue";
import DialogHeader from "@/components/DialogHeader.vue";
import http from "@/plugins/http";
import config from "@/app.config";
import { useCounterMixin } from "@/stores/mixin";
import { useQuasar } from "quasar";
const $q = useQuasar();
const mixin = useCounterMixin();
const { dialogConfirm, success, showLoader, hideLoader } = mixin;
const modal = defineModel<boolean>("modal", { required: true });
const editCheck = defineModel<boolean>("edit");
const round = defineModel<string>("round", { required: true });
const idRound = defineModel<string>("id", { required: true });
const props = defineProps({
getData: Function,
});
/** ปิด dialog */
function close() {
modal.value = false;
editCheck.value = false;
round.value = "";
idRound.value = "";
}
function onSubmit() {
dialogConfirm($q, () => {
const url = editCheck.value
? config.API.changePosition + `/${idRound.value}`
: config.API.changePosition;
http[editCheck.value ? "put" : "post"](url, {
name: round.value,
}).then((res) => {
close();
success($q, "บันทึกข้อมูลสำเร็จ");
props.getData?.();
});
});
}
</script>
<template>
<q-dialog persistent v-model="modal">
<q-card bordered style="min-width: 40vh">
<q-form greedy @submit.prevent @validation-success="onSubmit">
<DialogHeader
:tittle="`${
editCheck ? 'แก้ไข' : 'เพิ่ม'
}รอบการออกคำสงยายสบเปลยนตำแหน`"
:close="close"
/>
<q-separator />
<q-card-section class="q-pa-sm">
<div class="row">
<div class="col-12">
<q-input
v-model="round"
outlined
dense
hide-bottom-space
class="inputgreen"
label="ชื่อรอบการย้ายสับเปลี่ยนตำแหน่ง"
:rules="[(val:string) => !!val || `${'กรุณากรอกชื่อรอบการย้ายสับเปลี่ยนตำแหน่ง'}`,]"
></q-input>
</div>
</div>
</q-card-section>
<q-separator />
<q-card-actions align="right" class="bg-white text-teal">
<q-btn label="บันทึก" color="secondary" type="submit"
><q-tooltip>นทกขอม</q-tooltip></q-btn
>
</q-card-actions>
</q-form>
</q-card>
</q-dialog>
</template>

View file

@ -1,405 +0,0 @@
<script setup lang="ts">
import { ref, onMounted, watch } from "vue";
import type { QTableProps } from "quasar";
import { useQuasar } from "quasar";
import { useRouter } from "vue-router";
import { useCounterMixin } from "@/stores/mixin";
import { useTransferDataStore } from "@/modules/05_placement/store";
import SendToCommand from "@/modules/05_placement/components/ChangePosition/SendToCommand.vue";
import DialogRound from "@/modules/05_placement/components/ChangePosition/DialogRound.vue";
import type {
listAppointType,
resData,
} from "@/modules/05_placement/interface/response/AppointMent";
import type { OpType } from "@/modules/05_placement/interface/response/Main";
import http from "@/plugins/http";
import config from "@/app.config";
const total = ref<number>(0);
const totalList = ref<number>(1);
const round = ref<string>("");
const idRound = ref<string>("");
const editCheck = ref<boolean>(false);
const modalRound = ref<boolean>(false);
const $q = useQuasar();
const modal = ref<boolean>(false);
const storeFn = useTransferDataStore();
const { statusText } = storeFn;
const mixin = useCounterMixin(); //
const {
showLoader,
hideLoader,
success,
messageError,
date2Thai,
dialogRemove,
} = mixin;
const router = useRouter();
const rows = ref<any[]>([]);
const rows2 = ref<any>([]);
const filterKeyword = ref<string>("");
const filterKeyword2 = ref<string>("");
const filterRef = ref<any>(null);
const optionsType = ref<OpType[]>([]);
const type = ref<string>("");
const visibleColumns = ref<string[]>(["no", "name", "createdAt", "status"]);
const pagination = ref({
sortBy: "createdAt",
descending: true,
page: 1,
rowsPerPage: 10,
});
const columns = ref<QTableProps["columns"]>([
{
name: "no",
align: "left",
label: "ลำดับ",
sortable: false,
field: "no",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "name",
align: "left",
label: "ชื่อรอบการย้ายสับเปลี่ยนตำแหน่ง",
sortable: true,
field: "name",
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: "status",
align: "left",
label: "สถานะ",
sortable: true,
field: "status",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
]);
// input
const resetFilter = () => {
filterKeyword.value = "";
filterKeyword2.value = "";
filterRef.value.focus();
fecthLists();
};
// modal
const clickClose = () => {
modal.value = false;
};
// modal
function sendToCommand() {
modal.value = true;
filterKeyword2.value = "";
// fecthTypeOption();
}
// API
async function fecthLists() {
showLoader();
rows.value = [];
await http
.get(
config.API.changePosition +
`?page=${pagination.value.page}&pageSize=${pagination.value.rowsPerPage}&searchKeyword=${filterKeyword.value}`
)
.then((res) => {
totalList.value = Math.ceil(
res.data.result.total / pagination.value.rowsPerPage
);
total.value = res.data.result.total;
rows.value = res.data.result.data;
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
hideLoader();
});
}
// dialog
function openModaledit(data: any) {
modalRound.value = true;
editCheck.value = true;
round.value = data.name;
idRound.value = data.id;
}
//
function addRound() {
modalRound.value = true;
}
//
function clickDelete(id: string) {
dialogRemove($q, () => {
showLoader();
http
.delete(config.API.changePosition + `/${id}`)
.then(() => {
success($q, "ลบข้อมูลสำเร็จ");
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
fecthLists();
hideLoader();
});
});
}
//
function personalListPage(id: string) {
router.push({
path: `/change-positions/${id}`,
});
}
function updatePagination(newPagination: any) {
pagination.value.page = 1;
pagination.value.rowsPerPage = newPagination.rowsPerPage;
}
watch(
() => pagination.value.rowsPerPage,
async () => {
await fecthLists();
}
);
onMounted(() => {
fecthLists();
});
</script>
<template>
<div class="toptitle text-dark col-12 row items-center">
รายการออกคำสงยายสบเปลยนตำแหน
</div>
<q-card flat bordered class="col-12 q-mt-sm">
<q-separator />
<div class="row q-pa-md">
<div class="col-12">
<div class="row col-12">
<q-btn
@click="addRound()"
size="14px"
flat
round
color="primary"
icon="add"
>
<q-tooltip>เพมรอบการยายสบเปลยนตำแหน</q-tooltip>
</q-btn>
<q-btn
@click="sendToCommand()"
size="14px"
flat
round
color="add"
icon="mdi-account-arrow-right"
>
<q-tooltip>งไปออกคำสงแตงต-เลอน-าย</q-tooltip>
</q-btn>
<q-space />
<q-input
class="col-xs-12 col-sm-3 col-md-2"
standout
dense
v-model="filterKeyword"
ref="filterRef"
outlined
debounce="300"
placeholder="ค้นหา"
@keyup.enter="fecthLists()"
>
<template v-slot:append>
<q-icon v-if="filterKeyword == ''" name="search" />
<q-icon
v-if="filterKeyword !== ''"
name="clear"
class="cursor-pointer"
@click="resetFilter"
/>
</template>
</q-input>
<q-select
v-model="visibleColumns"
multiple
outlined
dense
options-dense
:display-value="$q.lang.table.columns"
emit-value
map-options
:options="columns"
option-value="name"
options-cover
style="min-width: 150px"
class="col-xs-12 col-sm-3 col-md-2 q-ml-sm"
/>
</div>
<div class="col-12 q-pt-sm">
<d-table
:columns="columns"
:rows="rows"
row-key="id"
:visible-columns="visibleColumns"
:rows-per-page-options="[1, 25, 50, 100]"
@update:pagination="updatePagination"
>
<template v-slot:pagination="scope">
งหมด {{ total }} รายการ
<q-pagination
v-model="pagination.page"
active-color="primary"
color="dark"
:max="Number(totalList)"
size="sm"
boundary-links
direction-links
:max-pages="5"
@update:model-value="fecthLists"
></q-pagination>
</template>
<template v-slot:header="props">
<q-tr :props="props">
<q-th auto-width />
<q-th v-for="col in props.cols" :key="col.name" :props="props">
<span class="text-weight-medium">{{ col.label }}</span>
</q-th>
</q-tr>
</template>
<template v-slot:body="props">
<q-tr :props="props" class="cursor-pointer">
<q-td auto-width>
<q-btn
v-if="
props.row.status !== 'REPORT' &&
props.row.status !== 'DONE'
"
icon="mdi-dots-vertical"
size="12px"
color="grey-7"
flat
round
dense
>
<q-menu
transition-show="jump-down"
transition-hide="jump-up"
>
<q-list dense style="min-width: 250px">
<q-item
clickable
v-close-popup
@click="openModaledit(props.row)"
>
<q-item-section
style="min-width: 0px"
avatar
class="q-py-sm"
>
<q-icon color="edit" size="xs" name="edit" />
</q-item-section>
<q-item-section>แกไข</q-item-section>
</q-item>
<q-item
clickable
v-close-popup
@click="clickDelete(props.row.id)"
>
<q-item-section
style="min-width: 0px"
avatar
class="q-py-sm"
>
<q-tooltip>ลบขอม</q-tooltip>
<q-icon color="red" size="xs" name="mdi-delete" />
</q-item-section>
<q-item-section>ลบ</q-item-section>
</q-item>
</q-list>
</q-menu>
</q-btn>
</q-td>
<q-td
v-for="col in props.cols"
:key="col.name"
@click="personalListPage(props.row.id)"
>
<div v-if="col.name == 'no'">
{{
(pagination.page - 1) * pagination.rowsPerPage +
props.rowIndex +
1
}}
</div>
<div v-else-if="col.name == 'createdAt'">
{{
props.row.createdAt ? date2Thai(props.row.createdAt) : "-"
}}
</div>
<div v-else-if="col.name == 'status'">
{{ props.row.status ? statusText(props.row.status) : "-" }}
</div>
<div v-else>
{{ col.value ? col.value : "-" }}
</div>
</q-td>
</q-tr>
</template>
</d-table>
</div>
</div>
</div>
</q-card>
<SendToCommand
v-model:Modal="modal"
:clickClose="clickClose"
:optionsType="optionsType"
:rows2="rows2"
v-model:filterKeyword2="filterKeyword2"
v-model:type="type"
:nextPage="personalListPage"
:fecthLists="fecthLists"
/>
<DialogRound
v-model:modal="modalRound"
v-model:edit="editCheck"
v-model:round="round"
v-model:id="idRound"
:getData="fecthLists"
/>
</template>
<style scoped></style>

View file

@ -1,716 +0,0 @@
<script setup lang="ts">
import { useQuasar, QForm } from "quasar";
import { onMounted, reactive, ref, watch } from "vue";
import DialogHeader from "@/components/DialogHeader.vue";
import DialogFooter from "@/modules/05_placement/components/PersonalList/DialogFooter.vue";
import { useCounterMixin } from "@/stores/mixin";
import http from "@/plugins/http";
import config from "@/app.config";
const $q = useQuasar();
const mixin = useCounterMixin(); //
const {
date2Thai,
hideLoader,
messageError,
showLoader,
success,
dialogConfirm,
} = mixin; //
const notFound = ref<string>("ไม่พบข้อมูลที่ค้นหา");
const noData = ref<string>("ไม่พบข้อมูลผังโครงสร้าง");
const checkValidate = ref<boolean>(false);
const myFormPosition = ref<any>();
const selected = ref<string>("");
const selectedFile = ref<string>("");
const dataRespone = ref<any>();
const personal = ref<any>();
const expanded = ref<string[]>([]);
const treeData = ref<Array<any>>([]);
const placementPosition = ref<any>([]);
const search = ref<string>("");
const filterRef = ref<any>(null);
const id = ref<string>("");
const editDataStatus = ref<boolean>(false);
// Set form field
let dataForm = reactive({
personalId: "",
containDate: new Date(),
posNoId: "",
positionId: "",
positionLevelId: "",
positionLineId: "",
positionPathSideId: "",
positionTypeId: "",
});
// const fetchPublishFile = async () => {
// await http
// .get(config.API.getPublishFileHistory)
// .then((res) => {
// let data = res.data.result;
// selectedFile.value = data[0].fileName;
// })
// .catch((e) => {
// messageError($q, e);
// })
// .finally(async () => {
// hideLoader();
// });
// };
// json
// const loadTreeData = async () => {
// expanded.value = [];
// await http
// .get(`${config.s3ClusterUrl}${selectedFile.value}`)
// .then((res: any) => {
// treeData.value = res.data;
// dataRespone.value = res.data;
// // Filter objects with "name" null
// const filteredData = res.data.filter(filterByPersonIdNull);
// treeData.value = filteredData;
// })
// .catch((e: any) => {
// messageError($q, e);
// })
// .finally(() => {
// hideLoader();
// });
// };
function filterByPersonIdNull(obj: any) {
if (obj.name === null && obj.isCondition != true) {
return true;
}
if (obj.children && obj.children.length > 0) {
obj.children = obj.children.filter(filterByPersonIdNull);
return obj.children.length > 0;
}
return false;
}
// position
const fetchplacementPosition = async () => {
await http
.get(config.API.apppointmentPosition())
.then((res: any) => {
placementPosition.value = res.data.result;
})
.catch((e: any) => {
messageError($q, e);
});
};
const props = defineProps({
personalId: String,
modal: Boolean,
close: {
type: Function,
default: () => console.log("close modal"),
},
personal: Object,
});
const myFilterMethod = (node: any, filter: string) => {
const filt = filter;
return (
(node.name && node.name.indexOf(filt) > -1) ||
(node.organizationName && node.organizationName.indexOf(filt) > -1) ||
(node.positionNum && node.positionNum.indexOf(filt) > -1) ||
(node.positionName && node.positionName.indexOf(filt) > -1) ||
(node.governmentCode &&
node.governmentCode.toString().indexOf(filt) > -1) ||
(node.agency && node.agency.indexOf(filt) > -1) ||
(node.government && node.government.indexOf(filt) > -1) ||
(node.department && node.department.indexOf(filt) > -1) ||
(node.pile && node.pile.indexOf(filt) > -1) ||
(node.organizationShortName &&
node.organizationShortName.indexOf(filt) > -1) ||
(node.positionSideName && node.positionSideName.indexOf(filt) > -1) ||
(node.executivePosition && node.executivePosition.indexOf(filt) > -1) ||
(node.executivePositionSide &&
node.executivePositionSide.indexOf(filt) > -1) ||
(node.positionLevel && node.positionLevel.indexOf(filt) > -1)
);
};
const validateData = async () => {
checkValidate.value = true;
await myFormPosition.value.validate().then((result: boolean) => {
if (result == false) {
checkValidate.value = false;
}
});
};
const saveAppoint = async () => {
myFormPosition.value.validate().then(async (result: boolean) => {
if (props.personalId !== undefined) {
id.value = props.personalId.toString();
}
if (result) {
const dataAppoint = await {
recruitDate: dataForm.containDate,
posNoId: dataForm.posNoId,
positionId: dataForm.positionId,
positionLevelId: dataForm.positionLevelId,
positionLineId: dataForm.positionLineId,
positionPathSideId: dataForm.positionPathSideId,
positionTypeId: dataForm.positionTypeId,
};
showLoader();
await http
.put(config.API.appointmentPosition(id.value), dataAppoint)
.then((res) => {
success($q, "บันทึกสำเร็จ");
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await closeAndClear();
// await fetchPublishFile();
// await loadTreeData();
await fetchplacementPosition();
hideLoader();
});
}
});
};
const closeModal = () => {
if (editDataStatus.value == true) {
dialogConfirm(
$q,
async () => {
editDataStatus.value = false;
await closeAndClear();
},
`ข้อมูลมีการแก้ไข`,
`ยืนยันที่จะปิดโดยไม่บันทึกใช่หรือไม่?`
);
} else {
closeAndClear();
}
};
const closeAndClear = async () => {
await props.close();
editDataStatus.value = false;
selected.value = "";
dataForm.personalId = "";
dataForm.containDate = new Date();
dataForm.posNoId = "";
dataForm.positionId = "";
dataForm.positionLevelId = "";
dataForm.positionLineId = "";
dataForm.positionPathSideId = "";
dataForm.positionTypeId = "";
};
//
const posNoOptions = ref<Object[]>([
{
label: "",
value: "",
},
]);
//
const positionOptions = ref<Object[]>([
{
label: "",
value: "",
},
]);
// /
const positionPathSideOptions = ref<Object[]>([
{
label: "",
value: "",
},
]);
//
const positionTypeOptions = ref<Object[]>([
{
label: "",
value: "",
},
]);
//
const positionLineOptions = ref<Object[]>([
{
label: "",
value: "",
},
]);
//
const positionLevelOptions = ref<Object[]>([
{
label: "",
value: "",
},
]);
const selectedPosition = async (data: any) => {
if (data.name == null && selected.value != data.keyId) {
editDataStatus.value = true;
selected.value = data.keyId;
// posNo Options
posNoOptions.value = [
{
label: data.positionNum,
value: data.positionNumId,
},
];
dataForm.posNoId = data.positionNumId;
// position Options
positionOptions.value = [
{
label: data.positionName,
value: data.positionNameId,
},
];
dataForm.positionId = data.positionNameId;
// positionPathSide Options
let positionPathSideArr: any = [];
if (data.positionSideNameObj && data.positionSideNameObj != null) {
data.positionSideNameObj.map((x: any) => {
positionPathSideArr.push({
label: x.Name,
value: x.Id,
});
});
positionPathSideOptions.value = positionPathSideArr;
dataForm.positionPathSideId =
positionPathSideArr.length > 1 || positionPathSideArr.length == 0
? ""
: positionPathSideArr[0].value;
}
// positionType Options
positionTypeOptions.value = [
{
label: data.positionType,
value: data.positionTypeId,
},
];
dataForm.positionTypeId = data.positionTypeId;
// positionLine Options
positionLineOptions.value = [
{
label: data.positionLine,
value: data.positionLineId,
},
];
dataForm.positionLineId = data.positionLineId;
// positionLevel Options
let positionLevelsArr: any = [];
if (data.positionLevelObj != null) {
data.positionLevelObj.map((x: any) => {
positionLevelsArr.push({
label: x.Name,
value: x.Id,
});
});
positionLevelOptions.value = positionLevelsArr;
dataForm.positionLevelId =
positionLevelsArr.length > 1 || positionLevelsArr.length == 0
? ""
: positionLevelsArr[0].value;
dataForm.positionLevelId = data.positionLevelObj[0].Id;
}
} else if (selected.value == data.keyId) {
selected.value = "";
dataForm.posNoId = "";
dataForm.positionId = "";
dataForm.positionLevelId = "";
dataForm.positionLineId = "";
dataForm.positionPathSideId = "";
dataForm.positionTypeId = "";
}
};
const checkPosition = (val: string) => {
const num = placementPosition.value.findIndex((e: string) => e === val);
return num;
};
watch(props, () => {
expanded.value = [];
const dataPersonal = props.personal;
if (dataPersonal) {
dataPersonal.map((data: any) => {
personal.value = data;
});
}
if (personal.value) {
let findData: any = null;
dataRespone.value.map((x: any) => {
findData = findByPerson(x);
if (findData != null) {
selectedPosition(findData);
for (let i = 3; i <= findData.keyId.length; i += 2) {
expanded.value.push(findData.keyId.slice(0, i));
}
}
});
}
});
function findByPerson(element: any): any {
if (
element.positionNumId &&
element.positionLineId === personal.value.positionLineId &&
element.positionTypeId === personal.value.positionTypeId &&
element.positionNumId === personal.value.posNoId &&
(element.positionLevelObj === null ||
element.positionLevelObj[0].Id === personal.value.positionLevelId)
) {
return element;
} else if (element.children) {
var i;
var result = null;
for (i = 0; result == null && i < element.children.length; i++) {
result = findByPerson(element.children[i]);
}
return result;
}
return null;
}
onMounted(async () => {
// await fetchPublishFile();
// await loadTreeData();
// await fetchplacementPosition();
});
</script>
<template>
<q-dialog v-model="props.modal" persistent>
<q-card style="width: 900px; max-width: 80vw">
<q-form ref="myFormPosition">
<DialogHeader
:tittle="'เลือกหน่วยงานที่แต่งตั้ง - เลื่อน'"
:close="closeModal"
/>
<q-separator />
<q-card-section class="q-pa-sm bg-grey-1">
<div class="row col-12 q-col-gutter-sm">
<div class="col-xs-12 col-sm-7 row">
<q-card flat bordered class="fit q-pa-sm">
<q-scroll-area visible style="height: 70vh">
<q-input
outlined
dense
ref="filterRef"
v-model="search"
placeholder="ค้นหา"
class="q-mb-sm"
>
<template v-slot:append>
<q-icon name="mdi-magnify" />
</template>
</q-input>
<div class="q-pa-sm q-gutter-sm">
<q-tree
no-transition
dense
:nodes="treeData"
node-key="keyId"
:filter="search"
:no-results-label="notFound"
:no-nodes-label="noData"
:filter-method="myFilterMethod"
v-model:expanded="expanded"
>
<template v-slot:header-organization="prop">
<div class="col">
<div
class="row items-center q-px-xs q-pt-xs q-gutter-sm"
>
<!--แสดงชอแผนก มพวหนา คลกแลวกาง/ Tree-->
<div class="text-weight-medium">
{{ prop.node.organizationName }}
</div>
<q-badge
v-if="prop.node.totalPositionVacant > 0"
rounded
color="red"
outline
:label="prop.node.totalPositionVacant"
/>
<q-space />
</div>
<div class="col items-center q-px-xs q-pt-xs">
<div class="text-weight-medium text-grey-7">
{{ prop.node.governmentCode }}
{{ prop.node.organizationShortName }}
</div>
</div>
</div>
</template>
<template v-slot:header-person="prop">
<q-item
clickable
:active="selected == prop.node.keyId"
@click="selectedPosition(prop.node)"
:disable="
prop.node.name != null ||
checkPosition(prop.node.positionNumId) != -1
"
active-class="my-list-link text-primary text-weight-medium"
class="row items-center text-dark q-py-xs q-pl-sm rounded-borders my-list"
>
<img
v-if="
prop.node.avatar == '' ||
prop.node.avatar ==
'https://cdn.quasar.dev/img/boy-avatar.png'
"
src="@/assets/avatar_user.jpg"
class="col-xs-1 col-sm-2"
style="
width: 28px;
height: 28px;
border-radius: 50%;
"
/>
<img
v-else
:src="prop.node.avatar"
class="col-xs-1 col-sm-2"
style="
width: 28px;
height: 28px;
border-radius: 50%;
"
/>
<!--=====ตำแหนงวาง แดง=====-->
<div
v-if="prop.node.name == null"
class="q-px-sm text-weight-medium text-red"
>
าง
</div>
<!--=====วหน เขยว=====-->
<div v-else-if="prop.node.positionLeaderFlag">
<div
class="q-px-sm text-weight-medium text-primary"
>
{{ prop.node.name }}
</div>
</div>
<!--=====กนอง ปกต=====-->
<div v-else>
<div class="q-px-sm text-weight-medium">
{{ prop.node.name }}
</div>
</div>
<!--อทายชอคน แสดงสปกต-->
<div class="q-pr-sm">
{{ prop.node.positionName }}
</div>
<div class="q-pr-sm">
{{ prop.node.positionNum }}
</div>
<div class="q-pr-sm">
{{ prop.node.positionLevel }}
</div>
<q-icon
v-if="prop.node.positionLeaderFlag"
class="q-mr-sm"
size="15px"
color="primary"
name="mdi-bookmark"
></q-icon>
<q-space />
</q-item>
</template>
</q-tree>
</div>
</q-scroll-area>
</q-card>
</div>
<div class="col-xs-12 col-sm-5">
<q-card flat bordered class="fit q-pa-sm">
<q-scroll-area visible style="height: 70vh">
<div class="row col-12 q-col-gutter-xs">
<div class="col-xs-12 col-sm-12 col-md-12"></div>
<div class="col-xs-12 col-sm-12 col-md-12">
<datepicker
menu-class-name="modalfix"
v-model="dataForm.containDate"
:locale="'th'"
autoApply
:enableTimePicker="false"
week-start="0"
>
<template #year="{ year }">{{ year + 543 }}</template>
<template #year-overlay-value="{ value }">{{
parseInt(value + 543)
}}</template>
<template #trigger>
<q-input
class="full-width inputgreen cursor-pointer"
outlined
dense
:model-value="
date2Thai(new Date(dataForm.containDate))
"
:rules="[ (val: string) =>!!val ||`${'วันที่รายงานตัว'}`]"
:label="`${'วันที่รายงานตัว'}`"
hide-bottom-space
>
<template v-slot:prepend>
<q-icon
name="event"
class="cursor-pointer"
style="color: var(--q-primary)"
>
</q-icon>
</template>
</q-input>
</template>
</datepicker>
</div>
<q-space />
<div class="col-xs-12 col-sm-12 col-md-12">
<q-select
class="full-width inputgreen cursor-pointer custom-input"
outlined
standout
dense
hide-bottom-space
lazy-rules
:options="posNoOptions"
v-model="dataForm.posNoId"
:label="`${'ตำแหน่งเลขที่'}`"
map-options
/>
</div>
<div class="col-xs-12 col-sm-12 col-md-12">
<q-select
outlined
class="full-width inputgreen cursor-pointer custom-input"
standout
dense
hide-bottom-space
lazy-rules
:options="positionOptions"
v-model="dataForm.positionId"
:label="`${'ตำแหน่ง'}`"
map-options
/>
</div>
<div class="col-xs-12 col-sm-12 col-md-12">
<q-select
outlined
class="full-width inputgreen cursor-pointer custom-input"
standout
dense
hide-bottom-space
lazy-rules
emit-value
:options="positionPathSideOptions"
v-model="dataForm.positionPathSideId"
:label="`${'ด้าน/สาขา'}`"
map-options
/>
</div>
<div class="col-xs-12 col-sm-12 col-md-12">
<q-select
outlined
class="full-width inputgreen cursor-pointer custom-input"
standout
dense
hide-bottom-space
lazy-rules
:options="positionTypeOptions"
v-model="dataForm.positionTypeId"
:label="`${'ประเภทตำแหน่ง'}`"
map-options
/>
</div>
<div class="col-xs-12 col-sm-12 col-md-12">
<q-select
outlined
class="full-width inputgreen cursor-pointer custom-input"
standout
dense
hide-bottom-space
lazy-rules
:options="positionLineOptions"
v-model="dataForm.positionLineId"
:label="`${'สายงาน'}`"
map-options
/>
</div>
<div class="col-xs-12 col-sm-12 col-md-12">
<q-select
outlined
class="full-width inputgreen cursor-pointer custom-input"
standout
dense
lazy-rules
:options="positionLevelOptions"
v-model="dataForm.positionLevelId"
:label="`${'ระดับตำแหน่ง'}`"
hide-bottom-space
:rules="[(val: string) => !!val || `${'กรุณาเลือกระดับตำแหน่ง'}`]"
emit-value
map-options
/>
</div>
</div>
</q-scroll-area>
</q-card>
</div>
</div>
</q-card-section>
<q-separator />
<DialogFooter
:editvisible="true"
:validate="validateData"
:save="saveAppoint"
v-model:modalEdit="editDataStatus"
/>
</q-form>
</q-card>
</q-dialog>
</template>
<style scoped lang="scss">
.q-tree__node-header {
padding: 0px;
margin-top: 0px;
border-radius: 4px;
outline: 0;
}
.my-list-link {
color: rgb(118, 168, 222);
border-radius: 5px;
background: #a3d3fb48 !important;
font-weight: 600;
border: 1px solid rgba(175, 185, 196, 0.217);
}
</style>

View file

@ -1,406 +0,0 @@
<script setup lang="ts">
import { onMounted, ref, reactive } from "vue";
import { useQuasar } from "quasar";
import { useRoute, useRouter } from "vue-router";
import { useCounterMixin } from "@/stores/mixin";
import type { ResponseTitle } from "@/modules/05_placement/interface/response/Receive";
import type { DataProfile } from "@/modules/05_placement/interface/response/AppointMent";
import type { QForm } from "quasar";
import http from "@/plugins/http";
import config from "@/app.config";
import CardProfile from "@/components/CardProfile.vue";
const modalPersonal = ref<boolean>(false);
const personId = ref<string>("");
const $q = useQuasar();
const route = useRoute();
const router = useRouter();
const mixin = useCounterMixin();
const dataProfile = ref<DataProfile>();
const myForm = ref<QForm | null>(null);
const edit = ref<boolean>(false);
const profileId = ref<string>("");
const organizationPositionOld = ref<string>("");
const positionTypeOld = ref<string>("");
const positionLevelOld = ref<string>("");
const posNo = ref<string>("");
const salary = ref<number>(0);
const educationOld = ref<string>("");
const reason = ref<string>("");
const date = ref<Date | null>(null);
const status = ref<string>("");
const avatar = ref<string>("");
const paramsId = route.params.id;
const {
date2Thai,
messageError,
showLoader,
hideLoader,
success,
dialogConfirm,
findOrgName,
} = mixin;
const title = ref<ResponseTitle>({
fullname: "",
organizationPositionOld: "",
positionLevelOld: "",
positionTypeOld: "",
});
// id
async function getData() {
showLoader();
await http
.get(config.API.changePositionByIdProfile + `/${paramsId.toString()}`)
.then((res) => {
dataProfile.value = res.data.result as unknown as DataProfile;
const data = res.data.result;
profileId.value = data.profileId;
title.value.fullname = `${data.prefix}${data.firstName ?? "-"} ${
data.lastName ?? "-"
}`;
title.value.organizationPositionOld = data.organizationPositionOld ?? "-";
title.value.positionLevelOld = data.positionLevelOld ?? "-";
title.value.positionTypeOld = data.positionTypeOld ?? "-";
(status.value = data.status),
(educationOld.value = data.educationOld ?? "-");
organizationPositionOld.value = data.organizationPositionOld;
positionTypeOld.value = data.posTypeNameOld;
positionLevelOld.value = data.posLevelNameOld;
posNo.value = data.posMasterNo;
salary.value = data.amountOld ?? 0;
reason.value = data.reason;
date.value = data.dateCurrent;
avatar.value = data.avatar ?? "";
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
hideLoader();
});
}
//
function putAppointment() {
dialogConfirm(
$q,
() => {
let data = {
educationOld: educationOld.value,
organizationPositionOld: organizationPositionOld.value,
positionTypeOld: positionTypeOld.value,
positionLevelOld: positionLevelOld.value,
posMasterNoOld: posNo.value,
amountOld: salary.value.toString().replace(/,/g, ""),
reason: reason.value,
dateCurrent: date.value,
};
showLoader();
http;
http
.put(
config.API.changePositionByIdProfile + `/${paramsId.toString()}`,
data
)
.then(() => {
success($q, "บันทึกข้อมูลสำเร็จ");
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
getData();
edit.value = false;
});
},
"ต้องการแก้ไขข้อมูลหรือไม่?",
"แก้ไขข้อมูลเพื่อลงบัญชีแนบท้าย"
);
}
const cancel = () => {
edit.value = false;
getData();
myForm.value?.resetValidation();
};
const getClass = (val: boolean) => {
return {
"full-width inputgreen cursor-pointer": val,
"full-width cursor-pointer": !val,
};
};
function onclickViewinfo(id: string) {
modalPersonal.value = true;
personId.value = id;
}
function updatemodalPersonal(modal: boolean) {
modalPersonal.value = modal;
}
onMounted(async () => {
await getData();
});
</script>
<template>
<div class="toptitle text-dark col-12 row items-center">
<q-btn
icon="mdi-arrow-left"
unelevated
round
dense
flat
color="primary"
class="q-mr-sm"
@click="router.go(-1)"
/>
รายละเอยดผายสบเปลยนตำแหน {{ title.fullname }}
</div>
<CardProfile :data="dataProfile as DataProfile" />
<q-card bordered class="row col-12 text-dark q-mt-sm">
<q-form
greedy
@submit.prevent
@validation-success="putAppointment"
ref="myForm"
class="full-width"
>
<div class="bg-grey-1 q-pa-sm col-12 row items-center text-primary">
<div class="q-pl-sm text-weight-bold text-dark">
แกไขขอมลเพอลงบญชแนบทาย
</div>
<q-space />
<div v-if="status !== 'DONE' && status !== 'REPORT'">
<div class="q-gutter-sm" v-if="!edit">
<q-btn
outline
color="primary"
dense
icon-right="mdi-file-edit-outline"
class="q-px-sm"
label="แก้ไข"
style="width: 80px"
@click="edit = !edit"
/>
</div>
<div class="q-gutter-sm" v-else>
<q-btn
outline
type="submit"
color="public"
dense
class="q-px-sm"
label="บันทึก"
style="width: 80px"
/>
<q-btn
outline
color="red"
dense
class="q-px-sm"
label="ยกเลิก"
style="width: 80px"
@click="cancel()"
/>
</div>
</div>
</div>
<div class="col-12"><q-separator /></div>
<div class="row col-12 q-pa-md">
<div class="col-12">
<div class="text-weight-bold">การศกษา</div>
</div>
<div class="col-12">
<q-input
:class="getClass(edit)"
:outlined="edit"
dense
lazy-rules
:readonly="!edit"
:borderless="!edit"
v-model="educationOld"
:rules="[(val) => !!val || `${'กรุณากรอกวุฒิการศึกษา'}`]"
hide-bottom-space
:label="`${'วุฒิการศึกษา'}`"
type="text"
/>
</div>
</div>
<div class="row col-12 q-pa-md">
<div class="col-12 row bg-white q-col-gutter-md">
<div class="col-xs-12 row q-pa-md items-center">
<div class="col-12">
<div class="text-weight-bold">ตำแหน/งกดเด</div>
</div>
<div class="col-12">
<q-input
:class="getClass(edit)"
:outlined="edit"
dense
lazy-rules
:readonly="!edit"
:borderless="!edit"
v-model="organizationPositionOld"
:rules="[(val) => !!val || `${'กรุณากรอกตำแหน่ง/สังกัด'}`]"
hide-bottom-space
:label="`${'ตำแหน่ง/สังกัด'}`"
type="textarea"
/>
</div>
</div>
<div class="col-xs-6 col-sm-3 row">
<div class="col-12">
<q-input
:class="getClass(edit)"
:outlined="edit"
dense
lazy-rules
:readonly="!edit"
:borderless="!edit"
v-model="positionTypeOld"
:rules="[(val) => !!val || `${'กรุณากรอกตำแหน่งประเภท'}`]"
hide-bottom-space
:label="`${'ตำแหน่งประเภท'}`"
/>
</div>
</div>
<div class="col-xs-6 col-sm-3 row">
<div class="col-12">
<q-input
:class="getClass(edit)"
:outlined="edit"
dense
lazy-rules
:readonly="!edit"
:borderless="!edit"
v-model="positionLevelOld"
:rules="[(val) => !!val || `${'กรุณากรอกระดับตำแหน่ง'}`]"
hide-bottom-space
:label="`${'ระดับตำแหน่ง'}`"
/>
</div>
</div>
<div class="col-xs-6 col-sm-3 row">
<div class="col-12">
<q-input
:class="getClass(edit)"
:outlined="edit"
dense
lazy-rules
:readonly="!edit"
:borderless="!edit"
v-model="posNo"
:rules="[(val) => !!val || `${'กรุณากรอกเลขที่'}`]"
hide-bottom-space
:label="`${'เลขที่'}`"
/>
</div>
</div>
<div class="col-xs-6 col-sm-3 row">
<div class="col-12">
<q-input
v-model="salary"
:outlined="edit"
dense
:readonly="!edit"
hide-bottom-space
:borderless="!edit"
:label="`${'เงินเดือน'}`"
:rules="[(val:number) => !!val || `${'กรุณากรอกเงินเดือน'}`]"
lazy-rules
mask="###,###,###,###"
reverse-fill-mask
:class="getClass(edit)"
/>
</div>
</div>
<div class="col-12"><q-separator /></div>
<div class="col-xs-6 col-sm-6 row items-center">
<div class="col-12">
<datepicker
menu-class-name="modalfix"
:readonly="!edit"
v-model="date"
:locale="'th'"
autoApply
:enableTimePicker="false"
week-start="0"
>
<template #year="{ year }">{{ year + 543 }}</template>
<template #year-overlay-value="{ value }">{{
parseInt(value + 543)
}}</template>
<template #trigger>
<q-input
:class="getClass(edit)"
:outlined="edit"
dense
:borderless="!edit"
:readonly="!edit"
:model-value="date !== null ? date2Thai(date) : null"
:rules="[(val) => !!val || `${'กรุณาเลือกตั้งแต่วัน'}`]"
hide-bottom-space
:label="`${'ดำรงตำแหน่งในระดับปัจจุบันเมื่อ'}`"
>
<template v-slot:prepend>
<q-icon
name="event"
class="cursor-pointer"
:style="
edit
? 'color: var(--q-primary)'
: 'color: var(--q-grey)'
"
>
</q-icon>
</template>
</q-input>
</template>
</datepicker>
</div>
</div>
<div class="col-12">
<q-input
:class="getClass(edit)"
:outlined="edit"
dense
lazy-rules
:readonly="!edit"
:borderless="!edit"
v-model="reason"
hide-bottom-space
:label="`${'หมายเหตุ '}`"
type="textarea"
/>
</div>
</div>
</div>
</q-form>
</q-card>
</template>
<style lang="scss" scope>
.q-img {
border-radius: 5px;
height: 70px;
}
.text-top {
color: gray;
font-weight: 400;
padding-bottom: 3px;
}
.text-detail {
font-weight: 500;
}
</style>

View file

@ -1,506 +0,0 @@
<script setup lang="ts">
import { ref, onMounted, watch } from "vue";
import type { QTableProps } from "quasar";
import { useQuasar } from "quasar";
import { useRoute, useRouter } from "vue-router";
import { useCounterMixin } from "@/stores/mixin";
import { useTransferDataStore } from "@/modules/05_placement/store";
import type { OpType } from "@/modules/05_placement/interface/response/Main";
import http from "@/plugins/http";
import config from "@/app.config";
import DialogOrgSelect from "@/components/Dialogs/DialogOrgSelect.vue";
import DialogEvalute from "@/modules/05_placement/components/ChangePosition/DialogChange.vue";
const router = useRouter();
const route = useRoute();
const id = ref<string>(route.params.id ? route.params.id.toString() : "");
const total = ref<number>(0);
const totalList = ref<number>(1);
const modalDialog = ref<boolean>(false);
const posType = ref<string>("");
const posLevel = ref<string>("");
const position = ref<string>("");
const typeModal = ref<string | null>(null);
const dataRows = ref<any[]>([]);
const $q = useQuasar();
const modal = ref<boolean>(false);
const storeFn = useTransferDataStore();
const { statusText } = storeFn;
const mixin = useCounterMixin(); //
const {
showLoader,
hideLoader,
success,
messageError,
date2Thai,
dialogRemove,
} = mixin;
const rows = ref<any[]>([]);
const modalTree = ref<boolean>(false);
const personalId = ref<string>("");
const filterKeyword = ref<string>("");
const filterKeyword2 = ref<string>("");
const filterRef = ref<any>(null);
const optionsType = ref<OpType[]>([]);
const type = ref<string>("");
const visibleColumns = ref<string[]>([
"no",
"citizenId",
"fullname",
"organizationName",
"birthDate",
"lastUpdatedAt",
"status",
]);
const pagination = ref({
sortBy: "createdAt",
descending: true,
page: 1,
rowsPerPage: 10,
});
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: "ชื่อ-นามสกุล",
sortable: true,
field: "fullname",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "organizationName",
align: "left",
label: "หน่วยงานที่รับย้าย",
sortable: true,
field: "organizationName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "birthDate",
align: "left",
label: "วัน/เดือน/ปี เกิด",
sortable: true,
field: "birthDate",
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: "status",
align: "left",
label: "สถานะ",
sortable: true,
field: "status",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
]);
// input
const resetFilter = () => {
filterKeyword.value = "";
filterKeyword2.value = "";
filterRef.value.focus();
fecthLists();
};
// modal
const clickClose = () => {
modal.value = false;
};
//
const addPerson = () => {
modalDialog.value = true;
};
// API
const fecthLists = async () => {
showLoader();
await http
.get(
config.API.changePositionById +
`/${id.value}?page=${pagination.value.page}&pageSize=${pagination.value.rowsPerPage}&searchKeyword=${filterKeyword.value}`
)
.then(async (res) => {
let response = await res.data.result;
totalList.value = Math.ceil(
res.data.result.total / pagination.value.rowsPerPage
);
total.value = response.total;
rows.value = response.data;
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
hideLoader();
});
};
//
const openModalTree = (data: any, type: string) => {
personalId.value = data.id;
modalTree.value = true;
typeModal.value = type;
dataRows.value = data;
posType.value = data.posTypeOldId;
posLevel.value = data.posLevelOldId;
position.value = data.positionOld;
};
//
const clickDelete = (id: string) => {
dialogRemove($q, () => {
showLoader();
http
.delete(config.API.changePositionByIdProfile + `/${id}`)
.then(() => {
success($q, "ลบข้อมูลสำเร็จ");
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
fecthLists();
hideLoader();
});
});
};
//
const detailPage = (id: string) => {
router.push({
path: `/change-positions/personal/${id}`,
});
};
function onSave(data: any) {
showLoader();
http
.put(
config.API.changePositionByIdProfile + `/position/${personalId.value}`,
{
node: data.node,
nodeId: data.nodeId,
posmasterId: data.posmasterId,
posMasterNo: data.posMasterNo,
positionId: data.positionId,
orgRevisionId: data.orgRevisionId,
position: data.positionName,
positionField: data.positionField,
posTypeId: data.posTypeId,
posTypeName: data.posTypeName,
posLevelId: data.posLevelId,
posLevelName: data.posLevelName,
}
)
.then((res) => {
modalTree.value = false;
success($q, "บันทึกสำเร็จ");
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
fecthLists();
hideLoader();
});
}
function updatePagination(newPagination: any) {
pagination.value.page = 1;
pagination.value.rowsPerPage = newPagination.rowsPerPage;
}
watch(
() => pagination.value.rowsPerPage,
async () => {
await fecthLists();
}
);
onMounted(() => {
fecthLists();
});
</script>
<template>
<div class="toptitle text-dark col-12 row items-center">
<q-btn
icon="mdi-arrow-left"
unelevated
round
dense
flat
color="primary"
class="q-mr-sm"
@click="router.push(`/change-positions`)"
/>
รายชอผายสบเปลยนตำแหน
</div>
<q-card flat bordered class="col-12 q-mt-sm">
<q-separator />
<div class="row q-pa-md">
<div class="col-12">
<div class="row col-12">
<q-btn
@click="addPerson()"
size="14px"
flat
round
color="primary"
icon="add"
>
<q-tooltip>เพมรายชอเพอยายสบเปลยนตำแหน</q-tooltip>
</q-btn>
<q-space />
<q-input
class="col-xs-12 col-sm-3 col-md-2"
standout
dense
v-model="filterKeyword"
ref="filterRef"
outlined
debounce="300"
placeholder="ค้นหา"
@keyup.enter="fecthLists()"
>
<template v-slot:append>
<q-icon v-if="filterKeyword == ''" name="search" />
<q-icon
v-if="filterKeyword !== ''"
name="clear"
class="cursor-pointer"
@click="resetFilter"
/>
</template>
</q-input>
<q-select
v-model="visibleColumns"
multiple
outlined
dense
options-dense
:display-value="$q.lang.table.columns"
emit-value
map-options
:options="columns"
option-value="name"
options-cover
style="min-width: 150px"
class="col-xs-12 col-sm-3 col-md-2 q-ml-sm"
/>
</div>
<div class="col-12 q-pt-sm">
<d-table
:columns="columns"
:rows="rows"
row-key="id"
:visible-columns="visibleColumns"
:rows-per-page-options="[1, 25, 50, 100]"
@update:pagination="updatePagination"
>
<template v-slot:pagination="scope">
งหมด {{ total }} รายการ
<q-pagination
v-model="pagination.page"
active-color="primary"
color="dark"
:max="Number(totalList)"
size="sm"
boundary-links
direction-links
:max-pages="5"
@update:model-value="fecthLists"
></q-pagination>
</template>
<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"
@click="detailPage(props.row.id)"
>
<div v-if="col.name == 'no'">
{{
(pagination.page - 1) * pagination.rowsPerPage +
props.rowIndex +
1
}}
</div>
<div v-else-if="col.name == 'fullname'">
{{
props.row.firstName
? `${props.row.prefix ?? ""}${
props.row.firstName ?? ""
} ${props.row.lastName ?? ""}`
: "-"
}}
</div>
<div v-else-if="col.name == 'status'">
{{ props.row.status ? statusText(props.row.status) : "-" }}
</div>
<div v-else-if="col.name == 'birthDate'">
{{
props.row.birthDate ? date2Thai(props.row.birthDate) : "-"
}}
</div>
<div v-else-if="col.name == 'organizationName'">
<div class="col-4">
<div class="text-weight-medium">
{{ props.row.root !== null ? props.row.root : "-" }}
{{
props.row.rootShortName !== null
? `(${props.row.rootShortName})`
: ""
}}
</div>
<div class="text-weight-light">
{{ props.row.root ? props.row.root : "" }}
{{
props.row.rootShortName
? `(${props.row.rootShortName}${props.row.posMasterNo})`
: ""
}}
</div>
</div>
</div>
<div v-else-if="col.name == 'lastUpdatedAt'">
{{
props.row.lastUpdatedAt
? date2Thai(props.row.lastUpdatedAt)
: "-"
}}
</div>
<div v-else>
{{ col.value ? col.value : "-" }}
</div>
</q-td>
<q-td auto-width>
<q-btn
v-if="
props.row.status !== 'REPORT' &&
props.row.status !== 'DONE'
"
icon="mdi-dots-vertical"
size="12px"
color="grey-7"
flat
round
dense
>
<q-menu
transition-show="jump-down"
transition-hide="jump-up"
>
<q-list dense style="min-width: 250px">
<q-item
clickable
v-close-popup
@click="openModalTree(props.row, 'MOVE')"
>
<q-item-section
style="min-width: 0px"
avatar
class="q-py-sm"
>
<q-icon
color="primary"
size="xs"
name="mdi-bookmark-outline"
/>
</q-item-section>
<q-item-section
>เลอกหนวยงานทบยาย</q-item-section
>
</q-item>
<q-item
clickable
v-close-popup
@click="clickDelete(props.row.id)"
>
<q-item-section
style="min-width: 0px"
avatar
class="q-py-sm"
>
<q-tooltip>ลบขอม</q-tooltip>
<q-icon color="red" size="xs" name="mdi-delete" />
</q-item-section>
<q-item-section>ลบ</q-item-section>
</q-item>
</q-list>
</q-menu>
</q-btn>
</q-td>
</q-tr>
</template>
</d-table>
</div>
</div>
</div>
</q-card>
<DialogOrgSelect
:title="`เลือกหน่วยงานที่รับย้าย`"
v-model:modal="modalTree"
v-model:type="typeModal"
:posType="posType"
:posLevel="posLevel"
:position="position"
:dataRows="dataRows"
:onSubmit="onSave"
/>
<DialogEvalute v-model:modal="modalDialog" :getData="fecthLists" />
</template>
<style scoped lang="scss"></style>

View file

@ -1,301 +0,0 @@
<script setup lang="ts">
import { ref, computed, watchEffect } from "vue";
import { useQuasar } from "quasar";
import { useCounterMixin } from "@/stores/mixin";
import type { QTableProps } from "quasar";
import type { UserDataNew } from "@/modules/05_placement/interface/response/AppointMent";
import DialogHeader from "@/components/DialogHeader.vue";
import { useTransferDataStore } from "@/modules/05_placement/store";
import http from "@/plugins/http";
import config from "@/app.config";
const storeFn = useTransferDataStore();
const { statusText } = storeFn;
const mixin = useCounterMixin();
const {
showLoader,
success,
messageError,
dialogConfirm,
hideLoader,
date2Thai,
} = mixin;
const $q = useQuasar();
const selected = ref<[]>([]);
const checkSelected = computed(() => {
if (selected.value.length === 0) {
return true;
}
});
const props = defineProps({
Modal: Boolean,
clickClose: Function,
fecthlistappointment: Function,
nextPage: Function,
optionsType: Array,
rows2: Array,
filterKeyword2: String,
type: String,
});
const visibleColumns2 = ref<string[]>(["no", "name", "createdAt"]);
const columns2 = ref<QTableProps["columns"]>([
{
name: "no",
align: "left",
label: "ลำดับ",
sortable: false,
field: "no",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "name",
align: "left",
label: "ชื่อรอบการย้ายสับเปลี่ยนตำแหน่ง",
sortable: true,
field: "name",
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",
},
]);
const pageNext = (item: object) => {
props.nextPage?.(item);
};
const emit = defineEmits([
"update:filterKeyword2",
"update:type",
"update:selected",
]);
const updateInput = (value: any) => {
emit("update:filterKeyword2", value);
};
// const updateInputType = (value: string) => {
// emit("update:type", value);
// };
//
const Reset = () => {
emit("update:filterKeyword2", "");
};
//
const sendToCommand = () => {
dialogConfirm($q, async () => {
let pId: string[] = [];
let Type = props.type as string;
selected.value.forEach((e: UserDataNew) => {
pId.push(e.id);
});
let data = {
id: pId,
};
showLoader();
await http
.put(config.API.apppointmentReport(Type), data)
.then((res) => {
success($q, "บันทึกสำเร็จ");
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
hideLoader();
props.fecthlistappointment?.();
selected.value = [];
props.clickClose?.();
});
});
};
watchEffect(() => {
if (props.Modal === true) {
selected.value = [];
}
});
</script>
<template>
<q-dialog v-model="props.Modal">
<q-card style="width: 1200px; max-width: 80vw">
<DialogHeader :tittle="'ส่งไปออกคำสั่ง'" :close="clickClose" />
<q-separator />
<q-card-section>
<div class="row justify-between">
<div class="col-5">
<!-- <q-toolbar style="padding: 0">
<q-select
outlined
dense
:model-value="type"
@update:model-value="updateInputType"
:options="optionsType"
label="คำสั่งแต่งตั่ง-เลื่อน-ย้าย"
style="width: 400px; max-width: auto"
emit-value
map-options
option-label="name"
option-value="id"
/>
</q-toolbar> -->
</div>
<div class="col-5">
<q-toolbar style="padding: 0">
<q-input
borderless
outlined
dense
debounce="300"
:model-value="filterKeyword2"
@update:model-value="updateInput"
placeholder="ค้นหา"
style="width: 850px; max-width: auto"
>
<template v-slot:append>
<q-icon v-if="filterKeyword2 == ''" name="search" />
<q-icon
v-if="filterKeyword2 !== ''"
name="clear"
class="cursor-pointer"
@click="Reset"
/>
</template>
</q-input>
<q-select
v-model="visibleColumns2"
multiple
outlined
dense
options-dense
:display-value="$q.lang.table.columns"
emit-value
map-options
:options="columns2"
option-value="name"
options-cover
style="min-width: 150px"
class="gt-xs q-ml-sm"
/>
</q-toolbar>
</div>
</div>
<d-table
:columns="columns2"
:rows="rows2"
:filter="filterKeyword2"
row-key="profileId"
flat
:visible-columns="visibleColumns2"
selection="multiple"
v-model:selected="selected"
>
<template v-slot:header-selection="scope">
<q-checkbox
keep-color
color="primary"
dense
v-model="scope.selected"
/>
</template>
<template v-slot:body="props">
<q-tr :props="props" class="cursor-pointer">
<q-td auto-width>
<q-checkbox
keep-color
color="primary"
dense
v-model="props.selected"
/>
</q-td>
<q-td
v-for="col in props.cols"
:key="col.name"
:props="props"
@click="pageNext(props.row)"
>
<div v-if="col.name == 'no'">
{{ props.rowIndex + 1 }}
</div>
<div v-else-if="col.name == 'fullname'">
{{
props.row.firstName
? `${props.row.prefix ?? ""}${
props.row.firstName ?? ""
} ${props.row.lastName ?? ""}`
: "-"
}}
</div>
<div v-else-if="col.name == 'status'">
{{ props.row.status ? statusText(props.row.status) : "-" }}
</div>
<div v-else-if="col.name == 'dateOfBirth'">
{{
props.row.dateOfBirth
? date2Thai(props.row.dateOfBirth)
: "-"
}}
</div>
<div v-else-if="col.name == 'organizationName'">
<div class="col-4">
<div class="text-weight-medium">
{{ props.row.root !== null ? props.row.root : "-" }}
{{
props.row.rootShortName !== null
? `(${props.row.rootShortName})`
: ""
}}
</div>
<div class="text-weight-light">
{{
props.row.nodeName !== null ? props.row.nodeName : ""
}}
{{
props.row.nodeShortName !== null
? `(${props.row.nodeShortName}${props.row.posMasterNo})`
: ""
}}
</div>
</div>
</div>
<div v-else-if="col.name == 'createdAt'">
{{
props.row.createdAt ? date2Thai(props.row.createdAt) : "-"
}}
</div>
<div v-else>
{{ col.value ? col.value : "-" }}
</div>
</q-td>
</q-tr>
</template>
</d-table>
</q-card-section>
<q-separator />
<q-card-actions align="right">
<q-btn
label="ส่งไปออกคำสั่ง"
@click="sendToCommand"
color="public"
:disable="checkSelected"
>
<q-tooltip>งไปออกคำส</q-tooltip>
</q-btn>
</q-card-actions>
</q-card>
</q-dialog>
</template>

View file

@ -1,6 +1,9 @@
<script setup lang="ts">
import { ref, computed, watch } from "vue";
import { ref, watch } from "vue";
import { useQuasar } from "quasar";
import { useCounterMixin } from "@/stores/mixin";
import { useTransferDataStore } from "@/modules/05_placement/store";
import http from "@/plugins/http";
import config from "@/app.config";
@ -15,12 +18,6 @@ import type { officerType } from "@/modules/05_placement/interface/response/offi
*/
import DialogHeader from "@/components/DialogHeader.vue";
/**
* importStore
*/
import { useCounterMixin } from "@/stores/mixin";
import { useTransferDataStore } from "@/modules/05_placement/store";
/**
* use
*/
@ -188,13 +185,7 @@ const visibleColumns2 = ref<string[]>([
"createdAt",
"status",
]);
const selected = ref<officerType[]>([]);
const checkSelected = computed(() => {
if (selected.value.length === 0) {
return true;
}
});
const selected = ref<officerType[]>([]); //
/**
* นยนการสงไปออกคำส
@ -242,6 +233,11 @@ function Reset() {
emit("update:filterKeyword2", "");
}
/**
* เม props.modal เป true
*
* กำหนดให selected เปนคาวาง
*/
watch(
() => props.Modal,
() => {
@ -354,7 +350,7 @@ watch(
<q-card-actions align="right">
<q-btn
label="ส่งไปออกคำสั่ง"
:disable="checkSelected"
:disable="selected.length === 0"
color="public"
@click="saveOrder"
><q-tooltip>งไปออกคำส</q-tooltip></q-btn

View file

@ -1,8 +1,10 @@
<script setup lang="ts">
import { onMounted, ref } from "vue";
import { checkPermission } from "@/utils/permissions";
import { useQuasar } from "quasar";
import { useRoute, useRouter } from "vue-router";
import { checkPermission } from "@/utils/permissions";
import { useCounterMixin } from "@/stores/mixin";
import http from "@/plugins/http";
import config from "@/app.config";
@ -14,9 +16,6 @@ import type { DataProfile } from "@/modules/05_placement/interface/index/Main";
/** importComponents*/
import CardProfile from "@/components/CardProfile.vue";
/** impoerStore*/
import { useCounterMixin } from "@/stores/mixin";
/** use*/
const $q = useQuasar();
const route = useRoute();
@ -32,12 +31,11 @@ const {
findOrgName,
} = mixin;
const myForm = ref<QForm | null>(null);
const edit = ref<boolean>(false);
const dataId = route.params.id as string;
const dataProfile = ref<DataProfile>();
const fullname = ref<string>("");
const myForm = ref<QForm | null>(null);
const edit = ref<boolean>(false); //
const dataProfile = ref<DataProfile>(); //
const fullname = ref<string>(""); //
/** form แก้ไขข้อมูลเพื่อลงบัญชีแนบท้าย*/
const organizationPositionOld = ref<string>(""); ///
@ -50,9 +48,9 @@ const status = ref<string>("");
/**
* fetch อมลรายละเอยด
*/
function getData() {
async function getData() {
showLoader();
http
await http
.get(config.API.officerDetail(dataId))
.then((res: resHelpDetail) => {
const data = res.data.result;
@ -128,6 +126,9 @@ const getClass = (val: boolean) => {
};
};
/**
* ทำงานเมอมการเรยกใช Components
*/
onMounted(() => {
getData();
});

View file

@ -1,34 +0,0 @@
<script setup lang="ts">
const props = defineProps({
title: String,
close: {
type: Function,
default: () => console.log("not function"),
},
});
const close = async () => {
props.close();
};
</script>
<template>
<q-toolbar class="q-py-md">
<q-toolbar-title class="header-text">{{ title }}</q-toolbar-title>
<q-btn
icon="close"
unelevated
round
dense
@click="close"
style="color: #ff8080; background-color: #ffdede"
/>
</q-toolbar>
</template>
<style scoped lang="scss">
.header-text {
font-size: 18px;
font-weight: 600;
line-height: 26px;
color: #35373c;
}
</style>

View file

@ -1,5 +1,5 @@
<script setup lang="ts">
import { ref, computed, watchEffect, watch } from "vue";
import { ref, watch } from "vue";
import { useQuasar } from "quasar";
import type { QTableProps } from "quasar";
import http from "@/plugins/http";
@ -41,12 +41,8 @@ const emit = defineEmits([
"update:selected",
]);
const selected = ref<any>([]);
const checkSelected = computed(() => {
if (selected.value.length === 0 || props.type === "") {
return true;
}
});
const selected = ref<any[]>([]); //
const OptionsTypeFn = ref<any[]>([]); //
/**
* Table
@ -183,21 +179,15 @@ function clickAddlist() {
});
}
watch(
() => props.Modal,
() => {
if (props.Modal === true) {
selected.value = [];
}
}
);
// filter OptionsType
const OptionsTypeFn = ref<any>([]);
function filterFnOptionsType(val: string, update: any) {
/**
* filter OptionsType
* @param val คำคนหา
* @param update Function
*/
function filterFnOptionsType(val: string, update: Function) {
if (val == "") {
update(() => {
OptionsTypeFn.value = props.optionsType;
OptionsTypeFn.value = props.optionsType || [];
});
} else {
update(() => {
@ -209,6 +199,20 @@ function filterFnOptionsType(val: string, update: any) {
});
}
}
/**
* เม props.modal เป true
*
* กำหนดให selected เปนคาวาง
*/
watch(
() => props.Modal,
() => {
if (props.Modal === true) {
selected.value = [];
}
}
);
</script>
<template>
@ -334,7 +338,7 @@ function filterFnOptionsType(val: string, update: any) {
<q-btn
label="ส่งไปออกคำสั่ง"
@click="clickAddlist"
:disable="checkSelected"
:disable="selected.length === 0"
color="public"
>
<q-tooltip>งไปออกคำส</q-tooltip>

View file

@ -1,11 +1,14 @@
<script setup lang="ts">
import { onMounted, ref } from "vue";
import { useQuasar } from "quasar";
import { checkPermission } from "@/utils/permissions";
import { useRoute, useRouter } from "vue-router";
import { checkPermission } from "@/utils/permissions";
import { tokenParsed } from "@/plugins/auth";
import { useCounterMixin } from "@/stores/mixin";
import http from "@/plugins/http";
import config from "@/app.config";
import { tokenParsed } from "@/plugins/auth";
/**
* impotyType
*/
@ -16,15 +19,11 @@ import type { DataProfile } from "@/modules/05_placement/interface/index/Main";
/** importComponents*/
import CardProfile from "@/components/CardProfile.vue";
/** importStore*/
import { useCounterMixin } from "@/stores/mixin";
/** use*/
const $q = useQuasar();
const route = useRoute();
const router = useRouter();
const mixin = useCounterMixin();
const paramsId = route.params.id;
const {
messageError,
showLoader,
@ -35,29 +34,30 @@ const {
success,
} = mixin;
const paramsId = route.params.id;
const myForm = ref<QForm | null>(null);
const roleAdmin = ref<boolean>(false);
const dataProfile = ref<DataProfile>();
const fullName = ref<string>("");
const dataProfile = ref<DataProfile>(); //
const edit = ref<boolean>(false);
const status = ref<string>("");
const fullName = ref<string>("");
const educationOld = ref<string>("");
const organizationPositionOld = ref<string>("");
const positionTypeOld = ref<string>("");
const positionLevelOld = ref<string>("");
const posNo = ref<string>("");
const salary = ref<number>(0);
const date = ref<Date | null>(null);
const militaryDate = ref<Date | null>(null);
const reason = ref<string>("");
const educationOld = ref<string>(""); ///
const organizationPositionOld = ref<string>(""); ///
const positionTypeOld = ref<string>(""); //
const positionLevelOld = ref<string>(""); //
const posNo = ref<string>(""); //
const salary = ref<number>(0); //
const date = ref<Date | null>(null); //
const militaryDate = ref<Date | null>(null); //
const reason = ref<string>(""); //
/**
* fetch รายละเอยดรายการอนๆ
*/
function fetchData() {
async function fetchData() {
showLoader();
http
await http
.get(config.API.otherByid(paramsId.toString()))
.then((res: resApiData) => {
const data = res.data.result;

View file

@ -1,783 +0,0 @@
<script setup lang="ts">
import { useQuasar, QForm } from "quasar";
import { onMounted, reactive, ref, watch } from "vue";
import DialogHeader from "@/components/DialogHeader.vue";
import DialogFooter from "@/modules/05_placement/components/PersonalList/DialogFooter.vue";
import { useCounterMixin } from "@/stores/mixin";
import http from "@/plugins/http";
import config from "@/app.config";
const $q = useQuasar();
const mixin = useCounterMixin(); //
const { date2Thai, hideLoader, messageError, showLoader, success } = mixin; //
const notFound = ref<string>("ไม่พบข้อมูลที่ค้นหา");
const noData = ref<string>("ไม่พบข้อมูลผังโครงสร้าง");
const checkValidate = ref<boolean>(false);
const myFormPosition = ref<any>();
const selected = ref<string>("");
const selectedFile = ref<string>("");
const dataRespone = ref<any>();
// Set form field
let dataForm = reactive({
personalId: "",
containDate: new Date(),
posNoId: "",
positionId: "",
positionLevelId: "",
positionLineId: "",
positionPathSideId: "",
positionTypeId: "",
// salaryAmount: null,
// mouthSalaryAmount: null,
// positionSalaryAmount: null,
});
onMounted(async () => {
await fetchPublishFile();
await loadTreeData();
await fetchplacementPosition();
});
const fetchPublishFile = async () => {
await http
.get(config.API.getPublishFileHistory)
.then((res) => {
let data = res.data.result;
selectedFile.value = data[0].fileName;
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
hideLoader();
});
};
// json
const treeData = ref<Array<any>>([]);
const loadTreeData = async () => {
expanded.value = [];
await http
.get(`${config.s3ClusterUrl}${selectedFile.value}`)
.then((res: any) => {
treeData.value = res.data;
dataRespone.value = res.data;
// Filter objects with "name" null
const filteredData = res.data.filter(filterByPersonIdNull);
treeData.value = filteredData;
})
.catch((e: any) => {
messageError($q, e);
})
.finally(() => {
hideLoader();
});
};
function filterByPersonIdNull(obj: any) {
if (obj.name === null && obj.isCondition != true) {
return true;
}
if (obj.children && obj.children.length > 0) {
obj.children = obj.children.filter(filterByPersonIdNull);
return obj.children.length > 0;
}
return false;
}
// position
const placementPosition = ref<any>([]);
const fetchplacementPosition = async () => {
await http
.get(config.API.placementPosition())
.then((res: any) => {
placementPosition.value = res.data.result;
})
.catch((e: any) => {
messageError($q, e);
});
};
const search = ref<string>("");
//reset Tree Filter
const filterRef = ref<any>(null);
// const resetFilter = () => {
// search.value = "";
// filterRef.value.focus();
// };
const props = defineProps({
personalId: String,
modal: Boolean,
close: {
type: Function,
default: () => console.log("close modal"),
},
personal: Object,
});
const myFilterMethod = (node: any, filter: string) => {
const filt = filter;
return (
// ((node.name && node.name == null) || !node.name) &&
(node.name && node.name.indexOf(filt) > -1) ||
(node.organizationName && node.organizationName.indexOf(filt) > -1) ||
(node.positionNum && node.positionNum.indexOf(filt) > -1) ||
(node.positionName && node.positionName.indexOf(filt) > -1) ||
(node.governmentCode &&
node.governmentCode.toString().indexOf(filt) > -1) ||
(node.agency && node.agency.indexOf(filt) > -1) ||
(node.government && node.government.indexOf(filt) > -1) ||
(node.department && node.department.indexOf(filt) > -1) ||
(node.pile && node.pile.indexOf(filt) > -1) ||
(node.organizationShortName &&
node.organizationShortName.indexOf(filt) > -1) ||
(node.positionSideName && node.positionSideName.indexOf(filt) > -1) ||
(node.executivePosition && node.executivePosition.indexOf(filt) > -1) ||
(node.executivePositionSide &&
node.executivePositionSide.indexOf(filt) > -1) ||
(node.positionLevel && node.positionLevel.indexOf(filt) > -1)
);
};
const validateData = async () => {
checkValidate.value = true;
await myFormPosition.value.validate().then((result: boolean) => {
if (result == false) {
checkValidate.value = false;
}
});
};
const id = ref<string>("");
const saveAppoint = async () => {
myFormPosition.value.validate().then(async (result: boolean) => {
if (props.personalId !== undefined) {
id.value = props.personalId.toString();
}
if (result) {
const dataAppoint = await {
// personalId: props.personalId,
recruitDate: dataForm.containDate,
posNoId: dataForm.posNoId,
positionId: dataForm.positionId,
positionLevelId: dataForm.positionLevelId,
positionLineId: dataForm.positionLineId,
positionPathSideId: dataForm.positionPathSideId,
positionTypeId: dataForm.positionTypeId,
// salaryAmount: dataForm.salaryAmount,
// mouthSalaryAmount: dataForm.mouthSalaryAmount,
// positionSalaryAmount: dataForm.positionSalaryAmount,
};
showLoader();
await http
.put(config.API.otherPosition(id.value), dataAppoint)
.then(() => {
success($q, "บันทึกสำเร็จ");
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await closeAndClear();
// await resetFilter();
await fetchPublishFile();
await loadTreeData();
await fetchplacementPosition();
hideLoader();
});
}
});
};
const editDataStatus = ref<boolean>(false);
const clickEditRow = () => {
editDataStatus.value = true;
};
const closeModal = () => {
if (editDataStatus.value == true) {
$q.dialog({
title: `ข้อมูลมีการแก้ไข`,
message: `ยืนยันที่จะปิดโดยไม่บันทึกใช่หรือไม่?`,
cancel: "ยกเลิก",
ok: "ยืนยัน",
persistent: true,
}).onOk(() => {
editDataStatus.value = false;
closeAndClear();
});
} else {
closeAndClear();
}
};
const closeAndClear = async () => {
await props.close();
editDataStatus.value = false;
selected.value = "";
dataForm.personalId = "";
dataForm.containDate = new Date();
dataForm.posNoId = "";
dataForm.positionId = "";
dataForm.positionLevelId = "";
dataForm.positionLineId = "";
dataForm.positionPathSideId = "";
dataForm.positionTypeId = "";
// dataForm.salaryAmount = null;
// dataForm.mouthSalaryAmount = null;
// dataForm.positionSalaryAmount = null;
};
//
const posNoOptions = ref<Object[]>([
{
label: "",
value: "",
},
]);
//
const positionOptions = ref<Object[]>([
{
label: "",
value: "",
},
]);
// /
const positionPathSideOptions = ref<Object[]>([
{
label: "",
value: "",
},
]);
//
const positionTypeOptions = ref<Object[]>([
{
label: "",
value: "",
},
]);
//
const positionLineOptions = ref<Object[]>([
{
label: "",
value: "",
},
]);
//
const positionLevelOptions = ref<Object[]>([
{
label: "",
value: "",
},
]);
const selectedPosition = async (data: any) => {
if (data.name == null && selected.value != data.keyId) {
editDataStatus.value = true;
selected.value = data.keyId;
// posNo Options
posNoOptions.value = [
{
label: data.positionNum,
value: data.positionNumId,
},
];
dataForm.posNoId = data.positionNumId;
// position Options
positionOptions.value = [
{
label: data.positionName,
value: data.positionNameId,
},
];
dataForm.positionId = data.positionNameId;
// positionPathSide Options
let positionPathSideArr: any = [];
if (data.positionSideNameObj && data.positionSideNameObj != null) {
data.positionSideNameObj.map((x: any) => {
positionPathSideArr.push({
label: x.Name,
value: x.Id,
});
});
positionPathSideOptions.value = positionPathSideArr;
dataForm.positionPathSideId =
positionPathSideArr.length > 1 || positionPathSideArr.length == 0
? ""
: positionPathSideArr[0].value;
}
// positionType Options
positionTypeOptions.value = [
{
label: data.positionType,
value: data.positionTypeId,
},
];
dataForm.positionTypeId = data.positionTypeId;
// positionLine Options
positionLineOptions.value = [
{
label: data.positionLine,
value: data.positionLineId,
},
];
dataForm.positionLineId = data.positionLineId;
// positionLevel Options
let positionLevelsArr: any = [];
if (data.positionLevelObj != null) {
data.positionLevelObj.map((x: any) => {
positionLevelsArr.push({
label: x.Name,
value: x.Id,
});
});
positionLevelOptions.value = positionLevelsArr;
dataForm.positionLevelId =
positionLevelsArr.length > 1 || positionLevelsArr.length == 0
? ""
: positionLevelsArr[0].value;
dataForm.positionLevelId = data.positionLevelObj[0].Id;
}
} else if (selected.value == data.keyId) {
selected.value = "";
dataForm.posNoId = "";
dataForm.positionId = "";
dataForm.positionLevelId = "";
dataForm.positionLineId = "";
dataForm.positionPathSideId = "";
dataForm.positionTypeId = "";
}
};
const checkPosition = (val: string) => {
const num = placementPosition.value.findIndex((e: string) => e === val);
return num;
};
const personal = ref<any>();
const expanded = ref<string[]>([]);
watch(props, () => {
expanded.value = [];
const dataPersonal = props.personal;
if (dataPersonal) {
dataPersonal.map((data: any) => {
personal.value = data;
});
}
if (personal.value) {
let findData: any = null;
dataRespone.value.map((x: any) => {
findData = findByPerson(x);
if (findData != null) {
selectedPosition(findData);
for (let i = 3; i <= findData.keyId.length; i += 2) {
expanded.value.push(findData.keyId.slice(0, i));
}
}
});
// loadTreeData();
// selectedPosition(findData.children.children.children)
}
});
function findByPerson(element: any): any {
if (
element.positionNumId &&
element.positionLineId === personal.value.positionLineId &&
element.positionTypeId === personal.value.positionTypeId &&
element.positionNumId === personal.value.posNoId &&
(element.positionLevelObj === null ||
element.positionLevelObj[0].Id === personal.value.positionLevelId)
) {
return element;
} else if (element.children) {
var i;
var result = null;
for (i = 0; result == null && i < element.children.length; i++) {
result = findByPerson(element.children[i]);
}
return result;
}
return null;
}
</script>
<template>
<q-dialog v-model="props.modal" persistent>
<q-card style="width: 900px; max-width: 80vw">
<q-form ref="myFormPosition">
<DialogHeader :tittle="'เลือกหน่วยงานที่รับโอน'" :close="closeModal" />
<q-separator />
<q-card-section class="q-pa-sm bg-grey-1">
<div class="row col-12 q-col-gutter-sm">
<div class="col-xs-12 col-sm-7 row">
<q-card flat bordered class="fit q-pa-sm">
<q-scroll-area visible style="height: 70vh">
<q-input
outlined
dense
ref="filterRef"
v-model="search"
placeholder="ค้นหา"
class="q-mb-sm"
>
<template v-slot:append>
<q-icon name="mdi-magnify" />
</template>
</q-input>
<div class="q-pa-sm q-gutter-sm">
<q-tree
no-transition
dense
:nodes="treeData"
node-key="keyId"
:filter="search"
:no-results-label="notFound"
:no-nodes-label="noData"
:filter-method="myFilterMethod"
v-model:expanded="expanded"
>
<template v-slot:header-organization="prop">
<div class="col">
<div
class="row items-center q-px-xs q-pt-xs q-gutter-sm"
>
<!--แสดงชอแผนก มพวหนา คลกแลวกาง/ Tree-->
<div class="text-weight-medium">
{{ prop.node.organizationName }}
</div>
<!--แสดง Total Count PositionNum-->
<!-- <q-badge rounded color="grey-2" text-color="dark"
:label="prop.node.totalPositionCount" /> -->
<q-badge
v-if="prop.node.totalPositionVacant > 0"
rounded
color="red"
outline
:label="prop.node.totalPositionVacant"
/>
<q-space />
</div>
<div class="col items-center q-px-xs q-pt-xs">
<div class="text-weight-medium text-grey-7">
{{ prop.node.governmentCode }}
{{ prop.node.organizationShortName }}
</div>
</div>
</div>
</template>
<template v-slot:header-person="prop">
<q-item
clickable
:active="selected == prop.node.keyId"
@click="selectedPosition(prop.node)"
:disable="
prop.node.name != null ||
checkPosition(prop.node.positionNumId) != -1
"
active-class="my-list-link text-primary text-weight-medium"
class="row items-center text-dark q-py-xs q-pl-sm rounded-borders my-list"
>
<img
v-if="
prop.node.avatar == '' ||
prop.node.avatar ==
'https://cdn.quasar.dev/img/boy-avatar.png'
"
src="@/assets/avatar_user.jpg"
class="col-xs-1 col-sm-2"
style="
width: 28px;
height: 28px;
border-radius: 50%;
"
/>
<img
v-else
:src="prop.node.avatar"
class="col-xs-1 col-sm-2"
style="
width: 28px;
height: 28px;
border-radius: 50%;
"
/>
<!--=====ตำแหนงวาง แดง=====-->
<div
v-if="prop.node.name == null"
class="q-px-sm text-weight-medium text-red"
>
าง
</div>
<!--=====วหน เขยว=====-->
<div v-else-if="prop.node.positionLeaderFlag">
<div
class="q-px-sm text-weight-medium text-primary"
>
{{ prop.node.name }}
</div>
</div>
<!--=====กนอง ปกต=====-->
<div v-else>
<div class="q-px-sm text-weight-medium">
{{ prop.node.name }}
</div>
</div>
<!--อทายชอคน แสดงสปกต-->
<div class="q-pr-sm">
{{ prop.node.positionName }}
</div>
<div class="q-pr-sm">
{{ prop.node.positionNum }}
</div>
<div class="q-pr-sm">
{{ prop.node.positionLevel }}
</div>
<q-icon
v-if="prop.node.positionLeaderFlag"
class="q-mr-sm"
size="15px"
color="primary"
name="mdi-bookmark"
></q-icon>
<q-space />
</q-item>
</template>
</q-tree>
</div>
</q-scroll-area>
</q-card>
</div>
<div class="col-xs-12 col-sm-5">
<q-card flat bordered class="fit q-pa-sm">
<q-scroll-area visible style="height: 70vh">
<div class="row col-12 q-col-gutter-xs">
<div class="col-xs-12 col-sm-12 col-md-12"></div>
<div class="col-xs-12 col-sm-12 col-md-12">
<datepicker
menu-class-name="modalfix"
v-model="dataForm.containDate"
:locale="'th'"
autoApply
:enableTimePicker="false"
week-start="0"
>
<template #year="{ year }">{{ year + 543 }}</template>
<template #year-overlay-value="{ value }">{{
parseInt(value + 543)
}}</template>
<template #trigger>
<q-input
class="full-width inputgreen cursor-pointer"
outlined
dense
:model-value="
date2Thai(new Date(dataForm.containDate))
"
:rules="[ (val: string) =>!!val ||`${'วันที่รายงานตัว'}`,
]"
:label="`${'วันที่รายงานตัว'}`"
hide-bottom-space
>
<template v-slot:prepend>
<q-icon
name="event"
class="cursor-pointer"
style="color: var(--q-primary)"
>
</q-icon>
</template>
</q-input>
</template>
</datepicker>
</div>
<q-space />
<div class="col-xs-12 col-sm-12 col-md-12">
<q-select
class="full-width inputgreen cursor-pointer custom-input"
outlined
standout
dense
hide-bottom-space
lazy-rules
:options="posNoOptions"
v-model="dataForm.posNoId"
:label="`${'ตำแหน่งเลขที่'}`"
map-options
/>
</div>
<div class="col-xs-12 col-sm-12 col-md-12">
<q-select
outlined
class="full-width inputgreen cursor-pointer custom-input"
standout
dense
hide-bottom-space
lazy-rules
:options="positionOptions"
v-model="dataForm.positionId"
:label="`${'ตำแหน่ง'}`"
map-options
/>
</div>
<div class="col-xs-12 col-sm-12 col-md-12">
<q-select
outlined
class="full-width inputgreen cursor-pointer custom-input"
standout
dense
hide-bottom-space
lazy-rules
:options="positionPathSideOptions"
v-model="dataForm.positionPathSideId"
:label="`${'ด้าน/สาขา'}`"
map-options
/>
</div>
<div class="col-xs-12 col-sm-12 col-md-12">
<q-select
outlined
class="full-width inputgreen cursor-pointer custom-input"
standout
dense
hide-bottom-space
lazy-rules
:options="positionTypeOptions"
v-model="dataForm.positionTypeId"
:label="`${'ประเภทตำแหน่ง'}`"
map-options
/>
</div>
<div class="col-xs-12 col-sm-12 col-md-12">
<q-select
outlined
class="full-width inputgreen cursor-pointer custom-input"
standout
dense
hide-bottom-space
lazy-rules
:options="positionLineOptions"
v-model="dataForm.positionLineId"
:label="`${'สายงาน'}`"
map-options
/>
</div>
<div class="col-xs-12 col-sm-12 col-md-12">
<q-select
outlined
class="full-width inputgreen cursor-pointer custom-input"
standout
dense
lazy-rules
:options="positionLevelOptions"
v-model="dataForm.positionLevelId"
:label="`${'ระดับ'}`"
hide-bottom-space
:rules="[(val: string) => !!val || `${'กรุณาเลือกระดับ'}`]"
emit-value
map-options
/>
</div>
<!-- <div class="col-sx-12 col-sm-12 col-md-12">
<q-separator inset size="2px" class="q-my-md" />
</div> -->
<!-- <div class="col-xs-6 col-sm-6 col-md-6">
<q-input
outlined
dense
lazy-rules
v-model="dataForm.salaryAmount"
:rules="[(val) => !!val || `${'กรุณากรอกเงินเดือน'}`]"
:label="`${'เงินเดือน'}`"
@update:modelValue="clickEditRow"
type="number"
hide-bottom-space
/>
</div> -->
<!-- <div class="col-xs-6 col-sm-6 col-md-6">
<q-input
outlined
dense
lazy-rules
v-model="dataForm.positionSalaryAmount"
:rules="[
(val) => !!val || `${'กรุณากรอกเงินประจำตำแหน่ง'}`,
]"
:label="`${'เงินประจำตำแหน่ง'}`"
@update:modelValue="clickEditRow"
type="number"
hide-bottom-space
/>
</div> -->
<!-- <div class="col-xs-6 col-sm-6 col-md-6">
<q-input
outlined
dense
lazy-rules
v-model="dataForm.mouthSalaryAmount"
:rules="[
(val) =>
!!val || `${'กรุณากรอกเงินค่าตอบแทนรายเดือน'}`,
]"
:label="`${'เงินค่าตอบแทนรายเดือน'}`"
@update:modelValue="clickEditRow"
type="number"
hide-bottom-space
/>
</div> -->
</div>
</q-scroll-area>
</q-card>
</div>
</div>
</q-card-section>
<q-separator />
<DialogFooter
:editvisible="true"
:validate="validateData"
:save="saveAppoint"
v-model:modalEdit="editDataStatus"
/>
</q-form>
</q-card>
</q-dialog>
</template>
<style scoped lang="scss">
.q-tree__node-header {
padding: 0px;
margin-top: 0px;
border-radius: 4px;
outline: 0;
}
.my-list-link {
color: rgb(118, 168, 222);
border-radius: 5px;
background: #a3d3fb48 !important;
font-weight: 600;
border: 1px solid rgba(175, 185, 196, 0.217);
/* box-shadow: 1px 1px 7px 1px rgba(41, 95, 255, 0.15) !important; */
}
</style>

View file

@ -1,30 +1,20 @@
<!-- หน รายละเอยดของ -->
<script setup lang="ts">
import { onMounted, reactive, ref } from "vue";
import { useDataStore } from "@/stores/data";
import { useRoute, useRouter } from "vue-router";
import { useCounterMixin } from "@/stores/mixin";
import { onMounted, ref } from "vue";
import { useQuasar } from "quasar";
import { useRoute, useRouter } from "vue-router";
import { useDataStore } from "@/stores/data";
import { usePersonalDataStore } from "@/modules/05_placement/storePersona";
import { useCounterMixin } from "@/stores/mixin";
import { checkPermission } from "@/utils/permissions";
import http from "@/plugins/http";
import config from "@/app.config";
import { usePersonalDataStore } from "@/modules/05_placement/storePersona";
import Informationvue from "@/modules/05_placement/components/PersonalDetail/Information/Information.vue";
import Addressvue from "@/modules/05_placement/components/PersonalDetail/Information/Address.vue";
import EducationVue from "@/modules/05_placement/components/PersonalDetail/Education.vue";
import Certicate from "@/modules/05_placement/components/PersonalDetail/Information/Certicate.vue";
import ExamResult from "@/modules/05_placement/components/PersonalDetail/ExamResult.vue";
import Qualification from "@/modules/05_placement/components/PersonalDetail/Qualification.vue";
import Familyvue from "@/modules/05_placement/components/PersonalDetail/Information/Family.vue";
import Document from "@/modules/05_placement/components/PersonalDetail/Information/Document.vue";
import {
AddressDataDefualt,
FamilyDataDefualt,
} from "@/modules/05_placement/interface/index/Main";
import type {
Property,
PointExam,
@ -35,25 +25,32 @@ import type {
optionData,
InformationOps,
} from "@/modules/05_placement/interface/index/Main";
import type { Information } from "@/modules/05_placement/components/PersonalDetail/profileType";
import { checkPermission } from "@/utils/permissions";
const $q = useQuasar(); // show dialog
import Informationvue from "@/modules/05_placement/components/PersonalDetail/Information/Information.vue";
import Addressvue from "@/modules/05_placement/components/PersonalDetail/Information/Address.vue";
import Familyvue from "@/modules/05_placement/components/PersonalDetail/Information/Family.vue";
import Certicate from "@/modules/05_placement/components/PersonalDetail/Information/Certicate.vue";
import EducationVue from "@/modules/05_placement/components/PersonalDetail/Information/Education.vue";
import ExamResult from "@/modules/05_placement/components/PersonalDetail/Information/ExamResult.vue";
import Qualification from "@/modules/05_placement/components/PersonalDetail/Information/Qualification.vue";
import Document from "@/modules/05_placement/components/PersonalDetail/Information/Document.vue";
const $q = useQuasar();
const route = useRoute();
const router = useRouter();
const store = useDataStore();
const mixin = useCounterMixin(); //
const mixin = useCounterMixin();
const storePersonal = usePersonalDataStore();
const { showLoader, hideLoader, messageError } = mixin;
const { changeTab } = store;
const statusEdit = ref<boolean>(false);
const profileType = ref<string>("");
const route = useRoute();
const examId = ref<string>(
route.params.personalId ? route.params.personalId.toString() : ""
);
const statusEdit = ref<boolean>(false); //
const profileType = ref<string>(""); //
//
const ExamDataDefualt: PointExam = {
pointA: 0,
pointB: 0,
@ -67,7 +64,7 @@ const ExamDataDefualt: PointExam = {
examRound: 0,
pass: "",
};
//
const InformationDataDefualt: Information = {
idCard: "",
prefix: "",
@ -89,29 +86,23 @@ const InformationDataDefualt: Information = {
religion: "",
religionId: "",
};
//
const personalData = ref({
id: "",
fullName: "",
});
const QualificationData = ref<Property[]>([]);
const ExamData = ref<PointExam>(ExamDataDefualt);
const InformationData = ref<Information>(InformationDataDefualt);
const EducationData = ref<Education[]>([]);
const FamilyData = ref<Family>(FamilyDataDefualt);
const AddressData = ref<Address>(AddressDataDefualt);
const CertificateData = ref<Certificate[]>([]);
const ExamData = ref<PointExam>(ExamDataDefualt); //
const InformationData = ref<Information>(InformationDataDefualt); //
const EducationData = ref<Education[]>([]); //
const FamilyData = ref<Family>(FamilyDataDefualt); //
const AddressData = ref<Address>(AddressDataDefualt); //
const CertificateData = ref<Certificate[]>([]); //
//
const isEdit = ref<boolean>(
checkPermission(route)?.attrIsUpdate ? true : false
);
const guidCheck = (id: string) => {
if (id == "00000000-0000-0000-0000-000000000000") {
return null;
}
return id;
};
const Ops = ref<InformationOps>({
prefixOps: [],
genderOps: [],
@ -144,16 +135,19 @@ const OpsFilter = ref<InformationOps>({
],
});
const fetchData = async () => {
/**
* งกนดงขอมลรายละเอยดทงหมด
*/
async function fetchData() {
showLoader();
storePersonal.loading = false;
await http
.get(config.API.placementPersonalId(examId.value))
.then((res: any) => {
const data = res.data.result;
.then(async (res) => {
const data = await res.data.result;
storePersonal.fecthDataInformation(data);
personalData.value.fullName = data.fullName;
personalData.value.id = data.personalId;
InformationData.value.idCard = data.idCard;
InformationData.value.fullName = data.fullName;
InformationData.value.firstname = data.firstname;
@ -263,19 +257,24 @@ const fetchData = async () => {
});
CertificateData.value = listCert;
})
.catch((e: any) => {
.catch((e) => {
messageError($q, e);
})
.finally(() => {});
};
.finally(() => {
hideLoader();
});
}
const fetchDataByType = async (type: string) => {
// storePersonal.loading = false;
/**
* งกนดงขอมลรายละเอยดตามประเภท
* @param type ประเภทของขอม
*/
async function fetchDataByType(type: string) {
showLoader();
await http
.get(config.API.placementPersonalId(examId.value))
.then((res: any) => {
const data = res.data.result;
.then(async (res) => {
const data = await res.data.result;
storePersonal.fecthDataInformation(data);
personalData.value.fullName = data.fullName;
personalData.value.id = data.personalId;
@ -392,18 +391,19 @@ const fetchDataByType = async (type: string) => {
QualificationData.value = data.isProperty;
}
})
.catch((e: any) => {
.catch((e) => {
messageError($q, e);
})
.finally(() => {
hideLoader();
});
};
}
/**
* get รายการ อมลเกยวกบบคคล
* งกนดอมลเกยวกบบคคล
*/
const fetchPerson = async () => {
async function fetchPerson() {
showLoader();
await http
.get(config.API.profileNewMetaMain)
.then((res) => {
@ -464,16 +464,32 @@ const fetchPerson = async () => {
Ops.value.religionOps = optionreligions;
OpsFilter.value.religionOps = optionreligions;
})
.catch((e: any) => {})
.finally(() => {});
};
.catch((e) => {
messageError($q, e);
})
.finally(() => {
hideLoader();
});
}
/**
* งกนเช id
* @param id profile
* @returns ID เป "00000000-0000-0000-0000-000000000000" ให return null
*
*/
function guidCheck(id: string) {
if (id == "00000000-0000-0000-0000-000000000000") {
return null;
}
return id;
}
/**
* ทำงานเมอมการเรยกใช Components
*/
onMounted(async () => {
// await checkProfileData();
await fetchData();
await changeTab("information");
await fetchPerson();
await Promise.all([fetchData(), changeTab("information"), fetchPerson()]);
});
</script>

View file

@ -53,10 +53,6 @@ const edit = async () => {
updateEdit(!props.editvisible);
props.edit();
};
const checkSave = () => {
props.validate();
props.save();
};
const clickNext = async () => {
await props.clickNext();
@ -93,8 +89,7 @@ const clickPrevious = async () => {
label="ลบข้อมูล"
color="red"
@click="clickDelete"
><!-- icon="mdi-delete"
<q-tooltip>ลบขอม</q-tooltip> -->
>
</q-btn>
<q-btn
v-show="editvisible"
@ -106,8 +101,6 @@ const clickPrevious = async () => {
label="ยกเลิกแก้ไข"
v-if="modalEdit == true"
>
<!-- icon="mdi-undo"
<q-tooltip>ยกเล</q-tooltip> -->
</q-btn>
<q-btn
v-if="!editvisible"
@ -117,8 +110,6 @@ const clickPrevious = async () => {
:color="editvisible ? 'grey-7' : 'primary'"
@click="edit"
>
<!-- icon="mdi-pencil-outline"
<q-tooltip></q-tooltip> -->
</q-btn>
<q-btn
@ -128,8 +119,7 @@ const clickPrevious = async () => {
:color="!editvisible ? 'grey-7' : 'public'"
type="submit"
label="บันทึก"
><!-- icon="mdi-content-save-outline"
<q-tooltip>นท</q-tooltip> -->
>
</q-btn>
</q-card-actions>
</template>

View file

@ -1,27 +0,0 @@
<script setup lang="ts">
const props = defineProps({
tittle: String,
close: {
type: Function,
default: () => console.log("not function"),
},
});
const close = async () => {
props.close();
};
</script>
<template>
<q-toolbar>
<q-toolbar-title class="text-subtitle2 text-bold">{{
tittle
}}</q-toolbar-title>
<q-btn
icon="close"
unelevated
round
dense
@click="close"
style="color: #ff8080; background-color: #ffdede"
/>
</q-toolbar>
</template>

View file

@ -1,17 +1,15 @@
<!-- card อมลทอย -->
<script setup lang="ts">
import { ref, onMounted, reactive } from "vue";
import { useCounterMixin } from "@/stores/mixin";
import { useQuasar } from "quasar";
import http from "@/plugins/http";
import config from "@/app.config";
import type { zipCodeOption } from "@/modules/05_placement/components/PersonalDetail/profileType";
import HeaderTop from "@/modules/05_placement/components/PersonalDetail/Information/top.vue";
import { useRoute } from "vue-router";
import { AddressDataDefualt } from "@/modules//05_placement/interface/index/Main";
import { useCounterMixin } from "@/stores/mixin";
import http from "@/plugins/http";
import config from "@/app.config";
import { AddressDataDefualt } from "@/modules//05_placement/interface/index/Main";
import type { zipCodeOption } from "@/modules/05_placement/components/PersonalDetail/profileType";
import type {
AddressOps,
Address as AddressType,
@ -20,6 +18,16 @@ import type {
} from "@/modules/05_placement/interface/index/Main";
import type { PropType } from "vue";
import HeaderTop from "@/modules/05_placement/components/PersonalDetail/Information/top.vue";
const route = useRoute();
const $q = useQuasar();
const mixin = useCounterMixin();
const { success, messageError, showLoader, hideLoader, dialogConfirm } = mixin;
/**
* props
*/
const props = defineProps({
statusEdit: {
type: Boolean,
@ -40,21 +48,11 @@ const props = defineProps({
});
const emit = defineEmits(["update:statusEdit"]);
const route = useRoute();
const $q = useQuasar();
const mixin = useCounterMixin();
const {
date2Thai,
success,
messageError,
showLoader,
hideLoader,
dialogConfirm,
} = mixin;
const edit = ref<boolean>(false);
const onEdit = ref<boolean>(false);
const addressData = ref<AddressType>(props.data);
const myform = ref<any>();
const myform = ref<any>(); //refForm
const edit = ref<boolean>(false); //
const onEdit = ref<boolean>(false); //
const addressData = ref<AddressType>(props.data); //
//
const Ops = ref<AddressOps>({
provinceOps: [],
districtOps: [],
@ -62,6 +60,7 @@ const Ops = ref<AddressOps>({
subdistrictOps: [],
subdistrictCOps: [],
});
//
const OpsFilter = ref<AddressOps>({
provinceOps: [],
districtOps: [],
@ -69,14 +68,14 @@ const OpsFilter = ref<AddressOps>({
subdistrictOps: [],
subdistrictCOps: [],
});
//
const registAddress = reactive<AddressData>({
subDistrictId: "",
zipCode: "",
districtId: "",
provinceId: "",
});
//
const currentAddress = reactive<AddressData>({
subDistrictId: "",
zipCode: "",
@ -84,12 +83,13 @@ const currentAddress = reactive<AddressData>({
provinceId: "",
});
onMounted(async () => {
await getNewData();
emit("update:statusEdit", false);
});
const filterSelector = (val: any, update: Function, refData: string) => {
/**
* งกนคนหาขอมลในรายการตวเลอก
* @param val คำคนหา
* @param update งก
* @param refData ประเภทของตวเลอก
*/
function filterSelector(val: string, update: Function, refData: string) {
switch (refData) {
case "provinceOps":
update(() => {
@ -130,9 +130,9 @@ const filterSelector = (val: any, update: Function, refData: string) => {
default:
break;
}
};
}
const refreshData = async () => {
function refreshData() {
myform.value.reset();
if (onEdit.value) {
dialogConfirm(
@ -150,15 +150,21 @@ const refreshData = async () => {
} else {
edit.value = false;
}
};
}
const getNewData = async () => {
/**
* งกนดงขอมลใหม
*/
async function getNewData() {
await fetchProvince();
};
}
//
const editData = async () => {
/**
* งกนบนทกการแกไข
*/
async function editData() {
dialogConfirm($q, async () => {
showLoader();
const body = {
registrationSame: addressData.value.registSame == "1",
registrationAddress: addressData.value.registAddress,
@ -201,13 +207,19 @@ const editData = async () => {
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
hideLoader();
});
});
};
}
//
const selectProvince = async (e: string | null, name: string) => {
/**
* งกนเลอกขอมลจงหว
* @param e id งหว
* @param name อยตามทะเบยนบาน , อยจจ
*/
async function selectProvince(e: string | null, name: string) {
onEdit.value = true;
if (e != null) {
if (name == "1") {
@ -222,10 +234,14 @@ const selectProvince = async (e: string | null, name: string) => {
myform.value.resetValidation();
await fetchDistrict(e, name);
}
};
}
//
const selectDistrict = async (e: string | null, name: string) => {
/**
* งกนลอกขอมลอำเภอ
* @param e id อำเภอ
* @param name อยตามทะเบยนบาน , อยจจ
*/
async function selectDistrict(e: string | null, name: string) {
onEdit.value = true;
if (e != null) {
if (name == "1") {
@ -238,10 +254,14 @@ const selectDistrict = async (e: string | null, name: string) => {
myform.value.resetValidation();
await fetchSubDistrict(e, name);
}
};
}
//
const selectSubDistrict = (e: string | null, name: string) => {
/**
* งกนเลอกขอมลตำบล
* @param e id ตำบล
* @param name อยตามทะเบยนบาน , อยจจ
*/
async function selectSubDistrict(e: string | null, name: string) {
onEdit.value = true;
if (e != null) {
if (name == "1") {
@ -254,10 +274,12 @@ const selectSubDistrict = (e: string | null, name: string) => {
currentAddress.zipCode = namecode;
}
}
};
}
//
const fetchProvince = async () => {
/**
* งกนดงขอมลจงหว
*/
async function fetchProvince() {
showLoader();
await http
.get(config.API.orgProvince)
@ -330,10 +352,14 @@ const fetchProvince = async () => {
messageError($q, e);
})
.finally(() => {});
};
}
//
const fetchDistrict = async (id: string | null, position: string) => {
/**
* งกนดงขอมลอำเภอ
* @param id งหว
* @param position อยตามทะเบยนบาน , อยจจ
*/
async function fetchDistrict(id: string | null, position: string) {
if (id != null && id != "") {
await http
.get(config.API.orgProvince + `/${id}`)
@ -373,10 +399,14 @@ const fetchDistrict = async (id: string | null, position: string) => {
})
.finally(() => {});
}
};
}
//
const fetchSubDistrict = async (id: string | null, position: string) => {
/**
* งกนดงขอมลตำบล
* @param id อำเภอ
* @param position อยตามทะเบยนบาน , อยจจ
*/
async function fetchSubDistrict(id: string | null, position: string) {
if (id != null && id != "") {
await http
.get(config.API.orgDistrict + `/${id}`)
@ -422,9 +452,12 @@ const fetchSubDistrict = async (id: string | null, position: string) => {
hideLoader();
});
}
};
}
const changeBtn = async () => {
/**
* งกนการแกไขขอม
*/
function changeBtn() {
if (edit.value == true) {
if (props.statusEdit === true) {
props.notiNoEdit();
@ -434,18 +467,33 @@ const changeBtn = async () => {
} else {
emit("update:statusEdit", false);
}
};
}
const getClass = (val: boolean) => {
/**
* งกนแกไขขอม
*/
function checkEdit() {
onEdit.value = true;
}
/**
* งกนสำหรบคนคาชอคลาสตามคาทกำหนด
* @param val าทใชกำหนดคลาส
*/
function getClass(val: boolean) {
return {
"full-width inputgreen cursor-pointer": val,
"full-width cursor-pointer": !val,
};
};
function checkEdit() {
onEdit.value = true;
}
/**
* ทำงานเมอมการเรยกใช Components
*/
onMounted(async () => {
await getNewData();
emit("update:statusEdit", false);
});
</script>
<template>

View file

@ -1,26 +1,30 @@
<!-- card ใบอนญาตประกอบอาช -->
<script setup lang="ts">
import { onMounted, ref, watch } from "vue";
import { useRoute } from "vue-router";
import { useProfileDataStore } from "@/modules/05_placement/store";
import { useCounterMixin } from "@/stores/mixin";
import { useDataStore } from "@/stores/data";
import ProfileTable from "@/modules/05_placement/components/PersonalDetail/Table.vue";
import DialogHeader from "@/modules/05_placement/components/PersonalDetail/DialogHeader.vue";
import DialogFooter from "@/modules/05_placement/components/PersonalDetail/DialogFooter.vue";
import { useQuasar } from "quasar";
import { useRoute } from "vue-router";
import { useCounterMixin } from "@/stores/mixin";
import { useProfileDataStore } from "@/modules/05_placement/store";
import http from "@/plugins/http";
import config from "@/app.config";
import type {
RequestItemsObject,
DataProps,
} from "@/modules/05_placement/interface/request/Certificate";
import type { ResponseObject } from "@/modules/05_placement/interface/response/Certificate";
import HistoryTable from "@/components/TableHistory.vue";
import http from "@/plugins/http";
import config from "@/app.config";
import type { QTableProps } from "quasar";
import type { PropType } from "vue";
import type { Certificate } from "@/modules/05_placement/interface/index/Main";
import HistoryTable from "@/components/TableHistory.vue";
import ProfileTable from "@/modules/05_placement/components/PersonalDetail/Information/TableEducation.vue";
import DialogHeader from "@/components/DialogHeader.vue";
import DialogFooter from "@/modules/05_placement/components/PersonalDetail/DialogFooter.vue";
/**
* props
*/
const props = defineProps({
statusEdit: {
type: Boolean,
@ -48,7 +52,7 @@ const mixin = useCounterMixin();
const {
date2Thai,
success,
dateToISO,
messageError,
showLoader,
hideLoader,
@ -75,10 +79,7 @@ const rowsHistory = ref<RequestItemsObject[]>([]); //select data history
const tittleHistory = ref<string>("ประวัติแก้ไขใบอนุญาตประกอบอาชีพ"); //
const filterHistory = ref<string>(""); //search data table history
const modalHistory = ref<boolean>(false); //modal
const checkValidate = ref<boolean>(false); //validate data
// const profileId = ref<string>(
// route.params.id ? route.params.id.toString() : ""
// );
const profileId = ref<string>("");
const rows = ref<Certificate[]>([]);
const filter = ref<string>(""); //search data table
@ -238,19 +239,6 @@ const visibleColumnsHistory = ref<String[]>([
"createdAt",
]);
watch(visibleColumns, async (count: String[], prevCount: String[]) => {
await changeProfileColumns("certicate", count);
});
onMounted(async () => {
// await fetchData();
if (route.params.id) {
profileId.value = route.params.personalId.toString();
}
// await props.fetch();
rows.value = props.data;
});
/**
* กดดอมลกอนหน
*/
@ -489,55 +477,6 @@ const clickEditRow = () => {
editRow.value = true;
};
/**
* งชนดอมลประวแกไขขอมลทเลอก
* @param row อม row ประวการแกไข
*/
const clickHistory = async (row: RequestItemsObject) => {
tittleHistory.value =
props.profileType == "employee"
? "ประวัติแก้ไขใบอนุญาตของลูกจ้าง"
: "ประวัติแก้ไขใบอนุญาตประกอบอาชีพ";
modalHistory.value = true;
showLoader();
await http
.get(config.API.profileCertHisId(row.id))
.then((res) => {
let data = res.data.result;
rowsHistory.value = [];
data.map((e: ResponseObject) => {
rowsHistory.value.push({
id: e.id,
certificateNo: e.certificateNo,
issuer: e.issuer,
issueDate: new Date(e.issueDate),
expireDate: new Date(e.expireDate),
certificateType: e.certificateType,
createdFullName: e.createdFullName,
createdAt: new Date(e.createdAt),
});
});
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
hideLoader();
});
};
/**
* validate input ใน dialog
*/
const validateData = async () => {
checkValidate.value = true;
await myForm.value.validate().then((result: boolean) => {
if (result == false) {
checkValidate.value = false;
}
});
};
/**
* class ดรปแบบแสดงระหวางขอมลทแกไขหรอแสดงเฉยๆ
* @param val อม input สำหรบแกไขหรอไม
@ -548,6 +487,17 @@ const getClass = (val: boolean) => {
"full-width cursor-pointer": !val,
};
};
watch(visibleColumns, async (count: String[], prevCount: String[]) => {
changeProfileColumns("certicate", count);
});
onMounted(() => {
if (route.params.id) {
profileId.value = route.params.personalId.toString();
}
rows.value = props.data;
});
</script>
<template>
<q-card flat bordered class="col-12 q-px-lg q-py-md q-mt-md no-border">
@ -587,17 +537,6 @@ const getClass = (val: boolean) => {
{{ col.value }}
</div>
</q-td>
<!-- <q-td auto-width>
<q-btn
color="info"
flat
dense
round
size="14px"
icon="mdi-history"
@click="clickHistory(props.row)"
/>
</q-td> -->
</q-tr>
</template>
</ProfileTable>

View file

@ -1,6 +1,6 @@
<script setup lang="ts">
import { onMounted, computed, ref, watch } from "vue";
import { useQuasar, QForm } from "quasar";
import { onMounted, ref } from "vue";
import { useQuasar } from "quasar";
import { useCounterMixin } from "@/stores/mixin";
import { useRoute } from "vue-router";
import axios from "axios";
@ -15,6 +15,18 @@ interface ArrayFileList {
fileName: string;
}
const $q = useQuasar(); // show dialog
const mixin = useCounterMixin();
const route = useRoute();
const {
success,
messageError,
showLoader,
dialogConfirm,
hideLoader,
dialogRemove,
} = mixin;
const props = defineProps({
statusEdit: {
type: Boolean,
@ -41,72 +53,13 @@ const emit = defineEmits(["update:statusEdit"]);
const documentFile = ref<any>(null);
const fileList = ref<ArrayFileList[]>([]);
const $q = useQuasar(); // show dialog
const mixin = useCounterMixin();
const route = useRoute();
const {
success,
messageError,
showLoader,
dialogConfirm,
hideLoader,
dialogRemove,
} = mixin;
const profileId = ref<string>(
route.params.personalId ? route.params.personalId.toString() : ""
);
const edit = ref<boolean>(false);
const uploader = ref<any>();
const files = ref<any>([]);
const file = ref<any>([]);
const edit = ref<boolean>(false); //
const uploader = ref<any>(); //
const file = ref<any>([]); //
const name = ref<string>("");
const dataMain = ref<any>([]);
// const getData = async () => {
// if (props.datainformation) {
// dataMain.value = props.datainformation;
// files.value = dataMain.value.docs;
// }
//
// if (profileId.value) {
// showLoader();
// await http
// .get(config.API.profilePaperId(profileId.value))
// .then((res) => {
// const data = res.data.result;
// files.value = data;
// })
// .catch((e) => {
// messageError($q, e);
// })
// .finally(() => {
// hideLoader();
// });
// }
// };
const deleteData = async (id: string) => {
dialogConfirm(
$q,
async () => {
showLoader();
await http
.delete(config.API.documentDelid(profileId.value, id))
.then(() => {
success($q, "ลบไฟล์เอกสารสำเร็จ");
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await props.fetch();
});
},
"ยืนยันการลบเอกสารหลักฐาน",
"ต้องการยืนยันการลบเอกสารหลักฐานนี้หรือไม่ ?"
);
};
const uploadData = async () => {
if (profileId.value) {
@ -117,7 +70,6 @@ const uploadData = async () => {
});
const formData = new FormData();
formData.append("file", newFile);
// formData.append("moss", "newFile");
showLoader();
await http
.put(config.API.documentByid(profileId.value), formData)
@ -134,26 +86,10 @@ const uploadData = async () => {
edit.value = false;
emit("update:statusEdit", false);
});
// } else {
// // modalError(
// // $q,
// // "",
// // ""
// // );
// getData();
}
}
};
const fileAdd = async (val: any) => {
name.value = val[0].name;
file.value = val;
};
const downloadData = async (path: string) => {
window.open(path);
};
const changeBtn = async () => {
name.value = "";
if (edit.value == true) {
@ -171,7 +107,6 @@ const changeBtn = async () => {
/** ฟังชั่นใหม่ */
function clickUpload(file: any) {
const fileName = { fileName: file.name };
dialogConfirm(
$q,
async () => {
@ -295,6 +230,9 @@ function deleteFile(fileName: string) {
});
}
/**
* งกนดงขอมลรายการไฟล
*/
async function getData() {
showLoader();
await http
@ -312,6 +250,9 @@ async function getData() {
});
}
/**
* ทำงานเมอมการเรยกใช Components
*/
onMounted(async () => {
await getData();
});

View file

@ -4,8 +4,8 @@ import { useRoute } from "vue-router";
import { useProfileDataStore } from "@/modules/05_placement/store";
import { useCounterMixin } from "@/stores/mixin";
import ProfileTable from "@/modules/05_placement/components/PersonalDetail/Table.vue";
import DialogHeader from "@/modules/05_placement/components/PersonalDetail/DialogHeader.vue";
import ProfileTable from "@/modules/05_placement/components/PersonalDetail/Information/TableEducation.vue";
import DialogHeader from "@/components/DialogHeader.vue";
import DialogFooter from "@/modules/05_placement/components/PersonalDetail/DialogFooter.vue";
import { useQuasar } from "quasar";
import type {
@ -23,6 +23,22 @@ import type {
import type { QTableProps } from "quasar";
import type { PropType } from "vue";
const $q = useQuasar();
const route = useRoute();
const store = useProfileDataStore();
const { profileData, changeProfileColumns } = store;
const mixin = useCounterMixin();
const {
success,
dateToISO,
date2Thai,
messageError,
showLoader,
hideLoader,
dialogRemove,
dialogConfirm,
} = mixin;
const props = defineProps({
statusEdit: {
type: Boolean,
@ -38,21 +54,6 @@ const props = defineProps({
},
});
const $q = useQuasar();
const store = useProfileDataStore();
const { profileData, changeProfileColumns } = store;
const mixin = useCounterMixin();
const {
success,
dateToISO,
date2Thai,
messageError,
showLoader,
hideLoader,
dialogRemove,
dialogConfirm,
} = mixin;
const route = useRoute();
const id = ref<string>("");
const levelId = ref<string>();
const Ops = ref<EduOps>({
@ -96,6 +97,7 @@ const checkValidate = ref<boolean>(false); //validate data ผ่านหรื
const rows = ref<Education[]>(props.data);
const filter = ref<string>(""); //search data table
const visibleColumns = ref<String[]>([]);
profileData.education.columns.length == 0
? (visibleColumns.value = [
"educationLevel",
@ -108,7 +110,6 @@ profileData.education.columns.length == 0
"durationYear",
"other",
"fundName",
// "positionPath",
"finishDate",
"startDate",
"endDate",
@ -170,17 +171,7 @@ const columns = ref<QTableProps["columns"]>([
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
// {
// name: "positionPath",
// align: "left",
// label: "",
// sortable: true,
// field: "positionPath",
// headerStyle: "font-size: 14px",
// style: "font-size: 14px",
// sort: (a: string, b: string) =>
// a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
// },
{
name: "degree",
align: "left",
@ -271,20 +262,9 @@ const columns = ref<QTableProps["columns"]>([
},
]);
watch(startDate, (count, prevCount) => {
minDate.value = new Date(`${startDate.value}-01-01`);
});
watch(visibleColumns, async (count: String[], prevCount: String[]) => {
await changeProfileColumns("education", count);
});
onMounted(async () => {
await fetchLevel();
await fetchPositionPath();
rows.value = props.data;
});
/**
* งกนดงขอมลระด
*/
const fetchLevel = async () => {
showLoader();
await http
@ -306,6 +286,9 @@ const fetchLevel = async () => {
});
};
/**
* งกนดงขอมลตำแหน
*/
const fetchPositionPath = async () => {
let option: any = [];
option.push({ id: true, name: "ใช่" });
@ -314,7 +297,13 @@ const fetchPositionPath = async () => {
OpsFilter.value.positionPathOptions = option;
};
const filterSelector = (val: any, update: Function, refData: string) => {
/**
* งกนคนหาขอมลในรายการตวเลอก
* @param val คำคนหา
* @param update งก
* @param refData ประเภทของตวเลอก
*/
const filterSelector = (val: string, update: Function, refData: string) => {
switch (refData) {
case "levelOptions":
update(() => {
@ -359,7 +348,7 @@ const clickNext = async () => {
/**
* กดดอมลตอไป
*/
const getData = () => {
const getData = async () => {
const row = rows.value[rowIndex.value];
const checkLevelEducation = OpsFilter.value.levelOptions.find(
(e) => e.id === row.educationLevelId
@ -367,8 +356,6 @@ const getData = () => {
levelId.value = checkLevelEducation ? row.educationLevelId : "";
isDate.value = row.isDate;
isEducation.value = row.isEducation;
// positionPathId.value = resultPath;
institute.value = row.institute;
degree.value = row.degree;
field.value = row.field;
@ -396,7 +383,7 @@ const getData = () => {
/**
* เชคปมดอม อน อไป าตองแสดงไหม
*/
const checkRowPage = () => {
const checkRowPage = async () => {
editRow.value = false;
next.value = true;
previous.value = true;
@ -420,9 +407,9 @@ const clickEdit = () => {
/**
* กดปมเพมดานบน table
*/
const clickAdd = async () => {
const clickAdd = () => {
editRow.value = false;
await addData();
addData();
};
/**
@ -430,9 +417,9 @@ const clickAdd = async () => {
*/
const clickSave = async () => {
if (modalEdit.value) {
await dialogConfirm($q, () => editData());
dialogConfirm($q, () => editData());
} else {
await dialogConfirm($q, () => saveData());
dialogConfirm($q, () => saveData());
}
};
@ -444,7 +431,6 @@ const saveData = async () => {
await http
.post(config.API.placementEducationId(route.params.personalId.toString()), {
id: id.value,
// educationLevel: filter[0].name,
educationLevelId: levelId.value,
positionPathId: positionPathId.value,
institute: institute.value,
@ -475,6 +461,8 @@ const saveData = async () => {
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
hideLoader();
});
};
@ -487,7 +475,6 @@ const editData = async () => {
await http
.put(config.API.placementEducationId(route.params.personalId.toString()), {
id: id.value,
// educationLevel: filter[0].name,
educationLevelId: levelId.value,
positionPathId: positionPathId.value,
institute: institute.value,
@ -518,6 +505,8 @@ const editData = async () => {
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
hideLoader();
});
};
@ -526,22 +515,23 @@ const editData = async () => {
* ลบลบขอม
*/
const clickDelete = async () => {
dialogRemove($q, async () => await deletePlacementEducation());
};
const deletePlacementEducation = async () => {
showLoader();
await http
.delete(config.API.placementEducationId(id.value))
.then(async (res) => {
await props.fetch("Education");
await success($q, "ลบข้อมูลสำเร็จ");
modal.value = false;
rows.value = props.data;
})
.catch((e) => {
messageError($q, e);
hideLoader();
});
dialogRemove($q, async () => {
showLoader();
await http
.delete(config.API.placementEducationId(id.value))
.then(async () => {
await props.fetch("Education");
await success($q, "ลบข้อมูลสำเร็จ");
modal.value = false;
rows.value = props.data;
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
hideLoader();
});
});
};
/**
@ -582,9 +572,6 @@ const selectData = async (_props: DataProps) => {
rowIndex.value = _props.rowIndex;
levelId.value = checkLevelEducation ? _props.row.educationLevelId : "";
// positionPathId.value = resultPath;
// levelId.value = _props.row.levelId;
// positionPathId.value = _props.row.positionPathId;
institute.value = _props.row.institute;
degree.value = _props.row.degree;
field.value = _props.row.field;
@ -646,17 +633,6 @@ const clickCancel = async () => {
`ข้อมูลมีการแก้ไข`,
`ยืนยันยกเลิกการแก้ไขใช่หรือไม่?`
);
// $q.dialog({
// title: ``,
// message: `?`,
// cancel: "",
// ok: "",
// persistent: true,
// }).onOk(async () => {
// edit.value = false;
// await checkRowPage();
// await getData();
// });
} else {
edit.value = false;
await checkRowPage();
@ -692,6 +668,23 @@ const getClass = (val: boolean) => {
"full-width cursor-pointer": !val,
};
};
watch(startDate, (count, prevCount) => {
minDate.value = new Date(`${startDate.value}-01-01`);
});
watch(visibleColumns, (count: String[], prevCount: String[]) => {
changeProfileColumns("education", count);
});
/**
* ทำงานเมอมการเรยกใช Components
*/
onMounted(async () => {
await fetchLevel();
await fetchPositionPath();
rows.value = props.data;
});
</script>
<template>
<q-card flat bordered class="col-12 q-px-lg q-py-md no-border">
@ -783,7 +776,7 @@ const getClass = (val: boolean) => {
option-value="id"
use-input
input-debounce="0"
@filter="(inputValue:any,
@filter="(inputValue:string,
doneFn:Function) => filterSelector(inputValue, doneFn,'levelOptions'
) "
/>
@ -1057,30 +1050,7 @@ const getClass = (val: boolean) => {
</template>
</datepicker>
</div>
<!-- <div class="col-xs-6 col-sm-6 col-md-6">
<selector
:class="getClass(edit)"
:outlined="edit"
dense
lazy-rules
:readonly="!edit"
:borderless="!edit"
v-model="isEducation"
hide-bottom-space
:label="`${'เป็นวุฒิการศึกษาในตำแหน่ง'}`"
@update:modelValue="clickEditRow"
emit-value
map-options
option-label="name"
:options="Ops.positionPathOptions"
option-value="id"
use-input
input-debounce="0"
@filter="(inputValue:any,
doneFn:Function) => filterSelector(inputValue, doneFn,'positionPathOptions'
) "
/>
</div> -->
<div class="col-xs-6 col-sm-6 col-md-6">
<q-input
:class="getClass(edit)"

View file

@ -1,16 +1,24 @@
<script setup lang="ts">
import { ref, onMounted } from "vue";
import type { QForm } from "quasar";
import { useCounterMixin } from "@/stores/mixin";
import { useQuasar } from "quasar";
import type { DataOption } from "@/modules/05_placement/components/PersonalDetail/profileType";
import HeaderTop from "@/modules/05_placement/components/PersonalDetail/Information/top.vue";
import { useRoute } from "vue-router";
import { useCounterMixin } from "@/stores/mixin";
import http from "@/plugins/http";
import config from "@/app.config";
import { useRoute } from "vue-router";
import { FamilyDataDefualt } from "@/modules/05_placement/interface/index/Main";
import type { QForm } from "quasar";
import type { PropType } from "vue";
import type { Family } from "@/modules/05_placement/interface/index/Main";
import { FamilyDataDefualt } from "@/modules/05_placement/interface/index/Main";
import type { DataOption } from "@/modules/05_placement/components/PersonalDetail/profileType";
import HeaderTop from "@/modules/05_placement/components/PersonalDetail/Information/top.vue";
const $q = useQuasar();
const route = useRoute();
const mixin = useCounterMixin();
const { success, messageError, showLoader, hideLoader, dialogConfirm } = mixin;
const props = defineProps({
statusEdit: {
@ -38,29 +46,25 @@ const props = defineProps({
});
const emit = defineEmits(["update:statusEdit"]);
const route = useRoute();
const $q = useQuasar();
const mixin = useCounterMixin();
const {
date2Thai,
success,
messageError,
showLoader,
hideLoader,
dialogConfirm,
} = mixin;
const edit = ref<boolean>(false);
const onEdit = ref<boolean>(false);
const myform = ref<QForm | null>(null);
const familyData = ref<Family>(props.data);
const edit = ref<boolean>(false); //
const onEdit = ref<boolean>(false); //
const familyData = ref<Family>(props.data); //
/**
* งกนแกไขขอม
*/
function checkEdit() {
onEdit.value = true;
}
function filterSelector(val: any, update: Function, refData: string) {
/**
* งกนคนหาขอมลในรายการตวเลอก
* @param val คำคนหา
* @param update งก
* @param refData ประเภทของตวเลอก
*/
function filterSelector(val: string, update: Function, refData: string) {
update(() => {
props.Ops[`${refData}`] = props.OpsFilter[`${refData}`].filter(
(v: DataOption) => v.name.indexOf(val) > -1
@ -121,32 +125,30 @@ async function editData() {
})
.catch((e) => {
messageError($q, e);
hideLoader();
})
.finally(async () => {});
.finally(() => {
hideLoader();
});
});
}
async function saveData() {
await myform.value?.validate().then(async (success: boolean) => {
if (success) {
await editData();
} else {
}
});
}
function selectRadio(e: boolean, i: any) {
/**
* งกนเลอกคสมรส
* @param e , ไมสมรส
*/
function selectRadio(e: boolean) {
onEdit.value = true;
if (e) {
familyData.value.marryPrefixId = "";
familyData.value.marryFirstName = "";
familyData.value.marryLastName = "";
// familyData.value.lastnameCOld = "";
familyData.value.marryOccupation = "";
}
}
/**
* งกนการแกไขขอม
*/
async function changeBtn() {
if (edit.value == true) {
if (props.statusEdit === true) {
@ -159,6 +161,10 @@ async function changeBtn() {
}
}
/**
* งกนสำหรบคนคาชอคลาสตามคาทกำหนด
* @param val าทใชกำหนดคลาส
*/
function getClass(val: boolean) {
return {
"full-width inputgreen cursor-pointer": val,
@ -166,6 +172,9 @@ function getClass(val: boolean) {
};
}
/**
* ทำงานเมอมการเรยกใช Components
*/
onMounted(async () => {
emit("update:statusEdit", false);
});

View file

@ -1,25 +1,40 @@
<!-- card อมลสวนต -->
<script setup lang="ts">
import { ref, onMounted } from "vue";
import { useCounterMixin } from "@/stores/mixin";
import { useQuasar } from "quasar";
import type { PropType } from "vue";
import { useRoute } from "vue-router";
import { useCounterMixin } from "@/stores/mixin";
import { useProfileDataStore } from "@/modules/05_placement/store";
import http from "@/plugins/http";
import config from "@/app.config";
import type {
Information,
DataOption,
} from "@/modules/05_placement/components/PersonalDetail/profileType";
import type { QForm } from "quasar";
import { defaultInformation } from "@/modules/05_placement/components/PersonalDetail/profileType";
import HeaderTop from "@/modules/05_placement/components/PersonalDetail/Information/top.vue";
import http from "@/plugins/http";
import config from "@/app.config";
import { useRoute } from "vue-router";
import { useProfileDataStore } from "@/modules/05_placement/store";
const route = useRoute();
const $q = useQuasar();
const mixin = useCounterMixin();
const profileStore = useProfileDataStore();
const { changeRetireText, changeBirth } = profileStore;
const {
date2Thai,
success,
dateToISO,
messageError,
modalError,
showLoader,
hideLoader,
dialogConfirm,
} = mixin;
import type { QForm } from "quasar";
import type { PropType } from "vue";
const onEdit = ref<boolean>(false);
const props = defineProps({
statusEdit: {
type: Boolean,
@ -46,30 +61,11 @@ const props = defineProps({
});
const emit = defineEmits(["update:statusEdit"]);
const route = useRoute();
const $q = useQuasar();
const mixin = useCounterMixin();
const {
date2Thai,
success,
dateToISO,
messageError,
modalError,
showLoader,
hideLoader,
dialogConfirm,
} = mixin;
const profileStore = useProfileDataStore();
const { changeRetireText, changeBirth } = profileStore;
const edit = ref<boolean>(false);
const informaData = ref<Information>(props.data);
const age = ref<boolean>(true);
const myform = ref<QForm | null>(null);
onMounted(async () => {
emit("update:statusEdit", false);
});
const onEdit = ref<boolean>(false); //
const edit = ref<boolean>(false); //
const informaData = ref<Information>(props.data); //
const age = ref<boolean>(true); //
const onCancel = async () => {
if (myform.value != null) {
@ -92,7 +88,13 @@ const onCancel = async () => {
}
};
const filterSelector = (val: any, update: Function, refData: string) => {
/**
* งกนคนหาขอมลในรายการตวเลอก
* @param val คำคนหา
* @param update งก
* @param refData ประเภทของตวเลอก
*/
const filterSelector = (val: string, update: Function, refData: string) => {
switch (refData) {
case "prefixOps":
update(() => {
@ -149,12 +151,20 @@ const filterSelector = (val: any, update: Function, refData: string) => {
}
};
/**
* งกเลอกวนเดอนปเก
* @param modelData นเดอนปเก
*/
const handleDate = async (modelData: Date) => {
informaData.value.dateOfBirth = modelData;
await calRetire(modelData);
onEdit.value = true;
};
/**
* งกนคำนวนวนเกษยณอายราชการ
* @param birth นเดอนปเก
*/
const calRetire = async (birth: Date) => {
const body = {
birthDate: dateToISO(birth),
@ -179,13 +189,16 @@ const calRetire = async (birth: Date) => {
});
};
/**
* นทกการแกไขขอม
*/
const editData = async () => {
dialogConfirm($q, async () => {
if (age.value == false) {
modalError($q, "พบข้อผิดพลาด", "วันเกิดไม่ถูกต้อง");
return;
}
showLoader();
const body: any = {
citizenId: informaData.value.idCard,
prefix: informaData.value.prefixId,
@ -215,11 +228,16 @@ const editData = async () => {
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
hideLoader();
});
});
};
/**
* งกนการแกไขขอม
*/
const changeBtn = async () => {
if (edit.value == true) {
if (props.statusEdit === true) {
@ -232,6 +250,17 @@ const changeBtn = async () => {
}
};
/**
* งกนแกไขขอม
*/
function checkEdit() {
onEdit.value = true;
}
/**
* งกนสำหรบคนคาชอคลาสตามคาทกำหนด
* @param val าทใชกำหนดคลาส
*/
const getClass = (val: boolean) => {
return {
"full-width inputgreen cursor-pointer": val,
@ -239,9 +268,12 @@ const getClass = (val: boolean) => {
};
};
function checkEdit() {
onEdit.value = true;
}
/**
* ทำงานเมอมการเรยกใช Components
*/
onMounted(async () => {
emit("update:statusEdit", false);
});
</script>
<template>
<q-card flat bordered class="col-12 q-px-lg q-py-md no-border">
@ -300,7 +332,7 @@ function checkEdit() {
:label="`${'คำนำหน้า'}`"
use-input
input-debounce="0"
@filter="(inputValue:any,
@filter="(inputValue:string,
doneFn:Function) => filterSelector(inputValue, doneFn,'prefixOps'
) "
/>
@ -417,7 +449,7 @@ function checkEdit() {
:label="`${'เพศ'}`"
use-input
input-debounce="0"
@filter="(inputValue:any,
@filter="(inputValue:string,
doneFn:Function) => filterSelector(inputValue, doneFn,'genderOps'
) "
/>
@ -443,7 +475,7 @@ function checkEdit() {
:label="`${'สถานภาพ'}`"
use-input
input-debounce="0"
@filter="(inputValue:any,
@filter="(inputValue:string,
doneFn:Function) => filterSelector(inputValue, doneFn,'statusOps'
) "
/>
@ -468,7 +500,7 @@ function checkEdit() {
:label="`${'หมู่เลือด'}`"
use-input
input-debounce="0"
@filter="(inputValue:any,
@filter="(inputValue:string,
doneFn:Function) => filterSelector(inputValue, doneFn,'bloodOps'
) "
/>
@ -524,7 +556,7 @@ function checkEdit() {
:label="`${'ศาสนา'}`"
use-input
input-debounce="0"
@filter="(inputValue:any,
@filter="(inputValue:string,
doneFn:Function) => filterSelector(inputValue, doneFn,'religionOps'
) "
/>

View file

@ -1,17 +1,17 @@
<script setup lang="ts">
import { ref, onMounted } from "vue";
import { useQuasar } from "quasar";
import { useCounterMixin } from "@/stores/mixin";
import { useRoute } from "vue-router";
import HeaderTop from "@/modules/05_placement/components/PersonalDetail/Information/top.vue";
import { useCounterMixin } from "@/stores/mixin";
import http from "@/plugins/http";
import config from "@/app.config";
import type { PropType } from "vue";
import type { Property } from "@/modules/05_placement/interface/index/Main";
import HeaderTop from "@/modules/05_placement/components/PersonalDetail/Information/top.vue";
const $q = useQuasar();
const mixin = useCounterMixin();
const route = useRoute();
@ -33,13 +33,12 @@ const props = defineProps({
});
const emit = defineEmits(["update:statusEdit", "update:data"]);
const edit = ref<boolean>(false);
const onEdit = ref<boolean>(false);
onMounted(() => {
emit("update:statusEdit", false);
});
const edit = ref<boolean>(false); //
const onEdit = ref<boolean>(false); //
/**
* งกนบนทกการแกไขขอม
*/
const saveData = async () => {
dialogConfirm($q, async () => {
showLoader();
@ -57,11 +56,16 @@ const saveData = async () => {
})
.catch((e: any) => {
messageError($q, e);
})
.finally(() => {
hideLoader();
});
});
};
/**
* งกนการแกไขขอม
*/
const changeBtn = async () => {
if (edit.value == true) {
if (props.statusEdit === true) {
@ -91,9 +95,19 @@ const onCancel = async () => {
}
};
/**
* งกนแกไขขอม
*/
function checkEdit() {
onEdit.value = true;
}
/**
* ทำงานเมอมการเรยกใช Components
*/
onMounted(() => {
emit("update:statusEdit", false);
});
</script>
<template>
<q-form ref="myform" greedy @submit.prevent @validation-success="saveData">

View file

@ -49,12 +49,18 @@ const emit = defineEmits([
"update:editvisible",
]);
const updateEdit = (value: Boolean) => {
emit("update:editvisible", value);
};
/**
* งกนอปเดทคำคนหา
* @param value คำคนหา
*/
const updateInput = (value: string | number | null) => {
emit("update:inputfilter", value);
};
/**
* งกนอปเดท Visible
* @param value Visible
*/
const updateVisible = (value: []) => {
emit("update:inputvisible", value);
};
@ -63,20 +69,13 @@ const paginationLabel = (start: string, end: string, total: string) => {
return start + "-" + end + " ใน " + total;
};
/**
* งกนเพมขอม
*/
const checkAdd = () => {
props.add();
};
const edit = async () => {
updateEdit(!props.editvisible);
props.edit();
};
const cancel = async () => {
updateEdit(!props.editvisible);
props.cancel();
};
const resetFilter = () => {
// reset X
emit("update:inputfilter", "");

View file

@ -1,65 +0,0 @@
<!-- card รวม อมลสวนต อย -->
<script setup lang="ts">
import { ref, onMounted, watch } from "vue";
import Information from "@/modules/05_placement/components/PersonalDetail/Information/Information.vue";
import Address from "@/modules/05_placement/components/PersonalDetail/Information/Address.vue";
import { useCounterMixin } from "@/stores/mixin";
const props = defineProps({
statusEdit: {
type: Boolean,
required: true,
},
profileType: {
type: String,
required: true,
},
});
const emit = defineEmits(["update:statusEdit"]);
const mixin = useCounterMixin();
const { showLoader, hideLoader } = mixin;
const statusEdit = ref<boolean>(false);
const modalNoEdit = ref<boolean>(false);
const modalNoEditTittle = ref<string>("ไม่สามารถไม่สามารถแก้ไขข้อมูลได้?");
const modalNoEditDetail = ref<string>("มีข้อมูลที่ยังไม่ถูกบันทึกข้อมูล");
watch(statusEdit, (count: boolean, prevCount: boolean) => {
emit("update:statusEdit", count);
});
watch(props, (count: any, prevCount: any) => {
statusEdit.value = props.statusEdit;
});
onMounted(() => {
// hideLoader();
});
const notiNoEdit = () => {
modalNoEdit.value = true;
};
const closeModalError = () => {
modalNoEdit.value = false;
};
</script>
<template>
<div class="row col-12 items-center">
<div>
<Information :notiNoEdit="notiNoEdit" v-model:statusEdit="statusEdit" />
</div>
<div class="col-12 q-px-md"><q-separator size="4px" /></div>
<div>
<Address :notiNoEdit="notiNoEdit" v-model:statusEdit="statusEdit" />
</div>
</div>
</template>
<style lang="scss" scoped>
.horizontal-line {
background-color: #f4f4f4;
height: 5px;
}
</style>

View file

@ -13,18 +13,17 @@ import { useCounterMixin } from "@/stores/mixin";
const { date2Thai } = useCounterMixin();
/** props*/
const selected = defineModel("selectedPos", { required: true });
const positionId = defineModel<string>("positionId", { required: true });
const seletcId = defineModel<string>("seletcId", { required: true });
const date = defineModel<Date>("datePos", { required: true });
const positionData = defineModel<any[]>("position", { required: true });
const isAll = defineModel<boolean>("isAll", { required: true });
const isBlank = defineModel<boolean>("isBlank", { required: true });
const selected = defineModel("selectedPos", { required: true }); //
const positionId = defineModel<string>("positionId", { required: true }); //id
const seletcId = defineModel<string>("seletcId", { required: true }); //
const date = defineModel<Date>("datePos", { required: true }); //
const positionData = defineModel<any[]>("position", { required: true }); //
const isAll = defineModel<boolean>("isAll", { required: true }); //
const isBlank = defineModel<boolean>("isBlank", { required: true }); //
const filters = ref<string>("");
const rowsPosition = ref<Positions[]>([]);
/** columns*/
//Table
const filters = ref<string>(""); //
const rowsPosition = ref<Positions[]>([]); //
const columns = ref<QTableProps["columns"]>([
{
name: "isPosition",
@ -90,7 +89,6 @@ const columns = ref<QTableProps["columns"]>([
style: "font-size: 14px",
},
]);
const columnsPostition = ref<QTableProps["columns"]>([
{
name: "no",
@ -165,7 +163,6 @@ const columnsPostition = ref<QTableProps["columns"]>([
style: "font-size: 14px",
},
]);
const visibleColumns = ref<string[]>([
"isPosition",
"no",
@ -195,10 +192,12 @@ async function onClickSelectPos(id: string) {
(e) => e.id === seletcId.value
);
}
console.log(selected.value);
}
}
/**
* ทำงานเม Components กเรยกใชงาน
*/
onMounted(async () => {
if (positionId.value) {
setTimeout(async () => {

View file

@ -1,22 +1,24 @@
<script setup lang="ts">
import { ref, watch } from "vue";
import { useQuasar } from "quasar";
import { useCounterMixin } from "@/stores/mixin";
import type { QTableProps } from "quasar";
import DialogHeader from "@/components/DialogHeader.vue";
import { useCounterMixin } from "@/stores/mixin";
import http from "@/plugins/http";
import config from "@/app.config";
import type { QTableProps } from "quasar";
import type { DataEducation } from "@/modules/05_placement/interface/index/Main";
import type {
DataPerson,
Education,
} from "@/modules/05_placement/interface/response/Main";
import DialogHeader from "@/components/DialogHeader.vue";
const $q = useQuasar();
const mixin = useCounterMixin(); //
const { showLoader, hideLoader, date2Thai, messageError } = mixin;
const rows = ref<any[]>([]);
const myForm = ref<any>([]);
const selection = ref<any>([]);
const personalForm = ref<any>([]);
/** รับค่ามาจากหน้าหลัก */
const props = defineProps({
Modal: Boolean,
@ -34,6 +36,9 @@ const props = defineProps({
},
});
const rows = ref<DataEducation[]>([]);
const personalForm = ref<DataPerson>();
/**หัวตาราง */
const columns = ref<QTableProps["columns"]>([
{
@ -78,16 +83,18 @@ const columns = ref<QTableProps["columns"]>([
},
]);
/** get ข้อมูลการศึกษา */
/**
* งกนดงขอมลรายละเอยด
*/
async function fetchData() {
showLoader();
await http
.get(config.API.getDatapersonal(props.personalId))
.then((res) => {
personalForm.value = res.data.result;
personalForm.value.education.map((e: any) => {
personalForm.value?.education.map((e: Education) => {
rows.value.push({
university: e.name,
university: e.institute,
degree: e.degree,
major: e.field,
graduation: date2Thai(e.finishDate),
@ -103,8 +110,8 @@ async function fetchData() {
}
/**
* convert text
* @param val type
* งกนแปลงประเภทขาราชการ เปนไทย
* @param val ประเภทขาราชการ
*/
function formBmaofficer(val: string) {
switch (val) {
@ -119,14 +126,17 @@ function formBmaofficer(val: string) {
}
}
/** ปิด POPUP ข้อมูล */
/**
* POPUP อม
*/
async function close() {
props.close();
selection.value = [];
rows.value = [];
}
/** เมื่อ props.Modal จะเรียกข้อมูลการศึกษา */
/**
* เม props.Modal เป true จะเรยกขอมลการศกษา
*/
watch(props, () => {
if (props.Modal === true) {
fetchData();
@ -136,9 +146,9 @@ watch(props, () => {
<template>
<q-dialog v-model="props.Modal" persistent>
<q-card style="max-width: 100%; width: 80%">
<q-form ref="myForm">
<q-form>
<DialogHeader
:tittle="`รายละเอียดของ ${personalForm.fullName}`"
:tittle="`รายละเอียดของ ${personalForm?.fullName}`"
:close="close"
/>
@ -150,7 +160,7 @@ watch(props, () => {
<div class="row items-center q-pa-xs header-text">
อมลทวไป
<span
v-if="personalForm.bmaOfficer != null"
v-if="personalForm?.bmaOfficer != null"
class="check-officer"
>
<q-icon name="mdi-check" />
@ -166,10 +176,10 @@ watch(props, () => {
<div class="col-4 sub-text">
<div class="q-pb-md">
{{ personalForm.idCard }}
{{ personalForm?.idCard }}
</div>
<div>
{{ date2Thai(personalForm.dateOfBirth) }}
{{ date2Thai(personalForm?.dateOfBirth) }}
</div>
</div>
@ -179,10 +189,10 @@ watch(props, () => {
</div>
<div class="col-3 sub-text">
<div class="q-pb-md">
{{ personalForm.fullName }}
{{ personalForm?.fullName }}
</div>
<div>
{{ personalForm.gender }}
{{ personalForm?.gender }}
</div>
</div>
</div>
@ -195,7 +205,7 @@ watch(props, () => {
<div class="row q-pa-xs">
<div class="col-3 header-sub-text">อย</div>
<div class="col-9 sub-text">
{{ personalForm.address }}
{{ personalForm?.registAddress }}
</div>
</div>
</q-card>
@ -233,10 +243,10 @@ watch(props, () => {
</div>
<div class="col-5 sub-text-exam">
<div class="q-pb-sm">
{{ personalForm.pass }}
{{ personalForm?.pass }}
</div>
<div class="q-pb-sm">{{ personalForm.examNumber }}</div>
<div class="q-pb-sm">{{ personalForm.examRound }}</div>
<div class="q-pb-sm">{{ personalForm?.examNumber }}</div>
<div class="q-pb-sm">{{ personalForm?.examRound }}</div>
</div>
</div>
</div>

View file

@ -1,32 +1,30 @@
<script setup lang="ts">
import { onMounted, ref } from "vue";
import { useRouter, useRoute } from "vue-router";
import { tokenParsed } from "@/plugins/auth";
import { useQuasar } from "quasar";
import { tokenParsed } from "@/plugins/auth";
import { useRouter, useRoute } from "vue-router";
import { useCounterMixin } from "@/stores/mixin";
import { usePlacementDataStore } from "@/modules/05_placement/store";
import http from "@/plugins/http";
import config from "@/app.config";
import { useCounterMixin } from "@/stores/mixin";
import { useQuasar } from "quasar";
import { usePlacementDataStore } from "@/modules/05_placement/store";
import CardTop from "@/modules/05_placement/components/PersonalList/StatCard.vue";
import AddTablePosition from "@/modules/05_placement/components/PersonalList/Table.vue";
const DataStore = usePlacementDataStore();
let roleAdmin = ref<boolean>(false);
const $q = useQuasar;
const mixin = useCounterMixin();
const { messageError, showLoader, hideLoader } = mixin;
const $q = useQuasar();
const router = useRouter();
const route = useRoute();
const mixin = useCounterMixin();
const DataStore = usePlacementDataStore();
const { messageError, showLoader, hideLoader } = mixin;
const examId = route.params.examId;
const year = ref<string>("");
const round = ref<string>("");
const title = ref<string>("");
const examData = ref<any>();
const roleAdmin = ref<boolean>(false);
const stat = ref<any>({
total: 0,
unContain: 0,
@ -35,7 +33,9 @@ const stat = ref<any>({
disclaim: 0,
});
/** เรียกข้อมูล Stat */
/**
* เรยกขอม Stat
*/
async function getStat() {
const examIdString = Array.isArray(examId) ? examId[0] : examId;
await http
@ -56,7 +56,9 @@ async function getStat() {
});
}
/** get รายละเอียด ของการสอบ */
/**
* get รายละเอยด ของการสอบ
*/
async function fetchPlacementData() {
showLoader();
await http

View file

@ -16,13 +16,23 @@ import type { QTableProps } from "quasar";
import type { DataList } from "@/modules/05_placement/interface/response/SelectOrg";
import DialogSelectOrg from "@/modules/05_placement/components/PersonalList/DialogSelectOrg.vue";
import Table from "@/modules/05_placement/components/PersonalList/TableView.vue";
import DialogCard from "@/modules/05_placement/components/PersonalList/DialogDetail.vue";
import DialogFooter from "@/modules/05_placement/components/PersonalList/DialogFooter.vue";
import DialogHeader from "@/components/DialogHeader.vue";
let roleAdmin = ref<boolean>(false);
const route = useRoute();
const mixin = useCounterMixin(); //
const $q = useQuasar(); // show dialog
const {
messageError,
showLoader,
hideLoader,
dateText,
success,
dialogConfirm,
date2Thai,
} = mixin;
/** รับค่ามาจากหน้าหลัก */
const props = defineProps({
@ -32,6 +42,7 @@ const props = defineProps({
},
});
let roleAdmin = ref<boolean>(false);
const edit = ref<boolean>(true);
const modal = ref<boolean>(false); //modal +
const editRow = ref<boolean>(false); //
@ -49,8 +60,7 @@ const rows = ref<any[]>([]);
const rowsFilter = ref<any>([]);
const myForm = ref<any>();
const files = ref<any>(null);
const mixin = useCounterMixin(); //
const $q = useQuasar(); // show dialog
const appointModal = ref<boolean>(false);
const getNumFile = ref(0);
const dataRes = ref<any>([]);
@ -69,25 +79,12 @@ const checkSelected = computed(() => {
return true;
}
});
const pagination = ref({
page: 1,
rowsPerPage: 10,
});
const dataInfo = reactive({
reason: "",
reliefDoc: "",
});
const {
messageError,
showLoader,
hideLoader,
dateText,
success,
dialogConfirm,
date2Thai,
} = mixin;
const route = useRoute();
const examId = route.params.examId;
const examIdString = Array.isArray(examId) ? examId[0] : examId;
const personalId = ref<string>("");
@ -251,6 +248,10 @@ function convertContainStatus(val: string, type: string = "") {
}
}
/**
* แปลงสถานะ
* @param val type
*/
function convertTypeCommand(val: string) {
switch (val) {
case "APPOINTED":
@ -281,7 +282,9 @@ function convertDraft(val: boolean) {
}
}
/**เรียกข้อมูลรายชื่อผู้สอบผ่าน */
/**
* เรยกขอมลรายชอผสอบผาน
*/
async function getTable() {
showLoader();
await http
@ -389,7 +392,9 @@ async function getTable() {
});
}
/**ยืนยันการผ่อนผัน */
/**
* นยนการผอนผ
*/
async function saveDeferment() {
myForm.value.validate().then(async (result: boolean) => {
if (result) {
@ -402,7 +407,9 @@ async function saveDeferment() {
}
});
}
/**post ผ่อนผัน */
/**
* post อนผ
*/
async function postDeferment() {
showLoader();
const formData = new FormData();
@ -425,7 +432,9 @@ async function postDeferment() {
});
}
/**ยืนยันการสละสิทธิ์ */
/**
* นยนการสละสทธ
*/
async function saveDisclaim() {
myForm.value.validate().then(async (result: boolean) => {
if (result) {
@ -439,7 +448,9 @@ async function saveDisclaim() {
});
}
/**post การสละสิทธิ์ */
/**
* post การสละสทธ
*/
async function postDisclaimf() {
showLoader();
const dataPost = {
@ -462,12 +473,16 @@ async function postDisclaimf() {
});
}
/** เปิด dialog */
/**
* dialog
*/
function clickEditRow() {
editRow.value = true;
}
/** เปลี่ยน class true/false */
/**
* เปลยน class true/false
*/
function getClass(val: boolean) {
return {
"full-width inputgreen cursor-pointer ": val,
@ -553,26 +568,23 @@ function openAppointModal(
data: DataList,
typeCommandVal: "APPOINTED" | "APPOINT" | "SLIP" | "MOVE"
) {
// appointModal.value = true;
// personalId.value = pid;
// personal.value = dataRes.value.filter(
// (e: any) => e.personalId == personalId.value
// );
// console.log(personal.value);
dataRow.value = data;
typeCommand.value = typeCommandVal;
modalDialogSelectOrg.value = !modalDialogSelectOrg.value;
}
/** close dialog */
/**
* close dialog
*/
async function clickCloseModalTree() {
await getTable();
appointModal.value = false;
props.statCard();
}
/** validate */
/**
* validate
*/
async function validateData() {
checkValidate.value = true;
await myForm.value.validate().then((result: boolean) => {
@ -582,12 +594,16 @@ async function validateData() {
});
}
/** ปิด dialog */
/**
* dialog
*/
function clickCloseSendModal() {
modaladdlist.value = false;
}
/** validate */
/**
* validate
*/
async function clickClose() {
userNote.value = "";
if (editRow.value == true) {
@ -610,7 +626,9 @@ async function clickClose() {
}
}
/** ยืนยันส่งรายชื่อไปหน่วยงาน */
/**
* นยนสงรายชอไปหนวยงาน
*/
function savelist() {
selected.value.map((e: any) => {
personal_selected.value.push(e.personalId);
@ -654,14 +672,6 @@ function paginationLabel(start: number, end: number, total: number) {
else return start + "-" + end + " ใน " + total;
}
watch(containStatus, () => {
if (containStatus.value) {
rows.value = rowsAll.value.filter((x: any) => x.statusId == "CONTAIN");
} else {
rows.value = rowsAll.value.filter((x: any) => x.statusId != "CONTAIN");
}
});
function onRestorePos(id: string) {
dialogConfirm(
$q,
@ -713,6 +723,14 @@ function onSubmitDate() {
});
}
watch(containStatus, () => {
if (containStatus.value) {
rows.value = rowsAll.value.filter((x: any) => x.statusId == "CONTAIN");
} else {
rows.value = rowsAll.value.filter((x: any) => x.statusId != "CONTAIN");
}
});
onMounted(async () => {
const user = await tokenParsed();
if (user) {
@ -754,7 +772,7 @@ onMounted(async () => {
:boss="true"
:saveNoDraft="true"
:role-admin="roleAdmin"
:displayAdd="displayAdd"
:display-add="displayAdd"
row-key="fullname"
>
<template #columns="props">
@ -1382,24 +1400,6 @@ onMounted(async () => {
</div>
</q-item-section>
</q-item>
<!-- <div class="row col-12 text-no-wrap items-center">
<img
v-if="props.row.avatar == ''"
src="@/assets/avatar_user.jpg"
class="col-4 img-info"
/>
<img
v-else
:src="props.row.avatar"
class="col-4 img-info"
/>
<div class="col-4">
<div class="text-weight-medium">{{ props.row.name }}</div>
<div class="text-weight-light">
{{ props.row.idCard }}
</div>
</div>
</div> -->
</template>
<template v-else-if="col.name === 'examNumber'">
<div class="text-weight-medium">
@ -1482,17 +1482,6 @@ onMounted(async () => {
</q-td>
</q-tr>
</template>
<!-- <template v-slot:pagination="scope">
<q-pagination
v-model="pagination.page"
color="primary"
:max="scope.pagesNumber"
:max-pages="5"
size="sm"
boundary-links
direction-links
></q-pagination>
</template> -->
</d-table>
</q-card-section>
<q-separator />
@ -1513,10 +1502,10 @@ onMounted(async () => {
<!-- เลอกหนวยงานทบรรจ -->
<DialogSelectOrg
v-model:modal="modalDialogSelectOrg"
:dataRow="dataRow"
:fetchTable="getTable"
:fetchStatCard="statCard"
:typeCommand="typeCommand"
:data-row="dataRow"
:fetch-table="getTable"
:fetch-stat-card="statCard"
:type-command="typeCommand"
/>
<!-- dialog นรายงานต-->

View file

@ -1,927 +0,0 @@
<script setup lang="ts">
import { ref, onMounted, reactive, watch } from "vue";
import { useCounterMixin } from "@/stores/mixin";
import { useQuasar } from "quasar";
import http from "@/plugins/http";
import config from "@/app.config";
import { useRouter } from "vue-router";
import type { QForm } from "quasar";
import { useProfileDataStore } from "@/modules/08_registryEmployee/store";
import type {
Information,
DataOption,
DataOptioninfo,
} from "@/modules/04_registry/components/profileType";
import type {
InformationOps,
FormAddPerson,
DataType,
} from "@/modules/04_registry/interface/index/Main";
import HeaderTop from "@/modules/08_registryEmployee/components/AddEmployee/HeaderTop.vue";
const retireDate = ref<Date>();
const router = useRouter();
const $q = useQuasar();
const mixin = useCounterMixin();
const {
date2Thai,
success,
dateToISO,
messageError,
dialogMessageNotify,
showLoader,
hideLoader,
dialogConfirm,
} = mixin;
const profileStore = useProfileDataStore();
const { changeRetireText } = profileStore;
const age = ref<string | null>("");
const informaData = ref<FormAddPerson>({
prefix: "",
firstName: "",
lastName: "",
citizenId: "",
birthDate: null,
age: null,
genderId: null,
bloodId: null,
nationality: null,
ethnicity: null,
statusId: null,
religionId: null,
tel: null,
employeeType: null,
employeeClass: null,
profileType: null,
});
const dateBefore = ref<Date>(new Date());
//
const Ops = ref<InformationOps>({
prefixOps: [],
prefixOldOps: [],
genderOps: [],
bloodOps: [],
statusOps: [],
religionOps: [],
employeeClassOps: [],
employeeTypeOps: [],
});
//
const OpsFilter = ref<InformationOps>({
prefixOps: [],
prefixOldOps: [],
genderOps: [],
bloodOps: [],
statusOps: [],
religionOps: [],
employeeClassOps: [],
employeeTypeOps: [],
});
/*** get รายการข้อมูลเกี่ยวกับบุคคล (dropdown list) */
const fetchPerson = async () => {
showLoader();
await http
.get(config.API.profileNewMetaMain)
.then((res) => {
const data = res.data.result;
let optionbloodGroups: DataOption[] = [];
data.bloodGroups.map((r: DataOptioninfo) => {
optionbloodGroups.push({
id: r.id.toString(),
name: r.name.toString(),
});
});
Ops.value.bloodOps = optionbloodGroups;
OpsFilter.value.bloodOps = optionbloodGroups;
let optiongenders: DataOption[] = [];
data.genders.map((r: DataOptioninfo) => {
optiongenders.push({
id: r.id.toString(),
name: r.name.toString(),
});
});
Ops.value.genderOps = optiongenders;
OpsFilter.value.genderOps = optiongenders;
let optionprefixs: DataOption[] = [];
optionprefixs = data.prefixs.map((v: any) => ({
id: v.id,
name: v.name,
}));
Ops.value.prefixOps = optionprefixs;
OpsFilter.value.prefixOps = optionprefixs;
let optionrelationships: DataOption[] = [];
data.relationships.map((r: DataOptioninfo) => {
optionrelationships.push({
id: r.id.toString(),
name: r.name.toString(),
});
});
Ops.value.statusOps = optionrelationships;
OpsFilter.value.statusOps = optionrelationships;
let optionreligions: DataOption[] = [];
data.religions.map((r: DataOptioninfo) => {
optionreligions.push({
id: r.id.toString(),
name: r.name.toString(),
});
});
Ops.value.religionOps = optionreligions;
OpsFilter.value.religionOps = optionreligions;
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
hideLoader();
});
};
// profile
const inputImage = ref<any>(null);
const image = ref<any>(null);
const fileData = ref<any>(null);
const uploadImage = async (e: any) => {
const input = e.target.files;
if (input.length > 0) {
const url = URL.createObjectURL(input[0]);
image.value = url;
fileData.value = input[0];
}
};
// profile
const addNewImage = async () => {
inputImage.value.click();
};
//
const defaultCitizenData = ref<string>("");
const changeCardID = async (value: string | number | null) => {
if (value != null && typeof value == "string") {
if (value.length == 13 && value != defaultCitizenData.value) {
await checkCitizen(value);
}
}
};
/**
* function เชคเลขประจำตวประชาชนช
* @param id เลขประจำตวประชาชน
*/
const checkCitizen = async (id: string) => {
showLoader();
await http
.put(config.API.profileNewCitizenId(id), {
citizenId: id,
})
.then(() => {})
.catch((err) => {
if (err.response.data.status === 500) {
dialogMessageNotify($q, err.response.data.message);
} else {
messageError($q, err);
}
})
.finally(() => {
hideLoader();
});
};
// filter list
const filterSelector = (val: any, update: Function, refData: string) => {
switch (refData) {
case "prefixOps":
update(() => {
Ops.value.prefixOps = OpsFilter.value.prefixOps.filter(
(v: DataOption) => v.name.indexOf(val) > -1
);
});
break;
case "genderOps":
update(() => {
Ops.value.genderOps = OpsFilter.value.genderOps.filter(
(v: DataOption) => v.name.indexOf(val) > -1
);
});
break;
case "bloodOps":
update(() => {
Ops.value.bloodOps = OpsFilter.value.bloodOps.filter(
(v: DataOption) => v.name.indexOf(val) > -1
);
});
break;
case "statusOps":
update(() => {
Ops.value.statusOps = OpsFilter.value.statusOps.filter(
(v: DataOption) => v.name.indexOf(val) > -1
);
});
break;
case "religionOps":
update(() => {
Ops.value.religionOps = OpsFilter.value.religionOps.filter(
(v: DataOption) => v.name.indexOf(val) > -1
);
});
break;
default:
break;
}
};
// max date
const calculateMaxDate = () => {
const today = new Date();
today.setFullYear(today.getFullYear() - 18);
return today;
};
// post api
const onSubmit = async () => {
const formData = new FormData();
if (fileData.value != null) formData.append("File", fileData.value); //
if (informaData.value.citizenId != undefined)
formData.append("citizenId", informaData.value.citizenId);
if (informaData.value.prefix != undefined)
formData.append("prefix", informaData.value.prefix);
if (informaData.value.firstName != undefined)
formData.append("firstName", informaData.value.firstName);
if (informaData.value.lastName != undefined)
formData.append("lastName", informaData.value.lastName);
if (informaData.value.genderId != undefined)
formData.append("gender", informaData.value.genderId);
if (informaData.value.nationality != undefined)
formData.append("nationality", informaData.value.nationality);
if (informaData.value.ethnicity != undefined)
formData.append("race", informaData.value.ethnicity);
if (informaData.value.religionId != undefined)
formData.append("religion", informaData.value.religionId);
if (informaData.value.birthDate != undefined)
formData.append(
"birthDate",
dateToISO(informaData.value.birthDate) ?? dateToISO(new Date())
);
if (informaData.value.bloodId != undefined)
formData.append("bloodGroup", informaData.value.bloodId);
if (informaData.value.statusId != undefined)
formData.append("relationship", informaData.value.statusId);
if (informaData.value.tel != undefined)
formData.append("telephoneNumber", informaData.value.tel);
if (informaData.value.employeeType != undefined)
formData.append("employeeType", informaData.value.employeeType);
if (informaData.value.employeeClass != undefined)
formData.append("employeeClass", informaData.value.employeeClass);
dialogConfirm($q, async () => {
showLoader();
await http
.post(config.API.receiveData(), formData)
.then(async (res) => {
success($q, "บันทึกข้อมูลสำเร็จ");
await clickBack();
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
hideLoader();
});
});
};
// back
const clickBack = () => {
router.push("/placement/receive");
};
function calculateAge(birthDate: Date | null) {
if (!birthDate) return null;
const birthDateTimeStamp = new Date(birthDate).getTime();
const now = new Date();
const diff = now.getTime() - birthDateTimeStamp;
const ageDate = new Date(diff);
const years = ageDate.getUTCFullYear() - 1970;
const months = ageDate.getUTCMonth();
const days = ageDate.getUTCDate() - 1;
const retire = new Date(birthDate);
retire.setFullYear(retire.getFullYear() + 60);
retireDate.value = retire;
if (years > 60) {
return "อายุเกิน 60 ปี";
}
return `${years} ปี ${months} เดือน ${days} วัน`;
}
watch(
() => informaData.value.birthDate,
(v) => {
if (v) {
age.value = calculateAge(v);
}
}
);
onMounted(async () => {
await fetchPerson();
});
</script>
<template>
<!-- <q-card flat bordered class="col-12 q-px-lg q-py-md">
<HeaderTop header="ข้อมูลส่วนตัว" icon="mdi-account" />
<q-form ref="myform" class="col-12 q-pt-md">
<div class="row">
<div class="row col-12 q-col-gutter-x-sm q-mb-xs">
<div class="col-xs-6 col-sm-3 col-md-3">
<q-input
hide-bottom-space
outlined
v-model="informaData.citizenId"
dense
@update:model-value="changeCardID"
lazy-rules
:rules="[
(val: string) => !!val || `${'กรุณากรอก เลขประจำตัวประชาชน'}`,
(val: string) =>
val.length >= 13 ||
`${'กรุณากรอกเลขประจำตัวประชาชนให้ครบ'}`,
]"
label="เลขประจำตัวประชาชน"
maxlength="13"
mask="#############"
/>
</div>
<div class="col-xs-6 col-sm-3 col-md-3">
<selector
hide-bottom-space
outlined
:rules="[(val: string) => !!val || `${'กรุณาเลือก คำนำหน้าชื่อ'}`]"
dense
lazy-rules
v-model="informaData.prefix"
emit-value
map-options
option-label="name"
:options="Ops.prefixOps"
option-value="id"
:label="`${'คำนำหน้าชื่อ'}`"
use-input
input-debounce="0"
@filter="(inputValue: any, doneFn: Function) => filterSelector(inputValue, doneFn, 'prefixOps')"
/>
</div>
<div class="col-xs-6 col-sm-3 col-md-3">
<q-input
hide-bottom-space
outlined
dense
lazy-rules
v-model="informaData.firstName"
:rules="[(val: string) => !!val || `${'กรุณากรอก ชื่อ'}`]"
:label="`${'ชื่อ'}`"
/>
</div>
<div class="col-xs-6 col-sm-3 col-md-3">
<q-input
hide-bottom-space
outlined
dense
lazy-rules
v-model="informaData.lastName"
:rules="[(val: string) => !!val || `${'กรุณากรอก นามสกุล'}`]"
:label="`${'นามสกุล'}`"
/>
</div>
</div>
<div class="row col-12 q-col-gutter-x-sm q-mb-xs">
<div class="col-xs-6 col-sm-2 col-md-2">
<datepicker
v-model="informaData.birthDate"
:locale="'th'"
autoApply
:enableTimePicker="false"
week-start="0"
:max-date="calculateMaxDate()"
@update:model-value="handleDate"
>
<template #year="{ year }">
{{ year + 543 }}
</template>
<template #year-overlay-value="{ value }">
{{ parseInt(value + 543) }}
</template>
<template #trigger>
<q-input
hide-bottom-space
outlined
dense
lazy-rules
:model-value="
informaData.birthDate == null
? null
: date2Thai(informaData.birthDate)
"
:rules="[(val: string) => !!val || `${'กรุณาเลือก วัน/เดือน/ปี เกิด'}`]"
:label="`${'วัน/เดือน/ปี เกิด'}`"
>
<template v-slot:prepend>
<q-icon
name="event"
class="cursor-pointer"
style="color: var(--q-primary)"
>
</q-icon>
</template>
</q-input>
</template>
</datepicker>
</div>
<div class="col-xs-6 col-sm-2 col-md-2">
<q-input
hide-bottom-space
dense
lazy-rules
readonly
borderless
style="padding: 0 12px"
:model-value="informaData.age"
:label="`${'อายุ'}`"
/>
</div>
<div class="col-xs-6 col-sm-2 col-md-2">
<selector
hide-bottom-space
outlined
dense
lazy-rules
v-model="informaData.genderId"
emit-value
map-options
option-label="name"
:options="Ops.genderOps"
option-value="id"
:label="`${'เพศ'}`"
use-input
input-debounce="0"
@filter="(inputValue: any,
doneFn: Function) => filterSelector(inputValue, doneFn, 'genderOps'
)"
/>
</div>
<div class="col-xs-6 col-sm-2 col-md-2">
<selector
hide-bottom-space
outlined
dense
lazy-rules
v-model="informaData.statusId"
emit-value
map-options
option-label="name"
:options="Ops.statusOps"
option-value="id"
:label="`${'สถานภาพ'}`"
use-input
input-debounce="0"
@filter="(inputValue: any,
doneFn: Function) => filterSelector(inputValue, doneFn, 'statusOps'
)"
/>
</div>
<div class="col-xs-6 col-sm-2 col-md-2">
<q-input
hide-bottom-space
outlined
dense
lazy-rules
v-model="informaData.nationality"
:label="`${'สัญชาติ'}`"
/>
</div>
<div class="col-xs-6 col-sm-2 col-md-2">
<q-input
hide-bottom-space
outlined
dense
lazy-rules
v-model="informaData.ethnicity"
:label="`${'เชื้อชาติ'}`"
/>
</div>
</div>
<div class="row col-12 q-col-gutter-x-sm q-mb-xs">
<div class="col-xs-6 col-sm-2 col-md-2">
<selector
hide-bottom-space
outlined
dense
lazy-rules
v-model="informaData.religionId"
emit-value
map-options
option-label="name"
:options="Ops.religionOps"
option-value="id"
:label="`${'ศาสนา'}`"
use-input
input-debounce="0"
@filter="(inputValue: any,
doneFn: Function) => filterSelector(inputValue, doneFn, 'religionOps'
)"
/>
</div>
<div class="col-xs-6 col-sm-2 col-md-2">
<selector
hide-bottom-space
outlined
dense
lazy-rules
v-model="informaData.bloodId"
emit-value
map-options
option-label="name"
:options="Ops.bloodOps"
option-value="id"
:label="`${'หมู่เลือด'}`"
use-input
input-debounce="0"
@filter="(inputValue: any,
doneFn: Function) => filterSelector(inputValue, doneFn, 'bloodOps'
)"
clearable
/>
</div>
<div class="col-xs-6 col-sm-2 col-md-2">
<q-input
hide-bottom-space
outlined
dense
lazy-rules
type="tel"
v-model="informaData.tel"
:label="`${'เบอร์โทร'}`"
mask="##########"
/>
</div>
</div>
</div>
</q-form>
<div class="col-12 q-pt-md q-pb-sm"><q-separator /></div>
<div class="row col-12">
<q-space />
<q-btn
unelevated
dense
class="q-px-md items-center"
color="light-blue-10"
label="บันทึก"
@click="saveData"
/>
</div>
</q-card> -->
<!-- Header -->
<q-page-sticky
position="top"
expand
class="bg-grey-2 text-white"
style="z-index: 99; padding: 0% 1% 0% 1%"
>
<div class="row col-12 q-gutter-sm q-pb-sm text-dark no-wrap items-center">
<q-btn
flat
round
class="bg-teal-1 full-height"
color="primary"
icon="mdi-chevron-left"
dense
@click="router.push(`/placement/receive`)"
>
</q-btn>
<q-avatar size="65px" rounded class="containerimage">
<img
v-if="image == null"
src="@/assets/avatar_user.jpg"
class="bg-grey-3"
style="object-fit: cover"
/>
<img :src="image" class="bg-grey-3" style="object-fit: cover" />
<div
class="overlay absolute-bottom text-subtitle2 text-center cursor-pointer"
@click="addNewImage()"
>
<q-icon name="mdi-camera" size="18px" color="blue">
<q-tooltip>ปเดตรปภาพ</q-tooltip>
</q-icon>
<input
type="file"
style="display: none"
ref="inputImage"
accept="image/*"
@change="uploadImage"
/>
</div>
</q-avatar>
<div class="row items-center text-dark q-ml-md">
<div class="column">
<div class="text-bold q-pb-xs text-name">
เพมขอมลทะเบยนประว
</div>
<div class="text-bold q-pb-xs text-sub">าราชการกทม. สาม</div>
</div>
</div>
<q-space />
</div>
</q-page-sticky>
<!-- End Header -->
<q-card flat bordered class="col-12">
<q-form greedy @submit.prevent @validation-success="onSubmit">
<HeaderTop
header="ข้อมูลส่วนตัว"
icon="mdi-account"
class="q-px-lg q-pt-md"
/>
<q-card-section class="q-px-lg">
<div class="row q-col-gutter-sm">
<div class="col-3">
<q-input
bg-color="white"
outlined
v-model="informaData.citizenId"
label="เลขประจำตัวประชาชน"
class="inputgreen"
dense
lazy-rules
borderless
:rules="[
(val: string) => !!val || `${'กรุณากรอกเลขประจำตัวประชาชน'}`,
(val: string) =>
val.length >= 13 ||
`${'กรุณากรอกเลขประจำตัวประชาชนให้ครบ'}`,
]"
maxlength="13"
hide-bottom-space
mask="#############"
@update:model-value="changeCardID"
/>
</div>
<div class="col-3">
<q-select
bg-color="white"
v-model="informaData.prefix"
label="คำนำหน้าชื่อ"
outlined
dense
lazy-rules
class="inputgreen"
:options="Ops.prefixOps"
option-label="name"
option-value="name"
map-options
hide-bottom-space
:rules="[
(val) => {
return val.length > 0 || 'กรุณาเลือกคำนำหน้าชื่อ';
},
]"
emit-value
/>
</div>
<div class="col-3">
<q-input
bg-color="white"
outlined
v-model="informaData.firstName"
label="ชื่อ"
dense
lazy-rules
class="inputgreen"
borderless
:rules="[(val) => val.length > 0 || 'กรุณากรอกชื่อ']"
hide-bottom-space
/>
</div>
<div class="col-3">
<q-input
bg-color="white"
outlined
v-model="informaData.lastName"
label="นามสกุล"
class="inputgreen"
dense
lazy-rules
borderless
:rules="[(val) => val.length > 0 || 'กรุณากรอกนามสกุล']"
hide-bottom-space
/>
</div>
<div class="col-2">
<datepicker
autoApply
borderless
week-start="0"
:max-date="calculateMaxDate()"
:enableTimePicker="false"
menu-class-name="modalfix"
v-model="informaData.birthDate"
:locale="'th'"
>
<template #year="{ year }">
{{ year + 543 }}
</template>
<template #year-overlay-value="{ value }">
{{ parseInt(value + 543) }}
</template>
<template #trigger>
<q-input
for="inputDatereceive"
outlined
dense
hide-bottom-space
class="inputgreen"
:model-value="
informaData.birthDate != null
? date2Thai(informaData.birthDate)
: null
"
label="วัน/เดือน/ปี เกิด"
:rules="[
(val) => !!val || `${'กรุณาเลือก วัน/เดือน/ปี เกิด'}`,
]"
>
<template v-slot:prepend>
<q-icon name="event" class="cursor-pointer" color="primary">
</q-icon>
</template>
</q-input>
</template>
</datepicker>
</div>
<div class="col-2">
<q-input
dense
outlined
lazy-rules
hide-bottom-space
readonly
class="inputgreen"
v-model="age"
label="อายุ"
/>
</div>
<div class="col-2">
<q-select
dense
outlined
use-input
clearable
lazy-rules
emit-value
map-options
hide-bottom-space
input-debounce="0"
option-label="name"
option-value="name"
v-model="informaData.genderId"
class="inputgreen"
:options="Ops.genderOps"
label="เพศ"
@filter="(inputValue: any,
doneFn: Function) => filterSelector(inputValue, doneFn, 'genderOps'
)"
/>
</div>
<div class="col-2">
<q-select
dense
outlined
use-input
clearable
lazy-rules
emit-value
map-options
hide-bottom-space
option-value="name"
option-label="name"
input-debounce="0"
class="inputgreen"
v-model="informaData.statusId"
:options="Ops.statusOps"
label="สถานภาพ"
@filter="(inputValue: any,
doneFn: Function) => filterSelector(inputValue, doneFn, 'statusOps'
)"
/>
</div>
<div class="col-2">
<q-input
dense
outlined
lazy-rules
hide-bottom-space
class="inputgreen"
v-model="informaData.nationality"
label="สัญชาติ"
/>
</div>
<div class="col-2">
<q-input
dense
outlined
lazy-rules
hide-bottom-space
class="inputgreen"
v-model="informaData.ethnicity"
label="เชื้อชาติ"
/>
</div>
<div class="col-2">
<q-select
dense
outlined
use-input
clearable
lazy-rules
emit-value
map-options
hide-bottom-space
option-value="name"
option-label="name"
input-debounce="0"
v-model="informaData.religionId"
class="inputgreen"
:options="Ops.religionOps"
label="ศาสนา"
@filter="(inputValue: any,
doneFn: Function) => filterSelector(inputValue, doneFn, 'religionOps'
)"
/>
</div>
<div class="col-2">
<q-select
dense
outlined
use-input
clearable
lazy-rules
emit-value
map-options
hide-bottom-space
option-value="name"
option-label="name"
input-debounce="0"
v-model="informaData.bloodId"
class="inputgreen"
:options="Ops.bloodOps"
label="หมู่เลือด"
@filter="(inputValue: any,
doneFn: Function) => filterSelector(inputValue, doneFn, 'bloodOps'
)"
/>
</div>
<div class="col-2">
<q-input
dense
outlined
lazy-rules
hide-bottom-space
mask="##########"
class="inputgreen"
v-model="informaData.tel"
label="เบอร์โทร"
/>
</div>
</div>
</q-card-section>
<q-separator />
<q-card-actions align="right" class="bg-white text-teal">
<q-btn label="บันทึก" color="secondary" type="submit"
><q-tooltip>นทกขอม</q-tooltip></q-btn
>
</q-card-actions>
</q-form>
</q-card>
</template>

View file

@ -1,68 +0,0 @@
<script setup lang="ts">
const props = defineProps({
editvisible: Boolean,
modalEdit: Boolean,
cancel: {
type: Function,
default: () => console.log("not function"),
},
edit: {
type: Function,
default: () => console.log("not function"),
},
save: {
type: Function,
default: () => console.log("not function"),
},
validate: {
type: Function,
default: () => console.log("not function"),
},
});
const emit = defineEmits([
"update:editvisible",
"update:next",
"update:previous",
]);
const updateEdit = (value: Boolean) => {
emit("update:editvisible", value);
};
// const cancel = async () => {
// props.cancel();
// };
const edit = async () => {
updateEdit(!props.editvisible);
props.edit();
};
const checkSave = () => {
props.validate();
props.save();
};
</script>
<template>
<q-card-actions class="text-primary">
<q-space />
<q-btn
v-if="!editvisible"
outline
:disabled="editvisible"
:color="editvisible ? 'grey-7' : 'primary'"
@click="edit"
><!-- icon="mdi-pencil-outline"
<q-tooltip>แกไขขอม</q-tooltip> -->
</q-btn>
<div v-else>
<q-btn
unelevated
label="บันทึก"
:disabled="!editvisible"
:color="!editvisible ? 'grey-7' : 'public'"
@click="checkSave"
>
</q-btn
><!-- icon="mdi-content-save-outline">
<q-tooltip>นท</q-tooltip> -->
</div>
</q-card-actions>
</template>

View file

@ -1,34 +0,0 @@
<script setup lang="ts">
const props = defineProps({
title: String,
close: {
type: Function,
default: () => console.log("not function"),
},
});
const close = async () => {
props.close();
};
</script>
<template>
<q-toolbar class="q-py-sm">
<q-toolbar-title class="header-text">{{ title }}</q-toolbar-title>
<q-btn
icon="close"
unelevated
round
dense
@click="close"
style="color: #ff8080; background-color: #ffdede"
/>
</q-toolbar>
</template>
<style scoped lang="scss">
.header-text {
font-size: 18px;
font-weight: 600;
line-height: 26px;
color: #35373c;
}
</style>

View file

@ -1,15 +1,17 @@
<script setup lang="ts">
import { ref, computed, watchEffect } from "vue";
import { ref, watchEffect } from "vue";
import { useQuasar } from "quasar";
import { useCounterMixin } from "@/stores/mixin";
import type { QTableProps } from "quasar";
import type { ResponseRow } from "@/modules/05_placement/interface/response/Receive";
import DialogHeader from "@/components/DialogHeader.vue";
// import DialogHeader from "@/modules/05_placement/components/PersonalList/DialogHeader.vue";
import http from "@/plugins/http";
import config from "@/app.config";
import type { QTableProps } from "quasar";
import type { ResponseRow } from "@/modules/05_placement/interface/response/Receive";
import { useTransferDataStore } from "@/modules/05_placement/store";
import DialogHeader from "@/components/DialogHeader.vue";
const transferStore = useTransferDataStore();
const { statusText } = transferStore;
const $q = useQuasar();
@ -24,17 +26,20 @@ const {
date2Thai,
} = mixin;
//
const visibleColumns2 = ref<string[]>([
"no",
"citizenId",
"fullname",
"organizationName",
"dateOfBirth",
"createdAt",
"status",
]);
//
/**
* props
*/
const props = defineProps({
modal: Boolean,
clickClose: Function,
fecthlistRecevice: Function,
nextPage: Function,
rows2: Array,
filterKeyword2: String,
});
const emit = defineEmits(["update:filterKeyword2", "update:selected"]);
//Table
const columns2 = ref<QTableProps["columns"]>([
{
name: "no",
@ -113,69 +118,74 @@ const columns2 = ref<QTableProps["columns"]>([
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
]);
const visibleColumns2 = ref<string[]>([
"no",
"citizenId",
"fullname",
"organizationName",
"dateOfBirth",
"createdAt",
"status",
]);
const props = defineProps({
Modal: Boolean,
clickClose: Function,
fecthlistRecevice: Function,
nextPage: Function,
rows2: Array,
filterKeyword2: String,
});
const checkSelected = computed(() => {
if (selected.value.length === 0) {
return true;
}
});
//popup
const saveOrder = () => {
/**
* งกนยนยนการสงออกคำส
*/
function saveOrder() {
dialogConfirm(
$q,
() => Ordersave(),
async () => {
const id = selected.value.map((r: ResponseRow) => r.id);
const body = {
id,
};
showLoader();
await http
.post(config.API.receiveReport, body)
.then(async () => {
await props.fecthlistRecevice?.();
success($q, "ส่งไปออกคำสั่งรับโอนสำเร็จ");
props.clickClose?.();
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
hideLoader();
});
},
"ยืนยันส่งไปออกคำสั่ง",
"ต้องการยืนยันส่งไปออกคำสั่งใช่หรือไม่?"
);
};
//
const Ordersave = async () => {
const id = selected.value.map((r: ResponseRow) => r.id);
const body = {
id,
};
showLoader();
await http
.post(config.API.receiveReport, body)
.then((res: any) => {
success($q, "ส่งไปออกคำสั่งรับโอนสำเร็จ");
props.clickClose?.();
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
props.fecthlistRecevice?.();
hideLoader();
});
};
}
const emit = defineEmits(["update:filterKeyword2", "update:selected"]);
const updateInput = (value: any) => {
/**
* งกนอปเดทคาในชองคนหา
*/
function updateInput(value: any) {
emit("update:filterKeyword2", value);
};
//
const Reset = () => {
}
/**
* งกนรเซตคาในชองคนหา
*/
function onReset() {
emit("update:filterKeyword2", "");
};
}
/**
* เม props.modal เป true
*
* กำหนดให selected เปนคาวาง
*/
watchEffect(() => {
if (props.Modal === true) {
if (props.modal === true) {
selected.value = [];
}
});
</script>
<template>
<q-dialog v-model="props.Modal">
<q-dialog v-model="props.modal">
<q-card style="width: 1200px; max-width: 80vw">
<DialogHeader :tittle="'ส่งไปออกคำสั่งรับโอน'" :close="clickClose" />
<q-separator />
@ -199,7 +209,7 @@ watchEffect(() => {
v-if="filterKeyword2 !== ''"
name="clear"
class="cursor-pointer"
@click="Reset"
@click="onReset"
/>
</template>
</q-input>
@ -317,7 +327,7 @@ watchEffect(() => {
<q-btn
label="ส่งไปออกคำสั่ง"
@click="saveOrder"
:disable="checkSelected"
:disable="selected.length === 0"
color="public"
><q-tooltip>งไปออกคำส</q-tooltip></q-btn
>

View file

@ -1,74 +0,0 @@
<script setup lang="ts">
import Information from "@/modules/05_placement/components/Receive/AddEmployee/Main.vue";
</script>
<template>
<div class="col-12 row">
<div class="row col-12" style="padding-top: 80px">
<div id="information" name="1" class="row col-12 information q-mt-sm">
<Information :statusAdd="true" />
</div>
</div>
</div>
</template>
<style>
.image-size-default {
height: 150px;
max-width: 15vw;
}
.image-size-full {
height: 160px;
max-width: 15vw;
}
.border-green {
border: 5px solid #52c688;
}
.area-div {
background-color: transparent;
}
.text-header {
font-size: 1.2em;
}
.containerimage {
position: relative;
}
.containerimage:hover .overlay {
opacity: 1;
}
.overlay {
background-color: #e4f2ffd2 !important;
opacity: 0;
padding: 2px !important;
}
.information:target {
padding-top: 84px;
}
.border-custom {
border: 0.5px solid #c3c3c3;
}
.bg-active-image {
background-color: #52c688;
}
.text-name {
font-size: 1.3em;
overflow: hidden;
}
.text-sub {
font-size: 1.2em;
overflow: hidden;
color: var(--q-primary);
}
</style>

View file

@ -0,0 +1,771 @@
<script setup lang="ts">
import { ref, onMounted } from "vue";
import { useQuasar } from "quasar";
import { useRouter } from "vue-router";
import { useCounterMixin } from "@/stores/mixin";
import { useProfileDataStore } from "@/modules/08_registryEmployee/store";
import http from "@/plugins/http";
import config from "@/app.config";
import type { QForm } from "quasar";
import type {
DataOption,
DataOptioninfo,
} from "@/modules/04_registry/components/profileType";
import type {
InformationOps,
FormAddPerson,
} from "@/modules/04_registry/interface/index/Main";
import HeaderTop from "@/modules/08_registryEmployee/components/AddEmployee/HeaderTop.vue";
const retireDate = ref<Date>();
const router = useRouter();
const $q = useQuasar();
const mixin = useCounterMixin();
const {
date2Thai,
success,
dateToISO,
messageError,
dialogMessageNotify,
showLoader,
hideLoader,
dialogConfirm,
} = mixin;
const profileStore = useProfileDataStore();
const age = ref<string | null>("");
const defaultCitizenData = ref<string>("");
const informaData = ref<FormAddPerson>({
prefix: "",
firstName: "",
lastName: "",
citizenId: "",
birthDate: null,
age: null,
genderId: null,
bloodId: null,
nationality: null,
ethnicity: null,
statusId: null,
religionId: null,
tel: null,
employeeType: null,
employeeClass: null,
profileType: null,
});
//
const Ops = ref<InformationOps>({
prefixOps: [],
prefixOldOps: [],
genderOps: [],
bloodOps: [],
statusOps: [],
religionOps: [],
employeeClassOps: [],
employeeTypeOps: [],
});
//
const OpsFilter = ref<InformationOps>({
prefixOps: [],
prefixOldOps: [],
genderOps: [],
bloodOps: [],
statusOps: [],
religionOps: [],
employeeClassOps: [],
employeeTypeOps: [],
});
// profile
const inputImage = ref<any>(null);
const image = ref<any>(null);
const fileData = ref<any>(null);
/**
* งกนดงขอมลรายการขอมลเกยวกบบคคล (dropdown list)
*/
async function fetchPerson() {
showLoader();
await http
.get(config.API.profileNewMetaMain)
.then((res) => {
const data = res.data.result;
let optionbloodGroups: DataOption[] = [];
data.bloodGroups.map((r: DataOptioninfo) => {
optionbloodGroups.push({
id: r.id.toString(),
name: r.name.toString(),
});
});
Ops.value.bloodOps = optionbloodGroups;
OpsFilter.value.bloodOps = optionbloodGroups;
let optiongenders: DataOption[] = [];
data.genders.map((r: DataOptioninfo) => {
optiongenders.push({
id: r.id.toString(),
name: r.name.toString(),
});
});
Ops.value.genderOps = optiongenders;
OpsFilter.value.genderOps = optiongenders;
let optionprefixs: DataOption[] = [];
optionprefixs = data.prefixs.map((v: any) => ({
id: v.id,
name: v.name,
}));
Ops.value.prefixOps = optionprefixs;
OpsFilter.value.prefixOps = optionprefixs;
let optionrelationships: DataOption[] = [];
data.relationships.map((r: DataOptioninfo) => {
optionrelationships.push({
id: r.id.toString(),
name: r.name.toString(),
});
});
Ops.value.statusOps = optionrelationships;
OpsFilter.value.statusOps = optionrelationships;
let optionreligions: DataOption[] = [];
data.religions.map((r: DataOptioninfo) => {
optionreligions.push({
id: r.id.toString(),
name: r.name.toString(),
});
});
Ops.value.religionOps = optionreligions;
OpsFilter.value.religionOps = optionreligions;
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
hideLoader();
});
}
function uploadImage(e: any) {
const input = e.target.files;
if (input.length > 0) {
const url = URL.createObjectURL(input[0]);
image.value = url;
fileData.value = input[0];
}
}
/**
* งกนคลกแกไขร profile
*/
function addNewImage() {
inputImage.value.click();
}
/**
* งกนตรวจสอบเลขบตรประจำตวประชาชน
* @param value เลขบตรประจำตวประชาชน
*/
async function changeCardID(value: string | number | null) {
if (value != null && typeof value == "string") {
if (value.length == 13 && value != defaultCitizenData.value) {
await checkCitizen(value);
}
}
}
/**
* งกนย API ตรวจสอบเลขบตรประจำตวประชาชนซ
* @param value เลขบตรประจำตวประชาชน
*/
async function checkCitizen(id: string) {
showLoader();
await http
.put(config.API.profileNewCitizenId(id), {
citizenId: id,
})
.then(() => {})
.catch((err) => {
if (err.response.data.status === 500) {
dialogMessageNotify($q, err.response.data.message);
} else {
messageError($q, err);
}
})
.finally(() => {
hideLoader();
});
}
/**
* งกนคนหาขอมลในรายการตวเลอก
* @param val คำคนหา
* @param update งก
* @param refData ประเภทของตวเลอก
*/
function filterSelector(val: string, update: Function, refData: string) {
switch (refData) {
case "prefixOps":
update(() => {
Ops.value.prefixOps = OpsFilter.value.prefixOps.filter(
(v: DataOption) => v.name.indexOf(val) > -1
);
});
break;
case "genderOps":
update(() => {
Ops.value.genderOps = OpsFilter.value.genderOps.filter(
(v: DataOption) => v.name.indexOf(val) > -1
);
});
break;
case "bloodOps":
update(() => {
Ops.value.bloodOps = OpsFilter.value.bloodOps.filter(
(v: DataOption) => v.name.indexOf(val) > -1
);
});
break;
case "statusOps":
update(() => {
Ops.value.statusOps = OpsFilter.value.statusOps.filter(
(v: DataOption) => v.name.indexOf(val) > -1
);
});
break;
case "religionOps":
update(() => {
Ops.value.religionOps = OpsFilter.value.religionOps.filter(
(v: DataOption) => v.name.indexOf(val) > -1
);
});
break;
default:
break;
}
}
/**
* งกนเชควนทสามารถเลอกวนเกดไดโดย max date อยกวาวนปจจ เพอใหงกนการเชคทำงานไดปกต
*/
function calculateMaxDate() {
const today = new Date();
today.setFullYear(today.getFullYear() - 18);
return today;
}
/**
* งกนยนยนการบนทกขอม
*/
function onSubmit() {
const formData = new FormData();
if (fileData.value != null) formData.append("File", fileData.value); //
if (informaData.value.citizenId != undefined)
formData.append("citizenId", informaData.value.citizenId);
if (informaData.value.prefix != undefined)
formData.append("prefix", informaData.value.prefix);
if (informaData.value.firstName != undefined)
formData.append("firstName", informaData.value.firstName);
if (informaData.value.lastName != undefined)
formData.append("lastName", informaData.value.lastName);
if (informaData.value.genderId != undefined)
formData.append("gender", informaData.value.genderId);
if (informaData.value.nationality != undefined)
formData.append("nationality", informaData.value.nationality);
if (informaData.value.ethnicity != undefined)
formData.append("race", informaData.value.ethnicity);
if (informaData.value.religionId != undefined)
formData.append("religion", informaData.value.religionId);
if (informaData.value.birthDate != undefined)
formData.append(
"birthDate",
dateToISO(informaData.value.birthDate) ?? dateToISO(new Date())
);
if (informaData.value.bloodId != undefined)
formData.append("bloodGroup", informaData.value.bloodId);
if (informaData.value.statusId != undefined)
formData.append("relationship", informaData.value.statusId);
if (informaData.value.tel != undefined)
formData.append("telephoneNumber", informaData.value.tel);
if (informaData.value.employeeType != undefined)
formData.append("employeeType", informaData.value.employeeType);
if (informaData.value.employeeClass != undefined)
formData.append("employeeClass", informaData.value.employeeClass);
dialogConfirm($q, async () => {
showLoader();
await http
.post(config.API.receiveData(), formData)
.then(async () => {
success($q, "บันทึกข้อมูลสำเร็จ");
clickBack();
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
hideLoader();
});
});
}
/**
* งกนกลบไปหนารายการรายการรบโอน
*/
function clickBack() {
router.push("/placement/receive");
}
/**
* งกนคำนวนอาย
* @param birthDate นเดอยปเก
* @returns อาย แบบ เดอน
*/
function calculateAge(birthDate: Date | null) {
if (!birthDate) return null;
const birthDateTimeStamp = new Date(birthDate).getTime();
const now = new Date();
const diff = now.getTime() - birthDateTimeStamp;
const ageDate = new Date(diff);
const years = ageDate.getUTCFullYear() - 1970;
const months = ageDate.getUTCMonth();
const days = ageDate.getUTCDate() - 1;
const retire = new Date(birthDate);
retire.setFullYear(retire.getFullYear() + 60);
retireDate.value = retire;
if (years > 60) {
return "อายุเกิน 60 ปี";
}
return `${years} ปี ${months} เดือน ${days} วัน`;
}
/**
* งกนอปเดทวนเดอนปเก
* @param v นเดอยปเก
*/
function updateBirthDate(v: Date) {
age.value = calculateAge(v);
}
/**
* ทำงานเมอมการเรยกใช Components
*/
onMounted(async () => {
await fetchPerson();
});
</script>
<template>
<div class="col-12 row">
<div class="row col-12" style="padding-top: 80px">
<div id="information" name="1" class="row col-12 information q-mt-sm">
<!-- Header -->
<q-page-sticky
position="top"
expand
class="bg-grey-2 text-white"
style="z-index: 99; padding: 0% 1% 0% 1%"
>
<div
class="row col-12 q-gutter-sm q-pb-sm text-dark no-wrap items-center"
>
<q-btn
flat
round
class="bg-teal-1 full-height"
color="primary"
icon="mdi-chevron-left"
dense
@click="router.push(`/placement/receive`)"
>
</q-btn>
<q-avatar size="65px" rounded class="containerimage">
<img
v-if="image == null"
src="@/assets/avatar_user.jpg"
class="bg-grey-3"
style="object-fit: cover"
/>
<img :src="image" class="bg-grey-3" style="object-fit: cover" />
<div
class="overlay absolute-bottom text-subtitle2 text-center cursor-pointer"
@click="addNewImage()"
>
<q-icon name="mdi-camera" size="18px" color="blue">
<q-tooltip>ปเดตรปภาพ</q-tooltip>
</q-icon>
<input
type="file"
style="display: none"
ref="inputImage"
accept="image/*"
@change="uploadImage"
/>
</div>
</q-avatar>
<div class="row items-center text-dark q-ml-md">
<div class="column">
<div class="text-bold q-pb-xs text-name">
เพมขอมลทะเบยนประว
</div>
<div class="text-bold q-pb-xs text-sub">
าราชการกทม. สาม
</div>
</div>
</div>
<q-space />
</div>
</q-page-sticky>
<q-card flat bordered class="col-12">
<q-form greedy @submit.prevent @validation-success="onSubmit">
<HeaderTop
header="ข้อมูลส่วนตัว"
icon="mdi-account"
class="q-px-lg q-pt-md"
/>
<q-card-section class="q-px-lg">
<div class="row q-col-gutter-sm">
<div class="col-3">
<q-input
bg-color="white"
outlined
v-model="informaData.citizenId"
label="เลขประจำตัวประชาชน"
class="inputgreen"
dense
lazy-rules
borderless
:rules="[
(val: string) => !!val || `${'กรุณากรอกเลขประจำตัวประชาชน'}`,
(val: string) =>
val.length >= 13 ||
`${'กรุณากรอกเลขประจำตัวประชาชนให้ครบ'}`,
]"
maxlength="13"
hide-bottom-space
mask="#############"
@update:model-value="changeCardID"
/>
</div>
<div class="col-3">
<q-select
bg-color="white"
v-model="informaData.prefix"
label="คำนำหน้าชื่อ"
outlined
dense
lazy-rules
class="inputgreen"
:options="Ops.prefixOps"
option-label="name"
option-value="name"
map-options
hide-bottom-space
:rules="[
(val) => {
return val.length > 0 || 'กรุณาเลือกคำนำหน้าชื่อ';
},
]"
emit-value
/>
</div>
<div class="col-3">
<q-input
bg-color="white"
outlined
v-model="informaData.firstName"
label="ชื่อ"
dense
lazy-rules
class="inputgreen"
borderless
:rules="[(val) => val.length > 0 || 'กรุณากรอกชื่อ']"
hide-bottom-space
/>
</div>
<div class="col-3">
<q-input
bg-color="white"
outlined
v-model="informaData.lastName"
label="นามสกุล"
class="inputgreen"
dense
lazy-rules
borderless
:rules="[(val) => val.length > 0 || 'กรุณากรอกนามสกุล']"
hide-bottom-space
/>
</div>
<div class="col-2">
<datepicker
autoApply
borderless
week-start="0"
:max-date="calculateMaxDate()"
:enableTimePicker="false"
menu-class-name="modalfix"
v-model="informaData.birthDate"
:locale="'th'"
@update:model-value="updateBirthDate"
>
<template #year="{ year }">
{{ year + 543 }}
</template>
<template #year-overlay-value="{ value }">
{{ parseInt(value + 543) }}
</template>
<template #trigger>
<q-input
for="inputDatereceive"
outlined
dense
hide-bottom-space
class="inputgreen"
:model-value="
informaData.birthDate != null
? date2Thai(informaData.birthDate)
: null
"
label="วัน/เดือน/ปี เกิด"
:rules="[
(val) => !!val || `${'กรุณาเลือก วัน/เดือน/ปี เกิด'}`,
]"
>
<template v-slot:prepend>
<q-icon
name="event"
class="cursor-pointer"
color="primary"
>
</q-icon>
</template>
</q-input>
</template>
</datepicker>
</div>
<div class="col-2">
<q-input
dense
outlined
lazy-rules
hide-bottom-space
readonly
class="inputgreen"
v-model="age"
label="อายุ"
/>
</div>
<div class="col-2">
<q-select
dense
outlined
use-input
clearable
lazy-rules
emit-value
map-options
hide-bottom-space
input-debounce="0"
option-label="name"
option-value="name"
v-model="informaData.genderId"
class="inputgreen"
:options="Ops.genderOps"
label="เพศ"
@filter="(inputValue:string,
doneFn: Function) => filterSelector(inputValue, doneFn, 'genderOps'
)"
/>
</div>
<div class="col-2">
<q-select
dense
outlined
use-input
clearable
lazy-rules
emit-value
map-options
hide-bottom-space
option-value="name"
option-label="name"
input-debounce="0"
class="inputgreen"
v-model="informaData.statusId"
:options="Ops.statusOps"
label="สถานภาพ"
@filter="(inputValue:string,
doneFn: Function) => filterSelector(inputValue, doneFn, 'statusOps'
)"
/>
</div>
<div class="col-2">
<q-input
dense
outlined
lazy-rules
hide-bottom-space
class="inputgreen"
v-model="informaData.nationality"
label="สัญชาติ"
/>
</div>
<div class="col-2">
<q-input
dense
outlined
lazy-rules
hide-bottom-space
class="inputgreen"
v-model="informaData.ethnicity"
label="เชื้อชาติ"
/>
</div>
<div class="col-2">
<q-select
dense
outlined
use-input
clearable
lazy-rules
emit-value
map-options
hide-bottom-space
option-value="name"
option-label="name"
input-debounce="0"
v-model="informaData.religionId"
class="inputgreen"
:options="Ops.religionOps"
label="ศาสนา"
@filter="(inputValue:string,
doneFn: Function) => filterSelector(inputValue, doneFn, 'religionOps'
)"
/>
</div>
<div class="col-2">
<q-select
dense
outlined
use-input
clearable
lazy-rules
emit-value
map-options
hide-bottom-space
option-value="name"
option-label="name"
input-debounce="0"
v-model="informaData.bloodId"
class="inputgreen"
:options="Ops.bloodOps"
label="หมู่เลือด"
@filter="(inputValue:string,
doneFn: Function) => filterSelector(inputValue, doneFn, 'bloodOps'
)"
/>
</div>
<div class="col-2">
<q-input
dense
outlined
lazy-rules
hide-bottom-space
mask="##########"
class="inputgreen"
v-model="informaData.tel"
label="เบอร์โทร"
/>
</div>
</div>
</q-card-section>
<q-separator />
<q-card-actions align="right" class="bg-white text-teal">
<q-btn label="บันทึก" color="secondary" type="submit"
><q-tooltip>นทกขอม</q-tooltip></q-btn
>
</q-card-actions>
</q-form>
</q-card>
</div>
</div>
</div>
</template>
<style>
.image-size-default {
height: 150px;
max-width: 15vw;
}
.image-size-full {
height: 160px;
max-width: 15vw;
}
.border-green {
border: 5px solid #52c688;
}
.area-div {
background-color: transparent;
}
.text-header {
font-size: 1.2em;
}
.containerimage {
position: relative;
}
.containerimage:hover .overlay {
opacity: 1;
}
.overlay {
background-color: #e4f2ffd2 !important;
opacity: 0;
padding: 2px !important;
}
.information:target {
padding-top: 84px;
}
.border-custom {
border: 0.5px solid #c3c3c3;
}
.bg-active-image {
background-color: #52c688;
}
.text-name {
font-size: 1.3em;
overflow: hidden;
}
.text-sub {
font-size: 1.2em;
overflow: hidden;
color: var(--q-primary);
}
</style>

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,733 +0,0 @@
<script setup lang="ts">
import { ref, computed, onMounted } from "vue";
import type { QTableProps } from "quasar";
import { useQuasar } from "quasar";
import { useRouter } from "vue-router";
import { useCounterMixin } from "@/stores/mixin";
import { useTransferDataStore } from "@/modules/05_placement/store";
import http from "@/plugins/http";
import config from "@/app.config";
import DialogOrgTree from "@/modules/05_placement/components/Relocation/RelocationModal.vue";
import DialogHeader from "@/components/DialogHeader.vue";
import type { relocationType } from "@/modules/05_placement/interface/response/Relocation";
const transferStore = useTransferDataStore();
const { statusText } = transferStore;
const personalId = ref<string>("");
const personal = ref<any[]>([]);
const modalTree = ref<boolean>(false);
const selected = ref<relocationType[]>([]);
const checkSelected = computed(() => {
if (selected.value.length === 0) {
return true;
}
});
const $q = useQuasar();
const router = useRouter();
const mixin = useCounterMixin();
const {
date2Thai,
messageError,
showLoader,
hideLoader,
success,
dialogMessage,
dialogRemove,
} = mixin;
const modal = ref<boolean>(false);
const visibleColumns = ref<string[]>([
"no",
"citizenId",
"fullname",
"organizationName",
"dateOfBirth",
"createdAt",
"statusText",
"btn",
]);
const visibleColumns2 = ref<string[]>([
"no",
"citizenId",
"fullname",
"organizationName",
"dateOfBirth",
]); //
const filterKeyword = ref<string>("");
const filterKeyword2 = ref<string>("");
const filterRef = ref<any>(null);
const resetFilter = () => {
filterKeyword.value = "";
filterKeyword2.value = "";
filterRef.value.focus();
};
const rows = ref<relocationType[]>([]);
const rows2 = ref<any[]>([]);
const columns = ref<QTableProps["columns"]>([
{
name: "no",
align: "left",
label: "ลำดับ",
sortable: true,
field: "no",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "citizenId",
align: "left",
label: "เลขประจำตัวประชาชน",
sortable: true,
field: "fullname",
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: "organizationName",
align: "left",
label: "หน่วยงานที่รับโอน",
sortable: true,
field: "organizationName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "dateOfBirth",
align: "left",
label: "วัน/เดือน/ปี เกิด",
sortable: true,
field: "dateOfBirth",
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: "statusText",
align: "left",
label: "สถานะ",
sortable: true,
field: "statusText",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "btn",
align: "left",
label: "",
sortable: true,
field: "btn",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
]);
const columns2 = ref<QTableProps["columns"]>([
{
name: "no",
align: "left",
label: "ลำดับ",
sortable: true,
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: "ชื่อ-นามสกุล",
sortable: true,
field: "fullname",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "organizationName",
align: "left",
label: "หน่วยงานที่รับโอน",
sortable: true,
field: "organizationName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "dateOfBirth",
align: "left",
label: "วัน/เดือน/ปี เกิด",
sortable: true,
field: "dateOfBirth",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
]);
//--------------()----------------//
const openDetail = (id: string) => {
router.push(`/relocation/detail/${id}`);
};
const openModal = () => (modal.value = true);
const closeModal = () => (modal.value = false);
const openModalOrder = () => {
openModal();
const row = rows.value.filter(
(item: relocationType) =>
item.status == "WAITTING" ||
item.status == "PENDING" ||
item.status == "APPROVE"
);
rows2.value = row;
};
const openModalTree = (id: string) => {
personalId.value = id;
personal.value = rows.value.filter((e: any) => e.id === id);
modalTree.value = true;
};
const getData = async () => {
showLoader();
await http
.get(config.API.relocationMain())
.then((res: any) => {
const data = res.data.result;
rows.value = data.map((item: relocationType) => ({
fullname: `${item.prefix}${item.firstname} ${item.lastname}`,
id: item.id,
citizenId: item.citizenId,
prefix: item.prefix,
firstname: item.firstname,
lastname: item.lastname,
dateOfBirth: date2Thai(item.dateOfBirth),
gender: item.gender,
status: item.status,
statusText: statusText(item.status),
recruitDate: item.recruitDate,
positionNumber: item.positionNumber,
positionPath: item.positionPath,
positionPathSide: item.positionPathSide,
positionType: item.positionType,
positionLine: item.positionLine,
positionLevel: item.positionLevel,
posNoId: item.posNoId,
positionId: item.positionId,
positionPathSideId: item.positionPathSideId,
positionTypeId: item.positionTypeId,
positionLineId: item.positionLineId,
positionLevelId: item.positionLevelId,
organizationPositionId: item.organizationPositionId,
organizationName: item.organizationName,
organizationShortName: item.organizationShortName,
isActive: item.isActive,
reason: item.reason,
educationOld: item.educationOld,
salary: item.salary,
positionTypeOld: item.positionTypeOld,
positionLevelOld: item.positionLevelOld,
positionNumberOld: item.positionNumberOld,
organizationPositionOld: item.organizationPositionOld,
createdAt: date2Thai(item.createdAt),
}));
})
.catch((e) => {
// messageError($q, e);
})
.finally(() => {
hideLoader();
});
};
const saveOrder = async () => {
const id = selected.value.map((item) => item.id);
const body = {
id,
};
showLoader();
await http
.post(config.API.relocationMainReport(), body)
.then(() => {
success($q, "ส่งไปออกคำสั่งย้าย");
closeModal();
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await getData();
hideLoader();
});
};
const deleteData = async (id: string) => {
await http
.delete(config.API.relocationMainDelete(id))
.then(() => {
success($q, "ลบข้อมูลสำเร็จ");
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await getData();
});
};
const clickDelete = async (name: string, id: string) => {
dialogRemove(
$q,
async () => {
await deleteData(id);
await getData();
},
`ลบข้อมูลของ ${name}`
);
};
const closeModalTree = async () => {
await getData();
modalTree.value = false;
};
onMounted(async () => {
await getData();
});
const pagination = ref({
sortBy: "createdAt",
descending: true,
page: 1,
rowsPerPage: 10,
});
</script>
<template>
<div class="toptitle text-dark col-12 row items-center">รายการยาย</div>
<q-card flat bordered class="col-12 q-mt-sm">
<q-separator />
<div class="row q-pa-md">
<div class="col-12">
<div class="row col-12">
<q-btn
@click="openModalOrder"
size="14px"
flat
round
color="add"
icon="mdi-account-arrow-right"
>
<q-tooltip>งไปออกคำสงยาย</q-tooltip>
</q-btn>
<q-space />
<q-input
class="col-xs-12 col-sm-3 col-md-2"
standout
dense
v-model="filterKeyword"
ref="filterRef"
outlined
debounce="300"
placeholder="ค้นหา"
>
<template v-slot:append>
<q-icon v-if="filterKeyword == ''" name="search" />
<q-icon
v-if="filterKeyword !== ''"
name="clear"
class="cursor-pointer"
@click="resetFilter"
/>
</template>
</q-input>
<q-select
v-model="visibleColumns"
multiple
outlined
dense
options-dense
:display-value="$q.lang.table.columns"
emit-value
map-options
:options="columns"
option-value="name"
options-cover
style="min-width: 150px"
class="col-xs-12 col-sm-3 col-md-2 q-ml-sm"
/>
</div>
<div class="col-12 q-pt-sm">
<d-table
:columns="columns"
:rows="rows"
:filter="filterKeyword"
row-key="id"
:visible-columns="visibleColumns"
v-model:pagination="pagination"
>
<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-tr>
</template>
<template v-slot:body="props">
<q-tr :props="props" class="cursor-pointer">
<q-td key="no" :props="props" @click="openDetail(props.row.id)">
{{ props.rowIndex + 1 }}
</q-td>
<q-td
key="citizenId"
:props="props"
@click="openDetail(props.row.id)"
>
{{ props.row.citizenId !== null ? props.row.citizenId : "-" }}
</q-td>
<q-td
key="fullname"
:props="props"
@click="openDetail(props.row.id)"
>
{{ props.row.fullname !== null ? props.row.fullname : "-" }}
</q-td>
<q-td
key="organizationName"
:props="props"
@click="openDetail(props.row.id)"
>
<div
v-if="
props.row.organizationName !== null ||
props.row.positionPath !== null
"
>
<div class="col-4">
<div class="text-weight-medium">
{{
props.row.organizationName !== null
? props.row.organizationName
: "-"
}}
{{
props.row.organizationShortName !== null
? `(${props.row.organizationShortName})`
: ""
}}
</div>
<div class="text-weight-light">
{{
props.row.positionPath !== null
? props.row.positionPath
: "-"
}}
{{
props.row.positionNumber !== null
? `(${props.row.positionNumber})`
: ""
}}
</div>
</div>
</div>
<div v-else>
<div class="col-4">
<div class="text-weight-medium">-</div>
</div>
</div>
</q-td>
<q-td
key="dateOfBirth"
:props="props"
@click="openDetail(props.row.id)"
>
{{
props.row.dateOfBirth !== null ? props.row.dateOfBirth : "-"
}}
</q-td>
<q-td
key="createdAt"
:props="props"
@click="openDetail(props.row.id)"
>
{{ props.row.createdAt }}
</q-td>
<q-td
key="organizationPositionOld"
:props="props"
@click="openDetail(props.row.id)"
>
<div class="table_ellipsis">
{{
props.row.organizationPositionOld !== null
? props.row.organizationPositionOld
: "-"
}}
</div>
</q-td>
<q-td
key="organization"
:props="props"
@click="openDetail(props.row.id)"
>
<div class="table_ellipsis">
{{
props.row.organization !== null
? props.row.organization
: "-"
}}
</div>
</q-td>
<q-td
key="statusText"
:props="props"
@click="openDetail(props.row.id)"
>
{{
props.row.statusText !== null ? props.row.statusText : "-"
}}
</q-td>
<q-td auto-width>
<q-btn
v-if="
props.row.status !== 'DONE' &&
props.row.status !== 'REPORT'
"
icon="mdi-dots-vertical"
size="12px"
color="grey-7"
flat
round
dense
>
<q-menu
transition-show="jump-down"
transition-hide="jump-up"
>
<q-list dense style="min-width: 100px">
<q-item
clickable
v-close-popup
@click="openModalTree(props.row.id)"
>
<q-item-section
style="min-width: 0px"
avatar
class="q-py-sm"
>
<q-icon
color="primary"
size="xs"
name="mdi-bookmark-outline"
/>
</q-item-section>
<q-item-section
>เลอกหนวยงานทบยาย</q-item-section
>
</q-item>
<q-item
clickable
v-close-popup
@click="clickDelete(props.row.fullname, props.row.id)"
>
<q-item-section
style="min-width: 0px"
avatar
class="q-py-sm"
>
<q-tooltip>ลบขอม</q-tooltip>
<q-icon color="red" size="xs" name="mdi-delete" />
</q-item-section>
<q-item-section>ลบ</q-item-section>
</q-item>
</q-list>
</q-menu>
</q-btn>
</q-td>
</q-tr>
</template>
</d-table>
</div>
</div>
</div>
</q-card>
<q-dialog v-model="modal">
<q-card style="width: 1200px; max-width: 80vw">
<DialogHeader :tittle="'ส่งไปออกคำสั่งย้าย'" :close="closeModal" />
<q-separator />
<q-card-section>
<div class="row justify-end">
<div class="col-5">
<q-toolbar style="padding: 0">
<q-input
borderless
outlined
dense
debounce="300"
v-model="filterKeyword2"
placeholder="ค้นหา"
style="width: 850px; max-width: auto"
>
<template v-slot:append>
<q-icon v-if="filterKeyword2 == ''" name="search" />
<q-icon
v-if="filterKeyword2 !== ''"
name="clear"
class="cursor-pointer"
@click="resetFilter"
/>
</template>
</q-input>
<q-select
v-model="visibleColumns2"
multiple
outlined
dense
options-dense
:display-value="$q.lang.table.columns"
emit-value
map-options
:options="columns2"
option-value="name"
options-cover
style="min-width: 150px"
class="gt-xs q-ml-sm"
/>
</q-toolbar>
</div>
</div>
<d-table
:columns="columns2"
:rows="rows2"
:filter="filterKeyword2"
row-key="id"
flat
:visible-columns="visibleColumns2"
selection="multiple"
v-model:selected="selected"
>
<template v-slot:header-selection="scope">
<q-checkbox
keep-color
color="primary"
dense
v-model="scope.selected"
/>
</template>
<template v-slot:body="props">
<q-tr :props="props" class="cursor-pointer">
<q-td>
<q-checkbox
keep-color
color="primary"
dense
v-model="props.selected"
/>
</q-td>
<q-td key="no" :props="props">
{{ props.rowIndex + 1 }}
</q-td>
<q-td key="citizenId" :props="props">
{{ props.row.citizenId }}
</q-td>
<q-td key="fullname" :props="props">
{{ props.row.fullname }}
</q-td>
<q-td key="organizationName" :props="props">
<div
v-if="
props.row.organizationName !== null ||
props.row.positionPath !== null
"
>
<div class="col-4">
<div class="text-weight-medium">
{{
props.row.organizationName !== null
? props.row.organizationName
: "-"
}}
{{
props.row.organizationShortName !== null
? `(${props.row.organizationShortName})`
: ""
}}
</div>
<div class="text-weight-light">
{{
props.row.positionPath !== null
? props.row.positionPath
: "-"
}}
{{
props.row.positionNumber !== null
? `(${props.row.positionNumber})`
: ""
}}
</div>
</div>
</div>
<div v-else>
<div class="col-4">
<div class="text-weight-medium">-</div>
</div>
</div>
</q-td>
<q-td key="dateOfBirth" :props="props">
{{ props.row.dateOfBirth }}
</q-td>
</q-tr>
</template>
</d-table>
</q-card-section>
<q-separator />
<q-card-actions align="right">
<q-btn
label="ส่งไปออกคำสั่ง"
@click="saveOrder"
:disable="checkSelected"
color="public"
>
<q-tooltpi>งไปออกคำส</q-tooltpi>
</q-btn>
</q-card-actions>
</q-card>
</q-dialog>
<DialogOrgTree
v-model:modal="modalTree"
:close="closeModalTree"
:personal="personal"
:personalId="personalId"
/>
<!-- :personalId="personalId" -->
</template>
<style scoped lang="scss"></style>

View file

@ -1,791 +0,0 @@
<script setup lang="ts">
import { useQuasar, QForm } from "quasar";
import { onMounted, reactive, ref, watch } from "vue";
import DialogHeader from "@/components/DialogHeader.vue";
import DialogFooter from "@/modules/05_placement/components/PersonalList/DialogFooter.vue";
import { useCounterMixin } from "@/stores/mixin";
import http from "@/plugins/http";
import config from "@/app.config";
const $q = useQuasar();
const mixin = useCounterMixin(); //
const {
date2Thai,
hideLoader,
messageError,
showLoader,
success,
dialogConfirm,
} = mixin; //
const notFound = ref<string>("ไม่พบข้อมูลที่ค้นหา");
const noData = ref<string>("ไม่พบข้อมูลผังโครงสร้าง");
const checkValidate = ref<boolean>(false);
const myFormPosition = ref<any>();
const selected = ref<string>("");
const selectedFile = ref<string>("");
const dataRespone = ref<any>();
// Set form field
let dataForm = reactive({
personalId: "",
containDate: new Date(),
posNoId: "",
positionId: "",
positionLevelId: "",
positionLineId: "",
positionPathSideId: "",
positionTypeId: "",
// salaryAmount: null,
// mouthSalaryAmount: null,
// positionSalaryAmount: null,
});
onMounted(async () => {
// await fetchPublishFile();
await loadTreeData();
await fetchplacementPosition();
});
// const fetchPublishFile = async () => {
// await http
// .get(config.API.getPublishFileHistory)
// .then((res) => {
// let data = res.data.result;
// selectedFile.value = data[0].fileName;
// })
// .catch((e) => {
// messageError($q, e);
// })
// .finally(async () => {
// hideLoader();
// });
// };
// json
const treeData = ref<Array<any>>([]);
const loadTreeData = async () => {
expanded.value = [];
await http
.get(`${config.s3ClusterUrl}${selectedFile.value}`)
.then((res: any) => {
treeData.value = res.data;
dataRespone.value = res.data;
// Filter objects with "name" null
const filteredData = res.data.filter(filterByPersonIdNull);
treeData.value = filteredData;
})
.catch((e: any) => {
messageError($q, e);
})
.finally(() => {
hideLoader();
});
};
function filterByPersonIdNull(obj: any) {
if (obj.name === null && obj.isCondition != true) {
return true;
}
if (obj.children && obj.children.length > 0) {
obj.children = obj.children.filter(filterByPersonIdNull);
return obj.children.length > 0;
}
return false;
}
// position
const placementPosition = ref<any>([]);
const fetchplacementPosition = async () => {
await http
.get(config.API.relocationMainPosition())
.then((res: any) => {
placementPosition.value = res.data.result;
})
.catch((e: any) => {
messageError($q, e);
});
};
const search = ref<string>("");
//reset Tree Filter
const filterRef = ref<any>(null);
// const resetFilter = () => {
// search.value = "";
// filterRef.value.focus();
// };
const props = defineProps({
personalId: String,
modal: Boolean,
close: {
type: Function,
default: () => console.log("close modal"),
},
personal: Object,
});
const myFilterMethod = (node: any, filter: string) => {
const filt = filter;
return (
// ((node.name && node.name == null) || !node.name) &&
(node.name && node.name.indexOf(filt) > -1) ||
(node.organizationName && node.organizationName.indexOf(filt) > -1) ||
(node.positionNum && node.positionNum.indexOf(filt) > -1) ||
(node.positionName && node.positionName.indexOf(filt) > -1) ||
(node.governmentCode &&
node.governmentCode.toString().indexOf(filt) > -1) ||
(node.agency && node.agency.indexOf(filt) > -1) ||
(node.government && node.government.indexOf(filt) > -1) ||
(node.department && node.department.indexOf(filt) > -1) ||
(node.pile && node.pile.indexOf(filt) > -1) ||
(node.organizationShortName &&
node.organizationShortName.indexOf(filt) > -1) ||
(node.positionSideName && node.positionSideName.indexOf(filt) > -1) ||
(node.executivePosition && node.executivePosition.indexOf(filt) > -1) ||
(node.executivePositionSide &&
node.executivePositionSide.indexOf(filt) > -1) ||
(node.positionLevel && node.positionLevel.indexOf(filt) > -1)
);
};
const validateData = async () => {
checkValidate.value = true;
await myFormPosition.value.validate().then((result: boolean) => {
if (result == false) {
checkValidate.value = false;
}
});
};
const id = ref<string>("");
const saveAppoint = async () => {
myFormPosition.value.validate().then(async (result: boolean) => {
if (props.personalId !== undefined) {
id.value = props.personalId.toString();
}
if (result) {
const dataAppoint = await {
// personalId: props.personalId,
recruitDate: dataForm.containDate,
posNoId: dataForm.posNoId,
positionId: dataForm.positionId,
positionLevelId: dataForm.positionLevelId,
positionLineId: dataForm.positionLineId,
positionPathSideId: dataForm.positionPathSideId,
positionTypeId: dataForm.positionTypeId,
// salaryAmount: dataForm.salaryAmount,
// mouthSalaryAmount: dataForm.mouthSalaryAmount,
// positionSalaryAmount: dataForm.positionSalaryAmount,
};
showLoader();
await http
.put(config.API.relocationMainPut(id.value), dataAppoint)
.then(() => {
success($q, "บันทึกสำเร็จ");
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await closeAndClear();
// await resetFilter();
// await fetchPublishFile();
await loadTreeData();
await fetchplacementPosition();
hideLoader();
});
}
});
};
const editDataStatus = ref<boolean>(false);
const clickEditRow = () => {
editDataStatus.value = true;
};
const closeModal = () => {
if (editDataStatus.value == true) {
dialogConfirm(
$q,
() => {
editDataStatus.value = false;
closeAndClear();
},
`ข้อมูลมีการแก้ไข`,
`ยืนยันที่จะปิดโดยไม่บันทึกใช่หรือไม่?`
);
} else {
closeAndClear();
}
};
const closeAndClear = async () => {
await props.close();
editDataStatus.value = false;
selected.value = "";
dataForm.personalId = "";
dataForm.containDate = new Date();
dataForm.posNoId = "";
dataForm.positionId = "";
dataForm.positionLevelId = "";
dataForm.positionLineId = "";
dataForm.positionPathSideId = "";
dataForm.positionTypeId = "";
// dataForm.salaryAmount = null;
// dataForm.mouthSalaryAmount = null;
// dataForm.positionSalaryAmount = null;
};
//
const posNoOptions = ref<Object[]>([
{
label: "",
value: "",
},
]);
//
const positionOptions = ref<Object[]>([
{
label: "",
value: "",
},
]);
// /
const positionPathSideOptions = ref<Object[]>([
{
label: "",
value: "",
},
]);
//
const positionTypeOptions = ref<Object[]>([
{
label: "",
value: "",
},
]);
//
const positionLineOptions = ref<Object[]>([
{
label: "",
value: "",
},
]);
//
const positionLevelOptions = ref<Object[]>([
{
label: "",
value: "",
},
]);
const selectedPosition = async (data: any) => {
if (data.name == null && selected.value != data.keyId) {
editDataStatus.value = true;
selected.value = data.keyId;
// posNo Options
posNoOptions.value = [
{
label: data.positionNum,
value: data.positionNumId,
},
];
dataForm.posNoId = data.positionNumId;
// position Options
positionOptions.value = [
{
label: data.positionName,
value: data.positionNameId,
},
];
dataForm.positionId = data.positionNameId;
// positionPathSide Options
let positionPathSideArr: any = [];
if (data.positionSideNameObj && data.positionSideNameObj != null) {
data.positionSideNameObj.map((x: any) => {
positionPathSideArr.push({
label: x.Name,
value: x.Id,
});
});
positionPathSideOptions.value = positionPathSideArr;
dataForm.positionPathSideId =
positionPathSideArr.length > 1 || positionPathSideArr.length == 0
? ""
: positionPathSideArr[0].value;
}
// positionType Options
positionTypeOptions.value = [
{
label: data.positionType,
value: data.positionTypeId,
},
];
dataForm.positionTypeId = data.positionTypeId;
// positionLine Options
positionLineOptions.value = [
{
label: data.positionLine,
value: data.positionLineId,
},
];
dataForm.positionLineId = data.positionLineId;
// positionLevel Options
let positionLevelsArr: any = [];
if (data.positionLevelObj != null) {
data.positionLevelObj.map((x: any) => {
positionLevelsArr.push({
label: x.Name,
value: x.Id,
});
});
positionLevelOptions.value = positionLevelsArr;
dataForm.positionLevelId =
positionLevelsArr.length > 1 || positionLevelsArr.length == 0
? ""
: positionLevelsArr[0].value;
dataForm.positionLevelId = data.positionLevelObj[0].Id;
}
} else if (selected.value == data.keyId) {
selected.value = "";
dataForm.posNoId = "";
dataForm.positionId = "";
dataForm.positionLevelId = "";
dataForm.positionLineId = "";
dataForm.positionPathSideId = "";
dataForm.positionTypeId = "";
}
};
const checkPosition = (val: string) => {
const num = placementPosition.value.findIndex((e: string) => e === val);
return num;
};
const personal = ref<any>();
const expanded = ref<string[]>([]);
watch(props, () => {
expanded.value = [];
const dataPersonal = props.personal;
if (dataPersonal) {
dataPersonal.map((data: any) => {
personal.value = data;
});
}
if (personal.value) {
// const findData = dataRespone.value.find(findByPerson);
let findData: any = null;
dataRespone.value.map((x: any) => {
findData = findByPerson(x);
if (findData != null) {
selectedPosition(findData);
for (let i = 3; i <= findData.keyId.length; i += 2) {
expanded.value.push(findData.keyId.slice(0, i));
}
}
});
// loadTreeData();
// selectedPosition(findData.children.children.children)
}
});
function findByPerson(element: any): any {
if (
element.positionNumId &&
element.positionLineId === personal.value.positionLineId &&
element.positionTypeId === personal.value.positionTypeId &&
element.positionNumId === personal.value.posNoId &&
(element.positionLevelObj === null ||
element.positionLevelObj[0].Id === personal.value.positionLevelId)
) {
return element;
} else if (element.children) {
var i;
var result = null;
for (i = 0; result == null && i < element.children.length; i++) {
result = findByPerson(element.children[i]);
}
return result;
}
return null;
}
</script>
<template>
<q-dialog v-model="props.modal" persistent>
<q-card style="width: 900px; max-width: 80vw">
<q-form ref="myFormPosition">
<DialogHeader tittle="เลือกหน่วยงานที่รับย้าย" :close="closeModal" />
<q-separator />
<q-card-section class="q-pa-sm bg-grey-1">
<div class="row col-12 q-col-gutter-sm">
<div class="col-xs-12 col-sm-7 row">
<q-card flat bordered class="fit q-pa-sm">
<q-scroll-area visible style="height: 70vh">
<q-input
outlined
dense
ref="filterRef"
v-model="search"
placeholder="ค้นหา"
class="q-mb-sm"
>
<template v-slot:append>
<q-icon name="mdi-magnify" />
</template>
</q-input>
<div class="q-pa-sm q-gutter-sm">
<q-tree
no-transition
dense
:nodes="treeData"
node-key="keyId"
:filter="search"
:no-results-label="notFound"
:no-nodes-label="noData"
:filter-method="myFilterMethod"
v-model:expanded="expanded"
>
<template v-slot:header-organization="prop">
<div class="col">
<div
class="row items-center q-px-xs q-pt-xs q-gutter-sm"
>
<!--แสดงชอแผนก มพวหนา คลกแลวกาง/ Tree-->
<div class="text-weight-medium">
{{ prop.node.organizationName }}
</div>
<!--แสดง Total Count PositionNum-->
<!-- <q-badge rounded color="grey-2" text-color="dark"
:label="prop.node.totalPositionCount" /> -->
<q-badge
v-if="prop.node.totalPositionVacant > 0"
rounded
color="red"
outline
:label="prop.node.totalPositionVacant"
/>
<q-space />
</div>
<div class="col items-center q-px-xs q-pt-xs">
<div class="text-weight-medium text-grey-7">
{{ prop.node.governmentCode }}
{{ prop.node.organizationShortName }}
</div>
</div>
</div>
</template>
<template v-slot:header-person="prop">
<q-item
clickable
:active="selected == prop.node.keyId"
@click="selectedPosition(prop.node)"
:disable="
prop.node.name != null ||
checkPosition(prop.node.positionNumId) != -1
"
active-class="my-list-link text-primary text-weight-medium"
class="row items-center text-dark q-py-xs q-pl-sm rounded-borders my-list"
>
<img
v-if="
prop.node.avatar == '' ||
prop.node.avatar ==
'https://cdn.quasar.dev/img/boy-avatar.png'
"
src="@/assets/avatar_user.jpg"
class="col-xs-1 col-sm-2"
style="
width: 28px;
height: 28px;
border-radius: 50%;
"
/>
<img
v-else
:src="prop.node.avatar"
class="col-xs-1 col-sm-2"
style="
width: 28px;
height: 28px;
border-radius: 50%;
"
/>
<!--=====ตำแหนงวาง แดง=====-->
<div
v-if="prop.node.name == null"
class="q-px-sm text-weight-medium text-red"
>
าง
</div>
<!--=====วหน เขยว=====-->
<div v-else-if="prop.node.positionLeaderFlag">
<div
class="q-px-sm text-weight-medium text-primary"
>
{{ prop.node.name }}
</div>
</div>
<!--=====กนอง ปกต=====-->
<div v-else>
<div class="q-px-sm text-weight-medium">
{{ prop.node.name }}
</div>
</div>
<!--อทายชอคน แสดงสปกต-->
<div class="q-pr-sm">
{{ prop.node.positionName }}
</div>
<div class="q-pr-sm">
{{ prop.node.positionNum }}
</div>
<div class="q-pr-sm">
{{ prop.node.positionLevel }}
</div>
<q-icon
v-if="prop.node.positionLeaderFlag"
class="q-mr-sm"
size="15px"
color="primary"
name="mdi-bookmark"
></q-icon>
<q-space />
</q-item>
</template>
</q-tree>
</div>
</q-scroll-area>
</q-card>
</div>
<div class="col-xs-12 col-sm-5">
<q-card flat bordered class="fit q-pa-sm">
<q-scroll-area visible style="height: 70vh">
<div class="row col-12 q-col-gutter-xs">
<div class="col-xs-12 col-sm-12 col-md-12"></div>
<div class="col-xs-12 col-sm-12 col-md-12">
<datepicker
menu-class-name="modalfix"
v-model="dataForm.containDate"
:locale="'th'"
autoApply
:enableTimePicker="false"
week-start="0"
>
<template #year="{ year }">{{ year + 543 }}</template>
<template #year-overlay-value="{ value }">{{
parseInt(value + 543)
}}</template>
<template #trigger>
<q-input
class="full-width inputgreen cursor-pointer"
outlined
dense
:model-value="
date2Thai(new Date(dataForm.containDate))
"
:rules="[ (val: string) =>!!val ||`${'วันที่รายงานตัว'}`,
]"
:label="`${'วันที่รายงานตัว'}`"
hide-bottom-space
>
<template v-slot:prepend>
<q-icon
name="event"
class="cursor-pointer"
style="color: var(--q-primary)"
>
</q-icon>
</template>
</q-input>
</template>
</datepicker>
</div>
<q-space />
<div class="col-xs-12 col-sm-12 col-md-12">
<q-select
class="full-width inputgreen cursor-pointer custom-input"
outlined
standout
dense
hide-bottom-space
lazy-rules
:options="posNoOptions"
v-model="dataForm.posNoId"
:label="`${'ตำแหน่งเลขที่'}`"
map-options
/>
</div>
<div class="col-xs-12 col-sm-12 col-md-12">
<q-select
outlined
class="full-width inputgreen cursor-pointer custom-input"
standout
dense
hide-bottom-space
lazy-rules
:options="positionOptions"
v-model="dataForm.positionId"
:label="`${'ตำแหน่ง'}`"
map-options
/>
</div>
<div class="col-xs-12 col-sm-12 col-md-12">
<q-select
outlined
class="full-width inputgreen cursor-pointer custom-input"
standout
emit-value
dense
hide-bottom-space
lazy-rules
:options="positionPathSideOptions"
v-model="dataForm.positionPathSideId"
:label="`${'ด้าน/สาขา'}`"
map-options
/>
</div>
<div class="col-xs-12 col-sm-12 col-md-12">
<q-select
outlined
class="full-width inputgreen cursor-pointer custom-input"
standout
dense
hide-bottom-space
lazy-rules
:options="positionTypeOptions"
v-model="dataForm.positionTypeId"
:label="`${'ประเภทตำแหน่ง'}`"
map-options
/>
</div>
<div class="col-xs-12 col-sm-12 col-md-12">
<q-select
outlined
class="full-width inputgreen cursor-pointer custom-input"
standout
dense
hide-bottom-space
lazy-rules
:options="positionLineOptions"
v-model="dataForm.positionLineId"
:label="`${'สายงาน'}`"
map-options
/>
</div>
<div class="col-xs-12 col-sm-12 col-md-12">
<q-select
outlined
class="full-width inputgreen cursor-pointer custom-input"
standout
dense
lazy-rules
:options="positionLevelOptions"
v-model="dataForm.positionLevelId"
:label="`${'ระดับ'}`"
hide-bottom-space
:rules="[(val: string) => !!val || `${'กรุณาเลือกระดับ'}`]"
emit-value
map-options
/>
</div>
<!-- <div class="col-sx-12 col-sm-12 col-md-12">
<q-separator inset size="2px" class="q-my-md" />
</div> -->
<!-- <div class="col-xs-6 col-sm-6 col-md-6">
<q-input
outlined
dense
lazy-rules
v-model="dataForm.salaryAmount"
:rules="[(val) => !!val || `${'กรุณากรอกเงินเดือน'}`]"
:label="`${'เงินเดือน'}`"
@update:modelValue="clickEditRow"
type="number"
hide-bottom-space
/>
</div> -->
<!-- <div class="col-xs-6 col-sm-6 col-md-6">
<q-input
outlined
dense
lazy-rules
v-model="dataForm.positionSalaryAmount"
:rules="[
(val) => !!val || `${'กรุณากรอกเงินประจำตำแหน่ง'}`,
]"
:label="`${'เงินประจำตำแหน่ง'}`"
@update:modelValue="clickEditRow"
type="number"
hide-bottom-space
/>
</div> -->
<!-- <div class="col-xs-6 col-sm-6 col-md-6">
<q-input
outlined
dense
lazy-rules
v-model="dataForm.mouthSalaryAmount"
:rules="[
(val) =>
!!val || `${'กรุณากรอกเงินค่าตอบแทนรายเดือน'}`,
]"
:label="`${'เงินค่าตอบแทนรายเดือน'}`"
@update:modelValue="clickEditRow"
type="number"
hide-bottom-space
/>
</div> -->
</div>
</q-scroll-area>
</q-card>
</div>
</div>
</q-card-section>
<q-separator />
<DialogFooter
:editvisible="true"
:validate="validateData"
:save="saveAppoint"
v-model:modalEdit="editDataStatus"
/>
</q-form>
</q-card>
</q-dialog>
</template>
<style scoped lang="scss">
.q-tree__node-header {
padding: 0px;
margin-top: 0px;
border-radius: 4px;
outline: 0;
}
.my-list-link {
color: rgb(118, 168, 222);
border-radius: 5px;
background: #a3d3fb48 !important;
font-weight: 600;
border: 1px solid rgba(175, 185, 196, 0.217);
/* box-shadow: 1px 1px 7px 1px rgba(41, 95, 255, 0.15) !important; */
}
</style>

View file

@ -1,526 +0,0 @@
<script setup lang="ts">
import { onMounted, ref } from "vue";
import { useQuasar } from "quasar";
import { useRoute, useRouter } from "vue-router";
import { useCounterMixin } from "@/stores/mixin";
import http from "@/plugins/http";
import config from "@/app.config";
import CurrencyInput from "@/components/CurruncyInput.vue";
import type { QTableProps, QForm } from "quasar";
import PopupPersonal from "@/components/Dialogs/PopupPersonal.vue";
const modalPersonal = ref<boolean>(false);
const personId = ref<string>("");
const $q = useQuasar();
const route = useRoute();
const router = useRouter();
const mixin = useCounterMixin();
const edit = ref<boolean>(false);
const dataId = route.params.id as string;
const {
date2Thai,
dialogMessage,
messageError,
showLoader,
hideLoader,
success,
dialogConfirm,
} = mixin;
const roleAdmin = ref<boolean>(false);
const myForm = ref<QForm | null>(null);
const name = ref<string>("นายสมคิด ยอดใจ");
const level = ref<string>("ชำนาญการพิเศษ");
const institution = ref<string>("ฝ่ายบริหารงานทั่วไป");
const fullname = ref<string>("");
const profileId = ref<string>("");
const prefix = ref<string>("");
const prefixId = ref<string>("");
const firstname = ref<string>("");
const citizenId = ref<string>("");
const lastname = ref<string>("");
const position = ref<string>("");
const posNo = ref<string>("");
const positionLevel = ref<string>("");
const educationOld = ref<string>("");
const createdAt = ref<string>("");
const organization = ref<string>("");
const reason = ref<string>("");
const status = ref<string>("");
const date = ref<Date | null>(null);
const amount = ref<number>();
const amountOld = ref<number>();
const positionTypeOld = ref<string>("");
const positionLevelOld = ref<string>("");
const dateOfBirth = ref<Date>();
const genderId = ref<string>("");
const nationality = ref<string>("");
const race = ref<string>("");
const religionId = ref<string>("");
const bloodGroupId = ref<string>("");
const relationshipId = ref<string>("");
const telephoneNumber = ref<string>("");
const positionNumberOld = ref<string>("");
const organizationPositionOld = ref<string>("");
const isActive = ref<string>("");
// const responseData = ref<ResponseDataDetail>({
// createdAt: new Date(),
// date: new Date(),
// id: "",
// organization: "",
// organizationPositionOld: "",
// positionLevelOld: "",
// positionNumberOld: "",
// positionTypeOld: "",
// reason: "",
// salary: 0,
// status: "",
// });
// const rows = ref<TypeFile[]>([]);
// const columns = ref<QTableProps["columns"]>([
// {
// name: "no",
// align: "left",
// label: "",
// sortable: true,
// field: "no",
// headerStyle: "font-size: 14px",
// style: "font-size: 14px",
// },
// {
// name: "fileName",
// align: "left",
// label: "",
// sortable: true,
// field: "fileName",
// headerStyle: "font-size: 14px",
// style: "font-size: 14px",
// },
// {
// name: "btnMicrosoft",
// align: "right",
// label: "",
// sortable: true,
// field: "btnMicrosoft",
// headerStyle: "font-size: 14px",
// style: "font-size: 14px",
// },
// ]);
const getData = async () => {
showLoader();
await http
.get(config.API.relocationDetail(dataId))
.then((res: any) => {
const data = res.data.result;
profileId.value = data.profileId;
citizenId.value = data.citizenId;
fullname.value = `${data.prefix}${data.firstname} ${data.lastname}`;
prefixId.value = data.prefixId;
prefix.value = data.prefix;
firstname.value = data.firstname;
lastname.value = data.lastname;
educationOld.value = data.educationOld;
position.value = data.position;
posNo.value = data.posNo;
positionLevel.value = data.positionLevel;
createdAt.value = data.createdAt;
organization.value = data.organization;
reason.value = data.reason;
status.value = data.status;
date.value = data.date;
amount.value = data.amount;
amountOld.value = data.amountOld;
positionTypeOld.value = data.positionTypeOld;
positionLevelOld.value = data.positionLevelOld;
positionNumberOld.value = data.positionNumberOld;
organizationPositionOld.value = data.organizationPositionOld;
dateOfBirth.value = data.dateOfBirth;
genderId.value = data.genderId;
nationality.value = data.nationality;
race.value = data.race;
religionId.value = data.religionId;
bloodGroupId.value = data.bloodGroupId;
relationshipId.value = data.relationshipId;
telephoneNumber.value = data.telephoneNumber;
isActive.value = data.isActive;
})
.catch((e) => {
// messageError($q, e);
})
.finally(() => {
hideLoader();
});
};
const getClass = (val: boolean) => {
return {
"full-width inputgreen cursor-pointer": val,
"full-width cursor-pointer": !val,
};
};
//
const conditionSave = async () => {
if (myForm.value !== null) {
myForm.value.validate().then((success: any) => {
if (success) {
dialogConfirm(
$q,
async () => await saveData(),
"ต้องการแก้ไขข้อมูลหรือไม่?",
"แก้ไขข้อมูลเพื่อลงบัญชีแนบท้าย"
);
}
});
}
};
const cancelBtn = () => {
edit.value = !edit;
getData();
};
const saveData = async () => {
const body = {
educationOld: educationOld.value,
prefixId: prefixId.value,
citizenId: citizenId.value,
firstname: firstname.value,
lastname: lastname.value,
reason: reason.value,
organizationPositionOld: organizationPositionOld.value,
positionTypeOld: positionTypeOld.value,
positionLevelOld: positionLevelOld.value,
positionNumberOld: positionNumberOld.value,
amount: amount.value,
amountOld: amountOld.value,
dateOfBirth: dateOfBirth.value,
genderId: genderId.value,
nationality: nationality.value,
race: race.value,
religionId: religionId.value,
bloodGroupId: bloodGroupId.value,
relationshipId: relationshipId.value,
telephoneNumber: telephoneNumber.value,
};
showLoader();
await http
.put(config.API.relocationMainEdit(dataId), body)
.then(() => {
success($q, "แก้ไขข้อมูลเพื่อลงบัญชีแนบท้ายสำเร็จ");
edit.value = false;
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await getData();
hideLoader();
});
};
function onclickViewinfo(id: string) {
modalPersonal.value = true;
personId.value = id;
}
function updatemodalPersonal(modal: boolean) {
modalPersonal.value = modal;
}
onMounted(async () => {
await getData();
});
</script>
<template>
<div class="toptitle text-dark col-12 row items-center">
<q-btn
icon="mdi-arrow-left"
unelevated
round
dense
flat
color="primary"
class="q-mr-sm"
@click="router.go(-1)"
/>
รายละเอยดการยาย {{ fullname }}
</div>
<q-card bordered class="row col-12 text-dark">
<div class="bg-grey-1 q-pa-sm col-12 row items-center text-primary">
<div class="q-pl-sm text-weight-bold text-subtitle2">{{ fullname }}</div>
<q-space />
<q-btn
outline
color="blue"
dense
icon-right="mdi-open-in-new"
class="q-px-sm"
label="ดูข้อมูลทะเบียนประวัติ"
@click="onclickViewinfo(profileId)"
/>
</div>
<div class="col-12"><q-separator /></div>
<div class="row col-12 q-pa-md">
<div class="col-12 row bg-white q-col-gutter-md">
<div class="col-xs-3 col-sm-2 col-md-1 row">
<q-img src="@/assets/avatar_user.jpg" />
</div>
<div class="col-xs-6 col-sm-3 row items-center">
<div class="col-12 q-pl-md">
<div class="col-12 text-top">ตำแหนงในสายงาน</div>
<div class="col-12 text-detail">
{{ positionTypeOld }}
</div>
</div>
</div>
<div class="col-xs-6 col-sm-3 row items-center">
<div class="col-12">
<div class="col-12 text-top">ระด</div>
<div class="col-12 text-detail">
{{ positionLevelOld }}
</div>
</div>
</div>
<div class="col-xs-6 col-sm-3 row items-center">
<div class="col-12">
<div class="col-12 text-top">งก</div>
<div class="col-12 text-detail">
{{ organizationPositionOld }}
</div>
</div>
</div>
</div>
</div>
</q-card>
<q-card bordered class="row col-12 text-dark q-mt-sm">
<div class="bg-grey-1 q-pa-sm col-12 row items-center text-primary">
<div class="q-pl-sm text-weight-bold text-dark">
แกไขขอมลเพอลงบญชแนบทาย
</div>
<q-space />
<div v-if="status !== 'REPORT' && status !== 'DONE'">
<div class="q-gutter-sm" v-if="!edit">
<q-btn
outline
color="primary"
dense
icon-right="mdi-file-edit-outline"
class="q-px-sm"
label="แก้ไข"
style="width: 80px"
@click="edit = !edit"
/>
</div>
<div class="q-gutter-sm" v-else>
<q-btn
outline
color="public"
dense
class="q-px-sm"
label="บันทึก"
style="width: 80px"
@click="conditionSave"
/>
<q-btn
outline
color="red"
dense
class="q-px-sm"
label="ยกเลิก"
style="width: 80px"
@click="cancelBtn"
/>
</div>
</div>
</div>
<div class="col-12"><q-separator /></div>
<q-form ref="myForm">
<div class="row col-12 q-pa-md">
<div class="col-12 row bg-white q-col-gutter-md">
<div class="col-xs-6 col-sm-3 row items-center">
<div class="text-weight-bold text-grey">การศกษา</div>
<div class="col-12">
<q-input
:class="getClass(edit)"
:outlined="edit"
dense
lazy-rules
:readonly="!edit"
:borderless="!edit"
v-model="educationOld"
:rules="[(val) => !!val || `${'กรุณากรอกประเภทตำแหน่ง'}`]"
hide-bottom-space
:label="`${'วุฒิ/สาขา'}`"
/>
</div>
</div>
<div class="col-xs-12 row items-center">
<div class="col-12 q-pb-sm"><q-separator /></div>
<div class="col-12">
<div class="text-weight-bold text-grey">ตำแหน/งกดเด</div>
</div>
<div class="col-12">
<q-input
:class="getClass(edit)"
:outlined="edit"
dense
lazy-rules
:readonly="!edit"
:borderless="!edit"
v-model="organizationPositionOld"
:rules="[(val) => !!val || `${'กรุณากรอกตำแหน่ง/สังกัด'}`]"
hide-bottom-space
:label="`${'ตำแหน่ง/สังกัด'}`"
type="textarea"
/>
</div>
</div>
<div class="col-xs-6 col-sm-3 row items-center">
<div class="col-12">
<q-input
:class="getClass(edit)"
:outlined="edit"
dense
lazy-rules
:readonly="!edit"
:borderless="!edit"
v-model="positionTypeOld"
:rules="[(val) => !!val || `${'กรุณากรอกประเภทตำแหน่ง'}`]"
hide-bottom-space
:label="`${'ประเภทตำแหน่ง'}`"
/>
</div>
</div>
<div class="col-xs-6 col-sm-3 row items-center">
<div class="col-12">
<q-input
:class="getClass(edit)"
:outlined="edit"
dense
lazy-rules
:readonly="!edit"
:borderless="!edit"
v-model="positionLevelOld"
:rules="[(val) => !!val || `${'กรุณากรอกระดับ'}`]"
hide-bottom-space
:label="`${'ระดับ'}`"
/>
</div>
</div>
<div class="col-xs-6 col-sm-3 row items-center">
<div class="col-12">
<q-input
:class="getClass(edit)"
:outlined="edit"
dense
lazy-rules
:readonly="!edit"
:borderless="!edit"
v-model="positionNumberOld"
:rules="[(val) => !!val || `${'กรุณากรอกเลขที่'}`]"
hide-bottom-space
:label="`${'เลขที่'}`"
/>
</div>
</div>
<div class="col-xs-6 col-sm-3 row items-center">
<div class="col-12">
<CurrencyInput
v-model="amountOld"
:edit="edit"
:options="{
currency: 'THB',
}"
:label="`${'เงินเดือน'}`"
/>
</div>
</div>
<div class="col-12"><q-separator /></div>
<!-- <div class="col-xs-6 col-sm-6 row items-center">
<div class="col-12">
<q-input
:class="getClass(edit)"
:outlined="edit"
dense
lazy-rules
:readonly="!edit"
:borderless="!edit"
v-model="organization"
:rules="[(val) => !!val || `${'กรุณากรอกโอนไปสังกัด'}`]"
hide-bottom-space
:label="`${'โอนไปสังกัด'}`"
/>
</div>
</div> -->
<div class="col-xs-6 col-sm-3 row items-center">
<div class="text-weight-bold text-grey col-12">
เงนเดอนตำแหนงและหนวยงานทบยาย
</div>
<div class="col-12">
<!-- <q-input
:class="getClass(edit)"
:outlined="edit"
dense
lazy-rules
:readonly="!edit"
:borderless="!edit"
v-model="amount"
:rules="[(val) => !!val || `${'กรุณากรอกเงินเดือน'}`]"
hide-bottom-space
:label="`${'เงินเดือน'}`"
type="number"
/> -->
<CurrencyInput
v-model="amount"
:edit="edit"
:options="{
currency: 'THB',
}"
:label="`${'เงินเดือน'}`"
/>
</div>
</div>
<div class="col-12">
<q-input
:class="getClass(edit)"
:outlined="edit"
dense
lazy-rules
:readonly="!edit"
:borderless="!edit"
v-model="reason"
:rules="[(val) => !!val || `${'กรุณากรอกหมายเหตุ '}`]"
hide-bottom-space
:label="`${'หมายเหตุ '}`"
type="textarea"
/>
</div>
</div>
</div>
</q-form>
</q-card>
<PopupPersonal
:modal="modalPersonal"
:id="personId"
@update:modal="updatemodalPersonal"
/>
</template>
<style lang="scss" scope>
.q-img {
border-radius: 5px;
height: 70px;
}
.text-top {
color: gray;
font-weight: 400;
padding-bottom: 3px;
}
.text-detail {
font-weight: 500;
}
</style>

View file

@ -1,8 +1,11 @@
<script setup lang="ts">
import { ref, computed, watch } from "vue";
import { useQuasar } from "quasar";
import http from "@/plugins/http";
import config from "@/app.config";
import { useCounterMixin } from "@/stores/mixin";
import { useTransferDataStore } from "@/modules/05_placement/store";
/**
* impportType
@ -18,8 +21,6 @@ import DialogHeader from "@/components/DialogHeader.vue";
/**
* importStore
*/
import { useCounterMixin } from "@/stores/mixin";
import { useTransferDataStore } from "@/modules/05_placement/store";
const $q = useQuasar();
const { statusText } = useTransferDataStore();

View file

@ -9,7 +9,7 @@ import http from "@/plugins/http";
import config from "@/app.config";
import genReport from "@/plugins/genreport";
import type { QTableProps, QForm } from "quasar";
import type { QTableProps } from "quasar";
import type { DataProfile } from "@/modules/05_placement/interface/index/Main";
import type {
TypeFile,
@ -38,15 +38,14 @@ const roleAdmin = ref<boolean>(false); //admin
const edit = ref<boolean>(false); //
const dataProfile = ref<DataProfile>(); //
const organizationPositionOld = ref<string>("");
const positionTypeOld = ref<string>("");
const positionLevelOld = ref<string>("");
const posNo = ref<string>("");
const salary = ref<number>(0);
const organization = ref<string>("");
const date = ref<Date | null>(null);
const reason = ref<string>("");
const rows = ref<TypeFile[]>([]); //
const organizationPositionOld = ref<string>(""); ///
const positionTypeOld = ref<string>(""); //
const positionLevelOld = ref<string>(""); //
const posNo = ref<string>(""); //
const salary = ref<number>(0); //
const organization = ref<string>(""); //
const date = ref<Date | null>(null); //
const reason = ref<string>(""); //
//
const responseData = ref<ResponseDataDetail>({
profileId: "",
@ -65,6 +64,7 @@ const responseData = ref<ResponseDataDetail>({
fullname: "",
});
const rows = ref<TypeFile[]>([]); //
const columns = ref<QTableProps["columns"]>([
{
name: "no",

View file

@ -6,7 +6,7 @@ import { useCounterMixin } from "@/stores/mixin";
import { useRouter, useRoute } from "vue-router";
import http from "@/plugins/http";
import config from "@/app.config";
import criterion from "@/modules/05_placement/components/Other/Criterion.vue";
import criterion from "@/modules/05_placement/components/probation/Criterion.vue";
import type { ListDataText } from "@/modules/05_placement/interface/index/Main";
const router = useRouter();

View file

@ -6,7 +6,7 @@ import { useCounterMixin } from "@/stores/mixin";
import { useRoute, useRouter } from "vue-router";
import http from "@/plugins/http";
import config from "@/app.config";
import criterion from "@/modules/05_placement/components/Other/Criterion.vue";
import criterion from "@/modules/05_placement/components/probation/Criterion.vue";
import type { ListDataText } from "@/modules/05_placement/interface/index/Main";
const $q = useQuasar();

View file

@ -6,7 +6,7 @@ import { useCounterMixin } from "@/stores/mixin";
import { useRouter, useRoute } from "vue-router";
import http from "@/plugins/http";
import config from "@/app.config";
import criterion from "@/modules/05_placement/components/Other/Criterion.vue";
import criterion from "@/modules/05_placement/components/probation/Criterion.vue";
import type { ListDataText } from "@/modules/05_placement/interface/index/Main";

View file

@ -6,7 +6,7 @@ import { useCounterMixin } from "@/stores/mixin";
import { useRoute, useRouter } from "vue-router";
import http from "@/plugins/http";
import config from "@/app.config";
import criterion from "@/modules/05_placement/components/Other/Criterion.vue";
import criterion from "@/modules/05_placement/components/probation/Criterion.vue";
import type { ListDataText } from "@/modules/05_placement/interface/index/Main";

View file

@ -8,7 +8,7 @@ import { useRouter, useRoute } from "vue-router";
import http from "@/plugins/http";
import config from "@/app.config";
import criterion from "@/modules/05_placement/components/Other/Criterion.vue";
import criterion from "@/modules/05_placement/components/probation/Criterion.vue";
import type { ListDataText } from "@/modules/05_placement/interface/index/Main";
const router = useRouter();

View file

@ -10,7 +10,7 @@ import { useRoute, useRouter } from "vue-router";
import http from "@/plugins/http";
import config from "@/app.config";
import criterion from "@/modules/05_placement/components/Other/Criterion.vue";
import criterion from "@/modules/05_placement/components/probation/Criterion.vue";
const $q = useQuasar();
const route = useRoute();

View file

@ -8,7 +8,7 @@ import { useRoute, useRouter } from "vue-router";
import http from "@/plugins/http";
import config from "@/app.config";
import criterion from "@/modules/05_placement/components/Other/Criterion.vue";
import criterion from "@/modules/05_placement/components/probation/Criterion.vue";
import type { ListDataText } from "@/modules/05_placement/interface/index/Main";

View file

@ -9,7 +9,7 @@ import { useRouter, useRoute } from "vue-router";
import http from "@/plugins/http";
import config from "@/app.config";
import criterion from "@/modules/05_placement/components/Other/Criterion.vue";
import criterion from "@/modules/05_placement/components/probation/Criterion.vue";
import type { ListDataText } from "@/modules/05_placement/interface/index/Main";

View file

@ -402,6 +402,7 @@ onMounted(async () => {
<div class="toptitle text-dark col-12 row items-center">
รายการผทดลองปฏหนาทราชการ
</div>
<q-card flat bordered class="col-12 q-mt-sm q-pa-md">
<div class="row q-col-gutter-sm">
<div class="row col-12 q-col-gutter-sm">

View file

@ -5,7 +5,7 @@ import { useCounterMixin } from "@/stores/mixin";
import { useRoute } from "vue-router";
import http from "@/plugins/http";
import config from "@/app.config";
import criterion from "@/modules/05_placement/components/Other/Criterion.vue";
import criterion from "@/modules/05_placement/components/probation/Criterion.vue";
import type { ListDataText } from "@/modules/05_placement/interface/index/Main";
const optionText = ref<ListDataText[]>([

View file

@ -283,6 +283,14 @@ interface ListMenu {
type: string;
color: string;
}
interface DataEducation {
university: string;
degree: string;
major: string;
graduation: string;
}
export type {
DataOption,
DataOptionInsignia,
@ -307,6 +315,7 @@ export type {
tableType,
ListDataText,
ListMenu,
DataEducation,
};
export { AddressDataDefualt, FamilyDataDefualt };

View file

@ -2,4 +2,103 @@ interface OpType {
commandCode: string;
id: string;
}
export type { OpType };
interface DataPerson {
age: string;
bloodGroup: string;
bmaOfficer: string;
certificates: [
{
certificateNo: string;
certificateType: string;
expireDate: string;
id: string;
issueDate: string;
issuer: string;
}
];
couple: boolean;
currentAddress: string;
currentDistrictId: string;
currentProvinceId: string;
currentSubDistrictId: string;
currentZipCode: string;
dateOfBirth: any;
docs: any;
draft: boolean;
education: Education[];
examNumber: number;
examRound: string;
fatherFirstName: string;
fatherLastName: string;
fatherOccupation: string;
fatherPrefix: string;
firstname: string;
fullName: string;
gender: string;
idCard: string;
isProperty: [
{
name: string;
value: boolean;
}
];
isRelief: boolean;
lastname: string;
marryFirstName: string;
marryLastName: string;
marryOccupation: string;
marryPrefix: string;
motherFirstName: string;
motherLastName: string;
motherOccupation: string;
motherPrefix: string;
nationality: string;
pass: string;
personalId: string;
point: number;
pointA: number;
pointB: number;
pointC: number;
pointTotal: number;
pointTotalA: number;
pointTotalB: number;
pointTotalC: number;
positionCandidate: string;
positionCandidateId: string;
prefix: string;
race: string;
registAddress: string;
registDistrictId: string;
registProvinceId: string;
registSame: boolean;
registSubDistrictId: string;
registZipCode: string;
relationship: string;
religion: string;
telephone: string;
}
interface Education {
country: string;
degree: string;
duration: string;
durationYear: string;
educationLevel: string;
educationLevelId: string;
endDate: string;
field: string;
finishDate: Date;
fundName: string;
gpa: string;
id: string;
institute: string;
isDate: boolean;
isEducation: string;
other: string;
positionPath: string;
positionPathId: string;
startDate: string;
}
export type { OpType, DataPerson, Education };

View file

@ -7,7 +7,7 @@ const PlacementMain = () => import("@/modules/05_placement/views/01_Main.vue");
const PlacementDetail = () =>
import("@/modules/05_placement/components/PersonalList/PersonalListPage.vue");
const PlacementPersonalDetail = () =>
import("@/modules/05_placement/components/PersonalDetail/Detail.vue");
import("@/modules/05_placement/components/PersonalDetail/DetailMain.vue");
// รายการขอโอน
const transfer = () =>
@ -19,27 +19,55 @@ const transferbyId = () =>
const receiveMain = () =>
import("@/modules/05_placement/views/03_receiveMain.vue");
const ReceiveAdd = () =>
import("@/modules/05_placement/components/Receive/FormAdd.vue");
import("@/modules/05_placement/components/Receive/ReceiveAddPerson.vue");
const receiveDetail2 = () =>
import("@/modules/05_placement/components/Receive/receiveDetail2.vue");
import("@/modules/05_placement/components/Receive/ReceiveDetail.vue");
//รายการช่วยราชการ
const helpgovernment = () =>
import("@/modules/05_placement/views/04_helpGovernmentMain.vue");
const helpgovernmentbyId = () =>
import(
"@/modules/05_placement/components/Help-Government/HelpGovernmentDetail.vue"
);
//รายการส่งตัวกลับ
const repatriate = () =>
import("@/modules/05_placement/views/05_repatriateMain.vue");
const repatriatebyId = () =>
import("@/modules/05_placement/components/Repatriate/RepatriateDetail.vue");
//รายการแต่งตั้ง-เลื่อน-ย้าย
const AppointmentMain = () =>
import("@/modules/05_placement/views/06_appointPromoteMain.vue");
const AppointmentDetail = () =>
import("@/modules/05_placement/components/AppointMent/AppointMentDetail.vue");
//รายการปรับระดับชั้นงานลูกจ้าง
const AppointEmployeeMain = () =>
import("@/modules/05_placement/views/07_appointEmployeeMain.vue");
const AppointEmployeeDetail = () =>
import("@/modules/05_placement/components/AppointEmployee/AppointEmployeeDetail.vue");
//อื่นๆ
const OtherMain = () =>
import("@/modules/05_placement/views/08_otherMain.vue");
const OthertDetail = () =>
import("@/modules/05_placement/components/Other/OtherDetail.vue");
// ระบบทดลองงาน
const mainProbation = () =>
import("@/modules/05_placement/components/probation/MainProbation.vue");
const probationDetail = () =>
import("@/modules/05_placement/components/probation/ProbationDetail.vue");
const probationFormEvaluation = () =>
import("@/modules/05_placement/components/probation/MainDetail.vue");
const probationFormEvaluationDetail = () =>
import("@/modules/05_placement/components/probation/MainDetail.vue");
const probationWorkAdd = () =>
import("@/modules/05_placement/components/probation/MainDetail.vue");
const probationFormAssign = () =>
import("@/modules/05_placement/components/probation/FormAssign.vue");
const FormSaveResultAdd = () =>
import(
"@/modules/05_placement/components/probation/FormEvaluation/FormSaveResultAdd.vue"
@ -57,41 +85,6 @@ const FormSaveResultAddCommander = () =>
"./components/probation/FormEvaluation/FormSaveResultAddCommander.vue"
);
const helpgovernment = () =>
import("@/modules/05_placement/components/helpgovernment/mainHelp.vue");
const helpgovernmentbyId = () =>
import(
"@/modules/05_placement/components/helpgovernment/governmentDetail.vue"
);
const repatriate = () =>
import("@/modules/05_placement/components/Repatriate/RepatriateMain.vue");
const repatriatebyId = () =>
import("@/modules/05_placement/components/Repatriate/RepatriatebyId.vue");
const relocation = () =>
import("@/modules/05_placement/components/Relocation/RelocationMain.vue");
const relocationbyId = () =>
import("@/modules/05_placement/components/Relocation/RelocationbyId.vue");
//รับโอน
// const receiveDetail = () =>
// import("@/modules/05_placement/components/Receive/receiveDetail.vue");
//แต่งตั้ง-เลื่อน
const AppointmentMain = () =>
import("@/modules/05_placement/components/AppointMent/Main.vue");
const AppointmentDetail = () =>
import("@/modules/05_placement/components/AppointMent/Detail.vue");
//แต่งตั้งลูกจ้างประจำ
const AppointEmployeeMain = () =>
import("@/modules/05_placement/components/AppointEmployee/Main.vue");
const AppointEmployeeDetail = () =>
import("@/modules/05_placement/components/AppointEmployee/Detail.vue");
//อื่นๆ
const OtherMain = () =>
import("@/modules/05_placement/components/Other/Main.vue");
const OthertDetail = () =>
import("@/modules/05_placement/components/Other/Detail.vue");
export default [
{
path: "/placement",
@ -255,6 +248,7 @@ export default [
Role: "STAFF",
},
},
//รายการรับโอน
{
path: "/placement/receive",
@ -286,6 +280,8 @@ export default [
Role: "STAFF",
},
},
//รายการช่วยราชการ
{
path: "/placement/help-government",
name: "help-government",
@ -306,6 +302,8 @@ export default [
Role: "STAFF",
},
},
// รายการส่งตัวกลับ
{
path: "/placement/repatriate",
name: "repatriate",
@ -326,6 +324,8 @@ export default [
Role: "STAFF",
},
},
// รายการแต่งตั้ง-เลื่อน-ย้าย
{
path: "/placement/appoint-promote",
name: "appoint-promote",
@ -346,6 +346,8 @@ export default [
Role: "STAFF",
},
},
//รายการปรับระดับชั้นงานลูกจ้าง
{
path: "/placement/appoint-employee",
name: "appoint-employee",
@ -386,54 +388,4 @@ export default [
Role: "STAFF",
},
},
// {
// path: "/relocation",
// name: "relocation",
// component: relocation,
// meta: {
// Auth: true,
// Key: [6.1],
// Role: "placement",
// },
// },
// {
// path: "/relocation/detail/:id",
// name: "relocationId",
// component: relocationbyId,
// meta: {
// Auth: true,
// Key: [6.9],
// Role: "placement",
// },
// },
// {
// path: "/change-positions",
// name: "changePositions",
// component: ChangePositionMain,
// meta: {
// Auth: true,
// Key: "",
// Role: "STAFF",
// },
// },
// {
// path: "/change-positions/:id",
// name: "changePersonalList",
// component: ChangePersonalList,
// meta: {
// Auth: true,
// Key: "",
// Role: "placement",
// },
// },
// {
// path: "/change-positions/personal/:id",
// name: "changePersonalId",
// component: ChangePersonalDetail,
// meta: {
// Auth: true,
// Key: "",
// Role: "placement",
// },
// },
];

View file

@ -312,8 +312,6 @@ async function expiredAccountFilter() {
await DataStore.DataMain(updatedRows);
}
/** filter ใน dropdown ครั้งที่ */
/**
* งช กรอกขอมลเพ นหา
* @param val าทกรอก
@ -376,7 +374,9 @@ function paginationLabel(start: number, end: number, total: number) {
else return start + "-" + end + " ใน " + total;
}
/** เรียกใช้ฟังชั่น เมื่อเริ่มหน้านี้ */
/**
* เรยกใชงช เมอเรมหนาน
*/
onMounted(async () => {
await fetchYearOptions();
});

View file

@ -21,14 +21,13 @@ const { statusText } = useTransferDataStore();
const { date2Thai, messageError, showLoader, hideLoader } = mixin;
const modal = ref<boolean>(false); //
const rowsOrder = ref<ResponseData[]>([]);
const filterOrder = ref<string>("");
const filterMain = ref<string>(""); //
const rows = ref<ResponseData[]>([]);
const dataTransfer = ref<ResponseData[]>([]);
const dataTransfer = ref<ResponseData[]>([]); //
//Table
const rows = ref<ResponseData[]>([]); //
const filterMain = ref<string>(""); //
const rowsOrder = ref<ResponseData[]>([]); //
const filterOrder = ref<string>(""); //
const columns = ref<QTableProps["columns"]>([
{
name: "no",

View file

@ -15,8 +15,8 @@ import type {
ResponseRow,
} from "@/modules/05_placement/interface/response/Receive";
import Dialogbody from "@/modules/05_placement/components/Receive/Dialogbody.vue";
import DialogHeader from "@/modules/05_placement/components/Receive/DialogHeader.vue";
import Dialogbody from "@/modules/05_placement/components/Receive/DialogOrders.vue";
import DialogHeader from "@/components/DialogHeader.vue";
import DialogOrgSelect from "@/components/Dialogs/DialogOrgSelect.vue";
const $q = useQuasar();
@ -34,27 +34,27 @@ const {
} = mixin;
const dataRecevice = ref<ResponseData[]>([]); //
const filters = ref<ResponseRow[]>([]); //
const dataRows = ref<ResponseRow>(); //
const modal = ref<boolean>(false); // popup
const modalupload = ref<boolean>(false); // popup
const modalTree = ref<boolean>(false); // popup
const dataRows = ref<any[]>([]);
const rows2 = ref<ResponseRow[]>([]);
const modal = ref<boolean>(false);
const modalupload = ref<boolean>(false);
const modalTree = ref<boolean>(false);
const myForm = ref<any>();
const personal = ref<ResponseData[]>([]);
const personalId = ref<string>("");
const filterKeyword = ref<string>("");
const filterKeyword2 = ref<string>("");
const filterRef = ref<any>(null);
const files = ref<any>();
const filters = ref<ResponseRow[]>([]);
const rows = ref<ResponseRow[]>([]);
const posType = ref<string>("");
const posLevel = ref<string>("");
const position = ref<string>("");
const personal = ref<ResponseData[]>([]); //
const personalId = ref<string>(""); //
const files = ref<any>(); //
const posType = ref<string>(""); //
const posLevel = ref<string>(""); //
const position = ref<string>(""); //
const type = ref<string | null>(null);
//Table
const rows = ref<ResponseRow[]>([]); //
const rows2 = ref<ResponseRow[]>([]); //
const filterKeyword = ref<string>(""); //
const filterKeyword2 = ref<string>(""); //
const visibleColumns = ref<string[]>([
"no",
"citizenId",
@ -143,6 +143,9 @@ const columns = ref<QTableProps["columns"]>([
},
]);
/**
* งกนดงขอมลรายการรบโอน
*/
async function fecthlistRecevice() {
showLoader();
await http
@ -189,45 +192,58 @@ function onSubmitDoc() {
});
}
//
const resetFilter = () => {
/**
* งกนบรเซตคาในฟลเตอร
*/
function resetFilter() {
filterKeyword.value = "";
filterKeyword2.value = "";
filterRef.value.focus();
};
//
const clickClose = () => {
}
/**
* งกนป popup ออกคำส
*/
function clickClose() {
modal.value = false;
filterKeyword2.value = "";
};
//
const clickCloseUpload = () => {
}
/**
* งกนป popup ปเดตไฟล
*/
function clickCloseUpload() {
modalupload.value = false;
files.value = null;
};
//
const openModalTree = (id: string, data: any) => {
}
/**
* งกนเป popup เลอกหนวยงานทบโอน
*/
function openModalTree(id: string, data: any) {
personalId.value = id;
personal.value = dataRecevice.value.filter((e: ResponseData) => e.id === id);
dataRows.value = data;
modalTree.value = true;
type.value = null;
dataRows.value = data;
// console.log("data===>", data);
posType.value = data.posTypeOldId;
posLevel.value = data.posLevelOldId;
position.value = data.positionOld;
};
//
const openUpload = (id: string) => {
}
/**
* งกนเป popup ปเดตไฟล
* @param id รายการทองการอปเดตไฟล
*/
function openUpload(id: string) {
personalId.value = id;
modalupload.value = true;
};
//
const openDelete = (id: string) => {
}
/**
* งกนยนยนการลบขอม
* @param id รายการทองการลบ
*/
function openDelete(id: string) {
dialogRemove($q, async () => {
showLoader();
await http
@ -241,16 +257,24 @@ const openDelete = (id: string) => {
hideLoader();
});
});
};
}
//
const nextPage = (id: string) => {
/**
* งกนไปหนารายละเอยด
* @param id รายการทองการดรายละเอยก
*/
function nextPage(id: string) {
router.push({
path: `/placement/receive/${id}`,
});
};
}
const popup = () => {
/**
* งกนสงไปออกคำส
*
* นหารายชอออกคำสงตามสถานะ อน (APPROVE)
*/
function openModalOrder() {
const row = filters.value.filter(
(r: any) =>
(r.status == "WAITTING" ||
@ -267,10 +291,9 @@ const popup = () => {
rows2.value = row;
modal.value = true;
};
}
function onSave(data: any) {
console.log("not save", data);
const dataAppoint = {
node: data.node,
nodeId: data.nodeId,
@ -303,6 +326,9 @@ function onSave(data: any) {
});
}
/**
* ทำงานเมอมการเรยกใช Components
*/
onMounted(() => {
fecthlistRecevice();
});
@ -331,7 +357,7 @@ onMounted(() => {
round
color="add"
icon="mdi-account-arrow-right"
@click="popup()"
@click="openModalOrder()"
>
<q-tooltip>งไปออกคำสงรบโอน</q-tooltip>
</q-btn>
@ -550,34 +576,23 @@ onMounted(() => {
</div>
</q-card>
<!-- ออกคำส -->
<Dialogbody
v-model:Modal="modal"
:clickClose="clickClose"
:rows2="rows2"
v-model:filterKeyword2="filterKeyword2"
:fecthlistRecevice="fecthlistRecevice"
:nextPage="nextPage"
/>
<!-- ปโหลดเอกสาร -->
<q-dialog v-model="modalupload">
<q-card style="width: 600px">
<q-form greedy @submit.prevent @validation-success="onSubmitDoc">
<DialogHeader title="อัปโหลดเอกสาร" :close="clickCloseUpload" />
<DialogHeader tittle="อัปโหลดเอกสาร" :close="clickCloseUpload" />
<q-separator />
<q-card-section class="q-py-sm">
<div class="col-12 row items-center q-col-gutter-sm">
<div class="col-12">
<q-file
ref="myForm"
outlined
dense
v-model="files"
label="อัปโหลดเอกสาร"
lazy-rules
:rules="[
(val) => val || 'กรุณาเลือกไฟล์หนังสือถึงหน่วยงานที่รับโอน',
(val:string) => val || 'กรุณาเลือกไฟล์หนังสือถึงหน่วยงานที่รับโอน',
]"
hide-bottom-space
>
@ -599,6 +614,16 @@ onMounted(() => {
</q-card>
</q-dialog>
<!-- ออกคำส -->
<Dialogbody
v-model:modal="modal"
v-model:filter-keyword2="filterKeyword2"
:click-close="clickClose"
:rows2="rows2"
:fecthlist-recevice="fecthlistRecevice"
:next-page="nextPage"
/>
<!-- เลอกหนวยงานทบโอน -->
<DialogOrgSelect
:title="`เลือกหน่วยงานที่รับโอน`"

View file

@ -1,8 +1,13 @@
<script setup lang="ts">
import { ref, onMounted } from "vue";
import { checkPermission } from "@/utils/permissions";
import { useQuasar } from "quasar";
import { checkPermission } from "@/utils/permissions";
import { useRouter } from "vue-router";
import { useTransferDataStore } from "@/modules/05_placement/store";
import { useCounterMixin } from "@/stores/mixin";
import http from "@/plugins/http";
import config from "@/app.config";
/**
* importType
@ -13,21 +18,12 @@ import type { officerType } from "@/modules/05_placement/interface/response/offi
/**
* importComponents
*/
import Dialogbody from "@/modules/05_placement/components/helpgovernment/Dialogbody.vue";
import http from "@/plugins/http";
import config from "@/app.config";
/**
* importStore
*/
import { useTransferDataStore } from "@/modules/05_placement/store";
import { useCounterMixin } from "@/stores/mixin";
const transferStore = useTransferDataStore();
const { statusText } = transferStore;
import Dialogbody from "@/modules/05_placement/components/Help-Government/DialogOrders.vue";
const $q = useQuasar();
const router = useRouter();
const transferStore = useTransferDataStore();
const { statusText } = transferStore;
const mixin = useCounterMixin();
const {
date2Thai,
@ -43,14 +39,12 @@ const {
/**
* Table
*/
const filterKeyword = ref<string>("");
const filterKeyword2 = ref<string>("");
const filterRef = ref<any>(null);
const rows = ref<officerType[]>([]);
const rows2 = ref<officerType[]>([]);
const modal = ref<boolean>(false);
const modal = ref<boolean>(false); // popup ;
//
const filterKeyword = ref<string>(""); //
const filterKeyword2 = ref<string>(""); //
const rows = ref<officerType[]>([]); //
const rows2 = ref<officerType[]>([]); //
const columns = ref<QTableProps["columns"]>([
{
name: "no",
@ -191,12 +185,12 @@ const visibleColumns = ref<string[]>([
/**
* fetch รายการชวยราชการ
*/
function getData() {
async function getData() {
showLoader();
http
await http
.get(config.API.officerMain())
.then((res: any) => {
const data = res.data.result;
.then(async (res) => {
const data = await res.data.result;
rows.value = data;
})
.catch((e) => {
@ -209,7 +203,7 @@ function getData() {
/**
* นยนการลบรายการชวยราชการ
* @param id
* @param id รายการทองการลบ
*/
function clickDelete(id: string) {
dialogRemove($q, () => {
@ -231,7 +225,7 @@ function clickDelete(id: string) {
/**
* rediarect หนารายละเอยดขอม
* @param id รายการชวยราชการ
* @param id รายการชวยราชการองการดรายละเอยด
*/
function openDetail(id: string) {
router.push(`/placement/help-government/detail/${id}`);
@ -269,9 +263,11 @@ function closeModal() {
function resetFilter() {
filterKeyword.value = "";
filterKeyword2.value = "";
filterRef.value.focus();
}
/**
* ทำงานเมอมการเรยกใช Components
*/
onMounted(() => {
getData();
});
@ -410,10 +406,10 @@ onMounted(() => {
<Dialogbody
v-model:Modal="modal"
:closeModal="closeModal"
v-model:filter-keyword2="filterKeyword2"
:get-data="getData"
:close-modal="closeModal"
:rows2="rows2"
v-model:filterKeyword2="filterKeyword2"
:getData="getData"
/>
</template>
<style scoped lang="scss"></style>

View file

@ -1,8 +1,11 @@
<script setup lang="ts">
import { ref, onMounted } from "vue";
import { checkPermission } from "@/utils/permissions";
import { useQuasar } from "quasar";
import { useRouter } from "vue-router";
import { checkPermission } from "@/utils/permissions";
import { useCounterMixin } from "@/stores/mixin";
import { useTransferDataStore } from "@/modules/05_placement/store";
import http from "@/plugins/http";
import config from "@/app.config";
@ -15,16 +18,11 @@ import type { officerType } from "@/modules/05_placement/interface/response/offi
/**
* importComponents
*/
import Dialogbody from "@/modules/05_placement/components/Repatriate/Dialogbody.vue"; //popup
import Dialogbody from "@/modules/05_placement/components/Repatriate/DialogOrders.vue"; //popup
/**
* importStore
*/
import { useCounterMixin } from "@/stores/mixin";
import { useTransferDataStore } from "@/modules/05_placement/store";
const { statusText } = useTransferDataStore();
const $q = useQuasar();
const router = useRouter();
const { statusText } = useTransferDataStore();
const {
date2Thai,
messageError,
@ -35,16 +33,13 @@ const {
findPosMasterNoOld,
} = useCounterMixin();
/**
* Table
*/
const filterKeyword = ref<string>("");
const filterKeyword2 = ref<string>("");
const filterRef = ref<any>(null);
const router = useRouter();
const rows = ref<officerType[]>([]);
const rows2 = ref<officerType[]>([]);
//
const modal = ref<boolean>(false); //
// Table
const filterKeyword = ref<string>(""); //
const filterKeyword2 = ref<string>(""); //
const rows = ref<officerType[]>([]); //
const rows2 = ref<officerType[]>([]); //
const columns = ref<QTableProps["columns"]>([
{
name: "no",
@ -149,8 +144,6 @@ const visibleColumns = ref<string[]>([
"status",
]);
const modal = ref<boolean>(false); //
/**
* rediarect ไปหนารายละเอยด
*/
@ -161,12 +154,12 @@ function openDetail(id: string) {
/**
* fetch รายการสงตวกล
*/
function getData() {
async function getData() {
showLoader();
http
await http
.get(config.API.repatriationMain())
.then((res) => {
const data = res.data.result;
.then(async (res) => {
const data = await res.data.result;
rows.value = data;
})
.catch((e) => {
@ -235,13 +228,16 @@ function closeModal() {
function resetFilter() {
filterKeyword.value = "";
filterKeyword2.value = "";
filterRef.value.focus();
}
/**
* ทำงานเมอมการเรยกใช Components
*/
onMounted(async () => {
await getData();
});
</script>
<template>
<div class="toptitle text-dark col-12 row items-center">รายการสงตวกล</div>
<q-card flat bordered class="col-12 q-mt-sm">
@ -372,10 +368,11 @@ onMounted(async () => {
<Dialogbody
v-model:Modal="modal"
:closeModal="closeModal"
v-model:filter-keyword2="filterKeyword2"
:get-data="getData"
:close-modal="closeModal"
:rows2="rows2"
v-model:filterKeyword2="filterKeyword2"
:getData="getData"
/>
</template>
<style scoped lang="scss"></style>

View file

@ -1,8 +1,11 @@
<script setup lang="ts">
import { ref, onMounted } from "vue";
import { checkPermission } from "@/utils/permissions";
import { useQuasar } from "quasar";
import { useRouter } from "vue-router";
import { checkPermission } from "@/utils/permissions";
import { useCounterMixin } from "@/stores/mixin";
import { useTransferDataStore } from "@/modules/05_placement/store";
import http from "@/plugins/http";
import config from "@/app.config";
@ -19,14 +22,11 @@ import type { QTableProps } from "quasar";
/**
* importComponents
*/
import Dialogbody from "@/modules/05_placement/components/AppointMent/Dialogbody.vue"; //
import Dialogbody from "@/modules/05_placement/components/AppointMent/DialogOrders.vue"; //
import DialogOrgSelect from "@/components/Dialogs/DialogOrgSelect.vue"; //
import { useCounterMixin } from "@/stores/mixin";
import { useTransferDataStore } from "@/modules/05_placement/store";
const $q = useQuasar();
const modal = ref<boolean>(false);
const router = useRouter();
const storeFn = useTransferDataStore();
const { statusText } = storeFn;
const {
@ -38,29 +38,27 @@ const {
dialogRemove,
} = useCounterMixin();
const posType = ref<string>("");
const posLevel = ref<string>("");
const position = ref<string>("");
const typeModal = ref<string | null>(null);
const modal = ref<boolean>(false); // popup
const modalTree = ref<boolean>(false); // popup - -
const posType = ref<string>(""); //
const posLevel = ref<string>(""); //
const position = ref<string>(""); //
const typeModal = ref<string | null>(null); // popup , ,
const dataRows = ref<any[]>([]);
const router = useRouter();
const modalTree = ref<boolean>(false);
const personalId = ref<string>("");
const filterRef = ref<any>(null);
const listRecevice = ref<resData[]>([]);
const listRecevice = ref<resData[]>([]); //--
const optionsType = ref<OpType[]>([]);
const type = ref<string>("");
/**
* Table
*/
const rows = ref<listAppointType[]>([]);
const rows2 = ref<listAppointType[]>([]);
const filterKeyword = ref<string>("");
const filterKeyword2 = ref<string>("");
const rows = ref<listAppointType[]>([]); //--
const rows2 = ref<listAppointType[]>([]); //
const filterKeyword = ref<string>(""); //--
const filterKeyword2 = ref<string>(""); //
const columns = ref<QTableProps["columns"]>([
{
name: "no",
@ -160,22 +158,22 @@ const pagination = ref({
page: 1,
rowsPerPage: 10,
});
/**
* เซ input
* เซคำคนหารายการ
*/
const resetFilter = () => {
function resetFilter() {
filterKeyword.value = "";
filterKeyword2.value = "";
filterRef.value.focus();
};
}
/**
* fetch รายการแตงต-เลอน-าย
*/
function fecthlistappointment() {
async function fecthlistappointment() {
showLoader();
rows.value = [];
http
await http
.get(config.API.appointmentMain())
.then((res) => {
let response = res.data.result;
@ -300,6 +298,9 @@ function clickClose() {
modal.value = false;
}
/**
* ทำงานเมอมการเรยกใช Components
*/
onMounted(() => {
fecthlistappointment();
});
@ -577,23 +578,23 @@ onMounted(() => {
<Dialogbody
v-model:Modal="modal"
:clickClose="clickClose"
:optionsType="optionsType"
:rows2="rows2"
v-model:filterKeyword2="filterKeyword2"
v-model:filter-keyword2="filterKeyword2"
v-model:type="type"
:nextPage="nextPage"
:fecthlistappointment="fecthlistappointment"
:click-close="clickClose"
:options-type="optionsType"
:rows2="rows2"
:next-page="nextPage"
:fetch-data="fecthlistappointment"
/>
<DialogOrgSelect
:title="`เลือกหน่วยงานที่แต่งตั้ง - เลื่อน - ย้าย`"
v-model:modal="modalTree"
v-model:type="typeModal"
:posType="posType"
:posLevel="posLevel"
:pos-type="posType"
:pos-level="posLevel"
:position="position"
:dataRows="dataRows"
:data-rows="dataRows"
:onSubmit="onSave"
/>
</template>

View file

@ -1,34 +1,27 @@
<script setup lang="ts">
import { ref, onMounted } from "vue";
import { checkPermission } from "@/utils/permissions";
import type { QTableProps } from "quasar";
import { useQuasar } from "quasar";
import { checkPermission } from "@/utils/permissions";
import { useRouter } from "vue-router";
import { useCounterMixin } from "@/stores/mixin";
import { useTransferDataStore } from "@/modules/05_placement/store";
import Dialogbody from "@/modules/05_placement/components/AppointEmployee/Dialogbody.vue";
// import DialogOrgTree from "@/modules/05_placement/components/AppointEmployee/Modal.vue";
import http from "@/plugins/http";
import config from "@/app.config";
import type { QTableProps } from "quasar";
import type {
listAppointType,
resData,
orgFilter,
} from "@/modules/05_placement/interface/response/AppointMent";
import type { OpType } from "@/modules/05_placement/interface/response/Main";
import http from "@/plugins/http";
import config from "@/app.config";
import DialogHeader from "@/components/DialogHeader.vue";
import DialogOrgSelectEmployee from "@/components/Dialogs/DialogOrgSelectEmployee.vue"; //
const typeModal = ref<string>("");
const posType = ref<string>("");
const posLevel = ref<string>("");
const position = ref<string>("");
const dataRows = ref<any[]>([]);
import Dialogbody from "@/modules/05_placement/components/AppointEmployee/DialogOrders.vue";
const $q = useQuasar();
const modal = ref<boolean>(false);
const router = useRouter();
const storeFn = useTransferDataStore();
const { statusText } = storeFn;
const mixin = useCounterMixin(); //
@ -40,19 +33,26 @@ const {
date2Thai,
dialogRemove,
} = mixin;
const router = useRouter();
const rows = ref<listAppointType[]>([]);
const rows2 = ref<listAppointType[]>([]);
const modalTree = ref<boolean>(false);
const personalId = ref<string>("");
const filterKeyword = ref<string>("");
const filterKeyword2 = ref<string>("");
const modal = ref<boolean>(false); // popup
const modalTree = ref<boolean>(false); // popup
const typeModal = ref<string>(""); // popup ,
const posType = ref<string>(""); //
const posLevel = ref<string>(""); //
const position = ref<string>(""); //
const dataRows = ref<any[]>([]);
const filterRef = ref<any>(null);
const listRecevice = ref<resData[]>([]);
const listRecevice = ref<resData[]>([]); //
const optionsType = ref<OpType[]>([]);
const type = ref<string>("");
// Table
const rows = ref<listAppointType[]>([]); //
const rows2 = ref<listAppointType[]>([]); //
const filterKeyword = ref<string>(""); //
const filterKeyword2 = ref<string>(""); //
const visibleColumns = ref<string[]>([
"no",
"citizenId",
@ -145,13 +145,13 @@ function resetFilter() {
/**
* fetch รายการปรบระดบชนงานลกจาง
*/
function fecthlistappointment() {
async function fecthlistappointment() {
showLoader();
rows.value = [];
http
await http
.get(config.API.appointEmployee())
.then((res) => {
let response = res.data.result;
.then(async (res) => {
let response = await res.data.result;
listRecevice.value = response;
rows.value = response;
@ -182,7 +182,7 @@ function fecthlistappointment() {
* นยนลบรายการปรบระดบชนงานลกจาง
* @param id รายการปรบระดบชนงานลกจาง
*/
const clickDelete = (id: string) => {
function clickDelete(id: string) {
dialogRemove($q, () => {
showLoader();
http
@ -198,7 +198,7 @@ const clickDelete = (id: string) => {
hideLoader();
});
});
};
}
/**
* redialect รายละเอยดการปรบระดบชนงานลกจาง
@ -259,7 +259,6 @@ function onSave(data: any) {
posmasterId: data.posmasterId,
typeCommand: data.typeCommand,
};
showLoader();
http
.put(config.API.appointmentPosition(personalId.value), dataAppoint)
@ -275,6 +274,7 @@ function onSave(data: any) {
hideLoader();
});
}
onMounted(() => {
fecthlistappointment();
});
@ -523,23 +523,23 @@ onMounted(() => {
<Dialogbody
v-model:Modal="modal"
:clickClose="clickClose"
:optionsType="optionsType"
:rows2="rows2"
v-model:filterKeyword2="filterKeyword2"
v-model:filter-keyword2="filterKeyword2"
v-model:type="type"
:nextPage="nextPage"
:fecthlistappointment="fecthlistappointment"
:click-close="clickClose"
:options-type="optionsType"
:rows2="rows2"
:next-page="nextPage"
:fetch-data="fecthlistappointment"
/>
<DialogOrgSelectEmployee
:title="`เลือกหน่วยงานที่รับการปรับระดับชั้นงาน`"
v-model:modal="modalTree"
v-model:type="typeModal"
:posType="posType"
:posLevel="posLevel"
:pos-type="posType"
:pos-level="posLevel"
:position="position"
:dataRows="dataRows"
:data-rows="dataRows"
:onSubmit="onSave"
/>
</template>

View file

@ -1,9 +1,11 @@
<script setup lang="ts">
import { ref, onMounted } from "vue";
import { checkPermission } from "@/utils/permissions";
import { useQuasar } from "quasar";
import { useRouter } from "vue-router";
import { useRouter } from "vue-router";
import { checkPermission } from "@/utils/permissions";
import { useTransferDataStore } from "@/modules/05_placement/store";
import { useCounterMixin } from "@/stores/mixin";
import http from "@/plugins/http";
import config from "@/app.config";
@ -13,11 +15,7 @@ import type { listMain } from "@/modules/05_placement/interface/response/OhterMa
import type { OpType } from "@/modules/05_placement/interface/response/Main";
/** importcomopnents*/
import Dialogbody from "@/modules/05_placement/components/Other/Dialogbody.vue";
/** importStore*/
import { useTransferDataStore } from "@/modules/05_placement/store";
import { useCounterMixin } from "@/stores/mixin";
import Dialogbody from "@/modules/05_placement/components/Other/DialogOrders.vue";
/** use*/
const $q = useQuasar();
@ -40,11 +38,10 @@ const optionsType = ref<OpType[]>([]);
/**
* Table
*/
const rows = ref<listMain[]>([]);
const rows2 = ref<listMain[]>([]);
const filterKeyword = ref<string>("");
const filterKeyword2 = ref<string>("");
const filterRef = ref<any>(null);
const rows = ref<listMain[]>([]); //
const rows2 = ref<listMain[]>([]); //
const filterKeyword = ref<string>(""); //
const filterKeyword2 = ref<string>(""); //
const visibleColumns = ref<string[]>([
"no",
"fullname",
@ -137,9 +134,9 @@ const pagination = ref({
/**
* fetch รายการอนๆ
*/
function fecthlistOthet() {
async function fecthlistOthet() {
showLoader();
http
await http
.get(config.API.otherMain())
.then((res) => {
let response = res.data.result;
@ -195,7 +192,6 @@ function fecthTypeOption() {
function resetFilter() {
filterKeyword.value = "";
filterKeyword2.value = "";
filterRef.value.focus();
}
/**
@ -383,12 +379,13 @@ onMounted(() => {
<Dialogbody
v-model:Modal="modal"
:clickClose="clickClose"
:optionsType="optionsType"
:rows2="rows2"
v-model:filterKeyword2="filterKeyword2"
v-model:filter-keyword2="filterKeyword2"
v-model:type="type"
:click-close="clickClose"
:options-type="optionsType"
:rows2="rows2"
:fecthlistOthet="fecthlistOthet"
/>
</template>
<style scoped lang="scss"></style>

View file

@ -1,8 +1,10 @@
<script setup lang="ts">
import { ref, reactive, watch } from "vue";
import { useQuasar } from "quasar";
import http from "@/plugins/http";
import config from "@/app.config";
import { useCounterMixin } from "@/stores/mixin";
/**
* importType
@ -11,7 +13,6 @@ import type {
ResGroup,
ResLevel,
} from "@/modules/01_masterdata/interface/response/positionEmployee/Main";
import type { ObjectPosRef } from "@/modules/01_masterdata/interface/index/positionEmployee";
import type { DataOption } from "@/modules/16_positionEmployee/interface/index/Main";
import type { OptionType } from "@/modules/16_positionEmployee/interface/response/organizational";
@ -20,11 +21,6 @@ import type { OptionType } from "@/modules/16_positionEmployee/interface/respons
*/
import DialogHeader from "@/components/DialogHeader.vue";
/**
* importStore
*/
import { useCounterMixin } from "@/stores/mixin";
/**
* use
*/
@ -44,86 +40,58 @@ const props = defineProps({
levelOp: Object,
});
const isDisValidate = ref<boolean>(false);
const isSpecial = ref<boolean>(false);
//
const formDataPos = reactive({
posName: "",
posTypeName: "",
posLevelName: "",
posName: "", //
posTypeName: "", //
posLevelName: "", //
});
const posNameRef = ref<object | null>(null);
const posTypeNameRef = ref<object | null>(null);
const posLevelNameRef = ref<object | null>(null);
const objectRef: ObjectPosRef = {
posName: posNameRef,
posTypeName: posTypeNameRef,
posLevelName: posLevelNameRef,
};
const posTypeMain = ref<ResGroup[]>([]);
const posTypeOp = ref<DataOption[]>([]);
const posLevelOp = ref<DataOption[]>([]);
const posTypeMain = ref<ResGroup[]>([]); //
const posTypeOp = ref<DataOption[]>([]); //
const posLevelOp = ref<DataOption[]>([]); //
/**
* งกนตรวจสอบความถกตองของขอมลในฟอร
* งกนยนยนการบนทกขอม
*/
function validateFormPositionEdit() {
isDisValidate.value = false;
const hasError = [];
for (const key in objectRef) {
if (Object.prototype.hasOwnProperty.call(objectRef, key)) {
const property = objectRef[key];
if (property.value && typeof property.value.validate === "function") {
const isValid = property.value.validate();
hasError.push(isValid);
}
async function onSubmit() {
dialogConfirm($q, async () => {
const body = {
posDictName: formDataPos.posName,
posTypeId: formDataPos.posTypeName,
posLevelId: formDataPos.posLevelName,
};
showLoader();
try {
const url = !isEditCheck.value
? config.API.orgEmployeePos
: config.API.orgEmployeePosById(props?.data?.id);
await http[!isEditCheck.value ? "post" : "put"](url, body);
await props.emitSearch?.(formDataPos.posName, "positionName");
await success($q, "บันทีกข้อมูลสำเร็จ");
close();
} catch (err) {
messageError($q, err);
} finally {
hideLoader();
}
}
if (hasError.every((result) => result === true)) {
dialogConfirm($q, () => {
submit();
});
}
}
async function submit() {
const body = {
posDictName: formDataPos.posName,
posTypeId: formDataPos.posTypeName,
posLevelId: formDataPos.posLevelName,
};
showLoader();
try {
const url = !isEditCheck.value
? config.API.orgEmployeePos
: config.API.orgEmployeePosById(props?.data?.id);
await http[!isEditCheck.value ? "post" : "put"](url, body);
await props.emitSearch?.(formDataPos.posName, "positionName");
await success($q, "บันทีกข้อมูลสำเร็จ");
await close();
} catch (err) {
messageError($q, err);
} finally {
hideLoader();
}
});
}
async function clearFormPositionSelect() {
/**
* งกนป popup
*/
function close() {
modal.value = false;
isEditCheck.value = false;
isDisValidate.value = true;
formDataPos.posName = "";
formDataPos.posTypeName = "";
formDataPos.posLevelName = "";
isSpecial.value = false;
setTimeout(() => {
isDisValidate.value = false;
}, 1000);
}
function close() {
modal.value = false;
clearFormPositionSelect();
}
/**
* งกนดงขอมลกลมงาน
*/
async function fetchType() {
showLoader();
await http
@ -143,6 +111,10 @@ async function fetchType() {
});
}
/**
* งกนหาขอมลระดบชนงานตามกลมงาน
* @param id กลมงาน
*/
function updatePosTypeName(id: string) {
const posLevel = posTypeMain.value.find((e: ResGroup) => e.id === id);
posLevelOp.value =
@ -153,6 +125,9 @@ function updatePosTypeName(id: string) {
formDataPos.posLevelName = "";
}
/**
* ทำงานเม modal เป true
*/
watch(
() => modal.value,
async () => {
@ -175,14 +150,16 @@ watch(
<template>
<q-dialog v-model="modal" persistent>
<q-card style="min-width: 50vw">
<DialogHeader
:tittle="`${isEditCheck ? `แก้ไขข้อมูลตำแหน่ง` : `เพิ่มข้อมูลตำแหน่ง`}`"
:close="close"
/>
<q-separator />
<q-form greedy @submit.prevent @validation-success="onSubmit">
<DialogHeader
:tittle="`${
isEditCheck ? `แก้ไขข้อมูลตำแหน่ง` : `เพิ่มข้อมูลตำแหน่ง`
}`"
:close="close"
/>
<q-separator />
<q-card-section class="q-pa-none">
<form @submit.prevent="validateFormPositionEdit">
<q-card-section class="q-pa-none">
<div class="row q-col-gutter-sm col-12 q-pa-md">
<div class="col-12">
<q-input
@ -194,7 +171,8 @@ watch(
label="ชื่อตำแหน่ง"
lazy-rules
hide-bottom-space
:rules="[(val) => !!val || `${'กรุณากรอกชื่อตำแหน่ง'}`]"
:rules="[(val:string) => !!val || `${'กรุณากรอกชื่อตำแหน่ง'}`]"
class="inputgreen"
/>
</div>
@ -212,8 +190,9 @@ watch(
option-value="id"
lazy-rules
hide-bottom-space
:rules="[(val) => !!val || `${'กรุณาเลือกกลุ่มงาน'}`]"
:rules="[(val:string) => !!val || `${'กรุณาเลือกกลุ่มงาน'}`]"
@update:model-value="updatePosTypeName"
class="inputgreen"
/>
</div>
@ -232,7 +211,8 @@ watch(
option-value="id"
lazy-rules
hide-bottom-space
:rules="[(val) => !!val || `${'กรุณาเลือกระดับชั้นงาน'}`]"
:rules="[(val:string) => !!val || `${'กรุณาเลือกระดับชั้นงาน'}`]"
class="inputgreen"
/>
</div>
</div>
@ -245,8 +225,8 @@ watch(
color="public"
/>
</q-card-actions>
</form>
</q-card-section>
</q-card-section>
</q-form>
</q-card>
</q-dialog>
</template>

View file

@ -1,6 +1,8 @@
<script setup lang="ts">
import { ref, reactive, watch } from "vue";
import { useQuasar } from "quasar";
import { useCounterMixin } from "@/stores/mixin";
import http from "@/plugins/http";
import config from "@/app.config";
@ -10,37 +12,15 @@ import config from "@/app.config";
import type { QTableProps } from "quasar";
import type {
FormDataPosition,
FormPositionRef,
DataOption,
RowDetailPositions,
ListMenu,
} from "@/modules/16_positionEmployee/interface/index/Main";
import type { FilterMaster } from "@/modules/16_positionEmployee/interface/request/organizational";
import DialogHeader from "@/components/DialogHeader.vue";
import DialogAddPosition from "@/modules/16_positionEmployee/components/DialogAddPosition.vue";
import DialogAddPosition from "@/modules/16_positionEmployee/components/DialogAddPosition.vue"; //
import { useCounterMixin } from "@/stores/mixin";
const props = defineProps({
modal: Boolean,
close: Function,
orgLevel: Number,
treeId: String,
actionType: String,
rowId: { type: String, default: "" },
fetchDataTable: Function,
getSummary: Function,
shortName: { type: String, required: true },
});
const isEdit = ref<boolean>(false);
const modalAdd = ref<boolean>(false);
const reqMaster = defineModel<FilterMaster>("reqMaster", { required: true });
const isReadonly = ref<boolean>(false); //
const isDisValidate = ref<boolean>(false);
const isPosition = ref<boolean>(false);
const dataCopy = ref<any>();
const $q = useQuasar();
const mixin = useCounterMixin();
const {
@ -53,7 +33,28 @@ const {
dialogMessageNotify,
} = mixin;
const search = ref<string>("");
/**
* props
*/
const reqMaster = defineModel<FilterMaster>("reqMaster", { required: true });
const props = defineProps({
modal: Boolean,
close: Function,
orgLevel: Number,
treeId: String,
actionType: String,
rowId: { type: String, default: "" },
fetchDataTable: Function,
getSummary: Function,
shortName: { type: String, required: true },
});
const modalAdd = ref<boolean>(false); //
const isEdit = ref<boolean>(false); //
const isReadonly = ref<boolean>(false); //
const isPosition = ref<boolean>(false); //
const dataCopy = ref<RowDetailPositions>(); //
const search = ref<string>(""); //
const type = ref<string>("positionName");
const optionFilter = ref<DataOption[]>([
{ id: "positionName", name: "ชื่อตำแหน่ง" },
@ -82,11 +83,8 @@ const listMenu = ref<ListMenu[]>([
},
]);
const rows = ref<RowDetailPositions[]>([]);
const rowsPositionSelect = ref<RowDetailPositions[]>([]);
const prefixNoRef = ref<Object | null>(null);
const positionNoRef = ref<Object | null>(null);
const rows = ref<RowDetailPositions[]>([]); //
const rowsPositionSelect = ref<RowDetailPositions[]>([]); //
const formData = reactive<FormDataPosition>({
shortName: props.shortName,
@ -96,12 +94,6 @@ const formData = reactive<FormDataPosition>({
reason: "",
});
/** maping ref เข้าตัวแปรเพื่อเตรียมตรวจสอบ */
const objectPositionRef: FormPositionRef = {
prefixNo: prefixNoRef,
positionNo: positionNoRef,
};
const columns = ref<QTableProps["columns"]>([
{
name: "no",
@ -171,75 +163,59 @@ async function fetchPosition(id: string) {
});
}
/** ฟังก์ชั่นตรวจสอบความถูกต้องของข้อมูลในฟอร์ม */
function validateForm() {
const hasError = [];
for (const key in objectPositionRef) {
if (Object.prototype.hasOwnProperty.call(objectPositionRef, key)) {
const property = objectPositionRef[key];
if (property.value && typeof property.value.validate === "function") {
const isValid = property.value.validate();
hasError.push(isValid);
}
}
}
if (hasError.every((result) => result === true)) {
if (rows.value.length == 0) {
dialogMessageNotify($q, "กรุณาเลือกตำแหน่งอย่างน้อย 1 ตำแหน่ง");
} else {
onSubmit();
}
}
}
/** ฟังชั่น บันทึก */
/**
* งกนบนทกขอมลอตรากำล
*/
function onSubmit() {
dialogConfirm($q, async () => {
showLoader();
const positionsData = rows.value.map((e: any) => ({
posDictName: e.posDictName, // ()
posTypeId: e.posTypeId, //*
posLevelId: e.posLevelId, //*
}));
const body = {
posMasterNoPrefix: formData.prefixNo, //*Prefix Optional (/)
posMasterNo: Number(formData.positionNo), //*
posMasterNoSuffix: formData.suffixNo, //Suffix .
reason: formData.reason, //Suffix .
orgRootId: props.orgLevel === 0 ? props.treeId : null, //Id
orgChild1Id: props.orgLevel === 1 ? props.treeId : null,
orgChild2Id: props.orgLevel === 2 ? props.treeId : null,
orgChild3Id: props.orgLevel === 3 ? props.treeId : null,
orgChild4Id: props.orgLevel === 4 ? props.treeId : null,
positions: positionsData,
isDirector: false,
isOfficer: false,
// succession: succession.value,
};
try {
const url =
props.actionType === "ADD"
? config.API.orgPosMasterEmp
: config.API.orgPosMasterByIdEmp(props.rowId);
await http[props.actionType === "ADD" ? "post" : "put"](url, body);
await props.getSummary?.();
await props.fetchDataTable?.(
reqMaster.value.id,
reqMaster.value.type,
false
);
await success($q, "บันทีกข้อมูลสำเร็จ");
close();
} catch (err) {
messageError($q, err);
} finally {
hideLoader();
}
});
if (rows.value.length == 0) {
dialogMessageNotify($q, "กรุณาเลือกตำแหน่งอย่างน้อย 1 ตำแหน่ง");
} else {
dialogConfirm($q, async () => {
showLoader();
const positionsData = rows.value.map((e: any) => ({
posDictName: e.posDictName, // ()
posTypeId: e.posTypeId, //*
posLevelId: e.posLevelId, //*
}));
const body = {
posMasterNoPrefix: formData.prefixNo, //*Prefix Optional (/)
posMasterNo: Number(formData.positionNo), //*
posMasterNoSuffix: formData.suffixNo, //Suffix .
reason: formData.reason, //Suffix .
orgRootId: props.orgLevel === 0 ? props.treeId : null, //Id
orgChild1Id: props.orgLevel === 1 ? props.treeId : null,
orgChild2Id: props.orgLevel === 2 ? props.treeId : null,
orgChild3Id: props.orgLevel === 3 ? props.treeId : null,
orgChild4Id: props.orgLevel === 4 ? props.treeId : null,
positions: positionsData,
isDirector: false,
};
try {
const url =
props.actionType === "ADD"
? config.API.orgPosMasterEmp
: config.API.orgPosMasterByIdEmp(props.rowId);
await http[props.actionType === "ADD" ? "post" : "put"](url, body);
await props.getSummary?.();
await props.fetchDataTable?.(
reqMaster.value.id,
reqMaster.value.type,
false
);
await success($q, "บันทีกข้อมูลสำเร็จ");
close();
} catch (err) {
messageError($q, err);
} finally {
hideLoader();
}
});
}
}
/** input ค้นหา */
/**
* งกนคนหาขอมลตำแหน
*/
const searchRef = ref<any>(null);
async function searchInput() {
searchRef.value.validate();
@ -281,20 +257,18 @@ function editDetiail(data: RowDetailPositions) {
}
/**
* งค css ออกไปตามเงอนไข
* @param val true/false
* งกนเลอกตำแหน
* @param data ตำแหนงทเลอก
*/
function inputEdit(val: boolean) {
return {
"full-width cursor-pointer inputgreen ": val,
"full-width cursor-pointer inputgreen": !val,
};
}
function addPosition(data: RowDetailPositions) {
rows.value = [];
rows.value.push(data);
}
/**
* งกยลบตำแหน
* @param id คำแหนเลอก
*/
function deletePos(id: string) {
dialogRemove($q, () => {
showLoader();
@ -313,27 +287,36 @@ function deletePos(id: string) {
});
}
function clearFormPositionSelect() {
isDisValidate.value = true;
search.value = "";
type.value = "positionName";
setTimeout(() => {
isDisValidate.value = false;
}, 1000);
}
/**
* งกนป Popup
*/
function close() {
props.close?.();
isPosition.value = false;
clearFormPositionSelect();
search.value = "";
type.value = "positionName";
}
/**
* งกนคนหาตำแหน
* @param keyword คำคนหา
* @param typeSelect นหาจาก
*/
async function emitSearch(keyword: string, typeSelect: string) {
search.value = keyword;
type.value = typeSelect;
await searchInput();
}
/**
* งค css ออกไปตามเงอนไข
* @param val true/false
*/
function inputEdit(val: boolean) {
return {
"full-width cursor-pointer inputgreen ": val,
"full-width cursor-pointer inputgreen": !val,
};
}
watch(
() => props.modal,
@ -343,7 +326,6 @@ watch(
rowsPositionSelect.value = [];
search.value = "";
rows.value = [];
clearFormPositionSelect();
formData.prefixNo = "";
formData.positionNo = "";
formData.suffixNo = "";
@ -358,7 +340,7 @@ watch(
() => modalAdd.value,
() => {
if (!modalAdd.value) {
dataCopy.value = [];
dataCopy.value = undefined;
}
}
);
@ -374,7 +356,7 @@ watch(
:close="close"
/>
<q-separator />
<form @submit.prevent="validateForm">
<q-form greedy @submit.prevent @validation-success="onSubmit">
<q-card-section class="q-pa-sm fixed-height">
<div class="row q-col-gutter-sm">
<div class="col-12">
@ -725,15 +707,17 @@ watch(
<q-tooltip>นท</q-tooltip>
</q-btn>
</q-card-actions>
</form>
</q-form>
</q-card>
</q-dialog>
<!-- เพมตำแหน -->
<DialogAddPosition
v-model:modalAdd="modalAdd"
:emitSearch="emitSearch"
:data="dataCopy"
v-model:is-edit="isEdit"
:get-data="searchInput"
:emit-search="emitSearch"
:data="dataCopy"
/>
</template>

View file

@ -1,6 +1,9 @@
<script setup lang="ts">
import { ref, watch } from "vue";
import { useQuasar } from "quasar";
import { useCounterMixin } from "@/stores/mixin";
import { usePositionEmp } from "@/modules/16_positionEmployee/store/organizational";
import http from "@/plugins/http";
import config from "@/app.config";
@ -15,12 +18,6 @@ import type { HistoryPos } from "@/modules/16_positionEmployee/interface/respons
*/
import Header from "@/components/DialogHeader.vue";
/**
* import*Store
*/
import { useCounterMixin } from "@/stores/mixin";
import { usePositionEmp } from "@/modules/16_positionEmployee/store/organizational";
/**
* use
*/
@ -38,6 +35,7 @@ const props = defineProps({
},
});
const rows = ref<HistoryPos[]>([]); //
const columns = ref<QTableProps["columns"]>([
{
name: "no",
@ -61,7 +59,7 @@ const columns = ref<QTableProps["columns"]>([
name: "lastUpdatedAt",
align: "left",
label: "วันที่แก้ไข",
field: "lastUpdatedAt",
field: (v) => date2Thai(v),
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
@ -93,7 +91,6 @@ const columns = ref<QTableProps["columns"]>([
style: "font-size: 14px",
},
]);
const rows = ref<any[]>([]);
/**
* function เรยกขอมลประวตำแหน
@ -105,14 +102,7 @@ function fetchHistoryPos(id: string) {
.get(config.API.orgPosHistory(id))
.then((res) => {
const data: HistoryPos[] = res.data.result;
const list = data.map((e: HistoryPos) => ({
...e,
lastUpdatedAt: e.lastUpdatedAt ? date2Thai(e.lastUpdatedAt) : "-",
posMasterNoPrefix: e.posMasterNoPrefix ?? "-",
posMasterNo: e.posMasterNo ?? "-",
posMasterNoSuffix: e.posMasterNoSuffix ?? "-",
}));
rows.value = list;
rows.value = data;
})
.catch((err) => {
messageError($q, err);

View file

@ -1,8 +1,11 @@
<script setup lang="ts">
import { ref, reactive, watch } from "vue";
import { useQuasar } from "quasar";
import http from "@/plugins/http";
import config from "@/app.config";
import { useCounterMixin } from "@/stores/mixin";
import { usePositionEmp } from "@/modules/16_positionEmployee/store/organizational";
/**
* importType
@ -29,12 +32,6 @@ import type {
*/
import DialogHeader from "@/components/DialogHeader.vue";
/**
* import*Store
*/
import { useCounterMixin } from "@/stores/mixin";
import { usePositionEmp } from "@/modules/16_positionEmployee/store/organizational";
/**
* use
*/
@ -70,12 +67,12 @@ const props = defineProps({
});
const isReadonly = ref<boolean>(false); //
const typeOpsMain = ref<DataOption[]>([]);
const levelOpsMain = ref<DataOption[]>([]);
const typeOps = ref<DataOption[]>([]);
const levelOps = ref<DataOption[]>([]);
const typeOpsMain = ref<DataOption[]>([]); //
const levelOpsMain = ref<DataOption[]>([]); //
const typeOps = ref<DataOption[]>([]); //
const levelOps = ref<DataOption[]>([]); //
const dataLevel = ref<TypePos[]>([]);
const selected = ref<Position[]>([]);
const selected = ref<Position[]>([]); //
const isSit = ref<boolean>(false);
const formData = reactive<FormPositionFilter>({
@ -201,14 +198,15 @@ const columnsResult = ref<QTableProps["columns"]>([
*/
function close() {
modal.value = false;
clearForm();
}
/**
* function เรยกขอมลประเภทตำแหน
*/
function fetchType() {
async function fetchType() {
showLoader();
http
await http
.get(config.API.orgEmployeeType)
.then((res) => {
dataLevel.value = res.data.result;
@ -377,7 +375,6 @@ watch(
() => modal.value,
async () => {
if (modal.value == true) {
await clearForm();
await fetchType();
if (props.dataDetailPos) {

View file

@ -1,8 +1,11 @@
<script setup lang="ts">
import { ref, watch } from "vue";
import { useQuasar } from "quasar";
import http from "@/plugins/http";
import config from "@/app.config";
import { useCounterMixin } from "@/stores/mixin";
import { usePositionEmp } from "@/modules/16_positionEmployee/store/organizational";
/**
* importType
@ -15,12 +18,6 @@ import type { DataSortPos } from "@/modules/02_organization/interface/index/orga
*/
import DialogHeader from "@/components/DialogHeader.vue";
/**
* importStore
*/
import { useCounterMixin } from "@/stores/mixin";
import { usePositionEmp } from "@/modules/16_positionEmployee/store/organizational";
/**
* use
*/

View file

@ -1,6 +1,10 @@
<script setup lang="ts">
import { ref, watch, reactive } from "vue";
import { useQuasar } from "quasar";
import { useRoute } from "vue-router";
import { useCounterMixin } from "@/stores/mixin";
import { usePositionEmp } from "@/modules/16_positionEmployee/store/organizational";
import http from "@/plugins/http";
import config from "@/app.config";
@ -20,11 +24,6 @@ import type {
/** importComponents*/
import Header from "@/components/DialogHeader.vue";
/** importStore*/
import { useCounterMixin } from "@/stores/mixin";
import { usePositionEmp } from "@/modules/16_positionEmployee/store/organizational";
import { useRoute } from "vue-router";
/** use*/
const $q = useQuasar();
const store = usePositionEmp();
@ -82,10 +81,10 @@ function resetFilter() {
* function เลอกหนวยงาน
*/
async function updateSelected(data: DataTree) {
levelTree.value = await data.orgLevel;
selectedTree.value = await data.orgTreeId;
reqMaster.id = await data.orgTreeId;
reqMaster.type = await data.orgLevel;
levelTree.value = data.orgLevel;
selectedTree.value = data.orgTreeId;
reqMaster.id = data.orgTreeId;
reqMaster.type = data.orgLevel;
await fetchTable();
}

View file

@ -18,7 +18,7 @@ const store = usePositionEmp();
const {} = useCounterMixin();
/** props*/
const nodeTEST = defineModel<OrgTree[]>("nodeTree", { default: [] });
const nodeMain = defineModel<OrgTree[]>("nodeTree", { default: [] });
const nodeId = defineModel<string>("nodeId", { required: true });
const shortName = defineModel<string>("shortName", { required: true });
const props = defineProps({
@ -32,12 +32,10 @@ const props = defineProps({
},
});
const filter = ref<string>("");
const nodes = ref<Array<OrgTree>>([]);
const filter = ref<string>(""); //
const nodes = ref<Array<OrgTree>>([]); //
const lazy = ref(nodes);
const expanded = ref<Array<any>>([]);
const notFound = ref<string>("ไม่พบข้อมูลที่ค้นหา");
const noData = ref<string>("ไม่มีข้อมูล");
const expanded = ref<Array<string[]>>([]);
/**
* funtion เลอกขอม Tree
@ -82,9 +80,9 @@ function updateSelected(data: DataTree) {
}
watch(
() => nodeTEST.value,
() => nodeMain.value,
() => {
nodes.value = nodeTEST.value;
nodes.value = nodeMain.value;
}
);
</script>
@ -116,8 +114,8 @@ watch(
node-key="orgTreeId"
label-key="labelName"
:filter="filter"
:no-results-label="notFound"
:no-nodes-label="noData"
no-results-label="ไม่พบข้อมูลที่ค้นหา"
no-nodes-label="ไม่มีข้อมูล"
v-model:expanded="expanded"
>
<template v-slot:default-header="prop">

View file

@ -1,9 +1,12 @@
<script setup lang="ts">
import { ref, watch } from "vue";
import { useQuasar } from "quasar";
import { usePositionEmp } from "@/modules/16_positionEmployee/store/organizational";
import { useCounterMixin } from "@/stores/mixin";
import { checkPermission } from "@/utils/permissions";
import config from "@/app.config";
import http from "@/plugins/http";
import { checkPermission } from "@/utils/permissions";
/**
* importType
@ -31,8 +34,6 @@ import DialogSuccession from "@/modules/16_positionEmployee/components/DialogSuc
/**
* importStore
*/
import { usePositionEmp } from "@/modules/16_positionEmployee/store/organizational";
import { useCounterMixin } from "@/stores/mixin";
/**
* ues

View file

@ -1,330 +0,0 @@
<script setup lang="ts">
import { ref, reactive, onMounted, watch } from "vue";
import { useQuasar } from "quasar";
import http from "@/plugins/http";
import config from "@/app.config";
import { useStructureTree } from "@/stores/structureTree";
/** importType*/
import type {
OrgTree,
PosMaster,
Position,
PosMaster2,
} from "@/modules/16_positionEmployee/interface/response/organizational";
import type { FilterMaster } from "@/modules/16_positionEmployee/interface/request/organizational";
/** importComponents*/
import TreeMain from "@/modules/16_positionEmployee/components/TreeMain.vue";
import TreeTable from "@/modules/16_positionEmployee/components/TreeTable.vue";
/** importStore*/
import { usePositionEmp } from "@/modules/16_positionEmployee/store/organizational";
import { useCounterMixin } from "@/stores/mixin";
import { useRoute } from "vue-router";
/** use*/
const store = usePositionEmp();
const $q = useQuasar();
const { showLoader, hideLoader, messageError } = useCounterMixin();
const route = useRoute();
const { fetchStructureTree } = useStructureTree();
const storeStructureTree = useStructureTree();
const nodeTree = ref<OrgTree[]>([]); // Tree
const nodeId = ref<string>(""); // id Tree
const orgLevel = ref<number>(0); // levelTree
const isLoad = ref<boolean>(false); // loadTable
const isLoadTree = ref<boolean>(false); // loadTable
const mainTree = ref<OrgTree>();
const selected = ref<string>("");
const reqMaster = reactive<FilterMaster>({
id: "",
type: 0,
isAll: false,
page: 1,
pageSize: 10,
keyword: "",
revisionId: "",
});
const totalPage = ref<number>(1);
const action1 = ref<boolean>(false);
const posMaster = ref<PosMaster2[]>([]);
const shortName = ref<string>("");
/**
* function fetch อมลของ Tree
* @param id id โครงสราง
*/
async function fetchDataTree() {
isLoadTree.value = false;
const dataTree = await fetchStructureTree(route.meta.Key as string, true);
store.activeId = storeStructureTree.activeId;
if (dataTree) {
nodeTree.value = dataTree;
selected.value = "";
nodeId.value = "";
store.treeId = "";
}
}
/**
* function fetch อรายการตำแหน
* @param id idTree
* @param level levelTree
*/
function fetchDataTable(id: string, level: number, action: boolean) {
searchAndReplaceOrgName(nodeTree.value, id);
orgLevel.value = level;
reqMaster.id = id;
reqMaster.type = level;
action1.value = action;
if (action) {
setTimeout(() => {
action1.value = false;
}, 1000);
reqMaster.isAll = false;
reqMaster.page = 1;
reqMaster.pageSize = 10;
reqMaster.keyword = "";
reqMaster.revisionId = store.activeId;
}
if (action === true) {
isLoad.value = true;
}
http
.post(config.API.orgPosMasterListEmp, reqMaster)
.then(async (res) => {
posMaster.value = [];
const dataMain: PosMaster[] = [];
totalPage.value = Math.ceil(res.data.result.total / reqMaster.pageSize);
res.data.result.data.forEach((e: PosMaster) => {
const p = e.positions;
if (p.length !== 0) {
const a = p.find((el: Position) => el.positionIsSelected === true);
const { id, ...rest } = a ? a : p[0];
const test = { ...e, ...rest };
dataMain.push(test);
}
});
posMaster.value = await store.fetchPosMaster(dataMain);
})
.catch((err) => {
messageError($q, err);
posMaster.value = [];
})
.finally(() => {
setTimeout(() => {
isLoad.value = false;
}, 500);
});
}
/**
* งขอมลสถจำนวนดานบน
*/
function getSummary() {
http
.post(config.API.orgSummaryEmp, {
id: reqMaster.id, //*Id node
type: reqMaster.type, //*node
isNode: reqMaster.isAll, //* node
})
.then(async (res: any) => {
const data = await res.data.result;
store.getSumPosition({
totalPosition: data.totalPosition,
totalPositionCurrentUse: data.totalPositionCurrentUse,
totalPositionCurrentVacant: data.totalPositionCurrentVacant,
totalPositionNextUse: data.totalPositionNextUse,
totalPositionNextVacant: data.totalPositionNextVacant,
totalRootPosition: data.totalPosition,
totalRootPositionCurrentUse: data.totalPositionCurrentUse,
totalRootPositionCurrentVacant: data.totalPositionCurrentVacant,
totalRootPositionNextUse: data.totalPositionNextUse,
totalRootPositionNextVacant: data.totalPositionNextVacant,
});
});
}
/**
* funcion นหาขอมลใน Table
*/
function filterKeyword() {
reqMaster.page = 1;
action1.value === false &&
fetchDataTable(reqMaster.id, reqMaster.type, false);
}
/**
* function นหาช
* @param data อม Tree
* @param targetId tree
*/
function searchAndReplaceOrgName(data: any, targetId: string) {
for (const child of data) {
if (child.orgTreeId === targetId) {
mainTree.value = child;
return true; // Found the targetId in this level
}
if (child.children && searchAndReplaceOrgName(child.children, targetId)) {
return true; // Found the targetId in the nested children
}
}
return false; // Not found in this branch
}
/**
* lifecycle Hook
*/
onMounted(() => {
fetchDataTree();
// setTimeout(async () => {
// store.activeId && (await );
// }, 200);
});
/**
* callblck function ทำการ fetch อม Table เมอมการเปลยนหน
*/
watch([() => reqMaster.page, () => reqMaster.pageSize], () => {
action1.value === false &&
fetchDataTable(reqMaster.id, reqMaster.type, false);
});
/**
* callblck function ทำการ fetch อม Table เมอแสดงตำแหนงทงหมด
*/
watch(
() => reqMaster.isAll,
() => {
getSummary();
if (reqMaster.page !== 1) {
reqMaster.page = 1;
} else {
fetchDataTable(reqMaster.id, reqMaster.type, false);
}
}
);
</script>
<template>
<div class="col-12">
<q-card bordered class="col-12 row caedNone">
<div class="col-xs-12 col-sm-3 row">
<div class="col-12 row no-wrap bg-grey-1">
<TreeMain
v-model:nodeTree="nodeTree"
v-model:shortName="shortName"
v-model:nodeId="nodeId"
:fetchDataTree="fetchDataTree"
:fetchDataTable="fetchDataTable"
/>
<div class="col-12 row">
<q-separator :vertical="!$q.screen.lt.md" />
</div>
</div>
</div>
<div class="col-xs-12 col-sm-9 q-pa-md row">
<div class="col-12 row">
<div
class="row col-12 justify-center"
v-if="isLoad"
style="height: 550px"
>
<div class="col-2">
<q-spinner color="primary" size="3em" />
</div>
</div>
<div v-else class="col-12 row">
<div class="col-12" v-if="nodeId !== ''">
<!-- summary -->
<q-card
bordered
v-if="nodeId"
class="row col-12 justify-between list-summary q-gutter-xs bg-grey-1 q-pb-xs q-pr-xs"
>
<div class="row col q-pa-sm item">
<div class="ellipsis">ตำแหนงทงหมด</div>
<q-space />
<q-badge
color="secondary"
:label="
reqMaster.isAll
? store.sumPosition.total
: store.sumPosition.totalRoot
"
/>
</div>
<div class="row col q-pa-sm item">
<div class="ellipsis">ตำแหนงทคนครอง</div>
<q-space />
<q-badge
color="primary"
:label="
reqMaster.isAll
? store.sumPosition.use
: store.sumPosition.useRoot
"
/>
</div>
<div class="row col q-pa-sm item">
<div class="ellipsis">ตำแหนงวาง</div>
<q-space />
<q-badge
color="red"
:label="
reqMaster.isAll
? store.sumPosition.vacant
: store.sumPosition.vacantRoot
"
/>
</div>
</q-card>
<TreeTable
v-if="nodeId !== ''"
v-model:nodeTree="nodeTree"
v-model:orgLevel="orgLevel"
v-model:treeId="nodeId"
v-model:reqMaster="reqMaster"
v-model:totalPage="totalPage"
v-model:posMaster="posMaster"
:shortName="shortName"
:mainTree="mainTree"
:fetchDataTable="fetchDataTable"
:filterKeyword="filterKeyword"
:fetchDataTree="fetchDataTree"
/>
</div>
<div class="row col-12 items-center" v-else>
<q-banner class="q-pa-lg col-12 text-center">
<q-icon
name="mdi-hand-pointing-left"
size="lg"
color="primary"
/>
<p class="text-grey-9 q-pt-sm">กรณาเลอกโครงสราง</p>
</q-banner>
</div>
</div>
</div>
</div>
</q-card>
</div>
</template>
<style scoped>
.list-summary .item {
border: 1px solid rgb(231, 231, 231);
border-radius: 4px;
background-color: white;
}
</style>

View file

@ -1,6 +1,210 @@
<script setup lang="ts">
import { ref, reactive, onMounted, watch } from "vue";
import { useQuasar } from "quasar";
import { useRoute } from "vue-router";
import { useStructureTree } from "@/stores/structureTree";
import { usePositionEmp } from "@/modules/16_positionEmployee/store/organizational";
import { useCounterMixin } from "@/stores/mixin";
import http from "@/plugins/http";
import config from "@/app.config";
/** importType*/
import type {
OrgTree,
PosMaster,
Position,
PosMaster2,
} from "@/modules/16_positionEmployee/interface/response/organizational";
import type { FilterMaster } from "@/modules/16_positionEmployee/interface/request/organizational";
/** importComponents*/
import TreeView from "@/modules/16_positionEmployee/components/TreeView.vue";
import TreeMain from "@/modules/16_positionEmployee/components/TreeMain.vue";
import TreeTable from "@/modules/16_positionEmployee/components/TreeTable.vue";
/** use*/
const store = usePositionEmp();
const $q = useQuasar();
const { messageError } = useCounterMixin();
const route = useRoute();
const { fetchStructureTree } = useStructureTree();
const storeStructureTree = useStructureTree();
const nodeTree = ref<OrgTree[]>([]); // Tree
const nodeId = ref<string>(""); // id Tree
const orgLevel = ref<number>(0); // levelTree
const isLoad = ref<boolean>(false); // loadTable
const isLoadTree = ref<boolean>(false); // loadTable
const mainTree = ref<OrgTree>();
const selected = ref<string>("");
const reqMaster = reactive<FilterMaster>({
id: "",
type: 0,
isAll: false,
page: 1,
pageSize: 10,
keyword: "",
revisionId: "",
});
const totalPage = ref<number>(1); //
const action1 = ref<boolean>(false);
const posMaster = ref<PosMaster2[]>([]); //
const shortName = ref<string>(""); //
/**
* function fetch อมลของ Tree
* @param id id โครงสราง
*/
async function fetchDataTree() {
isLoadTree.value = false;
const dataTree = await fetchStructureTree(route.meta.Key as string, true);
store.activeId = storeStructureTree.activeId;
if (dataTree) {
nodeTree.value = dataTree;
selected.value = "";
nodeId.value = "";
store.treeId = "";
}
}
/**
* function fetch อรายการตำแหน
* @param id idTree
* @param level levelTree
*/
function fetchDataTable(id: string, level: number, action: boolean) {
searchAndReplaceOrgName(nodeTree.value, id);
orgLevel.value = level;
reqMaster.id = id;
reqMaster.type = level;
action1.value = action;
if (action) {
setTimeout(() => {
action1.value = false;
}, 1000);
reqMaster.isAll = false;
reqMaster.page = 1;
reqMaster.pageSize = 10;
reqMaster.keyword = "";
reqMaster.revisionId = store.activeId;
}
if (action === true) {
isLoad.value = true;
}
http
.post(config.API.orgPosMasterListEmp, reqMaster)
.then(async (res) => {
posMaster.value = [];
const dataMain: PosMaster[] = [];
totalPage.value = Math.ceil(res.data.result.total / reqMaster.pageSize);
res.data.result.data.forEach((e: PosMaster) => {
const p = e.positions;
if (p.length !== 0) {
const a = p.find((el: Position) => el.positionIsSelected === true);
const { id, ...rest } = a ? a : p[0];
const test = { ...e, ...rest };
dataMain.push(test);
}
});
posMaster.value = await store.fetchPosMaster(dataMain);
})
.catch((err) => {
messageError($q, err);
posMaster.value = [];
})
.finally(() => {
setTimeout(() => {
isLoad.value = false;
}, 500);
});
}
/**
* งขอมลสถจำนวนดานบน
*/
function getSummary() {
http
.post(config.API.orgSummaryEmp, {
id: reqMaster.id, //*Id node
type: reqMaster.type, //*node
isNode: reqMaster.isAll, //* node
})
.then(async (res: any) => {
const data = await res.data.result;
store.getSumPosition({
totalPosition: data.totalPosition,
totalPositionCurrentUse: data.totalPositionCurrentUse,
totalPositionCurrentVacant: data.totalPositionCurrentVacant,
totalPositionNextUse: data.totalPositionNextUse,
totalPositionNextVacant: data.totalPositionNextVacant,
totalRootPosition: data.totalPosition,
totalRootPositionCurrentUse: data.totalPositionCurrentUse,
totalRootPositionCurrentVacant: data.totalPositionCurrentVacant,
totalRootPositionNextUse: data.totalPositionNextUse,
totalRootPositionNextVacant: data.totalPositionNextVacant,
});
});
}
/**
* funcion นหาขอมลใน Table
*/
function filterKeyword() {
reqMaster.page = 1;
action1.value === false &&
fetchDataTable(reqMaster.id, reqMaster.type, false);
}
/**
* function นหาช
* @param data อม Tree
* @param targetId tree
*/
function searchAndReplaceOrgName(data: any, targetId: string) {
for (const child of data) {
if (child.orgTreeId === targetId) {
mainTree.value = child;
return true; // Found the targetId in this level
}
if (child.children && searchAndReplaceOrgName(child.children, targetId)) {
return true; // Found the targetId in the nested children
}
}
return false; // Not found in this branch
}
/**
* callblck function ทำการ fetch อม Table เมอมการเปลยนหน
*/
watch([() => reqMaster.page, () => reqMaster.pageSize], () => {
action1.value === false &&
fetchDataTable(reqMaster.id, reqMaster.type, false);
});
/**
* callblck function ทำการ fetch อม Table เมอแสดงตำแหนงทงหมด
*/
watch(
() => reqMaster.isAll,
() => {
getSummary();
if (reqMaster.page !== 1) {
reqMaster.page = 1;
} else {
fetchDataTable(reqMaster.id, reqMaster.type, false);
}
}
);
/**
* lifecycle Hook
*/
onMounted(() => {
fetchDataTree();
});
</script>
<template>
@ -13,7 +217,114 @@ import TreeView from "@/modules/16_positionEmployee/components/TreeView.vue";
<q-card flat bordered>
<q-card class="my-card">
<q-card-section style="padding: 0px">
<TreeView />
<div class="col-12">
<q-card bordered class="col-12 row caedNone">
<div class="col-xs-12 col-sm-3 row">
<div class="col-12 row no-wrap bg-grey-1">
<TreeMain
v-model:node-tree="nodeTree"
v-model:short-name="shortName"
v-model:node-id="nodeId"
:fetch-data-table="fetchDataTable"
:fetch-data-tree="fetchDataTree"
/>
<div class="col-12 row">
<q-separator :vertical="!$q.screen.lt.md" />
</div>
</div>
</div>
<div class="col-xs-12 col-sm-9 q-pa-md row">
<div class="col-12 row">
<div
class="row col-12 justify-center"
v-if="isLoad"
style="height: 550px"
>
<div class="col-2">
<q-spinner color="primary" size="3em" />
</div>
</div>
<div v-else class="col-12 row">
<div class="col-12" v-if="nodeId !== ''">
<!-- summary -->
<q-card
bordered
v-if="nodeId"
class="row col-12 justify-between list-summary q-gutter-xs bg-grey-1 q-pb-xs q-pr-xs"
>
<div class="row col q-pa-sm item">
<div class="ellipsis">ตำแหนงทงหมด</div>
<q-space />
<q-badge
color="secondary"
:label="
reqMaster.isAll
? store.sumPosition.total
: store.sumPosition.totalRoot
"
/>
</div>
<div class="row col q-pa-sm item">
<div class="ellipsis">ตำแหนงทคนครอง</div>
<q-space />
<q-badge
color="primary"
:label="
reqMaster.isAll
? store.sumPosition.use
: store.sumPosition.useRoot
"
/>
</div>
<div class="row col q-pa-sm item">
<div class="ellipsis">ตำแหนงวาง</div>
<q-space />
<q-badge
color="red"
:label="
reqMaster.isAll
? store.sumPosition.vacant
: store.sumPosition.vacantRoot
"
/>
</div>
</q-card>
<TreeTable
v-if="nodeId !== ''"
v-model:node-tree="nodeTree"
v-model:org-level="orgLevel"
v-model:tree-id="nodeId"
v-model:pos-master="posMaster"
v-model:req-master="reqMaster"
v-model:total-page="totalPage"
:short-name="shortName"
:main-tree="mainTree"
:fetch-data-table="fetchDataTable"
:fetch-data-tree="fetchDataTree"
:filter-keyword="filterKeyword"
/>
</div>
<div class="row col-12 items-center" v-else>
<q-banner class="q-pa-lg col-12 text-center">
<q-icon
name="mdi-hand-pointing-left"
size="lg"
color="primary"
/>
<p class="text-grey-9 q-pt-sm">กรณาเลอกโครงสราง</p>
</q-banner>
</div>
</div>
</div>
</div>
</q-card>
</div>
<!-- <TreeView /> -->
</q-card-section>
</q-card>
</q-card>