Merge branch 'develop' into devTee

This commit is contained in:
setthawutttty 2025-02-24 16:48:27 +07:00
commit 479ffd1e55
13 changed files with 2963 additions and 859 deletions

View file

@ -1,15 +1,11 @@
VITE_S3CLUSTER_PUBLIC_URL: "https://s3cluster.frappet.com/bma-ehr-fpt/organization/strueture/" VITE_COMPETITIVE_EXAM_PANEL=VITE_COMPETITIVE_EXAM_PANEL
VITE_QUALIFY_DISABLE_EMAM_PANEL=VITE_QUALIFY_DISABLE_EMAM_PANEL
VITE_COMPETITIVE_EXAM_PANEL: "https://hrms-dash.bangkok.go.th/goto/KO0GpSu4z?orgId=1" VITE_QUALIFY_EXAM_PANEL=VITE_QUALIFY_EXAM_PANEL
VITE_QUALIFY_DISABLE_EMAM_PANEL: "https://hrms-dash.bangkok.go.th/goto/dQQzpIX4z?orgId=1" VITE_API_PUBLISH_URL=VITE_API_PUBLISH_URL
VITE_QUALIFY_EXAM_PANEL: "https://hrms-dash.bangkok.go.th/goto/cj1ZtIX4z?orgId=1" VITE_API_REPORT_URL=VITE_API_REPORT_URL
VITE_MANUAL_URL=VITE_MANUAL_URL
VITE_API_PUBLISH_URL: "https://bma-ehr-publish.frappet.synology.me" VITE_URL_SSO=VITE_URL_SSO
VITE_API_REPORT_URL: "https://report-server.frappet.synology.me/api/v1/" VITE_URL_LANDING=VITE_URL_LANDING
VITE_MANUAL_URL: "https://bma-ehr-manual.frappet.synology.me" VITE_API_URI_CONFIG=VITE_API_URI_CONFIG
VITE_URL_SSO: "http://localhost:3002/sso" VITE_API_URI_REPORT_CONFIG=VITE_API_URI_REPORT_CONFIG
VITE_URL_LANDING: "http://localhost:3002" VITE_DASHBOARD_PANEL=VITE_DASHBOARD_PANEL
VITE_API_URI_CONFIG: "https://hrms.chin.in.th/api/v1"
VITE_API_URI_REPORT_CONFIG: "https://bma-ehr.frappet.synology.me/api/v2/"
VITE_DASHBOARD_PANEL: "https://bma-dashboard.frappet.synology.me"

View file

@ -44,8 +44,7 @@ export default {
profileNewInsignByProfileId: (profileId: string, type: string) => profileNewInsignByProfileId: (profileId: string, type: string) =>
`${registryNew}${type}/insignia/${profileId}`, `${registryNew}${type}/insignia/${profileId}`,
orgInsigniaActive: () => orgInsigniaActive: () => `${org}/insignia/insignia-type/active`,
`${org}/insignia/insignia-type/active`,
profileNewInsignById: (dataId: string, type: string) => profileNewInsignById: (dataId: string, type: string) =>
`${registryNew}${type}/insignia/${dataId}`, `${registryNew}${type}/insignia/${dataId}`,
@ -169,6 +168,17 @@ export default {
leaveListCard: (id: string, type: string) => leaveListCard: (id: string, type: string) =>
`${registryNew}${type}/leave/admin/${id}`, //noPermission `${registryNew}${type}/leave/admin/${id}`, //noPermission
/** ตำแหน่ง*/
profileSalaryPositionNew: (type: string) => `${registryNew}${type}/salary/position`,
profileListSalaryPositionNew: (id: string, type: string) =>
`${registryNew}${type}/salary/position/${id}`,
profileListSalaryPositionHistoryNew: (profileId: string, type: string) =>
`${registryNew}${type}/salary/position/admin/history/${profileId}`,
profileSalaryPositionSwapNew: (type: string, id: string, type2: string) =>
`${registryNew}${type2}/salary/position/swap/${type}/${id}`,
salaryListCardPosition: (id: string, type: string) =>
`${registryNew}${type}/salary/position/admin/${id}`, //noPermission
/** ตำแหน่งเงินเดือน*/ /** ตำแหน่งเงินเดือน*/
profileSalaryNew: (type: string) => `${registryNew}${type}/salary`, profileSalaryNew: (type: string) => `${registryNew}${type}/salary`,
profileListSalaryNew: (id: string, type: string) => profileListSalaryNew: (id: string, type: string) =>

View file

@ -102,7 +102,7 @@ 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.status ? "Active" : "-"; return row.status ? "ใช้งาน" : "-";
}, },
}, },
]); ]);
@ -444,7 +444,7 @@ onMounted(() => {
<div class="col-3" v-else>-</div> <div class="col-3" v-else>-</div>
<div class="col-3 text-grey-6 text-weight-medium">สถานะ</div> <div class="col-3 text-grey-6 text-weight-medium">สถานะ</div>
<div class="col-3"> <div class="col-3">
{{ props.row.status ? "Active" : "-" }} {{ props.row.status ? "ใช้งาน" : "-" }}
</div> </div>
</div> </div>
<q-separator /> <q-separator />
@ -572,7 +572,7 @@ onMounted(() => {
<q-checkbox <q-checkbox
disable disable
v-model="formData.status" v-model="formData.status"
label="Active" label="ใช้งาน"
keep-color="primary" keep-color="primary"
/> />
</div> </div>

View file

@ -76,7 +76,7 @@ const columns = ref<QTableProps["columns"]>([
sortable: true, sortable: true,
field: "status", field: "status",
format(val, row) { format(val, row) {
return row.status ? "Active" : "-"; return row.status ? "ใช้งาน" : "-";
}, },
headerStyle: "font-size: 14px", headerStyle: "font-size: 14px",
style: "font-size: 14px", style: "font-size: 14px",

View file

@ -0,0 +1,394 @@
<script setup lang="ts">
import { ref, watch, computed } from "vue";
import { useQuasar } from "quasar";
import { useRoute } from "vue-router";
import { useCounterMixin } from "@/stores/mixin";
import http from "@/plugins/http";
import config from "@/app.config";
import type { QTableProps } from "quasar";
import type { ResListSalary } from "@/modules/04_registryPerson/interface/response/Salary";
import DialogHeader from "@/components/DialogHeader.vue";
const $q = useQuasar();
const route = useRoute();
const {
date2Thai,
showLoader,
hideLoader,
messageError,
pathRegistryEmp,
onSearchDataTable,
} = useCounterMixin();
/** props*/
const modal = defineModel<boolean>("modal", { required: true });
const salaryId = defineModel<string>("salaryId", { required: true });
const empType = ref<string>(pathRegistryEmp(route.name?.toString() ?? ""));
const rows = ref<ResListSalary[]>([]); //
const rowsMain = ref<ResListSalary[]>([]); //
const keyword = ref<string>(""); //
const baseColumns = ref<QTableProps["columns"]>([
{
name: "commandDateAffect",
align: "left",
label: "วัน เดือน ปี",
sortable: true,
field: "commandDateAffect",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
format: (v) => date2Thai(v),
},
{
name: "amount",
align: "left",
label: empType.value === "-employee" ? "ค่าตอบแทนรายเดือน" : "เงินเดือน",
sortable: true,
field: "amount",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
format: (v) => Number(v).toLocaleString(),
},
{
name: "positionSalaryAmount",
align: "left",
label: "เงินประจำตำแหน่ง",
sortable: true,
field: "positionSalaryAmount",
headerStyle: "font-size: 14px",
format: (v) => Number(v).toLocaleString(),
style: "font-size: 14px",
},
{
name: "mouthSalaryAmount",
align: "left",
label: "เงินค่าตอบแทนรายเดือน",
sortable: true,
field: "mouthSalaryAmount",
headerStyle: "font-size: 14px",
format: (v) => Number(v).toLocaleString(),
style: "font-size: 14px",
},
{
name: "oc",
align: "left",
label: "สังกัด",
sortable: true,
field: "oc",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "positionName",
align: "left",
label: "ตำแหน่ง",
sortable: true,
field: "positionName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "posNo",
align: "left",
label: "ตำแหน่งเลขที่",
sortable: true,
field: "posNo",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
format(val, row) {
return row.posNoAbb && row.posNo
? `${row.posNoAbb}${row.posNo}`
: row.posNo
? row.posNo
: "-";
},
},
{
name: "positionLine",
align: "left",
label: "สายงาน",
sortable: true,
field: "positionLine",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "positionPathSide",
align: "left",
label: "ด้าน/สาขา",
sortable: true,
field: "positionPathSide",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "positionType",
align: "left",
label: "ตำแหน่งประเภท",
sortable: true,
field: "positionType",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "positionLevel",
align: "left",
label: "ระดับ",
sortable: true,
field: "positionLevel",
format(val, row) {
return `${
row.positionLevel
? row.positionLevel
: row.positionCee
? row.positionCee
: "-"
}`;
},
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "positionExecutive",
align: "left",
label: "ตำแหน่งทางการบริหาร",
sortable: true,
field: "positionExecutive",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "positionExecutiveSide",
align: "left",
label: "ด้านทางการบริหาร",
sortable: true,
field: "positionExecutiveSide",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "salaryClass",
align: "left",
label: "ตำแหน่ง (รายละเอียด)",
sortable: true,
field: "salaryClass",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "commandName",
align: "left",
label: "เอกสารอ้างอิง",
sortable: true,
field: "commandName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "refCommandNo",
align: "left",
label: "เลขที่คำสั่ง",
sortable: true,
field: "refCommandNo",
format(val, row) {
return row.commandNo && row.commandYear
? `${row.commandNo}/${row.commandYear}`
: "";
},
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "remark",
align: "left",
label: "หมายเหตุ",
sortable: true,
field: "remark",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "lastUpdateFullName",
align: "left",
label: "ผู้ดำเนินการ",
sortable: true,
field: "lastUpdateFullName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "lastUpdatedAt",
align: "left",
label: "วันที่แก้ไข",
sortable: true,
field: "lastUpdatedAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
format: (v) => date2Thai(v, false, true),
},
]);
const visibleColumns = ref<string[]>([
"commandDateAffect",
"amount",
"positionSalaryAmount",
"mouthSalaryAmount",
"oc",
"positionName",
"posNo",
"positionLine",
"positionPathSide",
"positionType",
"positionLevel",
"positionExecutive",
"positionExecutiveSide",
"salaryClass",
"commandName",
"refCommandNo",
"remark",
"lastUpdateFullName",
"lastUpdatedAt",
]);
const columns = computed(() => {
if (empType.value === "-employee") {
if (baseColumns.value) {
return baseColumns.value.filter(
(column) =>
column.name !== "positionSalaryAmount" &&
column.name !== "mouthSalaryAmount"
);
}
}
return baseColumns.value;
});
const pagination = ref({
page: 1,
rowsPerPage: 10,
});
/** function fetch ข้อมูลประวัติการแก้ไข*/
function fetchListHistory() {
showLoader();
http
.get(
config.API.profileListSalaryPositionHistoryNew(
salaryId.value,
empType.value
)
)
.then((res) => {
rows.value = res.data.result;
rowsMain.value = res.data.result;
})
.catch((err) => {
messageError($q, err);
})
.finally(() => {
hideLoader();
});
}
/** ฟังก์ชันปิด Popup*/
function closeDialog() {
modal.value = false;
keyword.value = "";
rows.value = [];
}
/** ฟังก์ค้นหาข้อมูลรายการวินัย */
function serchDataTable() {
rows.value = onSearchDataTable(
keyword.value,
rowsMain.value,
columns.value ? columns.value : []
);
}
/**
* การเปลยนแปลงของ modal
* modal เป true เรยก getHistory เพอดงขอมลประวการแกไข
*/
watch(
() => modal.value,
() => {
modal.value && fetchListHistory();
}
);
</script>
<template>
<q-dialog v-model="modal" persistent>
<q-card style="min-width: 80%">
<DialogHeader
:tittle="'ประวัติแก้ไขตำแหน่ง/เงินเดือน'"
:close="closeDialog"
/>
<q-separator color="grey-4" />
<q-card-section style="max-height: 60vh" class="scroll">
<div class="row q-gutter-sm q-mb-sm">
<q-space />
<q-input
dense
outlined
v-model="keyword"
label="ค้นหา"
class="q-mr-sm"
@keydown.enter.pervent="serchDataTable"
>
<template v-slot:append>
<q-icon name="search" />
</template>
</q-input>
<q-select
v-model="visibleColumns"
multiple
outlined
dense
options-dense
:display-value="$q.lang.table.columns"
emit-value
map-options
:options="columns"
option-value="name"
style="min-width: 140px"
/>
</div>
<d-table
ref="table"
row-key="id"
flat
bordered
dense
:columns="columns"
:rows="rows"
:paging="true"
v-model:pagination="pagination"
:rows-per-page-options="[10, 20, 50, 100]"
:visible-columns="visibleColumns"
>
<template v-slot:header="props">
<q-tr :props="props">
<q-th v-for="col in props.cols" :key="col.name" :props="props">
<span class="text-weight-medium">{{ col.label }}</span>
</q-th>
</q-tr>
</template>
<template v-slot:body="props">
<q-tr :props="props">
<q-td v-for="col in props.cols">
<div class="table_ellipsis">
{{ col.value ? col.value : "-" }}
</div>
</q-td>
</q-tr>
</template>
</d-table>
</q-card-section>
</q-card>
</q-dialog>
</template>
<style scoped></style>

View file

@ -1,5 +1,10 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref } from "vue"; import { ref } from "vue";
import { useCounterMixin } from "@/stores/mixin";
import { useRoute } from "vue-router";
const { pathRegistryEmp } = useCounterMixin();
const route = useRoute();
/** importComponents*/ /** importComponents*/
import Info from "@/modules/04_registryPerson/components/detail/GovernmentInformation/01_Info.vue"; // import Info from "@/modules/04_registryPerson/components/detail/GovernmentInformation/01_Info.vue"; //
@ -11,9 +16,12 @@ import HelpGovernmentDetail from "@/modules/04_registryPerson/components/detail/
import Postion from "@/modules/04_registryPerson/components/detail/GovernmentInformation/07_Position.vue"; import Postion from "@/modules/04_registryPerson/components/detail/GovernmentInformation/07_Position.vue";
import { useRegistryNewDataStore } from "@/modules/04_registryPerson/store"; import { useRegistryNewDataStore } from "@/modules/04_registryPerson/store";
const empType = ref<string>(pathRegistryEmp(route.name?.toString() ?? ""));
const tab = ref<string>("1"); const tab = ref<string>("1");
const storeRegistry = useRegistryNewDataStore(); const storeRegistry = useRegistryNewDataStore();
</script> </script>
<template> <template>
<div class="row items-center q-my-md"> <div class="row items-center q-my-md">
<div class="text-dark row items-center q-px-md"> <div class="text-dark row items-center q-px-md">
@ -35,11 +43,11 @@ const storeRegistry = useRegistryNewDataStore();
> >
<q-tab name="1" label="ข้อมูลราชการ" /> <q-tab name="1" label="ข้อมูลราชการ" />
<q-tab name="7" label="ตำแหน่ง" /> <q-tab name="7" label="ตำแหน่ง" />
<q-tab v-if="empType != '-employee'" name="5" label="รักษาการในตำแหน่ง" />
<q-tab v-if="empType != '-employee'" name="6" label="ช่วยราชการ" />
<q-tab name="2" label="วินัย" /> <q-tab name="2" label="วินัย" />
<q-tab name="3" label="การลา" /> <q-tab name="3" label="การลา" />
<q-tab name="4" label="ปฏิบัติราชการพิเศษ" /> <q-tab name="4" label="ปฏิบัติราชการพิเศษ" />
<q-tab name="5" label="รักษาการในตำแหน่ง" />
<q-tab name="6" label="ช่วยราชการ" />
</q-tabs> </q-tabs>
<q-separator /> <q-separator />
@ -56,10 +64,10 @@ const storeRegistry = useRegistryNewDataStore();
<q-tab-panel name="4"> <q-tab-panel name="4">
<PerformSpecialWork :is-leave="storeRegistry.isLeave" /> <PerformSpecialWork :is-leave="storeRegistry.isLeave" />
</q-tab-panel> </q-tab-panel>
<q-tab-panel name="5"> <q-tab-panel v-if="empType != '-employee'" name="5">
<ActingPos :is-leave="storeRegistry.isLeave" /> <ActingPos :is-leave="storeRegistry.isLeave" />
</q-tab-panel> </q-tab-panel>
<q-tab-panel name="6"> <q-tab-panel v-if="empType != '-employee'" name="6">
<HelpGovernmentDetail :is-leave="storeRegistry.isLeave" /> <HelpGovernmentDetail :is-leave="storeRegistry.isLeave" />
</q-tab-panel> </q-tab-panel>
<q-tab-panel name="7"> <q-tab-panel name="7">

View file

@ -60,11 +60,11 @@ const command = ref<string>("");
const commandId = ref<string>(""); const commandId = ref<string>("");
const baseColumns = ref<QTableProps["columns"]>([ const baseColumns = ref<QTableProps["columns"]>([
{ {
name: "date", name: "commandDateAffect",
align: "left", align: "left",
label: "วัน เดือน ปี", label: "วัน เดือน ปี",
sortable: true, sortable: true,
field: "date", field: "commandDateAffect",
headerStyle: "font-size: 14px", headerStyle: "font-size: 14px",
style: "font-size: 14px", style: "font-size: 14px",
format: (v) => date2Thai(v), format: (v) => date2Thai(v),
@ -108,13 +108,20 @@ const baseColumns = ref<QTableProps["columns"]>([
field: "posNo", field: "posNo",
headerStyle: "font-size: 14px", headerStyle: "font-size: 14px",
style: "font-size: 14px", style: "font-size: 14px",
format(val, row) {
return row.posNoAbb && row.posNo
? `${row.posNoAbb}${row.posNo}`
: row.posNo
? row.posNo
: "-";
},
}, },
{ {
name: "position", name: "positionName",
align: "left", align: "left",
label: "ตำแหน่ง", label: "ตำแหน่ง",
sortable: true, sortable: true,
field: "position", field: "positionName",
headerStyle: "font-size: 14px", headerStyle: "font-size: 14px",
style: "font-size: 14px", style: "font-size: 14px",
}, },
@ -133,16 +140,24 @@ const baseColumns = ref<QTableProps["columns"]>([
label: "ระดับ", label: "ระดับ",
sortable: true, sortable: true,
field: "positionLevel", field: "positionLevel",
format(val, row) {
return `${
row.positionLevel
? row.positionLevel
: row.positionCee
? row.positionCee
: "-"
}`;
},
headerStyle: "font-size: 14px", headerStyle: "font-size: 14px",
style: "font-size: 14px", style: "font-size: 14px",
}, },
{ {
name: "templateDoc", name: "commandName",
align: "left", align: "left",
label: "เอกสารอ้างอิง", label: "เอกสารอ้างอิง",
sortable: true, sortable: true,
field: "templateDoc", field: "commandName",
headerStyle: "font-size: 14px", headerStyle: "font-size: 14px",
style: "font-size: 14px", style: "font-size: 14px",
}, },
@ -152,6 +167,20 @@ const baseColumns = ref<QTableProps["columns"]>([
label: "เลขที่คำสั่ง", label: "เลขที่คำสั่ง",
sortable: true, sortable: true,
field: "refCommandNo", field: "refCommandNo",
format(val, row) {
return row.commandNo && row.commandYear
? `${row.commandNo}/${row.commandYear}`
: "";
},
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "remark",
align: "left",
label: "หมายเหตุ",
sortable: true,
field: "remark",
headerStyle: "font-size: 14px", headerStyle: "font-size: 14px",
style: "font-size: 14px", style: "font-size: 14px",
}, },
@ -169,16 +198,17 @@ const columns = computed(() => {
return baseColumns.value; return baseColumns.value;
}); });
const visibleColumns = ref<string[]>([ const visibleColumns = ref<string[]>([
"date", "commandDateAffect",
"amount", "amount",
"positionSalaryAmount", "positionSalaryAmount",
"mouthSalaryAmount", "mouthSalaryAmount",
"posNo", "posNo",
"position", "positionName",
"positionType", "positionType",
"positionLevel", "positionLevel",
"templateDoc", "commandName",
"refCommandNo", "refCommandNo",
"remark",
]); ]);
const pagination = ref({ const pagination = ref({
page: 1, page: 1,

View file

@ -34,11 +34,11 @@ const rowsMain = ref<ResListSalary[]>([]); //รายการข้อมู
const keyword = ref<string>(""); // const keyword = ref<string>(""); //
const baseColumns = ref<QTableProps["columns"]>([ const baseColumns = ref<QTableProps["columns"]>([
{ {
name: "date", name: "commandDateAffect",
align: "left", align: "left",
label: "วัน เดือน ปี", label: "วัน เดือน ปี",
sortable: true, sortable: true,
field: "date", field: "commandDateAffect",
headerStyle: "font-size: 14px", headerStyle: "font-size: 14px",
style: "font-size: 14px", style: "font-size: 14px",
format: (v) => date2Thai(v), format: (v) => date2Thai(v),
@ -83,11 +83,11 @@ const baseColumns = ref<QTableProps["columns"]>([
style: "font-size: 14px", style: "font-size: 14px",
}, },
{ {
name: "position", name: "positionName",
align: "left", align: "left",
label: "ตำแหน่ง", label: "ตำแหน่ง",
sortable: true, sortable: true,
field: "position", field: "positionName",
headerStyle: "font-size: 14px", headerStyle: "font-size: 14px",
style: "font-size: 14px", style: "font-size: 14px",
}, },
@ -99,6 +99,13 @@ const baseColumns = ref<QTableProps["columns"]>([
field: "posNo", field: "posNo",
headerStyle: "font-size: 14px", headerStyle: "font-size: 14px",
style: "font-size: 14px", style: "font-size: 14px",
format(val, row) {
return row.posNoAbb && row.posNo
? `${row.posNoAbb}${row.posNo}`
: row.posNo
? row.posNo
: "-";
},
}, },
{ {
name: "positionLine", name: "positionLine",
@ -133,6 +140,15 @@ const baseColumns = ref<QTableProps["columns"]>([
label: "ระดับ", label: "ระดับ",
sortable: true, sortable: true,
field: "positionLevel", field: "positionLevel",
format(val, row) {
return `${
row.positionLevel
? row.positionLevel
: row.positionCee
? row.positionCee
: "-"
}`;
},
headerStyle: "font-size: 14px", headerStyle: "font-size: 14px",
style: "font-size: 14px", style: "font-size: 14px",
}, },
@ -164,11 +180,11 @@ const baseColumns = ref<QTableProps["columns"]>([
style: "font-size: 14px", style: "font-size: 14px",
}, },
{ {
name: "templateDoc", name: "commandName",
align: "left", align: "left",
label: "เอกสารอ้างอิง", label: "เอกสารอ้างอิง",
sortable: true, sortable: true,
field: "templateDoc", field: "commandName",
headerStyle: "font-size: 14px", headerStyle: "font-size: 14px",
style: "font-size: 14px", style: "font-size: 14px",
}, },
@ -178,6 +194,20 @@ const baseColumns = ref<QTableProps["columns"]>([
label: "เลขที่คำสั่ง", label: "เลขที่คำสั่ง",
sortable: true, sortable: true,
field: "refCommandNo", field: "refCommandNo",
format(val, row) {
return row.commandNo && row.commandYear
? `${row.commandNo}/${row.commandYear}`
: "";
},
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "remark",
align: "left",
label: "หมายเหตุ",
sortable: true,
field: "remark",
headerStyle: "font-size: 14px", headerStyle: "font-size: 14px",
style: "font-size: 14px", style: "font-size: 14px",
}, },
@ -202,12 +232,12 @@ const baseColumns = ref<QTableProps["columns"]>([
}, },
]); ]);
const visibleColumns = ref<string[]>([ const visibleColumns = ref<string[]>([
"date", "commandDateAffect",
"amount", "amount",
"positionSalaryAmount", "positionSalaryAmount",
"mouthSalaryAmount", "mouthSalaryAmount",
"oc", "oc",
"position", "positionName",
"posNo", "posNo",
"positionLine", "positionLine",
"positionPathSide", "positionPathSide",
@ -216,8 +246,9 @@ const visibleColumns = ref<string[]>([
"positionExecutive", "positionExecutive",
"positionExecutiveSide", "positionExecutiveSide",
"salaryClass", "salaryClass",
"templateDoc", "commandName",
"refCommandNo", "refCommandNo",
"remark",
"lastUpdateFullName", "lastUpdateFullName",
"lastUpdatedAt", "lastUpdatedAt",
]); ]);

View file

@ -23,7 +23,16 @@ interface ResListSalary {
profileId: string; profileId: string;
refCommandNo: string; refCommandNo: string;
templateDoc: string; templateDoc: string;
commandCode: string;
commandDateAffect: string;
commandDateSign: string;
commandId: string; commandId: string;
commandName: string;
commandNo: string;
commandYear: string;
positionName: string;
positionCee: string;
posNoAbb: string;
} }
interface ResType { interface ResType {

View file

@ -458,14 +458,14 @@ onMounted(async () => {
</div> </div>
</q-form> </q-form>
<div class="row q-mt-sm q-gutter-sm justify-center"> <div class="row q-mt-sm q-gutter-sm">
<q-btn-dropdown <q-btn-dropdown
flat flat
rounded rounded
dense dense
label-color="white" label-color="white"
dropdown-icon="mdi-chevron-down" dropdown-icon="mdi-chevron-down"
class="q-px-sm" class="q-pl-sm"
@click="() => ((selectNode = true), showLoader())" @click="() => ((selectNode = true), showLoader())"
> >
<template v-slot:label> <template v-slot:label>
@ -493,6 +493,19 @@ onMounted(async () => {
</template> </template>
</q-btn-dropdown> </q-btn-dropdown>
<q-toggle
v-if="store.formFilter.nodeId"
v-model="store.formFilter.isAll"
color="primary"
label="แสดงทุกตำแหน่ง"
class="q-pr-sm"
@update:model-value="getSearch"
>
<q-tooltip
>แสดงทกตำแหนงทอยภายใตหนวยงาน/วนราชการทเลอก</q-tooltip
>
</q-toggle>
<q-separator inset vertical class="lineFil" /> <q-separator inset vertical class="lineFil" />
<q-btn-dropdown <q-btn-dropdown
@ -581,6 +594,16 @@ onMounted(async () => {
</q-list> </q-list>
</q-btn-dropdown> </q-btn-dropdown>
<q-space />
<div class="q-pt-sm q-pr-sm">
<a href="/report/registry" class="text-white">
การคนหาขนส
<q-tooltip
>ไปยงหนาการคนหาขนส (Advanced search)</q-tooltip
>
</a>
</div>
<q-separator <q-separator
inset inset
vertical vertical
@ -597,13 +620,14 @@ onMounted(async () => {
/> />
</div> </div>
<div <div
class="row q-gutter-sm justify-center" class="row q-gutter-sm justify-start"
v-if="empType !== 'officer'" v-if="empType !== 'officer'"
> >
<q-toggle <q-toggle
v-model="store.formFilter.isShowRetire" v-model="store.formFilter.isShowRetire"
color="primary" color="primary"
label="แสดงข้อมูลผู้พ้นจากราชการ" label="แสดงข้อมูลผู้พ้นจากราชการ"
class="q-pr-sm"
@update:model-value="getSearch" @update:model-value="getSearch"
/> />
<q-btn-dropdown <q-btn-dropdown
@ -619,7 +643,7 @@ onMounted(async () => {
{{ {{
store.labelOption.retireType !== "ทั้งหมด" store.labelOption.retireType !== "ทั้งหมด"
? store.labelOption.retireType ? store.labelOption.retireType
: `ประเภท${store.labelOption.retireType}` : `${store.labelOption.retireType}`
}} }}
<q-btn <q-btn
v-if="store.labelOption.retireType !== 'ทั้งหมด'" v-if="store.labelOption.retireType !== 'ทั้งหมด'"
@ -685,12 +709,13 @@ onMounted(async () => {
<div <div
v-if="empType === 'officer'" v-if="empType === 'officer'"
class="row q-gutter-sm justify-center" class="row q-gutter-sm justify-start"
> >
<q-toggle <q-toggle
v-model="store.formFilter.isProbation" v-model="store.formFilter.isProbation"
color="primary" color="primary"
label="ทดลองปฏิบัติหน้าที่ราชการ" label="ทดลองปฏิบัติหน้าที่ราชการ"
class="q-pr-sm"
@update:model-value="getSearch" @update:model-value="getSearch"
/> />
@ -700,6 +725,7 @@ onMounted(async () => {
v-model="store.formFilter.isShowRetire" v-model="store.formFilter.isShowRetire"
color="primary" color="primary"
label="แสดงข้อมูลผู้พ้นจากราชการ" label="แสดงข้อมูลผู้พ้นจากราชการ"
class="q-pr-sm"
@update:model-value="getSearch" @update:model-value="getSearch"
/> />
@ -710,13 +736,12 @@ onMounted(async () => {
dense dense
label-color="white" label-color="white"
dropdown-icon="mdi-chevron-down" dropdown-icon="mdi-chevron-down"
class="q-px-sm"
> >
<template v-slot:label> <template v-slot:label>
{{ {{
store.labelOption.retireType !== "ทั้งหมด" store.labelOption.retireType !== "ทั้งหมด"
? store.labelOption.retireType ? store.labelOption.retireType
: `ประเภท${store.labelOption.retireType}` : `${store.labelOption.retireType}`
}} }}
<q-btn <q-btn
v-if="store.labelOption.retireType !== 'ทั้งหมด'" v-if="store.labelOption.retireType !== 'ทั้งหมด'"
@ -745,13 +770,13 @@ onMounted(async () => {
<q-separator inset vertical class="lineFil" /> <q-separator inset vertical class="lineFil" />
<q-toggle <!-- <q-toggle
v-if="store.formFilter.nodeId" v-if="store.formFilter.nodeId"
v-model="store.formFilter.isAll" v-model="store.formFilter.isAll"
color="primary" color="primary"
label="แสดงตำแหน่งทั้งหมด" label="แสดงตำแหน่งทั้งหมด"
@update:model-value="getSearch" @update:model-value="getSearch"
/> /> -->
<q-btn-dropdown <q-btn-dropdown
rounded rounded
@ -779,6 +804,9 @@ onMounted(async () => {
</q-list> </q-list>
</q-btn-dropdown> </q-btn-dropdown>
</div> </div>
<!-- <div class="row justify-center">
<a href="/report/registry" class="text-white"> Advanced search </a>
</div> -->
</div> </div>
</div> </div>
</q-card-section> </q-card-section>

View file

@ -73,6 +73,15 @@ watch(
async () => { async () => {
if (modal.value) { if (modal.value) {
await fetchTree(); await fetchTree();
if (!orgName.value) {
nodeData.name = "";
nodeData.node = "";
nodeData.nodeId = "";
store.formFilter.node = null;
store.formFilter.nodeId = null;
expanded.value = [];
}
} }
} }
); );
@ -143,8 +152,8 @@ watch(
<q-separator /> <q-separator />
<q-card-actions align="right"> <q-card-actions align="right">
<q-btn label="ค้นหา" color="secondary" @click="sendNode"> <q-btn label="เลือก" color="secondary" @click="sendNode">
<q-tooltip>นหา</q-tooltip></q-btn <q-tooltip>เลอก</q-tooltip></q-btn
> >
</q-card-actions> </q-card-actions>
</q-card> </q-card>

View file

@ -1,16 +1,17 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref, onMounted, computed } from "vue"; import { ref, onMounted, watch, computed } from "vue";
import { useQuasar, type QTableProps } from "quasar"; import { useQuasar, type QTableProps } from "quasar";
import { VuePDF, usePDF } from "@tato30/vue-pdf";
import axios from "axios";
import genReportXLSX from "@/plugins/genreportxlsx";
import * as XLSX from "xlsx"; 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 { checkPermission } from "@/utils/permissions"; import { checkPermission } from "@/utils/permissions";
import { useCounterMixin } from "@/stores/mixin"; import { useCounterMixin } from "@/stores/mixin";
import { useReportStore } from "@/modules/21_report/store"; import { useReportStore } from "@/modules/21_report/store";
import { useRegistryNewDataStore } from "@/modules/04_registryPerson/store";
import { useStructureTree } from "@/stores/structureTree";
import type { OptionData } from "@/modules/07_insignia/interface/index/Main"; import type { OptionData } from "@/modules/07_insignia/interface/index/Main";
import type { import type {
RangeAge, RangeAge,
@ -22,12 +23,14 @@ import type {
DataEducationLevel, DataEducationLevel,
} from "@/modules/21_report/interface/Main"; } from "@/modules/21_report/interface/Main";
import LoadView from "@/components/LoadView.vue";
import DialogOrg from "@/modules/21_report/components/01_org/DialogOrg.vue"; import DialogOrg from "@/modules/21_report/components/01_org/DialogOrg.vue";
import PopupPersonal from "@/components/Dialogs/PopupPersonalNew.vue";
const $q = useQuasar(); const $q = useQuasar();
const route = useRoute();
const storeReport = useReportStore(); const storeReport = useReportStore();
const stroeRegistry = useRegistryNewDataStore();
const { fetchStructureTree } = useStructureTree();
const mixin = useCounterMixin(); const mixin = useCounterMixin();
const { messageError, showLoader, hideLoader, date2Thai } = mixin; const { messageError, showLoader, hideLoader, date2Thai } = mixin;
@ -45,9 +48,6 @@ const detailReport = ref<any>();
/** ช่วงเวลา */ /** ช่วงเวลา */
const dateStart = ref<Date | null>(null); // const dateStart = ref<Date | null>(null); //
const dateEnd = ref<Date | null>(null); // const dateEnd = ref<Date | null>(null); //
const objMarkerLabel = computed(() => {
return { 39: `ช่วงอายุ ${rangeAge.value.min}-${rangeAge.value.max} ปี` };
});
const rangeAge = ref<RangeAge>({ const rangeAge = ref<RangeAge>({
min: 18, min: 18,
@ -90,33 +90,22 @@ const org = ref<string>("");
const isProbation = ref<boolean>(false); const isProbation = ref<boolean>(false);
const isRetire = ref<boolean>(false); const isRetire = ref<boolean>(false);
const isRetireLaw = ref<boolean>(false);
const pagination = ref<any>({ const pagination = ref<any>({
sortBy: "dateAppoint",
descending: true,
page: 1, page: 1,
rowsPerPage: 10, rowsPerPage: 20,
}); });
const sortBy = ref<string>("ASC"); const sortBy = ref<string>("DESC");
const retireType = ref<string>(""); const retireType = ref<string>("");
const retireTypeOps = ref<DataOption[]>([]); const retireTypeOps = ref<DataOption[]>([]);
const retireTypeOpsMain = ref<DataOption[]>([ const retireTypeOpsMain = ref<DataOption[]>(stroeRegistry.retireTypeOps);
{ id: "RETIRE", name: "เกษียณ" },
{ id: "RETIRE_RESIGN", name: "ลาออก" },
{ id: "RETIRE_DECEASED", name: "ถึงแก่กรรม" },
{ id: "RETIRE_OUT", name: "ให้ออกจากราชการ" },
{ id: "DISCIPLINE_RESULT_REMOVE", name: "ปลดออกจากราชการ" },
{ id: "DISCIPLINE_RESULT_DISMISS", name: "ไล่ออกจากราชการ" },
{ id: "DISCIPLINE_SUSPEND", name: "ถูกพักจากราชการ" },
{ id: "PROBATION_REPORT", name: "ไม่ผ่านทดลองงาน" },
]);
const retireTypeOpsMainEMP = ref<DataOption[]>([ const retireTypeOpsMainEMP = ref<DataOption[]>(stroeRegistry.retireTypeEmpOps);
{ id: "RETIRE", name: "เกษียณ" },
{ id: "RETIRE_RESIGN_EMP", name: "ลาออก" },
{ id: "RETIRE_DECEASED", name: "ถึงแก่กรรม" },
{ id: "RETIRE_OUT_EMP", name: "ให้ออกจากราชการ" },
]);
const visibleColumns = ref<string[]>([ const visibleColumnsBase = ref<string[]>([
"no", "no",
"fullName", "fullName",
"posNo", "posNo",
@ -129,12 +118,14 @@ const visibleColumns = ref<string[]>([
"status", "status",
"education", "education",
"dateAppoint", "dateAppoint",
"dateRetireLaw",
"age", "age",
"currentPosition", "currentPosition",
"lengthPosition", "lengthPosition",
]); ]);
const columns = ref<QTableProps["columns"]>([ const columns = computed<QTableProps["columns"]>(() => {
return [
{ {
name: "no", name: "no",
align: "left", align: "left",
@ -171,7 +162,7 @@ const columns = ref<QTableProps["columns"]>([
{ {
name: "position", name: "position",
align: "left", align: "left",
label: "ตำแหน่งในสายงาน", label: employeeClass.value === "officer" ? "ตำแหน่งในสายงาน" : "ตำแหน่ง",
sortable: true, sortable: true,
field: "position", field: "position",
headerStyle: "font-size: 14px", headerStyle: "font-size: 14px",
@ -264,6 +255,24 @@ const columns = ref<QTableProps["columns"]>([
field: "dateAppoint", field: "dateAppoint",
headerStyle: "font-size: 14px", headerStyle: "font-size: 14px",
style: "font-size: 14px", style: "font-size: 14px",
format(val, row) {
return val ? date2Thai(val) : "";
},
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "dateRetireLaw",
align: "left",
label: "วันที่เกษียณอายุราชการตามกฏหมาย",
sortable: true,
field: "dateRetireLaw",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
format(val, row) {
return val ? date2Thai(row.dateRetireLaw) : "";
},
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" }),
}, },
@ -300,7 +309,14 @@ 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" }),
}, },
]); ];
});
const visibleColumns = computed<string[]>(() => {
return employeeClass.value === "officer"
? visibleColumnsBase.value
: visibleColumnsBase.value.filter((e: string) => e !== "positionExecutive");
});
function onOpenOrg() { function onOpenOrg() {
modalOrg.value = true; modalOrg.value = true;
@ -362,7 +378,6 @@ function filterOption(val: string, update: any, typeOp: string) {
*/ */
function updateLevel(val: string) { function updateLevel(val: string) {
posType.value = val; posType.value = val;
if (val) { if (val) {
const listData: any = posTypeMainOp.value.find( const listData: any = posTypeMainOp.value.find(
(item: PosType) => item.posTypeName == val (item: PosType) => item.posTypeName == val
@ -380,9 +395,7 @@ function updateLevel(val: string) {
} }
} }
/** /** ฟังก์เรียกข้อมูลรายการประเภทตำแหน่ง*/
* งกเรยกขอมลรายการประเภทตำแหน
*/
async function getType() { async function getType() {
posType.value = ""; posType.value = "";
posLevel.value = ""; posLevel.value = "";
@ -420,9 +433,7 @@ async function getOptions() {
}); });
} }
/** /** ฟังก์เรียกข้อมูลรายการตำแหน่งทางการบริหาร*/
* งกเรยกขอมลรายการตำแหนงทางการบรหาร
*/
async function getExecutive() { async function getExecutive() {
await http await http
.get(config.API.orgPosExecutive) .get(config.API.orgPosExecutive)
@ -491,17 +502,18 @@ async function onSearch() {
positionExecutive: positionExecutive.value, positionExecutive: positionExecutive.value,
gender: gender.value, gender: gender.value,
status: status.value, status: status.value,
education: education.value, education: education.value.trim(),
ageMin: rangeAge.value.min, ageMin: rangeAge.value.min,
ageMax: rangeAge.value.max, ageMax: rangeAge.value.max,
dateStart: dateStart.value ?? "", dateStart: dateStart.value ?? null,
dateEnd: dateEnd.value ?? "", dateEnd: dateEnd.value ?? null,
isProbation: isProbation.value, isProbation: isProbation.value,
isRetire: isRetire.value, isRetire: isRetire.value,
retireType: retireType.value, retireType: retireType.value,
sortBy: sortBy.value ? "dateAppoint" : "", sortBy: sortBy.value ? "dateAppoint" : "",
sort: sortBy.value ? sortBy.value : "ASC", sort: sortBy.value ? sortBy.value : "ASC",
isRetireLaw: isRetireLaw.value,
}; };
showLoader(); showLoader();
await http await http
@ -515,6 +527,7 @@ async function onSearch() {
const data = res.data.result.data; const data = res.data.result.data;
total.value = res.data.result.total; total.value = res.data.result.total;
rows.value = data.map((item: any, index: number) => ({ rows.value = data.map((item: any, index: number) => ({
profileId: item.profileId,
no: index + 1, no: index + 1,
fullName: item.firstName fullName: item.firstName
? `${item.prefix ?? ""}${item.firstName ?? ""} ${item.lastName ?? ""}` ? `${item.prefix ?? ""}${item.firstName ?? ""} ${item.lastName ?? ""}`
@ -528,10 +541,12 @@ async function onSearch() {
gender: item.gender ?? "-", gender: item.gender ?? "-",
status: item.relationship ?? "-", status: item.relationship ?? "-",
education: item.degree ?? "-", education: item.degree ?? "-",
dateAppoint: item.dateAppoint ? date2Thai(item.dateAppoint) : "-", dateAppoint: item.dateAppoint ?? "-",
age: item.age ?? "-", age: item.age ?? "-",
currentPosition: item.currentPosition ?? "-", currentPosition: item.currentPosition ?? "-",
lengthPosition: item.lengthPosition ?? "-", lengthPosition: item.lengthPosition ?? "-",
empType: employeeClass.value,
dateRetireLaw: item.dateRetireLaw ?? "-",
})); }));
}) })
.catch((e) => { .catch((e) => {
@ -547,8 +562,17 @@ async function onSearch() {
} }
function exportToExcel() { function exportToExcel() {
const newData = rows.value.map((e: any) => {
const { profileId, empType, ...rest } = e;
return {
...rest,
dateAppoint: date2Thai(e.dateAppoint),
dateRetireLaw: date2Thai(e.dateRetireLaw),
};
});
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(rows.value, { const worksheet = XLSX.utils.json_to_sheet(newData, {
header: visibleColumns.value, header: visibleColumns.value,
}); });
@ -556,29 +580,110 @@ function exportToExcel() {
XLSX.utils.sheet_add_aoa(worksheet, [headers], { origin: "A1" }); XLSX.utils.sheet_add_aoa(worksheet, [headers], { origin: "A1" });
const workbook = XLSX.utils.book_new(); const workbook = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(workbook, worksheet, "รายงานทะเบียนประวัติ"); // sheet XLSX.utils.book_append_sheet(workbook, worksheet, `รายงานทะเบียนประวัติ`); // sheet
XLSX.writeFile(workbook, "รายงานทะเบียนประวัติ.xlsx"); XLSX.writeFile(
workbook,
`รายงานทะเบียนประวัติ${
employeeClass.value === "officer"
? "(ข้าราชการ กทม. สามัญ)"
: "(ลูกจ้างประจำ กทม.)"
}.xlsx`
);
}
/** ฟังก์ชันล้างตัวกรองทั้งหมด*/
function clearFilter() {
//
org.value = "";
storeReport.formFilter.node = null;
storeReport.formFilter.nodeId = null;
posType.value = ""; //,
posLevel.value = ""; //,
position.value = ""; //
positionExecutive.value = ""; //
gender.value = ""; //
status.value = ""; //
education.value = ""; //
//
dateStart.value = null; //
dateEnd.value = null; //
//
rangeAge.value.min = 18;
rangeAge.value.max = 60;
isProbation.value = false; //
isRetire.value = false; //
retireType.value = ""; //
expandedModal.value = false;
filterTree.value = "";
}
watch(
() => pagination.value.descending,
() => {
if (pagination.value.sortBy === "dateAppoint") {
sortBy.value = pagination.value.descending ? "DESC" : "ASC";
}
}
);
const node = ref<any[]>([]);
const filterTree = ref<string>("");
const expanded = ref<string[]>([]);
const expandedModal = ref<boolean>(false);
async function fetchTree() {
const data = await fetchStructureTree(route.meta.Key as string, true);
if (data) {
node.value = data;
}
}
/**
* งกนเลอกหนวยงาน/วนราชการ
* @param data อมลหนวยงาน/วนราชการทองการคนหาร
* เพอคนหาขอมลตามหนวยงาน/วนราชการ
*/
function updateSelectedTreeMain(data: any) {
org.value = data.orgName;
storeReport.formFilter.node = data.orgLevel;
storeReport.formFilter.nodeId = data.orgTreeId;
expandedModal.value = false;
}
const personId = ref<string>("");
const empType = ref<string>("");
const modalPersonal = ref<boolean>(false);
function onViewInfo(id: string, type: string) {
personId.value = id;
empType.value = type;
modalPersonal.value = true;
}
function updatemodalPersonal(modal: boolean) {
modalPersonal.value = modal;
} }
onMounted(async () => { onMounted(async () => {
showLoader(); showLoader();
storeReport.formFilter.node = null;
storeReport.formFilter.nodeId = "";
Promise.all([ Promise.all([
getType(), getType(),
getOptions(), getOptions(),
getExecutive(), getExecutive(),
getDataPerson(), getDataPerson(),
getEducationLevel(), getEducationLevel(),
fetchTree(),
]) ])
.then(() => {
hideLoader();
})
.catch((e) => { .catch((e) => {
messageError($q, e); messageError($q, e);
hideLoader();
}) })
.finally(() => { .finally(() => {
setTimeout(() => { setTimeout(() => {
loadingBtn.value = false; loadingBtn.value = false;
hideLoader();
}, 500); }, 500);
}); });
}); });
@ -590,11 +695,7 @@ onMounted(async () => {
</div> </div>
<div class="col-12"> <div class="col-12">
<q-form <q-form greedy @submit.prevent @validation-success="onSearch">
greedy
@submit.prevent
@validation-success="onSearch"
>
<div class="row col-12 q-gutter-sm"> <div class="row col-12 q-gutter-sm">
<q-card class="col-12 q-pa-sm"> <q-card class="col-12 q-pa-sm">
<div class="row col-12 q-col-gutter-sm no-wrap"> <div class="row col-12 q-col-gutter-sm no-wrap">
@ -609,11 +710,11 @@ onMounted(async () => {
map-options map-options
option-label="name" option-label="name"
option-value="id" option-value="id"
@update:model-value="retireType = ''" @update:model-value="clearFilter(), getType()"
> >
</q-select> </q-select>
</div> </div>
<div class="col-lg-9 col-md-8 col-sm-8 col-xs-11"> <!-- <div class="col-lg-9 col-md-8 col-sm-8 col-xs-11">
<q-input <q-input
outlined outlined
dense dense
@ -634,7 +735,7 @@ onMounted(async () => {
/> />
</template> </template>
</q-input> </q-input>
</div> </div> -->
<q-space /> <q-space />
<div> <div>
<q-btn <q-btn
@ -700,15 +801,125 @@ onMounted(async () => {
<div class="col-12 row q-pa-sm q-col-gutter-sm"> <div class="col-12 row q-pa-sm q-col-gutter-sm">
<div class="col"> <div class="col">
<q-card flat bordered class="col-12"> <q-card flat bordered class="col-12">
<q-card-section bordered class="bg-primary text-subtitle2 text-white q-pa-sm row col-12 items-center"> <q-card-section
bordered
class="bg-primary text-subtitle2 text-white q-pa-sm row col-12 items-center"
>
<q-icon name="mdi-filter" class="q-mr-xs" /> <q-icon name="mdi-filter" class="q-mr-xs" />
วกรอง วกรอง
<q-space /> <q-space />
<q-btn dense size="12px" class="q-px-sm" rounded flat label="ล้างทั้งหมด" /> <q-btn
dense
size="12px"
class="q-px-sm"
rounded
flat
label="ล้างทั้งหมด"
@click.stop.pervent="clearFilter"
/>
</q-card-section> </q-card-section>
<q-separator /> <q-separator />
<div class="row col-12"> <div class="row col-12">
<div class="row col-12 q-col-x-gutter-xs items-center"> <div class="row col-12 q-col-x-gutter-xs items-center">
<div class="col-12">
<q-expansion-item
v-model="expandedModal"
dense
dense-toggle
expand-separator
class="expansion-item"
>
<template #header>
<div class="full-width flex items-stretch">
<q-input
dense
:model-value="org ? org : 'ทั้งหมด'"
autogrow
borderless
label="สังกัด"
class="bg-white full-width"
>
<template v-if="org" v-slot:append>
<q-icon
name="cancel"
@click.stop.prevent="
(org = ''),
(storeReport.formFilter.node = null),
(storeReport.formFilter.nodeId = null)
"
class="cursor-pointer"
style="opacity: 0.6"
/>
</template>
</q-input>
</div>
<!-- @click="onOpenOrg" -->
</template>
<q-separator />
<q-card-section>
<q-input
dense
outlined
v-model="filterTree"
label="ค้นหา"
>
<template v-slot:append>
<q-icon
v-if="filterTree !== ''"
name="clear"
class="cursor-pointer"
@click="filterTree = ''"
/>
<q-icon v-else name="search" color="grey-5" />
</template>
</q-input>
<q-tree
class="tree-container q-mt-sm"
dense
:nodes="node"
node-key="orgTreeName"
label-key="labelName"
v-model:expanded="expanded"
no-results-label="ไม่พบข้อมูลที่ค้นหา"
no-nodes-label="ไม่มีข้อมูล"
:filter="filterTree.trim()"
>
<template v-slot:default-header="prop">
<q-item
clickable
active-class="my-list-link text-primary text-weight-medium"
class="row col-12 items-center text-dark q-py-xs q-pl-sm rounded-borders my-list"
:active="
storeReport.formFilter.nodeId ===
prop.node.orgTreeId
"
@click.stop="updateSelectedTreeMain(prop.node)"
>
<div>
<div class="text-weight-medium">
{{ prop.node.orgTreeName }}
</div>
<div class="text-weight-light text-grey-8">
{{
prop.node.orgCode == null
? null
: prop.node.orgCode
}}
{{
prop.node.orgTreeShortName == null
? null
: prop.node.orgTreeShortName
}}
</div>
</div>
</q-item>
</template>
</q-tree>
</q-card-section>
</q-expansion-item>
</div>
<div class="col-12"><q-separator /></div>
<div class="col-12 q-px-sm"> <div class="col-12 q-px-sm">
<q-select <q-select
class="bg-white" class="bg-white"
@ -719,7 +930,9 @@ onMounted(async () => {
hide-selected hide-selected
:model-value="posType == '' ? 'ทั้งหมด' : posType" :model-value="posType == '' ? 'ทั้งหมด' : posType"
:label="`${ :label="`${
employeeClass == 'officer' ? 'ประเภทตำแหน่ง' : 'กลุ่มงาน' employeeClass == 'officer'
? 'ประเภทตำแหน่ง'
: 'กลุ่มงาน'
}`" }`"
emit-value emit-value
map-options map-options
@ -736,7 +949,9 @@ onMounted(async () => {
<template v-if="posType" v-slot:append> <template v-if="posType" v-slot:append>
<q-icon <q-icon
name="cancel" name="cancel"
@click.stop.prevent="(posType = ''), (posLevel = '')" @click.stop.prevent="
(posType = ''), (posLevel = '')
"
class="cursor-pointer" class="cursor-pointer"
style="opacity: 0.6" style="opacity: 0.6"
/> />
@ -750,7 +965,7 @@ onMounted(async () => {
</template> </template>
</q-select> </q-select>
</div> </div>
<div class="col-12"> <q-separator /> </div> <div class="col-12"><q-separator /></div>
<div class="col-12 q-px-sm"> <div class="col-12 q-px-sm">
<q-select <q-select
class="bg-white" class="bg-white"
@ -796,12 +1011,16 @@ onMounted(async () => {
</template> </template>
</q-select> </q-select>
</div> </div>
<div class="col-12"> <q-separator /> </div> <div class="col-12"><q-separator /></div>
<div class="col-12 q-px-sm"> <div class="col-12 q-px-sm">
<q-select <q-select
dense dense
:model-value="position == '' ? 'ทั้งหมด' : position" :model-value="position == '' ? 'ทั้งหมด' : position"
label="ตำแหน่งในสายงาน" :label="`${
employeeClass == 'officer'
? 'ตำแหน่งในสายงาน'
: 'ตำแหน่ง'
}`"
emit-value emit-value
map-options map-options
fill-input fill-input
@ -834,12 +1053,19 @@ onMounted(async () => {
/> </template /> </template
></q-select> ></q-select>
</div> </div>
<div class="col-12"> <q-separator /> </div> <div class="col-12" v-if="employeeClass === 'officer'">
<div class="col-12 q-px-sm"> <q-separator />
</div>
<div
class="col-12 q-px-sm"
v-if="employeeClass === 'officer'"
>
<q-select <q-select
label="ตำแหน่งทางการบริหาร" label="ตำแหน่งทางการบริหาร"
:model-value=" :model-value="
positionExecutive == '' ? 'ทั้งหมด' : positionExecutive positionExecutive == ''
? 'ทั้งหมด'
: positionExecutive
" "
:options="executiveOps" :options="executiveOps"
emit-value emit-value
@ -872,7 +1098,7 @@ onMounted(async () => {
</template> </template>
</q-select> </q-select>
</div> </div>
<div class="col-12"> <q-separator /> </div> <div class="col-12"><q-separator /></div>
<div class="col-12 q-px-sm"> <div class="col-12 q-px-sm">
<q-select <q-select
label="เพศ" label="เพศ"
@ -908,7 +1134,7 @@ onMounted(async () => {
</template> </template>
</q-select> </q-select>
</div> </div>
<div class="col-12"> <q-separator /> </div> <div class="col-12"><q-separator /></div>
<div class="col-12 q-px-sm"> <div class="col-12 q-px-sm">
<q-select <q-select
label="สถานภาพ" label="สถานภาพ"
@ -944,9 +1170,25 @@ onMounted(async () => {
</template> </template>
</q-select> </q-select>
</div> </div>
<div class="col-12"> <q-separator /> </div> <div class="col-12"><q-separator /></div>
<div class="col-12 q-px-sm"> <div class="col-12 q-px-sm">
<q-select <q-input
dense
v-model="education"
borderless
label="วุฒิการศึกษา"
class="bg-white full-width"
>
<template v-if="education" v-slot:append>
<q-icon
name="cancel"
@click.stop.prevent="education = ''"
class="cursor-pointer"
style="opacity: 0.6"
/>
</template>
</q-input>
<!-- <q-select
label="วุฒิการศึกษา" label="วุฒิการศึกษา"
:model-value="education == '' ? 'ทั้งหมด' : education" :model-value="education == '' ? 'ทั้งหมด' : education"
:options="educationOp" :options="educationOp"
@ -978,11 +1220,11 @@ onMounted(async () => {
style="opacity: 0.6" style="opacity: 0.6"
/> />
</template> </template>
</q-select> </q-select> -->
</div> </div>
<div class="col-12"> <q-separator /> </div> <div class="col-12"><q-separator /></div>
<div class="col-12 q-pa-sm"> <div class="col-12 q-pa-sm">
<div class=" text-grey-8 text-caption">วงเวลาบรรจ</div> <div class="text-grey-8 text-caption">วงเวลาบรรจ</div>
<div class="col-12"> <div class="col-12">
<datepicker <datepicker
menu-class-name="modalfix" menu-class-name="modalfix"
@ -1000,7 +1242,6 @@ onMounted(async () => {
<template #trigger> <template #trigger>
<q-input <q-input
dense dense
:model-value=" :model-value="
dateStart === null ? '' : date2Thai(dateStart) dateStart === null ? '' : date2Thai(dateStart)
" "
@ -1049,7 +1290,6 @@ onMounted(async () => {
<q-input <q-input
dense dense
:readonly="!dateStart" :readonly="!dateStart"
:model-value=" :model-value="
dateEnd === null ? '' : date2Thai(dateEnd) dateEnd === null ? '' : date2Thai(dateEnd)
" "
@ -1070,12 +1310,11 @@ onMounted(async () => {
</datepicker> </datepicker>
</div> </div>
</div> </div>
<div class="col-12"> <q-separator /> </div> <div class="col-12"><q-separator /></div>
<div class="col-12 q-pa-sm"> <div class="col-12 q-pa-sm">
<div class="col-12 row"> <div class="col-12 row">
<div class=" text-grey-8 text-caption">วงอาย </div> <div class="text-grey-8 text-caption">วงอาย</div>
<q-space /> <q-space />
<!-- <div class="text-black">{{ rangeAge.min }} - {{ rangeAge.max }}</div> -->
</div> </div>
<div class="q-pa-sm row"> <div class="q-pa-sm row">
<q-range <q-range
@ -1090,25 +1329,53 @@ onMounted(async () => {
dense dense
><!-- :marker-labels="objMarkerLabel" --> ><!-- :marker-labels="objMarkerLabel" -->
</q-range> </q-range>
<div class="col-12 justify-around items-center row no-wrap q-pt-sm"> <div
<div><q-input type="number" style="max-width: 60px" v-model="rangeAge.min" dense standout="bg-teal text-white"/></div> class="col-12 justify-around items-center row no-wrap q-pt-sm"
<div class="q-px-sm text-grey-8">-</div> >
<div><q-input type="number" style="max-width: 60px" v-model="rangeAge.max" dense standout="bg-teal text-white"/></div> <div>
</div> <q-input
</div> readonly
</div> type="number"
<div class="col-12"> <q-separator /> </div> style="max-width: 60px"
v-model="rangeAge.min"
<div class="col-12 row q-pl-sm items-center no-wrap"> dense
<div class=" text-grey-8">ทดลองปฏราชการ</div> standout="bg-teal text-white"
<q-space />
<q-toggle
v-model="isProbation"
size="sm"
/> />
</div> </div>
<div class="q-px-sm text-grey-8">-</div>
<div>
<q-input
readonly
type="number"
style="max-width: 60px"
v-model="rangeAge.max"
dense
standout="bg-teal text-white"
/>
</div>
</div>
</div>
</div>
<div class="col-12"><q-separator /></div>
<div
class="col-12 row q-pl-sm items-center no-wrap"
v-if="employeeClass === 'officer'"
>
<div class="text-grey-8">ทดลองปฏราชการ</div>
<q-space />
<q-toggle v-model="isProbation" size="sm" />
</div>
<div class="col-12 row q-pl-sm items-center no-wrap">
<div class="text-grey-8">
แสดงผเกษยณอายราชการในปงบประมาณปจจ
</div>
<q-space />
<q-toggle v-model="isRetireLaw" size="sm" />
</div>
<div class="col-12 row q-pl-sm items-center"> <div class="col-12 row q-pl-sm items-center">
<div class=" text-grey-8">แสดงผนจากราชการ</div> <div class="text-grey-8">แสดงผนจากราชการ</div>
<q-space /> <q-space />
<q-toggle <q-toggle
v-model="isRetire" v-model="isRetire"
@ -1153,6 +1420,7 @@ onMounted(async () => {
</template> </template>
</q-select> </q-select>
</div> </div>
<div class="col-12"> <div class="col-12">
<!-- <q-btn-dropdown <!-- <q-btn-dropdown
:label=" :label="
@ -1194,35 +1462,45 @@ onMounted(async () => {
</q-btn-dropdown> --> </q-btn-dropdown> -->
</div> </div>
</div> </div>
<div class="col-12"> <q-separator /> </div> <div class="col-12"><q-separator /></div>
<div class="col-12 row q-pa-sm"> <div class="col-12 row q-pa-sm">
<q-space /> <q-space />
<q-btn dense class="q-px-md" label="ค้นหา" unelevated color="public" type="submit"> <q-btn
dense
class="q-px-md"
label="ค้นหา"
unelevated
color="public"
type="submit"
>
</q-btn> </q-btn>
</div> </div>
</div> </div>
</q-card> </q-card>
</div> </div>
<div class="col-lg-10 col-md-9 col-sm-9 col-xs-12 col-xs-12 flex "> <div class="col-lg-9 col-md-9 col-sm-9 col-xs-12 col-xs-12 flex">
<q-card bordered class="col-12 "> <q-card bordered class="col-12">
<div class="row col-12 q-pa-sm items-center" > <div class="row col-12 q-pa-sm items-center">
<div <div class="row items-center q-pa-sm no-wrap">
class="row items-center q-pa-sm no-wrap bg-grey-1" <div class="q-pr-md">จำนวนทพบทงหมด</div>
style="border: #c8d3db solid 1px; border-radius: 3px"
>
<div class="text-weight-medium q-pr-md">จำนวนทพบทงหมด</div>
<q-space /> <q-space />
<q-badge color="primary" class="q-pa-xs"> <q-badge
class="q-pa-xs text-primary text-bold text-subtitle2"
color="white"
>
{{ total.toLocaleString() }} {{ total.toLocaleString() }}
</q-badge> </q-badge>
</div> </div>
<q-space /> <q-space />
<div class="text-weight-medium q-pr-sm">เรยงตามวนทบรรจเเตงต :</div> <div class="text-weight-medium q-pr-sm">
เรยงตามวนทบรรจเเตงต :
</div>
<q-btn-dropdown <q-btn-dropdown
:label=" :label="
sortBy sortBy
? sortBy == 'DESC' ? sortBy == 'ASC'
? `(เก่า-ล่าสุด)` ? `(เก่า-ล่าสุด)`
: `(ล่าสุด-เก่า)` : `(ล่าสุด-เก่า)`
: 'ลำดับการเเสดงผล' : 'ลำดับการเเสดงผล'
@ -1235,19 +1513,31 @@ onMounted(async () => {
rounded rounded
> >
<q-list> <q-list>
<q-item clickable v-close-popup @click="sortBy = 'ASC'"> <q-item
<q-item-section> clickable
<q-item-label v-close-popup
>(าส-เก)</q-item-label @click="
(sortBy = 'DESC'),
(pagination.sortBy = 'dateAppoint'),
(pagination.descending = true)
"
> >
<q-item-section>
<q-item-label>(าส-เก)</q-item-label>
</q-item-section> </q-item-section>
</q-item> </q-item>
<q-item clickable v-close-popup @click="sortBy = 'DESC'"> <q-item
<q-item-section> clickable
<q-item-label v-close-popup
>(เก-าส)</q-item-label @click="
(sortBy = 'ASC'),
(pagination.sortBy = 'dateAppoint'),
(pagination.descending = false)
"
> >
<q-item-section>
<q-item-label>(เก-าส)</q-item-label>
</q-item-section> </q-item-section>
</q-item> </q-item>
</q-list> </q-list>
@ -1259,11 +1549,15 @@ onMounted(async () => {
row-key="id" row-key="id"
:visible-columns="visibleColumns" :visible-columns="visibleColumns"
v-model:pagination="pagination" v-model:pagination="pagination"
:rows-per-page-options="[10, 25, 50, 100]" :rows-per-page-options="[25, 50, 100]"
> >
<template v-slot:header="props"> <template v-slot:header="props">
<q-tr :props="props"> <q-tr :props="props">
<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">{{ col.label }}</span> <span class="text-weight-medium">{{ col.label }}</span>
</q-th> </q-th>
</q-tr> </q-tr>
@ -1274,7 +1568,29 @@ onMounted(async () => {
<div v-if="col.name === 'no'"> <div v-if="col.name === 'no'">
{{ props.rowIndex + 1 }} {{ props.rowIndex + 1 }}
</div> </div>
<div v-else class="table_ellipsis"> <div v-else-if="col.name === 'fullName'">
{{ col.value }}
<q-btn
size="sm"
v-if="checkPermission($route)?.attrIsGet"
flat
dense
icon="info"
color="info"
@click.pervent="
onViewInfo(props.row.profileId, props.row.empType)
"
>
<q-tooltip>ทะเบยนประว</q-tooltip>
</q-btn>
</div>
<div
v-else-if="col.name === 'org'"
class="table_ellipsis"
>
{{ col.value ? col.value : "-" }}
</div>
<div v-else>
{{ col.value ? col.value : "-" }} {{ col.value ? col.value : "-" }}
</div> </div>
</q-td> </q-td>
@ -1290,6 +1606,13 @@ onMounted(async () => {
</div> </div>
<DialogOrg v-model:modal="modalOrg" v-model:name="org" /> <DialogOrg v-model:modal="modalOrg" v-model:name="org" />
<PopupPersonal
:modal="modalPersonal"
:id="personId"
@update:modal="updatemodalPersonal"
:type="empType"
/>
</template> </template>
<style lang="scss" scope> <style lang="scss" scope>
@ -1303,9 +1626,7 @@ onMounted(async () => {
.tree-container { .tree-container {
overflow: auto; overflow: auto;
height: 60vh; height: 50vh;
border: 1px solid #e6e6e7;
border-radius: 10px;
} }
.my-list-link { .my-list-link {
color: rgb(118, 168, 222); color: rgb(118, 168, 222);
@ -1314,4 +1635,15 @@ onMounted(async () => {
font-weight: 600; font-weight: 600;
border: 1px solid rgba(175, 185, 196, 0.217); border: 1px solid rgba(175, 185, 196, 0.217);
} }
.expansion-item {
.q-item__section--side {
padding-right: 3px;
}
.q-item--dense {
min-height: 32px;
padding: 2px 9px;
}
}
</style> </style>