refactor code ===> สมรรถนะ

This commit is contained in:
DESKTOP-1R2VSQH\Lenovo ThinkPad E490 2025-07-15 10:50:51 +07:00
parent a3a318ba2d
commit f52cfd27a7
6 changed files with 328 additions and 213 deletions

View file

@ -9,6 +9,7 @@ import config from "@/app.config";
import { useCounterMixin } from "@/stores/mixin";
import { useKPIDataStore } from "@/modules/01_masterdata/stores/KPIStore";
import { checkPermission } from "@/utils/permissions";
import { updateCurrentPage } from "@/utils/function";
import type {
DataOption,
@ -23,10 +24,32 @@ const $q = useQuasar();
const mixin = useCounterMixin();
const { dialogRemove, messageError, showLoader, hideLoader, success } = mixin;
const total = ref<number>();
const store = useKPIDataStore();
const router = useRouter();
const columns = ref<QTableProps["columns"]>([
{
name: "name",
align: "left",
label: "ชื่อสมรรถนะ",
sortable: true,
field: "name",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
]);
const visibleColumns = ref<string[]>(["name"]);
const rows = ref<ResDataCapacity[]>([]); //
const total = ref<number>(0); //
const totalList = ref<number>(1); //
const formQuery = reactive<FormQueryCapacity>({
page: 1,
pageSize: 10,
keyword: "",
}); // form query
const competencyTypeOp = ref<DataOption[]>([
{
id: "HEAD",
@ -48,31 +71,9 @@ const competencyTypeOp = ref<DataOption[]>([
id: "INSPECTOR",
name: "สมรรถนะเฉพาะสำหรับตำแหน่งผู้ตรวจราชการ กทม. และผู้ตรวจราชการ",
},
]);
const columns = ref<QTableProps["columns"]>([
{
name: "name",
align: "left",
label: "ชื่อสมรรถนะ",
sortable: true,
field: "name",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
]);
const visibleColumns = ref<string[]>(["name"]);
]); //
const rows = ref<ResDataCapacity[]>([]);
const formQuery = reactive<FormQueryCapacity>({
page: 1,
pageSize: 10,
keyword: "",
});
const totalList = ref<number>(1); //
/** ดึงข้อมูล */
/** ฟังก์ชันดึงข้อมูลรายการสมรรถนะ */
async function fetchList() {
showLoader();
await http
@ -96,20 +97,37 @@ async function fetchList() {
});
}
/**
* งกนไปหนาแกไขสมรรถนะ
* @param id รหสสมรรถนะทองการแกไข
*/
async function onViewDetail(id: string) {
router.push(`/masterdata/competency/${id}`);
}
/**
* งกนดรายละเอยดสมรรถนะ
* @param id รหสสมรรถนะทองการดรายละเอยด
*/
async function onViewDetailPage(id: string) {
router.push(`/masterdata/competency-detail/${id}`);
}
/**
* งกนลบขอมลสมรรถนะ
* @param id รหสสมรรถนะทองการลบ
*/
function deleteData(id: string) {
dialogRemove($q, async () => {
showLoader();
await http
.delete(config.API.kpiCapacity + `/${id}`)
.then(async () => {
formQuery.page = await updateCurrentPage(
formQuery.page,
totalList.value,
rows.value.length
);
await fetchList();
success($q, "ลบข้อมูลสำเร็จ");
})

View file

@ -7,18 +7,24 @@ import http from "@/plugins/http";
import config from "@/app.config";
import { checkPermission } from "@/utils/permissions";
import { useCounterMixin } from "@/stores/mixin";
import { updateCurrentPage } from "@/utils/function";
import type { DataKPIGroup } from "@/modules/01_masterdata/interface/response/Main";
import type { NewPagination } from "@/modules/14_KPI/interface/index/Main";
import dialogHeader from "@/components/DialogHeader.vue";
const total = ref<number>();
const modal = ref<boolean>(false);
const rows = ref<any[]>([]);
const groupName = ref<string>("");
const $q = useQuasar();
const mixin = useCounterMixin();
const {
dialogRemove,
dialogConfirm,
showLoader,
hideLoader,
messageError,
success,
} = mixin;
const editStatus = ref<boolean>(false);
const editId = ref<string>("");
const columns = ref<QTableProps["columns"]>([
{
name: "nameGroupKPI",
@ -32,18 +38,6 @@ const columns = ref<QTableProps["columns"]>([
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
]);
const $q = useQuasar();
const mixin = useCounterMixin();
const {
dialogRemove,
dialogConfirm,
showLoader,
hideLoader,
messageError,
success,
} = mixin;
const visibleColumns = ref<string[]>(["nameGroupKPI"]);
const formQuery = reactive({
@ -51,9 +45,15 @@ const formQuery = reactive({
pageSize: 10,
keyword: "",
});
const totalList = ref<number>(1); //
const totalList = ref<number>(1); //
const total = ref<number>(0); //
const modal = ref<boolean>(false); // / dialog
const rows = ref<DataKPIGroup[]>([]); //
const groupName = ref<string>(""); //
const editStatus = ref<boolean>(false); //
const editId = ref<string>(""); //
/** ดึงข้อมูล */
/** ฟังก์ชันดึงข้อมูลกลุ่มงาน */
async function fetchData() {
showLoader();
await http
@ -77,7 +77,7 @@ async function fetchData() {
});
}
/** เพิ่มข้อมูล */
/** ฟังก์ชันบันทึกการเพิ่มข้อมูลกลุ่มงาน */
async function addData() {
showLoader();
await http
@ -96,7 +96,10 @@ async function addData() {
});
}
/** save แก้ไขข้อมูล */
/**
* งกนบนทกการแกไขขอมลกลมงาน
* @param id รหสกลมงานทองการแกไข
*/
async function editData(id: string) {
showLoader();
await http
@ -115,12 +118,20 @@ async function editData(id: string) {
});
}
/** ลบข้อมูล */
/**
* งกนลบขอมลกลมงาน
* @param id รหสกลมงานทองการลบ
*/
async function deleteData(id: string) {
showLoader();
await http
.delete(config.API.kpiGroupById(id))
.then(async () => {
formQuery.page = await updateCurrentPage(
formQuery.page,
totalList.value,
rows.value.length
);
await fetchData();
success($q, "ลบข้อมูลสำเร็จ");
})
@ -132,19 +143,23 @@ async function deleteData(id: string) {
});
}
/** เปลี่ยนเป็นหน้าเพิ่มข้อมูล */
/** ฟังก์ชันเปิด dialog เพิ่มข้อมูล */
function onAdd() {
modal.value = true;
}
/** ฟังก์ชันปิด dialog */
function closeDialog() {
modal.value = false;
editStatus.value = false;
groupName.value = "";
}
/** เปิด dialog แก้ไข */
function onEdit(data: any) {
/**
* งกนเป dialog แกไข
* @param data อมลกลมงานทองการแกไข
*/
function onEdit(data: DataKPIGroup) {
modal.value = true;
editStatus.value = true;
groupName.value = data.nameGroupKPI;
@ -165,18 +180,21 @@ async function onSubmit() {
}
/**
* function updatePagination
* งกนอปเดตขอม Pagination
* @param newPagination อม Pagination ใหม
*/
function updatePagination(newPagination: NewPagination) {
formQuery.page = 1;
formQuery.pageSize = newPagination.rowsPerPage;
}
/** ฟังก์ชันดึงข้อมูลกลุ่มงานใหม่ */
function fetchNewList() {
formQuery.page = 1;
fetchData();
}
/** ฟังก์ชันติดตามการเปลี่ยนแปลงจำนวนแถวต่อหน้า */
watch(
() => formQuery.pageSize,
() => {
@ -184,7 +202,8 @@ watch(
}
);
onMounted(async () => {
/** lifecycle hook */
onMounted(() => {
fetchData();
});
</script>

View file

@ -3,13 +3,12 @@ import { ref, onMounted, reactive, watch } from "vue";
import type { QTableProps } from "quasar";
import { useQuasar } from "quasar";
import { useRoute } from "vue-router";
import http from "@/plugins/http";
import config from "@/app.config";
import { useCounterMixin } from "@/stores/mixin";
import Header from "@/components/DialogHeader.vue";
import { checkPermission } from "@/utils/permissions";
import { updateCurrentPage } from "@/utils/function";
import type {
DataOption,
@ -17,26 +16,47 @@ import type {
ListLinkGroup,
Position,
} from "@/modules/01_masterdata/interface/index/Main";
import type {
DataKPIGroup,
DataKPIPosition,
DataKPICapacity,
} from "@/modules/01_masterdata/interface/response/Main";
import { checkPermission } from "@/utils/permissions";
import Header from "@/components/DialogHeader.vue";
const total = ref<number>();
const id = ref<string>("");
const modal = ref<boolean>(false);
const rows = ref<ListLinkGroup[]>([]);
const editStatus = ref<boolean>(false);
const groupName = ref<Position | null>();
const position = ref<string[]>();
const competency = ref<Position[]>();
const route = useRoute();
const $q = useQuasar();
const mixin = useCounterMixin();
const {
dialogRemove,
messageError,
showLoader,
hideLoader,
success,
dialogConfirm,
} = mixin;
const groupNameOp = ref<DataOption[]>([]);
const groupNameOpMain = ref<DataOption[]>([]);
const positionOp = ref<DataOption[]>([]);
const positionMainOp = ref<DataOption[]>([]);
const competencyOp = ref<DataOption[]>([]);
const competencyOpMain = ref<DataOption[]>([]);
const id = ref<string>(""); //
const modal = ref<boolean>(false); // / dialog
const editStatus = ref<boolean>(false); //
const groupName = ref<Position | null>(); //
const position = ref<string[]>([]); //
const competency = ref<Position[]>([]); //
const groupNameOp = ref<DataOption[]>([]); //
const groupNameOpMain = ref<DataOption[]>([]); //
const positionOp = ref<DataOption[]>([]); //
const positionMainOp = ref<DataOption[]>([]); //
const competencyOp = ref<DataOption[]>([]); //
const competencyOpMain = ref<DataOption[]>([]); //
const formQuery = reactive({
page: 1,
pageSize: 10,
keyword: "",
});
const totalList = ref<number>(1); //
const total = ref<number>(0); //
const rows = ref<ListLinkGroup[]>([]); //
const columns = ref<QTableProps["columns"]>([
{
name: "groupName",
@ -72,28 +92,9 @@ const columns = ref<QTableProps["columns"]>([
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
]);
const $q = useQuasar();
const mixin = useCounterMixin();
const {
dialogRemove,
messageError,
showLoader,
hideLoader,
success,
dialogConfirm,
} = mixin;
const visibleColumns = ref<string[]>(["groupName", "positions", "capacitys"]);
const formQuery = reactive({
page: 1,
pageSize: 10,
keyword: "",
});
const totalList = ref<number>(1); //
/** ดึงข้อมูล */
/** ฟังก์ชันดึงข้อมูลรายการเชื่อมโยงกับกลุ่มงานและตำแหน่ง */
async function getData() {
showLoader();
http
@ -109,19 +110,30 @@ async function getData() {
totalList.value = Math.ceil(res.data.result.total / formQuery.pageSize);
rows.value = data.data;
})
.catch((err) => {
messageError($q, err);
})
.finally(() => {
hideLoader();
});
}
/**
* งกนลบขอมลเชอมโยงกบกลมงานและตำแหน
* @param id รหสรายการขอมลเชอมโยงกบกลมงานและตำแหน
*/
async function deleteData(id: string) {
showLoader();
await http
.delete(config.API.kpiLink + `/${id}`)
.then(async () => {
formQuery.page = await updateCurrentPage(
formQuery.page,
totalList.value,
rows.value.length
);
await getData();
success($q, "ลบข้อมูลสำเร็จ");
close();
})
.catch((err) => {
messageError($q, err);
@ -131,23 +143,22 @@ async function deleteData(id: string) {
});
}
/** ดึงข้อมูล */
/** ฟังก์ชันดึงข้อมูลกลุ่มงาน */
async function getListGroup() {
showLoader();
await http
.get(config.API.kpiGroup + `?pageSize=50`)
.then(async (res) => {
const dataOp = res.data.result.data;
const uniqueNames = new Set();
const filteredData = dataOp
.filter((item: any) => {
.filter((item: DataKPIGroup) => {
if (!uniqueNames.has(item.id)) {
uniqueNames.add(item.nameGroupKPI);
return true;
}
return false;
})
.map((item: any) => ({
.map((item: DataKPIGroup) => ({
id: item.id,
name: item.nameGroupKPI,
}));
@ -156,29 +167,25 @@ async function getListGroup() {
})
.catch((err) => {
messageError($q, err);
})
.finally(() => {
hideLoader();
});
}
/** ดึงข้อมูล */
/** ฟังก์ชันดึงข้อมูลสมรรถนะ */
async function getCompetency() {
showLoader();
await http
.get(config.API.kpiCapacity + `?type=GROUP&pageSize=50`)
.then(async (res) => {
const dataOp = res.data.result.data;
const uniqueNames = new Set();
const filteredData = dataOp
.filter((item: any) => {
.filter((item: DataKPICapacity) => {
if (!uniqueNames.has(item.id)) {
uniqueNames.add(item.name);
return true;
}
return false;
})
.map((item: any) => ({
.map((item: DataKPICapacity) => ({
id: item.id,
name: item.name,
}));
@ -187,33 +194,70 @@ async function getCompetency() {
})
.catch((err) => {
messageError($q, err);
})
.finally(() => {
hideLoader();
});
}
/** เปลี่ยนเป็นหน้าเพิ่มข้อมูล */
function onAdd() {
getOptions();
getListGroup();
getCompetency();
modal.value = true;
/** ฟังก์ชันดึงข้อมูลตำแหน่ง */
async function getOptions() {
await http
.get(config.API.orgSalaryPosition)
.then((res) => {
const dataOp = res.data.result;
const uniqueNames = new Set();
const filteredData = dataOp
.filter((item: DataKPIPosition) => {
if (!uniqueNames.has(item.positionName)) {
uniqueNames.add(item.positionName);
return true;
}
return false;
})
.map((item: DataKPIPosition) => ({
id: item.positionName,
name: item.positionName,
}));
positionMainOp.value = filteredData;
})
.catch((err) => {
messageError($q, err);
});
}
async function onEdit(data: any) {
id.value = data;
await getOptions();
await getListGroup();
await getCompetency();
await getDataEdit(id.value);
modal.value = true;
editStatus.value = true;
}
async function getDataEdit(id: string) {
/** ฟังก์ชันเปิด dialog เพิ่มข้อมูล */
async function onAdd() {
showLoader();
http
try {
modal.value = true;
await Promise.all([getOptions(), getListGroup(), getCompetency()]);
} finally {
hideLoader();
}
}
/**
* งกนเป dialog แกไข
* @param rowId รหสกลมงานทองการแกไข
*/
async function onEdit(rowId: string) {
showLoader();
try {
id.value = rowId;
modal.value = true;
editStatus.value = true;
await Promise.all([getOptions(), getListGroup(), getCompetency()]);
await getDataEdit(id.value);
} finally {
hideLoader();
}
}
/**
* งกนดงขอมลสำหรบแกไข
* @param id รหสกลมงานทองการแกไข
*/
async function getDataEdit(id: string) {
await http
.get(config.API.kpiLink + `/edit/${id}`)
.then((res) => {
const data = res.data.result;
@ -221,17 +265,18 @@ async function getDataEdit(id: string) {
id: data.groupId,
name: data.groupName,
};
position.value = data.positions.map((i: any) => i.name);
competency.value = data.capacitys.map((i: any) => ({
position.value = data.positions.map((i: Position) => i.name);
competency.value = data.capacitys.map((i: DataKPICapacity) => ({
id: i.id,
name: i.name,
}));
})
.finally(() => {
hideLoader();
.catch((err) => {
messageError($q, err);
});
}
/** ฟังก์ชันบันทึกข้อมูล */
function onSubmit() {
const url = editStatus.value
? config.API.kpiLink + `/${id.value}`
@ -239,7 +284,7 @@ function onSubmit() {
const body = {
kpiGroupId: groupName.value?.id,
positions: position.value,
kpiCapacityIds: competency.value?.map((i: any) => i.id),
kpiCapacityIds: competency.value?.map((i: Position) => i.id),
};
dialogConfirm($q, async () => {
showLoader();
@ -267,82 +312,56 @@ function close() {
competency.value = [];
}
async function getOptions() {
http.get(config.API.orgSalaryPosition).then((res) => {
const dataOp = res.data.result;
const uniqueNames = new Set();
const filteredData = dataOp
.filter((item: any) => {
if (!uniqueNames.has(item.positionName)) {
uniqueNames.add(item.positionName);
return true;
}
return false;
})
.map((item: any) => ({
id: item.positionName,
name: item.positionName,
}));
positionMainOp.value = filteredData;
});
}
/**
* function นหาขอมลของ Option
* งกนคนหาขอมลของ Option
* @param val าทองการฟลเตอร
* @param update พเดทค
* @param refData ดาตองการฟลเตอร
* @param type ประเภทของ Option องการฟลเตอร
*/
function filterOptionGroup(val: any, update: Function) {
update(() => {
groupNameOp.value = groupNameOpMain.value.filter(
(v: any) => v.name.indexOf(val) > -1
);
});
function filterOptionSelect(val: string, update: Function, type: string) {
switch (type) {
case "group":
update(() => {
groupNameOp.value = groupNameOpMain.value.filter(
(v: DataOption) => v.name.indexOf(val) > -1
);
});
break;
case "position":
update(() => {
positionOp.value = positionMainOp.value.filter(
(v: DataOption) => v.name.indexOf(val) > -1
);
});
break;
case "competency":
update(() => {
competencyOp.value = competencyOpMain.value.filter(
(v: DataOption) => v.name.indexOf(val) > -1
);
});
default:
break;
}
}
/**
* function นหาขอมลของ Option
* @param val าทองการฟลเตอร
* @param update พเดทค
* @param refData ดาตาทองการฟลเตอร
*/
function filterOption(val: any, update: Function) {
update(() => {
positionOp.value = positionMainOp.value.filter(
(v: any) => v.name.indexOf(val) > -1
);
});
}
/**
* function นหาขอมลของ Option
* @param val าทองการฟลเตอร
* @param update พเดทค
* @param refData ดาตาทองการฟลเตอร
*/
function filterOptionCompetency(val: any, update: Function) {
update(() => {
competencyOp.value = competencyOpMain.value.filter(
(v: any) => v.name.indexOf(val) > -1
);
});
}
/**
* function updatePagination
* งกนอปเดต Pagination
* @param newPagination อม Pagination ใหม
*/
function updatePagination(newPagination: NewPagination) {
formQuery.page = 1;
formQuery.pageSize = newPagination.rowsPerPage;
}
/** ฟังก์ชันดึงข้อมูลใหม่ */
function fetchNewList() {
formQuery.page = 1;
getData();
}
/** ฟังก์ชันติดตามการเปลี่ยนแปลงจำนวนแถวต่อหน้า */
watch(
() => formQuery.pageSize,
() => {
@ -350,7 +369,8 @@ watch(
}
);
onMounted(async () => {
/** lifecycle hook */
onMounted(() => {
getData();
});
</script>
@ -376,8 +396,7 @@ onMounted(async () => {
label="ค้นหา"
@keyup.enter="fetchNewList()"
>
<template v-slot:append>
<q-icon name="search" /> </template
<template v-slot:append> <q-icon name="search" /> </template
></q-input>
<q-select
v-model="visibleColumns"
@ -407,7 +426,7 @@ onMounted(async () => {
class="custom-header-table"
:visible-columns="visibleColumns"
:separator="'cell'"
:rows-per-page-options="[10, 25, 50, 100]"
:rows-per-page-options="[1, 10, 25, 50, 100]"
@update:pagination="updatePagination"
>
<template v-slot:header="props">
@ -518,7 +537,7 @@ onMounted(async () => {
use-input
hide-selected
fill-input
@filter="(inputValue:any,doneFn:Function) => filterOptionGroup(inputValue, doneFn) "
@filter="(inputValue:string,doneFn:Function) => filterOptionSelect(inputValue, doneFn,'group') "
hide-bottom-space
lazy-rules
:rules="[(val:string) => !!val || `${'กรุณาเลือกกลุ่มงาน'}`,]"
@ -549,7 +568,7 @@ onMounted(async () => {
hide-bottom-space
lazy-rules
use-input
@filter="(inputValue:any,doneFn:Function) => filterOption(inputValue, doneFn) "
@filter="(inputValue:string,doneFn:Function) => filterOptionSelect(inputValue, doneFn,'position') "
>
<template v-slot:no-option>
<q-item>
@ -576,7 +595,7 @@ onMounted(async () => {
lazy-rules
:options="competencyOp"
use-input
@filter="(inputValue:any,doneFn:Function) => filterOptionCompetency(inputValue, doneFn) "
@filter="(inputValue:string,doneFn:Function) => filterOptionSelect(inputValue, doneFn,'competency') "
>
<template v-slot:no-option>
<q-item>

View file

@ -1,5 +1,5 @@
<script setup lang="ts">
import { ref, reactive, onMounted, watch } from "vue";
import { ref, onMounted } from "vue";
import { useCounterMixin } from "@/stores/mixin";
import http from "@/plugins/http";
@ -9,12 +9,14 @@ import { useQuasar } from "quasar";
import { checkPermission } from "@/utils/permissions";
import { useRoute } from "vue-router";
import type { DataKPIEvaluation } from "@/modules/01_masterdata/interface/response/Main";
const $q = useQuasar();
const route = useRoute();
const { showLoader, hideLoader, success, dialogConfirm, messageError } =
useCounterMixin();
const dataLevel = ref<any>();
const dataLevel = ref<DataKPIEvaluation[]>([]);
const fieldLabels = {
score5: "5",
score4: "4",
@ -23,11 +25,28 @@ const fieldLabels = {
score1: "1",
};
/** ฟังก์ชันดึงข้อมูลเกณฑ์การประเมิน */
async function getData() {
showLoader();
await http
.get(config.API.kpiEvaluation + `/edit`)
.then((res) => {
dataLevel.value = res.data.result.data;
})
.catch((err) => {
messageError($q, err);
})
.finally(() => {
hideLoader();
});
}
/** ฟังก์ชันบันทึกข้อมูลเกณฑ์การประเมิน */
function onSubmit() {
dialogConfirm($q, async () => {
showLoader();
const body = {
formScore: dataLevel.value.map((item: any) => {
formScore: dataLevel.value.map((item: DataKPIEvaluation) => {
const { level, ...rest } = item;
return rest;
}),
@ -48,20 +67,6 @@ function onSubmit() {
});
}
async function getData() {
showLoader();
http
.get(config.API.kpiEvaluation + `/edit`)
.then((res) => {
dataLevel.value = res.data.result.data;
})
.catch((err) => {
messageError($q, err);
})
.finally(() => {
hideLoader();
});
}
onMounted(() => {
if (checkPermission(route)?.attrIsList) getData();
});

View file

@ -73,6 +73,7 @@ function onClickAddLevels() {
/** บันทึกข้อมูล */
function onSubmit() {
dialogConfirm($q, async () => {
showLoader();
const formBody = {
type: store.competencyTypeVal,
name: formData.competencyName,

View file

@ -58,4 +58,57 @@ interface ResAssignment {
};
}
export type { ResRound, ResDataCapacity, ResEvaluator, ResAssignment };
interface DataKPIGroup {
createdAt: string;
createdFullName: string;
createdUserId: string;
id: string;
lastUpdateFullName: string;
lastUpdateUserId: string;
lastUpdatedAt: string;
nameGroupKPI: string;
}
interface DataKPIPosition {
createdAt: string;
id: string;
isSpecial: boolean;
lastUpdateFullName: string;
lastUpdatedAt: string;
posExecutiveId: string;
posExecutiveName: string;
posLevelId: string;
posLevelName: string;
posTypeId: string;
posTypeName: string;
positionArea: string;
positionExecutiveField: string;
positionField: string;
positionIsSelected: boolean;
positionName: string;
}
interface DataKPICapacity {
capacityDetails: capacityDetails[];
description: string;
id: string;
name: string;
type: string;
}
interface DataKPIEvaluation {
description: string;
id: string;
level: number;
}
export type {
ResRound,
ResDataCapacity,
ResEvaluator,
ResAssignment,
DataKPIGroup,
DataKPIPosition,
DataKPICapacity,
DataKPIEvaluation
};