Merge branch 'develop' into devTee

This commit is contained in:
STW_TTTY\stwtt 2024-07-10 15:11:38 +07:00
commit 7ab0dcd8e6
20 changed files with 570 additions and 232 deletions

View file

@ -10,6 +10,7 @@ const placemenRepatriation = `${placement}/repatriation`;
const placemenRelocation = `${placement}/relocation`;
const placemenOther = `${env.API_URI}/retirement/other`;
const placemenAppointment = `${placement}/appointment`;
const orgSearchCommand = `${env.API_URI}/org/profile/search/profile/command`;
export default {
MainDetail: (year: number) => `${placement}/exam/${year}`,
@ -102,6 +103,7 @@ export default {
orderReady: (id: string) => `${order}/order/ready/${id}`,
attachmentOrder: (orderId: string) => `${order}/order/attachment/${orderId}`,
searchOrderprofile: () => `${order}/order/search/profile/command`,
searchCommandProfileNew: () => `${orgSearchCommand}`,
disciplineReportList,
//receive ระบบรับโอน
receiveData: () => `${receive}`,

View file

@ -1225,7 +1225,7 @@ onMounted(async () => {
</div>
</div>
<!-- add -->
<q-dialog v-model="modalAdd">
<q-dialog v-model="modalAdd" persistent>
<q-card style="width: 900px; max-width: 80vw">
<q-toolbar class="q-py-md">
<q-toolbar-title class="text-h6">เพมรายช </q-toolbar-title>
@ -1486,7 +1486,7 @@ onMounted(async () => {
/>
<!-- เหตผลทลบออก -->
<DialogPopupReason
:modal="modelPopupDelete"
v-model:modal="modelPopupDelete"
title="เหตุผลการลบออก"
label="หมายเหตุ"
:click-close="closemodelPopupDelete"
@ -1500,7 +1500,7 @@ onMounted(async () => {
:click-close="clickCloseReson"
/>
<!-- แจงเตอน -->
<q-dialog v-model="dialogWarn">
<q-dialog v-model="dialogWarn" persistent>
<q-card style="width: 800px; max-width: 80vw">
<q-toolbar class="q-py-md">
<q-toolbar-title class="text-h6">แจงเตอน </q-toolbar-title>

View file

@ -103,9 +103,9 @@ const clickSearch = async () => {
};
showLoader();
http
.post(config.API.searchOrderprofile(), body)
.then((res) => {
let data = res.data.result;
.post(config.API.searchCommandProfileNew(), body)
.then(async (res) => {
let data = await res.data.result.data;
if (data.length !== 0) {
rows.value = data.map((e: history) => ({
id: e.id,
@ -312,7 +312,9 @@ function updatemodalPersonal(modal: boolean) {
>{{ props.row.name }}</q-td
>
<q-td key="posNo" :props="props">{{ props.row.posNo }}</q-td>
<q-td key="posNo" :props="props">{{
props.row.posNo !== null ? props.row.posNo : "-"
}}</q-td>
<q-td key="position" :props="props">{{
props.row.position
}}</q-td>

View file

@ -877,7 +877,6 @@ const getClass = (val: boolean) => {
v-model="command"
hide-bottom-space
:label="`${'คำสั่งเลขที่'}`"
:rules="[(val) => !!val || `${'กรุณากรอกคำสั่งเลขที่'}`]"
/>
</div>
<label class="col-1 flex justify-center items-center text-bold"

View file

@ -249,7 +249,7 @@ const saveModal = () => {
if (myForm.value !== null) {
myForm.value.validate().then(async (result: boolean) => {
if (result) {
putSalary(modalData.value);
putSalary();
}
});
}
@ -309,7 +309,7 @@ const fetchSalary = async (personalId: string) => {
});
};
//
const putSalary = async (salary: any) => {
const putSalary = async () => {
dialogConfirm($q, async () => {
showLoader();
if (modalData.value.salaryAmount === null) {
@ -323,15 +323,15 @@ const putSalary = async (salary: any) => {
}
await http
.put(config.API.salaryOrder(personalId.value), modalData.value)
.then(() => {
.then(async () => {
await conditionData();
modal.value = false;
success($q, "บันทึกข้อมูลสำเร็จ");
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await conditionData();
modal.value = false;
hideLoader();
});
});
@ -446,19 +446,6 @@ const resetFilter = () => {
filter.value = "";
filterRef.value!.focus();
};
const getClass = (val: boolean) => {
return {
"full-width inputgreen cursor-pointer": val,
"full-width cursor-pointer": !val,
};
};
const pagination = ref({
// sortBy: "OrderDate,OrderType",
descending: true,
page: 1,
rowsPerPage: 10,
});
</script>
<template>
@ -641,17 +628,9 @@ const pagination = ref({
:rules="[(val:number) => !!val || `${'กรุณากรอกเงินเดือน'}`]"
lazy-rules
class="inputgreen"
mask="###,###,###,###"
mask="###,###,###,###,###,###,###,###"
reverse-fill-mask
/>
<!-- <CurruncyInput
:edit="true"
:dense="true"
v-model="modalData.salaryAmount"
:label="`${'เงินเดือน'}`"
:rules="[(val: any) => !!val || `${'กรุณากรอกเงินเดือน'}`]"
hide-bottom-space
/> -->
</div>
<div class="col-xs-6 col-sm-6 col-md-6">
@ -661,19 +640,11 @@ const pagination = ref({
dense
hide-bottom-space
:label="`${'เงินประจำตำแหน่ง'}`"
:rules="modalData.positionSalaryAmount !== 0 ?[(val:number) => !!val || `${'กรุณากรอกเงินประจำตำแหน่ง'}`] : []"
lazy-rules
class="inputgreen"
mask="###,###,###,###"
mask="###,###,###,###,###,###,###,###"
reverse-fill-mask
/>
<!-- <CurruncyInput
:edit="true"
:dense="true"
v-model="modalData.positionSalaryAmount"
:label="`${'เงินประจำตำแหน่ง'}`"
hide-bottom-space
/> -->
</div>
<div class="col-xs-6 col-sm-6 col-md-6">
@ -683,19 +654,11 @@ const pagination = ref({
dense
hide-bottom-space
:label="`${'เงินค่าตอบแทนรายเดือน'}`"
:rules="modalData.monthSalaryAmount !== 0 ?[(val:number) => !!val || `${'กรุณากรอกเงินค่าตอบแทนรายเดือน'}`]:[]"
lazy-rules
class="inputgreen"
mask="###,###,###,###"
mask="###,###,###,###,###,###,###,###"
reverse-fill-mask
/>
<!-- <CurruncyInput
:edit="true"
:dense="true"
v-model="modalData.monthSalaryAmount"
:label="`${'เงินค่าตอบแทนรายเดือน'}`"
hide-bottom-space
/> -->
</div>
<div class="col-xs-6 col-sm-6 col-md-12" v-if="checkNote">
<q-input
@ -705,6 +668,7 @@ const pagination = ref({
label="หมายเหตุแนวตั้ง"
type="textarea"
rows="2"
class="inputgreen"
/>
</div>
<div class="col-xs-6 col-sm-6 col-md-12" v-if="checkNote">
@ -715,6 +679,7 @@ const pagination = ref({
type="textarea"
label="หมายเหตุแนวนอน"
rows="2"
class="inputgreen"
/>
</div>
</div>

View file

@ -1,13 +1,21 @@
const mainPage = () => import("@/modules/12_evaluatePersonal/views/MainPage.vue");
const detailPage = () => import("@/modules/12_evaluatePersonal/views/DetailPage.vue");
const mainPage = () =>
import("@/modules/12_evaluatePersonal/views/MainPage.vue");
const detailPage = () =>
import("@/modules/12_evaluatePersonal/views/DetailPage.vue");
const directorPage = () => import("@/modules/12_evaluatePersonal/components/Director/MainPage.vue");
const directorAddPage = () => import("@/modules/12_evaluatePersonal/components/Director/AddPage.vue");
const directorEditPage = () => import("@/modules/12_evaluatePersonal/components/Director/EditPage.vue");
const directorPage = () =>
import("@/modules/12_evaluatePersonal/components/Director/MainPage.vue");
const directorAddPage = () =>
import("@/modules/12_evaluatePersonal/components/Director/AddPage.vue");
const directorEditPage = () =>
import("@/modules/12_evaluatePersonal/components/Director/EditPage.vue");
const meetingPage = () => import("@/modules/12_evaluatePersonal/components/Meeting/MainPage.vue");
const meetingAddPage = () => import("@/modules/12_evaluatePersonal/components/Meeting/AddPage.vue");
const meetingEditPage = () => import("@/modules/12_evaluatePersonal/components/Meeting/EditPage.vue");
const meetingPage = () =>
import("@/modules/12_evaluatePersonal/components/Meeting/MainPage.vue");
const meetingAddPage = () =>
import("@/modules/12_evaluatePersonal/components/Meeting/AddPage.vue");
const meetingEditPage = () =>
import("@/modules/12_evaluatePersonal/components/Meeting/EditPage.vue");
export default [
{
@ -37,7 +45,7 @@ export default [
meta: {
Auth: true,
Key: [12.2],
Role: "discipline",
Role: "evaluate",
},
},
{
@ -47,7 +55,7 @@ export default [
meta: {
Auth: true,
Key: [12.2],
Role: "discipline",
Role: "evaluate",
},
},
{
@ -57,7 +65,7 @@ export default [
meta: {
Auth: true,
Key: [12.2],
Role: "discipline",
Role: "evaluate",
},
},
{
@ -67,7 +75,7 @@ export default [
meta: {
Auth: true,
Key: [12.2],
Role: "discipline",
Role: "evaluate",
},
},
{
@ -77,7 +85,7 @@ export default [
meta: {
Auth: true,
Key: [12.2],
Role: "discipline",
Role: "evaluate",
},
},
{
@ -87,7 +95,7 @@ export default [
meta: {
Auth: true,
Key: [12.2],
Role: "discipline",
Role: "evaluate",
},
},
];
];

View file

@ -455,7 +455,7 @@ function fetchSalaryRound() {
v-model="command"
hide-bottom-space
:label="`${'คำสั่งเลขที่'}`"
:rules="[(val) => !!val || `${'กรุณากรอกคำสั่งเลขที่'}`]"
/>
</div>
<label class="col-1 flex justify-center items-center text-bold"

View file

@ -319,15 +319,15 @@ const putSalary = async (salary: any) => {
}
await http
.put(config.API.salaryOrder(personalId.value), modalData.value)
.then(() => {
.then(async () => {
await conditionData();
modal.value = false;
success($q, "บันทึกข้อมูลสำเร็จ");
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await conditionData();
modal.value = false;
hideLoader();
});
});

View file

@ -1,7 +1,6 @@
<script setup lang="ts">
import { computed, ref, reactive, watch } from "vue";
import { useQuasar } from "quasar";
import axios from "axios";
import http from "@/plugins/http";
import config from "@/app.config";
@ -59,7 +58,9 @@ const formData = reactive<FormData>({
});
const posType = ref<SalaryPosType[]>([]);
const salaryPosTypeOptionMain = ref<DataOption[]>([]);
const salaryPosTypeOption = ref<DataOption[]>([]);
const salaryPosLevelOptionMain = ref<DataOption[]>([]);
const salaryPosLevelOption = ref<DataOption[]>([]);
const title = computed(() => {
@ -73,7 +74,9 @@ const title = computed(() => {
return name;
});
/** fiunction fetch ข้อมูลประเภทตำแหน่ง*/
/**
* fiunction fetch อมลประเภทตำแหน
*/
function fetchPosType() {
http
.get(config.API.salaryPosType)
@ -84,13 +87,16 @@ function fetchPosType() {
name: e.posTypeName,
}));
salaryPosTypeOption.value = listOption;
salaryPosTypeOptionMain.value = listOption;
})
.catch((err) => {
messageError($q, err);
});
}
/** fiunction fetch ข้อมูลระดับตำแหน่ง*/
/**
* fiunction fetch อมลระดบตำแหน
*/
function fetchPosLevel(id: string) {
const filterLevel = posType.value.find((e: SalaryPosType) => e.id === id);
const listOption =
@ -100,6 +106,7 @@ function fetchPosLevel(id: string) {
})) || [];
salaryPosLevelOption.value = listOption;
salaryPosLevelOptionMain.value = listOption;
if (!listOption.some((e: DataOption) => e.id === formData.posLevelId)) {
formData.posLevelId = "";
}
@ -134,34 +141,41 @@ function fetchSalaryDetail(id: string) {
});
}
/** callbackFunction ทำการ fetch ข้อมูลไฟล์เมื่อเปิด Dialog*/
/**
* callbackFunction ทำการ fetch อมลไฟลเมอเป Dialog
*/
watch(
() => modal.value,
() => {
async () => {
if (modal.value) {
if (salaryPosTypeOption.value.length === 0) {
fetchPosType();
}
await fetchPosType();
if (props.typeAction === "edit") {
showLoader();
setTimeout(() => {
if (props.data) {
salaryId.value = props.data.id;
fetchPosLevel(props?.data?.posTypeId);
fetchSalaryDetail(props.data.id);
fetchPosLevel(props.data.posTypeId);
hideLoader();
}
}, 100);
}, 2000);
}
}
}
);
/** function ปืด Dialog*/
/**
* function Dialog
*/
function closeDialog() {
modal.value = !modal.value;
clearFormData();
}
/** function เคลียข้อมูล form*/
/**
* function เคลยขอม form
*/
function clearFormData() {
formData.name = "";
formData.posTypeId = "";
@ -175,7 +189,9 @@ function clearFormData() {
isReadonly.value = false;
}
/** function บัยทึกข้อมูลผังบัญชีเงินเดือน*/
/**
* function ยทกขอมลผงบญชเงนเดอน
*/
function onSubmit() {
dialogConfirm($q, async () => {
showLoader();
@ -196,7 +212,9 @@ function onSubmit() {
});
}
/** function checkEndDate*/
/**
* function checkEndDate
*/
function checkEndDate() {
if (formData.endDate !== null && formData.startDate !== null) {
if (formData.endDate < formData.startDate) {
@ -204,6 +222,47 @@ function checkEndDate() {
}
}
}
/**
* function นหาคำใน select
* @param val คำคนหา
* @param update function
* @param type ประเภท select
*/
function filterSelector(val: string, update: Function, type: string) {
switch (type) {
case "posType":
update(() => {
formData.posTypeId = "";
salaryPosTypeOption.value = salaryPosTypeOptionMain.value.filter(
(v: DataOption) => v.name.toLowerCase().indexOf(val) > -1
);
});
break;
case "posLevel":
update(() => {
formData.posLevelId = "";
salaryPosLevelOption.value = salaryPosLevelOptionMain.value.filter(
(v: DataOption) => v.name.toLowerCase().indexOf(val) > -1
);
});
break;
default:
break;
}
}
/**
* class ดรปแบบแสดงระหวางขอมลทแกไขหรอแสดงเฉยๆ
* @param val อม input สำหรบแกไขหรอไม
*/
const getClass = (val: boolean) => {
return {
"full-width inputgreen cursor-pointer": val,
"full-width cursor-pointer": !val,
};
};
</script>
<template>
@ -219,6 +278,7 @@ function checkEndDate() {
<div class="col-xs-12 col-md-4">
<q-input
:readonly="isReadonly"
:class="getClass(!isReadonly)"
ref="nameRef"
dense
hide-bottom-space
@ -235,6 +295,7 @@ function checkEndDate() {
<div class="col-xs-12 col-md-4">
<q-select
:readonly="isReadonly"
:class="getClass(!isReadonly)"
ref="posTypeRef"
dense
hide-bottom-space
@ -248,13 +309,25 @@ function checkEndDate() {
label="ประเภทตำแหน่ง/กลุ่ม"
:rules="[(val) => !!val || 'กรุณาเลือกประเภทตำแหน่ง/กลุ่ม']"
lazy-rules
use-input
@update:model-value="fetchPosLevel"
/>
@filter="(inputValue: string,
doneFn: Function) => filterSelector(inputValue, doneFn ,'posType')"
>
<template v-slot:no-option>
<q-item>
<q-item-section class="text-grey">
ไมอม
</q-item-section>
</q-item>
</template>
</q-select>
</div>
<div class="col-xs-12 col-md-4">
<q-select
:readonly="isReadonly"
:class="getClass(!isReadonly)"
ref="posLevelRef"
dense
hide-bottom-space
@ -268,8 +341,19 @@ function checkEndDate() {
label="ระดับ"
:rules="[(val) => !!val || 'กรุณาเลือกระดับ']"
lazy-rules
use-input
:disable="formData.posTypeId === ''"
/>
@filter="(inputValue: string,
doneFn: Function) => filterSelector(inputValue, doneFn ,'posLevel')"
>
<template v-slot:no-option>
<q-item>
<q-item-section class="text-grey">
ไมอม
</q-item-section>
</q-item>
</template></q-select
>
</div>
<div class="row col-12">
@ -298,6 +382,7 @@ function checkEndDate() {
:enableTimePicker="false"
week-start="0"
:readonly="isReadonly"
:class="getClass(!isReadonly)"
>
<template #year="{ year }">
{{ year + 543 }}
@ -334,6 +419,7 @@ function checkEndDate() {
<div class="col-xs-12 col-md-4">
<datepicker
:readonly="isReadonly"
:class="getClass(!isReadonly)"
menu-class-name="modalfix"
v-model="formData.startDate"
:locale="'th'"
@ -378,6 +464,7 @@ function checkEndDate() {
<div class="col-xs-12 col-md-4">
<datepicker
:readonly="isReadonly"
:class="getClass(!isReadonly)"
menu-class-name="modalfix"
v-model="formData.endDate"
:locale="'th'"
@ -420,6 +507,7 @@ function checkEndDate() {
<div class="col-12">
<q-input
:class="getClass(!isReadonly)"
:readonly="isReadonly"
v-model="formData.details"
outlined

View file

@ -155,11 +155,19 @@ function getPosType() {
.get(config.API.salaryEmployeePosType())
.then((res) => {
const data = res.data.result;
posTypeOp.value = data.map((item: PosType) => ({
const option = [
{
id: "",
name: "ทั้งหมด",
},
];
const test = data.map((item: PosType) => ({
id: item.id,
name: item.posTypeName,
}));
option.push(...test);
posTypeOp.value = option;
})
.catch((e) => {
messageError($q, e);

View file

@ -194,7 +194,7 @@ const fiscalYearFilter = async () => {
};
//
const OrderType = ref<string>("");
const OrderType = ref<string | null>("");
const OrderTypeFilter1 = ref<DataOption1[]>([]);
const OrderTypeOption = ref<DataOption1[]>([{ id: "", name: "ทั้งหมด" }]);
@ -238,7 +238,9 @@ async function OrderTypeFilter() {
/** ฟังชั่นฟิลเตอร์ตามค่า ประเภท สถานะ ปี */
async function searchFilterTable() {
stroe.filterListOrder(OrderType.value, OrderStatus.value, fiscalyear.value);
if (OrderType.value) {
stroe.filterListOrder(OrderType.value, OrderStatus.value, fiscalyear.value);
}
}
/** fucnction หาสถานะทั่งหมด*/
@ -273,6 +275,7 @@ function filterSelector(val: string, update: Function, refData: string) {
switch (refData) {
case "fiscalyearOP":
update(() => {
fiscalyear.value = null;
fiscalyearOP.value = fiscalyearFilter1.value.filter(
(v: DataOption) => v.name.indexOf(val) > -1
);
@ -280,6 +283,7 @@ function filterSelector(val: string, update: Function, refData: string) {
break;
case "OrderTypeOption":
update(() => {
OrderType.value = null;
OrderTypeOption.value = OrderTypeFilter1.value.filter(
(v: DataOption1) => v.name.indexOf(val) > -1
);
@ -287,6 +291,7 @@ function filterSelector(val: string, update: Function, refData: string) {
break;
case "OrderStatusOption":
update(() => {
OrderStatus.value = "";
OrderStatusOption.value = OrderStatusFilter1.value.filter(
(v: DataOption1) => v.name.indexOf(val) > -1
);
@ -364,8 +369,17 @@ onMounted(async () => {
<q-item-section class="text-grey"> ไมอม </q-item-section>
</q-item>
</template>
<template v-if="fiscalyear !== 0" v-slot:append>
<q-icon
name="cancel"
@click.stop.prevent="
(fiscalyearOP = fiscalyearFilter1), (fiscalyear = 0)
"
class="cursor-pointer"
/>
</template>
</q-select>
<!-- use-input -->
<div>
<q-btn
size="12px"
@ -449,6 +463,15 @@ onMounted(async () => {
</q-item-section>
</q-item>
</template>
<template v-if="OrderType !== ''" v-slot:append>
<q-icon
name="cancel"
@click.stop.prevent="
(OrderTypeOption = OrderTypeFilter1), (OrderType = '')
"
class="cursor-pointer"
/>
</template>
</q-select>
</div>
<div class="col-xs-12 col-sm-3 col-md-3">
@ -480,6 +503,16 @@ onMounted(async () => {
</q-item-section>
</q-item>
</template>
<template v-if="OrderStatus !== 'ทั้งหมด'" v-slot:append>
<q-icon
name="cancel"
@click.stop.prevent="
(OrderStatusOption = OrderStatusFilter1),
(OrderStatus = 'ทั้งหมด')
"
class="cursor-pointer"
/>
</template>
</q-select>
</div>
<q-space />

View file

@ -122,7 +122,9 @@ const isActive = ref<boolean>(false);
const typeAction = ref<string>("");
const dataRow = ref<Salary>();
/** function fetch ข้อมูลรายการผังบัญชีเงินเดือน */
/**
* function fetch อมลรายการผงบญชเงนเดอน
*/
function fetchListSalaly() {
showLoader();
const page = formQuery.page.toString();
@ -219,7 +221,9 @@ function onClickUpload(type: string, id: string, active: boolean) {
isActive.value = active;
}
/** callbackFunction ทำงานเมื่อมีการ เปลี่ยนหน่าหรือ แถว*/
/**
* callbackFunction ทำงานเมอมการ เปลยนหนาหร แถว
*/
watch([() => formQuery.page, () => formQuery.pageSize], () => {
fetchListSalaly();
});
@ -233,7 +237,9 @@ function updatePagination(newPagination: NewPagination) {
formQuery.pageSize = newPagination.rowsPerPage;
}
/** function ค้นหาข้อมูลตาม keyword*/
/**
* function นหาขอมลตาม keyword
*/
function filterFn(page: number) {
page !== 1 ? (formQuery.page = 1) : fetchListSalaly();
}

View file

@ -447,7 +447,9 @@ onMounted(() => {
<template v-if="agencyFilter !== 'ALL'" v-slot:append>
<q-icon
name="cancel"
@click.stop.prevent="agencyFilter = 'ALL'"
@click.stop.prevent="
(agencyOptions = agencyOptionsMain), (agencyFilter = 'ALL')
"
class="cursor-pointer"
/> </template
></q-select>

View file

@ -427,6 +427,7 @@ onMounted(() => {
class="q-ml-xs"
v-model="agencyFilter"
label="หน่วยงาน"
lazy-rules
dense
outlined
emit-value
@ -451,7 +452,9 @@ onMounted(() => {
<template v-if="agencyFilter !== 'ALL'" v-slot:append>
<q-icon
name="cancel"
@click.stop.prevent="agencyFilter = 'ALL'"
@click.stop.prevent="
(agencyOptions = agencyOptionsMain), (agencyFilter = 'ALL')
"
class="cursor-pointer"
/>
</template>

View file

@ -272,7 +272,7 @@ onMounted(async () => {
<q-input
dense
outlined
:model-value="year === 0 ? null : Number(year) + 543"
:model-value="year === 0 ? 'ทั้งหมด' : Number(year) + 543"
:label="`${'ปีงบประมาณ'}`"
>
<template v-if="year" v-slot:append>

View file

@ -137,7 +137,7 @@ function onAnnounce() {
await porps.fetchData();
await success($q, "ประกาศผลสำเร็จ");
selected.value = [];
}, 1000);
}, 1500);
})
.catch((err) => {
messageError($q, err);

View file

@ -54,4 +54,86 @@ interface ResResults {
profileId: string;
}
export type { ResRound, ResDataCapacity, ResEvaluator, ResResults };
interface ResRoundEvaluate {
createdAt: string;
createdFullName: string;
createdUserId: string;
durationKPI: string;
endDate: string;
id: string;
isActive: boolean;
lastUpdateFullName: string;
lastUpdateUserId: string;
lastUpdatedAt: string;
startDate: string;
year: number;
}
interface ResOrg {
labelName: string;
orgCode: string;
orgLevel: number;
orgName: string;
orgRevisionId: string;
orgRootName: string;
orgTreeCode: string;
orgTreeFax: string;
orgTreeId: string;
orgTreeName: string;
orgTreeOrder: number;
orgTreePhoneEx: string;
orgTreePhoneIn: string;
orgTreeRank: string;
orgTreeRankSub: string;
orgTreeShortName: string;
responsibility: string;
totalPosition: number;
totalPositionCurrentUse: number;
totalPositionCurrentVacant: number;
totalPositionNextUse: number;
totalPositionNextVacant: number;
totalRootPosition: number;
totalRootPositionCurrentUse: number;
totalRootPositionCurrentVacant: number;
totalRootPositionNextUse: number;
totalRootPositionNextVacant: number;
children: ResOrg[];
}
interface ResReport {
reportName: string;
template: string;
}
interface ResPerson {
avatar: string;
avatarName: string;
citizenId: string;
firstName: string;
id: string;
lastName: string;
org: string;
orgRevisionId: string;
orgRootShortName: string;
posExecutive: string;
posLevel: string;
posLevelId: string;
posNo: string;
posType: string;
posTypeId: string;
position: string;
prefix: string;
rank: string;
root: string;
rootId: string;
}
export type {
ResRound,
ResDataCapacity,
ResEvaluator,
ResResults,
ResRoundEvaluate,
ResOrg,
ResReport,
ResPerson,
};

View file

@ -1,5 +1,5 @@
<script setup lang="ts">
import { ref, onMounted } from "vue";
import { ref, onMounted, reactive, watch } from "vue";
import { useQuasar } from "quasar";
import { VuePDF, usePDF } from "@tato30/vue-pdf";
import config from "@/app.config";
@ -7,18 +7,40 @@ import http from "@/plugins/http";
import axios from "axios";
import genReport from "@/plugins/genreport";
import type { DataOption } from "@/modules/14_KPI/interface/index/Main";
/**
* importType
*/
import type { QTableProps } from "quasar";
import type {
DataOption,
NewPagination,
} from "@/modules/14_KPI/interface/index/Main";
import type {
ResRoundEvaluate,
ResOrg,
ResReport,
ResPerson,
} from "@/modules/14_KPI/interface/response/Main";
import { useCounterMixin } from "@/stores/mixin";
/**
* importComponents
*/
import DialogHeader from "@/components/DialogHeader.vue";
/**
* importStore
*/
import { useCounterMixin } from "@/stores/mixin";
/**
* use
*/
const $q = useQuasar();
const { showLoader, hideLoader, messageError } = useCounterMixin();
const { showLoader, hideLoader, messageError, date2Thai, dialogConfirm } =
useCounterMixin();
/**
* วแปรงาน
*/
const year = ref<number | null>(new Date().getFullYear());
const round = ref<string>("");
const organization = ref<string>("");
@ -66,6 +88,9 @@ const listReportMain = ref<DataOption[]>([
]);
const listReport = ref<DataOption[]>([]);
/**
* funtion fetchขอมลรอบการประเม
*/
function fetchRoundOption() {
http
.get(
@ -74,8 +99,9 @@ function fetchRoundOption() {
)
.then(async (res) => {
const data = await res.data.result.data;
if (res.data.result.data.length > 0) {
const list = await data.map((e: any) => ({
const list = await data.map((e: ResRoundEvaluate) => ({
id: e.id,
name:
e.durationKPI === "OCT"
@ -98,6 +124,9 @@ function fetchRoundOption() {
});
}
/**
* function fetch อมลโครงสรางปจจ
*/
function fetchActiveId() {
showLoader();
http
@ -112,12 +141,16 @@ function fetchActiveId() {
});
}
/**
* function fetch อมลหนวยงาน
* @param id โครงสรางปจจ
*/
function fetchListOrg(id: string) {
showLoader();
http
.get(config.API.orgByid(id))
.then(async (res) => {
const data = await res.data.result.map((item: any) => ({
const data = await res.data.result.map((item: ResOrg) => ({
id: item.orgTreeId,
name: item.orgName,
}));
@ -131,13 +164,16 @@ function fetchListOrg(id: string) {
});
}
/**
* function fetch รายงาน
*/
function fetchReport() {
showLoader();
const body = {
type: typeReport.value,
periodId: round.value,
root: organization.value,
// persanalId: persanalId.value,
profileId: persanalId.value ? persanalId.value : undefined,
};
http
.post(config.API.kpiReport(), body)
@ -149,6 +185,9 @@ function fetchReport() {
.catch((err) => {
messageError($q, err);
hideLoader();
})
.finally(() => {
persanalId.value = "";
});
}
@ -156,7 +195,7 @@ function fetchReport() {
* function เรยกไฟล PDF
* @param data อมลบญชนลา
*/
function genPDf(data: any) {
function genPDf(data: ResReport) {
showLoader();
axios
.post(config.API.reportTemplate + `/docx`, data, {
@ -184,6 +223,10 @@ function genPDf(data: any) {
});
}
/**
* function เปลยนประเภทรายงาน
* @param val ประเภทรายงาน
*/
function changOption(val: string) {
if (
val === "KPI1" ||
@ -202,10 +245,17 @@ function changOption(val: string) {
}
}
/**
* function นหาคำใน select
* @param val คำคนหา
* @param update function
* @param type ประเภท select
*/
function filterSelector(val: string, update: Function, type: string) {
switch (type) {
case "typereport":
update(() => {
typeReport.value = "";
listReport.value = listReportMain.value.filter(
(v: DataOption) => v.name.toLowerCase().indexOf(val) > -1
);
@ -213,6 +263,7 @@ function filterSelector(val: string, update: Function, type: string) {
break;
case "organization":
update(() => {
organization.value = "";
organizationOps.value = organizationOpsMain.value.filter(
(v: DataOption) => v.name.toLowerCase().indexOf(val) > -1
);
@ -224,48 +275,64 @@ function filterSelector(val: string, update: Function, type: string) {
}
}
/**
* อม file
*/
const splitterModel = ref(14);
const numOfPages = ref<number>(0);
const page = ref<number>(1);
const pdfSrc = ref<any>();
const dataDownload = ref<any>();
const dataDownload = ref<ResReport | null>();
async function downloadReport(data: any, type: string) {
/**
* function โหลดไฟล
* @param data อมลไฟล
* @param type นามสกลไฟล
*/
function downloadReport(data: ResReport | null | undefined, type: string) {
const name =
listReportMain.value.find((e) => e.id === typeReport.value)?.name ?? "";
var fileName = name;
genReport(data, fileName, type);
}
/** ไปหน้าต่อไปของรายงาน */
/**
* ไปหนาตอไปของรายงาน
*/
function nextPage() {
if (page.value < numOfPages.value) {
page.value++;
}
}
/** กลับหน้าก่อนหน้าของรายงาน */
/**
* กลบหนากอนหนาของรายงาน
*/
function backPage() {
if (page.value !== 1) {
page.value--;
}
}
/*******/
/**
* popup เลอกราชช
*/
const modal = ref<boolean>(false);
const persanalId = ref<string>("");
const filter = ref<string>("");
const rowsPerson = ref<any[]>([
{
id: "1",
citizenId: "12345678910123",
name: "tset,",
posNo: "1",
position: "ตำแหน่งในสายงาน",
posType: "ตำแหน่งประเภท",
posLevel: "ระดับ",
},
const typeFilter = ref<DataOption[]>([
{ id: "fullName", name: "ชื่อ-นามสกุล" },
{ id: "citizenId", name: "เลขประจำตัวประชาชน" },
]);
const formFilter = reactive({
page: 1,
pageSize: 10,
searchField: "fullName",
searchKeyword: "",
});
const maxPage = ref<number>(1);
const total = ref<number>(0);
const rowsPerson = ref<ResPerson[]>([]);
const columns = ref<QTableProps["columns"]>([
{
name: "citizenId",
@ -281,6 +348,9 @@ const columns = ref<QTableProps["columns"]>([
align: "left",
label: "ชื่อ-นามสกุล",
field: "name",
format(val, row) {
return `${row.prefix ?? ""}${row.firstName ?? ""} ${row.lastName ?? ""}`;
},
sortable: false,
headerStyle: "font-size: 14px",
style: "font-size: 14px",
@ -323,25 +393,80 @@ const columns = ref<QTableProps["columns"]>([
},
]);
/**
* function เป popup เลอกราชช
*/
function onClickModal() {
modal.value = true;
if ((modal.value = true)) {
fetchListPerson();
}
fetchListPerson();
}
/**
* function popup เลอกราชช
*/
function onCloseModal() {
modal.value = false;
formFilter.page = 1;
formFilter.searchField = "fullName";
formFilter.searchKeyword = "";
}
function fetchListPerson() {}
/**
* function fetch รายชอขอมลทะเบยนประว
*/
function fetchListPerson() {
showLoader();
let queryParams = {
page: formFilter.page,
pageSize: formFilter.pageSize,
};
if (formFilter.searchKeyword) {
queryParams = Object.assign({}, queryParams, {
searchField: formFilter.searchField,
searchKeyword: formFilter.searchKeyword,
});
}
http
.get(config.API.registryNew(""), { params: queryParams })
.then((res) => {
maxPage.value = Math.ceil(res.data.result.total / formFilter.pageSize);
rowsPerson.value = res.data.result.data;
total.value = res.data.result.total;
})
.catch((err) => {
messageError($q, err);
})
.finally(() => {
hideLoader();
});
}
/**
* functiuon เลอกราชช
* @param id profile ID
*/
function onSelectPerson(id: string) {
persanalId.value = id;
onCloseModal();
fetchReport();
}
/**
* function เปลยนแถวตอหน
* @param newPagination อม Paging
*/
function updatePageSizePagination(newPagination: NewPagination) {
formFilter.page = 1;
formFilter.pageSize = newPagination.rowsPerPage;
}
watch(
() => formFilter.pageSize,
() => {
fetchListPerson();
}
);
onMounted(() => {
fetchRoundOption();
fetchActiveId();
@ -370,7 +495,13 @@ onMounted(() => {
@update:model-value="changOption"
@filter="(inputValue: string,
doneFn: Function) => filterSelector(inputValue, doneFn ,'typereport')"
/>
>
<template v-slot:no-option>
<q-item>
<q-item-section class="text-grey"> ไมอม </q-item-section>
</q-item>
</template></q-select
>
</div>
<q-space />
@ -492,48 +623,17 @@ onMounted(() => {
@filter="(inputValue: string,
doneFn: Function) => filterSelector(inputValue, doneFn,'organization' )"
/>
>
<template v-slot:no-option>
<q-item>
<q-item-section class="text-grey"> ไมอม </q-item-section>
</q-item>
</template></q-select
>
</div>
<div class="q-pa-sm" v-else>
<q-btn color="primary" label="เลือกรายชื่อ" @click="onClickModal" />
<!-- <q-select
class="bg-white"
style="width: 200px"
dense
hide-bottom-space
outlined
option-label="name"
option-value="id"
emit-value
map-options
v-model="searchField"
:options="typeFilter"
label="ค้นหาจาก"
/>
<q-input
class="bg-white"
v-model="search"
outlined
clearable
hide-bottom-space
dense
label="คำค้น"
style="width: 350px"
>
<template v-slot:after>
<q-btn
color="primary"
icon="search"
label="ค้นหา"
class="full-width q-py-sm q-px-md"
@click="fetchReport"
>
</q-btn>
</template>
</q-input> -->
</div>
</q-toolbar>
@ -627,16 +727,48 @@ onMounted(() => {
</q-card>
<q-dialog v-model="modal" persistent>
<q-card style="width: 900px; max-width: 80vw">
<q-card style="width: 1000px; max-width: 100vw">
<DialogHeader :tittle="'เลือกราชชื่อ'" :close="onCloseModal" />
<q-separator />
<q-card-section class="q-col-gutter-sm">
<div class="col-12">
<q-input outlined dense v-model="filter" label="ค้นหา">
<template v-slot:append>
<q-icon name="search" color="grey-5" />
</template>
</q-input>
<div class="row col-12 q-col-gutter-sm">
<div class="col-3">
<q-select
class="bg-white"
dense
hide-bottom-space
outlined
option-label="name"
option-value="id"
emit-value
map-options
v-model="formFilter.searchField"
:options="typeFilter"
label="ค้นหาจาก"
/>
</div>
<div class="col-9">
<q-input
class="bg-white"
v-model="formFilter.searchKeyword"
outlined
clearable
hide-bottom-space
dense
label="คำค้น"
>
<template v-slot:after>
<q-btn
color="primary"
icon="search"
label="ค้นหา"
class="full-width q-py-sm q-px-md"
@click="(formFilter.page = 1), fetchListPerson()"
>
</q-btn>
</template>
</q-input>
</div>
</div>
<div class="col-12">
<d-table
@ -649,6 +781,7 @@ onMounted(() => {
bordered
dense
:rows-per-page-options="[10, 25, 50, 100]"
@update:pagination="updatePageSizePagination"
>
<template v-slot:header="props">
<q-tr :props="props">
@ -675,18 +808,20 @@ onMounted(() => {
</q-td>
</q-tr>
</template>
<!-- <template v-slot:pagination="scope">
<q-pagination
v-model="reqMaster.page"
active-color="primary"
color="dark"
:max="totalPage"
:max-pages="5"
size="sm"
boundary-links
direction-links
></q-pagination>
</template> -->
<template v-slot:pagination="scope">
งหมด {{ total }} รายการ
<q-pagination
v-model="formFilter.page"
active-color="primary"
color="dark"
:max="maxPage"
:max-pages="5"
size="sm"
boundary-links
direction-links
@update:model-value="fetchListPerson()"
></q-pagination>
</template>
</d-table>
</div>
</q-card-section>

View file

@ -184,15 +184,15 @@ const formGroupTarget = reactive<FormGroupTargetPlannedGoal>({
groupTarget: "",
groupTargetSub: "",
position: "",
posType: "",
posLevel: "",
posType: null,
posLevel: null,
type: null,
amount: null,
positions: [
{
position: "",
posTypeId: "",
posLevelId: "",
posTypeId: null,
posLevelId: null,
},
],
});
@ -210,8 +210,8 @@ const posTypeMain = ref<ResGroup[]>([]);
const addGroupTargetData = async () => {
formGroupTarget.positions.push({
position: "",
posTypeId: "",
posLevelId: "",
posTypeId: null,
posLevelId: null,
});
};
@ -262,8 +262,8 @@ function onClickOpenDialog(type: string, target: string) {
(formGroupTarget.positions = [
{
position: "",
posTypeId: "",
posLevelId: "",
posTypeId: null,
posLevelId: null,
},
]),
(newModalGroupTarget.value = true);
@ -323,8 +323,12 @@ function onSubmitGroup() {
groupTarget: formGroupTarget.groupTarget,
groupTargetSub: formGroupTarget.groupTargetSub,
position: formGroupTarget.position,
posTypeActualId: formGroupTarget.posType,
posLevelActualId: formGroupTarget.posLevel,
posTypeActualId: formGroupTarget.posType
? formGroupTarget.posType
: null,
posLevelActualId: formGroupTarget.posLevel
? formGroupTarget.posLevel
: null,
type: formGroupTarget.type,
amount: formGroupTarget.amount,
}
@ -404,8 +408,8 @@ function cleanFormData() {
formGroupTarget.groupTarget = "";
formGroupTarget.groupTargetSub = "";
formGroupTarget.position = "";
formGroupTarget.posType = "";
formGroupTarget.posLevel = "";
formGroupTarget.posType = null;
formGroupTarget.posLevel = null;
formGroupTarget.type = "";
formGroupTarget.amount = null;
formGroupRelate.relate = "";
@ -556,8 +560,8 @@ onMounted(() => {
{{ `- ${row.position}`
}}{{
row.posType !== null || row.posLevel !== null
? `(${row.posType ? row.posType : ""} ${
row.posLevel ? row.posLevel : ""
? ` (${row.posType ? row.posType : ""}${
row.posLevel ? " " + row.posLevel : ""
})`
: ""
}}
@ -717,8 +721,13 @@ onMounted(() => {
<q-td v-for="col in props.cols" :key="col.name" :props="props">
<div v-if="col.name === 'posTypeActualId'">
<div v-if="props.row.groupTarget !== 'OUTSIDERS'">
{{
`${props.row.position} (${props.row.posType} ${props.row.posLevel})`
{{ `- ${props.row.position}`
}}{{
props.row.posType !== null || props.row.posLevel !== null
? ` (${props.row.posType ? props.row.posType : ""}${
props.row.posLevel ? " " + props.row.posLevel : ""
})`
: ""
}}
</div>
<div v-else>
@ -878,23 +887,6 @@ onMounted(() => {
/>
</div>
<div
class="col-xs-6 col-sm-4 col-md-4"
v-if="formGroupTarget.groupTarget !== 'OUTSIDERS'"
>
<q-input
outlined
dense
hide-bottom-space
class="inputgreen"
v-model="formGroupTarget.position"
label="ตำแหน่ง"
:rules="[
(val:string) =>
!!val || `${'กรุณากรอกตำแหน่ง'}`,
]"
/>
</div>
<div
class="col-xs-6 col-sm-4 col-md-4"
v-if="formGroupTarget.groupTarget !== 'OUTSIDERS'"
@ -913,11 +905,8 @@ onMounted(() => {
map-options
input-class="text-red"
label="ประเภทตำแหน่ง"
clearable
@update:model-value="updatePosTypeName"
:rules="[
(val:string) =>
!!val || `${'กรุณาเลือกประเภทตำแหน่ง'}`,
]"
/>
</div>
<div
@ -941,10 +930,24 @@ onMounted(() => {
map-options
input-class="text-red"
label="ระดับตำแหน่ง"
clearable
/>
</div>
<div
class="col-xs-6 col-sm-4 col-md-4"
v-if="formGroupTarget.groupTarget !== 'OUTSIDERS'"
>
<q-input
outlined
dense
hide-bottom-space
class="inputgreen"
v-model="formGroupTarget.position"
label="ตำแหน่ง"
:rules="[
(val:string) =>
!!val || `${'กรุณาเลือกระดับ'}`,
]"
(val:string) =>
!!val || `${'กรุณากรอกตำแหน่ง'}`,
]"
/>
</div>
<div
@ -1127,6 +1130,7 @@ onMounted(() => {
map-options
input-class="text-red"
label="ประเภทตำแหน่ง"
clearable
@update:model-value="updatePosTypeName"
/>
</div>
@ -1149,6 +1153,7 @@ onMounted(() => {
map-options
input-class="text-red"
label="ระดับตำแหน่ง"
clearable
/>
</div>
<div

View file

@ -33,8 +33,8 @@ interface FormGroupTargetPlannedGoal {
positions: [
{
position: string;
posTypeId: string;
posLevelId: string;
posTypeId: string | null;
posLevelId: string | null;
}
];
plannedGoalPositions?: [