hrms-mgt/src/modules/02_organization/components/StructureMain.vue
2024-08-01 12:12:28 +07:00

315 lines
8.7 KiB
Vue
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<script setup lang="ts">
import { ref, onMounted, watch } 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";
import { useOrganizational } from "@/modules/02_organization/store/organizational";
const mixin = useCounterMixin();
const store = useOrganizational();
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 () => {
const id =
store.typeOrganizational === "current"
? store.activeId
: store.typeOrganizational === "draft"
? store.draftId
: store.historyId;
id && (await fetchStructChart(id, "0"));
});
async function fetchStructChart(
id: string,
type: string,
status: boolean = false
) {
console.log(status);
showLoader();
await http
.get(config.API.orgStructChart(id, type))
.then((res) => {
if (res.data.result.length > 0) {
const data = res.data.result[0];
const struct = [];
struct.push({ ...data, officer: [], heads: [] });
dataSource.value = struct[0];
if (dataSourceLock.value === undefined || status)
dataSourceLock.value = dataSource.value;
breadcrumbsGen();
}
})
.catch((err) => {
messageError($q, err);
})
.finally(() => {
hideLoader();
});
}
/**
* อ่าน 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, type: number) => {
console.log(data, type);
if (data.value === undefined) {
fetchStructChart(data, type.toString());
rootOrgID.value = data;
} else {
searchAndReplace(dataSource.value, data.value);
}
};
function searchAndReplace(data: any, id: string) {
if (data.deptID === id) {
fetchStructChart(data.deptID, data.type.toString());
rootOrgID.value = data.deptID;
} else if (data.children) {
for (const child of data.children) {
searchAndReplace(child, id);
}
}
}
/**
* === กระบวนการสร้าง 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,
type: child.type,
});
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,
type: child.type,
});
return [..._returnPath, ...(_result ?? [])];
}
}
}
}
};
const findPath = (id: any) => {
let _path = [];
_path.push({
label: dataSourceLock.value.departmentName,
id: dataSourceLock.value.deptID,
type: dataSourceLock.value.type,
});
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;
}
};
watch(
() => store.typeOrganizational,
async () => {
store.historyId = "";
const id =
store.typeOrganizational === "current"
? store.activeId
: store.typeOrganizational === "draft"
? store.draftId
: "";
id && (await fetchStructChart(id, "0", true));
}
);
watch(
() => store.historyId,
async () => {
store.historyId && (await fetchStructChart(store.historyId, "0", true));
}
);
</script>
<template>
<q-card flat bordered>
<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, link.type)"
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>
<full-loader :visibility="loader"></full-loader>
</template>
<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>