Merge branch 'develop' into nice

This commit is contained in:
DESKTOP-1R2VSQH\Lenovo ThinkPad E490 2025-04-24 14:38:57 +07:00
commit 41fab07d17
11 changed files with 1140 additions and 458 deletions

View file

@ -2,7 +2,7 @@
import { ref, reactive, onMounted } from "vue";
import { QForm, useQuasar } from "quasar";
import { useRoute } from "vue-router";
import { useRoute, useRouter } from "vue-router";
import { checkPermission } from "@/utils/permissions";
import type { QTableColumn } from "quasar";
import { useCounterMixin } from "@/stores/mixin";
@ -21,6 +21,7 @@ const isLeave = defineModel<boolean>("isLeave", {
});
const route = useRoute();
const router = useRouter();
const $q = useQuasar();
const mixin = useCounterMixin();
const {
@ -368,6 +369,9 @@ function onViewHistory(id: string) {
historyId.value = id;
historyDialog.value = true;
}
function onViewDevelopment(id: string) {
router.push(`/development-detail/${id}`);
}
/** fetch ข้อมูลประวัติการแก้ไขข้อมูลใบอนุญาตประกอบวิชาชีพ*/
async function fetchDataHistory() {
@ -505,6 +509,21 @@ onMounted(() => {
<template v-slot:body="props" v-if="mode === 'table'">
<q-tr :props="props">
<q-td auto-width>
<q-btn
:disable="!props.row.developmentId"
flat
dense
round
:color="!props.row.developmentId ? 'grey' : 'info'"
icon="mdi-eye"
@click="() => onViewDevelopment(props.row.developmentId)"
>
<q-tooltip>{{
!props.row.developmentId
? "ไม่พบข้อมูลรายละเอียดโครงการ"
: "รายละเอียดโครงการ"
}}</q-tooltip>
</q-btn>
<q-btn
flat
dense

View file

@ -19,6 +19,7 @@ interface ResponseObject {
place: string;
profileId: string;
topic: string;
developmentId?: string;
yearly: number;
}

View file

@ -82,6 +82,16 @@ const projectTypeOp = ref<DataOptionTechnique[]>([
{ label: "โครงการต่อเนื่อง", value: "โครงการต่อเนื่อง" },
]);
const addressTypeOp = ref<DataOption[]>([
{
id: "IN_COUNTRY",
name: "สถานที่ในประเทศ",
},
{
id: "ABROAD",
name: "ต่างประเทศ",
},
]);
//70 ()
const projectTechniquesOp1 = ref<DataItemsDevelopment[]>(
itemsDevelopment.dataDevelopment70
@ -119,7 +129,9 @@ const formData = reactive<FormProjectDetail>({
dateStart: null, //
dateEnd: null, //
totalDate: null, // ()
developmentAddresss: [{ address: "", provinceId: "" }], // ,
developmentAddresss: [
{ address: "", provinceId: "", addressType: "IN_COUNTRY", country: "" },
], // ,
});
const nodes = ref<StrategyNode[]>([]);
@ -180,6 +192,8 @@ function fetchData() {
formData.developmentAddresss = data.developmentAddresss.map((e: any) => ({
address: e.address,
provinceId: e.provinceId,
addressType: e.addressType,
country: e.country,
}));
const arrayExpanded = [
@ -327,6 +341,8 @@ function onClickAddLocation() {
const data = {
address: "",
provinceId: "",
addressType: "IN_COUNTRY",
country: "",
};
formData.developmentAddresss.push(data);
}
@ -365,10 +381,12 @@ function onNextTab() {
const isCheckLocation = computed(() => {
if (formData?.developmentAddresss?.length !== 0) {
if (
formData.developmentAddresss[formData.developmentAddresss.length - 1]
(formData.developmentAddresss[formData.developmentAddresss.length - 1]
.address !== "" &&
formData.developmentAddresss[formData.developmentAddresss.length - 1]
.provinceId !== "") ||
formData.developmentAddresss[formData.developmentAddresss.length - 1]
.provinceId !== ""
.country !== ""
) {
return true;
} else return false;
@ -376,6 +394,10 @@ const isCheckLocation = computed(() => {
return true;
});
function clearDataLocation(index: any) {
formData.developmentAddresss[index].country = "";
formData.developmentAddresss[index].provinceId = "";
}
/**
* งขอมลเมอคอมโพเนนตโหลดเสรจสมบรณ
*/
@ -671,7 +693,7 @@ defineExpose({
v-for="(item, index) in formData.developmentAddresss"
>
<div class="row q-col-gutter-sm">
<div class="col-8">
<div class="col-5">
<q-input
:readonly="checkRoutePermission"
outlined
@ -684,6 +706,28 @@ defineExpose({
</div>
<div class="col-3">
<q-select
:readonly="checkRoutePermission"
outlined
dense
class="inputgreen"
v-model="formData.developmentAddresss[index].addressType"
label="สถานที่ดำเนินการ"
:options="addressTypeOp"
option-label="name"
option-value="id"
emit-value
map-options
@update:model-value="
props.onCheckChangeData(), clearDataLocation(index)
"
/>
</div>
<div class="col-3">
<q-select
v-if="
formData.developmentAddresss[index].addressType ==
'IN_COUNTRY'
"
:readonly="checkRoutePermission"
outlined
dense
@ -713,6 +757,17 @@ defineExpose({
</q-item>
</template>
</q-select>
<q-input
v-else
label="ประเทศ"
dense
:readonly="checkRoutePermission"
@update:model-value="props.onCheckChangeData()"
outlined
class="inputgreen"
v-model="formData.developmentAddresss[index].country"
>
</q-input>
</div>
<div class="col-1 text-center">
<q-btn

View file

@ -154,8 +154,8 @@ function onSubmit() {
orgRootShortName: data.orgRootShortName,
orgRevisionId: data.orgRevisionId,
};
props.upDate?.(body);
closeDialog();
props.upDate?.(body);
}
}

View file

@ -0,0 +1,341 @@
<script setup lang="ts">
import { ref, watch } from "vue";
import { useRoute } from "vue-router";
import http from "@/plugins/http";
import config from "@/app.config";
import { useCounterMixin } from "@/stores/mixin";
import { useQuasar } from "quasar";
import DialogHeader from "@/components/DialogHeader.vue";
const $q = useQuasar();
const route = useRoute();
const id = ref<string>(route.params.id as string);
const mixin = useCounterMixin();
const {
date2Thai,
dialogMessageNotify,
showLoader,
hideLoader,
messageError,
dialogConfirm,
success,
} = mixin;
const modal = defineModel<boolean>("modal", { required: true });
const props = defineProps({
fetchDataDetail: Function,
checkFileBackReceived: Function,
scholarshipId: String,
});
const governmentDate = ref<Date | null>(null);
const graduatedDate = ref<Date | null>(null);
const isGraduated = ref<string | null>(null);
const graduatedReason = ref<string>("");
const bookNumber = ref<string>("");
const bookDate = ref<Date | null>(null);
const governmentEndDate = ref<Date | null>(null);
function close() {
modal.value = false;
bookNumber.value = "";
bookDate.value = null;
governmentDate.value = null;
governmentEndDate.value = null;
isGraduated.value = null;
graduatedDate.value = null;
graduatedReason.value = "";
}
function onSubmit() {
if (isGraduated.value == null) {
dialogMessageNotify($q, "กรุณาเลือกสำเร็จการศึกษาตามที่หลักสูตรกำหนด");
} else {
dialogConfirm($q, () => {
showLoader();
http
.put(config.API.devScholarship + `/admin/detail/${id.value}`, {
bookNumber: bookNumber.value,
bookDate: bookDate.value,
governmentDate: governmentDate.value,
governmentEndDate: governmentEndDate.value,
isGraduated: isGraduated.value,
graduatedDate:
isGraduated.value == "true" ? graduatedDate.value : null,
graduatedReason:
isGraduated.value == "false" ? graduatedReason.value : null,
})
.then((res) => {
success($q, "บันทึกสำเร็จ");
props.fetchDataDetail?.(props.scholarshipId);
props.checkFileBackReceived?.(props.scholarshipId);
close();
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
hideLoader();
});
});
}
}
watch(
() => modal.value,
() => {
if (modal.value == true) {
showLoader();
http
.get(config.API.devScholarship + `/admin/detail/${id.value}`)
.then((res) => {
const data = res.data.result;
bookNumber.value = data.bookNumber;
bookDate.value = data.bookDate;
governmentDate.value = data.governmentDate;
governmentEndDate.value = data.governmentEndDate;
isGraduated.value = data.isGraduated.toLocaleString();
graduatedDate.value = data.graduatedDate;
graduatedReason.value = data.graduatedReason;
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
hideLoader();
});
}
}
);
</script>
<template>
<q-dialog v-model="modal">
<q-card flat style="min-width: 30vw">
<q-form greedy @submit.prevent @validation-success="onSubmit">
<DialogHeader tittle="รายงานตัวกลับเข้ารับราชการ" :close="close" />
<q-separator />
<q-card-section>
<div class="row q-col-gutter-sm">
<div class="col-xs-12 col-sm-12 col-md-6">
<q-input
label="เลขที่หนังสือรายงานตัวกลับเข้าปฏิบัติราชการ"
v-model="bookNumber"
outlined
lazy-rules
dense
hide-bottom-space
:rules="[
(val:string) =>
!!val || `${'กรุณากรอกเลขที่หนังสือรายงานตัวกลับเข้าปฏิบัติราชการ'}`,
]"
class="inputgreen"
/>
</div>
<div class="col-xs-12 col-sm-12 col-md-6">
<datepicker
menu-class-name="modalfix"
v-model="bookDate"
:locale="'th'"
autoApply
:enableTimePicker="false"
week-start="0"
>
<template #year="{ year }">{{ year + 543 }}</template>
<template #year-overlay-value="{ value }">{{
parseInt(value + 543)
}}</template>
<template #trigger>
<q-input
dense
outlined
:model-value="bookDate ? date2Thai(bookDate) : null"
:label="`${'หนังสือรายงานตัวกลับเข้าปฏิบัติราชการลงวันที่'}`"
hide-bottom-space
class="inputgreen"
:rules="[
(val:string) =>
!!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-12 col-md-6">
<datepicker
menu-class-name="modalfix"
v-model="governmentDate"
:locale="'th'"
autoApply
:enableTimePicker="false"
week-start="0"
>
<template #year="{ year }">{{ year + 543 }}</template>
<template #year-overlay-value="{ value }">{{
parseInt(value + 543)
}}</template>
<template #trigger>
<q-input
dense
outlined
:model-value="
governmentDate ? date2Thai(governmentDate) : null
"
:label="`${'วันที่กลับเข้าปฏิบัติราชการ'}`"
hide-bottom-space
class="inputgreen"
:rules="[
(val:string) =>
!!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-12 col-md-6">
<datepicker
menu-class-name="modalfix"
v-model="governmentEndDate"
:locale="'th'"
autoApply
:enableTimePicker="false"
week-start="0"
>
<template #year="{ year }">{{ year + 543 }}</template>
<template #year-overlay-value="{ value }">{{
parseInt(value + 543)
}}</template>
<template #trigger>
<q-input
dense
outlined
:model-value="
governmentEndDate ? date2Thai(governmentEndDate) : null
"
:label="`${' วันสิ้นสุดภาระผูกพัน'}`"
class="inputgreen"
>
<template v-slot:prepend>
<q-icon
name="event"
class="cursor-pointer"
style="color: var(--q-primary)"
>
</q-icon>
</template>
<template v-slot:append>
<q-icon
v-if="governmentEndDate"
name="clear"
class="cursor-pointer"
@click.stop.prevent="governmentEndDate = null"
>
</q-icon>
</template>
</q-input>
</template>
</datepicker>
</div>
<q-radio
v-model="isGraduated"
checked-icon="task_alt"
unchecked-icon="panorama_fish_eye"
val="true"
label="สำเร็จการศึกษาตามที่หลักสูตรกำหนด"
/>
<q-radio
v-model="isGraduated"
checked-icon="task_alt"
unchecked-icon="panorama_fish_eye"
val="false"
label="เสร็จสิ้นการศึกษาตามที่หลักสูตรกำหนดแล้วแต่ยังไม่สำเร็จการศึกษา"
/>
<div v-if="isGraduated == 'true'" class="col-12">
<datepicker
menu-class-name="modalfix"
v-model="graduatedDate"
:locale="'th'"
autoApply
:enableTimePicker="false"
week-start="0"
>
<template #year="{ year }">{{ year + 543 }}</template>
<template #year-overlay-value="{ value }">{{
parseInt(value + 543)
}}</template>
<template #trigger>
<q-input
dense
outlined
:model-value="
graduatedDate ? date2Thai(graduatedDate) : null
"
:label="`${'ตั้งแต่ (วันที่)'}`"
hide-bottom-space
class="inputgreen"
:rules="[
(val:string) =>
!!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 v-if="isGraduated == 'false'" class="col-12">
<q-input
v-model="graduatedReason"
type="textarea"
dense
outlined
hide-bottom-space
class="inputgreen"
:rules="[
(val:string) =>
!!val || `${'กรุณากรอก เนื่องจาก'}`,
]"
label="เนื่องจาก"
/>
</div>
</div>
</q-card-section>
<q-separator />
<q-card-actions align="right">
<q-btn label="บันทึก" color="secondary" type="submit"
><q-tooltip>นทกขอม</q-tooltip></q-btn
>
</q-card-actions>
</q-form>
</q-card>
</q-dialog>
</template>

View file

@ -96,6 +96,8 @@ interface FormProjectDetail {
interface DevelopmentAddress {
address: string;
provinceId: string;
addressType: string;
country: string;
}
interface DataHistory {

View file

@ -34,7 +34,7 @@ interface FormsSholarship {
bookNo: string; //เลขที่หนังสืออนุมัติ
bookNoDate: Date | null; //ลงวันที่(หนังสือ)
bookApproveDate: Date | null; //หนังสืออนุมัติเมื่อวันที่
useOfficialTime: boolean; //ใช้เวลาราชการ
useOfficialTime: string; //ใช้เวลาราชการ
changeDetail: string; //เปลี่ยนแปลงรายละเอียด
scholarshipType: string; //เลือกประเภททุน
fundType: string; //ประเภททุน
@ -61,6 +61,7 @@ interface FormsSholarship {
totalPeriod: string; //รวมระยะเวลาในการศึกษา/รวมระยะเวลาในการฝึกอบรม
planType: string; // INPLAN ในแผนฯ, OUTPLAN นอกแผนฯ
isNoUseBudget: boolean; //
budgetSourceOther: string; //
}
export type { FormsSholarship };

View file

@ -44,7 +44,7 @@ interface DataSholarship {
bookNo: string; //เลขที่หนังสืออนุมัติ
bookNoDate: Date | null; //ลงวันที่(หนังสือ)
bookApproveDate: Date | null; //หนังสืออนุมัติเมื่อวันที่
useOfficialTime: boolean; //ใช้เวลาราชการ
useOfficialTime: string; //ใช้เวลาราชการ
changeDetail: string; //เปลี่ยนแปลงรายละเอียด
scholarshipType: string; //เลือกประเภททุน
fundType: string; //ประเภททุน
@ -70,6 +70,7 @@ interface DataSholarship {
studyAbroadEndDate: Date | null; //วันสิ้นสุดการศึกษาดูงานต่างประเทศ
totalPeriod: string; //รวมระยะเวลาในการศึกษา/รวมระยะเวลาในการฝึกอบรม
status: string;
budgetSourceOther: string;
planType: string; // INPLAN ในแผนฯ, OUTPLAN นอกแผนฯ
isNoUseBudget: boolean; // ไม่ใช้งบประมาณ
}

View file

@ -131,8 +131,12 @@ const scholarshipTypeOp = ref<DataOption[]>([
name: " ฝึกอบรมในประเทศที่ส่งไปพัฒนากับหน่วยงานภายนอก (หลักสูตรประเภทนักบริหาร)",
},
{
id: "RESEARCH",
name: "ศึกษา ฝึกอบรม ประชุม ดูงาน และปฏิบัติการวิจัย ณ ต่างประเทศ",
id: "STUDY",
name: "ทุนการศึกษา ณ ต่างประเทศ",
},
{
id: "TRAINING",
name: "ทุนฝึกอบรม ณ ต่างประเทศ",
},
]);