<template> <div> <v-chart :option="option" style="height: 85dvh; width: 100%" ref="chart" @click="handleNodeClick" @dblclick="showModalTree" lazy ></v-chart> </div> </template> <script> // import { random } from "lodash"; // import HttpService from "@services/httpService"; // import { use } from "echarts/core"; import { TreeChart } from "echarts/charts"; import { TooltipComponent, ToolboxComponent } from "echarts/components"; import { CanvasRenderer } from "echarts/renderers"; import searchApis from "~/apis/searchApi"; use([TooltipComponent, TreeChart, CanvasRenderer, ToolboxComponent]); export default { props: { dataChart: { default() { return []; }, type: Array, }, }, data() { return { treeCounter: 1, showButtons: false, showDiv: false, buttonAction: "", addText: "", editText: "", // httpService: undefined, mainList: [], itemData: {}, tooltipText: "", position: { top: "0px", left: "0px" }, option: { tooltip: { trigger: "item", triggerOn: "mousemove", }, toolbox: { show: true, itemSize: 15, }, series: [ { type: "tree", id: 0, name: "tree1", data: [], top: "0%", left: "40%", bottom: "30%", right: "8%", while: "100%", height: "100%", zoom: 1, symbolSize: 10, edgeForkPosition: "30%", initialTreeDepth: 1, edgeShape: "curve", orient: "RL", label: { color: "#fff", fontFamily: "sahel", fontSize: 15, align: "center", position: "left", verticalAlign: "middle", borderRadius: 3, padding: 6, borderWidth: 2, // shadowColor: "rgba(51, 41, 41, 1)", // shadowBlur: 2.5, // shadowOffsetX: 2, // shadowOffsetY: 2, width: 140, height: 12, backgroundColor: "#fff", distance: 80, formatter: function (params) { const maxLength = 15; const text = params.name.length > maxLength ? params.name.substring(0, maxLength) + "..." : params.name; return text; }, }, leaves: { label: { distance: 80, color: "#fff", fontFamily: "sahel", fontSize: 15, align: "center", position: "left", verticalAlign: "middle", borderRadius: 3, padding: 6, borderWidth: 2, // shadowColor: "rgba(51, 41, 41, 1)", // shadowBlur: 2.5, // shadowOffsetX: 2, // shadowOffsetY: 2, width: 140, height: 12, backgroundColor: "#fff", formatter: function (params) { const maxLength = 15; const text = params.name.length > maxLength ? params.name.substring(0, maxLength) + "..." : params.name; return text; }, }, }, lineStyle: { curveness: 0.6, }, emphasis: { focus: "relative", blurScope: "coordinateSystem", }, expandAndCollapse: true, animationDuration: 550, animationDurationUpdate: 750, symbolOffset: [30, 0], }, ], }, colors: [ "#5470C6", "#91CC75", "#FAC858", "#EE6666", "#37a2da", "#3BA272", "#FC8452", "#9A60B4", "#EA7CCC", "#F59F00", ], currentIndex: 0, }; }, watch: { dataChart(newValue) { this.option.series[0].data = newValue; }, }, // beforeMount() { // this.httpService = new HttpService(); // }, mounted() { this.option.series[0].data = this.dataChart; }, methods: { /** * این تابع مسئول دریافت و نمایش آیتمهای موجود زیر یک آیتم پدر است. */ handleNodeClick(params) { const dataNode = params.data; // if (dataNode.children && dataNode.children.length > 0) { // this.handleNodeWithChildren(dataNode); // } // this.collapseAllExceptSelected(params); if (dataNode.children.length > 1) { return; } try { this.getChildrenNode(dataNode.id).then((list) => { list.forEach((element, index) => { const dataColor = dataNode.label.backgroundColor; var node = { item: element, text: element.title, name: element.title, id: element.id, pid: dataNode.id, collapsed: null, children: [], //children: element.children > 0 ? [1] : [], label: { backgroundColor: dataColor, }, itemStyle: { color: dataColor, }, }; // // وقتی دادههای جدید اضافه میشود، 1 را حذف میکنیم // if (dataNode.children.length === 1 && dataNode.children[0] === 1) { // dataNode.children.splice(0, 1); // حذف 1 // } dataNode.children.push(node); if (dataNode.id === 0) { this.option.series[0].data[0].children.push(node); } else { this.addChildToParent( this.option.series[0].data[0], dataNode.id, node ); } }); }); } catch (error) { console.error("Error fetching children nodes:", error); } }, // collapseAllExceptSelected(params) { // console.log(params.data.id) // const collapseNode = (node) => { // if (typeof node === "object" && node !== null) { // if (node.id !== params.data.id) { // node.collapsed = true; // } else { // node.collapsed = false; // } // if (Array.isArray(node.children)) { // node.children.forEach(collapseNode); // } // } // }; // this.option.series[0].data.forEach(collapseNode); // this.$refs.chart.setOption(this.option); // }, /** * این تابع مسئول دریافت لیست آیتمهای زیر یک آیتم پدر از سرور است. * @param {string} parentId - شناسه آیتم پدر * @returns {Promise} - لیست آیتمهای زیر آیتم پدر */ async getChildrenNode(parentId = 0) { const payload = { projectid: this.dataChart[0].projectId, parent: parentId, sortby: "id", offset: 0, limit: 100, listtype: 0, }; let url = searchApis.chart.tree; // ارسال درخواست به سرور و بازگشت پاسخ به صورت Promise try { const { $api } = useNuxtApp(); return await $api(url, { method: "post", baseURL: baseUrl(), body: payload, }); } catch (err) {} // return await this.httpService // .formDataRequest(url, payload) // .then((res) => { // return res.data; // }); }, /** * این تابع مسئول اضافه کردن یک آیتم فرزند به آیتم پدر میباشد. * @param {Object} node - آیتم پدر * @param {string} parentId - شناسه آیتم پدر * @param {Object} newChild - آیتم فرزند جدید * @returns {boolean} - مقدار منطقی True در صورت موفقیت آمیز بودن اضافه کردن، در غیر این صورت False */ addChildToParent(node, parentId, newChild) { if (node.id === parentId) { node.children.push(newChild); return true; } if (node.children) { for (let child of node.children) { if (this.addChildToParent(child, parentId, newChild)) { return true; } } } return false; }, showModalTree(event) { const itemSelected = { name: event.name, y: event.value }; this.$emit("list", itemSelected); }, }, }; </script> <style lang="scss"> .tooltip-button { button { color: #dee2e6 !important; &:hover { color: black !important; } } } .reject-button { color: #dee2e6 !important; &:hover { color: rgb(231, 10, 10) !important; } } .accept-button { color: #dee2e6 !important; &:hover { color: rgb(37, 223, 12) !important; } } </style>