提交 7b3de8a1 authored 作者: coderBryanFu's avatar coderBryanFu

修改工作日程表模块

......@@ -1084,7 +1084,8 @@ const processRankingData = rawData => {
// 新增字段
domains: item.domainList ? item.domainList.map(d => d.name) : [],
date: formattedDate,
member: item.keyMember || "-"
member: item.keyMember || "-",
province: item.province || ""
};
});
};
......
......@@ -148,7 +148,7 @@
<div class="warning">
<div class="warning-title">
<img src="./assets/warning.png" alt />
<span>新增排华联盟预警1</span>
<span>新增排华联盟预警</span>
</div>
<div class="warning-content">
<div class="content-item" v-for="(item, index) in warningList" :key="index">
......
......@@ -469,43 +469,45 @@ const handleIndicatorChange = indicator => {
{
name: "中国",
type: "line",
symbolSize: 10,
symbolSize: 8,
smooth: true,
itemStyle: {
color: "#CE4F51"
},
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{
offset: 0,
color: "rgb(206, 79, 81, .8)"
},
{
offset: 1,
color: "rgb(206, 79, 81, .3)"
}
])
},
// areaStyle: {
// color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
// {
// offset: 0,
// color: "rgb(206, 79, 81, .8)"
// },
// {
// offset: 1,
// color: "rgb(206, 79, 81, .3)"
// }
// ])
// },
data: chinaValues
},
{
name: "美国",
type: "line",
symbolSize: 10,
smooth: true,
symbolSize: 8,
itemStyle: {
color: "#055FC2"
},
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{
offset: 0,
color: "rgb(5, 95, 194,.8)"
},
{
offset: 1,
color: "rgb(5, 95, 194, .3)"
}
])
},
// areaStyle: {
// color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
// {
// offset: 0,
// color: "rgb(5, 95, 194,.8)"
// },
// {
// offset: 1,
// color: "rgb(5, 95, 194, .3)"
// }
// ])
// },
data: usaValues
}
];
......@@ -540,22 +542,25 @@ const lineOption = ref({
xAxis: {
type: "category",
boundaryGap: false,
minInterval: 1,
scale: true,
axisLine: {
lineStyle: {
color: "#ccc",
color: "#e0e0e0",
width: 1
}
},
axisTick: {
show: true,
show: false,
lineStyle: {
color: "#ccc"
}
},
axisLabel: {
color: "#ccc",
fontSize: 16,
fontWeight: 400
color: "#666",
fontSize: 13,
fontWeight: 500,
margin: 12
},
data: ["2021", "2022", "2023", "2024", "2025"]
},
......@@ -571,9 +576,9 @@ const lineOption = ref({
padding: [0, 0, 10, 0]
},
axisLine: {
show: false,
show: true,
lineStyle: {
color: "#ccc",
color: "#e0e0e0",
width: 1
}
},
......
......@@ -34,10 +34,10 @@ defineProps({
.overview-card {
height: 450px;
box-sizing: border-box;
border: 1px solid rgba(234, 236, 238, 1);
border: 1px solid var(--border-black-5);
border-radius: 10px;
box-shadow: 0px 0px 20px 0px rgba(25, 69, 130, 0.1);
background: rgba(255, 255, 255, 1);
background: var(--bg-white-100);
overflow: hidden;
.overview-card-header {
......
......@@ -25,7 +25,7 @@ const getWordCloudChart = (data = []) => {
// shape: 'star' // 星形
// shape: 'cardioid' // 心形
gridSize: 15, // 网格大小,影响词间距。
sizeRange: [10, 30], // 定义词云中文字大小的范围
sizeRange: [16, 36], // 定义词云中文字大小的范围
rotationRange: [0, 0],
rotationStep: 15,
drawOutOfBound: false, // 是否超出画布
......
......@@ -246,7 +246,7 @@
</template>
<script setup>
import { ref, onMounted, watch, computed } from "vue";
import { ref, onMounted, watch, computed, nextTick } from "vue";
import { getBillPoliContribution, getBillMainPoliContribution, getBillPersonPoliContribution } from "@/api/deepdig";
import setChart from "@/utils/setChart";
......@@ -488,6 +488,27 @@ const chart2Data = ref([]);
const chart2ColorList = ref(["#4096FF", "#FFA39E", "#ADC6FF", "#FFC069", "#B5F5EC", "#B37FEB", "#D6E4FF"]);
// 使用静态行业分布数据,用于“政治献金领域分布”模块展示
const useStaticIndustryData = true;
const staticChart2Data = [
{ name: "集成电路", value: 21 },
{ name: "能源", value: 18 },
{ name: "量子科技", value: 16 },
{ name: "航空航天", value: 14 },
{ name: "通信设备", value: 12 },
{ name: "生物科技", value: 11 },
{ name: "其他", value: 8 }
];
const staticAreaList = [
{ name: "集成电路", amount: 186000, insNum: 8 },
{ name: "能源", amount: 180000, insNum: 5 },
{ name: "量子科技", amount: 171000, insNum: 2 },
{ name: "航空航天", amount: 75000, insNum: 3 },
{ name: "通信设备", amount: 70000, insNum: 2 }
];
const sankeyColors = [
"#5470c6",
"#91cc75",
......@@ -617,7 +638,7 @@ const getMainPoliContribution = async () => {
const fullSourceList = ref([]);
const showAllSankeyData = ref(false);
const renderSankeyChart = () => {
const renderSankeyChart = async () => {
const sourceList = showAllSankeyData.value ? fullSourceList.value : fullSourceList.value.slice(0, 5);
if (sourceList.length > 0) {
......@@ -626,33 +647,39 @@ const renderSankeyChart = () => {
const totalAmount = sourceList.reduce((sum, item) => sum + (item.amount || 0), 0);
const orgNodes = sourceList.map((item, index) => ({
name: item.orgNameZh || item.orgName || `机构${index + 1}`,
value: item.amount,
itemStyle: {
color: sankeyColors[index % sankeyColors.length]
}
}));
const nodes = [
...orgNodes,
{
name: personName,
value: totalAmount,
label: { position: "left" },
itemStyle: {
color: "#FF1493"
color: "#34C38F"
}
},
...sourceList.map((item, index) => ({
name: item.orgNameZh,
value: item.amount,
itemStyle: {
color: sankeyColors[index % sankeyColors.length]
}
}))
];
const links = sourceList.map(item => ({
source: item.orgNameZhZh,
const links = sourceList
.map((item, index) => ({
source: item.orgNameZh || item.orgName || `机构${index + 1}`,
target: personName,
value: item.amount
}));
}))
.filter(item => !!item.source && !!item.target);
// `chart1` 容器由 v-if/v-else 动态渲染,必须等 DOM 挂载后再 init
await nextTick();
let chart1 = getSankeyChart(nodes, links);
setChart(chart1, "chart1");
} else {
await nextTick();
let chart1 = getSankeyChart([], []);
setChart(chart1, "chart1");
}
......@@ -678,25 +705,37 @@ const getPersonPoliContribution = async personId => {
if (res.code === 200 && res.data) {
personPoliContribution.value = res.data;
// 政治献金流向:始终使用真实接口数据渲染桑基图
fullSourceList.value = res.data.sourceList || [];
showAllSankeyData.value = false; // Reset to default (top 5)
renderSankeyChart();
// Update Industry List (Chart 2 and List)
// 政治献金领域分布:根据配置选择静态数据或接口数据
if (useStaticIndustryData) {
// 饼图数据(左侧圆环)
chart2Data.value = staticChart2Data;
const chart2Static = getPieChart(chart2Data.value, chart2ColorList.value);
setChart(chart2Static, "chart2");
// 右侧列表(Top5 领域)
areaList.value = staticAreaList.map(item => ({
name: item.name,
num: item.amount,
numtext: `$${item.amount.toLocaleString()}`,
insNum: item.insNum
}));
} else {
// 使用接口返回的行业分布
const industries = res.data.industryList || [];
// Update Chart 2 Data
chart2Data.value = industries.map(item => ({
name: item.industryName,
value: item.amount
}));
// Re-render Chart 2
let chart2 = getPieChart(chart2Data.value, chart2ColorList.value);
setChart(chart2, "chart2");
const chart2Dynamic = getPieChart(chart2Data.value, chart2ColorList.value);
setChart(chart2Dynamic, "chart2");
// Update List Data
// Sort by amount desc to ensure first item is max for progress bar
const sortedIndustries = [...industries].sort((a, b) => (b.amount || 0) - (a.amount || 0));
areaList.value = sortedIndustries.map(item => ({
......@@ -705,6 +744,7 @@ const getPersonPoliContribution = async personId => {
numtext: `$${(item.amount || 0).toLocaleString()}`,
insNum: item.orgNum
}));
}
} else {
personPoliContribution.value = [];
fullSourceList.value = [];
......@@ -712,8 +752,8 @@ const getPersonPoliContribution = async personId => {
chart2Data.value = [];
areaList.value = [];
let chart2 = getPieChart([], chart2ColorList.value);
setChart(chart2, "chart2");
const chart2Empty = getPieChart([], chart2ColorList.value);
setChart(chart2Empty, "chart2");
}
} catch (error) {
console.error(error);
......@@ -723,8 +763,8 @@ const getPersonPoliContribution = async personId => {
chart2Data.value = [];
areaList.value = [];
let chart2 = getPieChart([], chart2ColorList.value);
setChart(chart2, "chart2");
const chart2Error = getPieChart([], chart2ColorList.value);
setChart(chart2Error, "chart2");
}
};
......
......@@ -8,30 +8,87 @@ const getSankeyChart = (data = [], links = []) => {
},
series: {
type: 'sankey',
layout: 'none',
left: '1%',
right: '1%',
top: '5%',
bottom: '5%',
// 禁止鼠标拖拽/缩放平移,避免图表被交互改变
draggable: false,
roam: false,
left: 16,
right: 16,
top: 14,
bottom: 14,
nodeAlign: 'right', // 目标效果:人名贴右侧
emphasis: {
focus: 'adjacency'
},
nodeWidth: 50,
nodeGap: 2,
// 所有色块宽度增加三倍
nodeWidth: 54,
nodeGap: 10,
layoutIterations: 32,
lineStyle: {
color: 'source',
curveness: 0.5
color: 'rgba(0, 0, 0, 0.08)', // 浅灰“行背景带”的基色
opacity: 1,
curveness: 0.2
},
label: {
show: true,
formatter: function (params) {
return `${params.name} $${params.value.toLocaleString()}`;
return `${params.name}`;
},
position: 'right',
fontSize: 16,
color: '#555'
color: '#303133',
overflow: 'truncate',
width: 140
},
edgeLabel: {
show: true,
formatter: function (params) {
const val = params.value || 0;
return `$${Number(val).toLocaleString()}`;
},
color: '#303133',
fontSize: 16,
overflow: 'truncate',
width: 140,
align: 'center'
},
itemStyle: {
borderWidth: 0
},
nodeSort: 'descending',
levels: [
// depth = 0(机构节点)
{
depth: 0,
itemStyle: {
borderWidth: 0
},
label: {
position: 'right',
color: '#303133',
fontSize: 16,
overflow: 'truncate',
width: 140
}
},
// depth = 1(人物节点)
{
depth: 1,
itemStyle: {
color: '#34C38F'
},
label: {
// 人物名称移至色块左侧
position: 'left',
// 让文字最右侧紧贴绿色色块左侧
distance: 5,
color: '#303133',
fontSize: 16,
overflow: 'truncate',
width: 120,
align: 'right'
}
}
],
data: data,
links: links
}
......
......@@ -2049,6 +2049,7 @@ onMounted(async () => {
margin-top: 21px;
height: 450px;
display: flex;
gap:16px;
.box3 {
width: 792px;
......
......@@ -274,7 +274,7 @@
<el-row :gutter="20" style="width: 1600px; margin: 0 auto; height: 528px; margin-top: 64px">
<CustomTitle id="position3" title="数据总览" />
<el-col :span="24">
<custom-container title="发布频度" :titleIcon="box3Icon" height="450px">
<custom-container title="发布频度" :titleIcon="box3Icon" height="400px">
<template #default>
<div class="box3">
<div class="box3-content">
......
<template>
<div class="deep-mining" :class="{ deepMiningChartmode: isInChart }">
<div class="side-nav">
<div v-for="(item, index) in activeTab" :key="index" class="tab-item" :class="{ active: index === activeIndex }"
@click="activeIndex = index">
<div
v-for="(item, index) in activeTab"
:key="index"
class="tab-item"
:class="{ active: index === activeIndex }"
@click="activeIndex = index"
>
{{ item }}
<span v-if="index === activeIndex" class="arrow"></span>
</div>
......@@ -47,8 +52,13 @@
<span class="group-count">{{ group.count }}家</span>
</div>
<div class="group-children custom-scrollbar" v-show="group.expanded">
<div class="entity-item" v-for="item in group.children" :key="item.id"
:class="{ active: activeEntityId === item.id }" @click="selectEntity(item)">
<div
class="entity-item"
v-for="item in group.children"
:key="item.id"
:class="{ active: activeEntityId === item.id }"
@click="selectEntity(item)"
>
<div class="item-icon">
<img :src="defaultTitle" alt="" class="item-img" />
</div>
......@@ -63,12 +73,19 @@
<div class="right" @mouseenter="handleMouseEnter" @mouseleave="handleMouseLeave">
<div class="title-com custom-right-header">
<div class="toggle-group">
<div class="toggle-btn" :class="{ active: rightActiveTab === 'supplyChain' }"
@click="rightActiveTab = 'supplyChain'">
<div
class="toggle-btn"
:class="{ active: rightActiveTab === 'supplyChain' }"
@click="rightActiveTab = 'supplyChain'"
>
<img :src="rightActiveTab === 'supplyChain' ? icon01Active : icon01" alt="" />
<span>供应链</span>
</div>
<div class="toggle-btn" :class="{ active: rightActiveTab === 'equity' }" @click="rightActiveTab = 'equity'">
<div
class="toggle-btn"
:class="{ active: rightActiveTab === 'equity' }"
@click="rightActiveTab = 'equity'"
>
<img :src="rightActiveTab === 'equity' ? icon02Active : icon02" alt="" />
<span>股权</span>
</div>
......@@ -115,8 +132,8 @@ import {
getSingleSanctionEntitySupplyChain,
getSingleSanctionEntityEquity
} from "@/api/exportControlV2.0";
import RelationGraph from './components/RelationGraph.vue';
import AnalysisBox from '@/components/base/boxBackground/analysisBox.vue';
import RelationGraph from "./components/RelationGraph.vue";
import AnalysisBox from "@/components/base/boxBackground/analysisBox.vue";
const sanRecordId = ref("");
const activeTab = ref(["实体穿透分析"]);
......@@ -170,11 +187,11 @@ const handleMouseLeave = () => {
isInChart.value = false;
};
const handleNodeClick = (node) => {
const handleNodeClick = node => {
selectedNode.value = node;
};
const handleLayoutChange = (type) => {
const handleLayoutChange = type => {
controlActive.value = type;
if (type !== 2) {
isInChart.value = true;
......@@ -184,9 +201,8 @@ const handleLayoutChange = (type) => {
};
const updateGraphData = () => {
const data = rightActiveTab.value === 'supplyChain'
? singleSanctionEntitySupplyChainData.value
: singleSanctionEntityEquityData.value;
const data =
rightActiveTab.value === "supplyChain" ? singleSanctionEntitySupplyChainData.value : singleSanctionEntityEquityData.value;
if (!data) return;
......@@ -214,7 +230,7 @@ const updateGraphData = () => {
links.push({
source: `p-${item.id || index}`,
target: "0",
name: rightActiveTab.value === 'supplyChain' ? "供应商" : (item.type || "持股")
name: rightActiveTab.value === "supplyChain" ? "供应商" : item.type || "持股"
});
});
......@@ -231,14 +247,14 @@ const updateGraphData = () => {
links.push({
source: "0",
target: `c-${item.id || index}`,
name: rightActiveTab.value === 'supplyChain' ? "客户" : (item.type || "投资")
name: rightActiveTab.value === "supplyChain" ? "客户" : item.description || "投资"
});
});
graphData.value = { nodes, links };
};
const updateTreeData = (data) => {
const updateTreeData = data => {
if (!data) return;
treeData.value = {
......@@ -318,17 +334,17 @@ const getSingleSanctionEntityListRequest = async () => {
}
};
watch(rightActiveTab, async (newTab) => {
if (newTab === 'supplyChain') {
watch(rightActiveTab, async newTab => {
if (newTab === "supplyChain") {
await getSingleSanctionEntitySupplyChainRequest();
} else {
await getSingleSanctionEntityEquityRequest();
}
});
watch(activeEntityId, async (newId) => {
watch(activeEntityId, async newId => {
if (newId) {
if (rightActiveTab.value === 'supplyChain') {
if (rightActiveTab.value === "supplyChain") {
await getSingleSanctionEntitySupplyChainRequest();
} else {
await getSingleSanctionEntityEquityRequest();
......@@ -337,7 +353,7 @@ watch(activeEntityId, async (newId) => {
});
watch(is50PercentRule, async () => {
if (rightActiveTab.value === 'equity') {
if (rightActiveTab.value === "equity") {
await getSingleSanctionEntityEquityRequest();
}
});
......@@ -857,7 +873,6 @@ onMounted(async () => {
}
.title-com.custom-right-header {
.box,
.text {
display: none;
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论