<template>
<!-- 内容框 -->
<div class="stock-wrap">
<div class="header" @click="handleLinkOther">
<div class="logo" :style="{ backgroundColor: getRandomColor() }">
{{ baseInfo.companyName ? baseInfo.companyName.charAt(0) : "" }}
</div>
<div class="company-wrap">
<div class="com-name">
{{ baseInfo.companyName || "-" }}
</div>
<div class="status-wrap">
<div
v-for="(item, index) in baseInfo.tagsList"
:key="index"
class="status"
:class="getStatusClass(item, index)"
>
{{ item }}
</div>
</div>
</div>
</div>
<div id="appc" class="echarts" v-loading="loading"></div>
<div class="filter-box" @click="drawer = true">
<el-icon><Filter /></el-icon>
<div>筛选</div>
</div>
<el-drawer
v-model="drawer"
size="45%"
direction="rtl"
:before-close="handleClose"
header-class="echarts-chose-drawer-header"
>
<template #header>
<h4 class="fiter-title">筛选</h4>
</template>
<div class="slider-wrap" style="margin-top: -10px">
<div class="slider-item">
<div class="slider-title">股东持股比例</div>
<div class="slider-demo-block">
<div class="slider-w">
<el-slider
range
v-model="control.parent"
:show-tooltip="false"
@change="handleChange"
/>
<div class="show-tip">
<span>{{ control.parent[0] }}%</span>
<span>{{ control.parent[1] }}%</span>
</div>
</div>
<span class="btn" @click="handleSlier('parent')">不限</span>
</div>
</div>
<div class="slider-item">
<div class="slider-title">对外投资比例</div>
<div class="slider-demo-block">
<div class="slider-w">
<el-slider
range
v-model="control.child"
:show-tooltip="false"
@change="handleChange"
/>
<div class="show-tip">
<span>{{ control.child[0] }}%</span>
<span>{{ control.child[1] }}%</span>
</div>
</div>
<span class="btn" @click="handleSlier('child')">不限</span>
</div>
</div>
</div>
</el-drawer>
</div>
</template>
<script>
import * as $d3 from "d3";
import { dataTemp } from "./data";
import { reactive, toRaw } from "vue";
import {
listEnterpriseInforListAll,
listPartnerInfoAll,
listInvestInfoAll,
equityPenetrationChartQuery,
} from "@/api/userManage";
function filterTree1(node, control) {
if (node.parents && node.parents.length > 0) {
node.parents = node.parents.filter((item) => {
const percent = parseFloat(item.percent);
return percent >= control.parent[0] && percent <= control.parent[1];
});
if (node.parents && node.parents.length > 0) {
node.parents.map((item) => {
filterTree1(item);
});
}
}
}
function filterTree2(node, control) {
if (node.children && node.children.length > 0) {
node.children = node.children.filter((item) => {
const percent = parseFloat(item.percent);
return percent >= control.child[0] && percent <= control.child[1];
});
if (node.children && node.children.length > 0) {
node.children.map((item) => {
filterTree1(item);
});
}
}
}
function keep2Dot(percentStr) {
const percentNum = parseFloat(percentStr.replace("%", ""));
return percentNum.toFixed(2) + "%";
}
async function parentsTree(node, options = {}) {
const {
currentDepth = 1,
maxDepth = 3,
concurrency = 5,
onProgress,
} = options;
if (currentDepth >= maxDepth) return;
if (!node.parents || node.parents.length === 0) {
try {
const obj = await listPartnerInfoAll({ companyId: node.id });
if (obj.data) {
node.parents = obj.data.map((itemP, index) => {
return {
id: itemP.id,
name: itemP.investedCompanyName || "",
percent: itemP.stockName,
parents: null,
status: itemP.status,
econKind: itemP.econKind,
};
});
}
if (onProgress) onProgress(node, currentDepth);
} catch (error) {
console.error(`Failed to fetch parents for ${node.id}:`, error);
node.parents = null;
return;
}
}
const batches = [];
for (let i = 0; i < node.parents.length; i += concurrency) {
const batch = node.parents.slice(i, i + concurrency);
batches.push(batch);
}
for (const batch of batches) {
await Promise.all(
batch.map((child) =>
parentsTree(child, {
currentDepth: currentDepth + 1,
maxDepth,
concurrency,
onProgress,
})
)
);
}
}
async function childrenTree(node, options = {}) {
const {
currentDepth = 1,
maxDepth = 3,
concurrency = 5,
onProgress,
} = options;
if (currentDepth >= maxDepth) return;
if (!node.children || node.children.length === 0) {
try {
const obj = await listInvestInfoAll({ companyId: node.id });
if (obj.data) {
node.children = obj.data.map((itemP, index) => {
return {
id: itemP.investedCompanyId || itemP.companyId,
name: itemP.investedCompanyName || "",
percent: itemP.stockPercent,
children: null,
status: itemP.status,
econKind: itemP.econKind,
};
});
}
if (onProgress) onProgress(node, currentDepth);
} catch (error) {
console.error(`Failed to fetch children for ${node.id}:`, error);
node.children = null;
return;
}
}
const batches = [];
for (let i = 0; i < node.children.length; i += concurrency) {
const batch = node.children.slice(i, i + concurrency);
batches.push(batch);
}
for (const batch of batches) {
await Promise.all(
batch.map((child) =>
childrenTree(child, {
currentDepth: currentDepth + 1,
maxDepth,
concurrency,
onProgress,
})
)
);
}
}
function transformCompanyStructure(originalData) {
const result = {
id: "",
name: "",
children: [],
parents: [],
};
if (originalData.partnerInfoList && originalData.partnerInfoList.length > 0) {
result.parents = processPartnerList(originalData.partnerInfoList);
}
if (
originalData.foreignInvestmentList &&
originalData.foreignInvestmentList.length > 0
) {
result.children = processInvestmentList(originalData.foreignInvestmentList);
}
return result;
function processPartnerList(investments) {
return investments.map((investment) => {
const item = {
id: investment.pkeyNo || investment.id,
name: investment.stockName,
percent: investment.stockPercent
? keep2Dot(investment.stockPercent)
: "",
stockType: investment.stockType,
};
if (investment.children && investment.children.length > 0) {
item.parents = processPartnerList(investment.children);
}
return item;
});
}
function processInvestmentList(investments) {
return investments.map((investment) => {
const item = {
id: investment.investedCompanyId,
name: investment.investedCompanyName,
percent: investment.stockPercent
? keep2Dot(investment.stockPercent)
: "",
stockType: investment.stockType || "企业股东",
};
if (investment.children && investment.children.length > 0) {
item.children = processInvestmentList(investment.children);
}
return item;
});
}
}
export default {
name: "StockEcharts",
data() {
return {
drawer: false,
d3: $d3,
data: {},
dataInit: {},
companyId: "",
companyName: "",
companyIdSelf: "",
baseInfo: {},
loading: false,
control: {
parent: [0, 100],
child: [0, 100],
},
};
},
mounted() {
this.constructor();
document.title = "股权穿透图";
const query = this.$route.query;
const companyId = query.companyId;
const companyName = query.companyName;
if (companyId) {
this.companyId = decodeURIComponent(companyId);
this.companyName = decodeURIComponent(companyName);
} else {
this.companyId = "863e13b3db1654fadcb5a1789f4b5f18";
this.companyName = "小米";
}
const tagsList = [];
if (query.status) {
tagsList.push(decodeURIComponent(query.status.split("(")[0]));
}
if (query.econKind) {
tagsList.push(decodeURIComponent(query.econKind.split("(")[0]));
}
this.baseInfo = {
companyName: this.companyName,
id: this.companyId,
tagsList,
};
this.getData();
},
methods: {
handleChange() {
const MyData = JSON.parse(JSON.stringify(this.dataInit));
filterTree1(MyData, this.control);
filterTree2(MyData, this.control);
this.data = MyData;
this.drawChart({
type: "fold",
});
},
handleSlier(type) {
this.control[type] = [0, 100];
this.handleChange();
},
getData() {
this.loading = true;
equityPenetrationChartQuery(this.companyId)
.then((res) => {
const temp = transformCompanyStructure(res.data || {});
temp.id = this.companyId;
temp.name = this.companyName;
this.data = temp;
this.dataInit = JSON.parse(JSON.stringify(temp));
this.drawChart({
type: "fold",
});
})
.finally(() => {
this.loading = false;
});
},
constructor(options) {
this.el = document.getElementById("appc");
this.config = {
dx: 190,
dy: 80,
width: 0,
height: 0,
rectWidth: 170,
rectHeight: 40,
};
this.svg = null;
this.gAll = null;
this.gLinks = null;
this.gNodes = null;
this.tree = null;
this.rootOfDown = null;
this.rootOfUp = null;
this.scaleFactor = 1;
},
drawChart(options) {
this.originTreeData = this.data;
let host = this.d3.select(this.el);
let dom = host.node();
let domRect = dom.getBoundingClientRect();
this.config.width = domRect.width;
this.config.height = domRect.height;
let oldSvg = this.d3.select("svg");
if (!oldSvg.empty()) {
oldSvg.remove();
}
const svg = this.d3
.create("svg")
.attr("viewBox", () => {
let parentsLength = this.originTreeData.parents
? this.originTreeData.parents.length
: 0;
return [
-this.config.width / 2,
parentsLength > 0
? -this.config.height / 2
: -this.config.height / 3,
this.config.width,
this.config.height,
];
})
.style("user-select", "none")
.style("cursor", "move")
.attr("transform", `scale(${this.scaleFactor})`);
const gAll = svg.append("g").attr("id", "all");
svg
.call(
this.d3
.zoom()
.scaleExtent([0.2, 5])
.on("zoom", (e) => {
gAll.attr("transform", () => {
return `translate(${e.transform.x},${e.transform.y}) scale(${e.transform.k})`;
});
})
)
.on("dblclick.zoom", null);
this.gAll = gAll;
this.gLinks = gAll.append("g").attr("id", "linkGroup");
this.gNodes = gAll.append("g").attr("id", "nodeGroup");
this.tree = this.d3.tree().nodeSize([this.config.dx, this.config.dy]);
this.rootOfDown = this.d3.hierarchy(
this.originTreeData,
(d) => d.children
);
this.rootOfUp = this.d3.hierarchy(this.originTreeData, (d) => d.parents);
[this.rootOfDown.descendants(), this.rootOfUp.descendants()].forEach(
(nodes) => {
nodes.forEach((node) => {
node._children = node.children || null;
if (options.type === "all") {
node.children = node._children;
} else if (options.type === "fold") {
if (node.depth) {
node.children = null;
}
}
});
}
);
svg
.append("marker")
.attr("id", "markerOfDown")
.attr("markerUnits", "userSpaceOnUse")
.attr("viewBox", "0 -5 10 10")
.attr("refX", 55)
.attr("refY", 0)
.attr("markerWidth", 6)
.attr("markerHeight", 6)
.attr("orient", "90")
.attr("stroke-width", 2)
.append("path")
.attr("d", "M0,-5L10,0L0,5")
.attr("fill", "#C80F06");
svg
.append("marker")
.attr("id", "markerOfUp")
.attr("markerUnits", "userSpaceOnUse")
.attr("viewBox", "0 -5 10 10")
.attr("refX", -45)
.attr("refY", 0)
.attr("markerWidth", 6)
.attr("markerHeight", 6)
.attr("orient", "90")
.attr("stroke-width", 2)
.append("path")
.attr("d", "M0,-5L10,0L0,5")
.attr("fill", "#C80F06");
this.svg = svg;
this.update();
host.append(function () {
return svg.node();
});
},
updateNewData(e, d) {
listInvestInfoAll({
companyId: this.companyId,
}).then((res) => {
res.data;
if (res.data) {
d.children = res.data.map((itemP, index) => {
return {
id: itemP.companyId ? itemP.companyId + index : "tt" + index,
name: itemP.investedCompanyName || "",
percent: itemP.stockPercent,
children: [{}],
};
});
this.update(d);
}
});
},
update(source) {
if (!source) {
source = {
x0: 0,
y0: 0,
};
this.rootOfDown.x0 = 0;
this.rootOfDown.y0 = 0;
this.rootOfUp.x0 = 0;
this.rootOfUp.y0 = 0;
}
let nodesOfDown = this.rootOfDown.descendants().reverse();
let linksOfDown = this.rootOfDown.links();
let nodesOfUp = this.rootOfUp.descendants().reverse();
let linksOfUp = this.rootOfUp.links();
this.tree(this.rootOfDown);
this.tree(this.rootOfUp);
const myTransition = this.svg.transition().duration(500);
const node1 = this.gNodes
.selectAll("g.nodeOfDownItemGroup")
.data(nodesOfDown, (d) => {
return d.data.id;
});
const node1Enter = node1
.enter()
.append("g")
.attr("class", "nodeOfDownItemGroup")
.attr("transform", (d) => {
return `translate(${source.x0},${source.y0})`;
})
.attr("fill-opacity", 0)
.attr("stroke-opacity", 0)
.style("cursor", "pointer");
node1Enter
.append("rect")
.attr("width", (d) => {
if (d.depth === 0) {
return (d.data.name.length + 2) * 16;
}
return this.config.rectWidth;
})
.attr("height", (d) => {
if (d.depth === 0) {
return 30;
}
return this.config.rectHeight;
})
.attr("x", (d) => {
if (d.depth === 0) {
return (-(d.data.name.length + 2) * 16) / 2;
}
return -this.config.rectWidth / 2;
})
.attr("y", (d) => {
if (d.depth === 0) {
return -15;
}
return -this.config.rectHeight / 2;
})
.attr("rx", 5)
.attr("stroke-width", 1)
.attr("stroke", (d) => {
if (d.depth === 0) {
return "#C80F06";
}
return "#FEF1E7";
})
.attr("fill", (d) => {
if (d.depth === 0) {
return "#C80F06";
}
return "#FEF1E7";
})
.on("click", (e, d) => {
this.nodeClickEvent(e, d);
});
node1Enter
.append("text")
.attr("class", "main-title")
.attr("x", (d) => {
return 0;
})
.attr("y", (d) => {
if (d.depth === 0) {
return 5;
}
return -14;
})
.attr("text-anchor", (d) => {
return "middle";
})
.attr("dy", function (d) {
return "0.8em";
})
.text((d) => {
if (d.depth === 0) {
return d.data.name;
} else {
return d.data.name && d.data.name.length > 12
? d.data.name.substring(0, 12)
: d.data.name;
}
})
.attr("fill", (d) => {
if (d.depth === 0) {
return "#FFFFFF";
}
return "#000000";
})
.on("click", (e, d) => {
this.nodeClickEvent(e, d);
});
node1Enter
.append("text")
.attr("class", "sub-title")
.attr("x", (d) => {
return 0;
})
.attr("y", (d) => {
return 5;
})
.attr("text-anchor", (d) => {
return "middle";
})
.attr("dy", function (d) {
return "0.7em";
})
.text((d) => {
if (d.depth !== 0) {
let subTitle = d.data.name ? d.data.name.substring(12) : "";
if (subTitle.length > 10) {
return subTitle.substring(0, 10) + "...";
}
return subTitle;
}
});
node1Enter
.append("text")
.attr("class", "percent")
.attr("x", (d) => {
return 12;
})
.attr("y", (d) => {
return -27;
})
.text((d) => {
if (d.depth !== 0) {
return d.data.percent;
}
})
.on("click", (e, d) => {
this.nodeClickEvent(e, d);
});
const expandBtnG = node1Enter
.append("g")
.attr("class", "expandBtn")
.attr("transform", (d) => {
return `translate(${0},${this.config.rectHeight / 2})`;
})
.style("display", (d) => {
if (d.depth === 0) {
return "none";
}
if (!d._children) {
return "none";
}
})
.on("click", (e, d) => {
if (d.children) {
d._children = d.children;
d.children = null;
} else {
d.children = d._children;
}
this.update(d);
});
expandBtnG
.append("circle")
.attr("r", 8)
.attr("fill", "#C80F06")
.attr("cy", 8);
expandBtnG
.append("text")
.attr("text-anchor", "middle")
.attr("fill", "#ffffff")
.attr("y", 12)
.style("font-size", 16)
.style("font-family", "微软雅黑")
.text((d) => {
return d.children ? "-" : "+";
});
const link1 = this.gLinks
.selectAll("path.linkOfDownItem")
.data(linksOfDown, (d) => d.target.data.id);
const link1Enter = link1
.enter()
.append("path")
.attr("class", "linkOfDownItem")
.attr("d", (d) => {
let o = {
source: {
x: source.x0,
y: source.y0,
},
target: {
x: source.x0,
y: source.y0,
},
};
return this.drawLink(o);
})
.attr("fill", "none")
.attr("stroke", "#B8B8B8")
.attr("stroke-width", 1)
.attr("marker-end", "url(#markerOfDown)");
node1
.merge(node1Enter)
.transition(myTransition)
.attr("transform", (d) => {
return `translate(${d.x},${d.y})`;
})
.attr("fill-opacity", 1)
.attr("stroke-opacity", 1);
node1
.exit()
.transition(myTransition)
.remove()
.attr("transform", (d) => {
return `translate(${source.x0},${source.y0})`;
})
.attr("fill-opacity", 0)
.attr("stroke-opacity", 0);
link1.merge(link1Enter).transition(myTransition).attr("d", this.drawLink);
link1
.exit()
.transition(myTransition)
.remove()
.attr("d", (d) => {
let o = {
source: {
x: source.x,
y: source.y,
},
target: {
x: source.x,
y: source.y,
},
};
return this.drawLink(o);
});
nodesOfUp.forEach((node) => {
node.y = -node.y;
});
const node2 = this.gNodes
.selectAll("g.nodeOfUpItemGroup")
.data(nodesOfUp, (d) => {
return d.data.id;
});
const node2Enter = node2
.enter()
.append("g")
.attr("class", (d) => {
if (d.depth === 0) {
return "rootGroup";
}
return "nodeOfUpItemGroup";
})
.attr("transform", (d) => {
return `translate(${source.x0},${source.y0})`;
})
.attr("fill-opacity", 0)
.attr("stroke-opacity", 0)
.style("cursor", "pointer");
node2Enter
.append("rect")
.attr("width", (d) => {
if (d.depth === 0) {
return (d.data.name.length + 2) * 16;
}
return this.config.rectWidth;
})
.attr("height", (d) => {
if (d.depth === 0) {
return 30;
}
return this.config.rectHeight;
})
.attr("x", (d) => {
if (d.depth === 0) {
return (-(d.data.name.length + 2) * 16) / 2;
}
return -this.config.rectWidth / 2;
})
.attr("y", (d) => {
if (d.depth === 0) {
return -15;
}
return -this.config.rectHeight / 2;
})
.attr("rx", 5)
.attr("stroke-width", 1)
.attr("stroke", (d) => {
if (d.depth === 0) {
return "#C80F06";
}
return "#FEF1E7";
})
.attr("fill", (d) => {
if (d.depth === 0) {
return "#C80F06";
}
return "#FEF1E7";
})
.on("click", (e, d) => {
this.nodeClickEvent(e, d);
});
node2Enter
.append("text")
.attr("class", "main-title")
.attr("x", (d) => {
return 0;
})
.attr("y", (d) => {
if (d.depth === 0) {
return 5;
}
return -14;
})
.attr("text-anchor", (d) => {
return "middle";
})
.attr("dy", function (d) {
if (d.depth !== 0) {
return "1.0em";
} else {
}
})
.text((d) => {
if (d.depth === 0) {
return d.data.name;
} else {
return d.data.name && d.data.name.length > 12
? d.data.name.substring(0, 12)
: d.data.name;
}
})
.attr("fill", (d) => {
if (d.depth === 0) {
return "#FFFFFF";
}
return "#000000";
})
.on("click", (e, d) => {
this.nodeClickEvent(e, d);
});
node2Enter
.append("text")
.attr("class", "sub-title")
.attr("x", (d) => {
return 0;
})
.attr("y", (d) => {
return 5;
})
.attr("text-anchor", (d) => {
return "middle";
})
.attr("dy", function (d) {
if (d.depth !== 0) {
return "0.7em";
}
})
.text((d) => {
if (d.depth !== 0) {
let subTitle = d.data.name ? d.data.name.substring(12) : "";
if (subTitle.length > 10) {
return subTitle.substring(0, 10) + "...";
}
return subTitle;
}
})
.on("click", (e, d) => {
this.nodeClickEvent(e, d);
});
node2Enter
.append("text")
.attr("class", "percent")
.attr("x", (d) => {
return 12;
})
.attr("y", (d) => {
return 35;
})
.text((d) => {
if (d.depth !== 0) {
return d.data.percent;
}
});
const expandBtnG2 = node2Enter
.append("g")
.attr("class", "expandBtn")
.attr("transform", (d) => {
return `translate(${0},${-this.config.rectHeight / 2})`;
})
.style("display", (d) => {
if (d.depth === 0) {
return "none";
}
if (!d._children) {
return "none";
}
})
.on("click", (e, d) => {
if (d.children) {
d._children = d.children;
d.children = null;
} else {
d.children = d._children;
}
this.update(d);
});
expandBtnG2
.append("circle")
.attr("r", 8)
.attr("fill", "#C80F06")
.attr("cy", -8);
expandBtnG2
.append("text")
.attr("text-anchor", "middle")
.attr("fill", "#ffffff")
.attr("y", -3)
.style("font-size", 16)
.text((d) => {
return d.children ? "-" : "+";
});
const link2 = this.gLinks
.selectAll("path.linkOfUpItem")
.data(linksOfUp, (d) => d.target.data.id);
const link2Enter = link2
.enter()
.append("path")
.attr("class", "linkOfUpItem")
.attr("d", (d) => {
let o = {
source: {
x: source.x0,
y: source.y0,
},
target: {
x: source.x0,
y: source.y0,
},
};
return this.drawLink(o);
})
.attr("fill", "none")
.attr("stroke", "#B8B8B8")
.attr("stroke-width", 1)
.attr("marker-end", "url(#markerOfUp)");
node2
.merge(node2Enter)
.transition(myTransition)
.attr("transform", (d) => {
return `translate(${d.x},${d.y})`;
})
.attr("fill-opacity", 1)
.attr("stroke-opacity", 1);
node2
.exit()
.transition(myTransition)
.remove()
.attr("transform", (d) => {
return `translate(${source.x0},${source.y0})`;
})
.attr("fill-opacity", 0)
.attr("stroke-opacity", 0);
link2.merge(link2Enter).transition(myTransition).attr("d", this.drawLink);
link2
.exit()
.transition(myTransition)
.remove()
.attr("d", (d) => {
let o = {
source: {
x: source.x,
y: source.y,
},
target: {
x: source.x,
y: source.y,
},
};
return this.drawLink(o);
});
const expandButtonsSelection = this.d3.selectAll("g.expandBtn");
expandButtonsSelection
.select("text")
.transition()
.text((d) => {
return d.children ? "-" : "+";
});
this.rootOfDown.eachBefore((d) => {
d.x0 = d.x;
d.y0 = d.y;
});
this.rootOfUp.eachBefore((d) => {
d.x0 = d.x;
d.y0 = d.y;
});
},
drawLink({ source, target }) {
const halfDistance = (target.y - source.y) / 2;
const halfY = source.y + halfDistance;
return `M${source.x},${source.y} L${source.x},${halfY} ${target.x},${halfY} ${target.x},${target.y}`;
},
expandAllNodes() {
this.drawChart({
type: "all",
});
},
foldAllNodes() {
this.drawChart({
type: "fold",
});
},
nodeClickEvent(e, d) {
this.loading = true;
console.log("----------", d);
if (d.data && d.data.id && d.data.stockType === "企业股东") {
listEnterpriseInforListAll({ companyId: d.data.id }).then(
async (res) => {
this.companyIdSelf = d.data.id;
const data = res.data && res.data.length > 0 ? res.data[0] : "";
if (data) {
this.companyId = data.companyId;
this.companyName = data.companyName;
data.tagsList = [];
if (data.status) {
data.tagsList.push(data.status.split("(")[0]);
}
if (data.econKind) {
data.tagsList.push(data.econKind.split("(")[0]);
}
this.baseInfo = data;
this.getData();
} else {
ElMessage.warning("查询不到该公司信息");
this.loading = false;
}
}
);
} else {
ElMessage.warning("不能查询自然人股东信息");
this.loading = false;
}
},
getStatusClass(item) {
const status = {
存续: "status-active",
注销: "status-cancelled",
吊销: "status-revoked",
股份有限公司: "type-tag",
有限责任公司: "type-tag",
};
return status[item] || "";
},
getRandomColor() {
const colors = [
"#53C89C",
"#4EBCDE",
"#2E8AF0",
"#588BEA",
"#6875E4",
"#9370DB",
"#FC9682",
"#F5A882",
"#F8BF7F",
"#F5D678",
];
return colors[Math.floor(Math.random() * colors.length)];
},
handleLinkOther() {
wx.miniProgram.postMessage({
data: {
action: "customEvent",
payload: { key: "value" },
},
});
wx.miniProgram.redirectTo({
url:
"/pages-sub/CompanyDetails/CompanyDetails?companyId=" +
this.companyIdSelf,
});
},
},
};
</script>
<style lang="scss" scoped>
.stock-wrap {
overflow: hidden;
position: relative;
width: 100%;
height: 100%;
.header {
padding: 15px;
border-bottom: 1px solid #ececec;
display: flex;
.logo {
width: 43px;
height: 43px;
background: #63d5d2;
border-radius: 4px;
line-height: 40px;
font-size: 18px;
text-align: center;
margin-right: 6px;
color: #fff;
}
.com-name {
font-weight: bold;
font-size: 15px;
color: #333333;
margin-bottom: 6px;
}
.status-wrap {
display: flex;
.status {
height: 18px;
line-height: 18px;
font-size: 12px;
padding: 0 6px;
background: #ebf7f2;
border-radius: 2px;
color: #3bb27f;
margin-right: 5px;
&.status-active {
background: #ebf7f2;
color: #3bb27f;
}
&.status-revoked {
background: #fff1e4;
color: #ff830d;
}
&.status-cancelled {
background: #fff1e4;
color: #ff830d;
}
&.type-tag {
background: #e1ecff;
color: #0d86ff;
}
}
}
}
.echarts {
height: calc(100% - 80px);
}
.filter-box {
position: fixed;
bottom: 30px;
right: 20px;
width: 49px;
height: 49px;
background: #ffffff;
border-radius: 4px;
border: 1px solid #e5e5e5;
color: #333333;
text-align: center;
padding-top: 4px;
div {
text-align: center;
color: #333333;
font-size: 13px;
}
}
}
::v-deep .nodeOfDownItemGroup {
.main-title,
.sub-title {
font-size: 12px;
font-weight: 500;
fill: #ff8327;
}
.percent {
font-size: 12px;
font-weight: 500;
fill: #666666;
}
}
::v-deep .nodeOfUpItemGroup {
.main-title,
.sub-title {
font-size: 12px;
font-weight: 500;
fill: #ff8327;
}
.percent {
font-size: 12px;
font-weight: 500;
fill: #666666;
}
}
::v-deep .rootGroup {
.main-title {
font-size: 12px;
font-weight: 500;
fill: #fff;
}
}
.fiter-title {
text-align: center;
font-size: 15px;
}
</style>
<style lang="scss" scoped>
::v-deep .el-drawer {
&.rtl {
border-radius: 8px 0 0 8px;
}
}
::v-deep .echarts-chose-drawer-header {
&.el-drawer__header {
margin-bottom: 0px;
padding: 0px 20px;
border-bottom: 1px solid #ececec;
.fiter-title {
margin: 10px;
color: #333;
font-weight: 500;
}
.el-icon {
color: #333;
}
}
}
::v-deep .slider-item {
&:last-of-type {
margin-top: 15px;
}
.slider-title {
font-size: 14px;
font-weight: 500;
}
.slider-demo-block {
display: flex;
.slider-w {
flex: 1;
.show-tip {
display: flex;
justify-content: space-between;
font-size: 12px;
color: #999999;
}
}
}
.btn {
width: 68px;
height: 30px;
background: #f6f6f6;
border-radius: 4px;
font-size: 12px;
line-height: 30px;
text-align: center;
display: block;
margin-left: 25px;
}
.el-slider__button {
border: 2px solid #fff;
position: relative;
box-shadow: 0px 0px 10px 0px rgba(152, 102, 93, 0.3);
&::after {
content: "";
position: absolute;
width: 8px;
height: 8px;
background: #c80f06;
top: 50%;
left: 50%;
border-radius: 50%;
transform: translateX(-50%) translateY(-50%);
}
}
.el-slider__bar {
background-color: #c80f06;
}
}
</style>
export const dataTemp = {
id: "abc1005",
name: "山东吠舍科技有限责任公司",
children: [
{
id: "abc1006",
name: "山东第一首陀罗科技服务有限公司",
percent: "100%",
},
{
id: "abc1007",
name: "山东第二首陀罗程技术有限公司",
percent: "100%",
},
{
id: "abc1008",
name: "山东第三首陀罗光伏材料有限公司",
percent: "100%",
},
{
id: "abc1009",
name: "山东第四首陀罗科技发展有限公司",
percent: "100%",
children: [
{
id: "abc1010",
name: "山东第一达利特瑞利分析仪器有限公司",
percent: "100%",
children: [
{
id: "abc1011",
name: "山东瑞利的子公司一",
percent: "80%",
children: [
{
id: "a1",
name: "aaaaa",
percent: "80%",
},
{
id: "a2",
name: "bbbbb",
percent: "80%",
},
],
},
{
id: "abc1012",
name: "山东瑞利的子公司二",
percent: "90%",
},
{
id: "abc1013",
name: "山东瑞利的子公司三",
percent: "100%",
},
],
},
],
},
{
id: "abc1014",
name: "山东第五首陀罗电工科技有限公司",
percent: "100%",
children: [
{
id: "abc1015",
name: "山东第二达利特低自动化设备有限公司",
percent: "100%",
children: [
{
id: "abc1016",
name: "山东敬业的子公司一",
percent: "100%",
},
{
id: "abc1017",
name: "山东敬业的子公司二",
percent: "90%",
},
],
},
],
},
{
id: "abc1020",
name: "山东第六首陀罗分析仪器(集团)有限责任公司",
percent: "100%",
children: [
{
id: "abc1021",
name: "山东第三达利特分气体工业有限公司",
},
],
},
],
parents: [
{
id: "abc2001",
name: "山东刹帝利集团有限责任公司",
percent: "60%",
parents: [
{
id: "abc2000",
name: "山东婆罗门集团有限公司",
percent: "100%",
},
],
},
{
id: "abc2002",
name: "吴小远",
percent: "40%",
parents: [
{
id: "abc1010",
name: "山东第一达利特瑞利分析仪器有限公司",
percent: "100%",
parents: [
{
id: "abc1011",
name: "山东瑞利的子公司一",
percent: "80%",
},
{
id: "abc1012",
name: "山东瑞利的子公司二",
percent: "90%",
},
{
id: "abc1013",
name: "山东瑞利的子公司三",
percent: "100%",
},
],
},
],
},
{
id: "abc2003",
name: "测试数据",
percent: "40%",
},
],
};