hrms-mgt/src/modules/02_organizationalNew/components/mainTree.vue

526 lines
15 KiB
Vue

<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 type { ListMenu } from "@/modules/02_organizationalNew/interface/index/Main";
import type { OrgTree } from "@/modules/02_organizationalNew/interface/response/organizational";
/** importComponents*/
import DialogAgency from "@/modules/02_organizationalNew/components/DialogFormAgency.vue";
import DialogStructureDetail from "@/modules/02_organizationalNew/components/StructureDetail.vue";
import DialogSortAgency from "@/modules/02_organizationalNew/components/DialogSortAgency.vue";
import DialogHistory from "@/modules/02_organizationalNew/components/DialogHistory.vue";
/** importStore*/
import { useOrganizational } from "@/modules/02_organizationalNew/store/organizational";
import { useCounterMixin } from "@/stores/mixin";
const store = useOrganizational();
const { dialogRemove, showLoader, hideLoader, messageError, success } =
useCounterMixin();
const $q = useQuasar();
const props = defineProps({
fetchDataTree: {
type: Function,
require: true,
},
fetchDataTable: {
type: Function,
require: true,
},
});
const listAdd = ref<ListMenu[]>([
{
label: "เพิ่ม",
icon: "add",
type: "ADD",
color: "primary",
},
{
label: "แก้ไข",
icon: "edit",
type: "EDIT",
color: "info",
},
{
label: "ลบ",
icon: "mdi-trash-can-outline",
type: "DEL",
color: "red",
},
// {
// label: "สำเนาหน่วยงาน",
// icon: "content_copy",
// type: "COPY",
// color: "blue",
// },
{
label: "ประวัติ",
icon: "history",
type: "HISTORY",
color: "purple",
},
{
label: "จัดลำดับ",
icon: "mdi-sort",
type: "SORT",
color: "blue-6",
},
// {
// label: "แก้ไขสถานะ",
// icon: "rule",
// type: "STATUS",
// color: "yellow-9",
// },
{
label: "ดูรายละเอียด",
icon: "mdi-eye",
type: "DETAIL",
color: "blue-9",
},
]);
const nodeTEST = defineModel<OrgTree[]>("nodeTree", { default: [] });
const nodeId = defineModel<string>("nodeId", { required: true });
const isLoad = defineModel<boolean>("isLoad", { required: true });
const filter = ref<string>("");
const nodes = ref<Array<OrgTree>>([]);
const dataSort = ref<Array<any>>([]);
const lazy = ref(nodes);
const expanded = ref<Array<any>>([]);
const notFound = ref<string>("ไม่พบข้อมูลที่ค้นหา");
const noData = ref<string>("ไม่มีข้อมูล");
const selected = ref("");
const orgLevel = ref<number>(0);
const type = ref<number>(0);
const orgId = ref<string>("");
const updateSelected = (id: string, level: number) => {
if (id === nodeId.value) {
nodeId.value = "";
} else {
nodeId.value = id ? id : "";
id && props.fetchDataTable?.(id, level);
}
};
const breakLoop = ref<boolean>(false);
async function edit(id: string, type: string, data: any, orgRootCode: string) {
breakLoop.value = false;
const targetNodeId = id;
for (let index = 0; index < nodes.value.length; index++) {
const element = nodes.value[index];
searchAndReplace(element, targetNodeId, data, type, orgRootCode);
if (breakLoop.value) break;
}
}
function searchAndReplace(
treeNode: any,
organizationId: string,
data: any,
type: string,
orgRootCode: string
) {
if (treeNode.orgTreeId === organizationId) {
let newData = {
...treeNode,
orgTreeName: data[`org${type}Name`],
orgTreeShortName: data[`org${type}ShortName`],
orgCode:
data.orgRootRank == "DEPARTMENT"
? data[`org${type}Code`] + "00"
: orgRootCode + data[`org${type}Code`],
orgTreeCode: data[`org${type}Code`],
orgTreePhoneEx: data[`org${type}PhoneEx`],
orgTreePhoneIn: data[`org${type}PhoneIn`],
orgTreeFax: data[`org${type}Fax`],
orgTreeRank: data[`org${type}Rank`],
};
Object.assign(treeNode, newData);
breakLoop.value = true;
} else if (treeNode.children) {
for (const child of treeNode.children) {
searchAndReplace(child, organizationId, data, type, orgRootCode);
}
}
}
async function deleteUpdate(rootId: string, treeId: string) {
breakLoop.value = false;
if (rootId) {
for (let index = 0; index < nodes.value.length; index++) {
const element = nodes.value[index];
deleteNode(element, rootId, treeId);
if (breakLoop.value) break;
}
} else {
nodes.value = nodes.value.filter((x: any) => x.orgTreeId != treeId);
}
}
function deleteNode(treeNode: any, rootId: string, treeId: string): boolean {
if (treeNode.orgTreeId === rootId) {
const childrenNew = treeNode.children.filter(
(x: any) => x.orgTreeId != treeId
);
let newData = {
...treeNode,
children: childrenNew,
};
Object.assign(treeNode, newData);
breakLoop.value = true;
} else if (treeNode.children) {
for (const child of treeNode.children) {
deleteNode(child, rootId, treeId);
}
}
return false;
}
const modalHistory = ref<boolean>(false);
const modalSortAgency = ref<boolean>(false);
const dialogAgency = ref<boolean>(false);
const actionType = ref<string>("");
const dataNode = ref<any>();
const treeId = ref<string>("");
function onClickAgency(level: number, node: OrgTree | {}) {
dialogAgency.value = !dialogAgency.value;
orgLevel.value = level;
dataNode.value = node;
actionType.value = "ADD";
}
const dialogDetail = ref<boolean>(false);
function onClickDetail(id: string, level: number) {
showLoader();
treeId.value = id;
dialogDetail.value = !dialogDetail.value;
orgLevel.value = level;
}
async function onClickEdit(node: OrgTree) {
dialogAgency.value = !dialogAgency.value;
actionType.value = "EDIT";
orgLevel.value = node.orgLevel;
dataNode.value = node;
}
async function onClickDel(type: number, id: string, rootId: string) {
const level = store.checkLevel(type);
dialogRemove($q, async () => {
showLoader();
await http
.delete(config.API.orgLevelByid(level.toLocaleLowerCase(), id))
.then(() => {
success($q, "ลบข้อมูลสำเร็จ");
deleteUpdate(rootId, id);
})
.catch((err) => {
messageError($q, err);
})
.finally(async () => {
hideLoader();
});
});
}
async function onClickSort(id: string, level: number) {
type.value = level;
modalSortAgency.value = true;
if (id) {
breakLoop.value = false;
const orgId = id;
for (let index = 0; index < nodes.value.length; index++) {
const data = nodes.value[index];
searchAndReplace(data, orgId);
if (breakLoop.value) break;
}
} else {
const dataList = nodes.value;
const dataMap = dataList.map((item: any) => ({
orgTreeId: item.orgTreeId,
orgLevel: item.orgLevel,
orgTreeName: item.orgTreeName,
orgTreeShortName: item.orgTreeShortName,
orgRevisionId: item.orgRevisionId,
}));
dataSort.value = dataMap;
}
function searchAndReplace(data: any, id: string) {
if (data.orgTreeId === id) {
dataSort.value = data.children;
breakLoop.value = true;
} else if (data.children) {
for (const child of data.children) {
searchAndReplace(child, id);
}
}
}
}
function onClickHistory(level: number, id: string) {
type.value = level;
orgId.value = id;
modalHistory.value = true;
}
watch(
() => nodeTEST.value,
() => {
nodes.value = nodeTEST.value;
}
);
onMounted(async () => {});
</script>
<template>
<div class="col-12 q-py-md q-px-sm">
<div class="q-gutter-sm">
<div class="row q-col-gutter-sm q-pl-sm">
<div class="col-2" v-if="store.typeOrganizational === 'draft'">
<q-btn
dense
flat
round
color="primary"
icon="add"
@click="onClickAgency(0, {})"
>
<q-tooltip>เพมหนวยงาน</q-tooltip>
</q-btn>
</div>
<div
:class="store.typeOrganizational === 'draft' ? 'col-10' : 'col-12'"
>
<q-input
dense
outlined
v-model="filter"
label="ค้นหา"
class="bg-white"
>
<template v-slot:append>
<q-icon
v-if="filter !== ''"
name="clear"
class="cursor-pointer"
@click="filter = ''"
/>
</template>
</q-input>
</div>
</div>
<div class="bg-white tree-container">
<q-tree
class="q-pa-md q-gutter-sm"
dense
default-expand-all
selected-color="primary"
:nodes="lazy"
node-key="orgTreeId"
label-key="orgTreeName"
:filter="filter"
:no-results-label="notFound"
:no-nodes-label="noData"
v-model:expanded="expanded"
v-model:selected="selected"
>
<template v-slot:default-header="prop">
<!-- {{ prop.node.orgTreeName }} -->
<div
class="row items-center q-px-xs q-pt-xs q-gutter-sm"
@click="updateSelected(prop.node.orgTreeId, prop.node.orgLevel)"
>
<!--แสดงชอแผนก มพวหนา คลกแลวกาง/ Tree-->
<div>
<div class="text-weight-medium">
{{ prop.node.orgTreeName }}
</div>
<div class="text-weight-light">
{{ prop.node.orgCode == null ? null : prop.node.orgCode }}
{{
prop.node.orgTreeShortName == null
? null
: prop.node.orgTreeShortName
}}
</div>
</div>
</div>
<q-btn
v-if="store.typeOrganizational === 'draft'"
flat
dense
icon="mdi-dots-vertical"
class="q-pa-none q-ml-xs"
color="grey-13"
>
<q-menu>
<q-list
dense
v-for="(item, index) in prop.node.orgLevel === 4
? listAdd.slice(1, 6)
: listAdd"
:key="index"
style="min-width: 100px"
>
<q-item
clickable
v-close-popup
@click="
item.type === 'EDIT'
? onClickEdit(prop.node)
: item.type === 'ADD'
? onClickAgency(prop.node.orgLevel + 1, prop.node)
: item.type === 'DETAIL'
? onClickDetail(prop.node.orgTreeId, prop.node.orgLevel)
: item.type === 'DEL'
? onClickDel(
prop.node.orgLevel,
prop.node.orgTreeId,
prop.node.orgRootId
)
: item.type === 'SORT'
? onClickSort(prop.node.orgRootId, prop.node.orgLevel)
: item.type === 'HISTORY'
? onClickHistory(
prop.node.orgLevel,
prop.node.orgTreeId
)
: null
"
>
<q-item-section avatar>
<q-icon :color="item.color" :name="item.icon" />
</q-item-section>
<div v-if="prop.node.orgLevel === 0">
<q-item-section
v-if="
item.type === 'EDIT' ||
item.type === 'DEL' ||
item.type === 'HISTORY' ||
item.type === 'SORT'
"
>
{{ item.label }}หน่วยงาน
</q-item-section>
<q-item-section v-else-if="item.type === 'ADD'">
{{ item.label }}ส่วนราชการ
</q-item-section>
<q-item-section v-else> {{ item.label }} </q-item-section>
</div>
<div v-else>
<q-item-section
v-if="
item.type === 'ADD' ||
item.type === 'EDIT' ||
item.type === 'DEL' ||
item.type === 'HISTORY' ||
item.type === 'SORT'
"
>{{ item.label }}วนราชการ</q-item-section
>
<q-item-section v-else>{{ item.label }}</q-item-section>
</div>
</q-item>
</q-list>
</q-menu>
</q-btn>
<q-btn
v-else
flat
dense
icon="mdi-dots-vertical"
class="q-pa-none q-ml-xs"
color="grey-13"
>
<q-menu>
<q-list
dense
v-for="(item, index) in listAdd.slice(5, 6)"
:key="index"
style="min-width: 100px"
>
<q-item
clickable
v-close-popup
@click="
onClickDetail(prop.node.orgTreeId, prop.node.orgLevel)
"
>
<q-item-section avatar>
<q-icon :color="item.color" :name="item.icon" />
</q-item-section>
<q-item-section>{{ item.label }}</q-item-section>
</q-item>
</q-list>
</q-menu>
</q-btn>
</template>
</q-tree>
</div>
</div>
</div>
<!-- เพมหนวยงาน -->
<DialogAgency
:modal="dialogAgency"
:close="onClickAgency"
v-model:orgLevel="orgLevel"
:fetchDataTree="props.fetchDataTree"
v-model:actionType="actionType"
:dataNode="dataNode"
:edit="edit"
/>
<!-- รายละเอยดโครงสราง -->
<DialogStructureDetail
v-model:structure-detail="dialogDetail"
v-model:treeId="treeId"
v-model:orgLevel="orgLevel"
/>
<DialogSortAgency
v-model:sort-agency="modalSortAgency"
v-model:data="dataSort"
:fetchDataTree="props.fetchDataTree"
v-model:type="type"
/>
<DialogHistory
v-model:history="modalHistory"
v-model:type="type"
v-model:org-id="orgId"
/>
</template>
<style scoped>
.tree-container {
overflow: auto;
height: 60vh;
border: 1px solid rgb(210, 210, 210);
border-radius: 10px;
}
</style>