hrms-mgt/src/modules/03_recruiting/views/02_qualify/PeriodAdd.vue

1904 lines
77 KiB
Vue

<!-- page:ดการรอบการสอบ สรรหา -->
<template>
<div class="toptitle text-dark col-12 row items-center">
<q-btn
icon="mdi-arrow-left"
unelevated
round
dense
flat
color="primary"
class="q-mr-sm"
@click="clickBack"
/>
{{ edit ? `แก้ไขรอบ` : "เพิ่มรอบคัดเลือก" }}
{{
edit && announcementExam
? `${name} ครั้งที่ ${roundRaw}/${
yearlyRaw == null ? "" : yearlyRaw + 543
}`
: ""
}}
</div>
<q-card flat bordered class="col-12 q-my-sm q-pt-sm">
<q-form ref="myForm">
<q-card-section class="q-pa-md">
<div class="col-xs-12 col-sm-8 items-top q-pb-md">
<q-toggle
v-model="announcementExam"
:false-value="true"
:true-value="false"
color="primary"
label="ประกาศข่าวทั่วไป"
v-if="!edit"
/>
</div>
<div class="col-12 row items-top q-col-gutter-x-sm">
<div class="col-xs-12 col-sm-6 col-sm-5">
<q-input
outlined
v-model="name"
label="ชื่อรอบคัดเลือก/ชื่อประกาศ"
dense
lazy-rules
:rules="[
(val) => !!val || `${'กรุณากรอกชื่อรอบคัดเลือก/ชื่อประกาศ'}`,
]"
></q-input>
</div>
<div class="col-xs-12 col-sm-4 col-md-1" v-if="announcementExam">
<q-input
outlined
v-model="round"
type="number"
label="รอบการสอบ(ครั้ง)"
dense
lazy-rules
:rules="[(val) => val > 0 || `${'กรุณากรอกรอบการสอบให้ถูกต้อง'}`]"
></q-input>
</div>
<div class="col-xs-12 col-sm-4 col-md-1" v-if="announcementExam">
<q-input
outlined
v-model="fee"
type="number"
label="ค่าธรรมเนียม"
dense
lazy-rules
input-class="text-right"
:rules="[
(val) => val >= 0 || `${'กรุณากรอกค่าธรรมเนียมให้ถูกต้อง'}`,
]"
></q-input>
</div>
<div class="col-xs-12 col-sm-4 col-md-1" v-if="announcementExam">
<datepicker
menu-class-name="modalfix"
v-model="yearly"
:locale="'th'"
autoApply
year-picker
:enableTimePicker="false"
@update:modelValue="updateYear"
>
<template #year="{ year }">{{ year + 543 }}</template>
<template #year-overlay-value="{ value }">{{
parseInt(value + 543)
}}</template>
<template #trigger>
<q-input
dense
lazy-rules
outlined
:model-value="yearly + 543"
:rules="[(val) => !!val || `${'กรุณาเลือกปีงบประมาณ'}`]"
:label="`${'ปีงบประมาณ'}`"
>
<!-- <template v-slot:prepend>
<q-icon
name="event"
class="cursor-pointer"
style="color: var(--q-primary)"
>
</q-icon>
</template> -->
</q-input>
</template>
</datepicker>
</div>
<div class="col-xs-12 col-sm-3 col-md-3" v-if="announcementExam">
<datepicker
menu-class-name="modalfix"
v-model="dateExam"
:locale="'th'"
autoApply
borderless
:enableTimePicker="false"
week-start="0"
>
<template #year="{ year }">
{{ year + 543 }}
</template>
<template #year-overlay-value="{ value }">
{{ parseInt(value + 543) }}
</template>
<template #trigger>
<q-input
outlined
dense
class="full-width datepicker q-mb-md"
:model-value="dateExam != null ? date2Thai(dateExam) : null"
:label="`${'วันที่สอบ'}`"
clearable
@clear="clearDateExam"
>
<template v-slot:prepend>
<q-icon
name="event"
class="cursor-pointer"
style="color: var(--q-primary)"
>
</q-icon>
</template>
</q-input>
</template>
</datepicker>
</div>
<div class="col-xs-12 col-sm-3 col-md-3">
<datepicker
menu-class-name="modalfix"
v-model="dateAnnouncement"
:locale="'th'"
autoApply
borderless
range
:enableTimePicker="false"
week-start="0"
>
<template #year="{ year }">
{{ year + 543 }}
</template>
<template #year-overlay-value="{ value }">
{{ parseInt(value + 543) }}
</template>
<template #trigger>
<q-input
outlined
dense
class="full-width datepicker q-mb-md"
:model-value="dateThaiRange(dateAnnouncement)"
:label="`${'วันที่ประกาศ'}`"
:rules="[(val) => !!val || `${'กรุณาเลือกวันที่ประกาศ'}`]"
>
<template v-slot:prepend>
<q-icon
name="event"
class="cursor-pointer"
style="color: var(--q-primary)"
>
</q-icon>
</template>
</q-input>
</template>
</datepicker>
</div>
<div class="col-xs-12 col-sm-3 col-md-3" v-if="announcementExam">
<datepicker
menu-class-name="modalfix"
v-model="dateRegister"
:locale="'th'"
autoApply
clearValue
borderless
range
:enableTimePicker="false"
week-start="0"
>
<template #year="{ year }">
{{ year + 543 }}
</template>
<template #year-overlay-value="{ value }">
{{ parseInt(value + 543) }}
</template>
<template #trigger>
<q-input
outlined
dense
class="full-width datepicker q-mb-md"
:model-value="dateThaiRange(dateRegister)"
:label="`${'วันที่สมัคร'}`"
clearable
@clear="clearDateRegister"
>
<template v-slot:prepend>
<q-icon
name="event"
class="cursor-pointer"
style="color: var(--q-primary)"
>
</q-icon>
</template>
</q-input>
</template>
</datepicker>
</div>
<div
class="col-xs-12 col-sm-3 col-md-3"
v-if="announcementExam && fee != 0"
>
<datepicker
menu-class-name="modalfix"
v-model="datePayment"
:locale="'th'"
autoApply
borderless
range
:enableTimePicker="false"
week-start="0"
>
<template #year="{ year }">
{{ year + 543 }}
</template>
<template #year-overlay-value="{ value }">
{{ parseInt(value + 543) }}
</template>
<template #trigger>
<q-input
outlined
dense
class="full-width datepicker q-mb-md"
:model-value="dateThaiRange(datePayment)"
:label="`${'วันที่ชำระเงิน'}`"
clearable
@clear="clearDatePayment"
>
<template v-slot:prepend>
<q-icon
name="event"
class="cursor-pointer"
style="color: var(--q-primary)"
>
</q-icon>
</template>
</q-input>
</template>
</datepicker>
</div>
<div class="col-xs-12 col-sm-3 col-md-3" v-if="announcementExam">
<datepicker
menu-class-name="modalfix"
v-model="dateAnnounce"
:locale="'th'"
autoApply
borderless
:enableTimePicker="false"
week-start="0"
>
<template #year="{ year }">
{{ year + 543 }}
</template>
<template #year-overlay-value="{ value }">
{{ parseInt(value + 543) }}
</template>
<template #trigger>
<q-input
outlined
dense
class="full-width datepicker q-mb-md"
:model-value="
dateAnnounce != null ? date2Thai(dateAnnounce) : null
"
:label="`${'วันประกาศผลสอบ'}`"
clearable
@clear="clearDateAnnounce"
>
<template v-slot:prepend>
<q-icon
name="event"
class="cursor-pointer"
style="color: var(--q-primary)"
>
</q-icon>
</template>
</q-input>
</template>
</datepicker>
</div>
<!-- <div class="col-xs-12 col-sm-3 col-md-3">
<selector
outlined
v-model="category"
:options="categoryOptions"
label="สังกัด"
clearable
option-value="id"
option-label="name"
emit-value
map-options
dense
lazy-rules
:rules="[(val:any) => !!val || `${'กรุณาเลือกสังกัด'}`]"
></selector>
</div> -->
<div class="col-12" v-if="announcementExam">
<!-- <div class="row q-col-gutter-x-sm">
<div class="col-xs-12 col-sm-6 col-md-6">
<selector
outlined
v-model="organizationShortName"
:options="governmentCodeOption"
label="รหัสส่วนราชการ"
clearable
option-value="id"
option-label="name"
dense
lazy-rules
:rules="[(val:any) => !!val || `${'กรุณาเลือกรหัสส่วนราชการ'}`]"
@update:model-value="(value:any) => selectGovernmentCode(value)"
></selector>
</div>
<div class="col-xs-12 col-sm-6 col-md-6">
<selector
outlined
v-model="organizationName"
:options="organizationNameOptions"
label="หน่วยงาน"
clearable
option-value="id"
option-label="name"
dense
lazy-rules
:rules="[(val:any) => !!val || `${'กรุณาเลือกหน่วยงาน'}`]"
@update:model-value="(value:any) => selectOrganization(value)"
></selector>
</div>
</div> -->
<div class="col-12 q-mb-sm">
<q-separator size="5px" color="grey-2" />
</div>
<q-form ref="myFormPosition">
<ProfileTable
:rows="rowsPosition"
:columns="columnsPosition"
:filter="filterPosition"
:visible-columns="visibleColumnsPosition"
v-model:inputfilter="filterPosition"
v-model:inputvisible="visibleColumnsPosition"
:add="clickAddPosition"
name="ตำแหน่ง"
icon=""
:statusEdit="false"
:headerShow="false"
>
<template #columns="props">
<q-tr :props="props">
<q-td key="code" :props="props">
<q-input
outlined
dense
lazy-rules
v-model="props.row.code"
:rules="[
(val) =>
val.length >= 4 ||
`${'กรุณากรอกรหัสประจำตำแหน่งที่สอบ'}`,
]"
:label="`${'รหัสประจำตำแหน่งที่สอบ'}`"
@update:modelValue="clickEditRow"
hide-bottom-space
mask="####"
/>
</q-td>
<q-td key="position" :props="props">
<selector
class=""
outlined
use-input
v-model="props.row.position"
:options="positionPathOptions"
option-value="id"
option-label="name"
input-debounce="0"
dense
hide-bottom-space
lazy-rules
:rules="[(val:any) => !!val || `${'กรุณาเลือกตำแหน่ง'}`]"
@filter="(inputValue:any,
doneFn:Function) => filterSelector(inputValue, doneFn,'position'
) "
>
<template v-slot:option="scope">
<q-item v-bind="scope.itemProps">
<q-item-section>
<q-item-label>{{ scope.opt.name }}</q-item-label>
</q-item-section>
</q-item>
</template>
<template v-slot:selected-item="scope">
ตำแหน่ง:
<q-chip
dense
square
class="q-my-none q-ml-xs q-mr-none"
>
{{ scope.opt.name }}
</q-chip>
</template>
</selector>
</q-td>
<q-td key="level" :props="props">
<selector
class=""
outlined
use-input
v-model="props.row.level"
:options="positionLevelOptions"
option-value="id"
option-label="name"
input-debounce="0"
dense
hide-bottom-space
lazy-rules
:rules="[(val:any) => !!val || `${'กรุณาเลือกระดับ'}`]"
@filter="(inputValue:any,
doneFn:Function) => filterSelector(inputValue, doneFn,'positionLevel'
) "
>
<template v-slot:option="scope">
<q-item v-bind="scope.itemProps">
<q-item-section>
<q-item-label>{{ scope.opt.name }}</q-item-label>
</q-item-section>
</q-item>
</template>
<template v-slot:selected-item="scope">
ระดับ:
<q-chip
dense
square
class="q-my-none q-ml-xs q-mr-none"
>
{{ scope.opt.name }}
</q-chip>
</template>
</selector>
</q-td>
<q-td key="highDegree" :props="props">
<q-radio
v-model="props.row.highDegree"
label="ประเภททั่วไป"
color="teal"
val="0"
/>
<q-radio
v-model="props.row.highDegree"
label="ประเภทวิชาการ"
color="teal"
val="1"
/>
</q-td>
<q-td key="type" :props="props">
<selector
class=""
outlined
v-model="props.row.type"
:options="examTypeOptions"
option-value="id"
option-label="name"
dense
hide-bottom-space
lazy-rules
:rules="[(val:any) => !!val || `${'กรุณาเลือกประเภทแบบฟอร์ม'}`]"
></selector>
</q-td>
<q-td auto-width>
<q-btn
color="red"
flat
dense
round
size="14px"
icon="mdi-delete"
@click="clickDeletePosition(props.row)"
/>
</q-td>
</q-tr>
</template>
</ProfileTable>
</q-form>
</div>
<div class="col-12" v-if="announcementExam && fee != 0">
<q-separator size="5px" color="grey-2" class="q-mt-lg" />
</div>
<div class="col-12 q-mt-lg" v-if="announcementExam && fee != 0">
<div class="text-bold text-subtitle2 q-pb-md">
เลือกวิธีการชำระเงิน
</div>
<div class="row col-12 q-gutter-y-md q-mb-md">
<q-list dense bordered class="col-12 rounded-borders">
<q-item tag="label" v-ripple class="q-pa-md">
<q-radio
v-model="pay"
val="payment1"
color="blue"
class="q-mr-md"
:disable="fee <= 0"
/>
<q-item-section avatar>
<q-avatar size="28px">
<q-img src="@/assets/krungthai.png" class="col-12" />
</q-avatar>
</q-item-section>
<q-item-section>
<q-item-label class="text-weight-medium text-subtitle1"
>ชำระเงินค่าสมัครสอบผ่านธนาคารกรุงไทย</q-item-label
>
</q-item-section>
</q-item>
</q-list>
<q-list dense bordered class="col-12 rounded-borders">
<q-item tag="label" v-ripple class="q-py-lg">
<q-radio
v-model="pay"
val="payment2"
color="blue"
class="q-mr-md"
:disable="fee <= 0"
/>
<q-item-section avatar>
<q-icon name="mdi-cash" color="positive" size="33px" />
</q-item-section>
<q-item-section>
<q-item-label class="text-weight-medium text-subtitle1"
>ชำระเงินค่าสมัครสอบผ่านสำนัก/หน่วยงาน</q-item-label
>
</q-item-section>
</q-item>
<q-slide-transition :duration="100">
<div v-show="pay == 'payment2'" class="q-pa-sm bg-grey-1">
<q-form ref="myFormPayment">
<ProfileTable
:rows="rowsPayment"
:columns="columnsPayment"
:filter="filterPayment"
:visible-columns="visibleColumnsPayment"
v-model:inputfilter="filterPayment"
v-model:inputvisible="visibleColumnsPayment"
:add="clickAddPayment"
name=""
icon=""
:statusEdit="false"
:headerShow="false"
>
<template #columns="props">
<q-tr :props="props">
<q-td key="accountNumber" :props="props">
<q-input
class=""
outlined
hide-bottom-space
v-model="props.row.accountNumber"
dense
lazy-rules
mask="###-#-#####-#"
:rules="[
(val) =>
(val && val.length > 0) ||
'กรุณากรอกข้อมูลให้ครบ',
]"
></q-input>
</q-td>
<q-td key="bankName" :props="props">
<q-input
class=""
outlined
hide-bottom-space
v-model="props.row.bankName"
dense
lazy-rules
:rules="[
(val) =>
(val && val.length > 0) ||
'กรุณากรอกข้อมูลให้ครบ',
]"
></q-input>
</q-td>
<q-td key="accountName" :props="props">
<q-input
class=""
outlined
hide-bottom-space
v-model="props.row.accountName"
dense
lazy-rules
:rules="[
(val) =>
(val && val.length > 0) ||
'กรุณากรอกข้อมูลให้ครบ',
]"
></q-input>
</q-td>
<q-td auto-width>
<q-btn
color="red"
flat
dense
round
size="14px"
icon="mdi-delete"
@click="clickDeletePayment(props.row)"
/>
</q-td>
</q-tr>
</template>
</ProfileTable>
</q-form>
</div>
</q-slide-transition>
</q-list>
</div>
</div>
<div class="col-12" v-if="announcementExam">
<q-separator size="5px" color="grey-2" class="q-mt-md q-mb-lg" />
</div>
<div class="row col-12 items-top q-col-gutter-x-sm">
<div class="col-xs-12 col-sm-6">
<div class="text-bold text-subtitle2 q-pb-sm">รูปภาพประกอบ</div>
<div class="row justify-center row col-12">
<q-uploader
color="gray"
type="file"
flat
ref="uploader"
class="full-width"
text-color="dark"
:max-size="10000000"
accept=".jpg,.png,.pdf,.csv,.doc,.docx"
bordered
label="[ไฟล์ jpg,png,pdf,csv,doc,docx ขนาดไม่เกิน 10MB]"
multiple
@added="fileUploadImg"
@removed="fileRemoveImg"
>
<template v-slot:header="scope">
<div
class="row no-wrap items-center q-pa-sm q-gutter-xs text-white"
>
<q-btn
v-if="scope.queuedFiles.length > 0"
icon="clear_all"
@click="scope.removeQueuedFiles"
round
dense
flat
>
<q-tooltip>ลบทั้งหมด</q-tooltip>
</q-btn>
<q-btn
v-if="scope.uploadedFiles.length > 0"
icon="done_all"
@click="scope.removeUploadedFiles"
round
dense
flat
>
<q-tooltip>ลบไฟล์ที่อัปโหลด</q-tooltip>
</q-btn>
<q-spinner
v-if="scope.isUploading"
class="q-uploader__spinner"
/>
<div class="col">
<div class="q-uploader__title">
{{
"[ไฟล์ jpg,png,pdf,csv,doc,docx ขนาดไม่เกิน 10MB]"
}}
</div>
<div class="q-uploader__subtitle">
{{ scope.uploadSizeLabel }}
/
{{ scope.uploadProgressLabel }}
</div>
</div>
<q-btn
v-if="scope.canAddFiles"
type="a"
icon="add_box"
@click="scope.pickFiles"
round
dense
flat
>
<q-uploader-add-trigger />
<q-tooltip>เลือกไฟล์</q-tooltip>
</q-btn>
<q-btn
v-if="scope.isUploading"
icon="clear"
@click="scope.abort"
round
dense
flat
>
<q-tooltip>ยกเลิกการอัปโหลด</q-tooltip>
</q-btn>
</div>
</template>
</q-uploader>
</div>
<q-card
bordered
flat
class="full-width q-my-md"
v-if="fileImgs.length != 0"
>
<q-list separator>
<q-item
v-for="file in fileImgs"
:key="file.id"
class="q-my-xs"
>
<q-item-section>
<q-item-label class="full-width ellipsis">
{{ file.fileName }}
</q-item-label>
<q-item-label caption>
สถานะ: {{ file.fileType }} /
{{ file.fileSize }}
</q-item-label>
</q-item-section>
<q-item-section top side>
<div class="q-gutter-sm">
<q-btn
size="12px"
flat
dense
round
color="blue"
icon="mdi-download-outline"
@click="downloadData(file.detail)"
>
<q-tooltip>ดาวน์โหลด</q-tooltip>
</q-btn>
<q-btn
size="12px"
flat
dense
round
color="red"
icon="mdi-delete-outline"
v-if="edit"
@click="deleteDocData(file.id)"
>
<q-tooltip>ลบไฟล์</q-tooltip>
</q-btn>
</div>
</q-item-section>
</q-item>
</q-list>
</q-card>
</div>
<div class="col-xs-12 col-sm-6">
<div class="text-bold text-subtitle2 q-pb-sm">เอกสารประกอบ</div>
<div class="row justify-center row col-12">
<q-uploader
color="gray"
type="file"
flat
ref="uploader"
class="full-width"
text-color="dark"
:max-size="10000000"
accept=".jpg,.png,.pdf,.csv,.doc,.docx"
bordered
label="[ไฟล์ jpg,png,pdf,csv,doc,docx ขนาดไม่เกิน 10MB]"
multiple
@added="fileUploadDoc"
@removed="fileRemoveDoc"
>
<template v-slot:header="scope">
<div
class="row no-wrap items-center q-pa-sm q-gutter-xs text-white"
>
<q-btn
v-if="scope.queuedFiles.length > 0"
icon="clear_all"
@click="scope.removeQueuedFiles"
round
dense
flat
>
<q-tooltip>ลบทงหมด</q-tooltip>
</q-btn>
<q-btn
v-if="scope.uploadedFiles.length > 0"
icon="done_all"
@click="scope.removeUploadedFiles"
round
dense
flat
>
<q-tooltip>ลบไฟลปโหลด</q-tooltip>
</q-btn>
<q-spinner
v-if="scope.isUploading"
class="q-uploader__spinner"
/>
<div class="col">
<div class="q-uploader__title">
{{
"[ไฟล์ jpg,png,pdf,csv,doc,docx ขนาดไม่เกิน 10MB]"
}}
</div>
<div class="q-uploader__subtitle">
{{ scope.uploadSizeLabel }}
/
{{ scope.uploadProgressLabel }}
</div>
</div>
<q-btn
v-if="scope.canAddFiles"
type="a"
icon="add_box"
@click="scope.pickFiles"
round
dense
flat
>
<q-uploader-add-trigger />
<q-tooltip>เลอกไฟล</q-tooltip>
</q-btn>
<q-btn
v-if="scope.isUploading"
icon="clear"
@click="scope.abort"
round
dense
flat
>
<q-tooltip>ยกเลกการอปโหลด</q-tooltip>
</q-btn>
</div>
</template>
</q-uploader>
</div>
<q-card
bordered
flat
class="full-width q-my-md"
v-if="fileDocs.length != 0"
>
<q-list separator>
<q-item
v-for="file in fileDocs"
:key="file.id"
class="q-my-xs"
>
<q-item-section>
<q-item-label class="full-width ellipsis">
{{ file.fileName }}
</q-item-label>
<q-item-label caption>
สถานะ: {{ file.fileType }} /
{{ file.fileSize }}
</q-item-label>
</q-item-section>
<q-item-section top side>
<div class="q-gutter-sm">
<q-btn
size="12px"
flat
dense
round
color="blue"
icon="mdi-download-outline"
@click="downloadData(file.detail)"
>
<q-tooltip>ดาวนโหลด</q-tooltip>
</q-btn>
<q-btn
size="12px"
flat
dense
round
color="red"
icon="mdi-delete-outline"
v-if="edit"
@click="deleteDocData(file.id)"
>
<q-tooltip>ลบไฟล</q-tooltip>
</q-btn>
</div>
</q-item-section>
</q-item>
</q-list>
</q-card>
</div>
</div>
<div class="col-12">
<q-separator size="5px" color="grey-2" class="q-my-lg" />
</div>
<div class="col-12">
<div class="text-bold text-subtitle2 q-pb-sm">รายละเอยด</div>
<q-editor
v-model="editor"
:dense="$q.screen.lt.md"
toolbar-text-color="blue-grey-10"
toolbar-bg="blue-grey-2"
toolbar-toggle-color="blue-grey-8"
class="editor"
:toolbar="[
['left', 'center', 'right', 'justify'],
[
'bold',
'italic',
'strike',
'underline',
'subscript',
'superscript',
],
['token', 'hr', 'link', 'custom_btn'],
['print', 'fullscreen'],
[
{
label: $q.lang.editor.formatting,
icon: $q.iconSet.editor.formatting,
list: 'no-icons',
options: ['p', 'h1', 'h2', 'h3'],
},
{
label: $q.lang.editor.defaultFont,
icon: $q.iconSet.editor.font,
fixedIcon: true,
list: 'no-icons',
options: [
'default_font',
'arial',
'arial_black',
'comic_sans',
'courier_new',
'impact',
'lucida_grande',
'times_new_roman',
'verdana',
],
},
'removeFormat',
],
['undo', 'redo'],
['viewsource'],
]"
:fonts="{
arial: 'Arial',
arial_black: 'Arial Black',
comic_sans: 'Comic Sans MS',
courier_new: 'Courier New',
impact: 'Impact',
lucida_grande: 'Lucida Grande',
times_new_roman: 'Times New Roman',
verdana: 'Verdana',
}"
/>
</div>
<div class="col-12 q-mt-md">
<q-input
outlined
v-model="note"
label="หมายเหตุ"
dense
lazy-rules
type="textarea"
/>
</div>
<div class="col-12">
<q-separator size="5px" color="grey-2" class="q-my-lg" />
</div>
<div class="col-12">
<div class="text-bold text-subtitle2 q-pb-sm">
อกำหนดและเงอนไข
</div>
<q-editor
v-model="editorCondition"
:dense="$q.screen.lt.md"
toolbar-text-color="blue-grey-10"
toolbar-bg="blue-grey-2"
toolbar-toggle-color="blue-grey-8"
class="editor"
:toolbar="[
['left', 'center', 'right', 'justify'],
[
'bold',
'italic',
'strike',
'underline',
'subscript',
'superscript',
],
['token', 'hr', 'link', 'custom_btn'],
['print', 'fullscreen'],
[
{
label: $q.lang.editor.formatting,
icon: $q.iconSet.editor.formatting,
list: 'no-icons',
options: ['p', 'h1', 'h2', 'h3'],
},
{
label: $q.lang.editor.defaultFont,
icon: $q.iconSet.editor.font,
fixedIcon: true,
list: 'no-icons',
options: [
'default_font',
'arial',
'arial_black',
'comic_sans',
'courier_new',
'impact',
'lucida_grande',
'times_new_roman',
'verdana',
],
},
'removeFormat',
],
['undo', 'redo'],
['viewsource'],
]"
:fonts="{
arial: 'Arial',
arial_black: 'Arial Black',
comic_sans: 'Comic Sans MS',
courier_new: 'Courier New',
impact: 'Impact',
lucida_grande: 'Lucida Grande',
times_new_roman: 'Times New Roman',
verdana: 'Verdana',
}"
/>
</div>
<div class="col-12">
<q-separator size="5px" color="grey-2" class="q-my-lg" />
</div>
<div class="col-12">
<div class="text-bold text-subtitle2 q-pb-sm">คำรบรอง</div>
<q-editor
v-model="editorConfirm"
:dense="$q.screen.lt.md"
toolbar-text-color="blue-grey-10"
toolbar-bg="blue-grey-2"
toolbar-toggle-color="blue-grey-8"
class="editor"
:toolbar="[
['left', 'center', 'right', 'justify'],
[
'bold',
'italic',
'strike',
'underline',
'subscript',
'superscript',
],
['token', 'hr', 'link', 'custom_btn'],
['print', 'fullscreen'],
[
{
label: $q.lang.editor.formatting,
icon: $q.iconSet.editor.formatting,
list: 'no-icons',
options: ['p', 'h1', 'h2', 'h3'],
},
{
label: $q.lang.editor.defaultFont,
icon: $q.iconSet.editor.font,
fixedIcon: true,
list: 'no-icons',
options: [
'default_font',
'arial',
'arial_black',
'comic_sans',
'courier_new',
'impact',
'lucida_grande',
'times_new_roman',
'verdana',
],
},
'removeFormat',
],
['undo', 'redo'],
['viewsource'],
]"
:fonts="{
arial: 'Arial',
arial_black: 'Arial Black',
comic_sans: 'Comic Sans MS',
courier_new: 'Courier New',
impact: 'Impact',
lucida_grande: 'Lucida Grande',
times_new_roman: 'Times New Roman',
verdana: 'Verdana',
}"
/>
</div>
</div>
</q-card-section>
<q-separator />
<q-card-actions class="text-primary q-py-sm">
<q-space />
<q-btn
flat
round
color="public"
@click="checkSave"
icon="mdi-content-save-outline"
>
<q-tooltip>{{ edit ? "แก้ไขข้อมูล" : "บันทึกข้อมูล" }}</q-tooltip>
</q-btn>
</q-card-actions>
</q-form>
</q-card>
</template>
<script setup lang="ts">
import type { QTableProps } from "quasar";
import { onMounted, ref, watch } from "vue";
import { useQuasar, QForm } from "quasar";
import { useCounterMixin } from "@/stores/mixin";
import { useRouter, useRoute } from "vue-router";
import type { Columns } from "@/modules/03_recruiting/interface/request/Main";
import type {
RequestPeriodExam,
RequestPosition,
RequestPayment,
} from "@/modules/03_recruiting/interface/request/Period";
import type {
ResponsePosition,
ResponsePayment,
} from "@/modules/03_recruiting/interface/response/Period";
import type {
DataOption,
UploadType,
} from "@/modules/02_organizational/interface/index/Main";
import http from "@/plugins/http";
import config from "@/app.config";
import ProfileTable from "@/modules/04_registry/components/Table.vue";
const $q = useQuasar(); // show dialog
const mixin = useCounterMixin();
const router = useRouter();
const route = useRoute();
const { date2Thai, success, dateToISO, messageError, showLoader, hideLoader } =
mixin;
const myForm = ref<QForm | null>(null); //form data input
const name = ref<string>("");
const note = ref<string>("");
const editor = ref<string>("");
const editorCondition = ref<string>(
`<div style="text-align: center;"><span style="color: rgb(193, 0, 21); font-weight: 700; letter-spacing: 0.14992px;">ข้อกำหนดและเงื่อนไขฉบับนี้ ถือเป็นข้อตกลงในการเก็บข้อมูล</span><br></div><div><p style="margin-bottom: 16px; font-size: 14px;">&nbsp; &nbsp; หนังสือยินยอมให้เก็บ ใช้หรือเปิดเผยข้อมูลส่วนบุคคลของผู้สมัคร เพื่อสมัครงานกับกรุงเทพมหานครฯ 1. คำยินยอมจากผู้ให้ข้อมูลกับกรุงเทพมหานครฯ ข้าพเจ้า&nbsp;<strong>System Administrator</strong>&nbsp;ยินยอมให้ใช้หรือเปิดเผยข้อมูลส่วนบุคคลที่เกี่ยวข้องกับข้าพเจ้า สำหรับให้กรุงเทพมหานครฯ พิจารณาคุณสมบัติว่ามีความเหมาะสมกับตำแหน่งงานที่ทางกรุงเทพมหานครฯ เปิดรับหรือไม่ ข้าพเจ้าฯ ยินยอมให้ทางกรุงเทพมหานครฯ เก็บข้อมูลส่วนบุคคล ตรวจสอบประวัติส่วนบุคคล ประวัติอาชญากรรม หรือประวัติ/ประสบการณ์การทำงานที่ผ่านมาของข้าพเจ้าฯ ไปยังบุคคล และ/หรือ หน่วยงานต่างๆ ที่เกี่ยวข้อง เพื่อเป็นข้อมูลประกอบการพิจารณาการคัดเลือกตามตำแหน่งที่ข้าพเจ้าสมัคร โดยข้าพเจ้าฯ ยินยอมให้เปิดเผยข้อมูลดังต่อไปนี้</p><p style="margin-bottom: 16px; font-size: 14px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1. รายละเอียดข้อมูล ที่ผู้สมัครงานได้กรอกในใบสมัครงานของกรุงเทพมหานครฯ ข้อมูลบุคคลอ้างอิง/บุคคลที่เกี่ยวข้องตามที่ได้ระบุไว้ในใบสมคัร ประวัติส่วนบุคคลและประวัติการทำงานเป็นต้น 2.รายละเอียดข้อมูลต่างๆ ในเอกสารหรือหลักฐานที่ผู้สมัครได้นำส่งให้กับกรุงเทพมหานครฯ ทุกช่องทางการสื่อสาร เช่น จดหมาย หรืออีเมล์เป็นต้น ในกรณีที่ท่าน ไม่ผ่าน การพิจารณารับเข้าทำงาน ข้อมูลในใบสมคัรจะถูกเก็บรักษาไว้อีกเป็นระยะเวลา 24 เดือน เพื่อพิจารณาความเหมาะสมกับตำแหน่งงานอื่น ในกรณีที่ท่าน ผ่าน การพิจารณารับเข้าทำงาน ข้อมูลในใบสมัครจะถูกเก็บรักษาไว้ตลอดระยะเวลาการเป็นพนักงาน/ลูกจ้าง และเก็บต่อเนื่องอีกเป็นระยะเวลา 10 ปี เพื่อกรณีต้องใช้เป็นหลักฐานประกอบการใช้สิทธิเรียกร้องตามกฎหมาย พระราชบัญญัติคุ้มครองแรงงาน พ.ศ. 2541 และที่แก้ไขเพิ่มเติม</p><p style="margin-bottom: 16px; font-size: 14px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2. ข้อมูลส่วนบุคคลที่กรุงเทพมหานครฯ เก็บรวบรวมในคร้ังนี้ กรุงเทพมหานครฯ จะใช้วิธีการที่ชอบด้วยกฏหมายและเป็นธรรมในการเก็บรวบรวมข้อมูลส่วนบุคคลอย่างจำกัดเพียงเท่าที่จำเป็นภายใต้วัตถุประสงค์การทำงานของกรุงเทพมหานครฯ เพื่อใช้เป็นข้อมูลป</p></div><div><ul style="font-size: 14px; list-style-type: circle;"><li>ชื่อ-นามสกุล เพื่อติดต่อกับทางกรุงเทพมหานครฯ</li><li>อีเมล์ เพื่อใช้ในการติดต่อกับกรุงเทพมหานครฯ</li><li>เบอร์โทร เพื่อใช้สมัครงานกับทางกรุงเทพมหานครฯ</li><li>ที่อยู่ เพื่อใช้สมัครงานกับทางกรุงเทพมหานครฯ</li><li>ประวัติการทำงาน, ประวัติการศึกษา, ประวัติการฝึกอบรม ตามข้อมูลข้างต้น</li></ul></div><div><p style="margin-bottom: 16px; font-size: 14px;">&nbsp; &nbsp; &nbsp; &nbsp; ท้้งนี้ข้อมูลส่วนบุคคลดังกล่าวเป็นข้อมูลที่จำเป็นสำหรับการทำงานของกรุงเทพมหานครฯ หากไม่มีข้อมูลดังกล่าว อาจส่งผลต่อกระบวนการพิจารณาคุณสมบัติของผู้สมัคร</p><p style="margin-bottom: 16px; font-size: 14px;">&nbsp;&nbsp;&nbsp;&nbsp;ทั้งนี้ผู้สมัครเป็นผู้มีสิทธิเลือกได้ว่าจะบันทึกข้อมูลส่วนบุคคลอื่นใด และยินดีจะเปิดเผยข้อมูลดังกล่าวกับบุคคลหรือหน่วยงานอื่นหรือไม่ วัตถุประสงค์ในการเก็บรวบรวมข้อมูลส่วนบุคคล กรุงเทพมหานครฯ จะเก็บรวบรวมข้อมูลส่วนบุคคลของท่านเพื่อนำไปใช้หรือเปิดเผยเท่าที่จำเป็นภายใต้วัตถุประสงค์ในการใช้ประกอบการพิจารณาคัดเลือกตามตำแหน่งที่ผู้ให้ข้อมูลแสดงความประสงค์ไว้เท่าน้้น กรุงเทพมหานครฯ จะไม่ดำเนินการอื่นใดแตกต่างจากที่ระบุในวัตถุประสงค์เว้นแต่มีกฏหมายบัญญัติให้กระทำหรือมีหนังสือร้องขอที่สามารถปฏิบัติได้ตามกฏหมาย เช่น เพื่อความจำเป็นในการป้องกันด้านสุขภาพและโรคติดต่ออันตราย</p></div>`
);
const editorConfirm = ref<string>(
`<div style="color: rgb(53, 71, 60); font-size: 14px;">1. ข้าพเจ้าขอให้คำรับรองว่า ข้อความดังกล่าวข้างต้นนี้เป็นจริงทุกประการและข้าพเจ้ามีคุณสมบัติทั่วไปและ ไม่มีลักษณะต้องห้าม ตามมาตรา 43 แห่งพระราชบัญญัติระเบียบข้าราชการกรุงเทพมหานครและบุคลากร-กรุงเทพมหานคร พ.ศ. 2554 และมีคุณสมบัติเฉพาะสำหรับตำแหน่งที่สมัครตรงตามประกาศรับสมัคร</div><div style="color: rgb(53, 71, 60); font-size: 14px;">2. กรณีข้าพเจ้ามีลักษณะต้องห้าม ตามมาตรา 43 ข. แห่งพระราชบัญญัติระเบียบข้าราชการกรุงเทพมหานคร และบุคลากรกรุงเทพมหานคร พ.ศ. 2554 และประสงค์จะยื่นคำขอยกเว้นเข้ารับราชการฯ ต่อหัวหน้าสำนักงาน ก.ก. ตามระเบียบ ก.ก. ว่าด้วยการยกเว้นให้ผู้มีลักษณะต้องห้ามเข้ารับราชการเป็นข้าราชการกรุงเทพมหานคร พ.ศ. 2556 ตามมติ ก.ก. ครั้งที่ 7/2556 เมื่อวันที่ 15 สิงหาคม 2556 ข้าพเจ้าจะยื่นภายในวันปิดรับสมัคร ทั้งนี้ หากยื่นภายหลังกำหนด สำนักงาน ก.ก. จะไม่รับคำขอดังกล่าว</div><div style="color: rgb(53, 71, 60); font-size: 14px;">3. ข้าพเจ้าจะยื่นหลักฐานและเอกสารที่แสดงว่าเป็นผู้มีคุณสมบัติทั่วไปและมีคุณสมบัติเฉพาะสำหรับตำแหน่งที่สมัครตรงตามประกาศรับสมัครภายในระยะเวลาที่กำหนดตามประกาศฯ</div><div style="color: rgb(53, 71, 60); font-size: 14px;">4. หากมีการตรวจสอบหลักฐานและเอกสารและหรือคุณวุฒิการศึกษาของข้าพเจ้าในภายหลัง ปรากฏว่าข้าพเจ้ามีคุณสมบัติไม่ตรงหรือมีลักษณะต้องห้ามตามประกาศรับสมัครหรือไม่ได้รับการยกเว้นให้ถือว่าข้าพเจ้า เป็นผู้ขาดคุณสมบัติในการสมัครครั้งนี้มาตั้งแต่ต้น และไม่มีสิทธิได้รับการบรรจุและแต่งตั้งให้ดำรงตำแหน่ง และข้าพเจ้าจะไม่ใช้สิทธิเรียกร้องใด ๆ ทั้งสิ้น และหากข้าพเจ้าจงใจกรอกข้อความอันเป็นเท็จอาจมีความผิดทางอาญาฐานแจ้งความเท็จต่อเจ้าพนักงานตามประมวลกฎหมายอาญา มาตรา 137</div>`
);
const checkDocument = ref<boolean>(false);
const checkDisability = ref<boolean>(false);
const announcementExam = ref<boolean>(true);
const fee = ref<number>(0);
const round = ref<number>(1);
const yearly = ref<number>(new Date().getFullYear());
const nameRaw = ref<number | null>(null);
const roundRaw = ref<number | null>(null);
const yearlyRaw = ref<number | null>(null);
const dateRegister = ref<[Date, Date] | null>(null); //วันที่สมัคร
const datePayment = ref<[Date, Date] | null>(null); //วันที่จ่ายเงิน
const dateAnnouncement = ref<[Date, Date] | null>(null); //วันที่ประกาศ
const dateAnnounce = ref<Date | null>(null); //วันประกาศผลสอบ
const dateExam = ref<Date | null>(null); //วันที่สอบ
const myFormPayment = ref<any>();
const myFormPosition = ref<any>();
const positionPathOptions = ref<DataOption[]>([]);
const positionPathFilters = ref<DataOption[]>([]);
const positionLevelOptions = ref<DataOption[]>([]);
const positionLevelFilters = ref<DataOption[]>([]);
const governmentCodeOption = ref<DataOption[]>([]);
const organizationShortName = ref<DataOption>();
const organizationName = ref<DataOption>();
const organizationNameOptions = ref<DataOption[]>([]);
const examTypeOptions = [
{ name: "ทั่วไป", id: "normol" },
{ name: "แพทย์", id: "docter" },
];
const educateOptions = [
{ name: "ต่ำกว่าปริญญาตรี", id: "low" },
{ name: "ปริญญาขึ้นไป", id: "normol" },
];
const category = ref<string>("");
const categoryOptions = [
{ name: "สำนักอนามัย", id: "hygiene" },
{ name: "สำนักการแพทย์", id: "physician" },
{ name: "สำนักผังเมือง", id: "city" },
{ name: "สำนักวัฒนธรรม กีฬา และการท่องเที่ยว", id: "culture" },
];
const fileDocDataUpload = ref<File[]>([]);
const fileDocs = ref<UploadType[]>([]);
const fileImgDataUpload = ref<File[]>([]);
const fileImgs = ref<UploadType[]>([]);
const id = ref<string>("");
const pay = ref<string>("payment1");
const filterPayment = ref<string>(""); //search data table
const filterPosition = ref<string>(""); //search data table
const edit = ref<boolean>(false);
const rowsPayment = ref<ResponsePayment[]>([]);
const rowsPosition = ref<any>([]);
const visibleColumnsPayment = ref<String[]>([
"accountNumber",
"bankName",
"accountName",
]);
const columnsPayment = ref<QTableProps["columns"]>([
{
name: "accountNumber",
align: "left",
label: "เลขบัญชี",
sortable: true,
field: "accountNumber",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "bankName",
align: "left",
label: "ธนาคาร",
sortable: true,
field: "bankName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "accountName",
align: "left",
label: "ชื่อบัญชี",
sortable: true,
field: "accountName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
]);
const visibleColumnsPosition = ref<String[]>([
"code",
"position",
"level",
"type",
"highDegree",
]);
const columnsPosition = ref<QTableProps["columns"]>([
{
name: "code",
align: "left",
label: "รหัสประจำตำแหน่งที่สอบ",
sortable: true,
field: "code",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "position",
align: "left",
label: "ตำแหน่ง",
sortable: true,
field: "position",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "level",
align: "left",
label: "ระดับ",
sortable: true,
field: "level",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "highDegree",
align: "left",
label: "ประเภทตำแหน่ง",
sortable: true,
field: "highDegree",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "type",
align: "left",
label: "ประเภทแบบฟอร์ม",
sortable: true,
field: "type",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
]);
// watch(organizationShortName, () => {
// organizationNameOptions.value = [];
// });
// watch(organizationName, () => {
// positionPathOptions.value = [];
// });
watch(fee, (count: any, prevCount: any) => {
if (fee.value <= 0) {
pay.value = "";
}
});
onMounted(async () => {
hideLoader();
if (route.params.id != undefined) {
edit.value = true;
id.value = route.params.id.toString();
await fetchData();
} else {
pay.value = "";
edit.value = false;
}
// await fetchOrganizationShortName();
// if (
// organizationShortName.value != null &&
// organizationShortName.value.id != null
// )
// await fetchOrganizationOrganization(organizationShortName.value.id);
// if (organizationName.value != null && organizationName.value.id != null)
// await fetchPositionPath(organizationName.value.id);
await fetchPositionPath("test");
await fetchPositionLevel("test");
});
const clickBack = () => {
router.push({ name: "qualifyPeriod" });
};
const fetchData = async () => {
showLoader();
await http
.get(config.API.periodExamId(id.value))
.then((res) => {
const data = res.data.result;
const positionData: ResponsePosition[] = [];
data.positionExam.map((r: RequestPosition) => {
positionData.push({
id: r.id,
position: {
id: r.positionId,
name: r.positionName,
},
level: {
id: r.positionLevelId,
name: r.positionLevelName,
},
type: {
id: r.typeId,
name: r.typeName,
},
code: r.code,
highDegree: r.highDegree == true ? "1" : "0",
});
});
const bankData: ResponsePayment[] = [];
data.bankExam.map((r: RequestPayment) => {
bankData.push({
id: r.id,
accountNumber: r.accountNumber,
bankName: r.bankName,
accountName: r.accountName,
});
});
id.value = data.id;
name.value = data.name;
nameRaw.value = data.name;
checkDocument.value = data.checkDocument;
checkDisability.value = data.checkDisability;
announcementExam.value = data.announcementExam;
round.value = data.round;
yearly.value = data.year;
roundRaw.value = data.round;
yearlyRaw.value = data.year;
fee.value = data.fee;
dateAnnounce.value =
data.announcementDate != null ? new Date(data.announcementDate) : null;
dateAnnouncement.value =
data.announcementStartDate != null && data.announcementEndDate != null
? [
new Date(data.announcementStartDate),
new Date(data.announcementEndDate),
]
: null;
dateExam.value = data.examDate != null ? new Date(data.examDate) : null;
dateRegister.value =
data.registerStartDate != null && data.registerEndDate != null
? [new Date(data.registerStartDate), new Date(data.registerEndDate)]
: null;
if (data.fee == 0) {
data.paymentStartDate = null;
data.paymentEndDate = null;
}
datePayment.value =
data.paymentStartDate != null && data.paymentEndDate != null
? [new Date(data.paymentStartDate), new Date(data.paymentEndDate)]
: null;
if (data.organizationCodeId != null) {
organizationShortName.value = {
id: data.organizationCodeId,
name: data.organizationCodeName,
};
}
if (data.organizationId != null) {
organizationName.value = {
id: data.organizationId,
name: data.organizationName,
};
}
rowsPosition.value = positionData;
pay.value = data.paymentKrungThai;
rowsPayment.value = bankData;
editor.value = data.detail;
editorCondition.value = data.editorCondition;
editorConfirm.value = data.editorConfirm;
note.value = data.note;
fileDocs.value = data.documents;
fileImgs.value = data.images;
category.value = data.category;
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
hideLoader();
});
};
/**
* get รายการ รหัสหน่วยงาน
*/
const fetchOrganizationShortName = async () => {
showLoader();
await http
.get(config.API.organizationShortName)
.then((res) => {
const data = res.data.result;
let option: DataOption[] = [];
data.map((r: any) => {
option.push({
id: r.id.toString(),
name: r.governmentCode.toString(),
});
});
governmentCodeOption.value = option;
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
hideLoader();
});
};
/**
* get รายการ หน่วยงาน
*/
const fetchOrganizationOrganization = async (val: string) => {
showLoader();
await http
.get(config.API.organization)
.then((res) => {
const data = res.data.result;
let option: DataOption[] = [];
data.map((r: DataOption) => {
option.push({
id: r.id.toString(),
name: r.name.toString(),
});
});
organizationNameOptions.value = option;
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
hideLoader();
});
};
/**
* get รายการ ตำแหน่งในสายงาน
*/
const fetchPositionPath = async (val: string) => {
showLoader();
await http
.get(config.API.positionPath)
.then((res) => {
const data = res.data.result;
let option: DataOption[] = [];
data.map((r: DataOption) => {
option.push({
id: r.id.toString(),
name: r.name.toString(),
});
});
positionPathOptions.value = option;
positionPathFilters.value = option;
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
hideLoader();
});
};
/**
* get รายการ ตำแหน่งระดับ
*/
const fetchPositionLevel = async (val: string) => {
showLoader();
await http
.get(config.API.positionLevel)
.then((res) => {
const data = res.data.result;
let option: DataOption[] = [];
data.map((r: DataOption) => {
option.push({
id: r.id.toString(),
name: r.name.toString(),
});
});
positionLevelOptions.value = option;
positionLevelFilters.value = option;
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
hideLoader();
});
};
const filterSelector = (val: any, update: Function, refData: string) => {
switch (refData) {
case "positionLevel":
update(() => {
positionLevelOptions.value = positionLevelFilters.value.filter(
(v: DataOption) => v.name.indexOf(val) > -1
);
});
break;
case "position":
update(() => {
positionPathOptions.value = positionPathFilters.value.filter(
(v: DataOption) => v.name.indexOf(val) > -1
);
});
break;
default:
break;
}
};
const selectGovernmentCode = (row: DataOption) => {
organizationName.value = { id: "", name: "" };
if (myForm.value !== null) {
myForm.value.resetValidation();
}
if (row != null) fetchOrganizationOrganization(row.id);
};
const selectOrganization = (row: DataOption) => {
if (myForm.value !== null) {
myForm.value.resetValidation();
}
if (row != null) fetchPositionPath(row.id);
};
const updateYear = async (e: number) => {
yearly.value = e;
};
const checkSave = async () => {
if (myForm.value !== null) {
myForm.value.validate().then(async (success) => {
if (success) {
if (edit.value) {
await editData(id.value);
} else {
await addData();
}
}
});
}
};
const sendData = () => {
const positionData: RequestPosition[] = [];
rowsPosition.value.map((r: ResponsePosition) => {
positionData.push({
id: r.id,
positionId: r.position.id,
positionName: r.position.name,
positionLevelId: r.level.id,
positionLevelName: r.level.name,
typeId: r.type.id,
typeName: r.type.name,
code: r.code,
highDegree: r.highDegree == "1" ? true : false,
});
});
if (fee.value == 0) {
datePayment.value = null;
}
const valueData: any = {
announcementDate:
dateAnnounce.value != null ? dateToISO(dateAnnounce.value) : null,
announcementEndDate:
dateAnnouncement.value != null
? dateToISO(dateAnnouncement.value[1])
: null,
announcementStartDate:
dateAnnouncement.value != null
? dateToISO(dateAnnouncement.value[0])
: null,
examDate: dateExam.value != null ? dateToISO(dateExam.value) : null,
bankExam: rowsPayment.value,
checkDisability: checkDisability.value,
announcementExam: announcementExam.value,
checkDocument: checkDocument.value,
detail: editor.value,
editorCondition: editorCondition.value,
editorConfirm: editorConfirm.value,
fee: fee.value,
id: "",
isActive: true,
name: name.value,
note: note.value,
organizationCodeId: organizationShortName.value?.id,
organizationCodeName: organizationShortName.value?.name,
organizationId: organizationName.value?.id,
organizationName: organizationName.value?.name,
paymentEndDate:
datePayment.value != null ? dateToISO(datePayment.value[1]) : null,
paymentKrungThai: pay.value,
paymentStartDate:
datePayment.value != null ? dateToISO(datePayment.value[0]) : null,
positionExam: positionData,
registerEndDate:
dateRegister.value != null ? dateToISO(dateRegister.value[1]) : null,
registerStartDate:
dateRegister.value != null ? dateToISO(dateRegister.value[0]) : null,
round: round.value,
year: yearly.value,
category: category.value,
};
return valueData;
};
const addData = async () => {
showLoader();
await http
.post(config.API.periodExam, sendData())
.then(async (res) => {
const data = res.data.result;
id.value = data;
success($q, "บันทึกรอบคัดเลือกสำเร็จ");
await uploadImgData();
await uploadDocData();
await clickBack();
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
hideLoader();
});
};
const editData = async (id: string) => {
showLoader();
await http
.put(config.API.periodExamId(id), sendData())
.then(async (res) => {
success($q, "แก้ไขรอบคัดเลือกสำเร็จ");
await uploadImgData();
await uploadDocData();
await clickBack();
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
hideLoader();
});
};
const fileUploadDoc = async (files: any) => {
files.forEach((file: any) => {
fileDocDataUpload.value.push(file);
});
};
const fileRemoveDoc = async (files: any) => {
files.forEach((file: any) => {
const index = fileDocDataUpload.value.findIndex(
(x: any) => x.__key == file.__key
);
if (index > -1) {
fileDocDataUpload.value.splice(index, 1);
}
});
};
const uploadDocData = async () => {
const formData = new FormData();
if (fileDocDataUpload.value.length > 0) {
fileDocDataUpload.value.forEach((file: any) => {
formData.append("", file);
});
showLoader();
await http
.put(config.API.periodExamDoc(id.value), formData)
.then((res) => {})
.catch((e) => {})
.finally(async () => {
hideLoader();
});
} else {
clickBack();
}
};
const fileUploadImg = async (files: any) => {
files.forEach((file: any) => {
fileImgDataUpload.value.push(file);
});
};
const fileRemoveImg = async (files: any) => {
files.forEach((file: any) => {
const index = fileImgDataUpload.value.findIndex(
(x: any) => x.__key == file.__key
);
if (index > -1) {
fileImgDataUpload.value.splice(index, 1);
}
});
};
const uploadImgData = async () => {
if (fileImgDataUpload.value.length > 0) {
const formData = new FormData();
fileImgDataUpload.value.forEach((file: any) => {
formData.append("", file);
});
showLoader();
await http
.put(config.API.periodExamImg(id.value), formData)
.then((res) => {})
.catch((e) => {})
.finally(async () => {
hideLoader();
});
}
};
const deleteDocData = async (docId: string) => {
const params = {
documentId: docId,
};
showLoader();
await http
.delete(config.API.periodExamDoc(id.value.toString()), {
params,
})
.then((res) => {})
.catch((e) => {})
.finally(async () => {
await fetchData();
});
};
const downloadData = async (path: string) => {
window.open(path);
};
const clickAddPayment = () => {
myFormPayment.value.validate().then(async (result: boolean) => {
if (result) {
rowsPayment.value.push({
id: "00000000-0000-0000-0000-000000000000",
accountNumber: "",
bankName: "",
accountName: "",
});
}
});
};
const clickDeletePayment = (row: any) => {
const index = rowsPayment.value.indexOf(row);
if (index > -1) {
rowsPayment.value.splice(index, 1);
}
};
const clickAddPosition = () => {
myFormPosition.value.validate().then(async (result: boolean) => {
if (result) {
rowsPosition.value.push({
id: "00000000-0000-0000-0000-000000000000",
position: null,
type: { id: "normol", name: "ทั่วไป" },
code: null,
highDegree: "0",
});
}
});
};
const clickDeletePosition = (row: any) => {
const index = rowsPosition.value.indexOf(row);
if (index > -1) {
rowsPosition.value.splice(index, 1);
}
};
/**
* แปลงช่วงวันที่ถ้า2ค่าเป็นวันเดียวกันจะโชววันเดียวแต่ถ้าไม่เท่ากันจะแสดงเป็นช่วง
* @param val ช่วงวันที่
*/
const dateThaiRange = (val: [Date, Date] | null) => {
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)}`;
}
};
const clearDateExam = () => {
dateExam.value = null;
};
const clearDateRegister = () => {
dateRegister.value = null;
};
const clearDatePayment = () => {
datePayment.value = null;
};
const clearDateAnnounce = () => {
dateAnnounce.value = null;
};
</script>
<style></style>