Merge branch 'develop' into devTee

This commit is contained in:
setthawutttty 2023-12-21 11:24:14 +07:00
commit 10a7b1da05
13 changed files with 278 additions and 87 deletions

View file

@ -1,5 +1,6 @@
import env from "../index";
const leave = `${env.API_URI}/leave`;
const leaveReport = `${env.API_URI}/leave/report`;
export default {
roundDutytime: () => `${leave}/duty-time`,
roundDutytimeByid: (id: string) => `${leave}/duty-time/${id}`,
@ -33,4 +34,8 @@ export default {
leaveReportReject: (id: string) => `${leave}/report/reject/${id}`,
leaveDeleteApprove: (id: string) => `${leave}/admin/delete/approve/${id}`,
leaveDeleteReject: (id: string) => `${leave}/admin/delete/reject/${id}`,
/**รายงาน */
leaveReportTimeRecords: () => `${leaveReport}/time-records/officer`,
leaveReportLeaveday: (type: string) => `${leaveReport}/leaveday/${type}`,
};

View file

@ -1,6 +1,11 @@
<script setup lang="ts">
import { ref, computed } from "vue";
import { ref, computed, onMounted } from "vue";
import { VuePDF, usePDF } from "@tato30/vue-pdf";
import { useRoute } from "vue-router";
import { useQuasar } from "quasar";
import http from "@/plugins/http";
import config from "@/app.config";
import axios from "axios";
import type {
DataDateMonthObject,
@ -8,10 +13,21 @@ import type {
} from "@/modules/09_leave/interface/index/Main";
import { useCounterMixin } from "@/stores/mixin";
const route = useRoute();
const route = useRoute();
const mixin = useCounterMixin();
const { date2Thai, monthYear2Thai } = mixin;
const $q = useQuasar();
const {
showLoader,
hideLoader,
date2Thai,
monthYear2Thai,
dateToISO,
messageError,
} = mixin;
const apiGenReport =
"https://report-server.frappet.synology.me/api/v1/report-template/xlsx";
const typeReport = route.params.type.toString();
const titleReport = computed(() => {
@ -33,7 +49,7 @@ const year = ref<number>(new Date().getFullYear());
const dateStart = ref<Date>(new Date());
const dateEnd = ref<Date>(new Date());
const employeeClass = ref<string>("employee");
const yearType = ref<string>("fullyear");
const yearType = ref<string>("FULL");
const filterType = ref<string>("daily");
function monthYearThai(val: DataDateMonthObject) {
@ -47,12 +63,12 @@ const filterTypeMain = ref<DataOption[]>([
{ id: "yearly", name: "รายปี" },
]);
const employeeClassMain = ref<DataOption[]>([
{ id: "employee", name: "ข้าราชการ" },
{ id: "perm", name: "ลูกจ้างประจำ" },
{ id: "employee", name: "ลูกจ้างประจำ" },
{ id: "officer", name: "ข้าราชการ" },
]);
const yearTypeOptionMain = ref<DataOption[]>([
{ id: "fullyear", name: "รายปี" },
{ id: "halfyear", name: "ครึ่งปี" },
{ id: "FULL", name: "รายปี" },
{ id: "HAFT", name: "ครึ่งปี" },
]);
const employeeClassOption = ref<DataOption[]>(employeeClassMain.value);
const yearTypeOptionOption = ref<DataOption[]>(yearTypeOptionMain.value);
@ -95,6 +111,7 @@ const numOfPages = ref<number>(0);
const page = ref<number>(1);
const pdfSrc = ref<any>();
const modalFull = ref<boolean>(false);
const fileBlob = ref<any>();
/** ไปหน้าต่อไปของรายงาน */
function nextPage() {
if (page.value < numOfPages.value) {
@ -113,6 +130,161 @@ function backPage() {
function backHistory() {
window.history.back();
}
async function fetchReportTimeRecords(body: any) {
showLoader();
await http
.post(config.API.leaveReportTimeRecords(), body)
.then((res) => {
const data = res.data.result;
data && genReport(data);
dataDetail.value = data;
})
.catch((err) => {
messageError($q, err);
});
}
async function fetchLeaveday(type: string, year: string) {
showLoader();
const body = {
type: year,
};
await http
.post(config.API.leaveReportLeaveday(type), body)
.then((res) => {
const data = res.data.result;
data && genReport(data);
dataDetail.value = data;
})
.catch((err) => {
messageError($q, err);
});
}
async function updateFilterType() {
// console.log(filterType.value);
filterType.value === "daily"
? updateDte()
: filterType.value === "monthly"
? updateMonth()
: updateYear();
}
async function updateDte() {
const body = {
startDate: dateToISO(date.value),
endDate: dateToISO(date.value),
};
fetchReportTimeRecords(body);
}
async function updateMonth() {
const mount = dateMonth.value.month + 1;
//
const firstDay = new Date(dateMonth.value.year, mount - 1, 1);
//
const lastDay = new Date(dateMonth.value.year, mount, 0);
console.log(firstDay, lastDay);
const body = {
startDate: dateToISO(firstDay),
endDate: dateToISO(lastDay),
};
fetchReportTimeRecords(body);
}
async function updateYear() {
//
const firstDay = new Date(year.value, 0, 1);
//
const lastDay = new Date(year.value, 11, 31);
const body = {
startDate: dateToISO(firstDay),
endDate: dateToISO(lastDay),
};
fetchReportTimeRecords(body);
}
async function genReport(data: any) {
await axios
.post(apiGenReport, data, {
headers: {
accept: "application/pdf",
"content-Type": "application/json",
},
responseType: "blob",
})
.then(async (res) => {
const blob = new Blob([res.data]);
const objectUrl = URL.createObjectURL(blob);
fileBlob.value = blob;
const pdfData = await usePDF(`${objectUrl}`);
showLoader();
setTimeout(() => {
pdfSrc.value = pdfData.pdf.value;
numOfPages.value = pdfData.pages.value;
hideLoader();
}, 1500);
})
.catch((err) => {
messageError($q, err);
})
.finally(() => {
hideLoader();
});
}
const dataDetail = ref<any>([]);
async function genReportXLSX(data: any) {
await axios
.post(apiGenReport, data, {
headers: {
accept:
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
"content-Type": "application/json",
},
responseType: "blob",
})
.then(async (res) => {
const blob = new Blob([res.data]);
downloadReport(blob, "xlsx");
})
.catch((err) => {
messageError($q, err);
})
.finally(() => {
hideLoader();
});
}
async function updateLeaveday() {
fetchLeaveday(employeeClass.value, yearType.value);
}
async function downloadReport(data: any, type: string) {
const link = document.createElement("a");
var fileName = titleReport.value;
link.href = window.URL.createObjectURL(new Blob([data]));
link.setAttribute("download", `${fileName}.${type}`);
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
onMounted(() => {
const body = {
startDate: dateToISO(date.value),
endDate: dateToISO(date.value),
};
typeReport === "time-records"
? fetchReportTimeRecords(body)
: fetchLeaveday(employeeClass.value, yearType.value);
});
</script>
<template>
<div class="toptitle">
@ -144,6 +316,7 @@ function backHistory() {
option-value="id"
use-input
style="width: 230px"
@update:model-value="updateFilterType"
@filter="(inputValue: any,
doneFn: Function) => filterFnOptions(inputValue, doneFn,'filterType')"
><template v-slot:no-option>
@ -167,6 +340,7 @@ function backHistory() {
option-value="id"
use-input
style="width: 230px"
@update:model-value="updateLeaveday"
@filter="(inputValue: any,
doneFn: Function) => filterFnOptions(inputValue, doneFn,'employeeClass')"
><template v-slot:no-option>
@ -188,6 +362,7 @@ function backHistory() {
option-value="id"
use-input
style="width: 230px"
@update:model-value="updateLeaveday"
@filter="(inputValue: any,
doneFn: Function) => filterFnOptions(inputValue, doneFn,'yearType')"
><template v-slot:no-option>
@ -200,10 +375,36 @@ function backHistory() {
<q-space />
<div class="q-py-xs">
<q-btn unelevated color="primary" @click="modalFull = true">
<q-btn flat round color="primary" icon="download">
<q-menu>
<q-list style="min-width: 150px">
<q-item
clickable
v-close-popup
@click="downloadReport(fileBlob, 'pdf')"
>
<q-item-section avatar
><q-icon color="red" name="mdi-file-pdf"
/></q-item-section>
<q-item-section>ไฟล .PDF</q-item-section>
</q-item>
<q-item
clickable
v-close-popup
@click="genReportXLSX(dataDetail)"
>
<q-item-section avatar
><q-icon color="green" name="mdi-file-excel"
/></q-item-section>
<q-item-section>ไฟล .xlsx</q-item-section>
</q-item>
</q-list>
</q-menu>
</q-btn>
<!-- <q-btn unelevated color="primary" @click="modalFull = true">
<q-icon left size="2em" name="mdi-eye-outline" />
<div>แสดงรายงาน</div>
</q-btn>
</q-btn> -->
</div>
</q-toolbar>
<q-toolbar
@ -219,6 +420,7 @@ function backHistory() {
autoApply
:enableTimePicker="false"
week-start="0"
@update:model-value="updateDte"
>
<template #year="{ year }">{{ year + 543 }}</template>
<template #year-overlay-value="{ value }">{{
@ -249,6 +451,7 @@ function backHistory() {
autoApply
month-picker
:enableTimePicker="false"
@update:model-value="updateMonth"
>
<template #year="{ year }">{{ year + 543 }}</template>
<template #year-overlay-value="{ value }">{{
@ -284,6 +487,7 @@ function backHistory() {
autoApply
year-picker
:enableTimePicker="false"
@update:model-value="updateYear"
>
<template #year="{ year }">{{ year + 543 }}</template>
<template #year-overlay-value="{ value }">{{
@ -312,7 +516,7 @@ function backHistory() {
</div>
</q-toolbar>
<q-toolbar
<!-- <q-toolbar
v-if="typeReport === 'leaveday'"
class="q-pa-sm bg-grey-2"
style="border-radius: 5px"
@ -379,7 +583,7 @@ function backHistory() {
</template>
</datepicker>
</div>
</q-toolbar>
</q-toolbar> -->
<q-splitter
v-model="splitterModel"
horizontal

View file

@ -378,7 +378,11 @@ watch(
<div class="row items-center q-my-sm justify-between">
<p class="q-ma-none">สถานะการใชงาน</p>
<label class="toggle-control">
<input type="checkbox" v-model="formData.isActive" />
<input
type="checkbox"
v-model="formData.isActive"
:disabled="formData.isDefault"
/>
<span class="control"></span>
</label>
</div>

View file

@ -29,6 +29,8 @@ const props = defineProps({
date: { type: String, default: "" },
dateFix: { type: String, default: "" },
id: { type: String, default: "" },
checkInStatus: { type: String, default: "NORMAL" },
checkOutStatus: { type: String, default: "NORMAL" },
closeDialog: { type: Function, default: () => {} },
detailData: Object,
});
@ -151,6 +153,13 @@ watch(
formData.checkOutEdit = props.detailData.checkOutEdit;
}
}
if (props.modal === true) {
formData.checkInStatus = "NORMAL";
formData.checkOutStatus = "NORMAL";
} else {
formData.checkInStatus = props.checkInStatus;
formData.checkOutStatus = props.checkOutStatus;
}
}
);
</script>

View file

@ -21,7 +21,7 @@ const dataStore = useChangeRoundDataStore();
const $q = useQuasar();
const modal = ref<boolean>(false);
const dateWork = ref<any>();
const dateWork = ref<string>("5");
const modalFix = ref<boolean>(false);
const editCheck = ref<string>("");
const DataRow = ref<any>();
@ -57,6 +57,11 @@ function closeDialog() {
modalFix.value = false;
}
function save() {
console.log("dateWork===>", dateWork.value);
closeDialog();
}
/** Function ค้นหาข้อมูล */
function searchData() {
if (formData.cardId || formData.firstName || formData.lastName) {
@ -206,6 +211,8 @@ function searchData() {
</d-table>
</div>
</q-card>
<!-- popup แกไขปฏนวนทำงาน -->
<Dialogform
:modal="modal"
:closeDialog="closeDialog"
@ -230,18 +237,18 @@ function searchData() {
/>
</q-toolbar>
<q-separator color="grey-4" />
<q-form @submit="closeDialog" class="q-gutter-md">
<q-form @submit="save" class="q-gutter-md">
<div class="q-pa-md">
<q-radio
name="dateWork"
v-model="dateWork"
val="line"
val="5"
label="ทำงาน 5 วัน"
/>
<q-radio
name="dateWork"
v-model="dateWork"
val="rectangle"
val="6"
label="ทำงาน 6 วัน"
/>
</div>
@ -258,9 +265,11 @@ function searchData() {
/>
</div>
</div>
</q-form> </q-card
></q-dialog>
</q-form>
</q-card>
</q-dialog>
</template>
<style scoped lang="scss">
.q-table tbody td:before.no-background {
background: none;

View file

@ -12,7 +12,12 @@ function nextPage(type: string) {
<div>
<q-card flat bordered class="col-12 q-mt-sm">
<div class="q-pa-md">
<q-item clickable dense class="hover-green" @click="nextPage('time-records')">
<q-item
clickable
dense
class="hover-green"
@click="nextPage('time-records')"
>
<q-item-section avatar>
<q-icon color="primary" name="mdi-file" size="xs" />
</q-item-section>
@ -21,29 +26,6 @@ function nextPage(type: string) {
</q-item-section>
</q-item>
<!-- <q-item
clickable
dense
class="hover-green"
@click="nextPage('monthly')"
>
<q-item-section avatar>
<q-icon color="primary" name="mdi-file" size="xs" />
</q-item-section>
<q-item-section class="text-dark">
รายงานสรปบนทกการลงเวลาปฏงานเปนรายเดอน
</q-item-section>
</q-item> -->
<!-- <q-item clickable dense class="hover-green" @click="nextPage('yearly')">
<q-item-section avatar>
<q-icon color="primary" name="mdi-file" size="xs" />
</q-item-section>
<q-item-section class="text-dark">
รายงานสรปบนทกการลงเวลาปฏงานเปนรายป
</q-item-section>
</q-item> -->
<q-item
clickable
dense

View file

@ -1,6 +1,9 @@
import { defineStore } from "pinia";
import { ref } from "vue";
import type { DirectorRows,DirectorRowsResponse } from "@/modules/11_discipline/interface/response/director";
import type {
DirectorRows,
DirectorRowsResponse,
} from "@/modules/11_discipline/interface/response/director";
import type { QTableProps } from "quasar";
// store ระบบวินัย >> ข้อมูลพื้นฐาน >> กรรมการ
@ -88,23 +91,25 @@ export const useDisciplineDirectorDataStore = defineStore(
// ข้อมูลในตาราง
const rows = ref<DirectorRowsResponse[]>([]);
function fetchData(data: DirectorRows[]) {
const dataList:DirectorRowsResponse[] = data.map((item:DirectorRows)=>({
id:item.id,
fullName:`${item.prefix}${item.firstName} ${item.lastName}`,
position:item.position,
email:item.email,
phone:item.phone,
totalInvestigate: item.totalInvestigate,
totalDisciplinary: item.totalDisciplinary,
}))
rows.value = dataList
const dataList: DirectorRowsResponse[] = data.map(
(item: DirectorRows) => ({
id: item.id,
fullName: `${item.prefix}${item.firstName} ${item.lastName}`,
position: item.position,
email: item.email,
phone: item.phone,
totalInvestigate: item.totalInvestigate,
totalDisciplinary: item.totalDisciplinary,
})
);
rows.value = dataList;
}
return {
visibleColumns,
columns,
rows,
fetchData
fetchData,
};
}
);

View file

@ -5,6 +5,7 @@ import router from "@/router";
import { useCounterMixin } from "@/stores/mixin";
import { useQuasar } from "quasar";
import { useEvaluateDirectorDataStore } from "@/modules/12_evaluatePersonal/store/DirectorStore";
import http from "@/plugins/http";
import config from "@/app.config";

View file

@ -307,7 +307,7 @@ function inputEdit(val: boolean) {
dense
outlined
v-model="formData.title"
label="ชื่อการประชุม"
label="หัวข้อการประชุม"
ref="titleRef"
for="titleRef"
hide-bottom-space

View file

@ -12,9 +12,6 @@ interface DataResponseList {
Phone:string
Email:string
Position:string
totalInvestigate?:number
totalDisciplinary?:number
}
interface MainList {
@ -32,9 +29,6 @@ interface MainList {
lastUpdateUserId:string
createdAt:string
lastUpdatedAt:string
totalInvestigate:string|number
totalDisciplinary:string|number
}
interface FormData {

View file

@ -17,8 +17,6 @@ export const useEvaluateDirectorDataStore = defineStore(
"position",
"email",
"phone",
"totalInvestigate",
"totalDisciplinary",
]);
// หัวตาราง
@ -68,24 +66,6 @@ export const useEvaluateDirectorDataStore = defineStore(
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "totalInvestigate",
align: "left",
label: "จำนวนการสืบสวน",
sortable: true,
field: "totalInvestigate",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "totalDisciplinary",
align: "left",
label: "จำนวนการสอบสวน",
sortable: true,
field: "totalDisciplinary",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
]);
// ข้อมูลในตาราง
@ -100,8 +80,6 @@ export const useEvaluateDirectorDataStore = defineStore(
phone:item.Phone,
email:item.Email,
position:item.Position,
totalInvestigate:item.totalInvestigate ? item.totalInvestigate :'-',
totalDisciplinary:item.totalDisciplinary ? item.totalDisciplinary :'-',
createdFullName:item.CreatedFullName,
lastUpdateFullName:item.LastUpdateFullName,

View file

@ -39,7 +39,7 @@ export const useEvaluateMeetingDataStore = defineStore(
{
name: "title",
align: "left",
label: "เรื่อง",
label: "หัวข้อการประชุม",
sortable: true,
field: "title",
headerStyle: "font-size: 14px",

View file

@ -84,7 +84,7 @@ const options = ref<optionType[]>([
]);
const getDataNotification = async () => {
showLoader();
// showLoader();
await http
.get(config.API.msgNotificate)
.then((res: any) => {
@ -107,7 +107,7 @@ const getDataNotification = async () => {
// messageError($q, e);
})
.finally(() => {
hideLoader();
// hideLoader();
});
};