Merge branch 'develop' into devTee

This commit is contained in:
setthawutttty 2024-02-13 16:56:29 +07:00
commit ea91acf18a
16 changed files with 1113 additions and 413 deletions

View file

@ -18,67 +18,137 @@
class="q-py-xs col-6 row" class="q-py-xs col-6 row"
/> />
</q-tabs> </q-tabs>
<q-table <q-separator />
ref="table"
flat <q-tab-panels v-model="currentTab" animated>
bordered <q-tab-panel name="normal">
class="custom-header-table" <q-table
virtual-scroll ref="table"
:rows="calendarData" flat
:columns="columns" bordered
dense class="custom-header-table"
:rows-per-page-options="[0]" virtual-scroll
hide-header :rows="calendarData"
> :columns="columns"
<template v-slot:body="props"> dense
<q-tr :props="props"> :rows-per-page-options="[0]"
<q-td v-for="col in props.cols" :key="col.name" :props="props"> hide-header
<div v-if="col.name == 'week'" class=""> >
{{ dayThaiRange(props.row.dateRange) }} <template v-slot:body="props">
</div> <q-tr :props="props">
<div v-else-if="col.name == 'holidayDate'" class=""> <q-td v-for="col in props.cols" :key="col.name" :props="props">
{{ dateThaiRange(props.row.dateRange) }} <div v-if="col.name == 'week'" class="">
</div> {{ dayThaiRange(props.row.dateRange) }}
<div v-else class="my-table-details"> </div>
{{ col.value }} <div v-else-if="col.name == 'holidayDate'" class="">
</div> {{ dateThaiRange(props.row.dateRange) }}
</q-td> </div>
<q-td auto-width> <div v-else class="my-table-details">
<q-btn {{ col.value }}
flat </div>
round </q-td>
color="grey" <q-td auto-width>
@click.stop <q-btn
size="10px" flat
icon="more_vert" round
> color="grey"
<q-menu> @click.stop
<q-list> size="10px"
<q-item icon="more_vert"
clickable >
v-close-popup <q-menu>
@click="editCalendar(props.row)" <q-list>
> <q-item
<q-item-section> clickable
<q-item-label>แกไขวนหย</q-item-label> v-close-popup
</q-item-section> @click="editCalendar(props.row)"
</q-item> >
<q-item <q-item-section>
clickable <q-item-label>แกไขวนหย</q-item-label>
v-close-popup </q-item-section>
@click="deleteClick(props.row)" </q-item>
> <q-item
<q-item-section> clickable
<q-item-label>ลบวนหย</q-item-label> v-close-popup
</q-item-section> @click="deleteClick(props.row)"
</q-item> >
</q-list> <q-item-section>
</q-menu> <q-item-label>ลบวนหย</q-item-label>
</q-btn> </q-item-section>
</q-td> </q-item>
</q-tr> </q-list>
</template> </q-menu>
</q-table> </q-btn>
</q-td>
</q-tr>
</template>
</q-table>
</q-tab-panel>
<q-tab-panel name="6day">
<q-table
ref="table"
flat
bordered
class="custom-header-table"
virtual-scroll
:rows="calendarData"
:columns="columns"
dense
:rows-per-page-options="[0]"
hide-header
>
<template v-slot:body="props">
<q-tr :props="props">
<q-td v-for="col in props.cols" :key="col.name" :props="props">
<div v-if="col.name == 'week'" class="">
{{ dayThaiRange(props.row.dateRange) }}
</div>
<div v-else-if="col.name == 'holidayDate'" class="">
{{ dateThaiRange(props.row.dateRange) }}
</div>
<div v-else class="my-table-details">
{{ col.value }}
</div>
</q-td>
<q-td auto-width>
<q-btn
flat
round
color="grey"
@click.stop
size="10px"
icon="more_vert"
>
<q-menu>
<q-list>
<q-item
clickable
v-close-popup
@click="editCalendar(props.row)"
>
<q-item-section>
<q-item-label>แกไขวนหย</q-item-label>
</q-item-section>
</q-item>
<q-item
clickable
v-close-popup
@click="deleteClick(props.row)"
>
<q-item-section>
<q-item-label>ลบวนหย</q-item-label>
</q-item-section>
</q-item>
</q-list>
</q-menu>
</q-btn>
</q-td>
</q-tr>
</template>
</q-table>
</q-tab-panel>
</q-tab-panels>
</q-card> </q-card>
<!-- modal เพมวนหย --> <!-- modal เพมวนหย -->

View file

@ -50,17 +50,32 @@ onMounted(() => {
class="q-py-xs" class="q-py-xs"
/> />
</q-tabs> </q-tabs>
<q-separator size="2px" /> <q-separator />
<!-- person --> <!-- person -->
<div class="q-pa-md">
<ListPrefix v-if="currentTab == 'list_prefix'" /> <q-tab-panels v-model="currentTab" animated>
<ListRank v-if="currentTab == 'list_rank'" /> <q-tab-panel name="list_prefix">
<ListBloodGroup v-if="currentTab == 'list_bloodGroup'" /> <ListPrefix v-if="currentTab == 'list_prefix'" />
<ListGender v-if="currentTab == 'list_gender'" /> </q-tab-panel>
<ListReligion v-if="currentTab == 'list_religion'" /> <q-tab-panel name="list_rank">
<ListRelationship v-if="currentTab == 'list_relationship'" /> <ListRank v-if="currentTab == 'list_rank'" />
<ListEducation v-if="currentTab == 'list_education'" /> </q-tab-panel>
</div> <q-tab-panel name="list_bloodGroup">
<ListBloodGroup v-if="currentTab == 'list_bloodGroup'" />
</q-tab-panel>
<q-tab-panel name="list_gender">
<ListGender v-if="currentTab == 'list_gender'" />
</q-tab-panel>
<q-tab-panel name="list_religion">
<ListReligion v-if="currentTab == 'list_religion'" />
</q-tab-panel>
<q-tab-panel name="list_relationship">
<ListRelationship v-if="currentTab == 'list_relationship'" />
</q-tab-panel>
<q-tab-panel name="list_education">
<ListEducation v-if="currentTab == 'list_education'" />
</q-tab-panel>
</q-tab-panels>
</div> </div>
</q-card> </q-card>
</template> </template>

View file

@ -41,12 +41,21 @@ onMounted(() => {
class="q-py-xs" class="q-py-xs"
/> />
</q-tabs> </q-tabs>
<q-separator size="2px" /> <q-separator />
<div class="q-pa-md">
<ListPosition v-if="store.pathLocation == 'list_position'" /> <q-tab-panels v-model="store.pathLocation" animated>
<ListType v-if="store.pathLocation == 'list_type'" /> <q-tab-panel name="list_position">
<ListExecutive v-if="store.pathLocation == 'list_executive'" /> <ListPosition v-if="store.pathLocation == 'list_position'" />
</div> </q-tab-panel>
<q-tab-panel name="list_type">
<ListType v-if="store.pathLocation == 'list_type'" />
</q-tab-panel>
<q-tab-panel name="list_executive">
<ListExecutive v-if="store.pathLocation == 'list_executive'" />
</q-tab-panel>
</q-tab-panels>
</q-card> </q-card>
</template> </template>

View file

@ -43,81 +43,81 @@ const formData = reactive<FormDetailPosition>({
status: "", //* status: "", //*
}); });
const columns = ref<QTableProps["columns"]>([ // const columns = ref<QTableProps["columns"]>([
{ // {
name: "no", // name: "no",
align: "left", // align: "left",
label: "ลำดับ", // label: "",
sortable: false, // sortable: false,
field: "no", // field: "no",
headerStyle: "font-size: 14px", // headerStyle: "font-size: 14px",
style: "font-size: 14px", // style: "font-size: 14px",
}, // },
{ // {
name: "positionName", // name: "positionName",
align: "left", // align: "left",
label: "ตำแหน่งในสายงาน", // label: "",
sortable: true, // sortable: true,
field: "positionName", // field: "positionName",
headerStyle: "font-size: 14px", // headerStyle: "font-size: 14px",
style: "font-size: 14px", // style: "font-size: 14px",
}, // },
{ // {
name: "positionField", // name: "positionField",
align: "left", // align: "left",
label: "สายงาน", // label: "",
sortable: true, // sortable: true,
field: "positionField", // field: "positionField",
headerStyle: "font-size: 14px", // headerStyle: "font-size: 14px",
style: "font-size: 14px", // style: "font-size: 14px",
}, // },
{ // {
name: "posTypeName", // name: "posTypeName",
align: "left", // align: "left",
label: "ประเภทตำเเหน่ง", // label: "",
sortable: true, // sortable: true,
field: "posTypeName", // field: "posTypeName",
headerStyle: "font-size: 14px", // headerStyle: "font-size: 14px",
style: "font-size: 14px", // style: "font-size: 14px",
}, // },
{ // {
name: "posLevelName", // name: "posLevelName",
align: "left", // align: "left",
label: "ระดับตำแหน่ง", // label: "",
sortable: true, // sortable: true,
field: "posLevelName", // field: "posLevelName",
headerStyle: "font-size: 14px", // headerStyle: "font-size: 14px",
style: "font-size: 14px", // style: "font-size: 14px",
}, // },
{ // {
name: "posExecutiveName", // name: "posExecutiveName",
align: "left", // align: "left",
label: "ตำแหน่งทางการบริหาร", // label: "",
sortable: true, // sortable: true,
field: "posExecutiveName", // field: "posExecutiveName",
headerStyle: "font-size: 14px", // headerStyle: "font-size: 14px",
style: "font-size: 14px", // style: "font-size: 14px",
}, // },
{ // {
name: "positionExecutiveField", // name: "positionExecutiveField",
align: "left", // align: "left",
label: "ด้านทางการบริหาร", // label: "",
sortable: true, // sortable: true,
field: "positionExecutiveField", // field: "positionExecutiveField",
headerStyle: "font-size: 14px", // headerStyle: "font-size: 14px",
style: "font-size: 14px", // style: "font-size: 14px",
}, // },
{ // {
name: "positionArea", // name: "positionArea",
align: "left", // align: "left",
label: "ด้าน/สาขา", // label: "/",
sortable: true, // sortable: true,
field: "positionArea", // field: "positionArea",
headerStyle: "font-size: 14px", // headerStyle: "font-size: 14px",
style: "font-size: 14px", // style: "font-size: 14px",
}, // },
]); // ]);
const row = ref<Position[]>([]); // const row = ref<Position[]>([]);
/** function ปิด popup*/ /** function ปิด popup*/
function close() { function close() {
@ -137,18 +137,26 @@ watch(
: store.typeOrganizational === "draft" : store.typeOrganizational === "draft"
? "แบบร่าง" ? "แบบร่าง"
: "ยุบเลิก"; : "ยุบเลิก";
row.value = prosp.dataDetailPos.positions.map((e: Position) => ({ formData.positionType = prosp.dataDetailPos.posTypeName
...e, formData.positionPathSide = prosp.dataDetailPos.positionName
positionName: e.positionName ? e.positionName : "-", formData.positionLine = prosp.dataDetailPos.positionField
positionField: e.positionField ? e.positionField : "-", formData.positionSide = prosp.dataDetailPos.positionArea ? prosp.dataDetailPos.positionArea : "-"
posTypeName: e.posTypeName ? e.posTypeName : "-", formData.positionLevel = prosp.dataDetailPos.posLevelName
posLevelName: e.posLevelName ? e.posLevelName : "-", formData.positionExecutive = prosp.dataDetailPos.posExecutiveName ? prosp.dataDetailPos.posExecutiveName : "-"
posExecutiveName: e.posExecutiveName ? e.posExecutiveName : "-", formData.positionExecutiveSide = prosp.dataDetailPos.positionExecutiveField ? prosp.dataDetailPos.positionExecutiveField : "-"
positionExecutiveField: e.positionExecutiveField
? e.positionExecutiveField // row.value = prosp.dataDetailPos.positions.map((e: Position) => ({
: "-", // ...e,
positionArea: e.positionArea ? e.positionArea : "-", // positionName: e.positionName ? e.positionName : "-",
})); // positionField: e.positionField ? e.positionField : "-",
// posTypeName: e.posTypeName ? e.posTypeName : "-",
// posLevelName: e.posLevelName ? e.posLevelName : "-",
// posExecutiveName: e.posExecutiveName ? e.posExecutiveName : "-",
// positionExecutiveField: e.positionExecutiveField
// ? e.positionExecutiveField
// : "-",
// positionArea: e.positionArea ? e.positionArea : "-",
// }));
} }
} }
} }
@ -172,7 +180,6 @@ watch(
<p>{{ formData.positionNo }}</p> <p>{{ formData.positionNo }}</p>
</div> </div>
</div> </div>
<!--
<div class="row q-col-gutter-sm q-mb-xs"> <div class="row q-col-gutter-sm q-mb-xs">
<div class="col-4 text-bold"> <div class="col-4 text-bold">
<div> <div>
@ -182,9 +189,9 @@ watch(
<div class="col-8 text-grey-8"> <div class="col-8 text-grey-8">
<p>{{ formData.positionType }}</p> <p>{{ formData.positionType }}</p>
</div> </div>
</div> --> </div>
<!-- <div class="row q-col-gutter-sm q-mb-xs"> <div class="row q-col-gutter-sm q-mb-xs">
<div class="col-4 text-bold"> <div class="col-4 text-bold">
<div> <div>
<p>ตำแหนงในสายงาน</p> <p>ตำแหนงในสายงาน</p>
@ -193,9 +200,9 @@ watch(
<div class="col-8 text-grey-8"> <div class="col-8 text-grey-8">
<p>{{ formData.positionPathSide }}</p> <p>{{ formData.positionPathSide }}</p>
</div> </div>
</div> --> </div>
<!-- <div class="row q-col-gutter-sm q-mb-xs"> <div class="row q-col-gutter-sm q-mb-xs">
<div class="col-4 text-bold"> <div class="col-4 text-bold">
<div> <div>
<p>สายงาน</p> <p>สายงาน</p>
@ -204,9 +211,9 @@ watch(
<div class="col-8 text-grey-8"> <div class="col-8 text-grey-8">
<p>{{ formData.positionLine }}</p> <p>{{ formData.positionLine }}</p>
</div> </div>
</div> --> </div>
<!-- <div class="row q-col-gutter-sm q-mb-xs"> <div class="row q-col-gutter-sm q-mb-xs">
<div class="col-4 text-bold"> <div class="col-4 text-bold">
<div> <div>
<p>าน/สาขา</p> <p>าน/สาขา</p>
@ -215,9 +222,9 @@ watch(
<div class="col-8 text-grey-8"> <div class="col-8 text-grey-8">
<p>{{ formData.positionSide }}</p> <p>{{ formData.positionSide }}</p>
</div> </div>
</div> --> </div>
<!-- <div class="row q-col-gutter-sm q-mb-xs"> <div class="row q-col-gutter-sm q-mb-xs">
<div class="col-4 text-bold"> <div class="col-4 text-bold">
<div> <div>
<p>ระดบตำแหน</p> <p>ระดบตำแหน</p>
@ -226,9 +233,9 @@ watch(
<div class="col-8 text-grey-8"> <div class="col-8 text-grey-8">
<p>{{ formData.positionLevel }}</p> <p>{{ formData.positionLevel }}</p>
</div> </div>
</div> --> </div>
<!-- <div class="row q-col-gutter-sm q-mb-xs"> <div class="row q-col-gutter-sm q-mb-xs">
<div class="col-4 text-bold"> <div class="col-4 text-bold">
<div> <div>
<p>ตำแหนงทางการบรหาร</p> <p>ตำแหนงทางการบรหาร</p>
@ -237,9 +244,9 @@ watch(
<div class="col-8 text-grey-8"> <div class="col-8 text-grey-8">
<p>{{ formData.positionExecutive }}</p> <p>{{ formData.positionExecutive }}</p>
</div> </div>
</div> --> </div>
<!-- <div class="row q-col-gutter-sm q-mb-xs"> <div class="row q-col-gutter-sm q-mb-xs">
<div class="col-4 text-bold"> <div class="col-4 text-bold">
<div> <div>
<p>านทางการบรหาร</p> <p>านทางการบรหาร</p>
@ -248,7 +255,7 @@ watch(
<div class="col-8 text-grey-8"> <div class="col-8 text-grey-8">
<p>{{ formData.positionExecutiveSide }}</p> <p>{{ formData.positionExecutiveSide }}</p>
</div> </div>
</div> --> </div>
<div class="row q-col-gutter-sm q-mb-xs"> <div class="row q-col-gutter-sm q-mb-xs">
<div class="col-4 text-bold"> <div class="col-4 text-bold">
@ -261,7 +268,7 @@ watch(
</div> </div>
</div> </div>
<div class="row q-col-gutter-sm q-mb-xs"> <!-- <div class="row q-col-gutter-sm q-mb-xs">
<div class="col-12"> <div class="col-12">
<d-table <d-table
flat flat
@ -302,7 +309,7 @@ watch(
</template> </template>
</d-table> </d-table>
</div> </div>
</div> </div> -->
</div> </div>
</q-card-section> </q-card-section>
</q-card> </q-card>

View file

@ -34,6 +34,8 @@ const nodeTree = ref<OrgTree[]>(); // ข้อมูล Tree
const nodeId = ref<string>(""); // id Tree const nodeId = ref<string>(""); // id Tree
const orgLevel = ref<number>(0); // levelTree const orgLevel = ref<number>(0); // levelTree
const isLoad = ref<boolean>(false); // loadTable const isLoad = ref<boolean>(false); // loadTable
const isLoadTree = ref<boolean>(false); // loadTable
const selected = ref<string>(""); const selected = ref<string>("");
const reqMaster = reactive<FilterMaster>({ const reqMaster = reactive<FilterMaster>({
@ -53,6 +55,7 @@ const posMaster = ref<PosMaster2[]>([]);
* @param id id โครงสราง * @param id id โครงสราง
*/ */
async function fetchDataTree(id: string) { async function fetchDataTree(id: string) {
isLoadTree.value = false;
showLoader(); showLoader();
await http await http
.get(config.API.orgByid(id.toString())) .get(config.API.orgByid(id.toString()))
@ -121,6 +124,32 @@ async function fetchDataTable(id: string, level: number, action: boolean) {
}); });
} }
/** ดึงข้อมูลสถิติจำนวนด้านบน*/
function getSummary() {
http
.post(config.API.orgSummary, {
id: reqMaster.id, //*Id node
type: reqMaster.type, //*node
isNode: reqMaster.isAll, //* node
})
.then(async (res: any) => {
const data = await res.data.result;
store.getSumPosition({
totalPosition: data.totalPosition,
totalPositionCurrentUse: data.totalPositionCurrentUse,
totalPositionCurrentVacant: data.totalPositionCurrentVacant,
totalPositionNextUse: data.totalPositionNextUse,
totalPositionNextVacant: data.totalPositionNextVacant,
totalRootPosition: data.totalPosition,
totalRootPositionCurrentUse: data.totalPositionCurrentUse,
totalRootPositionCurrentVacant: data.totalPositionCurrentVacant,
totalRootPositionNextUse: data.totalPositionNextUse,
totalRootPositionNextVacant: data.totalPositionNextVacant,
});
});
}
/** funcion ค้นหาข้อมูลใน Table*/ /** funcion ค้นหาข้อมูลใน Table*/
async function filterKeyword() { async function filterKeyword() {
reqMaster.page = 1; reqMaster.page = 1;
@ -168,6 +197,7 @@ watch([() => reqMaster.page, () => reqMaster.pageSize], () => {
watch( watch(
() => reqMaster.isAll, () => reqMaster.isAll,
() => { () => {
getSummary();
if (reqMaster.page !== 1) { if (reqMaster.page !== 1) {
reqMaster.page = 1; reqMaster.page = 1;
} else { } else {
@ -185,7 +215,6 @@ watch(
<TreeView <TreeView
v-model:nodeTree="nodeTree" v-model:nodeTree="nodeTree"
v-model:nodeId="nodeId" v-model:nodeId="nodeId"
v-model:selected="selected"
:fetchDataTree="fetchDataTree" :fetchDataTree="fetchDataTree"
:fetchDataTable="fetchDataTable" :fetchDataTable="fetchDataTable"
/> />

View file

@ -28,7 +28,6 @@ const { dialogRemove, showLoader, hideLoader, messageError, success } =
/** props*/ /** props*/
const nodeTEST = defineModel<OrgTree[]>("nodeTree", { default: [] }); const nodeTEST = defineModel<OrgTree[]>("nodeTree", { default: [] });
const nodeId = defineModel<string>("nodeId", { required: true }); const nodeId = defineModel<string>("nodeId", { required: true });
const selected = defineModel<string>("selected", { required: true });
const props = defineProps({ const props = defineProps({
fetchDataTree: { fetchDataTree: {
type: Function, type: Function,
@ -97,39 +96,39 @@ const orgId = ref<string>("");
* @param data อม Tree * @param data อม Tree
*/ */
function updateSelected(data: DataTree) { function updateSelected(data: DataTree) {
store.treeId = data.orgTreeId; if (!store.treeId || store.treeId != data.orgTreeId) {
store.level = data.orgLevel; store.treeId = data.orgTreeId;
// if (data.orgTreeId === nodeId.value) { store.level = data.orgLevel;
// nodeId.value = "";
// } else {
nodeId.value = data.orgTreeId ? data.orgTreeId : "111";
data.orgTreeId && props.fetchDataTable?.(data.orgTreeId, data.orgLevel, true); nodeId.value = data.orgTreeId ? data.orgTreeId : "111";
/** ดึงข้อมูลสถิติจำนวนด้านบน*/
http data.orgTreeId &&
.post(config.API.orgSummary, { props.fetchDataTable?.(data.orgTreeId, data.orgLevel, true);
id: data.orgTreeId, //*Id node /** ดึงข้อมูลสถิติจำนวนด้านบน*/
type: data.orgLevel, //*node http
isNode: false, //* node .post(config.API.orgSummary, {
}) id: data.orgTreeId, //*Id node
.then(async (res: any) => { type: data.orgLevel, //*node
const data = await res.data.result; isNode: false, //* node
if (data) { })
store.getSumPosition({ .then(async (res: any) => {
totalPosition: data.totalPosition, const data = await res.data.result;
totalPositionCurrentUse: data.totalPositionCurrentUse, if (data) {
totalPositionCurrentVacant: data.totalPositionCurrentVacant, store.getSumPosition({
totalPositionNextUse: data.totalPositionNextUse, totalPosition: data.totalPosition,
totalPositionNextVacant: data.totalPositionNextVacant, totalPositionCurrentUse: data.totalPositionCurrentUse,
totalRootPosition: data.totalPosition, totalPositionCurrentVacant: data.totalPositionCurrentVacant,
totalRootPositionCurrentUse: data.totalPositionCurrentUse, totalPositionNextUse: data.totalPositionNextUse,
totalRootPositionCurrentVacant: data.totalPositionCurrentVacant, totalPositionNextVacant: data.totalPositionNextVacant,
totalRootPositionNextUse: data.totalPositionNextUse, totalRootPosition: data.totalPosition,
totalRootPositionNextVacant: data.totalPositionNextVacant, totalRootPositionCurrentUse: data.totalPositionCurrentUse,
}); totalRootPositionCurrentVacant: data.totalPositionCurrentVacant,
} totalRootPositionNextUse: data.totalPositionNextUse,
}); totalRootPositionNextVacant: data.totalPositionNextVacant,
// } });
}
});
}
} }
const breakLoop = ref<boolean>(false); const breakLoop = ref<boolean>(false);
@ -366,8 +365,6 @@ watch(
nodes.value = nodeTEST.value; nodes.value = nodeTEST.value;
} }
); );
const modaeMenu = ref<boolean>(false);
</script> </script>
<template> <template>

View file

@ -1,6 +1,240 @@
<script setup lang="ts"></script> <script setup lang="ts">
import { defineAsyncComponent } from "@vue/runtime-core";
import { ref, onMounted } from "vue";
import { useQuasar } from "quasar";
import http from "@/plugins/http";
import config from "@/app.config";
import { StructChart } from "structure-chart";
import "structure-chart/structure-chart.css";
import { useCounterMixin } from "@/stores/mixin";
const mixin = useCounterMixin();
const { showLoader, hideLoader, messageError } = mixin;
const $q = useQuasar(); // show dialog
// import chartData from '@/assets/structChartData'
// const dataSource = ref(chartData)
const dataSource = ref(); // Chart
const rootOrgID = ref(); // org id root
const dataSourceLock = ref(); // Chart home
const chartRef = ref(); // chart
const savePNG = () => {
chartRef.value.savePNG();
};
const savePDF = () => {
chartRef.value.savePDF();
};
const loader = ref<boolean>(false); // Loader
onMounted(async () => {
await fetchTreeRoot();
await fetchStructChart();
});
/**
* าน Root ของขอมลทงหมดจาก API องทำเปนอนดบแรก เพอจะไดรากของขอม
*/
const fetchTreeRoot = async () => {
showLoader();
let urlRequest = config.API.chartGetTreeRoot;
await http
.get(urlRequest)
.then((response) => {
if (response.data.result.length > 0) {
rootOrgID.value = response.data.result[0].organizationId;
}
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
hideLoader();
});
};
/**
* านขอม organization id จจนจาก API อมลทไดเอามาสราง Structure Chart
*/
const fetchStructChart = async () => {
showLoader();
let urlRequest = config.API.chartGetStructure(rootOrgID.value);
await http
.get(urlRequest)
.then((response) => {
if (response.data.result.length > 0) {
dataSource.value = response.data.result[0];
if (dataSourceLock.value === undefined)
dataSourceLock.value = dataSource.value;
breadcrumbsGen();
}
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
hideLoader();
});
};
/**
* เมอมการคลกท Chart ใหาน ID ของหนวยงานทกคล แลวดงขอม Chart ของหนวยงานน จาก API
* @param data
*/
const refreshChart = async (data: any) => {
if (data.value !== undefined) rootOrgID.value = data.value;
else rootOrgID.value = data;
if (rootOrgID.value !== 0) await fetchStructChart();
if (data.value !== undefined) data.value = 0;
};
/**
* === กระบวนการสราง Path ===
*/
/**
* Recursive เพอหา Path ใชคล
* @param id OrgID ของหนวยงานทองการหา
* @param chart Array ของ Object ของหนวยงานยอยใน Tree
*/
const chartTraverse = (id: any, chart: any): any => {
let _returnPath = [];
for (const child of chart) {
if (child.deptID === id) {
_returnPath.push({
label: child.departmentName,
id: child.deptID,
});
return _returnPath;
} else {
if (
typeof child.children !== "undefined" &&
child.children !== null &&
child.children.length > 0
) {
let _result = chartTraverse(id, child.children);
if (typeof _result !== "undefined" && _result !== null) {
_returnPath.push({
label: child.departmentName,
id: child.deptID,
});
return [..._returnPath, ...(_result ?? [])];
}
}
}
}
};
const findPath = (id: any) => {
let _path = [];
_path.push({
label: dataSourceLock.value.departmentName,
id: dataSourceLock.value.deptID,
});
if (dataSourceLock.value.deptID === id) return _path;
if (dataSourceLock.value.children.length > 0) {
let _returnPath = chartTraverse(id, dataSourceLock.value.children);
return [..._path, ...(_returnPath ?? [])];
}
};
const theBreadcrumb = ref();
/**
* สราง Path Breadcrumbs
*/
const breadcrumbsGen = () => {
if (rootOrgID.value !== 0) {
theBreadcrumb.value = [];
const newPath = findPath(rootOrgID.value);
theBreadcrumb.value = newPath;
}
};
</script>
<template> <template>
<div>Structure View</div> <div class="toptitle text-dark col-12 row items-center">แผนภโครงสราง</div>
<div class="text-dark">
<q-card flat bordered class="col-12 q-mt-sm">
<div class="q-pa-sm row wrap items-center">
<q-btn flat round color="primary" @click="savePNG()" icon="mdi-image">
<q-tooltip> ดาวนโหลด PNG </q-tooltip>
</q-btn>
<q-btn
flat
round
color="red-7"
@click="savePDF()"
icon="mdi-file-pdf-box"
>
<q-tooltip> ดาวนโหลด PDF </q-tooltip>
</q-btn>
<div class="bg-grey-2 q-py-xs q-px-sm rounded-borders">
<q-breadcrumbs>
<template v-slot:separator>
<q-icon size="1.5em" name="chevron_right" color="primary" />
</template>
<template v-for="link in theBreadcrumb" :key="link.id">
<q-breadcrumbs-el
:label="link.label"
@click="refreshChart(link.id)"
class="breadcrumbs-link"
/>
</template>
</q-breadcrumbs>
</div>
</div>
<q-separator />
<div style="overflow-x: auto; overflow-y: auto" class="q-pt-md">
<StructChart
style="height: 70vh"
ref="chartRef"
class="struct"
:dataSource="dataSource"
@onElementClick="refreshChart"
/>
</div>
</q-card>
</div>
<full-loader :visibility="loader"></full-loader>
</template> </template>
<style scoped></style> <style>
.breadcrumbs-link {
cursor: pointer;
}
.struct .section-primary .header,
.struct .section-secondary .header,
.struct .section-tertiary .header {
font-size: 1rem !important;
}
.struct .section-primary .column-side .side-button,
.struct .section-secondary .column-side .side-button,
.struct .section-list .column-side .side-button {
background-color: #d9d9d96b !important;
color: #545459 !important;
width: 25px !important;
height: 25px !important;
font-size: 11px !important;
padding: 0px;
}
.struct .section-primary,
.section-secondary,
.struct .section-list {
padding: 6px 15px 6px 15px;
}
.struct .section-primary .header {
font-weight: 600 !important;
}
.struct .section-secondary .header {
font-weight: 400 !important;
}
.struct .subchild-more {
background-position: center !important;
background-size: 14px !important;
}
</style>

View file

@ -89,12 +89,6 @@ const listMenu = ref<ListMenu[]>([
type: "HISTORY", type: "HISTORY",
color: "deep-purple", color: "deep-purple",
}, },
{
label: "ดูรายละเอียด",
icon: "mdi-eye",
type: "VIEWDETIAL",
color: "blue",
},
]); ]);
const document = ref<any>([ const document = ref<any>([
{ {
@ -612,16 +606,12 @@ async function onClickDownloadReport(val: string) {
<q-item <q-item
v-for="(item, index) in store.typeOrganizational === 'draft' v-for="(item, index) in store.typeOrganizational === 'draft'
? listMenu ? listMenu
: listMenu.filter( : listMenu.filter((e) => e.type === 'HISTORY')"
(e) => e.type === 'HISTORY' || e.type === 'VIEWDETIAL'
)"
:key="index" :key="index"
clickable clickable
v-close-popup v-close-popup
@click=" @click="
item.type === 'VIEWDETIAL' item.type === 'EDIT'
? onClickViewDetail(props.row)
: item.type === 'EDIT'
? onClickPosition('EDIT', props.row.id) ? onClickPosition('EDIT', props.row.id)
: item.type === 'DEL' : item.type === 'DEL'
? onClickDelete(props.row.id) ? onClickDelete(props.row.id)
@ -645,6 +635,19 @@ async function onClickDownloadReport(val: string) {
</div> </div>
</q-item-section> </q-item-section>
</q-item> </q-item>
<q-item
v-if="props.row.positionIsSelected != 'ว่าง'"
clickable
v-close-popup
@click="onClickViewDetail(props.row)"
>
<q-item-section>
<div class="row items-center">
<q-icon color="blue" size="17px" name="mdi-eye" />
<div class="q-pl-md">รายละเอยด</div>
</div>
</q-item-section>
</q-item>
</q-list> </q-list>
</q-menu> </q-menu>
</q-btn> </q-btn>

View file

@ -44,6 +44,8 @@
> >
<q-tooltip>ไฟลเอกสารหลกฐาน</q-tooltip> <q-tooltip>ไฟลเอกสารหลกฐาน</q-tooltip>
</q-btn> </q-btn>
</q-td>
<q-td auto-width>
<q-btn <q-btn
color="info" color="info"
flat flat
@ -692,47 +694,52 @@ const clickSave = async () => {
* นทกเพมขอม * นทกเพมขอม
*/ */
const saveData = async () => { const saveData = async () => {
if (fileUpload.value.length > 0) { // if (fileUpload.value.length > 0) {
const blob = fileUpload.value.slice(0, fileUpload.value[0].size); const blob =
const newFile = new File(blob, nameFile.value, { fileUpload.value.length > 0
type: fileUpload.value[0].type, ? fileUpload.value.slice(0, fileUpload.value[0].size)
: null;
const newFile: any = blob
? new File(blob, nameFile.value, {
type: fileUpload.value[0].type,
})
: null;
const formData = new FormData();
newFile && formData.append("", newFile);
if (prefixId.value != undefined) formData.append("prefixId", prefixId.value);
if (firstName.value != undefined)
formData.append("firstName", firstName.value);
if (lastName.value != undefined) formData.append("lastName", lastName.value);
if (status.value != undefined) formData.append("status", status.value);
showLoader();
await http
.post(config.API.profileChangeNameId(profileId.value), formData)
.then((res) => {
success($q, "บันทึกข้อมูลสำเร็จ");
modal.value = false;
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchData();
await props.fetchDataInformation();
}); });
const formData = new FormData(); // }
formData.append("", newFile); // else {
if (prefixId.value != undefined) // dialogMessage(
formData.append("prefixId", prefixId.value); // $q,
if (firstName.value != undefined) // "",
formData.append("firstName", firstName.value); // "",
if (lastName.value != undefined) // "warning",
formData.append("lastName", lastName.value); // undefined,
if (status.value != undefined) formData.append("status", status.value); // "orange",
showLoader(); // undefined,
await http // undefined,
.post(config.API.profileChangeNameId(profileId.value), formData) // true
.then((res) => { // );
success($q, "บันทึกข้อมูลสำเร็จ"); // }
modal.value = false;
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchData();
await props.fetchDataInformation();
});
} else {
dialogMessage(
$q,
"ไม่สามารถบันทึกข้อมูลได้",
"กรุณาอัปโหลดเอกสารหลักฐาน",
"warning",
undefined,
"orange",
undefined,
undefined,
true
);
}
}; };
/** /**

View file

@ -212,7 +212,21 @@
</div> --> </div> -->
<div class="row q-col-gutter-sm"> <div class="row q-col-gutter-sm">
<div class="col-6"> <div class="col-6">
<q-input
v-if="edit"
outlined
v-model="inputDateLaeaveYear"
:label="`${'ปี'}`"
mask="####"
dense
:rules="[(val:string) => !!val || `${'กรุณาเลือกปี'}`]"
:class="getClass(edit)"
:readonly="!edit"
:borderless="!edit"
/>
<datepicker <datepicker
v-else
menu-class-name="modalfix" menu-class-name="modalfix"
v-model="formData.leaveYear" v-model="formData.leaveYear"
class="col-2" class="col-2"
@ -470,6 +484,7 @@ import HistoryTable from "@/components/TableHistory.vue";
import http from "@/plugins/http"; import http from "@/plugins/http";
import config from "@/app.config"; import config from "@/app.config";
import type { QTableProps } from "quasar"; import type { QTableProps } from "quasar";
import moment from "moment";
const props = defineProps({ const props = defineProps({
statusEdit: { statusEdit: {
@ -503,6 +518,8 @@ const {
showLoader, showLoader,
hideLoader, hideLoader,
dialogConfirm, dialogConfirm,
convertDate,
convertDateDisplay,
} = mixin; } = mixin;
const route = useRoute(); const route = useRoute();
@ -566,6 +583,16 @@ const filterTotal = ref<string>("");
const rowsTotal = ref<RequestItemsTotalObject[]>([]); //select data history const rowsTotal = ref<RequestItemsTotalObject[]>([]); //select data history
const filter = ref<string>(""); //search data table const filter = ref<string>(""); //search data table
const inputDateLaeaveYear = ref<string>("");
/** ตรวจเวลา */
watch(
() => inputDateLaeaveYear.value,
(value: string) => {
if (value.length === 4) {
formData.leaveYear = parseInt(value) - 543;
}
}
);
/**old */ /**old */
// const visibleColumns = ref<String[]>([]); // const visibleColumns = ref<String[]>([]);
// profileData.leave.columns.length == 0 // profileData.leave.columns.length == 0
@ -1051,11 +1078,11 @@ const getData = () => {
// coupleDay.value = row.coupleDay; // coupleDay.value = row.coupleDay;
// therapyDay.value = row.therapyDay; // therapyDay.value = row.therapyDay;
formData.id = row.id; formData.id = row.id;
formData.sumSick = row.sumSick =='-' ? '':row.sumSick; formData.sumSick = row.sumSick == "-" ? "" : row.sumSick;
formData.sumRest = row.sumRest =='-' ? '':row.sumRest; formData.sumRest = row.sumRest == "-" ? "" : row.sumRest;
formData.sumLate = row.sumLate =='-' ? '':row.sumLate; formData.sumLate = row.sumLate == "-" ? "" : row.sumLate;
formData.sumAbsent = row.sumAbsent =='-' ? '':row.sumAbsent; formData.sumAbsent = row.sumAbsent == "-" ? "" : row.sumAbsent;
formData.sumEducation = row.sumEducation =='-' ? '':row.sumEducation; formData.sumEducation = row.sumEducation == "-" ? "" : row.sumEducation;
formData.leaveYear = row.leaveYear == "-" ? 0 : Number(row.leaveYear) - 543; formData.leaveYear = row.leaveYear == "-" ? 0 : Number(row.leaveYear) - 543;
// id.value = row.id; // id.value = row.id;
@ -1101,6 +1128,7 @@ const clickAdd = async () => {
const clickAddLeave = async () => { const clickAddLeave = async () => {
clearForm(); clearForm();
inputDateLaeaveYear.value = (moment().year() + 543).toString();
editRow.value = false; editRow.value = false;
edit.value = true; edit.value = true;
modalAdd.value = true; modalAdd.value = true;
@ -1158,11 +1186,11 @@ const clickSave = async () => {
if (result) { if (result) {
if (modalEdit.value) { if (modalEdit.value) {
// await dialogConfirm($q, () => { // await dialogConfirm($q, () => {
editData(); editData();
// }); // });
} else { } else {
// await dialogConfirm($q, () => { // await dialogConfirm($q, () => {
saveData(); saveData();
// }); // });
} }
} }
@ -1173,7 +1201,9 @@ const clickSave = async () => {
// * // *
// */ // */
const saveData = async () => { const saveData = async () => {
formData.leaveYear = (await Number(inputDateLaeaveYear.value)) - 543;
const sum = Number(numLeave.value) + Number(numUsedLeave.value); const sum = Number(numLeave.value) + Number(numUsedLeave.value);
console.log(formData.leaveYear);
if (profileId.value) { if (profileId.value) {
showLoader(); showLoader();
@ -1188,6 +1218,7 @@ const saveData = async () => {
}) })
.then((res) => { .then((res) => {
success($q, "บันทึกข้อมูลสำเร็จ"); success($q, "บันทึกข้อมูลสำเร็จ");
modalAdd.value = false; modalAdd.value = false;
}) })
.catch((e) => { .catch((e) => {
@ -1324,12 +1355,19 @@ const selectData = async (props: DataProps) => {
rowIndex.value = props.rowIndex; rowIndex.value = props.rowIndex;
formData.id = props.row.id; formData.id = props.row.id;
formData.sumSick = props.row.sumSick == '-' ? '':props.row.sumSick; formData.sumSick = props.row.sumSick == "-" ? "" : props.row.sumSick;
formData.sumRest = props.row.sumRest == '-' ? '':props.row.sumRest; formData.sumRest = props.row.sumRest == "-" ? "" : props.row.sumRest;
formData.sumLate = props.row.sumLate == '-' ? '':props.row.sumLate; formData.sumLate = props.row.sumLate == "-" ? "" : props.row.sumLate;
formData.sumAbsent = props.row.sumAbsent == '-' ? '':props.row.sumAbsent; formData.sumAbsent = props.row.sumAbsent == "-" ? "" : props.row.sumAbsent;
formData.sumEducation = props.row.sumEducation == '-' ? '':props.row.sumEducation; formData.sumEducation =
formData.leaveYear = props.row.leaveYear == "-" ? 0 : Number(props.row.leaveYear) - 543; props.row.sumEducation == "-" ? "" : props.row.sumEducation;
formData.leaveYear =
props.row.leaveYear == "-" ? 0 : Number(props.row.leaveYear) - 543;
console.log("เเก้ไข");
inputDateLaeaveYear.value = ((formData.leaveYear as number) + 543).toString();
console.log(inputDateLaeaveYear.value);
// id.value = props.row.id; // id.value = props.row.id;
// typeLeave.value = props.row.typeLeaveId; // typeLeave.value = props.row.typeLeaveId;
@ -1361,10 +1399,9 @@ const selectData = async (props: DataProps) => {
* กดปมเพมบน table * กดปมเพมบน table
*/ */
const addData = async () => { const addData = async () => {
// modalEdit.value = false; //modalEdit.value = false;
modal.value = true; modal.value = true;
// edit.value = true; //edit.value = true;
await clickTotal(); await clickTotal();
}; };

View file

@ -57,7 +57,18 @@
<q-card-section class="q-p-sm"> <q-card-section class="q-p-sm">
<div class="row col-12 q-col-gutter-x-xs q-col-gutter-y-xs"> <div class="row col-12 q-col-gutter-x-xs q-col-gutter-y-xs">
<div class="col-xs-6 col-sm-6 col-md-6"> <div class="col-xs-6 col-sm-6 col-md-6">
<q-input
v-if="edit"
outlined
v-model="inputDate"
:label="`${'วันที่'}`"
mask="##/##/####"
dense
:rules="[(val) => !!val || `${'กรุณาเลือกวันที่'}`]"
/>
<datepicker <datepicker
v-else
menu-class-name="modalfix" menu-class-name="modalfix"
:readonly="!edit" :readonly="!edit"
v-model="date" v-model="date"
@ -73,6 +84,7 @@
}}</template> }}</template>
<template #trigger> <template #trigger>
<q-input <q-input
readonly
:class="getClass(edit)" :class="getClass(edit)"
:outlined="edit" :outlined="edit"
dense dense
@ -193,7 +205,15 @@ const store = useProfileDataStore();
const { profileData, changeProfileColumns } = store; const { profileData, changeProfileColumns } = store;
const mixin = useCounterMixin(); const mixin = useCounterMixin();
const { date2Thai, success, messageError, showLoader, hideLoader } = mixin; const {
convertDateDisplay,
convertDate,
date2Thai,
success,
messageError,
showLoader,
hideLoader,
} = mixin;
const route = useRoute(); const route = useRoute();
const id = ref<string>(""); const id = ref<string>("");
const date = ref<Date>(new Date()); const date = ref<Date>(new Date());
@ -218,6 +238,26 @@ const profileId = ref<string>(
const rows = ref<RequestItemsObject[]>([]); const rows = ref<RequestItemsObject[]>([]);
const filter = ref<string>(""); //search data table const filter = ref<string>(""); //search data table
const visibleColumns = ref<String[]>([]); const visibleColumns = ref<String[]>([]);
const inputDate = ref<string>("");
const dayChecked = ref<boolean>(false);
/** ตรวจเวลา */
watch(
() => inputDate.value,
(value: string) => {
if (value.length === 10) {
const dateVal = convertDate(value);
if (dateVal.isValid) {
dayChecked.value = false;
date.value = new Date(dateVal.value);
} else {
dayChecked.value = true;
inputDate.value = "";
}
}
}
);
profileData.other.columns.length == 0 profileData.other.columns.length == 0
? (visibleColumns.value = ["date", "detail"]) ? (visibleColumns.value = ["date", "detail"])
: (visibleColumns.value = profileData.other.columns); : (visibleColumns.value = profileData.other.columns);
@ -387,6 +427,7 @@ const clickEdit = () => {
* กดปมเพมดานบน table * กดปมเพมดานบน table
*/ */
const clickAdd = async () => { const clickAdd = async () => {
inputDate.value = "";
editRow.value = false; editRow.value = false;
await addData(); await addData();
}; };
@ -521,6 +562,8 @@ const selectData = async (props: DataProps) => {
date.value = props.row.date; date.value = props.row.date;
detail.value = props.row.detail; detail.value = props.row.detail;
id.value = props.row.id; id.value = props.row.id;
inputDate.value = convertDateDisplay(date.value);
await checkRowPage(); await checkRowPage();
}; };

View file

@ -989,8 +989,8 @@ function onClickUnlock() {
hideLoader(); hideLoader();
}); });
}, },
"ยืนยันการปลดให้แก้ไขข้อมูล", "ยืนยันการปลดล็อคให้แก้ไขข้อมูล",
"ต้องการยืนยันการปลดให้แก้ไขข้อมูลนี้หรือไม่?" "ต้องการยืนยันการปลดล็อคให้แก้ไขข้อมูลนี้หรือไม่?"
); );
} }
onMounted(async () => { onMounted(async () => {

View file

@ -65,7 +65,18 @@
<q-card-section class="q-p-sm"> <q-card-section class="q-p-sm">
<div class="row col-12 q-col-gutter-x-xs q-col-gutter-y-xs"> <div class="row col-12 q-col-gutter-x-xs q-col-gutter-y-xs">
<div class="col-xs-6 col-sm-6 col-md-6"> <div class="col-xs-6 col-sm-6 col-md-6">
<q-input
v-if="edit"
outlined
v-model="inputDate"
label="วัน/เดือน/ปี"
mask="##/##/####"
dense
:rules="[(val) => !!val || `${'กรุณาเลือกวัน เดือน ปี'}`]"
/>
<datepicker <datepicker
v-else
menu-class-name="modalfix" menu-class-name="modalfix"
:readonly="!edit" :readonly="!edit"
v-model="date" v-model="date"
@ -81,6 +92,7 @@
}}</template> }}</template>
<template #trigger> <template #trigger>
<q-input <q-input
readonly
:class="getClass(edit)" :class="getClass(edit)"
:outlined="edit" :outlined="edit"
dense dense
@ -162,7 +174,17 @@
</q-input> </q-input>
</div> </div>
<div class="col-xs-6 col-sm-6 col-md-6"> <div class="col-xs-6 col-sm-6 col-md-6">
<q-input
v-if="edit"
outlined
v-model="inputDateRefCommandDate"
:label="`${'เอกสารอ้างอิง (ลงวันที่)'}`"
mask="##/##/####"
dense
/>
<datepicker <datepicker
v-else
menu-class-name="modalfix" menu-class-name="modalfix"
:readonly="!edit" :readonly="!edit"
v-model="refCommandDate" v-model="refCommandDate"
@ -178,6 +200,7 @@
}}</template> }}</template>
<template #trigger> <template #trigger>
<q-input <q-input
readonly
:class="getClass(edit)" :class="getClass(edit)"
:outlined="edit" :outlined="edit"
dense dense
@ -294,8 +317,16 @@ const store = useProfileDataStore();
const { profileData, changeProfileColumns } = store; const { profileData, changeProfileColumns } = store;
const mixin = useCounterMixin(); const mixin = useCounterMixin();
const { date2Thai, success, dateToISO, messageError, showLoader, hideLoader } = const {
mixin; convertDateDisplay,
convertDate,
date2Thai,
success,
dateToISO,
messageError,
showLoader,
hideLoader,
} = mixin;
const route = useRoute(); const route = useRoute();
const id = ref<string>(""); const id = ref<string>("");
const date = ref<Date>(new Date()); const date = ref<Date>(new Date());
@ -325,6 +356,47 @@ const checkValidate = ref<boolean>(false); //validate data ผ่านหรื
const rows = ref<RequestItemsObject[]>([]); const rows = ref<RequestItemsObject[]>([]);
const filter = ref<string>(""); //search data table const filter = ref<string>(""); //search data table
const visibleColumns = ref<String[]>([]); const visibleColumns = ref<String[]>([]);
const inputDate = ref<string>("");
const inputDateRefCommandDate = ref<string>(
refCommandDate.value ? convertDateDisplay(refCommandDate.value) : ""
);
const dayChecked = ref<boolean>(false);
const dayCheckedRefCommandDate = ref<boolean>(false);
/** ตรวจเวลา */
watch(
() => inputDate.value,
(value: string) => {
if (value.length === 10) {
const dateVal = convertDate(value);
if (dateVal.isValid) {
dayChecked.value = false;
date.value = new Date(dateVal.value);
} else {
dayChecked.value = true;
inputDate.value = "";
}
}
}
);
watch(
() => inputDateRefCommandDate.value,
(value: string) => {
if (value.length === 10) {
const dateVal = convertDate(value);
if (dateVal.isValid) {
dayChecked.value = false;
refCommandDate.value = new Date(dateVal.value);
} else {
dayChecked.value = true;
inputDateRefCommandDate.value = "";
}
} else {
refCommandDate.value = null;
}
}
);
profileData.record.columns.length == 0 profileData.record.columns.length == 0
? (visibleColumns.value = [ ? (visibleColumns.value = [
"date", "date",
@ -725,6 +797,11 @@ const selectData = async (props: DataProps) => {
refCommandNo.value = props.row.refCommandNo; refCommandNo.value = props.row.refCommandNo;
refCommandDate.value = props.row.refCommandDate; refCommandDate.value = props.row.refCommandDate;
id.value = props.row.id; id.value = props.row.id;
inputDate.value = convertDateDisplay(date.value);
inputDateRefCommandDate.value = refCommandDate.value
? convertDateDisplay(refCommandDate.value)
: "";
await checkRowPage(); await checkRowPage();
}; };
@ -740,6 +817,8 @@ const addData = () => {
reference.value = ""; reference.value = "";
refCommandNo.value = ""; refCommandNo.value = "";
refCommandDate.value = null; refCommandDate.value = null;
inputDate.value = convertDateDisplay(date.value);
inputDateRefCommandDate.value = "";
}; };
/** /**

View file

@ -74,7 +74,8 @@
<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-th auto-width v-if="name !== 'การลา'"/> <q-th auto-width v-if="name !== 'การลา'" />
<q-th auto-width v-if="name === 'ประวัติการเปลี่ยนชื่อ-นามสกุล'" />
</q-tr> </q-tr>
</template> </template>
<template #body="props"> <template #body="props">

View file

@ -64,7 +64,20 @@
<q-card-section class="q-p-sm"> <q-card-section class="q-p-sm">
<div class="row col-12 q-col-gutter-x-xs q-col-gutter-y-xs"> <div class="row col-12 q-col-gutter-x-xs q-col-gutter-y-xs">
<div class="col-xs-6 col-sm-6 col-md-6"> <div class="col-xs-6 col-sm-6 col-md-6">
<q-input
v-if="edit"
outlined
v-model="inputDateStart"
label="วันที่เริ่มต้น"
mask="##/##/####"
dense
:error="dayCheckedStart"
error-message="กรุณากรอกวัน/เดือน/ปี เริ่มต้น"
:rules="[(val) => !!val || `${'กรุณาเลือกวันที่เริ่มต้น'}`]"
/>
<datepicker <datepicker
v-else
menu-class-name="modalfix" menu-class-name="modalfix"
:readonly="!edit" :readonly="!edit"
v-model="dateStart" v-model="dateStart"
@ -80,6 +93,7 @@
}}</template> }}</template>
<template #trigger> <template #trigger>
<q-input <q-input
readonly
:class="getClass(edit)" :class="getClass(edit)"
:outlined="edit" :outlined="edit"
dense dense
@ -107,7 +121,19 @@
</datepicker> </datepicker>
</div> </div>
<div class="col-xs-6 col-sm-6 col-md-6"> <div class="col-xs-6 col-sm-6 col-md-6">
<q-input
v-if="edit"
outlined
v-model="inputDateEnd"
label="วันที่สิ้นสุด"
mask="##/##/####"
dense
:error="dayCheckedEnd"
error-message="กรุณากรอกวัน/เดือน/ปี สิ้นสุด"
:rules="[(val) => !!val || `${'กรุณาเลือกวันที่สิ้นสุด'}`]"
/>
<datepicker <datepicker
v-else
menu-class-name="modalfix" menu-class-name="modalfix"
v-model="dateEnd" v-model="dateEnd"
:locale="'th'" :locale="'th'"
@ -124,6 +150,7 @@
}}</template> }}</template>
<template #trigger> <template #trigger>
<q-input <q-input
readonly
:class="getClass(edit)" :class="getClass(edit)"
:outlined="edit" :outlined="edit"
dense dense
@ -205,7 +232,17 @@
</q-input> </q-input>
</div> </div>
<div class="col-xs-6 col-sm-6 col-md-6"> <div class="col-xs-6 col-sm-6 col-md-6">
<q-input
v-if="edit"
outlined
v-model="inputRefCommandDate"
:label="`${'เอกสารอ้างอิง (ลงวันที่)'}`"
mask="##/##/####"
dense
/>
<datepicker <datepicker
v-else
menu-class-name="modalfix" menu-class-name="modalfix"
:readonly="!edit" :readonly="!edit"
v-model="refCommandDate" v-model="refCommandDate"
@ -221,6 +258,7 @@
}}</template> }}</template>
<template #trigger> <template #trigger>
<q-input <q-input
readonly
:class="getClass(edit)" :class="getClass(edit)"
:outlined="edit" :outlined="edit"
dense dense
@ -252,9 +290,7 @@
/> />
</template> </template>
</q-input> </q-input>
</template> </template>
</datepicker> </datepicker>
</div> </div>
</div> </div>
@ -311,6 +347,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { onMounted, ref, watch } from "vue"; import { onMounted, ref, watch } from "vue";
import { useRoute } from "vue-router"; import { useRoute } from "vue-router";
import moment from "moment";
import { useProfileDataStore } from "@/modules/04_registry/store"; import { useProfileDataStore } from "@/modules/04_registry/store";
import { useCounterMixin } from "@/stores/mixin"; import { useCounterMixin } from "@/stores/mixin";
@ -340,8 +377,16 @@ const store = useProfileDataStore();
const { profileData, changeProfileColumns } = store; const { profileData, changeProfileColumns } = store;
const mixin = useCounterMixin(); const mixin = useCounterMixin();
const { date2Thai, success, dateToISO, messageError, showLoader, hideLoader } = const {
mixin; convertDateDisplay,
convertDate,
date2Thai,
success,
dateToISO,
messageError,
showLoader,
hideLoader,
} = mixin;
const route = useRoute(); const route = useRoute();
const id = ref<string>(""); const id = ref<string>("");
const dateStart = ref<Date>(new Date()); const dateStart = ref<Date>(new Date());
@ -371,6 +416,63 @@ const profileId = ref<string>(
const rows = ref<RequestItemsObject[]>([]); const rows = ref<RequestItemsObject[]>([]);
const filter = ref<string>(""); //search data table const filter = ref<string>(""); //search data table
const visibleColumns = ref<String[]>([]); const visibleColumns = ref<String[]>([]);
console.log(dateStart.value);
const inputDateStart = ref<string>(convertDateDisplay(dateStart.value));
const inputDateEnd = ref<string>(convertDateDisplay(dateEnd.value));
const inputRefCommandDate = ref<string>("");
const dayCheckedStart = ref<boolean>(false);
const dayCheckedEnd = ref<boolean>(false);
/** ตรวจเวลา */
watch(
() => inputDateStart.value,
(value: string) => {
if (value.length === 10) {
const dateVal = convertDate(value);
if (dateVal.isValid) {
dayCheckedStart.value = false;
dateStart.value = new Date(dateVal.value);
} else {
dayCheckedStart.value = true;
inputDateStart.value = "";
}
}
}
);
watch(
() => inputRefCommandDate.value,
(value: string) => {
if (value.length === 10) {
const dateVal = convertDate(value);
if (dateVal.isValid) {
dayCheckedEnd.value = false;
refCommandDate.value = new Date(dateVal.value);
} else {
dayCheckedEnd.value = true;
inputRefCommandDate.value = "";
}
} else {
refCommandDate.value = null;
}
}
);
watch(
() => inputDateEnd.value,
(value: string) => {
if (value.length === 10) {
const dateVal = convertDate(value);
if (dateVal.isValid) {
dayCheckedEnd.value = false;
dateEnd.value = new Date(dateVal.value);
} else {
dayCheckedEnd.value = true;
inputDateEnd.value = "";
}
}
}
);
profileData.work.columns.length == 0 profileData.work.columns.length == 0
? (visibleColumns.value = [ ? (visibleColumns.value = [
"dateStart", "dateStart",
@ -804,6 +906,12 @@ const selectData = async (props: DataProps) => {
refCommandNo.value = props.row.refCommandNo; refCommandNo.value = props.row.refCommandNo;
refCommandDate.value = props.row.refCommandDate; refCommandDate.value = props.row.refCommandDate;
id.value = props.row.id; id.value = props.row.id;
inputDateStart.value = convertDateDisplay(dateStart.value);
inputDateEnd.value = convertDateDisplay(dateEnd.value);
inputRefCommandDate.value = refCommandDate.value
? convertDateDisplay(refCommandDate.value)
: "";
await checkRowPage(); await checkRowPage();
}; };
@ -820,6 +928,10 @@ const addData = () => {
reference.value = ""; reference.value = "";
refCommandNo.value = ""; refCommandNo.value = "";
refCommandDate.value = null; refCommandDate.value = null;
inputDateStart.value = convertDateDisplay(dateStart.value);
inputDateEnd.value = convertDateDisplay(dateEnd.value);
inputRefCommandDate.value = "";
}; };
/** /**

View file

@ -18,6 +18,7 @@ const {
messageError, messageError,
showLoader, showLoader,
hideLoader, hideLoader,
dialogMessageNotify,
} = mixin; } = mixin;
const columns = ref<QTableProps["columns"]>([ const columns = ref<QTableProps["columns"]>([
{ {
@ -170,34 +171,66 @@ async function fetchPrefix() {
} }
async function addData() { async function addData() {
await http.post(config.API.registryNew, { showLoader();
prefix: prefix.value, await http
firstName: firstName.value, .post(config.API.registryNew, {
lastName: lastName.value, prefix: prefix.value,
citizenId: citizenId.value, firstName: firstName.value,
position: position.value, lastName: lastName.value,
posTypeId: posTypeId.value, citizenId: citizenId.value,
posLevelId: posLevelId.value, position: position.value,
}); posTypeId: posTypeId.value,
fetchData(); posLevelId: posLevelId.value,
})
.then(() => {
success($q, "บันทึกข้อมูลสำเร็จ");
})
.catch((err) => {
messageError($q, err);
})
.finally(() => {
fetchData();
hideLoader();
});
} }
async function editData(id: string) { async function editData(id: string) {
await http.put(config.API.registryNewId(id), { showLoader();
prefix: prefix.value, await http
firstName: firstName.value, .put(config.API.registryNewId(id), {
lastName: lastName.value, prefix: prefix.value,
citizenId: citizenId.value, firstName: firstName.value,
position: position.value, lastName: lastName.value,
posTypeId: posTypeId.value, citizenId: citizenId.value,
posLevelId: posLevelId.value, position: position.value,
}); posTypeId: posTypeId.value,
fetchData(); posLevelId: posLevelId.value,
})
.then(() => {
success($q, "บันทึกข้อมูลสำเร็จ");
})
.catch((err) => {
messageError($q, err);
})
.finally(() => {
fetchData();
hideLoader();
});
} }
async function deleteData(id: string) { async function deleteData(id: string) {
await http.delete(config.API.registryNewId(id)); await http
fetchData(); .delete(config.API.registryNewId(id))
.then(() => {
success($q, "ลบข้อมูลสำเร็จ");
})
.catch((err) => {
messageError($q, err);
})
.finally(() => {
fetchData();
hideLoader();
});
} }
function updateSelectType(val: string) { function updateSelectType(val: string) {
@ -250,6 +283,28 @@ watch(posTypeId, () => {
updateSelectType(posTypeId.value); updateSelectType(posTypeId.value);
}, 200); }, 200);
}); });
/**
* function ตรวจสอบเลขประจำตวประชาชน
* @param citizenId เลขประจำตวประชาชน
*/
async function changeCardID(citizenId: string | number | null) {
if (citizenId != null && typeof citizenId == "string") {
if (citizenId.length == 13 && citizenId) {
await http
.get(config.API.profileCitizenId(citizenId))
.then((res) => {
console.log(res);
const statusId = res.data.result.citizen;
!statusId &&
dialogMessageNotify($q, "เลขประจำตัวประชาชนนี้มีการใช้งานแล้ว");
})
.catch((err) => {
messageError($q, err);
});
}
}
}
</script> </script>
<template> <template>
@ -294,103 +349,104 @@ watch(posTypeId, () => {
/> />
</div> </div>
</q-toolbar> </q-toolbar>
<div class="col-12">
<d-table
ref="table"
:columns="columns"
:rows="store.row"
:filter="filterKeyword"
row-key="name"
flat
bordered
:paging="true"
dense
class="custom-header-table"
: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-th auto-width />
</q-tr>
</template>
<template v-slot:body="props">
<q-tr :props="props" class="cursor-pointer">
<q-td v-for="col in props.cols" :key="col.id">
<div v-if="col.name == 'no'">
{{ props.rowIndex + 1 }}
</div>
<div v-else-if="col.name == 'fullName'">
{{ props.row.prefix }}{{ props.row.firstName }}
{{ props.row.lastName }}
</div>
<d-table <div v-else>
ref="table" {{ col.value }}
:columns="columns" </div>
:rows="store.row" </q-td>
:filter="filterKeyword" <q-td auto-width>
row-key="name" <q-btn
flat color="grey"
bordered flat
:paging="true" dense
dense round
class="custom-header-table" size="14px"
:visible-columns="visibleColumns" icon="more_vert"
> @click.stop
<template v-slot:header="props"> >
<q-tr :props="props"> <q-menu>
<q-th v-for="col in props.cols" :key="col.name" :props="props"> <q-list dense>
<span class="text-weight-medium">{{ col.label }}</span> <q-item
</q-th>
<q-th auto-width />
</q-tr>
</template>
<template v-slot:body="props">
<q-tr :props="props" class="cursor-pointer">
<q-td v-for="col in props.cols" :key="col.id">
<div v-if="col.name == 'no'">
{{ props.rowIndex + 1 }}
</div>
<div v-else-if="col.name == 'fullName'">
{{ props.row.prefix }}{{ props.row.firstName }}
{{ props.row.lastName }}
</div>
<div v-else>
{{ col.value }}
</div>
</q-td>
<q-td auto-width>
<q-btn
color="grey"
flat
dense
round
size="14px"
icon="more_vert"
@click.stop
>
<q-menu>
<q-list dense>
<q-item
v-close-popup
clickable
@click.stop="
() => {
dialogStatus = 'edit';
dialog = true;
editId = props.row.id;
prefix = props.row.prefix;
firstName = props.row.firstName;
lastName = props.row.lastName;
citizenId = props.row.citizenId;
position = props.row.position;
posTypeId = props.row.posTypeId;
posLevelId = props.row.posLevelId;
}
"
>
<q-item-section>
<div class="row items-center white">
<q-icon name="o_edit" color="positive" />
<span class="q-ml-sm">แกไข</span>
</div>
</q-item-section>
</q-item>
<q-item clickable>
<q-item-section
@click="
dialogRemove(
$q,
async () => await deleteData(props.row.id)
)
"
v-close-popup v-close-popup
clickable
@click.stop="
() => {
dialogStatus = 'edit';
dialog = true;
editId = props.row.id;
prefix = props.row.prefix;
firstName = props.row.firstName;
lastName = props.row.lastName;
citizenId = props.row.citizenId;
position = props.row.position;
posTypeId = props.row.posTypeId;
posLevelId = props.row.posLevelId;
}
"
> >
<div class="row items-center white"> <q-item-section>
<q-icon name="mdi-trash-can-outline" color="negative" /> <div class="row items-center white">
<span class="q-ml-sm">ลบ</span> <q-icon name="o_edit" color="positive" />
</div> <span class="q-ml-sm">แกไข</span>
</q-item-section> </div>
</q-item> </q-item-section>
</q-list> </q-item>
</q-menu> <q-item clickable>
</q-btn> <q-item-section
</q-td> @click="
</q-tr> dialogRemove(
</template> $q,
</d-table> async () => await deleteData(props.row.id)
)
"
v-close-popup
>
<div class="row items-center white">
<q-icon name="mdi-trash-can-outline" color="negative" />
<span class="q-ml-sm">ลบ</span>
</div>
</q-item-section>
</q-item>
</q-list>
</q-menu>
</q-btn>
</q-td>
</q-tr>
</template>
</d-table>
</div>
<q-dialog v-model="dialog" class="dialog" persistent> <q-dialog v-model="dialog" class="dialog" persistent>
<q-card style="min-width: 350px" class="bg-grey-11"> <q-card style="min-width: 350px" class="bg-grey-11">
@ -461,6 +517,7 @@ watch(posTypeId, () => {
maxlength="13" maxlength="13"
hide-bottom-space hide-bottom-space
mask="#############" mask="#############"
@update:model-value="changeCardID"
/> />
<q-input <q-input
ref="positionRef" ref="positionRef"