提交 68e6c85e authored 作者: Vicky's avatar Vicky

风险信号管理页面

上级 2d656d06
......@@ -41,6 +41,9 @@ import MarketSingleCaseLayout from "@/views/marketAccessRestrictions/singleCaseL
import MarketSingleCaseOverview from "@/views/marketAccessRestrictions/singleCaseLayout/overview/index.vue";
import MarketSingleCaseDeepdig from "@/views/marketAccessRestrictions/singleCaseLayout/deepdig/index.vue";
//风险信号管理
import RiskSignal from "@/views/riskSignal/index.vue"
const routes = [
// 智库系统的主要路由
{
......@@ -329,6 +332,16 @@ const routes = [
]
},
// 风险信号管理路由
{
path: '/riskSignal',
name: 'RiskSignal',
component: RiskSignal,
meta: {
title: '风险信号管理'
},
},
// 转移过来的页面
{
path: "/analysis",
......
......@@ -3,7 +3,8 @@
<!-- 导航 -->
<div class="breadcrumb">
<el-breadcrumb :separator-icon="ArrowRight" class="breadcrumb">
<el-breadcrumb :separator-icon="ArrowRight" class="bre
adcrumb">
<el-breadcrumb-item>国家科技安全</el-breadcrumb-item>
<el-breadcrumb-item>中美博弈概览</el-breadcrumb-item>
<el-breadcrumb-item :to="{ path: '/' }">美对华科技合作限制信息平台</el-breadcrumb-item>
......
<template>
<div class="home-wrapper">
<div class="home-main">
<div class="home-main-center">
<div class="center-center">
<div class="center-header">
<div class="center-header-left">
<img class="iconstyle" src="./assets/images/warning.png" ></img>
<div class="center-header-title">风险信号管理</div>
</div>
<div class="center-header-right">
<img class="img" src="./assets/images/danger.png"></img>
<div class="text">风险统计</div>
</div>
</div>
<div class="center-middle">
<div class="center-middle-left">
<div class="lineitem">
<div class="item">
<div class="top">
<div class="dot" style="background-color: rgba(95, 101, 108, 1);"></div>
<div class="text1">本年新增风险</div>
</div>
<div class="text2" style="color: rgba(95, 101, 108, 1);">219项</div>
</div>
<div class="item">
<div class="top">
<div class="dot" style="background-color: rgba(95, 101, 108, 1);"></div>
<div class="text1">本月新增风险</div>
</div>
<div class="text2" style="color: rgba(95, 101, 108, 1);">40项</div>
</div>
</div>
<div class="lineitem">
<div class="item">
<div class="top">
<div class="dot" style="background-color: rgba(5, 95, 194, 1);"></div>
<div class="text1">已处理风险</div>
</div>
<div class="text2" style="color: rgba(5, 95, 194, 1);">212项</div>
</div>
<div class="item">
<div class="top">
<div class="dot" style="background-color: rgba(206, 79, 81, 1);"></div>
<div class="text1">待处理风险</div>
</div>
<div class="text2" style="color: rgba(206, 79, 81, 1);">7项</div>
</div>
</div>
</div>
<div class="center-middle-right" id="chartCalendar"></div>
</div>
</div>
</div>
<div class="home-main-footer">
<div class="home-main-footer-main">
<div class="left">
<div class="left-box1">
<div class="left-box1-header">
<div class="icon"></div>
<div class="title">{{ "风险类型" }}</div>
</div>
<div class="left-box1-main">
<div
class="time-label"
v-for="(item, index) in riskType"
:key="index"
>
<el-checkbox
v-model="item.selected"
:label="item.name"
size="large"
/>
</div>
</div>
</div>
<div class="left-box1">
<div class="left-box1-header">
<div class="icon"></div>
<div class="title">{{ "风险来源" }}</div>
</div>
<div class="left-box1-main">
<div
class="time-label"
v-for="(item, index) in riskSource"
:key="index"
>
<el-checkbox
v-model="item.selected"
:label="item.name"
size="large"
/>
</div>
</div>
</div>
<div class="left-box1">
<div class="left-box1-header">
<div class="icon"></div>
<div class="title">{{ "风险等级" }}</div>
</div>
<div class="left-box1-main">
<div
class="time-label"
v-for="(item, index) in riskDegree"
:key="index"
>
<el-checkbox
v-model="item.selected"
:label="item.name"
size="large"
/>
</div>
</div>
</div>
<div class="left-box1">
<div class="left-box1-header">
<div class="icon"></div>
<div class="title">{{ "设计领域" }}</div>
</div>
<div class="left-box1-main">
<div
class="time-label"
v-for="(item, index) in area"
:key="index"
>
<el-checkbox
v-model="item.selected"
:label="item.name"
size="large"
/>
</div>
</div>
</div>
</div>
<div class="right">
<div class="right-header">
<div class="header-left">
<div class="btn-left" :class="{ btnleftactive: activeBtn === '全部' }"
@click="handleClickBtn('全部')">
<div class="btn-text" :class="{ btntextactive: activeBtn === '全部' }">全部</div>
</div>
<div class="btn-left" :class="{btnleftactive: activeBtn === '未处理'}"
@click="handleClickBtn('未处理')">
<div class="btn-text" :class="{btntextactive: activeBtn === '未处理'}">未处理</div>
</div>
<div class="btn-left" :class="{btnleftactive: activeBtn === '已处理'}"
@click="handleClickBtn('已处理')">
<div class="btn-text" :class="{btntextactive: activeBtn === '已处理'}">已处理</div>
</div>
</div>
<div class="header-right">
<div class="searchbox">
<el-input
v-model="input"
style="width: 268px; height: 100%"
placeholder="搜索"/>
<div class="search-btn"></div>
</div>
<div class="select-box">
<el-select
v-model="releaseTime"
placeholder="发布时间"
style="width: 120px"
>
<el-option
v-for="item in releaseTimeList"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</div>
</div>
</div>
<div class="right-main">
<div class="itemlist" v-for="(val, idx) in riskList" :key="idx">
<div class="item-box">
<div class="box-title">
<div class="risktitle">{{ val.title }}</div>
<div class="risktype" :style="{backgroundColor: val.bgcolor,color: val.textcolor}">{{ val.risktype }}</div>
</div>
<div class="box-source">
<img class="source-pic" :src="val.pic" alt="" />
<div class="source-text">{{ val.origin }}</div>
<div class="source-text">{{ val.time }}</div>
</div>
<div class="desc-box">{{ val.dsc }}</div>
<div class="tag-box" >
<el-tag v-for="tag in val.tag">{{ tag }}</el-tag>
</div>
</div>
<div class="splitline"></div>
</div>
</div>
<div class="right-footer">
<div class="footer-left">
{{ "共105项调查" }}
</div>
<div class="footer-right">
<el-pagination
background
layout="prev, pager, next"
:total="105"
/>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { onMounted, ref } from "vue";
import * as echarts from "echarts";
import router from "@/router";
import getCalendarHeatChart from "./utils/cleandarHeat";
const activeBtn = ref("全部");
const handleClickBtn = name => {
activeBtn.value = name;
};
const riskType = ref([
{
name: "科技法案",
selected: true,
},
{
name: "行政令",
selected: true,
},
{
name: "智库报告",
selected: true,
},
{
name: "出口管制",
selected: true,
},
{
name: "投融资限制",
selected: true,
},
{
name: "市场准入限制",
selected: true,
},
{
name: "规则限制",
selected: true,
},
]);
const riskSource = ref([
{
name: "美国",
selected: true,
},
{
name: "欧盟",
selected: true,
},
{
name: "日本",
selected: true,
},
{
name: "韩国",
selected: true,
},
]);
const riskDegree = ref([
{
name: "特别重大风险",
selected: true,
},
{
name: "重大风险",
selected: true,
},
{
name: "较大风险",
selected: true,
},
{
name: "一般风险",
selected: true,
},
{
name: "无风险",
selected: true,
}
]);
const area = ref([
{
name: "人工智能",
selected: true,
},
{
name: "集成电路",
selected: true,
},
{
name: "通信网络",
selected: true,
},
{
name: "量子科技",
selected: true,
},
{
name: "生物科技",
selected: true,
},
{
name: "能源",
selected: true,
},
{
name: "航空航天",
selected: true,
},
{
name: "先进制造",
selected: true,
},
]);
const releaseTime = ref("发布时间");
const releaseTimeList = ref([
{
label: "近半年发布",
value: "近半年发布",
},
{
label: "近一年发布",
value: "近一年发布",
},
{
label: "近两年发布",
value: "近两年发布",
},
{
label: "近三年发布",
value: "近三年发布",
},
{
label: "近五年发布",
value: "近五年发布",
},
]);
const riskList = ref([
{
title: "扩大实体清单制裁范围,对中企子公司实施同等管制",
origin: "美国商务部 · 实体清单",
time:"2025年11月10日 16:14",
dsc: "任何被列入美国出口管制“实体清单”或“军事最终用户清单”的企业,如果其直接或间接持有另一家公司 ​50%或以上的股权,那么这家被控股的公司也将自动受到与清单上母公司同等的出口管制限制",
tag:["生物科技","人工智能"],
risktype: "·特别重大风险",
pic: "src/views/riskSignal/assets/images/origin1.png",
textcolor:"rgba(206, 79, 81, 1)",
bgcolor:"rgba(206, 79, 81, 0.1)"
},
{
title: "大而美法案通过国会众议院投票,将提交至总统签署",
origin: "美国国会 · 科技法案",
time:"2025年11月10日 16:14",
dsc: "",
tag:["能源","人工智能"],
risktype: "·重大风险",
pic: "src/views/riskSignal/assets/images/origin2.png",
textcolor:"rgba(255, 149, 77, 1)",
bgcolor:"rgba(255, 149, 77, 0.1)"
},
{
title: "兰德公司发布智库报告《中美经济竞争:复杂经济和地缘政治关系中的收益和风险》",
origin: "兰德公司 · 科技智库",
time:"2025年11月10日 16:14",
dsc: "包括经济竞争在内的美中竞争自2017年以来一直在定义美国外交政策。这两个经济体是世界上第一和第二大国家经济体,并且深深交织在一起。改变关系,无论多么必要,可能是昂贵的。因此,美国面临着一项挑战,确保其经济在耦合的战略竞争条件下满足国家的需求。",
tag:["生物科技","人工智能","集成电路"],
risktype: "·一般风险",
pic: "src/views/riskSignal/assets/images/origin3.png",
textcolor:"rgba(5, 95, 194, 1)",
bgcolor:"rgba(5, 95, 194, 0.1)"
},
{
title: "美国白宫发布总统政令《关于进一步延长TikTok执法宽限期的行政令》",
origin: "美国白宫 · 总统政令",
time:"2025年11月10日 16:14",
dsc: "再次推迟(第四次)对TikTok禁令的执法,新的宽限期截止日为2025年12月16日​。在宽限期内及对于宽限期前的行为,司法部不得强制执行​《保护美国人免受外国对手控制应用程序法》或因此处罚相关实体​(如TikTok及其分发平台)。",
tag:["人工智能"],
risktype: "·一般风险",
pic: "src/views/riskSignal/assets/images/origin2.png",
textcolor:"rgba(5, 95, 194, 1)",
bgcolor:"rgba(5, 95, 194, 0.1)"
},
{
title: "美国财政部更新《特别指定国民清单》",
origin: "美国财政部 · 特别指定国民清单",
time:"2025年11月10日 16:14",
dsc: "",
tag:["生物科技"],
risktype: "·特别重大风险",
pic: "src/views/riskSignal/assets/images/origin4.png",
textcolor:"rgba(206, 79, 81, 1)",
bgcolor:"rgba(206, 79, 81, 0.1)"
},
{
title: "美国FDA针对两家中国第三方检测机构的数据完整性问题采取行动",
origin: "美国食品药品监督管理局 · 规则限制",
time:"2025年11月10日 16:14",
dsc: "FDA因发现数据伪造或无效问题,向两家中国第三方检测公司(天津中联科技检测有限公司和苏州大学卫生与环境技术研究所)正式发出“一般信函”。",
tag:["生物科技","人工智能"],
risktype: "·特别重大风险",
pic: "src/views/riskSignal/assets/images/origin5.png",
textcolor:"rgba(206, 79, 81, 1)",
bgcolor:"rgba(206, 79, 81, 0.1)"
}
]);
// 绘制echarts图表
const setChart = (option, chartId) => {
let chartDom = document.getElementById(chartId);
chartDom.removeAttribute("_echarts_instance_");
let chart = echarts.init(chartDom);
chart.setOption(option);
return chart;
};
const calendarData = ref([
["2025-01-01", 20],
["2025-01-05", 120],
["2025-01-09", 220],
["2025-01-15", 320],
["2025-01-20", 120],
["2025-01-24", 420],
["2025-02-05", 80],
["2025-02-08", 280],
["2025-02-18", 480],
["2025-02-11", 420],
["2025-02-21", 320],
["2025-03-05", 160],
["2025-03-09", 260],
["2025-03-19", 460],
["2025-03-26", 430],
["2025-04-01", 70],
["2025-04-05", 170],
["2025-04-11", 270],
["2025-04-18", 370],
["2025-05-05", 210],
["2025-05-09", 210],
["2025-05-15", 410],
["2025-05-22", 480],
["2025-06-06", 45],
["2025-06-09", 415],
["2025-06-16", 245],
["2025-06-19", 332],
["2025-07-04", 127],
["2025-07-09", 327],
["2025-07-24", 427],
["2025-08-08", 150],
["2025-08-11", 250],
["2025-08-15", 350],
["2025-08-22", 460],
["2025-09-10", 480],
["2025-09-18", 312],
["2025-10-15", 60],
["2025-10-19", 80],
["2025-10-21", 190],
]);
onMounted(async () => {
let chartCalendar = getCalendarHeatChart(calendarData.value);
setChart(chartCalendar, "chartCalendar");
});
</script>
<style lang="scss" scoped>
:deep(.el-input__wrapper) {
box-shadow: none;
}
.home-wrapper {
.home-main {
// width: 1400px;
width: 100%;
margin: 0 auto;
background: url("./assets/images/background.png");
background-size: 100% 100%;
.home-main-center {
margin-top: 34px;
.center-center {
margin: 0 auto;
margin-top: 24px;
width: 1600px;
height: 288px;
border-radius: 4px;
box-shadow: 0px 0px 15px 0px rgba(60, 87, 126, 0.2);
background: rgba(255, 255, 255, 1);
.center-header {
display: flex;
justify-content: space-between;
.center-header-left {
margin-left: 30px;
display: flex;
margin-top: 15px;
.iconstyle{
width: 27px;
height: 24px;
margin-top: 3px;
}
.center-header-title{
margin-left: 10px;
font-size: 24px;
font-weight: 700;
line-height: 32px;
}
}
.center-header-right {
margin-top: 16px;
margin-right: 59px;
width: 118px;
height: 36px;
border-radius: 6px;
background-color: rgba(5, 95, 194, 1);
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
cursor: pointer;
.img{
width: 16px;
height: 15px;
}
.text{
margin-left: 8px;
font-size: 16px;
font-weight: 400;
line-height: 24px;
color: rgba(255, 255, 255, 1);
}
}
}
.center-middle{
display: flex;
.center-middle-left{
display: flex;
flex-direction: column;
.lineitem{
display: flex;
justify-content: space-between;
.item{
margin-left: 61px;
margin-top: 33px;
width: 111px;
height: 66px;
display: flex;
flex-direction: column;
justify-content: flex-end;
.top{
display: flex;
justify-content: flex-end;
.dot{
width: 6px;
height: 6px;
margin-top: 9px;
margin-right: 7px;
border-radius: 3px;
}
.text1{
font-size: 16px;
font-weight: 400;
line-height: 24px;
color: rgba(59, 65, 75, 1);
text-align: right;
}
}
.text2{
font-size: 32px;
font-weight: 700;
line-height: 42px;
text-align: right;
}
}
}
}
.center-middle-right{
width: 1159px;
height: 189px;
box-sizing: border-box;
border: 1px solid rgba(234, 236, 238, 1);
border-radius: 4px;
margin: 30px auto 0;
}
}
}
}
.home-main-footer {
// width: 100%;
height: 1059px;
background: rgba(248, 249, 250, 1);
.home-main-footer-header {
width: 1600px;
height: 42px;
margin: 36px auto;
// background: orange;
display: flex;
justify-content: space-between;
.btn-box {
width: 1000px;
display: flex;
.btn {
color: rgba(95, 101, 108, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 42px;
padding: 0 24px;
border-radius: 21px;
background: rgba(20, 89, 187, 0);
margin-right: 20px;
cursor: pointer;
&:hover {
background: rgba(20, 89, 187, 0.1);
}
}
.btnActive {
padding: 0 24px;
border-radius: 21px;
background: rgba(20, 89, 187, 1);
color: #fff;
&:hover {
color: #fff;
background: rgba(20, 89, 187, 1);
}
}
}
}
.home-main-footer-main {
width: 1600px;
margin-bottom: 30px;
// box-shadow: 0px 0px 15px 0px rgba(60, 87, 126, 0.2);
// background: rgba(255, 255, 255, 1);
margin: 30px auto;
box-sizing: border-box;
// padding: 20px;
display: flex;
.left {
width: 389px;
height: 747px;
border-radius: 4px;
box-shadow: 0px 0px 15px 0px rgba(60, 87, 126, 0.2);
background: rgba(255, 255, 255, 1);
.left-box1 {
margin-top: 17px;
.left-box1-header {
display: flex;
.icon {
width: 8px;
height: 16px;
margin-top: 4px;
border-radius: 2px 2px 0 0;
background: rgba(10, 87, 166, 1);
}
.title {
height: 2px;
margin-left: 17px;
color: rgba(10, 87, 166, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 700;
line-height: 24px;
}
}
.left-box1-main {
display: grid;
grid-template-columns: repeat(2,160px);
width: 336px;
margin-top: 10px;
margin-left: 17px;
.time-label {
height: 30px;
width: 160px;
margin-left: 8px;
}
}
}
}
.right {
margin-left: 16px;
width: 1196px;
border-radius: 4px;
box-shadow: 0px 0px 15px 0px rgba(60, 87, 126, 0.2);
background: rgba(255, 255, 255, 1);
.right-header {
height: 60px;
display: flex;
justify-content: space-between;
.header-left{
display: flex;
margin-left: 44px;
gap: 36px;
.btn-left{
display: flex;
height: 60px;
cursor: pointer;
align-items: center;
.btn-text{
font-size: 18px;
font-weight: 400;
line-height: 24px;
color: rgba(59, 65, 75, 1);
text-align: center;
}
.btntextactive{
font-weight: 700;
color: rgba(5, 95, 194, 1);
}
}
.btnleftactive{
border-bottom: 2px solid rgba(5, 95, 194, 1);
}
}
.header-right{
display: flex;
margin-right: 42px;
gap: 12px;
align-items: center;
.searchbox{
display: flex;
width: 300px;
height: 32px;
border-radius: 4px;
border: 1px solid rgba(230, 231, 232, 1);
background: rgba(255, 255, 255, 1);
box-sizing: border-box;
.search-btn{
width: 16px;
height: 16px;
margin: 8px;
cursor: pointer;
background: url("./assets/images/search-icon.png");
}
}
.select-box {
width: 120px;
height: 32px;
box-sizing: border-box;
}
}
}
.right-main {
width: 1196px;
display: flex;
flex-direction: column;
.itemlist {
width: 1138px;
display: flex;
margin-top: 22px;
margin-left: 18px;
flex-direction: column;
.item-box{
width: 1113px;
margin-left: 25px;
display: flex;
flex-direction: column;
gap: 10px;
.box-title{
display: flex;
justify-content: space-between;
.risktitle{
font-size: 18px;
font-weight: 700;
line-height: 24px;
color: rgba(59, 65, 75, 1);
}
.risktype{
height: 28px;
border-radius: 20px;
font-size: 16px;
font-weight: 400;
line-height: 24px;
}
}
.box-source{
display: flex;
flex-direction: row;
align-items: center;
height: 24px;
gap: 10px;
.source-pic{
width: 16px;
height: 16px;
}
.source-text{
font-size: 16px;
font-weight: 400;
line-height: 24px;
color: rgba(95, 101, 108, 1);
}
}
.desc-box{
font-size: 16px;
font-weight: 400;
line-height: 24px;
color: rgba(59, 65, 75, 1);
text-align: justify;
}
.tag-box{
display: flex;
flex-direction: row;
gap: 8px;
}
}
.splitline{
margin: 16px auto;
background-color: rgba(234, 236, 238, 1);
height: 1px;
width: 1138px;
}
}
}
.right-footer {
display: flex;
// height: 60px;
// background: orange;
margin: 34px auto;
justify-content: space-between;
.footer-left {
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-size: 14px;
font-weight: 400;
line-height: 18px;
margin-left: 24px;
margin-top: 6px;
}
.footer-right {
margin-right: 24px;
}
}
}
}
}
}
}
</style>
\ No newline at end of file
const getCalendarHeatChart = (data) => {
const option = {
title: {
top: 30,
left: 'center',
text: `日历热力图`,
show: false
},
tooltip: {
position: 'top',
formatter: function (params) {
const date = new Date(params.data[0]);
return `${date.getFullYear()}-${(date.getMonth() + 1).toString().padStart(2, '0')}-${date.getDate().toString().padStart(2, '0')}<br/>数值: ${params.data[1]}`;
}
},
visualMap: {
show: false,
min: 0,
max: 500,
calculable: true,
orient: 'horizontal',
left: 'center',
top: 65,
inRange: {
color: ['rgba(231, 243, 255, 1)', 'rgba(138, 196, 255, 1)', 'rgba(5, 95, 194, 1)']
},
textStyle: {
color: 'rgba(95, 101, 108, 1)'
}
},
calendar: {
top: 24,
left: 30,
right: 30,
cellSize: ['auto', 20],
range: '2025',
splitLine: {
show:false
},
itemStyle: {
borderWidth: 0.5,
borderColor: '#ccc'
},
yearLabel: { show: true },
monthLabel: {
nameMap: 'cn'
},
dayLabel: {
nameMap: ['日', '一', '二', '三', '四', '五', '六'],
show: false,
}
},
series: {
type: 'heatmap',
coordinateSystem: 'calendar',
data: data
}
};
return option
}
export default getCalendarHeatChart
\ No newline at end of file
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论