แผนผังองค์กร
This commit is contained in:
parent
3e213f0681
commit
43772f8d0a
5 changed files with 306 additions and 2 deletions
|
|
@ -52,4 +52,11 @@ export default {
|
||||||
dataUserCertificateHistory:(type:string,id:string) => `${profileOrg}/${type}/history/${id}`,
|
dataUserCertificateHistory:(type:string,id:string) => `${profileOrg}/${type}/history/${id}`,
|
||||||
dataUserHonorHistory:(type:string,emType:string,id:string) => `${profileOrg}${emType}/${type}/history/${id}`,
|
dataUserHonorHistory:(type:string,emType:string,id:string) => `${profileOrg}${emType}/${type}/history/${id}`,
|
||||||
dataUserOtherHistory:(id:string)=>`${profileOrg}/other/history/${id}`,
|
dataUserOtherHistory:(id:string)=>`${profileOrg}/other/history/${id}`,
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
orgActive:`${org}/active`,
|
||||||
|
/** struct-chart*/
|
||||||
|
orgStructChart: (id: string, type: string) =>
|
||||||
|
`${org}/struct-chart/${id}/${type}`,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ const items = ref<any>([
|
||||||
title: "แผนผังองค์กร",
|
title: "แผนผังองค์กร",
|
||||||
sub: "ดูแผนผังองค์กร",
|
sub: "ดูแผนผังองค์กร",
|
||||||
color: "blue-3",
|
color: "blue-3",
|
||||||
path: "",
|
path: "/organization-chart",
|
||||||
active: false,
|
active: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
||||||
13
src/modules/12_organization/router.ts
Normal file
13
src/modules/12_organization/router.ts
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
const organizationChart = () =>
|
||||||
|
import("@/modules/12_organization/views/main.vue");
|
||||||
|
export default [
|
||||||
|
{
|
||||||
|
path: "/organization-chart",
|
||||||
|
name: "organizationChart",
|
||||||
|
component: organizationChart,
|
||||||
|
meta: {
|
||||||
|
Auth: true,
|
||||||
|
Key: [7],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
282
src/modules/12_organization/views/main.vue
Normal file
282
src/modules/12_organization/views/main.vue
Normal file
|
|
@ -0,0 +1,282 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, computed, onMounted, watch } from "vue";
|
||||||
|
import { useQuasar } from "quasar";
|
||||||
|
import { useRouter } from "vue-router";
|
||||||
|
|
||||||
|
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";
|
||||||
|
|
||||||
|
/** use*/
|
||||||
|
const mixin = useCounterMixin();
|
||||||
|
const { showLoader, hideLoader, messageError } = mixin;
|
||||||
|
const router = useRouter();
|
||||||
|
const $q = useQuasar();
|
||||||
|
const chartRef = ref(); // อ้างอิงไปที่ตัว chart
|
||||||
|
const theBreadcrumb = ref();
|
||||||
|
const rootOrgID = ref(); // org id ของ root ตัวปัจจุบันที่เลือกอยู่
|
||||||
|
const dataSource = ref(); // ข้อมูล Chart
|
||||||
|
const idActive = ref<string>("");
|
||||||
|
const dataSourceLock = ref(); // ข้อมูลตั้งต้นของ Chart ใช้ให้กดกลับไปที่ home
|
||||||
|
|
||||||
|
/**
|
||||||
|
* สร้าง Path Breadcrumbs
|
||||||
|
*/
|
||||||
|
function breadcrumbsGen() {
|
||||||
|
if (rootOrgID.value !== 0) {
|
||||||
|
theBreadcrumb.value = [];
|
||||||
|
const newPath = findPath(rootOrgID.value);
|
||||||
|
theBreadcrumb.value = newPath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* === กระบวนการสร้าง Path ===
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* Recursive เพื่อหา Path ที่ผู้ใช้คลิก
|
||||||
|
* @param id OrgID ของหน่วยงานที่ต้องการหา
|
||||||
|
* @param chart Array ของ Object ของหน่วยงานย่อยใน Tree นั้น ๆ
|
||||||
|
*/
|
||||||
|
function 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 ?? [])];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function 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 ?? [])];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function savePNG() {
|
||||||
|
chartRef.value.savePNG();
|
||||||
|
}
|
||||||
|
|
||||||
|
function savePDF() {
|
||||||
|
chartRef.value.savePDF();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* เมื่อมีการคลิกที่ Chart ให้อ่าน ID ของหน่วยงานที่ถูกคลิก แล้วดึงข้อมูล Chart ของหน่วยงานนั้น ๆ จาก API
|
||||||
|
* @param data
|
||||||
|
*/
|
||||||
|
async function refreshChart(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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getActive() {
|
||||||
|
http
|
||||||
|
.get(config.API.orgActive)
|
||||||
|
.then(async (res) => {
|
||||||
|
const data = await res.data.result;
|
||||||
|
idActive.value = data.activeId;
|
||||||
|
fetchStructChart(data.activeId, "0");
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
messageError($q, e);
|
||||||
|
})
|
||||||
|
.finally(() => {});
|
||||||
|
}
|
||||||
|
/** hook lifecycle*/
|
||||||
|
onMounted(async () => {
|
||||||
|
await getActive();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="col-12 row justify-center">
|
||||||
|
<div class="col-xs-12 col-sm-12 col-md-11">
|
||||||
|
<div class="toptitle text-white col-12 row items-center">
|
||||||
|
<q-btn
|
||||||
|
icon="mdi-arrow-left"
|
||||||
|
unelevated
|
||||||
|
round
|
||||||
|
dense
|
||||||
|
flat
|
||||||
|
color="primary"
|
||||||
|
class="q-mr-sm"
|
||||||
|
@click="router.go(-1)"
|
||||||
|
/>
|
||||||
|
<div>แผนผังองค์กร</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-xs-12 col-sm-12 col-md-11 row q-col-gutter-md">
|
||||||
|
<div class="col-12 row">
|
||||||
|
<q-card bordered class="col-12 row caedNone">
|
||||||
|
<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>
|
||||||
|
<div class="col-12">
|
||||||
|
<q-separator/>
|
||||||
|
</div>
|
||||||
|
<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>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.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>
|
||||||
|
|
@ -15,6 +15,7 @@ import ModuleKPI from "@/modules/08_KPI/router";
|
||||||
import ModuleScholarship from "@/modules/09_scholarship/router";
|
import ModuleScholarship from "@/modules/09_scholarship/router";
|
||||||
import ModuleRegistry from "@/modules/10_registry/router";
|
import ModuleRegistry from "@/modules/10_registry/router";
|
||||||
import ModuleProbation from "@/modules/11_probation/router";
|
import ModuleProbation from "@/modules/11_probation/router";
|
||||||
|
import ModuleOrganization from "@/modules/12_organization/router";
|
||||||
// TODO: ใช้หรือไม่?
|
// TODO: ใช้หรือไม่?
|
||||||
import keycloak from "@/plugins/keycloak";
|
import keycloak from "@/plugins/keycloak";
|
||||||
|
|
||||||
|
|
@ -54,7 +55,8 @@ const router = createRouter({
|
||||||
...ModuleKPI,
|
...ModuleKPI,
|
||||||
...ModuleScholarship,
|
...ModuleScholarship,
|
||||||
...ModuleRegistry,
|
...ModuleRegistry,
|
||||||
...ModuleProbation
|
...ModuleProbation,
|
||||||
|
...ModuleOrganization,
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue