提交 6de917f9 authored 作者: coderBryanFu's avatar coderBryanFu

update

{
"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
})
}
......@@ -4,36 +4,38 @@ import request from "@/api/request.js";
// 全领域统计
export function getAllDomainCount() {
return request({
method: 'GET',
url: `/api/rivalryIndexV2/AllDomainCount`,
})
method: "GET",
url: `/api/rivalryIndexV2/AllDomainCount`
});
}
// 美对华制裁措施数量趋势
export function getDomainContainmentTrend() {
export function getDomainContainmentTrend(byYOrM = "按月统计") {
return request({
method: 'GET',
url: `/api/rivalryIndexV2/DomainContainmentTrend`,
})
method: "GET",
url: `/api/rivalryIndexV2/DomainContainmentTrend?byYOrM=${byYOrM}`
});
}
// 最新动态
export function getTechnologyGameAnalysis() {
// 中美科技博弈分析
export function getTechnologyGameAnalysis(domain = 1) {
return request({
method: 'GET',
url: `/api/rivalryIndexV2/TechnologyGameAnalysis`,
})
method: "GET",
url: `/api/rivalryIndexV2/TechnologyGameAnalysis?domain=${domain}`
});
}
// 领域打压遏制排行
/**
* @param {currentPage, pageSize}
*/
export function getDomainContainmentRanking() {
export function getDomainContainmentRanking(ContainmentOrg = "对我打压机构", Domains = "") {
return request({
method: 'GET',
url: `/api/rivalryIndexV2/DomainContainmentRanking`,
})
method: "GET",
url: !!Domains
? `/api/rivalryIndexV2/DomainContainmentRanking?ContainmentOrg=${ContainmentOrg}&Domains=${Domains}`
: `/api/rivalryIndexV2/DomainContainmentRanking?ContainmentOrg=${ContainmentOrg}`
});
}
// 领域打压遏制时间线
......@@ -42,9 +44,8 @@ export function getDomainContainmentRanking() {
*/
export function getDomainContainmentTimeline(params) {
return request({
method: 'GET',
method: "GET",
url: `/api/rivalryIndexV2/DomainContainmentTimeline`,
params
})
});
}
import request from "@/api/request.js";
// 中美博弈概览V2:最新风险动态统计
export function getLatestRiskUpdates(params) {
return request({
method: 'GET',
url: `/api/rivalryIndexV2/LatestRiskUpdates`,
params: params
})
}
// 中美博弈概览V2:最新风险信号
export function getLatestRisks() {
return request({
method: 'GET',
url: `/api/rivalryIndexV2/LatestRisks`,
})
}
// 中美博弈概览V2:美对华制裁措施数量趋势
export function geDomainContainmentTrend(params) {
return request({
method: 'GET',
url: `/api/rivalryIndexV2/DomainContainmentTrend`,
params: params
})
}
// 中美博弈概况:获取榜单字典
export function getChartDict() {
return request({
method: 'GET',
url: `/api/union/summary/chartDict`,
})
}
// 中美博弈概况:中美科技实力对比
export function getCompare(id) {
return request({
method: 'GET',
url: `/api/union/summary/compare/${id}`,
})
}
// 中美博弈分析
export function getTechnologyGameAnalysis() {
return request({
method: 'GET',
url: `/api/rivalryIndexV2/TechnologyGameAnalysis`,
})
}
//中美博弈概览V7:美国政府部门对华制裁最新动态
export function getGovernmentSanctionsDynamics() {
return request({
method: 'GET',
url: `/api/rivalryIndex/governmentSanctionsDynamics`,
})
}
\ No newline at end of file
//新闻速览
import newsBrief from "@/views/newsBrief/index.vue"
import newsBrief from "@/views/newsBrief/index.vue";
// 新闻事件分析
import NewsAnalysis from "@/views/newsAnalysis/index.vue";
......@@ -22,8 +22,7 @@ const newsRoutes = [
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
......@@ -5,7 +5,7 @@
<div class="timeline-box">
<div class="line" style="width:100vw ;" />
<!-- 一次性渲染全部节点 -->
<div v-for="(item, i) in data" :key="item[idKey]" class="node" :style="leftStyle(i)">
<div v-for="(item, i) in showList" :key="item[idKey]" class="node" :style="leftStyle(i)">
<!-- 圆环 -->
<div class="dot" :class="linePos(item)" :style="{ '--i': item.unit === '中国' ? ' #E29697' : '#69A0DA' }" />
......@@ -22,20 +22,21 @@
<!-- 卡片 -->
<div class="card" :class="[cardPos(item), 'right-side']" @click="$emit('click-card', item)">
<div style="justify-content: space-between;display: flex;width: 300px;">
<div class="tag">{{ item.tag }}</div>
<img :src="`/icon/${item.unit}.png`" class="icon"></img>
<div class="tag">{{ item.eventStrategy }}</div>
<img :src="item.eventCountryImg" class="icon"
style="border-radius: 14px;height: 28px;width: 28px;;"></img>
</div>
<div class="title" :style="{
}">{{ item.title }}</div>
<div class="time">{{ item.time }}</div>
}">{{ item.eventName }}</div>
<div class="time">{{ item.eventDate }}</div>
<!-- <div class="title" :style="{
color: item.unit === '中国' ? ' #CF4F51' : ''
}">{{ item.title }}</div>
<div class="time">{{ item.time }}</div> -->
<div class="content">{{ item.content }}</div>
<div class="content">{{ item.eventDesc }}</div>
</div>
</div>
</div>
......@@ -85,7 +86,7 @@ export default {
},
/* 卡片上下位置:unit=0 -> 下侧,其余 -> 上侧 */
cardPos(item) {
return item.unit === '中国' ? 'down' : 'up';
return item.eventType === '反制措施' ? 'down' : 'up';
},
/* 延伸线方向 = 卡片方向 */
linePos(item) {
......@@ -278,7 +279,7 @@ export default {
width: 120px;
height: 28px;
/* 自动布局 */
display: flex;
/* display: flex; */
flex-direction: row;
justify-content: flex-start;
align-items: flex-start;
......@@ -303,7 +304,7 @@ export default {
width: 120px;
height: 28px;
/* 自动布局 */
display: flex;
/* display: flex; */
flex-direction: row;
justify-content: flex-start;
align-items: flex-start;
......@@ -346,5 +347,23 @@ export default {
line-height: 24px;
letter-spacing: 0px;
text-align: justify;
width: 300px;
/* 设置一个固定的宽度 */
height: 100px;
/* 设置一个固定的高度,确保只显示 5 行 */
font-size: 16px;
/* 设置字体大小 */
line-height: 20px;
/* 设置行高 */
overflow: hidden;
/* 隐藏超出部分 */
display: -webkit-box;
/* 使用 Webkit 的 box 模型 */
-webkit-line-clamp: 3;
/* 限制为 5 行 */
-webkit-box-orient: vertical;
/* 垂直排列内容 */
text-overflow: ellipsis;
/* 超出部分显示省略号 */
}
</style>
\ No newline at end of file
......@@ -8,11 +8,13 @@
</div>
<div style="display: flex; height: 650px; width: 100%">
<div style="width: 50%">
<div style="display: flex; justify-content: space-between; margin-right: 50px; line-height: 32px;align-items: center;" >
<div
style="display: flex; justify-content: space-between; margin-right: 50px; line-height: 32px;align-items: center;">
<div style="display: flex; margin-left: 50px">
数据来源:
<el-select class="select-item" size="default" style="margin-left: 15px; width: 240px; height: 32px">
<el-option label="国家创新指数报告" value="last_year" />
<el-select class="select-item" size="default" style="margin-left: 15px; width: 240px; height: 32px"
v-model="origin" @change="handleGetCompare()">
<el-option :value="value.id" :label="value.name" v-for="value in originList" />
</el-select>
</div>
<div style="display: flex">
......@@ -25,21 +27,21 @@
<div style="width: 672px; height: 486px; padding-top: 50px" id="char"></div>
</div>
<div style="width: 50%">
<div style="width: 50%; height: 620px;overflow: auto;">
<el-table :data="tableData" style="width: 100%; margin-bottom: 20px" row-key="id" border default-expand-all>
<el-table-column prop="name" label="指标名称" sortable width="350" />
<el-table-column prop="percent" label="中国">
<el-table-column prop="targetName" label="指标名称" sortable width="350" />
<el-table-column prop="chinaScore" label="中国">
<template #default="scope">
<div class="progress-wrapper left" :style="{ '--i': '40px', '--j': '-20px', marginLeft: '20px' }">
<el-progress :percentage="scope.row.percent[0]" :stroke-width="20" class="left-progress"
<el-progress :percentage="scope.row.chinaScore" :stroke-width="20" class="left-progress"
:show-text="false" />
</div>
</template>
</el-table-column>
<el-table-column prop="percent" label="美国">
<el-table-column prop="usScore" label="美国">
<template #default="scope">
<div class="progress-wrapper right" :style="{ '--i': '40px', marginRight: '20px' }">
<el-progress :percentage="scope.row.percent[0]" :stroke-width="20" class="right-progress"
<el-progress :percentage="scope.row.usScore" :stroke-width="20" class="right-progress"
:show-text="false" />
</div>
</template>
......@@ -63,7 +65,8 @@
}">
<img :src="`/public/icon/ZM/btn-icon-${index}.png`" style="width: 22px; height: 19px; margin: 0 22px" />
{{ value.text }}
<img :src="`/public/icon/ZM/btn-icon-arrow.png`" style="margin-left: auto; margin-right: 22px; width: 13px; height: 12px" />
<img :src="`/public/icon/ZM/btn-icon-arrow.png`"
style="margin-left: auto; margin-right: 22px; width: 13px; height: 12px" />
</div>
</div>
</div>
......@@ -74,7 +77,10 @@ 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'
const course = ref([
{
time: "2025-01-15",
......@@ -129,22 +135,86 @@ const course = ref([
}
]);
onMounted(() => {
const originList = ref([])
const origin = ref('')
//数据来源
const handleGetChartDict = async () => {
try {
const res = await getChartDict();
console.log("数据来源", res);
if (res.code === 200 && res.data) {
originList.value = res.data
origin.value = res.data[0].id
}
} catch (error) {
console.error("获取数据来源error", error);
}
};
//中美科技实力对比
const handleGetCompare = async () => {
try {
const res = await getCompare(origin.value);
console.log("中美科技实力对比", res);
if (res.code === 200 && res.data) {
tableData.value = res.data
const secondLevelData = res.data[0].children;
const indicatorNames = secondLevelData.map(item => item.targetName);
const chinaScores = secondLevelData.map(item => item.chinaScore);
const usScores = secondLevelData.map(item => item.usScore);
const dom = document.getElementById("char");
const myChart = echarts.init(dom);
// 2. 传入容器,生成配置
const option = radarChart(
["创新资源", "知识创造", "企业创新", "创新绩效", "创新环境"],
[
[4200, 3000, 20000, 35000, 50000, 18000],
[1000, 42000, 32000, 35000, 50000, 18000]
const radarOption = {
indicatorNames: indicatorNames,
data: [
chinaScores,
usScores
]
};
const option = radarChart(
radarOption.indicatorNames, radarOption.data
);
myChart.setOption(option);
console.log(radarOption)
}
} catch (error) {
console.error("获取中美科技实力对比error", error);
}
};
//中美博弈概览V2:领域打压遏制时间线
const handlegetTechnologyGameAnalysis = async () => {
try {
const res = await getTechnologyGameAnalysis();
console.log("中美科技博弈分析", res);
if (res.code === 200 && res.data) {
course.value = res.data
}
} catch (error) {
console.error("获取中美科技博弈分析error", error);
}
};
onMounted(async () => {
await handleGetChartDict()
await handleGetCompare()
await handlegetTechnologyGameAnalysis()
// const dom = document.getElementById("char");
// const myChart = echarts.init(dom);
// // 2. 传入容器,生成配置
// const option = radarChart(
// ["创新资源", "知识创造", "企业创新", "创新绩效", "创新环境"],
// [
// [4200, 3000, 20000, 35000, 50000, 18000],
// [1000, 42000, 32000, 35000, 50000, 18000]
// ]
// );
// setChart(option, "char7");
// myChart.setOption(option);
// // setChart(option, "char7");
});
const tableData = ref([
......@@ -266,6 +336,7 @@ const btnList = ref([
width: 1600px;
height: 1600px;
margin: 0 auto;
.card-box {
width: 1600px;
height: 700px;
......
......@@ -34,7 +34,7 @@ let instance = null
/* 配置项 */
const makeOption = () => {
const p = Math.min(100, Math.max(0, props.percent)) / 100
console.log(props.color, 'colorcolorcolor')
// console.log(props, 'colorcolorcolor')
return {
series: [{
type: 'liquidFill',
......@@ -73,8 +73,8 @@ const makeOption = () => {
formatter: function () {
const change = props.data.change;
const unit = props.data.unit;
if (change === '无新增') {
return `{noChange|${change}}\n{b|共${props.data.count}${unit}}`
if (change === 0) {
return `{num|${'无新增'}}`
}
return `{num|${change}}{unit| ${unit}}\n{b|共${props.data.count}${unit}}`
},
......
......@@ -23,7 +23,7 @@
{{ sections[index].title }}
</div>
<div style="width: 50px; color: #ffffff">
{{ sections[index].date }}
{{ sections[index].date.slice(-5) }}
</div>
</div>
</div>
......@@ -33,7 +33,7 @@
<img class="section-title" src="./icon/title-icon-2.png" />
<div>风险信号</div>
<div class="num">12</div>
<div class="num">{{ riskTotal }}</div>
<div class="manage-btn" @click="handleToRiskManage">
风险信号管理 >
</div>
......@@ -74,22 +74,22 @@
<div class="carousel-title">
<div>
<div class="title-text">
{{ News.title }}
{{ News.hotspotTitle }}
</div>
<div class="title-tag">
{{ News.category }}
{{ News.hotspotType }}
</div>
</div>
<img src="./icon/矩形 295.png" style="width: 96px; height: 96px" />
<img :src="News.hotspotPicture" style="width: 96px; height: 96px" />
</div>
<div style="/* 矩形 351 */ width: 664px; height: 1px; background: rgba(234, 236, 238, 1)"></div>
<div class="news-carousel-content">{{ News.content }}</div>
<div class="news-carousel-content">{{ News.hotspotDesc }}</div>
<div class="carousel-bottom">
<div class="left">{{ News.date + News.source }}</div>
<div class="left">{{ News.hotspotDate + News.hotspotOrgName }}</div>
<div class="right">
<div v-for="tag in News.tags" class="tag">
{{ tag }}
<div v-for="tag in News.domainList" class="tag">
{{ tag.name }}
</div>
</div>
</div>
......@@ -105,9 +105,10 @@
<script setup>
import { color } from "echarts";
import { onMounted, ref, computed } from "vue";
import { onMounted, ref, computed, onBeforeUnmount } from "vue";
import WaveBall from "./WaveBall.vue";
import { getBillRiskSignal } from "@/api/bill/billHome";
import { getLatestRiskUpdates, getLatestRisks } from '@/api/zmOverview/risk/index.js'
const sectionTab = [
{
textColor: "rgba(9, 88, 217, 1)",
......@@ -148,14 +149,14 @@ const sections = ref([
date: "12-18",
waveBall: [
{
percent: 30, // 估算的百分比
percent: 0, // 估算的百分比
count: 1626,
change: "+3",
unit: "项",
title: "法案(提出)"
},
{
percent: 20, // 估算的百分比
percent: 0, // 估算的百分比
count: 69,
change: "+2",
unit: "个",
......@@ -168,14 +169,14 @@ const sections = ref([
date: "12-19",
waveBall: [
{
percent: 10, // 估算的百分比
percent: 0, // 估算的百分比
count: 128,
change: "+1",
unit: "次",
title: "实体清单"
},
{
percent: 20, // 估算的百分比
percent: 0, // 估算的百分比
count: 69,
change: "+1",
unit: "次",
......@@ -188,15 +189,15 @@ const sections = ref([
date: "12-15",
waveBall: [
{
percent: 15, // 估算的百分比
count: 35,
percent: 0, // 估算的百分比
count: 0,
change: "+1",
unit: "次",
title: "SDN"
},
{
percent: 5, // 估算的百分比
count: 28,
percent: 0, // 估算的百分比
count: 0,
change: "+1",
unit: "家",
title: "涉军企业"
......@@ -208,22 +209,22 @@ const sections = ref([
date: "12-15",
waveBall: [
{
percent: 3, // 估算的百分比
count: 215,
percent: 0, // 估算的百分比
count: 0,
change: "+1",
unit: "次",
title: "337调查"
},
{
percent: 3, // 估算的百分比
count: 14,
percent: 0, // 估算的百分比
count: 0,
change: "无新增",
unit: "次",
title: "230调查"
},
{
percent: 3, // 估算的百分比
count: 9,
percent: 0, // 估算的百分比
count: 0,
change: "无新增",
unit: "次",
title: "301调查"
......@@ -231,21 +232,117 @@ const sections = ref([
]
}
]);
// 风险信号
const warningList = ref([]);
// 获取法案风险信号
const handlegetBillRiskSignal = async () => {
const params = {
moduleId: "0100"
};
// 最新风险动态统计
const handleGetLatestRiskUpdates = async () => {
try {
const res = await getBillRiskSignal(params);
console.log("法案风险信号", res);
if (res.code === 200) {
warningList.value = res.data;
const params = {
currentDate: '本周'
}
const res = await getLatestRiskUpdates(params);
console.log("最新风险动态统计", res);
if (res.code === 200 && res.data) {
sections.value = [
{
title: res.data.policiesRegulations.hotspotTitle,
date: res.data.policiesRegulations.hotspotDate,
waveBall: [
{
percent: 30, // 估算的百分比
count: res.data.bill.total,
change: res.data.bill.dailyIncrement,
unit: "项",
title: "法案(提出)"
},
{
percent: 20, // 估算的百分比
count: res.data.administrativeOrder.total,
change: res.data.administrativeOrder.dailyIncrement,
unit: "个",
title: "政令"
}
]
},
{
title: res.data.exportControl.hotspotTitle,
date: res.data.exportControl.hotspotDate,
waveBall: [
{
percent: 10, // 估算的百分比
count: res.data.Entities.total,
change: res.data.Entities.dailyIncrement,
unit: "次",
title: "实体清单"
},
{
percent: 20, // 估算的百分比
count: res.data.CCL.total,
change: res.data.CCL.dailyIncrement,
unit: "次",
title: "CCL"
}
]
},
{
title: res.data.investmentFinancingRestrictions.hotspotTitle,
date: res.data.investmentFinancingRestrictions.hotspotDate,
waveBall: [
{
percent: 15, // 估算的百分比
count: res.data.SDN.total,
change: res.data.SDN.dailyIncrement,
unit: "次",
title: "SDN"
},
{
percent: 5, // 估算的百分比
count: res.data.militaryInvolvement.total,
change: res.data.militaryInvolvement.dailyIncrement,
unit: "家",
title: "涉军企业"
}
]
},
{
title: res.data.marketAccess.hotspotTitle,
date: res.data.marketAccess.hotspotDate,
waveBall: [
{
percent: 3, // 估算的百分比
count: res.data['337Survey'].total,
change: res.data['337Survey'].dailyIncrement,
unit: "次",
title: "337调查"
},
{
percent: 3, // 估算的百分比
count: res.data['232Survey'].total,
change: res.data['232Survey'].dailyIncrement,
unit: "次",
title: "230调查"
},
{
percent: 3, // 估算的百分比
count: res.data['301Survey'].total,
change: res.data['301Survey'].dailyIncrement,
unit: "次",
title: "301调查"
}
]
}
]
console.log(sections.value, 'sections.value')
}
} catch (error) {
console.error("获取最新风险动态统计error", error);
}
} catch (error) { }
};
// 风险信号
const warningList = ref([]);
const riskTotal = ref(0)
const hotNewsList = ref([
{
title: "美国白宫发布关于进一步延长TikTok执法宽限期的行政令",
......@@ -266,6 +363,24 @@ const hotNewsList = ref([
tags: ['人工智能', '通信网络']
}
]);
//最新风险信号
const handleGetLatestRisks = async () => {
try {
const res = await getLatestRisks();
console.log("最新风险信号", res);
if (res.code === 200 && res.data) {
warningList.value = res.data.riskVOS
hotNewsList.value = res.data.hotspotVOS
riskTotal.value = res.data.riskCount
console.log(hotNewsList.value, 'hotNewsList.value')
}
} catch (error) {
console.error("获取最新风险信号error", error);
}
};
const curNews = ref({});
const carouselRef = ref(null);
const curHotNewsListIndex = ref(0);
......@@ -289,11 +404,16 @@ const handleSwithCurNews = name => {
carouselRef.value.next();
}
};
onMounted(() => {
// 这里可以添加从后端获取数据的代码
handlegetBillRiskSignal();
onMounted(async () => {
await handleGetLatestRiskUpdates()
await handleGetLatestRisks()
console.log("页面加载完成,可以获取数据了");
});
// onBeforeUnmount(() => {
// andleGetLatestRiskUpdates()
// });
</script>
<style lang="scss" scoped>
......@@ -344,6 +464,7 @@ onMounted(() => {
text-align: left;
display: flex;
align-items: center;
img {
/* 矢量 347 */
width: 22px;
......@@ -375,8 +496,10 @@ onMounted(() => {
}
.manage-btn {
margin-left: auto; /* 推到最右侧 */
margin-right: 16px; /* 适当的右边距 */
margin-left: auto;
/* 推到最右侧 */
margin-right: 16px;
/* 适当的右边距 */
padding: 4px 12px;
border-radius: 20px;
background-color: rgba(206, 79, 81, 0.1);
......@@ -430,7 +553,7 @@ onMounted(() => {
font-style: Bold;
font-size: 20px;
font-weight: 700;
line-height: 26px;
// line-height: 26px;
letter-spacing: 0px;
text-align: center;
display: flex;
......
......@@ -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 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论