Compare commits
110 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
20f75d24b0 | ||
|
|
50fdb30920 | ||
|
|
ae8e667922 | ||
|
|
5ead16e528 | ||
|
|
9cbe56fb1e | ||
|
|
95f37cf68d | ||
|
|
bee7aa54f0 | ||
|
|
762ed36190 | ||
|
|
e14ba58df0 | ||
|
|
8d83bd2b1e | ||
|
|
9228132052 | ||
|
|
8f7a5c058b | ||
|
|
94d80409c3 | ||
|
|
eed4258617 | ||
|
|
b1a7983b00 | ||
|
|
1b2636cea2 | ||
|
|
3c91c0db16 | ||
|
|
dd875380df | ||
|
|
8dc473eec0 | ||
|
|
852f3226c1 | ||
|
|
4c7ab0f7e6 | ||
|
|
e998de2b95 | ||
|
|
084cf7bcfa | ||
|
|
ba392dec41 | ||
|
|
735617b541 | ||
|
|
b22ae37eec | ||
|
|
cf58e28a11 | ||
|
|
3cc8d9e974 | ||
|
|
0739f2b9d7 | ||
|
|
7848323b1f | ||
|
|
29b45f77ea | ||
|
|
5ac50fc1f2 | ||
|
|
a262319c20 | ||
|
|
ebdea05f4d | ||
|
|
22a9f0f935 | ||
|
|
e513586b65 | ||
|
|
46285f5d18 | ||
|
|
999a2d1b45 | ||
|
|
26f5d286d1 | ||
|
|
a7341c7440 | ||
|
|
0d1dea5289 | ||
|
|
7bbd9ae933 | ||
|
|
55d3897b2d | ||
|
|
44487139ea | ||
|
|
5ef1059659 | ||
|
|
c69c4c1fa8 | ||
|
|
dc71d0bb59 | ||
|
|
05afc1fe5b | ||
| de95ae61c0 | |||
|
|
4827823e82 | ||
|
|
c20e67d1a1 | ||
|
|
a71cdec921 | ||
|
|
598492b61e | ||
|
|
aad1009c0a | ||
|
|
9e550fc5bf | ||
|
|
6f798eed20 | ||
|
|
ebf34aa0c2 | ||
|
|
9cae94ae75 | ||
|
|
bad9bd3adf | ||
|
|
16707fee64 | ||
|
|
1f0ec397ff | ||
|
|
2a49e67022 | ||
|
|
df5268705c | ||
|
|
7c7f344a4a | ||
|
|
69859517fb | ||
|
|
8d5384c1d3 | ||
| 4486a32fd8 | |||
| fce944d90f | |||
| 83b6d723ba | |||
| 5b71a6a37b | |||
|
|
130adabc27 | ||
|
|
8a1fb4f9ed | ||
| e1bfc1b3bf | |||
| e1db58294b | |||
| bf5979aa2d | |||
| 41a9f9cb89 | |||
|
|
c3dc4ce774 | ||
|
|
52f4db00a9 | ||
|
|
9463d8c9f9 | ||
|
|
7211081d14 | ||
|
|
bfe71c1a23 | ||
|
|
9132efed11 | ||
|
|
69f9657719 | ||
|
|
433a0ce9b8 | ||
|
|
230dba078c | ||
|
|
874bedf7eb | ||
|
|
d296b2e4ac | ||
|
|
24d08ac0cf | ||
|
|
88667b8ea8 | ||
|
|
cf053cb306 | ||
| 5bf1f2f197 | |||
|
|
c6bb8fffe2 | ||
|
|
34cf21da65 | ||
|
|
1de3d35752 | ||
| ac7da9c363 | |||
| 5193720567 | |||
| f7412ca1a8 | |||
| 0ccda33b37 | |||
| cba8f4b703 | |||
|
|
926c47f273 | ||
|
|
d6e75d6966 | ||
|
|
170568384d | ||
|
|
7f25ed4ef1 | ||
|
|
8a0a6ea873 | ||
| 833718d276 | |||
| 73335d7dd5 | |||
|
|
07659ecc6c | ||
|
|
9d9cd92d6b | ||
|
|
40ebaa646f | ||
|
|
c700cf0abd |
73 changed files with 1644 additions and 528 deletions
|
|
@ -30,6 +30,7 @@
|
||||||
"axios": "^1.6.7",
|
"axios": "^1.6.7",
|
||||||
"bma-org-chart": "^0.0.8",
|
"bma-org-chart": "^0.0.8",
|
||||||
"esri-loader": "^3.7.0",
|
"esri-loader": "^3.7.0",
|
||||||
|
"exceljs": "^4.4.0",
|
||||||
"html-to-image": "^1.11.13",
|
"html-to-image": "^1.11.13",
|
||||||
"keycloak-js": "^20.0.2",
|
"keycloak-js": "^20.0.2",
|
||||||
"moment": "^2.29.4",
|
"moment": "^2.29.4",
|
||||||
|
|
|
||||||
|
|
@ -192,6 +192,8 @@ export default {
|
||||||
`${orgProfile}/keycloak/permissionProfile/${rootId}`,
|
`${orgProfile}/keycloak/permissionProfile/${rootId}`,
|
||||||
profileidPosition: (type: string) =>
|
profileidPosition: (type: string) =>
|
||||||
`${orgProfile}${type}/profileid/position`,
|
`${orgProfile}${type}/profileid/position`,
|
||||||
|
uploadProfile: (type: string, id: string) =>
|
||||||
|
`${organization}/upload/${type}-profileSalaryTemp/${id}`,
|
||||||
|
|
||||||
workflowCommanderOperate: `${workflow}/commander/operate`,
|
workflowCommanderOperate: `${workflow}/commander/operate`,
|
||||||
workflowCommanderSign: `${workflow}/commander/sign`,
|
workflowCommanderSign: `${workflow}/commander/sign`,
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ export default {
|
||||||
placementDefermentInfo: (id: string) => `${placement}/pass/deferment/${id}`,
|
placementDefermentInfo: (id: string) => `${placement}/pass/deferment/${id}`,
|
||||||
placementDisclaimInfo: (id: string) => `${placement}/pass/disclaim/${id}`,
|
placementDisclaimInfo: (id: string) => `${placement}/pass/disclaim/${id}`,
|
||||||
placementUpdatePass: `${placement}/pass/update-status`,
|
placementUpdatePass: `${placement}/pass/update-status`,
|
||||||
|
placementUpdateDraftStatus: `${placement}/update/draft-status`,
|
||||||
|
|
||||||
//personal
|
//personal
|
||||||
placementPersonalId: (personalId: string) =>
|
placementPersonalId: (personalId: string) =>
|
||||||
|
|
|
||||||
|
|
@ -96,4 +96,8 @@ export default {
|
||||||
|
|
||||||
applicationFormPDF: (candidateId: string) =>
|
applicationFormPDF: (candidateId: string) =>
|
||||||
`${env.API_URI}/placement/candidate/pdf/${candidateId}`,
|
`${env.API_URI}/placement/candidate/pdf/${candidateId}`,
|
||||||
|
|
||||||
|
downloadCandidateExam: (id: string) =>
|
||||||
|
`${periodExam}download/candidate-exam/${id}`,
|
||||||
|
downloadPassExam: (id: string) => `${periodExam}download/pass-exam/${id}`,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -43,9 +43,9 @@ async function fetchDataProfile(data: DataProfile) {
|
||||||
profile.avatar = data?.avatar ? data.avatar : "";
|
profile.avatar = data?.avatar ? data.avatar : "";
|
||||||
}
|
}
|
||||||
profile.id = data.profileId;
|
profile.id = data.profileId;
|
||||||
profile.fullName = `${data.prefix ?? ""}${data.firstName ?? ""} ${
|
profile.fullName = `${data.rank ? data.rank : data.prefix ?? ""}${
|
||||||
data.lastName ?? ""
|
data.firstName ?? ""
|
||||||
} `;
|
} ${data.lastName ?? ""} `;
|
||||||
|
|
||||||
if (data["posTypeNameOld"] !== undefined) {
|
if (data["posTypeNameOld"] !== undefined) {
|
||||||
profile.position =
|
profile.position =
|
||||||
|
|
|
||||||
|
|
@ -332,6 +332,7 @@ watch(
|
||||||
outlined
|
outlined
|
||||||
dense
|
dense
|
||||||
label="คำค้น"
|
label="คำค้น"
|
||||||
|
@keydown.enter.prevent="searchInput()"
|
||||||
>
|
>
|
||||||
<template v-slot:after>
|
<template v-slot:after>
|
||||||
<q-btn
|
<q-btn
|
||||||
|
|
|
||||||
|
|
@ -354,6 +354,11 @@ function onClose() {
|
||||||
|
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<div class="row col-12 q-col-gutter-sm">
|
<div class="row col-12 q-col-gutter-sm">
|
||||||
|
<div class="col-12">
|
||||||
|
<div class="text-caption text-grey-8">
|
||||||
|
ผู้ดูแลระบบจะติดต่อกลับผ่านทางอีเมลที่ท่านระบุ กรุณาตรวจสอบอีเมลของท่านเป็นระยะ
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="col-xs-12 col-md-6 col-lg-6">
|
<div class="col-xs-12 col-md-6 col-lg-6">
|
||||||
<q-input
|
<q-input
|
||||||
dense
|
dense
|
||||||
|
|
@ -363,10 +368,11 @@ function onClose() {
|
||||||
class="inputgreen"
|
class="inputgreen"
|
||||||
hide-bottom-space
|
hide-bottom-space
|
||||||
:rules="[
|
:rules="[
|
||||||
() =>
|
(val: string) => !!val || 'กรุณากรอกที่อยู่อีเมล',
|
||||||
!!formData.email ||
|
(val: string) => {
|
||||||
!!formData.phone ||
|
const emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||||||
'กรุณากรอกอีเมลหรือเบอร์โทรติดต่อกลับ',
|
return emailPattern.test(val) || 'กรุณากรอกที่อยู่อีเมลในรูปแบบที่ถูกต้อง';
|
||||||
|
}
|
||||||
]"
|
]"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -378,12 +384,6 @@ function onClose() {
|
||||||
v-model="formData.phone"
|
v-model="formData.phone"
|
||||||
class="inputgreen"
|
class="inputgreen"
|
||||||
hide-bottom-space
|
hide-bottom-space
|
||||||
:rules="[
|
|
||||||
() =>
|
|
||||||
!!formData.email ||
|
|
||||||
!!formData.phone ||
|
|
||||||
'กรุณากรอกอีเมลหรือเบอร์โทรติดต่อกลับ',
|
|
||||||
]"
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -24,14 +24,14 @@ import DialogHeader from "@/components/DialogHeader.vue";
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
dataRows: {
|
dataRows: {
|
||||||
type: Object,
|
type: Object,
|
||||||
require: true,
|
default: () => ({}),
|
||||||
},
|
},
|
||||||
onSubmit: Function,
|
onSubmit: Function,
|
||||||
});
|
});
|
||||||
const $q = useQuasar();
|
const $q = useQuasar();
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const storeTree = useStructureTree();
|
const storeTree = useStructureTree();
|
||||||
const { fetchStructureTree } = useStructureTree();
|
const { fetchStructureTree } = storeTree;
|
||||||
const mixin = useCounterMixin();
|
const mixin = useCounterMixin();
|
||||||
const {
|
const {
|
||||||
dialogConfirm,
|
dialogConfirm,
|
||||||
|
|
@ -47,10 +47,10 @@ const {
|
||||||
/** props*/
|
/** props*/
|
||||||
const modal = defineModel<boolean>("modal", { required: true });
|
const modal = defineModel<boolean>("modal", { required: true });
|
||||||
const title = defineModel<string>("title", { required: true });
|
const title = defineModel<string>("title", { required: true });
|
||||||
const type = defineModel<any>("type", { required: true });
|
const type = defineModel<string | null>("type", { required: true });
|
||||||
const posType = defineModel<any>("posType", { required: true });
|
const posType = defineModel<string | null>("posType", { required: true });
|
||||||
const posLevel = defineModel<any>("posLevel", { required: true });
|
const posLevel = defineModel<string | null>("posLevel", { required: true });
|
||||||
const position = defineModel<any>("position", { required: true });
|
const position = defineModel<string | null>("position", { required: true });
|
||||||
|
|
||||||
// const routeName = ref<string>(route?.name);
|
// const routeName = ref<string>(route?.name);
|
||||||
const orgRevisionId = ref<string>("");
|
const orgRevisionId = ref<string>("");
|
||||||
|
|
@ -64,7 +64,7 @@ const itemTaps = ref<string[]>();
|
||||||
const filters = ref<string>("");
|
const filters = ref<string>("");
|
||||||
const positionId = ref<string>("");
|
const positionId = ref<string>("");
|
||||||
const selectedPos = ref<any[]>([]);
|
const selectedPos = ref<any[]>([]);
|
||||||
const seletcId = ref<string>("");
|
const selectId = ref<string>("");
|
||||||
const datePos = ref<Date>(new Date());
|
const datePos = ref<Date>(new Date());
|
||||||
const rowsPosition = ref<Positions[]>([]);
|
const rowsPosition = ref<Positions[]>([]);
|
||||||
const positionData = ref<any[]>([]);
|
const positionData = ref<any[]>([]);
|
||||||
|
|
@ -79,7 +79,6 @@ const formActive = reactive<FormActive>({
|
||||||
});
|
});
|
||||||
/** node */
|
/** node */
|
||||||
const nodes = ref<Array<OrgTree>>([]);
|
const nodes = ref<Array<OrgTree>>([]);
|
||||||
const lazy = ref(nodes);
|
|
||||||
const expanded = ref<string[]>([]);
|
const expanded = ref<string[]>([]);
|
||||||
const nodeLevel = ref<number>(0);
|
const nodeLevel = ref<number>(0);
|
||||||
const nodeId = ref<string>(""); // id ของ Tree
|
const nodeId = ref<string>(""); // id ของ Tree
|
||||||
|
|
@ -150,7 +149,7 @@ const columns = ref<QTableProps["columns"]>([
|
||||||
style: "font-size: 14px",
|
style: "font-size: 14px",
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
const columnsPostition = ref<QTableProps["columns"]>([
|
const columnsPosition = ref<QTableProps["columns"]>([
|
||||||
{
|
{
|
||||||
name: "no",
|
name: "no",
|
||||||
align: "left",
|
align: "left",
|
||||||
|
|
@ -181,7 +180,7 @@ const columnsPostition = ref<QTableProps["columns"]>([
|
||||||
{
|
{
|
||||||
name: "posTypeName",
|
name: "posTypeName",
|
||||||
align: "left",
|
align: "left",
|
||||||
label: "ประเภทตำเเหน่ง",
|
label: "ประเภทตำแหน่ง",
|
||||||
sortable: true,
|
sortable: true,
|
||||||
field: "posTypeName",
|
field: "posTypeName",
|
||||||
headerStyle: "font-size: 14px",
|
headerStyle: "font-size: 14px",
|
||||||
|
|
@ -244,10 +243,16 @@ function close() {
|
||||||
expanded.value = [];
|
expanded.value = [];
|
||||||
nodeLevel.value = 0;
|
nodeLevel.value = 0;
|
||||||
nodeId.value = "";
|
nodeId.value = "";
|
||||||
|
positionData.value = [];
|
||||||
|
positionNo.value = [];
|
||||||
|
rowData.value = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getDataTable(id: string, level: number = 0) {
|
async function getDataTable(id: string, level: number = 0) {
|
||||||
showLoader();
|
showLoader();
|
||||||
|
positionData.value = [];
|
||||||
|
positionNo.value = [];
|
||||||
|
rowData.value = [];
|
||||||
const body = {
|
const body = {
|
||||||
node: level,
|
node: level,
|
||||||
nodeId: id,
|
nodeId: id,
|
||||||
|
|
@ -261,7 +266,7 @@ async function getDataTable(id: string, level: number = 0) {
|
||||||
|
|
||||||
await http
|
await http
|
||||||
.post(config.API.orgPosPlacement, body)
|
.post(config.API.orgPosPlacement, body)
|
||||||
.then((res) => {
|
.then(async (res) => {
|
||||||
const dataMain: PositionMain[] = [];
|
const dataMain: PositionMain[] = [];
|
||||||
posMasterMain.value = res.data.result.data;
|
posMasterMain.value = res.data.result.data;
|
||||||
|
|
||||||
|
|
@ -299,7 +304,6 @@ async function getDataTable(id: string, level: number = 0) {
|
||||||
|
|
||||||
positionNo.value = listPosNo;
|
positionNo.value = listPosNo;
|
||||||
rowData.value = listPosNo;
|
rowData.value = listPosNo;
|
||||||
// positionData.value = listPosNo;
|
|
||||||
|
|
||||||
if (props.dataRows?.posmasterId) {
|
if (props.dataRows?.posmasterId) {
|
||||||
const newUse = positionUse.value.filter(
|
const newUse = positionUse.value.filter(
|
||||||
|
|
@ -313,14 +317,13 @@ async function getDataTable(id: string, level: number = 0) {
|
||||||
(e: any) => !positionUse.value.includes(e.id)
|
(e: any) => !positionUse.value.includes(e.id)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
await onClickSelectPos(positionId.value);
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
messageError($q, err);
|
messageError($q, err);
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
setTimeout(() => {
|
hideLoader();
|
||||||
hideLoader();
|
|
||||||
}, 1000);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -331,11 +334,11 @@ async function getDataTable(id: string, level: number = 0) {
|
||||||
function updateSelected(data: DataTree) {
|
function updateSelected(data: DataTree) {
|
||||||
if (props?.dataRows?.nodeId === data.orgTreeId) {
|
if (props?.dataRows?.nodeId === data.orgTreeId) {
|
||||||
positionId.value = props?.dataRows?.posmasterId;
|
positionId.value = props?.dataRows?.posmasterId;
|
||||||
seletcId.value = props?.dataRows?.positionId;
|
selectId.value = props?.dataRows?.positionId;
|
||||||
datePos.value = props?.dataRows?.reportingDate;
|
datePos.value = props?.dataRows?.reportingDate;
|
||||||
} else {
|
} else {
|
||||||
positionId.value = "";
|
positionId.value = "";
|
||||||
seletcId.value = "";
|
selectId.value = "";
|
||||||
selectedPos.value = [];
|
selectedPos.value = [];
|
||||||
datePos.value = new Date();
|
datePos.value = new Date();
|
||||||
}
|
}
|
||||||
|
|
@ -382,9 +385,9 @@ async function onClickSelectPos(id: string) {
|
||||||
// หาตำแหน่ง
|
// หาตำแหน่ง
|
||||||
if (position) {
|
if (position) {
|
||||||
rowsPosition.value = position.positions;
|
rowsPosition.value = position.positions;
|
||||||
if (seletcId.value) {
|
if (selectId.value) {
|
||||||
selectedPos.value = rowsPosition.value.filter(
|
selectedPos.value = rowsPosition.value.filter(
|
||||||
(e) => e.id === seletcId.value
|
(e) => e.id === selectId.value
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -403,18 +406,19 @@ async function fetchPosFind(level: number, id: string) {
|
||||||
};
|
};
|
||||||
await http
|
await http
|
||||||
.post(config.API.orgPosFind, body)
|
.post(config.API.orgPosFind, body)
|
||||||
.then((res) => {
|
.then(async (res) => {
|
||||||
const data = res.data.result;
|
const data = res.data.result;
|
||||||
expanded.value = data;
|
expanded.value = data;
|
||||||
nodeId.value = id;
|
nodeId.value = id;
|
||||||
positionId.value = props?.dataRows?.posmasterId;
|
positionId.value = props?.dataRows?.posmasterId;
|
||||||
seletcId.value = props?.dataRows?.positionId;
|
selectId.value = props?.dataRows?.positionId;
|
||||||
datePos.value = props?.dataRows?.reportingDate;
|
datePos.value = props?.dataRows?.reportingDate;
|
||||||
|
await getDataTable(nodeId.value, level);
|
||||||
getDataTable(nodeId.value, level);
|
|
||||||
})
|
})
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
messageError($q, e);
|
messageError($q, e);
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
hideLoader();
|
hideLoader();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -427,11 +431,6 @@ watch(
|
||||||
|
|
||||||
if (props?.dataRows?.node !== null && props?.dataRows?.nodeId !== null) {
|
if (props?.dataRows?.node !== null && props?.dataRows?.nodeId !== null) {
|
||||||
await fetchPosFind(props?.dataRows?.node, props?.dataRows?.nodeId);
|
await fetchPosFind(props?.dataRows?.node, props?.dataRows?.nodeId);
|
||||||
if (positionId.value) {
|
|
||||||
setTimeout(async () => {
|
|
||||||
await onClickSelectPos(positionId.value);
|
|
||||||
}, 200);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
expanded.value = [];
|
expanded.value = [];
|
||||||
}
|
}
|
||||||
|
|
@ -463,19 +462,15 @@ function fetchPositionUes() {
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => isAll.value,
|
() => isAll.value,
|
||||||
(value, oldVal) => {
|
() => {
|
||||||
if (value !== oldVal) {
|
getDataTable(nodeId.value, nodeLevel.value);
|
||||||
getDataTable(nodeId.value, nodeLevel.value);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => isBlank.value,
|
() => isBlank.value,
|
||||||
(value, oldVal) => {
|
() => {
|
||||||
if (value !== oldVal) {
|
getDataTable(nodeId.value, nodeLevel.value);
|
||||||
getDataTable(nodeId.value, nodeLevel.value);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -491,35 +486,42 @@ function onSubmit() {
|
||||||
const dataPosMaster = posMasterMain.value?.find(
|
const dataPosMaster = posMasterMain.value?.find(
|
||||||
(e: any) => e.id === positionId.value
|
(e: any) => e.id === positionId.value
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (!dataPosMaster) {
|
||||||
|
dialogMessageNotify($q, "ไม่พบข้อมูลตำแหน่ง");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (selectedPos.value.length === 0) {
|
if (selectedPos.value.length === 0) {
|
||||||
dialogMessageNotify($q, "กรุณาเลือกตำแหน่ง");
|
dialogMessageNotify($q, "กรุณาเลือกตำแหน่ง");
|
||||||
} else {
|
return;
|
||||||
dialogConfirm($q, async () => {
|
|
||||||
const body = {
|
|
||||||
personalId: props?.dataRows?.id,
|
|
||||||
node: dataPosMaster.node,
|
|
||||||
nodeId: dataPosMaster.nodeId,
|
|
||||||
orgRevisionId: formActive.activeId,
|
|
||||||
positionId: selectedPos.value[0].id,
|
|
||||||
posMasterNo: dataPosMaster.posMasterNo, //ตำแหน่งเลขที่(เลขอย่่างเดียว)
|
|
||||||
positionName: selectedPos.value[0].positionName, //ชื่อตำแหน่ง
|
|
||||||
positionField: selectedPos.value[0].positionField, //ชื่อตำแหน่ง
|
|
||||||
posTypeId: selectedPos.value[0].posTypeId, //ชื่อตำแหน่ง
|
|
||||||
posTypeName: selectedPos.value[0].posTypeName, //ชื่อตำแหน่ง
|
|
||||||
posLevelId: selectedPos.value[0].posLevelId, //ชื่อตำแหน่ง
|
|
||||||
posLevelName: selectedPos.value[0].posLevelName, //ชื่อตำแหน่ง
|
|
||||||
posExecutiveName: selectedPos.value[0].posExecutiveName, //ชื่อตำแหน่ง
|
|
||||||
reportingDate: convertDateToAPI(datePos.value),
|
|
||||||
posmasterId: dataPosMaster.id,
|
|
||||||
typeCommand: type.value,
|
|
||||||
positionExecutiveField: selectedPos.value[0].positionExecutiveField, //ด้านทางการบริหาร
|
|
||||||
positionArea: selectedPos.value[0].positionArea, //ด้าน/สาขา
|
|
||||||
};
|
|
||||||
|
|
||||||
await props.onSubmit?.(body);
|
|
||||||
close();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dialogConfirm($q, async () => {
|
||||||
|
const body = {
|
||||||
|
personalId: props?.dataRows?.id,
|
||||||
|
node: dataPosMaster.node,
|
||||||
|
nodeId: dataPosMaster.nodeId,
|
||||||
|
orgRevisionId: formActive.activeId,
|
||||||
|
positionId: selectedPos.value[0].id,
|
||||||
|
posMasterNo: dataPosMaster.posMasterNo, //ตำแหน่งเลขที่(เลขอย่่างเดียว)
|
||||||
|
positionName: selectedPos.value[0].positionName, //ชื่อตำแหน่ง
|
||||||
|
positionField: selectedPos.value[0].positionField, //ชื่อตำแหน่ง
|
||||||
|
posTypeId: selectedPos.value[0].posTypeId, //ชื่อตำแหน่ง
|
||||||
|
posTypeName: selectedPos.value[0].posTypeName, //ชื่อตำแหน่ง
|
||||||
|
posLevelId: selectedPos.value[0].posLevelId, //ชื่อตำแหน่ง
|
||||||
|
posLevelName: selectedPos.value[0].posLevelName, //ชื่อตำแหน่ง
|
||||||
|
posExecutiveName: selectedPos.value[0].posExecutiveName, //ชื่อตำแหน่ง
|
||||||
|
reportingDate: convertDateToAPI(datePos.value),
|
||||||
|
posmasterId: dataPosMaster.id,
|
||||||
|
typeCommand: type.value,
|
||||||
|
positionExecutiveField: selectedPos.value[0].positionExecutiveField, //ด้านทางการบริหาร
|
||||||
|
positionArea: selectedPos.value[0].positionArea, //ด้าน/สาขา
|
||||||
|
};
|
||||||
|
|
||||||
|
await props.onSubmit?.(body);
|
||||||
|
close();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function onSearch() {
|
function onSearch() {
|
||||||
|
|
@ -534,6 +536,7 @@ onMounted(async () => {
|
||||||
await fetchTree();
|
await fetchTree();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<q-dialog v-model="modal" persistent full-width>
|
<q-dialog v-model="modal" persistent full-width>
|
||||||
<q-card class="no-scroll">
|
<q-card class="no-scroll">
|
||||||
|
|
@ -565,7 +568,7 @@ onMounted(async () => {
|
||||||
<q-tree
|
<q-tree
|
||||||
class="q-pa-sm q-gutter-sm"
|
class="q-pa-sm q-gutter-sm"
|
||||||
dense
|
dense
|
||||||
:nodes="lazy"
|
:nodes="nodes"
|
||||||
node-key="orgTreeId"
|
node-key="orgTreeId"
|
||||||
label-key="labelName"
|
label-key="labelName"
|
||||||
:filter="filter"
|
:filter="filter"
|
||||||
|
|
@ -831,7 +834,7 @@ onMounted(async () => {
|
||||||
</q-toolbar>
|
</q-toolbar>
|
||||||
<d-table
|
<d-table
|
||||||
ref="table"
|
ref="table"
|
||||||
:columns="columnsPostition"
|
:columns="columnsPosition"
|
||||||
:rows="rowsPosition"
|
:rows="rowsPosition"
|
||||||
row-key="id"
|
row-key="id"
|
||||||
flat
|
flat
|
||||||
|
|
@ -929,6 +932,7 @@ onMounted(async () => {
|
||||||
</q-card>
|
</q-card>
|
||||||
</q-dialog>
|
</q-dialog>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.my-list-link {
|
.my-list-link {
|
||||||
color: rgb(118, 168, 222);
|
color: rgb(118, 168, 222);
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,6 @@ import { useQuasar } from "quasar";
|
||||||
import { useCounterMixin } from "@/stores/mixin";
|
import { useCounterMixin } from "@/stores/mixin";
|
||||||
import http from "@/plugins/http";
|
import http from "@/plugins/http";
|
||||||
import config from "@/app.config";
|
import config from "@/app.config";
|
||||||
import { getColumnLabel } from "@/utils/function";
|
|
||||||
|
|
||||||
import type { QTableProps } from "quasar";
|
import type { QTableProps } from "quasar";
|
||||||
|
|
||||||
|
|
@ -187,6 +186,7 @@ watch(modal, (val) => {
|
||||||
dense
|
dense
|
||||||
label="คำค้น"
|
label="คำค้น"
|
||||||
@clear="search = ''"
|
@clear="search = ''"
|
||||||
|
@keydown.enter.prevent="onSearchData()"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<q-checkbox
|
<q-checkbox
|
||||||
|
|
@ -253,7 +253,7 @@ watch(modal, (val) => {
|
||||||
<q-th auto-width />
|
<q-th auto-width />
|
||||||
<q-th v-for="col in props.cols" :key="col.name" :props="props">
|
<q-th v-for="col in props.cols" :key="col.name" :props="props">
|
||||||
<span class="text-weight-medium">
|
<span class="text-weight-medium">
|
||||||
{{ getColumnLabel(col, isAct) }}
|
{{ col.label }}
|
||||||
</span>
|
</span>
|
||||||
</q-th>
|
</q-th>
|
||||||
</q-tr>
|
</q-tr>
|
||||||
|
|
|
||||||
|
|
@ -1004,7 +1004,6 @@ watch(
|
||||||
table-class="text-grey-9"
|
table-class="text-grey-9"
|
||||||
row-key="id"
|
row-key="id"
|
||||||
dense
|
dense
|
||||||
hide-bottom
|
|
||||||
bordered
|
bordered
|
||||||
separator="vertical"
|
separator="vertical"
|
||||||
class="custom-header-table-expand"
|
class="custom-header-table-expand"
|
||||||
|
|
|
||||||
|
|
@ -365,7 +365,7 @@ async function downloadFileDashboard() {
|
||||||
async function clickPassExam() {
|
async function clickPassExam() {
|
||||||
showLoader();
|
showLoader();
|
||||||
await http
|
await http
|
||||||
.get(config.API.exportExamPassExamList(examId.value))
|
.get(config.API.downloadPassExam(examId.value))
|
||||||
.then(async (res) => {
|
.then(async (res) => {
|
||||||
const data = res.data.result;
|
const data = res.data.result;
|
||||||
data.reportName = `Candidate_Dashboard_${dateToISO(new Date())}`;
|
data.reportName = `Candidate_Dashboard_${dateToISO(new Date())}`;
|
||||||
|
|
@ -382,7 +382,7 @@ async function clickPassExam() {
|
||||||
async function clickCandidateList() {
|
async function clickCandidateList() {
|
||||||
showLoader();
|
showLoader();
|
||||||
await http
|
await http
|
||||||
.get(config.API.exportExamCandidateList(examId.value))
|
.get(config.API.downloadCandidateExam(examId.value))
|
||||||
.then(async (res) => {
|
.then(async (res) => {
|
||||||
const data = res.data.result;
|
const data = res.data.result;
|
||||||
data.reportName = `Candidate_Dashboard_${dateToISO(new Date())}`;
|
data.reportName = `Candidate_Dashboard_${dateToISO(new Date())}`;
|
||||||
|
|
@ -397,8 +397,6 @@ async function clickCandidateList() {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function onCheckShowExaminfo() {
|
async function onCheckShowExaminfo() {
|
||||||
console.log(props.isShowExaminfo);
|
|
||||||
|
|
||||||
dialogMessage(
|
dialogMessage(
|
||||||
$q,
|
$q,
|
||||||
`ยืนยันการ${props.isShowExaminfo ? "ปิด" : "เปิด"}`,
|
`ยืนยันการ${props.isShowExaminfo ? "ปิด" : "เปิด"}`,
|
||||||
|
|
|
||||||
|
|
@ -212,17 +212,17 @@ const columnsPosition = ref<QTableProps["columns"]>([
|
||||||
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
|
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
// {
|
||||||
name: "type",
|
// name: "type",
|
||||||
align: "left",
|
// align: "left",
|
||||||
label: "ประเภทแบบฟอร์ม",
|
// label: "ประเภทแบบฟอร์ม",
|
||||||
sortable: true,
|
// sortable: true,
|
||||||
field: "type",
|
// field: "type",
|
||||||
headerStyle: "font-size: 14px",
|
// headerStyle: "font-size: 14px",
|
||||||
style: "font-size: 14px",
|
// style: "font-size: 14px",
|
||||||
sort: (a: string, b: string) =>
|
// sort: (a: string, b: string) =>
|
||||||
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
|
// a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
|
||||||
},
|
// },
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const shouldShowPaymentFields = computed(() => {
|
const shouldShowPaymentFields = computed(() => {
|
||||||
|
|
@ -1476,7 +1476,7 @@ onMounted(async () => {
|
||||||
</div>
|
</div>
|
||||||
</q-td>
|
</q-td>
|
||||||
|
|
||||||
<q-td key="type" :props="props">
|
<!-- <q-td key="type" :props="props">
|
||||||
<selector
|
<selector
|
||||||
class=""
|
class=""
|
||||||
outlined
|
outlined
|
||||||
|
|
@ -1490,7 +1490,7 @@ onMounted(async () => {
|
||||||
lazy-rules
|
lazy-rules
|
||||||
:rules="[(val:any) => !!val || `${'กรุณาเลือกประเภทแบบฟอร์ม'}`]"
|
:rules="[(val:any) => !!val || `${'กรุณาเลือกประเภทแบบฟอร์ม'}`]"
|
||||||
></selector>
|
></selector>
|
||||||
</q-td>
|
</q-td> -->
|
||||||
</q-tr>
|
</q-tr>
|
||||||
</template>
|
</template>
|
||||||
</ProfileTable>
|
</ProfileTable>
|
||||||
|
|
|
||||||
|
|
@ -260,7 +260,6 @@ async function fetchData(loading: boolean = true) {
|
||||||
total.value = data.total;
|
total.value = data.total;
|
||||||
maxPage.value = await Math.ceil(data.total / pageSize.value);
|
maxPage.value = await Math.ceil(data.total / pageSize.value);
|
||||||
maxPage.value = maxPage.value < 1 ? 1 : maxPage.value;
|
maxPage.value = maxPage.value < 1 ? 1 : maxPage.value;
|
||||||
|
|
||||||
rows.value = [];
|
rows.value = [];
|
||||||
data.data.map((r: any) => {
|
data.data.map((r: any) => {
|
||||||
rows.value.push({
|
rows.value.push({
|
||||||
|
|
@ -402,6 +401,7 @@ onMounted(async () => {
|
||||||
await fetchDataCom();
|
await fetchDataCom();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="toptitle text-dark col-12 row items-center">
|
<div class="toptitle text-dark col-12 row items-center">
|
||||||
<q-btn
|
<q-btn
|
||||||
|
|
@ -474,9 +474,9 @@ onMounted(async () => {
|
||||||
</div>
|
</div>
|
||||||
</q-card>
|
</q-card>
|
||||||
</q-slide-transition>
|
</q-slide-transition>
|
||||||
|
|
||||||
<q-card flat bordered class="col-12 q-pt-sm">
|
<q-card flat bordered class="col-12 q-pt-sm">
|
||||||
<TableCandidate
|
<TableCandidate
|
||||||
style="max-height: 80vh"
|
|
||||||
:rows="rows"
|
:rows="rows"
|
||||||
:columns="columns"
|
:columns="columns"
|
||||||
:filter="filter"
|
:filter="filter"
|
||||||
|
|
@ -603,6 +603,7 @@ onMounted(async () => {
|
||||||
</template>
|
</template>
|
||||||
</TableCandidate>
|
</TableCandidate>
|
||||||
</q-card>
|
</q-card>
|
||||||
|
|
||||||
<q-dialog v-model="modal" persistent>
|
<q-dialog v-model="modal" persistent>
|
||||||
<q-card style="min-width: 600px">
|
<q-card style="min-width: 600px">
|
||||||
<q-card-section class="row items-center q-py-sm">
|
<q-card-section class="row items-center q-py-sm">
|
||||||
|
|
|
||||||
|
|
@ -50,18 +50,10 @@ const formMain = reactive<FormMain>({
|
||||||
workDate: null, //วันที่เริ่มปฏิบัติราชการ
|
workDate: null, //วันที่เริ่มปฏิบัติราชการ
|
||||||
reasonSameDate: "",
|
reasonSameDate: "",
|
||||||
retireDate: null, //วันเกษียณอายุ
|
retireDate: null, //วันเกษียณอายุ
|
||||||
ageAll: {
|
ageAll: "", //อายุราชการ
|
||||||
year: 0,
|
|
||||||
month: 0,
|
|
||||||
day: 0,
|
|
||||||
}, //อายุราชการ
|
|
||||||
absent: 0, //ขาดราชการ
|
absent: 0, //ขาดราชการ
|
||||||
age: 0, //อายุราชการเกื้อกูล
|
age: 0, //อายุราชการเกื้อกูล
|
||||||
govAgeBkk:{
|
govAgeBkk: "",
|
||||||
year: 0,
|
|
||||||
month: 0,
|
|
||||||
day: 0,
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const modalEdit = ref<boolean>(false); //แสดง popup แก้ไขข้อมูลราชการ
|
const modalEdit = ref<boolean>(false); //แสดง popup แก้ไขข้อมูลราชการ
|
||||||
|
|
@ -165,10 +157,22 @@ async function getData() {
|
||||||
formMain.reasonSameDate = data.reasonSameDate;
|
formMain.reasonSameDate = data.reasonSameDate;
|
||||||
formMain.retireDate = data.dateLeave;
|
formMain.retireDate = data.dateLeave;
|
||||||
formMain.dateRetireLaw = data.dateRetireLaw;
|
formMain.dateRetireLaw = data.dateRetireLaw;
|
||||||
formMain.ageAll = data.govAge;
|
formMain.ageAll = data.govAge
|
||||||
|
? (
|
||||||
|
(data.govAge.year > 0 ? `${data.govAge.year} ปี ` : "") +
|
||||||
|
(data.govAge.month > 0 ? `${data.govAge.month} เดือน ` : "") +
|
||||||
|
(data.govAge.day > 0 ? `${data.govAge.day} วัน` : "")
|
||||||
|
).trim() || "-"
|
||||||
|
: "-";
|
||||||
formMain.absent = data.govAgeAbsent;
|
formMain.absent = data.govAgeAbsent;
|
||||||
formMain.age = data.govAgePlus;
|
formMain.age = data.govAgePlus;
|
||||||
formMain.govAgeBkk = data.govAgeBkk;
|
formMain.govAgeBkk = data.govAgeBkk
|
||||||
|
? (
|
||||||
|
(data.govAgeBkk.year > 0 ? `${data.govAgeBkk.year} ปี ` : "") +
|
||||||
|
(data.govAgeBkk.month > 0 ? `${data.govAgeBkk.month} เดือน ` : "") +
|
||||||
|
(data.govAgeBkk.day > 0 ? `${data.govAgeBkk.day} วัน` : "")
|
||||||
|
).trim() || "-"
|
||||||
|
: "-";
|
||||||
})
|
})
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
messageError($q, e);
|
messageError($q, e);
|
||||||
|
|
@ -455,25 +459,19 @@ onMounted(() => {
|
||||||
<span class="text-grey-6 text-weight-medium">อายุราชการ</span>
|
<span class="text-grey-6 text-weight-medium">อายุราชการ</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-12 col-sm-12 col-md-7">
|
<div class="col-12 col-sm-12 col-md-7">
|
||||||
<span>{{
|
<span>{{ formMain.ageAll }}</span>
|
||||||
formMain.ageAll
|
|
||||||
? `${formMain.ageAll.year} ปี ${formMain.ageAll.month} เดือน ${formMain.ageAll.day} วัน`
|
|
||||||
: "-"
|
|
||||||
}}</span>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-12 col-sm-6 col-md-6">
|
<div class="col-12 col-sm-6 col-md-6">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-12 col-sm-12 col-md-5">
|
<div class="col-12 col-sm-12 col-md-5">
|
||||||
<span class="text-grey-6 text-weight-medium">อายุราชการ (กทม.)</span>
|
<span class="text-grey-6 text-weight-medium"
|
||||||
|
>อายุราชการ (กทม.)</span
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-12 col-sm-12 col-md-7">
|
<div class="col-12 col-sm-12 col-md-7">
|
||||||
<span>{{
|
<span>{{ formMain.govAgeBkk }}</span>
|
||||||
formMain.govAgeBkk
|
|
||||||
? `${formMain.govAgeBkk.year} ปี ${formMain.govAgeBkk.month} เดือน ${formMain.govAgeBkk.day} วัน`
|
|
||||||
: "-"
|
|
||||||
}}</span>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -13,8 +13,8 @@ interface FormMain {
|
||||||
workDate: any;
|
workDate: any;
|
||||||
reasonSameDate: string;
|
reasonSameDate: string;
|
||||||
retireDate: any;
|
retireDate: any;
|
||||||
ageAll: GovAgeForm;
|
ageAll: GovAgeForm | string;
|
||||||
govAgeBkk: GovAgeForm;
|
govAgeBkk: GovAgeForm | string;
|
||||||
absent: number;
|
absent: number;
|
||||||
age: number;
|
age: number;
|
||||||
[key: string]: any;
|
[key: string]: any;
|
||||||
|
|
|
||||||
|
|
@ -70,6 +70,7 @@ interface DataPosition {
|
||||||
status: string;
|
status: string;
|
||||||
posNumCodeSitAbb: string;
|
posNumCodeSitAbb: string;
|
||||||
posNumCodeSit: string;
|
posNumCodeSit: string;
|
||||||
|
positionExecutiveField: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type { DataSalaryPos, DataPosition };
|
export type { DataSalaryPos, DataPosition };
|
||||||
|
|
|
||||||
177
src/modules/04_registryPerson/utils/excelParser.ts
Normal file
177
src/modules/04_registryPerson/utils/excelParser.ts
Normal file
|
|
@ -0,0 +1,177 @@
|
||||||
|
import * as XLSX from "xlsx";
|
||||||
|
|
||||||
|
export interface ExcelPreviewData {
|
||||||
|
fileName: string;
|
||||||
|
fileSize: number;
|
||||||
|
sheetNames: string[];
|
||||||
|
headers: string[];
|
||||||
|
rows: Array<Record<string, any>>;
|
||||||
|
totalRows: number;
|
||||||
|
previewRows: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ParseOptions {
|
||||||
|
maxPreviewRows?: number;
|
||||||
|
sheetIndex?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
const DEFAULT_CONFIG = {
|
||||||
|
MAX_FILE_SIZE: 10 * 1024 * 1024, // 10MB
|
||||||
|
MAX_PREVIEW_ROWS: 0, // 0 = ไม่จำกัด แสดงทั้งหมด
|
||||||
|
ALLOWED_EXTENSIONS: [".xlsx", ".xls"],
|
||||||
|
};
|
||||||
|
|
||||||
|
function formatFileSize(bytes: number): string {
|
||||||
|
if (bytes === 0) return "0 Bytes";
|
||||||
|
const k = 1024;
|
||||||
|
const sizes = ["Bytes", "KB", "MB", "GB"];
|
||||||
|
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
||||||
|
return Math.round((bytes / Math.pow(k, i)) * 100) / 100 + " " + sizes[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
function getFileExtension(fileName: string): string {
|
||||||
|
return fileName.substring(fileName.lastIndexOf(".")).toLowerCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
function validateFile(file: File): { message: string } | null {
|
||||||
|
const extension = getFileExtension(file.name);
|
||||||
|
|
||||||
|
if (!DEFAULT_CONFIG.ALLOWED_EXTENSIONS.includes(extension)) {
|
||||||
|
return {
|
||||||
|
message: `กรุณาเลือกไฟล์ Excel เท่านั้น (${DEFAULT_CONFIG.ALLOWED_EXTENSIONS.join(", ")})`,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (file.size > DEFAULT_CONFIG.MAX_FILE_SIZE) {
|
||||||
|
const fileSizeMB = (file.size / (1024 * 1024)).toFixed(2);
|
||||||
|
const maxSizeMB = (DEFAULT_CONFIG.MAX_FILE_SIZE / (1024 * 1024)).toFixed(2);
|
||||||
|
return {
|
||||||
|
message: `ขนาดไฟล์เกิน ${maxSizeMB}MB (ไฟล์ของคุณ: ${fileSizeMB}MB)`,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function parseExcelFile(
|
||||||
|
file: File,
|
||||||
|
options: ParseOptions = {}
|
||||||
|
): Promise<ExcelPreviewData> {
|
||||||
|
const maxPreviewRows = options.maxPreviewRows ?? DEFAULT_CONFIG.MAX_PREVIEW_ROWS;
|
||||||
|
const sheetIndex = options.sheetIndex ?? 0;
|
||||||
|
|
||||||
|
// Validate file
|
||||||
|
const validationError = validateFile(file);
|
||||||
|
if (validationError) {
|
||||||
|
throw new Error(validationError.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const reader = new FileReader();
|
||||||
|
|
||||||
|
reader.onload = (e) => {
|
||||||
|
try {
|
||||||
|
const data = e.target?.result;
|
||||||
|
if (!data) {
|
||||||
|
reject(new Error("ไม่สามารถอ่านไฟล์ได้"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const workbook = XLSX.read(data, { type: "binary" });
|
||||||
|
|
||||||
|
if (workbook.SheetNames.length === 0) {
|
||||||
|
reject(new Error("ไฟล์ไม่มีข้อมูล"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const sheetName = workbook.SheetNames[sheetIndex];
|
||||||
|
const worksheet = workbook.Sheets[sheetName];
|
||||||
|
|
||||||
|
// ใช้ sheet_to_json กับ raw: true เพื่ออ่าน raw values ก่อน
|
||||||
|
const jsonData = XLSX.utils.sheet_to_json(worksheet, {
|
||||||
|
header: 1,
|
||||||
|
defval: "",
|
||||||
|
raw: true, // อ่าน raw values
|
||||||
|
}) as any[][];
|
||||||
|
|
||||||
|
// หลังจากได้ raw data แล้ว ต้องไปอ่านค่าจาก formula ที่ cells โดยตรง
|
||||||
|
// เพราะบาง formula อาจจะยังไม่ถูกคำนวณ
|
||||||
|
const range = XLSX.utils.decode_range(worksheet["!ref"] || "A1");
|
||||||
|
|
||||||
|
// อ่านค่าจาก cells ที่มี formula (column สุดท้าย)
|
||||||
|
for (let row = range.s.r; row <= range.e.r; row++) {
|
||||||
|
for (let col = range.s.c; col <= range.e.c; col++) {
|
||||||
|
const cellAddress = XLSX.utils.encode_cell({ r: row, c: col });
|
||||||
|
const cell = worksheet[cellAddress];
|
||||||
|
|
||||||
|
// ถ้ามี formula ให้ใช้ผลลัพธ์ที่คำนวณแล้ว
|
||||||
|
if (cell && cell.f && !cell.v) {
|
||||||
|
// ลองใช้ cell.w (formatted value) ถ้ามี
|
||||||
|
if (cell.w) {
|
||||||
|
// แปลง array index ให้ถูกต้อง (row + 1 เพราะมี header row)
|
||||||
|
const arrayRowIndex = row - range.s.r;
|
||||||
|
if (jsonData[arrayRowIndex] && jsonData[arrayRowIndex][col] !== undefined) {
|
||||||
|
jsonData[arrayRowIndex][col] = cell.w;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (jsonData.length === 0) {
|
||||||
|
reject(new Error("ไฟล์ไม่มีข้อมูล"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract headers from first row (ภาษาไทย)
|
||||||
|
const headers = jsonData[0].map((h: any) => String(h ?? ""));
|
||||||
|
|
||||||
|
// Extract data rows (skip header row)
|
||||||
|
const dataRows = jsonData.slice(1).filter((row) => row.some((cell) => cell !== ""));
|
||||||
|
|
||||||
|
if (dataRows.length === 0) {
|
||||||
|
reject(new Error("ไฟล์ไม่มีข้อมูล"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert to array of objects - ใช้ header จาก Excel เป็น field names โดยตรง
|
||||||
|
// ถ้า maxPreviewRows = 0 จะแสดงทั้งหมด มิฉะนั้นจะแสดงตามจำนวนที่กำหนด
|
||||||
|
const rowsToProcess = maxPreviewRows === 0 ? dataRows : dataRows.slice(0, maxPreviewRows);
|
||||||
|
const rows = rowsToProcess.map((row, rowIndex) => {
|
||||||
|
const obj: Record<string, any> = {
|
||||||
|
id: `row_${rowIndex}`,
|
||||||
|
};
|
||||||
|
|
||||||
|
// ใช้ header เป็น field names โดยตรง
|
||||||
|
headers.forEach((header, index) => {
|
||||||
|
const cellValue = row[index] ?? "";
|
||||||
|
// ใช้ค่าจาก Excel โดยตรง ไม่แปลงค่า
|
||||||
|
obj[header] = cellValue;
|
||||||
|
});
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
});
|
||||||
|
|
||||||
|
resolve({
|
||||||
|
fileName: file.name,
|
||||||
|
fileSize: file.size,
|
||||||
|
sheetNames: workbook.SheetNames,
|
||||||
|
headers,
|
||||||
|
rows,
|
||||||
|
totalRows: dataRows.length,
|
||||||
|
previewRows: rows.length,
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
reject(new Error("ไม่สามารถอ่านไฟล์ Excel ได้ กรุณาตรวจสอบไฟล์อีกครั้ง"));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
reader.onerror = () => {
|
||||||
|
reject(new Error("ไม่สามารถอ่านไฟล์ได้"));
|
||||||
|
};
|
||||||
|
|
||||||
|
reader.readAsBinaryString(file);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export { formatFileSize };
|
||||||
157
src/modules/04_registryPerson/utils/exportPosition.ts
Normal file
157
src/modules/04_registryPerson/utils/exportPosition.ts
Normal file
|
|
@ -0,0 +1,157 @@
|
||||||
|
import ExcelJS from "exceljs";
|
||||||
|
import { useEditPosDataStore } from "@/modules/04_registryPerson/stores/Edit";
|
||||||
|
|
||||||
|
import type { DataPosition } from "@/modules/04_registryPerson/interface/response/Edit";
|
||||||
|
|
||||||
|
const store = useEditPosDataStore();
|
||||||
|
|
||||||
|
// ฟังก์ชันแปลงวันที่จาก ISO format เป็นรูปแบบ dd/mm/yyyy (เช่น 18/05/2564)
|
||||||
|
function formatDateToDDMMYYYY(dateString: string | null | Date): string {
|
||||||
|
if (!dateString) return "";
|
||||||
|
|
||||||
|
const date = new Date(dateString);
|
||||||
|
if (isNaN(date.getTime())) return "";
|
||||||
|
|
||||||
|
const day = String(date.getDate()).padStart(2, "0");
|
||||||
|
const month = String(date.getMonth() + 1).padStart(2, "0");
|
||||||
|
const year = date.getFullYear() + 543; // แปลงเป็นปีพุทธศักราช
|
||||||
|
|
||||||
|
return `${day}/${month}/${year}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function exportToExcelPosition(data: DataPosition[]) {
|
||||||
|
const workbook = new ExcelJS.Workbook();
|
||||||
|
const worksheet = workbook.addWorksheet("รายการประวัติตำแหน่งเงินเดือน");
|
||||||
|
|
||||||
|
// --- ส่วนที่ 1: สร้าง Master Data Sheet สำหรับอ้างอิง ID ---
|
||||||
|
// เราจะซ่อนแผ่นงานนี้ไว้ (hidden) เพื่อใช้ทำ Dropdown และ VLOOKUP
|
||||||
|
const masterSheet = workbook.addWorksheet("MasterData", { state: "hidden" });
|
||||||
|
const masterData = store.commandCodeData; // [{id: 1, name: "ย้าย"}, ...]
|
||||||
|
|
||||||
|
masterData.forEach((item, index) => {
|
||||||
|
masterSheet.getCell(`A${index + 1}`).value = item.name;
|
||||||
|
masterSheet.getCell(`B${index + 1}`).value = item.id;
|
||||||
|
});
|
||||||
|
|
||||||
|
// --- ส่วนที่ 2: กำหนด Columns ---
|
||||||
|
worksheet.columns = [
|
||||||
|
{ header: "ลำดับ", key: "no", width: 8 },
|
||||||
|
{ header: "วันที่คำสั่งมีผล", key: "commandDateAffect", width: 18 },
|
||||||
|
{ header: "ตำแหน่งในสายงาน", key: "positionName", width: 25 },
|
||||||
|
{ header: "ตำแหน่งประเภท", key: "positionType", width: 18 },
|
||||||
|
{ header: "ระดับ", key: "positionLevel", width: 12 },
|
||||||
|
{ header: "ระดับซี", key: "positionCee", width: 12 },
|
||||||
|
{ header: "สายงาน", key: "positionLine", width: 20 },
|
||||||
|
{ header: "ด้าน/สาขา", key: "positionPathSide", width: 15 },
|
||||||
|
{ header: "ตำแหน่งทางการบริหาร", key: "positionExecutive", width: 20 },
|
||||||
|
{ header: "ด้านทางการบริหาร", key: "positionExecutiveField", width: 20 },
|
||||||
|
{ header: "เงินเดือน", key: "amount", width: 15 },
|
||||||
|
{ header: "เงินค่าตอบแทนรายเดือน", key: "mouthSalaryAmount", width: 15 },
|
||||||
|
{ header: "เงินประจำตำแหน่ง", key: "positionSalaryAmount", width: 15 },
|
||||||
|
{ header: "เงินค่าตอบแทนพิเศษ", key: "amountSpecial", width: 15 },
|
||||||
|
{ header: "หน่วยงาน", key: "organization", width: 30 },
|
||||||
|
{ header: "ส่วนราชการระดับ 1", key: "orgChild1", width: 20 },
|
||||||
|
{ header: "ส่วนราชการระดับ 2", key: "orgChild2", width: 20 },
|
||||||
|
{ header: "ส่วนราชการระดับ 3", key: "orgChild3", width: 20 },
|
||||||
|
{ header: "ส่วนราชการระดับ 4", key: "orgChild4", width: 20 },
|
||||||
|
{ header: "ตัวย่อเลขที่ตำแหน่ง", key: "posNoAbb", width: 15 },
|
||||||
|
{ header: "เลขที่ตำแหน่ง", key: "posNo", width: 15 },
|
||||||
|
{ header: "หน่วยงานที่ออกคำสั่ง", key: "posNumCodeSit", width: 20 },
|
||||||
|
{
|
||||||
|
header: "ตัวย่อหน่วยงานที่ออกคำสั่ง",
|
||||||
|
key: "posNumCodeSitAbb",
|
||||||
|
width: 15,
|
||||||
|
},
|
||||||
|
{ header: "เลขที่คำสั่ง", key: "commandNo", width: 15 },
|
||||||
|
{ header: "ปีเลขที่คำสั่ง", key: "commandYear", width: 12 },
|
||||||
|
{ header: "วันที่ลงนาม", key: "commandDateSign", width: 18 },
|
||||||
|
{ header: "ประเภทคำสั่ง", key: "commandCodeName", width: 25 }, // AA
|
||||||
|
{ header: "หมายเหตุ", key: "remark", width: 20 },
|
||||||
|
{ header: "commandId", key: "commandId", width: 20 }, // AC (ลำดับที่ 29)
|
||||||
|
{ header: "commandCode", key: "commandCode", width: 20 }, // AD (ลำดับที่ 30)
|
||||||
|
];
|
||||||
|
|
||||||
|
// 3. Map ข้อมูล
|
||||||
|
const newData = data.map((e, index) => ({
|
||||||
|
no: index + 1,
|
||||||
|
commandDateAffect: e.commandDateAffect
|
||||||
|
? formatDateToDDMMYYYY(e.commandDateAffect)
|
||||||
|
: "",
|
||||||
|
positionName: e.positionName,
|
||||||
|
positionType: e.positionType,
|
||||||
|
positionLevel: e.positionLevel,
|
||||||
|
positionCee: e.positionCee,
|
||||||
|
positionLine: e.positionLine || "",
|
||||||
|
positionPathSide: e.positionPathSide || "",
|
||||||
|
positionExecutive: e.positionExecutive,
|
||||||
|
positionExecutiveField: e.positionExecutiveField || "",
|
||||||
|
amount: e.amount || 0,
|
||||||
|
mouthSalaryAmount: e.mouthSalaryAmount || 0,
|
||||||
|
positionSalaryAmount: e.positionSalaryAmount || 0,
|
||||||
|
amountSpecial: e.amountSpecial || 0,
|
||||||
|
organization: e.orgRoot,
|
||||||
|
orgChild1: e.orgChild1,
|
||||||
|
orgChild2: e.orgChild2,
|
||||||
|
orgChild3: e.orgChild3,
|
||||||
|
orgChild4: e.orgChild4,
|
||||||
|
posNoAbb: e.posNoAbb,
|
||||||
|
posNo: e.posNo,
|
||||||
|
posNumCodeSit: e.posNumCodeSit,
|
||||||
|
posNumCodeSitAbb: e.posNumCodeSitAbb,
|
||||||
|
commandNo: e.commandNo,
|
||||||
|
commandYear: e.commandYear ? Number(e.commandYear) + 543 : "",
|
||||||
|
commandDateSign: e.commandDateSign
|
||||||
|
? formatDateToDDMMYYYY(e.commandDateSign)
|
||||||
|
: "",
|
||||||
|
commandCodeName: store.convertCommandCodeName(e.commandCode),
|
||||||
|
remark: e.remark,
|
||||||
|
commandId: e.commandId || "",
|
||||||
|
commandCode: e.commandCode || "", // ใส่ค่าเริ่มต้นไว้
|
||||||
|
}));
|
||||||
|
|
||||||
|
worksheet.addRows(newData);
|
||||||
|
|
||||||
|
// 4. ตกแต่งสี, Dropdown และ สูตร VLOOKUP
|
||||||
|
newData.forEach((_, index) => {
|
||||||
|
const rowIndex = index + 2;
|
||||||
|
|
||||||
|
// --- ตั้งค่า Format สำหรับเซลล์วันที่ ---
|
||||||
|
// เซลล์ B (commandDateAffect) และ Z (commandDateSign)
|
||||||
|
const dateAffectCell = worksheet.getCell(`B${rowIndex}`);
|
||||||
|
const dateSignCell = worksheet.getCell(`Z${rowIndex}`);
|
||||||
|
|
||||||
|
[dateAffectCell, dateSignCell].forEach((cell) => {
|
||||||
|
cell.numFmt = "dd/mm/yyyy";
|
||||||
|
});
|
||||||
|
|
||||||
|
// --- ทำ Dropdown คอลัมน์ AA ---
|
||||||
|
// อ้างอิงรายการจาก MasterData Sheet จะทำให้ Excel ทำงานได้เสถียรกว่า (กรณีรายการเยอะ)
|
||||||
|
worksheet.getCell(`AA${rowIndex}`).dataValidation = {
|
||||||
|
type: "list",
|
||||||
|
allowBlank: true,
|
||||||
|
formulae: [`MasterData!$A$1:$A$${masterData.length}`],
|
||||||
|
};
|
||||||
|
|
||||||
|
// --- ผูกสูตรให้ commandCode (AD) เปลี่ยนตามการเลือกใน AA ---
|
||||||
|
// AA คือประเภทคำสั่ง, AD คือ commandCode
|
||||||
|
worksheet.getCell(`AD${rowIndex}`).value = {
|
||||||
|
formula: `=IFERROR(VLOOKUP(AA${rowIndex}, MasterData!$A$1:$B$${masterData.length}, 2, FALSE), "")`,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
// 5. สไตล์ Header
|
||||||
|
worksheet.getRow(1).font = { bold: true };
|
||||||
|
worksheet.getRow(1).alignment = { vertical: "middle", horizontal: "center" };
|
||||||
|
|
||||||
|
// 6. เขียนไฟล์
|
||||||
|
const buffer = await workbook.xlsx.writeBuffer();
|
||||||
|
const blob = new Blob([buffer], {
|
||||||
|
type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
||||||
|
});
|
||||||
|
const url = window.URL.createObjectURL(blob);
|
||||||
|
const a = document.createElement("a");
|
||||||
|
a.href = url;
|
||||||
|
a.download = "รายการประวัติตำแหน่งเงินเดือน.xlsx";
|
||||||
|
a.click();
|
||||||
|
window.URL.revokeObjectURL(url);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,270 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, computed, watch } from "vue";
|
||||||
|
import { useQuasar } from "quasar";
|
||||||
|
import moment from "moment";
|
||||||
|
|
||||||
|
import {
|
||||||
|
parseExcelFile,
|
||||||
|
formatFileSize,
|
||||||
|
} from "@/modules/04_registryPerson/utils/excelParser";
|
||||||
|
import { useCounterMixin } from "@/stores/mixin";
|
||||||
|
|
||||||
|
const $q = useQuasar();
|
||||||
|
const { dialogConfirm } = useCounterMixin();
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
modal: boolean;
|
||||||
|
file: File | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Emits {
|
||||||
|
(e: "update:modal", value: boolean): void;
|
||||||
|
(e: "confirm", file: File): void;
|
||||||
|
(e: "cancel"): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = defineProps<Props>();
|
||||||
|
const emit = defineEmits<Emits>();
|
||||||
|
|
||||||
|
const isLoading = ref(false);
|
||||||
|
const isUploading = ref(false);
|
||||||
|
const previewData = ref<Record<string, any>[]>([]);
|
||||||
|
const excelHeaders = ref<string[]>([]); // Headers จาก Excel
|
||||||
|
|
||||||
|
const fileName = computed(() => props.file?.name ?? "");
|
||||||
|
const fileSize = computed(() => props.file?.size ?? 0);
|
||||||
|
const totalRows = computed(() => previewData.value.length);
|
||||||
|
const previewRows = computed(() => previewData.value.length);
|
||||||
|
|
||||||
|
const pagination = ref({
|
||||||
|
page: 1,
|
||||||
|
rowsPerPage: 50,
|
||||||
|
});
|
||||||
|
|
||||||
|
// ฟังก์ชันแปลงวันที่เป็นภาษาไทย (ไม่บวก 543 เพราะ Excel เป็น พ.ศ. อยู่แล้ว)
|
||||||
|
function formatDateForDisplay(value: any): string {
|
||||||
|
if (!value) return "-";
|
||||||
|
|
||||||
|
// ถ้าเป็น string format dd/mm/yyyy (จาก Excel ที่เป็น พ.ศ.)
|
||||||
|
if (typeof value === "string") {
|
||||||
|
const parts = value.split("/");
|
||||||
|
if (parts.length === 3) {
|
||||||
|
const day = parts[0];
|
||||||
|
const monthNum = parseInt(parts[1], 10);
|
||||||
|
const year = parts[2];
|
||||||
|
|
||||||
|
// แปลงเลขเดือนเป็นชื่อเดือนภาษาไทย
|
||||||
|
const thaiMonths = [
|
||||||
|
"ม.ค.",
|
||||||
|
"ก.พ.",
|
||||||
|
"มี.ค.",
|
||||||
|
"เม.ย.",
|
||||||
|
"พ.ค.",
|
||||||
|
"มิ.ย.",
|
||||||
|
"ก.ค.",
|
||||||
|
"ส.ค.",
|
||||||
|
"ก.ย.",
|
||||||
|
"ต.ค.",
|
||||||
|
"พ.ย.",
|
||||||
|
"ธ.ค.",
|
||||||
|
];
|
||||||
|
const thaiMonth = thaiMonths[monthNum - 1] || parts[1];
|
||||||
|
|
||||||
|
return `${day} ${thaiMonth} ${year}`;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ถ้าเป็น Date object ให้แปลงโดยไม่บวก 543 (เพราะ Excel serial date แปลงเป็น ค.ศ. แล้วแต่เดิมเป็น พ.ศ.)
|
||||||
|
const dateMoment = moment(value);
|
||||||
|
const day = dateMoment.format("DD");
|
||||||
|
const month = dateMoment.format("MMM");
|
||||||
|
const year = +dateMoment.format("YYYY"); // ไม่บวก 543
|
||||||
|
return `${day} ${month} ${year}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Headers ที่เป็นวันที่
|
||||||
|
const DATE_HEADERS = ["วันที่คำสั่งมีผล", "วันที่ลงนาม"];
|
||||||
|
const SALARY_HEADERS = [
|
||||||
|
"เงินเดือน",
|
||||||
|
"ค่าจ้าง",
|
||||||
|
"เงินค่าตอบแทนรายเดือน",
|
||||||
|
"เงินประจำตำแหน่ง",
|
||||||
|
"เงินค่าตอบแทนพิเศษ",
|
||||||
|
];
|
||||||
|
|
||||||
|
// สร้าง columns จาก Excel headers
|
||||||
|
const tableColumns = computed(() => {
|
||||||
|
if (excelHeaders.value.length === 0) return [];
|
||||||
|
return excelHeaders.value.map((header, index) => {
|
||||||
|
const isDateColumn = DATE_HEADERS.includes(header);
|
||||||
|
const isSalaryColumn = SALARY_HEADERS.includes(header);
|
||||||
|
|
||||||
|
return {
|
||||||
|
name: `col_${index}`,
|
||||||
|
label: header,
|
||||||
|
field: header,
|
||||||
|
align: "left" as const,
|
||||||
|
sortable: false,
|
||||||
|
style: "white-space: nowrap;",
|
||||||
|
headerStyle: "font-size: 13px; font-weight: bold;",
|
||||||
|
format: (val: any) => {
|
||||||
|
// ถ้าค่าว่าง แสดง -
|
||||||
|
if (val == null || val === "") return "-";
|
||||||
|
|
||||||
|
// ถ้าเป็น column วันที่
|
||||||
|
if (isDateColumn) {
|
||||||
|
// ถ้าเป็น string วันที่ format dd/mm/yyyy (จาก Excel)
|
||||||
|
if (
|
||||||
|
typeof val === "string" &&
|
||||||
|
val.match(/^\d{1,2}\/\d{1,2}\/\d{4}$/)
|
||||||
|
) {
|
||||||
|
return formatDateForDisplay(val);
|
||||||
|
}
|
||||||
|
// ถ้าเป็น number (Excel serial date) ให้แปลงเป็น Date object ก่อน
|
||||||
|
if (typeof val === "number") {
|
||||||
|
return formatDateForDisplay((val - 25569) * 86400 * 1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ถ้าเป็น column เงินให้ format มี comma separator (ตรวจสอบชื่อ label)
|
||||||
|
if (isSalaryColumn) {
|
||||||
|
const numericValue = Number(val);
|
||||||
|
if (typeof numericValue === "number" && !isNaN(numericValue)) {
|
||||||
|
return numericValue.toLocaleString("en-US");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return val;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
async function loadPreview() {
|
||||||
|
if (!props.file) return;
|
||||||
|
|
||||||
|
isLoading.value = true;
|
||||||
|
try {
|
||||||
|
const result = await parseExcelFile(props.file, {
|
||||||
|
maxPreviewRows: 0, // 0 = แสดงทั้งหมด
|
||||||
|
sheetIndex: 0, // ใช้ sheet แรกเสมอ
|
||||||
|
});
|
||||||
|
previewData.value = result.rows;
|
||||||
|
excelHeaders.value = result.headers; // เก็บ headers จาก Excel
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error parsing Excel file:", error);
|
||||||
|
previewData.value = [];
|
||||||
|
excelHeaders.value = [];
|
||||||
|
} finally {
|
||||||
|
isLoading.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onConfirm() {
|
||||||
|
dialogConfirm($q, () => {
|
||||||
|
if (props.file) {
|
||||||
|
isUploading.value = true;
|
||||||
|
emit("confirm", props.file);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function onClose() {
|
||||||
|
emit("cancel");
|
||||||
|
emit("update:modal", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
function onModalUpdate(value: boolean) {
|
||||||
|
emit("update:modal", value);
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.modal,
|
||||||
|
(newValue) => {
|
||||||
|
if (newValue && props.file) {
|
||||||
|
isUploading.value = false;
|
||||||
|
loadPreview();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<q-dialog :model-value="modal" @update:model-value="onModalUpdate" persistent>
|
||||||
|
<q-card style="min-width: 80vw; max-width: 95vw">
|
||||||
|
<q-card-section class="row items-center q-pb-none">
|
||||||
|
<div class="text-h6">ตัวอย่างข้อมูลไฟล์ Excel</div>
|
||||||
|
<q-space />
|
||||||
|
<q-btn icon="close" flat round dense v-close-popup @click="onClose" />
|
||||||
|
</q-card-section>
|
||||||
|
|
||||||
|
<q-separator />
|
||||||
|
|
||||||
|
<!-- File Info Section -->
|
||||||
|
<q-card-section>
|
||||||
|
<div class="row q-col-gutter-md">
|
||||||
|
<div class="col-12">
|
||||||
|
<div class="text-subtitle2 text-grey-7">ข้อมูลไฟล์</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4 col-sm-6 col-12">
|
||||||
|
<div class="flex items-center">
|
||||||
|
<q-icon
|
||||||
|
name="insert_drive_file"
|
||||||
|
class="q-mr-sm"
|
||||||
|
color="primary"
|
||||||
|
/>
|
||||||
|
<span class="text-body2">ชื่อไฟล์: {{ fileName }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4 col-sm-6 col-12">
|
||||||
|
<div class="flex items-center">
|
||||||
|
<q-icon name="folder" class="q-mr-sm" color="primary" />
|
||||||
|
<span class="text-body2"
|
||||||
|
>ขนาด: {{ formatFileSize(fileSize) }}</span
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4 col-sm-12 col-12">
|
||||||
|
<div class="flex items-center">
|
||||||
|
<q-icon name="table_chart" class="q-mr-sm" color="primary" />
|
||||||
|
<span class="text-body2">จำนวนแถว: {{ totalRows }} แถว</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</q-card-section>
|
||||||
|
|
||||||
|
<q-separator />
|
||||||
|
|
||||||
|
<!-- Preview Table -->
|
||||||
|
<q-card-section style="max-height: 70vh" class="scroll">
|
||||||
|
<div class="text-subtitle2 q-mb-md">
|
||||||
|
รายการตำแหน่ง ({{ previewRows }} รายการ)
|
||||||
|
</div>
|
||||||
|
<d-table
|
||||||
|
:columns="tableColumns"
|
||||||
|
:rows="previewData"
|
||||||
|
:paging="true"
|
||||||
|
:rows-per-page-options="[20, 50, 100, 0]"
|
||||||
|
v-model:pagination="pagination"
|
||||||
|
:loading="isLoading"
|
||||||
|
row-key="id"
|
||||||
|
flat
|
||||||
|
bordered
|
||||||
|
dense
|
||||||
|
/>
|
||||||
|
</q-card-section>
|
||||||
|
|
||||||
|
<!-- Actions -->
|
||||||
|
<q-card-actions align="right" class="q-pa-md">
|
||||||
|
<q-btn
|
||||||
|
type="submit"
|
||||||
|
color="public"
|
||||||
|
label="ยืนยันการอัปโหลด"
|
||||||
|
@click="onConfirm"
|
||||||
|
:loading="isUploading"
|
||||||
|
/>
|
||||||
|
</q-card-actions>
|
||||||
|
</q-card>
|
||||||
|
</q-dialog>
|
||||||
|
</template>
|
||||||
|
|
@ -706,6 +706,7 @@ function classInput(val: boolean) {
|
||||||
hide-bottom-space
|
hide-bottom-space
|
||||||
autocomplete="on"
|
autocomplete="on"
|
||||||
name="organization"
|
name="organization"
|
||||||
|
:label="`${'หน่วยงาน'}`"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,13 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, onMounted, computed, reactive } from "vue";
|
import { ref, onMounted, computed, reactive } from "vue";
|
||||||
import { useQuasar } from "quasar";
|
import { useQuasar } from "quasar";
|
||||||
import * as XLSX from "xlsx";
|
|
||||||
|
|
||||||
import http from "@/plugins/http";
|
import http from "@/plugins/http";
|
||||||
import config from "@/app.config";
|
import config from "@/app.config";
|
||||||
import { useRoute } from "vue-router";
|
import { useRoute } from "vue-router";
|
||||||
import { useCounterMixin } from "@/stores/mixin";
|
import { useCounterMixin } from "@/stores/mixin";
|
||||||
import { useEditPosDataStore } from "@/modules/04_registryPerson/stores/Edit";
|
import { useEditPosDataStore } from "@/modules/04_registryPerson/stores/Edit";
|
||||||
|
import { exportToExcelPosition } from "@/modules/04_registryPerson/utils/exportPosition";
|
||||||
|
|
||||||
import type { QTableColumn } from "quasar";
|
import type { QTableColumn } from "quasar";
|
||||||
import type { FormDataSalary } from "@/modules/04_registryPerson/interface/index/Edit";
|
import type { FormDataSalary } from "@/modules/04_registryPerson/interface/index/Edit";
|
||||||
|
|
@ -20,6 +20,7 @@ import type {
|
||||||
|
|
||||||
import DialogForm from "@/modules/04_registryPerson/views/edit/components/DialogForm.vue";
|
import DialogForm from "@/modules/04_registryPerson/views/edit/components/DialogForm.vue";
|
||||||
import DialogSort from "@/modules/04_registryPerson/views/edit/components/DialogSort.vue";
|
import DialogSort from "@/modules/04_registryPerson/views/edit/components/DialogSort.vue";
|
||||||
|
import DialogExcelPreview from "@/modules/04_registryPerson/views/edit/components/DialogExcelPreview.vue";
|
||||||
import CurruncyInput from "@/components/CurruncyInput.vue";
|
import CurruncyInput from "@/components/CurruncyInput.vue";
|
||||||
|
|
||||||
const $q = useQuasar();
|
const $q = useQuasar();
|
||||||
|
|
@ -52,6 +53,11 @@ const amountRef = ref<any>(null);
|
||||||
const amountSpecialRef = ref<any>(null);
|
const amountSpecialRef = ref<any>(null);
|
||||||
const currencyPopupRef = ref<any>(null);
|
const currencyPopupRef = ref<any>(null);
|
||||||
|
|
||||||
|
// Excel Preview
|
||||||
|
const excelPreviewModal = ref<boolean>(false);
|
||||||
|
const selectedExcelFile = ref<File | null>(null);
|
||||||
|
const isParsingExcel = ref<boolean>(false);
|
||||||
|
|
||||||
//Table
|
//Table
|
||||||
const isLoad = ref<boolean>(true);
|
const isLoad = ref<boolean>(true);
|
||||||
const rowIndex = ref<number>(0);
|
const rowIndex = ref<number>(0);
|
||||||
|
|
@ -430,66 +436,67 @@ function classColorRow(isDelete: boolean, isEdit: boolean, isEntry: boolean) {
|
||||||
|
|
||||||
/** ฟังก์ชันดาวน์โหลดไฟล Excel */
|
/** ฟังก์ชันดาวน์โหลดไฟล Excel */
|
||||||
function exportToExcel() {
|
function exportToExcel() {
|
||||||
const newData = rows.value.map((e: DataPosition) => {
|
exportToExcelPosition(rows.value);
|
||||||
return {
|
// const newData = rows.value.map((e: DataPosition) => {
|
||||||
commandDateAffect: date2Thai(e.commandDateAffect),
|
// return {
|
||||||
positionName: e.positionName,
|
// commandDateAffect: date2Thai(e.commandDateAffect),
|
||||||
positionType: e.positionType,
|
// positionName: e.positionName,
|
||||||
positionLevel: e.positionLevel
|
// positionType: e.positionType,
|
||||||
? e.positionLevel
|
// positionLevel: e.positionLevel
|
||||||
: e.positionCee
|
// ? e.positionLevel
|
||||||
? e.positionCee
|
// : e.positionCee
|
||||||
: "",
|
// ? e.positionCee
|
||||||
positionExecutive: e.positionExecutive,
|
// : "",
|
||||||
amount: e.amount,
|
// positionExecutive: e.positionExecutive,
|
||||||
mouthSalaryAmount: e.mouthSalaryAmount,
|
// amount: e.amount,
|
||||||
positionSalaryAmount: e.positionSalaryAmount,
|
// mouthSalaryAmount: e.mouthSalaryAmount,
|
||||||
organization: findOrgName({
|
// positionSalaryAmount: e.positionSalaryAmount,
|
||||||
root: e.orgRoot,
|
// organization: findOrgName({
|
||||||
child1: e.orgChild1,
|
// root: e.orgRoot,
|
||||||
child2: e.orgChild2,
|
// child1: e.orgChild1,
|
||||||
child3: e.orgChild3,
|
// child2: e.orgChild2,
|
||||||
child4: e.orgChild4,
|
// child3: e.orgChild3,
|
||||||
}),
|
// child4: e.orgChild4,
|
||||||
posNo:
|
// }),
|
||||||
e.posNoAbb && e.posNo
|
// posNo:
|
||||||
? `${e.posNoAbb} ${e.posNo}`
|
// e.posNoAbb && e.posNo
|
||||||
: e.posNo
|
// ? `${e.posNoAbb} ${e.posNo}`
|
||||||
? e.posNo
|
// : e.posNo
|
||||||
: "",
|
// ? e.posNo
|
||||||
posNumCodeSit:
|
// : "",
|
||||||
e.posNumCodeSitAbb && e.posNumCodeSit
|
// posNumCodeSit:
|
||||||
? `${e.posNumCodeSit} (${e.posNumCodeSitAbb})`
|
// e.posNumCodeSitAbb && e.posNumCodeSit
|
||||||
: e.posNumCodeSit
|
// ? `${e.posNumCodeSit} (${e.posNumCodeSitAbb})`
|
||||||
? e.posNumCodeSit
|
// : e.posNumCodeSit
|
||||||
: "",
|
// ? e.posNumCodeSit
|
||||||
commandNo:
|
// : "",
|
||||||
e.commandNo && e.commandYear
|
// commandNo:
|
||||||
? `${e.commandNo}/${Number(e.commandYear) + 543}`
|
// e.commandNo && e.commandYear
|
||||||
: "",
|
// ? `${e.commandNo}/${Number(e.commandYear) + 543}`
|
||||||
commandDateSign: date2Thai(e.commandDateSign),
|
// : "",
|
||||||
commandCode: store.convertCommandCodeName(e.commandCode),
|
// commandDateSign: date2Thai(e.commandDateSign),
|
||||||
remark: e.remark,
|
// commandCode: store.convertCommandCodeName(e.commandCode),
|
||||||
};
|
// remark: e.remark,
|
||||||
});
|
// };
|
||||||
|
// });
|
||||||
|
|
||||||
const headers = columns.value.map((item: any) => item.label) || []; // หัวคอลัมน์ภาษาไทย
|
// const headers = columns.value.map((item: any) => item.label) || []; // หัวคอลัมน์ภาษาไทย
|
||||||
const worksheet = XLSX.utils.json_to_sheet(newData, {
|
// const worksheet = XLSX.utils.json_to_sheet(newData, {
|
||||||
header: visibleColumns.value,
|
// header: visibleColumns.value,
|
||||||
});
|
// });
|
||||||
|
|
||||||
//แทรกหัวคอลัมน์ภาษาไทย (ใช้ A1, B1, C1 แทน)
|
// //แทรกหัวคอลัมน์ภาษาไทย (ใช้ A1, B1, C1 แทน)
|
||||||
XLSX.utils.sheet_add_aoa(worksheet, [headers], { origin: "A1" });
|
// XLSX.utils.sheet_add_aoa(worksheet, [headers], { origin: "A1" });
|
||||||
|
|
||||||
// Create a new workbook and append the worksheet
|
// // Create a new workbook and append the worksheet
|
||||||
const workbook = XLSX.utils.book_new();
|
// const workbook = XLSX.utils.book_new();
|
||||||
|
|
||||||
XLSX.utils.book_append_sheet(
|
// XLSX.utils.book_append_sheet(
|
||||||
workbook,
|
// workbook,
|
||||||
worksheet,
|
// worksheet,
|
||||||
`รายการประวัติตำแหน่งเงินเดือน`
|
// `รายการประวัติตำแหน่งเงินเดือน`
|
||||||
);
|
// );
|
||||||
XLSX.writeFile(workbook, "รายการประวัติตำแหน่งเงินเดือน.xlsx");
|
// XLSX.writeFile(workbook, "รายการประวัติตำแหน่งเงินเดือน.xlsx");
|
||||||
}
|
}
|
||||||
|
|
||||||
const commandCodeOptions = ref<DataOption[]>(store.commandCodeData); //รายการปรเภทคำสั่ง
|
const commandCodeOptions = ref<DataOption[]>(store.commandCodeData); //รายการปรเภทคำสั่ง
|
||||||
|
|
@ -847,6 +854,83 @@ async function validateAndSave(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ฟังก์ชันอัปโหลดไฟล์ Excel
|
||||||
|
* เปิด preview modal ก่อนอัปโหลด
|
||||||
|
*/
|
||||||
|
function handUploadFile() {
|
||||||
|
const input = document.createElement("input");
|
||||||
|
input.type = "file";
|
||||||
|
input.accept = ".xlsx,.xls";
|
||||||
|
|
||||||
|
input.onchange = async (e: Event) => {
|
||||||
|
const file = (e.target as HTMLInputElement).files?.[0];
|
||||||
|
if (!file) return;
|
||||||
|
|
||||||
|
// ตรวจสอบชนิดไฟล์โดยตรวจสอบนามสกุล
|
||||||
|
const validExtensions = [".xlsx", ".xls"];
|
||||||
|
const fileExtension = file.name
|
||||||
|
.substring(file.name.lastIndexOf("."))
|
||||||
|
.toLowerCase();
|
||||||
|
|
||||||
|
if (!validExtensions.includes(fileExtension)) {
|
||||||
|
messageError($q, {
|
||||||
|
response: {
|
||||||
|
data: {
|
||||||
|
title: "กรุณาเลือกไฟล์ Excel เท่านั้น (.xlsx, .xls)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// เก็บไฟล์และเปิด preview modal
|
||||||
|
selectedExcelFile.value = file;
|
||||||
|
excelPreviewModal.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
input.click();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ฟังก์ชันยืนยันการอัปโหลดไฟล์
|
||||||
|
* ส่งไฟล์ไปยัง API เมื่อ user ยืนยันจาก preview modal
|
||||||
|
*/
|
||||||
|
async function onConfirmUpload(file: File) {
|
||||||
|
try {
|
||||||
|
isParsingExcel.value = true;
|
||||||
|
showLoader();
|
||||||
|
|
||||||
|
const type = empType.value === "officer" ? "office" : "employee";
|
||||||
|
const formData = new FormData();
|
||||||
|
formData.append("file", file);
|
||||||
|
|
||||||
|
await http.post(config.API.uploadProfile(type, profileId.value), formData, {
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "multipart/form-data",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
success($q, "อัปโหลดไฟล์สำเร็จ");
|
||||||
|
await fetchData();
|
||||||
|
excelPreviewModal.value = false;
|
||||||
|
} catch (error) {
|
||||||
|
messageError($q, error);
|
||||||
|
} finally {
|
||||||
|
hideLoader();
|
||||||
|
isParsingExcel.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ฟังก์ชันยกเลิกการอัปโหลด
|
||||||
|
* ปิด preview modal และล้างค่า
|
||||||
|
*/
|
||||||
|
function onCancelUpload() {
|
||||||
|
selectedExcelFile.value = null;
|
||||||
|
excelPreviewModal.value = false;
|
||||||
|
}
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
await Promise.all([fetchData(), fetchType()]);
|
await Promise.all([fetchData(), fetchType()]);
|
||||||
});
|
});
|
||||||
|
|
@ -886,6 +970,20 @@ onMounted(async () => {
|
||||||
>
|
>
|
||||||
<q-space />
|
<q-space />
|
||||||
<div>
|
<div>
|
||||||
|
<q-btn
|
||||||
|
v-if="
|
||||||
|
tabs === 'PENDING' &&
|
||||||
|
statusCheckEdit == 'PENDING' &&
|
||||||
|
isConfirmEdit
|
||||||
|
"
|
||||||
|
flat
|
||||||
|
round
|
||||||
|
color="blue"
|
||||||
|
icon="upload"
|
||||||
|
@click="handUploadFile()"
|
||||||
|
>
|
||||||
|
<q-tooltip>อัปโหลดไฟล์แก้ไข</q-tooltip>
|
||||||
|
</q-btn>
|
||||||
<q-btn
|
<q-btn
|
||||||
flat
|
flat
|
||||||
round
|
round
|
||||||
|
|
@ -893,7 +991,9 @@ onMounted(async () => {
|
||||||
icon="download"
|
icon="download"
|
||||||
:disable="rows.length == 0"
|
:disable="rows.length == 0"
|
||||||
@click="exportToExcel()"
|
@click="exportToExcel()"
|
||||||
/>
|
>
|
||||||
|
<q-tooltip>ดาวน์โหลดไฟล์</q-tooltip>
|
||||||
|
</q-btn>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<q-input
|
<q-input
|
||||||
|
|
@ -1724,6 +1824,13 @@ onMounted(async () => {
|
||||||
:fetch-data="fetchData"
|
:fetch-data="fetchData"
|
||||||
:columns="columns"
|
:columns="columns"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<DialogExcelPreview
|
||||||
|
v-model:modal="excelPreviewModal"
|
||||||
|
:file="selectedExcelFile"
|
||||||
|
@confirm="onConfirmUpload"
|
||||||
|
@cancel="onCancelUpload"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped></style>
|
<style scoped></style>
|
||||||
|
|
|
||||||
|
|
@ -54,6 +54,7 @@ const reason = ref<string>(""); //หมายเหตุ
|
||||||
const status = ref<string>("");
|
const status = ref<string>("");
|
||||||
const fullName = ref<string>("");
|
const fullName = ref<string>("");
|
||||||
const mianData = ref<MainData>();
|
const mianData = ref<MainData>();
|
||||||
|
const typeCommand = ref<string>(""); //ประเภทคำสั่ง
|
||||||
|
|
||||||
/** fetch รายละเอียดการปรับระดับชั้นงานลูกจ้าง*/
|
/** fetch รายละเอียดการปรับระดับชั้นงานลูกจ้าง*/
|
||||||
async function fecthappointmentByid() {
|
async function fecthappointmentByid() {
|
||||||
|
|
@ -79,6 +80,7 @@ async function fecthappointmentByid() {
|
||||||
salary.value = data.salary ?? 0;
|
salary.value = data.salary ?? 0;
|
||||||
reason.value = data.reason;
|
reason.value = data.reason;
|
||||||
date.value = data.positionDate;
|
date.value = data.positionDate;
|
||||||
|
typeCommand.value = data.typeCommand;
|
||||||
})
|
})
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
messageError($q, e);
|
messageError($q, e);
|
||||||
|
|
@ -323,7 +325,10 @@ onMounted(async () => {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-12"><q-separator /></div>
|
<div class="col-12"><q-separator /></div>
|
||||||
<div class="col-xs-6 col-sm-6 row items-center">
|
<div
|
||||||
|
class="col-xs-6 col-sm-6 row items-center"
|
||||||
|
v-if="typeCommand !== 'MOVE'"
|
||||||
|
>
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<datepicker
|
<datepicker
|
||||||
:readonly="!edit"
|
:readonly="!edit"
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,7 @@ const date = ref<Date | null>(null); //ดำรงตำแหน่งใน
|
||||||
const reason = ref<string>(""); //หมายเหตุ
|
const reason = ref<string>(""); //หมายเหตุ
|
||||||
const status = ref<string>("");
|
const status = ref<string>("");
|
||||||
const fullName = ref<string>("");
|
const fullName = ref<string>("");
|
||||||
|
const typeCommand = ref<string>(""); //ประเภทคำสั่ง
|
||||||
|
|
||||||
/** fetch รายละเอียดการแต่งตั้ง-เลื่อน-ย้าย*/
|
/** fetch รายละเอียดการแต่งตั้ง-เลื่อน-ย้าย*/
|
||||||
async function fecthappointmentByid() {
|
async function fecthappointmentByid() {
|
||||||
|
|
@ -61,6 +62,7 @@ async function fecthappointmentByid() {
|
||||||
}`;
|
}`;
|
||||||
|
|
||||||
status.value = data.status;
|
status.value = data.status;
|
||||||
|
typeCommand.value = data.typeCommand;
|
||||||
educationOld.value = data.educationOld ?? "-";
|
educationOld.value = data.educationOld ?? "-";
|
||||||
organizationPositionOld.value = data.organizationPositionOld;
|
organizationPositionOld.value = data.organizationPositionOld;
|
||||||
positionTypeOld.value = data.positionTypeOld;
|
positionTypeOld.value = data.positionTypeOld;
|
||||||
|
|
@ -313,7 +315,10 @@ onMounted(() => {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-12"><q-separator /></div>
|
<div class="col-12"><q-separator /></div>
|
||||||
<div class="col-xs-6 col-sm-6 row items-center">
|
<div
|
||||||
|
class="col-xs-6 col-sm-6 row items-center"
|
||||||
|
v-if="typeCommand !== 'MOVE'"
|
||||||
|
>
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<datepicker
|
<datepicker
|
||||||
:readonly="!edit"
|
:readonly="!edit"
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
import { ref, onMounted, watch } from "vue";
|
import { ref, onMounted, watch } from "vue";
|
||||||
|
|
||||||
/** importType*/
|
/** importType*/
|
||||||
import type { QTableProps } from "quasar";
|
import { type QTableProps } from "quasar";
|
||||||
import type {
|
import type {
|
||||||
Positions,
|
Positions,
|
||||||
FormPosType,
|
FormPosType,
|
||||||
|
|
@ -22,14 +22,14 @@ const store = useSelectOrgStore();
|
||||||
/** props*/
|
/** props*/
|
||||||
const selected = defineModel("selectedPos", { required: true }); //ตำแหน่งที่เลือก
|
const selected = defineModel("selectedPos", { required: true }); //ตำแหน่งที่เลือก
|
||||||
const positionId = defineModel<string>("positionId", { required: true }); //id ตำแหน่งที่เลือก
|
const positionId = defineModel<string>("positionId", { required: true }); //id ตำแหน่งที่เลือก
|
||||||
const seletcId = defineModel<string>("seletcId", { required: true }); // ตำแหน่งที่เลือก
|
const selectId = defineModel<string>("selectId", { required: true }); // ตำแหน่งที่เลือก
|
||||||
const date = defineModel<Date>("datePos", { required: true }); //วันยที่รายงานคัว
|
const date = defineModel<Date | null>("datePos", { required: true }); //วันยที่รายงานคัว
|
||||||
const positionData = defineModel<any[]>("position", { required: true }); //ข้อมูลรายการเลขที่ตำแหน่ง
|
const positionData = defineModel<any[]>("position", { required: true }); //ข้อมูลรายการเลขที่ตำแหน่ง
|
||||||
const isAll = defineModel<boolean>("isAll", { required: true }); //แสดงตำแหน่งทั้งหมด
|
const isAll = defineModel<boolean>("isAll", { required: true }); //แสดงตำแหน่งทั้งหมด
|
||||||
const isBlank = defineModel<boolean>("isBlank", { required: true }); //แสดงเฉพาะตำแหน่งว่าง
|
const isBlank = defineModel<boolean>("isBlank", { required: true }); //แสดงเฉพาะตำแหน่งว่าง
|
||||||
const isPosition = defineModel<string>("isPosition", { required: true });
|
const isPosition = defineModel<string>("isPosition", { required: true });
|
||||||
// const isPositionOld = defineModel<boolean>("isPositionOld", { required: true }); //แสดงตำแหน่งที่ตรงกับประเภทและระดับเดิม
|
// const isPositionOld = defineModel<boolean>("isPositionOld", { required: true }); //แสดงตำแหน่งที่ตรงกับประเภทและระดับเดิม
|
||||||
const posType = defineModel<FormPosType>("posType", { required: true }); //ตำแหน่งประเภท
|
const posType = defineModel<FormPosType | null>("posType", { required: true }); //ตำแหน่งประเภท
|
||||||
const posLevel = defineModel<string>("posLevel", { required: true }); //ระดับตำแหน่ง
|
const posLevel = defineModel<string>("posLevel", { required: true }); //ระดับตำแหน่ง
|
||||||
const optionPosType = defineModel<FormPosType[]>("optionPosType", {
|
const optionPosType = defineModel<FormPosType[]>("optionPosType", {
|
||||||
required: true,
|
required: true,
|
||||||
|
|
@ -47,6 +47,7 @@ const props = defineProps({
|
||||||
onPosType: Function,
|
onPosType: Function,
|
||||||
nodeId: String,
|
nodeId: String,
|
||||||
nodeLevel: Number,
|
nodeLevel: Number,
|
||||||
|
isLoadPosition: Boolean,
|
||||||
});
|
});
|
||||||
|
|
||||||
//Table
|
//Table
|
||||||
|
|
@ -213,9 +214,9 @@ async function onClickSelectPos(id: string) {
|
||||||
// หาตำแหน่ง
|
// หาตำแหน่ง
|
||||||
if (position) {
|
if (position) {
|
||||||
rowsPosition.value = position.positions;
|
rowsPosition.value = position.positions;
|
||||||
if (seletcId.value) {
|
if (selectId.value) {
|
||||||
selected.value = rowsPosition.value.filter(
|
selected.value = rowsPosition.value.filter(
|
||||||
(e) => e.id === seletcId.value
|
(e) => e.id === selectId.value
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -248,15 +249,20 @@ watch(positionData, (newVal, oldVal) => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.isLoadPosition,
|
||||||
|
(newVal) => {
|
||||||
|
if (newVal && positionId.value) {
|
||||||
|
onClickSelectPos(positionId.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ทำงานเมื่อ Components ถูกเรียกใช้งาน
|
* ทำงานเมื่อ Components ถูกเรียกใช้งาน
|
||||||
*/
|
*/
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
if (positionId.value) {
|
if (!positionId.value) {
|
||||||
setTimeout(async () => {
|
|
||||||
await onClickSelectPos(positionId.value);
|
|
||||||
}, 1000);
|
|
||||||
} else {
|
|
||||||
positionRows.value = positionData.value;
|
positionRows.value = positionData.value;
|
||||||
positionRowsData.value = positionData.value;
|
positionRowsData.value = positionData.value;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { onMounted, ref, watch, reactive } from "vue";
|
import { onMounted, ref, watch } from "vue";
|
||||||
import { useQuasar } from "quasar";
|
import { useQuasar } from "quasar";
|
||||||
|
|
||||||
import { useRoute } from "vue-router";
|
import { useRoute } from "vue-router";
|
||||||
|
|
@ -11,6 +11,7 @@ import { useStructureTree } from "@/stores/structureTree";
|
||||||
|
|
||||||
/** importType*/
|
/** importType*/
|
||||||
import type {
|
import type {
|
||||||
|
DataList,
|
||||||
PositionMaim,
|
PositionMaim,
|
||||||
PositionNo,
|
PositionNo,
|
||||||
Positions,
|
Positions,
|
||||||
|
|
@ -41,17 +42,14 @@ const {
|
||||||
|
|
||||||
/**props*/
|
/**props*/
|
||||||
const modal = defineModel<boolean>("modal", { required: true });
|
const modal = defineModel<boolean>("modal", { required: true });
|
||||||
const props = defineProps({
|
|
||||||
dataRow: {
|
interface Props {
|
||||||
type: Object,
|
dataRow?: DataList;
|
||||||
require: true,
|
fetchTable?: () => Promise<void>;
|
||||||
},
|
fetchStatCard?: () => Promise<void>;
|
||||||
fetchTable: {
|
}
|
||||||
type: Function,
|
|
||||||
require: true,
|
const props = defineProps<Props>();
|
||||||
},
|
|
||||||
fetchStatCard: { type: Function, require: true },
|
|
||||||
});
|
|
||||||
|
|
||||||
/** Tree*/
|
/** Tree*/
|
||||||
const nodeId = ref<string>("");
|
const nodeId = ref<string>("");
|
||||||
|
|
@ -65,15 +63,16 @@ const expanded = ref<string[]>([]);
|
||||||
const positionUse = ref<string[]>([]);
|
const positionUse = ref<string[]>([]);
|
||||||
const positionNo = ref<DataPositionNo[]>([]);
|
const positionNo = ref<DataPositionNo[]>([]);
|
||||||
const positionId = ref<string>("");
|
const positionId = ref<string>("");
|
||||||
const seletcId = ref<string>("");
|
const selectId = ref<string>("");
|
||||||
const posType = ref<FormPosType | null>(null);
|
const posType = ref<FormPosType | null>(null);
|
||||||
const posLevel = ref<string>("");
|
const posLevel = ref<string>("");
|
||||||
const selectedPos = ref<any[]>([]);
|
const selectedPos = ref<Positions[]>([]);
|
||||||
const datePos = ref<Date>(new Date());
|
const datePos = ref<Date | null>(new Date());
|
||||||
const posMasterMain = ref<any[]>([]);
|
const posMasterMain = ref<PositionMaim[]>([]);
|
||||||
const orgRevisionId = ref<string>("");
|
const orgRevisionId = ref<string>("");
|
||||||
const optionPosType = ref<FormPosType[]>([]);
|
const optionPosType = ref<FormPosType[]>([]);
|
||||||
const optionPosLevel = ref<FormPosLevel[]>([]);
|
const optionPosLevel = ref<FormPosLevel[]>([]);
|
||||||
|
const isLoadPosition = ref<boolean>(false);
|
||||||
|
|
||||||
/** function เรียกข้อมูลโครงสร้าง แบบปัจุบันและ แบบร่าง*/
|
/** function เรียกข้อมูลโครงสร้าง แบบปัจุบันและ แบบร่าง*/
|
||||||
async function fetchStructure() {
|
async function fetchStructure() {
|
||||||
|
|
@ -91,12 +90,14 @@ async function fetchStructure() {
|
||||||
*/
|
*/
|
||||||
function updateSelected(data: TreeMain) {
|
function updateSelected(data: TreeMain) {
|
||||||
if (props?.dataRow?.nodeId === data.orgTreeId) {
|
if (props?.dataRow?.nodeId === data.orgTreeId) {
|
||||||
positionId.value = props?.dataRow?.posmasterId;
|
positionId.value = props?.dataRow?.posmasterId ?? "";
|
||||||
seletcId.value = props?.dataRow?.positionId;
|
selectId.value = props?.dataRow?.positionId ?? "";
|
||||||
datePos.value = props?.dataRow?.reportingDate;
|
datePos.value = props?.dataRow?.reportingDate
|
||||||
|
? new Date(props.dataRow.reportingDate)
|
||||||
|
: new Date();
|
||||||
} else {
|
} else {
|
||||||
positionId.value = "";
|
positionId.value = "";
|
||||||
seletcId.value = "";
|
selectId.value = "";
|
||||||
selectedPos.value = [];
|
selectedPos.value = [];
|
||||||
datePos.value = new Date();
|
datePos.value = new Date();
|
||||||
}
|
}
|
||||||
|
|
@ -117,6 +118,8 @@ const isPosition = ref<string>("exam");
|
||||||
// const isPositionOld = ref<boolean>(false);
|
// const isPositionOld = ref<boolean>(false);
|
||||||
async function fetchDataTable(id: string, level: number = 0) {
|
async function fetchDataTable(id: string, level: number = 0) {
|
||||||
showLoader();
|
showLoader();
|
||||||
|
isLoadPosition.value = false;
|
||||||
|
positionNo.value = [];
|
||||||
const body = {
|
const body = {
|
||||||
node: level,
|
node: level,
|
||||||
nodeId: id,
|
nodeId: id,
|
||||||
|
|
@ -150,7 +153,7 @@ async function fetchDataTable(id: string, level: number = 0) {
|
||||||
if (p.length !== 0) {
|
if (p.length !== 0) {
|
||||||
const a = p.find((el: Positions) => el.positionIsSelected === true);
|
const a = p.find((el: Positions) => el.positionIsSelected === true);
|
||||||
const { id, ...rest } = a ? a : p[0];
|
const { id, ...rest } = a ? a : p[0];
|
||||||
const data: any = { ...e, ...rest };
|
const data: PositionMaim = { ...e, ...rest } as PositionMaim;
|
||||||
dataMain.push(data);
|
dataMain.push(data);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -162,21 +165,20 @@ async function fetchDataTable(id: string, level: number = 0) {
|
||||||
(e) => e !== props.dataRow?.posmasterId
|
(e) => e !== props.dataRow?.posmasterId
|
||||||
);
|
);
|
||||||
|
|
||||||
positionNo.value = posMain.filter((e: any) => !newUse.includes(e.id));
|
positionNo.value = posMain.filter((e: DataPositionNo) => !newUse.includes(e.id));
|
||||||
} else {
|
} else {
|
||||||
positionNo.value = posMain.filter(
|
positionNo.value = posMain.filter(
|
||||||
(e: any) => !positionUse.value.includes(e.id)
|
(e: DataPositionNo) => !positionUse.value.includes(e.id)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isLoadPosition.value = true;
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
messageError($q, err);
|
messageError($q, err);
|
||||||
hideLoader();
|
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
setTimeout(() => {
|
hideLoader();
|
||||||
hideLoader();
|
|
||||||
}, 1000);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -198,9 +200,11 @@ async function fetchPosFind(level: number, id: string) {
|
||||||
|
|
||||||
expanded.value = data;
|
expanded.value = data;
|
||||||
nodeId.value = id;
|
nodeId.value = id;
|
||||||
positionId.value = props?.dataRow?.posmasterId;
|
positionId.value = props?.dataRow?.posmasterId ?? "";
|
||||||
seletcId.value = props?.dataRow?.positionId;
|
selectId.value = props?.dataRow?.positionId ?? "";
|
||||||
datePos.value = props?.dataRow?.reportingDate;
|
datePos.value = props?.dataRow?.reportingDate
|
||||||
|
? new Date(props.dataRow.reportingDate)
|
||||||
|
: new Date();
|
||||||
|
|
||||||
fetchDataTable(nodeId.value, level);
|
fetchDataTable(nodeId.value, level);
|
||||||
})
|
})
|
||||||
|
|
@ -212,12 +216,14 @@ async function fetchPosFind(level: number, id: string) {
|
||||||
|
|
||||||
/** function บันทึกข้อมูลตำแหน่ง*/
|
/** function บันทึกข้อมูลตำแหน่ง*/
|
||||||
async function onClickSubmit() {
|
async function onClickSubmit() {
|
||||||
const dataPosMaster = await posMasterMain.value?.find(
|
const dataPosMaster = posMasterMain.value?.find(
|
||||||
(e: any) => e.id === positionId.value
|
(e) => e.id === positionId.value
|
||||||
);
|
);
|
||||||
|
|
||||||
if (selectedPos.value.length === 0) {
|
if (selectedPos.value.length === 0) {
|
||||||
dialogMessageNotify($q, "กรุณาเลือกตำแหน่ง");
|
dialogMessageNotify($q, "กรุณาเลือกตำแหน่ง");
|
||||||
|
} else if (!dataPosMaster) {
|
||||||
|
dialogMessageNotify($q, "ไม่พบข้อมูลตำแหน่ง");
|
||||||
} else {
|
} else {
|
||||||
dialogConfirm($q, async () => {
|
dialogConfirm($q, async () => {
|
||||||
showLoader();
|
showLoader();
|
||||||
|
|
@ -272,6 +278,9 @@ function clearData() {
|
||||||
posLevel.value = "";
|
posLevel.value = "";
|
||||||
isPosition.value = "exam";
|
isPosition.value = "exam";
|
||||||
filterTree.value = "";
|
filterTree.value = "";
|
||||||
|
datePos.value = new Date();
|
||||||
|
isLoadPosition.value = false;
|
||||||
|
positionNo.value = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
/** callback function เมื่อมีการเปิด popup*/
|
/** callback function เมื่อมีการเปิด popup*/
|
||||||
|
|
@ -280,9 +289,8 @@ watch(
|
||||||
async () => {
|
async () => {
|
||||||
if (modal.value) {
|
if (modal.value) {
|
||||||
await fetchPositionUes();
|
await fetchPositionUes();
|
||||||
|
|
||||||
if (props?.dataRow?.node !== null && props?.dataRow?.nodeId !== null) {
|
if (props?.dataRow?.node !== null && props?.dataRow?.nodeId !== null) {
|
||||||
await fetchPosFind(props?.dataRow?.node, props?.dataRow?.nodeId);
|
await fetchPosFind(props?.dataRow?.node ?? 0, props?.dataRow?.nodeId ?? "");
|
||||||
} else {
|
} else {
|
||||||
expanded.value = [];
|
expanded.value = [];
|
||||||
}
|
}
|
||||||
|
|
@ -323,8 +331,7 @@ async function getOrgPosType() {
|
||||||
})
|
})
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
messageError($q, e);
|
messageError($q, e);
|
||||||
})
|
});
|
||||||
.finally(() => {});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function onPosType() {
|
function onPosType() {
|
||||||
|
|
@ -336,28 +343,15 @@ function onPosType() {
|
||||||
}
|
}
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => isAll.value,
|
[isAll, isBlank, () => isPosition.value],
|
||||||
(value, oldVal) => {
|
([newAll, newBlank, newPos], [oldAll, oldBlank, oldPos]) => {
|
||||||
if (value !== oldVal) {
|
const shouldFetch = (newAll !== oldAll) || (newBlank !== oldBlank);
|
||||||
|
const isSelectMode = newPos === "select" && oldPos !== "select";
|
||||||
|
|
||||||
|
if (shouldFetch || isSelectMode) {
|
||||||
fetchDataTable(nodeId.value, nodeLevel.value);
|
fetchDataTable(nodeId.value, nodeLevel.value);
|
||||||
}
|
}
|
||||||
}
|
if (isSelectMode) {
|
||||||
);
|
|
||||||
|
|
||||||
watch(
|
|
||||||
() => isBlank.value,
|
|
||||||
(value, oldVal) => {
|
|
||||||
if (value !== oldVal) {
|
|
||||||
fetchDataTable(nodeId.value, nodeLevel.value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
watch(
|
|
||||||
() => isPosition.value === "select",
|
|
||||||
(value, oldVal) => {
|
|
||||||
if (value !== oldVal) {
|
|
||||||
fetchDataTable(nodeId.value, nodeLevel.value);
|
|
||||||
getOrgPosType();
|
getOrgPosType();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -458,15 +452,15 @@ onMounted(() => {
|
||||||
:name="item"
|
:name="item"
|
||||||
>
|
>
|
||||||
<CardPosition
|
<CardPosition
|
||||||
v-model:position="positionNo as []"
|
v-model:position="positionNo"
|
||||||
v-model:selectedPos="selectedPos"
|
v-model:selectedPos="selectedPos"
|
||||||
v-model:datePos="datePos"
|
v-model:datePos="datePos"
|
||||||
v-model:positionId="positionId"
|
v-model:positionId="positionId"
|
||||||
v-model:seletcId="seletcId"
|
v-model:selectId="selectId"
|
||||||
v-model:is-all="isAll"
|
v-model:is-all="isAll"
|
||||||
v-model:is-blank="isBlank"
|
v-model:is-blank="isBlank"
|
||||||
v-model:is-position="isPosition"
|
v-model:is-position="isPosition"
|
||||||
v-model:pos-type="posType as FormPosType"
|
v-model:pos-type="posType"
|
||||||
v-model:pos-level="posLevel"
|
v-model:pos-level="posLevel"
|
||||||
v-model:option-pos-type="optionPosType"
|
v-model:option-pos-type="optionPosType"
|
||||||
v-model:option-pos-level="optionPosLevel"
|
v-model:option-pos-level="optionPosLevel"
|
||||||
|
|
@ -474,7 +468,8 @@ onMounted(() => {
|
||||||
:on-pos-type="onPosType"
|
:on-pos-type="onPosType"
|
||||||
:node-id="nodeId"
|
:node-id="nodeId"
|
||||||
:node-level="nodeLevel"
|
:node-level="nodeLevel"
|
||||||
:bma-officer="props.dataRow?.bmaOfficer"
|
:bma-officer="props.dataRow?.bmaOfficer ?? ''"
|
||||||
|
:is-load-position="isLoadPosition"
|
||||||
/>
|
/>
|
||||||
</q-tab-panel>
|
</q-tab-panel>
|
||||||
</q-tab-panels>
|
</q-tab-panels>
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import { checkPermission } from "@/utils/permissions";
|
||||||
import { useCounterMixin } from "@/stores/mixin";
|
import { useCounterMixin } from "@/stores/mixin";
|
||||||
import { usePlacementDataStore } from "@/modules/05_placement/store";
|
import { usePlacementDataStore } from "@/modules/05_placement/store";
|
||||||
import { useMenuDataStore } from "@/stores/menuList";
|
import { useMenuDataStore } from "@/stores/menuList";
|
||||||
|
import { validateFileSize } from "@/utils/function";
|
||||||
import avatar from "@/assets/avatar_user.jpg";
|
import avatar from "@/assets/avatar_user.jpg";
|
||||||
|
|
||||||
import type { PartialTableName } from "@/modules/05_placement/interface/request/placement";
|
import type { PartialTableName } from "@/modules/05_placement/interface/request/placement";
|
||||||
|
|
@ -967,6 +968,28 @@ function onUpdateStatus(id: string) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function onUpdateDraftStatus(id: string) {
|
||||||
|
dialogConfirm(
|
||||||
|
$q,
|
||||||
|
async () => {
|
||||||
|
showLoader();
|
||||||
|
try {
|
||||||
|
await http.post(config.API.placementUpdateDraftStatus, {
|
||||||
|
personalId: id,
|
||||||
|
});
|
||||||
|
await success($q, "บันทึกสำเร็จ");
|
||||||
|
await getTable();
|
||||||
|
} catch (error) {
|
||||||
|
messageError($q, error);
|
||||||
|
} finally {
|
||||||
|
hideLoader();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ยืนยันการยกเลิกการส่งตัว",
|
||||||
|
"ต้องการยกเลิกการส่งตัวรายชื่อนี้ใช่หรือไม่ ?"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
await getWorkFlow();
|
await getWorkFlow();
|
||||||
await getTable();
|
await getTable();
|
||||||
|
|
@ -1029,6 +1052,31 @@ onMounted(async () => {
|
||||||
</q-item-section>
|
</q-item-section>
|
||||||
<q-item-section>รายละเอียด</q-item-section>
|
<q-item-section>รายละเอียด</q-item-section>
|
||||||
</q-item>
|
</q-item>
|
||||||
|
<q-item
|
||||||
|
v-if="
|
||||||
|
checkPermission($route)?.attrIsUpdate &&
|
||||||
|
props.row.isDraft &&
|
||||||
|
props.row.statusId === 'PREPARE-CONTAIN' &&
|
||||||
|
(DataStore.isOfficer ||
|
||||||
|
checkPermission($route)?.attrOwnership == 'OWNER')
|
||||||
|
"
|
||||||
|
clickable
|
||||||
|
v-close-popup
|
||||||
|
@click="onUpdateDraftStatus(props.row.personalId)"
|
||||||
|
>
|
||||||
|
<q-item-section
|
||||||
|
style="min-width: 0px"
|
||||||
|
avatar
|
||||||
|
class="q-py-sm"
|
||||||
|
>
|
||||||
|
<q-icon
|
||||||
|
color="red"
|
||||||
|
size="xs"
|
||||||
|
name="mdi-account-arrow-left-outline"
|
||||||
|
/>
|
||||||
|
</q-item-section>
|
||||||
|
<q-item-section>ยกเลิกการส่งตัว</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
|
||||||
<q-item
|
<q-item
|
||||||
v-if="
|
v-if="
|
||||||
|
|
@ -1497,7 +1545,10 @@ onMounted(async () => {
|
||||||
:label="`${'เลือกไฟล์เอกสารหลักฐาน'}`"
|
:label="`${'เลือกไฟล์เอกสารหลักฐาน'}`"
|
||||||
outlined
|
outlined
|
||||||
use-chips
|
use-chips
|
||||||
:rules="[(val:string) => !!val || 'กรุณาเลือกไฟล์เอกสารหลักฐาน']"
|
:rules="[
|
||||||
|
(val) => !!val || 'กรุณาเลือกไฟล์เอกสารหลักฐาน',
|
||||||
|
(val) => validateFileSize(val),
|
||||||
|
]"
|
||||||
multiple
|
multiple
|
||||||
@update:model-value="clickEditRow"
|
@update:model-value="clickEditRow"
|
||||||
class="q-py-sm"
|
class="q-py-sm"
|
||||||
|
|
|
||||||
|
|
@ -89,7 +89,9 @@ const columns2 = ref<QTableProps["columns"]>([
|
||||||
sort: (a: string, b: string) =>
|
sort: (a: string, b: string) =>
|
||||||
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
|
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
|
||||||
format(val, row) {
|
format(val, row) {
|
||||||
return `${row.prefix ?? ""}${row.firstName ?? ""} ${row.lastName ?? ""}`;
|
return `${row.rank ? row.rank : row.prefix ?? ""}${row.firstName ?? ""} ${
|
||||||
|
row.lastName ?? ""
|
||||||
|
}`;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -110,9 +112,11 @@ const columns2 = ref<QTableProps["columns"]>([
|
||||||
headerStyle: "font-size: 14px",
|
headerStyle: "font-size: 14px",
|
||||||
style: "font-size: 14px",
|
style: "font-size: 14px",
|
||||||
format(val, row) {
|
format(val, row) {
|
||||||
return row.positionTypeOld
|
return row.positionTypeOld && row.positionTypeOl !== "-"
|
||||||
? `${row.positionTypeOld}${
|
? `${row.positionTypeOld}${
|
||||||
row.positionLevelOld ? `(${row.positionLevelOld})` : ""
|
row.positionLevelOld && row.positionLevelOld !== "-"
|
||||||
|
? `(${row.positionLevelOld})`
|
||||||
|
: ""
|
||||||
}`
|
}`
|
||||||
: "";
|
: "";
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,7 @@ const informaData = ref<FormAddPerson>({
|
||||||
employeeType: null,
|
employeeType: null,
|
||||||
employeeClass: null,
|
employeeClass: null,
|
||||||
profileType: null,
|
profileType: null,
|
||||||
|
rank: "",
|
||||||
});
|
});
|
||||||
|
|
||||||
// รายการข้อมูลทั้งหมด
|
// รายการข้อมูลทั้งหมด
|
||||||
|
|
@ -60,6 +61,7 @@ const Ops = ref<InformationOps>({
|
||||||
religionOps: [],
|
religionOps: [],
|
||||||
employeeClassOps: [],
|
employeeClassOps: [],
|
||||||
employeeTypeOps: [],
|
employeeTypeOps: [],
|
||||||
|
rankOps: [],
|
||||||
});
|
});
|
||||||
// ข้อมูลเมื่อเลือกแล้ว
|
// ข้อมูลเมื่อเลือกแล้ว
|
||||||
const OpsFilter = ref<InformationOps>({
|
const OpsFilter = ref<InformationOps>({
|
||||||
|
|
@ -71,6 +73,7 @@ const OpsFilter = ref<InformationOps>({
|
||||||
religionOps: [],
|
religionOps: [],
|
||||||
employeeClassOps: [],
|
employeeClassOps: [],
|
||||||
employeeTypeOps: [],
|
employeeTypeOps: [],
|
||||||
|
rankOps: [],
|
||||||
});
|
});
|
||||||
|
|
||||||
// รูป profile
|
// รูป profile
|
||||||
|
|
@ -135,6 +138,16 @@ async function fetchPerson() {
|
||||||
});
|
});
|
||||||
Ops.value.religionOps = optionreligions;
|
Ops.value.religionOps = optionreligions;
|
||||||
OpsFilter.value.religionOps = optionreligions;
|
OpsFilter.value.religionOps = optionreligions;
|
||||||
|
|
||||||
|
let rank: DataOption[] = [];
|
||||||
|
data.rank.map((r: DataOptioninfo) => {
|
||||||
|
rank.push({
|
||||||
|
id: r.id.toString(),
|
||||||
|
name: r.name.toString(),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
Ops.value.rankOps = rank;
|
||||||
|
OpsFilter.value.rankOps = rank;
|
||||||
})
|
})
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
messageError($q, e);
|
messageError($q, e);
|
||||||
|
|
@ -204,7 +217,13 @@ function filterSelector(val: string, update: Function, refData: string) {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
|
case "rankOps":
|
||||||
|
update(() => {
|
||||||
|
Ops.value.rankOps = OpsFilter.value.rankOps.filter(
|
||||||
|
(v: DataOption) => v.name.toLowerCase().indexOf(newVal) > -1
|
||||||
|
);
|
||||||
|
});
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -227,7 +246,7 @@ function onSubmit() {
|
||||||
if (fileData.value != null) formData.append("File", fileData.value); //แก้ไขรูป
|
if (fileData.value != null) formData.append("File", fileData.value); //แก้ไขรูป
|
||||||
if (informaData.value.citizenId != undefined)
|
if (informaData.value.citizenId != undefined)
|
||||||
formData.append("citizenId", informaData.value.citizenId);
|
formData.append("citizenId", informaData.value.citizenId);
|
||||||
if (informaData.value.prefix != undefined)
|
if (informaData.value.prefix != undefined && informaData.value.prefix != "")
|
||||||
formData.append("prefix", informaData.value.prefix);
|
formData.append("prefix", informaData.value.prefix);
|
||||||
if (informaData.value.firstName != undefined)
|
if (informaData.value.firstName != undefined)
|
||||||
formData.append("firstName", informaData.value.firstName);
|
formData.append("firstName", informaData.value.firstName);
|
||||||
|
|
@ -256,6 +275,8 @@ function onSubmit() {
|
||||||
formData.append("employeeType", informaData.value.employeeType);
|
formData.append("employeeType", informaData.value.employeeType);
|
||||||
if (informaData.value.employeeClass != undefined)
|
if (informaData.value.employeeClass != undefined)
|
||||||
formData.append("employeeClass", informaData.value.employeeClass);
|
formData.append("employeeClass", informaData.value.employeeClass);
|
||||||
|
if (informaData.value.rank != undefined && informaData.value.rank != "")
|
||||||
|
formData.append("rank", informaData.value.rank);
|
||||||
|
|
||||||
dialogConfirm($q, async () => {
|
dialogConfirm($q, async () => {
|
||||||
showLoader();
|
showLoader();
|
||||||
|
|
@ -289,6 +310,15 @@ function updateBirthDate(v: Date) {
|
||||||
age.value = calculateAge(v);
|
age.value = calculateAge(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function prefixRankRule() {
|
||||||
|
return [
|
||||||
|
() =>
|
||||||
|
!!informaData.value.rank ||
|
||||||
|
!!informaData.value.prefix ||
|
||||||
|
"กรุณาเลือกคำนำหน้าชื่อ หรือยศ",
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ทำงานเมื่อมีการเรียกใช้ Components
|
* ทำงานเมื่อมีการเรียกใช้ Components
|
||||||
*/
|
*/
|
||||||
|
|
@ -383,7 +413,7 @@ onMounted(async () => {
|
||||||
</div>
|
</div>
|
||||||
<q-card-section class="q-px-lg">
|
<q-card-section class="q-px-lg">
|
||||||
<div class="row q-col-gutter-sm">
|
<div class="row q-col-gutter-sm">
|
||||||
<div class="col-3">
|
<div class="col-2">
|
||||||
<q-input
|
<q-input
|
||||||
bg-color="white"
|
bg-color="white"
|
||||||
outlined
|
outlined
|
||||||
|
|
@ -404,13 +434,14 @@ onMounted(async () => {
|
||||||
mask="#############"
|
mask="#############"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-3">
|
<div class="col-2">
|
||||||
<q-select
|
<q-select
|
||||||
bg-color="white"
|
bg-color="white"
|
||||||
v-model="informaData.prefix"
|
v-model="informaData.prefix"
|
||||||
label="คำนำหน้าชื่อ"
|
label="คำนำหน้าชื่อ"
|
||||||
outlined
|
outlined
|
||||||
dense
|
dense
|
||||||
|
clearable
|
||||||
lazy-rules
|
lazy-rules
|
||||||
class="inputgreen"
|
class="inputgreen"
|
||||||
:options="Ops.prefixOps"
|
:options="Ops.prefixOps"
|
||||||
|
|
@ -418,11 +449,8 @@ onMounted(async () => {
|
||||||
option-value="name"
|
option-value="name"
|
||||||
map-options
|
map-options
|
||||||
hide-bottom-space
|
hide-bottom-space
|
||||||
:rules="[
|
:rules="prefixRankRule()"
|
||||||
(val:string) => {
|
reactive-rules
|
||||||
return val.length > 0 || 'กรุณาเลือกคำนำหน้าชื่อ';
|
|
||||||
},
|
|
||||||
]"
|
|
||||||
emit-value
|
emit-value
|
||||||
use-input
|
use-input
|
||||||
hide-selected
|
hide-selected
|
||||||
|
|
@ -432,6 +460,32 @@ onMounted(async () => {
|
||||||
)"
|
)"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="col-2">
|
||||||
|
<q-select
|
||||||
|
bg-color="white"
|
||||||
|
v-model="informaData.rank"
|
||||||
|
label="ยศ"
|
||||||
|
outlined
|
||||||
|
dense
|
||||||
|
lazy-rules
|
||||||
|
clearable
|
||||||
|
class="inputgreen"
|
||||||
|
:options="Ops.rankOps"
|
||||||
|
option-label="name"
|
||||||
|
option-value="name"
|
||||||
|
map-options
|
||||||
|
hide-bottom-space
|
||||||
|
:rules="prefixRankRule()"
|
||||||
|
reactive-rules
|
||||||
|
emit-value
|
||||||
|
use-input
|
||||||
|
hide-selected
|
||||||
|
fill-input
|
||||||
|
@filter="(inputValue:string,
|
||||||
|
doneFn: Function) => filterSelector(inputValue, doneFn, 'rankOps'
|
||||||
|
)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<div class="col-3">
|
<div class="col-3">
|
||||||
<q-input
|
<q-input
|
||||||
bg-color="white"
|
bg-color="white"
|
||||||
|
|
|
||||||
|
|
@ -113,6 +113,7 @@ const Ops = ref<InformationOps>({
|
||||||
{ id: "gov", name: "งบประมาณเงินอุดหนุนรัฐบาล" },
|
{ id: "gov", name: "งบประมาณเงินอุดหนุนรัฐบาล" },
|
||||||
{ id: "bkk", name: "งบประมาณกรุงเทพมหานคร" },
|
{ id: "bkk", name: "งบประมาณกรุงเทพมหานคร" },
|
||||||
],
|
],
|
||||||
|
rankOps: [],
|
||||||
});
|
});
|
||||||
const OpsFilter = ref<InformationOps>({
|
const OpsFilter = ref<InformationOps>({
|
||||||
prefixOps: [],
|
prefixOps: [],
|
||||||
|
|
@ -129,6 +130,7 @@ const OpsFilter = ref<InformationOps>({
|
||||||
{ id: "gov", name: "งบประมาณเงินอุดหนุนรัฐบาล" },
|
{ id: "gov", name: "งบประมาณเงินอุดหนุนรัฐบาล" },
|
||||||
{ id: "bkk", name: "งบประมาณกรุงเทพมหานคร" },
|
{ id: "bkk", name: "งบประมาณกรุงเทพมหานคร" },
|
||||||
],
|
],
|
||||||
|
rankOps: [],
|
||||||
});
|
});
|
||||||
|
|
||||||
/** ฟังก์ชันดึงข้อมูลรายการข้อมูลเกี่ยวกับบุคคล (dropdown list)*/
|
/** ฟังก์ชันดึงข้อมูลรายการข้อมูลเกี่ยวกับบุคคล (dropdown list)*/
|
||||||
|
|
@ -186,6 +188,16 @@ async function fetchPerson() {
|
||||||
});
|
});
|
||||||
Ops.value.religionOps = optionreligions;
|
Ops.value.religionOps = optionreligions;
|
||||||
OpsFilter.value.religionOps = optionreligions;
|
OpsFilter.value.religionOps = optionreligions;
|
||||||
|
|
||||||
|
let rank: DataOption[] = [];
|
||||||
|
data.rank.map((r: DataOptioninfo) => {
|
||||||
|
rank.push({
|
||||||
|
id: r.id.toString(),
|
||||||
|
name: r.name.toString(),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
Ops.value.rankOps = rank;
|
||||||
|
OpsFilter.value.rankOps = rank;
|
||||||
})
|
})
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
messageError($q, e);
|
messageError($q, e);
|
||||||
|
|
@ -215,9 +227,9 @@ async function getData() {
|
||||||
}
|
}
|
||||||
rows.value = list;
|
rows.value = list;
|
||||||
profileId.value = data.profileId;
|
profileId.value = data.profileId;
|
||||||
title.value.fullname = `${data.prefix ?? ""}${data.firstName ?? ""} ${
|
title.value.fullname = `${data.rank ? data.rank : data.prefix ?? ""}${
|
||||||
data.lastName ?? ""
|
data.firstName ?? ""
|
||||||
}`;
|
} ${data.lastName ?? ""}`;
|
||||||
title.value.organizationPositionOld = data.organizationPositionOld ?? "-";
|
title.value.organizationPositionOld = data.organizationPositionOld ?? "-";
|
||||||
title.value.positionLevelOld = data.positionLevelOld ?? "-";
|
title.value.positionLevelOld = data.positionLevelOld ?? "-";
|
||||||
title.value.positionTypeOld = data.positionTypeOld ?? "-";
|
title.value.positionTypeOld = data.positionTypeOld ?? "-";
|
||||||
|
|
@ -230,6 +242,7 @@ async function getData() {
|
||||||
(data.prefix == "00000000-0000-0000-0000-000000000000"
|
(data.prefix == "00000000-0000-0000-0000-000000000000"
|
||||||
? null
|
? null
|
||||||
: data.prefix) ?? "",
|
: data.prefix) ?? "",
|
||||||
|
rank: data.rank ?? "",
|
||||||
firstname: data.firstName ?? "",
|
firstname: data.firstName ?? "",
|
||||||
lastname: data.lastName ?? "",
|
lastname: data.lastName ?? "",
|
||||||
birthDate:
|
birthDate:
|
||||||
|
|
@ -295,6 +308,7 @@ async function fetchData(data: any) {
|
||||||
(data.prefix == "00000000-0000-0000-0000-000000000000"
|
(data.prefix == "00000000-0000-0000-0000-000000000000"
|
||||||
? null
|
? null
|
||||||
: data.prefix) ?? "",
|
: data.prefix) ?? "",
|
||||||
|
rank: data.rank ?? "",
|
||||||
firstname: data.firstName ?? "",
|
firstname: data.firstName ?? "",
|
||||||
lastname: data.lastName ?? "",
|
lastname: data.lastName ?? "",
|
||||||
birthDate: data.dateOfBirth !== null ? new Date(data.dateOfBirth) : null,
|
birthDate: data.dateOfBirth !== null ? new Date(data.dateOfBirth) : null,
|
||||||
|
|
@ -436,6 +450,14 @@ function filterSelector(val: string, update: Function, refData: string) {
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case "rankOps":
|
||||||
|
update(() => {
|
||||||
|
Ops.value.rankOps = OpsFilter.value.rankOps.filter(
|
||||||
|
(v: DataOption) => v.name.toLowerCase().indexOf(newVal) > -1
|
||||||
|
);
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -470,6 +492,7 @@ function saveData() {
|
||||||
positionNumberOld: posNo.value,
|
positionNumberOld: posNo.value,
|
||||||
amount: 0,
|
amount: 0,
|
||||||
amountOld: salary.value,
|
amountOld: salary.value,
|
||||||
|
rank: informaData.value.rank,
|
||||||
};
|
};
|
||||||
showLoader();
|
showLoader();
|
||||||
http
|
http
|
||||||
|
|
@ -517,6 +540,15 @@ function updateBirthDate(v: Date) {
|
||||||
informaData.value.age = calculateAge(v);
|
informaData.value.age = calculateAge(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function prefixRankRule() {
|
||||||
|
return [
|
||||||
|
() =>
|
||||||
|
!!informaData.value.rank ||
|
||||||
|
!!informaData.value.prefixId ||
|
||||||
|
"กรุณาเลือกคำนำหน้าชื่อ หรือยศ",
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
/** ทำงานเมื่อมีการเรียกใช้ Components*/
|
/** ทำงานเมื่อมีการเรียกใช้ Components*/
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
await fetchPerson();
|
await fetchPerson();
|
||||||
|
|
@ -598,7 +630,7 @@ onMounted(async () => {
|
||||||
<div class="col-xs-12">
|
<div class="col-xs-12">
|
||||||
<div class="text-weight-bold text-grey">ข้อมูลส่วนตัว</div>
|
<div class="text-weight-bold text-grey">ข้อมูลส่วนตัว</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-xs-6 col-sm-3 col-md-3">
|
<div class="col-xs-6 col-sm-2 col-md-2">
|
||||||
<q-input
|
<q-input
|
||||||
:class="getClass(edit)"
|
:class="getClass(edit)"
|
||||||
hide-bottom-space
|
hide-bottom-space
|
||||||
|
|
@ -614,7 +646,7 @@ onMounted(async () => {
|
||||||
mask="#############"
|
mask="#############"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-xs-6 col-sm-3 col-md-3">
|
<div class="col-xs-6 col-sm-2 col-md-2">
|
||||||
<selector
|
<selector
|
||||||
:hide-dropdown-icon="!edit"
|
:hide-dropdown-icon="!edit"
|
||||||
hide-bottom-space
|
hide-bottom-space
|
||||||
|
|
@ -634,10 +666,42 @@ onMounted(async () => {
|
||||||
option-value="name"
|
option-value="name"
|
||||||
:label="`${'คำนำหน้าชื่อ'}`"
|
:label="`${'คำนำหน้าชื่อ'}`"
|
||||||
use-input
|
use-input
|
||||||
|
clearable
|
||||||
input-debounce="0"
|
input-debounce="0"
|
||||||
|
:rules="prefixRankRule()"
|
||||||
|
reactive-rules
|
||||||
@filter="(inputValue:string, doneFn:Function) => filterSelector(inputValue, doneFn,'prefixOps' ) "
|
@filter="(inputValue:string, doneFn:Function) => filterSelector(inputValue, doneFn,'prefixOps' ) "
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="col-xs-6 col-sm-2 col-md-2">
|
||||||
|
<selector
|
||||||
|
:hide-dropdown-icon="!edit"
|
||||||
|
hide-bottom-space
|
||||||
|
:class="getClass(edit)"
|
||||||
|
:readonly="!edit"
|
||||||
|
:borderless="!edit"
|
||||||
|
:outlined="edit"
|
||||||
|
dense
|
||||||
|
lazy-rules
|
||||||
|
v-model="informaData.rank"
|
||||||
|
emit-value
|
||||||
|
map-options
|
||||||
|
hide-selected
|
||||||
|
fill-input
|
||||||
|
:rules="prefixRankRule()"
|
||||||
|
option-label="name"
|
||||||
|
:options="Ops.rankOps"
|
||||||
|
option-value="name"
|
||||||
|
:label="`${'ยศ'}`"
|
||||||
|
reactive-rules
|
||||||
|
use-input
|
||||||
|
input-debounce="0"
|
||||||
|
@filter="(inputValue:string, doneFn:Function) => filterSelector(inputValue, doneFn,'rankOps' ) "
|
||||||
|
clearable
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="col-xs-6 col-sm-3 col-md-3">
|
<div class="col-xs-6 col-sm-3 col-md-3">
|
||||||
<q-input
|
<q-input
|
||||||
:class="getClass(edit)"
|
:class="getClass(edit)"
|
||||||
|
|
|
||||||
|
|
@ -201,6 +201,7 @@ watch(modal, (val) => {
|
||||||
hide-bottom-space
|
hide-bottom-space
|
||||||
dense
|
dense
|
||||||
label="คำค้น"
|
label="คำค้น"
|
||||||
|
@keydown.enter.prevent="onSearchData()"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<q-checkbox
|
<q-checkbox
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ interface InformationOps {
|
||||||
religionOps: DataOption[];
|
religionOps: DataOption[];
|
||||||
employeeClassOps: DataOption[];
|
employeeClassOps: DataOption[];
|
||||||
employeeTypeOps: DataOption[];
|
employeeTypeOps: DataOption[];
|
||||||
|
rankOps: DataOption[];
|
||||||
}
|
}
|
||||||
|
|
||||||
//ข้อมูลส่วนตัว
|
//ข้อมูลส่วนตัว
|
||||||
|
|
@ -63,6 +64,7 @@ interface FormAddPerson {
|
||||||
employeeType: string | null;
|
employeeType: string | null;
|
||||||
employeeClass: string | null;
|
employeeClass: string | null;
|
||||||
profileType: string | null;
|
profileType: string | null;
|
||||||
|
rank?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const defaultInformation: Information = {
|
const defaultInformation: Information = {
|
||||||
|
|
@ -83,6 +85,7 @@ const defaultInformation: Information = {
|
||||||
employeeType: null,
|
employeeType: null,
|
||||||
employeeClass: null,
|
employeeClass: null,
|
||||||
profileType: null,
|
profileType: null,
|
||||||
|
rank: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
export { defaultInformation };
|
export { defaultInformation };
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,24 @@
|
||||||
interface DataList {
|
interface DataList {
|
||||||
avatar: string;
|
avatar: string;
|
||||||
bmaOfficer: string;
|
bmaOfficer: string;
|
||||||
|
bmaOfficerCheck?: string;
|
||||||
deferment: boolean;
|
deferment: boolean;
|
||||||
draft: string;
|
draft: string;
|
||||||
examNumber: number;
|
examNumber: number;
|
||||||
fullName: string;
|
fullName: string;
|
||||||
idCard: string;
|
idCard: string;
|
||||||
name: string;
|
name: string;
|
||||||
|
node: number | null;
|
||||||
|
nodeId: string | null;
|
||||||
orgName: string | null;
|
orgName: string | null;
|
||||||
organizationName: string;
|
organizationName: string;
|
||||||
organizationShortName: string | null;
|
organizationShortName: string | null;
|
||||||
personalId: string;
|
personalId: string;
|
||||||
|
posLevelCandidateId: string | null;
|
||||||
|
posmasterId: string | null;
|
||||||
|
posTypeCandidateId: string | null;
|
||||||
positionCandidate: string;
|
positionCandidate: string;
|
||||||
|
positionId: string | null;
|
||||||
positionNumber: string | null;
|
positionNumber: string | null;
|
||||||
positionPath: string | null;
|
positionPath: string | null;
|
||||||
profilePhoto: string;
|
profilePhoto: string;
|
||||||
|
|
|
||||||
|
|
@ -110,7 +110,9 @@ const columns = ref<QTableProps["columns"]>([
|
||||||
sort: (a: string, b: string) =>
|
sort: (a: string, b: string) =>
|
||||||
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
|
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
|
||||||
format(val, row) {
|
format(val, row) {
|
||||||
return `${row.prefix ?? ""}${row.firstName ?? ""} ${row.lastName ?? ""}`;
|
return ` ${row.rank ? row.rank : row.prefix ?? ""}${
|
||||||
|
row.firstName ?? ""
|
||||||
|
} ${row.lastName ?? ""}`;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -131,9 +133,11 @@ const columns = ref<QTableProps["columns"]>([
|
||||||
headerStyle: "font-size: 14px",
|
headerStyle: "font-size: 14px",
|
||||||
style: "font-size: 14px",
|
style: "font-size: 14px",
|
||||||
format(val, row) {
|
format(val, row) {
|
||||||
return row.positionTypeOld
|
return row.positionTypeOld && row.positionTypeOld !== "-"
|
||||||
? `${row.positionTypeOld}${
|
? `${row.positionTypeOld}${
|
||||||
row.positionLevelOld ? `(${row.positionLevelOld})` : ""
|
row.positionLevelOld && row.positionLevelOld !== "-"
|
||||||
|
? `(${row.positionLevelOld})`
|
||||||
|
: ""
|
||||||
}`
|
}`
|
||||||
: "";
|
: "";
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -381,7 +381,7 @@ async function fecthlistappointment() {
|
||||||
e.positionTypeOld &&
|
e.positionTypeOld &&
|
||||||
e.positionLevelOld &&
|
e.positionLevelOld &&
|
||||||
e.positionNumberOld &&
|
e.positionNumberOld &&
|
||||||
e.positionDate
|
(e.typeCommand === "MOVE" || e.positionDate)
|
||||||
);
|
);
|
||||||
rows2.value = listData;
|
rows2.value = listData;
|
||||||
rows2Data.value = listData;
|
rows2Data.value = listData;
|
||||||
|
|
|
||||||
|
|
@ -252,7 +252,7 @@ async function fecthlistappointment() {
|
||||||
e.positionTypeOld &&
|
e.positionTypeOld &&
|
||||||
e.positionLevelOld &&
|
e.positionLevelOld &&
|
||||||
e.positionNumberOld &&
|
e.positionNumberOld &&
|
||||||
e.positionDate
|
(e.positionDate || e.typeCommand === "MOVE")
|
||||||
);
|
);
|
||||||
rows2.value = listData;
|
rows2.value = listData;
|
||||||
rows2Data.value = listData;
|
rows2Data.value = listData;
|
||||||
|
|
|
||||||
|
|
@ -370,18 +370,32 @@ async function uploadFile(event: any, date: any) {
|
||||||
*/
|
*/
|
||||||
async function downloadAttachment(type: string, id: string) {
|
async function downloadAttachment(type: string, id: string) {
|
||||||
showLoader();
|
showLoader();
|
||||||
await http
|
try {
|
||||||
.get(config.API.reportRetireList(type, id))
|
const response = await http.get(
|
||||||
.then(async (res) => {
|
config.API.retirementReport + `/${type}/${id}`,
|
||||||
const data = res.data.result;
|
{
|
||||||
await genReport(data, `รายชื่อผู้เกษียณอายุราชการ`, type);
|
headers: {
|
||||||
})
|
accept:
|
||||||
.catch(async (e) => {
|
type === "pdf"
|
||||||
messageError($q, JSON.parse(await e.response.data.text()));
|
? "application/pdf"
|
||||||
})
|
: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
||||||
.finally(() => {
|
"content-Type": "application/json",
|
||||||
hideLoader();
|
},
|
||||||
});
|
responseType: "blob",
|
||||||
|
}
|
||||||
|
);
|
||||||
|
const blob = response.data;
|
||||||
|
const url = URL.createObjectURL(blob);
|
||||||
|
const link = document.createElement("a");
|
||||||
|
link.href = url;
|
||||||
|
link.download = `รายชื่อผู้เกษียณอายุราชการ.${type}`;
|
||||||
|
link.click();
|
||||||
|
URL.revokeObjectURL(url);
|
||||||
|
} catch (e) {
|
||||||
|
messageError($q, e);
|
||||||
|
} finally {
|
||||||
|
hideLoader();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ยืนยันการแก้ไขข้อมูล
|
// ยืนยันการแก้ไขข้อมูล
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@ import { useQuasar, type QTableProps } from "quasar";
|
||||||
|
|
||||||
import http from "@/plugins/http";
|
import http from "@/plugins/http";
|
||||||
import config from "@/app.config";
|
import config from "@/app.config";
|
||||||
import { getColumnLabel } from "@/utils/function";
|
|
||||||
import { useCounterMixin } from "@/stores/mixin";
|
import { useCounterMixin } from "@/stores/mixin";
|
||||||
|
|
||||||
import DialogHeader from "@/components/DialogHeader.vue";
|
import DialogHeader from "@/components/DialogHeader.vue";
|
||||||
|
|
@ -229,6 +228,7 @@ watch(
|
||||||
label="ค้นหา"
|
label="ค้นหา"
|
||||||
v-model="keyword"
|
v-model="keyword"
|
||||||
style="width: 300px"
|
style="width: 300px"
|
||||||
|
@keydown.enter.prevent="onSearchData"
|
||||||
>
|
>
|
||||||
<template v-slot:append>
|
<template v-slot:append>
|
||||||
<q-icon name="search"></q-icon>
|
<q-icon name="search"></q-icon>
|
||||||
|
|
@ -308,9 +308,7 @@ watch(
|
||||||
:key="col.name"
|
:key="col.name"
|
||||||
:props="props"
|
:props="props"
|
||||||
>
|
>
|
||||||
<span class="text-weight-medium">{{
|
<span class="text-weight-medium">{{ col.label }}</span>
|
||||||
getColumnLabel(col, isAct)
|
|
||||||
}}</span>
|
|
||||||
</q-th>
|
</q-th>
|
||||||
</q-tr>
|
</q-tr>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -151,7 +151,7 @@ async function fetchDataRetirement() {
|
||||||
firstNameTH: filter.value.firstNameTH.trim(),
|
firstNameTH: filter.value.firstNameTH.trim(),
|
||||||
lastNameTH: filter.value.lastNameTH.trim(),
|
lastNameTH: filter.value.lastNameTH.trim(),
|
||||||
});
|
});
|
||||||
const data: RetirementOld = response.data.data;
|
const data: RetirementOld = response.data.result;
|
||||||
pagination.value.rowsNumber = data.totalRecords;
|
pagination.value.rowsNumber = data.totalRecords;
|
||||||
rows.value = data.dataRecords;
|
rows.value = data.dataRecords;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
|
||||||
|
|
@ -267,7 +267,13 @@ watch(
|
||||||
<div class="q-pa-md q-gutter-md">
|
<div class="q-pa-md q-gutter-md">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col text-grey-8">เวลาเข้างาน</div>
|
<div class="col text-grey-8">เวลาเข้างาน</div>
|
||||||
<div class="col">{{ formData.checkInTime }}</div>
|
<div class="col">
|
||||||
|
{{
|
||||||
|
formData.checkInDate
|
||||||
|
? `${formData.checkInDate} ${formData.checkInTime} น.`
|
||||||
|
: "-"
|
||||||
|
}}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col text-grey-8">สถานที่ทำงาน</div>
|
<div class="col text-grey-8">สถานที่ทำงาน</div>
|
||||||
|
|
@ -337,17 +343,23 @@ watch(
|
||||||
<div class="q-pa-md q-gutter-md">
|
<div class="q-pa-md q-gutter-md">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col text-grey-8">เวลาออกงาน</div>
|
<div class="col text-grey-8">เวลาออกงาน</div>
|
||||||
<div class="col">{{ formData.checkOutTime }}</div>
|
<div class="col">
|
||||||
|
{{
|
||||||
|
formData.checkOutDate
|
||||||
|
? `${formData.checkOutDate} ${formData.checkOutTime} น.`
|
||||||
|
: "-"
|
||||||
|
}}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col text-grey-8">สถานที่ทำงาน</div>
|
<div class="col text-grey-8">สถานที่ทำงาน</div>
|
||||||
<div class="col" v-if="formData.isLocationCheckOut">
|
<div class="col" v-if="formData.isLocationCheckOut">
|
||||||
ในสถานที่
|
{{ formData.checkOutLat ? "ในสถานที่" : "-" }}
|
||||||
</div>
|
</div>
|
||||||
<div class="col" v-else>
|
<div class="col" v-else>
|
||||||
{{
|
{{
|
||||||
formData.checkInLocationName
|
formData.checkOutLocationName
|
||||||
? `นอกสถานที่ (${formData.checkInLocationName})`
|
? `นอกสถานที่ (${formData.checkOutLocationName})`
|
||||||
: ""
|
: ""
|
||||||
}}
|
}}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -74,6 +74,12 @@ const columns = ref<QTableProps["columns"]>([
|
||||||
field: "checkInTime",
|
field: "checkInTime",
|
||||||
headerStyle: "font-size: 14px",
|
headerStyle: "font-size: 14px",
|
||||||
style: "font-size: 14px",
|
style: "font-size: 14px",
|
||||||
|
format(val, row) {
|
||||||
|
if (row.checkInDate && val) {
|
||||||
|
return `${row.checkInDate} ${val} น.`;
|
||||||
|
}
|
||||||
|
return "-";
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "checkInLocation",
|
name: "checkInLocation",
|
||||||
|
|
@ -101,6 +107,12 @@ const columns = ref<QTableProps["columns"]>([
|
||||||
field: "checkOutTime",
|
field: "checkOutTime",
|
||||||
headerStyle: "font-size: 14px",
|
headerStyle: "font-size: 14px",
|
||||||
style: "font-size: 14px",
|
style: "font-size: 14px",
|
||||||
|
format(val, row) {
|
||||||
|
if (row.checkOutDate && val) {
|
||||||
|
return `${row.checkOutDate} ${val} น.`;
|
||||||
|
}
|
||||||
|
return "-";
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "checkOutLocation",
|
name: "checkOutLocation",
|
||||||
|
|
@ -160,19 +172,19 @@ async function fetchListTimeRecord() {
|
||||||
id: e.id,
|
id: e.id,
|
||||||
fullName: e.fullName,
|
fullName: e.fullName,
|
||||||
profileType: e.profileType,
|
profileType: e.profileType,
|
||||||
checkInDate: e.checkInDate ? date2Thai(e.checkInDate) : "-",
|
checkInDate: date2Thai(e.checkInDate),
|
||||||
checkInTime: e.checkInTime,
|
checkInTime: e.checkInTime,
|
||||||
checkInLocation: e.checkInLocation,
|
checkInLocation: e.checkInLocation,
|
||||||
checkInLat: e.checkInLat ? e.checkInLat : "",
|
checkInLat: e.checkInLat,
|
||||||
checkInLon: e.checkInLon ? e.checkInLon : "",
|
checkInLon: e.checkInLon,
|
||||||
checkInStatus: e.checkInStatus
|
checkInStatus: e.checkInStatus
|
||||||
? workStore.convertSatatus(e.checkInStatus)
|
? workStore.convertSatatus(e.checkInStatus)
|
||||||
: "-",
|
: "-",
|
||||||
checkOutDate: e.checkOutDate ? date2Thai(e.checkOutDate) : "-",
|
checkOutDate: date2Thai(e.checkOutDate),
|
||||||
checkOutLocation: e.checkOutLocation ? e.checkOutLocation : "-",
|
checkOutLocation: e.checkOutLocation,
|
||||||
checkOutTime: e.checkOutTime ? e.checkOutTime : "-",
|
checkOutTime: e.checkOutTime,
|
||||||
checkOutLat: e.checkOutLat ? e.checkOutLat : "",
|
checkOutLat: e.checkOutLat,
|
||||||
checkOutLon: e.checkOutLat ? e.checkOutLon : "",
|
checkOutLon: e.checkOutLon,
|
||||||
checkOutStatus: e.checkOutStatus
|
checkOutStatus: e.checkOutStatus
|
||||||
? workStore.convertSatatus(e.checkOutStatus)
|
? workStore.convertSatatus(e.checkOutStatus)
|
||||||
: "-",
|
: "-",
|
||||||
|
|
|
||||||
|
|
@ -70,6 +70,12 @@ const columns = ref<QTableProps["columns"]>([
|
||||||
field: "checkInTime",
|
field: "checkInTime",
|
||||||
headerStyle: "font-size: 14px",
|
headerStyle: "font-size: 14px",
|
||||||
style: "font-size: 14px",
|
style: "font-size: 14px",
|
||||||
|
format(val, row) {
|
||||||
|
if (row.checkInDate && val) {
|
||||||
|
return `${row.checkInDate} ${val} น.`;
|
||||||
|
}
|
||||||
|
return "-";
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "checkInLocation",
|
name: "checkInLocation",
|
||||||
|
|
@ -88,6 +94,12 @@ const columns = ref<QTableProps["columns"]>([
|
||||||
field: "checkOutTime",
|
field: "checkOutTime",
|
||||||
headerStyle: "font-size: 14px",
|
headerStyle: "font-size: 14px",
|
||||||
style: "font-size: 14px",
|
style: "font-size: 14px",
|
||||||
|
format(val, row) {
|
||||||
|
if (row.checkOutDate && val) {
|
||||||
|
return `${row.checkOutDate} ${val} น.`;
|
||||||
|
}
|
||||||
|
return "-";
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "checkOutLocation",
|
name: "checkOutLocation",
|
||||||
|
|
@ -133,15 +145,15 @@ async function fetchListLogRecord() {
|
||||||
profileType: e.profileType,
|
profileType: e.profileType,
|
||||||
fullName: e.fullName,
|
fullName: e.fullName,
|
||||||
checkInDate: e.checkInDate && date2Thai(e.checkInDate),
|
checkInDate: e.checkInDate && date2Thai(e.checkInDate),
|
||||||
checkInTime: e.checkInTime ? e.checkInTime : "-",
|
checkInTime: e.checkInTime,
|
||||||
checkInLocation: e.checkInLocation ? e.checkInLocation : "-",
|
checkInLocation: e.checkInLocation,
|
||||||
checkInLat: e.checkInLat ? e.checkInLat : "",
|
checkInLat: e.checkInLat,
|
||||||
checkInLon: e.checkInLon ? e.checkInLon : "",
|
checkInLon: e.checkInLon,
|
||||||
checkOutDate: e.checkOutDate && date2Thai(e.checkOutDate),
|
checkOutDate: e.checkOutDate && date2Thai(e.checkOutDate),
|
||||||
checkOutLocation: e.checkOutLocation ? e.checkOutLocation : "-",
|
checkOutLocation: e.checkOutLocation,
|
||||||
checkOutTime: e.checkOutTime ? e.checkOutTime : "-",
|
checkOutTime: e.checkOutTime,
|
||||||
checkOutLat: e.checkOutLat ? e.checkOutLat : "",
|
checkOutLat: e.checkOutLat,
|
||||||
checkOutLon: e.checkOutLon ? e.checkOutLon : "",
|
checkOutLon: e.checkOutLon,
|
||||||
}));
|
}));
|
||||||
} else {
|
} else {
|
||||||
rows.value = [];
|
rows.value = [];
|
||||||
|
|
|
||||||
|
|
@ -123,7 +123,7 @@ onMounted(() => {
|
||||||
{{ props.rowIndex + 1 }}
|
{{ props.rowIndex + 1 }}
|
||||||
</div>
|
</div>
|
||||||
<div v-else-if="col.name == 'checkInLocation'">
|
<div v-else-if="col.name == 'checkInLocation'">
|
||||||
<q-item style="padding: 0">
|
<q-item style="padding: 0" v-if="props.row.checkInLocation">
|
||||||
<q-item-section>
|
<q-item-section>
|
||||||
<q-item-label> {{ props.row.checkInLocation }}</q-item-label>
|
<q-item-label> {{ props.row.checkInLocation }}</q-item-label>
|
||||||
<q-item-label caption lines="2">{{
|
<q-item-label caption lines="2">{{
|
||||||
|
|
@ -131,9 +131,10 @@ onMounted(() => {
|
||||||
}}</q-item-label>
|
}}</q-item-label>
|
||||||
</q-item-section>
|
</q-item-section>
|
||||||
</q-item>
|
</q-item>
|
||||||
|
<div v-else>-</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-else-if="col.name == 'checkOutLocation'">
|
<div v-else-if="col.name == 'checkOutLocation'">
|
||||||
<q-item style="padding: 0">
|
<q-item style="padding: 0" v-if="props.row.checkOutLocation">
|
||||||
<q-item-section>
|
<q-item-section>
|
||||||
<q-item-label> {{ props.row.checkOutLocation }}</q-item-label>
|
<q-item-label> {{ props.row.checkOutLocation }}</q-item-label>
|
||||||
<q-item-label caption lines="2">{{
|
<q-item-label caption lines="2">{{
|
||||||
|
|
@ -141,6 +142,7 @@ onMounted(() => {
|
||||||
}}</q-item-label>
|
}}</q-item-label>
|
||||||
</q-item-section>
|
</q-item-section>
|
||||||
</q-item>
|
</q-item>
|
||||||
|
<div v-else>-</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-else-if="col.name == 'profileType'">
|
<div v-else-if="col.name == 'profileType'">
|
||||||
{{
|
{{
|
||||||
|
|
@ -150,7 +152,7 @@ onMounted(() => {
|
||||||
}}
|
}}
|
||||||
</div>
|
</div>
|
||||||
<div v-else>
|
<div v-else>
|
||||||
{{ col.value }}
|
{{ col.value ? col.value : "-" }}
|
||||||
</div>
|
</div>
|
||||||
</q-td>
|
</q-td>
|
||||||
</q-tr>
|
</q-tr>
|
||||||
|
|
|
||||||
|
|
@ -82,6 +82,7 @@ const formData = reactive<FormData>({
|
||||||
status: "", //สถานะการของลา
|
status: "", //สถานะการของลา
|
||||||
leaveLimit: 0, //โควต้าลา(แต่ละประเภท)หน่วยเป็นวัน
|
leaveLimit: 0, //โควต้าลา(แต่ละประเภท)หน่วยเป็นวัน
|
||||||
leaveSummary: 0, //ลาป่วยไปแล้ว(แต่ละประเภท)หน่วยเป็นวัน
|
leaveSummary: 0, //ลาป่วยไปแล้ว(แต่ละประเภท)หน่วยเป็นวัน
|
||||||
|
leaveWaitingSummary: 0, //ลาอยู่ระหว่างการพิจารณา(แต่ละประเภท)หน่วยเป็นวัน
|
||||||
leaveRemain: 0, //คงเหลือโควต้า(แต่ละประเภท)หน่วยเป็นวัน
|
leaveRemain: 0, //คงเหลือโควต้า(แต่ละประเภท)หน่วยเป็นวัน
|
||||||
leaveWrote: "", //เขียนที่
|
leaveWrote: "", //เขียนที่
|
||||||
leaveAddress: "", //สถานที่ติดต่อขณะลา
|
leaveAddress: "", //สถานที่ติดต่อขณะลา
|
||||||
|
|
@ -149,21 +150,41 @@ const rows = ref<RowsType>();
|
||||||
// เช็คสิทธิ์การอนุมัติ
|
// เช็คสิทธิ์การอนุมัติ
|
||||||
const idCheck = computed(() => {
|
const idCheck = computed(() => {
|
||||||
if (typeAdd.value == "COMMANDER") {
|
if (typeAdd.value == "COMMANDER") {
|
||||||
return rows.value?.commanders.map((items: SeqTypeRow) => items.profileId);
|
return rows.value?.commanders.map((items: SeqTypeRow) => items.keyId);
|
||||||
} else if (typeAdd.value == "APPROVER") {
|
} else if (typeAdd.value == "APPROVER") {
|
||||||
return rows.value?.approvers.map((items: SeqTypeRow) => items.profileId);
|
return rows.value?.approvers.map((items: SeqTypeRow) => items.keyId);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// เช็คสิทธิ์การเลือกผู้มีอำนาจ
|
// เช็คสิทธิ์การเลือกผู้มีอำนาจ
|
||||||
const commanderList = computed(() => {
|
const commanderList = computed(() => {
|
||||||
if (typeAdd.value == "COMMANDER") {
|
if (typeAdd.value === "COMMANDER") {
|
||||||
return rows.value?.approvers.map((items: SeqTypeRow) => items.profileId);
|
return rows.value?.approvers.map((items: SeqTypeRow) => ({
|
||||||
} else if (typeAdd.value == "APPROVER") {
|
profileId: items.profileId,
|
||||||
return rows.value?.commanders.map((items: SeqTypeRow) => items.profileId);
|
isAct: items.isAct,
|
||||||
|
}));
|
||||||
|
} else if (typeAdd.value === "APPROVER") {
|
||||||
|
return rows.value?.commanders.map((items: SeqTypeRow) => ({
|
||||||
|
profileId: items.profileId,
|
||||||
|
isAct: items.isAct,
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
return [];
|
||||||
});
|
});
|
||||||
|
|
||||||
|
//
|
||||||
|
const isAct = computed(() => {
|
||||||
|
if (typeAdd.value === "COMMANDER") {
|
||||||
|
return rows.value?.commanders && rows.value.commanders.length > 0
|
||||||
|
? rows.value.commanders[0].isAct
|
||||||
|
: false;
|
||||||
|
} else if (typeAdd.value === "APPROVER") {
|
||||||
|
return rows.value?.approvers && rows.value.approvers.length > 0
|
||||||
|
? rows.value.approvers[0].isAct
|
||||||
|
: false;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
// เช็คว่าผู้ใช้มีสิทธิ์อนุมัติหรือไม่
|
// เช็คว่าผู้ใช้มีสิทธิ์อนุมัติหรือไม่
|
||||||
const approveCheck = computed(() => {
|
const approveCheck = computed(() => {
|
||||||
const commanders = rows.value?.commanders;
|
const commanders = rows.value?.commanders;
|
||||||
|
|
@ -391,6 +412,9 @@ async function fetchDetailLeave(paramsId: string) {
|
||||||
formData.leaveRange = data.leaveRange;
|
formData.leaveRange = data.leaveRange;
|
||||||
formData.commanderPosition = data.commanderPosition;
|
formData.commanderPosition = data.commanderPosition;
|
||||||
formData.leaveRangeEnd = data.leaveRangeEnd;
|
formData.leaveRangeEnd = data.leaveRangeEnd;
|
||||||
|
formData.leaveWaitingSummary = data.leaveWaitingSummary
|
||||||
|
? data.leaveWaitingSummary
|
||||||
|
: "0";
|
||||||
keycloakUserId.value = data.keycloakUserId;
|
keycloakUserId.value = data.keycloakUserId;
|
||||||
rows.value = {
|
rows.value = {
|
||||||
commanders: data.commanders,
|
commanders: data.commanders,
|
||||||
|
|
@ -668,10 +692,10 @@ onMounted(async () => {
|
||||||
fetchOptionType(),
|
fetchOptionType(),
|
||||||
fetchKeycloakPositionData(),
|
fetchKeycloakPositionData(),
|
||||||
fetchDetailLeave(paramsId),
|
fetchDetailLeave(paramsId),
|
||||||
checkOfficer(),
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
await checkLeaveType(formData.leaveTypeId, formData);
|
await checkLeaveType(formData.leaveTypeId, formData);
|
||||||
|
await checkOfficer();
|
||||||
} finally {
|
} finally {
|
||||||
hideLoader();
|
hideLoader();
|
||||||
}
|
}
|
||||||
|
|
@ -773,40 +797,50 @@ onMounted(async () => {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-xs-12 col-sm-7 row">
|
<div class="col-xs-12 col-sm-7 row">
|
||||||
<div class="row col-12 q-gutter-md">
|
<div class="row col-12 q-col-gutter-md">
|
||||||
<div
|
<div
|
||||||
v-if="formData.leaveTypeName == 'ลาพักผ่อน'"
|
v-if="formData.leaveTypeName == 'ลาพักผ่อน'"
|
||||||
class="col-3"
|
class="col-md-3 col-xs-6"
|
||||||
>
|
>
|
||||||
<q-card bordered class="items-center row col-12 q-pa-md">
|
<q-card bordered class="items-center row col-12 q-pa-md">
|
||||||
<div class="text-h6 text-weight-bold text-blue-10">
|
<div class="text-h6 text-weight-bold text-blue-10">
|
||||||
{{ formData.leaveLimit }}
|
{{ formData.leaveLimit }}
|
||||||
</div>
|
</div>
|
||||||
<div class="col-12 text-subtitle2 text-weight-regular">
|
<div class="col-12 text-subtitle2 text-weight-regular">
|
||||||
<span class="gt-xs">ได้รับ</span>
|
<span>ได้รับ</span>
|
||||||
</div>
|
</div>
|
||||||
</q-card>
|
</q-card>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-3">
|
<div class="col-md-3 col-xs-6">
|
||||||
<q-card bordered class="items-center row col-12 q-pa-md">
|
<q-card bordered class="items-center row col-12 q-pa-md">
|
||||||
<div class="text-h6 text-weight-bold text-light-blue-6">
|
<div class="text-h6 text-weight-bold text-light-blue-6">
|
||||||
{{ formData.leaveSummary }}
|
{{ formData.leaveSummary }}
|
||||||
</div>
|
</div>
|
||||||
<div class="col-12 text-subtitle2 text-weight-regular">
|
<div class="col-12 text-subtitle2 text-weight-regular">
|
||||||
<span class="gt-xs">ใช้ไป</span>
|
<span>ใช้ไป</span>
|
||||||
</div>
|
</div>
|
||||||
</q-card>
|
</q-card>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
v-if="formData.leaveTypeName == 'ลาพักผ่อน'"
|
v-if="formData.leaveTypeName == 'ลาพักผ่อน'"
|
||||||
class="col-3"
|
class="col-md-3 col-xs-6"
|
||||||
>
|
>
|
||||||
<q-card bordered class="items-center row col-12 q-pa-md">
|
<q-card bordered class="items-center row col-12 q-pa-md">
|
||||||
<div class="text-h6 text-weight-bold text-indigo-7">
|
<div class="text-h6 text-weight-bold text-indigo-7">
|
||||||
{{ formData.leaveRemain }}
|
{{ formData.leaveRemain }}
|
||||||
</div>
|
</div>
|
||||||
<div class="col-12 text-subtitle2 text-weight-regular">
|
<div class="col-12 text-subtitle2 text-weight-regular">
|
||||||
<span class="gt-xs">คงเหลือ</span>
|
<span>คงเหลือ</span>
|
||||||
|
</div>
|
||||||
|
</q-card>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-3 col-xs-6">
|
||||||
|
<q-card bordered class="items-center row col-12 q-pa-md">
|
||||||
|
<div class="text-h6 text-weight-bold text-light-blue-6">
|
||||||
|
{{ formData.leaveWaitingSummary }}
|
||||||
|
</div>
|
||||||
|
<div class="col-12 text-subtitle2 text-weight-regular">
|
||||||
|
<span>อยู่ระหว่างการพิจารณา</span>
|
||||||
</div>
|
</div>
|
||||||
</q-card>
|
</q-card>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -1258,5 +1292,6 @@ onMounted(async () => {
|
||||||
:id-check="idCheck"
|
:id-check="idCheck"
|
||||||
:keycloak-user-id="keycloakUserId"
|
:keycloak-user-id="keycloakUserId"
|
||||||
:commanders-list="commanderList"
|
:commanders-list="commanderList"
|
||||||
|
:commanders-is-act="isAct"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -151,6 +151,7 @@ const formData = reactive<FormData>({
|
||||||
leaveSubTypeName: "",
|
leaveSubTypeName: "",
|
||||||
commanderPosition: "",
|
commanderPosition: "",
|
||||||
leaveRangeEnd: "",
|
leaveRangeEnd: "",
|
||||||
|
leaveWaitingSummary: 0, //ลาอยู่ระหว่างการพิจารณา(แต่ละประเภท)หน่วยเป็นวัน
|
||||||
});
|
});
|
||||||
|
|
||||||
const isLoadData = ref<boolean>(false);
|
const isLoadData = ref<boolean>(false);
|
||||||
|
|
@ -217,6 +218,9 @@ async function fetchDetailLeave(paramsId: string) {
|
||||||
formData.leaveLimit = data.leaveLimit;
|
formData.leaveLimit = data.leaveLimit;
|
||||||
formData.leaveSummary = data.leaveSummary;
|
formData.leaveSummary = data.leaveSummary;
|
||||||
formData.leaveRemain = data.leaveRemain;
|
formData.leaveRemain = data.leaveRemain;
|
||||||
|
formData.leaveWaitingSummary = data.leaveWaitingSummary
|
||||||
|
? data.leaveWaitingSummary
|
||||||
|
: 0;
|
||||||
formData.leaveWrote = data.leaveWrote;
|
formData.leaveWrote = data.leaveWrote;
|
||||||
formData.leaveAddress = data.leaveAddress;
|
formData.leaveAddress = data.leaveAddress;
|
||||||
formData.leaveNumber = data.leaveNumber;
|
formData.leaveNumber = data.leaveNumber;
|
||||||
|
|
@ -626,40 +630,50 @@ onMounted(async () => {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-xs-12 col-sm-7 row">
|
<div class="col-xs-12 col-sm-7 row">
|
||||||
<div class="row col-12 q-gutter-md">
|
<div class="row col-12 q-col-gutter-md">
|
||||||
<div
|
<div
|
||||||
v-if="formData.leaveTypeName == 'ลาพักผ่อน'"
|
v-if="formData.leaveTypeName == 'ลาพักผ่อน'"
|
||||||
class="col-3"
|
class="col-md-3 col-xs-6"
|
||||||
>
|
>
|
||||||
<q-card bordered class="items-center row col-12 q-pa-md">
|
<q-card bordered class="items-center row col-12 q-pa-md">
|
||||||
<div class="text-h6 text-weight-bold text-blue-10">
|
<div class="text-h6 text-weight-bold text-blue-10">
|
||||||
{{ formData.leaveLimit }}
|
{{ formData.leaveLimit }}
|
||||||
</div>
|
</div>
|
||||||
<div class="col-12 text-subtitle2 text-weight-regular">
|
<div class="col-12 text-subtitle2 text-weight-regular">
|
||||||
<span class="gt-xs">ได้รับ</span>
|
<span>ได้รับ</span>
|
||||||
</div>
|
</div>
|
||||||
</q-card>
|
</q-card>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-3">
|
<div class="col-md-3 col-xs-6">
|
||||||
<q-card bordered class="items-center row col-12 q-pa-md">
|
<q-card bordered class="items-center row col-12 q-pa-md">
|
||||||
<div class="text-h6 text-weight-bold text-light-blue-6">
|
<div class="text-h6 text-weight-bold text-light-blue-6">
|
||||||
{{ formData.leaveSummary }}
|
{{ formData.leaveSummary }}
|
||||||
</div>
|
</div>
|
||||||
<div class="col-12 text-subtitle2 text-weight-regular">
|
<div class="col-12 text-subtitle2 text-weight-regular">
|
||||||
<span class="gt-xs">ใช้ไป</span>
|
<span>ใช้ไป</span>
|
||||||
</div>
|
</div>
|
||||||
</q-card>
|
</q-card>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
v-if="formData.leaveTypeName == 'ลาพักผ่อน'"
|
v-if="formData.leaveTypeName == 'ลาพักผ่อน'"
|
||||||
class="col-3"
|
class="col-md-3 col-xs-6"
|
||||||
>
|
>
|
||||||
<q-card bordered class="items-center row col-12 q-pa-md">
|
<q-card bordered class="items-center row col-12 q-pa-md">
|
||||||
<div class="text-h6 text-weight-bold text-indigo-7">
|
<div class="text-h6 text-weight-bold text-indigo-7">
|
||||||
{{ formData.leaveRemain }}
|
{{ formData.leaveRemain }}
|
||||||
</div>
|
</div>
|
||||||
<div class="col-12 text-subtitle2 text-weight-regular">
|
<div class="col-12 text-subtitle2 text-weight-regular">
|
||||||
<span class="gt-xs">คงเหลือ</span>
|
<span>คงเหลือ</span>
|
||||||
|
</div>
|
||||||
|
</q-card>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-3 col-xs-6">
|
||||||
|
<q-card bordered class="items-center row col-12 q-pa-md">
|
||||||
|
<div class="text-h6 text-weight-bold text-light-blue-6">
|
||||||
|
{{ formData.leaveWaitingSummary }}
|
||||||
|
</div>
|
||||||
|
<div class="col-12 text-subtitle2 text-weight-regular">
|
||||||
|
<span>อยู่ระหว่างการพิจารณา</span>
|
||||||
</div>
|
</div>
|
||||||
</q-card>
|
</q-card>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@ import { useQuasar, type QTableProps } from "quasar";
|
||||||
|
|
||||||
import http from "@/plugins/http";
|
import http from "@/plugins/http";
|
||||||
import config from "@/app.config";
|
import config from "@/app.config";
|
||||||
import { getColumnLabel } from "@/utils/function";
|
|
||||||
import { useCounterMixin } from "@/stores/mixin";
|
import { useCounterMixin } from "@/stores/mixin";
|
||||||
|
|
||||||
import DialogHeader from "@/components/DialogHeader.vue";
|
import DialogHeader from "@/components/DialogHeader.vue";
|
||||||
|
|
@ -30,6 +29,7 @@ const props = defineProps({
|
||||||
fetchDetailLeave: Function,
|
fetchDetailLeave: Function,
|
||||||
idCheck: Array,
|
idCheck: Array,
|
||||||
commandersList: Array,
|
commandersList: Array,
|
||||||
|
commandersIsAct: Boolean,
|
||||||
});
|
});
|
||||||
|
|
||||||
const pageId = ref<string>(route.params.id as string);
|
const pageId = ref<string>(route.params.id as string);
|
||||||
|
|
@ -117,7 +117,7 @@ async function getData() {
|
||||||
total.value = data.total;
|
total.value = data.total;
|
||||||
rows.value = data.data;
|
rows.value = data.data;
|
||||||
selected.value = data.data.filter((items: any) => {
|
selected.value = data.data.filter((items: any) => {
|
||||||
return props.idCheck?.some((i: any) => i === items.id);
|
return props.idCheck?.some((i: any) => i === items.key);
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
|
|
@ -153,10 +153,14 @@ function onSubmit() {
|
||||||
]
|
]
|
||||||
.filter(Boolean)
|
.filter(Boolean)
|
||||||
.join(" "),
|
.join(" "),
|
||||||
|
isAct: isAct.value,
|
||||||
|
keyId: items.key,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const hasCommander = selected.value.some((e) =>
|
const hasCommander = selected.value.some((e) =>
|
||||||
props.commandersList?.some((i: any) => i === e.id)
|
props.commandersList?.some(
|
||||||
|
(i: any) => i.profileId === e.id && i.isAct === isAct.value
|
||||||
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
if (hasCommander) {
|
if (hasCommander) {
|
||||||
|
|
@ -205,6 +209,7 @@ watch(
|
||||||
() => modal.value,
|
() => modal.value,
|
||||||
() => {
|
() => {
|
||||||
if (modal.value) {
|
if (modal.value) {
|
||||||
|
isAct.value = props.commandersIsAct ?? false;
|
||||||
getSearch();
|
getSearch();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -233,6 +238,7 @@ watch(
|
||||||
label="ค้นหา"
|
label="ค้นหา"
|
||||||
v-model="keyword"
|
v-model="keyword"
|
||||||
style="width: 300px"
|
style="width: 300px"
|
||||||
|
@keydown.enter.prevent="onSearchData()"
|
||||||
>
|
>
|
||||||
<template v-slot:append>
|
<template v-slot:append>
|
||||||
<q-icon name="search"></q-icon>
|
<q-icon name="search"></q-icon>
|
||||||
|
|
@ -312,9 +318,7 @@ watch(
|
||||||
:key="col.name"
|
:key="col.name"
|
||||||
:props="props"
|
:props="props"
|
||||||
>
|
>
|
||||||
<span class="text-weight-medium">{{
|
<span class="text-weight-medium">{{ col.label }}</span>
|
||||||
getColumnLabel(col, isAct)
|
|
||||||
}}</span>
|
|
||||||
</q-th>
|
</q-th>
|
||||||
</q-tr>
|
</q-tr>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import { useCounterMixin } from "@/stores/mixin";
|
||||||
import { useLeaveHistoryDataStore } from "@/modules/09_leave/stores/LeaveHistoryStore";
|
import { useLeaveHistoryDataStore } from "@/modules/09_leave/stores/LeaveHistoryStore";
|
||||||
import { calculateFiscalYear } from "@/utils/function";
|
import { calculateFiscalYear } from "@/utils/function";
|
||||||
import { usePagination } from "@/composables/usePagination";
|
import { usePagination } from "@/composables/usePagination";
|
||||||
|
import { checkPermission } from "@/utils/permissions";
|
||||||
|
|
||||||
import type { QTableColumn } from "quasar";
|
import type { QTableColumn } from "quasar";
|
||||||
import type { DataOption } from "@/modules/09_leave/interface/index/Main";
|
import type { DataOption } from "@/modules/09_leave/interface/index/Main";
|
||||||
|
|
@ -104,10 +105,18 @@ async function onSubmit() {
|
||||||
leaveTypeId: formData.leaveTypeId,
|
leaveTypeId: formData.leaveTypeId,
|
||||||
leaveYear: formData.leaveYear,
|
leaveYear: formData.leaveYear,
|
||||||
leaveDays: formData.leaveDays ? Number(formData.leaveDays) : 0,
|
leaveDays: formData.leaveDays ? Number(formData.leaveDays) : 0,
|
||||||
leaveDaysUsed: formData.leaveDaysUsed
|
leaveDaysUsed:
|
||||||
? Number(formData.leaveDaysUsed)
|
checkPermission(route)?.attrOwnership === "OWNER"
|
||||||
: 0,
|
? formData.leaveDaysUsed
|
||||||
leaveCount: formData.leaveCount ? Number(formData.leaveCount) : 0,
|
? Number(formData.leaveDaysUsed)
|
||||||
|
: 0
|
||||||
|
: undefined,
|
||||||
|
leaveCount:
|
||||||
|
checkPermission(route)?.attrOwnership === "OWNER"
|
||||||
|
? formData.leaveCount
|
||||||
|
? Number(formData.leaveCount)
|
||||||
|
: 0
|
||||||
|
: undefined,
|
||||||
beginningLeaveDays: formData.beginningLeaveDays
|
beginningLeaveDays: formData.beginningLeaveDays
|
||||||
? Number(formData.beginningLeaveDays)
|
? Number(formData.beginningLeaveDays)
|
||||||
: 0,
|
: 0,
|
||||||
|
|
@ -313,6 +322,7 @@ watch(modal, async (val) => {
|
||||||
hide-bottom-space
|
hide-bottom-space
|
||||||
dense
|
dense
|
||||||
label="คำค้น"
|
label="คำค้น"
|
||||||
|
@keydown.enter.prevent="onSearchData(true)"
|
||||||
>
|
>
|
||||||
<template v-slot:after>
|
<template v-slot:after>
|
||||||
<q-btn
|
<q-btn
|
||||||
|
|
@ -386,7 +396,7 @@ watch(modal, async (val) => {
|
||||||
<q-separator vertical />
|
<q-separator vertical />
|
||||||
|
|
||||||
<!-- input -->
|
<!-- input -->
|
||||||
<div class="col overflow-hidden q-pa-md">
|
<div class="col overflow-auto q-pa-md">
|
||||||
<div class="row q-col-gutter-sm">
|
<div class="row q-col-gutter-sm">
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<datepicker
|
<datepicker
|
||||||
|
|
@ -397,6 +407,7 @@ watch(modal, async (val) => {
|
||||||
year-picker
|
year-picker
|
||||||
:enableTimePicker="false"
|
:enableTimePicker="false"
|
||||||
:max-date="`${calculateFiscalYear(new Date())}, 12, 31`"
|
:max-date="`${calculateFiscalYear(new Date())}, 12, 31`"
|
||||||
|
:class="classInput(true)"
|
||||||
>
|
>
|
||||||
<template #year="{ year }">{{ year + 543 }}</template>
|
<template #year="{ year }">{{ year + 543 }}</template>
|
||||||
<template #year-overlay-value="{ value }">{{
|
<template #year-overlay-value="{ value }">{{
|
||||||
|
|
@ -453,7 +464,7 @@ watch(modal, async (val) => {
|
||||||
</template>
|
</template>
|
||||||
</q-select>
|
</q-select>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-12">
|
<div v-show="leaveTypeCode === 'LV-005'" class="col-12">
|
||||||
<q-input
|
<q-input
|
||||||
:class="classInput(leaveTypeCode == 'LV-005')"
|
:class="classInput(leaveTypeCode == 'LV-005')"
|
||||||
:readonly="leaveTypeCode !== 'LV-005'"
|
:readonly="leaveTypeCode !== 'LV-005'"
|
||||||
|
|
@ -461,33 +472,10 @@ watch(modal, async (val) => {
|
||||||
dense
|
dense
|
||||||
outlined
|
outlined
|
||||||
label="จำนวนสิทธิ์การลา"
|
label="จำนวนสิทธิ์การลา"
|
||||||
hide-bottom-space
|
hint="* สำหรับลาพักผ่อนเท่านั้น คือสิทธิ์ลาประจำปี + สิทธิ์สะสม"
|
||||||
:rules="[(val: string) => !val || /^\d+(\.\d*)?$/.test(val) || 'กรุณากรอกเฉพาะตัวเลข']"
|
:rules="[(val: string) => !val || /^\d+(\.\d*)?$/.test(val) || 'กรุณากรอกเฉพาะตัวเลข']"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-12">
|
|
||||||
<q-input
|
|
||||||
:class="classInput(true)"
|
|
||||||
v-model="formData.leaveDaysUsed"
|
|
||||||
dense
|
|
||||||
outlined
|
|
||||||
label="ที่ใช้ไป (วัน)"
|
|
||||||
hide-bottom-space
|
|
||||||
:rules="[(val: string) => !val || /^\d+(\.\d*)?$/.test(val) || 'กรุณากรอกเฉพาะตัวเลข']"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div class="col-12">
|
|
||||||
<q-input
|
|
||||||
:class="classInput(true)"
|
|
||||||
v-model="formData.leaveCount"
|
|
||||||
dense
|
|
||||||
outlined
|
|
||||||
label="ที่ใช้ไป (ครั้ง)"
|
|
||||||
hide-bottom-space
|
|
||||||
mask="#"
|
|
||||||
reverse-fill-mask
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<q-input
|
<q-input
|
||||||
|
|
@ -495,9 +483,9 @@ watch(modal, async (val) => {
|
||||||
v-model="formData.beginningLeaveDays"
|
v-model="formData.beginningLeaveDays"
|
||||||
dense
|
dense
|
||||||
outlined
|
outlined
|
||||||
label="ยกมา (วัน)"
|
label="จำนวนวันลาก่อนใช้งานระบบ"
|
||||||
hide-bottom-space
|
|
||||||
:rules="[(val: string) => !val || /^\d+(\.\d*)?$/.test(val) || 'กรุณากรอกเฉพาะตัวเลข']"
|
:rules="[(val: string) => !val || /^\d+(\.\d*)?$/.test(val) || 'กรุณากรอกเฉพาะตัวเลข']"
|
||||||
|
hint="* จำนวนวันรวมการลาในปีงบประมาณนี้ที่เกิดขึ้นก่อนเริ่มใช้ระบบ"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -507,10 +495,38 @@ watch(modal, async (val) => {
|
||||||
v-model="formData.beginningLeaveCount"
|
v-model="formData.beginningLeaveCount"
|
||||||
dense
|
dense
|
||||||
outlined
|
outlined
|
||||||
label="ยกมา (ครั้ง)"
|
label="จำนวนครั้งที่ลาก่อนใช้งานระบบ"
|
||||||
|
:rules="[(val: string) => !val || /^\d+$/.test(val) || 'กรุณากรอกเฉพาะตัวเลขที่เป็นจำนวนเต็ม']"
|
||||||
|
hint="* จำนวนครั้งของการลาในปีงบประมาณนี้ที่เกิดขึ้นก่อนเริ่มใช้ระบบ"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
v-if="checkPermission(route)?.attrOwnership === 'OWNER'"
|
||||||
|
class="col-12"
|
||||||
|
>
|
||||||
|
<q-input
|
||||||
|
:class="classInput(true)"
|
||||||
|
v-model="formData.leaveDaysUsed"
|
||||||
|
dense
|
||||||
|
outlined
|
||||||
|
label="ที่ใช้ไปทั้งหมด (วัน)"
|
||||||
hide-bottom-space
|
hide-bottom-space
|
||||||
mask="#"
|
:rules="[(val: string) => !val || /^\d+(\.\d*)?$/.test(val) || 'กรุณากรอกเฉพาะตัวเลข']"
|
||||||
reverse-fill-mask
|
/>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="checkPermission(route)?.attrOwnership === 'OWNER'"
|
||||||
|
class="col-12"
|
||||||
|
>
|
||||||
|
<q-input
|
||||||
|
:class="classInput(true)"
|
||||||
|
v-model="formData.leaveCount"
|
||||||
|
dense
|
||||||
|
outlined
|
||||||
|
label="ที่ใช้ไปทั้งหมด (ครั้ง)"
|
||||||
|
hide-bottom-space
|
||||||
|
:rules="[(val: string) => !val || /^\d+$/.test(val) || 'กรุณากรอกเฉพาะตัวเลขที่เป็นจำนวนเต็ม']"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,8 @@ interface DataPost {
|
||||||
lastName: string;
|
lastName: string;
|
||||||
page: number;
|
page: number;
|
||||||
pageSize: number;
|
pageSize: number;
|
||||||
selectedNodeId: string | null;
|
selectedNodeId?: string | null;
|
||||||
selectedNode: string;
|
selectedNode?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface DataOption {
|
interface DataOption {
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,7 @@ interface FormData {
|
||||||
status: string; //สถานะการของลา
|
status: string; //สถานะการของลา
|
||||||
leaveLimit: number; //โควต้าลา(แต่ละประเภท)หน่วยเป็นวัน
|
leaveLimit: number; //โควต้าลา(แต่ละประเภท)หน่วยเป็นวัน
|
||||||
leaveSummary: number; //ลาป่วยไปแล้ว(แต่ละประเภท)หน่วยเป็นวัน
|
leaveSummary: number; //ลาป่วยไปแล้ว(แต่ละประเภท)หน่วยเป็นวัน
|
||||||
|
leaveWaitingSummary: number; //ลาอยู่ระหว่างการพิจารณา(แต่ละประเภท)หน่วยเป็นวัน
|
||||||
leaveRemain: number; //คงเหลือโควต้า(แต่ละประเภท)หน่วยเป็นวัน
|
leaveRemain: number; //คงเหลือโควต้า(แต่ละประเภท)หน่วยเป็นวัน
|
||||||
// leaveStartDate: Date | null; //*วัน เดือน ปีเริ่มต้นลา
|
// leaveStartDate: Date | null; //*วัน เดือน ปีเริ่มต้นลา
|
||||||
// leaveEndDate: Date | null; //*วัน เดือน ปีสิ้นสุดลา
|
// leaveEndDate: Date | null; //*วัน เดือน ปีสิ้นสุดลา
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,8 @@ interface SeqTypeRow {
|
||||||
keycloakId: string;
|
keycloakId: string;
|
||||||
approveStatus: string;
|
approveStatus: string;
|
||||||
comment: string;
|
comment: string;
|
||||||
|
keyId?: string;
|
||||||
|
isAct?: boolean;
|
||||||
}
|
}
|
||||||
interface DataDateMonthObject {
|
interface DataDateMonthObject {
|
||||||
month: number;
|
month: number;
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,14 @@ export const useSpecialTimeStore = defineStore("LeaveSpecialTime", () => {
|
||||||
{ id: "NOT_COMPLETE", name: "ปฏิบัติงานไม่ครบตามกำหนดเวลา" },
|
{ id: "NOT_COMPLETE", name: "ปฏิบัติงานไม่ครบตามกำหนดเวลา" },
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// convertSatatus
|
const optionStatusMain = ref<DataOption[]>([
|
||||||
|
{ id: "ALL", name: "ทั้งหมด" },
|
||||||
|
{ id: "PENDING", name: "รอดำเนินการ" },
|
||||||
|
{ id: "APPROVE", name: "อนุมัติ" },
|
||||||
|
{ id: "REJECT", name: "ไม่อนุมัติ" },
|
||||||
|
]);
|
||||||
|
|
||||||
|
// convertStatus
|
||||||
function convertStatus(val: string) {
|
function convertStatus(val: string) {
|
||||||
const value = val ? val.toUpperCase() : null;
|
const value = val ? val.toUpperCase() : null;
|
||||||
switch (value) {
|
switch (value) {
|
||||||
|
|
@ -29,5 +36,6 @@ export const useSpecialTimeStore = defineStore("LeaveSpecialTime", () => {
|
||||||
return {
|
return {
|
||||||
optionStatus,
|
optionStatus,
|
||||||
convertStatus,
|
convertStatus,
|
||||||
|
optionStatusMain,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -410,6 +410,7 @@ onMounted(() => {
|
||||||
@click="selectAllRows()"
|
@click="selectAllRows()"
|
||||||
/> -->
|
/> -->
|
||||||
<q-btn
|
<q-btn
|
||||||
|
v-if="checkPermission($route)?.attrIsUpdate"
|
||||||
:disable="selected.length === 0 || isLoadingAll"
|
:disable="selected.length === 0 || isLoadingAll"
|
||||||
:color="selected.length === 0 ? 'grey' : 'info'"
|
:color="selected.length === 0 ? 'grey' : 'info'"
|
||||||
dense
|
dense
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,10 @@ import { useSpecialTimeStore } from "@/modules/09_leave/stores/SpecialTimeStore"
|
||||||
import { checkPermission } from "@/utils/permissions";
|
import { checkPermission } from "@/utils/permissions";
|
||||||
import { usePagination } from "@/composables/usePagination";
|
import { usePagination } from "@/composables/usePagination";
|
||||||
|
|
||||||
import type { DataDateMonthObject } from "@/modules/09_leave/interface/request/specialTime";
|
import type {
|
||||||
import type { DataSpecialTime } from "@/modules/09_leave/interface/index/Main";
|
DataSpecialTime,
|
||||||
|
DataOption,
|
||||||
|
} from "@/modules/09_leave/interface/index/Main";
|
||||||
|
|
||||||
import DialogReason from "@/components/Dialogs/PopupReason.vue";
|
import DialogReason from "@/components/Dialogs/PopupReason.vue";
|
||||||
import DialogApprove from "@/modules/09_leave/components/04_SpecialTime/DialogApprove.vue";
|
import DialogApprove from "@/modules/09_leave/components/04_SpecialTime/DialogApprove.vue";
|
||||||
|
|
@ -21,23 +23,17 @@ const mixin = useCounterMixin();
|
||||||
const store = useSpecialTimeStore();
|
const store = useSpecialTimeStore();
|
||||||
const {
|
const {
|
||||||
hideLoader,
|
hideLoader,
|
||||||
monthYear2Thai,
|
|
||||||
messageError,
|
messageError,
|
||||||
showLoader,
|
showLoader,
|
||||||
success,
|
success,
|
||||||
date2Thai,
|
date2Thai,
|
||||||
dialogConfirm,
|
dialogConfirm,
|
||||||
|
dateToISO,
|
||||||
} = mixin;
|
} = mixin;
|
||||||
const { pagination, params, onRequest } = usePagination("", fetchData);
|
const { pagination, params, onRequest } = usePagination("", fetchData);
|
||||||
|
|
||||||
const emit = defineEmits(["update:change-page"]);
|
const emit = defineEmits(["update:change-page"]);
|
||||||
|
|
||||||
const toDay = ref<Date>(new Date());
|
|
||||||
const monthToday = toDay.value.getMonth();
|
|
||||||
const yearToday = toDay.value.getFullYear();
|
|
||||||
|
|
||||||
const month = ref<number>(monthToday + 1);
|
|
||||||
const year = ref<number>(yearToday);
|
|
||||||
const description = ref<string>("");
|
const description = ref<string>("");
|
||||||
|
|
||||||
/**ตัวแปรที่ใช้ */
|
/**ตัวแปรที่ใช้ */
|
||||||
|
|
@ -51,16 +47,12 @@ const name = ref<string>("");
|
||||||
const id = ref<string>("");
|
const id = ref<string>("");
|
||||||
const dateDialog = ref<string>("");
|
const dateDialog = ref<string>("");
|
||||||
const dateFixDialog = ref<string>("");
|
const dateFixDialog = ref<string>("");
|
||||||
const dateYear = ref<number>(new Date().getFullYear());
|
|
||||||
|
|
||||||
/** Function Date */
|
|
||||||
const dateMonth = ref<DataDateMonthObject>({
|
|
||||||
month: new Date().getMonth(),
|
|
||||||
year: new Date().getFullYear(),
|
|
||||||
});
|
|
||||||
|
|
||||||
// ค้นหาในตาราง
|
// ค้นหาในตาราง
|
||||||
const filterKeyword = ref<string>("");
|
const filterKeyword = ref<string>("");
|
||||||
|
const filterStatus = ref<string>("PENDING");
|
||||||
|
const filterDate = ref<[Date, Date] | null>([new Date(), new Date()]); //วันที่ประกาศ
|
||||||
|
const optionStatus = ref<DataOption[]>(store.optionStatusMain);
|
||||||
const rows = ref<DataSpecialTime[]>([]);
|
const rows = ref<DataSpecialTime[]>([]);
|
||||||
const visibleColumns = ref<String[]>([
|
const visibleColumns = ref<String[]>([
|
||||||
"no",
|
"no",
|
||||||
|
|
@ -144,9 +136,10 @@ async function fetchData() {
|
||||||
.get(config.API.specialTime(), {
|
.get(config.API.specialTime(), {
|
||||||
params: {
|
params: {
|
||||||
...params.value,
|
...params.value,
|
||||||
year: year.value,
|
|
||||||
month: month.value,
|
|
||||||
keyword: filterKeyword.value.trim(),
|
keyword: filterKeyword.value.trim(),
|
||||||
|
status: filterStatus.value != "ALL" ? filterStatus.value : null,
|
||||||
|
startDate: filterDate.value ? dateToISO(filterDate.value[0]) : null,
|
||||||
|
endDate: filterDate.value ? dateToISO(filterDate.value[1]) : null,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
.then(async (res) => {
|
.then(async (res) => {
|
||||||
|
|
@ -246,40 +239,43 @@ async function clickSave(reason: string) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* ดึงข้อมูลตามปี
|
|
||||||
* @param e ปี
|
|
||||||
*/
|
|
||||||
async function updateMonth(e: DataDateMonthObject) {
|
|
||||||
if (e != null) {
|
|
||||||
dateYear.value = e.year;
|
|
||||||
dateYear.value = year.value;
|
|
||||||
month.value = dateMonth.value.month + 1;
|
|
||||||
year.value = dateMonth.value.year;
|
|
||||||
onSearchData();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//แปลงเดือนเป็นไทย
|
|
||||||
function monthYearThai(val: DataDateMonthObject) {
|
|
||||||
if (val == null) return "";
|
|
||||||
else return monthYear2Thai(val.month, val.year);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** ฟังก์ชั่นค้นหาข้อมูล */
|
/** ฟังก์ชั่นค้นหาข้อมูล */
|
||||||
function onSearchData() {
|
function onSearchData() {
|
||||||
pagination.value.page = 1;
|
pagination.value.page = 1;
|
||||||
fetchData();
|
fetchData();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ฟังก์ชั่นค้นหาข้อมูลของ Option Filter
|
||||||
|
* @param val คำที่ค้นหา
|
||||||
|
* @param update Function
|
||||||
|
* @param typeOp ประเภทของ Select
|
||||||
|
*/
|
||||||
|
function filterOption(val: string, update: Function) {
|
||||||
|
update(() => {
|
||||||
|
const needle = val.toLowerCase();
|
||||||
|
optionStatus.value = store.optionStatusMain.filter(
|
||||||
|
(v: DataOption) => v.name.toLowerCase().indexOf(needle) > -1
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* แปลงช่วงวันที่ถ้า2ค่าเป็นวันเดียวกันจะโชววันเดียวแต่ถ้าไม่เท่ากันจะแสดงเป็นช่วง
|
||||||
|
* @param val ช่วงวันที่
|
||||||
|
*/
|
||||||
|
function dateThaiRange(val: [Date, Date]) {
|
||||||
|
if (val === null) {
|
||||||
|
return "";
|
||||||
|
} else if (date2Thai(val[0], true) === date2Thai(val[1], true)) {
|
||||||
|
return `${date2Thai(val[0], true)}`;
|
||||||
|
} else {
|
||||||
|
return `${date2Thai(val[0], true)} - ${date2Thai(val[1], true)}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**Hook */
|
/**Hook */
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
//อัพเดทเป็นวันปัจจุบันเมื่อเข้าหน้านี้
|
|
||||||
const toDay = ref<Date>(new Date());
|
|
||||||
const monthToday = toDay.value.getMonth();
|
|
||||||
const yearToday = toDay.value.getFullYear();
|
|
||||||
month.value = monthToday + 1;
|
|
||||||
year.value = yearToday;
|
|
||||||
await fetchData();
|
await fetchData();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
@ -291,25 +287,31 @@ onMounted(async () => {
|
||||||
|
|
||||||
<q-card flat bordered class="col-12 q-pa-md">
|
<q-card flat bordered class="col-12 q-pa-md">
|
||||||
<div class="row col-12 q-col-gutter-sm q-mb-sm">
|
<div class="row col-12 q-col-gutter-sm q-mb-sm">
|
||||||
<div class="col-xs-12 col-sm-3 col-md-2">
|
<div class="col-xs-12 col-sm-6 col-md-3">
|
||||||
<datepicker
|
<datepicker
|
||||||
v-model="dateMonth"
|
v-model="filterDate"
|
||||||
:locale="'th'"
|
:locale="'th'"
|
||||||
autoApply
|
autoApply
|
||||||
month-picker
|
borderless
|
||||||
|
range
|
||||||
:enableTimePicker="false"
|
:enableTimePicker="false"
|
||||||
@update:modelValue="updateMonth"
|
week-start="0"
|
||||||
|
@update:modelValue="onSearchData()"
|
||||||
>
|
>
|
||||||
<template #year="{ year }">{{ year + 543 }}</template>
|
<template #year="{ year }">
|
||||||
<template #year-overlay-value="{ value }">{{
|
{{ year + 543 }}
|
||||||
parseInt(value + 543)
|
</template>
|
||||||
}}</template>
|
<template #year-overlay-value="{ value }">
|
||||||
|
{{ parseInt(value + 543) }}
|
||||||
|
</template>
|
||||||
<template #trigger>
|
<template #trigger>
|
||||||
<q-input
|
<q-input
|
||||||
:model-value="monthYearThai(dateMonth)"
|
|
||||||
dense
|
|
||||||
outlined
|
outlined
|
||||||
hide-bottom-space
|
dense
|
||||||
|
class="full-width datepicker"
|
||||||
|
:model-value="
|
||||||
|
filterDate != null ? dateThaiRange(filterDate) : null
|
||||||
|
"
|
||||||
>
|
>
|
||||||
<template v-slot:prepend>
|
<template v-slot:prepend>
|
||||||
<q-icon
|
<q-icon
|
||||||
|
|
@ -323,9 +325,37 @@ onMounted(async () => {
|
||||||
</template>
|
</template>
|
||||||
</datepicker>
|
</datepicker>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="col-xs-12 col-sm-6 col-md-2">
|
||||||
|
<q-select
|
||||||
|
hide-bottom-space
|
||||||
|
dense
|
||||||
|
lazy-rules
|
||||||
|
outlined
|
||||||
|
onlind
|
||||||
|
hide-selected
|
||||||
|
v-model="filterStatus"
|
||||||
|
label="สถานะ"
|
||||||
|
emit-value
|
||||||
|
map-options
|
||||||
|
:options="optionStatus"
|
||||||
|
option-value="id"
|
||||||
|
use-input
|
||||||
|
fill-input
|
||||||
|
option-label="name"
|
||||||
|
@update:modelValue="onSearchData()"
|
||||||
|
@filter="(inputValue:string, doneFn:Function) =>
|
||||||
|
filterOption(inputValue, doneFn,)"
|
||||||
|
>
|
||||||
|
<template v-slot:no-option>
|
||||||
|
<q-item>
|
||||||
|
<q-item-section class="text-grey"> ไม่มีข้อมูล </q-item-section>
|
||||||
|
</q-item>
|
||||||
|
</template>
|
||||||
|
</q-select>
|
||||||
|
</div>
|
||||||
|
|
||||||
<q-space />
|
<q-space v-if="!$q.screen.xs && !$q.screen.sm" />
|
||||||
<div class="col-xs-12 col-sm-3 col-md-2">
|
<div class="col-xs-12 col-sm-6 col-md-2">
|
||||||
<q-input
|
<q-input
|
||||||
standout
|
standout
|
||||||
dense
|
dense
|
||||||
|
|
@ -340,7 +370,7 @@ onMounted(async () => {
|
||||||
</q-input>
|
</q-input>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-xs-12 col-sm-3 col-md-2">
|
<div class="col-xs-12 col-sm-6 col-md-2">
|
||||||
<q-select
|
<q-select
|
||||||
v-model="visibleColumns"
|
v-model="visibleColumns"
|
||||||
multiple
|
multiple
|
||||||
|
|
|
||||||
|
|
@ -83,7 +83,7 @@ const columns = ref<QTableColumn[]>([
|
||||||
{
|
{
|
||||||
name: "leaveDaysUsed",
|
name: "leaveDaysUsed",
|
||||||
align: "left",
|
align: "left",
|
||||||
label: "ที่ใช้ไป (วัน)",
|
label: "ที่ใช้ไปทั้งหมด (วัน)",
|
||||||
sortable: true,
|
sortable: true,
|
||||||
field: "leaveDaysUsed",
|
field: "leaveDaysUsed",
|
||||||
headerStyle: "font-size: 14px",
|
headerStyle: "font-size: 14px",
|
||||||
|
|
@ -92,7 +92,7 @@ const columns = ref<QTableColumn[]>([
|
||||||
{
|
{
|
||||||
name: "leaveCount",
|
name: "leaveCount",
|
||||||
align: "left",
|
align: "left",
|
||||||
label: "ที่ใช้ไป (ครั้ง)",
|
label: "ที่ใช้ไปทั้งหมด (ครั้ง)",
|
||||||
sortable: true,
|
sortable: true,
|
||||||
field: "leaveCount",
|
field: "leaveCount",
|
||||||
headerStyle: "font-size: 14px",
|
headerStyle: "font-size: 14px",
|
||||||
|
|
@ -101,7 +101,7 @@ const columns = ref<QTableColumn[]>([
|
||||||
{
|
{
|
||||||
name: "beginningLeaveDays",
|
name: "beginningLeaveDays",
|
||||||
align: "left",
|
align: "left",
|
||||||
label: "ยกมา (วัน)",
|
label: "จำนวนวันลาก่อนใช้งานระบบ",
|
||||||
sortable: true,
|
sortable: true,
|
||||||
field: "beginningLeaveDays",
|
field: "beginningLeaveDays",
|
||||||
headerStyle: "font-size: 14px",
|
headerStyle: "font-size: 14px",
|
||||||
|
|
@ -110,7 +110,7 @@ const columns = ref<QTableColumn[]>([
|
||||||
{
|
{
|
||||||
name: "beginningLeaveCount",
|
name: "beginningLeaveCount",
|
||||||
align: "left",
|
align: "left",
|
||||||
label: "ยกมา (ครั้ง)",
|
label: "จำนวนครั้งที่ลาก่อนใช้งานระบบ",
|
||||||
sortable: true,
|
sortable: true,
|
||||||
field: "beginningLeaveCount",
|
field: "beginningLeaveCount",
|
||||||
headerStyle: "font-size: 14px",
|
headerStyle: "font-size: 14px",
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
import { ref } from "vue";
|
import { ref } from "vue";
|
||||||
import { useRoute } from "vue-router";
|
import { useRoute } from "vue-router";
|
||||||
import { useQuasar } from "quasar";
|
import { useQuasar } from "quasar";
|
||||||
|
import type { QTableColumn } from "quasar";
|
||||||
|
|
||||||
import http from "@/plugins/http";
|
import http from "@/plugins/http";
|
||||||
import config from "@/app.config";
|
import config from "@/app.config";
|
||||||
|
|
@ -22,21 +23,12 @@ const checkRoutePermisson = ref<boolean>(
|
||||||
route.name == "disciplineInvestigatefactsDetail"
|
route.name == "disciplineInvestigatefactsDetail"
|
||||||
);
|
);
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps<{
|
||||||
rows: {
|
rows?: any[];
|
||||||
type: Array,
|
columns?: QTableColumn[];
|
||||||
default: [],
|
visibleColumns?: string[];
|
||||||
},
|
fetchData?: () => void;
|
||||||
columns: {
|
}>();
|
||||||
type: Array,
|
|
||||||
default: [],
|
|
||||||
},
|
|
||||||
visibleColumns: {
|
|
||||||
type: Array,
|
|
||||||
default: [],
|
|
||||||
},
|
|
||||||
fetchData: Function,
|
|
||||||
});
|
|
||||||
|
|
||||||
const remark = ref<string>("");
|
const remark = ref<string>("");
|
||||||
const selected = ref<any[]>([]);
|
const selected = ref<any[]>([]);
|
||||||
|
|
@ -100,7 +92,7 @@ function onSubmit() {
|
||||||
<q-card-section class="q-pa-xs">
|
<q-card-section class="q-pa-xs">
|
||||||
<q-table
|
<q-table
|
||||||
:columns="props.columns"
|
:columns="props.columns"
|
||||||
:rows="rows"
|
:rows="props.rows ?? []"
|
||||||
row-key="personId"
|
row-key="personId"
|
||||||
flat
|
flat
|
||||||
bordered
|
bordered
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ import { useInvestigateFactStore } from "@/modules/11_discipline/store/Investiga
|
||||||
import { useDisciplineMainStore } from "@/modules/11_discipline/store/Main";
|
import { useDisciplineMainStore } from "@/modules/11_discipline/store/Main";
|
||||||
|
|
||||||
import type { ArrayPersonAdd } from "@/modules/11_discipline/interface/response/investigate";
|
import type { ArrayPersonAdd } from "@/modules/11_discipline/interface/response/investigate";
|
||||||
import type { FormData } from "@/modules/11_discipline/interface/request/InvestigateFact";
|
import type { FormData } from "@/modules/11_discipline/interface/request/investigateFact";
|
||||||
import type {
|
import type {
|
||||||
FormData as FormDataComplaint,
|
FormData as FormDataComplaint,
|
||||||
ArrayPerson,
|
ArrayPerson,
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ import { useInvestigateDisStore } from "@/modules/11_discipline/store/Investigat
|
||||||
import { useInvestigateFactStore } from "@/modules/11_discipline/store/InvestigateFactStore";
|
import { useInvestigateFactStore } from "@/modules/11_discipline/store/InvestigateFactStore";
|
||||||
import { useDisciplineMainStore } from "@/modules/11_discipline/store/Main";
|
import { useDisciplineMainStore } from "@/modules/11_discipline/store/Main";
|
||||||
|
|
||||||
import type { FormData } from "@/modules/11_discipline/interface/request/InvestigateFact";
|
import type { FormData } from "@/modules/11_discipline/interface/request/investigateFact";
|
||||||
import type { OptionData } from "@/modules/07_insignia/interface/index/Main";
|
import type { OptionData } from "@/modules/07_insignia/interface/index/Main";
|
||||||
|
|
||||||
import CalandarDialog from "@/modules/11_discipline/components/2_InvestigateFacts/CalandarDialog.vue";
|
import CalandarDialog from "@/modules/11_discipline/components/2_InvestigateFacts/CalandarDialog.vue";
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ import type {
|
||||||
FormData,
|
FormData,
|
||||||
Director,
|
Director,
|
||||||
PersonsArray,
|
PersonsArray,
|
||||||
} from "@/modules/11_discipline/interface/request/Disciplinary";
|
} from "@/modules/11_discipline/interface/request/disciplinary";
|
||||||
import type {
|
import type {
|
||||||
DataOption,
|
DataOption,
|
||||||
FileLists,
|
FileLists,
|
||||||
|
|
|
||||||
|
|
@ -260,7 +260,7 @@ watch(
|
||||||
keep-color
|
keep-color
|
||||||
color="primary"
|
color="primary"
|
||||||
dense
|
dense
|
||||||
:disable="commandType"
|
:disable="commandType === ''"
|
||||||
v-model="scope.selected"
|
v-model="scope.selected"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -271,7 +271,7 @@ watch(
|
||||||
keep-color
|
keep-color
|
||||||
color="primary"
|
color="primary"
|
||||||
dense
|
dense
|
||||||
:disable="commandType"
|
:disable="commandType === ''"
|
||||||
v-model="props.selected"
|
v-model="props.selected"
|
||||||
/>
|
/>
|
||||||
</q-td>
|
</q-td>
|
||||||
|
|
|
||||||
|
|
@ -9,13 +9,13 @@ import { useCounterMixin } from "@/stores/mixin";
|
||||||
import { useDisciplineResultStore } from "@/modules/11_discipline/store/ResultStore";
|
import { useDisciplineResultStore } from "@/modules/11_discipline/store/ResultStore";
|
||||||
import { useDisciplineMainStore } from "@/modules/11_discipline/store/Main";
|
import { useDisciplineMainStore } from "@/modules/11_discipline/store/Main";
|
||||||
|
|
||||||
import type { DataListRow } from "@/modules/11_discipline/interface/request/Result";
|
import type { DataListRow } from "@/modules/11_discipline/interface/request/result";
|
||||||
import type {
|
import type {
|
||||||
FormData as FormDataComplaint,
|
FormData as FormDataComplaint,
|
||||||
ArrayPerson,
|
ArrayPerson,
|
||||||
ArrayFileList,
|
ArrayFileList,
|
||||||
} from "@/modules/11_discipline/interface/request/complaint";
|
} from "@/modules/11_discipline/interface/request/complaint";
|
||||||
import type { FormData as FormInvestigateFact } from "@/modules/11_discipline/interface/request/InvestigateFact";
|
import type { FormData as FormInvestigateFact } from "@/modules/11_discipline/interface/request/investigateFact";
|
||||||
|
|
||||||
import DialogSendToCommand from "@/modules/11_discipline/components/4_Result/DialogSendToCommand.vue";
|
import DialogSendToCommand from "@/modules/11_discipline/components/4_Result/DialogSendToCommand.vue";
|
||||||
import FormComplaints from "@/modules/11_discipline/components/1_Complaint/Form.vue"; //เรื่องร้องเรียน
|
import FormComplaints from "@/modules/11_discipline/components/1_Complaint/Form.vue"; //เรื่องร้องเรียน
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,7 @@ watch(props, () => {
|
||||||
v-ripple
|
v-ripple
|
||||||
:active="listCheck === index"
|
:active="listCheck === index"
|
||||||
active-class="my-menu-link"
|
active-class="my-menu-link"
|
||||||
@click="clickList(index, item.director)"
|
@click="clickList(Number(index), item.director)"
|
||||||
>
|
>
|
||||||
<q-item-section>{{ item.title }}</q-item-section>
|
<q-item-section>{{ item.title }}</q-item-section>
|
||||||
</q-item>
|
</q-item>
|
||||||
|
|
|
||||||
|
|
@ -294,6 +294,7 @@ watch(
|
||||||
hide-bottom-space
|
hide-bottom-space
|
||||||
dense
|
dense
|
||||||
label="คำค้น"
|
label="คำค้น"
|
||||||
|
@keydown.enter.prevent="searchInput()"
|
||||||
>
|
>
|
||||||
<template v-slot:after>
|
<template v-slot:after>
|
||||||
<q-btn
|
<q-btn
|
||||||
|
|
|
||||||
|
|
@ -280,6 +280,7 @@ onMounted(async () => {
|
||||||
hide-bottom-space
|
hide-bottom-space
|
||||||
dense
|
dense
|
||||||
label="คำค้น"
|
label="คำค้น"
|
||||||
|
@keydown.enter.prevent="(pagination.page = 1), searchInput()"
|
||||||
>
|
>
|
||||||
<template v-slot:after>
|
<template v-slot:after>
|
||||||
<q-btn
|
<q-btn
|
||||||
|
|
|
||||||
|
|
@ -905,6 +905,7 @@ onMounted(() => {
|
||||||
hide-bottom-space
|
hide-bottom-space
|
||||||
dense
|
dense
|
||||||
label="คำค้น"
|
label="คำค้น"
|
||||||
|
@keydown.enter.prevent="(formFilter.page = 1), fetchListPerson()"
|
||||||
>
|
>
|
||||||
<template v-slot:after>
|
<template v-slot:after>
|
||||||
<q-btn
|
<q-btn
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,6 @@ let formData = reactive<FormDataDetail>({
|
||||||
});
|
});
|
||||||
const commandVolume = ref<string>(""); //เล่มที่
|
const commandVolume = ref<string>(""); //เล่มที่
|
||||||
const commandChapter = ref<string>(""); //ตอนที่
|
const commandChapter = ref<string>(""); //ตอนที่
|
||||||
const isIdofficer = ref<boolean>(false); //เช็ค สกจ.
|
|
||||||
|
|
||||||
const rows = ref<Array<DataOperators>>([]);
|
const rows = ref<Array<DataOperators>>([]);
|
||||||
const columns = ref<QTableProps["columns"]>([
|
const columns = ref<QTableProps["columns"]>([
|
||||||
|
|
@ -114,17 +113,7 @@ const visibleColumns = ref<Array<string>>([
|
||||||
|
|
||||||
const modalAddOperator = ref<boolean>(false); // แสดงเพิ่มรายชื่อลงนามในแนบท้ายคำสั่ง
|
const modalAddOperator = ref<boolean>(false); // แสดงเพิ่มรายชื่อลงนามในแนบท้ายคำสั่ง
|
||||||
|
|
||||||
/** ฟังก์ชันเช็ค สกจ.*/
|
|
||||||
async function fetchCheckIdofficer() {
|
|
||||||
await http
|
|
||||||
.get(config.API.checkIdofficer)
|
|
||||||
.then((res) => {
|
|
||||||
isIdofficer.value = res.data.result;
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
messageError($q, err);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ฟังก์ชันบันทึกข้อมูลรายละเอียดคำสั่ง
|
* ฟังก์ชันบันทึกข้อมูลรายละเอียดคำสั่ง
|
||||||
|
|
@ -133,7 +122,7 @@ async function fetchCheckIdofficer() {
|
||||||
async function onSubmit() {
|
async function onSubmit() {
|
||||||
//ถ้าเป็น สกจ. ต้องเลือกประเภทคำสั่งด้วย
|
//ถ้าเป็น สกจ. ต้องเลือกประเภทคำสั่งด้วย
|
||||||
if (
|
if (
|
||||||
isIdofficer.value &&
|
store.isIdofficer &&
|
||||||
formData.isBangkok !== "BANGKOK" &&
|
formData.isBangkok !== "BANGKOK" &&
|
||||||
formData.isBangkok !== "OFFICE"
|
formData.isBangkok !== "OFFICE"
|
||||||
) {
|
) {
|
||||||
|
|
@ -225,7 +214,6 @@ function onDeleteData(id: string) {
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
try {
|
try {
|
||||||
showLoader();
|
showLoader();
|
||||||
await fetchCheckIdofficer();
|
|
||||||
await fetchDataOperatorList();
|
await fetchDataOperatorList();
|
||||||
formData.commandNo = props.formCommandList.commandNo;
|
formData.commandNo = props.formCommandList.commandNo;
|
||||||
formData.commandYear = props.formCommandList.commandYear;
|
formData.commandYear = props.formCommandList.commandYear;
|
||||||
|
|
@ -235,7 +223,7 @@ onMounted(async () => {
|
||||||
formData.issue = props.formCommandList.issue;
|
formData.issue = props.formCommandList.issue;
|
||||||
formData.commandAffectDate = props.formCommandList.commandAffectDate;
|
formData.commandAffectDate = props.formCommandList.commandAffectDate;
|
||||||
formData.commandExcecuteDate = props.formCommandList.commandExcecuteDate;
|
formData.commandExcecuteDate = props.formCommandList.commandExcecuteDate;
|
||||||
formData.isBangkok = !isIdofficer.value
|
formData.isBangkok = !store.isIdofficer
|
||||||
? null
|
? null
|
||||||
: props.formCommandList.isBangkok;
|
: props.formCommandList.isBangkok;
|
||||||
commandCode.value = props.formCommandList.commandCode;
|
commandCode.value = props.formCommandList.commandCode;
|
||||||
|
|
@ -500,7 +488,7 @@ onMounted(async () => {
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class="col-12 q-gutter-sm"
|
class="col-12 q-gutter-sm"
|
||||||
v-if="isIdofficer && commandCode !== 'C-PM-47'"
|
v-if="store.isIdofficer && commandCode !== 'C-PM-47'"
|
||||||
>
|
>
|
||||||
<q-radio
|
<q-radio
|
||||||
:disable="store.readonly"
|
:disable="store.readonly"
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@ import { useQuasar, type QTableProps } from "quasar";
|
||||||
import { usePagination } from "@/composables/usePagination";
|
import { usePagination } from "@/composables/usePagination";
|
||||||
|
|
||||||
import { useCounterMixin } from "@/stores/mixin";
|
import { useCounterMixin } from "@/stores/mixin";
|
||||||
import { getColumnLabel } from "@/utils/function";
|
|
||||||
import http from "@/plugins/http";
|
import http from "@/plugins/http";
|
||||||
import config from "@/app.config";
|
import config from "@/app.config";
|
||||||
|
|
||||||
|
|
@ -274,9 +273,7 @@ watch(modal, (newVal) => {
|
||||||
:key="col.name"
|
:key="col.name"
|
||||||
:props="props"
|
:props="props"
|
||||||
>
|
>
|
||||||
<span class="text-weight-medium">{{
|
<span class="text-weight-medium">{{ col.label }}</span>
|
||||||
getColumnLabel(col, isAct)
|
|
||||||
}}</span>
|
|
||||||
</q-th>
|
</q-th>
|
||||||
</q-tr>
|
</q-tr>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -719,6 +719,7 @@ onMounted(async () => {
|
||||||
dense
|
dense
|
||||||
label="คำค้น"
|
label="คำค้น"
|
||||||
@clear="search = ''"
|
@clear="search = ''"
|
||||||
|
@keydown.enter.prevent="onSearchData"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<q-checkbox
|
<q-checkbox
|
||||||
|
|
|
||||||
|
|
@ -191,7 +191,6 @@ async function uploadFileDoc(
|
||||||
* @param group ประเภพไฟล์ "คำสั่ง","แนบท้าย"
|
* @param group ประเภพไฟล์ "คำสั่ง","แนบท้าย"
|
||||||
*/
|
*/
|
||||||
async function fetchDoc(group: string) {
|
async function fetchDoc(group: string) {
|
||||||
showLoader();
|
|
||||||
let type = group === "order" ? "คำสั่ง" : "แนบท้าย";
|
let type = group === "order" ? "คำสั่ง" : "แนบท้าย";
|
||||||
if (group === "order") {
|
if (group === "order") {
|
||||||
await fetchDocOrder(type);
|
await fetchDocOrder(type);
|
||||||
|
|
@ -292,7 +291,10 @@ function onConfirmOrder() {
|
||||||
if (
|
if (
|
||||||
store?.dataCommand?.commandNo !== "" &&
|
store?.dataCommand?.commandNo !== "" &&
|
||||||
store?.dataCommand?.commandAffectDate !== null &&
|
store?.dataCommand?.commandAffectDate !== null &&
|
||||||
store?.dataCommand?.commandExcecuteDate !== null
|
store?.dataCommand?.commandExcecuteDate !== null &&
|
||||||
|
(!store.isIdofficer ||
|
||||||
|
store?.dataCommand?.isBangkok === "BANGKOK" ||
|
||||||
|
store?.dataCommand?.isBangkok === "OFFICE")
|
||||||
) {
|
) {
|
||||||
dialogConfirm(
|
dialogConfirm(
|
||||||
$q,
|
$q,
|
||||||
|
|
@ -316,10 +318,10 @@ function onConfirmOrder() {
|
||||||
"คุณต้องการยืนยันการส่งออกคำสั่งใช่หรือไม่?"
|
"คุณต้องการยืนยันการส่งออกคำสั่งใช่หรือไม่?"
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
dialogMessageNotify(
|
const messageWarning = !store.isIdofficer
|
||||||
$q,
|
? "ไม่สามารถดำเนินการต่อได้ กรุณากรอกเลขที่คำสั่ง วันที่ลงนาม และวันที่คำสั่งมีผลให้ครบ"
|
||||||
"ไม่สามารถดำเนินการต่อได้ กรุณากรอกเลขที่คำสั่ง วันที่ลงนาม และวันที่คำสั่งมีผลให้ครบ"
|
: "ไม่สามารถดำเนินการต่อได้ กรุณากรอกเลขที่คำสั่ง วันที่ลงนาม วันที่คำสั่งมีผล และเลือกคำสั่งให้ครบ";
|
||||||
);
|
dialogMessageNotify($q, messageWarning);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,8 @@ export const useCommandDetail = defineStore("commandDetailStore", () => {
|
||||||
const readonly = ref<boolean>(false);
|
const readonly = ref<boolean>(false);
|
||||||
const dataCommand = ref<FormDataDetail>();
|
const dataCommand = ref<FormDataDetail>();
|
||||||
const status = ref<string>("");
|
const status = ref<string>("");
|
||||||
const isSalary = ref<boolean>(false)
|
const isSalary = ref<boolean>(false);
|
||||||
|
const isIdofficer = ref<boolean>(false);
|
||||||
function checkStep(val: string) {
|
function checkStep(val: string) {
|
||||||
status.value = val;
|
status.value = val;
|
||||||
switch (val) {
|
switch (val) {
|
||||||
|
|
@ -39,6 +40,7 @@ export const useCommandDetail = defineStore("commandDetailStore", () => {
|
||||||
readonly,
|
readonly,
|
||||||
status,
|
status,
|
||||||
dataCommand,
|
dataCommand,
|
||||||
isSalary
|
isSalary,
|
||||||
|
isIdofficer,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -92,11 +92,24 @@ async function fetchDataCommandList() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** ฟังก์ชันเช็ค สกจ.*/
|
||||||
|
async function fetchCheckIdofficer() {
|
||||||
|
await http
|
||||||
|
.get(config.API.checkIdofficer)
|
||||||
|
.then((res) => {
|
||||||
|
store.isIdofficer = res.data.result;
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
messageError($q, err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ทำงานเมื่อ Components ถูกเรียกใช้งาน
|
* ทำงานเมื่อ Components ถูกเรียกใช้งาน
|
||||||
* กำหนดค่า `store.readonly` เมื่อ route.name เป็น "commandViewDetailPage" จะอ่านข้อมูลได้อย่างเดียว
|
* กำหนดค่า `store.readonly` เมื่อ route.name เป็น "commandViewDetailPage" จะอ่านข้อมูลได้อย่างเดียว
|
||||||
*/
|
*/
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
|
await fetchCheckIdofficer();
|
||||||
await fetchDataCommandList();
|
await fetchDataCommandList();
|
||||||
store.readonly =
|
store.readonly =
|
||||||
route.name === "commandViewDetailPage" ||
|
route.name === "commandViewDetailPage" ||
|
||||||
|
|
|
||||||
|
|
@ -454,7 +454,6 @@ onMounted(async () => {
|
||||||
table-class="text-grey-9"
|
table-class="text-grey-9"
|
||||||
row-key="id"
|
row-key="id"
|
||||||
dense
|
dense
|
||||||
hide-bottom
|
|
||||||
bordered
|
bordered
|
||||||
separator="vertical"
|
separator="vertical"
|
||||||
class="custom-header-table-expand"
|
class="custom-header-table-expand"
|
||||||
|
|
|
||||||
|
|
@ -13,8 +13,10 @@ export const useIssueStore = defineStore("issue", () => {
|
||||||
const statusOptions = ref<Options[]>([
|
const statusOptions = ref<Options[]>([
|
||||||
{ label: "ทั้งหมด", value: "" },
|
{ label: "ทั้งหมด", value: "" },
|
||||||
{ label: "ใหม่", value: "NEW" },
|
{ label: "ใหม่", value: "NEW" },
|
||||||
{ label: "กำลังดำเนินการ", value: "IN_PROGRESS" },
|
{ label: "Dev กำลังดำเนินการ", value: "IN_PROGRESS" },
|
||||||
{ label: "แก้ไขแล้ว", value: "RESOLVED" },
|
{ label: "แก้ไขแล้ว", value: "RESOLVED" },
|
||||||
|
{ label: "Helpdesk กำลังดำเนินการ", value: "HELPDESK_IN_PROGRESS" },
|
||||||
|
{ label: "แจ้งกลับแล้ว", value: "REPLIED" },
|
||||||
{ label: "ปิดแล้ว", value: "CLOSED" },
|
{ label: "ปิดแล้ว", value: "CLOSED" },
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
@ -29,6 +31,10 @@ export const useIssueStore = defineStore("issue", () => {
|
||||||
return "แก้ไขแล้ว";
|
return "แก้ไขแล้ว";
|
||||||
case "CLOSED":
|
case "CLOSED":
|
||||||
return "ปิดแล้ว";
|
return "ปิดแล้ว";
|
||||||
|
case "HELPDESK_IN_PROGRESS":
|
||||||
|
return "Helpdesk กำลังดำเนินการ";
|
||||||
|
case "REPLIED":
|
||||||
|
return "แจ้งกลับแล้ว";
|
||||||
default:
|
default:
|
||||||
return "-";
|
return "-";
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ const { convertStatus, convertSystem } = store;
|
||||||
const { systemOptions, statusOptions } = storeToRefs(store);
|
const { systemOptions, statusOptions } = storeToRefs(store);
|
||||||
|
|
||||||
const visibleColumns = ref<string[]>([
|
const visibleColumns = ref<string[]>([
|
||||||
|
"codeIssue",
|
||||||
"title",
|
"title",
|
||||||
"description",
|
"description",
|
||||||
"system",
|
"system",
|
||||||
|
|
@ -34,6 +35,43 @@ const visibleColumns = ref<string[]>([
|
||||||
"status",
|
"status",
|
||||||
]);
|
]);
|
||||||
const columns = ref<QTableProps["columns"]>([
|
const columns = ref<QTableProps["columns"]>([
|
||||||
|
{
|
||||||
|
name: "codeIssue",
|
||||||
|
align: "left",
|
||||||
|
label: "รหัส",
|
||||||
|
sortable: false,
|
||||||
|
field: "codeIssue",
|
||||||
|
headerStyle: "font-size: 14px",
|
||||||
|
style: "font-size: 14px",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "createdAt",
|
||||||
|
align: "left",
|
||||||
|
label: "วันที่สร้าง",
|
||||||
|
sortable: false,
|
||||||
|
field: "createdAt",
|
||||||
|
headerStyle: "font-size: 14px",
|
||||||
|
style: "font-size: 14px",
|
||||||
|
format: (val: string) => date2Thai(new Date(val), false, true),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "org",
|
||||||
|
align: "left",
|
||||||
|
label: "หน่วยงาน",
|
||||||
|
sortable: false,
|
||||||
|
field: "org",
|
||||||
|
headerStyle: "font-size: 14px",
|
||||||
|
style: "font-size: 14px",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "createdFullName",
|
||||||
|
align: "left",
|
||||||
|
label: "ชื่อผู้สร้าง",
|
||||||
|
sortable: false,
|
||||||
|
field: "createdFullName",
|
||||||
|
headerStyle: "font-size: 14px",
|
||||||
|
style: "font-size: 14px",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "title",
|
name: "title",
|
||||||
align: "left",
|
align: "left",
|
||||||
|
|
@ -72,15 +110,6 @@ const columns = ref<QTableProps["columns"]>([
|
||||||
style: "font-size: 14px",
|
style: "font-size: 14px",
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
|
||||||
name: "org",
|
|
||||||
align: "left",
|
|
||||||
label: "หน่วยงาน",
|
|
||||||
sortable: false,
|
|
||||||
field: "org",
|
|
||||||
headerStyle: "font-size: 14px",
|
|
||||||
style: "font-size: 14px",
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: "email",
|
name: "email",
|
||||||
align: "left",
|
align: "left",
|
||||||
|
|
@ -100,25 +129,6 @@ const columns = ref<QTableProps["columns"]>([
|
||||||
style: "font-size: 14px",
|
style: "font-size: 14px",
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
|
||||||
name: "createdAt",
|
|
||||||
align: "left",
|
|
||||||
label: "วันที่สร้าง",
|
|
||||||
sortable: false,
|
|
||||||
field: "createdAt",
|
|
||||||
headerStyle: "font-size: 14px",
|
|
||||||
style: "font-size: 14px",
|
|
||||||
format: (val: string) => date2Thai(new Date(val), false, true),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "createdFullName",
|
|
||||||
align: "left",
|
|
||||||
label: "ชื่อผู้สร้าง",
|
|
||||||
sortable: false,
|
|
||||||
field: "createdFullName",
|
|
||||||
headerStyle: "font-size: 14px",
|
|
||||||
style: "font-size: 14px",
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: "status",
|
name: "status",
|
||||||
align: "left",
|
align: "left",
|
||||||
|
|
|
||||||
|
|
@ -73,3 +73,24 @@ export function getColumnLabel(col: any, isAct: boolean) {
|
||||||
}
|
}
|
||||||
return col.label;
|
return col.label;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ตรวจสอบขนาดไฟล์
|
||||||
|
* @param val ไฟล์หรืออาร์เรย์ของไฟล์ที่ต้องการตรวจสอบ
|
||||||
|
* @param maxSizeMB ขนาดจำกัดในหน่วย MB (ค่าเริ่มต้นคือ 10MB)
|
||||||
|
* @returns true หากไฟล์ทั้งหมดมีขนาดไม่เกินที่กำหนด, หรือข้อความแจ้งเตือนหากมีไฟล์ที่เกินขนาด
|
||||||
|
*/
|
||||||
|
export function validateFileSize(
|
||||||
|
val: File | File[],
|
||||||
|
maxSizeMB: number = 10
|
||||||
|
): string | true {
|
||||||
|
if (!val) return true;
|
||||||
|
|
||||||
|
const filesArray = Array.isArray(val) ? val : [val];
|
||||||
|
const limit = maxSizeMB * 1024 * 1024;
|
||||||
|
|
||||||
|
const isAllValid = filesArray.every((file: File) => file.size <= limit);
|
||||||
|
if (isAllValid) return true;
|
||||||
|
|
||||||
|
return `ขนาดไฟล์ไม่เกิน ${maxSizeMB}MB`;
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue