提交 f3a1fe29 authored 作者: huhuiqing's avatar huhuiqing

Merge branch 'master' of http://8.140.26.4:10003/caijian/risk-monitor into dev_hhq

# Conflicts: # src/views/ZMOverView/components/fourSuppress/components/allGovernment/index.vue # src/views/ZMOverView/components/gameProfile/Timeline.vue # src/views/ZMOverView/components/gameProfile/index.vue
{
"name": "think-tank",
"name": "zm-system",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "think-tank",
"name": "zm-system",
"version": "1.0.0",
"license": "MIT",
"dependencies": {
......
import request from "@/api/request.js";
// 全政府-获取美国政府部门制裁数据
/**
* @header token
*/
export function getAllGovernmentList() {
return request({
method: 'GET',
url: `/api/rivalryIndex/governmentSanctionsData`
})
}
// 全政府-获取美对华制裁措施数量趋势
/**
* @header token
* @param {Object} params
* @param {String} params.field // 领域
* @param {String} params.monthNum = 12 // 月份数
* @param {String} params.orgId // 机构ID
* @param {String} params.sanType // 制裁手段
*/
export function getUSChinaSanctionTrend(params) {
return request({
method: 'GET',
url: `/api/rivalryIndex/sanctionsQuantitativeTrend`,
params
})
}
// 全政府-美政府部门打压遏制最新动态
/**
* @header token
*/
export function getUSGovernmentLatestDynamic() {
return request({
method: 'GET',
url: `/api/rivalryIndex/governmentSanctionsDynamics`
})
}
// 全政府-美政府部门联合制裁排行
/**
* @header token
*/
export function getUSGovernmentJointSanctionRank() {
return request({
method: 'GET',
url: `/api/rivalryIndex/governmentJointSanctionsRanking`
})
}
// 全政府-美政府部门对我打压遏制时间线
/**
* @header token
* @param {Object} params
* @param {String} params.currentPage = 1 // 当前页
* @param {String} params.pageSize = 1000 // 每页数量
*/
export function getUSGovernmentSanctionHistory(params) {
return request({
method: 'GET',
url: `/api/rivalryIndex/getSanctionProcess`,
params
})
}
......@@ -3,48 +3,49 @@ import request from "@/api/request.js";
// 全领域统计
export function getAllDomainCount() {
return request({
method: 'GET',
url: `/api/rivalryIndexV2/AllDomainCount`,
})
return request({
method: "GET",
url: `/api/rivalryIndexV2/AllDomainCount`
});
}
// 美对华制裁措施数量趋势
export function getDomainContainmentTrend() {
return request({
method: 'GET',
url: `/api/rivalryIndexV2/DomainContainmentTrend`,
})
export function getDomainContainmentTrend(byYOrM = "按月统计") {
return request({
method: "GET",
url: `/api/rivalryIndexV2/DomainContainmentTrend?byYOrM=${byYOrM}`
});
}
// 最新动态
export function getTechnologyGameAnalysis() {
return request({
method: 'GET',
url: `/api/rivalryIndexV2/TechnologyGameAnalysis`,
})
// 中美科技博弈分析
export function getTechnologyGameAnalysis(domain = 1) {
return request({
method: "GET",
url: `/api/rivalryIndexV2/TechnologyGameAnalysis?domain=${domain}`
});
}
// 领域打压遏制排行
/**
* @param {currentPage, pageSize}
* @param {currentPage, pageSize}
*/
export function getDomainContainmentRanking() {
return request({
method: 'GET',
url: `/api/rivalryIndexV2/DomainContainmentRanking`,
})
export function getDomainContainmentRanking(ContainmentOrg = "对我打压机构", Domains = "") {
return request({
method: "GET",
url: !!Domains
? `/api/rivalryIndexV2/DomainContainmentRanking?ContainmentOrg=${ContainmentOrg}&Domains=${Domains}`
: `/api/rivalryIndexV2/DomainContainmentRanking?ContainmentOrg=${ContainmentOrg}`
});
}
// 领域打压遏制时间线
/**
* @param {currentPage, pageSize}
* @param {currentPage, pageSize}
*/
export function getDomainContainmentTimeline(params) {
return request({
method: 'GET',
url: `/api/rivalryIndexV2/DomainContainmentTimeline`,
params
})
return request({
method: "GET",
url: `/api/rivalryIndexV2/DomainContainmentTimeline`,
params
});
}
//新闻速览
import newsBrief from "@/views/newsBrief/index.vue"
import newsBrief from "@/views/newsBrief/index.vue";
// 新闻事件分析
import NewsAnalysis from "@/views/newsAnalysis/index.vue";
const newsRoutes = [
//新闻速览页面路由
{
path: "/newsBrief",
name: "newsBrief",
component: newsBrief,
meta: {
title: "新闻速览"
}
},
//新闻速览页面路由
{
path: "/newsBrief",
name: "newsBrief",
component: newsBrief,
meta: {
title: "新闻速览"
}
},
// 新闻事件分析
{
path: "/newsAnalysis",
name: "newsAnalysis",
component: NewsAnalysis,
meta: {
title: "新闻事件分析"
}
},
// 新闻事件分析
{
path: "/newsAnalysis",
name: "newsAnalysis",
component: NewsAnalysis,
meta: {
title: "新闻事件分析"
}
}
];
]
export default newsRoutes
\ No newline at end of file
export default newsRoutes;
......@@ -199,7 +199,7 @@
</template>
<script setup>
import { ref, computed, onMounted } from "vue";
import { ref, computed, onMounted, watch } from "vue";
import setChart from "@/utils/setChart";
import getMultiLineChart from "./multiLineChart";
import leftBtn from "../../assets/left-btn.png";
......@@ -289,6 +289,61 @@ const timelineList = ref([
}
]);
// 处理时间线数据的方法
const processTimelineData = rawData => {
if (!rawData || !Array.isArray(rawData) || rawData.length === 0) {
return [];
}
return rawData.map(item => {
// 将日期格式转换为 "YYYY年 M月" 格式
const eventDate = item.eventDate ? new Date(item.eventDate) : null;
const formattedDate = eventDate ? `${eventDate.getFullYear()}${eventDate.getMonth() + 1}月` : "";
// 提取领域标签
const tags = [];
if (item.eventDomainList && Array.isArray(item.eventDomainList)) {
item.eventDomainList.forEach(domain => {
if (domain.domainName) {
tags.push(domain.domainName);
}
});
}
return {
date: formattedDate,
tags: tags,
title: item.eventName || "",
content: item.eventDesc || "",
info: `${item.eventDate || ""} · ${item.eventType || ""}`,
// 保留原始数据字段
eventId: item.eventId,
eventOrg: item.eventOrg,
eventType: item.eventType,
eventCountryImg: item.eventCountryImg,
eventDomainList: item.eventDomainList
};
});
};
// 获取领域遏制时间线数据
const handleGetDomainContainmentTimeline = async () => {
try {
const res = await getDomainContainmentTimeline();
console.log("美对我领域打压遏制时间线", res);
if (res.code === 200 && res.data) {
// 处理返回的数据结构
const processedData = processTimelineData(res.data);
timelineList.value = processedData.length > 9 ? processedData.slice(0, 9) : processedData;
}
} catch (error) {
console.error("获取美对我领域打压遏制时间线失败:", error);
// 设置默认空数组
timelineList.value = [];
}
};
const maxPerRow = 3;
const nodeGapX = 450;
const rowHeight = 215;
......@@ -419,6 +474,7 @@ const svgWidth = computed(() => {
const svgHeight = computed(() => {
const rows = Math.ceil(timelineList.value.length / maxPerRow);
console.log("看下高度", rows);
return startY + rows * rowHeight;
});
......@@ -606,6 +662,77 @@ const box5Data = ref({
]
});
const handleGetDomainContainmentTrend = async () => {
try {
const res = await getDomainContainmentTrend();
console.log("美对华领域打压遏制数量趋势", res);
if (res.code === 200 && res.data) {
// 处理返回的数据结构,按照 mockdata.json 中的格式
const processedData = processDomainTrendData(res.data);
box5Data.value = processedData;
// 更新图表
let Chart = getMultiLineChart(box5Data.value);
setChart(Chart, "chartRef");
}
} catch (error) {
console.error("获取美对华领域打压遏制数量趋势失败:", error);
}
};
// 处理领域趋势数据的方法
const processDomainTrendData = rawData => {
// 提取所有的月份作为标题
const titles = rawData.map(item => item.yearOrMonth);
// 收集所有不重复的领域名称
const domainNamesSet = new Set();
rawData.forEach(item => {
item.domainList.forEach(domain => {
domainNamesSet.add(domain.domainName);
});
});
const domainNames = Array.from(domainNamesSet);
// 定义颜色映射
const colorMap = {
人工智能: "#E34D59",
新一代通信网络: "#FF9F1C",
: "#FFB3B3",
生物科技: "#00A79D",
量子科技: "#7B61FF",
先进制造: "#363B42",
新能源: "#2BA471",
太空: "#3762F0",
集成电路: "#0052D9",
新材料: "#FFD900",
航空航天: "#3762F0",
海洋: "#76D1FF",
深海: "#002060",
其他: "#A6A6A6"
};
// 生成数据系列
const dataSeries = domainNames.map(domainName => {
const values = rawData.map(monthData => {
const domainItem = monthData.domainList.find(d => d.domainName === domainName);
return domainItem ? domainItem.domainNum : 0;
});
return {
name: domainName,
color: colorMap[domainName] || `#${Math.floor(Math.random() * 16777215).toString(16)}`, // 如果没有预定义颜色,则随机生成
value: values
};
});
return {
title: titles,
data: dataSeries
};
};
const newsList = ref([
{
tags: ["航空航天", "能源"],
......@@ -700,6 +827,57 @@ const getProgressWidth = count => {
return (count / maxCount) * 100 + "%";
};
// 处理排名数据的方法
const processRankingData = rawData => {
if (!rawData || !Array.isArray(rawData) || rawData.length === 0) {
return [];
}
return rawData.map(item => {
return {
name: item.orgName || "",
count: item.orgCount || 0,
orgPicture: item.orgPicture // 保留原始图片字段,以防后续需要使用
};
});
};
const rankTypeMap = {
institution: "对我打压机构",
enterprise: "受打压企业",
school: "受打压院校"
};
// 获取领域遏制排名数据
const handleGetDomainContainmentRanking = async () => {
try {
console.log("获取领域遏制排名数据", rankTypeMap[rankType.value], selectedField.value);
const res = await getDomainContainmentRanking(
rankTypeMap[rankType.value],
!!selectedField.value ? selectedField.value : ""
);
console.log("获取领域遏制排名数据", rankTypeMap[rankType.value], selectedField.value);
console.log("美对华领域打压遏制排行", res);
if (res.code === 200 && res.data) {
// 处理返回的数据结构
const processedData = processRankingData(res.data);
rankList.value = processedData;
}
} catch (error) {
console.error("获取美对华领域打压遏制排行失败:", error);
// 设置默认空数组
rankList.value = [];
}
};
// 监听rankType变化, 调用获取领域遏制排名数据方法
watch(rankType, handleGetDomainContainmentRanking);
// 监听selectedField变化, 调用获取领域遏制排名数据方法
watch(selectedField, handleGetDomainContainmentRanking);
const currentIndex = ref(0);
const next = () => {
if (currentIndex.value < buttonsData.value.length - 5) {
......@@ -714,10 +892,13 @@ const prev = () => {
};
onMounted(() => {
let Chart = getMultiLineChart(box5Data.value);
setChart(Chart, "chartRef");
// let Chart = getMultiLineChart(box5Data.value);
// setChart(Chart, "chartRef");
handleGetDomainContainmentTrend();
handleGetAllDomainCount();
handleGetDomainContainmentRanking();
handleGetDomainContainmentTimeline();
});
</script>
......@@ -1461,4 +1642,3 @@ onMounted(() => {
border-color: rgb(59, 65, 75) !important;
}
</style>
{
"code": 200,
"message": "操作成功",
"success": true,
"data": [
{
"eventType": "行政令",
"eventName": "为了美国和委内瑞拉人民的利益保障委内瑞拉的石油收入",
"eventDesc": null,
"eventId": "248914",
"eventDomainList": [
{
"domainId": "1",
"domainName": "人工智能"
},
{
"domainId": "3",
"domainName": "新一代通信网络"
}
],
"eventOrgName": null,
"eventDate": "2026-01-10"
},
{
"eventType": "行政令",
"eventName": null,
"eventDesc": null,
"eventId": "248863",
"eventDomainList": [
{
"domainId": "8",
"domainName": "先进制造"
},
{
"domainId": "9",
"domainName": "新材料"
}
],
"eventOrgName": null,
"eventDate": "2026-01-09"
},
{
"eventType": "行政令",
"eventName": "使美国退出与美国利益相悖的国际组织、公约、条约",
"eventDesc": null,
"eventId": "249004",
"eventDomainList": [
{
"domainId": "2",
"domainName": "生物科技"
},
{
"domainId": "4",
"domainName": "量子科技"
},
{
"domainId": "5",
"domainName": "新能源"
},
{
"domainId": "3",
"domainName": "新一代通信网络"
}
],
"eventOrgName": null,
"eventDate": "2026-01-08"
},
{
"eventType": "行政令",
"eventName": "在国防合同中优先考虑作战人员",
"eventDesc": null,
"eventId": "248915",
"eventDomainList": [
{
"domainId": "99",
"domainName": "其他"
},
{
"domainId": "8",
"domainName": "先进制造"
},
{
"domainId": "10",
"domainName": "航空航天"
}
],
"eventOrgName": null,
"eventDate": "2026-01-08"
},
{
"eventType": "行政令",
"eventName": "大西洋高度洄游物种;商业性大西洋黑鼻鲨和娱乐性大西洋鲨鱼渔业管理措施的修订",
"eventDesc": "NMFS提议对商业和休闲大西洋鲨鱼渔业进行几项改革。具体来说,NMFS正在考虑取消大西洋地区黑鼻鲨管理边界,修改商业保留限额...",
"eventId": "163447",
"eventDomainList": [
{
"domainId": "14",
"domainName": "核"
},
{
"domainId": "7",
"domainName": "海洋"
}
],
"eventOrgName": null,
"eventDate": "2026-01-05"
},
{
"eventType": "行政令",
"eventName": "关于Hiefo Corporation收购Emcore Corporation部分资产",
"eventDesc": null,
"eventId": "248916",
"eventDomainList": [
{
"domainId": "3",
"domainName": "新一代通信网络"
},
{
"domainId": "8",
"domainName": "先进制造"
},
{
"domainId": "6",
"domainName": "集成电路"
}
],
"eventOrgName": null,
"eventDate": "2026-01-03"
},
{
"eventType": "行政令",
"eventName": "汽车贷款利息扣除",
"eventDesc": "本文件包含关于某些纳税人扣除高达10,000美元的合格乘用车贷款利息的拟议法规。本文件还包含关于新信息报告的拟议法规...",
"eventId": "163443",
"eventDomainList": [
{
"domainId": "13",
"domainName": "太空"
},
{
"domainId": "14",
"domainName": "核"
}
],
"eventOrgName": null,
"eventDate": "2026-01-02"
},
{
"eventType": "行政令",
"eventName": "品牌处方药费用法规的法定更新",
"eventDesc": "本文件建议修订有关对从事制造或进口某些品牌处方药业务的相关实体征收年费的法规。为了应对覆盖缺口折扣的替代...",
"eventId": "163444",
"eventDomainList": [
{
"domainId": "2",
"domainName": "生物科技"
},
{
"domainId": "3",
"domainName": "新一代通信网络"
}
],
"eventOrgName": null,
"eventDate": "2026-01-02"
},
{
"eventType": "337",
"eventName": "外国制造的半导体器件及其下游产品和组件",
"eventDesc": "美国ITC发布对外国制造的半导体器件及其下游产品和组件的337部分终裁",
"eventId": "111",
"eventDomainList": [
{
"domainId": "1",
"domainName": "人工智能"
},
{
"domainId": "5",
"domainName": "新能源"
}
],
"eventOrgName": "美国商务部",
"eventDate": "2026-01-01"
},
{
"eventType": "行政令",
"eventName": "美国东北部的渔业;大西洋冲浪蛤和海洋圆蛤渔业管理计划修正案21",
"eventDesc": "NMFS宣布,中大西洋渔业管理委员会已提交大西洋冲浪蛤和海洋圆蛤渔业管理计划第21号修正案,供商务部长审查和批准。我们正在征求意见...",
"eventId": "163426",
"eventDomainList": [
{
"domainId": "7",
"domainName": "海洋"
},
{
"domainId": "3",
"domainName": "新一代通信网络"
}
],
"eventOrgName": null,
"eventDate": "2025-12-29"
}
]
}
\ No newline at end of file
......@@ -4,7 +4,7 @@
<div class="main-content">
<div class="cards-mask">
<div class="cards-container" :style="{ transform: `translateX(-${currentIndex * (307 + 16)}px)` }">
<div v-for="(card, index) in cardList" :key="index" class="government-card">
<div v-for="(card, index) in cardList" :key="index" class="government-card" @click="handleCardClick(card)">
<div class="card-bg" :style="{ backgroundImage: `url(${card.icon || defaultIcon})` }"></div>
<div class="card-header">
<span class="card-title">{{ card.title }}</span>
......@@ -30,14 +30,16 @@
<span>美对华制裁措施数量趋势</span>
</div>
<div class="title-right">
<el-select v-model="fieldValue" placeholder="全部领域" class="custom-select">
<el-option label="全部领域" value="" />
<el-select v-model="fieldValue" placeholder="全部领域" class="custom-select"
@change="getUSChinaSanctionTrendData">
<el-option v-for="item in fieldOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
<el-select v-model="deptValue" placeholder="全部部门" class="custom-select">
<el-select v-model="deptValue" placeholder="全部部门" class="custom-select" @change="getUSChinaSanctionTrendData">
<el-option label="全部部门" value="" />
</el-select>
<el-select v-model="methodValue" placeholder="全部制裁手段" class="custom-select">
<el-option label="全部制裁手段" value="" />
<el-select v-model="methodValue" placeholder="全部制裁手段" class="custom-select"
@change="getUSChinaSanctionTrendData">
<el-option v-for="item in methodOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</div>
</div>
......@@ -56,7 +58,7 @@
<img :src="defaultImg" alt="" class="item-icon" />
<div class="item-right">
<div class="dynamic-item-header">
<span class="item-title">{{ item.title }}</span>
<span class="item-title" @click="handleNewsClick(item)">{{ item.title }}</span>
<span class="item-date">{{ item.date }} · {{ item.type }}</span>
</div>
<el-tooltip effect="dark" :content="item.content" popper-class="common-prompt-popper" placement="top"
......@@ -133,7 +135,7 @@
<div class="timeline-list">
<div v-for="(dept, index) in filteredTimelineList" :key="index" class="dept-row">
<div class="dept-info">
<img :src="defaultImg" alt="" class="dept-icon" />
<img :src="dept.icon || defaultImg" alt="" class="dept-icon" />
<div class="dept-text">
<div class="dept-name">{{ dept.name }}</div>
<div class="dept-count">{{ dept.count }}</div>
......@@ -174,6 +176,7 @@
<script setup>
import { onMounted, ref, computed } from "vue";
import { useRouter } from "vue-router";
import * as echarts from "echarts";
import defaultIcon from "../../assets/defaultIcon.png";
import leftBtn from "../../assets/left-btn.png";
......@@ -184,6 +187,275 @@ import icon3 from "../../assets/icon3.png";
import icon4 from "../../assets/icon4.png";
import timelineBg from "../../assets/timeline.png";
import defaultImg from "../../../../assets/images/default-icon2.png";
// 传递接口
import { getAllGovernmentList, getUSChinaSanctionTrend, getUSGovernmentLatestDynamic, getUSGovernmentJointSanctionRank, getUSGovernmentSanctionHistory } from "@/api/allGovernment.js";
const router = useRouter();
// 全政府-美政府部门对我打压遏制时间线
const loadingHistory = ref(false);
const getUSGovernmentSanctionHistoryData = async () => {
loadingHistory.value = true;
try {
const res = await getUSGovernmentSanctionHistory({
currentPage: 1,
pageSize: 1000
});
if (res.code === 200 && res.data && res.data.content) {
const rawList = res.data.content;
const orgMap = {};
if (governmentList.value && governmentList.value.length) {
governmentList.value.forEach(g => {
if (g.departId) {
orgMap[g.departId] = g.title;
}
});
}
const grouped = {};
rawList.forEach(item => {
// 尝试获取部门名称
let deptName = '未知部门';
if (item.orgName) {
deptName = item.orgName;
} else if (item.orgId && orgMap[item.orgId]) {
deptName = orgMap[item.orgId];
} else if (item.orgId) {
if (item.orgId === '241') deptName = '商务部工业与安全局';
else if (item.orgId === '203') deptName = '海外资产控制办公室';
else deptName = '部门 ' + item.orgId;
}
if (!grouped[deptName]) {
grouped[deptName] = {
name: deptName,
icon: item.orgLogoUrl,
count: 0,
events: []
};
}
grouped[deptName].count++;
grouped[deptName].events.push({
date: item.postDate ? item.postDate.replace(/^(\d{4})-(\d{2})-(\d{2})$/, '$1年$2月$3日') : '',
content: item.name || item.summary,
tags: item.techDomainList ? item.techDomainList.slice(0, 2) : [],
level: getLevelByCount(item.cnEntityCount)
});
});
timelineList.value = Object.values(grouped);
initSlider();
}
} catch (error) {
console.error("获取制裁历程失败:", error);
} finally {
loadingHistory.value = false;
}
};
// 辅助函数:根据受影响实体数量生成level
const getLevelByCount = (count) => {
const c = count || 0;
if (c === 0) return 'green'; // 0 或空 绿色
if (c <= 10) return 'yellow'; // 1-10 黄色
return 'red'; // >10 红色
};
// 全政府-美政府部门联合制裁排行
const loadingJointRank = ref(false);
const getUSGovernmentJointSanctionRankData = async () => {
loadingJointRank.value = true;
try {
const res = await getUSGovernmentJointSanctionRank();
if (res.code === 200 && res.data) {
const rawData = res.data || [];
// 按 orderId 分组
const groupedData = {};
rawData.forEach(item => {
if (!groupedData[item.orderId]) {
groupedData[item.orderId] = {
depts: item.org ? item.org.map(o => o.orgName) : [],
count: item.jointCount,
items: []
};
}
groupedData[item.orderId].items.push({
type: item.sanTypeName || '其他',
title: item.sanName,
date: item.postDate ? item.postDate.replace(/^(\d{4})-(\d{2})-(\d{2})$/, '$1年$2月$3日') : ''
});
});
rankingList.value = Object.values(groupedData);
}
} catch (error) {
console.error("获取美政府部门联合制裁排行失败:", error);
} finally {
loadingJointRank.value = false;
}
};
// 全政府-美政府部门打压遏制最新动态
const loadingLatestDynamic = ref(false);
const getUSGovernmentLatestDynamicData = async () => {
loadingLatestDynamic.value = true;
try {
const res = await getUSGovernmentLatestDynamic();
if (res.code === 200 && res.data) {
dynamicList.value = res.data.map(item => ({
title: item.orgName ? `${item.orgName}${item.title}` : item.title,
date: item.time ? item.time.replace(/^(\d{4})-(\d{2})-(\d{2})$/, '$1年$2月$3日') : '',
type: item.sanTypeName || '',
content: item.content || item.title,
tags: item.industrylist || [],
id: item.id
}));
}
} catch (error) {
console.error("获取美政府部门打压遏制最新动态失败:", error);
} finally {
loadingLatestDynamic.value = false;
}
};
// 点击科技要闻-跳转详情页
const handleNewsClick = (item) => {
if (!item || !item.id) return;
// 打开新标签页
const { href } = router.resolve({
path: "/newsAnalysis",
query: {
newsId: item.id
}
});
window.open(href, '_blank');
};
// 全政府-获取美对华制裁措施数量趋势
const usChinaSanctionTrend = ref([]);
const loadingTrend = ref(false);
const getUSChinaSanctionTrendData = async () => {
loadingTrend.value = true;
try {
const params = {
monthNum: 12
};
if (fieldValue.value) {
params.field = fieldValue.value;
}
if (deptValue.value) {
params.orgId = deptValue.value;
}
if (methodValue.value) {
params.sanType = methodValue.value;
}
const res = await getUSChinaSanctionTrend(params);
if (res.code === 200 && res.data) {
usChinaSanctionTrend.value = res.data;
// 更新图表
const xAxisData = res.data.map((item) => `${item.year}-${item.month}`);
const seriesData = res.data.map((item) => item.sanctionCount);
initChart(xAxisData, seriesData);
}
} catch (error) {
console.error("获取美对华制裁措施数量趋势失败:", error);
} finally {
loadingTrend.value = false;
}
};
// 全政府-获取美国政府部门制裁数据
const governmentList = ref([]);
const loadingGovernment = ref(false);
const getGovernmentList = async () => {
loadingGovernment.value = true;
try {
const res = await getAllGovernmentList();
if (res.code === 200 && res.data) {
governmentList.value = res.data;
// 如果后端返回了数据,则更新 cardList
if (Array.isArray(res.data) && res.data.length > 0) {
cardList.value = res.data.map((item) => {
const stats = [];
if (item.parliament) {
// 议会类型
if (item.billCount) {
stats.push({
label: "法案(提出)",
value: (item.billCount.proposedBillCount || 0) + "项"
});
stats.push({
label: "法案(通过)",
value: (item.billCount.passedBillCount || 0) + "项"
});
}
} else {
// 非议会类型
// 1. 处理制裁清单
if (item.sanctionCountList && item.sanctionCountList.length > 0) {
item.sanctionCountList.forEach((sanction) => {
stats.push({
label: sanction.nameZh || sanction.name,
value: (sanction.postCount || 0) + "次"
});
});
}
// 2. 处理政令
stats.push({
label: "政令",
value: (item.administrativeOrderCount || 0) + "项"
});
}
return {
title: item.departName || "未知部门",
icon: defaultIcon, // 暂时使用默认图标
stats: stats,
departId: item.departId
};
});
}
}
} catch (error) {
console.error("获取美国政府部门制裁数据失败:", error);
} finally {
loadingGovernment.value = false;
}
};
// 跳转到机构页面
const handleCardClick = (card) => {
if (!card || !card.departId) return;
// 打开新标签页
const { href } = router.resolve({
path: "/institution",
query: {
id: card.departId
}
});
window.open(href, '_blank');
};
const cardList = ref([
{
......@@ -251,8 +523,30 @@ const deptValue = ref("");
const methodValue = ref("");
const measureType = ref("history");
const selectedField = ref("all");
const fieldOptions = ref([{ label: "全部领域", value: "all" }]);
const selectedField = ref("");
const fieldOptions = ref([
{ label: "全部领域", value: "" },
{ label: "人工智能", value: "1" },
{ label: "生物科技", value: "2" },
{ label: "新一代信息技术", value: "3" },
{ label: "量子科技", value: "4" },
{ label: "新能源", value: "5" },
{ label: "集成电路", value: "6" },
{ label: "海洋", value: "7" },
{ label: "先进制造", value: "8" },
{ label: "新材料", value: "9" },
{ label: "航空航天", value: "10" },
{ label: "深海", value: "11" },
{ label: "极地", value: "12" },
{ label: "太空", value: "13" },
{ label: "核", value: "14" }
]);
const methodOptions = ref([
{ label: "全部制裁手段", value: "" },
{ label: "法案", value: "-1" },
{ label: "行政令", value: "-2" }
]);
const dynamicList = ref([
{
......@@ -660,7 +954,7 @@ const initSlider = () => {
});
};
const initChart = () => {
const initChart = (xAxisData = [], seriesData = []) => {
if (!chartRef.value) return;
myChart = echarts.init(chartRef.value);
const option = {
......@@ -688,20 +982,7 @@ const initChart = () => {
xAxis: {
type: "category",
boundaryGap: false,
data: [
"2024-12",
"2025-1",
"2025-2",
"2025-3",
"2025-4",
"2025-5",
"2025-6",
"2025-7",
"2025-8",
"2025-9",
"2025-10",
"2025-11"
],
data: xAxisData,
axisLine: {
lineStyle: {
color: "#f0f0f0"
......@@ -718,8 +999,7 @@ const initChart = () => {
yAxis: {
type: "value",
min: 0,
max: 100,
interval: 20,
minInterval: 1, // 保证最小间隔为1,避免小数
axisLine: {
show: false
},
......@@ -736,7 +1016,7 @@ const initChart = () => {
},
series: [
{
data: [45, 52, 62, 62, 62, 65, 52, 75, 75, 75, 82, 92],
data: seriesData,
type: "line",
symbol: "circle",
symbolSize: 8,
......@@ -770,6 +1050,11 @@ const initChart = () => {
onMounted(() => {
initChart();
initSlider();
getGovernmentList();
getUSChinaSanctionTrendData();
getUSGovernmentLatestDynamicData();
getUSGovernmentJointSanctionRankData();
getUSGovernmentSanctionHistoryData();
window.addEventListener("resize", () => {
myChart && myChart.resize();
sliderChart && sliderChart.resize();
......@@ -1104,6 +1389,7 @@ const prev = () => {
align-items: flex-start;
.item-title {
cursor: pointer;
font-family: "Microsoft YaHei";
font-size: 16px;
font-weight: 700;
......@@ -1112,7 +1398,9 @@ const prev = () => {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
max-width: 500px;
flex: 1;
min-width: 0;
margin-right: 12px;
}
.item-date {
......@@ -1121,6 +1409,8 @@ const prev = () => {
font-weight: 400;
line-height: 30px;
color: rgb(95, 101, 108);
flex-shrink: 0;
white-space: nowrap;
}
}
......@@ -1168,6 +1458,24 @@ const prev = () => {
background: rgba(250, 84, 28, 0.1);
border: 1px solid rgba(250, 84, 28, 0.3);
}
&.tag-orange {
color: #fa8c16;
background: rgba(250, 140, 22, 0.1);
border: 1px solid rgba(250, 140, 22, 0.3);
}
&.tag-purple {
color: #722ed1;
background: rgba(114, 46, 209, 0.1);
border: 1px solid rgba(114, 46, 209, 0.3);
}
&.tag-cyan {
color: #13c2c2;
background: rgba(19, 194, 194, 0.1);
border: 1px solid rgba(19, 194, 194, 0.3);
}
}
}
}
......@@ -1262,6 +1570,8 @@ const prev = () => {
font-weight: 400;
line-height: 20px;
margin-right: 13px;
white-space: nowrap;
flex-shrink: 0;
&.type-bill {
color: #2f79c4;
......@@ -1302,6 +1612,10 @@ const prev = () => {
}
}
}
.text-item:last-child {
padding-bottom: 22px;
}
}
.main-bottom {
......@@ -1414,7 +1728,7 @@ const prev = () => {
.timeline-list {
flex: 1;
overflow-y: auto;
overflow: auto;
padding-right: 8px;
padding-bottom: 8px;
......@@ -1470,11 +1784,26 @@ const prev = () => {
gap: 8px;
overflow-x: auto;
// 隐藏滚动条
// 启用滚动条
&::-webkit-scrollbar {
display: none;
height: 6px;
/* 横向滚动条高度 */
display: block;
}
&::-webkit-scrollbar-thumb {
background: rgba(0, 0, 0, 0.2);
border-radius: 3px;
}
&::-webkit-scrollbar-track {
background: transparent;
}
scrollbar-width: thin;
scrollbar-color: rgba(0, 0, 0, 0.2) transparent;
padding-bottom: 4px; // 给滚动条留出空间
.event-card {
min-width: 240px;
max-width: 240px;
......@@ -1577,6 +1906,8 @@ const prev = () => {
font-weight: 400;
color: rgb(59, 65, 75);
line-height: 24px;
min-height: 48px; // 强制最小高度为两行 (24px * 2)
height: 48px; // 固定高度为两行
// margin-bottom: auto;
display: -webkit-box;
-webkit-line-clamp: 2;
......@@ -1587,17 +1918,21 @@ const prev = () => {
.event-tags {
display: flex;
gap: 8px;
flex-wrap: wrap;
margin-top: 4px;
white-space: nowrap;
.tag {
padding: 2px 8px;
padding: 0 8px;
height: 22px;
line-height: 20px;
border-radius: 4px;
font-size: 14px;
font-weight: 400;
font-family: "Microsoft YaHei";
line-height: 20px;
border: 1px solid;
flex-shrink: 0;
display: flex;
align-items: center;
&.tag-blue {
color: rgba(9, 88, 217, 1);
......
......@@ -77,6 +77,7 @@ import { onMounted, ref, computed } from "vue";
import * as echarts from "echarts";
import Timeline from "./Timeline.vue";
import tableShow from "./tableShow.vue";
import radarChart from "./radarChart3.js";
import { getCompare, getChartDict, getTechnologyGameAnalysis } from '@/api/zmOverview/risk/index.js'
......
......@@ -9,7 +9,7 @@
</template>
<div class="tableWrap">
<el-table
:data="panel5MockData"
:data="panel5Data"
class="sanction-table"
stripe
empty-text="暂无数据"
......@@ -116,6 +116,7 @@ const selectedId = ref(selectOptions[0].value);
const indexMethod = index => {
return index + 1;
};
const panel5Data = ref([]);
const panel5MockData = [
{
name: "科大讯飞股份有限公司",
......@@ -283,6 +284,20 @@ const fetchOriginCountData = async () => {
}
};
const fetchScientificImpactEntityList = async () => {
try {
const data = await getScientificImpactEntityList(router.query.startTime);
if (data && Array.isArray(data)) {
panel5Data.value = data.map(item => ({
name: item.name,
number: item.count
}));
}
} catch (error) {
console.error("获取影响实体分析数据失败:", error);
}
};
onMounted(async () => {
// horizontalBarOptions.value = getHorizontalBarChart1(
// ["地球探测仪器", "计算机及其配套设备", "天文仪器", "分析仪器", "核仪器", "物理性能测试仪器", "医学科研仪器"],
......@@ -316,6 +331,8 @@ onMounted(async () => {
// { name: "核仪器", value: [48, 38, 28, 28, 28, 18, 18, 18, 28, 28] }
// ]
// });
// 科研机构
await fetchScientificImpactEntityList();
// 获取各类别仪器对美依赖情况数据
await fetchDependencyCountData();
// 获取仪器进口国可替代性分析数据
......
......@@ -88,13 +88,9 @@
<div class="hintWrap">
<div class="title">
共计
<span class="text1">{{ entityTotal }}</span>
<span class="text1">{{ entitiesCountBy50PercentRules?.totalCount }}</span>
家,其中50%规则涉及
<span class="text2">{{
panel5IsChecked
? entitiesCountBy50PercentRules?.ruleCount
: entitiesCountBy50PercentRules?.totalCount
}}</span>
<span class="text2">{{ entitiesCountBy50PercentRules?.ruleCount }}</span>
</div>
</div>
......
# 交互消息类
## ApiResult
```java
public class ApiResult<T> {
@ApiModelProperty("响应码")
private int code;
@ApiModelProperty("响应消息")
private String message;
@ApiModelProperty("是否成功")
private boolean success;
@ApiModelProperty("响应数据")
private T data;
}
```
## LatestRiskUpdatesVO
```java
public class LatestRiskUpdatesVO {
@Data
public static class ItemVO {
//统计总数
private long total;
//增加数
private long dailyIncrement;
}
@Data
public static class HotspotVO {
//最热事件id
private String HotspotID;
//最热事件类型
private String HotspotType;
//最热事件日期
private String HotspotDate;
//最热事件标题
private String HotspotTitle;
}
}
```
## LatestRisksVO
```java
public class LatestRisksVO {
//风险信号列表
private List<RiskVO> riskVOS;
//风险关联事件列表
private List<HotspotVO> hotspotVOS;
//所有风险数
private Long RiskCount;
@Data
@NoArgsConstructor
public static class HotspotVO {
@ApiModelProperty("id")
private String HotspotID;
@ApiModelProperty("标题")
private String HotspotTitle;
@ApiModelProperty("描述")
private String HotspotDesc;
@ApiModelProperty("时间")
private Date HotspotDate;
@ApiModelProperty("图片")
private String HotspotPicture;
@ApiModelProperty("发布机构名称")
private String HotspotOrgName;
@ApiModelProperty("类型")
private String HotspotType;
@ApiModelProperty("领域列表")
private List<BaseInfo> DomainList;
}
}
@Data
public static class RiskVO {
@ApiModelProperty("风险信号id")
private Long signalId;
@ApiModelProperty("风险信号标题")
private String signalTitle;
@ApiModelProperty("风险信号时间")
private Date signalTime;
@ApiModelProperty("风险信号等级")
private String signalLevel;
}
}
```
## AllDomainCountVO
```
public class AllDomainCountVO {
@ApiModelProperty(value = "统计名称")
private String countName;
@ApiModelProperty(value = "统计数量")
private Long countNum;
}
```
## DomainContainmentRankingVO
```
public class DomainContainmentRankingVO {
@ApiModelProperty(value = "机构名称")
private String orgName;
@ApiModelProperty(value = "机构图片")
private String orgPicture;
@ApiModelProperty(value = "机构打压次数")
private Long orgCount;
}
```
## DomainContainmentTrendVO
```
public class DomainContainmentTrendVO {
@ApiModelProperty(value = "年度/月份")
private String YearOrMonth;
@ApiModelProperty(value = "领域列表")
private List<DomainVO> DomainList;
@Data
@NoArgsConstructor
@AllArgsConstructor
public static class DomainVO {
@ApiModelProperty(value = "统计名称")
private String DomainName;
@ApiModelProperty(value = "统计数量")
private Long DomainNum;
}
}
```
## DomainContainmentTimelineVO
```
public class DomainContainmentTimelineVO {
@ApiModelProperty(value = "打压名称")
private String EventName;
@ApiModelProperty(value = "打压描述")
private String EventDesc;
@ApiModelProperty(value = "打压时间")
private Date EventDate;
@ApiModelProperty(value = "打压类别")
private String EventType;
@ApiModelProperty(value = "打压发起机构")
private String EventOrgName;
@ApiModelProperty(value = "打压事件id")
private String EventId;
@ApiModelProperty(value = "领域列表")
private List<DomainContainmentTimelineVO.DomainVO> EventDomainList;
@Data
@NoArgsConstructor
@AllArgsConstructor
public static class DomainVO {
@ApiModelProperty(value = "领域id")
private String DomainId;
@ApiModelProperty(value = "领域名称")
private String DomainName;
}
}
```
## TechnologyGameAnalysisVO
```
public class TechnologyGameAnalysisVO {
@ApiModelProperty(value = "事件id")
private String eventId;
@ApiModelProperty(value = "事件名称")
private String eventName;
@ApiModelProperty(value = "事件摘要")
private String eventDesc;
@ApiModelProperty(value = "事件发布机构")
private String eventOrg;
@ApiModelProperty(value = "事件时间")
private Date eventDate;
@ApiModelProperty(value = "事件策略")
private String eventStrategy;
@ApiModelProperty(value = "事件类型")
private String eventType;
@ApiModelProperty(value = "事件国旗图片")
private String eventCountryImg;
}
```
# 中美博弈概览
## **最新风险动态统计**
请求地址:/rivalryIndexV2/LatestRiskUpdates
请求类型:GET
输入参数:
​ 参数:无输入
```java
@ApiParam(value = "日期", defaultValue = "本周")
@RequestParam(value = "currentDate") String currentDate
```
​ 请求头:携带token,内容为:
```
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJkYXRhLWNlbnRlciIsImF1ZCI6IndlYiIsImlzcyI6ImRhdGEtY2VudGVyIiwiZXhwIjozODI1ODM1NTkxLCJpYXQiOjE2NzgzNTE5NTMsImp0aSI6IjI4YmY1NTZjMTc0MDQ3YjJiNTExNWM3NzVhYjhlNWRmIiwidXNlcm5hbWUiOiJzdXBlcl91c2VyIn0.zHyVzsleX2lEqjDBYRpwluu_wy2nZKGl0dw3IUGnKNw
```
输出结果:ApiResult<LatestRiskUpdatesVO>
```
"data": {
"bill": { -法案
"total": 167258,
"dailyIncrement": 91
},
"administrativeOrder": {-政令
"total": 215763,
"dailyIncrement": 27
},
"Entities": {-实体清单
"total": 141,
"dailyIncrement": 0
},
"CCL": {-ccl
"total": 3,
"dailyIncrement": 0
},
"SDN": {-sdn
"total": 3,
"dailyIncrement": 0
},
"militaryInvolvement": {-涉军企业
"total": 0,
"dailyIncrement": 0
},
"337Survey": {-337调查
"total": 2881,
"dailyIncrement": 1
},
"232Survey": {-232调查
"total": 35,
"dailyIncrement": 0
},
"301Survey": {-301调查
"total": 5,
"dailyIncrement": 0
},
"policiesRegulations": {-最热政策法规
"hotspotID": "119_HR_7065",
"hotspotDate": "2026-01-14",
"hotspotType": "法案",
"hotspotTitle": "塞尼卡民族执法效率法案 (Seneca Nation Law Enforcement Efficiency Act)"
},
"exportControl": {-最热出口管制
"hotspotID": "138",
"hotspotDate": "2025-10-08",
"hotspotType": "实体清单",
"hotspotTitle": "实体清单的增补与修订"
},
"investmentFinancingRestrictions": {-最热投融资限制
"hotspotID": "147",
"hotspotDate": "2025-06-30",
"hotspotType": "SDN",
"hotspotTitle": "《出口管理条例》修订:商业管制清单新增条目"
},
"marketAccess": {-最热市场准入
"hotspotID": "111",
"hotspotDate": "2026-01-01",
"hotspotType": "337",
"hotspotTitle": "外国制造的半导体器件及其下游产品和组件"
}
}
```
## **最新风险信号**
请求地址:/rivalryIndexV2/LatestRisks
请求类型:GET
输入参数:
​ 参数:无输入
​ 请求头:携带token
输出结果:ApiResult<LatestRisksVO>
## **全领域统计**
请求地址:/rivalryIndexV2/AllDomainCount
请求类型:GET
输入参数:
​ 参数:无输入
​ 请求头:携带token
输出结果:ApiResult<List<AllDomainCountVO>>
## 领域打压遏制排行
请求地址:/rivalryIndexV2/DomainContainmentRanking
请求类型:GET
输入参数:
​ 参数:
```java
@ApiParam(value = "对我打压机构", defaultValue = "对我打压机构")
@RequestParam(value = "ContainmentOrg") String ContainmentOrg,
@ApiParam(value = "领域", defaultValue = "")//传空值为查询全部领域
@RequestParam(value = "Domains",required = false) String Domain
```
请求头:携带token
输出结果:ApiResult<List<DomainContainmentRankingVO>>
## 美对华制裁措施数量趋势
请求地址:/rivalryIndexV2/DomainContainmentTrend
请求类型:GET
输入参数:
参数:required = false为非必传
```java
@ApiParam(value = "日期", defaultValue = "按月统计")
@RequestParam(value = "byYOrM") String byYOrM
```
请求头:携带token
输出结果:ApiResult<List<DomainContainmentTrendVO>>
## 领域打压遏制时间线
请求地址:/rivalryIndexV2/DomainContainmentTimeline
请求类型:GET
输入参数:
参数:required = false为非必传
```JAVA
//传空值为查询全部领域
@ApiParam(value = "领域", defaultValue = "1")
@RequestParam(value = "domain",required = false) String domain
```
请求头:携带token
输出结果: ApiResult<List<DomainContainmentTimelineVO>>
## 中美科技博弈分析
请求地址:/rivalryIndexV2/TechnologyGameAnalysis
请求类型:GET
输入参数:
参数:required = false为非必传
```java
//传空值为查询全部领域
@ApiParam(value = "领域", defaultValue = "1")
@RequestParam(value = "domain",required = false) String domain
```
输出结果:ApiResult<List<TechnologyGameAnalysisVO>>
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论